From f0941ba423572e6ec4264deb7736ca6508ad5431 Mon Sep 17 00:00:00 2001 From: Fabio Belavenuto Date: Fri, 1 Jul 2022 19:28:10 -0300 Subject: [PATCH] Separating addons to another repository --- .gitmodules | 3 + LICENSE | 674 + addons | 1 + addons/9p/install.sh | 6 - addons/9p/manifest.yml | 28 - addons/9p/src/3.10.108/Makefile | 36 - addons/9p/src/3.10.108/acl.c | 375 - addons/9p/src/3.10.108/acl.h | 55 - addons/9p/src/3.10.108/cache.c | 415 - addons/9p/src/3.10.108/cache.h | 139 - addons/9p/src/3.10.108/client.c | 2256 -- addons/9p/src/3.10.108/error.c | 247 - addons/9p/src/3.10.108/fid.c | 306 - addons/9p/src/3.10.108/fid.h | 30 - addons/9p/src/3.10.108/mod.c | 201 - addons/9p/src/3.10.108/protocol.c | 636 - addons/9p/src/3.10.108/protocol.h | 34 - addons/9p/src/3.10.108/trans_common.c | 69 - addons/9p/src/3.10.108/trans_common.h | 17 - addons/9p/src/3.10.108/trans_fd.c | 1090 - addons/9p/src/3.10.108/trans_rdma.c | 719 - addons/9p/src/3.10.108/trans_virtio.c | 730 - addons/9p/src/3.10.108/util.c | 141 - addons/9p/src/3.10.108/v9fs.c | 677 - addons/9p/src/3.10.108/v9fs.h | 227 - addons/9p/src/3.10.108/v9fs_vfs.h | 88 - addons/9p/src/3.10.108/vfs_addr.c | 353 - addons/9p/src/3.10.108/vfs_dentry.c | 139 - addons/9p/src/3.10.108/vfs_dir.c | 269 - addons/9p/src/3.10.108/vfs_file.c | 790 - addons/9p/src/3.10.108/vfs_inode.c | 1538 - addons/9p/src/3.10.108/vfs_inode_dotl.c | 1033 - addons/9p/src/3.10.108/vfs_super.c | 368 - addons/9p/src/3.10.108/xattr.c | 175 - addons/9p/src/3.10.108/xattr.h | 35 - addons/9p/src/3.10.108/xattr_user.c | 80 - addons/9p/src/4.4.180/Makefile | 35 - addons/9p/src/4.4.180/acl.c | 338 - addons/9p/src/4.4.180/acl.h | 55 - addons/9p/src/4.4.180/cache.c | 414 - addons/9p/src/4.4.180/cache.h | 152 - addons/9p/src/4.4.180/client.c | 2297 -- addons/9p/src/4.4.180/error.c | 247 - addons/9p/src/4.4.180/fid.c | 306 - addons/9p/src/4.4.180/fid.h | 30 - addons/9p/src/4.4.180/mod.c | 201 - addons/9p/src/4.4.180/protocol.c | 634 - addons/9p/src/4.4.180/protocol.h | 34 - addons/9p/src/4.4.180/trans_common.c | 29 - addons/9p/src/4.4.180/trans_common.h | 15 - addons/9p/src/4.4.180/trans_fd.c | 1122 - addons/9p/src/4.4.180/trans_rdma.c | 784 - addons/9p/src/4.4.180/trans_virtio.c | 788 - addons/9p/src/4.4.180/util.c | 141 - addons/9p/src/4.4.180/v9fs.c | 700 - addons/9p/src/4.4.180/v9fs.h | 226 - addons/9p/src/4.4.180/v9fs_vfs.h | 105 - addons/9p/src/4.4.180/vfs_addr.c | 351 - addons/9p/src/4.4.180/vfs_dentry.c | 122 - addons/9p/src/4.4.180/vfs_dir.c | 248 - addons/9p/src/4.4.180/vfs_file.c | 726 - addons/9p/src/4.4.180/vfs_inode.c | 1462 - addons/9p/src/4.4.180/vfs_inode_dotl.c | 999 - addons/9p/src/4.4.180/vfs_super.c | 366 - addons/9p/src/4.4.180/xattr.c | 195 - addons/9p/src/4.4.180/xattr.h | 34 - addons/acpid/all/addons/acpid.tgz | Bin 25210 -> 0 bytes addons/acpid/install.sh | 12 - addons/acpid/manifest.yml | 36 - addons/acpid/src/3.10.108/Makefile | 46 - addons/acpid/src/3.10.108/button.c | 454 - addons/acpid/src/4.4.180/Makefile | 1 - addons/acpid/src/4.4.180/Module.symvers | 0 addons/acpid/src/4.4.180/button.c | 449 - addons/acpid/src/4.4.180/modules.order | 0 addons/atl1c/install.sh | 4 - addons/atl1c/manifest.yml | 28 - addons/atl1c/src/3.10.108/Makefile | 2 - addons/atl1c/src/3.10.108/atl1c.h | 606 - addons/atl1c/src/3.10.108/atl1c_ethtool.c | 309 - addons/atl1c/src/3.10.108/atl1c_hw.c | 865 - addons/atl1c/src/3.10.108/atl1c_hw.h | 1024 - addons/atl1c/src/3.10.108/atl1c_main.c | 2818 -- addons/atl1c/src/4.4.180/Makefile | 2 - addons/atl1c/src/4.4.180/atl1c.h | 605 - addons/atl1c/src/4.4.180/atl1c_ethtool.c | 305 - addons/atl1c/src/4.4.180/atl1c_hw.c | 863 - addons/atl1c/src/4.4.180/atl1c_hw.h | 1024 - addons/atl1c/src/4.4.180/atl1c_main.c | 2813 -- addons/atl1e/install.sh | 4 - addons/atl1e/manifest.yml | 28 - addons/atl1e/src/3.10.108/Makefile | 2 - addons/atl1e/src/3.10.108/atl1e.h | 508 - addons/atl1e/src/3.10.108/atl1e_ethtool.c | 392 - addons/atl1e/src/3.10.108/atl1e_hw.c | 651 - addons/atl1e/src/3.10.108/atl1e_hw.h | 690 - addons/atl1e/src/3.10.108/atl1e_main.c | 2559 -- addons/atl1e/src/3.10.108/atl1e_param.c | 269 - addons/atl1e/src/4.4.180/Makefile | 2 - addons/atl1e/src/4.4.180/atl1e.h | 507 - addons/atl1e/src/4.4.180/atl1e_ethtool.c | 388 - addons/atl1e/src/4.4.180/atl1e_hw.c | 650 - addons/atl1e/src/4.4.180/atl1e_hw.h | 690 - addons/atl1e/src/4.4.180/atl1e_main.c | 2578 -- addons/atl1e/src/4.4.180/atl1e_param.c | 269 - addons/compile-addons.sh | 186 - addons/e1000/install.sh | 4 - addons/e1000/manifest.yml | 29 - addons/e1000/src/3.10.108/Makefile | 2 - addons/e1000/src/3.10.108/e1000.h | 365 - addons/e1000/src/3.10.108/e1000_ethtool.c | 1909 - addons/e1000/src/3.10.108/e1000_hw.c | 5893 ---- addons/e1000/src/3.10.108/e1000_hw.h | 3112 -- addons/e1000/src/3.10.108/e1000_main.c | 5226 --- addons/e1000/src/3.10.108/e1000_osdep.h | 109 - addons/e1000/src/3.10.108/e1000_param.c | 754 - addons/e1000/src/4.4.180/Makefile | 2 - addons/e1000/src/4.4.180/e1000.h | 378 - addons/e1000/src/4.4.180/e1000_ethtool.c | 1909 - addons/e1000/src/4.4.180/e1000_hw.c | 5681 --- addons/e1000/src/4.4.180/e1000_hw.h | 3110 -- addons/e1000/src/4.4.180/e1000_main.c | 5344 --- addons/e1000/src/4.4.180/e1000_osdep.h | 109 - addons/e1000/src/4.4.180/e1000_param.c | 754 - addons/e1000e/install.sh | 4 - addons/e1000e/manifest.yml | 29 - addons/e1000e/src/3.10.108/80003es2lan.c | 1421 - addons/e1000e/src/3.10.108/80003es2lan.h | 95 - addons/e1000e/src/3.10.108/82571.c | 2067 -- addons/e1000e/src/3.10.108/82571.h | 60 - addons/e1000e/src/3.10.108/Makefile | 5 - addons/e1000e/src/3.10.108/defines.h | 803 - addons/e1000e/src/3.10.108/e1000.h | 626 - addons/e1000e/src/3.10.108/ethtool.c | 2262 -- addons/e1000e/src/3.10.108/hw.h | 681 - addons/e1000e/src/3.10.108/ich8lan.c | 4738 --- addons/e1000e/src/3.10.108/ich8lan.h | 265 - addons/e1000e/src/3.10.108/mac.c | 1801 - addons/e1000e/src/3.10.108/mac.h | 74 - addons/e1000e/src/3.10.108/manage.c | 351 - addons/e1000e/src/3.10.108/manage.h | 72 - addons/e1000e/src/3.10.108/netdev.c | 7043 ---- addons/e1000e/src/3.10.108/nvm.c | 638 - addons/e1000e/src/3.10.108/nvm.h | 47 - addons/e1000e/src/3.10.108/param.c | 530 - addons/e1000e/src/3.10.108/phy.c | 3243 -- addons/e1000e/src/3.10.108/phy.h | 242 - addons/e1000e/src/3.10.108/ptp.c | 276 - addons/e1000e/src/3.10.108/regs.h | 253 - addons/e1000e/src/4.4.180/80003es2lan.c | 1418 - addons/e1000e/src/4.4.180/80003es2lan.h | 88 - addons/e1000e/src/4.4.180/82571.c | 2063 -- addons/e1000e/src/4.4.180/82571.h | 53 - addons/e1000e/src/4.4.180/Makefile | 5 - addons/e1000e/src/4.4.180/defines.h | 800 - addons/e1000e/src/4.4.180/e1000.h | 601 - addons/e1000e/src/4.4.180/ethtool.c | 2341 -- addons/e1000e/src/4.4.180/hw.h | 698 - addons/e1000e/src/4.4.180/ich8lan.c | 5873 ---- addons/e1000e/src/4.4.180/ich8lan.h | 310 - addons/e1000e/src/4.4.180/mac.c | 1805 - addons/e1000e/src/4.4.180/mac.h | 68 - addons/e1000e/src/4.4.180/manage.c | 347 - addons/e1000e/src/4.4.180/manage.h | 65 - addons/e1000e/src/4.4.180/netdev.c | 7554 ---- addons/e1000e/src/4.4.180/nvm.c | 633 - addons/e1000e/src/4.4.180/nvm.h | 40 - addons/e1000e/src/4.4.180/param.c | 533 - addons/e1000e/src/4.4.180/phy.c | 3238 -- addons/e1000e/src/4.4.180/phy.h | 236 - addons/e1000e/src/4.4.180/ptp.c | 280 - addons/e1000e/src/4.4.180/regs.h | 251 - addons/ehci-pci/install-bromolow-3.10.108.sh | 6 - addons/ehci-pci/install.sh | 5 - addons/ehci-pci/manifest.yml | 7 - addons/ehci-pci/src/3.10.108/Makefile | 3 - addons/ehci-pci/src/3.10.108/ehci-dbg.c | 980 - addons/ehci-pci/src/3.10.108/ehci-hcd.c | 1391 - addons/ehci-pci/src/3.10.108/ehci-hub.c | 1139 - addons/ehci-pci/src/3.10.108/ehci-mem.c | 245 - addons/ehci-pci/src/3.10.108/ehci-pci.c | 464 - addons/ehci-pci/src/3.10.108/ehci-q.c | 1368 - addons/ehci-pci/src/3.10.108/ehci-sched.c | 2327 -- addons/ehci-pci/src/3.10.108/ehci-sysfs.c | 190 - addons/ehci-pci/src/3.10.108/ehci-timer.c | 401 - addons/ehci-pci/src/3.10.108/ehci.h | 825 - addons/ehci-pci/src/3.10.108/pci-quirks.c | 1001 - addons/ehci-pci/src/3.10.108/pci-quirks.h | 21 - addons/ehci-pci/src/3.10.108/xhci-ext-caps.h | 155 - addons/ehci-pci/src/4.4.180/Makefile | 3 - addons/ehci-pci/src/4.4.180/ehci-dbg.c | 1085 - addons/ehci-pci/src/4.4.180/ehci-hcd.c | 1396 - addons/ehci-pci/src/4.4.180/ehci-hub.c | 1329 - addons/ehci-pci/src/4.4.180/ehci-mem.c | 246 - addons/ehci-pci/src/4.4.180/ehci-pci.c | 435 - addons/ehci-pci/src/4.4.180/ehci-q.c | 1476 - addons/ehci-pci/src/4.4.180/ehci-sched.c | 2517 -- addons/ehci-pci/src/4.4.180/ehci-sysfs.c | 187 - addons/ehci-pci/src/4.4.180/ehci-timer.c | 433 - addons/ehci-pci/src/4.4.180/ehci.h | 895 - addons/ehci-pci/src/4.4.180/pci-quirks.c | 1105 - addons/ehci-pci/src/4.4.180/pci-quirks.h | 26 - addons/ehci-pci/src/4.4.180/xhci-ext-caps.h | 156 - addons/mpt3sas/install.sh | 4 - addons/mpt3sas/manifest.yml | 29 - addons/mpt3sas/src/3.10.108/Makefile | 7 - addons/mpt3sas/src/3.10.108/mpi/mpi2.h | 1164 - addons/mpt3sas/src/3.10.108/mpi/mpi2_cnfg.h | 3323 -- addons/mpt3sas/src/3.10.108/mpi/mpi2_init.h | 560 - addons/mpt3sas/src/3.10.108/mpi/mpi2_ioc.h | 1665 - addons/mpt3sas/src/3.10.108/mpi/mpi2_raid.h | 346 - addons/mpt3sas/src/3.10.108/mpi/mpi2_sas.h | 295 - addons/mpt3sas/src/3.10.108/mpi/mpi2_tool.h | 437 - addons/mpt3sas/src/3.10.108/mpi/mpi2_type.h | 56 - addons/mpt3sas/src/3.10.108/mpt3sas_base.c | 4837 --- addons/mpt3sas/src/3.10.108/mpt3sas_base.h | 1151 - addons/mpt3sas/src/3.10.108/mpt3sas_config.c | 1649 - addons/mpt3sas/src/3.10.108/mpt3sas_ctl.c | 3282 -- addons/mpt3sas/src/3.10.108/mpt3sas_ctl.h | 418 - addons/mpt3sas/src/3.10.108/mpt3sas_debug.h | 219 - addons/mpt3sas/src/3.10.108/mpt3sas_scsih.c | 8198 ----- .../mpt3sas/src/3.10.108/mpt3sas_transport.c | 2128 -- .../src/3.10.108/mpt3sas_trigger_diag.c | 433 - .../src/3.10.108/mpt3sas_trigger_diag.h | 193 - addons/mpt3sas/src/4.4.180/Makefile | 8 - addons/mpt3sas/src/4.4.180/mpi/mpi2.h | 1176 - addons/mpt3sas/src/4.4.180/mpi/mpi2_cnfg.h | 3380 -- addons/mpt3sas/src/4.4.180/mpi/mpi2_init.h | 562 - addons/mpt3sas/src/4.4.180/mpi/mpi2_ioc.h | 1729 - addons/mpt3sas/src/4.4.180/mpi/mpi2_raid.h | 354 - addons/mpt3sas/src/4.4.180/mpi/mpi2_sas.h | 297 - addons/mpt3sas/src/4.4.180/mpi/mpi2_tool.h | 482 - addons/mpt3sas/src/4.4.180/mpi/mpi2_type.h | 56 - addons/mpt3sas/src/4.4.180/mpt3sas_base.c | 5634 --- addons/mpt3sas/src/4.4.180/mpt3sas_base.h | 1437 - addons/mpt3sas/src/4.4.180/mpt3sas_config.c | 1716 - addons/mpt3sas/src/4.4.180/mpt3sas_ctl.c | 3464 -- addons/mpt3sas/src/4.4.180/mpt3sas_ctl.h | 423 - addons/mpt3sas/src/4.4.180/mpt3sas_debug.h | 206 - addons/mpt3sas/src/4.4.180/mpt3sas_scsih.c | 9107 ----- .../mpt3sas/src/4.4.180/mpt3sas_transport.c | 2154 -- .../src/4.4.180/mpt3sas_trigger_diag.c | 434 - .../src/4.4.180/mpt3sas_trigger_diag.h | 194 - .../mpt3sas/src/4.4.180/mpt3sas_warpdrive.c | 344 - addons/qjs-dtb/all/addons/dts.js | 2 - addons/qjs-dtb/all/usr/sbin/dtc | Bin 150200 -> 0 bytes addons/qjs-dtb/all/usr/sbin/qjs | Bin 937504 -> 0 bytes addons/qjs-dtb/install.sh | 27 - addons/qjs-dtb/manifest.yml | 16 - addons/r8125/install.sh | 4 - addons/r8125/manifest.yml | 25 - addons/r8125/src/4.4.180/Makefile | 88 - addons/r8125/src/4.4.180/r8125.h | 2536 -- addons/r8125/src/4.4.180/r8125_dash.h | 261 - addons/r8125/src/4.4.180/r8125_firmware.c | 264 - addons/r8125/src/4.4.180/r8125_firmware.h | 68 - addons/r8125/src/4.4.180/r8125_n.c | 15803 --------- addons/r8125/src/4.4.180/r8125_ptp.c | 594 - addons/r8125/src/4.4.180/r8125_ptp.h | 81 - addons/r8125/src/4.4.180/r8125_realwow.h | 118 - addons/r8125/src/4.4.180/r8125_rss.c | 481 - addons/r8125/src/4.4.180/r8125_rss.h | 69 - addons/r8125/src/4.4.180/rtl_eeprom.c | 289 - addons/r8125/src/4.4.180/rtl_eeprom.h | 53 - addons/r8125/src/4.4.180/rtltool.c | 260 - addons/r8125/src/4.4.180/rtltool.h | 86 - addons/r8168/install.sh | 4 - addons/r8168/manifest.yml | 30 - addons/r8168/src/3.10.108/Makefile | 62 - addons/r8168/src/3.10.108/r8168.h | 1842 - addons/r8168/src/3.10.108/r8168.mod.c | 31 - addons/r8168/src/3.10.108/r8168_asf.c | 422 - addons/r8168/src/3.10.108/r8168_asf.h | 295 - addons/r8168/src/3.10.108/r8168_dash.h | 256 - addons/r8168/src/3.10.108/r8168_fiber.h | 67 - addons/r8168/src/3.10.108/r8168_firmware.c | 264 - addons/r8168/src/3.10.108/r8168_firmware.h | 68 - addons/r8168/src/3.10.108/r8168_n.c | 28743 ---------------- addons/r8168/src/3.10.108/r8168_realwow.h | 118 - addons/r8168/src/3.10.108/rtl_eeprom.c | 289 - addons/r8168/src/3.10.108/rtl_eeprom.h | 56 - addons/r8168/src/3.10.108/rtltool.c | 359 - addons/r8168/src/3.10.108/rtltool.h | 86 - addons/r8168/src/4.4.180/Makefile | 62 - addons/r8168/src/4.4.180/r8168.h | 1842 - addons/r8168/src/4.4.180/r8168_asf.c | 422 - addons/r8168/src/4.4.180/r8168_asf.h | 295 - addons/r8168/src/4.4.180/r8168_dash.h | 256 - addons/r8168/src/4.4.180/r8168_fiber.h | 67 - addons/r8168/src/4.4.180/r8168_firmware.c | 264 - addons/r8168/src/4.4.180/r8168_firmware.h | 68 - addons/r8168/src/4.4.180/r8168_n.c | 28743 ---------------- addons/r8168/src/4.4.180/r8168_realwow.h | 118 - addons/r8168/src/4.4.180/rtl_eeprom.c | 289 - addons/r8168/src/4.4.180/rtl_eeprom.h | 56 - addons/r8168/src/4.4.180/rtltool.c | 359 - addons/r8168/src/4.4.180/rtltool.h | 86 - addons/r8169/install.sh | 5 - addons/r8169/manifest.yml | 30 - addons/r8169/src/3.10.108/Makefile | 2 - addons/r8169/src/3.10.108/mii.c | 472 - addons/r8169/src/3.10.108/r8169.c | 7150 ---- addons/r8169/src/4.4.180/Makefile | 2 - addons/r8169/src/4.4.180/mii.c | 474 - addons/r8169/src/4.4.180/r8169.c | 8482 ----- addons/skge/install.sh | 4 - addons/skge/manifest.yml | 28 - addons/skge/src/3.10.108/Makefile | 1 - addons/skge/src/3.10.108/skge.c | 4180 --- addons/skge/src/3.10.108/skge.h | 2584 -- addons/skge/src/4.4.180/Makefile | 1 - addons/skge/src/4.4.180/skge.c | 4228 --- addons/skge/src/4.4.180/skge.h | 2584 -- addons/virtio/install.sh | 14 - addons/virtio/manifest.yml | 28 - addons/virtio/src/3.10.108/Makefile | 5 - addons/virtio/src/3.10.108/config.c | 12 - addons/virtio/src/3.10.108/virtio.c | 246 - addons/virtio/src/3.10.108/virtio_mmio.c | 665 - addons/virtio/src/3.10.108/virtio_net.c | 1812 - addons/virtio/src/3.10.108/virtio_pci.c | 858 - addons/virtio/src/3.10.108/virtio_ring.c | 871 - addons/virtio/src/3.10.108/virtio_scsi.c | 1086 - addons/virtio/src/4.4.180/Makefile | 7 - addons/virtio/src/4.4.180/config.c | 12 - addons/virtio/src/4.4.180/virtio.c | 422 - addons/virtio/src/4.4.180/virtio_mmio.c | 770 - addons/virtio/src/4.4.180/virtio_net.c | 2070 -- addons/virtio/src/4.4.180/virtio_pci_common.c | 576 - addons/virtio/src/4.4.180/virtio_pci_common.h | 167 - addons/virtio/src/4.4.180/virtio_pci_legacy.c | 267 - addons/virtio/src/4.4.180/virtio_pci_modern.c | 747 - addons/virtio/src/4.4.180/virtio_ring.c | 875 - addons/virtio/src/4.4.180/virtio_scsi.c | 1200 - .../arpl/p3/addons/9p/apollolake-4.4.180.tgz | Bin 38385 -> 38384 bytes .../arpl/p3/addons/9p/broadwell-4.4.180.tgz | Bin 37739 -> 37734 bytes .../arpl/p3/addons/9p/broadwellnk-4.4.180.tgz | Bin 37737 -> 37735 bytes .../arpl/p3/addons/9p/bromolow-3.10.108.tgz | Bin 35343 -> 35340 bytes .../arpl/p3/addons/9p/denverton-4.4.180.tgz | Bin 38896 -> 38898 bytes .../arpl/p3/addons/9p/geminilake-4.4.180.tgz | Bin 37736 -> 37736 bytes .../arpl/p3/addons/9p/purley-4.4.180.tgz | Bin 37743 -> 37740 bytes .../board/arpl/p3/addons/9p/v1000-4.4.180.tgz | Bin 37738 -> 37739 bytes .../p3/addons/atl1c/apollolake-4.4.180.tgz | Bin 21684 -> 21683 bytes .../p3/addons/atl1c/broadwell-4.4.180.tgz | Bin 21460 -> 21458 bytes .../p3/addons/atl1c/broadwellnk-4.4.180.tgz | Bin 21459 -> 21459 bytes .../p3/addons/atl1c/bromolow-3.10.108.tgz | Bin 22381 -> 22383 bytes .../p3/addons/atl1c/denverton-4.4.180.tgz | Bin 21682 -> 21681 bytes .../p3/addons/atl1c/geminilake-4.4.180.tgz | Bin 21460 -> 21459 bytes .../arpl/p3/addons/atl1c/purley-4.4.180.tgz | Bin 21427 -> 21429 bytes .../arpl/p3/addons/atl1c/v1000-4.4.180.tgz | Bin 21463 -> 21462 bytes .../p3/addons/e1000/apollolake-4.4.180.tgz | Bin 55711 -> 55714 bytes .../p3/addons/e1000/broadwell-4.4.180.tgz | Bin 55058 -> 55061 bytes .../p3/addons/e1000/broadwellnk-4.4.180.tgz | Bin 55054 -> 55056 bytes .../p3/addons/e1000/bromolow-3.10.108.tgz | Bin 69800 -> 69803 bytes .../p3/addons/e1000/denverton-4.4.180.tgz | Bin 55712 -> 55714 bytes .../p3/addons/e1000/geminilake-4.4.180.tgz | Bin 55056 -> 55061 bytes .../arpl/p3/addons/e1000/purley-4.4.180.tgz | Bin 55015 -> 55019 bytes .../arpl/p3/addons/e1000/v1000-4.4.180.tgz | Bin 55056 -> 55061 bytes .../p3/addons/e1000e/apollolake-4.4.180.tgz | Bin 89630 -> 0 bytes .../p3/addons/e1000e/broadwell-4.4.180.tgz | Bin 88110 -> 0 bytes .../p3/addons/e1000e/broadwellnk-4.4.180.tgz | Bin 88116 -> 0 bytes .../p3/addons/e1000e/bromolow-3.10.108.tgz | Bin 109110 -> 109111 bytes .../p3/addons/e1000e/denverton-4.4.180.tgz | Bin 89630 -> 0 bytes .../p3/addons/e1000e/geminilake-4.4.180.tgz | Bin 88114 -> 0 bytes .../arpl/p3/addons/e1000e/purley-4.4.180.tgz | Bin 88088 -> 0 bytes .../arpl/p3/addons/e1000e/v1000-4.4.180.tgz | Bin 88113 -> 0 bytes .../p3/addons/ehci-pci/broadwell-4.4.180.tgz | Bin 31094 -> 31097 bytes .../p3/addons/mpt3sas/apollolake-4.4.180.tgz | Bin 107887 -> 107890 bytes .../p3/addons/mpt3sas/broadwell-4.4.180.tgz | Bin 105584 -> 105580 bytes .../p3/addons/mpt3sas/broadwellnk-4.4.180.tgz | Bin 105582 -> 105585 bytes .../p3/addons/mpt3sas/bromolow-3.10.108.tgz | Bin 79047 -> 79050 bytes .../p3/addons/mpt3sas/denverton-4.4.180.tgz | Bin 107897 -> 107899 bytes .../p3/addons/mpt3sas/geminilake-4.4.180.tgz | Bin 105615 -> 105616 bytes .../arpl/p3/addons/mpt3sas/purley-4.4.180.tgz | Bin 105595 -> 105599 bytes .../arpl/p3/addons/mpt3sas/v1000-4.4.180.tgz | Bin 105607 -> 105610 bytes files/board/arpl/p3/addons/qjs-dtb/all.tgz | Bin 548222 -> 548240 bytes .../p3/addons/r8125/apollolake-4.4.180.tgz | Bin 67101 -> 67102 bytes .../p3/addons/r8125/broadwell-4.4.180.tgz | Bin 66406 -> 66406 bytes .../p3/addons/r8125/broadwellnk-4.4.180.tgz | Bin 66405 -> 66406 bytes .../p3/addons/r8125/denverton-4.4.180.tgz | Bin 67002 -> 67005 bytes .../p3/addons/r8125/geminilake-4.4.180.tgz | Bin 66402 -> 66406 bytes .../arpl/p3/addons/r8125/purley-4.4.180.tgz | Bin 66406 -> 66407 bytes .../arpl/p3/addons/r8125/v1000-4.4.180.tgz | Bin 66400 -> 66407 bytes .../p3/addons/r8168/apollolake-4.4.180.tgz | Bin 166929 -> 166911 bytes .../p3/addons/r8168/broadwell-4.4.180.tgz | Bin 166204 -> 166207 bytes .../p3/addons/r8168/broadwellnk-4.4.180.tgz | Bin 166201 -> 166207 bytes .../p3/addons/r8168/bromolow-3.10.108.tgz | Bin 167561 -> 167562 bytes .../p3/addons/r8168/denverton-4.4.180.tgz | Bin 166925 -> 166926 bytes .../p3/addons/r8168/geminilake-4.4.180.tgz | Bin 166082 -> 166214 bytes .../arpl/p3/addons/r8168/purley-4.4.180.tgz | Bin 166082 -> 166214 bytes .../arpl/p3/addons/r8168/v1000-4.4.180.tgz | Bin 166216 -> 166218 bytes .../p3/addons/r8169/apollolake-4.4.180.tgz | Bin 39930 -> 39939 bytes .../p3/addons/r8169/broadwell-4.4.180.tgz | Bin 39585 -> 39589 bytes .../p3/addons/r8169/broadwellnk-4.4.180.tgz | Bin 39584 -> 39593 bytes .../p3/addons/r8169/bromolow-3.10.108.tgz | Bin 34577 -> 34584 bytes .../p3/addons/r8169/denverton-4.4.180.tgz | Bin 39931 -> 39942 bytes .../p3/addons/r8169/geminilake-4.4.180.tgz | Bin 39573 -> 39584 bytes .../arpl/p3/addons/r8169/purley-4.4.180.tgz | Bin 39620 -> 39624 bytes .../arpl/p3/addons/r8169/v1000-4.4.180.tgz | Bin 39588 -> 39593 bytes .../p3/addons/virtio/apollolake-4.4.180.tgz | Bin 41924 -> 41928 bytes .../p3/addons/virtio/broadwell-4.4.180.tgz | Bin 40916 -> 40923 bytes .../p3/addons/virtio/broadwellnk-4.4.180.tgz | Bin 40913 -> 40911 bytes .../p3/addons/virtio/bromolow-3.10.108.tgz | Bin 36951 -> 36955 bytes .../p3/addons/virtio/denverton-4.4.180.tgz | Bin 41924 -> 41917 bytes .../p3/addons/virtio/geminilake-4.4.180.tgz | Bin 40910 -> 40913 bytes .../arpl/p3/addons/virtio/purley-4.4.180.tgz | Bin 40882 -> 40897 bytes .../arpl/p3/addons/virtio/v1000-4.4.180.tgz | Bin 40915 -> 40919 bytes 407 files changed, 678 insertions(+), 356062 deletions(-) create mode 100644 LICENSE create mode 160000 addons delete mode 100644 addons/9p/install.sh delete mode 100644 addons/9p/manifest.yml delete mode 100644 addons/9p/src/3.10.108/Makefile delete mode 100644 addons/9p/src/3.10.108/acl.c delete mode 100644 addons/9p/src/3.10.108/acl.h delete mode 100644 addons/9p/src/3.10.108/cache.c delete mode 100644 addons/9p/src/3.10.108/cache.h delete mode 100644 addons/9p/src/3.10.108/client.c delete mode 100644 addons/9p/src/3.10.108/error.c delete mode 100644 addons/9p/src/3.10.108/fid.c delete mode 100644 addons/9p/src/3.10.108/fid.h delete mode 100644 addons/9p/src/3.10.108/mod.c delete mode 100644 addons/9p/src/3.10.108/protocol.c delete mode 100644 addons/9p/src/3.10.108/protocol.h delete mode 100644 addons/9p/src/3.10.108/trans_common.c delete mode 100644 addons/9p/src/3.10.108/trans_common.h delete mode 100644 addons/9p/src/3.10.108/trans_fd.c delete mode 100644 addons/9p/src/3.10.108/trans_rdma.c delete mode 100644 addons/9p/src/3.10.108/trans_virtio.c delete mode 100644 addons/9p/src/3.10.108/util.c delete mode 100644 addons/9p/src/3.10.108/v9fs.c delete mode 100644 addons/9p/src/3.10.108/v9fs.h delete mode 100644 addons/9p/src/3.10.108/v9fs_vfs.h delete mode 100644 addons/9p/src/3.10.108/vfs_addr.c delete mode 100644 addons/9p/src/3.10.108/vfs_dentry.c delete mode 100644 addons/9p/src/3.10.108/vfs_dir.c delete mode 100644 addons/9p/src/3.10.108/vfs_file.c delete mode 100644 addons/9p/src/3.10.108/vfs_inode.c delete mode 100644 addons/9p/src/3.10.108/vfs_inode_dotl.c delete mode 100644 addons/9p/src/3.10.108/vfs_super.c delete mode 100644 addons/9p/src/3.10.108/xattr.c delete mode 100644 addons/9p/src/3.10.108/xattr.h delete mode 100644 addons/9p/src/3.10.108/xattr_user.c delete mode 100644 addons/9p/src/4.4.180/Makefile delete mode 100644 addons/9p/src/4.4.180/acl.c delete mode 100644 addons/9p/src/4.4.180/acl.h delete mode 100644 addons/9p/src/4.4.180/cache.c delete mode 100644 addons/9p/src/4.4.180/cache.h delete mode 100644 addons/9p/src/4.4.180/client.c delete mode 100644 addons/9p/src/4.4.180/error.c delete mode 100644 addons/9p/src/4.4.180/fid.c delete mode 100644 addons/9p/src/4.4.180/fid.h delete mode 100644 addons/9p/src/4.4.180/mod.c delete mode 100644 addons/9p/src/4.4.180/protocol.c delete mode 100644 addons/9p/src/4.4.180/protocol.h delete mode 100644 addons/9p/src/4.4.180/trans_common.c delete mode 100644 addons/9p/src/4.4.180/trans_common.h delete mode 100644 addons/9p/src/4.4.180/trans_fd.c delete mode 100644 addons/9p/src/4.4.180/trans_rdma.c delete mode 100644 addons/9p/src/4.4.180/trans_virtio.c delete mode 100644 addons/9p/src/4.4.180/util.c delete mode 100644 addons/9p/src/4.4.180/v9fs.c delete mode 100644 addons/9p/src/4.4.180/v9fs.h delete mode 100644 addons/9p/src/4.4.180/v9fs_vfs.h delete mode 100644 addons/9p/src/4.4.180/vfs_addr.c delete mode 100644 addons/9p/src/4.4.180/vfs_dentry.c delete mode 100644 addons/9p/src/4.4.180/vfs_dir.c delete mode 100644 addons/9p/src/4.4.180/vfs_file.c delete mode 100644 addons/9p/src/4.4.180/vfs_inode.c delete mode 100644 addons/9p/src/4.4.180/vfs_inode_dotl.c delete mode 100644 addons/9p/src/4.4.180/vfs_super.c delete mode 100644 addons/9p/src/4.4.180/xattr.c delete mode 100644 addons/9p/src/4.4.180/xattr.h delete mode 100644 addons/acpid/all/addons/acpid.tgz delete mode 100644 addons/acpid/install.sh delete mode 100644 addons/acpid/manifest.yml delete mode 100644 addons/acpid/src/3.10.108/Makefile delete mode 100644 addons/acpid/src/3.10.108/button.c delete mode 100644 addons/acpid/src/4.4.180/Makefile delete mode 100644 addons/acpid/src/4.4.180/Module.symvers delete mode 100644 addons/acpid/src/4.4.180/button.c delete mode 100644 addons/acpid/src/4.4.180/modules.order delete mode 100644 addons/atl1c/install.sh delete mode 100644 addons/atl1c/manifest.yml delete mode 100644 addons/atl1c/src/3.10.108/Makefile delete mode 100644 addons/atl1c/src/3.10.108/atl1c.h delete mode 100644 addons/atl1c/src/3.10.108/atl1c_ethtool.c delete mode 100644 addons/atl1c/src/3.10.108/atl1c_hw.c delete mode 100644 addons/atl1c/src/3.10.108/atl1c_hw.h delete mode 100644 addons/atl1c/src/3.10.108/atl1c_main.c delete mode 100644 addons/atl1c/src/4.4.180/Makefile delete mode 100644 addons/atl1c/src/4.4.180/atl1c.h delete mode 100644 addons/atl1c/src/4.4.180/atl1c_ethtool.c delete mode 100644 addons/atl1c/src/4.4.180/atl1c_hw.c delete mode 100644 addons/atl1c/src/4.4.180/atl1c_hw.h delete mode 100644 addons/atl1c/src/4.4.180/atl1c_main.c delete mode 100644 addons/atl1e/install.sh delete mode 100644 addons/atl1e/manifest.yml delete mode 100644 addons/atl1e/src/3.10.108/Makefile delete mode 100644 addons/atl1e/src/3.10.108/atl1e.h delete mode 100644 addons/atl1e/src/3.10.108/atl1e_ethtool.c delete mode 100644 addons/atl1e/src/3.10.108/atl1e_hw.c delete mode 100644 addons/atl1e/src/3.10.108/atl1e_hw.h delete mode 100644 addons/atl1e/src/3.10.108/atl1e_main.c delete mode 100644 addons/atl1e/src/3.10.108/atl1e_param.c delete mode 100644 addons/atl1e/src/4.4.180/Makefile delete mode 100644 addons/atl1e/src/4.4.180/atl1e.h delete mode 100644 addons/atl1e/src/4.4.180/atl1e_ethtool.c delete mode 100644 addons/atl1e/src/4.4.180/atl1e_hw.c delete mode 100644 addons/atl1e/src/4.4.180/atl1e_hw.h delete mode 100644 addons/atl1e/src/4.4.180/atl1e_main.c delete mode 100644 addons/atl1e/src/4.4.180/atl1e_param.c delete mode 100755 addons/compile-addons.sh delete mode 100644 addons/e1000/install.sh delete mode 100644 addons/e1000/manifest.yml delete mode 100644 addons/e1000/src/3.10.108/Makefile delete mode 100644 addons/e1000/src/3.10.108/e1000.h delete mode 100644 addons/e1000/src/3.10.108/e1000_ethtool.c delete mode 100644 addons/e1000/src/3.10.108/e1000_hw.c delete mode 100644 addons/e1000/src/3.10.108/e1000_hw.h delete mode 100644 addons/e1000/src/3.10.108/e1000_main.c delete mode 100644 addons/e1000/src/3.10.108/e1000_osdep.h delete mode 100644 addons/e1000/src/3.10.108/e1000_param.c delete mode 100644 addons/e1000/src/4.4.180/Makefile delete mode 100644 addons/e1000/src/4.4.180/e1000.h delete mode 100644 addons/e1000/src/4.4.180/e1000_ethtool.c delete mode 100644 addons/e1000/src/4.4.180/e1000_hw.c delete mode 100644 addons/e1000/src/4.4.180/e1000_hw.h delete mode 100644 addons/e1000/src/4.4.180/e1000_main.c delete mode 100644 addons/e1000/src/4.4.180/e1000_osdep.h delete mode 100644 addons/e1000/src/4.4.180/e1000_param.c delete mode 100644 addons/e1000e/install.sh delete mode 100644 addons/e1000e/manifest.yml delete mode 100644 addons/e1000e/src/3.10.108/80003es2lan.c delete mode 100644 addons/e1000e/src/3.10.108/80003es2lan.h delete mode 100644 addons/e1000e/src/3.10.108/82571.c delete mode 100644 addons/e1000e/src/3.10.108/82571.h delete mode 100644 addons/e1000e/src/3.10.108/Makefile delete mode 100644 addons/e1000e/src/3.10.108/defines.h delete mode 100644 addons/e1000e/src/3.10.108/e1000.h delete mode 100644 addons/e1000e/src/3.10.108/ethtool.c delete mode 100644 addons/e1000e/src/3.10.108/hw.h delete mode 100644 addons/e1000e/src/3.10.108/ich8lan.c delete mode 100644 addons/e1000e/src/3.10.108/ich8lan.h delete mode 100644 addons/e1000e/src/3.10.108/mac.c delete mode 100644 addons/e1000e/src/3.10.108/mac.h delete mode 100644 addons/e1000e/src/3.10.108/manage.c delete mode 100644 addons/e1000e/src/3.10.108/manage.h delete mode 100644 addons/e1000e/src/3.10.108/netdev.c delete mode 100644 addons/e1000e/src/3.10.108/nvm.c delete mode 100644 addons/e1000e/src/3.10.108/nvm.h delete mode 100644 addons/e1000e/src/3.10.108/param.c delete mode 100644 addons/e1000e/src/3.10.108/phy.c delete mode 100644 addons/e1000e/src/3.10.108/phy.h delete mode 100644 addons/e1000e/src/3.10.108/ptp.c delete mode 100644 addons/e1000e/src/3.10.108/regs.h delete mode 100644 addons/e1000e/src/4.4.180/80003es2lan.c delete mode 100644 addons/e1000e/src/4.4.180/80003es2lan.h delete mode 100644 addons/e1000e/src/4.4.180/82571.c delete mode 100644 addons/e1000e/src/4.4.180/82571.h delete mode 100644 addons/e1000e/src/4.4.180/Makefile delete mode 100644 addons/e1000e/src/4.4.180/defines.h delete mode 100644 addons/e1000e/src/4.4.180/e1000.h delete mode 100644 addons/e1000e/src/4.4.180/ethtool.c delete mode 100644 addons/e1000e/src/4.4.180/hw.h delete mode 100644 addons/e1000e/src/4.4.180/ich8lan.c delete mode 100644 addons/e1000e/src/4.4.180/ich8lan.h delete mode 100644 addons/e1000e/src/4.4.180/mac.c delete mode 100644 addons/e1000e/src/4.4.180/mac.h delete mode 100644 addons/e1000e/src/4.4.180/manage.c delete mode 100644 addons/e1000e/src/4.4.180/manage.h delete mode 100644 addons/e1000e/src/4.4.180/netdev.c delete mode 100644 addons/e1000e/src/4.4.180/nvm.c delete mode 100644 addons/e1000e/src/4.4.180/nvm.h delete mode 100644 addons/e1000e/src/4.4.180/param.c delete mode 100644 addons/e1000e/src/4.4.180/phy.c delete mode 100644 addons/e1000e/src/4.4.180/phy.h delete mode 100644 addons/e1000e/src/4.4.180/ptp.c delete mode 100644 addons/e1000e/src/4.4.180/regs.h delete mode 100644 addons/ehci-pci/install-bromolow-3.10.108.sh delete mode 100644 addons/ehci-pci/install.sh delete mode 100644 addons/ehci-pci/manifest.yml delete mode 100644 addons/ehci-pci/src/3.10.108/Makefile delete mode 100644 addons/ehci-pci/src/3.10.108/ehci-dbg.c delete mode 100644 addons/ehci-pci/src/3.10.108/ehci-hcd.c delete mode 100644 addons/ehci-pci/src/3.10.108/ehci-hub.c delete mode 100644 addons/ehci-pci/src/3.10.108/ehci-mem.c delete mode 100644 addons/ehci-pci/src/3.10.108/ehci-pci.c delete mode 100644 addons/ehci-pci/src/3.10.108/ehci-q.c delete mode 100644 addons/ehci-pci/src/3.10.108/ehci-sched.c delete mode 100644 addons/ehci-pci/src/3.10.108/ehci-sysfs.c delete mode 100644 addons/ehci-pci/src/3.10.108/ehci-timer.c delete mode 100644 addons/ehci-pci/src/3.10.108/ehci.h delete mode 100644 addons/ehci-pci/src/3.10.108/pci-quirks.c delete mode 100644 addons/ehci-pci/src/3.10.108/pci-quirks.h delete mode 100644 addons/ehci-pci/src/3.10.108/xhci-ext-caps.h delete mode 100644 addons/ehci-pci/src/4.4.180/Makefile delete mode 100644 addons/ehci-pci/src/4.4.180/ehci-dbg.c delete mode 100644 addons/ehci-pci/src/4.4.180/ehci-hcd.c delete mode 100644 addons/ehci-pci/src/4.4.180/ehci-hub.c delete mode 100644 addons/ehci-pci/src/4.4.180/ehci-mem.c delete mode 100644 addons/ehci-pci/src/4.4.180/ehci-pci.c delete mode 100644 addons/ehci-pci/src/4.4.180/ehci-q.c delete mode 100644 addons/ehci-pci/src/4.4.180/ehci-sched.c delete mode 100644 addons/ehci-pci/src/4.4.180/ehci-sysfs.c delete mode 100644 addons/ehci-pci/src/4.4.180/ehci-timer.c delete mode 100644 addons/ehci-pci/src/4.4.180/ehci.h delete mode 100644 addons/ehci-pci/src/4.4.180/pci-quirks.c delete mode 100644 addons/ehci-pci/src/4.4.180/pci-quirks.h delete mode 100644 addons/ehci-pci/src/4.4.180/xhci-ext-caps.h delete mode 100644 addons/mpt3sas/install.sh delete mode 100644 addons/mpt3sas/manifest.yml delete mode 100644 addons/mpt3sas/src/3.10.108/Makefile delete mode 100644 addons/mpt3sas/src/3.10.108/mpi/mpi2.h delete mode 100644 addons/mpt3sas/src/3.10.108/mpi/mpi2_cnfg.h delete mode 100644 addons/mpt3sas/src/3.10.108/mpi/mpi2_init.h delete mode 100644 addons/mpt3sas/src/3.10.108/mpi/mpi2_ioc.h delete mode 100644 addons/mpt3sas/src/3.10.108/mpi/mpi2_raid.h delete mode 100644 addons/mpt3sas/src/3.10.108/mpi/mpi2_sas.h delete mode 100644 addons/mpt3sas/src/3.10.108/mpi/mpi2_tool.h delete mode 100644 addons/mpt3sas/src/3.10.108/mpi/mpi2_type.h delete mode 100644 addons/mpt3sas/src/3.10.108/mpt3sas_base.c delete mode 100644 addons/mpt3sas/src/3.10.108/mpt3sas_base.h delete mode 100644 addons/mpt3sas/src/3.10.108/mpt3sas_config.c delete mode 100644 addons/mpt3sas/src/3.10.108/mpt3sas_ctl.c delete mode 100644 addons/mpt3sas/src/3.10.108/mpt3sas_ctl.h delete mode 100644 addons/mpt3sas/src/3.10.108/mpt3sas_debug.h delete mode 100644 addons/mpt3sas/src/3.10.108/mpt3sas_scsih.c delete mode 100644 addons/mpt3sas/src/3.10.108/mpt3sas_transport.c delete mode 100644 addons/mpt3sas/src/3.10.108/mpt3sas_trigger_diag.c delete mode 100644 addons/mpt3sas/src/3.10.108/mpt3sas_trigger_diag.h delete mode 100644 addons/mpt3sas/src/4.4.180/Makefile delete mode 100644 addons/mpt3sas/src/4.4.180/mpi/mpi2.h delete mode 100644 addons/mpt3sas/src/4.4.180/mpi/mpi2_cnfg.h delete mode 100644 addons/mpt3sas/src/4.4.180/mpi/mpi2_init.h delete mode 100644 addons/mpt3sas/src/4.4.180/mpi/mpi2_ioc.h delete mode 100644 addons/mpt3sas/src/4.4.180/mpi/mpi2_raid.h delete mode 100644 addons/mpt3sas/src/4.4.180/mpi/mpi2_sas.h delete mode 100644 addons/mpt3sas/src/4.4.180/mpi/mpi2_tool.h delete mode 100644 addons/mpt3sas/src/4.4.180/mpi/mpi2_type.h delete mode 100644 addons/mpt3sas/src/4.4.180/mpt3sas_base.c delete mode 100644 addons/mpt3sas/src/4.4.180/mpt3sas_base.h delete mode 100644 addons/mpt3sas/src/4.4.180/mpt3sas_config.c delete mode 100644 addons/mpt3sas/src/4.4.180/mpt3sas_ctl.c delete mode 100644 addons/mpt3sas/src/4.4.180/mpt3sas_ctl.h delete mode 100644 addons/mpt3sas/src/4.4.180/mpt3sas_debug.h delete mode 100644 addons/mpt3sas/src/4.4.180/mpt3sas_scsih.c delete mode 100644 addons/mpt3sas/src/4.4.180/mpt3sas_transport.c delete mode 100644 addons/mpt3sas/src/4.4.180/mpt3sas_trigger_diag.c delete mode 100644 addons/mpt3sas/src/4.4.180/mpt3sas_trigger_diag.h delete mode 100644 addons/mpt3sas/src/4.4.180/mpt3sas_warpdrive.c delete mode 100644 addons/qjs-dtb/all/addons/dts.js delete mode 100755 addons/qjs-dtb/all/usr/sbin/dtc delete mode 100755 addons/qjs-dtb/all/usr/sbin/qjs delete mode 100644 addons/qjs-dtb/install.sh delete mode 100644 addons/qjs-dtb/manifest.yml delete mode 100644 addons/r8125/install.sh delete mode 100644 addons/r8125/manifest.yml delete mode 100755 addons/r8125/src/4.4.180/Makefile delete mode 100755 addons/r8125/src/4.4.180/r8125.h delete mode 100755 addons/r8125/src/4.4.180/r8125_dash.h delete mode 100755 addons/r8125/src/4.4.180/r8125_firmware.c delete mode 100755 addons/r8125/src/4.4.180/r8125_firmware.h delete mode 100755 addons/r8125/src/4.4.180/r8125_n.c delete mode 100755 addons/r8125/src/4.4.180/r8125_ptp.c delete mode 100755 addons/r8125/src/4.4.180/r8125_ptp.h delete mode 100755 addons/r8125/src/4.4.180/r8125_realwow.h delete mode 100755 addons/r8125/src/4.4.180/r8125_rss.c delete mode 100755 addons/r8125/src/4.4.180/r8125_rss.h delete mode 100755 addons/r8125/src/4.4.180/rtl_eeprom.c delete mode 100755 addons/r8125/src/4.4.180/rtl_eeprom.h delete mode 100755 addons/r8125/src/4.4.180/rtltool.c delete mode 100755 addons/r8125/src/4.4.180/rtltool.h delete mode 100644 addons/r8168/install.sh delete mode 100644 addons/r8168/manifest.yml delete mode 100644 addons/r8168/src/3.10.108/Makefile delete mode 100644 addons/r8168/src/3.10.108/r8168.h delete mode 100644 addons/r8168/src/3.10.108/r8168.mod.c delete mode 100644 addons/r8168/src/3.10.108/r8168_asf.c delete mode 100644 addons/r8168/src/3.10.108/r8168_asf.h delete mode 100644 addons/r8168/src/3.10.108/r8168_dash.h delete mode 100644 addons/r8168/src/3.10.108/r8168_fiber.h delete mode 100644 addons/r8168/src/3.10.108/r8168_firmware.c delete mode 100644 addons/r8168/src/3.10.108/r8168_firmware.h delete mode 100644 addons/r8168/src/3.10.108/r8168_n.c delete mode 100644 addons/r8168/src/3.10.108/r8168_realwow.h delete mode 100644 addons/r8168/src/3.10.108/rtl_eeprom.c delete mode 100644 addons/r8168/src/3.10.108/rtl_eeprom.h delete mode 100644 addons/r8168/src/3.10.108/rtltool.c delete mode 100644 addons/r8168/src/3.10.108/rtltool.h delete mode 100644 addons/r8168/src/4.4.180/Makefile delete mode 100644 addons/r8168/src/4.4.180/r8168.h delete mode 100644 addons/r8168/src/4.4.180/r8168_asf.c delete mode 100644 addons/r8168/src/4.4.180/r8168_asf.h delete mode 100644 addons/r8168/src/4.4.180/r8168_dash.h delete mode 100644 addons/r8168/src/4.4.180/r8168_fiber.h delete mode 100644 addons/r8168/src/4.4.180/r8168_firmware.c delete mode 100644 addons/r8168/src/4.4.180/r8168_firmware.h delete mode 100644 addons/r8168/src/4.4.180/r8168_n.c delete mode 100644 addons/r8168/src/4.4.180/r8168_realwow.h delete mode 100644 addons/r8168/src/4.4.180/rtl_eeprom.c delete mode 100644 addons/r8168/src/4.4.180/rtl_eeprom.h delete mode 100644 addons/r8168/src/4.4.180/rtltool.c delete mode 100644 addons/r8168/src/4.4.180/rtltool.h delete mode 100644 addons/r8169/install.sh delete mode 100644 addons/r8169/manifest.yml delete mode 100644 addons/r8169/src/3.10.108/Makefile delete mode 100644 addons/r8169/src/3.10.108/mii.c delete mode 100644 addons/r8169/src/3.10.108/r8169.c delete mode 100644 addons/r8169/src/4.4.180/Makefile delete mode 100644 addons/r8169/src/4.4.180/mii.c delete mode 100644 addons/r8169/src/4.4.180/r8169.c delete mode 100644 addons/skge/install.sh delete mode 100644 addons/skge/manifest.yml delete mode 100644 addons/skge/src/3.10.108/Makefile delete mode 100644 addons/skge/src/3.10.108/skge.c delete mode 100644 addons/skge/src/3.10.108/skge.h delete mode 100644 addons/skge/src/4.4.180/Makefile delete mode 100644 addons/skge/src/4.4.180/skge.c delete mode 100644 addons/skge/src/4.4.180/skge.h delete mode 100644 addons/virtio/install.sh delete mode 100644 addons/virtio/manifest.yml delete mode 100644 addons/virtio/src/3.10.108/Makefile delete mode 100644 addons/virtio/src/3.10.108/config.c delete mode 100644 addons/virtio/src/3.10.108/virtio.c delete mode 100644 addons/virtio/src/3.10.108/virtio_mmio.c delete mode 100644 addons/virtio/src/3.10.108/virtio_net.c delete mode 100644 addons/virtio/src/3.10.108/virtio_pci.c delete mode 100644 addons/virtio/src/3.10.108/virtio_ring.c delete mode 100644 addons/virtio/src/3.10.108/virtio_scsi.c delete mode 100644 addons/virtio/src/4.4.180/Makefile delete mode 100644 addons/virtio/src/4.4.180/config.c delete mode 100644 addons/virtio/src/4.4.180/virtio.c delete mode 100644 addons/virtio/src/4.4.180/virtio_mmio.c delete mode 100644 addons/virtio/src/4.4.180/virtio_net.c delete mode 100644 addons/virtio/src/4.4.180/virtio_pci_common.c delete mode 100644 addons/virtio/src/4.4.180/virtio_pci_common.h delete mode 100644 addons/virtio/src/4.4.180/virtio_pci_legacy.c delete mode 100644 addons/virtio/src/4.4.180/virtio_pci_modern.c delete mode 100644 addons/virtio/src/4.4.180/virtio_ring.c delete mode 100644 addons/virtio/src/4.4.180/virtio_scsi.c delete mode 100644 files/board/arpl/p3/addons/e1000e/apollolake-4.4.180.tgz delete mode 100644 files/board/arpl/p3/addons/e1000e/broadwell-4.4.180.tgz delete mode 100644 files/board/arpl/p3/addons/e1000e/broadwellnk-4.4.180.tgz delete mode 100644 files/board/arpl/p3/addons/e1000e/denverton-4.4.180.tgz delete mode 100644 files/board/arpl/p3/addons/e1000e/geminilake-4.4.180.tgz delete mode 100644 files/board/arpl/p3/addons/e1000e/purley-4.4.180.tgz delete mode 100644 files/board/arpl/p3/addons/e1000e/v1000-4.4.180.tgz diff --git a/.gitmodules b/.gitmodules index 630c2424..dfd4259b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "redpill-lkm"] path = redpill-lkm url = git@github.com:fbelavenuto/redpill-lkm.git +[submodule "addons"] + path = addons + url = git@github.com:fbelavenuto/arpl-addons.git diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..f288702d --- /dev/null +++ b/LICENSE @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/addons b/addons new file mode 160000 index 00000000..a82e40e2 --- /dev/null +++ b/addons @@ -0,0 +1 @@ +Subproject commit a82e40e27cc829d30a3f6ce216444da1d7e0d030 diff --git a/addons/9p/install.sh b/addons/9p/install.sh deleted file mode 100644 index a8d42d95..00000000 --- a/addons/9p/install.sh +++ /dev/null @@ -1,6 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Installing module for Plan 9 Resource Sharing Support (9P2000)" - ${INSMOD} "/modules/9pnet.ko" - ${INSMOD} "/modules/9pnet_virtio.ko" - ${INSMOD} "/modules/9p.ko" ${PARAMS} -fi diff --git a/addons/9p/manifest.yml b/addons/9p/manifest.yml deleted file mode 100644 index cd4c5807..00000000 --- a/addons/9p/manifest.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: 1 -name: 9p -description: "Driver for Plan 9 Resource Sharing Support (9P2000)" -available-for: - bromolow-3.10.108: - install-script: &script "install.sh" - modules: true - apollolake-4.4.180: - install-script: *script - modules: true - broadwell-4.4.180: - install-script: *script - modules: true - broadwellnk-4.4.180: - install-script: *script - modules: true - denverton-4.4.180: - install-script: *script - modules: true - geminilake-4.4.180: - install-script: *script - modules: true - v1000-4.4.180: - install-script: *script - modules: true - purley-4.4.180: - install-script: *script - modules: true diff --git a/addons/9p/src/3.10.108/Makefile b/addons/9p/src/3.10.108/Makefile deleted file mode 100644 index 0d269d65..00000000 --- a/addons/9p/src/3.10.108/Makefile +++ /dev/null @@ -1,36 +0,0 @@ -obj-m := 9p.o - -9p-objs := \ - vfs_super.o \ - vfs_inode.o \ - vfs_inode_dotl.o \ - vfs_addr.o \ - vfs_file.o \ - vfs_dir.o \ - vfs_dentry.o \ - v9fs.o \ - fid.o \ - xattr.o \ - xattr_user.o - -9p-y += cache.o -9p-n += acl.o - -obj-m := 9pnet.o -obj-m += 9pnet_virtio.o -obj-n += 9pnet_rdma.o - -9pnet-objs := \ - mod.o \ - client.o \ - error.o \ - util.o \ - protocol.o \ - trans_fd.o \ - trans_common.o \ - -9pnet_virtio-objs := \ - trans_virtio.o - -9pnet_rdma-objs := \ - trans_rdma.o diff --git a/addons/9p/src/3.10.108/acl.c b/addons/9p/src/3.10.108/acl.c deleted file mode 100644 index 9686c1f1..00000000 --- a/addons/9p/src/3.10.108/acl.c +++ /dev/null @@ -1,375 +0,0 @@ -/* - * Copyright IBM Corporation, 2010 - * Author Aneesh Kumar K.V - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "xattr.h" -#include "acl.h" -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" - -static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name) -{ - ssize_t size; - void *value = NULL; - struct posix_acl *acl = NULL; - - size = v9fs_fid_xattr_get(fid, name, NULL, 0); - if (size > 0) { - value = kzalloc(size, GFP_NOFS); - if (!value) - return ERR_PTR(-ENOMEM); - size = v9fs_fid_xattr_get(fid, name, value, size); - if (size > 0) { - acl = posix_acl_from_xattr(&init_user_ns, value, size); - if (IS_ERR(acl)) - goto err_out; - } - } else if (size == -ENODATA || size == 0 || - size == -ENOSYS || size == -EOPNOTSUPP) { - acl = NULL; - } else - acl = ERR_PTR(-EIO); - -err_out: - kfree(value); - return acl; -} - -int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) -{ - int retval = 0; - struct posix_acl *pacl, *dacl; - struct v9fs_session_info *v9ses; - - v9ses = v9fs_inode2v9ses(inode); - if (((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) || - ((v9ses->flags & V9FS_ACL_MASK) != V9FS_POSIX_ACL)) { - set_cached_acl(inode, ACL_TYPE_DEFAULT, NULL); - set_cached_acl(inode, ACL_TYPE_ACCESS, NULL); - return 0; - } - /* get the default/access acl values and cache them */ - dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT); - pacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_ACCESS); - - if (!IS_ERR(dacl) && !IS_ERR(pacl)) { - set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl); - set_cached_acl(inode, ACL_TYPE_ACCESS, pacl); - } else - retval = -EIO; - - if (!IS_ERR(dacl)) - posix_acl_release(dacl); - - if (!IS_ERR(pacl)) - posix_acl_release(pacl); - - return retval; -} - -static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type) -{ - struct posix_acl *acl; - /* - * 9p Always cache the acl value when - * instantiating the inode (v9fs_inode_from_fid) - */ - acl = get_cached_acl(inode, type); - BUG_ON(acl == ACL_NOT_CACHED); - return acl; -} - -struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type) -{ - struct v9fs_session_info *v9ses; - - v9ses = v9fs_inode2v9ses(inode); - if (((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) || - ((v9ses->flags & V9FS_ACL_MASK) != V9FS_POSIX_ACL)) { - /* - * On access = client and acl = on mode get the acl - * values from the server - */ - return NULL; - } - return v9fs_get_cached_acl(inode, type); - -} - -static int v9fs_set_acl(struct p9_fid *fid, int type, struct posix_acl *acl) -{ - int retval; - char *name; - size_t size; - void *buffer; - if (!acl) - return 0; - - /* Set a setxattr request to server */ - size = posix_acl_xattr_size(acl->a_count); - buffer = kmalloc(size, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - retval = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); - if (retval < 0) - goto err_free_out; - switch (type) { - case ACL_TYPE_ACCESS: - name = POSIX_ACL_XATTR_ACCESS; - break; - case ACL_TYPE_DEFAULT: - name = POSIX_ACL_XATTR_DEFAULT; - break; - default: - BUG(); - } - retval = v9fs_fid_xattr_set(fid, name, buffer, size, 0); -err_free_out: - kfree(buffer); - return retval; -} - -int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid) -{ - int retval = 0; - struct posix_acl *acl; - - if (S_ISLNK(inode->i_mode)) - return -EOPNOTSUPP; - acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS); - if (acl) { - retval = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); - if (retval) - return retval; - set_cached_acl(inode, ACL_TYPE_ACCESS, acl); - retval = v9fs_set_acl(fid, ACL_TYPE_ACCESS, acl); - posix_acl_release(acl); - } - return retval; -} - -int v9fs_set_create_acl(struct inode *inode, struct p9_fid *fid, - struct posix_acl *dacl, struct posix_acl *acl) -{ - set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl); - set_cached_acl(inode, ACL_TYPE_ACCESS, acl); - v9fs_set_acl(fid, ACL_TYPE_DEFAULT, dacl); - v9fs_set_acl(fid, ACL_TYPE_ACCESS, acl); - return 0; -} - -void v9fs_put_acl(struct posix_acl *dacl, - struct posix_acl *acl) -{ - posix_acl_release(dacl); - posix_acl_release(acl); -} - -int v9fs_acl_mode(struct inode *dir, umode_t *modep, - struct posix_acl **dpacl, struct posix_acl **pacl) -{ - int retval = 0; - umode_t mode = *modep; - struct posix_acl *acl = NULL; - - if (!S_ISLNK(mode)) { - acl = v9fs_get_cached_acl(dir, ACL_TYPE_DEFAULT); - if (IS_ERR(acl)) - return PTR_ERR(acl); - if (!acl) - mode &= ~current_umask(); - } - if (acl) { - if (S_ISDIR(mode)) - *dpacl = posix_acl_dup(acl); - retval = posix_acl_create(&acl, GFP_NOFS, &mode); - if (retval < 0) - return retval; - if (retval > 0) - *pacl = acl; - else - posix_acl_release(acl); - } - *modep = mode; - return 0; -} - -static int v9fs_remote_get_acl(struct dentry *dentry, const char *name, - void *buffer, size_t size, int type) -{ - char *full_name; - - switch (type) { - case ACL_TYPE_ACCESS: - full_name = POSIX_ACL_XATTR_ACCESS; - break; - case ACL_TYPE_DEFAULT: - full_name = POSIX_ACL_XATTR_DEFAULT; - break; - default: - BUG(); - } - return v9fs_xattr_get(dentry, full_name, buffer, size); -} - -static int v9fs_xattr_get_acl(struct dentry *dentry, const char *name, - void *buffer, size_t size, int type) -{ - struct v9fs_session_info *v9ses; - struct posix_acl *acl; - int error; - - if (strcmp(name, "") != 0) - return -EINVAL; - - v9ses = v9fs_dentry2v9ses(dentry); - /* - * We allow set/get/list of acl when access=client is not specified - */ - if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) - return v9fs_remote_get_acl(dentry, name, buffer, size, type); - - acl = v9fs_get_cached_acl(dentry->d_inode, type); - if (IS_ERR(acl)) - return PTR_ERR(acl); - if (acl == NULL) - return -ENODATA; - error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); - posix_acl_release(acl); - - return error; -} - -static int v9fs_remote_set_acl(struct dentry *dentry, const char *name, - const void *value, size_t size, - int flags, int type) -{ - char *full_name; - - switch (type) { - case ACL_TYPE_ACCESS: - full_name = POSIX_ACL_XATTR_ACCESS; - break; - case ACL_TYPE_DEFAULT: - full_name = POSIX_ACL_XATTR_DEFAULT; - break; - default: - BUG(); - } - return v9fs_xattr_set(dentry, full_name, value, size, flags); -} - - -static int v9fs_xattr_set_acl(struct dentry *dentry, const char *name, - const void *value, size_t size, - int flags, int type) -{ - int retval; - struct posix_acl *acl; - struct v9fs_session_info *v9ses; - struct inode *inode = dentry->d_inode; - - if (strcmp(name, "") != 0) - return -EINVAL; - - v9ses = v9fs_dentry2v9ses(dentry); - /* - * set the attribute on the remote. Without even looking at the - * xattr value. We leave it to the server to validate - */ - if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) - return v9fs_remote_set_acl(dentry, name, - value, size, flags, type); - - if (S_ISLNK(inode->i_mode)) - return -EOPNOTSUPP; - if (!inode_owner_or_capable(inode)) - return -EPERM; - if (value) { - /* update the cached acl value */ - acl = posix_acl_from_xattr(&init_user_ns, value, size); - if (IS_ERR(acl)) - return PTR_ERR(acl); - else if (acl) { - retval = posix_acl_valid(acl); - if (retval) - goto err_out; - } - } else - acl = NULL; - - switch (type) { - case ACL_TYPE_ACCESS: - name = POSIX_ACL_XATTR_ACCESS; - if (acl) { - struct iattr iattr; - - retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); - if (retval) - goto err_out; - if (!acl) { - /* - * ACL can be represented - * by the mode bits. So don't - * update ACL. - */ - value = NULL; - size = 0; - } - iattr.ia_valid = ATTR_MODE; - /* FIXME should we update ctime ? - * What is the following setxattr update the - * mode ? - */ - v9fs_vfs_setattr_dotl(dentry, &iattr); - } - break; - case ACL_TYPE_DEFAULT: - name = POSIX_ACL_XATTR_DEFAULT; - if (!S_ISDIR(inode->i_mode)) { - retval = acl ? -EINVAL : 0; - goto err_out; - } - break; - default: - BUG(); - } - retval = v9fs_xattr_set(dentry, name, value, size, flags); - if (!retval) - set_cached_acl(inode, type, acl); -err_out: - posix_acl_release(acl); - return retval; -} - -const struct xattr_handler v9fs_xattr_acl_access_handler = { - .prefix = POSIX_ACL_XATTR_ACCESS, - .flags = ACL_TYPE_ACCESS, - .get = v9fs_xattr_get_acl, - .set = v9fs_xattr_set_acl, -}; - -const struct xattr_handler v9fs_xattr_acl_default_handler = { - .prefix = POSIX_ACL_XATTR_DEFAULT, - .flags = ACL_TYPE_DEFAULT, - .get = v9fs_xattr_get_acl, - .set = v9fs_xattr_set_acl, -}; diff --git a/addons/9p/src/3.10.108/acl.h b/addons/9p/src/3.10.108/acl.h deleted file mode 100644 index e4f7e882..00000000 --- a/addons/9p/src/3.10.108/acl.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright IBM Corporation, 2010 - * Author Aneesh Kumar K.V - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ -#ifndef FS_9P_ACL_H -#define FS_9P_ACL_H - -#ifdef CONFIG_9P_FS_POSIX_ACL -extern int v9fs_get_acl(struct inode *, struct p9_fid *); -extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type); -extern int v9fs_acl_chmod(struct inode *, struct p9_fid *); -extern int v9fs_set_create_acl(struct inode *, struct p9_fid *, - struct posix_acl *, struct posix_acl *); -extern int v9fs_acl_mode(struct inode *dir, umode_t *modep, - struct posix_acl **dpacl, struct posix_acl **pacl); -extern void v9fs_put_acl(struct posix_acl *dacl, struct posix_acl *acl); -#else -#define v9fs_iop_get_acl NULL -static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) -{ - return 0; -} -static inline int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid) -{ - return 0; -} -static inline int v9fs_set_create_acl(struct inode *inode, - struct p9_fid *fid, - struct posix_acl *dacl, - struct posix_acl *acl) -{ - return 0; -} -static inline void v9fs_put_acl(struct posix_acl *dacl, - struct posix_acl *acl) -{ -} -static inline int v9fs_acl_mode(struct inode *dir, umode_t *modep, - struct posix_acl **dpacl, - struct posix_acl **pacl) -{ - return 0; -} - -#endif -#endif /* FS_9P_XATTR_H */ diff --git a/addons/9p/src/3.10.108/cache.c b/addons/9p/src/3.10.108/cache.c deleted file mode 100644 index a9ea73d6..00000000 --- a/addons/9p/src/3.10.108/cache.c +++ /dev/null @@ -1,415 +0,0 @@ -/* - * V9FS cache definitions. - * - * Copyright (C) 2009 by Abhishek Kulkarni - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "cache.h" - -#define CACHETAG_LEN 11 - -struct fscache_netfs v9fs_cache_netfs = { - .name = "9p", - .version = 0, -}; - -/** - * v9fs_random_cachetag - Generate a random tag to be associated - * with a new cache session. - * - * The value of jiffies is used for a fairly randomly cache tag. - */ - -static -int v9fs_random_cachetag(struct v9fs_session_info *v9ses) -{ - v9ses->cachetag = kmalloc(CACHETAG_LEN, GFP_KERNEL); - if (!v9ses->cachetag) - return -ENOMEM; - - return scnprintf(v9ses->cachetag, CACHETAG_LEN, "%lu", jiffies); -} - -static uint16_t v9fs_cache_session_get_key(const void *cookie_netfs_data, - void *buffer, uint16_t bufmax) -{ - struct v9fs_session_info *v9ses; - uint16_t klen = 0; - - v9ses = (struct v9fs_session_info *)cookie_netfs_data; - p9_debug(P9_DEBUG_FSC, "session %p buf %p size %u\n", - v9ses, buffer, bufmax); - - if (v9ses->cachetag) - klen = strlen(v9ses->cachetag); - - if (klen > bufmax) - return 0; - - memcpy(buffer, v9ses->cachetag, klen); - p9_debug(P9_DEBUG_FSC, "cache session tag %s\n", v9ses->cachetag); - return klen; -} - -const struct fscache_cookie_def v9fs_cache_session_index_def = { - .name = "9P.session", - .type = FSCACHE_COOKIE_TYPE_INDEX, - .get_key = v9fs_cache_session_get_key, -}; - -void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses) -{ - /* If no cache session tag was specified, we generate a random one. */ - if (!v9ses->cachetag) - v9fs_random_cachetag(v9ses); - - v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index, - &v9fs_cache_session_index_def, - v9ses); - p9_debug(P9_DEBUG_FSC, "session %p get cookie %p\n", - v9ses, v9ses->fscache); -} - -void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses) -{ - p9_debug(P9_DEBUG_FSC, "session %p put cookie %p\n", - v9ses, v9ses->fscache); - fscache_relinquish_cookie(v9ses->fscache, 0); - v9ses->fscache = NULL; -} - - -static uint16_t v9fs_cache_inode_get_key(const void *cookie_netfs_data, - void *buffer, uint16_t bufmax) -{ - const struct v9fs_inode *v9inode = cookie_netfs_data; - memcpy(buffer, &v9inode->qid.path, sizeof(v9inode->qid.path)); - p9_debug(P9_DEBUG_FSC, "inode %p get key %llu\n", - &v9inode->vfs_inode, v9inode->qid.path); - return sizeof(v9inode->qid.path); -} - -static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data, - uint64_t *size) -{ - const struct v9fs_inode *v9inode = cookie_netfs_data; - *size = i_size_read(&v9inode->vfs_inode); - - p9_debug(P9_DEBUG_FSC, "inode %p get attr %llu\n", - &v9inode->vfs_inode, *size); -} - -static uint16_t v9fs_cache_inode_get_aux(const void *cookie_netfs_data, - void *buffer, uint16_t buflen) -{ - const struct v9fs_inode *v9inode = cookie_netfs_data; - memcpy(buffer, &v9inode->qid.version, sizeof(v9inode->qid.version)); - p9_debug(P9_DEBUG_FSC, "inode %p get aux %u\n", - &v9inode->vfs_inode, v9inode->qid.version); - return sizeof(v9inode->qid.version); -} - -static enum -fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data, - const void *buffer, - uint16_t buflen) -{ - const struct v9fs_inode *v9inode = cookie_netfs_data; - - if (buflen != sizeof(v9inode->qid.version)) - return FSCACHE_CHECKAUX_OBSOLETE; - - if (memcmp(buffer, &v9inode->qid.version, - sizeof(v9inode->qid.version))) - return FSCACHE_CHECKAUX_OBSOLETE; - - return FSCACHE_CHECKAUX_OKAY; -} - -static void v9fs_cache_inode_now_uncached(void *cookie_netfs_data) -{ - struct v9fs_inode *v9inode = cookie_netfs_data; - struct pagevec pvec; - pgoff_t first; - int loop, nr_pages; - - pagevec_init(&pvec, 0); - first = 0; - - for (;;) { - nr_pages = pagevec_lookup(&pvec, v9inode->vfs_inode.i_mapping, - first, - PAGEVEC_SIZE - pagevec_count(&pvec)); - if (!nr_pages) - break; - - for (loop = 0; loop < nr_pages; loop++) - ClearPageFsCache(pvec.pages[loop]); - - first = pvec.pages[nr_pages - 1]->index + 1; - - pvec.nr = nr_pages; - pagevec_release(&pvec); - cond_resched(); - } -} - -const struct fscache_cookie_def v9fs_cache_inode_index_def = { - .name = "9p.inode", - .type = FSCACHE_COOKIE_TYPE_DATAFILE, - .get_key = v9fs_cache_inode_get_key, - .get_attr = v9fs_cache_inode_get_attr, - .get_aux = v9fs_cache_inode_get_aux, - .check_aux = v9fs_cache_inode_check_aux, - .now_uncached = v9fs_cache_inode_now_uncached, -}; - -void v9fs_cache_inode_get_cookie(struct inode *inode) -{ - struct v9fs_inode *v9inode; - struct v9fs_session_info *v9ses; - - if (!S_ISREG(inode->i_mode)) - return; - - v9inode = V9FS_I(inode); - if (v9inode->fscache) - return; - - v9ses = v9fs_inode2v9ses(inode); - v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, - &v9fs_cache_inode_index_def, - v9inode); - - p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n", - inode, v9inode->fscache); -} - -void v9fs_cache_inode_put_cookie(struct inode *inode) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - - if (!v9inode->fscache) - return; - p9_debug(P9_DEBUG_FSC, "inode %p put cookie %p\n", - inode, v9inode->fscache); - - fscache_relinquish_cookie(v9inode->fscache, 0); - v9inode->fscache = NULL; -} - -void v9fs_cache_inode_flush_cookie(struct inode *inode) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - - if (!v9inode->fscache) - return; - p9_debug(P9_DEBUG_FSC, "inode %p flush cookie %p\n", - inode, v9inode->fscache); - - fscache_relinquish_cookie(v9inode->fscache, 1); - v9inode->fscache = NULL; -} - -void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - struct p9_fid *fid; - - if (!v9inode->fscache) - return; - - spin_lock(&v9inode->fscache_lock); - fid = filp->private_data; - if ((filp->f_flags & O_ACCMODE) != O_RDONLY) - v9fs_cache_inode_flush_cookie(inode); - else - v9fs_cache_inode_get_cookie(inode); - - spin_unlock(&v9inode->fscache_lock); -} - -void v9fs_cache_inode_reset_cookie(struct inode *inode) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - struct v9fs_session_info *v9ses; - struct fscache_cookie *old; - - if (!v9inode->fscache) - return; - - old = v9inode->fscache; - - spin_lock(&v9inode->fscache_lock); - fscache_relinquish_cookie(v9inode->fscache, 1); - - v9ses = v9fs_inode2v9ses(inode); - v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, - &v9fs_cache_inode_index_def, - v9inode); - p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p\n", - inode, old, v9inode->fscache); - - spin_unlock(&v9inode->fscache_lock); -} - -int __v9fs_fscache_release_page(struct page *page, gfp_t gfp) -{ - struct inode *inode = page->mapping->host; - struct v9fs_inode *v9inode = V9FS_I(inode); - - BUG_ON(!v9inode->fscache); - - return fscache_maybe_release_page(v9inode->fscache, page, gfp); -} - -void __v9fs_fscache_invalidate_page(struct page *page) -{ - struct inode *inode = page->mapping->host; - struct v9fs_inode *v9inode = V9FS_I(inode); - - BUG_ON(!v9inode->fscache); - - if (PageFsCache(page)) { - fscache_wait_on_page_write(v9inode->fscache, page); - BUG_ON(!PageLocked(page)); - fscache_uncache_page(v9inode->fscache, page); - } -} - -static void v9fs_vfs_readpage_complete(struct page *page, void *data, - int error) -{ - if (!error) - SetPageUptodate(page); - - unlock_page(page); -} - -/** - * __v9fs_readpage_from_fscache - read a page from cache - * - * Returns 0 if the pages are in cache and a BIO is submitted, - * 1 if the pages are not in cache and -error otherwise. - */ - -int __v9fs_readpage_from_fscache(struct inode *inode, struct page *page) -{ - int ret; - const struct v9fs_inode *v9inode = V9FS_I(inode); - - p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page); - if (!v9inode->fscache) - return -ENOBUFS; - - ret = fscache_read_or_alloc_page(v9inode->fscache, - page, - v9fs_vfs_readpage_complete, - NULL, - GFP_KERNEL); - switch (ret) { - case -ENOBUFS: - case -ENODATA: - p9_debug(P9_DEBUG_FSC, "page/inode not in cache %d\n", ret); - return 1; - case 0: - p9_debug(P9_DEBUG_FSC, "BIO submitted\n"); - return ret; - default: - p9_debug(P9_DEBUG_FSC, "ret %d\n", ret); - return ret; - } -} - -/** - * __v9fs_readpages_from_fscache - read multiple pages from cache - * - * Returns 0 if the pages are in cache and a BIO is submitted, - * 1 if the pages are not in cache and -error otherwise. - */ - -int __v9fs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - int ret; - const struct v9fs_inode *v9inode = V9FS_I(inode); - - p9_debug(P9_DEBUG_FSC, "inode %p pages %u\n", inode, *nr_pages); - if (!v9inode->fscache) - return -ENOBUFS; - - ret = fscache_read_or_alloc_pages(v9inode->fscache, - mapping, pages, nr_pages, - v9fs_vfs_readpage_complete, - NULL, - mapping_gfp_mask(mapping)); - switch (ret) { - case -ENOBUFS: - case -ENODATA: - p9_debug(P9_DEBUG_FSC, "pages/inodes not in cache %d\n", ret); - return 1; - case 0: - BUG_ON(!list_empty(pages)); - BUG_ON(*nr_pages != 0); - p9_debug(P9_DEBUG_FSC, "BIO submitted\n"); - return ret; - default: - p9_debug(P9_DEBUG_FSC, "ret %d\n", ret); - return ret; - } -} - -/** - * __v9fs_readpage_to_fscache - write a page to the cache - * - */ - -void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page) -{ - int ret; - const struct v9fs_inode *v9inode = V9FS_I(inode); - - p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page); - ret = fscache_write_page(v9inode->fscache, page, GFP_KERNEL); - p9_debug(P9_DEBUG_FSC, "ret = %d\n", ret); - if (ret != 0) - v9fs_uncache_page(inode, page); -} - -/* - * wait for a page to complete writing to the cache - */ -void __v9fs_fscache_wait_on_page_write(struct inode *inode, struct page *page) -{ - const struct v9fs_inode *v9inode = V9FS_I(inode); - p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page); - if (PageFsCache(page)) - fscache_wait_on_page_write(v9inode->fscache, page); -} diff --git a/addons/9p/src/3.10.108/cache.h b/addons/9p/src/3.10.108/cache.h deleted file mode 100644 index 40cc54ce..00000000 --- a/addons/9p/src/3.10.108/cache.h +++ /dev/null @@ -1,139 +0,0 @@ -/* - * V9FS cache definitions. - * - * Copyright (C) 2009 by Abhishek Kulkarni - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#ifndef _9P_CACHE_H -#ifdef CONFIG_9P_FSCACHE -#include -#include - -extern struct fscache_netfs v9fs_cache_netfs; -extern const struct fscache_cookie_def v9fs_cache_session_index_def; -extern const struct fscache_cookie_def v9fs_cache_inode_index_def; - -extern void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses); -extern void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses); - -extern void v9fs_cache_inode_get_cookie(struct inode *inode); -extern void v9fs_cache_inode_put_cookie(struct inode *inode); -extern void v9fs_cache_inode_flush_cookie(struct inode *inode); -extern void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp); -extern void v9fs_cache_inode_reset_cookie(struct inode *inode); - -extern int __v9fs_cache_register(void); -extern void __v9fs_cache_unregister(void); - -extern int __v9fs_fscache_release_page(struct page *page, gfp_t gfp); -extern void __v9fs_fscache_invalidate_page(struct page *page); -extern int __v9fs_readpage_from_fscache(struct inode *inode, - struct page *page); -extern int __v9fs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages); -extern void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page); -extern void __v9fs_fscache_wait_on_page_write(struct inode *inode, - struct page *page); - -static inline int v9fs_fscache_release_page(struct page *page, - gfp_t gfp) -{ - return __v9fs_fscache_release_page(page, gfp); -} - -static inline void v9fs_fscache_invalidate_page(struct page *page) -{ - __v9fs_fscache_invalidate_page(page); -} - -static inline int v9fs_readpage_from_fscache(struct inode *inode, - struct page *page) -{ - return __v9fs_readpage_from_fscache(inode, page); -} - -static inline int v9fs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - return __v9fs_readpages_from_fscache(inode, mapping, pages, - nr_pages); -} - -static inline void v9fs_readpage_to_fscache(struct inode *inode, - struct page *page) -{ - if (PageFsCache(page)) - __v9fs_readpage_to_fscache(inode, page); -} - -static inline void v9fs_uncache_page(struct inode *inode, struct page *page) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - fscache_uncache_page(v9inode->fscache, page); - BUG_ON(PageFsCache(page)); -} - -static inline void v9fs_fscache_wait_on_page_write(struct inode *inode, - struct page *page) -{ - return __v9fs_fscache_wait_on_page_write(inode, page); -} - -#else /* CONFIG_9P_FSCACHE */ - -static inline int v9fs_fscache_release_page(struct page *page, - gfp_t gfp) { - return 1; -} - -static inline void v9fs_fscache_invalidate_page(struct page *page) {} - -static inline int v9fs_readpage_from_fscache(struct inode *inode, - struct page *page) -{ - return -ENOBUFS; -} - -static inline int v9fs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - return -ENOBUFS; -} - -static inline void v9fs_readpage_to_fscache(struct inode *inode, - struct page *page) -{} - -static inline void v9fs_uncache_page(struct inode *inode, struct page *page) -{} - -static inline void v9fs_fscache_wait_on_page_write(struct inode *inode, - struct page *page) -{ - return; -} - -#endif /* CONFIG_9P_FSCACHE */ -#endif /* _9P_CACHE_H */ diff --git a/addons/9p/src/3.10.108/client.c b/addons/9p/src/3.10.108/client.c deleted file mode 100644 index e191aab9..00000000 --- a/addons/9p/src/3.10.108/client.c +++ /dev/null @@ -1,2256 +0,0 @@ -/* - * net/9p/clnt.c - * - * 9P Client - * - * Copyright (C) 2008 by Eric Van Hensbergen - * Copyright (C) 2007 by Latchesar Ionkov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "protocol.h" - -#define CREATE_TRACE_POINTS -#include - -/* - * Client Option Parsing (code inspired by NFS code) - * - a little lazy - parse all client options - */ - -enum { - Opt_msize, - Opt_trans, - Opt_legacy, - Opt_version, - Opt_err, -}; - -static const match_table_t tokens = { - {Opt_msize, "msize=%u"}, - {Opt_legacy, "noextend"}, - {Opt_trans, "trans=%s"}, - {Opt_version, "version=%s"}, - {Opt_err, NULL}, -}; - -inline int p9_is_proto_dotl(struct p9_client *clnt) -{ - return clnt->proto_version == p9_proto_2000L; -} -EXPORT_SYMBOL(p9_is_proto_dotl); - -inline int p9_is_proto_dotu(struct p9_client *clnt) -{ - return clnt->proto_version == p9_proto_2000u; -} -EXPORT_SYMBOL(p9_is_proto_dotu); - -/* - * Some error codes are taken directly from the server replies, - * make sure they are valid. - */ -static int safe_errno(int err) -{ - if ((err > 0) || (err < -MAX_ERRNO)) { - p9_debug(P9_DEBUG_ERROR, "Invalid error code %d\n", err); - return -EPROTO; - } - return err; -} - - -/* Interpret mount option for protocol version */ -static int get_protocol_version(char *s) -{ - int version = -EINVAL; - - if (!strcmp(s, "9p2000")) { - version = p9_proto_legacy; - p9_debug(P9_DEBUG_9P, "Protocol version: Legacy\n"); - } else if (!strcmp(s, "9p2000.u")) { - version = p9_proto_2000u; - p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.u\n"); - } else if (!strcmp(s, "9p2000.L")) { - version = p9_proto_2000L; - p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.L\n"); - } else - pr_info("Unknown protocol version %s\n", s); - - return version; -} - -/** - * parse_options - parse mount options into client structure - * @opts: options string passed from mount - * @clnt: existing v9fs client information - * - * Return 0 upon success, -ERRNO upon failure - */ - -static int parse_opts(char *opts, struct p9_client *clnt) -{ - char *options, *tmp_options; - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - char *s; - int ret = 0; - - clnt->proto_version = p9_proto_2000u; - clnt->msize = 8192; - - if (!opts) - return 0; - - tmp_options = kstrdup(opts, GFP_KERNEL); - if (!tmp_options) { - p9_debug(P9_DEBUG_ERROR, - "failed to allocate copy of option string\n"); - return -ENOMEM; - } - options = tmp_options; - - while ((p = strsep(&options, ",")) != NULL) { - int token, r; - if (!*p) - continue; - token = match_token(p, tokens, args); - switch (token) { - case Opt_msize: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - clnt->msize = option; - break; - case Opt_trans: - s = match_strdup(&args[0]); - if (!s) { - ret = -ENOMEM; - p9_debug(P9_DEBUG_ERROR, - "problem allocating copy of trans arg\n"); - goto free_and_return; - } - clnt->trans_mod = v9fs_get_trans_by_name(s); - if (clnt->trans_mod == NULL) { - pr_info("Could not find request transport: %s\n", - s); - ret = -EINVAL; - kfree(s); - goto free_and_return; - } - kfree(s); - break; - case Opt_legacy: - clnt->proto_version = p9_proto_legacy; - break; - case Opt_version: - s = match_strdup(&args[0]); - if (!s) { - ret = -ENOMEM; - p9_debug(P9_DEBUG_ERROR, - "problem allocating copy of version arg\n"); - goto free_and_return; - } - ret = get_protocol_version(s); - if (ret == -EINVAL) { - kfree(s); - goto free_and_return; - } - kfree(s); - clnt->proto_version = ret; - break; - default: - continue; - } - } - -free_and_return: - kfree(tmp_options); - return ret; -} - -/** - * p9_tag_alloc - lookup/allocate a request by tag - * @c: client session to lookup tag within - * @tag: numeric id for transaction - * - * this is a simple array lookup, but will grow the - * request_slots as necessary to accommodate transaction - * ids which did not previously have a slot. - * - * this code relies on the client spinlock to manage locks, its - * possible we should switch to something else, but I'd rather - * stick with something low-overhead for the common case. - * - */ - -static struct p9_req_t * -p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size) -{ - unsigned long flags; - int row, col; - struct p9_req_t *req; - int alloc_msize = min(c->msize, max_size); - - /* This looks up the original request by tag so we know which - * buffer to read the data into */ - tag++; - - if (tag >= c->max_tag) { - spin_lock_irqsave(&c->lock, flags); - /* check again since original check was outside of lock */ - while (tag >= c->max_tag) { - row = (tag / P9_ROW_MAXTAG); - c->reqs[row] = kcalloc(P9_ROW_MAXTAG, - sizeof(struct p9_req_t), GFP_ATOMIC); - - if (!c->reqs[row]) { - pr_err("Couldn't grow tag array\n"); - spin_unlock_irqrestore(&c->lock, flags); - return ERR_PTR(-ENOMEM); - } - for (col = 0; col < P9_ROW_MAXTAG; col++) { - c->reqs[row][col].status = REQ_STATUS_IDLE; - c->reqs[row][col].tc = NULL; - } - c->max_tag += P9_ROW_MAXTAG; - } - spin_unlock_irqrestore(&c->lock, flags); - } - row = tag / P9_ROW_MAXTAG; - col = tag % P9_ROW_MAXTAG; - - req = &c->reqs[row][col]; - if (!req->tc) { - req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS); - if (!req->wq) { - pr_err("Couldn't grow tag array\n"); - return ERR_PTR(-ENOMEM); - } - init_waitqueue_head(req->wq); - req->tc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, - GFP_NOFS); - req->rc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, - GFP_NOFS); - if ((!req->tc) || (!req->rc)) { - pr_err("Couldn't grow tag array\n"); - kfree(req->tc); - kfree(req->rc); - kfree(req->wq); - req->tc = req->rc = NULL; - req->wq = NULL; - return ERR_PTR(-ENOMEM); - } - req->tc->capacity = alloc_msize; - req->rc->capacity = alloc_msize; - req->tc->sdata = (char *) req->tc + sizeof(struct p9_fcall); - req->rc->sdata = (char *) req->rc + sizeof(struct p9_fcall); - } - - p9pdu_reset(req->tc); - p9pdu_reset(req->rc); - - req->tc->tag = tag-1; - req->status = REQ_STATUS_ALLOC; - - return &c->reqs[row][col]; -} - -/** - * p9_tag_lookup - lookup a request by tag - * @c: client session to lookup tag within - * @tag: numeric id for transaction - * - */ - -struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag) -{ - int row, col; - - /* This looks up the original request by tag so we know which - * buffer to read the data into */ - tag++; - - if(tag >= c->max_tag) - return NULL; - - row = tag / P9_ROW_MAXTAG; - col = tag % P9_ROW_MAXTAG; - - return &c->reqs[row][col]; -} -EXPORT_SYMBOL(p9_tag_lookup); - -/** - * p9_tag_init - setup tags structure and contents - * @c: v9fs client struct - * - * This initializes the tags structure for each client instance. - * - */ - -static int p9_tag_init(struct p9_client *c) -{ - int err = 0; - - c->tagpool = p9_idpool_create(); - if (IS_ERR(c->tagpool)) { - err = PTR_ERR(c->tagpool); - goto error; - } - err = p9_idpool_get(c->tagpool); /* reserve tag 0 */ - if (err < 0) { - p9_idpool_destroy(c->tagpool); - goto error; - } - c->max_tag = 0; -error: - return err; -} - -/** - * p9_tag_cleanup - cleans up tags structure and reclaims resources - * @c: v9fs client struct - * - * This frees resources associated with the tags structure - * - */ -static void p9_tag_cleanup(struct p9_client *c) -{ - int row, col; - - /* check to insure all requests are idle */ - for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { - for (col = 0; col < P9_ROW_MAXTAG; col++) { - if (c->reqs[row][col].status != REQ_STATUS_IDLE) { - p9_debug(P9_DEBUG_MUX, - "Attempting to cleanup non-free tag %d,%d\n", - row, col); - /* TODO: delay execution of cleanup */ - return; - } - } - } - - if (c->tagpool) { - p9_idpool_put(0, c->tagpool); /* free reserved tag 0 */ - p9_idpool_destroy(c->tagpool); - } - - /* free requests associated with tags */ - for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { - for (col = 0; col < P9_ROW_MAXTAG; col++) { - kfree(c->reqs[row][col].wq); - kfree(c->reqs[row][col].tc); - kfree(c->reqs[row][col].rc); - } - kfree(c->reqs[row]); - } - c->max_tag = 0; -} - -/** - * p9_free_req - free a request and clean-up as necessary - * c: client state - * r: request to release - * - */ - -static void p9_free_req(struct p9_client *c, struct p9_req_t *r) -{ - int tag = r->tc->tag; - p9_debug(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag); - - r->status = REQ_STATUS_IDLE; - if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool)) - p9_idpool_put(tag, c->tagpool); -} - -/** - * p9_client_cb - call back from transport to client - * c: client state - * req: request received - * - */ -void p9_client_cb(struct p9_client *c, struct p9_req_t *req) -{ - p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); - wake_up(req->wq); - p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); -} -EXPORT_SYMBOL(p9_client_cb); - -/** - * p9_parse_header - parse header arguments out of a packet - * @pdu: packet to parse - * @size: size of packet - * @type: type of request - * @tag: tag of packet - * @rewind: set if we need to rewind offset afterwards - */ - -int -p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag, - int rewind) -{ - int8_t r_type; - int16_t r_tag; - int32_t r_size; - int offset = pdu->offset; - int err; - - pdu->offset = 0; - if (pdu->size == 0) - pdu->size = 7; - - err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag); - if (err) - goto rewind_and_exit; - - pdu->size = r_size; - pdu->id = r_type; - pdu->tag = r_tag; - - p9_debug(P9_DEBUG_9P, "<<< size=%d type: %d tag: %d\n", - pdu->size, pdu->id, pdu->tag); - - if (type) - *type = r_type; - if (tag) - *tag = r_tag; - if (size) - *size = r_size; - - -rewind_and_exit: - if (rewind) - pdu->offset = offset; - return err; -} -EXPORT_SYMBOL(p9_parse_header); - -/** - * p9_check_errors - check 9p packet for error return and process it - * @c: current client instance - * @req: request to parse and check for error conditions - * - * returns error code if one is discovered, otherwise returns 0 - * - * this will have to be more complicated if we have multiple - * error packet types - */ - -static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) -{ - int8_t type; - int err; - int ecode; - - err = p9_parse_header(req->rc, NULL, &type, NULL, 0); - /* - * dump the response from server - * This should be after check errors which poplulate pdu_fcall. - */ - trace_9p_protocol_dump(c, req->rc); - if (err) { - p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err); - return err; - } - if (type != P9_RERROR && type != P9_RLERROR) - return 0; - - if (!p9_is_proto_dotl(c)) { - char *ename; - err = p9pdu_readf(req->rc, c->proto_version, "s?d", - &ename, &ecode); - if (err) - goto out_err; - - if (p9_is_proto_dotu(c)) - err = -ecode; - - if (!err || !IS_ERR_VALUE(err)) { - err = p9_errstr2errno(ename, strlen(ename)); - - p9_debug(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", - -ecode, ename); - } - kfree(ename); - } else { - err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); - err = -ecode; - - p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); - } - - return err; - -out_err: - p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err); - - return err; -} - -/** - * p9_check_zc_errors - check 9p packet for error return and process it - * @c: current client instance - * @req: request to parse and check for error conditions - * @in_hdrlen: Size of response protocol buffer. - * - * returns error code if one is discovered, otherwise returns 0 - * - * this will have to be more complicated if we have multiple - * error packet types - */ - -static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, - char *uidata, int in_hdrlen, int kern_buf) -{ - int err; - int ecode; - int8_t type; - char *ename = NULL; - - err = p9_parse_header(req->rc, NULL, &type, NULL, 0); - /* - * dump the response from server - * This should be after parse_header which poplulate pdu_fcall. - */ - trace_9p_protocol_dump(c, req->rc); - if (err) { - p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err); - return err; - } - - if (type != P9_RERROR && type != P9_RLERROR) - return 0; - - if (!p9_is_proto_dotl(c)) { - /* Error is reported in string format */ - int len; - /* 7 = header size for RERROR; */ - int inline_len = in_hdrlen - 7; - - len = req->rc->size - req->rc->offset; - if (len > (P9_ZC_HDR_SZ - 7)) { - err = -EFAULT; - goto out_err; - } - - ename = &req->rc->sdata[req->rc->offset]; - if (len > inline_len) { - /* We have error in external buffer */ - if (kern_buf) { - memcpy(ename + inline_len, uidata, - len - inline_len); - } else { - err = copy_from_user(ename + inline_len, - uidata, len - inline_len); - if (err) { - err = -EFAULT; - goto out_err; - } - } - } - ename = NULL; - err = p9pdu_readf(req->rc, c->proto_version, "s?d", - &ename, &ecode); - if (err) - goto out_err; - - if (p9_is_proto_dotu(c)) - err = -ecode; - - if (!err || !IS_ERR_VALUE(err)) { - err = p9_errstr2errno(ename, strlen(ename)); - - p9_debug(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", - -ecode, ename); - } - kfree(ename); - } else { - err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); - err = -ecode; - - p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); - } - return err; - -out_err: - p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err); - return err; -} - -static struct p9_req_t * -p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); - -/** - * p9_client_flush - flush (cancel) a request - * @c: client state - * @oldreq: request to cancel - * - * This sents a flush for a particular request and links - * the flush request to the original request. The current - * code only supports a single flush request although the protocol - * allows for multiple flush requests to be sent for a single request. - * - */ - -static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) -{ - struct p9_req_t *req; - int16_t oldtag; - int err; - - err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1); - if (err) - return err; - - p9_debug(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag); - - req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag); - if (IS_ERR(req)) - return PTR_ERR(req); - - - /* if we haven't received a response for oldreq, - remove it from the list. */ - spin_lock(&c->lock); - if (oldreq->status == REQ_STATUS_FLSH) - list_del(&oldreq->req_list); - spin_unlock(&c->lock); - - p9_free_req(c, req); - return 0; -} - -static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, - int8_t type, int req_size, - const char *fmt, va_list ap) -{ - int tag, err; - struct p9_req_t *req; - - p9_debug(P9_DEBUG_MUX, "client %p op %d\n", c, type); - - /* we allow for any status other than disconnected */ - if (c->status == Disconnected) - return ERR_PTR(-EIO); - - /* if status is begin_disconnected we allow only clunk request */ - if ((c->status == BeginDisconnect) && (type != P9_TCLUNK)) - return ERR_PTR(-EIO); - - tag = P9_NOTAG; - if (type != P9_TVERSION) { - tag = p9_idpool_get(c->tagpool); - if (tag < 0) - return ERR_PTR(-ENOMEM); - } - - req = p9_tag_alloc(c, tag, req_size); - if (IS_ERR(req)) - return req; - - /* marshall the data */ - p9pdu_prepare(req->tc, tag, type); - err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); - if (err) - goto reterr; - p9pdu_finalize(c, req->tc); - trace_9p_client_req(c, type, tag); - return req; -reterr: - p9_free_req(c, req); - return ERR_PTR(err); -} - -/** - * p9_client_rpc - issue a request and wait for a response - * @c: client session - * @type: type of request - * @fmt: protocol format string (see protocol.c) - * - * Returns request structure (which client must free using p9_free_req) - */ - -static struct p9_req_t * -p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) -{ - va_list ap; - int sigpending, err; - unsigned long flags; - struct p9_req_t *req; - - va_start(ap, fmt); - req = p9_client_prepare_req(c, type, c->msize, fmt, ap); - va_end(ap); - if (IS_ERR(req)) - return req; - - if (signal_pending(current)) { - sigpending = 1; - clear_thread_flag(TIF_SIGPENDING); - } else - sigpending = 0; - - err = c->trans_mod->request(c, req); - if (err < 0) { - if (err != -ERESTARTSYS && err != -EFAULT) - c->status = Disconnected; - goto reterr; - } -again: - /* Wait for the response */ - err = wait_event_interruptible(*req->wq, - req->status >= REQ_STATUS_RCVD); - - if ((err == -ERESTARTSYS) && (c->status == Connected) - && (type == P9_TFLUSH)) { - sigpending = 1; - clear_thread_flag(TIF_SIGPENDING); - goto again; - } - - if (req->status == REQ_STATUS_ERROR) { - p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); - err = req->t_err; - } - if ((err == -ERESTARTSYS) && (c->status == Connected)) { - p9_debug(P9_DEBUG_MUX, "flushing\n"); - sigpending = 1; - clear_thread_flag(TIF_SIGPENDING); - - if (c->trans_mod->cancel(c, req)) - p9_client_flush(c, req); - - /* if we received the response anyway, don't signal error */ - if (req->status == REQ_STATUS_RCVD) - err = 0; - } - if (sigpending) { - spin_lock_irqsave(¤t->sighand->siglock, flags); - recalc_sigpending(); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - } - if (err < 0) - goto reterr; - - err = p9_check_errors(c, req); - trace_9p_client_res(c, type, req->rc->tag, err); - if (!err) - return req; -reterr: - p9_free_req(c, req); - return ERR_PTR(safe_errno(err)); -} - -/** - * p9_client_zc_rpc - issue a request and wait for a response - * @c: client session - * @type: type of request - * @uidata: user bffer that should be ued for zero copy read - * @uodata: user buffer that shoud be user for zero copy write - * @inlen: read buffer size - * @olen: write buffer size - * @hdrlen: reader header size, This is the size of response protocol data - * @fmt: protocol format string (see protocol.c) - * - * Returns request structure (which client must free using p9_free_req) - */ -static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, - char *uidata, char *uodata, - int inlen, int olen, int in_hdrlen, - int kern_buf, const char *fmt, ...) -{ - va_list ap; - int sigpending, err; - unsigned long flags; - struct p9_req_t *req; - - va_start(ap, fmt); - /* - * We allocate a inline protocol data of only 4k bytes. - * The actual content is passed in zero-copy fashion. - */ - req = p9_client_prepare_req(c, type, P9_ZC_HDR_SZ, fmt, ap); - va_end(ap); - if (IS_ERR(req)) - return req; - - if (signal_pending(current)) { - sigpending = 1; - clear_thread_flag(TIF_SIGPENDING); - } else - sigpending = 0; - - /* If we are called with KERNEL_DS force kern_buf */ - if (segment_eq(get_fs(), KERNEL_DS)) - kern_buf = 1; - - err = c->trans_mod->zc_request(c, req, uidata, uodata, - inlen, olen, in_hdrlen, kern_buf); - if (err < 0) { - if (err == -EIO) - c->status = Disconnected; - if (err != -ERESTARTSYS) - goto reterr; - } - if (req->status == REQ_STATUS_ERROR) { - p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); - err = req->t_err; - } - if ((err == -ERESTARTSYS) && (c->status == Connected)) { - p9_debug(P9_DEBUG_MUX, "flushing\n"); - sigpending = 1; - clear_thread_flag(TIF_SIGPENDING); - - if (c->trans_mod->cancel(c, req)) - p9_client_flush(c, req); - - /* if we received the response anyway, don't signal error */ - if (req->status == REQ_STATUS_RCVD) - err = 0; - } - if (sigpending) { - spin_lock_irqsave(¤t->sighand->siglock, flags); - recalc_sigpending(); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - } - if (err < 0) - goto reterr; - - err = p9_check_zc_errors(c, req, uidata, in_hdrlen, kern_buf); - trace_9p_client_res(c, type, req->rc->tag, err); - if (!err) - return req; -reterr: - p9_free_req(c, req); - return ERR_PTR(safe_errno(err)); -} - -static struct p9_fid *p9_fid_create(struct p9_client *clnt) -{ - int ret; - struct p9_fid *fid; - unsigned long flags; - - p9_debug(P9_DEBUG_FID, "clnt %p\n", clnt); - fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL); - if (!fid) - return ERR_PTR(-ENOMEM); - - ret = p9_idpool_get(clnt->fidpool); - if (ret < 0) { - ret = -ENOSPC; - goto error; - } - fid->fid = ret; - - memset(&fid->qid, 0, sizeof(struct p9_qid)); - fid->mode = -1; - fid->uid = current_fsuid(); - fid->clnt = clnt; - fid->rdir = NULL; - spin_lock_irqsave(&clnt->lock, flags); - list_add(&fid->flist, &clnt->fidlist); - spin_unlock_irqrestore(&clnt->lock, flags); - - return fid; - -error: - kfree(fid); - return ERR_PTR(ret); -} - -static void p9_fid_destroy(struct p9_fid *fid) -{ - struct p9_client *clnt; - unsigned long flags; - - p9_debug(P9_DEBUG_FID, "fid %d\n", fid->fid); - clnt = fid->clnt; - p9_idpool_put(fid->fid, clnt->fidpool); - spin_lock_irqsave(&clnt->lock, flags); - list_del(&fid->flist); - spin_unlock_irqrestore(&clnt->lock, flags); - kfree(fid->rdir); - kfree(fid); -} - -static int p9_client_version(struct p9_client *c) -{ - int err = 0; - struct p9_req_t *req; - char *version; - int msize; - - p9_debug(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n", - c->msize, c->proto_version); - - switch (c->proto_version) { - case p9_proto_2000L: - req = p9_client_rpc(c, P9_TVERSION, "ds", - c->msize, "9P2000.L"); - break; - case p9_proto_2000u: - req = p9_client_rpc(c, P9_TVERSION, "ds", - c->msize, "9P2000.u"); - break; - case p9_proto_legacy: - req = p9_client_rpc(c, P9_TVERSION, "ds", - c->msize, "9P2000"); - break; - default: - return -EINVAL; - break; - } - - if (IS_ERR(req)) - return PTR_ERR(req); - - err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version); - if (err) { - p9_debug(P9_DEBUG_9P, "version error %d\n", err); - trace_9p_protocol_dump(c, req->rc); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); - if (!strncmp(version, "9P2000.L", 8)) - c->proto_version = p9_proto_2000L; - else if (!strncmp(version, "9P2000.u", 8)) - c->proto_version = p9_proto_2000u; - else if (!strncmp(version, "9P2000", 6)) - c->proto_version = p9_proto_legacy; - else { - err = -EREMOTEIO; - goto error; - } - - if (msize < c->msize) - c->msize = msize; - -error: - kfree(version); - p9_free_req(c, req); - - return err; -} - -struct p9_client *p9_client_create(const char *dev_name, char *options) -{ - int err; - struct p9_client *clnt; - - err = 0; - clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL); - if (!clnt) - return ERR_PTR(-ENOMEM); - - clnt->trans_mod = NULL; - clnt->trans = NULL; - spin_lock_init(&clnt->lock); - INIT_LIST_HEAD(&clnt->fidlist); - - err = p9_tag_init(clnt); - if (err < 0) - goto free_client; - - err = parse_opts(options, clnt); - if (err < 0) - goto destroy_tagpool; - - if (!clnt->trans_mod) - clnt->trans_mod = v9fs_get_default_trans(); - - if (clnt->trans_mod == NULL) { - err = -EPROTONOSUPPORT; - p9_debug(P9_DEBUG_ERROR, - "No transport defined or default transport\n"); - goto destroy_tagpool; - } - - clnt->fidpool = p9_idpool_create(); - if (IS_ERR(clnt->fidpool)) { - err = PTR_ERR(clnt->fidpool); - goto put_trans; - } - - p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n", - clnt, clnt->trans_mod, clnt->msize, clnt->proto_version); - - err = clnt->trans_mod->create(clnt, dev_name, options); - if (err) - goto destroy_fidpool; - - if (clnt->msize > clnt->trans_mod->maxsize) - clnt->msize = clnt->trans_mod->maxsize; - - err = p9_client_version(clnt); - if (err) - goto close_trans; - - return clnt; - -close_trans: - clnt->trans_mod->close(clnt); -destroy_fidpool: - p9_idpool_destroy(clnt->fidpool); -put_trans: - v9fs_put_trans(clnt->trans_mod); -destroy_tagpool: - p9_idpool_destroy(clnt->tagpool); -free_client: - kfree(clnt); - return ERR_PTR(err); -} -EXPORT_SYMBOL(p9_client_create); - -void p9_client_destroy(struct p9_client *clnt) -{ - struct p9_fid *fid, *fidptr; - - p9_debug(P9_DEBUG_MUX, "clnt %p\n", clnt); - - if (clnt->trans_mod) - clnt->trans_mod->close(clnt); - - v9fs_put_trans(clnt->trans_mod); - - list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) { - pr_info("Found fid %d not clunked\n", fid->fid); - p9_fid_destroy(fid); - } - - if (clnt->fidpool) - p9_idpool_destroy(clnt->fidpool); - - p9_tag_cleanup(clnt); - - kfree(clnt); -} -EXPORT_SYMBOL(p9_client_destroy); - -void p9_client_disconnect(struct p9_client *clnt) -{ - p9_debug(P9_DEBUG_9P, "clnt %p\n", clnt); - clnt->status = Disconnected; -} -EXPORT_SYMBOL(p9_client_disconnect); - -void p9_client_begin_disconnect(struct p9_client *clnt) -{ - p9_debug(P9_DEBUG_9P, "clnt %p\n", clnt); - clnt->status = BeginDisconnect; -} -EXPORT_SYMBOL(p9_client_begin_disconnect); - -struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, - char *uname, kuid_t n_uname, char *aname) -{ - int err = 0; - struct p9_req_t *req; - struct p9_fid *fid; - struct p9_qid qid; - - - p9_debug(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n", - afid ? afid->fid : -1, uname, aname); - fid = p9_fid_create(clnt); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - fid = NULL; - goto error; - } - - req = p9_client_rpc(clnt, P9_TATTACH, "ddss?u", fid->fid, - afid ? afid->fid : P9_NOFID, uname, aname, n_uname); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n", - qid.type, (unsigned long long)qid.path, qid.version); - - memmove(&fid->qid, &qid, sizeof(struct p9_qid)); - - p9_free_req(clnt, req); - return fid; - -error: - if (fid) - p9_fid_destroy(fid); - return ERR_PTR(err); -} -EXPORT_SYMBOL(p9_client_attach); - -struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname, - char **wnames, int clone) -{ - int err; - struct p9_client *clnt; - struct p9_fid *fid; - struct p9_qid *wqids; - struct p9_req_t *req; - uint16_t nwqids, count; - - err = 0; - wqids = NULL; - clnt = oldfid->clnt; - if (clone) { - fid = p9_fid_create(clnt); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - fid = NULL; - goto error; - } - - fid->uid = oldfid->uid; - } else - fid = oldfid; - - - p9_debug(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %ud wname[0] %s\n", - oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL); - - req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid, - nwname, wnames); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - goto clunk_fid; - } - p9_free_req(clnt, req); - - p9_debug(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids); - - if (nwqids != nwname) { - err = -ENOENT; - goto clunk_fid; - } - - for (count = 0; count < nwqids; count++) - p9_debug(P9_DEBUG_9P, "<<< [%d] %x.%llx.%x\n", - count, wqids[count].type, - (unsigned long long)wqids[count].path, - wqids[count].version); - - if (nwname) - memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid)); - else - fid->qid = oldfid->qid; - - kfree(wqids); - return fid; - -clunk_fid: - kfree(wqids); - p9_client_clunk(fid); - fid = NULL; - -error: - if (fid && (fid != oldfid)) - p9_fid_destroy(fid); - - return ERR_PTR(err); -} -EXPORT_SYMBOL(p9_client_walk); - -int p9_client_open(struct p9_fid *fid, int mode) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - struct p9_qid qid; - int iounit; - - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> %s fid %d mode %d\n", - p9_is_proto_dotl(clnt) ? "TLOPEN" : "TOPEN", fid->fid, mode); - err = 0; - - if (fid->mode != -1) - return -EINVAL; - - if (p9_is_proto_dotl(clnt)) - req = p9_client_rpc(clnt, P9_TLOPEN, "dd", fid->fid, mode); - else - req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto free_and_error; - } - - p9_debug(P9_DEBUG_9P, "<<< %s qid %x.%llx.%x iounit %x\n", - p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN", qid.type, - (unsigned long long)qid.path, qid.version, iounit); - - fid->mode = mode; - fid->iounit = iounit; - -free_and_error: - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_open); - -int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode, - kgid_t gid, struct p9_qid *qid) -{ - int err = 0; - struct p9_client *clnt; - struct p9_req_t *req; - int iounit; - - p9_debug(P9_DEBUG_9P, - ">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n", - ofid->fid, name, flags, mode, - from_kgid(&init_user_ns, gid)); - clnt = ofid->clnt; - - if (ofid->mode != -1) - return -EINVAL; - - req = p9_client_rpc(clnt, P9_TLCREATE, "dsddg", ofid->fid, name, flags, - mode, gid); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", qid, &iounit); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto free_and_error; - } - - p9_debug(P9_DEBUG_9P, "<<< RLCREATE qid %x.%llx.%x iounit %x\n", - qid->type, - (unsigned long long)qid->path, - qid->version, iounit); - - ofid->mode = mode; - ofid->iounit = iounit; - -free_and_error: - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_create_dotl); - -int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, - char *extension) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - struct p9_qid qid; - int iounit; - - p9_debug(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n", - fid->fid, name, perm, mode); - err = 0; - clnt = fid->clnt; - - if (fid->mode != -1) - return -EINVAL; - - req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm, - mode, extension); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto free_and_error; - } - - p9_debug(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n", - qid.type, - (unsigned long long)qid.path, - qid.version, iounit); - - fid->mode = mode; - fid->iounit = iounit; - -free_and_error: - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_fcreate); - -int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, kgid_t gid, - struct p9_qid *qid) -{ - int err = 0; - struct p9_client *clnt; - struct p9_req_t *req; - - p9_debug(P9_DEBUG_9P, ">>> TSYMLINK dfid %d name %s symtgt %s\n", - dfid->fid, name, symtgt); - clnt = dfid->clnt; - - req = p9_client_rpc(clnt, P9_TSYMLINK, "dssg", dfid->fid, name, symtgt, - gid); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto free_and_error; - } - - p9_debug(P9_DEBUG_9P, "<<< RSYMLINK qid %x.%llx.%x\n", - qid->type, (unsigned long long)qid->path, qid->version); - -free_and_error: - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_symlink); - -int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname) -{ - struct p9_client *clnt; - struct p9_req_t *req; - - p9_debug(P9_DEBUG_9P, ">>> TLINK dfid %d oldfid %d newname %s\n", - dfid->fid, oldfid->fid, newname); - clnt = dfid->clnt; - req = p9_client_rpc(clnt, P9_TLINK, "dds", dfid->fid, oldfid->fid, - newname); - if (IS_ERR(req)) - return PTR_ERR(req); - - p9_debug(P9_DEBUG_9P, "<<< RLINK\n"); - p9_free_req(clnt, req); - return 0; -} -EXPORT_SYMBOL(p9_client_link); - -int p9_client_fsync(struct p9_fid *fid, int datasync) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - p9_debug(P9_DEBUG_9P, ">>> TFSYNC fid %d datasync:%d\n", - fid->fid, datasync); - err = 0; - clnt = fid->clnt; - - req = p9_client_rpc(clnt, P9_TFSYNC, "dd", fid->fid, datasync); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid); - - p9_free_req(clnt, req); - -error: - return err; -} -EXPORT_SYMBOL(p9_client_fsync); - -int p9_client_clunk(struct p9_fid *fid) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - int retries = 0; - - if (!fid) { - pr_warn("%s (%d): Trying to clunk with NULL fid\n", - __func__, task_pid_nr(current)); - dump_stack(); - return 0; - } - -again: - p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n", fid->fid, - retries); - err = 0; - clnt = fid->clnt; - - req = p9_client_rpc(clnt, P9_TCLUNK, "d", fid->fid); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid); - - p9_free_req(clnt, req); -error: - /* - * Fid is not valid even after a failed clunk - * If interrupted, retry once then give up and - * leak fid until umount. - */ - if (err == -ERESTARTSYS) { - if (retries++ == 0) - goto again; - } else - p9_fid_destroy(fid); - return err; -} -EXPORT_SYMBOL(p9_client_clunk); - -int p9_client_remove(struct p9_fid *fid) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - p9_debug(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid); - err = 0; - clnt = fid->clnt; - - req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid); - - p9_free_req(clnt, req); -error: - if (err == -ERESTARTSYS) - p9_client_clunk(fid); - else - p9_fid_destroy(fid); - return err; -} -EXPORT_SYMBOL(p9_client_remove); - -int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags) -{ - int err = 0; - struct p9_req_t *req; - struct p9_client *clnt; - - p9_debug(P9_DEBUG_9P, ">>> TUNLINKAT fid %d %s %d\n", - dfid->fid, name, flags); - - clnt = dfid->clnt; - req = p9_client_rpc(clnt, P9_TUNLINKAT, "dsd", dfid->fid, name, flags); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RUNLINKAT fid %d %s\n", dfid->fid, name); - - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_unlinkat); - -int -p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, - u32 count) -{ - char *dataptr; - int kernel_buf = 0; - struct p9_req_t *req; - struct p9_client *clnt; - int err, rsize, non_zc = 0; - - - p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", - fid->fid, (unsigned long long) offset, count); - err = 0; - clnt = fid->clnt; - - rsize = fid->iounit; - if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) - rsize = clnt->msize - P9_IOHDRSZ; - - if (count < rsize) - rsize = count; - - /* Don't bother zerocopy for small IO (< 1024) */ - if (clnt->trans_mod->zc_request && rsize > 1024) { - char *indata; - if (data) { - kernel_buf = 1; - indata = data; - } else - indata = (__force char *)udata; - /* - * response header len is 11 - * PDU Header(7) + IO Size (4) - */ - req = p9_client_zc_rpc(clnt, P9_TREAD, indata, NULL, rsize, 0, - 11, kernel_buf, "dqd", fid->fid, - offset, rsize); - } else { - non_zc = 1; - req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, - rsize); - } - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto free_and_error; - } - - p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count); - - if (non_zc) { - if (data) { - memmove(data, dataptr, count); - } else { - err = copy_to_user(udata, dataptr, count); - if (err) { - err = -EFAULT; - goto free_and_error; - } - } - } - p9_free_req(clnt, req); - return count; - -free_and_error: - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_read); - -int -p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, - u64 offset, u32 count) -{ - int err, rsize; - int kernel_buf = 0; - struct p9_client *clnt; - struct p9_req_t *req; - - p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n", - fid->fid, (unsigned long long) offset, count); - err = 0; - clnt = fid->clnt; - - rsize = fid->iounit; - if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) - rsize = clnt->msize - P9_IOHDRSZ; - - if (count < rsize) - rsize = count; - - /* Don't bother zerocopy for small IO (< 1024) */ - if (clnt->trans_mod->zc_request && rsize > 1024) { - char *odata; - if (data) { - kernel_buf = 1; - odata = data; - } else - odata = (char *)udata; - req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, odata, 0, rsize, - P9_ZC_HDR_SZ, kernel_buf, "dqd", - fid->fid, offset, rsize); - } else { - if (data) - req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, - offset, rsize, data); - else - req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, - offset, rsize, udata); - } - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto free_and_error; - } - - p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count); - - p9_free_req(clnt, req); - return count; - -free_and_error: - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_write); - -struct p9_wstat *p9_client_stat(struct p9_fid *fid) -{ - int err; - struct p9_client *clnt; - struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL); - struct p9_req_t *req; - u16 ignored; - - p9_debug(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid); - - if (!ret) - return ERR_PTR(-ENOMEM); - - err = 0; - clnt = fid->clnt; - - req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - goto error; - } - - p9_debug(P9_DEBUG_9P, - "<<< RSTAT sz=%x type=%x dev=%x qid=%x.%llx.%x\n" - "<<< mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n" - "<<< name=%s uid=%s gid=%s muid=%s extension=(%s)\n" - "<<< uid=%d gid=%d n_muid=%d\n", - ret->size, ret->type, ret->dev, ret->qid.type, - (unsigned long long)ret->qid.path, ret->qid.version, ret->mode, - ret->atime, ret->mtime, (unsigned long long)ret->length, - ret->name, ret->uid, ret->gid, ret->muid, ret->extension, - from_kuid(&init_user_ns, ret->n_uid), - from_kgid(&init_user_ns, ret->n_gid), - from_kuid(&init_user_ns, ret->n_muid)); - - p9_free_req(clnt, req); - return ret; - -error: - kfree(ret); - return ERR_PTR(err); -} -EXPORT_SYMBOL(p9_client_stat); - -struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, - u64 request_mask) -{ - int err; - struct p9_client *clnt; - struct p9_stat_dotl *ret = kmalloc(sizeof(struct p9_stat_dotl), - GFP_KERNEL); - struct p9_req_t *req; - - p9_debug(P9_DEBUG_9P, ">>> TGETATTR fid %d, request_mask %lld\n", - fid->fid, request_mask); - - if (!ret) - return ERR_PTR(-ENOMEM); - - err = 0; - clnt = fid->clnt; - - req = p9_client_rpc(clnt, P9_TGETATTR, "dq", fid->fid, request_mask); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "A", ret); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - goto error; - } - - p9_debug(P9_DEBUG_9P, - "<<< RGETATTR st_result_mask=%lld\n" - "<<< qid=%x.%llx.%x\n" - "<<< st_mode=%8.8x st_nlink=%llu\n" - "<<< st_uid=%d st_gid=%d\n" - "<<< st_rdev=%llx st_size=%llx st_blksize=%llu st_blocks=%llu\n" - "<<< st_atime_sec=%lld st_atime_nsec=%lld\n" - "<<< st_mtime_sec=%lld st_mtime_nsec=%lld\n" - "<<< st_ctime_sec=%lld st_ctime_nsec=%lld\n" - "<<< st_btime_sec=%lld st_btime_nsec=%lld\n" - "<<< st_gen=%lld st_data_version=%lld", - ret->st_result_mask, ret->qid.type, ret->qid.path, - ret->qid.version, ret->st_mode, ret->st_nlink, - from_kuid(&init_user_ns, ret->st_uid), - from_kgid(&init_user_ns, ret->st_gid), - ret->st_rdev, ret->st_size, ret->st_blksize, - ret->st_blocks, ret->st_atime_sec, ret->st_atime_nsec, - ret->st_mtime_sec, ret->st_mtime_nsec, ret->st_ctime_sec, - ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec, - ret->st_gen, ret->st_data_version); - - p9_free_req(clnt, req); - return ret; - -error: - kfree(ret); - return ERR_PTR(err); -} -EXPORT_SYMBOL(p9_client_getattr_dotl); - -static int p9_client_statsize(struct p9_wstat *wst, int proto_version) -{ - int ret; - - /* NOTE: size shouldn't include its own length */ - /* size[2] type[2] dev[4] qid[13] */ - /* mode[4] atime[4] mtime[4] length[8]*/ - /* name[s] uid[s] gid[s] muid[s] */ - ret = 2+4+13+4+4+4+8+2+2+2+2; - - if (wst->name) - ret += strlen(wst->name); - if (wst->uid) - ret += strlen(wst->uid); - if (wst->gid) - ret += strlen(wst->gid); - if (wst->muid) - ret += strlen(wst->muid); - - if ((proto_version == p9_proto_2000u) || - (proto_version == p9_proto_2000L)) { - ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ - if (wst->extension) - ret += strlen(wst->extension); - } - - return ret; -} - -int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - - err = 0; - clnt = fid->clnt; - wst->size = p9_client_statsize(wst, clnt->proto_version); - p9_debug(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); - p9_debug(P9_DEBUG_9P, - " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" - " mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n" - " name=%s uid=%s gid=%s muid=%s extension=(%s)\n" - " uid=%d gid=%d n_muid=%d\n", - wst->size, wst->type, wst->dev, wst->qid.type, - (unsigned long long)wst->qid.path, wst->qid.version, wst->mode, - wst->atime, wst->mtime, (unsigned long long)wst->length, - wst->name, wst->uid, wst->gid, wst->muid, wst->extension, - from_kuid(&init_user_ns, wst->n_uid), - from_kgid(&init_user_ns, wst->n_gid), - from_kuid(&init_user_ns, wst->n_muid)); - - req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid); - - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_wstat); - -int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - - err = 0; - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> TSETATTR fid %d\n", fid->fid); - p9_debug(P9_DEBUG_9P, - " valid=%x mode=%x uid=%d gid=%d size=%lld\n" - " atime_sec=%lld atime_nsec=%lld\n" - " mtime_sec=%lld mtime_nsec=%lld\n", - p9attr->valid, p9attr->mode, - from_kuid(&init_user_ns, p9attr->uid), - from_kgid(&init_user_ns, p9attr->gid), - p9attr->size, p9attr->atime_sec, p9attr->atime_nsec, - p9attr->mtime_sec, p9attr->mtime_nsec); - - req = p9_client_rpc(clnt, P9_TSETATTR, "dI", fid->fid, p9attr); - - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RSETATTR fid %d\n", fid->fid); - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_setattr); - -int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - - err = 0; - clnt = fid->clnt; - - p9_debug(P9_DEBUG_9P, ">>> TSTATFS fid %d\n", fid->fid); - - req = p9_client_rpc(clnt, P9_TSTATFS, "d", fid->fid); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "ddqqqqqqd", &sb->type, - &sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail, - &sb->files, &sb->ffree, &sb->fsid, &sb->namelen); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RSTATFS fid %d type 0x%lx bsize %ld " - "blocks %llu bfree %llu bavail %llu files %llu ffree %llu " - "fsid %llu namelen %ld\n", - fid->fid, (long unsigned int)sb->type, (long int)sb->bsize, - sb->blocks, sb->bfree, sb->bavail, sb->files, sb->ffree, - sb->fsid, (long int)sb->namelen); - - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_statfs); - -int p9_client_rename(struct p9_fid *fid, - struct p9_fid *newdirfid, const char *name) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - - err = 0; - clnt = fid->clnt; - - p9_debug(P9_DEBUG_9P, ">>> TRENAME fid %d newdirfid %d name %s\n", - fid->fid, newdirfid->fid, name); - - req = p9_client_rpc(clnt, P9_TRENAME, "dds", fid->fid, - newdirfid->fid, name); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RRENAME fid %d\n", fid->fid); - - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_rename); - -int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name, - struct p9_fid *newdirfid, const char *new_name) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - - err = 0; - clnt = olddirfid->clnt; - - p9_debug(P9_DEBUG_9P, ">>> TRENAMEAT olddirfid %d old name %s" - " newdirfid %d new name %s\n", olddirfid->fid, old_name, - newdirfid->fid, new_name); - - req = p9_client_rpc(clnt, P9_TRENAMEAT, "dsds", olddirfid->fid, - old_name, newdirfid->fid, new_name); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RRENAMEAT newdirfid %d new name %s\n", - newdirfid->fid, new_name); - - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_renameat); - -/* - * An xattrwalk without @attr_name gives the fid for the lisxattr namespace - */ -struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid, - const char *attr_name, u64 *attr_size) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - struct p9_fid *attr_fid; - - err = 0; - clnt = file_fid->clnt; - attr_fid = p9_fid_create(clnt); - if (IS_ERR(attr_fid)) { - err = PTR_ERR(attr_fid); - attr_fid = NULL; - goto error; - } - p9_debug(P9_DEBUG_9P, - ">>> TXATTRWALK file_fid %d, attr_fid %d name %s\n", - file_fid->fid, attr_fid->fid, attr_name); - - req = p9_client_rpc(clnt, P9_TXATTRWALK, "dds", - file_fid->fid, attr_fid->fid, attr_name); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - err = p9pdu_readf(req->rc, clnt->proto_version, "q", attr_size); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - goto clunk_fid; - } - p9_free_req(clnt, req); - p9_debug(P9_DEBUG_9P, "<<< RXATTRWALK fid %d size %llu\n", - attr_fid->fid, *attr_size); - return attr_fid; -clunk_fid: - p9_client_clunk(attr_fid); - attr_fid = NULL; -error: - if (attr_fid && (attr_fid != file_fid)) - p9_fid_destroy(attr_fid); - - return ERR_PTR(err); -} -EXPORT_SYMBOL_GPL(p9_client_xattrwalk); - -int p9_client_xattrcreate(struct p9_fid *fid, const char *name, - u64 attr_size, int flags) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - - p9_debug(P9_DEBUG_9P, - ">>> TXATTRCREATE fid %d name %s size %lld flag %d\n", - fid->fid, name, (long long)attr_size, flags); - err = 0; - clnt = fid->clnt; - req = p9_client_rpc(clnt, P9_TXATTRCREATE, "dsqd", - fid->fid, name, attr_size, flags); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RXATTRCREATE fid %d\n", fid->fid); - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL_GPL(p9_client_xattrcreate); - -int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) -{ - int err, rsize, non_zc = 0; - struct p9_client *clnt; - struct p9_req_t *req; - char *dataptr; - - p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n", - fid->fid, (unsigned long long) offset, count); - - err = 0; - clnt = fid->clnt; - - rsize = fid->iounit; - if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ) - rsize = clnt->msize - P9_READDIRHDRSZ; - - if (count < rsize) - rsize = count; - - /* Don't bother zerocopy for small IO (< 1024) */ - if (clnt->trans_mod->zc_request && rsize > 1024) { - /* - * response header len is 11 - * PDU Header(7) + IO Size (4) - */ - req = p9_client_zc_rpc(clnt, P9_TREADDIR, data, NULL, rsize, 0, - 11, 1, "dqd", fid->fid, offset, rsize); - } else { - non_zc = 1; - req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, - offset, rsize); - } - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto free_and_error; - } - if (rsize < count) { - pr_err("bogus RREADDIR count (%d > %d)\n", count, rsize); - count = rsize; - } - - p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count); - - if (non_zc) - memmove(data, dataptr, count); - - p9_free_req(clnt, req); - return count; - -free_and_error: - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_readdir); - -int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode, - dev_t rdev, kgid_t gid, struct p9_qid *qid) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - err = 0; - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> TMKNOD fid %d name %s mode %d major %d " - "minor %d\n", fid->fid, name, mode, MAJOR(rdev), MINOR(rdev)); - req = p9_client_rpc(clnt, P9_TMKNOD, "dsdddg", fid->fid, name, mode, - MAJOR(rdev), MINOR(rdev), gid); - if (IS_ERR(req)) - return PTR_ERR(req); - - err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type, - (unsigned long long)qid->path, qid->version); - -error: - p9_free_req(clnt, req); - return err; - -} -EXPORT_SYMBOL(p9_client_mknod_dotl); - -int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode, - kgid_t gid, struct p9_qid *qid) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - err = 0; - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> TMKDIR fid %d name %s mode %d gid %d\n", - fid->fid, name, mode, from_kgid(&init_user_ns, gid)); - req = p9_client_rpc(clnt, P9_TMKDIR, "dsdg", fid->fid, name, mode, - gid); - if (IS_ERR(req)) - return PTR_ERR(req); - - err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type, - (unsigned long long)qid->path, qid->version); - -error: - p9_free_req(clnt, req); - return err; - -} -EXPORT_SYMBOL(p9_client_mkdir_dotl); - -int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - err = 0; - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> TLOCK fid %d type %i flags %d " - "start %lld length %lld proc_id %d client_id %s\n", - fid->fid, flock->type, flock->flags, flock->start, - flock->length, flock->proc_id, flock->client_id); - - req = p9_client_rpc(clnt, P9_TLOCK, "dbdqqds", fid->fid, flock->type, - flock->flags, flock->start, flock->length, - flock->proc_id, flock->client_id); - - if (IS_ERR(req)) - return PTR_ERR(req); - - err = p9pdu_readf(req->rc, clnt->proto_version, "b", status); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status); -error: - p9_free_req(clnt, req); - return err; - -} -EXPORT_SYMBOL(p9_client_lock_dotl); - -int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - err = 0; - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> TGETLOCK fid %d, type %i start %lld " - "length %lld proc_id %d client_id %s\n", fid->fid, glock->type, - glock->start, glock->length, glock->proc_id, glock->client_id); - - req = p9_client_rpc(clnt, P9_TGETLOCK, "dbqqds", fid->fid, glock->type, - glock->start, glock->length, glock->proc_id, glock->client_id); - - if (IS_ERR(req)) - return PTR_ERR(req); - - err = p9pdu_readf(req->rc, clnt->proto_version, "bqqds", &glock->type, - &glock->start, &glock->length, &glock->proc_id, - &glock->client_id); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld " - "proc_id %d client_id %s\n", glock->type, glock->start, - glock->length, glock->proc_id, glock->client_id); -error: - p9_free_req(clnt, req); - return err; -} -EXPORT_SYMBOL(p9_client_getlock_dotl); - -int p9_client_readlink(struct p9_fid *fid, char **target) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - err = 0; - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid); - - req = p9_client_rpc(clnt, P9_TREADLINK, "d", fid->fid); - if (IS_ERR(req)) - return PTR_ERR(req); - - err = p9pdu_readf(req->rc, clnt->proto_version, "s", target); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target); -error: - p9_free_req(clnt, req); - return err; -} -EXPORT_SYMBOL(p9_client_readlink); diff --git a/addons/9p/src/3.10.108/error.c b/addons/9p/src/3.10.108/error.c deleted file mode 100644 index 126fd0dc..00000000 --- a/addons/9p/src/3.10.108/error.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * linux/fs/9p/error.c - * - * Error string handling - * - * Plan 9 uses error strings, Unix uses error numbers. These functions - * try to help manage that and provide for dynamically adding error - * mappings. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include - -/** - * struct errormap - map string errors from Plan 9 to Linux numeric ids - * @name: string sent over 9P - * @val: numeric id most closely representing @name - * @namelen: length of string - * @list: hash-table list for string lookup - */ -struct errormap { - char *name; - int val; - - int namelen; - struct hlist_node list; -}; - -#define ERRHASHSZ 32 -static struct hlist_head hash_errmap[ERRHASHSZ]; - -/* FixMe - reduce to a reasonable size */ -static struct errormap errmap[] = { - {"Operation not permitted", EPERM}, - {"wstat prohibited", EPERM}, - {"No such file or directory", ENOENT}, - {"directory entry not found", ENOENT}, - {"file not found", ENOENT}, - {"Interrupted system call", EINTR}, - {"Input/output error", EIO}, - {"No such device or address", ENXIO}, - {"Argument list too long", E2BIG}, - {"Bad file descriptor", EBADF}, - {"Resource temporarily unavailable", EAGAIN}, - {"Cannot allocate memory", ENOMEM}, - {"Permission denied", EACCES}, - {"Bad address", EFAULT}, - {"Block device required", ENOTBLK}, - {"Device or resource busy", EBUSY}, - {"File exists", EEXIST}, - {"Invalid cross-device link", EXDEV}, - {"No such device", ENODEV}, - {"Not a directory", ENOTDIR}, - {"Is a directory", EISDIR}, - {"Invalid argument", EINVAL}, - {"Too many open files in system", ENFILE}, - {"Too many open files", EMFILE}, - {"Text file busy", ETXTBSY}, - {"File too large", EFBIG}, - {"No space left on device", ENOSPC}, - {"Illegal seek", ESPIPE}, - {"Read-only file system", EROFS}, - {"Too many links", EMLINK}, - {"Broken pipe", EPIPE}, - {"Numerical argument out of domain", EDOM}, - {"Numerical result out of range", ERANGE}, - {"Resource deadlock avoided", EDEADLK}, - {"File name too long", ENAMETOOLONG}, - {"No locks available", ENOLCK}, - {"Function not implemented", ENOSYS}, - {"Directory not empty", ENOTEMPTY}, - {"Too many levels of symbolic links", ELOOP}, - {"No message of desired type", ENOMSG}, - {"Identifier removed", EIDRM}, - {"No data available", ENODATA}, - {"Machine is not on the network", ENONET}, - {"Package not installed", ENOPKG}, - {"Object is remote", EREMOTE}, - {"Link has been severed", ENOLINK}, - {"Communication error on send", ECOMM}, - {"Protocol error", EPROTO}, - {"Bad message", EBADMSG}, - {"File descriptor in bad state", EBADFD}, - {"Streams pipe error", ESTRPIPE}, - {"Too many users", EUSERS}, - {"Socket operation on non-socket", ENOTSOCK}, - {"Message too long", EMSGSIZE}, - {"Protocol not available", ENOPROTOOPT}, - {"Protocol not supported", EPROTONOSUPPORT}, - {"Socket type not supported", ESOCKTNOSUPPORT}, - {"Operation not supported", EOPNOTSUPP}, - {"Protocol family not supported", EPFNOSUPPORT}, - {"Network is down", ENETDOWN}, - {"Network is unreachable", ENETUNREACH}, - {"Network dropped connection on reset", ENETRESET}, - {"Software caused connection abort", ECONNABORTED}, - {"Connection reset by peer", ECONNRESET}, - {"No buffer space available", ENOBUFS}, - {"Transport endpoint is already connected", EISCONN}, - {"Transport endpoint is not connected", ENOTCONN}, - {"Cannot send after transport endpoint shutdown", ESHUTDOWN}, - {"Connection timed out", ETIMEDOUT}, - {"Connection refused", ECONNREFUSED}, - {"Host is down", EHOSTDOWN}, - {"No route to host", EHOSTUNREACH}, - {"Operation already in progress", EALREADY}, - {"Operation now in progress", EINPROGRESS}, - {"Is a named type file", EISNAM}, - {"Remote I/O error", EREMOTEIO}, - {"Disk quota exceeded", EDQUOT}, -/* errors from fossil, vacfs, and u9fs */ - {"fid unknown or out of range", EBADF}, - {"permission denied", EACCES}, - {"file does not exist", ENOENT}, - {"authentication failed", ECONNREFUSED}, - {"bad offset in directory read", ESPIPE}, - {"bad use of fid", EBADF}, - {"wstat can't convert between files and directories", EPERM}, - {"directory is not empty", ENOTEMPTY}, - {"file exists", EEXIST}, - {"file already exists", EEXIST}, - {"file or directory already exists", EEXIST}, - {"fid already in use", EBADF}, - {"file in use", ETXTBSY}, - {"i/o error", EIO}, - {"file already open for I/O", ETXTBSY}, - {"illegal mode", EINVAL}, - {"illegal name", ENAMETOOLONG}, - {"not a directory", ENOTDIR}, - {"not a member of proposed group", EPERM}, - {"not owner", EACCES}, - {"only owner can change group in wstat", EACCES}, - {"read only file system", EROFS}, - {"no access to special file", EPERM}, - {"i/o count too large", EIO}, - {"unknown group", EINVAL}, - {"unknown user", EINVAL}, - {"bogus wstat buffer", EPROTO}, - {"exclusive use file already open", EAGAIN}, - {"corrupted directory entry", EIO}, - {"corrupted file entry", EIO}, - {"corrupted block label", EIO}, - {"corrupted meta data", EIO}, - {"illegal offset", EINVAL}, - {"illegal path element", ENOENT}, - {"root of file system is corrupted", EIO}, - {"corrupted super block", EIO}, - {"protocol botch", EPROTO}, - {"file system is full", ENOSPC}, - {"file is in use", EAGAIN}, - {"directory entry is not allocated", ENOENT}, - {"file is read only", EROFS}, - {"file has been removed", EIDRM}, - {"only support truncation to zero length", EPERM}, - {"cannot remove root", EPERM}, - {"file too big", EFBIG}, - {"venti i/o error", EIO}, - /* these are not errors */ - {"u9fs rhostsauth: no authentication required", 0}, - {"u9fs authnone: no authentication required", 0}, - {NULL, -1} -}; - -/** - * p9_error_init - preload mappings into hash list - * - */ - -int p9_error_init(void) -{ - struct errormap *c; - int bucket; - - /* initialize hash table */ - for (bucket = 0; bucket < ERRHASHSZ; bucket++) - INIT_HLIST_HEAD(&hash_errmap[bucket]); - - /* load initial error map into hash table */ - for (c = errmap; c->name != NULL; c++) { - c->namelen = strlen(c->name); - bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ; - INIT_HLIST_NODE(&c->list); - hlist_add_head(&c->list, &hash_errmap[bucket]); - } - - return 1; -} -EXPORT_SYMBOL(p9_error_init); - -/** - * errstr2errno - convert error string to error number - * @errstr: error string - * @len: length of error string - * - */ - -int p9_errstr2errno(char *errstr, int len) -{ - int errno; - struct errormap *c; - int bucket; - - errno = 0; - c = NULL; - bucket = jhash(errstr, len, 0) % ERRHASHSZ; - hlist_for_each_entry(c, &hash_errmap[bucket], list) { - if (c->namelen == len && !memcmp(c->name, errstr, len)) { - errno = c->val; - break; - } - } - - if (errno == 0) { - /* TODO: if error isn't found, add it dynamically */ - errstr[len] = 0; - pr_err("%s: server reported unknown error %s\n", - __func__, errstr); - errno = ESERVERFAULT; - } - - return -errno; -} -EXPORT_SYMBOL(p9_errstr2errno); diff --git a/addons/9p/src/3.10.108/fid.c b/addons/9p/src/3.10.108/fid.c deleted file mode 100644 index d51ec9fa..00000000 --- a/addons/9p/src/3.10.108/fid.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * V9FS FID Management - * - * Copyright (C) 2007 by Latchesar Ionkov - * Copyright (C) 2005, 2006 by Eric Van Hensbergen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" - -/** - * v9fs_fid_add - add a fid to a dentry - * @dentry: dentry that the fid is being added to - * @fid: fid to add - * - */ - -static inline void __add_fid(struct dentry *dentry, struct p9_fid *fid) -{ - hlist_add_head(&fid->dlist, (struct hlist_head *)&dentry->d_fsdata); -} - -void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid) -{ - spin_lock(&dentry->d_lock); - __add_fid(dentry, fid); - spin_unlock(&dentry->d_lock); -} - -/** - * v9fs_fid_find - retrieve a fid that belongs to the specified uid - * @dentry: dentry to look for fid in - * @uid: return fid that belongs to the specified user - * @any: if non-zero, return any fid associated with the dentry - * - */ - -static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any) -{ - struct p9_fid *fid, *ret; - - p9_debug(P9_DEBUG_VFS, " dentry: %s (%p) uid %d any %d\n", - dentry->d_name.name, dentry, from_kuid(&init_user_ns, uid), - any); - ret = NULL; - /* we'll recheck under lock if there's anything to look in */ - if (dentry->d_fsdata) { - struct hlist_head *h = (struct hlist_head *)&dentry->d_fsdata; - spin_lock(&dentry->d_lock); - hlist_for_each_entry(fid, h, dlist) { - if (any || uid_eq(fid->uid, uid)) { - ret = fid; - break; - } - } - spin_unlock(&dentry->d_lock); - } - - return ret; -} - -/* - * We need to hold v9ses->rename_sem as long as we hold references - * to returned path array. Array element contain pointers to - * dentry names. - */ -static int build_path_from_dentry(struct v9fs_session_info *v9ses, - struct dentry *dentry, char ***names) -{ - int n = 0, i; - char **wnames; - struct dentry *ds; - - for (ds = dentry; !IS_ROOT(ds); ds = ds->d_parent) - n++; - - wnames = kmalloc(sizeof(char *) * n, GFP_KERNEL); - if (!wnames) - goto err_out; - - for (ds = dentry, i = (n-1); i >= 0; i--, ds = ds->d_parent) - wnames[i] = (char *)ds->d_name.name; - - *names = wnames; - return n; -err_out: - return -ENOMEM; -} - -static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry, - kuid_t uid, int any) -{ - struct dentry *ds; - char **wnames, *uname; - int i, n, l, clone, access; - struct v9fs_session_info *v9ses; - struct p9_fid *fid, *old_fid = NULL; - - v9ses = v9fs_dentry2v9ses(dentry); - access = v9ses->flags & V9FS_ACCESS_MASK; - fid = v9fs_fid_find(dentry, uid, any); - if (fid) - return fid; - /* - * we don't have a matching fid. To do a TWALK we need - * parent fid. We need to prevent rename when we want to - * look at the parent. - */ - down_read(&v9ses->rename_sem); - ds = dentry->d_parent; - fid = v9fs_fid_find(ds, uid, any); - if (fid) { - /* Found the parent fid do a lookup with that */ - fid = p9_client_walk(fid, 1, (char **)&dentry->d_name.name, 1); - goto fid_out; - } - up_read(&v9ses->rename_sem); - - /* start from the root and try to do a lookup */ - fid = v9fs_fid_find(dentry->d_sb->s_root, uid, any); - if (!fid) { - /* the user is not attached to the fs yet */ - if (access == V9FS_ACCESS_SINGLE) - return ERR_PTR(-EPERM); - - if (v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) - uname = NULL; - else - uname = v9ses->uname; - - fid = p9_client_attach(v9ses->clnt, NULL, uname, uid, - v9ses->aname); - if (IS_ERR(fid)) - return fid; - - v9fs_fid_add(dentry->d_sb->s_root, fid); - } - /* If we are root ourself just return that */ - if (dentry->d_sb->s_root == dentry) - return fid; - /* - * Do a multipath walk with attached root. - * When walking parent we need to make sure we - * don't have a parallel rename happening - */ - down_read(&v9ses->rename_sem); - n = build_path_from_dentry(v9ses, dentry, &wnames); - if (n < 0) { - fid = ERR_PTR(n); - goto err_out; - } - clone = 1; - i = 0; - while (i < n) { - l = min(n - i, P9_MAXWELEM); - /* - * We need to hold rename lock when doing a multipath - * walk to ensure none of the patch component change - */ - fid = p9_client_walk(fid, l, &wnames[i], clone); - if (IS_ERR(fid)) { - if (old_fid) { - /* - * If we fail, clunk fid which are mapping - * to path component and not the last component - * of the path. - */ - p9_client_clunk(old_fid); - } - kfree(wnames); - goto err_out; - } - old_fid = fid; - i += l; - clone = 0; - } - kfree(wnames); -fid_out: - if (!IS_ERR(fid)) { - spin_lock(&dentry->d_lock); - if (d_unhashed(dentry)) { - spin_unlock(&dentry->d_lock); - p9_client_clunk(fid); - fid = ERR_PTR(-ENOENT); - } else { - __add_fid(dentry, fid); - spin_unlock(&dentry->d_lock); - } - } -err_out: - up_read(&v9ses->rename_sem); - return fid; -} - -/** - * v9fs_fid_lookup - lookup for a fid, try to walk if not found - * @dentry: dentry to look for fid in - * - * Look for a fid in the specified dentry for the current user. - * If no fid is found, try to create one walking from a fid from the parent - * dentry (if it has one), or the root dentry. If the user haven't accessed - * the fs yet, attach now and walk from the root. - */ - -struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) -{ - kuid_t uid; - int any, access; - struct v9fs_session_info *v9ses; - - v9ses = v9fs_dentry2v9ses(dentry); - access = v9ses->flags & V9FS_ACCESS_MASK; - switch (access) { - case V9FS_ACCESS_SINGLE: - case V9FS_ACCESS_USER: - case V9FS_ACCESS_CLIENT: - uid = current_fsuid(); - any = 0; - break; - - case V9FS_ACCESS_ANY: - uid = v9ses->uid; - any = 1; - break; - - default: - uid = INVALID_UID; - any = 0; - break; - } - return v9fs_fid_lookup_with_uid(dentry, uid, any); -} - -struct p9_fid *v9fs_fid_clone(struct dentry *dentry) -{ - struct p9_fid *fid, *ret; - - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return fid; - - ret = p9_client_walk(fid, 0, NULL, 1); - return ret; -} - -static struct p9_fid *v9fs_fid_clone_with_uid(struct dentry *dentry, kuid_t uid) -{ - struct p9_fid *fid, *ret; - - fid = v9fs_fid_lookup_with_uid(dentry, uid, 0); - if (IS_ERR(fid)) - return fid; - - ret = p9_client_walk(fid, 0, NULL, 1); - return ret; -} - -struct p9_fid *v9fs_writeback_fid(struct dentry *dentry) -{ - int err; - struct p9_fid *fid; - - fid = v9fs_fid_clone_with_uid(dentry, GLOBAL_ROOT_UID); - if (IS_ERR(fid)) - goto error_out; - /* - * writeback fid will only be used to write back the - * dirty pages. We always request for the open fid in read-write - * mode so that a partial page write which result in page - * read can work. - */ - err = p9_client_open(fid, O_RDWR); - if (err < 0) { - p9_client_clunk(fid); - fid = ERR_PTR(err); - goto error_out; - } -error_out: - return fid; -} diff --git a/addons/9p/src/3.10.108/fid.h b/addons/9p/src/3.10.108/fid.h deleted file mode 100644 index 2b6787fc..00000000 --- a/addons/9p/src/3.10.108/fid.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * V9FS FID Management - * - * Copyright (C) 2005 by Eric Van Hensbergen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ -#ifndef FS_9P_FID_H -#define FS_9P_FID_H -#include - -struct p9_fid *v9fs_fid_lookup(struct dentry *dentry); -struct p9_fid *v9fs_fid_clone(struct dentry *dentry); -void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid); -struct p9_fid *v9fs_writeback_fid(struct dentry *dentry); -#endif diff --git a/addons/9p/src/3.10.108/mod.c b/addons/9p/src/3.10.108/mod.c deleted file mode 100644 index 6ab36aea..00000000 --- a/addons/9p/src/3.10.108/mod.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * net/9p/9p.c - * - * 9P entry point - * - * Copyright (C) 2007 by Latchesar Ionkov - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_NET_9P_DEBUG -unsigned int p9_debug_level = 0; /* feature-rific global debug level */ -EXPORT_SYMBOL(p9_debug_level); -module_param_named(debug, p9_debug_level, uint, 0); -MODULE_PARM_DESC(debug, "9P debugging level"); - -void _p9_debug(enum p9_debug_flags level, const char *func, - const char *fmt, ...) -{ - struct va_format vaf; - va_list args; - - if ((p9_debug_level & level) != level) - return; - - va_start(args, fmt); - - vaf.fmt = fmt; - vaf.va = &args; - - if (level == P9_DEBUG_9P) - pr_notice("(%8.8d) %pV", task_pid_nr(current), &vaf); - else - pr_notice("-- %s (%d): %pV", func, task_pid_nr(current), &vaf); - - va_end(args); -} -EXPORT_SYMBOL(_p9_debug); -#endif - -/* - * Dynamic Transport Registration Routines - * - */ - -static DEFINE_SPINLOCK(v9fs_trans_lock); -static LIST_HEAD(v9fs_trans_list); - -/** - * v9fs_register_trans - register a new transport with 9p - * @m: structure describing the transport module and entry points - * - */ -void v9fs_register_trans(struct p9_trans_module *m) -{ - spin_lock(&v9fs_trans_lock); - list_add_tail(&m->list, &v9fs_trans_list); - spin_unlock(&v9fs_trans_lock); -} -EXPORT_SYMBOL(v9fs_register_trans); - -/** - * v9fs_unregister_trans - unregister a 9p transport - * @m: the transport to remove - * - */ -void v9fs_unregister_trans(struct p9_trans_module *m) -{ - spin_lock(&v9fs_trans_lock); - list_del_init(&m->list); - spin_unlock(&v9fs_trans_lock); -} -EXPORT_SYMBOL(v9fs_unregister_trans); - -/** - * v9fs_get_trans_by_name - get transport with the matching name - * @name: string identifying transport - * - */ -struct p9_trans_module *v9fs_get_trans_by_name(char *s) -{ - struct p9_trans_module *t, *found = NULL; - - spin_lock(&v9fs_trans_lock); - - list_for_each_entry(t, &v9fs_trans_list, list) - if (strcmp(t->name, s) == 0 && - try_module_get(t->owner)) { - found = t; - break; - } - - spin_unlock(&v9fs_trans_lock); - return found; -} -EXPORT_SYMBOL(v9fs_get_trans_by_name); - -/** - * v9fs_get_default_trans - get the default transport - * - */ - -struct p9_trans_module *v9fs_get_default_trans(void) -{ - struct p9_trans_module *t, *found = NULL; - - spin_lock(&v9fs_trans_lock); - - list_for_each_entry(t, &v9fs_trans_list, list) - if (t->def && try_module_get(t->owner)) { - found = t; - break; - } - - if (!found) - list_for_each_entry(t, &v9fs_trans_list, list) - if (try_module_get(t->owner)) { - found = t; - break; - } - - spin_unlock(&v9fs_trans_lock); - return found; -} -EXPORT_SYMBOL(v9fs_get_default_trans); - -/** - * v9fs_put_trans - put trans - * @m: transport to put - * - */ -void v9fs_put_trans(struct p9_trans_module *m) -{ - if (m) - module_put(m->owner); -} - -/** - * init_p9 - Initialize module - * - */ -static int __init init_p9(void) -{ - int ret = 0; - - p9_error_init(); - pr_info("Installing 9P2000 support\n"); - p9_trans_fd_init(); - - return ret; -} - -/** - * exit_p9 - shutdown module - * - */ - -static void __exit exit_p9(void) -{ - pr_info("Unloading 9P2000 support\n"); - - p9_trans_fd_exit(); -} - -module_init(init_p9) -module_exit(exit_p9) - -MODULE_AUTHOR("Latchesar Ionkov "); -MODULE_AUTHOR("Eric Van Hensbergen "); -MODULE_AUTHOR("Ron Minnich "); -MODULE_LICENSE("GPL"); diff --git a/addons/9p/src/3.10.108/protocol.c b/addons/9p/src/3.10.108/protocol.c deleted file mode 100644 index ab9127ec..00000000 --- a/addons/9p/src/3.10.108/protocol.c +++ /dev/null @@ -1,636 +0,0 @@ -/* - * net/9p/protocol.c - * - * 9P Protocol Support Code - * - * Copyright (C) 2008 by Eric Van Hensbergen - * - * Base on code from Anthony Liguori - * Copyright (C) 2008 by IBM, Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "protocol.h" - -#include - -static int -p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); - -void p9stat_free(struct p9_wstat *stbuf) -{ - kfree(stbuf->name); - kfree(stbuf->uid); - kfree(stbuf->gid); - kfree(stbuf->muid); - kfree(stbuf->extension); -} -EXPORT_SYMBOL(p9stat_free); - -size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size) -{ - size_t len = min(pdu->size - pdu->offset, size); - memcpy(data, &pdu->sdata[pdu->offset], len); - pdu->offset += len; - return size - len; -} - -static size_t pdu_write(struct p9_fcall *pdu, const void *data, size_t size) -{ - size_t len = min(pdu->capacity - pdu->size, size); - memcpy(&pdu->sdata[pdu->size], data, len); - pdu->size += len; - return size - len; -} - -static size_t -pdu_write_u(struct p9_fcall *pdu, const char __user *udata, size_t size) -{ - size_t len = min(pdu->capacity - pdu->size, size); - if (copy_from_user(&pdu->sdata[pdu->size], udata, len)) - len = 0; - - pdu->size += len; - return size - len; -} - -/* - b - int8_t - w - int16_t - d - int32_t - q - int64_t - s - string - u - numeric uid - g - numeric gid - S - stat - Q - qid - D - data blob (int32_t size followed by void *, results are not freed) - T - array of strings (int16_t count, followed by strings) - R - array of qids (int16_t count, followed by qids) - A - stat for 9p2000.L (p9_stat_dotl) - ? - if optional = 1, continue parsing -*/ - -static int -p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, - va_list ap) -{ - const char *ptr; - int errcode = 0; - - for (ptr = fmt; *ptr; ptr++) { - switch (*ptr) { - case 'b':{ - int8_t *val = va_arg(ap, int8_t *); - if (pdu_read(pdu, val, sizeof(*val))) { - errcode = -EFAULT; - break; - } - } - break; - case 'w':{ - int16_t *val = va_arg(ap, int16_t *); - __le16 le_val; - if (pdu_read(pdu, &le_val, sizeof(le_val))) { - errcode = -EFAULT; - break; - } - *val = le16_to_cpu(le_val); - } - break; - case 'd':{ - int32_t *val = va_arg(ap, int32_t *); - __le32 le_val; - if (pdu_read(pdu, &le_val, sizeof(le_val))) { - errcode = -EFAULT; - break; - } - *val = le32_to_cpu(le_val); - } - break; - case 'q':{ - int64_t *val = va_arg(ap, int64_t *); - __le64 le_val; - if (pdu_read(pdu, &le_val, sizeof(le_val))) { - errcode = -EFAULT; - break; - } - *val = le64_to_cpu(le_val); - } - break; - case 's':{ - char **sptr = va_arg(ap, char **); - uint16_t len; - - errcode = p9pdu_readf(pdu, proto_version, - "w", &len); - if (errcode) - break; - - *sptr = kmalloc(len + 1, GFP_NOFS); - if (*sptr == NULL) { - errcode = -EFAULT; - break; - } - if (pdu_read(pdu, *sptr, len)) { - errcode = -EFAULT; - kfree(*sptr); - *sptr = NULL; - } else - (*sptr)[len] = 0; - } - break; - case 'u': { - kuid_t *uid = va_arg(ap, kuid_t *); - __le32 le_val; - if (pdu_read(pdu, &le_val, sizeof(le_val))) { - errcode = -EFAULT; - break; - } - *uid = make_kuid(&init_user_ns, - le32_to_cpu(le_val)); - } break; - case 'g': { - kgid_t *gid = va_arg(ap, kgid_t *); - __le32 le_val; - if (pdu_read(pdu, &le_val, sizeof(le_val))) { - errcode = -EFAULT; - break; - } - *gid = make_kgid(&init_user_ns, - le32_to_cpu(le_val)); - } break; - case 'Q':{ - struct p9_qid *qid = - va_arg(ap, struct p9_qid *); - - errcode = p9pdu_readf(pdu, proto_version, "bdq", - &qid->type, &qid->version, - &qid->path); - } - break; - case 'S':{ - struct p9_wstat *stbuf = - va_arg(ap, struct p9_wstat *); - - memset(stbuf, 0, sizeof(struct p9_wstat)); - stbuf->n_uid = stbuf->n_muid = INVALID_UID; - stbuf->n_gid = INVALID_GID; - - errcode = - p9pdu_readf(pdu, proto_version, - "wwdQdddqssss?sugu", - &stbuf->size, &stbuf->type, - &stbuf->dev, &stbuf->qid, - &stbuf->mode, &stbuf->atime, - &stbuf->mtime, &stbuf->length, - &stbuf->name, &stbuf->uid, - &stbuf->gid, &stbuf->muid, - &stbuf->extension, - &stbuf->n_uid, &stbuf->n_gid, - &stbuf->n_muid); - if (errcode) - p9stat_free(stbuf); - } - break; - case 'D':{ - uint32_t *count = va_arg(ap, uint32_t *); - void **data = va_arg(ap, void **); - - errcode = - p9pdu_readf(pdu, proto_version, "d", count); - if (!errcode) { - *count = - min_t(uint32_t, *count, - pdu->size - pdu->offset); - *data = &pdu->sdata[pdu->offset]; - } - } - break; - case 'T':{ - uint16_t *nwname = va_arg(ap, uint16_t *); - char ***wnames = va_arg(ap, char ***); - - errcode = p9pdu_readf(pdu, proto_version, - "w", nwname); - if (!errcode) { - *wnames = - kmalloc(sizeof(char *) * *nwname, - GFP_NOFS); - if (!*wnames) - errcode = -ENOMEM; - } - - if (!errcode) { - int i; - - for (i = 0; i < *nwname; i++) { - errcode = - p9pdu_readf(pdu, - proto_version, - "s", - &(*wnames)[i]); - if (errcode) - break; - } - } - - if (errcode) { - if (*wnames) { - int i; - - for (i = 0; i < *nwname; i++) - kfree((*wnames)[i]); - } - kfree(*wnames); - *wnames = NULL; - } - } - break; - case 'R':{ - int16_t *nwqid = va_arg(ap, int16_t *); - struct p9_qid **wqids = - va_arg(ap, struct p9_qid **); - - *wqids = NULL; - - errcode = - p9pdu_readf(pdu, proto_version, "w", nwqid); - if (!errcode) { - *wqids = - kmalloc(*nwqid * - sizeof(struct p9_qid), - GFP_NOFS); - if (*wqids == NULL) - errcode = -ENOMEM; - } - - if (!errcode) { - int i; - - for (i = 0; i < *nwqid; i++) { - errcode = - p9pdu_readf(pdu, - proto_version, - "Q", - &(*wqids)[i]); - if (errcode) - break; - } - } - - if (errcode) { - kfree(*wqids); - *wqids = NULL; - } - } - break; - case 'A': { - struct p9_stat_dotl *stbuf = - va_arg(ap, struct p9_stat_dotl *); - - memset(stbuf, 0, sizeof(struct p9_stat_dotl)); - errcode = - p9pdu_readf(pdu, proto_version, - "qQdugqqqqqqqqqqqqqqq", - &stbuf->st_result_mask, - &stbuf->qid, - &stbuf->st_mode, - &stbuf->st_uid, &stbuf->st_gid, - &stbuf->st_nlink, - &stbuf->st_rdev, &stbuf->st_size, - &stbuf->st_blksize, &stbuf->st_blocks, - &stbuf->st_atime_sec, - &stbuf->st_atime_nsec, - &stbuf->st_mtime_sec, - &stbuf->st_mtime_nsec, - &stbuf->st_ctime_sec, - &stbuf->st_ctime_nsec, - &stbuf->st_btime_sec, - &stbuf->st_btime_nsec, - &stbuf->st_gen, - &stbuf->st_data_version); - } - break; - case '?': - if ((proto_version != p9_proto_2000u) && - (proto_version != p9_proto_2000L)) - return 0; - break; - default: - BUG(); - break; - } - - if (errcode) - break; - } - - return errcode; -} - -int -p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, - va_list ap) -{ - const char *ptr; - int errcode = 0; - - for (ptr = fmt; *ptr; ptr++) { - switch (*ptr) { - case 'b':{ - int8_t val = va_arg(ap, int); - if (pdu_write(pdu, &val, sizeof(val))) - errcode = -EFAULT; - } - break; - case 'w':{ - __le16 val = cpu_to_le16(va_arg(ap, int)); - if (pdu_write(pdu, &val, sizeof(val))) - errcode = -EFAULT; - } - break; - case 'd':{ - __le32 val = cpu_to_le32(va_arg(ap, int32_t)); - if (pdu_write(pdu, &val, sizeof(val))) - errcode = -EFAULT; - } - break; - case 'q':{ - __le64 val = cpu_to_le64(va_arg(ap, int64_t)); - if (pdu_write(pdu, &val, sizeof(val))) - errcode = -EFAULT; - } - break; - case 's':{ - const char *sptr = va_arg(ap, const char *); - uint16_t len = 0; - if (sptr) - len = min_t(size_t, strlen(sptr), - USHRT_MAX); - - errcode = p9pdu_writef(pdu, proto_version, - "w", len); - if (!errcode && pdu_write(pdu, sptr, len)) - errcode = -EFAULT; - } - break; - case 'u': { - kuid_t uid = va_arg(ap, kuid_t); - __le32 val = cpu_to_le32( - from_kuid(&init_user_ns, uid)); - if (pdu_write(pdu, &val, sizeof(val))) - errcode = -EFAULT; - } break; - case 'g': { - kgid_t gid = va_arg(ap, kgid_t); - __le32 val = cpu_to_le32( - from_kgid(&init_user_ns, gid)); - if (pdu_write(pdu, &val, sizeof(val))) - errcode = -EFAULT; - } break; - case 'Q':{ - const struct p9_qid *qid = - va_arg(ap, const struct p9_qid *); - errcode = - p9pdu_writef(pdu, proto_version, "bdq", - qid->type, qid->version, - qid->path); - } break; - case 'S':{ - const struct p9_wstat *stbuf = - va_arg(ap, const struct p9_wstat *); - errcode = - p9pdu_writef(pdu, proto_version, - "wwdQdddqssss?sugu", - stbuf->size, stbuf->type, - stbuf->dev, &stbuf->qid, - stbuf->mode, stbuf->atime, - stbuf->mtime, stbuf->length, - stbuf->name, stbuf->uid, - stbuf->gid, stbuf->muid, - stbuf->extension, stbuf->n_uid, - stbuf->n_gid, stbuf->n_muid); - } break; - case 'D':{ - uint32_t count = va_arg(ap, uint32_t); - const void *data = va_arg(ap, const void *); - - errcode = p9pdu_writef(pdu, proto_version, "d", - count); - if (!errcode && pdu_write(pdu, data, count)) - errcode = -EFAULT; - } - break; - case 'U':{ - int32_t count = va_arg(ap, int32_t); - const char __user *udata = - va_arg(ap, const void __user *); - errcode = p9pdu_writef(pdu, proto_version, "d", - count); - if (!errcode && pdu_write_u(pdu, udata, count)) - errcode = -EFAULT; - } - break; - case 'T':{ - uint16_t nwname = va_arg(ap, int); - const char **wnames = va_arg(ap, const char **); - - errcode = p9pdu_writef(pdu, proto_version, "w", - nwname); - if (!errcode) { - int i; - - for (i = 0; i < nwname; i++) { - errcode = - p9pdu_writef(pdu, - proto_version, - "s", - wnames[i]); - if (errcode) - break; - } - } - } - break; - case 'R':{ - int16_t nwqid = va_arg(ap, int); - struct p9_qid *wqids = - va_arg(ap, struct p9_qid *); - - errcode = p9pdu_writef(pdu, proto_version, "w", - nwqid); - if (!errcode) { - int i; - - for (i = 0; i < nwqid; i++) { - errcode = - p9pdu_writef(pdu, - proto_version, - "Q", - &wqids[i]); - if (errcode) - break; - } - } - } - break; - case 'I':{ - struct p9_iattr_dotl *p9attr = va_arg(ap, - struct p9_iattr_dotl *); - - errcode = p9pdu_writef(pdu, proto_version, - "ddugqqqqq", - p9attr->valid, - p9attr->mode, - p9attr->uid, - p9attr->gid, - p9attr->size, - p9attr->atime_sec, - p9attr->atime_nsec, - p9attr->mtime_sec, - p9attr->mtime_nsec); - } - break; - case '?': - if ((proto_version != p9_proto_2000u) && - (proto_version != p9_proto_2000L)) - return 0; - break; - default: - BUG(); - break; - } - - if (errcode) - break; - } - - return errcode; -} - -int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = p9pdu_vreadf(pdu, proto_version, fmt, ap); - va_end(ap); - - return ret; -} - -static int -p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = p9pdu_vwritef(pdu, proto_version, fmt, ap); - va_end(ap); - - return ret; -} - -int p9stat_read(struct p9_client *clnt, char *buf, int len, struct p9_wstat *st) -{ - struct p9_fcall fake_pdu; - int ret; - - fake_pdu.size = len; - fake_pdu.capacity = len; - fake_pdu.sdata = buf; - fake_pdu.offset = 0; - - ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "S", st); - if (ret) { - p9_debug(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret); - trace_9p_protocol_dump(clnt, &fake_pdu); - } - - return ret; -} -EXPORT_SYMBOL(p9stat_read); - -int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type) -{ - pdu->id = type; - return p9pdu_writef(pdu, 0, "dbw", 0, type, tag); -} - -int p9pdu_finalize(struct p9_client *clnt, struct p9_fcall *pdu) -{ - int size = pdu->size; - int err; - - pdu->size = 0; - err = p9pdu_writef(pdu, 0, "d", size); - pdu->size = size; - - trace_9p_protocol_dump(clnt, pdu); - p9_debug(P9_DEBUG_9P, ">>> size=%d type: %d tag: %d\n", - pdu->size, pdu->id, pdu->tag); - - return err; -} - -void p9pdu_reset(struct p9_fcall *pdu) -{ - pdu->offset = 0; - pdu->size = 0; -} - -int p9dirent_read(struct p9_client *clnt, char *buf, int len, - struct p9_dirent *dirent) -{ - struct p9_fcall fake_pdu; - int ret; - char *nameptr; - - fake_pdu.size = len; - fake_pdu.capacity = len; - fake_pdu.sdata = buf; - fake_pdu.offset = 0; - - ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "Qqbs", &dirent->qid, - &dirent->d_off, &dirent->d_type, &nameptr); - if (ret) { - p9_debug(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret); - trace_9p_protocol_dump(clnt, &fake_pdu); - goto out; - } - - strcpy(dirent->d_name, nameptr); - kfree(nameptr); - -out: - return fake_pdu.offset; -} -EXPORT_SYMBOL(p9dirent_read); diff --git a/addons/9p/src/3.10.108/protocol.h b/addons/9p/src/3.10.108/protocol.h deleted file mode 100644 index 2cc525fa..00000000 --- a/addons/9p/src/3.10.108/protocol.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * net/9p/protocol.h - * - * 9P Protocol Support Code - * - * Copyright (C) 2008 by Eric Van Hensbergen - * - * Base on code from Anthony Liguori - * Copyright (C) 2008 by IBM, Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -int p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, - va_list ap); -int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); -int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type); -int p9pdu_finalize(struct p9_client *clnt, struct p9_fcall *pdu); -void p9pdu_reset(struct p9_fcall *pdu); -size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size); diff --git a/addons/9p/src/3.10.108/trans_common.c b/addons/9p/src/3.10.108/trans_common.c deleted file mode 100644 index 2ee38791..00000000 --- a/addons/9p/src/3.10.108/trans_common.c +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright IBM Corporation, 2010 - * Author Venkateswararao Jujjuri - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -#include -#include -#include -#include -#include -#include "trans_common.h" - -/** - * p9_release_req_pages - Release pages after the transaction. - */ -void p9_release_pages(struct page **pages, int nr_pages) -{ - int i; - - for (i = 0; i < nr_pages; i++) - if (pages[i]) - put_page(pages[i]); -} -EXPORT_SYMBOL(p9_release_pages); - -/** - * p9_nr_pages - Return number of pages needed to accommodate the payload. - */ -int p9_nr_pages(char *data, int len) -{ - unsigned long start_page, end_page; - start_page = (unsigned long)data >> PAGE_SHIFT; - end_page = ((unsigned long)data + len + PAGE_SIZE - 1) >> PAGE_SHIFT; - return end_page - start_page; -} -EXPORT_SYMBOL(p9_nr_pages); - -/** - * payload_gup - Translates user buffer into kernel pages and - * pins them either for read/write through get_user_pages_fast(). - * @req: Request to be sent to server. - * @pdata_off: data offset into the first page after translation (gup). - * @pdata_len: Total length of the IO. gup may not return requested # of pages. - * @nr_pages: number of pages to accommodate the payload - * @rw: Indicates if the pages are for read or write. - */ - -int p9_payload_gup(char *data, int *nr_pages, struct page **pages, int write) -{ - int nr_mapped_pages; - - nr_mapped_pages = get_user_pages_fast((unsigned long)data, - *nr_pages, write, pages); - if (nr_mapped_pages <= 0) - return nr_mapped_pages; - - *nr_pages = nr_mapped_pages; - return 0; -} -EXPORT_SYMBOL(p9_payload_gup); diff --git a/addons/9p/src/3.10.108/trans_common.h b/addons/9p/src/3.10.108/trans_common.h deleted file mode 100644 index 173bb550..00000000 --- a/addons/9p/src/3.10.108/trans_common.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright IBM Corporation, 2010 - * Author Venkateswararao Jujjuri - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -void p9_release_pages(struct page **, int); -int p9_payload_gup(char *, int *, struct page **, int); -int p9_nr_pages(char *, int); diff --git a/addons/9p/src/3.10.108/trans_fd.c b/addons/9p/src/3.10.108/trans_fd.c deleted file mode 100644 index 02efb25c..00000000 --- a/addons/9p/src/3.10.108/trans_fd.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * linux/fs/9p/trans_fd.c - * - * Fd transport layer. Includes deprecated socket layer. - * - * Copyright (C) 2006 by Russ Cox - * Copyright (C) 2004-2005 by Latchesar Ionkov - * Copyright (C) 2004-2008 by Eric Van Hensbergen - * Copyright (C) 1997-2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include /* killme */ - -#define P9_PORT 564 -#define MAX_SOCK_BUF (64*1024) -#define MAXPOLLWADDR 2 - -/** - * struct p9_fd_opts - per-transport options - * @rfd: file descriptor for reading (trans=fd) - * @wfd: file descriptor for writing (trans=fd) - * @port: port to connect to (trans=tcp) - * - */ - -struct p9_fd_opts { - int rfd; - int wfd; - u16 port; -}; - -/** - * struct p9_trans_fd - transport state - * @rd: reference to file to read from - * @wr: reference of file to write to - * @conn: connection state reference - * - */ - -struct p9_trans_fd { - struct file *rd; - struct file *wr; - struct p9_conn *conn; -}; - -/* - * Option Parsing (code inspired by NFS code) - * - a little lazy - parse all fd-transport options - */ - -enum { - /* Options that take integer arguments */ - Opt_port, Opt_rfdno, Opt_wfdno, Opt_err, -}; - -static const match_table_t tokens = { - {Opt_port, "port=%u"}, - {Opt_rfdno, "rfdno=%u"}, - {Opt_wfdno, "wfdno=%u"}, - {Opt_err, NULL}, -}; - -enum { - Rworksched = 1, /* read work scheduled or running */ - Rpending = 2, /* can read */ - Wworksched = 4, /* write work scheduled or running */ - Wpending = 8, /* can write */ -}; - -struct p9_poll_wait { - struct p9_conn *conn; - wait_queue_t wait; - wait_queue_head_t *wait_addr; -}; - -/** - * struct p9_conn - fd mux connection state information - * @mux_list: list link for mux to manage multiple connections (?) - * @client: reference to client instance for this connection - * @err: error state - * @req_list: accounting for requests which have been sent - * @unsent_req_list: accounting for requests that haven't been sent - * @req: current request being processed (if any) - * @tmp_buf: temporary buffer to read in header - * @rsize: amount to read for current frame - * @rpos: read position in current frame - * @rbuf: current read buffer - * @wpos: write position for current frame - * @wsize: amount of data to write for current frame - * @wbuf: current write buffer - * @poll_pending_link: pending links to be polled per conn - * @poll_wait: array of wait_q's for various worker threads - * @pt: poll state - * @rq: current read work - * @wq: current write work - * @wsched: ???? - * - */ - -struct p9_conn { - struct list_head mux_list; - struct p9_client *client; - int err; - struct list_head req_list; - struct list_head unsent_req_list; - struct p9_req_t *req; - char tmp_buf[7]; - int rsize; - int rpos; - char *rbuf; - int wpos; - int wsize; - char *wbuf; - struct list_head poll_pending_link; - struct p9_poll_wait poll_wait[MAXPOLLWADDR]; - poll_table pt; - struct work_struct rq; - struct work_struct wq; - unsigned long wsched; -}; - -static void p9_poll_workfn(struct work_struct *work); - -static DEFINE_SPINLOCK(p9_poll_lock); -static LIST_HEAD(p9_poll_pending_list); -static DECLARE_WORK(p9_poll_work, p9_poll_workfn); - -static void p9_mux_poll_stop(struct p9_conn *m) -{ - unsigned long flags; - int i; - - for (i = 0; i < ARRAY_SIZE(m->poll_wait); i++) { - struct p9_poll_wait *pwait = &m->poll_wait[i]; - - if (pwait->wait_addr) { - remove_wait_queue(pwait->wait_addr, &pwait->wait); - pwait->wait_addr = NULL; - } - } - - spin_lock_irqsave(&p9_poll_lock, flags); - list_del_init(&m->poll_pending_link); - spin_unlock_irqrestore(&p9_poll_lock, flags); -} - -/** - * p9_conn_cancel - cancel all pending requests with error - * @m: mux data - * @err: error code - * - */ - -static void p9_conn_cancel(struct p9_conn *m, int err) -{ - struct p9_req_t *req, *rtmp; - unsigned long flags; - LIST_HEAD(cancel_list); - - p9_debug(P9_DEBUG_ERROR, "mux %p err %d\n", m, err); - - spin_lock_irqsave(&m->client->lock, flags); - - if (m->err) { - spin_unlock_irqrestore(&m->client->lock, flags); - return; - } - - m->err = err; - - list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { - req->status = REQ_STATUS_ERROR; - if (!req->t_err) - req->t_err = err; - list_move(&req->req_list, &cancel_list); - } - list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { - req->status = REQ_STATUS_ERROR; - if (!req->t_err) - req->t_err = err; - list_move(&req->req_list, &cancel_list); - } - spin_unlock_irqrestore(&m->client->lock, flags); - - list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { - p9_debug(P9_DEBUG_ERROR, "call back req %p\n", req); - list_del(&req->req_list); - p9_client_cb(m->client, req); - } -} - -static int -p9_fd_poll(struct p9_client *client, struct poll_table_struct *pt) -{ - int ret, n; - struct p9_trans_fd *ts = NULL; - - if (client && client->status == Connected) - ts = client->trans; - - if (!ts) - return -EREMOTEIO; - - if (!ts->rd->f_op || !ts->rd->f_op->poll) - return -EIO; - - if (!ts->wr->f_op || !ts->wr->f_op->poll) - return -EIO; - - ret = ts->rd->f_op->poll(ts->rd, pt); - if (ret < 0) - return ret; - - if (ts->rd != ts->wr) { - n = ts->wr->f_op->poll(ts->wr, pt); - if (n < 0) - return n; - ret = (ret & ~POLLOUT) | (n & ~POLLIN); - } - - return ret; -} - -/** - * p9_fd_read- read from a fd - * @client: client instance - * @v: buffer to receive data into - * @len: size of receive buffer - * - */ - -static int p9_fd_read(struct p9_client *client, void *v, int len) -{ - int ret; - struct p9_trans_fd *ts = NULL; - - if (client && client->status != Disconnected) - ts = client->trans; - - if (!ts) - return -EREMOTEIO; - - if (!(ts->rd->f_flags & O_NONBLOCK)) - p9_debug(P9_DEBUG_ERROR, "blocking read ...\n"); - - ret = kernel_read(ts->rd, ts->rd->f_pos, v, len); - if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) - client->status = Disconnected; - return ret; -} - -/** - * p9_read_work - called when there is some data to be read from a transport - * @work: container of work to be done - * - */ - -static void p9_read_work(struct work_struct *work) -{ - int n, err; - struct p9_conn *m; - - m = container_of(work, struct p9_conn, rq); - - if (m->err < 0) - return; - - p9_debug(P9_DEBUG_TRANS, "start mux %p pos %d\n", m, m->rpos); - - if (!m->rbuf) { - m->rbuf = m->tmp_buf; - m->rpos = 0; - m->rsize = 7; /* start by reading header */ - } - - clear_bit(Rpending, &m->wsched); - p9_debug(P9_DEBUG_TRANS, "read mux %p pos %d size: %d = %d\n", - m, m->rpos, m->rsize, m->rsize-m->rpos); - err = p9_fd_read(m->client, m->rbuf + m->rpos, - m->rsize - m->rpos); - p9_debug(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err); - if (err == -EAGAIN) { - goto end_clear; - } - - if (err <= 0) - goto error; - - m->rpos += err; - - if ((!m->req) && (m->rpos == m->rsize)) { /* header read in */ - u16 tag; - p9_debug(P9_DEBUG_TRANS, "got new header\n"); - - n = le32_to_cpu(*(__le32 *) m->rbuf); /* read packet size */ - if (n >= m->client->msize) { - p9_debug(P9_DEBUG_ERROR, - "requested packet size too big: %d\n", n); - err = -EIO; - goto error; - } - - tag = le16_to_cpu(*(__le16 *) (m->rbuf+5)); /* read tag */ - p9_debug(P9_DEBUG_TRANS, - "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag); - - m->req = p9_tag_lookup(m->client, tag); - if (!m->req || (m->req->status != REQ_STATUS_SENT && - m->req->status != REQ_STATUS_FLSH)) { - p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", - tag); - err = -EIO; - goto error; - } - - if (m->req->rc == NULL) { - m->req->rc = kmalloc(sizeof(struct p9_fcall) + - m->client->msize, GFP_NOFS); - if (!m->req->rc) { - m->req = NULL; - err = -ENOMEM; - goto error; - } - } - m->rbuf = (char *)m->req->rc + sizeof(struct p9_fcall); - memcpy(m->rbuf, m->tmp_buf, m->rsize); - m->rsize = n; - } - - /* not an else because some packets (like clunk) have no payload */ - if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ - p9_debug(P9_DEBUG_TRANS, "got new packet\n"); - spin_lock(&m->client->lock); - if (m->req->status != REQ_STATUS_ERROR) - m->req->status = REQ_STATUS_RCVD; - list_del(&m->req->req_list); - spin_unlock(&m->client->lock); - p9_client_cb(m->client, m->req); - m->rbuf = NULL; - m->rpos = 0; - m->rsize = 0; - m->req = NULL; - } - -end_clear: - clear_bit(Rworksched, &m->wsched); - - if (!list_empty(&m->req_list)) { - if (test_and_clear_bit(Rpending, &m->wsched)) - n = POLLIN; - else - n = p9_fd_poll(m->client, NULL); - - if ((n & POLLIN) && !test_and_set_bit(Rworksched, &m->wsched)) { - p9_debug(P9_DEBUG_TRANS, "sched read work %p\n", m); - schedule_work(&m->rq); - } - } - - return; -error: - p9_conn_cancel(m, err); - clear_bit(Rworksched, &m->wsched); -} - -/** - * p9_fd_write - write to a socket - * @client: client instance - * @v: buffer to send data from - * @len: size of send buffer - * - */ - -static int p9_fd_write(struct p9_client *client, void *v, int len) -{ - int ret; - mm_segment_t oldfs; - struct p9_trans_fd *ts = NULL; - - if (client && client->status != Disconnected) - ts = client->trans; - - if (!ts) - return -EREMOTEIO; - - if (!(ts->wr->f_flags & O_NONBLOCK)) - p9_debug(P9_DEBUG_ERROR, "blocking write ...\n"); - - oldfs = get_fs(); - set_fs(get_ds()); - /* The cast to a user pointer is valid due to the set_fs() */ - ret = vfs_write(ts->wr, (__force void __user *)v, len, &ts->wr->f_pos); - set_fs(oldfs); - - if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) - client->status = Disconnected; - return ret; -} - -/** - * p9_write_work - called when a transport can send some data - * @work: container for work to be done - * - */ - -static void p9_write_work(struct work_struct *work) -{ - int n, err; - struct p9_conn *m; - struct p9_req_t *req; - - m = container_of(work, struct p9_conn, wq); - - if (m->err < 0) { - clear_bit(Wworksched, &m->wsched); - return; - } - - if (!m->wsize) { - spin_lock(&m->client->lock); - if (list_empty(&m->unsent_req_list)) { - clear_bit(Wworksched, &m->wsched); - spin_unlock(&m->client->lock); - return; - } - - req = list_entry(m->unsent_req_list.next, struct p9_req_t, - req_list); - req->status = REQ_STATUS_SENT; - p9_debug(P9_DEBUG_TRANS, "move req %p\n", req); - list_move_tail(&req->req_list, &m->req_list); - - m->wbuf = req->tc->sdata; - m->wsize = req->tc->size; - m->wpos = 0; - spin_unlock(&m->client->lock); - } - - p9_debug(P9_DEBUG_TRANS, "mux %p pos %d size %d\n", - m, m->wpos, m->wsize); - clear_bit(Wpending, &m->wsched); - err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos); - p9_debug(P9_DEBUG_TRANS, "mux %p sent %d bytes\n", m, err); - if (err == -EAGAIN) - goto end_clear; - - - if (err < 0) - goto error; - else if (err == 0) { - err = -EREMOTEIO; - goto error; - } - - m->wpos += err; - if (m->wpos == m->wsize) - m->wpos = m->wsize = 0; - -end_clear: - clear_bit(Wworksched, &m->wsched); - - if (m->wsize || !list_empty(&m->unsent_req_list)) { - if (test_and_clear_bit(Wpending, &m->wsched)) - n = POLLOUT; - else - n = p9_fd_poll(m->client, NULL); - - if ((n & POLLOUT) && - !test_and_set_bit(Wworksched, &m->wsched)) { - p9_debug(P9_DEBUG_TRANS, "sched write work %p\n", m); - schedule_work(&m->wq); - } - } - - return; - -error: - p9_conn_cancel(m, err); - clear_bit(Wworksched, &m->wsched); -} - -static int p9_pollwake(wait_queue_t *wait, unsigned int mode, int sync, void *key) -{ - struct p9_poll_wait *pwait = - container_of(wait, struct p9_poll_wait, wait); - struct p9_conn *m = pwait->conn; - unsigned long flags; - - spin_lock_irqsave(&p9_poll_lock, flags); - if (list_empty(&m->poll_pending_link)) - list_add_tail(&m->poll_pending_link, &p9_poll_pending_list); - spin_unlock_irqrestore(&p9_poll_lock, flags); - - schedule_work(&p9_poll_work); - return 1; -} - -/** - * p9_pollwait - add poll task to the wait queue - * @filp: file pointer being polled - * @wait_address: wait_q to block on - * @p: poll state - * - * called by files poll operation to add v9fs-poll task to files wait queue - */ - -static void -p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p) -{ - struct p9_conn *m = container_of(p, struct p9_conn, pt); - struct p9_poll_wait *pwait = NULL; - int i; - - for (i = 0; i < ARRAY_SIZE(m->poll_wait); i++) { - if (m->poll_wait[i].wait_addr == NULL) { - pwait = &m->poll_wait[i]; - break; - } - } - - if (!pwait) { - p9_debug(P9_DEBUG_ERROR, "not enough wait_address slots\n"); - return; - } - - pwait->conn = m; - pwait->wait_addr = wait_address; - init_waitqueue_func_entry(&pwait->wait, p9_pollwake); - add_wait_queue(wait_address, &pwait->wait); -} - -/** - * p9_conn_create - allocate and initialize the per-session mux data - * @client: client instance - * - * Note: Creates the polling task if this is the first session. - */ - -static struct p9_conn *p9_conn_create(struct p9_client *client) -{ - int n; - struct p9_conn *m; - - p9_debug(P9_DEBUG_TRANS, "client %p msize %d\n", client, client->msize); - m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL); - if (!m) - return ERR_PTR(-ENOMEM); - - INIT_LIST_HEAD(&m->mux_list); - m->client = client; - - INIT_LIST_HEAD(&m->req_list); - INIT_LIST_HEAD(&m->unsent_req_list); - INIT_WORK(&m->rq, p9_read_work); - INIT_WORK(&m->wq, p9_write_work); - INIT_LIST_HEAD(&m->poll_pending_link); - init_poll_funcptr(&m->pt, p9_pollwait); - - n = p9_fd_poll(client, &m->pt); - if (n & POLLIN) { - p9_debug(P9_DEBUG_TRANS, "mux %p can read\n", m); - set_bit(Rpending, &m->wsched); - } - - if (n & POLLOUT) { - p9_debug(P9_DEBUG_TRANS, "mux %p can write\n", m); - set_bit(Wpending, &m->wsched); - } - - return m; -} - -/** - * p9_poll_mux - polls a mux and schedules read or write works if necessary - * @m: connection to poll - * - */ - -static void p9_poll_mux(struct p9_conn *m) -{ - int n; - - if (m->err < 0) - return; - - n = p9_fd_poll(m->client, NULL); - if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) { - p9_debug(P9_DEBUG_TRANS, "error mux %p err %d\n", m, n); - if (n >= 0) - n = -ECONNRESET; - p9_conn_cancel(m, n); - } - - if (n & POLLIN) { - set_bit(Rpending, &m->wsched); - p9_debug(P9_DEBUG_TRANS, "mux %p can read\n", m); - if (!test_and_set_bit(Rworksched, &m->wsched)) { - p9_debug(P9_DEBUG_TRANS, "sched read work %p\n", m); - schedule_work(&m->rq); - } - } - - if (n & POLLOUT) { - set_bit(Wpending, &m->wsched); - p9_debug(P9_DEBUG_TRANS, "mux %p can write\n", m); - if ((m->wsize || !list_empty(&m->unsent_req_list)) && - !test_and_set_bit(Wworksched, &m->wsched)) { - p9_debug(P9_DEBUG_TRANS, "sched write work %p\n", m); - schedule_work(&m->wq); - } - } -} - -/** - * p9_fd_request - send 9P request - * The function can sleep until the request is scheduled for sending. - * The function can be interrupted. Return from the function is not - * a guarantee that the request is sent successfully. - * - * @client: client instance - * @req: request to be sent - * - */ - -static int p9_fd_request(struct p9_client *client, struct p9_req_t *req) -{ - int n; - struct p9_trans_fd *ts = client->trans; - struct p9_conn *m = ts->conn; - - p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n", - m, current, req->tc, req->tc->id); - if (m->err < 0) - return m->err; - - spin_lock(&client->lock); - req->status = REQ_STATUS_UNSENT; - list_add_tail(&req->req_list, &m->unsent_req_list); - spin_unlock(&client->lock); - - if (test_and_clear_bit(Wpending, &m->wsched)) - n = POLLOUT; - else - n = p9_fd_poll(m->client, NULL); - - if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched)) - schedule_work(&m->wq); - - return 0; -} - -static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req) -{ - int ret = 1; - - p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req); - - spin_lock(&client->lock); - - if (req->status == REQ_STATUS_UNSENT) { - list_del(&req->req_list); - req->status = REQ_STATUS_FLSHD; - ret = 0; - } else if (req->status == REQ_STATUS_SENT) - req->status = REQ_STATUS_FLSH; - - spin_unlock(&client->lock); - - return ret; -} - -/** - * parse_opts - parse mount options into p9_fd_opts structure - * @params: options string passed from mount - * @opts: fd transport-specific structure to parse options into - * - * Returns 0 upon success, -ERRNO upon failure - */ - -static int parse_opts(char *params, struct p9_fd_opts *opts) -{ - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - char *options, *tmp_options; - - opts->port = P9_PORT; - opts->rfd = ~0; - opts->wfd = ~0; - - if (!params) - return 0; - - tmp_options = kstrdup(params, GFP_KERNEL); - if (!tmp_options) { - p9_debug(P9_DEBUG_ERROR, - "failed to allocate copy of option string\n"); - return -ENOMEM; - } - options = tmp_options; - - while ((p = strsep(&options, ",")) != NULL) { - int token; - int r; - if (!*p) - continue; - token = match_token(p, tokens, args); - if (token != Opt_err) { - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - continue; - } - } - switch (token) { - case Opt_port: - opts->port = option; - break; - case Opt_rfdno: - opts->rfd = option; - break; - case Opt_wfdno: - opts->wfd = option; - break; - default: - continue; - } - } - - kfree(tmp_options); - return 0; -} - -static int p9_fd_open(struct p9_client *client, int rfd, int wfd) -{ - struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd), - GFP_KERNEL); - if (!ts) - return -ENOMEM; - - ts->rd = fget(rfd); - ts->wr = fget(wfd); - if (!ts->rd || !ts->wr) { - if (ts->rd) - fput(ts->rd); - if (ts->wr) - fput(ts->wr); - kfree(ts); - return -EIO; - } - - client->trans = ts; - client->status = Connected; - - return 0; -} - -static int p9_socket_open(struct p9_client *client, struct socket *csocket) -{ - struct p9_trans_fd *p; - struct file *file; - int ret; - - p = kmalloc(sizeof(struct p9_trans_fd), GFP_KERNEL); - if (!p) - return -ENOMEM; - - csocket->sk->sk_allocation = GFP_NOIO; - file = sock_alloc_file(csocket, 0, NULL); - if (IS_ERR(file)) { - pr_err("%s (%d): failed to map fd\n", - __func__, task_pid_nr(current)); - sock_release(csocket); - kfree(p); - return PTR_ERR(file); - } - - get_file(file); - p->wr = p->rd = file; - client->trans = p; - client->status = Connected; - - p->rd->f_flags |= O_NONBLOCK; - - p->conn = p9_conn_create(client); - if (IS_ERR(p->conn)) { - ret = PTR_ERR(p->conn); - p->conn = NULL; - kfree(p); - sockfd_put(csocket); - sockfd_put(csocket); - return ret; - } - return 0; -} - -/** - * p9_mux_destroy - cancels all pending requests and frees mux resources - * @m: mux to destroy - * - */ - -static void p9_conn_destroy(struct p9_conn *m) -{ - p9_debug(P9_DEBUG_TRANS, "mux %p prev %p next %p\n", - m, m->mux_list.prev, m->mux_list.next); - - p9_mux_poll_stop(m); - cancel_work_sync(&m->rq); - cancel_work_sync(&m->wq); - - p9_conn_cancel(m, -ECONNRESET); - - m->client = NULL; - kfree(m); -} - -/** - * p9_fd_close - shutdown file descriptor transport - * @client: client instance - * - */ - -static void p9_fd_close(struct p9_client *client) -{ - struct p9_trans_fd *ts; - - if (!client) - return; - - ts = client->trans; - if (!ts) - return; - - client->status = Disconnected; - - p9_conn_destroy(ts->conn); - - if (ts->rd) - fput(ts->rd); - if (ts->wr) - fput(ts->wr); - - kfree(ts); -} - -/* - * stolen from NFS - maybe should be made a generic function? - */ -static inline int valid_ipaddr4(const char *buf) -{ - int rc, count, in[4]; - - rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]); - if (rc != 4) - return -EINVAL; - for (count = 0; count < 4; count++) { - if (in[count] > 255) - return -EINVAL; - } - return 0; -} - -static int -p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) -{ - int err; - struct socket *csocket; - struct sockaddr_in sin_server; - struct p9_fd_opts opts; - - err = parse_opts(args, &opts); - if (err < 0) - return err; - - if (valid_ipaddr4(addr) < 0) - return -EINVAL; - - csocket = NULL; - - sin_server.sin_family = AF_INET; - sin_server.sin_addr.s_addr = in_aton(addr); - sin_server.sin_port = htons(opts.port); - err = __sock_create(read_pnet(¤t->nsproxy->net_ns), PF_INET, - SOCK_STREAM, IPPROTO_TCP, &csocket, 1); - if (err) { - pr_err("%s (%d): problem creating socket\n", - __func__, task_pid_nr(current)); - return err; - } - - err = csocket->ops->connect(csocket, - (struct sockaddr *)&sin_server, - sizeof(struct sockaddr_in), 0); - if (err < 0) { - pr_err("%s (%d): problem connecting socket to %s\n", - __func__, task_pid_nr(current), addr); - sock_release(csocket); - return err; - } - - return p9_socket_open(client, csocket); -} - -static int -p9_fd_create_unix(struct p9_client *client, const char *addr, char *args) -{ - int err; - struct socket *csocket; - struct sockaddr_un sun_server; - - csocket = NULL; - - if (strlen(addr) >= UNIX_PATH_MAX) { - pr_err("%s (%d): address too long: %s\n", - __func__, task_pid_nr(current), addr); - return -ENAMETOOLONG; - } - - sun_server.sun_family = PF_UNIX; - strcpy(sun_server.sun_path, addr); - err = __sock_create(read_pnet(¤t->nsproxy->net_ns), PF_UNIX, - SOCK_STREAM, 0, &csocket, 1); - if (err < 0) { - pr_err("%s (%d): problem creating socket\n", - __func__, task_pid_nr(current)); - - return err; - } - err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, - sizeof(struct sockaddr_un) - 1, 0); - if (err < 0) { - pr_err("%s (%d): problem connecting socket: %s: %d\n", - __func__, task_pid_nr(current), addr, err); - sock_release(csocket); - return err; - } - - return p9_socket_open(client, csocket); -} - -static int -p9_fd_create(struct p9_client *client, const char *addr, char *args) -{ - int err; - struct p9_fd_opts opts; - struct p9_trans_fd *p; - - parse_opts(args, &opts); - - if (opts.rfd == ~0 || opts.wfd == ~0) { - pr_err("Insufficient options for proto=fd\n"); - return -ENOPROTOOPT; - } - - err = p9_fd_open(client, opts.rfd, opts.wfd); - if (err < 0) - return err; - - p = (struct p9_trans_fd *) client->trans; - p->conn = p9_conn_create(client); - if (IS_ERR(p->conn)) { - err = PTR_ERR(p->conn); - p->conn = NULL; - fput(p->rd); - fput(p->wr); - return err; - } - - return 0; -} - -static struct p9_trans_module p9_tcp_trans = { - .name = "tcp", - .maxsize = MAX_SOCK_BUF, - .def = 1, - .create = p9_fd_create_tcp, - .close = p9_fd_close, - .request = p9_fd_request, - .cancel = p9_fd_cancel, - .owner = THIS_MODULE, -}; - -static struct p9_trans_module p9_unix_trans = { - .name = "unix", - .maxsize = MAX_SOCK_BUF, - .def = 0, - .create = p9_fd_create_unix, - .close = p9_fd_close, - .request = p9_fd_request, - .cancel = p9_fd_cancel, - .owner = THIS_MODULE, -}; - -static struct p9_trans_module p9_fd_trans = { - .name = "fd", - .maxsize = MAX_SOCK_BUF, - .def = 0, - .create = p9_fd_create, - .close = p9_fd_close, - .request = p9_fd_request, - .cancel = p9_fd_cancel, - .owner = THIS_MODULE, -}; - -/** - * p9_poll_proc - poll worker thread - * @a: thread state and arguments - * - * polls all v9fs transports for new events and queues the appropriate - * work to the work queue - * - */ - -static void p9_poll_workfn(struct work_struct *work) -{ - unsigned long flags; - - p9_debug(P9_DEBUG_TRANS, "start %p\n", current); - - spin_lock_irqsave(&p9_poll_lock, flags); - while (!list_empty(&p9_poll_pending_list)) { - struct p9_conn *conn = list_first_entry(&p9_poll_pending_list, - struct p9_conn, - poll_pending_link); - list_del_init(&conn->poll_pending_link); - spin_unlock_irqrestore(&p9_poll_lock, flags); - - p9_poll_mux(conn); - - spin_lock_irqsave(&p9_poll_lock, flags); - } - spin_unlock_irqrestore(&p9_poll_lock, flags); - - p9_debug(P9_DEBUG_TRANS, "finish\n"); -} - -int p9_trans_fd_init(void) -{ - v9fs_register_trans(&p9_tcp_trans); - v9fs_register_trans(&p9_unix_trans); - v9fs_register_trans(&p9_fd_trans); - - return 0; -} - -void p9_trans_fd_exit(void) -{ - flush_work(&p9_poll_work); - v9fs_unregister_trans(&p9_tcp_trans); - v9fs_unregister_trans(&p9_unix_trans); - v9fs_unregister_trans(&p9_fd_trans); -} diff --git a/addons/9p/src/3.10.108/trans_rdma.c b/addons/9p/src/3.10.108/trans_rdma.c deleted file mode 100644 index 2c69ddd6..00000000 --- a/addons/9p/src/3.10.108/trans_rdma.c +++ /dev/null @@ -1,719 +0,0 @@ -/* - * linux/fs/9p/trans_rdma.c - * - * RDMA transport layer based on the trans_fd.c implementation. - * - * Copyright (C) 2008 by Tom Tucker - * Copyright (C) 2006 by Russ Cox - * Copyright (C) 2004-2005 by Latchesar Ionkov - * Copyright (C) 2004-2008 by Eric Van Hensbergen - * Copyright (C) 1997-2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define P9_PORT 5640 -#define P9_RDMA_SQ_DEPTH 32 -#define P9_RDMA_RQ_DEPTH 32 -#define P9_RDMA_SEND_SGE 4 -#define P9_RDMA_RECV_SGE 4 -#define P9_RDMA_IRD 0 -#define P9_RDMA_ORD 0 -#define P9_RDMA_TIMEOUT 30000 /* 30 seconds */ -#define P9_RDMA_MAXSIZE (4*4096) /* Min SGE is 4, so we can - * safely advertise a maxsize - * of 64k */ - -/** - * struct p9_trans_rdma - RDMA transport instance - * - * @state: tracks the transport state machine for connection setup and tear down - * @cm_id: The RDMA CM ID - * @pd: Protection Domain pointer - * @qp: Queue Pair pointer - * @cq: Completion Queue pointer - * @dm_mr: DMA Memory Region pointer - * @lkey: The local access only memory region key - * @timeout: Number of uSecs to wait for connection management events - * @sq_depth: The depth of the Send Queue - * @sq_sem: Semaphore for the SQ - * @rq_depth: The depth of the Receive Queue. - * @rq_count: Count of requests in the Receive Queue. - * @addr: The remote peer's address - * @req_lock: Protects the active request list - * @cm_done: Completion event for connection management tracking - */ -struct p9_trans_rdma { - enum { - P9_RDMA_INIT, - P9_RDMA_ADDR_RESOLVED, - P9_RDMA_ROUTE_RESOLVED, - P9_RDMA_CONNECTED, - P9_RDMA_FLUSHING, - P9_RDMA_CLOSING, - P9_RDMA_CLOSED, - } state; - struct rdma_cm_id *cm_id; - struct ib_pd *pd; - struct ib_qp *qp; - struct ib_cq *cq; - struct ib_mr *dma_mr; - u32 lkey; - long timeout; - int sq_depth; - struct semaphore sq_sem; - int rq_depth; - atomic_t rq_count; - struct sockaddr_in addr; - spinlock_t req_lock; - - struct completion cm_done; -}; - -/** - * p9_rdma_context - Keeps track of in-process WR - * - * @wc_op: The original WR op for when the CQE completes in error. - * @busa: Bus address to unmap when the WR completes - * @req: Keeps track of requests (send) - * @rc: Keepts track of replies (receive) - */ -struct p9_rdma_req; -struct p9_rdma_context { - enum ib_wc_opcode wc_op; - dma_addr_t busa; - union { - struct p9_req_t *req; - struct p9_fcall *rc; - }; -}; - -/** - * p9_rdma_opts - Collection of mount options - * @port: port of connection - * @sq_depth: The requested depth of the SQ. This really doesn't need - * to be any deeper than the number of threads used in the client - * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth - * @timeout: Time to wait in msecs for CM events - */ -struct p9_rdma_opts { - short port; - int sq_depth; - int rq_depth; - long timeout; -}; - -/* - * Option Parsing (code inspired by NFS code) - */ -enum { - /* Options that take integer arguments */ - Opt_port, Opt_rq_depth, Opt_sq_depth, Opt_timeout, Opt_err, -}; - -static match_table_t tokens = { - {Opt_port, "port=%u"}, - {Opt_sq_depth, "sq=%u"}, - {Opt_rq_depth, "rq=%u"}, - {Opt_timeout, "timeout=%u"}, - {Opt_err, NULL}, -}; - -/** - * parse_opts - parse mount options into rdma options structure - * @params: options string passed from mount - * @opts: rdma transport-specific structure to parse options into - * - * Returns 0 upon success, -ERRNO upon failure - */ -static int parse_opts(char *params, struct p9_rdma_opts *opts) -{ - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - char *options, *tmp_options; - - opts->port = P9_PORT; - opts->sq_depth = P9_RDMA_SQ_DEPTH; - opts->rq_depth = P9_RDMA_RQ_DEPTH; - opts->timeout = P9_RDMA_TIMEOUT; - - if (!params) - return 0; - - tmp_options = kstrdup(params, GFP_KERNEL); - if (!tmp_options) { - p9_debug(P9_DEBUG_ERROR, - "failed to allocate copy of option string\n"); - return -ENOMEM; - } - options = tmp_options; - - while ((p = strsep(&options, ",")) != NULL) { - int token; - int r; - if (!*p) - continue; - token = match_token(p, tokens, args); - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - continue; - } - switch (token) { - case Opt_port: - opts->port = option; - break; - case Opt_sq_depth: - opts->sq_depth = option; - break; - case Opt_rq_depth: - opts->rq_depth = option; - break; - case Opt_timeout: - opts->timeout = option; - break; - default: - continue; - } - } - /* RQ must be at least as large as the SQ */ - opts->rq_depth = max(opts->rq_depth, opts->sq_depth); - kfree(tmp_options); - return 0; -} - -static int -p9_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) -{ - struct p9_client *c = id->context; - struct p9_trans_rdma *rdma = c->trans; - switch (event->event) { - case RDMA_CM_EVENT_ADDR_RESOLVED: - BUG_ON(rdma->state != P9_RDMA_INIT); - rdma->state = P9_RDMA_ADDR_RESOLVED; - break; - - case RDMA_CM_EVENT_ROUTE_RESOLVED: - BUG_ON(rdma->state != P9_RDMA_ADDR_RESOLVED); - rdma->state = P9_RDMA_ROUTE_RESOLVED; - break; - - case RDMA_CM_EVENT_ESTABLISHED: - BUG_ON(rdma->state != P9_RDMA_ROUTE_RESOLVED); - rdma->state = P9_RDMA_CONNECTED; - break; - - case RDMA_CM_EVENT_DISCONNECTED: - if (rdma) - rdma->state = P9_RDMA_CLOSED; - if (c) - c->status = Disconnected; - break; - - case RDMA_CM_EVENT_TIMEWAIT_EXIT: - break; - - case RDMA_CM_EVENT_ADDR_CHANGE: - case RDMA_CM_EVENT_ROUTE_ERROR: - case RDMA_CM_EVENT_DEVICE_REMOVAL: - case RDMA_CM_EVENT_MULTICAST_JOIN: - case RDMA_CM_EVENT_MULTICAST_ERROR: - case RDMA_CM_EVENT_REJECTED: - case RDMA_CM_EVENT_CONNECT_REQUEST: - case RDMA_CM_EVENT_CONNECT_RESPONSE: - case RDMA_CM_EVENT_CONNECT_ERROR: - case RDMA_CM_EVENT_ADDR_ERROR: - case RDMA_CM_EVENT_UNREACHABLE: - c->status = Disconnected; - rdma_disconnect(rdma->cm_id); - break; - default: - BUG(); - } - complete(&rdma->cm_done); - return 0; -} - -static void -handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma, - struct p9_rdma_context *c, enum ib_wc_status status, u32 byte_len) -{ - struct p9_req_t *req; - int err = 0; - int16_t tag; - - req = NULL; - ib_dma_unmap_single(rdma->cm_id->device, c->busa, client->msize, - DMA_FROM_DEVICE); - - if (status != IB_WC_SUCCESS) - goto err_out; - - err = p9_parse_header(c->rc, NULL, NULL, &tag, 1); - if (err) - goto err_out; - - req = p9_tag_lookup(client, tag); - if (!req) - goto err_out; - - req->rc = c->rc; - req->status = REQ_STATUS_RCVD; - p9_client_cb(client, req); - - return; - - err_out: - p9_debug(P9_DEBUG_ERROR, "req %p err %d status %d\n", req, err, status); - rdma->state = P9_RDMA_FLUSHING; - client->status = Disconnected; -} - -static void -handle_send(struct p9_client *client, struct p9_trans_rdma *rdma, - struct p9_rdma_context *c, enum ib_wc_status status, u32 byte_len) -{ - ib_dma_unmap_single(rdma->cm_id->device, - c->busa, c->req->tc->size, - DMA_TO_DEVICE); -} - -static void qp_event_handler(struct ib_event *event, void *context) -{ - p9_debug(P9_DEBUG_ERROR, "QP event %d context %p\n", - event->event, context); -} - -static void cq_comp_handler(struct ib_cq *cq, void *cq_context) -{ - struct p9_client *client = cq_context; - struct p9_trans_rdma *rdma = client->trans; - int ret; - struct ib_wc wc; - - ib_req_notify_cq(rdma->cq, IB_CQ_NEXT_COMP); - while ((ret = ib_poll_cq(cq, 1, &wc)) > 0) { - struct p9_rdma_context *c = (void *) (unsigned long) wc.wr_id; - - switch (c->wc_op) { - case IB_WC_RECV: - atomic_dec(&rdma->rq_count); - handle_recv(client, rdma, c, wc.status, wc.byte_len); - break; - - case IB_WC_SEND: - handle_send(client, rdma, c, wc.status, wc.byte_len); - up(&rdma->sq_sem); - break; - - default: - pr_err("unexpected completion type, c->wc_op=%d, wc.opcode=%d, status=%d\n", - c->wc_op, wc.opcode, wc.status); - break; - } - kfree(c); - } -} - -static void cq_event_handler(struct ib_event *e, void *v) -{ - p9_debug(P9_DEBUG_ERROR, "CQ event %d context %p\n", e->event, v); -} - -static void rdma_destroy_trans(struct p9_trans_rdma *rdma) -{ - if (!rdma) - return; - - if (rdma->dma_mr && !IS_ERR(rdma->dma_mr)) - ib_dereg_mr(rdma->dma_mr); - - if (rdma->qp && !IS_ERR(rdma->qp)) - ib_destroy_qp(rdma->qp); - - if (rdma->pd && !IS_ERR(rdma->pd)) - ib_dealloc_pd(rdma->pd); - - if (rdma->cq && !IS_ERR(rdma->cq)) - ib_destroy_cq(rdma->cq); - - if (rdma->cm_id && !IS_ERR(rdma->cm_id)) - rdma_destroy_id(rdma->cm_id); - - kfree(rdma); -} - -static int -post_recv(struct p9_client *client, struct p9_rdma_context *c) -{ - struct p9_trans_rdma *rdma = client->trans; - struct ib_recv_wr wr, *bad_wr; - struct ib_sge sge; - - c->busa = ib_dma_map_single(rdma->cm_id->device, - c->rc->sdata, client->msize, - DMA_FROM_DEVICE); - if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) - goto error; - - sge.addr = c->busa; - sge.length = client->msize; - sge.lkey = rdma->lkey; - - wr.next = NULL; - c->wc_op = IB_WC_RECV; - wr.wr_id = (unsigned long) c; - wr.sg_list = &sge; - wr.num_sge = 1; - return ib_post_recv(rdma->qp, &wr, &bad_wr); - - error: - p9_debug(P9_DEBUG_ERROR, "EIO\n"); - return -EIO; -} - -static int rdma_request(struct p9_client *client, struct p9_req_t *req) -{ - struct p9_trans_rdma *rdma = client->trans; - struct ib_send_wr wr, *bad_wr; - struct ib_sge sge; - int err = 0; - unsigned long flags; - struct p9_rdma_context *c = NULL; - struct p9_rdma_context *rpl_context = NULL; - - /* Allocate an fcall for the reply */ - rpl_context = kmalloc(sizeof *rpl_context, GFP_NOFS); - if (!rpl_context) { - err = -ENOMEM; - goto err_close; - } - - /* - * If the request has a buffer, steal it, otherwise - * allocate a new one. Typically, requests should already - * have receive buffers allocated and just swap them around - */ - if (!req->rc) { - req->rc = kmalloc(sizeof(struct p9_fcall)+client->msize, - GFP_NOFS); - if (req->rc) { - req->rc->sdata = (char *) req->rc + - sizeof(struct p9_fcall); - req->rc->capacity = client->msize; - } - } - rpl_context->rc = req->rc; - if (!rpl_context->rc) { - err = -ENOMEM; - goto err_free2; - } - - /* - * Post a receive buffer for this request. We need to ensure - * there is a reply buffer available for every outstanding - * request. A flushed request can result in no reply for an - * outstanding request, so we must keep a count to avoid - * overflowing the RQ. - */ - if (atomic_inc_return(&rdma->rq_count) <= rdma->rq_depth) { - err = post_recv(client, rpl_context); - if (err) - goto err_free1; - } else - atomic_dec(&rdma->rq_count); - - /* remove posted receive buffer from request structure */ - req->rc = NULL; - - /* Post the request */ - c = kmalloc(sizeof *c, GFP_NOFS); - if (!c) { - err = -ENOMEM; - goto err_free1; - } - c->req = req; - - c->busa = ib_dma_map_single(rdma->cm_id->device, - c->req->tc->sdata, c->req->tc->size, - DMA_TO_DEVICE); - if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) - goto error; - - sge.addr = c->busa; - sge.length = c->req->tc->size; - sge.lkey = rdma->lkey; - - wr.next = NULL; - c->wc_op = IB_WC_SEND; - wr.wr_id = (unsigned long) c; - wr.opcode = IB_WR_SEND; - wr.send_flags = IB_SEND_SIGNALED; - wr.sg_list = &sge; - wr.num_sge = 1; - - if (down_interruptible(&rdma->sq_sem)) - goto error; - - return ib_post_send(rdma->qp, &wr, &bad_wr); - - error: - kfree(c); - kfree(rpl_context->rc); - kfree(rpl_context); - p9_debug(P9_DEBUG_ERROR, "EIO\n"); - return -EIO; - err_free1: - kfree(rpl_context->rc); - err_free2: - kfree(rpl_context); - err_close: - spin_lock_irqsave(&rdma->req_lock, flags); - if (rdma->state < P9_RDMA_CLOSING) { - rdma->state = P9_RDMA_CLOSING; - spin_unlock_irqrestore(&rdma->req_lock, flags); - rdma_disconnect(rdma->cm_id); - } else - spin_unlock_irqrestore(&rdma->req_lock, flags); - return err; -} - -static void rdma_close(struct p9_client *client) -{ - struct p9_trans_rdma *rdma; - - if (!client) - return; - - rdma = client->trans; - if (!rdma) - return; - - client->status = Disconnected; - rdma_disconnect(rdma->cm_id); - rdma_destroy_trans(rdma); -} - -/** - * alloc_rdma - Allocate and initialize the rdma transport structure - * @opts: Mount options structure - */ -static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts) -{ - struct p9_trans_rdma *rdma; - - rdma = kzalloc(sizeof(struct p9_trans_rdma), GFP_KERNEL); - if (!rdma) - return NULL; - - rdma->sq_depth = opts->sq_depth; - rdma->rq_depth = opts->rq_depth; - rdma->timeout = opts->timeout; - spin_lock_init(&rdma->req_lock); - init_completion(&rdma->cm_done); - sema_init(&rdma->sq_sem, rdma->sq_depth); - atomic_set(&rdma->rq_count, 0); - - return rdma; -} - -/* its not clear to me we can do anything after send has been posted */ -static int rdma_cancel(struct p9_client *client, struct p9_req_t *req) -{ - return 1; -} - -/** - * trans_create_rdma - Transport method for creating atransport instance - * @client: client instance - * @addr: IP address string - * @args: Mount options string - */ -static int -rdma_create_trans(struct p9_client *client, const char *addr, char *args) -{ - int err; - struct p9_rdma_opts opts; - struct p9_trans_rdma *rdma; - struct rdma_conn_param conn_param; - struct ib_qp_init_attr qp_attr; - struct ib_device_attr devattr; - - /* Parse the transport specific mount options */ - err = parse_opts(args, &opts); - if (err < 0) - return err; - - /* Create and initialize the RDMA transport structure */ - rdma = alloc_rdma(&opts); - if (!rdma) - return -ENOMEM; - - /* Create the RDMA CM ID */ - rdma->cm_id = rdma_create_id(p9_cm_event_handler, client, RDMA_PS_TCP, - IB_QPT_RC); - if (IS_ERR(rdma->cm_id)) - goto error; - - /* Associate the client with the transport */ - client->trans = rdma; - - /* Resolve the server's address */ - rdma->addr.sin_family = AF_INET; - rdma->addr.sin_addr.s_addr = in_aton(addr); - rdma->addr.sin_port = htons(opts.port); - err = rdma_resolve_addr(rdma->cm_id, NULL, - (struct sockaddr *)&rdma->addr, - rdma->timeout); - if (err) - goto error; - err = wait_for_completion_interruptible(&rdma->cm_done); - if (err || (rdma->state != P9_RDMA_ADDR_RESOLVED)) - goto error; - - /* Resolve the route to the server */ - err = rdma_resolve_route(rdma->cm_id, rdma->timeout); - if (err) - goto error; - err = wait_for_completion_interruptible(&rdma->cm_done); - if (err || (rdma->state != P9_RDMA_ROUTE_RESOLVED)) - goto error; - - /* Query the device attributes */ - err = ib_query_device(rdma->cm_id->device, &devattr); - if (err) - goto error; - - /* Create the Completion Queue */ - rdma->cq = ib_create_cq(rdma->cm_id->device, cq_comp_handler, - cq_event_handler, client, - opts.sq_depth + opts.rq_depth + 1, 0); - if (IS_ERR(rdma->cq)) - goto error; - ib_req_notify_cq(rdma->cq, IB_CQ_NEXT_COMP); - - /* Create the Protection Domain */ - rdma->pd = ib_alloc_pd(rdma->cm_id->device); - if (IS_ERR(rdma->pd)) - goto error; - - /* Cache the DMA lkey in the transport */ - rdma->dma_mr = NULL; - if (devattr.device_cap_flags & IB_DEVICE_LOCAL_DMA_LKEY) - rdma->lkey = rdma->cm_id->device->local_dma_lkey; - else { - rdma->dma_mr = ib_get_dma_mr(rdma->pd, IB_ACCESS_LOCAL_WRITE); - if (IS_ERR(rdma->dma_mr)) - goto error; - rdma->lkey = rdma->dma_mr->lkey; - } - - /* Create the Queue Pair */ - memset(&qp_attr, 0, sizeof qp_attr); - qp_attr.event_handler = qp_event_handler; - qp_attr.qp_context = client; - qp_attr.cap.max_send_wr = opts.sq_depth; - qp_attr.cap.max_recv_wr = opts.rq_depth; - qp_attr.cap.max_send_sge = P9_RDMA_SEND_SGE; - qp_attr.cap.max_recv_sge = P9_RDMA_RECV_SGE; - qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR; - qp_attr.qp_type = IB_QPT_RC; - qp_attr.send_cq = rdma->cq; - qp_attr.recv_cq = rdma->cq; - err = rdma_create_qp(rdma->cm_id, rdma->pd, &qp_attr); - if (err) - goto error; - rdma->qp = rdma->cm_id->qp; - - /* Request a connection */ - memset(&conn_param, 0, sizeof(conn_param)); - conn_param.private_data = NULL; - conn_param.private_data_len = 0; - conn_param.responder_resources = P9_RDMA_IRD; - conn_param.initiator_depth = P9_RDMA_ORD; - err = rdma_connect(rdma->cm_id, &conn_param); - if (err) - goto error; - err = wait_for_completion_interruptible(&rdma->cm_done); - if (err || (rdma->state != P9_RDMA_CONNECTED)) - goto error; - - client->status = Connected; - - return 0; - -error: - rdma_destroy_trans(rdma); - return -ENOTCONN; -} - -static struct p9_trans_module p9_rdma_trans = { - .name = "rdma", - .maxsize = P9_RDMA_MAXSIZE, - .def = 0, - .owner = THIS_MODULE, - .create = rdma_create_trans, - .close = rdma_close, - .request = rdma_request, - .cancel = rdma_cancel, -}; - -/** - * p9_trans_rdma_init - Register the 9P RDMA transport driver - */ -static int __init p9_trans_rdma_init(void) -{ - v9fs_register_trans(&p9_rdma_trans); - return 0; -} - -static void __exit p9_trans_rdma_exit(void) -{ - v9fs_unregister_trans(&p9_rdma_trans); -} - -module_init(p9_trans_rdma_init); -module_exit(p9_trans_rdma_exit); - -MODULE_AUTHOR("Tom Tucker "); -MODULE_DESCRIPTION("RDMA Transport for 9P"); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/addons/9p/src/3.10.108/trans_virtio.c b/addons/9p/src/3.10.108/trans_virtio.c deleted file mode 100644 index c76a4388..00000000 --- a/addons/9p/src/3.10.108/trans_virtio.c +++ /dev/null @@ -1,730 +0,0 @@ -/* - * The Virtio 9p transport driver - * - * This is a block based transport driver based on the lguest block driver - * code. - * - * Copyright (C) 2007, 2008 Eric Van Hensbergen, IBM Corporation - * - * Based on virtio console driver - * Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "trans_common.h" - -#define VIRTQUEUE_NUM 128 - -/* a single mutex to manage channel initialization and attachment */ -static DEFINE_MUTEX(virtio_9p_lock); -static DECLARE_WAIT_QUEUE_HEAD(vp_wq); -static atomic_t vp_pinned = ATOMIC_INIT(0); - -/** - * struct virtio_chan - per-instance transport information - * @initialized: whether the channel is initialized - * @inuse: whether the channel is in use - * @lock: protects multiple elements within this structure - * @client: client instance - * @vdev: virtio dev associated with this channel - * @vq: virtio queue associated with this channel - * @sg: scatter gather list which is used to pack a request (protected?) - * - * We keep all per-channel information in a structure. - * This structure is allocated within the devices dev->mem space. - * A pointer to the structure will get put in the transport private. - * - */ - -struct virtio_chan { - bool inuse; - - spinlock_t lock; - - struct p9_client *client; - struct virtio_device *vdev; - struct virtqueue *vq; - int ring_bufs_avail; - wait_queue_head_t *vc_wq; - /* This is global limit. Since we don't have a global structure, - * will be placing it in each channel. - */ - unsigned long p9_max_pages; - /* Scatterlist: can be too big for stack. */ - struct scatterlist sg[VIRTQUEUE_NUM]; - - int tag_len; - /* - * tag name to identify a mount Non-null terminated - */ - char *tag; - - struct list_head chan_list; -}; - -static struct list_head virtio_chan_list; - -/* How many bytes left in this page. */ -static unsigned int rest_of_page(void *data) -{ - return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE); -} - -/** - * p9_virtio_close - reclaim resources of a channel - * @client: client instance - * - * This reclaims a channel by freeing its resources and - * reseting its inuse flag. - * - */ - -static void p9_virtio_close(struct p9_client *client) -{ - struct virtio_chan *chan = client->trans; - - mutex_lock(&virtio_9p_lock); - if (chan) - chan->inuse = false; - mutex_unlock(&virtio_9p_lock); -} - -/** - * req_done - callback which signals activity from the server - * @vq: virtio queue activity was received on - * - * This notifies us that the server has triggered some activity - * on the virtio channel - most likely a response to request we - * sent. Figure out which requests now have responses and wake up - * those threads. - * - * Bugs: could do with some additional sanity checking, but appears to work. - * - */ - -static void req_done(struct virtqueue *vq) -{ - struct virtio_chan *chan = vq->vdev->priv; - struct p9_fcall *rc; - unsigned int len; - struct p9_req_t *req; - unsigned long flags; - - p9_debug(P9_DEBUG_TRANS, ": request done\n"); - - while (1) { - spin_lock_irqsave(&chan->lock, flags); - rc = virtqueue_get_buf(chan->vq, &len); - if (rc == NULL) { - spin_unlock_irqrestore(&chan->lock, flags); - break; - } - chan->ring_bufs_avail = 1; - spin_unlock_irqrestore(&chan->lock, flags); - /* Wakeup if anyone waiting for VirtIO ring space. */ - wake_up(chan->vc_wq); - p9_debug(P9_DEBUG_TRANS, ": rc %p\n", rc); - p9_debug(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); - req = p9_tag_lookup(chan->client, rc->tag); - req->status = REQ_STATUS_RCVD; - p9_client_cb(chan->client, req); - } -} - -/** - * pack_sg_list - pack a scatter gather list from a linear buffer - * @sg: scatter/gather list to pack into - * @start: which segment of the sg_list to start at - * @limit: maximum segment to pack data to - * @data: data to pack into scatter/gather list - * @count: amount of data to pack into the scatter/gather list - * - * sg_lists have multiple segments of various sizes. This will pack - * arbitrary data into an existing scatter gather list, segmenting the - * data as necessary within constraints. - * - */ - -static int pack_sg_list(struct scatterlist *sg, int start, - int limit, char *data, int count) -{ - int s; - int index = start; - - while (count) { - s = rest_of_page(data); - if (s > count) - s = count; - BUG_ON(index > limit); - /* Make sure we don't terminate early. */ - sg_unmark_end(&sg[index]); - sg_set_buf(&sg[index++], data, s); - count -= s; - data += s; - } - if (index-start) - sg_mark_end(&sg[index - 1]); - return index-start; -} - -/* We don't currently allow canceling of virtio requests */ -static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req) -{ - return 1; -} - -/** - * pack_sg_list_p - Just like pack_sg_list. Instead of taking a buffer, - * this takes a list of pages. - * @sg: scatter/gather list to pack into - * @start: which segment of the sg_list to start at - * @pdata: a list of pages to add into sg. - * @nr_pages: number of pages to pack into the scatter/gather list - * @data: data to pack into scatter/gather list - * @count: amount of data to pack into the scatter/gather list - */ -static int -pack_sg_list_p(struct scatterlist *sg, int start, int limit, - struct page **pdata, int nr_pages, char *data, int count) -{ - int i = 0, s; - int data_off; - int index = start; - - BUG_ON(nr_pages > (limit - start)); - /* - * if the first page doesn't start at - * page boundary find the offset - */ - data_off = offset_in_page(data); - while (nr_pages) { - s = rest_of_page(data); - if (s > count) - s = count; - /* Make sure we don't terminate early. */ - sg_unmark_end(&sg[index]); - sg_set_page(&sg[index++], pdata[i++], s, data_off); - data_off = 0; - data += s; - count -= s; - nr_pages--; - } - - if (index-start) - sg_mark_end(&sg[index - 1]); - return index - start; -} - -/** - * p9_virtio_request - issue a request - * @client: client instance issuing the request - * @req: request to be issued - * - */ - -static int -p9_virtio_request(struct p9_client *client, struct p9_req_t *req) -{ - int err; - int in, out, out_sgs, in_sgs; - unsigned long flags; - struct virtio_chan *chan = client->trans; - struct scatterlist *sgs[2]; - - p9_debug(P9_DEBUG_TRANS, "9p debug: virtio request\n"); - - req->status = REQ_STATUS_SENT; -req_retry: - spin_lock_irqsave(&chan->lock, flags); - - out_sgs = in_sgs = 0; - /* Handle out VirtIO ring buffers */ - out = pack_sg_list(chan->sg, 0, - VIRTQUEUE_NUM, req->tc->sdata, req->tc->size); - if (out) - sgs[out_sgs++] = chan->sg; - - in = pack_sg_list(chan->sg, out, - VIRTQUEUE_NUM, req->rc->sdata, req->rc->capacity); - if (in) - sgs[out_sgs + in_sgs++] = chan->sg + out; - - err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req->tc, - GFP_ATOMIC); - if (err < 0) { - if (err == -ENOSPC) { - chan->ring_bufs_avail = 0; - spin_unlock_irqrestore(&chan->lock, flags); - err = wait_event_interruptible(*chan->vc_wq, - chan->ring_bufs_avail); - if (err == -ERESTARTSYS) - return err; - - p9_debug(P9_DEBUG_TRANS, "Retry virtio request\n"); - goto req_retry; - } else { - spin_unlock_irqrestore(&chan->lock, flags); - p9_debug(P9_DEBUG_TRANS, - "virtio rpc add_sgs returned failure\n"); - return -EIO; - } - } - virtqueue_kick(chan->vq); - spin_unlock_irqrestore(&chan->lock, flags); - - p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n"); - return 0; -} - -static int p9_get_mapped_pages(struct virtio_chan *chan, - struct page **pages, char *data, - int nr_pages, int write, int kern_buf) -{ - int err; - if (!kern_buf) { - /* - * We allow only p9_max_pages pinned. We wait for the - * Other zc request to finish here - */ - if (atomic_read(&vp_pinned) >= chan->p9_max_pages) { - err = wait_event_interruptible(vp_wq, - (atomic_read(&vp_pinned) < chan->p9_max_pages)); - if (err == -ERESTARTSYS) - return err; - } - err = p9_payload_gup(data, &nr_pages, pages, write); - if (err < 0) - return err; - atomic_add(nr_pages, &vp_pinned); - } else { - /* kernel buffer, no need to pin pages */ - int s, index = 0; - int count = nr_pages; - while (nr_pages) { - s = rest_of_page(data); - if (is_vmalloc_addr(data)) - pages[index++] = vmalloc_to_page(data); - else - pages[index++] = kmap_to_page(data); - data += s; - nr_pages--; - } - nr_pages = count; - } - return nr_pages; -} - -/** - * p9_virtio_zc_request - issue a zero copy request - * @client: client instance issuing the request - * @req: request to be issued - * @uidata: user bffer that should be ued for zero copy read - * @uodata: user buffer that shoud be user for zero copy write - * @inlen: read buffer size - * @olen: write buffer size - * @hdrlen: reader header size, This is the size of response protocol data - * - */ -static int -p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, - char *uidata, char *uodata, int inlen, - int outlen, int in_hdr_len, int kern_buf) -{ - int in, out, err, out_sgs, in_sgs; - unsigned long flags; - int in_nr_pages = 0, out_nr_pages = 0; - struct page **in_pages = NULL, **out_pages = NULL; - struct virtio_chan *chan = client->trans; - struct scatterlist *sgs[4]; - - p9_debug(P9_DEBUG_TRANS, "virtio request\n"); - - if (uodata) { - out_nr_pages = p9_nr_pages(uodata, outlen); - out_pages = kmalloc(sizeof(struct page *) * out_nr_pages, - GFP_NOFS); - if (!out_pages) { - err = -ENOMEM; - goto err_out; - } - out_nr_pages = p9_get_mapped_pages(chan, out_pages, uodata, - out_nr_pages, 0, kern_buf); - if (out_nr_pages < 0) { - err = out_nr_pages; - kfree(out_pages); - out_pages = NULL; - goto err_out; - } - } - if (uidata) { - in_nr_pages = p9_nr_pages(uidata, inlen); - in_pages = kmalloc(sizeof(struct page *) * in_nr_pages, - GFP_NOFS); - if (!in_pages) { - err = -ENOMEM; - goto err_out; - } - in_nr_pages = p9_get_mapped_pages(chan, in_pages, uidata, - in_nr_pages, 1, kern_buf); - if (in_nr_pages < 0) { - err = in_nr_pages; - kfree(in_pages); - in_pages = NULL; - goto err_out; - } - } - req->status = REQ_STATUS_SENT; -req_retry_pinned: - spin_lock_irqsave(&chan->lock, flags); - - out_sgs = in_sgs = 0; - - /* out data */ - out = pack_sg_list(chan->sg, 0, - VIRTQUEUE_NUM, req->tc->sdata, req->tc->size); - - if (out) - sgs[out_sgs++] = chan->sg; - - if (out_pages) { - sgs[out_sgs++] = chan->sg + out; - out += pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM, - out_pages, out_nr_pages, uodata, outlen); - } - - /* - * Take care of in data - * For example TREAD have 11. - * 11 is the read/write header = PDU Header(7) + IO Size (4). - * Arrange in such a way that server places header in the - * alloced memory and payload onto the user buffer. - */ - in = pack_sg_list(chan->sg, out, - VIRTQUEUE_NUM, req->rc->sdata, in_hdr_len); - if (in) - sgs[out_sgs + in_sgs++] = chan->sg + out; - - if (in_pages) { - sgs[out_sgs + in_sgs++] = chan->sg + out + in; - in += pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM, - in_pages, in_nr_pages, uidata, inlen); - } - - BUG_ON(out_sgs + in_sgs > ARRAY_SIZE(sgs)); - err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req->tc, - GFP_ATOMIC); - if (err < 0) { - if (err == -ENOSPC) { - chan->ring_bufs_avail = 0; - spin_unlock_irqrestore(&chan->lock, flags); - err = wait_event_interruptible(*chan->vc_wq, - chan->ring_bufs_avail); - if (err == -ERESTARTSYS) - goto err_out; - - p9_debug(P9_DEBUG_TRANS, "Retry virtio request\n"); - goto req_retry_pinned; - } else { - spin_unlock_irqrestore(&chan->lock, flags); - p9_debug(P9_DEBUG_TRANS, - "virtio rpc add_sgs returned failure\n"); - err = -EIO; - goto err_out; - } - } - virtqueue_kick(chan->vq); - spin_unlock_irqrestore(&chan->lock, flags); - p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n"); - err = wait_event_interruptible(*req->wq, - req->status >= REQ_STATUS_RCVD); - /* - * Non kernel buffers are pinned, unpin them - */ -err_out: - if (!kern_buf) { - if (in_pages) { - p9_release_pages(in_pages, in_nr_pages); - atomic_sub(in_nr_pages, &vp_pinned); - } - if (out_pages) { - p9_release_pages(out_pages, out_nr_pages); - atomic_sub(out_nr_pages, &vp_pinned); - } - /* wakeup anybody waiting for slots to pin pages */ - wake_up(&vp_wq); - } - kfree(in_pages); - kfree(out_pages); - return err; -} - -static ssize_t p9_mount_tag_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct virtio_chan *chan; - struct virtio_device *vdev; - - vdev = dev_to_virtio(dev); - chan = vdev->priv; - - return snprintf(buf, chan->tag_len + 1, "%s", chan->tag); -} - -static DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL); - -/** - * p9_virtio_probe - probe for existence of 9P virtio channels - * @vdev: virtio device to probe - * - * This probes for existing virtio channels. - * - */ - -static int p9_virtio_probe(struct virtio_device *vdev) -{ - __u16 tag_len; - char *tag; - int err; - struct virtio_chan *chan; - - chan = kmalloc(sizeof(struct virtio_chan), GFP_KERNEL); - if (!chan) { - pr_err("Failed to allocate virtio 9P channel\n"); - err = -ENOMEM; - goto fail; - } - - chan->vdev = vdev; - - /* We expect one virtqueue, for requests. */ - chan->vq = virtio_find_single_vq(vdev, req_done, "requests"); - if (IS_ERR(chan->vq)) { - err = PTR_ERR(chan->vq); - goto out_free_vq; - } - chan->vq->vdev->priv = chan; - spin_lock_init(&chan->lock); - - sg_init_table(chan->sg, VIRTQUEUE_NUM); - - chan->inuse = false; - if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) { - vdev->config->get(vdev, - offsetof(struct virtio_9p_config, tag_len), - &tag_len, sizeof(tag_len)); - } else { - err = -EINVAL; - goto out_free_vq; - } - tag = kmalloc(tag_len, GFP_KERNEL); - if (!tag) { - err = -ENOMEM; - goto out_free_vq; - } - vdev->config->get(vdev, offsetof(struct virtio_9p_config, tag), - tag, tag_len); - chan->tag = tag; - chan->tag_len = tag_len; - err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); - if (err) { - goto out_free_tag; - } - chan->vc_wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); - if (!chan->vc_wq) { - err = -ENOMEM; - goto out_free_tag; - } - init_waitqueue_head(chan->vc_wq); - chan->ring_bufs_avail = 1; - /* Ceiling limit to avoid denial of service attacks */ - chan->p9_max_pages = nr_free_buffer_pages()/4; - - mutex_lock(&virtio_9p_lock); - list_add_tail(&chan->chan_list, &virtio_chan_list); - mutex_unlock(&virtio_9p_lock); - - /* Let udev rules use the new mount_tag attribute. */ - kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); - - return 0; - -out_free_tag: - kfree(tag); -out_free_vq: - vdev->config->del_vqs(vdev); - kfree(chan); -fail: - return err; -} - - -/** - * p9_virtio_create - allocate a new virtio channel - * @client: client instance invoking this transport - * @devname: string identifying the channel to connect to (unused) - * @args: args passed from sys_mount() for per-transport options (unused) - * - * This sets up a transport channel for 9p communication. Right now - * we only match the first available channel, but eventually we couldlook up - * alternate channels by matching devname versus a virtio_config entry. - * We use a simple reference count mechanism to ensure that only a single - * mount has a channel open at a time. - * - */ - -static int -p9_virtio_create(struct p9_client *client, const char *devname, char *args) -{ - struct virtio_chan *chan; - int ret = -ENOENT; - int found = 0; - - mutex_lock(&virtio_9p_lock); - list_for_each_entry(chan, &virtio_chan_list, chan_list) { - if (!strncmp(devname, chan->tag, chan->tag_len) && - strlen(devname) == chan->tag_len) { - if (!chan->inuse) { - chan->inuse = true; - found = 1; - break; - } - ret = -EBUSY; - } - } - mutex_unlock(&virtio_9p_lock); - - if (!found) { - pr_err("no channels available\n"); - return ret; - } - - client->trans = (void *)chan; - client->status = Connected; - chan->client = client; - - return 0; -} - -/** - * p9_virtio_remove - clean up resources associated with a virtio device - * @vdev: virtio device to remove - * - */ - -static void p9_virtio_remove(struct virtio_device *vdev) -{ - struct virtio_chan *chan = vdev->priv; - - if (chan->inuse) - p9_virtio_close(chan->client); - vdev->config->del_vqs(vdev); - - mutex_lock(&virtio_9p_lock); - list_del(&chan->chan_list); - mutex_unlock(&virtio_9p_lock); - sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); - kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); - kfree(chan->tag); - kfree(chan->vc_wq); - kfree(chan); - -} - -static struct virtio_device_id id_table[] = { - { VIRTIO_ID_9P, VIRTIO_DEV_ANY_ID }, - { 0 }, -}; - -static unsigned int features[] = { - VIRTIO_9P_MOUNT_TAG, -}; - -/* The standard "struct lguest_driver": */ -static struct virtio_driver p9_virtio_drv = { - .feature_table = features, - .feature_table_size = ARRAY_SIZE(features), - .driver.name = KBUILD_MODNAME, - .driver.owner = THIS_MODULE, - .id_table = id_table, - .probe = p9_virtio_probe, - .remove = p9_virtio_remove, -}; - -static struct p9_trans_module p9_virtio_trans = { - .name = "virtio", - .create = p9_virtio_create, - .close = p9_virtio_close, - .request = p9_virtio_request, - .zc_request = p9_virtio_zc_request, - .cancel = p9_virtio_cancel, - /* - * We leave one entry for input and one entry for response - * headers. We also skip one more entry to accomodate, address - * that are not at page boundary, that can result in an extra - * page in zero copy. - */ - .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3), - .def = 0, - .owner = THIS_MODULE, -}; - -/* The standard init function */ -static int __init p9_virtio_init(void) -{ - INIT_LIST_HEAD(&virtio_chan_list); - - v9fs_register_trans(&p9_virtio_trans); - return register_virtio_driver(&p9_virtio_drv); -} - -static void __exit p9_virtio_cleanup(void) -{ - unregister_virtio_driver(&p9_virtio_drv); - v9fs_unregister_trans(&p9_virtio_trans); -} - -module_init(p9_virtio_init); -module_exit(p9_virtio_cleanup); - -MODULE_DEVICE_TABLE(virtio, id_table); -MODULE_AUTHOR("Eric Van Hensbergen "); -MODULE_DESCRIPTION("Virtio 9p Transport"); -MODULE_LICENSE("GPL"); diff --git a/addons/9p/src/3.10.108/util.c b/addons/9p/src/3.10.108/util.c deleted file mode 100644 index 59f278e6..00000000 --- a/addons/9p/src/3.10.108/util.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * net/9p/util.c - * - * This file contains some helper functions - * - * Copyright (C) 2007 by Latchesar Ionkov - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * struct p9_idpool - per-connection accounting for tag idpool - * @lock: protects the pool - * @pool: idr to allocate tag id from - * - */ - -struct p9_idpool { - spinlock_t lock; - struct idr pool; -}; - -/** - * p9_idpool_create - create a new per-connection id pool - * - */ - -struct p9_idpool *p9_idpool_create(void) -{ - struct p9_idpool *p; - - p = kmalloc(sizeof(struct p9_idpool), GFP_KERNEL); - if (!p) - return ERR_PTR(-ENOMEM); - - spin_lock_init(&p->lock); - idr_init(&p->pool); - - return p; -} -EXPORT_SYMBOL(p9_idpool_create); - -/** - * p9_idpool_destroy - create a new per-connection id pool - * @p: idpool to destroy - */ - -void p9_idpool_destroy(struct p9_idpool *p) -{ - idr_destroy(&p->pool); - kfree(p); -} -EXPORT_SYMBOL(p9_idpool_destroy); - -/** - * p9_idpool_get - allocate numeric id from pool - * @p: pool to allocate from - * - * Bugs: This seems to be an awful generic function, should it be in idr.c with - * the lock included in struct idr? - */ - -int p9_idpool_get(struct p9_idpool *p) -{ - int i; - unsigned long flags; - - idr_preload(GFP_NOFS); - spin_lock_irqsave(&p->lock, flags); - - /* no need to store exactly p, we just need something non-null */ - i = idr_alloc(&p->pool, p, 0, 0, GFP_NOWAIT); - - spin_unlock_irqrestore(&p->lock, flags); - idr_preload_end(); - if (i < 0) - return -1; - - p9_debug(P9_DEBUG_MUX, " id %d pool %p\n", i, p); - return i; -} -EXPORT_SYMBOL(p9_idpool_get); - -/** - * p9_idpool_put - release numeric id from pool - * @id: numeric id which is being released - * @p: pool to release id into - * - * Bugs: This seems to be an awful generic function, should it be in idr.c with - * the lock included in struct idr? - */ - -void p9_idpool_put(int id, struct p9_idpool *p) -{ - unsigned long flags; - - p9_debug(P9_DEBUG_MUX, " id %d pool %p\n", id, p); - - spin_lock_irqsave(&p->lock, flags); - idr_remove(&p->pool, id); - spin_unlock_irqrestore(&p->lock, flags); -} -EXPORT_SYMBOL(p9_idpool_put); - -/** - * p9_idpool_check - check if the specified id is available - * @id: id to check - * @p: pool to check - */ - -int p9_idpool_check(int id, struct p9_idpool *p) -{ - return idr_find(&p->pool, id) != NULL; -} -EXPORT_SYMBOL(p9_idpool_check); - diff --git a/addons/9p/src/3.10.108/v9fs.c b/addons/9p/src/3.10.108/v9fs.c deleted file mode 100644 index 58e6cbce..00000000 --- a/addons/9p/src/3.10.108/v9fs.c +++ /dev/null @@ -1,677 +0,0 @@ -/* - * linux/fs/9p/v9fs.c - * - * This file contains functions assisting in mapping VFS to 9P2000 - * - * Copyright (C) 2004-2008 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "cache.h" - -static DEFINE_SPINLOCK(v9fs_sessionlist_lock); -static LIST_HEAD(v9fs_sessionlist); -struct kmem_cache *v9fs_inode_cache; - -/* - * Option Parsing (code inspired by NFS code) - * NOTE: each transport will parse its own options - */ - -enum { - /* Options that take integer arguments */ - Opt_debug, Opt_dfltuid, Opt_dfltgid, Opt_afid, - /* String options */ - Opt_uname, Opt_remotename, Opt_trans, Opt_cache, Opt_cachetag, - /* Options that take no arguments */ - Opt_nodevmap, - /* Cache options */ - Opt_cache_loose, Opt_fscache, - /* Access options */ - Opt_access, Opt_posixacl, - /* Error token */ - Opt_err -}; - -static const match_table_t tokens = { - {Opt_debug, "debug=%x"}, - {Opt_dfltuid, "dfltuid=%u"}, - {Opt_dfltgid, "dfltgid=%u"}, - {Opt_afid, "afid=%u"}, - {Opt_uname, "uname=%s"}, - {Opt_remotename, "aname=%s"}, - {Opt_nodevmap, "nodevmap"}, - {Opt_cache, "cache=%s"}, - {Opt_cache_loose, "loose"}, - {Opt_fscache, "fscache"}, - {Opt_cachetag, "cachetag=%s"}, - {Opt_access, "access=%s"}, - {Opt_posixacl, "posixacl"}, - {Opt_err, NULL} -}; - -/* Interpret mount options for cache mode */ -static int get_cache_mode(char *s) -{ - int version = -EINVAL; - - if (!strcmp(s, "loose")) { - version = CACHE_LOOSE; - p9_debug(P9_DEBUG_9P, "Cache mode: loose\n"); - } else if (!strcmp(s, "fscache")) { - version = CACHE_FSCACHE; - p9_debug(P9_DEBUG_9P, "Cache mode: fscache\n"); - } else if (!strcmp(s, "none")) { - version = CACHE_NONE; - p9_debug(P9_DEBUG_9P, "Cache mode: none\n"); - } else - pr_info("Unknown Cache mode %s\n", s); - return version; -} - -/** - * v9fs_parse_options - parse mount options into session structure - * @v9ses: existing v9fs session information - * - * Return 0 upon success, -ERRNO upon failure. - */ - -static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) -{ - char *options, *tmp_options; - substring_t args[MAX_OPT_ARGS]; - char *p; - int option = 0; - char *s, *e; - int ret = 0; - - /* setup defaults */ - v9ses->afid = ~0; - v9ses->debug = 0; - v9ses->cache = CACHE_NONE; -#ifdef CONFIG_9P_FSCACHE - v9ses->cachetag = NULL; -#endif - - if (!opts) - return 0; - - tmp_options = kstrdup(opts, GFP_KERNEL); - if (!tmp_options) { - ret = -ENOMEM; - goto fail_option_alloc; - } - options = tmp_options; - - while ((p = strsep(&options, ",")) != NULL) { - int token, r; - if (!*p) - continue; - token = match_token(p, tokens, args); - switch (token) { - case Opt_debug: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - v9ses->debug = option; -#ifdef CONFIG_NET_9P_DEBUG - p9_debug_level = option; -#endif - break; - - case Opt_dfltuid: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - v9ses->dfltuid = make_kuid(current_user_ns(), option); - if (!uid_valid(v9ses->dfltuid)) { - p9_debug(P9_DEBUG_ERROR, - "uid field, but not a uid?\n"); - ret = -EINVAL; - continue; - } - break; - case Opt_dfltgid: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - v9ses->dfltgid = make_kgid(current_user_ns(), option); - if (!gid_valid(v9ses->dfltgid)) { - p9_debug(P9_DEBUG_ERROR, - "gid field, but not a gid?\n"); - ret = -EINVAL; - continue; - } - break; - case Opt_afid: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - v9ses->afid = option; - break; - case Opt_uname: - kfree(v9ses->uname); - v9ses->uname = match_strdup(&args[0]); - if (!v9ses->uname) { - ret = -ENOMEM; - goto free_and_return; - } - break; - case Opt_remotename: - kfree(v9ses->aname); - v9ses->aname = match_strdup(&args[0]); - if (!v9ses->aname) { - ret = -ENOMEM; - goto free_and_return; - } - break; - case Opt_nodevmap: - v9ses->nodev = 1; - break; - case Opt_cache_loose: - v9ses->cache = CACHE_LOOSE; - break; - case Opt_fscache: - v9ses->cache = CACHE_FSCACHE; - break; - case Opt_cachetag: -#ifdef CONFIG_9P_FSCACHE - v9ses->cachetag = match_strdup(&args[0]); -#endif - break; - case Opt_cache: - s = match_strdup(&args[0]); - if (!s) { - ret = -ENOMEM; - p9_debug(P9_DEBUG_ERROR, - "problem allocating copy of cache arg\n"); - goto free_and_return; - } - ret = get_cache_mode(s); - if (ret == -EINVAL) { - kfree(s); - goto free_and_return; - } - - v9ses->cache = ret; - kfree(s); - break; - - case Opt_access: - s = match_strdup(&args[0]); - if (!s) { - ret = -ENOMEM; - p9_debug(P9_DEBUG_ERROR, - "problem allocating copy of access arg\n"); - goto free_and_return; - } - - v9ses->flags &= ~V9FS_ACCESS_MASK; - if (strcmp(s, "user") == 0) - v9ses->flags |= V9FS_ACCESS_USER; - else if (strcmp(s, "any") == 0) - v9ses->flags |= V9FS_ACCESS_ANY; - else if (strcmp(s, "client") == 0) { - v9ses->flags |= V9FS_ACCESS_CLIENT; - } else { - uid_t uid; - v9ses->flags |= V9FS_ACCESS_SINGLE; - uid = simple_strtoul(s, &e, 10); - if (*e != '\0') { - ret = -EINVAL; - pr_info("Unknown access argument %s\n", - s); - kfree(s); - goto free_and_return; - } - v9ses->uid = make_kuid(current_user_ns(), uid); - if (!uid_valid(v9ses->uid)) { - ret = -EINVAL; - pr_info("Uknown uid %s\n", s); - kfree(s); - goto free_and_return; - } - } - - kfree(s); - break; - - case Opt_posixacl: -#ifdef CONFIG_9P_FS_POSIX_ACL - v9ses->flags |= V9FS_POSIX_ACL; -#else - p9_debug(P9_DEBUG_ERROR, - "Not defined CONFIG_9P_FS_POSIX_ACL. Ignoring posixacl option\n"); -#endif - break; - - default: - continue; - } - } - -free_and_return: - kfree(tmp_options); -fail_option_alloc: - return ret; -} - -/** - * v9fs_session_init - initialize session - * @v9ses: session information structure - * @dev_name: device being mounted - * @data: options - * - */ - -struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, - const char *dev_name, char *data) -{ - int retval = -EINVAL; - struct p9_fid *fid; - int rc; - - v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL); - if (!v9ses->uname) - return ERR_PTR(-ENOMEM); - - v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL); - if (!v9ses->aname) { - kfree(v9ses->uname); - return ERR_PTR(-ENOMEM); - } - init_rwsem(&v9ses->rename_sem); - - rc = bdi_setup_and_register(&v9ses->bdi, "9p", BDI_CAP_MAP_COPY); - if (rc) { - kfree(v9ses->aname); - kfree(v9ses->uname); - return ERR_PTR(rc); - } - - spin_lock(&v9fs_sessionlist_lock); - list_add(&v9ses->slist, &v9fs_sessionlist); - spin_unlock(&v9fs_sessionlist_lock); - - v9ses->uid = INVALID_UID; - v9ses->dfltuid = V9FS_DEFUID; - v9ses->dfltgid = V9FS_DEFGID; - - v9ses->clnt = p9_client_create(dev_name, data); - if (IS_ERR(v9ses->clnt)) { - retval = PTR_ERR(v9ses->clnt); - v9ses->clnt = NULL; - p9_debug(P9_DEBUG_ERROR, "problem initializing 9p client\n"); - goto error; - } - - v9ses->flags = V9FS_ACCESS_USER; - - if (p9_is_proto_dotl(v9ses->clnt)) { - v9ses->flags = V9FS_ACCESS_CLIENT; - v9ses->flags |= V9FS_PROTO_2000L; - } else if (p9_is_proto_dotu(v9ses->clnt)) { - v9ses->flags |= V9FS_PROTO_2000U; - } - - rc = v9fs_parse_options(v9ses, data); - if (rc < 0) { - retval = rc; - goto error; - } - - v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ; - - if (!v9fs_proto_dotl(v9ses) && - ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) { - /* - * We support ACCESS_CLIENT only for dotl. - * Fall back to ACCESS_USER - */ - v9ses->flags &= ~V9FS_ACCESS_MASK; - v9ses->flags |= V9FS_ACCESS_USER; - } - /*FIXME !! */ - /* for legacy mode, fall back to V9FS_ACCESS_ANY */ - if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) && - ((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) { - - v9ses->flags &= ~V9FS_ACCESS_MASK; - v9ses->flags |= V9FS_ACCESS_ANY; - v9ses->uid = INVALID_UID; - } - if (!v9fs_proto_dotl(v9ses) || - !((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) { - /* - * We support ACL checks on clinet only if the protocol is - * 9P2000.L and access is V9FS_ACCESS_CLIENT. - */ - v9ses->flags &= ~V9FS_ACL_MASK; - } - - fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, INVALID_UID, - v9ses->aname); - if (IS_ERR(fid)) { - retval = PTR_ERR(fid); - fid = NULL; - p9_debug(P9_DEBUG_ERROR, "cannot attach\n"); - goto error; - } - - if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_SINGLE) - fid->uid = v9ses->uid; - else - fid->uid = INVALID_UID; - -#ifdef CONFIG_9P_FSCACHE - /* register the session for caching */ - v9fs_cache_session_get_cookie(v9ses); -#endif - - return fid; - -error: - bdi_destroy(&v9ses->bdi); - return ERR_PTR(retval); -} - -/** - * v9fs_session_close - shutdown a session - * @v9ses: session information structure - * - */ - -void v9fs_session_close(struct v9fs_session_info *v9ses) -{ - if (v9ses->clnt) { - p9_client_destroy(v9ses->clnt); - v9ses->clnt = NULL; - } - -#ifdef CONFIG_9P_FSCACHE - if (v9ses->fscache) { - v9fs_cache_session_put_cookie(v9ses); - kfree(v9ses->cachetag); - } -#endif - kfree(v9ses->uname); - kfree(v9ses->aname); - - bdi_destroy(&v9ses->bdi); - - spin_lock(&v9fs_sessionlist_lock); - list_del(&v9ses->slist); - spin_unlock(&v9fs_sessionlist_lock); -} - -/** - * v9fs_session_cancel - terminate a session - * @v9ses: session to terminate - * - * mark transport as disconnected and cancel all pending requests. - */ - -void v9fs_session_cancel(struct v9fs_session_info *v9ses) { - p9_debug(P9_DEBUG_ERROR, "cancel session %p\n", v9ses); - p9_client_disconnect(v9ses->clnt); -} - -/** - * v9fs_session_begin_cancel - Begin terminate of a session - * @v9ses: session to terminate - * - * After this call we don't allow any request other than clunk. - */ - -void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses) -{ - p9_debug(P9_DEBUG_ERROR, "begin cancel session %p\n", v9ses); - p9_client_begin_disconnect(v9ses->clnt); -} - -extern int v9fs_error_init(void); - -static struct kobject *v9fs_kobj; - -#ifdef CONFIG_9P_FSCACHE -/** - * caches_show - list caches associated with a session - * - * Returns the size of buffer written. - */ - -static ssize_t caches_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - ssize_t n = 0, count = 0, limit = PAGE_SIZE; - struct v9fs_session_info *v9ses; - - spin_lock(&v9fs_sessionlist_lock); - list_for_each_entry(v9ses, &v9fs_sessionlist, slist) { - if (v9ses->cachetag) { - n = snprintf(buf, limit, "%s\n", v9ses->cachetag); - if (n < 0) { - count = n; - break; - } - - count += n; - limit -= n; - } - } - - spin_unlock(&v9fs_sessionlist_lock); - return count; -} - -static struct kobj_attribute v9fs_attr_cache = __ATTR_RO(caches); -#endif /* CONFIG_9P_FSCACHE */ - -static struct attribute *v9fs_attrs[] = { -#ifdef CONFIG_9P_FSCACHE - &v9fs_attr_cache.attr, -#endif - NULL, -}; - -static struct attribute_group v9fs_attr_group = { - .attrs = v9fs_attrs, -}; - -/** - * v9fs_sysfs_init - Initialize the v9fs sysfs interface - * - */ - -static int v9fs_sysfs_init(void) -{ - v9fs_kobj = kobject_create_and_add("9p", fs_kobj); - if (!v9fs_kobj) - return -ENOMEM; - - if (sysfs_create_group(v9fs_kobj, &v9fs_attr_group)) { - kobject_put(v9fs_kobj); - return -ENOMEM; - } - - return 0; -} - -/** - * v9fs_sysfs_cleanup - Unregister the v9fs sysfs interface - * - */ - -static void v9fs_sysfs_cleanup(void) -{ - sysfs_remove_group(v9fs_kobj, &v9fs_attr_group); - kobject_put(v9fs_kobj); -} - -static void v9fs_inode_init_once(void *foo) -{ - struct v9fs_inode *v9inode = (struct v9fs_inode *)foo; -#ifdef CONFIG_9P_FSCACHE - v9inode->fscache = NULL; -#endif - memset(&v9inode->qid, 0, sizeof(v9inode->qid)); - inode_init_once(&v9inode->vfs_inode); -} - -/** - * v9fs_init_inode_cache - initialize a cache for 9P - * Returns 0 on success. - */ -static int v9fs_init_inode_cache(void) -{ - v9fs_inode_cache = kmem_cache_create("v9fs_inode_cache", - sizeof(struct v9fs_inode), - 0, (SLAB_RECLAIM_ACCOUNT| - SLAB_MEM_SPREAD), - v9fs_inode_init_once); - if (!v9fs_inode_cache) - return -ENOMEM; - - return 0; -} - -/** - * v9fs_destroy_inode_cache - destroy the cache of 9P inode - * - */ -static void v9fs_destroy_inode_cache(void) -{ - /* - * Make sure all delayed rcu free inodes are flushed before we - * destroy cache. - */ - rcu_barrier(); - kmem_cache_destroy(v9fs_inode_cache); -} - -static int v9fs_cache_register(void) -{ - int ret; - ret = v9fs_init_inode_cache(); - if (ret < 0) - return ret; -#ifdef CONFIG_9P_FSCACHE - return fscache_register_netfs(&v9fs_cache_netfs); -#else - return ret; -#endif -} - -static void v9fs_cache_unregister(void) -{ - v9fs_destroy_inode_cache(); -#ifdef CONFIG_9P_FSCACHE - fscache_unregister_netfs(&v9fs_cache_netfs); -#endif -} - -/** - * init_v9fs - Initialize module - * - */ - -static int __init init_v9fs(void) -{ - int err; - pr_info("Installing v9fs 9p2000 file system support\n"); - /* TODO: Setup list of registered trasnport modules */ - - err = v9fs_cache_register(); - if (err < 0) { - pr_err("Failed to register v9fs for caching\n"); - return err; - } - - err = v9fs_sysfs_init(); - if (err < 0) { - pr_err("Failed to register with sysfs\n"); - goto out_cache; - } - err = register_filesystem(&v9fs_fs_type); - if (err < 0) { - pr_err("Failed to register filesystem\n"); - goto out_sysfs_cleanup; - } - - return 0; - -out_sysfs_cleanup: - v9fs_sysfs_cleanup(); - -out_cache: - v9fs_cache_unregister(); - - return err; -} - -/** - * exit_v9fs - shutdown module - * - */ - -static void __exit exit_v9fs(void) -{ - v9fs_sysfs_cleanup(); - v9fs_cache_unregister(); - unregister_filesystem(&v9fs_fs_type); -} - -module_init(init_v9fs) -module_exit(exit_v9fs) - -MODULE_AUTHOR("Latchesar Ionkov "); -MODULE_AUTHOR("Eric Van Hensbergen "); -MODULE_AUTHOR("Ron Minnich "); -MODULE_LICENSE("GPL"); diff --git a/addons/9p/src/3.10.108/v9fs.h b/addons/9p/src/3.10.108/v9fs.h deleted file mode 100644 index a8e127c8..00000000 --- a/addons/9p/src/3.10.108/v9fs.h +++ /dev/null @@ -1,227 +0,0 @@ -/* - * V9FS definitions. - * - * Copyright (C) 2004-2008 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ -#ifndef FS_9P_V9FS_H -#define FS_9P_V9FS_H - -#include - -/** - * enum p9_session_flags - option flags for each 9P session - * @V9FS_PROTO_2000U: whether or not to use 9P2000.u extensions - * @V9FS_PROTO_2000L: whether or not to use 9P2000.l extensions - * @V9FS_ACCESS_SINGLE: only the mounting user can access the hierarchy - * @V9FS_ACCESS_USER: a new attach will be issued for every user (default) - * @V9FS_ACCESS_CLIENT: Just like user, but access check is performed on client. - * @V9FS_ACCESS_ANY: use a single attach for all users - * @V9FS_ACCESS_MASK: bit mask of different ACCESS options - * @V9FS_POSIX_ACL: POSIX ACLs are enforced - * - * Session flags reflect options selected by users at mount time - */ -#define V9FS_ACCESS_ANY (V9FS_ACCESS_SINGLE | \ - V9FS_ACCESS_USER | \ - V9FS_ACCESS_CLIENT) -#define V9FS_ACCESS_MASK V9FS_ACCESS_ANY -#define V9FS_ACL_MASK V9FS_POSIX_ACL - -enum p9_session_flags { - V9FS_PROTO_2000U = 0x01, - V9FS_PROTO_2000L = 0x02, - V9FS_ACCESS_SINGLE = 0x04, - V9FS_ACCESS_USER = 0x08, - V9FS_ACCESS_CLIENT = 0x10, - V9FS_POSIX_ACL = 0x20 -}; - -/* possible values of ->cache */ -/** - * enum p9_cache_modes - user specified cache preferences - * @CACHE_NONE: do not cache data, dentries, or directory contents (default) - * @CACHE_LOOSE: cache data, dentries, and directory contents w/no consistency - * - * eventually support loose, tight, time, session, default always none - */ - -enum p9_cache_modes { - CACHE_NONE, - CACHE_LOOSE, - CACHE_FSCACHE, -}; - -/** - * struct v9fs_session_info - per-instance session information - * @flags: session options of type &p9_session_flags - * @nodev: set to 1 to disable device mapping - * @debug: debug level - * @afid: authentication handle - * @cache: cache mode of type &p9_cache_modes - * @cachetag: the tag of the cache associated with this session - * @fscache: session cookie associated with FS-Cache - * @options: copy of options string given by user - * @uname: string user name to mount hierarchy as - * @aname: mount specifier for remote hierarchy - * @maxdata: maximum data to be sent/recvd per protocol message - * @dfltuid: default numeric userid to mount hierarchy as - * @dfltgid: default numeric groupid to mount hierarchy as - * @uid: if %V9FS_ACCESS_SINGLE, the numeric uid which mounted the hierarchy - * @clnt: reference to 9P network client instantiated for this session - * @slist: reference to list of registered 9p sessions - * - * This structure holds state for each session instance established during - * a sys_mount() . - * - * Bugs: there seems to be a lot of state which could be condensed and/or - * removed. - */ - -struct v9fs_session_info { - /* options */ - unsigned char flags; - unsigned char nodev; - unsigned short debug; - unsigned int afid; - unsigned int cache; -#ifdef CONFIG_9P_FSCACHE - char *cachetag; - struct fscache_cookie *fscache; -#endif - - char *uname; /* user name to mount as */ - char *aname; /* name of remote hierarchy being mounted */ - unsigned int maxdata; /* max data for client interface */ - kuid_t dfltuid; /* default uid/muid for legacy support */ - kgid_t dfltgid; /* default gid for legacy support */ - kuid_t uid; /* if ACCESS_SINGLE, the uid that has access */ - struct p9_client *clnt; /* 9p client */ - struct list_head slist; /* list of sessions registered with v9fs */ - struct backing_dev_info bdi; - struct rw_semaphore rename_sem; -}; - -/* cache_validity flags */ -#define V9FS_INO_INVALID_ATTR 0x01 - -struct v9fs_inode { -#ifdef CONFIG_9P_FSCACHE - spinlock_t fscache_lock; - struct fscache_cookie *fscache; -#endif - struct p9_qid qid; - unsigned int cache_validity; - struct p9_fid *writeback_fid; - struct mutex v_mutex; - struct inode vfs_inode; -}; - -static inline struct v9fs_inode *V9FS_I(const struct inode *inode) -{ - return container_of(inode, struct v9fs_inode, vfs_inode); -} - -struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *, - char *); -extern void v9fs_session_close(struct v9fs_session_info *v9ses); -extern void v9fs_session_cancel(struct v9fs_session_info *v9ses); -extern void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses); -extern struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, - unsigned int flags); -extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d); -extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d); -extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry); -extern void v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, - void *p); -extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses, - struct p9_fid *fid, - struct super_block *sb, int new); -extern const struct inode_operations v9fs_dir_inode_operations_dotl; -extern const struct inode_operations v9fs_file_inode_operations_dotl; -extern const struct inode_operations v9fs_symlink_inode_operations_dotl; -extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, - struct p9_fid *fid, - struct super_block *sb, int new); - -/* other default globals */ -#define V9FS_PORT 564 -#define V9FS_DEFUSER "nobody" -#define V9FS_DEFANAME "" -#define V9FS_DEFUID KUIDT_INIT(-2) -#define V9FS_DEFGID KGIDT_INIT(-2) - -static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode) -{ - return (inode->i_sb->s_fs_info); -} - -static inline struct v9fs_session_info *v9fs_dentry2v9ses(struct dentry *dentry) -{ - return dentry->d_sb->s_fs_info; -} - -static inline int v9fs_proto_dotu(struct v9fs_session_info *v9ses) -{ - return v9ses->flags & V9FS_PROTO_2000U; -} - -static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses) -{ - return v9ses->flags & V9FS_PROTO_2000L; -} - -/** - * v9fs_get_inode_from_fid - Helper routine to populate an inode by - * issuing a attribute request - * @v9ses: session information - * @fid: fid to issue attribute request for - * @sb: superblock on which to create inode - * - */ -static inline struct inode * -v9fs_get_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, - struct super_block *sb) -{ - if (v9fs_proto_dotl(v9ses)) - return v9fs_inode_from_fid_dotl(v9ses, fid, sb, 0); - else - return v9fs_inode_from_fid(v9ses, fid, sb, 0); -} - -/** - * v9fs_get_new_inode_from_fid - Helper routine to populate an inode by - * issuing a attribute request - * @v9ses: session information - * @fid: fid to issue attribute request for - * @sb: superblock on which to create inode - * - */ -static inline struct inode * -v9fs_get_new_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, - struct super_block *sb) -{ - if (v9fs_proto_dotl(v9ses)) - return v9fs_inode_from_fid_dotl(v9ses, fid, sb, 1); - else - return v9fs_inode_from_fid(v9ses, fid, sb, 1); -} - -#endif diff --git a/addons/9p/src/3.10.108/v9fs_vfs.h b/addons/9p/src/3.10.108/v9fs_vfs.h deleted file mode 100644 index dc95a252..00000000 --- a/addons/9p/src/3.10.108/v9fs_vfs.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * V9FS VFS extensions. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ -#ifndef FS_9P_V9FS_VFS_H -#define FS_9P_V9FS_VFS_H - -/* plan9 semantics are that created files are implicitly opened. - * But linux semantics are that you call create, then open. - * the plan9 approach is superior as it provides an atomic - * open. - * we track the create fid here. When the file is opened, if fidopen is - * non-zero, we use the fid and can skip some steps. - * there may be a better way to do this, but I don't know it. - * one BAD way is to clunk the fid on create, then open it again: - * you lose the atomicity of file open - */ - -/* special case: - * unlink calls remove, which is an implicit clunk. So we have to track - * that kind of thing so that we don't try to clunk a dead fid. - */ -#define P9_LOCK_TIMEOUT (30*HZ) - -extern struct file_system_type v9fs_fs_type; -extern const struct address_space_operations v9fs_addr_operations; -extern const struct file_operations v9fs_file_operations; -extern const struct file_operations v9fs_file_operations_dotl; -extern const struct file_operations v9fs_dir_operations; -extern const struct file_operations v9fs_dir_operations_dotl; -extern const struct dentry_operations v9fs_dentry_operations; -extern const struct dentry_operations v9fs_cached_dentry_operations; -extern const struct file_operations v9fs_cached_file_operations; -extern const struct file_operations v9fs_cached_file_operations_dotl; -extern struct kmem_cache *v9fs_inode_cache; - -struct inode *v9fs_alloc_inode(struct super_block *sb); -void v9fs_destroy_inode(struct inode *inode); -struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, dev_t); -int v9fs_init_inode(struct v9fs_session_info *v9ses, - struct inode *inode, umode_t mode, dev_t); -void v9fs_evict_inode(struct inode *inode); -ino_t v9fs_qid2ino(struct p9_qid *qid); -void v9fs_stat2inode(struct p9_wstat *, struct inode *, struct super_block *); -void v9fs_stat2inode_dotl(struct p9_stat_dotl *, struct inode *); -int v9fs_dir_release(struct inode *inode, struct file *filp); -int v9fs_file_open(struct inode *inode, struct file *file); -void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); -int v9fs_uflags2omode(int uflags, int extended); - -ssize_t v9fs_file_readn(struct file *, char *, char __user *, u32, u64); -ssize_t v9fs_fid_readn(struct p9_fid *, char *, char __user *, u32, u64); -void v9fs_blank_wstat(struct p9_wstat *wstat); -int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *); -int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end, - int datasync); -ssize_t v9fs_file_write_internal(struct inode *, struct p9_fid *, - const char __user *, size_t, loff_t *, int); -int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode); -int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode); -static inline void v9fs_invalidate_inode_attr(struct inode *inode) -{ - struct v9fs_inode *v9inode; - v9inode = V9FS_I(inode); - v9inode->cache_validity |= V9FS_INO_INVALID_ATTR; - return; -} - -int v9fs_open_to_dotl_flags(int flags); -#endif diff --git a/addons/9p/src/3.10.108/vfs_addr.c b/addons/9p/src/3.10.108/vfs_addr.c deleted file mode 100644 index 055562c5..00000000 --- a/addons/9p/src/3.10.108/vfs_addr.c +++ /dev/null @@ -1,353 +0,0 @@ -/* - * linux/fs/9p/vfs_addr.c - * - * This file contians vfs address (mmap) ops for 9P2000. - * - * Copyright (C) 2005 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "cache.h" -#include "fid.h" - -/** - * v9fs_fid_readpage - read an entire page in from 9P - * - * @fid: fid being read - * @page: structure to page - * - */ -static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) -{ - int retval; - loff_t offset; - char *buffer; - struct inode *inode; - - inode = page->mapping->host; - p9_debug(P9_DEBUG_VFS, "\n"); - - BUG_ON(!PageLocked(page)); - - retval = v9fs_readpage_from_fscache(inode, page); - if (retval == 0) - return retval; - - buffer = kmap(page); - offset = page_offset(page); - - retval = v9fs_fid_readn(fid, buffer, NULL, PAGE_CACHE_SIZE, offset); - if (retval < 0) { - v9fs_uncache_page(inode, page); - goto done; - } - - memset(buffer + retval, 0, PAGE_CACHE_SIZE - retval); - flush_dcache_page(page); - SetPageUptodate(page); - - v9fs_readpage_to_fscache(inode, page); - retval = 0; - -done: - kunmap(page); - unlock_page(page); - return retval; -} - -/** - * v9fs_vfs_readpage - read an entire page in from 9P - * - * @filp: file being read - * @page: structure to page - * - */ - -static int v9fs_vfs_readpage(struct file *filp, struct page *page) -{ - return v9fs_fid_readpage(filp->private_data, page); -} - -/** - * v9fs_vfs_readpages - read a set of pages from 9P - * - * @filp: file being read - * @mapping: the address space - * @pages: list of pages to read - * @nr_pages: count of pages to read - * - */ - -static int v9fs_vfs_readpages(struct file *filp, struct address_space *mapping, - struct list_head *pages, unsigned nr_pages) -{ - int ret = 0; - struct inode *inode; - - inode = mapping->host; - p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, filp); - - ret = v9fs_readpages_from_fscache(inode, mapping, pages, &nr_pages); - if (ret == 0) - return ret; - - ret = read_cache_pages(mapping, pages, (void *)v9fs_vfs_readpage, filp); - p9_debug(P9_DEBUG_VFS, " = %d\n", ret); - return ret; -} - -/** - * v9fs_release_page - release the private state associated with a page - * - * Returns 1 if the page can be released, false otherwise. - */ - -static int v9fs_release_page(struct page *page, gfp_t gfp) -{ - if (PagePrivate(page)) - return 0; - return v9fs_fscache_release_page(page, gfp); -} - -/** - * v9fs_invalidate_page - Invalidate a page completely or partially - * - * @page: structure to page - * @offset: offset in the page - */ - -static void v9fs_invalidate_page(struct page *page, unsigned long offset) -{ - /* - * If called with zero offset, we should release - * the private state assocated with the page - */ - if (offset == 0) - v9fs_fscache_invalidate_page(page); -} - -static int v9fs_vfs_writepage_locked(struct page *page) -{ - char *buffer; - int retval, len; - loff_t offset, size; - mm_segment_t old_fs; - struct v9fs_inode *v9inode; - struct inode *inode = page->mapping->host; - - v9inode = V9FS_I(inode); - size = i_size_read(inode); - if (page->index == size >> PAGE_CACHE_SHIFT) - len = size & ~PAGE_CACHE_MASK; - else - len = PAGE_CACHE_SIZE; - - set_page_writeback(page); - - buffer = kmap(page); - offset = page_offset(page); - - old_fs = get_fs(); - set_fs(get_ds()); - /* We should have writeback_fid always set */ - BUG_ON(!v9inode->writeback_fid); - - retval = v9fs_file_write_internal(inode, - v9inode->writeback_fid, - (__force const char __user *)buffer, - len, &offset, 0); - if (retval > 0) - retval = 0; - - set_fs(old_fs); - kunmap(page); - end_page_writeback(page); - return retval; -} - -static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc) -{ - int retval; - - retval = v9fs_vfs_writepage_locked(page); - if (retval < 0) { - if (retval == -EAGAIN) { - redirty_page_for_writepage(wbc, page); - retval = 0; - } else { - SetPageError(page); - mapping_set_error(page->mapping, retval); - } - } else - retval = 0; - - unlock_page(page); - return retval; -} - -/** - * v9fs_launder_page - Writeback a dirty page - * Returns 0 on success. - */ - -static int v9fs_launder_page(struct page *page) -{ - int retval; - struct inode *inode = page->mapping->host; - - v9fs_fscache_wait_on_page_write(inode, page); - if (clear_page_dirty_for_io(page)) { - retval = v9fs_vfs_writepage_locked(page); - if (retval) - return retval; - } - return 0; -} - -/** - * v9fs_direct_IO - 9P address space operation for direct I/O - * @rw: direction (read or write) - * @iocb: target I/O control block - * @iov: array of vectors that define I/O buffer - * @pos: offset in file to begin the operation - * @nr_segs: size of iovec array - * - * The presence of v9fs_direct_IO() in the address space ops vector - * allowes open() O_DIRECT flags which would have failed otherwise. - * - * In the non-cached mode, we shunt off direct read and write requests before - * the VFS gets them, so this method should never be called. - * - * Direct IO is not 'yet' supported in the cached mode. Hence when - * this routine is called through generic_file_aio_read(), the read/write fails - * with an error. - * - */ -static ssize_t -v9fs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, - loff_t pos, unsigned long nr_segs) -{ - /* - * FIXME - * Now that we do caching with cache mode enabled, We need - * to support direct IO - */ - p9_debug(P9_DEBUG_VFS, "v9fs_direct_IO: v9fs_direct_IO (%s) off/no(%lld/%lu) EINVAL\n", - iocb->ki_filp->f_path.dentry->d_name.name, - (long long)pos, nr_segs); - - return -EINVAL; -} - -static int v9fs_write_begin(struct file *filp, struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, - struct page **pagep, void **fsdata) -{ - int retval = 0; - struct page *page; - struct v9fs_inode *v9inode; - pgoff_t index = pos >> PAGE_CACHE_SHIFT; - struct inode *inode = mapping->host; - - v9inode = V9FS_I(inode); -start: - page = grab_cache_page_write_begin(mapping, index, flags); - if (!page) { - retval = -ENOMEM; - goto out; - } - BUG_ON(!v9inode->writeback_fid); - if (PageUptodate(page)) - goto out; - - if (len == PAGE_CACHE_SIZE) - goto out; - - retval = v9fs_fid_readpage(v9inode->writeback_fid, page); - page_cache_release(page); - if (!retval) - goto start; -out: - *pagep = page; - return retval; -} - -static int v9fs_write_end(struct file *filp, struct address_space *mapping, - loff_t pos, unsigned len, unsigned copied, - struct page *page, void *fsdata) -{ - loff_t last_pos = pos + copied; - struct inode *inode = page->mapping->host; - - if (unlikely(copied < len)) { - /* - * zero out the rest of the area - */ - unsigned from = pos & (PAGE_CACHE_SIZE - 1); - - zero_user(page, from + copied, len - copied); - flush_dcache_page(page); - } - - if (!PageUptodate(page)) - SetPageUptodate(page); - /* - * No need to use i_size_read() here, the i_size - * cannot change under us because we hold the i_mutex. - */ - if (last_pos > inode->i_size) { - inode_add_bytes(inode, last_pos - inode->i_size); - i_size_write(inode, last_pos); - } - set_page_dirty(page); - unlock_page(page); - page_cache_release(page); - - return copied; -} - - -const struct address_space_operations v9fs_addr_operations = { - .readpage = v9fs_vfs_readpage, - .readpages = v9fs_vfs_readpages, - .set_page_dirty = __set_page_dirty_nobuffers, - .writepage = v9fs_vfs_writepage, - .write_begin = v9fs_write_begin, - .write_end = v9fs_write_end, - .releasepage = v9fs_release_page, - .invalidatepage = v9fs_invalidate_page, - .launder_page = v9fs_launder_page, - .direct_IO = v9fs_direct_IO, -}; diff --git a/addons/9p/src/3.10.108/vfs_dentry.c b/addons/9p/src/3.10.108/vfs_dentry.c deleted file mode 100644 index f039b104..00000000 --- a/addons/9p/src/3.10.108/vfs_dentry.c +++ /dev/null @@ -1,139 +0,0 @@ -/* - * linux/fs/9p/vfs_dentry.c - * - * This file contians vfs dentry ops for the 9P2000 protocol. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" - -/** - * v9fs_dentry_delete - called when dentry refcount equals 0 - * @dentry: dentry in question - * - * By returning 1 here we should remove cacheing of unused - * dentry components. - * - */ - -static int v9fs_dentry_delete(const struct dentry *dentry) -{ - p9_debug(P9_DEBUG_VFS, " dentry: %s (%p)\n", - dentry->d_name.name, dentry); - - return 1; -} - -/** - * v9fs_cached_dentry_delete - called when dentry refcount equals 0 - * @dentry: dentry in question - * - */ -static int v9fs_cached_dentry_delete(const struct dentry *dentry) -{ - p9_debug(P9_DEBUG_VFS, " dentry: %s (%p)\n", - dentry->d_name.name, dentry); - - /* Don't cache negative dentries */ - if (!dentry->d_inode) - return 1; - return 0; -} - -/** - * v9fs_dentry_release - called when dentry is going to be freed - * @dentry: dentry that is being release - * - */ - -static void v9fs_dentry_release(struct dentry *dentry) -{ - struct hlist_node *p, *n; - p9_debug(P9_DEBUG_VFS, " dentry: %s (%p)\n", - dentry->d_name.name, dentry); - hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata) - p9_client_clunk(hlist_entry(p, struct p9_fid, dlist)); - dentry->d_fsdata = NULL; -} - -static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags) -{ - struct p9_fid *fid; - struct inode *inode; - struct v9fs_inode *v9inode; - - if (flags & LOOKUP_RCU) - return -ECHILD; - - inode = dentry->d_inode; - if (!inode) - goto out_valid; - - v9inode = V9FS_I(inode); - if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) { - int retval; - struct v9fs_session_info *v9ses; - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - v9ses = v9fs_inode2v9ses(inode); - if (v9fs_proto_dotl(v9ses)) - retval = v9fs_refresh_inode_dotl(fid, inode); - else - retval = v9fs_refresh_inode(fid, inode); - if (retval == -ENOENT) - return 0; - if (retval < 0) - return retval; - } -out_valid: - return 1; -} - -const struct dentry_operations v9fs_cached_dentry_operations = { - .d_revalidate = v9fs_lookup_revalidate, - .d_weak_revalidate = v9fs_lookup_revalidate, - .d_delete = v9fs_cached_dentry_delete, - .d_release = v9fs_dentry_release, -}; - -const struct dentry_operations v9fs_dentry_operations = { - .d_delete = v9fs_dentry_delete, - .d_release = v9fs_dentry_release, -}; diff --git a/addons/9p/src/3.10.108/vfs_dir.c b/addons/9p/src/3.10.108/vfs_dir.c deleted file mode 100644 index be1e34ad..00000000 --- a/addons/9p/src/3.10.108/vfs_dir.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * linux/fs/9p/vfs_dir.c - * - * This file contains vfs directory ops for the 9P2000 protocol. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" - -/** - * struct p9_rdir - readdir accounting - * @mutex: mutex protecting readdir - * @head: start offset of current dirread buffer - * @tail: end offset of current dirread buffer - * @buf: dirread buffer - * - * private structure for keeping track of readdir - * allocated on demand - */ - -struct p9_rdir { - int head; - int tail; - uint8_t buf[]; -}; - -/** - * dt_type - return file type - * @mistat: mistat structure - * - */ - -static inline int dt_type(struct p9_wstat *mistat) -{ - unsigned long perm = mistat->mode; - int rettype = DT_REG; - - if (perm & P9_DMDIR) - rettype = DT_DIR; - if (perm & P9_DMSYMLINK) - rettype = DT_LNK; - - return rettype; -} - -static void p9stat_init(struct p9_wstat *stbuf) -{ - stbuf->name = NULL; - stbuf->uid = NULL; - stbuf->gid = NULL; - stbuf->muid = NULL; - stbuf->extension = NULL; -} - -/** - * v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir - * @filp: opened file structure - * @buflen: Length in bytes of buffer to allocate - * - */ - -static struct p9_rdir *v9fs_alloc_rdir_buf(struct file *filp, int buflen) -{ - struct p9_fid *fid = filp->private_data; - if (!fid->rdir) - fid->rdir = kzalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL); - return fid->rdir; -} - -/** - * v9fs_dir_readdir - read a directory - * @filp: opened file structure - * @dirent: directory structure ??? - * @filldir: function to populate directory structure ??? - * - */ - -static int v9fs_dir_readdir(struct file *filp, void *dirent, filldir_t filldir) -{ - int over; - struct p9_wstat st; - int err = 0; - struct p9_fid *fid; - int buflen; - int reclen = 0; - struct p9_rdir *rdir; - - p9_debug(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); - fid = filp->private_data; - - buflen = fid->clnt->msize - P9_IOHDRSZ; - - rdir = v9fs_alloc_rdir_buf(filp, buflen); - if (!rdir) - return -ENOMEM; - - while (1) { - if (rdir->tail == rdir->head) { - err = v9fs_file_readn(filp, rdir->buf, NULL, - buflen, filp->f_pos); - if (err <= 0) - return err; - - rdir->head = 0; - rdir->tail = err; - } - while (rdir->head < rdir->tail) { - p9stat_init(&st); - err = p9stat_read(fid->clnt, rdir->buf + rdir->head, - rdir->tail - rdir->head, &st); - if (err) { - p9_debug(P9_DEBUG_VFS, "returned %d\n", err); - p9stat_free(&st); - return -EIO; - } - reclen = st.size+2; - - over = filldir(dirent, st.name, strlen(st.name), - filp->f_pos, v9fs_qid2ino(&st.qid), dt_type(&st)); - - p9stat_free(&st); - - if (over) - return 0; - - rdir->head += reclen; - filp->f_pos += reclen; - } - } -} - -/** - * v9fs_dir_readdir_dotl - read a directory - * @filp: opened file structure - * @dirent: buffer to fill dirent structures - * @filldir: function to populate dirent structures - * - */ -static int v9fs_dir_readdir_dotl(struct file *filp, void *dirent, - filldir_t filldir) -{ - int over; - int err = 0; - struct p9_fid *fid; - int buflen; - struct p9_rdir *rdir; - struct p9_dirent curdirent; - u64 oldoffset = 0; - - p9_debug(P9_DEBUG_VFS, "name %s\n", filp->f_path.dentry->d_name.name); - fid = filp->private_data; - - buflen = fid->clnt->msize - P9_READDIRHDRSZ; - - rdir = v9fs_alloc_rdir_buf(filp, buflen); - if (!rdir) - return -ENOMEM; - - while (1) { - if (rdir->tail == rdir->head) { - err = p9_client_readdir(fid, rdir->buf, buflen, - filp->f_pos); - if (err <= 0) - return err; - - rdir->head = 0; - rdir->tail = err; - } - - while (rdir->head < rdir->tail) { - - err = p9dirent_read(fid->clnt, rdir->buf + rdir->head, - rdir->tail - rdir->head, - &curdirent); - if (err < 0) { - p9_debug(P9_DEBUG_VFS, "returned %d\n", err); - return -EIO; - } - - /* d_off in dirent structure tracks the offset into - * the next dirent in the dir. However, filldir() - * expects offset into the current dirent. Hence - * while calling filldir send the offset from the - * previous dirent structure. - */ - over = filldir(dirent, curdirent.d_name, - strlen(curdirent.d_name), - oldoffset, v9fs_qid2ino(&curdirent.qid), - curdirent.d_type); - oldoffset = curdirent.d_off; - - if (over) - return 0; - - filp->f_pos = curdirent.d_off; - rdir->head += err; - } - } -} - - -/** - * v9fs_dir_release - close a directory - * @inode: inode of the directory - * @filp: file pointer to a directory - * - */ - -int v9fs_dir_release(struct inode *inode, struct file *filp) -{ - struct p9_fid *fid; - - fid = filp->private_data; - p9_debug(P9_DEBUG_VFS, "inode: %p filp: %p fid: %d\n", - inode, filp, fid ? fid->fid : -1); - if (fid) - p9_client_clunk(fid); - return 0; -} - -const struct file_operations v9fs_dir_operations = { - .read = generic_read_dir, - .llseek = generic_file_llseek, - .readdir = v9fs_dir_readdir, - .open = v9fs_file_open, - .release = v9fs_dir_release, -}; - -const struct file_operations v9fs_dir_operations_dotl = { - .read = generic_read_dir, - .llseek = generic_file_llseek, - .readdir = v9fs_dir_readdir_dotl, - .open = v9fs_file_open, - .release = v9fs_dir_release, - .fsync = v9fs_file_fsync_dotl, -}; diff --git a/addons/9p/src/3.10.108/vfs_file.c b/addons/9p/src/3.10.108/vfs_file.c deleted file mode 100644 index d384a8b7..00000000 --- a/addons/9p/src/3.10.108/vfs_file.c +++ /dev/null @@ -1,790 +0,0 @@ -/* - * linux/fs/9p/vfs_file.c - * - * This file contians vfs file ops for 9P2000. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" -#include "cache.h" - -static const struct vm_operations_struct v9fs_file_vm_ops; - -/** - * v9fs_file_open - open a file (or directory) - * @inode: inode to be opened - * @file: file being opened - * - */ - -int v9fs_file_open(struct inode *inode, struct file *file) -{ - int err; - struct v9fs_inode *v9inode; - struct v9fs_session_info *v9ses; - struct p9_fid *fid; - int omode; - - p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file); - v9inode = V9FS_I(inode); - v9ses = v9fs_inode2v9ses(inode); - if (v9fs_proto_dotl(v9ses)) - omode = v9fs_open_to_dotl_flags(file->f_flags); - else - omode = v9fs_uflags2omode(file->f_flags, - v9fs_proto_dotu(v9ses)); - fid = file->private_data; - if (!fid) { - fid = v9fs_fid_clone(file->f_path.dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - err = p9_client_open(fid, omode); - if (err < 0) { - p9_client_clunk(fid); - return err; - } - if ((file->f_flags & O_APPEND) && - (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses))) - generic_file_llseek(file, 0, SEEK_END); - } - - file->private_data = fid; - mutex_lock(&v9inode->v_mutex); - if (v9ses->cache && !v9inode->writeback_fid && - ((file->f_flags & O_ACCMODE) != O_RDONLY)) { - /* - * clone a fid and add it to writeback_fid - * we do it during open time instead of - * page dirty time via write_begin/page_mkwrite - * because we want write after unlink usecase - * to work. - */ - fid = v9fs_writeback_fid(file->f_path.dentry); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - mutex_unlock(&v9inode->v_mutex); - goto out_error; - } - v9inode->writeback_fid = (void *) fid; - } - mutex_unlock(&v9inode->v_mutex); -#ifdef CONFIG_9P_FSCACHE - if (v9ses->cache) - v9fs_cache_inode_set_cookie(inode, file); -#endif - return 0; -out_error: - p9_client_clunk(file->private_data); - file->private_data = NULL; - return err; -} - -/** - * v9fs_file_lock - lock a file (or directory) - * @filp: file to be locked - * @cmd: lock command - * @fl: file lock structure - * - * Bugs: this looks like a local only lock, we should extend into 9P - * by using open exclusive - */ - -static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) -{ - int res = 0; - struct inode *inode = file_inode(filp); - - p9_debug(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); - - /* No mandatory locks */ - if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) - return -ENOLCK; - - if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { - filemap_write_and_wait(inode->i_mapping); - invalidate_mapping_pages(&inode->i_data, 0, -1); - } - - return res; -} - -static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl) -{ - struct p9_flock flock; - struct p9_fid *fid; - uint8_t status; - int res = 0; - unsigned char fl_type; - - fid = filp->private_data; - BUG_ON(fid == NULL); - - if ((fl->fl_flags & FL_POSIX) != FL_POSIX) - BUG(); - - res = posix_lock_file_wait(filp, fl); - if (res < 0) - goto out; - - /* convert posix lock to p9 tlock args */ - memset(&flock, 0, sizeof(flock)); - /* map the lock type */ - switch (fl->fl_type) { - case F_RDLCK: - flock.type = P9_LOCK_TYPE_RDLCK; - break; - case F_WRLCK: - flock.type = P9_LOCK_TYPE_WRLCK; - break; - case F_UNLCK: - flock.type = P9_LOCK_TYPE_UNLCK; - break; - } - flock.start = fl->fl_start; - if (fl->fl_end == OFFSET_MAX) - flock.length = 0; - else - flock.length = fl->fl_end - fl->fl_start + 1; - flock.proc_id = fl->fl_pid; - flock.client_id = utsname()->nodename; - if (IS_SETLKW(cmd)) - flock.flags = P9_LOCK_FLAGS_BLOCK; - - /* - * if its a blocked request and we get P9_LOCK_BLOCKED as the status - * for lock request, keep on trying - */ - for (;;) { - res = p9_client_lock_dotl(fid, &flock, &status); - if (res < 0) - break; - - if (status != P9_LOCK_BLOCKED) - break; - if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd)) - break; - if (schedule_timeout_interruptible(P9_LOCK_TIMEOUT) != 0) - break; - } - - /* map 9p status to VFS status */ - switch (status) { - case P9_LOCK_SUCCESS: - res = 0; - break; - case P9_LOCK_BLOCKED: - res = -EAGAIN; - break; - case P9_LOCK_ERROR: - case P9_LOCK_GRACE: - res = -ENOLCK; - break; - default: - BUG(); - } - - /* - * incase server returned error for lock request, revert - * it locally - */ - if (res < 0 && fl->fl_type != F_UNLCK) { - fl_type = fl->fl_type; - fl->fl_type = F_UNLCK; - res = posix_lock_file_wait(filp, fl); - fl->fl_type = fl_type; - } -out: - return res; -} - -static int v9fs_file_getlock(struct file *filp, struct file_lock *fl) -{ - struct p9_getlock glock; - struct p9_fid *fid; - int res = 0; - - fid = filp->private_data; - BUG_ON(fid == NULL); - - posix_test_lock(filp, fl); - /* - * if we have a conflicting lock locally, no need to validate - * with server - */ - if (fl->fl_type != F_UNLCK) - return res; - - /* convert posix lock to p9 tgetlock args */ - memset(&glock, 0, sizeof(glock)); - glock.type = P9_LOCK_TYPE_UNLCK; - glock.start = fl->fl_start; - if (fl->fl_end == OFFSET_MAX) - glock.length = 0; - else - glock.length = fl->fl_end - fl->fl_start + 1; - glock.proc_id = fl->fl_pid; - glock.client_id = utsname()->nodename; - - res = p9_client_getlock_dotl(fid, &glock); - if (res < 0) - return res; - /* map 9p lock type to os lock type */ - switch (glock.type) { - case P9_LOCK_TYPE_RDLCK: - fl->fl_type = F_RDLCK; - break; - case P9_LOCK_TYPE_WRLCK: - fl->fl_type = F_WRLCK; - break; - case P9_LOCK_TYPE_UNLCK: - fl->fl_type = F_UNLCK; - break; - } - if (glock.type != P9_LOCK_TYPE_UNLCK) { - fl->fl_start = glock.start; - if (glock.length == 0) - fl->fl_end = OFFSET_MAX; - else - fl->fl_end = glock.start + glock.length - 1; - fl->fl_pid = glock.proc_id; - } - return res; -} - -/** - * v9fs_file_lock_dotl - lock a file (or directory) - * @filp: file to be locked - * @cmd: lock command - * @fl: file lock structure - * - */ - -static int v9fs_file_lock_dotl(struct file *filp, int cmd, struct file_lock *fl) -{ - struct inode *inode = file_inode(filp); - int ret = -ENOLCK; - - p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n", - filp, cmd, fl, filp->f_path.dentry->d_name.name); - - /* No mandatory locks */ - if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) - goto out_err; - - if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { - filemap_write_and_wait(inode->i_mapping); - invalidate_mapping_pages(&inode->i_data, 0, -1); - } - - if (IS_SETLK(cmd) || IS_SETLKW(cmd)) - ret = v9fs_file_do_lock(filp, cmd, fl); - else if (IS_GETLK(cmd)) - ret = v9fs_file_getlock(filp, fl); - else - ret = -EINVAL; -out_err: - return ret; -} - -/** - * v9fs_file_flock_dotl - lock a file - * @filp: file to be locked - * @cmd: lock command - * @fl: file lock structure - * - */ - -static int v9fs_file_flock_dotl(struct file *filp, int cmd, - struct file_lock *fl) -{ - struct inode *inode = file_inode(filp); - int ret = -ENOLCK; - - p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n", - filp, cmd, fl, filp->f_path.dentry->d_name.name); - - /* No mandatory locks */ - if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) - goto out_err; - - if (!(fl->fl_flags & FL_FLOCK)) - goto out_err; - - if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { - filemap_write_and_wait(inode->i_mapping); - invalidate_mapping_pages(&inode->i_data, 0, -1); - } - /* Convert flock to posix lock */ - fl->fl_owner = (fl_owner_t)filp; - fl->fl_start = 0; - fl->fl_end = OFFSET_MAX; - fl->fl_flags |= FL_POSIX; - fl->fl_flags ^= FL_FLOCK; - - if (IS_SETLK(cmd) | IS_SETLKW(cmd)) - ret = v9fs_file_do_lock(filp, cmd, fl); - else - ret = -EINVAL; -out_err: - return ret; -} - -/** - * v9fs_fid_readn - read from a fid - * @fid: fid to read - * @data: data buffer to read data into - * @udata: user data buffer to read data into - * @count: size of buffer - * @offset: offset at which to read data - * - */ -ssize_t -v9fs_fid_readn(struct p9_fid *fid, char *data, char __user *udata, u32 count, - u64 offset) -{ - int n, total, size; - - p9_debug(P9_DEBUG_VFS, "fid %d offset %llu count %d\n", - fid->fid, (long long unsigned)offset, count); - n = 0; - total = 0; - size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; - do { - n = p9_client_read(fid, data, udata, offset, count); - if (n <= 0) - break; - - if (data) - data += n; - if (udata) - udata += n; - - offset += n; - count -= n; - total += n; - } while (count > 0 && n == size); - - if (n < 0) - total = n; - - return total; -} - -/** - * v9fs_file_readn - read from a file - * @filp: file pointer to read - * @data: data buffer to read data into - * @udata: user data buffer to read data into - * @count: size of buffer - * @offset: offset at which to read data - * - */ -ssize_t -v9fs_file_readn(struct file *filp, char *data, char __user *udata, u32 count, - u64 offset) -{ - return v9fs_fid_readn(filp->private_data, data, udata, count, offset); -} - -/** - * v9fs_file_read - read from a file - * @filp: file pointer to read - * @udata: user data buffer to read data into - * @count: size of buffer - * @offset: offset at which to read data - * - */ - -static ssize_t -v9fs_file_read(struct file *filp, char __user *udata, size_t count, - loff_t * offset) -{ - int ret; - struct p9_fid *fid; - size_t size; - - p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", count, *offset); - fid = filp->private_data; - - size = fid->iounit ? fid->iounit : fid->clnt->msize - P9_IOHDRSZ; - if (count > size) - ret = v9fs_file_readn(filp, NULL, udata, count, *offset); - else - ret = p9_client_read(fid, NULL, udata, *offset, count); - - if (ret > 0) - *offset += ret; - - return ret; -} - -ssize_t -v9fs_file_write_internal(struct inode *inode, struct p9_fid *fid, - const char __user *data, size_t count, - loff_t *offset, int invalidate) -{ - int n; - loff_t i_size; - size_t total = 0; - struct p9_client *clnt; - loff_t origin = *offset; - unsigned long pg_start, pg_end; - - p9_debug(P9_DEBUG_VFS, "data %p count %d offset %x\n", - data, (int)count, (int)*offset); - - clnt = fid->clnt; - do { - n = p9_client_write(fid, NULL, data+total, origin+total, count); - if (n <= 0) - break; - count -= n; - total += n; - } while (count > 0); - - if (invalidate && (total > 0)) { - pg_start = origin >> PAGE_CACHE_SHIFT; - pg_end = (origin + total - 1) >> PAGE_CACHE_SHIFT; - if (inode->i_mapping && inode->i_mapping->nrpages) - invalidate_inode_pages2_range(inode->i_mapping, - pg_start, pg_end); - *offset += total; - i_size = i_size_read(inode); - if (*offset > i_size) { - inode_add_bytes(inode, *offset - i_size); - i_size_write(inode, *offset); - } - } - if (n < 0) - return n; - - return total; -} - -/** - * v9fs_file_write - write to a file - * @filp: file pointer to write - * @data: data buffer to write data from - * @count: size of buffer - * @offset: offset at which to write data - * - */ -static ssize_t -v9fs_file_write(struct file *filp, const char __user * data, - size_t count, loff_t *offset) -{ - ssize_t retval = 0; - loff_t origin = *offset; - - - retval = generic_write_checks(filp, &origin, &count, 0); - if (retval) - goto out; - - retval = -EINVAL; - if ((ssize_t) count < 0) - goto out; - retval = 0; - if (!count) - goto out; - - retval = v9fs_file_write_internal(file_inode(filp), - filp->private_data, - data, count, &origin, 1); - /* update offset on successful write */ - if (retval > 0) - *offset = origin; -out: - return retval; -} - - -static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end, - int datasync) -{ - struct p9_fid *fid; - struct inode *inode = filp->f_mapping->host; - struct p9_wstat wstat; - int retval; - - retval = filemap_write_and_wait_range(inode->i_mapping, start, end); - if (retval) - return retval; - - mutex_lock(&inode->i_mutex); - p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync); - - fid = filp->private_data; - v9fs_blank_wstat(&wstat); - - retval = p9_client_wstat(fid, &wstat); - mutex_unlock(&inode->i_mutex); - - return retval; -} - -int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end, - int datasync) -{ - struct p9_fid *fid; - struct inode *inode = filp->f_mapping->host; - int retval; - - retval = filemap_write_and_wait_range(inode->i_mapping, start, end); - if (retval) - return retval; - - mutex_lock(&inode->i_mutex); - p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync); - - fid = filp->private_data; - - retval = p9_client_fsync(fid, datasync); - mutex_unlock(&inode->i_mutex); - - return retval; -} - -static int -v9fs_file_mmap(struct file *file, struct vm_area_struct *vma) -{ - int retval; - - retval = generic_file_mmap(file, vma); - if (!retval) - vma->vm_ops = &v9fs_file_vm_ops; - - return retval; -} - -static int -v9fs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - struct v9fs_inode *v9inode; - struct page *page = vmf->page; - struct file *filp = vma->vm_file; - struct inode *inode = file_inode(filp); - - - p9_debug(P9_DEBUG_VFS, "page %p fid %lx\n", - page, (unsigned long)filp->private_data); - - /* Update file times before taking page lock */ - file_update_time(filp); - - v9inode = V9FS_I(inode); - /* make sure the cache has finished storing the page */ - v9fs_fscache_wait_on_page_write(inode, page); - BUG_ON(!v9inode->writeback_fid); - lock_page(page); - if (page->mapping != inode->i_mapping) - goto out_unlock; - wait_for_stable_page(page); - - return VM_FAULT_LOCKED; -out_unlock: - unlock_page(page); - return VM_FAULT_NOPAGE; -} - -static ssize_t -v9fs_direct_read(struct file *filp, char __user *udata, size_t count, - loff_t *offsetp) -{ - loff_t size, offset; - struct inode *inode; - struct address_space *mapping; - - offset = *offsetp; - mapping = filp->f_mapping; - inode = mapping->host; - if (!count) - return 0; - size = i_size_read(inode); - if (offset < size) - filemap_write_and_wait_range(mapping, offset, - offset + count - 1); - - return v9fs_file_read(filp, udata, count, offsetp); -} - -/** - * v9fs_cached_file_read - read from a file - * @filp: file pointer to read - * @udata: user data buffer to read data into - * @count: size of buffer - * @offset: offset at which to read data - * - */ -static ssize_t -v9fs_cached_file_read(struct file *filp, char __user *data, size_t count, - loff_t *offset) -{ - if (filp->f_flags & O_DIRECT) - return v9fs_direct_read(filp, data, count, offset); - return do_sync_read(filp, data, count, offset); -} - -static ssize_t -v9fs_direct_write(struct file *filp, const char __user * data, - size_t count, loff_t *offsetp) -{ - loff_t offset; - ssize_t retval; - struct inode *inode; - struct address_space *mapping; - - offset = *offsetp; - mapping = filp->f_mapping; - inode = mapping->host; - if (!count) - return 0; - - mutex_lock(&inode->i_mutex); - retval = filemap_write_and_wait_range(mapping, offset, - offset + count - 1); - if (retval) - goto err_out; - /* - * After a write we want buffered reads to be sure to go to disk to get - * the new data. We invalidate clean cached page from the region we're - * about to write. We do this *before* the write so that if we fail - * here we fall back to buffered write - */ - if (mapping->nrpages) { - pgoff_t pg_start = offset >> PAGE_CACHE_SHIFT; - pgoff_t pg_end = (offset + count - 1) >> PAGE_CACHE_SHIFT; - - retval = invalidate_inode_pages2_range(mapping, - pg_start, pg_end); - /* - * If a page can not be invalidated, fall back - * to buffered write. - */ - if (retval) { - if (retval == -EBUSY) - goto buff_write; - goto err_out; - } - } - retval = v9fs_file_write(filp, data, count, offsetp); -err_out: - mutex_unlock(&inode->i_mutex); - return retval; - -buff_write: - mutex_unlock(&inode->i_mutex); - return do_sync_write(filp, data, count, offsetp); -} - -/** - * v9fs_cached_file_write - write to a file - * @filp: file pointer to write - * @data: data buffer to write data from - * @count: size of buffer - * @offset: offset at which to write data - * - */ -static ssize_t -v9fs_cached_file_write(struct file *filp, const char __user * data, - size_t count, loff_t *offset) -{ - - if (filp->f_flags & O_DIRECT) - return v9fs_direct_write(filp, data, count, offset); - return do_sync_write(filp, data, count, offset); -} - -static const struct vm_operations_struct v9fs_file_vm_ops = { - .fault = filemap_fault, - .page_mkwrite = v9fs_vm_page_mkwrite, - .remap_pages = generic_file_remap_pages, -}; - - -const struct file_operations v9fs_cached_file_operations = { - .llseek = generic_file_llseek, - .read = v9fs_cached_file_read, - .write = v9fs_cached_file_write, - .aio_read = generic_file_aio_read, - .aio_write = generic_file_aio_write, - .open = v9fs_file_open, - .release = v9fs_dir_release, - .lock = v9fs_file_lock, - .mmap = v9fs_file_mmap, - .fsync = v9fs_file_fsync, -}; - -const struct file_operations v9fs_cached_file_operations_dotl = { - .llseek = generic_file_llseek, - .read = v9fs_cached_file_read, - .write = v9fs_cached_file_write, - .aio_read = generic_file_aio_read, - .aio_write = generic_file_aio_write, - .open = v9fs_file_open, - .release = v9fs_dir_release, - .lock = v9fs_file_lock_dotl, - .flock = v9fs_file_flock_dotl, - .mmap = v9fs_file_mmap, - .fsync = v9fs_file_fsync_dotl, -}; - -const struct file_operations v9fs_file_operations = { - .llseek = generic_file_llseek, - .read = v9fs_file_read, - .write = v9fs_file_write, - .open = v9fs_file_open, - .release = v9fs_dir_release, - .lock = v9fs_file_lock, - .mmap = generic_file_readonly_mmap, - .fsync = v9fs_file_fsync, -}; - -const struct file_operations v9fs_file_operations_dotl = { - .llseek = generic_file_llseek, - .read = v9fs_file_read, - .write = v9fs_file_write, - .open = v9fs_file_open, - .release = v9fs_dir_release, - .lock = v9fs_file_lock_dotl, - .flock = v9fs_file_flock_dotl, - .mmap = generic_file_readonly_mmap, - .fsync = v9fs_file_fsync_dotl, -}; diff --git a/addons/9p/src/3.10.108/vfs_inode.c b/addons/9p/src/3.10.108/vfs_inode.c deleted file mode 100644 index 4c7d309e..00000000 --- a/addons/9p/src/3.10.108/vfs_inode.c +++ /dev/null @@ -1,1538 +0,0 @@ -/* - * linux/fs/9p/vfs_inode.c - * - * This file contains vfs inode ops for the 9P2000 protocol. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" -#include "cache.h" -#include "xattr.h" -#include "acl.h" - -static const struct inode_operations v9fs_dir_inode_operations; -static const struct inode_operations v9fs_dir_inode_operations_dotu; -static const struct inode_operations v9fs_file_inode_operations; -static const struct inode_operations v9fs_symlink_inode_operations; - -/** - * unixmode2p9mode - convert unix mode bits to plan 9 - * @v9ses: v9fs session information - * @mode: mode to convert - * - */ - -static u32 unixmode2p9mode(struct v9fs_session_info *v9ses, umode_t mode) -{ - int res; - res = mode & 0777; - if (S_ISDIR(mode)) - res |= P9_DMDIR; - if (v9fs_proto_dotu(v9ses)) { - if (v9ses->nodev == 0) { - if (S_ISSOCK(mode)) - res |= P9_DMSOCKET; - if (S_ISFIFO(mode)) - res |= P9_DMNAMEDPIPE; - if (S_ISBLK(mode)) - res |= P9_DMDEVICE; - if (S_ISCHR(mode)) - res |= P9_DMDEVICE; - } - - if ((mode & S_ISUID) == S_ISUID) - res |= P9_DMSETUID; - if ((mode & S_ISGID) == S_ISGID) - res |= P9_DMSETGID; - if ((mode & S_ISVTX) == S_ISVTX) - res |= P9_DMSETVTX; - } - return res; -} - -/** - * p9mode2perm- convert plan9 mode bits to unix permission bits - * @v9ses: v9fs session information - * @stat: p9_wstat from which mode need to be derived - * - */ -static int p9mode2perm(struct v9fs_session_info *v9ses, - struct p9_wstat *stat) -{ - int res; - int mode = stat->mode; - - res = mode & S_IALLUGO; - if (v9fs_proto_dotu(v9ses)) { - if ((mode & P9_DMSETUID) == P9_DMSETUID) - res |= S_ISUID; - - if ((mode & P9_DMSETGID) == P9_DMSETGID) - res |= S_ISGID; - - if ((mode & P9_DMSETVTX) == P9_DMSETVTX) - res |= S_ISVTX; - } - return res; -} - -/** - * p9mode2unixmode- convert plan9 mode bits to unix mode bits - * @v9ses: v9fs session information - * @stat: p9_wstat from which mode need to be derived - * @rdev: major number, minor number in case of device files. - * - */ -static umode_t p9mode2unixmode(struct v9fs_session_info *v9ses, - struct p9_wstat *stat, dev_t *rdev) -{ - int res; - u32 mode = stat->mode; - - *rdev = 0; - res = p9mode2perm(v9ses, stat); - - if ((mode & P9_DMDIR) == P9_DMDIR) - res |= S_IFDIR; - else if ((mode & P9_DMSYMLINK) && (v9fs_proto_dotu(v9ses))) - res |= S_IFLNK; - else if ((mode & P9_DMSOCKET) && (v9fs_proto_dotu(v9ses)) - && (v9ses->nodev == 0)) - res |= S_IFSOCK; - else if ((mode & P9_DMNAMEDPIPE) && (v9fs_proto_dotu(v9ses)) - && (v9ses->nodev == 0)) - res |= S_IFIFO; - else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses)) - && (v9ses->nodev == 0)) { - char type = 0, ext[32]; - int major = -1, minor = -1; - - strncpy(ext, stat->extension, sizeof(ext)); - sscanf(ext, "%c %u %u", &type, &major, &minor); - switch (type) { - case 'c': - res |= S_IFCHR; - break; - case 'b': - res |= S_IFBLK; - break; - default: - p9_debug(P9_DEBUG_ERROR, "Unknown special type %c %s\n", - type, stat->extension); - }; - *rdev = MKDEV(major, minor); - } else - res |= S_IFREG; - - return res; -} - -/** - * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits - * @uflags: flags to convert - * @extended: if .u extensions are active - */ - -int v9fs_uflags2omode(int uflags, int extended) -{ - int ret; - - ret = 0; - switch (uflags&3) { - default: - case O_RDONLY: - ret = P9_OREAD; - break; - - case O_WRONLY: - ret = P9_OWRITE; - break; - - case O_RDWR: - ret = P9_ORDWR; - break; - } - - if (extended) { - if (uflags & O_EXCL) - ret |= P9_OEXCL; - - if (uflags & O_APPEND) - ret |= P9_OAPPEND; - } - - return ret; -} - -/** - * v9fs_blank_wstat - helper function to setup a 9P stat structure - * @wstat: structure to initialize - * - */ - -void -v9fs_blank_wstat(struct p9_wstat *wstat) -{ - wstat->type = ~0; - wstat->dev = ~0; - wstat->qid.type = ~0; - wstat->qid.version = ~0; - *((long long *)&wstat->qid.path) = ~0; - wstat->mode = ~0; - wstat->atime = ~0; - wstat->mtime = ~0; - wstat->length = ~0; - wstat->name = NULL; - wstat->uid = NULL; - wstat->gid = NULL; - wstat->muid = NULL; - wstat->n_uid = INVALID_UID; - wstat->n_gid = INVALID_GID; - wstat->n_muid = INVALID_UID; - wstat->extension = NULL; -} - -/** - * v9fs_alloc_inode - helper function to allocate an inode - * - */ -struct inode *v9fs_alloc_inode(struct super_block *sb) -{ - struct v9fs_inode *v9inode; - v9inode = (struct v9fs_inode *)kmem_cache_alloc(v9fs_inode_cache, - GFP_KERNEL); - if (!v9inode) - return NULL; -#ifdef CONFIG_9P_FSCACHE - v9inode->fscache = NULL; - spin_lock_init(&v9inode->fscache_lock); -#endif - v9inode->writeback_fid = NULL; - v9inode->cache_validity = 0; - mutex_init(&v9inode->v_mutex); - return &v9inode->vfs_inode; -} - -/** - * v9fs_destroy_inode - destroy an inode - * - */ - -static void v9fs_i_callback(struct rcu_head *head) -{ - struct inode *inode = container_of(head, struct inode, i_rcu); - kmem_cache_free(v9fs_inode_cache, V9FS_I(inode)); -} - -void v9fs_destroy_inode(struct inode *inode) -{ - call_rcu(&inode->i_rcu, v9fs_i_callback); -} - -int v9fs_init_inode(struct v9fs_session_info *v9ses, - struct inode *inode, umode_t mode, dev_t rdev) -{ - int err = 0; - - inode_init_owner(inode, NULL, mode); - inode->i_blocks = 0; - inode->i_rdev = rdev; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->i_mapping->a_ops = &v9fs_addr_operations; - - switch (mode & S_IFMT) { - case S_IFIFO: - case S_IFBLK: - case S_IFCHR: - case S_IFSOCK: - if (v9fs_proto_dotl(v9ses)) { - inode->i_op = &v9fs_file_inode_operations_dotl; - } else if (v9fs_proto_dotu(v9ses)) { - inode->i_op = &v9fs_file_inode_operations; - } else { - p9_debug(P9_DEBUG_ERROR, - "special files without extended mode\n"); - err = -EINVAL; - goto error; - } - init_special_inode(inode, inode->i_mode, inode->i_rdev); - break; - case S_IFREG: - if (v9fs_proto_dotl(v9ses)) { - inode->i_op = &v9fs_file_inode_operations_dotl; - if (v9ses->cache) - inode->i_fop = - &v9fs_cached_file_operations_dotl; - else - inode->i_fop = &v9fs_file_operations_dotl; - } else { - inode->i_op = &v9fs_file_inode_operations; - if (v9ses->cache) - inode->i_fop = &v9fs_cached_file_operations; - else - inode->i_fop = &v9fs_file_operations; - } - - break; - case S_IFLNK: - if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) { - p9_debug(P9_DEBUG_ERROR, - "extended modes used with legacy protocol\n"); - err = -EINVAL; - goto error; - } - - if (v9fs_proto_dotl(v9ses)) - inode->i_op = &v9fs_symlink_inode_operations_dotl; - else - inode->i_op = &v9fs_symlink_inode_operations; - - break; - case S_IFDIR: - inc_nlink(inode); - if (v9fs_proto_dotl(v9ses)) - inode->i_op = &v9fs_dir_inode_operations_dotl; - else if (v9fs_proto_dotu(v9ses)) - inode->i_op = &v9fs_dir_inode_operations_dotu; - else - inode->i_op = &v9fs_dir_inode_operations; - - if (v9fs_proto_dotl(v9ses)) - inode->i_fop = &v9fs_dir_operations_dotl; - else - inode->i_fop = &v9fs_dir_operations; - - break; - default: - p9_debug(P9_DEBUG_ERROR, "BAD mode 0x%hx S_IFMT 0x%x\n", - mode, mode & S_IFMT); - err = -EINVAL; - goto error; - } -error: - return err; - -} - -/** - * v9fs_get_inode - helper function to setup an inode - * @sb: superblock - * @mode: mode to setup inode with - * - */ - -struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, dev_t rdev) -{ - int err; - struct inode *inode; - struct v9fs_session_info *v9ses = sb->s_fs_info; - - p9_debug(P9_DEBUG_VFS, "super block: %p mode: %ho\n", sb, mode); - - inode = new_inode(sb); - if (!inode) { - pr_warn("%s (%d): Problem allocating inode\n", - __func__, task_pid_nr(current)); - return ERR_PTR(-ENOMEM); - } - err = v9fs_init_inode(v9ses, inode, mode, rdev); - if (err) { - iput(inode); - return ERR_PTR(err); - } - return inode; -} - -/* -static struct v9fs_fid* -v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry) -{ - int err; - int nfid; - struct v9fs_fid *ret; - struct v9fs_fcall *fcall; - - nfid = v9fs_get_idpool(&v9ses->fidpool); - if (nfid < 0) { - eprintk(KERN_WARNING, "no free fids available\n"); - return ERR_PTR(-ENOSPC); - } - - err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name, - &fcall); - - if (err < 0) { - if (fcall && fcall->id == RWALK) - goto clunk_fid; - - PRINT_FCALL_ERROR("walk error", fcall); - v9fs_put_idpool(nfid, &v9ses->fidpool); - goto error; - } - - kfree(fcall); - fcall = NULL; - ret = v9fs_fid_create(v9ses, nfid); - if (!ret) { - err = -ENOMEM; - goto clunk_fid; - } - - err = v9fs_fid_insert(ret, dentry); - if (err < 0) { - v9fs_fid_destroy(ret); - goto clunk_fid; - } - - return ret; - -clunk_fid: - v9fs_t_clunk(v9ses, nfid); - -error: - kfree(fcall); - return ERR_PTR(err); -} -*/ - - -/** - * v9fs_clear_inode - release an inode - * @inode: inode to release - * - */ -void v9fs_evict_inode(struct inode *inode) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - - truncate_inode_pages(inode->i_mapping, 0); - clear_inode(inode); - filemap_fdatawrite(inode->i_mapping); - -#ifdef CONFIG_9P_FSCACHE - v9fs_cache_inode_put_cookie(inode); -#endif - /* clunk the fid stashed in writeback_fid */ - if (v9inode->writeback_fid) { - p9_client_clunk(v9inode->writeback_fid); - v9inode->writeback_fid = NULL; - } -} - -static int v9fs_test_inode(struct inode *inode, void *data) -{ - int umode; - dev_t rdev; - struct v9fs_inode *v9inode = V9FS_I(inode); - struct p9_wstat *st = (struct p9_wstat *)data; - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); - - umode = p9mode2unixmode(v9ses, st, &rdev); - /* don't match inode of different type */ - if ((inode->i_mode & S_IFMT) != (umode & S_IFMT)) - return 0; - - /* compare qid details */ - if (memcmp(&v9inode->qid.version, - &st->qid.version, sizeof(v9inode->qid.version))) - return 0; - - if (v9inode->qid.type != st->qid.type) - return 0; - return 1; -} - -static int v9fs_test_new_inode(struct inode *inode, void *data) -{ - return 0; -} - -static int v9fs_set_inode(struct inode *inode, void *data) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - struct p9_wstat *st = (struct p9_wstat *)data; - - memcpy(&v9inode->qid, &st->qid, sizeof(st->qid)); - return 0; -} - -static struct inode *v9fs_qid_iget(struct super_block *sb, - struct p9_qid *qid, - struct p9_wstat *st, - int new) -{ - dev_t rdev; - int retval; - umode_t umode; - unsigned long i_ino; - struct inode *inode; - struct v9fs_session_info *v9ses = sb->s_fs_info; - int (*test)(struct inode *, void *); - - if (new) - test = v9fs_test_new_inode; - else - test = v9fs_test_inode; - - i_ino = v9fs_qid2ino(qid); - inode = iget5_locked(sb, i_ino, test, v9fs_set_inode, st); - if (!inode) - return ERR_PTR(-ENOMEM); - if (!(inode->i_state & I_NEW)) - return inode; - /* - * initialize the inode with the stat info - * FIXME!! we may need support for stale inodes - * later. - */ - inode->i_ino = i_ino; - umode = p9mode2unixmode(v9ses, st, &rdev); - retval = v9fs_init_inode(v9ses, inode, umode, rdev); - if (retval) - goto error; - - v9fs_stat2inode(st, inode, sb); -#ifdef CONFIG_9P_FSCACHE - v9fs_cache_inode_get_cookie(inode); -#endif - unlock_new_inode(inode); - return inode; -error: - iget_failed(inode); - return ERR_PTR(retval); - -} - -struct inode * -v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, - struct super_block *sb, int new) -{ - struct p9_wstat *st; - struct inode *inode = NULL; - - st = p9_client_stat(fid); - if (IS_ERR(st)) - return ERR_CAST(st); - - inode = v9fs_qid_iget(sb, &st->qid, st, new); - p9stat_free(st); - kfree(st); - return inode; -} - -/** - * v9fs_at_to_dotl_flags- convert Linux specific AT flags to - * plan 9 AT flag. - * @flags: flags to convert - */ -static int v9fs_at_to_dotl_flags(int flags) -{ - int rflags = 0; - if (flags & AT_REMOVEDIR) - rflags |= P9_DOTL_AT_REMOVEDIR; - return rflags; -} - -/** - * v9fs_remove - helper function to remove files and directories - * @dir: directory inode that is being deleted - * @dentry: dentry that is being deleted - * @rmdir: removing a directory - * - */ - -static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags) -{ - struct inode *inode; - int retval = -EOPNOTSUPP; - struct p9_fid *v9fid, *dfid; - struct v9fs_session_info *v9ses; - - p9_debug(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n", - dir, dentry, flags); - - v9ses = v9fs_inode2v9ses(dir); - inode = dentry->d_inode; - dfid = v9fs_fid_lookup(dentry->d_parent); - if (IS_ERR(dfid)) { - retval = PTR_ERR(dfid); - p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", retval); - return retval; - } - if (v9fs_proto_dotl(v9ses)) - retval = p9_client_unlinkat(dfid, dentry->d_name.name, - v9fs_at_to_dotl_flags(flags)); - if (retval == -EOPNOTSUPP) { - /* Try the one based on path */ - v9fid = v9fs_fid_clone(dentry); - if (IS_ERR(v9fid)) - return PTR_ERR(v9fid); - retval = p9_client_remove(v9fid); - } - if (!retval) { - /* - * directories on unlink should have zero - * link count - */ - if (flags & AT_REMOVEDIR) { - clear_nlink(inode); - drop_nlink(dir); - } else - drop_nlink(inode); - - v9fs_invalidate_inode_attr(inode); - v9fs_invalidate_inode_attr(dir); - } - return retval; -} - -/** - * v9fs_create - Create a file - * @v9ses: session information - * @dir: directory that dentry is being created in - * @dentry: dentry that is being created - * @extension: 9p2000.u extension string to support devices, etc. - * @perm: create permissions - * @mode: open mode - * - */ -static struct p9_fid * -v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, - struct dentry *dentry, char *extension, u32 perm, u8 mode) -{ - int err; - char *name; - struct p9_fid *dfid, *ofid, *fid; - struct inode *inode; - - p9_debug(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); - - err = 0; - ofid = NULL; - fid = NULL; - name = (char *) dentry->d_name.name; - dfid = v9fs_fid_lookup(dentry->d_parent); - if (IS_ERR(dfid)) { - err = PTR_ERR(dfid); - p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); - return ERR_PTR(err); - } - - /* clone a fid to use for creation */ - ofid = p9_client_walk(dfid, 0, NULL, 1); - if (IS_ERR(ofid)) { - err = PTR_ERR(ofid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); - return ERR_PTR(err); - } - - err = p9_client_fcreate(ofid, name, perm, mode, extension); - if (err < 0) { - p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err); - goto error; - } - - if (!(perm & P9_DMLINK)) { - /* now walk from the parent so we can get unopened fid */ - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - p9_debug(P9_DEBUG_VFS, - "p9_client_walk failed %d\n", err); - fid = NULL; - goto error; - } - /* - * instantiate inode and assign the unopened fid to the dentry - */ - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - p9_debug(P9_DEBUG_VFS, - "inode creation failed %d\n", err); - goto error; - } - v9fs_fid_add(dentry, fid); - d_instantiate(dentry, inode); - } - return ofid; -error: - if (ofid) - p9_client_clunk(ofid); - - if (fid) - p9_client_clunk(fid); - - return ERR_PTR(err); -} - -/** - * v9fs_vfs_create - VFS hook to create a regular file - * - * open(.., O_CREAT) is handled in v9fs_vfs_atomic_open(). This is only called - * for mknod(2). - * - * @dir: directory inode that is being created - * @dentry: dentry that is being deleted - * @mode: create permissions - * - */ - -static int -v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, - bool excl) -{ - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); - u32 perm = unixmode2p9mode(v9ses, mode); - struct p9_fid *fid; - - /* P9_OEXCL? */ - fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_ORDWR); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - v9fs_invalidate_inode_attr(dir); - p9_client_clunk(fid); - - return 0; -} - -/** - * v9fs_vfs_mkdir - VFS mkdir hook to create a directory - * @dir: inode that is being unlinked - * @dentry: dentry that is being unlinked - * @mode: mode for new directory - * - */ - -static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -{ - int err; - u32 perm; - struct p9_fid *fid; - struct v9fs_session_info *v9ses; - - p9_debug(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); - err = 0; - v9ses = v9fs_inode2v9ses(dir); - perm = unixmode2p9mode(v9ses, mode | S_IFDIR); - fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - fid = NULL; - } else { - inc_nlink(dir); - v9fs_invalidate_inode_attr(dir); - } - - if (fid) - p9_client_clunk(fid); - - return err; -} - -/** - * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode - * @dir: inode that is being walked from - * @dentry: dentry that is being walked to? - * @nameidata: path data - * - */ - -struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, - unsigned int flags) -{ - struct dentry *res; - struct super_block *sb; - struct v9fs_session_info *v9ses; - struct p9_fid *dfid, *fid; - struct inode *inode; - char *name; - - p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%s) %p flags: %x\n", - dir, dentry->d_name.name, dentry, flags); - - if (dentry->d_name.len > NAME_MAX) - return ERR_PTR(-ENAMETOOLONG); - - sb = dir->i_sb; - v9ses = v9fs_inode2v9ses(dir); - /* We can walk d_parent because we hold the dir->i_mutex */ - dfid = v9fs_fid_lookup(dentry->d_parent); - if (IS_ERR(dfid)) - return ERR_CAST(dfid); - - name = (char *) dentry->d_name.name; - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - if (fid == ERR_PTR(-ENOENT)) { - d_add(dentry, NULL); - return NULL; - } - return ERR_CAST(fid); - } - /* - * Make sure we don't use a wrong inode due to parallel - * unlink. For cached mode create calls request for new - * inode. But with cache disabled, lookup should do this. - */ - if (v9ses->cache) - inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); - else - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); - if (IS_ERR(inode)) { - p9_client_clunk(fid); - return ERR_CAST(inode); - } - /* - * If we had a rename on the server and a parallel lookup - * for the new name, then make sure we instantiate with - * the new name. ie look up for a/b, while on server somebody - * moved b under k and client parallely did a lookup for - * k/b. - */ - res = d_materialise_unique(dentry, inode); - if (!res) - v9fs_fid_add(dentry, fid); - else if (!IS_ERR(res)) - v9fs_fid_add(res, fid); - else - p9_client_clunk(fid); - return res; -} - -static int -v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, - struct file *file, unsigned flags, umode_t mode, - int *opened) -{ - int err; - u32 perm; - struct v9fs_inode *v9inode; - struct v9fs_session_info *v9ses; - struct p9_fid *fid, *inode_fid; - struct dentry *res = NULL; - - if (d_unhashed(dentry)) { - res = v9fs_vfs_lookup(dir, dentry, 0); - if (IS_ERR(res)) - return PTR_ERR(res); - - if (res) - dentry = res; - } - - /* Only creates */ - if (!(flags & O_CREAT) || dentry->d_inode) - return finish_no_open(file, res); - - err = 0; - fid = NULL; - v9ses = v9fs_inode2v9ses(dir); - perm = unixmode2p9mode(v9ses, mode); - fid = v9fs_create(v9ses, dir, dentry, NULL, perm, - v9fs_uflags2omode(flags, - v9fs_proto_dotu(v9ses))); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - fid = NULL; - goto error; - } - - v9fs_invalidate_inode_attr(dir); - v9inode = V9FS_I(dentry->d_inode); - mutex_lock(&v9inode->v_mutex); - if (v9ses->cache && !v9inode->writeback_fid && - ((flags & O_ACCMODE) != O_RDONLY)) { - /* - * clone a fid and add it to writeback_fid - * we do it during open time instead of - * page dirty time via write_begin/page_mkwrite - * because we want write after unlink usecase - * to work. - */ - inode_fid = v9fs_writeback_fid(dentry); - if (IS_ERR(inode_fid)) { - err = PTR_ERR(inode_fid); - mutex_unlock(&v9inode->v_mutex); - goto error; - } - v9inode->writeback_fid = (void *) inode_fid; - } - mutex_unlock(&v9inode->v_mutex); - err = finish_open(file, dentry, generic_file_open, opened); - if (err) - goto error; - - file->private_data = fid; -#ifdef CONFIG_9P_FSCACHE - if (v9ses->cache) - v9fs_cache_inode_set_cookie(dentry->d_inode, file); -#endif - - *opened |= FILE_CREATED; -out: - dput(res); - return err; - -error: - if (fid) - p9_client_clunk(fid); - goto out; -} - -/** - * v9fs_vfs_unlink - VFS unlink hook to delete an inode - * @i: inode that is being unlinked - * @d: dentry that is being unlinked - * - */ - -int v9fs_vfs_unlink(struct inode *i, struct dentry *d) -{ - return v9fs_remove(i, d, 0); -} - -/** - * v9fs_vfs_rmdir - VFS unlink hook to delete a directory - * @i: inode that is being unlinked - * @d: dentry that is being unlinked - * - */ - -int v9fs_vfs_rmdir(struct inode *i, struct dentry *d) -{ - return v9fs_remove(i, d, AT_REMOVEDIR); -} - -/** - * v9fs_vfs_rename - VFS hook to rename an inode - * @old_dir: old dir inode - * @old_dentry: old dentry - * @new_dir: new dir inode - * @new_dentry: new dentry - * - */ - -int -v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) -{ - int retval; - struct inode *old_inode; - struct inode *new_inode; - struct v9fs_session_info *v9ses; - struct p9_fid *oldfid; - struct p9_fid *olddirfid; - struct p9_fid *newdirfid; - struct p9_wstat wstat; - - p9_debug(P9_DEBUG_VFS, "\n"); - retval = 0; - old_inode = old_dentry->d_inode; - new_inode = new_dentry->d_inode; - v9ses = v9fs_inode2v9ses(old_inode); - oldfid = v9fs_fid_lookup(old_dentry); - if (IS_ERR(oldfid)) - return PTR_ERR(oldfid); - - olddirfid = v9fs_fid_clone(old_dentry->d_parent); - if (IS_ERR(olddirfid)) { - retval = PTR_ERR(olddirfid); - goto done; - } - - newdirfid = v9fs_fid_clone(new_dentry->d_parent); - if (IS_ERR(newdirfid)) { - retval = PTR_ERR(newdirfid); - goto clunk_olddir; - } - - down_write(&v9ses->rename_sem); - if (v9fs_proto_dotl(v9ses)) { - retval = p9_client_renameat(olddirfid, old_dentry->d_name.name, - newdirfid, new_dentry->d_name.name); - if (retval == -EOPNOTSUPP) - retval = p9_client_rename(oldfid, newdirfid, - new_dentry->d_name.name); - if (retval != -EOPNOTSUPP) - goto clunk_newdir; - } - if (old_dentry->d_parent != new_dentry->d_parent) { - /* - * 9P .u can only handle file rename in the same directory - */ - - p9_debug(P9_DEBUG_ERROR, "old dir and new dir are different\n"); - retval = -EXDEV; - goto clunk_newdir; - } - v9fs_blank_wstat(&wstat); - wstat.muid = v9ses->uname; - wstat.name = (char *) new_dentry->d_name.name; - retval = p9_client_wstat(oldfid, &wstat); - -clunk_newdir: - if (!retval) { - if (new_inode) { - if (S_ISDIR(new_inode->i_mode)) - clear_nlink(new_inode); - else - drop_nlink(new_inode); - } - if (S_ISDIR(old_inode->i_mode)) { - if (!new_inode) - inc_nlink(new_dir); - drop_nlink(old_dir); - } - v9fs_invalidate_inode_attr(old_inode); - v9fs_invalidate_inode_attr(old_dir); - v9fs_invalidate_inode_attr(new_dir); - - /* successful rename */ - d_move(old_dentry, new_dentry); - } - up_write(&v9ses->rename_sem); - p9_client_clunk(newdirfid); - -clunk_olddir: - p9_client_clunk(olddirfid); - -done: - return retval; -} - -/** - * v9fs_vfs_getattr - retrieve file metadata - * @mnt: mount information - * @dentry: file to get attributes on - * @stat: metadata structure to populate - * - */ - -static int -v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, - struct kstat *stat) -{ - int err; - struct v9fs_session_info *v9ses; - struct p9_fid *fid; - struct p9_wstat *st; - - p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry); - err = -EPERM; - v9ses = v9fs_dentry2v9ses(dentry); - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - generic_fillattr(dentry->d_inode, stat); - return 0; - } - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - st = p9_client_stat(fid); - if (IS_ERR(st)) - return PTR_ERR(st); - - v9fs_stat2inode(st, dentry->d_inode, dentry->d_inode->i_sb); - generic_fillattr(dentry->d_inode, stat); - - p9stat_free(st); - kfree(st); - return 0; -} - -/** - * v9fs_vfs_setattr - set file metadata - * @dentry: file whose metadata to set - * @iattr: metadata assignment structure - * - */ - -static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) -{ - int retval; - struct v9fs_session_info *v9ses; - struct p9_fid *fid; - struct p9_wstat wstat; - - p9_debug(P9_DEBUG_VFS, "\n"); - retval = inode_change_ok(dentry->d_inode, iattr); - if (retval) - return retval; - - retval = -EPERM; - v9ses = v9fs_dentry2v9ses(dentry); - fid = v9fs_fid_lookup(dentry); - if(IS_ERR(fid)) - return PTR_ERR(fid); - - v9fs_blank_wstat(&wstat); - if (iattr->ia_valid & ATTR_MODE) - wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode); - - if (iattr->ia_valid & ATTR_MTIME) - wstat.mtime = iattr->ia_mtime.tv_sec; - - if (iattr->ia_valid & ATTR_ATIME) - wstat.atime = iattr->ia_atime.tv_sec; - - if (iattr->ia_valid & ATTR_SIZE) - wstat.length = iattr->ia_size; - - if (v9fs_proto_dotu(v9ses)) { - if (iattr->ia_valid & ATTR_UID) - wstat.n_uid = iattr->ia_uid; - - if (iattr->ia_valid & ATTR_GID) - wstat.n_gid = iattr->ia_gid; - } - - /* Write all dirty data */ - if (S_ISREG(dentry->d_inode->i_mode)) - filemap_write_and_wait(dentry->d_inode->i_mapping); - - retval = p9_client_wstat(fid, &wstat); - if (retval < 0) - return retval; - - if ((iattr->ia_valid & ATTR_SIZE) && - iattr->ia_size != i_size_read(dentry->d_inode)) - truncate_setsize(dentry->d_inode, iattr->ia_size); - - v9fs_invalidate_inode_attr(dentry->d_inode); - - setattr_copy(dentry->d_inode, iattr); - mark_inode_dirty(dentry->d_inode); - return 0; -} - -/** - * v9fs_stat2inode - populate an inode structure with mistat info - * @stat: Plan 9 metadata (mistat) structure - * @inode: inode to populate - * @sb: superblock of filesystem - * - */ - -void -v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, - struct super_block *sb) -{ - umode_t mode; - char ext[32]; - char tag_name[14]; - unsigned int i_nlink; - struct v9fs_session_info *v9ses = sb->s_fs_info; - struct v9fs_inode *v9inode = V9FS_I(inode); - - set_nlink(inode, 1); - - inode->i_atime.tv_sec = stat->atime; - inode->i_mtime.tv_sec = stat->mtime; - inode->i_ctime.tv_sec = stat->mtime; - - inode->i_uid = v9ses->dfltuid; - inode->i_gid = v9ses->dfltgid; - - if (v9fs_proto_dotu(v9ses)) { - inode->i_uid = stat->n_uid; - inode->i_gid = stat->n_gid; - } - if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) { - if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) { - /* - * Hadlink support got added later to - * to the .u extension. So there can be - * server out there that doesn't support - * this even with .u extension. So check - * for non NULL stat->extension - */ - strncpy(ext, stat->extension, sizeof(ext)); - /* HARDLINKCOUNT %u */ - sscanf(ext, "%13s %u", tag_name, &i_nlink); - if (!strncmp(tag_name, "HARDLINKCOUNT", 13)) - set_nlink(inode, i_nlink); - } - } - mode = p9mode2perm(v9ses, stat); - mode |= inode->i_mode & ~S_IALLUGO; - inode->i_mode = mode; - i_size_write(inode, stat->length); - - /* not real number of blocks, but 512 byte ones ... */ - inode->i_blocks = (i_size_read(inode) + 512 - 1) >> 9; - v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR; -} - -/** - * v9fs_qid2ino - convert qid into inode number - * @qid: qid to hash - * - * BUG: potential for inode number collisions? - */ - -ino_t v9fs_qid2ino(struct p9_qid *qid) -{ - u64 path = qid->path + 2; - ino_t i = 0; - - if (sizeof(ino_t) == sizeof(path)) - memcpy(&i, &path, sizeof(ino_t)); - else - i = (ino_t) (path ^ (path >> 32)); - - return i; -} - -/** - * v9fs_readlink - read a symlink's location (internal version) - * @dentry: dentry for symlink - * @buffer: buffer to load symlink location into - * @buflen: length of buffer - * - */ - -static int v9fs_readlink(struct dentry *dentry, char *buffer, int buflen) -{ - int retval; - - struct v9fs_session_info *v9ses; - struct p9_fid *fid; - struct p9_wstat *st; - - p9_debug(P9_DEBUG_VFS, " %s\n", dentry->d_name.name); - retval = -EPERM; - v9ses = v9fs_dentry2v9ses(dentry); - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - if (!v9fs_proto_dotu(v9ses)) - return -EBADF; - - st = p9_client_stat(fid); - if (IS_ERR(st)) - return PTR_ERR(st); - - if (!(st->mode & P9_DMSYMLINK)) { - retval = -EINVAL; - goto done; - } - - /* copy extension buffer into buffer */ - retval = min(strlen(st->extension)+1, (size_t)buflen); - memcpy(buffer, st->extension, retval); - - p9_debug(P9_DEBUG_VFS, "%s -> %s (%.*s)\n", - dentry->d_name.name, st->extension, buflen, buffer); - -done: - p9stat_free(st); - kfree(st); - return retval; -} - -/** - * v9fs_vfs_follow_link - follow a symlink path - * @dentry: dentry for symlink - * @nd: nameidata - * - */ - -static void *v9fs_vfs_follow_link(struct dentry *dentry, struct nameidata *nd) -{ - int len = 0; - char *link = __getname(); - - p9_debug(P9_DEBUG_VFS, "%s\n", dentry->d_name.name); - - if (!link) - link = ERR_PTR(-ENOMEM); - else { - len = v9fs_readlink(dentry, link, PATH_MAX); - - if (len < 0) { - __putname(link); - link = ERR_PTR(len); - } else - link[min(len, PATH_MAX-1)] = 0; - } - nd_set_link(nd, link); - - return NULL; -} - -/** - * v9fs_vfs_put_link - release a symlink path - * @dentry: dentry for symlink - * @nd: nameidata - * @p: unused - * - */ - -void -v9fs_vfs_put_link(struct dentry *dentry, struct nameidata *nd, void *p) -{ - char *s = nd_get_link(nd); - - p9_debug(P9_DEBUG_VFS, " %s %s\n", - dentry->d_name.name, IS_ERR(s) ? "" : s); - if (!IS_ERR(s)) - __putname(s); -} - -/** - * v9fs_vfs_mkspecial - create a special file - * @dir: inode to create special file in - * @dentry: dentry to create - * @mode: mode to create special file - * @extension: 9p2000.u format extension string representing special file - * - */ - -static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, - u32 perm, const char *extension) -{ - struct p9_fid *fid; - struct v9fs_session_info *v9ses; - - v9ses = v9fs_inode2v9ses(dir); - if (!v9fs_proto_dotu(v9ses)) { - p9_debug(P9_DEBUG_ERROR, "not extended\n"); - return -EPERM; - } - - fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm, - P9_OREAD); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - v9fs_invalidate_inode_attr(dir); - p9_client_clunk(fid); - return 0; -} - -/** - * v9fs_vfs_symlink - helper function to create symlinks - * @dir: directory inode containing symlink - * @dentry: dentry for symlink - * @symname: symlink data - * - * See Also: 9P2000.u RFC for more information - * - */ - -static int -v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) -{ - p9_debug(P9_DEBUG_VFS, " %lu,%s,%s\n", - dir->i_ino, dentry->d_name.name, symname); - - return v9fs_vfs_mkspecial(dir, dentry, P9_DMSYMLINK, symname); -} - -/** - * v9fs_vfs_link - create a hardlink - * @old_dentry: dentry for file to link to - * @dir: inode destination for new link - * @dentry: dentry for link - * - */ - -static int -v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *dentry) -{ - int retval; - char *name; - struct p9_fid *oldfid; - - p9_debug(P9_DEBUG_VFS, " %lu,%s,%s\n", - dir->i_ino, dentry->d_name.name, old_dentry->d_name.name); - - oldfid = v9fs_fid_clone(old_dentry); - if (IS_ERR(oldfid)) - return PTR_ERR(oldfid); - - name = __getname(); - if (unlikely(!name)) { - retval = -ENOMEM; - goto clunk_fid; - } - - sprintf(name, "%d\n", oldfid->fid); - retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name); - __putname(name); - if (!retval) { - v9fs_refresh_inode(oldfid, old_dentry->d_inode); - v9fs_invalidate_inode_attr(dir); - } -clunk_fid: - p9_client_clunk(oldfid); - return retval; -} - -/** - * v9fs_vfs_mknod - create a special file - * @dir: inode destination for new link - * @dentry: dentry for file - * @mode: mode for creation - * @rdev: device associated with special file - * - */ - -static int -v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) -{ - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); - int retval; - char *name; - u32 perm; - - p9_debug(P9_DEBUG_VFS, " %lu,%s mode: %hx MAJOR: %u MINOR: %u\n", - dir->i_ino, dentry->d_name.name, mode, - MAJOR(rdev), MINOR(rdev)); - - if (!new_valid_dev(rdev)) - return -EINVAL; - - name = __getname(); - if (!name) - return -ENOMEM; - /* build extension */ - if (S_ISBLK(mode)) - sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev)); - else if (S_ISCHR(mode)) - sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev)); - else if (S_ISFIFO(mode)) - *name = 0; - else if (S_ISSOCK(mode)) - *name = 0; - else { - __putname(name); - return -EINVAL; - } - - perm = unixmode2p9mode(v9ses, mode); - retval = v9fs_vfs_mkspecial(dir, dentry, perm, name); - __putname(name); - - return retval; -} - -int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode) -{ - int umode; - dev_t rdev; - loff_t i_size; - struct p9_wstat *st; - struct v9fs_session_info *v9ses; - - v9ses = v9fs_inode2v9ses(inode); - st = p9_client_stat(fid); - if (IS_ERR(st)) - return PTR_ERR(st); - /* - * Don't update inode if the file type is different - */ - umode = p9mode2unixmode(v9ses, st, &rdev); - if ((inode->i_mode & S_IFMT) != (umode & S_IFMT)) - goto out; - - spin_lock(&inode->i_lock); - /* - * We don't want to refresh inode->i_size, - * because we may have cached data - */ - i_size = inode->i_size; - v9fs_stat2inode(st, inode, inode->i_sb); - if (v9ses->cache) - inode->i_size = i_size; - spin_unlock(&inode->i_lock); -out: - p9stat_free(st); - kfree(st); - return 0; -} - -static const struct inode_operations v9fs_dir_inode_operations_dotu = { - .create = v9fs_vfs_create, - .lookup = v9fs_vfs_lookup, - .atomic_open = v9fs_vfs_atomic_open, - .symlink = v9fs_vfs_symlink, - .link = v9fs_vfs_link, - .unlink = v9fs_vfs_unlink, - .mkdir = v9fs_vfs_mkdir, - .rmdir = v9fs_vfs_rmdir, - .mknod = v9fs_vfs_mknod, - .rename = v9fs_vfs_rename, - .getattr = v9fs_vfs_getattr, - .setattr = v9fs_vfs_setattr, -}; - -static const struct inode_operations v9fs_dir_inode_operations = { - .create = v9fs_vfs_create, - .lookup = v9fs_vfs_lookup, - .atomic_open = v9fs_vfs_atomic_open, - .unlink = v9fs_vfs_unlink, - .mkdir = v9fs_vfs_mkdir, - .rmdir = v9fs_vfs_rmdir, - .mknod = v9fs_vfs_mknod, - .rename = v9fs_vfs_rename, - .getattr = v9fs_vfs_getattr, - .setattr = v9fs_vfs_setattr, -}; - -static const struct inode_operations v9fs_file_inode_operations = { - .getattr = v9fs_vfs_getattr, - .setattr = v9fs_vfs_setattr, -}; - -static const struct inode_operations v9fs_symlink_inode_operations = { - .readlink = generic_readlink, - .follow_link = v9fs_vfs_follow_link, - .put_link = v9fs_vfs_put_link, - .getattr = v9fs_vfs_getattr, - .setattr = v9fs_vfs_setattr, -}; - diff --git a/addons/9p/src/3.10.108/vfs_inode_dotl.c b/addons/9p/src/3.10.108/vfs_inode_dotl.c deleted file mode 100644 index 65b21a24..00000000 --- a/addons/9p/src/3.10.108/vfs_inode_dotl.c +++ /dev/null @@ -1,1033 +0,0 @@ -/* - * linux/fs/9p/vfs_inode_dotl.c - * - * This file contains vfs inode ops for the 9P2000.L protocol. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" -#include "cache.h" -#include "xattr.h" -#include "acl.h" - -static int -v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, - dev_t rdev); - -/** - * v9fs_get_fsgid_for_create - Helper function to get the gid for creating a - * new file system object. This checks the S_ISGID to determine the owning - * group of the new file system object. - */ - -static kgid_t v9fs_get_fsgid_for_create(struct inode *dir_inode) -{ - BUG_ON(dir_inode == NULL); - - if (dir_inode->i_mode & S_ISGID) { - /* set_gid bit is set.*/ - return dir_inode->i_gid; - } - return current_fsgid(); -} - -static int v9fs_test_inode_dotl(struct inode *inode, void *data) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - struct p9_stat_dotl *st = (struct p9_stat_dotl *)data; - - /* don't match inode of different type */ - if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT)) - return 0; - - if (inode->i_generation != st->st_gen) - return 0; - - /* compare qid details */ - if (memcmp(&v9inode->qid.version, - &st->qid.version, sizeof(v9inode->qid.version))) - return 0; - - if (v9inode->qid.type != st->qid.type) - return 0; - return 1; -} - -/* Always get a new inode */ -static int v9fs_test_new_inode_dotl(struct inode *inode, void *data) -{ - return 0; -} - -static int v9fs_set_inode_dotl(struct inode *inode, void *data) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - struct p9_stat_dotl *st = (struct p9_stat_dotl *)data; - - memcpy(&v9inode->qid, &st->qid, sizeof(st->qid)); - inode->i_generation = st->st_gen; - return 0; -} - -static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, - struct p9_qid *qid, - struct p9_fid *fid, - struct p9_stat_dotl *st, - int new) -{ - int retval; - unsigned long i_ino; - struct inode *inode; - struct v9fs_session_info *v9ses = sb->s_fs_info; - int (*test)(struct inode *, void *); - - if (new) - test = v9fs_test_new_inode_dotl; - else - test = v9fs_test_inode_dotl; - - i_ino = v9fs_qid2ino(qid); - inode = iget5_locked(sb, i_ino, test, v9fs_set_inode_dotl, st); - if (!inode) - return ERR_PTR(-ENOMEM); - if (!(inode->i_state & I_NEW)) - return inode; - /* - * initialize the inode with the stat info - * FIXME!! we may need support for stale inodes - * later. - */ - inode->i_ino = i_ino; - retval = v9fs_init_inode(v9ses, inode, - st->st_mode, new_decode_dev(st->st_rdev)); - if (retval) - goto error; - - v9fs_stat2inode_dotl(st, inode); -#ifdef CONFIG_9P_FSCACHE - v9fs_cache_inode_get_cookie(inode); -#endif - retval = v9fs_get_acl(inode, fid); - if (retval) - goto error; - - unlock_new_inode(inode); - return inode; -error: - iget_failed(inode); - return ERR_PTR(retval); - -} - -struct inode * -v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, - struct super_block *sb, int new) -{ - struct p9_stat_dotl *st; - struct inode *inode = NULL; - - st = p9_client_getattr_dotl(fid, P9_STATS_BASIC | P9_STATS_GEN); - if (IS_ERR(st)) - return ERR_CAST(st); - - inode = v9fs_qid_iget_dotl(sb, &st->qid, fid, st, new); - kfree(st); - return inode; -} - -struct dotl_openflag_map { - int open_flag; - int dotl_flag; -}; - -static int v9fs_mapped_dotl_flags(int flags) -{ - int i; - int rflags = 0; - struct dotl_openflag_map dotl_oflag_map[] = { - { O_CREAT, P9_DOTL_CREATE }, - { O_EXCL, P9_DOTL_EXCL }, - { O_NOCTTY, P9_DOTL_NOCTTY }, - { O_APPEND, P9_DOTL_APPEND }, - { O_NONBLOCK, P9_DOTL_NONBLOCK }, - { O_DSYNC, P9_DOTL_DSYNC }, - { FASYNC, P9_DOTL_FASYNC }, - { O_DIRECT, P9_DOTL_DIRECT }, - { O_LARGEFILE, P9_DOTL_LARGEFILE }, - { O_DIRECTORY, P9_DOTL_DIRECTORY }, - { O_NOFOLLOW, P9_DOTL_NOFOLLOW }, - { O_NOATIME, P9_DOTL_NOATIME }, - { O_CLOEXEC, P9_DOTL_CLOEXEC }, - { O_SYNC, P9_DOTL_SYNC}, - }; - for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) { - if (flags & dotl_oflag_map[i].open_flag) - rflags |= dotl_oflag_map[i].dotl_flag; - } - return rflags; -} - -/** - * v9fs_open_to_dotl_flags- convert Linux specific open flags to - * plan 9 open flag. - * @flags: flags to convert - */ -int v9fs_open_to_dotl_flags(int flags) -{ - int rflags = 0; - - /* - * We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY - * and P9_DOTL_NOACCESS - */ - rflags |= flags & O_ACCMODE; - rflags |= v9fs_mapped_dotl_flags(flags); - - return rflags; -} - -/** - * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol. - * @dir: directory inode that is being created - * @dentry: dentry that is being deleted - * @mode: create permissions - * - */ - -static int -v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, - bool excl) -{ - return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0); -} - -static int -v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, - struct file *file, unsigned flags, umode_t omode, - int *opened) -{ - int err = 0; - kgid_t gid; - umode_t mode; - char *name = NULL; - struct p9_qid qid; - struct inode *inode; - struct p9_fid *fid = NULL; - struct v9fs_inode *v9inode; - struct p9_fid *dfid, *ofid, *inode_fid; - struct v9fs_session_info *v9ses; - struct posix_acl *pacl = NULL, *dacl = NULL; - struct dentry *res = NULL; - - if (d_unhashed(dentry)) { - res = v9fs_vfs_lookup(dir, dentry, 0); - if (IS_ERR(res)) - return PTR_ERR(res); - - if (res) - dentry = res; - } - - /* Only creates */ - if (!(flags & O_CREAT)) - return finish_no_open(file, res); - else if (dentry->d_inode) { - if ((flags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) - return -EEXIST; - else - return finish_no_open(file, res); - } - - v9ses = v9fs_inode2v9ses(dir); - - name = (char *) dentry->d_name.name; - p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%hx\n", - name, flags, omode); - - dfid = v9fs_fid_lookup(dentry->d_parent); - if (IS_ERR(dfid)) { - err = PTR_ERR(dfid); - p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); - goto out; - } - - /* clone a fid to use for creation */ - ofid = p9_client_walk(dfid, 0, NULL, 1); - if (IS_ERR(ofid)) { - err = PTR_ERR(ofid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); - goto out; - } - - gid = v9fs_get_fsgid_for_create(dir); - - mode = omode; - /* Update mode based on ACL value */ - err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); - if (err) { - p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n", - err); - goto error; - } - err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags), - mode, gid, &qid); - if (err < 0) { - p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n", - err); - goto error; - } - v9fs_invalidate_inode_attr(dir); - - /* instantiate inode and assign the unopened fid to the dentry */ - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); - fid = NULL; - goto error; - } - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err); - goto error; - } - /* Now set the ACL based on the default value */ - v9fs_set_create_acl(inode, fid, dacl, pacl); - - v9fs_fid_add(dentry, fid); - d_instantiate(dentry, inode); - - v9inode = V9FS_I(inode); - mutex_lock(&v9inode->v_mutex); - if (v9ses->cache && !v9inode->writeback_fid && - ((flags & O_ACCMODE) != O_RDONLY)) { - /* - * clone a fid and add it to writeback_fid - * we do it during open time instead of - * page dirty time via write_begin/page_mkwrite - * because we want write after unlink usecase - * to work. - */ - inode_fid = v9fs_writeback_fid(dentry); - if (IS_ERR(inode_fid)) { - err = PTR_ERR(inode_fid); - mutex_unlock(&v9inode->v_mutex); - goto err_clunk_old_fid; - } - v9inode->writeback_fid = (void *) inode_fid; - } - mutex_unlock(&v9inode->v_mutex); - /* Since we are opening a file, assign the open fid to the file */ - err = finish_open(file, dentry, generic_file_open, opened); - if (err) - goto err_clunk_old_fid; - file->private_data = ofid; -#ifdef CONFIG_9P_FSCACHE - if (v9ses->cache) - v9fs_cache_inode_set_cookie(inode, file); -#endif - *opened |= FILE_CREATED; -out: - v9fs_put_acl(dacl, pacl); - dput(res); - return err; - -error: - if (fid) - p9_client_clunk(fid); -err_clunk_old_fid: - if (ofid) - p9_client_clunk(ofid); - goto out; -} - -/** - * v9fs_vfs_mkdir_dotl - VFS mkdir hook to create a directory - * @dir: inode that is being unlinked - * @dentry: dentry that is being unlinked - * @mode: mode for new directory - * - */ - -static int v9fs_vfs_mkdir_dotl(struct inode *dir, - struct dentry *dentry, umode_t omode) -{ - int err; - struct v9fs_session_info *v9ses; - struct p9_fid *fid = NULL, *dfid = NULL; - kgid_t gid; - char *name; - umode_t mode; - struct inode *inode; - struct p9_qid qid; - struct dentry *dir_dentry; - struct posix_acl *dacl = NULL, *pacl = NULL; - - p9_debug(P9_DEBUG_VFS, "name %s\n", dentry->d_name.name); - err = 0; - v9ses = v9fs_inode2v9ses(dir); - - omode |= S_IFDIR; - if (dir->i_mode & S_ISGID) - omode |= S_ISGID; - - dir_dentry = dentry->d_parent; - dfid = v9fs_fid_lookup(dir_dentry); - if (IS_ERR(dfid)) { - err = PTR_ERR(dfid); - p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); - dfid = NULL; - goto error; - } - - gid = v9fs_get_fsgid_for_create(dir); - mode = omode; - /* Update mode based on ACL value */ - err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); - if (err) { - p9_debug(P9_DEBUG_VFS, "Failed to get acl values in mkdir %d\n", - err); - goto error; - } - name = (char *) dentry->d_name.name; - err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); - if (err < 0) - goto error; - - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", - err); - fid = NULL; - goto error; - } - - /* instantiate inode and assign the unopened fid to the dentry */ - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", - err); - goto error; - } - v9fs_fid_add(dentry, fid); - v9fs_set_create_acl(inode, fid, dacl, pacl); - d_instantiate(dentry, inode); - fid = NULL; - err = 0; - } else { - /* - * Not in cached mode. No need to populate - * inode with stat. We need to get an inode - * so that we can set the acl with dentry - */ - inode = v9fs_get_inode(dir->i_sb, mode, 0); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto error; - } - v9fs_set_create_acl(inode, fid, dacl, pacl); - d_instantiate(dentry, inode); - } - inc_nlink(dir); - v9fs_invalidate_inode_attr(dir); -error: - if (fid) - p9_client_clunk(fid); - v9fs_put_acl(dacl, pacl); - return err; -} - -static int -v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry, - struct kstat *stat) -{ - int err; - struct v9fs_session_info *v9ses; - struct p9_fid *fid; - struct p9_stat_dotl *st; - - p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry); - err = -EPERM; - v9ses = v9fs_dentry2v9ses(dentry); - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - generic_fillattr(dentry->d_inode, stat); - return 0; - } - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - /* Ask for all the fields in stat structure. Server will return - * whatever it supports - */ - - st = p9_client_getattr_dotl(fid, P9_STATS_ALL); - if (IS_ERR(st)) - return PTR_ERR(st); - - v9fs_stat2inode_dotl(st, dentry->d_inode); - generic_fillattr(dentry->d_inode, stat); - /* Change block size to what the server returned */ - stat->blksize = st->st_blksize; - - kfree(st); - return 0; -} - -/* - * Attribute flags. - */ -#define P9_ATTR_MODE (1 << 0) -#define P9_ATTR_UID (1 << 1) -#define P9_ATTR_GID (1 << 2) -#define P9_ATTR_SIZE (1 << 3) -#define P9_ATTR_ATIME (1 << 4) -#define P9_ATTR_MTIME (1 << 5) -#define P9_ATTR_CTIME (1 << 6) -#define P9_ATTR_ATIME_SET (1 << 7) -#define P9_ATTR_MTIME_SET (1 << 8) - -struct dotl_iattr_map { - int iattr_valid; - int p9_iattr_valid; -}; - -static int v9fs_mapped_iattr_valid(int iattr_valid) -{ - int i; - int p9_iattr_valid = 0; - struct dotl_iattr_map dotl_iattr_map[] = { - { ATTR_MODE, P9_ATTR_MODE }, - { ATTR_UID, P9_ATTR_UID }, - { ATTR_GID, P9_ATTR_GID }, - { ATTR_SIZE, P9_ATTR_SIZE }, - { ATTR_ATIME, P9_ATTR_ATIME }, - { ATTR_MTIME, P9_ATTR_MTIME }, - { ATTR_CTIME, P9_ATTR_CTIME }, - { ATTR_ATIME_SET, P9_ATTR_ATIME_SET }, - { ATTR_MTIME_SET, P9_ATTR_MTIME_SET }, - }; - for (i = 0; i < ARRAY_SIZE(dotl_iattr_map); i++) { - if (iattr_valid & dotl_iattr_map[i].iattr_valid) - p9_iattr_valid |= dotl_iattr_map[i].p9_iattr_valid; - } - return p9_iattr_valid; -} - -/** - * v9fs_vfs_setattr_dotl - set file metadata - * @dentry: file whose metadata to set - * @iattr: metadata assignment structure - * - */ - -int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) -{ - int retval; - struct v9fs_session_info *v9ses; - struct p9_fid *fid; - struct p9_iattr_dotl p9attr; - struct inode *inode = dentry->d_inode; - - p9_debug(P9_DEBUG_VFS, "\n"); - - retval = inode_change_ok(inode, iattr); - if (retval) - return retval; - - p9attr.valid = v9fs_mapped_iattr_valid(iattr->ia_valid); - p9attr.mode = iattr->ia_mode; - p9attr.uid = iattr->ia_uid; - p9attr.gid = iattr->ia_gid; - p9attr.size = iattr->ia_size; - p9attr.atime_sec = iattr->ia_atime.tv_sec; - p9attr.atime_nsec = iattr->ia_atime.tv_nsec; - p9attr.mtime_sec = iattr->ia_mtime.tv_sec; - p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec; - - retval = -EPERM; - v9ses = v9fs_dentry2v9ses(dentry); - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - /* Write all dirty data */ - if (S_ISREG(inode->i_mode)) - filemap_write_and_wait(inode->i_mapping); - - retval = p9_client_setattr(fid, &p9attr); - if (retval < 0) - return retval; - - if ((iattr->ia_valid & ATTR_SIZE) && - iattr->ia_size != i_size_read(inode)) - truncate_setsize(inode, iattr->ia_size); - - v9fs_invalidate_inode_attr(inode); - setattr_copy(inode, iattr); - mark_inode_dirty(inode); - if (iattr->ia_valid & ATTR_MODE) { - /* We also want to update ACL when we update mode bits */ - retval = v9fs_acl_chmod(inode, fid); - if (retval < 0) - return retval; - } - return 0; -} - -/** - * v9fs_stat2inode_dotl - populate an inode structure with stat info - * @stat: stat structure - * @inode: inode to populate - * @sb: superblock of filesystem - * - */ - -void -v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode) -{ - umode_t mode; - struct v9fs_inode *v9inode = V9FS_I(inode); - - if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { - inode->i_atime.tv_sec = stat->st_atime_sec; - inode->i_atime.tv_nsec = stat->st_atime_nsec; - inode->i_mtime.tv_sec = stat->st_mtime_sec; - inode->i_mtime.tv_nsec = stat->st_mtime_nsec; - inode->i_ctime.tv_sec = stat->st_ctime_sec; - inode->i_ctime.tv_nsec = stat->st_ctime_nsec; - inode->i_uid = stat->st_uid; - inode->i_gid = stat->st_gid; - set_nlink(inode, stat->st_nlink); - - mode = stat->st_mode & S_IALLUGO; - mode |= inode->i_mode & ~S_IALLUGO; - inode->i_mode = mode; - - i_size_write(inode, stat->st_size); - inode->i_blocks = stat->st_blocks; - } else { - if (stat->st_result_mask & P9_STATS_ATIME) { - inode->i_atime.tv_sec = stat->st_atime_sec; - inode->i_atime.tv_nsec = stat->st_atime_nsec; - } - if (stat->st_result_mask & P9_STATS_MTIME) { - inode->i_mtime.tv_sec = stat->st_mtime_sec; - inode->i_mtime.tv_nsec = stat->st_mtime_nsec; - } - if (stat->st_result_mask & P9_STATS_CTIME) { - inode->i_ctime.tv_sec = stat->st_ctime_sec; - inode->i_ctime.tv_nsec = stat->st_ctime_nsec; - } - if (stat->st_result_mask & P9_STATS_UID) - inode->i_uid = stat->st_uid; - if (stat->st_result_mask & P9_STATS_GID) - inode->i_gid = stat->st_gid; - if (stat->st_result_mask & P9_STATS_NLINK) - set_nlink(inode, stat->st_nlink); - if (stat->st_result_mask & P9_STATS_MODE) { - inode->i_mode = stat->st_mode; - if ((S_ISBLK(inode->i_mode)) || - (S_ISCHR(inode->i_mode))) - init_special_inode(inode, inode->i_mode, - inode->i_rdev); - } - if (stat->st_result_mask & P9_STATS_RDEV) - inode->i_rdev = new_decode_dev(stat->st_rdev); - if (stat->st_result_mask & P9_STATS_SIZE) - i_size_write(inode, stat->st_size); - if (stat->st_result_mask & P9_STATS_BLOCKS) - inode->i_blocks = stat->st_blocks; - } - if (stat->st_result_mask & P9_STATS_GEN) - inode->i_generation = stat->st_gen; - - /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION - * because the inode structure does not have fields for them. - */ - v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR; -} - -static int -v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry, - const char *symname) -{ - int err; - kgid_t gid; - char *name; - struct p9_qid qid; - struct inode *inode; - struct p9_fid *dfid; - struct p9_fid *fid = NULL; - struct v9fs_session_info *v9ses; - - name = (char *) dentry->d_name.name; - p9_debug(P9_DEBUG_VFS, "%lu,%s,%s\n", dir->i_ino, name, symname); - v9ses = v9fs_inode2v9ses(dir); - - dfid = v9fs_fid_lookup(dentry->d_parent); - if (IS_ERR(dfid)) { - err = PTR_ERR(dfid); - p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); - return err; - } - - gid = v9fs_get_fsgid_for_create(dir); - - /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */ - err = p9_client_symlink(dfid, name, (char *)symname, gid, &qid); - - if (err < 0) { - p9_debug(P9_DEBUG_VFS, "p9_client_symlink failed %d\n", err); - goto error; - } - - v9fs_invalidate_inode_attr(dir); - if (v9ses->cache) { - /* Now walk from the parent so we can get an unopened fid. */ - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", - err); - fid = NULL; - goto error; - } - - /* instantiate inode and assign the unopened fid to dentry */ - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", - err); - goto error; - } - v9fs_fid_add(dentry, fid); - d_instantiate(dentry, inode); - fid = NULL; - err = 0; - } else { - /* Not in cached mode. No need to populate inode with stat */ - inode = v9fs_get_inode(dir->i_sb, S_IFLNK, 0); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto error; - } - d_instantiate(dentry, inode); - } - -error: - if (fid) - p9_client_clunk(fid); - - return err; -} - -/** - * v9fs_vfs_link_dotl - create a hardlink for dotl - * @old_dentry: dentry for file to link to - * @dir: inode destination for new link - * @dentry: dentry for link - * - */ - -static int -v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, - struct dentry *dentry) -{ - int err; - char *name; - struct dentry *dir_dentry; - struct p9_fid *dfid, *oldfid; - struct v9fs_session_info *v9ses; - - p9_debug(P9_DEBUG_VFS, "dir ino: %lu, old_name: %s, new_name: %s\n", - dir->i_ino, old_dentry->d_name.name, dentry->d_name.name); - - v9ses = v9fs_inode2v9ses(dir); - dir_dentry = dentry->d_parent; - dfid = v9fs_fid_lookup(dir_dentry); - if (IS_ERR(dfid)) - return PTR_ERR(dfid); - - oldfid = v9fs_fid_lookup(old_dentry); - if (IS_ERR(oldfid)) - return PTR_ERR(oldfid); - - name = (char *) dentry->d_name.name; - - err = p9_client_link(dfid, oldfid, (char *)dentry->d_name.name); - - if (err < 0) { - p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err); - return err; - } - - v9fs_invalidate_inode_attr(dir); - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - /* Get the latest stat info from server. */ - struct p9_fid *fid; - fid = v9fs_fid_lookup(old_dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - v9fs_refresh_inode_dotl(fid, old_dentry->d_inode); - } - ihold(old_dentry->d_inode); - d_instantiate(dentry, old_dentry->d_inode); - - return err; -} - -/** - * v9fs_vfs_mknod_dotl - create a special file - * @dir: inode destination for new link - * @dentry: dentry for file - * @mode: mode for creation - * @rdev: device associated with special file - * - */ -static int -v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, - dev_t rdev) -{ - int err; - kgid_t gid; - char *name; - umode_t mode; - struct v9fs_session_info *v9ses; - struct p9_fid *fid = NULL, *dfid = NULL; - struct inode *inode; - struct p9_qid qid; - struct dentry *dir_dentry; - struct posix_acl *dacl = NULL, *pacl = NULL; - - p9_debug(P9_DEBUG_VFS, " %lu,%s mode: %hx MAJOR: %u MINOR: %u\n", - dir->i_ino, dentry->d_name.name, omode, - MAJOR(rdev), MINOR(rdev)); - - if (!new_valid_dev(rdev)) - return -EINVAL; - - v9ses = v9fs_inode2v9ses(dir); - dir_dentry = dentry->d_parent; - dfid = v9fs_fid_lookup(dir_dentry); - if (IS_ERR(dfid)) { - err = PTR_ERR(dfid); - p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); - dfid = NULL; - goto error; - } - - gid = v9fs_get_fsgid_for_create(dir); - mode = omode; - /* Update mode based on ACL value */ - err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); - if (err) { - p9_debug(P9_DEBUG_VFS, "Failed to get acl values in mknod %d\n", - err); - goto error; - } - name = (char *) dentry->d_name.name; - - err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid); - if (err < 0) - goto error; - - v9fs_invalidate_inode_attr(dir); - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", - err); - fid = NULL; - goto error; - } - - /* instantiate inode and assign the unopened fid to the dentry */ - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", - err); - goto error; - } - v9fs_set_create_acl(inode, fid, dacl, pacl); - v9fs_fid_add(dentry, fid); - d_instantiate(dentry, inode); - fid = NULL; - err = 0; - } else { - /* - * Not in cached mode. No need to populate inode with stat. - * socket syscall returns a fd, so we need instantiate - */ - inode = v9fs_get_inode(dir->i_sb, mode, rdev); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto error; - } - v9fs_set_create_acl(inode, fid, dacl, pacl); - d_instantiate(dentry, inode); - } -error: - if (fid) - p9_client_clunk(fid); - v9fs_put_acl(dacl, pacl); - return err; -} - -/** - * v9fs_vfs_follow_link_dotl - follow a symlink path - * @dentry: dentry for symlink - * @nd: nameidata - * - */ - -static void * -v9fs_vfs_follow_link_dotl(struct dentry *dentry, struct nameidata *nd) -{ - int retval; - struct p9_fid *fid; - char *link = __getname(); - char *target; - - p9_debug(P9_DEBUG_VFS, "%s\n", dentry->d_name.name); - - if (!link) { - link = ERR_PTR(-ENOMEM); - goto ndset; - } - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) { - __putname(link); - link = ERR_CAST(fid); - goto ndset; - } - retval = p9_client_readlink(fid, &target); - if (!retval) { - strcpy(link, target); - kfree(target); - goto ndset; - } - __putname(link); - link = ERR_PTR(retval); -ndset: - nd_set_link(nd, link); - return NULL; -} - -int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode) -{ - loff_t i_size; - struct p9_stat_dotl *st; - struct v9fs_session_info *v9ses; - - v9ses = v9fs_inode2v9ses(inode); - st = p9_client_getattr_dotl(fid, P9_STATS_ALL); - if (IS_ERR(st)) - return PTR_ERR(st); - /* - * Don't update inode if the file type is different - */ - if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT)) - goto out; - - spin_lock(&inode->i_lock); - /* - * We don't want to refresh inode->i_size, - * because we may have cached data - */ - i_size = inode->i_size; - v9fs_stat2inode_dotl(st, inode); - if (v9ses->cache) - inode->i_size = i_size; - spin_unlock(&inode->i_lock); -out: - kfree(st); - return 0; -} - -const struct inode_operations v9fs_dir_inode_operations_dotl = { - .create = v9fs_vfs_create_dotl, - .atomic_open = v9fs_vfs_atomic_open_dotl, - .lookup = v9fs_vfs_lookup, - .link = v9fs_vfs_link_dotl, - .symlink = v9fs_vfs_symlink_dotl, - .unlink = v9fs_vfs_unlink, - .mkdir = v9fs_vfs_mkdir_dotl, - .rmdir = v9fs_vfs_rmdir, - .mknod = v9fs_vfs_mknod_dotl, - .rename = v9fs_vfs_rename, - .getattr = v9fs_vfs_getattr_dotl, - .setattr = v9fs_vfs_setattr_dotl, - .setxattr = generic_setxattr, - .getxattr = generic_getxattr, - .removexattr = generic_removexattr, - .listxattr = v9fs_listxattr, - .get_acl = v9fs_iop_get_acl, -}; - -const struct inode_operations v9fs_file_inode_operations_dotl = { - .getattr = v9fs_vfs_getattr_dotl, - .setattr = v9fs_vfs_setattr_dotl, - .setxattr = generic_setxattr, - .getxattr = generic_getxattr, - .removexattr = generic_removexattr, - .listxattr = v9fs_listxattr, - .get_acl = v9fs_iop_get_acl, -}; - -const struct inode_operations v9fs_symlink_inode_operations_dotl = { - .readlink = generic_readlink, - .follow_link = v9fs_vfs_follow_link_dotl, - .put_link = v9fs_vfs_put_link, - .getattr = v9fs_vfs_getattr_dotl, - .setattr = v9fs_vfs_setattr_dotl, - .setxattr = generic_setxattr, - .getxattr = generic_getxattr, - .removexattr = generic_removexattr, - .listxattr = v9fs_listxattr, -}; diff --git a/addons/9p/src/3.10.108/vfs_super.c b/addons/9p/src/3.10.108/vfs_super.c deleted file mode 100644 index 2756dcd5..00000000 --- a/addons/9p/src/3.10.108/vfs_super.c +++ /dev/null @@ -1,368 +0,0 @@ -/* - * linux/fs/9p/vfs_super.c - * - * This file contians superblock ops for 9P2000. It is intended that - * you mount this file system on directories. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" -#include "xattr.h" -#include "acl.h" - -static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl; - -/** - * v9fs_set_super - set the superblock - * @s: super block - * @data: file system specific data - * - */ - -static int v9fs_set_super(struct super_block *s, void *data) -{ - s->s_fs_info = data; - return set_anon_super(s, data); -} - -/** - * v9fs_fill_super - populate superblock with info - * @sb: superblock - * @v9ses: session information - * @flags: flags propagated from v9fs_mount() - * - */ - -static void -v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, - int flags, void *data) -{ - sb->s_maxbytes = MAX_LFS_FILESIZE; - sb->s_blocksize_bits = fls(v9ses->maxdata - 1); - sb->s_blocksize = 1 << sb->s_blocksize_bits; - sb->s_magic = V9FS_MAGIC; - if (v9fs_proto_dotl(v9ses)) { - sb->s_op = &v9fs_super_ops_dotl; - sb->s_xattr = v9fs_xattr_handlers; - } else - sb->s_op = &v9fs_super_ops; - sb->s_bdi = &v9ses->bdi; - if (v9ses->cache) - sb->s_bdi->ra_pages = (VM_MAX_READAHEAD * 1024)/PAGE_CACHE_SIZE; - - sb->s_flags |= MS_ACTIVE | MS_DIRSYNC | MS_NOATIME; - if (!v9ses->cache) - sb->s_flags |= MS_SYNCHRONOUS; - -#ifdef CONFIG_9P_FS_POSIX_ACL - if ((v9ses->flags & V9FS_ACL_MASK) == V9FS_POSIX_ACL) - sb->s_flags |= MS_POSIXACL; -#endif - - save_mount_options(sb, data); -} - -/** - * v9fs_mount - mount a superblock - * @fs_type: file system type - * @flags: mount flags - * @dev_name: device name that was mounted - * @data: mount options - * - */ - -static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) -{ - struct super_block *sb = NULL; - struct inode *inode = NULL; - struct dentry *root = NULL; - struct v9fs_session_info *v9ses = NULL; - umode_t mode = S_IRWXUGO | S_ISVTX; - struct p9_fid *fid; - int retval = 0; - - p9_debug(P9_DEBUG_VFS, "\n"); - - v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); - if (!v9ses) - return ERR_PTR(-ENOMEM); - - fid = v9fs_session_init(v9ses, dev_name, data); - if (IS_ERR(fid)) { - retval = PTR_ERR(fid); - /* - * we need to call session_close to tear down some - * of the data structure setup by session_init - */ - goto close_session; - } - - sb = sget(fs_type, NULL, v9fs_set_super, flags, v9ses); - if (IS_ERR(sb)) { - retval = PTR_ERR(sb); - goto clunk_fid; - } - v9fs_fill_super(sb, v9ses, flags, data); - - if (v9ses->cache) - sb->s_d_op = &v9fs_cached_dentry_operations; - else - sb->s_d_op = &v9fs_dentry_operations; - - inode = v9fs_get_inode(sb, S_IFDIR | mode, 0); - if (IS_ERR(inode)) { - retval = PTR_ERR(inode); - goto release_sb; - } - - root = d_make_root(inode); - if (!root) { - retval = -ENOMEM; - goto release_sb; - } - sb->s_root = root; - if (v9fs_proto_dotl(v9ses)) { - struct p9_stat_dotl *st = NULL; - st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); - if (IS_ERR(st)) { - retval = PTR_ERR(st); - goto release_sb; - } - root->d_inode->i_ino = v9fs_qid2ino(&st->qid); - v9fs_stat2inode_dotl(st, root->d_inode); - kfree(st); - } else { - struct p9_wstat *st = NULL; - st = p9_client_stat(fid); - if (IS_ERR(st)) { - retval = PTR_ERR(st); - goto release_sb; - } - - root->d_inode->i_ino = v9fs_qid2ino(&st->qid); - v9fs_stat2inode(st, root->d_inode, sb); - - p9stat_free(st); - kfree(st); - } - retval = v9fs_get_acl(inode, fid); - if (retval) - goto release_sb; - v9fs_fid_add(root, fid); - - p9_debug(P9_DEBUG_VFS, " simple set mount, return 0\n"); - return dget(sb->s_root); - -clunk_fid: - p9_client_clunk(fid); -close_session: - v9fs_session_close(v9ses); - kfree(v9ses); - return ERR_PTR(retval); - -release_sb: - /* - * we will do the session_close and root dentry release - * in the below call. But we need to clunk fid, because we haven't - * attached the fid to dentry so it won't get clunked - * automatically. - */ - p9_client_clunk(fid); - deactivate_locked_super(sb); - return ERR_PTR(retval); -} - -/** - * v9fs_kill_super - Kill Superblock - * @s: superblock - * - */ - -static void v9fs_kill_super(struct super_block *s) -{ - struct v9fs_session_info *v9ses = s->s_fs_info; - - p9_debug(P9_DEBUG_VFS, " %p\n", s); - - kill_anon_super(s); - - v9fs_session_cancel(v9ses); - v9fs_session_close(v9ses); - kfree(v9ses); - s->s_fs_info = NULL; - p9_debug(P9_DEBUG_VFS, "exiting kill_super\n"); -} - -static void -v9fs_umount_begin(struct super_block *sb) -{ - struct v9fs_session_info *v9ses; - - v9ses = sb->s_fs_info; - v9fs_session_begin_cancel(v9ses); -} - -static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf) -{ - struct v9fs_session_info *v9ses; - struct p9_fid *fid; - struct p9_rstatfs rs; - int res; - - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) { - res = PTR_ERR(fid); - goto done; - } - - v9ses = v9fs_dentry2v9ses(dentry); - if (v9fs_proto_dotl(v9ses)) { - res = p9_client_statfs(fid, &rs); - if (res == 0) { - buf->f_type = rs.type; - buf->f_bsize = rs.bsize; - buf->f_blocks = rs.blocks; - buf->f_bfree = rs.bfree; - buf->f_bavail = rs.bavail; - buf->f_files = rs.files; - buf->f_ffree = rs.ffree; - buf->f_fsid.val[0] = rs.fsid & 0xFFFFFFFFUL; - buf->f_fsid.val[1] = (rs.fsid >> 32) & 0xFFFFFFFFUL; - buf->f_namelen = rs.namelen; - } - if (res != -ENOSYS) - goto done; - } - res = simple_statfs(dentry, buf); -done: - return res; -} - -static int v9fs_drop_inode(struct inode *inode) -{ - struct v9fs_session_info *v9ses; - v9ses = v9fs_inode2v9ses(inode); - if (v9ses->cache) - return generic_drop_inode(inode); - /* - * in case of non cached mode always drop the - * the inode because we want the inode attribute - * to always match that on the server. - */ - return 1; -} - -static int v9fs_write_inode(struct inode *inode, - struct writeback_control *wbc) -{ - int ret; - struct p9_wstat wstat; - struct v9fs_inode *v9inode; - /* - * send an fsync request to server irrespective of - * wbc->sync_mode. - */ - p9_debug(P9_DEBUG_VFS, "%s: inode %p\n", __func__, inode); - v9inode = V9FS_I(inode); - if (!v9inode->writeback_fid) - return 0; - v9fs_blank_wstat(&wstat); - - ret = p9_client_wstat(v9inode->writeback_fid, &wstat); - if (ret < 0) { - __mark_inode_dirty(inode, I_DIRTY_DATASYNC); - return ret; - } - return 0; -} - -static int v9fs_write_inode_dotl(struct inode *inode, - struct writeback_control *wbc) -{ - int ret; - struct v9fs_inode *v9inode; - /* - * send an fsync request to server irrespective of - * wbc->sync_mode. - */ - p9_debug(P9_DEBUG_VFS, "%s: inode %p\n", __func__, inode); - v9inode = V9FS_I(inode); - if (!v9inode->writeback_fid) - return 0; - ret = p9_client_fsync(v9inode->writeback_fid, 0); - if (ret < 0) { - __mark_inode_dirty(inode, I_DIRTY_DATASYNC); - return ret; - } - return 0; -} - -static const struct super_operations v9fs_super_ops = { - .alloc_inode = v9fs_alloc_inode, - .destroy_inode = v9fs_destroy_inode, - .statfs = simple_statfs, - .evict_inode = v9fs_evict_inode, - .show_options = generic_show_options, - .umount_begin = v9fs_umount_begin, - .write_inode = v9fs_write_inode, -}; - -static const struct super_operations v9fs_super_ops_dotl = { - .alloc_inode = v9fs_alloc_inode, - .destroy_inode = v9fs_destroy_inode, - .statfs = v9fs_statfs, - .drop_inode = v9fs_drop_inode, - .evict_inode = v9fs_evict_inode, - .show_options = generic_show_options, - .umount_begin = v9fs_umount_begin, - .write_inode = v9fs_write_inode_dotl, -}; - -struct file_system_type v9fs_fs_type = { - .name = "9p", - .mount = v9fs_mount, - .kill_sb = v9fs_kill_super, - .owner = THIS_MODULE, - .fs_flags = FS_RENAME_DOES_D_MOVE, -}; -MODULE_ALIAS_FS("9p"); diff --git a/addons/9p/src/3.10.108/xattr.c b/addons/9p/src/3.10.108/xattr.c deleted file mode 100644 index c45e016b..00000000 --- a/addons/9p/src/3.10.108/xattr.c +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright IBM Corporation, 2010 - * Author Aneesh Kumar K.V - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -#include -#include -#include -#include -#include - -#include "fid.h" -#include "xattr.h" - -ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name, - void *buffer, size_t buffer_size) -{ - ssize_t retval; - int msize, read_count; - u64 offset = 0, attr_size; - struct p9_fid *attr_fid; - - attr_fid = p9_client_xattrwalk(fid, name, &attr_size); - if (IS_ERR(attr_fid)) { - retval = PTR_ERR(attr_fid); - p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n", - retval); - attr_fid = NULL; - goto error; - } - if (!buffer_size) { - /* request to get the attr_size */ - retval = attr_size; - goto error; - } - if (attr_size > buffer_size) { - retval = -ERANGE; - goto error; - } - msize = attr_fid->clnt->msize; - while (attr_size) { - if (attr_size > (msize - P9_IOHDRSZ)) - read_count = msize - P9_IOHDRSZ; - else - read_count = attr_size; - read_count = p9_client_read(attr_fid, ((char *)buffer)+offset, - NULL, offset, read_count); - if (read_count < 0) { - /* error in xattr read */ - retval = read_count; - goto error; - } - offset += read_count; - attr_size -= read_count; - } - /* Total read xattr bytes */ - retval = offset; -error: - if (attr_fid) - p9_client_clunk(attr_fid); - return retval; - -} - - -/* - * v9fs_xattr_get() - * - * Copy an extended attribute into the buffer - * provided, or compute the buffer size required. - * Buffer is NULL to compute the size of the buffer required. - * - * Returns a negative error number on failure, or the number of bytes - * used / required on success. - */ -ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name, - void *buffer, size_t buffer_size) -{ - struct p9_fid *fid; - - p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu\n", - name, buffer_size); - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - return v9fs_fid_xattr_get(fid, name, buffer, buffer_size); -} - -/* - * v9fs_xattr_set() - * - * Create, replace or remove an extended attribute for this inode. Buffer - * is NULL to remove an existing extended attribute, and non-NULL to - * either replace an existing extended attribute, or create a new extended - * attribute. The flags XATTR_REPLACE and XATTR_CREATE - * specify that an extended attribute must exist and must not exist - * previous to the call, respectively. - * - * Returns 0, or a negative error number on failure. - */ -int v9fs_xattr_set(struct dentry *dentry, const char *name, - const void *value, size_t value_len, int flags) -{ - struct p9_fid *fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - return v9fs_fid_xattr_set(fid, name, value, value_len, flags); -} - -int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, - const void *value, size_t value_len, int flags) -{ - u64 offset = 0; - int retval, msize, write_count; - - p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", - name, value_len, flags); - - /* Clone it */ - fid = p9_client_walk(fid, 0, NULL, 1); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - /* - * On success fid points to xattr - */ - retval = p9_client_xattrcreate(fid, name, value_len, flags); - if (retval < 0) { - p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n", - retval); - p9_client_clunk(fid); - return retval; - } - msize = fid->clnt->msize; - while (value_len) { - if (value_len > (msize - P9_IOHDRSZ)) - write_count = msize - P9_IOHDRSZ; - else - write_count = value_len; - write_count = p9_client_write(fid, ((char *)value)+offset, - NULL, offset, write_count); - if (write_count < 0) { - /* error in xattr write */ - retval = write_count; - break; - } - offset += write_count; - value_len -= write_count; - } - return p9_client_clunk(fid); -} - -ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) -{ - return v9fs_xattr_get(dentry, NULL, buffer, buffer_size); -} - -const struct xattr_handler *v9fs_xattr_handlers[] = { - &v9fs_xattr_user_handler, -#ifdef CONFIG_9P_FS_POSIX_ACL - &v9fs_xattr_acl_access_handler, - &v9fs_xattr_acl_default_handler, -#endif - NULL -}; diff --git a/addons/9p/src/3.10.108/xattr.h b/addons/9p/src/3.10.108/xattr.h deleted file mode 100644 index eec348a3..00000000 --- a/addons/9p/src/3.10.108/xattr.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright IBM Corporation, 2010 - * Author Aneesh Kumar K.V - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ -#ifndef FS_9P_XATTR_H -#define FS_9P_XATTR_H - -#include -#include -#include - -extern const struct xattr_handler *v9fs_xattr_handlers[]; -extern struct xattr_handler v9fs_xattr_user_handler; -extern const struct xattr_handler v9fs_xattr_acl_access_handler; -extern const struct xattr_handler v9fs_xattr_acl_default_handler; - -extern ssize_t v9fs_fid_xattr_get(struct p9_fid *, const char *, - void *, size_t); -extern ssize_t v9fs_xattr_get(struct dentry *, const char *, - void *, size_t); -extern int v9fs_fid_xattr_set(struct p9_fid *, const char *, - const void *, size_t, int); -extern int v9fs_xattr_set(struct dentry *, const char *, - const void *, size_t, int); -extern ssize_t v9fs_listxattr(struct dentry *, char *, size_t); -#endif /* FS_9P_XATTR_H */ diff --git a/addons/9p/src/3.10.108/xattr_user.c b/addons/9p/src/3.10.108/xattr_user.c deleted file mode 100644 index d0b701b7..00000000 --- a/addons/9p/src/3.10.108/xattr_user.c +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright IBM Corporation, 2010 - * Author Aneesh Kumar K.V - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - - -#include -#include -#include -#include -#include "xattr.h" - -static int v9fs_xattr_user_get(struct dentry *dentry, const char *name, - void *buffer, size_t size, int type) -{ - int retval; - char *full_name; - size_t name_len; - size_t prefix_len = XATTR_USER_PREFIX_LEN; - - if (name == NULL) - return -EINVAL; - - if (strcmp(name, "") == 0) - return -EINVAL; - - name_len = strlen(name); - full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); - if (!full_name) - return -ENOMEM; - memcpy(full_name, XATTR_USER_PREFIX, prefix_len); - memcpy(full_name+prefix_len, name, name_len); - full_name[prefix_len + name_len] = '\0'; - - retval = v9fs_xattr_get(dentry, full_name, buffer, size); - kfree(full_name); - return retval; -} - -static int v9fs_xattr_user_set(struct dentry *dentry, const char *name, - const void *value, size_t size, int flags, int type) -{ - int retval; - char *full_name; - size_t name_len; - size_t prefix_len = XATTR_USER_PREFIX_LEN; - - if (name == NULL) - return -EINVAL; - - if (strcmp(name, "") == 0) - return -EINVAL; - - name_len = strlen(name); - full_name = kmalloc(prefix_len + name_len + 1 , GFP_KERNEL); - if (!full_name) - return -ENOMEM; - memcpy(full_name, XATTR_USER_PREFIX, prefix_len); - memcpy(full_name + prefix_len, name, name_len); - full_name[prefix_len + name_len] = '\0'; - - retval = v9fs_xattr_set(dentry, full_name, value, size, flags); - kfree(full_name); - return retval; -} - -struct xattr_handler v9fs_xattr_user_handler = { - .prefix = XATTR_USER_PREFIX, - .get = v9fs_xattr_user_get, - .set = v9fs_xattr_user_set, -}; diff --git a/addons/9p/src/4.4.180/Makefile b/addons/9p/src/4.4.180/Makefile deleted file mode 100644 index 2fb0605e..00000000 --- a/addons/9p/src/4.4.180/Makefile +++ /dev/null @@ -1,35 +0,0 @@ -obj-m := 9p.o - -9p-objs := \ - vfs_super.o \ - vfs_inode.o \ - vfs_inode_dotl.o \ - vfs_addr.o \ - vfs_file.o \ - vfs_dir.o \ - vfs_dentry.o \ - v9fs.o \ - fid.o \ - xattr.o - -9p-y += cache.o -9p-n += acl.o - -obj-m := 9pnet.o -obj-m += 9pnet_virtio.o -obj-n += 9pnet_rdma.o - -9pnet-objs := \ - mod.o \ - client.o \ - error.o \ - util.o \ - protocol.o \ - trans_fd.o \ - trans_common.o \ - -9pnet_virtio-objs := \ - trans_virtio.o - -9pnet_rdma-objs := \ - trans_rdma.o diff --git a/addons/9p/src/4.4.180/acl.c b/addons/9p/src/4.4.180/acl.c deleted file mode 100644 index c30c6cea..00000000 --- a/addons/9p/src/4.4.180/acl.c +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright IBM Corporation, 2010 - * Author Aneesh Kumar K.V - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include "xattr.h" -#include "acl.h" -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" - -static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name) -{ - ssize_t size; - void *value = NULL; - struct posix_acl *acl = NULL; - - size = v9fs_fid_xattr_get(fid, name, NULL, 0); - if (size > 0) { - value = kzalloc(size, GFP_NOFS); - if (!value) - return ERR_PTR(-ENOMEM); - size = v9fs_fid_xattr_get(fid, name, value, size); - if (size > 0) { - acl = posix_acl_from_xattr(&init_user_ns, value, size); - if (IS_ERR(acl)) - goto err_out; - } - } else if (size == -ENODATA || size == 0 || - size == -ENOSYS || size == -EOPNOTSUPP) { - acl = NULL; - } else - acl = ERR_PTR(-EIO); - -err_out: - kfree(value); - return acl; -} - -int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) -{ - int retval = 0; - struct posix_acl *pacl, *dacl; - struct v9fs_session_info *v9ses; - - v9ses = v9fs_inode2v9ses(inode); - if (((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) || - ((v9ses->flags & V9FS_ACL_MASK) != V9FS_POSIX_ACL)) { - set_cached_acl(inode, ACL_TYPE_DEFAULT, NULL); - set_cached_acl(inode, ACL_TYPE_ACCESS, NULL); - return 0; - } - /* get the default/access acl values and cache them */ - dacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_DEFAULT); - pacl = __v9fs_get_acl(fid, POSIX_ACL_XATTR_ACCESS); - - if (!IS_ERR(dacl) && !IS_ERR(pacl)) { - set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl); - set_cached_acl(inode, ACL_TYPE_ACCESS, pacl); - } else - retval = -EIO; - - if (!IS_ERR(dacl)) - posix_acl_release(dacl); - - if (!IS_ERR(pacl)) - posix_acl_release(pacl); - - return retval; -} - -static struct posix_acl *v9fs_get_cached_acl(struct inode *inode, int type) -{ - struct posix_acl *acl; - /* - * 9p Always cache the acl value when - * instantiating the inode (v9fs_inode_from_fid) - */ - acl = get_cached_acl(inode, type); - BUG_ON(acl == ACL_NOT_CACHED); - return acl; -} - -struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type) -{ - struct v9fs_session_info *v9ses; - - v9ses = v9fs_inode2v9ses(inode); - if (((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) || - ((v9ses->flags & V9FS_ACL_MASK) != V9FS_POSIX_ACL)) { - /* - * On access = client and acl = on mode get the acl - * values from the server - */ - return NULL; - } - return v9fs_get_cached_acl(inode, type); - -} - -static int v9fs_set_acl(struct p9_fid *fid, int type, struct posix_acl *acl) -{ - int retval; - char *name; - size_t size; - void *buffer; - if (!acl) - return 0; - - /* Set a setxattr request to server */ - size = posix_acl_xattr_size(acl->a_count); - buffer = kmalloc(size, GFP_KERNEL); - if (!buffer) - return -ENOMEM; - retval = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); - if (retval < 0) - goto err_free_out; - switch (type) { - case ACL_TYPE_ACCESS: - name = POSIX_ACL_XATTR_ACCESS; - break; - case ACL_TYPE_DEFAULT: - name = POSIX_ACL_XATTR_DEFAULT; - break; - default: - BUG(); - } - retval = v9fs_fid_xattr_set(fid, name, buffer, size, 0); -err_free_out: - kfree(buffer); - return retval; -} - -int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid) -{ - int retval = 0; - struct posix_acl *acl; - - if (S_ISLNK(inode->i_mode)) - return -EOPNOTSUPP; - acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS); - if (acl) { - retval = __posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); - if (retval) - return retval; - set_cached_acl(inode, ACL_TYPE_ACCESS, acl); - retval = v9fs_set_acl(fid, ACL_TYPE_ACCESS, acl); - posix_acl_release(acl); - } - return retval; -} - -int v9fs_set_create_acl(struct inode *inode, struct p9_fid *fid, - struct posix_acl *dacl, struct posix_acl *acl) -{ - set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl); - set_cached_acl(inode, ACL_TYPE_ACCESS, acl); - v9fs_set_acl(fid, ACL_TYPE_DEFAULT, dacl); - v9fs_set_acl(fid, ACL_TYPE_ACCESS, acl); - return 0; -} - -void v9fs_put_acl(struct posix_acl *dacl, - struct posix_acl *acl) -{ - posix_acl_release(dacl); - posix_acl_release(acl); -} - -int v9fs_acl_mode(struct inode *dir, umode_t *modep, - struct posix_acl **dpacl, struct posix_acl **pacl) -{ - int retval = 0; - umode_t mode = *modep; - struct posix_acl *acl = NULL; - - if (!S_ISLNK(mode)) { - acl = v9fs_get_cached_acl(dir, ACL_TYPE_DEFAULT); - if (IS_ERR(acl)) - return PTR_ERR(acl); - if (!acl) - mode &= ~current_umask(); - } - if (acl) { - if (S_ISDIR(mode)) - *dpacl = posix_acl_dup(acl); - retval = __posix_acl_create(&acl, GFP_NOFS, &mode); - if (retval < 0) - return retval; - if (retval > 0) - *pacl = acl; - else - posix_acl_release(acl); - } - *modep = mode; - return 0; -} - -static int v9fs_xattr_get_acl(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) -{ - struct v9fs_session_info *v9ses; - struct posix_acl *acl; - int error; - - if (strcmp(name, "") != 0) - return -EINVAL; - - v9ses = v9fs_dentry2v9ses(dentry); - /* - * We allow set/get/list of acl when access=client is not specified - */ - if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) - return v9fs_xattr_get(dentry, handler->prefix, buffer, size); - - acl = v9fs_get_cached_acl(d_inode(dentry), handler->flags); - if (IS_ERR(acl)) - return PTR_ERR(acl); - if (acl == NULL) - return -ENODATA; - error = posix_acl_to_xattr(&init_user_ns, acl, buffer, size); - posix_acl_release(acl); - - return error; -} - -static int v9fs_xattr_set_acl(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) -{ - int retval; - struct posix_acl *acl; - struct v9fs_session_info *v9ses; - struct inode *inode = d_inode(dentry); - - if (strcmp(name, "") != 0) - return -EINVAL; - - v9ses = v9fs_dentry2v9ses(dentry); - /* - * set the attribute on the remote. Without even looking at the - * xattr value. We leave it to the server to validate - */ - if ((v9ses->flags & V9FS_ACCESS_MASK) != V9FS_ACCESS_CLIENT) - return v9fs_xattr_set(dentry, handler->prefix, value, size, - flags); - - if (S_ISLNK(inode->i_mode)) - return -EOPNOTSUPP; - if (!inode_owner_or_capable(inode)) - return -EPERM; - if (value) { - /* update the cached acl value */ - acl = posix_acl_from_xattr(&init_user_ns, value, size); - if (IS_ERR(acl)) - return PTR_ERR(acl); - else if (acl) { - retval = posix_acl_valid(acl); - if (retval) - goto err_out; - } - } else - acl = NULL; - - switch (handler->flags) { - case ACL_TYPE_ACCESS: - if (acl) { - struct iattr iattr; - struct posix_acl *old_acl = acl; - - retval = posix_acl_update_mode(inode, &iattr.ia_mode, &acl); - if (retval) - goto err_out; - if (!acl) { - /* - * ACL can be represented - * by the mode bits. So don't - * update ACL. - */ - posix_acl_release(old_acl); - value = NULL; - size = 0; - } - iattr.ia_valid = ATTR_MODE; - /* FIXME should we update ctime ? - * What is the following setxattr update the - * mode ? - */ - v9fs_vfs_setattr_dotl(dentry, &iattr); - } - break; - case ACL_TYPE_DEFAULT: - if (!S_ISDIR(inode->i_mode)) { - retval = acl ? -EINVAL : 0; - goto err_out; - } - break; - default: - BUG(); - } - retval = v9fs_xattr_set(dentry, handler->prefix, value, size, flags); - if (!retval) - set_cached_acl(inode, handler->flags, acl); -err_out: - posix_acl_release(acl); - return retval; -} - -const struct xattr_handler v9fs_xattr_acl_access_handler = { - .prefix = POSIX_ACL_XATTR_ACCESS, - .flags = ACL_TYPE_ACCESS, - .get = v9fs_xattr_get_acl, - .set = v9fs_xattr_set_acl, -}; - -const struct xattr_handler v9fs_xattr_acl_default_handler = { - .prefix = POSIX_ACL_XATTR_DEFAULT, - .flags = ACL_TYPE_DEFAULT, - .get = v9fs_xattr_get_acl, - .set = v9fs_xattr_set_acl, -}; diff --git a/addons/9p/src/4.4.180/acl.h b/addons/9p/src/4.4.180/acl.h deleted file mode 100644 index e4f7e882..00000000 --- a/addons/9p/src/4.4.180/acl.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright IBM Corporation, 2010 - * Author Aneesh Kumar K.V - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ -#ifndef FS_9P_ACL_H -#define FS_9P_ACL_H - -#ifdef CONFIG_9P_FS_POSIX_ACL -extern int v9fs_get_acl(struct inode *, struct p9_fid *); -extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type); -extern int v9fs_acl_chmod(struct inode *, struct p9_fid *); -extern int v9fs_set_create_acl(struct inode *, struct p9_fid *, - struct posix_acl *, struct posix_acl *); -extern int v9fs_acl_mode(struct inode *dir, umode_t *modep, - struct posix_acl **dpacl, struct posix_acl **pacl); -extern void v9fs_put_acl(struct posix_acl *dacl, struct posix_acl *acl); -#else -#define v9fs_iop_get_acl NULL -static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) -{ - return 0; -} -static inline int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid) -{ - return 0; -} -static inline int v9fs_set_create_acl(struct inode *inode, - struct p9_fid *fid, - struct posix_acl *dacl, - struct posix_acl *acl) -{ - return 0; -} -static inline void v9fs_put_acl(struct posix_acl *dacl, - struct posix_acl *acl) -{ -} -static inline int v9fs_acl_mode(struct inode *dir, umode_t *modep, - struct posix_acl **dpacl, - struct posix_acl **pacl) -{ - return 0; -} - -#endif -#endif /* FS_9P_XATTR_H */ diff --git a/addons/9p/src/4.4.180/cache.c b/addons/9p/src/4.4.180/cache.c deleted file mode 100644 index 103ca5e1..00000000 --- a/addons/9p/src/4.4.180/cache.c +++ /dev/null @@ -1,414 +0,0 @@ -/* - * V9FS cache definitions. - * - * Copyright (C) 2009 by Abhishek Kulkarni - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "cache.h" - -#define CACHETAG_LEN 11 - -struct fscache_netfs v9fs_cache_netfs = { - .name = "9p", - .version = 0, -}; - -/** - * v9fs_random_cachetag - Generate a random tag to be associated - * with a new cache session. - * - * The value of jiffies is used for a fairly randomly cache tag. - */ - -static -int v9fs_random_cachetag(struct v9fs_session_info *v9ses) -{ - v9ses->cachetag = kmalloc(CACHETAG_LEN, GFP_KERNEL); - if (!v9ses->cachetag) - return -ENOMEM; - - return scnprintf(v9ses->cachetag, CACHETAG_LEN, "%lu", jiffies); -} - -static uint16_t v9fs_cache_session_get_key(const void *cookie_netfs_data, - void *buffer, uint16_t bufmax) -{ - struct v9fs_session_info *v9ses; - uint16_t klen = 0; - - v9ses = (struct v9fs_session_info *)cookie_netfs_data; - p9_debug(P9_DEBUG_FSC, "session %p buf %p size %u\n", - v9ses, buffer, bufmax); - - if (v9ses->cachetag) - klen = strlen(v9ses->cachetag); - - if (klen > bufmax) - return 0; - - memcpy(buffer, v9ses->cachetag, klen); - p9_debug(P9_DEBUG_FSC, "cache session tag %s\n", v9ses->cachetag); - return klen; -} - -const struct fscache_cookie_def v9fs_cache_session_index_def = { - .name = "9P.session", - .type = FSCACHE_COOKIE_TYPE_INDEX, - .get_key = v9fs_cache_session_get_key, -}; - -void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses) -{ - /* If no cache session tag was specified, we generate a random one. */ - if (!v9ses->cachetag) - v9fs_random_cachetag(v9ses); - - v9ses->fscache = fscache_acquire_cookie(v9fs_cache_netfs.primary_index, - &v9fs_cache_session_index_def, - v9ses, true); - p9_debug(P9_DEBUG_FSC, "session %p get cookie %p\n", - v9ses, v9ses->fscache); -} - -void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses) -{ - p9_debug(P9_DEBUG_FSC, "session %p put cookie %p\n", - v9ses, v9ses->fscache); - fscache_relinquish_cookie(v9ses->fscache, 0); - v9ses->fscache = NULL; -} - - -static uint16_t v9fs_cache_inode_get_key(const void *cookie_netfs_data, - void *buffer, uint16_t bufmax) -{ - const struct v9fs_inode *v9inode = cookie_netfs_data; - memcpy(buffer, &v9inode->qid.path, sizeof(v9inode->qid.path)); - p9_debug(P9_DEBUG_FSC, "inode %p get key %llu\n", - &v9inode->vfs_inode, v9inode->qid.path); - return sizeof(v9inode->qid.path); -} - -static void v9fs_cache_inode_get_attr(const void *cookie_netfs_data, - uint64_t *size) -{ - const struct v9fs_inode *v9inode = cookie_netfs_data; - *size = i_size_read(&v9inode->vfs_inode); - - p9_debug(P9_DEBUG_FSC, "inode %p get attr %llu\n", - &v9inode->vfs_inode, *size); -} - -static uint16_t v9fs_cache_inode_get_aux(const void *cookie_netfs_data, - void *buffer, uint16_t buflen) -{ - const struct v9fs_inode *v9inode = cookie_netfs_data; - memcpy(buffer, &v9inode->qid.version, sizeof(v9inode->qid.version)); - p9_debug(P9_DEBUG_FSC, "inode %p get aux %u\n", - &v9inode->vfs_inode, v9inode->qid.version); - return sizeof(v9inode->qid.version); -} - -static enum -fscache_checkaux v9fs_cache_inode_check_aux(void *cookie_netfs_data, - const void *buffer, - uint16_t buflen) -{ - const struct v9fs_inode *v9inode = cookie_netfs_data; - - if (buflen != sizeof(v9inode->qid.version)) - return FSCACHE_CHECKAUX_OBSOLETE; - - if (memcmp(buffer, &v9inode->qid.version, - sizeof(v9inode->qid.version))) - return FSCACHE_CHECKAUX_OBSOLETE; - - return FSCACHE_CHECKAUX_OKAY; -} - -static void v9fs_cache_inode_now_uncached(void *cookie_netfs_data) -{ - struct v9fs_inode *v9inode = cookie_netfs_data; - struct pagevec pvec; - pgoff_t first; - int loop, nr_pages; - - pagevec_init(&pvec, 0); - first = 0; - - for (;;) { - nr_pages = pagevec_lookup(&pvec, v9inode->vfs_inode.i_mapping, - first, - PAGEVEC_SIZE - pagevec_count(&pvec)); - if (!nr_pages) - break; - - for (loop = 0; loop < nr_pages; loop++) - ClearPageFsCache(pvec.pages[loop]); - - first = pvec.pages[nr_pages - 1]->index + 1; - - pvec.nr = nr_pages; - pagevec_release(&pvec); - cond_resched(); - } -} - -const struct fscache_cookie_def v9fs_cache_inode_index_def = { - .name = "9p.inode", - .type = FSCACHE_COOKIE_TYPE_DATAFILE, - .get_key = v9fs_cache_inode_get_key, - .get_attr = v9fs_cache_inode_get_attr, - .get_aux = v9fs_cache_inode_get_aux, - .check_aux = v9fs_cache_inode_check_aux, - .now_uncached = v9fs_cache_inode_now_uncached, -}; - -void v9fs_cache_inode_get_cookie(struct inode *inode) -{ - struct v9fs_inode *v9inode; - struct v9fs_session_info *v9ses; - - if (!S_ISREG(inode->i_mode)) - return; - - v9inode = V9FS_I(inode); - if (v9inode->fscache) - return; - - v9ses = v9fs_inode2v9ses(inode); - v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, - &v9fs_cache_inode_index_def, - v9inode, true); - - p9_debug(P9_DEBUG_FSC, "inode %p get cookie %p\n", - inode, v9inode->fscache); -} - -void v9fs_cache_inode_put_cookie(struct inode *inode) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - - if (!v9inode->fscache) - return; - p9_debug(P9_DEBUG_FSC, "inode %p put cookie %p\n", - inode, v9inode->fscache); - - fscache_relinquish_cookie(v9inode->fscache, 0); - v9inode->fscache = NULL; -} - -void v9fs_cache_inode_flush_cookie(struct inode *inode) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - - if (!v9inode->fscache) - return; - p9_debug(P9_DEBUG_FSC, "inode %p flush cookie %p\n", - inode, v9inode->fscache); - - fscache_relinquish_cookie(v9inode->fscache, 1); - v9inode->fscache = NULL; -} - -void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - - if (!v9inode->fscache) - return; - - mutex_lock(&v9inode->fscache_lock); - - if ((filp->f_flags & O_ACCMODE) != O_RDONLY) - v9fs_cache_inode_flush_cookie(inode); - else - v9fs_cache_inode_get_cookie(inode); - - mutex_unlock(&v9inode->fscache_lock); -} - -void v9fs_cache_inode_reset_cookie(struct inode *inode) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - struct v9fs_session_info *v9ses; - struct fscache_cookie *old; - - if (!v9inode->fscache) - return; - - old = v9inode->fscache; - - mutex_lock(&v9inode->fscache_lock); - fscache_relinquish_cookie(v9inode->fscache, 1); - - v9ses = v9fs_inode2v9ses(inode); - v9inode->fscache = fscache_acquire_cookie(v9ses->fscache, - &v9fs_cache_inode_index_def, - v9inode, true); - p9_debug(P9_DEBUG_FSC, "inode %p revalidating cookie old %p new %p\n", - inode, old, v9inode->fscache); - - mutex_unlock(&v9inode->fscache_lock); -} - -int __v9fs_fscache_release_page(struct page *page, gfp_t gfp) -{ - struct inode *inode = page->mapping->host; - struct v9fs_inode *v9inode = V9FS_I(inode); - - BUG_ON(!v9inode->fscache); - - return fscache_maybe_release_page(v9inode->fscache, page, gfp); -} - -void __v9fs_fscache_invalidate_page(struct page *page) -{ - struct inode *inode = page->mapping->host; - struct v9fs_inode *v9inode = V9FS_I(inode); - - BUG_ON(!v9inode->fscache); - - if (PageFsCache(page)) { - fscache_wait_on_page_write(v9inode->fscache, page); - BUG_ON(!PageLocked(page)); - fscache_uncache_page(v9inode->fscache, page); - } -} - -static void v9fs_vfs_readpage_complete(struct page *page, void *data, - int error) -{ - if (!error) - SetPageUptodate(page); - - unlock_page(page); -} - -/** - * __v9fs_readpage_from_fscache - read a page from cache - * - * Returns 0 if the pages are in cache and a BIO is submitted, - * 1 if the pages are not in cache and -error otherwise. - */ - -int __v9fs_readpage_from_fscache(struct inode *inode, struct page *page) -{ - int ret; - const struct v9fs_inode *v9inode = V9FS_I(inode); - - p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page); - if (!v9inode->fscache) - return -ENOBUFS; - - ret = fscache_read_or_alloc_page(v9inode->fscache, - page, - v9fs_vfs_readpage_complete, - NULL, - GFP_KERNEL); - switch (ret) { - case -ENOBUFS: - case -ENODATA: - p9_debug(P9_DEBUG_FSC, "page/inode not in cache %d\n", ret); - return 1; - case 0: - p9_debug(P9_DEBUG_FSC, "BIO submitted\n"); - return ret; - default: - p9_debug(P9_DEBUG_FSC, "ret %d\n", ret); - return ret; - } -} - -/** - * __v9fs_readpages_from_fscache - read multiple pages from cache - * - * Returns 0 if the pages are in cache and a BIO is submitted, - * 1 if the pages are not in cache and -error otherwise. - */ - -int __v9fs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - int ret; - const struct v9fs_inode *v9inode = V9FS_I(inode); - - p9_debug(P9_DEBUG_FSC, "inode %p pages %u\n", inode, *nr_pages); - if (!v9inode->fscache) - return -ENOBUFS; - - ret = fscache_read_or_alloc_pages(v9inode->fscache, - mapping, pages, nr_pages, - v9fs_vfs_readpage_complete, - NULL, - mapping_gfp_mask(mapping)); - switch (ret) { - case -ENOBUFS: - case -ENODATA: - p9_debug(P9_DEBUG_FSC, "pages/inodes not in cache %d\n", ret); - return 1; - case 0: - BUG_ON(!list_empty(pages)); - BUG_ON(*nr_pages != 0); - p9_debug(P9_DEBUG_FSC, "BIO submitted\n"); - return ret; - default: - p9_debug(P9_DEBUG_FSC, "ret %d\n", ret); - return ret; - } -} - -/** - * __v9fs_readpage_to_fscache - write a page to the cache - * - */ - -void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page) -{ - int ret; - const struct v9fs_inode *v9inode = V9FS_I(inode); - - p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page); - ret = fscache_write_page(v9inode->fscache, page, GFP_KERNEL); - p9_debug(P9_DEBUG_FSC, "ret = %d\n", ret); - if (ret != 0) - v9fs_uncache_page(inode, page); -} - -/* - * wait for a page to complete writing to the cache - */ -void __v9fs_fscache_wait_on_page_write(struct inode *inode, struct page *page) -{ - const struct v9fs_inode *v9inode = V9FS_I(inode); - p9_debug(P9_DEBUG_FSC, "inode %p page %p\n", inode, page); - if (PageFsCache(page)) - fscache_wait_on_page_write(v9inode->fscache, page); -} diff --git a/addons/9p/src/4.4.180/cache.h b/addons/9p/src/4.4.180/cache.h deleted file mode 100644 index 247e47e5..00000000 --- a/addons/9p/src/4.4.180/cache.h +++ /dev/null @@ -1,152 +0,0 @@ -/* - * V9FS cache definitions. - * - * Copyright (C) 2009 by Abhishek Kulkarni - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#ifndef _9P_CACHE_H -#define _9P_CACHE_H -#ifdef CONFIG_9P_FSCACHE -#include -#include - -extern struct fscache_netfs v9fs_cache_netfs; -extern const struct fscache_cookie_def v9fs_cache_session_index_def; -extern const struct fscache_cookie_def v9fs_cache_inode_index_def; - -extern void v9fs_cache_session_get_cookie(struct v9fs_session_info *v9ses); -extern void v9fs_cache_session_put_cookie(struct v9fs_session_info *v9ses); - -extern void v9fs_cache_inode_get_cookie(struct inode *inode); -extern void v9fs_cache_inode_put_cookie(struct inode *inode); -extern void v9fs_cache_inode_flush_cookie(struct inode *inode); -extern void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *filp); -extern void v9fs_cache_inode_reset_cookie(struct inode *inode); - -extern int __v9fs_cache_register(void); -extern void __v9fs_cache_unregister(void); - -extern int __v9fs_fscache_release_page(struct page *page, gfp_t gfp); -extern void __v9fs_fscache_invalidate_page(struct page *page); -extern int __v9fs_readpage_from_fscache(struct inode *inode, - struct page *page); -extern int __v9fs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages); -extern void __v9fs_readpage_to_fscache(struct inode *inode, struct page *page); -extern void __v9fs_fscache_wait_on_page_write(struct inode *inode, - struct page *page); - -static inline int v9fs_fscache_release_page(struct page *page, - gfp_t gfp) -{ - return __v9fs_fscache_release_page(page, gfp); -} - -static inline void v9fs_fscache_invalidate_page(struct page *page) -{ - __v9fs_fscache_invalidate_page(page); -} - -static inline int v9fs_readpage_from_fscache(struct inode *inode, - struct page *page) -{ - return __v9fs_readpage_from_fscache(inode, page); -} - -static inline int v9fs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - return __v9fs_readpages_from_fscache(inode, mapping, pages, - nr_pages); -} - -static inline void v9fs_readpage_to_fscache(struct inode *inode, - struct page *page) -{ - if (PageFsCache(page)) - __v9fs_readpage_to_fscache(inode, page); -} - -static inline void v9fs_uncache_page(struct inode *inode, struct page *page) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - fscache_uncache_page(v9inode->fscache, page); - BUG_ON(PageFsCache(page)); -} - -static inline void v9fs_fscache_wait_on_page_write(struct inode *inode, - struct page *page) -{ - return __v9fs_fscache_wait_on_page_write(inode, page); -} - -#else /* CONFIG_9P_FSCACHE */ - -static inline void v9fs_cache_inode_get_cookie(struct inode *inode) -{ -} - -static inline void v9fs_cache_inode_put_cookie(struct inode *inode) -{ -} - -static inline void v9fs_cache_inode_set_cookie(struct inode *inode, struct file *file) -{ -} - -static inline int v9fs_fscache_release_page(struct page *page, - gfp_t gfp) { - return 1; -} - -static inline void v9fs_fscache_invalidate_page(struct page *page) {} - -static inline int v9fs_readpage_from_fscache(struct inode *inode, - struct page *page) -{ - return -ENOBUFS; -} - -static inline int v9fs_readpages_from_fscache(struct inode *inode, - struct address_space *mapping, - struct list_head *pages, - unsigned *nr_pages) -{ - return -ENOBUFS; -} - -static inline void v9fs_readpage_to_fscache(struct inode *inode, - struct page *page) -{} - -static inline void v9fs_uncache_page(struct inode *inode, struct page *page) -{} - -static inline void v9fs_fscache_wait_on_page_write(struct inode *inode, - struct page *page) -{ - return; -} - -#endif /* CONFIG_9P_FSCACHE */ -#endif /* _9P_CACHE_H */ diff --git a/addons/9p/src/4.4.180/client.c b/addons/9p/src/4.4.180/client.c deleted file mode 100644 index 443db202..00000000 --- a/addons/9p/src/4.4.180/client.c +++ /dev/null @@ -1,2297 +0,0 @@ -/* - * net/9p/clnt.c - * - * 9P Client - * - * Copyright (C) 2008 by Eric Van Hensbergen - * Copyright (C) 2007 by Latchesar Ionkov - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "protocol.h" - -#define CREATE_TRACE_POINTS -#include - -/* - * Client Option Parsing (code inspired by NFS code) - * - a little lazy - parse all client options - */ - -enum { - Opt_msize, - Opt_trans, - Opt_legacy, - Opt_version, - Opt_err, -}; - -static const match_table_t tokens = { - {Opt_msize, "msize=%u"}, - {Opt_legacy, "noextend"}, - {Opt_trans, "trans=%s"}, - {Opt_version, "version=%s"}, - {Opt_err, NULL}, -}; - -inline int p9_is_proto_dotl(struct p9_client *clnt) -{ - return clnt->proto_version == p9_proto_2000L; -} -EXPORT_SYMBOL(p9_is_proto_dotl); - -inline int p9_is_proto_dotu(struct p9_client *clnt) -{ - return clnt->proto_version == p9_proto_2000u; -} -EXPORT_SYMBOL(p9_is_proto_dotu); - -/* - * Some error codes are taken directly from the server replies, - * make sure they are valid. - */ -static int safe_errno(int err) -{ - if ((err > 0) || (err < -MAX_ERRNO)) { - p9_debug(P9_DEBUG_ERROR, "Invalid error code %d\n", err); - return -EPROTO; - } - return err; -} - - -/* Interpret mount option for protocol version */ -static int get_protocol_version(char *s) -{ - int version = -EINVAL; - - if (!strcmp(s, "9p2000")) { - version = p9_proto_legacy; - p9_debug(P9_DEBUG_9P, "Protocol version: Legacy\n"); - } else if (!strcmp(s, "9p2000.u")) { - version = p9_proto_2000u; - p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.u\n"); - } else if (!strcmp(s, "9p2000.L")) { - version = p9_proto_2000L; - p9_debug(P9_DEBUG_9P, "Protocol version: 9P2000.L\n"); - } else - pr_info("Unknown protocol version %s\n", s); - - return version; -} - -/** - * parse_options - parse mount options into client structure - * @opts: options string passed from mount - * @clnt: existing v9fs client information - * - * Return 0 upon success, -ERRNO upon failure - */ - -static int parse_opts(char *opts, struct p9_client *clnt) -{ - char *options, *tmp_options; - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - char *s; - int ret = 0; - - clnt->proto_version = p9_proto_2000L; - clnt->msize = 8192; - - if (!opts) - return 0; - - tmp_options = kstrdup(opts, GFP_KERNEL); - if (!tmp_options) { - p9_debug(P9_DEBUG_ERROR, - "failed to allocate copy of option string\n"); - return -ENOMEM; - } - options = tmp_options; - - while ((p = strsep(&options, ",")) != NULL) { - int token, r; - if (!*p) - continue; - token = match_token(p, tokens, args); - switch (token) { - case Opt_msize: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - if (option < 4096) { - p9_debug(P9_DEBUG_ERROR, - "msize should be at least 4k\n"); - ret = -EINVAL; - continue; - } - clnt->msize = option; - break; - case Opt_trans: - s = match_strdup(&args[0]); - if (!s) { - ret = -ENOMEM; - p9_debug(P9_DEBUG_ERROR, - "problem allocating copy of trans arg\n"); - goto free_and_return; - } - clnt->trans_mod = v9fs_get_trans_by_name(s); - if (clnt->trans_mod == NULL) { - pr_info("Could not find request transport: %s\n", - s); - ret = -EINVAL; - kfree(s); - goto free_and_return; - } - kfree(s); - break; - case Opt_legacy: - clnt->proto_version = p9_proto_legacy; - break; - case Opt_version: - s = match_strdup(&args[0]); - if (!s) { - ret = -ENOMEM; - p9_debug(P9_DEBUG_ERROR, - "problem allocating copy of version arg\n"); - goto free_and_return; - } - ret = get_protocol_version(s); - if (ret == -EINVAL) { - kfree(s); - goto free_and_return; - } - kfree(s); - clnt->proto_version = ret; - break; - default: - continue; - } - } - -free_and_return: - kfree(tmp_options); - return ret; -} - -static struct p9_fcall *p9_fcall_alloc(int alloc_msize) -{ - struct p9_fcall *fc; - fc = kmalloc(sizeof(struct p9_fcall) + alloc_msize, GFP_NOFS); - if (!fc) - return NULL; - fc->capacity = alloc_msize; - fc->sdata = (char *) fc + sizeof(struct p9_fcall); - return fc; -} - -/** - * p9_tag_alloc - lookup/allocate a request by tag - * @c: client session to lookup tag within - * @tag: numeric id for transaction - * - * this is a simple array lookup, but will grow the - * request_slots as necessary to accommodate transaction - * ids which did not previously have a slot. - * - * this code relies on the client spinlock to manage locks, its - * possible we should switch to something else, but I'd rather - * stick with something low-overhead for the common case. - * - */ - -static struct p9_req_t * -p9_tag_alloc(struct p9_client *c, u16 tag, unsigned int max_size) -{ - unsigned long flags; - int row, col; - struct p9_req_t *req; - int alloc_msize = min(c->msize, max_size); - - /* This looks up the original request by tag so we know which - * buffer to read the data into */ - tag++; - - if (tag >= c->max_tag) { - spin_lock_irqsave(&c->lock, flags); - /* check again since original check was outside of lock */ - while (tag >= c->max_tag) { - row = (tag / P9_ROW_MAXTAG); - c->reqs[row] = kcalloc(P9_ROW_MAXTAG, - sizeof(struct p9_req_t), GFP_ATOMIC); - - if (!c->reqs[row]) { - pr_err("Couldn't grow tag array\n"); - spin_unlock_irqrestore(&c->lock, flags); - return ERR_PTR(-ENOMEM); - } - for (col = 0; col < P9_ROW_MAXTAG; col++) { - c->reqs[row][col].status = REQ_STATUS_IDLE; - c->reqs[row][col].tc = NULL; - } - c->max_tag += P9_ROW_MAXTAG; - } - spin_unlock_irqrestore(&c->lock, flags); - } - row = tag / P9_ROW_MAXTAG; - col = tag % P9_ROW_MAXTAG; - - req = &c->reqs[row][col]; - if (!req->wq) { - req->wq = kmalloc(sizeof(wait_queue_head_t), GFP_NOFS); - if (!req->wq) - goto grow_failed; - init_waitqueue_head(req->wq); - } - - if (!req->tc) - req->tc = p9_fcall_alloc(alloc_msize); - if (!req->rc) - req->rc = p9_fcall_alloc(alloc_msize); - if (!req->tc || !req->rc) - goto grow_failed; - - p9pdu_reset(req->tc); - p9pdu_reset(req->rc); - - req->tc->tag = tag-1; - req->status = REQ_STATUS_ALLOC; - - return req; - -grow_failed: - pr_err("Couldn't grow tag array\n"); - kfree(req->tc); - kfree(req->rc); - kfree(req->wq); - req->tc = req->rc = NULL; - req->wq = NULL; - return ERR_PTR(-ENOMEM); -} - -/** - * p9_tag_lookup - lookup a request by tag - * @c: client session to lookup tag within - * @tag: numeric id for transaction - * - */ - -struct p9_req_t *p9_tag_lookup(struct p9_client *c, u16 tag) -{ - int row, col; - - /* This looks up the original request by tag so we know which - * buffer to read the data into */ - tag++; - - if(tag >= c->max_tag) - return NULL; - - row = tag / P9_ROW_MAXTAG; - col = tag % P9_ROW_MAXTAG; - - return &c->reqs[row][col]; -} -EXPORT_SYMBOL(p9_tag_lookup); - -/** - * p9_tag_init - setup tags structure and contents - * @c: v9fs client struct - * - * This initializes the tags structure for each client instance. - * - */ - -static int p9_tag_init(struct p9_client *c) -{ - int err = 0; - - c->tagpool = p9_idpool_create(); - if (IS_ERR(c->tagpool)) { - err = PTR_ERR(c->tagpool); - goto error; - } - err = p9_idpool_get(c->tagpool); /* reserve tag 0 */ - if (err < 0) { - p9_idpool_destroy(c->tagpool); - goto error; - } - c->max_tag = 0; -error: - return err; -} - -/** - * p9_tag_cleanup - cleans up tags structure and reclaims resources - * @c: v9fs client struct - * - * This frees resources associated with the tags structure - * - */ -static void p9_tag_cleanup(struct p9_client *c) -{ - int row, col; - - /* check to insure all requests are idle */ - for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { - for (col = 0; col < P9_ROW_MAXTAG; col++) { - if (c->reqs[row][col].status != REQ_STATUS_IDLE) { - p9_debug(P9_DEBUG_MUX, - "Attempting to cleanup non-free tag %d,%d\n", - row, col); - /* TODO: delay execution of cleanup */ - return; - } - } - } - - if (c->tagpool) { - p9_idpool_put(0, c->tagpool); /* free reserved tag 0 */ - p9_idpool_destroy(c->tagpool); - } - - /* free requests associated with tags */ - for (row = 0; row < (c->max_tag/P9_ROW_MAXTAG); row++) { - for (col = 0; col < P9_ROW_MAXTAG; col++) { - kfree(c->reqs[row][col].wq); - kfree(c->reqs[row][col].tc); - kfree(c->reqs[row][col].rc); - } - kfree(c->reqs[row]); - } - c->max_tag = 0; -} - -/** - * p9_free_req - free a request and clean-up as necessary - * c: client state - * r: request to release - * - */ - -static void p9_free_req(struct p9_client *c, struct p9_req_t *r) -{ - int tag = r->tc->tag; - p9_debug(P9_DEBUG_MUX, "clnt %p req %p tag: %d\n", c, r, tag); - - r->status = REQ_STATUS_IDLE; - if (tag != P9_NOTAG && p9_idpool_check(tag, c->tagpool)) - p9_idpool_put(tag, c->tagpool); -} - -/** - * p9_client_cb - call back from transport to client - * c: client state - * req: request received - * - */ -void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status) -{ - p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); - - /* - * This barrier is needed to make sure any change made to req before - * the other thread wakes up will indeed be seen by the waiting side. - */ - smp_wmb(); - req->status = status; - - wake_up(req->wq); - p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); -} -EXPORT_SYMBOL(p9_client_cb); - -/** - * p9_parse_header - parse header arguments out of a packet - * @pdu: packet to parse - * @size: size of packet - * @type: type of request - * @tag: tag of packet - * @rewind: set if we need to rewind offset afterwards - */ - -int -p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag, - int rewind) -{ - int8_t r_type; - int16_t r_tag; - int32_t r_size; - int offset = pdu->offset; - int err; - - pdu->offset = 0; - if (pdu->size == 0) - pdu->size = 7; - - err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag); - if (err) - goto rewind_and_exit; - - pdu->size = r_size; - pdu->id = r_type; - pdu->tag = r_tag; - - p9_debug(P9_DEBUG_9P, "<<< size=%d type: %d tag: %d\n", - pdu->size, pdu->id, pdu->tag); - - if (type) - *type = r_type; - if (tag) - *tag = r_tag; - if (size) - *size = r_size; - - -rewind_and_exit: - if (rewind) - pdu->offset = offset; - return err; -} -EXPORT_SYMBOL(p9_parse_header); - -/** - * p9_check_errors - check 9p packet for error return and process it - * @c: current client instance - * @req: request to parse and check for error conditions - * - * returns error code if one is discovered, otherwise returns 0 - * - * this will have to be more complicated if we have multiple - * error packet types - */ - -static int p9_check_errors(struct p9_client *c, struct p9_req_t *req) -{ - int8_t type; - int err; - int ecode; - - err = p9_parse_header(req->rc, NULL, &type, NULL, 0); - /* - * dump the response from server - * This should be after check errors which poplulate pdu_fcall. - */ - trace_9p_protocol_dump(c, req->rc); - if (err) { - p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err); - return err; - } - if (type != P9_RERROR && type != P9_RLERROR) - return 0; - - if (!p9_is_proto_dotl(c)) { - char *ename; - err = p9pdu_readf(req->rc, c->proto_version, "s?d", - &ename, &ecode); - if (err) - goto out_err; - - if (p9_is_proto_dotu(c)) - err = -ecode; - - if (!err || !IS_ERR_VALUE(err)) { - err = p9_errstr2errno(ename, strlen(ename)); - - p9_debug(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", - -ecode, ename); - } - kfree(ename); - } else { - err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); - err = -ecode; - - p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); - } - - return err; - -out_err: - p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err); - - return err; -} - -/** - * p9_check_zc_errors - check 9p packet for error return and process it - * @c: current client instance - * @req: request to parse and check for error conditions - * @in_hdrlen: Size of response protocol buffer. - * - * returns error code if one is discovered, otherwise returns 0 - * - * this will have to be more complicated if we have multiple - * error packet types - */ - -static int p9_check_zc_errors(struct p9_client *c, struct p9_req_t *req, - struct iov_iter *uidata, int in_hdrlen) -{ - int err; - int ecode; - int8_t type; - char *ename = NULL; - - err = p9_parse_header(req->rc, NULL, &type, NULL, 0); - /* - * dump the response from server - * This should be after parse_header which poplulate pdu_fcall. - */ - trace_9p_protocol_dump(c, req->rc); - if (err) { - p9_debug(P9_DEBUG_ERROR, "couldn't parse header %d\n", err); - return err; - } - - if (type != P9_RERROR && type != P9_RLERROR) - return 0; - - if (!p9_is_proto_dotl(c)) { - /* Error is reported in string format */ - int len; - /* 7 = header size for RERROR; */ - int inline_len = in_hdrlen - 7; - - len = req->rc->size - req->rc->offset; - if (len > (P9_ZC_HDR_SZ - 7)) { - err = -EFAULT; - goto out_err; - } - - ename = &req->rc->sdata[req->rc->offset]; - if (len > inline_len) { - /* We have error in external buffer */ - err = copy_from_iter(ename + inline_len, - len - inline_len, uidata); - if (err != len - inline_len) { - err = -EFAULT; - goto out_err; - } - } - ename = NULL; - err = p9pdu_readf(req->rc, c->proto_version, "s?d", - &ename, &ecode); - if (err) - goto out_err; - - if (p9_is_proto_dotu(c)) - err = -ecode; - - if (!err || !IS_ERR_VALUE(err)) { - err = p9_errstr2errno(ename, strlen(ename)); - - p9_debug(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", - -ecode, ename); - } - kfree(ename); - } else { - err = p9pdu_readf(req->rc, c->proto_version, "d", &ecode); - err = -ecode; - - p9_debug(P9_DEBUG_9P, "<<< RLERROR (%d)\n", -ecode); - } - return err; - -out_err: - p9_debug(P9_DEBUG_ERROR, "couldn't parse error%d\n", err); - return err; -} - -static struct p9_req_t * -p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...); - -/** - * p9_client_flush - flush (cancel) a request - * @c: client state - * @oldreq: request to cancel - * - * This sents a flush for a particular request and links - * the flush request to the original request. The current - * code only supports a single flush request although the protocol - * allows for multiple flush requests to be sent for a single request. - * - */ - -static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) -{ - struct p9_req_t *req; - int16_t oldtag; - int err; - - err = p9_parse_header(oldreq->tc, NULL, NULL, &oldtag, 1); - if (err) - return err; - - p9_debug(P9_DEBUG_9P, ">>> TFLUSH tag %d\n", oldtag); - - req = p9_client_rpc(c, P9_TFLUSH, "w", oldtag); - if (IS_ERR(req)) - return PTR_ERR(req); - - /* - * if we haven't received a response for oldreq, - * remove it from the list - */ - if (oldreq->status == REQ_STATUS_SENT) - if (c->trans_mod->cancelled) - c->trans_mod->cancelled(c, oldreq); - - p9_free_req(c, req); - return 0; -} - -static struct p9_req_t *p9_client_prepare_req(struct p9_client *c, - int8_t type, int req_size, - const char *fmt, va_list ap) -{ - int tag, err; - struct p9_req_t *req; - - p9_debug(P9_DEBUG_MUX, "client %p op %d\n", c, type); - - /* we allow for any status other than disconnected */ - if (c->status == Disconnected) - return ERR_PTR(-EIO); - - /* if status is begin_disconnected we allow only clunk request */ - if ((c->status == BeginDisconnect) && (type != P9_TCLUNK)) - return ERR_PTR(-EIO); - - tag = P9_NOTAG; - if (type != P9_TVERSION) { - tag = p9_idpool_get(c->tagpool); - if (tag < 0) - return ERR_PTR(-ENOMEM); - } - - req = p9_tag_alloc(c, tag, req_size); - if (IS_ERR(req)) - return req; - - /* marshall the data */ - p9pdu_prepare(req->tc, tag, type); - err = p9pdu_vwritef(req->tc, c->proto_version, fmt, ap); - if (err) - goto reterr; - p9pdu_finalize(c, req->tc); - trace_9p_client_req(c, type, tag); - return req; -reterr: - p9_free_req(c, req); - return ERR_PTR(err); -} - -/** - * p9_client_rpc - issue a request and wait for a response - * @c: client session - * @type: type of request - * @fmt: protocol format string (see protocol.c) - * - * Returns request structure (which client must free using p9_free_req) - */ - -static struct p9_req_t * -p9_client_rpc(struct p9_client *c, int8_t type, const char *fmt, ...) -{ - va_list ap; - int sigpending, err; - unsigned long flags; - struct p9_req_t *req; - - va_start(ap, fmt); - req = p9_client_prepare_req(c, type, c->msize, fmt, ap); - va_end(ap); - if (IS_ERR(req)) - return req; - - if (signal_pending(current)) { - sigpending = 1; - clear_thread_flag(TIF_SIGPENDING); - } else - sigpending = 0; - - err = c->trans_mod->request(c, req); - if (err < 0) { - if (err != -ERESTARTSYS && err != -EFAULT) - c->status = Disconnected; - goto reterr; - } -again: - /* Wait for the response */ - err = wait_event_killable(*req->wq, req->status >= REQ_STATUS_RCVD); - - /* - * Make sure our req is coherent with regard to updates in other - * threads - echoes to wmb() in the callback - */ - smp_rmb(); - - if ((err == -ERESTARTSYS) && (c->status == Connected) - && (type == P9_TFLUSH)) { - sigpending = 1; - clear_thread_flag(TIF_SIGPENDING); - goto again; - } - - if (req->status == REQ_STATUS_ERROR) { - p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); - err = req->t_err; - } - if ((err == -ERESTARTSYS) && (c->status == Connected)) { - p9_debug(P9_DEBUG_MUX, "flushing\n"); - sigpending = 1; - clear_thread_flag(TIF_SIGPENDING); - - if (c->trans_mod->cancel(c, req)) - p9_client_flush(c, req); - - /* if we received the response anyway, don't signal error */ - if (req->status == REQ_STATUS_RCVD) - err = 0; - } - if (sigpending) { - spin_lock_irqsave(¤t->sighand->siglock, flags); - recalc_sigpending(); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - } - if (err < 0) - goto reterr; - - err = p9_check_errors(c, req); - trace_9p_client_res(c, type, req->rc->tag, err); - if (!err) - return req; -reterr: - p9_free_req(c, req); - return ERR_PTR(safe_errno(err)); -} - -/** - * p9_client_zc_rpc - issue a request and wait for a response - * @c: client session - * @type: type of request - * @uidata: destination for zero copy read - * @uodata: source for zero copy write - * @inlen: read buffer size - * @olen: write buffer size - * @hdrlen: reader header size, This is the size of response protocol data - * @fmt: protocol format string (see protocol.c) - * - * Returns request structure (which client must free using p9_free_req) - */ -static struct p9_req_t *p9_client_zc_rpc(struct p9_client *c, int8_t type, - struct iov_iter *uidata, - struct iov_iter *uodata, - int inlen, int olen, int in_hdrlen, - const char *fmt, ...) -{ - va_list ap; - int sigpending, err; - unsigned long flags; - struct p9_req_t *req; - - va_start(ap, fmt); - /* - * We allocate a inline protocol data of only 4k bytes. - * The actual content is passed in zero-copy fashion. - */ - req = p9_client_prepare_req(c, type, P9_ZC_HDR_SZ, fmt, ap); - va_end(ap); - if (IS_ERR(req)) - return req; - - if (signal_pending(current)) { - sigpending = 1; - clear_thread_flag(TIF_SIGPENDING); - } else - sigpending = 0; - - err = c->trans_mod->zc_request(c, req, uidata, uodata, - inlen, olen, in_hdrlen); - if (err < 0) { - if (err == -EIO) - c->status = Disconnected; - if (err != -ERESTARTSYS) - goto reterr; - } - if (req->status == REQ_STATUS_ERROR) { - p9_debug(P9_DEBUG_ERROR, "req_status error %d\n", req->t_err); - err = req->t_err; - } - if ((err == -ERESTARTSYS) && (c->status == Connected)) { - p9_debug(P9_DEBUG_MUX, "flushing\n"); - sigpending = 1; - clear_thread_flag(TIF_SIGPENDING); - - if (c->trans_mod->cancel(c, req)) - p9_client_flush(c, req); - - /* if we received the response anyway, don't signal error */ - if (req->status == REQ_STATUS_RCVD) - err = 0; - } - if (sigpending) { - spin_lock_irqsave(¤t->sighand->siglock, flags); - recalc_sigpending(); - spin_unlock_irqrestore(¤t->sighand->siglock, flags); - } - if (err < 0) - goto reterr; - - err = p9_check_zc_errors(c, req, uidata, in_hdrlen); - trace_9p_client_res(c, type, req->rc->tag, err); - if (!err) - return req; -reterr: - p9_free_req(c, req); - return ERR_PTR(safe_errno(err)); -} - -static struct p9_fid *p9_fid_create(struct p9_client *clnt) -{ - int ret; - struct p9_fid *fid; - unsigned long flags; - - p9_debug(P9_DEBUG_FID, "clnt %p\n", clnt); - fid = kmalloc(sizeof(struct p9_fid), GFP_KERNEL); - if (!fid) - return ERR_PTR(-ENOMEM); - - ret = p9_idpool_get(clnt->fidpool); - if (ret < 0) { - ret = -ENOSPC; - goto error; - } - fid->fid = ret; - - memset(&fid->qid, 0, sizeof(struct p9_qid)); - fid->mode = -1; - fid->uid = current_fsuid(); - fid->clnt = clnt; - fid->rdir = NULL; - spin_lock_irqsave(&clnt->lock, flags); - list_add(&fid->flist, &clnt->fidlist); - spin_unlock_irqrestore(&clnt->lock, flags); - - return fid; - -error: - kfree(fid); - return ERR_PTR(ret); -} - -static void p9_fid_destroy(struct p9_fid *fid) -{ - struct p9_client *clnt; - unsigned long flags; - - p9_debug(P9_DEBUG_FID, "fid %d\n", fid->fid); - clnt = fid->clnt; - p9_idpool_put(fid->fid, clnt->fidpool); - spin_lock_irqsave(&clnt->lock, flags); - list_del(&fid->flist); - spin_unlock_irqrestore(&clnt->lock, flags); - kfree(fid->rdir); - kfree(fid); -} - -static int p9_client_version(struct p9_client *c) -{ - int err = 0; - struct p9_req_t *req; - char *version = NULL; - int msize; - - p9_debug(P9_DEBUG_9P, ">>> TVERSION msize %d protocol %d\n", - c->msize, c->proto_version); - - switch (c->proto_version) { - case p9_proto_2000L: - req = p9_client_rpc(c, P9_TVERSION, "ds", - c->msize, "9P2000.L"); - break; - case p9_proto_2000u: - req = p9_client_rpc(c, P9_TVERSION, "ds", - c->msize, "9P2000.u"); - break; - case p9_proto_legacy: - req = p9_client_rpc(c, P9_TVERSION, "ds", - c->msize, "9P2000"); - break; - default: - return -EINVAL; - } - - if (IS_ERR(req)) - return PTR_ERR(req); - - err = p9pdu_readf(req->rc, c->proto_version, "ds", &msize, &version); - if (err) { - p9_debug(P9_DEBUG_9P, "version error %d\n", err); - trace_9p_protocol_dump(c, req->rc); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version); - if (!strncmp(version, "9P2000.L", 8)) - c->proto_version = p9_proto_2000L; - else if (!strncmp(version, "9P2000.u", 8)) - c->proto_version = p9_proto_2000u; - else if (!strncmp(version, "9P2000", 6)) - c->proto_version = p9_proto_legacy; - else { - p9_debug(P9_DEBUG_ERROR, - "server returned an unknown version: %s\n", version); - err = -EREMOTEIO; - goto error; - } - - if (msize < 4096) { - p9_debug(P9_DEBUG_ERROR, - "server returned a msize < 4096: %d\n", msize); - err = -EREMOTEIO; - goto error; - } - if (msize < c->msize) - c->msize = msize; - -error: - kfree(version); - p9_free_req(c, req); - - return err; -} - -struct p9_client *p9_client_create(const char *dev_name, char *options) -{ - int err; - struct p9_client *clnt; - char *client_id; - - err = 0; - clnt = kmalloc(sizeof(struct p9_client), GFP_KERNEL); - if (!clnt) - return ERR_PTR(-ENOMEM); - - clnt->trans_mod = NULL; - clnt->trans = NULL; - - client_id = utsname()->nodename; - memcpy(clnt->name, client_id, strlen(client_id) + 1); - - spin_lock_init(&clnt->lock); - INIT_LIST_HEAD(&clnt->fidlist); - - err = p9_tag_init(clnt); - if (err < 0) - goto free_client; - - err = parse_opts(options, clnt); - if (err < 0) - goto destroy_tagpool; - - if (!clnt->trans_mod) - clnt->trans_mod = v9fs_get_default_trans(); - - if (clnt->trans_mod == NULL) { - err = -EPROTONOSUPPORT; - p9_debug(P9_DEBUG_ERROR, - "No transport defined or default transport\n"); - goto destroy_tagpool; - } - - clnt->fidpool = p9_idpool_create(); - if (IS_ERR(clnt->fidpool)) { - err = PTR_ERR(clnt->fidpool); - goto put_trans; - } - - p9_debug(P9_DEBUG_MUX, "clnt %p trans %p msize %d protocol %d\n", - clnt, clnt->trans_mod, clnt->msize, clnt->proto_version); - - err = clnt->trans_mod->create(clnt, dev_name, options); - if (err) - goto destroy_fidpool; - - if (clnt->msize > clnt->trans_mod->maxsize) - clnt->msize = clnt->trans_mod->maxsize; - - if (clnt->msize < 4096) { - p9_debug(P9_DEBUG_ERROR, - "Please specify a msize of at least 4k\n"); - err = -EINVAL; - goto close_trans; - } - - err = p9_client_version(clnt); - if (err) - goto close_trans; - - return clnt; - -close_trans: - clnt->trans_mod->close(clnt); -destroy_fidpool: - p9_idpool_destroy(clnt->fidpool); -put_trans: - v9fs_put_trans(clnt->trans_mod); -destroy_tagpool: - p9_idpool_destroy(clnt->tagpool); -free_client: - kfree(clnt); - return ERR_PTR(err); -} -EXPORT_SYMBOL(p9_client_create); - -void p9_client_destroy(struct p9_client *clnt) -{ - struct p9_fid *fid, *fidptr; - - p9_debug(P9_DEBUG_MUX, "clnt %p\n", clnt); - - if (clnt->trans_mod) - clnt->trans_mod->close(clnt); - - v9fs_put_trans(clnt->trans_mod); - - list_for_each_entry_safe(fid, fidptr, &clnt->fidlist, flist) { - pr_info("Found fid %d not clunked\n", fid->fid); - p9_fid_destroy(fid); - } - - if (clnt->fidpool) - p9_idpool_destroy(clnt->fidpool); - - p9_tag_cleanup(clnt); - - kfree(clnt); -} -EXPORT_SYMBOL(p9_client_destroy); - -void p9_client_disconnect(struct p9_client *clnt) -{ - p9_debug(P9_DEBUG_9P, "clnt %p\n", clnt); - clnt->status = Disconnected; -} -EXPORT_SYMBOL(p9_client_disconnect); - -void p9_client_begin_disconnect(struct p9_client *clnt) -{ - p9_debug(P9_DEBUG_9P, "clnt %p\n", clnt); - clnt->status = BeginDisconnect; -} -EXPORT_SYMBOL(p9_client_begin_disconnect); - -struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid, - char *uname, kuid_t n_uname, char *aname) -{ - int err = 0; - struct p9_req_t *req; - struct p9_fid *fid; - struct p9_qid qid; - - - p9_debug(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n", - afid ? afid->fid : -1, uname, aname); - fid = p9_fid_create(clnt); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - fid = NULL; - goto error; - } - fid->uid = n_uname; - - req = p9_client_rpc(clnt, P9_TATTACH, "ddss?u", fid->fid, - afid ? afid->fid : P9_NOFID, uname, aname, n_uname); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "Q", &qid); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n", - qid.type, (unsigned long long)qid.path, qid.version); - - memmove(&fid->qid, &qid, sizeof(struct p9_qid)); - - p9_free_req(clnt, req); - return fid; - -error: - if (fid) - p9_fid_destroy(fid); - return ERR_PTR(err); -} -EXPORT_SYMBOL(p9_client_attach); - -struct p9_fid *p9_client_walk(struct p9_fid *oldfid, uint16_t nwname, - char **wnames, int clone) -{ - int err; - struct p9_client *clnt; - struct p9_fid *fid; - struct p9_qid *wqids; - struct p9_req_t *req; - uint16_t nwqids, count; - - err = 0; - wqids = NULL; - clnt = oldfid->clnt; - if (clone) { - fid = p9_fid_create(clnt); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - fid = NULL; - goto error; - } - - fid->uid = oldfid->uid; - } else - fid = oldfid; - - - p9_debug(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %ud wname[0] %s\n", - oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL); - - req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid, - nwname, wnames); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "R", &nwqids, &wqids); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - goto clunk_fid; - } - p9_free_req(clnt, req); - - p9_debug(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids); - - if (nwqids != nwname) { - err = -ENOENT; - goto clunk_fid; - } - - for (count = 0; count < nwqids; count++) - p9_debug(P9_DEBUG_9P, "<<< [%d] %x.%llx.%x\n", - count, wqids[count].type, - (unsigned long long)wqids[count].path, - wqids[count].version); - - if (nwname) - memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid)); - else - fid->qid = oldfid->qid; - - kfree(wqids); - return fid; - -clunk_fid: - kfree(wqids); - p9_client_clunk(fid); - fid = NULL; - -error: - if (fid && (fid != oldfid)) - p9_fid_destroy(fid); - - return ERR_PTR(err); -} -EXPORT_SYMBOL(p9_client_walk); - -int p9_client_open(struct p9_fid *fid, int mode) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - struct p9_qid qid; - int iounit; - - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> %s fid %d mode %d\n", - p9_is_proto_dotl(clnt) ? "TLOPEN" : "TOPEN", fid->fid, mode); - err = 0; - - if (fid->mode != -1) - return -EINVAL; - - if (p9_is_proto_dotl(clnt)) - req = p9_client_rpc(clnt, P9_TLOPEN, "dd", fid->fid, mode); - else - req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto free_and_error; - } - - p9_debug(P9_DEBUG_9P, "<<< %s qid %x.%llx.%x iounit %x\n", - p9_is_proto_dotl(clnt) ? "RLOPEN" : "ROPEN", qid.type, - (unsigned long long)qid.path, qid.version, iounit); - - fid->mode = mode; - fid->iounit = iounit; - -free_and_error: - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_open); - -int p9_client_create_dotl(struct p9_fid *ofid, char *name, u32 flags, u32 mode, - kgid_t gid, struct p9_qid *qid) -{ - int err = 0; - struct p9_client *clnt; - struct p9_req_t *req; - int iounit; - - p9_debug(P9_DEBUG_9P, - ">>> TLCREATE fid %d name %s flags %d mode %d gid %d\n", - ofid->fid, name, flags, mode, - from_kgid(&init_user_ns, gid)); - clnt = ofid->clnt; - - if (ofid->mode != -1) - return -EINVAL; - - req = p9_client_rpc(clnt, P9_TLCREATE, "dsddg", ofid->fid, name, flags, - mode, gid); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", qid, &iounit); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto free_and_error; - } - - p9_debug(P9_DEBUG_9P, "<<< RLCREATE qid %x.%llx.%x iounit %x\n", - qid->type, - (unsigned long long)qid->path, - qid->version, iounit); - - ofid->mode = mode; - ofid->iounit = iounit; - -free_and_error: - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_create_dotl); - -int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode, - char *extension) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - struct p9_qid qid; - int iounit; - - p9_debug(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n", - fid->fid, name, perm, mode); - err = 0; - clnt = fid->clnt; - - if (fid->mode != -1) - return -EINVAL; - - req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm, - mode, extension); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "Qd", &qid, &iounit); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto free_and_error; - } - - p9_debug(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n", - qid.type, - (unsigned long long)qid.path, - qid.version, iounit); - - fid->mode = mode; - fid->iounit = iounit; - -free_and_error: - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_fcreate); - -int p9_client_symlink(struct p9_fid *dfid, char *name, char *symtgt, kgid_t gid, - struct p9_qid *qid) -{ - int err = 0; - struct p9_client *clnt; - struct p9_req_t *req; - - p9_debug(P9_DEBUG_9P, ">>> TSYMLINK dfid %d name %s symtgt %s\n", - dfid->fid, name, symtgt); - clnt = dfid->clnt; - - req = p9_client_rpc(clnt, P9_TSYMLINK, "dssg", dfid->fid, name, symtgt, - gid); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto free_and_error; - } - - p9_debug(P9_DEBUG_9P, "<<< RSYMLINK qid %x.%llx.%x\n", - qid->type, (unsigned long long)qid->path, qid->version); - -free_and_error: - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_symlink); - -int p9_client_link(struct p9_fid *dfid, struct p9_fid *oldfid, char *newname) -{ - struct p9_client *clnt; - struct p9_req_t *req; - - p9_debug(P9_DEBUG_9P, ">>> TLINK dfid %d oldfid %d newname %s\n", - dfid->fid, oldfid->fid, newname); - clnt = dfid->clnt; - req = p9_client_rpc(clnt, P9_TLINK, "dds", dfid->fid, oldfid->fid, - newname); - if (IS_ERR(req)) - return PTR_ERR(req); - - p9_debug(P9_DEBUG_9P, "<<< RLINK\n"); - p9_free_req(clnt, req); - return 0; -} -EXPORT_SYMBOL(p9_client_link); - -int p9_client_fsync(struct p9_fid *fid, int datasync) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - p9_debug(P9_DEBUG_9P, ">>> TFSYNC fid %d datasync:%d\n", - fid->fid, datasync); - err = 0; - clnt = fid->clnt; - - req = p9_client_rpc(clnt, P9_TFSYNC, "dd", fid->fid, datasync); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RFSYNC fid %d\n", fid->fid); - - p9_free_req(clnt, req); - -error: - return err; -} -EXPORT_SYMBOL(p9_client_fsync); - -int p9_client_clunk(struct p9_fid *fid) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - int retries = 0; - - if (!fid) { - pr_warn("%s (%d): Trying to clunk with NULL fid\n", - __func__, task_pid_nr(current)); - dump_stack(); - return 0; - } - -again: - p9_debug(P9_DEBUG_9P, ">>> TCLUNK fid %d (try %d)\n", fid->fid, - retries); - err = 0; - clnt = fid->clnt; - - req = p9_client_rpc(clnt, P9_TCLUNK, "d", fid->fid); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RCLUNK fid %d\n", fid->fid); - - p9_free_req(clnt, req); -error: - /* - * Fid is not valid even after a failed clunk - * If interrupted, retry once then give up and - * leak fid until umount. - */ - if (err == -ERESTARTSYS) { - if (retries++ == 0) - goto again; - } else - p9_fid_destroy(fid); - return err; -} -EXPORT_SYMBOL(p9_client_clunk); - -int p9_client_remove(struct p9_fid *fid) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - p9_debug(P9_DEBUG_9P, ">>> TREMOVE fid %d\n", fid->fid); - err = 0; - clnt = fid->clnt; - - req = p9_client_rpc(clnt, P9_TREMOVE, "d", fid->fid); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RREMOVE fid %d\n", fid->fid); - - p9_free_req(clnt, req); -error: - if (err == -ERESTARTSYS) - p9_client_clunk(fid); - else - p9_fid_destroy(fid); - return err; -} -EXPORT_SYMBOL(p9_client_remove); - -int p9_client_unlinkat(struct p9_fid *dfid, const char *name, int flags) -{ - int err = 0; - struct p9_req_t *req; - struct p9_client *clnt; - - p9_debug(P9_DEBUG_9P, ">>> TUNLINKAT fid %d %s %d\n", - dfid->fid, name, flags); - - clnt = dfid->clnt; - req = p9_client_rpc(clnt, P9_TUNLINKAT, "dsd", dfid->fid, name, flags); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RUNLINKAT fid %d %s\n", dfid->fid, name); - - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_unlinkat); - -int -p9_client_read(struct p9_fid *fid, u64 offset, struct iov_iter *to, int *err) -{ - struct p9_client *clnt = fid->clnt; - struct p9_req_t *req; - int total = 0; - *err = 0; - - p9_debug(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", - fid->fid, (unsigned long long) offset, (int)iov_iter_count(to)); - - while (iov_iter_count(to)) { - int count = iov_iter_count(to); - int rsize, non_zc = 0; - char *dataptr; - - rsize = fid->iounit; - if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) - rsize = clnt->msize - P9_IOHDRSZ; - - if (count < rsize) - rsize = count; - - /* Don't bother zerocopy for small IO (< 1024) */ - if (clnt->trans_mod->zc_request && rsize > 1024) { - /* - * response header len is 11 - * PDU Header(7) + IO Size (4) - */ - req = p9_client_zc_rpc(clnt, P9_TREAD, to, NULL, rsize, - 0, 11, "dqd", fid->fid, - offset, rsize); - } else { - non_zc = 1; - req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, - rsize); - } - if (IS_ERR(req)) { - *err = PTR_ERR(req); - break; - } - - *err = p9pdu_readf(req->rc, clnt->proto_version, - "D", &count, &dataptr); - if (*err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - break; - } - if (rsize < count) { - pr_err("bogus RREAD count (%d > %d)\n", count, rsize); - count = rsize; - } - - p9_debug(P9_DEBUG_9P, "<<< RREAD count %d\n", count); - if (!count) { - p9_free_req(clnt, req); - break; - } - - if (non_zc) { - int n = copy_to_iter(dataptr, count, to); - total += n; - offset += n; - if (n != count) { - *err = -EFAULT; - p9_free_req(clnt, req); - break; - } - } else { - iov_iter_advance(to, count); - total += count; - offset += count; - } - p9_free_req(clnt, req); - } - return total; -} -EXPORT_SYMBOL(p9_client_read); - -int -p9_client_write(struct p9_fid *fid, u64 offset, struct iov_iter *from, int *err) -{ - struct p9_client *clnt = fid->clnt; - struct p9_req_t *req; - int total = 0; - *err = 0; - - p9_debug(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %zd\n", - fid->fid, (unsigned long long) offset, - iov_iter_count(from)); - - while (iov_iter_count(from)) { - int count = iov_iter_count(from); - int rsize = fid->iounit; - if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) - rsize = clnt->msize - P9_IOHDRSZ; - - if (count < rsize) - rsize = count; - - /* Don't bother zerocopy for small IO (< 1024) */ - if (clnt->trans_mod->zc_request && rsize > 1024) { - req = p9_client_zc_rpc(clnt, P9_TWRITE, NULL, from, 0, - rsize, P9_ZC_HDR_SZ, "dqd", - fid->fid, offset, rsize); - } else { - req = p9_client_rpc(clnt, P9_TWRITE, "dqV", fid->fid, - offset, rsize, from); - } - if (IS_ERR(req)) { - *err = PTR_ERR(req); - break; - } - - *err = p9pdu_readf(req->rc, clnt->proto_version, "d", &count); - if (*err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - break; - } - if (rsize < count) { - pr_err("bogus RWRITE count (%d > %d)\n", count, rsize); - count = rsize; - } - - p9_debug(P9_DEBUG_9P, "<<< RWRITE count %d\n", count); - - p9_free_req(clnt, req); - iov_iter_advance(from, count); - total += count; - offset += count; - } - return total; -} -EXPORT_SYMBOL(p9_client_write); - -struct p9_wstat *p9_client_stat(struct p9_fid *fid) -{ - int err; - struct p9_client *clnt; - struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL); - struct p9_req_t *req; - u16 ignored; - - p9_debug(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid); - - if (!ret) - return ERR_PTR(-ENOMEM); - - err = 0; - clnt = fid->clnt; - - req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "wS", &ignored, ret); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - goto error; - } - - p9_debug(P9_DEBUG_9P, - "<<< RSTAT sz=%x type=%x dev=%x qid=%x.%llx.%x\n" - "<<< mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n" - "<<< name=%s uid=%s gid=%s muid=%s extension=(%s)\n" - "<<< uid=%d gid=%d n_muid=%d\n", - ret->size, ret->type, ret->dev, ret->qid.type, - (unsigned long long)ret->qid.path, ret->qid.version, ret->mode, - ret->atime, ret->mtime, (unsigned long long)ret->length, - ret->name, ret->uid, ret->gid, ret->muid, ret->extension, - from_kuid(&init_user_ns, ret->n_uid), - from_kgid(&init_user_ns, ret->n_gid), - from_kuid(&init_user_ns, ret->n_muid)); - - p9_free_req(clnt, req); - return ret; - -error: - kfree(ret); - return ERR_PTR(err); -} -EXPORT_SYMBOL(p9_client_stat); - -struct p9_stat_dotl *p9_client_getattr_dotl(struct p9_fid *fid, - u64 request_mask) -{ - int err; - struct p9_client *clnt; - struct p9_stat_dotl *ret = kmalloc(sizeof(struct p9_stat_dotl), - GFP_KERNEL); - struct p9_req_t *req; - - p9_debug(P9_DEBUG_9P, ">>> TGETATTR fid %d, request_mask %lld\n", - fid->fid, request_mask); - - if (!ret) - return ERR_PTR(-ENOMEM); - - err = 0; - clnt = fid->clnt; - - req = p9_client_rpc(clnt, P9_TGETATTR, "dq", fid->fid, request_mask); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "A", ret); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - goto error; - } - - p9_debug(P9_DEBUG_9P, - "<<< RGETATTR st_result_mask=%lld\n" - "<<< qid=%x.%llx.%x\n" - "<<< st_mode=%8.8x st_nlink=%llu\n" - "<<< st_uid=%d st_gid=%d\n" - "<<< st_rdev=%llx st_size=%llx st_blksize=%llu st_blocks=%llu\n" - "<<< st_atime_sec=%lld st_atime_nsec=%lld\n" - "<<< st_mtime_sec=%lld st_mtime_nsec=%lld\n" - "<<< st_ctime_sec=%lld st_ctime_nsec=%lld\n" - "<<< st_btime_sec=%lld st_btime_nsec=%lld\n" - "<<< st_gen=%lld st_data_version=%lld", - ret->st_result_mask, ret->qid.type, ret->qid.path, - ret->qid.version, ret->st_mode, ret->st_nlink, - from_kuid(&init_user_ns, ret->st_uid), - from_kgid(&init_user_ns, ret->st_gid), - ret->st_rdev, ret->st_size, ret->st_blksize, - ret->st_blocks, ret->st_atime_sec, ret->st_atime_nsec, - ret->st_mtime_sec, ret->st_mtime_nsec, ret->st_ctime_sec, - ret->st_ctime_nsec, ret->st_btime_sec, ret->st_btime_nsec, - ret->st_gen, ret->st_data_version); - - p9_free_req(clnt, req); - return ret; - -error: - kfree(ret); - return ERR_PTR(err); -} -EXPORT_SYMBOL(p9_client_getattr_dotl); - -static int p9_client_statsize(struct p9_wstat *wst, int proto_version) -{ - int ret; - - /* NOTE: size shouldn't include its own length */ - /* size[2] type[2] dev[4] qid[13] */ - /* mode[4] atime[4] mtime[4] length[8]*/ - /* name[s] uid[s] gid[s] muid[s] */ - ret = 2+4+13+4+4+4+8+2+2+2+2; - - if (wst->name) - ret += strlen(wst->name); - if (wst->uid) - ret += strlen(wst->uid); - if (wst->gid) - ret += strlen(wst->gid); - if (wst->muid) - ret += strlen(wst->muid); - - if ((proto_version == p9_proto_2000u) || - (proto_version == p9_proto_2000L)) { - ret += 2+4+4+4; /* extension[s] n_uid[4] n_gid[4] n_muid[4] */ - if (wst->extension) - ret += strlen(wst->extension); - } - - return ret; -} - -int p9_client_wstat(struct p9_fid *fid, struct p9_wstat *wst) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - - err = 0; - clnt = fid->clnt; - wst->size = p9_client_statsize(wst, clnt->proto_version); - p9_debug(P9_DEBUG_9P, ">>> TWSTAT fid %d\n", fid->fid); - p9_debug(P9_DEBUG_9P, - " sz=%x type=%x dev=%x qid=%x.%llx.%x\n" - " mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n" - " name=%s uid=%s gid=%s muid=%s extension=(%s)\n" - " uid=%d gid=%d n_muid=%d\n", - wst->size, wst->type, wst->dev, wst->qid.type, - (unsigned long long)wst->qid.path, wst->qid.version, wst->mode, - wst->atime, wst->mtime, (unsigned long long)wst->length, - wst->name, wst->uid, wst->gid, wst->muid, wst->extension, - from_kuid(&init_user_ns, wst->n_uid), - from_kgid(&init_user_ns, wst->n_gid), - from_kuid(&init_user_ns, wst->n_muid)); - - req = p9_client_rpc(clnt, P9_TWSTAT, "dwS", fid->fid, wst->size+2, wst); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RWSTAT fid %d\n", fid->fid); - - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_wstat); - -int p9_client_setattr(struct p9_fid *fid, struct p9_iattr_dotl *p9attr) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - - err = 0; - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> TSETATTR fid %d\n", fid->fid); - p9_debug(P9_DEBUG_9P, - " valid=%x mode=%x uid=%d gid=%d size=%lld\n" - " atime_sec=%lld atime_nsec=%lld\n" - " mtime_sec=%lld mtime_nsec=%lld\n", - p9attr->valid, p9attr->mode, - from_kuid(&init_user_ns, p9attr->uid), - from_kgid(&init_user_ns, p9attr->gid), - p9attr->size, p9attr->atime_sec, p9attr->atime_nsec, - p9attr->mtime_sec, p9attr->mtime_nsec); - - req = p9_client_rpc(clnt, P9_TSETATTR, "dI", fid->fid, p9attr); - - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RSETATTR fid %d\n", fid->fid); - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_setattr); - -int p9_client_statfs(struct p9_fid *fid, struct p9_rstatfs *sb) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - - err = 0; - clnt = fid->clnt; - - p9_debug(P9_DEBUG_9P, ">>> TSTATFS fid %d\n", fid->fid); - - req = p9_client_rpc(clnt, P9_TSTATFS, "d", fid->fid); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "ddqqqqqqd", &sb->type, - &sb->bsize, &sb->blocks, &sb->bfree, &sb->bavail, - &sb->files, &sb->ffree, &sb->fsid, &sb->namelen); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RSTATFS fid %d type 0x%lx bsize %ld " - "blocks %llu bfree %llu bavail %llu files %llu ffree %llu " - "fsid %llu namelen %ld\n", - fid->fid, (long unsigned int)sb->type, (long int)sb->bsize, - sb->blocks, sb->bfree, sb->bavail, sb->files, sb->ffree, - sb->fsid, (long int)sb->namelen); - - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_statfs); - -int p9_client_rename(struct p9_fid *fid, - struct p9_fid *newdirfid, const char *name) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - - err = 0; - clnt = fid->clnt; - - p9_debug(P9_DEBUG_9P, ">>> TRENAME fid %d newdirfid %d name %s\n", - fid->fid, newdirfid->fid, name); - - req = p9_client_rpc(clnt, P9_TRENAME, "dds", fid->fid, - newdirfid->fid, name); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RRENAME fid %d\n", fid->fid); - - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_rename); - -int p9_client_renameat(struct p9_fid *olddirfid, const char *old_name, - struct p9_fid *newdirfid, const char *new_name) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - - err = 0; - clnt = olddirfid->clnt; - - p9_debug(P9_DEBUG_9P, ">>> TRENAMEAT olddirfid %d old name %s" - " newdirfid %d new name %s\n", olddirfid->fid, old_name, - newdirfid->fid, new_name); - - req = p9_client_rpc(clnt, P9_TRENAMEAT, "dsds", olddirfid->fid, - old_name, newdirfid->fid, new_name); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - p9_debug(P9_DEBUG_9P, "<<< RRENAMEAT newdirfid %d new name %s\n", - newdirfid->fid, new_name); - - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_renameat); - -/* - * An xattrwalk without @attr_name gives the fid for the lisxattr namespace - */ -struct p9_fid *p9_client_xattrwalk(struct p9_fid *file_fid, - const char *attr_name, u64 *attr_size) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - struct p9_fid *attr_fid; - - err = 0; - clnt = file_fid->clnt; - attr_fid = p9_fid_create(clnt); - if (IS_ERR(attr_fid)) { - err = PTR_ERR(attr_fid); - attr_fid = NULL; - goto error; - } - p9_debug(P9_DEBUG_9P, - ">>> TXATTRWALK file_fid %d, attr_fid %d name %s\n", - file_fid->fid, attr_fid->fid, attr_name); - - req = p9_client_rpc(clnt, P9_TXATTRWALK, "dds", - file_fid->fid, attr_fid->fid, attr_name); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - err = p9pdu_readf(req->rc, clnt->proto_version, "q", attr_size); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - p9_free_req(clnt, req); - goto clunk_fid; - } - p9_free_req(clnt, req); - p9_debug(P9_DEBUG_9P, "<<< RXATTRWALK fid %d size %llu\n", - attr_fid->fid, *attr_size); - return attr_fid; -clunk_fid: - p9_client_clunk(attr_fid); - attr_fid = NULL; -error: - if (attr_fid && (attr_fid != file_fid)) - p9_fid_destroy(attr_fid); - - return ERR_PTR(err); -} -EXPORT_SYMBOL_GPL(p9_client_xattrwalk); - -int p9_client_xattrcreate(struct p9_fid *fid, const char *name, - u64 attr_size, int flags) -{ - int err; - struct p9_req_t *req; - struct p9_client *clnt; - - p9_debug(P9_DEBUG_9P, - ">>> TXATTRCREATE fid %d name %s size %lld flag %d\n", - fid->fid, name, (long long)attr_size, flags); - err = 0; - clnt = fid->clnt; - req = p9_client_rpc(clnt, P9_TXATTRCREATE, "dsqd", - fid->fid, name, attr_size, flags); - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RXATTRCREATE fid %d\n", fid->fid); - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL_GPL(p9_client_xattrcreate); - -int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) -{ - int err, rsize, non_zc = 0; - struct p9_client *clnt; - struct p9_req_t *req; - char *dataptr; - struct kvec kv = {.iov_base = data, .iov_len = count}; - struct iov_iter to; - - iov_iter_kvec(&to, READ | ITER_KVEC, &kv, 1, count); - - p9_debug(P9_DEBUG_9P, ">>> TREADDIR fid %d offset %llu count %d\n", - fid->fid, (unsigned long long) offset, count); - - err = 0; - clnt = fid->clnt; - - rsize = fid->iounit; - if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ) - rsize = clnt->msize - P9_READDIRHDRSZ; - - if (count < rsize) - rsize = count; - - /* Don't bother zerocopy for small IO (< 1024) */ - if (clnt->trans_mod->zc_request && rsize > 1024) { - /* - * response header len is 11 - * PDU Header(7) + IO Size (4) - */ - req = p9_client_zc_rpc(clnt, P9_TREADDIR, &to, NULL, rsize, 0, - 11, "dqd", fid->fid, offset, rsize); - } else { - non_zc = 1; - req = p9_client_rpc(clnt, P9_TREADDIR, "dqd", fid->fid, - offset, rsize); - } - if (IS_ERR(req)) { - err = PTR_ERR(req); - goto error; - } - - err = p9pdu_readf(req->rc, clnt->proto_version, "D", &count, &dataptr); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto free_and_error; - } - if (rsize < count) { - pr_err("bogus RREADDIR count (%d > %d)\n", count, rsize); - count = rsize; - } - - p9_debug(P9_DEBUG_9P, "<<< RREADDIR count %d\n", count); - - if (non_zc) - memmove(data, dataptr, count); - - p9_free_req(clnt, req); - return count; - -free_and_error: - p9_free_req(clnt, req); -error: - return err; -} -EXPORT_SYMBOL(p9_client_readdir); - -int p9_client_mknod_dotl(struct p9_fid *fid, char *name, int mode, - dev_t rdev, kgid_t gid, struct p9_qid *qid) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - err = 0; - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> TMKNOD fid %d name %s mode %d major %d " - "minor %d\n", fid->fid, name, mode, MAJOR(rdev), MINOR(rdev)); - req = p9_client_rpc(clnt, P9_TMKNOD, "dsdddg", fid->fid, name, mode, - MAJOR(rdev), MINOR(rdev), gid); - if (IS_ERR(req)) - return PTR_ERR(req); - - err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RMKNOD qid %x.%llx.%x\n", qid->type, - (unsigned long long)qid->path, qid->version); - -error: - p9_free_req(clnt, req); - return err; - -} -EXPORT_SYMBOL(p9_client_mknod_dotl); - -int p9_client_mkdir_dotl(struct p9_fid *fid, char *name, int mode, - kgid_t gid, struct p9_qid *qid) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - err = 0; - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> TMKDIR fid %d name %s mode %d gid %d\n", - fid->fid, name, mode, from_kgid(&init_user_ns, gid)); - req = p9_client_rpc(clnt, P9_TMKDIR, "dsdg", fid->fid, name, mode, - gid); - if (IS_ERR(req)) - return PTR_ERR(req); - - err = p9pdu_readf(req->rc, clnt->proto_version, "Q", qid); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RMKDIR qid %x.%llx.%x\n", qid->type, - (unsigned long long)qid->path, qid->version); - -error: - p9_free_req(clnt, req); - return err; - -} -EXPORT_SYMBOL(p9_client_mkdir_dotl); - -int p9_client_lock_dotl(struct p9_fid *fid, struct p9_flock *flock, u8 *status) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - err = 0; - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> TLOCK fid %d type %i flags %d " - "start %lld length %lld proc_id %d client_id %s\n", - fid->fid, flock->type, flock->flags, flock->start, - flock->length, flock->proc_id, flock->client_id); - - req = p9_client_rpc(clnt, P9_TLOCK, "dbdqqds", fid->fid, flock->type, - flock->flags, flock->start, flock->length, - flock->proc_id, flock->client_id); - - if (IS_ERR(req)) - return PTR_ERR(req); - - err = p9pdu_readf(req->rc, clnt->proto_version, "b", status); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RLOCK status %i\n", *status); -error: - p9_free_req(clnt, req); - return err; - -} -EXPORT_SYMBOL(p9_client_lock_dotl); - -int p9_client_getlock_dotl(struct p9_fid *fid, struct p9_getlock *glock) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - err = 0; - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> TGETLOCK fid %d, type %i start %lld " - "length %lld proc_id %d client_id %s\n", fid->fid, glock->type, - glock->start, glock->length, glock->proc_id, glock->client_id); - - req = p9_client_rpc(clnt, P9_TGETLOCK, "dbqqds", fid->fid, glock->type, - glock->start, glock->length, glock->proc_id, glock->client_id); - - if (IS_ERR(req)) - return PTR_ERR(req); - - err = p9pdu_readf(req->rc, clnt->proto_version, "bqqds", &glock->type, - &glock->start, &glock->length, &glock->proc_id, - &glock->client_id); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RGETLOCK type %i start %lld length %lld " - "proc_id %d client_id %s\n", glock->type, glock->start, - glock->length, glock->proc_id, glock->client_id); -error: - p9_free_req(clnt, req); - return err; -} -EXPORT_SYMBOL(p9_client_getlock_dotl); - -int p9_client_readlink(struct p9_fid *fid, char **target) -{ - int err; - struct p9_client *clnt; - struct p9_req_t *req; - - err = 0; - clnt = fid->clnt; - p9_debug(P9_DEBUG_9P, ">>> TREADLINK fid %d\n", fid->fid); - - req = p9_client_rpc(clnt, P9_TREADLINK, "d", fid->fid); - if (IS_ERR(req)) - return PTR_ERR(req); - - err = p9pdu_readf(req->rc, clnt->proto_version, "s", target); - if (err) { - trace_9p_protocol_dump(clnt, req->rc); - goto error; - } - p9_debug(P9_DEBUG_9P, "<<< RREADLINK target %s\n", *target); -error: - p9_free_req(clnt, req); - return err; -} -EXPORT_SYMBOL(p9_client_readlink); diff --git a/addons/9p/src/4.4.180/error.c b/addons/9p/src/4.4.180/error.c deleted file mode 100644 index 126fd0dc..00000000 --- a/addons/9p/src/4.4.180/error.c +++ /dev/null @@ -1,247 +0,0 @@ -/* - * linux/fs/9p/error.c - * - * Error string handling - * - * Plan 9 uses error strings, Unix uses error numbers. These functions - * try to help manage that and provide for dynamically adding error - * mappings. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include - -/** - * struct errormap - map string errors from Plan 9 to Linux numeric ids - * @name: string sent over 9P - * @val: numeric id most closely representing @name - * @namelen: length of string - * @list: hash-table list for string lookup - */ -struct errormap { - char *name; - int val; - - int namelen; - struct hlist_node list; -}; - -#define ERRHASHSZ 32 -static struct hlist_head hash_errmap[ERRHASHSZ]; - -/* FixMe - reduce to a reasonable size */ -static struct errormap errmap[] = { - {"Operation not permitted", EPERM}, - {"wstat prohibited", EPERM}, - {"No such file or directory", ENOENT}, - {"directory entry not found", ENOENT}, - {"file not found", ENOENT}, - {"Interrupted system call", EINTR}, - {"Input/output error", EIO}, - {"No such device or address", ENXIO}, - {"Argument list too long", E2BIG}, - {"Bad file descriptor", EBADF}, - {"Resource temporarily unavailable", EAGAIN}, - {"Cannot allocate memory", ENOMEM}, - {"Permission denied", EACCES}, - {"Bad address", EFAULT}, - {"Block device required", ENOTBLK}, - {"Device or resource busy", EBUSY}, - {"File exists", EEXIST}, - {"Invalid cross-device link", EXDEV}, - {"No such device", ENODEV}, - {"Not a directory", ENOTDIR}, - {"Is a directory", EISDIR}, - {"Invalid argument", EINVAL}, - {"Too many open files in system", ENFILE}, - {"Too many open files", EMFILE}, - {"Text file busy", ETXTBSY}, - {"File too large", EFBIG}, - {"No space left on device", ENOSPC}, - {"Illegal seek", ESPIPE}, - {"Read-only file system", EROFS}, - {"Too many links", EMLINK}, - {"Broken pipe", EPIPE}, - {"Numerical argument out of domain", EDOM}, - {"Numerical result out of range", ERANGE}, - {"Resource deadlock avoided", EDEADLK}, - {"File name too long", ENAMETOOLONG}, - {"No locks available", ENOLCK}, - {"Function not implemented", ENOSYS}, - {"Directory not empty", ENOTEMPTY}, - {"Too many levels of symbolic links", ELOOP}, - {"No message of desired type", ENOMSG}, - {"Identifier removed", EIDRM}, - {"No data available", ENODATA}, - {"Machine is not on the network", ENONET}, - {"Package not installed", ENOPKG}, - {"Object is remote", EREMOTE}, - {"Link has been severed", ENOLINK}, - {"Communication error on send", ECOMM}, - {"Protocol error", EPROTO}, - {"Bad message", EBADMSG}, - {"File descriptor in bad state", EBADFD}, - {"Streams pipe error", ESTRPIPE}, - {"Too many users", EUSERS}, - {"Socket operation on non-socket", ENOTSOCK}, - {"Message too long", EMSGSIZE}, - {"Protocol not available", ENOPROTOOPT}, - {"Protocol not supported", EPROTONOSUPPORT}, - {"Socket type not supported", ESOCKTNOSUPPORT}, - {"Operation not supported", EOPNOTSUPP}, - {"Protocol family not supported", EPFNOSUPPORT}, - {"Network is down", ENETDOWN}, - {"Network is unreachable", ENETUNREACH}, - {"Network dropped connection on reset", ENETRESET}, - {"Software caused connection abort", ECONNABORTED}, - {"Connection reset by peer", ECONNRESET}, - {"No buffer space available", ENOBUFS}, - {"Transport endpoint is already connected", EISCONN}, - {"Transport endpoint is not connected", ENOTCONN}, - {"Cannot send after transport endpoint shutdown", ESHUTDOWN}, - {"Connection timed out", ETIMEDOUT}, - {"Connection refused", ECONNREFUSED}, - {"Host is down", EHOSTDOWN}, - {"No route to host", EHOSTUNREACH}, - {"Operation already in progress", EALREADY}, - {"Operation now in progress", EINPROGRESS}, - {"Is a named type file", EISNAM}, - {"Remote I/O error", EREMOTEIO}, - {"Disk quota exceeded", EDQUOT}, -/* errors from fossil, vacfs, and u9fs */ - {"fid unknown or out of range", EBADF}, - {"permission denied", EACCES}, - {"file does not exist", ENOENT}, - {"authentication failed", ECONNREFUSED}, - {"bad offset in directory read", ESPIPE}, - {"bad use of fid", EBADF}, - {"wstat can't convert between files and directories", EPERM}, - {"directory is not empty", ENOTEMPTY}, - {"file exists", EEXIST}, - {"file already exists", EEXIST}, - {"file or directory already exists", EEXIST}, - {"fid already in use", EBADF}, - {"file in use", ETXTBSY}, - {"i/o error", EIO}, - {"file already open for I/O", ETXTBSY}, - {"illegal mode", EINVAL}, - {"illegal name", ENAMETOOLONG}, - {"not a directory", ENOTDIR}, - {"not a member of proposed group", EPERM}, - {"not owner", EACCES}, - {"only owner can change group in wstat", EACCES}, - {"read only file system", EROFS}, - {"no access to special file", EPERM}, - {"i/o count too large", EIO}, - {"unknown group", EINVAL}, - {"unknown user", EINVAL}, - {"bogus wstat buffer", EPROTO}, - {"exclusive use file already open", EAGAIN}, - {"corrupted directory entry", EIO}, - {"corrupted file entry", EIO}, - {"corrupted block label", EIO}, - {"corrupted meta data", EIO}, - {"illegal offset", EINVAL}, - {"illegal path element", ENOENT}, - {"root of file system is corrupted", EIO}, - {"corrupted super block", EIO}, - {"protocol botch", EPROTO}, - {"file system is full", ENOSPC}, - {"file is in use", EAGAIN}, - {"directory entry is not allocated", ENOENT}, - {"file is read only", EROFS}, - {"file has been removed", EIDRM}, - {"only support truncation to zero length", EPERM}, - {"cannot remove root", EPERM}, - {"file too big", EFBIG}, - {"venti i/o error", EIO}, - /* these are not errors */ - {"u9fs rhostsauth: no authentication required", 0}, - {"u9fs authnone: no authentication required", 0}, - {NULL, -1} -}; - -/** - * p9_error_init - preload mappings into hash list - * - */ - -int p9_error_init(void) -{ - struct errormap *c; - int bucket; - - /* initialize hash table */ - for (bucket = 0; bucket < ERRHASHSZ; bucket++) - INIT_HLIST_HEAD(&hash_errmap[bucket]); - - /* load initial error map into hash table */ - for (c = errmap; c->name != NULL; c++) { - c->namelen = strlen(c->name); - bucket = jhash(c->name, c->namelen, 0) % ERRHASHSZ; - INIT_HLIST_NODE(&c->list); - hlist_add_head(&c->list, &hash_errmap[bucket]); - } - - return 1; -} -EXPORT_SYMBOL(p9_error_init); - -/** - * errstr2errno - convert error string to error number - * @errstr: error string - * @len: length of error string - * - */ - -int p9_errstr2errno(char *errstr, int len) -{ - int errno; - struct errormap *c; - int bucket; - - errno = 0; - c = NULL; - bucket = jhash(errstr, len, 0) % ERRHASHSZ; - hlist_for_each_entry(c, &hash_errmap[bucket], list) { - if (c->namelen == len && !memcmp(c->name, errstr, len)) { - errno = c->val; - break; - } - } - - if (errno == 0) { - /* TODO: if error isn't found, add it dynamically */ - errstr[len] = 0; - pr_err("%s: server reported unknown error %s\n", - __func__, errstr); - errno = ESERVERFAULT; - } - - return -errno; -} -EXPORT_SYMBOL(p9_errstr2errno); diff --git a/addons/9p/src/4.4.180/fid.c b/addons/9p/src/4.4.180/fid.c deleted file mode 100644 index 47db55ae..00000000 --- a/addons/9p/src/4.4.180/fid.c +++ /dev/null @@ -1,306 +0,0 @@ -/* - * V9FS FID Management - * - * Copyright (C) 2007 by Latchesar Ionkov - * Copyright (C) 2005, 2006 by Eric Van Hensbergen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" - -/** - * v9fs_fid_add - add a fid to a dentry - * @dentry: dentry that the fid is being added to - * @fid: fid to add - * - */ - -static inline void __add_fid(struct dentry *dentry, struct p9_fid *fid) -{ - hlist_add_head(&fid->dlist, (struct hlist_head *)&dentry->d_fsdata); -} - -void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid) -{ - spin_lock(&dentry->d_lock); - __add_fid(dentry, fid); - spin_unlock(&dentry->d_lock); -} - -/** - * v9fs_fid_find - retrieve a fid that belongs to the specified uid - * @dentry: dentry to look for fid in - * @uid: return fid that belongs to the specified user - * @any: if non-zero, return any fid associated with the dentry - * - */ - -static struct p9_fid *v9fs_fid_find(struct dentry *dentry, kuid_t uid, int any) -{ - struct p9_fid *fid, *ret; - - p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p) uid %d any %d\n", - dentry, dentry, from_kuid(&init_user_ns, uid), - any); - ret = NULL; - /* we'll recheck under lock if there's anything to look in */ - if (dentry->d_fsdata) { - struct hlist_head *h = (struct hlist_head *)&dentry->d_fsdata; - spin_lock(&dentry->d_lock); - hlist_for_each_entry(fid, h, dlist) { - if (any || uid_eq(fid->uid, uid)) { - ret = fid; - break; - } - } - spin_unlock(&dentry->d_lock); - } - - return ret; -} - -/* - * We need to hold v9ses->rename_sem as long as we hold references - * to returned path array. Array element contain pointers to - * dentry names. - */ -static int build_path_from_dentry(struct v9fs_session_info *v9ses, - struct dentry *dentry, char ***names) -{ - int n = 0, i; - char **wnames; - struct dentry *ds; - - for (ds = dentry; !IS_ROOT(ds); ds = ds->d_parent) - n++; - - wnames = kmalloc(sizeof(char *) * n, GFP_KERNEL); - if (!wnames) - goto err_out; - - for (ds = dentry, i = (n-1); i >= 0; i--, ds = ds->d_parent) - wnames[i] = (char *)ds->d_name.name; - - *names = wnames; - return n; -err_out: - return -ENOMEM; -} - -static struct p9_fid *v9fs_fid_lookup_with_uid(struct dentry *dentry, - kuid_t uid, int any) -{ - struct dentry *ds; - char **wnames, *uname; - int i, n, l, clone, access; - struct v9fs_session_info *v9ses; - struct p9_fid *fid, *old_fid = NULL; - - v9ses = v9fs_dentry2v9ses(dentry); - access = v9ses->flags & V9FS_ACCESS_MASK; - fid = v9fs_fid_find(dentry, uid, any); - if (fid) - return fid; - /* - * we don't have a matching fid. To do a TWALK we need - * parent fid. We need to prevent rename when we want to - * look at the parent. - */ - down_read(&v9ses->rename_sem); - ds = dentry->d_parent; - fid = v9fs_fid_find(ds, uid, any); - if (fid) { - /* Found the parent fid do a lookup with that */ - fid = p9_client_walk(fid, 1, (char **)&dentry->d_name.name, 1); - goto fid_out; - } - up_read(&v9ses->rename_sem); - - /* start from the root and try to do a lookup */ - fid = v9fs_fid_find(dentry->d_sb->s_root, uid, any); - if (!fid) { - /* the user is not attached to the fs yet */ - if (access == V9FS_ACCESS_SINGLE) - return ERR_PTR(-EPERM); - - if (v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) - uname = NULL; - else - uname = v9ses->uname; - - fid = p9_client_attach(v9ses->clnt, NULL, uname, uid, - v9ses->aname); - if (IS_ERR(fid)) - return fid; - - v9fs_fid_add(dentry->d_sb->s_root, fid); - } - /* If we are root ourself just return that */ - if (dentry->d_sb->s_root == dentry) - return fid; - /* - * Do a multipath walk with attached root. - * When walking parent we need to make sure we - * don't have a parallel rename happening - */ - down_read(&v9ses->rename_sem); - n = build_path_from_dentry(v9ses, dentry, &wnames); - if (n < 0) { - fid = ERR_PTR(n); - goto err_out; - } - clone = 1; - i = 0; - while (i < n) { - l = min(n - i, P9_MAXWELEM); - /* - * We need to hold rename lock when doing a multipath - * walk to ensure none of the patch component change - */ - fid = p9_client_walk(fid, l, &wnames[i], clone); - if (IS_ERR(fid)) { - if (old_fid) { - /* - * If we fail, clunk fid which are mapping - * to path component and not the last component - * of the path. - */ - p9_client_clunk(old_fid); - } - kfree(wnames); - goto err_out; - } - old_fid = fid; - i += l; - clone = 0; - } - kfree(wnames); -fid_out: - if (!IS_ERR(fid)) { - spin_lock(&dentry->d_lock); - if (d_unhashed(dentry)) { - spin_unlock(&dentry->d_lock); - p9_client_clunk(fid); - fid = ERR_PTR(-ENOENT); - } else { - __add_fid(dentry, fid); - spin_unlock(&dentry->d_lock); - } - } -err_out: - up_read(&v9ses->rename_sem); - return fid; -} - -/** - * v9fs_fid_lookup - lookup for a fid, try to walk if not found - * @dentry: dentry to look for fid in - * - * Look for a fid in the specified dentry for the current user. - * If no fid is found, try to create one walking from a fid from the parent - * dentry (if it has one), or the root dentry. If the user haven't accessed - * the fs yet, attach now and walk from the root. - */ - -struct p9_fid *v9fs_fid_lookup(struct dentry *dentry) -{ - kuid_t uid; - int any, access; - struct v9fs_session_info *v9ses; - - v9ses = v9fs_dentry2v9ses(dentry); - access = v9ses->flags & V9FS_ACCESS_MASK; - switch (access) { - case V9FS_ACCESS_SINGLE: - case V9FS_ACCESS_USER: - case V9FS_ACCESS_CLIENT: - uid = current_fsuid(); - any = 0; - break; - - case V9FS_ACCESS_ANY: - uid = v9ses->uid; - any = 1; - break; - - default: - uid = INVALID_UID; - any = 0; - break; - } - return v9fs_fid_lookup_with_uid(dentry, uid, any); -} - -struct p9_fid *v9fs_fid_clone(struct dentry *dentry) -{ - struct p9_fid *fid, *ret; - - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return fid; - - ret = p9_client_walk(fid, 0, NULL, 1); - return ret; -} - -static struct p9_fid *v9fs_fid_clone_with_uid(struct dentry *dentry, kuid_t uid) -{ - struct p9_fid *fid, *ret; - - fid = v9fs_fid_lookup_with_uid(dentry, uid, 0); - if (IS_ERR(fid)) - return fid; - - ret = p9_client_walk(fid, 0, NULL, 1); - return ret; -} - -struct p9_fid *v9fs_writeback_fid(struct dentry *dentry) -{ - int err; - struct p9_fid *fid; - - fid = v9fs_fid_clone_with_uid(dentry, GLOBAL_ROOT_UID); - if (IS_ERR(fid)) - goto error_out; - /* - * writeback fid will only be used to write back the - * dirty pages. We always request for the open fid in read-write - * mode so that a partial page write which result in page - * read can work. - */ - err = p9_client_open(fid, O_RDWR); - if (err < 0) { - p9_client_clunk(fid); - fid = ERR_PTR(err); - goto error_out; - } -error_out: - return fid; -} diff --git a/addons/9p/src/4.4.180/fid.h b/addons/9p/src/4.4.180/fid.h deleted file mode 100644 index 2b6787fc..00000000 --- a/addons/9p/src/4.4.180/fid.h +++ /dev/null @@ -1,30 +0,0 @@ -/* - * V9FS FID Management - * - * Copyright (C) 2005 by Eric Van Hensbergen - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ -#ifndef FS_9P_FID_H -#define FS_9P_FID_H -#include - -struct p9_fid *v9fs_fid_lookup(struct dentry *dentry); -struct p9_fid *v9fs_fid_clone(struct dentry *dentry); -void v9fs_fid_add(struct dentry *dentry, struct p9_fid *fid); -struct p9_fid *v9fs_writeback_fid(struct dentry *dentry); -#endif diff --git a/addons/9p/src/4.4.180/mod.c b/addons/9p/src/4.4.180/mod.c deleted file mode 100644 index 6ab36aea..00000000 --- a/addons/9p/src/4.4.180/mod.c +++ /dev/null @@ -1,201 +0,0 @@ -/* - * net/9p/9p.c - * - * 9P entry point - * - * Copyright (C) 2007 by Latchesar Ionkov - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef CONFIG_NET_9P_DEBUG -unsigned int p9_debug_level = 0; /* feature-rific global debug level */ -EXPORT_SYMBOL(p9_debug_level); -module_param_named(debug, p9_debug_level, uint, 0); -MODULE_PARM_DESC(debug, "9P debugging level"); - -void _p9_debug(enum p9_debug_flags level, const char *func, - const char *fmt, ...) -{ - struct va_format vaf; - va_list args; - - if ((p9_debug_level & level) != level) - return; - - va_start(args, fmt); - - vaf.fmt = fmt; - vaf.va = &args; - - if (level == P9_DEBUG_9P) - pr_notice("(%8.8d) %pV", task_pid_nr(current), &vaf); - else - pr_notice("-- %s (%d): %pV", func, task_pid_nr(current), &vaf); - - va_end(args); -} -EXPORT_SYMBOL(_p9_debug); -#endif - -/* - * Dynamic Transport Registration Routines - * - */ - -static DEFINE_SPINLOCK(v9fs_trans_lock); -static LIST_HEAD(v9fs_trans_list); - -/** - * v9fs_register_trans - register a new transport with 9p - * @m: structure describing the transport module and entry points - * - */ -void v9fs_register_trans(struct p9_trans_module *m) -{ - spin_lock(&v9fs_trans_lock); - list_add_tail(&m->list, &v9fs_trans_list); - spin_unlock(&v9fs_trans_lock); -} -EXPORT_SYMBOL(v9fs_register_trans); - -/** - * v9fs_unregister_trans - unregister a 9p transport - * @m: the transport to remove - * - */ -void v9fs_unregister_trans(struct p9_trans_module *m) -{ - spin_lock(&v9fs_trans_lock); - list_del_init(&m->list); - spin_unlock(&v9fs_trans_lock); -} -EXPORT_SYMBOL(v9fs_unregister_trans); - -/** - * v9fs_get_trans_by_name - get transport with the matching name - * @name: string identifying transport - * - */ -struct p9_trans_module *v9fs_get_trans_by_name(char *s) -{ - struct p9_trans_module *t, *found = NULL; - - spin_lock(&v9fs_trans_lock); - - list_for_each_entry(t, &v9fs_trans_list, list) - if (strcmp(t->name, s) == 0 && - try_module_get(t->owner)) { - found = t; - break; - } - - spin_unlock(&v9fs_trans_lock); - return found; -} -EXPORT_SYMBOL(v9fs_get_trans_by_name); - -/** - * v9fs_get_default_trans - get the default transport - * - */ - -struct p9_trans_module *v9fs_get_default_trans(void) -{ - struct p9_trans_module *t, *found = NULL; - - spin_lock(&v9fs_trans_lock); - - list_for_each_entry(t, &v9fs_trans_list, list) - if (t->def && try_module_get(t->owner)) { - found = t; - break; - } - - if (!found) - list_for_each_entry(t, &v9fs_trans_list, list) - if (try_module_get(t->owner)) { - found = t; - break; - } - - spin_unlock(&v9fs_trans_lock); - return found; -} -EXPORT_SYMBOL(v9fs_get_default_trans); - -/** - * v9fs_put_trans - put trans - * @m: transport to put - * - */ -void v9fs_put_trans(struct p9_trans_module *m) -{ - if (m) - module_put(m->owner); -} - -/** - * init_p9 - Initialize module - * - */ -static int __init init_p9(void) -{ - int ret = 0; - - p9_error_init(); - pr_info("Installing 9P2000 support\n"); - p9_trans_fd_init(); - - return ret; -} - -/** - * exit_p9 - shutdown module - * - */ - -static void __exit exit_p9(void) -{ - pr_info("Unloading 9P2000 support\n"); - - p9_trans_fd_exit(); -} - -module_init(init_p9) -module_exit(exit_p9) - -MODULE_AUTHOR("Latchesar Ionkov "); -MODULE_AUTHOR("Eric Van Hensbergen "); -MODULE_AUTHOR("Ron Minnich "); -MODULE_LICENSE("GPL"); diff --git a/addons/9p/src/4.4.180/protocol.c b/addons/9p/src/4.4.180/protocol.c deleted file mode 100644 index 7f1b45c0..00000000 --- a/addons/9p/src/4.4.180/protocol.c +++ /dev/null @@ -1,634 +0,0 @@ -/* - * net/9p/protocol.c - * - * 9P Protocol Support Code - * - * Copyright (C) 2008 by Eric Van Hensbergen - * - * Base on code from Anthony Liguori - * Copyright (C) 2008 by IBM, Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "protocol.h" - -#include - -static int -p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); - -void p9stat_free(struct p9_wstat *stbuf) -{ - kfree(stbuf->name); - stbuf->name = NULL; - kfree(stbuf->uid); - stbuf->uid = NULL; - kfree(stbuf->gid); - stbuf->gid = NULL; - kfree(stbuf->muid); - stbuf->muid = NULL; - kfree(stbuf->extension); - stbuf->extension = NULL; -} -EXPORT_SYMBOL(p9stat_free); - -size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size) -{ - size_t len = min(pdu->size - pdu->offset, size); - memcpy(data, &pdu->sdata[pdu->offset], len); - pdu->offset += len; - return size - len; -} - -static size_t pdu_write(struct p9_fcall *pdu, const void *data, size_t size) -{ - size_t len = min(pdu->capacity - pdu->size, size); - memcpy(&pdu->sdata[pdu->size], data, len); - pdu->size += len; - return size - len; -} - -static size_t -pdu_write_u(struct p9_fcall *pdu, struct iov_iter *from, size_t size) -{ - size_t len = min(pdu->capacity - pdu->size, size); - struct iov_iter i = *from; - if (copy_from_iter(&pdu->sdata[pdu->size], len, &i) != len) - len = 0; - - pdu->size += len; - return size - len; -} - -/* - b - int8_t - w - int16_t - d - int32_t - q - int64_t - s - string - u - numeric uid - g - numeric gid - S - stat - Q - qid - D - data blob (int32_t size followed by void *, results are not freed) - T - array of strings (int16_t count, followed by strings) - R - array of qids (int16_t count, followed by qids) - A - stat for 9p2000.L (p9_stat_dotl) - ? - if optional = 1, continue parsing -*/ - -static int -p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt, - va_list ap) -{ - const char *ptr; - int errcode = 0; - - for (ptr = fmt; *ptr; ptr++) { - switch (*ptr) { - case 'b':{ - int8_t *val = va_arg(ap, int8_t *); - if (pdu_read(pdu, val, sizeof(*val))) { - errcode = -EFAULT; - break; - } - } - break; - case 'w':{ - int16_t *val = va_arg(ap, int16_t *); - __le16 le_val; - if (pdu_read(pdu, &le_val, sizeof(le_val))) { - errcode = -EFAULT; - break; - } - *val = le16_to_cpu(le_val); - } - break; - case 'd':{ - int32_t *val = va_arg(ap, int32_t *); - __le32 le_val; - if (pdu_read(pdu, &le_val, sizeof(le_val))) { - errcode = -EFAULT; - break; - } - *val = le32_to_cpu(le_val); - } - break; - case 'q':{ - int64_t *val = va_arg(ap, int64_t *); - __le64 le_val; - if (pdu_read(pdu, &le_val, sizeof(le_val))) { - errcode = -EFAULT; - break; - } - *val = le64_to_cpu(le_val); - } - break; - case 's':{ - char **sptr = va_arg(ap, char **); - uint16_t len; - - errcode = p9pdu_readf(pdu, proto_version, - "w", &len); - if (errcode) - break; - - *sptr = kmalloc(len + 1, GFP_NOFS); - if (*sptr == NULL) { - errcode = -EFAULT; - break; - } - if (pdu_read(pdu, *sptr, len)) { - errcode = -EFAULT; - kfree(*sptr); - *sptr = NULL; - } else - (*sptr)[len] = 0; - } - break; - case 'u': { - kuid_t *uid = va_arg(ap, kuid_t *); - __le32 le_val; - if (pdu_read(pdu, &le_val, sizeof(le_val))) { - errcode = -EFAULT; - break; - } - *uid = make_kuid(&init_user_ns, - le32_to_cpu(le_val)); - } break; - case 'g': { - kgid_t *gid = va_arg(ap, kgid_t *); - __le32 le_val; - if (pdu_read(pdu, &le_val, sizeof(le_val))) { - errcode = -EFAULT; - break; - } - *gid = make_kgid(&init_user_ns, - le32_to_cpu(le_val)); - } break; - case 'Q':{ - struct p9_qid *qid = - va_arg(ap, struct p9_qid *); - - errcode = p9pdu_readf(pdu, proto_version, "bdq", - &qid->type, &qid->version, - &qid->path); - } - break; - case 'S':{ - struct p9_wstat *stbuf = - va_arg(ap, struct p9_wstat *); - - memset(stbuf, 0, sizeof(struct p9_wstat)); - stbuf->n_uid = stbuf->n_muid = INVALID_UID; - stbuf->n_gid = INVALID_GID; - - errcode = - p9pdu_readf(pdu, proto_version, - "wwdQdddqssss?sugu", - &stbuf->size, &stbuf->type, - &stbuf->dev, &stbuf->qid, - &stbuf->mode, &stbuf->atime, - &stbuf->mtime, &stbuf->length, - &stbuf->name, &stbuf->uid, - &stbuf->gid, &stbuf->muid, - &stbuf->extension, - &stbuf->n_uid, &stbuf->n_gid, - &stbuf->n_muid); - if (errcode) - p9stat_free(stbuf); - } - break; - case 'D':{ - uint32_t *count = va_arg(ap, uint32_t *); - void **data = va_arg(ap, void **); - - errcode = - p9pdu_readf(pdu, proto_version, "d", count); - if (!errcode) { - *count = - min_t(uint32_t, *count, - pdu->size - pdu->offset); - *data = &pdu->sdata[pdu->offset]; - } - } - break; - case 'T':{ - uint16_t *nwname = va_arg(ap, uint16_t *); - char ***wnames = va_arg(ap, char ***); - - errcode = p9pdu_readf(pdu, proto_version, - "w", nwname); - if (!errcode) { - *wnames = - kmalloc(sizeof(char *) * *nwname, - GFP_NOFS); - if (!*wnames) - errcode = -ENOMEM; - } - - if (!errcode) { - int i; - - for (i = 0; i < *nwname; i++) { - errcode = - p9pdu_readf(pdu, - proto_version, - "s", - &(*wnames)[i]); - if (errcode) - break; - } - } - - if (errcode) { - if (*wnames) { - int i; - - for (i = 0; i < *nwname; i++) - kfree((*wnames)[i]); - } - kfree(*wnames); - *wnames = NULL; - } - } - break; - case 'R':{ - uint16_t *nwqid = va_arg(ap, uint16_t *); - struct p9_qid **wqids = - va_arg(ap, struct p9_qid **); - - *wqids = NULL; - - errcode = - p9pdu_readf(pdu, proto_version, "w", nwqid); - if (!errcode) { - *wqids = - kmalloc(*nwqid * - sizeof(struct p9_qid), - GFP_NOFS); - if (*wqids == NULL) - errcode = -ENOMEM; - } - - if (!errcode) { - int i; - - for (i = 0; i < *nwqid; i++) { - errcode = - p9pdu_readf(pdu, - proto_version, - "Q", - &(*wqids)[i]); - if (errcode) - break; - } - } - - if (errcode) { - kfree(*wqids); - *wqids = NULL; - } - } - break; - case 'A': { - struct p9_stat_dotl *stbuf = - va_arg(ap, struct p9_stat_dotl *); - - memset(stbuf, 0, sizeof(struct p9_stat_dotl)); - errcode = - p9pdu_readf(pdu, proto_version, - "qQdugqqqqqqqqqqqqqqq", - &stbuf->st_result_mask, - &stbuf->qid, - &stbuf->st_mode, - &stbuf->st_uid, &stbuf->st_gid, - &stbuf->st_nlink, - &stbuf->st_rdev, &stbuf->st_size, - &stbuf->st_blksize, &stbuf->st_blocks, - &stbuf->st_atime_sec, - &stbuf->st_atime_nsec, - &stbuf->st_mtime_sec, - &stbuf->st_mtime_nsec, - &stbuf->st_ctime_sec, - &stbuf->st_ctime_nsec, - &stbuf->st_btime_sec, - &stbuf->st_btime_nsec, - &stbuf->st_gen, - &stbuf->st_data_version); - } - break; - case '?': - if ((proto_version != p9_proto_2000u) && - (proto_version != p9_proto_2000L)) - return 0; - break; - default: - BUG(); - break; - } - - if (errcode) - break; - } - - return errcode; -} - -int -p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, - va_list ap) -{ - const char *ptr; - int errcode = 0; - - for (ptr = fmt; *ptr; ptr++) { - switch (*ptr) { - case 'b':{ - int8_t val = va_arg(ap, int); - if (pdu_write(pdu, &val, sizeof(val))) - errcode = -EFAULT; - } - break; - case 'w':{ - __le16 val = cpu_to_le16(va_arg(ap, int)); - if (pdu_write(pdu, &val, sizeof(val))) - errcode = -EFAULT; - } - break; - case 'd':{ - __le32 val = cpu_to_le32(va_arg(ap, int32_t)); - if (pdu_write(pdu, &val, sizeof(val))) - errcode = -EFAULT; - } - break; - case 'q':{ - __le64 val = cpu_to_le64(va_arg(ap, int64_t)); - if (pdu_write(pdu, &val, sizeof(val))) - errcode = -EFAULT; - } - break; - case 's':{ - const char *sptr = va_arg(ap, const char *); - uint16_t len = 0; - if (sptr) - len = min_t(size_t, strlen(sptr), - USHRT_MAX); - - errcode = p9pdu_writef(pdu, proto_version, - "w", len); - if (!errcode && pdu_write(pdu, sptr, len)) - errcode = -EFAULT; - } - break; - case 'u': { - kuid_t uid = va_arg(ap, kuid_t); - __le32 val = cpu_to_le32( - from_kuid(&init_user_ns, uid)); - if (pdu_write(pdu, &val, sizeof(val))) - errcode = -EFAULT; - } break; - case 'g': { - kgid_t gid = va_arg(ap, kgid_t); - __le32 val = cpu_to_le32( - from_kgid(&init_user_ns, gid)); - if (pdu_write(pdu, &val, sizeof(val))) - errcode = -EFAULT; - } break; - case 'Q':{ - const struct p9_qid *qid = - va_arg(ap, const struct p9_qid *); - errcode = - p9pdu_writef(pdu, proto_version, "bdq", - qid->type, qid->version, - qid->path); - } break; - case 'S':{ - const struct p9_wstat *stbuf = - va_arg(ap, const struct p9_wstat *); - errcode = - p9pdu_writef(pdu, proto_version, - "wwdQdddqssss?sugu", - stbuf->size, stbuf->type, - stbuf->dev, &stbuf->qid, - stbuf->mode, stbuf->atime, - stbuf->mtime, stbuf->length, - stbuf->name, stbuf->uid, - stbuf->gid, stbuf->muid, - stbuf->extension, stbuf->n_uid, - stbuf->n_gid, stbuf->n_muid); - } break; - case 'V':{ - uint32_t count = va_arg(ap, uint32_t); - struct iov_iter *from = - va_arg(ap, struct iov_iter *); - errcode = p9pdu_writef(pdu, proto_version, "d", - count); - if (!errcode && pdu_write_u(pdu, from, count)) - errcode = -EFAULT; - } - break; - case 'T':{ - uint16_t nwname = va_arg(ap, int); - const char **wnames = va_arg(ap, const char **); - - errcode = p9pdu_writef(pdu, proto_version, "w", - nwname); - if (!errcode) { - int i; - - for (i = 0; i < nwname; i++) { - errcode = - p9pdu_writef(pdu, - proto_version, - "s", - wnames[i]); - if (errcode) - break; - } - } - } - break; - case 'R':{ - uint16_t nwqid = va_arg(ap, int); - struct p9_qid *wqids = - va_arg(ap, struct p9_qid *); - - errcode = p9pdu_writef(pdu, proto_version, "w", - nwqid); - if (!errcode) { - int i; - - for (i = 0; i < nwqid; i++) { - errcode = - p9pdu_writef(pdu, - proto_version, - "Q", - &wqids[i]); - if (errcode) - break; - } - } - } - break; - case 'I':{ - struct p9_iattr_dotl *p9attr = va_arg(ap, - struct p9_iattr_dotl *); - - errcode = p9pdu_writef(pdu, proto_version, - "ddugqqqqq", - p9attr->valid, - p9attr->mode, - p9attr->uid, - p9attr->gid, - p9attr->size, - p9attr->atime_sec, - p9attr->atime_nsec, - p9attr->mtime_sec, - p9attr->mtime_nsec); - } - break; - case '?': - if ((proto_version != p9_proto_2000u) && - (proto_version != p9_proto_2000L)) - return 0; - break; - default: - BUG(); - break; - } - - if (errcode) - break; - } - - return errcode; -} - -int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = p9pdu_vreadf(pdu, proto_version, fmt, ap); - va_end(ap); - - return ret; -} - -static int -p9pdu_writef(struct p9_fcall *pdu, int proto_version, const char *fmt, ...) -{ - va_list ap; - int ret; - - va_start(ap, fmt); - ret = p9pdu_vwritef(pdu, proto_version, fmt, ap); - va_end(ap); - - return ret; -} - -int p9stat_read(struct p9_client *clnt, char *buf, int len, struct p9_wstat *st) -{ - struct p9_fcall fake_pdu; - int ret; - - fake_pdu.size = len; - fake_pdu.capacity = len; - fake_pdu.sdata = buf; - fake_pdu.offset = 0; - - ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "S", st); - if (ret) { - p9_debug(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret); - trace_9p_protocol_dump(clnt, &fake_pdu); - return ret; - } - - return fake_pdu.offset; -} -EXPORT_SYMBOL(p9stat_read); - -int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type) -{ - pdu->id = type; - return p9pdu_writef(pdu, 0, "dbw", 0, type, tag); -} - -int p9pdu_finalize(struct p9_client *clnt, struct p9_fcall *pdu) -{ - int size = pdu->size; - int err; - - pdu->size = 0; - err = p9pdu_writef(pdu, 0, "d", size); - pdu->size = size; - - trace_9p_protocol_dump(clnt, pdu); - p9_debug(P9_DEBUG_9P, ">>> size=%d type: %d tag: %d\n", - pdu->size, pdu->id, pdu->tag); - - return err; -} - -void p9pdu_reset(struct p9_fcall *pdu) -{ - pdu->offset = 0; - pdu->size = 0; -} - -int p9dirent_read(struct p9_client *clnt, char *buf, int len, - struct p9_dirent *dirent) -{ - struct p9_fcall fake_pdu; - int ret; - char *nameptr; - - fake_pdu.size = len; - fake_pdu.capacity = len; - fake_pdu.sdata = buf; - fake_pdu.offset = 0; - - ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "Qqbs", &dirent->qid, - &dirent->d_off, &dirent->d_type, &nameptr); - if (ret) { - p9_debug(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret); - trace_9p_protocol_dump(clnt, &fake_pdu); - goto out; - } - - strcpy(dirent->d_name, nameptr); - kfree(nameptr); - -out: - return fake_pdu.offset; -} -EXPORT_SYMBOL(p9dirent_read); diff --git a/addons/9p/src/4.4.180/protocol.h b/addons/9p/src/4.4.180/protocol.h deleted file mode 100644 index 2cc525fa..00000000 --- a/addons/9p/src/4.4.180/protocol.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * net/9p/protocol.h - * - * 9P Protocol Support Code - * - * Copyright (C) 2008 by Eric Van Hensbergen - * - * Base on code from Anthony Liguori - * Copyright (C) 2008 by IBM, Corp. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -int p9pdu_vwritef(struct p9_fcall *pdu, int proto_version, const char *fmt, - va_list ap); -int p9pdu_readf(struct p9_fcall *pdu, int proto_version, const char *fmt, ...); -int p9pdu_prepare(struct p9_fcall *pdu, int16_t tag, int8_t type); -int p9pdu_finalize(struct p9_client *clnt, struct p9_fcall *pdu); -void p9pdu_reset(struct p9_fcall *pdu); -size_t pdu_read(struct p9_fcall *pdu, void *data, size_t size); diff --git a/addons/9p/src/4.4.180/trans_common.c b/addons/9p/src/4.4.180/trans_common.c deleted file mode 100644 index 38aa6345..00000000 --- a/addons/9p/src/4.4.180/trans_common.c +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright IBM Corporation, 2010 - * Author Venkateswararao Jujjuri - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -#include -#include - -/** - * p9_release_req_pages - Release pages after the transaction. - */ -void p9_release_pages(struct page **pages, int nr_pages) -{ - int i; - - for (i = 0; i < nr_pages; i++) - if (pages[i]) - put_page(pages[i]); -} -EXPORT_SYMBOL(p9_release_pages); diff --git a/addons/9p/src/4.4.180/trans_common.h b/addons/9p/src/4.4.180/trans_common.h deleted file mode 100644 index c43babb3..00000000 --- a/addons/9p/src/4.4.180/trans_common.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright IBM Corporation, 2010 - * Author Venkateswararao Jujjuri - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -void p9_release_pages(struct page **, int); diff --git a/addons/9p/src/4.4.180/trans_fd.c b/addons/9p/src/4.4.180/trans_fd.c deleted file mode 100644 index 2f68ffda..00000000 --- a/addons/9p/src/4.4.180/trans_fd.c +++ /dev/null @@ -1,1122 +0,0 @@ -/* - * linux/fs/9p/trans_fd.c - * - * Fd transport layer. Includes deprecated socket layer. - * - * Copyright (C) 2006 by Russ Cox - * Copyright (C) 2004-2005 by Latchesar Ionkov - * Copyright (C) 2004-2008 by Eric Van Hensbergen - * Copyright (C) 1997-2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include /* killme */ - -#define P9_PORT 564 -#define MAX_SOCK_BUF (64*1024) -#define MAXPOLLWADDR 2 - -/** - * struct p9_fd_opts - per-transport options - * @rfd: file descriptor for reading (trans=fd) - * @wfd: file descriptor for writing (trans=fd) - * @port: port to connect to (trans=tcp) - * - */ - -struct p9_fd_opts { - int rfd; - int wfd; - u16 port; - int privport; -}; - -/* - * Option Parsing (code inspired by NFS code) - * - a little lazy - parse all fd-transport options - */ - -enum { - /* Options that take integer arguments */ - Opt_port, Opt_rfdno, Opt_wfdno, Opt_err, - /* Options that take no arguments */ - Opt_privport, -}; - -static const match_table_t tokens = { - {Opt_port, "port=%u"}, - {Opt_rfdno, "rfdno=%u"}, - {Opt_wfdno, "wfdno=%u"}, - {Opt_privport, "privport"}, - {Opt_err, NULL}, -}; - -enum { - Rworksched = 1, /* read work scheduled or running */ - Rpending = 2, /* can read */ - Wworksched = 4, /* write work scheduled or running */ - Wpending = 8, /* can write */ -}; - -struct p9_poll_wait { - struct p9_conn *conn; - wait_queue_t wait; - wait_queue_head_t *wait_addr; -}; - -/** - * struct p9_conn - fd mux connection state information - * @mux_list: list link for mux to manage multiple connections (?) - * @client: reference to client instance for this connection - * @err: error state - * @req_list: accounting for requests which have been sent - * @unsent_req_list: accounting for requests that haven't been sent - * @req: current request being processed (if any) - * @tmp_buf: temporary buffer to read in header - * @rsize: amount to read for current frame - * @rpos: read position in current frame - * @rbuf: current read buffer - * @wpos: write position for current frame - * @wsize: amount of data to write for current frame - * @wbuf: current write buffer - * @poll_pending_link: pending links to be polled per conn - * @poll_wait: array of wait_q's for various worker threads - * @pt: poll state - * @rq: current read work - * @wq: current write work - * @wsched: ???? - * - */ - -struct p9_conn { - struct list_head mux_list; - struct p9_client *client; - int err; - struct list_head req_list; - struct list_head unsent_req_list; - struct p9_req_t *req; - char tmp_buf[7]; - int rsize; - int rpos; - char *rbuf; - int wpos; - int wsize; - char *wbuf; - struct list_head poll_pending_link; - struct p9_poll_wait poll_wait[MAXPOLLWADDR]; - poll_table pt; - struct work_struct rq; - struct work_struct wq; - unsigned long wsched; -}; - -/** - * struct p9_trans_fd - transport state - * @rd: reference to file to read from - * @wr: reference of file to write to - * @conn: connection state reference - * - */ - -struct p9_trans_fd { - struct file *rd; - struct file *wr; - struct p9_conn conn; -}; - -static void p9_poll_workfn(struct work_struct *work); - -static DEFINE_SPINLOCK(p9_poll_lock); -static LIST_HEAD(p9_poll_pending_list); -static DECLARE_WORK(p9_poll_work, p9_poll_workfn); - -static unsigned int p9_ipport_resv_min = P9_DEF_MIN_RESVPORT; -static unsigned int p9_ipport_resv_max = P9_DEF_MAX_RESVPORT; - -static void p9_mux_poll_stop(struct p9_conn *m) -{ - unsigned long flags; - int i; - - for (i = 0; i < ARRAY_SIZE(m->poll_wait); i++) { - struct p9_poll_wait *pwait = &m->poll_wait[i]; - - if (pwait->wait_addr) { - remove_wait_queue(pwait->wait_addr, &pwait->wait); - pwait->wait_addr = NULL; - } - } - - spin_lock_irqsave(&p9_poll_lock, flags); - list_del_init(&m->poll_pending_link); - spin_unlock_irqrestore(&p9_poll_lock, flags); - - flush_work(&p9_poll_work); -} - -/** - * p9_conn_cancel - cancel all pending requests with error - * @m: mux data - * @err: error code - * - */ - -static void p9_conn_cancel(struct p9_conn *m, int err) -{ - struct p9_req_t *req, *rtmp; - unsigned long flags; - LIST_HEAD(cancel_list); - - p9_debug(P9_DEBUG_ERROR, "mux %p err %d\n", m, err); - - spin_lock_irqsave(&m->client->lock, flags); - - if (m->err) { - spin_unlock_irqrestore(&m->client->lock, flags); - return; - } - - m->err = err; - - list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { - list_move(&req->req_list, &cancel_list); - } - list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { - list_move(&req->req_list, &cancel_list); - } - spin_unlock_irqrestore(&m->client->lock, flags); - - list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { - p9_debug(P9_DEBUG_ERROR, "call back req %p\n", req); - list_del(&req->req_list); - if (!req->t_err) - req->t_err = err; - p9_client_cb(m->client, req, REQ_STATUS_ERROR); - } -} - -static int -p9_fd_poll(struct p9_client *client, struct poll_table_struct *pt) -{ - int ret, n; - struct p9_trans_fd *ts = NULL; - - if (client && client->status == Connected) - ts = client->trans; - - if (!ts) - return -EREMOTEIO; - - if (!ts->rd->f_op->poll) - return -EIO; - - if (!ts->wr->f_op->poll) - return -EIO; - - ret = ts->rd->f_op->poll(ts->rd, pt); - if (ret < 0) - return ret; - - if (ts->rd != ts->wr) { - n = ts->wr->f_op->poll(ts->wr, pt); - if (n < 0) - return n; - ret = (ret & ~POLLOUT) | (n & ~POLLIN); - } - - return ret; -} - -/** - * p9_fd_read- read from a fd - * @client: client instance - * @v: buffer to receive data into - * @len: size of receive buffer - * - */ - -static int p9_fd_read(struct p9_client *client, void *v, int len) -{ - int ret; - struct p9_trans_fd *ts = NULL; - - if (client && client->status != Disconnected) - ts = client->trans; - - if (!ts) - return -EREMOTEIO; - - if (!(ts->rd->f_flags & O_NONBLOCK)) - p9_debug(P9_DEBUG_ERROR, "blocking read ...\n"); - - ret = kernel_read(ts->rd, ts->rd->f_pos, v, len); - if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) - client->status = Disconnected; - return ret; -} - -/** - * p9_read_work - called when there is some data to be read from a transport - * @work: container of work to be done - * - */ - -static void p9_read_work(struct work_struct *work) -{ - int n, err; - struct p9_conn *m; - int status = REQ_STATUS_ERROR; - - m = container_of(work, struct p9_conn, rq); - - if (m->err < 0) - return; - - p9_debug(P9_DEBUG_TRANS, "start mux %p pos %d\n", m, m->rpos); - - if (!m->rbuf) { - m->rbuf = m->tmp_buf; - m->rpos = 0; - m->rsize = 7; /* start by reading header */ - } - - clear_bit(Rpending, &m->wsched); - p9_debug(P9_DEBUG_TRANS, "read mux %p pos %d size: %d = %d\n", - m, m->rpos, m->rsize, m->rsize-m->rpos); - err = p9_fd_read(m->client, m->rbuf + m->rpos, - m->rsize - m->rpos); - p9_debug(P9_DEBUG_TRANS, "mux %p got %d bytes\n", m, err); - if (err == -EAGAIN) { - goto end_clear; - } - - if (err <= 0) - goto error; - - m->rpos += err; - - if ((!m->req) && (m->rpos == m->rsize)) { /* header read in */ - u16 tag; - p9_debug(P9_DEBUG_TRANS, "got new header\n"); - - n = le32_to_cpu(*(__le32 *) m->rbuf); /* read packet size */ - if (n >= m->client->msize) { - p9_debug(P9_DEBUG_ERROR, - "requested packet size too big: %d\n", n); - err = -EIO; - goto error; - } - - tag = le16_to_cpu(*(__le16 *) (m->rbuf+5)); /* read tag */ - p9_debug(P9_DEBUG_TRANS, - "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag); - - m->req = p9_tag_lookup(m->client, tag); - if (!m->req || (m->req->status != REQ_STATUS_SENT)) { - p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", - tag); - err = -EIO; - goto error; - } - - if (m->req->rc == NULL) { - m->req->rc = kmalloc(sizeof(struct p9_fcall) + - m->client->msize, GFP_NOFS); - if (!m->req->rc) { - m->req = NULL; - err = -ENOMEM; - goto error; - } - } - m->rbuf = (char *)m->req->rc + sizeof(struct p9_fcall); - memcpy(m->rbuf, m->tmp_buf, m->rsize); - m->rsize = n; - } - - /* not an else because some packets (like clunk) have no payload */ - if ((m->req) && (m->rpos == m->rsize)) { /* packet is read in */ - p9_debug(P9_DEBUG_TRANS, "got new packet\n"); - spin_lock(&m->client->lock); - if (m->req->status != REQ_STATUS_ERROR) - status = REQ_STATUS_RCVD; - list_del(&m->req->req_list); - spin_unlock(&m->client->lock); - p9_client_cb(m->client, m->req, status); - m->rbuf = NULL; - m->rpos = 0; - m->rsize = 0; - m->req = NULL; - } - -end_clear: - clear_bit(Rworksched, &m->wsched); - - if (!list_empty(&m->req_list)) { - if (test_and_clear_bit(Rpending, &m->wsched)) - n = POLLIN; - else - n = p9_fd_poll(m->client, NULL); - - if ((n & POLLIN) && !test_and_set_bit(Rworksched, &m->wsched)) { - p9_debug(P9_DEBUG_TRANS, "sched read work %p\n", m); - schedule_work(&m->rq); - } - } - - return; -error: - p9_conn_cancel(m, err); - clear_bit(Rworksched, &m->wsched); -} - -/** - * p9_fd_write - write to a socket - * @client: client instance - * @v: buffer to send data from - * @len: size of send buffer - * - */ - -static int p9_fd_write(struct p9_client *client, void *v, int len) -{ - int ret; - mm_segment_t oldfs; - struct p9_trans_fd *ts = NULL; - - if (client && client->status != Disconnected) - ts = client->trans; - - if (!ts) - return -EREMOTEIO; - - if (!(ts->wr->f_flags & O_NONBLOCK)) - p9_debug(P9_DEBUG_ERROR, "blocking write ...\n"); - - oldfs = get_fs(); - set_fs(get_ds()); - /* The cast to a user pointer is valid due to the set_fs() */ - ret = vfs_write(ts->wr, (__force void __user *)v, len, &ts->wr->f_pos); - set_fs(oldfs); - - if (ret <= 0 && ret != -ERESTARTSYS && ret != -EAGAIN) - client->status = Disconnected; - return ret; -} - -/** - * p9_write_work - called when a transport can send some data - * @work: container for work to be done - * - */ - -static void p9_write_work(struct work_struct *work) -{ - int n, err; - struct p9_conn *m; - struct p9_req_t *req; - - m = container_of(work, struct p9_conn, wq); - - if (m->err < 0) { - clear_bit(Wworksched, &m->wsched); - return; - } - - if (!m->wsize) { - spin_lock(&m->client->lock); - if (list_empty(&m->unsent_req_list)) { - clear_bit(Wworksched, &m->wsched); - spin_unlock(&m->client->lock); - return; - } - - req = list_entry(m->unsent_req_list.next, struct p9_req_t, - req_list); - req->status = REQ_STATUS_SENT; - p9_debug(P9_DEBUG_TRANS, "move req %p\n", req); - list_move_tail(&req->req_list, &m->req_list); - - m->wbuf = req->tc->sdata; - m->wsize = req->tc->size; - m->wpos = 0; - spin_unlock(&m->client->lock); - } - - p9_debug(P9_DEBUG_TRANS, "mux %p pos %d size %d\n", - m, m->wpos, m->wsize); - clear_bit(Wpending, &m->wsched); - err = p9_fd_write(m->client, m->wbuf + m->wpos, m->wsize - m->wpos); - p9_debug(P9_DEBUG_TRANS, "mux %p sent %d bytes\n", m, err); - if (err == -EAGAIN) - goto end_clear; - - - if (err < 0) - goto error; - else if (err == 0) { - err = -EREMOTEIO; - goto error; - } - - m->wpos += err; - if (m->wpos == m->wsize) - m->wpos = m->wsize = 0; - -end_clear: - clear_bit(Wworksched, &m->wsched); - - if (m->wsize || !list_empty(&m->unsent_req_list)) { - if (test_and_clear_bit(Wpending, &m->wsched)) - n = POLLOUT; - else - n = p9_fd_poll(m->client, NULL); - - if ((n & POLLOUT) && - !test_and_set_bit(Wworksched, &m->wsched)) { - p9_debug(P9_DEBUG_TRANS, "sched write work %p\n", m); - schedule_work(&m->wq); - } - } - - return; - -error: - p9_conn_cancel(m, err); - clear_bit(Wworksched, &m->wsched); -} - -static int p9_pollwake(wait_queue_t *wait, unsigned int mode, int sync, void *key) -{ - struct p9_poll_wait *pwait = - container_of(wait, struct p9_poll_wait, wait); - struct p9_conn *m = pwait->conn; - unsigned long flags; - - spin_lock_irqsave(&p9_poll_lock, flags); - if (list_empty(&m->poll_pending_link)) - list_add_tail(&m->poll_pending_link, &p9_poll_pending_list); - spin_unlock_irqrestore(&p9_poll_lock, flags); - - schedule_work(&p9_poll_work); - return 1; -} - -/** - * p9_pollwait - add poll task to the wait queue - * @filp: file pointer being polled - * @wait_address: wait_q to block on - * @p: poll state - * - * called by files poll operation to add v9fs-poll task to files wait queue - */ - -static void -p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p) -{ - struct p9_conn *m = container_of(p, struct p9_conn, pt); - struct p9_poll_wait *pwait = NULL; - int i; - - for (i = 0; i < ARRAY_SIZE(m->poll_wait); i++) { - if (m->poll_wait[i].wait_addr == NULL) { - pwait = &m->poll_wait[i]; - break; - } - } - - if (!pwait) { - p9_debug(P9_DEBUG_ERROR, "not enough wait_address slots\n"); - return; - } - - pwait->conn = m; - pwait->wait_addr = wait_address; - init_waitqueue_func_entry(&pwait->wait, p9_pollwake); - add_wait_queue(wait_address, &pwait->wait); -} - -/** - * p9_conn_create - initialize the per-session mux data - * @client: client instance - * - * Note: Creates the polling task if this is the first session. - */ - -static void p9_conn_create(struct p9_client *client) -{ - int n; - struct p9_trans_fd *ts = client->trans; - struct p9_conn *m = &ts->conn; - - p9_debug(P9_DEBUG_TRANS, "client %p msize %d\n", client, client->msize); - - INIT_LIST_HEAD(&m->mux_list); - m->client = client; - - INIT_LIST_HEAD(&m->req_list); - INIT_LIST_HEAD(&m->unsent_req_list); - INIT_WORK(&m->rq, p9_read_work); - INIT_WORK(&m->wq, p9_write_work); - INIT_LIST_HEAD(&m->poll_pending_link); - init_poll_funcptr(&m->pt, p9_pollwait); - - n = p9_fd_poll(client, &m->pt); - if (n & POLLIN) { - p9_debug(P9_DEBUG_TRANS, "mux %p can read\n", m); - set_bit(Rpending, &m->wsched); - } - - if (n & POLLOUT) { - p9_debug(P9_DEBUG_TRANS, "mux %p can write\n", m); - set_bit(Wpending, &m->wsched); - } -} - -/** - * p9_poll_mux - polls a mux and schedules read or write works if necessary - * @m: connection to poll - * - */ - -static void p9_poll_mux(struct p9_conn *m) -{ - int n; - - if (m->err < 0) - return; - - n = p9_fd_poll(m->client, NULL); - if (n < 0 || n & (POLLERR | POLLHUP | POLLNVAL)) { - p9_debug(P9_DEBUG_TRANS, "error mux %p err %d\n", m, n); - if (n >= 0) - n = -ECONNRESET; - p9_conn_cancel(m, n); - } - - if (n & POLLIN) { - set_bit(Rpending, &m->wsched); - p9_debug(P9_DEBUG_TRANS, "mux %p can read\n", m); - if (!test_and_set_bit(Rworksched, &m->wsched)) { - p9_debug(P9_DEBUG_TRANS, "sched read work %p\n", m); - schedule_work(&m->rq); - } - } - - if (n & POLLOUT) { - set_bit(Wpending, &m->wsched); - p9_debug(P9_DEBUG_TRANS, "mux %p can write\n", m); - if ((m->wsize || !list_empty(&m->unsent_req_list)) && - !test_and_set_bit(Wworksched, &m->wsched)) { - p9_debug(P9_DEBUG_TRANS, "sched write work %p\n", m); - schedule_work(&m->wq); - } - } -} - -/** - * p9_fd_request - send 9P request - * The function can sleep until the request is scheduled for sending. - * The function can be interrupted. Return from the function is not - * a guarantee that the request is sent successfully. - * - * @client: client instance - * @req: request to be sent - * - */ - -static int p9_fd_request(struct p9_client *client, struct p9_req_t *req) -{ - int n; - struct p9_trans_fd *ts = client->trans; - struct p9_conn *m = &ts->conn; - - p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n", - m, current, req->tc, req->tc->id); - if (m->err < 0) - return m->err; - - spin_lock(&client->lock); - req->status = REQ_STATUS_UNSENT; - list_add_tail(&req->req_list, &m->unsent_req_list); - spin_unlock(&client->lock); - - if (test_and_clear_bit(Wpending, &m->wsched)) - n = POLLOUT; - else - n = p9_fd_poll(m->client, NULL); - - if (n & POLLOUT && !test_and_set_bit(Wworksched, &m->wsched)) - schedule_work(&m->wq); - - return 0; -} - -static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req) -{ - int ret = 1; - - p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req); - - spin_lock(&client->lock); - - if (req->status == REQ_STATUS_UNSENT) { - list_del(&req->req_list); - req->status = REQ_STATUS_FLSHD; - ret = 0; - } - spin_unlock(&client->lock); - - return ret; -} - -static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req) -{ - p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req); - - /* we haven't received a response for oldreq, - * remove it from the list. - */ - spin_lock(&client->lock); - list_del(&req->req_list); - spin_unlock(&client->lock); - - return 0; -} - -/** - * parse_opts - parse mount options into p9_fd_opts structure - * @params: options string passed from mount - * @opts: fd transport-specific structure to parse options into - * - * Returns 0 upon success, -ERRNO upon failure - */ - -static int parse_opts(char *params, struct p9_fd_opts *opts) -{ - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - char *options, *tmp_options; - - opts->port = P9_PORT; - opts->rfd = ~0; - opts->wfd = ~0; - opts->privport = 0; - - if (!params) - return 0; - - tmp_options = kstrdup(params, GFP_KERNEL); - if (!tmp_options) { - p9_debug(P9_DEBUG_ERROR, - "failed to allocate copy of option string\n"); - return -ENOMEM; - } - options = tmp_options; - - while ((p = strsep(&options, ",")) != NULL) { - int token; - int r; - if (!*p) - continue; - token = match_token(p, tokens, args); - if ((token != Opt_err) && (token != Opt_privport)) { - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - continue; - } - } - switch (token) { - case Opt_port: - opts->port = option; - break; - case Opt_rfdno: - opts->rfd = option; - break; - case Opt_wfdno: - opts->wfd = option; - break; - case Opt_privport: - opts->privport = 1; - break; - default: - continue; - } - } - - kfree(tmp_options); - return 0; -} - -static int p9_fd_open(struct p9_client *client, int rfd, int wfd) -{ - struct p9_trans_fd *ts = kzalloc(sizeof(struct p9_trans_fd), - GFP_KERNEL); - if (!ts) - return -ENOMEM; - - ts->rd = fget(rfd); - ts->wr = fget(wfd); - if (!ts->rd || !ts->wr) { - if (ts->rd) - fput(ts->rd); - if (ts->wr) - fput(ts->wr); - kfree(ts); - return -EIO; - } - - client->trans = ts; - client->status = Connected; - - return 0; -} - -static int p9_socket_open(struct p9_client *client, struct socket *csocket) -{ - struct p9_trans_fd *p; - struct file *file; - - p = kzalloc(sizeof(struct p9_trans_fd), GFP_KERNEL); - if (!p) - return -ENOMEM; - - csocket->sk->sk_allocation = GFP_NOIO; - file = sock_alloc_file(csocket, 0, NULL); - if (IS_ERR(file)) { - pr_err("%s (%d): failed to map fd\n", - __func__, task_pid_nr(current)); - sock_release(csocket); - kfree(p); - return PTR_ERR(file); - } - - get_file(file); - p->wr = p->rd = file; - client->trans = p; - client->status = Connected; - - p->rd->f_flags |= O_NONBLOCK; - - p9_conn_create(client); - return 0; -} - -/** - * p9_mux_destroy - cancels all pending requests of mux - * @m: mux to destroy - * - */ - -static void p9_conn_destroy(struct p9_conn *m) -{ - p9_debug(P9_DEBUG_TRANS, "mux %p prev %p next %p\n", - m, m->mux_list.prev, m->mux_list.next); - - p9_mux_poll_stop(m); - cancel_work_sync(&m->rq); - cancel_work_sync(&m->wq); - - p9_conn_cancel(m, -ECONNRESET); - - m->client = NULL; -} - -/** - * p9_fd_close - shutdown file descriptor transport - * @client: client instance - * - */ - -static void p9_fd_close(struct p9_client *client) -{ - struct p9_trans_fd *ts; - - if (!client) - return; - - ts = client->trans; - if (!ts) - return; - - client->status = Disconnected; - - p9_conn_destroy(&ts->conn); - - if (ts->rd) - fput(ts->rd); - if (ts->wr) - fput(ts->wr); - - kfree(ts); -} - -/* - * stolen from NFS - maybe should be made a generic function? - */ -static inline int valid_ipaddr4(const char *buf) -{ - int rc, count, in[4]; - - rc = sscanf(buf, "%d.%d.%d.%d", &in[0], &in[1], &in[2], &in[3]); - if (rc != 4) - return -EINVAL; - for (count = 0; count < 4; count++) { - if (in[count] > 255) - return -EINVAL; - } - return 0; -} - -static int p9_bind_privport(struct socket *sock) -{ - struct sockaddr_in cl; - int port, err = -EINVAL; - - memset(&cl, 0, sizeof(cl)); - cl.sin_family = AF_INET; - cl.sin_addr.s_addr = INADDR_ANY; - for (port = p9_ipport_resv_max; port >= p9_ipport_resv_min; port--) { - cl.sin_port = htons((ushort)port); - err = kernel_bind(sock, (struct sockaddr *)&cl, sizeof(cl)); - if (err != -EADDRINUSE) - break; - } - return err; -} - - -static int -p9_fd_create_tcp(struct p9_client *client, const char *addr, char *args) -{ - int err; - struct socket *csocket; - struct sockaddr_in sin_server; - struct p9_fd_opts opts; - - err = parse_opts(args, &opts); - if (err < 0) - return err; - - if (addr == NULL || valid_ipaddr4(addr) < 0) - return -EINVAL; - - csocket = NULL; - - sin_server.sin_family = AF_INET; - sin_server.sin_addr.s_addr = in_aton(addr); - sin_server.sin_port = htons(opts.port); - err = __sock_create(current->nsproxy->net_ns, PF_INET, - SOCK_STREAM, IPPROTO_TCP, &csocket, 1); - if (err) { - pr_err("%s (%d): problem creating socket\n", - __func__, task_pid_nr(current)); - return err; - } - - if (opts.privport) { - err = p9_bind_privport(csocket); - if (err < 0) { - pr_err("%s (%d): problem binding to privport\n", - __func__, task_pid_nr(current)); - sock_release(csocket); - return err; - } - } - - err = csocket->ops->connect(csocket, - (struct sockaddr *)&sin_server, - sizeof(struct sockaddr_in), 0); - if (err < 0) { - pr_err("%s (%d): problem connecting socket to %s\n", - __func__, task_pid_nr(current), addr); - sock_release(csocket); - return err; - } - - return p9_socket_open(client, csocket); -} - -static int -p9_fd_create_unix(struct p9_client *client, const char *addr, char *args) -{ - int err; - struct socket *csocket; - struct sockaddr_un sun_server; - - csocket = NULL; - - if (addr == NULL) - return -EINVAL; - - if (strlen(addr) >= UNIX_PATH_MAX) { - pr_err("%s (%d): address too long: %s\n", - __func__, task_pid_nr(current), addr); - return -ENAMETOOLONG; - } - - sun_server.sun_family = PF_UNIX; - strcpy(sun_server.sun_path, addr); - err = __sock_create(current->nsproxy->net_ns, PF_UNIX, - SOCK_STREAM, 0, &csocket, 1); - if (err < 0) { - pr_err("%s (%d): problem creating socket\n", - __func__, task_pid_nr(current)); - - return err; - } - err = csocket->ops->connect(csocket, (struct sockaddr *)&sun_server, - sizeof(struct sockaddr_un) - 1, 0); - if (err < 0) { - pr_err("%s (%d): problem connecting socket: %s: %d\n", - __func__, task_pid_nr(current), addr, err); - sock_release(csocket); - return err; - } - - return p9_socket_open(client, csocket); -} - -static int -p9_fd_create(struct p9_client *client, const char *addr, char *args) -{ - int err; - struct p9_fd_opts opts; - - parse_opts(args, &opts); - - if (opts.rfd == ~0 || opts.wfd == ~0) { - pr_err("Insufficient options for proto=fd\n"); - return -ENOPROTOOPT; - } - - err = p9_fd_open(client, opts.rfd, opts.wfd); - if (err < 0) - return err; - - p9_conn_create(client); - - return 0; -} - -static struct p9_trans_module p9_tcp_trans = { - .name = "tcp", - .maxsize = MAX_SOCK_BUF, - .def = 0, - .create = p9_fd_create_tcp, - .close = p9_fd_close, - .request = p9_fd_request, - .cancel = p9_fd_cancel, - .cancelled = p9_fd_cancelled, - .owner = THIS_MODULE, -}; - -static struct p9_trans_module p9_unix_trans = { - .name = "unix", - .maxsize = MAX_SOCK_BUF, - .def = 0, - .create = p9_fd_create_unix, - .close = p9_fd_close, - .request = p9_fd_request, - .cancel = p9_fd_cancel, - .cancelled = p9_fd_cancelled, - .owner = THIS_MODULE, -}; - -static struct p9_trans_module p9_fd_trans = { - .name = "fd", - .maxsize = MAX_SOCK_BUF, - .def = 0, - .create = p9_fd_create, - .close = p9_fd_close, - .request = p9_fd_request, - .cancel = p9_fd_cancel, - .cancelled = p9_fd_cancelled, - .owner = THIS_MODULE, -}; - -/** - * p9_poll_proc - poll worker thread - * @a: thread state and arguments - * - * polls all v9fs transports for new events and queues the appropriate - * work to the work queue - * - */ - -static void p9_poll_workfn(struct work_struct *work) -{ - unsigned long flags; - - p9_debug(P9_DEBUG_TRANS, "start %p\n", current); - - spin_lock_irqsave(&p9_poll_lock, flags); - while (!list_empty(&p9_poll_pending_list)) { - struct p9_conn *conn = list_first_entry(&p9_poll_pending_list, - struct p9_conn, - poll_pending_link); - list_del_init(&conn->poll_pending_link); - spin_unlock_irqrestore(&p9_poll_lock, flags); - - p9_poll_mux(conn); - - spin_lock_irqsave(&p9_poll_lock, flags); - } - spin_unlock_irqrestore(&p9_poll_lock, flags); - - p9_debug(P9_DEBUG_TRANS, "finish\n"); -} - -int p9_trans_fd_init(void) -{ - v9fs_register_trans(&p9_tcp_trans); - v9fs_register_trans(&p9_unix_trans); - v9fs_register_trans(&p9_fd_trans); - - return 0; -} - -void p9_trans_fd_exit(void) -{ - flush_work(&p9_poll_work); - v9fs_unregister_trans(&p9_tcp_trans); - v9fs_unregister_trans(&p9_unix_trans); - v9fs_unregister_trans(&p9_fd_trans); -} diff --git a/addons/9p/src/4.4.180/trans_rdma.c b/addons/9p/src/4.4.180/trans_rdma.c deleted file mode 100644 index f42550dd..00000000 --- a/addons/9p/src/4.4.180/trans_rdma.c +++ /dev/null @@ -1,784 +0,0 @@ -/* - * linux/fs/9p/trans_rdma.c - * - * RDMA transport layer based on the trans_fd.c implementation. - * - * Copyright (C) 2008 by Tom Tucker - * Copyright (C) 2006 by Russ Cox - * Copyright (C) 2004-2005 by Latchesar Ionkov - * Copyright (C) 2004-2008 by Eric Van Hensbergen - * Copyright (C) 1997-2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define P9_PORT 5640 -#define P9_RDMA_SQ_DEPTH 32 -#define P9_RDMA_RQ_DEPTH 32 -#define P9_RDMA_SEND_SGE 4 -#define P9_RDMA_RECV_SGE 4 -#define P9_RDMA_IRD 0 -#define P9_RDMA_ORD 0 -#define P9_RDMA_TIMEOUT 30000 /* 30 seconds */ -#define P9_RDMA_MAXSIZE (1024*1024) /* 1MB */ - -/** - * struct p9_trans_rdma - RDMA transport instance - * - * @state: tracks the transport state machine for connection setup and tear down - * @cm_id: The RDMA CM ID - * @pd: Protection Domain pointer - * @qp: Queue Pair pointer - * @cq: Completion Queue pointer - * @dm_mr: DMA Memory Region pointer - * @lkey: The local access only memory region key - * @timeout: Number of uSecs to wait for connection management events - * @sq_depth: The depth of the Send Queue - * @sq_sem: Semaphore for the SQ - * @rq_depth: The depth of the Receive Queue. - * @rq_sem: Semaphore for the RQ - * @excess_rc : Amount of posted Receive Contexts without a pending request. - * See rdma_request() - * @addr: The remote peer's address - * @req_lock: Protects the active request list - * @cm_done: Completion event for connection management tracking - */ -struct p9_trans_rdma { - enum { - P9_RDMA_INIT, - P9_RDMA_ADDR_RESOLVED, - P9_RDMA_ROUTE_RESOLVED, - P9_RDMA_CONNECTED, - P9_RDMA_FLUSHING, - P9_RDMA_CLOSING, - P9_RDMA_CLOSED, - } state; - struct rdma_cm_id *cm_id; - struct ib_pd *pd; - struct ib_qp *qp; - struct ib_cq *cq; - long timeout; - int sq_depth; - struct semaphore sq_sem; - int rq_depth; - struct semaphore rq_sem; - atomic_t excess_rc; - struct sockaddr_in addr; - spinlock_t req_lock; - - struct completion cm_done; -}; - -/** - * p9_rdma_context - Keeps track of in-process WR - * - * @wc_op: The original WR op for when the CQE completes in error. - * @busa: Bus address to unmap when the WR completes - * @req: Keeps track of requests (send) - * @rc: Keepts track of replies (receive) - */ -struct p9_rdma_req; -struct p9_rdma_context { - enum ib_wc_opcode wc_op; - dma_addr_t busa; - union { - struct p9_req_t *req; - struct p9_fcall *rc; - }; -}; - -/** - * p9_rdma_opts - Collection of mount options - * @port: port of connection - * @sq_depth: The requested depth of the SQ. This really doesn't need - * to be any deeper than the number of threads used in the client - * @rq_depth: The depth of the RQ. Should be greater than or equal to SQ depth - * @timeout: Time to wait in msecs for CM events - */ -struct p9_rdma_opts { - short port; - int sq_depth; - int rq_depth; - long timeout; - int privport; -}; - -/* - * Option Parsing (code inspired by NFS code) - */ -enum { - /* Options that take integer arguments */ - Opt_port, Opt_rq_depth, Opt_sq_depth, Opt_timeout, - /* Options that take no argument */ - Opt_privport, - Opt_err, -}; - -static match_table_t tokens = { - {Opt_port, "port=%u"}, - {Opt_sq_depth, "sq=%u"}, - {Opt_rq_depth, "rq=%u"}, - {Opt_timeout, "timeout=%u"}, - {Opt_privport, "privport"}, - {Opt_err, NULL}, -}; - -/** - * parse_opts - parse mount options into rdma options structure - * @params: options string passed from mount - * @opts: rdma transport-specific structure to parse options into - * - * Returns 0 upon success, -ERRNO upon failure - */ -static int parse_opts(char *params, struct p9_rdma_opts *opts) -{ - char *p; - substring_t args[MAX_OPT_ARGS]; - int option; - char *options, *tmp_options; - - opts->port = P9_PORT; - opts->sq_depth = P9_RDMA_SQ_DEPTH; - opts->rq_depth = P9_RDMA_RQ_DEPTH; - opts->timeout = P9_RDMA_TIMEOUT; - opts->privport = 0; - - if (!params) - return 0; - - tmp_options = kstrdup(params, GFP_KERNEL); - if (!tmp_options) { - p9_debug(P9_DEBUG_ERROR, - "failed to allocate copy of option string\n"); - return -ENOMEM; - } - options = tmp_options; - - while ((p = strsep(&options, ",")) != NULL) { - int token; - int r; - if (!*p) - continue; - token = match_token(p, tokens, args); - if ((token != Opt_err) && (token != Opt_privport)) { - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - continue; - } - } - switch (token) { - case Opt_port: - opts->port = option; - break; - case Opt_sq_depth: - opts->sq_depth = option; - break; - case Opt_rq_depth: - opts->rq_depth = option; - break; - case Opt_timeout: - opts->timeout = option; - break; - case Opt_privport: - opts->privport = 1; - break; - default: - continue; - } - } - /* RQ must be at least as large as the SQ */ - opts->rq_depth = max(opts->rq_depth, opts->sq_depth); - kfree(tmp_options); - return 0; -} - -static int -p9_cm_event_handler(struct rdma_cm_id *id, struct rdma_cm_event *event) -{ - struct p9_client *c = id->context; - struct p9_trans_rdma *rdma = c->trans; - switch (event->event) { - case RDMA_CM_EVENT_ADDR_RESOLVED: - BUG_ON(rdma->state != P9_RDMA_INIT); - rdma->state = P9_RDMA_ADDR_RESOLVED; - break; - - case RDMA_CM_EVENT_ROUTE_RESOLVED: - BUG_ON(rdma->state != P9_RDMA_ADDR_RESOLVED); - rdma->state = P9_RDMA_ROUTE_RESOLVED; - break; - - case RDMA_CM_EVENT_ESTABLISHED: - BUG_ON(rdma->state != P9_RDMA_ROUTE_RESOLVED); - rdma->state = P9_RDMA_CONNECTED; - break; - - case RDMA_CM_EVENT_DISCONNECTED: - if (rdma) - rdma->state = P9_RDMA_CLOSED; - if (c) - c->status = Disconnected; - break; - - case RDMA_CM_EVENT_TIMEWAIT_EXIT: - break; - - case RDMA_CM_EVENT_ADDR_CHANGE: - case RDMA_CM_EVENT_ROUTE_ERROR: - case RDMA_CM_EVENT_DEVICE_REMOVAL: - case RDMA_CM_EVENT_MULTICAST_JOIN: - case RDMA_CM_EVENT_MULTICAST_ERROR: - case RDMA_CM_EVENT_REJECTED: - case RDMA_CM_EVENT_CONNECT_REQUEST: - case RDMA_CM_EVENT_CONNECT_RESPONSE: - case RDMA_CM_EVENT_CONNECT_ERROR: - case RDMA_CM_EVENT_ADDR_ERROR: - case RDMA_CM_EVENT_UNREACHABLE: - c->status = Disconnected; - rdma_disconnect(rdma->cm_id); - break; - default: - BUG(); - } - complete(&rdma->cm_done); - return 0; -} - -static void -handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma, - struct p9_rdma_context *c, enum ib_wc_status status, u32 byte_len) -{ - struct p9_req_t *req; - int err = 0; - int16_t tag; - - req = NULL; - ib_dma_unmap_single(rdma->cm_id->device, c->busa, client->msize, - DMA_FROM_DEVICE); - - if (status != IB_WC_SUCCESS) - goto err_out; - - err = p9_parse_header(c->rc, NULL, NULL, &tag, 1); - if (err) - goto err_out; - - req = p9_tag_lookup(client, tag); - if (!req) - goto err_out; - - /* Check that we have not yet received a reply for this request. - */ - if (unlikely(req->rc)) { - pr_err("Duplicate reply for request %d", tag); - goto err_out; - } - - req->rc = c->rc; - p9_client_cb(client, req, REQ_STATUS_RCVD); - - return; - - err_out: - p9_debug(P9_DEBUG_ERROR, "req %p err %d status %d\n", req, err, status); - rdma->state = P9_RDMA_FLUSHING; - client->status = Disconnected; -} - -static void -handle_send(struct p9_client *client, struct p9_trans_rdma *rdma, - struct p9_rdma_context *c, enum ib_wc_status status, u32 byte_len) -{ - ib_dma_unmap_single(rdma->cm_id->device, - c->busa, c->req->tc->size, - DMA_TO_DEVICE); -} - -static void qp_event_handler(struct ib_event *event, void *context) -{ - p9_debug(P9_DEBUG_ERROR, "QP event %d context %p\n", - event->event, context); -} - -static void cq_comp_handler(struct ib_cq *cq, void *cq_context) -{ - struct p9_client *client = cq_context; - struct p9_trans_rdma *rdma = client->trans; - int ret; - struct ib_wc wc; - - ib_req_notify_cq(rdma->cq, IB_CQ_NEXT_COMP); - while ((ret = ib_poll_cq(cq, 1, &wc)) > 0) { - struct p9_rdma_context *c = (void *) (unsigned long) wc.wr_id; - - switch (c->wc_op) { - case IB_WC_RECV: - handle_recv(client, rdma, c, wc.status, wc.byte_len); - up(&rdma->rq_sem); - break; - - case IB_WC_SEND: - handle_send(client, rdma, c, wc.status, wc.byte_len); - up(&rdma->sq_sem); - break; - - default: - pr_err("unexpected completion type, c->wc_op=%d, wc.opcode=%d, status=%d\n", - c->wc_op, wc.opcode, wc.status); - break; - } - kfree(c); - } -} - -static void cq_event_handler(struct ib_event *e, void *v) -{ - p9_debug(P9_DEBUG_ERROR, "CQ event %d context %p\n", e->event, v); -} - -static void rdma_destroy_trans(struct p9_trans_rdma *rdma) -{ - if (!rdma) - return; - - if (rdma->qp && !IS_ERR(rdma->qp)) - ib_destroy_qp(rdma->qp); - - if (rdma->pd && !IS_ERR(rdma->pd)) - ib_dealloc_pd(rdma->pd); - - if (rdma->cq && !IS_ERR(rdma->cq)) - ib_destroy_cq(rdma->cq); - - if (rdma->cm_id && !IS_ERR(rdma->cm_id)) - rdma_destroy_id(rdma->cm_id); - - kfree(rdma); -} - -static int -post_recv(struct p9_client *client, struct p9_rdma_context *c) -{ - struct p9_trans_rdma *rdma = client->trans; - struct ib_recv_wr wr, *bad_wr; - struct ib_sge sge; - - c->busa = ib_dma_map_single(rdma->cm_id->device, - c->rc->sdata, client->msize, - DMA_FROM_DEVICE); - if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) - goto error; - - sge.addr = c->busa; - sge.length = client->msize; - sge.lkey = rdma->pd->local_dma_lkey; - - wr.next = NULL; - c->wc_op = IB_WC_RECV; - wr.wr_id = (unsigned long) c; - wr.sg_list = &sge; - wr.num_sge = 1; - return ib_post_recv(rdma->qp, &wr, &bad_wr); - - error: - p9_debug(P9_DEBUG_ERROR, "EIO\n"); - return -EIO; -} - -static int rdma_request(struct p9_client *client, struct p9_req_t *req) -{ - struct p9_trans_rdma *rdma = client->trans; - struct ib_send_wr wr, *bad_wr; - struct ib_sge sge; - int err = 0; - unsigned long flags; - struct p9_rdma_context *c = NULL; - struct p9_rdma_context *rpl_context = NULL; - - /* When an error occurs between posting the recv and the send, - * there will be a receive context posted without a pending request. - * Since there is no way to "un-post" it, we remember it and skip - * post_recv() for the next request. - * So here, - * see if we are this `next request' and need to absorb an excess rc. - * If yes, then drop and free our own, and do not recv_post(). - **/ - if (unlikely(atomic_read(&rdma->excess_rc) > 0)) { - if ((atomic_sub_return(1, &rdma->excess_rc) >= 0)) { - /* Got one ! */ - kfree(req->rc); - req->rc = NULL; - goto dont_need_post_recv; - } else { - /* We raced and lost. */ - atomic_inc(&rdma->excess_rc); - } - } - - /* Allocate an fcall for the reply */ - rpl_context = kmalloc(sizeof *rpl_context, GFP_NOFS); - if (!rpl_context) { - err = -ENOMEM; - goto recv_error; - } - rpl_context->rc = req->rc; - - /* - * Post a receive buffer for this request. We need to ensure - * there is a reply buffer available for every outstanding - * request. A flushed request can result in no reply for an - * outstanding request, so we must keep a count to avoid - * overflowing the RQ. - */ - if (down_interruptible(&rdma->rq_sem)) { - err = -EINTR; - goto recv_error; - } - - err = post_recv(client, rpl_context); - if (err) { - p9_debug(P9_DEBUG_FCALL, "POST RECV failed\n"); - goto recv_error; - } - /* remove posted receive buffer from request structure */ - req->rc = NULL; - -dont_need_post_recv: - /* Post the request */ - c = kmalloc(sizeof *c, GFP_NOFS); - if (!c) { - err = -ENOMEM; - goto send_error; - } - c->req = req; - - c->busa = ib_dma_map_single(rdma->cm_id->device, - c->req->tc->sdata, c->req->tc->size, - DMA_TO_DEVICE); - if (ib_dma_mapping_error(rdma->cm_id->device, c->busa)) { - err = -EIO; - goto send_error; - } - - sge.addr = c->busa; - sge.length = c->req->tc->size; - sge.lkey = rdma->pd->local_dma_lkey; - - wr.next = NULL; - c->wc_op = IB_WC_SEND; - wr.wr_id = (unsigned long) c; - wr.opcode = IB_WR_SEND; - wr.send_flags = IB_SEND_SIGNALED; - wr.sg_list = &sge; - wr.num_sge = 1; - - if (down_interruptible(&rdma->sq_sem)) { - err = -EINTR; - goto send_error; - } - - /* Mark request as `sent' *before* we actually send it, - * because doing if after could erase the REQ_STATUS_RCVD - * status in case of a very fast reply. - */ - req->status = REQ_STATUS_SENT; - err = ib_post_send(rdma->qp, &wr, &bad_wr); - if (err) - goto send_error; - - /* Success */ - return 0; - - /* Handle errors that happened during or while preparing the send: */ - send_error: - req->status = REQ_STATUS_ERROR; - kfree(c); - p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err); - - /* Ach. - * We did recv_post(), but not send. We have one recv_post in excess. - */ - atomic_inc(&rdma->excess_rc); - return err; - - /* Handle errors that happened during or while preparing post_recv(): */ - recv_error: - kfree(rpl_context); - spin_lock_irqsave(&rdma->req_lock, flags); - if (rdma->state < P9_RDMA_CLOSING) { - rdma->state = P9_RDMA_CLOSING; - spin_unlock_irqrestore(&rdma->req_lock, flags); - rdma_disconnect(rdma->cm_id); - } else - spin_unlock_irqrestore(&rdma->req_lock, flags); - return err; -} - -static void rdma_close(struct p9_client *client) -{ - struct p9_trans_rdma *rdma; - - if (!client) - return; - - rdma = client->trans; - if (!rdma) - return; - - client->status = Disconnected; - rdma_disconnect(rdma->cm_id); - rdma_destroy_trans(rdma); -} - -/** - * alloc_rdma - Allocate and initialize the rdma transport structure - * @opts: Mount options structure - */ -static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts) -{ - struct p9_trans_rdma *rdma; - - rdma = kzalloc(sizeof(struct p9_trans_rdma), GFP_KERNEL); - if (!rdma) - return NULL; - - rdma->sq_depth = opts->sq_depth; - rdma->rq_depth = opts->rq_depth; - rdma->timeout = opts->timeout; - spin_lock_init(&rdma->req_lock); - init_completion(&rdma->cm_done); - sema_init(&rdma->sq_sem, rdma->sq_depth); - sema_init(&rdma->rq_sem, rdma->rq_depth); - atomic_set(&rdma->excess_rc, 0); - - return rdma; -} - -static int rdma_cancel(struct p9_client *client, struct p9_req_t *req) -{ - /* Nothing to do here. - * We will take care of it (if we have to) in rdma_cancelled() - */ - return 1; -} - -/* A request has been fully flushed without a reply. - * That means we have posted one buffer in excess. - */ -static int rdma_cancelled(struct p9_client *client, struct p9_req_t *req) -{ - struct p9_trans_rdma *rdma = client->trans; - atomic_inc(&rdma->excess_rc); - return 0; -} - -static int p9_rdma_bind_privport(struct p9_trans_rdma *rdma) -{ - struct sockaddr_in cl = { - .sin_family = AF_INET, - .sin_addr.s_addr = htonl(INADDR_ANY), - }; - int port, err = -EINVAL; - - for (port = P9_DEF_MAX_RESVPORT; port >= P9_DEF_MIN_RESVPORT; port--) { - cl.sin_port = htons((ushort)port); - err = rdma_bind_addr(rdma->cm_id, (struct sockaddr *)&cl); - if (err != -EADDRINUSE) - break; - } - return err; -} - -/** - * trans_create_rdma - Transport method for creating atransport instance - * @client: client instance - * @addr: IP address string - * @args: Mount options string - */ -static int -rdma_create_trans(struct p9_client *client, const char *addr, char *args) -{ - int err; - struct p9_rdma_opts opts; - struct p9_trans_rdma *rdma; - struct rdma_conn_param conn_param; - struct ib_qp_init_attr qp_attr; - struct ib_cq_init_attr cq_attr = {}; - - if (addr == NULL) - return -EINVAL; - - /* Parse the transport specific mount options */ - err = parse_opts(args, &opts); - if (err < 0) - return err; - - /* Create and initialize the RDMA transport structure */ - rdma = alloc_rdma(&opts); - if (!rdma) - return -ENOMEM; - - /* Create the RDMA CM ID */ - rdma->cm_id = rdma_create_id(&init_net, p9_cm_event_handler, client, - RDMA_PS_TCP, IB_QPT_RC); - if (IS_ERR(rdma->cm_id)) - goto error; - - /* Associate the client with the transport */ - client->trans = rdma; - - /* Bind to a privileged port if we need to */ - if (opts.privport) { - err = p9_rdma_bind_privport(rdma); - if (err < 0) { - pr_err("%s (%d): problem binding to privport: %d\n", - __func__, task_pid_nr(current), -err); - goto error; - } - } - - /* Resolve the server's address */ - rdma->addr.sin_family = AF_INET; - rdma->addr.sin_addr.s_addr = in_aton(addr); - rdma->addr.sin_port = htons(opts.port); - err = rdma_resolve_addr(rdma->cm_id, NULL, - (struct sockaddr *)&rdma->addr, - rdma->timeout); - if (err) - goto error; - err = wait_for_completion_interruptible(&rdma->cm_done); - if (err || (rdma->state != P9_RDMA_ADDR_RESOLVED)) - goto error; - - /* Resolve the route to the server */ - err = rdma_resolve_route(rdma->cm_id, rdma->timeout); - if (err) - goto error; - err = wait_for_completion_interruptible(&rdma->cm_done); - if (err || (rdma->state != P9_RDMA_ROUTE_RESOLVED)) - goto error; - - /* Create the Completion Queue */ - cq_attr.cqe = opts.sq_depth + opts.rq_depth + 1; - rdma->cq = ib_create_cq(rdma->cm_id->device, cq_comp_handler, - cq_event_handler, client, - &cq_attr); - if (IS_ERR(rdma->cq)) - goto error; - ib_req_notify_cq(rdma->cq, IB_CQ_NEXT_COMP); - - /* Create the Protection Domain */ - rdma->pd = ib_alloc_pd(rdma->cm_id->device); - if (IS_ERR(rdma->pd)) - goto error; - - /* Create the Queue Pair */ - memset(&qp_attr, 0, sizeof qp_attr); - qp_attr.event_handler = qp_event_handler; - qp_attr.qp_context = client; - qp_attr.cap.max_send_wr = opts.sq_depth; - qp_attr.cap.max_recv_wr = opts.rq_depth; - qp_attr.cap.max_send_sge = P9_RDMA_SEND_SGE; - qp_attr.cap.max_recv_sge = P9_RDMA_RECV_SGE; - qp_attr.sq_sig_type = IB_SIGNAL_REQ_WR; - qp_attr.qp_type = IB_QPT_RC; - qp_attr.send_cq = rdma->cq; - qp_attr.recv_cq = rdma->cq; - err = rdma_create_qp(rdma->cm_id, rdma->pd, &qp_attr); - if (err) - goto error; - rdma->qp = rdma->cm_id->qp; - - /* Request a connection */ - memset(&conn_param, 0, sizeof(conn_param)); - conn_param.private_data = NULL; - conn_param.private_data_len = 0; - conn_param.responder_resources = P9_RDMA_IRD; - conn_param.initiator_depth = P9_RDMA_ORD; - err = rdma_connect(rdma->cm_id, &conn_param); - if (err) - goto error; - err = wait_for_completion_interruptible(&rdma->cm_done); - if (err || (rdma->state != P9_RDMA_CONNECTED)) - goto error; - - client->status = Connected; - - return 0; - -error: - rdma_destroy_trans(rdma); - return -ENOTCONN; -} - -static struct p9_trans_module p9_rdma_trans = { - .name = "rdma", - .maxsize = P9_RDMA_MAXSIZE, - .def = 0, - .owner = THIS_MODULE, - .create = rdma_create_trans, - .close = rdma_close, - .request = rdma_request, - .cancel = rdma_cancel, - .cancelled = rdma_cancelled, -}; - -/** - * p9_trans_rdma_init - Register the 9P RDMA transport driver - */ -static int __init p9_trans_rdma_init(void) -{ - v9fs_register_trans(&p9_rdma_trans); - return 0; -} - -static void __exit p9_trans_rdma_exit(void) -{ - v9fs_unregister_trans(&p9_rdma_trans); -} - -module_init(p9_trans_rdma_init); -module_exit(p9_trans_rdma_exit); - -MODULE_AUTHOR("Tom Tucker "); -MODULE_DESCRIPTION("RDMA Transport for 9P"); -MODULE_LICENSE("Dual BSD/GPL"); diff --git a/addons/9p/src/4.4.180/trans_virtio.c b/addons/9p/src/4.4.180/trans_virtio.c deleted file mode 100644 index 2a15b6aa..00000000 --- a/addons/9p/src/4.4.180/trans_virtio.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - * The Virtio 9p transport driver - * - * This is a block based transport driver based on the lguest block driver - * code. - * - * Copyright (C) 2007, 2008 Eric Van Hensbergen, IBM Corporation - * - * Based on virtio console driver - * Copyright (C) 2006, 2007 Rusty Russell, IBM Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "trans_common.h" - -#define VIRTQUEUE_NUM 128 - -/* a single mutex to manage channel initialization and attachment */ -static DEFINE_MUTEX(virtio_9p_lock); -static DECLARE_WAIT_QUEUE_HEAD(vp_wq); -static atomic_t vp_pinned = ATOMIC_INIT(0); - -/** - * struct virtio_chan - per-instance transport information - * @initialized: whether the channel is initialized - * @inuse: whether the channel is in use - * @lock: protects multiple elements within this structure - * @client: client instance - * @vdev: virtio dev associated with this channel - * @vq: virtio queue associated with this channel - * @sg: scatter gather list which is used to pack a request (protected?) - * - * We keep all per-channel information in a structure. - * This structure is allocated within the devices dev->mem space. - * A pointer to the structure will get put in the transport private. - * - */ - -struct virtio_chan { - bool inuse; - - spinlock_t lock; - - struct p9_client *client; - struct virtio_device *vdev; - struct virtqueue *vq; - int ring_bufs_avail; - wait_queue_head_t *vc_wq; - /* This is global limit. Since we don't have a global structure, - * will be placing it in each channel. - */ - unsigned long p9_max_pages; - /* Scatterlist: can be too big for stack. */ - struct scatterlist sg[VIRTQUEUE_NUM]; - - int tag_len; - /* - * tag name to identify a mount Non-null terminated - */ - char *tag; - - struct list_head chan_list; -}; - -static struct list_head virtio_chan_list; - -/* How many bytes left in this page. */ -static unsigned int rest_of_page(void *data) -{ - return PAGE_SIZE - ((unsigned long)data % PAGE_SIZE); -} - -/** - * p9_virtio_close - reclaim resources of a channel - * @client: client instance - * - * This reclaims a channel by freeing its resources and - * reseting its inuse flag. - * - */ - -static void p9_virtio_close(struct p9_client *client) -{ - struct virtio_chan *chan = client->trans; - - mutex_lock(&virtio_9p_lock); - if (chan) - chan->inuse = false; - mutex_unlock(&virtio_9p_lock); -} - -/** - * req_done - callback which signals activity from the server - * @vq: virtio queue activity was received on - * - * This notifies us that the server has triggered some activity - * on the virtio channel - most likely a response to request we - * sent. Figure out which requests now have responses and wake up - * those threads. - * - * Bugs: could do with some additional sanity checking, but appears to work. - * - */ - -static void req_done(struct virtqueue *vq) -{ - struct virtio_chan *chan = vq->vdev->priv; - struct p9_fcall *rc; - unsigned int len; - struct p9_req_t *req; - unsigned long flags; - - p9_debug(P9_DEBUG_TRANS, ": request done\n"); - - while (1) { - spin_lock_irqsave(&chan->lock, flags); - rc = virtqueue_get_buf(chan->vq, &len); - if (rc == NULL) { - spin_unlock_irqrestore(&chan->lock, flags); - break; - } - chan->ring_bufs_avail = 1; - spin_unlock_irqrestore(&chan->lock, flags); - /* Wakeup if anyone waiting for VirtIO ring space. */ - wake_up(chan->vc_wq); - p9_debug(P9_DEBUG_TRANS, ": rc %p\n", rc); - p9_debug(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); - req = p9_tag_lookup(chan->client, rc->tag); - p9_client_cb(chan->client, req, REQ_STATUS_RCVD); - } -} - -/** - * pack_sg_list - pack a scatter gather list from a linear buffer - * @sg: scatter/gather list to pack into - * @start: which segment of the sg_list to start at - * @limit: maximum segment to pack data to - * @data: data to pack into scatter/gather list - * @count: amount of data to pack into the scatter/gather list - * - * sg_lists have multiple segments of various sizes. This will pack - * arbitrary data into an existing scatter gather list, segmenting the - * data as necessary within constraints. - * - */ - -static int pack_sg_list(struct scatterlist *sg, int start, - int limit, char *data, int count) -{ - int s; - int index = start; - - while (count) { - s = rest_of_page(data); - if (s > count) - s = count; - BUG_ON(index >= limit); - /* Make sure we don't terminate early. */ - sg_unmark_end(&sg[index]); - sg_set_buf(&sg[index++], data, s); - count -= s; - data += s; - } - if (index-start) - sg_mark_end(&sg[index - 1]); - return index-start; -} - -/* We don't currently allow canceling of virtio requests */ -static int p9_virtio_cancel(struct p9_client *client, struct p9_req_t *req) -{ - return 1; -} - -/** - * pack_sg_list_p - Just like pack_sg_list. Instead of taking a buffer, - * this takes a list of pages. - * @sg: scatter/gather list to pack into - * @start: which segment of the sg_list to start at - * @pdata: a list of pages to add into sg. - * @nr_pages: number of pages to pack into the scatter/gather list - * @offs: amount of data in the beginning of first page _not_ to pack - * @count: amount of data to pack into the scatter/gather list - */ -static int -pack_sg_list_p(struct scatterlist *sg, int start, int limit, - struct page **pdata, int nr_pages, size_t offs, int count) -{ - int i = 0, s; - int data_off = offs; - int index = start; - - BUG_ON(nr_pages > (limit - start)); - /* - * if the first page doesn't start at - * page boundary find the offset - */ - while (nr_pages) { - s = PAGE_SIZE - data_off; - if (s > count) - s = count; - BUG_ON(index >= limit); - /* Make sure we don't terminate early. */ - sg_unmark_end(&sg[index]); - sg_set_page(&sg[index++], pdata[i++], s, data_off); - data_off = 0; - count -= s; - nr_pages--; - } - - if (index-start) - sg_mark_end(&sg[index - 1]); - return index - start; -} - -/** - * p9_virtio_request - issue a request - * @client: client instance issuing the request - * @req: request to be issued - * - */ - -static int -p9_virtio_request(struct p9_client *client, struct p9_req_t *req) -{ - int err; - int in, out, out_sgs, in_sgs; - unsigned long flags; - struct virtio_chan *chan = client->trans; - struct scatterlist *sgs[2]; - - p9_debug(P9_DEBUG_TRANS, "9p debug: virtio request\n"); - - req->status = REQ_STATUS_SENT; -req_retry: - spin_lock_irqsave(&chan->lock, flags); - - out_sgs = in_sgs = 0; - /* Handle out VirtIO ring buffers */ - out = pack_sg_list(chan->sg, 0, - VIRTQUEUE_NUM, req->tc->sdata, req->tc->size); - if (out) - sgs[out_sgs++] = chan->sg; - - in = pack_sg_list(chan->sg, out, - VIRTQUEUE_NUM, req->rc->sdata, req->rc->capacity); - if (in) - sgs[out_sgs + in_sgs++] = chan->sg + out; - - err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req->tc, - GFP_ATOMIC); - if (err < 0) { - if (err == -ENOSPC) { - chan->ring_bufs_avail = 0; - spin_unlock_irqrestore(&chan->lock, flags); - err = wait_event_killable(*chan->vc_wq, - chan->ring_bufs_avail); - if (err == -ERESTARTSYS) - return err; - - p9_debug(P9_DEBUG_TRANS, "Retry virtio request\n"); - goto req_retry; - } else { - spin_unlock_irqrestore(&chan->lock, flags); - p9_debug(P9_DEBUG_TRANS, - "virtio rpc add_sgs returned failure\n"); - return -EIO; - } - } - virtqueue_kick(chan->vq); - spin_unlock_irqrestore(&chan->lock, flags); - - p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n"); - return 0; -} - -static int p9_get_mapped_pages(struct virtio_chan *chan, - struct page ***pages, - struct iov_iter *data, - int count, - size_t *offs, - int *need_drop) -{ - int nr_pages; - int err; - - if (!iov_iter_count(data)) - return 0; - - if (!(data->type & ITER_KVEC)) { - int n; - /* - * We allow only p9_max_pages pinned. We wait for the - * Other zc request to finish here - */ - if (atomic_read(&vp_pinned) >= chan->p9_max_pages) { - err = wait_event_killable(vp_wq, - (atomic_read(&vp_pinned) < chan->p9_max_pages)); - if (err == -ERESTARTSYS) - return err; - } - n = iov_iter_get_pages_alloc(data, pages, count, offs); - if (n < 0) - return n; - *need_drop = 1; - nr_pages = DIV_ROUND_UP(n + *offs, PAGE_SIZE); - atomic_add(nr_pages, &vp_pinned); - return n; - } else { - /* kernel buffer, no need to pin pages */ - int index; - size_t len; - void *p; - - /* we'd already checked that it's non-empty */ - while (1) { - len = iov_iter_single_seg_count(data); - if (likely(len)) { - p = data->kvec->iov_base + data->iov_offset; - break; - } - iov_iter_advance(data, 0); - } - if (len > count) - len = count; - - nr_pages = DIV_ROUND_UP((unsigned long)p + len, PAGE_SIZE) - - (unsigned long)p / PAGE_SIZE; - - *pages = kmalloc(sizeof(struct page *) * nr_pages, GFP_NOFS); - if (!*pages) - return -ENOMEM; - - *need_drop = 0; - p -= (*offs = (unsigned long)p % PAGE_SIZE); - for (index = 0; index < nr_pages; index++) { - if (is_vmalloc_addr(p)) - (*pages)[index] = vmalloc_to_page(p); - else - (*pages)[index] = kmap_to_page(p); - p += PAGE_SIZE; - } - return len; - } -} - -/** - * p9_virtio_zc_request - issue a zero copy request - * @client: client instance issuing the request - * @req: request to be issued - * @uidata: user bffer that should be ued for zero copy read - * @uodata: user buffer that shoud be user for zero copy write - * @inlen: read buffer size - * @olen: write buffer size - * @hdrlen: reader header size, This is the size of response protocol data - * - */ -static int -p9_virtio_zc_request(struct p9_client *client, struct p9_req_t *req, - struct iov_iter *uidata, struct iov_iter *uodata, - int inlen, int outlen, int in_hdr_len) -{ - int in, out, err, out_sgs, in_sgs; - unsigned long flags; - int in_nr_pages = 0, out_nr_pages = 0; - struct page **in_pages = NULL, **out_pages = NULL; - struct virtio_chan *chan = client->trans; - struct scatterlist *sgs[4]; - size_t offs; - int need_drop = 0; - - p9_debug(P9_DEBUG_TRANS, "virtio request\n"); - - if (uodata) { - __le32 sz; - int n = p9_get_mapped_pages(chan, &out_pages, uodata, - outlen, &offs, &need_drop); - if (n < 0) - return n; - out_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE); - if (n != outlen) { - __le32 v = cpu_to_le32(n); - memcpy(&req->tc->sdata[req->tc->size - 4], &v, 4); - outlen = n; - } - /* The size field of the message must include the length of the - * header and the length of the data. We didn't actually know - * the length of the data until this point so add it in now. - */ - sz = cpu_to_le32(req->tc->size + outlen); - memcpy(&req->tc->sdata[0], &sz, sizeof(sz)); - } else if (uidata) { - int n = p9_get_mapped_pages(chan, &in_pages, uidata, - inlen, &offs, &need_drop); - if (n < 0) - return n; - in_nr_pages = DIV_ROUND_UP(n + offs, PAGE_SIZE); - if (n != inlen) { - __le32 v = cpu_to_le32(n); - memcpy(&req->tc->sdata[req->tc->size - 4], &v, 4); - inlen = n; - } - } - req->status = REQ_STATUS_SENT; -req_retry_pinned: - spin_lock_irqsave(&chan->lock, flags); - - out_sgs = in_sgs = 0; - - /* out data */ - out = pack_sg_list(chan->sg, 0, - VIRTQUEUE_NUM, req->tc->sdata, req->tc->size); - - if (out) - sgs[out_sgs++] = chan->sg; - - if (out_pages) { - sgs[out_sgs++] = chan->sg + out; - out += pack_sg_list_p(chan->sg, out, VIRTQUEUE_NUM, - out_pages, out_nr_pages, offs, outlen); - } - - /* - * Take care of in data - * For example TREAD have 11. - * 11 is the read/write header = PDU Header(7) + IO Size (4). - * Arrange in such a way that server places header in the - * alloced memory and payload onto the user buffer. - */ - in = pack_sg_list(chan->sg, out, - VIRTQUEUE_NUM, req->rc->sdata, in_hdr_len); - if (in) - sgs[out_sgs + in_sgs++] = chan->sg + out; - - if (in_pages) { - sgs[out_sgs + in_sgs++] = chan->sg + out + in; - in += pack_sg_list_p(chan->sg, out + in, VIRTQUEUE_NUM, - in_pages, in_nr_pages, offs, inlen); - } - - BUG_ON(out_sgs + in_sgs > ARRAY_SIZE(sgs)); - err = virtqueue_add_sgs(chan->vq, sgs, out_sgs, in_sgs, req->tc, - GFP_ATOMIC); - if (err < 0) { - if (err == -ENOSPC) { - chan->ring_bufs_avail = 0; - spin_unlock_irqrestore(&chan->lock, flags); - err = wait_event_killable(*chan->vc_wq, - chan->ring_bufs_avail); - if (err == -ERESTARTSYS) - goto err_out; - - p9_debug(P9_DEBUG_TRANS, "Retry virtio request\n"); - goto req_retry_pinned; - } else { - spin_unlock_irqrestore(&chan->lock, flags); - p9_debug(P9_DEBUG_TRANS, - "virtio rpc add_sgs returned failure\n"); - err = -EIO; - goto err_out; - } - } - virtqueue_kick(chan->vq); - spin_unlock_irqrestore(&chan->lock, flags); - p9_debug(P9_DEBUG_TRANS, "virtio request kicked\n"); - err = wait_event_killable(*req->wq, req->status >= REQ_STATUS_RCVD); - /* - * Non kernel buffers are pinned, unpin them - */ -err_out: - if (need_drop) { - if (in_pages) { - p9_release_pages(in_pages, in_nr_pages); - atomic_sub(in_nr_pages, &vp_pinned); - } - if (out_pages) { - p9_release_pages(out_pages, out_nr_pages); - atomic_sub(out_nr_pages, &vp_pinned); - } - /* wakeup anybody waiting for slots to pin pages */ - wake_up(&vp_wq); - } - kfree(in_pages); - kfree(out_pages); - return err; -} - -static ssize_t p9_mount_tag_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct virtio_chan *chan; - struct virtio_device *vdev; - - vdev = dev_to_virtio(dev); - chan = vdev->priv; - - memcpy(buf, chan->tag, chan->tag_len); - buf[chan->tag_len] = 0; - - return chan->tag_len + 1; -} - -static DEVICE_ATTR(mount_tag, 0444, p9_mount_tag_show, NULL); - -/** - * p9_virtio_probe - probe for existence of 9P virtio channels - * @vdev: virtio device to probe - * - * This probes for existing virtio channels. - * - */ - -static int p9_virtio_probe(struct virtio_device *vdev) -{ - __u16 tag_len; - char *tag; - int err; - struct virtio_chan *chan; - - if (!vdev->config->get) { - dev_err(&vdev->dev, "%s failure: config access disabled\n", - __func__); - return -EINVAL; - } - - chan = kmalloc(sizeof(struct virtio_chan), GFP_KERNEL); - if (!chan) { - pr_err("Failed to allocate virtio 9P channel\n"); - err = -ENOMEM; - goto fail; - } - - chan->vdev = vdev; - - /* We expect one virtqueue, for requests. */ - chan->vq = virtio_find_single_vq(vdev, req_done, "requests"); - if (IS_ERR(chan->vq)) { - err = PTR_ERR(chan->vq); - goto out_free_chan; - } - chan->vq->vdev->priv = chan; - spin_lock_init(&chan->lock); - - sg_init_table(chan->sg, VIRTQUEUE_NUM); - - chan->inuse = false; - if (virtio_has_feature(vdev, VIRTIO_9P_MOUNT_TAG)) { - virtio_cread(vdev, struct virtio_9p_config, tag_len, &tag_len); - } else { - err = -EINVAL; - goto out_free_vq; - } - tag = kmalloc(tag_len, GFP_KERNEL); - if (!tag) { - err = -ENOMEM; - goto out_free_vq; - } - - virtio_cread_bytes(vdev, offsetof(struct virtio_9p_config, tag), - tag, tag_len); - chan->tag = tag; - chan->tag_len = tag_len; - err = sysfs_create_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); - if (err) { - goto out_free_tag; - } - chan->vc_wq = kmalloc(sizeof(wait_queue_head_t), GFP_KERNEL); - if (!chan->vc_wq) { - err = -ENOMEM; - goto out_free_tag; - } - init_waitqueue_head(chan->vc_wq); - chan->ring_bufs_avail = 1; - /* Ceiling limit to avoid denial of service attacks */ - chan->p9_max_pages = nr_free_buffer_pages()/4; - - virtio_device_ready(vdev); - - mutex_lock(&virtio_9p_lock); - list_add_tail(&chan->chan_list, &virtio_chan_list); - mutex_unlock(&virtio_9p_lock); - - /* Let udev rules use the new mount_tag attribute. */ - kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); - - return 0; - -out_free_tag: - kfree(tag); -out_free_vq: - vdev->config->del_vqs(vdev); -out_free_chan: - kfree(chan); -fail: - return err; -} - - -/** - * p9_virtio_create - allocate a new virtio channel - * @client: client instance invoking this transport - * @devname: string identifying the channel to connect to (unused) - * @args: args passed from sys_mount() for per-transport options (unused) - * - * This sets up a transport channel for 9p communication. Right now - * we only match the first available channel, but eventually we couldlook up - * alternate channels by matching devname versus a virtio_config entry. - * We use a simple reference count mechanism to ensure that only a single - * mount has a channel open at a time. - * - */ - -static int -p9_virtio_create(struct p9_client *client, const char *devname, char *args) -{ - struct virtio_chan *chan; - int ret = -ENOENT; - int found = 0; - - if (devname == NULL) - return -EINVAL; - - mutex_lock(&virtio_9p_lock); - list_for_each_entry(chan, &virtio_chan_list, chan_list) { - if (!strncmp(devname, chan->tag, chan->tag_len) && - strlen(devname) == chan->tag_len) { - if (!chan->inuse) { - chan->inuse = true; - found = 1; - break; - } - ret = -EBUSY; - } - } - mutex_unlock(&virtio_9p_lock); - - if (!found) { - pr_err("no channels available\n"); - return ret; - } - - client->trans = (void *)chan; - client->status = Connected; - chan->client = client; - - return 0; -} - -/** - * p9_virtio_remove - clean up resources associated with a virtio device - * @vdev: virtio device to remove - * - */ - -static void p9_virtio_remove(struct virtio_device *vdev) -{ - struct virtio_chan *chan = vdev->priv; - unsigned long warning_time; - - mutex_lock(&virtio_9p_lock); - - /* Remove self from list so we don't get new users. */ - list_del(&chan->chan_list); - warning_time = jiffies; - - /* Wait for existing users to close. */ - while (chan->inuse) { - mutex_unlock(&virtio_9p_lock); - msleep(250); - if (time_after(jiffies, warning_time + 10 * HZ)) { - dev_emerg(&vdev->dev, - "p9_virtio_remove: waiting for device in use.\n"); - warning_time = jiffies; - } - mutex_lock(&virtio_9p_lock); - } - - mutex_unlock(&virtio_9p_lock); - - vdev->config->reset(vdev); - vdev->config->del_vqs(vdev); - - sysfs_remove_file(&(vdev->dev.kobj), &dev_attr_mount_tag.attr); - kobject_uevent(&(vdev->dev.kobj), KOBJ_CHANGE); - kfree(chan->tag); - kfree(chan->vc_wq); - kfree(chan); - -} - -static struct virtio_device_id id_table[] = { - { VIRTIO_ID_9P, VIRTIO_DEV_ANY_ID }, - { 0 }, -}; - -static unsigned int features[] = { - VIRTIO_9P_MOUNT_TAG, -}; - -/* The standard "struct lguest_driver": */ -static struct virtio_driver p9_virtio_drv = { - .feature_table = features, - .feature_table_size = ARRAY_SIZE(features), - .driver.name = KBUILD_MODNAME, - .driver.owner = THIS_MODULE, - .id_table = id_table, - .probe = p9_virtio_probe, - .remove = p9_virtio_remove, -}; - -static struct p9_trans_module p9_virtio_trans = { - .name = "virtio", - .create = p9_virtio_create, - .close = p9_virtio_close, - .request = p9_virtio_request, - .zc_request = p9_virtio_zc_request, - .cancel = p9_virtio_cancel, - /* - * We leave one entry for input and one entry for response - * headers. We also skip one more entry to accomodate, address - * that are not at page boundary, that can result in an extra - * page in zero copy. - */ - .maxsize = PAGE_SIZE * (VIRTQUEUE_NUM - 3), - .def = 1, - .owner = THIS_MODULE, -}; - -/* The standard init function */ -static int __init p9_virtio_init(void) -{ - INIT_LIST_HEAD(&virtio_chan_list); - - v9fs_register_trans(&p9_virtio_trans); - return register_virtio_driver(&p9_virtio_drv); -} - -static void __exit p9_virtio_cleanup(void) -{ - unregister_virtio_driver(&p9_virtio_drv); - v9fs_unregister_trans(&p9_virtio_trans); -} - -module_init(p9_virtio_init); -module_exit(p9_virtio_cleanup); - -MODULE_DEVICE_TABLE(virtio, id_table); -MODULE_AUTHOR("Eric Van Hensbergen "); -MODULE_DESCRIPTION("Virtio 9p Transport"); -MODULE_LICENSE("GPL"); diff --git a/addons/9p/src/4.4.180/util.c b/addons/9p/src/4.4.180/util.c deleted file mode 100644 index 59f278e6..00000000 --- a/addons/9p/src/4.4.180/util.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * net/9p/util.c - * - * This file contains some helper functions - * - * Copyright (C) 2007 by Latchesar Ionkov - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * struct p9_idpool - per-connection accounting for tag idpool - * @lock: protects the pool - * @pool: idr to allocate tag id from - * - */ - -struct p9_idpool { - spinlock_t lock; - struct idr pool; -}; - -/** - * p9_idpool_create - create a new per-connection id pool - * - */ - -struct p9_idpool *p9_idpool_create(void) -{ - struct p9_idpool *p; - - p = kmalloc(sizeof(struct p9_idpool), GFP_KERNEL); - if (!p) - return ERR_PTR(-ENOMEM); - - spin_lock_init(&p->lock); - idr_init(&p->pool); - - return p; -} -EXPORT_SYMBOL(p9_idpool_create); - -/** - * p9_idpool_destroy - create a new per-connection id pool - * @p: idpool to destroy - */ - -void p9_idpool_destroy(struct p9_idpool *p) -{ - idr_destroy(&p->pool); - kfree(p); -} -EXPORT_SYMBOL(p9_idpool_destroy); - -/** - * p9_idpool_get - allocate numeric id from pool - * @p: pool to allocate from - * - * Bugs: This seems to be an awful generic function, should it be in idr.c with - * the lock included in struct idr? - */ - -int p9_idpool_get(struct p9_idpool *p) -{ - int i; - unsigned long flags; - - idr_preload(GFP_NOFS); - spin_lock_irqsave(&p->lock, flags); - - /* no need to store exactly p, we just need something non-null */ - i = idr_alloc(&p->pool, p, 0, 0, GFP_NOWAIT); - - spin_unlock_irqrestore(&p->lock, flags); - idr_preload_end(); - if (i < 0) - return -1; - - p9_debug(P9_DEBUG_MUX, " id %d pool %p\n", i, p); - return i; -} -EXPORT_SYMBOL(p9_idpool_get); - -/** - * p9_idpool_put - release numeric id from pool - * @id: numeric id which is being released - * @p: pool to release id into - * - * Bugs: This seems to be an awful generic function, should it be in idr.c with - * the lock included in struct idr? - */ - -void p9_idpool_put(int id, struct p9_idpool *p) -{ - unsigned long flags; - - p9_debug(P9_DEBUG_MUX, " id %d pool %p\n", id, p); - - spin_lock_irqsave(&p->lock, flags); - idr_remove(&p->pool, id); - spin_unlock_irqrestore(&p->lock, flags); -} -EXPORT_SYMBOL(p9_idpool_put); - -/** - * p9_idpool_check - check if the specified id is available - * @id: id to check - * @p: pool to check - */ - -int p9_idpool_check(int id, struct p9_idpool *p) -{ - return idr_find(&p->pool, id) != NULL; -} -EXPORT_SYMBOL(p9_idpool_check); - diff --git a/addons/9p/src/4.4.180/v9fs.c b/addons/9p/src/4.4.180/v9fs.c deleted file mode 100644 index 1e9bb8db..00000000 --- a/addons/9p/src/4.4.180/v9fs.c +++ /dev/null @@ -1,700 +0,0 @@ -/* - * linux/fs/9p/v9fs.c - * - * This file contains functions assisting in mapping VFS to 9P2000 - * - * Copyright (C) 2004-2008 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "cache.h" - -static DEFINE_SPINLOCK(v9fs_sessionlist_lock); -static LIST_HEAD(v9fs_sessionlist); -struct kmem_cache *v9fs_inode_cache; - -/* - * Option Parsing (code inspired by NFS code) - * NOTE: each transport will parse its own options - */ - -enum { - /* Options that take integer arguments */ - Opt_debug, Opt_dfltuid, Opt_dfltgid, Opt_afid, - /* String options */ - Opt_uname, Opt_remotename, Opt_cache, Opt_cachetag, - /* Options that take no arguments */ - Opt_nodevmap, - /* Cache options */ - Opt_cache_loose, Opt_fscache, Opt_mmap, - /* Access options */ - Opt_access, Opt_posixacl, - /* Lock timeout option */ - Opt_locktimeout, - /* Error token */ - Opt_err -}; - -static const match_table_t tokens = { - {Opt_debug, "debug=%x"}, - {Opt_dfltuid, "dfltuid=%u"}, - {Opt_dfltgid, "dfltgid=%u"}, - {Opt_afid, "afid=%u"}, - {Opt_uname, "uname=%s"}, - {Opt_remotename, "aname=%s"}, - {Opt_nodevmap, "nodevmap"}, - {Opt_cache, "cache=%s"}, - {Opt_cache_loose, "loose"}, - {Opt_fscache, "fscache"}, - {Opt_mmap, "mmap"}, - {Opt_cachetag, "cachetag=%s"}, - {Opt_access, "access=%s"}, - {Opt_posixacl, "posixacl"}, - {Opt_locktimeout, "locktimeout=%u"}, - {Opt_err, NULL} -}; - -/* Interpret mount options for cache mode */ -static int get_cache_mode(char *s) -{ - int version = -EINVAL; - - if (!strcmp(s, "loose")) { - version = CACHE_LOOSE; - p9_debug(P9_DEBUG_9P, "Cache mode: loose\n"); - } else if (!strcmp(s, "fscache")) { - version = CACHE_FSCACHE; - p9_debug(P9_DEBUG_9P, "Cache mode: fscache\n"); - } else if (!strcmp(s, "mmap")) { - version = CACHE_MMAP; - p9_debug(P9_DEBUG_9P, "Cache mode: mmap\n"); - } else if (!strcmp(s, "none")) { - version = CACHE_NONE; - p9_debug(P9_DEBUG_9P, "Cache mode: none\n"); - } else - pr_info("Unknown Cache mode %s\n", s); - return version; -} - -/** - * v9fs_parse_options - parse mount options into session structure - * @v9ses: existing v9fs session information - * - * Return 0 upon success, -ERRNO upon failure. - */ - -static int v9fs_parse_options(struct v9fs_session_info *v9ses, char *opts) -{ - char *options, *tmp_options; - substring_t args[MAX_OPT_ARGS]; - char *p; - int option = 0; - char *s, *e; - int ret = 0; - - /* setup defaults */ - v9ses->afid = ~0; - v9ses->debug = 0; - v9ses->cache = CACHE_NONE; -#ifdef CONFIG_9P_FSCACHE - v9ses->cachetag = NULL; -#endif - v9ses->session_lock_timeout = P9_LOCK_TIMEOUT; - - if (!opts) - return 0; - - tmp_options = kstrdup(opts, GFP_KERNEL); - if (!tmp_options) { - ret = -ENOMEM; - goto fail_option_alloc; - } - options = tmp_options; - - while ((p = strsep(&options, ",")) != NULL) { - int token, r; - if (!*p) - continue; - token = match_token(p, tokens, args); - switch (token) { - case Opt_debug: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - v9ses->debug = option; -#ifdef CONFIG_NET_9P_DEBUG - p9_debug_level = option; -#endif - break; - - case Opt_dfltuid: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - v9ses->dfltuid = make_kuid(current_user_ns(), option); - if (!uid_valid(v9ses->dfltuid)) { - p9_debug(P9_DEBUG_ERROR, - "uid field, but not a uid?\n"); - ret = -EINVAL; - continue; - } - break; - case Opt_dfltgid: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - v9ses->dfltgid = make_kgid(current_user_ns(), option); - if (!gid_valid(v9ses->dfltgid)) { - p9_debug(P9_DEBUG_ERROR, - "gid field, but not a gid?\n"); - ret = -EINVAL; - continue; - } - break; - case Opt_afid: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - v9ses->afid = option; - break; - case Opt_uname: - kfree(v9ses->uname); - v9ses->uname = match_strdup(&args[0]); - if (!v9ses->uname) { - ret = -ENOMEM; - goto free_and_return; - } - break; - case Opt_remotename: - kfree(v9ses->aname); - v9ses->aname = match_strdup(&args[0]); - if (!v9ses->aname) { - ret = -ENOMEM; - goto free_and_return; - } - break; - case Opt_nodevmap: - v9ses->nodev = 1; - break; - case Opt_cache_loose: - v9ses->cache = CACHE_LOOSE; - break; - case Opt_fscache: - v9ses->cache = CACHE_FSCACHE; - break; - case Opt_mmap: - v9ses->cache = CACHE_MMAP; - break; - case Opt_cachetag: -#ifdef CONFIG_9P_FSCACHE - v9ses->cachetag = match_strdup(&args[0]); -#endif - break; - case Opt_cache: - s = match_strdup(&args[0]); - if (!s) { - ret = -ENOMEM; - p9_debug(P9_DEBUG_ERROR, - "problem allocating copy of cache arg\n"); - goto free_and_return; - } - ret = get_cache_mode(s); - if (ret == -EINVAL) { - kfree(s); - goto free_and_return; - } - - v9ses->cache = ret; - kfree(s); - break; - - case Opt_access: - s = match_strdup(&args[0]); - if (!s) { - ret = -ENOMEM; - p9_debug(P9_DEBUG_ERROR, - "problem allocating copy of access arg\n"); - goto free_and_return; - } - - v9ses->flags &= ~V9FS_ACCESS_MASK; - if (strcmp(s, "user") == 0) - v9ses->flags |= V9FS_ACCESS_USER; - else if (strcmp(s, "any") == 0) - v9ses->flags |= V9FS_ACCESS_ANY; - else if (strcmp(s, "client") == 0) { - v9ses->flags |= V9FS_ACCESS_CLIENT; - } else { - uid_t uid; - v9ses->flags |= V9FS_ACCESS_SINGLE; - uid = simple_strtoul(s, &e, 10); - if (*e != '\0') { - ret = -EINVAL; - pr_info("Unknown access argument %s\n", - s); - kfree(s); - goto free_and_return; - } - v9ses->uid = make_kuid(current_user_ns(), uid); - if (!uid_valid(v9ses->uid)) { - ret = -EINVAL; - pr_info("Uknown uid %s\n", s); - kfree(s); - goto free_and_return; - } - } - - kfree(s); - break; - - case Opt_posixacl: -#ifdef CONFIG_9P_FS_POSIX_ACL - v9ses->flags |= V9FS_POSIX_ACL; -#else - p9_debug(P9_DEBUG_ERROR, - "Not defined CONFIG_9P_FS_POSIX_ACL. Ignoring posixacl option\n"); -#endif - break; - - case Opt_locktimeout: - r = match_int(&args[0], &option); - if (r < 0) { - p9_debug(P9_DEBUG_ERROR, - "integer field, but no integer?\n"); - ret = r; - continue; - } - if (option < 1) { - p9_debug(P9_DEBUG_ERROR, - "locktimeout must be a greater than zero integer.\n"); - ret = -EINVAL; - continue; - } - v9ses->session_lock_timeout = (long)option * HZ; - break; - - default: - continue; - } - } - -free_and_return: - kfree(tmp_options); -fail_option_alloc: - return ret; -} - -/** - * v9fs_session_init - initialize session - * @v9ses: session information structure - * @dev_name: device being mounted - * @data: options - * - */ - -struct p9_fid *v9fs_session_init(struct v9fs_session_info *v9ses, - const char *dev_name, char *data) -{ - struct p9_fid *fid; - int rc = -ENOMEM; - - v9ses->uname = kstrdup(V9FS_DEFUSER, GFP_KERNEL); - if (!v9ses->uname) - goto err_names; - - v9ses->aname = kstrdup(V9FS_DEFANAME, GFP_KERNEL); - if (!v9ses->aname) - goto err_names; - init_rwsem(&v9ses->rename_sem); - - rc = bdi_setup_and_register(&v9ses->bdi, "9p"); - if (rc) - goto err_names; - - v9ses->uid = INVALID_UID; - v9ses->dfltuid = V9FS_DEFUID; - v9ses->dfltgid = V9FS_DEFGID; - - v9ses->clnt = p9_client_create(dev_name, data); - if (IS_ERR(v9ses->clnt)) { - rc = PTR_ERR(v9ses->clnt); - p9_debug(P9_DEBUG_ERROR, "problem initializing 9p client\n"); - goto err_bdi; - } - - v9ses->flags = V9FS_ACCESS_USER; - - if (p9_is_proto_dotl(v9ses->clnt)) { - v9ses->flags = V9FS_ACCESS_CLIENT; - v9ses->flags |= V9FS_PROTO_2000L; - } else if (p9_is_proto_dotu(v9ses->clnt)) { - v9ses->flags |= V9FS_PROTO_2000U; - } - - rc = v9fs_parse_options(v9ses, data); - if (rc < 0) - goto err_clnt; - - v9ses->maxdata = v9ses->clnt->msize - P9_IOHDRSZ; - - if (!v9fs_proto_dotl(v9ses) && - ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) { - /* - * We support ACCESS_CLIENT only for dotl. - * Fall back to ACCESS_USER - */ - v9ses->flags &= ~V9FS_ACCESS_MASK; - v9ses->flags |= V9FS_ACCESS_USER; - } - /*FIXME !! */ - /* for legacy mode, fall back to V9FS_ACCESS_ANY */ - if (!(v9fs_proto_dotu(v9ses) || v9fs_proto_dotl(v9ses)) && - ((v9ses->flags&V9FS_ACCESS_MASK) == V9FS_ACCESS_USER)) { - - v9ses->flags &= ~V9FS_ACCESS_MASK; - v9ses->flags |= V9FS_ACCESS_ANY; - v9ses->uid = INVALID_UID; - } - if (!v9fs_proto_dotl(v9ses) || - !((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_CLIENT)) { - /* - * We support ACL checks on clinet only if the protocol is - * 9P2000.L and access is V9FS_ACCESS_CLIENT. - */ - v9ses->flags &= ~V9FS_ACL_MASK; - } - - fid = p9_client_attach(v9ses->clnt, NULL, v9ses->uname, INVALID_UID, - v9ses->aname); - if (IS_ERR(fid)) { - rc = PTR_ERR(fid); - p9_debug(P9_DEBUG_ERROR, "cannot attach\n"); - goto err_clnt; - } - - if ((v9ses->flags & V9FS_ACCESS_MASK) == V9FS_ACCESS_SINGLE) - fid->uid = v9ses->uid; - else - fid->uid = INVALID_UID; - -#ifdef CONFIG_9P_FSCACHE - /* register the session for caching */ - v9fs_cache_session_get_cookie(v9ses); -#endif - spin_lock(&v9fs_sessionlist_lock); - list_add(&v9ses->slist, &v9fs_sessionlist); - spin_unlock(&v9fs_sessionlist_lock); - - return fid; - -err_clnt: - p9_client_destroy(v9ses->clnt); -err_bdi: - bdi_destroy(&v9ses->bdi); -err_names: - kfree(v9ses->uname); - kfree(v9ses->aname); - return ERR_PTR(rc); -} - -/** - * v9fs_session_close - shutdown a session - * @v9ses: session information structure - * - */ - -void v9fs_session_close(struct v9fs_session_info *v9ses) -{ - if (v9ses->clnt) { - p9_client_destroy(v9ses->clnt); - v9ses->clnt = NULL; - } - -#ifdef CONFIG_9P_FSCACHE - if (v9ses->fscache) { - v9fs_cache_session_put_cookie(v9ses); - kfree(v9ses->cachetag); - } -#endif - kfree(v9ses->uname); - kfree(v9ses->aname); - - bdi_destroy(&v9ses->bdi); - - spin_lock(&v9fs_sessionlist_lock); - list_del(&v9ses->slist); - spin_unlock(&v9fs_sessionlist_lock); -} - -/** - * v9fs_session_cancel - terminate a session - * @v9ses: session to terminate - * - * mark transport as disconnected and cancel all pending requests. - */ - -void v9fs_session_cancel(struct v9fs_session_info *v9ses) { - p9_debug(P9_DEBUG_ERROR, "cancel session %p\n", v9ses); - p9_client_disconnect(v9ses->clnt); -} - -/** - * v9fs_session_begin_cancel - Begin terminate of a session - * @v9ses: session to terminate - * - * After this call we don't allow any request other than clunk. - */ - -void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses) -{ - p9_debug(P9_DEBUG_ERROR, "begin cancel session %p\n", v9ses); - p9_client_begin_disconnect(v9ses->clnt); -} - -extern int v9fs_error_init(void); - -static struct kobject *v9fs_kobj; - -#ifdef CONFIG_9P_FSCACHE -/** - * caches_show - list caches associated with a session - * - * Returns the size of buffer written. - */ - -static ssize_t caches_show(struct kobject *kobj, - struct kobj_attribute *attr, - char *buf) -{ - ssize_t n = 0, count = 0, limit = PAGE_SIZE; - struct v9fs_session_info *v9ses; - - spin_lock(&v9fs_sessionlist_lock); - list_for_each_entry(v9ses, &v9fs_sessionlist, slist) { - if (v9ses->cachetag) { - n = snprintf(buf, limit, "%s\n", v9ses->cachetag); - if (n < 0) { - count = n; - break; - } - - count += n; - limit -= n; - } - } - - spin_unlock(&v9fs_sessionlist_lock); - return count; -} - -static struct kobj_attribute v9fs_attr_cache = __ATTR_RO(caches); -#endif /* CONFIG_9P_FSCACHE */ - -static struct attribute *v9fs_attrs[] = { -#ifdef CONFIG_9P_FSCACHE - &v9fs_attr_cache.attr, -#endif - NULL, -}; - -static struct attribute_group v9fs_attr_group = { - .attrs = v9fs_attrs, -}; - -/** - * v9fs_sysfs_init - Initialize the v9fs sysfs interface - * - */ - -static int __init v9fs_sysfs_init(void) -{ - v9fs_kobj = kobject_create_and_add("9p", fs_kobj); - if (!v9fs_kobj) - return -ENOMEM; - - if (sysfs_create_group(v9fs_kobj, &v9fs_attr_group)) { - kobject_put(v9fs_kobj); - return -ENOMEM; - } - - return 0; -} - -/** - * v9fs_sysfs_cleanup - Unregister the v9fs sysfs interface - * - */ - -static void v9fs_sysfs_cleanup(void) -{ - sysfs_remove_group(v9fs_kobj, &v9fs_attr_group); - kobject_put(v9fs_kobj); -} - -static void v9fs_inode_init_once(void *foo) -{ - struct v9fs_inode *v9inode = (struct v9fs_inode *)foo; -#ifdef CONFIG_9P_FSCACHE - v9inode->fscache = NULL; -#endif - memset(&v9inode->qid, 0, sizeof(v9inode->qid)); - inode_init_once(&v9inode->vfs_inode); -} - -/** - * v9fs_init_inode_cache - initialize a cache for 9P - * Returns 0 on success. - */ -static int v9fs_init_inode_cache(void) -{ - v9fs_inode_cache = kmem_cache_create("v9fs_inode_cache", - sizeof(struct v9fs_inode), - 0, (SLAB_RECLAIM_ACCOUNT| - SLAB_MEM_SPREAD), - v9fs_inode_init_once); - if (!v9fs_inode_cache) - return -ENOMEM; - - return 0; -} - -/** - * v9fs_destroy_inode_cache - destroy the cache of 9P inode - * - */ -static void v9fs_destroy_inode_cache(void) -{ - /* - * Make sure all delayed rcu free inodes are flushed before we - * destroy cache. - */ - rcu_barrier(); - kmem_cache_destroy(v9fs_inode_cache); -} - -static int v9fs_cache_register(void) -{ - int ret; - ret = v9fs_init_inode_cache(); - if (ret < 0) - return ret; -#ifdef CONFIG_9P_FSCACHE - ret = fscache_register_netfs(&v9fs_cache_netfs); - if (ret < 0) - v9fs_destroy_inode_cache(); -#endif - return ret; -} - -static void v9fs_cache_unregister(void) -{ - v9fs_destroy_inode_cache(); -#ifdef CONFIG_9P_FSCACHE - fscache_unregister_netfs(&v9fs_cache_netfs); -#endif -} - -/** - * init_v9fs - Initialize module - * - */ - -static int __init init_v9fs(void) -{ - int err; - pr_info("Installing v9fs 9p2000 file system support\n"); - /* TODO: Setup list of registered trasnport modules */ - - err = v9fs_cache_register(); - if (err < 0) { - pr_err("Failed to register v9fs for caching\n"); - return err; - } - - err = v9fs_sysfs_init(); - if (err < 0) { - pr_err("Failed to register with sysfs\n"); - goto out_cache; - } - err = register_filesystem(&v9fs_fs_type); - if (err < 0) { - pr_err("Failed to register filesystem\n"); - goto out_sysfs_cleanup; - } - - return 0; - -out_sysfs_cleanup: - v9fs_sysfs_cleanup(); - -out_cache: - v9fs_cache_unregister(); - - return err; -} - -/** - * exit_v9fs - shutdown module - * - */ - -static void __exit exit_v9fs(void) -{ - v9fs_sysfs_cleanup(); - v9fs_cache_unregister(); - unregister_filesystem(&v9fs_fs_type); -} - -module_init(init_v9fs) -module_exit(exit_v9fs) - -MODULE_AUTHOR("Latchesar Ionkov "); -MODULE_AUTHOR("Eric Van Hensbergen "); -MODULE_AUTHOR("Ron Minnich "); -MODULE_LICENSE("GPL"); diff --git a/addons/9p/src/4.4.180/v9fs.h b/addons/9p/src/4.4.180/v9fs.h deleted file mode 100644 index 3775f275..00000000 --- a/addons/9p/src/4.4.180/v9fs.h +++ /dev/null @@ -1,226 +0,0 @@ -/* - * V9FS definitions. - * - * Copyright (C) 2004-2008 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ -#ifndef FS_9P_V9FS_H -#define FS_9P_V9FS_H - -#include - -/** - * enum p9_session_flags - option flags for each 9P session - * @V9FS_PROTO_2000U: whether or not to use 9P2000.u extensions - * @V9FS_PROTO_2000L: whether or not to use 9P2000.l extensions - * @V9FS_ACCESS_SINGLE: only the mounting user can access the hierarchy - * @V9FS_ACCESS_USER: a new attach will be issued for every user (default) - * @V9FS_ACCESS_CLIENT: Just like user, but access check is performed on client. - * @V9FS_ACCESS_ANY: use a single attach for all users - * @V9FS_ACCESS_MASK: bit mask of different ACCESS options - * @V9FS_POSIX_ACL: POSIX ACLs are enforced - * - * Session flags reflect options selected by users at mount time - */ -#define V9FS_ACCESS_ANY (V9FS_ACCESS_SINGLE | \ - V9FS_ACCESS_USER | \ - V9FS_ACCESS_CLIENT) -#define V9FS_ACCESS_MASK V9FS_ACCESS_ANY -#define V9FS_ACL_MASK V9FS_POSIX_ACL - -enum p9_session_flags { - V9FS_PROTO_2000U = 0x01, - V9FS_PROTO_2000L = 0x02, - V9FS_ACCESS_SINGLE = 0x04, - V9FS_ACCESS_USER = 0x08, - V9FS_ACCESS_CLIENT = 0x10, - V9FS_POSIX_ACL = 0x20 -}; - -/* possible values of ->cache */ -/** - * enum p9_cache_modes - user specified cache preferences - * @CACHE_NONE: do not cache data, dentries, or directory contents (default) - * @CACHE_LOOSE: cache data, dentries, and directory contents w/no consistency - * - * eventually support loose, tight, time, session, default always none - */ - -enum p9_cache_modes { - CACHE_NONE, - CACHE_MMAP, - CACHE_LOOSE, - CACHE_FSCACHE, -}; - -/** - * struct v9fs_session_info - per-instance session information - * @flags: session options of type &p9_session_flags - * @nodev: set to 1 to disable device mapping - * @debug: debug level - * @afid: authentication handle - * @cache: cache mode of type &p9_cache_modes - * @cachetag: the tag of the cache associated with this session - * @fscache: session cookie associated with FS-Cache - * @uname: string user name to mount hierarchy as - * @aname: mount specifier for remote hierarchy - * @maxdata: maximum data to be sent/recvd per protocol message - * @dfltuid: default numeric userid to mount hierarchy as - * @dfltgid: default numeric groupid to mount hierarchy as - * @uid: if %V9FS_ACCESS_SINGLE, the numeric uid which mounted the hierarchy - * @clnt: reference to 9P network client instantiated for this session - * @slist: reference to list of registered 9p sessions - * - * This structure holds state for each session instance established during - * a sys_mount() . - * - * Bugs: there seems to be a lot of state which could be condensed and/or - * removed. - */ - -struct v9fs_session_info { - /* options */ - unsigned char flags; - unsigned char nodev; - unsigned short debug; - unsigned int afid; - unsigned int cache; -#ifdef CONFIG_9P_FSCACHE - char *cachetag; - struct fscache_cookie *fscache; -#endif - - char *uname; /* user name to mount as */ - char *aname; /* name of remote hierarchy being mounted */ - unsigned int maxdata; /* max data for client interface */ - kuid_t dfltuid; /* default uid/muid for legacy support */ - kgid_t dfltgid; /* default gid for legacy support */ - kuid_t uid; /* if ACCESS_SINGLE, the uid that has access */ - struct p9_client *clnt; /* 9p client */ - struct list_head slist; /* list of sessions registered with v9fs */ - struct backing_dev_info bdi; - struct rw_semaphore rename_sem; - long session_lock_timeout; /* retry interval for blocking locks */ -}; - -/* cache_validity flags */ -#define V9FS_INO_INVALID_ATTR 0x01 - -struct v9fs_inode { -#ifdef CONFIG_9P_FSCACHE - struct mutex fscache_lock; - struct fscache_cookie *fscache; -#endif - struct p9_qid qid; - unsigned int cache_validity; - struct p9_fid *writeback_fid; - struct mutex v_mutex; - struct inode vfs_inode; -}; - -static inline struct v9fs_inode *V9FS_I(const struct inode *inode) -{ - return container_of(inode, struct v9fs_inode, vfs_inode); -} - -struct p9_fid *v9fs_session_init(struct v9fs_session_info *, const char *, - char *); -extern void v9fs_session_close(struct v9fs_session_info *v9ses); -extern void v9fs_session_cancel(struct v9fs_session_info *v9ses); -extern void v9fs_session_begin_cancel(struct v9fs_session_info *v9ses); -extern struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, - unsigned int flags); -extern int v9fs_vfs_unlink(struct inode *i, struct dentry *d); -extern int v9fs_vfs_rmdir(struct inode *i, struct dentry *d); -extern int v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry); -extern struct inode *v9fs_inode_from_fid(struct v9fs_session_info *v9ses, - struct p9_fid *fid, - struct super_block *sb, int new); -extern const struct inode_operations v9fs_dir_inode_operations_dotl; -extern const struct inode_operations v9fs_file_inode_operations_dotl; -extern const struct inode_operations v9fs_symlink_inode_operations_dotl; -extern struct inode *v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, - struct p9_fid *fid, - struct super_block *sb, int new); - -/* other default globals */ -#define V9FS_PORT 564 -#define V9FS_DEFUSER "nobody" -#define V9FS_DEFANAME "" -#define V9FS_DEFUID KUIDT_INIT(-2) -#define V9FS_DEFGID KGIDT_INIT(-2) - -static inline struct v9fs_session_info *v9fs_inode2v9ses(struct inode *inode) -{ - return (inode->i_sb->s_fs_info); -} - -static inline struct v9fs_session_info *v9fs_dentry2v9ses(struct dentry *dentry) -{ - return dentry->d_sb->s_fs_info; -} - -static inline int v9fs_proto_dotu(struct v9fs_session_info *v9ses) -{ - return v9ses->flags & V9FS_PROTO_2000U; -} - -static inline int v9fs_proto_dotl(struct v9fs_session_info *v9ses) -{ - return v9ses->flags & V9FS_PROTO_2000L; -} - -/** - * v9fs_get_inode_from_fid - Helper routine to populate an inode by - * issuing a attribute request - * @v9ses: session information - * @fid: fid to issue attribute request for - * @sb: superblock on which to create inode - * - */ -static inline struct inode * -v9fs_get_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, - struct super_block *sb) -{ - if (v9fs_proto_dotl(v9ses)) - return v9fs_inode_from_fid_dotl(v9ses, fid, sb, 0); - else - return v9fs_inode_from_fid(v9ses, fid, sb, 0); -} - -/** - * v9fs_get_new_inode_from_fid - Helper routine to populate an inode by - * issuing a attribute request - * @v9ses: session information - * @fid: fid to issue attribute request for - * @sb: superblock on which to create inode - * - */ -static inline struct inode * -v9fs_get_new_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, - struct super_block *sb) -{ - if (v9fs_proto_dotl(v9ses)) - return v9fs_inode_from_fid_dotl(v9ses, fid, sb, 1); - else - return v9fs_inode_from_fid(v9ses, fid, sb, 1); -} - -#endif diff --git a/addons/9p/src/4.4.180/v9fs_vfs.h b/addons/9p/src/4.4.180/v9fs_vfs.h deleted file mode 100644 index aaee1e65..00000000 --- a/addons/9p/src/4.4.180/v9fs_vfs.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * V9FS VFS extensions. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ -#ifndef FS_9P_V9FS_VFS_H -#define FS_9P_V9FS_VFS_H - -/* plan9 semantics are that created files are implicitly opened. - * But linux semantics are that you call create, then open. - * the plan9 approach is superior as it provides an atomic - * open. - * we track the create fid here. When the file is opened, if fidopen is - * non-zero, we use the fid and can skip some steps. - * there may be a better way to do this, but I don't know it. - * one BAD way is to clunk the fid on create, then open it again: - * you lose the atomicity of file open - */ - -/* special case: - * unlink calls remove, which is an implicit clunk. So we have to track - * that kind of thing so that we don't try to clunk a dead fid. - */ -#define P9_LOCK_TIMEOUT (30*HZ) - -/* flags for v9fs_stat2inode() & v9fs_stat2inode_dotl() */ -#define V9FS_STAT2INODE_KEEP_ISIZE 1 - -extern struct file_system_type v9fs_fs_type; -extern const struct address_space_operations v9fs_addr_operations; -extern const struct file_operations v9fs_file_operations; -extern const struct file_operations v9fs_file_operations_dotl; -extern const struct file_operations v9fs_dir_operations; -extern const struct file_operations v9fs_dir_operations_dotl; -extern const struct dentry_operations v9fs_dentry_operations; -extern const struct dentry_operations v9fs_cached_dentry_operations; -extern const struct file_operations v9fs_cached_file_operations; -extern const struct file_operations v9fs_cached_file_operations_dotl; -extern const struct file_operations v9fs_mmap_file_operations; -extern const struct file_operations v9fs_mmap_file_operations_dotl; -extern struct kmem_cache *v9fs_inode_cache; - -struct inode *v9fs_alloc_inode(struct super_block *sb); -void v9fs_destroy_inode(struct inode *inode); -struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, dev_t); -int v9fs_init_inode(struct v9fs_session_info *v9ses, - struct inode *inode, umode_t mode, dev_t); -void v9fs_evict_inode(struct inode *inode); -ino_t v9fs_qid2ino(struct p9_qid *qid); -void v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, - struct super_block *sb, unsigned int flags); -void v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode, - unsigned int flags); -int v9fs_dir_release(struct inode *inode, struct file *filp); -int v9fs_file_open(struct inode *inode, struct file *file); -void v9fs_inode2stat(struct inode *inode, struct p9_wstat *stat); -int v9fs_uflags2omode(int uflags, int extended); - -void v9fs_blank_wstat(struct p9_wstat *wstat); -int v9fs_vfs_setattr_dotl(struct dentry *, struct iattr *); -int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end, - int datasync); -int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode); -int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode); -static inline void v9fs_invalidate_inode_attr(struct inode *inode) -{ - struct v9fs_inode *v9inode; - v9inode = V9FS_I(inode); - v9inode->cache_validity |= V9FS_INO_INVALID_ATTR; - return; -} - -int v9fs_open_to_dotl_flags(int flags); - -static inline void v9fs_i_size_write(struct inode *inode, loff_t i_size) -{ - /* - * 32-bit need the lock, concurrent updates could break the - * sequences and make i_size_read() loop forever. - * 64-bit updates are atomic and can skip the locking. - */ - if (sizeof(i_size) > sizeof(long)) - spin_lock(&inode->i_lock); - i_size_write(inode, i_size); - if (sizeof(i_size) > sizeof(long)) - spin_unlock(&inode->i_lock); -} -#endif diff --git a/addons/9p/src/4.4.180/vfs_addr.c b/addons/9p/src/4.4.180/vfs_addr.c deleted file mode 100644 index e9e04376..00000000 --- a/addons/9p/src/4.4.180/vfs_addr.c +++ /dev/null @@ -1,351 +0,0 @@ -/* - * linux/fs/9p/vfs_addr.c - * - * This file contians vfs address (mmap) ops for 9P2000. - * - * Copyright (C) 2005 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "cache.h" -#include "fid.h" - -/** - * v9fs_fid_readpage - read an entire page in from 9P - * - * @fid: fid being read - * @page: structure to page - * - */ -static int v9fs_fid_readpage(struct p9_fid *fid, struct page *page) -{ - struct inode *inode = page->mapping->host; - struct bio_vec bvec = {.bv_page = page, .bv_len = PAGE_SIZE}; - struct iov_iter to; - int retval, err; - - p9_debug(P9_DEBUG_VFS, "\n"); - - BUG_ON(!PageLocked(page)); - - retval = v9fs_readpage_from_fscache(inode, page); - if (retval == 0) - return retval; - - iov_iter_bvec(&to, ITER_BVEC | READ, &bvec, 1, PAGE_SIZE); - - retval = p9_client_read(fid, page_offset(page), &to, &err); - if (err) { - v9fs_uncache_page(inode, page); - retval = err; - goto done; - } - - zero_user(page, retval, PAGE_SIZE - retval); - flush_dcache_page(page); - SetPageUptodate(page); - - v9fs_readpage_to_fscache(inode, page); - retval = 0; - -done: - unlock_page(page); - return retval; -} - -/** - * v9fs_vfs_readpage - read an entire page in from 9P - * - * @filp: file being read - * @page: structure to page - * - */ - -static int v9fs_vfs_readpage(struct file *filp, struct page *page) -{ - return v9fs_fid_readpage(filp->private_data, page); -} - -/** - * v9fs_vfs_readpages - read a set of pages from 9P - * - * @filp: file being read - * @mapping: the address space - * @pages: list of pages to read - * @nr_pages: count of pages to read - * - */ - -static int v9fs_vfs_readpages(struct file *filp, struct address_space *mapping, - struct list_head *pages, unsigned nr_pages) -{ - int ret = 0; - struct inode *inode; - - inode = mapping->host; - p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, filp); - - ret = v9fs_readpages_from_fscache(inode, mapping, pages, &nr_pages); - if (ret == 0) - return ret; - - ret = read_cache_pages(mapping, pages, (void *)v9fs_vfs_readpage, filp); - p9_debug(P9_DEBUG_VFS, " = %d\n", ret); - return ret; -} - -/** - * v9fs_release_page - release the private state associated with a page - * - * Returns 1 if the page can be released, false otherwise. - */ - -static int v9fs_release_page(struct page *page, gfp_t gfp) -{ - if (PagePrivate(page)) - return 0; - return v9fs_fscache_release_page(page, gfp); -} - -/** - * v9fs_invalidate_page - Invalidate a page completely or partially - * - * @page: structure to page - * @offset: offset in the page - */ - -static void v9fs_invalidate_page(struct page *page, unsigned int offset, - unsigned int length) -{ - /* - * If called with zero offset, we should release - * the private state assocated with the page - */ - if (offset == 0 && length == PAGE_CACHE_SIZE) - v9fs_fscache_invalidate_page(page); -} - -static int v9fs_vfs_writepage_locked(struct page *page) -{ - struct inode *inode = page->mapping->host; - struct v9fs_inode *v9inode = V9FS_I(inode); - loff_t size = i_size_read(inode); - struct iov_iter from; - struct bio_vec bvec; - int err, len; - - if (page->index == size >> PAGE_CACHE_SHIFT) - len = size & ~PAGE_CACHE_MASK; - else - len = PAGE_CACHE_SIZE; - - bvec.bv_page = page; - bvec.bv_offset = 0; - bvec.bv_len = len; - iov_iter_bvec(&from, ITER_BVEC | WRITE, &bvec, 1, len); - - /* We should have writeback_fid always set */ - BUG_ON(!v9inode->writeback_fid); - - set_page_writeback(page); - - p9_client_write(v9inode->writeback_fid, page_offset(page), &from, &err); - - end_page_writeback(page); - return err; -} - -static int v9fs_vfs_writepage(struct page *page, struct writeback_control *wbc) -{ - int retval; - - p9_debug(P9_DEBUG_VFS, "page %p\n", page); - - retval = v9fs_vfs_writepage_locked(page); - if (retval < 0) { - if (retval == -EAGAIN) { - redirty_page_for_writepage(wbc, page); - retval = 0; - } else { - SetPageError(page); - mapping_set_error(page->mapping, retval); - } - } else - retval = 0; - - unlock_page(page); - return retval; -} - -/** - * v9fs_launder_page - Writeback a dirty page - * Returns 0 on success. - */ - -static int v9fs_launder_page(struct page *page) -{ - int retval; - struct inode *inode = page->mapping->host; - - v9fs_fscache_wait_on_page_write(inode, page); - if (clear_page_dirty_for_io(page)) { - retval = v9fs_vfs_writepage_locked(page); - if (retval) - return retval; - } - return 0; -} - -/** - * v9fs_direct_IO - 9P address space operation for direct I/O - * @iocb: target I/O control block - * @pos: offset in file to begin the operation - * - * The presence of v9fs_direct_IO() in the address space ops vector - * allowes open() O_DIRECT flags which would have failed otherwise. - * - * In the non-cached mode, we shunt off direct read and write requests before - * the VFS gets them, so this method should never be called. - * - * Direct IO is not 'yet' supported in the cached mode. Hence when - * this routine is called through generic_file_aio_read(), the read/write fails - * with an error. - * - */ -static ssize_t -v9fs_direct_IO(struct kiocb *iocb, struct iov_iter *iter, loff_t pos) -{ - struct file *file = iocb->ki_filp; - ssize_t n; - int err = 0; - if (iov_iter_rw(iter) == WRITE) { - n = p9_client_write(file->private_data, pos, iter, &err); - if (n) { - struct inode *inode = file_inode(file); - loff_t i_size = i_size_read(inode); - if (pos + n > i_size) - inode_add_bytes(inode, pos + n - i_size); - } - } else { - n = p9_client_read(file->private_data, pos, iter, &err); - } - return n ? n : err; -} - -static int v9fs_write_begin(struct file *filp, struct address_space *mapping, - loff_t pos, unsigned len, unsigned flags, - struct page **pagep, void **fsdata) -{ - int retval = 0; - struct page *page; - struct v9fs_inode *v9inode; - pgoff_t index = pos >> PAGE_CACHE_SHIFT; - struct inode *inode = mapping->host; - - - p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping); - - v9inode = V9FS_I(inode); -start: - page = grab_cache_page_write_begin(mapping, index, flags); - if (!page) { - retval = -ENOMEM; - goto out; - } - BUG_ON(!v9inode->writeback_fid); - if (PageUptodate(page)) - goto out; - - if (len == PAGE_CACHE_SIZE) - goto out; - - retval = v9fs_fid_readpage(v9inode->writeback_fid, page); - page_cache_release(page); - if (!retval) - goto start; -out: - *pagep = page; - return retval; -} - -static int v9fs_write_end(struct file *filp, struct address_space *mapping, - loff_t pos, unsigned len, unsigned copied, - struct page *page, void *fsdata) -{ - loff_t last_pos = pos + copied; - struct inode *inode = page->mapping->host; - - p9_debug(P9_DEBUG_VFS, "filp %p, mapping %p\n", filp, mapping); - - if (unlikely(copied < len)) { - /* - * zero out the rest of the area - */ - unsigned from = pos & (PAGE_CACHE_SIZE - 1); - - zero_user(page, from + copied, len - copied); - flush_dcache_page(page); - } - - if (!PageUptodate(page)) - SetPageUptodate(page); - /* - * No need to use i_size_read() here, the i_size - * cannot change under us because we hold the i_mutex. - */ - if (last_pos > inode->i_size) { - inode_add_bytes(inode, last_pos - inode->i_size); - i_size_write(inode, last_pos); - } - set_page_dirty(page); - unlock_page(page); - page_cache_release(page); - - return copied; -} - - -const struct address_space_operations v9fs_addr_operations = { - .readpage = v9fs_vfs_readpage, - .readpages = v9fs_vfs_readpages, - .set_page_dirty = __set_page_dirty_nobuffers, - .writepage = v9fs_vfs_writepage, - .write_begin = v9fs_write_begin, - .write_end = v9fs_write_end, - .releasepage = v9fs_release_page, - .invalidatepage = v9fs_invalidate_page, - .launder_page = v9fs_launder_page, - .direct_IO = v9fs_direct_IO, -}; diff --git a/addons/9p/src/4.4.180/vfs_dentry.c b/addons/9p/src/4.4.180/vfs_dentry.c deleted file mode 100644 index bd456c66..00000000 --- a/addons/9p/src/4.4.180/vfs_dentry.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * linux/fs/9p/vfs_dentry.c - * - * This file contians vfs dentry ops for the 9P2000 protocol. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" - -/** - * v9fs_cached_dentry_delete - called when dentry refcount equals 0 - * @dentry: dentry in question - * - */ -static int v9fs_cached_dentry_delete(const struct dentry *dentry) -{ - p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n", - dentry, dentry); - - /* Don't cache negative dentries */ - if (d_really_is_negative(dentry)) - return 1; - return 0; -} - -/** - * v9fs_dentry_release - called when dentry is going to be freed - * @dentry: dentry that is being release - * - */ - -static void v9fs_dentry_release(struct dentry *dentry) -{ - struct hlist_node *p, *n; - p9_debug(P9_DEBUG_VFS, " dentry: %pd (%p)\n", - dentry, dentry); - hlist_for_each_safe(p, n, (struct hlist_head *)&dentry->d_fsdata) - p9_client_clunk(hlist_entry(p, struct p9_fid, dlist)); - dentry->d_fsdata = NULL; -} - -static int v9fs_lookup_revalidate(struct dentry *dentry, unsigned int flags) -{ - struct p9_fid *fid; - struct inode *inode; - struct v9fs_inode *v9inode; - - if (flags & LOOKUP_RCU) - return -ECHILD; - - inode = d_inode(dentry); - if (!inode) - goto out_valid; - - v9inode = V9FS_I(inode); - if (v9inode->cache_validity & V9FS_INO_INVALID_ATTR) { - int retval; - struct v9fs_session_info *v9ses; - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - v9ses = v9fs_inode2v9ses(inode); - if (v9fs_proto_dotl(v9ses)) - retval = v9fs_refresh_inode_dotl(fid, inode); - else - retval = v9fs_refresh_inode(fid, inode); - if (retval == -ENOENT) - return 0; - if (retval < 0) - return retval; - } -out_valid: - return 1; -} - -const struct dentry_operations v9fs_cached_dentry_operations = { - .d_revalidate = v9fs_lookup_revalidate, - .d_weak_revalidate = v9fs_lookup_revalidate, - .d_delete = v9fs_cached_dentry_delete, - .d_release = v9fs_dentry_release, -}; - -const struct dentry_operations v9fs_dentry_operations = { - .d_delete = always_delete_dentry, - .d_release = v9fs_dentry_release, -}; diff --git a/addons/9p/src/4.4.180/vfs_dir.c b/addons/9p/src/4.4.180/vfs_dir.c deleted file mode 100644 index 05769219..00000000 --- a/addons/9p/src/4.4.180/vfs_dir.c +++ /dev/null @@ -1,248 +0,0 @@ -/* - * linux/fs/9p/vfs_dir.c - * - * This file contains vfs directory ops for the 9P2000 protocol. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" - -/** - * struct p9_rdir - readdir accounting - * @head: start offset of current dirread buffer - * @tail: end offset of current dirread buffer - * @buf: dirread buffer - * - * private structure for keeping track of readdir - * allocated on demand - */ - -struct p9_rdir { - int head; - int tail; - uint8_t buf[]; -}; - -/** - * dt_type - return file type - * @mistat: mistat structure - * - */ - -static inline int dt_type(struct p9_wstat *mistat) -{ - unsigned long perm = mistat->mode; - int rettype = DT_REG; - - if (perm & P9_DMDIR) - rettype = DT_DIR; - if (perm & P9_DMSYMLINK) - rettype = DT_LNK; - - return rettype; -} - -/** - * v9fs_alloc_rdir_buf - Allocate buffer used for read and readdir - * @filp: opened file structure - * @buflen: Length in bytes of buffer to allocate - * - */ - -static struct p9_rdir *v9fs_alloc_rdir_buf(struct file *filp, int buflen) -{ - struct p9_fid *fid = filp->private_data; - if (!fid->rdir) - fid->rdir = kzalloc(sizeof(struct p9_rdir) + buflen, GFP_KERNEL); - return fid->rdir; -} - -/** - * v9fs_dir_readdir - iterate through a directory - * @file: opened file structure - * @ctx: actor we feed the entries to - * - */ - -static int v9fs_dir_readdir(struct file *file, struct dir_context *ctx) -{ - bool over; - struct p9_wstat st; - int err = 0; - struct p9_fid *fid; - int buflen; - struct p9_rdir *rdir; - struct kvec kvec; - - p9_debug(P9_DEBUG_VFS, "name %pD\n", file); - fid = file->private_data; - - buflen = fid->clnt->msize - P9_IOHDRSZ; - - rdir = v9fs_alloc_rdir_buf(file, buflen); - if (!rdir) - return -ENOMEM; - kvec.iov_base = rdir->buf; - kvec.iov_len = buflen; - - while (1) { - if (rdir->tail == rdir->head) { - struct iov_iter to; - int n; - iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buflen); - n = p9_client_read(file->private_data, ctx->pos, &to, - &err); - if (err) - return err; - if (n == 0) - return 0; - - rdir->head = 0; - rdir->tail = n; - } - while (rdir->head < rdir->tail) { - err = p9stat_read(fid->clnt, rdir->buf + rdir->head, - rdir->tail - rdir->head, &st); - if (err <= 0) { - p9_debug(P9_DEBUG_VFS, "returned %d\n", err); - return -EIO; - } - - over = !dir_emit(ctx, st.name, strlen(st.name), - v9fs_qid2ino(&st.qid), dt_type(&st)); - p9stat_free(&st); - if (over) - return 0; - - rdir->head += err; - ctx->pos += err; - } - } -} - -/** - * v9fs_dir_readdir_dotl - iterate through a directory - * @file: opened file structure - * @ctx: actor we feed the entries to - * - */ -static int v9fs_dir_readdir_dotl(struct file *file, struct dir_context *ctx) -{ - int err = 0; - struct p9_fid *fid; - int buflen; - struct p9_rdir *rdir; - struct p9_dirent curdirent; - - p9_debug(P9_DEBUG_VFS, "name %pD\n", file); - fid = file->private_data; - - buflen = fid->clnt->msize - P9_READDIRHDRSZ; - - rdir = v9fs_alloc_rdir_buf(file, buflen); - if (!rdir) - return -ENOMEM; - - while (1) { - if (rdir->tail == rdir->head) { - err = p9_client_readdir(fid, rdir->buf, buflen, - ctx->pos); - if (err <= 0) - return err; - - rdir->head = 0; - rdir->tail = err; - } - - while (rdir->head < rdir->tail) { - - err = p9dirent_read(fid->clnt, rdir->buf + rdir->head, - rdir->tail - rdir->head, - &curdirent); - if (err < 0) { - p9_debug(P9_DEBUG_VFS, "returned %d\n", err); - return -EIO; - } - - if (!dir_emit(ctx, curdirent.d_name, - strlen(curdirent.d_name), - v9fs_qid2ino(&curdirent.qid), - curdirent.d_type)) - return 0; - - ctx->pos = curdirent.d_off; - rdir->head += err; - } - } -} - - -/** - * v9fs_dir_release - close a directory - * @inode: inode of the directory - * @filp: file pointer to a directory - * - */ - -int v9fs_dir_release(struct inode *inode, struct file *filp) -{ - struct p9_fid *fid; - - fid = filp->private_data; - p9_debug(P9_DEBUG_VFS, "inode: %p filp: %p fid: %d\n", - inode, filp, fid ? fid->fid : -1); - if (fid) - p9_client_clunk(fid); - return 0; -} - -const struct file_operations v9fs_dir_operations = { - .read = generic_read_dir, - .llseek = generic_file_llseek, - .iterate = v9fs_dir_readdir, - .open = v9fs_file_open, - .release = v9fs_dir_release, -}; - -const struct file_operations v9fs_dir_operations_dotl = { - .read = generic_read_dir, - .llseek = generic_file_llseek, - .iterate = v9fs_dir_readdir_dotl, - .open = v9fs_file_open, - .release = v9fs_dir_release, - .fsync = v9fs_file_fsync_dotl, -}; diff --git a/addons/9p/src/4.4.180/vfs_file.c b/addons/9p/src/4.4.180/vfs_file.c deleted file mode 100644 index 373cc505..00000000 --- a/addons/9p/src/4.4.180/vfs_file.c +++ /dev/null @@ -1,726 +0,0 @@ -/* - * linux/fs/9p/vfs_file.c - * - * This file contians vfs file ops for 9P2000. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" -#include "cache.h" - -static const struct vm_operations_struct v9fs_file_vm_ops; -static const struct vm_operations_struct v9fs_mmap_file_vm_ops; - -/** - * v9fs_file_open - open a file (or directory) - * @inode: inode to be opened - * @file: file being opened - * - */ - -int v9fs_file_open(struct inode *inode, struct file *file) -{ - int err; - struct v9fs_inode *v9inode; - struct v9fs_session_info *v9ses; - struct p9_fid *fid; - int omode; - - p9_debug(P9_DEBUG_VFS, "inode: %p file: %p\n", inode, file); - v9inode = V9FS_I(inode); - v9ses = v9fs_inode2v9ses(inode); - if (v9fs_proto_dotl(v9ses)) - omode = v9fs_open_to_dotl_flags(file->f_flags); - else - omode = v9fs_uflags2omode(file->f_flags, - v9fs_proto_dotu(v9ses)); - fid = file->private_data; - if (!fid) { - fid = v9fs_fid_clone(file_dentry(file)); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - err = p9_client_open(fid, omode); - if (err < 0) { - p9_client_clunk(fid); - return err; - } - if ((file->f_flags & O_APPEND) && - (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses))) - generic_file_llseek(file, 0, SEEK_END); - } - - file->private_data = fid; - mutex_lock(&v9inode->v_mutex); - if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) && - !v9inode->writeback_fid && - ((file->f_flags & O_ACCMODE) != O_RDONLY)) { - /* - * clone a fid and add it to writeback_fid - * we do it during open time instead of - * page dirty time via write_begin/page_mkwrite - * because we want write after unlink usecase - * to work. - */ - fid = v9fs_writeback_fid(file_dentry(file)); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - mutex_unlock(&v9inode->v_mutex); - goto out_error; - } - v9inode->writeback_fid = (void *) fid; - } - mutex_unlock(&v9inode->v_mutex); - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) - v9fs_cache_inode_set_cookie(inode, file); - return 0; -out_error: - p9_client_clunk(file->private_data); - file->private_data = NULL; - return err; -} - -/** - * v9fs_file_lock - lock a file (or directory) - * @filp: file to be locked - * @cmd: lock command - * @fl: file lock structure - * - * Bugs: this looks like a local only lock, we should extend into 9P - * by using open exclusive - */ - -static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) -{ - int res = 0; - struct inode *inode = file_inode(filp); - - p9_debug(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); - - /* No mandatory locks */ - if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) - return -ENOLCK; - - if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { - filemap_write_and_wait(inode->i_mapping); - invalidate_mapping_pages(&inode->i_data, 0, -1); - } - - return res; -} - -static int v9fs_file_do_lock(struct file *filp, int cmd, struct file_lock *fl) -{ - struct p9_flock flock; - struct p9_fid *fid; - uint8_t status = P9_LOCK_ERROR; - int res = 0; - unsigned char fl_type; - struct v9fs_session_info *v9ses; - - fid = filp->private_data; - BUG_ON(fid == NULL); - - if ((fl->fl_flags & FL_POSIX) != FL_POSIX) - BUG(); - - res = locks_lock_file_wait(filp, fl); - if (res < 0) - goto out; - - /* convert posix lock to p9 tlock args */ - memset(&flock, 0, sizeof(flock)); - /* map the lock type */ - switch (fl->fl_type) { - case F_RDLCK: - flock.type = P9_LOCK_TYPE_RDLCK; - break; - case F_WRLCK: - flock.type = P9_LOCK_TYPE_WRLCK; - break; - case F_UNLCK: - flock.type = P9_LOCK_TYPE_UNLCK; - break; - } - flock.start = fl->fl_start; - if (fl->fl_end == OFFSET_MAX) - flock.length = 0; - else - flock.length = fl->fl_end - fl->fl_start + 1; - flock.proc_id = fl->fl_pid; - flock.client_id = fid->clnt->name; - if (IS_SETLKW(cmd)) - flock.flags = P9_LOCK_FLAGS_BLOCK; - - v9ses = v9fs_inode2v9ses(file_inode(filp)); - - /* - * if its a blocked request and we get P9_LOCK_BLOCKED as the status - * for lock request, keep on trying - */ - for (;;) { - res = p9_client_lock_dotl(fid, &flock, &status); - if (res < 0) - goto out_unlock; - - if (status != P9_LOCK_BLOCKED) - break; - if (status == P9_LOCK_BLOCKED && !IS_SETLKW(cmd)) - break; - if (schedule_timeout_interruptible(v9ses->session_lock_timeout) - != 0) - break; - /* - * p9_client_lock_dotl overwrites flock.client_id with the - * server message, free and reuse the client name - */ - if (flock.client_id != fid->clnt->name) { - kfree(flock.client_id); - flock.client_id = fid->clnt->name; - } - } - - /* map 9p status to VFS status */ - switch (status) { - case P9_LOCK_SUCCESS: - res = 0; - break; - case P9_LOCK_BLOCKED: - res = -EAGAIN; - break; - default: - WARN_ONCE(1, "unknown lock status code: %d\n", status); - /* fallthough */ - case P9_LOCK_ERROR: - case P9_LOCK_GRACE: - res = -ENOLCK; - break; - } - -out_unlock: - /* - * incase server returned error for lock request, revert - * it locally - */ - if (res < 0 && fl->fl_type != F_UNLCK) { - fl_type = fl->fl_type; - fl->fl_type = F_UNLCK; - /* Even if this fails we want to return the remote error */ - locks_lock_file_wait(filp, fl); - fl->fl_type = fl_type; - } - if (flock.client_id != fid->clnt->name) - kfree(flock.client_id); -out: - return res; -} - -static int v9fs_file_getlock(struct file *filp, struct file_lock *fl) -{ - struct p9_getlock glock; - struct p9_fid *fid; - int res = 0; - - fid = filp->private_data; - BUG_ON(fid == NULL); - - posix_test_lock(filp, fl); - /* - * if we have a conflicting lock locally, no need to validate - * with server - */ - if (fl->fl_type != F_UNLCK) - return res; - - /* convert posix lock to p9 tgetlock args */ - memset(&glock, 0, sizeof(glock)); - glock.type = P9_LOCK_TYPE_UNLCK; - glock.start = fl->fl_start; - if (fl->fl_end == OFFSET_MAX) - glock.length = 0; - else - glock.length = fl->fl_end - fl->fl_start + 1; - glock.proc_id = fl->fl_pid; - glock.client_id = fid->clnt->name; - - res = p9_client_getlock_dotl(fid, &glock); - if (res < 0) - goto out; - /* map 9p lock type to os lock type */ - switch (glock.type) { - case P9_LOCK_TYPE_RDLCK: - fl->fl_type = F_RDLCK; - break; - case P9_LOCK_TYPE_WRLCK: - fl->fl_type = F_WRLCK; - break; - case P9_LOCK_TYPE_UNLCK: - fl->fl_type = F_UNLCK; - break; - } - if (glock.type != P9_LOCK_TYPE_UNLCK) { - fl->fl_start = glock.start; - if (glock.length == 0) - fl->fl_end = OFFSET_MAX; - else - fl->fl_end = glock.start + glock.length - 1; - fl->fl_pid = glock.proc_id; - } -out: - if (glock.client_id != fid->clnt->name) - kfree(glock.client_id); - return res; -} - -/** - * v9fs_file_lock_dotl - lock a file (or directory) - * @filp: file to be locked - * @cmd: lock command - * @fl: file lock structure - * - */ - -static int v9fs_file_lock_dotl(struct file *filp, int cmd, struct file_lock *fl) -{ - struct inode *inode = file_inode(filp); - int ret = -ENOLCK; - - p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %pD\n", - filp, cmd, fl, filp); - - /* No mandatory locks */ - if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) - goto out_err; - - if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { - filemap_write_and_wait(inode->i_mapping); - invalidate_mapping_pages(&inode->i_data, 0, -1); - } - - if (IS_SETLK(cmd) || IS_SETLKW(cmd)) - ret = v9fs_file_do_lock(filp, cmd, fl); - else if (IS_GETLK(cmd)) - ret = v9fs_file_getlock(filp, fl); - else - ret = -EINVAL; -out_err: - return ret; -} - -/** - * v9fs_file_flock_dotl - lock a file - * @filp: file to be locked - * @cmd: lock command - * @fl: file lock structure - * - */ - -static int v9fs_file_flock_dotl(struct file *filp, int cmd, - struct file_lock *fl) -{ - struct inode *inode = file_inode(filp); - int ret = -ENOLCK; - - p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %pD\n", - filp, cmd, fl, filp); - - /* No mandatory locks */ - if (__mandatory_lock(inode) && fl->fl_type != F_UNLCK) - goto out_err; - - if (!(fl->fl_flags & FL_FLOCK)) - goto out_err; - - if ((IS_SETLK(cmd) || IS_SETLKW(cmd)) && fl->fl_type != F_UNLCK) { - filemap_write_and_wait(inode->i_mapping); - invalidate_mapping_pages(&inode->i_data, 0, -1); - } - /* Convert flock to posix lock */ - fl->fl_flags |= FL_POSIX; - fl->fl_flags ^= FL_FLOCK; - - if (IS_SETLK(cmd) | IS_SETLKW(cmd)) - ret = v9fs_file_do_lock(filp, cmd, fl); - else - ret = -EINVAL; -out_err: - return ret; -} - -/** - * v9fs_file_read - read from a file - * @filp: file pointer to read - * @udata: user data buffer to read data into - * @count: size of buffer - * @offset: offset at which to read data - * - */ - -static ssize_t -v9fs_file_read_iter(struct kiocb *iocb, struct iov_iter *to) -{ - struct p9_fid *fid = iocb->ki_filp->private_data; - int ret, err = 0; - - p9_debug(P9_DEBUG_VFS, "count %zu offset %lld\n", - iov_iter_count(to), iocb->ki_pos); - - ret = p9_client_read(fid, iocb->ki_pos, to, &err); - if (!ret) - return err; - - iocb->ki_pos += ret; - return ret; -} - -/** - * v9fs_file_write - write to a file - * @filp: file pointer to write - * @data: data buffer to write data from - * @count: size of buffer - * @offset: offset at which to write data - * - */ -static ssize_t -v9fs_file_write_iter(struct kiocb *iocb, struct iov_iter *from) -{ - struct file *file = iocb->ki_filp; - ssize_t retval; - loff_t origin; - int err = 0; - - retval = generic_write_checks(iocb, from); - if (retval <= 0) - return retval; - - origin = iocb->ki_pos; - retval = p9_client_write(file->private_data, iocb->ki_pos, from, &err); - if (retval > 0) { - struct inode *inode = file_inode(file); - loff_t i_size; - unsigned long pg_start, pg_end; - pg_start = origin >> PAGE_CACHE_SHIFT; - pg_end = (origin + retval - 1) >> PAGE_CACHE_SHIFT; - if (inode->i_mapping && inode->i_mapping->nrpages) - invalidate_inode_pages2_range(inode->i_mapping, - pg_start, pg_end); - iocb->ki_pos += retval; - i_size = i_size_read(inode); - if (iocb->ki_pos > i_size) { - inode_add_bytes(inode, iocb->ki_pos - i_size); - /* - * Need to serialize against i_size_write() in - * v9fs_stat2inode() - */ - v9fs_i_size_write(inode, iocb->ki_pos); - } - return retval; - } - return err; -} - -static int v9fs_file_fsync(struct file *filp, loff_t start, loff_t end, - int datasync) -{ - struct p9_fid *fid; - struct inode *inode = filp->f_mapping->host; - struct p9_wstat wstat; - int retval; - - retval = filemap_write_and_wait_range(inode->i_mapping, start, end); - if (retval) - return retval; - - mutex_lock(&inode->i_mutex); - p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync); - - fid = filp->private_data; - v9fs_blank_wstat(&wstat); - - retval = p9_client_wstat(fid, &wstat); - mutex_unlock(&inode->i_mutex); - - return retval; -} - -int v9fs_file_fsync_dotl(struct file *filp, loff_t start, loff_t end, - int datasync) -{ - struct p9_fid *fid; - struct inode *inode = filp->f_mapping->host; - int retval; - - retval = filemap_write_and_wait_range(inode->i_mapping, start, end); - if (retval) - return retval; - - mutex_lock(&inode->i_mutex); - p9_debug(P9_DEBUG_VFS, "filp %p datasync %x\n", filp, datasync); - - fid = filp->private_data; - - retval = p9_client_fsync(fid, datasync); - mutex_unlock(&inode->i_mutex); - - return retval; -} - -static int -v9fs_file_mmap(struct file *filp, struct vm_area_struct *vma) -{ - int retval; - - - retval = generic_file_mmap(filp, vma); - if (!retval) - vma->vm_ops = &v9fs_file_vm_ops; - - return retval; -} - -static int -v9fs_mmap_file_mmap(struct file *filp, struct vm_area_struct *vma) -{ - int retval; - struct inode *inode; - struct v9fs_inode *v9inode; - struct p9_fid *fid; - - inode = file_inode(filp); - v9inode = V9FS_I(inode); - mutex_lock(&v9inode->v_mutex); - if (!v9inode->writeback_fid && - (vma->vm_flags & VM_WRITE)) { - /* - * clone a fid and add it to writeback_fid - * we do it during mmap instead of - * page dirty time via write_begin/page_mkwrite - * because we want write after unlink usecase - * to work. - */ - fid = v9fs_writeback_fid(file_dentry(filp)); - if (IS_ERR(fid)) { - retval = PTR_ERR(fid); - mutex_unlock(&v9inode->v_mutex); - return retval; - } - v9inode->writeback_fid = (void *) fid; - } - mutex_unlock(&v9inode->v_mutex); - - retval = generic_file_mmap(filp, vma); - if (!retval) - vma->vm_ops = &v9fs_mmap_file_vm_ops; - - return retval; -} - -static int -v9fs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) -{ - struct v9fs_inode *v9inode; - struct page *page = vmf->page; - struct file *filp = vma->vm_file; - struct inode *inode = file_inode(filp); - - - p9_debug(P9_DEBUG_VFS, "page %p fid %lx\n", - page, (unsigned long)filp->private_data); - - /* Update file times before taking page lock */ - file_update_time(filp); - - v9inode = V9FS_I(inode); - /* make sure the cache has finished storing the page */ - v9fs_fscache_wait_on_page_write(inode, page); - BUG_ON(!v9inode->writeback_fid); - lock_page(page); - if (page->mapping != inode->i_mapping) - goto out_unlock; - wait_for_stable_page(page); - - return VM_FAULT_LOCKED; -out_unlock: - unlock_page(page); - return VM_FAULT_NOPAGE; -} - -/** - * v9fs_mmap_file_read - read from a file - * @filp: file pointer to read - * @data: user data buffer to read data into - * @count: size of buffer - * @offset: offset at which to read data - * - */ -static ssize_t -v9fs_mmap_file_read_iter(struct kiocb *iocb, struct iov_iter *to) -{ - /* TODO: Check if there are dirty pages */ - return v9fs_file_read_iter(iocb, to); -} - -/** - * v9fs_mmap_file_write - write to a file - * @filp: file pointer to write - * @data: data buffer to write data from - * @count: size of buffer - * @offset: offset at which to write data - * - */ -static ssize_t -v9fs_mmap_file_write_iter(struct kiocb *iocb, struct iov_iter *from) -{ - /* - * TODO: invalidate mmaps on filp's inode between - * offset and offset+count - */ - return v9fs_file_write_iter(iocb, from); -} - -static void v9fs_mmap_vm_close(struct vm_area_struct *vma) -{ - struct inode *inode; - - struct writeback_control wbc = { - .nr_to_write = LONG_MAX, - .sync_mode = WB_SYNC_ALL, - .range_start = vma->vm_pgoff * PAGE_SIZE, - /* absolute end, byte at end included */ - .range_end = vma->vm_pgoff * PAGE_SIZE + - (vma->vm_end - vma->vm_start - 1), - }; - - - p9_debug(P9_DEBUG_VFS, "9p VMA close, %p, flushing", vma); - - inode = file_inode(vma->vm_file); - - if (!mapping_cap_writeback_dirty(inode->i_mapping)) - wbc.nr_to_write = 0; - - might_sleep(); - sync_inode(inode, &wbc); -} - - -static const struct vm_operations_struct v9fs_file_vm_ops = { - .fault = filemap_fault, - .map_pages = filemap_map_pages, - .page_mkwrite = v9fs_vm_page_mkwrite, -}; - -static const struct vm_operations_struct v9fs_mmap_file_vm_ops = { - .close = v9fs_mmap_vm_close, - .fault = filemap_fault, - .map_pages = filemap_map_pages, - .page_mkwrite = v9fs_vm_page_mkwrite, -}; - - -const struct file_operations v9fs_cached_file_operations = { - .llseek = generic_file_llseek, - .read_iter = generic_file_read_iter, - .write_iter = generic_file_write_iter, - .open = v9fs_file_open, - .release = v9fs_dir_release, - .lock = v9fs_file_lock, - .mmap = v9fs_file_mmap, - .fsync = v9fs_file_fsync, -}; - -const struct file_operations v9fs_cached_file_operations_dotl = { - .llseek = generic_file_llseek, - .read_iter = generic_file_read_iter, - .write_iter = generic_file_write_iter, - .open = v9fs_file_open, - .release = v9fs_dir_release, - .lock = v9fs_file_lock_dotl, - .flock = v9fs_file_flock_dotl, - .mmap = v9fs_file_mmap, - .fsync = v9fs_file_fsync_dotl, -}; - -const struct file_operations v9fs_file_operations = { - .llseek = generic_file_llseek, - .read_iter = v9fs_file_read_iter, - .write_iter = v9fs_file_write_iter, - .open = v9fs_file_open, - .release = v9fs_dir_release, - .lock = v9fs_file_lock, - .mmap = generic_file_readonly_mmap, - .fsync = v9fs_file_fsync, -}; - -const struct file_operations v9fs_file_operations_dotl = { - .llseek = generic_file_llseek, - .read_iter = v9fs_file_read_iter, - .write_iter = v9fs_file_write_iter, - .open = v9fs_file_open, - .release = v9fs_dir_release, - .lock = v9fs_file_lock_dotl, - .flock = v9fs_file_flock_dotl, - .mmap = generic_file_readonly_mmap, - .fsync = v9fs_file_fsync_dotl, -}; - -const struct file_operations v9fs_mmap_file_operations = { - .llseek = generic_file_llseek, - .read_iter = v9fs_mmap_file_read_iter, - .write_iter = v9fs_mmap_file_write_iter, - .open = v9fs_file_open, - .release = v9fs_dir_release, - .lock = v9fs_file_lock, - .mmap = v9fs_mmap_file_mmap, - .fsync = v9fs_file_fsync, -}; - -const struct file_operations v9fs_mmap_file_operations_dotl = { - .llseek = generic_file_llseek, - .read_iter = v9fs_mmap_file_read_iter, - .write_iter = v9fs_mmap_file_write_iter, - .open = v9fs_file_open, - .release = v9fs_dir_release, - .lock = v9fs_file_lock_dotl, - .flock = v9fs_file_flock_dotl, - .mmap = v9fs_mmap_file_mmap, - .fsync = v9fs_file_fsync_dotl, -}; diff --git a/addons/9p/src/4.4.180/vfs_inode.c b/addons/9p/src/4.4.180/vfs_inode.c deleted file mode 100644 index 2de1505a..00000000 --- a/addons/9p/src/4.4.180/vfs_inode.c +++ /dev/null @@ -1,1462 +0,0 @@ -/* - * linux/fs/9p/vfs_inode.c - * - * This file contains vfs inode ops for the 9P2000 protocol. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" -#include "cache.h" -#include "xattr.h" -#include "acl.h" - -static const struct inode_operations v9fs_dir_inode_operations; -static const struct inode_operations v9fs_dir_inode_operations_dotu; -static const struct inode_operations v9fs_file_inode_operations; -static const struct inode_operations v9fs_symlink_inode_operations; - -/** - * unixmode2p9mode - convert unix mode bits to plan 9 - * @v9ses: v9fs session information - * @mode: mode to convert - * - */ - -static u32 unixmode2p9mode(struct v9fs_session_info *v9ses, umode_t mode) -{ - int res; - res = mode & 0777; - if (S_ISDIR(mode)) - res |= P9_DMDIR; - if (v9fs_proto_dotu(v9ses)) { - if (v9ses->nodev == 0) { - if (S_ISSOCK(mode)) - res |= P9_DMSOCKET; - if (S_ISFIFO(mode)) - res |= P9_DMNAMEDPIPE; - if (S_ISBLK(mode)) - res |= P9_DMDEVICE; - if (S_ISCHR(mode)) - res |= P9_DMDEVICE; - } - - if ((mode & S_ISUID) == S_ISUID) - res |= P9_DMSETUID; - if ((mode & S_ISGID) == S_ISGID) - res |= P9_DMSETGID; - if ((mode & S_ISVTX) == S_ISVTX) - res |= P9_DMSETVTX; - } - return res; -} - -/** - * p9mode2perm- convert plan9 mode bits to unix permission bits - * @v9ses: v9fs session information - * @stat: p9_wstat from which mode need to be derived - * - */ -static int p9mode2perm(struct v9fs_session_info *v9ses, - struct p9_wstat *stat) -{ - int res; - int mode = stat->mode; - - res = mode & S_IALLUGO; - if (v9fs_proto_dotu(v9ses)) { - if ((mode & P9_DMSETUID) == P9_DMSETUID) - res |= S_ISUID; - - if ((mode & P9_DMSETGID) == P9_DMSETGID) - res |= S_ISGID; - - if ((mode & P9_DMSETVTX) == P9_DMSETVTX) - res |= S_ISVTX; - } - return res; -} - -/** - * p9mode2unixmode- convert plan9 mode bits to unix mode bits - * @v9ses: v9fs session information - * @stat: p9_wstat from which mode need to be derived - * @rdev: major number, minor number in case of device files. - * - */ -static umode_t p9mode2unixmode(struct v9fs_session_info *v9ses, - struct p9_wstat *stat, dev_t *rdev) -{ - int res; - u32 mode = stat->mode; - - *rdev = 0; - res = p9mode2perm(v9ses, stat); - - if ((mode & P9_DMDIR) == P9_DMDIR) - res |= S_IFDIR; - else if ((mode & P9_DMSYMLINK) && (v9fs_proto_dotu(v9ses))) - res |= S_IFLNK; - else if ((mode & P9_DMSOCKET) && (v9fs_proto_dotu(v9ses)) - && (v9ses->nodev == 0)) - res |= S_IFSOCK; - else if ((mode & P9_DMNAMEDPIPE) && (v9fs_proto_dotu(v9ses)) - && (v9ses->nodev == 0)) - res |= S_IFIFO; - else if ((mode & P9_DMDEVICE) && (v9fs_proto_dotu(v9ses)) - && (v9ses->nodev == 0)) { - char type = 0, ext[32]; - int major = -1, minor = -1; - - strlcpy(ext, stat->extension, sizeof(ext)); - sscanf(ext, "%c %i %i", &type, &major, &minor); - switch (type) { - case 'c': - res |= S_IFCHR; - break; - case 'b': - res |= S_IFBLK; - break; - default: - p9_debug(P9_DEBUG_ERROR, "Unknown special type %c %s\n", - type, stat->extension); - }; - *rdev = MKDEV(major, minor); - } else - res |= S_IFREG; - - return res; -} - -/** - * v9fs_uflags2omode- convert posix open flags to plan 9 mode bits - * @uflags: flags to convert - * @extended: if .u extensions are active - */ - -int v9fs_uflags2omode(int uflags, int extended) -{ - int ret; - - ret = 0; - switch (uflags&3) { - default: - case O_RDONLY: - ret = P9_OREAD; - break; - - case O_WRONLY: - ret = P9_OWRITE; - break; - - case O_RDWR: - ret = P9_ORDWR; - break; - } - - if (extended) { - if (uflags & O_EXCL) - ret |= P9_OEXCL; - - if (uflags & O_APPEND) - ret |= P9_OAPPEND; - } - - return ret; -} - -/** - * v9fs_blank_wstat - helper function to setup a 9P stat structure - * @wstat: structure to initialize - * - */ - -void -v9fs_blank_wstat(struct p9_wstat *wstat) -{ - wstat->type = ~0; - wstat->dev = ~0; - wstat->qid.type = ~0; - wstat->qid.version = ~0; - *((long long *)&wstat->qid.path) = ~0; - wstat->mode = ~0; - wstat->atime = ~0; - wstat->mtime = ~0; - wstat->length = ~0; - wstat->name = NULL; - wstat->uid = NULL; - wstat->gid = NULL; - wstat->muid = NULL; - wstat->n_uid = INVALID_UID; - wstat->n_gid = INVALID_GID; - wstat->n_muid = INVALID_UID; - wstat->extension = NULL; -} - -/** - * v9fs_alloc_inode - helper function to allocate an inode - * - */ -struct inode *v9fs_alloc_inode(struct super_block *sb) -{ - struct v9fs_inode *v9inode; - v9inode = (struct v9fs_inode *)kmem_cache_alloc(v9fs_inode_cache, - GFP_KERNEL); - if (!v9inode) - return NULL; -#ifdef CONFIG_9P_FSCACHE - v9inode->fscache = NULL; - mutex_init(&v9inode->fscache_lock); -#endif - v9inode->writeback_fid = NULL; - v9inode->cache_validity = 0; - mutex_init(&v9inode->v_mutex); - return &v9inode->vfs_inode; -} - -/** - * v9fs_destroy_inode - destroy an inode - * - */ - -static void v9fs_i_callback(struct rcu_head *head) -{ - struct inode *inode = container_of(head, struct inode, i_rcu); - kmem_cache_free(v9fs_inode_cache, V9FS_I(inode)); -} - -void v9fs_destroy_inode(struct inode *inode) -{ - call_rcu(&inode->i_rcu, v9fs_i_callback); -} - -int v9fs_init_inode(struct v9fs_session_info *v9ses, - struct inode *inode, umode_t mode, dev_t rdev) -{ - int err = 0; - - inode_init_owner(inode, NULL, mode); - inode->i_blocks = 0; - inode->i_rdev = rdev; - inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; - inode->i_mapping->a_ops = &v9fs_addr_operations; - - switch (mode & S_IFMT) { - case S_IFIFO: - case S_IFBLK: - case S_IFCHR: - case S_IFSOCK: - if (v9fs_proto_dotl(v9ses)) { - inode->i_op = &v9fs_file_inode_operations_dotl; - } else if (v9fs_proto_dotu(v9ses)) { - inode->i_op = &v9fs_file_inode_operations; - } else { - p9_debug(P9_DEBUG_ERROR, - "special files without extended mode\n"); - err = -EINVAL; - goto error; - } - init_special_inode(inode, inode->i_mode, inode->i_rdev); - break; - case S_IFREG: - if (v9fs_proto_dotl(v9ses)) { - inode->i_op = &v9fs_file_inode_operations_dotl; - if (v9ses->cache == CACHE_LOOSE || - v9ses->cache == CACHE_FSCACHE) - inode->i_fop = - &v9fs_cached_file_operations_dotl; - else if (v9ses->cache == CACHE_MMAP) - inode->i_fop = &v9fs_mmap_file_operations_dotl; - else - inode->i_fop = &v9fs_file_operations_dotl; - } else { - inode->i_op = &v9fs_file_inode_operations; - if (v9ses->cache == CACHE_LOOSE || - v9ses->cache == CACHE_FSCACHE) - inode->i_fop = - &v9fs_cached_file_operations; - else if (v9ses->cache == CACHE_MMAP) - inode->i_fop = &v9fs_mmap_file_operations; - else - inode->i_fop = &v9fs_file_operations; - } - - break; - case S_IFLNK: - if (!v9fs_proto_dotu(v9ses) && !v9fs_proto_dotl(v9ses)) { - p9_debug(P9_DEBUG_ERROR, - "extended modes used with legacy protocol\n"); - err = -EINVAL; - goto error; - } - - if (v9fs_proto_dotl(v9ses)) - inode->i_op = &v9fs_symlink_inode_operations_dotl; - else - inode->i_op = &v9fs_symlink_inode_operations; - - break; - case S_IFDIR: - inc_nlink(inode); - if (v9fs_proto_dotl(v9ses)) - inode->i_op = &v9fs_dir_inode_operations_dotl; - else if (v9fs_proto_dotu(v9ses)) - inode->i_op = &v9fs_dir_inode_operations_dotu; - else - inode->i_op = &v9fs_dir_inode_operations; - - if (v9fs_proto_dotl(v9ses)) - inode->i_fop = &v9fs_dir_operations_dotl; - else - inode->i_fop = &v9fs_dir_operations; - - break; - default: - p9_debug(P9_DEBUG_ERROR, "BAD mode 0x%hx S_IFMT 0x%x\n", - mode, mode & S_IFMT); - err = -EINVAL; - goto error; - } -error: - return err; - -} - -/** - * v9fs_get_inode - helper function to setup an inode - * @sb: superblock - * @mode: mode to setup inode with - * - */ - -struct inode *v9fs_get_inode(struct super_block *sb, umode_t mode, dev_t rdev) -{ - int err; - struct inode *inode; - struct v9fs_session_info *v9ses = sb->s_fs_info; - - p9_debug(P9_DEBUG_VFS, "super block: %p mode: %ho\n", sb, mode); - - inode = new_inode(sb); - if (!inode) { - pr_warn("%s (%d): Problem allocating inode\n", - __func__, task_pid_nr(current)); - return ERR_PTR(-ENOMEM); - } - err = v9fs_init_inode(v9ses, inode, mode, rdev); - if (err) { - iput(inode); - return ERR_PTR(err); - } - return inode; -} - -/* -static struct v9fs_fid* -v9fs_clone_walk(struct v9fs_session_info *v9ses, u32 fid, struct dentry *dentry) -{ - int err; - int nfid; - struct v9fs_fid *ret; - struct v9fs_fcall *fcall; - - nfid = v9fs_get_idpool(&v9ses->fidpool); - if (nfid < 0) { - eprintk(KERN_WARNING, "no free fids available\n"); - return ERR_PTR(-ENOSPC); - } - - err = v9fs_t_walk(v9ses, fid, nfid, (char *) dentry->d_name.name, - &fcall); - - if (err < 0) { - if (fcall && fcall->id == RWALK) - goto clunk_fid; - - PRINT_FCALL_ERROR("walk error", fcall); - v9fs_put_idpool(nfid, &v9ses->fidpool); - goto error; - } - - kfree(fcall); - fcall = NULL; - ret = v9fs_fid_create(v9ses, nfid); - if (!ret) { - err = -ENOMEM; - goto clunk_fid; - } - - err = v9fs_fid_insert(ret, dentry); - if (err < 0) { - v9fs_fid_destroy(ret); - goto clunk_fid; - } - - return ret; - -clunk_fid: - v9fs_t_clunk(v9ses, nfid); - -error: - kfree(fcall); - return ERR_PTR(err); -} -*/ - - -/** - * v9fs_clear_inode - release an inode - * @inode: inode to release - * - */ -void v9fs_evict_inode(struct inode *inode) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - - truncate_inode_pages_final(&inode->i_data); - clear_inode(inode); - filemap_fdatawrite(&inode->i_data); - - v9fs_cache_inode_put_cookie(inode); - /* clunk the fid stashed in writeback_fid */ - if (v9inode->writeback_fid) { - p9_client_clunk(v9inode->writeback_fid); - v9inode->writeback_fid = NULL; - } -} - -static int v9fs_test_inode(struct inode *inode, void *data) -{ - int umode; - dev_t rdev; - struct v9fs_inode *v9inode = V9FS_I(inode); - struct p9_wstat *st = (struct p9_wstat *)data; - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(inode); - - umode = p9mode2unixmode(v9ses, st, &rdev); - /* don't match inode of different type */ - if ((inode->i_mode & S_IFMT) != (umode & S_IFMT)) - return 0; - - /* compare qid details */ - if (memcmp(&v9inode->qid.version, - &st->qid.version, sizeof(v9inode->qid.version))) - return 0; - - if (v9inode->qid.type != st->qid.type) - return 0; - - if (v9inode->qid.path != st->qid.path) - return 0; - return 1; -} - -static int v9fs_test_new_inode(struct inode *inode, void *data) -{ - return 0; -} - -static int v9fs_set_inode(struct inode *inode, void *data) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - struct p9_wstat *st = (struct p9_wstat *)data; - - memcpy(&v9inode->qid, &st->qid, sizeof(st->qid)); - return 0; -} - -static struct inode *v9fs_qid_iget(struct super_block *sb, - struct p9_qid *qid, - struct p9_wstat *st, - int new) -{ - dev_t rdev; - int retval; - umode_t umode; - unsigned long i_ino; - struct inode *inode; - struct v9fs_session_info *v9ses = sb->s_fs_info; - int (*test)(struct inode *, void *); - - if (new) - test = v9fs_test_new_inode; - else - test = v9fs_test_inode; - - i_ino = v9fs_qid2ino(qid); - inode = iget5_locked(sb, i_ino, test, v9fs_set_inode, st); - if (!inode) - return ERR_PTR(-ENOMEM); - if (!(inode->i_state & I_NEW)) - return inode; - /* - * initialize the inode with the stat info - * FIXME!! we may need support for stale inodes - * later. - */ - inode->i_ino = i_ino; - umode = p9mode2unixmode(v9ses, st, &rdev); - retval = v9fs_init_inode(v9ses, inode, umode, rdev); - if (retval) - goto error; - - v9fs_stat2inode(st, inode, sb, 0); - v9fs_cache_inode_get_cookie(inode); - unlock_new_inode(inode); - return inode; -error: - iget_failed(inode); - return ERR_PTR(retval); - -} - -struct inode * -v9fs_inode_from_fid(struct v9fs_session_info *v9ses, struct p9_fid *fid, - struct super_block *sb, int new) -{ - struct p9_wstat *st; - struct inode *inode = NULL; - - st = p9_client_stat(fid); - if (IS_ERR(st)) - return ERR_CAST(st); - - inode = v9fs_qid_iget(sb, &st->qid, st, new); - p9stat_free(st); - kfree(st); - return inode; -} - -/** - * v9fs_at_to_dotl_flags- convert Linux specific AT flags to - * plan 9 AT flag. - * @flags: flags to convert - */ -static int v9fs_at_to_dotl_flags(int flags) -{ - int rflags = 0; - if (flags & AT_REMOVEDIR) - rflags |= P9_DOTL_AT_REMOVEDIR; - return rflags; -} - -/** - * v9fs_remove - helper function to remove files and directories - * @dir: directory inode that is being deleted - * @dentry: dentry that is being deleted - * @flags: removing a directory - * - */ - -static int v9fs_remove(struct inode *dir, struct dentry *dentry, int flags) -{ - struct inode *inode; - int retval = -EOPNOTSUPP; - struct p9_fid *v9fid, *dfid; - struct v9fs_session_info *v9ses; - - p9_debug(P9_DEBUG_VFS, "inode: %p dentry: %p rmdir: %x\n", - dir, dentry, flags); - - v9ses = v9fs_inode2v9ses(dir); - inode = d_inode(dentry); - dfid = v9fs_fid_lookup(dentry->d_parent); - if (IS_ERR(dfid)) { - retval = PTR_ERR(dfid); - p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", retval); - return retval; - } - if (v9fs_proto_dotl(v9ses)) - retval = p9_client_unlinkat(dfid, dentry->d_name.name, - v9fs_at_to_dotl_flags(flags)); - if (retval == -EOPNOTSUPP) { - /* Try the one based on path */ - v9fid = v9fs_fid_clone(dentry); - if (IS_ERR(v9fid)) - return PTR_ERR(v9fid); - retval = p9_client_remove(v9fid); - } - if (!retval) { - /* - * directories on unlink should have zero - * link count - */ - if (flags & AT_REMOVEDIR) { - clear_nlink(inode); - drop_nlink(dir); - } else - drop_nlink(inode); - - v9fs_invalidate_inode_attr(inode); - v9fs_invalidate_inode_attr(dir); - } - return retval; -} - -/** - * v9fs_create - Create a file - * @v9ses: session information - * @dir: directory that dentry is being created in - * @dentry: dentry that is being created - * @extension: 9p2000.u extension string to support devices, etc. - * @perm: create permissions - * @mode: open mode - * - */ -static struct p9_fid * -v9fs_create(struct v9fs_session_info *v9ses, struct inode *dir, - struct dentry *dentry, char *extension, u32 perm, u8 mode) -{ - int err; - char *name; - struct p9_fid *dfid, *ofid, *fid; - struct inode *inode; - - p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry); - - err = 0; - ofid = NULL; - fid = NULL; - name = (char *) dentry->d_name.name; - dfid = v9fs_fid_lookup(dentry->d_parent); - if (IS_ERR(dfid)) { - err = PTR_ERR(dfid); - p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); - return ERR_PTR(err); - } - - /* clone a fid to use for creation */ - ofid = p9_client_walk(dfid, 0, NULL, 1); - if (IS_ERR(ofid)) { - err = PTR_ERR(ofid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); - return ERR_PTR(err); - } - - err = p9_client_fcreate(ofid, name, perm, mode, extension); - if (err < 0) { - p9_debug(P9_DEBUG_VFS, "p9_client_fcreate failed %d\n", err); - goto error; - } - - if (!(perm & P9_DMLINK)) { - /* now walk from the parent so we can get unopened fid */ - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - p9_debug(P9_DEBUG_VFS, - "p9_client_walk failed %d\n", err); - fid = NULL; - goto error; - } - /* - * instantiate inode and assign the unopened fid to the dentry - */ - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - p9_debug(P9_DEBUG_VFS, - "inode creation failed %d\n", err); - goto error; - } - v9fs_fid_add(dentry, fid); - d_instantiate(dentry, inode); - } - return ofid; -error: - if (ofid) - p9_client_clunk(ofid); - - if (fid) - p9_client_clunk(fid); - - return ERR_PTR(err); -} - -/** - * v9fs_vfs_create - VFS hook to create a regular file - * - * open(.., O_CREAT) is handled in v9fs_vfs_atomic_open(). This is only called - * for mknod(2). - * - * @dir: directory inode that is being created - * @dentry: dentry that is being deleted - * @mode: create permissions - * - */ - -static int -v9fs_vfs_create(struct inode *dir, struct dentry *dentry, umode_t mode, - bool excl) -{ - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); - u32 perm = unixmode2p9mode(v9ses, mode); - struct p9_fid *fid; - - /* P9_OEXCL? */ - fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_ORDWR); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - v9fs_invalidate_inode_attr(dir); - p9_client_clunk(fid); - - return 0; -} - -/** - * v9fs_vfs_mkdir - VFS mkdir hook to create a directory - * @dir: inode that is being unlinked - * @dentry: dentry that is being unlinked - * @mode: mode for new directory - * - */ - -static int v9fs_vfs_mkdir(struct inode *dir, struct dentry *dentry, umode_t mode) -{ - int err; - u32 perm; - struct p9_fid *fid; - struct v9fs_session_info *v9ses; - - p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry); - err = 0; - v9ses = v9fs_inode2v9ses(dir); - perm = unixmode2p9mode(v9ses, mode | S_IFDIR); - fid = v9fs_create(v9ses, dir, dentry, NULL, perm, P9_OREAD); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - fid = NULL; - } else { - inc_nlink(dir); - v9fs_invalidate_inode_attr(dir); - } - - if (fid) - p9_client_clunk(fid); - - return err; -} - -/** - * v9fs_vfs_lookup - VFS lookup hook to "walk" to a new inode - * @dir: inode that is being walked from - * @dentry: dentry that is being walked to? - * @flags: lookup flags (unused) - * - */ - -struct dentry *v9fs_vfs_lookup(struct inode *dir, struct dentry *dentry, - unsigned int flags) -{ - struct dentry *res; - struct v9fs_session_info *v9ses; - struct p9_fid *dfid, *fid; - struct inode *inode; - char *name; - - p9_debug(P9_DEBUG_VFS, "dir: %p dentry: (%pd) %p flags: %x\n", - dir, dentry, dentry, flags); - - if (dentry->d_name.len > NAME_MAX) - return ERR_PTR(-ENAMETOOLONG); - - v9ses = v9fs_inode2v9ses(dir); - /* We can walk d_parent because we hold the dir->i_mutex */ - dfid = v9fs_fid_lookup(dentry->d_parent); - if (IS_ERR(dfid)) - return ERR_CAST(dfid); - - name = (char *) dentry->d_name.name; - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - if (fid == ERR_PTR(-ENOENT)) { - d_add(dentry, NULL); - return NULL; - } - return ERR_CAST(fid); - } - /* - * Make sure we don't use a wrong inode due to parallel - * unlink. For cached mode create calls request for new - * inode. But with cache disabled, lookup should do this. - */ - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) - inode = v9fs_get_inode_from_fid(v9ses, fid, dir->i_sb); - else - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); - if (IS_ERR(inode)) { - p9_client_clunk(fid); - return ERR_CAST(inode); - } - /* - * If we had a rename on the server and a parallel lookup - * for the new name, then make sure we instantiate with - * the new name. ie look up for a/b, while on server somebody - * moved b under k and client parallely did a lookup for - * k/b. - */ - res = d_splice_alias(inode, dentry); - if (!res) - v9fs_fid_add(dentry, fid); - else if (!IS_ERR(res)) - v9fs_fid_add(res, fid); - else - p9_client_clunk(fid); - return res; -} - -static int -v9fs_vfs_atomic_open(struct inode *dir, struct dentry *dentry, - struct file *file, unsigned flags, umode_t mode, - int *opened) -{ - int err; - u32 perm; - struct v9fs_inode *v9inode; - struct v9fs_session_info *v9ses; - struct p9_fid *fid, *inode_fid; - struct dentry *res = NULL; - - if (d_unhashed(dentry)) { - res = v9fs_vfs_lookup(dir, dentry, 0); - if (IS_ERR(res)) - return PTR_ERR(res); - - if (res) - dentry = res; - } - - /* Only creates */ - if (!(flags & O_CREAT) || d_really_is_positive(dentry)) - return finish_no_open(file, res); - - err = 0; - - v9ses = v9fs_inode2v9ses(dir); - perm = unixmode2p9mode(v9ses, mode); - fid = v9fs_create(v9ses, dir, dentry, NULL, perm, - v9fs_uflags2omode(flags, - v9fs_proto_dotu(v9ses))); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - fid = NULL; - goto error; - } - - v9fs_invalidate_inode_attr(dir); - v9inode = V9FS_I(d_inode(dentry)); - mutex_lock(&v9inode->v_mutex); - if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) && - !v9inode->writeback_fid && - ((flags & O_ACCMODE) != O_RDONLY)) { - /* - * clone a fid and add it to writeback_fid - * we do it during open time instead of - * page dirty time via write_begin/page_mkwrite - * because we want write after unlink usecase - * to work. - */ - inode_fid = v9fs_writeback_fid(dentry); - if (IS_ERR(inode_fid)) { - err = PTR_ERR(inode_fid); - mutex_unlock(&v9inode->v_mutex); - goto error; - } - v9inode->writeback_fid = (void *) inode_fid; - } - mutex_unlock(&v9inode->v_mutex); - err = finish_open(file, dentry, generic_file_open, opened); - if (err) - goto error; - - file->private_data = fid; - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) - v9fs_cache_inode_set_cookie(d_inode(dentry), file); - - *opened |= FILE_CREATED; -out: - dput(res); - return err; - -error: - if (fid) - p9_client_clunk(fid); - goto out; -} - -/** - * v9fs_vfs_unlink - VFS unlink hook to delete an inode - * @i: inode that is being unlinked - * @d: dentry that is being unlinked - * - */ - -int v9fs_vfs_unlink(struct inode *i, struct dentry *d) -{ - return v9fs_remove(i, d, 0); -} - -/** - * v9fs_vfs_rmdir - VFS unlink hook to delete a directory - * @i: inode that is being unlinked - * @d: dentry that is being unlinked - * - */ - -int v9fs_vfs_rmdir(struct inode *i, struct dentry *d) -{ - return v9fs_remove(i, d, AT_REMOVEDIR); -} - -/** - * v9fs_vfs_rename - VFS hook to rename an inode - * @old_dir: old dir inode - * @old_dentry: old dentry - * @new_dir: new dir inode - * @new_dentry: new dentry - * - */ - -int -v9fs_vfs_rename(struct inode *old_dir, struct dentry *old_dentry, - struct inode *new_dir, struct dentry *new_dentry) -{ - int retval; - struct inode *old_inode; - struct inode *new_inode; - struct v9fs_session_info *v9ses; - struct p9_fid *oldfid; - struct p9_fid *olddirfid; - struct p9_fid *newdirfid; - struct p9_wstat wstat; - - p9_debug(P9_DEBUG_VFS, "\n"); - retval = 0; - old_inode = d_inode(old_dentry); - new_inode = d_inode(new_dentry); - v9ses = v9fs_inode2v9ses(old_inode); - oldfid = v9fs_fid_lookup(old_dentry); - if (IS_ERR(oldfid)) - return PTR_ERR(oldfid); - - olddirfid = v9fs_fid_clone(old_dentry->d_parent); - if (IS_ERR(olddirfid)) { - retval = PTR_ERR(olddirfid); - goto done; - } - - newdirfid = v9fs_fid_clone(new_dentry->d_parent); - if (IS_ERR(newdirfid)) { - retval = PTR_ERR(newdirfid); - goto clunk_olddir; - } - - down_write(&v9ses->rename_sem); - if (v9fs_proto_dotl(v9ses)) { - retval = p9_client_renameat(olddirfid, old_dentry->d_name.name, - newdirfid, new_dentry->d_name.name); - if (retval == -EOPNOTSUPP) - retval = p9_client_rename(oldfid, newdirfid, - new_dentry->d_name.name); - if (retval != -EOPNOTSUPP) - goto clunk_newdir; - } - if (old_dentry->d_parent != new_dentry->d_parent) { - /* - * 9P .u can only handle file rename in the same directory - */ - - p9_debug(P9_DEBUG_ERROR, "old dir and new dir are different\n"); - retval = -EXDEV; - goto clunk_newdir; - } - v9fs_blank_wstat(&wstat); - wstat.muid = v9ses->uname; - wstat.name = (char *) new_dentry->d_name.name; - retval = p9_client_wstat(oldfid, &wstat); - -clunk_newdir: - if (!retval) { - if (new_inode) { - if (S_ISDIR(new_inode->i_mode)) - clear_nlink(new_inode); - else - drop_nlink(new_inode); - } - if (S_ISDIR(old_inode->i_mode)) { - if (!new_inode) - inc_nlink(new_dir); - drop_nlink(old_dir); - } - v9fs_invalidate_inode_attr(old_inode); - v9fs_invalidate_inode_attr(old_dir); - v9fs_invalidate_inode_attr(new_dir); - - /* successful rename */ - d_move(old_dentry, new_dentry); - } - up_write(&v9ses->rename_sem); - p9_client_clunk(newdirfid); - -clunk_olddir: - p9_client_clunk(olddirfid); - -done: - return retval; -} - -/** - * v9fs_vfs_getattr - retrieve file metadata - * @mnt: mount information - * @dentry: file to get attributes on - * @stat: metadata structure to populate - * - */ - -static int -v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry, - struct kstat *stat) -{ - struct v9fs_session_info *v9ses; - struct p9_fid *fid; - struct p9_wstat *st; - - p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry); - v9ses = v9fs_dentry2v9ses(dentry); - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - generic_fillattr(d_inode(dentry), stat); - return 0; - } - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - st = p9_client_stat(fid); - if (IS_ERR(st)) - return PTR_ERR(st); - - v9fs_stat2inode(st, d_inode(dentry), d_inode(dentry)->i_sb, 0); - generic_fillattr(d_inode(dentry), stat); - - p9stat_free(st); - kfree(st); - return 0; -} - -/** - * v9fs_vfs_setattr - set file metadata - * @dentry: file whose metadata to set - * @iattr: metadata assignment structure - * - */ - -static int v9fs_vfs_setattr(struct dentry *dentry, struct iattr *iattr) -{ - int retval; - struct v9fs_session_info *v9ses; - struct p9_fid *fid; - struct p9_wstat wstat; - - p9_debug(P9_DEBUG_VFS, "\n"); - retval = inode_change_ok(d_inode(dentry), iattr); - if (retval) - return retval; - - retval = -EPERM; - v9ses = v9fs_dentry2v9ses(dentry); - fid = v9fs_fid_lookup(dentry); - if(IS_ERR(fid)) - return PTR_ERR(fid); - - v9fs_blank_wstat(&wstat); - if (iattr->ia_valid & ATTR_MODE) - wstat.mode = unixmode2p9mode(v9ses, iattr->ia_mode); - - if (iattr->ia_valid & ATTR_MTIME) - wstat.mtime = iattr->ia_mtime.tv_sec; - - if (iattr->ia_valid & ATTR_ATIME) - wstat.atime = iattr->ia_atime.tv_sec; - - if (iattr->ia_valid & ATTR_SIZE) - wstat.length = iattr->ia_size; - - if (v9fs_proto_dotu(v9ses)) { - if (iattr->ia_valid & ATTR_UID) - wstat.n_uid = iattr->ia_uid; - - if (iattr->ia_valid & ATTR_GID) - wstat.n_gid = iattr->ia_gid; - } - - /* Write all dirty data */ - if (d_is_reg(dentry)) - filemap_write_and_wait(d_inode(dentry)->i_mapping); - - retval = p9_client_wstat(fid, &wstat); - if (retval < 0) - return retval; - - if ((iattr->ia_valid & ATTR_SIZE) && - iattr->ia_size != i_size_read(d_inode(dentry))) - truncate_setsize(d_inode(dentry), iattr->ia_size); - - v9fs_invalidate_inode_attr(d_inode(dentry)); - - setattr_copy(d_inode(dentry), iattr); - mark_inode_dirty(d_inode(dentry)); - return 0; -} - -/** - * v9fs_stat2inode - populate an inode structure with mistat info - * @stat: Plan 9 metadata (mistat) structure - * @inode: inode to populate - * @sb: superblock of filesystem - * @flags: control flags (e.g. V9FS_STAT2INODE_KEEP_ISIZE) - * - */ - -void -v9fs_stat2inode(struct p9_wstat *stat, struct inode *inode, - struct super_block *sb, unsigned int flags) -{ - umode_t mode; - char ext[32]; - char tag_name[14]; - unsigned int i_nlink; - struct v9fs_session_info *v9ses = sb->s_fs_info; - struct v9fs_inode *v9inode = V9FS_I(inode); - - set_nlink(inode, 1); - - inode->i_atime.tv_sec = stat->atime; - inode->i_mtime.tv_sec = stat->mtime; - inode->i_ctime.tv_sec = stat->mtime; - - inode->i_uid = v9ses->dfltuid; - inode->i_gid = v9ses->dfltgid; - - if (v9fs_proto_dotu(v9ses)) { - inode->i_uid = stat->n_uid; - inode->i_gid = stat->n_gid; - } - if ((S_ISREG(inode->i_mode)) || (S_ISDIR(inode->i_mode))) { - if (v9fs_proto_dotu(v9ses) && (stat->extension[0] != '\0')) { - /* - * Hadlink support got added later to - * to the .u extension. So there can be - * server out there that doesn't support - * this even with .u extension. So check - * for non NULL stat->extension - */ - strlcpy(ext, stat->extension, sizeof(ext)); - /* HARDLINKCOUNT %u */ - sscanf(ext, "%13s %u", tag_name, &i_nlink); - if (!strncmp(tag_name, "HARDLINKCOUNT", 13)) - set_nlink(inode, i_nlink); - } - } - mode = p9mode2perm(v9ses, stat); - mode |= inode->i_mode & ~S_IALLUGO; - inode->i_mode = mode; - - if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE)) - v9fs_i_size_write(inode, stat->length); - /* not real number of blocks, but 512 byte ones ... */ - inode->i_blocks = (stat->length + 512 - 1) >> 9; - v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR; -} - -/** - * v9fs_qid2ino - convert qid into inode number - * @qid: qid to hash - * - * BUG: potential for inode number collisions? - */ - -ino_t v9fs_qid2ino(struct p9_qid *qid) -{ - u64 path = qid->path + 2; - ino_t i = 0; - - if (sizeof(ino_t) == sizeof(path)) - memcpy(&i, &path, sizeof(ino_t)); - else - i = (ino_t) (path ^ (path >> 32)); - - return i; -} - -/** - * v9fs_vfs_follow_link - follow a symlink path - * @dentry: dentry for symlink - * @cookie: place to pass the data to put_link() - */ - -static const char *v9fs_vfs_follow_link(struct dentry *dentry, void **cookie) -{ - struct v9fs_session_info *v9ses = v9fs_dentry2v9ses(dentry); - struct p9_fid *fid = v9fs_fid_lookup(dentry); - struct p9_wstat *st; - char *res; - - p9_debug(P9_DEBUG_VFS, "%pd\n", dentry); - - if (IS_ERR(fid)) - return ERR_CAST(fid); - - if (!v9fs_proto_dotu(v9ses)) - return ERR_PTR(-EBADF); - - st = p9_client_stat(fid); - if (IS_ERR(st)) - return ERR_CAST(st); - - if (!(st->mode & P9_DMSYMLINK)) { - p9stat_free(st); - kfree(st); - return ERR_PTR(-EINVAL); - } - res = st->extension; - st->extension = NULL; - if (strlen(res) >= PATH_MAX) - res[PATH_MAX - 1] = '\0'; - - p9stat_free(st); - kfree(st); - return *cookie = res; -} - -/** - * v9fs_vfs_mkspecial - create a special file - * @dir: inode to create special file in - * @dentry: dentry to create - * @perm: mode to create special file - * @extension: 9p2000.u format extension string representing special file - * - */ - -static int v9fs_vfs_mkspecial(struct inode *dir, struct dentry *dentry, - u32 perm, const char *extension) -{ - struct p9_fid *fid; - struct v9fs_session_info *v9ses; - - v9ses = v9fs_inode2v9ses(dir); - if (!v9fs_proto_dotu(v9ses)) { - p9_debug(P9_DEBUG_ERROR, "not extended\n"); - return -EPERM; - } - - fid = v9fs_create(v9ses, dir, dentry, (char *) extension, perm, - P9_OREAD); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - v9fs_invalidate_inode_attr(dir); - p9_client_clunk(fid); - return 0; -} - -/** - * v9fs_vfs_symlink - helper function to create symlinks - * @dir: directory inode containing symlink - * @dentry: dentry for symlink - * @symname: symlink data - * - * See Also: 9P2000.u RFC for more information - * - */ - -static int -v9fs_vfs_symlink(struct inode *dir, struct dentry *dentry, const char *symname) -{ - p9_debug(P9_DEBUG_VFS, " %lu,%pd,%s\n", - dir->i_ino, dentry, symname); - - return v9fs_vfs_mkspecial(dir, dentry, P9_DMSYMLINK, symname); -} - -#define U32_MAX_DIGITS 10 - -/** - * v9fs_vfs_link - create a hardlink - * @old_dentry: dentry for file to link to - * @dir: inode destination for new link - * @dentry: dentry for link - * - */ - -static int -v9fs_vfs_link(struct dentry *old_dentry, struct inode *dir, - struct dentry *dentry) -{ - int retval; - char name[1 + U32_MAX_DIGITS + 2]; /* sign + number + \n + \0 */ - struct p9_fid *oldfid; - - p9_debug(P9_DEBUG_VFS, " %lu,%pd,%pd\n", - dir->i_ino, dentry, old_dentry); - - oldfid = v9fs_fid_clone(old_dentry); - if (IS_ERR(oldfid)) - return PTR_ERR(oldfid); - - sprintf(name, "%d\n", oldfid->fid); - retval = v9fs_vfs_mkspecial(dir, dentry, P9_DMLINK, name); - if (!retval) { - v9fs_refresh_inode(oldfid, d_inode(old_dentry)); - v9fs_invalidate_inode_attr(dir); - } - p9_client_clunk(oldfid); - return retval; -} - -/** - * v9fs_vfs_mknod - create a special file - * @dir: inode destination for new link - * @dentry: dentry for file - * @mode: mode for creation - * @rdev: device associated with special file - * - */ - -static int -v9fs_vfs_mknod(struct inode *dir, struct dentry *dentry, umode_t mode, dev_t rdev) -{ - struct v9fs_session_info *v9ses = v9fs_inode2v9ses(dir); - int retval; - char name[2 + U32_MAX_DIGITS + 1 + U32_MAX_DIGITS + 1]; - u32 perm; - - p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %hx MAJOR: %u MINOR: %u\n", - dir->i_ino, dentry, mode, - MAJOR(rdev), MINOR(rdev)); - - /* build extension */ - if (S_ISBLK(mode)) - sprintf(name, "b %u %u", MAJOR(rdev), MINOR(rdev)); - else if (S_ISCHR(mode)) - sprintf(name, "c %u %u", MAJOR(rdev), MINOR(rdev)); - else - *name = 0; - - perm = unixmode2p9mode(v9ses, mode); - retval = v9fs_vfs_mkspecial(dir, dentry, perm, name); - - return retval; -} - -int v9fs_refresh_inode(struct p9_fid *fid, struct inode *inode) -{ - int umode; - dev_t rdev; - struct p9_wstat *st; - struct v9fs_session_info *v9ses; - unsigned int flags; - - v9ses = v9fs_inode2v9ses(inode); - st = p9_client_stat(fid); - if (IS_ERR(st)) - return PTR_ERR(st); - /* - * Don't update inode if the file type is different - */ - umode = p9mode2unixmode(v9ses, st, &rdev); - if ((inode->i_mode & S_IFMT) != (umode & S_IFMT)) - goto out; - - /* - * We don't want to refresh inode->i_size, - * because we may have cached data - */ - flags = (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) ? - V9FS_STAT2INODE_KEEP_ISIZE : 0; - v9fs_stat2inode(st, inode, inode->i_sb, flags); -out: - p9stat_free(st); - kfree(st); - return 0; -} - -static const struct inode_operations v9fs_dir_inode_operations_dotu = { - .create = v9fs_vfs_create, - .lookup = v9fs_vfs_lookup, - .atomic_open = v9fs_vfs_atomic_open, - .symlink = v9fs_vfs_symlink, - .link = v9fs_vfs_link, - .unlink = v9fs_vfs_unlink, - .mkdir = v9fs_vfs_mkdir, - .rmdir = v9fs_vfs_rmdir, - .mknod = v9fs_vfs_mknod, - .rename = v9fs_vfs_rename, - .getattr = v9fs_vfs_getattr, - .setattr = v9fs_vfs_setattr, -}; - -static const struct inode_operations v9fs_dir_inode_operations = { - .create = v9fs_vfs_create, - .lookup = v9fs_vfs_lookup, - .atomic_open = v9fs_vfs_atomic_open, - .unlink = v9fs_vfs_unlink, - .mkdir = v9fs_vfs_mkdir, - .rmdir = v9fs_vfs_rmdir, - .mknod = v9fs_vfs_mknod, - .rename = v9fs_vfs_rename, - .getattr = v9fs_vfs_getattr, - .setattr = v9fs_vfs_setattr, -}; - -static const struct inode_operations v9fs_file_inode_operations = { - .getattr = v9fs_vfs_getattr, - .setattr = v9fs_vfs_setattr, -}; - -static const struct inode_operations v9fs_symlink_inode_operations = { - .readlink = generic_readlink, - .follow_link = v9fs_vfs_follow_link, - .put_link = kfree_put_link, - .getattr = v9fs_vfs_getattr, - .setattr = v9fs_vfs_setattr, -}; - diff --git a/addons/9p/src/4.4.180/vfs_inode_dotl.c b/addons/9p/src/4.4.180/vfs_inode_dotl.c deleted file mode 100644 index 7ae67fcc..00000000 --- a/addons/9p/src/4.4.180/vfs_inode_dotl.c +++ /dev/null @@ -1,999 +0,0 @@ -/* - * linux/fs/9p/vfs_inode_dotl.c - * - * This file contains vfs inode ops for the 9P2000.L protocol. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" -#include "cache.h" -#include "xattr.h" -#include "acl.h" - -static int -v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, - dev_t rdev); - -/** - * v9fs_get_fsgid_for_create - Helper function to get the gid for creating a - * new file system object. This checks the S_ISGID to determine the owning - * group of the new file system object. - */ - -static kgid_t v9fs_get_fsgid_for_create(struct inode *dir_inode) -{ - BUG_ON(dir_inode == NULL); - - if (dir_inode->i_mode & S_ISGID) { - /* set_gid bit is set.*/ - return dir_inode->i_gid; - } - return current_fsgid(); -} - -static int v9fs_test_inode_dotl(struct inode *inode, void *data) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - struct p9_stat_dotl *st = (struct p9_stat_dotl *)data; - - /* don't match inode of different type */ - if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT)) - return 0; - - if (inode->i_generation != st->st_gen) - return 0; - - /* compare qid details */ - if (memcmp(&v9inode->qid.version, - &st->qid.version, sizeof(v9inode->qid.version))) - return 0; - - if (v9inode->qid.type != st->qid.type) - return 0; - - if (v9inode->qid.path != st->qid.path) - return 0; - return 1; -} - -/* Always get a new inode */ -static int v9fs_test_new_inode_dotl(struct inode *inode, void *data) -{ - return 0; -} - -static int v9fs_set_inode_dotl(struct inode *inode, void *data) -{ - struct v9fs_inode *v9inode = V9FS_I(inode); - struct p9_stat_dotl *st = (struct p9_stat_dotl *)data; - - memcpy(&v9inode->qid, &st->qid, sizeof(st->qid)); - inode->i_generation = st->st_gen; - return 0; -} - -static struct inode *v9fs_qid_iget_dotl(struct super_block *sb, - struct p9_qid *qid, - struct p9_fid *fid, - struct p9_stat_dotl *st, - int new) -{ - int retval; - unsigned long i_ino; - struct inode *inode; - struct v9fs_session_info *v9ses = sb->s_fs_info; - int (*test)(struct inode *, void *); - - if (new) - test = v9fs_test_new_inode_dotl; - else - test = v9fs_test_inode_dotl; - - i_ino = v9fs_qid2ino(qid); - inode = iget5_locked(sb, i_ino, test, v9fs_set_inode_dotl, st); - if (!inode) - return ERR_PTR(-ENOMEM); - if (!(inode->i_state & I_NEW)) - return inode; - /* - * initialize the inode with the stat info - * FIXME!! we may need support for stale inodes - * later. - */ - inode->i_ino = i_ino; - retval = v9fs_init_inode(v9ses, inode, - st->st_mode, new_decode_dev(st->st_rdev)); - if (retval) - goto error; - - v9fs_stat2inode_dotl(st, inode, 0); - v9fs_cache_inode_get_cookie(inode); - retval = v9fs_get_acl(inode, fid); - if (retval) - goto error; - - unlock_new_inode(inode); - return inode; -error: - iget_failed(inode); - return ERR_PTR(retval); - -} - -struct inode * -v9fs_inode_from_fid_dotl(struct v9fs_session_info *v9ses, struct p9_fid *fid, - struct super_block *sb, int new) -{ - struct p9_stat_dotl *st; - struct inode *inode = NULL; - - st = p9_client_getattr_dotl(fid, P9_STATS_BASIC | P9_STATS_GEN); - if (IS_ERR(st)) - return ERR_CAST(st); - - inode = v9fs_qid_iget_dotl(sb, &st->qid, fid, st, new); - kfree(st); - return inode; -} - -struct dotl_openflag_map { - int open_flag; - int dotl_flag; -}; - -static int v9fs_mapped_dotl_flags(int flags) -{ - int i; - int rflags = 0; - struct dotl_openflag_map dotl_oflag_map[] = { - { O_CREAT, P9_DOTL_CREATE }, - { O_EXCL, P9_DOTL_EXCL }, - { O_NOCTTY, P9_DOTL_NOCTTY }, - { O_APPEND, P9_DOTL_APPEND }, - { O_NONBLOCK, P9_DOTL_NONBLOCK }, - { O_DSYNC, P9_DOTL_DSYNC }, - { FASYNC, P9_DOTL_FASYNC }, - { O_DIRECT, P9_DOTL_DIRECT }, - { O_LARGEFILE, P9_DOTL_LARGEFILE }, - { O_DIRECTORY, P9_DOTL_DIRECTORY }, - { O_NOFOLLOW, P9_DOTL_NOFOLLOW }, - { O_NOATIME, P9_DOTL_NOATIME }, - { O_CLOEXEC, P9_DOTL_CLOEXEC }, - { O_SYNC, P9_DOTL_SYNC}, - }; - for (i = 0; i < ARRAY_SIZE(dotl_oflag_map); i++) { - if (flags & dotl_oflag_map[i].open_flag) - rflags |= dotl_oflag_map[i].dotl_flag; - } - return rflags; -} - -/** - * v9fs_open_to_dotl_flags- convert Linux specific open flags to - * plan 9 open flag. - * @flags: flags to convert - */ -int v9fs_open_to_dotl_flags(int flags) -{ - int rflags = 0; - - /* - * We have same bits for P9_DOTL_READONLY, P9_DOTL_WRONLY - * and P9_DOTL_NOACCESS - */ - rflags |= flags & O_ACCMODE; - rflags |= v9fs_mapped_dotl_flags(flags); - - return rflags; -} - -/** - * v9fs_vfs_create_dotl - VFS hook to create files for 9P2000.L protocol. - * @dir: directory inode that is being created - * @dentry: dentry that is being deleted - * @omode: create permissions - * - */ - -static int -v9fs_vfs_create_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, - bool excl) -{ - return v9fs_vfs_mknod_dotl(dir, dentry, omode, 0); -} - -static int -v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, - struct file *file, unsigned flags, umode_t omode, - int *opened) -{ - int err = 0; - kgid_t gid; - umode_t mode; - char *name = NULL; - struct p9_qid qid; - struct inode *inode; - struct p9_fid *fid = NULL; - struct v9fs_inode *v9inode; - struct p9_fid *dfid, *ofid, *inode_fid; - struct v9fs_session_info *v9ses; - struct posix_acl *pacl = NULL, *dacl = NULL; - struct dentry *res = NULL; - - if (d_unhashed(dentry)) { - res = v9fs_vfs_lookup(dir, dentry, 0); - if (IS_ERR(res)) - return PTR_ERR(res); - - if (res) - dentry = res; - } - - /* Only creates */ - if (!(flags & O_CREAT) || d_really_is_positive(dentry)) - return finish_no_open(file, res); - - v9ses = v9fs_inode2v9ses(dir); - - name = (char *) dentry->d_name.name; - p9_debug(P9_DEBUG_VFS, "name:%s flags:0x%x mode:0x%hx\n", - name, flags, omode); - - dfid = v9fs_fid_lookup(dentry->d_parent); - if (IS_ERR(dfid)) { - err = PTR_ERR(dfid); - p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); - goto out; - } - - /* clone a fid to use for creation */ - ofid = p9_client_walk(dfid, 0, NULL, 1); - if (IS_ERR(ofid)) { - err = PTR_ERR(ofid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); - goto out; - } - - gid = v9fs_get_fsgid_for_create(dir); - - mode = omode; - /* Update mode based on ACL value */ - err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); - if (err) { - p9_debug(P9_DEBUG_VFS, "Failed to get acl values in creat %d\n", - err); - goto error; - } - err = p9_client_create_dotl(ofid, name, v9fs_open_to_dotl_flags(flags), - mode, gid, &qid); - if (err < 0) { - p9_debug(P9_DEBUG_VFS, "p9_client_open_dotl failed in creat %d\n", - err); - goto error; - } - v9fs_invalidate_inode_attr(dir); - - /* instantiate inode and assign the unopened fid to the dentry */ - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", err); - fid = NULL; - goto error; - } - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err); - goto error; - } - /* Now set the ACL based on the default value */ - v9fs_set_create_acl(inode, fid, dacl, pacl); - - v9fs_fid_add(dentry, fid); - d_instantiate(dentry, inode); - - v9inode = V9FS_I(inode); - mutex_lock(&v9inode->v_mutex); - if ((v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) && - !v9inode->writeback_fid && - ((flags & O_ACCMODE) != O_RDONLY)) { - /* - * clone a fid and add it to writeback_fid - * we do it during open time instead of - * page dirty time via write_begin/page_mkwrite - * because we want write after unlink usecase - * to work. - */ - inode_fid = v9fs_writeback_fid(dentry); - if (IS_ERR(inode_fid)) { - err = PTR_ERR(inode_fid); - mutex_unlock(&v9inode->v_mutex); - goto err_clunk_old_fid; - } - v9inode->writeback_fid = (void *) inode_fid; - } - mutex_unlock(&v9inode->v_mutex); - /* Since we are opening a file, assign the open fid to the file */ - err = finish_open(file, dentry, generic_file_open, opened); - if (err) - goto err_clunk_old_fid; - file->private_data = ofid; - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) - v9fs_cache_inode_set_cookie(inode, file); - *opened |= FILE_CREATED; -out: - v9fs_put_acl(dacl, pacl); - dput(res); - return err; - -error: - if (fid) - p9_client_clunk(fid); -err_clunk_old_fid: - if (ofid) - p9_client_clunk(ofid); - goto out; -} - -/** - * v9fs_vfs_mkdir_dotl - VFS mkdir hook to create a directory - * @dir: inode that is being unlinked - * @dentry: dentry that is being unlinked - * @omode: mode for new directory - * - */ - -static int v9fs_vfs_mkdir_dotl(struct inode *dir, - struct dentry *dentry, umode_t omode) -{ - int err; - struct v9fs_session_info *v9ses; - struct p9_fid *fid = NULL, *dfid = NULL; - kgid_t gid; - char *name; - umode_t mode; - struct inode *inode; - struct p9_qid qid; - struct dentry *dir_dentry; - struct posix_acl *dacl = NULL, *pacl = NULL; - - p9_debug(P9_DEBUG_VFS, "name %pd\n", dentry); - err = 0; - v9ses = v9fs_inode2v9ses(dir); - - omode |= S_IFDIR; - if (dir->i_mode & S_ISGID) - omode |= S_ISGID; - - dir_dentry = dentry->d_parent; - dfid = v9fs_fid_lookup(dir_dentry); - if (IS_ERR(dfid)) { - err = PTR_ERR(dfid); - p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); - dfid = NULL; - goto error; - } - - gid = v9fs_get_fsgid_for_create(dir); - mode = omode; - /* Update mode based on ACL value */ - err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); - if (err) { - p9_debug(P9_DEBUG_VFS, "Failed to get acl values in mkdir %d\n", - err); - goto error; - } - name = (char *) dentry->d_name.name; - err = p9_client_mkdir_dotl(dfid, name, mode, gid, &qid); - if (err < 0) - goto error; - - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", - err); - fid = NULL; - goto error; - } - - /* instantiate inode and assign the unopened fid to the dentry */ - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", - err); - goto error; - } - v9fs_fid_add(dentry, fid); - v9fs_set_create_acl(inode, fid, dacl, pacl); - d_instantiate(dentry, inode); - fid = NULL; - err = 0; - } else { - /* - * Not in cached mode. No need to populate - * inode with stat. We need to get an inode - * so that we can set the acl with dentry - */ - inode = v9fs_get_inode(dir->i_sb, mode, 0); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto error; - } - v9fs_set_create_acl(inode, fid, dacl, pacl); - d_instantiate(dentry, inode); - } - inc_nlink(dir); - v9fs_invalidate_inode_attr(dir); -error: - if (fid) - p9_client_clunk(fid); - v9fs_put_acl(dacl, pacl); - return err; -} - -static int -v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry, - struct kstat *stat) -{ - struct v9fs_session_info *v9ses; - struct p9_fid *fid; - struct p9_stat_dotl *st; - - p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry); - v9ses = v9fs_dentry2v9ses(dentry); - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - generic_fillattr(d_inode(dentry), stat); - return 0; - } - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - /* Ask for all the fields in stat structure. Server will return - * whatever it supports - */ - - st = p9_client_getattr_dotl(fid, P9_STATS_ALL); - if (IS_ERR(st)) - return PTR_ERR(st); - - v9fs_stat2inode_dotl(st, d_inode(dentry), 0); - generic_fillattr(d_inode(dentry), stat); - /* Change block size to what the server returned */ - stat->blksize = st->st_blksize; - - kfree(st); - return 0; -} - -/* - * Attribute flags. - */ -#define P9_ATTR_MODE (1 << 0) -#define P9_ATTR_UID (1 << 1) -#define P9_ATTR_GID (1 << 2) -#define P9_ATTR_SIZE (1 << 3) -#define P9_ATTR_ATIME (1 << 4) -#define P9_ATTR_MTIME (1 << 5) -#define P9_ATTR_CTIME (1 << 6) -#define P9_ATTR_ATIME_SET (1 << 7) -#define P9_ATTR_MTIME_SET (1 << 8) - -struct dotl_iattr_map { - int iattr_valid; - int p9_iattr_valid; -}; - -static int v9fs_mapped_iattr_valid(int iattr_valid) -{ - int i; - int p9_iattr_valid = 0; - struct dotl_iattr_map dotl_iattr_map[] = { - { ATTR_MODE, P9_ATTR_MODE }, - { ATTR_UID, P9_ATTR_UID }, - { ATTR_GID, P9_ATTR_GID }, - { ATTR_SIZE, P9_ATTR_SIZE }, - { ATTR_ATIME, P9_ATTR_ATIME }, - { ATTR_MTIME, P9_ATTR_MTIME }, - { ATTR_CTIME, P9_ATTR_CTIME }, - { ATTR_ATIME_SET, P9_ATTR_ATIME_SET }, - { ATTR_MTIME_SET, P9_ATTR_MTIME_SET }, - }; - for (i = 0; i < ARRAY_SIZE(dotl_iattr_map); i++) { - if (iattr_valid & dotl_iattr_map[i].iattr_valid) - p9_iattr_valid |= dotl_iattr_map[i].p9_iattr_valid; - } - return p9_iattr_valid; -} - -/** - * v9fs_vfs_setattr_dotl - set file metadata - * @dentry: file whose metadata to set - * @iattr: metadata assignment structure - * - */ - -int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) -{ - int retval; - struct p9_fid *fid; - struct p9_iattr_dotl p9attr; - struct inode *inode = d_inode(dentry); - - p9_debug(P9_DEBUG_VFS, "\n"); - - retval = inode_change_ok(inode, iattr); - if (retval) - return retval; - - p9attr.valid = v9fs_mapped_iattr_valid(iattr->ia_valid); - p9attr.mode = iattr->ia_mode; - p9attr.uid = iattr->ia_uid; - p9attr.gid = iattr->ia_gid; - p9attr.size = iattr->ia_size; - p9attr.atime_sec = iattr->ia_atime.tv_sec; - p9attr.atime_nsec = iattr->ia_atime.tv_nsec; - p9attr.mtime_sec = iattr->ia_mtime.tv_sec; - p9attr.mtime_nsec = iattr->ia_mtime.tv_nsec; - - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - /* Write all dirty data */ - if (S_ISREG(inode->i_mode)) - filemap_write_and_wait(inode->i_mapping); - - retval = p9_client_setattr(fid, &p9attr); - if (retval < 0) - return retval; - - if ((iattr->ia_valid & ATTR_SIZE) && - iattr->ia_size != i_size_read(inode)) - truncate_setsize(inode, iattr->ia_size); - - v9fs_invalidate_inode_attr(inode); - setattr_copy(inode, iattr); - mark_inode_dirty(inode); - if (iattr->ia_valid & ATTR_MODE) { - /* We also want to update ACL when we update mode bits */ - retval = v9fs_acl_chmod(inode, fid); - if (retval < 0) - return retval; - } - return 0; -} - -/** - * v9fs_stat2inode_dotl - populate an inode structure with stat info - * @stat: stat structure - * @inode: inode to populate - * @flags: ctrl flags (e.g. V9FS_STAT2INODE_KEEP_ISIZE) - * - */ - -void -v9fs_stat2inode_dotl(struct p9_stat_dotl *stat, struct inode *inode, - unsigned int flags) -{ - umode_t mode; - struct v9fs_inode *v9inode = V9FS_I(inode); - - if ((stat->st_result_mask & P9_STATS_BASIC) == P9_STATS_BASIC) { - inode->i_atime.tv_sec = stat->st_atime_sec; - inode->i_atime.tv_nsec = stat->st_atime_nsec; - inode->i_mtime.tv_sec = stat->st_mtime_sec; - inode->i_mtime.tv_nsec = stat->st_mtime_nsec; - inode->i_ctime.tv_sec = stat->st_ctime_sec; - inode->i_ctime.tv_nsec = stat->st_ctime_nsec; - inode->i_uid = stat->st_uid; - inode->i_gid = stat->st_gid; - set_nlink(inode, stat->st_nlink); - - mode = stat->st_mode & S_IALLUGO; - mode |= inode->i_mode & ~S_IALLUGO; - inode->i_mode = mode; - - if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE)) - v9fs_i_size_write(inode, stat->st_size); - inode->i_blocks = stat->st_blocks; - } else { - if (stat->st_result_mask & P9_STATS_ATIME) { - inode->i_atime.tv_sec = stat->st_atime_sec; - inode->i_atime.tv_nsec = stat->st_atime_nsec; - } - if (stat->st_result_mask & P9_STATS_MTIME) { - inode->i_mtime.tv_sec = stat->st_mtime_sec; - inode->i_mtime.tv_nsec = stat->st_mtime_nsec; - } - if (stat->st_result_mask & P9_STATS_CTIME) { - inode->i_ctime.tv_sec = stat->st_ctime_sec; - inode->i_ctime.tv_nsec = stat->st_ctime_nsec; - } - if (stat->st_result_mask & P9_STATS_UID) - inode->i_uid = stat->st_uid; - if (stat->st_result_mask & P9_STATS_GID) - inode->i_gid = stat->st_gid; - if (stat->st_result_mask & P9_STATS_NLINK) - set_nlink(inode, stat->st_nlink); - if (stat->st_result_mask & P9_STATS_MODE) { - inode->i_mode = stat->st_mode; - if ((S_ISBLK(inode->i_mode)) || - (S_ISCHR(inode->i_mode))) - init_special_inode(inode, inode->i_mode, - inode->i_rdev); - } - if (stat->st_result_mask & P9_STATS_RDEV) - inode->i_rdev = new_decode_dev(stat->st_rdev); - if (!(flags & V9FS_STAT2INODE_KEEP_ISIZE) && - stat->st_result_mask & P9_STATS_SIZE) - v9fs_i_size_write(inode, stat->st_size); - if (stat->st_result_mask & P9_STATS_BLOCKS) - inode->i_blocks = stat->st_blocks; - } - if (stat->st_result_mask & P9_STATS_GEN) - inode->i_generation = stat->st_gen; - - /* Currently we don't support P9_STATS_BTIME and P9_STATS_DATA_VERSION - * because the inode structure does not have fields for them. - */ - v9inode->cache_validity &= ~V9FS_INO_INVALID_ATTR; -} - -static int -v9fs_vfs_symlink_dotl(struct inode *dir, struct dentry *dentry, - const char *symname) -{ - int err; - kgid_t gid; - char *name; - struct p9_qid qid; - struct inode *inode; - struct p9_fid *dfid; - struct p9_fid *fid = NULL; - struct v9fs_session_info *v9ses; - - name = (char *) dentry->d_name.name; - p9_debug(P9_DEBUG_VFS, "%lu,%s,%s\n", dir->i_ino, name, symname); - v9ses = v9fs_inode2v9ses(dir); - - dfid = v9fs_fid_lookup(dentry->d_parent); - if (IS_ERR(dfid)) { - err = PTR_ERR(dfid); - p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); - return err; - } - - gid = v9fs_get_fsgid_for_create(dir); - - /* Server doesn't alter fid on TSYMLINK. Hence no need to clone it. */ - err = p9_client_symlink(dfid, name, (char *)symname, gid, &qid); - - if (err < 0) { - p9_debug(P9_DEBUG_VFS, "p9_client_symlink failed %d\n", err); - goto error; - } - - v9fs_invalidate_inode_attr(dir); - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - /* Now walk from the parent so we can get an unopened fid. */ - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", - err); - fid = NULL; - goto error; - } - - /* instantiate inode and assign the unopened fid to dentry */ - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", - err); - goto error; - } - v9fs_fid_add(dentry, fid); - d_instantiate(dentry, inode); - fid = NULL; - err = 0; - } else { - /* Not in cached mode. No need to populate inode with stat */ - inode = v9fs_get_inode(dir->i_sb, S_IFLNK, 0); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto error; - } - d_instantiate(dentry, inode); - } - -error: - if (fid) - p9_client_clunk(fid); - - return err; -} - -/** - * v9fs_vfs_link_dotl - create a hardlink for dotl - * @old_dentry: dentry for file to link to - * @dir: inode destination for new link - * @dentry: dentry for link - * - */ - -static int -v9fs_vfs_link_dotl(struct dentry *old_dentry, struct inode *dir, - struct dentry *dentry) -{ - int err; - struct dentry *dir_dentry; - struct p9_fid *dfid, *oldfid; - struct v9fs_session_info *v9ses; - - p9_debug(P9_DEBUG_VFS, "dir ino: %lu, old_name: %pd, new_name: %pd\n", - dir->i_ino, old_dentry, dentry); - - v9ses = v9fs_inode2v9ses(dir); - dir_dentry = dentry->d_parent; - dfid = v9fs_fid_lookup(dir_dentry); - if (IS_ERR(dfid)) - return PTR_ERR(dfid); - - oldfid = v9fs_fid_lookup(old_dentry); - if (IS_ERR(oldfid)) - return PTR_ERR(oldfid); - - err = p9_client_link(dfid, oldfid, (char *)dentry->d_name.name); - - if (err < 0) { - p9_debug(P9_DEBUG_VFS, "p9_client_link failed %d\n", err); - return err; - } - - v9fs_invalidate_inode_attr(dir); - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - /* Get the latest stat info from server. */ - struct p9_fid *fid; - fid = v9fs_fid_lookup(old_dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - v9fs_refresh_inode_dotl(fid, d_inode(old_dentry)); - } - ihold(d_inode(old_dentry)); - d_instantiate(dentry, d_inode(old_dentry)); - - return err; -} - -/** - * v9fs_vfs_mknod_dotl - create a special file - * @dir: inode destination for new link - * @dentry: dentry for file - * @omode: mode for creation - * @rdev: device associated with special file - * - */ -static int -v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, - dev_t rdev) -{ - int err; - kgid_t gid; - char *name; - umode_t mode; - struct v9fs_session_info *v9ses; - struct p9_fid *fid = NULL, *dfid = NULL; - struct inode *inode; - struct p9_qid qid; - struct dentry *dir_dentry; - struct posix_acl *dacl = NULL, *pacl = NULL; - - p9_debug(P9_DEBUG_VFS, " %lu,%pd mode: %hx MAJOR: %u MINOR: %u\n", - dir->i_ino, dentry, omode, - MAJOR(rdev), MINOR(rdev)); - - v9ses = v9fs_inode2v9ses(dir); - dir_dentry = dentry->d_parent; - dfid = v9fs_fid_lookup(dir_dentry); - if (IS_ERR(dfid)) { - err = PTR_ERR(dfid); - p9_debug(P9_DEBUG_VFS, "fid lookup failed %d\n", err); - dfid = NULL; - goto error; - } - - gid = v9fs_get_fsgid_for_create(dir); - mode = omode; - /* Update mode based on ACL value */ - err = v9fs_acl_mode(dir, &mode, &dacl, &pacl); - if (err) { - p9_debug(P9_DEBUG_VFS, "Failed to get acl values in mknod %d\n", - err); - goto error; - } - name = (char *) dentry->d_name.name; - - err = p9_client_mknod_dotl(dfid, name, mode, rdev, gid, &qid); - if (err < 0) - goto error; - - v9fs_invalidate_inode_attr(dir); - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", - err); - fid = NULL; - goto error; - } - - /* instantiate inode and assign the unopened fid to the dentry */ - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", - err); - goto error; - } - v9fs_set_create_acl(inode, fid, dacl, pacl); - v9fs_fid_add(dentry, fid); - d_instantiate(dentry, inode); - fid = NULL; - err = 0; - } else { - /* - * Not in cached mode. No need to populate inode with stat. - * socket syscall returns a fd, so we need instantiate - */ - inode = v9fs_get_inode(dir->i_sb, mode, rdev); - if (IS_ERR(inode)) { - err = PTR_ERR(inode); - goto error; - } - v9fs_set_create_acl(inode, fid, dacl, pacl); - d_instantiate(dentry, inode); - } -error: - if (fid) - p9_client_clunk(fid); - v9fs_put_acl(dacl, pacl); - return err; -} - -/** - * v9fs_vfs_follow_link_dotl - follow a symlink path - * @dentry: dentry for symlink - * @cookie: place to pass the data to put_link() - */ - -static const char * -v9fs_vfs_follow_link_dotl(struct dentry *dentry, void **cookie) -{ - struct p9_fid *fid = v9fs_fid_lookup(dentry); - char *target; - int retval; - - p9_debug(P9_DEBUG_VFS, "%pd\n", dentry); - - if (IS_ERR(fid)) - return ERR_CAST(fid); - retval = p9_client_readlink(fid, &target); - if (retval) - return ERR_PTR(retval); - return *cookie = target; -} - -int v9fs_refresh_inode_dotl(struct p9_fid *fid, struct inode *inode) -{ - struct p9_stat_dotl *st; - struct v9fs_session_info *v9ses; - unsigned int flags; - - v9ses = v9fs_inode2v9ses(inode); - st = p9_client_getattr_dotl(fid, P9_STATS_ALL); - if (IS_ERR(st)) - return PTR_ERR(st); - /* - * Don't update inode if the file type is different - */ - if ((inode->i_mode & S_IFMT) != (st->st_mode & S_IFMT)) - goto out; - - /* - * We don't want to refresh inode->i_size, - * because we may have cached data - */ - flags = (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) ? - V9FS_STAT2INODE_KEEP_ISIZE : 0; - v9fs_stat2inode_dotl(st, inode, flags); -out: - kfree(st); - return 0; -} - -const struct inode_operations v9fs_dir_inode_operations_dotl = { - .create = v9fs_vfs_create_dotl, - .atomic_open = v9fs_vfs_atomic_open_dotl, - .lookup = v9fs_vfs_lookup, - .link = v9fs_vfs_link_dotl, - .symlink = v9fs_vfs_symlink_dotl, - .unlink = v9fs_vfs_unlink, - .mkdir = v9fs_vfs_mkdir_dotl, - .rmdir = v9fs_vfs_rmdir, - .mknod = v9fs_vfs_mknod_dotl, - .rename = v9fs_vfs_rename, - .getattr = v9fs_vfs_getattr_dotl, - .setattr = v9fs_vfs_setattr_dotl, - .setxattr = generic_setxattr, - .getxattr = generic_getxattr, - .removexattr = generic_removexattr, - .listxattr = v9fs_listxattr, - .get_acl = v9fs_iop_get_acl, -}; - -const struct inode_operations v9fs_file_inode_operations_dotl = { - .getattr = v9fs_vfs_getattr_dotl, - .setattr = v9fs_vfs_setattr_dotl, - .setxattr = generic_setxattr, - .getxattr = generic_getxattr, - .removexattr = generic_removexattr, - .listxattr = v9fs_listxattr, - .get_acl = v9fs_iop_get_acl, -}; - -const struct inode_operations v9fs_symlink_inode_operations_dotl = { - .readlink = generic_readlink, - .follow_link = v9fs_vfs_follow_link_dotl, - .put_link = kfree_put_link, - .getattr = v9fs_vfs_getattr_dotl, - .setattr = v9fs_vfs_setattr_dotl, - .setxattr = generic_setxattr, - .getxattr = generic_getxattr, - .removexattr = generic_removexattr, - .listxattr = v9fs_listxattr, -}; diff --git a/addons/9p/src/4.4.180/vfs_super.c b/addons/9p/src/4.4.180/vfs_super.c deleted file mode 100644 index ccf935d9..00000000 --- a/addons/9p/src/4.4.180/vfs_super.c +++ /dev/null @@ -1,366 +0,0 @@ -/* - * linux/fs/9p/vfs_super.c - * - * This file contians superblock ops for 9P2000. It is intended that - * you mount this file system on directories. - * - * Copyright (C) 2004 by Eric Van Hensbergen - * Copyright (C) 2002 by Ron Minnich - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to: - * Free Software Foundation - * 51 Franklin Street, Fifth Floor - * Boston, MA 02111-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "v9fs.h" -#include "v9fs_vfs.h" -#include "fid.h" -#include "xattr.h" -#include "acl.h" - -static const struct super_operations v9fs_super_ops, v9fs_super_ops_dotl; - -/** - * v9fs_set_super - set the superblock - * @s: super block - * @data: file system specific data - * - */ - -static int v9fs_set_super(struct super_block *s, void *data) -{ - s->s_fs_info = data; - return set_anon_super(s, data); -} - -/** - * v9fs_fill_super - populate superblock with info - * @sb: superblock - * @v9ses: session information - * @flags: flags propagated from v9fs_mount() - * - */ - -static void -v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, - int flags, void *data) -{ - sb->s_maxbytes = MAX_LFS_FILESIZE; - sb->s_blocksize_bits = fls(v9ses->maxdata - 1); - sb->s_blocksize = 1 << sb->s_blocksize_bits; - sb->s_magic = V9FS_MAGIC; - if (v9fs_proto_dotl(v9ses)) { - sb->s_op = &v9fs_super_ops_dotl; - sb->s_xattr = v9fs_xattr_handlers; - } else - sb->s_op = &v9fs_super_ops; - sb->s_bdi = &v9ses->bdi; - if (v9ses->cache) - sb->s_bdi->ra_pages = (VM_MAX_READAHEAD * 1024)/PAGE_CACHE_SIZE; - - sb->s_flags |= MS_ACTIVE | MS_DIRSYNC | MS_NOATIME; - if (!v9ses->cache) - sb->s_flags |= MS_SYNCHRONOUS; - -#ifdef CONFIG_9P_FS_POSIX_ACL - if ((v9ses->flags & V9FS_ACL_MASK) == V9FS_POSIX_ACL) - sb->s_flags |= MS_POSIXACL; -#endif - - save_mount_options(sb, data); -} - -/** - * v9fs_mount - mount a superblock - * @fs_type: file system type - * @flags: mount flags - * @dev_name: device name that was mounted - * @data: mount options - * - */ - -static struct dentry *v9fs_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) -{ - struct super_block *sb = NULL; - struct inode *inode = NULL; - struct dentry *root = NULL; - struct v9fs_session_info *v9ses = NULL; - umode_t mode = S_IRWXUGO | S_ISVTX; - struct p9_fid *fid; - int retval = 0; - - p9_debug(P9_DEBUG_VFS, "\n"); - - v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); - if (!v9ses) - return ERR_PTR(-ENOMEM); - - fid = v9fs_session_init(v9ses, dev_name, data); - if (IS_ERR(fid)) { - retval = PTR_ERR(fid); - goto free_session; - } - - sb = sget(fs_type, NULL, v9fs_set_super, flags, v9ses); - if (IS_ERR(sb)) { - retval = PTR_ERR(sb); - goto clunk_fid; - } - v9fs_fill_super(sb, v9ses, flags, data); - - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) - sb->s_d_op = &v9fs_cached_dentry_operations; - else - sb->s_d_op = &v9fs_dentry_operations; - - inode = v9fs_get_inode(sb, S_IFDIR | mode, 0); - if (IS_ERR(inode)) { - retval = PTR_ERR(inode); - goto release_sb; - } - - root = d_make_root(inode); - if (!root) { - retval = -ENOMEM; - goto release_sb; - } - sb->s_root = root; - if (v9fs_proto_dotl(v9ses)) { - struct p9_stat_dotl *st = NULL; - st = p9_client_getattr_dotl(fid, P9_STATS_BASIC); - if (IS_ERR(st)) { - retval = PTR_ERR(st); - goto release_sb; - } - d_inode(root)->i_ino = v9fs_qid2ino(&st->qid); - v9fs_stat2inode_dotl(st, d_inode(root), 0); - kfree(st); - } else { - struct p9_wstat *st = NULL; - st = p9_client_stat(fid); - if (IS_ERR(st)) { - retval = PTR_ERR(st); - goto release_sb; - } - - d_inode(root)->i_ino = v9fs_qid2ino(&st->qid); - v9fs_stat2inode(st, d_inode(root), sb, 0); - - p9stat_free(st); - kfree(st); - } - retval = v9fs_get_acl(inode, fid); - if (retval) - goto release_sb; - v9fs_fid_add(root, fid); - - p9_debug(P9_DEBUG_VFS, " simple set mount, return 0\n"); - return dget(sb->s_root); - -clunk_fid: - p9_client_clunk(fid); - v9fs_session_close(v9ses); -free_session: - kfree(v9ses); - return ERR_PTR(retval); - -release_sb: - /* - * we will do the session_close and root dentry release - * in the below call. But we need to clunk fid, because we haven't - * attached the fid to dentry so it won't get clunked - * automatically. - */ - p9_client_clunk(fid); - deactivate_locked_super(sb); - return ERR_PTR(retval); -} - -/** - * v9fs_kill_super - Kill Superblock - * @s: superblock - * - */ - -static void v9fs_kill_super(struct super_block *s) -{ - struct v9fs_session_info *v9ses = s->s_fs_info; - - p9_debug(P9_DEBUG_VFS, " %p\n", s); - - kill_anon_super(s); - - v9fs_session_cancel(v9ses); - v9fs_session_close(v9ses); - kfree(v9ses); - s->s_fs_info = NULL; - p9_debug(P9_DEBUG_VFS, "exiting kill_super\n"); -} - -static void -v9fs_umount_begin(struct super_block *sb) -{ - struct v9fs_session_info *v9ses; - - v9ses = sb->s_fs_info; - v9fs_session_begin_cancel(v9ses); -} - -static int v9fs_statfs(struct dentry *dentry, struct kstatfs *buf) -{ - struct v9fs_session_info *v9ses; - struct p9_fid *fid; - struct p9_rstatfs rs; - int res; - - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) { - res = PTR_ERR(fid); - goto done; - } - - v9ses = v9fs_dentry2v9ses(dentry); - if (v9fs_proto_dotl(v9ses)) { - res = p9_client_statfs(fid, &rs); - if (res == 0) { - buf->f_type = rs.type; - buf->f_bsize = rs.bsize; - buf->f_blocks = rs.blocks; - buf->f_bfree = rs.bfree; - buf->f_bavail = rs.bavail; - buf->f_files = rs.files; - buf->f_ffree = rs.ffree; - buf->f_fsid.val[0] = rs.fsid & 0xFFFFFFFFUL; - buf->f_fsid.val[1] = (rs.fsid >> 32) & 0xFFFFFFFFUL; - buf->f_namelen = rs.namelen; - } - if (res != -ENOSYS) - goto done; - } - res = simple_statfs(dentry, buf); -done: - return res; -} - -static int v9fs_drop_inode(struct inode *inode) -{ - struct v9fs_session_info *v9ses; - v9ses = v9fs_inode2v9ses(inode); - if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) - return generic_drop_inode(inode); - /* - * in case of non cached mode always drop the - * the inode because we want the inode attribute - * to always match that on the server. - */ - return 1; -} - -static int v9fs_write_inode(struct inode *inode, - struct writeback_control *wbc) -{ - int ret; - struct p9_wstat wstat; - struct v9fs_inode *v9inode; - /* - * send an fsync request to server irrespective of - * wbc->sync_mode. - */ - p9_debug(P9_DEBUG_VFS, "%s: inode %p\n", __func__, inode); - v9inode = V9FS_I(inode); - if (!v9inode->writeback_fid) - return 0; - v9fs_blank_wstat(&wstat); - - ret = p9_client_wstat(v9inode->writeback_fid, &wstat); - if (ret < 0) { - __mark_inode_dirty(inode, I_DIRTY_DATASYNC); - return ret; - } - return 0; -} - -static int v9fs_write_inode_dotl(struct inode *inode, - struct writeback_control *wbc) -{ - int ret; - struct v9fs_inode *v9inode; - /* - * send an fsync request to server irrespective of - * wbc->sync_mode. - */ - v9inode = V9FS_I(inode); - p9_debug(P9_DEBUG_VFS, "%s: inode %p, writeback_fid %p\n", - __func__, inode, v9inode->writeback_fid); - if (!v9inode->writeback_fid) - return 0; - - ret = p9_client_fsync(v9inode->writeback_fid, 0); - if (ret < 0) { - __mark_inode_dirty(inode, I_DIRTY_DATASYNC); - return ret; - } - return 0; -} - -static const struct super_operations v9fs_super_ops = { - .alloc_inode = v9fs_alloc_inode, - .destroy_inode = v9fs_destroy_inode, - .statfs = simple_statfs, - .evict_inode = v9fs_evict_inode, - .show_options = generic_show_options, - .umount_begin = v9fs_umount_begin, - .write_inode = v9fs_write_inode, -}; - -static const struct super_operations v9fs_super_ops_dotl = { - .alloc_inode = v9fs_alloc_inode, - .destroy_inode = v9fs_destroy_inode, - .statfs = v9fs_statfs, - .drop_inode = v9fs_drop_inode, - .evict_inode = v9fs_evict_inode, - .show_options = generic_show_options, - .umount_begin = v9fs_umount_begin, - .write_inode = v9fs_write_inode_dotl, -}; - -struct file_system_type v9fs_fs_type = { - .name = "9p", - .mount = v9fs_mount, - .kill_sb = v9fs_kill_super, - .owner = THIS_MODULE, - .fs_flags = FS_RENAME_DOES_D_MOVE, -}; -MODULE_ALIAS_FS("9p"); diff --git a/addons/9p/src/4.4.180/xattr.c b/addons/9p/src/4.4.180/xattr.c deleted file mode 100644 index f35168ce..00000000 --- a/addons/9p/src/4.4.180/xattr.c +++ /dev/null @@ -1,195 +0,0 @@ -/* - * Copyright IBM Corporation, 2010 - * Author Aneesh Kumar K.V - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ - -#include -#include -#include -#include -#include -#include - -#include "fid.h" -#include "xattr.h" - -ssize_t v9fs_fid_xattr_get(struct p9_fid *fid, const char *name, - void *buffer, size_t buffer_size) -{ - ssize_t retval; - u64 attr_size; - struct p9_fid *attr_fid; - struct kvec kvec = {.iov_base = buffer, .iov_len = buffer_size}; - struct iov_iter to; - int err; - - iov_iter_kvec(&to, READ | ITER_KVEC, &kvec, 1, buffer_size); - - attr_fid = p9_client_xattrwalk(fid, name, &attr_size); - if (IS_ERR(attr_fid)) { - retval = PTR_ERR(attr_fid); - p9_debug(P9_DEBUG_VFS, "p9_client_attrwalk failed %zd\n", - retval); - return retval; - } - if (attr_size > buffer_size) { - if (!buffer_size) /* request to get the attr_size */ - retval = attr_size; - else - retval = -ERANGE; - } else { - iov_iter_truncate(&to, attr_size); - retval = p9_client_read(attr_fid, 0, &to, &err); - if (err) - retval = err; - } - p9_client_clunk(attr_fid); - return retval; -} - - -/* - * v9fs_xattr_get() - * - * Copy an extended attribute into the buffer - * provided, or compute the buffer size required. - * Buffer is NULL to compute the size of the buffer required. - * - * Returns a negative error number on failure, or the number of bytes - * used / required on success. - */ -ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name, - void *buffer, size_t buffer_size) -{ - struct p9_fid *fid; - - p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu\n", - name, buffer_size); - fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - return v9fs_fid_xattr_get(fid, name, buffer, buffer_size); -} - -/* - * v9fs_xattr_set() - * - * Create, replace or remove an extended attribute for this inode. Buffer - * is NULL to remove an existing extended attribute, and non-NULL to - * either replace an existing extended attribute, or create a new extended - * attribute. The flags XATTR_REPLACE and XATTR_CREATE - * specify that an extended attribute must exist and must not exist - * previous to the call, respectively. - * - * Returns 0, or a negative error number on failure. - */ -int v9fs_xattr_set(struct dentry *dentry, const char *name, - const void *value, size_t value_len, int flags) -{ - struct p9_fid *fid = v9fs_fid_lookup(dentry); - if (IS_ERR(fid)) - return PTR_ERR(fid); - return v9fs_fid_xattr_set(fid, name, value, value_len, flags); -} - -int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, - const void *value, size_t value_len, int flags) -{ - struct kvec kvec = {.iov_base = (void *)value, .iov_len = value_len}; - struct iov_iter from; - int retval, err; - - iov_iter_kvec(&from, WRITE | ITER_KVEC, &kvec, 1, value_len); - - p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", - name, value_len, flags); - - /* Clone it */ - fid = p9_client_walk(fid, 0, NULL, 1); - if (IS_ERR(fid)) - return PTR_ERR(fid); - - /* - * On success fid points to xattr - */ - retval = p9_client_xattrcreate(fid, name, value_len, flags); - if (retval < 0) - p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n", - retval); - else - p9_client_write(fid, 0, &from, &retval); - err = p9_client_clunk(fid); - if (!retval && err) - retval = err; - return retval; -} - -ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) -{ - return v9fs_xattr_get(dentry, NULL, buffer, buffer_size); -} - -static int v9fs_xattr_handler_get(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - void *buffer, size_t size) -{ - const char *full_name = xattr_full_name(handler, name); - - if (strcmp(name, "") == 0) - return -EINVAL; - return v9fs_xattr_get(dentry, full_name, buffer, size); -} - -static int v9fs_xattr_handler_set(const struct xattr_handler *handler, - struct dentry *dentry, const char *name, - const void *value, size_t size, int flags) -{ - const char *full_name = xattr_full_name(handler, name); - - if (strcmp(name, "") == 0) - return -EINVAL; - return v9fs_xattr_set(dentry, full_name, value, size, flags); -} - -static struct xattr_handler v9fs_xattr_user_handler = { - .prefix = XATTR_USER_PREFIX, - .get = v9fs_xattr_handler_get, - .set = v9fs_xattr_handler_set, -}; - -static struct xattr_handler v9fs_xattr_trusted_handler = { - .prefix = XATTR_TRUSTED_PREFIX, - .get = v9fs_xattr_handler_get, - .set = v9fs_xattr_handler_set, -}; - -#ifdef CONFIG_9P_FS_SECURITY -static struct xattr_handler v9fs_xattr_security_handler = { - .prefix = XATTR_SECURITY_PREFIX, - .get = v9fs_xattr_handler_get, - .set = v9fs_xattr_handler_set, -}; -#endif - -const struct xattr_handler *v9fs_xattr_handlers[] = { - &v9fs_xattr_user_handler, - &v9fs_xattr_trusted_handler, -#ifdef CONFIG_9P_FS_POSIX_ACL - &v9fs_xattr_acl_access_handler, - &v9fs_xattr_acl_default_handler, -#endif -#ifdef CONFIG_9P_FS_SECURITY - &v9fs_xattr_security_handler, -#endif - NULL -}; diff --git a/addons/9p/src/4.4.180/xattr.h b/addons/9p/src/4.4.180/xattr.h deleted file mode 100644 index c63c3bea..00000000 --- a/addons/9p/src/4.4.180/xattr.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright IBM Corporation, 2010 - * Author Aneesh Kumar K.V - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2.1 of the GNU Lesser General Public License - * as published by the Free Software Foundation. - * - * This program is distributed in the hope that it would be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - */ -#ifndef FS_9P_XATTR_H -#define FS_9P_XATTR_H - -#include -#include -#include - -extern const struct xattr_handler *v9fs_xattr_handlers[]; -extern const struct xattr_handler v9fs_xattr_acl_access_handler; -extern const struct xattr_handler v9fs_xattr_acl_default_handler; - -extern ssize_t v9fs_fid_xattr_get(struct p9_fid *, const char *, - void *, size_t); -extern ssize_t v9fs_xattr_get(struct dentry *, const char *, - void *, size_t); -extern int v9fs_fid_xattr_set(struct p9_fid *, const char *, - const void *, size_t, int); -extern int v9fs_xattr_set(struct dentry *, const char *, - const void *, size_t, int); -extern ssize_t v9fs_listxattr(struct dentry *, char *, size_t); -#endif /* FS_9P_XATTR_H */ diff --git a/addons/acpid/all/addons/acpid.tgz b/addons/acpid/all/addons/acpid.tgz deleted file mode 100644 index 84fb7611e242d212cdea12ed52063c7f61e60115..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25210 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 diff --git a/addons/acpid/install.sh b/addons/acpid/install.sh deleted file mode 100644 index e7ae16b7..00000000 --- a/addons/acpid/install.sh +++ /dev/null @@ -1,12 +0,0 @@ -if [ "${1}" = "sys" ]; then - echo "Installing module and daemon for ACPI button" - if [ ! -f /tmpRoot/lib/modules/button.ko ]; then - cp /modules/button.ko /tmpRoot/lib/modules/ - fi - tar -zxvf /addons/acpid.tgz -C /tmpRoot/ - chmod 755 /tmpRoot/usr/sbin/acpid - chmod 644 /tmpRoot/etc/acpi/events/power - chmod 744 /tmpRoot/etc/acpi/power.sh - chmod 744 /tmpRoot/usr/lib/systemd/system/acpid.service - ln -sf /usr/lib/systemd/system/acpid.service /tmpRoot/etc/systemd/system/multi-user.target.wants/acpid.service -fi diff --git a/addons/acpid/manifest.yml b/addons/acpid/manifest.yml deleted file mode 100644 index e22a99a1..00000000 --- a/addons/acpid/manifest.yml +++ /dev/null @@ -1,36 +0,0 @@ -version: 1 -name: acpid -description: "Flexible and extensible daemon for delivering ACPI events" -available-for: - bromolow-3.10.108: - install-script: "install.sh" - copy: "all" - modules: true - apollolake-4.4.180: - install-script: "install.sh" - copy: "all" - modules: true - broadwell-4.4.180: - install-script: "install.sh" - copy: "all" - modules: true - broadwellnk-4.4.180: - install-script: "install.sh" - copy: "all" - modules: true - denverton-4.4.180: - install-script: "install.sh" - copy: "all" - modules: true - geminilake-4.4.180: - install-script: "install.sh" - copy: "all" - modules: true - v1000-4.4.180: - install-script: "install.sh" - copy: "all" - modules: true - purley-4.4.180: - install-script: "install.sh" - copy: "all" - modules: false diff --git a/addons/acpid/src/3.10.108/Makefile b/addons/acpid/src/3.10.108/Makefile deleted file mode 100644 index fe863c2b..00000000 --- a/addons/acpid/src/3.10.108/Makefile +++ /dev/null @@ -1,46 +0,0 @@ -# -# Makefile for the Linux ACPI interpreter -# - -# -# ACPI Boot-Time Table Parsing -# -#obj-$(CONFIG_X86) += blacklist.o - -# Power management related files -#acpi-$(CONFIG_ACPI_SLEEP) += proc.o - - -# -# ACPI Bus and Device Drivers -# -#acpi-$(CONFIG_ACPI_DOCK) += dock.o -#acpi-$(CONFIG_X86_INTEL_LPSS) += acpi_lpss.o -#acpi-$(CONFIG_X86) += acpi_cmos_rtc.o -#acpi-$(CONFIG_DEBUG_FS) += debugfs.o -acpi-$(CONFIG_ACPI_NUMA) += numa.o -#acpi-$(CONFIG_ACPI_PROCFS_POWER) += cm_sbs.o - -# These are (potentially) separate modules - -# IPMI may be used by other drivers, so it has to initialise before them -#obj-$(CONFIG_ACPI_IPMI) += acpi_ipmi.o - -#obj-$(CONFIG_ACPI_AC) += ac.o -obj-$(CONFIG_ACPI_BUTTON) += button.o -#obj-$(CONFIG_ACPI_FAN) += fan.o -#obj-$(CONFIG_ACPI_VIDEO) += video.o -#obj-$(CONFIG_ACPI_PCI_SLOT) += pci_slot.o -#obj-$(CONFIG_ACPI_CONTAINER) += container.o -#obj-$(CONFIG_ACPI_THERMAL) += thermal.o -#obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o -#obj-$(CONFIG_ACPI_BATTERY) += battery.o -#obj-$(CONFIG_ACPI_SBS) += sbshc.o -#obj-$(CONFIG_ACPI_SBS) += sbs.o -#obj-$(CONFIG_ACPI_HED) += hed.o -#obj-$(CONFIG_ACPI_EC_DEBUGFS) += ec_sys.o -#obj-$(CONFIG_ACPI_CUSTOM_METHOD)+= custom_method.o -#obj-$(CONFIG_ACPI_BGRT) += bgrt.o -#obj-$(CONFIG_ACPI_I2C) += acpi_i2c.o - -#obj-$(CONFIG_ACPI_PROCESSOR_AGGREGATOR) += acpi_pad.o diff --git a/addons/acpid/src/3.10.108/button.c b/addons/acpid/src/3.10.108/button.c deleted file mode 100644 index d2e617b5..00000000 --- a/addons/acpid/src/3.10.108/button.c +++ /dev/null @@ -1,454 +0,0 @@ -/* - * button.c - ACPI Button Driver - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or (at - * your option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PREFIX "ACPI: " - -#define ACPI_BUTTON_CLASS "button" -#define ACPI_BUTTON_FILE_INFO "info" -#define ACPI_BUTTON_FILE_STATE "state" -#define ACPI_BUTTON_TYPE_UNKNOWN 0x00 -#define ACPI_BUTTON_NOTIFY_STATUS 0x80 - -#define ACPI_BUTTON_SUBCLASS_POWER "power" -#define ACPI_BUTTON_HID_POWER "PNP0C0C" -#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button" -#define ACPI_BUTTON_TYPE_POWER 0x01 - -#define ACPI_BUTTON_SUBCLASS_SLEEP "sleep" -#define ACPI_BUTTON_HID_SLEEP "PNP0C0E" -#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button" -#define ACPI_BUTTON_TYPE_SLEEP 0x03 - -#define ACPI_BUTTON_SUBCLASS_LID "lid" -#define ACPI_BUTTON_HID_LID "PNP0C0D" -#define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch" -#define ACPI_BUTTON_TYPE_LID 0x05 - -#define _COMPONENT ACPI_BUTTON_COMPONENT -ACPI_MODULE_NAME("button"); - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION("ACPI Button Driver"); -MODULE_LICENSE("GPL"); - -static const struct acpi_device_id button_device_ids[] = { - {ACPI_BUTTON_HID_LID, 0}, - {ACPI_BUTTON_HID_SLEEP, 0}, - {ACPI_BUTTON_HID_SLEEPF, 0}, - {ACPI_BUTTON_HID_POWER, 0}, - {ACPI_BUTTON_HID_POWERF, 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, button_device_ids); - -static int acpi_button_add(struct acpi_device *device); -static int acpi_button_remove(struct acpi_device *device); -static void acpi_button_notify(struct acpi_device *device, u32 event); - -#ifdef CONFIG_PM_SLEEP -static int acpi_button_resume(struct device *dev); -#endif -static SIMPLE_DEV_PM_OPS(acpi_button_pm, NULL, acpi_button_resume); - -static struct acpi_driver acpi_button_driver = { - .name = "button", - .class = ACPI_BUTTON_CLASS, - .ids = button_device_ids, - .ops = { - .add = acpi_button_add, - .remove = acpi_button_remove, - .notify = acpi_button_notify, - }, - .drv.pm = &acpi_button_pm, -}; - -struct acpi_button { - unsigned int type; - struct input_dev *input; - char phys[32]; /* for input device */ - unsigned long pushed; - bool wakeup_enabled; -}; - -static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); -static struct acpi_device *lid_device; - -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -static struct proc_dir_entry *acpi_button_dir; -static struct proc_dir_entry *acpi_lid_dir; - -static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_device *device = seq->private; - acpi_status status; - unsigned long long state; - - status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state); - seq_printf(seq, "state: %s\n", - ACPI_FAILURE(status) ? "unsupported" : - (state ? "open" : "closed")); - return 0; -} - -static int acpi_button_state_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_button_state_seq_show, PDE_DATA(inode)); -} - -static const struct file_operations acpi_button_state_fops = { - .owner = THIS_MODULE, - .open = acpi_button_state_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int acpi_button_add_fs(struct acpi_device *device) -{ - struct acpi_button *button = acpi_driver_data(device); - struct proc_dir_entry *entry = NULL; - int ret = 0; - - /* procfs I/F for ACPI lid device only */ - if (button->type != ACPI_BUTTON_TYPE_LID) - return 0; - - if (acpi_button_dir || acpi_lid_dir) { - printk(KERN_ERR PREFIX "More than one Lid device found!\n"); - return -EEXIST; - } - - /* create /proc/acpi/button */ - acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); - if (!acpi_button_dir) - return -ENODEV; - - /* create /proc/acpi/button/lid */ - acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); - if (!acpi_lid_dir) { - ret = -ENODEV; - goto remove_button_dir; - } - - /* create /proc/acpi/button/lid/LID/ */ - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_lid_dir); - if (!acpi_device_dir(device)) { - ret = -ENODEV; - goto remove_lid_dir; - } - - /* create /proc/acpi/button/lid/LID/state */ - entry = proc_create_data(ACPI_BUTTON_FILE_STATE, - S_IRUGO, acpi_device_dir(device), - &acpi_button_state_fops, device); - if (!entry) { - ret = -ENODEV; - goto remove_dev_dir; - } - -done: - return ret; - -remove_dev_dir: - remove_proc_entry(acpi_device_bid(device), - acpi_lid_dir); - acpi_device_dir(device) = NULL; -remove_lid_dir: - remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); -remove_button_dir: - remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); - goto done; -} - -static int acpi_button_remove_fs(struct acpi_device *device) -{ - struct acpi_button *button = acpi_driver_data(device); - - if (button->type != ACPI_BUTTON_TYPE_LID) - return 0; - - remove_proc_entry(ACPI_BUTTON_FILE_STATE, - acpi_device_dir(device)); - remove_proc_entry(acpi_device_bid(device), - acpi_lid_dir); - acpi_device_dir(device) = NULL; - remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); - remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); - - return 0; -} - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ -int acpi_lid_notifier_register(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&acpi_lid_notifier, nb); -} -EXPORT_SYMBOL(acpi_lid_notifier_register); - -int acpi_lid_notifier_unregister(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&acpi_lid_notifier, nb); -} -EXPORT_SYMBOL(acpi_lid_notifier_unregister); - -int acpi_lid_open(void) -{ - acpi_status status; - unsigned long long state; - - if (!lid_device) - return -ENODEV; - - status = acpi_evaluate_integer(lid_device->handle, "_LID", NULL, - &state); - if (ACPI_FAILURE(status)) - return -ENODEV; - - return !!state; -} -EXPORT_SYMBOL(acpi_lid_open); - -static int acpi_lid_send_state(struct acpi_device *device) -{ - struct acpi_button *button = acpi_driver_data(device); - unsigned long long state; - acpi_status status; - int ret; - - status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state); - if (ACPI_FAILURE(status)) - return -ENODEV; - - /* input layer checks if event is redundant */ - input_report_switch(button->input, SW_LID, !state); - input_sync(button->input); - - if (state) - pm_wakeup_event(&device->dev, 0); - - ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); - if (ret == NOTIFY_DONE) - ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, - device); - if (ret == NOTIFY_DONE || ret == NOTIFY_OK) { - /* - * It is also regarded as success if the notifier_chain - * returns NOTIFY_OK or NOTIFY_DONE. - */ - ret = 0; - } - return ret; -} - -static void acpi_button_notify(struct acpi_device *device, u32 event) -{ - struct acpi_button *button = acpi_driver_data(device); - struct input_dev *input; - - switch (event) { - case ACPI_FIXED_HARDWARE_EVENT: - event = ACPI_BUTTON_NOTIFY_STATUS; - /* fall through */ - case ACPI_BUTTON_NOTIFY_STATUS: - input = button->input; - if (button->type == ACPI_BUTTON_TYPE_LID) { - acpi_lid_send_state(device); - } else { - int keycode = test_bit(KEY_SLEEP, input->keybit) ? - KEY_SLEEP : KEY_POWER; - - input_report_key(input, keycode, 1); - input_sync(input); - input_report_key(input, keycode, 0); - input_sync(input); - - pm_wakeup_event(&device->dev, 0); - } - - acpi_bus_generate_proc_event(device, event, ++button->pushed); - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Unsupported event [0x%x]\n", event)); - break; - } -} - -#ifdef CONFIG_PM_SLEEP -static int acpi_button_resume(struct device *dev) -{ - struct acpi_device *device = to_acpi_device(dev); - struct acpi_button *button = acpi_driver_data(device); - - if (button->type == ACPI_BUTTON_TYPE_LID) - return acpi_lid_send_state(device); - return 0; -} -#endif - -static int acpi_button_add(struct acpi_device *device) -{ - struct acpi_button *button; - struct input_dev *input; - const char *hid = acpi_device_hid(device); - char *name, *class; - int error; - - button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL); - if (!button) - return -ENOMEM; - - device->driver_data = button; - - button->input = input = input_allocate_device(); - if (!input) { - error = -ENOMEM; - goto err_free_button; - } - - name = acpi_device_name(device); - class = acpi_device_class(device); - - if (!strcmp(hid, ACPI_BUTTON_HID_POWER) || - !strcmp(hid, ACPI_BUTTON_HID_POWERF)) { - button->type = ACPI_BUTTON_TYPE_POWER; - strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER); - sprintf(class, "%s/%s", - ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); - } else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) || - !strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) { - button->type = ACPI_BUTTON_TYPE_SLEEP; - strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP); - sprintf(class, "%s/%s", - ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); - } else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) { - button->type = ACPI_BUTTON_TYPE_LID; - strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID); - sprintf(class, "%s/%s", - ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID); - } else { - printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid); - error = -ENODEV; - goto err_free_input; - } - - error = acpi_button_add_fs(device); - if (error) - goto err_free_input; - - snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid); - - input->name = name; - input->phys = button->phys; - input->id.bustype = BUS_HOST; - input->id.product = button->type; - input->dev.parent = &device->dev; - - switch (button->type) { - case ACPI_BUTTON_TYPE_POWER: - input->evbit[0] = BIT_MASK(EV_KEY); - set_bit(KEY_POWER, input->keybit); - break; - - case ACPI_BUTTON_TYPE_SLEEP: - input->evbit[0] = BIT_MASK(EV_KEY); - set_bit(KEY_SLEEP, input->keybit); - break; - - case ACPI_BUTTON_TYPE_LID: - input->evbit[0] = BIT_MASK(EV_SW); - set_bit(SW_LID, input->swbit); - break; - } - - error = input_register_device(input); - if (error) - goto err_remove_fs; - if (button->type == ACPI_BUTTON_TYPE_LID) { - acpi_lid_send_state(device); - /* - * This assumes there's only one lid device, or if there are - * more we only care about the last one... - */ - lid_device = device; - } - - if (device->wakeup.flags.valid) { - /* Button's GPE is run-wake GPE */ - acpi_enable_gpe(device->wakeup.gpe_device, - device->wakeup.gpe_number); - if (!device_may_wakeup(&device->dev)) { - device_set_wakeup_enable(&device->dev, true); - button->wakeup_enabled = true; - } - } - - printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); - return 0; - - err_remove_fs: - acpi_button_remove_fs(device); - err_free_input: - input_free_device(input); - err_free_button: - kfree(button); - return error; -} - -static int acpi_button_remove(struct acpi_device *device) -{ - struct acpi_button *button = acpi_driver_data(device); - - if (device->wakeup.flags.valid) { - acpi_disable_gpe(device->wakeup.gpe_device, - device->wakeup.gpe_number); - if (button->wakeup_enabled) - device_set_wakeup_enable(&device->dev, false); - } - - acpi_button_remove_fs(device); - input_unregister_device(button->input); - kfree(button); - return 0; -} - -module_acpi_driver(acpi_button_driver); diff --git a/addons/acpid/src/4.4.180/Makefile b/addons/acpid/src/4.4.180/Makefile deleted file mode 100644 index 2fff3349..00000000 --- a/addons/acpid/src/4.4.180/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-$(CONFIG_ACPI_BUTTON) += button.o diff --git a/addons/acpid/src/4.4.180/Module.symvers b/addons/acpid/src/4.4.180/Module.symvers deleted file mode 100644 index e69de29b..00000000 diff --git a/addons/acpid/src/4.4.180/button.c b/addons/acpid/src/4.4.180/button.c deleted file mode 100644 index 5c3b0918..00000000 --- a/addons/acpid/src/4.4.180/button.c +++ /dev/null @@ -1,449 +0,0 @@ -/* - * button.c - ACPI Button Driver - * - * Copyright (C) 2001, 2002 Andy Grover - * Copyright (C) 2001, 2002 Paul Diefenbaugh - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * - * 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. - * - * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define PREFIX "ACPI: " - -#define ACPI_BUTTON_CLASS "button" -#define ACPI_BUTTON_FILE_INFO "info" -#define ACPI_BUTTON_FILE_STATE "state" -#define ACPI_BUTTON_TYPE_UNKNOWN 0x00 -#define ACPI_BUTTON_NOTIFY_STATUS 0x80 - -#define ACPI_BUTTON_SUBCLASS_POWER "power" -#define ACPI_BUTTON_HID_POWER "PNP0C0C" -#define ACPI_BUTTON_DEVICE_NAME_POWER "Power Button" -#define ACPI_BUTTON_TYPE_POWER 0x01 - -#define ACPI_BUTTON_SUBCLASS_SLEEP "sleep" -#define ACPI_BUTTON_HID_SLEEP "PNP0C0E" -#define ACPI_BUTTON_DEVICE_NAME_SLEEP "Sleep Button" -#define ACPI_BUTTON_TYPE_SLEEP 0x03 - -#define ACPI_BUTTON_SUBCLASS_LID "lid" -#define ACPI_BUTTON_HID_LID "PNP0C0D" -#define ACPI_BUTTON_DEVICE_NAME_LID "Lid Switch" -#define ACPI_BUTTON_TYPE_LID 0x05 - -#define _COMPONENT ACPI_BUTTON_COMPONENT -ACPI_MODULE_NAME("button"); - -MODULE_AUTHOR("Paul Diefenbaugh"); -MODULE_DESCRIPTION("ACPI Button Driver"); -MODULE_LICENSE("GPL"); - -static const struct acpi_device_id button_device_ids[] = { - {ACPI_BUTTON_HID_LID, 0}, - {ACPI_BUTTON_HID_SLEEP, 0}, - {ACPI_BUTTON_HID_SLEEPF, 0}, - {ACPI_BUTTON_HID_POWER, 0}, - {ACPI_BUTTON_HID_POWERF, 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, button_device_ids); - -static int acpi_button_add(struct acpi_device *device); -static int acpi_button_remove(struct acpi_device *device); -static void acpi_button_notify(struct acpi_device *device, u32 event); - -#ifdef CONFIG_PM_SLEEP -static int acpi_button_suspend(struct device *dev); -static int acpi_button_resume(struct device *dev); -#else -#define acpi_button_suspend NULL -#define acpi_button_resume NULL -#endif -static SIMPLE_DEV_PM_OPS(acpi_button_pm, acpi_button_suspend, acpi_button_resume); - -static struct acpi_driver acpi_button_driver = { - .name = "button", - .class = ACPI_BUTTON_CLASS, - .ids = button_device_ids, - .ops = { - .add = acpi_button_add, - .remove = acpi_button_remove, - .notify = acpi_button_notify, - }, - .drv.pm = &acpi_button_pm, -}; - -struct acpi_button { - unsigned int type; - struct input_dev *input; - char phys[32]; /* for input device */ - unsigned long pushed; - bool suspended; -}; - -static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier); -static struct acpi_device *lid_device; - -/* -------------------------------------------------------------------------- - FS Interface (/proc) - -------------------------------------------------------------------------- */ - -static struct proc_dir_entry *acpi_button_dir; -static struct proc_dir_entry *acpi_lid_dir; - -static int acpi_button_state_seq_show(struct seq_file *seq, void *offset) -{ - struct acpi_device *device = seq->private; - acpi_status status; - unsigned long long state; - - status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state); - seq_printf(seq, "state: %s\n", - ACPI_FAILURE(status) ? "unsupported" : - (state ? "open" : "closed")); - return 0; -} - -static int acpi_button_state_open_fs(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_button_state_seq_show, PDE_DATA(inode)); -} - -static const struct file_operations acpi_button_state_fops = { - .owner = THIS_MODULE, - .open = acpi_button_state_open_fs, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static int acpi_button_add_fs(struct acpi_device *device) -{ - struct acpi_button *button = acpi_driver_data(device); - struct proc_dir_entry *entry = NULL; - int ret = 0; - - /* procfs I/F for ACPI lid device only */ - if (button->type != ACPI_BUTTON_TYPE_LID) - return 0; - - if (acpi_button_dir || acpi_lid_dir) { - printk(KERN_ERR PREFIX "More than one Lid device found!\n"); - return -EEXIST; - } - - /* create /proc/acpi/button */ - acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir); - if (!acpi_button_dir) - return -ENODEV; - - /* create /proc/acpi/button/lid */ - acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); - if (!acpi_lid_dir) { - ret = -ENODEV; - goto remove_button_dir; - } - - /* create /proc/acpi/button/lid/LID/ */ - acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_lid_dir); - if (!acpi_device_dir(device)) { - ret = -ENODEV; - goto remove_lid_dir; - } - - /* create /proc/acpi/button/lid/LID/state */ - entry = proc_create_data(ACPI_BUTTON_FILE_STATE, - S_IRUGO, acpi_device_dir(device), - &acpi_button_state_fops, device); - if (!entry) { - ret = -ENODEV; - goto remove_dev_dir; - } - -done: - return ret; - -remove_dev_dir: - remove_proc_entry(acpi_device_bid(device), - acpi_lid_dir); - acpi_device_dir(device) = NULL; -remove_lid_dir: - remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); -remove_button_dir: - remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); - goto done; -} - -static int acpi_button_remove_fs(struct acpi_device *device) -{ - struct acpi_button *button = acpi_driver_data(device); - - if (button->type != ACPI_BUTTON_TYPE_LID) - return 0; - - remove_proc_entry(ACPI_BUTTON_FILE_STATE, - acpi_device_dir(device)); - remove_proc_entry(acpi_device_bid(device), - acpi_lid_dir); - acpi_device_dir(device) = NULL; - remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir); - remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir); - - return 0; -} - -/* -------------------------------------------------------------------------- - Driver Interface - -------------------------------------------------------------------------- */ -int acpi_lid_notifier_register(struct notifier_block *nb) -{ - return blocking_notifier_chain_register(&acpi_lid_notifier, nb); -} -EXPORT_SYMBOL(acpi_lid_notifier_register); - -int acpi_lid_notifier_unregister(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&acpi_lid_notifier, nb); -} -EXPORT_SYMBOL(acpi_lid_notifier_unregister); - -int acpi_lid_open(void) -{ - acpi_status status; - unsigned long long state; - - if (!lid_device) - return -ENODEV; - - status = acpi_evaluate_integer(lid_device->handle, "_LID", NULL, - &state); - if (ACPI_FAILURE(status)) - return -ENODEV; - - return !!state; -} -EXPORT_SYMBOL(acpi_lid_open); - -static int acpi_lid_send_state(struct acpi_device *device) -{ - struct acpi_button *button = acpi_driver_data(device); - unsigned long long state; - acpi_status status; - int ret; - - status = acpi_evaluate_integer(device->handle, "_LID", NULL, &state); - if (ACPI_FAILURE(status)) - return -ENODEV; - - /* input layer checks if event is redundant */ - input_report_switch(button->input, SW_LID, !state); - input_sync(button->input); - - if (state) - pm_wakeup_event(&device->dev, 0); - - ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, device); - if (ret == NOTIFY_DONE) - ret = blocking_notifier_call_chain(&acpi_lid_notifier, state, - device); - if (ret == NOTIFY_DONE || ret == NOTIFY_OK) { - /* - * It is also regarded as success if the notifier_chain - * returns NOTIFY_OK or NOTIFY_DONE. - */ - ret = 0; - } - return ret; -} - -static void acpi_button_notify(struct acpi_device *device, u32 event) -{ - struct acpi_button *button = acpi_driver_data(device); - struct input_dev *input; - - switch (event) { - case ACPI_FIXED_HARDWARE_EVENT: - event = ACPI_BUTTON_NOTIFY_STATUS; - /* fall through */ - case ACPI_BUTTON_NOTIFY_STATUS: - input = button->input; - if (button->type == ACPI_BUTTON_TYPE_LID) { - acpi_lid_send_state(device); - } else { - int keycode; - - pm_wakeup_event(&device->dev, 0); - if (button->suspended) - break; - - keycode = test_bit(KEY_SLEEP, input->keybit) ? - KEY_SLEEP : KEY_POWER; - input_report_key(input, keycode, 1); - input_sync(input); - input_report_key(input, keycode, 0); - input_sync(input); - - acpi_bus_generate_netlink_event( - device->pnp.device_class, - dev_name(&device->dev), - event, ++button->pushed); - } - break; - default: - ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Unsupported event [0x%x]\n", event)); - break; - } -} - -#ifdef CONFIG_PM_SLEEP -static int acpi_button_suspend(struct device *dev) -{ - struct acpi_device *device = to_acpi_device(dev); - struct acpi_button *button = acpi_driver_data(device); - - button->suspended = true; - return 0; -} - -static int acpi_button_resume(struct device *dev) -{ - struct acpi_device *device = to_acpi_device(dev); - struct acpi_button *button = acpi_driver_data(device); - - button->suspended = false; - if (button->type == ACPI_BUTTON_TYPE_LID) - return acpi_lid_send_state(device); - return 0; -} -#endif - -static int acpi_button_add(struct acpi_device *device) -{ - struct acpi_button *button; - struct input_dev *input; - const char *hid = acpi_device_hid(device); - char *name, *class; - int error; - - button = kzalloc(sizeof(struct acpi_button), GFP_KERNEL); - if (!button) - return -ENOMEM; - - device->driver_data = button; - - button->input = input = input_allocate_device(); - if (!input) { - error = -ENOMEM; - goto err_free_button; - } - - name = acpi_device_name(device); - class = acpi_device_class(device); - - if (!strcmp(hid, ACPI_BUTTON_HID_POWER) || - !strcmp(hid, ACPI_BUTTON_HID_POWERF)) { - button->type = ACPI_BUTTON_TYPE_POWER; - strcpy(name, ACPI_BUTTON_DEVICE_NAME_POWER); - sprintf(class, "%s/%s", - ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_POWER); - } else if (!strcmp(hid, ACPI_BUTTON_HID_SLEEP) || - !strcmp(hid, ACPI_BUTTON_HID_SLEEPF)) { - button->type = ACPI_BUTTON_TYPE_SLEEP; - strcpy(name, ACPI_BUTTON_DEVICE_NAME_SLEEP); - sprintf(class, "%s/%s", - ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_SLEEP); - } else if (!strcmp(hid, ACPI_BUTTON_HID_LID)) { - button->type = ACPI_BUTTON_TYPE_LID; - strcpy(name, ACPI_BUTTON_DEVICE_NAME_LID); - sprintf(class, "%s/%s", - ACPI_BUTTON_CLASS, ACPI_BUTTON_SUBCLASS_LID); - } else { - printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid); - error = -ENODEV; - goto err_free_input; - } - - error = acpi_button_add_fs(device); - if (error) - goto err_free_input; - - snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid); - - input->name = name; - input->phys = button->phys; - input->id.bustype = BUS_HOST; - input->id.product = button->type; - input->dev.parent = &device->dev; - - switch (button->type) { - case ACPI_BUTTON_TYPE_POWER: - input_set_capability(input, EV_KEY, KEY_POWER); - break; - - case ACPI_BUTTON_TYPE_SLEEP: - input_set_capability(input, EV_KEY, KEY_SLEEP); - break; - - case ACPI_BUTTON_TYPE_LID: - input_set_capability(input, EV_SW, SW_LID); - break; - } - - error = input_register_device(input); - if (error) - goto err_remove_fs; - if (button->type == ACPI_BUTTON_TYPE_LID) { - acpi_lid_send_state(device); - /* - * This assumes there's only one lid device, or if there are - * more we only care about the last one... - */ - lid_device = device; - } - - printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device)); - return 0; - - err_remove_fs: - acpi_button_remove_fs(device); - err_free_input: - input_free_device(input); - err_free_button: - kfree(button); - return error; -} - -static int acpi_button_remove(struct acpi_device *device) -{ - struct acpi_button *button = acpi_driver_data(device); - - acpi_button_remove_fs(device); - input_unregister_device(button->input); - kfree(button); - return 0; -} - -module_acpi_driver(acpi_button_driver); diff --git a/addons/acpid/src/4.4.180/modules.order b/addons/acpid/src/4.4.180/modules.order deleted file mode 100644 index e69de29b..00000000 diff --git a/addons/atl1c/install.sh b/addons/atl1c/install.sh deleted file mode 100644 index 035b4149..00000000 --- a/addons/atl1c/install.sh +++ /dev/null @@ -1,4 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Installing module for Atheros L1C Gigabit Ethernet adapter" - ${INSMOD} "/modules/atl1c.ko" ${PARAMS} -fi diff --git a/addons/atl1c/manifest.yml b/addons/atl1c/manifest.yml deleted file mode 100644 index d2a309c2..00000000 --- a/addons/atl1c/manifest.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: 1 -name: atl1c -description: "Driver for Atheros L1C Gigabit Ethernet adapters" -available-for: - bromolow-3.10.108: - install-script: &script "install.sh" - modules: true - apollolake-4.4.180: - install-script: *script - modules: true - broadwell-4.4.180: - install-script: *script - modules: true - broadwellnk-4.4.180: - install-script: *script - modules: true - denverton-4.4.180: - install-script: *script - modules: true - geminilake-4.4.180: - install-script: *script - modules: true - v1000-4.4.180: - install-script: *script - modules: true - purley-4.4.180: - install-script: *script - modules: true diff --git a/addons/atl1c/src/3.10.108/Makefile b/addons/atl1c/src/3.10.108/Makefile deleted file mode 100644 index d6fff141..00000000 --- a/addons/atl1c/src/3.10.108/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-m += atl1c.o -atl1c-objs := atl1c_main.o atl1c_hw.o atl1c_ethtool.o diff --git a/addons/atl1c/src/3.10.108/atl1c.h b/addons/atl1c/src/3.10.108/atl1c.h deleted file mode 100644 index 0f055652..00000000 --- a/addons/atl1c/src/3.10.108/atl1c.h +++ /dev/null @@ -1,606 +0,0 @@ -/* - * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _ATL1C_H_ -#define _ATL1C_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "atl1c_hw.h" - -/* Wake Up Filter Control */ -#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ -#define AT_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ -#define AT_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ -#define AT_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */ -#define AT_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ - -#define AT_VLAN_TO_TAG(_vlan, _tag) \ - _tag = ((((_vlan) >> 8) & 0xFF) |\ - (((_vlan) & 0xFF) << 8)) - -#define AT_TAG_TO_VLAN(_tag, _vlan) \ - _vlan = ((((_tag) >> 8) & 0xFF) |\ - (((_tag) & 0xFF) << 8)) - -#define SPEED_0 0xffff -#define HALF_DUPLEX 1 -#define FULL_DUPLEX 2 - -#define AT_RX_BUF_SIZE (ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN) -#define MAX_JUMBO_FRAME_SIZE (6*1024) - -#define AT_MAX_RECEIVE_QUEUE 4 -#define AT_DEF_RECEIVE_QUEUE 1 -#define AT_MAX_TRANSMIT_QUEUE 2 - -#define AT_DMA_HI_ADDR_MASK 0xffffffff00000000ULL -#define AT_DMA_LO_ADDR_MASK 0x00000000ffffffffULL - -#define AT_TX_WATCHDOG (5 * HZ) -#define AT_MAX_INT_WORK 5 -#define AT_TWSI_EEPROM_TIMEOUT 100 -#define AT_HW_MAX_IDLE_DELAY 10 -#define AT_SUSPEND_LINK_TIMEOUT 100 - -#define AT_ASPM_L0S_TIMER 6 -#define AT_ASPM_L1_TIMER 12 -#define AT_LCKDET_TIMER 12 - -#define ATL1C_PCIE_L0S_L1_DISABLE 0x01 -#define ATL1C_PCIE_PHY_RESET 0x02 - -#define ATL1C_ASPM_L0s_ENABLE 0x0001 -#define ATL1C_ASPM_L1_ENABLE 0x0002 - -#define AT_REGS_LEN (74 * sizeof(u32)) -#define AT_EEPROM_LEN 512 - -#define ATL1C_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i])) -#define ATL1C_RFD_DESC(R, i) ATL1C_GET_DESC(R, i, struct atl1c_rx_free_desc) -#define ATL1C_TPD_DESC(R, i) ATL1C_GET_DESC(R, i, struct atl1c_tpd_desc) -#define ATL1C_RRD_DESC(R, i) ATL1C_GET_DESC(R, i, struct atl1c_recv_ret_status) - -/* tpd word 1 bit 0:7 General Checksum task offload */ -#define TPD_L4HDR_OFFSET_MASK 0x00FF -#define TPD_L4HDR_OFFSET_SHIFT 0 - -/* tpd word 1 bit 0:7 Large Send task offload (IPv4/IPV6) */ -#define TPD_TCPHDR_OFFSET_MASK 0x00FF -#define TPD_TCPHDR_OFFSET_SHIFT 0 - -/* tpd word 1 bit 0:7 Custom Checksum task offload */ -#define TPD_PLOADOFFSET_MASK 0x00FF -#define TPD_PLOADOFFSET_SHIFT 0 - -/* tpd word 1 bit 8:17 */ -#define TPD_CCSUM_EN_MASK 0x0001 -#define TPD_CCSUM_EN_SHIFT 8 -#define TPD_IP_CSUM_MASK 0x0001 -#define TPD_IP_CSUM_SHIFT 9 -#define TPD_TCP_CSUM_MASK 0x0001 -#define TPD_TCP_CSUM_SHIFT 10 -#define TPD_UDP_CSUM_MASK 0x0001 -#define TPD_UDP_CSUM_SHIFT 11 -#define TPD_LSO_EN_MASK 0x0001 /* TCP Large Send Offload */ -#define TPD_LSO_EN_SHIFT 12 -#define TPD_LSO_VER_MASK 0x0001 -#define TPD_LSO_VER_SHIFT 13 /* 0 : ipv4; 1 : ipv4/ipv6 */ -#define TPD_CON_VTAG_MASK 0x0001 -#define TPD_CON_VTAG_SHIFT 14 -#define TPD_INS_VTAG_MASK 0x0001 -#define TPD_INS_VTAG_SHIFT 15 -#define TPD_IPV4_PACKET_MASK 0x0001 /* valid when LSO VER is 1 */ -#define TPD_IPV4_PACKET_SHIFT 16 -#define TPD_ETH_TYPE_MASK 0x0001 -#define TPD_ETH_TYPE_SHIFT 17 /* 0 : 802.3 frame; 1 : Ethernet */ - -/* tpd word 18:25 Custom Checksum task offload */ -#define TPD_CCSUM_OFFSET_MASK 0x00FF -#define TPD_CCSUM_OFFSET_SHIFT 18 -#define TPD_CCSUM_EPAD_MASK 0x0001 -#define TPD_CCSUM_EPAD_SHIFT 30 - -/* tpd word 18:30 Large Send task offload (IPv4/IPV6) */ -#define TPD_MSS_MASK 0x1FFF -#define TPD_MSS_SHIFT 18 - -#define TPD_EOP_MASK 0x0001 -#define TPD_EOP_SHIFT 31 - -struct atl1c_tpd_desc { - __le16 buffer_len; /* include 4-byte CRC */ - __le16 vlan_tag; - __le32 word1; - __le64 buffer_addr; -}; - -struct atl1c_tpd_ext_desc { - u32 reservd_0; - __le32 word1; - __le32 pkt_len; - u32 reservd_1; -}; -/* rrs word 0 bit 0:31 */ -#define RRS_RX_CSUM_MASK 0xFFFF -#define RRS_RX_CSUM_SHIFT 0 -#define RRS_RX_RFD_CNT_MASK 0x000F -#define RRS_RX_RFD_CNT_SHIFT 16 -#define RRS_RX_RFD_INDEX_MASK 0x0FFF -#define RRS_RX_RFD_INDEX_SHIFT 20 - -/* rrs flag bit 0:16 */ -#define RRS_HEAD_LEN_MASK 0x00FF -#define RRS_HEAD_LEN_SHIFT 0 -#define RRS_HDS_TYPE_MASK 0x0003 -#define RRS_HDS_TYPE_SHIFT 8 -#define RRS_CPU_NUM_MASK 0x0003 -#define RRS_CPU_NUM_SHIFT 10 -#define RRS_HASH_FLG_MASK 0x000F -#define RRS_HASH_FLG_SHIFT 12 - -#define RRS_HDS_TYPE_HEAD 1 -#define RRS_HDS_TYPE_DATA 2 - -#define RRS_IS_NO_HDS_TYPE(flag) \ - ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == 0) - -#define RRS_IS_HDS_HEAD(flag) \ - ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \ - RRS_HDS_TYPE_HEAD) - -#define RRS_IS_HDS_DATA(flag) \ - ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \ - RRS_HDS_TYPE_DATA) - -/* rrs word 3 bit 0:31 */ -#define RRS_PKT_SIZE_MASK 0x3FFF -#define RRS_PKT_SIZE_SHIFT 0 -#define RRS_ERR_L4_CSUM_MASK 0x0001 -#define RRS_ERR_L4_CSUM_SHIFT 14 -#define RRS_ERR_IP_CSUM_MASK 0x0001 -#define RRS_ERR_IP_CSUM_SHIFT 15 -#define RRS_VLAN_INS_MASK 0x0001 -#define RRS_VLAN_INS_SHIFT 16 -#define RRS_PROT_ID_MASK 0x0007 -#define RRS_PROT_ID_SHIFT 17 -#define RRS_RX_ERR_SUM_MASK 0x0001 -#define RRS_RX_ERR_SUM_SHIFT 20 -#define RRS_RX_ERR_CRC_MASK 0x0001 -#define RRS_RX_ERR_CRC_SHIFT 21 -#define RRS_RX_ERR_FAE_MASK 0x0001 -#define RRS_RX_ERR_FAE_SHIFT 22 -#define RRS_RX_ERR_TRUNC_MASK 0x0001 -#define RRS_RX_ERR_TRUNC_SHIFT 23 -#define RRS_RX_ERR_RUNC_MASK 0x0001 -#define RRS_RX_ERR_RUNC_SHIFT 24 -#define RRS_RX_ERR_ICMP_MASK 0x0001 -#define RRS_RX_ERR_ICMP_SHIFT 25 -#define RRS_PACKET_BCAST_MASK 0x0001 -#define RRS_PACKET_BCAST_SHIFT 26 -#define RRS_PACKET_MCAST_MASK 0x0001 -#define RRS_PACKET_MCAST_SHIFT 27 -#define RRS_PACKET_TYPE_MASK 0x0001 -#define RRS_PACKET_TYPE_SHIFT 28 -#define RRS_FIFO_FULL_MASK 0x0001 -#define RRS_FIFO_FULL_SHIFT 29 -#define RRS_802_3_LEN_ERR_MASK 0x0001 -#define RRS_802_3_LEN_ERR_SHIFT 30 -#define RRS_RXD_UPDATED_MASK 0x0001 -#define RRS_RXD_UPDATED_SHIFT 31 - -#define RRS_ERR_L4_CSUM 0x00004000 -#define RRS_ERR_IP_CSUM 0x00008000 -#define RRS_VLAN_INS 0x00010000 -#define RRS_RX_ERR_SUM 0x00100000 -#define RRS_RX_ERR_CRC 0x00200000 -#define RRS_802_3_LEN_ERR 0x40000000 -#define RRS_RXD_UPDATED 0x80000000 - -#define RRS_PACKET_TYPE_802_3 1 -#define RRS_PACKET_TYPE_ETH 0 -#define RRS_PACKET_IS_ETH(word) \ - ((((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK) == \ - RRS_PACKET_TYPE_ETH) -#define RRS_RXD_IS_VALID(word) \ - ((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1) - -#define RRS_PACKET_PROT_IS_IPV4_ONLY(word) \ - ((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 1) -#define RRS_PACKET_PROT_IS_IPV6_ONLY(word) \ - ((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 6) - -struct atl1c_recv_ret_status { - __le32 word0; - __le32 rss_hash; - __le16 vlan_tag; - __le16 flag; - __le32 word3; -}; - -/* RFD descriptor */ -struct atl1c_rx_free_desc { - __le64 buffer_addr; -}; - -/* DMA Order Settings */ -enum atl1c_dma_order { - atl1c_dma_ord_in = 1, - atl1c_dma_ord_enh = 2, - atl1c_dma_ord_out = 4 -}; - -enum atl1c_dma_rcb { - atl1c_rcb_64 = 0, - atl1c_rcb_128 = 1 -}; - -enum atl1c_mac_speed { - atl1c_mac_speed_0 = 0, - atl1c_mac_speed_10_100 = 1, - atl1c_mac_speed_1000 = 2 -}; - -enum atl1c_dma_req_block { - atl1c_dma_req_128 = 0, - atl1c_dma_req_256 = 1, - atl1c_dma_req_512 = 2, - atl1c_dma_req_1024 = 3, - atl1c_dma_req_2048 = 4, - atl1c_dma_req_4096 = 5 -}; - - -enum atl1c_nic_type { - athr_l1c = 0, - athr_l2c = 1, - athr_l2c_b, - athr_l2c_b2, - athr_l1d, - athr_l1d_2, -}; - -enum atl1c_trans_queue { - atl1c_trans_normal = 0, - atl1c_trans_high = 1 -}; - -struct atl1c_hw_stats { - /* rx */ - unsigned long rx_ok; /* The number of good packet received. */ - unsigned long rx_bcast; /* The number of good broadcast packet received. */ - unsigned long rx_mcast; /* The number of good multicast packet received. */ - unsigned long rx_pause; /* The number of Pause packet received. */ - unsigned long rx_ctrl; /* The number of Control packet received other than Pause frame. */ - unsigned long rx_fcs_err; /* The number of packets with bad FCS. */ - unsigned long rx_len_err; /* The number of packets with mismatch of length field and actual size. */ - unsigned long rx_byte_cnt; /* The number of bytes of good packet received. FCS is NOT included. */ - unsigned long rx_runt; /* The number of packets received that are less than 64 byte long and with good FCS. */ - unsigned long rx_frag; /* The number of packets received that are less than 64 byte long and with bad FCS. */ - unsigned long rx_sz_64; /* The number of good and bad packets received that are 64 byte long. */ - unsigned long rx_sz_65_127; /* The number of good and bad packets received that are between 65 and 127-byte long. */ - unsigned long rx_sz_128_255; /* The number of good and bad packets received that are between 128 and 255-byte long. */ - unsigned long rx_sz_256_511; /* The number of good and bad packets received that are between 256 and 511-byte long. */ - unsigned long rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */ - unsigned long rx_sz_1024_1518; /* The number of good and bad packets received that are between 1024 and 1518-byte long. */ - unsigned long rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */ - unsigned long rx_sz_ov; /* The number of good and bad packets received that are more than MTU size truncated by Selene. */ - unsigned long rx_rxf_ov; /* The number of frame dropped due to occurrence of RX FIFO overflow. */ - unsigned long rx_rrd_ov; /* The number of frame dropped due to occurrence of RRD overflow. */ - unsigned long rx_align_err; /* Alignment Error */ - unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */ - unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */ - unsigned long rx_err_addr; /* The number of packets dropped due to address filtering. */ - - /* tx */ - unsigned long tx_ok; /* The number of good packet transmitted. */ - unsigned long tx_bcast; /* The number of good broadcast packet transmitted. */ - unsigned long tx_mcast; /* The number of good multicast packet transmitted. */ - unsigned long tx_pause; /* The number of Pause packet transmitted. */ - unsigned long tx_exc_defer; /* The number of packets transmitted with excessive deferral. */ - unsigned long tx_ctrl; /* The number of packets transmitted is a control frame, excluding Pause frame. */ - unsigned long tx_defer; /* The number of packets transmitted that is deferred. */ - unsigned long tx_byte_cnt; /* The number of bytes of data transmitted. FCS is NOT included. */ - unsigned long tx_sz_64; /* The number of good and bad packets transmitted that are 64 byte long. */ - unsigned long tx_sz_65_127; /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */ - unsigned long tx_sz_128_255; /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */ - unsigned long tx_sz_256_511; /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */ - unsigned long tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */ - unsigned long tx_sz_1024_1518; /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */ - unsigned long tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */ - unsigned long tx_1_col; /* The number of packets subsequently transmitted successfully with a single prior collision. */ - unsigned long tx_2_col; /* The number of packets subsequently transmitted successfully with multiple prior collisions. */ - unsigned long tx_late_col; /* The number of packets transmitted with late collisions. */ - unsigned long tx_abort_col; /* The number of transmit packets aborted due to excessive collisions. */ - unsigned long tx_underrun; /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */ - unsigned long tx_rd_eop; /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */ - unsigned long tx_len_err; /* The number of transmit packets with length field does NOT match the actual frame size. */ - unsigned long tx_trunc; /* The number of transmit packets truncated due to size exceeding MTU. */ - unsigned long tx_bcast_byte; /* The byte count of broadcast packet transmitted, excluding FCS. */ - unsigned long tx_mcast_byte; /* The byte count of multicast packet transmitted, excluding FCS. */ -}; - -struct atl1c_hw { - u8 __iomem *hw_addr; /* inner register address */ - struct atl1c_adapter *adapter; - enum atl1c_nic_type nic_type; - enum atl1c_dma_order dma_order; - enum atl1c_dma_rcb rcb_value; - enum atl1c_dma_req_block dmar_block; - - u16 device_id; - u16 vendor_id; - u16 subsystem_id; - u16 subsystem_vendor_id; - u8 revision_id; - u16 phy_id1; - u16 phy_id2; - - u32 intr_mask; - - u8 preamble_len; - u16 max_frame_size; - u16 min_frame_size; - - enum atl1c_mac_speed mac_speed; - bool mac_duplex; - bool hibernate; - u16 media_type; -#define MEDIA_TYPE_AUTO_SENSOR 0 -#define MEDIA_TYPE_100M_FULL 1 -#define MEDIA_TYPE_100M_HALF 2 -#define MEDIA_TYPE_10M_FULL 3 -#define MEDIA_TYPE_10M_HALF 4 - - u16 autoneg_advertised; - u16 mii_autoneg_adv_reg; - u16 mii_1000t_ctrl_reg; - - u16 tx_imt; /* TX Interrupt Moderator timer ( 2us resolution) */ - u16 rx_imt; /* RX Interrupt Moderator timer ( 2us resolution) */ - u16 ict; /* Interrupt Clear timer (2us resolution) */ - u16 ctrl_flags; -#define ATL1C_INTR_CLEAR_ON_READ 0x0001 -#define ATL1C_INTR_MODRT_ENABLE 0x0002 -#define ATL1C_CMB_ENABLE 0x0004 -#define ATL1C_SMB_ENABLE 0x0010 -#define ATL1C_TXQ_MODE_ENHANCE 0x0020 -#define ATL1C_RX_IPV6_CHKSUM 0x0040 -#define ATL1C_ASPM_L0S_SUPPORT 0x0080 -#define ATL1C_ASPM_L1_SUPPORT 0x0100 -#define ATL1C_ASPM_CTRL_MON 0x0200 -#define ATL1C_HIB_DISABLE 0x0400 -#define ATL1C_APS_MODE_ENABLE 0x0800 -#define ATL1C_LINK_EXT_SYNC 0x1000 -#define ATL1C_CLK_GATING_EN 0x2000 -#define ATL1C_FPGA_VERSION 0x8000 - u16 link_cap_flags; -#define ATL1C_LINK_CAP_1000M 0x0001 - u32 smb_timer; - - u16 rrd_thresh; /* Threshold of number of RRD produced to trigger - interrupt request */ - u16 tpd_thresh; - u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */ - u8 rfd_burst; - u32 base_cpu; - u32 indirect_tab; - u8 mac_addr[ETH_ALEN]; - u8 perm_mac_addr[ETH_ALEN]; - - bool phy_configured; - bool re_autoneg; - bool emi_ca; - bool msi_lnkpatch; /* link patch for specific platforms */ -}; - -/* - * atl1c_ring_header represents a single, contiguous block of DMA space - * mapped for the three descriptor rings (tpd, rfd, rrd) described below - */ -struct atl1c_ring_header { - void *desc; /* virtual address */ - dma_addr_t dma; /* physical address*/ - unsigned int size; /* length in bytes */ -}; - -/* - * atl1c_buffer is wrapper around a pointer to a socket buffer - * so a DMA handle can be stored along with the skb - */ -struct atl1c_buffer { - struct sk_buff *skb; /* socket buffer */ - u16 length; /* rx buffer length */ - u16 flags; /* information of buffer */ -#define ATL1C_BUFFER_FREE 0x0001 -#define ATL1C_BUFFER_BUSY 0x0002 -#define ATL1C_BUFFER_STATE_MASK 0x0003 - -#define ATL1C_PCIMAP_SINGLE 0x0004 -#define ATL1C_PCIMAP_PAGE 0x0008 -#define ATL1C_PCIMAP_TYPE_MASK 0x000C - -#define ATL1C_PCIMAP_TODEVICE 0x0010 -#define ATL1C_PCIMAP_FROMDEVICE 0x0020 -#define ATL1C_PCIMAP_DIRECTION_MASK 0x0030 - dma_addr_t dma; -}; - -#define ATL1C_SET_BUFFER_STATE(buff, state) do { \ - ((buff)->flags) &= ~ATL1C_BUFFER_STATE_MASK; \ - ((buff)->flags) |= (state); \ - } while (0) - -#define ATL1C_SET_PCIMAP_TYPE(buff, type, direction) do { \ - ((buff)->flags) &= ~ATL1C_PCIMAP_TYPE_MASK; \ - ((buff)->flags) |= (type); \ - ((buff)->flags) &= ~ATL1C_PCIMAP_DIRECTION_MASK; \ - ((buff)->flags) |= (direction); \ - } while (0) - -/* transimit packet descriptor (tpd) ring */ -struct atl1c_tpd_ring { - void *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - u16 size; /* descriptor ring length in bytes */ - u16 count; /* number of descriptors in the ring */ - u16 next_to_use; /* this is protectd by adapter->tx_lock */ - atomic_t next_to_clean; - struct atl1c_buffer *buffer_info; -}; - -/* receive free descriptor (rfd) ring */ -struct atl1c_rfd_ring { - void *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - u16 size; /* descriptor ring length in bytes */ - u16 count; /* number of descriptors in the ring */ - u16 next_to_use; - u16 next_to_clean; - struct atl1c_buffer *buffer_info; -}; - -/* receive return descriptor (rrd) ring */ -struct atl1c_rrd_ring { - void *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - u16 size; /* descriptor ring length in bytes */ - u16 count; /* number of descriptors in the ring */ - u16 next_to_use; - u16 next_to_clean; -}; - -/* board specific private data structure */ -struct atl1c_adapter { - struct net_device *netdev; - struct pci_dev *pdev; - struct napi_struct napi; - struct page *rx_page; - unsigned int rx_page_offset; - unsigned int rx_frag_size; - struct atl1c_hw hw; - struct atl1c_hw_stats hw_stats; - struct mii_if_info mii; /* MII interface info */ - u16 rx_buffer_len; - - unsigned long flags; -#define __AT_TESTING 0x0001 -#define __AT_RESETTING 0x0002 -#define __AT_DOWN 0x0003 - unsigned long work_event; -#define ATL1C_WORK_EVENT_RESET 0 -#define ATL1C_WORK_EVENT_LINK_CHANGE 1 - u32 msg_enable; - - bool have_msi; - u32 wol; - u16 link_speed; - u16 link_duplex; - - spinlock_t mdio_lock; - spinlock_t tx_lock; - atomic_t irq_sem; - - struct work_struct common_task; - struct timer_list watchdog_timer; - struct timer_list phy_config_timer; - - /* All Descriptor memory */ - struct atl1c_ring_header ring_header; - struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE]; - struct atl1c_rfd_ring rfd_ring; - struct atl1c_rrd_ring rrd_ring; - u32 bd_number; /* board number;*/ -}; - -#define AT_WRITE_REG(a, reg, value) ( \ - writel((value), ((a)->hw_addr + reg))) - -#define AT_WRITE_FLUSH(a) (\ - readl((a)->hw_addr)) - -#define AT_READ_REG(a, reg, pdata) do { \ - if (unlikely((a)->hibernate)) { \ - readl((a)->hw_addr + reg); \ - *(u32 *)pdata = readl((a)->hw_addr + reg); \ - } else { \ - *(u32 *)pdata = readl((a)->hw_addr + reg); \ - } \ - } while (0) - -#define AT_WRITE_REGB(a, reg, value) (\ - writeb((value), ((a)->hw_addr + reg))) - -#define AT_READ_REGB(a, reg) (\ - readb((a)->hw_addr + reg)) - -#define AT_WRITE_REGW(a, reg, value) (\ - writew((value), ((a)->hw_addr + reg))) - -#define AT_READ_REGW(a, reg, pdata) do { \ - if (unlikely((a)->hibernate)) { \ - readw((a)->hw_addr + reg); \ - *(u16 *)pdata = readw((a)->hw_addr + reg); \ - } else { \ - *(u16 *)pdata = readw((a)->hw_addr + reg); \ - } \ - } while (0) - -#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \ - writel((value), (((a)->hw_addr + reg) + ((offset) << 2)))) - -#define AT_READ_REG_ARRAY(a, reg, offset) ( \ - readl(((a)->hw_addr + reg) + ((offset) << 2))) - -extern char atl1c_driver_name[]; -extern char atl1c_driver_version[]; - -extern void atl1c_reinit_locked(struct atl1c_adapter *adapter); -extern s32 atl1c_reset_hw(struct atl1c_hw *hw); -extern void atl1c_set_ethtool_ops(struct net_device *netdev); -#endif /* _ATL1C_H_ */ diff --git a/addons/atl1c/src/3.10.108/atl1c_ethtool.c b/addons/atl1c/src/3.10.108/atl1c_ethtool.c deleted file mode 100644 index 859ea844..00000000 --- a/addons/atl1c/src/3.10.108/atl1c_ethtool.c +++ /dev/null @@ -1,309 +0,0 @@ -/* - * Copyright(c) 2009 - 2009 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include -#include -#include - -#include "atl1c.h" - -static int atl1c_get_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - - ecmd->supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP); - if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M) - ecmd->supported |= SUPPORTED_1000baseT_Full; - - ecmd->advertising = ADVERTISED_TP; - - ecmd->advertising |= hw->autoneg_advertised; - - ecmd->port = PORT_TP; - ecmd->phy_address = 0; - ecmd->transceiver = XCVR_INTERNAL; - - if (adapter->link_speed != SPEED_0) { - ethtool_cmd_speed_set(ecmd, adapter->link_speed); - if (adapter->link_duplex == FULL_DUPLEX) - ecmd->duplex = DUPLEX_FULL; - else - ecmd->duplex = DUPLEX_HALF; - } else { - ethtool_cmd_speed_set(ecmd, -1); - ecmd->duplex = -1; - } - - ecmd->autoneg = AUTONEG_ENABLE; - return 0; -} - -static int atl1c_set_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - u16 autoneg_advertised; - - while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) - msleep(1); - - if (ecmd->autoneg == AUTONEG_ENABLE) { - autoneg_advertised = ADVERTISED_Autoneg; - } else { - u32 speed = ethtool_cmd_speed(ecmd); - if (speed == SPEED_1000) { - if (ecmd->duplex != DUPLEX_FULL) { - if (netif_msg_link(adapter)) - dev_warn(&adapter->pdev->dev, - "1000M half is invalid\n"); - clear_bit(__AT_RESETTING, &adapter->flags); - return -EINVAL; - } - autoneg_advertised = ADVERTISED_1000baseT_Full; - } else if (speed == SPEED_100) { - if (ecmd->duplex == DUPLEX_FULL) - autoneg_advertised = ADVERTISED_100baseT_Full; - else - autoneg_advertised = ADVERTISED_100baseT_Half; - } else { - if (ecmd->duplex == DUPLEX_FULL) - autoneg_advertised = ADVERTISED_10baseT_Full; - else - autoneg_advertised = ADVERTISED_10baseT_Half; - } - } - - if (hw->autoneg_advertised != autoneg_advertised) { - hw->autoneg_advertised = autoneg_advertised; - if (atl1c_restart_autoneg(hw) != 0) { - if (netif_msg_link(adapter)) - dev_warn(&adapter->pdev->dev, - "ethtool speed/duplex setting failed\n"); - clear_bit(__AT_RESETTING, &adapter->flags); - return -EINVAL; - } - } - clear_bit(__AT_RESETTING, &adapter->flags); - return 0; -} - -static u32 atl1c_get_msglevel(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - return adapter->msg_enable; -} - -static void atl1c_set_msglevel(struct net_device *netdev, u32 data) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - adapter->msg_enable = data; -} - -static int atl1c_get_regs_len(struct net_device *netdev) -{ - return AT_REGS_LEN; -} - -static void atl1c_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - u32 *regs_buff = p; - u16 phy_data; - - memset(p, 0, AT_REGS_LEN); - - regs->version = 1; - AT_READ_REG(hw, REG_PM_CTRL, p++); - AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL, p++); - AT_READ_REG(hw, REG_TWSI_CTRL, p++); - AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL, p++); - AT_READ_REG(hw, REG_MASTER_CTRL, p++); - AT_READ_REG(hw, REG_MANUAL_TIMER_INIT, p++); - AT_READ_REG(hw, REG_IRQ_MODRT_TIMER_INIT, p++); - AT_READ_REG(hw, REG_GPHY_CTRL, p++); - AT_READ_REG(hw, REG_LINK_CTRL, p++); - AT_READ_REG(hw, REG_IDLE_STATUS, p++); - AT_READ_REG(hw, REG_MDIO_CTRL, p++); - AT_READ_REG(hw, REG_SERDES, p++); - AT_READ_REG(hw, REG_MAC_CTRL, p++); - AT_READ_REG(hw, REG_MAC_IPG_IFG, p++); - AT_READ_REG(hw, REG_MAC_STA_ADDR, p++); - AT_READ_REG(hw, REG_MAC_STA_ADDR+4, p++); - AT_READ_REG(hw, REG_RX_HASH_TABLE, p++); - AT_READ_REG(hw, REG_RX_HASH_TABLE+4, p++); - AT_READ_REG(hw, REG_RXQ_CTRL, p++); - AT_READ_REG(hw, REG_TXQ_CTRL, p++); - AT_READ_REG(hw, REG_MTU, p++); - AT_READ_REG(hw, REG_WOL_CTRL, p++); - - atl1c_read_phy_reg(hw, MII_BMCR, &phy_data); - regs_buff[AT_REGS_LEN/sizeof(u32) - 2] = (u32) phy_data; - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - regs_buff[AT_REGS_LEN/sizeof(u32) - 1] = (u32) phy_data; -} - -static int atl1c_get_eeprom_len(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - if (atl1c_check_eeprom_exist(&adapter->hw)) - return AT_EEPROM_LEN; - else - return 0; -} - -static int atl1c_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - u32 *eeprom_buff; - int first_dword, last_dword; - int ret_val = 0; - int i; - - if (eeprom->len == 0) - return -EINVAL; - - if (!atl1c_check_eeprom_exist(hw)) /* not exist */ - return -EINVAL; - - eeprom->magic = adapter->pdev->vendor | - (adapter->pdev->device << 16); - - first_dword = eeprom->offset >> 2; - last_dword = (eeprom->offset + eeprom->len - 1) >> 2; - - eeprom_buff = kmalloc(sizeof(u32) * - (last_dword - first_dword + 1), GFP_KERNEL); - if (eeprom_buff == NULL) - return -ENOMEM; - - for (i = first_dword; i < last_dword; i++) { - if (!atl1c_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) { - kfree(eeprom_buff); - return -EIO; - } - } - - memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3), - eeprom->len); - kfree(eeprom_buff); - - return ret_val; - return 0; -} - -static void atl1c_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - strlcpy(drvinfo->driver, atl1c_driver_name, sizeof(drvinfo->driver)); - strlcpy(drvinfo->version, atl1c_driver_version, - sizeof(drvinfo->version)); - strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), - sizeof(drvinfo->bus_info)); - drvinfo->n_stats = 0; - drvinfo->testinfo_len = 0; - drvinfo->regdump_len = atl1c_get_regs_len(netdev); - drvinfo->eedump_len = atl1c_get_eeprom_len(netdev); -} - -static void atl1c_get_wol(struct net_device *netdev, - struct ethtool_wolinfo *wol) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - wol->supported = WAKE_MAGIC | WAKE_PHY; - wol->wolopts = 0; - - if (adapter->wol & AT_WUFC_EX) - wol->wolopts |= WAKE_UCAST; - if (adapter->wol & AT_WUFC_MC) - wol->wolopts |= WAKE_MCAST; - if (adapter->wol & AT_WUFC_BC) - wol->wolopts |= WAKE_BCAST; - if (adapter->wol & AT_WUFC_MAG) - wol->wolopts |= WAKE_MAGIC; - if (adapter->wol & AT_WUFC_LNKC) - wol->wolopts |= WAKE_PHY; -} - -static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | - WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)) - return -EOPNOTSUPP; - /* these settings will always override what we currently have */ - adapter->wol = 0; - - if (wol->wolopts & WAKE_MAGIC) - adapter->wol |= AT_WUFC_MAG; - if (wol->wolopts & WAKE_PHY) - adapter->wol |= AT_WUFC_LNKC; - - device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); - - return 0; -} - -static int atl1c_nway_reset(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - if (netif_running(netdev)) - atl1c_reinit_locked(adapter); - return 0; -} - -static const struct ethtool_ops atl1c_ethtool_ops = { - .get_settings = atl1c_get_settings, - .set_settings = atl1c_set_settings, - .get_drvinfo = atl1c_get_drvinfo, - .get_regs_len = atl1c_get_regs_len, - .get_regs = atl1c_get_regs, - .get_wol = atl1c_get_wol, - .set_wol = atl1c_set_wol, - .get_msglevel = atl1c_get_msglevel, - .set_msglevel = atl1c_set_msglevel, - .nway_reset = atl1c_nway_reset, - .get_link = ethtool_op_get_link, - .get_eeprom_len = atl1c_get_eeprom_len, - .get_eeprom = atl1c_get_eeprom, -}; - -void atl1c_set_ethtool_ops(struct net_device *netdev) -{ - SET_ETHTOOL_OPS(netdev, &atl1c_ethtool_ops); -} diff --git a/addons/atl1c/src/3.10.108/atl1c_hw.c b/addons/atl1c/src/3.10.108/atl1c_hw.c deleted file mode 100644 index 3ef7092e..00000000 --- a/addons/atl1c/src/3.10.108/atl1c_hw.c +++ /dev/null @@ -1,865 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include -#include -#include -#include - -#include "atl1c.h" - -/* - * check_eeprom_exist - * return 1 if eeprom exist - */ -int atl1c_check_eeprom_exist(struct atl1c_hw *hw) -{ - u32 data; - - AT_READ_REG(hw, REG_TWSI_DEBUG, &data); - if (data & TWSI_DEBUG_DEV_EXIST) - return 1; - - AT_READ_REG(hw, REG_MASTER_CTRL, &data); - if (data & MASTER_CTRL_OTP_SEL) - return 1; - return 0; -} - -void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr) -{ - u32 value; - /* - * 00-0B-6A-F6-00-DC - * 0: 6AF600DC 1: 000B - * low dword - */ - value = mac_addr[2] << 24 | - mac_addr[3] << 16 | - mac_addr[4] << 8 | - mac_addr[5]; - AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value); - /* hight dword */ - value = mac_addr[0] << 8 | - mac_addr[1]; - AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value); -} - -/* read mac address from hardware register */ -static bool atl1c_read_current_addr(struct atl1c_hw *hw, u8 *eth_addr) -{ - u32 addr[2]; - - AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]); - AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]); - - *(u32 *) ð_addr[2] = htonl(addr[0]); - *(u16 *) ð_addr[0] = htons((u16)addr[1]); - - return is_valid_ether_addr(eth_addr); -} - -/* - * atl1c_get_permanent_address - * return 0 if get valid mac address, - */ -static int atl1c_get_permanent_address(struct atl1c_hw *hw) -{ - u32 i; - u32 otp_ctrl_data; - u32 twsi_ctrl_data; - u16 phy_data; - bool raise_vol = false; - - /* MAC-address from BIOS is the 1st priority */ - if (atl1c_read_current_addr(hw, hw->perm_mac_addr)) - return 0; - - /* init */ - AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data); - if (atl1c_check_eeprom_exist(hw)) { - if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) { - /* Enable OTP CLK */ - if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) { - otp_ctrl_data |= OTP_CTRL_CLK_EN; - AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); - AT_WRITE_FLUSH(hw); - msleep(1); - } - } - /* raise voltage temporally for l2cb */ - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { - atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data); - phy_data &= ~ANACTRL_HB_EN; - atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data); - atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); - phy_data |= VOLT_CTRL_SWLOWEST; - atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); - udelay(20); - raise_vol = true; - } - - AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); - twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART; - AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data); - for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) { - msleep(10); - AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); - if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0) - break; - } - if (i >= AT_TWSI_EEPROM_TIMEOUT) - return -1; - } - /* Disable OTP_CLK */ - if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) { - otp_ctrl_data &= ~OTP_CTRL_CLK_EN; - AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); - msleep(1); - } - if (raise_vol) { - atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data); - phy_data |= ANACTRL_HB_EN; - atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data); - atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); - phy_data &= ~VOLT_CTRL_SWLOWEST; - atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); - udelay(20); - } - - if (atl1c_read_current_addr(hw, hw->perm_mac_addr)) - return 0; - - return -1; -} - -bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value) -{ - int i; - int ret = false; - u32 otp_ctrl_data; - u32 control; - u32 data; - - if (offset & 3) - return ret; /* address do not align */ - - AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data); - if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) - AT_WRITE_REG(hw, REG_OTP_CTRL, - (otp_ctrl_data | OTP_CTRL_CLK_EN)); - - AT_WRITE_REG(hw, REG_EEPROM_DATA_LO, 0); - control = (offset & EEPROM_CTRL_ADDR_MASK) << EEPROM_CTRL_ADDR_SHIFT; - AT_WRITE_REG(hw, REG_EEPROM_CTRL, control); - - for (i = 0; i < 10; i++) { - udelay(100); - AT_READ_REG(hw, REG_EEPROM_CTRL, &control); - if (control & EEPROM_CTRL_RW) - break; - } - if (control & EEPROM_CTRL_RW) { - AT_READ_REG(hw, REG_EEPROM_CTRL, &data); - AT_READ_REG(hw, REG_EEPROM_DATA_LO, p_value); - data = data & 0xFFFF; - *p_value = swab32((data << 16) | (*p_value >> 16)); - ret = true; - } - if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) - AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); - - return ret; -} -/* - * Reads the adapter's MAC address from the EEPROM - * - * hw - Struct containing variables accessed by shared code - */ -int atl1c_read_mac_addr(struct atl1c_hw *hw) -{ - int err = 0; - - err = atl1c_get_permanent_address(hw); - if (err) - eth_random_addr(hw->perm_mac_addr); - - memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr)); - return err; -} - -/* - * atl1c_hash_mc_addr - * purpose - * set hash value for a multicast address - * hash calcu processing : - * 1. calcu 32bit CRC for multicast address - * 2. reverse crc with MSB to LSB - */ -u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr) -{ - u32 crc32; - u32 value = 0; - int i; - - crc32 = ether_crc_le(6, mc_addr); - for (i = 0; i < 32; i++) - value |= (((crc32 >> i) & 1) << (31 - i)); - - return value; -} - -/* - * Sets the bit in the multicast table corresponding to the hash value. - * hw - Struct containing variables accessed by shared code - * hash_value - Multicast address hash value - */ -void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value) -{ - u32 hash_bit, hash_reg; - u32 mta; - - /* - * The HASH Table is a register array of 2 32-bit registers. - * It is treated like an array of 64 bits. We want to set - * bit BitArray[hash_value]. So we figure out what register - * the bit is in, read it, OR in the new bit, then write - * back the new value. The register is determined by the - * upper bit of the hash value and the bit within that - * register are determined by the lower 5 bits of the value. - */ - hash_reg = (hash_value >> 31) & 0x1; - hash_bit = (hash_value >> 26) & 0x1F; - - mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg); - - mta |= (1 << hash_bit); - - AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta); -} - -/* - * wait mdio module be idle - * return true: idle - * false: still busy - */ -bool atl1c_wait_mdio_idle(struct atl1c_hw *hw) -{ - u32 val; - int i; - - for (i = 0; i < MDIO_MAX_AC_TO; i++) { - AT_READ_REG(hw, REG_MDIO_CTRL, &val); - if (!(val & (MDIO_CTRL_BUSY | MDIO_CTRL_START))) - break; - udelay(10); - } - - return i != MDIO_MAX_AC_TO; -} - -void atl1c_stop_phy_polling(struct atl1c_hw *hw) -{ - if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) - return; - - AT_WRITE_REG(hw, REG_MDIO_CTRL, 0); - atl1c_wait_mdio_idle(hw); -} - -void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel) -{ - u32 val; - - if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) - return; - - val = MDIO_CTRL_SPRES_PRMBL | - FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | - FIELDX(MDIO_CTRL_REG, 1) | - MDIO_CTRL_START | - MDIO_CTRL_OP_READ; - AT_WRITE_REG(hw, REG_MDIO_CTRL, val); - atl1c_wait_mdio_idle(hw); - val |= MDIO_CTRL_AP_EN; - val &= ~MDIO_CTRL_START; - AT_WRITE_REG(hw, REG_MDIO_CTRL, val); - udelay(30); -} - - -/* - * atl1c_read_phy_core - * core funtion to read register in PHY via MDIO control regsiter. - * ext: extension register (see IEEE 802.3) - * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0) - * reg: reg to read - */ -int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, - u16 reg, u16 *phy_data) -{ - u32 val; - u16 clk_sel = MDIO_CTRL_CLK_25_4; - - atl1c_stop_phy_polling(hw); - - *phy_data = 0; - - /* only l2c_b2 & l1d_2 could use slow clock */ - if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) && - hw->hibernate) - clk_sel = MDIO_CTRL_CLK_25_128; - if (ext) { - val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg); - AT_WRITE_REG(hw, REG_MDIO_EXTN, val); - val = MDIO_CTRL_SPRES_PRMBL | - FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | - MDIO_CTRL_START | - MDIO_CTRL_MODE_EXT | - MDIO_CTRL_OP_READ; - } else { - val = MDIO_CTRL_SPRES_PRMBL | - FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | - FIELDX(MDIO_CTRL_REG, reg) | - MDIO_CTRL_START | - MDIO_CTRL_OP_READ; - } - AT_WRITE_REG(hw, REG_MDIO_CTRL, val); - - if (!atl1c_wait_mdio_idle(hw)) - return -1; - - AT_READ_REG(hw, REG_MDIO_CTRL, &val); - *phy_data = (u16)FIELD_GETX(val, MDIO_CTRL_DATA); - - atl1c_start_phy_polling(hw, clk_sel); - - return 0; -} - -/* - * atl1c_write_phy_core - * core funtion to write to register in PHY via MDIO control regsiter. - * ext: extension register (see IEEE 802.3) - * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0) - * reg: reg to write - */ -int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, - u16 reg, u16 phy_data) -{ - u32 val; - u16 clk_sel = MDIO_CTRL_CLK_25_4; - - atl1c_stop_phy_polling(hw); - - - /* only l2c_b2 & l1d_2 could use slow clock */ - if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) && - hw->hibernate) - clk_sel = MDIO_CTRL_CLK_25_128; - - if (ext) { - val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg); - AT_WRITE_REG(hw, REG_MDIO_EXTN, val); - val = MDIO_CTRL_SPRES_PRMBL | - FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | - FIELDX(MDIO_CTRL_DATA, phy_data) | - MDIO_CTRL_START | - MDIO_CTRL_MODE_EXT; - } else { - val = MDIO_CTRL_SPRES_PRMBL | - FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | - FIELDX(MDIO_CTRL_DATA, phy_data) | - FIELDX(MDIO_CTRL_REG, reg) | - MDIO_CTRL_START; - } - AT_WRITE_REG(hw, REG_MDIO_CTRL, val); - - if (!atl1c_wait_mdio_idle(hw)) - return -1; - - atl1c_start_phy_polling(hw, clk_sel); - - return 0; -} - -/* - * Reads the value from a PHY register - * hw - Struct containing variables accessed by shared code - * reg_addr - address of the PHY register to read - */ -int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) -{ - return atl1c_read_phy_core(hw, false, 0, reg_addr, phy_data); -} - -/* - * Writes a value to a PHY register - * hw - Struct containing variables accessed by shared code - * reg_addr - address of the PHY register to write - * data - data to write to the PHY - */ -int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data) -{ - return atl1c_write_phy_core(hw, false, 0, reg_addr, phy_data); -} - -/* read from PHY extension register */ -int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr, - u16 reg_addr, u16 *phy_data) -{ - return atl1c_read_phy_core(hw, true, dev_addr, reg_addr, phy_data); -} - -/* write to PHY extension register */ -int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr, - u16 reg_addr, u16 phy_data) -{ - return atl1c_write_phy_core(hw, true, dev_addr, reg_addr, phy_data); -} - -int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) -{ - int err; - - err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr); - if (unlikely(err)) - return err; - else - err = atl1c_read_phy_reg(hw, MII_DBG_DATA, phy_data); - - return err; -} - -int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data) -{ - int err; - - err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr); - if (unlikely(err)) - return err; - else - err = atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); - - return err; -} - -/* - * Configures PHY autoneg and flow control advertisement settings - * - * hw - Struct containing variables accessed by shared code - */ -static int atl1c_phy_setup_adv(struct atl1c_hw *hw) -{ - u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_ALL; - u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP & - ~GIGA_CR_1000T_SPEED_MASK; - - if (hw->autoneg_advertised & ADVERTISED_10baseT_Half) - mii_adv_data |= ADVERTISE_10HALF; - if (hw->autoneg_advertised & ADVERTISED_10baseT_Full) - mii_adv_data |= ADVERTISE_10FULL; - if (hw->autoneg_advertised & ADVERTISED_100baseT_Half) - mii_adv_data |= ADVERTISE_100HALF; - if (hw->autoneg_advertised & ADVERTISED_100baseT_Full) - mii_adv_data |= ADVERTISE_100FULL; - - if (hw->autoneg_advertised & ADVERTISED_Autoneg) - mii_adv_data |= ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL; - - if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M) { - if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half) - mii_giga_ctrl_data |= ADVERTISE_1000HALF; - if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full) - mii_giga_ctrl_data |= ADVERTISE_1000FULL; - if (hw->autoneg_advertised & ADVERTISED_Autoneg) - mii_giga_ctrl_data |= ADVERTISE_1000HALF | - ADVERTISE_1000FULL; - } - - if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 || - atl1c_write_phy_reg(hw, MII_CTRL1000, mii_giga_ctrl_data) != 0) - return -1; - return 0; -} - -void atl1c_phy_disable(struct atl1c_hw *hw) -{ - atl1c_power_saving(hw, 0); -} - - -int atl1c_phy_reset(struct atl1c_hw *hw) -{ - struct atl1c_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; - u16 phy_data; - u32 phy_ctrl_data, lpi_ctrl; - int err; - - /* reset PHY core */ - AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data); - phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_PHY_IDDQ | - GPHY_CTRL_GATE_25M_EN | GPHY_CTRL_PWDOWN_HW | GPHY_CTRL_CLS); - phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST; - if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) - phy_ctrl_data |= (GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE); - else - phy_ctrl_data &= ~(GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE); - AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data); - AT_WRITE_FLUSH(hw); - udelay(10); - AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data | GPHY_CTRL_EXT_RESET); - AT_WRITE_FLUSH(hw); - udelay(10 * GPHY_CTRL_EXT_RST_TO); /* delay 800us */ - - /* switch clock */ - if (hw->nic_type == athr_l2c_b) { - atl1c_read_phy_dbg(hw, MIIDBG_CFGLPSPD, &phy_data); - atl1c_write_phy_dbg(hw, MIIDBG_CFGLPSPD, - phy_data & ~CFGLPSPD_RSTCNT_CLK125SW); - } - - /* tx-half amplitude issue fix */ - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { - atl1c_read_phy_dbg(hw, MIIDBG_CABLE1TH_DET, &phy_data); - phy_data |= CABLE1TH_DET_EN; - atl1c_write_phy_dbg(hw, MIIDBG_CABLE1TH_DET, phy_data); - } - - /* clear bit3 of dbgport 3B to lower voltage */ - if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) { - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { - atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); - phy_data &= ~VOLT_CTRL_SWLOWEST; - atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); - } - /* power saving config */ - phy_data = - hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ? - L1D_LEGCYPS_DEF : L1C_LEGCYPS_DEF; - atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, phy_data); - /* hib */ - atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, - SYSMODCTRL_IECHOADJ_DEF); - } else { - /* disable pws */ - atl1c_read_phy_dbg(hw, MIIDBG_LEGCYPS, &phy_data); - atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, - phy_data & ~LEGCYPS_EN); - /* disable hibernate */ - atl1c_read_phy_dbg(hw, MIIDBG_HIBNEG, &phy_data); - atl1c_write_phy_dbg(hw, MIIDBG_HIBNEG, - phy_data & HIBNEG_PSHIB_EN); - } - /* disable AZ(EEE) by default */ - if (hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 || - hw->nic_type == athr_l2c_b2) { - AT_READ_REG(hw, REG_LPI_CTRL, &lpi_ctrl); - AT_WRITE_REG(hw, REG_LPI_CTRL, lpi_ctrl & ~LPI_CTRL_EN); - atl1c_write_phy_ext(hw, MIIEXT_ANEG, MIIEXT_LOCAL_EEEADV, 0); - atl1c_write_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL3, - L2CB_CLDCTRL3); - } - - /* other debug port to set */ - atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, ANACTRL_DEF); - atl1c_write_phy_dbg(hw, MIIDBG_SRDSYSMOD, SRDSYSMOD_DEF); - atl1c_write_phy_dbg(hw, MIIDBG_TST10BTCFG, TST10BTCFG_DEF); - /* UNH-IOL test issue, set bit7 */ - atl1c_write_phy_dbg(hw, MIIDBG_TST100BTCFG, - TST100BTCFG_DEF | TST100BTCFG_LITCH_EN); - - /* set phy interrupt mask */ - phy_data = IER_LINK_UP | IER_LINK_DOWN; - err = atl1c_write_phy_reg(hw, MII_IER, phy_data); - if (err) { - if (netif_msg_hw(adapter)) - dev_err(&pdev->dev, - "Error enable PHY linkChange Interrupt\n"); - return err; - } - return 0; -} - -int atl1c_phy_init(struct atl1c_hw *hw) -{ - struct atl1c_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; - int ret_val; - u16 mii_bmcr_data = BMCR_RESET; - - if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &hw->phy_id1) != 0) || - (atl1c_read_phy_reg(hw, MII_PHYSID2, &hw->phy_id2) != 0)) { - dev_err(&pdev->dev, "Error get phy ID\n"); - return -1; - } - switch (hw->media_type) { - case MEDIA_TYPE_AUTO_SENSOR: - ret_val = atl1c_phy_setup_adv(hw); - if (ret_val) { - if (netif_msg_link(adapter)) - dev_err(&pdev->dev, - "Error Setting up Auto-Negotiation\n"); - return ret_val; - } - mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART; - break; - case MEDIA_TYPE_100M_FULL: - mii_bmcr_data |= BMCR_SPEED100 | BMCR_FULLDPLX; - break; - case MEDIA_TYPE_100M_HALF: - mii_bmcr_data |= BMCR_SPEED100; - break; - case MEDIA_TYPE_10M_FULL: - mii_bmcr_data |= BMCR_FULLDPLX; - break; - case MEDIA_TYPE_10M_HALF: - break; - default: - if (netif_msg_link(adapter)) - dev_err(&pdev->dev, "Wrong Media type %d\n", - hw->media_type); - return -1; - break; - } - - ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data); - if (ret_val) - return ret_val; - hw->phy_configured = true; - - return 0; -} - -/* - * Detects the current speed and duplex settings of the hardware. - * - * hw - Struct containing variables accessed by shared code - * speed - Speed of the connection - * duplex - Duplex setting of the connection - */ -int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex) -{ - int err; - u16 phy_data; - - /* Read PHY Specific Status Register (17) */ - err = atl1c_read_phy_reg(hw, MII_GIGA_PSSR, &phy_data); - if (err) - return err; - - if (!(phy_data & GIGA_PSSR_SPD_DPLX_RESOLVED)) - return -1; - - switch (phy_data & GIGA_PSSR_SPEED) { - case GIGA_PSSR_1000MBS: - *speed = SPEED_1000; - break; - case GIGA_PSSR_100MBS: - *speed = SPEED_100; - break; - case GIGA_PSSR_10MBS: - *speed = SPEED_10; - break; - default: - return -1; - break; - } - - if (phy_data & GIGA_PSSR_DPLX) - *duplex = FULL_DUPLEX; - else - *duplex = HALF_DUPLEX; - - return 0; -} - -/* select one link mode to get lower power consumption */ -int atl1c_phy_to_ps_link(struct atl1c_hw *hw) -{ - struct atl1c_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; - int ret = 0; - u16 autoneg_advertised = ADVERTISED_10baseT_Half; - u16 save_autoneg_advertised; - u16 phy_data; - u16 mii_lpa_data; - u16 speed = SPEED_0; - u16 duplex = FULL_DUPLEX; - int i; - - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - if (phy_data & BMSR_LSTATUS) { - atl1c_read_phy_reg(hw, MII_LPA, &mii_lpa_data); - if (mii_lpa_data & LPA_10FULL) - autoneg_advertised = ADVERTISED_10baseT_Full; - else if (mii_lpa_data & LPA_10HALF) - autoneg_advertised = ADVERTISED_10baseT_Half; - else if (mii_lpa_data & LPA_100HALF) - autoneg_advertised = ADVERTISED_100baseT_Half; - else if (mii_lpa_data & LPA_100FULL) - autoneg_advertised = ADVERTISED_100baseT_Full; - - save_autoneg_advertised = hw->autoneg_advertised; - hw->phy_configured = false; - hw->autoneg_advertised = autoneg_advertised; - if (atl1c_restart_autoneg(hw) != 0) { - dev_dbg(&pdev->dev, "phy autoneg failed\n"); - ret = -1; - } - hw->autoneg_advertised = save_autoneg_advertised; - - if (mii_lpa_data) { - for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) { - mdelay(100); - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - if (phy_data & BMSR_LSTATUS) { - if (atl1c_get_speed_and_duplex(hw, &speed, - &duplex) != 0) - dev_dbg(&pdev->dev, - "get speed and duplex failed\n"); - break; - } - } - } - } else { - speed = SPEED_10; - duplex = HALF_DUPLEX; - } - adapter->link_speed = speed; - adapter->link_duplex = duplex; - - return ret; -} - -int atl1c_restart_autoneg(struct atl1c_hw *hw) -{ - int err = 0; - u16 mii_bmcr_data = BMCR_RESET; - - err = atl1c_phy_setup_adv(hw); - if (err) - return err; - mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART; - - return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data); -} - -int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc) -{ - struct atl1c_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; - u32 master_ctrl, mac_ctrl, phy_ctrl; - u32 wol_ctrl, speed; - u16 phy_data; - - wol_ctrl = 0; - speed = adapter->link_speed == SPEED_1000 ? - MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100; - - AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl); - AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl); - AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl); - - master_ctrl &= ~MASTER_CTRL_CLK_SEL_DIS; - mac_ctrl = FIELD_SETX(mac_ctrl, MAC_CTRL_SPEED, speed); - mac_ctrl &= ~(MAC_CTRL_DUPLX | MAC_CTRL_RX_EN | MAC_CTRL_TX_EN); - if (adapter->link_duplex == FULL_DUPLEX) - mac_ctrl |= MAC_CTRL_DUPLX; - phy_ctrl &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS); - phy_ctrl |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE | - GPHY_CTRL_HIB_EN; - if (!wufc) { /* without WoL */ - master_ctrl |= MASTER_CTRL_CLK_SEL_DIS; - phy_ctrl |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW; - AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl); - AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl); - AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl); - AT_WRITE_REG(hw, REG_WOL_CTRL, 0); - hw->phy_configured = false; /* re-init PHY when resume */ - return 0; - } - phy_ctrl |= GPHY_CTRL_EXT_RESET; - if (wufc & AT_WUFC_MAG) { - mac_ctrl |= MAC_CTRL_RX_EN | MAC_CTRL_BC_EN; - wol_ctrl |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN; - if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V11) - wol_ctrl |= WOL_PATTERN_EN | WOL_PATTERN_PME_EN; - } - if (wufc & AT_WUFC_LNKC) { - wol_ctrl |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; - if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) { - dev_dbg(&pdev->dev, "%s: write phy MII_IER failed.\n", - atl1c_driver_name); - } - } - /* clear PHY interrupt */ - atl1c_read_phy_reg(hw, MII_ISR, &phy_data); - - dev_dbg(&pdev->dev, "%s: suspend MAC=%x,MASTER=%x,PHY=0x%x,WOL=%x\n", - atl1c_driver_name, mac_ctrl, master_ctrl, phy_ctrl, wol_ctrl); - AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl); - AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl); - AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl); - AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl); - - return 0; -} - - -/* configure phy after Link change Event */ -void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed) -{ - u16 phy_val; - bool adj_thresh = false; - - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 || - hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2) - adj_thresh = true; - - if (link_speed != SPEED_0) { /* link up */ - /* az with brcm, half-amp */ - if (hw->nic_type == athr_l1d_2) { - atl1c_read_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL6, - &phy_val); - phy_val = FIELD_GETX(phy_val, CLDCTRL6_CAB_LEN); - phy_val = phy_val > CLDCTRL6_CAB_LEN_SHORT ? - AZ_ANADECT_LONG : AZ_ANADECT_DEF; - atl1c_write_phy_dbg(hw, MIIDBG_AZ_ANADECT, phy_val); - } - /* threshold adjust */ - if (adj_thresh && link_speed == SPEED_100 && hw->msi_lnkpatch) { - atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, L1D_MSE16DB_UP); - atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, - L1D_SYSMODCTRL_IECHOADJ_DEF); - } - } else { /* link down */ - if (adj_thresh && hw->msi_lnkpatch) { - atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, - SYSMODCTRL_IECHOADJ_DEF); - atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, - L1D_MSE16DB_DOWN); - } - } -} diff --git a/addons/atl1c/src/3.10.108/atl1c_hw.h b/addons/atl1c/src/3.10.108/atl1c_hw.h deleted file mode 100644 index 21d8c4db..00000000 --- a/addons/atl1c/src/3.10.108/atl1c_hw.h +++ /dev/null @@ -1,1024 +0,0 @@ -/* - * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _ATL1C_HW_H_ -#define _ATL1C_HW_H_ - -#include -#include - -#define FIELD_GETX(_x, _name) ((_x) >> (_name##_SHIFT) & (_name##_MASK)) -#define FIELD_SETX(_x, _name, _v) \ -(((_x) & ~((_name##_MASK) << (_name##_SHIFT))) |\ -(((_v) & (_name##_MASK)) << (_name##_SHIFT))) -#define FIELDX(_name, _v) (((_v) & (_name##_MASK)) << (_name##_SHIFT)) - -struct atl1c_adapter; -struct atl1c_hw; - -/* function prototype */ -void atl1c_phy_disable(struct atl1c_hw *hw); -void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr); -int atl1c_phy_reset(struct atl1c_hw *hw); -int atl1c_read_mac_addr(struct atl1c_hw *hw); -int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex); -u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr); -void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value); -int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data); -int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data); -bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value); -int atl1c_phy_init(struct atl1c_hw *hw); -int atl1c_check_eeprom_exist(struct atl1c_hw *hw); -int atl1c_restart_autoneg(struct atl1c_hw *hw); -int atl1c_phy_to_ps_link(struct atl1c_hw *hw); -int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc); -bool atl1c_wait_mdio_idle(struct atl1c_hw *hw); -void atl1c_stop_phy_polling(struct atl1c_hw *hw); -void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel); -int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, - u16 reg, u16 *phy_data); -int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, - u16 reg, u16 phy_data); -int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr, - u16 reg_addr, u16 *phy_data); -int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr, - u16 reg_addr, u16 phy_data); -int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data); -int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data); -void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed); - -/* hw-ids */ -#define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062 -#define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063 -#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */ -#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */ -#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */ -#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */ -#define L2CB_V10 0xc0 -#define L2CB_V11 0xc1 -#define L2CB_V20 0xc0 -#define L2CB_V21 0xc1 - -/* register definition */ -#define REG_DEVICE_CAP 0x5C -#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7 -#define DEVICE_CAP_MAX_PAYLOAD_SHIFT 0 - -#define DEVICE_CTRL_MAXRRS_MIN 2 - -#define REG_LINK_CTRL 0x68 -#define LINK_CTRL_L0S_EN 0x01 -#define LINK_CTRL_L1_EN 0x02 -#define LINK_CTRL_EXT_SYNC 0x80 - -#define REG_PCIE_IND_ACC_ADDR 0x80 -#define REG_PCIE_IND_ACC_DATA 0x84 - -#define REG_DEV_SERIALNUM_CTRL 0x200 -#define REG_DEV_MAC_SEL_MASK 0x0 /* 0:EUI; 1:MAC */ -#define REG_DEV_MAC_SEL_SHIFT 0 -#define REG_DEV_SERIAL_NUM_EN_MASK 0x1 -#define REG_DEV_SERIAL_NUM_EN_SHIFT 1 - -#define REG_TWSI_CTRL 0x218 -#define TWSI_CTLR_FREQ_MASK 0x3UL -#define TWSI_CTRL_FREQ_SHIFT 24 -#define TWSI_CTRL_FREQ_100K 0 -#define TWSI_CTRL_FREQ_200K 1 -#define TWSI_CTRL_FREQ_300K 2 -#define TWSI_CTRL_FREQ_400K 3 -#define TWSI_CTRL_LD_EXIST BIT(23) -#define TWSI_CTRL_HW_LDSTAT BIT(12) /* 0:finish,1:in progress */ -#define TWSI_CTRL_SW_LDSTART BIT(11) -#define TWSI_CTRL_LD_OFFSET_MASK 0xFF -#define TWSI_CTRL_LD_OFFSET_SHIFT 0 - -#define REG_PCIE_DEV_MISC_CTRL 0x21C -#define PCIE_DEV_MISC_EXT_PIPE 0x2 -#define PCIE_DEV_MISC_RETRY_BUFDIS 0x1 -#define PCIE_DEV_MISC_SPIROM_EXIST 0x4 -#define PCIE_DEV_MISC_SERDES_ENDIAN 0x8 -#define PCIE_DEV_MISC_SERDES_SEL_DIN 0x10 - -#define REG_PCIE_PHYMISC 0x1000 -#define PCIE_PHYMISC_FORCE_RCV_DET BIT(2) -#define PCIE_PHYMISC_NFTS_MASK 0xFFUL -#define PCIE_PHYMISC_NFTS_SHIFT 16 - -#define REG_PCIE_PHYMISC2 0x1004 -#define PCIE_PHYMISC2_L0S_TH_MASK 0x3UL -#define PCIE_PHYMISC2_L0S_TH_SHIFT 18 -#define L2CB1_PCIE_PHYMISC2_L0S_TH 3 -#define PCIE_PHYMISC2_CDR_BW_MASK 0x3UL -#define PCIE_PHYMISC2_CDR_BW_SHIFT 16 -#define L2CB1_PCIE_PHYMISC2_CDR_BW 3 - -#define REG_TWSI_DEBUG 0x1108 -#define TWSI_DEBUG_DEV_EXIST BIT(29) - -#define REG_DMA_DBG 0x1114 -#define DMA_DBG_VENDOR_MSG BIT(0) - -#define REG_EEPROM_CTRL 0x12C0 -#define EEPROM_CTRL_DATA_HI_MASK 0xFFFF -#define EEPROM_CTRL_DATA_HI_SHIFT 0 -#define EEPROM_CTRL_ADDR_MASK 0x3FF -#define EEPROM_CTRL_ADDR_SHIFT 16 -#define EEPROM_CTRL_ACK 0x40000000 -#define EEPROM_CTRL_RW 0x80000000 - -#define REG_EEPROM_DATA_LO 0x12C4 - -#define REG_OTP_CTRL 0x12F0 -#define OTP_CTRL_CLK_EN BIT(1) - -#define REG_PM_CTRL 0x12F8 -#define PM_CTRL_HOTRST BIT(31) -#define PM_CTRL_MAC_ASPM_CHK BIT(30) /* L0s/L1 dis by MAC based on - * thrghput(setting in 15A0) */ -#define PM_CTRL_SA_DLY_EN BIT(29) -#define PM_CTRL_L0S_BUFSRX_EN BIT(28) -#define PM_CTRL_LCKDET_TIMER_MASK 0xFUL -#define PM_CTRL_LCKDET_TIMER_SHIFT 24 -#define PM_CTRL_LCKDET_TIMER_DEF 0xC -#define PM_CTRL_PM_REQ_TIMER_MASK 0xFUL -#define PM_CTRL_PM_REQ_TIMER_SHIFT 20 /* pm_request_l1 time > @ - * ->L0s not L1 */ -#define PM_CTRL_PM_REQ_TO_DEF 0xF -#define PMCTRL_TXL1_AFTER_L0S BIT(19) /* l1dv2.0+ */ -#define L1D_PMCTRL_L1_ENTRY_TM_MASK 7UL /* l1dv2.0+, 3bits */ -#define L1D_PMCTRL_L1_ENTRY_TM_SHIFT 16 -#define L1D_PMCTRL_L1_ENTRY_TM_DIS 0 -#define L1D_PMCTRL_L1_ENTRY_TM_2US 1 -#define L1D_PMCTRL_L1_ENTRY_TM_4US 2 -#define L1D_PMCTRL_L1_ENTRY_TM_8US 3 -#define L1D_PMCTRL_L1_ENTRY_TM_16US 4 -#define L1D_PMCTRL_L1_ENTRY_TM_24US 5 -#define L1D_PMCTRL_L1_ENTRY_TM_32US 6 -#define L1D_PMCTRL_L1_ENTRY_TM_63US 7 -#define PM_CTRL_L1_ENTRY_TIMER_MASK 0xFUL /* l1C 4bits */ -#define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16 -#define L2CB1_PM_CTRL_L1_ENTRY_TM 7 -#define L1C_PM_CTRL_L1_ENTRY_TM 0xF -#define PM_CTRL_RCVR_WT_TIMER BIT(15) /* 1:1us, 0:2ms */ -#define PM_CTRL_CLK_PWM_VER1_1 BIT(14) /* 0:1.0a,1:1.1 */ -#define PM_CTRL_CLK_SWH_L1 BIT(13) /* en pcie clk sw in L1 */ -#define PM_CTRL_ASPM_L0S_EN BIT(12) -#define PM_CTRL_RXL1_AFTER_L0S BIT(11) /* l1dv2.0+ */ -#define L1D_PMCTRL_L0S_TIMER_MASK 7UL /* l1d2.0+, 3bits*/ -#define L1D_PMCTRL_L0S_TIMER_SHIFT 8 -#define PM_CTRL_L0S_ENTRY_TIMER_MASK 0xFUL /* l1c, 4bits */ -#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT 8 -#define PM_CTRL_SERDES_BUFS_RX_L1_EN BIT(7) -#define PM_CTRL_SERDES_PD_EX_L1 BIT(6) /* power down serdes rx */ -#define PM_CTRL_SERDES_PLL_L1_EN BIT(5) -#define PM_CTRL_SERDES_L1_EN BIT(4) -#define PM_CTRL_ASPM_L1_EN BIT(3) -#define PM_CTRL_CLK_REQ_EN BIT(2) -#define PM_CTRL_RBER_EN BIT(1) -#define PM_CTRL_SPRSDWER_EN BIT(0) - -#define REG_LTSSM_ID_CTRL 0x12FC -#define LTSSM_ID_EN_WRO 0x1000 - - -/* Selene Master Control Register */ -#define REG_MASTER_CTRL 0x1400 -#define MASTER_CTRL_OTP_SEL BIT(31) -#define MASTER_DEV_NUM_MASK 0x7FUL -#define MASTER_DEV_NUM_SHIFT 24 -#define MASTER_REV_NUM_MASK 0xFFUL -#define MASTER_REV_NUM_SHIFT 16 -#define MASTER_CTRL_INT_RDCLR BIT(14) -#define MASTER_CTRL_CLK_SEL_DIS BIT(12) /* 1:alwys sel pclk from - * serdes, not sw to 25M */ -#define MASTER_CTRL_RX_ITIMER_EN BIT(11) /* IRQ MODURATION FOR RX */ -#define MASTER_CTRL_TX_ITIMER_EN BIT(10) /* MODURATION FOR TX/RX */ -#define MASTER_CTRL_MANU_INT BIT(9) /* SOFT MANUAL INT */ -#define MASTER_CTRL_MANUTIMER_EN BIT(8) -#define MASTER_CTRL_SA_TIMER_EN BIT(7) /* SYS ALIVE TIMER EN */ -#define MASTER_CTRL_OOB_DIS BIT(6) /* OUT OF BOX DIS */ -#define MASTER_CTRL_WAKEN_25M BIT(5) /* WAKE WO. PCIE CLK */ -#define MASTER_CTRL_BERT_START BIT(4) -#define MASTER_PCIE_TSTMOD_MASK 3UL -#define MASTER_PCIE_TSTMOD_SHIFT 2 -#define MASTER_PCIE_RST BIT(1) -#define MASTER_CTRL_SOFT_RST BIT(0) /* RST MAC & DMA */ -#define DMA_MAC_RST_TO 50 - -/* Timer Initial Value Register */ -#define REG_MANUAL_TIMER_INIT 0x1404 - -/* IRQ ModeratorTimer Initial Value Register */ -#define REG_IRQ_MODRT_TIMER_INIT 0x1408 -#define IRQ_MODRT_TIMER_MASK 0xffff -#define IRQ_MODRT_TX_TIMER_SHIFT 0 -#define IRQ_MODRT_RX_TIMER_SHIFT 16 - -#define REG_GPHY_CTRL 0x140C -#define GPHY_CTRL_ADDR_MASK 0x1FUL -#define GPHY_CTRL_ADDR_SHIFT 19 -#define GPHY_CTRL_BP_VLTGSW BIT(18) -#define GPHY_CTRL_100AB_EN BIT(17) -#define GPHY_CTRL_10AB_EN BIT(16) -#define GPHY_CTRL_PHY_PLL_BYPASS BIT(15) -#define GPHY_CTRL_PWDOWN_HW BIT(14) /* affect MAC&PHY, to low pw */ -#define GPHY_CTRL_PHY_PLL_ON BIT(13) /* 1:pll always on, 0:can sw */ -#define GPHY_CTRL_SEL_ANA_RST BIT(12) -#define GPHY_CTRL_HIB_PULSE BIT(11) -#define GPHY_CTRL_HIB_EN BIT(10) -#define GPHY_CTRL_GIGA_DIS BIT(9) -#define GPHY_CTRL_PHY_IDDQ_DIS BIT(8) /* pw on RST */ -#define GPHY_CTRL_PHY_IDDQ BIT(7) /* bit8 affect bit7 while rb */ -#define GPHY_CTRL_LPW_EXIT BIT(6) -#define GPHY_CTRL_GATE_25M_EN BIT(5) -#define GPHY_CTRL_REV_ANEG BIT(4) -#define GPHY_CTRL_ANEG_NOW BIT(3) -#define GPHY_CTRL_LED_MODE BIT(2) -#define GPHY_CTRL_RTL_MODE BIT(1) -#define GPHY_CTRL_EXT_RESET BIT(0) /* 1:out of DSP RST status */ -#define GPHY_CTRL_EXT_RST_TO 80 /* 800us atmost */ -#define GPHY_CTRL_CLS (\ - GPHY_CTRL_LED_MODE |\ - GPHY_CTRL_100AB_EN |\ - GPHY_CTRL_PHY_PLL_ON) - -/* Block IDLE Status Register */ -#define REG_IDLE_STATUS 0x1410 -#define IDLE_STATUS_SFORCE_MASK 0xFUL -#define IDLE_STATUS_SFORCE_SHIFT 14 -#define IDLE_STATUS_CALIB_DONE BIT(13) -#define IDLE_STATUS_CALIB_RES_MASK 0x1FUL -#define IDLE_STATUS_CALIB_RES_SHIFT 8 -#define IDLE_STATUS_CALIBERR_MASK 0xFUL -#define IDLE_STATUS_CALIBERR_SHIFT 4 -#define IDLE_STATUS_TXQ_BUSY BIT(3) -#define IDLE_STATUS_RXQ_BUSY BIT(2) -#define IDLE_STATUS_TXMAC_BUSY BIT(1) -#define IDLE_STATUS_RXMAC_BUSY BIT(0) -#define IDLE_STATUS_MASK (\ - IDLE_STATUS_TXQ_BUSY |\ - IDLE_STATUS_RXQ_BUSY |\ - IDLE_STATUS_TXMAC_BUSY |\ - IDLE_STATUS_RXMAC_BUSY) - -/* MDIO Control Register */ -#define REG_MDIO_CTRL 0x1414 -#define MDIO_CTRL_MODE_EXT BIT(30) -#define MDIO_CTRL_POST_READ BIT(29) -#define MDIO_CTRL_AP_EN BIT(28) -#define MDIO_CTRL_BUSY BIT(27) -#define MDIO_CTRL_CLK_SEL_MASK 0x7UL -#define MDIO_CTRL_CLK_SEL_SHIFT 24 -#define MDIO_CTRL_CLK_25_4 0 /* 25MHz divide 4 */ -#define MDIO_CTRL_CLK_25_6 2 -#define MDIO_CTRL_CLK_25_8 3 -#define MDIO_CTRL_CLK_25_10 4 -#define MDIO_CTRL_CLK_25_32 5 -#define MDIO_CTRL_CLK_25_64 6 -#define MDIO_CTRL_CLK_25_128 7 -#define MDIO_CTRL_START BIT(23) -#define MDIO_CTRL_SPRES_PRMBL BIT(22) -#define MDIO_CTRL_OP_READ BIT(21) /* 1:read, 0:write */ -#define MDIO_CTRL_REG_MASK 0x1FUL -#define MDIO_CTRL_REG_SHIFT 16 -#define MDIO_CTRL_DATA_MASK 0xFFFFUL -#define MDIO_CTRL_DATA_SHIFT 0 -#define MDIO_MAX_AC_TO 120 /* 1.2ms timeout for slow clk */ - -/* for extension reg access */ -#define REG_MDIO_EXTN 0x1448 -#define MDIO_EXTN_PORTAD_MASK 0x1FUL -#define MDIO_EXTN_PORTAD_SHIFT 21 -#define MDIO_EXTN_DEVAD_MASK 0x1FUL -#define MDIO_EXTN_DEVAD_SHIFT 16 -#define MDIO_EXTN_REG_MASK 0xFFFFUL -#define MDIO_EXTN_REG_SHIFT 0 - -/* BIST Control and Status Register0 (for the Packet Memory) */ -#define REG_BIST0_CTRL 0x141c -#define BIST0_NOW 0x1 -#define BIST0_SRAM_FAIL 0x2 /* 1: The SRAM failure is - * un-repairable because - * it has address decoder - * failure or more than 1 cell - * stuck-to-x failure */ -#define BIST0_FUSE_FLAG 0x4 - -/* BIST Control and Status Register1(for the retry buffer of PCI Express) */ -#define REG_BIST1_CTRL 0x1420 -#define BIST1_NOW 0x1 -#define BIST1_SRAM_FAIL 0x2 -#define BIST1_FUSE_FLAG 0x4 - -/* SerDes Lock Detect Control and Status Register */ -#define REG_SERDES 0x1424 -#define SERDES_PHY_CLK_SLOWDOWN BIT(18) -#define SERDES_MAC_CLK_SLOWDOWN BIT(17) -#define SERDES_SELFB_PLL_MASK 0x3UL -#define SERDES_SELFB_PLL_SHIFT 14 -#define SERDES_PHYCLK_SEL_GTX BIT(13) /* 1:gtx_clk, 0:25M */ -#define SERDES_PCIECLK_SEL_SRDS BIT(12) /* 1:serdes,0:25M */ -#define SERDES_BUFS_RX_EN BIT(11) -#define SERDES_PD_RX BIT(10) -#define SERDES_PLL_EN BIT(9) -#define SERDES_EN BIT(8) -#define SERDES_SELFB_PLL_SEL_CSR BIT(6) /* 0:state-machine,1:csr */ -#define SERDES_SELFB_PLL_CSR_MASK 0x3UL -#define SERDES_SELFB_PLL_CSR_SHIFT 4 -#define SERDES_SELFB_PLL_CSR_4 3 /* 4-12% OV-CLK */ -#define SERDES_SELFB_PLL_CSR_0 2 /* 0-4% OV-CLK */ -#define SERDES_SELFB_PLL_CSR_12 1 /* 12-18% OV-CLK */ -#define SERDES_SELFB_PLL_CSR_18 0 /* 18-25% OV-CLK */ -#define SERDES_VCO_SLOW BIT(3) -#define SERDES_VCO_FAST BIT(2) -#define SERDES_LOCK_DETECT_EN BIT(1) -#define SERDES_LOCK_DETECT BIT(0) - -#define REG_LPI_DECISN_TIMER 0x143C -#define L2CB_LPI_DESISN_TIMER 0x7D00 - -#define REG_LPI_CTRL 0x1440 -#define LPI_CTRL_CHK_DA BIT(31) -#define LPI_CTRL_ENH_TO_MASK 0x1FFFUL -#define LPI_CTRL_ENH_TO_SHIFT 12 -#define LPI_CTRL_ENH_TH_MASK 0x1FUL -#define LPI_CTRL_ENH_TH_SHIFT 6 -#define LPI_CTRL_ENH_EN BIT(5) -#define LPI_CTRL_CHK_RX BIT(4) -#define LPI_CTRL_CHK_STATE BIT(3) -#define LPI_CTRL_GMII BIT(2) -#define LPI_CTRL_TO_PHY BIT(1) -#define LPI_CTRL_EN BIT(0) - -#define REG_LPI_WAIT 0x1444 -#define LPI_WAIT_TIMER_MASK 0xFFFFUL -#define LPI_WAIT_TIMER_SHIFT 0 - -/* MAC Control Register */ -#define REG_MAC_CTRL 0x1480 -#define MAC_CTRL_SPEED_MODE_SW BIT(30) /* 0:phy,1:sw */ -#define MAC_CTRL_HASH_ALG_CRC32 BIT(29) /* 1:legacy,0:lw_5b */ -#define MAC_CTRL_SINGLE_PAUSE_EN BIT(28) -#define MAC_CTRL_DBG BIT(27) -#define MAC_CTRL_BC_EN BIT(26) -#define MAC_CTRL_MC_ALL_EN BIT(25) -#define MAC_CTRL_RX_CHKSUM_EN BIT(24) -#define MAC_CTRL_TX_HUGE BIT(23) -#define MAC_CTRL_DBG_TX_BKPRESURE BIT(22) -#define MAC_CTRL_SPEED_MASK 3UL -#define MAC_CTRL_SPEED_SHIFT 20 -#define MAC_CTRL_SPEED_10_100 1 -#define MAC_CTRL_SPEED_1000 2 -#define MAC_CTRL_TX_SIMURST BIT(19) -#define MAC_CTRL_SCNT BIT(17) -#define MAC_CTRL_TX_PAUSE BIT(16) -#define MAC_CTRL_PROMIS_EN BIT(15) -#define MAC_CTRL_RMV_VLAN BIT(14) -#define MAC_CTRL_PRMLEN_MASK 0xFUL -#define MAC_CTRL_PRMLEN_SHIFT 10 -#define MAC_CTRL_HUGE_EN BIT(9) -#define MAC_CTRL_LENCHK BIT(8) -#define MAC_CTRL_PAD BIT(7) -#define MAC_CTRL_ADD_CRC BIT(6) -#define MAC_CTRL_DUPLX BIT(5) -#define MAC_CTRL_LOOPBACK BIT(4) -#define MAC_CTRL_RX_FLOW BIT(3) -#define MAC_CTRL_TX_FLOW BIT(2) -#define MAC_CTRL_RX_EN BIT(1) -#define MAC_CTRL_TX_EN BIT(0) - -/* MAC IPG/IFG Control Register */ -#define REG_MAC_IPG_IFG 0x1484 -#define MAC_IPG_IFG_IPGT_SHIFT 0 /* Desired back to back - * inter-packet gap. The - * default is 96-bit time */ -#define MAC_IPG_IFG_IPGT_MASK 0x7f -#define MAC_IPG_IFG_MIFG_SHIFT 8 /* Minimum number of IFG to - * enforce in between RX frames */ -#define MAC_IPG_IFG_MIFG_MASK 0xff /* Frame gap below such IFP is dropped */ -#define MAC_IPG_IFG_IPGR1_SHIFT 16 /* 64bit Carrier-Sense window */ -#define MAC_IPG_IFG_IPGR1_MASK 0x7f -#define MAC_IPG_IFG_IPGR2_SHIFT 24 /* 96-bit IPG window */ -#define MAC_IPG_IFG_IPGR2_MASK 0x7f - -/* MAC STATION ADDRESS */ -#define REG_MAC_STA_ADDR 0x1488 - -/* Hash table for multicast address */ -#define REG_RX_HASH_TABLE 0x1490 - -/* MAC Half-Duplex Control Register */ -#define REG_MAC_HALF_DUPLX_CTRL 0x1498 -#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT 0 /* Collision Window */ -#define MAC_HALF_DUPLX_CTRL_LCOL_MASK 0x3ff -#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12 -#define MAC_HALF_DUPLX_CTRL_RETRY_MASK 0xf -#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN 0x10000 -#define MAC_HALF_DUPLX_CTRL_NO_BACK_C 0x20000 -#define MAC_HALF_DUPLX_CTRL_NO_BACK_P 0x40000 /* No back-off on backpressure, - * immediately start the - * transmission after back pressure */ -#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */ -#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20 /* Maximum binary exponential number */ -#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xf -#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24 /* IPG to start JAM for collision based flow control in half-duplex */ -#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xf /* mode. In unit of 8-bit time */ - -/* Maximum Frame Length Control Register */ -#define REG_MTU 0x149c - -/* Wake-On-Lan control register */ -#define REG_WOL_CTRL 0x14a0 -#define WOL_PT7_MATCH BIT(31) -#define WOL_PT6_MATCH BIT(30) -#define WOL_PT5_MATCH BIT(29) -#define WOL_PT4_MATCH BIT(28) -#define WOL_PT3_MATCH BIT(27) -#define WOL_PT2_MATCH BIT(26) -#define WOL_PT1_MATCH BIT(25) -#define WOL_PT0_MATCH BIT(24) -#define WOL_PT7_EN BIT(23) -#define WOL_PT6_EN BIT(22) -#define WOL_PT5_EN BIT(21) -#define WOL_PT4_EN BIT(20) -#define WOL_PT3_EN BIT(19) -#define WOL_PT2_EN BIT(18) -#define WOL_PT1_EN BIT(17) -#define WOL_PT0_EN BIT(16) -#define WOL_LNKCHG_ST BIT(10) -#define WOL_MAGIC_ST BIT(9) -#define WOL_PATTERN_ST BIT(8) -#define WOL_OOB_EN BIT(6) -#define WOL_LINK_CHG_PME_EN BIT(5) -#define WOL_LINK_CHG_EN BIT(4) -#define WOL_MAGIC_PME_EN BIT(3) -#define WOL_MAGIC_EN BIT(2) -#define WOL_PATTERN_PME_EN BIT(1) -#define WOL_PATTERN_EN BIT(0) - -/* WOL Length ( 2 DWORD ) */ -#define REG_WOL_PTLEN1 0x14A4 -#define WOL_PTLEN1_3_MASK 0xFFUL -#define WOL_PTLEN1_3_SHIFT 24 -#define WOL_PTLEN1_2_MASK 0xFFUL -#define WOL_PTLEN1_2_SHIFT 16 -#define WOL_PTLEN1_1_MASK 0xFFUL -#define WOL_PTLEN1_1_SHIFT 8 -#define WOL_PTLEN1_0_MASK 0xFFUL -#define WOL_PTLEN1_0_SHIFT 0 - -#define REG_WOL_PTLEN2 0x14A8 -#define WOL_PTLEN2_7_MASK 0xFFUL -#define WOL_PTLEN2_7_SHIFT 24 -#define WOL_PTLEN2_6_MASK 0xFFUL -#define WOL_PTLEN2_6_SHIFT 16 -#define WOL_PTLEN2_5_MASK 0xFFUL -#define WOL_PTLEN2_5_SHIFT 8 -#define WOL_PTLEN2_4_MASK 0xFFUL -#define WOL_PTLEN2_4_SHIFT 0 - -/* Internal SRAM Partition Register */ -#define RFDX_HEAD_ADDR_MASK 0x03FF -#define RFDX_HARD_ADDR_SHIFT 0 -#define RFDX_TAIL_ADDR_MASK 0x03FF -#define RFDX_TAIL_ADDR_SHIFT 16 - -#define REG_SRAM_RFD0_INFO 0x1500 -#define REG_SRAM_RFD1_INFO 0x1504 -#define REG_SRAM_RFD2_INFO 0x1508 -#define REG_SRAM_RFD3_INFO 0x150C - -#define REG_RFD_NIC_LEN 0x1510 /* In 8-bytes */ -#define RFD_NIC_LEN_MASK 0x03FF - -#define REG_SRAM_TRD_ADDR 0x1518 -#define TPD_HEAD_ADDR_MASK 0x03FF -#define TPD_HEAD_ADDR_SHIFT 0 -#define TPD_TAIL_ADDR_MASK 0x03FF -#define TPD_TAIL_ADDR_SHIFT 16 - -#define REG_SRAM_TRD_LEN 0x151C /* In 8-bytes */ -#define TPD_NIC_LEN_MASK 0x03FF - -#define REG_SRAM_RXF_ADDR 0x1520 -#define REG_SRAM_RXF_LEN 0x1524 -#define REG_SRAM_TXF_ADDR 0x1528 -#define REG_SRAM_TXF_LEN 0x152C -#define REG_SRAM_TCPH_ADDR 0x1530 -#define REG_SRAM_PKTH_ADDR 0x1532 - -/* - * Load Ptr Register - * Software sets this bit after the initialization of the head and tail */ -#define REG_LOAD_PTR 0x1534 - -/* - * addresses of all descriptors, as well as the following descriptor - * control register, which triggers each function block to load the head - * pointer to prepare for the operation. This bit is then self-cleared - * after one cycle. - */ -#define REG_RX_BASE_ADDR_HI 0x1540 -#define REG_TX_BASE_ADDR_HI 0x1544 -#define REG_RFD0_HEAD_ADDR_LO 0x1550 -#define REG_RFD_RING_SIZE 0x1560 -#define RFD_RING_SIZE_MASK 0x0FFF -#define REG_RX_BUF_SIZE 0x1564 -#define RX_BUF_SIZE_MASK 0xFFFF -#define REG_RRD0_HEAD_ADDR_LO 0x1568 -#define REG_RRD_RING_SIZE 0x1578 -#define RRD_RING_SIZE_MASK 0x0FFF -#define REG_TPD_PRI1_ADDR_LO 0x157C -#define REG_TPD_PRI0_ADDR_LO 0x1580 -#define REG_TPD_RING_SIZE 0x1584 -#define TPD_RING_SIZE_MASK 0xFFFF - -/* TXQ Control Register */ -#define REG_TXQ_CTRL 0x1590 -#define TXQ_TXF_BURST_NUM_MASK 0xFFFFUL -#define TXQ_TXF_BURST_NUM_SHIFT 16 -#define L1C_TXQ_TXF_BURST_PREF 0x200 -#define L2CB_TXQ_TXF_BURST_PREF 0x40 -#define TXQ_CTRL_PEDING_CLR BIT(8) -#define TXQ_CTRL_LS_8023_EN BIT(7) -#define TXQ_CTRL_ENH_MODE BIT(6) -#define TXQ_CTRL_EN BIT(5) -#define TXQ_CTRL_IP_OPTION_EN BIT(4) -#define TXQ_NUM_TPD_BURST_MASK 0xFUL -#define TXQ_NUM_TPD_BURST_SHIFT 0 -#define TXQ_NUM_TPD_BURST_DEF 5 -#define TXQ_CFGV (\ - FIELDX(TXQ_NUM_TPD_BURST, TXQ_NUM_TPD_BURST_DEF) |\ - TXQ_CTRL_ENH_MODE |\ - TXQ_CTRL_LS_8023_EN |\ - TXQ_CTRL_IP_OPTION_EN) -#define L1C_TXQ_CFGV (\ - TXQ_CFGV |\ - FIELDX(TXQ_TXF_BURST_NUM, L1C_TXQ_TXF_BURST_PREF)) -#define L2CB_TXQ_CFGV (\ - TXQ_CFGV |\ - FIELDX(TXQ_TXF_BURST_NUM, L2CB_TXQ_TXF_BURST_PREF)) - - -/* Jumbo packet Threshold for task offload */ -#define REG_TX_TSO_OFFLOAD_THRESH 0x1594 /* In 8-bytes */ -#define TX_TSO_OFFLOAD_THRESH_MASK 0x07FF -#define MAX_TSO_FRAME_SIZE (7*1024) - -#define REG_TXF_WATER_MARK 0x1598 /* In 8-bytes */ -#define TXF_WATER_MARK_MASK 0x0FFF -#define TXF_LOW_WATER_MARK_SHIFT 0 -#define TXF_HIGH_WATER_MARK_SHIFT 16 -#define TXQ_CTRL_BURST_MODE_EN 0x80000000 - -#define REG_THRUPUT_MON_CTRL 0x159C -#define THRUPUT_MON_RATE_MASK 0x3 -#define THRUPUT_MON_RATE_SHIFT 0 -#define THRUPUT_MON_EN 0x80 - -/* RXQ Control Register */ -#define REG_RXQ_CTRL 0x15A0 -#define ASPM_THRUPUT_LIMIT_MASK 0x3 -#define ASPM_THRUPUT_LIMIT_SHIFT 0 -#define ASPM_THRUPUT_LIMIT_NO 0x00 -#define ASPM_THRUPUT_LIMIT_1M 0x01 -#define ASPM_THRUPUT_LIMIT_10M 0x02 -#define ASPM_THRUPUT_LIMIT_100M 0x03 -#define IPV6_CHKSUM_CTRL_EN BIT(7) -#define RXQ_RFD_BURST_NUM_MASK 0x003F -#define RXQ_RFD_BURST_NUM_SHIFT 20 -#define RXQ_NUM_RFD_PREF_DEF 8 -#define RSS_MODE_MASK 3UL -#define RSS_MODE_SHIFT 26 -#define RSS_MODE_DIS 0 -#define RSS_MODE_SQSI 1 -#define RSS_MODE_MQSI 2 -#define RSS_MODE_MQMI 3 -#define RSS_NIP_QUEUE_SEL BIT(28) /* 0:q0, 1:table */ -#define RRS_HASH_CTRL_EN BIT(29) -#define RX_CUT_THRU_EN BIT(30) -#define RXQ_CTRL_EN BIT(31) - -#define REG_RFD_FREE_THRESH 0x15A4 -#define RFD_FREE_THRESH_MASK 0x003F -#define RFD_FREE_HI_THRESH_SHIFT 0 -#define RFD_FREE_LO_THRESH_SHIFT 6 - -/* RXF flow control register */ -#define REG_RXQ_RXF_PAUSE_THRESH 0x15A8 -#define RXQ_RXF_PAUSE_TH_HI_SHIFT 0 -#define RXQ_RXF_PAUSE_TH_HI_MASK 0x0FFF -#define RXQ_RXF_PAUSE_TH_LO_SHIFT 16 -#define RXQ_RXF_PAUSE_TH_LO_MASK 0x0FFF - -#define REG_RXD_DMA_CTRL 0x15AC -#define RXD_DMA_THRESH_MASK 0x0FFF /* In 8-bytes */ -#define RXD_DMA_THRESH_SHIFT 0 -#define RXD_DMA_DOWN_TIMER_MASK 0xFFFF -#define RXD_DMA_DOWN_TIMER_SHIFT 16 - -/* DMA Engine Control Register */ -#define REG_DMA_CTRL 0x15C0 -#define DMA_CTRL_SMB_NOW BIT(31) -#define DMA_CTRL_WPEND_CLR BIT(30) -#define DMA_CTRL_RPEND_CLR BIT(29) -#define DMA_CTRL_WDLY_CNT_MASK 0xFUL -#define DMA_CTRL_WDLY_CNT_SHIFT 16 -#define DMA_CTRL_WDLY_CNT_DEF 4 -#define DMA_CTRL_RDLY_CNT_MASK 0x1FUL -#define DMA_CTRL_RDLY_CNT_SHIFT 11 -#define DMA_CTRL_RDLY_CNT_DEF 15 -#define DMA_CTRL_RREQ_PRI_DATA BIT(10) /* 0:tpd, 1:data */ -#define DMA_CTRL_WREQ_BLEN_MASK 7UL -#define DMA_CTRL_WREQ_BLEN_SHIFT 7 -#define DMA_CTRL_RREQ_BLEN_MASK 7UL -#define DMA_CTRL_RREQ_BLEN_SHIFT 4 -#define L1C_CTRL_DMA_RCB_LEN128 BIT(3) /* 0:64bytes,1:128bytes */ -#define DMA_CTRL_RORDER_MODE_MASK 7UL -#define DMA_CTRL_RORDER_MODE_SHIFT 0 -#define DMA_CTRL_RORDER_MODE_OUT 4 -#define DMA_CTRL_RORDER_MODE_ENHANCE 2 -#define DMA_CTRL_RORDER_MODE_IN 1 - -/* INT-triggle/SMB Control Register */ -#define REG_SMB_STAT_TIMER 0x15C4 /* 2us resolution */ -#define SMB_STAT_TIMER_MASK 0xFFFFFF -#define REG_TINT_TPD_THRESH 0x15C8 /* tpd th to trig intrrupt */ - -/* Mail box */ -#define MB_RFDX_PROD_IDX_MASK 0xFFFF -#define REG_MB_RFD0_PROD_IDX 0x15E0 - -#define REG_TPD_PRI1_PIDX 0x15F0 /* 16bit,hi-tpd producer idx */ -#define REG_TPD_PRI0_PIDX 0x15F2 /* 16bit,lo-tpd producer idx */ -#define REG_TPD_PRI1_CIDX 0x15F4 /* 16bit,hi-tpd consumer idx */ -#define REG_TPD_PRI0_CIDX 0x15F6 /* 16bit,lo-tpd consumer idx */ - -#define REG_MB_RFD01_CONS_IDX 0x15F8 -#define MB_RFD0_CONS_IDX_MASK 0x0000FFFF -#define MB_RFD1_CONS_IDX_MASK 0xFFFF0000 - -/* Interrupt Status Register */ -#define REG_ISR 0x1600 -#define ISR_SMB 0x00000001 -#define ISR_TIMER 0x00000002 -/* - * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set - * in Table 51 Selene Master Control Register (Offset 0x1400). - */ -#define ISR_MANUAL 0x00000004 -#define ISR_HW_RXF_OV 0x00000008 /* RXF overflow interrupt */ -#define ISR_RFD0_UR 0x00000010 /* RFD0 under run */ -#define ISR_RFD1_UR 0x00000020 -#define ISR_RFD2_UR 0x00000040 -#define ISR_RFD3_UR 0x00000080 -#define ISR_TXF_UR 0x00000100 -#define ISR_DMAR_TO_RST 0x00000200 -#define ISR_DMAW_TO_RST 0x00000400 -#define ISR_TX_CREDIT 0x00000800 -#define ISR_GPHY 0x00001000 -/* GPHY low power state interrupt */ -#define ISR_GPHY_LPW 0x00002000 -#define ISR_TXQ_TO_RST 0x00004000 -#define ISR_TX_PKT 0x00008000 -#define ISR_RX_PKT_0 0x00010000 -#define ISR_RX_PKT_1 0x00020000 -#define ISR_RX_PKT_2 0x00040000 -#define ISR_RX_PKT_3 0x00080000 -#define ISR_MAC_RX 0x00100000 -#define ISR_MAC_TX 0x00200000 -#define ISR_UR_DETECTED 0x00400000 -#define ISR_FERR_DETECTED 0x00800000 -#define ISR_NFERR_DETECTED 0x01000000 -#define ISR_CERR_DETECTED 0x02000000 -#define ISR_PHY_LINKDOWN 0x04000000 -#define ISR_DIS_INT 0x80000000 - -/* Interrupt Mask Register */ -#define REG_IMR 0x1604 - -#define IMR_NORMAL_MASK (\ - ISR_MANUAL |\ - ISR_HW_RXF_OV |\ - ISR_RFD0_UR |\ - ISR_TXF_UR |\ - ISR_DMAR_TO_RST |\ - ISR_TXQ_TO_RST |\ - ISR_DMAW_TO_RST |\ - ISR_GPHY |\ - ISR_TX_PKT |\ - ISR_RX_PKT_0 |\ - ISR_GPHY_LPW |\ - ISR_PHY_LINKDOWN) - -#define ISR_RX_PKT (\ - ISR_RX_PKT_0 |\ - ISR_RX_PKT_1 |\ - ISR_RX_PKT_2 |\ - ISR_RX_PKT_3) - -#define ISR_OVER (\ - ISR_RFD0_UR |\ - ISR_RFD1_UR |\ - ISR_RFD2_UR |\ - ISR_RFD3_UR |\ - ISR_HW_RXF_OV |\ - ISR_TXF_UR) - -#define ISR_ERROR (\ - ISR_DMAR_TO_RST |\ - ISR_TXQ_TO_RST |\ - ISR_DMAW_TO_RST |\ - ISR_PHY_LINKDOWN) - -#define REG_INT_RETRIG_TIMER 0x1608 -#define INT_RETRIG_TIMER_MASK 0xFFFF - -#define REG_MAC_RX_STATUS_BIN 0x1700 -#define REG_MAC_RX_STATUS_END 0x175c -#define REG_MAC_TX_STATUS_BIN 0x1760 -#define REG_MAC_TX_STATUS_END 0x17c0 - -#define REG_CLK_GATING_CTRL 0x1814 -#define CLK_GATING_DMAW_EN 0x0001 -#define CLK_GATING_DMAR_EN 0x0002 -#define CLK_GATING_TXQ_EN 0x0004 -#define CLK_GATING_RXQ_EN 0x0008 -#define CLK_GATING_TXMAC_EN 0x0010 -#define CLK_GATING_RXMAC_EN 0x0020 - -#define CLK_GATING_EN_ALL (CLK_GATING_DMAW_EN |\ - CLK_GATING_DMAR_EN |\ - CLK_GATING_TXQ_EN |\ - CLK_GATING_RXQ_EN |\ - CLK_GATING_TXMAC_EN|\ - CLK_GATING_RXMAC_EN) - -/* DEBUG ADDR */ -#define REG_DEBUG_DATA0 0x1900 -#define REG_DEBUG_DATA1 0x1904 - -#define L1D_MPW_PHYID1 0xD01C /* V7 */ -#define L1D_MPW_PHYID2 0xD01D /* V1-V6 */ -#define L1D_MPW_PHYID3 0xD01E /* V8 */ - - -/* Autoneg Advertisement Register */ -#define ADVERTISE_DEFAULT_CAP \ - (ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM) - -/* 1000BASE-T Control Register */ -#define GIGA_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port 0=DTE device */ - -#define GIGA_CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master 0=Configure PHY as Slave */ -#define GIGA_CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value 0=Automatic Master/Slave config */ -#define GIGA_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ -#define GIGA_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ -#define GIGA_CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ -#define GIGA_CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ -#define GIGA_CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ -#define GIGA_CR_1000T_SPEED_MASK 0x0300 -#define GIGA_CR_1000T_DEFAULT_CAP 0x0300 - -/* PHY Specific Status Register */ -#define MII_GIGA_PSSR 0x11 -#define GIGA_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ -#define GIGA_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ -#define GIGA_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ -#define GIGA_PSSR_10MBS 0x0000 /* 00=10Mbs */ -#define GIGA_PSSR_100MBS 0x4000 /* 01=100Mbs */ -#define GIGA_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ - -/* PHY Interrupt Enable Register */ -#define MII_IER 0x12 -#define IER_LINK_UP 0x0400 -#define IER_LINK_DOWN 0x0800 - -/* PHY Interrupt Status Register */ -#define MII_ISR 0x13 -#define ISR_LINK_UP 0x0400 -#define ISR_LINK_DOWN 0x0800 - -/* Cable-Detect-Test Control Register */ -#define MII_CDTC 0x16 -#define CDTC_EN_OFF 0 /* sc */ -#define CDTC_EN_BITS 1 -#define CDTC_PAIR_OFF 8 -#define CDTC_PAIR_BIT 2 - -/* Cable-Detect-Test Status Register */ -#define MII_CDTS 0x1C -#define CDTS_STATUS_OFF 8 -#define CDTS_STATUS_BITS 2 -#define CDTS_STATUS_NORMAL 0 -#define CDTS_STATUS_SHORT 1 -#define CDTS_STATUS_OPEN 2 -#define CDTS_STATUS_INVALID 3 - -#define MII_DBG_ADDR 0x1D -#define MII_DBG_DATA 0x1E - -/***************************** debug port *************************************/ - -#define MIIDBG_ANACTRL 0x00 -#define ANACTRL_CLK125M_DELAY_EN 0x8000 -#define ANACTRL_VCO_FAST 0x4000 -#define ANACTRL_VCO_SLOW 0x2000 -#define ANACTRL_AFE_MODE_EN 0x1000 -#define ANACTRL_LCKDET_PHY 0x800 -#define ANACTRL_LCKDET_EN 0x400 -#define ANACTRL_OEN_125M 0x200 -#define ANACTRL_HBIAS_EN 0x100 -#define ANACTRL_HB_EN 0x80 -#define ANACTRL_SEL_HSP 0x40 -#define ANACTRL_CLASSA_EN 0x20 -#define ANACTRL_MANUSWON_SWR_MASK 3U -#define ANACTRL_MANUSWON_SWR_SHIFT 2 -#define ANACTRL_MANUSWON_SWR_2V 0 -#define ANACTRL_MANUSWON_SWR_1P9V 1 -#define ANACTRL_MANUSWON_SWR_1P8V 2 -#define ANACTRL_MANUSWON_SWR_1P7V 3 -#define ANACTRL_MANUSWON_BW3_4M 0x2 -#define ANACTRL_RESTART_CAL 0x1 -#define ANACTRL_DEF 0x02EF - -#define MIIDBG_SYSMODCTRL 0x04 -#define SYSMODCTRL_IECHOADJ_PFMH_PHY 0x8000 -#define SYSMODCTRL_IECHOADJ_BIASGEN 0x4000 -#define SYSMODCTRL_IECHOADJ_PFML_PHY 0x2000 -#define SYSMODCTRL_IECHOADJ_PS_MASK 3U -#define SYSMODCTRL_IECHOADJ_PS_SHIFT 10 -#define SYSMODCTRL_IECHOADJ_PS_40 3 -#define SYSMODCTRL_IECHOADJ_PS_20 2 -#define SYSMODCTRL_IECHOADJ_PS_0 1 -#define SYSMODCTRL_IECHOADJ_10BT_100MV 0x40 /* 1:100mv, 0:200mv */ -#define SYSMODCTRL_IECHOADJ_HLFAP_MASK 3U -#define SYSMODCTRL_IECHOADJ_HLFAP_SHIFT 4 -#define SYSMODCTRL_IECHOADJ_VDFULBW 0x8 -#define SYSMODCTRL_IECHOADJ_VDBIASHLF 0x4 -#define SYSMODCTRL_IECHOADJ_VDAMPHLF 0x2 -#define SYSMODCTRL_IECHOADJ_VDLANSW 0x1 -#define SYSMODCTRL_IECHOADJ_DEF 0x88BB /* ???? */ - -/* for l1d & l2cb */ -#define SYSMODCTRL_IECHOADJ_CUR_ADD 0x8000 -#define SYSMODCTRL_IECHOADJ_CUR_MASK 7U -#define SYSMODCTRL_IECHOADJ_CUR_SHIFT 12 -#define SYSMODCTRL_IECHOADJ_VOL_MASK 0xFU -#define SYSMODCTRL_IECHOADJ_VOL_SHIFT 8 -#define SYSMODCTRL_IECHOADJ_VOL_17ALL 3 -#define SYSMODCTRL_IECHOADJ_VOL_100M15 1 -#define SYSMODCTRL_IECHOADJ_VOL_10M17 0 -#define SYSMODCTRL_IECHOADJ_BIAS1_MASK 0xFU -#define SYSMODCTRL_IECHOADJ_BIAS1_SHIFT 4 -#define SYSMODCTRL_IECHOADJ_BIAS2_MASK 0xFU -#define SYSMODCTRL_IECHOADJ_BIAS2_SHIFT 0 -#define L1D_SYSMODCTRL_IECHOADJ_DEF 0x4FBB - -#define MIIDBG_SRDSYSMOD 0x05 -#define SRDSYSMOD_LCKDET_EN 0x2000 -#define SRDSYSMOD_PLL_EN 0x800 -#define SRDSYSMOD_SEL_HSP 0x400 -#define SRDSYSMOD_HLFTXDR 0x200 -#define SRDSYSMOD_TXCLK_DELAY_EN 0x100 -#define SRDSYSMOD_TXELECIDLE 0x80 -#define SRDSYSMOD_DEEMP_EN 0x40 -#define SRDSYSMOD_MS_PAD 0x4 -#define SRDSYSMOD_CDR_ADC_VLTG 0x2 -#define SRDSYSMOD_CDR_DAC_1MA 0x1 -#define SRDSYSMOD_DEF 0x2C46 - -#define MIIDBG_CFGLPSPD 0x0A -#define CFGLPSPD_RSTCNT_MASK 3U -#define CFGLPSPD_RSTCNT_SHIFT 14 -#define CFGLPSPD_RSTCNT_CLK125SW 0x2000 - -#define MIIDBG_HIBNEG 0x0B -#define HIBNEG_PSHIB_EN 0x8000 -#define HIBNEG_WAKE_BOTH 0x4000 -#define HIBNEG_ONOFF_ANACHG_SUDEN 0x2000 -#define HIBNEG_HIB_PULSE 0x1000 -#define HIBNEG_GATE_25M_EN 0x800 -#define HIBNEG_RST_80U 0x400 -#define HIBNEG_RST_TIMER_MASK 3U -#define HIBNEG_RST_TIMER_SHIFT 8 -#define HIBNEG_GTX_CLK_DELAY_MASK 3U -#define HIBNEG_GTX_CLK_DELAY_SHIFT 5 -#define HIBNEG_BYPSS_BRKTIMER 0x10 -#define HIBNEG_DEF 0xBC40 - -#define MIIDBG_TST10BTCFG 0x12 -#define TST10BTCFG_INTV_TIMER_MASK 3U -#define TST10BTCFG_INTV_TIMER_SHIFT 14 -#define TST10BTCFG_TRIGER_TIMER_MASK 3U -#define TST10BTCFG_TRIGER_TIMER_SHIFT 12 -#define TST10BTCFG_DIV_MAN_MLT3_EN 0x800 -#define TST10BTCFG_OFF_DAC_IDLE 0x400 -#define TST10BTCFG_LPBK_DEEP 0x4 /* 1:deep,0:shallow */ -#define TST10BTCFG_DEF 0x4C04 - -#define MIIDBG_AZ_ANADECT 0x15 -#define AZ_ANADECT_10BTRX_TH 0x8000 -#define AZ_ANADECT_BOTH_01CHNL 0x4000 -#define AZ_ANADECT_INTV_MASK 0x3FU -#define AZ_ANADECT_INTV_SHIFT 8 -#define AZ_ANADECT_THRESH_MASK 0xFU -#define AZ_ANADECT_THRESH_SHIFT 4 -#define AZ_ANADECT_CHNL_MASK 0xFU -#define AZ_ANADECT_CHNL_SHIFT 0 -#define AZ_ANADECT_DEF 0x3220 -#define AZ_ANADECT_LONG 0xb210 - -#define MIIDBG_MSE16DB 0x18 /* l1d */ -#define L1D_MSE16DB_UP 0x05EA -#define L1D_MSE16DB_DOWN 0x02EA - -#define MIIDBG_LEGCYPS 0x29 -#define LEGCYPS_EN 0x8000 -#define LEGCYPS_DAC_AMP1000_MASK 7U -#define LEGCYPS_DAC_AMP1000_SHIFT 12 -#define LEGCYPS_DAC_AMP100_MASK 7U -#define LEGCYPS_DAC_AMP100_SHIFT 9 -#define LEGCYPS_DAC_AMP10_MASK 7U -#define LEGCYPS_DAC_AMP10_SHIFT 6 -#define LEGCYPS_UNPLUG_TIMER_MASK 7U -#define LEGCYPS_UNPLUG_TIMER_SHIFT 3 -#define LEGCYPS_UNPLUG_DECT_EN 0x4 -#define LEGCYPS_ECNC_PS_EN 0x1 -#define L1D_LEGCYPS_DEF 0x129D -#define L1C_LEGCYPS_DEF 0x36DD - -#define MIIDBG_TST100BTCFG 0x36 -#define TST100BTCFG_NORMAL_BW_EN 0x8000 -#define TST100BTCFG_BADLNK_BYPASS 0x4000 -#define TST100BTCFG_SHORTCABL_TH_MASK 0x3FU -#define TST100BTCFG_SHORTCABL_TH_SHIFT 8 -#define TST100BTCFG_LITCH_EN 0x80 -#define TST100BTCFG_VLT_SW 0x40 -#define TST100BTCFG_LONGCABL_TH_MASK 0x3FU -#define TST100BTCFG_LONGCABL_TH_SHIFT 0 -#define TST100BTCFG_DEF 0xE12C - -#define MIIDBG_VOLT_CTRL 0x3B /* only for l2cb 1 & 2 */ -#define VOLT_CTRL_CABLE1TH_MASK 0x1FFU -#define VOLT_CTRL_CABLE1TH_SHIFT 7 -#define VOLT_CTRL_AMPCTRL_MASK 3U -#define VOLT_CTRL_AMPCTRL_SHIFT 5 -#define VOLT_CTRL_SW_BYPASS 0x10 -#define VOLT_CTRL_SWLOWEST 0x8 -#define VOLT_CTRL_DACAMP10_MASK 7U -#define VOLT_CTRL_DACAMP10_SHIFT 0 - -#define MIIDBG_CABLE1TH_DET 0x3E -#define CABLE1TH_DET_EN 0x8000 - - -/******* dev 3 *********/ -#define MIIEXT_PCS 3 - -#define MIIEXT_CLDCTRL3 0x8003 -#define CLDCTRL3_BP_CABLE1TH_DET_GT 0x8000 -#define CLDCTRL3_AZ_DISAMP 0x1000 -#define L2CB_CLDCTRL3 0x4D19 -#define L1D_CLDCTRL3 0xDD19 - -#define MIIEXT_CLDCTRL6 0x8006 -#define CLDCTRL6_CAB_LEN_MASK 0x1FFU -#define CLDCTRL6_CAB_LEN_SHIFT 0 -#define CLDCTRL6_CAB_LEN_SHORT 0x50 - -/********* dev 7 **********/ -#define MIIEXT_ANEG 7 - -#define MIIEXT_LOCAL_EEEADV 0x3C -#define LOCAL_EEEADV_1000BT 0x4 -#define LOCAL_EEEADV_100BT 0x2 - -#define MIIEXT_REMOTE_EEEADV 0x3D -#define REMOTE_EEEADV_1000BT 0x4 -#define REMOTE_EEEADV_100BT 0x2 - -#define MIIEXT_EEE_ANEG 0x8000 -#define EEE_ANEG_1000M 0x4 -#define EEE_ANEG_100M 0x2 - -#endif /*_ATL1C_HW_H_*/ diff --git a/addons/atl1c/src/3.10.108/atl1c_main.c b/addons/atl1c/src/3.10.108/atl1c_main.c deleted file mode 100644 index 297c3e5e..00000000 --- a/addons/atl1c/src/3.10.108/atl1c_main.c +++ /dev/null @@ -1,2818 +0,0 @@ -/* - * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "atl1c.h" - -#define ATL1C_DRV_VERSION "1.0.1.1-NAPI" -char atl1c_driver_name[] = "atl1c"; -char atl1c_driver_version[] = ATL1C_DRV_VERSION; - -/* - * atl1c_pci_tbl - PCI Device ID Table - * - * Wildcard entries (PCI_ANY_ID) should come last - * Last entry must be all 0s - * - * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, - * Class, Class Mask, private data (not used) } - */ -static DEFINE_PCI_DEVICE_TABLE(atl1c_pci_tbl) = { - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1C)}, - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2C)}, - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B)}, - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B2)}, - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L1D)}, - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L1D_2_0)}, - /* required last entry */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, atl1c_pci_tbl); - -MODULE_AUTHOR("Jie Yang"); -MODULE_AUTHOR("Qualcomm Atheros Inc., "); -MODULE_DESCRIPTION("Qualcom Atheros 100/1000M Ethernet Network Driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(ATL1C_DRV_VERSION); - -static int atl1c_stop_mac(struct atl1c_hw *hw); -static void atl1c_disable_l0s_l1(struct atl1c_hw *hw); -static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed); -static void atl1c_start_mac(struct atl1c_adapter *adapter); -static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, - int *work_done, int work_to_do); -static int atl1c_up(struct atl1c_adapter *adapter); -static void atl1c_down(struct atl1c_adapter *adapter); -static int atl1c_reset_mac(struct atl1c_hw *hw); -static void atl1c_reset_dma_ring(struct atl1c_adapter *adapter); -static int atl1c_configure(struct atl1c_adapter *adapter); -static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter); - -static const u16 atl1c_pay_load_size[] = { - 128, 256, 512, 1024, 2048, 4096, -}; - - -static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | - NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP; -static void atl1c_pcie_patch(struct atl1c_hw *hw) -{ - u32 mst_data, data; - - /* pclk sel could switch to 25M */ - AT_READ_REG(hw, REG_MASTER_CTRL, &mst_data); - mst_data &= ~MASTER_CTRL_CLK_SEL_DIS; - AT_WRITE_REG(hw, REG_MASTER_CTRL, mst_data); - - /* WoL/PCIE related settings */ - if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) { - AT_READ_REG(hw, REG_PCIE_PHYMISC, &data); - data |= PCIE_PHYMISC_FORCE_RCV_DET; - AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data); - } else { /* new dev set bit5 of MASTER */ - if (!(mst_data & MASTER_CTRL_WAKEN_25M)) - AT_WRITE_REG(hw, REG_MASTER_CTRL, - mst_data | MASTER_CTRL_WAKEN_25M); - } - /* aspm/PCIE setting only for l2cb 1.0 */ - if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) { - AT_READ_REG(hw, REG_PCIE_PHYMISC2, &data); - data = FIELD_SETX(data, PCIE_PHYMISC2_CDR_BW, - L2CB1_PCIE_PHYMISC2_CDR_BW); - data = FIELD_SETX(data, PCIE_PHYMISC2_L0S_TH, - L2CB1_PCIE_PHYMISC2_L0S_TH); - AT_WRITE_REG(hw, REG_PCIE_PHYMISC2, data); - /* extend L1 sync timer */ - AT_READ_REG(hw, REG_LINK_CTRL, &data); - data |= LINK_CTRL_EXT_SYNC; - AT_WRITE_REG(hw, REG_LINK_CTRL, data); - } - /* l2cb 1.x & l1d 1.x */ - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d) { - AT_READ_REG(hw, REG_PM_CTRL, &data); - data |= PM_CTRL_L0S_BUFSRX_EN; - AT_WRITE_REG(hw, REG_PM_CTRL, data); - /* clear vendor msg */ - AT_READ_REG(hw, REG_DMA_DBG, &data); - AT_WRITE_REG(hw, REG_DMA_DBG, data & ~DMA_DBG_VENDOR_MSG); - } -} - -/* FIXME: no need any more ? */ -/* - * atl1c_init_pcie - init PCIE module - */ -static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) -{ - u32 data; - u32 pci_cmd; - struct pci_dev *pdev = hw->adapter->pdev; - int pos; - - AT_READ_REG(hw, PCI_COMMAND, &pci_cmd); - pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; - pci_cmd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | - PCI_COMMAND_IO); - AT_WRITE_REG(hw, PCI_COMMAND, pci_cmd); - - /* - * Clear any PowerSaveing Settings - */ - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - /* wol sts read-clear */ - AT_READ_REG(hw, REG_WOL_CTRL, &data); - AT_WRITE_REG(hw, REG_WOL_CTRL, 0); - - /* - * Mask some pcie error bits - */ - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); - pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data); - data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP); - pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data); - /* clear error status */ - pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, - PCI_EXP_DEVSTA_NFED | - PCI_EXP_DEVSTA_FED | - PCI_EXP_DEVSTA_CED | - PCI_EXP_DEVSTA_URD); - - AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &data); - data &= ~LTSSM_ID_EN_WRO; - AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, data); - - atl1c_pcie_patch(hw); - if (flag & ATL1C_PCIE_L0S_L1_DISABLE) - atl1c_disable_l0s_l1(hw); - - msleep(5); -} - -/** - * atl1c_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - */ -static inline void atl1c_irq_enable(struct atl1c_adapter *adapter) -{ - if (likely(atomic_dec_and_test(&adapter->irq_sem))) { - AT_WRITE_REG(&adapter->hw, REG_ISR, 0x7FFFFFFF); - AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask); - AT_WRITE_FLUSH(&adapter->hw); - } -} - -/** - * atl1c_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - */ -static inline void atl1c_irq_disable(struct atl1c_adapter *adapter) -{ - atomic_inc(&adapter->irq_sem); - AT_WRITE_REG(&adapter->hw, REG_IMR, 0); - AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_INT); - AT_WRITE_FLUSH(&adapter->hw); - synchronize_irq(adapter->pdev->irq); -} - -/** - * atl1c_irq_reset - reset interrupt confiure on the NIC - * @adapter: board private structure - */ -static inline void atl1c_irq_reset(struct atl1c_adapter *adapter) -{ - atomic_set(&adapter->irq_sem, 1); - atl1c_irq_enable(adapter); -} - -/* - * atl1c_wait_until_idle - wait up to AT_HW_MAX_IDLE_DELAY reads - * of the idle status register until the device is actually idle - */ -static u32 atl1c_wait_until_idle(struct atl1c_hw *hw, u32 modu_ctrl) -{ - int timeout; - u32 data; - - for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { - AT_READ_REG(hw, REG_IDLE_STATUS, &data); - if ((data & modu_ctrl) == 0) - return 0; - msleep(1); - } - return data; -} - -/** - * atl1c_phy_config - Timer Call-back - * @data: pointer to netdev cast into an unsigned long - */ -static void atl1c_phy_config(unsigned long data) -{ - struct atl1c_adapter *adapter = (struct atl1c_adapter *) data; - struct atl1c_hw *hw = &adapter->hw; - unsigned long flags; - - spin_lock_irqsave(&adapter->mdio_lock, flags); - atl1c_restart_autoneg(hw); - spin_unlock_irqrestore(&adapter->mdio_lock, flags); -} - -void atl1c_reinit_locked(struct atl1c_adapter *adapter) -{ - WARN_ON(in_interrupt()); - atl1c_down(adapter); - atl1c_up(adapter); - clear_bit(__AT_RESETTING, &adapter->flags); -} - -static void atl1c_check_link_status(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - int err; - unsigned long flags; - u16 speed, duplex, phy_data; - - spin_lock_irqsave(&adapter->mdio_lock, flags); - /* MII_BMSR must read twise */ - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - spin_unlock_irqrestore(&adapter->mdio_lock, flags); - - if ((phy_data & BMSR_LSTATUS) == 0) { - /* link down */ - netif_carrier_off(netdev); - hw->hibernate = true; - if (atl1c_reset_mac(hw) != 0) - if (netif_msg_hw(adapter)) - dev_warn(&pdev->dev, "reset mac failed\n"); - atl1c_set_aspm(hw, SPEED_0); - atl1c_post_phy_linkchg(hw, SPEED_0); - atl1c_reset_dma_ring(adapter); - atl1c_configure(adapter); - } else { - /* Link Up */ - hw->hibernate = false; - spin_lock_irqsave(&adapter->mdio_lock, flags); - err = atl1c_get_speed_and_duplex(hw, &speed, &duplex); - spin_unlock_irqrestore(&adapter->mdio_lock, flags); - if (unlikely(err)) - return; - /* link result is our setting */ - if (adapter->link_speed != speed || - adapter->link_duplex != duplex) { - adapter->link_speed = speed; - adapter->link_duplex = duplex; - atl1c_set_aspm(hw, speed); - atl1c_post_phy_linkchg(hw, speed); - atl1c_start_mac(adapter); - if (netif_msg_link(adapter)) - dev_info(&pdev->dev, - "%s: %s NIC Link is Up<%d Mbps %s>\n", - atl1c_driver_name, netdev->name, - adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? - "Full Duplex" : "Half Duplex"); - } - if (!netif_carrier_ok(netdev)) - netif_carrier_on(netdev); - } -} - -static void atl1c_link_chg_event(struct atl1c_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - u16 phy_data; - u16 link_up; - - spin_lock(&adapter->mdio_lock); - atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); - atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); - spin_unlock(&adapter->mdio_lock); - link_up = phy_data & BMSR_LSTATUS; - /* notify upper layer link down ASAP */ - if (!link_up) { - if (netif_carrier_ok(netdev)) { - /* old link state: Up */ - netif_carrier_off(netdev); - if (netif_msg_link(adapter)) - dev_info(&pdev->dev, - "%s: %s NIC Link is Down\n", - atl1c_driver_name, netdev->name); - adapter->link_speed = SPEED_0; - } - } - - set_bit(ATL1C_WORK_EVENT_LINK_CHANGE, &adapter->work_event); - schedule_work(&adapter->common_task); -} - -static void atl1c_common_task(struct work_struct *work) -{ - struct atl1c_adapter *adapter; - struct net_device *netdev; - - adapter = container_of(work, struct atl1c_adapter, common_task); - netdev = adapter->netdev; - - if (test_bit(__AT_DOWN, &adapter->flags)) - return; - - if (test_and_clear_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event)) { - netif_device_detach(netdev); - atl1c_down(adapter); - atl1c_up(adapter); - netif_device_attach(netdev); - } - - if (test_and_clear_bit(ATL1C_WORK_EVENT_LINK_CHANGE, - &adapter->work_event)) { - atl1c_irq_disable(adapter); - atl1c_check_link_status(adapter); - atl1c_irq_enable(adapter); - } -} - - -static void atl1c_del_timer(struct atl1c_adapter *adapter) -{ - del_timer_sync(&adapter->phy_config_timer); -} - - -/** - * atl1c_tx_timeout - Respond to a Tx Hang - * @netdev: network interface device structure - */ -static void atl1c_tx_timeout(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - /* Do the reset outside of interrupt context */ - set_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event); - schedule_work(&adapter->common_task); -} - -/** - * atl1c_set_multi - Multicast and Promiscuous mode set - * @netdev: network interface device structure - * - * The set_multi entry point is called whenever the multicast address - * list or the network interface flags are updated. This routine is - * responsible for configuring the hardware for proper multicast, - * promiscuous mode, and all-multi behavior. - */ -static void atl1c_set_multi(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - struct netdev_hw_addr *ha; - u32 mac_ctrl_data; - u32 hash_value; - - /* Check for Promiscuous and All Multicast modes */ - AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data); - - if (netdev->flags & IFF_PROMISC) { - mac_ctrl_data |= MAC_CTRL_PROMIS_EN; - } else if (netdev->flags & IFF_ALLMULTI) { - mac_ctrl_data |= MAC_CTRL_MC_ALL_EN; - mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN; - } else { - mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN); - } - - AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); - - /* clear the old settings from the multicast hash table */ - AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); - AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); - - /* comoute mc addresses' hash value ,and put it into hash table */ - netdev_for_each_mc_addr(ha, netdev) { - hash_value = atl1c_hash_mc_addr(hw, ha->addr); - atl1c_hash_set(hw, hash_value); - } -} - -static void __atl1c_vlan_mode(netdev_features_t features, u32 *mac_ctrl_data) -{ - if (features & NETIF_F_HW_VLAN_CTAG_RX) { - /* enable VLAN tag insert/strip */ - *mac_ctrl_data |= MAC_CTRL_RMV_VLAN; - } else { - /* disable VLAN tag insert/strip */ - *mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN; - } -} - -static void atl1c_vlan_mode(struct net_device *netdev, - netdev_features_t features) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct pci_dev *pdev = adapter->pdev; - u32 mac_ctrl_data = 0; - - if (netif_msg_pktdata(adapter)) - dev_dbg(&pdev->dev, "atl1c_vlan_mode\n"); - - atl1c_irq_disable(adapter); - AT_READ_REG(&adapter->hw, REG_MAC_CTRL, &mac_ctrl_data); - __atl1c_vlan_mode(features, &mac_ctrl_data); - AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data); - atl1c_irq_enable(adapter); -} - -static void atl1c_restore_vlan(struct atl1c_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - - if (netif_msg_pktdata(adapter)) - dev_dbg(&pdev->dev, "atl1c_restore_vlan\n"); - atl1c_vlan_mode(adapter->netdev, adapter->netdev->features); -} - -/** - * atl1c_set_mac - Change the Ethernet Address of the NIC - * @netdev: network interface device structure - * @p: pointer to an address structure - * - * Returns 0 on success, negative on failure - */ -static int atl1c_set_mac_addr(struct net_device *netdev, void *p) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - if (netif_running(netdev)) - return -EBUSY; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); - - atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr); - - return 0; -} - -static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter, - struct net_device *dev) -{ - unsigned int head_size; - int mtu = dev->mtu; - - adapter->rx_buffer_len = mtu > AT_RX_BUF_SIZE ? - roundup(mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN, 8) : AT_RX_BUF_SIZE; - - head_size = SKB_DATA_ALIGN(adapter->rx_buffer_len + NET_SKB_PAD) + - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - adapter->rx_frag_size = roundup_pow_of_two(head_size); -} - -static netdev_features_t atl1c_fix_features(struct net_device *netdev, - netdev_features_t 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_CTAG_RX) - features |= NETIF_F_HW_VLAN_CTAG_TX; - else - features &= ~NETIF_F_HW_VLAN_CTAG_TX; - - if (netdev->mtu > MAX_TSO_FRAME_SIZE) - features &= ~(NETIF_F_TSO | NETIF_F_TSO6); - - return features; -} - -static int atl1c_set_features(struct net_device *netdev, - netdev_features_t features) -{ - netdev_features_t changed = netdev->features ^ features; - - if (changed & NETIF_F_HW_VLAN_CTAG_RX) - atl1c_vlan_mode(netdev, features); - - return 0; -} - -/** - * atl1c_change_mtu - Change the Maximum Transfer Unit - * @netdev: network interface device structure - * @new_mtu: new value for maximum frame size - * - * Returns 0 on success, negative on failure - */ -static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - int old_mtu = netdev->mtu; - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; - - /* Fast Ethernet controller doesn't support jumbo packet */ - if (((hw->nic_type == athr_l2c || - hw->nic_type == athr_l2c_b || - hw->nic_type == athr_l2c_b2) && new_mtu > ETH_DATA_LEN) || - max_frame < ETH_ZLEN + ETH_FCS_LEN || - max_frame > MAX_JUMBO_FRAME_SIZE) { - if (netif_msg_link(adapter)) - dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); - return -EINVAL; - } - /* set MTU */ - if (old_mtu != new_mtu && netif_running(netdev)) { - while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) - msleep(1); - netdev->mtu = new_mtu; - adapter->hw.max_frame_size = new_mtu; - atl1c_set_rxbufsize(adapter, netdev); - atl1c_down(adapter); - netdev_update_features(netdev); - atl1c_up(adapter); - clear_bit(__AT_RESETTING, &adapter->flags); - } - return 0; -} - -/* - * caller should hold mdio_lock - */ -static int atl1c_mdio_read(struct net_device *netdev, int phy_id, int reg_num) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - u16 result; - - atl1c_read_phy_reg(&adapter->hw, reg_num, &result); - return result; -} - -static void atl1c_mdio_write(struct net_device *netdev, int phy_id, - int reg_num, int val) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - atl1c_write_phy_reg(&adapter->hw, reg_num, val); -} - -static int atl1c_mii_ioctl(struct net_device *netdev, - struct ifreq *ifr, int cmd) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct pci_dev *pdev = adapter->pdev; - struct mii_ioctl_data *data = if_mii(ifr); - unsigned long flags; - int retval = 0; - - if (!netif_running(netdev)) - return -EINVAL; - - spin_lock_irqsave(&adapter->mdio_lock, flags); - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 0; - break; - - case SIOCGMIIREG: - if (atl1c_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, - &data->val_out)) { - retval = -EIO; - goto out; - } - break; - - case SIOCSMIIREG: - if (data->reg_num & ~(0x1F)) { - retval = -EFAULT; - goto out; - } - - dev_dbg(&pdev->dev, " write %x %x", - data->reg_num, data->val_in); - if (atl1c_write_phy_reg(&adapter->hw, - data->reg_num, data->val_in)) { - retval = -EIO; - goto out; - } - break; - - default: - retval = -EOPNOTSUPP; - break; - } -out: - spin_unlock_irqrestore(&adapter->mdio_lock, flags); - return retval; -} - -static int atl1c_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return atl1c_mii_ioctl(netdev, ifr, cmd); - default: - return -EOPNOTSUPP; - } -} - -/** - * atl1c_alloc_queues - Allocate memory for all rings - * @adapter: board private structure to initialize - * - */ -static int atl1c_alloc_queues(struct atl1c_adapter *adapter) -{ - return 0; -} - -static void atl1c_set_mac_type(struct atl1c_hw *hw) -{ - switch (hw->device_id) { - case PCI_DEVICE_ID_ATTANSIC_L2C: - hw->nic_type = athr_l2c; - break; - case PCI_DEVICE_ID_ATTANSIC_L1C: - hw->nic_type = athr_l1c; - break; - case PCI_DEVICE_ID_ATHEROS_L2C_B: - hw->nic_type = athr_l2c_b; - break; - case PCI_DEVICE_ID_ATHEROS_L2C_B2: - hw->nic_type = athr_l2c_b2; - break; - case PCI_DEVICE_ID_ATHEROS_L1D: - hw->nic_type = athr_l1d; - break; - case PCI_DEVICE_ID_ATHEROS_L1D_2_0: - hw->nic_type = athr_l1d_2; - break; - default: - break; - } -} - -static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) -{ - u32 link_ctrl_data; - - atl1c_set_mac_type(hw); - AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data); - - hw->ctrl_flags = ATL1C_INTR_MODRT_ENABLE | - ATL1C_TXQ_MODE_ENHANCE; - hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT | - ATL1C_ASPM_L1_SUPPORT; - hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON; - - if (hw->nic_type == athr_l1c || - hw->nic_type == athr_l1d || - hw->nic_type == athr_l1d_2) - hw->link_cap_flags |= ATL1C_LINK_CAP_1000M; - return 0; -} - -struct atl1c_platform_patch { - u16 pci_did; - u8 pci_revid; - u16 subsystem_vid; - u16 subsystem_did; - u32 patch_flag; -#define ATL1C_LINK_PATCH 0x1 -}; -static const struct atl1c_platform_patch plats[] = { -{0x2060, 0xC1, 0x1019, 0x8152, 0x1}, -{0x2060, 0xC1, 0x1019, 0x2060, 0x1}, -{0x2060, 0xC1, 0x1019, 0xE000, 0x1}, -{0x2062, 0xC0, 0x1019, 0x8152, 0x1}, -{0x2062, 0xC0, 0x1019, 0x2062, 0x1}, -{0x2062, 0xC0, 0x1458, 0xE000, 0x1}, -{0x2062, 0xC1, 0x1019, 0x8152, 0x1}, -{0x2062, 0xC1, 0x1019, 0x2062, 0x1}, -{0x2062, 0xC1, 0x1458, 0xE000, 0x1}, -{0x2062, 0xC1, 0x1565, 0x2802, 0x1}, -{0x2062, 0xC1, 0x1565, 0x2801, 0x1}, -{0x1073, 0xC0, 0x1019, 0x8151, 0x1}, -{0x1073, 0xC0, 0x1019, 0x1073, 0x1}, -{0x1073, 0xC0, 0x1458, 0xE000, 0x1}, -{0x1083, 0xC0, 0x1458, 0xE000, 0x1}, -{0x1083, 0xC0, 0x1019, 0x8151, 0x1}, -{0x1083, 0xC0, 0x1019, 0x1083, 0x1}, -{0x1083, 0xC0, 0x1462, 0x7680, 0x1}, -{0x1083, 0xC0, 0x1565, 0x2803, 0x1}, -{0}, -}; - -static void atl1c_patch_assign(struct atl1c_hw *hw) -{ - struct pci_dev *pdev = hw->adapter->pdev; - u32 misc_ctrl; - int i = 0; - - hw->msi_lnkpatch = false; - - while (plats[i].pci_did != 0) { - if (plats[i].pci_did == hw->device_id && - plats[i].pci_revid == hw->revision_id && - plats[i].subsystem_vid == hw->subsystem_vendor_id && - plats[i].subsystem_did == hw->subsystem_id) { - if (plats[i].patch_flag & ATL1C_LINK_PATCH) - hw->msi_lnkpatch = true; - } - i++; - } - - if (hw->device_id == PCI_DEVICE_ID_ATHEROS_L2C_B2 && - hw->revision_id == L2CB_V21) { - /* config acess mode */ - pci_write_config_dword(pdev, REG_PCIE_IND_ACC_ADDR, - REG_PCIE_DEV_MISC_CTRL); - pci_read_config_dword(pdev, REG_PCIE_IND_ACC_DATA, &misc_ctrl); - misc_ctrl &= ~0x100; - pci_write_config_dword(pdev, REG_PCIE_IND_ACC_ADDR, - REG_PCIE_DEV_MISC_CTRL); - pci_write_config_dword(pdev, REG_PCIE_IND_ACC_DATA, misc_ctrl); - } -} -/** - * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter) - * @adapter: board private structure to initialize - * - * atl1c_sw_init initializes the Adapter private data structure. - * Fields are initialized based on PCI device information and - * OS network device settings (MTU size). - */ -static int atl1c_sw_init(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - struct pci_dev *pdev = adapter->pdev; - u32 revision; - - - adapter->wol = 0; - device_set_wakeup_enable(&pdev->dev, false); - adapter->link_speed = SPEED_0; - adapter->link_duplex = FULL_DUPLEX; - adapter->tpd_ring[0].count = 1024; - adapter->rfd_ring.count = 512; - - hw->vendor_id = pdev->vendor; - hw->device_id = pdev->device; - hw->subsystem_vendor_id = pdev->subsystem_vendor; - hw->subsystem_id = pdev->subsystem_device; - pci_read_config_dword(pdev, PCI_CLASS_REVISION, &revision); - hw->revision_id = revision & 0xFF; - /* before link up, we assume hibernate is true */ - hw->hibernate = true; - hw->media_type = MEDIA_TYPE_AUTO_SENSOR; - if (atl1c_setup_mac_funcs(hw) != 0) { - dev_err(&pdev->dev, "set mac function pointers failed\n"); - return -1; - } - atl1c_patch_assign(hw); - - hw->intr_mask = IMR_NORMAL_MASK; - hw->phy_configured = false; - hw->preamble_len = 7; - hw->max_frame_size = adapter->netdev->mtu; - hw->autoneg_advertised = ADVERTISED_Autoneg; - hw->indirect_tab = 0xE4E4E4E4; - hw->base_cpu = 0; - - hw->ict = 50000; /* 100ms */ - hw->smb_timer = 200000; /* 400ms */ - hw->rx_imt = 200; - hw->tx_imt = 1000; - - hw->tpd_burst = 5; - hw->rfd_burst = 8; - hw->dma_order = atl1c_dma_ord_out; - hw->dmar_block = atl1c_dma_req_1024; - - if (atl1c_alloc_queues(adapter)) { - dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); - return -ENOMEM; - } - /* TODO */ - atl1c_set_rxbufsize(adapter, adapter->netdev); - atomic_set(&adapter->irq_sem, 1); - spin_lock_init(&adapter->mdio_lock); - spin_lock_init(&adapter->tx_lock); - set_bit(__AT_DOWN, &adapter->flags); - - return 0; -} - -static inline void atl1c_clean_buffer(struct pci_dev *pdev, - struct atl1c_buffer *buffer_info, int in_irq) -{ - u16 pci_driection; - if (buffer_info->flags & ATL1C_BUFFER_FREE) - return; - if (buffer_info->dma) { - if (buffer_info->flags & ATL1C_PCIMAP_FROMDEVICE) - pci_driection = PCI_DMA_FROMDEVICE; - else - pci_driection = PCI_DMA_TODEVICE; - - if (buffer_info->flags & ATL1C_PCIMAP_SINGLE) - pci_unmap_single(pdev, buffer_info->dma, - buffer_info->length, pci_driection); - else if (buffer_info->flags & ATL1C_PCIMAP_PAGE) - pci_unmap_page(pdev, buffer_info->dma, - buffer_info->length, pci_driection); - } - if (buffer_info->skb) { - if (in_irq) - dev_kfree_skb_irq(buffer_info->skb); - else - dev_kfree_skb(buffer_info->skb); - } - buffer_info->dma = 0; - buffer_info->skb = NULL; - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); -} -/** - * atl1c_clean_tx_ring - Free Tx-skb - * @adapter: board private structure - */ -static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter, - enum atl1c_trans_queue type) -{ - struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; - struct atl1c_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - u16 index, ring_count; - - ring_count = tpd_ring->count; - for (index = 0; index < ring_count; index++) { - buffer_info = &tpd_ring->buffer_info[index]; - atl1c_clean_buffer(pdev, buffer_info, 0); - } - - /* Zero out Tx-buffers */ - memset(tpd_ring->desc, 0, sizeof(struct atl1c_tpd_desc) * - ring_count); - atomic_set(&tpd_ring->next_to_clean, 0); - tpd_ring->next_to_use = 0; -} - -/** - * atl1c_clean_rx_ring - Free rx-reservation skbs - * @adapter: board private structure - */ -static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter) -{ - struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1c_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - int j; - - for (j = 0; j < rfd_ring->count; j++) { - buffer_info = &rfd_ring->buffer_info[j]; - atl1c_clean_buffer(pdev, buffer_info, 0); - } - /* zero out the descriptor ring */ - memset(rfd_ring->desc, 0, rfd_ring->size); - rfd_ring->next_to_clean = 0; - rfd_ring->next_to_use = 0; - rrd_ring->next_to_use = 0; - rrd_ring->next_to_clean = 0; -} - -/* - * Read / Write Ptr Initialize: - */ -static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) -{ - struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; - struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1c_buffer *buffer_info; - int i, j; - - for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) { - tpd_ring[i].next_to_use = 0; - atomic_set(&tpd_ring[i].next_to_clean, 0); - buffer_info = tpd_ring[i].buffer_info; - for (j = 0; j < tpd_ring->count; j++) - ATL1C_SET_BUFFER_STATE(&buffer_info[i], - ATL1C_BUFFER_FREE); - } - rfd_ring->next_to_use = 0; - rfd_ring->next_to_clean = 0; - rrd_ring->next_to_use = 0; - rrd_ring->next_to_clean = 0; - for (j = 0; j < rfd_ring->count; j++) { - buffer_info = &rfd_ring->buffer_info[j]; - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); - } -} - -/** - * atl1c_free_ring_resources - Free Tx / RX descriptor Resources - * @adapter: board private structure - * - * Free all transmit software resources - */ -static void atl1c_free_ring_resources(struct atl1c_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - - pci_free_consistent(pdev, adapter->ring_header.size, - adapter->ring_header.desc, - adapter->ring_header.dma); - adapter->ring_header.desc = NULL; - - /* Note: just free tdp_ring.buffer_info, - * it contain rfd_ring.buffer_info, do not double free */ - if (adapter->tpd_ring[0].buffer_info) { - kfree(adapter->tpd_ring[0].buffer_info); - adapter->tpd_ring[0].buffer_info = NULL; - } - if (adapter->rx_page) { - put_page(adapter->rx_page); - adapter->rx_page = NULL; - } -} - -/** - * atl1c_setup_mem_resources - allocate Tx / RX descriptor resources - * @adapter: board private structure - * - * Return 0 on success, negative on failure - */ -static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; - struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1c_ring_header *ring_header = &adapter->ring_header; - int size; - int i; - int count = 0; - int rx_desc_count = 0; - u32 offset = 0; - - rrd_ring->count = rfd_ring->count; - for (i = 1; i < AT_MAX_TRANSMIT_QUEUE; i++) - tpd_ring[i].count = tpd_ring[0].count; - - /* 2 tpd queue, one high priority queue, - * another normal priority queue */ - size = sizeof(struct atl1c_buffer) * (tpd_ring->count * 2 + - rfd_ring->count); - tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL); - if (unlikely(!tpd_ring->buffer_info)) - goto err_nomem; - - for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) { - tpd_ring[i].buffer_info = - (tpd_ring->buffer_info + count); - count += tpd_ring[i].count; - } - - rfd_ring->buffer_info = - (tpd_ring->buffer_info + count); - count += rfd_ring->count; - rx_desc_count += rfd_ring->count; - - /* - * real ring DMA buffer - * each ring/block may need up to 8 bytes for alignment, hence the - * additional bytes tacked onto the end. - */ - ring_header->size = size = - sizeof(struct atl1c_tpd_desc) * tpd_ring->count * 2 + - sizeof(struct atl1c_rx_free_desc) * rx_desc_count + - sizeof(struct atl1c_recv_ret_status) * rx_desc_count + - 8 * 4; - - ring_header->desc = dma_zalloc_coherent(&pdev->dev, ring_header->size, - &ring_header->dma, GFP_KERNEL); - if (unlikely(!ring_header->desc)) { - dev_err(&pdev->dev, "could not get memory for DMA buffer\n"); - goto err_nomem; - } - /* init TPD ring */ - - tpd_ring[0].dma = roundup(ring_header->dma, 8); - offset = tpd_ring[0].dma - ring_header->dma; - for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) { - tpd_ring[i].dma = ring_header->dma + offset; - tpd_ring[i].desc = (u8 *) ring_header->desc + offset; - tpd_ring[i].size = - sizeof(struct atl1c_tpd_desc) * tpd_ring[i].count; - offset += roundup(tpd_ring[i].size, 8); - } - /* init RFD ring */ - rfd_ring->dma = ring_header->dma + offset; - rfd_ring->desc = (u8 *) ring_header->desc + offset; - rfd_ring->size = sizeof(struct atl1c_rx_free_desc) * rfd_ring->count; - offset += roundup(rfd_ring->size, 8); - - /* init RRD ring */ - rrd_ring->dma = ring_header->dma + offset; - rrd_ring->desc = (u8 *) ring_header->desc + offset; - rrd_ring->size = sizeof(struct atl1c_recv_ret_status) * - rrd_ring->count; - offset += roundup(rrd_ring->size, 8); - - return 0; - -err_nomem: - kfree(tpd_ring->buffer_info); - return -ENOMEM; -} - -static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *) - adapter->tpd_ring; - - /* TPD */ - AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI, - (u32)((tpd_ring[atl1c_trans_normal].dma & - AT_DMA_HI_ADDR_MASK) >> 32)); - /* just enable normal priority TX queue */ - AT_WRITE_REG(hw, REG_TPD_PRI0_ADDR_LO, - (u32)(tpd_ring[atl1c_trans_normal].dma & - AT_DMA_LO_ADDR_MASK)); - AT_WRITE_REG(hw, REG_TPD_PRI1_ADDR_LO, - (u32)(tpd_ring[atl1c_trans_high].dma & - AT_DMA_LO_ADDR_MASK)); - AT_WRITE_REG(hw, REG_TPD_RING_SIZE, - (u32)(tpd_ring[0].count & TPD_RING_SIZE_MASK)); - - - /* RFD */ - AT_WRITE_REG(hw, REG_RX_BASE_ADDR_HI, - (u32)((rfd_ring->dma & AT_DMA_HI_ADDR_MASK) >> 32)); - AT_WRITE_REG(hw, REG_RFD0_HEAD_ADDR_LO, - (u32)(rfd_ring->dma & AT_DMA_LO_ADDR_MASK)); - - AT_WRITE_REG(hw, REG_RFD_RING_SIZE, - rfd_ring->count & RFD_RING_SIZE_MASK); - AT_WRITE_REG(hw, REG_RX_BUF_SIZE, - adapter->rx_buffer_len & RX_BUF_SIZE_MASK); - - /* RRD */ - AT_WRITE_REG(hw, REG_RRD0_HEAD_ADDR_LO, - (u32)(rrd_ring->dma & AT_DMA_LO_ADDR_MASK)); - AT_WRITE_REG(hw, REG_RRD_RING_SIZE, - (rrd_ring->count & RRD_RING_SIZE_MASK)); - - if (hw->nic_type == athr_l2c_b) { - AT_WRITE_REG(hw, REG_SRAM_RXF_LEN, 0x02a0L); - AT_WRITE_REG(hw, REG_SRAM_TXF_LEN, 0x0100L); - AT_WRITE_REG(hw, REG_SRAM_RXF_ADDR, 0x029f0000L); - AT_WRITE_REG(hw, REG_SRAM_RFD0_INFO, 0x02bf02a0L); - AT_WRITE_REG(hw, REG_SRAM_TXF_ADDR, 0x03bf02c0L); - AT_WRITE_REG(hw, REG_SRAM_TRD_ADDR, 0x03df03c0L); - AT_WRITE_REG(hw, REG_TXF_WATER_MARK, 0); /* TX watermark, to enter l1 state.*/ - AT_WRITE_REG(hw, REG_RXD_DMA_CTRL, 0); /* RXD threshold.*/ - } - /* Load all of base address above */ - AT_WRITE_REG(hw, REG_LOAD_PTR, 1); -} - -static void atl1c_configure_tx(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - int max_pay_load; - u16 tx_offload_thresh; - u32 txq_ctrl_data; - - tx_offload_thresh = MAX_TSO_FRAME_SIZE; - AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH, - (tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK); - max_pay_load = pcie_get_readrq(adapter->pdev) >> 8; - hw->dmar_block = min_t(u32, max_pay_load, hw->dmar_block); - /* - * if BIOS had changed the dam-read-max-length to an invalid value, - * restore it to default value - */ - if (hw->dmar_block < DEVICE_CTRL_MAXRRS_MIN) { - pcie_set_readrq(adapter->pdev, 128 << DEVICE_CTRL_MAXRRS_MIN); - hw->dmar_block = DEVICE_CTRL_MAXRRS_MIN; - } - txq_ctrl_data = - hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 ? - L2CB_TXQ_CFGV : L1C_TXQ_CFGV; - - AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data); -} - -static void atl1c_configure_rx(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - u32 rxq_ctrl_data; - - rxq_ctrl_data = (hw->rfd_burst & RXQ_RFD_BURST_NUM_MASK) << - RXQ_RFD_BURST_NUM_SHIFT; - - if (hw->ctrl_flags & ATL1C_RX_IPV6_CHKSUM) - rxq_ctrl_data |= IPV6_CHKSUM_CTRL_EN; - - /* aspm for gigabit */ - if (hw->nic_type != athr_l1d_2 && (hw->device_id & 1) != 0) - rxq_ctrl_data = FIELD_SETX(rxq_ctrl_data, ASPM_THRUPUT_LIMIT, - ASPM_THRUPUT_LIMIT_100M); - - AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data); -} - -static void atl1c_configure_dma(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - u32 dma_ctrl_data; - - dma_ctrl_data = FIELDX(DMA_CTRL_RORDER_MODE, DMA_CTRL_RORDER_MODE_OUT) | - DMA_CTRL_RREQ_PRI_DATA | - FIELDX(DMA_CTRL_RREQ_BLEN, hw->dmar_block) | - FIELDX(DMA_CTRL_WDLY_CNT, DMA_CTRL_WDLY_CNT_DEF) | - FIELDX(DMA_CTRL_RDLY_CNT, DMA_CTRL_RDLY_CNT_DEF); - - AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data); -} - -/* - * Stop the mac, transmit and receive units - * hw - Struct containing variables accessed by shared code - * return : 0 or idle status (if error) - */ -static int atl1c_stop_mac(struct atl1c_hw *hw) -{ - u32 data; - - AT_READ_REG(hw, REG_RXQ_CTRL, &data); - data &= ~RXQ_CTRL_EN; - AT_WRITE_REG(hw, REG_RXQ_CTRL, data); - - AT_READ_REG(hw, REG_TXQ_CTRL, &data); - data &= ~TXQ_CTRL_EN; - AT_WRITE_REG(hw, REG_TXQ_CTRL, data); - - atl1c_wait_until_idle(hw, IDLE_STATUS_RXQ_BUSY | IDLE_STATUS_TXQ_BUSY); - - AT_READ_REG(hw, REG_MAC_CTRL, &data); - data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN); - AT_WRITE_REG(hw, REG_MAC_CTRL, data); - - return (int)atl1c_wait_until_idle(hw, - IDLE_STATUS_TXMAC_BUSY | IDLE_STATUS_RXMAC_BUSY); -} - -static void atl1c_start_mac(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - u32 mac, txq, rxq; - - hw->mac_duplex = adapter->link_duplex == FULL_DUPLEX ? true : false; - hw->mac_speed = adapter->link_speed == SPEED_1000 ? - atl1c_mac_speed_1000 : atl1c_mac_speed_10_100; - - AT_READ_REG(hw, REG_TXQ_CTRL, &txq); - AT_READ_REG(hw, REG_RXQ_CTRL, &rxq); - AT_READ_REG(hw, REG_MAC_CTRL, &mac); - - txq |= TXQ_CTRL_EN; - rxq |= RXQ_CTRL_EN; - mac |= MAC_CTRL_TX_EN | MAC_CTRL_TX_FLOW | - MAC_CTRL_RX_EN | MAC_CTRL_RX_FLOW | - MAC_CTRL_ADD_CRC | MAC_CTRL_PAD | - MAC_CTRL_BC_EN | MAC_CTRL_SINGLE_PAUSE_EN | - MAC_CTRL_HASH_ALG_CRC32; - if (hw->mac_duplex) - mac |= MAC_CTRL_DUPLX; - else - mac &= ~MAC_CTRL_DUPLX; - mac = FIELD_SETX(mac, MAC_CTRL_SPEED, hw->mac_speed); - mac = FIELD_SETX(mac, MAC_CTRL_PRMLEN, hw->preamble_len); - - AT_WRITE_REG(hw, REG_TXQ_CTRL, txq); - AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq); - AT_WRITE_REG(hw, REG_MAC_CTRL, mac); -} - -/* - * Reset the transmit and receive units; mask and clear all interrupts. - * hw - Struct containing variables accessed by shared code - * return : 0 or idle status (if error) - */ -static int atl1c_reset_mac(struct atl1c_hw *hw) -{ - struct atl1c_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; - u32 ctrl_data = 0; - - atl1c_stop_mac(hw); - /* - * Issue Soft Reset to the MAC. This will reset the chip's - * transmit, receive, DMA. It will not effect - * the current PCI configuration. The global reset bit is self- - * clearing, and should clear within a microsecond. - */ - AT_READ_REG(hw, REG_MASTER_CTRL, &ctrl_data); - ctrl_data |= MASTER_CTRL_OOB_DIS; - AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data | MASTER_CTRL_SOFT_RST); - - AT_WRITE_FLUSH(hw); - msleep(10); - /* Wait at least 10ms for All module to be Idle */ - - if (atl1c_wait_until_idle(hw, IDLE_STATUS_MASK)) { - dev_err(&pdev->dev, - "MAC state machine can't be idle since" - " disabled for 10ms second\n"); - return -1; - } - AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data); - - /* driver control speed/duplex */ - AT_READ_REG(hw, REG_MAC_CTRL, &ctrl_data); - AT_WRITE_REG(hw, REG_MAC_CTRL, ctrl_data | MAC_CTRL_SPEED_MODE_SW); - - /* clk switch setting */ - AT_READ_REG(hw, REG_SERDES, &ctrl_data); - switch (hw->nic_type) { - case athr_l2c_b: - ctrl_data &= ~(SERDES_PHY_CLK_SLOWDOWN | - SERDES_MAC_CLK_SLOWDOWN); - AT_WRITE_REG(hw, REG_SERDES, ctrl_data); - break; - case athr_l2c_b2: - case athr_l1d_2: - ctrl_data |= SERDES_PHY_CLK_SLOWDOWN | SERDES_MAC_CLK_SLOWDOWN; - AT_WRITE_REG(hw, REG_SERDES, ctrl_data); - break; - default: - break; - } - - return 0; -} - -static void atl1c_disable_l0s_l1(struct atl1c_hw *hw) -{ - u16 ctrl_flags = hw->ctrl_flags; - - hw->ctrl_flags &= ~(ATL1C_ASPM_L0S_SUPPORT | ATL1C_ASPM_L1_SUPPORT); - atl1c_set_aspm(hw, SPEED_0); - hw->ctrl_flags = ctrl_flags; -} - -/* - * Set ASPM state. - * Enable/disable L0s/L1 depend on link state. - */ -static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed) -{ - u32 pm_ctrl_data; - u32 link_l1_timer; - - AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); - pm_ctrl_data &= ~(PM_CTRL_ASPM_L1_EN | - PM_CTRL_ASPM_L0S_EN | - PM_CTRL_MAC_ASPM_CHK); - /* L1 timer */ - if (hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { - pm_ctrl_data &= ~PMCTRL_TXL1_AFTER_L0S; - link_l1_timer = - link_speed == SPEED_1000 || link_speed == SPEED_100 ? - L1D_PMCTRL_L1_ENTRY_TM_16US : 1; - pm_ctrl_data = FIELD_SETX(pm_ctrl_data, - L1D_PMCTRL_L1_ENTRY_TM, link_l1_timer); - } else { - link_l1_timer = hw->nic_type == athr_l2c_b ? - L2CB1_PM_CTRL_L1_ENTRY_TM : L1C_PM_CTRL_L1_ENTRY_TM; - if (link_speed != SPEED_1000 && link_speed != SPEED_100) - link_l1_timer = 1; - pm_ctrl_data = FIELD_SETX(pm_ctrl_data, - PM_CTRL_L1_ENTRY_TIMER, link_l1_timer); - } - - /* L0S/L1 enable */ - if ((hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) && link_speed != SPEED_0) - pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN | PM_CTRL_MAC_ASPM_CHK; - if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) - pm_ctrl_data |= PM_CTRL_ASPM_L1_EN | PM_CTRL_MAC_ASPM_CHK; - - /* l2cb & l1d & l2cb2 & l1d2 */ - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d || - hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { - pm_ctrl_data = FIELD_SETX(pm_ctrl_data, - PM_CTRL_PM_REQ_TIMER, PM_CTRL_PM_REQ_TO_DEF); - pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER | - PM_CTRL_SERDES_PD_EX_L1 | - PM_CTRL_CLK_SWH_L1; - pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN | - PM_CTRL_SERDES_PLL_L1_EN | - PM_CTRL_SERDES_BUFS_RX_L1_EN | - PM_CTRL_SA_DLY_EN | - PM_CTRL_HOTRST); - /* disable l0s if link down or l2cb */ - if (link_speed == SPEED_0 || hw->nic_type == athr_l2c_b) - pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; - } else { /* l1c */ - pm_ctrl_data = - FIELD_SETX(pm_ctrl_data, PM_CTRL_L1_ENTRY_TIMER, 0); - if (link_speed != SPEED_0) { - pm_ctrl_data |= PM_CTRL_SERDES_L1_EN | - PM_CTRL_SERDES_PLL_L1_EN | - PM_CTRL_SERDES_BUFS_RX_L1_EN; - pm_ctrl_data &= ~(PM_CTRL_SERDES_PD_EX_L1 | - PM_CTRL_CLK_SWH_L1 | - PM_CTRL_ASPM_L0S_EN | - PM_CTRL_ASPM_L1_EN); - } else { /* link down */ - pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; - pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN | - PM_CTRL_SERDES_PLL_L1_EN | - PM_CTRL_SERDES_BUFS_RX_L1_EN | - PM_CTRL_ASPM_L0S_EN); - } - } - AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data); - - return; -} - -/** - * atl1c_configure - Configure Transmit&Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Tx /Rx unit of the MAC after a reset. - */ -static int atl1c_configure_mac(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - u32 master_ctrl_data = 0; - u32 intr_modrt_data; - u32 data; - - AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); - master_ctrl_data &= ~(MASTER_CTRL_TX_ITIMER_EN | - MASTER_CTRL_RX_ITIMER_EN | - MASTER_CTRL_INT_RDCLR); - /* clear interrupt status */ - AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF); - /* Clear any WOL status */ - AT_WRITE_REG(hw, REG_WOL_CTRL, 0); - /* set Interrupt Clear Timer - * HW will enable self to assert interrupt event to system after - * waiting x-time for software to notify it accept interrupt. - */ - - data = CLK_GATING_EN_ALL; - if (hw->ctrl_flags & ATL1C_CLK_GATING_EN) { - if (hw->nic_type == athr_l2c_b) - data &= ~CLK_GATING_RXMAC_EN; - } else - data = 0; - AT_WRITE_REG(hw, REG_CLK_GATING_CTRL, data); - - AT_WRITE_REG(hw, REG_INT_RETRIG_TIMER, - hw->ict & INT_RETRIG_TIMER_MASK); - - atl1c_configure_des_ring(adapter); - - if (hw->ctrl_flags & ATL1C_INTR_MODRT_ENABLE) { - intr_modrt_data = (hw->tx_imt & IRQ_MODRT_TIMER_MASK) << - IRQ_MODRT_TX_TIMER_SHIFT; - intr_modrt_data |= (hw->rx_imt & IRQ_MODRT_TIMER_MASK) << - IRQ_MODRT_RX_TIMER_SHIFT; - AT_WRITE_REG(hw, REG_IRQ_MODRT_TIMER_INIT, intr_modrt_data); - master_ctrl_data |= - MASTER_CTRL_TX_ITIMER_EN | MASTER_CTRL_RX_ITIMER_EN; - } - - if (hw->ctrl_flags & ATL1C_INTR_CLEAR_ON_READ) - master_ctrl_data |= MASTER_CTRL_INT_RDCLR; - - master_ctrl_data |= MASTER_CTRL_SA_TIMER_EN; - AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); - - AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, - hw->smb_timer & SMB_STAT_TIMER_MASK); - - /* set MTU */ - AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN + - VLAN_HLEN + ETH_FCS_LEN); - - atl1c_configure_tx(adapter); - atl1c_configure_rx(adapter); - atl1c_configure_dma(adapter); - - return 0; -} - -static int atl1c_configure(struct atl1c_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - int num; - - atl1c_init_ring_ptrs(adapter); - atl1c_set_multi(netdev); - atl1c_restore_vlan(adapter); - - num = atl1c_alloc_rx_buffer(adapter); - if (unlikely(num == 0)) - return -ENOMEM; - - if (atl1c_configure_mac(adapter)) - return -EIO; - - return 0; -} - -static void atl1c_update_hw_stats(struct atl1c_adapter *adapter) -{ - u16 hw_reg_addr = 0; - unsigned long *stats_item = NULL; - u32 data; - - /* update rx status */ - hw_reg_addr = REG_MAC_RX_STATUS_BIN; - stats_item = &adapter->hw_stats.rx_ok; - while (hw_reg_addr <= REG_MAC_RX_STATUS_END) { - AT_READ_REG(&adapter->hw, hw_reg_addr, &data); - *stats_item += data; - stats_item++; - hw_reg_addr += 4; - } -/* update tx status */ - hw_reg_addr = REG_MAC_TX_STATUS_BIN; - stats_item = &adapter->hw_stats.tx_ok; - while (hw_reg_addr <= REG_MAC_TX_STATUS_END) { - AT_READ_REG(&adapter->hw, hw_reg_addr, &data); - *stats_item += data; - stats_item++; - hw_reg_addr += 4; - } -} - -/** - * atl1c_get_stats - Get System Network Statistics - * @netdev: network interface device structure - * - * Returns the address of the device statistics structure. - * The statistics are actually updated from the timer callback. - */ -static struct net_device_stats *atl1c_get_stats(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw_stats *hw_stats = &adapter->hw_stats; - struct net_device_stats *net_stats = &netdev->stats; - - atl1c_update_hw_stats(adapter); - net_stats->rx_packets = hw_stats->rx_ok; - net_stats->tx_packets = hw_stats->tx_ok; - net_stats->rx_bytes = hw_stats->rx_byte_cnt; - net_stats->tx_bytes = hw_stats->tx_byte_cnt; - net_stats->multicast = hw_stats->rx_mcast; - net_stats->collisions = hw_stats->tx_1_col + - hw_stats->tx_2_col * 2 + - hw_stats->tx_late_col + hw_stats->tx_abort_col; - net_stats->rx_errors = hw_stats->rx_frag + hw_stats->rx_fcs_err + - hw_stats->rx_len_err + hw_stats->rx_sz_ov + - hw_stats->rx_rrd_ov + hw_stats->rx_align_err; - net_stats->rx_fifo_errors = hw_stats->rx_rxf_ov; - net_stats->rx_length_errors = hw_stats->rx_len_err; - net_stats->rx_crc_errors = hw_stats->rx_fcs_err; - net_stats->rx_frame_errors = hw_stats->rx_align_err; - net_stats->rx_over_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov; - - net_stats->rx_missed_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov; - - net_stats->tx_errors = hw_stats->tx_late_col + hw_stats->tx_abort_col + - hw_stats->tx_underrun + hw_stats->tx_trunc; - net_stats->tx_fifo_errors = hw_stats->tx_underrun; - net_stats->tx_aborted_errors = hw_stats->tx_abort_col; - net_stats->tx_window_errors = hw_stats->tx_late_col; - - return net_stats; -} - -static inline void atl1c_clear_phy_int(struct atl1c_adapter *adapter) -{ - u16 phy_data; - - spin_lock(&adapter->mdio_lock); - atl1c_read_phy_reg(&adapter->hw, MII_ISR, &phy_data); - spin_unlock(&adapter->mdio_lock); -} - -static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter, - enum atl1c_trans_queue type) -{ - struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; - struct atl1c_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean); - u16 hw_next_to_clean; - u16 reg; - - reg = type == atl1c_trans_high ? REG_TPD_PRI1_CIDX : REG_TPD_PRI0_CIDX; - - AT_READ_REGW(&adapter->hw, reg, &hw_next_to_clean); - - while (next_to_clean != hw_next_to_clean) { - buffer_info = &tpd_ring->buffer_info[next_to_clean]; - atl1c_clean_buffer(pdev, buffer_info, 1); - if (++next_to_clean == tpd_ring->count) - next_to_clean = 0; - atomic_set(&tpd_ring->next_to_clean, next_to_clean); - } - - if (netif_queue_stopped(adapter->netdev) && - netif_carrier_ok(adapter->netdev)) { - netif_wake_queue(adapter->netdev); - } - - return true; -} - -/** - * atl1c_intr - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - */ -static irqreturn_t atl1c_intr(int irq, void *data) -{ - struct net_device *netdev = data; - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct pci_dev *pdev = adapter->pdev; - struct atl1c_hw *hw = &adapter->hw; - int max_ints = AT_MAX_INT_WORK; - int handled = IRQ_NONE; - u32 status; - u32 reg_data; - - do { - AT_READ_REG(hw, REG_ISR, ®_data); - status = reg_data & hw->intr_mask; - - if (status == 0 || (status & ISR_DIS_INT) != 0) { - if (max_ints != AT_MAX_INT_WORK) - handled = IRQ_HANDLED; - break; - } - /* link event */ - if (status & ISR_GPHY) - atl1c_clear_phy_int(adapter); - /* Ack ISR */ - AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT); - if (status & ISR_RX_PKT) { - if (likely(napi_schedule_prep(&adapter->napi))) { - hw->intr_mask &= ~ISR_RX_PKT; - AT_WRITE_REG(hw, REG_IMR, hw->intr_mask); - __napi_schedule(&adapter->napi); - } - } - if (status & ISR_TX_PKT) - atl1c_clean_tx_irq(adapter, atl1c_trans_normal); - - handled = IRQ_HANDLED; - /* check if PCIE PHY Link down */ - if (status & ISR_ERROR) { - if (netif_msg_hw(adapter)) - dev_err(&pdev->dev, - "atl1c hardware error (status = 0x%x)\n", - status & ISR_ERROR); - /* reset MAC */ - set_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event); - schedule_work(&adapter->common_task); - return IRQ_HANDLED; - } - - if (status & ISR_OVER) - if (netif_msg_intr(adapter)) - dev_warn(&pdev->dev, - "TX/RX overflow (status = 0x%x)\n", - status & ISR_OVER); - - /* link event */ - if (status & (ISR_GPHY | ISR_MANUAL)) { - netdev->stats.tx_carrier_errors++; - atl1c_link_chg_event(adapter); - break; - } - - } while (--max_ints > 0); - /* re-enable Interrupt*/ - AT_WRITE_REG(&adapter->hw, REG_ISR, 0); - return handled; -} - -static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter, - struct sk_buff *skb, struct atl1c_recv_ret_status *prrs) -{ - /* - * The pid field in RRS in not correct sometimes, so we - * cannot figure out if the packet is fragmented or not, - * so we tell the KERNEL CHECKSUM_NONE - */ - skb_checksum_none_assert(skb); -} - -static struct sk_buff *atl1c_alloc_skb(struct atl1c_adapter *adapter) -{ - struct sk_buff *skb; - struct page *page; - - if (adapter->rx_frag_size > PAGE_SIZE) - return netdev_alloc_skb(adapter->netdev, - adapter->rx_buffer_len); - - page = adapter->rx_page; - if (!page) { - adapter->rx_page = page = alloc_page(GFP_ATOMIC); - if (unlikely(!page)) - return NULL; - adapter->rx_page_offset = 0; - } - - skb = build_skb(page_address(page) + adapter->rx_page_offset, - adapter->rx_frag_size); - if (likely(skb)) { - adapter->rx_page_offset += adapter->rx_frag_size; - if (adapter->rx_page_offset >= PAGE_SIZE) - adapter->rx_page = NULL; - else - get_page(page); - } - return skb; -} - -static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter) -{ - struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct pci_dev *pdev = adapter->pdev; - struct atl1c_buffer *buffer_info, *next_info; - struct sk_buff *skb; - void *vir_addr = NULL; - u16 num_alloc = 0; - u16 rfd_next_to_use, next_next; - struct atl1c_rx_free_desc *rfd_desc; - dma_addr_t mapping; - - next_next = rfd_next_to_use = rfd_ring->next_to_use; - if (++next_next == rfd_ring->count) - next_next = 0; - buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; - next_info = &rfd_ring->buffer_info[next_next]; - - while (next_info->flags & ATL1C_BUFFER_FREE) { - rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use); - - skb = atl1c_alloc_skb(adapter); - if (unlikely(!skb)) { - if (netif_msg_rx_err(adapter)) - dev_warn(&pdev->dev, "alloc rx buffer failed\n"); - break; - } - - /* - * Make buffer alignment 2 beyond a 16 byte boundary - * this will result in a 16 byte aligned IP header after - * the 14 byte MAC header is removed - */ - vir_addr = skb->data; - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - buffer_info->skb = skb; - buffer_info->length = adapter->rx_buffer_len; - mapping = pci_map_single(pdev, vir_addr, - buffer_info->length, - PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(pdev, mapping))) { - dev_kfree_skb(skb); - buffer_info->skb = NULL; - buffer_info->length = 0; - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); - netif_warn(adapter, rx_err, adapter->netdev, "RX pci_map_single failed"); - break; - } - buffer_info->dma = mapping; - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, - ATL1C_PCIMAP_FROMDEVICE); - rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - rfd_next_to_use = next_next; - if (++next_next == rfd_ring->count) - next_next = 0; - buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; - next_info = &rfd_ring->buffer_info[next_next]; - num_alloc++; - } - - if (num_alloc) { - /* TODO: update mailbox here */ - wmb(); - rfd_ring->next_to_use = rfd_next_to_use; - AT_WRITE_REG(&adapter->hw, REG_MB_RFD0_PROD_IDX, - rfd_ring->next_to_use & MB_RFDX_PROD_IDX_MASK); - } - - return num_alloc; -} - -static void atl1c_clean_rrd(struct atl1c_rrd_ring *rrd_ring, - struct atl1c_recv_ret_status *rrs, u16 num) -{ - u16 i; - /* the relationship between rrd and rfd is one map one */ - for (i = 0; i < num; i++, rrs = ATL1C_RRD_DESC(rrd_ring, - rrd_ring->next_to_clean)) { - rrs->word3 &= ~RRS_RXD_UPDATED; - if (++rrd_ring->next_to_clean == rrd_ring->count) - rrd_ring->next_to_clean = 0; - } -} - -static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring, - struct atl1c_recv_ret_status *rrs, u16 num) -{ - u16 i; - u16 rfd_index; - struct atl1c_buffer *buffer_info = rfd_ring->buffer_info; - - rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) & - RRS_RX_RFD_INDEX_MASK; - for (i = 0; i < num; i++) { - buffer_info[rfd_index].skb = NULL; - ATL1C_SET_BUFFER_STATE(&buffer_info[rfd_index], - ATL1C_BUFFER_FREE); - if (++rfd_index == rfd_ring->count) - rfd_index = 0; - } - rfd_ring->next_to_clean = rfd_index; -} - -static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, - int *work_done, int work_to_do) -{ - u16 rfd_num, rfd_index; - u16 count = 0; - u16 length; - struct pci_dev *pdev = adapter->pdev; - struct net_device *netdev = adapter->netdev; - struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct sk_buff *skb; - struct atl1c_recv_ret_status *rrs; - struct atl1c_buffer *buffer_info; - - while (1) { - if (*work_done >= work_to_do) - break; - rrs = ATL1C_RRD_DESC(rrd_ring, rrd_ring->next_to_clean); - if (likely(RRS_RXD_IS_VALID(rrs->word3))) { - rfd_num = (rrs->word0 >> RRS_RX_RFD_CNT_SHIFT) & - RRS_RX_RFD_CNT_MASK; - if (unlikely(rfd_num != 1)) - /* TODO support mul rfd*/ - if (netif_msg_rx_err(adapter)) - dev_warn(&pdev->dev, - "Multi rfd not support yet!\n"); - goto rrs_checked; - } else { - break; - } -rrs_checked: - atl1c_clean_rrd(rrd_ring, rrs, rfd_num); - if (rrs->word3 & (RRS_RX_ERR_SUM | RRS_802_3_LEN_ERR)) { - atl1c_clean_rfd(rfd_ring, rrs, rfd_num); - if (netif_msg_rx_err(adapter)) - dev_warn(&pdev->dev, - "wrong packet! rrs word3 is %x\n", - rrs->word3); - continue; - } - - length = le16_to_cpu((rrs->word3 >> RRS_PKT_SIZE_SHIFT) & - RRS_PKT_SIZE_MASK); - /* Good Receive */ - if (likely(rfd_num == 1)) { - rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) & - RRS_RX_RFD_INDEX_MASK; - buffer_info = &rfd_ring->buffer_info[rfd_index]; - pci_unmap_single(pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_FROMDEVICE); - skb = buffer_info->skb; - } else { - /* TODO */ - if (netif_msg_rx_err(adapter)) - dev_warn(&pdev->dev, - "Multi rfd not support yet!\n"); - break; - } - atl1c_clean_rfd(rfd_ring, rrs, rfd_num); - skb_put(skb, length - ETH_FCS_LEN); - skb->protocol = eth_type_trans(skb, netdev); - atl1c_rx_checksum(adapter, skb, rrs); - if (rrs->word3 & RRS_VLAN_INS) { - u16 vlan; - - AT_TAG_TO_VLAN(rrs->vlan_tag, vlan); - vlan = le16_to_cpu(vlan); - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan); - } - netif_receive_skb(skb); - - (*work_done)++; - count++; - } - if (count) - atl1c_alloc_rx_buffer(adapter); -} - -/** - * atl1c_clean - NAPI Rx polling callback - */ -static int atl1c_clean(struct napi_struct *napi, int budget) -{ - struct atl1c_adapter *adapter = - container_of(napi, struct atl1c_adapter, napi); - int work_done = 0; - - /* Keep link state information with original netdev */ - if (!netif_carrier_ok(adapter->netdev)) - goto quit_polling; - /* just enable one RXQ */ - atl1c_clean_rx_irq(adapter, &work_done, budget); - - if (work_done < budget) { -quit_polling: - napi_complete(napi); - adapter->hw.intr_mask |= ISR_RX_PKT; - AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask); - } - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER - -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void atl1c_netpoll(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - disable_irq(adapter->pdev->irq); - atl1c_intr(adapter->pdev->irq, netdev); - enable_irq(adapter->pdev->irq); -} -#endif - -static inline u16 atl1c_tpd_avail(struct atl1c_adapter *adapter, enum atl1c_trans_queue type) -{ - struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; - u16 next_to_use = 0; - u16 next_to_clean = 0; - - next_to_clean = atomic_read(&tpd_ring->next_to_clean); - next_to_use = tpd_ring->next_to_use; - - return (u16)(next_to_clean > next_to_use) ? - (next_to_clean - next_to_use - 1) : - (tpd_ring->count + next_to_clean - next_to_use - 1); -} - -/* - * get next usable tpd - * Note: should call atl1c_tdp_avail to make sure - * there is enough tpd to use - */ -static struct atl1c_tpd_desc *atl1c_get_tpd(struct atl1c_adapter *adapter, - enum atl1c_trans_queue type) -{ - struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; - struct atl1c_tpd_desc *tpd_desc; - u16 next_to_use = 0; - - next_to_use = tpd_ring->next_to_use; - if (++tpd_ring->next_to_use == tpd_ring->count) - tpd_ring->next_to_use = 0; - tpd_desc = ATL1C_TPD_DESC(tpd_ring, next_to_use); - memset(tpd_desc, 0, sizeof(struct atl1c_tpd_desc)); - return tpd_desc; -} - -static struct atl1c_buffer * -atl1c_get_tx_buffer(struct atl1c_adapter *adapter, struct atl1c_tpd_desc *tpd) -{ - struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; - - return &tpd_ring->buffer_info[tpd - - (struct atl1c_tpd_desc *)tpd_ring->desc]; -} - -/* Calculate the transmit packet descript needed*/ -static u16 atl1c_cal_tpd_req(const struct sk_buff *skb) -{ - u16 tpd_req; - u16 proto_hdr_len = 0; - - tpd_req = skb_shinfo(skb)->nr_frags + 1; - - if (skb_is_gso(skb)) { - proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - if (proto_hdr_len < skb_headlen(skb)) - tpd_req++; - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - tpd_req++; - } - return tpd_req; -} - -static int atl1c_tso_csum(struct atl1c_adapter *adapter, - struct sk_buff *skb, - struct atl1c_tpd_desc **tpd, - enum atl1c_trans_queue type) -{ - struct pci_dev *pdev = adapter->pdev; - u8 hdr_len; - u32 real_len; - unsigned short offload_type; - int err; - - if (skb_is_gso(skb)) { - if (skb_header_cloned(skb)) { - err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); - if (unlikely(err)) - return -1; - } - offload_type = skb_shinfo(skb)->gso_type; - - if (offload_type & SKB_GSO_TCPV4) { - real_len = (((unsigned char *)ip_hdr(skb) - skb->data) - + ntohs(ip_hdr(skb)->tot_len)); - - if (real_len < skb->len) - pskb_trim(skb, real_len); - - hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); - if (unlikely(skb->len == hdr_len)) { - /* only xsum need */ - if (netif_msg_tx_queued(adapter)) - dev_warn(&pdev->dev, - "IPV4 tso with zero data??\n"); - goto check_sum; - } else { - ip_hdr(skb)->check = 0; - tcp_hdr(skb)->check = ~csum_tcpudp_magic( - ip_hdr(skb)->saddr, - ip_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); - (*tpd)->word1 |= 1 << TPD_IPV4_PACKET_SHIFT; - } - } - - if (offload_type & SKB_GSO_TCPV6) { - struct atl1c_tpd_ext_desc *etpd = - *(struct atl1c_tpd_ext_desc **)(tpd); - - memset(etpd, 0, sizeof(struct atl1c_tpd_ext_desc)); - *tpd = atl1c_get_tpd(adapter, type); - ipv6_hdr(skb)->payload_len = 0; - /* check payload == 0 byte ? */ - hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); - if (unlikely(skb->len == hdr_len)) { - /* only xsum need */ - if (netif_msg_tx_queued(adapter)) - dev_warn(&pdev->dev, - "IPV6 tso with zero data??\n"); - goto check_sum; - } else - tcp_hdr(skb)->check = ~csum_ipv6_magic( - &ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); - etpd->word1 |= 1 << TPD_LSO_EN_SHIFT; - etpd->word1 |= 1 << TPD_LSO_VER_SHIFT; - etpd->pkt_len = cpu_to_le32(skb->len); - (*tpd)->word1 |= 1 << TPD_LSO_VER_SHIFT; - } - - (*tpd)->word1 |= 1 << TPD_LSO_EN_SHIFT; - (*tpd)->word1 |= (skb_transport_offset(skb) & TPD_TCPHDR_OFFSET_MASK) << - TPD_TCPHDR_OFFSET_SHIFT; - (*tpd)->word1 |= (skb_shinfo(skb)->gso_size & TPD_MSS_MASK) << - TPD_MSS_SHIFT; - return 0; - } - -check_sum: - if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { - u8 css, cso; - cso = skb_checksum_start_offset(skb); - - if (unlikely(cso & 0x1)) { - if (netif_msg_tx_err(adapter)) - dev_err(&adapter->pdev->dev, - "payload offset should not an event number\n"); - return -1; - } else { - css = cso + skb->csum_offset; - - (*tpd)->word1 |= ((cso >> 1) & TPD_PLOADOFFSET_MASK) << - TPD_PLOADOFFSET_SHIFT; - (*tpd)->word1 |= ((css >> 1) & TPD_CCSUM_OFFSET_MASK) << - TPD_CCSUM_OFFSET_SHIFT; - (*tpd)->word1 |= 1 << TPD_CCSUM_EN_SHIFT; - } - } - return 0; -} - -static void atl1c_tx_rollback(struct atl1c_adapter *adpt, - struct atl1c_tpd_desc *first_tpd, - enum atl1c_trans_queue type) -{ - struct atl1c_tpd_ring *tpd_ring = &adpt->tpd_ring[type]; - struct atl1c_buffer *buffer_info; - struct atl1c_tpd_desc *tpd; - u16 first_index, index; - - first_index = first_tpd - (struct atl1c_tpd_desc *)tpd_ring->desc; - index = first_index; - while (index != tpd_ring->next_to_use) { - tpd = ATL1C_TPD_DESC(tpd_ring, index); - buffer_info = &tpd_ring->buffer_info[index]; - atl1c_clean_buffer(adpt->pdev, buffer_info, 0); - memset(tpd, 0, sizeof(struct atl1c_tpd_desc)); - if (++index == tpd_ring->count) - index = 0; - } - tpd_ring->next_to_use = first_index; -} - -static int atl1c_tx_map(struct atl1c_adapter *adapter, - struct sk_buff *skb, struct atl1c_tpd_desc *tpd, - enum atl1c_trans_queue type) -{ - struct atl1c_tpd_desc *use_tpd = NULL; - struct atl1c_buffer *buffer_info = NULL; - u16 buf_len = skb_headlen(skb); - u16 map_len = 0; - u16 mapped_len = 0; - u16 hdr_len = 0; - u16 nr_frags; - u16 f; - int tso; - - nr_frags = skb_shinfo(skb)->nr_frags; - tso = (tpd->word1 >> TPD_LSO_EN_SHIFT) & TPD_LSO_EN_MASK; - if (tso) { - /* TSO */ - map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - use_tpd = tpd; - - buffer_info = atl1c_get_tx_buffer(adapter, use_tpd); - buffer_info->length = map_len; - buffer_info->dma = pci_map_single(adapter->pdev, - skb->data, hdr_len, PCI_DMA_TODEVICE); - if (unlikely(pci_dma_mapping_error(adapter->pdev, - buffer_info->dma))) - goto err_dma; - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, - ATL1C_PCIMAP_TODEVICE); - mapped_len += map_len; - use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); - use_tpd->buffer_len = cpu_to_le16(buffer_info->length); - } - - if (mapped_len < buf_len) { - /* mapped_len == 0, means we should use the first tpd, - which is given by caller */ - if (mapped_len == 0) - use_tpd = tpd; - else { - use_tpd = atl1c_get_tpd(adapter, type); - memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc)); - } - buffer_info = atl1c_get_tx_buffer(adapter, use_tpd); - buffer_info->length = buf_len - mapped_len; - buffer_info->dma = - pci_map_single(adapter->pdev, skb->data + mapped_len, - buffer_info->length, PCI_DMA_TODEVICE); - if (unlikely(pci_dma_mapping_error(adapter->pdev, - buffer_info->dma))) - goto err_dma; - - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, - ATL1C_PCIMAP_TODEVICE); - use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); - use_tpd->buffer_len = cpu_to_le16(buffer_info->length); - } - - for (f = 0; f < nr_frags; f++) { - struct skb_frag_struct *frag; - - frag = &skb_shinfo(skb)->frags[f]; - - use_tpd = atl1c_get_tpd(adapter, type); - memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc)); - - buffer_info = atl1c_get_tx_buffer(adapter, use_tpd); - buffer_info->length = skb_frag_size(frag); - buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev, - frag, 0, - buffer_info->length, - DMA_TO_DEVICE); - if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) - goto err_dma; - - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE, - ATL1C_PCIMAP_TODEVICE); - use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); - use_tpd->buffer_len = cpu_to_le16(buffer_info->length); - } - - /* The last tpd */ - use_tpd->word1 |= 1 << TPD_EOP_SHIFT; - /* The last buffer info contain the skb address, - so it will be free after unmap */ - buffer_info->skb = skb; - - return 0; - -err_dma: - buffer_info->dma = 0; - buffer_info->length = 0; - return -1; -} - -static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb, - struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type) -{ - struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; - u16 reg; - - reg = type == atl1c_trans_high ? REG_TPD_PRI1_PIDX : REG_TPD_PRI0_PIDX; - AT_WRITE_REGW(&adapter->hw, reg, tpd_ring->next_to_use); -} - -static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - unsigned long flags; - u16 tpd_req = 1; - struct atl1c_tpd_desc *tpd; - enum atl1c_trans_queue type = atl1c_trans_normal; - - if (test_bit(__AT_DOWN, &adapter->flags)) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - tpd_req = atl1c_cal_tpd_req(skb); - if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) { - if (netif_msg_pktdata(adapter)) - dev_info(&adapter->pdev->dev, "tx locked\n"); - return NETDEV_TX_LOCKED; - } - - if (atl1c_tpd_avail(adapter, type) < tpd_req) { - /* no enough descriptor, just stop queue */ - netif_stop_queue(netdev); - spin_unlock_irqrestore(&adapter->tx_lock, flags); - return NETDEV_TX_BUSY; - } - - tpd = atl1c_get_tpd(adapter, type); - - /* do TSO and check sum */ - if (atl1c_tso_csum(adapter, skb, &tpd, type) != 0) { - spin_unlock_irqrestore(&adapter->tx_lock, flags); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if (unlikely(vlan_tx_tag_present(skb))) { - u16 vlan = vlan_tx_tag_get(skb); - __le16 tag; - - vlan = cpu_to_le16(vlan); - AT_VLAN_TO_TAG(vlan, tag); - tpd->word1 |= 1 << TPD_INS_VTAG_SHIFT; - tpd->vlan_tag = tag; - } - - if (skb_network_offset(skb) != ETH_HLEN) - tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */ - - if (atl1c_tx_map(adapter, skb, tpd, type) < 0) { - netif_info(adapter, tx_done, adapter->netdev, - "tx-skb droppted due to dma error\n"); - /* roll back tpd/buffer */ - atl1c_tx_rollback(adapter, tpd, type); - spin_unlock_irqrestore(&adapter->tx_lock, flags); - dev_kfree_skb(skb); - } else { - atl1c_tx_queue(adapter, skb, tpd, type); - spin_unlock_irqrestore(&adapter->tx_lock, flags); - } - - return NETDEV_TX_OK; -} - -static void atl1c_free_irq(struct atl1c_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - free_irq(adapter->pdev->irq, netdev); - - if (adapter->have_msi) - pci_disable_msi(adapter->pdev); -} - -static int atl1c_request_irq(struct atl1c_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - struct net_device *netdev = adapter->netdev; - int flags = 0; - int err = 0; - - adapter->have_msi = true; - err = pci_enable_msi(adapter->pdev); - if (err) { - if (netif_msg_ifup(adapter)) - dev_err(&pdev->dev, - "Unable to allocate MSI interrupt Error: %d\n", - err); - adapter->have_msi = false; - } - - if (!adapter->have_msi) - flags |= IRQF_SHARED; - err = request_irq(adapter->pdev->irq, atl1c_intr, flags, - netdev->name, netdev); - if (err) { - if (netif_msg_ifup(adapter)) - dev_err(&pdev->dev, - "Unable to allocate interrupt Error: %d\n", - err); - if (adapter->have_msi) - pci_disable_msi(adapter->pdev); - return err; - } - if (netif_msg_ifup(adapter)) - dev_dbg(&pdev->dev, "atl1c_request_irq OK\n"); - return err; -} - - -static void atl1c_reset_dma_ring(struct atl1c_adapter *adapter) -{ - /* release tx-pending skbs and reset tx/rx ring index */ - atl1c_clean_tx_ring(adapter, atl1c_trans_normal); - atl1c_clean_tx_ring(adapter, atl1c_trans_high); - atl1c_clean_rx_ring(adapter); -} - -static int atl1c_up(struct atl1c_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - int err; - - netif_carrier_off(netdev); - - err = atl1c_configure(adapter); - if (unlikely(err)) - goto err_up; - - err = atl1c_request_irq(adapter); - if (unlikely(err)) - goto err_up; - - atl1c_check_link_status(adapter); - clear_bit(__AT_DOWN, &adapter->flags); - napi_enable(&adapter->napi); - atl1c_irq_enable(adapter); - netif_start_queue(netdev); - return err; - -err_up: - atl1c_clean_rx_ring(adapter); - return err; -} - -static void atl1c_down(struct atl1c_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - atl1c_del_timer(adapter); - adapter->work_event = 0; /* clear all event */ - /* signal that we're down so the interrupt handler does not - * reschedule our watchdog timer */ - set_bit(__AT_DOWN, &adapter->flags); - netif_carrier_off(netdev); - napi_disable(&adapter->napi); - atl1c_irq_disable(adapter); - atl1c_free_irq(adapter); - /* disable ASPM if device inactive */ - atl1c_disable_l0s_l1(&adapter->hw); - /* reset MAC to disable all RX/TX */ - atl1c_reset_mac(&adapter->hw); - msleep(1); - - adapter->link_speed = SPEED_0; - adapter->link_duplex = -1; - atl1c_reset_dma_ring(adapter); -} - -/** - * atl1c_open - Called when a network interface is made active - * @netdev: network interface device structure - * - * Returns 0 on success, negative value on failure - * - * The open entry point is called when a network interface is made - * active by the system (IFF_UP). At this point all resources needed - * for transmit and receive operations are allocated, the interrupt - * handler is registered with the OS, the watchdog timer is started, - * and the stack is notified that the interface is ready. - */ -static int atl1c_open(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - int err; - - /* disallow open during test */ - if (test_bit(__AT_TESTING, &adapter->flags)) - return -EBUSY; - - /* allocate rx/tx dma buffer & descriptors */ - err = atl1c_setup_ring_resources(adapter); - if (unlikely(err)) - return err; - - err = atl1c_up(adapter); - if (unlikely(err)) - goto err_up; - - return 0; - -err_up: - atl1c_free_irq(adapter); - atl1c_free_ring_resources(adapter); - atl1c_reset_mac(&adapter->hw); - return err; -} - -/** - * atl1c_close - Disables a network interface - * @netdev: network interface device structure - * - * Returns 0, this is not allowed to fail - * - * The close entry point is called when an interface is de-activated - * by the OS. The hardware is still under the drivers control, but - * needs to be disabled. A global MAC reset is issued to stop the - * hardware, and all transmit and receive resources are freed. - */ -static int atl1c_close(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); - set_bit(__AT_DOWN, &adapter->flags); - cancel_work_sync(&adapter->common_task); - atl1c_down(adapter); - atl1c_free_ring_resources(adapter); - return 0; -} - -static int atl1c_suspend(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - u32 wufc = adapter->wol; - - atl1c_disable_l0s_l1(hw); - if (netif_running(netdev)) { - WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); - atl1c_down(adapter); - } - netif_device_detach(netdev); - - if (wufc) - if (atl1c_phy_to_ps_link(hw) != 0) - dev_dbg(&pdev->dev, "phy power saving failed"); - - atl1c_power_saving(hw, wufc); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int atl1c_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - - AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); - atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE); - - atl1c_phy_reset(&adapter->hw); - atl1c_reset_mac(&adapter->hw); - atl1c_phy_init(&adapter->hw); - -#if 0 - AT_READ_REG(&adapter->hw, REG_PM_CTRLSTAT, &pm_data); - pm_data &= ~PM_CTRLSTAT_PME_EN; - AT_WRITE_REG(&adapter->hw, REG_PM_CTRLSTAT, pm_data); -#endif - - netif_device_attach(netdev); - if (netif_running(netdev)) - atl1c_up(adapter); - - return 0; -} -#endif - -static void atl1c_shutdown(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - - atl1c_suspend(&pdev->dev); - pci_wake_from_d3(pdev, adapter->wol); - pci_set_power_state(pdev, PCI_D3hot); -} - -static const struct net_device_ops atl1c_netdev_ops = { - .ndo_open = atl1c_open, - .ndo_stop = atl1c_close, - .ndo_validate_addr = eth_validate_addr, - .ndo_start_xmit = atl1c_xmit_frame, - .ndo_set_mac_address = atl1c_set_mac_addr, - .ndo_set_rx_mode = atl1c_set_multi, - .ndo_change_mtu = atl1c_change_mtu, - .ndo_fix_features = atl1c_fix_features, - .ndo_set_features = atl1c_set_features, - .ndo_do_ioctl = atl1c_ioctl, - .ndo_tx_timeout = atl1c_tx_timeout, - .ndo_get_stats = atl1c_get_stats, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = atl1c_netpoll, -#endif -}; - -static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev) -{ - SET_NETDEV_DEV(netdev, &pdev->dev); - pci_set_drvdata(pdev, netdev); - - netdev->netdev_ops = &atl1c_netdev_ops; - netdev->watchdog_timeo = AT_TX_WATCHDOG; - atl1c_set_ethtool_ops(netdev); - - /* TODO: add when ready */ - netdev->hw_features = NETIF_F_SG | - NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_TSO | - NETIF_F_TSO6; - netdev->features = netdev->hw_features | - NETIF_F_HW_VLAN_CTAG_TX; - return 0; -} - -/** - * atl1c_probe - Device Initialization Routine - * @pdev: PCI device information struct - * @ent: entry in atl1c_pci_tbl - * - * Returns 0 on success, negative on failure - * - * atl1c_probe initializes an adapter identified by a pci_dev structure. - * The OS initialization, configuring of the adapter private structure, - * and a hardware reset occur. - */ -static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct atl1c_adapter *adapter; - static int cards_found; - - int err = 0; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - err = pci_enable_device_mem(pdev); - if (err) { - dev_err(&pdev->dev, "cannot enable PCI device\n"); - return err; - } - - /* - * The atl1c chip can DMA to 64-bit addresses, but it uses a single - * shared register for the high 32 bits, so only a single, aligned, - * 4 GB physical address range can be used at a time. - * - * Supporting 64-bit DMA on this hardware is more trouble than it's - * worth. It is far easier to limit to 32-bit DMA than update - * various kernel subsystems to support the mechanics required by a - * fixed-high-32-bit system. - */ - if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) || - (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)) { - dev_err(&pdev->dev, "No usable DMA configuration,aborting\n"); - goto err_dma; - } - - err = pci_request_regions(pdev, atl1c_driver_name); - if (err) { - dev_err(&pdev->dev, "cannot obtain PCI resources\n"); - goto err_pci_reg; - } - - pci_set_master(pdev); - - netdev = alloc_etherdev(sizeof(struct atl1c_adapter)); - if (netdev == NULL) { - err = -ENOMEM; - goto err_alloc_etherdev; - } - - err = atl1c_init_netdev(netdev, pdev); - if (err) { - dev_err(&pdev->dev, "init netdevice failed\n"); - goto err_init_netdev; - } - adapter = netdev_priv(netdev); - adapter->bd_number = cards_found; - adapter->netdev = netdev; - adapter->pdev = pdev; - adapter->hw.adapter = adapter; - adapter->msg_enable = netif_msg_init(-1, atl1c_default_msg); - adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); - if (!adapter->hw.hw_addr) { - err = -EIO; - dev_err(&pdev->dev, "cannot map device registers\n"); - goto err_ioremap; - } - - /* init mii data */ - adapter->mii.dev = netdev; - adapter->mii.mdio_read = atl1c_mdio_read; - adapter->mii.mdio_write = atl1c_mdio_write; - adapter->mii.phy_id_mask = 0x1f; - adapter->mii.reg_num_mask = MDIO_CTRL_REG_MASK; - netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64); - setup_timer(&adapter->phy_config_timer, atl1c_phy_config, - (unsigned long)adapter); - /* setup the private structure */ - err = atl1c_sw_init(adapter); - if (err) { - dev_err(&pdev->dev, "net device private data init failed\n"); - goto err_sw_init; - } - atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE); - - /* Init GPHY as early as possible due to power saving issue */ - atl1c_phy_reset(&adapter->hw); - - err = atl1c_reset_mac(&adapter->hw); - if (err) { - err = -EIO; - goto err_reset; - } - - /* reset the controller to - * put the device in a known good starting state */ - err = atl1c_phy_init(&adapter->hw); - if (err) { - err = -EIO; - goto err_reset; - } - if (atl1c_read_mac_addr(&adapter->hw)) { - /* got a random MAC address, set NET_ADDR_RANDOM to netdev */ - netdev->addr_assign_type = NET_ADDR_RANDOM; - } - memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); - if (netif_msg_probe(adapter)) - dev_dbg(&pdev->dev, "mac address : %pM\n", - adapter->hw.mac_addr); - - atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr); - INIT_WORK(&adapter->common_task, atl1c_common_task); - adapter->work_event = 0; - err = register_netdev(netdev); - if (err) { - dev_err(&pdev->dev, "register netdevice failed\n"); - goto err_register; - } - - if (netif_msg_probe(adapter)) - dev_info(&pdev->dev, "version %s\n", ATL1C_DRV_VERSION); - cards_found++; - return 0; - -err_reset: -err_register: -err_sw_init: - iounmap(adapter->hw.hw_addr); -err_init_netdev: -err_ioremap: - free_netdev(netdev); -err_alloc_etherdev: - pci_release_regions(pdev); -err_pci_reg: -err_dma: - pci_disable_device(pdev); - return err; -} - -/** - * atl1c_remove - Device Removal Routine - * @pdev: PCI device information struct - * - * atl1c_remove is called by the PCI subsystem to alert the driver - * that it should release a PCI device. The could be caused by a - * Hot-Plug event, or because the driver is going to be removed from - * memory. - */ -static void atl1c_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - - unregister_netdev(netdev); - /* restore permanent address */ - atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.perm_mac_addr); - atl1c_phy_disable(&adapter->hw); - - iounmap(adapter->hw.hw_addr); - - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(netdev); -} - -/** - * atl1c_io_error_detected - called when PCI error is detected - * @pdev: Pointer to PCI device - * @state: The current pci connection state - * - * This function is called after a PCI bus error affecting - * this device has been detected. - */ -static pci_ers_result_t atl1c_io_error_detected(struct pci_dev *pdev, - pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - atl1c_down(adapter); - - pci_disable_device(pdev); - - /* Request a slot slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * atl1c_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch, as if from a cold-boot. Implementation - * resembles the first-half of the e1000_resume routine. - */ -static pci_ers_result_t atl1c_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - if (netif_msg_hw(adapter)) - dev_err(&pdev->dev, - "Cannot re-enable PCI device after reset\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - atl1c_reset_mac(&adapter->hw); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * atl1c_io_resume - called when traffic can start flowing again. - * @pdev: Pointer to PCI device - * - * This callback is called when the error recovery driver tells us that - * its OK to resume normal operation. Implementation resembles the - * second-half of the atl1c_resume routine. - */ -static void atl1c_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - - if (netif_running(netdev)) { - if (atl1c_up(adapter)) { - if (netif_msg_hw(adapter)) - dev_err(&pdev->dev, - "Cannot bring device back up after reset\n"); - return; - } - } - - netif_device_attach(netdev); -} - -static const struct pci_error_handlers atl1c_err_handler = { - .error_detected = atl1c_io_error_detected, - .slot_reset = atl1c_io_slot_reset, - .resume = atl1c_io_resume, -}; - -static SIMPLE_DEV_PM_OPS(atl1c_pm_ops, atl1c_suspend, atl1c_resume); - -static struct pci_driver atl1c_driver = { - .name = atl1c_driver_name, - .id_table = atl1c_pci_tbl, - .probe = atl1c_probe, - .remove = atl1c_remove, - .shutdown = atl1c_shutdown, - .err_handler = &atl1c_err_handler, - .driver.pm = &atl1c_pm_ops, -}; - -/** - * atl1c_init_module - Driver Registration Routine - * - * atl1c_init_module is the first routine called when the driver is - * loaded. All it does is register with the PCI subsystem. - */ -static int __init atl1c_init_module(void) -{ - return pci_register_driver(&atl1c_driver); -} - -/** - * atl1c_exit_module - Driver Exit Cleanup Routine - * - * atl1c_exit_module is called just before the driver is removed - * from memory. - */ -static void __exit atl1c_exit_module(void) -{ - pci_unregister_driver(&atl1c_driver); -} - -module_init(atl1c_init_module); -module_exit(atl1c_exit_module); diff --git a/addons/atl1c/src/4.4.180/Makefile b/addons/atl1c/src/4.4.180/Makefile deleted file mode 100644 index d6fff141..00000000 --- a/addons/atl1c/src/4.4.180/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-m += atl1c.o -atl1c-objs := atl1c_main.o atl1c_hw.o atl1c_ethtool.o diff --git a/addons/atl1c/src/4.4.180/atl1c.h b/addons/atl1c/src/4.4.180/atl1c.h deleted file mode 100644 index b9203d92..00000000 --- a/addons/atl1c/src/4.4.180/atl1c.h +++ /dev/null @@ -1,605 +0,0 @@ -/* - * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _ATL1C_H_ -#define _ATL1C_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "atl1c_hw.h" - -/* Wake Up Filter Control */ -#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ -#define AT_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ -#define AT_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ -#define AT_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */ -#define AT_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ - -#define AT_VLAN_TO_TAG(_vlan, _tag) \ - _tag = ((((_vlan) >> 8) & 0xFF) |\ - (((_vlan) & 0xFF) << 8)) - -#define AT_TAG_TO_VLAN(_tag, _vlan) \ - _vlan = ((((_tag) >> 8) & 0xFF) |\ - (((_tag) & 0xFF) << 8)) - -#define SPEED_0 0xffff -#define HALF_DUPLEX 1 -#define FULL_DUPLEX 2 - -#define AT_RX_BUF_SIZE (ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN) -#define MAX_JUMBO_FRAME_SIZE (6*1024) - -#define AT_MAX_RECEIVE_QUEUE 4 -#define AT_DEF_RECEIVE_QUEUE 1 -#define AT_MAX_TRANSMIT_QUEUE 2 - -#define AT_DMA_HI_ADDR_MASK 0xffffffff00000000ULL -#define AT_DMA_LO_ADDR_MASK 0x00000000ffffffffULL - -#define AT_TX_WATCHDOG (5 * HZ) -#define AT_MAX_INT_WORK 5 -#define AT_TWSI_EEPROM_TIMEOUT 100 -#define AT_HW_MAX_IDLE_DELAY 10 -#define AT_SUSPEND_LINK_TIMEOUT 100 - -#define AT_ASPM_L0S_TIMER 6 -#define AT_ASPM_L1_TIMER 12 -#define AT_LCKDET_TIMER 12 - -#define ATL1C_PCIE_L0S_L1_DISABLE 0x01 -#define ATL1C_PCIE_PHY_RESET 0x02 - -#define ATL1C_ASPM_L0s_ENABLE 0x0001 -#define ATL1C_ASPM_L1_ENABLE 0x0002 - -#define AT_REGS_LEN (74 * sizeof(u32)) -#define AT_EEPROM_LEN 512 - -#define ATL1C_GET_DESC(R, i, type) (&(((type *)((R)->desc))[i])) -#define ATL1C_RFD_DESC(R, i) ATL1C_GET_DESC(R, i, struct atl1c_rx_free_desc) -#define ATL1C_TPD_DESC(R, i) ATL1C_GET_DESC(R, i, struct atl1c_tpd_desc) -#define ATL1C_RRD_DESC(R, i) ATL1C_GET_DESC(R, i, struct atl1c_recv_ret_status) - -/* tpd word 1 bit 0:7 General Checksum task offload */ -#define TPD_L4HDR_OFFSET_MASK 0x00FF -#define TPD_L4HDR_OFFSET_SHIFT 0 - -/* tpd word 1 bit 0:7 Large Send task offload (IPv4/IPV6) */ -#define TPD_TCPHDR_OFFSET_MASK 0x00FF -#define TPD_TCPHDR_OFFSET_SHIFT 0 - -/* tpd word 1 bit 0:7 Custom Checksum task offload */ -#define TPD_PLOADOFFSET_MASK 0x00FF -#define TPD_PLOADOFFSET_SHIFT 0 - -/* tpd word 1 bit 8:17 */ -#define TPD_CCSUM_EN_MASK 0x0001 -#define TPD_CCSUM_EN_SHIFT 8 -#define TPD_IP_CSUM_MASK 0x0001 -#define TPD_IP_CSUM_SHIFT 9 -#define TPD_TCP_CSUM_MASK 0x0001 -#define TPD_TCP_CSUM_SHIFT 10 -#define TPD_UDP_CSUM_MASK 0x0001 -#define TPD_UDP_CSUM_SHIFT 11 -#define TPD_LSO_EN_MASK 0x0001 /* TCP Large Send Offload */ -#define TPD_LSO_EN_SHIFT 12 -#define TPD_LSO_VER_MASK 0x0001 -#define TPD_LSO_VER_SHIFT 13 /* 0 : ipv4; 1 : ipv4/ipv6 */ -#define TPD_CON_VTAG_MASK 0x0001 -#define TPD_CON_VTAG_SHIFT 14 -#define TPD_INS_VTAG_MASK 0x0001 -#define TPD_INS_VTAG_SHIFT 15 -#define TPD_IPV4_PACKET_MASK 0x0001 /* valid when LSO VER is 1 */ -#define TPD_IPV4_PACKET_SHIFT 16 -#define TPD_ETH_TYPE_MASK 0x0001 -#define TPD_ETH_TYPE_SHIFT 17 /* 0 : 802.3 frame; 1 : Ethernet */ - -/* tpd word 18:25 Custom Checksum task offload */ -#define TPD_CCSUM_OFFSET_MASK 0x00FF -#define TPD_CCSUM_OFFSET_SHIFT 18 -#define TPD_CCSUM_EPAD_MASK 0x0001 -#define TPD_CCSUM_EPAD_SHIFT 30 - -/* tpd word 18:30 Large Send task offload (IPv4/IPV6) */ -#define TPD_MSS_MASK 0x1FFF -#define TPD_MSS_SHIFT 18 - -#define TPD_EOP_MASK 0x0001 -#define TPD_EOP_SHIFT 31 - -struct atl1c_tpd_desc { - __le16 buffer_len; /* include 4-byte CRC */ - __le16 vlan_tag; - __le32 word1; - __le64 buffer_addr; -}; - -struct atl1c_tpd_ext_desc { - u32 reservd_0; - __le32 word1; - __le32 pkt_len; - u32 reservd_1; -}; -/* rrs word 0 bit 0:31 */ -#define RRS_RX_CSUM_MASK 0xFFFF -#define RRS_RX_CSUM_SHIFT 0 -#define RRS_RX_RFD_CNT_MASK 0x000F -#define RRS_RX_RFD_CNT_SHIFT 16 -#define RRS_RX_RFD_INDEX_MASK 0x0FFF -#define RRS_RX_RFD_INDEX_SHIFT 20 - -/* rrs flag bit 0:16 */ -#define RRS_HEAD_LEN_MASK 0x00FF -#define RRS_HEAD_LEN_SHIFT 0 -#define RRS_HDS_TYPE_MASK 0x0003 -#define RRS_HDS_TYPE_SHIFT 8 -#define RRS_CPU_NUM_MASK 0x0003 -#define RRS_CPU_NUM_SHIFT 10 -#define RRS_HASH_FLG_MASK 0x000F -#define RRS_HASH_FLG_SHIFT 12 - -#define RRS_HDS_TYPE_HEAD 1 -#define RRS_HDS_TYPE_DATA 2 - -#define RRS_IS_NO_HDS_TYPE(flag) \ - ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == 0) - -#define RRS_IS_HDS_HEAD(flag) \ - ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \ - RRS_HDS_TYPE_HEAD) - -#define RRS_IS_HDS_DATA(flag) \ - ((((flag) >> (RRS_HDS_TYPE_SHIFT)) & RRS_HDS_TYPE_MASK) == \ - RRS_HDS_TYPE_DATA) - -/* rrs word 3 bit 0:31 */ -#define RRS_PKT_SIZE_MASK 0x3FFF -#define RRS_PKT_SIZE_SHIFT 0 -#define RRS_ERR_L4_CSUM_MASK 0x0001 -#define RRS_ERR_L4_CSUM_SHIFT 14 -#define RRS_ERR_IP_CSUM_MASK 0x0001 -#define RRS_ERR_IP_CSUM_SHIFT 15 -#define RRS_VLAN_INS_MASK 0x0001 -#define RRS_VLAN_INS_SHIFT 16 -#define RRS_PROT_ID_MASK 0x0007 -#define RRS_PROT_ID_SHIFT 17 -#define RRS_RX_ERR_SUM_MASK 0x0001 -#define RRS_RX_ERR_SUM_SHIFT 20 -#define RRS_RX_ERR_CRC_MASK 0x0001 -#define RRS_RX_ERR_CRC_SHIFT 21 -#define RRS_RX_ERR_FAE_MASK 0x0001 -#define RRS_RX_ERR_FAE_SHIFT 22 -#define RRS_RX_ERR_TRUNC_MASK 0x0001 -#define RRS_RX_ERR_TRUNC_SHIFT 23 -#define RRS_RX_ERR_RUNC_MASK 0x0001 -#define RRS_RX_ERR_RUNC_SHIFT 24 -#define RRS_RX_ERR_ICMP_MASK 0x0001 -#define RRS_RX_ERR_ICMP_SHIFT 25 -#define RRS_PACKET_BCAST_MASK 0x0001 -#define RRS_PACKET_BCAST_SHIFT 26 -#define RRS_PACKET_MCAST_MASK 0x0001 -#define RRS_PACKET_MCAST_SHIFT 27 -#define RRS_PACKET_TYPE_MASK 0x0001 -#define RRS_PACKET_TYPE_SHIFT 28 -#define RRS_FIFO_FULL_MASK 0x0001 -#define RRS_FIFO_FULL_SHIFT 29 -#define RRS_802_3_LEN_ERR_MASK 0x0001 -#define RRS_802_3_LEN_ERR_SHIFT 30 -#define RRS_RXD_UPDATED_MASK 0x0001 -#define RRS_RXD_UPDATED_SHIFT 31 - -#define RRS_ERR_L4_CSUM 0x00004000 -#define RRS_ERR_IP_CSUM 0x00008000 -#define RRS_VLAN_INS 0x00010000 -#define RRS_RX_ERR_SUM 0x00100000 -#define RRS_RX_ERR_CRC 0x00200000 -#define RRS_802_3_LEN_ERR 0x40000000 -#define RRS_RXD_UPDATED 0x80000000 - -#define RRS_PACKET_TYPE_802_3 1 -#define RRS_PACKET_TYPE_ETH 0 -#define RRS_PACKET_IS_ETH(word) \ - ((((word) >> RRS_PACKET_TYPE_SHIFT) & RRS_PACKET_TYPE_MASK) == \ - RRS_PACKET_TYPE_ETH) -#define RRS_RXD_IS_VALID(word) \ - ((((word) >> RRS_RXD_UPDATED_SHIFT) & RRS_RXD_UPDATED_MASK) == 1) - -#define RRS_PACKET_PROT_IS_IPV4_ONLY(word) \ - ((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 1) -#define RRS_PACKET_PROT_IS_IPV6_ONLY(word) \ - ((((word) >> RRS_PROT_ID_SHIFT) & RRS_PROT_ID_MASK) == 6) - -struct atl1c_recv_ret_status { - __le32 word0; - __le32 rss_hash; - __le16 vlan_tag; - __le16 flag; - __le32 word3; -}; - -/* RFD descriptor */ -struct atl1c_rx_free_desc { - __le64 buffer_addr; -}; - -/* DMA Order Settings */ -enum atl1c_dma_order { - atl1c_dma_ord_in = 1, - atl1c_dma_ord_enh = 2, - atl1c_dma_ord_out = 4 -}; - -enum atl1c_dma_rcb { - atl1c_rcb_64 = 0, - atl1c_rcb_128 = 1 -}; - -enum atl1c_mac_speed { - atl1c_mac_speed_0 = 0, - atl1c_mac_speed_10_100 = 1, - atl1c_mac_speed_1000 = 2 -}; - -enum atl1c_dma_req_block { - atl1c_dma_req_128 = 0, - atl1c_dma_req_256 = 1, - atl1c_dma_req_512 = 2, - atl1c_dma_req_1024 = 3, - atl1c_dma_req_2048 = 4, - atl1c_dma_req_4096 = 5 -}; - - -enum atl1c_nic_type { - athr_l1c = 0, - athr_l2c = 1, - athr_l2c_b, - athr_l2c_b2, - athr_l1d, - athr_l1d_2, -}; - -enum atl1c_trans_queue { - atl1c_trans_normal = 0, - atl1c_trans_high = 1 -}; - -struct atl1c_hw_stats { - /* rx */ - unsigned long rx_ok; /* The number of good packet received. */ - unsigned long rx_bcast; /* The number of good broadcast packet received. */ - unsigned long rx_mcast; /* The number of good multicast packet received. */ - unsigned long rx_pause; /* The number of Pause packet received. */ - unsigned long rx_ctrl; /* The number of Control packet received other than Pause frame. */ - unsigned long rx_fcs_err; /* The number of packets with bad FCS. */ - unsigned long rx_len_err; /* The number of packets with mismatch of length field and actual size. */ - unsigned long rx_byte_cnt; /* The number of bytes of good packet received. FCS is NOT included. */ - unsigned long rx_runt; /* The number of packets received that are less than 64 byte long and with good FCS. */ - unsigned long rx_frag; /* The number of packets received that are less than 64 byte long and with bad FCS. */ - unsigned long rx_sz_64; /* The number of good and bad packets received that are 64 byte long. */ - unsigned long rx_sz_65_127; /* The number of good and bad packets received that are between 65 and 127-byte long. */ - unsigned long rx_sz_128_255; /* The number of good and bad packets received that are between 128 and 255-byte long. */ - unsigned long rx_sz_256_511; /* The number of good and bad packets received that are between 256 and 511-byte long. */ - unsigned long rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */ - unsigned long rx_sz_1024_1518; /* The number of good and bad packets received that are between 1024 and 1518-byte long. */ - unsigned long rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */ - unsigned long rx_sz_ov; /* The number of good and bad packets received that are more than MTU size truncated by Selene. */ - unsigned long rx_rxf_ov; /* The number of frame dropped due to occurrence of RX FIFO overflow. */ - unsigned long rx_rrd_ov; /* The number of frame dropped due to occurrence of RRD overflow. */ - unsigned long rx_align_err; /* Alignment Error */ - unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */ - unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */ - unsigned long rx_err_addr; /* The number of packets dropped due to address filtering. */ - - /* tx */ - unsigned long tx_ok; /* The number of good packet transmitted. */ - unsigned long tx_bcast; /* The number of good broadcast packet transmitted. */ - unsigned long tx_mcast; /* The number of good multicast packet transmitted. */ - unsigned long tx_pause; /* The number of Pause packet transmitted. */ - unsigned long tx_exc_defer; /* The number of packets transmitted with excessive deferral. */ - unsigned long tx_ctrl; /* The number of packets transmitted is a control frame, excluding Pause frame. */ - unsigned long tx_defer; /* The number of packets transmitted that is deferred. */ - unsigned long tx_byte_cnt; /* The number of bytes of data transmitted. FCS is NOT included. */ - unsigned long tx_sz_64; /* The number of good and bad packets transmitted that are 64 byte long. */ - unsigned long tx_sz_65_127; /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */ - unsigned long tx_sz_128_255; /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */ - unsigned long tx_sz_256_511; /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */ - unsigned long tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */ - unsigned long tx_sz_1024_1518; /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */ - unsigned long tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */ - unsigned long tx_1_col; /* The number of packets subsequently transmitted successfully with a single prior collision. */ - unsigned long tx_2_col; /* The number of packets subsequently transmitted successfully with multiple prior collisions. */ - unsigned long tx_late_col; /* The number of packets transmitted with late collisions. */ - unsigned long tx_abort_col; /* The number of transmit packets aborted due to excessive collisions. */ - unsigned long tx_underrun; /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */ - unsigned long tx_rd_eop; /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */ - unsigned long tx_len_err; /* The number of transmit packets with length field does NOT match the actual frame size. */ - unsigned long tx_trunc; /* The number of transmit packets truncated due to size exceeding MTU. */ - unsigned long tx_bcast_byte; /* The byte count of broadcast packet transmitted, excluding FCS. */ - unsigned long tx_mcast_byte; /* The byte count of multicast packet transmitted, excluding FCS. */ -}; - -struct atl1c_hw { - u8 __iomem *hw_addr; /* inner register address */ - struct atl1c_adapter *adapter; - enum atl1c_nic_type nic_type; - enum atl1c_dma_order dma_order; - enum atl1c_dma_rcb rcb_value; - enum atl1c_dma_req_block dmar_block; - - u16 device_id; - u16 vendor_id; - u16 subsystem_id; - u16 subsystem_vendor_id; - u8 revision_id; - u16 phy_id1; - u16 phy_id2; - - u32 intr_mask; - - u8 preamble_len; - u16 max_frame_size; - u16 min_frame_size; - - enum atl1c_mac_speed mac_speed; - bool mac_duplex; - bool hibernate; - u16 media_type; -#define MEDIA_TYPE_AUTO_SENSOR 0 -#define MEDIA_TYPE_100M_FULL 1 -#define MEDIA_TYPE_100M_HALF 2 -#define MEDIA_TYPE_10M_FULL 3 -#define MEDIA_TYPE_10M_HALF 4 - - u16 autoneg_advertised; - u16 mii_autoneg_adv_reg; - u16 mii_1000t_ctrl_reg; - - u16 tx_imt; /* TX Interrupt Moderator timer ( 2us resolution) */ - u16 rx_imt; /* RX Interrupt Moderator timer ( 2us resolution) */ - u16 ict; /* Interrupt Clear timer (2us resolution) */ - u16 ctrl_flags; -#define ATL1C_INTR_CLEAR_ON_READ 0x0001 -#define ATL1C_INTR_MODRT_ENABLE 0x0002 -#define ATL1C_CMB_ENABLE 0x0004 -#define ATL1C_SMB_ENABLE 0x0010 -#define ATL1C_TXQ_MODE_ENHANCE 0x0020 -#define ATL1C_RX_IPV6_CHKSUM 0x0040 -#define ATL1C_ASPM_L0S_SUPPORT 0x0080 -#define ATL1C_ASPM_L1_SUPPORT 0x0100 -#define ATL1C_ASPM_CTRL_MON 0x0200 -#define ATL1C_HIB_DISABLE 0x0400 -#define ATL1C_APS_MODE_ENABLE 0x0800 -#define ATL1C_LINK_EXT_SYNC 0x1000 -#define ATL1C_CLK_GATING_EN 0x2000 -#define ATL1C_FPGA_VERSION 0x8000 - u16 link_cap_flags; -#define ATL1C_LINK_CAP_1000M 0x0001 - u32 smb_timer; - - u16 rrd_thresh; /* Threshold of number of RRD produced to trigger - interrupt request */ - u16 tpd_thresh; - u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */ - u8 rfd_burst; - u32 base_cpu; - u32 indirect_tab; - u8 mac_addr[ETH_ALEN]; - u8 perm_mac_addr[ETH_ALEN]; - - bool phy_configured; - bool re_autoneg; - bool emi_ca; - bool msi_lnkpatch; /* link patch for specific platforms */ -}; - -/* - * atl1c_ring_header represents a single, contiguous block of DMA space - * mapped for the three descriptor rings (tpd, rfd, rrd) described below - */ -struct atl1c_ring_header { - void *desc; /* virtual address */ - dma_addr_t dma; /* physical address*/ - unsigned int size; /* length in bytes */ -}; - -/* - * atl1c_buffer is wrapper around a pointer to a socket buffer - * so a DMA handle can be stored along with the skb - */ -struct atl1c_buffer { - struct sk_buff *skb; /* socket buffer */ - u16 length; /* rx buffer length */ - u16 flags; /* information of buffer */ -#define ATL1C_BUFFER_FREE 0x0001 -#define ATL1C_BUFFER_BUSY 0x0002 -#define ATL1C_BUFFER_STATE_MASK 0x0003 - -#define ATL1C_PCIMAP_SINGLE 0x0004 -#define ATL1C_PCIMAP_PAGE 0x0008 -#define ATL1C_PCIMAP_TYPE_MASK 0x000C - -#define ATL1C_PCIMAP_TODEVICE 0x0010 -#define ATL1C_PCIMAP_FROMDEVICE 0x0020 -#define ATL1C_PCIMAP_DIRECTION_MASK 0x0030 - dma_addr_t dma; -}; - -#define ATL1C_SET_BUFFER_STATE(buff, state) do { \ - ((buff)->flags) &= ~ATL1C_BUFFER_STATE_MASK; \ - ((buff)->flags) |= (state); \ - } while (0) - -#define ATL1C_SET_PCIMAP_TYPE(buff, type, direction) do { \ - ((buff)->flags) &= ~ATL1C_PCIMAP_TYPE_MASK; \ - ((buff)->flags) |= (type); \ - ((buff)->flags) &= ~ATL1C_PCIMAP_DIRECTION_MASK; \ - ((buff)->flags) |= (direction); \ - } while (0) - -/* transimit packet descriptor (tpd) ring */ -struct atl1c_tpd_ring { - void *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - u16 size; /* descriptor ring length in bytes */ - u16 count; /* number of descriptors in the ring */ - u16 next_to_use; /* this is protectd by adapter->tx_lock */ - atomic_t next_to_clean; - struct atl1c_buffer *buffer_info; -}; - -/* receive free descriptor (rfd) ring */ -struct atl1c_rfd_ring { - void *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - u16 size; /* descriptor ring length in bytes */ - u16 count; /* number of descriptors in the ring */ - u16 next_to_use; - u16 next_to_clean; - struct atl1c_buffer *buffer_info; -}; - -/* receive return descriptor (rrd) ring */ -struct atl1c_rrd_ring { - void *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - u16 size; /* descriptor ring length in bytes */ - u16 count; /* number of descriptors in the ring */ - u16 next_to_use; - u16 next_to_clean; -}; - -/* board specific private data structure */ -struct atl1c_adapter { - struct net_device *netdev; - struct pci_dev *pdev; - struct napi_struct napi; - struct page *rx_page; - unsigned int rx_page_offset; - unsigned int rx_frag_size; - struct atl1c_hw hw; - struct atl1c_hw_stats hw_stats; - struct mii_if_info mii; /* MII interface info */ - u16 rx_buffer_len; - - unsigned long flags; -#define __AT_TESTING 0x0001 -#define __AT_RESETTING 0x0002 -#define __AT_DOWN 0x0003 - unsigned long work_event; -#define ATL1C_WORK_EVENT_RESET 0 -#define ATL1C_WORK_EVENT_LINK_CHANGE 1 - u32 msg_enable; - - bool have_msi; - u32 wol; - u16 link_speed; - u16 link_duplex; - - spinlock_t mdio_lock; - spinlock_t tx_lock; - atomic_t irq_sem; - - struct work_struct common_task; - struct timer_list watchdog_timer; - struct timer_list phy_config_timer; - - /* All Descriptor memory */ - struct atl1c_ring_header ring_header; - struct atl1c_tpd_ring tpd_ring[AT_MAX_TRANSMIT_QUEUE]; - struct atl1c_rfd_ring rfd_ring; - struct atl1c_rrd_ring rrd_ring; - u32 bd_number; /* board number;*/ -}; - -#define AT_WRITE_REG(a, reg, value) ( \ - writel((value), ((a)->hw_addr + reg))) - -#define AT_WRITE_FLUSH(a) (\ - readl((a)->hw_addr)) - -#define AT_READ_REG(a, reg, pdata) do { \ - if (unlikely((a)->hibernate)) { \ - readl((a)->hw_addr + reg); \ - *(u32 *)pdata = readl((a)->hw_addr + reg); \ - } else { \ - *(u32 *)pdata = readl((a)->hw_addr + reg); \ - } \ - } while (0) - -#define AT_WRITE_REGB(a, reg, value) (\ - writeb((value), ((a)->hw_addr + reg))) - -#define AT_READ_REGB(a, reg) (\ - readb((a)->hw_addr + reg)) - -#define AT_WRITE_REGW(a, reg, value) (\ - writew((value), ((a)->hw_addr + reg))) - -#define AT_READ_REGW(a, reg, pdata) do { \ - if (unlikely((a)->hibernate)) { \ - readw((a)->hw_addr + reg); \ - *(u16 *)pdata = readw((a)->hw_addr + reg); \ - } else { \ - *(u16 *)pdata = readw((a)->hw_addr + reg); \ - } \ - } while (0) - -#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \ - writel((value), (((a)->hw_addr + reg) + ((offset) << 2)))) - -#define AT_READ_REG_ARRAY(a, reg, offset) ( \ - readl(((a)->hw_addr + reg) + ((offset) << 2))) - -extern char atl1c_driver_name[]; -extern char atl1c_driver_version[]; - -void atl1c_reinit_locked(struct atl1c_adapter *adapter); -s32 atl1c_reset_hw(struct atl1c_hw *hw); -void atl1c_set_ethtool_ops(struct net_device *netdev); -#endif /* _ATL1C_H_ */ diff --git a/addons/atl1c/src/4.4.180/atl1c_ethtool.c b/addons/atl1c/src/4.4.180/atl1c_ethtool.c deleted file mode 100644 index 872b7abb..00000000 --- a/addons/atl1c/src/4.4.180/atl1c_ethtool.c +++ /dev/null @@ -1,305 +0,0 @@ -/* - * Copyright(c) 2009 - 2009 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include -#include -#include - -#include "atl1c.h" - -static int atl1c_get_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - - ecmd->supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP); - if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M) - ecmd->supported |= SUPPORTED_1000baseT_Full; - - ecmd->advertising = ADVERTISED_TP; - - ecmd->advertising |= hw->autoneg_advertised; - - ecmd->port = PORT_TP; - ecmd->phy_address = 0; - ecmd->transceiver = XCVR_INTERNAL; - - if (adapter->link_speed != SPEED_0) { - ethtool_cmd_speed_set(ecmd, adapter->link_speed); - if (adapter->link_duplex == FULL_DUPLEX) - ecmd->duplex = DUPLEX_FULL; - else - ecmd->duplex = DUPLEX_HALF; - } else { - ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); - ecmd->duplex = DUPLEX_UNKNOWN; - } - - ecmd->autoneg = AUTONEG_ENABLE; - return 0; -} - -static int atl1c_set_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - u16 autoneg_advertised; - - while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) - msleep(1); - - if (ecmd->autoneg == AUTONEG_ENABLE) { - autoneg_advertised = ADVERTISED_Autoneg; - } else { - u32 speed = ethtool_cmd_speed(ecmd); - if (speed == SPEED_1000) { - if (ecmd->duplex != DUPLEX_FULL) { - if (netif_msg_link(adapter)) - dev_warn(&adapter->pdev->dev, - "1000M half is invalid\n"); - clear_bit(__AT_RESETTING, &adapter->flags); - return -EINVAL; - } - autoneg_advertised = ADVERTISED_1000baseT_Full; - } else if (speed == SPEED_100) { - if (ecmd->duplex == DUPLEX_FULL) - autoneg_advertised = ADVERTISED_100baseT_Full; - else - autoneg_advertised = ADVERTISED_100baseT_Half; - } else { - if (ecmd->duplex == DUPLEX_FULL) - autoneg_advertised = ADVERTISED_10baseT_Full; - else - autoneg_advertised = ADVERTISED_10baseT_Half; - } - } - - if (hw->autoneg_advertised != autoneg_advertised) { - hw->autoneg_advertised = autoneg_advertised; - if (atl1c_restart_autoneg(hw) != 0) { - if (netif_msg_link(adapter)) - dev_warn(&adapter->pdev->dev, - "ethtool speed/duplex setting failed\n"); - clear_bit(__AT_RESETTING, &adapter->flags); - return -EINVAL; - } - } - clear_bit(__AT_RESETTING, &adapter->flags); - return 0; -} - -static u32 atl1c_get_msglevel(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - return adapter->msg_enable; -} - -static void atl1c_set_msglevel(struct net_device *netdev, u32 data) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - adapter->msg_enable = data; -} - -static int atl1c_get_regs_len(struct net_device *netdev) -{ - return AT_REGS_LEN; -} - -static void atl1c_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - u32 *regs_buff = p; - u16 phy_data; - - memset(p, 0, AT_REGS_LEN); - - regs->version = 1; - AT_READ_REG(hw, REG_PM_CTRL, p++); - AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL, p++); - AT_READ_REG(hw, REG_TWSI_CTRL, p++); - AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL, p++); - AT_READ_REG(hw, REG_MASTER_CTRL, p++); - AT_READ_REG(hw, REG_MANUAL_TIMER_INIT, p++); - AT_READ_REG(hw, REG_IRQ_MODRT_TIMER_INIT, p++); - AT_READ_REG(hw, REG_GPHY_CTRL, p++); - AT_READ_REG(hw, REG_LINK_CTRL, p++); - AT_READ_REG(hw, REG_IDLE_STATUS, p++); - AT_READ_REG(hw, REG_MDIO_CTRL, p++); - AT_READ_REG(hw, REG_SERDES, p++); - AT_READ_REG(hw, REG_MAC_CTRL, p++); - AT_READ_REG(hw, REG_MAC_IPG_IFG, p++); - AT_READ_REG(hw, REG_MAC_STA_ADDR, p++); - AT_READ_REG(hw, REG_MAC_STA_ADDR+4, p++); - AT_READ_REG(hw, REG_RX_HASH_TABLE, p++); - AT_READ_REG(hw, REG_RX_HASH_TABLE+4, p++); - AT_READ_REG(hw, REG_RXQ_CTRL, p++); - AT_READ_REG(hw, REG_TXQ_CTRL, p++); - AT_READ_REG(hw, REG_MTU, p++); - AT_READ_REG(hw, REG_WOL_CTRL, p++); - - atl1c_read_phy_reg(hw, MII_BMCR, &phy_data); - regs_buff[AT_REGS_LEN/sizeof(u32) - 2] = (u32) phy_data; - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - regs_buff[AT_REGS_LEN/sizeof(u32) - 1] = (u32) phy_data; -} - -static int atl1c_get_eeprom_len(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - if (atl1c_check_eeprom_exist(&adapter->hw)) - return AT_EEPROM_LEN; - else - return 0; -} - -static int atl1c_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - u32 *eeprom_buff; - int first_dword, last_dword; - int ret_val = 0; - int i; - - if (eeprom->len == 0) - return -EINVAL; - - if (!atl1c_check_eeprom_exist(hw)) /* not exist */ - return -EINVAL; - - eeprom->magic = adapter->pdev->vendor | - (adapter->pdev->device << 16); - - first_dword = eeprom->offset >> 2; - last_dword = (eeprom->offset + eeprom->len - 1) >> 2; - - eeprom_buff = kmalloc(sizeof(u32) * - (last_dword - first_dword + 1), GFP_KERNEL); - if (eeprom_buff == NULL) - return -ENOMEM; - - for (i = first_dword; i < last_dword; i++) { - if (!atl1c_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) { - kfree(eeprom_buff); - return -EIO; - } - } - - memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3), - eeprom->len); - kfree(eeprom_buff); - - return ret_val; - return 0; -} - -static void atl1c_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - strlcpy(drvinfo->driver, atl1c_driver_name, sizeof(drvinfo->driver)); - strlcpy(drvinfo->version, atl1c_driver_version, - sizeof(drvinfo->version)); - strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), - sizeof(drvinfo->bus_info)); -} - -static void atl1c_get_wol(struct net_device *netdev, - struct ethtool_wolinfo *wol) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - wol->supported = WAKE_MAGIC | WAKE_PHY; - wol->wolopts = 0; - - if (adapter->wol & AT_WUFC_EX) - wol->wolopts |= WAKE_UCAST; - if (adapter->wol & AT_WUFC_MC) - wol->wolopts |= WAKE_MCAST; - if (adapter->wol & AT_WUFC_BC) - wol->wolopts |= WAKE_BCAST; - if (adapter->wol & AT_WUFC_MAG) - wol->wolopts |= WAKE_MAGIC; - if (adapter->wol & AT_WUFC_LNKC) - wol->wolopts |= WAKE_PHY; -} - -static int atl1c_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | - WAKE_UCAST | WAKE_BCAST | WAKE_MCAST)) - return -EOPNOTSUPP; - /* these settings will always override what we currently have */ - adapter->wol = 0; - - if (wol->wolopts & WAKE_MAGIC) - adapter->wol |= AT_WUFC_MAG; - if (wol->wolopts & WAKE_PHY) - adapter->wol |= AT_WUFC_LNKC; - - device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); - - return 0; -} - -static int atl1c_nway_reset(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - if (netif_running(netdev)) - atl1c_reinit_locked(adapter); - return 0; -} - -static const struct ethtool_ops atl1c_ethtool_ops = { - .get_settings = atl1c_get_settings, - .set_settings = atl1c_set_settings, - .get_drvinfo = atl1c_get_drvinfo, - .get_regs_len = atl1c_get_regs_len, - .get_regs = atl1c_get_regs, - .get_wol = atl1c_get_wol, - .set_wol = atl1c_set_wol, - .get_msglevel = atl1c_get_msglevel, - .set_msglevel = atl1c_set_msglevel, - .nway_reset = atl1c_nway_reset, - .get_link = ethtool_op_get_link, - .get_eeprom_len = atl1c_get_eeprom_len, - .get_eeprom = atl1c_get_eeprom, -}; - -void atl1c_set_ethtool_ops(struct net_device *netdev) -{ - netdev->ethtool_ops = &atl1c_ethtool_ops; -} diff --git a/addons/atl1c/src/4.4.180/atl1c_hw.c b/addons/atl1c/src/4.4.180/atl1c_hw.c deleted file mode 100644 index a8b80c56..00000000 --- a/addons/atl1c/src/4.4.180/atl1c_hw.c +++ /dev/null @@ -1,863 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include -#include -#include -#include - -#include "atl1c.h" - -/* - * check_eeprom_exist - * return 1 if eeprom exist - */ -int atl1c_check_eeprom_exist(struct atl1c_hw *hw) -{ - u32 data; - - AT_READ_REG(hw, REG_TWSI_DEBUG, &data); - if (data & TWSI_DEBUG_DEV_EXIST) - return 1; - - AT_READ_REG(hw, REG_MASTER_CTRL, &data); - if (data & MASTER_CTRL_OTP_SEL) - return 1; - return 0; -} - -void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr) -{ - u32 value; - /* - * 00-0B-6A-F6-00-DC - * 0: 6AF600DC 1: 000B - * low dword - */ - value = mac_addr[2] << 24 | - mac_addr[3] << 16 | - mac_addr[4] << 8 | - mac_addr[5]; - AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value); - /* hight dword */ - value = mac_addr[0] << 8 | - mac_addr[1]; - AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value); -} - -/* read mac address from hardware register */ -static bool atl1c_read_current_addr(struct atl1c_hw *hw, u8 *eth_addr) -{ - u32 addr[2]; - - AT_READ_REG(hw, REG_MAC_STA_ADDR, &addr[0]); - AT_READ_REG(hw, REG_MAC_STA_ADDR + 4, &addr[1]); - - *(u32 *) ð_addr[2] = htonl(addr[0]); - *(u16 *) ð_addr[0] = htons((u16)addr[1]); - - return is_valid_ether_addr(eth_addr); -} - -/* - * atl1c_get_permanent_address - * return 0 if get valid mac address, - */ -static int atl1c_get_permanent_address(struct atl1c_hw *hw) -{ - u32 i; - u32 otp_ctrl_data; - u32 twsi_ctrl_data; - u16 phy_data; - bool raise_vol = false; - - /* MAC-address from BIOS is the 1st priority */ - if (atl1c_read_current_addr(hw, hw->perm_mac_addr)) - return 0; - - /* init */ - AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data); - if (atl1c_check_eeprom_exist(hw)) { - if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) { - /* Enable OTP CLK */ - if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) { - otp_ctrl_data |= OTP_CTRL_CLK_EN; - AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); - AT_WRITE_FLUSH(hw); - msleep(1); - } - } - /* raise voltage temporally for l2cb */ - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { - atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data); - phy_data &= ~ANACTRL_HB_EN; - atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data); - atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); - phy_data |= VOLT_CTRL_SWLOWEST; - atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); - udelay(20); - raise_vol = true; - } - - AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); - twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART; - AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data); - for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) { - msleep(10); - AT_READ_REG(hw, REG_TWSI_CTRL, &twsi_ctrl_data); - if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0) - break; - } - if (i >= AT_TWSI_EEPROM_TIMEOUT) - return -1; - } - /* Disable OTP_CLK */ - if ((hw->nic_type == athr_l1c || hw->nic_type == athr_l2c)) { - otp_ctrl_data &= ~OTP_CTRL_CLK_EN; - AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); - msleep(1); - } - if (raise_vol) { - atl1c_read_phy_dbg(hw, MIIDBG_ANACTRL, &phy_data); - phy_data |= ANACTRL_HB_EN; - atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, phy_data); - atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); - phy_data &= ~VOLT_CTRL_SWLOWEST; - atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); - udelay(20); - } - - if (atl1c_read_current_addr(hw, hw->perm_mac_addr)) - return 0; - - return -1; -} - -bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value) -{ - int i; - bool ret = false; - u32 otp_ctrl_data; - u32 control; - u32 data; - - if (offset & 3) - return ret; /* address do not align */ - - AT_READ_REG(hw, REG_OTP_CTRL, &otp_ctrl_data); - if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) - AT_WRITE_REG(hw, REG_OTP_CTRL, - (otp_ctrl_data | OTP_CTRL_CLK_EN)); - - AT_WRITE_REG(hw, REG_EEPROM_DATA_LO, 0); - control = (offset & EEPROM_CTRL_ADDR_MASK) << EEPROM_CTRL_ADDR_SHIFT; - AT_WRITE_REG(hw, REG_EEPROM_CTRL, control); - - for (i = 0; i < 10; i++) { - udelay(100); - AT_READ_REG(hw, REG_EEPROM_CTRL, &control); - if (control & EEPROM_CTRL_RW) - break; - } - if (control & EEPROM_CTRL_RW) { - AT_READ_REG(hw, REG_EEPROM_CTRL, &data); - AT_READ_REG(hw, REG_EEPROM_DATA_LO, p_value); - data = data & 0xFFFF; - *p_value = swab32((data << 16) | (*p_value >> 16)); - ret = true; - } - if (!(otp_ctrl_data & OTP_CTRL_CLK_EN)) - AT_WRITE_REG(hw, REG_OTP_CTRL, otp_ctrl_data); - - return ret; -} -/* - * Reads the adapter's MAC address from the EEPROM - * - * hw - Struct containing variables accessed by shared code - */ -int atl1c_read_mac_addr(struct atl1c_hw *hw) -{ - int err = 0; - - err = atl1c_get_permanent_address(hw); - if (err) - eth_random_addr(hw->perm_mac_addr); - - memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr)); - return err; -} - -/* - * atl1c_hash_mc_addr - * purpose - * set hash value for a multicast address - * hash calcu processing : - * 1. calcu 32bit CRC for multicast address - * 2. reverse crc with MSB to LSB - */ -u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr) -{ - u32 crc32; - u32 value = 0; - int i; - - crc32 = ether_crc_le(6, mc_addr); - for (i = 0; i < 32; i++) - value |= (((crc32 >> i) & 1) << (31 - i)); - - return value; -} - -/* - * Sets the bit in the multicast table corresponding to the hash value. - * hw - Struct containing variables accessed by shared code - * hash_value - Multicast address hash value - */ -void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value) -{ - u32 hash_bit, hash_reg; - u32 mta; - - /* - * The HASH Table is a register array of 2 32-bit registers. - * It is treated like an array of 64 bits. We want to set - * bit BitArray[hash_value]. So we figure out what register - * the bit is in, read it, OR in the new bit, then write - * back the new value. The register is determined by the - * upper bit of the hash value and the bit within that - * register are determined by the lower 5 bits of the value. - */ - hash_reg = (hash_value >> 31) & 0x1; - hash_bit = (hash_value >> 26) & 0x1F; - - mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg); - - mta |= (1 << hash_bit); - - AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta); -} - -/* - * wait mdio module be idle - * return true: idle - * false: still busy - */ -bool atl1c_wait_mdio_idle(struct atl1c_hw *hw) -{ - u32 val; - int i; - - for (i = 0; i < MDIO_MAX_AC_TO; i++) { - AT_READ_REG(hw, REG_MDIO_CTRL, &val); - if (!(val & (MDIO_CTRL_BUSY | MDIO_CTRL_START))) - break; - udelay(10); - } - - return i != MDIO_MAX_AC_TO; -} - -void atl1c_stop_phy_polling(struct atl1c_hw *hw) -{ - if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) - return; - - AT_WRITE_REG(hw, REG_MDIO_CTRL, 0); - atl1c_wait_mdio_idle(hw); -} - -void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel) -{ - u32 val; - - if (!(hw->ctrl_flags & ATL1C_FPGA_VERSION)) - return; - - val = MDIO_CTRL_SPRES_PRMBL | - FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | - FIELDX(MDIO_CTRL_REG, 1) | - MDIO_CTRL_START | - MDIO_CTRL_OP_READ; - AT_WRITE_REG(hw, REG_MDIO_CTRL, val); - atl1c_wait_mdio_idle(hw); - val |= MDIO_CTRL_AP_EN; - val &= ~MDIO_CTRL_START; - AT_WRITE_REG(hw, REG_MDIO_CTRL, val); - udelay(30); -} - - -/* - * atl1c_read_phy_core - * core function to read register in PHY via MDIO control regsiter. - * ext: extension register (see IEEE 802.3) - * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0) - * reg: reg to read - */ -int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, - u16 reg, u16 *phy_data) -{ - u32 val; - u16 clk_sel = MDIO_CTRL_CLK_25_4; - - atl1c_stop_phy_polling(hw); - - *phy_data = 0; - - /* only l2c_b2 & l1d_2 could use slow clock */ - if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) && - hw->hibernate) - clk_sel = MDIO_CTRL_CLK_25_128; - if (ext) { - val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg); - AT_WRITE_REG(hw, REG_MDIO_EXTN, val); - val = MDIO_CTRL_SPRES_PRMBL | - FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | - MDIO_CTRL_START | - MDIO_CTRL_MODE_EXT | - MDIO_CTRL_OP_READ; - } else { - val = MDIO_CTRL_SPRES_PRMBL | - FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | - FIELDX(MDIO_CTRL_REG, reg) | - MDIO_CTRL_START | - MDIO_CTRL_OP_READ; - } - AT_WRITE_REG(hw, REG_MDIO_CTRL, val); - - if (!atl1c_wait_mdio_idle(hw)) - return -1; - - AT_READ_REG(hw, REG_MDIO_CTRL, &val); - *phy_data = (u16)FIELD_GETX(val, MDIO_CTRL_DATA); - - atl1c_start_phy_polling(hw, clk_sel); - - return 0; -} - -/* - * atl1c_write_phy_core - * core function to write to register in PHY via MDIO control register. - * ext: extension register (see IEEE 802.3) - * dev: device address (see IEEE 802.3 DEVAD, PRTAD is fixed to 0) - * reg: reg to write - */ -int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, - u16 reg, u16 phy_data) -{ - u32 val; - u16 clk_sel = MDIO_CTRL_CLK_25_4; - - atl1c_stop_phy_polling(hw); - - - /* only l2c_b2 & l1d_2 could use slow clock */ - if ((hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) && - hw->hibernate) - clk_sel = MDIO_CTRL_CLK_25_128; - - if (ext) { - val = FIELDX(MDIO_EXTN_DEVAD, dev) | FIELDX(MDIO_EXTN_REG, reg); - AT_WRITE_REG(hw, REG_MDIO_EXTN, val); - val = MDIO_CTRL_SPRES_PRMBL | - FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | - FIELDX(MDIO_CTRL_DATA, phy_data) | - MDIO_CTRL_START | - MDIO_CTRL_MODE_EXT; - } else { - val = MDIO_CTRL_SPRES_PRMBL | - FIELDX(MDIO_CTRL_CLK_SEL, clk_sel) | - FIELDX(MDIO_CTRL_DATA, phy_data) | - FIELDX(MDIO_CTRL_REG, reg) | - MDIO_CTRL_START; - } - AT_WRITE_REG(hw, REG_MDIO_CTRL, val); - - if (!atl1c_wait_mdio_idle(hw)) - return -1; - - atl1c_start_phy_polling(hw, clk_sel); - - return 0; -} - -/* - * Reads the value from a PHY register - * hw - Struct containing variables accessed by shared code - * reg_addr - address of the PHY register to read - */ -int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) -{ - return atl1c_read_phy_core(hw, false, 0, reg_addr, phy_data); -} - -/* - * Writes a value to a PHY register - * hw - Struct containing variables accessed by shared code - * reg_addr - address of the PHY register to write - * data - data to write to the PHY - */ -int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data) -{ - return atl1c_write_phy_core(hw, false, 0, reg_addr, phy_data); -} - -/* read from PHY extension register */ -int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr, - u16 reg_addr, u16 *phy_data) -{ - return atl1c_read_phy_core(hw, true, dev_addr, reg_addr, phy_data); -} - -/* write to PHY extension register */ -int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr, - u16 reg_addr, u16 phy_data) -{ - return atl1c_write_phy_core(hw, true, dev_addr, reg_addr, phy_data); -} - -int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data) -{ - int err; - - err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr); - if (unlikely(err)) - return err; - else - err = atl1c_read_phy_reg(hw, MII_DBG_DATA, phy_data); - - return err; -} - -int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data) -{ - int err; - - err = atl1c_write_phy_reg(hw, MII_DBG_ADDR, reg_addr); - if (unlikely(err)) - return err; - else - err = atl1c_write_phy_reg(hw, MII_DBG_DATA, phy_data); - - return err; -} - -/* - * Configures PHY autoneg and flow control advertisement settings - * - * hw - Struct containing variables accessed by shared code - */ -static int atl1c_phy_setup_adv(struct atl1c_hw *hw) -{ - u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_ALL; - u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP & - ~GIGA_CR_1000T_SPEED_MASK; - - if (hw->autoneg_advertised & ADVERTISED_10baseT_Half) - mii_adv_data |= ADVERTISE_10HALF; - if (hw->autoneg_advertised & ADVERTISED_10baseT_Full) - mii_adv_data |= ADVERTISE_10FULL; - if (hw->autoneg_advertised & ADVERTISED_100baseT_Half) - mii_adv_data |= ADVERTISE_100HALF; - if (hw->autoneg_advertised & ADVERTISED_100baseT_Full) - mii_adv_data |= ADVERTISE_100FULL; - - if (hw->autoneg_advertised & ADVERTISED_Autoneg) - mii_adv_data |= ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL; - - if (hw->link_cap_flags & ATL1C_LINK_CAP_1000M) { - if (hw->autoneg_advertised & ADVERTISED_1000baseT_Half) - mii_giga_ctrl_data |= ADVERTISE_1000HALF; - if (hw->autoneg_advertised & ADVERTISED_1000baseT_Full) - mii_giga_ctrl_data |= ADVERTISE_1000FULL; - if (hw->autoneg_advertised & ADVERTISED_Autoneg) - mii_giga_ctrl_data |= ADVERTISE_1000HALF | - ADVERTISE_1000FULL; - } - - if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 || - atl1c_write_phy_reg(hw, MII_CTRL1000, mii_giga_ctrl_data) != 0) - return -1; - return 0; -} - -void atl1c_phy_disable(struct atl1c_hw *hw) -{ - atl1c_power_saving(hw, 0); -} - - -int atl1c_phy_reset(struct atl1c_hw *hw) -{ - struct atl1c_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; - u16 phy_data; - u32 phy_ctrl_data, lpi_ctrl; - int err; - - /* reset PHY core */ - AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl_data); - phy_ctrl_data &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_PHY_IDDQ | - GPHY_CTRL_GATE_25M_EN | GPHY_CTRL_PWDOWN_HW | GPHY_CTRL_CLS); - phy_ctrl_data |= GPHY_CTRL_SEL_ANA_RST; - if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) - phy_ctrl_data |= (GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE); - else - phy_ctrl_data &= ~(GPHY_CTRL_HIB_EN | GPHY_CTRL_HIB_PULSE); - AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data); - AT_WRITE_FLUSH(hw); - udelay(10); - AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl_data | GPHY_CTRL_EXT_RESET); - AT_WRITE_FLUSH(hw); - udelay(10 * GPHY_CTRL_EXT_RST_TO); /* delay 800us */ - - /* switch clock */ - if (hw->nic_type == athr_l2c_b) { - atl1c_read_phy_dbg(hw, MIIDBG_CFGLPSPD, &phy_data); - atl1c_write_phy_dbg(hw, MIIDBG_CFGLPSPD, - phy_data & ~CFGLPSPD_RSTCNT_CLK125SW); - } - - /* tx-half amplitude issue fix */ - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { - atl1c_read_phy_dbg(hw, MIIDBG_CABLE1TH_DET, &phy_data); - phy_data |= CABLE1TH_DET_EN; - atl1c_write_phy_dbg(hw, MIIDBG_CABLE1TH_DET, phy_data); - } - - /* clear bit3 of dbgport 3B to lower voltage */ - if (!(hw->ctrl_flags & ATL1C_HIB_DISABLE)) { - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2) { - atl1c_read_phy_dbg(hw, MIIDBG_VOLT_CTRL, &phy_data); - phy_data &= ~VOLT_CTRL_SWLOWEST; - atl1c_write_phy_dbg(hw, MIIDBG_VOLT_CTRL, phy_data); - } - /* power saving config */ - phy_data = - hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 ? - L1D_LEGCYPS_DEF : L1C_LEGCYPS_DEF; - atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, phy_data); - /* hib */ - atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, - SYSMODCTRL_IECHOADJ_DEF); - } else { - /* disable pws */ - atl1c_read_phy_dbg(hw, MIIDBG_LEGCYPS, &phy_data); - atl1c_write_phy_dbg(hw, MIIDBG_LEGCYPS, - phy_data & ~LEGCYPS_EN); - /* disable hibernate */ - atl1c_read_phy_dbg(hw, MIIDBG_HIBNEG, &phy_data); - atl1c_write_phy_dbg(hw, MIIDBG_HIBNEG, - phy_data & HIBNEG_PSHIB_EN); - } - /* disable AZ(EEE) by default */ - if (hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2 || - hw->nic_type == athr_l2c_b2) { - AT_READ_REG(hw, REG_LPI_CTRL, &lpi_ctrl); - AT_WRITE_REG(hw, REG_LPI_CTRL, lpi_ctrl & ~LPI_CTRL_EN); - atl1c_write_phy_ext(hw, MIIEXT_ANEG, MIIEXT_LOCAL_EEEADV, 0); - atl1c_write_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL3, - L2CB_CLDCTRL3); - } - - /* other debug port to set */ - atl1c_write_phy_dbg(hw, MIIDBG_ANACTRL, ANACTRL_DEF); - atl1c_write_phy_dbg(hw, MIIDBG_SRDSYSMOD, SRDSYSMOD_DEF); - atl1c_write_phy_dbg(hw, MIIDBG_TST10BTCFG, TST10BTCFG_DEF); - /* UNH-IOL test issue, set bit7 */ - atl1c_write_phy_dbg(hw, MIIDBG_TST100BTCFG, - TST100BTCFG_DEF | TST100BTCFG_LITCH_EN); - - /* set phy interrupt mask */ - phy_data = IER_LINK_UP | IER_LINK_DOWN; - err = atl1c_write_phy_reg(hw, MII_IER, phy_data); - if (err) { - if (netif_msg_hw(adapter)) - dev_err(&pdev->dev, - "Error enable PHY linkChange Interrupt\n"); - return err; - } - return 0; -} - -int atl1c_phy_init(struct atl1c_hw *hw) -{ - struct atl1c_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; - int ret_val; - u16 mii_bmcr_data = BMCR_RESET; - - if ((atl1c_read_phy_reg(hw, MII_PHYSID1, &hw->phy_id1) != 0) || - (atl1c_read_phy_reg(hw, MII_PHYSID2, &hw->phy_id2) != 0)) { - dev_err(&pdev->dev, "Error get phy ID\n"); - return -1; - } - switch (hw->media_type) { - case MEDIA_TYPE_AUTO_SENSOR: - ret_val = atl1c_phy_setup_adv(hw); - if (ret_val) { - if (netif_msg_link(adapter)) - dev_err(&pdev->dev, - "Error Setting up Auto-Negotiation\n"); - return ret_val; - } - mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART; - break; - case MEDIA_TYPE_100M_FULL: - mii_bmcr_data |= BMCR_SPEED100 | BMCR_FULLDPLX; - break; - case MEDIA_TYPE_100M_HALF: - mii_bmcr_data |= BMCR_SPEED100; - break; - case MEDIA_TYPE_10M_FULL: - mii_bmcr_data |= BMCR_FULLDPLX; - break; - case MEDIA_TYPE_10M_HALF: - break; - default: - if (netif_msg_link(adapter)) - dev_err(&pdev->dev, "Wrong Media type %d\n", - hw->media_type); - return -1; - } - - ret_val = atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data); - if (ret_val) - return ret_val; - hw->phy_configured = true; - - return 0; -} - -/* - * Detects the current speed and duplex settings of the hardware. - * - * hw - Struct containing variables accessed by shared code - * speed - Speed of the connection - * duplex - Duplex setting of the connection - */ -int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex) -{ - int err; - u16 phy_data; - - /* Read PHY Specific Status Register (17) */ - err = atl1c_read_phy_reg(hw, MII_GIGA_PSSR, &phy_data); - if (err) - return err; - - if (!(phy_data & GIGA_PSSR_SPD_DPLX_RESOLVED)) - return -1; - - switch (phy_data & GIGA_PSSR_SPEED) { - case GIGA_PSSR_1000MBS: - *speed = SPEED_1000; - break; - case GIGA_PSSR_100MBS: - *speed = SPEED_100; - break; - case GIGA_PSSR_10MBS: - *speed = SPEED_10; - break; - default: - return -1; - } - - if (phy_data & GIGA_PSSR_DPLX) - *duplex = FULL_DUPLEX; - else - *duplex = HALF_DUPLEX; - - return 0; -} - -/* select one link mode to get lower power consumption */ -int atl1c_phy_to_ps_link(struct atl1c_hw *hw) -{ - struct atl1c_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; - int ret = 0; - u16 autoneg_advertised = ADVERTISED_10baseT_Half; - u16 save_autoneg_advertised; - u16 phy_data; - u16 mii_lpa_data; - u16 speed = SPEED_0; - u16 duplex = FULL_DUPLEX; - int i; - - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - if (phy_data & BMSR_LSTATUS) { - atl1c_read_phy_reg(hw, MII_LPA, &mii_lpa_data); - if (mii_lpa_data & LPA_10FULL) - autoneg_advertised = ADVERTISED_10baseT_Full; - else if (mii_lpa_data & LPA_10HALF) - autoneg_advertised = ADVERTISED_10baseT_Half; - else if (mii_lpa_data & LPA_100HALF) - autoneg_advertised = ADVERTISED_100baseT_Half; - else if (mii_lpa_data & LPA_100FULL) - autoneg_advertised = ADVERTISED_100baseT_Full; - - save_autoneg_advertised = hw->autoneg_advertised; - hw->phy_configured = false; - hw->autoneg_advertised = autoneg_advertised; - if (atl1c_restart_autoneg(hw) != 0) { - dev_dbg(&pdev->dev, "phy autoneg failed\n"); - ret = -1; - } - hw->autoneg_advertised = save_autoneg_advertised; - - if (mii_lpa_data) { - for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) { - mdelay(100); - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - if (phy_data & BMSR_LSTATUS) { - if (atl1c_get_speed_and_duplex(hw, &speed, - &duplex) != 0) - dev_dbg(&pdev->dev, - "get speed and duplex failed\n"); - break; - } - } - } - } else { - speed = SPEED_10; - duplex = HALF_DUPLEX; - } - adapter->link_speed = speed; - adapter->link_duplex = duplex; - - return ret; -} - -int atl1c_restart_autoneg(struct atl1c_hw *hw) -{ - int err = 0; - u16 mii_bmcr_data = BMCR_RESET; - - err = atl1c_phy_setup_adv(hw); - if (err) - return err; - mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART; - - return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data); -} - -int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc) -{ - struct atl1c_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; - u32 master_ctrl, mac_ctrl, phy_ctrl; - u32 wol_ctrl, speed; - u16 phy_data; - - wol_ctrl = 0; - speed = adapter->link_speed == SPEED_1000 ? - MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100; - - AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl); - AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl); - AT_READ_REG(hw, REG_GPHY_CTRL, &phy_ctrl); - - master_ctrl &= ~MASTER_CTRL_CLK_SEL_DIS; - mac_ctrl = FIELD_SETX(mac_ctrl, MAC_CTRL_SPEED, speed); - mac_ctrl &= ~(MAC_CTRL_DUPLX | MAC_CTRL_RX_EN | MAC_CTRL_TX_EN); - if (adapter->link_duplex == FULL_DUPLEX) - mac_ctrl |= MAC_CTRL_DUPLX; - phy_ctrl &= ~(GPHY_CTRL_EXT_RESET | GPHY_CTRL_CLS); - phy_ctrl |= GPHY_CTRL_SEL_ANA_RST | GPHY_CTRL_HIB_PULSE | - GPHY_CTRL_HIB_EN; - if (!wufc) { /* without WoL */ - master_ctrl |= MASTER_CTRL_CLK_SEL_DIS; - phy_ctrl |= GPHY_CTRL_PHY_IDDQ | GPHY_CTRL_PWDOWN_HW; - AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl); - AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl); - AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl); - AT_WRITE_REG(hw, REG_WOL_CTRL, 0); - hw->phy_configured = false; /* re-init PHY when resume */ - return 0; - } - phy_ctrl |= GPHY_CTRL_EXT_RESET; - if (wufc & AT_WUFC_MAG) { - mac_ctrl |= MAC_CTRL_RX_EN | MAC_CTRL_BC_EN; - wol_ctrl |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN; - if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V11) - wol_ctrl |= WOL_PATTERN_EN | WOL_PATTERN_PME_EN; - } - if (wufc & AT_WUFC_LNKC) { - wol_ctrl |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; - if (atl1c_write_phy_reg(hw, MII_IER, IER_LINK_UP) != 0) { - dev_dbg(&pdev->dev, "%s: write phy MII_IER failed.\n", - atl1c_driver_name); - } - } - /* clear PHY interrupt */ - atl1c_read_phy_reg(hw, MII_ISR, &phy_data); - - dev_dbg(&pdev->dev, "%s: suspend MAC=%x,MASTER=%x,PHY=0x%x,WOL=%x\n", - atl1c_driver_name, mac_ctrl, master_ctrl, phy_ctrl, wol_ctrl); - AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl); - AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl); - AT_WRITE_REG(hw, REG_GPHY_CTRL, phy_ctrl); - AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl); - - return 0; -} - - -/* configure phy after Link change Event */ -void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed) -{ - u16 phy_val; - bool adj_thresh = false; - - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 || - hw->nic_type == athr_l1d || hw->nic_type == athr_l1d_2) - adj_thresh = true; - - if (link_speed != SPEED_0) { /* link up */ - /* az with brcm, half-amp */ - if (hw->nic_type == athr_l1d_2) { - atl1c_read_phy_ext(hw, MIIEXT_PCS, MIIEXT_CLDCTRL6, - &phy_val); - phy_val = FIELD_GETX(phy_val, CLDCTRL6_CAB_LEN); - phy_val = phy_val > CLDCTRL6_CAB_LEN_SHORT ? - AZ_ANADECT_LONG : AZ_ANADECT_DEF; - atl1c_write_phy_dbg(hw, MIIDBG_AZ_ANADECT, phy_val); - } - /* threshold adjust */ - if (adj_thresh && link_speed == SPEED_100 && hw->msi_lnkpatch) { - atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, L1D_MSE16DB_UP); - atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, - L1D_SYSMODCTRL_IECHOADJ_DEF); - } - } else { /* link down */ - if (adj_thresh && hw->msi_lnkpatch) { - atl1c_write_phy_dbg(hw, MIIDBG_SYSMODCTRL, - SYSMODCTRL_IECHOADJ_DEF); - atl1c_write_phy_dbg(hw, MIIDBG_MSE16DB, - L1D_MSE16DB_DOWN); - } - } -} diff --git a/addons/atl1c/src/4.4.180/atl1c_hw.h b/addons/atl1c/src/4.4.180/atl1c_hw.h deleted file mode 100644 index 21d8c4db..00000000 --- a/addons/atl1c/src/4.4.180/atl1c_hw.h +++ /dev/null @@ -1,1024 +0,0 @@ -/* - * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _ATL1C_HW_H_ -#define _ATL1C_HW_H_ - -#include -#include - -#define FIELD_GETX(_x, _name) ((_x) >> (_name##_SHIFT) & (_name##_MASK)) -#define FIELD_SETX(_x, _name, _v) \ -(((_x) & ~((_name##_MASK) << (_name##_SHIFT))) |\ -(((_v) & (_name##_MASK)) << (_name##_SHIFT))) -#define FIELDX(_name, _v) (((_v) & (_name##_MASK)) << (_name##_SHIFT)) - -struct atl1c_adapter; -struct atl1c_hw; - -/* function prototype */ -void atl1c_phy_disable(struct atl1c_hw *hw); -void atl1c_hw_set_mac_addr(struct atl1c_hw *hw, u8 *mac_addr); -int atl1c_phy_reset(struct atl1c_hw *hw); -int atl1c_read_mac_addr(struct atl1c_hw *hw); -int atl1c_get_speed_and_duplex(struct atl1c_hw *hw, u16 *speed, u16 *duplex); -u32 atl1c_hash_mc_addr(struct atl1c_hw *hw, u8 *mc_addr); -void atl1c_hash_set(struct atl1c_hw *hw, u32 hash_value); -int atl1c_read_phy_reg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data); -int atl1c_write_phy_reg(struct atl1c_hw *hw, u32 reg_addr, u16 phy_data); -bool atl1c_read_eeprom(struct atl1c_hw *hw, u32 offset, u32 *p_value); -int atl1c_phy_init(struct atl1c_hw *hw); -int atl1c_check_eeprom_exist(struct atl1c_hw *hw); -int atl1c_restart_autoneg(struct atl1c_hw *hw); -int atl1c_phy_to_ps_link(struct atl1c_hw *hw); -int atl1c_power_saving(struct atl1c_hw *hw, u32 wufc); -bool atl1c_wait_mdio_idle(struct atl1c_hw *hw); -void atl1c_stop_phy_polling(struct atl1c_hw *hw); -void atl1c_start_phy_polling(struct atl1c_hw *hw, u16 clk_sel); -int atl1c_read_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, - u16 reg, u16 *phy_data); -int atl1c_write_phy_core(struct atl1c_hw *hw, bool ext, u8 dev, - u16 reg, u16 phy_data); -int atl1c_read_phy_ext(struct atl1c_hw *hw, u8 dev_addr, - u16 reg_addr, u16 *phy_data); -int atl1c_write_phy_ext(struct atl1c_hw *hw, u8 dev_addr, - u16 reg_addr, u16 phy_data); -int atl1c_read_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 *phy_data); -int atl1c_write_phy_dbg(struct atl1c_hw *hw, u16 reg_addr, u16 phy_data); -void atl1c_post_phy_linkchg(struct atl1c_hw *hw, u16 link_speed); - -/* hw-ids */ -#define PCI_DEVICE_ID_ATTANSIC_L2C 0x1062 -#define PCI_DEVICE_ID_ATTANSIC_L1C 0x1063 -#define PCI_DEVICE_ID_ATHEROS_L2C_B 0x2060 /* AR8152 v1.1 Fast 10/100 */ -#define PCI_DEVICE_ID_ATHEROS_L2C_B2 0x2062 /* AR8152 v2.0 Fast 10/100 */ -#define PCI_DEVICE_ID_ATHEROS_L1D 0x1073 /* AR8151 v1.0 Gigabit 1000 */ -#define PCI_DEVICE_ID_ATHEROS_L1D_2_0 0x1083 /* AR8151 v2.0 Gigabit 1000 */ -#define L2CB_V10 0xc0 -#define L2CB_V11 0xc1 -#define L2CB_V20 0xc0 -#define L2CB_V21 0xc1 - -/* register definition */ -#define REG_DEVICE_CAP 0x5C -#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7 -#define DEVICE_CAP_MAX_PAYLOAD_SHIFT 0 - -#define DEVICE_CTRL_MAXRRS_MIN 2 - -#define REG_LINK_CTRL 0x68 -#define LINK_CTRL_L0S_EN 0x01 -#define LINK_CTRL_L1_EN 0x02 -#define LINK_CTRL_EXT_SYNC 0x80 - -#define REG_PCIE_IND_ACC_ADDR 0x80 -#define REG_PCIE_IND_ACC_DATA 0x84 - -#define REG_DEV_SERIALNUM_CTRL 0x200 -#define REG_DEV_MAC_SEL_MASK 0x0 /* 0:EUI; 1:MAC */ -#define REG_DEV_MAC_SEL_SHIFT 0 -#define REG_DEV_SERIAL_NUM_EN_MASK 0x1 -#define REG_DEV_SERIAL_NUM_EN_SHIFT 1 - -#define REG_TWSI_CTRL 0x218 -#define TWSI_CTLR_FREQ_MASK 0x3UL -#define TWSI_CTRL_FREQ_SHIFT 24 -#define TWSI_CTRL_FREQ_100K 0 -#define TWSI_CTRL_FREQ_200K 1 -#define TWSI_CTRL_FREQ_300K 2 -#define TWSI_CTRL_FREQ_400K 3 -#define TWSI_CTRL_LD_EXIST BIT(23) -#define TWSI_CTRL_HW_LDSTAT BIT(12) /* 0:finish,1:in progress */ -#define TWSI_CTRL_SW_LDSTART BIT(11) -#define TWSI_CTRL_LD_OFFSET_MASK 0xFF -#define TWSI_CTRL_LD_OFFSET_SHIFT 0 - -#define REG_PCIE_DEV_MISC_CTRL 0x21C -#define PCIE_DEV_MISC_EXT_PIPE 0x2 -#define PCIE_DEV_MISC_RETRY_BUFDIS 0x1 -#define PCIE_DEV_MISC_SPIROM_EXIST 0x4 -#define PCIE_DEV_MISC_SERDES_ENDIAN 0x8 -#define PCIE_DEV_MISC_SERDES_SEL_DIN 0x10 - -#define REG_PCIE_PHYMISC 0x1000 -#define PCIE_PHYMISC_FORCE_RCV_DET BIT(2) -#define PCIE_PHYMISC_NFTS_MASK 0xFFUL -#define PCIE_PHYMISC_NFTS_SHIFT 16 - -#define REG_PCIE_PHYMISC2 0x1004 -#define PCIE_PHYMISC2_L0S_TH_MASK 0x3UL -#define PCIE_PHYMISC2_L0S_TH_SHIFT 18 -#define L2CB1_PCIE_PHYMISC2_L0S_TH 3 -#define PCIE_PHYMISC2_CDR_BW_MASK 0x3UL -#define PCIE_PHYMISC2_CDR_BW_SHIFT 16 -#define L2CB1_PCIE_PHYMISC2_CDR_BW 3 - -#define REG_TWSI_DEBUG 0x1108 -#define TWSI_DEBUG_DEV_EXIST BIT(29) - -#define REG_DMA_DBG 0x1114 -#define DMA_DBG_VENDOR_MSG BIT(0) - -#define REG_EEPROM_CTRL 0x12C0 -#define EEPROM_CTRL_DATA_HI_MASK 0xFFFF -#define EEPROM_CTRL_DATA_HI_SHIFT 0 -#define EEPROM_CTRL_ADDR_MASK 0x3FF -#define EEPROM_CTRL_ADDR_SHIFT 16 -#define EEPROM_CTRL_ACK 0x40000000 -#define EEPROM_CTRL_RW 0x80000000 - -#define REG_EEPROM_DATA_LO 0x12C4 - -#define REG_OTP_CTRL 0x12F0 -#define OTP_CTRL_CLK_EN BIT(1) - -#define REG_PM_CTRL 0x12F8 -#define PM_CTRL_HOTRST BIT(31) -#define PM_CTRL_MAC_ASPM_CHK BIT(30) /* L0s/L1 dis by MAC based on - * thrghput(setting in 15A0) */ -#define PM_CTRL_SA_DLY_EN BIT(29) -#define PM_CTRL_L0S_BUFSRX_EN BIT(28) -#define PM_CTRL_LCKDET_TIMER_MASK 0xFUL -#define PM_CTRL_LCKDET_TIMER_SHIFT 24 -#define PM_CTRL_LCKDET_TIMER_DEF 0xC -#define PM_CTRL_PM_REQ_TIMER_MASK 0xFUL -#define PM_CTRL_PM_REQ_TIMER_SHIFT 20 /* pm_request_l1 time > @ - * ->L0s not L1 */ -#define PM_CTRL_PM_REQ_TO_DEF 0xF -#define PMCTRL_TXL1_AFTER_L0S BIT(19) /* l1dv2.0+ */ -#define L1D_PMCTRL_L1_ENTRY_TM_MASK 7UL /* l1dv2.0+, 3bits */ -#define L1D_PMCTRL_L1_ENTRY_TM_SHIFT 16 -#define L1D_PMCTRL_L1_ENTRY_TM_DIS 0 -#define L1D_PMCTRL_L1_ENTRY_TM_2US 1 -#define L1D_PMCTRL_L1_ENTRY_TM_4US 2 -#define L1D_PMCTRL_L1_ENTRY_TM_8US 3 -#define L1D_PMCTRL_L1_ENTRY_TM_16US 4 -#define L1D_PMCTRL_L1_ENTRY_TM_24US 5 -#define L1D_PMCTRL_L1_ENTRY_TM_32US 6 -#define L1D_PMCTRL_L1_ENTRY_TM_63US 7 -#define PM_CTRL_L1_ENTRY_TIMER_MASK 0xFUL /* l1C 4bits */ -#define PM_CTRL_L1_ENTRY_TIMER_SHIFT 16 -#define L2CB1_PM_CTRL_L1_ENTRY_TM 7 -#define L1C_PM_CTRL_L1_ENTRY_TM 0xF -#define PM_CTRL_RCVR_WT_TIMER BIT(15) /* 1:1us, 0:2ms */ -#define PM_CTRL_CLK_PWM_VER1_1 BIT(14) /* 0:1.0a,1:1.1 */ -#define PM_CTRL_CLK_SWH_L1 BIT(13) /* en pcie clk sw in L1 */ -#define PM_CTRL_ASPM_L0S_EN BIT(12) -#define PM_CTRL_RXL1_AFTER_L0S BIT(11) /* l1dv2.0+ */ -#define L1D_PMCTRL_L0S_TIMER_MASK 7UL /* l1d2.0+, 3bits*/ -#define L1D_PMCTRL_L0S_TIMER_SHIFT 8 -#define PM_CTRL_L0S_ENTRY_TIMER_MASK 0xFUL /* l1c, 4bits */ -#define PM_CTRL_L0S_ENTRY_TIMER_SHIFT 8 -#define PM_CTRL_SERDES_BUFS_RX_L1_EN BIT(7) -#define PM_CTRL_SERDES_PD_EX_L1 BIT(6) /* power down serdes rx */ -#define PM_CTRL_SERDES_PLL_L1_EN BIT(5) -#define PM_CTRL_SERDES_L1_EN BIT(4) -#define PM_CTRL_ASPM_L1_EN BIT(3) -#define PM_CTRL_CLK_REQ_EN BIT(2) -#define PM_CTRL_RBER_EN BIT(1) -#define PM_CTRL_SPRSDWER_EN BIT(0) - -#define REG_LTSSM_ID_CTRL 0x12FC -#define LTSSM_ID_EN_WRO 0x1000 - - -/* Selene Master Control Register */ -#define REG_MASTER_CTRL 0x1400 -#define MASTER_CTRL_OTP_SEL BIT(31) -#define MASTER_DEV_NUM_MASK 0x7FUL -#define MASTER_DEV_NUM_SHIFT 24 -#define MASTER_REV_NUM_MASK 0xFFUL -#define MASTER_REV_NUM_SHIFT 16 -#define MASTER_CTRL_INT_RDCLR BIT(14) -#define MASTER_CTRL_CLK_SEL_DIS BIT(12) /* 1:alwys sel pclk from - * serdes, not sw to 25M */ -#define MASTER_CTRL_RX_ITIMER_EN BIT(11) /* IRQ MODURATION FOR RX */ -#define MASTER_CTRL_TX_ITIMER_EN BIT(10) /* MODURATION FOR TX/RX */ -#define MASTER_CTRL_MANU_INT BIT(9) /* SOFT MANUAL INT */ -#define MASTER_CTRL_MANUTIMER_EN BIT(8) -#define MASTER_CTRL_SA_TIMER_EN BIT(7) /* SYS ALIVE TIMER EN */ -#define MASTER_CTRL_OOB_DIS BIT(6) /* OUT OF BOX DIS */ -#define MASTER_CTRL_WAKEN_25M BIT(5) /* WAKE WO. PCIE CLK */ -#define MASTER_CTRL_BERT_START BIT(4) -#define MASTER_PCIE_TSTMOD_MASK 3UL -#define MASTER_PCIE_TSTMOD_SHIFT 2 -#define MASTER_PCIE_RST BIT(1) -#define MASTER_CTRL_SOFT_RST BIT(0) /* RST MAC & DMA */ -#define DMA_MAC_RST_TO 50 - -/* Timer Initial Value Register */ -#define REG_MANUAL_TIMER_INIT 0x1404 - -/* IRQ ModeratorTimer Initial Value Register */ -#define REG_IRQ_MODRT_TIMER_INIT 0x1408 -#define IRQ_MODRT_TIMER_MASK 0xffff -#define IRQ_MODRT_TX_TIMER_SHIFT 0 -#define IRQ_MODRT_RX_TIMER_SHIFT 16 - -#define REG_GPHY_CTRL 0x140C -#define GPHY_CTRL_ADDR_MASK 0x1FUL -#define GPHY_CTRL_ADDR_SHIFT 19 -#define GPHY_CTRL_BP_VLTGSW BIT(18) -#define GPHY_CTRL_100AB_EN BIT(17) -#define GPHY_CTRL_10AB_EN BIT(16) -#define GPHY_CTRL_PHY_PLL_BYPASS BIT(15) -#define GPHY_CTRL_PWDOWN_HW BIT(14) /* affect MAC&PHY, to low pw */ -#define GPHY_CTRL_PHY_PLL_ON BIT(13) /* 1:pll always on, 0:can sw */ -#define GPHY_CTRL_SEL_ANA_RST BIT(12) -#define GPHY_CTRL_HIB_PULSE BIT(11) -#define GPHY_CTRL_HIB_EN BIT(10) -#define GPHY_CTRL_GIGA_DIS BIT(9) -#define GPHY_CTRL_PHY_IDDQ_DIS BIT(8) /* pw on RST */ -#define GPHY_CTRL_PHY_IDDQ BIT(7) /* bit8 affect bit7 while rb */ -#define GPHY_CTRL_LPW_EXIT BIT(6) -#define GPHY_CTRL_GATE_25M_EN BIT(5) -#define GPHY_CTRL_REV_ANEG BIT(4) -#define GPHY_CTRL_ANEG_NOW BIT(3) -#define GPHY_CTRL_LED_MODE BIT(2) -#define GPHY_CTRL_RTL_MODE BIT(1) -#define GPHY_CTRL_EXT_RESET BIT(0) /* 1:out of DSP RST status */ -#define GPHY_CTRL_EXT_RST_TO 80 /* 800us atmost */ -#define GPHY_CTRL_CLS (\ - GPHY_CTRL_LED_MODE |\ - GPHY_CTRL_100AB_EN |\ - GPHY_CTRL_PHY_PLL_ON) - -/* Block IDLE Status Register */ -#define REG_IDLE_STATUS 0x1410 -#define IDLE_STATUS_SFORCE_MASK 0xFUL -#define IDLE_STATUS_SFORCE_SHIFT 14 -#define IDLE_STATUS_CALIB_DONE BIT(13) -#define IDLE_STATUS_CALIB_RES_MASK 0x1FUL -#define IDLE_STATUS_CALIB_RES_SHIFT 8 -#define IDLE_STATUS_CALIBERR_MASK 0xFUL -#define IDLE_STATUS_CALIBERR_SHIFT 4 -#define IDLE_STATUS_TXQ_BUSY BIT(3) -#define IDLE_STATUS_RXQ_BUSY BIT(2) -#define IDLE_STATUS_TXMAC_BUSY BIT(1) -#define IDLE_STATUS_RXMAC_BUSY BIT(0) -#define IDLE_STATUS_MASK (\ - IDLE_STATUS_TXQ_BUSY |\ - IDLE_STATUS_RXQ_BUSY |\ - IDLE_STATUS_TXMAC_BUSY |\ - IDLE_STATUS_RXMAC_BUSY) - -/* MDIO Control Register */ -#define REG_MDIO_CTRL 0x1414 -#define MDIO_CTRL_MODE_EXT BIT(30) -#define MDIO_CTRL_POST_READ BIT(29) -#define MDIO_CTRL_AP_EN BIT(28) -#define MDIO_CTRL_BUSY BIT(27) -#define MDIO_CTRL_CLK_SEL_MASK 0x7UL -#define MDIO_CTRL_CLK_SEL_SHIFT 24 -#define MDIO_CTRL_CLK_25_4 0 /* 25MHz divide 4 */ -#define MDIO_CTRL_CLK_25_6 2 -#define MDIO_CTRL_CLK_25_8 3 -#define MDIO_CTRL_CLK_25_10 4 -#define MDIO_CTRL_CLK_25_32 5 -#define MDIO_CTRL_CLK_25_64 6 -#define MDIO_CTRL_CLK_25_128 7 -#define MDIO_CTRL_START BIT(23) -#define MDIO_CTRL_SPRES_PRMBL BIT(22) -#define MDIO_CTRL_OP_READ BIT(21) /* 1:read, 0:write */ -#define MDIO_CTRL_REG_MASK 0x1FUL -#define MDIO_CTRL_REG_SHIFT 16 -#define MDIO_CTRL_DATA_MASK 0xFFFFUL -#define MDIO_CTRL_DATA_SHIFT 0 -#define MDIO_MAX_AC_TO 120 /* 1.2ms timeout for slow clk */ - -/* for extension reg access */ -#define REG_MDIO_EXTN 0x1448 -#define MDIO_EXTN_PORTAD_MASK 0x1FUL -#define MDIO_EXTN_PORTAD_SHIFT 21 -#define MDIO_EXTN_DEVAD_MASK 0x1FUL -#define MDIO_EXTN_DEVAD_SHIFT 16 -#define MDIO_EXTN_REG_MASK 0xFFFFUL -#define MDIO_EXTN_REG_SHIFT 0 - -/* BIST Control and Status Register0 (for the Packet Memory) */ -#define REG_BIST0_CTRL 0x141c -#define BIST0_NOW 0x1 -#define BIST0_SRAM_FAIL 0x2 /* 1: The SRAM failure is - * un-repairable because - * it has address decoder - * failure or more than 1 cell - * stuck-to-x failure */ -#define BIST0_FUSE_FLAG 0x4 - -/* BIST Control and Status Register1(for the retry buffer of PCI Express) */ -#define REG_BIST1_CTRL 0x1420 -#define BIST1_NOW 0x1 -#define BIST1_SRAM_FAIL 0x2 -#define BIST1_FUSE_FLAG 0x4 - -/* SerDes Lock Detect Control and Status Register */ -#define REG_SERDES 0x1424 -#define SERDES_PHY_CLK_SLOWDOWN BIT(18) -#define SERDES_MAC_CLK_SLOWDOWN BIT(17) -#define SERDES_SELFB_PLL_MASK 0x3UL -#define SERDES_SELFB_PLL_SHIFT 14 -#define SERDES_PHYCLK_SEL_GTX BIT(13) /* 1:gtx_clk, 0:25M */ -#define SERDES_PCIECLK_SEL_SRDS BIT(12) /* 1:serdes,0:25M */ -#define SERDES_BUFS_RX_EN BIT(11) -#define SERDES_PD_RX BIT(10) -#define SERDES_PLL_EN BIT(9) -#define SERDES_EN BIT(8) -#define SERDES_SELFB_PLL_SEL_CSR BIT(6) /* 0:state-machine,1:csr */ -#define SERDES_SELFB_PLL_CSR_MASK 0x3UL -#define SERDES_SELFB_PLL_CSR_SHIFT 4 -#define SERDES_SELFB_PLL_CSR_4 3 /* 4-12% OV-CLK */ -#define SERDES_SELFB_PLL_CSR_0 2 /* 0-4% OV-CLK */ -#define SERDES_SELFB_PLL_CSR_12 1 /* 12-18% OV-CLK */ -#define SERDES_SELFB_PLL_CSR_18 0 /* 18-25% OV-CLK */ -#define SERDES_VCO_SLOW BIT(3) -#define SERDES_VCO_FAST BIT(2) -#define SERDES_LOCK_DETECT_EN BIT(1) -#define SERDES_LOCK_DETECT BIT(0) - -#define REG_LPI_DECISN_TIMER 0x143C -#define L2CB_LPI_DESISN_TIMER 0x7D00 - -#define REG_LPI_CTRL 0x1440 -#define LPI_CTRL_CHK_DA BIT(31) -#define LPI_CTRL_ENH_TO_MASK 0x1FFFUL -#define LPI_CTRL_ENH_TO_SHIFT 12 -#define LPI_CTRL_ENH_TH_MASK 0x1FUL -#define LPI_CTRL_ENH_TH_SHIFT 6 -#define LPI_CTRL_ENH_EN BIT(5) -#define LPI_CTRL_CHK_RX BIT(4) -#define LPI_CTRL_CHK_STATE BIT(3) -#define LPI_CTRL_GMII BIT(2) -#define LPI_CTRL_TO_PHY BIT(1) -#define LPI_CTRL_EN BIT(0) - -#define REG_LPI_WAIT 0x1444 -#define LPI_WAIT_TIMER_MASK 0xFFFFUL -#define LPI_WAIT_TIMER_SHIFT 0 - -/* MAC Control Register */ -#define REG_MAC_CTRL 0x1480 -#define MAC_CTRL_SPEED_MODE_SW BIT(30) /* 0:phy,1:sw */ -#define MAC_CTRL_HASH_ALG_CRC32 BIT(29) /* 1:legacy,0:lw_5b */ -#define MAC_CTRL_SINGLE_PAUSE_EN BIT(28) -#define MAC_CTRL_DBG BIT(27) -#define MAC_CTRL_BC_EN BIT(26) -#define MAC_CTRL_MC_ALL_EN BIT(25) -#define MAC_CTRL_RX_CHKSUM_EN BIT(24) -#define MAC_CTRL_TX_HUGE BIT(23) -#define MAC_CTRL_DBG_TX_BKPRESURE BIT(22) -#define MAC_CTRL_SPEED_MASK 3UL -#define MAC_CTRL_SPEED_SHIFT 20 -#define MAC_CTRL_SPEED_10_100 1 -#define MAC_CTRL_SPEED_1000 2 -#define MAC_CTRL_TX_SIMURST BIT(19) -#define MAC_CTRL_SCNT BIT(17) -#define MAC_CTRL_TX_PAUSE BIT(16) -#define MAC_CTRL_PROMIS_EN BIT(15) -#define MAC_CTRL_RMV_VLAN BIT(14) -#define MAC_CTRL_PRMLEN_MASK 0xFUL -#define MAC_CTRL_PRMLEN_SHIFT 10 -#define MAC_CTRL_HUGE_EN BIT(9) -#define MAC_CTRL_LENCHK BIT(8) -#define MAC_CTRL_PAD BIT(7) -#define MAC_CTRL_ADD_CRC BIT(6) -#define MAC_CTRL_DUPLX BIT(5) -#define MAC_CTRL_LOOPBACK BIT(4) -#define MAC_CTRL_RX_FLOW BIT(3) -#define MAC_CTRL_TX_FLOW BIT(2) -#define MAC_CTRL_RX_EN BIT(1) -#define MAC_CTRL_TX_EN BIT(0) - -/* MAC IPG/IFG Control Register */ -#define REG_MAC_IPG_IFG 0x1484 -#define MAC_IPG_IFG_IPGT_SHIFT 0 /* Desired back to back - * inter-packet gap. The - * default is 96-bit time */ -#define MAC_IPG_IFG_IPGT_MASK 0x7f -#define MAC_IPG_IFG_MIFG_SHIFT 8 /* Minimum number of IFG to - * enforce in between RX frames */ -#define MAC_IPG_IFG_MIFG_MASK 0xff /* Frame gap below such IFP is dropped */ -#define MAC_IPG_IFG_IPGR1_SHIFT 16 /* 64bit Carrier-Sense window */ -#define MAC_IPG_IFG_IPGR1_MASK 0x7f -#define MAC_IPG_IFG_IPGR2_SHIFT 24 /* 96-bit IPG window */ -#define MAC_IPG_IFG_IPGR2_MASK 0x7f - -/* MAC STATION ADDRESS */ -#define REG_MAC_STA_ADDR 0x1488 - -/* Hash table for multicast address */ -#define REG_RX_HASH_TABLE 0x1490 - -/* MAC Half-Duplex Control Register */ -#define REG_MAC_HALF_DUPLX_CTRL 0x1498 -#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT 0 /* Collision Window */ -#define MAC_HALF_DUPLX_CTRL_LCOL_MASK 0x3ff -#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12 -#define MAC_HALF_DUPLX_CTRL_RETRY_MASK 0xf -#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN 0x10000 -#define MAC_HALF_DUPLX_CTRL_NO_BACK_C 0x20000 -#define MAC_HALF_DUPLX_CTRL_NO_BACK_P 0x40000 /* No back-off on backpressure, - * immediately start the - * transmission after back pressure */ -#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */ -#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20 /* Maximum binary exponential number */ -#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xf -#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24 /* IPG to start JAM for collision based flow control in half-duplex */ -#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xf /* mode. In unit of 8-bit time */ - -/* Maximum Frame Length Control Register */ -#define REG_MTU 0x149c - -/* Wake-On-Lan control register */ -#define REG_WOL_CTRL 0x14a0 -#define WOL_PT7_MATCH BIT(31) -#define WOL_PT6_MATCH BIT(30) -#define WOL_PT5_MATCH BIT(29) -#define WOL_PT4_MATCH BIT(28) -#define WOL_PT3_MATCH BIT(27) -#define WOL_PT2_MATCH BIT(26) -#define WOL_PT1_MATCH BIT(25) -#define WOL_PT0_MATCH BIT(24) -#define WOL_PT7_EN BIT(23) -#define WOL_PT6_EN BIT(22) -#define WOL_PT5_EN BIT(21) -#define WOL_PT4_EN BIT(20) -#define WOL_PT3_EN BIT(19) -#define WOL_PT2_EN BIT(18) -#define WOL_PT1_EN BIT(17) -#define WOL_PT0_EN BIT(16) -#define WOL_LNKCHG_ST BIT(10) -#define WOL_MAGIC_ST BIT(9) -#define WOL_PATTERN_ST BIT(8) -#define WOL_OOB_EN BIT(6) -#define WOL_LINK_CHG_PME_EN BIT(5) -#define WOL_LINK_CHG_EN BIT(4) -#define WOL_MAGIC_PME_EN BIT(3) -#define WOL_MAGIC_EN BIT(2) -#define WOL_PATTERN_PME_EN BIT(1) -#define WOL_PATTERN_EN BIT(0) - -/* WOL Length ( 2 DWORD ) */ -#define REG_WOL_PTLEN1 0x14A4 -#define WOL_PTLEN1_3_MASK 0xFFUL -#define WOL_PTLEN1_3_SHIFT 24 -#define WOL_PTLEN1_2_MASK 0xFFUL -#define WOL_PTLEN1_2_SHIFT 16 -#define WOL_PTLEN1_1_MASK 0xFFUL -#define WOL_PTLEN1_1_SHIFT 8 -#define WOL_PTLEN1_0_MASK 0xFFUL -#define WOL_PTLEN1_0_SHIFT 0 - -#define REG_WOL_PTLEN2 0x14A8 -#define WOL_PTLEN2_7_MASK 0xFFUL -#define WOL_PTLEN2_7_SHIFT 24 -#define WOL_PTLEN2_6_MASK 0xFFUL -#define WOL_PTLEN2_6_SHIFT 16 -#define WOL_PTLEN2_5_MASK 0xFFUL -#define WOL_PTLEN2_5_SHIFT 8 -#define WOL_PTLEN2_4_MASK 0xFFUL -#define WOL_PTLEN2_4_SHIFT 0 - -/* Internal SRAM Partition Register */ -#define RFDX_HEAD_ADDR_MASK 0x03FF -#define RFDX_HARD_ADDR_SHIFT 0 -#define RFDX_TAIL_ADDR_MASK 0x03FF -#define RFDX_TAIL_ADDR_SHIFT 16 - -#define REG_SRAM_RFD0_INFO 0x1500 -#define REG_SRAM_RFD1_INFO 0x1504 -#define REG_SRAM_RFD2_INFO 0x1508 -#define REG_SRAM_RFD3_INFO 0x150C - -#define REG_RFD_NIC_LEN 0x1510 /* In 8-bytes */ -#define RFD_NIC_LEN_MASK 0x03FF - -#define REG_SRAM_TRD_ADDR 0x1518 -#define TPD_HEAD_ADDR_MASK 0x03FF -#define TPD_HEAD_ADDR_SHIFT 0 -#define TPD_TAIL_ADDR_MASK 0x03FF -#define TPD_TAIL_ADDR_SHIFT 16 - -#define REG_SRAM_TRD_LEN 0x151C /* In 8-bytes */ -#define TPD_NIC_LEN_MASK 0x03FF - -#define REG_SRAM_RXF_ADDR 0x1520 -#define REG_SRAM_RXF_LEN 0x1524 -#define REG_SRAM_TXF_ADDR 0x1528 -#define REG_SRAM_TXF_LEN 0x152C -#define REG_SRAM_TCPH_ADDR 0x1530 -#define REG_SRAM_PKTH_ADDR 0x1532 - -/* - * Load Ptr Register - * Software sets this bit after the initialization of the head and tail */ -#define REG_LOAD_PTR 0x1534 - -/* - * addresses of all descriptors, as well as the following descriptor - * control register, which triggers each function block to load the head - * pointer to prepare for the operation. This bit is then self-cleared - * after one cycle. - */ -#define REG_RX_BASE_ADDR_HI 0x1540 -#define REG_TX_BASE_ADDR_HI 0x1544 -#define REG_RFD0_HEAD_ADDR_LO 0x1550 -#define REG_RFD_RING_SIZE 0x1560 -#define RFD_RING_SIZE_MASK 0x0FFF -#define REG_RX_BUF_SIZE 0x1564 -#define RX_BUF_SIZE_MASK 0xFFFF -#define REG_RRD0_HEAD_ADDR_LO 0x1568 -#define REG_RRD_RING_SIZE 0x1578 -#define RRD_RING_SIZE_MASK 0x0FFF -#define REG_TPD_PRI1_ADDR_LO 0x157C -#define REG_TPD_PRI0_ADDR_LO 0x1580 -#define REG_TPD_RING_SIZE 0x1584 -#define TPD_RING_SIZE_MASK 0xFFFF - -/* TXQ Control Register */ -#define REG_TXQ_CTRL 0x1590 -#define TXQ_TXF_BURST_NUM_MASK 0xFFFFUL -#define TXQ_TXF_BURST_NUM_SHIFT 16 -#define L1C_TXQ_TXF_BURST_PREF 0x200 -#define L2CB_TXQ_TXF_BURST_PREF 0x40 -#define TXQ_CTRL_PEDING_CLR BIT(8) -#define TXQ_CTRL_LS_8023_EN BIT(7) -#define TXQ_CTRL_ENH_MODE BIT(6) -#define TXQ_CTRL_EN BIT(5) -#define TXQ_CTRL_IP_OPTION_EN BIT(4) -#define TXQ_NUM_TPD_BURST_MASK 0xFUL -#define TXQ_NUM_TPD_BURST_SHIFT 0 -#define TXQ_NUM_TPD_BURST_DEF 5 -#define TXQ_CFGV (\ - FIELDX(TXQ_NUM_TPD_BURST, TXQ_NUM_TPD_BURST_DEF) |\ - TXQ_CTRL_ENH_MODE |\ - TXQ_CTRL_LS_8023_EN |\ - TXQ_CTRL_IP_OPTION_EN) -#define L1C_TXQ_CFGV (\ - TXQ_CFGV |\ - FIELDX(TXQ_TXF_BURST_NUM, L1C_TXQ_TXF_BURST_PREF)) -#define L2CB_TXQ_CFGV (\ - TXQ_CFGV |\ - FIELDX(TXQ_TXF_BURST_NUM, L2CB_TXQ_TXF_BURST_PREF)) - - -/* Jumbo packet Threshold for task offload */ -#define REG_TX_TSO_OFFLOAD_THRESH 0x1594 /* In 8-bytes */ -#define TX_TSO_OFFLOAD_THRESH_MASK 0x07FF -#define MAX_TSO_FRAME_SIZE (7*1024) - -#define REG_TXF_WATER_MARK 0x1598 /* In 8-bytes */ -#define TXF_WATER_MARK_MASK 0x0FFF -#define TXF_LOW_WATER_MARK_SHIFT 0 -#define TXF_HIGH_WATER_MARK_SHIFT 16 -#define TXQ_CTRL_BURST_MODE_EN 0x80000000 - -#define REG_THRUPUT_MON_CTRL 0x159C -#define THRUPUT_MON_RATE_MASK 0x3 -#define THRUPUT_MON_RATE_SHIFT 0 -#define THRUPUT_MON_EN 0x80 - -/* RXQ Control Register */ -#define REG_RXQ_CTRL 0x15A0 -#define ASPM_THRUPUT_LIMIT_MASK 0x3 -#define ASPM_THRUPUT_LIMIT_SHIFT 0 -#define ASPM_THRUPUT_LIMIT_NO 0x00 -#define ASPM_THRUPUT_LIMIT_1M 0x01 -#define ASPM_THRUPUT_LIMIT_10M 0x02 -#define ASPM_THRUPUT_LIMIT_100M 0x03 -#define IPV6_CHKSUM_CTRL_EN BIT(7) -#define RXQ_RFD_BURST_NUM_MASK 0x003F -#define RXQ_RFD_BURST_NUM_SHIFT 20 -#define RXQ_NUM_RFD_PREF_DEF 8 -#define RSS_MODE_MASK 3UL -#define RSS_MODE_SHIFT 26 -#define RSS_MODE_DIS 0 -#define RSS_MODE_SQSI 1 -#define RSS_MODE_MQSI 2 -#define RSS_MODE_MQMI 3 -#define RSS_NIP_QUEUE_SEL BIT(28) /* 0:q0, 1:table */ -#define RRS_HASH_CTRL_EN BIT(29) -#define RX_CUT_THRU_EN BIT(30) -#define RXQ_CTRL_EN BIT(31) - -#define REG_RFD_FREE_THRESH 0x15A4 -#define RFD_FREE_THRESH_MASK 0x003F -#define RFD_FREE_HI_THRESH_SHIFT 0 -#define RFD_FREE_LO_THRESH_SHIFT 6 - -/* RXF flow control register */ -#define REG_RXQ_RXF_PAUSE_THRESH 0x15A8 -#define RXQ_RXF_PAUSE_TH_HI_SHIFT 0 -#define RXQ_RXF_PAUSE_TH_HI_MASK 0x0FFF -#define RXQ_RXF_PAUSE_TH_LO_SHIFT 16 -#define RXQ_RXF_PAUSE_TH_LO_MASK 0x0FFF - -#define REG_RXD_DMA_CTRL 0x15AC -#define RXD_DMA_THRESH_MASK 0x0FFF /* In 8-bytes */ -#define RXD_DMA_THRESH_SHIFT 0 -#define RXD_DMA_DOWN_TIMER_MASK 0xFFFF -#define RXD_DMA_DOWN_TIMER_SHIFT 16 - -/* DMA Engine Control Register */ -#define REG_DMA_CTRL 0x15C0 -#define DMA_CTRL_SMB_NOW BIT(31) -#define DMA_CTRL_WPEND_CLR BIT(30) -#define DMA_CTRL_RPEND_CLR BIT(29) -#define DMA_CTRL_WDLY_CNT_MASK 0xFUL -#define DMA_CTRL_WDLY_CNT_SHIFT 16 -#define DMA_CTRL_WDLY_CNT_DEF 4 -#define DMA_CTRL_RDLY_CNT_MASK 0x1FUL -#define DMA_CTRL_RDLY_CNT_SHIFT 11 -#define DMA_CTRL_RDLY_CNT_DEF 15 -#define DMA_CTRL_RREQ_PRI_DATA BIT(10) /* 0:tpd, 1:data */ -#define DMA_CTRL_WREQ_BLEN_MASK 7UL -#define DMA_CTRL_WREQ_BLEN_SHIFT 7 -#define DMA_CTRL_RREQ_BLEN_MASK 7UL -#define DMA_CTRL_RREQ_BLEN_SHIFT 4 -#define L1C_CTRL_DMA_RCB_LEN128 BIT(3) /* 0:64bytes,1:128bytes */ -#define DMA_CTRL_RORDER_MODE_MASK 7UL -#define DMA_CTRL_RORDER_MODE_SHIFT 0 -#define DMA_CTRL_RORDER_MODE_OUT 4 -#define DMA_CTRL_RORDER_MODE_ENHANCE 2 -#define DMA_CTRL_RORDER_MODE_IN 1 - -/* INT-triggle/SMB Control Register */ -#define REG_SMB_STAT_TIMER 0x15C4 /* 2us resolution */ -#define SMB_STAT_TIMER_MASK 0xFFFFFF -#define REG_TINT_TPD_THRESH 0x15C8 /* tpd th to trig intrrupt */ - -/* Mail box */ -#define MB_RFDX_PROD_IDX_MASK 0xFFFF -#define REG_MB_RFD0_PROD_IDX 0x15E0 - -#define REG_TPD_PRI1_PIDX 0x15F0 /* 16bit,hi-tpd producer idx */ -#define REG_TPD_PRI0_PIDX 0x15F2 /* 16bit,lo-tpd producer idx */ -#define REG_TPD_PRI1_CIDX 0x15F4 /* 16bit,hi-tpd consumer idx */ -#define REG_TPD_PRI0_CIDX 0x15F6 /* 16bit,lo-tpd consumer idx */ - -#define REG_MB_RFD01_CONS_IDX 0x15F8 -#define MB_RFD0_CONS_IDX_MASK 0x0000FFFF -#define MB_RFD1_CONS_IDX_MASK 0xFFFF0000 - -/* Interrupt Status Register */ -#define REG_ISR 0x1600 -#define ISR_SMB 0x00000001 -#define ISR_TIMER 0x00000002 -/* - * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set - * in Table 51 Selene Master Control Register (Offset 0x1400). - */ -#define ISR_MANUAL 0x00000004 -#define ISR_HW_RXF_OV 0x00000008 /* RXF overflow interrupt */ -#define ISR_RFD0_UR 0x00000010 /* RFD0 under run */ -#define ISR_RFD1_UR 0x00000020 -#define ISR_RFD2_UR 0x00000040 -#define ISR_RFD3_UR 0x00000080 -#define ISR_TXF_UR 0x00000100 -#define ISR_DMAR_TO_RST 0x00000200 -#define ISR_DMAW_TO_RST 0x00000400 -#define ISR_TX_CREDIT 0x00000800 -#define ISR_GPHY 0x00001000 -/* GPHY low power state interrupt */ -#define ISR_GPHY_LPW 0x00002000 -#define ISR_TXQ_TO_RST 0x00004000 -#define ISR_TX_PKT 0x00008000 -#define ISR_RX_PKT_0 0x00010000 -#define ISR_RX_PKT_1 0x00020000 -#define ISR_RX_PKT_2 0x00040000 -#define ISR_RX_PKT_3 0x00080000 -#define ISR_MAC_RX 0x00100000 -#define ISR_MAC_TX 0x00200000 -#define ISR_UR_DETECTED 0x00400000 -#define ISR_FERR_DETECTED 0x00800000 -#define ISR_NFERR_DETECTED 0x01000000 -#define ISR_CERR_DETECTED 0x02000000 -#define ISR_PHY_LINKDOWN 0x04000000 -#define ISR_DIS_INT 0x80000000 - -/* Interrupt Mask Register */ -#define REG_IMR 0x1604 - -#define IMR_NORMAL_MASK (\ - ISR_MANUAL |\ - ISR_HW_RXF_OV |\ - ISR_RFD0_UR |\ - ISR_TXF_UR |\ - ISR_DMAR_TO_RST |\ - ISR_TXQ_TO_RST |\ - ISR_DMAW_TO_RST |\ - ISR_GPHY |\ - ISR_TX_PKT |\ - ISR_RX_PKT_0 |\ - ISR_GPHY_LPW |\ - ISR_PHY_LINKDOWN) - -#define ISR_RX_PKT (\ - ISR_RX_PKT_0 |\ - ISR_RX_PKT_1 |\ - ISR_RX_PKT_2 |\ - ISR_RX_PKT_3) - -#define ISR_OVER (\ - ISR_RFD0_UR |\ - ISR_RFD1_UR |\ - ISR_RFD2_UR |\ - ISR_RFD3_UR |\ - ISR_HW_RXF_OV |\ - ISR_TXF_UR) - -#define ISR_ERROR (\ - ISR_DMAR_TO_RST |\ - ISR_TXQ_TO_RST |\ - ISR_DMAW_TO_RST |\ - ISR_PHY_LINKDOWN) - -#define REG_INT_RETRIG_TIMER 0x1608 -#define INT_RETRIG_TIMER_MASK 0xFFFF - -#define REG_MAC_RX_STATUS_BIN 0x1700 -#define REG_MAC_RX_STATUS_END 0x175c -#define REG_MAC_TX_STATUS_BIN 0x1760 -#define REG_MAC_TX_STATUS_END 0x17c0 - -#define REG_CLK_GATING_CTRL 0x1814 -#define CLK_GATING_DMAW_EN 0x0001 -#define CLK_GATING_DMAR_EN 0x0002 -#define CLK_GATING_TXQ_EN 0x0004 -#define CLK_GATING_RXQ_EN 0x0008 -#define CLK_GATING_TXMAC_EN 0x0010 -#define CLK_GATING_RXMAC_EN 0x0020 - -#define CLK_GATING_EN_ALL (CLK_GATING_DMAW_EN |\ - CLK_GATING_DMAR_EN |\ - CLK_GATING_TXQ_EN |\ - CLK_GATING_RXQ_EN |\ - CLK_GATING_TXMAC_EN|\ - CLK_GATING_RXMAC_EN) - -/* DEBUG ADDR */ -#define REG_DEBUG_DATA0 0x1900 -#define REG_DEBUG_DATA1 0x1904 - -#define L1D_MPW_PHYID1 0xD01C /* V7 */ -#define L1D_MPW_PHYID2 0xD01D /* V1-V6 */ -#define L1D_MPW_PHYID3 0xD01E /* V8 */ - - -/* Autoneg Advertisement Register */ -#define ADVERTISE_DEFAULT_CAP \ - (ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM) - -/* 1000BASE-T Control Register */ -#define GIGA_CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port 0=DTE device */ - -#define GIGA_CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master 0=Configure PHY as Slave */ -#define GIGA_CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value 0=Automatic Master/Slave config */ -#define GIGA_CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ -#define GIGA_CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ -#define GIGA_CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ -#define GIGA_CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ -#define GIGA_CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ -#define GIGA_CR_1000T_SPEED_MASK 0x0300 -#define GIGA_CR_1000T_DEFAULT_CAP 0x0300 - -/* PHY Specific Status Register */ -#define MII_GIGA_PSSR 0x11 -#define GIGA_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ -#define GIGA_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ -#define GIGA_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ -#define GIGA_PSSR_10MBS 0x0000 /* 00=10Mbs */ -#define GIGA_PSSR_100MBS 0x4000 /* 01=100Mbs */ -#define GIGA_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ - -/* PHY Interrupt Enable Register */ -#define MII_IER 0x12 -#define IER_LINK_UP 0x0400 -#define IER_LINK_DOWN 0x0800 - -/* PHY Interrupt Status Register */ -#define MII_ISR 0x13 -#define ISR_LINK_UP 0x0400 -#define ISR_LINK_DOWN 0x0800 - -/* Cable-Detect-Test Control Register */ -#define MII_CDTC 0x16 -#define CDTC_EN_OFF 0 /* sc */ -#define CDTC_EN_BITS 1 -#define CDTC_PAIR_OFF 8 -#define CDTC_PAIR_BIT 2 - -/* Cable-Detect-Test Status Register */ -#define MII_CDTS 0x1C -#define CDTS_STATUS_OFF 8 -#define CDTS_STATUS_BITS 2 -#define CDTS_STATUS_NORMAL 0 -#define CDTS_STATUS_SHORT 1 -#define CDTS_STATUS_OPEN 2 -#define CDTS_STATUS_INVALID 3 - -#define MII_DBG_ADDR 0x1D -#define MII_DBG_DATA 0x1E - -/***************************** debug port *************************************/ - -#define MIIDBG_ANACTRL 0x00 -#define ANACTRL_CLK125M_DELAY_EN 0x8000 -#define ANACTRL_VCO_FAST 0x4000 -#define ANACTRL_VCO_SLOW 0x2000 -#define ANACTRL_AFE_MODE_EN 0x1000 -#define ANACTRL_LCKDET_PHY 0x800 -#define ANACTRL_LCKDET_EN 0x400 -#define ANACTRL_OEN_125M 0x200 -#define ANACTRL_HBIAS_EN 0x100 -#define ANACTRL_HB_EN 0x80 -#define ANACTRL_SEL_HSP 0x40 -#define ANACTRL_CLASSA_EN 0x20 -#define ANACTRL_MANUSWON_SWR_MASK 3U -#define ANACTRL_MANUSWON_SWR_SHIFT 2 -#define ANACTRL_MANUSWON_SWR_2V 0 -#define ANACTRL_MANUSWON_SWR_1P9V 1 -#define ANACTRL_MANUSWON_SWR_1P8V 2 -#define ANACTRL_MANUSWON_SWR_1P7V 3 -#define ANACTRL_MANUSWON_BW3_4M 0x2 -#define ANACTRL_RESTART_CAL 0x1 -#define ANACTRL_DEF 0x02EF - -#define MIIDBG_SYSMODCTRL 0x04 -#define SYSMODCTRL_IECHOADJ_PFMH_PHY 0x8000 -#define SYSMODCTRL_IECHOADJ_BIASGEN 0x4000 -#define SYSMODCTRL_IECHOADJ_PFML_PHY 0x2000 -#define SYSMODCTRL_IECHOADJ_PS_MASK 3U -#define SYSMODCTRL_IECHOADJ_PS_SHIFT 10 -#define SYSMODCTRL_IECHOADJ_PS_40 3 -#define SYSMODCTRL_IECHOADJ_PS_20 2 -#define SYSMODCTRL_IECHOADJ_PS_0 1 -#define SYSMODCTRL_IECHOADJ_10BT_100MV 0x40 /* 1:100mv, 0:200mv */ -#define SYSMODCTRL_IECHOADJ_HLFAP_MASK 3U -#define SYSMODCTRL_IECHOADJ_HLFAP_SHIFT 4 -#define SYSMODCTRL_IECHOADJ_VDFULBW 0x8 -#define SYSMODCTRL_IECHOADJ_VDBIASHLF 0x4 -#define SYSMODCTRL_IECHOADJ_VDAMPHLF 0x2 -#define SYSMODCTRL_IECHOADJ_VDLANSW 0x1 -#define SYSMODCTRL_IECHOADJ_DEF 0x88BB /* ???? */ - -/* for l1d & l2cb */ -#define SYSMODCTRL_IECHOADJ_CUR_ADD 0x8000 -#define SYSMODCTRL_IECHOADJ_CUR_MASK 7U -#define SYSMODCTRL_IECHOADJ_CUR_SHIFT 12 -#define SYSMODCTRL_IECHOADJ_VOL_MASK 0xFU -#define SYSMODCTRL_IECHOADJ_VOL_SHIFT 8 -#define SYSMODCTRL_IECHOADJ_VOL_17ALL 3 -#define SYSMODCTRL_IECHOADJ_VOL_100M15 1 -#define SYSMODCTRL_IECHOADJ_VOL_10M17 0 -#define SYSMODCTRL_IECHOADJ_BIAS1_MASK 0xFU -#define SYSMODCTRL_IECHOADJ_BIAS1_SHIFT 4 -#define SYSMODCTRL_IECHOADJ_BIAS2_MASK 0xFU -#define SYSMODCTRL_IECHOADJ_BIAS2_SHIFT 0 -#define L1D_SYSMODCTRL_IECHOADJ_DEF 0x4FBB - -#define MIIDBG_SRDSYSMOD 0x05 -#define SRDSYSMOD_LCKDET_EN 0x2000 -#define SRDSYSMOD_PLL_EN 0x800 -#define SRDSYSMOD_SEL_HSP 0x400 -#define SRDSYSMOD_HLFTXDR 0x200 -#define SRDSYSMOD_TXCLK_DELAY_EN 0x100 -#define SRDSYSMOD_TXELECIDLE 0x80 -#define SRDSYSMOD_DEEMP_EN 0x40 -#define SRDSYSMOD_MS_PAD 0x4 -#define SRDSYSMOD_CDR_ADC_VLTG 0x2 -#define SRDSYSMOD_CDR_DAC_1MA 0x1 -#define SRDSYSMOD_DEF 0x2C46 - -#define MIIDBG_CFGLPSPD 0x0A -#define CFGLPSPD_RSTCNT_MASK 3U -#define CFGLPSPD_RSTCNT_SHIFT 14 -#define CFGLPSPD_RSTCNT_CLK125SW 0x2000 - -#define MIIDBG_HIBNEG 0x0B -#define HIBNEG_PSHIB_EN 0x8000 -#define HIBNEG_WAKE_BOTH 0x4000 -#define HIBNEG_ONOFF_ANACHG_SUDEN 0x2000 -#define HIBNEG_HIB_PULSE 0x1000 -#define HIBNEG_GATE_25M_EN 0x800 -#define HIBNEG_RST_80U 0x400 -#define HIBNEG_RST_TIMER_MASK 3U -#define HIBNEG_RST_TIMER_SHIFT 8 -#define HIBNEG_GTX_CLK_DELAY_MASK 3U -#define HIBNEG_GTX_CLK_DELAY_SHIFT 5 -#define HIBNEG_BYPSS_BRKTIMER 0x10 -#define HIBNEG_DEF 0xBC40 - -#define MIIDBG_TST10BTCFG 0x12 -#define TST10BTCFG_INTV_TIMER_MASK 3U -#define TST10BTCFG_INTV_TIMER_SHIFT 14 -#define TST10BTCFG_TRIGER_TIMER_MASK 3U -#define TST10BTCFG_TRIGER_TIMER_SHIFT 12 -#define TST10BTCFG_DIV_MAN_MLT3_EN 0x800 -#define TST10BTCFG_OFF_DAC_IDLE 0x400 -#define TST10BTCFG_LPBK_DEEP 0x4 /* 1:deep,0:shallow */ -#define TST10BTCFG_DEF 0x4C04 - -#define MIIDBG_AZ_ANADECT 0x15 -#define AZ_ANADECT_10BTRX_TH 0x8000 -#define AZ_ANADECT_BOTH_01CHNL 0x4000 -#define AZ_ANADECT_INTV_MASK 0x3FU -#define AZ_ANADECT_INTV_SHIFT 8 -#define AZ_ANADECT_THRESH_MASK 0xFU -#define AZ_ANADECT_THRESH_SHIFT 4 -#define AZ_ANADECT_CHNL_MASK 0xFU -#define AZ_ANADECT_CHNL_SHIFT 0 -#define AZ_ANADECT_DEF 0x3220 -#define AZ_ANADECT_LONG 0xb210 - -#define MIIDBG_MSE16DB 0x18 /* l1d */ -#define L1D_MSE16DB_UP 0x05EA -#define L1D_MSE16DB_DOWN 0x02EA - -#define MIIDBG_LEGCYPS 0x29 -#define LEGCYPS_EN 0x8000 -#define LEGCYPS_DAC_AMP1000_MASK 7U -#define LEGCYPS_DAC_AMP1000_SHIFT 12 -#define LEGCYPS_DAC_AMP100_MASK 7U -#define LEGCYPS_DAC_AMP100_SHIFT 9 -#define LEGCYPS_DAC_AMP10_MASK 7U -#define LEGCYPS_DAC_AMP10_SHIFT 6 -#define LEGCYPS_UNPLUG_TIMER_MASK 7U -#define LEGCYPS_UNPLUG_TIMER_SHIFT 3 -#define LEGCYPS_UNPLUG_DECT_EN 0x4 -#define LEGCYPS_ECNC_PS_EN 0x1 -#define L1D_LEGCYPS_DEF 0x129D -#define L1C_LEGCYPS_DEF 0x36DD - -#define MIIDBG_TST100BTCFG 0x36 -#define TST100BTCFG_NORMAL_BW_EN 0x8000 -#define TST100BTCFG_BADLNK_BYPASS 0x4000 -#define TST100BTCFG_SHORTCABL_TH_MASK 0x3FU -#define TST100BTCFG_SHORTCABL_TH_SHIFT 8 -#define TST100BTCFG_LITCH_EN 0x80 -#define TST100BTCFG_VLT_SW 0x40 -#define TST100BTCFG_LONGCABL_TH_MASK 0x3FU -#define TST100BTCFG_LONGCABL_TH_SHIFT 0 -#define TST100BTCFG_DEF 0xE12C - -#define MIIDBG_VOLT_CTRL 0x3B /* only for l2cb 1 & 2 */ -#define VOLT_CTRL_CABLE1TH_MASK 0x1FFU -#define VOLT_CTRL_CABLE1TH_SHIFT 7 -#define VOLT_CTRL_AMPCTRL_MASK 3U -#define VOLT_CTRL_AMPCTRL_SHIFT 5 -#define VOLT_CTRL_SW_BYPASS 0x10 -#define VOLT_CTRL_SWLOWEST 0x8 -#define VOLT_CTRL_DACAMP10_MASK 7U -#define VOLT_CTRL_DACAMP10_SHIFT 0 - -#define MIIDBG_CABLE1TH_DET 0x3E -#define CABLE1TH_DET_EN 0x8000 - - -/******* dev 3 *********/ -#define MIIEXT_PCS 3 - -#define MIIEXT_CLDCTRL3 0x8003 -#define CLDCTRL3_BP_CABLE1TH_DET_GT 0x8000 -#define CLDCTRL3_AZ_DISAMP 0x1000 -#define L2CB_CLDCTRL3 0x4D19 -#define L1D_CLDCTRL3 0xDD19 - -#define MIIEXT_CLDCTRL6 0x8006 -#define CLDCTRL6_CAB_LEN_MASK 0x1FFU -#define CLDCTRL6_CAB_LEN_SHIFT 0 -#define CLDCTRL6_CAB_LEN_SHORT 0x50 - -/********* dev 7 **********/ -#define MIIEXT_ANEG 7 - -#define MIIEXT_LOCAL_EEEADV 0x3C -#define LOCAL_EEEADV_1000BT 0x4 -#define LOCAL_EEEADV_100BT 0x2 - -#define MIIEXT_REMOTE_EEEADV 0x3D -#define REMOTE_EEEADV_1000BT 0x4 -#define REMOTE_EEEADV_100BT 0x2 - -#define MIIEXT_EEE_ANEG 0x8000 -#define EEE_ANEG_1000M 0x4 -#define EEE_ANEG_100M 0x2 - -#endif /*_ATL1C_HW_H_*/ diff --git a/addons/atl1c/src/4.4.180/atl1c_main.c b/addons/atl1c/src/4.4.180/atl1c_main.c deleted file mode 100644 index c08d34f6..00000000 --- a/addons/atl1c/src/4.4.180/atl1c_main.c +++ /dev/null @@ -1,2813 +0,0 @@ -/* - * Copyright(c) 2008 - 2009 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "atl1c.h" - -#define ATL1C_DRV_VERSION "1.0.1.1-NAPI" -char atl1c_driver_name[] = "atl1c"; -char atl1c_driver_version[] = ATL1C_DRV_VERSION; - -/* - * atl1c_pci_tbl - PCI Device ID Table - * - * Wildcard entries (PCI_ANY_ID) should come last - * Last entry must be all 0s - * - * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, - * Class, Class Mask, private data (not used) } - */ -static const struct pci_device_id atl1c_pci_tbl[] = { - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1C)}, - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L2C)}, - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B)}, - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L2C_B2)}, - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L1D)}, - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATHEROS_L1D_2_0)}, - /* required last entry */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, atl1c_pci_tbl); - -MODULE_AUTHOR("Jie Yang"); -MODULE_AUTHOR("Qualcomm Atheros Inc., "); -MODULE_DESCRIPTION("Qualcomm Atheros 100/1000M Ethernet Network Driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(ATL1C_DRV_VERSION); - -static int atl1c_stop_mac(struct atl1c_hw *hw); -static void atl1c_disable_l0s_l1(struct atl1c_hw *hw); -static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed); -static void atl1c_start_mac(struct atl1c_adapter *adapter); -static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, - int *work_done, int work_to_do); -static int atl1c_up(struct atl1c_adapter *adapter); -static void atl1c_down(struct atl1c_adapter *adapter); -static int atl1c_reset_mac(struct atl1c_hw *hw); -static void atl1c_reset_dma_ring(struct atl1c_adapter *adapter); -static int atl1c_configure(struct atl1c_adapter *adapter); -static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter); - -static const u16 atl1c_pay_load_size[] = { - 128, 256, 512, 1024, 2048, 4096, -}; - - -static const u32 atl1c_default_msg = NETIF_MSG_DRV | NETIF_MSG_PROBE | - NETIF_MSG_LINK | NETIF_MSG_TIMER | NETIF_MSG_IFDOWN | NETIF_MSG_IFUP; -static void atl1c_pcie_patch(struct atl1c_hw *hw) -{ - u32 mst_data, data; - - /* pclk sel could switch to 25M */ - AT_READ_REG(hw, REG_MASTER_CTRL, &mst_data); - mst_data &= ~MASTER_CTRL_CLK_SEL_DIS; - AT_WRITE_REG(hw, REG_MASTER_CTRL, mst_data); - - /* WoL/PCIE related settings */ - if (hw->nic_type == athr_l1c || hw->nic_type == athr_l2c) { - AT_READ_REG(hw, REG_PCIE_PHYMISC, &data); - data |= PCIE_PHYMISC_FORCE_RCV_DET; - AT_WRITE_REG(hw, REG_PCIE_PHYMISC, data); - } else { /* new dev set bit5 of MASTER */ - if (!(mst_data & MASTER_CTRL_WAKEN_25M)) - AT_WRITE_REG(hw, REG_MASTER_CTRL, - mst_data | MASTER_CTRL_WAKEN_25M); - } - /* aspm/PCIE setting only for l2cb 1.0 */ - if (hw->nic_type == athr_l2c_b && hw->revision_id == L2CB_V10) { - AT_READ_REG(hw, REG_PCIE_PHYMISC2, &data); - data = FIELD_SETX(data, PCIE_PHYMISC2_CDR_BW, - L2CB1_PCIE_PHYMISC2_CDR_BW); - data = FIELD_SETX(data, PCIE_PHYMISC2_L0S_TH, - L2CB1_PCIE_PHYMISC2_L0S_TH); - AT_WRITE_REG(hw, REG_PCIE_PHYMISC2, data); - /* extend L1 sync timer */ - AT_READ_REG(hw, REG_LINK_CTRL, &data); - data |= LINK_CTRL_EXT_SYNC; - AT_WRITE_REG(hw, REG_LINK_CTRL, data); - } - /* l2cb 1.x & l1d 1.x */ - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d) { - AT_READ_REG(hw, REG_PM_CTRL, &data); - data |= PM_CTRL_L0S_BUFSRX_EN; - AT_WRITE_REG(hw, REG_PM_CTRL, data); - /* clear vendor msg */ - AT_READ_REG(hw, REG_DMA_DBG, &data); - AT_WRITE_REG(hw, REG_DMA_DBG, data & ~DMA_DBG_VENDOR_MSG); - } -} - -/* FIXME: no need any more ? */ -/* - * atl1c_init_pcie - init PCIE module - */ -static void atl1c_reset_pcie(struct atl1c_hw *hw, u32 flag) -{ - u32 data; - u32 pci_cmd; - struct pci_dev *pdev = hw->adapter->pdev; - int pos; - - AT_READ_REG(hw, PCI_COMMAND, &pci_cmd); - pci_cmd &= ~PCI_COMMAND_INTX_DISABLE; - pci_cmd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | - PCI_COMMAND_IO); - AT_WRITE_REG(hw, PCI_COMMAND, pci_cmd); - - /* - * Clear any PowerSaveing Settings - */ - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - /* wol sts read-clear */ - AT_READ_REG(hw, REG_WOL_CTRL, &data); - AT_WRITE_REG(hw, REG_WOL_CTRL, 0); - - /* - * Mask some pcie error bits - */ - pos = pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ERR); - if (pos) { - pci_read_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, &data); - data &= ~(PCI_ERR_UNC_DLP | PCI_ERR_UNC_FCP); - pci_write_config_dword(pdev, pos + PCI_ERR_UNCOR_SEVER, data); - } - /* clear error status */ - pcie_capability_write_word(pdev, PCI_EXP_DEVSTA, - PCI_EXP_DEVSTA_NFED | - PCI_EXP_DEVSTA_FED | - PCI_EXP_DEVSTA_CED | - PCI_EXP_DEVSTA_URD); - - AT_READ_REG(hw, REG_LTSSM_ID_CTRL, &data); - data &= ~LTSSM_ID_EN_WRO; - AT_WRITE_REG(hw, REG_LTSSM_ID_CTRL, data); - - atl1c_pcie_patch(hw); - if (flag & ATL1C_PCIE_L0S_L1_DISABLE) - atl1c_disable_l0s_l1(hw); - - msleep(5); -} - -/** - * atl1c_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - */ -static inline void atl1c_irq_enable(struct atl1c_adapter *adapter) -{ - if (likely(atomic_dec_and_test(&adapter->irq_sem))) { - AT_WRITE_REG(&adapter->hw, REG_ISR, 0x7FFFFFFF); - AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask); - AT_WRITE_FLUSH(&adapter->hw); - } -} - -/** - * atl1c_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - */ -static inline void atl1c_irq_disable(struct atl1c_adapter *adapter) -{ - atomic_inc(&adapter->irq_sem); - AT_WRITE_REG(&adapter->hw, REG_IMR, 0); - AT_WRITE_REG(&adapter->hw, REG_ISR, ISR_DIS_INT); - AT_WRITE_FLUSH(&adapter->hw); - synchronize_irq(adapter->pdev->irq); -} - -/** - * atl1c_irq_reset - reset interrupt confiure on the NIC - * @adapter: board private structure - */ -static inline void atl1c_irq_reset(struct atl1c_adapter *adapter) -{ - atomic_set(&adapter->irq_sem, 1); - atl1c_irq_enable(adapter); -} - -/* - * atl1c_wait_until_idle - wait up to AT_HW_MAX_IDLE_DELAY reads - * of the idle status register until the device is actually idle - */ -static u32 atl1c_wait_until_idle(struct atl1c_hw *hw, u32 modu_ctrl) -{ - int timeout; - u32 data; - - for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { - AT_READ_REG(hw, REG_IDLE_STATUS, &data); - if ((data & modu_ctrl) == 0) - return 0; - msleep(1); - } - return data; -} - -/** - * atl1c_phy_config - Timer Call-back - * @data: pointer to netdev cast into an unsigned long - */ -static void atl1c_phy_config(unsigned long data) -{ - struct atl1c_adapter *adapter = (struct atl1c_adapter *) data; - struct atl1c_hw *hw = &adapter->hw; - unsigned long flags; - - spin_lock_irqsave(&adapter->mdio_lock, flags); - atl1c_restart_autoneg(hw); - spin_unlock_irqrestore(&adapter->mdio_lock, flags); -} - -void atl1c_reinit_locked(struct atl1c_adapter *adapter) -{ - WARN_ON(in_interrupt()); - atl1c_down(adapter); - atl1c_up(adapter); - clear_bit(__AT_RESETTING, &adapter->flags); -} - -static void atl1c_check_link_status(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - int err; - unsigned long flags; - u16 speed, duplex, phy_data; - - spin_lock_irqsave(&adapter->mdio_lock, flags); - /* MII_BMSR must read twise */ - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - atl1c_read_phy_reg(hw, MII_BMSR, &phy_data); - spin_unlock_irqrestore(&adapter->mdio_lock, flags); - - if ((phy_data & BMSR_LSTATUS) == 0) { - /* link down */ - netif_carrier_off(netdev); - hw->hibernate = true; - if (atl1c_reset_mac(hw) != 0) - if (netif_msg_hw(adapter)) - dev_warn(&pdev->dev, "reset mac failed\n"); - atl1c_set_aspm(hw, SPEED_0); - atl1c_post_phy_linkchg(hw, SPEED_0); - atl1c_reset_dma_ring(adapter); - atl1c_configure(adapter); - } else { - /* Link Up */ - hw->hibernate = false; - spin_lock_irqsave(&adapter->mdio_lock, flags); - err = atl1c_get_speed_and_duplex(hw, &speed, &duplex); - spin_unlock_irqrestore(&adapter->mdio_lock, flags); - if (unlikely(err)) - return; - /* link result is our setting */ - if (adapter->link_speed != speed || - adapter->link_duplex != duplex) { - adapter->link_speed = speed; - adapter->link_duplex = duplex; - atl1c_set_aspm(hw, speed); - atl1c_post_phy_linkchg(hw, speed); - atl1c_start_mac(adapter); - if (netif_msg_link(adapter)) - dev_info(&pdev->dev, - "%s: %s NIC Link is Up<%d Mbps %s>\n", - atl1c_driver_name, netdev->name, - adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? - "Full Duplex" : "Half Duplex"); - } - if (!netif_carrier_ok(netdev)) - netif_carrier_on(netdev); - } -} - -static void atl1c_link_chg_event(struct atl1c_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - u16 phy_data; - u16 link_up; - - spin_lock(&adapter->mdio_lock); - atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); - atl1c_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); - spin_unlock(&adapter->mdio_lock); - link_up = phy_data & BMSR_LSTATUS; - /* notify upper layer link down ASAP */ - if (!link_up) { - if (netif_carrier_ok(netdev)) { - /* old link state: Up */ - netif_carrier_off(netdev); - if (netif_msg_link(adapter)) - dev_info(&pdev->dev, - "%s: %s NIC Link is Down\n", - atl1c_driver_name, netdev->name); - adapter->link_speed = SPEED_0; - } - } - - set_bit(ATL1C_WORK_EVENT_LINK_CHANGE, &adapter->work_event); - schedule_work(&adapter->common_task); -} - -static void atl1c_common_task(struct work_struct *work) -{ - struct atl1c_adapter *adapter; - struct net_device *netdev; - - adapter = container_of(work, struct atl1c_adapter, common_task); - netdev = adapter->netdev; - - if (test_bit(__AT_DOWN, &adapter->flags)) - return; - - if (test_and_clear_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event)) { - netif_device_detach(netdev); - atl1c_down(adapter); - atl1c_up(adapter); - netif_device_attach(netdev); - } - - if (test_and_clear_bit(ATL1C_WORK_EVENT_LINK_CHANGE, - &adapter->work_event)) { - atl1c_irq_disable(adapter); - atl1c_check_link_status(adapter); - atl1c_irq_enable(adapter); - } -} - - -static void atl1c_del_timer(struct atl1c_adapter *adapter) -{ - del_timer_sync(&adapter->phy_config_timer); -} - - -/** - * atl1c_tx_timeout - Respond to a Tx Hang - * @netdev: network interface device structure - */ -static void atl1c_tx_timeout(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - /* Do the reset outside of interrupt context */ - set_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event); - schedule_work(&adapter->common_task); -} - -/** - * atl1c_set_multi - Multicast and Promiscuous mode set - * @netdev: network interface device structure - * - * The set_multi entry point is called whenever the multicast address - * list or the network interface flags are updated. This routine is - * responsible for configuring the hardware for proper multicast, - * promiscuous mode, and all-multi behavior. - */ -static void atl1c_set_multi(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - struct netdev_hw_addr *ha; - u32 mac_ctrl_data; - u32 hash_value; - - /* Check for Promiscuous and All Multicast modes */ - AT_READ_REG(hw, REG_MAC_CTRL, &mac_ctrl_data); - - if (netdev->flags & IFF_PROMISC) { - mac_ctrl_data |= MAC_CTRL_PROMIS_EN; - } else if (netdev->flags & IFF_ALLMULTI) { - mac_ctrl_data |= MAC_CTRL_MC_ALL_EN; - mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN; - } else { - mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN); - } - - AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); - - /* clear the old settings from the multicast hash table */ - AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); - AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); - - /* comoute mc addresses' hash value ,and put it into hash table */ - netdev_for_each_mc_addr(ha, netdev) { - hash_value = atl1c_hash_mc_addr(hw, ha->addr); - atl1c_hash_set(hw, hash_value); - } -} - -static void __atl1c_vlan_mode(netdev_features_t features, u32 *mac_ctrl_data) -{ - if (features & NETIF_F_HW_VLAN_CTAG_RX) { - /* enable VLAN tag insert/strip */ - *mac_ctrl_data |= MAC_CTRL_RMV_VLAN; - } else { - /* disable VLAN tag insert/strip */ - *mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN; - } -} - -static void atl1c_vlan_mode(struct net_device *netdev, - netdev_features_t features) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct pci_dev *pdev = adapter->pdev; - u32 mac_ctrl_data = 0; - - if (netif_msg_pktdata(adapter)) - dev_dbg(&pdev->dev, "atl1c_vlan_mode\n"); - - atl1c_irq_disable(adapter); - AT_READ_REG(&adapter->hw, REG_MAC_CTRL, &mac_ctrl_data); - __atl1c_vlan_mode(features, &mac_ctrl_data); - AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data); - atl1c_irq_enable(adapter); -} - -static void atl1c_restore_vlan(struct atl1c_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - - if (netif_msg_pktdata(adapter)) - dev_dbg(&pdev->dev, "atl1c_restore_vlan\n"); - atl1c_vlan_mode(adapter->netdev, adapter->netdev->features); -} - -/** - * atl1c_set_mac - Change the Ethernet Address of the NIC - * @netdev: network interface device structure - * @p: pointer to an address structure - * - * Returns 0 on success, negative on failure - */ -static int atl1c_set_mac_addr(struct net_device *netdev, void *p) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - if (netif_running(netdev)) - return -EBUSY; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); - - atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr); - - return 0; -} - -static void atl1c_set_rxbufsize(struct atl1c_adapter *adapter, - struct net_device *dev) -{ - unsigned int head_size; - int mtu = dev->mtu; - - adapter->rx_buffer_len = mtu > AT_RX_BUF_SIZE ? - roundup(mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN, 8) : AT_RX_BUF_SIZE; - - head_size = SKB_DATA_ALIGN(adapter->rx_buffer_len + NET_SKB_PAD) + - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); - adapter->rx_frag_size = roundup_pow_of_two(head_size); -} - -static netdev_features_t atl1c_fix_features(struct net_device *netdev, - netdev_features_t 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_CTAG_RX) - features |= NETIF_F_HW_VLAN_CTAG_TX; - else - features &= ~NETIF_F_HW_VLAN_CTAG_TX; - - if (netdev->mtu > MAX_TSO_FRAME_SIZE) - features &= ~(NETIF_F_TSO | NETIF_F_TSO6); - - return features; -} - -static int atl1c_set_features(struct net_device *netdev, - netdev_features_t features) -{ - netdev_features_t changed = netdev->features ^ features; - - if (changed & NETIF_F_HW_VLAN_CTAG_RX) - atl1c_vlan_mode(netdev, features); - - return 0; -} - -/** - * atl1c_change_mtu - Change the Maximum Transfer Unit - * @netdev: network interface device structure - * @new_mtu: new value for maximum frame size - * - * Returns 0 on success, negative on failure - */ -static int atl1c_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - int old_mtu = netdev->mtu; - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; - - /* Fast Ethernet controller doesn't support jumbo packet */ - if (((hw->nic_type == athr_l2c || - hw->nic_type == athr_l2c_b || - hw->nic_type == athr_l2c_b2) && new_mtu > ETH_DATA_LEN) || - max_frame < ETH_ZLEN + ETH_FCS_LEN || - max_frame > MAX_JUMBO_FRAME_SIZE) { - if (netif_msg_link(adapter)) - dev_warn(&adapter->pdev->dev, "invalid MTU setting\n"); - return -EINVAL; - } - /* set MTU */ - if (old_mtu != new_mtu && netif_running(netdev)) { - while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) - msleep(1); - netdev->mtu = new_mtu; - adapter->hw.max_frame_size = new_mtu; - atl1c_set_rxbufsize(adapter, netdev); - atl1c_down(adapter); - netdev_update_features(netdev); - atl1c_up(adapter); - clear_bit(__AT_RESETTING, &adapter->flags); - } - return 0; -} - -/* - * caller should hold mdio_lock - */ -static int atl1c_mdio_read(struct net_device *netdev, int phy_id, int reg_num) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - u16 result; - - atl1c_read_phy_reg(&adapter->hw, reg_num, &result); - return result; -} - -static void atl1c_mdio_write(struct net_device *netdev, int phy_id, - int reg_num, int val) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - atl1c_write_phy_reg(&adapter->hw, reg_num, val); -} - -static int atl1c_mii_ioctl(struct net_device *netdev, - struct ifreq *ifr, int cmd) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct pci_dev *pdev = adapter->pdev; - struct mii_ioctl_data *data = if_mii(ifr); - unsigned long flags; - int retval = 0; - - if (!netif_running(netdev)) - return -EINVAL; - - spin_lock_irqsave(&adapter->mdio_lock, flags); - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 0; - break; - - case SIOCGMIIREG: - if (atl1c_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, - &data->val_out)) { - retval = -EIO; - goto out; - } - break; - - case SIOCSMIIREG: - if (data->reg_num & ~(0x1F)) { - retval = -EFAULT; - goto out; - } - - dev_dbg(&pdev->dev, " write %x %x", - data->reg_num, data->val_in); - if (atl1c_write_phy_reg(&adapter->hw, - data->reg_num, data->val_in)) { - retval = -EIO; - goto out; - } - break; - - default: - retval = -EOPNOTSUPP; - break; - } -out: - spin_unlock_irqrestore(&adapter->mdio_lock, flags); - return retval; -} - -static int atl1c_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return atl1c_mii_ioctl(netdev, ifr, cmd); - default: - return -EOPNOTSUPP; - } -} - -/** - * atl1c_alloc_queues - Allocate memory for all rings - * @adapter: board private structure to initialize - * - */ -static int atl1c_alloc_queues(struct atl1c_adapter *adapter) -{ - return 0; -} - -static void atl1c_set_mac_type(struct atl1c_hw *hw) -{ - switch (hw->device_id) { - case PCI_DEVICE_ID_ATTANSIC_L2C: - hw->nic_type = athr_l2c; - break; - case PCI_DEVICE_ID_ATTANSIC_L1C: - hw->nic_type = athr_l1c; - break; - case PCI_DEVICE_ID_ATHEROS_L2C_B: - hw->nic_type = athr_l2c_b; - break; - case PCI_DEVICE_ID_ATHEROS_L2C_B2: - hw->nic_type = athr_l2c_b2; - break; - case PCI_DEVICE_ID_ATHEROS_L1D: - hw->nic_type = athr_l1d; - break; - case PCI_DEVICE_ID_ATHEROS_L1D_2_0: - hw->nic_type = athr_l1d_2; - break; - default: - break; - } -} - -static int atl1c_setup_mac_funcs(struct atl1c_hw *hw) -{ - u32 link_ctrl_data; - - atl1c_set_mac_type(hw); - AT_READ_REG(hw, REG_LINK_CTRL, &link_ctrl_data); - - hw->ctrl_flags = ATL1C_INTR_MODRT_ENABLE | - ATL1C_TXQ_MODE_ENHANCE; - hw->ctrl_flags |= ATL1C_ASPM_L0S_SUPPORT | - ATL1C_ASPM_L1_SUPPORT; - hw->ctrl_flags |= ATL1C_ASPM_CTRL_MON; - - if (hw->nic_type == athr_l1c || - hw->nic_type == athr_l1d || - hw->nic_type == athr_l1d_2) - hw->link_cap_flags |= ATL1C_LINK_CAP_1000M; - return 0; -} - -struct atl1c_platform_patch { - u16 pci_did; - u8 pci_revid; - u16 subsystem_vid; - u16 subsystem_did; - u32 patch_flag; -#define ATL1C_LINK_PATCH 0x1 -}; -static const struct atl1c_platform_patch plats[] = { -{0x2060, 0xC1, 0x1019, 0x8152, 0x1}, -{0x2060, 0xC1, 0x1019, 0x2060, 0x1}, -{0x2060, 0xC1, 0x1019, 0xE000, 0x1}, -{0x2062, 0xC0, 0x1019, 0x8152, 0x1}, -{0x2062, 0xC0, 0x1019, 0x2062, 0x1}, -{0x2062, 0xC0, 0x1458, 0xE000, 0x1}, -{0x2062, 0xC1, 0x1019, 0x8152, 0x1}, -{0x2062, 0xC1, 0x1019, 0x2062, 0x1}, -{0x2062, 0xC1, 0x1458, 0xE000, 0x1}, -{0x2062, 0xC1, 0x1565, 0x2802, 0x1}, -{0x2062, 0xC1, 0x1565, 0x2801, 0x1}, -{0x1073, 0xC0, 0x1019, 0x8151, 0x1}, -{0x1073, 0xC0, 0x1019, 0x1073, 0x1}, -{0x1073, 0xC0, 0x1458, 0xE000, 0x1}, -{0x1083, 0xC0, 0x1458, 0xE000, 0x1}, -{0x1083, 0xC0, 0x1019, 0x8151, 0x1}, -{0x1083, 0xC0, 0x1019, 0x1083, 0x1}, -{0x1083, 0xC0, 0x1462, 0x7680, 0x1}, -{0x1083, 0xC0, 0x1565, 0x2803, 0x1}, -{0}, -}; - -static void atl1c_patch_assign(struct atl1c_hw *hw) -{ - struct pci_dev *pdev = hw->adapter->pdev; - u32 misc_ctrl; - int i = 0; - - hw->msi_lnkpatch = false; - - while (plats[i].pci_did != 0) { - if (plats[i].pci_did == hw->device_id && - plats[i].pci_revid == hw->revision_id && - plats[i].subsystem_vid == hw->subsystem_vendor_id && - plats[i].subsystem_did == hw->subsystem_id) { - if (plats[i].patch_flag & ATL1C_LINK_PATCH) - hw->msi_lnkpatch = true; - } - i++; - } - - if (hw->device_id == PCI_DEVICE_ID_ATHEROS_L2C_B2 && - hw->revision_id == L2CB_V21) { - /* config access mode */ - pci_write_config_dword(pdev, REG_PCIE_IND_ACC_ADDR, - REG_PCIE_DEV_MISC_CTRL); - pci_read_config_dword(pdev, REG_PCIE_IND_ACC_DATA, &misc_ctrl); - misc_ctrl &= ~0x100; - pci_write_config_dword(pdev, REG_PCIE_IND_ACC_ADDR, - REG_PCIE_DEV_MISC_CTRL); - pci_write_config_dword(pdev, REG_PCIE_IND_ACC_DATA, misc_ctrl); - } -} -/** - * atl1c_sw_init - Initialize general software structures (struct atl1c_adapter) - * @adapter: board private structure to initialize - * - * atl1c_sw_init initializes the Adapter private data structure. - * Fields are initialized based on PCI device information and - * OS network device settings (MTU size). - */ -static int atl1c_sw_init(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - struct pci_dev *pdev = adapter->pdev; - u32 revision; - - - adapter->wol = 0; - device_set_wakeup_enable(&pdev->dev, false); - adapter->link_speed = SPEED_0; - adapter->link_duplex = FULL_DUPLEX; - adapter->tpd_ring[0].count = 1024; - adapter->rfd_ring.count = 512; - - hw->vendor_id = pdev->vendor; - hw->device_id = pdev->device; - hw->subsystem_vendor_id = pdev->subsystem_vendor; - hw->subsystem_id = pdev->subsystem_device; - pci_read_config_dword(pdev, PCI_CLASS_REVISION, &revision); - hw->revision_id = revision & 0xFF; - /* before link up, we assume hibernate is true */ - hw->hibernate = true; - hw->media_type = MEDIA_TYPE_AUTO_SENSOR; - if (atl1c_setup_mac_funcs(hw) != 0) { - dev_err(&pdev->dev, "set mac function pointers failed\n"); - return -1; - } - atl1c_patch_assign(hw); - - hw->intr_mask = IMR_NORMAL_MASK; - hw->phy_configured = false; - hw->preamble_len = 7; - hw->max_frame_size = adapter->netdev->mtu; - hw->autoneg_advertised = ADVERTISED_Autoneg; - hw->indirect_tab = 0xE4E4E4E4; - hw->base_cpu = 0; - - hw->ict = 50000; /* 100ms */ - hw->smb_timer = 200000; /* 400ms */ - hw->rx_imt = 200; - hw->tx_imt = 1000; - - hw->tpd_burst = 5; - hw->rfd_burst = 8; - hw->dma_order = atl1c_dma_ord_out; - hw->dmar_block = atl1c_dma_req_1024; - - if (atl1c_alloc_queues(adapter)) { - dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); - return -ENOMEM; - } - /* TODO */ - atl1c_set_rxbufsize(adapter, adapter->netdev); - atomic_set(&adapter->irq_sem, 1); - spin_lock_init(&adapter->mdio_lock); - spin_lock_init(&adapter->tx_lock); - set_bit(__AT_DOWN, &adapter->flags); - - return 0; -} - -static inline void atl1c_clean_buffer(struct pci_dev *pdev, - struct atl1c_buffer *buffer_info) -{ - u16 pci_driection; - if (buffer_info->flags & ATL1C_BUFFER_FREE) - return; - if (buffer_info->dma) { - if (buffer_info->flags & ATL1C_PCIMAP_FROMDEVICE) - pci_driection = PCI_DMA_FROMDEVICE; - else - pci_driection = PCI_DMA_TODEVICE; - - if (buffer_info->flags & ATL1C_PCIMAP_SINGLE) - pci_unmap_single(pdev, buffer_info->dma, - buffer_info->length, pci_driection); - else if (buffer_info->flags & ATL1C_PCIMAP_PAGE) - pci_unmap_page(pdev, buffer_info->dma, - buffer_info->length, pci_driection); - } - if (buffer_info->skb) - dev_consume_skb_any(buffer_info->skb); - buffer_info->dma = 0; - buffer_info->skb = NULL; - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); -} -/** - * atl1c_clean_tx_ring - Free Tx-skb - * @adapter: board private structure - */ -static void atl1c_clean_tx_ring(struct atl1c_adapter *adapter, - enum atl1c_trans_queue type) -{ - struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; - struct atl1c_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - u16 index, ring_count; - - ring_count = tpd_ring->count; - for (index = 0; index < ring_count; index++) { - buffer_info = &tpd_ring->buffer_info[index]; - atl1c_clean_buffer(pdev, buffer_info); - } - - netdev_reset_queue(adapter->netdev); - - /* Zero out Tx-buffers */ - memset(tpd_ring->desc, 0, sizeof(struct atl1c_tpd_desc) * - ring_count); - atomic_set(&tpd_ring->next_to_clean, 0); - tpd_ring->next_to_use = 0; -} - -/** - * atl1c_clean_rx_ring - Free rx-reservation skbs - * @adapter: board private structure - */ -static void atl1c_clean_rx_ring(struct atl1c_adapter *adapter) -{ - struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1c_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - int j; - - for (j = 0; j < rfd_ring->count; j++) { - buffer_info = &rfd_ring->buffer_info[j]; - atl1c_clean_buffer(pdev, buffer_info); - } - /* zero out the descriptor ring */ - memset(rfd_ring->desc, 0, rfd_ring->size); - rfd_ring->next_to_clean = 0; - rfd_ring->next_to_use = 0; - rrd_ring->next_to_use = 0; - rrd_ring->next_to_clean = 0; -} - -/* - * Read / Write Ptr Initialize: - */ -static void atl1c_init_ring_ptrs(struct atl1c_adapter *adapter) -{ - struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; - struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1c_buffer *buffer_info; - int i, j; - - for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) { - tpd_ring[i].next_to_use = 0; - atomic_set(&tpd_ring[i].next_to_clean, 0); - buffer_info = tpd_ring[i].buffer_info; - for (j = 0; j < tpd_ring->count; j++) - ATL1C_SET_BUFFER_STATE(&buffer_info[i], - ATL1C_BUFFER_FREE); - } - rfd_ring->next_to_use = 0; - rfd_ring->next_to_clean = 0; - rrd_ring->next_to_use = 0; - rrd_ring->next_to_clean = 0; - for (j = 0; j < rfd_ring->count; j++) { - buffer_info = &rfd_ring->buffer_info[j]; - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); - } -} - -/** - * atl1c_free_ring_resources - Free Tx / RX descriptor Resources - * @adapter: board private structure - * - * Free all transmit software resources - */ -static void atl1c_free_ring_resources(struct atl1c_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - - pci_free_consistent(pdev, adapter->ring_header.size, - adapter->ring_header.desc, - adapter->ring_header.dma); - adapter->ring_header.desc = NULL; - - /* Note: just free tdp_ring.buffer_info, - * it contain rfd_ring.buffer_info, do not double free */ - if (adapter->tpd_ring[0].buffer_info) { - kfree(adapter->tpd_ring[0].buffer_info); - adapter->tpd_ring[0].buffer_info = NULL; - } - if (adapter->rx_page) { - put_page(adapter->rx_page); - adapter->rx_page = NULL; - } -} - -/** - * atl1c_setup_mem_resources - allocate Tx / RX descriptor resources - * @adapter: board private structure - * - * Return 0 on success, negative on failure - */ -static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; - struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1c_ring_header *ring_header = &adapter->ring_header; - int size; - int i; - int count = 0; - int rx_desc_count = 0; - u32 offset = 0; - - rrd_ring->count = rfd_ring->count; - for (i = 1; i < AT_MAX_TRANSMIT_QUEUE; i++) - tpd_ring[i].count = tpd_ring[0].count; - - /* 2 tpd queue, one high priority queue, - * another normal priority queue */ - size = sizeof(struct atl1c_buffer) * (tpd_ring->count * 2 + - rfd_ring->count); - tpd_ring->buffer_info = kzalloc(size, GFP_KERNEL); - if (unlikely(!tpd_ring->buffer_info)) - goto err_nomem; - - for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) { - tpd_ring[i].buffer_info = - (tpd_ring->buffer_info + count); - count += tpd_ring[i].count; - } - - rfd_ring->buffer_info = - (tpd_ring->buffer_info + count); - count += rfd_ring->count; - rx_desc_count += rfd_ring->count; - - /* - * real ring DMA buffer - * each ring/block may need up to 8 bytes for alignment, hence the - * additional bytes tacked onto the end. - */ - ring_header->size = size = - sizeof(struct atl1c_tpd_desc) * tpd_ring->count * 2 + - sizeof(struct atl1c_rx_free_desc) * rx_desc_count + - sizeof(struct atl1c_recv_ret_status) * rx_desc_count + - 8 * 4; - - ring_header->desc = dma_zalloc_coherent(&pdev->dev, ring_header->size, - &ring_header->dma, GFP_KERNEL); - if (unlikely(!ring_header->desc)) { - dev_err(&pdev->dev, "could not get memory for DMA buffer\n"); - goto err_nomem; - } - /* init TPD ring */ - - tpd_ring[0].dma = roundup(ring_header->dma, 8); - offset = tpd_ring[0].dma - ring_header->dma; - for (i = 0; i < AT_MAX_TRANSMIT_QUEUE; i++) { - tpd_ring[i].dma = ring_header->dma + offset; - tpd_ring[i].desc = (u8 *) ring_header->desc + offset; - tpd_ring[i].size = - sizeof(struct atl1c_tpd_desc) * tpd_ring[i].count; - offset += roundup(tpd_ring[i].size, 8); - } - /* init RFD ring */ - rfd_ring->dma = ring_header->dma + offset; - rfd_ring->desc = (u8 *) ring_header->desc + offset; - rfd_ring->size = sizeof(struct atl1c_rx_free_desc) * rfd_ring->count; - offset += roundup(rfd_ring->size, 8); - - /* init RRD ring */ - rrd_ring->dma = ring_header->dma + offset; - rrd_ring->desc = (u8 *) ring_header->desc + offset; - rrd_ring->size = sizeof(struct atl1c_recv_ret_status) * - rrd_ring->count; - offset += roundup(rrd_ring->size, 8); - - return 0; - -err_nomem: - kfree(tpd_ring->buffer_info); - return -ENOMEM; -} - -static void atl1c_configure_des_ring(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct atl1c_tpd_ring *tpd_ring = (struct atl1c_tpd_ring *) - adapter->tpd_ring; - - /* TPD */ - AT_WRITE_REG(hw, REG_TX_BASE_ADDR_HI, - (u32)((tpd_ring[atl1c_trans_normal].dma & - AT_DMA_HI_ADDR_MASK) >> 32)); - /* just enable normal priority TX queue */ - AT_WRITE_REG(hw, REG_TPD_PRI0_ADDR_LO, - (u32)(tpd_ring[atl1c_trans_normal].dma & - AT_DMA_LO_ADDR_MASK)); - AT_WRITE_REG(hw, REG_TPD_PRI1_ADDR_LO, - (u32)(tpd_ring[atl1c_trans_high].dma & - AT_DMA_LO_ADDR_MASK)); - AT_WRITE_REG(hw, REG_TPD_RING_SIZE, - (u32)(tpd_ring[0].count & TPD_RING_SIZE_MASK)); - - - /* RFD */ - AT_WRITE_REG(hw, REG_RX_BASE_ADDR_HI, - (u32)((rfd_ring->dma & AT_DMA_HI_ADDR_MASK) >> 32)); - AT_WRITE_REG(hw, REG_RFD0_HEAD_ADDR_LO, - (u32)(rfd_ring->dma & AT_DMA_LO_ADDR_MASK)); - - AT_WRITE_REG(hw, REG_RFD_RING_SIZE, - rfd_ring->count & RFD_RING_SIZE_MASK); - AT_WRITE_REG(hw, REG_RX_BUF_SIZE, - adapter->rx_buffer_len & RX_BUF_SIZE_MASK); - - /* RRD */ - AT_WRITE_REG(hw, REG_RRD0_HEAD_ADDR_LO, - (u32)(rrd_ring->dma & AT_DMA_LO_ADDR_MASK)); - AT_WRITE_REG(hw, REG_RRD_RING_SIZE, - (rrd_ring->count & RRD_RING_SIZE_MASK)); - - if (hw->nic_type == athr_l2c_b) { - AT_WRITE_REG(hw, REG_SRAM_RXF_LEN, 0x02a0L); - AT_WRITE_REG(hw, REG_SRAM_TXF_LEN, 0x0100L); - AT_WRITE_REG(hw, REG_SRAM_RXF_ADDR, 0x029f0000L); - AT_WRITE_REG(hw, REG_SRAM_RFD0_INFO, 0x02bf02a0L); - AT_WRITE_REG(hw, REG_SRAM_TXF_ADDR, 0x03bf02c0L); - AT_WRITE_REG(hw, REG_SRAM_TRD_ADDR, 0x03df03c0L); - AT_WRITE_REG(hw, REG_TXF_WATER_MARK, 0); /* TX watermark, to enter l1 state.*/ - AT_WRITE_REG(hw, REG_RXD_DMA_CTRL, 0); /* RXD threshold.*/ - } - /* Load all of base address above */ - AT_WRITE_REG(hw, REG_LOAD_PTR, 1); -} - -static void atl1c_configure_tx(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - int max_pay_load; - u16 tx_offload_thresh; - u32 txq_ctrl_data; - - tx_offload_thresh = MAX_TSO_FRAME_SIZE; - AT_WRITE_REG(hw, REG_TX_TSO_OFFLOAD_THRESH, - (tx_offload_thresh >> 3) & TX_TSO_OFFLOAD_THRESH_MASK); - max_pay_load = pcie_get_readrq(adapter->pdev) >> 8; - hw->dmar_block = min_t(u32, max_pay_load, hw->dmar_block); - /* - * if BIOS had changed the dam-read-max-length to an invalid value, - * restore it to default value - */ - if (hw->dmar_block < DEVICE_CTRL_MAXRRS_MIN) { - pcie_set_readrq(adapter->pdev, 128 << DEVICE_CTRL_MAXRRS_MIN); - hw->dmar_block = DEVICE_CTRL_MAXRRS_MIN; - } - txq_ctrl_data = - hw->nic_type == athr_l2c_b || hw->nic_type == athr_l2c_b2 ? - L2CB_TXQ_CFGV : L1C_TXQ_CFGV; - - AT_WRITE_REG(hw, REG_TXQ_CTRL, txq_ctrl_data); -} - -static void atl1c_configure_rx(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - u32 rxq_ctrl_data; - - rxq_ctrl_data = (hw->rfd_burst & RXQ_RFD_BURST_NUM_MASK) << - RXQ_RFD_BURST_NUM_SHIFT; - - if (hw->ctrl_flags & ATL1C_RX_IPV6_CHKSUM) - rxq_ctrl_data |= IPV6_CHKSUM_CTRL_EN; - - /* aspm for gigabit */ - if (hw->nic_type != athr_l1d_2 && (hw->device_id & 1) != 0) - rxq_ctrl_data = FIELD_SETX(rxq_ctrl_data, ASPM_THRUPUT_LIMIT, - ASPM_THRUPUT_LIMIT_100M); - - AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data); -} - -static void atl1c_configure_dma(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - u32 dma_ctrl_data; - - dma_ctrl_data = FIELDX(DMA_CTRL_RORDER_MODE, DMA_CTRL_RORDER_MODE_OUT) | - DMA_CTRL_RREQ_PRI_DATA | - FIELDX(DMA_CTRL_RREQ_BLEN, hw->dmar_block) | - FIELDX(DMA_CTRL_WDLY_CNT, DMA_CTRL_WDLY_CNT_DEF) | - FIELDX(DMA_CTRL_RDLY_CNT, DMA_CTRL_RDLY_CNT_DEF); - - AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data); -} - -/* - * Stop the mac, transmit and receive units - * hw - Struct containing variables accessed by shared code - * return : 0 or idle status (if error) - */ -static int atl1c_stop_mac(struct atl1c_hw *hw) -{ - u32 data; - - AT_READ_REG(hw, REG_RXQ_CTRL, &data); - data &= ~RXQ_CTRL_EN; - AT_WRITE_REG(hw, REG_RXQ_CTRL, data); - - AT_READ_REG(hw, REG_TXQ_CTRL, &data); - data &= ~TXQ_CTRL_EN; - AT_WRITE_REG(hw, REG_TXQ_CTRL, data); - - atl1c_wait_until_idle(hw, IDLE_STATUS_RXQ_BUSY | IDLE_STATUS_TXQ_BUSY); - - AT_READ_REG(hw, REG_MAC_CTRL, &data); - data &= ~(MAC_CTRL_TX_EN | MAC_CTRL_RX_EN); - AT_WRITE_REG(hw, REG_MAC_CTRL, data); - - return (int)atl1c_wait_until_idle(hw, - IDLE_STATUS_TXMAC_BUSY | IDLE_STATUS_RXMAC_BUSY); -} - -static void atl1c_start_mac(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - u32 mac, txq, rxq; - - hw->mac_duplex = adapter->link_duplex == FULL_DUPLEX ? true : false; - hw->mac_speed = adapter->link_speed == SPEED_1000 ? - atl1c_mac_speed_1000 : atl1c_mac_speed_10_100; - - AT_READ_REG(hw, REG_TXQ_CTRL, &txq); - AT_READ_REG(hw, REG_RXQ_CTRL, &rxq); - AT_READ_REG(hw, REG_MAC_CTRL, &mac); - - txq |= TXQ_CTRL_EN; - rxq |= RXQ_CTRL_EN; - mac |= MAC_CTRL_TX_EN | MAC_CTRL_TX_FLOW | - MAC_CTRL_RX_EN | MAC_CTRL_RX_FLOW | - MAC_CTRL_ADD_CRC | MAC_CTRL_PAD | - MAC_CTRL_BC_EN | MAC_CTRL_SINGLE_PAUSE_EN | - MAC_CTRL_HASH_ALG_CRC32; - if (hw->mac_duplex) - mac |= MAC_CTRL_DUPLX; - else - mac &= ~MAC_CTRL_DUPLX; - mac = FIELD_SETX(mac, MAC_CTRL_SPEED, hw->mac_speed); - mac = FIELD_SETX(mac, MAC_CTRL_PRMLEN, hw->preamble_len); - - AT_WRITE_REG(hw, REG_TXQ_CTRL, txq); - AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq); - AT_WRITE_REG(hw, REG_MAC_CTRL, mac); -} - -/* - * Reset the transmit and receive units; mask and clear all interrupts. - * hw - Struct containing variables accessed by shared code - * return : 0 or idle status (if error) - */ -static int atl1c_reset_mac(struct atl1c_hw *hw) -{ - struct atl1c_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; - u32 ctrl_data = 0; - - atl1c_stop_mac(hw); - /* - * Issue Soft Reset to the MAC. This will reset the chip's - * transmit, receive, DMA. It will not effect - * the current PCI configuration. The global reset bit is self- - * clearing, and should clear within a microsecond. - */ - AT_READ_REG(hw, REG_MASTER_CTRL, &ctrl_data); - ctrl_data |= MASTER_CTRL_OOB_DIS; - AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data | MASTER_CTRL_SOFT_RST); - - AT_WRITE_FLUSH(hw); - msleep(10); - /* Wait at least 10ms for All module to be Idle */ - - if (atl1c_wait_until_idle(hw, IDLE_STATUS_MASK)) { - dev_err(&pdev->dev, - "MAC state machine can't be idle since" - " disabled for 10ms second\n"); - return -1; - } - AT_WRITE_REG(hw, REG_MASTER_CTRL, ctrl_data); - - /* driver control speed/duplex */ - AT_READ_REG(hw, REG_MAC_CTRL, &ctrl_data); - AT_WRITE_REG(hw, REG_MAC_CTRL, ctrl_data | MAC_CTRL_SPEED_MODE_SW); - - /* clk switch setting */ - AT_READ_REG(hw, REG_SERDES, &ctrl_data); - switch (hw->nic_type) { - case athr_l2c_b: - ctrl_data &= ~(SERDES_PHY_CLK_SLOWDOWN | - SERDES_MAC_CLK_SLOWDOWN); - AT_WRITE_REG(hw, REG_SERDES, ctrl_data); - break; - case athr_l2c_b2: - case athr_l1d_2: - ctrl_data |= SERDES_PHY_CLK_SLOWDOWN | SERDES_MAC_CLK_SLOWDOWN; - AT_WRITE_REG(hw, REG_SERDES, ctrl_data); - break; - default: - break; - } - - return 0; -} - -static void atl1c_disable_l0s_l1(struct atl1c_hw *hw) -{ - u16 ctrl_flags = hw->ctrl_flags; - - hw->ctrl_flags &= ~(ATL1C_ASPM_L0S_SUPPORT | ATL1C_ASPM_L1_SUPPORT); - atl1c_set_aspm(hw, SPEED_0); - hw->ctrl_flags = ctrl_flags; -} - -/* - * Set ASPM state. - * Enable/disable L0s/L1 depend on link state. - */ -static void atl1c_set_aspm(struct atl1c_hw *hw, u16 link_speed) -{ - u32 pm_ctrl_data; - u32 link_l1_timer; - - AT_READ_REG(hw, REG_PM_CTRL, &pm_ctrl_data); - pm_ctrl_data &= ~(PM_CTRL_ASPM_L1_EN | - PM_CTRL_ASPM_L0S_EN | - PM_CTRL_MAC_ASPM_CHK); - /* L1 timer */ - if (hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { - pm_ctrl_data &= ~PMCTRL_TXL1_AFTER_L0S; - link_l1_timer = - link_speed == SPEED_1000 || link_speed == SPEED_100 ? - L1D_PMCTRL_L1_ENTRY_TM_16US : 1; - pm_ctrl_data = FIELD_SETX(pm_ctrl_data, - L1D_PMCTRL_L1_ENTRY_TM, link_l1_timer); - } else { - link_l1_timer = hw->nic_type == athr_l2c_b ? - L2CB1_PM_CTRL_L1_ENTRY_TM : L1C_PM_CTRL_L1_ENTRY_TM; - if (link_speed != SPEED_1000 && link_speed != SPEED_100) - link_l1_timer = 1; - pm_ctrl_data = FIELD_SETX(pm_ctrl_data, - PM_CTRL_L1_ENTRY_TIMER, link_l1_timer); - } - - /* L0S/L1 enable */ - if ((hw->ctrl_flags & ATL1C_ASPM_L0S_SUPPORT) && link_speed != SPEED_0) - pm_ctrl_data |= PM_CTRL_ASPM_L0S_EN | PM_CTRL_MAC_ASPM_CHK; - if (hw->ctrl_flags & ATL1C_ASPM_L1_SUPPORT) - pm_ctrl_data |= PM_CTRL_ASPM_L1_EN | PM_CTRL_MAC_ASPM_CHK; - - /* l2cb & l1d & l2cb2 & l1d2 */ - if (hw->nic_type == athr_l2c_b || hw->nic_type == athr_l1d || - hw->nic_type == athr_l2c_b2 || hw->nic_type == athr_l1d_2) { - pm_ctrl_data = FIELD_SETX(pm_ctrl_data, - PM_CTRL_PM_REQ_TIMER, PM_CTRL_PM_REQ_TO_DEF); - pm_ctrl_data |= PM_CTRL_RCVR_WT_TIMER | - PM_CTRL_SERDES_PD_EX_L1 | - PM_CTRL_CLK_SWH_L1; - pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN | - PM_CTRL_SERDES_PLL_L1_EN | - PM_CTRL_SERDES_BUFS_RX_L1_EN | - PM_CTRL_SA_DLY_EN | - PM_CTRL_HOTRST); - /* disable l0s if link down or l2cb */ - if (link_speed == SPEED_0 || hw->nic_type == athr_l2c_b) - pm_ctrl_data &= ~PM_CTRL_ASPM_L0S_EN; - } else { /* l1c */ - pm_ctrl_data = - FIELD_SETX(pm_ctrl_data, PM_CTRL_L1_ENTRY_TIMER, 0); - if (link_speed != SPEED_0) { - pm_ctrl_data |= PM_CTRL_SERDES_L1_EN | - PM_CTRL_SERDES_PLL_L1_EN | - PM_CTRL_SERDES_BUFS_RX_L1_EN; - pm_ctrl_data &= ~(PM_CTRL_SERDES_PD_EX_L1 | - PM_CTRL_CLK_SWH_L1 | - PM_CTRL_ASPM_L0S_EN | - PM_CTRL_ASPM_L1_EN); - } else { /* link down */ - pm_ctrl_data |= PM_CTRL_CLK_SWH_L1; - pm_ctrl_data &= ~(PM_CTRL_SERDES_L1_EN | - PM_CTRL_SERDES_PLL_L1_EN | - PM_CTRL_SERDES_BUFS_RX_L1_EN | - PM_CTRL_ASPM_L0S_EN); - } - } - AT_WRITE_REG(hw, REG_PM_CTRL, pm_ctrl_data); - - return; -} - -/** - * atl1c_configure - Configure Transmit&Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Tx /Rx unit of the MAC after a reset. - */ -static int atl1c_configure_mac(struct atl1c_adapter *adapter) -{ - struct atl1c_hw *hw = &adapter->hw; - u32 master_ctrl_data = 0; - u32 intr_modrt_data; - u32 data; - - AT_READ_REG(hw, REG_MASTER_CTRL, &master_ctrl_data); - master_ctrl_data &= ~(MASTER_CTRL_TX_ITIMER_EN | - MASTER_CTRL_RX_ITIMER_EN | - MASTER_CTRL_INT_RDCLR); - /* clear interrupt status */ - AT_WRITE_REG(hw, REG_ISR, 0xFFFFFFFF); - /* Clear any WOL status */ - AT_WRITE_REG(hw, REG_WOL_CTRL, 0); - /* set Interrupt Clear Timer - * HW will enable self to assert interrupt event to system after - * waiting x-time for software to notify it accept interrupt. - */ - - data = CLK_GATING_EN_ALL; - if (hw->ctrl_flags & ATL1C_CLK_GATING_EN) { - if (hw->nic_type == athr_l2c_b) - data &= ~CLK_GATING_RXMAC_EN; - } else - data = 0; - AT_WRITE_REG(hw, REG_CLK_GATING_CTRL, data); - - AT_WRITE_REG(hw, REG_INT_RETRIG_TIMER, - hw->ict & INT_RETRIG_TIMER_MASK); - - atl1c_configure_des_ring(adapter); - - if (hw->ctrl_flags & ATL1C_INTR_MODRT_ENABLE) { - intr_modrt_data = (hw->tx_imt & IRQ_MODRT_TIMER_MASK) << - IRQ_MODRT_TX_TIMER_SHIFT; - intr_modrt_data |= (hw->rx_imt & IRQ_MODRT_TIMER_MASK) << - IRQ_MODRT_RX_TIMER_SHIFT; - AT_WRITE_REG(hw, REG_IRQ_MODRT_TIMER_INIT, intr_modrt_data); - master_ctrl_data |= - MASTER_CTRL_TX_ITIMER_EN | MASTER_CTRL_RX_ITIMER_EN; - } - - if (hw->ctrl_flags & ATL1C_INTR_CLEAR_ON_READ) - master_ctrl_data |= MASTER_CTRL_INT_RDCLR; - - master_ctrl_data |= MASTER_CTRL_SA_TIMER_EN; - AT_WRITE_REG(hw, REG_MASTER_CTRL, master_ctrl_data); - - AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, - hw->smb_timer & SMB_STAT_TIMER_MASK); - - /* set MTU */ - AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN + - VLAN_HLEN + ETH_FCS_LEN); - - atl1c_configure_tx(adapter); - atl1c_configure_rx(adapter); - atl1c_configure_dma(adapter); - - return 0; -} - -static int atl1c_configure(struct atl1c_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - int num; - - atl1c_init_ring_ptrs(adapter); - atl1c_set_multi(netdev); - atl1c_restore_vlan(adapter); - - num = atl1c_alloc_rx_buffer(adapter); - if (unlikely(num == 0)) - return -ENOMEM; - - if (atl1c_configure_mac(adapter)) - return -EIO; - - return 0; -} - -static void atl1c_update_hw_stats(struct atl1c_adapter *adapter) -{ - u16 hw_reg_addr = 0; - unsigned long *stats_item = NULL; - u32 data; - - /* update rx status */ - hw_reg_addr = REG_MAC_RX_STATUS_BIN; - stats_item = &adapter->hw_stats.rx_ok; - while (hw_reg_addr <= REG_MAC_RX_STATUS_END) { - AT_READ_REG(&adapter->hw, hw_reg_addr, &data); - *stats_item += data; - stats_item++; - hw_reg_addr += 4; - } -/* update tx status */ - hw_reg_addr = REG_MAC_TX_STATUS_BIN; - stats_item = &adapter->hw_stats.tx_ok; - while (hw_reg_addr <= REG_MAC_TX_STATUS_END) { - AT_READ_REG(&adapter->hw, hw_reg_addr, &data); - *stats_item += data; - stats_item++; - hw_reg_addr += 4; - } -} - -/** - * atl1c_get_stats - Get System Network Statistics - * @netdev: network interface device structure - * - * Returns the address of the device statistics structure. - * The statistics are actually updated from the timer callback. - */ -static struct net_device_stats *atl1c_get_stats(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw_stats *hw_stats = &adapter->hw_stats; - struct net_device_stats *net_stats = &netdev->stats; - - atl1c_update_hw_stats(adapter); - net_stats->rx_bytes = hw_stats->rx_byte_cnt; - net_stats->tx_bytes = hw_stats->tx_byte_cnt; - net_stats->multicast = hw_stats->rx_mcast; - net_stats->collisions = hw_stats->tx_1_col + - hw_stats->tx_2_col + - hw_stats->tx_late_col + - hw_stats->tx_abort_col; - - net_stats->rx_errors = hw_stats->rx_frag + - hw_stats->rx_fcs_err + - hw_stats->rx_len_err + - hw_stats->rx_sz_ov + - hw_stats->rx_rrd_ov + - hw_stats->rx_align_err + - hw_stats->rx_rxf_ov; - - net_stats->rx_fifo_errors = hw_stats->rx_rxf_ov; - net_stats->rx_length_errors = hw_stats->rx_len_err; - net_stats->rx_crc_errors = hw_stats->rx_fcs_err; - net_stats->rx_frame_errors = hw_stats->rx_align_err; - net_stats->rx_dropped = hw_stats->rx_rrd_ov; - - net_stats->tx_errors = hw_stats->tx_late_col + - hw_stats->tx_abort_col + - hw_stats->tx_underrun + - hw_stats->tx_trunc; - - net_stats->tx_fifo_errors = hw_stats->tx_underrun; - net_stats->tx_aborted_errors = hw_stats->tx_abort_col; - net_stats->tx_window_errors = hw_stats->tx_late_col; - - net_stats->rx_packets = hw_stats->rx_ok + net_stats->rx_errors; - net_stats->tx_packets = hw_stats->tx_ok + net_stats->tx_errors; - - return net_stats; -} - -static inline void atl1c_clear_phy_int(struct atl1c_adapter *adapter) -{ - u16 phy_data; - - spin_lock(&adapter->mdio_lock); - atl1c_read_phy_reg(&adapter->hw, MII_ISR, &phy_data); - spin_unlock(&adapter->mdio_lock); -} - -static bool atl1c_clean_tx_irq(struct atl1c_adapter *adapter, - enum atl1c_trans_queue type) -{ - struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; - struct atl1c_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - u16 next_to_clean = atomic_read(&tpd_ring->next_to_clean); - u16 hw_next_to_clean; - u16 reg; - unsigned int total_bytes = 0, total_packets = 0; - - reg = type == atl1c_trans_high ? REG_TPD_PRI1_CIDX : REG_TPD_PRI0_CIDX; - - AT_READ_REGW(&adapter->hw, reg, &hw_next_to_clean); - - while (next_to_clean != hw_next_to_clean) { - buffer_info = &tpd_ring->buffer_info[next_to_clean]; - if (buffer_info->skb) { - total_bytes += buffer_info->skb->len; - total_packets++; - } - atl1c_clean_buffer(pdev, buffer_info); - if (++next_to_clean == tpd_ring->count) - next_to_clean = 0; - atomic_set(&tpd_ring->next_to_clean, next_to_clean); - } - - netdev_completed_queue(adapter->netdev, total_packets, total_bytes); - - if (netif_queue_stopped(adapter->netdev) && - netif_carrier_ok(adapter->netdev)) { - netif_wake_queue(adapter->netdev); - } - - return true; -} - -/** - * atl1c_intr - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - */ -static irqreturn_t atl1c_intr(int irq, void *data) -{ - struct net_device *netdev = data; - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct pci_dev *pdev = adapter->pdev; - struct atl1c_hw *hw = &adapter->hw; - int max_ints = AT_MAX_INT_WORK; - int handled = IRQ_NONE; - u32 status; - u32 reg_data; - - do { - AT_READ_REG(hw, REG_ISR, ®_data); - status = reg_data & hw->intr_mask; - - if (status == 0 || (status & ISR_DIS_INT) != 0) { - if (max_ints != AT_MAX_INT_WORK) - handled = IRQ_HANDLED; - break; - } - /* link event */ - if (status & ISR_GPHY) - atl1c_clear_phy_int(adapter); - /* Ack ISR */ - AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT); - if (status & ISR_RX_PKT) { - if (likely(napi_schedule_prep(&adapter->napi))) { - hw->intr_mask &= ~ISR_RX_PKT; - AT_WRITE_REG(hw, REG_IMR, hw->intr_mask); - __napi_schedule(&adapter->napi); - } - } - if (status & ISR_TX_PKT) - atl1c_clean_tx_irq(adapter, atl1c_trans_normal); - - handled = IRQ_HANDLED; - /* check if PCIE PHY Link down */ - if (status & ISR_ERROR) { - if (netif_msg_hw(adapter)) - dev_err(&pdev->dev, - "atl1c hardware error (status = 0x%x)\n", - status & ISR_ERROR); - /* reset MAC */ - set_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event); - schedule_work(&adapter->common_task); - return IRQ_HANDLED; - } - - if (status & ISR_OVER) - if (netif_msg_intr(adapter)) - dev_warn(&pdev->dev, - "TX/RX overflow (status = 0x%x)\n", - status & ISR_OVER); - - /* link event */ - if (status & (ISR_GPHY | ISR_MANUAL)) { - netdev->stats.tx_carrier_errors++; - atl1c_link_chg_event(adapter); - break; - } - - } while (--max_ints > 0); - /* re-enable Interrupt*/ - AT_WRITE_REG(&adapter->hw, REG_ISR, 0); - return handled; -} - -static inline void atl1c_rx_checksum(struct atl1c_adapter *adapter, - struct sk_buff *skb, struct atl1c_recv_ret_status *prrs) -{ - /* - * The pid field in RRS in not correct sometimes, so we - * cannot figure out if the packet is fragmented or not, - * so we tell the KERNEL CHECKSUM_NONE - */ - skb_checksum_none_assert(skb); -} - -static struct sk_buff *atl1c_alloc_skb(struct atl1c_adapter *adapter) -{ - struct sk_buff *skb; - struct page *page; - - if (adapter->rx_frag_size > PAGE_SIZE) - return netdev_alloc_skb(adapter->netdev, - adapter->rx_buffer_len); - - page = adapter->rx_page; - if (!page) { - adapter->rx_page = page = alloc_page(GFP_ATOMIC); - if (unlikely(!page)) - return NULL; - adapter->rx_page_offset = 0; - } - - skb = build_skb(page_address(page) + adapter->rx_page_offset, - adapter->rx_frag_size); - if (likely(skb)) { - skb_reserve(skb, NET_SKB_PAD); - adapter->rx_page_offset += adapter->rx_frag_size; - if (adapter->rx_page_offset >= PAGE_SIZE) - adapter->rx_page = NULL; - else - get_page(page); - } - return skb; -} - -static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter) -{ - struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct pci_dev *pdev = adapter->pdev; - struct atl1c_buffer *buffer_info, *next_info; - struct sk_buff *skb; - void *vir_addr = NULL; - u16 num_alloc = 0; - u16 rfd_next_to_use, next_next; - struct atl1c_rx_free_desc *rfd_desc; - dma_addr_t mapping; - - next_next = rfd_next_to_use = rfd_ring->next_to_use; - if (++next_next == rfd_ring->count) - next_next = 0; - buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; - next_info = &rfd_ring->buffer_info[next_next]; - - while (next_info->flags & ATL1C_BUFFER_FREE) { - rfd_desc = ATL1C_RFD_DESC(rfd_ring, rfd_next_to_use); - - skb = atl1c_alloc_skb(adapter); - if (unlikely(!skb)) { - if (netif_msg_rx_err(adapter)) - dev_warn(&pdev->dev, "alloc rx buffer failed\n"); - break; - } - - /* - * Make buffer alignment 2 beyond a 16 byte boundary - * this will result in a 16 byte aligned IP header after - * the 14 byte MAC header is removed - */ - vir_addr = skb->data; - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - buffer_info->skb = skb; - buffer_info->length = adapter->rx_buffer_len; - mapping = pci_map_single(pdev, vir_addr, - buffer_info->length, - PCI_DMA_FROMDEVICE); - if (unlikely(pci_dma_mapping_error(pdev, mapping))) { - dev_kfree_skb(skb); - buffer_info->skb = NULL; - buffer_info->length = 0; - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); - netif_warn(adapter, rx_err, adapter->netdev, "RX pci_map_single failed"); - break; - } - buffer_info->dma = mapping; - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, - ATL1C_PCIMAP_FROMDEVICE); - rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - rfd_next_to_use = next_next; - if (++next_next == rfd_ring->count) - next_next = 0; - buffer_info = &rfd_ring->buffer_info[rfd_next_to_use]; - next_info = &rfd_ring->buffer_info[next_next]; - num_alloc++; - } - - if (num_alloc) { - /* TODO: update mailbox here */ - wmb(); - rfd_ring->next_to_use = rfd_next_to_use; - AT_WRITE_REG(&adapter->hw, REG_MB_RFD0_PROD_IDX, - rfd_ring->next_to_use & MB_RFDX_PROD_IDX_MASK); - } - - return num_alloc; -} - -static void atl1c_clean_rrd(struct atl1c_rrd_ring *rrd_ring, - struct atl1c_recv_ret_status *rrs, u16 num) -{ - u16 i; - /* the relationship between rrd and rfd is one map one */ - for (i = 0; i < num; i++, rrs = ATL1C_RRD_DESC(rrd_ring, - rrd_ring->next_to_clean)) { - rrs->word3 &= ~RRS_RXD_UPDATED; - if (++rrd_ring->next_to_clean == rrd_ring->count) - rrd_ring->next_to_clean = 0; - } -} - -static void atl1c_clean_rfd(struct atl1c_rfd_ring *rfd_ring, - struct atl1c_recv_ret_status *rrs, u16 num) -{ - u16 i; - u16 rfd_index; - struct atl1c_buffer *buffer_info = rfd_ring->buffer_info; - - rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) & - RRS_RX_RFD_INDEX_MASK; - for (i = 0; i < num; i++) { - buffer_info[rfd_index].skb = NULL; - ATL1C_SET_BUFFER_STATE(&buffer_info[rfd_index], - ATL1C_BUFFER_FREE); - if (++rfd_index == rfd_ring->count) - rfd_index = 0; - } - rfd_ring->next_to_clean = rfd_index; -} - -static void atl1c_clean_rx_irq(struct atl1c_adapter *adapter, - int *work_done, int work_to_do) -{ - u16 rfd_num, rfd_index; - u16 count = 0; - u16 length; - struct pci_dev *pdev = adapter->pdev; - struct net_device *netdev = adapter->netdev; - struct atl1c_rfd_ring *rfd_ring = &adapter->rfd_ring; - struct atl1c_rrd_ring *rrd_ring = &adapter->rrd_ring; - struct sk_buff *skb; - struct atl1c_recv_ret_status *rrs; - struct atl1c_buffer *buffer_info; - - while (1) { - if (*work_done >= work_to_do) - break; - rrs = ATL1C_RRD_DESC(rrd_ring, rrd_ring->next_to_clean); - if (likely(RRS_RXD_IS_VALID(rrs->word3))) { - rfd_num = (rrs->word0 >> RRS_RX_RFD_CNT_SHIFT) & - RRS_RX_RFD_CNT_MASK; - if (unlikely(rfd_num != 1)) - /* TODO support mul rfd*/ - if (netif_msg_rx_err(adapter)) - dev_warn(&pdev->dev, - "Multi rfd not support yet!\n"); - goto rrs_checked; - } else { - break; - } -rrs_checked: - atl1c_clean_rrd(rrd_ring, rrs, rfd_num); - if (rrs->word3 & (RRS_RX_ERR_SUM | RRS_802_3_LEN_ERR)) { - atl1c_clean_rfd(rfd_ring, rrs, rfd_num); - if (netif_msg_rx_err(adapter)) - dev_warn(&pdev->dev, - "wrong packet! rrs word3 is %x\n", - rrs->word3); - continue; - } - - length = le16_to_cpu((rrs->word3 >> RRS_PKT_SIZE_SHIFT) & - RRS_PKT_SIZE_MASK); - /* Good Receive */ - if (likely(rfd_num == 1)) { - rfd_index = (rrs->word0 >> RRS_RX_RFD_INDEX_SHIFT) & - RRS_RX_RFD_INDEX_MASK; - buffer_info = &rfd_ring->buffer_info[rfd_index]; - pci_unmap_single(pdev, buffer_info->dma, - buffer_info->length, PCI_DMA_FROMDEVICE); - skb = buffer_info->skb; - } else { - /* TODO */ - if (netif_msg_rx_err(adapter)) - dev_warn(&pdev->dev, - "Multi rfd not support yet!\n"); - break; - } - atl1c_clean_rfd(rfd_ring, rrs, rfd_num); - skb_put(skb, length - ETH_FCS_LEN); - skb->protocol = eth_type_trans(skb, netdev); - atl1c_rx_checksum(adapter, skb, rrs); - if (rrs->word3 & RRS_VLAN_INS) { - u16 vlan; - - AT_TAG_TO_VLAN(rrs->vlan_tag, vlan); - vlan = le16_to_cpu(vlan); - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan); - } - netif_receive_skb(skb); - - (*work_done)++; - count++; - } - if (count) - atl1c_alloc_rx_buffer(adapter); -} - -/** - * atl1c_clean - NAPI Rx polling callback - */ -static int atl1c_clean(struct napi_struct *napi, int budget) -{ - struct atl1c_adapter *adapter = - container_of(napi, struct atl1c_adapter, napi); - int work_done = 0; - - /* Keep link state information with original netdev */ - if (!netif_carrier_ok(adapter->netdev)) - goto quit_polling; - /* just enable one RXQ */ - atl1c_clean_rx_irq(adapter, &work_done, budget); - - if (work_done < budget) { -quit_polling: - napi_complete(napi); - adapter->hw.intr_mask |= ISR_RX_PKT; - AT_WRITE_REG(&adapter->hw, REG_IMR, adapter->hw.intr_mask); - } - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER - -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void atl1c_netpoll(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - disable_irq(adapter->pdev->irq); - atl1c_intr(adapter->pdev->irq, netdev); - enable_irq(adapter->pdev->irq); -} -#endif - -static inline u16 atl1c_tpd_avail(struct atl1c_adapter *adapter, enum atl1c_trans_queue type) -{ - struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; - u16 next_to_use = 0; - u16 next_to_clean = 0; - - next_to_clean = atomic_read(&tpd_ring->next_to_clean); - next_to_use = tpd_ring->next_to_use; - - return (u16)(next_to_clean > next_to_use) ? - (next_to_clean - next_to_use - 1) : - (tpd_ring->count + next_to_clean - next_to_use - 1); -} - -/* - * get next usable tpd - * Note: should call atl1c_tdp_avail to make sure - * there is enough tpd to use - */ -static struct atl1c_tpd_desc *atl1c_get_tpd(struct atl1c_adapter *adapter, - enum atl1c_trans_queue type) -{ - struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; - struct atl1c_tpd_desc *tpd_desc; - u16 next_to_use = 0; - - next_to_use = tpd_ring->next_to_use; - if (++tpd_ring->next_to_use == tpd_ring->count) - tpd_ring->next_to_use = 0; - tpd_desc = ATL1C_TPD_DESC(tpd_ring, next_to_use); - memset(tpd_desc, 0, sizeof(struct atl1c_tpd_desc)); - return tpd_desc; -} - -static struct atl1c_buffer * -atl1c_get_tx_buffer(struct atl1c_adapter *adapter, struct atl1c_tpd_desc *tpd) -{ - struct atl1c_tpd_ring *tpd_ring = adapter->tpd_ring; - - return &tpd_ring->buffer_info[tpd - - (struct atl1c_tpd_desc *)tpd_ring->desc]; -} - -/* Calculate the transmit packet descript needed*/ -static u16 atl1c_cal_tpd_req(const struct sk_buff *skb) -{ - u16 tpd_req; - u16 proto_hdr_len = 0; - - tpd_req = skb_shinfo(skb)->nr_frags + 1; - - if (skb_is_gso(skb)) { - proto_hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - if (proto_hdr_len < skb_headlen(skb)) - tpd_req++; - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - tpd_req++; - } - return tpd_req; -} - -static int atl1c_tso_csum(struct atl1c_adapter *adapter, - struct sk_buff *skb, - struct atl1c_tpd_desc **tpd, - enum atl1c_trans_queue type) -{ - struct pci_dev *pdev = adapter->pdev; - unsigned short offload_type; - u8 hdr_len; - u32 real_len; - - if (skb_is_gso(skb)) { - int err; - - err = skb_cow_head(skb, 0); - if (err < 0) - return err; - - offload_type = skb_shinfo(skb)->gso_type; - - if (offload_type & SKB_GSO_TCPV4) { - real_len = (((unsigned char *)ip_hdr(skb) - skb->data) - + ntohs(ip_hdr(skb)->tot_len)); - - if (real_len < skb->len) - pskb_trim(skb, real_len); - - hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); - if (unlikely(skb->len == hdr_len)) { - /* only xsum need */ - if (netif_msg_tx_queued(adapter)) - dev_warn(&pdev->dev, - "IPV4 tso with zero data??\n"); - goto check_sum; - } else { - ip_hdr(skb)->check = 0; - tcp_hdr(skb)->check = ~csum_tcpudp_magic( - ip_hdr(skb)->saddr, - ip_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); - (*tpd)->word1 |= 1 << TPD_IPV4_PACKET_SHIFT; - } - } - - if (offload_type & SKB_GSO_TCPV6) { - struct atl1c_tpd_ext_desc *etpd = - *(struct atl1c_tpd_ext_desc **)(tpd); - - memset(etpd, 0, sizeof(struct atl1c_tpd_ext_desc)); - *tpd = atl1c_get_tpd(adapter, type); - ipv6_hdr(skb)->payload_len = 0; - /* check payload == 0 byte ? */ - hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); - if (unlikely(skb->len == hdr_len)) { - /* only xsum need */ - if (netif_msg_tx_queued(adapter)) - dev_warn(&pdev->dev, - "IPV6 tso with zero data??\n"); - goto check_sum; - } else - tcp_hdr(skb)->check = ~csum_ipv6_magic( - &ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); - etpd->word1 |= 1 << TPD_LSO_EN_SHIFT; - etpd->word1 |= 1 << TPD_LSO_VER_SHIFT; - etpd->pkt_len = cpu_to_le32(skb->len); - (*tpd)->word1 |= 1 << TPD_LSO_VER_SHIFT; - } - - (*tpd)->word1 |= 1 << TPD_LSO_EN_SHIFT; - (*tpd)->word1 |= (skb_transport_offset(skb) & TPD_TCPHDR_OFFSET_MASK) << - TPD_TCPHDR_OFFSET_SHIFT; - (*tpd)->word1 |= (skb_shinfo(skb)->gso_size & TPD_MSS_MASK) << - TPD_MSS_SHIFT; - return 0; - } - -check_sum: - if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { - u8 css, cso; - cso = skb_checksum_start_offset(skb); - - if (unlikely(cso & 0x1)) { - if (netif_msg_tx_err(adapter)) - dev_err(&adapter->pdev->dev, - "payload offset should not an event number\n"); - return -1; - } else { - css = cso + skb->csum_offset; - - (*tpd)->word1 |= ((cso >> 1) & TPD_PLOADOFFSET_MASK) << - TPD_PLOADOFFSET_SHIFT; - (*tpd)->word1 |= ((css >> 1) & TPD_CCSUM_OFFSET_MASK) << - TPD_CCSUM_OFFSET_SHIFT; - (*tpd)->word1 |= 1 << TPD_CCSUM_EN_SHIFT; - } - } - return 0; -} - -static void atl1c_tx_rollback(struct atl1c_adapter *adpt, - struct atl1c_tpd_desc *first_tpd, - enum atl1c_trans_queue type) -{ - struct atl1c_tpd_ring *tpd_ring = &adpt->tpd_ring[type]; - struct atl1c_buffer *buffer_info; - struct atl1c_tpd_desc *tpd; - u16 first_index, index; - - first_index = first_tpd - (struct atl1c_tpd_desc *)tpd_ring->desc; - index = first_index; - while (index != tpd_ring->next_to_use) { - tpd = ATL1C_TPD_DESC(tpd_ring, index); - buffer_info = &tpd_ring->buffer_info[index]; - atl1c_clean_buffer(adpt->pdev, buffer_info); - memset(tpd, 0, sizeof(struct atl1c_tpd_desc)); - if (++index == tpd_ring->count) - index = 0; - } - tpd_ring->next_to_use = first_index; -} - -static int atl1c_tx_map(struct atl1c_adapter *adapter, - struct sk_buff *skb, struct atl1c_tpd_desc *tpd, - enum atl1c_trans_queue type) -{ - struct atl1c_tpd_desc *use_tpd = NULL; - struct atl1c_buffer *buffer_info = NULL; - u16 buf_len = skb_headlen(skb); - u16 map_len = 0; - u16 mapped_len = 0; - u16 hdr_len = 0; - u16 nr_frags; - u16 f; - int tso; - - nr_frags = skb_shinfo(skb)->nr_frags; - tso = (tpd->word1 >> TPD_LSO_EN_SHIFT) & TPD_LSO_EN_MASK; - if (tso) { - /* TSO */ - map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - use_tpd = tpd; - - buffer_info = atl1c_get_tx_buffer(adapter, use_tpd); - buffer_info->length = map_len; - buffer_info->dma = pci_map_single(adapter->pdev, - skb->data, hdr_len, PCI_DMA_TODEVICE); - if (unlikely(pci_dma_mapping_error(adapter->pdev, - buffer_info->dma))) - goto err_dma; - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, - ATL1C_PCIMAP_TODEVICE); - mapped_len += map_len; - use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); - use_tpd->buffer_len = cpu_to_le16(buffer_info->length); - } - - if (mapped_len < buf_len) { - /* mapped_len == 0, means we should use the first tpd, - which is given by caller */ - if (mapped_len == 0) - use_tpd = tpd; - else { - use_tpd = atl1c_get_tpd(adapter, type); - memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc)); - } - buffer_info = atl1c_get_tx_buffer(adapter, use_tpd); - buffer_info->length = buf_len - mapped_len; - buffer_info->dma = - pci_map_single(adapter->pdev, skb->data + mapped_len, - buffer_info->length, PCI_DMA_TODEVICE); - if (unlikely(pci_dma_mapping_error(adapter->pdev, - buffer_info->dma))) - goto err_dma; - - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, - ATL1C_PCIMAP_TODEVICE); - use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); - use_tpd->buffer_len = cpu_to_le16(buffer_info->length); - } - - for (f = 0; f < nr_frags; f++) { - struct skb_frag_struct *frag; - - frag = &skb_shinfo(skb)->frags[f]; - - use_tpd = atl1c_get_tpd(adapter, type); - memcpy(use_tpd, tpd, sizeof(struct atl1c_tpd_desc)); - - buffer_info = atl1c_get_tx_buffer(adapter, use_tpd); - buffer_info->length = skb_frag_size(frag); - buffer_info->dma = skb_frag_dma_map(&adapter->pdev->dev, - frag, 0, - buffer_info->length, - DMA_TO_DEVICE); - if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) - goto err_dma; - - ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); - ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE, - ATL1C_PCIMAP_TODEVICE); - use_tpd->buffer_addr = cpu_to_le64(buffer_info->dma); - use_tpd->buffer_len = cpu_to_le16(buffer_info->length); - } - - /* The last tpd */ - use_tpd->word1 |= 1 << TPD_EOP_SHIFT; - /* The last buffer info contain the skb address, - so it will be free after unmap */ - buffer_info->skb = skb; - - return 0; - -err_dma: - buffer_info->dma = 0; - buffer_info->length = 0; - return -1; -} - -static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb, - struct atl1c_tpd_desc *tpd, enum atl1c_trans_queue type) -{ - struct atl1c_tpd_ring *tpd_ring = &adapter->tpd_ring[type]; - u16 reg; - - reg = type == atl1c_trans_high ? REG_TPD_PRI1_PIDX : REG_TPD_PRI0_PIDX; - AT_WRITE_REGW(&adapter->hw, reg, tpd_ring->next_to_use); -} - -static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - unsigned long flags; - u16 tpd_req = 1; - struct atl1c_tpd_desc *tpd; - enum atl1c_trans_queue type = atl1c_trans_normal; - - if (test_bit(__AT_DOWN, &adapter->flags)) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - tpd_req = atl1c_cal_tpd_req(skb); - if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) { - if (netif_msg_pktdata(adapter)) - dev_info(&adapter->pdev->dev, "tx locked\n"); - return NETDEV_TX_LOCKED; - } - - if (atl1c_tpd_avail(adapter, type) < tpd_req) { - /* no enough descriptor, just stop queue */ - netif_stop_queue(netdev); - spin_unlock_irqrestore(&adapter->tx_lock, flags); - return NETDEV_TX_BUSY; - } - - tpd = atl1c_get_tpd(adapter, type); - - /* do TSO and check sum */ - if (atl1c_tso_csum(adapter, skb, &tpd, type) != 0) { - spin_unlock_irqrestore(&adapter->tx_lock, flags); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if (unlikely(skb_vlan_tag_present(skb))) { - u16 vlan = skb_vlan_tag_get(skb); - __le16 tag; - - vlan = cpu_to_le16(vlan); - AT_VLAN_TO_TAG(vlan, tag); - tpd->word1 |= 1 << TPD_INS_VTAG_SHIFT; - tpd->vlan_tag = tag; - } - - if (skb_network_offset(skb) != ETH_HLEN) - tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */ - - if (atl1c_tx_map(adapter, skb, tpd, type) < 0) { - netif_info(adapter, tx_done, adapter->netdev, - "tx-skb droppted due to dma error\n"); - /* roll back tpd/buffer */ - atl1c_tx_rollback(adapter, tpd, type); - spin_unlock_irqrestore(&adapter->tx_lock, flags); - dev_kfree_skb_any(skb); - } else { - netdev_sent_queue(adapter->netdev, skb->len); - atl1c_tx_queue(adapter, skb, tpd, type); - spin_unlock_irqrestore(&adapter->tx_lock, flags); - } - - return NETDEV_TX_OK; -} - -static void atl1c_free_irq(struct atl1c_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - free_irq(adapter->pdev->irq, netdev); - - if (adapter->have_msi) - pci_disable_msi(adapter->pdev); -} - -static int atl1c_request_irq(struct atl1c_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - struct net_device *netdev = adapter->netdev; - int flags = 0; - int err = 0; - - adapter->have_msi = true; - err = pci_enable_msi(adapter->pdev); - if (err) { - if (netif_msg_ifup(adapter)) - dev_err(&pdev->dev, - "Unable to allocate MSI interrupt Error: %d\n", - err); - adapter->have_msi = false; - } - - if (!adapter->have_msi) - flags |= IRQF_SHARED; - err = request_irq(adapter->pdev->irq, atl1c_intr, flags, - netdev->name, netdev); - if (err) { - if (netif_msg_ifup(adapter)) - dev_err(&pdev->dev, - "Unable to allocate interrupt Error: %d\n", - err); - if (adapter->have_msi) - pci_disable_msi(adapter->pdev); - return err; - } - if (netif_msg_ifup(adapter)) - dev_dbg(&pdev->dev, "atl1c_request_irq OK\n"); - return err; -} - - -static void atl1c_reset_dma_ring(struct atl1c_adapter *adapter) -{ - /* release tx-pending skbs and reset tx/rx ring index */ - atl1c_clean_tx_ring(adapter, atl1c_trans_normal); - atl1c_clean_tx_ring(adapter, atl1c_trans_high); - atl1c_clean_rx_ring(adapter); -} - -static int atl1c_up(struct atl1c_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - int err; - - netif_carrier_off(netdev); - - err = atl1c_configure(adapter); - if (unlikely(err)) - goto err_up; - - err = atl1c_request_irq(adapter); - if (unlikely(err)) - goto err_up; - - atl1c_check_link_status(adapter); - clear_bit(__AT_DOWN, &adapter->flags); - napi_enable(&adapter->napi); - atl1c_irq_enable(adapter); - netif_start_queue(netdev); - return err; - -err_up: - atl1c_clean_rx_ring(adapter); - return err; -} - -static void atl1c_down(struct atl1c_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - atl1c_del_timer(adapter); - adapter->work_event = 0; /* clear all event */ - /* signal that we're down so the interrupt handler does not - * reschedule our watchdog timer */ - set_bit(__AT_DOWN, &adapter->flags); - netif_carrier_off(netdev); - napi_disable(&adapter->napi); - atl1c_irq_disable(adapter); - atl1c_free_irq(adapter); - /* disable ASPM if device inactive */ - atl1c_disable_l0s_l1(&adapter->hw); - /* reset MAC to disable all RX/TX */ - atl1c_reset_mac(&adapter->hw); - msleep(1); - - adapter->link_speed = SPEED_0; - adapter->link_duplex = -1; - atl1c_reset_dma_ring(adapter); -} - -/** - * atl1c_open - Called when a network interface is made active - * @netdev: network interface device structure - * - * Returns 0 on success, negative value on failure - * - * The open entry point is called when a network interface is made - * active by the system (IFF_UP). At this point all resources needed - * for transmit and receive operations are allocated, the interrupt - * handler is registered with the OS, the watchdog timer is started, - * and the stack is notified that the interface is ready. - */ -static int atl1c_open(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - int err; - - /* disallow open during test */ - if (test_bit(__AT_TESTING, &adapter->flags)) - return -EBUSY; - - /* allocate rx/tx dma buffer & descriptors */ - err = atl1c_setup_ring_resources(adapter); - if (unlikely(err)) - return err; - - err = atl1c_up(adapter); - if (unlikely(err)) - goto err_up; - - return 0; - -err_up: - atl1c_free_irq(adapter); - atl1c_free_ring_resources(adapter); - atl1c_reset_mac(&adapter->hw); - return err; -} - -/** - * atl1c_close - Disables a network interface - * @netdev: network interface device structure - * - * Returns 0, this is not allowed to fail - * - * The close entry point is called when an interface is de-activated - * by the OS. The hardware is still under the drivers control, but - * needs to be disabled. A global MAC reset is issued to stop the - * hardware, and all transmit and receive resources are freed. - */ -static int atl1c_close(struct net_device *netdev) -{ - struct atl1c_adapter *adapter = netdev_priv(netdev); - - WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); - set_bit(__AT_DOWN, &adapter->flags); - cancel_work_sync(&adapter->common_task); - atl1c_down(adapter); - atl1c_free_ring_resources(adapter); - return 0; -} - -static int atl1c_suspend(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - struct atl1c_hw *hw = &adapter->hw; - u32 wufc = adapter->wol; - - atl1c_disable_l0s_l1(hw); - if (netif_running(netdev)) { - WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); - atl1c_down(adapter); - } - netif_device_detach(netdev); - - if (wufc) - if (atl1c_phy_to_ps_link(hw) != 0) - dev_dbg(&pdev->dev, "phy power saving failed"); - - atl1c_power_saving(hw, wufc); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int atl1c_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - - AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); - atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE); - - atl1c_phy_reset(&adapter->hw); - atl1c_reset_mac(&adapter->hw); - atl1c_phy_init(&adapter->hw); - -#if 0 - AT_READ_REG(&adapter->hw, REG_PM_CTRLSTAT, &pm_data); - pm_data &= ~PM_CTRLSTAT_PME_EN; - AT_WRITE_REG(&adapter->hw, REG_PM_CTRLSTAT, pm_data); -#endif - - netif_device_attach(netdev); - if (netif_running(netdev)) - atl1c_up(adapter); - - return 0; -} -#endif - -static void atl1c_shutdown(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - - atl1c_suspend(&pdev->dev); - pci_wake_from_d3(pdev, adapter->wol); - pci_set_power_state(pdev, PCI_D3hot); -} - -static const struct net_device_ops atl1c_netdev_ops = { - .ndo_open = atl1c_open, - .ndo_stop = atl1c_close, - .ndo_validate_addr = eth_validate_addr, - .ndo_start_xmit = atl1c_xmit_frame, - .ndo_set_mac_address = atl1c_set_mac_addr, - .ndo_set_rx_mode = atl1c_set_multi, - .ndo_change_mtu = atl1c_change_mtu, - .ndo_fix_features = atl1c_fix_features, - .ndo_set_features = atl1c_set_features, - .ndo_do_ioctl = atl1c_ioctl, - .ndo_tx_timeout = atl1c_tx_timeout, - .ndo_get_stats = atl1c_get_stats, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = atl1c_netpoll, -#endif -}; - -static int atl1c_init_netdev(struct net_device *netdev, struct pci_dev *pdev) -{ - SET_NETDEV_DEV(netdev, &pdev->dev); - pci_set_drvdata(pdev, netdev); - - netdev->netdev_ops = &atl1c_netdev_ops; - netdev->watchdog_timeo = AT_TX_WATCHDOG; - atl1c_set_ethtool_ops(netdev); - - /* TODO: add when ready */ - netdev->hw_features = NETIF_F_SG | - NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_TSO | - NETIF_F_TSO6; - netdev->features = netdev->hw_features | - NETIF_F_HW_VLAN_CTAG_TX; - return 0; -} - -/** - * atl1c_probe - Device Initialization Routine - * @pdev: PCI device information struct - * @ent: entry in atl1c_pci_tbl - * - * Returns 0 on success, negative on failure - * - * atl1c_probe initializes an adapter identified by a pci_dev structure. - * The OS initialization, configuring of the adapter private structure, - * and a hardware reset occur. - */ -static int atl1c_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct atl1c_adapter *adapter; - static int cards_found; - - int err = 0; - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - err = pci_enable_device_mem(pdev); - if (err) { - dev_err(&pdev->dev, "cannot enable PCI device\n"); - return err; - } - - /* - * The atl1c chip can DMA to 64-bit addresses, but it uses a single - * shared register for the high 32 bits, so only a single, aligned, - * 4 GB physical address range can be used at a time. - * - * Supporting 64-bit DMA on this hardware is more trouble than it's - * worth. It is far easier to limit to 32-bit DMA than update - * various kernel subsystems to support the mechanics required by a - * fixed-high-32-bit system. - */ - if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) || - (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)) { - dev_err(&pdev->dev, "No usable DMA configuration,aborting\n"); - goto err_dma; - } - - err = pci_request_regions(pdev, atl1c_driver_name); - if (err) { - dev_err(&pdev->dev, "cannot obtain PCI resources\n"); - goto err_pci_reg; - } - - pci_set_master(pdev); - - netdev = alloc_etherdev(sizeof(struct atl1c_adapter)); - if (netdev == NULL) { - err = -ENOMEM; - goto err_alloc_etherdev; - } - - err = atl1c_init_netdev(netdev, pdev); - if (err) { - dev_err(&pdev->dev, "init netdevice failed\n"); - goto err_init_netdev; - } - adapter = netdev_priv(netdev); - adapter->bd_number = cards_found; - adapter->netdev = netdev; - adapter->pdev = pdev; - adapter->hw.adapter = adapter; - adapter->msg_enable = netif_msg_init(-1, atl1c_default_msg); - adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, 0), pci_resource_len(pdev, 0)); - if (!adapter->hw.hw_addr) { - err = -EIO; - dev_err(&pdev->dev, "cannot map device registers\n"); - goto err_ioremap; - } - - /* init mii data */ - adapter->mii.dev = netdev; - adapter->mii.mdio_read = atl1c_mdio_read; - adapter->mii.mdio_write = atl1c_mdio_write; - adapter->mii.phy_id_mask = 0x1f; - adapter->mii.reg_num_mask = MDIO_CTRL_REG_MASK; - netif_napi_add(netdev, &adapter->napi, atl1c_clean, 64); - setup_timer(&adapter->phy_config_timer, atl1c_phy_config, - (unsigned long)adapter); - /* setup the private structure */ - err = atl1c_sw_init(adapter); - if (err) { - dev_err(&pdev->dev, "net device private data init failed\n"); - goto err_sw_init; - } - atl1c_reset_pcie(&adapter->hw, ATL1C_PCIE_L0S_L1_DISABLE); - - /* Init GPHY as early as possible due to power saving issue */ - atl1c_phy_reset(&adapter->hw); - - err = atl1c_reset_mac(&adapter->hw); - if (err) { - err = -EIO; - goto err_reset; - } - - /* reset the controller to - * put the device in a known good starting state */ - err = atl1c_phy_init(&adapter->hw); - if (err) { - err = -EIO; - goto err_reset; - } - if (atl1c_read_mac_addr(&adapter->hw)) { - /* got a random MAC address, set NET_ADDR_RANDOM to netdev */ - netdev->addr_assign_type = NET_ADDR_RANDOM; - } - memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); - if (netif_msg_probe(adapter)) - dev_dbg(&pdev->dev, "mac address : %pM\n", - adapter->hw.mac_addr); - - atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.mac_addr); - INIT_WORK(&adapter->common_task, atl1c_common_task); - adapter->work_event = 0; - err = register_netdev(netdev); - if (err) { - dev_err(&pdev->dev, "register netdevice failed\n"); - goto err_register; - } - - if (netif_msg_probe(adapter)) - dev_info(&pdev->dev, "version %s\n", ATL1C_DRV_VERSION); - cards_found++; - return 0; - -err_reset: -err_register: -err_sw_init: - iounmap(adapter->hw.hw_addr); -err_init_netdev: -err_ioremap: - free_netdev(netdev); -err_alloc_etherdev: - pci_release_regions(pdev); -err_pci_reg: -err_dma: - pci_disable_device(pdev); - return err; -} - -/** - * atl1c_remove - Device Removal Routine - * @pdev: PCI device information struct - * - * atl1c_remove is called by the PCI subsystem to alert the driver - * that it should release a PCI device. The could be caused by a - * Hot-Plug event, or because the driver is going to be removed from - * memory. - */ -static void atl1c_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - - unregister_netdev(netdev); - /* restore permanent address */ - atl1c_hw_set_mac_addr(&adapter->hw, adapter->hw.perm_mac_addr); - atl1c_phy_disable(&adapter->hw); - - iounmap(adapter->hw.hw_addr); - - pci_release_regions(pdev); - pci_disable_device(pdev); - free_netdev(netdev); -} - -/** - * atl1c_io_error_detected - called when PCI error is detected - * @pdev: Pointer to PCI device - * @state: The current pci connection state - * - * This function is called after a PCI bus error affecting - * this device has been detected. - */ -static pci_ers_result_t atl1c_io_error_detected(struct pci_dev *pdev, - pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - atl1c_down(adapter); - - pci_disable_device(pdev); - - /* Request a slot slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * atl1c_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch, as if from a cold-boot. Implementation - * resembles the first-half of the e1000_resume routine. - */ -static pci_ers_result_t atl1c_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - if (netif_msg_hw(adapter)) - dev_err(&pdev->dev, - "Cannot re-enable PCI device after reset\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - atl1c_reset_mac(&adapter->hw); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * atl1c_io_resume - called when traffic can start flowing again. - * @pdev: Pointer to PCI device - * - * This callback is called when the error recovery driver tells us that - * its OK to resume normal operation. Implementation resembles the - * second-half of the atl1c_resume routine. - */ -static void atl1c_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1c_adapter *adapter = netdev_priv(netdev); - - if (netif_running(netdev)) { - if (atl1c_up(adapter)) { - if (netif_msg_hw(adapter)) - dev_err(&pdev->dev, - "Cannot bring device back up after reset\n"); - return; - } - } - - netif_device_attach(netdev); -} - -static const struct pci_error_handlers atl1c_err_handler = { - .error_detected = atl1c_io_error_detected, - .slot_reset = atl1c_io_slot_reset, - .resume = atl1c_io_resume, -}; - -static SIMPLE_DEV_PM_OPS(atl1c_pm_ops, atl1c_suspend, atl1c_resume); - -static struct pci_driver atl1c_driver = { - .name = atl1c_driver_name, - .id_table = atl1c_pci_tbl, - .probe = atl1c_probe, - .remove = atl1c_remove, - .shutdown = atl1c_shutdown, - .err_handler = &atl1c_err_handler, - .driver.pm = &atl1c_pm_ops, -}; - -module_pci_driver(atl1c_driver); diff --git a/addons/atl1e/install.sh b/addons/atl1e/install.sh deleted file mode 100644 index d13abb99..00000000 --- a/addons/atl1e/install.sh +++ /dev/null @@ -1,4 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Installing module for Atheros L1E Gigabit Ethernet adapter" - ${INSMOD} "/modules/atl1e.ko" ${PARAMS} -fi diff --git a/addons/atl1e/manifest.yml b/addons/atl1e/manifest.yml deleted file mode 100644 index 77a403b3..00000000 --- a/addons/atl1e/manifest.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: 1 -name: atl1e -description: "Driver for Atheros L1E Gigabit Ethernet adapters" -available-for: - bromolow-3.10.108: - install-script: &script "install.sh" - modules: true - apollolake-4.4.180: - install-script: *script - modules: true - broadwell-4.4.180: - install-script: *script - modules: true - broadwellnk-4.4.180: - install-script: *script - modules: true - denverton-4.4.180: - install-script: *script - modules: true - geminilake-4.4.180: - install-script: *script - modules: true - v1000-4.4.180: - install-script: *script - modules: true - purley-4.4.180: - install-script: *script - modules: true diff --git a/addons/atl1e/src/3.10.108/Makefile b/addons/atl1e/src/3.10.108/Makefile deleted file mode 100644 index fe2e3d47..00000000 --- a/addons/atl1e/src/3.10.108/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-m += atl1e.o -atl1e-objs += atl1e_main.o atl1e_hw.o atl1e_ethtool.o atl1e_param.o diff --git a/addons/atl1e/src/3.10.108/atl1e.h b/addons/atl1e/src/3.10.108/atl1e.h deleted file mode 100644 index b5fd9345..00000000 --- a/addons/atl1e/src/3.10.108/atl1e.h +++ /dev/null @@ -1,508 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * Copyright(c) 2007 xiong huang - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _ATL1E_H_ -#define _ATL1E_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "atl1e_hw.h" - -#define PCI_REG_COMMAND 0x04 /* PCI Command Register */ -#define CMD_IO_SPACE 0x0001 -#define CMD_MEMORY_SPACE 0x0002 -#define CMD_BUS_MASTER 0x0004 - -#define BAR_0 0 -#define BAR_1 1 -#define BAR_5 5 - -/* Wake Up Filter Control */ -#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ -#define AT_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ -#define AT_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ -#define AT_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */ -#define AT_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ - -#define SPEED_0 0xffff -#define HALF_DUPLEX 1 -#define FULL_DUPLEX 2 - -/* Error Codes */ -#define AT_ERR_EEPROM 1 -#define AT_ERR_PHY 2 -#define AT_ERR_CONFIG 3 -#define AT_ERR_PARAM 4 -#define AT_ERR_MAC_TYPE 5 -#define AT_ERR_PHY_TYPE 6 -#define AT_ERR_PHY_SPEED 7 -#define AT_ERR_PHY_RES 8 -#define AT_ERR_TIMEOUT 9 - -#define MAX_JUMBO_FRAME_SIZE 0x2000 - -#define AT_VLAN_TAG_TO_TPD_TAG(_vlan, _tpd) \ - _tpd = (((_vlan) << (4)) | (((_vlan) >> 13) & 7) |\ - (((_vlan) >> 9) & 8)) - -#define AT_TPD_TAG_TO_VLAN_TAG(_tpd, _vlan) \ - _vlan = (((_tpd) >> 8) | (((_tpd) & 0x77) << 9) |\ - (((_tdp) & 0x88) << 5)) - -#define AT_MAX_RECEIVE_QUEUE 4 -#define AT_PAGE_NUM_PER_QUEUE 2 - -#define AT_DMA_HI_ADDR_MASK 0xffffffff00000000ULL -#define AT_DMA_LO_ADDR_MASK 0x00000000ffffffffULL - -#define AT_TX_WATCHDOG (5 * HZ) -#define AT_MAX_INT_WORK 10 -#define AT_TWSI_EEPROM_TIMEOUT 100 -#define AT_HW_MAX_IDLE_DELAY 10 -#define AT_SUSPEND_LINK_TIMEOUT 28 - -#define AT_REGS_LEN 75 -#define AT_EEPROM_LEN 512 -#define AT_ADV_MASK (ADVERTISE_10_HALF |\ - ADVERTISE_10_FULL |\ - ADVERTISE_100_HALF |\ - ADVERTISE_100_FULL |\ - ADVERTISE_1000_FULL) - -/* tpd word 2 */ -#define TPD_BUFLEN_MASK 0x3FFF -#define TPD_BUFLEN_SHIFT 0 -#define TPD_DMAINT_MASK 0x0001 -#define TPD_DMAINT_SHIFT 14 -#define TPD_PKTNT_MASK 0x0001 -#define TPD_PKTINT_SHIFT 15 -#define TPD_VLANTAG_MASK 0xFFFF -#define TPD_VLAN_SHIFT 16 - -/* tpd word 3 bits 0:4 */ -#define TPD_EOP_MASK 0x0001 -#define TPD_EOP_SHIFT 0 -#define TPD_IP_VERSION_MASK 0x0001 -#define TPD_IP_VERSION_SHIFT 1 /* 0 : IPV4, 1 : IPV6 */ -#define TPD_INS_VL_TAG_MASK 0x0001 -#define TPD_INS_VL_TAG_SHIFT 2 -#define TPD_CC_SEGMENT_EN_MASK 0x0001 -#define TPD_CC_SEGMENT_EN_SHIFT 3 -#define TPD_SEGMENT_EN_MASK 0x0001 -#define TPD_SEGMENT_EN_SHIFT 4 - -/* tdp word 3 bits 5:7 if ip version is 0 */ -#define TPD_IP_CSUM_MASK 0x0001 -#define TPD_IP_CSUM_SHIFT 5 -#define TPD_TCP_CSUM_MASK 0x0001 -#define TPD_TCP_CSUM_SHIFT 6 -#define TPD_UDP_CSUM_MASK 0x0001 -#define TPD_UDP_CSUM_SHIFT 7 - -/* tdp word 3 bits 5:7 if ip version is 1 */ -#define TPD_V6_IPHLLO_MASK 0x0007 -#define TPD_V6_IPHLLO_SHIFT 7 - -/* tpd word 3 bits 8:9 bit */ -#define TPD_VL_TAGGED_MASK 0x0001 -#define TPD_VL_TAGGED_SHIFT 8 -#define TPD_ETHTYPE_MASK 0x0001 -#define TPD_ETHTYPE_SHIFT 9 - -/* tdp word 3 bits 10:13 if ip version is 0 */ -#define TDP_V4_IPHL_MASK 0x000F -#define TPD_V4_IPHL_SHIFT 10 - -/* tdp word 3 bits 10:13 if ip version is 1 */ -#define TPD_V6_IPHLHI_MASK 0x000F -#define TPD_V6_IPHLHI_SHIFT 10 - -/* tpd word 3 bit 14:31 if segment enabled */ -#define TPD_TCPHDRLEN_MASK 0x000F -#define TPD_TCPHDRLEN_SHIFT 14 -#define TPD_HDRFLAG_MASK 0x0001 -#define TPD_HDRFLAG_SHIFT 18 -#define TPD_MSS_MASK 0x1FFF -#define TPD_MSS_SHIFT 19 - -/* tdp word 3 bit 16:31 if custom csum enabled */ -#define TPD_PLOADOFFSET_MASK 0x00FF -#define TPD_PLOADOFFSET_SHIFT 16 -#define TPD_CCSUMOFFSET_MASK 0x00FF -#define TPD_CCSUMOFFSET_SHIFT 24 - -struct atl1e_tpd_desc { - __le64 buffer_addr; - __le32 word2; - __le32 word3; -}; - -/* how about 0x2000 */ -#define MAX_TX_BUF_LEN 0x2000 -#define MAX_TX_BUF_SHIFT 13 -#define MAX_TSO_SEG_SIZE 0x3c00 - -/* rrs word 1 bit 0:31 */ -#define RRS_RX_CSUM_MASK 0xFFFF -#define RRS_RX_CSUM_SHIFT 0 -#define RRS_PKT_SIZE_MASK 0x3FFF -#define RRS_PKT_SIZE_SHIFT 16 -#define RRS_CPU_NUM_MASK 0x0003 -#define RRS_CPU_NUM_SHIFT 30 - -#define RRS_IS_RSS_IPV4 0x0001 -#define RRS_IS_RSS_IPV4_TCP 0x0002 -#define RRS_IS_RSS_IPV6 0x0004 -#define RRS_IS_RSS_IPV6_TCP 0x0008 -#define RRS_IS_IPV6 0x0010 -#define RRS_IS_IP_FRAG 0x0020 -#define RRS_IS_IP_DF 0x0040 -#define RRS_IS_802_3 0x0080 -#define RRS_IS_VLAN_TAG 0x0100 -#define RRS_IS_ERR_FRAME 0x0200 -#define RRS_IS_IPV4 0x0400 -#define RRS_IS_UDP 0x0800 -#define RRS_IS_TCP 0x1000 -#define RRS_IS_BCAST 0x2000 -#define RRS_IS_MCAST 0x4000 -#define RRS_IS_PAUSE 0x8000 - -#define RRS_ERR_BAD_CRC 0x0001 -#define RRS_ERR_CODE 0x0002 -#define RRS_ERR_DRIBBLE 0x0004 -#define RRS_ERR_RUNT 0x0008 -#define RRS_ERR_RX_OVERFLOW 0x0010 -#define RRS_ERR_TRUNC 0x0020 -#define RRS_ERR_IP_CSUM 0x0040 -#define RRS_ERR_L4_CSUM 0x0080 -#define RRS_ERR_LENGTH 0x0100 -#define RRS_ERR_DES_ADDR 0x0200 - -struct atl1e_recv_ret_status { - u16 seq_num; - u16 hash_lo; - __le32 word1; - u16 pkt_flag; - u16 err_flag; - u16 hash_hi; - u16 vtag; -}; - -enum atl1e_dma_req_block { - atl1e_dma_req_128 = 0, - atl1e_dma_req_256 = 1, - atl1e_dma_req_512 = 2, - atl1e_dma_req_1024 = 3, - atl1e_dma_req_2048 = 4, - atl1e_dma_req_4096 = 5 -}; - -enum atl1e_rrs_type { - atl1e_rrs_disable = 0, - atl1e_rrs_ipv4 = 1, - atl1e_rrs_ipv4_tcp = 2, - atl1e_rrs_ipv6 = 4, - atl1e_rrs_ipv6_tcp = 8 -}; - -enum atl1e_nic_type { - athr_l1e = 0, - athr_l2e_revA = 1, - athr_l2e_revB = 2 -}; - -struct atl1e_hw_stats { - /* rx */ - unsigned long rx_ok; /* The number of good packet received. */ - unsigned long rx_bcast; /* The number of good broadcast packet received. */ - unsigned long rx_mcast; /* The number of good multicast packet received. */ - unsigned long rx_pause; /* The number of Pause packet received. */ - unsigned long rx_ctrl; /* The number of Control packet received other than Pause frame. */ - unsigned long rx_fcs_err; /* The number of packets with bad FCS. */ - unsigned long rx_len_err; /* The number of packets with mismatch of length field and actual size. */ - unsigned long rx_byte_cnt; /* The number of bytes of good packet received. FCS is NOT included. */ - unsigned long rx_runt; /* The number of packets received that are less than 64 byte long and with good FCS. */ - unsigned long rx_frag; /* The number of packets received that are less than 64 byte long and with bad FCS. */ - unsigned long rx_sz_64; /* The number of good and bad packets received that are 64 byte long. */ - unsigned long rx_sz_65_127; /* The number of good and bad packets received that are between 65 and 127-byte long. */ - unsigned long rx_sz_128_255; /* The number of good and bad packets received that are between 128 and 255-byte long. */ - unsigned long rx_sz_256_511; /* The number of good and bad packets received that are between 256 and 511-byte long. */ - unsigned long rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */ - unsigned long rx_sz_1024_1518; /* The number of good and bad packets received that are between 1024 and 1518-byte long. */ - unsigned long rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */ - unsigned long rx_sz_ov; /* The number of good and bad packets received that are more than MTU size truncated by Selene. */ - unsigned long rx_rxf_ov; /* The number of frame dropped due to occurrence of RX FIFO overflow. */ - unsigned long rx_rrd_ov; /* The number of frame dropped due to occurrence of RRD overflow. */ - unsigned long rx_align_err; /* Alignment Error */ - unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */ - unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */ - unsigned long rx_err_addr; /* The number of packets dropped due to address filtering. */ - - /* tx */ - unsigned long tx_ok; /* The number of good packet transmitted. */ - unsigned long tx_bcast; /* The number of good broadcast packet transmitted. */ - unsigned long tx_mcast; /* The number of good multicast packet transmitted. */ - unsigned long tx_pause; /* The number of Pause packet transmitted. */ - unsigned long tx_exc_defer; /* The number of packets transmitted with excessive deferral. */ - unsigned long tx_ctrl; /* The number of packets transmitted is a control frame, excluding Pause frame. */ - unsigned long tx_defer; /* The number of packets transmitted that is deferred. */ - unsigned long tx_byte_cnt; /* The number of bytes of data transmitted. FCS is NOT included. */ - unsigned long tx_sz_64; /* The number of good and bad packets transmitted that are 64 byte long. */ - unsigned long tx_sz_65_127; /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */ - unsigned long tx_sz_128_255; /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */ - unsigned long tx_sz_256_511; /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */ - unsigned long tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */ - unsigned long tx_sz_1024_1518; /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */ - unsigned long tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */ - unsigned long tx_1_col; /* The number of packets subsequently transmitted successfully with a single prior collision. */ - unsigned long tx_2_col; /* The number of packets subsequently transmitted successfully with multiple prior collisions. */ - unsigned long tx_late_col; /* The number of packets transmitted with late collisions. */ - unsigned long tx_abort_col; /* The number of transmit packets aborted due to excessive collisions. */ - unsigned long tx_underrun; /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */ - unsigned long tx_rd_eop; /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */ - unsigned long tx_len_err; /* The number of transmit packets with length field does NOT match the actual frame size. */ - unsigned long tx_trunc; /* The number of transmit packets truncated due to size exceeding MTU. */ - unsigned long tx_bcast_byte; /* The byte count of broadcast packet transmitted, excluding FCS. */ - unsigned long tx_mcast_byte; /* The byte count of multicast packet transmitted, excluding FCS. */ -}; - -struct atl1e_hw { - u8 __iomem *hw_addr; /* inner register address */ - resource_size_t mem_rang; - struct atl1e_adapter *adapter; - enum atl1e_nic_type nic_type; - u16 device_id; - u16 vendor_id; - u16 subsystem_id; - u16 subsystem_vendor_id; - u8 revision_id; - u16 pci_cmd_word; - u8 mac_addr[ETH_ALEN]; - u8 perm_mac_addr[ETH_ALEN]; - u8 preamble_len; - u16 max_frame_size; - u16 rx_jumbo_th; - u16 tx_jumbo_th; - - u16 media_type; -#define MEDIA_TYPE_AUTO_SENSOR 0 -#define MEDIA_TYPE_100M_FULL 1 -#define MEDIA_TYPE_100M_HALF 2 -#define MEDIA_TYPE_10M_FULL 3 -#define MEDIA_TYPE_10M_HALF 4 - - u16 autoneg_advertised; -#define ADVERTISE_10_HALF 0x0001 -#define ADVERTISE_10_FULL 0x0002 -#define ADVERTISE_100_HALF 0x0004 -#define ADVERTISE_100_FULL 0x0008 -#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */ -#define ADVERTISE_1000_FULL 0x0020 - u16 mii_autoneg_adv_reg; - u16 mii_1000t_ctrl_reg; - - u16 imt; /* Interrupt Moderator timer ( 2us resolution) */ - u16 ict; /* Interrupt Clear timer (2us resolution) */ - u32 smb_timer; - u16 rrd_thresh; /* Threshold of number of RRD produced to trigger - interrupt request */ - u16 tpd_thresh; - u16 rx_count_down; /* 2us resolution */ - u16 tx_count_down; - - u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */ - enum atl1e_rrs_type rrs_type; - u32 base_cpu; - u32 indirect_tab; - - enum atl1e_dma_req_block dmar_block; - enum atl1e_dma_req_block dmaw_block; - u8 dmaw_dly_cnt; - u8 dmar_dly_cnt; - - bool phy_configured; - bool re_autoneg; - bool emi_ca; -}; - -/* - * wrapper around a pointer to a socket buffer, - * so a DMA handle can be stored along with the buffer - */ -struct atl1e_tx_buffer { - struct sk_buff *skb; - u16 flags; -#define ATL1E_TX_PCIMAP_SINGLE 0x0001 -#define ATL1E_TX_PCIMAP_PAGE 0x0002 -#define ATL1E_TX_PCIMAP_TYPE_MASK 0x0003 - u16 length; - dma_addr_t dma; -}; - -#define ATL1E_SET_PCIMAP_TYPE(tx_buff, type) do { \ - ((tx_buff)->flags) &= ~ATL1E_TX_PCIMAP_TYPE_MASK; \ - ((tx_buff)->flags) |= (type); \ - } while (0) - -struct atl1e_rx_page { - dma_addr_t dma; /* receive rage DMA address */ - u8 *addr; /* receive rage virtual address */ - dma_addr_t write_offset_dma; /* the DMA address which contain the - receive data offset in the page */ - u32 *write_offset_addr; /* the virtaul address which contain - the receive data offset in the page */ - u32 read_offset; /* the offset where we have read */ -}; - -struct atl1e_rx_page_desc { - struct atl1e_rx_page rx_page[AT_PAGE_NUM_PER_QUEUE]; - u8 rx_using; - u16 rx_nxseq; -}; - -/* transmit packet descriptor (tpd) ring */ -struct atl1e_tx_ring { - struct atl1e_tpd_desc *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - u16 count; /* the count of transmit rings */ - rwlock_t tx_lock; - u16 next_to_use; - atomic_t next_to_clean; - struct atl1e_tx_buffer *tx_buffer; - dma_addr_t cmb_dma; - u32 *cmb; -}; - -/* receive packet descriptor ring */ -struct atl1e_rx_ring { - void *desc; - dma_addr_t dma; - int size; - u32 page_size; /* bytes length of rxf page */ - u32 real_page_size; /* real_page_size = page_size + jumbo + aliagn */ - struct atl1e_rx_page_desc rx_page_desc[AT_MAX_RECEIVE_QUEUE]; -}; - -/* board specific private data structure */ -struct atl1e_adapter { - struct net_device *netdev; - struct pci_dev *pdev; - struct napi_struct napi; - struct mii_if_info mii; /* MII interface info */ - struct atl1e_hw hw; - struct atl1e_hw_stats hw_stats; - - u32 wol; - u16 link_speed; - u16 link_duplex; - - spinlock_t mdio_lock; - spinlock_t tx_lock; - atomic_t irq_sem; - - struct work_struct reset_task; - struct work_struct link_chg_task; - struct timer_list watchdog_timer; - struct timer_list phy_config_timer; - - /* All Descriptor memory */ - dma_addr_t ring_dma; - void *ring_vir_addr; - u32 ring_size; - - struct atl1e_tx_ring tx_ring; - struct atl1e_rx_ring rx_ring; - int num_rx_queues; - unsigned long flags; -#define __AT_TESTING 0x0001 -#define __AT_RESETTING 0x0002 -#define __AT_DOWN 0x0003 - - u32 bd_number; /* board number;*/ - u32 pci_state[16]; - u32 *config_space; -}; - -#define AT_WRITE_REG(a, reg, value) ( \ - writel((value), ((a)->hw_addr + reg))) - -#define AT_WRITE_FLUSH(a) (\ - readl((a)->hw_addr)) - -#define AT_READ_REG(a, reg) ( \ - readl((a)->hw_addr + reg)) - -#define AT_WRITE_REGB(a, reg, value) (\ - writeb((value), ((a)->hw_addr + reg))) - -#define AT_READ_REGB(a, reg) (\ - readb((a)->hw_addr + reg)) - -#define AT_WRITE_REGW(a, reg, value) (\ - writew((value), ((a)->hw_addr + reg))) - -#define AT_READ_REGW(a, reg) (\ - readw((a)->hw_addr + reg)) - -#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \ - writel((value), (((a)->hw_addr + reg) + ((offset) << 2)))) - -#define AT_READ_REG_ARRAY(a, reg, offset) ( \ - readl(((a)->hw_addr + reg) + ((offset) << 2))) - -extern char atl1e_driver_name[]; -extern char atl1e_driver_version[]; - -extern void atl1e_check_options(struct atl1e_adapter *adapter); -extern int atl1e_up(struct atl1e_adapter *adapter); -extern void atl1e_down(struct atl1e_adapter *adapter); -extern void atl1e_reinit_locked(struct atl1e_adapter *adapter); -extern s32 atl1e_reset_hw(struct atl1e_hw *hw); -extern void atl1e_set_ethtool_ops(struct net_device *netdev); -#endif /* _ATL1_E_H_ */ diff --git a/addons/atl1e/src/3.10.108/atl1e_ethtool.c b/addons/atl1e/src/3.10.108/atl1e_ethtool.c deleted file mode 100644 index 82b23861..00000000 --- a/addons/atl1e/src/3.10.108/atl1e_ethtool.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include -#include -#include - -#include "atl1e.h" - -static int atl1e_get_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - - ecmd->supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP); - if (hw->nic_type == athr_l1e) - ecmd->supported |= SUPPORTED_1000baseT_Full; - - ecmd->advertising = ADVERTISED_TP; - - ecmd->advertising |= ADVERTISED_Autoneg; - ecmd->advertising |= hw->autoneg_advertised; - - ecmd->port = PORT_TP; - ecmd->phy_address = 0; - ecmd->transceiver = XCVR_INTERNAL; - - if (adapter->link_speed != SPEED_0) { - ethtool_cmd_speed_set(ecmd, adapter->link_speed); - if (adapter->link_duplex == FULL_DUPLEX) - ecmd->duplex = DUPLEX_FULL; - else - ecmd->duplex = DUPLEX_HALF; - } else { - ethtool_cmd_speed_set(ecmd, -1); - ecmd->duplex = -1; - } - - ecmd->autoneg = AUTONEG_ENABLE; - return 0; -} - -static int atl1e_set_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - - while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) - msleep(1); - - if (ecmd->autoneg == AUTONEG_ENABLE) { - u16 adv4, adv9; - - if ((ecmd->advertising&ADVERTISE_1000_FULL)) { - if (hw->nic_type == athr_l1e) { - hw->autoneg_advertised = - ecmd->advertising & AT_ADV_MASK; - } else { - clear_bit(__AT_RESETTING, &adapter->flags); - return -EINVAL; - } - } else if (ecmd->advertising&ADVERTISE_1000_HALF) { - clear_bit(__AT_RESETTING, &adapter->flags); - return -EINVAL; - } else { - hw->autoneg_advertised = - ecmd->advertising & AT_ADV_MASK; - } - ecmd->advertising = hw->autoneg_advertised | - ADVERTISED_TP | ADVERTISED_Autoneg; - - adv4 = hw->mii_autoneg_adv_reg & ~ADVERTISE_ALL; - adv9 = hw->mii_1000t_ctrl_reg & ~MII_AT001_CR_1000T_SPEED_MASK; - if (hw->autoneg_advertised & ADVERTISE_10_HALF) - adv4 |= ADVERTISE_10HALF; - if (hw->autoneg_advertised & ADVERTISE_10_FULL) - adv4 |= ADVERTISE_10FULL; - if (hw->autoneg_advertised & ADVERTISE_100_HALF) - adv4 |= ADVERTISE_100HALF; - if (hw->autoneg_advertised & ADVERTISE_100_FULL) - adv4 |= ADVERTISE_100FULL; - if (hw->autoneg_advertised & ADVERTISE_1000_FULL) - adv9 |= ADVERTISE_1000FULL; - - if (adv4 != hw->mii_autoneg_adv_reg || - adv9 != hw->mii_1000t_ctrl_reg) { - hw->mii_autoneg_adv_reg = adv4; - hw->mii_1000t_ctrl_reg = adv9; - hw->re_autoneg = true; - } - - } else { - clear_bit(__AT_RESETTING, &adapter->flags); - return -EINVAL; - } - - /* reset the link */ - - if (netif_running(adapter->netdev)) { - atl1e_down(adapter); - atl1e_up(adapter); - } else - atl1e_reset_hw(&adapter->hw); - - clear_bit(__AT_RESETTING, &adapter->flags); - return 0; -} - -static u32 atl1e_get_msglevel(struct net_device *netdev) -{ -#ifdef DBG - return 1; -#else - return 0; -#endif -} - -static int atl1e_get_regs_len(struct net_device *netdev) -{ - return AT_REGS_LEN * sizeof(u32); -} - -static void atl1e_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - u32 *regs_buff = p; - u16 phy_data; - - memset(p, 0, AT_REGS_LEN * sizeof(u32)); - - regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; - - regs_buff[0] = AT_READ_REG(hw, REG_VPD_CAP); - regs_buff[1] = AT_READ_REG(hw, REG_SPI_FLASH_CTRL); - regs_buff[2] = AT_READ_REG(hw, REG_SPI_FLASH_CONFIG); - regs_buff[3] = AT_READ_REG(hw, REG_TWSI_CTRL); - regs_buff[4] = AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL); - regs_buff[5] = AT_READ_REG(hw, REG_MASTER_CTRL); - regs_buff[6] = AT_READ_REG(hw, REG_MANUAL_TIMER_INIT); - regs_buff[7] = AT_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT); - regs_buff[8] = AT_READ_REG(hw, REG_GPHY_CTRL); - regs_buff[9] = AT_READ_REG(hw, REG_CMBDISDMA_TIMER); - regs_buff[10] = AT_READ_REG(hw, REG_IDLE_STATUS); - regs_buff[11] = AT_READ_REG(hw, REG_MDIO_CTRL); - regs_buff[12] = AT_READ_REG(hw, REG_SERDES_LOCK); - regs_buff[13] = AT_READ_REG(hw, REG_MAC_CTRL); - regs_buff[14] = AT_READ_REG(hw, REG_MAC_IPG_IFG); - regs_buff[15] = AT_READ_REG(hw, REG_MAC_STA_ADDR); - regs_buff[16] = AT_READ_REG(hw, REG_MAC_STA_ADDR+4); - regs_buff[17] = AT_READ_REG(hw, REG_RX_HASH_TABLE); - regs_buff[18] = AT_READ_REG(hw, REG_RX_HASH_TABLE+4); - regs_buff[19] = AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL); - regs_buff[20] = AT_READ_REG(hw, REG_MTU); - regs_buff[21] = AT_READ_REG(hw, REG_WOL_CTRL); - regs_buff[22] = AT_READ_REG(hw, REG_SRAM_TRD_ADDR); - regs_buff[23] = AT_READ_REG(hw, REG_SRAM_TRD_LEN); - regs_buff[24] = AT_READ_REG(hw, REG_SRAM_RXF_ADDR); - regs_buff[25] = AT_READ_REG(hw, REG_SRAM_RXF_LEN); - regs_buff[26] = AT_READ_REG(hw, REG_SRAM_TXF_ADDR); - regs_buff[27] = AT_READ_REG(hw, REG_SRAM_TXF_LEN); - regs_buff[28] = AT_READ_REG(hw, REG_SRAM_TCPH_ADDR); - regs_buff[29] = AT_READ_REG(hw, REG_SRAM_PKTH_ADDR); - - atl1e_read_phy_reg(hw, MII_BMCR, &phy_data); - regs_buff[73] = (u32)phy_data; - atl1e_read_phy_reg(hw, MII_BMSR, &phy_data); - regs_buff[74] = (u32)phy_data; -} - -static int atl1e_get_eeprom_len(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - if (!atl1e_check_eeprom_exist(&adapter->hw)) - return AT_EEPROM_LEN; - else - return 0; -} - -static int atl1e_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - u32 *eeprom_buff; - int first_dword, last_dword; - int ret_val = 0; - int i; - - if (eeprom->len == 0) - return -EINVAL; - - if (atl1e_check_eeprom_exist(hw)) /* not exist */ - return -EINVAL; - - eeprom->magic = hw->vendor_id | (hw->device_id << 16); - - first_dword = eeprom->offset >> 2; - last_dword = (eeprom->offset + eeprom->len - 1) >> 2; - - eeprom_buff = kmalloc(sizeof(u32) * - (last_dword - first_dword + 1), GFP_KERNEL); - if (eeprom_buff == NULL) - return -ENOMEM; - - for (i = first_dword; i < last_dword; i++) { - if (!atl1e_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) { - kfree(eeprom_buff); - return -EIO; - } - } - - memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3), - eeprom->len); - kfree(eeprom_buff); - - return ret_val; -} - -static int atl1e_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - u32 *eeprom_buff; - u32 *ptr; - int first_dword, last_dword; - int ret_val = 0; - int i; - - if (eeprom->len == 0) - return -EOPNOTSUPP; - - if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) - return -EINVAL; - - first_dword = eeprom->offset >> 2; - last_dword = (eeprom->offset + eeprom->len - 1) >> 2; - eeprom_buff = kmalloc(AT_EEPROM_LEN, GFP_KERNEL); - if (eeprom_buff == NULL) - return -ENOMEM; - - ptr = eeprom_buff; - - if (eeprom->offset & 3) { - /* need read/modify/write of first changed EEPROM word */ - /* only the second byte of the word is being modified */ - if (!atl1e_read_eeprom(hw, first_dword * 4, &(eeprom_buff[0]))) { - ret_val = -EIO; - goto out; - } - ptr++; - } - if (((eeprom->offset + eeprom->len) & 3)) { - /* need read/modify/write of last changed EEPROM word */ - /* only the first byte of the word is being modified */ - - if (!atl1e_read_eeprom(hw, last_dword * 4, - &(eeprom_buff[last_dword - first_dword]))) { - ret_val = -EIO; - goto out; - } - } - - /* Device's eeprom is always little-endian, word addressable */ - memcpy(ptr, bytes, eeprom->len); - - for (i = 0; i < last_dword - first_dword + 1; i++) { - if (!atl1e_write_eeprom(hw, ((first_dword + i) * 4), - eeprom_buff[i])) { - ret_val = -EIO; - goto out; - } - } -out: - kfree(eeprom_buff); - return ret_val; -} - -static void atl1e_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - strlcpy(drvinfo->driver, atl1e_driver_name, sizeof(drvinfo->driver)); - strlcpy(drvinfo->version, atl1e_driver_version, - sizeof(drvinfo->version)); - strlcpy(drvinfo->fw_version, "L1e", sizeof(drvinfo->fw_version)); - strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), - sizeof(drvinfo->bus_info)); - drvinfo->n_stats = 0; - drvinfo->testinfo_len = 0; - drvinfo->regdump_len = atl1e_get_regs_len(netdev); - drvinfo->eedump_len = atl1e_get_eeprom_len(netdev); -} - -static void atl1e_get_wol(struct net_device *netdev, - struct ethtool_wolinfo *wol) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - wol->supported = WAKE_MAGIC | WAKE_PHY; - wol->wolopts = 0; - - if (adapter->wol & AT_WUFC_EX) - wol->wolopts |= WAKE_UCAST; - if (adapter->wol & AT_WUFC_MC) - wol->wolopts |= WAKE_MCAST; - if (adapter->wol & AT_WUFC_BC) - wol->wolopts |= WAKE_BCAST; - if (adapter->wol & AT_WUFC_MAG) - wol->wolopts |= WAKE_MAGIC; - if (adapter->wol & AT_WUFC_LNKC) - wol->wolopts |= WAKE_PHY; -} - -static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | - WAKE_UCAST | WAKE_MCAST | WAKE_BCAST)) - return -EOPNOTSUPP; - /* these settings will always override what we currently have */ - adapter->wol = 0; - - if (wol->wolopts & WAKE_MAGIC) - adapter->wol |= AT_WUFC_MAG; - if (wol->wolopts & WAKE_PHY) - adapter->wol |= AT_WUFC_LNKC; - - device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); - - return 0; -} - -static int atl1e_nway_reset(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - if (netif_running(netdev)) - atl1e_reinit_locked(adapter); - return 0; -} - -static const struct ethtool_ops atl1e_ethtool_ops = { - .get_settings = atl1e_get_settings, - .set_settings = atl1e_set_settings, - .get_drvinfo = atl1e_get_drvinfo, - .get_regs_len = atl1e_get_regs_len, - .get_regs = atl1e_get_regs, - .get_wol = atl1e_get_wol, - .set_wol = atl1e_set_wol, - .get_msglevel = atl1e_get_msglevel, - .nway_reset = atl1e_nway_reset, - .get_link = ethtool_op_get_link, - .get_eeprom_len = atl1e_get_eeprom_len, - .get_eeprom = atl1e_get_eeprom, - .set_eeprom = atl1e_set_eeprom, -}; - -void atl1e_set_ethtool_ops(struct net_device *netdev) -{ - SET_ETHTOOL_OPS(netdev, &atl1e_ethtool_ops); -} diff --git a/addons/atl1e/src/3.10.108/atl1e_hw.c b/addons/atl1e/src/3.10.108/atl1e_hw.c deleted file mode 100644 index 923063d2..00000000 --- a/addons/atl1e/src/3.10.108/atl1e_hw.c +++ /dev/null @@ -1,651 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include -#include -#include -#include - -#include "atl1e.h" - -/* - * check_eeprom_exist - * return 0 if eeprom exist - */ -int atl1e_check_eeprom_exist(struct atl1e_hw *hw) -{ - u32 value; - - value = AT_READ_REG(hw, REG_SPI_FLASH_CTRL); - if (value & SPI_FLASH_CTRL_EN_VPD) { - value &= ~SPI_FLASH_CTRL_EN_VPD; - AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value); - } - value = AT_READ_REGW(hw, REG_PCIE_CAP_LIST); - return ((value & 0xFF00) == 0x6C00) ? 0 : 1; -} - -void atl1e_hw_set_mac_addr(struct atl1e_hw *hw) -{ - u32 value; - /* - * 00-0B-6A-F6-00-DC - * 0: 6AF600DC 1: 000B - * low dword - */ - value = (((u32)hw->mac_addr[2]) << 24) | - (((u32)hw->mac_addr[3]) << 16) | - (((u32)hw->mac_addr[4]) << 8) | - (((u32)hw->mac_addr[5])) ; - AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value); - /* hight dword */ - value = (((u32)hw->mac_addr[0]) << 8) | - (((u32)hw->mac_addr[1])) ; - AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value); -} - -/* - * atl1e_get_permanent_address - * return 0 if get valid mac address, - */ -static int atl1e_get_permanent_address(struct atl1e_hw *hw) -{ - u32 addr[2]; - u32 i; - u32 twsi_ctrl_data; - u8 eth_addr[ETH_ALEN]; - - if (is_valid_ether_addr(hw->perm_mac_addr)) - return 0; - - /* init */ - addr[0] = addr[1] = 0; - - if (!atl1e_check_eeprom_exist(hw)) { - /* eeprom exist */ - twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL); - twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART; - AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data); - for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) { - msleep(10); - twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL); - if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0) - break; - } - if (i >= AT_TWSI_EEPROM_TIMEOUT) - return AT_ERR_TIMEOUT; - } - - /* maybe MAC-address is from BIOS */ - addr[0] = AT_READ_REG(hw, REG_MAC_STA_ADDR); - addr[1] = AT_READ_REG(hw, REG_MAC_STA_ADDR + 4); - *(u32 *) ð_addr[2] = swab32(addr[0]); - *(u16 *) ð_addr[0] = swab16(*(u16 *)&addr[1]); - - if (is_valid_ether_addr(eth_addr)) { - memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN); - return 0; - } - - return AT_ERR_EEPROM; -} - -bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value) -{ - return true; -} - -bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value) -{ - int i; - u32 control; - - if (offset & 3) - return false; /* address do not align */ - - AT_WRITE_REG(hw, REG_VPD_DATA, 0); - control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT; - AT_WRITE_REG(hw, REG_VPD_CAP, control); - - for (i = 0; i < 10; i++) { - msleep(2); - control = AT_READ_REG(hw, REG_VPD_CAP); - if (control & VPD_CAP_VPD_FLAG) - break; - } - if (control & VPD_CAP_VPD_FLAG) { - *p_value = AT_READ_REG(hw, REG_VPD_DATA); - return true; - } - return false; /* timeout */ -} - -void atl1e_force_ps(struct atl1e_hw *hw) -{ - AT_WRITE_REGW(hw, REG_GPHY_CTRL, - GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET); -} - -/* - * Reads the adapter's MAC address from the EEPROM - * - * hw - Struct containing variables accessed by shared code - */ -int atl1e_read_mac_addr(struct atl1e_hw *hw) -{ - int err = 0; - - err = atl1e_get_permanent_address(hw); - if (err) - return AT_ERR_EEPROM; - memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr)); - return 0; -} - -/* - * atl1e_hash_mc_addr - * purpose - * set hash value for a multicast address - */ -u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr) -{ - u32 crc32; - u32 value = 0; - int i; - - crc32 = ether_crc_le(6, mc_addr); - for (i = 0; i < 32; i++) - value |= (((crc32 >> i) & 1) << (31 - i)); - - return value; -} - -/* - * Sets the bit in the multicast table corresponding to the hash value. - * hw - Struct containing variables accessed by shared code - * hash_value - Multicast address hash value - */ -void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value) -{ - u32 hash_bit, hash_reg; - u32 mta; - - /* - * The HASH Table is a register array of 2 32-bit registers. - * It is treated like an array of 64 bits. We want to set - * bit BitArray[hash_value]. So we figure out what register - * the bit is in, read it, OR in the new bit, then write - * back the new value. The register is determined by the - * upper 7 bits of the hash value and the bit within that - * register are determined by the lower 5 bits of the value. - */ - hash_reg = (hash_value >> 31) & 0x1; - hash_bit = (hash_value >> 26) & 0x1F; - - mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg); - - mta |= (1 << hash_bit); - - AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta); -} -/* - * Reads the value from a PHY register - * hw - Struct containing variables accessed by shared code - * reg_addr - address of the PHY register to read - */ -int atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data) -{ - u32 val; - int i; - - val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT | - MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | - MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; - - AT_WRITE_REG(hw, REG_MDIO_CTRL, val); - - wmb(); - - for (i = 0; i < MDIO_WAIT_TIMES; i++) { - udelay(2); - val = AT_READ_REG(hw, REG_MDIO_CTRL); - if (!(val & (MDIO_START | MDIO_BUSY))) - break; - wmb(); - } - if (!(val & (MDIO_START | MDIO_BUSY))) { - *phy_data = (u16)val; - return 0; - } - - return AT_ERR_PHY; -} - -/* - * Writes a value to a PHY register - * hw - Struct containing variables accessed by shared code - * reg_addr - address of the PHY register to write - * data - data to write to the PHY - */ -int atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data) -{ - int i; - u32 val; - - val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT | - (reg_addr&MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT | - MDIO_SUP_PREAMBLE | - MDIO_START | - MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; - - AT_WRITE_REG(hw, REG_MDIO_CTRL, val); - wmb(); - - for (i = 0; i < MDIO_WAIT_TIMES; i++) { - udelay(2); - val = AT_READ_REG(hw, REG_MDIO_CTRL); - if (!(val & (MDIO_START | MDIO_BUSY))) - break; - wmb(); - } - - if (!(val & (MDIO_START | MDIO_BUSY))) - return 0; - - return AT_ERR_PHY; -} - -/* - * atl1e_init_pcie - init PCIE module - */ -static void atl1e_init_pcie(struct atl1e_hw *hw) -{ - u32 value; - /* comment 2lines below to save more power when sususpend - value = LTSSM_TEST_MODE_DEF; - AT_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value); - */ - - /* pcie flow control mode change */ - value = AT_READ_REG(hw, 0x1008); - value |= 0x8000; - AT_WRITE_REG(hw, 0x1008, value); -} -/* - * Configures PHY autoneg and flow control advertisement settings - * - * hw - Struct containing variables accessed by shared code - */ -static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw) -{ - s32 ret_val; - u16 mii_autoneg_adv_reg; - u16 mii_1000t_ctrl_reg; - - if (0 != hw->mii_autoneg_adv_reg) - return 0; - /* Read the MII Auto-Neg Advertisement Register (Address 4/9). */ - mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK; - mii_1000t_ctrl_reg = MII_AT001_CR_1000T_DEFAULT_CAP_MASK; - - /* - * Need to parse autoneg_advertised and set up - * the appropriate PHY registers. First we will parse for - * autoneg_advertised software override. Since we can advertise - * a plethora of combinations, we need to check each bit - * individually. - */ - - /* - * First we clear all the 10/100 mb speed bits in the Auto-Neg - * Advertisement Register (Address 4) and the 1000 mb speed bits in - * the 1000Base-T control Register (Address 9). - */ - mii_autoneg_adv_reg &= ~ADVERTISE_ALL; - mii_1000t_ctrl_reg &= ~MII_AT001_CR_1000T_SPEED_MASK; - - /* - * Need to parse MediaType and setup the - * appropriate PHY registers. - */ - switch (hw->media_type) { - case MEDIA_TYPE_AUTO_SENSOR: - mii_autoneg_adv_reg |= ADVERTISE_ALL; - hw->autoneg_advertised = ADVERTISE_ALL; - if (hw->nic_type == athr_l1e) { - mii_1000t_ctrl_reg |= ADVERTISE_1000FULL; - hw->autoneg_advertised |= ADVERTISE_1000_FULL; - } - break; - - case MEDIA_TYPE_100M_FULL: - mii_autoneg_adv_reg |= ADVERTISE_100FULL; - hw->autoneg_advertised = ADVERTISE_100_FULL; - break; - - case MEDIA_TYPE_100M_HALF: - mii_autoneg_adv_reg |= ADVERTISE_100_HALF; - hw->autoneg_advertised = ADVERTISE_100_HALF; - break; - - case MEDIA_TYPE_10M_FULL: - mii_autoneg_adv_reg |= ADVERTISE_10_FULL; - hw->autoneg_advertised = ADVERTISE_10_FULL; - break; - - default: - mii_autoneg_adv_reg |= ADVERTISE_10_HALF; - hw->autoneg_advertised = ADVERTISE_10_HALF; - break; - } - - /* flow control fixed to enable all */ - mii_autoneg_adv_reg |= (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP); - - hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg; - hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg; - - ret_val = atl1e_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg); - if (ret_val) - return ret_val; - - if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) { - ret_val = atl1e_write_phy_reg(hw, MII_CTRL1000, - mii_1000t_ctrl_reg); - if (ret_val) - return ret_val; - } - - return 0; -} - - -/* - * Resets the PHY and make all config validate - * - * hw - Struct containing variables accessed by shared code - * - * Sets bit 15 and 12 of the MII control regiser (for F001 bug) - */ -int atl1e_phy_commit(struct atl1e_hw *hw) -{ - struct atl1e_adapter *adapter = hw->adapter; - int ret_val; - u16 phy_data; - - phy_data = BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART; - - ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data); - if (ret_val) { - u32 val; - int i; - /************************************** - * pcie serdes link may be down ! - **************************************/ - for (i = 0; i < 25; i++) { - msleep(1); - val = AT_READ_REG(hw, REG_MDIO_CTRL); - if (!(val & (MDIO_START | MDIO_BUSY))) - break; - } - - if (0 != (val & (MDIO_START | MDIO_BUSY))) { - netdev_err(adapter->netdev, - "pcie linkdown at least for 25ms\n"); - return ret_val; - } - - netdev_err(adapter->netdev, "pcie linkup after %d ms\n", i); - } - return 0; -} - -int atl1e_phy_init(struct atl1e_hw *hw) -{ - struct atl1e_adapter *adapter = hw->adapter; - s32 ret_val; - u16 phy_val; - - if (hw->phy_configured) { - if (hw->re_autoneg) { - hw->re_autoneg = false; - return atl1e_restart_autoneg(hw); - } - return 0; - } - - /* RESET GPHY Core */ - AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT); - msleep(2); - AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT | - GPHY_CTRL_EXT_RESET); - msleep(2); - - /* patches */ - /* p1. eable hibernation mode */ - ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0xB); - if (ret_val) - return ret_val; - ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0xBC00); - if (ret_val) - return ret_val; - /* p2. set Class A/B for all modes */ - ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0); - if (ret_val) - return ret_val; - phy_val = 0x02ef; - /* remove Class AB */ - /* phy_val = hw->emi_ca ? 0x02ef : 0x02df; */ - ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, phy_val); - if (ret_val) - return ret_val; - /* p3. 10B ??? */ - ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x12); - if (ret_val) - return ret_val; - ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x4C04); - if (ret_val) - return ret_val; - /* p4. 1000T power */ - ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x4); - if (ret_val) - return ret_val; - ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x8BBB); - if (ret_val) - return ret_val; - - ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x5); - if (ret_val) - return ret_val; - ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x2C46); - if (ret_val) - return ret_val; - - msleep(1); - - /*Enable PHY LinkChange Interrupt */ - ret_val = atl1e_write_phy_reg(hw, MII_INT_CTRL, 0xC00); - if (ret_val) { - netdev_err(adapter->netdev, - "Error enable PHY linkChange Interrupt\n"); - return ret_val; - } - /* setup AutoNeg parameters */ - ret_val = atl1e_phy_setup_autoneg_adv(hw); - if (ret_val) { - netdev_err(adapter->netdev, - "Error Setting up Auto-Negotiation\n"); - return ret_val; - } - /* SW.Reset & En-Auto-Neg to restart Auto-Neg*/ - netdev_dbg(adapter->netdev, "Restarting Auto-Negotiation\n"); - ret_val = atl1e_phy_commit(hw); - if (ret_val) { - netdev_err(adapter->netdev, "Error resetting the phy\n"); - return ret_val; - } - - hw->phy_configured = true; - - return 0; -} - -/* - * Reset the transmit and receive units; mask and clear all interrupts. - * hw - Struct containing variables accessed by shared code - * return : 0 or idle status (if error) - */ -int atl1e_reset_hw(struct atl1e_hw *hw) -{ - struct atl1e_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; - - u32 idle_status_data = 0; - u16 pci_cfg_cmd_word = 0; - int timeout = 0; - - /* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */ - pci_read_config_word(pdev, PCI_REG_COMMAND, &pci_cfg_cmd_word); - if ((pci_cfg_cmd_word & (CMD_IO_SPACE | - CMD_MEMORY_SPACE | CMD_BUS_MASTER)) - != (CMD_IO_SPACE | CMD_MEMORY_SPACE | CMD_BUS_MASTER)) { - pci_cfg_cmd_word |= (CMD_IO_SPACE | - CMD_MEMORY_SPACE | CMD_BUS_MASTER); - pci_write_config_word(pdev, PCI_REG_COMMAND, pci_cfg_cmd_word); - } - - /* - * Issue Soft Reset to the MAC. This will reset the chip's - * transmit, receive, DMA. It will not effect - * the current PCI configuration. The global reset bit is self- - * clearing, and should clear within a microsecond. - */ - AT_WRITE_REG(hw, REG_MASTER_CTRL, - MASTER_CTRL_LED_MODE | MASTER_CTRL_SOFT_RST); - wmb(); - msleep(1); - - /* Wait at least 10ms for All module to be Idle */ - for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { - idle_status_data = AT_READ_REG(hw, REG_IDLE_STATUS); - if (idle_status_data == 0) - break; - msleep(1); - cpu_relax(); - } - - if (timeout >= AT_HW_MAX_IDLE_DELAY) { - netdev_err(adapter->netdev, - "MAC state machine can't be idle since disabled for 10ms second\n"); - return AT_ERR_TIMEOUT; - } - - return 0; -} - - -/* - * Performs basic configuration of the adapter. - * - * hw - Struct containing variables accessed by shared code - * Assumes that the controller has previously been reset and is in a - * post-reset uninitialized state. Initializes multicast table, - * and Calls routines to setup link - * Leaves the transmit and receive units disabled and uninitialized. - */ -int atl1e_init_hw(struct atl1e_hw *hw) -{ - s32 ret_val = 0; - - atl1e_init_pcie(hw); - - /* Zero out the Multicast HASH table */ - /* clear the old settings from the multicast hash table */ - AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); - AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); - - ret_val = atl1e_phy_init(hw); - - return ret_val; -} - -/* - * Detects the current speed and duplex settings of the hardware. - * - * hw - Struct containing variables accessed by shared code - * speed - Speed of the connection - * duplex - Duplex setting of the connection - */ -int atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex) -{ - int err; - u16 phy_data; - - /* Read PHY Specific Status Register (17) */ - err = atl1e_read_phy_reg(hw, MII_AT001_PSSR, &phy_data); - if (err) - return err; - - if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED)) - return AT_ERR_PHY_RES; - - switch (phy_data & MII_AT001_PSSR_SPEED) { - case MII_AT001_PSSR_1000MBS: - *speed = SPEED_1000; - break; - case MII_AT001_PSSR_100MBS: - *speed = SPEED_100; - break; - case MII_AT001_PSSR_10MBS: - *speed = SPEED_10; - break; - default: - return AT_ERR_PHY_SPEED; - break; - } - - if (phy_data & MII_AT001_PSSR_DPLX) - *duplex = FULL_DUPLEX; - else - *duplex = HALF_DUPLEX; - - return 0; -} - -int atl1e_restart_autoneg(struct atl1e_hw *hw) -{ - int err = 0; - - err = atl1e_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg); - if (err) - return err; - - if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) { - err = atl1e_write_phy_reg(hw, MII_CTRL1000, - hw->mii_1000t_ctrl_reg); - if (err) - return err; - } - - err = atl1e_write_phy_reg(hw, MII_BMCR, - BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART); - return err; -} - diff --git a/addons/atl1e/src/3.10.108/atl1e_hw.h b/addons/atl1e/src/3.10.108/atl1e_hw.h deleted file mode 100644 index 74df16ae..00000000 --- a/addons/atl1e/src/3.10.108/atl1e_hw.h +++ /dev/null @@ -1,690 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _ATHL1E_HW_H_ -#define _ATHL1E_HW_H_ - -#include -#include - -struct atl1e_adapter; -struct atl1e_hw; - -/* function prototype */ -s32 atl1e_reset_hw(struct atl1e_hw *hw); -s32 atl1e_read_mac_addr(struct atl1e_hw *hw); -s32 atl1e_init_hw(struct atl1e_hw *hw); -s32 atl1e_phy_commit(struct atl1e_hw *hw); -s32 atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex); -u32 atl1e_auto_get_fc(struct atl1e_adapter *adapter, u16 duplex); -u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr); -void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value); -s32 atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data); -s32 atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data); -s32 atl1e_validate_mdi_setting(struct atl1e_hw *hw); -void atl1e_hw_set_mac_addr(struct atl1e_hw *hw); -bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value); -bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value); -s32 atl1e_phy_enter_power_saving(struct atl1e_hw *hw); -s32 atl1e_phy_leave_power_saving(struct atl1e_hw *hw); -s32 atl1e_phy_init(struct atl1e_hw *hw); -int atl1e_check_eeprom_exist(struct atl1e_hw *hw); -void atl1e_force_ps(struct atl1e_hw *hw); -s32 atl1e_restart_autoneg(struct atl1e_hw *hw); - -/* register definition */ -#define REG_PM_CTRLSTAT 0x44 - -#define REG_PCIE_CAP_LIST 0x58 - -#define REG_DEVICE_CAP 0x5C -#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7 -#define DEVICE_CAP_MAX_PAYLOAD_SHIFT 0 - -#define REG_DEVICE_CTRL 0x60 -#define DEVICE_CTRL_MAX_PAYLOAD_MASK 0x7 -#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT 5 -#define DEVICE_CTRL_MAX_RREQ_SZ_MASK 0x7 -#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT 12 - -#define REG_VPD_CAP 0x6C -#define VPD_CAP_ID_MASK 0xff -#define VPD_CAP_ID_SHIFT 0 -#define VPD_CAP_NEXT_PTR_MASK 0xFF -#define VPD_CAP_NEXT_PTR_SHIFT 8 -#define VPD_CAP_VPD_ADDR_MASK 0x7FFF -#define VPD_CAP_VPD_ADDR_SHIFT 16 -#define VPD_CAP_VPD_FLAG 0x80000000 - -#define REG_VPD_DATA 0x70 - -#define REG_SPI_FLASH_CTRL 0x200 -#define SPI_FLASH_CTRL_STS_NON_RDY 0x1 -#define SPI_FLASH_CTRL_STS_WEN 0x2 -#define SPI_FLASH_CTRL_STS_WPEN 0x80 -#define SPI_FLASH_CTRL_DEV_STS_MASK 0xFF -#define SPI_FLASH_CTRL_DEV_STS_SHIFT 0 -#define SPI_FLASH_CTRL_INS_MASK 0x7 -#define SPI_FLASH_CTRL_INS_SHIFT 8 -#define SPI_FLASH_CTRL_START 0x800 -#define SPI_FLASH_CTRL_EN_VPD 0x2000 -#define SPI_FLASH_CTRL_LDSTART 0x8000 -#define SPI_FLASH_CTRL_CS_HI_MASK 0x3 -#define SPI_FLASH_CTRL_CS_HI_SHIFT 16 -#define SPI_FLASH_CTRL_CS_HOLD_MASK 0x3 -#define SPI_FLASH_CTRL_CS_HOLD_SHIFT 18 -#define SPI_FLASH_CTRL_CLK_LO_MASK 0x3 -#define SPI_FLASH_CTRL_CLK_LO_SHIFT 20 -#define SPI_FLASH_CTRL_CLK_HI_MASK 0x3 -#define SPI_FLASH_CTRL_CLK_HI_SHIFT 22 -#define SPI_FLASH_CTRL_CS_SETUP_MASK 0x3 -#define SPI_FLASH_CTRL_CS_SETUP_SHIFT 24 -#define SPI_FLASH_CTRL_EROM_PGSZ_MASK 0x3 -#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT 26 -#define SPI_FLASH_CTRL_WAIT_READY 0x10000000 - -#define REG_SPI_ADDR 0x204 - -#define REG_SPI_DATA 0x208 - -#define REG_SPI_FLASH_CONFIG 0x20C -#define SPI_FLASH_CONFIG_LD_ADDR_MASK 0xFFFFFF -#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT 0 -#define SPI_FLASH_CONFIG_VPD_ADDR_MASK 0x3 -#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24 -#define SPI_FLASH_CONFIG_LD_EXIST 0x4000000 - - -#define REG_SPI_FLASH_OP_PROGRAM 0x210 -#define REG_SPI_FLASH_OP_SC_ERASE 0x211 -#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212 -#define REG_SPI_FLASH_OP_RDID 0x213 -#define REG_SPI_FLASH_OP_WREN 0x214 -#define REG_SPI_FLASH_OP_RDSR 0x215 -#define REG_SPI_FLASH_OP_WRSR 0x216 -#define REG_SPI_FLASH_OP_READ 0x217 - -#define REG_TWSI_CTRL 0x218 -#define TWSI_CTRL_LD_OFFSET_MASK 0xFF -#define TWSI_CTRL_LD_OFFSET_SHIFT 0 -#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7 -#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8 -#define TWSI_CTRL_SW_LDSTART 0x800 -#define TWSI_CTRL_HW_LDSTART 0x1000 -#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x0x7F -#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15 -#define TWSI_CTRL_LD_EXIST 0x400000 -#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3 -#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23 -#define TWSI_CTRL_FREQ_SEL_100K 0 -#define TWSI_CTRL_FREQ_SEL_200K 1 -#define TWSI_CTRL_FREQ_SEL_300K 2 -#define TWSI_CTRL_FREQ_SEL_400K 3 -#define TWSI_CTRL_SMB_SLV_ADDR -#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3 -#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24 - - -#define REG_PCIE_DEV_MISC_CTRL 0x21C -#define PCIE_DEV_MISC_CTRL_EXT_PIPE 0x2 -#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1 -#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4 -#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN 0x8 -#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN 0x10 - -#define REG_PCIE_PHYMISC 0x1000 -#define PCIE_PHYMISC_FORCE_RCV_DET 0x4 - -#define REG_LTSSM_TEST_MODE 0x12FC -#define LTSSM_TEST_MODE_DEF 0xE000 - -/* Selene Master Control Register */ -#define REG_MASTER_CTRL 0x1400 -#define MASTER_CTRL_SOFT_RST 0x1 -#define MASTER_CTRL_MTIMER_EN 0x2 -#define MASTER_CTRL_ITIMER_EN 0x4 -#define MASTER_CTRL_MANUAL_INT 0x8 -#define MASTER_CTRL_ITIMER2_EN 0x20 -#define MASTER_CTRL_INT_RDCLR 0x40 -#define MASTER_CTRL_LED_MODE 0x200 -#define MASTER_CTRL_REV_NUM_SHIFT 16 -#define MASTER_CTRL_REV_NUM_MASK 0xff -#define MASTER_CTRL_DEV_ID_SHIFT 24 -#define MASTER_CTRL_DEV_ID_MASK 0xff - -/* Timer Initial Value Register */ -#define REG_MANUAL_TIMER_INIT 0x1404 - - -/* IRQ ModeratorTimer Initial Value Register */ -#define REG_IRQ_MODU_TIMER_INIT 0x1408 /* w */ -#define REG_IRQ_MODU_TIMER2_INIT 0x140A /* w */ - - -#define REG_GPHY_CTRL 0x140C -#define GPHY_CTRL_EXT_RESET 1 -#define GPHY_CTRL_PIPE_MOD 2 -#define GPHY_CTRL_TEST_MODE_MASK 3 -#define GPHY_CTRL_TEST_MODE_SHIFT 2 -#define GPHY_CTRL_BERT_START 0x10 -#define GPHY_CTRL_GATE_25M_EN 0x20 -#define GPHY_CTRL_LPW_EXIT 0x40 -#define GPHY_CTRL_PHY_IDDQ 0x80 -#define GPHY_CTRL_PHY_IDDQ_DIS 0x100 -#define GPHY_CTRL_PCLK_SEL_DIS 0x200 -#define GPHY_CTRL_HIB_EN 0x400 -#define GPHY_CTRL_HIB_PULSE 0x800 -#define GPHY_CTRL_SEL_ANA_RST 0x1000 -#define GPHY_CTRL_PHY_PLL_ON 0x2000 -#define GPHY_CTRL_PWDOWN_HW 0x4000 -#define GPHY_CTRL_DEFAULT (\ - GPHY_CTRL_PHY_PLL_ON |\ - GPHY_CTRL_SEL_ANA_RST |\ - GPHY_CTRL_HIB_PULSE |\ - GPHY_CTRL_HIB_EN) - -#define GPHY_CTRL_PW_WOL_DIS (\ - GPHY_CTRL_PHY_PLL_ON |\ - GPHY_CTRL_SEL_ANA_RST |\ - GPHY_CTRL_HIB_PULSE |\ - GPHY_CTRL_HIB_EN |\ - GPHY_CTRL_PWDOWN_HW |\ - GPHY_CTRL_PCLK_SEL_DIS |\ - GPHY_CTRL_PHY_IDDQ) - -/* IRQ Anti-Lost Timer Initial Value Register */ -#define REG_CMBDISDMA_TIMER 0x140E - - -/* Block IDLE Status Register */ -#define REG_IDLE_STATUS 0x1410 -#define IDLE_STATUS_RXMAC 1 /* 1: RXMAC state machine is in non-IDLE state. 0: RXMAC is idling */ -#define IDLE_STATUS_TXMAC 2 /* 1: TXMAC state machine is in non-IDLE state. 0: TXMAC is idling */ -#define IDLE_STATUS_RXQ 4 /* 1: RXQ state machine is in non-IDLE state. 0: RXQ is idling */ -#define IDLE_STATUS_TXQ 8 /* 1: TXQ state machine is in non-IDLE state. 0: TXQ is idling */ -#define IDLE_STATUS_DMAR 0x10 /* 1: DMAR state machine is in non-IDLE state. 0: DMAR is idling */ -#define IDLE_STATUS_DMAW 0x20 /* 1: DMAW state machine is in non-IDLE state. 0: DMAW is idling */ -#define IDLE_STATUS_SMB 0x40 /* 1: SMB state machine is in non-IDLE state. 0: SMB is idling */ -#define IDLE_STATUS_CMB 0x80 /* 1: CMB state machine is in non-IDLE state. 0: CMB is idling */ - -/* MDIO Control Register */ -#define REG_MDIO_CTRL 0x1414 -#define MDIO_DATA_MASK 0xffff /* On MDIO write, the 16-bit control data to write to PHY MII management register */ -#define MDIO_DATA_SHIFT 0 /* On MDIO read, the 16-bit status data that was read from the PHY MII management register*/ -#define MDIO_REG_ADDR_MASK 0x1f /* MDIO register address */ -#define MDIO_REG_ADDR_SHIFT 16 -#define MDIO_RW 0x200000 /* 1: read, 0: write */ -#define MDIO_SUP_PREAMBLE 0x400000 /* Suppress preamble */ -#define MDIO_START 0x800000 /* Write 1 to initiate the MDIO master. And this bit is self cleared after one cycle*/ -#define MDIO_CLK_SEL_SHIFT 24 -#define MDIO_CLK_25_4 0 -#define MDIO_CLK_25_6 2 -#define MDIO_CLK_25_8 3 -#define MDIO_CLK_25_10 4 -#define MDIO_CLK_25_14 5 -#define MDIO_CLK_25_20 6 -#define MDIO_CLK_25_28 7 -#define MDIO_BUSY 0x8000000 -#define MDIO_AP_EN 0x10000000 -#define MDIO_WAIT_TIMES 10 - -/* MII PHY Status Register */ -#define REG_PHY_STATUS 0x1418 -#define PHY_STATUS_100M 0x20000 -#define PHY_STATUS_EMI_CA 0x40000 - -/* BIST Control and Status Register0 (for the Packet Memory) */ -#define REG_BIST0_CTRL 0x141c -#define BIST0_NOW 0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */ -/* BIST process and reset to zero when BIST is done */ -#define BIST0_SRAM_FAIL 0x2 /* 1: The SRAM failure is un-repairable because it has address */ -/* decoder failure or more than 1 cell stuck-to-x failure */ -#define BIST0_FUSE_FLAG 0x4 /* 1: Indicating one cell has been fixed */ - -/* BIST Control and Status Register1(for the retry buffer of PCI Express) */ -#define REG_BIST1_CTRL 0x1420 -#define BIST1_NOW 0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */ -/* BIST process and reset to zero when BIST is done */ -#define BIST1_SRAM_FAIL 0x2 /* 1: The SRAM failure is un-repairable because it has address */ -/* decoder failure or more than 1 cell stuck-to-x failure.*/ -#define BIST1_FUSE_FLAG 0x4 - -/* SerDes Lock Detect Control and Status Register */ -#define REG_SERDES_LOCK 0x1424 -#define SERDES_LOCK_DETECT 1 /* 1: SerDes lock detected . This signal comes from Analog SerDes */ -#define SERDES_LOCK_DETECT_EN 2 /* 1: Enable SerDes Lock detect function */ - -/* MAC Control Register */ -#define REG_MAC_CTRL 0x1480 -#define MAC_CTRL_TX_EN 1 /* 1: Transmit Enable */ -#define MAC_CTRL_RX_EN 2 /* 1: Receive Enable */ -#define MAC_CTRL_TX_FLOW 4 /* 1: Transmit Flow Control Enable */ -#define MAC_CTRL_RX_FLOW 8 /* 1: Receive Flow Control Enable */ -#define MAC_CTRL_LOOPBACK 0x10 /* 1: Loop back at G/MII Interface */ -#define MAC_CTRL_DUPLX 0x20 /* 1: Full-duplex mode 0: Half-duplex mode */ -#define MAC_CTRL_ADD_CRC 0x40 /* 1: Instruct MAC to attach CRC on all egress Ethernet frames */ -#define MAC_CTRL_PAD 0x80 /* 1: Instruct MAC to pad short frames to 60-bytes, and then attach CRC. This bit has higher priority over CRC_EN */ -#define MAC_CTRL_LENCHK 0x100 /* 1: Instruct MAC to check if length field matches the real packet length */ -#define MAC_CTRL_HUGE_EN 0x200 /* 1: receive Jumbo frame enable */ -#define MAC_CTRL_PRMLEN_SHIFT 10 /* Preamble length */ -#define MAC_CTRL_PRMLEN_MASK 0xf -#define MAC_CTRL_RMV_VLAN 0x4000 /* 1: to remove VLAN Tag automatically from all receive packets */ -#define MAC_CTRL_PROMIS_EN 0x8000 /* 1: Promiscuous Mode Enable */ -#define MAC_CTRL_TX_PAUSE 0x10000 /* 1: transmit test pause */ -#define MAC_CTRL_SCNT 0x20000 /* 1: shortcut slot time counter */ -#define MAC_CTRL_SRST_TX 0x40000 /* 1: synchronized reset Transmit MAC module */ -#define MAC_CTRL_TX_SIMURST 0x80000 /* 1: transmit simulation reset */ -#define MAC_CTRL_SPEED_SHIFT 20 /* 10: gigabit 01:10M/100M */ -#define MAC_CTRL_SPEED_MASK 0x300000 -#define MAC_CTRL_SPEED_1000 2 -#define MAC_CTRL_SPEED_10_100 1 -#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000 /* 1: transmit maximum backoff (half-duplex test bit) */ -#define MAC_CTRL_TX_HUGE 0x800000 /* 1: transmit huge enable */ -#define MAC_CTRL_RX_CHKSUM_EN 0x1000000 /* 1: RX checksum enable */ -#define MAC_CTRL_MC_ALL_EN 0x2000000 /* 1: upload all multicast frame without error to system */ -#define MAC_CTRL_BC_EN 0x4000000 /* 1: upload all broadcast frame without error to system */ -#define MAC_CTRL_DBG 0x8000000 /* 1: upload all received frame to system (Debug Mode) */ - -/* MAC IPG/IFG Control Register */ -#define REG_MAC_IPG_IFG 0x1484 -#define MAC_IPG_IFG_IPGT_SHIFT 0 /* Desired back to back inter-packet gap. The default is 96-bit time */ -#define MAC_IPG_IFG_IPGT_MASK 0x7f -#define MAC_IPG_IFG_MIFG_SHIFT 8 /* Minimum number of IFG to enforce in between RX frames */ -#define MAC_IPG_IFG_MIFG_MASK 0xff /* Frame gap below such IFP is dropped */ -#define MAC_IPG_IFG_IPGR1_SHIFT 16 /* 64bit Carrier-Sense window */ -#define MAC_IPG_IFG_IPGR1_MASK 0x7f -#define MAC_IPG_IFG_IPGR2_SHIFT 24 /* 96-bit IPG window */ -#define MAC_IPG_IFG_IPGR2_MASK 0x7f - -/* MAC STATION ADDRESS */ -#define REG_MAC_STA_ADDR 0x1488 - -/* Hash table for multicast address */ -#define REG_RX_HASH_TABLE 0x1490 - - -/* MAC Half-Duplex Control Register */ -#define REG_MAC_HALF_DUPLX_CTRL 0x1498 -#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT 0 /* Collision Window */ -#define MAC_HALF_DUPLX_CTRL_LCOL_MASK 0x3ff -#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12 /* Retransmission maximum, afterwards the packet will be discarded */ -#define MAC_HALF_DUPLX_CTRL_RETRY_MASK 0xf -#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN 0x10000 /* 1: Allow the transmission of a packet which has been excessively deferred */ -#define MAC_HALF_DUPLX_CTRL_NO_BACK_C 0x20000 /* 1: No back-off on collision, immediately start the retransmission */ -#define MAC_HALF_DUPLX_CTRL_NO_BACK_P 0x40000 /* 1: No back-off on backpressure, immediately start the transmission after back pressure */ -#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */ -#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20 /* Maximum binary exponential number */ -#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xf -#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24 /* IPG to start JAM for collision based flow control in half-duplex */ -#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xf /* mode. In unit of 8-bit time */ - -/* Maximum Frame Length Control Register */ -#define REG_MTU 0x149c - -/* Wake-On-Lan control register */ -#define REG_WOL_CTRL 0x14a0 -#define WOL_PATTERN_EN 0x00000001 -#define WOL_PATTERN_PME_EN 0x00000002 -#define WOL_MAGIC_EN 0x00000004 -#define WOL_MAGIC_PME_EN 0x00000008 -#define WOL_LINK_CHG_EN 0x00000010 -#define WOL_LINK_CHG_PME_EN 0x00000020 -#define WOL_PATTERN_ST 0x00000100 -#define WOL_MAGIC_ST 0x00000200 -#define WOL_LINKCHG_ST 0x00000400 -#define WOL_CLK_SWITCH_EN 0x00008000 -#define WOL_PT0_EN 0x00010000 -#define WOL_PT1_EN 0x00020000 -#define WOL_PT2_EN 0x00040000 -#define WOL_PT3_EN 0x00080000 -#define WOL_PT4_EN 0x00100000 -#define WOL_PT5_EN 0x00200000 -#define WOL_PT6_EN 0x00400000 -/* WOL Length ( 2 DWORD ) */ -#define REG_WOL_PATTERN_LEN 0x14a4 -#define WOL_PT_LEN_MASK 0x7f -#define WOL_PT0_LEN_SHIFT 0 -#define WOL_PT1_LEN_SHIFT 8 -#define WOL_PT2_LEN_SHIFT 16 -#define WOL_PT3_LEN_SHIFT 24 -#define WOL_PT4_LEN_SHIFT 0 -#define WOL_PT5_LEN_SHIFT 8 -#define WOL_PT6_LEN_SHIFT 16 - -/* Internal SRAM Partition Register */ -#define REG_SRAM_TRD_ADDR 0x1518 -#define REG_SRAM_TRD_LEN 0x151C -#define REG_SRAM_RXF_ADDR 0x1520 -#define REG_SRAM_RXF_LEN 0x1524 -#define REG_SRAM_TXF_ADDR 0x1528 -#define REG_SRAM_TXF_LEN 0x152C -#define REG_SRAM_TCPH_ADDR 0x1530 -#define REG_SRAM_PKTH_ADDR 0x1532 - -/* Load Ptr Register */ -#define REG_LOAD_PTR 0x1534 /* Software sets this bit after the initialization of the head and tail */ - -/* - * addresses of all descriptors, as well as the following descriptor - * control register, which triggers each function block to load the head - * pointer to prepare for the operation. This bit is then self-cleared - * after one cycle. - */ - -/* Descriptor Control register */ -#define REG_RXF3_BASE_ADDR_HI 0x153C -#define REG_DESC_BASE_ADDR_HI 0x1540 -#define REG_RXF0_BASE_ADDR_HI 0x1540 /* share with DESC BASE ADDR HI */ -#define REG_HOST_RXF0_PAGE0_LO 0x1544 -#define REG_HOST_RXF0_PAGE1_LO 0x1548 -#define REG_TPD_BASE_ADDR_LO 0x154C -#define REG_RXF1_BASE_ADDR_HI 0x1550 -#define REG_RXF2_BASE_ADDR_HI 0x1554 -#define REG_HOST_RXFPAGE_SIZE 0x1558 -#define REG_TPD_RING_SIZE 0x155C -/* RSS about */ -#define REG_RSS_KEY0 0x14B0 -#define REG_RSS_KEY1 0x14B4 -#define REG_RSS_KEY2 0x14B8 -#define REG_RSS_KEY3 0x14BC -#define REG_RSS_KEY4 0x14C0 -#define REG_RSS_KEY5 0x14C4 -#define REG_RSS_KEY6 0x14C8 -#define REG_RSS_KEY7 0x14CC -#define REG_RSS_KEY8 0x14D0 -#define REG_RSS_KEY9 0x14D4 -#define REG_IDT_TABLE4 0x14E0 -#define REG_IDT_TABLE5 0x14E4 -#define REG_IDT_TABLE6 0x14E8 -#define REG_IDT_TABLE7 0x14EC -#define REG_IDT_TABLE0 0x1560 -#define REG_IDT_TABLE1 0x1564 -#define REG_IDT_TABLE2 0x1568 -#define REG_IDT_TABLE3 0x156C -#define REG_IDT_TABLE REG_IDT_TABLE0 -#define REG_RSS_HASH_VALUE 0x1570 -#define REG_RSS_HASH_FLAG 0x1574 -#define REG_BASE_CPU_NUMBER 0x157C - - -/* TXQ Control Register */ -#define REG_TXQ_CTRL 0x1580 -#define TXQ_CTRL_NUM_TPD_BURST_MASK 0xF -#define TXQ_CTRL_NUM_TPD_BURST_SHIFT 0 -#define TXQ_CTRL_EN 0x20 /* 1: Enable TXQ */ -#define TXQ_CTRL_ENH_MODE 0x40 /* Performance enhancement mode, in which up to two back-to-back DMA read commands might be dispatched. */ -#define TXQ_CTRL_TXF_BURST_NUM_SHIFT 16 /* Number of data byte to read in a cache-aligned burst. Each SRAM entry is 8-byte in length. */ -#define TXQ_CTRL_TXF_BURST_NUM_MASK 0xffff - -/* Jumbo packet Threshold for task offload */ -#define REG_TX_EARLY_TH 0x1584 /* Jumbo frame threshold in QWORD unit. Packet greater than */ -/* JUMBO_TASK_OFFLOAD_THRESHOLD will not be task offloaded. */ -#define TX_TX_EARLY_TH_MASK 0x7ff -#define TX_TX_EARLY_TH_SHIFT 0 - - -/* RXQ Control Register */ -#define REG_RXQ_CTRL 0x15A0 -#define RXQ_CTRL_PBA_ALIGN_32 0 /* rx-packet alignment */ -#define RXQ_CTRL_PBA_ALIGN_64 1 -#define RXQ_CTRL_PBA_ALIGN_128 2 -#define RXQ_CTRL_PBA_ALIGN_256 3 -#define RXQ_CTRL_Q1_EN 0x10 -#define RXQ_CTRL_Q2_EN 0x20 -#define RXQ_CTRL_Q3_EN 0x40 -#define RXQ_CTRL_IPV6_XSUM_VERIFY_EN 0x80 -#define RXQ_CTRL_HASH_TLEN_SHIFT 8 -#define RXQ_CTRL_HASH_TLEN_MASK 0xFF -#define RXQ_CTRL_HASH_TYPE_IPV4 0x10000 -#define RXQ_CTRL_HASH_TYPE_IPV4_TCP 0x20000 -#define RXQ_CTRL_HASH_TYPE_IPV6 0x40000 -#define RXQ_CTRL_HASH_TYPE_IPV6_TCP 0x80000 -#define RXQ_CTRL_RSS_MODE_DISABLE 0 -#define RXQ_CTRL_RSS_MODE_SQSINT 0x4000000 -#define RXQ_CTRL_RSS_MODE_MQUESINT 0x8000000 -#define RXQ_CTRL_RSS_MODE_MQUEMINT 0xC000000 -#define RXQ_CTRL_NIP_QUEUE_SEL_TBL 0x10000000 -#define RXQ_CTRL_HASH_ENABLE 0x20000000 -#define RXQ_CTRL_CUT_THRU_EN 0x40000000 -#define RXQ_CTRL_EN 0x80000000 - -/* Rx jumbo packet threshold and rrd retirement timer */ -#define REG_RXQ_JMBOSZ_RRDTIM 0x15A4 -/* - * Jumbo packet threshold for non-VLAN packet, in QWORD (64-bit) unit. - * When the packet length greater than or equal to this value, RXQ - * shall start cut-through forwarding of the received packet. - */ -#define RXQ_JMBOSZ_TH_MASK 0x7ff -#define RXQ_JMBOSZ_TH_SHIFT 0 /* RRD retirement timer. Decrement by 1 after every 512ns passes*/ -#define RXQ_JMBO_LKAH_MASK 0xf -#define RXQ_JMBO_LKAH_SHIFT 11 - -/* RXF flow control register */ -#define REG_RXQ_RXF_PAUSE_THRESH 0x15A8 -#define RXQ_RXF_PAUSE_TH_HI_SHIFT 0 -#define RXQ_RXF_PAUSE_TH_HI_MASK 0xfff -#define RXQ_RXF_PAUSE_TH_LO_SHIFT 16 -#define RXQ_RXF_PAUSE_TH_LO_MASK 0xfff - - -/* DMA Engine Control Register */ -#define REG_DMA_CTRL 0x15C0 -#define DMA_CTRL_DMAR_IN_ORDER 0x1 -#define DMA_CTRL_DMAR_ENH_ORDER 0x2 -#define DMA_CTRL_DMAR_OUT_ORDER 0x4 -#define DMA_CTRL_RCB_VALUE 0x8 -#define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4 -#define DMA_CTRL_DMAR_BURST_LEN_MASK 7 -#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7 -#define DMA_CTRL_DMAW_BURST_LEN_MASK 7 -#define DMA_CTRL_DMAR_REQ_PRI 0x400 -#define DMA_CTRL_DMAR_DLY_CNT_MASK 0x1F -#define DMA_CTRL_DMAR_DLY_CNT_SHIFT 11 -#define DMA_CTRL_DMAW_DLY_CNT_MASK 0xF -#define DMA_CTRL_DMAW_DLY_CNT_SHIFT 16 -#define DMA_CTRL_TXCMB_EN 0x100000 -#define DMA_CTRL_RXCMB_EN 0x200000 - - -/* CMB/SMB Control Register */ -#define REG_SMB_STAT_TIMER 0x15C4 -#define REG_TRIG_RRD_THRESH 0x15CA -#define REG_TRIG_TPD_THRESH 0x15C8 -#define REG_TRIG_TXTIMER 0x15CC -#define REG_TRIG_RXTIMER 0x15CE - -/* HOST RXF Page 1,2,3 address */ -#define REG_HOST_RXF1_PAGE0_LO 0x15D0 -#define REG_HOST_RXF1_PAGE1_LO 0x15D4 -#define REG_HOST_RXF2_PAGE0_LO 0x15D8 -#define REG_HOST_RXF2_PAGE1_LO 0x15DC -#define REG_HOST_RXF3_PAGE0_LO 0x15E0 -#define REG_HOST_RXF3_PAGE1_LO 0x15E4 - -/* Mail box */ -#define REG_MB_RXF1_RADDR 0x15B4 -#define REG_MB_RXF2_RADDR 0x15B8 -#define REG_MB_RXF3_RADDR 0x15BC -#define REG_MB_TPD_PROD_IDX 0x15F0 - -/* RXF-Page 0-3 PageNo & Valid bit */ -#define REG_HOST_RXF0_PAGE0_VLD 0x15F4 -#define HOST_RXF_VALID 1 -#define HOST_RXF_PAGENO_SHIFT 1 -#define HOST_RXF_PAGENO_MASK 0x7F -#define REG_HOST_RXF0_PAGE1_VLD 0x15F5 -#define REG_HOST_RXF1_PAGE0_VLD 0x15F6 -#define REG_HOST_RXF1_PAGE1_VLD 0x15F7 -#define REG_HOST_RXF2_PAGE0_VLD 0x15F8 -#define REG_HOST_RXF2_PAGE1_VLD 0x15F9 -#define REG_HOST_RXF3_PAGE0_VLD 0x15FA -#define REG_HOST_RXF3_PAGE1_VLD 0x15FB - -/* Interrupt Status Register */ -#define REG_ISR 0x1600 -#define ISR_SMB 1 -#define ISR_TIMER 2 /* Interrupt when Timer is counted down to zero */ -/* - * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set - * in Table 51 Selene Master Control Register (Offset 0x1400). - */ -#define ISR_MANUAL 4 -#define ISR_HW_RXF_OV 8 /* RXF overflow interrupt */ -#define ISR_HOST_RXF0_OV 0x10 -#define ISR_HOST_RXF1_OV 0x20 -#define ISR_HOST_RXF2_OV 0x40 -#define ISR_HOST_RXF3_OV 0x80 -#define ISR_TXF_UN 0x100 -#define ISR_RX0_PAGE_FULL 0x200 -#define ISR_DMAR_TO_RST 0x400 -#define ISR_DMAW_TO_RST 0x800 -#define ISR_GPHY 0x1000 -#define ISR_TX_CREDIT 0x2000 -#define ISR_GPHY_LPW 0x4000 /* GPHY low power state interrupt */ -#define ISR_RX_PKT 0x10000 /* One packet received, triggered by RFD */ -#define ISR_TX_PKT 0x20000 /* One packet transmitted, triggered by TPD */ -#define ISR_TX_DMA 0x40000 -#define ISR_RX_PKT_1 0x80000 -#define ISR_RX_PKT_2 0x100000 -#define ISR_RX_PKT_3 0x200000 -#define ISR_MAC_RX 0x400000 -#define ISR_MAC_TX 0x800000 -#define ISR_UR_DETECTED 0x1000000 -#define ISR_FERR_DETECTED 0x2000000 -#define ISR_NFERR_DETECTED 0x4000000 -#define ISR_CERR_DETECTED 0x8000000 -#define ISR_PHY_LINKDOWN 0x10000000 -#define ISR_DIS_INT 0x80000000 - - -/* Interrupt Mask Register */ -#define REG_IMR 0x1604 - - -#define IMR_NORMAL_MASK (\ - ISR_SMB |\ - ISR_TXF_UN |\ - ISR_HW_RXF_OV |\ - ISR_HOST_RXF0_OV|\ - ISR_MANUAL |\ - ISR_GPHY |\ - ISR_GPHY_LPW |\ - ISR_DMAR_TO_RST |\ - ISR_DMAW_TO_RST |\ - ISR_PHY_LINKDOWN|\ - ISR_RX_PKT |\ - ISR_TX_PKT) - -#define ISR_TX_EVENT (ISR_TXF_UN | ISR_TX_PKT) -#define ISR_RX_EVENT (ISR_HOST_RXF0_OV | ISR_HW_RXF_OV | ISR_RX_PKT) - -#define REG_MAC_RX_STATUS_BIN 0x1700 -#define REG_MAC_RX_STATUS_END 0x175c -#define REG_MAC_TX_STATUS_BIN 0x1760 -#define REG_MAC_TX_STATUS_END 0x17c0 - -/* Hardware Offset Register */ -#define REG_HOST_RXF0_PAGEOFF 0x1800 -#define REG_TPD_CONS_IDX 0x1804 -#define REG_HOST_RXF1_PAGEOFF 0x1808 -#define REG_HOST_RXF2_PAGEOFF 0x180C -#define REG_HOST_RXF3_PAGEOFF 0x1810 - -/* RXF-Page 0-3 Offset DMA Address */ -#define REG_HOST_RXF0_MB0_LO 0x1820 -#define REG_HOST_RXF0_MB1_LO 0x1824 -#define REG_HOST_RXF1_MB0_LO 0x1828 -#define REG_HOST_RXF1_MB1_LO 0x182C -#define REG_HOST_RXF2_MB0_LO 0x1830 -#define REG_HOST_RXF2_MB1_LO 0x1834 -#define REG_HOST_RXF3_MB0_LO 0x1838 -#define REG_HOST_RXF3_MB1_LO 0x183C - -/* Tpd CMB DMA Address */ -#define REG_HOST_TX_CMB_LO 0x1840 -#define REG_HOST_SMB_ADDR_LO 0x1844 - -/* DEBUG ADDR */ -#define REG_DEBUG_DATA0 0x1900 -#define REG_DEBUG_DATA1 0x1904 - -/***************************** MII definition ***************************************/ -/* PHY Common Register */ -#define MII_AT001_PSCR 0x10 -#define MII_AT001_PSSR 0x11 -#define MII_INT_CTRL 0x12 -#define MII_INT_STATUS 0x13 -#define MII_SMARTSPEED 0x14 -#define MII_LBRERROR 0x18 -#define MII_RESV2 0x1a - -#define MII_DBG_ADDR 0x1D -#define MII_DBG_DATA 0x1E - -/* Autoneg Advertisement Register */ -#define MII_AR_DEFAULT_CAP_MASK 0 - -/* 1000BASE-T Control Register */ -#define MII_AT001_CR_1000T_SPEED_MASK \ - (ADVERTISE_1000FULL | ADVERTISE_1000HALF) -#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK MII_AT001_CR_1000T_SPEED_MASK - -/* AT001 PHY Specific Control Register */ -#define MII_AT001_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */ -#define MII_AT001_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ -#define MII_AT001_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */ -#define MII_AT001_PSCR_MAC_POWERDOWN 0x0008 -#define MII_AT001_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low, - * 0=CLK125 toggling - */ -#define MII_AT001_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ -/* Manual MDI configuration */ -#define MII_AT001_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ -#define MII_AT001_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover, - * 100BASE-TX/10BASE-T: - * MDI Mode - */ -#define MII_AT001_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled - * all speeds. - */ -#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE 0x0080 -/* 1=Enable Extended 10BASE-T distance - * (Lower 10BASE-T RX Threshold) - * 0=Normal 10BASE-T RX Threshold */ -#define MII_AT001_PSCR_MII_5BIT_ENABLE 0x0100 -/* 1=5-Bit interface in 100BASE-TX - * 0=MII interface in 100BASE-TX */ -#define MII_AT001_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */ -#define MII_AT001_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */ -#define MII_AT001_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ -#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT 1 -#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT 5 -#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7 -/* AT001 PHY Specific Status Register */ -#define MII_AT001_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ -#define MII_AT001_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ -#define MII_AT001_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ -#define MII_AT001_PSSR_10MBS 0x0000 /* 00=10Mbs */ -#define MII_AT001_PSSR_100MBS 0x4000 /* 01=100Mbs */ -#define MII_AT001_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ - -#endif /*_ATHL1E_HW_H_*/ diff --git a/addons/atl1e/src/3.10.108/atl1e_main.c b/addons/atl1e/src/3.10.108/atl1e_main.c deleted file mode 100644 index c23bb02e..00000000 --- a/addons/atl1e/src/3.10.108/atl1e_main.c +++ /dev/null @@ -1,2559 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "atl1e.h" - -#define DRV_VERSION "1.0.0.7-NAPI" - -char atl1e_driver_name[] = "ATL1E"; -char atl1e_driver_version[] = DRV_VERSION; -#define PCI_DEVICE_ID_ATTANSIC_L1E 0x1026 -/* - * atl1e_pci_tbl - PCI Device ID Table - * - * Wildcard entries (PCI_ANY_ID) should come last - * Last entry must be all 0s - * - * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, - * Class, Class Mask, private data (not used) } - */ -static DEFINE_PCI_DEVICE_TABLE(atl1e_pci_tbl) = { - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1E)}, - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, 0x1066)}, - /* required last entry */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, atl1e_pci_tbl); - -MODULE_AUTHOR("Atheros Corporation, , Jie Yang "); -MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter); - -static const u16 -atl1e_rx_page_vld_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] = -{ - {REG_HOST_RXF0_PAGE0_VLD, REG_HOST_RXF0_PAGE1_VLD}, - {REG_HOST_RXF1_PAGE0_VLD, REG_HOST_RXF1_PAGE1_VLD}, - {REG_HOST_RXF2_PAGE0_VLD, REG_HOST_RXF2_PAGE1_VLD}, - {REG_HOST_RXF3_PAGE0_VLD, REG_HOST_RXF3_PAGE1_VLD} -}; - -static const u16 atl1e_rx_page_hi_addr_regs[AT_MAX_RECEIVE_QUEUE] = -{ - REG_RXF0_BASE_ADDR_HI, - REG_RXF1_BASE_ADDR_HI, - REG_RXF2_BASE_ADDR_HI, - REG_RXF3_BASE_ADDR_HI -}; - -static const u16 -atl1e_rx_page_lo_addr_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] = -{ - {REG_HOST_RXF0_PAGE0_LO, REG_HOST_RXF0_PAGE1_LO}, - {REG_HOST_RXF1_PAGE0_LO, REG_HOST_RXF1_PAGE1_LO}, - {REG_HOST_RXF2_PAGE0_LO, REG_HOST_RXF2_PAGE1_LO}, - {REG_HOST_RXF3_PAGE0_LO, REG_HOST_RXF3_PAGE1_LO} -}; - -static const u16 -atl1e_rx_page_write_offset_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] = -{ - {REG_HOST_RXF0_MB0_LO, REG_HOST_RXF0_MB1_LO}, - {REG_HOST_RXF1_MB0_LO, REG_HOST_RXF1_MB1_LO}, - {REG_HOST_RXF2_MB0_LO, REG_HOST_RXF2_MB1_LO}, - {REG_HOST_RXF3_MB0_LO, REG_HOST_RXF3_MB1_LO} -}; - -static const u16 atl1e_pay_load_size[] = { - 128, 256, 512, 1024, 2048, 4096, -}; - -/** - * atl1e_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - */ -static inline void atl1e_irq_enable(struct atl1e_adapter *adapter) -{ - if (likely(atomic_dec_and_test(&adapter->irq_sem))) { - AT_WRITE_REG(&adapter->hw, REG_ISR, 0); - AT_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK); - AT_WRITE_FLUSH(&adapter->hw); - } -} - -/** - * atl1e_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - */ -static inline void atl1e_irq_disable(struct atl1e_adapter *adapter) -{ - atomic_inc(&adapter->irq_sem); - AT_WRITE_REG(&adapter->hw, REG_IMR, 0); - AT_WRITE_FLUSH(&adapter->hw); - synchronize_irq(adapter->pdev->irq); -} - -/** - * atl1e_irq_reset - reset interrupt confiure on the NIC - * @adapter: board private structure - */ -static inline void atl1e_irq_reset(struct atl1e_adapter *adapter) -{ - atomic_set(&adapter->irq_sem, 0); - AT_WRITE_REG(&adapter->hw, REG_ISR, 0); - AT_WRITE_REG(&adapter->hw, REG_IMR, 0); - AT_WRITE_FLUSH(&adapter->hw); -} - -/** - * atl1e_phy_config - Timer Call-back - * @data: pointer to netdev cast into an unsigned long - */ -static void atl1e_phy_config(unsigned long data) -{ - struct atl1e_adapter *adapter = (struct atl1e_adapter *) data; - struct atl1e_hw *hw = &adapter->hw; - unsigned long flags; - - spin_lock_irqsave(&adapter->mdio_lock, flags); - atl1e_restart_autoneg(hw); - spin_unlock_irqrestore(&adapter->mdio_lock, flags); -} - -void atl1e_reinit_locked(struct atl1e_adapter *adapter) -{ - - WARN_ON(in_interrupt()); - while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) - msleep(1); - atl1e_down(adapter); - atl1e_up(adapter); - clear_bit(__AT_RESETTING, &adapter->flags); -} - -static void atl1e_reset_task(struct work_struct *work) -{ - struct atl1e_adapter *adapter; - adapter = container_of(work, struct atl1e_adapter, reset_task); - - atl1e_reinit_locked(adapter); -} - -static int atl1e_check_link(struct atl1e_adapter *adapter) -{ - struct atl1e_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - int err = 0; - u16 speed, duplex, phy_data; - - /* MII_BMSR must read twice */ - atl1e_read_phy_reg(hw, MII_BMSR, &phy_data); - atl1e_read_phy_reg(hw, MII_BMSR, &phy_data); - if ((phy_data & BMSR_LSTATUS) == 0) { - /* link down */ - if (netif_carrier_ok(netdev)) { /* old link state: Up */ - u32 value; - /* disable rx */ - value = AT_READ_REG(hw, REG_MAC_CTRL); - value &= ~MAC_CTRL_RX_EN; - AT_WRITE_REG(hw, REG_MAC_CTRL, value); - adapter->link_speed = SPEED_0; - netif_carrier_off(netdev); - netif_stop_queue(netdev); - } - } else { - /* Link Up */ - err = atl1e_get_speed_and_duplex(hw, &speed, &duplex); - if (unlikely(err)) - return err; - - /* link result is our setting */ - if (adapter->link_speed != speed || - adapter->link_duplex != duplex) { - adapter->link_speed = speed; - adapter->link_duplex = duplex; - atl1e_setup_mac_ctrl(adapter); - netdev_info(netdev, - "NIC Link is Up <%d Mbps %s Duplex>\n", - adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? - "Full" : "Half"); - } - - if (!netif_carrier_ok(netdev)) { - /* Link down -> Up */ - netif_carrier_on(netdev); - netif_wake_queue(netdev); - } - } - return 0; -} - -/** - * atl1e_link_chg_task - deal with link change event Out of interrupt context - * @netdev: network interface device structure - */ -static void atl1e_link_chg_task(struct work_struct *work) -{ - struct atl1e_adapter *adapter; - unsigned long flags; - - adapter = container_of(work, struct atl1e_adapter, link_chg_task); - spin_lock_irqsave(&adapter->mdio_lock, flags); - atl1e_check_link(adapter); - spin_unlock_irqrestore(&adapter->mdio_lock, flags); -} - -static void atl1e_link_chg_event(struct atl1e_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - u16 phy_data = 0; - u16 link_up = 0; - - spin_lock(&adapter->mdio_lock); - atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); - atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); - spin_unlock(&adapter->mdio_lock); - link_up = phy_data & BMSR_LSTATUS; - /* notify upper layer link down ASAP */ - if (!link_up) { - if (netif_carrier_ok(netdev)) { - /* old link state: Up */ - netdev_info(netdev, "NIC Link is Down\n"); - adapter->link_speed = SPEED_0; - netif_stop_queue(netdev); - } - } - schedule_work(&adapter->link_chg_task); -} - -static void atl1e_del_timer(struct atl1e_adapter *adapter) -{ - del_timer_sync(&adapter->phy_config_timer); -} - -static void atl1e_cancel_work(struct atl1e_adapter *adapter) -{ - cancel_work_sync(&adapter->reset_task); - cancel_work_sync(&adapter->link_chg_task); -} - -/** - * atl1e_tx_timeout - Respond to a Tx Hang - * @netdev: network interface device structure - */ -static void atl1e_tx_timeout(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - /* Do the reset outside of interrupt context */ - schedule_work(&adapter->reset_task); -} - -/** - * atl1e_set_multi - Multicast and Promiscuous mode set - * @netdev: network interface device structure - * - * The set_multi entry point is called whenever the multicast address - * list or the network interface flags are updated. This routine is - * responsible for configuring the hardware for proper multicast, - * promiscuous mode, and all-multi behavior. - */ -static void atl1e_set_multi(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - struct netdev_hw_addr *ha; - u32 mac_ctrl_data = 0; - u32 hash_value; - - /* Check for Promiscuous and All Multicast modes */ - mac_ctrl_data = AT_READ_REG(hw, REG_MAC_CTRL); - - if (netdev->flags & IFF_PROMISC) { - mac_ctrl_data |= MAC_CTRL_PROMIS_EN; - } else if (netdev->flags & IFF_ALLMULTI) { - mac_ctrl_data |= MAC_CTRL_MC_ALL_EN; - mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN; - } else { - mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN); - } - - AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); - - /* clear the old settings from the multicast hash table */ - AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); - AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); - - /* comoute mc addresses' hash value ,and put it into hash table */ - netdev_for_each_mc_addr(ha, netdev) { - hash_value = atl1e_hash_mc_addr(hw, ha->addr); - atl1e_hash_set(hw, hash_value); - } -} - -static void __atl1e_vlan_mode(netdev_features_t features, u32 *mac_ctrl_data) -{ - if (features & NETIF_F_HW_VLAN_CTAG_RX) { - /* enable VLAN tag insert/strip */ - *mac_ctrl_data |= MAC_CTRL_RMV_VLAN; - } else { - /* disable VLAN tag insert/strip */ - *mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN; - } -} - -static void atl1e_vlan_mode(struct net_device *netdev, - netdev_features_t features) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - u32 mac_ctrl_data = 0; - - netdev_dbg(adapter->netdev, "%s\n", __func__); - - atl1e_irq_disable(adapter); - mac_ctrl_data = AT_READ_REG(&adapter->hw, REG_MAC_CTRL); - __atl1e_vlan_mode(features, &mac_ctrl_data); - AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data); - atl1e_irq_enable(adapter); -} - -static void atl1e_restore_vlan(struct atl1e_adapter *adapter) -{ - netdev_dbg(adapter->netdev, "%s\n", __func__); - atl1e_vlan_mode(adapter->netdev, adapter->netdev->features); -} - -/** - * atl1e_set_mac - Change the Ethernet Address of the NIC - * @netdev: network interface device structure - * @p: pointer to an address structure - * - * Returns 0 on success, negative on failure - */ -static int atl1e_set_mac_addr(struct net_device *netdev, void *p) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - if (netif_running(netdev)) - return -EBUSY; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); - - atl1e_hw_set_mac_addr(&adapter->hw); - - return 0; -} - -static netdev_features_t atl1e_fix_features(struct net_device *netdev, - netdev_features_t 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_CTAG_RX) - features |= NETIF_F_HW_VLAN_CTAG_TX; - else - features &= ~NETIF_F_HW_VLAN_CTAG_TX; - - return features; -} - -static int atl1e_set_features(struct net_device *netdev, - netdev_features_t features) -{ - netdev_features_t changed = netdev->features ^ features; - - if (changed & NETIF_F_HW_VLAN_CTAG_RX) - atl1e_vlan_mode(netdev, features); - - return 0; -} - -/** - * atl1e_change_mtu - Change the Maximum Transfer Unit - * @netdev: network interface device structure - * @new_mtu: new value for maximum frame size - * - * Returns 0 on success, negative on failure - */ -static int atl1e_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - int old_mtu = netdev->mtu; - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; - - if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || - (max_frame > MAX_JUMBO_FRAME_SIZE)) { - netdev_warn(adapter->netdev, "invalid MTU setting\n"); - return -EINVAL; - } - /* set MTU */ - if (old_mtu != new_mtu && netif_running(netdev)) { - while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) - msleep(1); - netdev->mtu = new_mtu; - adapter->hw.max_frame_size = new_mtu; - adapter->hw.rx_jumbo_th = (max_frame + 7) >> 3; - atl1e_down(adapter); - atl1e_up(adapter); - clear_bit(__AT_RESETTING, &adapter->flags); - } - return 0; -} - -/* - * caller should hold mdio_lock - */ -static int atl1e_mdio_read(struct net_device *netdev, int phy_id, int reg_num) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - u16 result; - - atl1e_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result); - return result; -} - -static void atl1e_mdio_write(struct net_device *netdev, int phy_id, - int reg_num, int val) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - atl1e_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val); -} - -static int atl1e_mii_ioctl(struct net_device *netdev, - struct ifreq *ifr, int cmd) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct mii_ioctl_data *data = if_mii(ifr); - unsigned long flags; - int retval = 0; - - if (!netif_running(netdev)) - return -EINVAL; - - spin_lock_irqsave(&adapter->mdio_lock, flags); - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 0; - break; - - case SIOCGMIIREG: - if (atl1e_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, - &data->val_out)) { - retval = -EIO; - goto out; - } - break; - - case SIOCSMIIREG: - if (data->reg_num & ~(0x1F)) { - retval = -EFAULT; - goto out; - } - - netdev_dbg(adapter->netdev, " write %x %x\n", - data->reg_num, data->val_in); - if (atl1e_write_phy_reg(&adapter->hw, - data->reg_num, data->val_in)) { - retval = -EIO; - goto out; - } - break; - - default: - retval = -EOPNOTSUPP; - break; - } -out: - spin_unlock_irqrestore(&adapter->mdio_lock, flags); - return retval; - -} - -static int atl1e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return atl1e_mii_ioctl(netdev, ifr, cmd); - default: - return -EOPNOTSUPP; - } -} - -static void atl1e_setup_pcicmd(struct pci_dev *pdev) -{ - u16 cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd &= ~(PCI_COMMAND_INTX_DISABLE | PCI_COMMAND_IO); - cmd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - pci_write_config_word(pdev, PCI_COMMAND, cmd); - - /* - * some motherboards BIOS(PXE/EFI) driver may set PME - * while they transfer control to OS (Windows/Linux) - * so we should clear this bit before NIC work normally - */ - pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0); - msleep(1); -} - -/** - * atl1e_alloc_queues - Allocate memory for all rings - * @adapter: board private structure to initialize - * - */ -static int atl1e_alloc_queues(struct atl1e_adapter *adapter) -{ - return 0; -} - -/** - * atl1e_sw_init - Initialize general software structures (struct atl1e_adapter) - * @adapter: board private structure to initialize - * - * atl1e_sw_init initializes the Adapter private data structure. - * Fields are initialized based on PCI device information and - * OS network device settings (MTU size). - */ -static int atl1e_sw_init(struct atl1e_adapter *adapter) -{ - struct atl1e_hw *hw = &adapter->hw; - struct pci_dev *pdev = adapter->pdev; - u32 phy_status_data = 0; - - adapter->wol = 0; - adapter->link_speed = SPEED_0; /* hardware init */ - adapter->link_duplex = FULL_DUPLEX; - adapter->num_rx_queues = 1; - - /* PCI config space info */ - hw->vendor_id = pdev->vendor; - hw->device_id = pdev->device; - hw->subsystem_vendor_id = pdev->subsystem_vendor; - hw->subsystem_id = pdev->subsystem_device; - hw->revision_id = pdev->revision; - - pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); - - phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS); - /* nic type */ - if (hw->revision_id >= 0xF0) { - hw->nic_type = athr_l2e_revB; - } else { - if (phy_status_data & PHY_STATUS_100M) - hw->nic_type = athr_l1e; - else - hw->nic_type = athr_l2e_revA; - } - - phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS); - - if (phy_status_data & PHY_STATUS_EMI_CA) - hw->emi_ca = true; - else - hw->emi_ca = false; - - hw->phy_configured = false; - hw->preamble_len = 7; - hw->max_frame_size = adapter->netdev->mtu; - hw->rx_jumbo_th = (hw->max_frame_size + ETH_HLEN + - VLAN_HLEN + ETH_FCS_LEN + 7) >> 3; - - hw->rrs_type = atl1e_rrs_disable; - hw->indirect_tab = 0; - hw->base_cpu = 0; - - /* need confirm */ - - hw->ict = 50000; /* 100ms */ - hw->smb_timer = 200000; /* 200ms */ - hw->tpd_burst = 5; - hw->rrd_thresh = 1; - hw->tpd_thresh = adapter->tx_ring.count / 2; - hw->rx_count_down = 4; /* 2us resolution */ - hw->tx_count_down = hw->imt * 4 / 3; - hw->dmar_block = atl1e_dma_req_1024; - hw->dmaw_block = atl1e_dma_req_1024; - hw->dmar_dly_cnt = 15; - hw->dmaw_dly_cnt = 4; - - if (atl1e_alloc_queues(adapter)) { - netdev_err(adapter->netdev, "Unable to allocate memory for queues\n"); - return -ENOMEM; - } - - atomic_set(&adapter->irq_sem, 1); - spin_lock_init(&adapter->mdio_lock); - spin_lock_init(&adapter->tx_lock); - - set_bit(__AT_DOWN, &adapter->flags); - - return 0; -} - -/** - * atl1e_clean_tx_ring - Free Tx-skb - * @adapter: board private structure - */ -static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter) -{ - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - struct atl1e_tx_buffer *tx_buffer = NULL; - struct pci_dev *pdev = adapter->pdev; - u16 index, ring_count; - - if (tx_ring->desc == NULL || tx_ring->tx_buffer == NULL) - return; - - ring_count = tx_ring->count; - /* first unmmap dma */ - for (index = 0; index < ring_count; index++) { - tx_buffer = &tx_ring->tx_buffer[index]; - if (tx_buffer->dma) { - if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE) - pci_unmap_single(pdev, tx_buffer->dma, - tx_buffer->length, PCI_DMA_TODEVICE); - else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE) - pci_unmap_page(pdev, tx_buffer->dma, - tx_buffer->length, PCI_DMA_TODEVICE); - tx_buffer->dma = 0; - } - } - /* second free skb */ - for (index = 0; index < ring_count; index++) { - tx_buffer = &tx_ring->tx_buffer[index]; - if (tx_buffer->skb) { - dev_kfree_skb_any(tx_buffer->skb); - tx_buffer->skb = NULL; - } - } - /* Zero out Tx-buffers */ - memset(tx_ring->desc, 0, sizeof(struct atl1e_tpd_desc) * - ring_count); - memset(tx_ring->tx_buffer, 0, sizeof(struct atl1e_tx_buffer) * - ring_count); -} - -/** - * atl1e_clean_rx_ring - Free rx-reservation skbs - * @adapter: board private structure - */ -static void atl1e_clean_rx_ring(struct atl1e_adapter *adapter) -{ - struct atl1e_rx_ring *rx_ring = - &adapter->rx_ring; - struct atl1e_rx_page_desc *rx_page_desc = rx_ring->rx_page_desc; - u16 i, j; - - - if (adapter->ring_vir_addr == NULL) - return; - /* Zero out the descriptor ring */ - for (i = 0; i < adapter->num_rx_queues; i++) { - for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) { - if (rx_page_desc[i].rx_page[j].addr != NULL) { - memset(rx_page_desc[i].rx_page[j].addr, 0, - rx_ring->real_page_size); - } - } - } -} - -static void atl1e_cal_ring_size(struct atl1e_adapter *adapter, u32 *ring_size) -{ - *ring_size = ((u32)(adapter->tx_ring.count * - sizeof(struct atl1e_tpd_desc) + 7 - /* tx ring, qword align */ - + adapter->rx_ring.real_page_size * AT_PAGE_NUM_PER_QUEUE * - adapter->num_rx_queues + 31 - /* rx ring, 32 bytes align */ - + (1 + AT_PAGE_NUM_PER_QUEUE * adapter->num_rx_queues) * - sizeof(u32) + 3)); - /* tx, rx cmd, dword align */ -} - -static void atl1e_init_ring_resources(struct atl1e_adapter *adapter) -{ - struct atl1e_rx_ring *rx_ring = NULL; - - rx_ring = &adapter->rx_ring; - - rx_ring->real_page_size = adapter->rx_ring.page_size - + adapter->hw.max_frame_size - + ETH_HLEN + VLAN_HLEN - + ETH_FCS_LEN; - rx_ring->real_page_size = roundup(rx_ring->real_page_size, 32); - atl1e_cal_ring_size(adapter, &adapter->ring_size); - - adapter->ring_vir_addr = NULL; - adapter->rx_ring.desc = NULL; - rwlock_init(&adapter->tx_ring.tx_lock); -} - -/* - * Read / Write Ptr Initialize: - */ -static void atl1e_init_ring_ptrs(struct atl1e_adapter *adapter) -{ - struct atl1e_tx_ring *tx_ring = NULL; - struct atl1e_rx_ring *rx_ring = NULL; - struct atl1e_rx_page_desc *rx_page_desc = NULL; - int i, j; - - tx_ring = &adapter->tx_ring; - rx_ring = &adapter->rx_ring; - rx_page_desc = rx_ring->rx_page_desc; - - tx_ring->next_to_use = 0; - atomic_set(&tx_ring->next_to_clean, 0); - - for (i = 0; i < adapter->num_rx_queues; i++) { - rx_page_desc[i].rx_using = 0; - rx_page_desc[i].rx_nxseq = 0; - for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) { - *rx_page_desc[i].rx_page[j].write_offset_addr = 0; - rx_page_desc[i].rx_page[j].read_offset = 0; - } - } -} - -/** - * atl1e_free_ring_resources - Free Tx / RX descriptor Resources - * @adapter: board private structure - * - * Free all transmit software resources - */ -static void atl1e_free_ring_resources(struct atl1e_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - - atl1e_clean_tx_ring(adapter); - atl1e_clean_rx_ring(adapter); - - if (adapter->ring_vir_addr) { - pci_free_consistent(pdev, adapter->ring_size, - adapter->ring_vir_addr, adapter->ring_dma); - adapter->ring_vir_addr = NULL; - } - - if (adapter->tx_ring.tx_buffer) { - kfree(adapter->tx_ring.tx_buffer); - adapter->tx_ring.tx_buffer = NULL; - } -} - -/** - * atl1e_setup_mem_resources - allocate Tx / RX descriptor resources - * @adapter: board private structure - * - * Return 0 on success, negative on failure - */ -static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - struct atl1e_tx_ring *tx_ring; - struct atl1e_rx_ring *rx_ring; - struct atl1e_rx_page_desc *rx_page_desc; - int size, i, j; - u32 offset = 0; - int err = 0; - - if (adapter->ring_vir_addr != NULL) - return 0; /* alloced already */ - - tx_ring = &adapter->tx_ring; - rx_ring = &adapter->rx_ring; - - /* real ring DMA buffer */ - - size = adapter->ring_size; - adapter->ring_vir_addr = pci_alloc_consistent(pdev, - adapter->ring_size, &adapter->ring_dma); - - if (adapter->ring_vir_addr == NULL) { - netdev_err(adapter->netdev, - "pci_alloc_consistent failed, size = D%d\n", size); - return -ENOMEM; - } - - memset(adapter->ring_vir_addr, 0, adapter->ring_size); - - rx_page_desc = rx_ring->rx_page_desc; - - /* Init TPD Ring */ - tx_ring->dma = roundup(adapter->ring_dma, 8); - offset = tx_ring->dma - adapter->ring_dma; - tx_ring->desc = adapter->ring_vir_addr + offset; - size = sizeof(struct atl1e_tx_buffer) * (tx_ring->count); - tx_ring->tx_buffer = kzalloc(size, GFP_KERNEL); - if (tx_ring->tx_buffer == NULL) { - err = -ENOMEM; - goto failed; - } - - /* Init RXF-Pages */ - offset += (sizeof(struct atl1e_tpd_desc) * tx_ring->count); - offset = roundup(offset, 32); - - for (i = 0; i < adapter->num_rx_queues; i++) { - for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) { - rx_page_desc[i].rx_page[j].dma = - adapter->ring_dma + offset; - rx_page_desc[i].rx_page[j].addr = - adapter->ring_vir_addr + offset; - offset += rx_ring->real_page_size; - } - } - - /* Init CMB dma address */ - tx_ring->cmb_dma = adapter->ring_dma + offset; - tx_ring->cmb = adapter->ring_vir_addr + offset; - offset += sizeof(u32); - - for (i = 0; i < adapter->num_rx_queues; i++) { - for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) { - rx_page_desc[i].rx_page[j].write_offset_dma = - adapter->ring_dma + offset; - rx_page_desc[i].rx_page[j].write_offset_addr = - adapter->ring_vir_addr + offset; - offset += sizeof(u32); - } - } - - if (unlikely(offset > adapter->ring_size)) { - netdev_err(adapter->netdev, "offset(%d) > ring size(%d) !!\n", - offset, adapter->ring_size); - err = -1; - goto failed; - } - - return 0; -failed: - if (adapter->ring_vir_addr != NULL) { - pci_free_consistent(pdev, adapter->ring_size, - adapter->ring_vir_addr, adapter->ring_dma); - adapter->ring_vir_addr = NULL; - } - return err; -} - -static inline void atl1e_configure_des_ring(struct atl1e_adapter *adapter) -{ - - struct atl1e_hw *hw = &adapter->hw; - struct atl1e_rx_ring *rx_ring = &adapter->rx_ring; - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - struct atl1e_rx_page_desc *rx_page_desc = NULL; - int i, j; - - AT_WRITE_REG(hw, REG_DESC_BASE_ADDR_HI, - (u32)((adapter->ring_dma & AT_DMA_HI_ADDR_MASK) >> 32)); - AT_WRITE_REG(hw, REG_TPD_BASE_ADDR_LO, - (u32)((tx_ring->dma) & AT_DMA_LO_ADDR_MASK)); - AT_WRITE_REG(hw, REG_TPD_RING_SIZE, (u16)(tx_ring->count)); - AT_WRITE_REG(hw, REG_HOST_TX_CMB_LO, - (u32)((tx_ring->cmb_dma) & AT_DMA_LO_ADDR_MASK)); - - rx_page_desc = rx_ring->rx_page_desc; - /* RXF Page Physical address / Page Length */ - for (i = 0; i < AT_MAX_RECEIVE_QUEUE; i++) { - AT_WRITE_REG(hw, atl1e_rx_page_hi_addr_regs[i], - (u32)((adapter->ring_dma & - AT_DMA_HI_ADDR_MASK) >> 32)); - for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) { - u32 page_phy_addr; - u32 offset_phy_addr; - - page_phy_addr = rx_page_desc[i].rx_page[j].dma; - offset_phy_addr = - rx_page_desc[i].rx_page[j].write_offset_dma; - - AT_WRITE_REG(hw, atl1e_rx_page_lo_addr_regs[i][j], - page_phy_addr & AT_DMA_LO_ADDR_MASK); - AT_WRITE_REG(hw, atl1e_rx_page_write_offset_regs[i][j], - offset_phy_addr & AT_DMA_LO_ADDR_MASK); - AT_WRITE_REGB(hw, atl1e_rx_page_vld_regs[i][j], 1); - } - } - /* Page Length */ - AT_WRITE_REG(hw, REG_HOST_RXFPAGE_SIZE, rx_ring->page_size); - /* Load all of base address above */ - AT_WRITE_REG(hw, REG_LOAD_PTR, 1); -} - -static inline void atl1e_configure_tx(struct atl1e_adapter *adapter) -{ - struct atl1e_hw *hw = &adapter->hw; - u32 dev_ctrl_data = 0; - u32 max_pay_load = 0; - u32 jumbo_thresh = 0; - u32 extra_size = 0; /* Jumbo frame threshold in QWORD unit */ - - /* configure TXQ param */ - if (hw->nic_type != athr_l2e_revB) { - extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN; - if (hw->max_frame_size <= 1500) { - jumbo_thresh = hw->max_frame_size + extra_size; - } else if (hw->max_frame_size < 6*1024) { - jumbo_thresh = - (hw->max_frame_size + extra_size) * 2 / 3; - } else { - jumbo_thresh = (hw->max_frame_size + extra_size) / 2; - } - AT_WRITE_REG(hw, REG_TX_EARLY_TH, (jumbo_thresh + 7) >> 3); - } - - dev_ctrl_data = AT_READ_REG(hw, REG_DEVICE_CTRL); - - max_pay_load = ((dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT)) & - DEVICE_CTRL_MAX_PAYLOAD_MASK; - - hw->dmaw_block = min_t(u32, max_pay_load, hw->dmaw_block); - - max_pay_load = ((dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT)) & - DEVICE_CTRL_MAX_RREQ_SZ_MASK; - hw->dmar_block = min_t(u32, max_pay_load, hw->dmar_block); - - if (hw->nic_type != athr_l2e_revB) - AT_WRITE_REGW(hw, REG_TXQ_CTRL + 2, - atl1e_pay_load_size[hw->dmar_block]); - /* enable TXQ */ - AT_WRITE_REGW(hw, REG_TXQ_CTRL, - (((u16)hw->tpd_burst & TXQ_CTRL_NUM_TPD_BURST_MASK) - << TXQ_CTRL_NUM_TPD_BURST_SHIFT) - | TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN); -} - -static inline void atl1e_configure_rx(struct atl1e_adapter *adapter) -{ - struct atl1e_hw *hw = &adapter->hw; - u32 rxf_len = 0; - u32 rxf_low = 0; - u32 rxf_high = 0; - u32 rxf_thresh_data = 0; - u32 rxq_ctrl_data = 0; - - if (hw->nic_type != athr_l2e_revB) { - AT_WRITE_REGW(hw, REG_RXQ_JMBOSZ_RRDTIM, - (u16)((hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK) << - RXQ_JMBOSZ_TH_SHIFT | - (1 & RXQ_JMBO_LKAH_MASK) << - RXQ_JMBO_LKAH_SHIFT)); - - rxf_len = AT_READ_REG(hw, REG_SRAM_RXF_LEN); - rxf_high = rxf_len * 4 / 5; - rxf_low = rxf_len / 5; - rxf_thresh_data = ((rxf_high & RXQ_RXF_PAUSE_TH_HI_MASK) - << RXQ_RXF_PAUSE_TH_HI_SHIFT) | - ((rxf_low & RXQ_RXF_PAUSE_TH_LO_MASK) - << RXQ_RXF_PAUSE_TH_LO_SHIFT); - - AT_WRITE_REG(hw, REG_RXQ_RXF_PAUSE_THRESH, rxf_thresh_data); - } - - /* RRS */ - AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab); - AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu); - - if (hw->rrs_type & atl1e_rrs_ipv4) - rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV4; - - if (hw->rrs_type & atl1e_rrs_ipv4_tcp) - rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV4_TCP; - - if (hw->rrs_type & atl1e_rrs_ipv6) - rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV6; - - if (hw->rrs_type & atl1e_rrs_ipv6_tcp) - rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV6_TCP; - - if (hw->rrs_type != atl1e_rrs_disable) - rxq_ctrl_data |= - (RXQ_CTRL_HASH_ENABLE | RXQ_CTRL_RSS_MODE_MQUESINT); - - rxq_ctrl_data |= RXQ_CTRL_IPV6_XSUM_VERIFY_EN | RXQ_CTRL_PBA_ALIGN_32 | - RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN; - - AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data); -} - -static inline void atl1e_configure_dma(struct atl1e_adapter *adapter) -{ - struct atl1e_hw *hw = &adapter->hw; - u32 dma_ctrl_data = 0; - - dma_ctrl_data = DMA_CTRL_RXCMB_EN; - dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) - << DMA_CTRL_DMAR_BURST_LEN_SHIFT; - dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK) - << DMA_CTRL_DMAW_BURST_LEN_SHIFT; - dma_ctrl_data |= DMA_CTRL_DMAR_REQ_PRI | DMA_CTRL_DMAR_OUT_ORDER; - dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK) - << DMA_CTRL_DMAR_DLY_CNT_SHIFT; - dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK) - << DMA_CTRL_DMAW_DLY_CNT_SHIFT; - - AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data); -} - -static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter) -{ - u32 value; - struct atl1e_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - - /* Config MAC CTRL Register */ - value = MAC_CTRL_TX_EN | - MAC_CTRL_RX_EN ; - - if (FULL_DUPLEX == adapter->link_duplex) - value |= MAC_CTRL_DUPLX; - - value |= ((u32)((SPEED_1000 == adapter->link_speed) ? - MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) << - MAC_CTRL_SPEED_SHIFT); - value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW); - - value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD); - value |= (((u32)adapter->hw.preamble_len & - MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); - - __atl1e_vlan_mode(netdev->features, &value); - - value |= MAC_CTRL_BC_EN; - if (netdev->flags & IFF_PROMISC) - value |= MAC_CTRL_PROMIS_EN; - if (netdev->flags & IFF_ALLMULTI) - value |= MAC_CTRL_MC_ALL_EN; - - AT_WRITE_REG(hw, REG_MAC_CTRL, value); -} - -/** - * atl1e_configure - Configure Transmit&Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Tx /Rx unit of the MAC after a reset. - */ -static int atl1e_configure(struct atl1e_adapter *adapter) -{ - struct atl1e_hw *hw = &adapter->hw; - - u32 intr_status_data = 0; - - /* clear interrupt status */ - AT_WRITE_REG(hw, REG_ISR, ~0); - - /* 1. set MAC Address */ - atl1e_hw_set_mac_addr(hw); - - /* 2. Init the Multicast HASH table done by set_muti */ - - /* 3. Clear any WOL status */ - AT_WRITE_REG(hw, REG_WOL_CTRL, 0); - - /* 4. Descripter Ring BaseMem/Length/Read ptr/Write ptr - * TPD Ring/SMB/RXF0 Page CMBs, they use the same - * High 32bits memory */ - atl1e_configure_des_ring(adapter); - - /* 5. set Interrupt Moderator Timer */ - AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, hw->imt); - AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER2_INIT, hw->imt); - AT_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_LED_MODE | - MASTER_CTRL_ITIMER_EN | MASTER_CTRL_ITIMER2_EN); - - /* 6. rx/tx threshold to trig interrupt */ - AT_WRITE_REGW(hw, REG_TRIG_RRD_THRESH, hw->rrd_thresh); - AT_WRITE_REGW(hw, REG_TRIG_TPD_THRESH, hw->tpd_thresh); - AT_WRITE_REGW(hw, REG_TRIG_RXTIMER, hw->rx_count_down); - AT_WRITE_REGW(hw, REG_TRIG_TXTIMER, hw->tx_count_down); - - /* 7. set Interrupt Clear Timer */ - AT_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, hw->ict); - - /* 8. set MTU */ - AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN + - VLAN_HLEN + ETH_FCS_LEN); - - /* 9. config TXQ early tx threshold */ - atl1e_configure_tx(adapter); - - /* 10. config RXQ */ - atl1e_configure_rx(adapter); - - /* 11. config DMA Engine */ - atl1e_configure_dma(adapter); - - /* 12. smb timer to trig interrupt */ - AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, hw->smb_timer); - - intr_status_data = AT_READ_REG(hw, REG_ISR); - if (unlikely((intr_status_data & ISR_PHY_LINKDOWN) != 0)) { - netdev_err(adapter->netdev, - "atl1e_configure failed, PCIE phy link down\n"); - return -1; - } - - AT_WRITE_REG(hw, REG_ISR, 0x7fffffff); - return 0; -} - -/** - * atl1e_get_stats - Get System Network Statistics - * @netdev: network interface device structure - * - * Returns the address of the device statistics structure. - * The statistics are actually updated from the timer callback. - */ -static struct net_device_stats *atl1e_get_stats(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw_stats *hw_stats = &adapter->hw_stats; - struct net_device_stats *net_stats = &netdev->stats; - - net_stats->rx_packets = hw_stats->rx_ok; - net_stats->tx_packets = hw_stats->tx_ok; - net_stats->rx_bytes = hw_stats->rx_byte_cnt; - net_stats->tx_bytes = hw_stats->tx_byte_cnt; - net_stats->multicast = hw_stats->rx_mcast; - net_stats->collisions = hw_stats->tx_1_col + - hw_stats->tx_2_col * 2 + - hw_stats->tx_late_col + hw_stats->tx_abort_col; - - net_stats->rx_errors = hw_stats->rx_frag + hw_stats->rx_fcs_err + - hw_stats->rx_len_err + hw_stats->rx_sz_ov + - hw_stats->rx_rrd_ov + hw_stats->rx_align_err; - net_stats->rx_fifo_errors = hw_stats->rx_rxf_ov; - net_stats->rx_length_errors = hw_stats->rx_len_err; - net_stats->rx_crc_errors = hw_stats->rx_fcs_err; - net_stats->rx_frame_errors = hw_stats->rx_align_err; - net_stats->rx_over_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov; - - net_stats->rx_missed_errors = hw_stats->rx_rrd_ov + hw_stats->rx_rxf_ov; - - net_stats->tx_errors = hw_stats->tx_late_col + hw_stats->tx_abort_col + - hw_stats->tx_underrun + hw_stats->tx_trunc; - net_stats->tx_fifo_errors = hw_stats->tx_underrun; - net_stats->tx_aborted_errors = hw_stats->tx_abort_col; - net_stats->tx_window_errors = hw_stats->tx_late_col; - - return net_stats; -} - -static void atl1e_update_hw_stats(struct atl1e_adapter *adapter) -{ - u16 hw_reg_addr = 0; - unsigned long *stats_item = NULL; - - /* update rx status */ - hw_reg_addr = REG_MAC_RX_STATUS_BIN; - stats_item = &adapter->hw_stats.rx_ok; - while (hw_reg_addr <= REG_MAC_RX_STATUS_END) { - *stats_item += AT_READ_REG(&adapter->hw, hw_reg_addr); - stats_item++; - hw_reg_addr += 4; - } - /* update tx status */ - hw_reg_addr = REG_MAC_TX_STATUS_BIN; - stats_item = &adapter->hw_stats.tx_ok; - while (hw_reg_addr <= REG_MAC_TX_STATUS_END) { - *stats_item += AT_READ_REG(&adapter->hw, hw_reg_addr); - stats_item++; - hw_reg_addr += 4; - } -} - -static inline void atl1e_clear_phy_int(struct atl1e_adapter *adapter) -{ - u16 phy_data; - - spin_lock(&adapter->mdio_lock); - atl1e_read_phy_reg(&adapter->hw, MII_INT_STATUS, &phy_data); - spin_unlock(&adapter->mdio_lock); -} - -static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter) -{ - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - struct atl1e_tx_buffer *tx_buffer = NULL; - u16 hw_next_to_clean = AT_READ_REGW(&adapter->hw, REG_TPD_CONS_IDX); - u16 next_to_clean = atomic_read(&tx_ring->next_to_clean); - - while (next_to_clean != hw_next_to_clean) { - tx_buffer = &tx_ring->tx_buffer[next_to_clean]; - if (tx_buffer->dma) { - if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE) - pci_unmap_single(adapter->pdev, tx_buffer->dma, - tx_buffer->length, PCI_DMA_TODEVICE); - else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE) - pci_unmap_page(adapter->pdev, tx_buffer->dma, - tx_buffer->length, PCI_DMA_TODEVICE); - tx_buffer->dma = 0; - } - - if (tx_buffer->skb) { - dev_kfree_skb_irq(tx_buffer->skb); - tx_buffer->skb = NULL; - } - - if (++next_to_clean == tx_ring->count) - next_to_clean = 0; - } - - atomic_set(&tx_ring->next_to_clean, next_to_clean); - - if (netif_queue_stopped(adapter->netdev) && - netif_carrier_ok(adapter->netdev)) { - netif_wake_queue(adapter->netdev); - } - - return true; -} - -/** - * atl1e_intr - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - */ -static irqreturn_t atl1e_intr(int irq, void *data) -{ - struct net_device *netdev = data; - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - int max_ints = AT_MAX_INT_WORK; - int handled = IRQ_NONE; - u32 status; - - do { - status = AT_READ_REG(hw, REG_ISR); - if ((status & IMR_NORMAL_MASK) == 0 || - (status & ISR_DIS_INT) != 0) { - if (max_ints != AT_MAX_INT_WORK) - handled = IRQ_HANDLED; - break; - } - /* link event */ - if (status & ISR_GPHY) - atl1e_clear_phy_int(adapter); - /* Ack ISR */ - AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT); - - handled = IRQ_HANDLED; - /* check if PCIE PHY Link down */ - if (status & ISR_PHY_LINKDOWN) { - netdev_err(adapter->netdev, - "pcie phy linkdown %x\n", status); - if (netif_running(adapter->netdev)) { - /* reset MAC */ - atl1e_irq_reset(adapter); - schedule_work(&adapter->reset_task); - break; - } - } - - /* check if DMA read/write error */ - if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) { - netdev_err(adapter->netdev, - "PCIE DMA RW error (status = 0x%x)\n", - status); - atl1e_irq_reset(adapter); - schedule_work(&adapter->reset_task); - break; - } - - if (status & ISR_SMB) - atl1e_update_hw_stats(adapter); - - /* link event */ - if (status & (ISR_GPHY | ISR_MANUAL)) { - netdev->stats.tx_carrier_errors++; - atl1e_link_chg_event(adapter); - break; - } - - /* transmit event */ - if (status & ISR_TX_EVENT) - atl1e_clean_tx_irq(adapter); - - if (status & ISR_RX_EVENT) { - /* - * disable rx interrupts, without - * the synchronize_irq bit - */ - AT_WRITE_REG(hw, REG_IMR, - IMR_NORMAL_MASK & ~ISR_RX_EVENT); - AT_WRITE_FLUSH(hw); - if (likely(napi_schedule_prep( - &adapter->napi))) - __napi_schedule(&adapter->napi); - } - } while (--max_ints > 0); - /* re-enable Interrupt*/ - AT_WRITE_REG(&adapter->hw, REG_ISR, 0); - - return handled; -} - -static inline void atl1e_rx_checksum(struct atl1e_adapter *adapter, - struct sk_buff *skb, struct atl1e_recv_ret_status *prrs) -{ - u8 *packet = (u8 *)(prrs + 1); - struct iphdr *iph; - u16 head_len = ETH_HLEN; - u16 pkt_flags; - u16 err_flags; - - skb_checksum_none_assert(skb); - pkt_flags = prrs->pkt_flag; - err_flags = prrs->err_flag; - if (((pkt_flags & RRS_IS_IPV4) || (pkt_flags & RRS_IS_IPV6)) && - ((pkt_flags & RRS_IS_TCP) || (pkt_flags & RRS_IS_UDP))) { - if (pkt_flags & RRS_IS_IPV4) { - if (pkt_flags & RRS_IS_802_3) - head_len += 8; - iph = (struct iphdr *) (packet + head_len); - if (iph->frag_off != 0 && !(pkt_flags & RRS_IS_IP_DF)) - goto hw_xsum; - } - if (!(err_flags & (RRS_ERR_IP_CSUM | RRS_ERR_L4_CSUM))) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - return; - } - } - -hw_xsum : - return; -} - -static struct atl1e_rx_page *atl1e_get_rx_page(struct atl1e_adapter *adapter, - u8 que) -{ - struct atl1e_rx_page_desc *rx_page_desc = - (struct atl1e_rx_page_desc *) adapter->rx_ring.rx_page_desc; - u8 rx_using = rx_page_desc[que].rx_using; - - return &(rx_page_desc[que].rx_page[rx_using]); -} - -static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que, - int *work_done, int work_to_do) -{ - struct net_device *netdev = adapter->netdev; - struct atl1e_rx_ring *rx_ring = &adapter->rx_ring; - struct atl1e_rx_page_desc *rx_page_desc = - (struct atl1e_rx_page_desc *) rx_ring->rx_page_desc; - struct sk_buff *skb = NULL; - struct atl1e_rx_page *rx_page = atl1e_get_rx_page(adapter, que); - u32 packet_size, write_offset; - struct atl1e_recv_ret_status *prrs; - - write_offset = *(rx_page->write_offset_addr); - if (likely(rx_page->read_offset < write_offset)) { - do { - if (*work_done >= work_to_do) - break; - (*work_done)++; - /* get new packet's rrs */ - prrs = (struct atl1e_recv_ret_status *) (rx_page->addr + - rx_page->read_offset); - /* check sequence number */ - if (prrs->seq_num != rx_page_desc[que].rx_nxseq) { - netdev_err(netdev, - "rx sequence number error (rx=%d) (expect=%d)\n", - prrs->seq_num, - rx_page_desc[que].rx_nxseq); - rx_page_desc[que].rx_nxseq++; - /* just for debug use */ - AT_WRITE_REG(&adapter->hw, REG_DEBUG_DATA0, - (((u32)prrs->seq_num) << 16) | - rx_page_desc[que].rx_nxseq); - goto fatal_err; - } - rx_page_desc[que].rx_nxseq++; - - /* error packet */ - if (prrs->pkt_flag & RRS_IS_ERR_FRAME) { - if (prrs->err_flag & (RRS_ERR_BAD_CRC | - RRS_ERR_DRIBBLE | RRS_ERR_CODE | - RRS_ERR_TRUNC)) { - /* hardware error, discard this packet*/ - netdev_err(netdev, - "rx packet desc error %x\n", - *((u32 *)prrs + 1)); - goto skip_pkt; - } - } - - packet_size = ((prrs->word1 >> RRS_PKT_SIZE_SHIFT) & - RRS_PKT_SIZE_MASK) - 4; /* CRC */ - skb = netdev_alloc_skb_ip_align(netdev, packet_size); - if (skb == NULL) - goto skip_pkt; - - memcpy(skb->data, (u8 *)(prrs + 1), packet_size); - skb_put(skb, packet_size); - skb->protocol = eth_type_trans(skb, netdev); - atl1e_rx_checksum(adapter, skb, prrs); - - if (prrs->pkt_flag & RRS_IS_VLAN_TAG) { - u16 vlan_tag = (prrs->vtag >> 4) | - ((prrs->vtag & 7) << 13) | - ((prrs->vtag & 8) << 9); - netdev_dbg(netdev, - "RXD VLAN TAG=0x%04x\n", - prrs->vtag); - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag); - } - netif_receive_skb(skb); - -skip_pkt: - /* skip current packet whether it's ok or not. */ - rx_page->read_offset += - (((u32)((prrs->word1 >> RRS_PKT_SIZE_SHIFT) & - RRS_PKT_SIZE_MASK) + - sizeof(struct atl1e_recv_ret_status) + 31) & - 0xFFFFFFE0); - - if (rx_page->read_offset >= rx_ring->page_size) { - /* mark this page clean */ - u16 reg_addr; - u8 rx_using; - - rx_page->read_offset = - *(rx_page->write_offset_addr) = 0; - rx_using = rx_page_desc[que].rx_using; - reg_addr = - atl1e_rx_page_vld_regs[que][rx_using]; - AT_WRITE_REGB(&adapter->hw, reg_addr, 1); - rx_page_desc[que].rx_using ^= 1; - rx_page = atl1e_get_rx_page(adapter, que); - } - write_offset = *(rx_page->write_offset_addr); - } while (rx_page->read_offset < write_offset); - } - - return; - -fatal_err: - if (!test_bit(__AT_DOWN, &adapter->flags)) - schedule_work(&adapter->reset_task); -} - -/** - * atl1e_clean - NAPI Rx polling callback - */ -static int atl1e_clean(struct napi_struct *napi, int budget) -{ - struct atl1e_adapter *adapter = - container_of(napi, struct atl1e_adapter, napi); - u32 imr_data; - int work_done = 0; - - /* Keep link state information with original netdev */ - if (!netif_carrier_ok(adapter->netdev)) - goto quit_polling; - - atl1e_clean_rx_irq(adapter, 0, &work_done, budget); - - /* If no Tx and not enough Rx work done, exit the polling mode */ - if (work_done < budget) { -quit_polling: - napi_complete(napi); - imr_data = AT_READ_REG(&adapter->hw, REG_IMR); - AT_WRITE_REG(&adapter->hw, REG_IMR, imr_data | ISR_RX_EVENT); - /* test debug */ - if (test_bit(__AT_DOWN, &adapter->flags)) { - atomic_dec(&adapter->irq_sem); - netdev_err(adapter->netdev, - "atl1e_clean is called when AT_DOWN\n"); - } - /* reenable RX intr */ - /*atl1e_irq_enable(adapter); */ - - } - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER - -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void atl1e_netpoll(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - disable_irq(adapter->pdev->irq); - atl1e_intr(adapter->pdev->irq, netdev); - enable_irq(adapter->pdev->irq); -} -#endif - -static inline u16 atl1e_tpd_avail(struct atl1e_adapter *adapter) -{ - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - u16 next_to_use = 0; - u16 next_to_clean = 0; - - next_to_clean = atomic_read(&tx_ring->next_to_clean); - next_to_use = tx_ring->next_to_use; - - return (u16)(next_to_clean > next_to_use) ? - (next_to_clean - next_to_use - 1) : - (tx_ring->count + next_to_clean - next_to_use - 1); -} - -/* - * get next usable tpd - * Note: should call atl1e_tdp_avail to make sure - * there is enough tpd to use - */ -static struct atl1e_tpd_desc *atl1e_get_tpd(struct atl1e_adapter *adapter) -{ - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - u16 next_to_use = 0; - - next_to_use = tx_ring->next_to_use; - if (++tx_ring->next_to_use == tx_ring->count) - tx_ring->next_to_use = 0; - - memset(&tx_ring->desc[next_to_use], 0, sizeof(struct atl1e_tpd_desc)); - return &tx_ring->desc[next_to_use]; -} - -static struct atl1e_tx_buffer * -atl1e_get_tx_buffer(struct atl1e_adapter *adapter, struct atl1e_tpd_desc *tpd) -{ - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - - return &tx_ring->tx_buffer[tpd - tx_ring->desc]; -} - -/* Calculate the transmit packet descript needed*/ -static u16 atl1e_cal_tdp_req(const struct sk_buff *skb) -{ - int i = 0; - u16 tpd_req = 1; - u16 fg_size = 0; - u16 proto_hdr_len = 0; - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - fg_size = skb_frag_size(&skb_shinfo(skb)->frags[i]); - tpd_req += ((fg_size + MAX_TX_BUF_LEN - 1) >> MAX_TX_BUF_SHIFT); - } - - if (skb_is_gso(skb)) { - if (skb->protocol == htons(ETH_P_IP) || - (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6)) { - proto_hdr_len = skb_transport_offset(skb) + - tcp_hdrlen(skb); - if (proto_hdr_len < skb_headlen(skb)) { - tpd_req += ((skb_headlen(skb) - proto_hdr_len + - MAX_TX_BUF_LEN - 1) >> - MAX_TX_BUF_SHIFT); - } - } - - } - return tpd_req; -} - -static int atl1e_tso_csum(struct atl1e_adapter *adapter, - struct sk_buff *skb, struct atl1e_tpd_desc *tpd) -{ - u8 hdr_len; - u32 real_len; - unsigned short offload_type; - int err; - - if (skb_is_gso(skb)) { - if (skb_header_cloned(skb)) { - err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); - if (unlikely(err)) - return -1; - } - offload_type = skb_shinfo(skb)->gso_type; - - if (offload_type & SKB_GSO_TCPV4) { - real_len = (((unsigned char *)ip_hdr(skb) - skb->data) - + ntohs(ip_hdr(skb)->tot_len)); - - if (real_len < skb->len) - pskb_trim(skb, real_len); - - hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); - if (unlikely(skb->len == hdr_len)) { - /* only xsum need */ - netdev_warn(adapter->netdev, - "IPV4 tso with zero data??\n"); - goto check_sum; - } else { - ip_hdr(skb)->check = 0; - ip_hdr(skb)->tot_len = 0; - tcp_hdr(skb)->check = ~csum_tcpudp_magic( - ip_hdr(skb)->saddr, - ip_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); - tpd->word3 |= (ip_hdr(skb)->ihl & - TDP_V4_IPHL_MASK) << - TPD_V4_IPHL_SHIFT; - tpd->word3 |= ((tcp_hdrlen(skb) >> 2) & - TPD_TCPHDRLEN_MASK) << - TPD_TCPHDRLEN_SHIFT; - tpd->word3 |= ((skb_shinfo(skb)->gso_size) & - TPD_MSS_MASK) << TPD_MSS_SHIFT; - tpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT; - } - return 0; - } - } - -check_sum: - if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { - u8 css, cso; - - cso = skb_checksum_start_offset(skb); - if (unlikely(cso & 0x1)) { - netdev_err(adapter->netdev, - "payload offset should not ant event number\n"); - return -1; - } else { - css = cso + skb->csum_offset; - tpd->word3 |= (cso & TPD_PLOADOFFSET_MASK) << - TPD_PLOADOFFSET_SHIFT; - tpd->word3 |= (css & TPD_CCSUMOFFSET_MASK) << - TPD_CCSUMOFFSET_SHIFT; - tpd->word3 |= 1 << TPD_CC_SEGMENT_EN_SHIFT; - } - } - - return 0; -} - -static int atl1e_tx_map(struct atl1e_adapter *adapter, - struct sk_buff *skb, struct atl1e_tpd_desc *tpd) -{ - struct atl1e_tpd_desc *use_tpd = NULL; - struct atl1e_tx_buffer *tx_buffer = NULL; - u16 buf_len = skb_headlen(skb); - u16 map_len = 0; - u16 mapped_len = 0; - u16 hdr_len = 0; - u16 nr_frags; - u16 f; - int segment; - int ring_start = adapter->tx_ring.next_to_use; - int ring_end; - - nr_frags = skb_shinfo(skb)->nr_frags; - segment = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK; - if (segment) { - /* TSO */ - map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - use_tpd = tpd; - - tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd); - tx_buffer->length = map_len; - tx_buffer->dma = pci_map_single(adapter->pdev, - skb->data, hdr_len, PCI_DMA_TODEVICE); - if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) - return -ENOSPC; - - ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE); - mapped_len += map_len; - use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); - use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) | - ((cpu_to_le32(tx_buffer->length) & - TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT); - } - - while (mapped_len < buf_len) { - /* mapped_len == 0, means we should use the first tpd, - which is given by caller */ - if (mapped_len == 0) { - use_tpd = tpd; - } else { - use_tpd = atl1e_get_tpd(adapter); - memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc)); - } - tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd); - tx_buffer->skb = NULL; - - tx_buffer->length = map_len = - ((buf_len - mapped_len) >= MAX_TX_BUF_LEN) ? - MAX_TX_BUF_LEN : (buf_len - mapped_len); - tx_buffer->dma = - pci_map_single(adapter->pdev, skb->data + mapped_len, - map_len, PCI_DMA_TODEVICE); - - if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) { - /* We need to unwind the mappings we've done */ - ring_end = adapter->tx_ring.next_to_use; - adapter->tx_ring.next_to_use = ring_start; - while (adapter->tx_ring.next_to_use != ring_end) { - tpd = atl1e_get_tpd(adapter); - tx_buffer = atl1e_get_tx_buffer(adapter, tpd); - pci_unmap_single(adapter->pdev, tx_buffer->dma, - tx_buffer->length, PCI_DMA_TODEVICE); - } - /* Reset the tx rings next pointer */ - adapter->tx_ring.next_to_use = ring_start; - return -ENOSPC; - } - - ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE); - mapped_len += map_len; - use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); - use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) | - ((cpu_to_le32(tx_buffer->length) & - TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT); - } - - for (f = 0; f < nr_frags; f++) { - const struct skb_frag_struct *frag; - u16 i; - u16 seg_num; - - frag = &skb_shinfo(skb)->frags[f]; - buf_len = skb_frag_size(frag); - - seg_num = (buf_len + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN; - for (i = 0; i < seg_num; i++) { - use_tpd = atl1e_get_tpd(adapter); - memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc)); - - tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd); - BUG_ON(tx_buffer->skb); - - tx_buffer->skb = NULL; - tx_buffer->length = - (buf_len > MAX_TX_BUF_LEN) ? - MAX_TX_BUF_LEN : buf_len; - buf_len -= tx_buffer->length; - - tx_buffer->dma = skb_frag_dma_map(&adapter->pdev->dev, - frag, - (i * MAX_TX_BUF_LEN), - tx_buffer->length, - DMA_TO_DEVICE); - - if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) { - /* We need to unwind the mappings we've done */ - ring_end = adapter->tx_ring.next_to_use; - adapter->tx_ring.next_to_use = ring_start; - while (adapter->tx_ring.next_to_use != ring_end) { - tpd = atl1e_get_tpd(adapter); - tx_buffer = atl1e_get_tx_buffer(adapter, tpd); - dma_unmap_page(&adapter->pdev->dev, tx_buffer->dma, - tx_buffer->length, DMA_TO_DEVICE); - } - - /* Reset the ring next to use pointer */ - adapter->tx_ring.next_to_use = ring_start; - return -ENOSPC; - } - - ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE); - use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); - use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) | - ((cpu_to_le32(tx_buffer->length) & - TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT); - } - } - - if ((tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK) - /* note this one is a tcp header */ - tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT; - /* The last tpd */ - - use_tpd->word3 |= 1 << TPD_EOP_SHIFT; - /* The last buffer info contain the skb address, - so it will be free after unmap */ - tx_buffer->skb = skb; - return 0; -} - -static void atl1e_tx_queue(struct atl1e_adapter *adapter, u16 count, - struct atl1e_tpd_desc *tpd) -{ - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). */ - wmb(); - AT_WRITE_REG(&adapter->hw, REG_MB_TPD_PROD_IDX, tx_ring->next_to_use); -} - -static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - unsigned long flags; - u16 tpd_req = 1; - struct atl1e_tpd_desc *tpd; - - if (test_bit(__AT_DOWN, &adapter->flags)) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if (unlikely(skb->len <= 0)) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - tpd_req = atl1e_cal_tdp_req(skb); - if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) - return NETDEV_TX_LOCKED; - - if (atl1e_tpd_avail(adapter) < tpd_req) { - /* no enough descriptor, just stop queue */ - netif_stop_queue(netdev); - spin_unlock_irqrestore(&adapter->tx_lock, flags); - return NETDEV_TX_BUSY; - } - - tpd = atl1e_get_tpd(adapter); - - if (vlan_tx_tag_present(skb)) { - u16 vlan_tag = vlan_tx_tag_get(skb); - u16 atl1e_vlan_tag; - - tpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT; - AT_VLAN_TAG_TO_TPD_TAG(vlan_tag, atl1e_vlan_tag); - tpd->word2 |= (atl1e_vlan_tag & TPD_VLANTAG_MASK) << - TPD_VLAN_SHIFT; - } - - if (skb->protocol == htons(ETH_P_8021Q)) - tpd->word3 |= 1 << TPD_VL_TAGGED_SHIFT; - - if (skb_network_offset(skb) != ETH_HLEN) - tpd->word3 |= 1 << TPD_ETHTYPE_SHIFT; /* 802.3 frame */ - - /* do TSO and check sum */ - if (atl1e_tso_csum(adapter, skb, tpd) != 0) { - spin_unlock_irqrestore(&adapter->tx_lock, flags); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if (atl1e_tx_map(adapter, skb, tpd)) { - dev_kfree_skb_any(skb); - goto out; - } - - atl1e_tx_queue(adapter, tpd_req, tpd); - - netdev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */ -out: - spin_unlock_irqrestore(&adapter->tx_lock, flags); - return NETDEV_TX_OK; -} - -static void atl1e_free_irq(struct atl1e_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - free_irq(adapter->pdev->irq, netdev); -} - -static int atl1e_request_irq(struct atl1e_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - struct net_device *netdev = adapter->netdev; - int err = 0; - - err = request_irq(pdev->irq, atl1e_intr, IRQF_SHARED, netdev->name, - netdev); - if (err) { - netdev_dbg(adapter->netdev, - "Unable to allocate interrupt Error: %d\n", err); - return err; - } - netdev_dbg(netdev, "atl1e_request_irq OK\n"); - return err; -} - -int atl1e_up(struct atl1e_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - int err = 0; - u32 val; - - /* hardware has been reset, we need to reload some things */ - err = atl1e_init_hw(&adapter->hw); - if (err) { - err = -EIO; - return err; - } - atl1e_init_ring_ptrs(adapter); - atl1e_set_multi(netdev); - atl1e_restore_vlan(adapter); - - if (atl1e_configure(adapter)) { - err = -EIO; - goto err_up; - } - - clear_bit(__AT_DOWN, &adapter->flags); - napi_enable(&adapter->napi); - atl1e_irq_enable(adapter); - val = AT_READ_REG(&adapter->hw, REG_MASTER_CTRL); - AT_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, - val | MASTER_CTRL_MANUAL_INT); - -err_up: - return err; -} - -void atl1e_down(struct atl1e_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - /* signal that we're down so the interrupt handler does not - * reschedule our watchdog timer */ - set_bit(__AT_DOWN, &adapter->flags); - - netif_stop_queue(netdev); - - /* reset MAC to disable all RX/TX */ - atl1e_reset_hw(&adapter->hw); - msleep(1); - - napi_disable(&adapter->napi); - atl1e_del_timer(adapter); - atl1e_irq_disable(adapter); - - netif_carrier_off(netdev); - adapter->link_speed = SPEED_0; - adapter->link_duplex = -1; - atl1e_clean_tx_ring(adapter); - atl1e_clean_rx_ring(adapter); -} - -/** - * atl1e_open - Called when a network interface is made active - * @netdev: network interface device structure - * - * Returns 0 on success, negative value on failure - * - * The open entry point is called when a network interface is made - * active by the system (IFF_UP). At this point all resources needed - * for transmit and receive operations are allocated, the interrupt - * handler is registered with the OS, the watchdog timer is started, - * and the stack is notified that the interface is ready. - */ -static int atl1e_open(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - int err; - - /* disallow open during test */ - if (test_bit(__AT_TESTING, &adapter->flags)) - return -EBUSY; - - /* allocate rx/tx dma buffer & descriptors */ - atl1e_init_ring_resources(adapter); - err = atl1e_setup_ring_resources(adapter); - if (unlikely(err)) - return err; - - err = atl1e_request_irq(adapter); - if (unlikely(err)) - goto err_req_irq; - - err = atl1e_up(adapter); - if (unlikely(err)) - goto err_up; - - return 0; - -err_up: - atl1e_free_irq(adapter); -err_req_irq: - atl1e_free_ring_resources(adapter); - atl1e_reset_hw(&adapter->hw); - - return err; -} - -/** - * atl1e_close - Disables a network interface - * @netdev: network interface device structure - * - * Returns 0, this is not allowed to fail - * - * The close entry point is called when an interface is de-activated - * by the OS. The hardware is still under the drivers control, but - * needs to be disabled. A global MAC reset is issued to stop the - * hardware, and all transmit and receive resources are freed. - */ -static int atl1e_close(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); - atl1e_down(adapter); - atl1e_free_irq(adapter); - atl1e_free_ring_resources(adapter); - - return 0; -} - -static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - u32 ctrl = 0; - u32 mac_ctrl_data = 0; - u32 wol_ctrl_data = 0; - u16 mii_advertise_data = 0; - u16 mii_bmsr_data = 0; - u16 mii_intr_status_data = 0; - u32 wufc = adapter->wol; - u32 i; -#ifdef CONFIG_PM - int retval = 0; -#endif - - if (netif_running(netdev)) { - WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); - atl1e_down(adapter); - } - netif_device_detach(netdev); - -#ifdef CONFIG_PM - retval = pci_save_state(pdev); - if (retval) - return retval; -#endif - - if (wufc) { - /* get link status */ - atl1e_read_phy_reg(hw, MII_BMSR, &mii_bmsr_data); - atl1e_read_phy_reg(hw, MII_BMSR, &mii_bmsr_data); - - mii_advertise_data = ADVERTISE_10HALF; - - if ((atl1e_write_phy_reg(hw, MII_CTRL1000, 0) != 0) || - (atl1e_write_phy_reg(hw, - MII_ADVERTISE, mii_advertise_data) != 0) || - (atl1e_phy_commit(hw)) != 0) { - netdev_dbg(adapter->netdev, "set phy register failed\n"); - goto wol_dis; - } - - hw->phy_configured = false; /* re-init PHY when resume */ - - /* turn on magic packet wol */ - if (wufc & AT_WUFC_MAG) - wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN; - - if (wufc & AT_WUFC_LNKC) { - /* if orignal link status is link, just wait for retrive link */ - if (mii_bmsr_data & BMSR_LSTATUS) { - for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) { - msleep(100); - atl1e_read_phy_reg(hw, MII_BMSR, - &mii_bmsr_data); - if (mii_bmsr_data & BMSR_LSTATUS) - break; - } - - if ((mii_bmsr_data & BMSR_LSTATUS) == 0) - netdev_dbg(adapter->netdev, - "Link may change when suspend\n"); - } - wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; - /* only link up can wake up */ - if (atl1e_write_phy_reg(hw, MII_INT_CTRL, 0x400) != 0) { - netdev_dbg(adapter->netdev, - "read write phy register failed\n"); - goto wol_dis; - } - } - /* clear phy interrupt */ - atl1e_read_phy_reg(hw, MII_INT_STATUS, &mii_intr_status_data); - /* Config MAC Ctrl register */ - mac_ctrl_data = MAC_CTRL_RX_EN; - /* set to 10/100M halt duplex */ - mac_ctrl_data |= MAC_CTRL_SPEED_10_100 << MAC_CTRL_SPEED_SHIFT; - mac_ctrl_data |= (((u32)adapter->hw.preamble_len & - MAC_CTRL_PRMLEN_MASK) << - MAC_CTRL_PRMLEN_SHIFT); - - __atl1e_vlan_mode(netdev->features, &mac_ctrl_data); - - /* magic packet maybe Broadcast&multicast&Unicast frame */ - if (wufc & AT_WUFC_MAG) - mac_ctrl_data |= MAC_CTRL_BC_EN; - - netdev_dbg(adapter->netdev, "suspend MAC=0x%x\n", - mac_ctrl_data); - - AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data); - AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); - /* pcie patch */ - ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC); - ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; - AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); - pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); - goto suspend_exit; - } -wol_dis: - - /* WOL disabled */ - AT_WRITE_REG(hw, REG_WOL_CTRL, 0); - - /* pcie patch */ - ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC); - ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; - AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); - - atl1e_force_ps(hw); - hw->phy_configured = false; /* re-init PHY when resume */ - - pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); - -suspend_exit: - - if (netif_running(netdev)) - atl1e_free_irq(adapter); - - pci_disable_device(pdev); - - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -#ifdef CONFIG_PM -static int atl1e_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1e_adapter *adapter = netdev_priv(netdev); - u32 err; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - err = pci_enable_device(pdev); - if (err) { - netdev_err(adapter->netdev, - "Cannot enable PCI device from suspend\n"); - return err; - } - - pci_set_master(pdev); - - AT_READ_REG(&adapter->hw, REG_WOL_CTRL); /* clear WOL status */ - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); - - if (netif_running(netdev)) { - err = atl1e_request_irq(adapter); - if (err) - return err; - } - - atl1e_reset_hw(&adapter->hw); - - if (netif_running(netdev)) - atl1e_up(adapter); - - netif_device_attach(netdev); - - return 0; -} -#endif - -static void atl1e_shutdown(struct pci_dev *pdev) -{ - atl1e_suspend(pdev, PMSG_SUSPEND); -} - -static const struct net_device_ops atl1e_netdev_ops = { - .ndo_open = atl1e_open, - .ndo_stop = atl1e_close, - .ndo_start_xmit = atl1e_xmit_frame, - .ndo_get_stats = atl1e_get_stats, - .ndo_set_rx_mode = atl1e_set_multi, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = atl1e_set_mac_addr, - .ndo_fix_features = atl1e_fix_features, - .ndo_set_features = atl1e_set_features, - .ndo_change_mtu = atl1e_change_mtu, - .ndo_do_ioctl = atl1e_ioctl, - .ndo_tx_timeout = atl1e_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = atl1e_netpoll, -#endif - -}; - -static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev) -{ - SET_NETDEV_DEV(netdev, &pdev->dev); - pci_set_drvdata(pdev, netdev); - - netdev->netdev_ops = &atl1e_netdev_ops; - - netdev->watchdog_timeo = AT_TX_WATCHDOG; - atl1e_set_ethtool_ops(netdev); - - netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO | - NETIF_F_HW_VLAN_CTAG_RX; - netdev->features = netdev->hw_features | NETIF_F_LLTX | - NETIF_F_HW_VLAN_CTAG_TX; - - return 0; -} - -/** - * atl1e_probe - Device Initialization Routine - * @pdev: PCI device information struct - * @ent: entry in atl1e_pci_tbl - * - * Returns 0 on success, negative on failure - * - * atl1e_probe initializes an adapter identified by a pci_dev structure. - * The OS initialization, configuring of the adapter private structure, - * and a hardware reset occur. - */ -static int atl1e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct atl1e_adapter *adapter = NULL; - static int cards_found; - - int err = 0; - - err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "cannot enable PCI device\n"); - return err; - } - - /* - * The atl1e chip can DMA to 64-bit addresses, but it uses a single - * shared register for the high 32 bits, so only a single, aligned, - * 4 GB physical address range can be used at a time. - * - * Supporting 64-bit DMA on this hardware is more trouble than it's - * worth. It is far easier to limit to 32-bit DMA than update - * various kernel subsystems to support the mechanics required by a - * fixed-high-32-bit system. - */ - if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) || - (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)) { - dev_err(&pdev->dev, "No usable DMA configuration,aborting\n"); - goto err_dma; - } - - err = pci_request_regions(pdev, atl1e_driver_name); - if (err) { - dev_err(&pdev->dev, "cannot obtain PCI resources\n"); - goto err_pci_reg; - } - - pci_set_master(pdev); - - netdev = alloc_etherdev(sizeof(struct atl1e_adapter)); - if (netdev == NULL) { - err = -ENOMEM; - goto err_alloc_etherdev; - } - - err = atl1e_init_netdev(netdev, pdev); - if (err) { - netdev_err(netdev, "init netdevice failed\n"); - goto err_init_netdev; - } - adapter = netdev_priv(netdev); - adapter->bd_number = cards_found; - adapter->netdev = netdev; - adapter->pdev = pdev; - adapter->hw.adapter = adapter; - adapter->hw.hw_addr = pci_iomap(pdev, BAR_0, 0); - if (!adapter->hw.hw_addr) { - err = -EIO; - netdev_err(netdev, "cannot map device registers\n"); - goto err_ioremap; - } - - /* init mii data */ - adapter->mii.dev = netdev; - adapter->mii.mdio_read = atl1e_mdio_read; - adapter->mii.mdio_write = atl1e_mdio_write; - adapter->mii.phy_id_mask = 0x1f; - adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK; - - netif_napi_add(netdev, &adapter->napi, atl1e_clean, 64); - - init_timer(&adapter->phy_config_timer); - adapter->phy_config_timer.function = atl1e_phy_config; - adapter->phy_config_timer.data = (unsigned long) adapter; - - /* get user settings */ - atl1e_check_options(adapter); - /* - * Mark all PCI regions associated with PCI device - * pdev as being reserved by owner atl1e_driver_name - * Enables bus-mastering on the device and calls - * pcibios_set_master to do the needed arch specific settings - */ - atl1e_setup_pcicmd(pdev); - /* setup the private structure */ - err = atl1e_sw_init(adapter); - if (err) { - netdev_err(netdev, "net device private data init failed\n"); - goto err_sw_init; - } - - /* Init GPHY as early as possible due to power saving issue */ - atl1e_phy_init(&adapter->hw); - /* reset the controller to - * put the device in a known good starting state */ - err = atl1e_reset_hw(&adapter->hw); - if (err) { - err = -EIO; - goto err_reset; - } - - if (atl1e_read_mac_addr(&adapter->hw) != 0) { - err = -EIO; - netdev_err(netdev, "get mac address failed\n"); - goto err_eeprom; - } - - memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); - netdev_dbg(netdev, "mac address : %pM\n", adapter->hw.mac_addr); - - INIT_WORK(&adapter->reset_task, atl1e_reset_task); - INIT_WORK(&adapter->link_chg_task, atl1e_link_chg_task); - netif_set_gso_max_size(netdev, MAX_TSO_SEG_SIZE); - err = register_netdev(netdev); - if (err) { - netdev_err(netdev, "register netdevice failed\n"); - goto err_register; - } - - /* assume we have no link for now */ - netif_stop_queue(netdev); - netif_carrier_off(netdev); - - cards_found++; - - return 0; - -err_reset: -err_register: -err_sw_init: -err_eeprom: - iounmap(adapter->hw.hw_addr); -err_init_netdev: -err_ioremap: - free_netdev(netdev); -err_alloc_etherdev: - pci_release_regions(pdev); -err_pci_reg: -err_dma: - pci_disable_device(pdev); - return err; -} - -/** - * atl1e_remove - Device Removal Routine - * @pdev: PCI device information struct - * - * atl1e_remove is called by the PCI subsystem to alert the driver - * that it should release a PCI device. The could be caused by a - * Hot-Plug event, or because the driver is going to be removed from - * memory. - */ -static void atl1e_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1e_adapter *adapter = netdev_priv(netdev); - - /* - * flush_scheduled work may reschedule our watchdog task, so - * explicitly disable watchdog tasks from being rescheduled - */ - set_bit(__AT_DOWN, &adapter->flags); - - atl1e_del_timer(adapter); - atl1e_cancel_work(adapter); - - unregister_netdev(netdev); - atl1e_free_ring_resources(adapter); - atl1e_force_ps(&adapter->hw); - iounmap(adapter->hw.hw_addr); - pci_release_regions(pdev); - free_netdev(netdev); - pci_disable_device(pdev); -} - -/** - * atl1e_io_error_detected - called when PCI error is detected - * @pdev: Pointer to PCI device - * @state: The current pci connection state - * - * This function is called after a PCI bus error affecting - * this device has been detected. - */ -static pci_ers_result_t -atl1e_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1e_adapter *adapter = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - atl1e_down(adapter); - - pci_disable_device(pdev); - - /* Request a slot slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * atl1e_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch, as if from a cold-boot. Implementation - * resembles the first-half of the e1000_resume routine. - */ -static pci_ers_result_t atl1e_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1e_adapter *adapter = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - netdev_err(adapter->netdev, - "Cannot re-enable PCI device after reset\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - atl1e_reset_hw(&adapter->hw); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * atl1e_io_resume - called when traffic can start flowing again. - * @pdev: Pointer to PCI device - * - * This callback is called when the error recovery driver tells us that - * its OK to resume normal operation. Implementation resembles the - * second-half of the atl1e_resume routine. - */ -static void atl1e_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1e_adapter *adapter = netdev_priv(netdev); - - if (netif_running(netdev)) { - if (atl1e_up(adapter)) { - netdev_err(adapter->netdev, - "can't bring device back up after reset\n"); - return; - } - } - - netif_device_attach(netdev); -} - -static const struct pci_error_handlers atl1e_err_handler = { - .error_detected = atl1e_io_error_detected, - .slot_reset = atl1e_io_slot_reset, - .resume = atl1e_io_resume, -}; - -static struct pci_driver atl1e_driver = { - .name = atl1e_driver_name, - .id_table = atl1e_pci_tbl, - .probe = atl1e_probe, - .remove = atl1e_remove, - /* Power Management Hooks */ -#ifdef CONFIG_PM - .suspend = atl1e_suspend, - .resume = atl1e_resume, -#endif - .shutdown = atl1e_shutdown, - .err_handler = &atl1e_err_handler -}; - -/** - * atl1e_init_module - Driver Registration Routine - * - * atl1e_init_module is the first routine called when the driver is - * loaded. All it does is register with the PCI subsystem. - */ -static int __init atl1e_init_module(void) -{ - return pci_register_driver(&atl1e_driver); -} - -/** - * atl1e_exit_module - Driver Exit Cleanup Routine - * - * atl1e_exit_module is called just before the driver is removed - * from memory. - */ -static void __exit atl1e_exit_module(void) -{ - pci_unregister_driver(&atl1e_driver); -} - -module_init(atl1e_init_module); -module_exit(atl1e_exit_module); diff --git a/addons/atl1e/src/3.10.108/atl1e_param.c b/addons/atl1e/src/3.10.108/atl1e_param.c deleted file mode 100644 index fa314282..00000000 --- a/addons/atl1e/src/3.10.108/atl1e_param.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include - -#include "atl1e.h" - -/* This is the only thing that needs to be changed to adjust the - * maximum number of ports that the driver can manage. - */ - -#define ATL1E_MAX_NIC 32 - -#define OPTION_UNSET -1 -#define OPTION_DISABLED 0 -#define OPTION_ENABLED 1 - -/* All parameters are treated the same, as an integer array of values. - * This macro just reduces the need to repeat the same declaration code - * over and over (plus this helps to avoid typo bugs). - */ -#define ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET } - -#define ATL1E_PARAM(x, desc) \ - static int x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \ - static unsigned int num_##x; \ - module_param_array_named(x, x, int, &num_##x, 0); \ - MODULE_PARM_DESC(x, desc); - -/* Transmit Memory count - * - * Valid Range: 64-2048 - * - * Default Value: 128 - */ -#define ATL1E_MIN_TX_DESC_CNT 32 -#define ATL1E_MAX_TX_DESC_CNT 1020 -#define ATL1E_DEFAULT_TX_DESC_CNT 128 -ATL1E_PARAM(tx_desc_cnt, "Transmit description count"); - -/* Receive Memory Block Count - * - * Valid Range: 16-512 - * - * Default Value: 128 - */ -#define ATL1E_MIN_RX_MEM_SIZE 8 /* 8KB */ -#define ATL1E_MAX_RX_MEM_SIZE 1024 /* 1MB */ -#define ATL1E_DEFAULT_RX_MEM_SIZE 256 /* 128KB */ -ATL1E_PARAM(rx_mem_size, "memory size of rx buffer(KB)"); - -/* User Specified MediaType Override - * - * Valid Range: 0-5 - * - 0 - auto-negotiate at all supported speeds - * - 1 - only link at 100Mbps Full Duplex - * - 2 - only link at 100Mbps Half Duplex - * - 3 - only link at 10Mbps Full Duplex - * - 4 - only link at 10Mbps Half Duplex - * Default Value: 0 - */ - -ATL1E_PARAM(media_type, "MediaType Select"); - -/* Interrupt Moderate Timer in units of 2 us - * - * Valid Range: 10-65535 - * - * Default Value: 45000(90ms) - */ -#define INT_MOD_DEFAULT_CNT 100 /* 200us */ -#define INT_MOD_MAX_CNT 65000 -#define INT_MOD_MIN_CNT 50 -ATL1E_PARAM(int_mod_timer, "Interrupt Moderator Timer"); - -#define AUTONEG_ADV_DEFAULT 0x2F -#define AUTONEG_ADV_MASK 0x2F -#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL - -#define FLASH_VENDOR_DEFAULT 0 -#define FLASH_VENDOR_MIN 0 -#define FLASH_VENDOR_MAX 2 - -struct atl1e_option { - enum { enable_option, range_option, list_option } type; - char *name; - char *err; - int def; - union { - struct { /* range_option info */ - int min; - int max; - } r; - struct { /* list_option info */ - int nr; - struct atl1e_opt_list { int i; char *str; } *p; - } l; - } arg; -}; - -static int atl1e_validate_option(int *value, struct atl1e_option *opt, - struct atl1e_adapter *adapter) -{ - if (*value == OPTION_UNSET) { - *value = opt->def; - return 0; - } - - switch (opt->type) { - case enable_option: - switch (*value) { - case OPTION_ENABLED: - netdev_info(adapter->netdev, - "%s Enabled\n", opt->name); - return 0; - case OPTION_DISABLED: - netdev_info(adapter->netdev, - "%s Disabled\n", opt->name); - return 0; - } - break; - case range_option: - if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { - netdev_info(adapter->netdev, "%s set to %i\n", - opt->name, *value); - return 0; - } - break; - case list_option:{ - int i; - struct atl1e_opt_list *ent; - - for (i = 0; i < opt->arg.l.nr; i++) { - ent = &opt->arg.l.p[i]; - if (*value == ent->i) { - if (ent->str[0] != '\0') - netdev_info(adapter->netdev, - "%s\n", ent->str); - return 0; - } - } - break; - } - default: - BUG(); - } - - netdev_info(adapter->netdev, "Invalid %s specified (%i) %s\n", - opt->name, *value, opt->err); - *value = opt->def; - return -1; -} - -/** - * atl1e_check_options - Range Checking for Command Line Parameters - * @adapter: board private structure - * - * This routine checks all command line parameters for valid user - * input. If an invalid value is given, or if no user specified - * value exists, a default value is used. The final value is stored - * in a variable in the adapter structure. - */ -void atl1e_check_options(struct atl1e_adapter *adapter) -{ - int bd = adapter->bd_number; - - if (bd >= ATL1E_MAX_NIC) { - netdev_notice(adapter->netdev, - "no configuration for board #%i\n", bd); - netdev_notice(adapter->netdev, - "Using defaults for all values\n"); - } - - { /* Transmit Ring Size */ - struct atl1e_option opt = { - .type = range_option, - .name = "Transmit Ddescription Count", - .err = "using default of " - __MODULE_STRING(ATL1E_DEFAULT_TX_DESC_CNT), - .def = ATL1E_DEFAULT_TX_DESC_CNT, - .arg = { .r = { .min = ATL1E_MIN_TX_DESC_CNT, - .max = ATL1E_MAX_TX_DESC_CNT} } - }; - int val; - if (num_tx_desc_cnt > bd) { - val = tx_desc_cnt[bd]; - atl1e_validate_option(&val, &opt, adapter); - adapter->tx_ring.count = (u16) val & 0xFFFC; - } else - adapter->tx_ring.count = (u16)opt.def; - } - - { /* Receive Memory Block Count */ - struct atl1e_option opt = { - .type = range_option, - .name = "Memory size of rx buffer(KB)", - .err = "using default of " - __MODULE_STRING(ATL1E_DEFAULT_RX_MEM_SIZE), - .def = ATL1E_DEFAULT_RX_MEM_SIZE, - .arg = { .r = { .min = ATL1E_MIN_RX_MEM_SIZE, - .max = ATL1E_MAX_RX_MEM_SIZE} } - }; - int val; - if (num_rx_mem_size > bd) { - val = rx_mem_size[bd]; - atl1e_validate_option(&val, &opt, adapter); - adapter->rx_ring.page_size = (u32)val * 1024; - } else { - adapter->rx_ring.page_size = (u32)opt.def * 1024; - } - } - - { /* Interrupt Moderate Timer */ - struct atl1e_option opt = { - .type = range_option, - .name = "Interrupt Moderate Timer", - .err = "using default of " - __MODULE_STRING(INT_MOD_DEFAULT_CNT), - .def = INT_MOD_DEFAULT_CNT, - .arg = { .r = { .min = INT_MOD_MIN_CNT, - .max = INT_MOD_MAX_CNT} } - } ; - int val; - if (num_int_mod_timer > bd) { - val = int_mod_timer[bd]; - atl1e_validate_option(&val, &opt, adapter); - adapter->hw.imt = (u16) val; - } else - adapter->hw.imt = (u16)(opt.def); - } - - { /* MediaType */ - struct atl1e_option opt = { - .type = range_option, - .name = "Speed/Duplex Selection", - .err = "using default of " - __MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR), - .def = MEDIA_TYPE_AUTO_SENSOR, - .arg = { .r = { .min = MEDIA_TYPE_AUTO_SENSOR, - .max = MEDIA_TYPE_10M_HALF} } - } ; - int val; - if (num_media_type > bd) { - val = media_type[bd]; - atl1e_validate_option(&val, &opt, adapter); - adapter->hw.media_type = (u16) val; - } else - adapter->hw.media_type = (u16)(opt.def); - - } -} diff --git a/addons/atl1e/src/4.4.180/Makefile b/addons/atl1e/src/4.4.180/Makefile deleted file mode 100644 index fe2e3d47..00000000 --- a/addons/atl1e/src/4.4.180/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-m += atl1e.o -atl1e-objs += atl1e_main.o atl1e_hw.o atl1e_ethtool.o atl1e_param.o diff --git a/addons/atl1e/src/4.4.180/atl1e.h b/addons/atl1e/src/4.4.180/atl1e.h deleted file mode 100644 index 0212dac7..00000000 --- a/addons/atl1e/src/4.4.180/atl1e.h +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * Copyright(c) 2007 xiong huang - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _ATL1E_H_ -#define _ATL1E_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "atl1e_hw.h" - -#define PCI_REG_COMMAND 0x04 /* PCI Command Register */ -#define CMD_IO_SPACE 0x0001 -#define CMD_MEMORY_SPACE 0x0002 -#define CMD_BUS_MASTER 0x0004 - -#define BAR_0 0 -#define BAR_1 1 -#define BAR_5 5 - -/* Wake Up Filter Control */ -#define AT_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ -#define AT_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ -#define AT_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ -#define AT_WUFC_MC 0x00000008 /* Multicast Wakeup Enable */ -#define AT_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ - -#define SPEED_0 0xffff -#define HALF_DUPLEX 1 -#define FULL_DUPLEX 2 - -/* Error Codes */ -#define AT_ERR_EEPROM 1 -#define AT_ERR_PHY 2 -#define AT_ERR_CONFIG 3 -#define AT_ERR_PARAM 4 -#define AT_ERR_MAC_TYPE 5 -#define AT_ERR_PHY_TYPE 6 -#define AT_ERR_PHY_SPEED 7 -#define AT_ERR_PHY_RES 8 -#define AT_ERR_TIMEOUT 9 - -#define MAX_JUMBO_FRAME_SIZE 0x2000 - -#define AT_VLAN_TAG_TO_TPD_TAG(_vlan, _tpd) \ - _tpd = (((_vlan) << (4)) | (((_vlan) >> 13) & 7) |\ - (((_vlan) >> 9) & 8)) - -#define AT_TPD_TAG_TO_VLAN_TAG(_tpd, _vlan) \ - _vlan = (((_tpd) >> 8) | (((_tpd) & 0x77) << 9) |\ - (((_tdp) & 0x88) << 5)) - -#define AT_MAX_RECEIVE_QUEUE 4 -#define AT_PAGE_NUM_PER_QUEUE 2 - -#define AT_DMA_HI_ADDR_MASK 0xffffffff00000000ULL -#define AT_DMA_LO_ADDR_MASK 0x00000000ffffffffULL - -#define AT_TX_WATCHDOG (5 * HZ) -#define AT_MAX_INT_WORK 10 -#define AT_TWSI_EEPROM_TIMEOUT 100 -#define AT_HW_MAX_IDLE_DELAY 10 -#define AT_SUSPEND_LINK_TIMEOUT 28 - -#define AT_REGS_LEN 75 -#define AT_EEPROM_LEN 512 -#define AT_ADV_MASK (ADVERTISE_10_HALF |\ - ADVERTISE_10_FULL |\ - ADVERTISE_100_HALF |\ - ADVERTISE_100_FULL |\ - ADVERTISE_1000_FULL) - -/* tpd word 2 */ -#define TPD_BUFLEN_MASK 0x3FFF -#define TPD_BUFLEN_SHIFT 0 -#define TPD_DMAINT_MASK 0x0001 -#define TPD_DMAINT_SHIFT 14 -#define TPD_PKTNT_MASK 0x0001 -#define TPD_PKTINT_SHIFT 15 -#define TPD_VLANTAG_MASK 0xFFFF -#define TPD_VLAN_SHIFT 16 - -/* tpd word 3 bits 0:4 */ -#define TPD_EOP_MASK 0x0001 -#define TPD_EOP_SHIFT 0 -#define TPD_IP_VERSION_MASK 0x0001 -#define TPD_IP_VERSION_SHIFT 1 /* 0 : IPV4, 1 : IPV6 */ -#define TPD_INS_VL_TAG_MASK 0x0001 -#define TPD_INS_VL_TAG_SHIFT 2 -#define TPD_CC_SEGMENT_EN_MASK 0x0001 -#define TPD_CC_SEGMENT_EN_SHIFT 3 -#define TPD_SEGMENT_EN_MASK 0x0001 -#define TPD_SEGMENT_EN_SHIFT 4 - -/* tdp word 3 bits 5:7 if ip version is 0 */ -#define TPD_IP_CSUM_MASK 0x0001 -#define TPD_IP_CSUM_SHIFT 5 -#define TPD_TCP_CSUM_MASK 0x0001 -#define TPD_TCP_CSUM_SHIFT 6 -#define TPD_UDP_CSUM_MASK 0x0001 -#define TPD_UDP_CSUM_SHIFT 7 - -/* tdp word 3 bits 5:7 if ip version is 1 */ -#define TPD_V6_IPHLLO_MASK 0x0007 -#define TPD_V6_IPHLLO_SHIFT 7 - -/* tpd word 3 bits 8:9 bit */ -#define TPD_VL_TAGGED_MASK 0x0001 -#define TPD_VL_TAGGED_SHIFT 8 -#define TPD_ETHTYPE_MASK 0x0001 -#define TPD_ETHTYPE_SHIFT 9 - -/* tdp word 3 bits 10:13 if ip version is 0 */ -#define TDP_V4_IPHL_MASK 0x000F -#define TPD_V4_IPHL_SHIFT 10 - -/* tdp word 3 bits 10:13 if ip version is 1 */ -#define TPD_V6_IPHLHI_MASK 0x000F -#define TPD_V6_IPHLHI_SHIFT 10 - -/* tpd word 3 bit 14:31 if segment enabled */ -#define TPD_TCPHDRLEN_MASK 0x000F -#define TPD_TCPHDRLEN_SHIFT 14 -#define TPD_HDRFLAG_MASK 0x0001 -#define TPD_HDRFLAG_SHIFT 18 -#define TPD_MSS_MASK 0x1FFF -#define TPD_MSS_SHIFT 19 - -/* tdp word 3 bit 16:31 if custom csum enabled */ -#define TPD_PLOADOFFSET_MASK 0x00FF -#define TPD_PLOADOFFSET_SHIFT 16 -#define TPD_CCSUMOFFSET_MASK 0x00FF -#define TPD_CCSUMOFFSET_SHIFT 24 - -struct atl1e_tpd_desc { - __le64 buffer_addr; - __le32 word2; - __le32 word3; -}; - -/* how about 0x2000 */ -#define MAX_TX_BUF_LEN 0x2000 -#define MAX_TX_BUF_SHIFT 13 -#define MAX_TSO_SEG_SIZE 0x3c00 - -/* rrs word 1 bit 0:31 */ -#define RRS_RX_CSUM_MASK 0xFFFF -#define RRS_RX_CSUM_SHIFT 0 -#define RRS_PKT_SIZE_MASK 0x3FFF -#define RRS_PKT_SIZE_SHIFT 16 -#define RRS_CPU_NUM_MASK 0x0003 -#define RRS_CPU_NUM_SHIFT 30 - -#define RRS_IS_RSS_IPV4 0x0001 -#define RRS_IS_RSS_IPV4_TCP 0x0002 -#define RRS_IS_RSS_IPV6 0x0004 -#define RRS_IS_RSS_IPV6_TCP 0x0008 -#define RRS_IS_IPV6 0x0010 -#define RRS_IS_IP_FRAG 0x0020 -#define RRS_IS_IP_DF 0x0040 -#define RRS_IS_802_3 0x0080 -#define RRS_IS_VLAN_TAG 0x0100 -#define RRS_IS_ERR_FRAME 0x0200 -#define RRS_IS_IPV4 0x0400 -#define RRS_IS_UDP 0x0800 -#define RRS_IS_TCP 0x1000 -#define RRS_IS_BCAST 0x2000 -#define RRS_IS_MCAST 0x4000 -#define RRS_IS_PAUSE 0x8000 - -#define RRS_ERR_BAD_CRC 0x0001 -#define RRS_ERR_CODE 0x0002 -#define RRS_ERR_DRIBBLE 0x0004 -#define RRS_ERR_RUNT 0x0008 -#define RRS_ERR_RX_OVERFLOW 0x0010 -#define RRS_ERR_TRUNC 0x0020 -#define RRS_ERR_IP_CSUM 0x0040 -#define RRS_ERR_L4_CSUM 0x0080 -#define RRS_ERR_LENGTH 0x0100 -#define RRS_ERR_DES_ADDR 0x0200 - -struct atl1e_recv_ret_status { - u16 seq_num; - u16 hash_lo; - __le32 word1; - u16 pkt_flag; - u16 err_flag; - u16 hash_hi; - u16 vtag; -}; - -enum atl1e_dma_req_block { - atl1e_dma_req_128 = 0, - atl1e_dma_req_256 = 1, - atl1e_dma_req_512 = 2, - atl1e_dma_req_1024 = 3, - atl1e_dma_req_2048 = 4, - atl1e_dma_req_4096 = 5 -}; - -enum atl1e_rrs_type { - atl1e_rrs_disable = 0, - atl1e_rrs_ipv4 = 1, - atl1e_rrs_ipv4_tcp = 2, - atl1e_rrs_ipv6 = 4, - atl1e_rrs_ipv6_tcp = 8 -}; - -enum atl1e_nic_type { - athr_l1e = 0, - athr_l2e_revA = 1, - athr_l2e_revB = 2 -}; - -struct atl1e_hw_stats { - /* rx */ - unsigned long rx_ok; /* The number of good packet received. */ - unsigned long rx_bcast; /* The number of good broadcast packet received. */ - unsigned long rx_mcast; /* The number of good multicast packet received. */ - unsigned long rx_pause; /* The number of Pause packet received. */ - unsigned long rx_ctrl; /* The number of Control packet received other than Pause frame. */ - unsigned long rx_fcs_err; /* The number of packets with bad FCS. */ - unsigned long rx_len_err; /* The number of packets with mismatch of length field and actual size. */ - unsigned long rx_byte_cnt; /* The number of bytes of good packet received. FCS is NOT included. */ - unsigned long rx_runt; /* The number of packets received that are less than 64 byte long and with good FCS. */ - unsigned long rx_frag; /* The number of packets received that are less than 64 byte long and with bad FCS. */ - unsigned long rx_sz_64; /* The number of good and bad packets received that are 64 byte long. */ - unsigned long rx_sz_65_127; /* The number of good and bad packets received that are between 65 and 127-byte long. */ - unsigned long rx_sz_128_255; /* The number of good and bad packets received that are between 128 and 255-byte long. */ - unsigned long rx_sz_256_511; /* The number of good and bad packets received that are between 256 and 511-byte long. */ - unsigned long rx_sz_512_1023; /* The number of good and bad packets received that are between 512 and 1023-byte long. */ - unsigned long rx_sz_1024_1518; /* The number of good and bad packets received that are between 1024 and 1518-byte long. */ - unsigned long rx_sz_1519_max; /* The number of good and bad packets received that are between 1519-byte and MTU. */ - unsigned long rx_sz_ov; /* The number of good and bad packets received that are more than MTU size truncated by Selene. */ - unsigned long rx_rxf_ov; /* The number of frame dropped due to occurrence of RX FIFO overflow. */ - unsigned long rx_rrd_ov; /* The number of frame dropped due to occurrence of RRD overflow. */ - unsigned long rx_align_err; /* Alignment Error */ - unsigned long rx_bcast_byte_cnt; /* The byte count of broadcast packet received, excluding FCS. */ - unsigned long rx_mcast_byte_cnt; /* The byte count of multicast packet received, excluding FCS. */ - unsigned long rx_err_addr; /* The number of packets dropped due to address filtering. */ - - /* tx */ - unsigned long tx_ok; /* The number of good packet transmitted. */ - unsigned long tx_bcast; /* The number of good broadcast packet transmitted. */ - unsigned long tx_mcast; /* The number of good multicast packet transmitted. */ - unsigned long tx_pause; /* The number of Pause packet transmitted. */ - unsigned long tx_exc_defer; /* The number of packets transmitted with excessive deferral. */ - unsigned long tx_ctrl; /* The number of packets transmitted is a control frame, excluding Pause frame. */ - unsigned long tx_defer; /* The number of packets transmitted that is deferred. */ - unsigned long tx_byte_cnt; /* The number of bytes of data transmitted. FCS is NOT included. */ - unsigned long tx_sz_64; /* The number of good and bad packets transmitted that are 64 byte long. */ - unsigned long tx_sz_65_127; /* The number of good and bad packets transmitted that are between 65 and 127-byte long. */ - unsigned long tx_sz_128_255; /* The number of good and bad packets transmitted that are between 128 and 255-byte long. */ - unsigned long tx_sz_256_511; /* The number of good and bad packets transmitted that are between 256 and 511-byte long. */ - unsigned long tx_sz_512_1023; /* The number of good and bad packets transmitted that are between 512 and 1023-byte long. */ - unsigned long tx_sz_1024_1518; /* The number of good and bad packets transmitted that are between 1024 and 1518-byte long. */ - unsigned long tx_sz_1519_max; /* The number of good and bad packets transmitted that are between 1519-byte and MTU. */ - unsigned long tx_1_col; /* The number of packets subsequently transmitted successfully with a single prior collision. */ - unsigned long tx_2_col; /* The number of packets subsequently transmitted successfully with multiple prior collisions. */ - unsigned long tx_late_col; /* The number of packets transmitted with late collisions. */ - unsigned long tx_abort_col; /* The number of transmit packets aborted due to excessive collisions. */ - unsigned long tx_underrun; /* The number of transmit packets aborted due to transmit FIFO underrun, or TRD FIFO underrun */ - unsigned long tx_rd_eop; /* The number of times that read beyond the EOP into the next frame area when TRD was not written timely */ - unsigned long tx_len_err; /* The number of transmit packets with length field does NOT match the actual frame size. */ - unsigned long tx_trunc; /* The number of transmit packets truncated due to size exceeding MTU. */ - unsigned long tx_bcast_byte; /* The byte count of broadcast packet transmitted, excluding FCS. */ - unsigned long tx_mcast_byte; /* The byte count of multicast packet transmitted, excluding FCS. */ -}; - -struct atl1e_hw { - u8 __iomem *hw_addr; /* inner register address */ - resource_size_t mem_rang; - struct atl1e_adapter *adapter; - enum atl1e_nic_type nic_type; - u16 device_id; - u16 vendor_id; - u16 subsystem_id; - u16 subsystem_vendor_id; - u8 revision_id; - u16 pci_cmd_word; - u8 mac_addr[ETH_ALEN]; - u8 perm_mac_addr[ETH_ALEN]; - u8 preamble_len; - u16 max_frame_size; - u16 rx_jumbo_th; - u16 tx_jumbo_th; - - u16 media_type; -#define MEDIA_TYPE_AUTO_SENSOR 0 -#define MEDIA_TYPE_100M_FULL 1 -#define MEDIA_TYPE_100M_HALF 2 -#define MEDIA_TYPE_10M_FULL 3 -#define MEDIA_TYPE_10M_HALF 4 - - u16 autoneg_advertised; -#define ADVERTISE_10_HALF 0x0001 -#define ADVERTISE_10_FULL 0x0002 -#define ADVERTISE_100_HALF 0x0004 -#define ADVERTISE_100_FULL 0x0008 -#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */ -#define ADVERTISE_1000_FULL 0x0020 - u16 mii_autoneg_adv_reg; - u16 mii_1000t_ctrl_reg; - - u16 imt; /* Interrupt Moderator timer ( 2us resolution) */ - u16 ict; /* Interrupt Clear timer (2us resolution) */ - u32 smb_timer; - u16 rrd_thresh; /* Threshold of number of RRD produced to trigger - interrupt request */ - u16 tpd_thresh; - u16 rx_count_down; /* 2us resolution */ - u16 tx_count_down; - - u8 tpd_burst; /* Number of TPD to prefetch in cache-aligned burst. */ - enum atl1e_rrs_type rrs_type; - u32 base_cpu; - u32 indirect_tab; - - enum atl1e_dma_req_block dmar_block; - enum atl1e_dma_req_block dmaw_block; - u8 dmaw_dly_cnt; - u8 dmar_dly_cnt; - - bool phy_configured; - bool re_autoneg; - bool emi_ca; -}; - -/* - * wrapper around a pointer to a socket buffer, - * so a DMA handle can be stored along with the buffer - */ -struct atl1e_tx_buffer { - struct sk_buff *skb; - u16 flags; -#define ATL1E_TX_PCIMAP_SINGLE 0x0001 -#define ATL1E_TX_PCIMAP_PAGE 0x0002 -#define ATL1E_TX_PCIMAP_TYPE_MASK 0x0003 - u16 length; - dma_addr_t dma; -}; - -#define ATL1E_SET_PCIMAP_TYPE(tx_buff, type) do { \ - ((tx_buff)->flags) &= ~ATL1E_TX_PCIMAP_TYPE_MASK; \ - ((tx_buff)->flags) |= (type); \ - } while (0) - -struct atl1e_rx_page { - dma_addr_t dma; /* receive rage DMA address */ - u8 *addr; /* receive rage virtual address */ - dma_addr_t write_offset_dma; /* the DMA address which contain the - receive data offset in the page */ - u32 *write_offset_addr; /* the virtaul address which contain - the receive data offset in the page */ - u32 read_offset; /* the offset where we have read */ -}; - -struct atl1e_rx_page_desc { - struct atl1e_rx_page rx_page[AT_PAGE_NUM_PER_QUEUE]; - u8 rx_using; - u16 rx_nxseq; -}; - -/* transmit packet descriptor (tpd) ring */ -struct atl1e_tx_ring { - struct atl1e_tpd_desc *desc; /* descriptor ring virtual address */ - dma_addr_t dma; /* descriptor ring physical address */ - u16 count; /* the count of transmit rings */ - rwlock_t tx_lock; - u16 next_to_use; - atomic_t next_to_clean; - struct atl1e_tx_buffer *tx_buffer; - dma_addr_t cmb_dma; - u32 *cmb; -}; - -/* receive packet descriptor ring */ -struct atl1e_rx_ring { - void *desc; - dma_addr_t dma; - int size; - u32 page_size; /* bytes length of rxf page */ - u32 real_page_size; /* real_page_size = page_size + jumbo + aliagn */ - struct atl1e_rx_page_desc rx_page_desc[AT_MAX_RECEIVE_QUEUE]; -}; - -/* board specific private data structure */ -struct atl1e_adapter { - struct net_device *netdev; - struct pci_dev *pdev; - struct napi_struct napi; - struct mii_if_info mii; /* MII interface info */ - struct atl1e_hw hw; - struct atl1e_hw_stats hw_stats; - - u32 wol; - u16 link_speed; - u16 link_duplex; - - spinlock_t mdio_lock; - spinlock_t tx_lock; - atomic_t irq_sem; - - struct work_struct reset_task; - struct work_struct link_chg_task; - struct timer_list watchdog_timer; - struct timer_list phy_config_timer; - - /* All Descriptor memory */ - dma_addr_t ring_dma; - void *ring_vir_addr; - u32 ring_size; - - struct atl1e_tx_ring tx_ring; - struct atl1e_rx_ring rx_ring; - int num_rx_queues; - unsigned long flags; -#define __AT_TESTING 0x0001 -#define __AT_RESETTING 0x0002 -#define __AT_DOWN 0x0003 - - u32 bd_number; /* board number;*/ - u32 pci_state[16]; - u32 *config_space; -}; - -#define AT_WRITE_REG(a, reg, value) ( \ - writel((value), ((a)->hw_addr + reg))) - -#define AT_WRITE_FLUSH(a) (\ - readl((a)->hw_addr)) - -#define AT_READ_REG(a, reg) ( \ - readl((a)->hw_addr + reg)) - -#define AT_WRITE_REGB(a, reg, value) (\ - writeb((value), ((a)->hw_addr + reg))) - -#define AT_READ_REGB(a, reg) (\ - readb((a)->hw_addr + reg)) - -#define AT_WRITE_REGW(a, reg, value) (\ - writew((value), ((a)->hw_addr + reg))) - -#define AT_READ_REGW(a, reg) (\ - readw((a)->hw_addr + reg)) - -#define AT_WRITE_REG_ARRAY(a, reg, offset, value) ( \ - writel((value), (((a)->hw_addr + reg) + ((offset) << 2)))) - -#define AT_READ_REG_ARRAY(a, reg, offset) ( \ - readl(((a)->hw_addr + reg) + ((offset) << 2))) - -extern char atl1e_driver_name[]; -extern char atl1e_driver_version[]; - -void atl1e_check_options(struct atl1e_adapter *adapter); -int atl1e_up(struct atl1e_adapter *adapter); -void atl1e_down(struct atl1e_adapter *adapter); -void atl1e_reinit_locked(struct atl1e_adapter *adapter); -s32 atl1e_reset_hw(struct atl1e_hw *hw); -void atl1e_set_ethtool_ops(struct net_device *netdev); -#endif /* _ATL1_E_H_ */ diff --git a/addons/atl1e/src/4.4.180/atl1e_ethtool.c b/addons/atl1e/src/4.4.180/atl1e_ethtool.c deleted file mode 100644 index 8e3dbd4d..00000000 --- a/addons/atl1e/src/4.4.180/atl1e_ethtool.c +++ /dev/null @@ -1,388 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - * - */ - -#include -#include -#include - -#include "atl1e.h" - -static int atl1e_get_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - - ecmd->supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP); - if (hw->nic_type == athr_l1e) - ecmd->supported |= SUPPORTED_1000baseT_Full; - - ecmd->advertising = ADVERTISED_TP; - - ecmd->advertising |= ADVERTISED_Autoneg; - ecmd->advertising |= hw->autoneg_advertised; - - ecmd->port = PORT_TP; - ecmd->phy_address = 0; - ecmd->transceiver = XCVR_INTERNAL; - - if (adapter->link_speed != SPEED_0) { - ethtool_cmd_speed_set(ecmd, adapter->link_speed); - if (adapter->link_duplex == FULL_DUPLEX) - ecmd->duplex = DUPLEX_FULL; - else - ecmd->duplex = DUPLEX_HALF; - } else { - ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); - ecmd->duplex = DUPLEX_UNKNOWN; - } - - ecmd->autoneg = AUTONEG_ENABLE; - return 0; -} - -static int atl1e_set_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - - while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) - msleep(1); - - if (ecmd->autoneg == AUTONEG_ENABLE) { - u16 adv4, adv9; - - if ((ecmd->advertising&ADVERTISE_1000_FULL)) { - if (hw->nic_type == athr_l1e) { - hw->autoneg_advertised = - ecmd->advertising & AT_ADV_MASK; - } else { - clear_bit(__AT_RESETTING, &adapter->flags); - return -EINVAL; - } - } else if (ecmd->advertising&ADVERTISE_1000_HALF) { - clear_bit(__AT_RESETTING, &adapter->flags); - return -EINVAL; - } else { - hw->autoneg_advertised = - ecmd->advertising & AT_ADV_MASK; - } - ecmd->advertising = hw->autoneg_advertised | - ADVERTISED_TP | ADVERTISED_Autoneg; - - adv4 = hw->mii_autoneg_adv_reg & ~ADVERTISE_ALL; - adv9 = hw->mii_1000t_ctrl_reg & ~MII_AT001_CR_1000T_SPEED_MASK; - if (hw->autoneg_advertised & ADVERTISE_10_HALF) - adv4 |= ADVERTISE_10HALF; - if (hw->autoneg_advertised & ADVERTISE_10_FULL) - adv4 |= ADVERTISE_10FULL; - if (hw->autoneg_advertised & ADVERTISE_100_HALF) - adv4 |= ADVERTISE_100HALF; - if (hw->autoneg_advertised & ADVERTISE_100_FULL) - adv4 |= ADVERTISE_100FULL; - if (hw->autoneg_advertised & ADVERTISE_1000_FULL) - adv9 |= ADVERTISE_1000FULL; - - if (adv4 != hw->mii_autoneg_adv_reg || - adv9 != hw->mii_1000t_ctrl_reg) { - hw->mii_autoneg_adv_reg = adv4; - hw->mii_1000t_ctrl_reg = adv9; - hw->re_autoneg = true; - } - - } else { - clear_bit(__AT_RESETTING, &adapter->flags); - return -EINVAL; - } - - /* reset the link */ - - if (netif_running(adapter->netdev)) { - atl1e_down(adapter); - atl1e_up(adapter); - } else - atl1e_reset_hw(&adapter->hw); - - clear_bit(__AT_RESETTING, &adapter->flags); - return 0; -} - -static u32 atl1e_get_msglevel(struct net_device *netdev) -{ -#ifdef DBG - return 1; -#else - return 0; -#endif -} - -static int atl1e_get_regs_len(struct net_device *netdev) -{ - return AT_REGS_LEN * sizeof(u32); -} - -static void atl1e_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - u32 *regs_buff = p; - u16 phy_data; - - memset(p, 0, AT_REGS_LEN * sizeof(u32)); - - regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; - - regs_buff[0] = AT_READ_REG(hw, REG_VPD_CAP); - regs_buff[1] = AT_READ_REG(hw, REG_SPI_FLASH_CTRL); - regs_buff[2] = AT_READ_REG(hw, REG_SPI_FLASH_CONFIG); - regs_buff[3] = AT_READ_REG(hw, REG_TWSI_CTRL); - regs_buff[4] = AT_READ_REG(hw, REG_PCIE_DEV_MISC_CTRL); - regs_buff[5] = AT_READ_REG(hw, REG_MASTER_CTRL); - regs_buff[6] = AT_READ_REG(hw, REG_MANUAL_TIMER_INIT); - regs_buff[7] = AT_READ_REG(hw, REG_IRQ_MODU_TIMER_INIT); - regs_buff[8] = AT_READ_REG(hw, REG_GPHY_CTRL); - regs_buff[9] = AT_READ_REG(hw, REG_CMBDISDMA_TIMER); - regs_buff[10] = AT_READ_REG(hw, REG_IDLE_STATUS); - regs_buff[11] = AT_READ_REG(hw, REG_MDIO_CTRL); - regs_buff[12] = AT_READ_REG(hw, REG_SERDES_LOCK); - regs_buff[13] = AT_READ_REG(hw, REG_MAC_CTRL); - regs_buff[14] = AT_READ_REG(hw, REG_MAC_IPG_IFG); - regs_buff[15] = AT_READ_REG(hw, REG_MAC_STA_ADDR); - regs_buff[16] = AT_READ_REG(hw, REG_MAC_STA_ADDR+4); - regs_buff[17] = AT_READ_REG(hw, REG_RX_HASH_TABLE); - regs_buff[18] = AT_READ_REG(hw, REG_RX_HASH_TABLE+4); - regs_buff[19] = AT_READ_REG(hw, REG_MAC_HALF_DUPLX_CTRL); - regs_buff[20] = AT_READ_REG(hw, REG_MTU); - regs_buff[21] = AT_READ_REG(hw, REG_WOL_CTRL); - regs_buff[22] = AT_READ_REG(hw, REG_SRAM_TRD_ADDR); - regs_buff[23] = AT_READ_REG(hw, REG_SRAM_TRD_LEN); - regs_buff[24] = AT_READ_REG(hw, REG_SRAM_RXF_ADDR); - regs_buff[25] = AT_READ_REG(hw, REG_SRAM_RXF_LEN); - regs_buff[26] = AT_READ_REG(hw, REG_SRAM_TXF_ADDR); - regs_buff[27] = AT_READ_REG(hw, REG_SRAM_TXF_LEN); - regs_buff[28] = AT_READ_REG(hw, REG_SRAM_TCPH_ADDR); - regs_buff[29] = AT_READ_REG(hw, REG_SRAM_PKTH_ADDR); - - atl1e_read_phy_reg(hw, MII_BMCR, &phy_data); - regs_buff[73] = (u32)phy_data; - atl1e_read_phy_reg(hw, MII_BMSR, &phy_data); - regs_buff[74] = (u32)phy_data; -} - -static int atl1e_get_eeprom_len(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - if (!atl1e_check_eeprom_exist(&adapter->hw)) - return AT_EEPROM_LEN; - else - return 0; -} - -static int atl1e_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - u32 *eeprom_buff; - int first_dword, last_dword; - int ret_val = 0; - int i; - - if (eeprom->len == 0) - return -EINVAL; - - if (atl1e_check_eeprom_exist(hw)) /* not exist */ - return -EINVAL; - - eeprom->magic = hw->vendor_id | (hw->device_id << 16); - - first_dword = eeprom->offset >> 2; - last_dword = (eeprom->offset + eeprom->len - 1) >> 2; - - eeprom_buff = kmalloc(sizeof(u32) * - (last_dword - first_dword + 1), GFP_KERNEL); - if (eeprom_buff == NULL) - return -ENOMEM; - - for (i = first_dword; i < last_dword; i++) { - if (!atl1e_read_eeprom(hw, i * 4, &(eeprom_buff[i-first_dword]))) { - kfree(eeprom_buff); - return -EIO; - } - } - - memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 3), - eeprom->len); - kfree(eeprom_buff); - - return ret_val; -} - -static int atl1e_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - u32 *eeprom_buff; - u32 *ptr; - int first_dword, last_dword; - int ret_val = 0; - int i; - - if (eeprom->len == 0) - return -EOPNOTSUPP; - - if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) - return -EINVAL; - - first_dword = eeprom->offset >> 2; - last_dword = (eeprom->offset + eeprom->len - 1) >> 2; - eeprom_buff = kmalloc(AT_EEPROM_LEN, GFP_KERNEL); - if (eeprom_buff == NULL) - return -ENOMEM; - - ptr = eeprom_buff; - - if (eeprom->offset & 3) { - /* need read/modify/write of first changed EEPROM word */ - /* only the second byte of the word is being modified */ - if (!atl1e_read_eeprom(hw, first_dword * 4, &(eeprom_buff[0]))) { - ret_val = -EIO; - goto out; - } - ptr++; - } - if (((eeprom->offset + eeprom->len) & 3)) { - /* need read/modify/write of last changed EEPROM word */ - /* only the first byte of the word is being modified */ - - if (!atl1e_read_eeprom(hw, last_dword * 4, - &(eeprom_buff[last_dword - first_dword]))) { - ret_val = -EIO; - goto out; - } - } - - /* Device's eeprom is always little-endian, word addressable */ - memcpy(ptr, bytes, eeprom->len); - - for (i = 0; i < last_dword - first_dword + 1; i++) { - if (!atl1e_write_eeprom(hw, ((first_dword + i) * 4), - eeprom_buff[i])) { - ret_val = -EIO; - goto out; - } - } -out: - kfree(eeprom_buff); - return ret_val; -} - -static void atl1e_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - strlcpy(drvinfo->driver, atl1e_driver_name, sizeof(drvinfo->driver)); - strlcpy(drvinfo->version, atl1e_driver_version, - sizeof(drvinfo->version)); - strlcpy(drvinfo->fw_version, "L1e", sizeof(drvinfo->fw_version)); - strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), - sizeof(drvinfo->bus_info)); -} - -static void atl1e_get_wol(struct net_device *netdev, - struct ethtool_wolinfo *wol) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - wol->supported = WAKE_MAGIC | WAKE_PHY; - wol->wolopts = 0; - - if (adapter->wol & AT_WUFC_EX) - wol->wolopts |= WAKE_UCAST; - if (adapter->wol & AT_WUFC_MC) - wol->wolopts |= WAKE_MCAST; - if (adapter->wol & AT_WUFC_BC) - wol->wolopts |= WAKE_BCAST; - if (adapter->wol & AT_WUFC_MAG) - wol->wolopts |= WAKE_MAGIC; - if (adapter->wol & AT_WUFC_LNKC) - wol->wolopts |= WAKE_PHY; -} - -static int atl1e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - if (wol->wolopts & (WAKE_ARP | WAKE_MAGICSECURE | - WAKE_UCAST | WAKE_MCAST | WAKE_BCAST)) - return -EOPNOTSUPP; - /* these settings will always override what we currently have */ - adapter->wol = 0; - - if (wol->wolopts & WAKE_MAGIC) - adapter->wol |= AT_WUFC_MAG; - if (wol->wolopts & WAKE_PHY) - adapter->wol |= AT_WUFC_LNKC; - - device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); - - return 0; -} - -static int atl1e_nway_reset(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - if (netif_running(netdev)) - atl1e_reinit_locked(adapter); - return 0; -} - -static const struct ethtool_ops atl1e_ethtool_ops = { - .get_settings = atl1e_get_settings, - .set_settings = atl1e_set_settings, - .get_drvinfo = atl1e_get_drvinfo, - .get_regs_len = atl1e_get_regs_len, - .get_regs = atl1e_get_regs, - .get_wol = atl1e_get_wol, - .set_wol = atl1e_set_wol, - .get_msglevel = atl1e_get_msglevel, - .nway_reset = atl1e_nway_reset, - .get_link = ethtool_op_get_link, - .get_eeprom_len = atl1e_get_eeprom_len, - .get_eeprom = atl1e_get_eeprom, - .set_eeprom = atl1e_set_eeprom, -}; - -void atl1e_set_ethtool_ops(struct net_device *netdev) -{ - netdev->ethtool_ops = &atl1e_ethtool_ops; -} diff --git a/addons/atl1e/src/4.4.180/atl1e_hw.c b/addons/atl1e/src/4.4.180/atl1e_hw.c deleted file mode 100644 index 113565da..00000000 --- a/addons/atl1e/src/4.4.180/atl1e_hw.c +++ /dev/null @@ -1,650 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ -#include -#include -#include -#include - -#include "atl1e.h" - -/* - * check_eeprom_exist - * return 0 if eeprom exist - */ -int atl1e_check_eeprom_exist(struct atl1e_hw *hw) -{ - u32 value; - - value = AT_READ_REG(hw, REG_SPI_FLASH_CTRL); - if (value & SPI_FLASH_CTRL_EN_VPD) { - value &= ~SPI_FLASH_CTRL_EN_VPD; - AT_WRITE_REG(hw, REG_SPI_FLASH_CTRL, value); - } - value = AT_READ_REGW(hw, REG_PCIE_CAP_LIST); - return ((value & 0xFF00) == 0x6C00) ? 0 : 1; -} - -void atl1e_hw_set_mac_addr(struct atl1e_hw *hw) -{ - u32 value; - /* - * 00-0B-6A-F6-00-DC - * 0: 6AF600DC 1: 000B - * low dword - */ - value = (((u32)hw->mac_addr[2]) << 24) | - (((u32)hw->mac_addr[3]) << 16) | - (((u32)hw->mac_addr[4]) << 8) | - (((u32)hw->mac_addr[5])) ; - AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 0, value); - /* hight dword */ - value = (((u32)hw->mac_addr[0]) << 8) | - (((u32)hw->mac_addr[1])) ; - AT_WRITE_REG_ARRAY(hw, REG_MAC_STA_ADDR, 1, value); -} - -/* - * atl1e_get_permanent_address - * return 0 if get valid mac address, - */ -static int atl1e_get_permanent_address(struct atl1e_hw *hw) -{ - u32 addr[2]; - u32 i; - u32 twsi_ctrl_data; - u8 eth_addr[ETH_ALEN]; - - if (is_valid_ether_addr(hw->perm_mac_addr)) - return 0; - - /* init */ - addr[0] = addr[1] = 0; - - if (!atl1e_check_eeprom_exist(hw)) { - /* eeprom exist */ - twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL); - twsi_ctrl_data |= TWSI_CTRL_SW_LDSTART; - AT_WRITE_REG(hw, REG_TWSI_CTRL, twsi_ctrl_data); - for (i = 0; i < AT_TWSI_EEPROM_TIMEOUT; i++) { - msleep(10); - twsi_ctrl_data = AT_READ_REG(hw, REG_TWSI_CTRL); - if ((twsi_ctrl_data & TWSI_CTRL_SW_LDSTART) == 0) - break; - } - if (i >= AT_TWSI_EEPROM_TIMEOUT) - return AT_ERR_TIMEOUT; - } - - /* maybe MAC-address is from BIOS */ - addr[0] = AT_READ_REG(hw, REG_MAC_STA_ADDR); - addr[1] = AT_READ_REG(hw, REG_MAC_STA_ADDR + 4); - *(u32 *) ð_addr[2] = swab32(addr[0]); - *(u16 *) ð_addr[0] = swab16(*(u16 *)&addr[1]); - - if (is_valid_ether_addr(eth_addr)) { - memcpy(hw->perm_mac_addr, eth_addr, ETH_ALEN); - return 0; - } - - return AT_ERR_EEPROM; -} - -bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value) -{ - return true; -} - -bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value) -{ - int i; - u32 control; - - if (offset & 3) - return false; /* address do not align */ - - AT_WRITE_REG(hw, REG_VPD_DATA, 0); - control = (offset & VPD_CAP_VPD_ADDR_MASK) << VPD_CAP_VPD_ADDR_SHIFT; - AT_WRITE_REG(hw, REG_VPD_CAP, control); - - for (i = 0; i < 10; i++) { - msleep(2); - control = AT_READ_REG(hw, REG_VPD_CAP); - if (control & VPD_CAP_VPD_FLAG) - break; - } - if (control & VPD_CAP_VPD_FLAG) { - *p_value = AT_READ_REG(hw, REG_VPD_DATA); - return true; - } - return false; /* timeout */ -} - -void atl1e_force_ps(struct atl1e_hw *hw) -{ - AT_WRITE_REGW(hw, REG_GPHY_CTRL, - GPHY_CTRL_PW_WOL_DIS | GPHY_CTRL_EXT_RESET); -} - -/* - * Reads the adapter's MAC address from the EEPROM - * - * hw - Struct containing variables accessed by shared code - */ -int atl1e_read_mac_addr(struct atl1e_hw *hw) -{ - int err = 0; - - err = atl1e_get_permanent_address(hw); - if (err) - return AT_ERR_EEPROM; - memcpy(hw->mac_addr, hw->perm_mac_addr, sizeof(hw->perm_mac_addr)); - return 0; -} - -/* - * atl1e_hash_mc_addr - * purpose - * set hash value for a multicast address - */ -u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr) -{ - u32 crc32; - u32 value = 0; - int i; - - crc32 = ether_crc_le(6, mc_addr); - for (i = 0; i < 32; i++) - value |= (((crc32 >> i) & 1) << (31 - i)); - - return value; -} - -/* - * Sets the bit in the multicast table corresponding to the hash value. - * hw - Struct containing variables accessed by shared code - * hash_value - Multicast address hash value - */ -void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value) -{ - u32 hash_bit, hash_reg; - u32 mta; - - /* - * The HASH Table is a register array of 2 32-bit registers. - * It is treated like an array of 64 bits. We want to set - * bit BitArray[hash_value]. So we figure out what register - * the bit is in, read it, OR in the new bit, then write - * back the new value. The register is determined by the - * upper 7 bits of the hash value and the bit within that - * register are determined by the lower 5 bits of the value. - */ - hash_reg = (hash_value >> 31) & 0x1; - hash_bit = (hash_value >> 26) & 0x1F; - - mta = AT_READ_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg); - - mta |= (1 << hash_bit); - - AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, hash_reg, mta); -} -/* - * Reads the value from a PHY register - * hw - Struct containing variables accessed by shared code - * reg_addr - address of the PHY register to read - */ -int atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data) -{ - u32 val; - int i; - - val = ((u32)(reg_addr & MDIO_REG_ADDR_MASK)) << MDIO_REG_ADDR_SHIFT | - MDIO_START | MDIO_SUP_PREAMBLE | MDIO_RW | - MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; - - AT_WRITE_REG(hw, REG_MDIO_CTRL, val); - - wmb(); - - for (i = 0; i < MDIO_WAIT_TIMES; i++) { - udelay(2); - val = AT_READ_REG(hw, REG_MDIO_CTRL); - if (!(val & (MDIO_START | MDIO_BUSY))) - break; - wmb(); - } - if (!(val & (MDIO_START | MDIO_BUSY))) { - *phy_data = (u16)val; - return 0; - } - - return AT_ERR_PHY; -} - -/* - * Writes a value to a PHY register - * hw - Struct containing variables accessed by shared code - * reg_addr - address of the PHY register to write - * data - data to write to the PHY - */ -int atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data) -{ - int i; - u32 val; - - val = ((u32)(phy_data & MDIO_DATA_MASK)) << MDIO_DATA_SHIFT | - (reg_addr&MDIO_REG_ADDR_MASK) << MDIO_REG_ADDR_SHIFT | - MDIO_SUP_PREAMBLE | - MDIO_START | - MDIO_CLK_25_4 << MDIO_CLK_SEL_SHIFT; - - AT_WRITE_REG(hw, REG_MDIO_CTRL, val); - wmb(); - - for (i = 0; i < MDIO_WAIT_TIMES; i++) { - udelay(2); - val = AT_READ_REG(hw, REG_MDIO_CTRL); - if (!(val & (MDIO_START | MDIO_BUSY))) - break; - wmb(); - } - - if (!(val & (MDIO_START | MDIO_BUSY))) - return 0; - - return AT_ERR_PHY; -} - -/* - * atl1e_init_pcie - init PCIE module - */ -static void atl1e_init_pcie(struct atl1e_hw *hw) -{ - u32 value; - /* comment 2lines below to save more power when sususpend - value = LTSSM_TEST_MODE_DEF; - AT_WRITE_REG(hw, REG_LTSSM_TEST_MODE, value); - */ - - /* pcie flow control mode change */ - value = AT_READ_REG(hw, 0x1008); - value |= 0x8000; - AT_WRITE_REG(hw, 0x1008, value); -} -/* - * Configures PHY autoneg and flow control advertisement settings - * - * hw - Struct containing variables accessed by shared code - */ -static int atl1e_phy_setup_autoneg_adv(struct atl1e_hw *hw) -{ - s32 ret_val; - u16 mii_autoneg_adv_reg; - u16 mii_1000t_ctrl_reg; - - if (0 != hw->mii_autoneg_adv_reg) - return 0; - /* Read the MII Auto-Neg Advertisement Register (Address 4/9). */ - mii_autoneg_adv_reg = MII_AR_DEFAULT_CAP_MASK; - mii_1000t_ctrl_reg = MII_AT001_CR_1000T_DEFAULT_CAP_MASK; - - /* - * Need to parse autoneg_advertised and set up - * the appropriate PHY registers. First we will parse for - * autoneg_advertised software override. Since we can advertise - * a plethora of combinations, we need to check each bit - * individually. - */ - - /* - * First we clear all the 10/100 mb speed bits in the Auto-Neg - * Advertisement Register (Address 4) and the 1000 mb speed bits in - * the 1000Base-T control Register (Address 9). - */ - mii_autoneg_adv_reg &= ~ADVERTISE_ALL; - mii_1000t_ctrl_reg &= ~MII_AT001_CR_1000T_SPEED_MASK; - - /* - * Need to parse MediaType and setup the - * appropriate PHY registers. - */ - switch (hw->media_type) { - case MEDIA_TYPE_AUTO_SENSOR: - mii_autoneg_adv_reg |= ADVERTISE_ALL; - hw->autoneg_advertised = ADVERTISE_ALL; - if (hw->nic_type == athr_l1e) { - mii_1000t_ctrl_reg |= ADVERTISE_1000FULL; - hw->autoneg_advertised |= ADVERTISE_1000_FULL; - } - break; - - case MEDIA_TYPE_100M_FULL: - mii_autoneg_adv_reg |= ADVERTISE_100FULL; - hw->autoneg_advertised = ADVERTISE_100_FULL; - break; - - case MEDIA_TYPE_100M_HALF: - mii_autoneg_adv_reg |= ADVERTISE_100_HALF; - hw->autoneg_advertised = ADVERTISE_100_HALF; - break; - - case MEDIA_TYPE_10M_FULL: - mii_autoneg_adv_reg |= ADVERTISE_10_FULL; - hw->autoneg_advertised = ADVERTISE_10_FULL; - break; - - default: - mii_autoneg_adv_reg |= ADVERTISE_10_HALF; - hw->autoneg_advertised = ADVERTISE_10_HALF; - break; - } - - /* flow control fixed to enable all */ - mii_autoneg_adv_reg |= (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP); - - hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg; - hw->mii_1000t_ctrl_reg = mii_1000t_ctrl_reg; - - ret_val = atl1e_write_phy_reg(hw, MII_ADVERTISE, mii_autoneg_adv_reg); - if (ret_val) - return ret_val; - - if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) { - ret_val = atl1e_write_phy_reg(hw, MII_CTRL1000, - mii_1000t_ctrl_reg); - if (ret_val) - return ret_val; - } - - return 0; -} - - -/* - * Resets the PHY and make all config validate - * - * hw - Struct containing variables accessed by shared code - * - * Sets bit 15 and 12 of the MII control regiser (for F001 bug) - */ -int atl1e_phy_commit(struct atl1e_hw *hw) -{ - struct atl1e_adapter *adapter = hw->adapter; - int ret_val; - u16 phy_data; - - phy_data = BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART; - - ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data); - if (ret_val) { - u32 val; - int i; - /************************************** - * pcie serdes link may be down ! - **************************************/ - for (i = 0; i < 25; i++) { - msleep(1); - val = AT_READ_REG(hw, REG_MDIO_CTRL); - if (!(val & (MDIO_START | MDIO_BUSY))) - break; - } - - if (0 != (val & (MDIO_START | MDIO_BUSY))) { - netdev_err(adapter->netdev, - "pcie linkdown at least for 25ms\n"); - return ret_val; - } - - netdev_err(adapter->netdev, "pcie linkup after %d ms\n", i); - } - return 0; -} - -int atl1e_phy_init(struct atl1e_hw *hw) -{ - struct atl1e_adapter *adapter = hw->adapter; - s32 ret_val; - u16 phy_val; - - if (hw->phy_configured) { - if (hw->re_autoneg) { - hw->re_autoneg = false; - return atl1e_restart_autoneg(hw); - } - return 0; - } - - /* RESET GPHY Core */ - AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT); - msleep(2); - AT_WRITE_REGW(hw, REG_GPHY_CTRL, GPHY_CTRL_DEFAULT | - GPHY_CTRL_EXT_RESET); - msleep(2); - - /* patches */ - /* p1. eable hibernation mode */ - ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0xB); - if (ret_val) - return ret_val; - ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0xBC00); - if (ret_val) - return ret_val; - /* p2. set Class A/B for all modes */ - ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0); - if (ret_val) - return ret_val; - phy_val = 0x02ef; - /* remove Class AB */ - /* phy_val = hw->emi_ca ? 0x02ef : 0x02df; */ - ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, phy_val); - if (ret_val) - return ret_val; - /* p3. 10B ??? */ - ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x12); - if (ret_val) - return ret_val; - ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x4C04); - if (ret_val) - return ret_val; - /* p4. 1000T power */ - ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x4); - if (ret_val) - return ret_val; - ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x8BBB); - if (ret_val) - return ret_val; - - ret_val = atl1e_write_phy_reg(hw, MII_DBG_ADDR, 0x5); - if (ret_val) - return ret_val; - ret_val = atl1e_write_phy_reg(hw, MII_DBG_DATA, 0x2C46); - if (ret_val) - return ret_val; - - msleep(1); - - /*Enable PHY LinkChange Interrupt */ - ret_val = atl1e_write_phy_reg(hw, MII_INT_CTRL, 0xC00); - if (ret_val) { - netdev_err(adapter->netdev, - "Error enable PHY linkChange Interrupt\n"); - return ret_val; - } - /* setup AutoNeg parameters */ - ret_val = atl1e_phy_setup_autoneg_adv(hw); - if (ret_val) { - netdev_err(adapter->netdev, - "Error Setting up Auto-Negotiation\n"); - return ret_val; - } - /* SW.Reset & En-Auto-Neg to restart Auto-Neg*/ - netdev_dbg(adapter->netdev, "Restarting Auto-Negotiation\n"); - ret_val = atl1e_phy_commit(hw); - if (ret_val) { - netdev_err(adapter->netdev, "Error resetting the phy\n"); - return ret_val; - } - - hw->phy_configured = true; - - return 0; -} - -/* - * Reset the transmit and receive units; mask and clear all interrupts. - * hw - Struct containing variables accessed by shared code - * return : 0 or idle status (if error) - */ -int atl1e_reset_hw(struct atl1e_hw *hw) -{ - struct atl1e_adapter *adapter = hw->adapter; - struct pci_dev *pdev = adapter->pdev; - - u32 idle_status_data = 0; - u16 pci_cfg_cmd_word = 0; - int timeout = 0; - - /* Workaround for PCI problem when BIOS sets MMRBC incorrectly. */ - pci_read_config_word(pdev, PCI_REG_COMMAND, &pci_cfg_cmd_word); - if ((pci_cfg_cmd_word & (CMD_IO_SPACE | - CMD_MEMORY_SPACE | CMD_BUS_MASTER)) - != (CMD_IO_SPACE | CMD_MEMORY_SPACE | CMD_BUS_MASTER)) { - pci_cfg_cmd_word |= (CMD_IO_SPACE | - CMD_MEMORY_SPACE | CMD_BUS_MASTER); - pci_write_config_word(pdev, PCI_REG_COMMAND, pci_cfg_cmd_word); - } - - /* - * Issue Soft Reset to the MAC. This will reset the chip's - * transmit, receive, DMA. It will not effect - * the current PCI configuration. The global reset bit is self- - * clearing, and should clear within a microsecond. - */ - AT_WRITE_REG(hw, REG_MASTER_CTRL, - MASTER_CTRL_LED_MODE | MASTER_CTRL_SOFT_RST); - wmb(); - msleep(1); - - /* Wait at least 10ms for All module to be Idle */ - for (timeout = 0; timeout < AT_HW_MAX_IDLE_DELAY; timeout++) { - idle_status_data = AT_READ_REG(hw, REG_IDLE_STATUS); - if (idle_status_data == 0) - break; - msleep(1); - cpu_relax(); - } - - if (timeout >= AT_HW_MAX_IDLE_DELAY) { - netdev_err(adapter->netdev, - "MAC state machine can't be idle since disabled for 10ms second\n"); - return AT_ERR_TIMEOUT; - } - - return 0; -} - - -/* - * Performs basic configuration of the adapter. - * - * hw - Struct containing variables accessed by shared code - * Assumes that the controller has previously been reset and is in a - * post-reset uninitialized state. Initializes multicast table, - * and Calls routines to setup link - * Leaves the transmit and receive units disabled and uninitialized. - */ -int atl1e_init_hw(struct atl1e_hw *hw) -{ - s32 ret_val = 0; - - atl1e_init_pcie(hw); - - /* Zero out the Multicast HASH table */ - /* clear the old settings from the multicast hash table */ - AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); - AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); - - ret_val = atl1e_phy_init(hw); - - return ret_val; -} - -/* - * Detects the current speed and duplex settings of the hardware. - * - * hw - Struct containing variables accessed by shared code - * speed - Speed of the connection - * duplex - Duplex setting of the connection - */ -int atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex) -{ - int err; - u16 phy_data; - - /* Read PHY Specific Status Register (17) */ - err = atl1e_read_phy_reg(hw, MII_AT001_PSSR, &phy_data); - if (err) - return err; - - if (!(phy_data & MII_AT001_PSSR_SPD_DPLX_RESOLVED)) - return AT_ERR_PHY_RES; - - switch (phy_data & MII_AT001_PSSR_SPEED) { - case MII_AT001_PSSR_1000MBS: - *speed = SPEED_1000; - break; - case MII_AT001_PSSR_100MBS: - *speed = SPEED_100; - break; - case MII_AT001_PSSR_10MBS: - *speed = SPEED_10; - break; - default: - return AT_ERR_PHY_SPEED; - } - - if (phy_data & MII_AT001_PSSR_DPLX) - *duplex = FULL_DUPLEX; - else - *duplex = HALF_DUPLEX; - - return 0; -} - -int atl1e_restart_autoneg(struct atl1e_hw *hw) -{ - int err = 0; - - err = atl1e_write_phy_reg(hw, MII_ADVERTISE, hw->mii_autoneg_adv_reg); - if (err) - return err; - - if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) { - err = atl1e_write_phy_reg(hw, MII_CTRL1000, - hw->mii_1000t_ctrl_reg); - if (err) - return err; - } - - err = atl1e_write_phy_reg(hw, MII_BMCR, - BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART); - return err; -} - diff --git a/addons/atl1e/src/4.4.180/atl1e_hw.h b/addons/atl1e/src/4.4.180/atl1e_hw.h deleted file mode 100644 index 88a6271d..00000000 --- a/addons/atl1e/src/4.4.180/atl1e_hw.h +++ /dev/null @@ -1,690 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#ifndef _ATHL1E_HW_H_ -#define _ATHL1E_HW_H_ - -#include -#include - -struct atl1e_adapter; -struct atl1e_hw; - -/* function prototype */ -s32 atl1e_reset_hw(struct atl1e_hw *hw); -s32 atl1e_read_mac_addr(struct atl1e_hw *hw); -s32 atl1e_init_hw(struct atl1e_hw *hw); -s32 atl1e_phy_commit(struct atl1e_hw *hw); -s32 atl1e_get_speed_and_duplex(struct atl1e_hw *hw, u16 *speed, u16 *duplex); -u32 atl1e_auto_get_fc(struct atl1e_adapter *adapter, u16 duplex); -u32 atl1e_hash_mc_addr(struct atl1e_hw *hw, u8 *mc_addr); -void atl1e_hash_set(struct atl1e_hw *hw, u32 hash_value); -s32 atl1e_read_phy_reg(struct atl1e_hw *hw, u16 reg_addr, u16 *phy_data); -s32 atl1e_write_phy_reg(struct atl1e_hw *hw, u32 reg_addr, u16 phy_data); -s32 atl1e_validate_mdi_setting(struct atl1e_hw *hw); -void atl1e_hw_set_mac_addr(struct atl1e_hw *hw); -bool atl1e_read_eeprom(struct atl1e_hw *hw, u32 offset, u32 *p_value); -bool atl1e_write_eeprom(struct atl1e_hw *hw, u32 offset, u32 value); -s32 atl1e_phy_enter_power_saving(struct atl1e_hw *hw); -s32 atl1e_phy_leave_power_saving(struct atl1e_hw *hw); -s32 atl1e_phy_init(struct atl1e_hw *hw); -int atl1e_check_eeprom_exist(struct atl1e_hw *hw); -void atl1e_force_ps(struct atl1e_hw *hw); -s32 atl1e_restart_autoneg(struct atl1e_hw *hw); - -/* register definition */ -#define REG_PM_CTRLSTAT 0x44 - -#define REG_PCIE_CAP_LIST 0x58 - -#define REG_DEVICE_CAP 0x5C -#define DEVICE_CAP_MAX_PAYLOAD_MASK 0x7 -#define DEVICE_CAP_MAX_PAYLOAD_SHIFT 0 - -#define REG_DEVICE_CTRL 0x60 -#define DEVICE_CTRL_MAX_PAYLOAD_MASK 0x7 -#define DEVICE_CTRL_MAX_PAYLOAD_SHIFT 5 -#define DEVICE_CTRL_MAX_RREQ_SZ_MASK 0x7 -#define DEVICE_CTRL_MAX_RREQ_SZ_SHIFT 12 - -#define REG_VPD_CAP 0x6C -#define VPD_CAP_ID_MASK 0xff -#define VPD_CAP_ID_SHIFT 0 -#define VPD_CAP_NEXT_PTR_MASK 0xFF -#define VPD_CAP_NEXT_PTR_SHIFT 8 -#define VPD_CAP_VPD_ADDR_MASK 0x7FFF -#define VPD_CAP_VPD_ADDR_SHIFT 16 -#define VPD_CAP_VPD_FLAG 0x80000000 - -#define REG_VPD_DATA 0x70 - -#define REG_SPI_FLASH_CTRL 0x200 -#define SPI_FLASH_CTRL_STS_NON_RDY 0x1 -#define SPI_FLASH_CTRL_STS_WEN 0x2 -#define SPI_FLASH_CTRL_STS_WPEN 0x80 -#define SPI_FLASH_CTRL_DEV_STS_MASK 0xFF -#define SPI_FLASH_CTRL_DEV_STS_SHIFT 0 -#define SPI_FLASH_CTRL_INS_MASK 0x7 -#define SPI_FLASH_CTRL_INS_SHIFT 8 -#define SPI_FLASH_CTRL_START 0x800 -#define SPI_FLASH_CTRL_EN_VPD 0x2000 -#define SPI_FLASH_CTRL_LDSTART 0x8000 -#define SPI_FLASH_CTRL_CS_HI_MASK 0x3 -#define SPI_FLASH_CTRL_CS_HI_SHIFT 16 -#define SPI_FLASH_CTRL_CS_HOLD_MASK 0x3 -#define SPI_FLASH_CTRL_CS_HOLD_SHIFT 18 -#define SPI_FLASH_CTRL_CLK_LO_MASK 0x3 -#define SPI_FLASH_CTRL_CLK_LO_SHIFT 20 -#define SPI_FLASH_CTRL_CLK_HI_MASK 0x3 -#define SPI_FLASH_CTRL_CLK_HI_SHIFT 22 -#define SPI_FLASH_CTRL_CS_SETUP_MASK 0x3 -#define SPI_FLASH_CTRL_CS_SETUP_SHIFT 24 -#define SPI_FLASH_CTRL_EROM_PGSZ_MASK 0x3 -#define SPI_FLASH_CTRL_EROM_PGSZ_SHIFT 26 -#define SPI_FLASH_CTRL_WAIT_READY 0x10000000 - -#define REG_SPI_ADDR 0x204 - -#define REG_SPI_DATA 0x208 - -#define REG_SPI_FLASH_CONFIG 0x20C -#define SPI_FLASH_CONFIG_LD_ADDR_MASK 0xFFFFFF -#define SPI_FLASH_CONFIG_LD_ADDR_SHIFT 0 -#define SPI_FLASH_CONFIG_VPD_ADDR_MASK 0x3 -#define SPI_FLASH_CONFIG_VPD_ADDR_SHIFT 24 -#define SPI_FLASH_CONFIG_LD_EXIST 0x4000000 - - -#define REG_SPI_FLASH_OP_PROGRAM 0x210 -#define REG_SPI_FLASH_OP_SC_ERASE 0x211 -#define REG_SPI_FLASH_OP_CHIP_ERASE 0x212 -#define REG_SPI_FLASH_OP_RDID 0x213 -#define REG_SPI_FLASH_OP_WREN 0x214 -#define REG_SPI_FLASH_OP_RDSR 0x215 -#define REG_SPI_FLASH_OP_WRSR 0x216 -#define REG_SPI_FLASH_OP_READ 0x217 - -#define REG_TWSI_CTRL 0x218 -#define TWSI_CTRL_LD_OFFSET_MASK 0xFF -#define TWSI_CTRL_LD_OFFSET_SHIFT 0 -#define TWSI_CTRL_LD_SLV_ADDR_MASK 0x7 -#define TWSI_CTRL_LD_SLV_ADDR_SHIFT 8 -#define TWSI_CTRL_SW_LDSTART 0x800 -#define TWSI_CTRL_HW_LDSTART 0x1000 -#define TWSI_CTRL_SMB_SLV_ADDR_MASK 0x7F -#define TWSI_CTRL_SMB_SLV_ADDR_SHIFT 15 -#define TWSI_CTRL_LD_EXIST 0x400000 -#define TWSI_CTRL_READ_FREQ_SEL_MASK 0x3 -#define TWSI_CTRL_READ_FREQ_SEL_SHIFT 23 -#define TWSI_CTRL_FREQ_SEL_100K 0 -#define TWSI_CTRL_FREQ_SEL_200K 1 -#define TWSI_CTRL_FREQ_SEL_300K 2 -#define TWSI_CTRL_FREQ_SEL_400K 3 -#define TWSI_CTRL_SMB_SLV_ADDR -#define TWSI_CTRL_WRITE_FREQ_SEL_MASK 0x3 -#define TWSI_CTRL_WRITE_FREQ_SEL_SHIFT 24 - - -#define REG_PCIE_DEV_MISC_CTRL 0x21C -#define PCIE_DEV_MISC_CTRL_EXT_PIPE 0x2 -#define PCIE_DEV_MISC_CTRL_RETRY_BUFDIS 0x1 -#define PCIE_DEV_MISC_CTRL_SPIROM_EXIST 0x4 -#define PCIE_DEV_MISC_CTRL_SERDES_ENDIAN 0x8 -#define PCIE_DEV_MISC_CTRL_SERDES_SEL_DIN 0x10 - -#define REG_PCIE_PHYMISC 0x1000 -#define PCIE_PHYMISC_FORCE_RCV_DET 0x4 - -#define REG_LTSSM_TEST_MODE 0x12FC -#define LTSSM_TEST_MODE_DEF 0xE000 - -/* Selene Master Control Register */ -#define REG_MASTER_CTRL 0x1400 -#define MASTER_CTRL_SOFT_RST 0x1 -#define MASTER_CTRL_MTIMER_EN 0x2 -#define MASTER_CTRL_ITIMER_EN 0x4 -#define MASTER_CTRL_MANUAL_INT 0x8 -#define MASTER_CTRL_ITIMER2_EN 0x20 -#define MASTER_CTRL_INT_RDCLR 0x40 -#define MASTER_CTRL_LED_MODE 0x200 -#define MASTER_CTRL_REV_NUM_SHIFT 16 -#define MASTER_CTRL_REV_NUM_MASK 0xff -#define MASTER_CTRL_DEV_ID_SHIFT 24 -#define MASTER_CTRL_DEV_ID_MASK 0xff - -/* Timer Initial Value Register */ -#define REG_MANUAL_TIMER_INIT 0x1404 - - -/* IRQ ModeratorTimer Initial Value Register */ -#define REG_IRQ_MODU_TIMER_INIT 0x1408 /* w */ -#define REG_IRQ_MODU_TIMER2_INIT 0x140A /* w */ - - -#define REG_GPHY_CTRL 0x140C -#define GPHY_CTRL_EXT_RESET 1 -#define GPHY_CTRL_PIPE_MOD 2 -#define GPHY_CTRL_TEST_MODE_MASK 3 -#define GPHY_CTRL_TEST_MODE_SHIFT 2 -#define GPHY_CTRL_BERT_START 0x10 -#define GPHY_CTRL_GATE_25M_EN 0x20 -#define GPHY_CTRL_LPW_EXIT 0x40 -#define GPHY_CTRL_PHY_IDDQ 0x80 -#define GPHY_CTRL_PHY_IDDQ_DIS 0x100 -#define GPHY_CTRL_PCLK_SEL_DIS 0x200 -#define GPHY_CTRL_HIB_EN 0x400 -#define GPHY_CTRL_HIB_PULSE 0x800 -#define GPHY_CTRL_SEL_ANA_RST 0x1000 -#define GPHY_CTRL_PHY_PLL_ON 0x2000 -#define GPHY_CTRL_PWDOWN_HW 0x4000 -#define GPHY_CTRL_DEFAULT (\ - GPHY_CTRL_PHY_PLL_ON |\ - GPHY_CTRL_SEL_ANA_RST |\ - GPHY_CTRL_HIB_PULSE |\ - GPHY_CTRL_HIB_EN) - -#define GPHY_CTRL_PW_WOL_DIS (\ - GPHY_CTRL_PHY_PLL_ON |\ - GPHY_CTRL_SEL_ANA_RST |\ - GPHY_CTRL_HIB_PULSE |\ - GPHY_CTRL_HIB_EN |\ - GPHY_CTRL_PWDOWN_HW |\ - GPHY_CTRL_PCLK_SEL_DIS |\ - GPHY_CTRL_PHY_IDDQ) - -/* IRQ Anti-Lost Timer Initial Value Register */ -#define REG_CMBDISDMA_TIMER 0x140E - - -/* Block IDLE Status Register */ -#define REG_IDLE_STATUS 0x1410 -#define IDLE_STATUS_RXMAC 1 /* 1: RXMAC state machine is in non-IDLE state. 0: RXMAC is idling */ -#define IDLE_STATUS_TXMAC 2 /* 1: TXMAC state machine is in non-IDLE state. 0: TXMAC is idling */ -#define IDLE_STATUS_RXQ 4 /* 1: RXQ state machine is in non-IDLE state. 0: RXQ is idling */ -#define IDLE_STATUS_TXQ 8 /* 1: TXQ state machine is in non-IDLE state. 0: TXQ is idling */ -#define IDLE_STATUS_DMAR 0x10 /* 1: DMAR state machine is in non-IDLE state. 0: DMAR is idling */ -#define IDLE_STATUS_DMAW 0x20 /* 1: DMAW state machine is in non-IDLE state. 0: DMAW is idling */ -#define IDLE_STATUS_SMB 0x40 /* 1: SMB state machine is in non-IDLE state. 0: SMB is idling */ -#define IDLE_STATUS_CMB 0x80 /* 1: CMB state machine is in non-IDLE state. 0: CMB is idling */ - -/* MDIO Control Register */ -#define REG_MDIO_CTRL 0x1414 -#define MDIO_DATA_MASK 0xffff /* On MDIO write, the 16-bit control data to write to PHY MII management register */ -#define MDIO_DATA_SHIFT 0 /* On MDIO read, the 16-bit status data that was read from the PHY MII management register*/ -#define MDIO_REG_ADDR_MASK 0x1f /* MDIO register address */ -#define MDIO_REG_ADDR_SHIFT 16 -#define MDIO_RW 0x200000 /* 1: read, 0: write */ -#define MDIO_SUP_PREAMBLE 0x400000 /* Suppress preamble */ -#define MDIO_START 0x800000 /* Write 1 to initiate the MDIO master. And this bit is self cleared after one cycle*/ -#define MDIO_CLK_SEL_SHIFT 24 -#define MDIO_CLK_25_4 0 -#define MDIO_CLK_25_6 2 -#define MDIO_CLK_25_8 3 -#define MDIO_CLK_25_10 4 -#define MDIO_CLK_25_14 5 -#define MDIO_CLK_25_20 6 -#define MDIO_CLK_25_28 7 -#define MDIO_BUSY 0x8000000 -#define MDIO_AP_EN 0x10000000 -#define MDIO_WAIT_TIMES 10 - -/* MII PHY Status Register */ -#define REG_PHY_STATUS 0x1418 -#define PHY_STATUS_100M 0x20000 -#define PHY_STATUS_EMI_CA 0x40000 - -/* BIST Control and Status Register0 (for the Packet Memory) */ -#define REG_BIST0_CTRL 0x141c -#define BIST0_NOW 0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */ -/* BIST process and reset to zero when BIST is done */ -#define BIST0_SRAM_FAIL 0x2 /* 1: The SRAM failure is un-repairable because it has address */ -/* decoder failure or more than 1 cell stuck-to-x failure */ -#define BIST0_FUSE_FLAG 0x4 /* 1: Indicating one cell has been fixed */ - -/* BIST Control and Status Register1(for the retry buffer of PCI Express) */ -#define REG_BIST1_CTRL 0x1420 -#define BIST1_NOW 0x1 /* 1: To trigger BIST0 logic. This bit stays high during the */ -/* BIST process and reset to zero when BIST is done */ -#define BIST1_SRAM_FAIL 0x2 /* 1: The SRAM failure is un-repairable because it has address */ -/* decoder failure or more than 1 cell stuck-to-x failure.*/ -#define BIST1_FUSE_FLAG 0x4 - -/* SerDes Lock Detect Control and Status Register */ -#define REG_SERDES_LOCK 0x1424 -#define SERDES_LOCK_DETECT 1 /* 1: SerDes lock detected . This signal comes from Analog SerDes */ -#define SERDES_LOCK_DETECT_EN 2 /* 1: Enable SerDes Lock detect function */ - -/* MAC Control Register */ -#define REG_MAC_CTRL 0x1480 -#define MAC_CTRL_TX_EN 1 /* 1: Transmit Enable */ -#define MAC_CTRL_RX_EN 2 /* 1: Receive Enable */ -#define MAC_CTRL_TX_FLOW 4 /* 1: Transmit Flow Control Enable */ -#define MAC_CTRL_RX_FLOW 8 /* 1: Receive Flow Control Enable */ -#define MAC_CTRL_LOOPBACK 0x10 /* 1: Loop back at G/MII Interface */ -#define MAC_CTRL_DUPLX 0x20 /* 1: Full-duplex mode 0: Half-duplex mode */ -#define MAC_CTRL_ADD_CRC 0x40 /* 1: Instruct MAC to attach CRC on all egress Ethernet frames */ -#define MAC_CTRL_PAD 0x80 /* 1: Instruct MAC to pad short frames to 60-bytes, and then attach CRC. This bit has higher priority over CRC_EN */ -#define MAC_CTRL_LENCHK 0x100 /* 1: Instruct MAC to check if length field matches the real packet length */ -#define MAC_CTRL_HUGE_EN 0x200 /* 1: receive Jumbo frame enable */ -#define MAC_CTRL_PRMLEN_SHIFT 10 /* Preamble length */ -#define MAC_CTRL_PRMLEN_MASK 0xf -#define MAC_CTRL_RMV_VLAN 0x4000 /* 1: to remove VLAN Tag automatically from all receive packets */ -#define MAC_CTRL_PROMIS_EN 0x8000 /* 1: Promiscuous Mode Enable */ -#define MAC_CTRL_TX_PAUSE 0x10000 /* 1: transmit test pause */ -#define MAC_CTRL_SCNT 0x20000 /* 1: shortcut slot time counter */ -#define MAC_CTRL_SRST_TX 0x40000 /* 1: synchronized reset Transmit MAC module */ -#define MAC_CTRL_TX_SIMURST 0x80000 /* 1: transmit simulation reset */ -#define MAC_CTRL_SPEED_SHIFT 20 /* 10: gigabit 01:10M/100M */ -#define MAC_CTRL_SPEED_MASK 0x300000 -#define MAC_CTRL_SPEED_1000 2 -#define MAC_CTRL_SPEED_10_100 1 -#define MAC_CTRL_DBG_TX_BKPRESURE 0x400000 /* 1: transmit maximum backoff (half-duplex test bit) */ -#define MAC_CTRL_TX_HUGE 0x800000 /* 1: transmit huge enable */ -#define MAC_CTRL_RX_CHKSUM_EN 0x1000000 /* 1: RX checksum enable */ -#define MAC_CTRL_MC_ALL_EN 0x2000000 /* 1: upload all multicast frame without error to system */ -#define MAC_CTRL_BC_EN 0x4000000 /* 1: upload all broadcast frame without error to system */ -#define MAC_CTRL_DBG 0x8000000 /* 1: upload all received frame to system (Debug Mode) */ - -/* MAC IPG/IFG Control Register */ -#define REG_MAC_IPG_IFG 0x1484 -#define MAC_IPG_IFG_IPGT_SHIFT 0 /* Desired back to back inter-packet gap. The default is 96-bit time */ -#define MAC_IPG_IFG_IPGT_MASK 0x7f -#define MAC_IPG_IFG_MIFG_SHIFT 8 /* Minimum number of IFG to enforce in between RX frames */ -#define MAC_IPG_IFG_MIFG_MASK 0xff /* Frame gap below such IFP is dropped */ -#define MAC_IPG_IFG_IPGR1_SHIFT 16 /* 64bit Carrier-Sense window */ -#define MAC_IPG_IFG_IPGR1_MASK 0x7f -#define MAC_IPG_IFG_IPGR2_SHIFT 24 /* 96-bit IPG window */ -#define MAC_IPG_IFG_IPGR2_MASK 0x7f - -/* MAC STATION ADDRESS */ -#define REG_MAC_STA_ADDR 0x1488 - -/* Hash table for multicast address */ -#define REG_RX_HASH_TABLE 0x1490 - - -/* MAC Half-Duplex Control Register */ -#define REG_MAC_HALF_DUPLX_CTRL 0x1498 -#define MAC_HALF_DUPLX_CTRL_LCOL_SHIFT 0 /* Collision Window */ -#define MAC_HALF_DUPLX_CTRL_LCOL_MASK 0x3ff -#define MAC_HALF_DUPLX_CTRL_RETRY_SHIFT 12 /* Retransmission maximum, afterwards the packet will be discarded */ -#define MAC_HALF_DUPLX_CTRL_RETRY_MASK 0xf -#define MAC_HALF_DUPLX_CTRL_EXC_DEF_EN 0x10000 /* 1: Allow the transmission of a packet which has been excessively deferred */ -#define MAC_HALF_DUPLX_CTRL_NO_BACK_C 0x20000 /* 1: No back-off on collision, immediately start the retransmission */ -#define MAC_HALF_DUPLX_CTRL_NO_BACK_P 0x40000 /* 1: No back-off on backpressure, immediately start the transmission after back pressure */ -#define MAC_HALF_DUPLX_CTRL_ABEBE 0x80000 /* 1: Alternative Binary Exponential Back-off Enabled */ -#define MAC_HALF_DUPLX_CTRL_ABEBT_SHIFT 20 /* Maximum binary exponential number */ -#define MAC_HALF_DUPLX_CTRL_ABEBT_MASK 0xf -#define MAC_HALF_DUPLX_CTRL_JAMIPG_SHIFT 24 /* IPG to start JAM for collision based flow control in half-duplex */ -#define MAC_HALF_DUPLX_CTRL_JAMIPG_MASK 0xf /* mode. In unit of 8-bit time */ - -/* Maximum Frame Length Control Register */ -#define REG_MTU 0x149c - -/* Wake-On-Lan control register */ -#define REG_WOL_CTRL 0x14a0 -#define WOL_PATTERN_EN 0x00000001 -#define WOL_PATTERN_PME_EN 0x00000002 -#define WOL_MAGIC_EN 0x00000004 -#define WOL_MAGIC_PME_EN 0x00000008 -#define WOL_LINK_CHG_EN 0x00000010 -#define WOL_LINK_CHG_PME_EN 0x00000020 -#define WOL_PATTERN_ST 0x00000100 -#define WOL_MAGIC_ST 0x00000200 -#define WOL_LINKCHG_ST 0x00000400 -#define WOL_CLK_SWITCH_EN 0x00008000 -#define WOL_PT0_EN 0x00010000 -#define WOL_PT1_EN 0x00020000 -#define WOL_PT2_EN 0x00040000 -#define WOL_PT3_EN 0x00080000 -#define WOL_PT4_EN 0x00100000 -#define WOL_PT5_EN 0x00200000 -#define WOL_PT6_EN 0x00400000 -/* WOL Length ( 2 DWORD ) */ -#define REG_WOL_PATTERN_LEN 0x14a4 -#define WOL_PT_LEN_MASK 0x7f -#define WOL_PT0_LEN_SHIFT 0 -#define WOL_PT1_LEN_SHIFT 8 -#define WOL_PT2_LEN_SHIFT 16 -#define WOL_PT3_LEN_SHIFT 24 -#define WOL_PT4_LEN_SHIFT 0 -#define WOL_PT5_LEN_SHIFT 8 -#define WOL_PT6_LEN_SHIFT 16 - -/* Internal SRAM Partition Register */ -#define REG_SRAM_TRD_ADDR 0x1518 -#define REG_SRAM_TRD_LEN 0x151C -#define REG_SRAM_RXF_ADDR 0x1520 -#define REG_SRAM_RXF_LEN 0x1524 -#define REG_SRAM_TXF_ADDR 0x1528 -#define REG_SRAM_TXF_LEN 0x152C -#define REG_SRAM_TCPH_ADDR 0x1530 -#define REG_SRAM_PKTH_ADDR 0x1532 - -/* Load Ptr Register */ -#define REG_LOAD_PTR 0x1534 /* Software sets this bit after the initialization of the head and tail */ - -/* - * addresses of all descriptors, as well as the following descriptor - * control register, which triggers each function block to load the head - * pointer to prepare for the operation. This bit is then self-cleared - * after one cycle. - */ - -/* Descriptor Control register */ -#define REG_RXF3_BASE_ADDR_HI 0x153C -#define REG_DESC_BASE_ADDR_HI 0x1540 -#define REG_RXF0_BASE_ADDR_HI 0x1540 /* share with DESC BASE ADDR HI */ -#define REG_HOST_RXF0_PAGE0_LO 0x1544 -#define REG_HOST_RXF0_PAGE1_LO 0x1548 -#define REG_TPD_BASE_ADDR_LO 0x154C -#define REG_RXF1_BASE_ADDR_HI 0x1550 -#define REG_RXF2_BASE_ADDR_HI 0x1554 -#define REG_HOST_RXFPAGE_SIZE 0x1558 -#define REG_TPD_RING_SIZE 0x155C -/* RSS about */ -#define REG_RSS_KEY0 0x14B0 -#define REG_RSS_KEY1 0x14B4 -#define REG_RSS_KEY2 0x14B8 -#define REG_RSS_KEY3 0x14BC -#define REG_RSS_KEY4 0x14C0 -#define REG_RSS_KEY5 0x14C4 -#define REG_RSS_KEY6 0x14C8 -#define REG_RSS_KEY7 0x14CC -#define REG_RSS_KEY8 0x14D0 -#define REG_RSS_KEY9 0x14D4 -#define REG_IDT_TABLE4 0x14E0 -#define REG_IDT_TABLE5 0x14E4 -#define REG_IDT_TABLE6 0x14E8 -#define REG_IDT_TABLE7 0x14EC -#define REG_IDT_TABLE0 0x1560 -#define REG_IDT_TABLE1 0x1564 -#define REG_IDT_TABLE2 0x1568 -#define REG_IDT_TABLE3 0x156C -#define REG_IDT_TABLE REG_IDT_TABLE0 -#define REG_RSS_HASH_VALUE 0x1570 -#define REG_RSS_HASH_FLAG 0x1574 -#define REG_BASE_CPU_NUMBER 0x157C - - -/* TXQ Control Register */ -#define REG_TXQ_CTRL 0x1580 -#define TXQ_CTRL_NUM_TPD_BURST_MASK 0xF -#define TXQ_CTRL_NUM_TPD_BURST_SHIFT 0 -#define TXQ_CTRL_EN 0x20 /* 1: Enable TXQ */ -#define TXQ_CTRL_ENH_MODE 0x40 /* Performance enhancement mode, in which up to two back-to-back DMA read commands might be dispatched. */ -#define TXQ_CTRL_TXF_BURST_NUM_SHIFT 16 /* Number of data byte to read in a cache-aligned burst. Each SRAM entry is 8-byte in length. */ -#define TXQ_CTRL_TXF_BURST_NUM_MASK 0xffff - -/* Jumbo packet Threshold for task offload */ -#define REG_TX_EARLY_TH 0x1584 /* Jumbo frame threshold in QWORD unit. Packet greater than */ -/* JUMBO_TASK_OFFLOAD_THRESHOLD will not be task offloaded. */ -#define TX_TX_EARLY_TH_MASK 0x7ff -#define TX_TX_EARLY_TH_SHIFT 0 - - -/* RXQ Control Register */ -#define REG_RXQ_CTRL 0x15A0 -#define RXQ_CTRL_PBA_ALIGN_32 0 /* rx-packet alignment */ -#define RXQ_CTRL_PBA_ALIGN_64 1 -#define RXQ_CTRL_PBA_ALIGN_128 2 -#define RXQ_CTRL_PBA_ALIGN_256 3 -#define RXQ_CTRL_Q1_EN 0x10 -#define RXQ_CTRL_Q2_EN 0x20 -#define RXQ_CTRL_Q3_EN 0x40 -#define RXQ_CTRL_IPV6_XSUM_VERIFY_EN 0x80 -#define RXQ_CTRL_HASH_TLEN_SHIFT 8 -#define RXQ_CTRL_HASH_TLEN_MASK 0xFF -#define RXQ_CTRL_HASH_TYPE_IPV4 0x10000 -#define RXQ_CTRL_HASH_TYPE_IPV4_TCP 0x20000 -#define RXQ_CTRL_HASH_TYPE_IPV6 0x40000 -#define RXQ_CTRL_HASH_TYPE_IPV6_TCP 0x80000 -#define RXQ_CTRL_RSS_MODE_DISABLE 0 -#define RXQ_CTRL_RSS_MODE_SQSINT 0x4000000 -#define RXQ_CTRL_RSS_MODE_MQUESINT 0x8000000 -#define RXQ_CTRL_RSS_MODE_MQUEMINT 0xC000000 -#define RXQ_CTRL_NIP_QUEUE_SEL_TBL 0x10000000 -#define RXQ_CTRL_HASH_ENABLE 0x20000000 -#define RXQ_CTRL_CUT_THRU_EN 0x40000000 -#define RXQ_CTRL_EN 0x80000000 - -/* Rx jumbo packet threshold and rrd retirement timer */ -#define REG_RXQ_JMBOSZ_RRDTIM 0x15A4 -/* - * Jumbo packet threshold for non-VLAN packet, in QWORD (64-bit) unit. - * When the packet length greater than or equal to this value, RXQ - * shall start cut-through forwarding of the received packet. - */ -#define RXQ_JMBOSZ_TH_MASK 0x7ff -#define RXQ_JMBOSZ_TH_SHIFT 0 /* RRD retirement timer. Decrement by 1 after every 512ns passes*/ -#define RXQ_JMBO_LKAH_MASK 0xf -#define RXQ_JMBO_LKAH_SHIFT 11 - -/* RXF flow control register */ -#define REG_RXQ_RXF_PAUSE_THRESH 0x15A8 -#define RXQ_RXF_PAUSE_TH_HI_SHIFT 0 -#define RXQ_RXF_PAUSE_TH_HI_MASK 0xfff -#define RXQ_RXF_PAUSE_TH_LO_SHIFT 16 -#define RXQ_RXF_PAUSE_TH_LO_MASK 0xfff - - -/* DMA Engine Control Register */ -#define REG_DMA_CTRL 0x15C0 -#define DMA_CTRL_DMAR_IN_ORDER 0x1 -#define DMA_CTRL_DMAR_ENH_ORDER 0x2 -#define DMA_CTRL_DMAR_OUT_ORDER 0x4 -#define DMA_CTRL_RCB_VALUE 0x8 -#define DMA_CTRL_DMAR_BURST_LEN_SHIFT 4 -#define DMA_CTRL_DMAR_BURST_LEN_MASK 7 -#define DMA_CTRL_DMAW_BURST_LEN_SHIFT 7 -#define DMA_CTRL_DMAW_BURST_LEN_MASK 7 -#define DMA_CTRL_DMAR_REQ_PRI 0x400 -#define DMA_CTRL_DMAR_DLY_CNT_MASK 0x1F -#define DMA_CTRL_DMAR_DLY_CNT_SHIFT 11 -#define DMA_CTRL_DMAW_DLY_CNT_MASK 0xF -#define DMA_CTRL_DMAW_DLY_CNT_SHIFT 16 -#define DMA_CTRL_TXCMB_EN 0x100000 -#define DMA_CTRL_RXCMB_EN 0x200000 - - -/* CMB/SMB Control Register */ -#define REG_SMB_STAT_TIMER 0x15C4 -#define REG_TRIG_RRD_THRESH 0x15CA -#define REG_TRIG_TPD_THRESH 0x15C8 -#define REG_TRIG_TXTIMER 0x15CC -#define REG_TRIG_RXTIMER 0x15CE - -/* HOST RXF Page 1,2,3 address */ -#define REG_HOST_RXF1_PAGE0_LO 0x15D0 -#define REG_HOST_RXF1_PAGE1_LO 0x15D4 -#define REG_HOST_RXF2_PAGE0_LO 0x15D8 -#define REG_HOST_RXF2_PAGE1_LO 0x15DC -#define REG_HOST_RXF3_PAGE0_LO 0x15E0 -#define REG_HOST_RXF3_PAGE1_LO 0x15E4 - -/* Mail box */ -#define REG_MB_RXF1_RADDR 0x15B4 -#define REG_MB_RXF2_RADDR 0x15B8 -#define REG_MB_RXF3_RADDR 0x15BC -#define REG_MB_TPD_PROD_IDX 0x15F0 - -/* RXF-Page 0-3 PageNo & Valid bit */ -#define REG_HOST_RXF0_PAGE0_VLD 0x15F4 -#define HOST_RXF_VALID 1 -#define HOST_RXF_PAGENO_SHIFT 1 -#define HOST_RXF_PAGENO_MASK 0x7F -#define REG_HOST_RXF0_PAGE1_VLD 0x15F5 -#define REG_HOST_RXF1_PAGE0_VLD 0x15F6 -#define REG_HOST_RXF1_PAGE1_VLD 0x15F7 -#define REG_HOST_RXF2_PAGE0_VLD 0x15F8 -#define REG_HOST_RXF2_PAGE1_VLD 0x15F9 -#define REG_HOST_RXF3_PAGE0_VLD 0x15FA -#define REG_HOST_RXF3_PAGE1_VLD 0x15FB - -/* Interrupt Status Register */ -#define REG_ISR 0x1600 -#define ISR_SMB 1 -#define ISR_TIMER 2 /* Interrupt when Timer is counted down to zero */ -/* - * Software manual interrupt, for debug. Set when SW_MAN_INT_EN is set - * in Table 51 Selene Master Control Register (Offset 0x1400). - */ -#define ISR_MANUAL 4 -#define ISR_HW_RXF_OV 8 /* RXF overflow interrupt */ -#define ISR_HOST_RXF0_OV 0x10 -#define ISR_HOST_RXF1_OV 0x20 -#define ISR_HOST_RXF2_OV 0x40 -#define ISR_HOST_RXF3_OV 0x80 -#define ISR_TXF_UN 0x100 -#define ISR_RX0_PAGE_FULL 0x200 -#define ISR_DMAR_TO_RST 0x400 -#define ISR_DMAW_TO_RST 0x800 -#define ISR_GPHY 0x1000 -#define ISR_TX_CREDIT 0x2000 -#define ISR_GPHY_LPW 0x4000 /* GPHY low power state interrupt */ -#define ISR_RX_PKT 0x10000 /* One packet received, triggered by RFD */ -#define ISR_TX_PKT 0x20000 /* One packet transmitted, triggered by TPD */ -#define ISR_TX_DMA 0x40000 -#define ISR_RX_PKT_1 0x80000 -#define ISR_RX_PKT_2 0x100000 -#define ISR_RX_PKT_3 0x200000 -#define ISR_MAC_RX 0x400000 -#define ISR_MAC_TX 0x800000 -#define ISR_UR_DETECTED 0x1000000 -#define ISR_FERR_DETECTED 0x2000000 -#define ISR_NFERR_DETECTED 0x4000000 -#define ISR_CERR_DETECTED 0x8000000 -#define ISR_PHY_LINKDOWN 0x10000000 -#define ISR_DIS_INT 0x80000000 - - -/* Interrupt Mask Register */ -#define REG_IMR 0x1604 - - -#define IMR_NORMAL_MASK (\ - ISR_SMB |\ - ISR_TXF_UN |\ - ISR_HW_RXF_OV |\ - ISR_HOST_RXF0_OV|\ - ISR_MANUAL |\ - ISR_GPHY |\ - ISR_GPHY_LPW |\ - ISR_DMAR_TO_RST |\ - ISR_DMAW_TO_RST |\ - ISR_PHY_LINKDOWN|\ - ISR_RX_PKT |\ - ISR_TX_PKT) - -#define ISR_TX_EVENT (ISR_TXF_UN | ISR_TX_PKT) -#define ISR_RX_EVENT (ISR_HOST_RXF0_OV | ISR_HW_RXF_OV | ISR_RX_PKT) - -#define REG_MAC_RX_STATUS_BIN 0x1700 -#define REG_MAC_RX_STATUS_END 0x175c -#define REG_MAC_TX_STATUS_BIN 0x1760 -#define REG_MAC_TX_STATUS_END 0x17c0 - -/* Hardware Offset Register */ -#define REG_HOST_RXF0_PAGEOFF 0x1800 -#define REG_TPD_CONS_IDX 0x1804 -#define REG_HOST_RXF1_PAGEOFF 0x1808 -#define REG_HOST_RXF2_PAGEOFF 0x180C -#define REG_HOST_RXF3_PAGEOFF 0x1810 - -/* RXF-Page 0-3 Offset DMA Address */ -#define REG_HOST_RXF0_MB0_LO 0x1820 -#define REG_HOST_RXF0_MB1_LO 0x1824 -#define REG_HOST_RXF1_MB0_LO 0x1828 -#define REG_HOST_RXF1_MB1_LO 0x182C -#define REG_HOST_RXF2_MB0_LO 0x1830 -#define REG_HOST_RXF2_MB1_LO 0x1834 -#define REG_HOST_RXF3_MB0_LO 0x1838 -#define REG_HOST_RXF3_MB1_LO 0x183C - -/* Tpd CMB DMA Address */ -#define REG_HOST_TX_CMB_LO 0x1840 -#define REG_HOST_SMB_ADDR_LO 0x1844 - -/* DEBUG ADDR */ -#define REG_DEBUG_DATA0 0x1900 -#define REG_DEBUG_DATA1 0x1904 - -/***************************** MII definition ***************************************/ -/* PHY Common Register */ -#define MII_AT001_PSCR 0x10 -#define MII_AT001_PSSR 0x11 -#define MII_INT_CTRL 0x12 -#define MII_INT_STATUS 0x13 -#define MII_SMARTSPEED 0x14 -#define MII_LBRERROR 0x18 -#define MII_RESV2 0x1a - -#define MII_DBG_ADDR 0x1D -#define MII_DBG_DATA 0x1E - -/* Autoneg Advertisement Register */ -#define MII_AR_DEFAULT_CAP_MASK 0 - -/* 1000BASE-T Control Register */ -#define MII_AT001_CR_1000T_SPEED_MASK \ - (ADVERTISE_1000FULL | ADVERTISE_1000HALF) -#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK MII_AT001_CR_1000T_SPEED_MASK - -/* AT001 PHY Specific Control Register */ -#define MII_AT001_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */ -#define MII_AT001_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ -#define MII_AT001_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */ -#define MII_AT001_PSCR_MAC_POWERDOWN 0x0008 -#define MII_AT001_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low, - * 0=CLK125 toggling - */ -#define MII_AT001_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ -/* Manual MDI configuration */ -#define MII_AT001_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ -#define MII_AT001_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover, - * 100BASE-TX/10BASE-T: - * MDI Mode - */ -#define MII_AT001_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled - * all speeds. - */ -#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE 0x0080 -/* 1=Enable Extended 10BASE-T distance - * (Lower 10BASE-T RX Threshold) - * 0=Normal 10BASE-T RX Threshold */ -#define MII_AT001_PSCR_MII_5BIT_ENABLE 0x0100 -/* 1=5-Bit interface in 100BASE-TX - * 0=MII interface in 100BASE-TX */ -#define MII_AT001_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */ -#define MII_AT001_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */ -#define MII_AT001_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ -#define MII_AT001_PSCR_POLARITY_REVERSAL_SHIFT 1 -#define MII_AT001_PSCR_AUTO_X_MODE_SHIFT 5 -#define MII_AT001_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7 -/* AT001 PHY Specific Status Register */ -#define MII_AT001_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ -#define MII_AT001_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ -#define MII_AT001_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ -#define MII_AT001_PSSR_10MBS 0x0000 /* 00=10Mbs */ -#define MII_AT001_PSSR_100MBS 0x4000 /* 01=100Mbs */ -#define MII_AT001_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ - -#endif /*_ATHL1E_HW_H_*/ diff --git a/addons/atl1e/src/4.4.180/atl1e_main.c b/addons/atl1e/src/4.4.180/atl1e_main.c deleted file mode 100644 index 59a03a19..00000000 --- a/addons/atl1e/src/4.4.180/atl1e_main.c +++ /dev/null @@ -1,2578 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include "atl1e.h" - -#define DRV_VERSION "1.0.0.7-NAPI" - -char atl1e_driver_name[] = "ATL1E"; -char atl1e_driver_version[] = DRV_VERSION; -#define PCI_DEVICE_ID_ATTANSIC_L1E 0x1026 -/* - * atl1e_pci_tbl - PCI Device ID Table - * - * Wildcard entries (PCI_ANY_ID) should come last - * Last entry must be all 0s - * - * { Vendor ID, Device ID, SubVendor ID, SubDevice ID, - * Class, Class Mask, private data (not used) } - */ -static const struct pci_device_id atl1e_pci_tbl[] = { - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1E)}, - {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, 0x1066)}, - /* required last entry */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, atl1e_pci_tbl); - -MODULE_AUTHOR("Atheros Corporation, , Jie Yang "); -MODULE_DESCRIPTION("Atheros 1000M Ethernet Network Driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter); - -static const u16 -atl1e_rx_page_vld_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] = -{ - {REG_HOST_RXF0_PAGE0_VLD, REG_HOST_RXF0_PAGE1_VLD}, - {REG_HOST_RXF1_PAGE0_VLD, REG_HOST_RXF1_PAGE1_VLD}, - {REG_HOST_RXF2_PAGE0_VLD, REG_HOST_RXF2_PAGE1_VLD}, - {REG_HOST_RXF3_PAGE0_VLD, REG_HOST_RXF3_PAGE1_VLD} -}; - -static const u16 atl1e_rx_page_hi_addr_regs[AT_MAX_RECEIVE_QUEUE] = -{ - REG_RXF0_BASE_ADDR_HI, - REG_RXF1_BASE_ADDR_HI, - REG_RXF2_BASE_ADDR_HI, - REG_RXF3_BASE_ADDR_HI -}; - -static const u16 -atl1e_rx_page_lo_addr_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] = -{ - {REG_HOST_RXF0_PAGE0_LO, REG_HOST_RXF0_PAGE1_LO}, - {REG_HOST_RXF1_PAGE0_LO, REG_HOST_RXF1_PAGE1_LO}, - {REG_HOST_RXF2_PAGE0_LO, REG_HOST_RXF2_PAGE1_LO}, - {REG_HOST_RXF3_PAGE0_LO, REG_HOST_RXF3_PAGE1_LO} -}; - -static const u16 -atl1e_rx_page_write_offset_regs[AT_MAX_RECEIVE_QUEUE][AT_PAGE_NUM_PER_QUEUE] = -{ - {REG_HOST_RXF0_MB0_LO, REG_HOST_RXF0_MB1_LO}, - {REG_HOST_RXF1_MB0_LO, REG_HOST_RXF1_MB1_LO}, - {REG_HOST_RXF2_MB0_LO, REG_HOST_RXF2_MB1_LO}, - {REG_HOST_RXF3_MB0_LO, REG_HOST_RXF3_MB1_LO} -}; - -static const u16 atl1e_pay_load_size[] = { - 128, 256, 512, 1024, 2048, 4096, -}; - -/** - * atl1e_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - */ -static inline void atl1e_irq_enable(struct atl1e_adapter *adapter) -{ - if (likely(atomic_dec_and_test(&adapter->irq_sem))) { - AT_WRITE_REG(&adapter->hw, REG_ISR, 0); - AT_WRITE_REG(&adapter->hw, REG_IMR, IMR_NORMAL_MASK); - AT_WRITE_FLUSH(&adapter->hw); - } -} - -/** - * atl1e_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - */ -static inline void atl1e_irq_disable(struct atl1e_adapter *adapter) -{ - atomic_inc(&adapter->irq_sem); - AT_WRITE_REG(&adapter->hw, REG_IMR, 0); - AT_WRITE_FLUSH(&adapter->hw); - synchronize_irq(adapter->pdev->irq); -} - -/** - * atl1e_irq_reset - reset interrupt confiure on the NIC - * @adapter: board private structure - */ -static inline void atl1e_irq_reset(struct atl1e_adapter *adapter) -{ - atomic_set(&adapter->irq_sem, 0); - AT_WRITE_REG(&adapter->hw, REG_ISR, 0); - AT_WRITE_REG(&adapter->hw, REG_IMR, 0); - AT_WRITE_FLUSH(&adapter->hw); -} - -/** - * atl1e_phy_config - Timer Call-back - * @data: pointer to netdev cast into an unsigned long - */ -static void atl1e_phy_config(unsigned long data) -{ - struct atl1e_adapter *adapter = (struct atl1e_adapter *) data; - struct atl1e_hw *hw = &adapter->hw; - unsigned long flags; - - spin_lock_irqsave(&adapter->mdio_lock, flags); - atl1e_restart_autoneg(hw); - spin_unlock_irqrestore(&adapter->mdio_lock, flags); -} - -void atl1e_reinit_locked(struct atl1e_adapter *adapter) -{ - - WARN_ON(in_interrupt()); - while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) - msleep(1); - atl1e_down(adapter); - atl1e_up(adapter); - clear_bit(__AT_RESETTING, &adapter->flags); -} - -static void atl1e_reset_task(struct work_struct *work) -{ - struct atl1e_adapter *adapter; - adapter = container_of(work, struct atl1e_adapter, reset_task); - - atl1e_reinit_locked(adapter); -} - -static int atl1e_check_link(struct atl1e_adapter *adapter) -{ - struct atl1e_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - int err = 0; - u16 speed, duplex, phy_data; - - /* MII_BMSR must read twice */ - atl1e_read_phy_reg(hw, MII_BMSR, &phy_data); - atl1e_read_phy_reg(hw, MII_BMSR, &phy_data); - if ((phy_data & BMSR_LSTATUS) == 0) { - /* link down */ - if (netif_carrier_ok(netdev)) { /* old link state: Up */ - u32 value; - /* disable rx */ - value = AT_READ_REG(hw, REG_MAC_CTRL); - value &= ~MAC_CTRL_RX_EN; - AT_WRITE_REG(hw, REG_MAC_CTRL, value); - adapter->link_speed = SPEED_0; - netif_carrier_off(netdev); - netif_stop_queue(netdev); - } - } else { - /* Link Up */ - err = atl1e_get_speed_and_duplex(hw, &speed, &duplex); - if (unlikely(err)) - return err; - - /* link result is our setting */ - if (adapter->link_speed != speed || - adapter->link_duplex != duplex) { - adapter->link_speed = speed; - adapter->link_duplex = duplex; - atl1e_setup_mac_ctrl(adapter); - netdev_info(netdev, - "NIC Link is Up <%d Mbps %s Duplex>\n", - adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? - "Full" : "Half"); - } - - if (!netif_carrier_ok(netdev)) { - /* Link down -> Up */ - netif_carrier_on(netdev); - netif_wake_queue(netdev); - } - } - return 0; -} - -/** - * atl1e_link_chg_task - deal with link change event Out of interrupt context - * @netdev: network interface device structure - */ -static void atl1e_link_chg_task(struct work_struct *work) -{ - struct atl1e_adapter *adapter; - unsigned long flags; - - adapter = container_of(work, struct atl1e_adapter, link_chg_task); - spin_lock_irqsave(&adapter->mdio_lock, flags); - atl1e_check_link(adapter); - spin_unlock_irqrestore(&adapter->mdio_lock, flags); -} - -static void atl1e_link_chg_event(struct atl1e_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - u16 phy_data = 0; - u16 link_up = 0; - - spin_lock(&adapter->mdio_lock); - atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); - atl1e_read_phy_reg(&adapter->hw, MII_BMSR, &phy_data); - spin_unlock(&adapter->mdio_lock); - link_up = phy_data & BMSR_LSTATUS; - /* notify upper layer link down ASAP */ - if (!link_up) { - if (netif_carrier_ok(netdev)) { - /* old link state: Up */ - netdev_info(netdev, "NIC Link is Down\n"); - adapter->link_speed = SPEED_0; - netif_stop_queue(netdev); - } - } - schedule_work(&adapter->link_chg_task); -} - -static void atl1e_del_timer(struct atl1e_adapter *adapter) -{ - del_timer_sync(&adapter->phy_config_timer); -} - -static void atl1e_cancel_work(struct atl1e_adapter *adapter) -{ - cancel_work_sync(&adapter->reset_task); - cancel_work_sync(&adapter->link_chg_task); -} - -/** - * atl1e_tx_timeout - Respond to a Tx Hang - * @netdev: network interface device structure - */ -static void atl1e_tx_timeout(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - /* Do the reset outside of interrupt context */ - schedule_work(&adapter->reset_task); -} - -/** - * atl1e_set_multi - Multicast and Promiscuous mode set - * @netdev: network interface device structure - * - * The set_multi entry point is called whenever the multicast address - * list or the network interface flags are updated. This routine is - * responsible for configuring the hardware for proper multicast, - * promiscuous mode, and all-multi behavior. - */ -static void atl1e_set_multi(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - struct netdev_hw_addr *ha; - u32 mac_ctrl_data = 0; - u32 hash_value; - - /* Check for Promiscuous and All Multicast modes */ - mac_ctrl_data = AT_READ_REG(hw, REG_MAC_CTRL); - - if (netdev->flags & IFF_PROMISC) { - mac_ctrl_data |= MAC_CTRL_PROMIS_EN; - } else if (netdev->flags & IFF_ALLMULTI) { - mac_ctrl_data |= MAC_CTRL_MC_ALL_EN; - mac_ctrl_data &= ~MAC_CTRL_PROMIS_EN; - } else { - mac_ctrl_data &= ~(MAC_CTRL_PROMIS_EN | MAC_CTRL_MC_ALL_EN); - } - - AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); - - /* clear the old settings from the multicast hash table */ - AT_WRITE_REG(hw, REG_RX_HASH_TABLE, 0); - AT_WRITE_REG_ARRAY(hw, REG_RX_HASH_TABLE, 1, 0); - - /* comoute mc addresses' hash value ,and put it into hash table */ - netdev_for_each_mc_addr(ha, netdev) { - hash_value = atl1e_hash_mc_addr(hw, ha->addr); - atl1e_hash_set(hw, hash_value); - } -} - -static void __atl1e_rx_mode(netdev_features_t features, u32 *mac_ctrl_data) -{ - - if (features & NETIF_F_RXALL) { - /* enable RX of ALL frames */ - *mac_ctrl_data |= MAC_CTRL_DBG; - } else { - /* disable RX of ALL frames */ - *mac_ctrl_data &= ~MAC_CTRL_DBG; - } -} - -static void atl1e_rx_mode(struct net_device *netdev, - netdev_features_t features) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - u32 mac_ctrl_data = 0; - - netdev_dbg(adapter->netdev, "%s\n", __func__); - - atl1e_irq_disable(adapter); - mac_ctrl_data = AT_READ_REG(&adapter->hw, REG_MAC_CTRL); - __atl1e_rx_mode(features, &mac_ctrl_data); - AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data); - atl1e_irq_enable(adapter); -} - - -static void __atl1e_vlan_mode(netdev_features_t features, u32 *mac_ctrl_data) -{ - if (features & NETIF_F_HW_VLAN_CTAG_RX) { - /* enable VLAN tag insert/strip */ - *mac_ctrl_data |= MAC_CTRL_RMV_VLAN; - } else { - /* disable VLAN tag insert/strip */ - *mac_ctrl_data &= ~MAC_CTRL_RMV_VLAN; - } -} - -static void atl1e_vlan_mode(struct net_device *netdev, - netdev_features_t features) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - u32 mac_ctrl_data = 0; - - netdev_dbg(adapter->netdev, "%s\n", __func__); - - atl1e_irq_disable(adapter); - mac_ctrl_data = AT_READ_REG(&adapter->hw, REG_MAC_CTRL); - __atl1e_vlan_mode(features, &mac_ctrl_data); - AT_WRITE_REG(&adapter->hw, REG_MAC_CTRL, mac_ctrl_data); - atl1e_irq_enable(adapter); -} - -static void atl1e_restore_vlan(struct atl1e_adapter *adapter) -{ - netdev_dbg(adapter->netdev, "%s\n", __func__); - atl1e_vlan_mode(adapter->netdev, adapter->netdev->features); -} - -/** - * atl1e_set_mac - Change the Ethernet Address of the NIC - * @netdev: network interface device structure - * @p: pointer to an address structure - * - * Returns 0 on success, negative on failure - */ -static int atl1e_set_mac_addr(struct net_device *netdev, void *p) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - if (netif_running(netdev)) - return -EBUSY; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - memcpy(adapter->hw.mac_addr, addr->sa_data, netdev->addr_len); - - atl1e_hw_set_mac_addr(&adapter->hw); - - return 0; -} - -static netdev_features_t atl1e_fix_features(struct net_device *netdev, - netdev_features_t 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_CTAG_RX) - features |= NETIF_F_HW_VLAN_CTAG_TX; - else - features &= ~NETIF_F_HW_VLAN_CTAG_TX; - - return features; -} - -static int atl1e_set_features(struct net_device *netdev, - netdev_features_t features) -{ - netdev_features_t changed = netdev->features ^ features; - - if (changed & NETIF_F_HW_VLAN_CTAG_RX) - atl1e_vlan_mode(netdev, features); - - if (changed & NETIF_F_RXALL) - atl1e_rx_mode(netdev, features); - - - return 0; -} - -/** - * atl1e_change_mtu - Change the Maximum Transfer Unit - * @netdev: network interface device structure - * @new_mtu: new value for maximum frame size - * - * Returns 0 on success, negative on failure - */ -static int atl1e_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - int old_mtu = netdev->mtu; - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN; - - if ((max_frame < ETH_ZLEN + ETH_FCS_LEN) || - (max_frame > MAX_JUMBO_FRAME_SIZE)) { - netdev_warn(adapter->netdev, "invalid MTU setting\n"); - return -EINVAL; - } - /* set MTU */ - if (old_mtu != new_mtu && netif_running(netdev)) { - while (test_and_set_bit(__AT_RESETTING, &adapter->flags)) - msleep(1); - netdev->mtu = new_mtu; - adapter->hw.max_frame_size = new_mtu; - adapter->hw.rx_jumbo_th = (max_frame + 7) >> 3; - atl1e_down(adapter); - atl1e_up(adapter); - clear_bit(__AT_RESETTING, &adapter->flags); - } - return 0; -} - -/* - * caller should hold mdio_lock - */ -static int atl1e_mdio_read(struct net_device *netdev, int phy_id, int reg_num) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - u16 result; - - atl1e_read_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, &result); - return result; -} - -static void atl1e_mdio_write(struct net_device *netdev, int phy_id, - int reg_num, int val) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - atl1e_write_phy_reg(&adapter->hw, reg_num & MDIO_REG_ADDR_MASK, val); -} - -static int atl1e_mii_ioctl(struct net_device *netdev, - struct ifreq *ifr, int cmd) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct mii_ioctl_data *data = if_mii(ifr); - unsigned long flags; - int retval = 0; - - if (!netif_running(netdev)) - return -EINVAL; - - spin_lock_irqsave(&adapter->mdio_lock, flags); - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 0; - break; - - case SIOCGMIIREG: - if (atl1e_read_phy_reg(&adapter->hw, data->reg_num & 0x1F, - &data->val_out)) { - retval = -EIO; - goto out; - } - break; - - case SIOCSMIIREG: - if (data->reg_num & ~(0x1F)) { - retval = -EFAULT; - goto out; - } - - netdev_dbg(adapter->netdev, " write %x %x\n", - data->reg_num, data->val_in); - if (atl1e_write_phy_reg(&adapter->hw, - data->reg_num, data->val_in)) { - retval = -EIO; - goto out; - } - break; - - default: - retval = -EOPNOTSUPP; - break; - } -out: - spin_unlock_irqrestore(&adapter->mdio_lock, flags); - return retval; - -} - -static int atl1e_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return atl1e_mii_ioctl(netdev, ifr, cmd); - default: - return -EOPNOTSUPP; - } -} - -static void atl1e_setup_pcicmd(struct pci_dev *pdev) -{ - u16 cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &cmd); - cmd &= ~(PCI_COMMAND_INTX_DISABLE | PCI_COMMAND_IO); - cmd |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER); - pci_write_config_word(pdev, PCI_COMMAND, cmd); - - /* - * some motherboards BIOS(PXE/EFI) driver may set PME - * while they transfer control to OS (Windows/Linux) - * so we should clear this bit before NIC work normally - */ - pci_write_config_dword(pdev, REG_PM_CTRLSTAT, 0); - msleep(1); -} - -/** - * atl1e_alloc_queues - Allocate memory for all rings - * @adapter: board private structure to initialize - * - */ -static int atl1e_alloc_queues(struct atl1e_adapter *adapter) -{ - return 0; -} - -/** - * atl1e_sw_init - Initialize general software structures (struct atl1e_adapter) - * @adapter: board private structure to initialize - * - * atl1e_sw_init initializes the Adapter private data structure. - * Fields are initialized based on PCI device information and - * OS network device settings (MTU size). - */ -static int atl1e_sw_init(struct atl1e_adapter *adapter) -{ - struct atl1e_hw *hw = &adapter->hw; - struct pci_dev *pdev = adapter->pdev; - u32 phy_status_data = 0; - - adapter->wol = 0; - adapter->link_speed = SPEED_0; /* hardware init */ - adapter->link_duplex = FULL_DUPLEX; - adapter->num_rx_queues = 1; - - /* PCI config space info */ - hw->vendor_id = pdev->vendor; - hw->device_id = pdev->device; - hw->subsystem_vendor_id = pdev->subsystem_vendor; - hw->subsystem_id = pdev->subsystem_device; - hw->revision_id = pdev->revision; - - pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); - - phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS); - /* nic type */ - if (hw->revision_id >= 0xF0) { - hw->nic_type = athr_l2e_revB; - } else { - if (phy_status_data & PHY_STATUS_100M) - hw->nic_type = athr_l1e; - else - hw->nic_type = athr_l2e_revA; - } - - phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS); - - if (phy_status_data & PHY_STATUS_EMI_CA) - hw->emi_ca = true; - else - hw->emi_ca = false; - - hw->phy_configured = false; - hw->preamble_len = 7; - hw->max_frame_size = adapter->netdev->mtu; - hw->rx_jumbo_th = (hw->max_frame_size + ETH_HLEN + - VLAN_HLEN + ETH_FCS_LEN + 7) >> 3; - - hw->rrs_type = atl1e_rrs_disable; - hw->indirect_tab = 0; - hw->base_cpu = 0; - - /* need confirm */ - - hw->ict = 50000; /* 100ms */ - hw->smb_timer = 200000; /* 200ms */ - hw->tpd_burst = 5; - hw->rrd_thresh = 1; - hw->tpd_thresh = adapter->tx_ring.count / 2; - hw->rx_count_down = 4; /* 2us resolution */ - hw->tx_count_down = hw->imt * 4 / 3; - hw->dmar_block = atl1e_dma_req_1024; - hw->dmaw_block = atl1e_dma_req_1024; - hw->dmar_dly_cnt = 15; - hw->dmaw_dly_cnt = 4; - - if (atl1e_alloc_queues(adapter)) { - netdev_err(adapter->netdev, "Unable to allocate memory for queues\n"); - return -ENOMEM; - } - - atomic_set(&adapter->irq_sem, 1); - spin_lock_init(&adapter->mdio_lock); - spin_lock_init(&adapter->tx_lock); - - set_bit(__AT_DOWN, &adapter->flags); - - return 0; -} - -/** - * atl1e_clean_tx_ring - Free Tx-skb - * @adapter: board private structure - */ -static void atl1e_clean_tx_ring(struct atl1e_adapter *adapter) -{ - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - struct atl1e_tx_buffer *tx_buffer = NULL; - struct pci_dev *pdev = adapter->pdev; - u16 index, ring_count; - - if (tx_ring->desc == NULL || tx_ring->tx_buffer == NULL) - return; - - ring_count = tx_ring->count; - /* first unmmap dma */ - for (index = 0; index < ring_count; index++) { - tx_buffer = &tx_ring->tx_buffer[index]; - if (tx_buffer->dma) { - if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE) - pci_unmap_single(pdev, tx_buffer->dma, - tx_buffer->length, PCI_DMA_TODEVICE); - else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE) - pci_unmap_page(pdev, tx_buffer->dma, - tx_buffer->length, PCI_DMA_TODEVICE); - tx_buffer->dma = 0; - } - } - /* second free skb */ - for (index = 0; index < ring_count; index++) { - tx_buffer = &tx_ring->tx_buffer[index]; - if (tx_buffer->skb) { - dev_kfree_skb_any(tx_buffer->skb); - tx_buffer->skb = NULL; - } - } - /* Zero out Tx-buffers */ - memset(tx_ring->desc, 0, sizeof(struct atl1e_tpd_desc) * - ring_count); - memset(tx_ring->tx_buffer, 0, sizeof(struct atl1e_tx_buffer) * - ring_count); -} - -/** - * atl1e_clean_rx_ring - Free rx-reservation skbs - * @adapter: board private structure - */ -static void atl1e_clean_rx_ring(struct atl1e_adapter *adapter) -{ - struct atl1e_rx_ring *rx_ring = - &adapter->rx_ring; - struct atl1e_rx_page_desc *rx_page_desc = rx_ring->rx_page_desc; - u16 i, j; - - - if (adapter->ring_vir_addr == NULL) - return; - /* Zero out the descriptor ring */ - for (i = 0; i < adapter->num_rx_queues; i++) { - for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) { - if (rx_page_desc[i].rx_page[j].addr != NULL) { - memset(rx_page_desc[i].rx_page[j].addr, 0, - rx_ring->real_page_size); - } - } - } -} - -static void atl1e_cal_ring_size(struct atl1e_adapter *adapter, u32 *ring_size) -{ - *ring_size = ((u32)(adapter->tx_ring.count * - sizeof(struct atl1e_tpd_desc) + 7 - /* tx ring, qword align */ - + adapter->rx_ring.real_page_size * AT_PAGE_NUM_PER_QUEUE * - adapter->num_rx_queues + 31 - /* rx ring, 32 bytes align */ - + (1 + AT_PAGE_NUM_PER_QUEUE * adapter->num_rx_queues) * - sizeof(u32) + 3)); - /* tx, rx cmd, dword align */ -} - -static void atl1e_init_ring_resources(struct atl1e_adapter *adapter) -{ - struct atl1e_rx_ring *rx_ring = NULL; - - rx_ring = &adapter->rx_ring; - - rx_ring->real_page_size = adapter->rx_ring.page_size - + adapter->hw.max_frame_size - + ETH_HLEN + VLAN_HLEN - + ETH_FCS_LEN; - rx_ring->real_page_size = roundup(rx_ring->real_page_size, 32); - atl1e_cal_ring_size(adapter, &adapter->ring_size); - - adapter->ring_vir_addr = NULL; - adapter->rx_ring.desc = NULL; - rwlock_init(&adapter->tx_ring.tx_lock); -} - -/* - * Read / Write Ptr Initialize: - */ -static void atl1e_init_ring_ptrs(struct atl1e_adapter *adapter) -{ - struct atl1e_tx_ring *tx_ring = NULL; - struct atl1e_rx_ring *rx_ring = NULL; - struct atl1e_rx_page_desc *rx_page_desc = NULL; - int i, j; - - tx_ring = &adapter->tx_ring; - rx_ring = &adapter->rx_ring; - rx_page_desc = rx_ring->rx_page_desc; - - tx_ring->next_to_use = 0; - atomic_set(&tx_ring->next_to_clean, 0); - - for (i = 0; i < adapter->num_rx_queues; i++) { - rx_page_desc[i].rx_using = 0; - rx_page_desc[i].rx_nxseq = 0; - for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) { - *rx_page_desc[i].rx_page[j].write_offset_addr = 0; - rx_page_desc[i].rx_page[j].read_offset = 0; - } - } -} - -/** - * atl1e_free_ring_resources - Free Tx / RX descriptor Resources - * @adapter: board private structure - * - * Free all transmit software resources - */ -static void atl1e_free_ring_resources(struct atl1e_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - - atl1e_clean_tx_ring(adapter); - atl1e_clean_rx_ring(adapter); - - if (adapter->ring_vir_addr) { - pci_free_consistent(pdev, adapter->ring_size, - adapter->ring_vir_addr, adapter->ring_dma); - adapter->ring_vir_addr = NULL; - } - - if (adapter->tx_ring.tx_buffer) { - kfree(adapter->tx_ring.tx_buffer); - adapter->tx_ring.tx_buffer = NULL; - } -} - -/** - * atl1e_setup_mem_resources - allocate Tx / RX descriptor resources - * @adapter: board private structure - * - * Return 0 on success, negative on failure - */ -static int atl1e_setup_ring_resources(struct atl1e_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - struct atl1e_tx_ring *tx_ring; - struct atl1e_rx_ring *rx_ring; - struct atl1e_rx_page_desc *rx_page_desc; - int size, i, j; - u32 offset = 0; - int err = 0; - - if (adapter->ring_vir_addr != NULL) - return 0; /* alloced already */ - - tx_ring = &adapter->tx_ring; - rx_ring = &adapter->rx_ring; - - /* real ring DMA buffer */ - - size = adapter->ring_size; - adapter->ring_vir_addr = pci_zalloc_consistent(pdev, adapter->ring_size, - &adapter->ring_dma); - if (adapter->ring_vir_addr == NULL) { - netdev_err(adapter->netdev, - "pci_alloc_consistent failed, size = D%d\n", size); - return -ENOMEM; - } - - rx_page_desc = rx_ring->rx_page_desc; - - /* Init TPD Ring */ - tx_ring->dma = roundup(adapter->ring_dma, 8); - offset = tx_ring->dma - adapter->ring_dma; - tx_ring->desc = adapter->ring_vir_addr + offset; - size = sizeof(struct atl1e_tx_buffer) * (tx_ring->count); - tx_ring->tx_buffer = kzalloc(size, GFP_KERNEL); - if (tx_ring->tx_buffer == NULL) { - err = -ENOMEM; - goto failed; - } - - /* Init RXF-Pages */ - offset += (sizeof(struct atl1e_tpd_desc) * tx_ring->count); - offset = roundup(offset, 32); - - for (i = 0; i < adapter->num_rx_queues; i++) { - for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) { - rx_page_desc[i].rx_page[j].dma = - adapter->ring_dma + offset; - rx_page_desc[i].rx_page[j].addr = - adapter->ring_vir_addr + offset; - offset += rx_ring->real_page_size; - } - } - - /* Init CMB dma address */ - tx_ring->cmb_dma = adapter->ring_dma + offset; - tx_ring->cmb = adapter->ring_vir_addr + offset; - offset += sizeof(u32); - - for (i = 0; i < adapter->num_rx_queues; i++) { - for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) { - rx_page_desc[i].rx_page[j].write_offset_dma = - adapter->ring_dma + offset; - rx_page_desc[i].rx_page[j].write_offset_addr = - adapter->ring_vir_addr + offset; - offset += sizeof(u32); - } - } - - if (unlikely(offset > adapter->ring_size)) { - netdev_err(adapter->netdev, "offset(%d) > ring size(%d) !!\n", - offset, adapter->ring_size); - err = -1; - goto failed; - } - - return 0; -failed: - if (adapter->ring_vir_addr != NULL) { - pci_free_consistent(pdev, adapter->ring_size, - adapter->ring_vir_addr, adapter->ring_dma); - adapter->ring_vir_addr = NULL; - } - return err; -} - -static inline void atl1e_configure_des_ring(struct atl1e_adapter *adapter) -{ - - struct atl1e_hw *hw = &adapter->hw; - struct atl1e_rx_ring *rx_ring = &adapter->rx_ring; - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - struct atl1e_rx_page_desc *rx_page_desc = NULL; - int i, j; - - AT_WRITE_REG(hw, REG_DESC_BASE_ADDR_HI, - (u32)((adapter->ring_dma & AT_DMA_HI_ADDR_MASK) >> 32)); - AT_WRITE_REG(hw, REG_TPD_BASE_ADDR_LO, - (u32)((tx_ring->dma) & AT_DMA_LO_ADDR_MASK)); - AT_WRITE_REG(hw, REG_TPD_RING_SIZE, (u16)(tx_ring->count)); - AT_WRITE_REG(hw, REG_HOST_TX_CMB_LO, - (u32)((tx_ring->cmb_dma) & AT_DMA_LO_ADDR_MASK)); - - rx_page_desc = rx_ring->rx_page_desc; - /* RXF Page Physical address / Page Length */ - for (i = 0; i < AT_MAX_RECEIVE_QUEUE; i++) { - AT_WRITE_REG(hw, atl1e_rx_page_hi_addr_regs[i], - (u32)((adapter->ring_dma & - AT_DMA_HI_ADDR_MASK) >> 32)); - for (j = 0; j < AT_PAGE_NUM_PER_QUEUE; j++) { - u32 page_phy_addr; - u32 offset_phy_addr; - - page_phy_addr = rx_page_desc[i].rx_page[j].dma; - offset_phy_addr = - rx_page_desc[i].rx_page[j].write_offset_dma; - - AT_WRITE_REG(hw, atl1e_rx_page_lo_addr_regs[i][j], - page_phy_addr & AT_DMA_LO_ADDR_MASK); - AT_WRITE_REG(hw, atl1e_rx_page_write_offset_regs[i][j], - offset_phy_addr & AT_DMA_LO_ADDR_MASK); - AT_WRITE_REGB(hw, atl1e_rx_page_vld_regs[i][j], 1); - } - } - /* Page Length */ - AT_WRITE_REG(hw, REG_HOST_RXFPAGE_SIZE, rx_ring->page_size); - /* Load all of base address above */ - AT_WRITE_REG(hw, REG_LOAD_PTR, 1); -} - -static inline void atl1e_configure_tx(struct atl1e_adapter *adapter) -{ - struct atl1e_hw *hw = &adapter->hw; - u32 dev_ctrl_data = 0; - u32 max_pay_load = 0; - u32 jumbo_thresh = 0; - u32 extra_size = 0; /* Jumbo frame threshold in QWORD unit */ - - /* configure TXQ param */ - if (hw->nic_type != athr_l2e_revB) { - extra_size = ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN; - if (hw->max_frame_size <= 1500) { - jumbo_thresh = hw->max_frame_size + extra_size; - } else if (hw->max_frame_size < 6*1024) { - jumbo_thresh = - (hw->max_frame_size + extra_size) * 2 / 3; - } else { - jumbo_thresh = (hw->max_frame_size + extra_size) / 2; - } - AT_WRITE_REG(hw, REG_TX_EARLY_TH, (jumbo_thresh + 7) >> 3); - } - - dev_ctrl_data = AT_READ_REG(hw, REG_DEVICE_CTRL); - - max_pay_load = ((dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT)) & - DEVICE_CTRL_MAX_PAYLOAD_MASK; - - hw->dmaw_block = min_t(u32, max_pay_load, hw->dmaw_block); - - max_pay_load = ((dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT)) & - DEVICE_CTRL_MAX_RREQ_SZ_MASK; - hw->dmar_block = min_t(u32, max_pay_load, hw->dmar_block); - - if (hw->nic_type != athr_l2e_revB) - AT_WRITE_REGW(hw, REG_TXQ_CTRL + 2, - atl1e_pay_load_size[hw->dmar_block]); - /* enable TXQ */ - AT_WRITE_REGW(hw, REG_TXQ_CTRL, - (((u16)hw->tpd_burst & TXQ_CTRL_NUM_TPD_BURST_MASK) - << TXQ_CTRL_NUM_TPD_BURST_SHIFT) - | TXQ_CTRL_ENH_MODE | TXQ_CTRL_EN); -} - -static inline void atl1e_configure_rx(struct atl1e_adapter *adapter) -{ - struct atl1e_hw *hw = &adapter->hw; - u32 rxf_len = 0; - u32 rxf_low = 0; - u32 rxf_high = 0; - u32 rxf_thresh_data = 0; - u32 rxq_ctrl_data = 0; - - if (hw->nic_type != athr_l2e_revB) { - AT_WRITE_REGW(hw, REG_RXQ_JMBOSZ_RRDTIM, - (u16)((hw->rx_jumbo_th & RXQ_JMBOSZ_TH_MASK) << - RXQ_JMBOSZ_TH_SHIFT | - (1 & RXQ_JMBO_LKAH_MASK) << - RXQ_JMBO_LKAH_SHIFT)); - - rxf_len = AT_READ_REG(hw, REG_SRAM_RXF_LEN); - rxf_high = rxf_len * 4 / 5; - rxf_low = rxf_len / 5; - rxf_thresh_data = ((rxf_high & RXQ_RXF_PAUSE_TH_HI_MASK) - << RXQ_RXF_PAUSE_TH_HI_SHIFT) | - ((rxf_low & RXQ_RXF_PAUSE_TH_LO_MASK) - << RXQ_RXF_PAUSE_TH_LO_SHIFT); - - AT_WRITE_REG(hw, REG_RXQ_RXF_PAUSE_THRESH, rxf_thresh_data); - } - - /* RRS */ - AT_WRITE_REG(hw, REG_IDT_TABLE, hw->indirect_tab); - AT_WRITE_REG(hw, REG_BASE_CPU_NUMBER, hw->base_cpu); - - if (hw->rrs_type & atl1e_rrs_ipv4) - rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV4; - - if (hw->rrs_type & atl1e_rrs_ipv4_tcp) - rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV4_TCP; - - if (hw->rrs_type & atl1e_rrs_ipv6) - rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV6; - - if (hw->rrs_type & atl1e_rrs_ipv6_tcp) - rxq_ctrl_data |= RXQ_CTRL_HASH_TYPE_IPV6_TCP; - - if (hw->rrs_type != atl1e_rrs_disable) - rxq_ctrl_data |= - (RXQ_CTRL_HASH_ENABLE | RXQ_CTRL_RSS_MODE_MQUESINT); - - rxq_ctrl_data |= RXQ_CTRL_IPV6_XSUM_VERIFY_EN | RXQ_CTRL_PBA_ALIGN_32 | - RXQ_CTRL_CUT_THRU_EN | RXQ_CTRL_EN; - - AT_WRITE_REG(hw, REG_RXQ_CTRL, rxq_ctrl_data); -} - -static inline void atl1e_configure_dma(struct atl1e_adapter *adapter) -{ - struct atl1e_hw *hw = &adapter->hw; - u32 dma_ctrl_data = 0; - - dma_ctrl_data = DMA_CTRL_RXCMB_EN; - dma_ctrl_data |= (((u32)hw->dmar_block) & DMA_CTRL_DMAR_BURST_LEN_MASK) - << DMA_CTRL_DMAR_BURST_LEN_SHIFT; - dma_ctrl_data |= (((u32)hw->dmaw_block) & DMA_CTRL_DMAW_BURST_LEN_MASK) - << DMA_CTRL_DMAW_BURST_LEN_SHIFT; - dma_ctrl_data |= DMA_CTRL_DMAR_REQ_PRI | DMA_CTRL_DMAR_OUT_ORDER; - dma_ctrl_data |= (((u32)hw->dmar_dly_cnt) & DMA_CTRL_DMAR_DLY_CNT_MASK) - << DMA_CTRL_DMAR_DLY_CNT_SHIFT; - dma_ctrl_data |= (((u32)hw->dmaw_dly_cnt) & DMA_CTRL_DMAW_DLY_CNT_MASK) - << DMA_CTRL_DMAW_DLY_CNT_SHIFT; - - AT_WRITE_REG(hw, REG_DMA_CTRL, dma_ctrl_data); -} - -static void atl1e_setup_mac_ctrl(struct atl1e_adapter *adapter) -{ - u32 value; - struct atl1e_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - - /* Config MAC CTRL Register */ - value = MAC_CTRL_TX_EN | - MAC_CTRL_RX_EN ; - - if (FULL_DUPLEX == adapter->link_duplex) - value |= MAC_CTRL_DUPLX; - - value |= ((u32)((SPEED_1000 == adapter->link_speed) ? - MAC_CTRL_SPEED_1000 : MAC_CTRL_SPEED_10_100) << - MAC_CTRL_SPEED_SHIFT); - value |= (MAC_CTRL_TX_FLOW | MAC_CTRL_RX_FLOW); - - value |= (MAC_CTRL_ADD_CRC | MAC_CTRL_PAD); - value |= (((u32)adapter->hw.preamble_len & - MAC_CTRL_PRMLEN_MASK) << MAC_CTRL_PRMLEN_SHIFT); - - __atl1e_vlan_mode(netdev->features, &value); - - value |= MAC_CTRL_BC_EN; - if (netdev->flags & IFF_PROMISC) - value |= MAC_CTRL_PROMIS_EN; - if (netdev->flags & IFF_ALLMULTI) - value |= MAC_CTRL_MC_ALL_EN; - if (netdev->features & NETIF_F_RXALL) - value |= MAC_CTRL_DBG; - AT_WRITE_REG(hw, REG_MAC_CTRL, value); -} - -/** - * atl1e_configure - Configure Transmit&Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Tx /Rx unit of the MAC after a reset. - */ -static int atl1e_configure(struct atl1e_adapter *adapter) -{ - struct atl1e_hw *hw = &adapter->hw; - - u32 intr_status_data = 0; - - /* clear interrupt status */ - AT_WRITE_REG(hw, REG_ISR, ~0); - - /* 1. set MAC Address */ - atl1e_hw_set_mac_addr(hw); - - /* 2. Init the Multicast HASH table done by set_muti */ - - /* 3. Clear any WOL status */ - AT_WRITE_REG(hw, REG_WOL_CTRL, 0); - - /* 4. Descripter Ring BaseMem/Length/Read ptr/Write ptr - * TPD Ring/SMB/RXF0 Page CMBs, they use the same - * High 32bits memory */ - atl1e_configure_des_ring(adapter); - - /* 5. set Interrupt Moderator Timer */ - AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER_INIT, hw->imt); - AT_WRITE_REGW(hw, REG_IRQ_MODU_TIMER2_INIT, hw->imt); - AT_WRITE_REG(hw, REG_MASTER_CTRL, MASTER_CTRL_LED_MODE | - MASTER_CTRL_ITIMER_EN | MASTER_CTRL_ITIMER2_EN); - - /* 6. rx/tx threshold to trig interrupt */ - AT_WRITE_REGW(hw, REG_TRIG_RRD_THRESH, hw->rrd_thresh); - AT_WRITE_REGW(hw, REG_TRIG_TPD_THRESH, hw->tpd_thresh); - AT_WRITE_REGW(hw, REG_TRIG_RXTIMER, hw->rx_count_down); - AT_WRITE_REGW(hw, REG_TRIG_TXTIMER, hw->tx_count_down); - - /* 7. set Interrupt Clear Timer */ - AT_WRITE_REGW(hw, REG_CMBDISDMA_TIMER, hw->ict); - - /* 8. set MTU */ - AT_WRITE_REG(hw, REG_MTU, hw->max_frame_size + ETH_HLEN + - VLAN_HLEN + ETH_FCS_LEN); - - /* 9. config TXQ early tx threshold */ - atl1e_configure_tx(adapter); - - /* 10. config RXQ */ - atl1e_configure_rx(adapter); - - /* 11. config DMA Engine */ - atl1e_configure_dma(adapter); - - /* 12. smb timer to trig interrupt */ - AT_WRITE_REG(hw, REG_SMB_STAT_TIMER, hw->smb_timer); - - intr_status_data = AT_READ_REG(hw, REG_ISR); - if (unlikely((intr_status_data & ISR_PHY_LINKDOWN) != 0)) { - netdev_err(adapter->netdev, - "atl1e_configure failed, PCIE phy link down\n"); - return -1; - } - - AT_WRITE_REG(hw, REG_ISR, 0x7fffffff); - return 0; -} - -/** - * atl1e_get_stats - Get System Network Statistics - * @netdev: network interface device structure - * - * Returns the address of the device statistics structure. - * The statistics are actually updated from the timer callback. - */ -static struct net_device_stats *atl1e_get_stats(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw_stats *hw_stats = &adapter->hw_stats; - struct net_device_stats *net_stats = &netdev->stats; - - net_stats->rx_bytes = hw_stats->rx_byte_cnt; - net_stats->tx_bytes = hw_stats->tx_byte_cnt; - net_stats->multicast = hw_stats->rx_mcast; - net_stats->collisions = hw_stats->tx_1_col + - hw_stats->tx_2_col + - hw_stats->tx_late_col + - hw_stats->tx_abort_col; - - net_stats->rx_errors = hw_stats->rx_frag + - hw_stats->rx_fcs_err + - hw_stats->rx_len_err + - hw_stats->rx_sz_ov + - hw_stats->rx_rrd_ov + - hw_stats->rx_align_err + - hw_stats->rx_rxf_ov; - - net_stats->rx_fifo_errors = hw_stats->rx_rxf_ov; - net_stats->rx_length_errors = hw_stats->rx_len_err; - net_stats->rx_crc_errors = hw_stats->rx_fcs_err; - net_stats->rx_frame_errors = hw_stats->rx_align_err; - net_stats->rx_dropped = hw_stats->rx_rrd_ov; - - net_stats->tx_errors = hw_stats->tx_late_col + - hw_stats->tx_abort_col + - hw_stats->tx_underrun + - hw_stats->tx_trunc; - - net_stats->tx_fifo_errors = hw_stats->tx_underrun; - net_stats->tx_aborted_errors = hw_stats->tx_abort_col; - net_stats->tx_window_errors = hw_stats->tx_late_col; - - net_stats->rx_packets = hw_stats->rx_ok + net_stats->rx_errors; - net_stats->tx_packets = hw_stats->tx_ok + net_stats->tx_errors; - - return net_stats; -} - -static void atl1e_update_hw_stats(struct atl1e_adapter *adapter) -{ - u16 hw_reg_addr = 0; - unsigned long *stats_item = NULL; - - /* update rx status */ - hw_reg_addr = REG_MAC_RX_STATUS_BIN; - stats_item = &adapter->hw_stats.rx_ok; - while (hw_reg_addr <= REG_MAC_RX_STATUS_END) { - *stats_item += AT_READ_REG(&adapter->hw, hw_reg_addr); - stats_item++; - hw_reg_addr += 4; - } - /* update tx status */ - hw_reg_addr = REG_MAC_TX_STATUS_BIN; - stats_item = &adapter->hw_stats.tx_ok; - while (hw_reg_addr <= REG_MAC_TX_STATUS_END) { - *stats_item += AT_READ_REG(&adapter->hw, hw_reg_addr); - stats_item++; - hw_reg_addr += 4; - } -} - -static inline void atl1e_clear_phy_int(struct atl1e_adapter *adapter) -{ - u16 phy_data; - - spin_lock(&adapter->mdio_lock); - atl1e_read_phy_reg(&adapter->hw, MII_INT_STATUS, &phy_data); - spin_unlock(&adapter->mdio_lock); -} - -static bool atl1e_clean_tx_irq(struct atl1e_adapter *adapter) -{ - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - struct atl1e_tx_buffer *tx_buffer = NULL; - u16 hw_next_to_clean = AT_READ_REGW(&adapter->hw, REG_TPD_CONS_IDX); - u16 next_to_clean = atomic_read(&tx_ring->next_to_clean); - - while (next_to_clean != hw_next_to_clean) { - tx_buffer = &tx_ring->tx_buffer[next_to_clean]; - if (tx_buffer->dma) { - if (tx_buffer->flags & ATL1E_TX_PCIMAP_SINGLE) - pci_unmap_single(adapter->pdev, tx_buffer->dma, - tx_buffer->length, PCI_DMA_TODEVICE); - else if (tx_buffer->flags & ATL1E_TX_PCIMAP_PAGE) - pci_unmap_page(adapter->pdev, tx_buffer->dma, - tx_buffer->length, PCI_DMA_TODEVICE); - tx_buffer->dma = 0; - } - - if (tx_buffer->skb) { - dev_kfree_skb_irq(tx_buffer->skb); - tx_buffer->skb = NULL; - } - - if (++next_to_clean == tx_ring->count) - next_to_clean = 0; - } - - atomic_set(&tx_ring->next_to_clean, next_to_clean); - - if (netif_queue_stopped(adapter->netdev) && - netif_carrier_ok(adapter->netdev)) { - netif_wake_queue(adapter->netdev); - } - - return true; -} - -/** - * atl1e_intr - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - */ -static irqreturn_t atl1e_intr(int irq, void *data) -{ - struct net_device *netdev = data; - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - int max_ints = AT_MAX_INT_WORK; - int handled = IRQ_NONE; - u32 status; - - do { - status = AT_READ_REG(hw, REG_ISR); - if ((status & IMR_NORMAL_MASK) == 0 || - (status & ISR_DIS_INT) != 0) { - if (max_ints != AT_MAX_INT_WORK) - handled = IRQ_HANDLED; - break; - } - /* link event */ - if (status & ISR_GPHY) - atl1e_clear_phy_int(adapter); - /* Ack ISR */ - AT_WRITE_REG(hw, REG_ISR, status | ISR_DIS_INT); - - handled = IRQ_HANDLED; - /* check if PCIE PHY Link down */ - if (status & ISR_PHY_LINKDOWN) { - netdev_err(adapter->netdev, - "pcie phy linkdown %x\n", status); - if (netif_running(adapter->netdev)) { - /* reset MAC */ - atl1e_irq_reset(adapter); - schedule_work(&adapter->reset_task); - break; - } - } - - /* check if DMA read/write error */ - if (status & (ISR_DMAR_TO_RST | ISR_DMAW_TO_RST)) { - netdev_err(adapter->netdev, - "PCIE DMA RW error (status = 0x%x)\n", - status); - atl1e_irq_reset(adapter); - schedule_work(&adapter->reset_task); - break; - } - - if (status & ISR_SMB) - atl1e_update_hw_stats(adapter); - - /* link event */ - if (status & (ISR_GPHY | ISR_MANUAL)) { - netdev->stats.tx_carrier_errors++; - atl1e_link_chg_event(adapter); - break; - } - - /* transmit event */ - if (status & ISR_TX_EVENT) - atl1e_clean_tx_irq(adapter); - - if (status & ISR_RX_EVENT) { - /* - * disable rx interrupts, without - * the synchronize_irq bit - */ - AT_WRITE_REG(hw, REG_IMR, - IMR_NORMAL_MASK & ~ISR_RX_EVENT); - AT_WRITE_FLUSH(hw); - if (likely(napi_schedule_prep( - &adapter->napi))) - __napi_schedule(&adapter->napi); - } - } while (--max_ints > 0); - /* re-enable Interrupt*/ - AT_WRITE_REG(&adapter->hw, REG_ISR, 0); - - return handled; -} - -static inline void atl1e_rx_checksum(struct atl1e_adapter *adapter, - struct sk_buff *skb, struct atl1e_recv_ret_status *prrs) -{ - u8 *packet = (u8 *)(prrs + 1); - struct iphdr *iph; - u16 head_len = ETH_HLEN; - u16 pkt_flags; - u16 err_flags; - - skb_checksum_none_assert(skb); - pkt_flags = prrs->pkt_flag; - err_flags = prrs->err_flag; - if (((pkt_flags & RRS_IS_IPV4) || (pkt_flags & RRS_IS_IPV6)) && - ((pkt_flags & RRS_IS_TCP) || (pkt_flags & RRS_IS_UDP))) { - if (pkt_flags & RRS_IS_IPV4) { - if (pkt_flags & RRS_IS_802_3) - head_len += 8; - iph = (struct iphdr *) (packet + head_len); - if (iph->frag_off != 0 && !(pkt_flags & RRS_IS_IP_DF)) - goto hw_xsum; - } - if (!(err_flags & (RRS_ERR_IP_CSUM | RRS_ERR_L4_CSUM))) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - return; - } - } - -hw_xsum : - return; -} - -static struct atl1e_rx_page *atl1e_get_rx_page(struct atl1e_adapter *adapter, - u8 que) -{ - struct atl1e_rx_page_desc *rx_page_desc = - (struct atl1e_rx_page_desc *) adapter->rx_ring.rx_page_desc; - u8 rx_using = rx_page_desc[que].rx_using; - - return &(rx_page_desc[que].rx_page[rx_using]); -} - -static void atl1e_clean_rx_irq(struct atl1e_adapter *adapter, u8 que, - int *work_done, int work_to_do) -{ - struct net_device *netdev = adapter->netdev; - struct atl1e_rx_ring *rx_ring = &adapter->rx_ring; - struct atl1e_rx_page_desc *rx_page_desc = - (struct atl1e_rx_page_desc *) rx_ring->rx_page_desc; - struct sk_buff *skb = NULL; - struct atl1e_rx_page *rx_page = atl1e_get_rx_page(adapter, que); - u32 packet_size, write_offset; - struct atl1e_recv_ret_status *prrs; - - write_offset = *(rx_page->write_offset_addr); - if (likely(rx_page->read_offset < write_offset)) { - do { - if (*work_done >= work_to_do) - break; - (*work_done)++; - /* get new packet's rrs */ - prrs = (struct atl1e_recv_ret_status *) (rx_page->addr + - rx_page->read_offset); - /* check sequence number */ - if (prrs->seq_num != rx_page_desc[que].rx_nxseq) { - netdev_err(netdev, - "rx sequence number error (rx=%d) (expect=%d)\n", - prrs->seq_num, - rx_page_desc[que].rx_nxseq); - rx_page_desc[que].rx_nxseq++; - /* just for debug use */ - AT_WRITE_REG(&adapter->hw, REG_DEBUG_DATA0, - (((u32)prrs->seq_num) << 16) | - rx_page_desc[que].rx_nxseq); - goto fatal_err; - } - rx_page_desc[que].rx_nxseq++; - - /* error packet */ - if ((prrs->pkt_flag & RRS_IS_ERR_FRAME) && - !(netdev->features & NETIF_F_RXALL)) { - if (prrs->err_flag & (RRS_ERR_BAD_CRC | - RRS_ERR_DRIBBLE | RRS_ERR_CODE | - RRS_ERR_TRUNC)) { - /* hardware error, discard this packet*/ - netdev_err(netdev, - "rx packet desc error %x\n", - *((u32 *)prrs + 1)); - goto skip_pkt; - } - } - - packet_size = ((prrs->word1 >> RRS_PKT_SIZE_SHIFT) & - RRS_PKT_SIZE_MASK); - if (likely(!(netdev->features & NETIF_F_RXFCS))) - packet_size -= 4; /* CRC */ - - skb = netdev_alloc_skb_ip_align(netdev, packet_size); - if (skb == NULL) - goto skip_pkt; - - memcpy(skb->data, (u8 *)(prrs + 1), packet_size); - skb_put(skb, packet_size); - skb->protocol = eth_type_trans(skb, netdev); - atl1e_rx_checksum(adapter, skb, prrs); - - if (prrs->pkt_flag & RRS_IS_VLAN_TAG) { - u16 vlan_tag = (prrs->vtag >> 4) | - ((prrs->vtag & 7) << 13) | - ((prrs->vtag & 8) << 9); - netdev_dbg(netdev, - "RXD VLAN TAG=0x%04x\n", - prrs->vtag); - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vlan_tag); - } - netif_receive_skb(skb); - -skip_pkt: - /* skip current packet whether it's ok or not. */ - rx_page->read_offset += - (((u32)((prrs->word1 >> RRS_PKT_SIZE_SHIFT) & - RRS_PKT_SIZE_MASK) + - sizeof(struct atl1e_recv_ret_status) + 31) & - 0xFFFFFFE0); - - if (rx_page->read_offset >= rx_ring->page_size) { - /* mark this page clean */ - u16 reg_addr; - u8 rx_using; - - rx_page->read_offset = - *(rx_page->write_offset_addr) = 0; - rx_using = rx_page_desc[que].rx_using; - reg_addr = - atl1e_rx_page_vld_regs[que][rx_using]; - AT_WRITE_REGB(&adapter->hw, reg_addr, 1); - rx_page_desc[que].rx_using ^= 1; - rx_page = atl1e_get_rx_page(adapter, que); - } - write_offset = *(rx_page->write_offset_addr); - } while (rx_page->read_offset < write_offset); - } - - return; - -fatal_err: - if (!test_bit(__AT_DOWN, &adapter->flags)) - schedule_work(&adapter->reset_task); -} - -/** - * atl1e_clean - NAPI Rx polling callback - */ -static int atl1e_clean(struct napi_struct *napi, int budget) -{ - struct atl1e_adapter *adapter = - container_of(napi, struct atl1e_adapter, napi); - u32 imr_data; - int work_done = 0; - - /* Keep link state information with original netdev */ - if (!netif_carrier_ok(adapter->netdev)) - goto quit_polling; - - atl1e_clean_rx_irq(adapter, 0, &work_done, budget); - - /* If no Tx and not enough Rx work done, exit the polling mode */ - if (work_done < budget) { -quit_polling: - napi_complete(napi); - imr_data = AT_READ_REG(&adapter->hw, REG_IMR); - AT_WRITE_REG(&adapter->hw, REG_IMR, imr_data | ISR_RX_EVENT); - /* test debug */ - if (test_bit(__AT_DOWN, &adapter->flags)) { - atomic_dec(&adapter->irq_sem); - netdev_err(adapter->netdev, - "atl1e_clean is called when AT_DOWN\n"); - } - /* reenable RX intr */ - /*atl1e_irq_enable(adapter); */ - - } - return work_done; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER - -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void atl1e_netpoll(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - disable_irq(adapter->pdev->irq); - atl1e_intr(adapter->pdev->irq, netdev); - enable_irq(adapter->pdev->irq); -} -#endif - -static inline u16 atl1e_tpd_avail(struct atl1e_adapter *adapter) -{ - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - u16 next_to_use = 0; - u16 next_to_clean = 0; - - next_to_clean = atomic_read(&tx_ring->next_to_clean); - next_to_use = tx_ring->next_to_use; - - return (u16)(next_to_clean > next_to_use) ? - (next_to_clean - next_to_use - 1) : - (tx_ring->count + next_to_clean - next_to_use - 1); -} - -/* - * get next usable tpd - * Note: should call atl1e_tdp_avail to make sure - * there is enough tpd to use - */ -static struct atl1e_tpd_desc *atl1e_get_tpd(struct atl1e_adapter *adapter) -{ - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - u16 next_to_use = 0; - - next_to_use = tx_ring->next_to_use; - if (++tx_ring->next_to_use == tx_ring->count) - tx_ring->next_to_use = 0; - - memset(&tx_ring->desc[next_to_use], 0, sizeof(struct atl1e_tpd_desc)); - return &tx_ring->desc[next_to_use]; -} - -static struct atl1e_tx_buffer * -atl1e_get_tx_buffer(struct atl1e_adapter *adapter, struct atl1e_tpd_desc *tpd) -{ - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - - return &tx_ring->tx_buffer[tpd - tx_ring->desc]; -} - -/* Calculate the transmit packet descript needed*/ -static u16 atl1e_cal_tdp_req(const struct sk_buff *skb) -{ - int i = 0; - u16 tpd_req = 1; - u16 fg_size = 0; - u16 proto_hdr_len = 0; - - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - fg_size = skb_frag_size(&skb_shinfo(skb)->frags[i]); - tpd_req += ((fg_size + MAX_TX_BUF_LEN - 1) >> MAX_TX_BUF_SHIFT); - } - - if (skb_is_gso(skb)) { - if (skb->protocol == htons(ETH_P_IP) || - (skb_shinfo(skb)->gso_type == SKB_GSO_TCPV6)) { - proto_hdr_len = skb_transport_offset(skb) + - tcp_hdrlen(skb); - if (proto_hdr_len < skb_headlen(skb)) { - tpd_req += ((skb_headlen(skb) - proto_hdr_len + - MAX_TX_BUF_LEN - 1) >> - MAX_TX_BUF_SHIFT); - } - } - - } - return tpd_req; -} - -static int atl1e_tso_csum(struct atl1e_adapter *adapter, - struct sk_buff *skb, struct atl1e_tpd_desc *tpd) -{ - unsigned short offload_type; - u8 hdr_len; - u32 real_len; - - if (skb_is_gso(skb)) { - int err; - - err = skb_cow_head(skb, 0); - if (err < 0) - return err; - - offload_type = skb_shinfo(skb)->gso_type; - - if (offload_type & SKB_GSO_TCPV4) { - real_len = (((unsigned char *)ip_hdr(skb) - skb->data) - + ntohs(ip_hdr(skb)->tot_len)); - - if (real_len < skb->len) - pskb_trim(skb, real_len); - - hdr_len = (skb_transport_offset(skb) + tcp_hdrlen(skb)); - if (unlikely(skb->len == hdr_len)) { - /* only xsum need */ - netdev_warn(adapter->netdev, - "IPV4 tso with zero data??\n"); - goto check_sum; - } else { - ip_hdr(skb)->check = 0; - ip_hdr(skb)->tot_len = 0; - tcp_hdr(skb)->check = ~csum_tcpudp_magic( - ip_hdr(skb)->saddr, - ip_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); - tpd->word3 |= (ip_hdr(skb)->ihl & - TDP_V4_IPHL_MASK) << - TPD_V4_IPHL_SHIFT; - tpd->word3 |= ((tcp_hdrlen(skb) >> 2) & - TPD_TCPHDRLEN_MASK) << - TPD_TCPHDRLEN_SHIFT; - tpd->word3 |= ((skb_shinfo(skb)->gso_size) & - TPD_MSS_MASK) << TPD_MSS_SHIFT; - tpd->word3 |= 1 << TPD_SEGMENT_EN_SHIFT; - } - return 0; - } - } - -check_sum: - if (likely(skb->ip_summed == CHECKSUM_PARTIAL)) { - u8 css, cso; - - cso = skb_checksum_start_offset(skb); - if (unlikely(cso & 0x1)) { - netdev_err(adapter->netdev, - "payload offset should not ant event number\n"); - return -1; - } else { - css = cso + skb->csum_offset; - tpd->word3 |= (cso & TPD_PLOADOFFSET_MASK) << - TPD_PLOADOFFSET_SHIFT; - tpd->word3 |= (css & TPD_CCSUMOFFSET_MASK) << - TPD_CCSUMOFFSET_SHIFT; - tpd->word3 |= 1 << TPD_CC_SEGMENT_EN_SHIFT; - } - } - - return 0; -} - -static int atl1e_tx_map(struct atl1e_adapter *adapter, - struct sk_buff *skb, struct atl1e_tpd_desc *tpd) -{ - struct atl1e_tpd_desc *use_tpd = NULL; - struct atl1e_tx_buffer *tx_buffer = NULL; - u16 buf_len = skb_headlen(skb); - u16 map_len = 0; - u16 mapped_len = 0; - u16 hdr_len = 0; - u16 nr_frags; - u16 f; - int segment; - int ring_start = adapter->tx_ring.next_to_use; - int ring_end; - - nr_frags = skb_shinfo(skb)->nr_frags; - segment = (tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK; - if (segment) { - /* TSO */ - map_len = hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - use_tpd = tpd; - - tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd); - tx_buffer->length = map_len; - tx_buffer->dma = pci_map_single(adapter->pdev, - skb->data, hdr_len, PCI_DMA_TODEVICE); - if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) - return -ENOSPC; - - ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE); - mapped_len += map_len; - use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); - use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) | - ((cpu_to_le32(tx_buffer->length) & - TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT); - } - - while (mapped_len < buf_len) { - /* mapped_len == 0, means we should use the first tpd, - which is given by caller */ - if (mapped_len == 0) { - use_tpd = tpd; - } else { - use_tpd = atl1e_get_tpd(adapter); - memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc)); - } - tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd); - tx_buffer->skb = NULL; - - tx_buffer->length = map_len = - ((buf_len - mapped_len) >= MAX_TX_BUF_LEN) ? - MAX_TX_BUF_LEN : (buf_len - mapped_len); - tx_buffer->dma = - pci_map_single(adapter->pdev, skb->data + mapped_len, - map_len, PCI_DMA_TODEVICE); - - if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) { - /* We need to unwind the mappings we've done */ - ring_end = adapter->tx_ring.next_to_use; - adapter->tx_ring.next_to_use = ring_start; - while (adapter->tx_ring.next_to_use != ring_end) { - tpd = atl1e_get_tpd(adapter); - tx_buffer = atl1e_get_tx_buffer(adapter, tpd); - pci_unmap_single(adapter->pdev, tx_buffer->dma, - tx_buffer->length, PCI_DMA_TODEVICE); - } - /* Reset the tx rings next pointer */ - adapter->tx_ring.next_to_use = ring_start; - return -ENOSPC; - } - - ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_SINGLE); - mapped_len += map_len; - use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); - use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) | - ((cpu_to_le32(tx_buffer->length) & - TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT); - } - - for (f = 0; f < nr_frags; f++) { - const struct skb_frag_struct *frag; - u16 i; - u16 seg_num; - - frag = &skb_shinfo(skb)->frags[f]; - buf_len = skb_frag_size(frag); - - seg_num = (buf_len + MAX_TX_BUF_LEN - 1) / MAX_TX_BUF_LEN; - for (i = 0; i < seg_num; i++) { - use_tpd = atl1e_get_tpd(adapter); - memcpy(use_tpd, tpd, sizeof(struct atl1e_tpd_desc)); - - tx_buffer = atl1e_get_tx_buffer(adapter, use_tpd); - BUG_ON(tx_buffer->skb); - - tx_buffer->skb = NULL; - tx_buffer->length = - (buf_len > MAX_TX_BUF_LEN) ? - MAX_TX_BUF_LEN : buf_len; - buf_len -= tx_buffer->length; - - tx_buffer->dma = skb_frag_dma_map(&adapter->pdev->dev, - frag, - (i * MAX_TX_BUF_LEN), - tx_buffer->length, - DMA_TO_DEVICE); - - if (dma_mapping_error(&adapter->pdev->dev, tx_buffer->dma)) { - /* We need to unwind the mappings we've done */ - ring_end = adapter->tx_ring.next_to_use; - adapter->tx_ring.next_to_use = ring_start; - while (adapter->tx_ring.next_to_use != ring_end) { - tpd = atl1e_get_tpd(adapter); - tx_buffer = atl1e_get_tx_buffer(adapter, tpd); - dma_unmap_page(&adapter->pdev->dev, tx_buffer->dma, - tx_buffer->length, DMA_TO_DEVICE); - } - - /* Reset the ring next to use pointer */ - adapter->tx_ring.next_to_use = ring_start; - return -ENOSPC; - } - - ATL1E_SET_PCIMAP_TYPE(tx_buffer, ATL1E_TX_PCIMAP_PAGE); - use_tpd->buffer_addr = cpu_to_le64(tx_buffer->dma); - use_tpd->word2 = (use_tpd->word2 & (~TPD_BUFLEN_MASK)) | - ((cpu_to_le32(tx_buffer->length) & - TPD_BUFLEN_MASK) << TPD_BUFLEN_SHIFT); - } - } - - if ((tpd->word3 >> TPD_SEGMENT_EN_SHIFT) & TPD_SEGMENT_EN_MASK) - /* note this one is a tcp header */ - tpd->word3 |= 1 << TPD_HDRFLAG_SHIFT; - /* The last tpd */ - - use_tpd->word3 |= 1 << TPD_EOP_SHIFT; - /* The last buffer info contain the skb address, - so it will be free after unmap */ - tx_buffer->skb = skb; - return 0; -} - -static void atl1e_tx_queue(struct atl1e_adapter *adapter, u16 count, - struct atl1e_tpd_desc *tpd) -{ - struct atl1e_tx_ring *tx_ring = &adapter->tx_ring; - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). */ - wmb(); - AT_WRITE_REG(&adapter->hw, REG_MB_TPD_PROD_IDX, tx_ring->next_to_use); -} - -static netdev_tx_t atl1e_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - unsigned long flags; - u16 tpd_req = 1; - struct atl1e_tpd_desc *tpd; - - if (test_bit(__AT_DOWN, &adapter->flags)) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if (unlikely(skb->len <= 0)) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - tpd_req = atl1e_cal_tdp_req(skb); - if (!spin_trylock_irqsave(&adapter->tx_lock, flags)) - return NETDEV_TX_LOCKED; - - if (atl1e_tpd_avail(adapter) < tpd_req) { - /* no enough descriptor, just stop queue */ - netif_stop_queue(netdev); - spin_unlock_irqrestore(&adapter->tx_lock, flags); - return NETDEV_TX_BUSY; - } - - tpd = atl1e_get_tpd(adapter); - - if (skb_vlan_tag_present(skb)) { - u16 vlan_tag = skb_vlan_tag_get(skb); - u16 atl1e_vlan_tag; - - tpd->word3 |= 1 << TPD_INS_VL_TAG_SHIFT; - AT_VLAN_TAG_TO_TPD_TAG(vlan_tag, atl1e_vlan_tag); - tpd->word2 |= (atl1e_vlan_tag & TPD_VLANTAG_MASK) << - TPD_VLAN_SHIFT; - } - - if (skb->protocol == htons(ETH_P_8021Q)) - tpd->word3 |= 1 << TPD_VL_TAGGED_SHIFT; - - if (skb_network_offset(skb) != ETH_HLEN) - tpd->word3 |= 1 << TPD_ETHTYPE_SHIFT; /* 802.3 frame */ - - /* do TSO and check sum */ - if (atl1e_tso_csum(adapter, skb, tpd) != 0) { - spin_unlock_irqrestore(&adapter->tx_lock, flags); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if (atl1e_tx_map(adapter, skb, tpd)) { - dev_kfree_skb_any(skb); - goto out; - } - - atl1e_tx_queue(adapter, tpd_req, tpd); - - netdev->trans_start = jiffies; /* NETIF_F_LLTX driver :( */ -out: - spin_unlock_irqrestore(&adapter->tx_lock, flags); - return NETDEV_TX_OK; -} - -static void atl1e_free_irq(struct atl1e_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - free_irq(adapter->pdev->irq, netdev); -} - -static int atl1e_request_irq(struct atl1e_adapter *adapter) -{ - struct pci_dev *pdev = adapter->pdev; - struct net_device *netdev = adapter->netdev; - int err = 0; - - err = request_irq(pdev->irq, atl1e_intr, IRQF_SHARED, netdev->name, - netdev); - if (err) { - netdev_dbg(adapter->netdev, - "Unable to allocate interrupt Error: %d\n", err); - return err; - } - netdev_dbg(netdev, "atl1e_request_irq OK\n"); - return err; -} - -int atl1e_up(struct atl1e_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - int err = 0; - u32 val; - - /* hardware has been reset, we need to reload some things */ - err = atl1e_init_hw(&adapter->hw); - if (err) { - err = -EIO; - return err; - } - atl1e_init_ring_ptrs(adapter); - atl1e_set_multi(netdev); - atl1e_restore_vlan(adapter); - - if (atl1e_configure(adapter)) { - err = -EIO; - goto err_up; - } - - clear_bit(__AT_DOWN, &adapter->flags); - napi_enable(&adapter->napi); - atl1e_irq_enable(adapter); - val = AT_READ_REG(&adapter->hw, REG_MASTER_CTRL); - AT_WRITE_REG(&adapter->hw, REG_MASTER_CTRL, - val | MASTER_CTRL_MANUAL_INT); - -err_up: - return err; -} - -void atl1e_down(struct atl1e_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - /* signal that we're down so the interrupt handler does not - * reschedule our watchdog timer */ - set_bit(__AT_DOWN, &adapter->flags); - - netif_stop_queue(netdev); - - /* reset MAC to disable all RX/TX */ - atl1e_reset_hw(&adapter->hw); - msleep(1); - - napi_disable(&adapter->napi); - atl1e_del_timer(adapter); - atl1e_irq_disable(adapter); - - netif_carrier_off(netdev); - adapter->link_speed = SPEED_0; - adapter->link_duplex = -1; - atl1e_clean_tx_ring(adapter); - atl1e_clean_rx_ring(adapter); -} - -/** - * atl1e_open - Called when a network interface is made active - * @netdev: network interface device structure - * - * Returns 0 on success, negative value on failure - * - * The open entry point is called when a network interface is made - * active by the system (IFF_UP). At this point all resources needed - * for transmit and receive operations are allocated, the interrupt - * handler is registered with the OS, the watchdog timer is started, - * and the stack is notified that the interface is ready. - */ -static int atl1e_open(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - int err; - - /* disallow open during test */ - if (test_bit(__AT_TESTING, &adapter->flags)) - return -EBUSY; - - /* allocate rx/tx dma buffer & descriptors */ - atl1e_init_ring_resources(adapter); - err = atl1e_setup_ring_resources(adapter); - if (unlikely(err)) - return err; - - err = atl1e_request_irq(adapter); - if (unlikely(err)) - goto err_req_irq; - - err = atl1e_up(adapter); - if (unlikely(err)) - goto err_up; - - return 0; - -err_up: - atl1e_free_irq(adapter); -err_req_irq: - atl1e_free_ring_resources(adapter); - atl1e_reset_hw(&adapter->hw); - - return err; -} - -/** - * atl1e_close - Disables a network interface - * @netdev: network interface device structure - * - * Returns 0, this is not allowed to fail - * - * The close entry point is called when an interface is de-activated - * by the OS. The hardware is still under the drivers control, but - * needs to be disabled. A global MAC reset is issued to stop the - * hardware, and all transmit and receive resources are freed. - */ -static int atl1e_close(struct net_device *netdev) -{ - struct atl1e_adapter *adapter = netdev_priv(netdev); - - WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); - atl1e_down(adapter); - atl1e_free_irq(adapter); - atl1e_free_ring_resources(adapter); - - return 0; -} - -static int atl1e_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1e_adapter *adapter = netdev_priv(netdev); - struct atl1e_hw *hw = &adapter->hw; - u32 ctrl = 0; - u32 mac_ctrl_data = 0; - u32 wol_ctrl_data = 0; - u16 mii_advertise_data = 0; - u16 mii_bmsr_data = 0; - u16 mii_intr_status_data = 0; - u32 wufc = adapter->wol; - u32 i; -#ifdef CONFIG_PM - int retval = 0; -#endif - - if (netif_running(netdev)) { - WARN_ON(test_bit(__AT_RESETTING, &adapter->flags)); - atl1e_down(adapter); - } - netif_device_detach(netdev); - -#ifdef CONFIG_PM - retval = pci_save_state(pdev); - if (retval) - return retval; -#endif - - if (wufc) { - /* get link status */ - atl1e_read_phy_reg(hw, MII_BMSR, &mii_bmsr_data); - atl1e_read_phy_reg(hw, MII_BMSR, &mii_bmsr_data); - - mii_advertise_data = ADVERTISE_10HALF; - - if ((atl1e_write_phy_reg(hw, MII_CTRL1000, 0) != 0) || - (atl1e_write_phy_reg(hw, - MII_ADVERTISE, mii_advertise_data) != 0) || - (atl1e_phy_commit(hw)) != 0) { - netdev_dbg(adapter->netdev, "set phy register failed\n"); - goto wol_dis; - } - - hw->phy_configured = false; /* re-init PHY when resume */ - - /* turn on magic packet wol */ - if (wufc & AT_WUFC_MAG) - wol_ctrl_data |= WOL_MAGIC_EN | WOL_MAGIC_PME_EN; - - if (wufc & AT_WUFC_LNKC) { - /* if orignal link status is link, just wait for retrive link */ - if (mii_bmsr_data & BMSR_LSTATUS) { - for (i = 0; i < AT_SUSPEND_LINK_TIMEOUT; i++) { - msleep(100); - atl1e_read_phy_reg(hw, MII_BMSR, - &mii_bmsr_data); - if (mii_bmsr_data & BMSR_LSTATUS) - break; - } - - if ((mii_bmsr_data & BMSR_LSTATUS) == 0) - netdev_dbg(adapter->netdev, - "Link may change when suspend\n"); - } - wol_ctrl_data |= WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN; - /* only link up can wake up */ - if (atl1e_write_phy_reg(hw, MII_INT_CTRL, 0x400) != 0) { - netdev_dbg(adapter->netdev, - "read write phy register failed\n"); - goto wol_dis; - } - } - /* clear phy interrupt */ - atl1e_read_phy_reg(hw, MII_INT_STATUS, &mii_intr_status_data); - /* Config MAC Ctrl register */ - mac_ctrl_data = MAC_CTRL_RX_EN; - /* set to 10/100M halt duplex */ - mac_ctrl_data |= MAC_CTRL_SPEED_10_100 << MAC_CTRL_SPEED_SHIFT; - mac_ctrl_data |= (((u32)adapter->hw.preamble_len & - MAC_CTRL_PRMLEN_MASK) << - MAC_CTRL_PRMLEN_SHIFT); - - __atl1e_vlan_mode(netdev->features, &mac_ctrl_data); - - /* magic packet maybe Broadcast&multicast&Unicast frame */ - if (wufc & AT_WUFC_MAG) - mac_ctrl_data |= MAC_CTRL_BC_EN; - - netdev_dbg(adapter->netdev, "suspend MAC=0x%x\n", - mac_ctrl_data); - - AT_WRITE_REG(hw, REG_WOL_CTRL, wol_ctrl_data); - AT_WRITE_REG(hw, REG_MAC_CTRL, mac_ctrl_data); - /* pcie patch */ - ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC); - ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; - AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); - pci_enable_wake(pdev, pci_choose_state(pdev, state), 1); - goto suspend_exit; - } -wol_dis: - - /* WOL disabled */ - AT_WRITE_REG(hw, REG_WOL_CTRL, 0); - - /* pcie patch */ - ctrl = AT_READ_REG(hw, REG_PCIE_PHYMISC); - ctrl |= PCIE_PHYMISC_FORCE_RCV_DET; - AT_WRITE_REG(hw, REG_PCIE_PHYMISC, ctrl); - - atl1e_force_ps(hw); - hw->phy_configured = false; /* re-init PHY when resume */ - - pci_enable_wake(pdev, pci_choose_state(pdev, state), 0); - -suspend_exit: - - if (netif_running(netdev)) - atl1e_free_irq(adapter); - - pci_disable_device(pdev); - - pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -#ifdef CONFIG_PM -static int atl1e_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1e_adapter *adapter = netdev_priv(netdev); - u32 err; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - - err = pci_enable_device(pdev); - if (err) { - netdev_err(adapter->netdev, - "Cannot enable PCI device from suspend\n"); - return err; - } - - pci_set_master(pdev); - - AT_READ_REG(&adapter->hw, REG_WOL_CTRL); /* clear WOL status */ - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - AT_WRITE_REG(&adapter->hw, REG_WOL_CTRL, 0); - - if (netif_running(netdev)) { - err = atl1e_request_irq(adapter); - if (err) - return err; - } - - atl1e_reset_hw(&adapter->hw); - - if (netif_running(netdev)) - atl1e_up(adapter); - - netif_device_attach(netdev); - - return 0; -} -#endif - -static void atl1e_shutdown(struct pci_dev *pdev) -{ - atl1e_suspend(pdev, PMSG_SUSPEND); -} - -static const struct net_device_ops atl1e_netdev_ops = { - .ndo_open = atl1e_open, - .ndo_stop = atl1e_close, - .ndo_start_xmit = atl1e_xmit_frame, - .ndo_get_stats = atl1e_get_stats, - .ndo_set_rx_mode = atl1e_set_multi, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = atl1e_set_mac_addr, - .ndo_fix_features = atl1e_fix_features, - .ndo_set_features = atl1e_set_features, - .ndo_change_mtu = atl1e_change_mtu, - .ndo_do_ioctl = atl1e_ioctl, - .ndo_tx_timeout = atl1e_tx_timeout, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = atl1e_netpoll, -#endif - -}; - -static int atl1e_init_netdev(struct net_device *netdev, struct pci_dev *pdev) -{ - SET_NETDEV_DEV(netdev, &pdev->dev); - pci_set_drvdata(pdev, netdev); - - netdev->netdev_ops = &atl1e_netdev_ops; - - netdev->watchdog_timeo = AT_TX_WATCHDOG; - atl1e_set_ethtool_ops(netdev); - - netdev->hw_features = NETIF_F_SG | NETIF_F_HW_CSUM | NETIF_F_TSO | - NETIF_F_HW_VLAN_CTAG_RX; - netdev->features = netdev->hw_features | NETIF_F_LLTX | - NETIF_F_HW_VLAN_CTAG_TX; - /* not enabled by default */ - netdev->hw_features |= NETIF_F_RXALL | NETIF_F_RXFCS; - return 0; -} - -/** - * atl1e_probe - Device Initialization Routine - * @pdev: PCI device information struct - * @ent: entry in atl1e_pci_tbl - * - * Returns 0 on success, negative on failure - * - * atl1e_probe initializes an adapter identified by a pci_dev structure. - * The OS initialization, configuring of the adapter private structure, - * and a hardware reset occur. - */ -static int atl1e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct atl1e_adapter *adapter = NULL; - static int cards_found; - - int err = 0; - - err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "cannot enable PCI device\n"); - return err; - } - - /* - * The atl1e chip can DMA to 64-bit addresses, but it uses a single - * shared register for the high 32 bits, so only a single, aligned, - * 4 GB physical address range can be used at a time. - * - * Supporting 64-bit DMA on this hardware is more trouble than it's - * worth. It is far easier to limit to 32-bit DMA than update - * various kernel subsystems to support the mechanics required by a - * fixed-high-32-bit system. - */ - if ((pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) != 0) || - (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)) != 0)) { - dev_err(&pdev->dev, "No usable DMA configuration,aborting\n"); - goto err_dma; - } - - err = pci_request_regions(pdev, atl1e_driver_name); - if (err) { - dev_err(&pdev->dev, "cannot obtain PCI resources\n"); - goto err_pci_reg; - } - - pci_set_master(pdev); - - netdev = alloc_etherdev(sizeof(struct atl1e_adapter)); - if (netdev == NULL) { - err = -ENOMEM; - goto err_alloc_etherdev; - } - - err = atl1e_init_netdev(netdev, pdev); - if (err) { - netdev_err(netdev, "init netdevice failed\n"); - goto err_init_netdev; - } - adapter = netdev_priv(netdev); - adapter->bd_number = cards_found; - adapter->netdev = netdev; - adapter->pdev = pdev; - adapter->hw.adapter = adapter; - adapter->hw.hw_addr = pci_iomap(pdev, BAR_0, 0); - if (!adapter->hw.hw_addr) { - err = -EIO; - netdev_err(netdev, "cannot map device registers\n"); - goto err_ioremap; - } - - /* init mii data */ - adapter->mii.dev = netdev; - adapter->mii.mdio_read = atl1e_mdio_read; - adapter->mii.mdio_write = atl1e_mdio_write; - adapter->mii.phy_id_mask = 0x1f; - adapter->mii.reg_num_mask = MDIO_REG_ADDR_MASK; - - netif_napi_add(netdev, &adapter->napi, atl1e_clean, 64); - - setup_timer(&adapter->phy_config_timer, atl1e_phy_config, - (unsigned long)adapter); - - /* get user settings */ - atl1e_check_options(adapter); - /* - * Mark all PCI regions associated with PCI device - * pdev as being reserved by owner atl1e_driver_name - * Enables bus-mastering on the device and calls - * pcibios_set_master to do the needed arch specific settings - */ - atl1e_setup_pcicmd(pdev); - /* setup the private structure */ - err = atl1e_sw_init(adapter); - if (err) { - netdev_err(netdev, "net device private data init failed\n"); - goto err_sw_init; - } - - /* Init GPHY as early as possible due to power saving issue */ - atl1e_phy_init(&adapter->hw); - /* reset the controller to - * put the device in a known good starting state */ - err = atl1e_reset_hw(&adapter->hw); - if (err) { - err = -EIO; - goto err_reset; - } - - if (atl1e_read_mac_addr(&adapter->hw) != 0) { - err = -EIO; - netdev_err(netdev, "get mac address failed\n"); - goto err_eeprom; - } - - memcpy(netdev->dev_addr, adapter->hw.mac_addr, netdev->addr_len); - netdev_dbg(netdev, "mac address : %pM\n", adapter->hw.mac_addr); - - INIT_WORK(&adapter->reset_task, atl1e_reset_task); - INIT_WORK(&adapter->link_chg_task, atl1e_link_chg_task); - netif_set_gso_max_size(netdev, MAX_TSO_SEG_SIZE); - err = register_netdev(netdev); - if (err) { - netdev_err(netdev, "register netdevice failed\n"); - goto err_register; - } - - /* assume we have no link for now */ - netif_stop_queue(netdev); - netif_carrier_off(netdev); - - cards_found++; - - return 0; - -err_reset: -err_register: -err_sw_init: -err_eeprom: - pci_iounmap(pdev, adapter->hw.hw_addr); -err_init_netdev: -err_ioremap: - free_netdev(netdev); -err_alloc_etherdev: - pci_release_regions(pdev); -err_pci_reg: -err_dma: - pci_disable_device(pdev); - return err; -} - -/** - * atl1e_remove - Device Removal Routine - * @pdev: PCI device information struct - * - * atl1e_remove is called by the PCI subsystem to alert the driver - * that it should release a PCI device. The could be caused by a - * Hot-Plug event, or because the driver is going to be removed from - * memory. - */ -static void atl1e_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1e_adapter *adapter = netdev_priv(netdev); - - /* - * flush_scheduled work may reschedule our watchdog task, so - * explicitly disable watchdog tasks from being rescheduled - */ - set_bit(__AT_DOWN, &adapter->flags); - - atl1e_del_timer(adapter); - atl1e_cancel_work(adapter); - - unregister_netdev(netdev); - atl1e_free_ring_resources(adapter); - atl1e_force_ps(&adapter->hw); - pci_iounmap(pdev, adapter->hw.hw_addr); - pci_release_regions(pdev); - free_netdev(netdev); - pci_disable_device(pdev); -} - -/** - * atl1e_io_error_detected - called when PCI error is detected - * @pdev: Pointer to PCI device - * @state: The current pci connection state - * - * This function is called after a PCI bus error affecting - * this device has been detected. - */ -static pci_ers_result_t -atl1e_io_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1e_adapter *adapter = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - atl1e_down(adapter); - - pci_disable_device(pdev); - - /* Request a slot slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * atl1e_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch, as if from a cold-boot. Implementation - * resembles the first-half of the e1000_resume routine. - */ -static pci_ers_result_t atl1e_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1e_adapter *adapter = netdev_priv(netdev); - - if (pci_enable_device(pdev)) { - netdev_err(adapter->netdev, - "Cannot re-enable PCI device after reset\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - atl1e_reset_hw(&adapter->hw); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * atl1e_io_resume - called when traffic can start flowing again. - * @pdev: Pointer to PCI device - * - * This callback is called when the error recovery driver tells us that - * its OK to resume normal operation. Implementation resembles the - * second-half of the atl1e_resume routine. - */ -static void atl1e_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct atl1e_adapter *adapter = netdev_priv(netdev); - - if (netif_running(netdev)) { - if (atl1e_up(adapter)) { - netdev_err(adapter->netdev, - "can't bring device back up after reset\n"); - return; - } - } - - netif_device_attach(netdev); -} - -static const struct pci_error_handlers atl1e_err_handler = { - .error_detected = atl1e_io_error_detected, - .slot_reset = atl1e_io_slot_reset, - .resume = atl1e_io_resume, -}; - -static struct pci_driver atl1e_driver = { - .name = atl1e_driver_name, - .id_table = atl1e_pci_tbl, - .probe = atl1e_probe, - .remove = atl1e_remove, - /* Power Management Hooks */ -#ifdef CONFIG_PM - .suspend = atl1e_suspend, - .resume = atl1e_resume, -#endif - .shutdown = atl1e_shutdown, - .err_handler = &atl1e_err_handler -}; - -module_pci_driver(atl1e_driver); diff --git a/addons/atl1e/src/4.4.180/atl1e_param.c b/addons/atl1e/src/4.4.180/atl1e_param.c deleted file mode 100644 index fa314282..00000000 --- a/addons/atl1e/src/4.4.180/atl1e_param.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * Copyright(c) 2007 Atheros Corporation. All rights reserved. - * - * Derived from Intel e1000 driver - * Copyright(c) 1999 - 2005 Intel Corporation. All rights reserved. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the Free - * Software Foundation; either version 2 of the License, or (at your option) - * any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., 59 - * Temple Place - Suite 330, Boston, MA 02111-1307, USA. - */ - -#include - -#include "atl1e.h" - -/* This is the only thing that needs to be changed to adjust the - * maximum number of ports that the driver can manage. - */ - -#define ATL1E_MAX_NIC 32 - -#define OPTION_UNSET -1 -#define OPTION_DISABLED 0 -#define OPTION_ENABLED 1 - -/* All parameters are treated the same, as an integer array of values. - * This macro just reduces the need to repeat the same declaration code - * over and over (plus this helps to avoid typo bugs). - */ -#define ATL1E_PARAM_INIT { [0 ... ATL1E_MAX_NIC] = OPTION_UNSET } - -#define ATL1E_PARAM(x, desc) \ - static int x[ATL1E_MAX_NIC + 1] = ATL1E_PARAM_INIT; \ - static unsigned int num_##x; \ - module_param_array_named(x, x, int, &num_##x, 0); \ - MODULE_PARM_DESC(x, desc); - -/* Transmit Memory count - * - * Valid Range: 64-2048 - * - * Default Value: 128 - */ -#define ATL1E_MIN_TX_DESC_CNT 32 -#define ATL1E_MAX_TX_DESC_CNT 1020 -#define ATL1E_DEFAULT_TX_DESC_CNT 128 -ATL1E_PARAM(tx_desc_cnt, "Transmit description count"); - -/* Receive Memory Block Count - * - * Valid Range: 16-512 - * - * Default Value: 128 - */ -#define ATL1E_MIN_RX_MEM_SIZE 8 /* 8KB */ -#define ATL1E_MAX_RX_MEM_SIZE 1024 /* 1MB */ -#define ATL1E_DEFAULT_RX_MEM_SIZE 256 /* 128KB */ -ATL1E_PARAM(rx_mem_size, "memory size of rx buffer(KB)"); - -/* User Specified MediaType Override - * - * Valid Range: 0-5 - * - 0 - auto-negotiate at all supported speeds - * - 1 - only link at 100Mbps Full Duplex - * - 2 - only link at 100Mbps Half Duplex - * - 3 - only link at 10Mbps Full Duplex - * - 4 - only link at 10Mbps Half Duplex - * Default Value: 0 - */ - -ATL1E_PARAM(media_type, "MediaType Select"); - -/* Interrupt Moderate Timer in units of 2 us - * - * Valid Range: 10-65535 - * - * Default Value: 45000(90ms) - */ -#define INT_MOD_DEFAULT_CNT 100 /* 200us */ -#define INT_MOD_MAX_CNT 65000 -#define INT_MOD_MIN_CNT 50 -ATL1E_PARAM(int_mod_timer, "Interrupt Moderator Timer"); - -#define AUTONEG_ADV_DEFAULT 0x2F -#define AUTONEG_ADV_MASK 0x2F -#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL - -#define FLASH_VENDOR_DEFAULT 0 -#define FLASH_VENDOR_MIN 0 -#define FLASH_VENDOR_MAX 2 - -struct atl1e_option { - enum { enable_option, range_option, list_option } type; - char *name; - char *err; - int def; - union { - struct { /* range_option info */ - int min; - int max; - } r; - struct { /* list_option info */ - int nr; - struct atl1e_opt_list { int i; char *str; } *p; - } l; - } arg; -}; - -static int atl1e_validate_option(int *value, struct atl1e_option *opt, - struct atl1e_adapter *adapter) -{ - if (*value == OPTION_UNSET) { - *value = opt->def; - return 0; - } - - switch (opt->type) { - case enable_option: - switch (*value) { - case OPTION_ENABLED: - netdev_info(adapter->netdev, - "%s Enabled\n", opt->name); - return 0; - case OPTION_DISABLED: - netdev_info(adapter->netdev, - "%s Disabled\n", opt->name); - return 0; - } - break; - case range_option: - if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { - netdev_info(adapter->netdev, "%s set to %i\n", - opt->name, *value); - return 0; - } - break; - case list_option:{ - int i; - struct atl1e_opt_list *ent; - - for (i = 0; i < opt->arg.l.nr; i++) { - ent = &opt->arg.l.p[i]; - if (*value == ent->i) { - if (ent->str[0] != '\0') - netdev_info(adapter->netdev, - "%s\n", ent->str); - return 0; - } - } - break; - } - default: - BUG(); - } - - netdev_info(adapter->netdev, "Invalid %s specified (%i) %s\n", - opt->name, *value, opt->err); - *value = opt->def; - return -1; -} - -/** - * atl1e_check_options - Range Checking for Command Line Parameters - * @adapter: board private structure - * - * This routine checks all command line parameters for valid user - * input. If an invalid value is given, or if no user specified - * value exists, a default value is used. The final value is stored - * in a variable in the adapter structure. - */ -void atl1e_check_options(struct atl1e_adapter *adapter) -{ - int bd = adapter->bd_number; - - if (bd >= ATL1E_MAX_NIC) { - netdev_notice(adapter->netdev, - "no configuration for board #%i\n", bd); - netdev_notice(adapter->netdev, - "Using defaults for all values\n"); - } - - { /* Transmit Ring Size */ - struct atl1e_option opt = { - .type = range_option, - .name = "Transmit Ddescription Count", - .err = "using default of " - __MODULE_STRING(ATL1E_DEFAULT_TX_DESC_CNT), - .def = ATL1E_DEFAULT_TX_DESC_CNT, - .arg = { .r = { .min = ATL1E_MIN_TX_DESC_CNT, - .max = ATL1E_MAX_TX_DESC_CNT} } - }; - int val; - if (num_tx_desc_cnt > bd) { - val = tx_desc_cnt[bd]; - atl1e_validate_option(&val, &opt, adapter); - adapter->tx_ring.count = (u16) val & 0xFFFC; - } else - adapter->tx_ring.count = (u16)opt.def; - } - - { /* Receive Memory Block Count */ - struct atl1e_option opt = { - .type = range_option, - .name = "Memory size of rx buffer(KB)", - .err = "using default of " - __MODULE_STRING(ATL1E_DEFAULT_RX_MEM_SIZE), - .def = ATL1E_DEFAULT_RX_MEM_SIZE, - .arg = { .r = { .min = ATL1E_MIN_RX_MEM_SIZE, - .max = ATL1E_MAX_RX_MEM_SIZE} } - }; - int val; - if (num_rx_mem_size > bd) { - val = rx_mem_size[bd]; - atl1e_validate_option(&val, &opt, adapter); - adapter->rx_ring.page_size = (u32)val * 1024; - } else { - adapter->rx_ring.page_size = (u32)opt.def * 1024; - } - } - - { /* Interrupt Moderate Timer */ - struct atl1e_option opt = { - .type = range_option, - .name = "Interrupt Moderate Timer", - .err = "using default of " - __MODULE_STRING(INT_MOD_DEFAULT_CNT), - .def = INT_MOD_DEFAULT_CNT, - .arg = { .r = { .min = INT_MOD_MIN_CNT, - .max = INT_MOD_MAX_CNT} } - } ; - int val; - if (num_int_mod_timer > bd) { - val = int_mod_timer[bd]; - atl1e_validate_option(&val, &opt, adapter); - adapter->hw.imt = (u16) val; - } else - adapter->hw.imt = (u16)(opt.def); - } - - { /* MediaType */ - struct atl1e_option opt = { - .type = range_option, - .name = "Speed/Duplex Selection", - .err = "using default of " - __MODULE_STRING(MEDIA_TYPE_AUTO_SENSOR), - .def = MEDIA_TYPE_AUTO_SENSOR, - .arg = { .r = { .min = MEDIA_TYPE_AUTO_SENSOR, - .max = MEDIA_TYPE_10M_HALF} } - } ; - int val; - if (num_media_type > bd) { - val = media_type[bd]; - atl1e_validate_option(&val, &opt, adapter); - adapter->hw.media_type = (u16) val; - } else - adapter->hw.media_type = (u16)(opt.def); - - } -} diff --git a/addons/compile-addons.sh b/addons/compile-addons.sh deleted file mode 100755 index aff1a862..00000000 --- a/addons/compile-addons.sh +++ /dev/null @@ -1,186 +0,0 @@ -#!/usr/bin/env bash - -set -e - -TMP_PATH="/tmp" -DEST_PATH="../files/board/arpl/p3/addons" - -############################################################################### -function trap_cancel() { - echo "Press Control+C once more terminate the process (or wait 2s for it to restart)" - sleep 2 || exit 1 -} -trap trap_cancel SIGINT SIGTERM - -############################################################################### -function die() { - echo -e "\033[1;31m$@\033[0m" - exit 1 -} - -############################################################################### -# -# 1 - Path of key -function hasConfigKey() { - [ "`yq eval '.'${1}' | has("'${2}'")' "${3}"`" == "true" ] && return 0 || return 1 -} - -############################################################################### -# Read key value from yaml config file -# 1 - Path of key -# 2 - Path of yaml config file -# Return Value -function readConfigKey() { - RESULT=`yq eval '.'${1}' | explode(.)' "${2}"` - [ "${RESULT}" == "null" ] && echo "" || echo ${RESULT} -} - -############################################################################### -# Read Entries as map(key=value) from yaml config file -# 1 - Path of key -# 2 - Path of yaml config file -# Returns map of values -function readConfigMap() { - yq eval '.'${1}' | explode(.) | to_entries | map([.key, .value] | join("=")) | .[]' "${2}" -} - -############################################################################### -# Read an array from yaml config file -# 1 - Path of key -# 2 - Path of yaml config file -# Returns array/map of values -function readConfigArray() { - yq eval '.'${1} "${2}" -} - -############################################################################### -# Read Entries as array from yaml config file -# 1 - Path of key -# 2 - Path of yaml config file -# Returns array of values -function readConfigEntriesArray() { - yq eval '.'${1}' | explode(.) | to_entries | map([.key])[] | .[]' "${2}" -} - - -############################################################################### -function compile-addon() { - MANIFEST="${1}/manifest.yml" - [ ! -f "${MANIFEST}" ] && die "${MANIFEST} not found" - echo -e "\033[7mProcessing manifest ${MANIFEST}\033[0m" - OUT_PATH="${TMP_PATH}/${1}" - rm -rf "${OUT_PATH}" - mkdir -p "${OUT_PATH}" - VER=`readConfigKey "version" "${MANIFEST}"` - [ ${VER} -ne 1 ] && die "Error, version ${VER} of manifest not suported" - cp "${MANIFEST}" "${OUT_PATH}" - # Check if exist files for all platforms - if hasConfigKey "" "all" "${MANIFEST}"; then - echo -e "\033[1;32m Processing 'all' section\033[0m" - mkdir -p "${OUT_PATH}/all/root" - HAS_FILES=0 - # Get name of script to install, if defined. This script has low priority - INSTALL_SCRIPT="`readConfigKey "all.install-script" "${MANIFEST}"`" - if [ -n "${INSTALL_SCRIPT}" ]; then - if [ -f "${1}/${INSTALL_SCRIPT}" ]; then - echo -e "\033[1;35m Copying install script ${INSTALL_SCRIPT}\033[0m" - cp "${1}/${INSTALL_SCRIPT}" "${OUT_PATH}/all/install.sh" - HAS_FILES=1 - else - echo -e "\033[1;33m WARNING: install script '${INSTALL_SCRIPT}' not found\033[0m" - fi - fi - # Get folder name for copy - COPY_PATH="`readConfigKey "all.copy" "${MANIFEST}"`" - # If folder exists, copy - if [ -n "${COPY_PATH}" ]; then - if [ -d "${1}/${COPY_PATH}" ]; then - echo -e "\033[1;35m Copying folder '${COPY_PATH}'\033[0m" - cp -R "${1}/${COPY_PATH}/"* "${OUT_PATH}/all/root" - HAS_FILES=1 - else - echo -e "\033[1;33m WARNING: folder '${COPY_PATH}' not found\033[0m" - fi - fi - if [ ${HAS_FILES} -eq 1 ]; then - # Create tar gziped - tar caf "${OUT_PATH}/all.tgz" -C "${OUT_PATH}/all" . - echo -e "\033[1;36m Created file '${OUT_PATH}/all.tgz' \033[0m" - fi - # Clean - rm -rf "${OUT_PATH}/all" - fi - unset AVAL_FOR - declare -a AVAL_FOR - for P in `readConfigEntriesArray "available-for" "${MANIFEST}"`; do - AVAL_FOR+=(${P}) - done - [ ${#AVAL_FOR} -eq 0 ] && return - - # Loop in each available platform-kver - for P in ${AVAL_FOR[@]}; do - echo -e "\033[1;32m Processing '${P}' platform-kver section\033[0m" - mkdir -p "${OUT_PATH}/${P}/root" - HAS_FILES=0 - # Get name of script to install, if defined. This script has high priority - INSTALL_SCRIPT="`readConfigKey 'available-for."'${P}'".install-script' "${MANIFEST}"`" - if [ -n "${INSTALL_SCRIPT}" ]; then - if [ -f "${1}/${INSTALL_SCRIPT}" ]; then - echo -e "\033[1;35m Copying install script ${INSTALL_SCRIPT}\033[0m" - cp "${1}/${INSTALL_SCRIPT}" "${OUT_PATH}/${P}/install.sh" - HAS_FILES=1 - else - echo -e "\033[1;33m WARNING: install script '${INSTALL_SCRIPT}' not found\033[0m" - fi - fi - # Get folder name for copy - COPY_PATH="`readConfigKey 'available-for."'${P}'".copy' "${MANIFEST}"`" - # If folder exists, copy - if [ -n "${COPY_PATH}" ]; then - if [ -d "${1}/${COPY_PATH}" ]; then - echo -e "\033[1;35m Copying folder '${COPY_PATH}'\033[0m" - cp -R "${1}/${COPY_PATH}/"* "${OUT_PATH}/${P}/root" - HAS_FILES=1 - else - echo -e "\033[1;33m WARNING: folder '${COPY_PATH}' not found\033[0m" - fi - fi - HAS_MODULES="`readConfigKey 'available-for."'${P}'".modules' "${MANIFEST}"`" - # Check if has modules for compile - if [ "${HAS_MODULES}" = "true" ]; then - echo "Compiling modules" - PLATFORM="`echo ${P} | cut -d'-' -f1`" - KVER="`echo ${P} | cut -d'-' -f2`" - # Compile using docker - docker run --rm -t --user `id -u` -v "${TMP_PATH}":/output \ - -v "${PWD}/${1}/src/${KVER}":/input syno-compiler compile-module ${PLATFORM} - mkdir -p "${OUT_PATH}/${P}/root/modules" - mv "${TMP_PATH}/"*.ko "${OUT_PATH}/${P}/root/modules/" - HAS_FILES=1 - fi - if [ ${HAS_FILES} -eq 1 ]; then - # Create tar gziped - tar caf "${OUT_PATH}/${P}.tgz" -C "${OUT_PATH}/${P}" . - echo -e "\033[1;36m Created file '${P}.tgz' \033[0m" - fi - # Clean - rm -rf "${OUT_PATH}/${P}" - done - # Update files for image - rm -rf "${DEST_PATH}/${1}" - mkdir -p "${DEST_PATH}/${1}" - cp "${OUT_PATH}/"* "${DEST_PATH}/${1}/" -} - -# Main -if [ $# -ge 1 ]; then - for A in $@; do - compile-addon ${A} - done -else - while read D; do - DRIVER=`basename ${D}` - [ "${DRIVER}" = "." ] && continue - compile-addon ${DRIVER} - done < <(find -maxdepth 1 -type d) -fi diff --git a/addons/e1000/install.sh b/addons/e1000/install.sh deleted file mode 100644 index 83efefa8..00000000 --- a/addons/e1000/install.sh +++ /dev/null @@ -1,4 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Installing module for Intel(R) PRO/1000 Gigabit Ethernet adapter" - ${INSMOD} "/modules/e1000.ko" ${PARAMS} -fi diff --git a/addons/e1000/manifest.yml b/addons/e1000/manifest.yml deleted file mode 100644 index 017e1f50..00000000 --- a/addons/e1000/manifest.yml +++ /dev/null @@ -1,29 +0,0 @@ -version: 1 -name: e1000 -description: "Driver for Intel(R) PRO/1000 Gigabit Ethernet adapters" -available-for: - bromolow-3.10.108: - install-script: &script "install.sh" - modules: true - apollolake-4.4.180: - install-script: *script - modules: true - broadwell-4.4.180: - install-script: *script - modules: true - broadwellnk-4.4.180: - install-script: *script - modules: true - denverton-4.4.180: - install-script: *script - modules: true - geminilake-4.4.180: - install-script: *script - modules: true - v1000-4.4.180: - install-script: *script - modules: true - purley-4.4.180: - install-script: *script - modules: true - diff --git a/addons/e1000/src/3.10.108/Makefile b/addons/e1000/src/3.10.108/Makefile deleted file mode 100644 index 59afd9fd..00000000 --- a/addons/e1000/src/3.10.108/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-m += e1000.o -e1000-objs := e1000_main.o e1000_hw.o e1000_ethtool.o e1000_param.o diff --git a/addons/e1000/src/3.10.108/e1000.h b/addons/e1000/src/3.10.108/e1000.h deleted file mode 100644 index 26d9cd59..00000000 --- a/addons/e1000/src/3.10.108/e1000.h +++ /dev/null @@ -1,365 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - - -/* Linux PRO/1000 Ethernet Driver main header file */ - -#ifndef _E1000_H_ -#define _E1000_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BAR_0 0 -#define BAR_1 1 -#define BAR_5 5 - -#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\ - PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} - -struct e1000_adapter; - -#include "e1000_hw.h" - -#define E1000_MAX_INTR 10 - -/* TX/RX descriptor defines */ -#define E1000_DEFAULT_TXD 256 -#define E1000_MAX_TXD 256 -#define E1000_MIN_TXD 48 -#define E1000_MAX_82544_TXD 4096 - -#define E1000_DEFAULT_RXD 256 -#define E1000_MAX_RXD 256 -#define E1000_MIN_RXD 48 -#define E1000_MAX_82544_RXD 4096 - -#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */ -#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */ - -/* this is the size past which hardware will drop packets when setting LPE=0 */ -#define MAXIMUM_ETHERNET_VLAN_SIZE 1522 - -/* Supported Rx Buffer Sizes */ -#define E1000_RXBUFFER_128 128 /* Used for packet split */ -#define E1000_RXBUFFER_256 256 /* Used for packet split */ -#define E1000_RXBUFFER_512 512 -#define E1000_RXBUFFER_1024 1024 -#define E1000_RXBUFFER_2048 2048 -#define E1000_RXBUFFER_4096 4096 -#define E1000_RXBUFFER_8192 8192 -#define E1000_RXBUFFER_16384 16384 - -/* SmartSpeed delimiters */ -#define E1000_SMARTSPEED_DOWNSHIFT 3 -#define E1000_SMARTSPEED_MAX 15 - -/* Packet Buffer allocations */ -#define E1000_PBA_BYTES_SHIFT 0xA -#define E1000_TX_HEAD_ADDR_SHIFT 7 -#define E1000_PBA_TX_MASK 0xFFFF0000 - -/* Flow Control Watermarks */ -#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */ -#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */ - -#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */ - -/* How many Tx Descriptors do we need to call netif_wake_queue ? */ -#define E1000_TX_QUEUE_WAKE 16 -/* How many Rx Buffers do we bundle into one write to the hardware ? */ -#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ - -#define AUTO_ALL_MODES 0 -#define E1000_EEPROM_82544_APM 0x0004 -#define E1000_EEPROM_APME 0x0400 - -#ifndef E1000_MASTER_SLAVE -/* Switch to override PHY master/slave setting */ -#define E1000_MASTER_SLAVE e1000_ms_hw_default -#endif - -#define E1000_MNG_VLAN_NONE (-1) - -/* wrapper around a pointer to a socket buffer, - * so a DMA handle can be stored along with the buffer - */ -struct e1000_buffer { - struct sk_buff *skb; - dma_addr_t dma; - struct page *page; - unsigned long time_stamp; - u16 length; - u16 next_to_watch; - unsigned int segs; - unsigned int bytecount; - u16 mapped_as_page; -}; - -struct e1000_tx_ring { - /* pointer to the descriptor ring memory */ - void *desc; - /* physical address of the descriptor ring */ - dma_addr_t dma; - /* length of descriptor ring in bytes */ - unsigned int size; - /* number of descriptors in the ring */ - unsigned int count; - /* next descriptor to associate a buffer with */ - unsigned int next_to_use; - /* next descriptor to check for DD status bit */ - unsigned int next_to_clean; - /* array of buffer information structs */ - struct e1000_buffer *buffer_info; - - u16 tdh; - u16 tdt; - bool last_tx_tso; -}; - -struct e1000_rx_ring { - /* pointer to the descriptor ring memory */ - void *desc; - /* physical address of the descriptor ring */ - dma_addr_t dma; - /* length of descriptor ring in bytes */ - unsigned int size; - /* number of descriptors in the ring */ - unsigned int count; - /* next descriptor to associate a buffer with */ - unsigned int next_to_use; - /* next descriptor to check for DD status bit */ - unsigned int next_to_clean; - /* array of buffer information structs */ - struct e1000_buffer *buffer_info; - struct sk_buff *rx_skb_top; - - /* cpu for rx queue */ - int cpu; - - u16 rdh; - u16 rdt; -}; - -#define E1000_DESC_UNUSED(R) \ - ((((R)->next_to_clean > (R)->next_to_use) \ - ? 0 : (R)->count) + (R)->next_to_clean - (R)->next_to_use - 1) - -#define E1000_RX_DESC_EXT(R, i) \ - (&(((union e1000_rx_desc_extended *)((R).desc))[i])) -#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) -#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc) -#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) -#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc) - -/* board specific private data structure */ - -struct e1000_adapter { - unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; - u16 mng_vlan_id; - u32 bd_number; - u32 rx_buffer_len; - u32 wol; - u32 smartspeed; - u32 en_mng_pt; - u16 link_speed; - u16 link_duplex; - spinlock_t stats_lock; - unsigned int total_tx_bytes; - unsigned int total_tx_packets; - unsigned int total_rx_bytes; - unsigned int total_rx_packets; - /* Interrupt Throttle Rate */ - u32 itr; - u32 itr_setting; - u16 tx_itr; - u16 rx_itr; - - u8 fc_autoneg; - - /* TX */ - struct e1000_tx_ring *tx_ring; /* One per active queue */ - unsigned int restart_queue; - u32 txd_cmd; - u32 tx_int_delay; - u32 tx_abs_int_delay; - u32 gotcl; - u64 gotcl_old; - u64 tpt_old; - u64 colc_old; - u32 tx_timeout_count; - u32 tx_fifo_head; - u32 tx_head_addr; - u32 tx_fifo_size; - u8 tx_timeout_factor; - atomic_t tx_fifo_stall; - bool pcix_82544; - bool detect_tx_hung; - bool dump_buffers; - - /* RX */ - bool (*clean_rx)(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int *work_done, int work_to_do); - void (*alloc_rx_buf)(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count); - struct e1000_rx_ring *rx_ring; /* One per active queue */ - struct napi_struct napi; - - int num_tx_queues; - int num_rx_queues; - - u64 hw_csum_err; - u64 hw_csum_good; - u32 alloc_rx_buff_failed; - u32 rx_int_delay; - u32 rx_abs_int_delay; - bool rx_csum; - u32 gorcl; - u64 gorcl_old; - - /* OS defined structs */ - struct net_device *netdev; - struct pci_dev *pdev; - - /* structs defined in e1000_hw.h */ - struct e1000_hw hw; - struct e1000_hw_stats stats; - struct e1000_phy_info phy_info; - struct e1000_phy_stats phy_stats; - - u32 test_icr; - struct e1000_tx_ring test_tx_ring; - struct e1000_rx_ring test_rx_ring; - - int msg_enable; - - /* to not mess up cache alignment, always add to the bottom */ - bool tso_force; - bool smart_power_down; /* phy smart power down */ - bool quad_port_a; - unsigned long flags; - u32 eeprom_wol; - - /* for ioport free */ - int bars; - int need_ioport; - - bool discarding; - - struct work_struct reset_task; - struct delayed_work watchdog_task; - struct delayed_work fifo_stall_task; - struct delayed_work phy_info_task; - - struct mutex mutex; -}; - -enum e1000_state_t { - __E1000_TESTING, - __E1000_RESETTING, - __E1000_DOWN -}; - -#undef pr_fmt -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -extern struct net_device *e1000_get_hw_dev(struct e1000_hw *hw); -#define e_dbg(format, arg...) \ - netdev_dbg(e1000_get_hw_dev(hw), format, ## arg) -#define e_err(msglvl, format, arg...) \ - netif_err(adapter, msglvl, adapter->netdev, format, ## arg) -#define e_info(msglvl, format, arg...) \ - netif_info(adapter, msglvl, adapter->netdev, format, ## arg) -#define e_warn(msglvl, format, arg...) \ - netif_warn(adapter, msglvl, adapter->netdev, format, ## arg) -#define e_notice(msglvl, format, arg...) \ - netif_notice(adapter, msglvl, adapter->netdev, format, ## arg) -#define e_dev_info(format, arg...) \ - dev_info(&adapter->pdev->dev, format, ## arg) -#define e_dev_warn(format, arg...) \ - dev_warn(&adapter->pdev->dev, format, ## arg) -#define e_dev_err(format, arg...) \ - dev_err(&adapter->pdev->dev, format, ## arg) - -extern char e1000_driver_name[]; -extern const char e1000_driver_version[]; - -extern int e1000_up(struct e1000_adapter *adapter); -extern void e1000_down(struct e1000_adapter *adapter); -extern void e1000_reinit_locked(struct e1000_adapter *adapter); -extern void e1000_reset(struct e1000_adapter *adapter); -extern int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx); -extern int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); -extern int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); -extern void e1000_free_all_rx_resources(struct e1000_adapter *adapter); -extern void e1000_free_all_tx_resources(struct e1000_adapter *adapter); -extern void e1000_update_stats(struct e1000_adapter *adapter); -extern bool e1000_has_link(struct e1000_adapter *adapter); -extern void e1000_power_up_phy(struct e1000_adapter *); -extern void e1000_set_ethtool_ops(struct net_device *netdev); -extern void e1000_check_options(struct e1000_adapter *adapter); -extern char *e1000_get_hw_dev_name(struct e1000_hw *hw); - -#endif /* _E1000_H_ */ diff --git a/addons/e1000/src/3.10.108/e1000_ethtool.c b/addons/e1000/src/3.10.108/e1000_ethtool.c deleted file mode 100644 index 82a967c9..00000000 --- a/addons/e1000/src/3.10.108/e1000_ethtool.c +++ /dev/null @@ -1,1909 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* ethtool support for e1000 */ - -#include "e1000.h" -#include - -enum {NETDEV_STATS, E1000_STATS}; - -struct e1000_stats { - char stat_string[ETH_GSTRING_LEN]; - int type; - int sizeof_stat; - int stat_offset; -}; - -#define E1000_STAT(m) E1000_STATS, \ - sizeof(((struct e1000_adapter *)0)->m), \ - offsetof(struct e1000_adapter, m) -#define E1000_NETDEV_STAT(m) NETDEV_STATS, \ - sizeof(((struct net_device *)0)->m), \ - offsetof(struct net_device, m) - -static const struct e1000_stats e1000_gstrings_stats[] = { - { "rx_packets", E1000_STAT(stats.gprc) }, - { "tx_packets", E1000_STAT(stats.gptc) }, - { "rx_bytes", E1000_STAT(stats.gorcl) }, - { "tx_bytes", E1000_STAT(stats.gotcl) }, - { "rx_broadcast", E1000_STAT(stats.bprc) }, - { "tx_broadcast", E1000_STAT(stats.bptc) }, - { "rx_multicast", E1000_STAT(stats.mprc) }, - { "tx_multicast", E1000_STAT(stats.mptc) }, - { "rx_errors", E1000_STAT(stats.rxerrc) }, - { "tx_errors", E1000_STAT(stats.txerrc) }, - { "tx_dropped", E1000_NETDEV_STAT(stats.tx_dropped) }, - { "multicast", E1000_STAT(stats.mprc) }, - { "collisions", E1000_STAT(stats.colc) }, - { "rx_length_errors", E1000_STAT(stats.rlerrc) }, - { "rx_over_errors", E1000_NETDEV_STAT(stats.rx_over_errors) }, - { "rx_crc_errors", E1000_STAT(stats.crcerrs) }, - { "rx_frame_errors", E1000_NETDEV_STAT(stats.rx_frame_errors) }, - { "rx_no_buffer_count", E1000_STAT(stats.rnbc) }, - { "rx_missed_errors", E1000_STAT(stats.mpc) }, - { "tx_aborted_errors", E1000_STAT(stats.ecol) }, - { "tx_carrier_errors", E1000_STAT(stats.tncrs) }, - { "tx_fifo_errors", E1000_NETDEV_STAT(stats.tx_fifo_errors) }, - { "tx_heartbeat_errors", E1000_NETDEV_STAT(stats.tx_heartbeat_errors) }, - { "tx_window_errors", E1000_STAT(stats.latecol) }, - { "tx_abort_late_coll", E1000_STAT(stats.latecol) }, - { "tx_deferred_ok", E1000_STAT(stats.dc) }, - { "tx_single_coll_ok", E1000_STAT(stats.scc) }, - { "tx_multi_coll_ok", E1000_STAT(stats.mcc) }, - { "tx_timeout_count", E1000_STAT(tx_timeout_count) }, - { "tx_restart_queue", E1000_STAT(restart_queue) }, - { "rx_long_length_errors", E1000_STAT(stats.roc) }, - { "rx_short_length_errors", E1000_STAT(stats.ruc) }, - { "rx_align_errors", E1000_STAT(stats.algnerrc) }, - { "tx_tcp_seg_good", E1000_STAT(stats.tsctc) }, - { "tx_tcp_seg_failed", E1000_STAT(stats.tsctfc) }, - { "rx_flow_control_xon", E1000_STAT(stats.xonrxc) }, - { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) }, - { "tx_flow_control_xon", E1000_STAT(stats.xontxc) }, - { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) }, - { "rx_long_byte_count", E1000_STAT(stats.gorcl) }, - { "rx_csum_offload_good", E1000_STAT(hw_csum_good) }, - { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }, - { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) }, - { "tx_smbus", E1000_STAT(stats.mgptc) }, - { "rx_smbus", E1000_STAT(stats.mgprc) }, - { "dropped_smbus", E1000_STAT(stats.mgpdc) }, -}; - -#define E1000_QUEUE_STATS_LEN 0 -#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats) -#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN) -static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { - "Register test (offline)", "Eeprom test (offline)", - "Interrupt test (offline)", "Loopback test (offline)", - "Link test (on/offline)" -}; -#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test) - -static int e1000_get_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - if (hw->media_type == e1000_media_type_copper) { - - ecmd->supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full| - SUPPORTED_Autoneg | - SUPPORTED_TP); - ecmd->advertising = ADVERTISED_TP; - - if (hw->autoneg == 1) { - ecmd->advertising |= ADVERTISED_Autoneg; - /* the e1000 autoneg seems to match ethtool nicely */ - ecmd->advertising |= hw->autoneg_advertised; - } - - ecmd->port = PORT_TP; - ecmd->phy_address = hw->phy_addr; - - if (hw->mac_type == e1000_82543) - ecmd->transceiver = XCVR_EXTERNAL; - else - ecmd->transceiver = XCVR_INTERNAL; - - } else { - ecmd->supported = (SUPPORTED_1000baseT_Full | - SUPPORTED_FIBRE | - SUPPORTED_Autoneg); - - ecmd->advertising = (ADVERTISED_1000baseT_Full | - ADVERTISED_FIBRE | - ADVERTISED_Autoneg); - - ecmd->port = PORT_FIBRE; - - if (hw->mac_type >= e1000_82545) - ecmd->transceiver = XCVR_INTERNAL; - else - ecmd->transceiver = XCVR_EXTERNAL; - } - - if (er32(STATUS) & E1000_STATUS_LU) { - - e1000_get_speed_and_duplex(hw, &adapter->link_speed, - &adapter->link_duplex); - ethtool_cmd_speed_set(ecmd, adapter->link_speed); - - /* unfortunately FULL_DUPLEX != DUPLEX_FULL - * and HALF_DUPLEX != DUPLEX_HALF - */ - if (adapter->link_duplex == FULL_DUPLEX) - ecmd->duplex = DUPLEX_FULL; - else - ecmd->duplex = DUPLEX_HALF; - } else { - ethtool_cmd_speed_set(ecmd, -1); - ecmd->duplex = -1; - } - - ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) || - hw->autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; - - /* MDI-X => 1; MDI => 0 */ - if ((hw->media_type == e1000_media_type_copper) && - netif_carrier_ok(netdev)) - ecmd->eth_tp_mdix = (!!adapter->phy_info.mdix_mode ? - ETH_TP_MDI_X : ETH_TP_MDI); - else - ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; - - if (hw->mdix == AUTO_ALL_MODES) - ecmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; - else - ecmd->eth_tp_mdix_ctrl = hw->mdix; - return 0; -} - -static int e1000_set_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - /* MDI setting is only allowed when autoneg enabled because - * some hardware doesn't allow MDI setting when speed or - * duplex is forced. - */ - if (ecmd->eth_tp_mdix_ctrl) { - if (hw->media_type != e1000_media_type_copper) - return -EOPNOTSUPP; - - if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) && - (ecmd->autoneg != AUTONEG_ENABLE)) { - e_err(drv, "forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n"); - return -EINVAL; - } - } - - while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) - msleep(1); - - if (ecmd->autoneg == AUTONEG_ENABLE) { - hw->autoneg = 1; - if (hw->media_type == e1000_media_type_fiber) - hw->autoneg_advertised = ADVERTISED_1000baseT_Full | - ADVERTISED_FIBRE | - ADVERTISED_Autoneg; - else - hw->autoneg_advertised = ecmd->advertising | - ADVERTISED_TP | - ADVERTISED_Autoneg; - ecmd->advertising = hw->autoneg_advertised; - } else { - u32 speed = ethtool_cmd_speed(ecmd); - /* calling this overrides forced MDI setting */ - if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) { - clear_bit(__E1000_RESETTING, &adapter->flags); - return -EINVAL; - } - } - - /* MDI-X => 2; MDI => 1; Auto => 3 */ - if (ecmd->eth_tp_mdix_ctrl) { - if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) - hw->mdix = AUTO_ALL_MODES; - else - hw->mdix = ecmd->eth_tp_mdix_ctrl; - } - - /* reset the link */ - - if (netif_running(adapter->netdev)) { - e1000_down(adapter); - e1000_up(adapter); - } else - e1000_reset(adapter); - - clear_bit(__E1000_RESETTING, &adapter->flags); - return 0; -} - -static u32 e1000_get_link(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - /* If the link is not reported up to netdev, interrupts are disabled, - * and so the physical link state may have changed since we last - * looked. Set get_link_status to make sure that the true link - * state is interrogated, rather than pulling a cached and possibly - * stale link state from the driver. - */ - if (!netif_carrier_ok(netdev)) - adapter->hw.get_link_status = 1; - - return e1000_has_link(adapter); -} - -static void e1000_get_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - pause->autoneg = - (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); - - if (hw->fc == E1000_FC_RX_PAUSE) - pause->rx_pause = 1; - else if (hw->fc == E1000_FC_TX_PAUSE) - pause->tx_pause = 1; - else if (hw->fc == E1000_FC_FULL) { - pause->rx_pause = 1; - pause->tx_pause = 1; - } -} - -static int e1000_set_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - int retval = 0; - - adapter->fc_autoneg = pause->autoneg; - - while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) - msleep(1); - - if (pause->rx_pause && pause->tx_pause) - hw->fc = E1000_FC_FULL; - else if (pause->rx_pause && !pause->tx_pause) - hw->fc = E1000_FC_RX_PAUSE; - else if (!pause->rx_pause && pause->tx_pause) - hw->fc = E1000_FC_TX_PAUSE; - else if (!pause->rx_pause && !pause->tx_pause) - hw->fc = E1000_FC_NONE; - - hw->original_fc = hw->fc; - - if (adapter->fc_autoneg == AUTONEG_ENABLE) { - if (netif_running(adapter->netdev)) { - e1000_down(adapter); - e1000_up(adapter); - } else - e1000_reset(adapter); - } else - retval = ((hw->media_type == e1000_media_type_fiber) ? - e1000_setup_link(hw) : e1000_force_mac_fc(hw)); - - clear_bit(__E1000_RESETTING, &adapter->flags); - return retval; -} - -static u32 e1000_get_msglevel(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - return adapter->msg_enable; -} - -static void e1000_set_msglevel(struct net_device *netdev, u32 data) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - adapter->msg_enable = data; -} - -static int e1000_get_regs_len(struct net_device *netdev) -{ -#define E1000_REGS_LEN 32 - return E1000_REGS_LEN * sizeof(u32); -} - -static void e1000_get_regs(struct net_device *netdev, struct ethtool_regs *regs, - void *p) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 *regs_buff = p; - u16 phy_data; - - memset(p, 0, E1000_REGS_LEN * sizeof(u32)); - - regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; - - regs_buff[0] = er32(CTRL); - regs_buff[1] = er32(STATUS); - - regs_buff[2] = er32(RCTL); - regs_buff[3] = er32(RDLEN); - regs_buff[4] = er32(RDH); - regs_buff[5] = er32(RDT); - regs_buff[6] = er32(RDTR); - - regs_buff[7] = er32(TCTL); - regs_buff[8] = er32(TDLEN); - regs_buff[9] = er32(TDH); - regs_buff[10] = er32(TDT); - regs_buff[11] = er32(TIDV); - - regs_buff[12] = hw->phy_type; /* PHY type (IGP=1, M88=0) */ - if (hw->phy_type == e1000_phy_igp) { - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_AGC_A); - e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[13] = (u32)phy_data; /* cable length */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_AGC_B); - e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_B & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[14] = (u32)phy_data; /* cable length */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_AGC_C); - e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_C & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[15] = (u32)phy_data; /* cable length */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_AGC_D); - e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_D & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[16] = (u32)phy_data; /* cable length */ - regs_buff[17] = 0; /* extended 10bt distance (not needed) */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0); - e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[18] = (u32)phy_data; /* cable polarity */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_PCS_INIT_REG); - e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[19] = (u32)phy_data; /* cable polarity */ - regs_buff[20] = 0; /* polarity correction enabled (always) */ - regs_buff[22] = 0; /* phy receive errors (unavailable) */ - regs_buff[23] = regs_buff[18]; /* mdix mode */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0); - } else { - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - regs_buff[13] = (u32)phy_data; /* cable length */ - regs_buff[14] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[15] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[16] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - regs_buff[17] = (u32)phy_data; /* extended 10bt distance */ - regs_buff[18] = regs_buff[13]; /* cable polarity */ - regs_buff[19] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[20] = regs_buff[17]; /* polarity correction */ - /* phy receive errors */ - regs_buff[22] = adapter->phy_stats.receive_errors; - regs_buff[23] = regs_buff[13]; /* mdix mode */ - } - regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */ - e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); - regs_buff[24] = (u32)phy_data; /* phy local receiver status */ - regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ - if (hw->mac_type >= e1000_82540 && - hw->media_type == e1000_media_type_copper) { - regs_buff[26] = er32(MANC); - } -} - -static int e1000_get_eeprom_len(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - return hw->eeprom.word_size * 2; -} - -static int e1000_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 *eeprom_buff; - int first_word, last_word; - int ret_val = 0; - u16 i; - - if (eeprom->len == 0) - return -EINVAL; - - eeprom->magic = hw->vendor_id | (hw->device_id << 16); - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - - eeprom_buff = kmalloc(sizeof(u16) * - (last_word - first_word + 1), GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - if (hw->eeprom.type == e1000_eeprom_spi) - ret_val = e1000_read_eeprom(hw, first_word, - last_word - first_word + 1, - eeprom_buff); - else { - for (i = 0; i < last_word - first_word + 1; i++) { - ret_val = e1000_read_eeprom(hw, first_word + i, 1, - &eeprom_buff[i]); - if (ret_val) - break; - } - } - - /* Device's eeprom is always little-endian, word addressable */ - for (i = 0; i < last_word - first_word + 1; i++) - le16_to_cpus(&eeprom_buff[i]); - - memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), - eeprom->len); - kfree(eeprom_buff); - - return ret_val; -} - -static int e1000_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 *eeprom_buff; - void *ptr; - int max_len, first_word, last_word, ret_val = 0; - u16 i; - - if (eeprom->len == 0) - return -EOPNOTSUPP; - - if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) - return -EFAULT; - - max_len = hw->eeprom.word_size * 2; - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(max_len, GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - ptr = (void *)eeprom_buff; - - if (eeprom->offset & 1) { - /* need read/modify/write of first changed EEPROM word - * only the second byte of the word is being modified - */ - ret_val = e1000_read_eeprom(hw, first_word, 1, - &eeprom_buff[0]); - ptr++; - } - if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { - /* need read/modify/write of last changed EEPROM word - * only the first byte of the word is being modified - */ - ret_val = e1000_read_eeprom(hw, last_word, 1, - &eeprom_buff[last_word - first_word]); - } - - /* Device's eeprom is always little-endian, word addressable */ - for (i = 0; i < last_word - first_word + 1; i++) - le16_to_cpus(&eeprom_buff[i]); - - memcpy(ptr, bytes, eeprom->len); - - for (i = 0; i < last_word - first_word + 1; i++) - eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); - - ret_val = e1000_write_eeprom(hw, first_word, - last_word - first_word + 1, eeprom_buff); - - /* Update the checksum over the first part of the EEPROM if needed */ - if ((ret_val == 0) && (first_word <= EEPROM_CHECKSUM_REG)) - e1000_update_eeprom_checksum(hw); - - kfree(eeprom_buff); - return ret_val; -} - -static void e1000_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - strlcpy(drvinfo->driver, e1000_driver_name, - sizeof(drvinfo->driver)); - strlcpy(drvinfo->version, e1000_driver_version, - sizeof(drvinfo->version)); - - strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), - sizeof(drvinfo->bus_info)); - drvinfo->regdump_len = e1000_get_regs_len(netdev); - drvinfo->eedump_len = e1000_get_eeprom_len(netdev); -} - -static void e1000_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - e1000_mac_type mac_type = hw->mac_type; - struct e1000_tx_ring *txdr = adapter->tx_ring; - struct e1000_rx_ring *rxdr = adapter->rx_ring; - - ring->rx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_RXD : - E1000_MAX_82544_RXD; - ring->tx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_TXD : - E1000_MAX_82544_TXD; - ring->rx_pending = rxdr->count; - ring->tx_pending = txdr->count; -} - -static int e1000_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - e1000_mac_type mac_type = hw->mac_type; - struct e1000_tx_ring *txdr, *tx_old; - struct e1000_rx_ring *rxdr, *rx_old; - int i, err; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) - msleep(1); - - if (netif_running(adapter->netdev)) - e1000_down(adapter); - - tx_old = adapter->tx_ring; - rx_old = adapter->rx_ring; - - err = -ENOMEM; - txdr = kcalloc(adapter->num_tx_queues, sizeof(struct e1000_tx_ring), - GFP_KERNEL); - if (!txdr) - goto err_alloc_tx; - - rxdr = kcalloc(adapter->num_rx_queues, sizeof(struct e1000_rx_ring), - GFP_KERNEL); - if (!rxdr) - goto err_alloc_rx; - - adapter->tx_ring = txdr; - adapter->rx_ring = rxdr; - - rxdr->count = max(ring->rx_pending,(u32)E1000_MIN_RXD); - rxdr->count = min(rxdr->count,(u32)(mac_type < e1000_82544 ? - E1000_MAX_RXD : E1000_MAX_82544_RXD)); - rxdr->count = ALIGN(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE); - - txdr->count = max(ring->tx_pending,(u32)E1000_MIN_TXD); - txdr->count = min(txdr->count,(u32)(mac_type < e1000_82544 ? - E1000_MAX_TXD : E1000_MAX_82544_TXD)); - txdr->count = ALIGN(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); - - for (i = 0; i < adapter->num_tx_queues; i++) - txdr[i].count = txdr->count; - for (i = 0; i < adapter->num_rx_queues; i++) - rxdr[i].count = rxdr->count; - - if (netif_running(adapter->netdev)) { - /* Try to get new resources before deleting old */ - err = e1000_setup_all_rx_resources(adapter); - if (err) - goto err_setup_rx; - err = e1000_setup_all_tx_resources(adapter); - if (err) - goto err_setup_tx; - - /* save the new, restore the old in order to free it, - * then restore the new back again - */ - - adapter->rx_ring = rx_old; - adapter->tx_ring = tx_old; - e1000_free_all_rx_resources(adapter); - e1000_free_all_tx_resources(adapter); - kfree(tx_old); - kfree(rx_old); - adapter->rx_ring = rxdr; - adapter->tx_ring = txdr; - err = e1000_up(adapter); - if (err) - goto err_setup; - } - - clear_bit(__E1000_RESETTING, &adapter->flags); - return 0; -err_setup_tx: - e1000_free_all_rx_resources(adapter); -err_setup_rx: - adapter->rx_ring = rx_old; - adapter->tx_ring = tx_old; - kfree(rxdr); -err_alloc_rx: - kfree(txdr); -err_alloc_tx: - e1000_up(adapter); -err_setup: - clear_bit(__E1000_RESETTING, &adapter->flags); - return err; -} - -static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, int reg, - u32 mask, u32 write) -{ - struct e1000_hw *hw = &adapter->hw; - static const u32 test[] = - {0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF}; - u8 __iomem *address = hw->hw_addr + reg; - u32 read; - int i; - - for (i = 0; i < ARRAY_SIZE(test); i++) { - writel(write & test[i], address); - read = readl(address); - if (read != (write & test[i] & mask)) { - e_err(drv, "pattern test reg %04X failed: " - "got 0x%08X expected 0x%08X\n", - reg, read, (write & test[i] & mask)); - *data = reg; - return true; - } - } - return false; -} - -static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, int reg, - u32 mask, u32 write) -{ - struct e1000_hw *hw = &adapter->hw; - u8 __iomem *address = hw->hw_addr + reg; - u32 read; - - writel(write & mask, address); - read = readl(address); - if ((read & mask) != (write & mask)) { - e_err(drv, "set/check reg %04X test failed: " - "got 0x%08X expected 0x%08X\n", - reg, (read & mask), (write & mask)); - *data = reg; - return true; - } - return false; -} - -#define REG_PATTERN_TEST(reg, mask, write) \ - do { \ - if (reg_pattern_test(adapter, data, \ - (hw->mac_type >= e1000_82543) \ - ? E1000_##reg : E1000_82542_##reg, \ - mask, write)) \ - return 1; \ - } while (0) - -#define REG_SET_AND_CHECK(reg, mask, write) \ - do { \ - if (reg_set_and_check(adapter, data, \ - (hw->mac_type >= e1000_82543) \ - ? E1000_##reg : E1000_82542_##reg, \ - mask, write)) \ - return 1; \ - } while (0) - -static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) -{ - u32 value, before, after; - u32 i, toggle; - struct e1000_hw *hw = &adapter->hw; - - /* The status register is Read Only, so a write should fail. - * Some bits that get toggled are ignored. - */ - - /* there are several bits on newer hardware that are r/w */ - toggle = 0xFFFFF833; - - before = er32(STATUS); - value = (er32(STATUS) & toggle); - ew32(STATUS, toggle); - after = er32(STATUS) & toggle; - if (value != after) { - e_err(drv, "failed STATUS register test got: " - "0x%08X expected: 0x%08X\n", after, value); - *data = 1; - return 1; - } - /* restore previous status */ - ew32(STATUS, before); - - REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF); - - REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF); - REG_PATTERN_TEST(RDH, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(RDT, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(FCRTH, 0x0000FFF8, 0x0000FFF8); - REG_PATTERN_TEST(FCTTV, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(TIPG, 0x3FFFFFFF, 0x3FFFFFFF); - REG_PATTERN_TEST(TDBAH, 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF); - - REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000); - - before = 0x06DFB3FE; - REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB); - REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000); - - if (hw->mac_type >= e1000_82543) { - REG_SET_AND_CHECK(RCTL, before, 0xFFFFFFFF); - REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF); - REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF); - REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF); - value = E1000_RAR_ENTRIES; - for (i = 0; i < value; i++) { - REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), 0x8003FFFF, - 0xFFFFFFFF); - } - } else { - REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x01FFFFFF); - REG_PATTERN_TEST(RDBAL, 0xFFFFF000, 0xFFFFFFFF); - REG_PATTERN_TEST(TXCW, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(TDBAL, 0xFFFFF000, 0xFFFFFFFF); - } - - value = E1000_MC_TBL_SIZE; - for (i = 0; i < value; i++) - REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF); - - *data = 0; - return 0; -} - -static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data) -{ - struct e1000_hw *hw = &adapter->hw; - u16 temp; - u16 checksum = 0; - u16 i; - - *data = 0; - /* Read and add up the contents of the EEPROM */ - for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { - if ((e1000_read_eeprom(hw, i, 1, &temp)) < 0) { - *data = 1; - break; - } - checksum += temp; - } - - /* If Checksum is not Correct return error else test passed */ - if ((checksum != (u16)EEPROM_SUM) && !(*data)) - *data = 2; - - return *data; -} - -static irqreturn_t e1000_test_intr(int irq, void *data) -{ - struct net_device *netdev = (struct net_device *)data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - adapter->test_icr |= er32(ICR); - - return IRQ_HANDLED; -} - -static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) -{ - struct net_device *netdev = adapter->netdev; - u32 mask, i = 0; - bool shared_int = true; - u32 irq = adapter->pdev->irq; - struct e1000_hw *hw = &adapter->hw; - - *data = 0; - - /* NOTE: we don't test MSI interrupts here, yet - * Hook up test interrupt handler just for this test - */ - if (!request_irq(irq, e1000_test_intr, IRQF_PROBE_SHARED, netdev->name, - netdev)) - shared_int = false; - else if (request_irq(irq, e1000_test_intr, IRQF_SHARED, - netdev->name, netdev)) { - *data = 1; - return -1; - } - e_info(hw, "testing %s interrupt\n", (shared_int ? - "shared" : "unshared")); - - /* Disable all the interrupts */ - ew32(IMC, 0xFFFFFFFF); - E1000_WRITE_FLUSH(); - msleep(10); - - /* Test each interrupt */ - for (; i < 10; i++) { - - /* Interrupt to test */ - mask = 1 << i; - - if (!shared_int) { - /* Disable the interrupt to be reported in - * the cause register and then force the same - * interrupt and see if one gets posted. If - * an interrupt was posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - ew32(IMC, mask); - ew32(ICS, mask); - E1000_WRITE_FLUSH(); - msleep(10); - - if (adapter->test_icr & mask) { - *data = 3; - break; - } - } - - /* Enable the interrupt to be reported in - * the cause register and then force the same - * interrupt and see if one gets posted. If - * an interrupt was not posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - ew32(IMS, mask); - ew32(ICS, mask); - E1000_WRITE_FLUSH(); - msleep(10); - - if (!(adapter->test_icr & mask)) { - *data = 4; - break; - } - - if (!shared_int) { - /* Disable the other interrupts to be reported in - * the cause register and then force the other - * interrupts and see if any get posted. If - * an interrupt was posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - ew32(IMC, ~mask & 0x00007FFF); - ew32(ICS, ~mask & 0x00007FFF); - E1000_WRITE_FLUSH(); - msleep(10); - - if (adapter->test_icr) { - *data = 5; - break; - } - } - } - - /* Disable all the interrupts */ - ew32(IMC, 0xFFFFFFFF); - E1000_WRITE_FLUSH(); - msleep(10); - - /* Unhook test interrupt handler */ - free_irq(irq, netdev); - - return *data; -} - -static void e1000_free_desc_rings(struct e1000_adapter *adapter) -{ - struct e1000_tx_ring *txdr = &adapter->test_tx_ring; - struct e1000_rx_ring *rxdr = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - int i; - - if (txdr->desc && txdr->buffer_info) { - for (i = 0; i < txdr->count; i++) { - if (txdr->buffer_info[i].dma) - dma_unmap_single(&pdev->dev, - txdr->buffer_info[i].dma, - txdr->buffer_info[i].length, - DMA_TO_DEVICE); - if (txdr->buffer_info[i].skb) - dev_kfree_skb(txdr->buffer_info[i].skb); - } - } - - if (rxdr->desc && rxdr->buffer_info) { - for (i = 0; i < rxdr->count; i++) { - if (rxdr->buffer_info[i].dma) - dma_unmap_single(&pdev->dev, - rxdr->buffer_info[i].dma, - rxdr->buffer_info[i].length, - DMA_FROM_DEVICE); - if (rxdr->buffer_info[i].skb) - dev_kfree_skb(rxdr->buffer_info[i].skb); - } - } - - if (txdr->desc) { - dma_free_coherent(&pdev->dev, txdr->size, txdr->desc, - txdr->dma); - txdr->desc = NULL; - } - if (rxdr->desc) { - dma_free_coherent(&pdev->dev, rxdr->size, rxdr->desc, - rxdr->dma); - rxdr->desc = NULL; - } - - kfree(txdr->buffer_info); - txdr->buffer_info = NULL; - kfree(rxdr->buffer_info); - rxdr->buffer_info = NULL; -} - -static int e1000_setup_desc_rings(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_tx_ring *txdr = &adapter->test_tx_ring; - struct e1000_rx_ring *rxdr = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - u32 rctl; - int i, ret_val; - - /* Setup Tx descriptor ring and Tx buffers */ - - if (!txdr->count) - txdr->count = E1000_DEFAULT_TXD; - - txdr->buffer_info = kcalloc(txdr->count, sizeof(struct e1000_buffer), - GFP_KERNEL); - if (!txdr->buffer_info) { - ret_val = 1; - goto err_nomem; - } - - txdr->size = txdr->count * sizeof(struct e1000_tx_desc); - txdr->size = ALIGN(txdr->size, 4096); - txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma, - GFP_KERNEL | __GFP_ZERO); - if (!txdr->desc) { - ret_val = 2; - goto err_nomem; - } - txdr->next_to_use = txdr->next_to_clean = 0; - - ew32(TDBAL, ((u64)txdr->dma & 0x00000000FFFFFFFF)); - ew32(TDBAH, ((u64)txdr->dma >> 32)); - ew32(TDLEN, txdr->count * sizeof(struct e1000_tx_desc)); - ew32(TDH, 0); - ew32(TDT, 0); - ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | - E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | - E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT); - - for (i = 0; i < txdr->count; i++) { - struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i); - struct sk_buff *skb; - unsigned int size = 1024; - - skb = alloc_skb(size, GFP_KERNEL); - if (!skb) { - ret_val = 3; - goto err_nomem; - } - skb_put(skb, size); - txdr->buffer_info[i].skb = skb; - txdr->buffer_info[i].length = skb->len; - txdr->buffer_info[i].dma = - dma_map_single(&pdev->dev, skb->data, skb->len, - DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, txdr->buffer_info[i].dma)) { - ret_val = 4; - goto err_nomem; - } - tx_desc->buffer_addr = cpu_to_le64(txdr->buffer_info[i].dma); - tx_desc->lower.data = cpu_to_le32(skb->len); - tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP | - E1000_TXD_CMD_IFCS | - E1000_TXD_CMD_RPS); - tx_desc->upper.data = 0; - } - - /* Setup Rx descriptor ring and Rx buffers */ - - if (!rxdr->count) - rxdr->count = E1000_DEFAULT_RXD; - - rxdr->buffer_info = kcalloc(rxdr->count, sizeof(struct e1000_buffer), - GFP_KERNEL); - if (!rxdr->buffer_info) { - ret_val = 5; - goto err_nomem; - } - - rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc); - rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma, - GFP_KERNEL | __GFP_ZERO); - if (!rxdr->desc) { - ret_val = 6; - goto err_nomem; - } - rxdr->next_to_use = rxdr->next_to_clean = 0; - - rctl = er32(RCTL); - ew32(RCTL, rctl & ~E1000_RCTL_EN); - ew32(RDBAL, ((u64)rxdr->dma & 0xFFFFFFFF)); - ew32(RDBAH, ((u64)rxdr->dma >> 32)); - ew32(RDLEN, rxdr->size); - ew32(RDH, 0); - ew32(RDT, 0); - rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | - E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | - (hw->mc_filter_type << E1000_RCTL_MO_SHIFT); - ew32(RCTL, rctl); - - for (i = 0; i < rxdr->count; i++) { - struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i); - struct sk_buff *skb; - - skb = alloc_skb(E1000_RXBUFFER_2048 + NET_IP_ALIGN, GFP_KERNEL); - if (!skb) { - ret_val = 7; - goto err_nomem; - } - skb_reserve(skb, NET_IP_ALIGN); - rxdr->buffer_info[i].skb = skb; - rxdr->buffer_info[i].length = E1000_RXBUFFER_2048; - rxdr->buffer_info[i].dma = - dma_map_single(&pdev->dev, skb->data, - E1000_RXBUFFER_2048, DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, rxdr->buffer_info[i].dma)) { - ret_val = 8; - goto err_nomem; - } - rx_desc->buffer_addr = cpu_to_le64(rxdr->buffer_info[i].dma); - memset(skb->data, 0x00, skb->len); - } - - return 0; - -err_nomem: - e1000_free_desc_rings(adapter); - return ret_val; -} - -static void e1000_phy_disable_receiver(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - /* Write out to PHY registers 29 and 30 to disable the Receiver. */ - e1000_write_phy_reg(hw, 29, 0x001F); - e1000_write_phy_reg(hw, 30, 0x8FFC); - e1000_write_phy_reg(hw, 29, 0x001A); - e1000_write_phy_reg(hw, 30, 0x8FF0); -} - -static void e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u16 phy_reg; - - /* Because we reset the PHY above, we need to re-force TX_CLK in the - * Extended PHY Specific Control Register to 25MHz clock. This - * value defaults back to a 2.5MHz clock when the PHY is reset. - */ - e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg); - phy_reg |= M88E1000_EPSCR_TX_CLK_25; - e1000_write_phy_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, phy_reg); - - /* In addition, because of the s/w reset above, we need to enable - * CRS on TX. This must be set for both full and half duplex - * operation. - */ - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_reg); - phy_reg |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - e1000_write_phy_reg(hw, - M88E1000_PHY_SPEC_CTRL, phy_reg); -} - -static int e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl_reg; - u16 phy_reg; - - /* Setup the Device Control Register for PHY loopback test. */ - - ctrl_reg = er32(CTRL); - ctrl_reg |= (E1000_CTRL_ILOS | /* Invert Loss-Of-Signal */ - E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ - E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ - E1000_CTRL_SPD_1000 | /* Force Speed to 1000 */ - E1000_CTRL_FD); /* Force Duplex to FULL */ - - ew32(CTRL, ctrl_reg); - - /* Read the PHY Specific Control Register (0x10) */ - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_reg); - - /* Clear Auto-Crossover bits in PHY Specific Control Register - * (bits 6:5). - */ - phy_reg &= ~M88E1000_PSCR_AUTO_X_MODE; - e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_reg); - - /* Perform software reset on the PHY */ - e1000_phy_reset(hw); - - /* Have to setup TX_CLK and TX_CRS after software reset */ - e1000_phy_reset_clk_and_crs(adapter); - - e1000_write_phy_reg(hw, PHY_CTRL, 0x8100); - - /* Wait for reset to complete. */ - udelay(500); - - /* Have to setup TX_CLK and TX_CRS after software reset */ - e1000_phy_reset_clk_and_crs(adapter); - - /* Write out to PHY registers 29 and 30 to disable the Receiver. */ - e1000_phy_disable_receiver(adapter); - - /* Set the loopback bit in the PHY control register. */ - e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg); - phy_reg |= MII_CR_LOOPBACK; - e1000_write_phy_reg(hw, PHY_CTRL, phy_reg); - - /* Setup TX_CLK and TX_CRS one more time. */ - e1000_phy_reset_clk_and_crs(adapter); - - /* Check Phy Configuration */ - e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg); - if (phy_reg != 0x4100) - return 9; - - e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg); - if (phy_reg != 0x0070) - return 10; - - e1000_read_phy_reg(hw, 29, &phy_reg); - if (phy_reg != 0x001A) - return 11; - - return 0; -} - -static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl_reg = 0; - u32 stat_reg = 0; - - hw->autoneg = false; - - if (hw->phy_type == e1000_phy_m88) { - /* Auto-MDI/MDIX Off */ - e1000_write_phy_reg(hw, - M88E1000_PHY_SPEC_CTRL, 0x0808); - /* reset to update Auto-MDI/MDIX */ - e1000_write_phy_reg(hw, PHY_CTRL, 0x9140); - /* autoneg off */ - e1000_write_phy_reg(hw, PHY_CTRL, 0x8140); - } - - ctrl_reg = er32(CTRL); - - /* force 1000, set loopback */ - e1000_write_phy_reg(hw, PHY_CTRL, 0x4140); - - /* Now set up the MAC to the same speed/duplex as the PHY. */ - ctrl_reg = er32(CTRL); - ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ - ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ - E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ - E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ - E1000_CTRL_FD); /* Force Duplex to FULL */ - - if (hw->media_type == e1000_media_type_copper && - hw->phy_type == e1000_phy_m88) - ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ - else { - /* Set the ILOS bit on the fiber Nic is half - * duplex link is detected. - */ - stat_reg = er32(STATUS); - if ((stat_reg & E1000_STATUS_FD) == 0) - ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU); - } - - ew32(CTRL, ctrl_reg); - - /* Disable the receiver on the PHY so when a cable is plugged in, the - * PHY does not begin to autoneg when a cable is reconnected to the NIC. - */ - if (hw->phy_type == e1000_phy_m88) - e1000_phy_disable_receiver(adapter); - - udelay(500); - - return 0; -} - -static int e1000_set_phy_loopback(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u16 phy_reg = 0; - u16 count = 0; - - switch (hw->mac_type) { - case e1000_82543: - if (hw->media_type == e1000_media_type_copper) { - /* Attempt to setup Loopback mode on Non-integrated PHY. - * Some PHY registers get corrupted at random, so - * attempt this 10 times. - */ - while (e1000_nonintegrated_phy_loopback(adapter) && - count++ < 10); - if (count < 11) - return 0; - } - break; - - case e1000_82544: - case e1000_82540: - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_82546_rev_3: - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - return e1000_integrated_phy_loopback(adapter); - break; - default: - /* Default PHY loopback work is to read the MII - * control register and assert bit 14 (loopback mode). - */ - e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg); - phy_reg |= MII_CR_LOOPBACK; - e1000_write_phy_reg(hw, PHY_CTRL, phy_reg); - return 0; - break; - } - - return 8; -} - -static int e1000_setup_loopback_test(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - if (hw->media_type == e1000_media_type_fiber || - hw->media_type == e1000_media_type_internal_serdes) { - switch (hw->mac_type) { - case e1000_82545: - case e1000_82546: - case e1000_82545_rev_3: - case e1000_82546_rev_3: - return e1000_set_phy_loopback(adapter); - break; - default: - rctl = er32(RCTL); - rctl |= E1000_RCTL_LBM_TCVR; - ew32(RCTL, rctl); - return 0; - } - } else if (hw->media_type == e1000_media_type_copper) - return e1000_set_phy_loopback(adapter); - - return 7; -} - -static void e1000_loopback_cleanup(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - u16 phy_reg; - - rctl = er32(RCTL); - rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); - ew32(RCTL, rctl); - - switch (hw->mac_type) { - case e1000_82545: - case e1000_82546: - case e1000_82545_rev_3: - case e1000_82546_rev_3: - default: - hw->autoneg = true; - e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg); - if (phy_reg & MII_CR_LOOPBACK) { - phy_reg &= ~MII_CR_LOOPBACK; - e1000_write_phy_reg(hw, PHY_CTRL, phy_reg); - e1000_phy_reset(hw); - } - break; - } -} - -static void e1000_create_lbtest_frame(struct sk_buff *skb, - unsigned int frame_size) -{ - memset(skb->data, 0xFF, frame_size); - frame_size &= ~1; - memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1); - memset(&skb->data[frame_size / 2 + 10], 0xBE, 1); - memset(&skb->data[frame_size / 2 + 12], 0xAF, 1); -} - -static int e1000_check_lbtest_frame(struct sk_buff *skb, - unsigned int frame_size) -{ - frame_size &= ~1; - if (*(skb->data + 3) == 0xFF) { - if ((*(skb->data + frame_size / 2 + 10) == 0xBE) && - (*(skb->data + frame_size / 2 + 12) == 0xAF)) { - return 0; - } - } - return 13; -} - -static int e1000_run_loopback_test(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_tx_ring *txdr = &adapter->test_tx_ring; - struct e1000_rx_ring *rxdr = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - int i, j, k, l, lc, good_cnt, ret_val=0; - unsigned long time; - - ew32(RDT, rxdr->count - 1); - - /* Calculate the loop count based on the largest descriptor ring - * The idea is to wrap the largest ring a number of times using 64 - * send/receive pairs during each loop - */ - - if (rxdr->count <= txdr->count) - lc = ((txdr->count / 64) * 2) + 1; - else - lc = ((rxdr->count / 64) * 2) + 1; - - k = l = 0; - for (j = 0; j <= lc; j++) { /* loop count loop */ - for (i = 0; i < 64; i++) { /* send the packets */ - e1000_create_lbtest_frame(txdr->buffer_info[i].skb, - 1024); - dma_sync_single_for_device(&pdev->dev, - txdr->buffer_info[k].dma, - txdr->buffer_info[k].length, - DMA_TO_DEVICE); - if (unlikely(++k == txdr->count)) k = 0; - } - ew32(TDT, k); - E1000_WRITE_FLUSH(); - msleep(200); - time = jiffies; /* set the start time for the receive */ - good_cnt = 0; - do { /* receive the sent packets */ - dma_sync_single_for_cpu(&pdev->dev, - rxdr->buffer_info[l].dma, - rxdr->buffer_info[l].length, - DMA_FROM_DEVICE); - - ret_val = e1000_check_lbtest_frame( - rxdr->buffer_info[l].skb, - 1024); - if (!ret_val) - good_cnt++; - if (unlikely(++l == rxdr->count)) l = 0; - /* time + 20 msecs (200 msecs on 2.4) is more than - * enough time to complete the receives, if it's - * exceeded, break and error off - */ - } while (good_cnt < 64 && jiffies < (time + 20)); - if (good_cnt != 64) { - ret_val = 13; /* ret_val is the same as mis-compare */ - break; - } - if (jiffies >= (time + 2)) { - ret_val = 14; /* error code for time out error */ - break; - } - } /* end loop count loop */ - return ret_val; -} - -static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) -{ - *data = e1000_setup_desc_rings(adapter); - if (*data) - goto out; - *data = e1000_setup_loopback_test(adapter); - if (*data) - goto err_loopback; - *data = e1000_run_loopback_test(adapter); - e1000_loopback_cleanup(adapter); - -err_loopback: - e1000_free_desc_rings(adapter); -out: - return *data; -} - -static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) -{ - struct e1000_hw *hw = &adapter->hw; - *data = 0; - if (hw->media_type == e1000_media_type_internal_serdes) { - int i = 0; - hw->serdes_has_link = false; - - /* On some blade server designs, link establishment - * could take as long as 2-3 minutes - */ - do { - e1000_check_for_link(hw); - if (hw->serdes_has_link) - return *data; - msleep(20); - } while (i++ < 3750); - - *data = 1; - } else { - e1000_check_for_link(hw); - if (hw->autoneg) /* if auto_neg is set wait for it */ - msleep(4000); - - if (!(er32(STATUS) & E1000_STATUS_LU)) { - *data = 1; - } - } - return *data; -} - -static int e1000_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E1000_TEST_LEN; - case ETH_SS_STATS: - return E1000_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e1000_diag_test(struct net_device *netdev, - struct ethtool_test *eth_test, u64 *data) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - bool if_running = netif_running(netdev); - - set_bit(__E1000_TESTING, &adapter->flags); - if (eth_test->flags == ETH_TEST_FL_OFFLINE) { - /* Offline tests */ - - /* save speed, duplex, autoneg settings */ - u16 autoneg_advertised = hw->autoneg_advertised; - u8 forced_speed_duplex = hw->forced_speed_duplex; - u8 autoneg = hw->autoneg; - - e_info(hw, "offline testing starting\n"); - - /* Link test performed before hardware reset so autoneg doesn't - * interfere with test result - */ - if (e1000_link_test(adapter, &data[4])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - if (if_running) - /* indicate we're in test mode */ - dev_close(netdev); - else - e1000_reset(adapter); - - if (e1000_reg_test(adapter, &data[0])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000_reset(adapter); - if (e1000_eeprom_test(adapter, &data[1])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000_reset(adapter); - if (e1000_intr_test(adapter, &data[2])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000_reset(adapter); - /* make sure the phy is powered up */ - e1000_power_up_phy(adapter); - if (e1000_loopback_test(adapter, &data[3])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - /* restore speed, duplex, autoneg settings */ - hw->autoneg_advertised = autoneg_advertised; - hw->forced_speed_duplex = forced_speed_duplex; - hw->autoneg = autoneg; - - e1000_reset(adapter); - clear_bit(__E1000_TESTING, &adapter->flags); - if (if_running) - dev_open(netdev); - } else { - e_info(hw, "online testing starting\n"); - /* Online tests */ - if (e1000_link_test(adapter, &data[4])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - /* Online tests aren't run; pass by default */ - data[0] = 0; - data[1] = 0; - data[2] = 0; - data[3] = 0; - - clear_bit(__E1000_TESTING, &adapter->flags); - } - msleep_interruptible(4 * 1000); -} - -static int e1000_wol_exclusion(struct e1000_adapter *adapter, - struct ethtool_wolinfo *wol) -{ - struct e1000_hw *hw = &adapter->hw; - int retval = 1; /* fail by default */ - - switch (hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82546GB_QUAD_COPPER: - case E1000_DEV_ID_82546GB_PCIE: - /* these don't support WoL at all */ - wol->supported = 0; - break; - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546GB_FIBER: - /* Wake events not supported on port B */ - if (er32(STATUS) & E1000_STATUS_FUNC_1) { - wol->supported = 0; - break; - } - /* return success for non excluded adapter ports */ - retval = 0; - break; - case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: - /* quad port adapters only support WoL on port A */ - if (!adapter->quad_port_a) { - wol->supported = 0; - break; - } - /* return success for non excluded adapter ports */ - retval = 0; - break; - default: - /* dual port cards only support WoL on port A from now on - * unless it was enabled in the eeprom for port B - * so exclude FUNC_1 ports from having WoL enabled - */ - if (er32(STATUS) & E1000_STATUS_FUNC_1 && - !adapter->eeprom_wol) { - wol->supported = 0; - break; - } - - retval = 0; - } - - return retval; -} - -static void e1000_get_wol(struct net_device *netdev, - struct ethtool_wolinfo *wol) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - wol->supported = WAKE_UCAST | WAKE_MCAST | - WAKE_BCAST | WAKE_MAGIC; - wol->wolopts = 0; - - /* this function will set ->supported = 0 and return 1 if wol is not - * supported by this hardware - */ - if (e1000_wol_exclusion(adapter, wol) || - !device_can_wakeup(&adapter->pdev->dev)) - return; - - /* apply any specific unsupported masks here */ - switch (hw->device_id) { - case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: - /* KSP3 does not support UCAST wake-ups */ - wol->supported &= ~WAKE_UCAST; - - if (adapter->wol & E1000_WUFC_EX) - e_err(drv, "Interface does not support directed " - "(unicast) frame wake-up packets\n"); - break; - default: - break; - } - - if (adapter->wol & E1000_WUFC_EX) - wol->wolopts |= WAKE_UCAST; - if (adapter->wol & E1000_WUFC_MC) - wol->wolopts |= WAKE_MCAST; - if (adapter->wol & E1000_WUFC_BC) - wol->wolopts |= WAKE_BCAST; - if (adapter->wol & E1000_WUFC_MAG) - wol->wolopts |= WAKE_MAGIC; -} - -static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) - return -EOPNOTSUPP; - - if (e1000_wol_exclusion(adapter, wol) || - !device_can_wakeup(&adapter->pdev->dev)) - return wol->wolopts ? -EOPNOTSUPP : 0; - - switch (hw->device_id) { - case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: - if (wol->wolopts & WAKE_UCAST) { - e_err(drv, "Interface does not support directed " - "(unicast) frame wake-up packets\n"); - return -EOPNOTSUPP; - } - break; - default: - break; - } - - /* these settings will always override what we currently have */ - adapter->wol = 0; - - if (wol->wolopts & WAKE_UCAST) - adapter->wol |= E1000_WUFC_EX; - if (wol->wolopts & WAKE_MCAST) - adapter->wol |= E1000_WUFC_MC; - if (wol->wolopts & WAKE_BCAST) - adapter->wol |= E1000_WUFC_BC; - if (wol->wolopts & WAKE_MAGIC) - adapter->wol |= E1000_WUFC_MAG; - - device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); - - return 0; -} - -static int e1000_set_phys_id(struct net_device *netdev, - enum ethtool_phys_id_state state) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - switch (state) { - case ETHTOOL_ID_ACTIVE: - e1000_setup_led(hw); - return 2; - - case ETHTOOL_ID_ON: - e1000_led_on(hw); - break; - - case ETHTOOL_ID_OFF: - e1000_led_off(hw); - break; - - case ETHTOOL_ID_INACTIVE: - e1000_cleanup_led(hw); - } - - return 0; -} - -static int e1000_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (adapter->hw.mac_type < e1000_82545) - return -EOPNOTSUPP; - - if (adapter->itr_setting <= 4) - ec->rx_coalesce_usecs = adapter->itr_setting; - else - ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting; - - return 0; -} - -static int e1000_set_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - if (hw->mac_type < e1000_82545) - return -EOPNOTSUPP; - - if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || - ((ec->rx_coalesce_usecs > 4) && - (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) || - (ec->rx_coalesce_usecs == 2)) - return -EINVAL; - - if (ec->rx_coalesce_usecs == 4) { - adapter->itr = adapter->itr_setting = 4; - } else if (ec->rx_coalesce_usecs <= 3) { - adapter->itr = 20000; - adapter->itr_setting = ec->rx_coalesce_usecs; - } else { - adapter->itr = (1000000 / ec->rx_coalesce_usecs); - adapter->itr_setting = adapter->itr & ~3; - } - - if (adapter->itr_setting != 0) - ew32(ITR, 1000000000 / (adapter->itr * 256)); - else - ew32(ITR, 0); - - return 0; -} - -static int e1000_nway_reset(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - if (netif_running(netdev)) - e1000_reinit_locked(adapter); - return 0; -} - -static void e1000_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - int i; - char *p = NULL; - - e1000_update_stats(adapter); - for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { - switch (e1000_gstrings_stats[i].type) { - case NETDEV_STATS: - p = (char *) netdev + - e1000_gstrings_stats[i].stat_offset; - break; - case E1000_STATS: - p = (char *) adapter + - e1000_gstrings_stats[i].stat_offset; - break; - } - - data[i] = (e1000_gstrings_stats[i].sizeof_stat == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } -/* BUG_ON(i != E1000_STATS_LEN); */ -} - -static void e1000_get_strings(struct net_device *netdev, u32 stringset, - u8 *data) -{ - u8 *p = data; - int i; - - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, *e1000_gstrings_test, - sizeof(e1000_gstrings_test)); - break; - case ETH_SS_STATS: - for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { - memcpy(p, e1000_gstrings_stats[i].stat_string, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - } - /* BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */ - break; - } -} - -static const struct ethtool_ops e1000_ethtool_ops = { - .get_settings = e1000_get_settings, - .set_settings = e1000_set_settings, - .get_drvinfo = e1000_get_drvinfo, - .get_regs_len = e1000_get_regs_len, - .get_regs = e1000_get_regs, - .get_wol = e1000_get_wol, - .set_wol = e1000_set_wol, - .get_msglevel = e1000_get_msglevel, - .set_msglevel = e1000_set_msglevel, - .nway_reset = e1000_nway_reset, - .get_link = e1000_get_link, - .get_eeprom_len = e1000_get_eeprom_len, - .get_eeprom = e1000_get_eeprom, - .set_eeprom = e1000_set_eeprom, - .get_ringparam = e1000_get_ringparam, - .set_ringparam = e1000_set_ringparam, - .get_pauseparam = e1000_get_pauseparam, - .set_pauseparam = e1000_set_pauseparam, - .self_test = e1000_diag_test, - .get_strings = e1000_get_strings, - .set_phys_id = e1000_set_phys_id, - .get_ethtool_stats = e1000_get_ethtool_stats, - .get_sset_count = e1000_get_sset_count, - .get_coalesce = e1000_get_coalesce, - .set_coalesce = e1000_set_coalesce, - .get_ts_info = ethtool_op_get_ts_info, -}; - -void e1000_set_ethtool_ops(struct net_device *netdev) -{ - SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops); -} diff --git a/addons/e1000/src/3.10.108/e1000_hw.c b/addons/e1000/src/3.10.108/e1000_hw.c deleted file mode 100644 index 2879b963..00000000 --- a/addons/e1000/src/3.10.108/e1000_hw.c +++ /dev/null @@ -1,5893 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - - */ - -/* e1000_hw.c - * Shared functions for accessing and configuring the MAC - */ - -#include "e1000.h" - -static s32 e1000_check_downshift(struct e1000_hw *hw); -static s32 e1000_check_polarity(struct e1000_hw *hw, - e1000_rev_polarity *polarity); -static void e1000_clear_hw_cntrs(struct e1000_hw *hw); -static void e1000_clear_vfta(struct e1000_hw *hw); -static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, - bool link_up); -static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw); -static s32 e1000_detect_gig_phy(struct e1000_hw *hw); -static s32 e1000_get_auto_rd_done(struct e1000_hw *hw); -static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length, - u16 *max_length); -static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw); -static s32 e1000_id_led_init(struct e1000_hw *hw); -static void e1000_init_rx_addrs(struct e1000_hw *hw); -static s32 e1000_phy_igp_get_info(struct e1000_hw *hw, - struct e1000_phy_info *phy_info); -static s32 e1000_phy_m88_get_info(struct e1000_hw *hw, - struct e1000_phy_info *phy_info); -static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active); -static s32 e1000_wait_autoneg(struct e1000_hw *hw); -static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value); -static s32 e1000_set_phy_type(struct e1000_hw *hw); -static void e1000_phy_init_script(struct e1000_hw *hw); -static s32 e1000_setup_copper_link(struct e1000_hw *hw); -static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw); -static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw); -static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw); -static s32 e1000_config_mac_to_phy(struct e1000_hw *hw); -static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl); -static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl); -static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count); -static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw); -static s32 e1000_phy_reset_dsp(struct e1000_hw *hw); -static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw); -static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd); -static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd); -static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count); -static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, - u16 phy_data); -static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, - u16 *phy_data); -static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count); -static s32 e1000_acquire_eeprom(struct e1000_hw *hw); -static void e1000_release_eeprom(struct e1000_hw *hw); -static void e1000_standby_eeprom(struct e1000_hw *hw); -static s32 e1000_set_vco_speed(struct e1000_hw *hw); -static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw); -static s32 e1000_set_phy_mode(struct e1000_hw *hw); -static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data); -static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data); - -/* IGP cable length table */ -static const -u16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = { - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, - 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, - 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, - 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, - 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120 -}; - -static DEFINE_SPINLOCK(e1000_eeprom_lock); -static DEFINE_SPINLOCK(e1000_phy_lock); - -/** - * e1000_set_phy_type - Set the phy type member in the hw struct. - * @hw: Struct containing variables accessed by shared code - */ -static s32 e1000_set_phy_type(struct e1000_hw *hw) -{ - e_dbg("e1000_set_phy_type"); - - if (hw->mac_type == e1000_undefined) - return -E1000_ERR_PHY_TYPE; - - switch (hw->phy_id) { - case M88E1000_E_PHY_ID: - case M88E1000_I_PHY_ID: - case M88E1011_I_PHY_ID: - case M88E1111_I_PHY_ID: - case M88E1118_E_PHY_ID: - hw->phy_type = e1000_phy_m88; - break; - case IGP01E1000_I_PHY_ID: - if (hw->mac_type == e1000_82541 || - hw->mac_type == e1000_82541_rev_2 || - hw->mac_type == e1000_82547 || - hw->mac_type == e1000_82547_rev_2) - hw->phy_type = e1000_phy_igp; - break; - case RTL8211B_PHY_ID: - hw->phy_type = e1000_phy_8211; - break; - case RTL8201N_PHY_ID: - hw->phy_type = e1000_phy_8201; - break; - default: - /* Should never have loaded on this device */ - hw->phy_type = e1000_phy_undefined; - return -E1000_ERR_PHY_TYPE; - } - - return E1000_SUCCESS; -} - -/** - * e1000_phy_init_script - IGP phy init script - initializes the GbE PHY - * @hw: Struct containing variables accessed by shared code - */ -static void e1000_phy_init_script(struct e1000_hw *hw) -{ - u32 ret_val; - u16 phy_saved_data; - - e_dbg("e1000_phy_init_script"); - - if (hw->phy_init_script) { - msleep(20); - - /* Save off the current value of register 0x2F5B to be restored - * at the end of this routine. - */ - ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data); - - /* Disabled the PHY transmitter */ - e1000_write_phy_reg(hw, 0x2F5B, 0x0003); - msleep(20); - - e1000_write_phy_reg(hw, 0x0000, 0x0140); - msleep(5); - - switch (hw->mac_type) { - case e1000_82541: - case e1000_82547: - e1000_write_phy_reg(hw, 0x1F95, 0x0001); - e1000_write_phy_reg(hw, 0x1F71, 0xBD21); - e1000_write_phy_reg(hw, 0x1F79, 0x0018); - e1000_write_phy_reg(hw, 0x1F30, 0x1600); - e1000_write_phy_reg(hw, 0x1F31, 0x0014); - e1000_write_phy_reg(hw, 0x1F32, 0x161C); - e1000_write_phy_reg(hw, 0x1F94, 0x0003); - e1000_write_phy_reg(hw, 0x1F96, 0x003F); - e1000_write_phy_reg(hw, 0x2010, 0x0008); - break; - - case e1000_82541_rev_2: - case e1000_82547_rev_2: - e1000_write_phy_reg(hw, 0x1F73, 0x0099); - break; - default: - break; - } - - e1000_write_phy_reg(hw, 0x0000, 0x3300); - msleep(20); - - /* Now enable the transmitter */ - e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data); - - if (hw->mac_type == e1000_82547) { - u16 fused, fine, coarse; - - /* Move to analog registers page */ - e1000_read_phy_reg(hw, - IGP01E1000_ANALOG_SPARE_FUSE_STATUS, - &fused); - - if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { - e1000_read_phy_reg(hw, - IGP01E1000_ANALOG_FUSE_STATUS, - &fused); - - fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK; - coarse = - fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK; - - if (coarse > - IGP01E1000_ANALOG_FUSE_COARSE_THRESH) { - coarse -= - IGP01E1000_ANALOG_FUSE_COARSE_10; - fine -= IGP01E1000_ANALOG_FUSE_FINE_1; - } else if (coarse == - IGP01E1000_ANALOG_FUSE_COARSE_THRESH) - fine -= IGP01E1000_ANALOG_FUSE_FINE_10; - - fused = - (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | - (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | - (coarse & - IGP01E1000_ANALOG_FUSE_COARSE_MASK); - - e1000_write_phy_reg(hw, - IGP01E1000_ANALOG_FUSE_CONTROL, - fused); - e1000_write_phy_reg(hw, - IGP01E1000_ANALOG_FUSE_BYPASS, - IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL); - } - } - } -} - -/** - * e1000_set_mac_type - Set the mac type member in the hw struct. - * @hw: Struct containing variables accessed by shared code - */ -s32 e1000_set_mac_type(struct e1000_hw *hw) -{ - e_dbg("e1000_set_mac_type"); - - switch (hw->device_id) { - case E1000_DEV_ID_82542: - switch (hw->revision_id) { - case E1000_82542_2_0_REV_ID: - hw->mac_type = e1000_82542_rev2_0; - break; - case E1000_82542_2_1_REV_ID: - hw->mac_type = e1000_82542_rev2_1; - break; - default: - /* Invalid 82542 revision ID */ - return -E1000_ERR_MAC_TYPE; - } - break; - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - hw->mac_type = e1000_82543; - break; - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: - hw->mac_type = e1000_82544; - break; - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - hw->mac_type = e1000_82540; - break; - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82545EM_FIBER: - hw->mac_type = e1000_82545; - break; - case E1000_DEV_ID_82545GM_COPPER: - case E1000_DEV_ID_82545GM_FIBER: - case E1000_DEV_ID_82545GM_SERDES: - hw->mac_type = e1000_82545_rev_3; - break; - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - hw->mac_type = e1000_82546; - break; - case E1000_DEV_ID_82546GB_COPPER: - case E1000_DEV_ID_82546GB_FIBER: - case E1000_DEV_ID_82546GB_SERDES: - case E1000_DEV_ID_82546GB_PCIE: - case E1000_DEV_ID_82546GB_QUAD_COPPER: - case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: - hw->mac_type = e1000_82546_rev_3; - break; - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EI_MOBILE: - case E1000_DEV_ID_82541ER_LOM: - hw->mac_type = e1000_82541; - break; - case E1000_DEV_ID_82541ER: - case E1000_DEV_ID_82541GI: - case E1000_DEV_ID_82541GI_LF: - case E1000_DEV_ID_82541GI_MOBILE: - hw->mac_type = e1000_82541_rev_2; - break; - case E1000_DEV_ID_82547EI: - case E1000_DEV_ID_82547EI_MOBILE: - hw->mac_type = e1000_82547; - break; - case E1000_DEV_ID_82547GI: - hw->mac_type = e1000_82547_rev_2; - break; - case E1000_DEV_ID_INTEL_CE4100_GBE: - hw->mac_type = e1000_ce4100; - break; - default: - /* Should never have loaded on this device */ - return -E1000_ERR_MAC_TYPE; - } - - switch (hw->mac_type) { - case e1000_82541: - case e1000_82547: - case e1000_82541_rev_2: - case e1000_82547_rev_2: - hw->asf_firmware_present = true; - break; - default: - break; - } - - /* The 82543 chip does not count tx_carrier_errors properly in - * FD mode - */ - if (hw->mac_type == e1000_82543) - hw->bad_tx_carr_stats_fd = true; - - if (hw->mac_type > e1000_82544) - hw->has_smbus = true; - - return E1000_SUCCESS; -} - -/** - * e1000_set_media_type - Set media type and TBI compatibility. - * @hw: Struct containing variables accessed by shared code - */ -void e1000_set_media_type(struct e1000_hw *hw) -{ - u32 status; - - e_dbg("e1000_set_media_type"); - - if (hw->mac_type != e1000_82543) { - /* tbi_compatibility is only valid on 82543 */ - hw->tbi_compatibility_en = false; - } - - switch (hw->device_id) { - case E1000_DEV_ID_82545GM_SERDES: - case E1000_DEV_ID_82546GB_SERDES: - hw->media_type = e1000_media_type_internal_serdes; - break; - default: - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - hw->media_type = e1000_media_type_fiber; - break; - case e1000_ce4100: - hw->media_type = e1000_media_type_copper; - break; - default: - status = er32(STATUS); - if (status & E1000_STATUS_TBIMODE) { - hw->media_type = e1000_media_type_fiber; - /* tbi_compatibility not valid on fiber */ - hw->tbi_compatibility_en = false; - } else { - hw->media_type = e1000_media_type_copper; - } - break; - } - } -} - -/** - * e1000_reset_hw - reset the hardware completely - * @hw: Struct containing variables accessed by shared code - * - * Reset the transmit and receive units; mask and clear all interrupts. - */ -s32 e1000_reset_hw(struct e1000_hw *hw) -{ - u32 ctrl; - u32 ctrl_ext; - u32 icr; - u32 manc; - u32 led_ctrl; - s32 ret_val; - - e_dbg("e1000_reset_hw"); - - /* For 82542 (rev 2.0), disable MWI before issuing a device reset */ - if (hw->mac_type == e1000_82542_rev2_0) { - e_dbg("Disabling MWI on 82542 rev 2.0\n"); - e1000_pci_clear_mwi(hw); - } - - /* Clear interrupt mask to stop board from generating interrupts */ - e_dbg("Masking off all interrupts\n"); - ew32(IMC, 0xffffffff); - - /* Disable the Transmit and Receive units. Then delay to allow - * any pending transactions to complete before we hit the MAC with - * the global reset. - */ - ew32(RCTL, 0); - ew32(TCTL, E1000_TCTL_PSP); - E1000_WRITE_FLUSH(); - - /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */ - hw->tbi_compatibility_on = false; - - /* Delay to allow any outstanding PCI transactions to complete before - * resetting the device - */ - msleep(10); - - ctrl = er32(CTRL); - - /* Must reset the PHY before resetting the MAC */ - if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - ew32(CTRL, (ctrl | E1000_CTRL_PHY_RST)); - E1000_WRITE_FLUSH(); - msleep(5); - } - - /* Issue a global reset to the MAC. This will reset the chip's - * transmit, receive, DMA, and link units. It will not effect - * the current PCI configuration. The global reset bit is self- - * clearing, and should clear within a microsecond. - */ - e_dbg("Issuing a global reset to MAC\n"); - - switch (hw->mac_type) { - case e1000_82544: - case e1000_82540: - case e1000_82545: - case e1000_82546: - case e1000_82541: - case e1000_82541_rev_2: - /* These controllers can't ack the 64-bit write when issuing the - * reset, so use IO-mapping as a workaround to issue the reset - */ - E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); - break; - case e1000_82545_rev_3: - case e1000_82546_rev_3: - /* Reset is performed on a shadow of the control register */ - ew32(CTRL_DUP, (ctrl | E1000_CTRL_RST)); - break; - case e1000_ce4100: - default: - ew32(CTRL, (ctrl | E1000_CTRL_RST)); - break; - } - - /* After MAC reset, force reload of EEPROM to restore power-on settings - * to device. Later controllers reload the EEPROM automatically, so - * just wait for reload to complete. - */ - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - /* Wait for reset to complete */ - udelay(10); - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - ew32(CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(); - /* Wait for EEPROM reload */ - msleep(2); - break; - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - /* Wait for EEPROM reload */ - msleep(20); - break; - default: - /* Auto read done will delay 5ms or poll based on mac type */ - ret_val = e1000_get_auto_rd_done(hw); - if (ret_val) - return ret_val; - break; - } - - /* Disable HW ARPs on ASF enabled adapters */ - if (hw->mac_type >= e1000_82540) { - manc = er32(MANC); - manc &= ~(E1000_MANC_ARP_EN); - ew32(MANC, manc); - } - - if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - e1000_phy_init_script(hw); - - /* Configure activity LED after PHY reset */ - led_ctrl = er32(LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - ew32(LEDCTL, led_ctrl); - } - - /* Clear interrupt mask to stop board from generating interrupts */ - e_dbg("Masking off all interrupts\n"); - ew32(IMC, 0xffffffff); - - /* Clear any pending interrupt events. */ - icr = er32(ICR); - - /* If MWI was previously enabled, reenable it. */ - if (hw->mac_type == e1000_82542_rev2_0) { - if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE) - e1000_pci_set_mwi(hw); - } - - return E1000_SUCCESS; -} - -/** - * e1000_init_hw - Performs basic configuration of the adapter. - * @hw: Struct containing variables accessed by shared code - * - * Assumes that the controller has previously been reset and is in a - * post-reset uninitialized state. Initializes the receive address registers, - * multicast table, and VLAN filter table. Calls routines to setup link - * configuration and flow control settings. Clears all on-chip counters. Leaves - * the transmit and receive units disabled and uninitialized. - */ -s32 e1000_init_hw(struct e1000_hw *hw) -{ - u32 ctrl; - u32 i; - s32 ret_val; - u32 mta_size; - u32 ctrl_ext; - - e_dbg("e1000_init_hw"); - - /* Initialize Identification LED */ - ret_val = e1000_id_led_init(hw); - if (ret_val) { - e_dbg("Error Initializing Identification LED\n"); - return ret_val; - } - - /* Set the media type and TBI compatibility */ - e1000_set_media_type(hw); - - /* Disabling VLAN filtering. */ - e_dbg("Initializing the IEEE VLAN\n"); - if (hw->mac_type < e1000_82545_rev_3) - ew32(VET, 0); - e1000_clear_vfta(hw); - - /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ - if (hw->mac_type == e1000_82542_rev2_0) { - e_dbg("Disabling MWI on 82542 rev 2.0\n"); - e1000_pci_clear_mwi(hw); - ew32(RCTL, E1000_RCTL_RST); - E1000_WRITE_FLUSH(); - msleep(5); - } - - /* Setup the receive address. This involves initializing all of the - * Receive Address Registers (RARs 0 - 15). - */ - e1000_init_rx_addrs(hw); - - /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */ - if (hw->mac_type == e1000_82542_rev2_0) { - ew32(RCTL, 0); - E1000_WRITE_FLUSH(); - msleep(1); - if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE) - e1000_pci_set_mwi(hw); - } - - /* Zero out the Multicast HASH table */ - e_dbg("Zeroing the MTA\n"); - mta_size = E1000_MC_TBL_SIZE; - for (i = 0; i < mta_size; i++) { - E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); - /* use write flush to prevent Memory Write Block (MWB) from - * occurring when accessing our register space - */ - E1000_WRITE_FLUSH(); - } - - /* Set the PCI priority bit correctly in the CTRL register. This - * determines if the adapter gives priority to receives, or if it - * gives equal priority to transmits and receives. Valid only on - * 82542 and 82543 silicon. - */ - if (hw->dma_fairness && hw->mac_type <= e1000_82543) { - ctrl = er32(CTRL); - ew32(CTRL, ctrl | E1000_CTRL_PRIOR); - } - - switch (hw->mac_type) { - case e1000_82545_rev_3: - case e1000_82546_rev_3: - break; - default: - /* Workaround for PCI-X problem when BIOS sets MMRBC - * incorrectly. - */ - if (hw->bus_type == e1000_bus_type_pcix - && e1000_pcix_get_mmrbc(hw) > 2048) - e1000_pcix_set_mmrbc(hw, 2048); - break; - } - - /* Call a subroutine to configure the link and setup flow control. */ - ret_val = e1000_setup_link(hw); - - /* Set the transmit descriptor write-back policy */ - if (hw->mac_type > e1000_82544) { - ctrl = er32(TXDCTL); - ctrl = - (ctrl & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB; - ew32(TXDCTL, ctrl); - } - - /* Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs(hw); - - if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER || - hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) { - ctrl_ext = er32(CTRL_EXT); - /* Relaxed ordering must be disabled to avoid a parity - * error crash in a PCI slot. - */ - ctrl_ext |= E1000_CTRL_EXT_RO_DIS; - ew32(CTRL_EXT, ctrl_ext); - } - - return ret_val; -} - -/** - * e1000_adjust_serdes_amplitude - Adjust SERDES output amplitude based on EEPROM setting. - * @hw: Struct containing variables accessed by shared code. - */ -static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw) -{ - u16 eeprom_data; - s32 ret_val; - - e_dbg("e1000_adjust_serdes_amplitude"); - - if (hw->media_type != e1000_media_type_internal_serdes) - return E1000_SUCCESS; - - switch (hw->mac_type) { - case e1000_82545_rev_3: - case e1000_82546_rev_3: - break; - default: - return E1000_SUCCESS; - } - - ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1, - &eeprom_data); - if (ret_val) { - return ret_val; - } - - if (eeprom_data != EEPROM_RESERVED_WORD) { - /* Adjust SERDES output amplitude only. */ - eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data); - if (ret_val) - return ret_val; - } - - return E1000_SUCCESS; -} - -/** - * e1000_setup_link - Configures flow control and link settings. - * @hw: Struct containing variables accessed by shared code - * - * Determines which flow control settings to use. Calls the appropriate media- - * specific link configuration function. Configures the flow control settings. - * Assuming the adapter has a valid link partner, a valid link should be - * established. Assumes the hardware has previously been reset and the - * transmitter and receiver are not enabled. - */ -s32 e1000_setup_link(struct e1000_hw *hw) -{ - u32 ctrl_ext; - s32 ret_val; - u16 eeprom_data; - - e_dbg("e1000_setup_link"); - - /* Read and store word 0x0F of the EEPROM. This word contains bits - * that determine the hardware's default PAUSE (flow control) mode, - * a bit that determines whether the HW defaults to enabling or - * disabling auto-negotiation, and the direction of the - * SW defined pins. If there is no SW over-ride of the flow - * control setting, then the variable hw->fc will - * be initialized based on a value in the EEPROM. - */ - if (hw->fc == E1000_FC_DEFAULT) { - ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, - 1, &eeprom_data); - if (ret_val) { - e_dbg("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) - hw->fc = E1000_FC_NONE; - else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == - EEPROM_WORD0F_ASM_DIR) - hw->fc = E1000_FC_TX_PAUSE; - else - hw->fc = E1000_FC_FULL; - } - - /* We want to save off the original Flow Control configuration just - * in case we get disconnected and then reconnected into a different - * hub or switch with different Flow Control capabilities. - */ - if (hw->mac_type == e1000_82542_rev2_0) - hw->fc &= (~E1000_FC_TX_PAUSE); - - if ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1)) - hw->fc &= (~E1000_FC_RX_PAUSE); - - hw->original_fc = hw->fc; - - e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc); - - /* Take the 4 bits from EEPROM word 0x0F that determine the initial - * polarity value for the SW controlled pins, and setup the - * Extended Device Control reg with that info. - * This is needed because one of the SW controlled pins is used for - * signal detection. So this should be done before e1000_setup_pcs_link() - * or e1000_phy_setup() is called. - */ - if (hw->mac_type == e1000_82543) { - ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, - 1, &eeprom_data); - if (ret_val) { - e_dbg("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) << - SWDPIO__EXT_SHIFT); - ew32(CTRL_EXT, ctrl_ext); - } - - /* Call the necessary subroutine to configure the link. */ - ret_val = (hw->media_type == e1000_media_type_copper) ? - e1000_setup_copper_link(hw) : e1000_setup_fiber_serdes_link(hw); - - /* Initialize the flow control address, type, and PAUSE timer - * registers to their default values. This is done even if flow - * control is disabled, because it does not hurt anything to - * initialize these registers. - */ - e_dbg("Initializing the Flow Control address, type and timer regs\n"); - - ew32(FCT, FLOW_CONTROL_TYPE); - ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH); - ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW); - - ew32(FCTTV, hw->fc_pause_time); - - /* Set the flow control receive threshold registers. Normally, - * these registers will be set to a default threshold that may be - * adjusted later by the driver's runtime code. However, if the - * ability to transmit pause frames in not enabled, then these - * registers will be set to 0. - */ - if (!(hw->fc & E1000_FC_TX_PAUSE)) { - ew32(FCRTL, 0); - ew32(FCRTH, 0); - } else { - /* We need to set up the Receive Threshold high and low water - * marks as well as (optionally) enabling the transmission of - * XON frames. - */ - if (hw->fc_send_xon) { - ew32(FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE)); - ew32(FCRTH, hw->fc_high_water); - } else { - ew32(FCRTL, hw->fc_low_water); - ew32(FCRTH, hw->fc_high_water); - } - } - return ret_val; -} - -/** - * e1000_setup_fiber_serdes_link - prepare fiber or serdes link - * @hw: Struct containing variables accessed by shared code - * - * Manipulates Physical Coding Sublayer functions in order to configure - * link. Assumes the hardware has been previously reset and the transmitter - * and receiver are not enabled. - */ -static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw) -{ - u32 ctrl; - u32 status; - u32 txcw = 0; - u32 i; - u32 signal = 0; - s32 ret_val; - - e_dbg("e1000_setup_fiber_serdes_link"); - - /* On adapters with a MAC newer than 82544, SWDP 1 will be - * set when the optics detect a signal. On older adapters, it will be - * cleared when there is a signal. This applies to fiber media only. - * If we're on serdes media, adjust the output amplitude to value - * set in the EEPROM. - */ - ctrl = er32(CTRL); - if (hw->media_type == e1000_media_type_fiber) - signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; - - ret_val = e1000_adjust_serdes_amplitude(hw); - if (ret_val) - return ret_val; - - /* Take the link out of reset */ - ctrl &= ~(E1000_CTRL_LRST); - - /* Adjust VCO speed to improve BER performance */ - ret_val = e1000_set_vco_speed(hw); - if (ret_val) - return ret_val; - - e1000_config_collision_dist(hw); - - /* Check for a software override of the flow control settings, and setup - * the device accordingly. If auto-negotiation is enabled, then - * software will have to set the "PAUSE" bits to the correct value in - * the Tranmsit Config Word Register (TXCW) and re-start - * auto-negotiation. However, if auto-negotiation is disabled, then - * software will have to manually configure the two flow control enable - * bits in the CTRL register. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames, but - * not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but we do - * not support receiving pause frames). - * 3: Both Rx and TX flow control (symmetric) are enabled. - */ - switch (hw->fc) { - case E1000_FC_NONE: - /* Flow ctrl is completely disabled by a software over-ride */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); - break; - case E1000_FC_RX_PAUSE: - /* Rx Flow control is enabled and Tx Flow control is disabled by - * a software over-ride. Since there really isn't a way to - * advertise that we are capable of Rx Pause ONLY, we will - * advertise that we support both symmetric and asymmetric Rx - * PAUSE. Later, we will disable the adapter's ability to send - * PAUSE frames. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - case E1000_FC_TX_PAUSE: - /* Tx Flow control is enabled, and Rx Flow control is disabled, - * by a software over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); - break; - case E1000_FC_FULL: - /* Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - break; - } - - /* Since auto-negotiation is enabled, take the link out of reset (the - * link will be in reset, because we previously reset the chip). This - * will restart auto-negotiation. If auto-negotiation is successful - * then the link-up status bit will be set and the flow control enable - * bits (RFCE and TFCE) will be set according to their negotiated value. - */ - e_dbg("Auto-negotiation enabled\n"); - - ew32(TXCW, txcw); - ew32(CTRL, ctrl); - E1000_WRITE_FLUSH(); - - hw->txcw = txcw; - msleep(1); - - /* If we have a signal (the cable is plugged in) then poll for a - * "Link-Up" indication in the Device Status Register. Time-out if a - * link isn't seen in 500 milliseconds seconds (Auto-negotiation should - * complete in less than 500 milliseconds even if the other end is doing - * it in SW). For internal serdes, we just assume a signal is present, - * then poll. - */ - if (hw->media_type == e1000_media_type_internal_serdes || - (er32(CTRL) & E1000_CTRL_SWDPIN1) == signal) { - e_dbg("Looking for Link\n"); - for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) { - msleep(10); - status = er32(STATUS); - if (status & E1000_STATUS_LU) - break; - } - if (i == (LINK_UP_TIMEOUT / 10)) { - e_dbg("Never got a valid link from auto-neg!!!\n"); - hw->autoneg_failed = 1; - /* AutoNeg failed to achieve a link, so we'll call - * e1000_check_for_link. This routine will force the - * link up if we detect a signal. This will allow us to - * communicate with non-autonegotiating link partners. - */ - ret_val = e1000_check_for_link(hw); - if (ret_val) { - e_dbg("Error while checking for link\n"); - return ret_val; - } - hw->autoneg_failed = 0; - } else { - hw->autoneg_failed = 0; - e_dbg("Valid Link Found\n"); - } - } else { - e_dbg("No Signal Detected\n"); - } - return E1000_SUCCESS; -} - -/** - * e1000_copper_link_rtl_setup - Copper link setup for e1000_phy_rtl series. - * @hw: Struct containing variables accessed by shared code - * - * Commits changes to PHY configuration by calling e1000_phy_reset(). - */ -static s32 e1000_copper_link_rtl_setup(struct e1000_hw *hw) -{ - s32 ret_val; - - /* SW reset the PHY so all changes take effect */ - ret_val = e1000_phy_reset(hw); - if (ret_val) { - e_dbg("Error Resetting the PHY\n"); - return ret_val; - } - - return E1000_SUCCESS; -} - -static s32 gbe_dhg_phy_setup(struct e1000_hw *hw) -{ - s32 ret_val; - u32 ctrl_aux; - - switch (hw->phy_type) { - case e1000_phy_8211: - ret_val = e1000_copper_link_rtl_setup(hw); - if (ret_val) { - e_dbg("e1000_copper_link_rtl_setup failed!\n"); - return ret_val; - } - break; - case e1000_phy_8201: - /* Set RMII mode */ - ctrl_aux = er32(CTL_AUX); - ctrl_aux |= E1000_CTL_AUX_RMII; - ew32(CTL_AUX, ctrl_aux); - E1000_WRITE_FLUSH(); - - /* Disable the J/K bits required for receive */ - ctrl_aux = er32(CTL_AUX); - ctrl_aux |= 0x4; - ctrl_aux &= ~0x2; - ew32(CTL_AUX, ctrl_aux); - E1000_WRITE_FLUSH(); - ret_val = e1000_copper_link_rtl_setup(hw); - - if (ret_val) { - e_dbg("e1000_copper_link_rtl_setup failed!\n"); - return ret_val; - } - break; - default: - e_dbg("Error Resetting the PHY\n"); - return E1000_ERR_PHY_TYPE; - } - - return E1000_SUCCESS; -} - -/** - * e1000_copper_link_preconfig - early configuration for copper - * @hw: Struct containing variables accessed by shared code - * - * Make sure we have a valid PHY and change PHY mode before link setup. - */ -static s32 e1000_copper_link_preconfig(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 phy_data; - - e_dbg("e1000_copper_link_preconfig"); - - ctrl = er32(CTRL); - /* With 82543, we need to force speed and duplex on the MAC equal to - * what the PHY speed and duplex configuration is. In addition, we need - * to perform a hardware reset on the PHY to take it out of reset. - */ - if (hw->mac_type > e1000_82543) { - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ew32(CTRL, ctrl); - } else { - ctrl |= - (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU); - ew32(CTRL, ctrl); - ret_val = e1000_phy_hw_reset(hw); - if (ret_val) - return ret_val; - } - - /* Make sure we have a valid PHY */ - ret_val = e1000_detect_gig_phy(hw); - if (ret_val) { - e_dbg("Error, did not detect valid phy.\n"); - return ret_val; - } - e_dbg("Phy ID = %x\n", hw->phy_id); - - /* Set PHY to class A mode (if necessary) */ - ret_val = e1000_set_phy_mode(hw); - if (ret_val) - return ret_val; - - if ((hw->mac_type == e1000_82545_rev_3) || - (hw->mac_type == e1000_82546_rev_3)) { - ret_val = - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - phy_data |= 0x00000008; - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - } - - if (hw->mac_type <= e1000_82543 || - hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 || - hw->mac_type == e1000_82541_rev_2 - || hw->mac_type == e1000_82547_rev_2) - hw->phy_reset_disable = false; - - return E1000_SUCCESS; -} - -/** - * e1000_copper_link_igp_setup - Copper link setup for e1000_phy_igp series. - * @hw: Struct containing variables accessed by shared code - */ -static s32 e1000_copper_link_igp_setup(struct e1000_hw *hw) -{ - u32 led_ctrl; - s32 ret_val; - u16 phy_data; - - e_dbg("e1000_copper_link_igp_setup"); - - if (hw->phy_reset_disable) - return E1000_SUCCESS; - - ret_val = e1000_phy_reset(hw); - if (ret_val) { - e_dbg("Error Resetting the PHY\n"); - return ret_val; - } - - /* Wait 15ms for MAC to configure PHY from eeprom settings */ - msleep(15); - /* Configure activity LED after PHY reset */ - led_ctrl = er32(LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - ew32(LEDCTL, led_ctrl); - - /* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */ - if (hw->phy_type == e1000_phy_igp) { - /* disable lplu d3 during driver init */ - ret_val = e1000_set_d3_lplu_state(hw, false); - if (ret_val) { - e_dbg("Error Disabling LPLU D3\n"); - return ret_val; - } - } - - /* Configure mdi-mdix settings */ - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); - if (ret_val) - return ret_val; - - if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - hw->dsp_config_state = e1000_dsp_config_disabled; - /* Force MDI for earlier revs of the IGP PHY */ - phy_data &= - ~(IGP01E1000_PSCR_AUTO_MDIX | - IGP01E1000_PSCR_FORCE_MDI_MDIX); - hw->mdix = 1; - - } else { - hw->dsp_config_state = e1000_dsp_config_enabled; - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - - switch (hw->mdix) { - case 1: - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 2: - phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 0: - default: - phy_data |= IGP01E1000_PSCR_AUTO_MDIX; - break; - } - } - ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); - if (ret_val) - return ret_val; - - /* set auto-master slave resolution settings */ - if (hw->autoneg) { - e1000_ms_type phy_ms_setting = hw->master_slave; - - if (hw->ffe_config_state == e1000_ffe_config_active) - hw->ffe_config_state = e1000_ffe_config_enabled; - - if (hw->dsp_config_state == e1000_dsp_config_activated) - hw->dsp_config_state = e1000_dsp_config_enabled; - - /* when autonegotiation advertisement is only 1000Mbps then we - * should disable SmartSpeed and enable Auto MasterSlave - * resolution as hardware default. - */ - if (hw->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data); - if (ret_val) - return ret_val; - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - phy_data); - if (ret_val) - return ret_val; - /* Set auto Master/Slave resolution process */ - ret_val = - e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data); - if (ret_val) - return ret_val; - phy_data &= ~CR_1000T_MS_ENABLE; - ret_val = - e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); - if (ret_val) - return ret_val; - } - - ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data); - if (ret_val) - return ret_val; - - /* load defaults for future use */ - hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ? - ((phy_data & CR_1000T_MS_VALUE) ? - e1000_ms_force_master : - e1000_ms_force_slave) : e1000_ms_auto; - - switch (phy_ms_setting) { - case e1000_ms_force_master: - phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); - break; - case e1000_ms_force_slave: - phy_data |= CR_1000T_MS_ENABLE; - phy_data &= ~(CR_1000T_MS_VALUE); - break; - case e1000_ms_auto: - phy_data &= ~CR_1000T_MS_ENABLE; - default: - break; - } - ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); - if (ret_val) - return ret_val; - } - - return E1000_SUCCESS; -} - -/** - * e1000_copper_link_mgp_setup - Copper link setup for e1000_phy_m88 series. - * @hw: Struct containing variables accessed by shared code - */ -static s32 e1000_copper_link_mgp_setup(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - - e_dbg("e1000_copper_link_mgp_setup"); - - if (hw->phy_reset_disable) - return E1000_SUCCESS; - - /* Enable CRS on TX. This must be set for half-duplex operation. */ - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - - /* Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - - switch (hw->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } - - /* Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if (hw->disable_polarity_correction == 1) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - if (hw->phy_revision < M88E1011_I_REV_4) { - /* Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - ret_val = - e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_EPSCR_TX_CLK_25; - - if ((hw->phy_revision == E1000_REVISION_2) && - (hw->phy_id == M88E1111_I_PHY_ID)) { - /* Vidalia Phy, set the downshift counter to 5x */ - phy_data &= ~(M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK); - phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; - ret_val = e1000_write_phy_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, - phy_data); - if (ret_val) - return ret_val; - } else { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - ret_val = e1000_write_phy_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, - phy_data); - if (ret_val) - return ret_val; - } - } - - /* SW Reset the PHY so all changes take effect */ - ret_val = e1000_phy_reset(hw); - if (ret_val) { - e_dbg("Error Resetting the PHY\n"); - return ret_val; - } - - return E1000_SUCCESS; -} - -/** - * e1000_copper_link_autoneg - setup auto-neg - * @hw: Struct containing variables accessed by shared code - * - * Setup auto-negotiation and flow control advertisements, - * and then perform auto-negotiation. - */ -static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - - e_dbg("e1000_copper_link_autoneg"); - - /* Perform some bounds checking on the hw->autoneg_advertised - * parameter. If this variable is zero, then set it to the default. - */ - hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT; - - /* If autoneg_advertised is zero, we assume it was not defaulted - * by the calling code so we set to advertise full capability. - */ - if (hw->autoneg_advertised == 0) - hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; - - /* IFE/RTL8201N PHY only supports 10/100 */ - if (hw->phy_type == e1000_phy_8201) - hw->autoneg_advertised &= AUTONEG_ADVERTISE_10_100_ALL; - - e_dbg("Reconfiguring auto-neg advertisement params\n"); - ret_val = e1000_phy_setup_autoneg(hw); - if (ret_val) { - e_dbg("Error Setting up Auto-Negotiation\n"); - return ret_val; - } - e_dbg("Restarting Auto-Neg\n"); - - /* Restart auto-negotiation by setting the Auto Neg Enable bit and - * the Auto Neg Restart bit in the PHY control register. - */ - ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); - ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data); - if (ret_val) - return ret_val; - - /* Does the user want to wait for Auto-Neg to complete here, or - * check at a later time (for example, callback routine). - */ - if (hw->wait_autoneg_complete) { - ret_val = e1000_wait_autoneg(hw); - if (ret_val) { - e_dbg - ("Error while waiting for autoneg to complete\n"); - return ret_val; - } - } - - hw->get_link_status = true; - - return E1000_SUCCESS; -} - -/** - * e1000_copper_link_postconfig - post link setup - * @hw: Struct containing variables accessed by shared code - * - * Config the MAC and the PHY after link is up. - * 1) Set up the MAC to the current PHY speed/duplex - * if we are on 82543. If we - * are on newer silicon, we only need to configure - * collision distance in the Transmit Control Register. - * 2) Set up flow control on the MAC to that established with - * the link partner. - * 3) Config DSP to improve Gigabit link quality for some PHY revisions. - */ -static s32 e1000_copper_link_postconfig(struct e1000_hw *hw) -{ - s32 ret_val; - e_dbg("e1000_copper_link_postconfig"); - - if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100)) { - e1000_config_collision_dist(hw); - } else { - ret_val = e1000_config_mac_to_phy(hw); - if (ret_val) { - e_dbg("Error configuring MAC to PHY settings\n"); - return ret_val; - } - } - ret_val = e1000_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error Configuring Flow Control\n"); - return ret_val; - } - - /* Config DSP to improve Giga link quality */ - if (hw->phy_type == e1000_phy_igp) { - ret_val = e1000_config_dsp_after_link_change(hw, true); - if (ret_val) { - e_dbg("Error Configuring DSP after link up\n"); - return ret_val; - } - } - - return E1000_SUCCESS; -} - -/** - * e1000_setup_copper_link - phy/speed/duplex setting - * @hw: Struct containing variables accessed by shared code - * - * Detects which PHY is present and sets up the speed and duplex - */ -static s32 e1000_setup_copper_link(struct e1000_hw *hw) -{ - s32 ret_val; - u16 i; - u16 phy_data; - - e_dbg("e1000_setup_copper_link"); - - /* Check if it is a valid PHY and set PHY mode if necessary. */ - ret_val = e1000_copper_link_preconfig(hw); - if (ret_val) - return ret_val; - - if (hw->phy_type == e1000_phy_igp) { - ret_val = e1000_copper_link_igp_setup(hw); - if (ret_val) - return ret_val; - } else if (hw->phy_type == e1000_phy_m88) { - ret_val = e1000_copper_link_mgp_setup(hw); - if (ret_val) - return ret_val; - } else { - ret_val = gbe_dhg_phy_setup(hw); - if (ret_val) { - e_dbg("gbe_dhg_phy_setup failed!\n"); - return ret_val; - } - } - - if (hw->autoneg) { - /* Setup autoneg and flow control advertisement - * and perform autonegotiation - */ - ret_val = e1000_copper_link_autoneg(hw); - if (ret_val) - return ret_val; - } else { - /* PHY will be set to 10H, 10F, 100H,or 100F - * depending on value from forced_speed_duplex. - */ - e_dbg("Forcing speed and duplex\n"); - ret_val = e1000_phy_force_speed_duplex(hw); - if (ret_val) { - e_dbg("Error Forcing Speed and Duplex\n"); - return ret_val; - } - } - - /* Check link status. Wait up to 100 microseconds for link to become - * valid. - */ - for (i = 0; i < 10; i++) { - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - - if (phy_data & MII_SR_LINK_STATUS) { - /* Config the MAC and PHY after link is up */ - ret_val = e1000_copper_link_postconfig(hw); - if (ret_val) - return ret_val; - - e_dbg("Valid link established!!!\n"); - return E1000_SUCCESS; - } - udelay(10); - } - - e_dbg("Unable to establish link!!!\n"); - return E1000_SUCCESS; -} - -/** - * e1000_phy_setup_autoneg - phy settings - * @hw: Struct containing variables accessed by shared code - * - * Configures PHY autoneg and flow control advertisement settings - */ -s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) -{ - s32 ret_val; - u16 mii_autoneg_adv_reg; - u16 mii_1000t_ctrl_reg; - - e_dbg("e1000_phy_setup_autoneg"); - - /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); - if (ret_val) - return ret_val; - - /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); - if (ret_val) - return ret_val; - else if (hw->phy_type == e1000_phy_8201) - mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK; - - /* Need to parse both autoneg_advertised and fc and set up - * the appropriate PHY registers. First we will parse for - * autoneg_advertised software override. Since we can advertise - * a plethora of combinations, we need to check each bit - * individually. - */ - - /* First we clear all the 10/100 mb speed bits in the Auto-Neg - * Advertisement Register (Address 4) and the 1000 mb speed bits in - * the 1000Base-T Control Register (Address 9). - */ - mii_autoneg_adv_reg &= ~REG4_SPEED_MASK; - mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK; - - e_dbg("autoneg_advertised %x\n", hw->autoneg_advertised); - - /* Do we want to advertise 10 Mb Half Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_10_HALF) { - e_dbg("Advertise 10mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; - } - - /* Do we want to advertise 10 Mb Full Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_10_FULL) { - e_dbg("Advertise 10mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; - } - - /* Do we want to advertise 100 Mb Half Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_100_HALF) { - e_dbg("Advertise 100mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; - } - - /* Do we want to advertise 100 Mb Full Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_100_FULL) { - e_dbg("Advertise 100mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; - } - - /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ - if (hw->autoneg_advertised & ADVERTISE_1000_HALF) { - e_dbg - ("Advertise 1000mb Half duplex requested, request denied!\n"); - } - - /* Do we want to advertise 1000 Mb Full Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_1000_FULL) { - e_dbg("Advertise 1000mb Full duplex\n"); - mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; - } - - /* Check for a software override of the flow control settings, and - * setup the PHY advertisement registers accordingly. If - * auto-negotiation is enabled, then software will have to set the - * "PAUSE" bits to the correct value in the Auto-Negotiation - * Advertisement Register (PHY_AUTONEG_ADV) and re-start - * auto-negotiation. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * but we do not support receiving pause frames). - * 3: Both Rx and TX flow control (symmetric) are enabled. - * other: No software override. The flow control configuration - * in the EEPROM is used. - */ - switch (hw->fc) { - case E1000_FC_NONE: /* 0 */ - /* Flow control (RX & TX) is completely disabled by a - * software over-ride. - */ - mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case E1000_FC_RX_PAUSE: /* 1 */ - /* RX Flow control is enabled, and TX Flow control is - * disabled, by a software over-ride. - */ - /* Since there really isn't a way to advertise that we are - * capable of RX Pause ONLY, we will advertise that we - * support both symmetric and asymmetric RX PAUSE. Later - * (in e1000_config_fc_after_link_up) we will disable the - * hw's ability to send PAUSE frames. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case E1000_FC_TX_PAUSE: /* 2 */ - /* TX Flow control is enabled, and RX Flow control is - * disabled, by a software over-ride. - */ - mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; - mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; - break; - case E1000_FC_FULL: /* 3 */ - /* Flow control (both RX and TX) is enabled by a software - * over-ride. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - } - - ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); - if (ret_val) - return ret_val; - - e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - - if (hw->phy_type == e1000_phy_8201) { - mii_1000t_ctrl_reg = 0; - } else { - ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, - mii_1000t_ctrl_reg); - if (ret_val) - return ret_val; - } - - return E1000_SUCCESS; -} - -/** - * e1000_phy_force_speed_duplex - force link settings - * @hw: Struct containing variables accessed by shared code - * - * Force PHY speed and duplex settings to hw->forced_speed_duplex - */ -static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 mii_ctrl_reg; - u16 mii_status_reg; - u16 phy_data; - u16 i; - - e_dbg("e1000_phy_force_speed_duplex"); - - /* Turn off Flow control if we are forcing speed and duplex. */ - hw->fc = E1000_FC_NONE; - - e_dbg("hw->fc = %d\n", hw->fc); - - /* Read the Device Control Register. */ - ctrl = er32(CTRL); - - /* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */ - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ctrl &= ~(DEVICE_SPEED_MASK); - - /* Clear the Auto Speed Detect Enable bit. */ - ctrl &= ~E1000_CTRL_ASDE; - - /* Read the MII Control Register. */ - ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg); - if (ret_val) - return ret_val; - - /* We need to disable autoneg in order to force link and duplex. */ - - mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN; - - /* Are we forcing Full or Half Duplex? */ - if (hw->forced_speed_duplex == e1000_100_full || - hw->forced_speed_duplex == e1000_10_full) { - /* We want to force full duplex so we SET the full duplex bits - * in the Device and MII Control Registers. - */ - ctrl |= E1000_CTRL_FD; - mii_ctrl_reg |= MII_CR_FULL_DUPLEX; - e_dbg("Full Duplex\n"); - } else { - /* We want to force half duplex so we CLEAR the full duplex bits - * in the Device and MII Control Registers. - */ - ctrl &= ~E1000_CTRL_FD; - mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX; - e_dbg("Half Duplex\n"); - } - - /* Are we forcing 100Mbps??? */ - if (hw->forced_speed_duplex == e1000_100_full || - hw->forced_speed_duplex == e1000_100_half) { - /* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */ - ctrl |= E1000_CTRL_SPD_100; - mii_ctrl_reg |= MII_CR_SPEED_100; - mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10); - e_dbg("Forcing 100mb "); - } else { - /* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */ - ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - mii_ctrl_reg |= MII_CR_SPEED_10; - mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); - e_dbg("Forcing 10mb "); - } - - e1000_config_collision_dist(hw); - - /* Write the configured values back to the Device Control Reg. */ - ew32(CTRL, ctrl); - - if (hw->phy_type == e1000_phy_m88) { - ret_val = - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - /* Clear Auto-Crossover to force MDI manually. M88E1000 requires - * MDI forced whenever speed are duplex are forced. - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - e_dbg("M88E1000 PSCR: %x\n", phy_data); - - /* Need to reset the PHY or these changes will be ignored */ - mii_ctrl_reg |= MII_CR_RESET; - - /* Disable MDI-X support for 10/100 */ - } else { - /* Clear Auto-Crossover to force MDI manually. IGP requires MDI - * forced whenever speed or duplex are forced. - */ - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); - if (ret_val) - return ret_val; - } - - /* Write back the modified PHY MII control register. */ - ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg); - if (ret_val) - return ret_val; - - udelay(1); - - /* The wait_autoneg_complete flag may be a little misleading here. - * Since we are forcing speed and duplex, Auto-Neg is not enabled. - * But we do want to delay for a period while forcing only so we - * don't generate false No Link messages. So we will wait here - * only if the user has set wait_autoneg_complete to 1, which is - * the default. - */ - if (hw->wait_autoneg_complete) { - /* We will wait for autoneg to complete. */ - e_dbg("Waiting for forced speed/duplex link.\n"); - mii_status_reg = 0; - - /* Wait for autoneg to complete or 4.5 seconds to expire */ - for (i = PHY_FORCE_TIME; i > 0; i--) { - /* Read the MII Status Register and wait for Auto-Neg - * Complete bit to be set. - */ - ret_val = - e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - ret_val = - e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - if (mii_status_reg & MII_SR_LINK_STATUS) - break; - msleep(100); - } - if ((i == 0) && (hw->phy_type == e1000_phy_m88)) { - /* We didn't get link. Reset the DSP and wait again - * for link. - */ - ret_val = e1000_phy_reset_dsp(hw); - if (ret_val) { - e_dbg("Error Resetting PHY DSP\n"); - return ret_val; - } - } - /* This loop will early-out if the link condition has been - * met - */ - for (i = PHY_FORCE_TIME; i > 0; i--) { - if (mii_status_reg & MII_SR_LINK_STATUS) - break; - msleep(100); - /* Read the MII Status Register and wait for Auto-Neg - * Complete bit to be set. - */ - ret_val = - e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - ret_val = - e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - } - } - - if (hw->phy_type == e1000_phy_m88) { - /* Because we reset the PHY above, we need to re-force TX_CLK in - * the Extended PHY Specific Control Register to 25MHz clock. - * This value defaults back to a 2.5MHz clock when the PHY is - * reset. - */ - ret_val = - e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_EPSCR_TX_CLK_25; - ret_val = - e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - phy_data); - if (ret_val) - return ret_val; - - /* In addition, because of the s/w reset above, we need to - * enable CRS on Tx. This must be set for both full and half - * duplex operation. - */ - ret_val = - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - if ((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) - && (!hw->autoneg) - && (hw->forced_speed_duplex == e1000_10_full - || hw->forced_speed_duplex == e1000_10_half)) { - ret_val = e1000_polarity_reversal_workaround(hw); - if (ret_val) - return ret_val; - } - } - return E1000_SUCCESS; -} - -/** - * e1000_config_collision_dist - set collision distance register - * @hw: Struct containing variables accessed by shared code - * - * Sets the collision distance in the Transmit Control register. - * Link should have been established previously. Reads the speed and duplex - * information from the Device Status register. - */ -void e1000_config_collision_dist(struct e1000_hw *hw) -{ - u32 tctl, coll_dist; - - e_dbg("e1000_config_collision_dist"); - - if (hw->mac_type < e1000_82543) - coll_dist = E1000_COLLISION_DISTANCE_82542; - else - coll_dist = E1000_COLLISION_DISTANCE; - - tctl = er32(TCTL); - - tctl &= ~E1000_TCTL_COLD; - tctl |= coll_dist << E1000_COLD_SHIFT; - - ew32(TCTL, tctl); - E1000_WRITE_FLUSH(); -} - -/** - * e1000_config_mac_to_phy - sync phy and mac settings - * @hw: Struct containing variables accessed by shared code - * @mii_reg: data to write to the MII control register - * - * Sets MAC speed and duplex settings to reflect the those in the PHY - * The contents of the PHY register containing the needed information need to - * be passed in. - */ -static s32 e1000_config_mac_to_phy(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 phy_data; - - e_dbg("e1000_config_mac_to_phy"); - - /* 82544 or newer MAC, Auto Speed Detection takes care of - * MAC speed/duplex configuration. - */ - if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100)) - return E1000_SUCCESS; - - /* Read the Device Control Register and set the bits to Force Speed - * and Duplex. - */ - ctrl = er32(CTRL); - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS); - - switch (hw->phy_type) { - case e1000_phy_8201: - ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data); - if (ret_val) - return ret_val; - - if (phy_data & RTL_PHY_CTRL_FD) - ctrl |= E1000_CTRL_FD; - else - ctrl &= ~E1000_CTRL_FD; - - if (phy_data & RTL_PHY_CTRL_SPD_100) - ctrl |= E1000_CTRL_SPD_100; - else - ctrl |= E1000_CTRL_SPD_10; - - e1000_config_collision_dist(hw); - break; - default: - /* Set up duplex in the Device Control and Transmit Control - * registers depending on negotiated values. - */ - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data); - if (ret_val) - return ret_val; - - if (phy_data & M88E1000_PSSR_DPLX) - ctrl |= E1000_CTRL_FD; - else - ctrl &= ~E1000_CTRL_FD; - - e1000_config_collision_dist(hw); - - /* Set up speed in the Device Control register depending on - * negotiated values. - */ - if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) - ctrl |= E1000_CTRL_SPD_1000; - else if ((phy_data & M88E1000_PSSR_SPEED) == - M88E1000_PSSR_100MBS) - ctrl |= E1000_CTRL_SPD_100; - } - - /* Write the configured values back to the Device Control Reg. */ - ew32(CTRL, ctrl); - return E1000_SUCCESS; -} - -/** - * e1000_force_mac_fc - force flow control settings - * @hw: Struct containing variables accessed by shared code - * - * Forces the MAC's flow control settings. - * Sets the TFCE and RFCE bits in the device control register to reflect - * the adapter settings. TFCE and RFCE need to be explicitly set by - * software when a Copper PHY is used because autonegotiation is managed - * by the PHY rather than the MAC. Software must also configure these - * bits when link is forced on a fiber connection. - */ -s32 e1000_force_mac_fc(struct e1000_hw *hw) -{ - u32 ctrl; - - e_dbg("e1000_force_mac_fc"); - - /* Get the current configuration of the Device Control Register */ - ctrl = er32(CTRL); - - /* Because we didn't get link via the internal auto-negotiation - * mechanism (we either forced link or we got link via PHY - * auto-neg), we have to manually enable/disable transmit an - * receive flow control. - * - * The "Case" statement below enables/disable flow control - * according to the "hw->fc" parameter. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause - * frames but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * frames but we do not receive pause frames). - * 3: Both Rx and TX flow control (symmetric) is enabled. - * other: No other values should be possible at this point. - */ - - switch (hw->fc) { - case E1000_FC_NONE: - ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); - break; - case E1000_FC_RX_PAUSE: - ctrl &= (~E1000_CTRL_TFCE); - ctrl |= E1000_CTRL_RFCE; - break; - case E1000_FC_TX_PAUSE: - ctrl &= (~E1000_CTRL_RFCE); - ctrl |= E1000_CTRL_TFCE; - break; - case E1000_FC_FULL: - ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - } - - /* Disable TX Flow Control for 82542 (rev 2.0) */ - if (hw->mac_type == e1000_82542_rev2_0) - ctrl &= (~E1000_CTRL_TFCE); - - ew32(CTRL, ctrl); - return E1000_SUCCESS; -} - -/** - * e1000_config_fc_after_link_up - configure flow control after autoneg - * @hw: Struct containing variables accessed by shared code - * - * Configures flow control settings after link is established - * Should be called immediately after a valid link has been established. - * Forces MAC flow control settings if link was forced. When in MII/GMII mode - * and autonegotiation is enabled, the MAC flow control settings will be set - * based on the flow control negotiated by the PHY. In TBI mode, the TFCE - * and RFCE bits will be automatically set to the negotiated flow control mode. - */ -static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw) -{ - s32 ret_val; - u16 mii_status_reg; - u16 mii_nway_adv_reg; - u16 mii_nway_lp_ability_reg; - u16 speed; - u16 duplex; - - e_dbg("e1000_config_fc_after_link_up"); - - /* Check for the case where we have fiber media and auto-neg failed - * so we had to force link. In this case, we need to force the - * configuration of the MAC to match the "fc" parameter. - */ - if (((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) - || ((hw->media_type == e1000_media_type_internal_serdes) - && (hw->autoneg_failed)) - || ((hw->media_type == e1000_media_type_copper) - && (!hw->autoneg))) { - ret_val = e1000_force_mac_fc(hw); - if (ret_val) { - e_dbg("Error forcing flow control settings\n"); - return ret_val; - } - } - - /* Check for the case where we have copper media and auto-neg is - * enabled. In this case, we need to check and see if Auto-Neg - * has completed, and if so, how the PHY and link partner has - * flow control configured. - */ - if ((hw->media_type == e1000_media_type_copper) && hw->autoneg) { - /* Read the MII Status Register and check to see if AutoNeg - * has completed. We read this twice because this reg has - * some "sticky" (latched) bits. - */ - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - if (mii_status_reg & MII_SR_AUTONEG_COMPLETE) { - /* The AutoNeg process has completed, so we now need to - * read both the Auto Negotiation Advertisement Register - * (Address 4) and the Auto_Negotiation Base Page - * Ability Register (Address 5) to determine how flow - * control was negotiated. - */ - ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, - &mii_nway_adv_reg); - if (ret_val) - return ret_val; - ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, - &mii_nway_lp_ability_reg); - if (ret_val) - return ret_val; - - /* Two bits in the Auto Negotiation Advertisement - * Register (Address 4) and two bits in the Auto - * Negotiation Base Page Ability Register (Address 5) - * determine flow control for both the PHY and the link - * partner. The following table, taken out of the IEEE - * 802.3ab/D6.0 dated March 25, 1999, describes these - * PAUSE resolution bits and how flow control is - * determined based upon these settings. - * NOTE: DC = Don't Care - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution - *-------|---------|-------|---------|------------------ - * 0 | 0 | DC | DC | E1000_FC_NONE - * 0 | 1 | 0 | DC | E1000_FC_NONE - * 0 | 1 | 1 | 0 | E1000_FC_NONE - * 0 | 1 | 1 | 1 | E1000_FC_TX_PAUSE - * 1 | 0 | 0 | DC | E1000_FC_NONE - * 1 | DC | 1 | DC | E1000_FC_FULL - * 1 | 1 | 0 | 0 | E1000_FC_NONE - * 1 | 1 | 0 | 1 | E1000_FC_RX_PAUSE - * - */ - /* Are both PAUSE bits set to 1? If so, this implies - * Symmetric Flow Control is enabled at both ends. The - * ASM_DIR bits are irrelevant per the spec. - * - * For Symmetric Flow Control: - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|------------------ - * 1 | DC | 1 | DC | E1000_FC_FULL - * - */ - if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { - /* Now we need to check if the user selected Rx - * ONLY of pause frames. In this case, we had - * to advertise FULL flow control because we - * could not advertise Rx ONLY. Hence, we must - * now check to see if we need to turn OFF the - * TRANSMISSION of PAUSE frames. - */ - if (hw->original_fc == E1000_FC_FULL) { - hw->fc = E1000_FC_FULL; - e_dbg("Flow Control = FULL.\n"); - } else { - hw->fc = E1000_FC_RX_PAUSE; - e_dbg - ("Flow Control = RX PAUSE frames only.\n"); - } - } - /* For receiving PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|------------------ - * 0 | 1 | 1 | 1 | E1000_FC_TX_PAUSE - * - */ - else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) - { - hw->fc = E1000_FC_TX_PAUSE; - e_dbg - ("Flow Control = TX PAUSE frames only.\n"); - } - /* For transmitting PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|------------------ - * 1 | 1 | 0 | 1 | E1000_FC_RX_PAUSE - * - */ - else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) - { - hw->fc = E1000_FC_RX_PAUSE; - e_dbg - ("Flow Control = RX PAUSE frames only.\n"); - } - /* Per the IEEE spec, at this point flow control should - * be disabled. However, we want to consider that we - * could be connected to a legacy switch that doesn't - * advertise desired flow control, but can be forced on - * the link partner. So if we advertised no flow - * control, that is what we will resolve to. If we - * advertised some kind of receive capability (Rx Pause - * Only or Full Flow Control) and the link partner - * advertised none, we will configure ourselves to - * enable Rx Flow Control only. We can do this safely - * for two reasons: If the link partner really - * didn't want flow control enabled, and we enable Rx, - * no harm done since we won't be receiving any PAUSE - * frames anyway. If the intent on the link partner was - * to have flow control enabled, then by us enabling Rx - * only, we can at least receive pause frames and - * process them. This is a good idea because in most - * cases, since we are predominantly a server NIC, more - * times than not we will be asked to delay transmission - * of packets than asking our link partner to pause - * transmission of frames. - */ - else if ((hw->original_fc == E1000_FC_NONE || - hw->original_fc == E1000_FC_TX_PAUSE) || - hw->fc_strict_ieee) { - hw->fc = E1000_FC_NONE; - e_dbg("Flow Control = NONE.\n"); - } else { - hw->fc = E1000_FC_RX_PAUSE; - e_dbg - ("Flow Control = RX PAUSE frames only.\n"); - } - - /* Now we need to do one last check... If we auto- - * negotiated to HALF DUPLEX, flow control should not be - * enabled per IEEE 802.3 spec. - */ - ret_val = - e1000_get_speed_and_duplex(hw, &speed, &duplex); - if (ret_val) { - e_dbg - ("Error getting link speed and duplex\n"); - return ret_val; - } - - if (duplex == HALF_DUPLEX) - hw->fc = E1000_FC_NONE; - - /* Now we call a subroutine to actually force the MAC - * controller to use the correct flow control settings. - */ - ret_val = e1000_force_mac_fc(hw); - if (ret_val) { - e_dbg - ("Error forcing flow control settings\n"); - return ret_val; - } - } else { - e_dbg - ("Copper PHY and Auto Neg has not completed.\n"); - } - } - return E1000_SUCCESS; -} - -/** - * e1000_check_for_serdes_link_generic - Check for link (Serdes) - * @hw: pointer to the HW structure - * - * Checks for link up on the hardware. If link is not up and we have - * a signal, then we need to force link up. - */ -static s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) -{ - u32 rxcw; - u32 ctrl; - u32 status; - s32 ret_val = E1000_SUCCESS; - - e_dbg("e1000_check_for_serdes_link_generic"); - - ctrl = er32(CTRL); - status = er32(STATUS); - rxcw = er32(RXCW); - - /* If we don't have link (auto-negotiation failed or link partner - * cannot auto-negotiate), and our link partner is not trying to - * auto-negotiate with us (we are receiving idles or data), - * we need to force link up. We also need to give auto-negotiation - * time to complete. - */ - /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) { - if (hw->autoneg_failed == 0) { - hw->autoneg_failed = 1; - goto out; - } - e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n"); - - /* Disable auto-negotiation in the TXCW register */ - ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = er32(CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - ew32(CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - ret_val = e1000_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error configuring flow control\n"); - goto out; - } - } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* If we are forcing link and we are receiving /C/ ordered - * sets, re-enable auto-negotiation in the TXCW register - * and disable forced link in the Device Control register - * in an attempt to auto-negotiate with our link partner. - */ - e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n"); - ew32(TXCW, hw->txcw); - ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - - hw->serdes_has_link = true; - } else if (!(E1000_TXCW_ANE & er32(TXCW))) { - /* If we force link for non-auto-negotiation switch, check - * link status based on MAC synchronization for internal - * serdes media type. - */ - /* SYNCH bit and IV bit are sticky. */ - udelay(10); - rxcw = er32(RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - hw->serdes_has_link = true; - e_dbg("SERDES: Link up - forced.\n"); - } - } else { - hw->serdes_has_link = false; - e_dbg("SERDES: Link down - force failed.\n"); - } - } - - if (E1000_TXCW_ANE & er32(TXCW)) { - status = er32(STATUS); - if (status & E1000_STATUS_LU) { - /* SYNCH bit and IV bit are sticky, so reread rxcw. */ - udelay(10); - rxcw = er32(RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - hw->serdes_has_link = true; - e_dbg("SERDES: Link up - autoneg " - "completed successfully.\n"); - } else { - hw->serdes_has_link = false; - e_dbg("SERDES: Link down - invalid" - "codewords detected in autoneg.\n"); - } - } else { - hw->serdes_has_link = false; - e_dbg("SERDES: Link down - no sync.\n"); - } - } else { - hw->serdes_has_link = false; - e_dbg("SERDES: Link down - autoneg failed\n"); - } - } - - out: - return ret_val; -} - -/** - * e1000_check_for_link - * @hw: Struct containing variables accessed by shared code - * - * Checks to see if the link status of the hardware has changed. - * Called by any function that needs to check the link status of the adapter. - */ -s32 e1000_check_for_link(struct e1000_hw *hw) -{ - u32 rxcw = 0; - u32 ctrl; - u32 status; - u32 rctl; - u32 icr; - u32 signal = 0; - s32 ret_val; - u16 phy_data; - - e_dbg("e1000_check_for_link"); - - ctrl = er32(CTRL); - status = er32(STATUS); - - /* On adapters with a MAC newer than 82544, SW Definable pin 1 will be - * set when the optics detect a signal. On older adapters, it will be - * cleared when there is a signal. This applies to fiber media only. - */ - if ((hw->media_type == e1000_media_type_fiber) || - (hw->media_type == e1000_media_type_internal_serdes)) { - rxcw = er32(RXCW); - - if (hw->media_type == e1000_media_type_fiber) { - signal = - (hw->mac_type > - e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; - if (status & E1000_STATUS_LU) - hw->get_link_status = false; - } - } - - /* If we have a copper PHY then we only want to go out to the PHY - * registers to see if Auto-Neg has completed and/or if our link - * status has changed. The get_link_status flag will be set if we - * receive a Link Status Change interrupt or we have Rx Sequence - * Errors. - */ - if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) { - /* First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * of the PHY. - * Read the register twice since the link bit is sticky. - */ - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - - if (phy_data & MII_SR_LINK_STATUS) { - hw->get_link_status = false; - /* Check if there was DownShift, must be checked - * immediately after link-up - */ - e1000_check_downshift(hw); - - /* If we are on 82544 or 82543 silicon and speed/duplex - * are forced to 10H or 10F, then we will implement the - * polarity reversal workaround. We disable interrupts - * first, and upon returning, place the devices - * interrupt state to its previous value except for the - * link status change interrupt which will - * happen due to the execution of this workaround. - */ - - if ((hw->mac_type == e1000_82544 - || hw->mac_type == e1000_82543) && (!hw->autoneg) - && (hw->forced_speed_duplex == e1000_10_full - || hw->forced_speed_duplex == e1000_10_half)) { - ew32(IMC, 0xffffffff); - ret_val = - e1000_polarity_reversal_workaround(hw); - icr = er32(ICR); - ew32(ICS, (icr & ~E1000_ICS_LSC)); - ew32(IMS, IMS_ENABLE_MASK); - } - - } else { - /* No link detected */ - e1000_config_dsp_after_link_change(hw, false); - return 0; - } - - /* If we are forcing speed/duplex, then we simply return since - * we have already determined whether we have link or not. - */ - if (!hw->autoneg) - return -E1000_ERR_CONFIG; - - /* optimize the dsp settings for the igp phy */ - e1000_config_dsp_after_link_change(hw, true); - - /* We have a M88E1000 PHY and Auto-Neg is enabled. If we - * have Si on board that is 82544 or newer, Auto - * Speed Detection takes care of MAC speed/duplex - * configuration. So we only need to configure Collision - * Distance in the MAC. Otherwise, we need to force - * speed/duplex on the MAC to the current PHY speed/duplex - * settings. - */ - if ((hw->mac_type >= e1000_82544) && - (hw->mac_type != e1000_ce4100)) - e1000_config_collision_dist(hw); - else { - ret_val = e1000_config_mac_to_phy(hw); - if (ret_val) { - e_dbg - ("Error configuring MAC to PHY settings\n"); - return ret_val; - } - } - - /* Configure Flow Control now that Auto-Neg has completed. - * First, we need to restore the desired flow control settings - * because we may have had to re-autoneg with a different link - * partner. - */ - ret_val = e1000_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error configuring flow control\n"); - return ret_val; - } - - /* At this point we know that we are on copper and we have - * auto-negotiated link. These are conditions for checking the - * link partner capability register. We use the link speed to - * determine if TBI compatibility needs to be turned on or off. - * If the link is not at gigabit speed, then TBI compatibility - * is not needed. If we are at gigabit speed, we turn on TBI - * compatibility. - */ - if (hw->tbi_compatibility_en) { - u16 speed, duplex; - ret_val = - e1000_get_speed_and_duplex(hw, &speed, &duplex); - if (ret_val) { - e_dbg - ("Error getting link speed and duplex\n"); - return ret_val; - } - if (speed != SPEED_1000) { - /* If link speed is not set to gigabit speed, we - * do not need to enable TBI compatibility. - */ - if (hw->tbi_compatibility_on) { - /* If we previously were in the mode, - * turn it off. - */ - rctl = er32(RCTL); - rctl &= ~E1000_RCTL_SBP; - ew32(RCTL, rctl); - hw->tbi_compatibility_on = false; - } - } else { - /* If TBI compatibility is was previously off, - * turn it on. For compatibility with a TBI link - * partner, we will store bad packets. Some - * frames have an additional byte on the end and - * will look like CRC errors to to the hardware. - */ - if (!hw->tbi_compatibility_on) { - hw->tbi_compatibility_on = true; - rctl = er32(RCTL); - rctl |= E1000_RCTL_SBP; - ew32(RCTL, rctl); - } - } - } - } - - if ((hw->media_type == e1000_media_type_fiber) || - (hw->media_type == e1000_media_type_internal_serdes)) - e1000_check_for_serdes_link_generic(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_get_speed_and_duplex - * @hw: Struct containing variables accessed by shared code - * @speed: Speed of the connection - * @duplex: Duplex setting of the connection - * - * Detects the current speed and duplex settings of the hardware. - */ -s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex) -{ - u32 status; - s32 ret_val; - u16 phy_data; - - e_dbg("e1000_get_speed_and_duplex"); - - if (hw->mac_type >= e1000_82543) { - status = er32(STATUS); - if (status & E1000_STATUS_SPEED_1000) { - *speed = SPEED_1000; - e_dbg("1000 Mbs, "); - } else if (status & E1000_STATUS_SPEED_100) { - *speed = SPEED_100; - e_dbg("100 Mbs, "); - } else { - *speed = SPEED_10; - e_dbg("10 Mbs, "); - } - - if (status & E1000_STATUS_FD) { - *duplex = FULL_DUPLEX; - e_dbg("Full Duplex\n"); - } else { - *duplex = HALF_DUPLEX; - e_dbg(" Half Duplex\n"); - } - } else { - e_dbg("1000 Mbs, Full Duplex\n"); - *speed = SPEED_1000; - *duplex = FULL_DUPLEX; - } - - /* IGP01 PHY may advertise full duplex operation after speed downgrade - * even if it is operating at half duplex. Here we set the duplex - * settings to match the duplex in the link partner's capabilities. - */ - if (hw->phy_type == e1000_phy_igp && hw->speed_downgraded) { - ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data); - if (ret_val) - return ret_val; - - if (!(phy_data & NWAY_ER_LP_NWAY_CAPS)) - *duplex = HALF_DUPLEX; - else { - ret_val = - e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data); - if (ret_val) - return ret_val; - if ((*speed == SPEED_100 - && !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) - || (*speed == SPEED_10 - && !(phy_data & NWAY_LPAR_10T_FD_CAPS))) - *duplex = HALF_DUPLEX; - } - } - - return E1000_SUCCESS; -} - -/** - * e1000_wait_autoneg - * @hw: Struct containing variables accessed by shared code - * - * Blocks until autoneg completes or times out (~4.5 seconds) - */ -static s32 e1000_wait_autoneg(struct e1000_hw *hw) -{ - s32 ret_val; - u16 i; - u16 phy_data; - - e_dbg("e1000_wait_autoneg"); - e_dbg("Waiting for Auto-Neg to complete.\n"); - - /* We will wait for autoneg to complete or 4.5 seconds to expire. */ - for (i = PHY_AUTO_NEG_TIME; i > 0; i--) { - /* Read the MII Status Register and wait for Auto-Neg - * Complete bit to be set. - */ - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - if (phy_data & MII_SR_AUTONEG_COMPLETE) { - return E1000_SUCCESS; - } - msleep(100); - } - return E1000_SUCCESS; -} - -/** - * e1000_raise_mdi_clk - Raises the Management Data Clock - * @hw: Struct containing variables accessed by shared code - * @ctrl: Device control register's current value - */ -static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl) -{ - /* Raise the clock input to the Management Data Clock (by setting the - * MDC bit), and then delay 10 microseconds. - */ - ew32(CTRL, (*ctrl | E1000_CTRL_MDC)); - E1000_WRITE_FLUSH(); - udelay(10); -} - -/** - * e1000_lower_mdi_clk - Lowers the Management Data Clock - * @hw: Struct containing variables accessed by shared code - * @ctrl: Device control register's current value - */ -static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl) -{ - /* Lower the clock input to the Management Data Clock (by clearing the - * MDC bit), and then delay 10 microseconds. - */ - ew32(CTRL, (*ctrl & ~E1000_CTRL_MDC)); - E1000_WRITE_FLUSH(); - udelay(10); -} - -/** - * e1000_shift_out_mdi_bits - Shifts data bits out to the PHY - * @hw: Struct containing variables accessed by shared code - * @data: Data to send out to the PHY - * @count: Number of bits to shift out - * - * Bits are shifted out in MSB to LSB order. - */ -static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count) -{ - u32 ctrl; - u32 mask; - - /* We need to shift "count" number of bits out to the PHY. So, the value - * in the "data" parameter will be shifted out to the PHY one bit at a - * time. In order to do this, "data" must be broken down into bits. - */ - mask = 0x01; - mask <<= (count - 1); - - ctrl = er32(CTRL); - - /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */ - ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR); - - while (mask) { - /* A "1" is shifted out to the PHY by setting the MDIO bit to - * "1" and then raising and lowering the Management Data Clock. - * A "0" is shifted out to the PHY by setting the MDIO bit to - * "0" and then raising and lowering the clock. - */ - if (data & mask) - ctrl |= E1000_CTRL_MDIO; - else - ctrl &= ~E1000_CTRL_MDIO; - - ew32(CTRL, ctrl); - E1000_WRITE_FLUSH(); - - udelay(10); - - e1000_raise_mdi_clk(hw, &ctrl); - e1000_lower_mdi_clk(hw, &ctrl); - - mask = mask >> 1; - } -} - -/** - * e1000_shift_in_mdi_bits - Shifts data bits in from the PHY - * @hw: Struct containing variables accessed by shared code - * - * Bits are shifted in in MSB to LSB order. - */ -static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw) -{ - u32 ctrl; - u16 data = 0; - u8 i; - - /* In order to read a register from the PHY, we need to shift in a total - * of 18 bits from the PHY. The first two bit (turnaround) times are - * used to avoid contention on the MDIO pin when a read operation is - * performed. These two bits are ignored by us and thrown away. Bits are - * "shifted in" by raising the input to the Management Data Clock - * (setting the MDC bit), and then reading the value of the MDIO bit. - */ - ctrl = er32(CTRL); - - /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as - * input. - */ - ctrl &= ~E1000_CTRL_MDIO_DIR; - ctrl &= ~E1000_CTRL_MDIO; - - ew32(CTRL, ctrl); - E1000_WRITE_FLUSH(); - - /* Raise and Lower the clock before reading in the data. This accounts - * for the turnaround bits. The first clock occurred when we clocked out - * the last bit of the Register Address. - */ - e1000_raise_mdi_clk(hw, &ctrl); - e1000_lower_mdi_clk(hw, &ctrl); - - for (data = 0, i = 0; i < 16; i++) { - data = data << 1; - e1000_raise_mdi_clk(hw, &ctrl); - ctrl = er32(CTRL); - /* Check to see if we shifted in a "1". */ - if (ctrl & E1000_CTRL_MDIO) - data |= 1; - e1000_lower_mdi_clk(hw, &ctrl); - } - - e1000_raise_mdi_clk(hw, &ctrl); - e1000_lower_mdi_clk(hw, &ctrl); - - return data; -} - - -/** - * e1000_read_phy_reg - read a phy register - * @hw: Struct containing variables accessed by shared code - * @reg_addr: address of the PHY register to read - * - * Reads the value from a PHY register, if the value is on a specific non zero - * page, sets the page first. - */ -s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data) -{ - u32 ret_val; - unsigned long flags; - - e_dbg("e1000_read_phy_reg"); - - spin_lock_irqsave(&e1000_phy_lock, flags); - - if ((hw->phy_type == e1000_phy_igp) && - (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { - ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, - (u16) reg_addr); - if (ret_val) { - spin_unlock_irqrestore(&e1000_phy_lock, flags); - return ret_val; - } - } - - ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, - phy_data); - spin_unlock_irqrestore(&e1000_phy_lock, flags); - - return ret_val; -} - -static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, - u16 *phy_data) -{ - u32 i; - u32 mdic = 0; - const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1; - - e_dbg("e1000_read_phy_reg_ex"); - - if (reg_addr > MAX_PHY_REG_ADDRESS) { - e_dbg("PHY Address %d is out of range\n", reg_addr); - return -E1000_ERR_PARAM; - } - - if (hw->mac_type > e1000_82543) { - /* Set up Op-code, Phy Address, and register address in the MDI - * Control register. The MAC will take care of interfacing with - * the PHY to retrieve the desired data. - */ - if (hw->mac_type == e1000_ce4100) { - mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | - (INTEL_CE_GBE_MDIC_OP_READ) | - (INTEL_CE_GBE_MDIC_GO)); - - writel(mdic, E1000_MDIO_CMD); - - /* Poll the ready bit to see if the MDI read - * completed - */ - for (i = 0; i < 64; i++) { - udelay(50); - mdic = readl(E1000_MDIO_CMD); - if (!(mdic & INTEL_CE_GBE_MDIC_GO)) - break; - } - - if (mdic & INTEL_CE_GBE_MDIC_GO) { - e_dbg("MDI Read did not complete\n"); - return -E1000_ERR_PHY; - } - - mdic = readl(E1000_MDIO_STS); - if (mdic & INTEL_CE_GBE_MDIC_READ_ERROR) { - e_dbg("MDI Read Error\n"); - return -E1000_ERR_PHY; - } - *phy_data = (u16) mdic; - } else { - mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_READ)); - - ew32(MDIC, mdic); - - /* Poll the ready bit to see if the MDI read - * completed - */ - for (i = 0; i < 64; i++) { - udelay(50); - mdic = er32(MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - e_dbg("MDI Read did not complete\n"); - return -E1000_ERR_PHY; - } - if (mdic & E1000_MDIC_ERROR) { - e_dbg("MDI Error\n"); - return -E1000_ERR_PHY; - } - *phy_data = (u16) mdic; - } - } else { - /* We must first send a preamble through the MDIO pin to signal - * the beginning of an MII instruction. This is done by sending - * 32 consecutive "1" bits. - */ - e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); - - /* Now combine the next few fields that are required for a read - * operation. We use this method instead of calling the - * e1000_shift_out_mdi_bits routine five different times. The - * format of a MII read instruction consists of a shift out of - * 14 bits and is defined as follows: - * - * followed by a shift in of 18 bits. This first two bits - * shifted in are TurnAround bits used to avoid contention on - * the MDIO pin when a READ operation is performed. These two - * bits are thrown away followed by a shift in of 16 bits which - * contains the desired data. - */ - mdic = ((reg_addr) | (phy_addr << 5) | - (PHY_OP_READ << 10) | (PHY_SOF << 12)); - - e1000_shift_out_mdi_bits(hw, mdic, 14); - - /* Now that we've shifted out the read command to the MII, we - * need to "shift in" the 16-bit value (18 total bits) of the - * requested PHY register address. - */ - *phy_data = e1000_shift_in_mdi_bits(hw); - } - return E1000_SUCCESS; -} - -/** - * e1000_write_phy_reg - write a phy register - * - * @hw: Struct containing variables accessed by shared code - * @reg_addr: address of the PHY register to write - * @data: data to write to the PHY - * - * Writes a value to a PHY register - */ -s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data) -{ - u32 ret_val; - unsigned long flags; - - e_dbg("e1000_write_phy_reg"); - - spin_lock_irqsave(&e1000_phy_lock, flags); - - if ((hw->phy_type == e1000_phy_igp) && - (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { - ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, - (u16) reg_addr); - if (ret_val) { - spin_unlock_irqrestore(&e1000_phy_lock, flags); - return ret_val; - } - } - - ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, - phy_data); - spin_unlock_irqrestore(&e1000_phy_lock, flags); - - return ret_val; -} - -static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, - u16 phy_data) -{ - u32 i; - u32 mdic = 0; - const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1; - - e_dbg("e1000_write_phy_reg_ex"); - - if (reg_addr > MAX_PHY_REG_ADDRESS) { - e_dbg("PHY Address %d is out of range\n", reg_addr); - return -E1000_ERR_PARAM; - } - - if (hw->mac_type > e1000_82543) { - /* Set up Op-code, Phy Address, register address, and data - * intended for the PHY register in the MDI Control register. - * The MAC will take care of interfacing with the PHY to send - * the desired data. - */ - if (hw->mac_type == e1000_ce4100) { - mdic = (((u32) phy_data) | - (reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | - (INTEL_CE_GBE_MDIC_OP_WRITE) | - (INTEL_CE_GBE_MDIC_GO)); - - writel(mdic, E1000_MDIO_CMD); - - /* Poll the ready bit to see if the MDI read - * completed - */ - for (i = 0; i < 640; i++) { - udelay(5); - mdic = readl(E1000_MDIO_CMD); - if (!(mdic & INTEL_CE_GBE_MDIC_GO)) - break; - } - if (mdic & INTEL_CE_GBE_MDIC_GO) { - e_dbg("MDI Write did not complete\n"); - return -E1000_ERR_PHY; - } - } else { - mdic = (((u32) phy_data) | - (reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_WRITE)); - - ew32(MDIC, mdic); - - /* Poll the ready bit to see if the MDI read - * completed - */ - for (i = 0; i < 641; i++) { - udelay(5); - mdic = er32(MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - e_dbg("MDI Write did not complete\n"); - return -E1000_ERR_PHY; - } - } - } else { - /* We'll need to use the SW defined pins to shift the write - * command out to the PHY. We first send a preamble to the PHY - * to signal the beginning of the MII instruction. This is done - * by sending 32 consecutive "1" bits. - */ - e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); - - /* Now combine the remaining required fields that will indicate - * a write operation. We use this method instead of calling the - * e1000_shift_out_mdi_bits routine for each field in the - * command. The format of a MII write instruction is as follows: - * . - */ - mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) | - (PHY_OP_WRITE << 12) | (PHY_SOF << 14)); - mdic <<= 16; - mdic |= (u32) phy_data; - - e1000_shift_out_mdi_bits(hw, mdic, 32); - } - - return E1000_SUCCESS; -} - -/** - * e1000_phy_hw_reset - reset the phy, hardware style - * @hw: Struct containing variables accessed by shared code - * - * Returns the PHY to the power-on reset state - */ -s32 e1000_phy_hw_reset(struct e1000_hw *hw) -{ - u32 ctrl, ctrl_ext; - u32 led_ctrl; - - e_dbg("e1000_phy_hw_reset"); - - e_dbg("Resetting Phy...\n"); - - if (hw->mac_type > e1000_82543) { - /* Read the device control register and assert the - * E1000_CTRL_PHY_RST bit. Then, take it out of reset. - * For e1000 hardware, we delay for 10ms between the assert - * and de-assert. - */ - ctrl = er32(CTRL); - ew32(CTRL, ctrl | E1000_CTRL_PHY_RST); - E1000_WRITE_FLUSH(); - - msleep(10); - - ew32(CTRL, ctrl); - E1000_WRITE_FLUSH(); - - } else { - /* Read the Extended Device Control Register, assert the - * PHY_RESET_DIR bit to put the PHY into reset. Then, take it - * out of reset. - */ - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR; - ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA; - ew32(CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(); - msleep(10); - ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA; - ew32(CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(); - } - udelay(150); - - if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - /* Configure activity LED after PHY reset */ - led_ctrl = er32(LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - ew32(LEDCTL, led_ctrl); - } - - /* Wait for FW to finish PHY configuration. */ - return e1000_get_phy_cfg_done(hw); -} - -/** - * e1000_phy_reset - reset the phy to commit settings - * @hw: Struct containing variables accessed by shared code - * - * Resets the PHY - * Sets bit 15 of the MII Control register - */ -s32 e1000_phy_reset(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - - e_dbg("e1000_phy_reset"); - - switch (hw->phy_type) { - case e1000_phy_igp: - ret_val = e1000_phy_hw_reset(hw); - if (ret_val) - return ret_val; - break; - default: - ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= MII_CR_RESET; - ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data); - if (ret_val) - return ret_val; - - udelay(1); - break; - } - - if (hw->phy_type == e1000_phy_igp) - e1000_phy_init_script(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_detect_gig_phy - check the phy type - * @hw: Struct containing variables accessed by shared code - * - * Probes the expected PHY address for known PHY IDs - */ -static s32 e1000_detect_gig_phy(struct e1000_hw *hw) -{ - s32 phy_init_status, ret_val; - u16 phy_id_high, phy_id_low; - bool match = false; - - e_dbg("e1000_detect_gig_phy"); - - if (hw->phy_id != 0) - return E1000_SUCCESS; - - /* Read the PHY ID Registers to identify which PHY is onboard. */ - ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high); - if (ret_val) - return ret_val; - - hw->phy_id = (u32) (phy_id_high << 16); - udelay(20); - ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low); - if (ret_val) - return ret_val; - - hw->phy_id |= (u32) (phy_id_low & PHY_REVISION_MASK); - hw->phy_revision = (u32) phy_id_low & ~PHY_REVISION_MASK; - - switch (hw->mac_type) { - case e1000_82543: - if (hw->phy_id == M88E1000_E_PHY_ID) - match = true; - break; - case e1000_82544: - if (hw->phy_id == M88E1000_I_PHY_ID) - match = true; - break; - case e1000_82540: - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_82546_rev_3: - if (hw->phy_id == M88E1011_I_PHY_ID) - match = true; - break; - case e1000_ce4100: - if ((hw->phy_id == RTL8211B_PHY_ID) || - (hw->phy_id == RTL8201N_PHY_ID) || - (hw->phy_id == M88E1118_E_PHY_ID)) - match = true; - break; - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - if (hw->phy_id == IGP01E1000_I_PHY_ID) - match = true; - break; - default: - e_dbg("Invalid MAC type %d\n", hw->mac_type); - return -E1000_ERR_CONFIG; - } - phy_init_status = e1000_set_phy_type(hw); - - if ((match) && (phy_init_status == E1000_SUCCESS)) { - e_dbg("PHY ID 0x%X detected\n", hw->phy_id); - return E1000_SUCCESS; - } - e_dbg("Invalid PHY ID 0x%X\n", hw->phy_id); - return -E1000_ERR_PHY; -} - -/** - * e1000_phy_reset_dsp - reset DSP - * @hw: Struct containing variables accessed by shared code - * - * Resets the PHY's DSP - */ -static s32 e1000_phy_reset_dsp(struct e1000_hw *hw) -{ - s32 ret_val; - e_dbg("e1000_phy_reset_dsp"); - - do { - ret_val = e1000_write_phy_reg(hw, 29, 0x001d); - if (ret_val) - break; - ret_val = e1000_write_phy_reg(hw, 30, 0x00c1); - if (ret_val) - break; - ret_val = e1000_write_phy_reg(hw, 30, 0x0000); - if (ret_val) - break; - ret_val = E1000_SUCCESS; - } while (0); - - return ret_val; -} - -/** - * e1000_phy_igp_get_info - get igp specific registers - * @hw: Struct containing variables accessed by shared code - * @phy_info: PHY information structure - * - * Get PHY information from various PHY registers for igp PHY only. - */ -static s32 e1000_phy_igp_get_info(struct e1000_hw *hw, - struct e1000_phy_info *phy_info) -{ - s32 ret_val; - u16 phy_data, min_length, max_length, average; - e1000_rev_polarity polarity; - - e_dbg("e1000_phy_igp_get_info"); - - /* The downshift status is checked only once, after link is established, - * and it stored in the hw->speed_downgraded parameter. - */ - phy_info->downshift = (e1000_downshift) hw->speed_downgraded; - - /* IGP01E1000 does not need to support it. */ - phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal; - - /* IGP01E1000 always correct polarity reversal */ - phy_info->polarity_correction = e1000_polarity_reversal_enabled; - - /* Check polarity status */ - ret_val = e1000_check_polarity(hw, &polarity); - if (ret_val) - return ret_val; - - phy_info->cable_polarity = polarity; - - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data); - if (ret_val) - return ret_val; - - phy_info->mdix_mode = - (e1000_auto_x_mode) ((phy_data & IGP01E1000_PSSR_MDIX) >> - IGP01E1000_PSSR_MDIX_SHIFT); - - if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - /* Local/Remote Receiver Information are only valid @ 1000 - * Mbps - */ - ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); - if (ret_val) - return ret_val; - - phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >> - SR_1000T_LOCAL_RX_STATUS_SHIFT) ? - e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >> - SR_1000T_REMOTE_RX_STATUS_SHIFT) ? - e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - - /* Get cable length */ - ret_val = e1000_get_cable_length(hw, &min_length, &max_length); - if (ret_val) - return ret_val; - - /* Translate to old method */ - average = (max_length + min_length) / 2; - - if (average <= e1000_igp_cable_length_50) - phy_info->cable_length = e1000_cable_length_50; - else if (average <= e1000_igp_cable_length_80) - phy_info->cable_length = e1000_cable_length_50_80; - else if (average <= e1000_igp_cable_length_110) - phy_info->cable_length = e1000_cable_length_80_110; - else if (average <= e1000_igp_cable_length_140) - phy_info->cable_length = e1000_cable_length_110_140; - else - phy_info->cable_length = e1000_cable_length_140; - } - - return E1000_SUCCESS; -} - -/** - * e1000_phy_m88_get_info - get m88 specific registers - * @hw: Struct containing variables accessed by shared code - * @phy_info: PHY information structure - * - * Get PHY information from various PHY registers for m88 PHY only. - */ -static s32 e1000_phy_m88_get_info(struct e1000_hw *hw, - struct e1000_phy_info *phy_info) -{ - s32 ret_val; - u16 phy_data; - e1000_rev_polarity polarity; - - e_dbg("e1000_phy_m88_get_info"); - - /* The downshift status is checked only once, after link is established, - * and it stored in the hw->speed_downgraded parameter. - */ - phy_info->downshift = (e1000_downshift) hw->speed_downgraded; - - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_info->extended_10bt_distance = - ((phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >> - M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT) ? - e1000_10bt_ext_dist_enable_lower : - e1000_10bt_ext_dist_enable_normal; - - phy_info->polarity_correction = - ((phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >> - M88E1000_PSCR_POLARITY_REVERSAL_SHIFT) ? - e1000_polarity_reversal_disabled : e1000_polarity_reversal_enabled; - - /* Check polarity status */ - ret_val = e1000_check_polarity(hw, &polarity); - if (ret_val) - return ret_val; - phy_info->cable_polarity = polarity; - - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if (ret_val) - return ret_val; - - phy_info->mdix_mode = - (e1000_auto_x_mode) ((phy_data & M88E1000_PSSR_MDIX) >> - M88E1000_PSSR_MDIX_SHIFT); - - if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { - /* Cable Length Estimation and Local/Remote Receiver Information - * are only valid at 1000 Mbps. - */ - phy_info->cable_length = - (e1000_cable_length) ((phy_data & - M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT); - - ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); - if (ret_val) - return ret_val; - - phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >> - SR_1000T_LOCAL_RX_STATUS_SHIFT) ? - e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >> - SR_1000T_REMOTE_RX_STATUS_SHIFT) ? - e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - - } - - return E1000_SUCCESS; -} - -/** - * e1000_phy_get_info - request phy info - * @hw: Struct containing variables accessed by shared code - * @phy_info: PHY information structure - * - * Get PHY information from various PHY registers - */ -s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) -{ - s32 ret_val; - u16 phy_data; - - e_dbg("e1000_phy_get_info"); - - phy_info->cable_length = e1000_cable_length_undefined; - phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined; - phy_info->cable_polarity = e1000_rev_polarity_undefined; - phy_info->downshift = e1000_downshift_undefined; - phy_info->polarity_correction = e1000_polarity_reversal_undefined; - phy_info->mdix_mode = e1000_auto_x_mode_undefined; - phy_info->local_rx = e1000_1000t_rx_status_undefined; - phy_info->remote_rx = e1000_1000t_rx_status_undefined; - - if (hw->media_type != e1000_media_type_copper) { - e_dbg("PHY info is only valid for copper media\n"); - return -E1000_ERR_CONFIG; - } - - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - - if ((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) { - e_dbg("PHY info is only valid if link is up\n"); - return -E1000_ERR_CONFIG; - } - - if (hw->phy_type == e1000_phy_igp) - return e1000_phy_igp_get_info(hw, phy_info); - else if ((hw->phy_type == e1000_phy_8211) || - (hw->phy_type == e1000_phy_8201)) - return E1000_SUCCESS; - else - return e1000_phy_m88_get_info(hw, phy_info); -} - -s32 e1000_validate_mdi_setting(struct e1000_hw *hw) -{ - e_dbg("e1000_validate_mdi_settings"); - - if (!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) { - e_dbg("Invalid MDI setting detected\n"); - hw->mdix = 1; - return -E1000_ERR_CONFIG; - } - return E1000_SUCCESS; -} - -/** - * e1000_init_eeprom_params - initialize sw eeprom vars - * @hw: Struct containing variables accessed by shared code - * - * Sets up eeprom variables in the hw struct. Must be called after mac_type - * is configured. - */ -s32 e1000_init_eeprom_params(struct e1000_hw *hw) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u32 eecd = er32(EECD); - s32 ret_val = E1000_SUCCESS; - u16 eeprom_size; - - e_dbg("e1000_init_eeprom_params"); - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - eeprom->type = e1000_eeprom_microwire; - eeprom->word_size = 64; - eeprom->opcode_bits = 3; - eeprom->address_bits = 6; - eeprom->delay_usec = 50; - break; - case e1000_82540: - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_82546_rev_3: - eeprom->type = e1000_eeprom_microwire; - eeprom->opcode_bits = 3; - eeprom->delay_usec = 50; - if (eecd & E1000_EECD_SIZE) { - eeprom->word_size = 256; - eeprom->address_bits = 8; - } else { - eeprom->word_size = 64; - eeprom->address_bits = 6; - } - break; - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - if (eecd & E1000_EECD_TYPE) { - eeprom->type = e1000_eeprom_spi; - eeprom->opcode_bits = 8; - eeprom->delay_usec = 1; - if (eecd & E1000_EECD_ADDR_BITS) { - eeprom->page_size = 32; - eeprom->address_bits = 16; - } else { - eeprom->page_size = 8; - eeprom->address_bits = 8; - } - } else { - eeprom->type = e1000_eeprom_microwire; - eeprom->opcode_bits = 3; - eeprom->delay_usec = 50; - if (eecd & E1000_EECD_ADDR_BITS) { - eeprom->word_size = 256; - eeprom->address_bits = 8; - } else { - eeprom->word_size = 64; - eeprom->address_bits = 6; - } - } - break; - default: - break; - } - - if (eeprom->type == e1000_eeprom_spi) { - /* eeprom_size will be an enum [0..8] that maps to eeprom sizes - * 128B to 32KB (incremented by powers of 2). - */ - /* Set to default value for initial eeprom read. */ - eeprom->word_size = 64; - ret_val = e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size); - if (ret_val) - return ret_val; - eeprom_size = - (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT; - /* 256B eeprom size was not supported in earlier hardware, so we - * bump eeprom_size up one to ensure that "1" (which maps to - * 256B) is never the result used in the shifting logic below. - */ - if (eeprom_size) - eeprom_size++; - - eeprom->word_size = 1 << (eeprom_size + EEPROM_WORD_SIZE_SHIFT); - } - return ret_val; -} - -/** - * e1000_raise_ee_clk - Raises the EEPROM's clock input. - * @hw: Struct containing variables accessed by shared code - * @eecd: EECD's current value - */ -static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd) -{ - /* Raise the clock input to the EEPROM (by setting the SK bit), and then - * wait microseconds. - */ - *eecd = *eecd | E1000_EECD_SK; - ew32(EECD, *eecd); - E1000_WRITE_FLUSH(); - udelay(hw->eeprom.delay_usec); -} - -/** - * e1000_lower_ee_clk - Lowers the EEPROM's clock input. - * @hw: Struct containing variables accessed by shared code - * @eecd: EECD's current value - */ -static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd) -{ - /* Lower the clock input to the EEPROM (by clearing the SK bit), and - * then wait 50 microseconds. - */ - *eecd = *eecd & ~E1000_EECD_SK; - ew32(EECD, *eecd); - E1000_WRITE_FLUSH(); - udelay(hw->eeprom.delay_usec); -} - -/** - * e1000_shift_out_ee_bits - Shift data bits out to the EEPROM. - * @hw: Struct containing variables accessed by shared code - * @data: data to send to the EEPROM - * @count: number of bits to shift out - */ -static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u32 eecd; - u32 mask; - - /* We need to shift "count" bits out to the EEPROM. So, value in the - * "data" parameter will be shifted out to the EEPROM one bit at a time. - * In order to do this, "data" must be broken down into bits. - */ - mask = 0x01 << (count - 1); - eecd = er32(EECD); - if (eeprom->type == e1000_eeprom_microwire) { - eecd &= ~E1000_EECD_DO; - } else if (eeprom->type == e1000_eeprom_spi) { - eecd |= E1000_EECD_DO; - } - do { - /* A "1" is shifted out to the EEPROM by setting bit "DI" to a - * "1", and then raising and then lowering the clock (the SK bit - * controls the clock input to the EEPROM). A "0" is shifted - * out to the EEPROM by setting "DI" to "0" and then raising and - * then lowering the clock. - */ - eecd &= ~E1000_EECD_DI; - - if (data & mask) - eecd |= E1000_EECD_DI; - - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - - udelay(eeprom->delay_usec); - - e1000_raise_ee_clk(hw, &eecd); - e1000_lower_ee_clk(hw, &eecd); - - mask = mask >> 1; - - } while (mask); - - /* We leave the "DI" bit set to "0" when we leave this routine. */ - eecd &= ~E1000_EECD_DI; - ew32(EECD, eecd); -} - -/** - * e1000_shift_in_ee_bits - Shift data bits in from the EEPROM - * @hw: Struct containing variables accessed by shared code - * @count: number of bits to shift in - */ -static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count) -{ - u32 eecd; - u32 i; - u16 data; - - /* In order to read a register from the EEPROM, we need to shift 'count' - * bits in from the EEPROM. Bits are "shifted in" by raising the clock - * input to the EEPROM (setting the SK bit), and then reading the value - * of the "DO" bit. During this "shifting in" process the "DI" bit - * should always be clear. - */ - - eecd = er32(EECD); - - eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); - data = 0; - - for (i = 0; i < count; i++) { - data = data << 1; - e1000_raise_ee_clk(hw, &eecd); - - eecd = er32(EECD); - - eecd &= ~(E1000_EECD_DI); - if (eecd & E1000_EECD_DO) - data |= 1; - - e1000_lower_ee_clk(hw, &eecd); - } - - return data; -} - -/** - * e1000_acquire_eeprom - Prepares EEPROM for access - * @hw: Struct containing variables accessed by shared code - * - * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This - * function should be called before issuing a command to the EEPROM. - */ -static s32 e1000_acquire_eeprom(struct e1000_hw *hw) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u32 eecd, i = 0; - - e_dbg("e1000_acquire_eeprom"); - - eecd = er32(EECD); - - /* Request EEPROM Access */ - if (hw->mac_type > e1000_82544) { - eecd |= E1000_EECD_REQ; - ew32(EECD, eecd); - eecd = er32(EECD); - while ((!(eecd & E1000_EECD_GNT)) && - (i < E1000_EEPROM_GRANT_ATTEMPTS)) { - i++; - udelay(5); - eecd = er32(EECD); - } - if (!(eecd & E1000_EECD_GNT)) { - eecd &= ~E1000_EECD_REQ; - ew32(EECD, eecd); - e_dbg("Could not acquire EEPROM grant\n"); - return -E1000_ERR_EEPROM; - } - } - - /* Setup EEPROM for Read/Write */ - - if (eeprom->type == e1000_eeprom_microwire) { - /* Clear SK and DI */ - eecd &= ~(E1000_EECD_DI | E1000_EECD_SK); - ew32(EECD, eecd); - - /* Set CS */ - eecd |= E1000_EECD_CS; - ew32(EECD, eecd); - } else if (eeprom->type == e1000_eeprom_spi) { - /* Clear SK and CS */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(1); - } - - return E1000_SUCCESS; -} - -/** - * e1000_standby_eeprom - Returns EEPROM to a "standby" state - * @hw: Struct containing variables accessed by shared code - */ -static void e1000_standby_eeprom(struct e1000_hw *hw) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u32 eecd; - - eecd = er32(EECD); - - if (eeprom->type == e1000_eeprom_microwire) { - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(eeprom->delay_usec); - - /* Clock high */ - eecd |= E1000_EECD_SK; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(eeprom->delay_usec); - - /* Select EEPROM */ - eecd |= E1000_EECD_CS; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(eeprom->delay_usec); - - /* Clock low */ - eecd &= ~E1000_EECD_SK; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(eeprom->delay_usec); - } else if (eeprom->type == e1000_eeprom_spi) { - /* Toggle CS to flush commands */ - eecd |= E1000_EECD_CS; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(eeprom->delay_usec); - eecd &= ~E1000_EECD_CS; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(eeprom->delay_usec); - } -} - -/** - * e1000_release_eeprom - drop chip select - * @hw: Struct containing variables accessed by shared code - * - * Terminates a command by inverting the EEPROM's chip select pin - */ -static void e1000_release_eeprom(struct e1000_hw *hw) -{ - u32 eecd; - - e_dbg("e1000_release_eeprom"); - - eecd = er32(EECD); - - if (hw->eeprom.type == e1000_eeprom_spi) { - eecd |= E1000_EECD_CS; /* Pull CS high */ - eecd &= ~E1000_EECD_SK; /* Lower SCK */ - - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - - udelay(hw->eeprom.delay_usec); - } else if (hw->eeprom.type == e1000_eeprom_microwire) { - /* cleanup eeprom */ - - /* CS on Microwire is active-high */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); - - ew32(EECD, eecd); - - /* Rising edge of clock */ - eecd |= E1000_EECD_SK; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(hw->eeprom.delay_usec); - - /* Falling edge of clock */ - eecd &= ~E1000_EECD_SK; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(hw->eeprom.delay_usec); - } - - /* Stop requesting EEPROM access */ - if (hw->mac_type > e1000_82544) { - eecd &= ~E1000_EECD_REQ; - ew32(EECD, eecd); - } -} - -/** - * e1000_spi_eeprom_ready - Reads a 16 bit word from the EEPROM. - * @hw: Struct containing variables accessed by shared code - */ -static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw) -{ - u16 retry_count = 0; - u8 spi_stat_reg; - - e_dbg("e1000_spi_eeprom_ready"); - - /* Read "Status Register" repeatedly until the LSB is cleared. The - * EEPROM will signal that the command has been completed by clearing - * bit 0 of the internal status register. If it's not cleared within - * 5 milliseconds, then error out. - */ - retry_count = 0; - do { - e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI, - hw->eeprom.opcode_bits); - spi_stat_reg = (u8) e1000_shift_in_ee_bits(hw, 8); - if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI)) - break; - - udelay(5); - retry_count += 5; - - e1000_standby_eeprom(hw); - } while (retry_count < EEPROM_MAX_RETRY_SPI); - - /* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and - * only 0-5mSec on 5V devices) - */ - if (retry_count >= EEPROM_MAX_RETRY_SPI) { - e_dbg("SPI EEPROM Status error\n"); - return -E1000_ERR_EEPROM; - } - - return E1000_SUCCESS; -} - -/** - * e1000_read_eeprom - Reads a 16 bit word from the EEPROM. - * @hw: Struct containing variables accessed by shared code - * @offset: offset of word in the EEPROM to read - * @data: word read from the EEPROM - * @words: number of words to read - */ -s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - s32 ret; - spin_lock(&e1000_eeprom_lock); - ret = e1000_do_read_eeprom(hw, offset, words, data); - spin_unlock(&e1000_eeprom_lock); - return ret; -} - -static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u32 i = 0; - - e_dbg("e1000_read_eeprom"); - - if (hw->mac_type == e1000_ce4100) { - GBE_CONFIG_FLASH_READ(GBE_CONFIG_BASE_VIRT, offset, words, - data); - return E1000_SUCCESS; - } - - /* If eeprom is not yet detected, do so now */ - if (eeprom->word_size == 0) - e1000_init_eeprom_params(hw); - - /* A check for invalid values: offset too large, too many words, and - * not enough words. - */ - if ((offset >= eeprom->word_size) - || (words > eeprom->word_size - offset) || (words == 0)) { - e_dbg("\"words\" parameter out of bounds. Words = %d," - "size = %d\n", offset, eeprom->word_size); - return -E1000_ERR_EEPROM; - } - - /* EEPROM's that don't use EERD to read require us to bit-bang the SPI - * directly. In this case, we need to acquire the EEPROM so that - * FW or other port software does not interrupt. - */ - /* Prepare the EEPROM for bit-bang reading */ - if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) - return -E1000_ERR_EEPROM; - - /* Set up the SPI or Microwire EEPROM for bit-bang reading. We have - * acquired the EEPROM at this point, so any returns should release it - */ - if (eeprom->type == e1000_eeprom_spi) { - u16 word_in; - u8 read_opcode = EEPROM_READ_OPCODE_SPI; - - if (e1000_spi_eeprom_ready(hw)) { - e1000_release_eeprom(hw); - return -E1000_ERR_EEPROM; - } - - e1000_standby_eeprom(hw); - - /* Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((eeprom->address_bits == 8) && (offset >= 128)) - read_opcode |= EEPROM_A8_OPCODE_SPI; - - /* Send the READ command (opcode + addr) */ - e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits); - e1000_shift_out_ee_bits(hw, (u16) (offset * 2), - eeprom->address_bits); - - /* Read the data. The address of the eeprom internally - * increments with each byte (spi) being read, saving on the - * overhead of eeprom setup and tear-down. The address counter - * will roll over if reading beyond the size of the eeprom, thus - * allowing the entire memory to be read starting from any - * offset. - */ - for (i = 0; i < words; i++) { - word_in = e1000_shift_in_ee_bits(hw, 16); - data[i] = (word_in >> 8) | (word_in << 8); - } - } else if (eeprom->type == e1000_eeprom_microwire) { - for (i = 0; i < words; i++) { - /* Send the READ command (opcode + addr) */ - e1000_shift_out_ee_bits(hw, - EEPROM_READ_OPCODE_MICROWIRE, - eeprom->opcode_bits); - e1000_shift_out_ee_bits(hw, (u16) (offset + i), - eeprom->address_bits); - - /* Read the data. For microwire, each word requires the - * overhead of eeprom setup and tear-down. - */ - data[i] = e1000_shift_in_ee_bits(hw, 16); - e1000_standby_eeprom(hw); - } - } - - /* End this read operation */ - e1000_release_eeprom(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_validate_eeprom_checksum - Verifies that the EEPROM has a valid checksum - * @hw: Struct containing variables accessed by shared code - * - * Reads the first 64 16 bit words of the EEPROM and sums the values read. - * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is - * valid. - */ -s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw) -{ - u16 checksum = 0; - u16 i, eeprom_data; - - e_dbg("e1000_validate_eeprom_checksum"); - - for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { - if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { - e_dbg("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - checksum += eeprom_data; - } - -#ifdef CONFIG_PARISC - /* This is a signature and not a checksum on HP c8000 */ - if ((hw->subsystem_vendor_id == 0x103C) && (eeprom_data == 0x16d6)) - return E1000_SUCCESS; - -#endif - if (checksum == (u16) EEPROM_SUM) - return E1000_SUCCESS; - else { - e_dbg("EEPROM Checksum Invalid\n"); - return -E1000_ERR_EEPROM; - } -} - -/** - * e1000_update_eeprom_checksum - Calculates/writes the EEPROM checksum - * @hw: Struct containing variables accessed by shared code - * - * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA. - * Writes the difference to word offset 63 of the EEPROM. - */ -s32 e1000_update_eeprom_checksum(struct e1000_hw *hw) -{ - u16 checksum = 0; - u16 i, eeprom_data; - - e_dbg("e1000_update_eeprom_checksum"); - - for (i = 0; i < EEPROM_CHECKSUM_REG; i++) { - if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { - e_dbg("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - checksum += eeprom_data; - } - checksum = (u16) EEPROM_SUM - checksum; - if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) { - e_dbg("EEPROM Write Error\n"); - return -E1000_ERR_EEPROM; - } - return E1000_SUCCESS; -} - -/** - * e1000_write_eeprom - write words to the different EEPROM types. - * @hw: Struct containing variables accessed by shared code - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word to be written to the EEPROM - * - * If e1000_update_eeprom_checksum is not called after this function, the - * EEPROM will most likely contain an invalid checksum. - */ -s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - s32 ret; - spin_lock(&e1000_eeprom_lock); - ret = e1000_do_write_eeprom(hw, offset, words, data); - spin_unlock(&e1000_eeprom_lock); - return ret; -} - -static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - s32 status = 0; - - e_dbg("e1000_write_eeprom"); - - if (hw->mac_type == e1000_ce4100) { - GBE_CONFIG_FLASH_WRITE(GBE_CONFIG_BASE_VIRT, offset, words, - data); - return E1000_SUCCESS; - } - - /* If eeprom is not yet detected, do so now */ - if (eeprom->word_size == 0) - e1000_init_eeprom_params(hw); - - /* A check for invalid values: offset too large, too many words, and - * not enough words. - */ - if ((offset >= eeprom->word_size) - || (words > eeprom->word_size - offset) || (words == 0)) { - e_dbg("\"words\" parameter out of bounds\n"); - return -E1000_ERR_EEPROM; - } - - /* Prepare the EEPROM for writing */ - if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) - return -E1000_ERR_EEPROM; - - if (eeprom->type == e1000_eeprom_microwire) { - status = e1000_write_eeprom_microwire(hw, offset, words, data); - } else { - status = e1000_write_eeprom_spi(hw, offset, words, data); - msleep(10); - } - - /* Done with writing */ - e1000_release_eeprom(hw); - - return status; -} - -/** - * e1000_write_eeprom_spi - Writes a 16 bit word to a given offset in an SPI EEPROM. - * @hw: Struct containing variables accessed by shared code - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: pointer to array of 8 bit words to be written to the EEPROM - */ -static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u16 widx = 0; - - e_dbg("e1000_write_eeprom_spi"); - - while (widx < words) { - u8 write_opcode = EEPROM_WRITE_OPCODE_SPI; - - if (e1000_spi_eeprom_ready(hw)) - return -E1000_ERR_EEPROM; - - e1000_standby_eeprom(hw); - - /* Send the WRITE ENABLE command (8 bit opcode ) */ - e1000_shift_out_ee_bits(hw, EEPROM_WREN_OPCODE_SPI, - eeprom->opcode_bits); - - e1000_standby_eeprom(hw); - - /* Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((eeprom->address_bits == 8) && (offset >= 128)) - write_opcode |= EEPROM_A8_OPCODE_SPI; - - /* Send the Write command (8-bit opcode + addr) */ - e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits); - - e1000_shift_out_ee_bits(hw, (u16) ((offset + widx) * 2), - eeprom->address_bits); - - /* Send the data */ - - /* Loop to allow for up to whole page write (32 bytes) of - * eeprom - */ - while (widx < words) { - u16 word_out = data[widx]; - word_out = (word_out >> 8) | (word_out << 8); - e1000_shift_out_ee_bits(hw, word_out, 16); - widx++; - - /* Some larger eeprom sizes are capable of a 32-byte - * PAGE WRITE operation, while the smaller eeproms are - * capable of an 8-byte PAGE WRITE operation. Break the - * inner loop to pass new address - */ - if ((((offset + widx) * 2) % eeprom->page_size) == 0) { - e1000_standby_eeprom(hw); - break; - } - } - } - - return E1000_SUCCESS; -} - -/** - * e1000_write_eeprom_microwire - Writes a 16 bit word to a given offset in a Microwire EEPROM. - * @hw: Struct containing variables accessed by shared code - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: pointer to array of 8 bit words to be written to the EEPROM - */ -static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u32 eecd; - u16 words_written = 0; - u16 i = 0; - - e_dbg("e1000_write_eeprom_microwire"); - - /* Send the write enable command to the EEPROM (3-bit opcode plus - * 6/8-bit dummy address beginning with 11). It's less work to include - * the 11 of the dummy address as part of the opcode than it is to shift - * it over the correct number of bits for the address. This puts the - * EEPROM into write/erase mode. - */ - e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE, - (u16) (eeprom->opcode_bits + 2)); - - e1000_shift_out_ee_bits(hw, 0, (u16) (eeprom->address_bits - 2)); - - /* Prepare the EEPROM */ - e1000_standby_eeprom(hw); - - while (words_written < words) { - /* Send the Write command (3-bit opcode + addr) */ - e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE, - eeprom->opcode_bits); - - e1000_shift_out_ee_bits(hw, (u16) (offset + words_written), - eeprom->address_bits); - - /* Send the data */ - e1000_shift_out_ee_bits(hw, data[words_written], 16); - - /* Toggle the CS line. This in effect tells the EEPROM to - * execute the previous command. - */ - e1000_standby_eeprom(hw); - - /* Read DO repeatedly until it is high (equal to '1'). The - * EEPROM will signal that the command has been completed by - * raising the DO signal. If DO does not go high in 10 - * milliseconds, then error out. - */ - for (i = 0; i < 200; i++) { - eecd = er32(EECD); - if (eecd & E1000_EECD_DO) - break; - udelay(50); - } - if (i == 200) { - e_dbg("EEPROM Write did not complete\n"); - return -E1000_ERR_EEPROM; - } - - /* Recover from write */ - e1000_standby_eeprom(hw); - - words_written++; - } - - /* Send the write disable command to the EEPROM (3-bit opcode plus - * 6/8-bit dummy address beginning with 10). It's less work to include - * the 10 of the dummy address as part of the opcode than it is to shift - * it over the correct number of bits for the address. This takes the - * EEPROM out of write/erase mode. - */ - e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE, - (u16) (eeprom->opcode_bits + 2)); - - e1000_shift_out_ee_bits(hw, 0, (u16) (eeprom->address_bits - 2)); - - return E1000_SUCCESS; -} - -/** - * e1000_read_mac_addr - read the adapters MAC from eeprom - * @hw: Struct containing variables accessed by shared code - * - * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the - * second function of dual function devices - */ -s32 e1000_read_mac_addr(struct e1000_hw *hw) -{ - u16 offset; - u16 eeprom_data, i; - - e_dbg("e1000_read_mac_addr"); - - for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) { - offset = i >> 1; - if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { - e_dbg("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - hw->perm_mac_addr[i] = (u8) (eeprom_data & 0x00FF); - hw->perm_mac_addr[i + 1] = (u8) (eeprom_data >> 8); - } - - switch (hw->mac_type) { - default: - break; - case e1000_82546: - case e1000_82546_rev_3: - if (er32(STATUS) & E1000_STATUS_FUNC_1) - hw->perm_mac_addr[5] ^= 0x01; - break; - } - - for (i = 0; i < NODE_ADDRESS_SIZE; i++) - hw->mac_addr[i] = hw->perm_mac_addr[i]; - return E1000_SUCCESS; -} - -/** - * e1000_init_rx_addrs - Initializes receive address filters. - * @hw: Struct containing variables accessed by shared code - * - * Places the MAC address in receive address register 0 and clears the rest - * of the receive address registers. Clears the multicast table. Assumes - * the receiver is in reset when the routine is called. - */ -static void e1000_init_rx_addrs(struct e1000_hw *hw) -{ - u32 i; - u32 rar_num; - - e_dbg("e1000_init_rx_addrs"); - - /* Setup the receive address. */ - e_dbg("Programming MAC Address into RAR[0]\n"); - - e1000_rar_set(hw, hw->mac_addr, 0); - - rar_num = E1000_RAR_ENTRIES; - - /* Zero out the other 15 receive addresses. */ - e_dbg("Clearing RAR[1-15]\n"); - for (i = 1; i < rar_num; i++) { - E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); - E1000_WRITE_FLUSH(); - E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0); - E1000_WRITE_FLUSH(); - } -} - -/** - * e1000_hash_mc_addr - Hashes an address to determine its location in the multicast table - * @hw: Struct containing variables accessed by shared code - * @mc_addr: the multicast address to hash - */ -u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) -{ - u32 hash_value = 0; - - /* The portion of the address that is used for the hash table is - * determined by the mc_filter_type setting. - */ - switch (hw->mc_filter_type) { - /* [0] [1] [2] [3] [4] [5] - * 01 AA 00 12 34 56 - * LSB MSB - */ - case 0: - /* [47:36] i.e. 0x563 for above example address */ - hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4)); - break; - case 1: - /* [46:35] i.e. 0xAC6 for above example address */ - hash_value = ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5)); - break; - case 2: - /* [45:34] i.e. 0x5D8 for above example address */ - hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6)); - break; - case 3: - /* [43:32] i.e. 0x634 for above example address */ - hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8)); - break; - } - - hash_value &= 0xFFF; - return hash_value; -} - -/** - * e1000_rar_set - Puts an ethernet address into a receive address register. - * @hw: Struct containing variables accessed by shared code - * @addr: Address to put into receive address register - * @index: Receive address register to write - */ -void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) -{ - u32 rar_low, rar_high; - - /* HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian - */ - rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) | - ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); - rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); - - /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx - * unit hang. - * - * Description: - * If there are any Rx frames queued up or otherwise present in the HW - * before RSS is enabled, and then we enable RSS, the HW Rx unit will - * hang. To work around this issue, we have to disable receives and - * flush out all Rx frames before we enable RSS. To do so, we modify we - * redirect all Rx traffic to manageability and then reset the HW. - * This flushes away Rx frames, and (since the redirections to - * manageability persists across resets) keeps new ones from coming in - * while we work. Then, we clear the Address Valid AV bit for all MAC - * addresses and undo the re-direction to manageability. - * Now, frames are coming in again, but the MAC won't accept them, so - * far so good. We now proceed to initialize RSS (if necessary) and - * configure the Rx unit. Last, we re-enable the AV bits and continue - * on our merry way. - */ - switch (hw->mac_type) { - default: - /* Indicate to hardware the Address is Valid. */ - rar_high |= E1000_RAH_AV; - break; - } - - E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low); - E1000_WRITE_FLUSH(); - E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high); - E1000_WRITE_FLUSH(); -} - -/** - * e1000_write_vfta - Writes a value to the specified offset in the VLAN filter table. - * @hw: Struct containing variables accessed by shared code - * @offset: Offset in VLAN filer table to write - * @value: Value to write into VLAN filter table - */ -void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) -{ - u32 temp; - - if ((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) { - temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1)); - E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value); - E1000_WRITE_FLUSH(); - E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp); - E1000_WRITE_FLUSH(); - } else { - E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value); - E1000_WRITE_FLUSH(); - } -} - -/** - * e1000_clear_vfta - Clears the VLAN filer table - * @hw: Struct containing variables accessed by shared code - */ -static void e1000_clear_vfta(struct e1000_hw *hw) -{ - u32 offset; - u32 vfta_value = 0; - u32 vfta_offset = 0; - u32 vfta_bit_in_reg = 0; - - for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { - /* If the offset we want to clear is the same offset of the - * manageability VLAN ID, then clear all bits except that of the - * manageability unit - */ - vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0; - E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value); - E1000_WRITE_FLUSH(); - } -} - -static s32 e1000_id_led_init(struct e1000_hw *hw) -{ - u32 ledctl; - const u32 ledctl_mask = 0x000000FF; - const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; - const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; - u16 eeprom_data, i, temp; - const u16 led_mask = 0x0F; - - e_dbg("e1000_id_led_init"); - - if (hw->mac_type < e1000_82540) { - /* Nothing to do */ - return E1000_SUCCESS; - } - - ledctl = er32(LEDCTL); - hw->ledctl_default = ledctl; - hw->ledctl_mode1 = hw->ledctl_default; - hw->ledctl_mode2 = hw->ledctl_default; - - if (e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) { - e_dbg("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - - if ((eeprom_data == ID_LED_RESERVED_0000) || - (eeprom_data == ID_LED_RESERVED_FFFF)) { - eeprom_data = ID_LED_DEFAULT; - } - - for (i = 0; i < 4; i++) { - temp = (eeprom_data >> (i << 2)) & led_mask; - switch (temp) { - case ID_LED_ON1_DEF2: - case ID_LED_ON1_ON2: - case ID_LED_ON1_OFF2: - hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - hw->ledctl_mode1 |= ledctl_on << (i << 3); - break; - case ID_LED_OFF1_DEF2: - case ID_LED_OFF1_ON2: - case ID_LED_OFF1_OFF2: - hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - hw->ledctl_mode1 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - switch (temp) { - case ID_LED_DEF1_ON2: - case ID_LED_ON1_ON2: - case ID_LED_OFF1_ON2: - hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - hw->ledctl_mode2 |= ledctl_on << (i << 3); - break; - case ID_LED_DEF1_OFF2: - case ID_LED_ON1_OFF2: - case ID_LED_OFF1_OFF2: - hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - hw->ledctl_mode2 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - } - return E1000_SUCCESS; -} - -/** - * e1000_setup_led - * @hw: Struct containing variables accessed by shared code - * - * Prepares SW controlable LED for use and saves the current state of the LED. - */ -s32 e1000_setup_led(struct e1000_hw *hw) -{ - u32 ledctl; - s32 ret_val = E1000_SUCCESS; - - e_dbg("e1000_setup_led"); - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - /* No setup necessary */ - break; - case e1000_82541: - case e1000_82547: - case e1000_82541_rev_2: - case e1000_82547_rev_2: - /* Turn off PHY Smart Power Down (if enabled) */ - ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, - &hw->phy_spd_default); - if (ret_val) - return ret_val; - ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, - (u16) (hw->phy_spd_default & - ~IGP01E1000_GMII_SPD)); - if (ret_val) - return ret_val; - /* Fall Through */ - default: - if (hw->media_type == e1000_media_type_fiber) { - ledctl = er32(LEDCTL); - /* Save current LEDCTL settings */ - hw->ledctl_default = ledctl; - /* Turn off LED0 */ - ledctl &= ~(E1000_LEDCTL_LED0_IVRT | - E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_LED0_MODE_MASK); - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << - E1000_LEDCTL_LED0_MODE_SHIFT); - ew32(LEDCTL, ledctl); - } else if (hw->media_type == e1000_media_type_copper) - ew32(LEDCTL, hw->ledctl_mode1); - break; - } - - return E1000_SUCCESS; -} - -/** - * e1000_cleanup_led - Restores the saved state of the SW controlable LED. - * @hw: Struct containing variables accessed by shared code - */ -s32 e1000_cleanup_led(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - e_dbg("e1000_cleanup_led"); - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - /* No cleanup necessary */ - break; - case e1000_82541: - case e1000_82547: - case e1000_82541_rev_2: - case e1000_82547_rev_2: - /* Turn on PHY Smart Power Down (if previously enabled) */ - ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, - hw->phy_spd_default); - if (ret_val) - return ret_val; - /* Fall Through */ - default: - /* Restore LEDCTL settings */ - ew32(LEDCTL, hw->ledctl_default); - break; - } - - return E1000_SUCCESS; -} - -/** - * e1000_led_on - Turns on the software controllable LED - * @hw: Struct containing variables accessed by shared code - */ -s32 e1000_led_on(struct e1000_hw *hw) -{ - u32 ctrl = er32(CTRL); - - e_dbg("e1000_led_on"); - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - /* Set SW Defineable Pin 0 to turn on the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - break; - case e1000_82544: - if (hw->media_type == e1000_media_type_fiber) { - /* Set SW Defineable Pin 0 to turn on the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else { - /* Clear SW Defineable Pin 0 to turn on the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } - break; - default: - if (hw->media_type == e1000_media_type_fiber) { - /* Clear SW Defineable Pin 0 to turn on the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else if (hw->media_type == e1000_media_type_copper) { - ew32(LEDCTL, hw->ledctl_mode2); - return E1000_SUCCESS; - } - break; - } - - ew32(CTRL, ctrl); - - return E1000_SUCCESS; -} - -/** - * e1000_led_off - Turns off the software controllable LED - * @hw: Struct containing variables accessed by shared code - */ -s32 e1000_led_off(struct e1000_hw *hw) -{ - u32 ctrl = er32(CTRL); - - e_dbg("e1000_led_off"); - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - /* Clear SW Defineable Pin 0 to turn off the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - break; - case e1000_82544: - if (hw->media_type == e1000_media_type_fiber) { - /* Clear SW Defineable Pin 0 to turn off the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else { - /* Set SW Defineable Pin 0 to turn off the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } - break; - default: - if (hw->media_type == e1000_media_type_fiber) { - /* Set SW Defineable Pin 0 to turn off the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else if (hw->media_type == e1000_media_type_copper) { - ew32(LEDCTL, hw->ledctl_mode1); - return E1000_SUCCESS; - } - break; - } - - ew32(CTRL, ctrl); - - return E1000_SUCCESS; -} - -/** - * e1000_clear_hw_cntrs - Clears all hardware statistics counters. - * @hw: Struct containing variables accessed by shared code - */ -static void e1000_clear_hw_cntrs(struct e1000_hw *hw) -{ - volatile u32 temp; - - temp = er32(CRCERRS); - temp = er32(SYMERRS); - temp = er32(MPC); - temp = er32(SCC); - temp = er32(ECOL); - temp = er32(MCC); - temp = er32(LATECOL); - temp = er32(COLC); - temp = er32(DC); - temp = er32(SEC); - temp = er32(RLEC); - temp = er32(XONRXC); - temp = er32(XONTXC); - temp = er32(XOFFRXC); - temp = er32(XOFFTXC); - temp = er32(FCRUC); - - temp = er32(PRC64); - temp = er32(PRC127); - temp = er32(PRC255); - temp = er32(PRC511); - temp = er32(PRC1023); - temp = er32(PRC1522); - - temp = er32(GPRC); - temp = er32(BPRC); - temp = er32(MPRC); - temp = er32(GPTC); - temp = er32(GORCL); - temp = er32(GORCH); - temp = er32(GOTCL); - temp = er32(GOTCH); - temp = er32(RNBC); - temp = er32(RUC); - temp = er32(RFC); - temp = er32(ROC); - temp = er32(RJC); - temp = er32(TORL); - temp = er32(TORH); - temp = er32(TOTL); - temp = er32(TOTH); - temp = er32(TPR); - temp = er32(TPT); - - temp = er32(PTC64); - temp = er32(PTC127); - temp = er32(PTC255); - temp = er32(PTC511); - temp = er32(PTC1023); - temp = er32(PTC1522); - - temp = er32(MPTC); - temp = er32(BPTC); - - if (hw->mac_type < e1000_82543) - return; - - temp = er32(ALGNERRC); - temp = er32(RXERRC); - temp = er32(TNCRS); - temp = er32(CEXTERR); - temp = er32(TSCTC); - temp = er32(TSCTFC); - - if (hw->mac_type <= e1000_82544) - return; - - temp = er32(MGTPRC); - temp = er32(MGTPDC); - temp = er32(MGTPTC); -} - -/** - * e1000_reset_adaptive - Resets Adaptive IFS to its default state. - * @hw: Struct containing variables accessed by shared code - * - * Call this after e1000_init_hw. You may override the IFS defaults by setting - * hw->ifs_params_forced to true. However, you must initialize hw-> - * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio - * before calling this function. - */ -void e1000_reset_adaptive(struct e1000_hw *hw) -{ - e_dbg("e1000_reset_adaptive"); - - if (hw->adaptive_ifs) { - if (!hw->ifs_params_forced) { - hw->current_ifs_val = 0; - hw->ifs_min_val = IFS_MIN; - hw->ifs_max_val = IFS_MAX; - hw->ifs_step_size = IFS_STEP; - hw->ifs_ratio = IFS_RATIO; - } - hw->in_ifs_mode = false; - ew32(AIT, 0); - } else { - e_dbg("Not in Adaptive IFS mode!\n"); - } -} - -/** - * e1000_update_adaptive - update adaptive IFS - * @hw: Struct containing variables accessed by shared code - * @tx_packets: Number of transmits since last callback - * @total_collisions: Number of collisions since last callback - * - * Called during the callback/watchdog routine to update IFS value based on - * the ratio of transmits to collisions. - */ -void e1000_update_adaptive(struct e1000_hw *hw) -{ - e_dbg("e1000_update_adaptive"); - - if (hw->adaptive_ifs) { - if ((hw->collision_delta *hw->ifs_ratio) > hw->tx_packet_delta) { - if (hw->tx_packet_delta > MIN_NUM_XMITS) { - hw->in_ifs_mode = true; - if (hw->current_ifs_val < hw->ifs_max_val) { - if (hw->current_ifs_val == 0) - hw->current_ifs_val = - hw->ifs_min_val; - else - hw->current_ifs_val += - hw->ifs_step_size; - ew32(AIT, hw->current_ifs_val); - } - } - } else { - if (hw->in_ifs_mode - && (hw->tx_packet_delta <= MIN_NUM_XMITS)) { - hw->current_ifs_val = 0; - hw->in_ifs_mode = false; - ew32(AIT, 0); - } - } - } else { - e_dbg("Not in Adaptive IFS mode!\n"); - } -} - -/** - * e1000_tbi_adjust_stats - * @hw: Struct containing variables accessed by shared code - * @frame_len: The length of the frame in question - * @mac_addr: The Ethernet destination address of the frame in question - * - * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT - */ -void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, - u32 frame_len, u8 *mac_addr) -{ - u64 carry_bit; - - /* First adjust the frame length. */ - frame_len--; - /* We need to adjust the statistics counters, since the hardware - * counters overcount this packet as a CRC error and undercount - * the packet as a good packet - */ - /* This packet should not be counted as a CRC error. */ - stats->crcerrs--; - /* This packet does count as a Good Packet Received. */ - stats->gprc++; - - /* Adjust the Good Octets received counters */ - carry_bit = 0x80000000 & stats->gorcl; - stats->gorcl += frame_len; - /* If the high bit of Gorcl (the low 32 bits of the Good Octets - * Received Count) was one before the addition, - * AND it is zero after, then we lost the carry out, - * need to add one to Gorch (Good Octets Received Count High). - * This could be simplified if all environments supported - * 64-bit integers. - */ - if (carry_bit && ((stats->gorcl & 0x80000000) == 0)) - stats->gorch++; - /* Is this a broadcast or multicast? Check broadcast first, - * since the test for a multicast frame will test positive on - * a broadcast frame. - */ - if ((mac_addr[0] == (u8) 0xff) && (mac_addr[1] == (u8) 0xff)) - /* Broadcast packet */ - stats->bprc++; - else if (*mac_addr & 0x01) - /* Multicast packet */ - stats->mprc++; - - if (frame_len == hw->max_frame_size) { - /* In this case, the hardware has overcounted the number of - * oversize frames. - */ - if (stats->roc > 0) - stats->roc--; - } - - /* Adjust the bin counters when the extra byte put the frame in the - * wrong bin. Remember that the frame_len was adjusted above. - */ - if (frame_len == 64) { - stats->prc64++; - stats->prc127--; - } else if (frame_len == 127) { - stats->prc127++; - stats->prc255--; - } else if (frame_len == 255) { - stats->prc255++; - stats->prc511--; - } else if (frame_len == 511) { - stats->prc511++; - stats->prc1023--; - } else if (frame_len == 1023) { - stats->prc1023++; - stats->prc1522--; - } else if (frame_len == 1522) { - stats->prc1522++; - } -} - -/** - * e1000_get_bus_info - * @hw: Struct containing variables accessed by shared code - * - * Gets the current PCI bus type, speed, and width of the hardware - */ -void e1000_get_bus_info(struct e1000_hw *hw) -{ - u32 status; - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - hw->bus_type = e1000_bus_type_pci; - hw->bus_speed = e1000_bus_speed_unknown; - hw->bus_width = e1000_bus_width_unknown; - break; - default: - status = er32(STATUS); - hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? - e1000_bus_type_pcix : e1000_bus_type_pci; - - if (hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) { - hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ? - e1000_bus_speed_66 : e1000_bus_speed_120; - } else if (hw->bus_type == e1000_bus_type_pci) { - hw->bus_speed = (status & E1000_STATUS_PCI66) ? - e1000_bus_speed_66 : e1000_bus_speed_33; - } else { - switch (status & E1000_STATUS_PCIX_SPEED) { - case E1000_STATUS_PCIX_SPEED_66: - hw->bus_speed = e1000_bus_speed_66; - break; - case E1000_STATUS_PCIX_SPEED_100: - hw->bus_speed = e1000_bus_speed_100; - break; - case E1000_STATUS_PCIX_SPEED_133: - hw->bus_speed = e1000_bus_speed_133; - break; - default: - hw->bus_speed = e1000_bus_speed_reserved; - break; - } - } - hw->bus_width = (status & E1000_STATUS_BUS64) ? - e1000_bus_width_64 : e1000_bus_width_32; - break; - } -} - -/** - * e1000_write_reg_io - * @hw: Struct containing variables accessed by shared code - * @offset: offset to write to - * @value: value to write - * - * Writes a value to one of the devices registers using port I/O (as opposed to - * memory mapped I/O). Only 82544 and newer devices support port I/O. - */ -static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value) -{ - unsigned long io_addr = hw->io_base; - unsigned long io_data = hw->io_base + 4; - - e1000_io_write(hw, io_addr, offset); - e1000_io_write(hw, io_data, value); -} - -/** - * e1000_get_cable_length - Estimates the cable length. - * @hw: Struct containing variables accessed by shared code - * @min_length: The estimated minimum length - * @max_length: The estimated maximum length - * - * returns: - E1000_ERR_XXX - * E1000_SUCCESS - * - * This function always returns a ranged length (minimum & maximum). - * So for M88 phy's, this function interprets the one value returned from the - * register to the minimum and maximum range. - * For IGP phy's, the function calculates the range by the AGC registers. - */ -static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length, - u16 *max_length) -{ - s32 ret_val; - u16 agc_value = 0; - u16 i, phy_data; - u16 cable_length; - - e_dbg("e1000_get_cable_length"); - - *min_length = *max_length = 0; - - /* Use old method for Phy older than IGP */ - if (hw->phy_type == e1000_phy_m88) { - - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data); - if (ret_val) - return ret_val; - cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT; - - /* Convert the enum value to ranged values */ - switch (cable_length) { - case e1000_cable_length_50: - *min_length = 0; - *max_length = e1000_igp_cable_length_50; - break; - case e1000_cable_length_50_80: - *min_length = e1000_igp_cable_length_50; - *max_length = e1000_igp_cable_length_80; - break; - case e1000_cable_length_80_110: - *min_length = e1000_igp_cable_length_80; - *max_length = e1000_igp_cable_length_110; - break; - case e1000_cable_length_110_140: - *min_length = e1000_igp_cable_length_110; - *max_length = e1000_igp_cable_length_140; - break; - case e1000_cable_length_140: - *min_length = e1000_igp_cable_length_140; - *max_length = e1000_igp_cable_length_170; - break; - default: - return -E1000_ERR_PHY; - break; - } - } else if (hw->phy_type == e1000_phy_igp) { /* For IGP PHY */ - u16 cur_agc_value; - u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE; - static const u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = { - IGP01E1000_PHY_AGC_A, - IGP01E1000_PHY_AGC_B, - IGP01E1000_PHY_AGC_C, - IGP01E1000_PHY_AGC_D - }; - /* Read the AGC registers for all channels */ - for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { - - ret_val = - e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data); - if (ret_val) - return ret_val; - - cur_agc_value = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT; - - /* Value bound check. */ - if ((cur_agc_value >= - IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) - || (cur_agc_value == 0)) - return -E1000_ERR_PHY; - - agc_value += cur_agc_value; - - /* Update minimal AGC value. */ - if (min_agc_value > cur_agc_value) - min_agc_value = cur_agc_value; - } - - /* Remove the minimal AGC result for length < 50m */ - if (agc_value < - IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) { - agc_value -= min_agc_value; - - /* Get the average length of the remaining 3 channels */ - agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1); - } else { - /* Get the average length of all the 4 channels. */ - agc_value /= IGP01E1000_PHY_CHANNEL_NUM; - } - - /* Set the range of the calculated length. */ - *min_length = ((e1000_igp_cable_length_table[agc_value] - - IGP01E1000_AGC_RANGE) > 0) ? - (e1000_igp_cable_length_table[agc_value] - - IGP01E1000_AGC_RANGE) : 0; - *max_length = e1000_igp_cable_length_table[agc_value] + - IGP01E1000_AGC_RANGE; - } - - return E1000_SUCCESS; -} - -/** - * e1000_check_polarity - Check the cable polarity - * @hw: Struct containing variables accessed by shared code - * @polarity: output parameter : 0 - Polarity is not reversed - * 1 - Polarity is reversed. - * - * returns: - E1000_ERR_XXX - * E1000_SUCCESS - * - * For phy's older than IGP, this function simply reads the polarity bit in the - * Phy Status register. For IGP phy's, this bit is valid only if link speed is - * 10 Mbps. If the link speed is 100 Mbps there is no polarity so this bit will - * return 0. If the link speed is 1000 Mbps the polarity status is in the - * IGP01E1000_PHY_PCS_INIT_REG. - */ -static s32 e1000_check_polarity(struct e1000_hw *hw, - e1000_rev_polarity *polarity) -{ - s32 ret_val; - u16 phy_data; - - e_dbg("e1000_check_polarity"); - - if (hw->phy_type == e1000_phy_m88) { - /* return the Polarity bit in the Status register. */ - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data); - if (ret_val) - return ret_val; - *polarity = ((phy_data & M88E1000_PSSR_REV_POLARITY) >> - M88E1000_PSSR_REV_POLARITY_SHIFT) ? - e1000_rev_polarity_reversed : e1000_rev_polarity_normal; - - } else if (hw->phy_type == e1000_phy_igp) { - /* Read the Status register to check the speed */ - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, - &phy_data); - if (ret_val) - return ret_val; - - /* If speed is 1000 Mbps, must read the - * IGP01E1000_PHY_PCS_INIT_REG to find the polarity status - */ - if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - - /* Read the GIG initialization PCS register (0x00B4) */ - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG, - &phy_data); - if (ret_val) - return ret_val; - - /* Check the polarity bits */ - *polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ? - e1000_rev_polarity_reversed : - e1000_rev_polarity_normal; - } else { - /* For 10 Mbps, read the polarity bit in the status - * register. (for 100 Mbps this bit is always 0) - */ - *polarity = - (phy_data & IGP01E1000_PSSR_POLARITY_REVERSED) ? - e1000_rev_polarity_reversed : - e1000_rev_polarity_normal; - } - } - return E1000_SUCCESS; -} - -/** - * e1000_check_downshift - Check if Downshift occurred - * @hw: Struct containing variables accessed by shared code - * @downshift: output parameter : 0 - No Downshift occurred. - * 1 - Downshift occurred. - * - * returns: - E1000_ERR_XXX - * E1000_SUCCESS - * - * For phy's older than IGP, this function reads the Downshift bit in the Phy - * Specific Status register. For IGP phy's, it reads the Downgrade bit in the - * Link Health register. In IGP this bit is latched high, so the driver must - * read it immediately after link is established. - */ -static s32 e1000_check_downshift(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - - e_dbg("e1000_check_downshift"); - - if (hw->phy_type == e1000_phy_igp) { - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, - &phy_data); - if (ret_val) - return ret_val; - - hw->speed_downgraded = - (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; - } else if (hw->phy_type == e1000_phy_m88) { - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data); - if (ret_val) - return ret_val; - - hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >> - M88E1000_PSSR_DOWNSHIFT_SHIFT; - } - - return E1000_SUCCESS; -} - -static const u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = { - IGP01E1000_PHY_AGC_PARAM_A, - IGP01E1000_PHY_AGC_PARAM_B, - IGP01E1000_PHY_AGC_PARAM_C, - IGP01E1000_PHY_AGC_PARAM_D -}; - -static s32 e1000_1000Mb_check_cable_length(struct e1000_hw *hw) -{ - u16 min_length, max_length; - u16 phy_data, i; - s32 ret_val; - - ret_val = e1000_get_cable_length(hw, &min_length, &max_length); - if (ret_val) - return ret_val; - - if (hw->dsp_config_state != e1000_dsp_config_enabled) - return 0; - - if (min_length >= e1000_igp_cable_length_50) { - for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { - ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], - &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; - - ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i], - phy_data); - if (ret_val) - return ret_val; - } - hw->dsp_config_state = e1000_dsp_config_activated; - } else { - u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20; - u32 idle_errs = 0; - - /* clear previous idle error counts */ - ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); - if (ret_val) - return ret_val; - - for (i = 0; i < ffe_idle_err_timeout; i++) { - udelay(1000); - ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, - &phy_data); - if (ret_val) - return ret_val; - - idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT); - if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) { - hw->ffe_config_state = e1000_ffe_config_active; - - ret_val = e1000_write_phy_reg(hw, - IGP01E1000_PHY_DSP_FFE, - IGP01E1000_PHY_DSP_FFE_CM_CP); - if (ret_val) - return ret_val; - break; - } - - if (idle_errs) - ffe_idle_err_timeout = - FFE_IDLE_ERR_COUNT_TIMEOUT_100; - } - } - - return 0; -} - -/** - * e1000_config_dsp_after_link_change - * @hw: Struct containing variables accessed by shared code - * @link_up: was link up at the time this was called - * - * returns: - E1000_ERR_PHY if fail to read/write the PHY - * E1000_SUCCESS at any other case. - * - * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a - * gigabit link is achieved to improve link quality. - */ - -static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up) -{ - s32 ret_val; - u16 phy_data, phy_saved_data, speed, duplex, i; - - e_dbg("e1000_config_dsp_after_link_change"); - - if (hw->phy_type != e1000_phy_igp) - return E1000_SUCCESS; - - if (link_up) { - ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex); - if (ret_val) { - e_dbg("Error getting link speed and duplex\n"); - return ret_val; - } - - if (speed == SPEED_1000) { - ret_val = e1000_1000Mb_check_cable_length(hw); - if (ret_val) - return ret_val; - } - } else { - if (hw->dsp_config_state == e1000_dsp_config_activated) { - /* Save off the current value of register 0x2F5B to be - * restored at the end of the routines. - */ - ret_val = - e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data); - - if (ret_val) - return ret_val; - - /* Disable the PHY transmitter */ - ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003); - - if (ret_val) - return ret_val; - - msleep(20); - - ret_val = e1000_write_phy_reg(hw, 0x0000, - IGP01E1000_IEEE_FORCE_GIGA); - if (ret_val) - return ret_val; - for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { - ret_val = - e1000_read_phy_reg(hw, dsp_reg_array[i], - &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; - phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS; - - ret_val = - e1000_write_phy_reg(hw, dsp_reg_array[i], - phy_data); - if (ret_val) - return ret_val; - } - - ret_val = e1000_write_phy_reg(hw, 0x0000, - IGP01E1000_IEEE_RESTART_AUTONEG); - if (ret_val) - return ret_val; - - msleep(20); - - /* Now enable the transmitter */ - ret_val = - e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data); - - if (ret_val) - return ret_val; - - hw->dsp_config_state = e1000_dsp_config_enabled; - } - - if (hw->ffe_config_state == e1000_ffe_config_active) { - /* Save off the current value of register 0x2F5B to be - * restored at the end of the routines. - */ - ret_val = - e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data); - - if (ret_val) - return ret_val; - - /* Disable the PHY transmitter */ - ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003); - - if (ret_val) - return ret_val; - - msleep(20); - - ret_val = e1000_write_phy_reg(hw, 0x0000, - IGP01E1000_IEEE_FORCE_GIGA); - if (ret_val) - return ret_val; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE, - IGP01E1000_PHY_DSP_FFE_DEFAULT); - if (ret_val) - return ret_val; - - ret_val = e1000_write_phy_reg(hw, 0x0000, - IGP01E1000_IEEE_RESTART_AUTONEG); - if (ret_val) - return ret_val; - - msleep(20); - - /* Now enable the transmitter */ - ret_val = - e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data); - - if (ret_val) - return ret_val; - - hw->ffe_config_state = e1000_ffe_config_enabled; - } - } - return E1000_SUCCESS; -} - -/** - * e1000_set_phy_mode - Set PHY to class A mode - * @hw: Struct containing variables accessed by shared code - * - * Assumes the following operations will follow to enable the new class mode. - * 1. Do a PHY soft reset - * 2. Restart auto-negotiation or force link. - */ -static s32 e1000_set_phy_mode(struct e1000_hw *hw) -{ - s32 ret_val; - u16 eeprom_data; - - e_dbg("e1000_set_phy_mode"); - - if ((hw->mac_type == e1000_82545_rev_3) && - (hw->media_type == e1000_media_type_copper)) { - ret_val = - e1000_read_eeprom(hw, EEPROM_PHY_CLASS_WORD, 1, - &eeprom_data); - if (ret_val) { - return ret_val; - } - - if ((eeprom_data != EEPROM_RESERVED_WORD) && - (eeprom_data & EEPROM_PHY_CLASS_A)) { - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, - 0x000B); - if (ret_val) - return ret_val; - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, - 0x8104); - if (ret_val) - return ret_val; - - hw->phy_reset_disable = false; - } - } - - return E1000_SUCCESS; -} - -/** - * e1000_set_d3_lplu_state - set d3 link power state - * @hw: Struct containing variables accessed by shared code - * @active: true to enable lplu false to disable lplu. - * - * This function sets the lplu state according to the active flag. When - * activating lplu this function also disables smart speed and vise versa. - * lplu will not be activated unless the device autonegotiation advertisement - * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes. - * - * returns: - E1000_ERR_PHY if fail to read/write the PHY - * E1000_SUCCESS at any other case. - */ -static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active) -{ - s32 ret_val; - u16 phy_data; - e_dbg("e1000_set_d3_lplu_state"); - - if (hw->phy_type != e1000_phy_igp) - return E1000_SUCCESS; - - /* During driver activity LPLU should not be used or it will attain link - * from the lowest speeds starting from 10Mbps. The capability is used - * for Dx transitions and states - */ - if (hw->mac_type == e1000_82541_rev_2 - || hw->mac_type == e1000_82547_rev_2) { - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data); - if (ret_val) - return ret_val; - } - - if (!active) { - if (hw->mac_type == e1000_82541_rev_2 || - hw->mac_type == e1000_82547_rev_2) { - phy_data &= ~IGP01E1000_GMII_FLEX_SPD; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, - phy_data); - if (ret_val) - return ret_val; - } - - /* LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (hw->smart_speed == e1000_smart_speed_on) { - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data); - if (ret_val) - return ret_val; - - phy_data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - phy_data); - if (ret_val) - return ret_val; - } else if (hw->smart_speed == e1000_smart_speed_off) { - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - phy_data); - if (ret_val) - return ret_val; - } - } else if ((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) - || (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL) - || (hw->autoneg_advertised == - AUTONEG_ADVERTISE_10_100_ALL)) { - - if (hw->mac_type == e1000_82541_rev_2 || - hw->mac_type == e1000_82547_rev_2) { - phy_data |= IGP01E1000_GMII_FLEX_SPD; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, - phy_data); - if (ret_val) - return ret_val; - } - - /* When LPLU is enabled we should disable SmartSpeed */ - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - phy_data); - if (ret_val) - return ret_val; - - } - return E1000_SUCCESS; -} - -/** - * e1000_set_vco_speed - * @hw: Struct containing variables accessed by shared code - * - * Change VCO speed register to improve Bit Error Rate performance of SERDES. - */ -static s32 e1000_set_vco_speed(struct e1000_hw *hw) -{ - s32 ret_val; - u16 default_page = 0; - u16 phy_data; - - e_dbg("e1000_set_vco_speed"); - - switch (hw->mac_type) { - case e1000_82545_rev_3: - case e1000_82546_rev_3: - break; - default: - return E1000_SUCCESS; - } - - /* Set PHY register 30, page 5, bit 8 to 0 */ - - ret_val = - e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page); - if (ret_val) - return ret_val; - - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005); - if (ret_val) - return ret_val; - - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~M88E1000_PHY_VCO_REG_BIT8; - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); - if (ret_val) - return ret_val; - - /* Set PHY register 30, page 4, bit 11 to 1 */ - - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004); - if (ret_val) - return ret_val; - - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_PHY_VCO_REG_BIT11; - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); - if (ret_val) - return ret_val; - - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page); - if (ret_val) - return ret_val; - - return E1000_SUCCESS; -} - - -/** - * e1000_enable_mng_pass_thru - check for bmc pass through - * @hw: Struct containing variables accessed by shared code - * - * Verifies the hardware needs to allow ARPs to be processed by the host - * returns: - true/false - */ -u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw) -{ - u32 manc; - - if (hw->asf_firmware_present) { - manc = er32(MANC); - - if (!(manc & E1000_MANC_RCV_TCO_EN) || - !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) - return false; - if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN)) - return true; - } - return false; -} - -static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw) -{ - s32 ret_val; - u16 mii_status_reg; - u16 i; - - /* Polarity reversal workaround for forced 10F/10H links. */ - - /* Disable the transmitter on the PHY */ - - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); - if (ret_val) - return ret_val; - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF); - if (ret_val) - return ret_val; - - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); - if (ret_val) - return ret_val; - - /* This loop will early-out if the NO link condition has been met. */ - for (i = PHY_FORCE_TIME; i > 0; i--) { - /* Read the MII Status Register and wait for Link Status bit - * to be clear. - */ - - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0) - break; - msleep(100); - } - - /* Recommended delay time after link has been lost */ - msleep(1000); - - /* Now we will re-enable th transmitter on the PHY */ - - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); - if (ret_val) - return ret_val; - msleep(50); - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0); - if (ret_val) - return ret_val; - msleep(50); - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00); - if (ret_val) - return ret_val; - msleep(50); - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000); - if (ret_val) - return ret_val; - - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); - if (ret_val) - return ret_val; - - /* This loop will early-out if the link condition has been met. */ - for (i = PHY_FORCE_TIME; i > 0; i--) { - /* Read the MII Status Register and wait for Link Status bit - * to be set. - */ - - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - if (mii_status_reg & MII_SR_LINK_STATUS) - break; - msleep(100); - } - return E1000_SUCCESS; -} - -/** - * e1000_get_auto_rd_done - * @hw: Struct containing variables accessed by shared code - * - * Check for EEPROM Auto Read bit done. - * returns: - E1000_ERR_RESET if fail to reset MAC - * E1000_SUCCESS at any other case. - */ -static s32 e1000_get_auto_rd_done(struct e1000_hw *hw) -{ - e_dbg("e1000_get_auto_rd_done"); - msleep(5); - return E1000_SUCCESS; -} - -/** - * e1000_get_phy_cfg_done - * @hw: Struct containing variables accessed by shared code - * - * Checks if the PHY configuration is done - * returns: - E1000_ERR_RESET if fail to reset MAC - * E1000_SUCCESS at any other case. - */ -static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw) -{ - e_dbg("e1000_get_phy_cfg_done"); - msleep(10); - return E1000_SUCCESS; -} diff --git a/addons/e1000/src/3.10.108/e1000_hw.h b/addons/e1000/src/3.10.108/e1000_hw.h deleted file mode 100644 index 11578c89..00000000 --- a/addons/e1000/src/3.10.108/e1000_hw.h +++ /dev/null @@ -1,3112 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* e1000_hw.h - * Structures, enums, and macros for the MAC - */ - -#ifndef _E1000_HW_H_ -#define _E1000_HW_H_ - -#include "e1000_osdep.h" - - -/* Forward declarations of structures used by the shared code */ -struct e1000_hw; -struct e1000_hw_stats; - -/* Enumerated types specific to the e1000 hardware */ -/* Media Access Controllers */ -typedef enum { - e1000_undefined = 0, - e1000_82542_rev2_0, - e1000_82542_rev2_1, - e1000_82543, - e1000_82544, - e1000_82540, - e1000_82545, - e1000_82545_rev_3, - e1000_82546, - e1000_ce4100, - e1000_82546_rev_3, - e1000_82541, - e1000_82541_rev_2, - e1000_82547, - e1000_82547_rev_2, - e1000_num_macs -} e1000_mac_type; - -typedef enum { - e1000_eeprom_uninitialized = 0, - e1000_eeprom_spi, - e1000_eeprom_microwire, - e1000_eeprom_flash, - e1000_eeprom_none, /* No NVM support */ - e1000_num_eeprom_types -} e1000_eeprom_type; - -/* Media Types */ -typedef enum { - e1000_media_type_copper = 0, - e1000_media_type_fiber = 1, - e1000_media_type_internal_serdes = 2, - e1000_num_media_types -} e1000_media_type; - -typedef enum { - e1000_10_half = 0, - e1000_10_full = 1, - e1000_100_half = 2, - e1000_100_full = 3 -} e1000_speed_duplex_type; - -/* Flow Control Settings */ -typedef enum { - E1000_FC_NONE = 0, - E1000_FC_RX_PAUSE = 1, - E1000_FC_TX_PAUSE = 2, - E1000_FC_FULL = 3, - E1000_FC_DEFAULT = 0xFF -} e1000_fc_type; - -struct e1000_shadow_ram { - u16 eeprom_word; - bool modified; -}; - -/* PCI bus types */ -typedef enum { - e1000_bus_type_unknown = 0, - e1000_bus_type_pci, - e1000_bus_type_pcix, - e1000_bus_type_reserved -} e1000_bus_type; - -/* PCI bus speeds */ -typedef enum { - e1000_bus_speed_unknown = 0, - e1000_bus_speed_33, - e1000_bus_speed_66, - e1000_bus_speed_100, - e1000_bus_speed_120, - e1000_bus_speed_133, - e1000_bus_speed_reserved -} e1000_bus_speed; - -/* PCI bus widths */ -typedef enum { - e1000_bus_width_unknown = 0, - e1000_bus_width_32, - e1000_bus_width_64, - e1000_bus_width_reserved -} e1000_bus_width; - -/* PHY status info structure and supporting enums */ -typedef enum { - e1000_cable_length_50 = 0, - e1000_cable_length_50_80, - e1000_cable_length_80_110, - e1000_cable_length_110_140, - e1000_cable_length_140, - e1000_cable_length_undefined = 0xFF -} e1000_cable_length; - -typedef enum { - e1000_gg_cable_length_60 = 0, - e1000_gg_cable_length_60_115 = 1, - e1000_gg_cable_length_115_150 = 2, - e1000_gg_cable_length_150 = 4 -} e1000_gg_cable_length; - -typedef enum { - e1000_igp_cable_length_10 = 10, - e1000_igp_cable_length_20 = 20, - e1000_igp_cable_length_30 = 30, - e1000_igp_cable_length_40 = 40, - e1000_igp_cable_length_50 = 50, - e1000_igp_cable_length_60 = 60, - e1000_igp_cable_length_70 = 70, - e1000_igp_cable_length_80 = 80, - e1000_igp_cable_length_90 = 90, - e1000_igp_cable_length_100 = 100, - e1000_igp_cable_length_110 = 110, - e1000_igp_cable_length_115 = 115, - e1000_igp_cable_length_120 = 120, - e1000_igp_cable_length_130 = 130, - e1000_igp_cable_length_140 = 140, - e1000_igp_cable_length_150 = 150, - e1000_igp_cable_length_160 = 160, - e1000_igp_cable_length_170 = 170, - e1000_igp_cable_length_180 = 180 -} e1000_igp_cable_length; - -typedef enum { - e1000_10bt_ext_dist_enable_normal = 0, - e1000_10bt_ext_dist_enable_lower, - e1000_10bt_ext_dist_enable_undefined = 0xFF -} e1000_10bt_ext_dist_enable; - -typedef enum { - e1000_rev_polarity_normal = 0, - e1000_rev_polarity_reversed, - e1000_rev_polarity_undefined = 0xFF -} e1000_rev_polarity; - -typedef enum { - e1000_downshift_normal = 0, - e1000_downshift_activated, - e1000_downshift_undefined = 0xFF -} e1000_downshift; - -typedef enum { - e1000_smart_speed_default = 0, - e1000_smart_speed_on, - e1000_smart_speed_off -} e1000_smart_speed; - -typedef enum { - e1000_polarity_reversal_enabled = 0, - e1000_polarity_reversal_disabled, - e1000_polarity_reversal_undefined = 0xFF -} e1000_polarity_reversal; - -typedef enum { - e1000_auto_x_mode_manual_mdi = 0, - e1000_auto_x_mode_manual_mdix, - e1000_auto_x_mode_auto1, - e1000_auto_x_mode_auto2, - e1000_auto_x_mode_undefined = 0xFF -} e1000_auto_x_mode; - -typedef enum { - e1000_1000t_rx_status_not_ok = 0, - e1000_1000t_rx_status_ok, - e1000_1000t_rx_status_undefined = 0xFF -} e1000_1000t_rx_status; - -typedef enum { - e1000_phy_m88 = 0, - e1000_phy_igp, - e1000_phy_8211, - e1000_phy_8201, - e1000_phy_undefined = 0xFF -} e1000_phy_type; - -typedef enum { - e1000_ms_hw_default = 0, - e1000_ms_force_master, - e1000_ms_force_slave, - e1000_ms_auto -} e1000_ms_type; - -typedef enum { - e1000_ffe_config_enabled = 0, - e1000_ffe_config_active, - e1000_ffe_config_blocked -} e1000_ffe_config; - -typedef enum { - e1000_dsp_config_disabled = 0, - e1000_dsp_config_enabled, - e1000_dsp_config_activated, - e1000_dsp_config_undefined = 0xFF -} e1000_dsp_config; - -struct e1000_phy_info { - e1000_cable_length cable_length; - e1000_10bt_ext_dist_enable extended_10bt_distance; - e1000_rev_polarity cable_polarity; - e1000_downshift downshift; - e1000_polarity_reversal polarity_correction; - e1000_auto_x_mode mdix_mode; - e1000_1000t_rx_status local_rx; - e1000_1000t_rx_status remote_rx; -}; - -struct e1000_phy_stats { - u32 idle_errors; - u32 receive_errors; -}; - -struct e1000_eeprom_info { - e1000_eeprom_type type; - u16 word_size; - u16 opcode_bits; - u16 address_bits; - u16 delay_usec; - u16 page_size; -}; - -/* Flex ASF Information */ -#define E1000_HOST_IF_MAX_SIZE 2048 - -typedef enum { - e1000_byte_align = 0, - e1000_word_align = 1, - e1000_dword_align = 2 -} e1000_align_type; - -/* Error Codes */ -#define E1000_SUCCESS 0 -#define E1000_ERR_EEPROM 1 -#define E1000_ERR_PHY 2 -#define E1000_ERR_CONFIG 3 -#define E1000_ERR_PARAM 4 -#define E1000_ERR_MAC_TYPE 5 -#define E1000_ERR_PHY_TYPE 6 -#define E1000_ERR_RESET 9 -#define E1000_ERR_MASTER_REQUESTS_PENDING 10 -#define E1000_ERR_HOST_INTERFACE_COMMAND 11 -#define E1000_BLK_PHY_RESET 12 - -#define E1000_BYTE_SWAP_WORD(_value) ((((_value) & 0x00ff) << 8) | \ - (((_value) & 0xff00) >> 8)) - -/* Function prototypes */ -/* Initialization */ -s32 e1000_reset_hw(struct e1000_hw *hw); -s32 e1000_init_hw(struct e1000_hw *hw); -s32 e1000_set_mac_type(struct e1000_hw *hw); -void e1000_set_media_type(struct e1000_hw *hw); - -/* Link Configuration */ -s32 e1000_setup_link(struct e1000_hw *hw); -s32 e1000_phy_setup_autoneg(struct e1000_hw *hw); -void e1000_config_collision_dist(struct e1000_hw *hw); -s32 e1000_check_for_link(struct e1000_hw *hw); -s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 * speed, u16 * duplex); -s32 e1000_force_mac_fc(struct e1000_hw *hw); - -/* PHY */ -s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 * phy_data); -s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 data); -s32 e1000_phy_hw_reset(struct e1000_hw *hw); -s32 e1000_phy_reset(struct e1000_hw *hw); -s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); -s32 e1000_validate_mdi_setting(struct e1000_hw *hw); - -/* EEPROM Functions */ -s32 e1000_init_eeprom_params(struct e1000_hw *hw); - -/* MNG HOST IF functions */ -u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw); - -#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64 -#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 /* Host Interface data length */ - -#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 /* Time in ms to process MNG command */ -#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 /* Cookie offset */ -#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 /* Cookie length */ -#define E1000_MNG_IAMT_MODE 0x3 -#define E1000_MNG_ICH_IAMT_MODE 0x2 -#define E1000_IAMT_SIGNATURE 0x544D4149 /* Intel(R) Active Management Technology signature */ - -#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT 0x1 /* DHCP parsing enabled */ -#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT 0x2 /* DHCP parsing enabled */ -#define E1000_VFTA_ENTRY_SHIFT 0x5 -#define E1000_VFTA_ENTRY_MASK 0x7F -#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F - -struct e1000_host_mng_command_header { - u8 command_id; - u8 checksum; - u16 reserved1; - u16 reserved2; - u16 command_length; -}; - -struct e1000_host_mng_command_info { - struct e1000_host_mng_command_header command_header; /* Command Head/Command Result Head has 4 bytes */ - u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; /* Command data can length 0..0x658 */ -}; -#ifdef __BIG_ENDIAN -struct e1000_host_mng_dhcp_cookie { - u32 signature; - u16 vlan_id; - u8 reserved0; - u8 status; - u32 reserved1; - u8 checksum; - u8 reserved3; - u16 reserved2; -}; -#else -struct e1000_host_mng_dhcp_cookie { - u32 signature; - u8 status; - u8 reserved0; - u16 vlan_id; - u32 reserved1; - u16 reserved2; - u8 reserved3; - u8 checksum; -}; -#endif - -bool e1000_check_mng_mode(struct e1000_hw *hw); -s32 e1000_read_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 * data); -s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw); -s32 e1000_update_eeprom_checksum(struct e1000_hw *hw); -s32 e1000_write_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 * data); -s32 e1000_read_mac_addr(struct e1000_hw *hw); - -/* Filters (multicast, vlan, receive) */ -u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 * mc_addr); -void e1000_mta_set(struct e1000_hw *hw, u32 hash_value); -void e1000_rar_set(struct e1000_hw *hw, u8 * mc_addr, u32 rar_index); -void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value); - -/* LED functions */ -s32 e1000_setup_led(struct e1000_hw *hw); -s32 e1000_cleanup_led(struct e1000_hw *hw); -s32 e1000_led_on(struct e1000_hw *hw); -s32 e1000_led_off(struct e1000_hw *hw); -s32 e1000_blink_led_start(struct e1000_hw *hw); - -/* Adaptive IFS Functions */ - -/* Everything else */ -void e1000_reset_adaptive(struct e1000_hw *hw); -void e1000_update_adaptive(struct e1000_hw *hw); -void e1000_tbi_adjust_stats(struct e1000_hw *hw, struct e1000_hw_stats *stats, - u32 frame_len, u8 * mac_addr); -void e1000_get_bus_info(struct e1000_hw *hw); -void e1000_pci_set_mwi(struct e1000_hw *hw); -void e1000_pci_clear_mwi(struct e1000_hw *hw); -void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc); -int e1000_pcix_get_mmrbc(struct e1000_hw *hw); -/* Port I/O is only supported on 82544 and newer */ -void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value); - -#define E1000_READ_REG_IO(a, reg) \ - e1000_read_reg_io((a), E1000_##reg) -#define E1000_WRITE_REG_IO(a, reg, val) \ - e1000_write_reg_io((a), E1000_##reg, val) - -/* PCI Device IDs */ -#define E1000_DEV_ID_82542 0x1000 -#define E1000_DEV_ID_82543GC_FIBER 0x1001 -#define E1000_DEV_ID_82543GC_COPPER 0x1004 -#define E1000_DEV_ID_82544EI_COPPER 0x1008 -#define E1000_DEV_ID_82544EI_FIBER 0x1009 -#define E1000_DEV_ID_82544GC_COPPER 0x100C -#define E1000_DEV_ID_82544GC_LOM 0x100D -#define E1000_DEV_ID_82540EM 0x100E -#define E1000_DEV_ID_82540EM_LOM 0x1015 -#define E1000_DEV_ID_82540EP_LOM 0x1016 -#define E1000_DEV_ID_82540EP 0x1017 -#define E1000_DEV_ID_82540EP_LP 0x101E -#define E1000_DEV_ID_82545EM_COPPER 0x100F -#define E1000_DEV_ID_82545EM_FIBER 0x1011 -#define E1000_DEV_ID_82545GM_COPPER 0x1026 -#define E1000_DEV_ID_82545GM_FIBER 0x1027 -#define E1000_DEV_ID_82545GM_SERDES 0x1028 -#define E1000_DEV_ID_82546EB_COPPER 0x1010 -#define E1000_DEV_ID_82546EB_FIBER 0x1012 -#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D -#define E1000_DEV_ID_82541EI 0x1013 -#define E1000_DEV_ID_82541EI_MOBILE 0x1018 -#define E1000_DEV_ID_82541ER_LOM 0x1014 -#define E1000_DEV_ID_82541ER 0x1078 -#define E1000_DEV_ID_82547GI 0x1075 -#define E1000_DEV_ID_82541GI 0x1076 -#define E1000_DEV_ID_82541GI_MOBILE 0x1077 -#define E1000_DEV_ID_82541GI_LF 0x107C -#define E1000_DEV_ID_82546GB_COPPER 0x1079 -#define E1000_DEV_ID_82546GB_FIBER 0x107A -#define E1000_DEV_ID_82546GB_SERDES 0x107B -#define E1000_DEV_ID_82546GB_PCIE 0x108A -#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099 -#define E1000_DEV_ID_82547EI 0x1019 -#define E1000_DEV_ID_82547EI_MOBILE 0x101A -#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5 -#define E1000_DEV_ID_INTEL_CE4100_GBE 0x2E6E - -#define NODE_ADDRESS_SIZE 6 - -/* MAC decode size is 128K - This is the size of BAR0 */ -#define MAC_DECODE_SIZE (128 * 1024) - -#define E1000_82542_2_0_REV_ID 2 -#define E1000_82542_2_1_REV_ID 3 -#define E1000_REVISION_0 0 -#define E1000_REVISION_1 1 -#define E1000_REVISION_2 2 -#define E1000_REVISION_3 3 - -#define SPEED_10 10 -#define SPEED_100 100 -#define SPEED_1000 1000 -#define HALF_DUPLEX 1 -#define FULL_DUPLEX 2 - -/* The sizes (in bytes) of a ethernet packet */ -#define ENET_HEADER_SIZE 14 -#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */ -#define ETHERNET_FCS_SIZE 4 -#define MINIMUM_ETHERNET_PACKET_SIZE \ - (MINIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE) -#define CRC_LENGTH ETHERNET_FCS_SIZE -#define MAX_JUMBO_FRAME_SIZE 0x3F00 - -/* 802.1q VLAN Packet Sizes */ -#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMAed) */ - -/* Ethertype field values */ -#define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */ -#define ETHERNET_IP_TYPE 0x0800 /* IP packets */ -#define ETHERNET_ARP_TYPE 0x0806 /* Address Resolution Protocol (ARP) */ - -/* Packet Header defines */ -#define IP_PROTOCOL_TCP 6 -#define IP_PROTOCOL_UDP 0x11 - -/* This defines the bits that are set in the Interrupt Mask - * Set/Read Register. Each bit is documented below: - * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) - * o RXSEQ = Receive Sequence Error - */ -#define POLL_IMS_ENABLE_MASK ( \ - E1000_IMS_RXDMT0 | \ - E1000_IMS_RXSEQ) - -/* This defines the bits that are set in the Interrupt Mask - * Set/Read Register. Each bit is documented below: - * o RXT0 = Receiver Timer Interrupt (ring 0) - * o TXDW = Transmit Descriptor Written Back - * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) - * o RXSEQ = Receive Sequence Error - * o LSC = Link Status Change - */ -#define IMS_ENABLE_MASK ( \ - E1000_IMS_RXT0 | \ - E1000_IMS_TXDW | \ - E1000_IMS_RXDMT0 | \ - E1000_IMS_RXSEQ | \ - E1000_IMS_LSC) - -/* Number of high/low register pairs in the RAR. The RAR (Receive Address - * Registers) holds the directed and multicast addresses that we monitor. We - * reserve one of these spots for our directed address, allowing us room for - * E1000_RAR_ENTRIES - 1 multicast addresses. - */ -#define E1000_RAR_ENTRIES 15 - -#define MIN_NUMBER_OF_DESCRIPTORS 8 -#define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8 - -/* Receive Descriptor */ -struct e1000_rx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - __le16 length; /* Length of data DMAed into data buffer */ - __le16 csum; /* Packet checksum */ - u8 status; /* Descriptor status */ - u8 errors; /* Descriptor Errors */ - __le16 special; -}; - -/* Receive Descriptor - Extended */ -union e1000_rx_desc_extended { - struct { - __le64 buffer_addr; - __le64 reserved; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length; - __le16 vlan; /* VLAN tag */ - } upper; - } wb; /* writeback */ -}; - -#define MAX_PS_BUFFERS 4 -/* Receive Descriptor - Packet Split */ -union e1000_rx_desc_packet_split { - struct { - /* one buffer for protocol header(s), three data buffers */ - __le64 buffer_addr[MAX_PS_BUFFERS]; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length0; /* length of buffer 0 */ - __le16 vlan; /* VLAN tag */ - } middle; - struct { - __le16 header_status; - __le16 length[3]; /* length of buffers 1-3 */ - } upper; - __le64 reserved; - } wb; /* writeback */ -}; - -/* Receive Descriptor bit definitions */ -#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ -#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */ -#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */ -#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ -#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ -#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ -#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ -#define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */ -#define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */ -#define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */ -#define E1000_RXD_STAT_ACK 0x8000 /* ACK Packet indication */ -#define E1000_RXD_ERR_CE 0x01 /* CRC Error */ -#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ -#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ -#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */ -#define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */ -#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */ -#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ -#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ -#define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */ -#define E1000_RXD_SPC_PRI_SHIFT 13 -#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */ -#define E1000_RXD_SPC_CFI_SHIFT 12 - -#define E1000_RXDEXT_STATERR_CE 0x01000000 -#define E1000_RXDEXT_STATERR_SE 0x02000000 -#define E1000_RXDEXT_STATERR_SEQ 0x04000000 -#define E1000_RXDEXT_STATERR_CXE 0x10000000 -#define E1000_RXDEXT_STATERR_TCPE 0x20000000 -#define E1000_RXDEXT_STATERR_IPE 0x40000000 -#define E1000_RXDEXT_STATERR_RXE 0x80000000 - -#define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000 -#define E1000_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF - -/* mask to determine if packets should be dropped due to frame errors */ -#define E1000_RXD_ERR_FRAME_ERR_MASK ( \ - E1000_RXD_ERR_CE | \ - E1000_RXD_ERR_SE | \ - E1000_RXD_ERR_SEQ | \ - E1000_RXD_ERR_CXE | \ - E1000_RXD_ERR_RXE) - -/* Same mask, but for extended and packet split descriptors */ -#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \ - E1000_RXDEXT_STATERR_CE | \ - E1000_RXDEXT_STATERR_SE | \ - E1000_RXDEXT_STATERR_SEQ | \ - E1000_RXDEXT_STATERR_CXE | \ - E1000_RXDEXT_STATERR_RXE) - -/* Transmit Descriptor */ -struct e1000_tx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 cso; /* Checksum offset */ - u8 cmd; /* Descriptor control */ - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 css; /* Checksum start */ - __le16 special; - } fields; - } upper; -}; - -/* Transmit Descriptor bit definitions */ -#define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */ -#define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */ -#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ -#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ -#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ -#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ -#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */ -#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */ -#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */ -#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */ -#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ -#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */ -#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */ -#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */ -#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */ -#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */ -#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */ -#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ -#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ -#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ - -/* Offload Context Descriptor */ -struct e1000_context_desc { - union { - __le32 ip_config; - struct { - u8 ipcss; /* IP checksum start */ - u8 ipcso; /* IP checksum offset */ - __le16 ipcse; /* IP checksum end */ - } ip_fields; - } lower_setup; - union { - __le32 tcp_config; - struct { - u8 tucss; /* TCP checksum start */ - u8 tucso; /* TCP checksum offset */ - __le16 tucse; /* TCP checksum end */ - } tcp_fields; - } upper_setup; - __le32 cmd_and_length; /* */ - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 hdr_len; /* Header length */ - __le16 mss; /* Maximum segment size */ - } fields; - } tcp_seg_setup; -}; - -/* Offload data descriptor */ -struct e1000_data_desc { - __le64 buffer_addr; /* Address of the descriptor's buffer address */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 typ_len_ext; /* */ - u8 cmd; /* */ - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 popts; /* Packet Options */ - __le16 special; /* */ - } fields; - } upper; -}; - -/* Filters */ -#define E1000_NUM_UNICAST 16 /* Unicast filter entries */ -#define E1000_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */ -#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ - -/* Receive Address Register */ -struct e1000_rar { - volatile __le32 low; /* receive address low */ - volatile __le32 high; /* receive address high */ -}; - -/* Number of entries in the Multicast Table Array (MTA). */ -#define E1000_NUM_MTA_REGISTERS 128 - -/* IPv4 Address Table Entry */ -struct e1000_ipv4_at_entry { - volatile u32 ipv4_addr; /* IP Address (RW) */ - volatile u32 reserved; -}; - -/* Four wakeup IP addresses are supported */ -#define E1000_WAKEUP_IP_ADDRESS_COUNT_MAX 4 -#define E1000_IP4AT_SIZE E1000_WAKEUP_IP_ADDRESS_COUNT_MAX -#define E1000_IP6AT_SIZE 1 - -/* IPv6 Address Table Entry */ -struct e1000_ipv6_at_entry { - volatile u8 ipv6_addr[16]; -}; - -/* Flexible Filter Length Table Entry */ -struct e1000_fflt_entry { - volatile u32 length; /* Flexible Filter Length (RW) */ - volatile u32 reserved; -}; - -/* Flexible Filter Mask Table Entry */ -struct e1000_ffmt_entry { - volatile u32 mask; /* Flexible Filter Mask (RW) */ - volatile u32 reserved; -}; - -/* Flexible Filter Value Table Entry */ -struct e1000_ffvt_entry { - volatile u32 value; /* Flexible Filter Value (RW) */ - volatile u32 reserved; -}; - -/* Four Flexible Filters are supported */ -#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4 - -/* Each Flexible Filter is at most 128 (0x80) bytes in length */ -#define E1000_FLEXIBLE_FILTER_SIZE_MAX 128 - -#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX -#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX -#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX - -#define E1000_DISABLE_SERDES_LOOPBACK 0x0400 - -/* Register Set. (82543, 82544) - * - * Registers are defined to be 32 bits and should be accessed as 32 bit values. - * These registers are physically located on the NIC, but are mapped into the - * host memory address space. - * - * RW - register is both readable and writable - * RO - register is read only - * WO - register is write only - * R/clr - register is read only and is cleared when read - * A - register array - */ -#define E1000_CTRL 0x00000 /* Device Control - RW */ -#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */ -#define E1000_STATUS 0x00008 /* Device Status - RO */ -#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ -#define E1000_EERD 0x00014 /* EEPROM Read - RW */ -#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ -#define E1000_FLA 0x0001C /* Flash Access - RW */ -#define E1000_MDIC 0x00020 /* MDI Control - RW */ - -#define INTEL_CE_GBE_MDIO_RCOMP_BASE (hw->ce4100_gbe_mdio_base_virt) -#define E1000_MDIO_STS (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0) -#define E1000_MDIO_CMD (INTEL_CE_GBE_MDIO_RCOMP_BASE + 4) -#define E1000_MDIO_DRV (INTEL_CE_GBE_MDIO_RCOMP_BASE + 8) -#define E1000_MDC_CMD (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0xC) -#define E1000_RCOMP_CTL (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0x20) -#define E1000_RCOMP_STS (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0x24) - -#define E1000_SCTL 0x00024 /* SerDes Control - RW */ -#define E1000_FEXTNVM 0x00028 /* Future Extended NVM register */ -#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ -#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ -#define E1000_FCT 0x00030 /* Flow Control Type - RW */ -#define E1000_VET 0x00038 /* VLAN Ether Type - RW */ -#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ -#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ -#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ -#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ -#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ -#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ - -/* Auxiliary Control Register. This register is CE4100 specific, - * RMII/RGMII function is switched by this register - RW - * Following are bits definitions of the Auxiliary Control Register - */ -#define E1000_CTL_AUX 0x000E0 -#define E1000_CTL_AUX_END_SEL_SHIFT 10 -#define E1000_CTL_AUX_ENDIANESS_SHIFT 8 -#define E1000_CTL_AUX_RGMII_RMII_SHIFT 0 - -/* descriptor and packet transfer use CTL_AUX.ENDIANESS */ -#define E1000_CTL_AUX_DES_PKT (0x0 << E1000_CTL_AUX_END_SEL_SHIFT) -/* descriptor use CTL_AUX.ENDIANESS, packet use default */ -#define E1000_CTL_AUX_DES (0x1 << E1000_CTL_AUX_END_SEL_SHIFT) -/* descriptor use default, packet use CTL_AUX.ENDIANESS */ -#define E1000_CTL_AUX_PKT (0x2 << E1000_CTL_AUX_END_SEL_SHIFT) -/* all use CTL_AUX.ENDIANESS */ -#define E1000_CTL_AUX_ALL (0x3 << E1000_CTL_AUX_END_SEL_SHIFT) - -#define E1000_CTL_AUX_RGMII (0x0 << E1000_CTL_AUX_RGMII_RMII_SHIFT) -#define E1000_CTL_AUX_RMII (0x1 << E1000_CTL_AUX_RGMII_RMII_SHIFT) - -/* LW little endian, Byte big endian */ -#define E1000_CTL_AUX_LWLE_BBE (0x0 << E1000_CTL_AUX_ENDIANESS_SHIFT) -#define E1000_CTL_AUX_LWLE_BLE (0x1 << E1000_CTL_AUX_ENDIANESS_SHIFT) -#define E1000_CTL_AUX_LWBE_BBE (0x2 << E1000_CTL_AUX_ENDIANESS_SHIFT) -#define E1000_CTL_AUX_LWBE_BLE (0x3 << E1000_CTL_AUX_ENDIANESS_SHIFT) - -#define E1000_RCTL 0x00100 /* RX Control - RW */ -#define E1000_RDTR1 0x02820 /* RX Delay Timer (1) - RW */ -#define E1000_RDBAL1 0x02900 /* RX Descriptor Base Address Low (1) - RW */ -#define E1000_RDBAH1 0x02904 /* RX Descriptor Base Address High (1) - RW */ -#define E1000_RDLEN1 0x02908 /* RX Descriptor Length (1) - RW */ -#define E1000_RDH1 0x02910 /* RX Descriptor Head (1) - RW */ -#define E1000_RDT1 0x02918 /* RX Descriptor Tail (1) - RW */ -#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ -#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */ -#define E1000_RXCW 0x00180 /* RX Configuration Word - RO */ -#define E1000_TCTL 0x00400 /* TX Control - RW */ -#define E1000_TCTL_EXT 0x00404 /* Extended TX Control - RW */ -#define E1000_TIPG 0x00410 /* TX Inter-packet gap -RW */ -#define E1000_TBT 0x00448 /* TX Burst Timer - RW */ -#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ -#define E1000_LEDCTL 0x00E00 /* LED Control - RW */ -#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */ -#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */ -#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */ -#define FEXTNVM_SW_CONFIG 0x0001 -#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ -#define E1000_PBS 0x01008 /* Packet Buffer Size */ -#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ -#define E1000_FLASH_UPDATES 1000 -#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */ -#define E1000_FLASHT 0x01028 /* FLASH Timer Register */ -#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */ -#define E1000_FLSWCTL 0x01030 /* FLASH control register */ -#define E1000_FLSWDATA 0x01034 /* FLASH data register */ -#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */ -#define E1000_FLOP 0x0103C /* FLASH Opcode Register */ -#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ -#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ -#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ -#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */ -#define E1000_RDFH 0x02410 /* RX Data FIFO Head - RW */ -#define E1000_RDFT 0x02418 /* RX Data FIFO Tail - RW */ -#define E1000_RDFHS 0x02420 /* RX Data FIFO Head Saved - RW */ -#define E1000_RDFTS 0x02428 /* RX Data FIFO Tail Saved - RW */ -#define E1000_RDFPC 0x02430 /* RX Data FIFO Packet Count - RW */ -#define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */ -#define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */ -#define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */ -#define E1000_RDH 0x02810 /* RX Descriptor Head - RW */ -#define E1000_RDT 0x02818 /* RX Descriptor Tail - RW */ -#define E1000_RDTR 0x02820 /* RX Delay Timer - RW */ -#define E1000_RDBAL0 E1000_RDBAL /* RX Desc Base Address Low (0) - RW */ -#define E1000_RDBAH0 E1000_RDBAH /* RX Desc Base Address High (0) - RW */ -#define E1000_RDLEN0 E1000_RDLEN /* RX Desc Length (0) - RW */ -#define E1000_RDH0 E1000_RDH /* RX Desc Head (0) - RW */ -#define E1000_RDT0 E1000_RDT /* RX Desc Tail (0) - RW */ -#define E1000_RDTR0 E1000_RDTR /* RX Delay Timer (0) - RW */ -#define E1000_RXDCTL 0x02828 /* RX Descriptor Control queue 0 - RW */ -#define E1000_RXDCTL1 0x02928 /* RX Descriptor Control queue 1 - RW */ -#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */ -#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */ -#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */ -#define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */ -#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */ -#define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */ -#define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */ -#define E1000_TDFHS 0x03420 /* TX Data FIFO Head Saved - RW */ -#define E1000_TDFTS 0x03428 /* TX Data FIFO Tail Saved - RW */ -#define E1000_TDFPC 0x03430 /* TX Data FIFO Packet Count - RW */ -#define E1000_TDBAL 0x03800 /* TX Descriptor Base Address Low - RW */ -#define E1000_TDBAH 0x03804 /* TX Descriptor Base Address High - RW */ -#define E1000_TDLEN 0x03808 /* TX Descriptor Length - RW */ -#define E1000_TDH 0x03810 /* TX Descriptor Head - RW */ -#define E1000_TDT 0x03818 /* TX Descripotr Tail - RW */ -#define E1000_TIDV 0x03820 /* TX Interrupt Delay Value - RW */ -#define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */ -#define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */ -#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */ -#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */ -#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */ -#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */ -#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */ -#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */ -#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */ -#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */ -#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */ -#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ -#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ -#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ -#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */ -#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */ -#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */ -#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */ -#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */ -#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */ -#define E1000_COLC 0x04028 /* Collision Count - R/clr */ -#define E1000_DC 0x04030 /* Defer Count - R/clr */ -#define E1000_TNCRS 0x04034 /* TX-No CRS - R/clr */ -#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ -#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ -#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ -#define E1000_XONRXC 0x04048 /* XON RX Count - R/clr */ -#define E1000_XONTXC 0x0404C /* XON TX Count - R/clr */ -#define E1000_XOFFRXC 0x04050 /* XOFF RX Count - R/clr */ -#define E1000_XOFFTXC 0x04054 /* XOFF TX Count - R/clr */ -#define E1000_FCRUC 0x04058 /* Flow Control RX Unsupported Count- R/clr */ -#define E1000_PRC64 0x0405C /* Packets RX (64 bytes) - R/clr */ -#define E1000_PRC127 0x04060 /* Packets RX (65-127 bytes) - R/clr */ -#define E1000_PRC255 0x04064 /* Packets RX (128-255 bytes) - R/clr */ -#define E1000_PRC511 0x04068 /* Packets RX (255-511 bytes) - R/clr */ -#define E1000_PRC1023 0x0406C /* Packets RX (512-1023 bytes) - R/clr */ -#define E1000_PRC1522 0x04070 /* Packets RX (1024-1522 bytes) - R/clr */ -#define E1000_GPRC 0x04074 /* Good Packets RX Count - R/clr */ -#define E1000_BPRC 0x04078 /* Broadcast Packets RX Count - R/clr */ -#define E1000_MPRC 0x0407C /* Multicast Packets RX Count - R/clr */ -#define E1000_GPTC 0x04080 /* Good Packets TX Count - R/clr */ -#define E1000_GORCL 0x04088 /* Good Octets RX Count Low - R/clr */ -#define E1000_GORCH 0x0408C /* Good Octets RX Count High - R/clr */ -#define E1000_GOTCL 0x04090 /* Good Octets TX Count Low - R/clr */ -#define E1000_GOTCH 0x04094 /* Good Octets TX Count High - R/clr */ -#define E1000_RNBC 0x040A0 /* RX No Buffers Count - R/clr */ -#define E1000_RUC 0x040A4 /* RX Undersize Count - R/clr */ -#define E1000_RFC 0x040A8 /* RX Fragment Count - R/clr */ -#define E1000_ROC 0x040AC /* RX Oversize Count - R/clr */ -#define E1000_RJC 0x040B0 /* RX Jabber Count - R/clr */ -#define E1000_MGTPRC 0x040B4 /* Management Packets RX Count - R/clr */ -#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ -#define E1000_MGTPTC 0x040BC /* Management Packets TX Count - R/clr */ -#define E1000_TORL 0x040C0 /* Total Octets RX Low - R/clr */ -#define E1000_TORH 0x040C4 /* Total Octets RX High - R/clr */ -#define E1000_TOTL 0x040C8 /* Total Octets TX Low - R/clr */ -#define E1000_TOTH 0x040CC /* Total Octets TX High - R/clr */ -#define E1000_TPR 0x040D0 /* Total Packets RX - R/clr */ -#define E1000_TPT 0x040D4 /* Total Packets TX - R/clr */ -#define E1000_PTC64 0x040D8 /* Packets TX (64 bytes) - R/clr */ -#define E1000_PTC127 0x040DC /* Packets TX (65-127 bytes) - R/clr */ -#define E1000_PTC255 0x040E0 /* Packets TX (128-255 bytes) - R/clr */ -#define E1000_PTC511 0x040E4 /* Packets TX (256-511 bytes) - R/clr */ -#define E1000_PTC1023 0x040E8 /* Packets TX (512-1023 bytes) - R/clr */ -#define E1000_PTC1522 0x040EC /* Packets TX (1024-1522 Bytes) - R/clr */ -#define E1000_MPTC 0x040F0 /* Multicast Packets TX Count - R/clr */ -#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */ -#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */ -#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */ -#define E1000_IAC 0x04100 /* Interrupt Assertion Count */ -#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Packet Timer Expire Count */ -#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Absolute Timer Expire Count */ -#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Packet Timer Expire Count */ -#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Absolute Timer Expire Count */ -#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */ -#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Minimum Threshold Count */ -#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */ -#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */ -#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */ -#define E1000_RFCTL 0x05008 /* Receive Filter Control */ -#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ -#define E1000_RA 0x05400 /* Receive Address - RW Array */ -#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ -#define E1000_WUC 0x05800 /* Wakeup Control - RW */ -#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ -#define E1000_WUS 0x05810 /* Wakeup Status - RO */ -#define E1000_MANC 0x05820 /* Management Control - RW */ -#define E1000_IPAV 0x05838 /* IP Address Valid - RW */ -#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */ -#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */ -#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */ -#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */ -#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ -#define E1000_HOST_IF 0x08800 /* Host Interface */ -#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ -#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ - -#define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */ -#define E1000_MDPHYA 0x0003C /* PHY address - RW */ -#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */ -#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */ - -#define E1000_GCR 0x05B00 /* PCI-Ex Control */ -#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */ -#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */ -#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */ -#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */ -#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ -#define E1000_SWSM 0x05B50 /* SW Semaphore */ -#define E1000_FWSM 0x05B54 /* FW Semaphore */ -#define E1000_FFLT_DBG 0x05F04 /* Debug Register */ -#define E1000_HICR 0x08F00 /* Host Interface Control */ - -/* RSS registers */ -#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */ -#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */ -#define E1000_RETA 0x05C00 /* Redirection Table - RW Array */ -#define E1000_RSSRK 0x05C80 /* RSS Random Key - RW Array */ -#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */ -#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */ -/* Register Set (82542) - * - * Some of the 82542 registers are located at different offsets than they are - * in more current versions of the 8254x. Despite the difference in location, - * the registers function in the same manner. - */ -#define E1000_82542_CTL_AUX E1000_CTL_AUX -#define E1000_82542_CTRL E1000_CTRL -#define E1000_82542_CTRL_DUP E1000_CTRL_DUP -#define E1000_82542_STATUS E1000_STATUS -#define E1000_82542_EECD E1000_EECD -#define E1000_82542_EERD E1000_EERD -#define E1000_82542_CTRL_EXT E1000_CTRL_EXT -#define E1000_82542_FLA E1000_FLA -#define E1000_82542_MDIC E1000_MDIC -#define E1000_82542_SCTL E1000_SCTL -#define E1000_82542_FEXTNVM E1000_FEXTNVM -#define E1000_82542_FCAL E1000_FCAL -#define E1000_82542_FCAH E1000_FCAH -#define E1000_82542_FCT E1000_FCT -#define E1000_82542_VET E1000_VET -#define E1000_82542_RA 0x00040 -#define E1000_82542_ICR E1000_ICR -#define E1000_82542_ITR E1000_ITR -#define E1000_82542_ICS E1000_ICS -#define E1000_82542_IMS E1000_IMS -#define E1000_82542_IMC E1000_IMC -#define E1000_82542_RCTL E1000_RCTL -#define E1000_82542_RDTR 0x00108 -#define E1000_82542_RDFH E1000_RDFH -#define E1000_82542_RDFT E1000_RDFT -#define E1000_82542_RDFHS E1000_RDFHS -#define E1000_82542_RDFTS E1000_RDFTS -#define E1000_82542_RDFPC E1000_RDFPC -#define E1000_82542_RDBAL 0x00110 -#define E1000_82542_RDBAH 0x00114 -#define E1000_82542_RDLEN 0x00118 -#define E1000_82542_RDH 0x00120 -#define E1000_82542_RDT 0x00128 -#define E1000_82542_RDTR0 E1000_82542_RDTR -#define E1000_82542_RDBAL0 E1000_82542_RDBAL -#define E1000_82542_RDBAH0 E1000_82542_RDBAH -#define E1000_82542_RDLEN0 E1000_82542_RDLEN -#define E1000_82542_RDH0 E1000_82542_RDH -#define E1000_82542_RDT0 E1000_82542_RDT -#define E1000_82542_SRRCTL(_n) (0x280C + ((_n) << 8)) /* Split and Replication - * RX Control - RW */ -#define E1000_82542_DCA_RXCTRL(_n) (0x02814 + ((_n) << 8)) -#define E1000_82542_RDBAH3 0x02B04 /* RX Desc Base High Queue 3 - RW */ -#define E1000_82542_RDBAL3 0x02B00 /* RX Desc Low Queue 3 - RW */ -#define E1000_82542_RDLEN3 0x02B08 /* RX Desc Length Queue 3 - RW */ -#define E1000_82542_RDH3 0x02B10 /* RX Desc Head Queue 3 - RW */ -#define E1000_82542_RDT3 0x02B18 /* RX Desc Tail Queue 3 - RW */ -#define E1000_82542_RDBAL2 0x02A00 /* RX Desc Base Low Queue 2 - RW */ -#define E1000_82542_RDBAH2 0x02A04 /* RX Desc Base High Queue 2 - RW */ -#define E1000_82542_RDLEN2 0x02A08 /* RX Desc Length Queue 2 - RW */ -#define E1000_82542_RDH2 0x02A10 /* RX Desc Head Queue 2 - RW */ -#define E1000_82542_RDT2 0x02A18 /* RX Desc Tail Queue 2 - RW */ -#define E1000_82542_RDTR1 0x00130 -#define E1000_82542_RDBAL1 0x00138 -#define E1000_82542_RDBAH1 0x0013C -#define E1000_82542_RDLEN1 0x00140 -#define E1000_82542_RDH1 0x00148 -#define E1000_82542_RDT1 0x00150 -#define E1000_82542_FCRTH 0x00160 -#define E1000_82542_FCRTL 0x00168 -#define E1000_82542_FCTTV E1000_FCTTV -#define E1000_82542_TXCW E1000_TXCW -#define E1000_82542_RXCW E1000_RXCW -#define E1000_82542_MTA 0x00200 -#define E1000_82542_TCTL E1000_TCTL -#define E1000_82542_TCTL_EXT E1000_TCTL_EXT -#define E1000_82542_TIPG E1000_TIPG -#define E1000_82542_TDBAL 0x00420 -#define E1000_82542_TDBAH 0x00424 -#define E1000_82542_TDLEN 0x00428 -#define E1000_82542_TDH 0x00430 -#define E1000_82542_TDT 0x00438 -#define E1000_82542_TIDV 0x00440 -#define E1000_82542_TBT E1000_TBT -#define E1000_82542_AIT E1000_AIT -#define E1000_82542_VFTA 0x00600 -#define E1000_82542_LEDCTL E1000_LEDCTL -#define E1000_82542_PBA E1000_PBA -#define E1000_82542_PBS E1000_PBS -#define E1000_82542_EEMNGCTL E1000_EEMNGCTL -#define E1000_82542_EEARBC E1000_EEARBC -#define E1000_82542_FLASHT E1000_FLASHT -#define E1000_82542_EEWR E1000_EEWR -#define E1000_82542_FLSWCTL E1000_FLSWCTL -#define E1000_82542_FLSWDATA E1000_FLSWDATA -#define E1000_82542_FLSWCNT E1000_FLSWCNT -#define E1000_82542_FLOP E1000_FLOP -#define E1000_82542_EXTCNF_CTRL E1000_EXTCNF_CTRL -#define E1000_82542_EXTCNF_SIZE E1000_EXTCNF_SIZE -#define E1000_82542_PHY_CTRL E1000_PHY_CTRL -#define E1000_82542_ERT E1000_ERT -#define E1000_82542_RXDCTL E1000_RXDCTL -#define E1000_82542_RXDCTL1 E1000_RXDCTL1 -#define E1000_82542_RADV E1000_RADV -#define E1000_82542_RSRPD E1000_RSRPD -#define E1000_82542_TXDMAC E1000_TXDMAC -#define E1000_82542_KABGTXD E1000_KABGTXD -#define E1000_82542_TDFHS E1000_TDFHS -#define E1000_82542_TDFTS E1000_TDFTS -#define E1000_82542_TDFPC E1000_TDFPC -#define E1000_82542_TXDCTL E1000_TXDCTL -#define E1000_82542_TADV E1000_TADV -#define E1000_82542_TSPMT E1000_TSPMT -#define E1000_82542_CRCERRS E1000_CRCERRS -#define E1000_82542_ALGNERRC E1000_ALGNERRC -#define E1000_82542_SYMERRS E1000_SYMERRS -#define E1000_82542_RXERRC E1000_RXERRC -#define E1000_82542_MPC E1000_MPC -#define E1000_82542_SCC E1000_SCC -#define E1000_82542_ECOL E1000_ECOL -#define E1000_82542_MCC E1000_MCC -#define E1000_82542_LATECOL E1000_LATECOL -#define E1000_82542_COLC E1000_COLC -#define E1000_82542_DC E1000_DC -#define E1000_82542_TNCRS E1000_TNCRS -#define E1000_82542_SEC E1000_SEC -#define E1000_82542_CEXTERR E1000_CEXTERR -#define E1000_82542_RLEC E1000_RLEC -#define E1000_82542_XONRXC E1000_XONRXC -#define E1000_82542_XONTXC E1000_XONTXC -#define E1000_82542_XOFFRXC E1000_XOFFRXC -#define E1000_82542_XOFFTXC E1000_XOFFTXC -#define E1000_82542_FCRUC E1000_FCRUC -#define E1000_82542_PRC64 E1000_PRC64 -#define E1000_82542_PRC127 E1000_PRC127 -#define E1000_82542_PRC255 E1000_PRC255 -#define E1000_82542_PRC511 E1000_PRC511 -#define E1000_82542_PRC1023 E1000_PRC1023 -#define E1000_82542_PRC1522 E1000_PRC1522 -#define E1000_82542_GPRC E1000_GPRC -#define E1000_82542_BPRC E1000_BPRC -#define E1000_82542_MPRC E1000_MPRC -#define E1000_82542_GPTC E1000_GPTC -#define E1000_82542_GORCL E1000_GORCL -#define E1000_82542_GORCH E1000_GORCH -#define E1000_82542_GOTCL E1000_GOTCL -#define E1000_82542_GOTCH E1000_GOTCH -#define E1000_82542_RNBC E1000_RNBC -#define E1000_82542_RUC E1000_RUC -#define E1000_82542_RFC E1000_RFC -#define E1000_82542_ROC E1000_ROC -#define E1000_82542_RJC E1000_RJC -#define E1000_82542_MGTPRC E1000_MGTPRC -#define E1000_82542_MGTPDC E1000_MGTPDC -#define E1000_82542_MGTPTC E1000_MGTPTC -#define E1000_82542_TORL E1000_TORL -#define E1000_82542_TORH E1000_TORH -#define E1000_82542_TOTL E1000_TOTL -#define E1000_82542_TOTH E1000_TOTH -#define E1000_82542_TPR E1000_TPR -#define E1000_82542_TPT E1000_TPT -#define E1000_82542_PTC64 E1000_PTC64 -#define E1000_82542_PTC127 E1000_PTC127 -#define E1000_82542_PTC255 E1000_PTC255 -#define E1000_82542_PTC511 E1000_PTC511 -#define E1000_82542_PTC1023 E1000_PTC1023 -#define E1000_82542_PTC1522 E1000_PTC1522 -#define E1000_82542_MPTC E1000_MPTC -#define E1000_82542_BPTC E1000_BPTC -#define E1000_82542_TSCTC E1000_TSCTC -#define E1000_82542_TSCTFC E1000_TSCTFC -#define E1000_82542_RXCSUM E1000_RXCSUM -#define E1000_82542_WUC E1000_WUC -#define E1000_82542_WUFC E1000_WUFC -#define E1000_82542_WUS E1000_WUS -#define E1000_82542_MANC E1000_MANC -#define E1000_82542_IPAV E1000_IPAV -#define E1000_82542_IP4AT E1000_IP4AT -#define E1000_82542_IP6AT E1000_IP6AT -#define E1000_82542_WUPL E1000_WUPL -#define E1000_82542_WUPM E1000_WUPM -#define E1000_82542_FFLT E1000_FFLT -#define E1000_82542_TDFH 0x08010 -#define E1000_82542_TDFT 0x08018 -#define E1000_82542_FFMT E1000_FFMT -#define E1000_82542_FFVT E1000_FFVT -#define E1000_82542_HOST_IF E1000_HOST_IF -#define E1000_82542_IAM E1000_IAM -#define E1000_82542_EEMNGCTL E1000_EEMNGCTL -#define E1000_82542_PSRCTL E1000_PSRCTL -#define E1000_82542_RAID E1000_RAID -#define E1000_82542_TARC0 E1000_TARC0 -#define E1000_82542_TDBAL1 E1000_TDBAL1 -#define E1000_82542_TDBAH1 E1000_TDBAH1 -#define E1000_82542_TDLEN1 E1000_TDLEN1 -#define E1000_82542_TDH1 E1000_TDH1 -#define E1000_82542_TDT1 E1000_TDT1 -#define E1000_82542_TXDCTL1 E1000_TXDCTL1 -#define E1000_82542_TARC1 E1000_TARC1 -#define E1000_82542_RFCTL E1000_RFCTL -#define E1000_82542_GCR E1000_GCR -#define E1000_82542_GSCL_1 E1000_GSCL_1 -#define E1000_82542_GSCL_2 E1000_GSCL_2 -#define E1000_82542_GSCL_3 E1000_GSCL_3 -#define E1000_82542_GSCL_4 E1000_GSCL_4 -#define E1000_82542_FACTPS E1000_FACTPS -#define E1000_82542_SWSM E1000_SWSM -#define E1000_82542_FWSM E1000_FWSM -#define E1000_82542_FFLT_DBG E1000_FFLT_DBG -#define E1000_82542_IAC E1000_IAC -#define E1000_82542_ICRXPTC E1000_ICRXPTC -#define E1000_82542_ICRXATC E1000_ICRXATC -#define E1000_82542_ICTXPTC E1000_ICTXPTC -#define E1000_82542_ICTXATC E1000_ICTXATC -#define E1000_82542_ICTXQEC E1000_ICTXQEC -#define E1000_82542_ICTXQMTC E1000_ICTXQMTC -#define E1000_82542_ICRXDMTC E1000_ICRXDMTC -#define E1000_82542_ICRXOC E1000_ICRXOC -#define E1000_82542_HICR E1000_HICR - -#define E1000_82542_CPUVEC E1000_CPUVEC -#define E1000_82542_MRQC E1000_MRQC -#define E1000_82542_RETA E1000_RETA -#define E1000_82542_RSSRK E1000_RSSRK -#define E1000_82542_RSSIM E1000_RSSIM -#define E1000_82542_RSSIR E1000_RSSIR -#define E1000_82542_KUMCTRLSTA E1000_KUMCTRLSTA -#define E1000_82542_SW_FW_SYNC E1000_SW_FW_SYNC - -/* Statistics counters collected by the MAC */ -struct e1000_hw_stats { - u64 crcerrs; - u64 algnerrc; - u64 symerrs; - u64 rxerrc; - u64 txerrc; - u64 mpc; - u64 scc; - u64 ecol; - u64 mcc; - u64 latecol; - u64 colc; - u64 dc; - u64 tncrs; - u64 sec; - u64 cexterr; - u64 rlec; - u64 xonrxc; - u64 xontxc; - u64 xoffrxc; - u64 xofftxc; - u64 fcruc; - u64 prc64; - u64 prc127; - u64 prc255; - u64 prc511; - u64 prc1023; - u64 prc1522; - u64 gprc; - u64 bprc; - u64 mprc; - u64 gptc; - u64 gorcl; - u64 gorch; - u64 gotcl; - u64 gotch; - u64 rnbc; - u64 ruc; - u64 rfc; - u64 roc; - u64 rlerrc; - u64 rjc; - u64 mgprc; - u64 mgpdc; - u64 mgptc; - u64 torl; - u64 torh; - u64 totl; - u64 toth; - u64 tpr; - u64 tpt; - u64 ptc64; - u64 ptc127; - u64 ptc255; - u64 ptc511; - u64 ptc1023; - u64 ptc1522; - u64 mptc; - u64 bptc; - u64 tsctc; - u64 tsctfc; - u64 iac; - u64 icrxptc; - u64 icrxatc; - u64 ictxptc; - u64 ictxatc; - u64 ictxqec; - u64 ictxqmtc; - u64 icrxdmtc; - u64 icrxoc; -}; - -/* Structure containing variables used by the shared code (e1000_hw.c) */ -struct e1000_hw { - u8 __iomem *hw_addr; - u8 __iomem *flash_address; - void __iomem *ce4100_gbe_mdio_base_virt; - e1000_mac_type mac_type; - e1000_phy_type phy_type; - u32 phy_init_script; - e1000_media_type media_type; - void *back; - struct e1000_shadow_ram *eeprom_shadow_ram; - u32 flash_bank_size; - u32 flash_base_addr; - e1000_fc_type fc; - e1000_bus_speed bus_speed; - e1000_bus_width bus_width; - e1000_bus_type bus_type; - struct e1000_eeprom_info eeprom; - e1000_ms_type master_slave; - e1000_ms_type original_master_slave; - e1000_ffe_config ffe_config_state; - u32 asf_firmware_present; - u32 eeprom_semaphore_present; - unsigned long io_base; - u32 phy_id; - u32 phy_revision; - u32 phy_addr; - u32 original_fc; - u32 txcw; - u32 autoneg_failed; - u32 max_frame_size; - u32 min_frame_size; - u32 mc_filter_type; - u32 num_mc_addrs; - u32 collision_delta; - u32 tx_packet_delta; - u32 ledctl_default; - u32 ledctl_mode1; - u32 ledctl_mode2; - bool tx_pkt_filtering; - struct e1000_host_mng_dhcp_cookie mng_cookie; - u16 phy_spd_default; - u16 autoneg_advertised; - u16 pci_cmd_word; - u16 fc_high_water; - u16 fc_low_water; - u16 fc_pause_time; - u16 current_ifs_val; - u16 ifs_min_val; - u16 ifs_max_val; - u16 ifs_step_size; - u16 ifs_ratio; - u16 device_id; - u16 vendor_id; - u16 subsystem_id; - u16 subsystem_vendor_id; - u8 revision_id; - u8 autoneg; - u8 mdix; - u8 forced_speed_duplex; - u8 wait_autoneg_complete; - u8 dma_fairness; - u8 mac_addr[NODE_ADDRESS_SIZE]; - u8 perm_mac_addr[NODE_ADDRESS_SIZE]; - bool disable_polarity_correction; - bool speed_downgraded; - e1000_smart_speed smart_speed; - e1000_dsp_config dsp_config_state; - bool get_link_status; - bool serdes_has_link; - bool tbi_compatibility_en; - bool tbi_compatibility_on; - bool laa_is_present; - bool phy_reset_disable; - bool initialize_hw_bits_disable; - bool fc_send_xon; - bool fc_strict_ieee; - bool report_tx_early; - bool adaptive_ifs; - bool ifs_params_forced; - bool in_ifs_mode; - bool mng_reg_access_disabled; - bool leave_av_bit_off; - bool bad_tx_carr_stats_fd; - bool has_smbus; -}; - -#define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */ -#define E1000_EEPROM_LED_LOGIC 0x0020 /* Led Logic Word */ -#define E1000_EEPROM_RW_REG_DATA 16 /* Offset to data in EEPROM read/write registers */ -#define E1000_EEPROM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ -#define E1000_EEPROM_RW_REG_START 1 /* First bit for telling part to start operation */ -#define E1000_EEPROM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ -#define E1000_EEPROM_POLL_WRITE 1 /* Flag for polling for write complete */ -#define E1000_EEPROM_POLL_READ 0 /* Flag for polling for read complete */ -/* Register Bit Masks */ -/* Device Control */ -#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ -#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */ -#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */ -#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */ -#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ -#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */ -#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */ -#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */ -#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ -#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */ -#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */ -#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */ -#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */ -#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */ -#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */ -#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ -#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ -#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */ -#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */ -#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */ -#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */ -#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ -#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ -#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ -#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */ -#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ -#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */ -#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */ -#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */ -#define E1000_CTRL_RST 0x04000000 /* Global reset */ -#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ -#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ -#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */ -#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ -#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ -#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to manageability engine */ - -/* Device Status */ -#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ -#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ -#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ -#define E1000_STATUS_FUNC_SHIFT 2 -#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */ -#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ -#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ -#define E1000_STATUS_TBIMODE 0x00000020 /* TBI mode */ -#define E1000_STATUS_SPEED_MASK 0x000000C0 -#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ -#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ -#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ -#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion - by EEPROM/Flash */ -#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */ -#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. Clear on write '0'. */ -#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ -#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */ -#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ -#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ -#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */ -#define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */ -#define E1000_STATUS_BMC_SKU_0 0x00100000 /* BMC USB redirect disabled */ -#define E1000_STATUS_BMC_SKU_1 0x00200000 /* BMC SRAM disabled */ -#define E1000_STATUS_BMC_SKU_2 0x00400000 /* BMC SDRAM disabled */ -#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */ -#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution disabled */ -#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */ -#define E1000_STATUS_FUSE_8 0x04000000 -#define E1000_STATUS_FUSE_9 0x08000000 -#define E1000_STATUS_SERDES0_DIS 0x10000000 /* SERDES disabled on port 0 */ -#define E1000_STATUS_SERDES1_DIS 0x20000000 /* SERDES disabled on port 1 */ - -/* Constants used to interpret the masked PCI-X bus speed. */ -#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */ -#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */ -#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */ - -/* EEPROM/Flash Control */ -#define E1000_EECD_SK 0x00000001 /* EEPROM Clock */ -#define E1000_EECD_CS 0x00000002 /* EEPROM Chip Select */ -#define E1000_EECD_DI 0x00000004 /* EEPROM Data In */ -#define E1000_EECD_DO 0x00000008 /* EEPROM Data Out */ -#define E1000_EECD_FWE_MASK 0x00000030 -#define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */ -#define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */ -#define E1000_EECD_FWE_SHIFT 4 -#define E1000_EECD_REQ 0x00000040 /* EEPROM Access Request */ -#define E1000_EECD_GNT 0x00000080 /* EEPROM Access Grant */ -#define E1000_EECD_PRES 0x00000100 /* EEPROM Present */ -#define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */ -#define E1000_EECD_ADDR_BITS 0x00000400 /* EEPROM Addressing bits based on type - * (0-small, 1-large) */ -#define E1000_EECD_TYPE 0x00002000 /* EEPROM Type (1-SPI, 0-Microwire) */ -#ifndef E1000_EEPROM_GRANT_ATTEMPTS -#define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */ -#endif -#define E1000_EECD_AUTO_RD 0x00000200 /* EEPROM Auto Read done */ -#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* EEprom Size */ -#define E1000_EECD_SIZE_EX_SHIFT 11 -#define E1000_EECD_NVADDS 0x00018000 /* NVM Address Size */ -#define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */ -#define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */ -#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */ -#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */ -#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */ -#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */ -#define E1000_EECD_SECVAL_SHIFT 22 -#define E1000_STM_OPCODE 0xDB00 -#define E1000_HICR_FW_RESET 0xC0 - -#define E1000_SHADOW_RAM_WORDS 2048 -#define E1000_ICH_NVM_SIG_WORD 0x13 -#define E1000_ICH_NVM_SIG_MASK 0xC0 - -/* EEPROM Read */ -#define E1000_EERD_START 0x00000001 /* Start Read */ -#define E1000_EERD_DONE 0x00000010 /* Read Done */ -#define E1000_EERD_ADDR_SHIFT 8 -#define E1000_EERD_ADDR_MASK 0x0000FF00 /* Read Address */ -#define E1000_EERD_DATA_SHIFT 16 -#define E1000_EERD_DATA_MASK 0xFFFF0000 /* Read Data */ - -/* SPI EEPROM Status Register */ -#define EEPROM_STATUS_RDY_SPI 0x01 -#define EEPROM_STATUS_WEN_SPI 0x02 -#define EEPROM_STATUS_BP0_SPI 0x04 -#define EEPROM_STATUS_BP1_SPI 0x08 -#define EEPROM_STATUS_WPEN_SPI 0x80 - -/* Extended Device Control */ -#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */ -#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */ -#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN -#define E1000_CTRL_EXT_GPI2_EN 0x00000004 /* Maps SDP6 to GPI2 */ -#define E1000_CTRL_EXT_GPI3_EN 0x00000008 /* Maps SDP7 to GPI3 */ -#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */ -#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */ -#define E1000_CTRL_EXT_PHY_INT E1000_CTRL_EXT_SDP5_DATA -#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Defineable Pin 6 */ -#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */ -#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */ -#define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */ -#define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */ -#define E1000_CTRL_EXT_SDP7_DIR 0x00000800 /* Direction of SDP7 0=in 1=out */ -#define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */ -#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ -#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ -#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ -#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ -#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 -#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 -#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000 -#define E1000_CTRL_EXT_LINK_MODE_KMRN 0x00000000 -#define E1000_CTRL_EXT_LINK_MODE_SERDES 0x00C00000 -#define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000 -#define E1000_CTRL_EXT_WR_WMARK_MASK 0x03000000 -#define E1000_CTRL_EXT_WR_WMARK_256 0x00000000 -#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 -#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000 -#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000 -#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ -#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ -#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ -#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error detection enabled */ -#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */ -#define E1000_CTRL_EXT_GHOST_PAREN 0x40000000 - -/* MDI Control */ -#define E1000_MDIC_DATA_MASK 0x0000FFFF -#define E1000_MDIC_REG_MASK 0x001F0000 -#define E1000_MDIC_REG_SHIFT 16 -#define E1000_MDIC_PHY_MASK 0x03E00000 -#define E1000_MDIC_PHY_SHIFT 21 -#define E1000_MDIC_OP_WRITE 0x04000000 -#define E1000_MDIC_OP_READ 0x08000000 -#define E1000_MDIC_READY 0x10000000 -#define E1000_MDIC_INT_EN 0x20000000 -#define E1000_MDIC_ERROR 0x40000000 - -#define INTEL_CE_GBE_MDIC_OP_WRITE 0x04000000 -#define INTEL_CE_GBE_MDIC_OP_READ 0x00000000 -#define INTEL_CE_GBE_MDIC_GO 0x80000000 -#define INTEL_CE_GBE_MDIC_READ_ERROR 0x80000000 - -#define E1000_KUMCTRLSTA_MASK 0x0000FFFF -#define E1000_KUMCTRLSTA_OFFSET 0x001F0000 -#define E1000_KUMCTRLSTA_OFFSET_SHIFT 16 -#define E1000_KUMCTRLSTA_REN 0x00200000 - -#define E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL 0x00000000 -#define E1000_KUMCTRLSTA_OFFSET_CTRL 0x00000001 -#define E1000_KUMCTRLSTA_OFFSET_INB_CTRL 0x00000002 -#define E1000_KUMCTRLSTA_OFFSET_DIAG 0x00000003 -#define E1000_KUMCTRLSTA_OFFSET_TIMEOUTS 0x00000004 -#define E1000_KUMCTRLSTA_OFFSET_INB_PARAM 0x00000009 -#define E1000_KUMCTRLSTA_OFFSET_HD_CTRL 0x00000010 -#define E1000_KUMCTRLSTA_OFFSET_M2P_SERDES 0x0000001E -#define E1000_KUMCTRLSTA_OFFSET_M2P_MODES 0x0000001F - -/* FIFO Control */ -#define E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS 0x00000008 -#define E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS 0x00000800 - -/* In-Band Control */ -#define E1000_KUMCTRLSTA_INB_CTRL_LINK_STATUS_TX_TIMEOUT_DEFAULT 0x00000500 -#define E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING 0x00000010 - -/* Half-Duplex Control */ -#define E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004 -#define E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT 0x00000000 - -#define E1000_KUMCTRLSTA_OFFSET_K0S_CTRL 0x0000001E - -#define E1000_KUMCTRLSTA_DIAG_FELPBK 0x2000 -#define E1000_KUMCTRLSTA_DIAG_NELPBK 0x1000 - -#define E1000_KUMCTRLSTA_K0S_100_EN 0x2000 -#define E1000_KUMCTRLSTA_K0S_GBE_EN 0x1000 -#define E1000_KUMCTRLSTA_K0S_ENTRY_LATENCY_MASK 0x0003 - -#define E1000_KABGTXD_BGSQLBIAS 0x00050000 - -#define E1000_PHY_CTRL_SPD_EN 0x00000001 -#define E1000_PHY_CTRL_D0A_LPLU 0x00000002 -#define E1000_PHY_CTRL_NOND0A_LPLU 0x00000004 -#define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008 -#define E1000_PHY_CTRL_GBE_DISABLE 0x00000040 -#define E1000_PHY_CTRL_B2B_EN 0x00000080 - -/* LED Control */ -#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F -#define E1000_LEDCTL_LED0_MODE_SHIFT 0 -#define E1000_LEDCTL_LED0_BLINK_RATE 0x0000020 -#define E1000_LEDCTL_LED0_IVRT 0x00000040 -#define E1000_LEDCTL_LED0_BLINK 0x00000080 -#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00 -#define E1000_LEDCTL_LED1_MODE_SHIFT 8 -#define E1000_LEDCTL_LED1_BLINK_RATE 0x0002000 -#define E1000_LEDCTL_LED1_IVRT 0x00004000 -#define E1000_LEDCTL_LED1_BLINK 0x00008000 -#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000 -#define E1000_LEDCTL_LED2_MODE_SHIFT 16 -#define E1000_LEDCTL_LED2_BLINK_RATE 0x00200000 -#define E1000_LEDCTL_LED2_IVRT 0x00400000 -#define E1000_LEDCTL_LED2_BLINK 0x00800000 -#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000 -#define E1000_LEDCTL_LED3_MODE_SHIFT 24 -#define E1000_LEDCTL_LED3_BLINK_RATE 0x20000000 -#define E1000_LEDCTL_LED3_IVRT 0x40000000 -#define E1000_LEDCTL_LED3_BLINK 0x80000000 - -#define E1000_LEDCTL_MODE_LINK_10_1000 0x0 -#define E1000_LEDCTL_MODE_LINK_100_1000 0x1 -#define E1000_LEDCTL_MODE_LINK_UP 0x2 -#define E1000_LEDCTL_MODE_ACTIVITY 0x3 -#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4 -#define E1000_LEDCTL_MODE_LINK_10 0x5 -#define E1000_LEDCTL_MODE_LINK_100 0x6 -#define E1000_LEDCTL_MODE_LINK_1000 0x7 -#define E1000_LEDCTL_MODE_PCIX_MODE 0x8 -#define E1000_LEDCTL_MODE_FULL_DUPLEX 0x9 -#define E1000_LEDCTL_MODE_COLLISION 0xA -#define E1000_LEDCTL_MODE_BUS_SPEED 0xB -#define E1000_LEDCTL_MODE_BUS_SIZE 0xC -#define E1000_LEDCTL_MODE_PAUSED 0xD -#define E1000_LEDCTL_MODE_LED_ON 0xE -#define E1000_LEDCTL_MODE_LED_OFF 0xF - -/* Receive Address */ -#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ - -/* Interrupt Cause Read */ -#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ -#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ -#define E1000_ICR_LSC 0x00000004 /* Link Status Change */ -#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */ -#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ -#define E1000_ICR_RXO 0x00000040 /* rx overrun */ -#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ -#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */ -#define E1000_ICR_RXCFG 0x00000400 /* RX /c/ ordered set */ -#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ -#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ -#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ -#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ -#define E1000_ICR_TXD_LOW 0x00008000 -#define E1000_ICR_SRPD 0x00010000 -#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */ -#define E1000_ICR_MNG 0x00040000 /* Manageability event */ -#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ -#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */ -#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO parity error */ -#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO parity error */ -#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity error */ -#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */ -#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */ -#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */ -#define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */ -#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW bit in the FWSM */ -#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */ -#define E1000_ICR_EPRST 0x00100000 /* ME hardware reset occurs */ - -/* Interrupt Cause Set */ -#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_ICS_SRPD E1000_ICR_SRPD -#define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */ -#define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */ -#define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */ -#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ -#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ -#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ -#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ -#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ -#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ -#define E1000_ICS_DSW E1000_ICR_DSW -#define E1000_ICS_PHYINT E1000_ICR_PHYINT -#define E1000_ICS_EPRST E1000_ICR_EPRST - -/* Interrupt Mask Set */ -#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_IMS_SRPD E1000_ICR_SRPD -#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */ -#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */ -#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */ -#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ -#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ -#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ -#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ -#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ -#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ -#define E1000_IMS_DSW E1000_ICR_DSW -#define E1000_IMS_PHYINT E1000_ICR_PHYINT -#define E1000_IMS_EPRST E1000_ICR_EPRST - -/* Interrupt Mask Clear */ -#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMC_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_IMC_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMC_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_IMC_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_IMC_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_IMC_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_IMC_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_IMC_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_IMC_SRPD E1000_ICR_SRPD -#define E1000_IMC_ACK E1000_ICR_ACK /* Receive Ack frame */ -#define E1000_IMC_MNG E1000_ICR_MNG /* Manageability event */ -#define E1000_IMC_DOCK E1000_ICR_DOCK /* Dock/Undock */ -#define E1000_IMC_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ -#define E1000_IMC_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ -#define E1000_IMC_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ -#define E1000_IMC_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ -#define E1000_IMC_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ -#define E1000_IMC_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ -#define E1000_IMC_DSW E1000_ICR_DSW -#define E1000_IMC_PHYINT E1000_ICR_PHYINT -#define E1000_IMC_EPRST E1000_ICR_EPRST - -/* Receive Control */ -#define E1000_RCTL_RST 0x00000001 /* Software reset */ -#define E1000_RCTL_EN 0x00000002 /* enable */ -#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ -#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ -#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ -#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ -#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ -#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ -#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */ -#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ -#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */ -#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */ -#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ -#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */ -#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */ -#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ -#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ -#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ -#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */ -#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ -#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */ -#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ -/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ -#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */ -#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */ -#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */ -#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */ -/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */ -#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */ -#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */ -#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */ -#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ -#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ -#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ -#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */ -#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ -#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ -#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ -#define E1000_RCTL_FLXBUF_MASK 0x78000000 /* Flexible buffer size */ -#define E1000_RCTL_FLXBUF_SHIFT 27 /* Flexible buffer shift */ - -/* Use byte values for the following shift parameters - * Usage: - * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) & - * E1000_PSRCTL_BSIZE0_MASK) | - * ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) & - * E1000_PSRCTL_BSIZE1_MASK) | - * ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) & - * E1000_PSRCTL_BSIZE2_MASK) | - * ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |; - * E1000_PSRCTL_BSIZE3_MASK)) - * where value0 = [128..16256], default=256 - * value1 = [1024..64512], default=4096 - * value2 = [0..64512], default=4096 - * value3 = [0..64512], default=0 - */ - -#define E1000_PSRCTL_BSIZE0_MASK 0x0000007F -#define E1000_PSRCTL_BSIZE1_MASK 0x00003F00 -#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000 -#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000 - -#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */ -#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */ -#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */ -#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */ - -/* SW_W_SYNC definitions */ -#define E1000_SWFW_EEP_SM 0x0001 -#define E1000_SWFW_PHY0_SM 0x0002 -#define E1000_SWFW_PHY1_SM 0x0004 -#define E1000_SWFW_MAC_CSR_SM 0x0008 - -/* Receive Descriptor */ -#define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */ -#define E1000_RDT_FPDB 0x80000000 /* Flush descriptor block */ -#define E1000_RDLEN_LEN 0x0007ff80 /* descriptor length */ -#define E1000_RDH_RDH 0x0000ffff /* receive descriptor head */ -#define E1000_RDT_RDT 0x0000ffff /* receive descriptor tail */ - -/* Flow Control */ -#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */ -#define E1000_FCRTH_XFCE 0x80000000 /* External Flow Control Enable */ -#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ -#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ - -/* Header split receive */ -#define E1000_RFCTL_ISCSI_DIS 0x00000001 -#define E1000_RFCTL_ISCSI_DWC_MASK 0x0000003E -#define E1000_RFCTL_ISCSI_DWC_SHIFT 1 -#define E1000_RFCTL_NFSW_DIS 0x00000040 -#define E1000_RFCTL_NFSR_DIS 0x00000080 -#define E1000_RFCTL_NFS_VER_MASK 0x00000300 -#define E1000_RFCTL_NFS_VER_SHIFT 8 -#define E1000_RFCTL_IPV6_DIS 0x00000400 -#define E1000_RFCTL_IPV6_XSUM_DIS 0x00000800 -#define E1000_RFCTL_ACK_DIS 0x00001000 -#define E1000_RFCTL_ACKD_DIS 0x00002000 -#define E1000_RFCTL_IPFRSP_DIS 0x00004000 -#define E1000_RFCTL_EXTEN 0x00008000 -#define E1000_RFCTL_IPV6_EX_DIS 0x00010000 -#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000 - -/* Receive Descriptor Control */ -#define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */ -#define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */ -#define E1000_RXDCTL_WTHRESH 0x003F0000 /* RXDCTL Writeback Threshold */ -#define E1000_RXDCTL_GRAN 0x01000000 /* RXDCTL Granularity */ - -/* Transmit Descriptor Control */ -#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */ -#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */ -#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */ -#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ -#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */ -#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ -#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc. - still to be processed. */ -/* Transmit Configuration Word */ -#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ -#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */ -#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ -#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ -#define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */ -#define E1000_TXCW_RF 0x00003000 /* TXCW remote fault */ -#define E1000_TXCW_NP 0x00008000 /* TXCW next page */ -#define E1000_TXCW_CW 0x0000ffff /* TxConfigWord mask */ -#define E1000_TXCW_TXC 0x40000000 /* Transmit Config control */ -#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */ - -/* Receive Configuration Word */ -#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */ -#define E1000_RXCW_NC 0x04000000 /* Receive config no carrier */ -#define E1000_RXCW_IV 0x08000000 /* Receive config invalid */ -#define E1000_RXCW_CC 0x10000000 /* Receive config change */ -#define E1000_RXCW_C 0x20000000 /* Receive config */ -#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ -#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */ - -/* Transmit Control */ -#define E1000_TCTL_RST 0x00000001 /* software reset */ -#define E1000_TCTL_EN 0x00000002 /* enable tx */ -#define E1000_TCTL_BCE 0x00000004 /* busy check enable */ -#define E1000_TCTL_PSP 0x00000008 /* pad short packets */ -#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */ -#define E1000_TCTL_COLD 0x003ff000 /* collision distance */ -#define E1000_TCTL_SWXOFF 0x00400000 /* SW Xoff transmission */ -#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */ -#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ -#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */ -#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */ -/* Extended Transmit Control */ -#define E1000_TCTL_EXT_BST_MASK 0x000003FF /* Backoff Slot Time */ -#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */ - -/* Receive Checksum Control */ -#define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */ -#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ -#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ -#define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */ -#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ -#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ - -/* Multiple Receive Queue Control */ -#define E1000_MRQC_ENABLE_MASK 0x00000003 -#define E1000_MRQC_ENABLE_RSS_2Q 0x00000001 -#define E1000_MRQC_ENABLE_RSS_INT 0x00000004 -#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000 -#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 -#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000 -#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000 -#define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000 -#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000 -#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 - -/* Definitions for power management and wakeup registers */ -/* Wake Up Control */ -#define E1000_WUC_APME 0x00000001 /* APM Enable */ -#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ -#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */ -#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */ -#define E1000_WUC_SPM 0x80000000 /* Enable SPM */ - -/* Wake Up Filter Control */ -#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ -#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ -#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ -#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ -#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ -#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ -#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ -#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ -#define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */ -#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ -#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ -#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */ -#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */ -#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */ -#define E1000_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */ -#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ - -/* Wake Up Status */ -#define E1000_WUS_LNKC 0x00000001 /* Link Status Changed */ -#define E1000_WUS_MAG 0x00000002 /* Magic Packet Received */ -#define E1000_WUS_EX 0x00000004 /* Directed Exact Received */ -#define E1000_WUS_MC 0x00000008 /* Directed Multicast Received */ -#define E1000_WUS_BC 0x00000010 /* Broadcast Received */ -#define E1000_WUS_ARP 0x00000020 /* ARP Request Packet Received */ -#define E1000_WUS_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Received */ -#define E1000_WUS_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Received */ -#define E1000_WUS_FLX0 0x00010000 /* Flexible Filter 0 Match */ -#define E1000_WUS_FLX1 0x00020000 /* Flexible Filter 1 Match */ -#define E1000_WUS_FLX2 0x00040000 /* Flexible Filter 2 Match */ -#define E1000_WUS_FLX3 0x00080000 /* Flexible Filter 3 Match */ -#define E1000_WUS_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ - -/* Management Control */ -#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ -#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ -#define E1000_MANC_R_ON_FORCE 0x00000004 /* Reset on Force TCO - RO */ -#define E1000_MANC_RMCP_EN 0x00000100 /* Enable RCMP 026Fh Filtering */ -#define E1000_MANC_0298_EN 0x00000200 /* Enable RCMP 0298h Filtering */ -#define E1000_MANC_IPV4_EN 0x00000400 /* Enable IPv4 */ -#define E1000_MANC_IPV6_EN 0x00000800 /* Enable IPv6 */ -#define E1000_MANC_SNAP_EN 0x00001000 /* Accept LLC/SNAP */ -#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ -#define E1000_MANC_NEIGHBOR_EN 0x00004000 /* Enable Neighbor Discovery - * Filtering */ -#define E1000_MANC_ARP_RES_EN 0x00008000 /* Enable ARP response Filtering */ -#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */ -#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ -#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */ -#define E1000_MANC_RCV_ALL 0x00080000 /* Receive All Enabled */ -#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ -#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MAC address - * filtering */ -#define E1000_MANC_EN_MNG2HOST 0x00200000 /* Enable MNG packets to host - * memory */ -#define E1000_MANC_EN_IP_ADDR_FILTER 0x00400000 /* Enable IP address - * filtering */ -#define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Enable checksum filtering */ -#define E1000_MANC_BR_EN 0x01000000 /* Enable broadcast filtering */ -#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */ -#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */ -#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */ -#define E1000_MANC_SMB_DATA_IN 0x08000000 /* SMBus Data In */ -#define E1000_MANC_SMB_DATA_OUT 0x10000000 /* SMBus Data Out */ -#define E1000_MANC_SMB_CLK_OUT 0x20000000 /* SMBus Clock Out */ - -#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */ -#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */ - -/* SW Semaphore Register */ -#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ -#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ -#define E1000_SWSM_WMNG 0x00000004 /* Wake MNG Clock */ -#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */ - -/* FW Semaphore Register */ -#define E1000_FWSM_MODE_MASK 0x0000000E /* FW mode */ -#define E1000_FWSM_MODE_SHIFT 1 -#define E1000_FWSM_FW_VALID 0x00008000 /* FW established a valid mode */ - -#define E1000_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI reset */ -#define E1000_FWSM_DISSW 0x10000000 /* FW disable SW Write Access */ -#define E1000_FWSM_SKUSEL_MASK 0x60000000 /* LAN SKU select */ -#define E1000_FWSM_SKUEL_SHIFT 29 -#define E1000_FWSM_SKUSEL_EMB 0x0 /* Embedded SKU */ -#define E1000_FWSM_SKUSEL_CONS 0x1 /* Consumer SKU */ -#define E1000_FWSM_SKUSEL_PERF_100 0x2 /* Perf & Corp 10/100 SKU */ -#define E1000_FWSM_SKUSEL_PERF_GBE 0x3 /* Perf & Copr GbE SKU */ - -/* FFLT Debug Register */ -#define E1000_FFLT_DBG_INVC 0x00100000 /* Invalid /C/ code handling */ - -typedef enum { - e1000_mng_mode_none = 0, - e1000_mng_mode_asf, - e1000_mng_mode_pt, - e1000_mng_mode_ipmi, - e1000_mng_mode_host_interface_only -} e1000_mng_mode; - -/* Host Interface Control Register */ -#define E1000_HICR_EN 0x00000001 /* Enable Bit - RO */ -#define E1000_HICR_C 0x00000002 /* Driver sets this bit when done - * to put command in RAM */ -#define E1000_HICR_SV 0x00000004 /* Status Validity */ -#define E1000_HICR_FWR 0x00000080 /* FW reset. Set by the Host */ - -/* Host Interface Command Interface - Address range 0x8800-0x8EFF */ -#define E1000_HI_MAX_DATA_LENGTH 252 /* Host Interface data length */ -#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Number of bytes in range */ -#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Number of dwords in range */ -#define E1000_HI_COMMAND_TIMEOUT 500 /* Time in ms to process HI command */ - -struct e1000_host_command_header { - u8 command_id; - u8 command_length; - u8 command_options; /* I/F bits for command, status for return */ - u8 checksum; -}; -struct e1000_host_command_info { - struct e1000_host_command_header command_header; /* Command Head/Command Result Head has 4 bytes */ - u8 command_data[E1000_HI_MAX_DATA_LENGTH]; /* Command data can length 0..252 */ -}; - -/* Host SMB register #0 */ -#define E1000_HSMC0R_CLKIN 0x00000001 /* SMB Clock in */ -#define E1000_HSMC0R_DATAIN 0x00000002 /* SMB Data in */ -#define E1000_HSMC0R_DATAOUT 0x00000004 /* SMB Data out */ -#define E1000_HSMC0R_CLKOUT 0x00000008 /* SMB Clock out */ - -/* Host SMB register #1 */ -#define E1000_HSMC1R_CLKIN E1000_HSMC0R_CLKIN -#define E1000_HSMC1R_DATAIN E1000_HSMC0R_DATAIN -#define E1000_HSMC1R_DATAOUT E1000_HSMC0R_DATAOUT -#define E1000_HSMC1R_CLKOUT E1000_HSMC0R_CLKOUT - -/* FW Status Register */ -#define E1000_FWSTS_FWS_MASK 0x000000FF /* FW Status */ - -/* Wake Up Packet Length */ -#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */ - -#define E1000_MDALIGN 4096 - -/* PCI-Ex registers*/ - -/* PCI-Ex Control Register */ -#define E1000_GCR_RXD_NO_SNOOP 0x00000001 -#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 -#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004 -#define E1000_GCR_TXD_NO_SNOOP 0x00000008 -#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 -#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 - -#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ - E1000_GCR_RXDSCW_NO_SNOOP | \ - E1000_GCR_RXDSCR_NO_SNOOP | \ - E1000_GCR_TXD_NO_SNOOP | \ - E1000_GCR_TXDSCW_NO_SNOOP | \ - E1000_GCR_TXDSCR_NO_SNOOP) - -#define PCI_EX_82566_SNOOP_ALL PCI_EX_NO_SNOOP_ALL - -#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 -/* Function Active and Power State to MNG */ -#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003 -#define E1000_FACTPS_LAN0_VALID 0x00000004 -#define E1000_FACTPS_FUNC0_AUX_EN 0x00000008 -#define E1000_FACTPS_FUNC1_POWER_STATE_MASK 0x000000C0 -#define E1000_FACTPS_FUNC1_POWER_STATE_SHIFT 6 -#define E1000_FACTPS_LAN1_VALID 0x00000100 -#define E1000_FACTPS_FUNC1_AUX_EN 0x00000200 -#define E1000_FACTPS_FUNC2_POWER_STATE_MASK 0x00003000 -#define E1000_FACTPS_FUNC2_POWER_STATE_SHIFT 12 -#define E1000_FACTPS_IDE_ENABLE 0x00004000 -#define E1000_FACTPS_FUNC2_AUX_EN 0x00008000 -#define E1000_FACTPS_FUNC3_POWER_STATE_MASK 0x000C0000 -#define E1000_FACTPS_FUNC3_POWER_STATE_SHIFT 18 -#define E1000_FACTPS_SP_ENABLE 0x00100000 -#define E1000_FACTPS_FUNC3_AUX_EN 0x00200000 -#define E1000_FACTPS_FUNC4_POWER_STATE_MASK 0x03000000 -#define E1000_FACTPS_FUNC4_POWER_STATE_SHIFT 24 -#define E1000_FACTPS_IPMI_ENABLE 0x04000000 -#define E1000_FACTPS_FUNC4_AUX_EN 0x08000000 -#define E1000_FACTPS_MNGCG 0x20000000 -#define E1000_FACTPS_LAN_FUNC_SEL 0x40000000 -#define E1000_FACTPS_PM_STATE_CHANGED 0x80000000 - -/* PCI-Ex Config Space */ -#define PCI_EX_LINK_STATUS 0x12 -#define PCI_EX_LINK_WIDTH_MASK 0x3F0 -#define PCI_EX_LINK_WIDTH_SHIFT 4 - -/* EEPROM Commands - Microwire */ -#define EEPROM_READ_OPCODE_MICROWIRE 0x6 /* EEPROM read opcode */ -#define EEPROM_WRITE_OPCODE_MICROWIRE 0x5 /* EEPROM write opcode */ -#define EEPROM_ERASE_OPCODE_MICROWIRE 0x7 /* EEPROM erase opcode */ -#define EEPROM_EWEN_OPCODE_MICROWIRE 0x13 /* EEPROM erase/write enable */ -#define EEPROM_EWDS_OPCODE_MICROWIRE 0x10 /* EEPROM erase/write disable */ - -/* EEPROM Commands - SPI */ -#define EEPROM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ -#define EEPROM_READ_OPCODE_SPI 0x03 /* EEPROM read opcode */ -#define EEPROM_WRITE_OPCODE_SPI 0x02 /* EEPROM write opcode */ -#define EEPROM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */ -#define EEPROM_WREN_OPCODE_SPI 0x06 /* EEPROM set Write Enable latch */ -#define EEPROM_WRDI_OPCODE_SPI 0x04 /* EEPROM reset Write Enable latch */ -#define EEPROM_RDSR_OPCODE_SPI 0x05 /* EEPROM read Status register */ -#define EEPROM_WRSR_OPCODE_SPI 0x01 /* EEPROM write Status register */ -#define EEPROM_ERASE4K_OPCODE_SPI 0x20 /* EEPROM ERASE 4KB */ -#define EEPROM_ERASE64K_OPCODE_SPI 0xD8 /* EEPROM ERASE 64KB */ -#define EEPROM_ERASE256_OPCODE_SPI 0xDB /* EEPROM ERASE 256B */ - -/* EEPROM Size definitions */ -#define EEPROM_WORD_SIZE_SHIFT 6 -#define EEPROM_SIZE_SHIFT 10 -#define EEPROM_SIZE_MASK 0x1C00 - -/* EEPROM Word Offsets */ -#define EEPROM_COMPAT 0x0003 -#define EEPROM_ID_LED_SETTINGS 0x0004 -#define EEPROM_VERSION 0x0005 -#define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */ -#define EEPROM_PHY_CLASS_WORD 0x0007 -#define EEPROM_INIT_CONTROL1_REG 0x000A -#define EEPROM_INIT_CONTROL2_REG 0x000F -#define EEPROM_SWDEF_PINS_CTRL_PORT_1 0x0010 -#define EEPROM_INIT_CONTROL3_PORT_B 0x0014 -#define EEPROM_INIT_3GIO_3 0x001A -#define EEPROM_SWDEF_PINS_CTRL_PORT_0 0x0020 -#define EEPROM_INIT_CONTROL3_PORT_A 0x0024 -#define EEPROM_CFG 0x0012 -#define EEPROM_FLASH_VERSION 0x0032 -#define EEPROM_CHECKSUM_REG 0x003F - -#define E1000_EEPROM_CFG_DONE 0x00040000 /* MNG config cycle done */ -#define E1000_EEPROM_CFG_DONE_PORT_1 0x00080000 /* ...for second port */ - -/* Word definitions for ID LED Settings */ -#define ID_LED_RESERVED_0000 0x0000 -#define ID_LED_RESERVED_FFFF 0xFFFF -#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ - (ID_LED_OFF1_OFF2 << 8) | \ - (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_DEF1_DEF2)) -#define ID_LED_DEF1_DEF2 0x1 -#define ID_LED_DEF1_ON2 0x2 -#define ID_LED_DEF1_OFF2 0x3 -#define ID_LED_ON1_DEF2 0x4 -#define ID_LED_ON1_ON2 0x5 -#define ID_LED_ON1_OFF2 0x6 -#define ID_LED_OFF1_DEF2 0x7 -#define ID_LED_OFF1_ON2 0x8 -#define ID_LED_OFF1_OFF2 0x9 - -#define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF -#define IGP_ACTIVITY_LED_ENABLE 0x0300 -#define IGP_LED3_MODE 0x07000000 - -/* Mask bits for SERDES amplitude adjustment in Word 6 of the EEPROM */ -#define EEPROM_SERDES_AMPLITUDE_MASK 0x000F - -/* Mask bit for PHY class in Word 7 of the EEPROM */ -#define EEPROM_PHY_CLASS_A 0x8000 - -/* Mask bits for fields in Word 0x0a of the EEPROM */ -#define EEPROM_WORD0A_ILOS 0x0010 -#define EEPROM_WORD0A_SWDPIO 0x01E0 -#define EEPROM_WORD0A_LRST 0x0200 -#define EEPROM_WORD0A_FD 0x0400 -#define EEPROM_WORD0A_66MHZ 0x0800 - -/* Mask bits for fields in Word 0x0f of the EEPROM */ -#define EEPROM_WORD0F_PAUSE_MASK 0x3000 -#define EEPROM_WORD0F_PAUSE 0x1000 -#define EEPROM_WORD0F_ASM_DIR 0x2000 -#define EEPROM_WORD0F_ANE 0x0800 -#define EEPROM_WORD0F_SWPDIO_EXT 0x00F0 -#define EEPROM_WORD0F_LPLU 0x0001 - -/* Mask bits for fields in Word 0x10/0x20 of the EEPROM */ -#define EEPROM_WORD1020_GIGA_DISABLE 0x0010 -#define EEPROM_WORD1020_GIGA_DISABLE_NON_D0A 0x0008 - -/* Mask bits for fields in Word 0x1a of the EEPROM */ -#define EEPROM_WORD1A_ASPM_MASK 0x000C - -/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */ -#define EEPROM_SUM 0xBABA - -/* EEPROM Map defines (WORD OFFSETS)*/ -#define EEPROM_NODE_ADDRESS_BYTE_0 0 -#define EEPROM_PBA_BYTE_1 8 - -#define EEPROM_RESERVED_WORD 0xFFFF - -/* EEPROM Map Sizes (Byte Counts) */ -#define PBA_SIZE 4 - -/* Collision related configuration parameters */ -#define E1000_COLLISION_THRESHOLD 15 -#define E1000_CT_SHIFT 4 -/* Collision distance is a 0-based value that applies to - * half-duplex-capable hardware only. */ -#define E1000_COLLISION_DISTANCE 63 -#define E1000_COLLISION_DISTANCE_82542 64 -#define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE -#define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE -#define E1000_COLD_SHIFT 12 - -/* Number of Transmit and Receive Descriptors must be a multiple of 8 */ -#define REQ_TX_DESCRIPTOR_MULTIPLE 8 -#define REQ_RX_DESCRIPTOR_MULTIPLE 8 - -/* Default values for the transmit IPG register */ -#define DEFAULT_82542_TIPG_IPGT 10 -#define DEFAULT_82543_TIPG_IPGT_FIBER 9 -#define DEFAULT_82543_TIPG_IPGT_COPPER 8 - -#define E1000_TIPG_IPGT_MASK 0x000003FF -#define E1000_TIPG_IPGR1_MASK 0x000FFC00 -#define E1000_TIPG_IPGR2_MASK 0x3FF00000 - -#define DEFAULT_82542_TIPG_IPGR1 2 -#define DEFAULT_82543_TIPG_IPGR1 8 -#define E1000_TIPG_IPGR1_SHIFT 10 - -#define DEFAULT_82542_TIPG_IPGR2 10 -#define DEFAULT_82543_TIPG_IPGR2 6 -#define E1000_TIPG_IPGR2_SHIFT 20 - -#define E1000_TXDMAC_DPP 0x00000001 - -/* Adaptive IFS defines */ -#define TX_THRESHOLD_START 8 -#define TX_THRESHOLD_INCREMENT 10 -#define TX_THRESHOLD_DECREMENT 1 -#define TX_THRESHOLD_STOP 190 -#define TX_THRESHOLD_DISABLE 0 -#define TX_THRESHOLD_TIMER_MS 10000 -#define MIN_NUM_XMITS 1000 -#define IFS_MAX 80 -#define IFS_STEP 10 -#define IFS_MIN 40 -#define IFS_RATIO 4 - -/* Extended Configuration Control and Size */ -#define E1000_EXTCNF_CTRL_PCIE_WRITE_ENABLE 0x00000001 -#define E1000_EXTCNF_CTRL_PHY_WRITE_ENABLE 0x00000002 -#define E1000_EXTCNF_CTRL_D_UD_ENABLE 0x00000004 -#define E1000_EXTCNF_CTRL_D_UD_LATENCY 0x00000008 -#define E1000_EXTCNF_CTRL_D_UD_OWNER 0x00000010 -#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 -#define E1000_EXTCNF_CTRL_MDIO_HW_OWNERSHIP 0x00000040 -#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER 0x0FFF0000 - -#define E1000_EXTCNF_SIZE_EXT_PHY_LENGTH 0x000000FF -#define E1000_EXTCNF_SIZE_EXT_DOCK_LENGTH 0x0000FF00 -#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH 0x00FF0000 -#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 -#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 - -/* PBA constants */ -#define E1000_PBA_8K 0x0008 /* 8KB, default Rx allocation */ -#define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */ -#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */ -#define E1000_PBA_20K 0x0014 -#define E1000_PBA_22K 0x0016 -#define E1000_PBA_24K 0x0018 -#define E1000_PBA_30K 0x001E -#define E1000_PBA_32K 0x0020 -#define E1000_PBA_34K 0x0022 -#define E1000_PBA_38K 0x0026 -#define E1000_PBA_40K 0x0028 -#define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */ - -#define E1000_PBS_16K E1000_PBA_16K - -/* Flow Control Constants */ -#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 -#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 -#define FLOW_CONTROL_TYPE 0x8808 - -/* The historical defaults for the flow control values are given below. */ -#define FC_DEFAULT_HI_THRESH (0x8000) /* 32KB */ -#define FC_DEFAULT_LO_THRESH (0x4000) /* 16KB */ -#define FC_DEFAULT_TX_TIMER (0x100) /* ~130 us */ - -/* PCIX Config space */ -#define PCIX_COMMAND_REGISTER 0xE6 -#define PCIX_STATUS_REGISTER_LO 0xE8 -#define PCIX_STATUS_REGISTER_HI 0xEA - -#define PCIX_COMMAND_MMRBC_MASK 0x000C -#define PCIX_COMMAND_MMRBC_SHIFT 0x2 -#define PCIX_STATUS_HI_MMRBC_MASK 0x0060 -#define PCIX_STATUS_HI_MMRBC_SHIFT 0x5 -#define PCIX_STATUS_HI_MMRBC_4K 0x3 -#define PCIX_STATUS_HI_MMRBC_2K 0x2 - -/* Number of bits required to shift right the "pause" bits from the - * EEPROM (bits 13:12) to the "pause" (bits 8:7) field in the TXCW register. - */ -#define PAUSE_SHIFT 5 - -/* Number of bits required to shift left the "SWDPIO" bits from the - * EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field in the CTRL register. - */ -#define SWDPIO_SHIFT 17 - -/* Number of bits required to shift left the "SWDPIO_EXT" bits from the - * EEPROM word F (bits 7:4) to the bits 11:8 of The Extended CTRL register. - */ -#define SWDPIO__EXT_SHIFT 4 - -/* Number of bits required to shift left the "ILOS" bit from the EEPROM - * (bit 4) to the "ILOS" (bit 7) field in the CTRL register. - */ -#define ILOS_SHIFT 3 - -#define RECEIVE_BUFFER_ALIGN_SIZE (256) - -/* Number of milliseconds we wait for auto-negotiation to complete */ -#define LINK_UP_TIMEOUT 500 - -/* Number of milliseconds we wait for Eeprom auto read bit done after MAC reset */ -#define AUTO_READ_DONE_TIMEOUT 10 -/* Number of milliseconds we wait for PHY configuration done after MAC reset */ -#define PHY_CFG_TIMEOUT 100 - -#define E1000_TX_BUFFER_SIZE ((u32)1514) - -/* The carrier extension symbol, as received by the NIC. */ -#define CARRIER_EXTENSION 0x0F - -/* TBI_ACCEPT macro definition: - * - * This macro requires: - * adapter = a pointer to struct e1000_hw - * status = the 8 bit status field of the RX descriptor with EOP set - * error = the 8 bit error field of the RX descriptor with EOP set - * length = the sum of all the length fields of the RX descriptors that - * make up the current frame - * last_byte = the last byte of the frame DMAed by the hardware - * max_frame_length = the maximum frame length we want to accept. - * min_frame_length = the minimum frame length we want to accept. - * - * This macro is a conditional that should be used in the interrupt - * handler's Rx processing routine when RxErrors have been detected. - * - * Typical use: - * ... - * if (TBI_ACCEPT) { - * accept_frame = true; - * e1000_tbi_adjust_stats(adapter, MacAddress); - * frame_length--; - * } else { - * accept_frame = false; - * } - * ... - */ - -#define TBI_ACCEPT(adapter, status, errors, length, last_byte) \ - ((adapter)->tbi_compatibility_on && \ - (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \ - ((last_byte) == CARRIER_EXTENSION) && \ - (((status) & E1000_RXD_STAT_VP) ? \ - (((length) > ((adapter)->min_frame_size - VLAN_TAG_SIZE)) && \ - ((length) <= ((adapter)->max_frame_size + 1))) : \ - (((length) > (adapter)->min_frame_size) && \ - ((length) <= ((adapter)->max_frame_size + VLAN_TAG_SIZE + 1))))) - -/* Structures, enums, and macros for the PHY */ - -/* Bit definitions for the Management Data IO (MDIO) and Management Data - * Clock (MDC) pins in the Device Control Register. - */ -#define E1000_CTRL_PHY_RESET_DIR E1000_CTRL_SWDPIO0 -#define E1000_CTRL_PHY_RESET E1000_CTRL_SWDPIN0 -#define E1000_CTRL_MDIO_DIR E1000_CTRL_SWDPIO2 -#define E1000_CTRL_MDIO E1000_CTRL_SWDPIN2 -#define E1000_CTRL_MDC_DIR E1000_CTRL_SWDPIO3 -#define E1000_CTRL_MDC E1000_CTRL_SWDPIN3 -#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR -#define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA - -/* PHY 1000 MII Register/Bit Definitions */ -/* PHY Registers defined by IEEE */ -#define PHY_CTRL 0x00 /* Control Register */ -#define PHY_STATUS 0x01 /* Status Register */ -#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ -#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ -#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ -#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ -#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ -#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */ -#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */ -#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ -#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ -#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ - -#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ -#define MAX_PHY_MULTI_PAGE_REG 0xF /* Registers equal on all pages */ - -/* M88E1000 Specific Registers */ -#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ -#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */ -#define M88E1000_INT_ENABLE 0x12 /* Interrupt Enable Register */ -#define M88E1000_INT_STATUS 0x13 /* Interrupt Status Register */ -#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ -#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ - -#define M88E1000_PHY_EXT_CTRL 0x1A /* PHY extend control register */ -#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */ -#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */ -#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */ -#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */ - -#define IGP01E1000_IEEE_REGS_PAGE 0x0000 -#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300 -#define IGP01E1000_IEEE_FORCE_GIGA 0x0140 - -/* IGP01E1000 Specific Registers */ -#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */ -#define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */ -#define IGP01E1000_PHY_PORT_CTRL 0x12 /* PHY Specific Control Register */ -#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health Register */ -#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO Register */ -#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality Register */ -#define IGP02E1000_PHY_POWER_MGMT 0x19 -#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* PHY Page Select Core Register */ - -/* IGP01E1000 AGC Registers - stores the cable length values*/ -#define IGP01E1000_PHY_AGC_A 0x1172 -#define IGP01E1000_PHY_AGC_B 0x1272 -#define IGP01E1000_PHY_AGC_C 0x1472 -#define IGP01E1000_PHY_AGC_D 0x1872 - -/* IGP02E1000 AGC Registers for cable length values */ -#define IGP02E1000_PHY_AGC_A 0x11B1 -#define IGP02E1000_PHY_AGC_B 0x12B1 -#define IGP02E1000_PHY_AGC_C 0x14B1 -#define IGP02E1000_PHY_AGC_D 0x18B1 - -/* IGP01E1000 DSP Reset Register */ -#define IGP01E1000_PHY_DSP_RESET 0x1F33 -#define IGP01E1000_PHY_DSP_SET 0x1F71 -#define IGP01E1000_PHY_DSP_FFE 0x1F35 - -#define IGP01E1000_PHY_CHANNEL_NUM 4 -#define IGP02E1000_PHY_CHANNEL_NUM 4 - -#define IGP01E1000_PHY_AGC_PARAM_A 0x1171 -#define IGP01E1000_PHY_AGC_PARAM_B 0x1271 -#define IGP01E1000_PHY_AGC_PARAM_C 0x1471 -#define IGP01E1000_PHY_AGC_PARAM_D 0x1871 - -#define IGP01E1000_PHY_EDAC_MU_INDEX 0xC000 -#define IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS 0x8000 - -#define IGP01E1000_PHY_ANALOG_TX_STATE 0x2890 -#define IGP01E1000_PHY_ANALOG_CLASS_A 0x2000 -#define IGP01E1000_PHY_FORCE_ANALOG_ENABLE 0x0004 -#define IGP01E1000_PHY_DSP_FFE_CM_CP 0x0069 - -#define IGP01E1000_PHY_DSP_FFE_DEFAULT 0x002A -/* IGP01E1000 PCS Initialization register - stores the polarity status when - * speed = 1000 Mbps. */ -#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 -#define IGP01E1000_PHY_PCS_CTRL_REG 0x00B5 - -#define IGP01E1000_ANALOG_REGS_PAGE 0x20C0 - -/* PHY Control Register */ -#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ -#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ -#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ -#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ -#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ -#define MII_CR_POWER_DOWN 0x0800 /* Power down */ -#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ -#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ -#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ -#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ - -/* PHY Status Register */ -#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ -#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ -#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ -#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ -#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ -#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ -#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ -#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ -#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ -#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ -#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ -#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ -#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ -#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ -#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ - -/* Autoneg Advertisement Register */ -#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */ -#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ -#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ -#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ -#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ -#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */ -#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ -#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ -#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */ -#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */ - -/* Link Partner Ability Register (Base Page) */ -#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */ -#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */ -#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */ -#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */ -#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */ -#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */ -#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ -#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */ -#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */ -#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */ -#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */ - -/* Autoneg Expansion Register */ -#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */ -#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */ -#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */ -#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */ -#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */ - -/* Next Page TX Register */ -#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ -#define NPTX_TOGGLE 0x0800 /* Toggles between exchanges - * of different NP - */ -#define NPTX_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg - * 0 = cannot comply with msg - */ -#define NPTX_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ -#define NPTX_NEXT_PAGE 0x8000 /* 1 = addition NP will follow - * 0 = sending last NP - */ - -/* Link Partner Next Page Register */ -#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ -#define LP_RNPR_TOGGLE 0x0800 /* Toggles between exchanges - * of different NP - */ -#define LP_RNPR_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg - * 0 = cannot comply with msg - */ -#define LP_RNPR_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ -#define LP_RNPR_ACKNOWLDGE 0x4000 /* 1 = ACK / 0 = NO ACK */ -#define LP_RNPR_NEXT_PAGE 0x8000 /* 1 = addition NP will follow - * 0 = sending last NP - */ - -/* 1000BASE-T Control Register */ -#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */ -#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ -#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ -#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */ - /* 0=DTE device */ -#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */ - /* 0=Configure PHY as Slave */ -#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */ - /* 0=Automatic Master/Slave config */ -#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ -#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ -#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ -#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ -#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ - -/* 1000BASE-T Status Register */ -#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */ -#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */ -#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ -#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ -#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ -#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ -#define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */ -#define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ -#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12 -#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13 -#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5 -#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20 -#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100 - -/* Extended Status Register */ -#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */ -#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */ -#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */ -#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */ - -#define PHY_TX_POLARITY_MASK 0x0100 /* register 10h bit 8 (polarity bit) */ -#define PHY_TX_NORMAL_POLARITY 0 /* register 10h bit 8 (normal polarity) */ - -#define AUTO_POLARITY_DISABLE 0x0010 /* register 11h bit 4 */ - /* (0=enable, 1=disable) */ - -/* M88E1000 PHY Specific Control Register */ -#define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */ -#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ -#define M88E1000_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */ -#define M88E1000_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low, - * 0=CLK125 toggling - */ -#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ - /* Manual MDI configuration */ -#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ -#define M88E1000_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover, - * 100BASE-TX/10BASE-T: - * MDI Mode - */ -#define M88E1000_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled - * all speeds. - */ -#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE 0x0080 - /* 1=Enable Extended 10BASE-T distance - * (Lower 10BASE-T RX Threshold) - * 0=Normal 10BASE-T RX Threshold */ -#define M88E1000_PSCR_MII_5BIT_ENABLE 0x0100 - /* 1=5-Bit interface in 100BASE-TX - * 0=MII interface in 100BASE-TX */ -#define M88E1000_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */ -#define M88E1000_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */ -#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ - -#define M88E1000_PSCR_POLARITY_REVERSAL_SHIFT 1 -#define M88E1000_PSCR_AUTO_X_MODE_SHIFT 5 -#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7 - -/* M88E1000 PHY Specific Status Register */ -#define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */ -#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ -#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */ -#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ -#define M88E1000_PSSR_CABLE_LENGTH 0x0380 /* 0=<50M;1=50-80M;2=80-110M; - * 3=110-140M;4=>140M */ -#define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */ -#define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ -#define M88E1000_PSSR_PAGE_RCVD 0x1000 /* 1=Page received */ -#define M88E1000_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ -#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ -#define M88E1000_PSSR_10MBS 0x0000 /* 00=10Mbs */ -#define M88E1000_PSSR_100MBS 0x4000 /* 01=100Mbs */ -#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ - -#define M88E1000_PSSR_REV_POLARITY_SHIFT 1 -#define M88E1000_PSSR_DOWNSHIFT_SHIFT 5 -#define M88E1000_PSSR_MDIX_SHIFT 6 -#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 - -/* M88E1000 Extended PHY Specific Control Register */ -#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */ -#define M88E1000_EPSCR_DOWN_NO_IDLE 0x8000 /* 1=Lost lock detect enabled. - * Will assert lost lock and bring - * link down if idle not seen - * within 1ms in 1000BASE-T - */ -/* Number of times we will attempt to autonegotiate before downshifting if we - * are the master */ -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X 0x0400 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X 0x0800 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X 0x0C00 -/* Number of times we will attempt to autonegotiate before downshifting if we - * are the slave */ -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_DIS 0x0000 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X 0x0200 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X 0x0300 -#define M88E1000_EPSCR_TX_CLK_2_5 0x0060 /* 2.5 MHz TX_CLK */ -#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ -#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */ - -/* M88EC018 Rev 2 specific DownShift settings */ -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_1X 0x0000 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_2X 0x0200 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_3X 0x0400 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_4X 0x0600 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_6X 0x0A00 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X 0x0C00 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X 0x0E00 - -/* IGP01E1000 Specific Port Config Register - R/W */ -#define IGP01E1000_PSCFR_AUTO_MDIX_PAR_DETECT 0x0010 -#define IGP01E1000_PSCFR_PRE_EN 0x0020 -#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 -#define IGP01E1000_PSCFR_DISABLE_TPLOOPBACK 0x0100 -#define IGP01E1000_PSCFR_DISABLE_JABBER 0x0400 -#define IGP01E1000_PSCFR_DISABLE_TRANSMIT 0x2000 - -/* IGP01E1000 Specific Port Status Register - R/O */ -#define IGP01E1000_PSSR_AUTONEG_FAILED 0x0001 /* RO LH SC */ -#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 -#define IGP01E1000_PSSR_CABLE_LENGTH 0x007C -#define IGP01E1000_PSSR_FULL_DUPLEX 0x0200 -#define IGP01E1000_PSSR_LINK_UP 0x0400 -#define IGP01E1000_PSSR_MDIX 0x0800 -#define IGP01E1000_PSSR_SPEED_MASK 0xC000 /* speed bits mask */ -#define IGP01E1000_PSSR_SPEED_10MBPS 0x4000 -#define IGP01E1000_PSSR_SPEED_100MBPS 0x8000 -#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 -#define IGP01E1000_PSSR_CABLE_LENGTH_SHIFT 0x0002 /* shift right 2 */ -#define IGP01E1000_PSSR_MDIX_SHIFT 0x000B /* shift right 11 */ - -/* IGP01E1000 Specific Port Control Register - R/W */ -#define IGP01E1000_PSCR_TP_LOOPBACK 0x0010 -#define IGP01E1000_PSCR_CORRECT_NC_SCMBLR 0x0200 -#define IGP01E1000_PSCR_TEN_CRS_SELECT 0x0400 -#define IGP01E1000_PSCR_FLIP_CHIP 0x0800 -#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 -#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0-MDI, 1-MDIX */ - -/* IGP01E1000 Specific Port Link Health Register */ -#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 -#define IGP01E1000_PLHR_GIG_SCRAMBLER_ERROR 0x4000 -#define IGP01E1000_PLHR_MASTER_FAULT 0x2000 -#define IGP01E1000_PLHR_MASTER_RESOLUTION 0x1000 -#define IGP01E1000_PLHR_GIG_REM_RCVR_NOK 0x0800 /* LH */ -#define IGP01E1000_PLHR_IDLE_ERROR_CNT_OFLOW 0x0400 /* LH */ -#define IGP01E1000_PLHR_DATA_ERR_1 0x0200 /* LH */ -#define IGP01E1000_PLHR_DATA_ERR_0 0x0100 -#define IGP01E1000_PLHR_AUTONEG_FAULT 0x0040 -#define IGP01E1000_PLHR_AUTONEG_ACTIVE 0x0010 -#define IGP01E1000_PLHR_VALID_CHANNEL_D 0x0008 -#define IGP01E1000_PLHR_VALID_CHANNEL_C 0x0004 -#define IGP01E1000_PLHR_VALID_CHANNEL_B 0x0002 -#define IGP01E1000_PLHR_VALID_CHANNEL_A 0x0001 - -/* IGP01E1000 Channel Quality Register */ -#define IGP01E1000_MSE_CHANNEL_D 0x000F -#define IGP01E1000_MSE_CHANNEL_C 0x00F0 -#define IGP01E1000_MSE_CHANNEL_B 0x0F00 -#define IGP01E1000_MSE_CHANNEL_A 0xF000 - -#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ -#define IGP02E1000_PM_D3_LPLU 0x0004 /* Enable LPLU in non-D0a modes */ -#define IGP02E1000_PM_D0_LPLU 0x0002 /* Enable LPLU in D0a mode */ - -/* IGP01E1000 DSP reset macros */ -#define DSP_RESET_ENABLE 0x0 -#define DSP_RESET_DISABLE 0x2 -#define E1000_MAX_DSP_RESETS 10 - -/* IGP01E1000 & IGP02E1000 AGC Registers */ - -#define IGP01E1000_AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */ -#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Coarse - 15:13, Fine - 12:9 */ - -/* IGP02E1000 AGC Register Length 9-bit mask */ -#define IGP02E1000_AGC_LENGTH_MASK 0x7F - -/* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */ -#define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128 -#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 113 - -/* The precision error of the cable length is +/- 10 meters */ -#define IGP01E1000_AGC_RANGE 10 -#define IGP02E1000_AGC_RANGE 15 - -/* IGP01E1000 PCS Initialization register */ -/* bits 3:6 in the PCS registers stores the channels polarity */ -#define IGP01E1000_PHY_POLARITY_MASK 0x0078 - -/* IGP01E1000 GMII FIFO Register */ -#define IGP01E1000_GMII_FLEX_SPD 0x10 /* Enable flexible speed - * on Link-Up */ -#define IGP01E1000_GMII_SPD 0x20 /* Enable SPD */ - -/* IGP01E1000 Analog Register */ -#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x20D1 -#define IGP01E1000_ANALOG_FUSE_STATUS 0x20D0 -#define IGP01E1000_ANALOG_FUSE_CONTROL 0x20DC -#define IGP01E1000_ANALOG_FUSE_BYPASS 0x20DE - -#define IGP01E1000_ANALOG_FUSE_POLY_MASK 0xF000 -#define IGP01E1000_ANALOG_FUSE_FINE_MASK 0x0F80 -#define IGP01E1000_ANALOG_FUSE_COARSE_MASK 0x0070 -#define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED 0x0100 -#define IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL 0x0002 - -#define IGP01E1000_ANALOG_FUSE_COARSE_THRESH 0x0040 -#define IGP01E1000_ANALOG_FUSE_COARSE_10 0x0010 -#define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080 -#define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500 - -/* Bit definitions for valid PHY IDs. */ -/* I = Integrated - * E = External - */ -#define M88_VENDOR 0x0141 -#define M88E1000_E_PHY_ID 0x01410C50 -#define M88E1000_I_PHY_ID 0x01410C30 -#define M88E1011_I_PHY_ID 0x01410C20 -#define IGP01E1000_I_PHY_ID 0x02A80380 -#define M88E1000_12_PHY_ID M88E1000_E_PHY_ID -#define M88E1000_14_PHY_ID M88E1000_E_PHY_ID -#define M88E1011_I_REV_4 0x04 -#define M88E1111_I_PHY_ID 0x01410CC0 -#define M88E1118_E_PHY_ID 0x01410E40 -#define L1LXT971A_PHY_ID 0x001378E0 - -#define RTL8211B_PHY_ID 0x001CC910 -#define RTL8201N_PHY_ID 0x8200 -#define RTL_PHY_CTRL_FD 0x0100 /* Full duplex.0=half; 1=full */ -#define RTL_PHY_CTRL_SPD_100 0x200000 /* Force 100Mb */ - -/* Bits... - * 15-5: page - * 4-0: register offset - */ -#define PHY_PAGE_SHIFT 5 -#define PHY_REG(page, reg) \ - (((page) << PHY_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS)) - -#define IGP3_PHY_PORT_CTRL \ - PHY_REG(769, 17) /* Port General Configuration */ -#define IGP3_PHY_RATE_ADAPT_CTRL \ - PHY_REG(769, 25) /* Rate Adapter Control Register */ - -#define IGP3_KMRN_FIFO_CTRL_STATS \ - PHY_REG(770, 16) /* KMRN FIFO's control/status register */ -#define IGP3_KMRN_POWER_MNG_CTRL \ - PHY_REG(770, 17) /* KMRN Power Management Control Register */ -#define IGP3_KMRN_INBAND_CTRL \ - PHY_REG(770, 18) /* KMRN Inband Control Register */ -#define IGP3_KMRN_DIAG \ - PHY_REG(770, 19) /* KMRN Diagnostic register */ -#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 /* RX PCS is not synced */ -#define IGP3_KMRN_ACK_TIMEOUT \ - PHY_REG(770, 20) /* KMRN Acknowledge Timeouts register */ - -#define IGP3_VR_CTRL \ - PHY_REG(776, 18) /* Voltage regulator control register */ -#define IGP3_VR_CTRL_MODE_SHUT 0x0200 /* Enter powerdown, shutdown VRs */ -#define IGP3_VR_CTRL_MODE_MASK 0x0300 /* Shutdown VR Mask */ - -#define IGP3_CAPABILITY \ - PHY_REG(776, 19) /* IGP3 Capability Register */ - -/* Capabilities for SKU Control */ -#define IGP3_CAP_INITIATE_TEAM 0x0001 /* Able to initiate a team */ -#define IGP3_CAP_WFM 0x0002 /* Support WoL and PXE */ -#define IGP3_CAP_ASF 0x0004 /* Support ASF */ -#define IGP3_CAP_LPLU 0x0008 /* Support Low Power Link Up */ -#define IGP3_CAP_DC_AUTO_SPEED 0x0010 /* Support AC/DC Auto Link Speed */ -#define IGP3_CAP_SPD 0x0020 /* Support Smart Power Down */ -#define IGP3_CAP_MULT_QUEUE 0x0040 /* Support 2 tx & 2 rx queues */ -#define IGP3_CAP_RSS 0x0080 /* Support RSS */ -#define IGP3_CAP_8021PQ 0x0100 /* Support 802.1Q & 802.1p */ -#define IGP3_CAP_AMT_CB 0x0200 /* Support active manageability and circuit breaker */ - -#define IGP3_PPC_JORDAN_EN 0x0001 -#define IGP3_PPC_JORDAN_GIGA_SPEED 0x0002 - -#define IGP3_KMRN_PMC_EE_IDLE_LINK_DIS 0x0001 -#define IGP3_KMRN_PMC_K0S_ENTRY_LATENCY_MASK 0x001E -#define IGP3_KMRN_PMC_K0S_MODE1_EN_GIGA 0x0020 -#define IGP3_KMRN_PMC_K0S_MODE1_EN_100 0x0040 - -#define IGP3E1000_PHY_MISC_CTRL 0x1B /* Misc. Ctrl register */ -#define IGP3_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Duplex Manual Set */ - -#define IGP3_KMRN_EXT_CTRL PHY_REG(770, 18) -#define IGP3_KMRN_EC_DIS_INBAND 0x0080 - -#define IGP03E1000_E_PHY_ID 0x02A80390 -#define IFE_E_PHY_ID 0x02A80330 /* 10/100 PHY */ -#define IFE_PLUS_E_PHY_ID 0x02A80320 -#define IFE_C_E_PHY_ID 0x02A80310 - -#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 /* 100BaseTx Extended Status, Control and Address */ -#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY special control register */ -#define IFE_PHY_RCV_FALSE_CARRIER 0x13 /* 100BaseTx Receive False Carrier Counter */ -#define IFE_PHY_RCV_DISCONNECT 0x14 /* 100BaseTx Receive Disconnect Counter */ -#define IFE_PHY_RCV_ERROT_FRAME 0x15 /* 100BaseTx Receive Error Frame Counter */ -#define IFE_PHY_RCV_SYMBOL_ERR 0x16 /* Receive Symbol Error Counter */ -#define IFE_PHY_PREM_EOF_ERR 0x17 /* 100BaseTx Receive Premature End Of Frame Error Counter */ -#define IFE_PHY_RCV_EOF_ERR 0x18 /* 10BaseT Receive End Of Frame Error Counter */ -#define IFE_PHY_TX_JABBER_DETECT 0x19 /* 10BaseT Transmit Jabber Detect Counter */ -#define IFE_PHY_EQUALIZER 0x1A /* PHY Equalizer Control and Status */ -#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY special control and LED configuration */ -#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control register */ -#define IFE_PHY_HWI_CONTROL 0x1D /* Hardware Integrity Control (HWI) */ - -#define IFE_PESC_REDUCED_POWER_DOWN_DISABLE 0x2000 /* Default 1 = Disable auto reduced power down */ -#define IFE_PESC_100BTX_POWER_DOWN 0x0400 /* Indicates the power state of 100BASE-TX */ -#define IFE_PESC_10BTX_POWER_DOWN 0x0200 /* Indicates the power state of 10BASE-T */ -#define IFE_PESC_POLARITY_REVERSED 0x0100 /* Indicates 10BASE-T polarity */ -#define IFE_PESC_PHY_ADDR_MASK 0x007C /* Bit 6:2 for sampled PHY address */ -#define IFE_PESC_SPEED 0x0002 /* Auto-negotiation speed result 1=100Mbs, 0=10Mbs */ -#define IFE_PESC_DUPLEX 0x0001 /* Auto-negotiation duplex result 1=Full, 0=Half */ -#define IFE_PESC_POLARITY_REVERSED_SHIFT 8 - -#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100 /* 1 = Dynamic Power Down disabled */ -#define IFE_PSC_FORCE_POLARITY 0x0020 /* 1=Reversed Polarity, 0=Normal */ -#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 /* 1=Auto Polarity Disabled, 0=Enabled */ -#define IFE_PSC_JABBER_FUNC_DISABLE 0x0001 /* 1=Jabber Disabled, 0=Normal Jabber Operation */ -#define IFE_PSC_FORCE_POLARITY_SHIFT 5 -#define IFE_PSC_AUTO_POLARITY_DISABLE_SHIFT 4 - -#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable MDI/MDI-X feature, default 0=disabled */ -#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDIX-X, 0=force MDI */ -#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ -#define IFE_PMC_AUTO_MDIX_COMPLETE 0x0010 /* Resolution algorithm is completed */ -#define IFE_PMC_MDIX_MODE_SHIFT 6 -#define IFE_PHC_MDIX_RESET_ALL_MASK 0x0000 /* Disable auto MDI-X */ - -#define IFE_PHC_HWI_ENABLE 0x8000 /* Enable the HWI feature */ -#define IFE_PHC_ABILITY_CHECK 0x4000 /* 1= Test Passed, 0=failed */ -#define IFE_PHC_TEST_EXEC 0x2000 /* PHY launch test pulses on the wire */ -#define IFE_PHC_HIGHZ 0x0200 /* 1 = Open Circuit */ -#define IFE_PHC_LOWZ 0x0400 /* 1 = Short Circuit */ -#define IFE_PHC_LOW_HIGH_Z_MASK 0x0600 /* Mask for indication type of problem on the line */ -#define IFE_PHC_DISTANCE_MASK 0x01FF /* Mask for distance to the cable problem, in 80cm granularity */ -#define IFE_PHC_RESET_ALL_MASK 0x0000 /* Disable HWI */ -#define IFE_PSCL_PROBE_MODE 0x0020 /* LED Probe mode */ -#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ -#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ - -#define ICH_FLASH_COMMAND_TIMEOUT 5000 /* 5000 uSecs - adjusted */ -#define ICH_FLASH_ERASE_TIMEOUT 3000000 /* Up to 3 seconds - worst case */ -#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 /* 10 cycles */ -#define ICH_FLASH_SEG_SIZE_256 256 -#define ICH_FLASH_SEG_SIZE_4K 4096 -#define ICH_FLASH_SEG_SIZE_64K 65536 - -#define ICH_CYCLE_READ 0x0 -#define ICH_CYCLE_RESERVED 0x1 -#define ICH_CYCLE_WRITE 0x2 -#define ICH_CYCLE_ERASE 0x3 - -#define ICH_FLASH_GFPREG 0x0000 -#define ICH_FLASH_HSFSTS 0x0004 -#define ICH_FLASH_HSFCTL 0x0006 -#define ICH_FLASH_FADDR 0x0008 -#define ICH_FLASH_FDATA0 0x0010 -#define ICH_FLASH_FRACC 0x0050 -#define ICH_FLASH_FREG0 0x0054 -#define ICH_FLASH_FREG1 0x0058 -#define ICH_FLASH_FREG2 0x005C -#define ICH_FLASH_FREG3 0x0060 -#define ICH_FLASH_FPR0 0x0074 -#define ICH_FLASH_FPR1 0x0078 -#define ICH_FLASH_SSFSTS 0x0090 -#define ICH_FLASH_SSFCTL 0x0092 -#define ICH_FLASH_PREOP 0x0094 -#define ICH_FLASH_OPTYPE 0x0096 -#define ICH_FLASH_OPMENU 0x0098 - -#define ICH_FLASH_REG_MAPSIZE 0x00A0 -#define ICH_FLASH_SECTOR_SIZE 4096 -#define ICH_GFPREG_BASE_MASK 0x1FFF -#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF - -/* Miscellaneous PHY bit definitions. */ -#define PHY_PREAMBLE 0xFFFFFFFF -#define PHY_SOF 0x01 -#define PHY_OP_READ 0x02 -#define PHY_OP_WRITE 0x01 -#define PHY_TURNAROUND 0x02 -#define PHY_PREAMBLE_SIZE 32 -#define MII_CR_SPEED_1000 0x0040 -#define MII_CR_SPEED_100 0x2000 -#define MII_CR_SPEED_10 0x0000 -#define E1000_PHY_ADDRESS 0x01 -#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */ -#define PHY_FORCE_TIME 20 /* 2.0 Seconds */ -#define PHY_REVISION_MASK 0xFFFFFFF0 -#define DEVICE_SPEED_MASK 0x00000300 /* Device Ctrl Reg Speed Mask */ -#define REG4_SPEED_MASK 0x01E0 -#define REG9_SPEED_MASK 0x0300 -#define ADVERTISE_10_HALF 0x0001 -#define ADVERTISE_10_FULL 0x0002 -#define ADVERTISE_100_HALF 0x0004 -#define ADVERTISE_100_FULL 0x0008 -#define ADVERTISE_1000_HALF 0x0010 -#define ADVERTISE_1000_FULL 0x0020 -#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* Everything but 1000-Half */ -#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds */ -#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds */ - -#endif /* _E1000_HW_H_ */ diff --git a/addons/e1000/src/3.10.108/e1000_main.c b/addons/e1000/src/3.10.108/e1000_main.c deleted file mode 100644 index a978fc82..00000000 --- a/addons/e1000/src/3.10.108/e1000_main.c +++ /dev/null @@ -1,5226 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include "e1000.h" -#include -#include -#include -#include -#include - -char e1000_driver_name[] = "e1000"; -static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -#define DRV_VERSION "7.3.21-k8-NAPI" -const char e1000_driver_version[] = DRV_VERSION; -static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; - -/* e1000_pci_tbl - PCI Device ID Table - * - * Last entry must be all 0s - * - * Macro expands to... - * {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} - */ -static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { - INTEL_E1000_ETHERNET_DEVICE(0x1000), - INTEL_E1000_ETHERNET_DEVICE(0x1001), - INTEL_E1000_ETHERNET_DEVICE(0x1004), - INTEL_E1000_ETHERNET_DEVICE(0x1008), - INTEL_E1000_ETHERNET_DEVICE(0x1009), - INTEL_E1000_ETHERNET_DEVICE(0x100C), - INTEL_E1000_ETHERNET_DEVICE(0x100D), - INTEL_E1000_ETHERNET_DEVICE(0x100E), - INTEL_E1000_ETHERNET_DEVICE(0x100F), - INTEL_E1000_ETHERNET_DEVICE(0x1010), - INTEL_E1000_ETHERNET_DEVICE(0x1011), - INTEL_E1000_ETHERNET_DEVICE(0x1012), - INTEL_E1000_ETHERNET_DEVICE(0x1013), - INTEL_E1000_ETHERNET_DEVICE(0x1014), - INTEL_E1000_ETHERNET_DEVICE(0x1015), - INTEL_E1000_ETHERNET_DEVICE(0x1016), - INTEL_E1000_ETHERNET_DEVICE(0x1017), - INTEL_E1000_ETHERNET_DEVICE(0x1018), - INTEL_E1000_ETHERNET_DEVICE(0x1019), - INTEL_E1000_ETHERNET_DEVICE(0x101A), - INTEL_E1000_ETHERNET_DEVICE(0x101D), - INTEL_E1000_ETHERNET_DEVICE(0x101E), - INTEL_E1000_ETHERNET_DEVICE(0x1026), - INTEL_E1000_ETHERNET_DEVICE(0x1027), - INTEL_E1000_ETHERNET_DEVICE(0x1028), - INTEL_E1000_ETHERNET_DEVICE(0x1075), - INTEL_E1000_ETHERNET_DEVICE(0x1076), - INTEL_E1000_ETHERNET_DEVICE(0x1077), - INTEL_E1000_ETHERNET_DEVICE(0x1078), - INTEL_E1000_ETHERNET_DEVICE(0x1079), - INTEL_E1000_ETHERNET_DEVICE(0x107A), - INTEL_E1000_ETHERNET_DEVICE(0x107B), - INTEL_E1000_ETHERNET_DEVICE(0x107C), - INTEL_E1000_ETHERNET_DEVICE(0x108A), - INTEL_E1000_ETHERNET_DEVICE(0x1099), - INTEL_E1000_ETHERNET_DEVICE(0x10B5), - INTEL_E1000_ETHERNET_DEVICE(0x2E6E), - /* required last entry */ - {0,} -}; - -MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); - -int e1000_up(struct e1000_adapter *adapter); -void e1000_down(struct e1000_adapter *adapter); -void e1000_reinit_locked(struct e1000_adapter *adapter); -void e1000_reset(struct e1000_adapter *adapter); -int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); -int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); -void e1000_free_all_tx_resources(struct e1000_adapter *adapter); -void e1000_free_all_rx_resources(struct e1000_adapter *adapter); -static int e1000_setup_tx_resources(struct e1000_adapter *adapter, - struct e1000_tx_ring *txdr); -static int e1000_setup_rx_resources(struct e1000_adapter *adapter, - struct e1000_rx_ring *rxdr); -static void e1000_free_tx_resources(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring); -static void e1000_free_rx_resources(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring); -void e1000_update_stats(struct e1000_adapter *adapter); - -static int e1000_init_module(void); -static void e1000_exit_module(void); -static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent); -static void e1000_remove(struct pci_dev *pdev); -static int e1000_alloc_queues(struct e1000_adapter *adapter); -static int e1000_sw_init(struct e1000_adapter *adapter); -static int e1000_open(struct net_device *netdev); -static int e1000_close(struct net_device *netdev); -static void e1000_configure_tx(struct e1000_adapter *adapter); -static void e1000_configure_rx(struct e1000_adapter *adapter); -static void e1000_setup_rctl(struct e1000_adapter *adapter); -static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter); -static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter); -static void e1000_clean_tx_ring(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring); -static void e1000_clean_rx_ring(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring); -static void e1000_set_rx_mode(struct net_device *netdev); -static void e1000_update_phy_info_task(struct work_struct *work); -static void e1000_watchdog(struct work_struct *work); -static void e1000_82547_tx_fifo_stall_task(struct work_struct *work); -static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, - struct net_device *netdev); -static struct net_device_stats * e1000_get_stats(struct net_device *netdev); -static int e1000_change_mtu(struct net_device *netdev, int new_mtu); -static int e1000_set_mac(struct net_device *netdev, void *p); -static irqreturn_t e1000_intr(int irq, void *data); -static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring); -static int e1000_clean(struct napi_struct *napi, int budget); -static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int *work_done, int work_to_do); -static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int *work_done, int work_to_do); -static void e1000_alloc_dummy_rx_buffers(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count) -{ -} -static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count); -static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count); -static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); -static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, - int cmd); -static void e1000_enter_82542_rst(struct e1000_adapter *adapter); -static void e1000_leave_82542_rst(struct e1000_adapter *adapter); -static void e1000_tx_timeout(struct net_device *dev); -static void e1000_reset_task(struct work_struct *work); -static void e1000_smartspeed(struct e1000_adapter *adapter); -static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, - struct sk_buff *skb); - -static bool e1000_vlan_used(struct e1000_adapter *adapter); -static void e1000_vlan_mode(struct net_device *netdev, - netdev_features_t features); -static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter, - bool filter_on); -static int e1000_vlan_rx_add_vid(struct net_device *netdev, - __be16 proto, u16 vid); -static int e1000_vlan_rx_kill_vid(struct net_device *netdev, - __be16 proto, u16 vid); -static void e1000_restore_vlan(struct e1000_adapter *adapter); - -#ifdef CONFIG_PM -static int e1000_suspend(struct pci_dev *pdev, pm_message_t state); -static int e1000_resume(struct pci_dev *pdev); -#endif -static void e1000_shutdown(struct pci_dev *pdev); - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* for netdump / net console */ -static void e1000_netpoll (struct net_device *netdev); -#endif - -#define COPYBREAK_DEFAULT 256 -static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT; -module_param(copybreak, uint, 0644); -MODULE_PARM_DESC(copybreak, - "Maximum size of packet that is copied to a new buffer on receive"); - -static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, - pci_channel_state_t state); -static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev); -static void e1000_io_resume(struct pci_dev *pdev); - -static const struct pci_error_handlers e1000_err_handler = { - .error_detected = e1000_io_error_detected, - .slot_reset = e1000_io_slot_reset, - .resume = e1000_io_resume, -}; - -static struct pci_driver e1000_driver = { - .name = e1000_driver_name, - .id_table = e1000_pci_tbl, - .probe = e1000_probe, - .remove = e1000_remove, -#ifdef CONFIG_PM - /* Power Management Hooks */ - .suspend = e1000_suspend, - .resume = e1000_resume, -#endif - .shutdown = e1000_shutdown, - .err_handler = &e1000_err_handler -}; - -MODULE_AUTHOR("Intel Corporation, "); -MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) -static int debug = -1; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); - -/** - * e1000_get_hw_dev - return device - * used by hardware layer to print debugging information - * - **/ -struct net_device *e1000_get_hw_dev(struct e1000_hw *hw) -{ - struct e1000_adapter *adapter = hw->back; - return adapter->netdev; -} - -/** - * e1000_init_module - Driver Registration Routine - * - * e1000_init_module is the first routine called when the driver is - * loaded. All it does is register with the PCI subsystem. - **/ -static int __init e1000_init_module(void) -{ - int ret; - pr_info("%s - version %s\n", e1000_driver_string, e1000_driver_version); - - pr_info("%s\n", e1000_copyright); - - ret = pci_register_driver(&e1000_driver); - if (copybreak != COPYBREAK_DEFAULT) { - if (copybreak == 0) - pr_info("copybreak disabled\n"); - else - pr_info("copybreak enabled for " - "packets <= %u bytes\n", copybreak); - } - return ret; -} - -module_init(e1000_init_module); - -/** - * e1000_exit_module - Driver Exit Cleanup Routine - * - * e1000_exit_module is called just before the driver is removed - * from memory. - **/ -static void __exit e1000_exit_module(void) -{ - pci_unregister_driver(&e1000_driver); -} - -module_exit(e1000_exit_module); - -static int e1000_request_irq(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - irq_handler_t handler = e1000_intr; - int irq_flags = IRQF_SHARED; - int err; - - err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name, - netdev); - if (err) { - e_err(probe, "Unable to allocate interrupt Error: %d\n", err); - } - - return err; -} - -static void e1000_free_irq(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - free_irq(adapter->pdev->irq, netdev); -} - -/** - * e1000_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - **/ -static void e1000_irq_disable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - ew32(IMC, ~0); - E1000_WRITE_FLUSH(); - synchronize_irq(adapter->pdev->irq); -} - -/** - * e1000_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - **/ -static void e1000_irq_enable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - ew32(IMS, IMS_ENABLE_MASK); - E1000_WRITE_FLUSH(); -} - -static void e1000_update_mng_vlan(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - u16 vid = hw->mng_cookie.vlan_id; - u16 old_vid = adapter->mng_vlan_id; - - if (!e1000_vlan_used(adapter)) - return; - - if (!test_bit(vid, adapter->active_vlans)) { - if (hw->mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) { - e1000_vlan_rx_add_vid(netdev, htons(ETH_P_8021Q), vid); - adapter->mng_vlan_id = vid; - } else { - adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; - } - if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && - (vid != old_vid) && - !test_bit(old_vid, adapter->active_vlans)) - e1000_vlan_rx_kill_vid(netdev, htons(ETH_P_8021Q), - old_vid); - } else { - adapter->mng_vlan_id = vid; - } -} - -static void e1000_init_manageability(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - if (adapter->en_mng_pt) { - u32 manc = er32(MANC); - - /* disable hardware interception of ARP */ - manc &= ~(E1000_MANC_ARP_EN); - - ew32(MANC, manc); - } -} - -static void e1000_release_manageability(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - if (adapter->en_mng_pt) { - u32 manc = er32(MANC); - - /* re-enable hardware interception of ARP */ - manc |= E1000_MANC_ARP_EN; - - ew32(MANC, manc); - } -} - -/** - * e1000_configure - configure the hardware for RX and TX - * @adapter = private board structure - **/ -static void e1000_configure(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - int i; - - e1000_set_rx_mode(netdev); - - e1000_restore_vlan(adapter); - e1000_init_manageability(adapter); - - e1000_configure_tx(adapter); - e1000_setup_rctl(adapter); - e1000_configure_rx(adapter); - /* call E1000_DESC_UNUSED which always leaves - * at least 1 descriptor unused to make sure - * next_to_use != next_to_clean - */ - for (i = 0; i < adapter->num_rx_queues; i++) { - struct e1000_rx_ring *ring = &adapter->rx_ring[i]; - adapter->alloc_rx_buf(adapter, ring, - E1000_DESC_UNUSED(ring)); - } -} - -int e1000_up(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - /* hardware has been reset, we need to reload some things */ - e1000_configure(adapter); - - clear_bit(__E1000_DOWN, &adapter->flags); - - napi_enable(&adapter->napi); - - e1000_irq_enable(adapter); - - netif_wake_queue(adapter->netdev); - - /* fire a link change interrupt to start the watchdog */ - ew32(ICS, E1000_ICS_LSC); - return 0; -} - -/** - * e1000_power_up_phy - restore link in case the phy was powered down - * @adapter: address of board private structure - * - * The phy may be powered down to save power and turn off link when the - * driver is unloaded and wake on lan is not enabled (among others) - * *** this routine MUST be followed by a call to e1000_reset *** - **/ -void e1000_power_up_phy(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u16 mii_reg = 0; - - /* Just clear the power down bit to wake the phy back up */ - if (hw->media_type == e1000_media_type_copper) { - /* according to the manual, the phy will retain its - * settings across a power-down/up cycle - */ - e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg); - mii_reg &= ~MII_CR_POWER_DOWN; - e1000_write_phy_reg(hw, PHY_CTRL, mii_reg); - } -} - -static void e1000_power_down_phy(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - /* Power down the PHY so no link is implied when interface is down * - * The PHY cannot be powered down if any of the following is true * - * (a) WoL is enabled - * (b) AMT is active - * (c) SoL/IDER session is active - */ - if (!adapter->wol && hw->mac_type >= e1000_82540 && - hw->media_type == e1000_media_type_copper) { - u16 mii_reg = 0; - - switch (hw->mac_type) { - case e1000_82540: - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_ce4100: - case e1000_82546_rev_3: - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - if (er32(MANC) & E1000_MANC_SMBUS_EN) - goto out; - break; - default: - goto out; - } - e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg); - mii_reg |= MII_CR_POWER_DOWN; - e1000_write_phy_reg(hw, PHY_CTRL, mii_reg); - msleep(1); - } -out: - return; -} - -static void e1000_down_and_stop(struct e1000_adapter *adapter) -{ - set_bit(__E1000_DOWN, &adapter->flags); - - /* Only kill reset task if adapter is not resetting */ - if (!test_bit(__E1000_RESETTING, &adapter->flags)) - cancel_work_sync(&adapter->reset_task); - - cancel_delayed_work_sync(&adapter->watchdog_task); - cancel_delayed_work_sync(&adapter->phy_info_task); - cancel_delayed_work_sync(&adapter->fifo_stall_task); -} - -void e1000_down(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - u32 rctl, tctl; - - - /* disable receives in the hardware */ - rctl = er32(RCTL); - ew32(RCTL, rctl & ~E1000_RCTL_EN); - /* flush and sleep below */ - - netif_tx_disable(netdev); - - /* disable transmits in the hardware */ - tctl = er32(TCTL); - tctl &= ~E1000_TCTL_EN; - ew32(TCTL, tctl); - /* flush both disables and wait for them to finish */ - E1000_WRITE_FLUSH(); - msleep(10); - - napi_disable(&adapter->napi); - - e1000_irq_disable(adapter); - - /* Setting DOWN must be after irq_disable to prevent - * a screaming interrupt. Setting DOWN also prevents - * tasks from rescheduling. - */ - e1000_down_and_stop(adapter); - - adapter->link_speed = 0; - adapter->link_duplex = 0; - netif_carrier_off(netdev); - - e1000_reset(adapter); - e1000_clean_all_tx_rings(adapter); - e1000_clean_all_rx_rings(adapter); -} - -static void e1000_reinit_safe(struct e1000_adapter *adapter) -{ - while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) - msleep(1); - mutex_lock(&adapter->mutex); - e1000_down(adapter); - e1000_up(adapter); - mutex_unlock(&adapter->mutex); - clear_bit(__E1000_RESETTING, &adapter->flags); -} - -void e1000_reinit_locked(struct e1000_adapter *adapter) -{ - /* if rtnl_lock is not held the call path is bogus */ - ASSERT_RTNL(); - WARN_ON(in_interrupt()); - while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) - msleep(1); - e1000_down(adapter); - e1000_up(adapter); - clear_bit(__E1000_RESETTING, &adapter->flags); -} - -void e1000_reset(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 pba = 0, tx_space, min_tx_space, min_rx_space; - bool legacy_pba_adjust = false; - u16 hwm; - - /* Repartition Pba for greater than 9k mtu - * To take effect CTRL.RST is required. - */ - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - case e1000_82540: - case e1000_82541: - case e1000_82541_rev_2: - legacy_pba_adjust = true; - pba = E1000_PBA_48K; - break; - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_ce4100: - case e1000_82546_rev_3: - pba = E1000_PBA_48K; - break; - case e1000_82547: - case e1000_82547_rev_2: - legacy_pba_adjust = true; - pba = E1000_PBA_30K; - break; - case e1000_undefined: - case e1000_num_macs: - break; - } - - if (legacy_pba_adjust) { - if (hw->max_frame_size > E1000_RXBUFFER_8192) - pba -= 8; /* allocate more FIFO for Tx */ - - if (hw->mac_type == e1000_82547) { - adapter->tx_fifo_head = 0; - adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT; - adapter->tx_fifo_size = - (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT; - atomic_set(&adapter->tx_fifo_stall, 0); - } - } else if (hw->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) { - /* adjust PBA for jumbo frames */ - ew32(PBA, pba); - - /* To maintain wire speed transmits, the Tx FIFO should be - * large enough to accommodate two full transmit packets, - * rounded up to the next 1KB and expressed in KB. Likewise, - * the Rx FIFO should be large enough to accommodate at least - * one full receive packet and is similarly rounded up and - * expressed in KB. - */ - pba = er32(PBA); - /* upper 16 bits has Tx packet buffer allocation size in KB */ - tx_space = pba >> 16; - /* lower 16 bits has Rx packet buffer allocation size in KB */ - pba &= 0xffff; - /* the Tx fifo also stores 16 bytes of information about the Tx - * but don't include ethernet FCS because hardware appends it - */ - min_tx_space = (hw->max_frame_size + - sizeof(struct e1000_tx_desc) - - ETH_FCS_LEN) * 2; - min_tx_space = ALIGN(min_tx_space, 1024); - min_tx_space >>= 10; - /* software strips receive CRC, so leave room for it */ - min_rx_space = hw->max_frame_size; - min_rx_space = ALIGN(min_rx_space, 1024); - min_rx_space >>= 10; - - /* If current Tx allocation is less than the min Tx FIFO size, - * and the min Tx FIFO size is less than the current Rx FIFO - * allocation, take space away from current Rx allocation - */ - if (tx_space < min_tx_space && - ((min_tx_space - tx_space) < pba)) { - pba = pba - (min_tx_space - tx_space); - - /* PCI/PCIx hardware has PBA alignment constraints */ - switch (hw->mac_type) { - case e1000_82545 ... e1000_82546_rev_3: - pba &= ~(E1000_PBA_8K - 1); - break; - default: - break; - } - - /* if short on Rx space, Rx wins and must trump Tx - * adjustment or use Early Receive if available - */ - if (pba < min_rx_space) - pba = min_rx_space; - } - } - - ew32(PBA, pba); - - /* flow control settings: - * The high water mark must be low enough to fit one full frame - * (or the size used for early receive) above it in the Rx FIFO. - * Set it to the lower of: - * - 90% of the Rx FIFO size, and - * - the full Rx FIFO size minus the early receive size (for parts - * with ERT support assuming ERT set to E1000_ERT_2048), or - * - the full Rx FIFO size minus one full frame - */ - hwm = min(((pba << 10) * 9 / 10), - ((pba << 10) - hw->max_frame_size)); - - hw->fc_high_water = hwm & 0xFFF8; /* 8-byte granularity */ - hw->fc_low_water = hw->fc_high_water - 8; - hw->fc_pause_time = E1000_FC_PAUSE_TIME; - hw->fc_send_xon = 1; - hw->fc = hw->original_fc; - - /* Allow time for pending master requests to run */ - e1000_reset_hw(hw); - if (hw->mac_type >= e1000_82544) - ew32(WUC, 0); - - if (e1000_init_hw(hw)) - e_dev_err("Hardware Error\n"); - e1000_update_mng_vlan(adapter); - - /* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */ - if (hw->mac_type >= e1000_82544 && - hw->autoneg == 1 && - hw->autoneg_advertised == ADVERTISE_1000_FULL) { - u32 ctrl = er32(CTRL); - /* clear phy power management bit if we are in gig only mode, - * which if enabled will attempt negotiation to 100Mb, which - * can cause a loss of link at power off or driver unload - */ - ctrl &= ~E1000_CTRL_SWDPIN3; - ew32(CTRL, ctrl); - } - - /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ - ew32(VET, ETHERNET_IEEE_VLAN_TYPE); - - e1000_reset_adaptive(hw); - e1000_phy_get_info(hw, &adapter->phy_info); - - e1000_release_manageability(adapter); -} - -/* Dump the eeprom for users having checksum issues */ -static void e1000_dump_eeprom(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct ethtool_eeprom eeprom; - const struct ethtool_ops *ops = netdev->ethtool_ops; - u8 *data; - int i; - u16 csum_old, csum_new = 0; - - eeprom.len = ops->get_eeprom_len(netdev); - eeprom.offset = 0; - - data = kmalloc(eeprom.len, GFP_KERNEL); - if (!data) - return; - - ops->get_eeprom(netdev, &eeprom, data); - - csum_old = (data[EEPROM_CHECKSUM_REG * 2]) + - (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8); - for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2) - csum_new += data[i] + (data[i + 1] << 8); - csum_new = EEPROM_SUM - csum_new; - - pr_err("/*********************/\n"); - pr_err("Current EEPROM Checksum : 0x%04x\n", csum_old); - pr_err("Calculated : 0x%04x\n", csum_new); - - pr_err("Offset Values\n"); - pr_err("======== ======\n"); - print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0); - - pr_err("Include this output when contacting your support provider.\n"); - pr_err("This is not a software error! Something bad happened to\n"); - pr_err("your hardware or EEPROM image. Ignoring this problem could\n"); - pr_err("result in further problems, possibly loss of data,\n"); - pr_err("corruption or system hangs!\n"); - pr_err("The MAC Address will be reset to 00:00:00:00:00:00,\n"); - pr_err("which is invalid and requires you to set the proper MAC\n"); - pr_err("address manually before continuing to enable this network\n"); - pr_err("device. Please inspect the EEPROM dump and report the\n"); - pr_err("issue to your hardware vendor or Intel Customer Support.\n"); - pr_err("/*********************/\n"); - - kfree(data); -} - -/** - * e1000_is_need_ioport - determine if an adapter needs ioport resources or not - * @pdev: PCI device information struct - * - * Return true if an adapter needs ioport resources - **/ -static int e1000_is_need_ioport(struct pci_dev *pdev) -{ - switch (pdev->device) { - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EI_MOBILE: - case E1000_DEV_ID_82541ER: - case E1000_DEV_ID_82541ER_LOM: - case E1000_DEV_ID_82541GI: - case E1000_DEV_ID_82541GI_LF: - case E1000_DEV_ID_82541GI_MOBILE: - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - return true; - default: - return false; - } -} - -static netdev_features_t e1000_fix_features(struct net_device *netdev, - netdev_features_t 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_CTAG_RX) - features |= NETIF_F_HW_VLAN_CTAG_TX; - else - features &= ~NETIF_F_HW_VLAN_CTAG_TX; - - return features; -} - -static int e1000_set_features(struct net_device *netdev, - netdev_features_t features) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - netdev_features_t changed = features ^ netdev->features; - - if (changed & NETIF_F_HW_VLAN_CTAG_RX) - e1000_vlan_mode(netdev, features); - - if (!(changed & (NETIF_F_RXCSUM | NETIF_F_RXALL))) - return 0; - - netdev->features = features; - adapter->rx_csum = !!(features & NETIF_F_RXCSUM); - - if (netif_running(netdev)) - e1000_reinit_locked(adapter); - else - e1000_reset(adapter); - - return 0; -} - -static const struct net_device_ops e1000_netdev_ops = { - .ndo_open = e1000_open, - .ndo_stop = e1000_close, - .ndo_start_xmit = e1000_xmit_frame, - .ndo_get_stats = e1000_get_stats, - .ndo_set_rx_mode = e1000_set_rx_mode, - .ndo_set_mac_address = e1000_set_mac, - .ndo_tx_timeout = e1000_tx_timeout, - .ndo_change_mtu = e1000_change_mtu, - .ndo_do_ioctl = e1000_ioctl, - .ndo_validate_addr = eth_validate_addr, - .ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = e1000_vlan_rx_kill_vid, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e1000_netpoll, -#endif - .ndo_fix_features = e1000_fix_features, - .ndo_set_features = e1000_set_features, -}; - -/** - * e1000_init_hw_struct - initialize members of hw struct - * @adapter: board private struct - * @hw: structure used by e1000_hw.c - * - * Factors out initialization of the e1000_hw struct to its own function - * that can be called very early at init (just after struct allocation). - * Fields are initialized based on PCI device information and - * OS network device settings (MTU size). - * Returns negative error codes if MAC type setup fails. - */ -static int e1000_init_hw_struct(struct e1000_adapter *adapter, - struct e1000_hw *hw) -{ - struct pci_dev *pdev = adapter->pdev; - - /* PCI config space info */ - hw->vendor_id = pdev->vendor; - hw->device_id = pdev->device; - hw->subsystem_vendor_id = pdev->subsystem_vendor; - hw->subsystem_id = pdev->subsystem_device; - hw->revision_id = pdev->revision; - - pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); - - hw->max_frame_size = adapter->netdev->mtu + - ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; - - /* identify the MAC */ - if (e1000_set_mac_type(hw)) { - e_err(probe, "Unknown MAC Type\n"); - return -EIO; - } - - switch (hw->mac_type) { - default: - break; - case e1000_82541: - case e1000_82547: - case e1000_82541_rev_2: - case e1000_82547_rev_2: - hw->phy_init_script = 1; - break; - } - - e1000_set_media_type(hw); - e1000_get_bus_info(hw); - - hw->wait_autoneg_complete = false; - hw->tbi_compatibility_en = true; - hw->adaptive_ifs = true; - - /* Copper options */ - - if (hw->media_type == e1000_media_type_copper) { - hw->mdix = AUTO_ALL_MODES; - hw->disable_polarity_correction = false; - hw->master_slave = E1000_MASTER_SLAVE; - } - - return 0; -} - -/** - * e1000_probe - Device Initialization Routine - * @pdev: PCI device information struct - * @ent: entry in e1000_pci_tbl - * - * Returns 0 on success, negative on failure - * - * e1000_probe initializes an adapter identified by a pci_dev structure. - * The OS initialization, configuring of the adapter private structure, - * and a hardware reset occur. - **/ -static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct e1000_adapter *adapter; - struct e1000_hw *hw; - - static int cards_found = 0; - static int global_quad_port_a = 0; /* global ksp3 port a indication */ - int i, err, pci_using_dac; - u16 eeprom_data = 0; - u16 tmp = 0; - u16 eeprom_apme_mask = E1000_EEPROM_APME; - int bars, need_ioport; - - /* do not allocate ioport bars when not needed */ - need_ioport = e1000_is_need_ioport(pdev); - if (need_ioport) { - bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO); - err = pci_enable_device(pdev); - } else { - bars = pci_select_bars(pdev, IORESOURCE_MEM); - err = pci_enable_device_mem(pdev); - } - if (err) - return err; - - err = pci_request_selected_regions(pdev, bars, e1000_driver_name); - if (err) - goto err_pci_reg; - - pci_set_master(pdev); - err = pci_save_state(pdev); - if (err) - goto err_alloc_etherdev; - - err = -ENOMEM; - netdev = alloc_etherdev(sizeof(struct e1000_adapter)); - if (!netdev) - goto err_alloc_etherdev; - - SET_NETDEV_DEV(netdev, &pdev->dev); - - pci_set_drvdata(pdev, netdev); - adapter = netdev_priv(netdev); - adapter->netdev = netdev; - adapter->pdev = pdev; - adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); - adapter->bars = bars; - adapter->need_ioport = need_ioport; - - hw = &adapter->hw; - hw->back = adapter; - - err = -EIO; - hw->hw_addr = pci_ioremap_bar(pdev, BAR_0); - if (!hw->hw_addr) - goto err_ioremap; - - if (adapter->need_ioport) { - for (i = BAR_1; i <= BAR_5; i++) { - if (pci_resource_len(pdev, i) == 0) - continue; - if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { - hw->io_base = pci_resource_start(pdev, i); - break; - } - } - } - - /* make ready for any if (hw->...) below */ - err = e1000_init_hw_struct(adapter, hw); - if (err) - goto err_sw_init; - - /* there is a workaround being applied below that limits - * 64-bit DMA addresses to 64-bit hardware. There are some - * 32-bit adapters that Tx hang when given 64-bit DMA addresses - */ - pci_using_dac = 0; - if ((hw->bus_type == e1000_bus_type_pcix) && - !dma_set_mask(&pdev->dev, DMA_BIT_MASK(64))) { - /* according to DMA-API-HOWTO, coherent calls will always - * succeed if the set call did - */ - dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); - pci_using_dac = 1; - } else { - err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (err) { - pr_err("No usable DMA config, aborting\n"); - goto err_dma; - } - dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32)); - } - - netdev->netdev_ops = &e1000_netdev_ops; - e1000_set_ethtool_ops(netdev); - netdev->watchdog_timeo = 5 * HZ; - netif_napi_add(netdev, &adapter->napi, e1000_clean, 64); - - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - adapter->bd_number = cards_found; - - /* setup the private structure */ - - err = e1000_sw_init(adapter); - if (err) - goto err_sw_init; - - err = -EIO; - if (hw->mac_type == e1000_ce4100) { - hw->ce4100_gbe_mdio_base_virt = - ioremap(pci_resource_start(pdev, BAR_1), - pci_resource_len(pdev, BAR_1)); - - if (!hw->ce4100_gbe_mdio_base_virt) - goto err_mdio_ioremap; - } - - if (hw->mac_type >= e1000_82543) { - netdev->hw_features = NETIF_F_SG | - NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_CTAG_RX; - netdev->features = NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_FILTER; - } - - if ((hw->mac_type >= e1000_82544) && - (hw->mac_type != e1000_82547)) - netdev->hw_features |= NETIF_F_TSO; - - netdev->priv_flags |= IFF_SUPP_NOFCS; - - netdev->features |= netdev->hw_features; - netdev->hw_features |= (NETIF_F_RXCSUM | - NETIF_F_RXALL | - NETIF_F_RXFCS); - - if (pci_using_dac) { - netdev->features |= NETIF_F_HIGHDMA; - netdev->vlan_features |= NETIF_F_HIGHDMA; - } - - netdev->vlan_features |= (NETIF_F_TSO | - NETIF_F_HW_CSUM | - NETIF_F_SG); - - netdev->priv_flags |= IFF_UNICAST_FLT; - - adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw); - - /* initialize eeprom parameters */ - if (e1000_init_eeprom_params(hw)) { - e_err(probe, "EEPROM initialization failed\n"); - goto err_eeprom; - } - - /* before reading the EEPROM, reset the controller to - * put the device in a known good starting state - */ - - e1000_reset_hw(hw); - - /* make sure the EEPROM is good */ - if (e1000_validate_eeprom_checksum(hw) < 0) { - e_err(probe, "The EEPROM Checksum Is Not Valid\n"); - e1000_dump_eeprom(adapter); - /* set MAC address to all zeroes to invalidate and temporary - * disable this device for the user. This blocks regular - * traffic while still permitting ethtool ioctls from reaching - * the hardware as well as allowing the user to run the - * interface after manually setting a hw addr using - * `ip set address` - */ - memset(hw->mac_addr, 0, netdev->addr_len); - } else { - /* copy the MAC address out of the EEPROM */ - if (e1000_read_mac_addr(hw)) - e_err(probe, "EEPROM Read Error\n"); - } - /* don't block initalization here due to bad MAC address */ - memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len); - - if (!is_valid_ether_addr(netdev->dev_addr)) - e_err(probe, "Invalid MAC Address\n"); - - - INIT_DELAYED_WORK(&adapter->watchdog_task, e1000_watchdog); - INIT_DELAYED_WORK(&adapter->fifo_stall_task, - e1000_82547_tx_fifo_stall_task); - INIT_DELAYED_WORK(&adapter->phy_info_task, e1000_update_phy_info_task); - INIT_WORK(&adapter->reset_task, e1000_reset_task); - - e1000_check_options(adapter); - - /* Initial Wake on LAN setting - * If APM wake is enabled in the EEPROM, - * enable the ACPI Magic Packet filter - */ - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - break; - case e1000_82544: - e1000_read_eeprom(hw, - EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data); - eeprom_apme_mask = E1000_EEPROM_82544_APM; - break; - case e1000_82546: - case e1000_82546_rev_3: - if (er32(STATUS) & E1000_STATUS_FUNC_1){ - e1000_read_eeprom(hw, - EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); - break; - } - /* Fall Through */ - default: - e1000_read_eeprom(hw, - EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); - break; - } - if (eeprom_data & eeprom_apme_mask) - adapter->eeprom_wol |= E1000_WUFC_MAG; - - /* now that we have the eeprom settings, apply the special cases - * where the eeprom may be wrong or the board simply won't support - * wake on lan on a particular port - */ - switch (pdev->device) { - case E1000_DEV_ID_82546GB_PCIE: - adapter->eeprom_wol = 0; - break; - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546GB_FIBER: - /* Wake events only supported on port A for dual fiber - * regardless of eeprom setting - */ - if (er32(STATUS) & E1000_STATUS_FUNC_1) - adapter->eeprom_wol = 0; - break; - case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: - /* if quad port adapter, disable WoL on all but port A */ - if (global_quad_port_a != 0) - adapter->eeprom_wol = 0; - else - adapter->quad_port_a = true; - /* Reset for multiple quad port adapters */ - if (++global_quad_port_a == 4) - global_quad_port_a = 0; - break; - } - - /* initialize the wol settings based on the eeprom settings */ - adapter->wol = adapter->eeprom_wol; - device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); - - /* Auto detect PHY address */ - if (hw->mac_type == e1000_ce4100) { - for (i = 0; i < 32; i++) { - hw->phy_addr = i; - e1000_read_phy_reg(hw, PHY_ID2, &tmp); - if (tmp == 0 || tmp == 0xFF) { - if (i == 31) - goto err_eeprom; - continue; - } else - break; - } - } - - /* reset the hardware with the new settings */ - e1000_reset(adapter); - - strcpy(netdev->name, "eth%d"); - err = register_netdev(netdev); - if (err) - goto err_register; - - e1000_vlan_filter_on_off(adapter, false); - - /* print bus type/speed/width info */ - e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n", - ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""), - ((hw->bus_speed == e1000_bus_speed_133) ? 133 : - (hw->bus_speed == e1000_bus_speed_120) ? 120 : - (hw->bus_speed == e1000_bus_speed_100) ? 100 : - (hw->bus_speed == e1000_bus_speed_66) ? 66 : 33), - ((hw->bus_width == e1000_bus_width_64) ? 64 : 32), - netdev->dev_addr); - - /* carrier off reporting is important to ethtool even BEFORE open */ - netif_carrier_off(netdev); - - e_info(probe, "Intel(R) PRO/1000 Network Connection\n"); - - cards_found++; - return 0; - -err_register: -err_eeprom: - e1000_phy_hw_reset(hw); - - if (hw->flash_address) - iounmap(hw->flash_address); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); -err_dma: -err_sw_init: -err_mdio_ioremap: - iounmap(hw->ce4100_gbe_mdio_base_virt); - iounmap(hw->hw_addr); -err_ioremap: - free_netdev(netdev); -err_alloc_etherdev: - pci_release_selected_regions(pdev, bars); -err_pci_reg: - pci_disable_device(pdev); - return err; -} - -/** - * e1000_remove - Device Removal Routine - * @pdev: PCI device information struct - * - * e1000_remove is called by the PCI subsystem to alert the driver - * that it should release a PCI device. The could be caused by a - * Hot-Plug event, or because the driver is going to be removed from - * memory. - **/ -static void e1000_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - e1000_down_and_stop(adapter); - e1000_release_manageability(adapter); - - unregister_netdev(netdev); - - e1000_phy_hw_reset(hw); - - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - - if (hw->mac_type == e1000_ce4100) - iounmap(hw->ce4100_gbe_mdio_base_virt); - iounmap(hw->hw_addr); - if (hw->flash_address) - iounmap(hw->flash_address); - pci_release_selected_regions(pdev, adapter->bars); - - free_netdev(netdev); - - pci_disable_device(pdev); -} - -/** - * e1000_sw_init - Initialize general software structures (struct e1000_adapter) - * @adapter: board private structure to initialize - * - * e1000_sw_init initializes the Adapter private data structure. - * e1000_init_hw_struct MUST be called before this function - **/ -static int e1000_sw_init(struct e1000_adapter *adapter) -{ - adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; - - adapter->num_tx_queues = 1; - adapter->num_rx_queues = 1; - - if (e1000_alloc_queues(adapter)) { - e_err(probe, "Unable to allocate memory for queues\n"); - return -ENOMEM; - } - - /* Explicitly disable IRQ since the NIC can be in any state. */ - e1000_irq_disable(adapter); - - spin_lock_init(&adapter->stats_lock); - mutex_init(&adapter->mutex); - - set_bit(__E1000_DOWN, &adapter->flags); - - return 0; -} - -/** - * e1000_alloc_queues - Allocate memory for all rings - * @adapter: board private structure to initialize - * - * We allocate one ring per queue at run-time since we don't know the - * number of queues at compile-time. - **/ -static int e1000_alloc_queues(struct e1000_adapter *adapter) -{ - adapter->tx_ring = kcalloc(adapter->num_tx_queues, - sizeof(struct e1000_tx_ring), GFP_KERNEL); - if (!adapter->tx_ring) - return -ENOMEM; - - adapter->rx_ring = kcalloc(adapter->num_rx_queues, - sizeof(struct e1000_rx_ring), GFP_KERNEL); - if (!adapter->rx_ring) { - kfree(adapter->tx_ring); - return -ENOMEM; - } - - return E1000_SUCCESS; -} - -/** - * e1000_open - Called when a network interface is made active - * @netdev: network interface device structure - * - * Returns 0 on success, negative value on failure - * - * The open entry point is called when a network interface is made - * active by the system (IFF_UP). At this point all resources needed - * for transmit and receive operations are allocated, the interrupt - * handler is registered with the OS, the watchdog task is started, - * and the stack is notified that the interface is ready. - **/ -static int e1000_open(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - int err; - - /* disallow open during test */ - if (test_bit(__E1000_TESTING, &adapter->flags)) - return -EBUSY; - - netif_carrier_off(netdev); - - /* allocate transmit descriptors */ - err = e1000_setup_all_tx_resources(adapter); - if (err) - goto err_setup_tx; - - /* allocate receive descriptors */ - err = e1000_setup_all_rx_resources(adapter); - if (err) - goto err_setup_rx; - - e1000_power_up_phy(adapter); - - adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; - if ((hw->mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { - e1000_update_mng_vlan(adapter); - } - - /* before we allocate an interrupt, we must be ready to handle it. - * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt - * as soon as we call pci_request_irq, so we have to setup our - * clean_rx handler before we do so. - */ - e1000_configure(adapter); - - err = e1000_request_irq(adapter); - if (err) - goto err_req_irq; - - /* From here on the code is the same as e1000_up() */ - clear_bit(__E1000_DOWN, &adapter->flags); - - napi_enable(&adapter->napi); - - e1000_irq_enable(adapter); - - netif_start_queue(netdev); - - /* fire a link status change interrupt to start the watchdog */ - ew32(ICS, E1000_ICS_LSC); - - return E1000_SUCCESS; - -err_req_irq: - e1000_power_down_phy(adapter); - e1000_free_all_rx_resources(adapter); -err_setup_rx: - e1000_free_all_tx_resources(adapter); -err_setup_tx: - e1000_reset(adapter); - - return err; -} - -/** - * e1000_close - Disables a network interface - * @netdev: network interface device structure - * - * Returns 0, this is not allowed to fail - * - * The close entry point is called when an interface is de-activated - * by the OS. The hardware is still under the drivers control, but - * needs to be disabled. A global MAC reset is issued to stop the - * hardware, and all transmit and receive resources are freed. - **/ -static int e1000_close(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); - e1000_down(adapter); - e1000_power_down_phy(adapter); - e1000_free_irq(adapter); - - e1000_free_all_tx_resources(adapter); - e1000_free_all_rx_resources(adapter); - - /* kill manageability vlan ID if supported, but not if a vlan with - * the same ID is registered on the host OS (let 8021q kill it) - */ - if ((hw->mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && - !test_bit(adapter->mng_vlan_id, adapter->active_vlans)) { - e1000_vlan_rx_kill_vid(netdev, htons(ETH_P_8021Q), - adapter->mng_vlan_id); - } - - return 0; -} - -/** - * e1000_check_64k_bound - check that memory doesn't cross 64kB boundary - * @adapter: address of board private structure - * @start: address of beginning of memory - * @len: length of memory - **/ -static bool e1000_check_64k_bound(struct e1000_adapter *adapter, void *start, - unsigned long len) -{ - struct e1000_hw *hw = &adapter->hw; - unsigned long begin = (unsigned long)start; - unsigned long end = begin + len; - - /* First rev 82545 and 82546 need to not allow any memory - * write location to cross 64k boundary due to errata 23 - */ - if (hw->mac_type == e1000_82545 || - hw->mac_type == e1000_ce4100 || - hw->mac_type == e1000_82546) { - return ((begin ^ (end - 1)) >> 16) != 0 ? false : true; - } - - return true; -} - -/** - * e1000_setup_tx_resources - allocate Tx resources (Descriptors) - * @adapter: board private structure - * @txdr: tx descriptor ring (for a specific queue) to setup - * - * Return 0 on success, negative on failure - **/ -static int e1000_setup_tx_resources(struct e1000_adapter *adapter, - struct e1000_tx_ring *txdr) -{ - struct pci_dev *pdev = adapter->pdev; - int size; - - size = sizeof(struct e1000_buffer) * txdr->count; - txdr->buffer_info = vzalloc(size); - if (!txdr->buffer_info) - return -ENOMEM; - - /* round up to nearest 4K */ - - txdr->size = txdr->count * sizeof(struct e1000_tx_desc); - txdr->size = ALIGN(txdr->size, 4096); - - txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma, - GFP_KERNEL); - if (!txdr->desc) { -setup_tx_desc_die: - vfree(txdr->buffer_info); - return -ENOMEM; - } - - /* Fix for errata 23, can't cross 64kB boundary */ - if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) { - void *olddesc = txdr->desc; - dma_addr_t olddma = txdr->dma; - e_err(tx_err, "txdr align check failed: %u bytes at %p\n", - txdr->size, txdr->desc); - /* Try again, without freeing the previous */ - txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, - &txdr->dma, GFP_KERNEL); - /* Failed allocation, critical failure */ - if (!txdr->desc) { - dma_free_coherent(&pdev->dev, txdr->size, olddesc, - olddma); - goto setup_tx_desc_die; - } - - if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) { - /* give up */ - dma_free_coherent(&pdev->dev, txdr->size, txdr->desc, - txdr->dma); - dma_free_coherent(&pdev->dev, txdr->size, olddesc, - olddma); - e_err(probe, "Unable to allocate aligned memory " - "for the transmit descriptor ring\n"); - vfree(txdr->buffer_info); - return -ENOMEM; - } else { - /* Free old allocation, new allocation was successful */ - dma_free_coherent(&pdev->dev, txdr->size, olddesc, - olddma); - } - } - memset(txdr->desc, 0, txdr->size); - - txdr->next_to_use = 0; - txdr->next_to_clean = 0; - - return 0; -} - -/** - * e1000_setup_all_tx_resources - wrapper to allocate Tx resources - * (Descriptors) for all queues - * @adapter: board private structure - * - * Return 0 on success, negative on failure - **/ -int e1000_setup_all_tx_resources(struct e1000_adapter *adapter) -{ - int i, err = 0; - - for (i = 0; i < adapter->num_tx_queues; i++) { - err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]); - if (err) { - e_err(probe, "Allocation for Tx Queue %u failed\n", i); - for (i-- ; i >= 0; i--) - e1000_free_tx_resources(adapter, - &adapter->tx_ring[i]); - break; - } - } - - return err; -} - -/** - * e1000_configure_tx - Configure 8254x Transmit Unit after Reset - * @adapter: board private structure - * - * Configure the Tx unit of the MAC after a reset. - **/ -static void e1000_configure_tx(struct e1000_adapter *adapter) -{ - u64 tdba; - struct e1000_hw *hw = &adapter->hw; - u32 tdlen, tctl, tipg; - u32 ipgr1, ipgr2; - - /* Setup the HW Tx Head and Tail descriptor pointers */ - - switch (adapter->num_tx_queues) { - case 1: - default: - tdba = adapter->tx_ring[0].dma; - tdlen = adapter->tx_ring[0].count * - sizeof(struct e1000_tx_desc); - ew32(TDLEN, tdlen); - ew32(TDBAH, (tdba >> 32)); - ew32(TDBAL, (tdba & 0x00000000ffffffffULL)); - ew32(TDT, 0); - ew32(TDH, 0); - adapter->tx_ring[0].tdh = ((hw->mac_type >= e1000_82543) ? - E1000_TDH : E1000_82542_TDH); - adapter->tx_ring[0].tdt = ((hw->mac_type >= e1000_82543) ? - E1000_TDT : E1000_82542_TDT); - break; - } - - /* Set the default values for the Tx Inter Packet Gap timer */ - if ((hw->media_type == e1000_media_type_fiber || - hw->media_type == e1000_media_type_internal_serdes)) - tipg = DEFAULT_82543_TIPG_IPGT_FIBER; - else - tipg = DEFAULT_82543_TIPG_IPGT_COPPER; - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - tipg = DEFAULT_82542_TIPG_IPGT; - ipgr1 = DEFAULT_82542_TIPG_IPGR1; - ipgr2 = DEFAULT_82542_TIPG_IPGR2; - break; - default: - ipgr1 = DEFAULT_82543_TIPG_IPGR1; - ipgr2 = DEFAULT_82543_TIPG_IPGR2; - break; - } - tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT; - tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT; - ew32(TIPG, tipg); - - /* Set the Tx Interrupt Delay register */ - - ew32(TIDV, adapter->tx_int_delay); - if (hw->mac_type >= e1000_82540) - ew32(TADV, adapter->tx_abs_int_delay); - - /* Program the Transmit Control Register */ - - tctl = er32(TCTL); - tctl &= ~E1000_TCTL_CT; - tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | - (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); - - e1000_config_collision_dist(hw); - - /* Setup Transmit Descriptor Settings for eop descriptor */ - adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS; - - /* only set IDE if we are delaying interrupts using the timers */ - if (adapter->tx_int_delay) - adapter->txd_cmd |= E1000_TXD_CMD_IDE; - - if (hw->mac_type < e1000_82543) - adapter->txd_cmd |= E1000_TXD_CMD_RPS; - else - adapter->txd_cmd |= E1000_TXD_CMD_RS; - - /* Cache if we're 82544 running in PCI-X because we'll - * need this to apply a workaround later in the send path. - */ - if (hw->mac_type == e1000_82544 && - hw->bus_type == e1000_bus_type_pcix) - adapter->pcix_82544 = true; - - ew32(TCTL, tctl); - -} - -/** - * e1000_setup_rx_resources - allocate Rx resources (Descriptors) - * @adapter: board private structure - * @rxdr: rx descriptor ring (for a specific queue) to setup - * - * Returns 0 on success, negative on failure - **/ -static int e1000_setup_rx_resources(struct e1000_adapter *adapter, - struct e1000_rx_ring *rxdr) -{ - struct pci_dev *pdev = adapter->pdev; - int size, desc_len; - - size = sizeof(struct e1000_buffer) * rxdr->count; - rxdr->buffer_info = vzalloc(size); - if (!rxdr->buffer_info) - return -ENOMEM; - - desc_len = sizeof(struct e1000_rx_desc); - - /* Round up to nearest 4K */ - - rxdr->size = rxdr->count * desc_len; - rxdr->size = ALIGN(rxdr->size, 4096); - - rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma, - GFP_KERNEL); - if (!rxdr->desc) { -setup_rx_desc_die: - vfree(rxdr->buffer_info); - return -ENOMEM; - } - - /* Fix for errata 23, can't cross 64kB boundary */ - if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { - void *olddesc = rxdr->desc; - dma_addr_t olddma = rxdr->dma; - e_err(rx_err, "rxdr align check failed: %u bytes at %p\n", - rxdr->size, rxdr->desc); - /* Try again, without freeing the previous */ - rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, - &rxdr->dma, GFP_KERNEL); - /* Failed allocation, critical failure */ - if (!rxdr->desc) { - dma_free_coherent(&pdev->dev, rxdr->size, olddesc, - olddma); - goto setup_rx_desc_die; - } - - if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { - /* give up */ - dma_free_coherent(&pdev->dev, rxdr->size, rxdr->desc, - rxdr->dma); - dma_free_coherent(&pdev->dev, rxdr->size, olddesc, - olddma); - e_err(probe, "Unable to allocate aligned memory for " - "the Rx descriptor ring\n"); - goto setup_rx_desc_die; - } else { - /* Free old allocation, new allocation was successful */ - dma_free_coherent(&pdev->dev, rxdr->size, olddesc, - olddma); - } - } - memset(rxdr->desc, 0, rxdr->size); - - rxdr->next_to_clean = 0; - rxdr->next_to_use = 0; - rxdr->rx_skb_top = NULL; - - return 0; -} - -/** - * e1000_setup_all_rx_resources - wrapper to allocate Rx resources - * (Descriptors) for all queues - * @adapter: board private structure - * - * Return 0 on success, negative on failure - **/ -int e1000_setup_all_rx_resources(struct e1000_adapter *adapter) -{ - int i, err = 0; - - for (i = 0; i < adapter->num_rx_queues; i++) { - err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]); - if (err) { - e_err(probe, "Allocation for Rx Queue %u failed\n", i); - for (i-- ; i >= 0; i--) - e1000_free_rx_resources(adapter, - &adapter->rx_ring[i]); - break; - } - } - - return err; -} - -/** - * e1000_setup_rctl - configure the receive control registers - * @adapter: Board private structure - **/ -static void e1000_setup_rctl(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - rctl = er32(RCTL); - - rctl &= ~(3 << E1000_RCTL_MO_SHIFT); - - rctl |= E1000_RCTL_BAM | E1000_RCTL_LBM_NO | - E1000_RCTL_RDMTS_HALF | - (hw->mc_filter_type << E1000_RCTL_MO_SHIFT); - - if (hw->tbi_compatibility_on == 1) - rctl |= E1000_RCTL_SBP; - else - rctl &= ~E1000_RCTL_SBP; - - if (adapter->netdev->mtu <= ETH_DATA_LEN) - rctl &= ~E1000_RCTL_LPE; - else - rctl |= E1000_RCTL_LPE; - - /* Setup buffer sizes */ - rctl &= ~E1000_RCTL_SZ_4096; - rctl |= E1000_RCTL_BSEX; - switch (adapter->rx_buffer_len) { - case E1000_RXBUFFER_2048: - default: - rctl |= E1000_RCTL_SZ_2048; - rctl &= ~E1000_RCTL_BSEX; - break; - case E1000_RXBUFFER_4096: - rctl |= E1000_RCTL_SZ_4096; - break; - case E1000_RXBUFFER_8192: - rctl |= E1000_RCTL_SZ_8192; - break; - case E1000_RXBUFFER_16384: - rctl |= E1000_RCTL_SZ_16384; - break; - } - - /* This is useful for sniffing bad packets. */ - if (adapter->netdev->features & NETIF_F_RXALL) { - /* UPE and MPE will be handled by normal PROMISC logic - * in e1000e_set_rx_mode - */ - rctl |= (E1000_RCTL_SBP | /* Receive bad packets */ - E1000_RCTL_BAM | /* RX All Bcast Pkts */ - E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */ - - rctl &= ~(E1000_RCTL_VFE | /* Disable VLAN filter */ - E1000_RCTL_DPF | /* Allow filtered pause */ - E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */ - /* Do not mess with E1000_CTRL_VME, it affects transmit as well, - * and that breaks VLANs. - */ - } - - ew32(RCTL, rctl); -} - -/** - * e1000_configure_rx - Configure 8254x Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Rx unit of the MAC after a reset. - **/ -static void e1000_configure_rx(struct e1000_adapter *adapter) -{ - u64 rdba; - struct e1000_hw *hw = &adapter->hw; - u32 rdlen, rctl, rxcsum; - - if (adapter->netdev->mtu > ETH_DATA_LEN) { - rdlen = adapter->rx_ring[0].count * - sizeof(struct e1000_rx_desc); - adapter->clean_rx = e1000_clean_jumbo_rx_irq; - adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers; - } else { - rdlen = adapter->rx_ring[0].count * - sizeof(struct e1000_rx_desc); - adapter->clean_rx = e1000_clean_rx_irq; - adapter->alloc_rx_buf = e1000_alloc_rx_buffers; - } - - /* disable receives while setting up the descriptors */ - rctl = er32(RCTL); - ew32(RCTL, rctl & ~E1000_RCTL_EN); - - /* set the Receive Delay Timer Register */ - ew32(RDTR, adapter->rx_int_delay); - - if (hw->mac_type >= e1000_82540) { - ew32(RADV, adapter->rx_abs_int_delay); - if (adapter->itr_setting != 0) - ew32(ITR, 1000000000 / (adapter->itr * 256)); - } - - /* Setup the HW Rx Head and Tail Descriptor Pointers and - * the Base and Length of the Rx Descriptor Ring - */ - switch (adapter->num_rx_queues) { - case 1: - default: - rdba = adapter->rx_ring[0].dma; - ew32(RDLEN, rdlen); - ew32(RDBAH, (rdba >> 32)); - ew32(RDBAL, (rdba & 0x00000000ffffffffULL)); - ew32(RDT, 0); - ew32(RDH, 0); - adapter->rx_ring[0].rdh = ((hw->mac_type >= e1000_82543) ? - E1000_RDH : E1000_82542_RDH); - adapter->rx_ring[0].rdt = ((hw->mac_type >= e1000_82543) ? - E1000_RDT : E1000_82542_RDT); - break; - } - - /* Enable 82543 Receive Checksum Offload for TCP and UDP */ - if (hw->mac_type >= e1000_82543) { - rxcsum = er32(RXCSUM); - if (adapter->rx_csum) - rxcsum |= E1000_RXCSUM_TUOFL; - else - /* don't need to clear IPPCSE as it defaults to 0 */ - rxcsum &= ~E1000_RXCSUM_TUOFL; - ew32(RXCSUM, rxcsum); - } - - /* Enable Receives */ - ew32(RCTL, rctl | E1000_RCTL_EN); -} - -/** - * e1000_free_tx_resources - Free Tx Resources per Queue - * @adapter: board private structure - * @tx_ring: Tx descriptor ring for a specific queue - * - * Free all transmit software resources - **/ -static void e1000_free_tx_resources(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring) -{ - struct pci_dev *pdev = adapter->pdev; - - e1000_clean_tx_ring(adapter, tx_ring); - - vfree(tx_ring->buffer_info); - tx_ring->buffer_info = NULL; - - dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, - tx_ring->dma); - - tx_ring->desc = NULL; -} - -/** - * e1000_free_all_tx_resources - Free Tx Resources for All Queues - * @adapter: board private structure - * - * Free all transmit software resources - **/ -void e1000_free_all_tx_resources(struct e1000_adapter *adapter) -{ - int i; - - for (i = 0; i < adapter->num_tx_queues; i++) - e1000_free_tx_resources(adapter, &adapter->tx_ring[i]); -} - -static void e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter, - struct e1000_buffer *buffer_info) -{ - if (buffer_info->dma) { - if (buffer_info->mapped_as_page) - dma_unmap_page(&adapter->pdev->dev, buffer_info->dma, - buffer_info->length, DMA_TO_DEVICE); - else - dma_unmap_single(&adapter->pdev->dev, buffer_info->dma, - buffer_info->length, - DMA_TO_DEVICE); - buffer_info->dma = 0; - } - if (buffer_info->skb) { - dev_kfree_skb_any(buffer_info->skb); - buffer_info->skb = NULL; - } - buffer_info->time_stamp = 0; - /* buffer_info must be completely set up in the transmit path */ -} - -/** - * e1000_clean_tx_ring - Free Tx Buffers - * @adapter: board private structure - * @tx_ring: ring to be cleaned - **/ -static void e1000_clean_tx_ring(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_buffer *buffer_info; - unsigned long size; - unsigned int i; - - /* Free all the Tx ring sk_buffs */ - - for (i = 0; i < tx_ring->count; i++) { - buffer_info = &tx_ring->buffer_info[i]; - e1000_unmap_and_free_tx_resource(adapter, buffer_info); - } - - netdev_reset_queue(adapter->netdev); - size = sizeof(struct e1000_buffer) * tx_ring->count; - memset(tx_ring->buffer_info, 0, size); - - /* Zero out the descriptor ring */ - - memset(tx_ring->desc, 0, tx_ring->size); - - tx_ring->next_to_use = 0; - tx_ring->next_to_clean = 0; - tx_ring->last_tx_tso = false; - - writel(0, hw->hw_addr + tx_ring->tdh); - writel(0, hw->hw_addr + tx_ring->tdt); -} - -/** - * e1000_clean_all_tx_rings - Free Tx Buffers for all queues - * @adapter: board private structure - **/ -static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter) -{ - int i; - - for (i = 0; i < adapter->num_tx_queues; i++) - e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]); -} - -/** - * e1000_free_rx_resources - Free Rx Resources - * @adapter: board private structure - * @rx_ring: ring to clean the resources from - * - * Free all receive software resources - **/ -static void e1000_free_rx_resources(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring) -{ - struct pci_dev *pdev = adapter->pdev; - - e1000_clean_rx_ring(adapter, rx_ring); - - vfree(rx_ring->buffer_info); - rx_ring->buffer_info = NULL; - - dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, - rx_ring->dma); - - rx_ring->desc = NULL; -} - -/** - * e1000_free_all_rx_resources - Free Rx Resources for All Queues - * @adapter: board private structure - * - * Free all receive software resources - **/ -void e1000_free_all_rx_resources(struct e1000_adapter *adapter) -{ - int i; - - for (i = 0; i < adapter->num_rx_queues; i++) - e1000_free_rx_resources(adapter, &adapter->rx_ring[i]); -} - -/** - * e1000_clean_rx_ring - Free Rx Buffers per Queue - * @adapter: board private structure - * @rx_ring: ring to free buffers from - **/ -static void e1000_clean_rx_ring(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - unsigned long size; - unsigned int i; - - /* Free all the Rx ring sk_buffs */ - for (i = 0; i < rx_ring->count; i++) { - buffer_info = &rx_ring->buffer_info[i]; - if (buffer_info->dma && - adapter->clean_rx == e1000_clean_rx_irq) { - dma_unmap_single(&pdev->dev, buffer_info->dma, - buffer_info->length, - DMA_FROM_DEVICE); - } else if (buffer_info->dma && - adapter->clean_rx == e1000_clean_jumbo_rx_irq) { - dma_unmap_page(&pdev->dev, buffer_info->dma, - buffer_info->length, - DMA_FROM_DEVICE); - } - - buffer_info->dma = 0; - if (buffer_info->page) { - put_page(buffer_info->page); - buffer_info->page = NULL; - } - if (buffer_info->skb) { - dev_kfree_skb(buffer_info->skb); - buffer_info->skb = NULL; - } - } - - /* there also may be some cached data from a chained receive */ - if (rx_ring->rx_skb_top) { - dev_kfree_skb(rx_ring->rx_skb_top); - rx_ring->rx_skb_top = NULL; - } - - size = sizeof(struct e1000_buffer) * rx_ring->count; - memset(rx_ring->buffer_info, 0, size); - - /* Zero out the descriptor ring */ - memset(rx_ring->desc, 0, rx_ring->size); - - rx_ring->next_to_clean = 0; - rx_ring->next_to_use = 0; - - writel(0, hw->hw_addr + rx_ring->rdh); - writel(0, hw->hw_addr + rx_ring->rdt); -} - -/** - * e1000_clean_all_rx_rings - Free Rx Buffers for all queues - * @adapter: board private structure - **/ -static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter) -{ - int i; - - for (i = 0; i < adapter->num_rx_queues; i++) - e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]); -} - -/* The 82542 2.0 (revision 2) needs to have the receive unit in reset - * and memory write and invalidate disabled for certain operations - */ -static void e1000_enter_82542_rst(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - u32 rctl; - - e1000_pci_clear_mwi(hw); - - rctl = er32(RCTL); - rctl |= E1000_RCTL_RST; - ew32(RCTL, rctl); - E1000_WRITE_FLUSH(); - mdelay(5); - - if (netif_running(netdev)) - e1000_clean_all_rx_rings(adapter); -} - -static void e1000_leave_82542_rst(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - u32 rctl; - - rctl = er32(RCTL); - rctl &= ~E1000_RCTL_RST; - ew32(RCTL, rctl); - E1000_WRITE_FLUSH(); - mdelay(5); - - if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE) - e1000_pci_set_mwi(hw); - - if (netif_running(netdev)) { - /* No need to loop, because 82542 supports only 1 queue */ - struct e1000_rx_ring *ring = &adapter->rx_ring[0]; - e1000_configure_rx(adapter); - adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring)); - } -} - -/** - * e1000_set_mac - Change the Ethernet Address of the NIC - * @netdev: network interface device structure - * @p: pointer to an address structure - * - * Returns 0 on success, negative on failure - **/ -static int e1000_set_mac(struct net_device *netdev, void *p) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - /* 82542 2.0 needs to be in reset to write receive address registers */ - - if (hw->mac_type == e1000_82542_rev2_0) - e1000_enter_82542_rst(adapter); - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - memcpy(hw->mac_addr, addr->sa_data, netdev->addr_len); - - e1000_rar_set(hw, hw->mac_addr, 0); - - if (hw->mac_type == e1000_82542_rev2_0) - e1000_leave_82542_rst(adapter); - - return 0; -} - -/** - * e1000_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set - * @netdev: network interface device structure - * - * The set_rx_mode entry point is called whenever the unicast or multicast - * address lists or the network interface flags are updated. This routine is - * responsible for configuring the hardware for proper unicast, multicast, - * promiscuous mode, and all-multi behavior. - **/ -static void e1000_set_rx_mode(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct netdev_hw_addr *ha; - bool use_uc = false; - u32 rctl; - u32 hash_value; - int i, rar_entries = E1000_RAR_ENTRIES; - int mta_reg_count = E1000_NUM_MTA_REGISTERS; - u32 *mcarray = kcalloc(mta_reg_count, sizeof(u32), GFP_ATOMIC); - - if (!mcarray) - return; - - /* Check for Promiscuous and All Multicast modes */ - - rctl = er32(RCTL); - - if (netdev->flags & IFF_PROMISC) { - rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); - rctl &= ~E1000_RCTL_VFE; - } else { - if (netdev->flags & IFF_ALLMULTI) - rctl |= E1000_RCTL_MPE; - else - rctl &= ~E1000_RCTL_MPE; - /* Enable VLAN filter if there is a VLAN */ - if (e1000_vlan_used(adapter)) - rctl |= E1000_RCTL_VFE; - } - - if (netdev_uc_count(netdev) > rar_entries - 1) { - rctl |= E1000_RCTL_UPE; - } else if (!(netdev->flags & IFF_PROMISC)) { - rctl &= ~E1000_RCTL_UPE; - use_uc = true; - } - - ew32(RCTL, rctl); - - /* 82542 2.0 needs to be in reset to write receive address registers */ - - if (hw->mac_type == e1000_82542_rev2_0) - e1000_enter_82542_rst(adapter); - - /* load the first 14 addresses into the exact filters 1-14. Unicast - * addresses take precedence to avoid disabling unicast filtering - * when possible. - * - * RAR 0 is used for the station MAC address - * if there are not 14 addresses, go ahead and clear the filters - */ - i = 1; - if (use_uc) - netdev_for_each_uc_addr(ha, netdev) { - if (i == rar_entries) - break; - e1000_rar_set(hw, ha->addr, i++); - } - - netdev_for_each_mc_addr(ha, netdev) { - if (i == rar_entries) { - /* load any remaining addresses into the hash table */ - u32 hash_reg, hash_bit, mta; - hash_value = e1000_hash_mc_addr(hw, ha->addr); - hash_reg = (hash_value >> 5) & 0x7F; - hash_bit = hash_value & 0x1F; - mta = (1 << hash_bit); - mcarray[hash_reg] |= mta; - } else { - e1000_rar_set(hw, ha->addr, i++); - } - } - - for (; i < rar_entries; i++) { - E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0); - E1000_WRITE_FLUSH(); - E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0); - E1000_WRITE_FLUSH(); - } - - /* write the hash table completely, write from bottom to avoid - * both stupid write combining chipsets, and flushing each write - */ - for (i = mta_reg_count - 1; i >= 0 ; i--) { - /* If we are on an 82544 has an errata where writing odd - * offsets overwrites the previous even offset, but writing - * backwards over the range solves the issue by always - * writing the odd offset first - */ - E1000_WRITE_REG_ARRAY(hw, MTA, i, mcarray[i]); - } - E1000_WRITE_FLUSH(); - - if (hw->mac_type == e1000_82542_rev2_0) - e1000_leave_82542_rst(adapter); - - kfree(mcarray); -} - -/** - * e1000_update_phy_info_task - get phy info - * @work: work struct contained inside adapter struct - * - * Need to wait a few seconds after link up to get diagnostic information from - * the phy - */ -static void e1000_update_phy_info_task(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - phy_info_task.work); - if (test_bit(__E1000_DOWN, &adapter->flags)) - return; - mutex_lock(&adapter->mutex); - e1000_phy_get_info(&adapter->hw, &adapter->phy_info); - mutex_unlock(&adapter->mutex); -} - -/** - * e1000_82547_tx_fifo_stall_task - task to complete work - * @work: work struct contained inside adapter struct - **/ -static void e1000_82547_tx_fifo_stall_task(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - fifo_stall_task.work); - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - u32 tctl; - - if (test_bit(__E1000_DOWN, &adapter->flags)) - return; - mutex_lock(&adapter->mutex); - if (atomic_read(&adapter->tx_fifo_stall)) { - if ((er32(TDT) == er32(TDH)) && - (er32(TDFT) == er32(TDFH)) && - (er32(TDFTS) == er32(TDFHS))) { - tctl = er32(TCTL); - ew32(TCTL, tctl & ~E1000_TCTL_EN); - ew32(TDFT, adapter->tx_head_addr); - ew32(TDFH, adapter->tx_head_addr); - ew32(TDFTS, adapter->tx_head_addr); - ew32(TDFHS, adapter->tx_head_addr); - ew32(TCTL, tctl); - E1000_WRITE_FLUSH(); - - adapter->tx_fifo_head = 0; - atomic_set(&adapter->tx_fifo_stall, 0); - netif_wake_queue(netdev); - } else if (!test_bit(__E1000_DOWN, &adapter->flags)) { - schedule_delayed_work(&adapter->fifo_stall_task, 1); - } - } - mutex_unlock(&adapter->mutex); -} - -bool e1000_has_link(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - bool link_active = false; - - /* get_link_status is set on LSC (link status) interrupt or rx - * sequence error interrupt (except on intel ce4100). - * get_link_status will stay false until the - * e1000_check_for_link establishes link for copper adapters - * ONLY - */ - switch (hw->media_type) { - case e1000_media_type_copper: - if (hw->mac_type == e1000_ce4100) - hw->get_link_status = 1; - if (hw->get_link_status) { - e1000_check_for_link(hw); - link_active = !hw->get_link_status; - } else { - link_active = true; - } - break; - case e1000_media_type_fiber: - e1000_check_for_link(hw); - link_active = !!(er32(STATUS) & E1000_STATUS_LU); - break; - case e1000_media_type_internal_serdes: - e1000_check_for_link(hw); - link_active = hw->serdes_has_link; - break; - default: - break; - } - - return link_active; -} - -/** - * e1000_watchdog - work function - * @work: work struct contained inside adapter struct - **/ -static void e1000_watchdog(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - watchdog_task.work); - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - struct e1000_tx_ring *txdr = adapter->tx_ring; - u32 link, tctl; - - if (test_bit(__E1000_DOWN, &adapter->flags)) - return; - - mutex_lock(&adapter->mutex); - link = e1000_has_link(adapter); - if ((netif_carrier_ok(netdev)) && link) - goto link_up; - - if (link) { - if (!netif_carrier_ok(netdev)) { - u32 ctrl; - bool txb2b = true; - /* update snapshot of PHY registers on LSC */ - e1000_get_speed_and_duplex(hw, - &adapter->link_speed, - &adapter->link_duplex); - - ctrl = er32(CTRL); - pr_info("%s NIC Link is Up %d Mbps %s, " - "Flow Control: %s\n", - netdev->name, - adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? - "Full Duplex" : "Half Duplex", - ((ctrl & E1000_CTRL_TFCE) && (ctrl & - E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl & - E1000_CTRL_RFCE) ? "RX" : ((ctrl & - E1000_CTRL_TFCE) ? "TX" : "None"))); - - /* adjust timeout factor according to speed/duplex */ - adapter->tx_timeout_factor = 1; - switch (adapter->link_speed) { - case SPEED_10: - txb2b = false; - adapter->tx_timeout_factor = 16; - break; - case SPEED_100: - txb2b = false; - /* maybe add some timeout factor ? */ - break; - } - - /* enable transmits in the hardware */ - tctl = er32(TCTL); - tctl |= E1000_TCTL_EN; - ew32(TCTL, tctl); - - netif_carrier_on(netdev); - if (!test_bit(__E1000_DOWN, &adapter->flags)) - schedule_delayed_work(&adapter->phy_info_task, - 2 * HZ); - adapter->smartspeed = 0; - } - } else { - if (netif_carrier_ok(netdev)) { - adapter->link_speed = 0; - adapter->link_duplex = 0; - pr_info("%s NIC Link is Down\n", - netdev->name); - netif_carrier_off(netdev); - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - schedule_delayed_work(&adapter->phy_info_task, - 2 * HZ); - } - - e1000_smartspeed(adapter); - } - -link_up: - e1000_update_stats(adapter); - - hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; - adapter->tpt_old = adapter->stats.tpt; - hw->collision_delta = adapter->stats.colc - adapter->colc_old; - adapter->colc_old = adapter->stats.colc; - - adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old; - adapter->gorcl_old = adapter->stats.gorcl; - adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old; - adapter->gotcl_old = adapter->stats.gotcl; - - e1000_update_adaptive(hw); - - if (!netif_carrier_ok(netdev)) { - if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) { - /* We've lost link, so the controller stops DMA, - * but we've got queued Tx work that's never going - * to get done, so reset controller to flush Tx. - * (Do the reset outside of interrupt context). - */ - adapter->tx_timeout_count++; - schedule_work(&adapter->reset_task); - /* exit immediately since reset is imminent */ - goto unlock; - } - } - - /* Simple mode for Interrupt Throttle Rate (ITR) */ - if (hw->mac_type >= e1000_82540 && adapter->itr_setting == 4) { - /* Symmetric Tx/Rx gets a reduced ITR=2000; - * Total asymmetrical Tx or Rx gets ITR=8000; - * everyone else is between 2000-8000. - */ - u32 goc = (adapter->gotcl + adapter->gorcl) / 10000; - u32 dif = (adapter->gotcl > adapter->gorcl ? - adapter->gotcl - adapter->gorcl : - adapter->gorcl - adapter->gotcl) / 10000; - u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000; - - ew32(ITR, 1000000000 / (itr * 256)); - } - - /* Cause software interrupt to ensure rx ring is cleaned */ - ew32(ICS, E1000_ICS_RXDMT0); - - /* Force detection of hung controller every watchdog period */ - adapter->detect_tx_hung = true; - - /* Reschedule the task */ - if (!test_bit(__E1000_DOWN, &adapter->flags)) - schedule_delayed_work(&adapter->watchdog_task, 2 * HZ); - -unlock: - mutex_unlock(&adapter->mutex); -} - -enum latency_range { - lowest_latency = 0, - low_latency = 1, - bulk_latency = 2, - latency_invalid = 255 -}; - -/** - * e1000_update_itr - update the dynamic ITR value based on statistics - * @adapter: pointer to adapter - * @itr_setting: current adapter->itr - * @packets: the number of packets during this measurement interval - * @bytes: the number of bytes during this measurement interval - * - * Stores a new ITR value based on packets and byte - * counts during the last interrupt. The advantage of per interrupt - * computation is faster updates and more accurate ITR for the current - * traffic pattern. Constants in this function were computed - * based on theoretical maximum wire speed and thresholds were set based - * on testing data as well as attempting to minimize response time - * while increasing bulk throughput. - * this functionality is controlled by the InterruptThrottleRate module - * parameter (see e1000_param.c) - **/ -static unsigned int e1000_update_itr(struct e1000_adapter *adapter, - u16 itr_setting, int packets, int bytes) -{ - unsigned int retval = itr_setting; - struct e1000_hw *hw = &adapter->hw; - - if (unlikely(hw->mac_type < e1000_82540)) - goto update_itr_done; - - if (packets == 0) - goto update_itr_done; - - switch (itr_setting) { - case lowest_latency: - /* jumbo frames get bulk treatment*/ - if (bytes/packets > 8000) - retval = bulk_latency; - else if ((packets < 5) && (bytes > 512)) - retval = low_latency; - break; - case low_latency: /* 50 usec aka 20000 ints/s */ - if (bytes > 10000) { - /* jumbo frames need bulk latency setting */ - if (bytes/packets > 8000) - retval = bulk_latency; - else if ((packets < 10) || ((bytes/packets) > 1200)) - retval = bulk_latency; - else if ((packets > 35)) - retval = lowest_latency; - } else if (bytes/packets > 2000) - retval = bulk_latency; - else if (packets <= 2 && bytes < 512) - retval = lowest_latency; - break; - case bulk_latency: /* 250 usec aka 4000 ints/s */ - if (bytes > 25000) { - if (packets > 35) - retval = low_latency; - } else if (bytes < 6000) { - retval = low_latency; - } - break; - } - -update_itr_done: - return retval; -} - -static void e1000_set_itr(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u16 current_itr; - u32 new_itr = adapter->itr; - - if (unlikely(hw->mac_type < e1000_82540)) - return; - - /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ - if (unlikely(adapter->link_speed != SPEED_1000)) { - current_itr = 0; - new_itr = 4000; - goto set_itr_now; - } - - adapter->tx_itr = e1000_update_itr(adapter, adapter->tx_itr, - adapter->total_tx_packets, - adapter->total_tx_bytes); - /* conservative mode (itr 3) eliminates the lowest_latency setting */ - if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency) - adapter->tx_itr = low_latency; - - adapter->rx_itr = e1000_update_itr(adapter, adapter->rx_itr, - adapter->total_rx_packets, - adapter->total_rx_bytes); - /* conservative mode (itr 3) eliminates the lowest_latency setting */ - if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency) - adapter->rx_itr = low_latency; - - current_itr = max(adapter->rx_itr, adapter->tx_itr); - - switch (current_itr) { - /* counts and packets in update_itr are dependent on these numbers */ - case lowest_latency: - new_itr = 70000; - break; - case low_latency: - new_itr = 20000; /* aka hwitr = ~200 */ - break; - case bulk_latency: - new_itr = 4000; - break; - default: - break; - } - -set_itr_now: - if (new_itr != adapter->itr) { - /* this attempts to bias the interrupt rate towards Bulk - * by adding intermediate steps when interrupt rate is - * increasing - */ - new_itr = new_itr > adapter->itr ? - min(adapter->itr + (new_itr >> 2), new_itr) : - new_itr; - adapter->itr = new_itr; - ew32(ITR, 1000000000 / (new_itr * 256)); - } -} - -#define E1000_TX_FLAGS_CSUM 0x00000001 -#define E1000_TX_FLAGS_VLAN 0x00000002 -#define E1000_TX_FLAGS_TSO 0x00000004 -#define E1000_TX_FLAGS_IPV4 0x00000008 -#define E1000_TX_FLAGS_NO_FCS 0x00000010 -#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 -#define E1000_TX_FLAGS_VLAN_SHIFT 16 - -static int e1000_tso(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring, struct sk_buff *skb) -{ - struct e1000_context_desc *context_desc; - struct e1000_buffer *buffer_info; - unsigned int i; - u32 cmd_length = 0; - u16 ipcse = 0, tucse, mss; - u8 ipcss, ipcso, tucss, tucso, hdr_len; - int err; - - if (skb_is_gso(skb)) { - if (skb_header_cloned(skb)) { - err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); - if (err) - return err; - } - - hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - mss = skb_shinfo(skb)->gso_size; - if (skb->protocol == htons(ETH_P_IP)) { - struct iphdr *iph = ip_hdr(skb); - iph->tot_len = 0; - iph->check = 0; - tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, - iph->daddr, 0, - IPPROTO_TCP, - 0); - cmd_length = E1000_TXD_CMD_IP; - ipcse = skb_transport_offset(skb) - 1; - } else if (skb->protocol == htons(ETH_P_IPV6)) { - ipv6_hdr(skb)->payload_len = 0; - tcp_hdr(skb)->check = - ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); - ipcse = 0; - } - ipcss = skb_network_offset(skb); - ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data; - tucss = skb_transport_offset(skb); - tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data; - tucse = 0; - - cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | - E1000_TXD_CMD_TCP | (skb->len - (hdr_len))); - - i = tx_ring->next_to_use; - context_desc = E1000_CONTEXT_DESC(*tx_ring, i); - buffer_info = &tx_ring->buffer_info[i]; - - context_desc->lower_setup.ip_fields.ipcss = ipcss; - context_desc->lower_setup.ip_fields.ipcso = ipcso; - context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse); - context_desc->upper_setup.tcp_fields.tucss = tucss; - context_desc->upper_setup.tcp_fields.tucso = tucso; - context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse); - context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss); - context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; - context_desc->cmd_and_length = cpu_to_le32(cmd_length); - - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; - - if (++i == tx_ring->count) i = 0; - tx_ring->next_to_use = i; - - return true; - } - return false; -} - -static bool e1000_tx_csum(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring, struct sk_buff *skb) -{ - struct e1000_context_desc *context_desc; - struct e1000_buffer *buffer_info; - unsigned int i; - u8 css; - u32 cmd_len = E1000_TXD_CMD_DEXT; - - if (skb->ip_summed != CHECKSUM_PARTIAL) - return false; - - switch (skb->protocol) { - case cpu_to_be16(ETH_P_IP): - if (ip_hdr(skb)->protocol == IPPROTO_TCP) - cmd_len |= E1000_TXD_CMD_TCP; - break; - case cpu_to_be16(ETH_P_IPV6): - /* XXX not handling all IPV6 headers */ - if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) - cmd_len |= E1000_TXD_CMD_TCP; - break; - default: - if (unlikely(net_ratelimit())) - e_warn(drv, "checksum_partial proto=%x!\n", - skb->protocol); - break; - } - - css = skb_checksum_start_offset(skb); - - i = tx_ring->next_to_use; - buffer_info = &tx_ring->buffer_info[i]; - context_desc = E1000_CONTEXT_DESC(*tx_ring, i); - - context_desc->lower_setup.ip_config = 0; - context_desc->upper_setup.tcp_fields.tucss = css; - context_desc->upper_setup.tcp_fields.tucso = - css + skb->csum_offset; - context_desc->upper_setup.tcp_fields.tucse = 0; - context_desc->tcp_seg_setup.data = 0; - context_desc->cmd_and_length = cpu_to_le32(cmd_len); - - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; - - if (unlikely(++i == tx_ring->count)) i = 0; - tx_ring->next_to_use = i; - - return true; -} - -#define E1000_MAX_TXD_PWR 12 -#define E1000_MAX_DATA_PER_TXD (1<hw; - struct pci_dev *pdev = adapter->pdev; - struct e1000_buffer *buffer_info; - unsigned int len = skb_headlen(skb); - unsigned int offset = 0, size, count = 0, i; - unsigned int f, bytecount, segs; - - i = tx_ring->next_to_use; - - while (len) { - buffer_info = &tx_ring->buffer_info[i]; - size = min(len, max_per_txd); - /* Workaround for Controller erratum -- - * descriptor for non-tso packet in a linear SKB that follows a - * tso gets written back prematurely before the data is fully - * DMA'd to the controller - */ - if (!skb->data_len && tx_ring->last_tx_tso && - !skb_is_gso(skb)) { - tx_ring->last_tx_tso = false; - size -= 4; - } - - /* Workaround for premature desc write-backs - * in TSO mode. Append 4-byte sentinel desc - */ - if (unlikely(mss && !nr_frags && size == len && size > 8)) - size -= 4; - /* work-around for errata 10 and it applies - * to all controllers in PCI-X mode - * The fix is to make sure that the first descriptor of a - * packet is smaller than 2048 - 16 - 16 (or 2016) bytes - */ - if (unlikely((hw->bus_type == e1000_bus_type_pcix) && - (size > 2015) && count == 0)) - size = 2015; - - /* Workaround for potential 82544 hang in PCI-X. Avoid - * terminating buffers within evenly-aligned dwords. - */ - if (unlikely(adapter->pcix_82544 && - !((unsigned long)(skb->data + offset + size - 1) & 4) && - size > 4)) - size -= 4; - - buffer_info->length = size; - /* set time_stamp *before* dma to help avoid a possible race */ - buffer_info->time_stamp = jiffies; - buffer_info->mapped_as_page = false; - buffer_info->dma = dma_map_single(&pdev->dev, - skb->data + offset, - size, DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) - goto dma_error; - buffer_info->next_to_watch = i; - - len -= size; - offset += size; - count++; - if (len) { - i++; - if (unlikely(i == tx_ring->count)) - i = 0; - } - } - - for (f = 0; f < nr_frags; f++) { - const struct skb_frag_struct *frag; - - frag = &skb_shinfo(skb)->frags[f]; - len = skb_frag_size(frag); - offset = 0; - - while (len) { - unsigned long bufend; - i++; - if (unlikely(i == tx_ring->count)) - i = 0; - - buffer_info = &tx_ring->buffer_info[i]; - size = min(len, max_per_txd); - /* Workaround for premature desc write-backs - * in TSO mode. Append 4-byte sentinel desc - */ - if (unlikely(mss && f == (nr_frags-1) && - size == len && size > 8)) - size -= 4; - /* Workaround for potential 82544 hang in PCI-X. - * Avoid terminating buffers within evenly-aligned - * dwords. - */ - bufend = (unsigned long) - page_to_phys(skb_frag_page(frag)); - bufend += offset + size - 1; - if (unlikely(adapter->pcix_82544 && - !(bufend & 4) && - size > 4)) - size -= 4; - - buffer_info->length = size; - buffer_info->time_stamp = jiffies; - buffer_info->mapped_as_page = true; - buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag, - offset, size, DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) - goto dma_error; - buffer_info->next_to_watch = i; - - len -= size; - offset += size; - count++; - } - } - - segs = skb_shinfo(skb)->gso_segs ?: 1; - /* multiply data chunks by size of headers */ - bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len; - - tx_ring->buffer_info[i].skb = skb; - tx_ring->buffer_info[i].segs = segs; - tx_ring->buffer_info[i].bytecount = bytecount; - tx_ring->buffer_info[first].next_to_watch = i; - - return count; - -dma_error: - dev_err(&pdev->dev, "TX DMA map failed\n"); - buffer_info->dma = 0; - if (count) - count--; - - while (count--) { - if (i==0) - i += tx_ring->count; - i--; - buffer_info = &tx_ring->buffer_info[i]; - e1000_unmap_and_free_tx_resource(adapter, buffer_info); - } - - return 0; -} - -static void e1000_tx_queue(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring, int tx_flags, - int count) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_tx_desc *tx_desc = NULL; - struct e1000_buffer *buffer_info; - u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; - unsigned int i; - - if (likely(tx_flags & E1000_TX_FLAGS_TSO)) { - txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | - E1000_TXD_CMD_TSE; - txd_upper |= E1000_TXD_POPTS_TXSM << 8; - - if (likely(tx_flags & E1000_TX_FLAGS_IPV4)) - txd_upper |= E1000_TXD_POPTS_IXSM << 8; - } - - if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) { - txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; - txd_upper |= E1000_TXD_POPTS_TXSM << 8; - } - - if (unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) { - txd_lower |= E1000_TXD_CMD_VLE; - txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); - } - - if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS)) - txd_lower &= ~(E1000_TXD_CMD_IFCS); - - i = tx_ring->next_to_use; - - while (count--) { - buffer_info = &tx_ring->buffer_info[i]; - tx_desc = E1000_TX_DESC(*tx_ring, i); - tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - tx_desc->lower.data = - cpu_to_le32(txd_lower | buffer_info->length); - tx_desc->upper.data = cpu_to_le32(txd_upper); - if (unlikely(++i == tx_ring->count)) i = 0; - } - - tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); - - /* txd_cmd re-enables FCS, so we'll re-disable it here as desired. */ - if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS)) - tx_desc->lower.data &= ~(cpu_to_le32(E1000_TXD_CMD_IFCS)); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - - tx_ring->next_to_use = i; - writel(i, hw->hw_addr + tx_ring->tdt); - /* we need this if more than one processor can write to our tail - * at a time, it synchronizes IO on IA64/Altix systems - */ - mmiowb(); -} - -/* 82547 workaround to avoid controller hang in half-duplex environment. - * The workaround is to avoid queuing a large packet that would span - * the internal Tx FIFO ring boundary by notifying the stack to resend - * the packet at a later time. This gives the Tx FIFO an opportunity to - * flush all packets. When that occurs, we reset the Tx FIFO pointers - * to the beginning of the Tx FIFO. - */ - -#define E1000_FIFO_HDR 0x10 -#define E1000_82547_PAD_LEN 0x3E0 - -static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, - struct sk_buff *skb) -{ - u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; - u32 skb_fifo_len = skb->len + E1000_FIFO_HDR; - - skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR); - - if (adapter->link_duplex != HALF_DUPLEX) - goto no_fifo_stall_required; - - if (atomic_read(&adapter->tx_fifo_stall)) - return 1; - - if (skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) { - atomic_set(&adapter->tx_fifo_stall, 1); - return 1; - } - -no_fifo_stall_required: - adapter->tx_fifo_head += skb_fifo_len; - if (adapter->tx_fifo_head >= adapter->tx_fifo_size) - adapter->tx_fifo_head -= adapter->tx_fifo_size; - return 0; -} - -static int __e1000_maybe_stop_tx(struct net_device *netdev, int size) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_tx_ring *tx_ring = adapter->tx_ring; - - netif_stop_queue(netdev); - /* Herbert's original patch had: - * smp_mb__after_netif_stop_queue(); - * but since that doesn't exist yet, just open code it. - */ - smp_mb(); - - /* We need to check again in a case another CPU has just - * made room available. - */ - if (likely(E1000_DESC_UNUSED(tx_ring) < size)) - return -EBUSY; - - /* A reprieve! */ - netif_start_queue(netdev); - ++adapter->restart_queue; - return 0; -} - -static int e1000_maybe_stop_tx(struct net_device *netdev, - struct e1000_tx_ring *tx_ring, int size) -{ - if (likely(E1000_DESC_UNUSED(tx_ring) >= size)) - return 0; - return __e1000_maybe_stop_tx(netdev, size); -} - -#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) -static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct e1000_tx_ring *tx_ring; - unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD; - unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; - unsigned int tx_flags = 0; - unsigned int len = skb_headlen(skb); - unsigned int nr_frags; - unsigned int mss; - int count = 0; - int tso; - unsigned int f; - - /* This goes back to the question of how to logically map a Tx queue - * to a flow. Right now, performance is impacted slightly negatively - * if using multiple Tx queues. If the stack breaks away from a - * single qdisc implementation, we can look at this again. - */ - tx_ring = adapter->tx_ring; - - if (unlikely(skb->len <= 0)) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - /* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN, - * packets may get corrupted during padding by HW. - * To WA this issue, pad all small packets manually. - */ - if (skb->len < ETH_ZLEN) { - if (skb_pad(skb, ETH_ZLEN - skb->len)) - return NETDEV_TX_OK; - skb->len = ETH_ZLEN; - skb_set_tail_pointer(skb, ETH_ZLEN); - } - - mss = skb_shinfo(skb)->gso_size; - /* The controller does a simple calculation to - * make sure there is enough room in the FIFO before - * initiating the DMA for each buffer. The calc is: - * 4 = ceil(buffer len/mss). To make sure we don't - * overrun the FIFO, adjust the max buffer len if mss - * drops. - */ - if (mss) { - u8 hdr_len; - max_per_txd = min(mss << 2, max_per_txd); - max_txd_pwr = fls(max_per_txd) - 1; - - hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - if (skb->data_len && hdr_len == len) { - switch (hw->mac_type) { - unsigned int pull_size; - case e1000_82544: - /* Make sure we have room to chop off 4 bytes, - * and that the end alignment will work out to - * this hardware's requirements - * NOTE: this is a TSO only workaround - * if end byte alignment not correct move us - * into the next dword - */ - if ((unsigned long)(skb_tail_pointer(skb) - 1) - & 4) - break; - /* fall through */ - pull_size = min((unsigned int)4, skb->data_len); - if (!__pskb_pull_tail(skb, pull_size)) { - e_err(drv, "__pskb_pull_tail " - "failed.\n"); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - len = skb_headlen(skb); - break; - default: - /* do nothing */ - break; - } - } - } - - /* reserve a descriptor for the offload context */ - if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL)) - count++; - count++; - - /* Controller Erratum workaround */ - if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb)) - count++; - - count += TXD_USE_COUNT(len, max_txd_pwr); - - if (adapter->pcix_82544) - count++; - - /* work-around for errata 10 and it applies to all controllers - * in PCI-X mode, so add one more descriptor to the count - */ - if (unlikely((hw->bus_type == e1000_bus_type_pcix) && - (len > 2015))) - count++; - - nr_frags = skb_shinfo(skb)->nr_frags; - for (f = 0; f < nr_frags; f++) - count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f]), - max_txd_pwr); - if (adapter->pcix_82544) - count += nr_frags; - - /* need: count + 2 desc gap to keep tail from touching - * head, otherwise try next time - */ - if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2))) - return NETDEV_TX_BUSY; - - if (unlikely((hw->mac_type == e1000_82547) && - (e1000_82547_fifo_workaround(adapter, skb)))) { - netif_stop_queue(netdev); - if (!test_bit(__E1000_DOWN, &adapter->flags)) - schedule_delayed_work(&adapter->fifo_stall_task, 1); - return NETDEV_TX_BUSY; - } - - if (vlan_tx_tag_present(skb)) { - tx_flags |= E1000_TX_FLAGS_VLAN; - tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); - } - - first = tx_ring->next_to_use; - - tso = e1000_tso(adapter, tx_ring, skb); - if (tso < 0) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if (likely(tso)) { - if (likely(hw->mac_type != e1000_82544)) - tx_ring->last_tx_tso = true; - tx_flags |= E1000_TX_FLAGS_TSO; - } else if (likely(e1000_tx_csum(adapter, tx_ring, skb))) - tx_flags |= E1000_TX_FLAGS_CSUM; - - if (likely(skb->protocol == htons(ETH_P_IP))) - tx_flags |= E1000_TX_FLAGS_IPV4; - - if (unlikely(skb->no_fcs)) - tx_flags |= E1000_TX_FLAGS_NO_FCS; - - count = e1000_tx_map(adapter, tx_ring, skb, first, max_per_txd, - nr_frags, mss); - - if (count) { - netdev_sent_queue(netdev, skb->len); - skb_tx_timestamp(skb); - - e1000_tx_queue(adapter, tx_ring, tx_flags, count); - /* Make sure there is space in the ring for the next send. */ - e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2); - - } else { - dev_kfree_skb_any(skb); - tx_ring->buffer_info[first].time_stamp = 0; - tx_ring->next_to_use = first; - } - - return NETDEV_TX_OK; -} - -#define NUM_REGS 38 /* 1 based count */ -static void e1000_regdump(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 regs[NUM_REGS]; - u32 *regs_buff = regs; - int i = 0; - - static const char * const reg_name[] = { - "CTRL", "STATUS", - "RCTL", "RDLEN", "RDH", "RDT", "RDTR", - "TCTL", "TDBAL", "TDBAH", "TDLEN", "TDH", "TDT", - "TIDV", "TXDCTL", "TADV", "TARC0", - "TDBAL1", "TDBAH1", "TDLEN1", "TDH1", "TDT1", - "TXDCTL1", "TARC1", - "CTRL_EXT", "ERT", "RDBAL", "RDBAH", - "TDFH", "TDFT", "TDFHS", "TDFTS", "TDFPC", - "RDFH", "RDFT", "RDFHS", "RDFTS", "RDFPC" - }; - - regs_buff[0] = er32(CTRL); - regs_buff[1] = er32(STATUS); - - regs_buff[2] = er32(RCTL); - regs_buff[3] = er32(RDLEN); - regs_buff[4] = er32(RDH); - regs_buff[5] = er32(RDT); - regs_buff[6] = er32(RDTR); - - regs_buff[7] = er32(TCTL); - regs_buff[8] = er32(TDBAL); - regs_buff[9] = er32(TDBAH); - regs_buff[10] = er32(TDLEN); - regs_buff[11] = er32(TDH); - regs_buff[12] = er32(TDT); - regs_buff[13] = er32(TIDV); - regs_buff[14] = er32(TXDCTL); - regs_buff[15] = er32(TADV); - regs_buff[16] = er32(TARC0); - - regs_buff[17] = er32(TDBAL1); - regs_buff[18] = er32(TDBAH1); - regs_buff[19] = er32(TDLEN1); - regs_buff[20] = er32(TDH1); - regs_buff[21] = er32(TDT1); - regs_buff[22] = er32(TXDCTL1); - regs_buff[23] = er32(TARC1); - regs_buff[24] = er32(CTRL_EXT); - regs_buff[25] = er32(ERT); - regs_buff[26] = er32(RDBAL0); - regs_buff[27] = er32(RDBAH0); - regs_buff[28] = er32(TDFH); - regs_buff[29] = er32(TDFT); - regs_buff[30] = er32(TDFHS); - regs_buff[31] = er32(TDFTS); - regs_buff[32] = er32(TDFPC); - regs_buff[33] = er32(RDFH); - regs_buff[34] = er32(RDFT); - regs_buff[35] = er32(RDFHS); - regs_buff[36] = er32(RDFTS); - regs_buff[37] = er32(RDFPC); - - pr_info("Register dump\n"); - for (i = 0; i < NUM_REGS; i++) - pr_info("%-15s %08x\n", reg_name[i], regs_buff[i]); -} - -/* - * e1000_dump: Print registers, tx ring and rx ring - */ -static void e1000_dump(struct e1000_adapter *adapter) -{ - /* this code doesn't handle multiple rings */ - struct e1000_tx_ring *tx_ring = adapter->tx_ring; - struct e1000_rx_ring *rx_ring = adapter->rx_ring; - int i; - - if (!netif_msg_hw(adapter)) - return; - - /* Print Registers */ - e1000_regdump(adapter); - - /* transmit dump */ - pr_info("TX Desc ring0 dump\n"); - - /* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended) - * - * Legacy Transmit Descriptor - * +--------------------------------------------------------------+ - * 0 | Buffer Address [63:0] (Reserved on Write Back) | - * +--------------------------------------------------------------+ - * 8 | Special | CSS | Status | CMD | CSO | Length | - * +--------------------------------------------------------------+ - * 63 48 47 36 35 32 31 24 23 16 15 0 - * - * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload - * 63 48 47 40 39 32 31 16 15 8 7 0 - * +----------------------------------------------------------------+ - * 0 | TUCSE | TUCS0 | TUCSS | IPCSE | IPCS0 | IPCSS | - * +----------------------------------------------------------------+ - * 8 | MSS | HDRLEN | RSV | STA | TUCMD | DTYP | PAYLEN | - * +----------------------------------------------------------------+ - * 63 48 47 40 39 36 35 32 31 24 23 20 19 0 - * - * Extended Data Descriptor (DTYP=0x1) - * +----------------------------------------------------------------+ - * 0 | Buffer Address [63:0] | - * +----------------------------------------------------------------+ - * 8 | VLAN tag | POPTS | Rsvd | Status | Command | DTYP | DTALEN | - * +----------------------------------------------------------------+ - * 63 48 47 40 39 36 35 32 31 24 23 20 19 0 - */ - pr_info("Tc[desc] [Ce CoCsIpceCoS] [MssHlRSCm0Plen] [bi->dma ] leng ntw timestmp bi->skb\n"); - pr_info("Td[desc] [address 63:0 ] [VlaPoRSCm1Dlen] [bi->dma ] leng ntw timestmp bi->skb\n"); - - if (!netif_msg_tx_done(adapter)) - goto rx_ring_summary; - - for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { - struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i); - struct e1000_buffer *buffer_info = &tx_ring->buffer_info[i]; - struct my_u { __le64 a; __le64 b; }; - struct my_u *u = (struct my_u *)tx_desc; - const char *type; - - if (i == tx_ring->next_to_use && i == tx_ring->next_to_clean) - type = "NTC/U"; - else if (i == tx_ring->next_to_use) - type = "NTU"; - else if (i == tx_ring->next_to_clean) - type = "NTC"; - else - type = ""; - - pr_info("T%c[0x%03X] %016llX %016llX %016llX %04X %3X %016llX %p %s\n", - ((le64_to_cpu(u->b) & (1<<20)) ? 'd' : 'c'), i, - le64_to_cpu(u->a), le64_to_cpu(u->b), - (u64)buffer_info->dma, buffer_info->length, - buffer_info->next_to_watch, - (u64)buffer_info->time_stamp, buffer_info->skb, type); - } - -rx_ring_summary: - /* receive dump */ - pr_info("\nRX Desc ring dump\n"); - - /* Legacy Receive Descriptor Format - * - * +-----------------------------------------------------+ - * | Buffer Address [63:0] | - * +-----------------------------------------------------+ - * | VLAN Tag | Errors | Status 0 | Packet csum | Length | - * +-----------------------------------------------------+ - * 63 48 47 40 39 32 31 16 15 0 - */ - pr_info("R[desc] [address 63:0 ] [vl er S cks ln] [bi->dma ] [bi->skb]\n"); - - if (!netif_msg_rx_status(adapter)) - goto exit; - - for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) { - struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i); - struct e1000_buffer *buffer_info = &rx_ring->buffer_info[i]; - struct my_u { __le64 a; __le64 b; }; - struct my_u *u = (struct my_u *)rx_desc; - const char *type; - - if (i == rx_ring->next_to_use) - type = "NTU"; - else if (i == rx_ring->next_to_clean) - type = "NTC"; - else - type = ""; - - pr_info("R[0x%03X] %016llX %016llX %016llX %p %s\n", - i, le64_to_cpu(u->a), le64_to_cpu(u->b), - (u64)buffer_info->dma, buffer_info->skb, type); - } /* for */ - - /* dump the descriptor caches */ - /* rx */ - pr_info("Rx descriptor cache in 64bit format\n"); - for (i = 0x6000; i <= 0x63FF ; i += 0x10) { - pr_info("R%04X: %08X|%08X %08X|%08X\n", - i, - readl(adapter->hw.hw_addr + i+4), - readl(adapter->hw.hw_addr + i), - readl(adapter->hw.hw_addr + i+12), - readl(adapter->hw.hw_addr + i+8)); - } - /* tx */ - pr_info("Tx descriptor cache in 64bit format\n"); - for (i = 0x7000; i <= 0x73FF ; i += 0x10) { - pr_info("T%04X: %08X|%08X %08X|%08X\n", - i, - readl(adapter->hw.hw_addr + i+4), - readl(adapter->hw.hw_addr + i), - readl(adapter->hw.hw_addr + i+12), - readl(adapter->hw.hw_addr + i+8)); - } -exit: - return; -} - -/** - * e1000_tx_timeout - Respond to a Tx Hang - * @netdev: network interface device structure - **/ -static void e1000_tx_timeout(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - /* Do the reset outside of interrupt context */ - adapter->tx_timeout_count++; - schedule_work(&adapter->reset_task); -} - -static void e1000_reset_task(struct work_struct *work) -{ - struct e1000_adapter *adapter = - container_of(work, struct e1000_adapter, reset_task); - - if (test_bit(__E1000_DOWN, &adapter->flags)) - return; - e_err(drv, "Reset adapter\n"); - e1000_reinit_safe(adapter); -} - -/** - * e1000_get_stats - Get System Network Statistics - * @netdev: network interface device structure - * - * Returns the address of the device statistics structure. - * The statistics are actually updated from the watchdog. - **/ -static struct net_device_stats *e1000_get_stats(struct net_device *netdev) -{ - /* only return the current stats */ - return &netdev->stats; -} - -/** - * e1000_change_mtu - Change the Maximum Transfer Unit - * @netdev: network interface device structure - * @new_mtu: new value for maximum frame size - * - * Returns 0 on success, negative on failure - **/ -static int e1000_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - - if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || - (max_frame > MAX_JUMBO_FRAME_SIZE)) { - e_err(probe, "Invalid MTU setting\n"); - return -EINVAL; - } - - /* Adapter-specific max frame size limits. */ - switch (hw->mac_type) { - case e1000_undefined ... e1000_82542_rev2_1: - if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) { - e_err(probe, "Jumbo Frames not supported.\n"); - return -EINVAL; - } - break; - default: - /* Capable of supporting up to MAX_JUMBO_FRAME_SIZE limit. */ - break; - } - - while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) - msleep(1); - /* e1000_down has a dependency on max_frame_size */ - hw->max_frame_size = max_frame; - if (netif_running(netdev)) { - /* prevent buffers from being reallocated */ - adapter->alloc_rx_buf = e1000_alloc_dummy_rx_buffers; - e1000_down(adapter); - } - - /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN - * means we reserve 2 more, this pushes us to allocate from the next - * larger slab size. - * i.e. RXBUFFER_2048 --> size-4096 slab - * however with the new *_jumbo_rx* routines, jumbo receives will use - * fragmented skbs - */ - - if (max_frame <= E1000_RXBUFFER_2048) - adapter->rx_buffer_len = E1000_RXBUFFER_2048; - else -#if (PAGE_SIZE >= E1000_RXBUFFER_16384) - adapter->rx_buffer_len = E1000_RXBUFFER_16384; -#elif (PAGE_SIZE >= E1000_RXBUFFER_4096) - adapter->rx_buffer_len = PAGE_SIZE; -#endif - - /* adjust allocation if LPE protects us, and we aren't using SBP */ - if (!hw->tbi_compatibility_on && - ((max_frame == (ETH_FRAME_LEN + ETH_FCS_LEN)) || - (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE))) - adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; - - pr_info("%s changing MTU from %d to %d\n", - netdev->name, netdev->mtu, new_mtu); - netdev->mtu = new_mtu; - - if (netif_running(netdev)) - e1000_up(adapter); - else - e1000_reset(adapter); - - clear_bit(__E1000_RESETTING, &adapter->flags); - - return 0; -} - -/** - * e1000_update_stats - Update the board statistics counters - * @adapter: board private structure - **/ -void e1000_update_stats(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - struct pci_dev *pdev = adapter->pdev; - unsigned long flags; - u16 phy_tmp; - -#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF - - /* Prevent stats update while adapter is being reset, or if the pci - * connection is down. - */ - if (adapter->link_speed == 0) - return; - if (pci_channel_offline(pdev)) - return; - - spin_lock_irqsave(&adapter->stats_lock, flags); - - /* these counters are modified from e1000_tbi_adjust_stats, - * called from the interrupt context, so they must only - * be written while holding adapter->stats_lock - */ - - adapter->stats.crcerrs += er32(CRCERRS); - adapter->stats.gprc += er32(GPRC); - adapter->stats.gorcl += er32(GORCL); - adapter->stats.gorch += er32(GORCH); - adapter->stats.bprc += er32(BPRC); - adapter->stats.mprc += er32(MPRC); - adapter->stats.roc += er32(ROC); - - adapter->stats.prc64 += er32(PRC64); - adapter->stats.prc127 += er32(PRC127); - adapter->stats.prc255 += er32(PRC255); - adapter->stats.prc511 += er32(PRC511); - adapter->stats.prc1023 += er32(PRC1023); - adapter->stats.prc1522 += er32(PRC1522); - - adapter->stats.symerrs += er32(SYMERRS); - adapter->stats.mpc += er32(MPC); - adapter->stats.scc += er32(SCC); - adapter->stats.ecol += er32(ECOL); - adapter->stats.mcc += er32(MCC); - adapter->stats.latecol += er32(LATECOL); - adapter->stats.dc += er32(DC); - adapter->stats.sec += er32(SEC); - adapter->stats.rlec += er32(RLEC); - adapter->stats.xonrxc += er32(XONRXC); - adapter->stats.xontxc += er32(XONTXC); - adapter->stats.xoffrxc += er32(XOFFRXC); - adapter->stats.xofftxc += er32(XOFFTXC); - adapter->stats.fcruc += er32(FCRUC); - adapter->stats.gptc += er32(GPTC); - adapter->stats.gotcl += er32(GOTCL); - adapter->stats.gotch += er32(GOTCH); - adapter->stats.rnbc += er32(RNBC); - adapter->stats.ruc += er32(RUC); - adapter->stats.rfc += er32(RFC); - adapter->stats.rjc += er32(RJC); - adapter->stats.torl += er32(TORL); - adapter->stats.torh += er32(TORH); - adapter->stats.totl += er32(TOTL); - adapter->stats.toth += er32(TOTH); - adapter->stats.tpr += er32(TPR); - - adapter->stats.ptc64 += er32(PTC64); - adapter->stats.ptc127 += er32(PTC127); - adapter->stats.ptc255 += er32(PTC255); - adapter->stats.ptc511 += er32(PTC511); - adapter->stats.ptc1023 += er32(PTC1023); - adapter->stats.ptc1522 += er32(PTC1522); - - adapter->stats.mptc += er32(MPTC); - adapter->stats.bptc += er32(BPTC); - - /* used for adaptive IFS */ - - hw->tx_packet_delta = er32(TPT); - adapter->stats.tpt += hw->tx_packet_delta; - hw->collision_delta = er32(COLC); - adapter->stats.colc += hw->collision_delta; - - if (hw->mac_type >= e1000_82543) { - adapter->stats.algnerrc += er32(ALGNERRC); - adapter->stats.rxerrc += er32(RXERRC); - adapter->stats.tncrs += er32(TNCRS); - adapter->stats.cexterr += er32(CEXTERR); - adapter->stats.tsctc += er32(TSCTC); - adapter->stats.tsctfc += er32(TSCTFC); - } - - /* Fill out the OS statistics structure */ - netdev->stats.multicast = adapter->stats.mprc; - netdev->stats.collisions = adapter->stats.colc; - - /* Rx Errors */ - - /* RLEC on some newer hardware can be incorrect so build - * our own version based on RUC and ROC - */ - netdev->stats.rx_errors = adapter->stats.rxerrc + - adapter->stats.crcerrs + adapter->stats.algnerrc + - adapter->stats.ruc + adapter->stats.roc + - adapter->stats.cexterr; - adapter->stats.rlerrc = adapter->stats.ruc + adapter->stats.roc; - netdev->stats.rx_length_errors = adapter->stats.rlerrc; - netdev->stats.rx_crc_errors = adapter->stats.crcerrs; - netdev->stats.rx_frame_errors = adapter->stats.algnerrc; - netdev->stats.rx_missed_errors = adapter->stats.mpc; - - /* Tx Errors */ - adapter->stats.txerrc = adapter->stats.ecol + adapter->stats.latecol; - netdev->stats.tx_errors = adapter->stats.txerrc; - netdev->stats.tx_aborted_errors = adapter->stats.ecol; - netdev->stats.tx_window_errors = adapter->stats.latecol; - netdev->stats.tx_carrier_errors = adapter->stats.tncrs; - if (hw->bad_tx_carr_stats_fd && - adapter->link_duplex == FULL_DUPLEX) { - netdev->stats.tx_carrier_errors = 0; - adapter->stats.tncrs = 0; - } - - /* Tx Dropped needs to be maintained elsewhere */ - - /* Phy Stats */ - if (hw->media_type == e1000_media_type_copper) { - if ((adapter->link_speed == SPEED_1000) && - (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { - phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; - adapter->phy_stats.idle_errors += phy_tmp; - } - - if ((hw->mac_type <= e1000_82546) && - (hw->phy_type == e1000_phy_m88) && - !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp)) - adapter->phy_stats.receive_errors += phy_tmp; - } - - /* Management Stats */ - if (hw->has_smbus) { - adapter->stats.mgptc += er32(MGTPTC); - adapter->stats.mgprc += er32(MGTPRC); - adapter->stats.mgpdc += er32(MGTPDC); - } - - spin_unlock_irqrestore(&adapter->stats_lock, flags); -} - -/** - * e1000_intr - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - **/ -static irqreturn_t e1000_intr(int irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 icr = er32(ICR); - - if (unlikely((!icr))) - return IRQ_NONE; /* Not our interrupt */ - - /* we might have caused the interrupt, but the above - * read cleared it, and just in case the driver is - * down there is nothing to do so return handled - */ - if (unlikely(test_bit(__E1000_DOWN, &adapter->flags))) - return IRQ_HANDLED; - - if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) { - hw->get_link_status = 1; - /* guard against interrupt when we're going down */ - if (!test_bit(__E1000_DOWN, &adapter->flags)) - schedule_delayed_work(&adapter->watchdog_task, 1); - } - - /* disable interrupts, without the synchronize_irq bit */ - ew32(IMC, ~0); - E1000_WRITE_FLUSH(); - - if (likely(napi_schedule_prep(&adapter->napi))) { - adapter->total_tx_bytes = 0; - adapter->total_tx_packets = 0; - adapter->total_rx_bytes = 0; - adapter->total_rx_packets = 0; - __napi_schedule(&adapter->napi); - } else { - /* this really should not happen! if it does it is basically a - * bug, but not a hard error, so enable ints and continue - */ - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_enable(adapter); - } - - return IRQ_HANDLED; -} - -/** - * e1000_clean - NAPI Rx polling callback - * @adapter: board private structure - **/ -static int e1000_clean(struct napi_struct *napi, int budget) -{ - struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, - napi); - int tx_clean_complete = 0, work_done = 0; - - tx_clean_complete = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]); - - adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget); - - if (!tx_clean_complete) - work_done = budget; - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - if (likely(adapter->itr_setting & 3)) - e1000_set_itr(adapter); - napi_complete(napi); - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_enable(adapter); - } - - return work_done; -} - -/** - * e1000_clean_tx_irq - Reclaim resources after transmit completes - * @adapter: board private structure - **/ -static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - struct e1000_tx_desc *tx_desc, *eop_desc; - struct e1000_buffer *buffer_info; - unsigned int i, eop; - unsigned int count = 0; - unsigned int total_tx_bytes=0, total_tx_packets=0; - unsigned int bytes_compl = 0, pkts_compl = 0; - - i = tx_ring->next_to_clean; - eop = tx_ring->buffer_info[i].next_to_watch; - eop_desc = E1000_TX_DESC(*tx_ring, eop); - - while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && - (count < tx_ring->count)) { - bool cleaned = false; - rmb(); /* read buffer_info after eop_desc */ - for ( ; !cleaned; count++) { - tx_desc = E1000_TX_DESC(*tx_ring, i); - buffer_info = &tx_ring->buffer_info[i]; - cleaned = (i == eop); - - if (cleaned) { - total_tx_packets += buffer_info->segs; - total_tx_bytes += buffer_info->bytecount; - if (buffer_info->skb) { - bytes_compl += buffer_info->skb->len; - pkts_compl++; - } - - } - e1000_unmap_and_free_tx_resource(adapter, buffer_info); - tx_desc->upper.data = 0; - - if (unlikely(++i == tx_ring->count)) i = 0; - } - - eop = tx_ring->buffer_info[i].next_to_watch; - eop_desc = E1000_TX_DESC(*tx_ring, eop); - } - - tx_ring->next_to_clean = i; - - netdev_completed_queue(netdev, pkts_compl, bytes_compl); - -#define TX_WAKE_THRESHOLD 32 - if (unlikely(count && netif_carrier_ok(netdev) && - E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) { - /* Make sure that anybody stopping the queue after this - * sees the new next_to_clean. - */ - smp_mb(); - - if (netif_queue_stopped(netdev) && - !(test_bit(__E1000_DOWN, &adapter->flags))) { - netif_wake_queue(netdev); - ++adapter->restart_queue; - } - } - - if (adapter->detect_tx_hung) { - /* Detect a transmit hang in hardware, this serializes the - * check with the clearing of time_stamp and movement of i - */ - adapter->detect_tx_hung = false; - if (tx_ring->buffer_info[eop].time_stamp && - time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + - (adapter->tx_timeout_factor * HZ)) && - !(er32(STATUS) & E1000_STATUS_TXOFF)) { - - /* detected Tx unit hang */ - e_err(drv, "Detected Tx Unit Hang\n" - " Tx Queue <%lu>\n" - " TDH <%x>\n" - " TDT <%x>\n" - " next_to_use <%x>\n" - " next_to_clean <%x>\n" - "buffer_info[next_to_clean]\n" - " time_stamp <%lx>\n" - " next_to_watch <%x>\n" - " jiffies <%lx>\n" - " next_to_watch.status <%x>\n", - (unsigned long)((tx_ring - adapter->tx_ring) / - sizeof(struct e1000_tx_ring)), - readl(hw->hw_addr + tx_ring->tdh), - readl(hw->hw_addr + tx_ring->tdt), - tx_ring->next_to_use, - tx_ring->next_to_clean, - tx_ring->buffer_info[eop].time_stamp, - eop, - jiffies, - eop_desc->upper.fields.status); - e1000_dump(adapter); - netif_stop_queue(netdev); - } - } - adapter->total_tx_bytes += total_tx_bytes; - adapter->total_tx_packets += total_tx_packets; - netdev->stats.tx_bytes += total_tx_bytes; - netdev->stats.tx_packets += total_tx_packets; - return count < tx_ring->count; -} - -/** - * e1000_rx_checksum - Receive Checksum Offload for 82543 - * @adapter: board private structure - * @status_err: receive descriptor status and error fields - * @csum: receive descriptor csum field - * @sk_buff: socket buffer with received data - **/ -static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, - u32 csum, struct sk_buff *skb) -{ - struct e1000_hw *hw = &adapter->hw; - u16 status = (u16)status_err; - u8 errors = (u8)(status_err >> 24); - - skb_checksum_none_assert(skb); - - /* 82543 or newer only */ - if (unlikely(hw->mac_type < e1000_82543)) return; - /* Ignore Checksum bit is set */ - if (unlikely(status & E1000_RXD_STAT_IXSM)) return; - /* TCP/UDP checksum error bit is set */ - if (unlikely(errors & E1000_RXD_ERR_TCPE)) { - /* let the stack verify checksum errors */ - adapter->hw_csum_err++; - return; - } - /* TCP/UDP Checksum has not been calculated */ - if (!(status & E1000_RXD_STAT_TCPCS)) - return; - - /* It must be a TCP or UDP packet with a valid checksum */ - if (likely(status & E1000_RXD_STAT_TCPCS)) { - /* TCP checksum is good */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - } - adapter->hw_csum_good++; -} - -/** - * e1000_consume_page - helper function - **/ -static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb, - u16 length) -{ - bi->page = NULL; - skb->len += length; - skb->data_len += length; - skb->truesize += PAGE_SIZE; -} - -/** - * e1000_receive_skb - helper function to handle rx indications - * @adapter: board private structure - * @status: descriptor status field as written by hardware - * @vlan: descriptor vlan field as written by hardware (no le/be conversion) - * @skb: pointer to sk_buff to be indicated to stack - */ -static void e1000_receive_skb(struct e1000_adapter *adapter, u8 status, - __le16 vlan, struct sk_buff *skb) -{ - skb->protocol = eth_type_trans(skb, adapter->netdev); - - if (status & E1000_RXD_STAT_VP) { - u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; - - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); - } - napi_gro_receive(&adapter->napi, skb); -} - -/** - * e1000_clean_jumbo_rx_irq - Send received data up the network stack; legacy - * @adapter: board private structure - * @rx_ring: ring to clean - * @work_done: amount of napi work completed this call - * @work_to_do: max amount of work allowed for this call to do - * - * the return value indicates whether actual cleaning was done, there - * is no guarantee that everything was cleaned - */ -static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int *work_done, int work_to_do) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_rx_desc *rx_desc, *next_rxd; - struct e1000_buffer *buffer_info, *next_buffer; - unsigned long irq_flags; - u32 length; - unsigned int i; - int cleaned_count = 0; - bool cleaned = false; - unsigned int total_rx_bytes=0, total_rx_packets=0; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC(*rx_ring, i); - buffer_info = &rx_ring->buffer_info[i]; - - while (rx_desc->status & E1000_RXD_STAT_DD) { - struct sk_buff *skb; - u8 status; - - if (*work_done >= work_to_do) - break; - (*work_done)++; - rmb(); /* read descriptor and rx_buffer_info after status DD */ - - status = rx_desc->status; - skb = buffer_info->skb; - buffer_info->skb = NULL; - - if (++i == rx_ring->count) i = 0; - next_rxd = E1000_RX_DESC(*rx_ring, i); - prefetch(next_rxd); - - next_buffer = &rx_ring->buffer_info[i]; - - cleaned = true; - cleaned_count++; - dma_unmap_page(&pdev->dev, buffer_info->dma, - buffer_info->length, DMA_FROM_DEVICE); - buffer_info->dma = 0; - - length = le16_to_cpu(rx_desc->length); - - /* errors is only valid for DD + EOP descriptors */ - if (unlikely((status & E1000_RXD_STAT_EOP) && - (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) { - u8 *mapped; - u8 last_byte; - - mapped = page_address(buffer_info->page); - last_byte = *(mapped + length - 1); - if (TBI_ACCEPT(hw, status, rx_desc->errors, length, - last_byte)) { - spin_lock_irqsave(&adapter->stats_lock, - irq_flags); - e1000_tbi_adjust_stats(hw, &adapter->stats, - length, mapped); - spin_unlock_irqrestore(&adapter->stats_lock, - irq_flags); - length--; - } else { - if (netdev->features & NETIF_F_RXALL) - goto process_skb; - /* recycle both page and skb */ - buffer_info->skb = skb; - /* an error means any chain goes out the window - * too - */ - if (rx_ring->rx_skb_top) - dev_kfree_skb(rx_ring->rx_skb_top); - rx_ring->rx_skb_top = NULL; - goto next_desc; - } - } - -#define rxtop rx_ring->rx_skb_top -process_skb: - if (!(status & E1000_RXD_STAT_EOP)) { - /* this descriptor is only the beginning (or middle) */ - if (!rxtop) { - /* this is the beginning of a chain */ - rxtop = skb; - skb_fill_page_desc(rxtop, 0, buffer_info->page, - 0, length); - } else { - /* this is the middle of a chain */ - skb_fill_page_desc(rxtop, - skb_shinfo(rxtop)->nr_frags, - buffer_info->page, 0, length); - /* re-use the skb, only consumed the page */ - buffer_info->skb = skb; - } - e1000_consume_page(buffer_info, rxtop, length); - goto next_desc; - } else { - if (rxtop) { - /* end of the chain */ - skb_fill_page_desc(rxtop, - skb_shinfo(rxtop)->nr_frags, - buffer_info->page, 0, length); - /* re-use the current skb, we only consumed the - * page - */ - buffer_info->skb = skb; - skb = rxtop; - rxtop = NULL; - e1000_consume_page(buffer_info, skb, length); - } else { - /* no chain, got EOP, this buf is the packet - * copybreak to save the put_page/alloc_page - */ - if (length <= copybreak && - skb_tailroom(skb) >= length) { - u8 *vaddr; - vaddr = kmap_atomic(buffer_info->page); - memcpy(skb_tail_pointer(skb), vaddr, - length); - kunmap_atomic(vaddr); - /* re-use the page, so don't erase - * buffer_info->page - */ - skb_put(skb, length); - } else { - skb_fill_page_desc(skb, 0, - buffer_info->page, 0, - length); - e1000_consume_page(buffer_info, skb, - length); - } - } - } - - /* Receive Checksum Offload XXX recompute due to CRC strip? */ - e1000_rx_checksum(adapter, - (u32)(status) | - ((u32)(rx_desc->errors) << 24), - le16_to_cpu(rx_desc->csum), skb); - - total_rx_bytes += (skb->len - 4); /* don't count FCS */ - if (likely(!(netdev->features & NETIF_F_RXFCS))) - pskb_trim(skb, skb->len - 4); - total_rx_packets++; - - /* eth type trans needs skb->data to point to something */ - if (!pskb_may_pull(skb, ETH_HLEN)) { - e_err(drv, "pskb_may_pull failed.\n"); - dev_kfree_skb(skb); - goto next_desc; - } - - e1000_receive_skb(adapter, status, rx_desc->special, skb); - -next_desc: - rx_desc->status = 0; - - /* return some buffers to hardware, one at a time is too slow */ - if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { - adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); - cleaned_count = 0; - } - - /* use prefetched values */ - rx_desc = next_rxd; - buffer_info = next_buffer; - } - rx_ring->next_to_clean = i; - - cleaned_count = E1000_DESC_UNUSED(rx_ring); - if (cleaned_count) - adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); - - adapter->total_rx_packets += total_rx_packets; - adapter->total_rx_bytes += total_rx_bytes; - netdev->stats.rx_bytes += total_rx_bytes; - netdev->stats.rx_packets += total_rx_packets; - return cleaned; -} - -/* this should improve performance for small packets with large amounts - * of reassembly being done in the stack - */ -static void e1000_check_copybreak(struct net_device *netdev, - struct e1000_buffer *buffer_info, - u32 length, struct sk_buff **skb) -{ - struct sk_buff *new_skb; - - if (length > copybreak) - return; - - new_skb = netdev_alloc_skb_ip_align(netdev, length); - if (!new_skb) - return; - - skb_copy_to_linear_data_offset(new_skb, -NET_IP_ALIGN, - (*skb)->data - NET_IP_ALIGN, - length + NET_IP_ALIGN); - /* save the skb in buffer_info as good */ - buffer_info->skb = *skb; - *skb = new_skb; -} - -/** - * e1000_clean_rx_irq - Send received data up the network stack; legacy - * @adapter: board private structure - * @rx_ring: ring to clean - * @work_done: amount of napi work completed this call - * @work_to_do: max amount of work allowed for this call to do - */ -static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int *work_done, int work_to_do) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_rx_desc *rx_desc, *next_rxd; - struct e1000_buffer *buffer_info, *next_buffer; - unsigned long flags; - u32 length; - unsigned int i; - int cleaned_count = 0; - bool cleaned = false; - unsigned int total_rx_bytes=0, total_rx_packets=0; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC(*rx_ring, i); - buffer_info = &rx_ring->buffer_info[i]; - - while (rx_desc->status & E1000_RXD_STAT_DD) { - struct sk_buff *skb; - u8 status; - - if (*work_done >= work_to_do) - break; - (*work_done)++; - rmb(); /* read descriptor and rx_buffer_info after status DD */ - - status = rx_desc->status; - skb = buffer_info->skb; - buffer_info->skb = NULL; - - prefetch(skb->data - NET_IP_ALIGN); - - if (++i == rx_ring->count) i = 0; - next_rxd = E1000_RX_DESC(*rx_ring, i); - prefetch(next_rxd); - - next_buffer = &rx_ring->buffer_info[i]; - - cleaned = true; - cleaned_count++; - dma_unmap_single(&pdev->dev, buffer_info->dma, - buffer_info->length, DMA_FROM_DEVICE); - buffer_info->dma = 0; - - length = le16_to_cpu(rx_desc->length); - /* !EOP means multiple descriptors were used to store a single - * packet, if thats the case we need to toss it. In fact, we - * to toss every packet with the EOP bit clear and the next - * frame that _does_ have the EOP bit set, as it is by - * definition only a frame fragment - */ - if (unlikely(!(status & E1000_RXD_STAT_EOP))) - adapter->discarding = true; - - if (adapter->discarding) { - /* All receives must fit into a single buffer */ - e_dbg("Receive packet consumed multiple buffers\n"); - /* recycle */ - buffer_info->skb = skb; - if (status & E1000_RXD_STAT_EOP) - adapter->discarding = false; - goto next_desc; - } - - if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { - u8 last_byte = *(skb->data + length - 1); - if (TBI_ACCEPT(hw, status, rx_desc->errors, length, - last_byte)) { - spin_lock_irqsave(&adapter->stats_lock, flags); - e1000_tbi_adjust_stats(hw, &adapter->stats, - length, skb->data); - spin_unlock_irqrestore(&adapter->stats_lock, - flags); - length--; - } else { - if (netdev->features & NETIF_F_RXALL) - goto process_skb; - /* recycle */ - buffer_info->skb = skb; - goto next_desc; - } - } - -process_skb: - total_rx_bytes += (length - 4); /* don't count FCS */ - total_rx_packets++; - - if (likely(!(netdev->features & NETIF_F_RXFCS))) - /* adjust length to remove Ethernet CRC, this must be - * done after the TBI_ACCEPT workaround above - */ - length -= 4; - - e1000_check_copybreak(netdev, buffer_info, length, &skb); - - skb_put(skb, length); - - /* Receive Checksum Offload */ - e1000_rx_checksum(adapter, - (u32)(status) | - ((u32)(rx_desc->errors) << 24), - le16_to_cpu(rx_desc->csum), skb); - - e1000_receive_skb(adapter, status, rx_desc->special, skb); - -next_desc: - rx_desc->status = 0; - - /* return some buffers to hardware, one at a time is too slow */ - if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { - adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); - cleaned_count = 0; - } - - /* use prefetched values */ - rx_desc = next_rxd; - buffer_info = next_buffer; - } - rx_ring->next_to_clean = i; - - cleaned_count = E1000_DESC_UNUSED(rx_ring); - if (cleaned_count) - adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); - - adapter->total_rx_packets += total_rx_packets; - adapter->total_rx_bytes += total_rx_bytes; - netdev->stats.rx_bytes += total_rx_bytes; - netdev->stats.rx_packets += total_rx_packets; - return cleaned; -} - -/** - * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers - * @adapter: address of board private structure - * @rx_ring: pointer to receive ring structure - * @cleaned_count: number of buffers to allocate this pass - **/ -static void -e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, int cleaned_count) -{ - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_rx_desc *rx_desc; - struct e1000_buffer *buffer_info; - struct sk_buff *skb; - unsigned int i; - unsigned int bufsz = 256 - 16 /*for skb_reserve */ ; - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - - while (cleaned_count--) { - skb = buffer_info->skb; - if (skb) { - skb_trim(skb, 0); - goto check_page; - } - - skb = netdev_alloc_skb_ip_align(netdev, bufsz); - if (unlikely(!skb)) { - /* Better luck next round */ - adapter->alloc_rx_buff_failed++; - break; - } - - buffer_info->skb = skb; - buffer_info->length = adapter->rx_buffer_len; -check_page: - /* allocate a new page if necessary */ - if (!buffer_info->page) { - buffer_info->page = alloc_page(GFP_ATOMIC); - if (unlikely(!buffer_info->page)) { - adapter->alloc_rx_buff_failed++; - break; - } - } - - if (!buffer_info->dma) { - buffer_info->dma = dma_map_page(&pdev->dev, - buffer_info->page, 0, - buffer_info->length, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { - put_page(buffer_info->page); - dev_kfree_skb(skb); - buffer_info->page = NULL; - buffer_info->skb = NULL; - buffer_info->dma = 0; - adapter->alloc_rx_buff_failed++; - break; /* while !buffer_info->skb */ - } - } - - rx_desc = E1000_RX_DESC(*rx_ring, i); - rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - - if (unlikely(++i == rx_ring->count)) - i = 0; - buffer_info = &rx_ring->buffer_info[i]; - } - - if (likely(rx_ring->next_to_use != i)) { - rx_ring->next_to_use = i; - if (unlikely(i-- == 0)) - i = (rx_ring->count - 1); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - writel(i, adapter->hw.hw_addr + rx_ring->rdt); - } -} - -/** - * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended - * @adapter: address of board private structure - **/ -static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_rx_desc *rx_desc; - struct e1000_buffer *buffer_info; - struct sk_buff *skb; - unsigned int i; - unsigned int bufsz = adapter->rx_buffer_len; - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - - while (cleaned_count--) { - skb = buffer_info->skb; - if (skb) { - skb_trim(skb, 0); - goto map_skb; - } - - skb = netdev_alloc_skb_ip_align(netdev, bufsz); - if (unlikely(!skb)) { - /* Better luck next round */ - adapter->alloc_rx_buff_failed++; - break; - } - - /* Fix for errata 23, can't cross 64kB boundary */ - if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) { - struct sk_buff *oldskb = skb; - e_err(rx_err, "skb align check failed: %u bytes at " - "%p\n", bufsz, skb->data); - /* Try again, without freeing the previous */ - skb = netdev_alloc_skb_ip_align(netdev, bufsz); - /* Failed allocation, critical failure */ - if (!skb) { - dev_kfree_skb(oldskb); - adapter->alloc_rx_buff_failed++; - break; - } - - if (!e1000_check_64k_bound(adapter, skb->data, bufsz)) { - /* give up */ - dev_kfree_skb(skb); - dev_kfree_skb(oldskb); - adapter->alloc_rx_buff_failed++; - break; /* while !buffer_info->skb */ - } - - /* Use new allocation */ - dev_kfree_skb(oldskb); - } - buffer_info->skb = skb; - buffer_info->length = adapter->rx_buffer_len; -map_skb: - buffer_info->dma = dma_map_single(&pdev->dev, - skb->data, - buffer_info->length, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { - dev_kfree_skb(skb); - buffer_info->skb = NULL; - buffer_info->dma = 0; - adapter->alloc_rx_buff_failed++; - break; /* while !buffer_info->skb */ - } - - /* XXX if it was allocated cleanly it will never map to a - * boundary crossing - */ - - /* Fix for errata 23, can't cross 64kB boundary */ - if (!e1000_check_64k_bound(adapter, - (void *)(unsigned long)buffer_info->dma, - adapter->rx_buffer_len)) { - e_err(rx_err, "dma align check failed: %u bytes at " - "%p\n", adapter->rx_buffer_len, - (void *)(unsigned long)buffer_info->dma); - dev_kfree_skb(skb); - buffer_info->skb = NULL; - - dma_unmap_single(&pdev->dev, buffer_info->dma, - adapter->rx_buffer_len, - DMA_FROM_DEVICE); - buffer_info->dma = 0; - - adapter->alloc_rx_buff_failed++; - break; /* while !buffer_info->skb */ - } - rx_desc = E1000_RX_DESC(*rx_ring, i); - rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - - if (unlikely(++i == rx_ring->count)) - i = 0; - buffer_info = &rx_ring->buffer_info[i]; - } - - if (likely(rx_ring->next_to_use != i)) { - rx_ring->next_to_use = i; - if (unlikely(i-- == 0)) - i = (rx_ring->count - 1); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - writel(i, hw->hw_addr + rx_ring->rdt); - } -} - -/** - * e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers. - * @adapter: - **/ -static void e1000_smartspeed(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u16 phy_status; - u16 phy_ctrl; - - if ((hw->phy_type != e1000_phy_igp) || !hw->autoneg || - !(hw->autoneg_advertised & ADVERTISE_1000_FULL)) - return; - - if (adapter->smartspeed == 0) { - /* If Master/Slave config fault is asserted twice, - * we assume back-to-back - */ - e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status); - if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return; - e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status); - if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return; - e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl); - if (phy_ctrl & CR_1000T_MS_ENABLE) { - phy_ctrl &= ~CR_1000T_MS_ENABLE; - e1000_write_phy_reg(hw, PHY_1000T_CTRL, - phy_ctrl); - adapter->smartspeed++; - if (!e1000_phy_setup_autoneg(hw) && - !e1000_read_phy_reg(hw, PHY_CTRL, - &phy_ctrl)) { - phy_ctrl |= (MII_CR_AUTO_NEG_EN | - MII_CR_RESTART_AUTO_NEG); - e1000_write_phy_reg(hw, PHY_CTRL, - phy_ctrl); - } - } - return; - } else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) { - /* If still no link, perhaps using 2/3 pair cable */ - e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl); - phy_ctrl |= CR_1000T_MS_ENABLE; - e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_ctrl); - if (!e1000_phy_setup_autoneg(hw) && - !e1000_read_phy_reg(hw, PHY_CTRL, &phy_ctrl)) { - phy_ctrl |= (MII_CR_AUTO_NEG_EN | - MII_CR_RESTART_AUTO_NEG); - e1000_write_phy_reg(hw, PHY_CTRL, phy_ctrl); - } - } - /* Restart process after E1000_SMARTSPEED_MAX iterations */ - if (adapter->smartspeed++ == E1000_SMARTSPEED_MAX) - adapter->smartspeed = 0; -} - -/** - * e1000_ioctl - - * @netdev: - * @ifreq: - * @cmd: - **/ -static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return e1000_mii_ioctl(netdev, ifr, cmd); - default: - return -EOPNOTSUPP; - } -} - -/** - * e1000_mii_ioctl - - * @netdev: - * @ifreq: - * @cmd: - **/ -static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, - int cmd) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct mii_ioctl_data *data = if_mii(ifr); - int retval; - u16 mii_reg; - unsigned long flags; - - if (hw->media_type != e1000_media_type_copper) - return -EOPNOTSUPP; - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = hw->phy_addr; - break; - case SIOCGMIIREG: - spin_lock_irqsave(&adapter->stats_lock, flags); - if (e1000_read_phy_reg(hw, data->reg_num & 0x1F, - &data->val_out)) { - spin_unlock_irqrestore(&adapter->stats_lock, flags); - return -EIO; - } - spin_unlock_irqrestore(&adapter->stats_lock, flags); - break; - case SIOCSMIIREG: - if (data->reg_num & ~(0x1F)) - return -EFAULT; - mii_reg = data->val_in; - spin_lock_irqsave(&adapter->stats_lock, flags); - if (e1000_write_phy_reg(hw, data->reg_num, - mii_reg)) { - spin_unlock_irqrestore(&adapter->stats_lock, flags); - return -EIO; - } - spin_unlock_irqrestore(&adapter->stats_lock, flags); - if (hw->media_type == e1000_media_type_copper) { - switch (data->reg_num) { - case PHY_CTRL: - if (mii_reg & MII_CR_POWER_DOWN) - break; - if (mii_reg & MII_CR_AUTO_NEG_EN) { - hw->autoneg = 1; - hw->autoneg_advertised = 0x2F; - } else { - u32 speed; - if (mii_reg & 0x40) - speed = SPEED_1000; - else if (mii_reg & 0x2000) - speed = SPEED_100; - else - speed = SPEED_10; - retval = e1000_set_spd_dplx( - adapter, speed, - ((mii_reg & 0x100) - ? DUPLEX_FULL : - DUPLEX_HALF)); - if (retval) - return retval; - } - if (netif_running(adapter->netdev)) - e1000_reinit_locked(adapter); - else - e1000_reset(adapter); - break; - case M88E1000_PHY_SPEC_CTRL: - case M88E1000_EXT_PHY_SPEC_CTRL: - if (e1000_phy_reset(hw)) - return -EIO; - break; - } - } else { - switch (data->reg_num) { - case PHY_CTRL: - if (mii_reg & MII_CR_POWER_DOWN) - break; - if (netif_running(adapter->netdev)) - e1000_reinit_locked(adapter); - else - e1000_reset(adapter); - break; - } - } - break; - default: - return -EOPNOTSUPP; - } - return E1000_SUCCESS; -} - -void e1000_pci_set_mwi(struct e1000_hw *hw) -{ - struct e1000_adapter *adapter = hw->back; - int ret_val = pci_set_mwi(adapter->pdev); - - if (ret_val) - e_err(probe, "Error in setting MWI\n"); -} - -void e1000_pci_clear_mwi(struct e1000_hw *hw) -{ - struct e1000_adapter *adapter = hw->back; - - pci_clear_mwi(adapter->pdev); -} - -int e1000_pcix_get_mmrbc(struct e1000_hw *hw) -{ - struct e1000_adapter *adapter = hw->back; - return pcix_get_mmrbc(adapter->pdev); -} - -void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc) -{ - struct e1000_adapter *adapter = hw->back; - pcix_set_mmrbc(adapter->pdev, mmrbc); -} - -void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value) -{ - outl(value, port); -} - -static bool e1000_vlan_used(struct e1000_adapter *adapter) -{ - u16 vid; - - for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) - return true; - return false; -} - -static void __e1000_vlan_mode(struct e1000_adapter *adapter, - netdev_features_t features) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl; - - ctrl = er32(CTRL); - if (features & NETIF_F_HW_VLAN_CTAG_RX) { - /* enable VLAN tag insert/strip */ - ctrl |= E1000_CTRL_VME; - } else { - /* disable VLAN tag insert/strip */ - ctrl &= ~E1000_CTRL_VME; - } - ew32(CTRL, ctrl); -} -static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter, - bool filter_on) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_disable(adapter); - - __e1000_vlan_mode(adapter, adapter->netdev->features); - if (filter_on) { - /* enable VLAN receive filtering */ - rctl = er32(RCTL); - rctl &= ~E1000_RCTL_CFIEN; - if (!(adapter->netdev->flags & IFF_PROMISC)) - rctl |= E1000_RCTL_VFE; - ew32(RCTL, rctl); - e1000_update_mng_vlan(adapter); - } else { - /* disable VLAN receive filtering */ - rctl = er32(RCTL); - rctl &= ~E1000_RCTL_VFE; - ew32(RCTL, rctl); - } - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_enable(adapter); -} - -static void e1000_vlan_mode(struct net_device *netdev, - netdev_features_t features) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_disable(adapter); - - __e1000_vlan_mode(adapter, features); - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_enable(adapter); -} - -static int e1000_vlan_rx_add_vid(struct net_device *netdev, - __be16 proto, u16 vid) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 vfta, index; - - if ((hw->mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && - (vid == adapter->mng_vlan_id)) - return 0; - - if (!e1000_vlan_used(adapter)) - e1000_vlan_filter_on_off(adapter, true); - - /* add VID to filter table */ - index = (vid >> 5) & 0x7F; - vfta = E1000_READ_REG_ARRAY(hw, VFTA, index); - vfta |= (1 << (vid & 0x1F)); - e1000_write_vfta(hw, index, vfta); - - set_bit(vid, adapter->active_vlans); - - return 0; -} - -static int e1000_vlan_rx_kill_vid(struct net_device *netdev, - __be16 proto, u16 vid) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 vfta, index; - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_disable(adapter); - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_enable(adapter); - - /* remove VID from filter table */ - index = (vid >> 5) & 0x7F; - vfta = E1000_READ_REG_ARRAY(hw, VFTA, index); - vfta &= ~(1 << (vid & 0x1F)); - e1000_write_vfta(hw, index, vfta); - - clear_bit(vid, adapter->active_vlans); - - if (!e1000_vlan_used(adapter)) - e1000_vlan_filter_on_off(adapter, false); - - return 0; -} - -static void e1000_restore_vlan(struct e1000_adapter *adapter) -{ - u16 vid; - - if (!e1000_vlan_used(adapter)) - return; - - e1000_vlan_filter_on_off(adapter, true); - for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) - e1000_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid); -} - -int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx) -{ - struct e1000_hw *hw = &adapter->hw; - - hw->autoneg = 0; - - /* Make sure dplx is at most 1 bit and lsb of speed is not set - * for the switch() below to work - */ - if ((spd & 1) || (dplx & ~1)) - goto err_inval; - - /* Fiber NICs only allow 1000 gbps Full duplex */ - if ((hw->media_type == e1000_media_type_fiber) && - spd != SPEED_1000 && - dplx != DUPLEX_FULL) - goto err_inval; - - switch (spd + dplx) { - case SPEED_10 + DUPLEX_HALF: - hw->forced_speed_duplex = e1000_10_half; - break; - case SPEED_10 + DUPLEX_FULL: - hw->forced_speed_duplex = e1000_10_full; - break; - case SPEED_100 + DUPLEX_HALF: - hw->forced_speed_duplex = e1000_100_half; - break; - case SPEED_100 + DUPLEX_FULL: - hw->forced_speed_duplex = e1000_100_full; - break; - case SPEED_1000 + DUPLEX_FULL: - hw->autoneg = 1; - hw->autoneg_advertised = ADVERTISE_1000_FULL; - break; - case SPEED_1000 + DUPLEX_HALF: /* not supported */ - default: - goto err_inval; - } - - /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ - hw->mdix = AUTO_ALL_MODES; - - return 0; - -err_inval: - e_err(probe, "Unsupported Speed/Duplex configuration\n"); - return -EINVAL; -} - -static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 ctrl, ctrl_ext, rctl, status; - u32 wufc = adapter->wol; -#ifdef CONFIG_PM - int retval = 0; -#endif - - netif_device_detach(netdev); - - if (netif_running(netdev)) { - WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); - e1000_down(adapter); - } - -#ifdef CONFIG_PM - retval = pci_save_state(pdev); - if (retval) - return retval; -#endif - - status = er32(STATUS); - if (status & E1000_STATUS_LU) - wufc &= ~E1000_WUFC_LNKC; - - if (wufc) { - e1000_setup_rctl(adapter); - e1000_set_rx_mode(netdev); - - rctl = er32(RCTL); - - /* turn on all-multi mode if wake on multicast is enabled */ - if (wufc & E1000_WUFC_MC) - rctl |= E1000_RCTL_MPE; - - /* enable receives in the hardware */ - ew32(RCTL, rctl | E1000_RCTL_EN); - - if (hw->mac_type >= e1000_82540) { - ctrl = er32(CTRL); - /* advertise wake from D3Cold */ - #define E1000_CTRL_ADVD3WUC 0x00100000 - /* phy power management enable */ - #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 - ctrl |= E1000_CTRL_ADVD3WUC | - E1000_CTRL_EN_PHY_PWR_MGMT; - ew32(CTRL, ctrl); - } - - if (hw->media_type == e1000_media_type_fiber || - hw->media_type == e1000_media_type_internal_serdes) { - /* keep the laser running in D3 */ - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; - ew32(CTRL_EXT, ctrl_ext); - } - - ew32(WUC, E1000_WUC_PME_EN); - ew32(WUFC, wufc); - } else { - ew32(WUC, 0); - ew32(WUFC, 0); - } - - e1000_release_manageability(adapter); - - *enable_wake = !!wufc; - - /* make sure adapter isn't asleep if manageability is enabled */ - if (adapter->en_mng_pt) - *enable_wake = true; - - if (netif_running(netdev)) - e1000_free_irq(adapter); - - pci_disable_device(pdev); - - return 0; -} - -#ifdef CONFIG_PM -static int e1000_suspend(struct pci_dev *pdev, pm_message_t state) -{ - int retval; - bool wake; - - retval = __e1000_shutdown(pdev, &wake); - if (retval) - return retval; - - if (wake) { - pci_prepare_to_sleep(pdev); - } else { - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - } - - return 0; -} - -static int e1000_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 err; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_save_state(pdev); - - if (adapter->need_ioport) - err = pci_enable_device(pdev); - else - err = pci_enable_device_mem(pdev); - if (err) { - pr_err("Cannot enable PCI device from suspend\n"); - return err; - } - pci_set_master(pdev); - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - if (netif_running(netdev)) { - err = e1000_request_irq(adapter); - if (err) - return err; - } - - e1000_power_up_phy(adapter); - e1000_reset(adapter); - ew32(WUS, ~0); - - e1000_init_manageability(adapter); - - if (netif_running(netdev)) - e1000_up(adapter); - - netif_device_attach(netdev); - - return 0; -} -#endif - -static void e1000_shutdown(struct pci_dev *pdev) -{ - bool wake; - - __e1000_shutdown(pdev, &wake); - - if (system_state == SYSTEM_POWER_OFF) { - pci_wake_from_d3(pdev, wake); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void e1000_netpoll(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - disable_irq(adapter->pdev->irq); - e1000_intr(adapter->pdev->irq, netdev); - enable_irq(adapter->pdev->irq); -} -#endif - -/** - * e1000_io_error_detected - called when PCI error is detected - * @pdev: Pointer to PCI device - * @state: The current pci connection state - * - * This function is called after a PCI bus error affecting - * this device has been detected. - */ -static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, - pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e1000_down(adapter); - pci_disable_device(pdev); - - /* Request a slot slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e1000_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch, as if from a cold-boot. Implementation - * resembles the first-half of the e1000_resume routine. - */ -static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - int err; - - if (adapter->need_ioport) - err = pci_enable_device(pdev); - else - err = pci_enable_device_mem(pdev); - if (err) { - pr_err("Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - pci_set_master(pdev); - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - e1000_reset(adapter); - ew32(WUS, ~0); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e1000_io_resume - called when traffic can start flowing again. - * @pdev: Pointer to PCI device - * - * This callback is called when the error recovery driver tells us that - * its OK to resume normal operation. Implementation resembles the - * second-half of the e1000_resume routine. - */ -static void e1000_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - - e1000_init_manageability(adapter); - - if (netif_running(netdev)) { - if (e1000_up(adapter)) { - pr_info("can't bring device back up after reset\n"); - return; - } - } - - netif_device_attach(netdev); -} - -/* e1000_main.c */ diff --git a/addons/e1000/src/3.10.108/e1000_osdep.h b/addons/e1000/src/3.10.108/e1000_osdep.h deleted file mode 100644 index 33e7c45a..00000000 --- a/addons/e1000/src/3.10.108/e1000_osdep.h +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - - -/* glue for the OS independent part of e1000 - * includes register access macros - */ - -#ifndef _E1000_OSDEP_H_ -#define _E1000_OSDEP_H_ - -#include - -#define CONFIG_RAM_BASE 0x60000 -#define GBE_CONFIG_OFFSET 0x0 - -#define GBE_CONFIG_RAM_BASE \ - ((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET)) - -#define GBE_CONFIG_BASE_VIRT \ - ((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE)) - -#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \ - (iowrite16_rep(base + offset, data, count)) - -#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \ - (ioread16_rep(base + (offset << 1), data, count)) - -#define er32(reg) \ - (readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \ - ? E1000_##reg : E1000_82542_##reg))) - -#define ew32(reg, value) \ - (writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \ - ? E1000_##reg : E1000_82542_##reg)))) - -#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \ - writel((value), ((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - ((offset) << 2)))) - -#define E1000_READ_REG_ARRAY(a, reg, offset) ( \ - readl((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - ((offset) << 2))) - -#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY -#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY - -#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \ - writew((value), ((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - ((offset) << 1)))) - -#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \ - readw((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - ((offset) << 1))) - -#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \ - writeb((value), ((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - (offset)))) - -#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \ - readb((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - (offset))) - -#define E1000_WRITE_FLUSH() er32(STATUS) - -#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \ - writel((value), ((a)->flash_address + reg))) - -#define E1000_READ_ICH_FLASH_REG(a, reg) ( \ - readl((a)->flash_address + reg)) - -#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \ - writew((value), ((a)->flash_address + reg))) - -#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \ - readw((a)->flash_address + reg)) - -#endif /* _E1000_OSDEP_H_ */ diff --git a/addons/e1000/src/3.10.108/e1000_param.c b/addons/e1000/src/3.10.108/e1000_param.c deleted file mode 100644 index c9cde352..00000000 --- a/addons/e1000/src/3.10.108/e1000_param.c +++ /dev/null @@ -1,754 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include "e1000.h" - -/* This is the only thing that needs to be changed to adjust the - * maximum number of ports that the driver can manage. - */ - -#define E1000_MAX_NIC 32 - -#define OPTION_UNSET -1 -#define OPTION_DISABLED 0 -#define OPTION_ENABLED 1 - -/* All parameters are treated the same, as an integer array of values. - * This macro just reduces the need to repeat the same declaration code - * over and over (plus this helps to avoid typo bugs). - */ - -#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } -#define E1000_PARAM(X, desc) \ - static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ - static unsigned int num_##X; \ - module_param_array_named(X, X, int, &num_##X, 0); \ - MODULE_PARM_DESC(X, desc); - -/* Transmit Descriptor Count - * - * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers - * Valid Range: 80-4096 for 82544 and newer - * - * Default Value: 256 - */ -E1000_PARAM(TxDescriptors, "Number of transmit descriptors"); - -/* Receive Descriptor Count - * - * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers - * Valid Range: 80-4096 for 82544 and newer - * - * Default Value: 256 - */ -E1000_PARAM(RxDescriptors, "Number of receive descriptors"); - -/* User Specified Speed Override - * - * Valid Range: 0, 10, 100, 1000 - * - 0 - auto-negotiate at all supported speeds - * - 10 - only link at 10 Mbps - * - 100 - only link at 100 Mbps - * - 1000 - only link at 1000 Mbps - * - * Default Value: 0 - */ -E1000_PARAM(Speed, "Speed setting"); - -/* User Specified Duplex Override - * - * Valid Range: 0-2 - * - 0 - auto-negotiate for duplex - * - 1 - only link at half duplex - * - 2 - only link at full duplex - * - * Default Value: 0 - */ -E1000_PARAM(Duplex, "Duplex setting"); - -/* Auto-negotiation Advertisement Override - * - * Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber) - * - * The AutoNeg value is a bit mask describing which speed and duplex - * combinations should be advertised during auto-negotiation. - * The supported speed and duplex modes are listed below - * - * Bit 7 6 5 4 3 2 1 0 - * Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10 - * Duplex Full Full Half Full Half - * - * Default Value: 0x2F (copper); 0x20 (fiber) - */ -E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting"); -#define AUTONEG_ADV_DEFAULT 0x2F -#define AUTONEG_ADV_MASK 0x2F - -/* User Specified Flow Control Override - * - * Valid Range: 0-3 - * - 0 - No Flow Control - * - 1 - Rx only, respond to PAUSE frames but do not generate them - * - 2 - Tx only, generate PAUSE frames but ignore them on receive - * - 3 - Full Flow Control Support - * - * Default Value: Read flow control settings from the EEPROM - */ -E1000_PARAM(FlowControl, "Flow Control setting"); -#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL - -/* XsumRX - Receive Checksum Offload Enable/Disable - * - * Valid Range: 0, 1 - * - 0 - disables all checksum offload - * - 1 - enables receive IP/TCP/UDP checksum offload - * on 82543 and newer -based NICs - * - * Default Value: 1 - */ -E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload"); - -/* Transmit Interrupt Delay in units of 1.024 microseconds - * Tx interrupt delay needs to typically be set to something non zero - * - * Valid Range: 0-65535 - */ -E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay"); -#define DEFAULT_TIDV 8 -#define MAX_TXDELAY 0xFFFF -#define MIN_TXDELAY 0 - -/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds - * - * Valid Range: 0-65535 - */ -E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay"); -#define DEFAULT_TADV 32 -#define MAX_TXABSDELAY 0xFFFF -#define MIN_TXABSDELAY 0 - -/* Receive Interrupt Delay in units of 1.024 microseconds - * hardware will likely hang if you set this to anything but zero. - * - * Valid Range: 0-65535 - */ -E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); -#define DEFAULT_RDTR 0 -#define MAX_RXDELAY 0xFFFF -#define MIN_RXDELAY 0 - -/* Receive Absolute Interrupt Delay in units of 1.024 microseconds - * - * Valid Range: 0-65535 - */ -E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); -#define DEFAULT_RADV 8 -#define MAX_RXABSDELAY 0xFFFF -#define MIN_RXABSDELAY 0 - -/* Interrupt Throttle Rate (interrupts/sec) - * - * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative) - */ -E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); -#define DEFAULT_ITR 3 -#define MAX_ITR 100000 -#define MIN_ITR 100 - -/* Enable Smart Power Down of the PHY - * - * Valid Range: 0, 1 - * - * Default Value: 0 (disabled) - */ -E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down"); - -struct e1000_option { - enum { enable_option, range_option, list_option } type; - const char *name; - const char *err; - int def; - union { - struct { /* range_option info */ - int min; - int max; - } r; - struct { /* list_option info */ - int nr; - const struct e1000_opt_list { int i; char *str; } *p; - } l; - } arg; -}; - -static int e1000_validate_option(unsigned int *value, - const struct e1000_option *opt, - struct e1000_adapter *adapter) -{ - if (*value == OPTION_UNSET) { - *value = opt->def; - return 0; - } - - switch (opt->type) { - case enable_option: - switch (*value) { - case OPTION_ENABLED: - e_dev_info("%s Enabled\n", opt->name); - return 0; - case OPTION_DISABLED: - e_dev_info("%s Disabled\n", opt->name); - return 0; - } - break; - case range_option: - if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { - e_dev_info("%s set to %i\n", opt->name, *value); - return 0; - } - break; - case list_option: { - int i; - const struct e1000_opt_list *ent; - - for (i = 0; i < opt->arg.l.nr; i++) { - ent = &opt->arg.l.p[i]; - if (*value == ent->i) { - if (ent->str[0] != '\0') - e_dev_info("%s\n", ent->str); - return 0; - } - } - } - break; - default: - BUG(); - } - - e_dev_info("Invalid %s value specified (%i) %s\n", - opt->name, *value, opt->err); - *value = opt->def; - return -1; -} - -static void e1000_check_fiber_options(struct e1000_adapter *adapter); -static void e1000_check_copper_options(struct e1000_adapter *adapter); - -/** - * e1000_check_options - Range Checking for Command Line Parameters - * @adapter: board private structure - * - * This routine checks all command line parameters for valid user - * input. If an invalid value is given, or if no user specified - * value exists, a default value is used. The final value is stored - * in a variable in the adapter structure. - **/ -void e1000_check_options(struct e1000_adapter *adapter) -{ - struct e1000_option opt; - int bd = adapter->bd_number; - - if (bd >= E1000_MAX_NIC) { - e_dev_warn("Warning: no configuration for board #%i " - "using defaults for all values\n", bd); - } - - { /* Transmit Descriptor Count */ - struct e1000_tx_ring *tx_ring = adapter->tx_ring; - int i; - e1000_mac_type mac_type = adapter->hw.mac_type; - - opt = (struct e1000_option) { - .type = range_option, - .name = "Transmit Descriptors", - .err = "using default of " - __MODULE_STRING(E1000_DEFAULT_TXD), - .def = E1000_DEFAULT_TXD, - .arg = { .r = { - .min = E1000_MIN_TXD, - .max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD - }} - }; - - if (num_TxDescriptors > bd) { - tx_ring->count = TxDescriptors[bd]; - e1000_validate_option(&tx_ring->count, &opt, adapter); - tx_ring->count = ALIGN(tx_ring->count, - REQ_TX_DESCRIPTOR_MULTIPLE); - } else { - tx_ring->count = opt.def; - } - for (i = 0; i < adapter->num_tx_queues; i++) - tx_ring[i].count = tx_ring->count; - } - { /* Receive Descriptor Count */ - struct e1000_rx_ring *rx_ring = adapter->rx_ring; - int i; - e1000_mac_type mac_type = adapter->hw.mac_type; - - opt = (struct e1000_option) { - .type = range_option, - .name = "Receive Descriptors", - .err = "using default of " - __MODULE_STRING(E1000_DEFAULT_RXD), - .def = E1000_DEFAULT_RXD, - .arg = { .r = { - .min = E1000_MIN_RXD, - .max = mac_type < e1000_82544 ? E1000_MAX_RXD : - E1000_MAX_82544_RXD - }} - }; - - if (num_RxDescriptors > bd) { - rx_ring->count = RxDescriptors[bd]; - e1000_validate_option(&rx_ring->count, &opt, adapter); - rx_ring->count = ALIGN(rx_ring->count, - REQ_RX_DESCRIPTOR_MULTIPLE); - } else { - rx_ring->count = opt.def; - } - for (i = 0; i < adapter->num_rx_queues; i++) - rx_ring[i].count = rx_ring->count; - } - { /* Checksum Offload Enable/Disable */ - opt = (struct e1000_option) { - .type = enable_option, - .name = "Checksum Offload", - .err = "defaulting to Enabled", - .def = OPTION_ENABLED - }; - - if (num_XsumRX > bd) { - unsigned int rx_csum = XsumRX[bd]; - e1000_validate_option(&rx_csum, &opt, adapter); - adapter->rx_csum = rx_csum; - } else { - adapter->rx_csum = opt.def; - } - } - { /* Flow Control */ - - static const struct e1000_opt_list fc_list[] = { - { E1000_FC_NONE, "Flow Control Disabled" }, - { E1000_FC_RX_PAUSE, "Flow Control Receive Only" }, - { E1000_FC_TX_PAUSE, "Flow Control Transmit Only" }, - { E1000_FC_FULL, "Flow Control Enabled" }, - { E1000_FC_DEFAULT, "Flow Control Hardware Default" } - }; - - opt = (struct e1000_option) { - .type = list_option, - .name = "Flow Control", - .err = "reading default settings from EEPROM", - .def = E1000_FC_DEFAULT, - .arg = { .l = { .nr = ARRAY_SIZE(fc_list), - .p = fc_list }} - }; - - if (num_FlowControl > bd) { - unsigned int fc = FlowControl[bd]; - e1000_validate_option(&fc, &opt, adapter); - adapter->hw.fc = adapter->hw.original_fc = fc; - } else { - adapter->hw.fc = adapter->hw.original_fc = opt.def; - } - } - { /* Transmit Interrupt Delay */ - opt = (struct e1000_option) { - .type = range_option, - .name = "Transmit Interrupt Delay", - .err = "using default of " __MODULE_STRING(DEFAULT_TIDV), - .def = DEFAULT_TIDV, - .arg = { .r = { .min = MIN_TXDELAY, - .max = MAX_TXDELAY }} - }; - - if (num_TxIntDelay > bd) { - adapter->tx_int_delay = TxIntDelay[bd]; - e1000_validate_option(&adapter->tx_int_delay, &opt, - adapter); - } else { - adapter->tx_int_delay = opt.def; - } - } - { /* Transmit Absolute Interrupt Delay */ - opt = (struct e1000_option) { - .type = range_option, - .name = "Transmit Absolute Interrupt Delay", - .err = "using default of " __MODULE_STRING(DEFAULT_TADV), - .def = DEFAULT_TADV, - .arg = { .r = { .min = MIN_TXABSDELAY, - .max = MAX_TXABSDELAY }} - }; - - if (num_TxAbsIntDelay > bd) { - adapter->tx_abs_int_delay = TxAbsIntDelay[bd]; - e1000_validate_option(&adapter->tx_abs_int_delay, &opt, - adapter); - } else { - adapter->tx_abs_int_delay = opt.def; - } - } - { /* Receive Interrupt Delay */ - opt = (struct e1000_option) { - .type = range_option, - .name = "Receive Interrupt Delay", - .err = "using default of " __MODULE_STRING(DEFAULT_RDTR), - .def = DEFAULT_RDTR, - .arg = { .r = { .min = MIN_RXDELAY, - .max = MAX_RXDELAY }} - }; - - if (num_RxIntDelay > bd) { - adapter->rx_int_delay = RxIntDelay[bd]; - e1000_validate_option(&adapter->rx_int_delay, &opt, - adapter); - } else { - adapter->rx_int_delay = opt.def; - } - } - { /* Receive Absolute Interrupt Delay */ - opt = (struct e1000_option) { - .type = range_option, - .name = "Receive Absolute Interrupt Delay", - .err = "using default of " __MODULE_STRING(DEFAULT_RADV), - .def = DEFAULT_RADV, - .arg = { .r = { .min = MIN_RXABSDELAY, - .max = MAX_RXABSDELAY }} - }; - - if (num_RxAbsIntDelay > bd) { - adapter->rx_abs_int_delay = RxAbsIntDelay[bd]; - e1000_validate_option(&adapter->rx_abs_int_delay, &opt, - adapter); - } else { - adapter->rx_abs_int_delay = opt.def; - } - } - { /* Interrupt Throttling Rate */ - opt = (struct e1000_option) { - .type = range_option, - .name = "Interrupt Throttling Rate (ints/sec)", - .err = "using default of " __MODULE_STRING(DEFAULT_ITR), - .def = DEFAULT_ITR, - .arg = { .r = { .min = MIN_ITR, - .max = MAX_ITR }} - }; - - if (num_InterruptThrottleRate > bd) { - adapter->itr = InterruptThrottleRate[bd]; - switch (adapter->itr) { - case 0: - e_dev_info("%s turned off\n", opt.name); - break; - case 1: - e_dev_info("%s set to dynamic mode\n", - opt.name); - adapter->itr_setting = adapter->itr; - adapter->itr = 20000; - break; - case 3: - e_dev_info("%s set to dynamic conservative " - "mode\n", opt.name); - adapter->itr_setting = adapter->itr; - adapter->itr = 20000; - break; - case 4: - e_dev_info("%s set to simplified " - "(2000-8000) ints mode\n", opt.name); - adapter->itr_setting = adapter->itr; - break; - default: - e1000_validate_option(&adapter->itr, &opt, - adapter); - /* save the setting, because the dynamic bits - * change itr. - * clear the lower two bits because they are - * used as control - */ - adapter->itr_setting = adapter->itr & ~3; - break; - } - } else { - adapter->itr_setting = opt.def; - adapter->itr = 20000; - } - } - { /* Smart Power Down */ - opt = (struct e1000_option) { - .type = enable_option, - .name = "PHY Smart Power Down", - .err = "defaulting to Disabled", - .def = OPTION_DISABLED - }; - - if (num_SmartPowerDownEnable > bd) { - unsigned int spd = SmartPowerDownEnable[bd]; - e1000_validate_option(&spd, &opt, adapter); - adapter->smart_power_down = spd; - } else { - adapter->smart_power_down = opt.def; - } - } - - switch (adapter->hw.media_type) { - case e1000_media_type_fiber: - case e1000_media_type_internal_serdes: - e1000_check_fiber_options(adapter); - break; - case e1000_media_type_copper: - e1000_check_copper_options(adapter); - break; - default: - BUG(); - } -} - -/** - * e1000_check_fiber_options - Range Checking for Link Options, Fiber Version - * @adapter: board private structure - * - * Handles speed and duplex options on fiber adapters - **/ -static void e1000_check_fiber_options(struct e1000_adapter *adapter) -{ - int bd = adapter->bd_number; - if (num_Speed > bd) { - e_dev_info("Speed not valid for fiber adapters, parameter " - "ignored\n"); - } - - if (num_Duplex > bd) { - e_dev_info("Duplex not valid for fiber adapters, parameter " - "ignored\n"); - } - - if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) { - e_dev_info("AutoNeg other than 1000/Full is not valid for fiber" - "adapters, parameter ignored\n"); - } -} - -/** - * e1000_check_copper_options - Range Checking for Link Options, Copper Version - * @adapter: board private structure - * - * Handles speed and duplex options on copper adapters - **/ -static void e1000_check_copper_options(struct e1000_adapter *adapter) -{ - struct e1000_option opt; - unsigned int speed, dplx, an; - int bd = adapter->bd_number; - - { /* Speed */ - static const struct e1000_opt_list speed_list[] = { - { 0, "" }, - { SPEED_10, "" }, - { SPEED_100, "" }, - { SPEED_1000, "" }}; - - opt = (struct e1000_option) { - .type = list_option, - .name = "Speed", - .err = "parameter ignored", - .def = 0, - .arg = { .l = { .nr = ARRAY_SIZE(speed_list), - .p = speed_list }} - }; - - if (num_Speed > bd) { - speed = Speed[bd]; - e1000_validate_option(&speed, &opt, adapter); - } else { - speed = opt.def; - } - } - { /* Duplex */ - static const struct e1000_opt_list dplx_list[] = { - { 0, "" }, - { HALF_DUPLEX, "" }, - { FULL_DUPLEX, "" }}; - - opt = (struct e1000_option) { - .type = list_option, - .name = "Duplex", - .err = "parameter ignored", - .def = 0, - .arg = { .l = { .nr = ARRAY_SIZE(dplx_list), - .p = dplx_list }} - }; - - if (num_Duplex > bd) { - dplx = Duplex[bd]; - e1000_validate_option(&dplx, &opt, adapter); - } else { - dplx = opt.def; - } - } - - if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) { - e_dev_info("AutoNeg specified along with Speed or Duplex, " - "parameter ignored\n"); - adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT; - } else { /* Autoneg */ - static const struct e1000_opt_list an_list[] = - #define AA "AutoNeg advertising " - {{ 0x01, AA "10/HD" }, - { 0x02, AA "10/FD" }, - { 0x03, AA "10/FD, 10/HD" }, - { 0x04, AA "100/HD" }, - { 0x05, AA "100/HD, 10/HD" }, - { 0x06, AA "100/HD, 10/FD" }, - { 0x07, AA "100/HD, 10/FD, 10/HD" }, - { 0x08, AA "100/FD" }, - { 0x09, AA "100/FD, 10/HD" }, - { 0x0a, AA "100/FD, 10/FD" }, - { 0x0b, AA "100/FD, 10/FD, 10/HD" }, - { 0x0c, AA "100/FD, 100/HD" }, - { 0x0d, AA "100/FD, 100/HD, 10/HD" }, - { 0x0e, AA "100/FD, 100/HD, 10/FD" }, - { 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" }, - { 0x20, AA "1000/FD" }, - { 0x21, AA "1000/FD, 10/HD" }, - { 0x22, AA "1000/FD, 10/FD" }, - { 0x23, AA "1000/FD, 10/FD, 10/HD" }, - { 0x24, AA "1000/FD, 100/HD" }, - { 0x25, AA "1000/FD, 100/HD, 10/HD" }, - { 0x26, AA "1000/FD, 100/HD, 10/FD" }, - { 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" }, - { 0x28, AA "1000/FD, 100/FD" }, - { 0x29, AA "1000/FD, 100/FD, 10/HD" }, - { 0x2a, AA "1000/FD, 100/FD, 10/FD" }, - { 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" }, - { 0x2c, AA "1000/FD, 100/FD, 100/HD" }, - { 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" }, - { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" }, - { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }}; - - opt = (struct e1000_option) { - .type = list_option, - .name = "AutoNeg", - .err = "parameter ignored", - .def = AUTONEG_ADV_DEFAULT, - .arg = { .l = { .nr = ARRAY_SIZE(an_list), - .p = an_list }} - }; - - if (num_AutoNeg > bd) { - an = AutoNeg[bd]; - e1000_validate_option(&an, &opt, adapter); - } else { - an = opt.def; - } - adapter->hw.autoneg_advertised = an; - } - - switch (speed + dplx) { - case 0: - adapter->hw.autoneg = adapter->fc_autoneg = 1; - if ((num_Speed > bd) && (speed != 0 || dplx != 0)) - e_dev_info("Speed and duplex autonegotiation " - "enabled\n"); - break; - case HALF_DUPLEX: - e_dev_info("Half Duplex specified without Speed\n"); - e_dev_info("Using Autonegotiation at Half Duplex only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | - ADVERTISE_100_HALF; - break; - case FULL_DUPLEX: - e_dev_info("Full Duplex specified without Speed\n"); - e_dev_info("Using Autonegotiation at Full Duplex only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_10_FULL | - ADVERTISE_100_FULL | - ADVERTISE_1000_FULL; - break; - case SPEED_10: - e_dev_info("10 Mbps Speed specified without Duplex\n"); - e_dev_info("Using Autonegotiation at 10 Mbps only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | - ADVERTISE_10_FULL; - break; - case SPEED_10 + HALF_DUPLEX: - e_dev_info("Forcing to 10 Mbps Half Duplex\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 0; - adapter->hw.forced_speed_duplex = e1000_10_half; - adapter->hw.autoneg_advertised = 0; - break; - case SPEED_10 + FULL_DUPLEX: - e_dev_info("Forcing to 10 Mbps Full Duplex\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 0; - adapter->hw.forced_speed_duplex = e1000_10_full; - adapter->hw.autoneg_advertised = 0; - break; - case SPEED_100: - e_dev_info("100 Mbps Speed specified without Duplex\n"); - e_dev_info("Using Autonegotiation at 100 Mbps only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_100_HALF | - ADVERTISE_100_FULL; - break; - case SPEED_100 + HALF_DUPLEX: - e_dev_info("Forcing to 100 Mbps Half Duplex\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 0; - adapter->hw.forced_speed_duplex = e1000_100_half; - adapter->hw.autoneg_advertised = 0; - break; - case SPEED_100 + FULL_DUPLEX: - e_dev_info("Forcing to 100 Mbps Full Duplex\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 0; - adapter->hw.forced_speed_duplex = e1000_100_full; - adapter->hw.autoneg_advertised = 0; - break; - case SPEED_1000: - e_dev_info("1000 Mbps Speed specified without Duplex\n"); - goto full_duplex_only; - case SPEED_1000 + HALF_DUPLEX: - e_dev_info("Half Duplex is not supported at 1000 Mbps\n"); - /* fall through */ - case SPEED_1000 + FULL_DUPLEX: -full_duplex_only: - e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex " - "only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; - break; - default: - BUG(); - } - - /* Speed, AutoNeg and MDI/MDI-X must all play nice */ - if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) { - e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. " - "Setting MDI-X to a compatible value.\n"); - } -} - diff --git a/addons/e1000/src/4.4.180/Makefile b/addons/e1000/src/4.4.180/Makefile deleted file mode 100644 index 59afd9fd..00000000 --- a/addons/e1000/src/4.4.180/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-m += e1000.o -e1000-objs := e1000_main.o e1000_hw.o e1000_ethtool.o e1000_param.o diff --git a/addons/e1000/src/4.4.180/e1000.h b/addons/e1000/src/4.4.180/e1000.h deleted file mode 100644 index 481e9944..00000000 --- a/addons/e1000/src/4.4.180/e1000.h +++ /dev/null @@ -1,378 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - - -/* Linux PRO/1000 Ethernet Driver main header file */ - -#ifndef _E1000_H_ -#define _E1000_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define BAR_0 0 -#define BAR_1 1 -#define BAR_5 5 - -#define INTEL_E1000_ETHERNET_DEVICE(device_id) {\ - PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} - -struct e1000_adapter; - -#include "e1000_hw.h" - -#define E1000_MAX_INTR 10 - -/* - * Count for polling __E1000_RESET condition every 10-20msec. - */ -#define E1000_CHECK_RESET_COUNT 50 - -/* TX/RX descriptor defines */ -#define E1000_DEFAULT_TXD 256 -#define E1000_MAX_TXD 256 -#define E1000_MIN_TXD 48 -#define E1000_MAX_82544_TXD 4096 - -#define E1000_DEFAULT_RXD 256 -#define E1000_MAX_RXD 256 -#define E1000_MIN_RXD 48 -#define E1000_MAX_82544_RXD 4096 - -#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */ -#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */ - -/* this is the size past which hardware will drop packets when setting LPE=0 */ -#define MAXIMUM_ETHERNET_VLAN_SIZE 1522 - -/* Supported Rx Buffer Sizes */ -#define E1000_RXBUFFER_128 128 /* Used for packet split */ -#define E1000_RXBUFFER_256 256 /* Used for packet split */ -#define E1000_RXBUFFER_512 512 -#define E1000_RXBUFFER_1024 1024 -#define E1000_RXBUFFER_2048 2048 -#define E1000_RXBUFFER_4096 4096 -#define E1000_RXBUFFER_8192 8192 -#define E1000_RXBUFFER_16384 16384 - -/* SmartSpeed delimiters */ -#define E1000_SMARTSPEED_DOWNSHIFT 3 -#define E1000_SMARTSPEED_MAX 15 - -/* Packet Buffer allocations */ -#define E1000_PBA_BYTES_SHIFT 0xA -#define E1000_TX_HEAD_ADDR_SHIFT 7 -#define E1000_PBA_TX_MASK 0xFFFF0000 - -/* Flow Control Watermarks */ -#define E1000_FC_HIGH_DIFF 0x1638 /* High: 5688 bytes below Rx FIFO size */ -#define E1000_FC_LOW_DIFF 0x1640 /* Low: 5696 bytes below Rx FIFO size */ - -#define E1000_FC_PAUSE_TIME 0xFFFF /* pause for the max or until send xon */ - -/* How many Tx Descriptors do we need to call netif_wake_queue ? */ -#define E1000_TX_QUEUE_WAKE 16 -/* How many Rx Buffers do we bundle into one write to the hardware ? */ -#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ - -#define AUTO_ALL_MODES 0 -#define E1000_EEPROM_82544_APM 0x0004 -#define E1000_EEPROM_APME 0x0400 - -#ifndef E1000_MASTER_SLAVE -/* Switch to override PHY master/slave setting */ -#define E1000_MASTER_SLAVE e1000_ms_hw_default -#endif - -#define E1000_MNG_VLAN_NONE (-1) - -/* wrapper around a pointer to a socket buffer, - * so a DMA handle can be stored along with the buffer - */ -struct e1000_tx_buffer { - struct sk_buff *skb; - dma_addr_t dma; - unsigned long time_stamp; - u16 length; - u16 next_to_watch; - bool mapped_as_page; - unsigned short segs; - unsigned int bytecount; -}; - -struct e1000_rx_buffer { - union { - struct page *page; /* jumbo: alloc_page */ - u8 *data; /* else, netdev_alloc_frag */ - } rxbuf; - dma_addr_t dma; -}; - -struct e1000_tx_ring { - /* pointer to the descriptor ring memory */ - void *desc; - /* physical address of the descriptor ring */ - dma_addr_t dma; - /* length of descriptor ring in bytes */ - unsigned int size; - /* number of descriptors in the ring */ - unsigned int count; - /* next descriptor to associate a buffer with */ - unsigned int next_to_use; - /* next descriptor to check for DD status bit */ - unsigned int next_to_clean; - /* array of buffer information structs */ - struct e1000_tx_buffer *buffer_info; - - u16 tdh; - u16 tdt; - bool last_tx_tso; -}; - -struct e1000_rx_ring { - /* pointer to the descriptor ring memory */ - void *desc; - /* physical address of the descriptor ring */ - dma_addr_t dma; - /* length of descriptor ring in bytes */ - unsigned int size; - /* number of descriptors in the ring */ - unsigned int count; - /* next descriptor to associate a buffer with */ - unsigned int next_to_use; - /* next descriptor to check for DD status bit */ - unsigned int next_to_clean; - /* array of buffer information structs */ - struct e1000_rx_buffer *buffer_info; - struct sk_buff *rx_skb_top; - - /* cpu for rx queue */ - int cpu; - - u16 rdh; - u16 rdt; -}; - -#define E1000_DESC_UNUSED(R) \ -({ \ - unsigned int clean = smp_load_acquire(&(R)->next_to_clean); \ - unsigned int use = READ_ONCE((R)->next_to_use); \ - (clean > use ? 0 : (R)->count) + clean - use - 1; \ -}) - -#define E1000_RX_DESC_EXT(R, i) \ - (&(((union e1000_rx_desc_extended *)((R).desc))[i])) -#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) -#define E1000_RX_DESC(R, i) E1000_GET_DESC(R, i, e1000_rx_desc) -#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) -#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc) - -/* board specific private data structure */ - -struct e1000_adapter { - unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; - u16 mng_vlan_id; - u32 bd_number; - u32 rx_buffer_len; - u32 wol; - u32 smartspeed; - u32 en_mng_pt; - u16 link_speed; - u16 link_duplex; - spinlock_t stats_lock; - unsigned int total_tx_bytes; - unsigned int total_tx_packets; - unsigned int total_rx_bytes; - unsigned int total_rx_packets; - /* Interrupt Throttle Rate */ - u32 itr; - u32 itr_setting; - u16 tx_itr; - u16 rx_itr; - - u8 fc_autoneg; - - /* TX */ - struct e1000_tx_ring *tx_ring; /* One per active queue */ - unsigned int restart_queue; - u32 txd_cmd; - u32 tx_int_delay; - u32 tx_abs_int_delay; - u32 gotcl; - u64 gotcl_old; - u64 tpt_old; - u64 colc_old; - u32 tx_timeout_count; - u32 tx_fifo_head; - u32 tx_head_addr; - u32 tx_fifo_size; - u8 tx_timeout_factor; - atomic_t tx_fifo_stall; - bool pcix_82544; - bool detect_tx_hung; - bool dump_buffers; - - /* RX */ - bool (*clean_rx)(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int *work_done, int work_to_do); - void (*alloc_rx_buf)(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count); - struct e1000_rx_ring *rx_ring; /* One per active queue */ - struct napi_struct napi; - - int num_tx_queues; - int num_rx_queues; - - u64 hw_csum_err; - u64 hw_csum_good; - u32 alloc_rx_buff_failed; - u32 rx_int_delay; - u32 rx_abs_int_delay; - bool rx_csum; - u32 gorcl; - u64 gorcl_old; - - /* OS defined structs */ - struct net_device *netdev; - struct pci_dev *pdev; - - /* structs defined in e1000_hw.h */ - struct e1000_hw hw; - struct e1000_hw_stats stats; - struct e1000_phy_info phy_info; - struct e1000_phy_stats phy_stats; - - u32 test_icr; - struct e1000_tx_ring test_tx_ring; - struct e1000_rx_ring test_rx_ring; - - int msg_enable; - - /* to not mess up cache alignment, always add to the bottom */ - bool tso_force; - bool smart_power_down; /* phy smart power down */ - bool quad_port_a; - unsigned long flags; - u32 eeprom_wol; - - /* for ioport free */ - int bars; - int need_ioport; - - bool discarding; - - struct work_struct reset_task; - struct delayed_work watchdog_task; - struct delayed_work fifo_stall_task; - struct delayed_work phy_info_task; -}; - -enum e1000_state_t { - __E1000_TESTING, - __E1000_RESETTING, - __E1000_DOWN, - __E1000_DISABLED -}; - -#undef pr_fmt -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -struct net_device *e1000_get_hw_dev(struct e1000_hw *hw); -#define e_dbg(format, arg...) \ - netdev_dbg(e1000_get_hw_dev(hw), format, ## arg) -#define e_err(msglvl, format, arg...) \ - netif_err(adapter, msglvl, adapter->netdev, format, ## arg) -#define e_info(msglvl, format, arg...) \ - netif_info(adapter, msglvl, adapter->netdev, format, ## arg) -#define e_warn(msglvl, format, arg...) \ - netif_warn(adapter, msglvl, adapter->netdev, format, ## arg) -#define e_notice(msglvl, format, arg...) \ - netif_notice(adapter, msglvl, adapter->netdev, format, ## arg) -#define e_dev_info(format, arg...) \ - dev_info(&adapter->pdev->dev, format, ## arg) -#define e_dev_warn(format, arg...) \ - dev_warn(&adapter->pdev->dev, format, ## arg) -#define e_dev_err(format, arg...) \ - dev_err(&adapter->pdev->dev, format, ## arg) - -extern char e1000_driver_name[]; -extern const char e1000_driver_version[]; - -int e1000_up(struct e1000_adapter *adapter); -void e1000_down(struct e1000_adapter *adapter); -void e1000_reinit_locked(struct e1000_adapter *adapter); -void e1000_reset(struct e1000_adapter *adapter); -int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx); -int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); -int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); -void e1000_free_all_rx_resources(struct e1000_adapter *adapter); -void e1000_free_all_tx_resources(struct e1000_adapter *adapter); -void e1000_update_stats(struct e1000_adapter *adapter); -bool e1000_has_link(struct e1000_adapter *adapter); -void e1000_power_up_phy(struct e1000_adapter *); -void e1000_set_ethtool_ops(struct net_device *netdev); -void e1000_check_options(struct e1000_adapter *adapter); -char *e1000_get_hw_dev_name(struct e1000_hw *hw); - -#endif /* _E1000_H_ */ diff --git a/addons/e1000/src/4.4.180/e1000_ethtool.c b/addons/e1000/src/4.4.180/e1000_ethtool.c deleted file mode 100644 index d70b2e5d..00000000 --- a/addons/e1000/src/4.4.180/e1000_ethtool.c +++ /dev/null @@ -1,1909 +0,0 @@ -/******************************************************************************* - * Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2006 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - * - ******************************************************************************/ - -/* ethtool support for e1000 */ - -#include "e1000.h" -#include -#include - -enum {NETDEV_STATS, E1000_STATS}; - -struct e1000_stats { - char stat_string[ETH_GSTRING_LEN]; - int type; - int sizeof_stat; - int stat_offset; -}; - -#define E1000_STAT(m) E1000_STATS, \ - sizeof(((struct e1000_adapter *)0)->m), \ - offsetof(struct e1000_adapter, m) -#define E1000_NETDEV_STAT(m) NETDEV_STATS, \ - sizeof(((struct net_device *)0)->m), \ - offsetof(struct net_device, m) - -static const struct e1000_stats e1000_gstrings_stats[] = { - { "rx_packets", E1000_STAT(stats.gprc) }, - { "tx_packets", E1000_STAT(stats.gptc) }, - { "rx_bytes", E1000_STAT(stats.gorcl) }, - { "tx_bytes", E1000_STAT(stats.gotcl) }, - { "rx_broadcast", E1000_STAT(stats.bprc) }, - { "tx_broadcast", E1000_STAT(stats.bptc) }, - { "rx_multicast", E1000_STAT(stats.mprc) }, - { "tx_multicast", E1000_STAT(stats.mptc) }, - { "rx_errors", E1000_STAT(stats.rxerrc) }, - { "tx_errors", E1000_STAT(stats.txerrc) }, - { "tx_dropped", E1000_NETDEV_STAT(stats.tx_dropped) }, - { "multicast", E1000_STAT(stats.mprc) }, - { "collisions", E1000_STAT(stats.colc) }, - { "rx_length_errors", E1000_STAT(stats.rlerrc) }, - { "rx_over_errors", E1000_NETDEV_STAT(stats.rx_over_errors) }, - { "rx_crc_errors", E1000_STAT(stats.crcerrs) }, - { "rx_frame_errors", E1000_NETDEV_STAT(stats.rx_frame_errors) }, - { "rx_no_buffer_count", E1000_STAT(stats.rnbc) }, - { "rx_missed_errors", E1000_STAT(stats.mpc) }, - { "tx_aborted_errors", E1000_STAT(stats.ecol) }, - { "tx_carrier_errors", E1000_STAT(stats.tncrs) }, - { "tx_fifo_errors", E1000_NETDEV_STAT(stats.tx_fifo_errors) }, - { "tx_heartbeat_errors", E1000_NETDEV_STAT(stats.tx_heartbeat_errors) }, - { "tx_window_errors", E1000_STAT(stats.latecol) }, - { "tx_abort_late_coll", E1000_STAT(stats.latecol) }, - { "tx_deferred_ok", E1000_STAT(stats.dc) }, - { "tx_single_coll_ok", E1000_STAT(stats.scc) }, - { "tx_multi_coll_ok", E1000_STAT(stats.mcc) }, - { "tx_timeout_count", E1000_STAT(tx_timeout_count) }, - { "tx_restart_queue", E1000_STAT(restart_queue) }, - { "rx_long_length_errors", E1000_STAT(stats.roc) }, - { "rx_short_length_errors", E1000_STAT(stats.ruc) }, - { "rx_align_errors", E1000_STAT(stats.algnerrc) }, - { "tx_tcp_seg_good", E1000_STAT(stats.tsctc) }, - { "tx_tcp_seg_failed", E1000_STAT(stats.tsctfc) }, - { "rx_flow_control_xon", E1000_STAT(stats.xonrxc) }, - { "rx_flow_control_xoff", E1000_STAT(stats.xoffrxc) }, - { "tx_flow_control_xon", E1000_STAT(stats.xontxc) }, - { "tx_flow_control_xoff", E1000_STAT(stats.xofftxc) }, - { "rx_long_byte_count", E1000_STAT(stats.gorcl) }, - { "rx_csum_offload_good", E1000_STAT(hw_csum_good) }, - { "rx_csum_offload_errors", E1000_STAT(hw_csum_err) }, - { "alloc_rx_buff_failed", E1000_STAT(alloc_rx_buff_failed) }, - { "tx_smbus", E1000_STAT(stats.mgptc) }, - { "rx_smbus", E1000_STAT(stats.mgprc) }, - { "dropped_smbus", E1000_STAT(stats.mgpdc) }, -}; - -#define E1000_QUEUE_STATS_LEN 0 -#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats) -#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN + E1000_QUEUE_STATS_LEN) -static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { - "Register test (offline)", "Eeprom test (offline)", - "Interrupt test (offline)", "Loopback test (offline)", - "Link test (on/offline)" -}; - -#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test) - -static int e1000_get_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - if (hw->media_type == e1000_media_type_copper) { - ecmd->supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full| - SUPPORTED_Autoneg | - SUPPORTED_TP); - ecmd->advertising = ADVERTISED_TP; - - if (hw->autoneg == 1) { - ecmd->advertising |= ADVERTISED_Autoneg; - /* the e1000 autoneg seems to match ethtool nicely */ - ecmd->advertising |= hw->autoneg_advertised; - } - - ecmd->port = PORT_TP; - ecmd->phy_address = hw->phy_addr; - - if (hw->mac_type == e1000_82543) - ecmd->transceiver = XCVR_EXTERNAL; - else - ecmd->transceiver = XCVR_INTERNAL; - - } else { - ecmd->supported = (SUPPORTED_1000baseT_Full | - SUPPORTED_FIBRE | - SUPPORTED_Autoneg); - - ecmd->advertising = (ADVERTISED_1000baseT_Full | - ADVERTISED_FIBRE | - ADVERTISED_Autoneg); - - ecmd->port = PORT_FIBRE; - - if (hw->mac_type >= e1000_82545) - ecmd->transceiver = XCVR_INTERNAL; - else - ecmd->transceiver = XCVR_EXTERNAL; - } - - if (er32(STATUS) & E1000_STATUS_LU) { - e1000_get_speed_and_duplex(hw, &adapter->link_speed, - &adapter->link_duplex); - ethtool_cmd_speed_set(ecmd, adapter->link_speed); - - /* unfortunately FULL_DUPLEX != DUPLEX_FULL - * and HALF_DUPLEX != DUPLEX_HALF - */ - if (adapter->link_duplex == FULL_DUPLEX) - ecmd->duplex = DUPLEX_FULL; - else - ecmd->duplex = DUPLEX_HALF; - } else { - ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); - ecmd->duplex = DUPLEX_UNKNOWN; - } - - ecmd->autoneg = ((hw->media_type == e1000_media_type_fiber) || - hw->autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; - - /* MDI-X => 1; MDI => 0 */ - if ((hw->media_type == e1000_media_type_copper) && - netif_carrier_ok(netdev)) - ecmd->eth_tp_mdix = (!!adapter->phy_info.mdix_mode ? - ETH_TP_MDI_X : ETH_TP_MDI); - else - ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; - - if (hw->mdix == AUTO_ALL_MODES) - ecmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; - else - ecmd->eth_tp_mdix_ctrl = hw->mdix; - return 0; -} - -static int e1000_set_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - /* MDI setting is only allowed when autoneg enabled because - * some hardware doesn't allow MDI setting when speed or - * duplex is forced. - */ - if (ecmd->eth_tp_mdix_ctrl) { - if (hw->media_type != e1000_media_type_copper) - return -EOPNOTSUPP; - - if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) && - (ecmd->autoneg != AUTONEG_ENABLE)) { - e_err(drv, "forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n"); - return -EINVAL; - } - } - - while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) - msleep(1); - - if (ecmd->autoneg == AUTONEG_ENABLE) { - hw->autoneg = 1; - if (hw->media_type == e1000_media_type_fiber) - hw->autoneg_advertised = ADVERTISED_1000baseT_Full | - ADVERTISED_FIBRE | - ADVERTISED_Autoneg; - else - hw->autoneg_advertised = ecmd->advertising | - ADVERTISED_TP | - ADVERTISED_Autoneg; - ecmd->advertising = hw->autoneg_advertised; - } else { - u32 speed = ethtool_cmd_speed(ecmd); - /* calling this overrides forced MDI setting */ - if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) { - clear_bit(__E1000_RESETTING, &adapter->flags); - return -EINVAL; - } - } - - /* MDI-X => 2; MDI => 1; Auto => 3 */ - if (ecmd->eth_tp_mdix_ctrl) { - if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) - hw->mdix = AUTO_ALL_MODES; - else - hw->mdix = ecmd->eth_tp_mdix_ctrl; - } - - /* reset the link */ - - if (netif_running(adapter->netdev)) { - e1000_down(adapter); - e1000_up(adapter); - } else { - e1000_reset(adapter); - } - clear_bit(__E1000_RESETTING, &adapter->flags); - return 0; -} - -static u32 e1000_get_link(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - /* If the link is not reported up to netdev, interrupts are disabled, - * and so the physical link state may have changed since we last - * looked. Set get_link_status to make sure that the true link - * state is interrogated, rather than pulling a cached and possibly - * stale link state from the driver. - */ - if (!netif_carrier_ok(netdev)) - adapter->hw.get_link_status = 1; - - return e1000_has_link(adapter); -} - -static void e1000_get_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - pause->autoneg = - (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); - - if (hw->fc == E1000_FC_RX_PAUSE) { - pause->rx_pause = 1; - } else if (hw->fc == E1000_FC_TX_PAUSE) { - pause->tx_pause = 1; - } else if (hw->fc == E1000_FC_FULL) { - pause->rx_pause = 1; - pause->tx_pause = 1; - } -} - -static int e1000_set_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - int retval = 0; - - adapter->fc_autoneg = pause->autoneg; - - while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) - msleep(1); - - if (pause->rx_pause && pause->tx_pause) - hw->fc = E1000_FC_FULL; - else if (pause->rx_pause && !pause->tx_pause) - hw->fc = E1000_FC_RX_PAUSE; - else if (!pause->rx_pause && pause->tx_pause) - hw->fc = E1000_FC_TX_PAUSE; - else if (!pause->rx_pause && !pause->tx_pause) - hw->fc = E1000_FC_NONE; - - hw->original_fc = hw->fc; - - if (adapter->fc_autoneg == AUTONEG_ENABLE) { - if (netif_running(adapter->netdev)) { - e1000_down(adapter); - e1000_up(adapter); - } else { - e1000_reset(adapter); - } - } else - retval = ((hw->media_type == e1000_media_type_fiber) ? - e1000_setup_link(hw) : e1000_force_mac_fc(hw)); - - clear_bit(__E1000_RESETTING, &adapter->flags); - return retval; -} - -static u32 e1000_get_msglevel(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - return adapter->msg_enable; -} - -static void e1000_set_msglevel(struct net_device *netdev, u32 data) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - adapter->msg_enable = data; -} - -static int e1000_get_regs_len(struct net_device *netdev) -{ -#define E1000_REGS_LEN 32 - return E1000_REGS_LEN * sizeof(u32); -} - -static void e1000_get_regs(struct net_device *netdev, struct ethtool_regs *regs, - void *p) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 *regs_buff = p; - u16 phy_data; - - memset(p, 0, E1000_REGS_LEN * sizeof(u32)); - - regs->version = (1 << 24) | (hw->revision_id << 16) | hw->device_id; - - regs_buff[0] = er32(CTRL); - regs_buff[1] = er32(STATUS); - - regs_buff[2] = er32(RCTL); - regs_buff[3] = er32(RDLEN); - regs_buff[4] = er32(RDH); - regs_buff[5] = er32(RDT); - regs_buff[6] = er32(RDTR); - - regs_buff[7] = er32(TCTL); - regs_buff[8] = er32(TDLEN); - regs_buff[9] = er32(TDH); - regs_buff[10] = er32(TDT); - regs_buff[11] = er32(TIDV); - - regs_buff[12] = hw->phy_type; /* PHY type (IGP=1, M88=0) */ - if (hw->phy_type == e1000_phy_igp) { - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_AGC_A); - e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_A & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[13] = (u32)phy_data; /* cable length */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_AGC_B); - e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_B & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[14] = (u32)phy_data; /* cable length */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_AGC_C); - e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_C & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[15] = (u32)phy_data; /* cable length */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_AGC_D); - e1000_read_phy_reg(hw, IGP01E1000_PHY_AGC_D & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[16] = (u32)phy_data; /* cable length */ - regs_buff[17] = 0; /* extended 10bt distance (not needed) */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0); - e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[18] = (u32)phy_data; /* cable polarity */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, - IGP01E1000_PHY_PCS_INIT_REG); - e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG & - IGP01E1000_PHY_PAGE_SELECT, &phy_data); - regs_buff[19] = (u32)phy_data; /* cable polarity */ - regs_buff[20] = 0; /* polarity correction enabled (always) */ - regs_buff[22] = 0; /* phy receive errors (unavailable) */ - regs_buff[23] = regs_buff[18]; /* mdix mode */ - e1000_write_phy_reg(hw, IGP01E1000_PHY_PAGE_SELECT, 0x0); - } else { - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - regs_buff[13] = (u32)phy_data; /* cable length */ - regs_buff[14] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[15] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[16] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - regs_buff[17] = (u32)phy_data; /* extended 10bt distance */ - regs_buff[18] = regs_buff[13]; /* cable polarity */ - regs_buff[19] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[20] = regs_buff[17]; /* polarity correction */ - /* phy receive errors */ - regs_buff[22] = adapter->phy_stats.receive_errors; - regs_buff[23] = regs_buff[13]; /* mdix mode */ - } - regs_buff[21] = adapter->phy_stats.idle_errors; /* phy idle errors */ - e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); - regs_buff[24] = (u32)phy_data; /* phy local receiver status */ - regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ - if (hw->mac_type >= e1000_82540 && - hw->media_type == e1000_media_type_copper) { - regs_buff[26] = er32(MANC); - } -} - -static int e1000_get_eeprom_len(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - return hw->eeprom.word_size * 2; -} - -static int e1000_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 *eeprom_buff; - int first_word, last_word; - int ret_val = 0; - u16 i; - - if (eeprom->len == 0) - return -EINVAL; - - eeprom->magic = hw->vendor_id | (hw->device_id << 16); - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - - eeprom_buff = kmalloc(sizeof(u16) * - (last_word - first_word + 1), GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - if (hw->eeprom.type == e1000_eeprom_spi) - ret_val = e1000_read_eeprom(hw, first_word, - last_word - first_word + 1, - eeprom_buff); - else { - for (i = 0; i < last_word - first_word + 1; i++) { - ret_val = e1000_read_eeprom(hw, first_word + i, 1, - &eeprom_buff[i]); - if (ret_val) - break; - } - } - - /* Device's eeprom is always little-endian, word addressable */ - for (i = 0; i < last_word - first_word + 1; i++) - le16_to_cpus(&eeprom_buff[i]); - - memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), - eeprom->len); - kfree(eeprom_buff); - - return ret_val; -} - -static int e1000_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 *eeprom_buff; - void *ptr; - int max_len, first_word, last_word, ret_val = 0; - u16 i; - - if (eeprom->len == 0) - return -EOPNOTSUPP; - - if (eeprom->magic != (hw->vendor_id | (hw->device_id << 16))) - return -EFAULT; - - max_len = hw->eeprom.word_size * 2; - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(max_len, GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - ptr = (void *)eeprom_buff; - - if (eeprom->offset & 1) { - /* need read/modify/write of first changed EEPROM word - * only the second byte of the word is being modified - */ - ret_val = e1000_read_eeprom(hw, first_word, 1, - &eeprom_buff[0]); - ptr++; - } - if (((eeprom->offset + eeprom->len) & 1) && (ret_val == 0)) { - /* need read/modify/write of last changed EEPROM word - * only the first byte of the word is being modified - */ - ret_val = e1000_read_eeprom(hw, last_word, 1, - &eeprom_buff[last_word - first_word]); - } - - /* Device's eeprom is always little-endian, word addressable */ - for (i = 0; i < last_word - first_word + 1; i++) - le16_to_cpus(&eeprom_buff[i]); - - memcpy(ptr, bytes, eeprom->len); - - for (i = 0; i < last_word - first_word + 1; i++) - eeprom_buff[i] = cpu_to_le16(eeprom_buff[i]); - - ret_val = e1000_write_eeprom(hw, first_word, - last_word - first_word + 1, eeprom_buff); - - /* Update the checksum over the first part of the EEPROM if needed */ - if ((ret_val == 0) && (first_word <= EEPROM_CHECKSUM_REG)) - e1000_update_eeprom_checksum(hw); - - kfree(eeprom_buff); - return ret_val; -} - -static void e1000_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - strlcpy(drvinfo->driver, e1000_driver_name, - sizeof(drvinfo->driver)); - strlcpy(drvinfo->version, e1000_driver_version, - sizeof(drvinfo->version)); - - strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), - sizeof(drvinfo->bus_info)); -} - -static void e1000_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - e1000_mac_type mac_type = hw->mac_type; - struct e1000_tx_ring *txdr = adapter->tx_ring; - struct e1000_rx_ring *rxdr = adapter->rx_ring; - - ring->rx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_RXD : - E1000_MAX_82544_RXD; - ring->tx_max_pending = (mac_type < e1000_82544) ? E1000_MAX_TXD : - E1000_MAX_82544_TXD; - ring->rx_pending = rxdr->count; - ring->tx_pending = txdr->count; -} - -static int e1000_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - e1000_mac_type mac_type = hw->mac_type; - struct e1000_tx_ring *txdr, *tx_old; - struct e1000_rx_ring *rxdr, *rx_old; - int i, err; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) - msleep(1); - - if (netif_running(adapter->netdev)) - e1000_down(adapter); - - tx_old = adapter->tx_ring; - rx_old = adapter->rx_ring; - - err = -ENOMEM; - txdr = kcalloc(adapter->num_tx_queues, sizeof(struct e1000_tx_ring), - GFP_KERNEL); - if (!txdr) - goto err_alloc_tx; - - rxdr = kcalloc(adapter->num_rx_queues, sizeof(struct e1000_rx_ring), - GFP_KERNEL); - if (!rxdr) - goto err_alloc_rx; - - adapter->tx_ring = txdr; - adapter->rx_ring = rxdr; - - rxdr->count = max(ring->rx_pending, (u32)E1000_MIN_RXD); - rxdr->count = min(rxdr->count, (u32)(mac_type < e1000_82544 ? - E1000_MAX_RXD : E1000_MAX_82544_RXD)); - rxdr->count = ALIGN(rxdr->count, REQ_RX_DESCRIPTOR_MULTIPLE); - txdr->count = max(ring->tx_pending, (u32)E1000_MIN_TXD); - txdr->count = min(txdr->count, (u32)(mac_type < e1000_82544 ? - E1000_MAX_TXD : E1000_MAX_82544_TXD)); - txdr->count = ALIGN(txdr->count, REQ_TX_DESCRIPTOR_MULTIPLE); - - for (i = 0; i < adapter->num_tx_queues; i++) - txdr[i].count = txdr->count; - for (i = 0; i < adapter->num_rx_queues; i++) - rxdr[i].count = rxdr->count; - - if (netif_running(adapter->netdev)) { - /* Try to get new resources before deleting old */ - err = e1000_setup_all_rx_resources(adapter); - if (err) - goto err_setup_rx; - err = e1000_setup_all_tx_resources(adapter); - if (err) - goto err_setup_tx; - - /* save the new, restore the old in order to free it, - * then restore the new back again - */ - - adapter->rx_ring = rx_old; - adapter->tx_ring = tx_old; - e1000_free_all_rx_resources(adapter); - e1000_free_all_tx_resources(adapter); - adapter->rx_ring = rxdr; - adapter->tx_ring = txdr; - err = e1000_up(adapter); - if (err) - goto err_setup; - } - kfree(tx_old); - kfree(rx_old); - - clear_bit(__E1000_RESETTING, &adapter->flags); - return 0; -err_setup_tx: - e1000_free_all_rx_resources(adapter); -err_setup_rx: - adapter->rx_ring = rx_old; - adapter->tx_ring = tx_old; - kfree(rxdr); -err_alloc_rx: - kfree(txdr); -err_alloc_tx: - if (netif_running(adapter->netdev)) - e1000_up(adapter); -err_setup: - clear_bit(__E1000_RESETTING, &adapter->flags); - return err; -} - -static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, int reg, - u32 mask, u32 write) -{ - struct e1000_hw *hw = &adapter->hw; - static const u32 test[] = { - 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF - }; - u8 __iomem *address = hw->hw_addr + reg; - u32 read; - int i; - - for (i = 0; i < ARRAY_SIZE(test); i++) { - writel(write & test[i], address); - read = readl(address); - if (read != (write & test[i] & mask)) { - e_err(drv, "pattern test reg %04X failed: " - "got 0x%08X expected 0x%08X\n", - reg, read, (write & test[i] & mask)); - *data = reg; - return true; - } - } - return false; -} - -static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, int reg, - u32 mask, u32 write) -{ - struct e1000_hw *hw = &adapter->hw; - u8 __iomem *address = hw->hw_addr + reg; - u32 read; - - writel(write & mask, address); - read = readl(address); - if ((read & mask) != (write & mask)) { - e_err(drv, "set/check reg %04X test failed: " - "got 0x%08X expected 0x%08X\n", - reg, (read & mask), (write & mask)); - *data = reg; - return true; - } - return false; -} - -#define REG_PATTERN_TEST(reg, mask, write) \ - do { \ - if (reg_pattern_test(adapter, data, \ - (hw->mac_type >= e1000_82543) \ - ? E1000_##reg : E1000_82542_##reg, \ - mask, write)) \ - return 1; \ - } while (0) - -#define REG_SET_AND_CHECK(reg, mask, write) \ - do { \ - if (reg_set_and_check(adapter, data, \ - (hw->mac_type >= e1000_82543) \ - ? E1000_##reg : E1000_82542_##reg, \ - mask, write)) \ - return 1; \ - } while (0) - -static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) -{ - u32 value, before, after; - u32 i, toggle; - struct e1000_hw *hw = &adapter->hw; - - /* The status register is Read Only, so a write should fail. - * Some bits that get toggled are ignored. - */ - - /* there are several bits on newer hardware that are r/w */ - toggle = 0xFFFFF833; - - before = er32(STATUS); - value = (er32(STATUS) & toggle); - ew32(STATUS, toggle); - after = er32(STATUS) & toggle; - if (value != after) { - e_err(drv, "failed STATUS register test got: " - "0x%08X expected: 0x%08X\n", after, value); - *data = 1; - return 1; - } - /* restore previous status */ - ew32(STATUS, before); - - REG_PATTERN_TEST(FCAL, 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(FCAH, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(FCT, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(VET, 0x0000FFFF, 0xFFFFFFFF); - - REG_PATTERN_TEST(RDTR, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(RDBAH, 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(RDLEN, 0x000FFF80, 0x000FFFFF); - REG_PATTERN_TEST(RDH, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(RDT, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(FCRTH, 0x0000FFF8, 0x0000FFF8); - REG_PATTERN_TEST(FCTTV, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(TIPG, 0x3FFFFFFF, 0x3FFFFFFF); - REG_PATTERN_TEST(TDBAH, 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(TDLEN, 0x000FFF80, 0x000FFFFF); - - REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x00000000); - - before = 0x06DFB3FE; - REG_SET_AND_CHECK(RCTL, before, 0x003FFFFB); - REG_SET_AND_CHECK(TCTL, 0xFFFFFFFF, 0x00000000); - - if (hw->mac_type >= e1000_82543) { - REG_SET_AND_CHECK(RCTL, before, 0xFFFFFFFF); - REG_PATTERN_TEST(RDBAL, 0xFFFFFFF0, 0xFFFFFFFF); - REG_PATTERN_TEST(TXCW, 0xC000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(TDBAL, 0xFFFFFFF0, 0xFFFFFFFF); - REG_PATTERN_TEST(TIDV, 0x0000FFFF, 0x0000FFFF); - value = E1000_RAR_ENTRIES; - for (i = 0; i < value; i++) { - REG_PATTERN_TEST(RA + (((i << 1) + 1) << 2), - 0x8003FFFF, 0xFFFFFFFF); - } - } else { - REG_SET_AND_CHECK(RCTL, 0xFFFFFFFF, 0x01FFFFFF); - REG_PATTERN_TEST(RDBAL, 0xFFFFF000, 0xFFFFFFFF); - REG_PATTERN_TEST(TXCW, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(TDBAL, 0xFFFFF000, 0xFFFFFFFF); - } - - value = E1000_MC_TBL_SIZE; - for (i = 0; i < value; i++) - REG_PATTERN_TEST(MTA + (i << 2), 0xFFFFFFFF, 0xFFFFFFFF); - - *data = 0; - return 0; -} - -static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data) -{ - struct e1000_hw *hw = &adapter->hw; - u16 temp; - u16 checksum = 0; - u16 i; - - *data = 0; - /* Read and add up the contents of the EEPROM */ - for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { - if ((e1000_read_eeprom(hw, i, 1, &temp)) < 0) { - *data = 1; - break; - } - checksum += temp; - } - - /* If Checksum is not Correct return error else test passed */ - if ((checksum != (u16)EEPROM_SUM) && !(*data)) - *data = 2; - - return *data; -} - -static irqreturn_t e1000_test_intr(int irq, void *data) -{ - struct net_device *netdev = (struct net_device *)data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - adapter->test_icr |= er32(ICR); - - return IRQ_HANDLED; -} - -static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) -{ - struct net_device *netdev = adapter->netdev; - u32 mask, i = 0; - bool shared_int = true; - u32 irq = adapter->pdev->irq; - struct e1000_hw *hw = &adapter->hw; - - *data = 0; - - /* NOTE: we don't test MSI interrupts here, yet - * Hook up test interrupt handler just for this test - */ - if (!request_irq(irq, e1000_test_intr, IRQF_PROBE_SHARED, netdev->name, - netdev)) - shared_int = false; - else if (request_irq(irq, e1000_test_intr, IRQF_SHARED, - netdev->name, netdev)) { - *data = 1; - return -1; - } - e_info(hw, "testing %s interrupt\n", (shared_int ? - "shared" : "unshared")); - - /* Disable all the interrupts */ - ew32(IMC, 0xFFFFFFFF); - E1000_WRITE_FLUSH(); - msleep(10); - - /* Test each interrupt */ - for (; i < 10; i++) { - /* Interrupt to test */ - mask = 1 << i; - - if (!shared_int) { - /* Disable the interrupt to be reported in - * the cause register and then force the same - * interrupt and see if one gets posted. If - * an interrupt was posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - ew32(IMC, mask); - ew32(ICS, mask); - E1000_WRITE_FLUSH(); - msleep(10); - - if (adapter->test_icr & mask) { - *data = 3; - break; - } - } - - /* Enable the interrupt to be reported in - * the cause register and then force the same - * interrupt and see if one gets posted. If - * an interrupt was not posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - ew32(IMS, mask); - ew32(ICS, mask); - E1000_WRITE_FLUSH(); - msleep(10); - - if (!(adapter->test_icr & mask)) { - *data = 4; - break; - } - - if (!shared_int) { - /* Disable the other interrupts to be reported in - * the cause register and then force the other - * interrupts and see if any get posted. If - * an interrupt was posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - ew32(IMC, ~mask & 0x00007FFF); - ew32(ICS, ~mask & 0x00007FFF); - E1000_WRITE_FLUSH(); - msleep(10); - - if (adapter->test_icr) { - *data = 5; - break; - } - } - } - - /* Disable all the interrupts */ - ew32(IMC, 0xFFFFFFFF); - E1000_WRITE_FLUSH(); - msleep(10); - - /* Unhook test interrupt handler */ - free_irq(irq, netdev); - - return *data; -} - -static void e1000_free_desc_rings(struct e1000_adapter *adapter) -{ - struct e1000_tx_ring *txdr = &adapter->test_tx_ring; - struct e1000_rx_ring *rxdr = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - int i; - - if (txdr->desc && txdr->buffer_info) { - for (i = 0; i < txdr->count; i++) { - if (txdr->buffer_info[i].dma) - dma_unmap_single(&pdev->dev, - txdr->buffer_info[i].dma, - txdr->buffer_info[i].length, - DMA_TO_DEVICE); - if (txdr->buffer_info[i].skb) - dev_kfree_skb(txdr->buffer_info[i].skb); - } - } - - if (rxdr->desc && rxdr->buffer_info) { - for (i = 0; i < rxdr->count; i++) { - if (rxdr->buffer_info[i].dma) - dma_unmap_single(&pdev->dev, - rxdr->buffer_info[i].dma, - E1000_RXBUFFER_2048, - DMA_FROM_DEVICE); - kfree(rxdr->buffer_info[i].rxbuf.data); - } - } - - if (txdr->desc) { - dma_free_coherent(&pdev->dev, txdr->size, txdr->desc, - txdr->dma); - txdr->desc = NULL; - } - if (rxdr->desc) { - dma_free_coherent(&pdev->dev, rxdr->size, rxdr->desc, - rxdr->dma); - rxdr->desc = NULL; - } - - kfree(txdr->buffer_info); - txdr->buffer_info = NULL; - kfree(rxdr->buffer_info); - rxdr->buffer_info = NULL; -} - -static int e1000_setup_desc_rings(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_tx_ring *txdr = &adapter->test_tx_ring; - struct e1000_rx_ring *rxdr = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - u32 rctl; - int i, ret_val; - - /* Setup Tx descriptor ring and Tx buffers */ - - if (!txdr->count) - txdr->count = E1000_DEFAULT_TXD; - - txdr->buffer_info = kcalloc(txdr->count, sizeof(struct e1000_tx_buffer), - GFP_KERNEL); - if (!txdr->buffer_info) { - ret_val = 1; - goto err_nomem; - } - - txdr->size = txdr->count * sizeof(struct e1000_tx_desc); - txdr->size = ALIGN(txdr->size, 4096); - txdr->desc = dma_zalloc_coherent(&pdev->dev, txdr->size, &txdr->dma, - GFP_KERNEL); - if (!txdr->desc) { - ret_val = 2; - goto err_nomem; - } - txdr->next_to_use = txdr->next_to_clean = 0; - - ew32(TDBAL, ((u64)txdr->dma & 0x00000000FFFFFFFF)); - ew32(TDBAH, ((u64)txdr->dma >> 32)); - ew32(TDLEN, txdr->count * sizeof(struct e1000_tx_desc)); - ew32(TDH, 0); - ew32(TDT, 0); - ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | - E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | - E1000_FDX_COLLISION_DISTANCE << E1000_COLD_SHIFT); - - for (i = 0; i < txdr->count; i++) { - struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*txdr, i); - struct sk_buff *skb; - unsigned int size = 1024; - - skb = alloc_skb(size, GFP_KERNEL); - if (!skb) { - ret_val = 3; - goto err_nomem; - } - skb_put(skb, size); - txdr->buffer_info[i].skb = skb; - txdr->buffer_info[i].length = skb->len; - txdr->buffer_info[i].dma = - dma_map_single(&pdev->dev, skb->data, skb->len, - DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, txdr->buffer_info[i].dma)) { - ret_val = 4; - goto err_nomem; - } - tx_desc->buffer_addr = cpu_to_le64(txdr->buffer_info[i].dma); - tx_desc->lower.data = cpu_to_le32(skb->len); - tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP | - E1000_TXD_CMD_IFCS | - E1000_TXD_CMD_RPS); - tx_desc->upper.data = 0; - } - - /* Setup Rx descriptor ring and Rx buffers */ - - if (!rxdr->count) - rxdr->count = E1000_DEFAULT_RXD; - - rxdr->buffer_info = kcalloc(rxdr->count, sizeof(struct e1000_rx_buffer), - GFP_KERNEL); - if (!rxdr->buffer_info) { - ret_val = 5; - goto err_nomem; - } - - rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc); - rxdr->desc = dma_zalloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma, - GFP_KERNEL); - if (!rxdr->desc) { - ret_val = 6; - goto err_nomem; - } - rxdr->next_to_use = rxdr->next_to_clean = 0; - - rctl = er32(RCTL); - ew32(RCTL, rctl & ~E1000_RCTL_EN); - ew32(RDBAL, ((u64)rxdr->dma & 0xFFFFFFFF)); - ew32(RDBAH, ((u64)rxdr->dma >> 32)); - ew32(RDLEN, rxdr->size); - ew32(RDH, 0); - ew32(RDT, 0); - rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | - E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | - (hw->mc_filter_type << E1000_RCTL_MO_SHIFT); - ew32(RCTL, rctl); - - for (i = 0; i < rxdr->count; i++) { - struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rxdr, i); - u8 *buf; - - buf = kzalloc(E1000_RXBUFFER_2048 + NET_SKB_PAD + NET_IP_ALIGN, - GFP_KERNEL); - if (!buf) { - ret_val = 7; - goto err_nomem; - } - rxdr->buffer_info[i].rxbuf.data = buf; - - rxdr->buffer_info[i].dma = - dma_map_single(&pdev->dev, - buf + NET_SKB_PAD + NET_IP_ALIGN, - E1000_RXBUFFER_2048, DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, rxdr->buffer_info[i].dma)) { - ret_val = 8; - goto err_nomem; - } - rx_desc->buffer_addr = cpu_to_le64(rxdr->buffer_info[i].dma); - } - - return 0; - -err_nomem: - e1000_free_desc_rings(adapter); - return ret_val; -} - -static void e1000_phy_disable_receiver(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - /* Write out to PHY registers 29 and 30 to disable the Receiver. */ - e1000_write_phy_reg(hw, 29, 0x001F); - e1000_write_phy_reg(hw, 30, 0x8FFC); - e1000_write_phy_reg(hw, 29, 0x001A); - e1000_write_phy_reg(hw, 30, 0x8FF0); -} - -static void e1000_phy_reset_clk_and_crs(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u16 phy_reg; - - /* Because we reset the PHY above, we need to re-force TX_CLK in the - * Extended PHY Specific Control Register to 25MHz clock. This - * value defaults back to a 2.5MHz clock when the PHY is reset. - */ - e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg); - phy_reg |= M88E1000_EPSCR_TX_CLK_25; - e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_reg); - - /* In addition, because of the s/w reset above, we need to enable - * CRS on TX. This must be set for both full and half duplex - * operation. - */ - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_reg); - phy_reg |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_reg); -} - -static int e1000_nonintegrated_phy_loopback(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl_reg; - u16 phy_reg; - - /* Setup the Device Control Register for PHY loopback test. */ - - ctrl_reg = er32(CTRL); - ctrl_reg |= (E1000_CTRL_ILOS | /* Invert Loss-Of-Signal */ - E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ - E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ - E1000_CTRL_SPD_1000 | /* Force Speed to 1000 */ - E1000_CTRL_FD); /* Force Duplex to FULL */ - - ew32(CTRL, ctrl_reg); - - /* Read the PHY Specific Control Register (0x10) */ - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_reg); - - /* Clear Auto-Crossover bits in PHY Specific Control Register - * (bits 6:5). - */ - phy_reg &= ~M88E1000_PSCR_AUTO_X_MODE; - e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_reg); - - /* Perform software reset on the PHY */ - e1000_phy_reset(hw); - - /* Have to setup TX_CLK and TX_CRS after software reset */ - e1000_phy_reset_clk_and_crs(adapter); - - e1000_write_phy_reg(hw, PHY_CTRL, 0x8100); - - /* Wait for reset to complete. */ - udelay(500); - - /* Have to setup TX_CLK and TX_CRS after software reset */ - e1000_phy_reset_clk_and_crs(adapter); - - /* Write out to PHY registers 29 and 30 to disable the Receiver. */ - e1000_phy_disable_receiver(adapter); - - /* Set the loopback bit in the PHY control register. */ - e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg); - phy_reg |= MII_CR_LOOPBACK; - e1000_write_phy_reg(hw, PHY_CTRL, phy_reg); - - /* Setup TX_CLK and TX_CRS one more time. */ - e1000_phy_reset_clk_and_crs(adapter); - - /* Check Phy Configuration */ - e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg); - if (phy_reg != 0x4100) - return 9; - - e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_reg); - if (phy_reg != 0x0070) - return 10; - - e1000_read_phy_reg(hw, 29, &phy_reg); - if (phy_reg != 0x001A) - return 11; - - return 0; -} - -static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl_reg = 0; - u32 stat_reg = 0; - - hw->autoneg = false; - - if (hw->phy_type == e1000_phy_m88) { - /* Auto-MDI/MDIX Off */ - e1000_write_phy_reg(hw, - M88E1000_PHY_SPEC_CTRL, 0x0808); - /* reset to update Auto-MDI/MDIX */ - e1000_write_phy_reg(hw, PHY_CTRL, 0x9140); - /* autoneg off */ - e1000_write_phy_reg(hw, PHY_CTRL, 0x8140); - } - - ctrl_reg = er32(CTRL); - - /* force 1000, set loopback */ - e1000_write_phy_reg(hw, PHY_CTRL, 0x4140); - - /* Now set up the MAC to the same speed/duplex as the PHY. */ - ctrl_reg = er32(CTRL); - ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ - ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ - E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ - E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ - E1000_CTRL_FD); /* Force Duplex to FULL */ - - if (hw->media_type == e1000_media_type_copper && - hw->phy_type == e1000_phy_m88) - ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ - else { - /* Set the ILOS bit on the fiber Nic is half - * duplex link is detected. - */ - stat_reg = er32(STATUS); - if ((stat_reg & E1000_STATUS_FD) == 0) - ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU); - } - - ew32(CTRL, ctrl_reg); - - /* Disable the receiver on the PHY so when a cable is plugged in, the - * PHY does not begin to autoneg when a cable is reconnected to the NIC. - */ - if (hw->phy_type == e1000_phy_m88) - e1000_phy_disable_receiver(adapter); - - udelay(500); - - return 0; -} - -static int e1000_set_phy_loopback(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u16 phy_reg = 0; - u16 count = 0; - - switch (hw->mac_type) { - case e1000_82543: - if (hw->media_type == e1000_media_type_copper) { - /* Attempt to setup Loopback mode on Non-integrated PHY. - * Some PHY registers get corrupted at random, so - * attempt this 10 times. - */ - while (e1000_nonintegrated_phy_loopback(adapter) && - count++ < 10); - if (count < 11) - return 0; - } - break; - - case e1000_82544: - case e1000_82540: - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_82546_rev_3: - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - return e1000_integrated_phy_loopback(adapter); - default: - /* Default PHY loopback work is to read the MII - * control register and assert bit 14 (loopback mode). - */ - e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg); - phy_reg |= MII_CR_LOOPBACK; - e1000_write_phy_reg(hw, PHY_CTRL, phy_reg); - return 0; - } - - return 8; -} - -static int e1000_setup_loopback_test(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - if (hw->media_type == e1000_media_type_fiber || - hw->media_type == e1000_media_type_internal_serdes) { - switch (hw->mac_type) { - case e1000_82545: - case e1000_82546: - case e1000_82545_rev_3: - case e1000_82546_rev_3: - return e1000_set_phy_loopback(adapter); - default: - rctl = er32(RCTL); - rctl |= E1000_RCTL_LBM_TCVR; - ew32(RCTL, rctl); - return 0; - } - } else if (hw->media_type == e1000_media_type_copper) { - return e1000_set_phy_loopback(adapter); - } - - return 7; -} - -static void e1000_loopback_cleanup(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - u16 phy_reg; - - rctl = er32(RCTL); - rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); - ew32(RCTL, rctl); - - switch (hw->mac_type) { - case e1000_82545: - case e1000_82546: - case e1000_82545_rev_3: - case e1000_82546_rev_3: - default: - hw->autoneg = true; - e1000_read_phy_reg(hw, PHY_CTRL, &phy_reg); - if (phy_reg & MII_CR_LOOPBACK) { - phy_reg &= ~MII_CR_LOOPBACK; - e1000_write_phy_reg(hw, PHY_CTRL, phy_reg); - e1000_phy_reset(hw); - } - break; - } -} - -static void e1000_create_lbtest_frame(struct sk_buff *skb, - unsigned int frame_size) -{ - memset(skb->data, 0xFF, frame_size); - frame_size &= ~1; - memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1); - memset(&skb->data[frame_size / 2 + 10], 0xBE, 1); - memset(&skb->data[frame_size / 2 + 12], 0xAF, 1); -} - -static int e1000_check_lbtest_frame(const unsigned char *data, - unsigned int frame_size) -{ - frame_size &= ~1; - if (*(data + 3) == 0xFF) { - if ((*(data + frame_size / 2 + 10) == 0xBE) && - (*(data + frame_size / 2 + 12) == 0xAF)) { - return 0; - } - } - return 13; -} - -static int e1000_run_loopback_test(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_tx_ring *txdr = &adapter->test_tx_ring; - struct e1000_rx_ring *rxdr = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - int i, j, k, l, lc, good_cnt, ret_val = 0; - unsigned long time; - - ew32(RDT, rxdr->count - 1); - - /* Calculate the loop count based on the largest descriptor ring - * The idea is to wrap the largest ring a number of times using 64 - * send/receive pairs during each loop - */ - - if (rxdr->count <= txdr->count) - lc = ((txdr->count / 64) * 2) + 1; - else - lc = ((rxdr->count / 64) * 2) + 1; - - k = l = 0; - for (j = 0; j <= lc; j++) { /* loop count loop */ - for (i = 0; i < 64; i++) { /* send the packets */ - e1000_create_lbtest_frame(txdr->buffer_info[i].skb, - 1024); - dma_sync_single_for_device(&pdev->dev, - txdr->buffer_info[k].dma, - txdr->buffer_info[k].length, - DMA_TO_DEVICE); - if (unlikely(++k == txdr->count)) - k = 0; - } - ew32(TDT, k); - E1000_WRITE_FLUSH(); - msleep(200); - time = jiffies; /* set the start time for the receive */ - good_cnt = 0; - do { /* receive the sent packets */ - dma_sync_single_for_cpu(&pdev->dev, - rxdr->buffer_info[l].dma, - E1000_RXBUFFER_2048, - DMA_FROM_DEVICE); - - ret_val = e1000_check_lbtest_frame( - rxdr->buffer_info[l].rxbuf.data + - NET_SKB_PAD + NET_IP_ALIGN, - 1024); - if (!ret_val) - good_cnt++; - if (unlikely(++l == rxdr->count)) - l = 0; - /* time + 20 msecs (200 msecs on 2.4) is more than - * enough time to complete the receives, if it's - * exceeded, break and error off - */ - } while (good_cnt < 64 && time_after(time + 20, jiffies)); - - if (good_cnt != 64) { - ret_val = 13; /* ret_val is the same as mis-compare */ - break; - } - if (time_after_eq(jiffies, time + 2)) { - ret_val = 14; /* error code for time out error */ - break; - } - } /* end loop count loop */ - return ret_val; -} - -static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) -{ - *data = e1000_setup_desc_rings(adapter); - if (*data) - goto out; - *data = e1000_setup_loopback_test(adapter); - if (*data) - goto err_loopback; - *data = e1000_run_loopback_test(adapter); - e1000_loopback_cleanup(adapter); - -err_loopback: - e1000_free_desc_rings(adapter); -out: - return *data; -} - -static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) -{ - struct e1000_hw *hw = &adapter->hw; - *data = 0; - if (hw->media_type == e1000_media_type_internal_serdes) { - int i = 0; - - hw->serdes_has_link = false; - - /* On some blade server designs, link establishment - * could take as long as 2-3 minutes - */ - do { - e1000_check_for_link(hw); - if (hw->serdes_has_link) - return *data; - msleep(20); - } while (i++ < 3750); - - *data = 1; - } else { - e1000_check_for_link(hw); - if (hw->autoneg) /* if auto_neg is set wait for it */ - msleep(4000); - - if (!(er32(STATUS) & E1000_STATUS_LU)) - *data = 1; - } - return *data; -} - -static int e1000_get_sset_count(struct net_device *netdev, int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E1000_TEST_LEN; - case ETH_SS_STATS: - return E1000_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e1000_diag_test(struct net_device *netdev, - struct ethtool_test *eth_test, u64 *data) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - bool if_running = netif_running(netdev); - - set_bit(__E1000_TESTING, &adapter->flags); - if (eth_test->flags == ETH_TEST_FL_OFFLINE) { - /* Offline tests */ - - /* save speed, duplex, autoneg settings */ - u16 autoneg_advertised = hw->autoneg_advertised; - u8 forced_speed_duplex = hw->forced_speed_duplex; - u8 autoneg = hw->autoneg; - - e_info(hw, "offline testing starting\n"); - - /* Link test performed before hardware reset so autoneg doesn't - * interfere with test result - */ - if (e1000_link_test(adapter, &data[4])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - if (if_running) - /* indicate we're in test mode */ - dev_close(netdev); - else - e1000_reset(adapter); - - if (e1000_reg_test(adapter, &data[0])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000_reset(adapter); - if (e1000_eeprom_test(adapter, &data[1])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000_reset(adapter); - if (e1000_intr_test(adapter, &data[2])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000_reset(adapter); - /* make sure the phy is powered up */ - e1000_power_up_phy(adapter); - if (e1000_loopback_test(adapter, &data[3])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - /* restore speed, duplex, autoneg settings */ - hw->autoneg_advertised = autoneg_advertised; - hw->forced_speed_duplex = forced_speed_duplex; - hw->autoneg = autoneg; - - e1000_reset(adapter); - clear_bit(__E1000_TESTING, &adapter->flags); - if (if_running) - dev_open(netdev); - } else { - e_info(hw, "online testing starting\n"); - /* Online tests */ - if (e1000_link_test(adapter, &data[4])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - /* Online tests aren't run; pass by default */ - data[0] = 0; - data[1] = 0; - data[2] = 0; - data[3] = 0; - - clear_bit(__E1000_TESTING, &adapter->flags); - } - msleep_interruptible(4 * 1000); -} - -static int e1000_wol_exclusion(struct e1000_adapter *adapter, - struct ethtool_wolinfo *wol) -{ - struct e1000_hw *hw = &adapter->hw; - int retval = 1; /* fail by default */ - - switch (hw->device_id) { - case E1000_DEV_ID_82542: - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82546GB_QUAD_COPPER: - case E1000_DEV_ID_82546GB_PCIE: - /* these don't support WoL at all */ - wol->supported = 0; - break; - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546GB_FIBER: - /* Wake events not supported on port B */ - if (er32(STATUS) & E1000_STATUS_FUNC_1) { - wol->supported = 0; - break; - } - /* return success for non excluded adapter ports */ - retval = 0; - break; - case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: - /* quad port adapters only support WoL on port A */ - if (!adapter->quad_port_a) { - wol->supported = 0; - break; - } - /* return success for non excluded adapter ports */ - retval = 0; - break; - default: - /* dual port cards only support WoL on port A from now on - * unless it was enabled in the eeprom for port B - * so exclude FUNC_1 ports from having WoL enabled - */ - if (er32(STATUS) & E1000_STATUS_FUNC_1 && - !adapter->eeprom_wol) { - wol->supported = 0; - break; - } - - retval = 0; - } - - return retval; -} - -static void e1000_get_wol(struct net_device *netdev, - struct ethtool_wolinfo *wol) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - wol->supported = WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | WAKE_MAGIC; - wol->wolopts = 0; - - /* this function will set ->supported = 0 and return 1 if wol is not - * supported by this hardware - */ - if (e1000_wol_exclusion(adapter, wol) || - !device_can_wakeup(&adapter->pdev->dev)) - return; - - /* apply any specific unsupported masks here */ - switch (hw->device_id) { - case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: - /* KSP3 does not support UCAST wake-ups */ - wol->supported &= ~WAKE_UCAST; - - if (adapter->wol & E1000_WUFC_EX) - e_err(drv, "Interface does not support directed " - "(unicast) frame wake-up packets\n"); - break; - default: - break; - } - - if (adapter->wol & E1000_WUFC_EX) - wol->wolopts |= WAKE_UCAST; - if (adapter->wol & E1000_WUFC_MC) - wol->wolopts |= WAKE_MCAST; - if (adapter->wol & E1000_WUFC_BC) - wol->wolopts |= WAKE_BCAST; - if (adapter->wol & E1000_WUFC_MAG) - wol->wolopts |= WAKE_MAGIC; -} - -static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - if (wol->wolopts & (WAKE_PHY | WAKE_ARP | WAKE_MAGICSECURE)) - return -EOPNOTSUPP; - - if (e1000_wol_exclusion(adapter, wol) || - !device_can_wakeup(&adapter->pdev->dev)) - return wol->wolopts ? -EOPNOTSUPP : 0; - - switch (hw->device_id) { - case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: - if (wol->wolopts & WAKE_UCAST) { - e_err(drv, "Interface does not support directed " - "(unicast) frame wake-up packets\n"); - return -EOPNOTSUPP; - } - break; - default: - break; - } - - /* these settings will always override what we currently have */ - adapter->wol = 0; - - if (wol->wolopts & WAKE_UCAST) - adapter->wol |= E1000_WUFC_EX; - if (wol->wolopts & WAKE_MCAST) - adapter->wol |= E1000_WUFC_MC; - if (wol->wolopts & WAKE_BCAST) - adapter->wol |= E1000_WUFC_BC; - if (wol->wolopts & WAKE_MAGIC) - adapter->wol |= E1000_WUFC_MAG; - - device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); - - return 0; -} - -static int e1000_set_phys_id(struct net_device *netdev, - enum ethtool_phys_id_state state) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - switch (state) { - case ETHTOOL_ID_ACTIVE: - e1000_setup_led(hw); - return 2; - - case ETHTOOL_ID_ON: - e1000_led_on(hw); - break; - - case ETHTOOL_ID_OFF: - e1000_led_off(hw); - break; - - case ETHTOOL_ID_INACTIVE: - e1000_cleanup_led(hw); - } - - return 0; -} - -static int e1000_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (adapter->hw.mac_type < e1000_82545) - return -EOPNOTSUPP; - - if (adapter->itr_setting <= 4) - ec->rx_coalesce_usecs = adapter->itr_setting; - else - ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting; - - return 0; -} - -static int e1000_set_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - if (hw->mac_type < e1000_82545) - return -EOPNOTSUPP; - - if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || - ((ec->rx_coalesce_usecs > 4) && - (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) || - (ec->rx_coalesce_usecs == 2)) - return -EINVAL; - - if (ec->rx_coalesce_usecs == 4) { - adapter->itr = adapter->itr_setting = 4; - } else if (ec->rx_coalesce_usecs <= 3) { - adapter->itr = 20000; - adapter->itr_setting = ec->rx_coalesce_usecs; - } else { - adapter->itr = (1000000 / ec->rx_coalesce_usecs); - adapter->itr_setting = adapter->itr & ~3; - } - - if (adapter->itr_setting != 0) - ew32(ITR, 1000000000 / (adapter->itr * 256)); - else - ew32(ITR, 0); - - return 0; -} - -static int e1000_nway_reset(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (netif_running(netdev)) - e1000_reinit_locked(adapter); - return 0; -} - -static void e1000_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats *stats, u64 *data) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - int i; - const struct e1000_stats *stat = e1000_gstrings_stats; - - e1000_update_stats(adapter); - for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++, stat++) { - char *p; - - switch (stat->type) { - case NETDEV_STATS: - p = (char *)netdev + stat->stat_offset; - break; - case E1000_STATS: - p = (char *)adapter + stat->stat_offset; - break; - default: - WARN_ONCE(1, "Invalid E1000 stat type: %u index %d\n", - stat->type, i); - continue; - } - - if (stat->sizeof_stat == sizeof(u64)) - data[i] = *(u64 *)p; - else - data[i] = *(u32 *)p; - } -/* BUG_ON(i != E1000_STATS_LEN); */ -} - -static void e1000_get_strings(struct net_device *netdev, u32 stringset, - u8 *data) -{ - u8 *p = data; - int i; - - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, e1000_gstrings_test, sizeof(e1000_gstrings_test)); - break; - case ETH_SS_STATS: - for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { - memcpy(p, e1000_gstrings_stats[i].stat_string, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - } - /* BUG_ON(p - data != E1000_STATS_LEN * ETH_GSTRING_LEN); */ - break; - } -} - -static const struct ethtool_ops e1000_ethtool_ops = { - .get_settings = e1000_get_settings, - .set_settings = e1000_set_settings, - .get_drvinfo = e1000_get_drvinfo, - .get_regs_len = e1000_get_regs_len, - .get_regs = e1000_get_regs, - .get_wol = e1000_get_wol, - .set_wol = e1000_set_wol, - .get_msglevel = e1000_get_msglevel, - .set_msglevel = e1000_set_msglevel, - .nway_reset = e1000_nway_reset, - .get_link = e1000_get_link, - .get_eeprom_len = e1000_get_eeprom_len, - .get_eeprom = e1000_get_eeprom, - .set_eeprom = e1000_set_eeprom, - .get_ringparam = e1000_get_ringparam, - .set_ringparam = e1000_set_ringparam, - .get_pauseparam = e1000_get_pauseparam, - .set_pauseparam = e1000_set_pauseparam, - .self_test = e1000_diag_test, - .get_strings = e1000_get_strings, - .set_phys_id = e1000_set_phys_id, - .get_ethtool_stats = e1000_get_ethtool_stats, - .get_sset_count = e1000_get_sset_count, - .get_coalesce = e1000_get_coalesce, - .set_coalesce = e1000_set_coalesce, - .get_ts_info = ethtool_op_get_ts_info, -}; - -void e1000_set_ethtool_ops(struct net_device *netdev) -{ - netdev->ethtool_ops = &e1000_ethtool_ops; -} diff --git a/addons/e1000/src/4.4.180/e1000_hw.c b/addons/e1000/src/4.4.180/e1000_hw.c deleted file mode 100644 index b1af0d61..00000000 --- a/addons/e1000/src/4.4.180/e1000_hw.c +++ /dev/null @@ -1,5681 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - - */ - -/* e1000_hw.c - * Shared functions for accessing and configuring the MAC - */ - -#include "e1000.h" - -static s32 e1000_check_downshift(struct e1000_hw *hw); -static s32 e1000_check_polarity(struct e1000_hw *hw, - e1000_rev_polarity *polarity); -static void e1000_clear_hw_cntrs(struct e1000_hw *hw); -static void e1000_clear_vfta(struct e1000_hw *hw); -static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, - bool link_up); -static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw); -static s32 e1000_detect_gig_phy(struct e1000_hw *hw); -static s32 e1000_get_auto_rd_done(struct e1000_hw *hw); -static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length, - u16 *max_length); -static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw); -static s32 e1000_id_led_init(struct e1000_hw *hw); -static void e1000_init_rx_addrs(struct e1000_hw *hw); -static s32 e1000_phy_igp_get_info(struct e1000_hw *hw, - struct e1000_phy_info *phy_info); -static s32 e1000_phy_m88_get_info(struct e1000_hw *hw, - struct e1000_phy_info *phy_info); -static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active); -static s32 e1000_wait_autoneg(struct e1000_hw *hw); -static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value); -static s32 e1000_set_phy_type(struct e1000_hw *hw); -static void e1000_phy_init_script(struct e1000_hw *hw); -static s32 e1000_setup_copper_link(struct e1000_hw *hw); -static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw); -static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw); -static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw); -static s32 e1000_config_mac_to_phy(struct e1000_hw *hw); -static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl); -static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl); -static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count); -static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw); -static s32 e1000_phy_reset_dsp(struct e1000_hw *hw); -static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw); -static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd); -static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd); -static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count); -static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, - u16 phy_data); -static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, - u16 *phy_data); -static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count); -static s32 e1000_acquire_eeprom(struct e1000_hw *hw); -static void e1000_release_eeprom(struct e1000_hw *hw); -static void e1000_standby_eeprom(struct e1000_hw *hw); -static s32 e1000_set_vco_speed(struct e1000_hw *hw); -static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw); -static s32 e1000_set_phy_mode(struct e1000_hw *hw); -static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data); -static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data); - -/* IGP cable length table */ -static const -u16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = { - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, - 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, - 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, - 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, - 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, - 100, - 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, - 110, 110, - 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, - 120, 120 -}; - -static DEFINE_SPINLOCK(e1000_eeprom_lock); -static DEFINE_SPINLOCK(e1000_phy_lock); - -/** - * e1000_set_phy_type - Set the phy type member in the hw struct. - * @hw: Struct containing variables accessed by shared code - */ -static s32 e1000_set_phy_type(struct e1000_hw *hw) -{ - if (hw->mac_type == e1000_undefined) - return -E1000_ERR_PHY_TYPE; - - switch (hw->phy_id) { - case M88E1000_E_PHY_ID: - case M88E1000_I_PHY_ID: - case M88E1011_I_PHY_ID: - case M88E1111_I_PHY_ID: - case M88E1118_E_PHY_ID: - hw->phy_type = e1000_phy_m88; - break; - case IGP01E1000_I_PHY_ID: - if (hw->mac_type == e1000_82541 || - hw->mac_type == e1000_82541_rev_2 || - hw->mac_type == e1000_82547 || - hw->mac_type == e1000_82547_rev_2) - hw->phy_type = e1000_phy_igp; - break; - case RTL8211B_PHY_ID: - hw->phy_type = e1000_phy_8211; - break; - case RTL8201N_PHY_ID: - hw->phy_type = e1000_phy_8201; - break; - default: - /* Should never have loaded on this device */ - hw->phy_type = e1000_phy_undefined; - return -E1000_ERR_PHY_TYPE; - } - - return E1000_SUCCESS; -} - -/** - * e1000_phy_init_script - IGP phy init script - initializes the GbE PHY - * @hw: Struct containing variables accessed by shared code - */ -static void e1000_phy_init_script(struct e1000_hw *hw) -{ - u32 ret_val; - u16 phy_saved_data; - - if (hw->phy_init_script) { - msleep(20); - - /* Save off the current value of register 0x2F5B to be restored - * at the end of this routine. - */ - ret_val = e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data); - - /* Disabled the PHY transmitter */ - e1000_write_phy_reg(hw, 0x2F5B, 0x0003); - msleep(20); - - e1000_write_phy_reg(hw, 0x0000, 0x0140); - msleep(5); - - switch (hw->mac_type) { - case e1000_82541: - case e1000_82547: - e1000_write_phy_reg(hw, 0x1F95, 0x0001); - e1000_write_phy_reg(hw, 0x1F71, 0xBD21); - e1000_write_phy_reg(hw, 0x1F79, 0x0018); - e1000_write_phy_reg(hw, 0x1F30, 0x1600); - e1000_write_phy_reg(hw, 0x1F31, 0x0014); - e1000_write_phy_reg(hw, 0x1F32, 0x161C); - e1000_write_phy_reg(hw, 0x1F94, 0x0003); - e1000_write_phy_reg(hw, 0x1F96, 0x003F); - e1000_write_phy_reg(hw, 0x2010, 0x0008); - break; - - case e1000_82541_rev_2: - case e1000_82547_rev_2: - e1000_write_phy_reg(hw, 0x1F73, 0x0099); - break; - default: - break; - } - - e1000_write_phy_reg(hw, 0x0000, 0x3300); - msleep(20); - - /* Now enable the transmitter */ - e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data); - - if (hw->mac_type == e1000_82547) { - u16 fused, fine, coarse; - - /* Move to analog registers page */ - e1000_read_phy_reg(hw, - IGP01E1000_ANALOG_SPARE_FUSE_STATUS, - &fused); - - if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { - e1000_read_phy_reg(hw, - IGP01E1000_ANALOG_FUSE_STATUS, - &fused); - - fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK; - coarse = - fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK; - - if (coarse > - IGP01E1000_ANALOG_FUSE_COARSE_THRESH) { - coarse -= - IGP01E1000_ANALOG_FUSE_COARSE_10; - fine -= IGP01E1000_ANALOG_FUSE_FINE_1; - } else if (coarse == - IGP01E1000_ANALOG_FUSE_COARSE_THRESH) - fine -= IGP01E1000_ANALOG_FUSE_FINE_10; - - fused = - (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | - (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | - (coarse & - IGP01E1000_ANALOG_FUSE_COARSE_MASK); - - e1000_write_phy_reg(hw, - IGP01E1000_ANALOG_FUSE_CONTROL, - fused); - e1000_write_phy_reg(hw, - IGP01E1000_ANALOG_FUSE_BYPASS, - IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL); - } - } - } -} - -/** - * e1000_set_mac_type - Set the mac type member in the hw struct. - * @hw: Struct containing variables accessed by shared code - */ -s32 e1000_set_mac_type(struct e1000_hw *hw) -{ - switch (hw->device_id) { - case E1000_DEV_ID_82542: - switch (hw->revision_id) { - case E1000_82542_2_0_REV_ID: - hw->mac_type = e1000_82542_rev2_0; - break; - case E1000_82542_2_1_REV_ID: - hw->mac_type = e1000_82542_rev2_1; - break; - default: - /* Invalid 82542 revision ID */ - return -E1000_ERR_MAC_TYPE; - } - break; - case E1000_DEV_ID_82543GC_FIBER: - case E1000_DEV_ID_82543GC_COPPER: - hw->mac_type = e1000_82543; - break; - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: - hw->mac_type = e1000_82544; - break; - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - hw->mac_type = e1000_82540; - break; - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82545EM_FIBER: - hw->mac_type = e1000_82545; - break; - case E1000_DEV_ID_82545GM_COPPER: - case E1000_DEV_ID_82545GM_FIBER: - case E1000_DEV_ID_82545GM_SERDES: - hw->mac_type = e1000_82545_rev_3; - break; - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - hw->mac_type = e1000_82546; - break; - case E1000_DEV_ID_82546GB_COPPER: - case E1000_DEV_ID_82546GB_FIBER: - case E1000_DEV_ID_82546GB_SERDES: - case E1000_DEV_ID_82546GB_PCIE: - case E1000_DEV_ID_82546GB_QUAD_COPPER: - case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: - hw->mac_type = e1000_82546_rev_3; - break; - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EI_MOBILE: - case E1000_DEV_ID_82541ER_LOM: - hw->mac_type = e1000_82541; - break; - case E1000_DEV_ID_82541ER: - case E1000_DEV_ID_82541GI: - case E1000_DEV_ID_82541GI_LF: - case E1000_DEV_ID_82541GI_MOBILE: - hw->mac_type = e1000_82541_rev_2; - break; - case E1000_DEV_ID_82547EI: - case E1000_DEV_ID_82547EI_MOBILE: - hw->mac_type = e1000_82547; - break; - case E1000_DEV_ID_82547GI: - hw->mac_type = e1000_82547_rev_2; - break; - case E1000_DEV_ID_INTEL_CE4100_GBE: - hw->mac_type = e1000_ce4100; - break; - default: - /* Should never have loaded on this device */ - return -E1000_ERR_MAC_TYPE; - } - - switch (hw->mac_type) { - case e1000_82541: - case e1000_82547: - case e1000_82541_rev_2: - case e1000_82547_rev_2: - hw->asf_firmware_present = true; - break; - default: - break; - } - - /* The 82543 chip does not count tx_carrier_errors properly in - * FD mode - */ - if (hw->mac_type == e1000_82543) - hw->bad_tx_carr_stats_fd = true; - - if (hw->mac_type > e1000_82544) - hw->has_smbus = true; - - return E1000_SUCCESS; -} - -/** - * e1000_set_media_type - Set media type and TBI compatibility. - * @hw: Struct containing variables accessed by shared code - */ -void e1000_set_media_type(struct e1000_hw *hw) -{ - u32 status; - - if (hw->mac_type != e1000_82543) { - /* tbi_compatibility is only valid on 82543 */ - hw->tbi_compatibility_en = false; - } - - switch (hw->device_id) { - case E1000_DEV_ID_82545GM_SERDES: - case E1000_DEV_ID_82546GB_SERDES: - hw->media_type = e1000_media_type_internal_serdes; - break; - default: - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - hw->media_type = e1000_media_type_fiber; - break; - case e1000_ce4100: - hw->media_type = e1000_media_type_copper; - break; - default: - status = er32(STATUS); - if (status & E1000_STATUS_TBIMODE) { - hw->media_type = e1000_media_type_fiber; - /* tbi_compatibility not valid on fiber */ - hw->tbi_compatibility_en = false; - } else { - hw->media_type = e1000_media_type_copper; - } - break; - } - } -} - -/** - * e1000_reset_hw - reset the hardware completely - * @hw: Struct containing variables accessed by shared code - * - * Reset the transmit and receive units; mask and clear all interrupts. - */ -s32 e1000_reset_hw(struct e1000_hw *hw) -{ - u32 ctrl; - u32 ctrl_ext; - u32 icr; - u32 manc; - u32 led_ctrl; - s32 ret_val; - - /* For 82542 (rev 2.0), disable MWI before issuing a device reset */ - if (hw->mac_type == e1000_82542_rev2_0) { - e_dbg("Disabling MWI on 82542 rev 2.0\n"); - e1000_pci_clear_mwi(hw); - } - - /* Clear interrupt mask to stop board from generating interrupts */ - e_dbg("Masking off all interrupts\n"); - ew32(IMC, 0xffffffff); - - /* Disable the Transmit and Receive units. Then delay to allow - * any pending transactions to complete before we hit the MAC with - * the global reset. - */ - ew32(RCTL, 0); - ew32(TCTL, E1000_TCTL_PSP); - E1000_WRITE_FLUSH(); - - /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */ - hw->tbi_compatibility_on = false; - - /* Delay to allow any outstanding PCI transactions to complete before - * resetting the device - */ - msleep(10); - - ctrl = er32(CTRL); - - /* Must reset the PHY before resetting the MAC */ - if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - ew32(CTRL, (ctrl | E1000_CTRL_PHY_RST)); - E1000_WRITE_FLUSH(); - msleep(5); - } - - /* Issue a global reset to the MAC. This will reset the chip's - * transmit, receive, DMA, and link units. It will not effect - * the current PCI configuration. The global reset bit is self- - * clearing, and should clear within a microsecond. - */ - e_dbg("Issuing a global reset to MAC\n"); - - switch (hw->mac_type) { - case e1000_82544: - case e1000_82540: - case e1000_82545: - case e1000_82546: - case e1000_82541: - case e1000_82541_rev_2: - /* These controllers can't ack the 64-bit write when issuing the - * reset, so use IO-mapping as a workaround to issue the reset - */ - E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); - break; - case e1000_82545_rev_3: - case e1000_82546_rev_3: - /* Reset is performed on a shadow of the control register */ - ew32(CTRL_DUP, (ctrl | E1000_CTRL_RST)); - break; - case e1000_ce4100: - default: - ew32(CTRL, (ctrl | E1000_CTRL_RST)); - break; - } - - /* After MAC reset, force reload of EEPROM to restore power-on settings - * to device. Later controllers reload the EEPROM automatically, so - * just wait for reload to complete. - */ - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - /* Wait for reset to complete */ - udelay(10); - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - ew32(CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(); - /* Wait for EEPROM reload */ - msleep(2); - break; - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - /* Wait for EEPROM reload */ - msleep(20); - break; - default: - /* Auto read done will delay 5ms or poll based on mac type */ - ret_val = e1000_get_auto_rd_done(hw); - if (ret_val) - return ret_val; - break; - } - - /* Disable HW ARPs on ASF enabled adapters */ - if (hw->mac_type >= e1000_82540) { - manc = er32(MANC); - manc &= ~(E1000_MANC_ARP_EN); - ew32(MANC, manc); - } - - if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - e1000_phy_init_script(hw); - - /* Configure activity LED after PHY reset */ - led_ctrl = er32(LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - ew32(LEDCTL, led_ctrl); - } - - /* Clear interrupt mask to stop board from generating interrupts */ - e_dbg("Masking off all interrupts\n"); - ew32(IMC, 0xffffffff); - - /* Clear any pending interrupt events. */ - icr = er32(ICR); - - /* If MWI was previously enabled, reenable it. */ - if (hw->mac_type == e1000_82542_rev2_0) { - if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE) - e1000_pci_set_mwi(hw); - } - - return E1000_SUCCESS; -} - -/** - * e1000_init_hw - Performs basic configuration of the adapter. - * @hw: Struct containing variables accessed by shared code - * - * Assumes that the controller has previously been reset and is in a - * post-reset uninitialized state. Initializes the receive address registers, - * multicast table, and VLAN filter table. Calls routines to setup link - * configuration and flow control settings. Clears all on-chip counters. Leaves - * the transmit and receive units disabled and uninitialized. - */ -s32 e1000_init_hw(struct e1000_hw *hw) -{ - u32 ctrl; - u32 i; - s32 ret_val; - u32 mta_size; - u32 ctrl_ext; - - /* Initialize Identification LED */ - ret_val = e1000_id_led_init(hw); - if (ret_val) { - e_dbg("Error Initializing Identification LED\n"); - return ret_val; - } - - /* Set the media type and TBI compatibility */ - e1000_set_media_type(hw); - - /* Disabling VLAN filtering. */ - e_dbg("Initializing the IEEE VLAN\n"); - if (hw->mac_type < e1000_82545_rev_3) - ew32(VET, 0); - e1000_clear_vfta(hw); - - /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ - if (hw->mac_type == e1000_82542_rev2_0) { - e_dbg("Disabling MWI on 82542 rev 2.0\n"); - e1000_pci_clear_mwi(hw); - ew32(RCTL, E1000_RCTL_RST); - E1000_WRITE_FLUSH(); - msleep(5); - } - - /* Setup the receive address. This involves initializing all of the - * Receive Address Registers (RARs 0 - 15). - */ - e1000_init_rx_addrs(hw); - - /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */ - if (hw->mac_type == e1000_82542_rev2_0) { - ew32(RCTL, 0); - E1000_WRITE_FLUSH(); - msleep(1); - if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE) - e1000_pci_set_mwi(hw); - } - - /* Zero out the Multicast HASH table */ - e_dbg("Zeroing the MTA\n"); - mta_size = E1000_MC_TBL_SIZE; - for (i = 0; i < mta_size; i++) { - E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); - /* use write flush to prevent Memory Write Block (MWB) from - * occurring when accessing our register space - */ - E1000_WRITE_FLUSH(); - } - - /* Set the PCI priority bit correctly in the CTRL register. This - * determines if the adapter gives priority to receives, or if it - * gives equal priority to transmits and receives. Valid only on - * 82542 and 82543 silicon. - */ - if (hw->dma_fairness && hw->mac_type <= e1000_82543) { - ctrl = er32(CTRL); - ew32(CTRL, ctrl | E1000_CTRL_PRIOR); - } - - switch (hw->mac_type) { - case e1000_82545_rev_3: - case e1000_82546_rev_3: - break; - default: - /* Workaround for PCI-X problem when BIOS sets MMRBC - * incorrectly. - */ - if (hw->bus_type == e1000_bus_type_pcix - && e1000_pcix_get_mmrbc(hw) > 2048) - e1000_pcix_set_mmrbc(hw, 2048); - break; - } - - /* Call a subroutine to configure the link and setup flow control. */ - ret_val = e1000_setup_link(hw); - - /* Set the transmit descriptor write-back policy */ - if (hw->mac_type > e1000_82544) { - ctrl = er32(TXDCTL); - ctrl = - (ctrl & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB; - ew32(TXDCTL, ctrl); - } - - /* Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs(hw); - - if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER || - hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) { - ctrl_ext = er32(CTRL_EXT); - /* Relaxed ordering must be disabled to avoid a parity - * error crash in a PCI slot. - */ - ctrl_ext |= E1000_CTRL_EXT_RO_DIS; - ew32(CTRL_EXT, ctrl_ext); - } - - return ret_val; -} - -/** - * e1000_adjust_serdes_amplitude - Adjust SERDES output amplitude based on EEPROM setting. - * @hw: Struct containing variables accessed by shared code. - */ -static s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw) -{ - u16 eeprom_data; - s32 ret_val; - - if (hw->media_type != e1000_media_type_internal_serdes) - return E1000_SUCCESS; - - switch (hw->mac_type) { - case e1000_82545_rev_3: - case e1000_82546_rev_3: - break; - default: - return E1000_SUCCESS; - } - - ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1, - &eeprom_data); - if (ret_val) { - return ret_val; - } - - if (eeprom_data != EEPROM_RESERVED_WORD) { - /* Adjust SERDES output amplitude only. */ - eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data); - if (ret_val) - return ret_val; - } - - return E1000_SUCCESS; -} - -/** - * e1000_setup_link - Configures flow control and link settings. - * @hw: Struct containing variables accessed by shared code - * - * Determines which flow control settings to use. Calls the appropriate media- - * specific link configuration function. Configures the flow control settings. - * Assuming the adapter has a valid link partner, a valid link should be - * established. Assumes the hardware has previously been reset and the - * transmitter and receiver are not enabled. - */ -s32 e1000_setup_link(struct e1000_hw *hw) -{ - u32 ctrl_ext; - s32 ret_val; - u16 eeprom_data; - - /* Read and store word 0x0F of the EEPROM. This word contains bits - * that determine the hardware's default PAUSE (flow control) mode, - * a bit that determines whether the HW defaults to enabling or - * disabling auto-negotiation, and the direction of the - * SW defined pins. If there is no SW over-ride of the flow - * control setting, then the variable hw->fc will - * be initialized based on a value in the EEPROM. - */ - if (hw->fc == E1000_FC_DEFAULT) { - ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, - 1, &eeprom_data); - if (ret_val) { - e_dbg("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) - hw->fc = E1000_FC_NONE; - else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == - EEPROM_WORD0F_ASM_DIR) - hw->fc = E1000_FC_TX_PAUSE; - else - hw->fc = E1000_FC_FULL; - } - - /* We want to save off the original Flow Control configuration just - * in case we get disconnected and then reconnected into a different - * hub or switch with different Flow Control capabilities. - */ - if (hw->mac_type == e1000_82542_rev2_0) - hw->fc &= (~E1000_FC_TX_PAUSE); - - if ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1)) - hw->fc &= (~E1000_FC_RX_PAUSE); - - hw->original_fc = hw->fc; - - e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc); - - /* Take the 4 bits from EEPROM word 0x0F that determine the initial - * polarity value for the SW controlled pins, and setup the - * Extended Device Control reg with that info. - * This is needed because one of the SW controlled pins is used for - * signal detection. So this should be done before e1000_setup_pcs_link() - * or e1000_phy_setup() is called. - */ - if (hw->mac_type == e1000_82543) { - ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, - 1, &eeprom_data); - if (ret_val) { - e_dbg("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) << - SWDPIO__EXT_SHIFT); - ew32(CTRL_EXT, ctrl_ext); - } - - /* Call the necessary subroutine to configure the link. */ - ret_val = (hw->media_type == e1000_media_type_copper) ? - e1000_setup_copper_link(hw) : e1000_setup_fiber_serdes_link(hw); - - /* Initialize the flow control address, type, and PAUSE timer - * registers to their default values. This is done even if flow - * control is disabled, because it does not hurt anything to - * initialize these registers. - */ - e_dbg("Initializing the Flow Control address, type and timer regs\n"); - - ew32(FCT, FLOW_CONTROL_TYPE); - ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH); - ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW); - - ew32(FCTTV, hw->fc_pause_time); - - /* Set the flow control receive threshold registers. Normally, - * these registers will be set to a default threshold that may be - * adjusted later by the driver's runtime code. However, if the - * ability to transmit pause frames in not enabled, then these - * registers will be set to 0. - */ - if (!(hw->fc & E1000_FC_TX_PAUSE)) { - ew32(FCRTL, 0); - ew32(FCRTH, 0); - } else { - /* We need to set up the Receive Threshold high and low water - * marks as well as (optionally) enabling the transmission of - * XON frames. - */ - if (hw->fc_send_xon) { - ew32(FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE)); - ew32(FCRTH, hw->fc_high_water); - } else { - ew32(FCRTL, hw->fc_low_water); - ew32(FCRTH, hw->fc_high_water); - } - } - return ret_val; -} - -/** - * e1000_setup_fiber_serdes_link - prepare fiber or serdes link - * @hw: Struct containing variables accessed by shared code - * - * Manipulates Physical Coding Sublayer functions in order to configure - * link. Assumes the hardware has been previously reset and the transmitter - * and receiver are not enabled. - */ -static s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw) -{ - u32 ctrl; - u32 status; - u32 txcw = 0; - u32 i; - u32 signal = 0; - s32 ret_val; - - /* On adapters with a MAC newer than 82544, SWDP 1 will be - * set when the optics detect a signal. On older adapters, it will be - * cleared when there is a signal. This applies to fiber media only. - * If we're on serdes media, adjust the output amplitude to value - * set in the EEPROM. - */ - ctrl = er32(CTRL); - if (hw->media_type == e1000_media_type_fiber) - signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; - - ret_val = e1000_adjust_serdes_amplitude(hw); - if (ret_val) - return ret_val; - - /* Take the link out of reset */ - ctrl &= ~(E1000_CTRL_LRST); - - /* Adjust VCO speed to improve BER performance */ - ret_val = e1000_set_vco_speed(hw); - if (ret_val) - return ret_val; - - e1000_config_collision_dist(hw); - - /* Check for a software override of the flow control settings, and setup - * the device accordingly. If auto-negotiation is enabled, then - * software will have to set the "PAUSE" bits to the correct value in - * the Tranmsit Config Word Register (TXCW) and re-start - * auto-negotiation. However, if auto-negotiation is disabled, then - * software will have to manually configure the two flow control enable - * bits in the CTRL register. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames, but - * not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but we do - * not support receiving pause frames). - * 3: Both Rx and TX flow control (symmetric) are enabled. - */ - switch (hw->fc) { - case E1000_FC_NONE: - /* Flow ctrl is completely disabled by a software over-ride */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); - break; - case E1000_FC_RX_PAUSE: - /* Rx Flow control is enabled and Tx Flow control is disabled by - * a software over-ride. Since there really isn't a way to - * advertise that we are capable of Rx Pause ONLY, we will - * advertise that we support both symmetric and asymmetric Rx - * PAUSE. Later, we will disable the adapter's ability to send - * PAUSE frames. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - case E1000_FC_TX_PAUSE: - /* Tx Flow control is enabled, and Rx Flow control is disabled, - * by a software over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); - break; - case E1000_FC_FULL: - /* Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - } - - /* Since auto-negotiation is enabled, take the link out of reset (the - * link will be in reset, because we previously reset the chip). This - * will restart auto-negotiation. If auto-negotiation is successful - * then the link-up status bit will be set and the flow control enable - * bits (RFCE and TFCE) will be set according to their negotiated value. - */ - e_dbg("Auto-negotiation enabled\n"); - - ew32(TXCW, txcw); - ew32(CTRL, ctrl); - E1000_WRITE_FLUSH(); - - hw->txcw = txcw; - msleep(1); - - /* If we have a signal (the cable is plugged in) then poll for a - * "Link-Up" indication in the Device Status Register. Time-out if a - * link isn't seen in 500 milliseconds seconds (Auto-negotiation should - * complete in less than 500 milliseconds even if the other end is doing - * it in SW). For internal serdes, we just assume a signal is present, - * then poll. - */ - if (hw->media_type == e1000_media_type_internal_serdes || - (er32(CTRL) & E1000_CTRL_SWDPIN1) == signal) { - e_dbg("Looking for Link\n"); - for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) { - msleep(10); - status = er32(STATUS); - if (status & E1000_STATUS_LU) - break; - } - if (i == (LINK_UP_TIMEOUT / 10)) { - e_dbg("Never got a valid link from auto-neg!!!\n"); - hw->autoneg_failed = 1; - /* AutoNeg failed to achieve a link, so we'll call - * e1000_check_for_link. This routine will force the - * link up if we detect a signal. This will allow us to - * communicate with non-autonegotiating link partners. - */ - ret_val = e1000_check_for_link(hw); - if (ret_val) { - e_dbg("Error while checking for link\n"); - return ret_val; - } - hw->autoneg_failed = 0; - } else { - hw->autoneg_failed = 0; - e_dbg("Valid Link Found\n"); - } - } else { - e_dbg("No Signal Detected\n"); - } - return E1000_SUCCESS; -} - -/** - * e1000_copper_link_rtl_setup - Copper link setup for e1000_phy_rtl series. - * @hw: Struct containing variables accessed by shared code - * - * Commits changes to PHY configuration by calling e1000_phy_reset(). - */ -static s32 e1000_copper_link_rtl_setup(struct e1000_hw *hw) -{ - s32 ret_val; - - /* SW reset the PHY so all changes take effect */ - ret_val = e1000_phy_reset(hw); - if (ret_val) { - e_dbg("Error Resetting the PHY\n"); - return ret_val; - } - - return E1000_SUCCESS; -} - -static s32 gbe_dhg_phy_setup(struct e1000_hw *hw) -{ - s32 ret_val; - u32 ctrl_aux; - - switch (hw->phy_type) { - case e1000_phy_8211: - ret_val = e1000_copper_link_rtl_setup(hw); - if (ret_val) { - e_dbg("e1000_copper_link_rtl_setup failed!\n"); - return ret_val; - } - break; - case e1000_phy_8201: - /* Set RMII mode */ - ctrl_aux = er32(CTL_AUX); - ctrl_aux |= E1000_CTL_AUX_RMII; - ew32(CTL_AUX, ctrl_aux); - E1000_WRITE_FLUSH(); - - /* Disable the J/K bits required for receive */ - ctrl_aux = er32(CTL_AUX); - ctrl_aux |= 0x4; - ctrl_aux &= ~0x2; - ew32(CTL_AUX, ctrl_aux); - E1000_WRITE_FLUSH(); - ret_val = e1000_copper_link_rtl_setup(hw); - - if (ret_val) { - e_dbg("e1000_copper_link_rtl_setup failed!\n"); - return ret_val; - } - break; - default: - e_dbg("Error Resetting the PHY\n"); - return E1000_ERR_PHY_TYPE; - } - - return E1000_SUCCESS; -} - -/** - * e1000_copper_link_preconfig - early configuration for copper - * @hw: Struct containing variables accessed by shared code - * - * Make sure we have a valid PHY and change PHY mode before link setup. - */ -static s32 e1000_copper_link_preconfig(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 phy_data; - - ctrl = er32(CTRL); - /* With 82543, we need to force speed and duplex on the MAC equal to - * what the PHY speed and duplex configuration is. In addition, we need - * to perform a hardware reset on the PHY to take it out of reset. - */ - if (hw->mac_type > e1000_82543) { - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ew32(CTRL, ctrl); - } else { - ctrl |= - (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU); - ew32(CTRL, ctrl); - ret_val = e1000_phy_hw_reset(hw); - if (ret_val) - return ret_val; - } - - /* Make sure we have a valid PHY */ - ret_val = e1000_detect_gig_phy(hw); - if (ret_val) { - e_dbg("Error, did not detect valid phy.\n"); - return ret_val; - } - e_dbg("Phy ID = %x\n", hw->phy_id); - - /* Set PHY to class A mode (if necessary) */ - ret_val = e1000_set_phy_mode(hw); - if (ret_val) - return ret_val; - - if ((hw->mac_type == e1000_82545_rev_3) || - (hw->mac_type == e1000_82546_rev_3)) { - ret_val = - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - phy_data |= 0x00000008; - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - } - - if (hw->mac_type <= e1000_82543 || - hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 || - hw->mac_type == e1000_82541_rev_2 - || hw->mac_type == e1000_82547_rev_2) - hw->phy_reset_disable = false; - - return E1000_SUCCESS; -} - -/** - * e1000_copper_link_igp_setup - Copper link setup for e1000_phy_igp series. - * @hw: Struct containing variables accessed by shared code - */ -static s32 e1000_copper_link_igp_setup(struct e1000_hw *hw) -{ - u32 led_ctrl; - s32 ret_val; - u16 phy_data; - - if (hw->phy_reset_disable) - return E1000_SUCCESS; - - ret_val = e1000_phy_reset(hw); - if (ret_val) { - e_dbg("Error Resetting the PHY\n"); - return ret_val; - } - - /* Wait 15ms for MAC to configure PHY from eeprom settings */ - msleep(15); - /* Configure activity LED after PHY reset */ - led_ctrl = er32(LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - ew32(LEDCTL, led_ctrl); - - /* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */ - if (hw->phy_type == e1000_phy_igp) { - /* disable lplu d3 during driver init */ - ret_val = e1000_set_d3_lplu_state(hw, false); - if (ret_val) { - e_dbg("Error Disabling LPLU D3\n"); - return ret_val; - } - } - - /* Configure mdi-mdix settings */ - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); - if (ret_val) - return ret_val; - - if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - hw->dsp_config_state = e1000_dsp_config_disabled; - /* Force MDI for earlier revs of the IGP PHY */ - phy_data &= - ~(IGP01E1000_PSCR_AUTO_MDIX | - IGP01E1000_PSCR_FORCE_MDI_MDIX); - hw->mdix = 1; - - } else { - hw->dsp_config_state = e1000_dsp_config_enabled; - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - - switch (hw->mdix) { - case 1: - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 2: - phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 0: - default: - phy_data |= IGP01E1000_PSCR_AUTO_MDIX; - break; - } - } - ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); - if (ret_val) - return ret_val; - - /* set auto-master slave resolution settings */ - if (hw->autoneg) { - e1000_ms_type phy_ms_setting = hw->master_slave; - - if (hw->ffe_config_state == e1000_ffe_config_active) - hw->ffe_config_state = e1000_ffe_config_enabled; - - if (hw->dsp_config_state == e1000_dsp_config_activated) - hw->dsp_config_state = e1000_dsp_config_enabled; - - /* when autonegotiation advertisement is only 1000Mbps then we - * should disable SmartSpeed and enable Auto MasterSlave - * resolution as hardware default. - */ - if (hw->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data); - if (ret_val) - return ret_val; - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - phy_data); - if (ret_val) - return ret_val; - /* Set auto Master/Slave resolution process */ - ret_val = - e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data); - if (ret_val) - return ret_val; - phy_data &= ~CR_1000T_MS_ENABLE; - ret_val = - e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); - if (ret_val) - return ret_val; - } - - ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data); - if (ret_val) - return ret_val; - - /* load defaults for future use */ - hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ? - ((phy_data & CR_1000T_MS_VALUE) ? - e1000_ms_force_master : - e1000_ms_force_slave) : e1000_ms_auto; - - switch (phy_ms_setting) { - case e1000_ms_force_master: - phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); - break; - case e1000_ms_force_slave: - phy_data |= CR_1000T_MS_ENABLE; - phy_data &= ~(CR_1000T_MS_VALUE); - break; - case e1000_ms_auto: - phy_data &= ~CR_1000T_MS_ENABLE; - default: - break; - } - ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); - if (ret_val) - return ret_val; - } - - return E1000_SUCCESS; -} - -/** - * e1000_copper_link_mgp_setup - Copper link setup for e1000_phy_m88 series. - * @hw: Struct containing variables accessed by shared code - */ -static s32 e1000_copper_link_mgp_setup(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - - if (hw->phy_reset_disable) - return E1000_SUCCESS; - - /* Enable CRS on TX. This must be set for half-duplex operation. */ - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - - /* Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - - switch (hw->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } - - /* Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if (hw->disable_polarity_correction == 1) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - if (hw->phy_revision < M88E1011_I_REV_4) { - /* Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - ret_val = - e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_EPSCR_TX_CLK_25; - - if ((hw->phy_revision == E1000_REVISION_2) && - (hw->phy_id == M88E1111_I_PHY_ID)) { - /* Vidalia Phy, set the downshift counter to 5x */ - phy_data &= ~(M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK); - phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; - ret_val = e1000_write_phy_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, - phy_data); - if (ret_val) - return ret_val; - } else { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - ret_val = e1000_write_phy_reg(hw, - M88E1000_EXT_PHY_SPEC_CTRL, - phy_data); - if (ret_val) - return ret_val; - } - } - - /* SW Reset the PHY so all changes take effect */ - ret_val = e1000_phy_reset(hw); - if (ret_val) { - e_dbg("Error Resetting the PHY\n"); - return ret_val; - } - - return E1000_SUCCESS; -} - -/** - * e1000_copper_link_autoneg - setup auto-neg - * @hw: Struct containing variables accessed by shared code - * - * Setup auto-negotiation and flow control advertisements, - * and then perform auto-negotiation. - */ -static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - - /* Perform some bounds checking on the hw->autoneg_advertised - * parameter. If this variable is zero, then set it to the default. - */ - hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT; - - /* If autoneg_advertised is zero, we assume it was not defaulted - * by the calling code so we set to advertise full capability. - */ - if (hw->autoneg_advertised == 0) - hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; - - /* IFE/RTL8201N PHY only supports 10/100 */ - if (hw->phy_type == e1000_phy_8201) - hw->autoneg_advertised &= AUTONEG_ADVERTISE_10_100_ALL; - - e_dbg("Reconfiguring auto-neg advertisement params\n"); - ret_val = e1000_phy_setup_autoneg(hw); - if (ret_val) { - e_dbg("Error Setting up Auto-Negotiation\n"); - return ret_val; - } - e_dbg("Restarting Auto-Neg\n"); - - /* Restart auto-negotiation by setting the Auto Neg Enable bit and - * the Auto Neg Restart bit in the PHY control register. - */ - ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); - ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data); - if (ret_val) - return ret_val; - - /* Does the user want to wait for Auto-Neg to complete here, or - * check at a later time (for example, callback routine). - */ - if (hw->wait_autoneg_complete) { - ret_val = e1000_wait_autoneg(hw); - if (ret_val) { - e_dbg - ("Error while waiting for autoneg to complete\n"); - return ret_val; - } - } - - hw->get_link_status = true; - - return E1000_SUCCESS; -} - -/** - * e1000_copper_link_postconfig - post link setup - * @hw: Struct containing variables accessed by shared code - * - * Config the MAC and the PHY after link is up. - * 1) Set up the MAC to the current PHY speed/duplex - * if we are on 82543. If we - * are on newer silicon, we only need to configure - * collision distance in the Transmit Control Register. - * 2) Set up flow control on the MAC to that established with - * the link partner. - * 3) Config DSP to improve Gigabit link quality for some PHY revisions. - */ -static s32 e1000_copper_link_postconfig(struct e1000_hw *hw) -{ - s32 ret_val; - - if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100)) { - e1000_config_collision_dist(hw); - } else { - ret_val = e1000_config_mac_to_phy(hw); - if (ret_val) { - e_dbg("Error configuring MAC to PHY settings\n"); - return ret_val; - } - } - ret_val = e1000_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error Configuring Flow Control\n"); - return ret_val; - } - - /* Config DSP to improve Giga link quality */ - if (hw->phy_type == e1000_phy_igp) { - ret_val = e1000_config_dsp_after_link_change(hw, true); - if (ret_val) { - e_dbg("Error Configuring DSP after link up\n"); - return ret_val; - } - } - - return E1000_SUCCESS; -} - -/** - * e1000_setup_copper_link - phy/speed/duplex setting - * @hw: Struct containing variables accessed by shared code - * - * Detects which PHY is present and sets up the speed and duplex - */ -static s32 e1000_setup_copper_link(struct e1000_hw *hw) -{ - s32 ret_val; - u16 i; - u16 phy_data; - - /* Check if it is a valid PHY and set PHY mode if necessary. */ - ret_val = e1000_copper_link_preconfig(hw); - if (ret_val) - return ret_val; - - if (hw->phy_type == e1000_phy_igp) { - ret_val = e1000_copper_link_igp_setup(hw); - if (ret_val) - return ret_val; - } else if (hw->phy_type == e1000_phy_m88) { - ret_val = e1000_copper_link_mgp_setup(hw); - if (ret_val) - return ret_val; - } else { - ret_val = gbe_dhg_phy_setup(hw); - if (ret_val) { - e_dbg("gbe_dhg_phy_setup failed!\n"); - return ret_val; - } - } - - if (hw->autoneg) { - /* Setup autoneg and flow control advertisement - * and perform autonegotiation - */ - ret_val = e1000_copper_link_autoneg(hw); - if (ret_val) - return ret_val; - } else { - /* PHY will be set to 10H, 10F, 100H,or 100F - * depending on value from forced_speed_duplex. - */ - e_dbg("Forcing speed and duplex\n"); - ret_val = e1000_phy_force_speed_duplex(hw); - if (ret_val) { - e_dbg("Error Forcing Speed and Duplex\n"); - return ret_val; - } - } - - /* Check link status. Wait up to 100 microseconds for link to become - * valid. - */ - for (i = 0; i < 10; i++) { - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - - if (phy_data & MII_SR_LINK_STATUS) { - /* Config the MAC and PHY after link is up */ - ret_val = e1000_copper_link_postconfig(hw); - if (ret_val) - return ret_val; - - e_dbg("Valid link established!!!\n"); - return E1000_SUCCESS; - } - udelay(10); - } - - e_dbg("Unable to establish link!!!\n"); - return E1000_SUCCESS; -} - -/** - * e1000_phy_setup_autoneg - phy settings - * @hw: Struct containing variables accessed by shared code - * - * Configures PHY autoneg and flow control advertisement settings - */ -s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) -{ - s32 ret_val; - u16 mii_autoneg_adv_reg; - u16 mii_1000t_ctrl_reg; - - /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); - if (ret_val) - return ret_val; - - /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); - if (ret_val) - return ret_val; - else if (hw->phy_type == e1000_phy_8201) - mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK; - - /* Need to parse both autoneg_advertised and fc and set up - * the appropriate PHY registers. First we will parse for - * autoneg_advertised software override. Since we can advertise - * a plethora of combinations, we need to check each bit - * individually. - */ - - /* First we clear all the 10/100 mb speed bits in the Auto-Neg - * Advertisement Register (Address 4) and the 1000 mb speed bits in - * the 1000Base-T Control Register (Address 9). - */ - mii_autoneg_adv_reg &= ~REG4_SPEED_MASK; - mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK; - - e_dbg("autoneg_advertised %x\n", hw->autoneg_advertised); - - /* Do we want to advertise 10 Mb Half Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_10_HALF) { - e_dbg("Advertise 10mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; - } - - /* Do we want to advertise 10 Mb Full Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_10_FULL) { - e_dbg("Advertise 10mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; - } - - /* Do we want to advertise 100 Mb Half Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_100_HALF) { - e_dbg("Advertise 100mb Half duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; - } - - /* Do we want to advertise 100 Mb Full Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_100_FULL) { - e_dbg("Advertise 100mb Full duplex\n"); - mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; - } - - /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ - if (hw->autoneg_advertised & ADVERTISE_1000_HALF) { - e_dbg - ("Advertise 1000mb Half duplex requested, request denied!\n"); - } - - /* Do we want to advertise 1000 Mb Full Duplex? */ - if (hw->autoneg_advertised & ADVERTISE_1000_FULL) { - e_dbg("Advertise 1000mb Full duplex\n"); - mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; - } - - /* Check for a software override of the flow control settings, and - * setup the PHY advertisement registers accordingly. If - * auto-negotiation is enabled, then software will have to set the - * "PAUSE" bits to the correct value in the Auto-Negotiation - * Advertisement Register (PHY_AUTONEG_ADV) and re-start - * auto-negotiation. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * but we do not support receiving pause frames). - * 3: Both Rx and TX flow control (symmetric) are enabled. - * other: No software override. The flow control configuration - * in the EEPROM is used. - */ - switch (hw->fc) { - case E1000_FC_NONE: /* 0 */ - /* Flow control (RX & TX) is completely disabled by a - * software over-ride. - */ - mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case E1000_FC_RX_PAUSE: /* 1 */ - /* RX Flow control is enabled, and TX Flow control is - * disabled, by a software over-ride. - */ - /* Since there really isn't a way to advertise that we are - * capable of RX Pause ONLY, we will advertise that we - * support both symmetric and asymmetric RX PAUSE. Later - * (in e1000_config_fc_after_link_up) we will disable the - * hw's ability to send PAUSE frames. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - case E1000_FC_TX_PAUSE: /* 2 */ - /* TX Flow control is enabled, and RX Flow control is - * disabled, by a software over-ride. - */ - mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; - mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; - break; - case E1000_FC_FULL: /* 3 */ - /* Flow control (both RX and TX) is enabled by a software - * over-ride. - */ - mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - } - - ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); - if (ret_val) - return ret_val; - - e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - - if (hw->phy_type == e1000_phy_8201) { - mii_1000t_ctrl_reg = 0; - } else { - ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, - mii_1000t_ctrl_reg); - if (ret_val) - return ret_val; - } - - return E1000_SUCCESS; -} - -/** - * e1000_phy_force_speed_duplex - force link settings - * @hw: Struct containing variables accessed by shared code - * - * Force PHY speed and duplex settings to hw->forced_speed_duplex - */ -static s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 mii_ctrl_reg; - u16 mii_status_reg; - u16 phy_data; - u16 i; - - /* Turn off Flow control if we are forcing speed and duplex. */ - hw->fc = E1000_FC_NONE; - - e_dbg("hw->fc = %d\n", hw->fc); - - /* Read the Device Control Register. */ - ctrl = er32(CTRL); - - /* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */ - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ctrl &= ~(DEVICE_SPEED_MASK); - - /* Clear the Auto Speed Detect Enable bit. */ - ctrl &= ~E1000_CTRL_ASDE; - - /* Read the MII Control Register. */ - ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg); - if (ret_val) - return ret_val; - - /* We need to disable autoneg in order to force link and duplex. */ - - mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN; - - /* Are we forcing Full or Half Duplex? */ - if (hw->forced_speed_duplex == e1000_100_full || - hw->forced_speed_duplex == e1000_10_full) { - /* We want to force full duplex so we SET the full duplex bits - * in the Device and MII Control Registers. - */ - ctrl |= E1000_CTRL_FD; - mii_ctrl_reg |= MII_CR_FULL_DUPLEX; - e_dbg("Full Duplex\n"); - } else { - /* We want to force half duplex so we CLEAR the full duplex bits - * in the Device and MII Control Registers. - */ - ctrl &= ~E1000_CTRL_FD; - mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX; - e_dbg("Half Duplex\n"); - } - - /* Are we forcing 100Mbps??? */ - if (hw->forced_speed_duplex == e1000_100_full || - hw->forced_speed_duplex == e1000_100_half) { - /* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */ - ctrl |= E1000_CTRL_SPD_100; - mii_ctrl_reg |= MII_CR_SPEED_100; - mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10); - e_dbg("Forcing 100mb "); - } else { - /* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */ - ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - mii_ctrl_reg |= MII_CR_SPEED_10; - mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); - e_dbg("Forcing 10mb "); - } - - e1000_config_collision_dist(hw); - - /* Write the configured values back to the Device Control Reg. */ - ew32(CTRL, ctrl); - - if (hw->phy_type == e1000_phy_m88) { - ret_val = - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - /* Clear Auto-Crossover to force MDI manually. M88E1000 requires - * MDI forced whenever speed are duplex are forced. - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - e_dbg("M88E1000 PSCR: %x\n", phy_data); - - /* Need to reset the PHY or these changes will be ignored */ - mii_ctrl_reg |= MII_CR_RESET; - - /* Disable MDI-X support for 10/100 */ - } else { - /* Clear Auto-Crossover to force MDI manually. IGP requires MDI - * forced whenever speed or duplex are forced. - */ - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); - if (ret_val) - return ret_val; - } - - /* Write back the modified PHY MII control register. */ - ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg); - if (ret_val) - return ret_val; - - udelay(1); - - /* The wait_autoneg_complete flag may be a little misleading here. - * Since we are forcing speed and duplex, Auto-Neg is not enabled. - * But we do want to delay for a period while forcing only so we - * don't generate false No Link messages. So we will wait here - * only if the user has set wait_autoneg_complete to 1, which is - * the default. - */ - if (hw->wait_autoneg_complete) { - /* We will wait for autoneg to complete. */ - e_dbg("Waiting for forced speed/duplex link.\n"); - mii_status_reg = 0; - - /* Wait for autoneg to complete or 4.5 seconds to expire */ - for (i = PHY_FORCE_TIME; i > 0; i--) { - /* Read the MII Status Register and wait for Auto-Neg - * Complete bit to be set. - */ - ret_val = - e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - ret_val = - e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - if (mii_status_reg & MII_SR_LINK_STATUS) - break; - msleep(100); - } - if ((i == 0) && (hw->phy_type == e1000_phy_m88)) { - /* We didn't get link. Reset the DSP and wait again - * for link. - */ - ret_val = e1000_phy_reset_dsp(hw); - if (ret_val) { - e_dbg("Error Resetting PHY DSP\n"); - return ret_val; - } - } - /* This loop will early-out if the link condition has been - * met - */ - for (i = PHY_FORCE_TIME; i > 0; i--) { - if (mii_status_reg & MII_SR_LINK_STATUS) - break; - msleep(100); - /* Read the MII Status Register and wait for Auto-Neg - * Complete bit to be set. - */ - ret_val = - e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - ret_val = - e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - } - } - - if (hw->phy_type == e1000_phy_m88) { - /* Because we reset the PHY above, we need to re-force TX_CLK in - * the Extended PHY Specific Control Register to 25MHz clock. - * This value defaults back to a 2.5MHz clock when the PHY is - * reset. - */ - ret_val = - e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_EPSCR_TX_CLK_25; - ret_val = - e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, - phy_data); - if (ret_val) - return ret_val; - - /* In addition, because of the s/w reset above, we need to - * enable CRS on Tx. This must be set for both full and half - * duplex operation. - */ - ret_val = - e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - if ((hw->mac_type == e1000_82544 || hw->mac_type == e1000_82543) - && (!hw->autoneg) - && (hw->forced_speed_duplex == e1000_10_full - || hw->forced_speed_duplex == e1000_10_half)) { - ret_val = e1000_polarity_reversal_workaround(hw); - if (ret_val) - return ret_val; - } - } - return E1000_SUCCESS; -} - -/** - * e1000_config_collision_dist - set collision distance register - * @hw: Struct containing variables accessed by shared code - * - * Sets the collision distance in the Transmit Control register. - * Link should have been established previously. Reads the speed and duplex - * information from the Device Status register. - */ -void e1000_config_collision_dist(struct e1000_hw *hw) -{ - u32 tctl, coll_dist; - - if (hw->mac_type < e1000_82543) - coll_dist = E1000_COLLISION_DISTANCE_82542; - else - coll_dist = E1000_COLLISION_DISTANCE; - - tctl = er32(TCTL); - - tctl &= ~E1000_TCTL_COLD; - tctl |= coll_dist << E1000_COLD_SHIFT; - - ew32(TCTL, tctl); - E1000_WRITE_FLUSH(); -} - -/** - * e1000_config_mac_to_phy - sync phy and mac settings - * @hw: Struct containing variables accessed by shared code - * @mii_reg: data to write to the MII control register - * - * Sets MAC speed and duplex settings to reflect the those in the PHY - * The contents of the PHY register containing the needed information need to - * be passed in. - */ -static s32 e1000_config_mac_to_phy(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 phy_data; - - /* 82544 or newer MAC, Auto Speed Detection takes care of - * MAC speed/duplex configuration. - */ - if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100)) - return E1000_SUCCESS; - - /* Read the Device Control Register and set the bits to Force Speed - * and Duplex. - */ - ctrl = er32(CTRL); - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS); - - switch (hw->phy_type) { - case e1000_phy_8201: - ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data); - if (ret_val) - return ret_val; - - if (phy_data & RTL_PHY_CTRL_FD) - ctrl |= E1000_CTRL_FD; - else - ctrl &= ~E1000_CTRL_FD; - - if (phy_data & RTL_PHY_CTRL_SPD_100) - ctrl |= E1000_CTRL_SPD_100; - else - ctrl |= E1000_CTRL_SPD_10; - - e1000_config_collision_dist(hw); - break; - default: - /* Set up duplex in the Device Control and Transmit Control - * registers depending on negotiated values. - */ - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data); - if (ret_val) - return ret_val; - - if (phy_data & M88E1000_PSSR_DPLX) - ctrl |= E1000_CTRL_FD; - else - ctrl &= ~E1000_CTRL_FD; - - e1000_config_collision_dist(hw); - - /* Set up speed in the Device Control register depending on - * negotiated values. - */ - if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) - ctrl |= E1000_CTRL_SPD_1000; - else if ((phy_data & M88E1000_PSSR_SPEED) == - M88E1000_PSSR_100MBS) - ctrl |= E1000_CTRL_SPD_100; - } - - /* Write the configured values back to the Device Control Reg. */ - ew32(CTRL, ctrl); - return E1000_SUCCESS; -} - -/** - * e1000_force_mac_fc - force flow control settings - * @hw: Struct containing variables accessed by shared code - * - * Forces the MAC's flow control settings. - * Sets the TFCE and RFCE bits in the device control register to reflect - * the adapter settings. TFCE and RFCE need to be explicitly set by - * software when a Copper PHY is used because autonegotiation is managed - * by the PHY rather than the MAC. Software must also configure these - * bits when link is forced on a fiber connection. - */ -s32 e1000_force_mac_fc(struct e1000_hw *hw) -{ - u32 ctrl; - - /* Get the current configuration of the Device Control Register */ - ctrl = er32(CTRL); - - /* Because we didn't get link via the internal auto-negotiation - * mechanism (we either forced link or we got link via PHY - * auto-neg), we have to manually enable/disable transmit an - * receive flow control. - * - * The "Case" statement below enables/disable flow control - * according to the "hw->fc" parameter. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause - * frames but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * frames but we do not receive pause frames). - * 3: Both Rx and TX flow control (symmetric) is enabled. - * other: No other values should be possible at this point. - */ - - switch (hw->fc) { - case E1000_FC_NONE: - ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); - break; - case E1000_FC_RX_PAUSE: - ctrl &= (~E1000_CTRL_TFCE); - ctrl |= E1000_CTRL_RFCE; - break; - case E1000_FC_TX_PAUSE: - ctrl &= (~E1000_CTRL_RFCE); - ctrl |= E1000_CTRL_TFCE; - break; - case E1000_FC_FULL: - ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - } - - /* Disable TX Flow Control for 82542 (rev 2.0) */ - if (hw->mac_type == e1000_82542_rev2_0) - ctrl &= (~E1000_CTRL_TFCE); - - ew32(CTRL, ctrl); - return E1000_SUCCESS; -} - -/** - * e1000_config_fc_after_link_up - configure flow control after autoneg - * @hw: Struct containing variables accessed by shared code - * - * Configures flow control settings after link is established - * Should be called immediately after a valid link has been established. - * Forces MAC flow control settings if link was forced. When in MII/GMII mode - * and autonegotiation is enabled, the MAC flow control settings will be set - * based on the flow control negotiated by the PHY. In TBI mode, the TFCE - * and RFCE bits will be automatically set to the negotiated flow control mode. - */ -static s32 e1000_config_fc_after_link_up(struct e1000_hw *hw) -{ - s32 ret_val; - u16 mii_status_reg; - u16 mii_nway_adv_reg; - u16 mii_nway_lp_ability_reg; - u16 speed; - u16 duplex; - - /* Check for the case where we have fiber media and auto-neg failed - * so we had to force link. In this case, we need to force the - * configuration of the MAC to match the "fc" parameter. - */ - if (((hw->media_type == e1000_media_type_fiber) && (hw->autoneg_failed)) - || ((hw->media_type == e1000_media_type_internal_serdes) - && (hw->autoneg_failed)) - || ((hw->media_type == e1000_media_type_copper) - && (!hw->autoneg))) { - ret_val = e1000_force_mac_fc(hw); - if (ret_val) { - e_dbg("Error forcing flow control settings\n"); - return ret_val; - } - } - - /* Check for the case where we have copper media and auto-neg is - * enabled. In this case, we need to check and see if Auto-Neg - * has completed, and if so, how the PHY and link partner has - * flow control configured. - */ - if ((hw->media_type == e1000_media_type_copper) && hw->autoneg) { - /* Read the MII Status Register and check to see if AutoNeg - * has completed. We read this twice because this reg has - * some "sticky" (latched) bits. - */ - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - if (mii_status_reg & MII_SR_AUTONEG_COMPLETE) { - /* The AutoNeg process has completed, so we now need to - * read both the Auto Negotiation Advertisement Register - * (Address 4) and the Auto_Negotiation Base Page - * Ability Register (Address 5) to determine how flow - * control was negotiated. - */ - ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, - &mii_nway_adv_reg); - if (ret_val) - return ret_val; - ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, - &mii_nway_lp_ability_reg); - if (ret_val) - return ret_val; - - /* Two bits in the Auto Negotiation Advertisement - * Register (Address 4) and two bits in the Auto - * Negotiation Base Page Ability Register (Address 5) - * determine flow control for both the PHY and the link - * partner. The following table, taken out of the IEEE - * 802.3ab/D6.0 dated March 25, 1999, describes these - * PAUSE resolution bits and how flow control is - * determined based upon these settings. - * NOTE: DC = Don't Care - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution - *-------|---------|-------|---------|------------------ - * 0 | 0 | DC | DC | E1000_FC_NONE - * 0 | 1 | 0 | DC | E1000_FC_NONE - * 0 | 1 | 1 | 0 | E1000_FC_NONE - * 0 | 1 | 1 | 1 | E1000_FC_TX_PAUSE - * 1 | 0 | 0 | DC | E1000_FC_NONE - * 1 | DC | 1 | DC | E1000_FC_FULL - * 1 | 1 | 0 | 0 | E1000_FC_NONE - * 1 | 1 | 0 | 1 | E1000_FC_RX_PAUSE - * - */ - /* Are both PAUSE bits set to 1? If so, this implies - * Symmetric Flow Control is enabled at both ends. The - * ASM_DIR bits are irrelevant per the spec. - * - * For Symmetric Flow Control: - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|------------------ - * 1 | DC | 1 | DC | E1000_FC_FULL - * - */ - if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { - /* Now we need to check if the user selected Rx - * ONLY of pause frames. In this case, we had - * to advertise FULL flow control because we - * could not advertise Rx ONLY. Hence, we must - * now check to see if we need to turn OFF the - * TRANSMISSION of PAUSE frames. - */ - if (hw->original_fc == E1000_FC_FULL) { - hw->fc = E1000_FC_FULL; - e_dbg("Flow Control = FULL.\n"); - } else { - hw->fc = E1000_FC_RX_PAUSE; - e_dbg - ("Flow Control = RX PAUSE frames only.\n"); - } - } - /* For receiving PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|------------------ - * 0 | 1 | 1 | 1 | E1000_FC_TX_PAUSE - * - */ - else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) - { - hw->fc = E1000_FC_TX_PAUSE; - e_dbg - ("Flow Control = TX PAUSE frames only.\n"); - } - /* For transmitting PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|------------------ - * 1 | 1 | 0 | 1 | E1000_FC_RX_PAUSE - * - */ - else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && - (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && - !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && - (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) - { - hw->fc = E1000_FC_RX_PAUSE; - e_dbg - ("Flow Control = RX PAUSE frames only.\n"); - } - /* Per the IEEE spec, at this point flow control should - * be disabled. However, we want to consider that we - * could be connected to a legacy switch that doesn't - * advertise desired flow control, but can be forced on - * the link partner. So if we advertised no flow - * control, that is what we will resolve to. If we - * advertised some kind of receive capability (Rx Pause - * Only or Full Flow Control) and the link partner - * advertised none, we will configure ourselves to - * enable Rx Flow Control only. We can do this safely - * for two reasons: If the link partner really - * didn't want flow control enabled, and we enable Rx, - * no harm done since we won't be receiving any PAUSE - * frames anyway. If the intent on the link partner was - * to have flow control enabled, then by us enabling Rx - * only, we can at least receive pause frames and - * process them. This is a good idea because in most - * cases, since we are predominantly a server NIC, more - * times than not we will be asked to delay transmission - * of packets than asking our link partner to pause - * transmission of frames. - */ - else if ((hw->original_fc == E1000_FC_NONE || - hw->original_fc == E1000_FC_TX_PAUSE) || - hw->fc_strict_ieee) { - hw->fc = E1000_FC_NONE; - e_dbg("Flow Control = NONE.\n"); - } else { - hw->fc = E1000_FC_RX_PAUSE; - e_dbg - ("Flow Control = RX PAUSE frames only.\n"); - } - - /* Now we need to do one last check... If we auto- - * negotiated to HALF DUPLEX, flow control should not be - * enabled per IEEE 802.3 spec. - */ - ret_val = - e1000_get_speed_and_duplex(hw, &speed, &duplex); - if (ret_val) { - e_dbg - ("Error getting link speed and duplex\n"); - return ret_val; - } - - if (duplex == HALF_DUPLEX) - hw->fc = E1000_FC_NONE; - - /* Now we call a subroutine to actually force the MAC - * controller to use the correct flow control settings. - */ - ret_val = e1000_force_mac_fc(hw); - if (ret_val) { - e_dbg - ("Error forcing flow control settings\n"); - return ret_val; - } - } else { - e_dbg - ("Copper PHY and Auto Neg has not completed.\n"); - } - } - return E1000_SUCCESS; -} - -/** - * e1000_check_for_serdes_link_generic - Check for link (Serdes) - * @hw: pointer to the HW structure - * - * Checks for link up on the hardware. If link is not up and we have - * a signal, then we need to force link up. - */ -static s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) -{ - u32 rxcw; - u32 ctrl; - u32 status; - s32 ret_val = E1000_SUCCESS; - - ctrl = er32(CTRL); - status = er32(STATUS); - rxcw = er32(RXCW); - - /* If we don't have link (auto-negotiation failed or link partner - * cannot auto-negotiate), and our link partner is not trying to - * auto-negotiate with us (we are receiving idles or data), - * we need to force link up. We also need to give auto-negotiation - * time to complete. - */ - /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) { - if (hw->autoneg_failed == 0) { - hw->autoneg_failed = 1; - goto out; - } - e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n"); - - /* Disable auto-negotiation in the TXCW register */ - ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = er32(CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - ew32(CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - ret_val = e1000_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error configuring flow control\n"); - goto out; - } - } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* If we are forcing link and we are receiving /C/ ordered - * sets, re-enable auto-negotiation in the TXCW register - * and disable forced link in the Device Control register - * in an attempt to auto-negotiate with our link partner. - */ - e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n"); - ew32(TXCW, hw->txcw); - ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - - hw->serdes_has_link = true; - } else if (!(E1000_TXCW_ANE & er32(TXCW))) { - /* If we force link for non-auto-negotiation switch, check - * link status based on MAC synchronization for internal - * serdes media type. - */ - /* SYNCH bit and IV bit are sticky. */ - udelay(10); - rxcw = er32(RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - hw->serdes_has_link = true; - e_dbg("SERDES: Link up - forced.\n"); - } - } else { - hw->serdes_has_link = false; - e_dbg("SERDES: Link down - force failed.\n"); - } - } - - if (E1000_TXCW_ANE & er32(TXCW)) { - status = er32(STATUS); - if (status & E1000_STATUS_LU) { - /* SYNCH bit and IV bit are sticky, so reread rxcw. */ - udelay(10); - rxcw = er32(RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - hw->serdes_has_link = true; - e_dbg("SERDES: Link up - autoneg " - "completed successfully.\n"); - } else { - hw->serdes_has_link = false; - e_dbg("SERDES: Link down - invalid" - "codewords detected in autoneg.\n"); - } - } else { - hw->serdes_has_link = false; - e_dbg("SERDES: Link down - no sync.\n"); - } - } else { - hw->serdes_has_link = false; - e_dbg("SERDES: Link down - autoneg failed\n"); - } - } - - out: - return ret_val; -} - -/** - * e1000_check_for_link - * @hw: Struct containing variables accessed by shared code - * - * Checks to see if the link status of the hardware has changed. - * Called by any function that needs to check the link status of the adapter. - */ -s32 e1000_check_for_link(struct e1000_hw *hw) -{ - u32 rxcw = 0; - u32 ctrl; - u32 status; - u32 rctl; - u32 icr; - u32 signal = 0; - s32 ret_val; - u16 phy_data; - - ctrl = er32(CTRL); - status = er32(STATUS); - - /* On adapters with a MAC newer than 82544, SW Definable pin 1 will be - * set when the optics detect a signal. On older adapters, it will be - * cleared when there is a signal. This applies to fiber media only. - */ - if ((hw->media_type == e1000_media_type_fiber) || - (hw->media_type == e1000_media_type_internal_serdes)) { - rxcw = er32(RXCW); - - if (hw->media_type == e1000_media_type_fiber) { - signal = - (hw->mac_type > - e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; - if (status & E1000_STATUS_LU) - hw->get_link_status = false; - } - } - - /* If we have a copper PHY then we only want to go out to the PHY - * registers to see if Auto-Neg has completed and/or if our link - * status has changed. The get_link_status flag will be set if we - * receive a Link Status Change interrupt or we have Rx Sequence - * Errors. - */ - if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) { - /* First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * of the PHY. - * Read the register twice since the link bit is sticky. - */ - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - - if (phy_data & MII_SR_LINK_STATUS) { - hw->get_link_status = false; - /* Check if there was DownShift, must be checked - * immediately after link-up - */ - e1000_check_downshift(hw); - - /* If we are on 82544 or 82543 silicon and speed/duplex - * are forced to 10H or 10F, then we will implement the - * polarity reversal workaround. We disable interrupts - * first, and upon returning, place the devices - * interrupt state to its previous value except for the - * link status change interrupt which will - * happen due to the execution of this workaround. - */ - - if ((hw->mac_type == e1000_82544 - || hw->mac_type == e1000_82543) && (!hw->autoneg) - && (hw->forced_speed_duplex == e1000_10_full - || hw->forced_speed_duplex == e1000_10_half)) { - ew32(IMC, 0xffffffff); - ret_val = - e1000_polarity_reversal_workaround(hw); - icr = er32(ICR); - ew32(ICS, (icr & ~E1000_ICS_LSC)); - ew32(IMS, IMS_ENABLE_MASK); - } - - } else { - /* No link detected */ - e1000_config_dsp_after_link_change(hw, false); - return 0; - } - - /* If we are forcing speed/duplex, then we simply return since - * we have already determined whether we have link or not. - */ - if (!hw->autoneg) - return -E1000_ERR_CONFIG; - - /* optimize the dsp settings for the igp phy */ - e1000_config_dsp_after_link_change(hw, true); - - /* We have a M88E1000 PHY and Auto-Neg is enabled. If we - * have Si on board that is 82544 or newer, Auto - * Speed Detection takes care of MAC speed/duplex - * configuration. So we only need to configure Collision - * Distance in the MAC. Otherwise, we need to force - * speed/duplex on the MAC to the current PHY speed/duplex - * settings. - */ - if ((hw->mac_type >= e1000_82544) && - (hw->mac_type != e1000_ce4100)) - e1000_config_collision_dist(hw); - else { - ret_val = e1000_config_mac_to_phy(hw); - if (ret_val) { - e_dbg - ("Error configuring MAC to PHY settings\n"); - return ret_val; - } - } - - /* Configure Flow Control now that Auto-Neg has completed. - * First, we need to restore the desired flow control settings - * because we may have had to re-autoneg with a different link - * partner. - */ - ret_val = e1000_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error configuring flow control\n"); - return ret_val; - } - - /* At this point we know that we are on copper and we have - * auto-negotiated link. These are conditions for checking the - * link partner capability register. We use the link speed to - * determine if TBI compatibility needs to be turned on or off. - * If the link is not at gigabit speed, then TBI compatibility - * is not needed. If we are at gigabit speed, we turn on TBI - * compatibility. - */ - if (hw->tbi_compatibility_en) { - u16 speed, duplex; - ret_val = - e1000_get_speed_and_duplex(hw, &speed, &duplex); - if (ret_val) { - e_dbg - ("Error getting link speed and duplex\n"); - return ret_val; - } - if (speed != SPEED_1000) { - /* If link speed is not set to gigabit speed, we - * do not need to enable TBI compatibility. - */ - if (hw->tbi_compatibility_on) { - /* If we previously were in the mode, - * turn it off. - */ - rctl = er32(RCTL); - rctl &= ~E1000_RCTL_SBP; - ew32(RCTL, rctl); - hw->tbi_compatibility_on = false; - } - } else { - /* If TBI compatibility is was previously off, - * turn it on. For compatibility with a TBI link - * partner, we will store bad packets. Some - * frames have an additional byte on the end and - * will look like CRC errors to to the hardware. - */ - if (!hw->tbi_compatibility_on) { - hw->tbi_compatibility_on = true; - rctl = er32(RCTL); - rctl |= E1000_RCTL_SBP; - ew32(RCTL, rctl); - } - } - } - } - - if ((hw->media_type == e1000_media_type_fiber) || - (hw->media_type == e1000_media_type_internal_serdes)) - e1000_check_for_serdes_link_generic(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_get_speed_and_duplex - * @hw: Struct containing variables accessed by shared code - * @speed: Speed of the connection - * @duplex: Duplex setting of the connection - * - * Detects the current speed and duplex settings of the hardware. - */ -s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex) -{ - u32 status; - s32 ret_val; - u16 phy_data; - - if (hw->mac_type >= e1000_82543) { - status = er32(STATUS); - if (status & E1000_STATUS_SPEED_1000) { - *speed = SPEED_1000; - e_dbg("1000 Mbs, "); - } else if (status & E1000_STATUS_SPEED_100) { - *speed = SPEED_100; - e_dbg("100 Mbs, "); - } else { - *speed = SPEED_10; - e_dbg("10 Mbs, "); - } - - if (status & E1000_STATUS_FD) { - *duplex = FULL_DUPLEX; - e_dbg("Full Duplex\n"); - } else { - *duplex = HALF_DUPLEX; - e_dbg(" Half Duplex\n"); - } - } else { - e_dbg("1000 Mbs, Full Duplex\n"); - *speed = SPEED_1000; - *duplex = FULL_DUPLEX; - } - - /* IGP01 PHY may advertise full duplex operation after speed downgrade - * even if it is operating at half duplex. Here we set the duplex - * settings to match the duplex in the link partner's capabilities. - */ - if (hw->phy_type == e1000_phy_igp && hw->speed_downgraded) { - ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data); - if (ret_val) - return ret_val; - - if (!(phy_data & NWAY_ER_LP_NWAY_CAPS)) - *duplex = HALF_DUPLEX; - else { - ret_val = - e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data); - if (ret_val) - return ret_val; - if ((*speed == SPEED_100 - && !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) - || (*speed == SPEED_10 - && !(phy_data & NWAY_LPAR_10T_FD_CAPS))) - *duplex = HALF_DUPLEX; - } - } - - return E1000_SUCCESS; -} - -/** - * e1000_wait_autoneg - * @hw: Struct containing variables accessed by shared code - * - * Blocks until autoneg completes or times out (~4.5 seconds) - */ -static s32 e1000_wait_autoneg(struct e1000_hw *hw) -{ - s32 ret_val; - u16 i; - u16 phy_data; - - e_dbg("Waiting for Auto-Neg to complete.\n"); - - /* We will wait for autoneg to complete or 4.5 seconds to expire. */ - for (i = PHY_AUTO_NEG_TIME; i > 0; i--) { - /* Read the MII Status Register and wait for Auto-Neg - * Complete bit to be set. - */ - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - if (phy_data & MII_SR_AUTONEG_COMPLETE) { - return E1000_SUCCESS; - } - msleep(100); - } - return E1000_SUCCESS; -} - -/** - * e1000_raise_mdi_clk - Raises the Management Data Clock - * @hw: Struct containing variables accessed by shared code - * @ctrl: Device control register's current value - */ -static void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl) -{ - /* Raise the clock input to the Management Data Clock (by setting the - * MDC bit), and then delay 10 microseconds. - */ - ew32(CTRL, (*ctrl | E1000_CTRL_MDC)); - E1000_WRITE_FLUSH(); - udelay(10); -} - -/** - * e1000_lower_mdi_clk - Lowers the Management Data Clock - * @hw: Struct containing variables accessed by shared code - * @ctrl: Device control register's current value - */ -static void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl) -{ - /* Lower the clock input to the Management Data Clock (by clearing the - * MDC bit), and then delay 10 microseconds. - */ - ew32(CTRL, (*ctrl & ~E1000_CTRL_MDC)); - E1000_WRITE_FLUSH(); - udelay(10); -} - -/** - * e1000_shift_out_mdi_bits - Shifts data bits out to the PHY - * @hw: Struct containing variables accessed by shared code - * @data: Data to send out to the PHY - * @count: Number of bits to shift out - * - * Bits are shifted out in MSB to LSB order. - */ -static void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count) -{ - u32 ctrl; - u32 mask; - - /* We need to shift "count" number of bits out to the PHY. So, the value - * in the "data" parameter will be shifted out to the PHY one bit at a - * time. In order to do this, "data" must be broken down into bits. - */ - mask = 0x01; - mask <<= (count - 1); - - ctrl = er32(CTRL); - - /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */ - ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR); - - while (mask) { - /* A "1" is shifted out to the PHY by setting the MDIO bit to - * "1" and then raising and lowering the Management Data Clock. - * A "0" is shifted out to the PHY by setting the MDIO bit to - * "0" and then raising and lowering the clock. - */ - if (data & mask) - ctrl |= E1000_CTRL_MDIO; - else - ctrl &= ~E1000_CTRL_MDIO; - - ew32(CTRL, ctrl); - E1000_WRITE_FLUSH(); - - udelay(10); - - e1000_raise_mdi_clk(hw, &ctrl); - e1000_lower_mdi_clk(hw, &ctrl); - - mask = mask >> 1; - } -} - -/** - * e1000_shift_in_mdi_bits - Shifts data bits in from the PHY - * @hw: Struct containing variables accessed by shared code - * - * Bits are shifted in in MSB to LSB order. - */ -static u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw) -{ - u32 ctrl; - u16 data = 0; - u8 i; - - /* In order to read a register from the PHY, we need to shift in a total - * of 18 bits from the PHY. The first two bit (turnaround) times are - * used to avoid contention on the MDIO pin when a read operation is - * performed. These two bits are ignored by us and thrown away. Bits are - * "shifted in" by raising the input to the Management Data Clock - * (setting the MDC bit), and then reading the value of the MDIO bit. - */ - ctrl = er32(CTRL); - - /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as - * input. - */ - ctrl &= ~E1000_CTRL_MDIO_DIR; - ctrl &= ~E1000_CTRL_MDIO; - - ew32(CTRL, ctrl); - E1000_WRITE_FLUSH(); - - /* Raise and Lower the clock before reading in the data. This accounts - * for the turnaround bits. The first clock occurred when we clocked out - * the last bit of the Register Address. - */ - e1000_raise_mdi_clk(hw, &ctrl); - e1000_lower_mdi_clk(hw, &ctrl); - - for (data = 0, i = 0; i < 16; i++) { - data = data << 1; - e1000_raise_mdi_clk(hw, &ctrl); - ctrl = er32(CTRL); - /* Check to see if we shifted in a "1". */ - if (ctrl & E1000_CTRL_MDIO) - data |= 1; - e1000_lower_mdi_clk(hw, &ctrl); - } - - e1000_raise_mdi_clk(hw, &ctrl); - e1000_lower_mdi_clk(hw, &ctrl); - - return data; -} - - -/** - * e1000_read_phy_reg - read a phy register - * @hw: Struct containing variables accessed by shared code - * @reg_addr: address of the PHY register to read - * - * Reads the value from a PHY register, if the value is on a specific non zero - * page, sets the page first. - */ -s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data) -{ - u32 ret_val; - unsigned long flags; - - spin_lock_irqsave(&e1000_phy_lock, flags); - - if ((hw->phy_type == e1000_phy_igp) && - (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { - ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, - (u16) reg_addr); - if (ret_val) { - spin_unlock_irqrestore(&e1000_phy_lock, flags); - return ret_val; - } - } - - ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, - phy_data); - spin_unlock_irqrestore(&e1000_phy_lock, flags); - - return ret_val; -} - -static s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, - u16 *phy_data) -{ - u32 i; - u32 mdic = 0; - const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1; - - if (reg_addr > MAX_PHY_REG_ADDRESS) { - e_dbg("PHY Address %d is out of range\n", reg_addr); - return -E1000_ERR_PARAM; - } - - if (hw->mac_type > e1000_82543) { - /* Set up Op-code, Phy Address, and register address in the MDI - * Control register. The MAC will take care of interfacing with - * the PHY to retrieve the desired data. - */ - if (hw->mac_type == e1000_ce4100) { - mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | - (INTEL_CE_GBE_MDIC_OP_READ) | - (INTEL_CE_GBE_MDIC_GO)); - - writel(mdic, E1000_MDIO_CMD); - - /* Poll the ready bit to see if the MDI read - * completed - */ - for (i = 0; i < 64; i++) { - udelay(50); - mdic = readl(E1000_MDIO_CMD); - if (!(mdic & INTEL_CE_GBE_MDIC_GO)) - break; - } - - if (mdic & INTEL_CE_GBE_MDIC_GO) { - e_dbg("MDI Read did not complete\n"); - return -E1000_ERR_PHY; - } - - mdic = readl(E1000_MDIO_STS); - if (mdic & INTEL_CE_GBE_MDIC_READ_ERROR) { - e_dbg("MDI Read Error\n"); - return -E1000_ERR_PHY; - } - *phy_data = (u16) mdic; - } else { - mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_READ)); - - ew32(MDIC, mdic); - - /* Poll the ready bit to see if the MDI read - * completed - */ - for (i = 0; i < 64; i++) { - udelay(50); - mdic = er32(MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - e_dbg("MDI Read did not complete\n"); - return -E1000_ERR_PHY; - } - if (mdic & E1000_MDIC_ERROR) { - e_dbg("MDI Error\n"); - return -E1000_ERR_PHY; - } - *phy_data = (u16) mdic; - } - } else { - /* We must first send a preamble through the MDIO pin to signal - * the beginning of an MII instruction. This is done by sending - * 32 consecutive "1" bits. - */ - e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); - - /* Now combine the next few fields that are required for a read - * operation. We use this method instead of calling the - * e1000_shift_out_mdi_bits routine five different times. The - * format of a MII read instruction consists of a shift out of - * 14 bits and is defined as follows: - * - * followed by a shift in of 18 bits. This first two bits - * shifted in are TurnAround bits used to avoid contention on - * the MDIO pin when a READ operation is performed. These two - * bits are thrown away followed by a shift in of 16 bits which - * contains the desired data. - */ - mdic = ((reg_addr) | (phy_addr << 5) | - (PHY_OP_READ << 10) | (PHY_SOF << 12)); - - e1000_shift_out_mdi_bits(hw, mdic, 14); - - /* Now that we've shifted out the read command to the MII, we - * need to "shift in" the 16-bit value (18 total bits) of the - * requested PHY register address. - */ - *phy_data = e1000_shift_in_mdi_bits(hw); - } - return E1000_SUCCESS; -} - -/** - * e1000_write_phy_reg - write a phy register - * - * @hw: Struct containing variables accessed by shared code - * @reg_addr: address of the PHY register to write - * @data: data to write to the PHY - * - * Writes a value to a PHY register - */ -s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data) -{ - u32 ret_val; - unsigned long flags; - - spin_lock_irqsave(&e1000_phy_lock, flags); - - if ((hw->phy_type == e1000_phy_igp) && - (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { - ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, - (u16) reg_addr); - if (ret_val) { - spin_unlock_irqrestore(&e1000_phy_lock, flags); - return ret_val; - } - } - - ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, - phy_data); - spin_unlock_irqrestore(&e1000_phy_lock, flags); - - return ret_val; -} - -static s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, - u16 phy_data) -{ - u32 i; - u32 mdic = 0; - const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1; - - if (reg_addr > MAX_PHY_REG_ADDRESS) { - e_dbg("PHY Address %d is out of range\n", reg_addr); - return -E1000_ERR_PARAM; - } - - if (hw->mac_type > e1000_82543) { - /* Set up Op-code, Phy Address, register address, and data - * intended for the PHY register in the MDI Control register. - * The MAC will take care of interfacing with the PHY to send - * the desired data. - */ - if (hw->mac_type == e1000_ce4100) { - mdic = (((u32) phy_data) | - (reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | - (INTEL_CE_GBE_MDIC_OP_WRITE) | - (INTEL_CE_GBE_MDIC_GO)); - - writel(mdic, E1000_MDIO_CMD); - - /* Poll the ready bit to see if the MDI read - * completed - */ - for (i = 0; i < 640; i++) { - udelay(5); - mdic = readl(E1000_MDIO_CMD); - if (!(mdic & INTEL_CE_GBE_MDIC_GO)) - break; - } - if (mdic & INTEL_CE_GBE_MDIC_GO) { - e_dbg("MDI Write did not complete\n"); - return -E1000_ERR_PHY; - } - } else { - mdic = (((u32) phy_data) | - (reg_addr << E1000_MDIC_REG_SHIFT) | - (phy_addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_WRITE)); - - ew32(MDIC, mdic); - - /* Poll the ready bit to see if the MDI read - * completed - */ - for (i = 0; i < 641; i++) { - udelay(5); - mdic = er32(MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - e_dbg("MDI Write did not complete\n"); - return -E1000_ERR_PHY; - } - } - } else { - /* We'll need to use the SW defined pins to shift the write - * command out to the PHY. We first send a preamble to the PHY - * to signal the beginning of the MII instruction. This is done - * by sending 32 consecutive "1" bits. - */ - e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); - - /* Now combine the remaining required fields that will indicate - * a write operation. We use this method instead of calling the - * e1000_shift_out_mdi_bits routine for each field in the - * command. The format of a MII write instruction is as follows: - * . - */ - mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) | - (PHY_OP_WRITE << 12) | (PHY_SOF << 14)); - mdic <<= 16; - mdic |= (u32) phy_data; - - e1000_shift_out_mdi_bits(hw, mdic, 32); - } - - return E1000_SUCCESS; -} - -/** - * e1000_phy_hw_reset - reset the phy, hardware style - * @hw: Struct containing variables accessed by shared code - * - * Returns the PHY to the power-on reset state - */ -s32 e1000_phy_hw_reset(struct e1000_hw *hw) -{ - u32 ctrl, ctrl_ext; - u32 led_ctrl; - - e_dbg("Resetting Phy...\n"); - - if (hw->mac_type > e1000_82543) { - /* Read the device control register and assert the - * E1000_CTRL_PHY_RST bit. Then, take it out of reset. - * For e1000 hardware, we delay for 10ms between the assert - * and de-assert. - */ - ctrl = er32(CTRL); - ew32(CTRL, ctrl | E1000_CTRL_PHY_RST); - E1000_WRITE_FLUSH(); - - msleep(10); - - ew32(CTRL, ctrl); - E1000_WRITE_FLUSH(); - - } else { - /* Read the Extended Device Control Register, assert the - * PHY_RESET_DIR bit to put the PHY into reset. Then, take it - * out of reset. - */ - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR; - ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA; - ew32(CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(); - msleep(10); - ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA; - ew32(CTRL_EXT, ctrl_ext); - E1000_WRITE_FLUSH(); - } - udelay(150); - - if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { - /* Configure activity LED after PHY reset */ - led_ctrl = er32(LEDCTL); - led_ctrl &= IGP_ACTIVITY_LED_MASK; - led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); - ew32(LEDCTL, led_ctrl); - } - - /* Wait for FW to finish PHY configuration. */ - return e1000_get_phy_cfg_done(hw); -} - -/** - * e1000_phy_reset - reset the phy to commit settings - * @hw: Struct containing variables accessed by shared code - * - * Resets the PHY - * Sets bit 15 of the MII Control register - */ -s32 e1000_phy_reset(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - - switch (hw->phy_type) { - case e1000_phy_igp: - ret_val = e1000_phy_hw_reset(hw); - if (ret_val) - return ret_val; - break; - default: - ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= MII_CR_RESET; - ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data); - if (ret_val) - return ret_val; - - udelay(1); - break; - } - - if (hw->phy_type == e1000_phy_igp) - e1000_phy_init_script(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_detect_gig_phy - check the phy type - * @hw: Struct containing variables accessed by shared code - * - * Probes the expected PHY address for known PHY IDs - */ -static s32 e1000_detect_gig_phy(struct e1000_hw *hw) -{ - s32 phy_init_status, ret_val; - u16 phy_id_high, phy_id_low; - bool match = false; - - if (hw->phy_id != 0) - return E1000_SUCCESS; - - /* Read the PHY ID Registers to identify which PHY is onboard. */ - ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high); - if (ret_val) - return ret_val; - - hw->phy_id = (u32) (phy_id_high << 16); - udelay(20); - ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low); - if (ret_val) - return ret_val; - - hw->phy_id |= (u32) (phy_id_low & PHY_REVISION_MASK); - hw->phy_revision = (u32) phy_id_low & ~PHY_REVISION_MASK; - - switch (hw->mac_type) { - case e1000_82543: - if (hw->phy_id == M88E1000_E_PHY_ID) - match = true; - break; - case e1000_82544: - if (hw->phy_id == M88E1000_I_PHY_ID) - match = true; - break; - case e1000_82540: - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_82546_rev_3: - if (hw->phy_id == M88E1011_I_PHY_ID) - match = true; - break; - case e1000_ce4100: - if ((hw->phy_id == RTL8211B_PHY_ID) || - (hw->phy_id == RTL8201N_PHY_ID) || - (hw->phy_id == M88E1118_E_PHY_ID)) - match = true; - break; - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - if (hw->phy_id == IGP01E1000_I_PHY_ID) - match = true; - break; - default: - e_dbg("Invalid MAC type %d\n", hw->mac_type); - return -E1000_ERR_CONFIG; - } - phy_init_status = e1000_set_phy_type(hw); - - if ((match) && (phy_init_status == E1000_SUCCESS)) { - e_dbg("PHY ID 0x%X detected\n", hw->phy_id); - return E1000_SUCCESS; - } - e_dbg("Invalid PHY ID 0x%X\n", hw->phy_id); - return -E1000_ERR_PHY; -} - -/** - * e1000_phy_reset_dsp - reset DSP - * @hw: Struct containing variables accessed by shared code - * - * Resets the PHY's DSP - */ -static s32 e1000_phy_reset_dsp(struct e1000_hw *hw) -{ - s32 ret_val; - - do { - ret_val = e1000_write_phy_reg(hw, 29, 0x001d); - if (ret_val) - break; - ret_val = e1000_write_phy_reg(hw, 30, 0x00c1); - if (ret_val) - break; - ret_val = e1000_write_phy_reg(hw, 30, 0x0000); - if (ret_val) - break; - ret_val = E1000_SUCCESS; - } while (0); - - return ret_val; -} - -/** - * e1000_phy_igp_get_info - get igp specific registers - * @hw: Struct containing variables accessed by shared code - * @phy_info: PHY information structure - * - * Get PHY information from various PHY registers for igp PHY only. - */ -static s32 e1000_phy_igp_get_info(struct e1000_hw *hw, - struct e1000_phy_info *phy_info) -{ - s32 ret_val; - u16 phy_data, min_length, max_length, average; - e1000_rev_polarity polarity; - - /* The downshift status is checked only once, after link is established, - * and it stored in the hw->speed_downgraded parameter. - */ - phy_info->downshift = (e1000_downshift) hw->speed_downgraded; - - /* IGP01E1000 does not need to support it. */ - phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal; - - /* IGP01E1000 always correct polarity reversal */ - phy_info->polarity_correction = e1000_polarity_reversal_enabled; - - /* Check polarity status */ - ret_val = e1000_check_polarity(hw, &polarity); - if (ret_val) - return ret_val; - - phy_info->cable_polarity = polarity; - - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data); - if (ret_val) - return ret_val; - - phy_info->mdix_mode = - (e1000_auto_x_mode) ((phy_data & IGP01E1000_PSSR_MDIX) >> - IGP01E1000_PSSR_MDIX_SHIFT); - - if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - /* Local/Remote Receiver Information are only valid @ 1000 - * Mbps - */ - ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); - if (ret_val) - return ret_val; - - phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >> - SR_1000T_LOCAL_RX_STATUS_SHIFT) ? - e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >> - SR_1000T_REMOTE_RX_STATUS_SHIFT) ? - e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - - /* Get cable length */ - ret_val = e1000_get_cable_length(hw, &min_length, &max_length); - if (ret_val) - return ret_val; - - /* Translate to old method */ - average = (max_length + min_length) / 2; - - if (average <= e1000_igp_cable_length_50) - phy_info->cable_length = e1000_cable_length_50; - else if (average <= e1000_igp_cable_length_80) - phy_info->cable_length = e1000_cable_length_50_80; - else if (average <= e1000_igp_cable_length_110) - phy_info->cable_length = e1000_cable_length_80_110; - else if (average <= e1000_igp_cable_length_140) - phy_info->cable_length = e1000_cable_length_110_140; - else - phy_info->cable_length = e1000_cable_length_140; - } - - return E1000_SUCCESS; -} - -/** - * e1000_phy_m88_get_info - get m88 specific registers - * @hw: Struct containing variables accessed by shared code - * @phy_info: PHY information structure - * - * Get PHY information from various PHY registers for m88 PHY only. - */ -static s32 e1000_phy_m88_get_info(struct e1000_hw *hw, - struct e1000_phy_info *phy_info) -{ - s32 ret_val; - u16 phy_data; - e1000_rev_polarity polarity; - - /* The downshift status is checked only once, after link is established, - * and it stored in the hw->speed_downgraded parameter. - */ - phy_info->downshift = (e1000_downshift) hw->speed_downgraded; - - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_info->extended_10bt_distance = - ((phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >> - M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT) ? - e1000_10bt_ext_dist_enable_lower : - e1000_10bt_ext_dist_enable_normal; - - phy_info->polarity_correction = - ((phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >> - M88E1000_PSCR_POLARITY_REVERSAL_SHIFT) ? - e1000_polarity_reversal_disabled : e1000_polarity_reversal_enabled; - - /* Check polarity status */ - ret_val = e1000_check_polarity(hw, &polarity); - if (ret_val) - return ret_val; - phy_info->cable_polarity = polarity; - - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if (ret_val) - return ret_val; - - phy_info->mdix_mode = - (e1000_auto_x_mode) ((phy_data & M88E1000_PSSR_MDIX) >> - M88E1000_PSSR_MDIX_SHIFT); - - if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { - /* Cable Length Estimation and Local/Remote Receiver Information - * are only valid at 1000 Mbps. - */ - phy_info->cable_length = - (e1000_cable_length) ((phy_data & - M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT); - - ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); - if (ret_val) - return ret_val; - - phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >> - SR_1000T_LOCAL_RX_STATUS_SHIFT) ? - e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >> - SR_1000T_REMOTE_RX_STATUS_SHIFT) ? - e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - - } - - return E1000_SUCCESS; -} - -/** - * e1000_phy_get_info - request phy info - * @hw: Struct containing variables accessed by shared code - * @phy_info: PHY information structure - * - * Get PHY information from various PHY registers - */ -s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) -{ - s32 ret_val; - u16 phy_data; - - phy_info->cable_length = e1000_cable_length_undefined; - phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined; - phy_info->cable_polarity = e1000_rev_polarity_undefined; - phy_info->downshift = e1000_downshift_undefined; - phy_info->polarity_correction = e1000_polarity_reversal_undefined; - phy_info->mdix_mode = e1000_auto_x_mode_undefined; - phy_info->local_rx = e1000_1000t_rx_status_undefined; - phy_info->remote_rx = e1000_1000t_rx_status_undefined; - - if (hw->media_type != e1000_media_type_copper) { - e_dbg("PHY info is only valid for copper media\n"); - return -E1000_ERR_CONFIG; - } - - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); - if (ret_val) - return ret_val; - - if ((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) { - e_dbg("PHY info is only valid if link is up\n"); - return -E1000_ERR_CONFIG; - } - - if (hw->phy_type == e1000_phy_igp) - return e1000_phy_igp_get_info(hw, phy_info); - else if ((hw->phy_type == e1000_phy_8211) || - (hw->phy_type == e1000_phy_8201)) - return E1000_SUCCESS; - else - return e1000_phy_m88_get_info(hw, phy_info); -} - -s32 e1000_validate_mdi_setting(struct e1000_hw *hw) -{ - if (!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) { - e_dbg("Invalid MDI setting detected\n"); - hw->mdix = 1; - return -E1000_ERR_CONFIG; - } - return E1000_SUCCESS; -} - -/** - * e1000_init_eeprom_params - initialize sw eeprom vars - * @hw: Struct containing variables accessed by shared code - * - * Sets up eeprom variables in the hw struct. Must be called after mac_type - * is configured. - */ -s32 e1000_init_eeprom_params(struct e1000_hw *hw) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u32 eecd = er32(EECD); - s32 ret_val = E1000_SUCCESS; - u16 eeprom_size; - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - eeprom->type = e1000_eeprom_microwire; - eeprom->word_size = 64; - eeprom->opcode_bits = 3; - eeprom->address_bits = 6; - eeprom->delay_usec = 50; - break; - case e1000_82540: - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_82546_rev_3: - eeprom->type = e1000_eeprom_microwire; - eeprom->opcode_bits = 3; - eeprom->delay_usec = 50; - if (eecd & E1000_EECD_SIZE) { - eeprom->word_size = 256; - eeprom->address_bits = 8; - } else { - eeprom->word_size = 64; - eeprom->address_bits = 6; - } - break; - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - if (eecd & E1000_EECD_TYPE) { - eeprom->type = e1000_eeprom_spi; - eeprom->opcode_bits = 8; - eeprom->delay_usec = 1; - if (eecd & E1000_EECD_ADDR_BITS) { - eeprom->page_size = 32; - eeprom->address_bits = 16; - } else { - eeprom->page_size = 8; - eeprom->address_bits = 8; - } - } else { - eeprom->type = e1000_eeprom_microwire; - eeprom->opcode_bits = 3; - eeprom->delay_usec = 50; - if (eecd & E1000_EECD_ADDR_BITS) { - eeprom->word_size = 256; - eeprom->address_bits = 8; - } else { - eeprom->word_size = 64; - eeprom->address_bits = 6; - } - } - break; - default: - break; - } - - if (eeprom->type == e1000_eeprom_spi) { - /* eeprom_size will be an enum [0..8] that maps to eeprom sizes - * 128B to 32KB (incremented by powers of 2). - */ - /* Set to default value for initial eeprom read. */ - eeprom->word_size = 64; - ret_val = e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size); - if (ret_val) - return ret_val; - eeprom_size = - (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT; - /* 256B eeprom size was not supported in earlier hardware, so we - * bump eeprom_size up one to ensure that "1" (which maps to - * 256B) is never the result used in the shifting logic below. - */ - if (eeprom_size) - eeprom_size++; - - eeprom->word_size = 1 << (eeprom_size + EEPROM_WORD_SIZE_SHIFT); - } - return ret_val; -} - -/** - * e1000_raise_ee_clk - Raises the EEPROM's clock input. - * @hw: Struct containing variables accessed by shared code - * @eecd: EECD's current value - */ -static void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd) -{ - /* Raise the clock input to the EEPROM (by setting the SK bit), and then - * wait microseconds. - */ - *eecd = *eecd | E1000_EECD_SK; - ew32(EECD, *eecd); - E1000_WRITE_FLUSH(); - udelay(hw->eeprom.delay_usec); -} - -/** - * e1000_lower_ee_clk - Lowers the EEPROM's clock input. - * @hw: Struct containing variables accessed by shared code - * @eecd: EECD's current value - */ -static void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd) -{ - /* Lower the clock input to the EEPROM (by clearing the SK bit), and - * then wait 50 microseconds. - */ - *eecd = *eecd & ~E1000_EECD_SK; - ew32(EECD, *eecd); - E1000_WRITE_FLUSH(); - udelay(hw->eeprom.delay_usec); -} - -/** - * e1000_shift_out_ee_bits - Shift data bits out to the EEPROM. - * @hw: Struct containing variables accessed by shared code - * @data: data to send to the EEPROM - * @count: number of bits to shift out - */ -static void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u32 eecd; - u32 mask; - - /* We need to shift "count" bits out to the EEPROM. So, value in the - * "data" parameter will be shifted out to the EEPROM one bit at a time. - * In order to do this, "data" must be broken down into bits. - */ - mask = 0x01 << (count - 1); - eecd = er32(EECD); - if (eeprom->type == e1000_eeprom_microwire) { - eecd &= ~E1000_EECD_DO; - } else if (eeprom->type == e1000_eeprom_spi) { - eecd |= E1000_EECD_DO; - } - do { - /* A "1" is shifted out to the EEPROM by setting bit "DI" to a - * "1", and then raising and then lowering the clock (the SK bit - * controls the clock input to the EEPROM). A "0" is shifted - * out to the EEPROM by setting "DI" to "0" and then raising and - * then lowering the clock. - */ - eecd &= ~E1000_EECD_DI; - - if (data & mask) - eecd |= E1000_EECD_DI; - - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - - udelay(eeprom->delay_usec); - - e1000_raise_ee_clk(hw, &eecd); - e1000_lower_ee_clk(hw, &eecd); - - mask = mask >> 1; - - } while (mask); - - /* We leave the "DI" bit set to "0" when we leave this routine. */ - eecd &= ~E1000_EECD_DI; - ew32(EECD, eecd); -} - -/** - * e1000_shift_in_ee_bits - Shift data bits in from the EEPROM - * @hw: Struct containing variables accessed by shared code - * @count: number of bits to shift in - */ -static u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count) -{ - u32 eecd; - u32 i; - u16 data; - - /* In order to read a register from the EEPROM, we need to shift 'count' - * bits in from the EEPROM. Bits are "shifted in" by raising the clock - * input to the EEPROM (setting the SK bit), and then reading the value - * of the "DO" bit. During this "shifting in" process the "DI" bit - * should always be clear. - */ - - eecd = er32(EECD); - - eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); - data = 0; - - for (i = 0; i < count; i++) { - data = data << 1; - e1000_raise_ee_clk(hw, &eecd); - - eecd = er32(EECD); - - eecd &= ~(E1000_EECD_DI); - if (eecd & E1000_EECD_DO) - data |= 1; - - e1000_lower_ee_clk(hw, &eecd); - } - - return data; -} - -/** - * e1000_acquire_eeprom - Prepares EEPROM for access - * @hw: Struct containing variables accessed by shared code - * - * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This - * function should be called before issuing a command to the EEPROM. - */ -static s32 e1000_acquire_eeprom(struct e1000_hw *hw) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u32 eecd, i = 0; - - eecd = er32(EECD); - - /* Request EEPROM Access */ - if (hw->mac_type > e1000_82544) { - eecd |= E1000_EECD_REQ; - ew32(EECD, eecd); - eecd = er32(EECD); - while ((!(eecd & E1000_EECD_GNT)) && - (i < E1000_EEPROM_GRANT_ATTEMPTS)) { - i++; - udelay(5); - eecd = er32(EECD); - } - if (!(eecd & E1000_EECD_GNT)) { - eecd &= ~E1000_EECD_REQ; - ew32(EECD, eecd); - e_dbg("Could not acquire EEPROM grant\n"); - return -E1000_ERR_EEPROM; - } - } - - /* Setup EEPROM for Read/Write */ - - if (eeprom->type == e1000_eeprom_microwire) { - /* Clear SK and DI */ - eecd &= ~(E1000_EECD_DI | E1000_EECD_SK); - ew32(EECD, eecd); - - /* Set CS */ - eecd |= E1000_EECD_CS; - ew32(EECD, eecd); - } else if (eeprom->type == e1000_eeprom_spi) { - /* Clear SK and CS */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(1); - } - - return E1000_SUCCESS; -} - -/** - * e1000_standby_eeprom - Returns EEPROM to a "standby" state - * @hw: Struct containing variables accessed by shared code - */ -static void e1000_standby_eeprom(struct e1000_hw *hw) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u32 eecd; - - eecd = er32(EECD); - - if (eeprom->type == e1000_eeprom_microwire) { - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(eeprom->delay_usec); - - /* Clock high */ - eecd |= E1000_EECD_SK; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(eeprom->delay_usec); - - /* Select EEPROM */ - eecd |= E1000_EECD_CS; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(eeprom->delay_usec); - - /* Clock low */ - eecd &= ~E1000_EECD_SK; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(eeprom->delay_usec); - } else if (eeprom->type == e1000_eeprom_spi) { - /* Toggle CS to flush commands */ - eecd |= E1000_EECD_CS; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(eeprom->delay_usec); - eecd &= ~E1000_EECD_CS; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(eeprom->delay_usec); - } -} - -/** - * e1000_release_eeprom - drop chip select - * @hw: Struct containing variables accessed by shared code - * - * Terminates a command by inverting the EEPROM's chip select pin - */ -static void e1000_release_eeprom(struct e1000_hw *hw) -{ - u32 eecd; - - eecd = er32(EECD); - - if (hw->eeprom.type == e1000_eeprom_spi) { - eecd |= E1000_EECD_CS; /* Pull CS high */ - eecd &= ~E1000_EECD_SK; /* Lower SCK */ - - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - - udelay(hw->eeprom.delay_usec); - } else if (hw->eeprom.type == e1000_eeprom_microwire) { - /* cleanup eeprom */ - - /* CS on Microwire is active-high */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); - - ew32(EECD, eecd); - - /* Rising edge of clock */ - eecd |= E1000_EECD_SK; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(hw->eeprom.delay_usec); - - /* Falling edge of clock */ - eecd &= ~E1000_EECD_SK; - ew32(EECD, eecd); - E1000_WRITE_FLUSH(); - udelay(hw->eeprom.delay_usec); - } - - /* Stop requesting EEPROM access */ - if (hw->mac_type > e1000_82544) { - eecd &= ~E1000_EECD_REQ; - ew32(EECD, eecd); - } -} - -/** - * e1000_spi_eeprom_ready - Reads a 16 bit word from the EEPROM. - * @hw: Struct containing variables accessed by shared code - */ -static s32 e1000_spi_eeprom_ready(struct e1000_hw *hw) -{ - u16 retry_count = 0; - u8 spi_stat_reg; - - /* Read "Status Register" repeatedly until the LSB is cleared. The - * EEPROM will signal that the command has been completed by clearing - * bit 0 of the internal status register. If it's not cleared within - * 5 milliseconds, then error out. - */ - retry_count = 0; - do { - e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI, - hw->eeprom.opcode_bits); - spi_stat_reg = (u8) e1000_shift_in_ee_bits(hw, 8); - if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI)) - break; - - udelay(5); - retry_count += 5; - - e1000_standby_eeprom(hw); - } while (retry_count < EEPROM_MAX_RETRY_SPI); - - /* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and - * only 0-5mSec on 5V devices) - */ - if (retry_count >= EEPROM_MAX_RETRY_SPI) { - e_dbg("SPI EEPROM Status error\n"); - return -E1000_ERR_EEPROM; - } - - return E1000_SUCCESS; -} - -/** - * e1000_read_eeprom - Reads a 16 bit word from the EEPROM. - * @hw: Struct containing variables accessed by shared code - * @offset: offset of word in the EEPROM to read - * @data: word read from the EEPROM - * @words: number of words to read - */ -s32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - s32 ret; - spin_lock(&e1000_eeprom_lock); - ret = e1000_do_read_eeprom(hw, offset, words, data); - spin_unlock(&e1000_eeprom_lock); - return ret; -} - -static s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u32 i = 0; - - if (hw->mac_type == e1000_ce4100) { - GBE_CONFIG_FLASH_READ(GBE_CONFIG_BASE_VIRT, offset, words, - data); - return E1000_SUCCESS; - } - - /* A check for invalid values: offset too large, too many words, and - * not enough words. - */ - if ((offset >= eeprom->word_size) - || (words > eeprom->word_size - offset) || (words == 0)) { - e_dbg("\"words\" parameter out of bounds. Words = %d," - "size = %d\n", offset, eeprom->word_size); - return -E1000_ERR_EEPROM; - } - - /* EEPROM's that don't use EERD to read require us to bit-bang the SPI - * directly. In this case, we need to acquire the EEPROM so that - * FW or other port software does not interrupt. - */ - /* Prepare the EEPROM for bit-bang reading */ - if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) - return -E1000_ERR_EEPROM; - - /* Set up the SPI or Microwire EEPROM for bit-bang reading. We have - * acquired the EEPROM at this point, so any returns should release it - */ - if (eeprom->type == e1000_eeprom_spi) { - u16 word_in; - u8 read_opcode = EEPROM_READ_OPCODE_SPI; - - if (e1000_spi_eeprom_ready(hw)) { - e1000_release_eeprom(hw); - return -E1000_ERR_EEPROM; - } - - e1000_standby_eeprom(hw); - - /* Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((eeprom->address_bits == 8) && (offset >= 128)) - read_opcode |= EEPROM_A8_OPCODE_SPI; - - /* Send the READ command (opcode + addr) */ - e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits); - e1000_shift_out_ee_bits(hw, (u16) (offset * 2), - eeprom->address_bits); - - /* Read the data. The address of the eeprom internally - * increments with each byte (spi) being read, saving on the - * overhead of eeprom setup and tear-down. The address counter - * will roll over if reading beyond the size of the eeprom, thus - * allowing the entire memory to be read starting from any - * offset. - */ - for (i = 0; i < words; i++) { - word_in = e1000_shift_in_ee_bits(hw, 16); - data[i] = (word_in >> 8) | (word_in << 8); - } - } else if (eeprom->type == e1000_eeprom_microwire) { - for (i = 0; i < words; i++) { - /* Send the READ command (opcode + addr) */ - e1000_shift_out_ee_bits(hw, - EEPROM_READ_OPCODE_MICROWIRE, - eeprom->opcode_bits); - e1000_shift_out_ee_bits(hw, (u16) (offset + i), - eeprom->address_bits); - - /* Read the data. For microwire, each word requires the - * overhead of eeprom setup and tear-down. - */ - data[i] = e1000_shift_in_ee_bits(hw, 16); - e1000_standby_eeprom(hw); - } - } - - /* End this read operation */ - e1000_release_eeprom(hw); - - return E1000_SUCCESS; -} - -/** - * e1000_validate_eeprom_checksum - Verifies that the EEPROM has a valid checksum - * @hw: Struct containing variables accessed by shared code - * - * Reads the first 64 16 bit words of the EEPROM and sums the values read. - * If the the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is - * valid. - */ -s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw) -{ - u16 checksum = 0; - u16 i, eeprom_data; - - for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { - if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { - e_dbg("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - checksum += eeprom_data; - } - -#ifdef CONFIG_PARISC - /* This is a signature and not a checksum on HP c8000 */ - if ((hw->subsystem_vendor_id == 0x103C) && (eeprom_data == 0x16d6)) - return E1000_SUCCESS; - -#endif - if (checksum == (u16) EEPROM_SUM) - return E1000_SUCCESS; - else { - e_dbg("EEPROM Checksum Invalid\n"); - return -E1000_ERR_EEPROM; - } -} - -/** - * e1000_update_eeprom_checksum - Calculates/writes the EEPROM checksum - * @hw: Struct containing variables accessed by shared code - * - * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA. - * Writes the difference to word offset 63 of the EEPROM. - */ -s32 e1000_update_eeprom_checksum(struct e1000_hw *hw) -{ - u16 checksum = 0; - u16 i, eeprom_data; - - for (i = 0; i < EEPROM_CHECKSUM_REG; i++) { - if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { - e_dbg("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - checksum += eeprom_data; - } - checksum = (u16) EEPROM_SUM - checksum; - if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) { - e_dbg("EEPROM Write Error\n"); - return -E1000_ERR_EEPROM; - } - return E1000_SUCCESS; -} - -/** - * e1000_write_eeprom - write words to the different EEPROM types. - * @hw: Struct containing variables accessed by shared code - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word to be written to the EEPROM - * - * If e1000_update_eeprom_checksum is not called after this function, the - * EEPROM will most likely contain an invalid checksum. - */ -s32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - s32 ret; - spin_lock(&e1000_eeprom_lock); - ret = e1000_do_write_eeprom(hw, offset, words, data); - spin_unlock(&e1000_eeprom_lock); - return ret; -} - -static s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - s32 status = 0; - - if (hw->mac_type == e1000_ce4100) { - GBE_CONFIG_FLASH_WRITE(GBE_CONFIG_BASE_VIRT, offset, words, - data); - return E1000_SUCCESS; - } - - /* A check for invalid values: offset too large, too many words, and - * not enough words. - */ - if ((offset >= eeprom->word_size) - || (words > eeprom->word_size - offset) || (words == 0)) { - e_dbg("\"words\" parameter out of bounds\n"); - return -E1000_ERR_EEPROM; - } - - /* Prepare the EEPROM for writing */ - if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) - return -E1000_ERR_EEPROM; - - if (eeprom->type == e1000_eeprom_microwire) { - status = e1000_write_eeprom_microwire(hw, offset, words, data); - } else { - status = e1000_write_eeprom_spi(hw, offset, words, data); - msleep(10); - } - - /* Done with writing */ - e1000_release_eeprom(hw); - - return status; -} - -/** - * e1000_write_eeprom_spi - Writes a 16 bit word to a given offset in an SPI EEPROM. - * @hw: Struct containing variables accessed by shared code - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: pointer to array of 8 bit words to be written to the EEPROM - */ -static s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u16 widx = 0; - - while (widx < words) { - u8 write_opcode = EEPROM_WRITE_OPCODE_SPI; - - if (e1000_spi_eeprom_ready(hw)) - return -E1000_ERR_EEPROM; - - e1000_standby_eeprom(hw); - - /* Send the WRITE ENABLE command (8 bit opcode ) */ - e1000_shift_out_ee_bits(hw, EEPROM_WREN_OPCODE_SPI, - eeprom->opcode_bits); - - e1000_standby_eeprom(hw); - - /* Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((eeprom->address_bits == 8) && (offset >= 128)) - write_opcode |= EEPROM_A8_OPCODE_SPI; - - /* Send the Write command (8-bit opcode + addr) */ - e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits); - - e1000_shift_out_ee_bits(hw, (u16) ((offset + widx) * 2), - eeprom->address_bits); - - /* Send the data */ - - /* Loop to allow for up to whole page write (32 bytes) of - * eeprom - */ - while (widx < words) { - u16 word_out = data[widx]; - word_out = (word_out >> 8) | (word_out << 8); - e1000_shift_out_ee_bits(hw, word_out, 16); - widx++; - - /* Some larger eeprom sizes are capable of a 32-byte - * PAGE WRITE operation, while the smaller eeproms are - * capable of an 8-byte PAGE WRITE operation. Break the - * inner loop to pass new address - */ - if ((((offset + widx) * 2) % eeprom->page_size) == 0) { - e1000_standby_eeprom(hw); - break; - } - } - } - - return E1000_SUCCESS; -} - -/** - * e1000_write_eeprom_microwire - Writes a 16 bit word to a given offset in a Microwire EEPROM. - * @hw: Struct containing variables accessed by shared code - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: pointer to array of 8 bit words to be written to the EEPROM - */ -static s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data) -{ - struct e1000_eeprom_info *eeprom = &hw->eeprom; - u32 eecd; - u16 words_written = 0; - u16 i = 0; - - /* Send the write enable command to the EEPROM (3-bit opcode plus - * 6/8-bit dummy address beginning with 11). It's less work to include - * the 11 of the dummy address as part of the opcode than it is to shift - * it over the correct number of bits for the address. This puts the - * EEPROM into write/erase mode. - */ - e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE, - (u16) (eeprom->opcode_bits + 2)); - - e1000_shift_out_ee_bits(hw, 0, (u16) (eeprom->address_bits - 2)); - - /* Prepare the EEPROM */ - e1000_standby_eeprom(hw); - - while (words_written < words) { - /* Send the Write command (3-bit opcode + addr) */ - e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE, - eeprom->opcode_bits); - - e1000_shift_out_ee_bits(hw, (u16) (offset + words_written), - eeprom->address_bits); - - /* Send the data */ - e1000_shift_out_ee_bits(hw, data[words_written], 16); - - /* Toggle the CS line. This in effect tells the EEPROM to - * execute the previous command. - */ - e1000_standby_eeprom(hw); - - /* Read DO repeatedly until it is high (equal to '1'). The - * EEPROM will signal that the command has been completed by - * raising the DO signal. If DO does not go high in 10 - * milliseconds, then error out. - */ - for (i = 0; i < 200; i++) { - eecd = er32(EECD); - if (eecd & E1000_EECD_DO) - break; - udelay(50); - } - if (i == 200) { - e_dbg("EEPROM Write did not complete\n"); - return -E1000_ERR_EEPROM; - } - - /* Recover from write */ - e1000_standby_eeprom(hw); - - words_written++; - } - - /* Send the write disable command to the EEPROM (3-bit opcode plus - * 6/8-bit dummy address beginning with 10). It's less work to include - * the 10 of the dummy address as part of the opcode than it is to shift - * it over the correct number of bits for the address. This takes the - * EEPROM out of write/erase mode. - */ - e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE, - (u16) (eeprom->opcode_bits + 2)); - - e1000_shift_out_ee_bits(hw, 0, (u16) (eeprom->address_bits - 2)); - - return E1000_SUCCESS; -} - -/** - * e1000_read_mac_addr - read the adapters MAC from eeprom - * @hw: Struct containing variables accessed by shared code - * - * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the - * second function of dual function devices - */ -s32 e1000_read_mac_addr(struct e1000_hw *hw) -{ - u16 offset; - u16 eeprom_data, i; - - for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) { - offset = i >> 1; - if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { - e_dbg("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - hw->perm_mac_addr[i] = (u8) (eeprom_data & 0x00FF); - hw->perm_mac_addr[i + 1] = (u8) (eeprom_data >> 8); - } - - switch (hw->mac_type) { - default: - break; - case e1000_82546: - case e1000_82546_rev_3: - if (er32(STATUS) & E1000_STATUS_FUNC_1) - hw->perm_mac_addr[5] ^= 0x01; - break; - } - - for (i = 0; i < NODE_ADDRESS_SIZE; i++) - hw->mac_addr[i] = hw->perm_mac_addr[i]; - return E1000_SUCCESS; -} - -/** - * e1000_init_rx_addrs - Initializes receive address filters. - * @hw: Struct containing variables accessed by shared code - * - * Places the MAC address in receive address register 0 and clears the rest - * of the receive address registers. Clears the multicast table. Assumes - * the receiver is in reset when the routine is called. - */ -static void e1000_init_rx_addrs(struct e1000_hw *hw) -{ - u32 i; - u32 rar_num; - - /* Setup the receive address. */ - e_dbg("Programming MAC Address into RAR[0]\n"); - - e1000_rar_set(hw, hw->mac_addr, 0); - - rar_num = E1000_RAR_ENTRIES; - - /* Zero out the other 15 receive addresses. */ - e_dbg("Clearing RAR[1-15]\n"); - for (i = 1; i < rar_num; i++) { - E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); - E1000_WRITE_FLUSH(); - E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0); - E1000_WRITE_FLUSH(); - } -} - -/** - * e1000_hash_mc_addr - Hashes an address to determine its location in the multicast table - * @hw: Struct containing variables accessed by shared code - * @mc_addr: the multicast address to hash - */ -u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) -{ - u32 hash_value = 0; - - /* The portion of the address that is used for the hash table is - * determined by the mc_filter_type setting. - */ - switch (hw->mc_filter_type) { - /* [0] [1] [2] [3] [4] [5] - * 01 AA 00 12 34 56 - * LSB MSB - */ - case 0: - /* [47:36] i.e. 0x563 for above example address */ - hash_value = ((mc_addr[4] >> 4) | (((u16) mc_addr[5]) << 4)); - break; - case 1: - /* [46:35] i.e. 0xAC6 for above example address */ - hash_value = ((mc_addr[4] >> 3) | (((u16) mc_addr[5]) << 5)); - break; - case 2: - /* [45:34] i.e. 0x5D8 for above example address */ - hash_value = ((mc_addr[4] >> 2) | (((u16) mc_addr[5]) << 6)); - break; - case 3: - /* [43:32] i.e. 0x634 for above example address */ - hash_value = ((mc_addr[4]) | (((u16) mc_addr[5]) << 8)); - break; - } - - hash_value &= 0xFFF; - return hash_value; -} - -/** - * e1000_rar_set - Puts an ethernet address into a receive address register. - * @hw: Struct containing variables accessed by shared code - * @addr: Address to put into receive address register - * @index: Receive address register to write - */ -void e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) -{ - u32 rar_low, rar_high; - - /* HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian - */ - rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) | - ((u32) addr[2] << 16) | ((u32) addr[3] << 24)); - rar_high = ((u32) addr[4] | ((u32) addr[5] << 8)); - - /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx - * unit hang. - * - * Description: - * If there are any Rx frames queued up or otherwise present in the HW - * before RSS is enabled, and then we enable RSS, the HW Rx unit will - * hang. To work around this issue, we have to disable receives and - * flush out all Rx frames before we enable RSS. To do so, we modify we - * redirect all Rx traffic to manageability and then reset the HW. - * This flushes away Rx frames, and (since the redirections to - * manageability persists across resets) keeps new ones from coming in - * while we work. Then, we clear the Address Valid AV bit for all MAC - * addresses and undo the re-direction to manageability. - * Now, frames are coming in again, but the MAC won't accept them, so - * far so good. We now proceed to initialize RSS (if necessary) and - * configure the Rx unit. Last, we re-enable the AV bits and continue - * on our merry way. - */ - switch (hw->mac_type) { - default: - /* Indicate to hardware the Address is Valid. */ - rar_high |= E1000_RAH_AV; - break; - } - - E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low); - E1000_WRITE_FLUSH(); - E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high); - E1000_WRITE_FLUSH(); -} - -/** - * e1000_write_vfta - Writes a value to the specified offset in the VLAN filter table. - * @hw: Struct containing variables accessed by shared code - * @offset: Offset in VLAN filer table to write - * @value: Value to write into VLAN filter table - */ -void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) -{ - u32 temp; - - if ((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) { - temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1)); - E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value); - E1000_WRITE_FLUSH(); - E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp); - E1000_WRITE_FLUSH(); - } else { - E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value); - E1000_WRITE_FLUSH(); - } -} - -/** - * e1000_clear_vfta - Clears the VLAN filer table - * @hw: Struct containing variables accessed by shared code - */ -static void e1000_clear_vfta(struct e1000_hw *hw) -{ - u32 offset; - u32 vfta_value = 0; - u32 vfta_offset = 0; - u32 vfta_bit_in_reg = 0; - - for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { - /* If the offset we want to clear is the same offset of the - * manageability VLAN ID, then clear all bits except that of the - * manageability unit - */ - vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0; - E1000_WRITE_REG_ARRAY(hw, VFTA, offset, vfta_value); - E1000_WRITE_FLUSH(); - } -} - -static s32 e1000_id_led_init(struct e1000_hw *hw) -{ - u32 ledctl; - const u32 ledctl_mask = 0x000000FF; - const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; - const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; - u16 eeprom_data, i, temp; - const u16 led_mask = 0x0F; - - if (hw->mac_type < e1000_82540) { - /* Nothing to do */ - return E1000_SUCCESS; - } - - ledctl = er32(LEDCTL); - hw->ledctl_default = ledctl; - hw->ledctl_mode1 = hw->ledctl_default; - hw->ledctl_mode2 = hw->ledctl_default; - - if (e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) { - e_dbg("EEPROM Read Error\n"); - return -E1000_ERR_EEPROM; - } - - if ((eeprom_data == ID_LED_RESERVED_0000) || - (eeprom_data == ID_LED_RESERVED_FFFF)) { - eeprom_data = ID_LED_DEFAULT; - } - - for (i = 0; i < 4; i++) { - temp = (eeprom_data >> (i << 2)) & led_mask; - switch (temp) { - case ID_LED_ON1_DEF2: - case ID_LED_ON1_ON2: - case ID_LED_ON1_OFF2: - hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - hw->ledctl_mode1 |= ledctl_on << (i << 3); - break; - case ID_LED_OFF1_DEF2: - case ID_LED_OFF1_ON2: - case ID_LED_OFF1_OFF2: - hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - hw->ledctl_mode1 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - switch (temp) { - case ID_LED_DEF1_ON2: - case ID_LED_ON1_ON2: - case ID_LED_OFF1_ON2: - hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - hw->ledctl_mode2 |= ledctl_on << (i << 3); - break; - case ID_LED_DEF1_OFF2: - case ID_LED_ON1_OFF2: - case ID_LED_OFF1_OFF2: - hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - hw->ledctl_mode2 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - } - return E1000_SUCCESS; -} - -/** - * e1000_setup_led - * @hw: Struct containing variables accessed by shared code - * - * Prepares SW controlable LED for use and saves the current state of the LED. - */ -s32 e1000_setup_led(struct e1000_hw *hw) -{ - u32 ledctl; - s32 ret_val = E1000_SUCCESS; - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - /* No setup necessary */ - break; - case e1000_82541: - case e1000_82547: - case e1000_82541_rev_2: - case e1000_82547_rev_2: - /* Turn off PHY Smart Power Down (if enabled) */ - ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, - &hw->phy_spd_default); - if (ret_val) - return ret_val; - ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, - (u16) (hw->phy_spd_default & - ~IGP01E1000_GMII_SPD)); - if (ret_val) - return ret_val; - /* Fall Through */ - default: - if (hw->media_type == e1000_media_type_fiber) { - ledctl = er32(LEDCTL); - /* Save current LEDCTL settings */ - hw->ledctl_default = ledctl; - /* Turn off LED0 */ - ledctl &= ~(E1000_LEDCTL_LED0_IVRT | - E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_LED0_MODE_MASK); - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << - E1000_LEDCTL_LED0_MODE_SHIFT); - ew32(LEDCTL, ledctl); - } else if (hw->media_type == e1000_media_type_copper) - ew32(LEDCTL, hw->ledctl_mode1); - break; - } - - return E1000_SUCCESS; -} - -/** - * e1000_cleanup_led - Restores the saved state of the SW controlable LED. - * @hw: Struct containing variables accessed by shared code - */ -s32 e1000_cleanup_led(struct e1000_hw *hw) -{ - s32 ret_val = E1000_SUCCESS; - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - /* No cleanup necessary */ - break; - case e1000_82541: - case e1000_82547: - case e1000_82541_rev_2: - case e1000_82547_rev_2: - /* Turn on PHY Smart Power Down (if previously enabled) */ - ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, - hw->phy_spd_default); - if (ret_val) - return ret_val; - /* Fall Through */ - default: - /* Restore LEDCTL settings */ - ew32(LEDCTL, hw->ledctl_default); - break; - } - - return E1000_SUCCESS; -} - -/** - * e1000_led_on - Turns on the software controllable LED - * @hw: Struct containing variables accessed by shared code - */ -s32 e1000_led_on(struct e1000_hw *hw) -{ - u32 ctrl = er32(CTRL); - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - /* Set SW Defineable Pin 0 to turn on the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - break; - case e1000_82544: - if (hw->media_type == e1000_media_type_fiber) { - /* Set SW Defineable Pin 0 to turn on the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else { - /* Clear SW Defineable Pin 0 to turn on the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } - break; - default: - if (hw->media_type == e1000_media_type_fiber) { - /* Clear SW Defineable Pin 0 to turn on the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else if (hw->media_type == e1000_media_type_copper) { - ew32(LEDCTL, hw->ledctl_mode2); - return E1000_SUCCESS; - } - break; - } - - ew32(CTRL, ctrl); - - return E1000_SUCCESS; -} - -/** - * e1000_led_off - Turns off the software controllable LED - * @hw: Struct containing variables accessed by shared code - */ -s32 e1000_led_off(struct e1000_hw *hw) -{ - u32 ctrl = er32(CTRL); - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - /* Clear SW Defineable Pin 0 to turn off the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - break; - case e1000_82544: - if (hw->media_type == e1000_media_type_fiber) { - /* Clear SW Defineable Pin 0 to turn off the LED */ - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else { - /* Set SW Defineable Pin 0 to turn off the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } - break; - default: - if (hw->media_type == e1000_media_type_fiber) { - /* Set SW Defineable Pin 0 to turn off the LED */ - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - } else if (hw->media_type == e1000_media_type_copper) { - ew32(LEDCTL, hw->ledctl_mode1); - return E1000_SUCCESS; - } - break; - } - - ew32(CTRL, ctrl); - - return E1000_SUCCESS; -} - -/** - * e1000_clear_hw_cntrs - Clears all hardware statistics counters. - * @hw: Struct containing variables accessed by shared code - */ -static void e1000_clear_hw_cntrs(struct e1000_hw *hw) -{ - volatile u32 temp; - - temp = er32(CRCERRS); - temp = er32(SYMERRS); - temp = er32(MPC); - temp = er32(SCC); - temp = er32(ECOL); - temp = er32(MCC); - temp = er32(LATECOL); - temp = er32(COLC); - temp = er32(DC); - temp = er32(SEC); - temp = er32(RLEC); - temp = er32(XONRXC); - temp = er32(XONTXC); - temp = er32(XOFFRXC); - temp = er32(XOFFTXC); - temp = er32(FCRUC); - - temp = er32(PRC64); - temp = er32(PRC127); - temp = er32(PRC255); - temp = er32(PRC511); - temp = er32(PRC1023); - temp = er32(PRC1522); - - temp = er32(GPRC); - temp = er32(BPRC); - temp = er32(MPRC); - temp = er32(GPTC); - temp = er32(GORCL); - temp = er32(GORCH); - temp = er32(GOTCL); - temp = er32(GOTCH); - temp = er32(RNBC); - temp = er32(RUC); - temp = er32(RFC); - temp = er32(ROC); - temp = er32(RJC); - temp = er32(TORL); - temp = er32(TORH); - temp = er32(TOTL); - temp = er32(TOTH); - temp = er32(TPR); - temp = er32(TPT); - - temp = er32(PTC64); - temp = er32(PTC127); - temp = er32(PTC255); - temp = er32(PTC511); - temp = er32(PTC1023); - temp = er32(PTC1522); - - temp = er32(MPTC); - temp = er32(BPTC); - - if (hw->mac_type < e1000_82543) - return; - - temp = er32(ALGNERRC); - temp = er32(RXERRC); - temp = er32(TNCRS); - temp = er32(CEXTERR); - temp = er32(TSCTC); - temp = er32(TSCTFC); - - if (hw->mac_type <= e1000_82544) - return; - - temp = er32(MGTPRC); - temp = er32(MGTPDC); - temp = er32(MGTPTC); -} - -/** - * e1000_reset_adaptive - Resets Adaptive IFS to its default state. - * @hw: Struct containing variables accessed by shared code - * - * Call this after e1000_init_hw. You may override the IFS defaults by setting - * hw->ifs_params_forced to true. However, you must initialize hw-> - * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio - * before calling this function. - */ -void e1000_reset_adaptive(struct e1000_hw *hw) -{ - if (hw->adaptive_ifs) { - if (!hw->ifs_params_forced) { - hw->current_ifs_val = 0; - hw->ifs_min_val = IFS_MIN; - hw->ifs_max_val = IFS_MAX; - hw->ifs_step_size = IFS_STEP; - hw->ifs_ratio = IFS_RATIO; - } - hw->in_ifs_mode = false; - ew32(AIT, 0); - } else { - e_dbg("Not in Adaptive IFS mode!\n"); - } -} - -/** - * e1000_update_adaptive - update adaptive IFS - * @hw: Struct containing variables accessed by shared code - * @tx_packets: Number of transmits since last callback - * @total_collisions: Number of collisions since last callback - * - * Called during the callback/watchdog routine to update IFS value based on - * the ratio of transmits to collisions. - */ -void e1000_update_adaptive(struct e1000_hw *hw) -{ - if (hw->adaptive_ifs) { - if ((hw->collision_delta *hw->ifs_ratio) > hw->tx_packet_delta) { - if (hw->tx_packet_delta > MIN_NUM_XMITS) { - hw->in_ifs_mode = true; - if (hw->current_ifs_val < hw->ifs_max_val) { - if (hw->current_ifs_val == 0) - hw->current_ifs_val = - hw->ifs_min_val; - else - hw->current_ifs_val += - hw->ifs_step_size; - ew32(AIT, hw->current_ifs_val); - } - } - } else { - if (hw->in_ifs_mode - && (hw->tx_packet_delta <= MIN_NUM_XMITS)) { - hw->current_ifs_val = 0; - hw->in_ifs_mode = false; - ew32(AIT, 0); - } - } - } else { - e_dbg("Not in Adaptive IFS mode!\n"); - } -} - -/** - * e1000_get_bus_info - * @hw: Struct containing variables accessed by shared code - * - * Gets the current PCI bus type, speed, and width of the hardware - */ -void e1000_get_bus_info(struct e1000_hw *hw) -{ - u32 status; - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - hw->bus_type = e1000_bus_type_pci; - hw->bus_speed = e1000_bus_speed_unknown; - hw->bus_width = e1000_bus_width_unknown; - break; - default: - status = er32(STATUS); - hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? - e1000_bus_type_pcix : e1000_bus_type_pci; - - if (hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) { - hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ? - e1000_bus_speed_66 : e1000_bus_speed_120; - } else if (hw->bus_type == e1000_bus_type_pci) { - hw->bus_speed = (status & E1000_STATUS_PCI66) ? - e1000_bus_speed_66 : e1000_bus_speed_33; - } else { - switch (status & E1000_STATUS_PCIX_SPEED) { - case E1000_STATUS_PCIX_SPEED_66: - hw->bus_speed = e1000_bus_speed_66; - break; - case E1000_STATUS_PCIX_SPEED_100: - hw->bus_speed = e1000_bus_speed_100; - break; - case E1000_STATUS_PCIX_SPEED_133: - hw->bus_speed = e1000_bus_speed_133; - break; - default: - hw->bus_speed = e1000_bus_speed_reserved; - break; - } - } - hw->bus_width = (status & E1000_STATUS_BUS64) ? - e1000_bus_width_64 : e1000_bus_width_32; - break; - } -} - -/** - * e1000_write_reg_io - * @hw: Struct containing variables accessed by shared code - * @offset: offset to write to - * @value: value to write - * - * Writes a value to one of the devices registers using port I/O (as opposed to - * memory mapped I/O). Only 82544 and newer devices support port I/O. - */ -static void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value) -{ - unsigned long io_addr = hw->io_base; - unsigned long io_data = hw->io_base + 4; - - e1000_io_write(hw, io_addr, offset); - e1000_io_write(hw, io_data, value); -} - -/** - * e1000_get_cable_length - Estimates the cable length. - * @hw: Struct containing variables accessed by shared code - * @min_length: The estimated minimum length - * @max_length: The estimated maximum length - * - * returns: - E1000_ERR_XXX - * E1000_SUCCESS - * - * This function always returns a ranged length (minimum & maximum). - * So for M88 phy's, this function interprets the one value returned from the - * register to the minimum and maximum range. - * For IGP phy's, the function calculates the range by the AGC registers. - */ -static s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length, - u16 *max_length) -{ - s32 ret_val; - u16 agc_value = 0; - u16 i, phy_data; - u16 cable_length; - - *min_length = *max_length = 0; - - /* Use old method for Phy older than IGP */ - if (hw->phy_type == e1000_phy_m88) { - - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data); - if (ret_val) - return ret_val; - cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT; - - /* Convert the enum value to ranged values */ - switch (cable_length) { - case e1000_cable_length_50: - *min_length = 0; - *max_length = e1000_igp_cable_length_50; - break; - case e1000_cable_length_50_80: - *min_length = e1000_igp_cable_length_50; - *max_length = e1000_igp_cable_length_80; - break; - case e1000_cable_length_80_110: - *min_length = e1000_igp_cable_length_80; - *max_length = e1000_igp_cable_length_110; - break; - case e1000_cable_length_110_140: - *min_length = e1000_igp_cable_length_110; - *max_length = e1000_igp_cable_length_140; - break; - case e1000_cable_length_140: - *min_length = e1000_igp_cable_length_140; - *max_length = e1000_igp_cable_length_170; - break; - default: - return -E1000_ERR_PHY; - } - } else if (hw->phy_type == e1000_phy_igp) { /* For IGP PHY */ - u16 cur_agc_value; - u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE; - static const u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = { - IGP01E1000_PHY_AGC_A, - IGP01E1000_PHY_AGC_B, - IGP01E1000_PHY_AGC_C, - IGP01E1000_PHY_AGC_D - }; - /* Read the AGC registers for all channels */ - for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { - - ret_val = - e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data); - if (ret_val) - return ret_val; - - cur_agc_value = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT; - - /* Value bound check. */ - if ((cur_agc_value >= - IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) - || (cur_agc_value == 0)) - return -E1000_ERR_PHY; - - agc_value += cur_agc_value; - - /* Update minimal AGC value. */ - if (min_agc_value > cur_agc_value) - min_agc_value = cur_agc_value; - } - - /* Remove the minimal AGC result for length < 50m */ - if (agc_value < - IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) { - agc_value -= min_agc_value; - - /* Get the average length of the remaining 3 channels */ - agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1); - } else { - /* Get the average length of all the 4 channels. */ - agc_value /= IGP01E1000_PHY_CHANNEL_NUM; - } - - /* Set the range of the calculated length. */ - *min_length = ((e1000_igp_cable_length_table[agc_value] - - IGP01E1000_AGC_RANGE) > 0) ? - (e1000_igp_cable_length_table[agc_value] - - IGP01E1000_AGC_RANGE) : 0; - *max_length = e1000_igp_cable_length_table[agc_value] + - IGP01E1000_AGC_RANGE; - } - - return E1000_SUCCESS; -} - -/** - * e1000_check_polarity - Check the cable polarity - * @hw: Struct containing variables accessed by shared code - * @polarity: output parameter : 0 - Polarity is not reversed - * 1 - Polarity is reversed. - * - * returns: - E1000_ERR_XXX - * E1000_SUCCESS - * - * For phy's older than IGP, this function simply reads the polarity bit in the - * Phy Status register. For IGP phy's, this bit is valid only if link speed is - * 10 Mbps. If the link speed is 100 Mbps there is no polarity so this bit will - * return 0. If the link speed is 1000 Mbps the polarity status is in the - * IGP01E1000_PHY_PCS_INIT_REG. - */ -static s32 e1000_check_polarity(struct e1000_hw *hw, - e1000_rev_polarity *polarity) -{ - s32 ret_val; - u16 phy_data; - - if (hw->phy_type == e1000_phy_m88) { - /* return the Polarity bit in the Status register. */ - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data); - if (ret_val) - return ret_val; - *polarity = ((phy_data & M88E1000_PSSR_REV_POLARITY) >> - M88E1000_PSSR_REV_POLARITY_SHIFT) ? - e1000_rev_polarity_reversed : e1000_rev_polarity_normal; - - } else if (hw->phy_type == e1000_phy_igp) { - /* Read the Status register to check the speed */ - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, - &phy_data); - if (ret_val) - return ret_val; - - /* If speed is 1000 Mbps, must read the - * IGP01E1000_PHY_PCS_INIT_REG to find the polarity status - */ - if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - - /* Read the GIG initialization PCS register (0x00B4) */ - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG, - &phy_data); - if (ret_val) - return ret_val; - - /* Check the polarity bits */ - *polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ? - e1000_rev_polarity_reversed : - e1000_rev_polarity_normal; - } else { - /* For 10 Mbps, read the polarity bit in the status - * register. (for 100 Mbps this bit is always 0) - */ - *polarity = - (phy_data & IGP01E1000_PSSR_POLARITY_REVERSED) ? - e1000_rev_polarity_reversed : - e1000_rev_polarity_normal; - } - } - return E1000_SUCCESS; -} - -/** - * e1000_check_downshift - Check if Downshift occurred - * @hw: Struct containing variables accessed by shared code - * @downshift: output parameter : 0 - No Downshift occurred. - * 1 - Downshift occurred. - * - * returns: - E1000_ERR_XXX - * E1000_SUCCESS - * - * For phy's older than IGP, this function reads the Downshift bit in the Phy - * Specific Status register. For IGP phy's, it reads the Downgrade bit in the - * Link Health register. In IGP this bit is latched high, so the driver must - * read it immediately after link is established. - */ -static s32 e1000_check_downshift(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - - if (hw->phy_type == e1000_phy_igp) { - ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, - &phy_data); - if (ret_val) - return ret_val; - - hw->speed_downgraded = - (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; - } else if (hw->phy_type == e1000_phy_m88) { - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, - &phy_data); - if (ret_val) - return ret_val; - - hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >> - M88E1000_PSSR_DOWNSHIFT_SHIFT; - } - - return E1000_SUCCESS; -} - -static const u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = { - IGP01E1000_PHY_AGC_PARAM_A, - IGP01E1000_PHY_AGC_PARAM_B, - IGP01E1000_PHY_AGC_PARAM_C, - IGP01E1000_PHY_AGC_PARAM_D -}; - -static s32 e1000_1000Mb_check_cable_length(struct e1000_hw *hw) -{ - u16 min_length, max_length; - u16 phy_data, i; - s32 ret_val; - - ret_val = e1000_get_cable_length(hw, &min_length, &max_length); - if (ret_val) - return ret_val; - - if (hw->dsp_config_state != e1000_dsp_config_enabled) - return 0; - - if (min_length >= e1000_igp_cable_length_50) { - for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { - ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], - &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; - - ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i], - phy_data); - if (ret_val) - return ret_val; - } - hw->dsp_config_state = e1000_dsp_config_activated; - } else { - u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20; - u32 idle_errs = 0; - - /* clear previous idle error counts */ - ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); - if (ret_val) - return ret_val; - - for (i = 0; i < ffe_idle_err_timeout; i++) { - udelay(1000); - ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, - &phy_data); - if (ret_val) - return ret_val; - - idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT); - if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) { - hw->ffe_config_state = e1000_ffe_config_active; - - ret_val = e1000_write_phy_reg(hw, - IGP01E1000_PHY_DSP_FFE, - IGP01E1000_PHY_DSP_FFE_CM_CP); - if (ret_val) - return ret_val; - break; - } - - if (idle_errs) - ffe_idle_err_timeout = - FFE_IDLE_ERR_COUNT_TIMEOUT_100; - } - } - - return 0; -} - -/** - * e1000_config_dsp_after_link_change - * @hw: Struct containing variables accessed by shared code - * @link_up: was link up at the time this was called - * - * returns: - E1000_ERR_PHY if fail to read/write the PHY - * E1000_SUCCESS at any other case. - * - * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a - * gigabit link is achieved to improve link quality. - */ - -static s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up) -{ - s32 ret_val; - u16 phy_data, phy_saved_data, speed, duplex, i; - - if (hw->phy_type != e1000_phy_igp) - return E1000_SUCCESS; - - if (link_up) { - ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex); - if (ret_val) { - e_dbg("Error getting link speed and duplex\n"); - return ret_val; - } - - if (speed == SPEED_1000) { - ret_val = e1000_1000Mb_check_cable_length(hw); - if (ret_val) - return ret_val; - } - } else { - if (hw->dsp_config_state == e1000_dsp_config_activated) { - /* Save off the current value of register 0x2F5B to be - * restored at the end of the routines. - */ - ret_val = - e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data); - - if (ret_val) - return ret_val; - - /* Disable the PHY transmitter */ - ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003); - - if (ret_val) - return ret_val; - - msleep(20); - - ret_val = e1000_write_phy_reg(hw, 0x0000, - IGP01E1000_IEEE_FORCE_GIGA); - if (ret_val) - return ret_val; - for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { - ret_val = - e1000_read_phy_reg(hw, dsp_reg_array[i], - &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; - phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS; - - ret_val = - e1000_write_phy_reg(hw, dsp_reg_array[i], - phy_data); - if (ret_val) - return ret_val; - } - - ret_val = e1000_write_phy_reg(hw, 0x0000, - IGP01E1000_IEEE_RESTART_AUTONEG); - if (ret_val) - return ret_val; - - msleep(20); - - /* Now enable the transmitter */ - ret_val = - e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data); - - if (ret_val) - return ret_val; - - hw->dsp_config_state = e1000_dsp_config_enabled; - } - - if (hw->ffe_config_state == e1000_ffe_config_active) { - /* Save off the current value of register 0x2F5B to be - * restored at the end of the routines. - */ - ret_val = - e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data); - - if (ret_val) - return ret_val; - - /* Disable the PHY transmitter */ - ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003); - - if (ret_val) - return ret_val; - - msleep(20); - - ret_val = e1000_write_phy_reg(hw, 0x0000, - IGP01E1000_IEEE_FORCE_GIGA); - if (ret_val) - return ret_val; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE, - IGP01E1000_PHY_DSP_FFE_DEFAULT); - if (ret_val) - return ret_val; - - ret_val = e1000_write_phy_reg(hw, 0x0000, - IGP01E1000_IEEE_RESTART_AUTONEG); - if (ret_val) - return ret_val; - - msleep(20); - - /* Now enable the transmitter */ - ret_val = - e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data); - - if (ret_val) - return ret_val; - - hw->ffe_config_state = e1000_ffe_config_enabled; - } - } - return E1000_SUCCESS; -} - -/** - * e1000_set_phy_mode - Set PHY to class A mode - * @hw: Struct containing variables accessed by shared code - * - * Assumes the following operations will follow to enable the new class mode. - * 1. Do a PHY soft reset - * 2. Restart auto-negotiation or force link. - */ -static s32 e1000_set_phy_mode(struct e1000_hw *hw) -{ - s32 ret_val; - u16 eeprom_data; - - if ((hw->mac_type == e1000_82545_rev_3) && - (hw->media_type == e1000_media_type_copper)) { - ret_val = - e1000_read_eeprom(hw, EEPROM_PHY_CLASS_WORD, 1, - &eeprom_data); - if (ret_val) { - return ret_val; - } - - if ((eeprom_data != EEPROM_RESERVED_WORD) && - (eeprom_data & EEPROM_PHY_CLASS_A)) { - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, - 0x000B); - if (ret_val) - return ret_val; - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, - 0x8104); - if (ret_val) - return ret_val; - - hw->phy_reset_disable = false; - } - } - - return E1000_SUCCESS; -} - -/** - * e1000_set_d3_lplu_state - set d3 link power state - * @hw: Struct containing variables accessed by shared code - * @active: true to enable lplu false to disable lplu. - * - * This function sets the lplu state according to the active flag. When - * activating lplu this function also disables smart speed and vise versa. - * lplu will not be activated unless the device autonegotiation advertisement - * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes. - * - * returns: - E1000_ERR_PHY if fail to read/write the PHY - * E1000_SUCCESS at any other case. - */ -static s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active) -{ - s32 ret_val; - u16 phy_data; - - if (hw->phy_type != e1000_phy_igp) - return E1000_SUCCESS; - - /* During driver activity LPLU should not be used or it will attain link - * from the lowest speeds starting from 10Mbps. The capability is used - * for Dx transitions and states - */ - if (hw->mac_type == e1000_82541_rev_2 - || hw->mac_type == e1000_82547_rev_2) { - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data); - if (ret_val) - return ret_val; - } - - if (!active) { - if (hw->mac_type == e1000_82541_rev_2 || - hw->mac_type == e1000_82547_rev_2) { - phy_data &= ~IGP01E1000_GMII_FLEX_SPD; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, - phy_data); - if (ret_val) - return ret_val; - } - - /* LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (hw->smart_speed == e1000_smart_speed_on) { - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data); - if (ret_val) - return ret_val; - - phy_data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - phy_data); - if (ret_val) - return ret_val; - } else if (hw->smart_speed == e1000_smart_speed_off) { - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - phy_data); - if (ret_val) - return ret_val; - } - } else if ((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) - || (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL) - || (hw->autoneg_advertised == - AUTONEG_ADVERTISE_10_100_ALL)) { - - if (hw->mac_type == e1000_82541_rev_2 || - hw->mac_type == e1000_82547_rev_2) { - phy_data |= IGP01E1000_GMII_FLEX_SPD; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, - phy_data); - if (ret_val) - return ret_val; - } - - /* When LPLU is enabled we should disable SmartSpeed */ - ret_val = - e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = - e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, - phy_data); - if (ret_val) - return ret_val; - - } - return E1000_SUCCESS; -} - -/** - * e1000_set_vco_speed - * @hw: Struct containing variables accessed by shared code - * - * Change VCO speed register to improve Bit Error Rate performance of SERDES. - */ -static s32 e1000_set_vco_speed(struct e1000_hw *hw) -{ - s32 ret_val; - u16 default_page = 0; - u16 phy_data; - - switch (hw->mac_type) { - case e1000_82545_rev_3: - case e1000_82546_rev_3: - break; - default: - return E1000_SUCCESS; - } - - /* Set PHY register 30, page 5, bit 8 to 0 */ - - ret_val = - e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page); - if (ret_val) - return ret_val; - - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005); - if (ret_val) - return ret_val; - - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~M88E1000_PHY_VCO_REG_BIT8; - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); - if (ret_val) - return ret_val; - - /* Set PHY register 30, page 4, bit 11 to 1 */ - - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004); - if (ret_val) - return ret_val; - - ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_PHY_VCO_REG_BIT11; - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); - if (ret_val) - return ret_val; - - ret_val = - e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page); - if (ret_val) - return ret_val; - - return E1000_SUCCESS; -} - - -/** - * e1000_enable_mng_pass_thru - check for bmc pass through - * @hw: Struct containing variables accessed by shared code - * - * Verifies the hardware needs to allow ARPs to be processed by the host - * returns: - true/false - */ -u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw) -{ - u32 manc; - - if (hw->asf_firmware_present) { - manc = er32(MANC); - - if (!(manc & E1000_MANC_RCV_TCO_EN) || - !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) - return false; - if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN)) - return true; - } - return false; -} - -static s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw) -{ - s32 ret_val; - u16 mii_status_reg; - u16 i; - - /* Polarity reversal workaround for forced 10F/10H links. */ - - /* Disable the transmitter on the PHY */ - - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); - if (ret_val) - return ret_val; - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF); - if (ret_val) - return ret_val; - - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); - if (ret_val) - return ret_val; - - /* This loop will early-out if the NO link condition has been met. */ - for (i = PHY_FORCE_TIME; i > 0; i--) { - /* Read the MII Status Register and wait for Link Status bit - * to be clear. - */ - - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0) - break; - msleep(100); - } - - /* Recommended delay time after link has been lost */ - msleep(1000); - - /* Now we will re-enable th transmitter on the PHY */ - - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); - if (ret_val) - return ret_val; - msleep(50); - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0); - if (ret_val) - return ret_val; - msleep(50); - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00); - if (ret_val) - return ret_val; - msleep(50); - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000); - if (ret_val) - return ret_val; - - ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); - if (ret_val) - return ret_val; - - /* This loop will early-out if the link condition has been met. */ - for (i = PHY_FORCE_TIME; i > 0; i--) { - /* Read the MII Status Register and wait for Link Status bit - * to be set. - */ - - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); - if (ret_val) - return ret_val; - - if (mii_status_reg & MII_SR_LINK_STATUS) - break; - msleep(100); - } - return E1000_SUCCESS; -} - -/** - * e1000_get_auto_rd_done - * @hw: Struct containing variables accessed by shared code - * - * Check for EEPROM Auto Read bit done. - * returns: - E1000_ERR_RESET if fail to reset MAC - * E1000_SUCCESS at any other case. - */ -static s32 e1000_get_auto_rd_done(struct e1000_hw *hw) -{ - msleep(5); - return E1000_SUCCESS; -} - -/** - * e1000_get_phy_cfg_done - * @hw: Struct containing variables accessed by shared code - * - * Checks if the PHY configuration is done - * returns: - E1000_ERR_RESET if fail to reset MAC - * E1000_SUCCESS at any other case. - */ -static s32 e1000_get_phy_cfg_done(struct e1000_hw *hw) -{ - msleep(10); - return E1000_SUCCESS; -} diff --git a/addons/e1000/src/4.4.180/e1000_hw.h b/addons/e1000/src/4.4.180/e1000_hw.h deleted file mode 100644 index 5cf7268c..00000000 --- a/addons/e1000/src/4.4.180/e1000_hw.h +++ /dev/null @@ -1,3110 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* e1000_hw.h - * Structures, enums, and macros for the MAC - */ - -#ifndef _E1000_HW_H_ -#define _E1000_HW_H_ - -#include "e1000_osdep.h" - - -/* Forward declarations of structures used by the shared code */ -struct e1000_hw; -struct e1000_hw_stats; - -/* Enumerated types specific to the e1000 hardware */ -/* Media Access Controllers */ -typedef enum { - e1000_undefined = 0, - e1000_82542_rev2_0, - e1000_82542_rev2_1, - e1000_82543, - e1000_82544, - e1000_82540, - e1000_82545, - e1000_82545_rev_3, - e1000_82546, - e1000_ce4100, - e1000_82546_rev_3, - e1000_82541, - e1000_82541_rev_2, - e1000_82547, - e1000_82547_rev_2, - e1000_num_macs -} e1000_mac_type; - -typedef enum { - e1000_eeprom_uninitialized = 0, - e1000_eeprom_spi, - e1000_eeprom_microwire, - e1000_eeprom_flash, - e1000_eeprom_none, /* No NVM support */ - e1000_num_eeprom_types -} e1000_eeprom_type; - -/* Media Types */ -typedef enum { - e1000_media_type_copper = 0, - e1000_media_type_fiber = 1, - e1000_media_type_internal_serdes = 2, - e1000_num_media_types -} e1000_media_type; - -typedef enum { - e1000_10_half = 0, - e1000_10_full = 1, - e1000_100_half = 2, - e1000_100_full = 3 -} e1000_speed_duplex_type; - -/* Flow Control Settings */ -typedef enum { - E1000_FC_NONE = 0, - E1000_FC_RX_PAUSE = 1, - E1000_FC_TX_PAUSE = 2, - E1000_FC_FULL = 3, - E1000_FC_DEFAULT = 0xFF -} e1000_fc_type; - -struct e1000_shadow_ram { - u16 eeprom_word; - bool modified; -}; - -/* PCI bus types */ -typedef enum { - e1000_bus_type_unknown = 0, - e1000_bus_type_pci, - e1000_bus_type_pcix, - e1000_bus_type_reserved -} e1000_bus_type; - -/* PCI bus speeds */ -typedef enum { - e1000_bus_speed_unknown = 0, - e1000_bus_speed_33, - e1000_bus_speed_66, - e1000_bus_speed_100, - e1000_bus_speed_120, - e1000_bus_speed_133, - e1000_bus_speed_reserved -} e1000_bus_speed; - -/* PCI bus widths */ -typedef enum { - e1000_bus_width_unknown = 0, - e1000_bus_width_32, - e1000_bus_width_64, - e1000_bus_width_reserved -} e1000_bus_width; - -/* PHY status info structure and supporting enums */ -typedef enum { - e1000_cable_length_50 = 0, - e1000_cable_length_50_80, - e1000_cable_length_80_110, - e1000_cable_length_110_140, - e1000_cable_length_140, - e1000_cable_length_undefined = 0xFF -} e1000_cable_length; - -typedef enum { - e1000_gg_cable_length_60 = 0, - e1000_gg_cable_length_60_115 = 1, - e1000_gg_cable_length_115_150 = 2, - e1000_gg_cable_length_150 = 4 -} e1000_gg_cable_length; - -typedef enum { - e1000_igp_cable_length_10 = 10, - e1000_igp_cable_length_20 = 20, - e1000_igp_cable_length_30 = 30, - e1000_igp_cable_length_40 = 40, - e1000_igp_cable_length_50 = 50, - e1000_igp_cable_length_60 = 60, - e1000_igp_cable_length_70 = 70, - e1000_igp_cable_length_80 = 80, - e1000_igp_cable_length_90 = 90, - e1000_igp_cable_length_100 = 100, - e1000_igp_cable_length_110 = 110, - e1000_igp_cable_length_115 = 115, - e1000_igp_cable_length_120 = 120, - e1000_igp_cable_length_130 = 130, - e1000_igp_cable_length_140 = 140, - e1000_igp_cable_length_150 = 150, - e1000_igp_cable_length_160 = 160, - e1000_igp_cable_length_170 = 170, - e1000_igp_cable_length_180 = 180 -} e1000_igp_cable_length; - -typedef enum { - e1000_10bt_ext_dist_enable_normal = 0, - e1000_10bt_ext_dist_enable_lower, - e1000_10bt_ext_dist_enable_undefined = 0xFF -} e1000_10bt_ext_dist_enable; - -typedef enum { - e1000_rev_polarity_normal = 0, - e1000_rev_polarity_reversed, - e1000_rev_polarity_undefined = 0xFF -} e1000_rev_polarity; - -typedef enum { - e1000_downshift_normal = 0, - e1000_downshift_activated, - e1000_downshift_undefined = 0xFF -} e1000_downshift; - -typedef enum { - e1000_smart_speed_default = 0, - e1000_smart_speed_on, - e1000_smart_speed_off -} e1000_smart_speed; - -typedef enum { - e1000_polarity_reversal_enabled = 0, - e1000_polarity_reversal_disabled, - e1000_polarity_reversal_undefined = 0xFF -} e1000_polarity_reversal; - -typedef enum { - e1000_auto_x_mode_manual_mdi = 0, - e1000_auto_x_mode_manual_mdix, - e1000_auto_x_mode_auto1, - e1000_auto_x_mode_auto2, - e1000_auto_x_mode_undefined = 0xFF -} e1000_auto_x_mode; - -typedef enum { - e1000_1000t_rx_status_not_ok = 0, - e1000_1000t_rx_status_ok, - e1000_1000t_rx_status_undefined = 0xFF -} e1000_1000t_rx_status; - -typedef enum { - e1000_phy_m88 = 0, - e1000_phy_igp, - e1000_phy_8211, - e1000_phy_8201, - e1000_phy_undefined = 0xFF -} e1000_phy_type; - -typedef enum { - e1000_ms_hw_default = 0, - e1000_ms_force_master, - e1000_ms_force_slave, - e1000_ms_auto -} e1000_ms_type; - -typedef enum { - e1000_ffe_config_enabled = 0, - e1000_ffe_config_active, - e1000_ffe_config_blocked -} e1000_ffe_config; - -typedef enum { - e1000_dsp_config_disabled = 0, - e1000_dsp_config_enabled, - e1000_dsp_config_activated, - e1000_dsp_config_undefined = 0xFF -} e1000_dsp_config; - -struct e1000_phy_info { - e1000_cable_length cable_length; - e1000_10bt_ext_dist_enable extended_10bt_distance; - e1000_rev_polarity cable_polarity; - e1000_downshift downshift; - e1000_polarity_reversal polarity_correction; - e1000_auto_x_mode mdix_mode; - e1000_1000t_rx_status local_rx; - e1000_1000t_rx_status remote_rx; -}; - -struct e1000_phy_stats { - u32 idle_errors; - u32 receive_errors; -}; - -struct e1000_eeprom_info { - e1000_eeprom_type type; - u16 word_size; - u16 opcode_bits; - u16 address_bits; - u16 delay_usec; - u16 page_size; -}; - -/* Flex ASF Information */ -#define E1000_HOST_IF_MAX_SIZE 2048 - -typedef enum { - e1000_byte_align = 0, - e1000_word_align = 1, - e1000_dword_align = 2 -} e1000_align_type; - -/* Error Codes */ -#define E1000_SUCCESS 0 -#define E1000_ERR_EEPROM 1 -#define E1000_ERR_PHY 2 -#define E1000_ERR_CONFIG 3 -#define E1000_ERR_PARAM 4 -#define E1000_ERR_MAC_TYPE 5 -#define E1000_ERR_PHY_TYPE 6 -#define E1000_ERR_RESET 9 -#define E1000_ERR_MASTER_REQUESTS_PENDING 10 -#define E1000_ERR_HOST_INTERFACE_COMMAND 11 -#define E1000_BLK_PHY_RESET 12 - -#define E1000_BYTE_SWAP_WORD(_value) ((((_value) & 0x00ff) << 8) | \ - (((_value) & 0xff00) >> 8)) - -/* Function prototypes */ -/* Initialization */ -s32 e1000_reset_hw(struct e1000_hw *hw); -s32 e1000_init_hw(struct e1000_hw *hw); -s32 e1000_set_mac_type(struct e1000_hw *hw); -void e1000_set_media_type(struct e1000_hw *hw); - -/* Link Configuration */ -s32 e1000_setup_link(struct e1000_hw *hw); -s32 e1000_phy_setup_autoneg(struct e1000_hw *hw); -void e1000_config_collision_dist(struct e1000_hw *hw); -s32 e1000_check_for_link(struct e1000_hw *hw); -s32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 * speed, u16 * duplex); -s32 e1000_force_mac_fc(struct e1000_hw *hw); - -/* PHY */ -s32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 * phy_data); -s32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 data); -s32 e1000_phy_hw_reset(struct e1000_hw *hw); -s32 e1000_phy_reset(struct e1000_hw *hw); -s32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info); -s32 e1000_validate_mdi_setting(struct e1000_hw *hw); - -/* EEPROM Functions */ -s32 e1000_init_eeprom_params(struct e1000_hw *hw); - -/* MNG HOST IF functions */ -u32 e1000_enable_mng_pass_thru(struct e1000_hw *hw); - -#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64 -#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 /* Host Interface data length */ - -#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 /* Time in ms to process MNG command */ -#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 /* Cookie offset */ -#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 /* Cookie length */ -#define E1000_MNG_IAMT_MODE 0x3 -#define E1000_MNG_ICH_IAMT_MODE 0x2 -#define E1000_IAMT_SIGNATURE 0x544D4149 /* Intel(R) Active Management Technology signature */ - -#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING_SUPPORT 0x1 /* DHCP parsing enabled */ -#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT 0x2 /* DHCP parsing enabled */ -#define E1000_VFTA_ENTRY_SHIFT 0x5 -#define E1000_VFTA_ENTRY_MASK 0x7F -#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F - -struct e1000_host_mng_command_header { - u8 command_id; - u8 checksum; - u16 reserved1; - u16 reserved2; - u16 command_length; -}; - -struct e1000_host_mng_command_info { - struct e1000_host_mng_command_header command_header; /* Command Head/Command Result Head has 4 bytes */ - u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; /* Command data can length 0..0x658 */ -}; -#ifdef __BIG_ENDIAN -struct e1000_host_mng_dhcp_cookie { - u32 signature; - u16 vlan_id; - u8 reserved0; - u8 status; - u32 reserved1; - u8 checksum; - u8 reserved3; - u16 reserved2; -}; -#else -struct e1000_host_mng_dhcp_cookie { - u32 signature; - u8 status; - u8 reserved0; - u16 vlan_id; - u32 reserved1; - u16 reserved2; - u8 reserved3; - u8 checksum; -}; -#endif - -bool e1000_check_mng_mode(struct e1000_hw *hw); -s32 e1000_read_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 * data); -s32 e1000_validate_eeprom_checksum(struct e1000_hw *hw); -s32 e1000_update_eeprom_checksum(struct e1000_hw *hw); -s32 e1000_write_eeprom(struct e1000_hw *hw, u16 reg, u16 words, u16 * data); -s32 e1000_read_mac_addr(struct e1000_hw *hw); - -/* Filters (multicast, vlan, receive) */ -u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 * mc_addr); -void e1000_mta_set(struct e1000_hw *hw, u32 hash_value); -void e1000_rar_set(struct e1000_hw *hw, u8 * mc_addr, u32 rar_index); -void e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value); - -/* LED functions */ -s32 e1000_setup_led(struct e1000_hw *hw); -s32 e1000_cleanup_led(struct e1000_hw *hw); -s32 e1000_led_on(struct e1000_hw *hw); -s32 e1000_led_off(struct e1000_hw *hw); -s32 e1000_blink_led_start(struct e1000_hw *hw); - -/* Adaptive IFS Functions */ - -/* Everything else */ -void e1000_reset_adaptive(struct e1000_hw *hw); -void e1000_update_adaptive(struct e1000_hw *hw); -void e1000_get_bus_info(struct e1000_hw *hw); -void e1000_pci_set_mwi(struct e1000_hw *hw); -void e1000_pci_clear_mwi(struct e1000_hw *hw); -void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc); -int e1000_pcix_get_mmrbc(struct e1000_hw *hw); -/* Port I/O is only supported on 82544 and newer */ -void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value); - -#define E1000_READ_REG_IO(a, reg) \ - e1000_read_reg_io((a), E1000_##reg) -#define E1000_WRITE_REG_IO(a, reg, val) \ - e1000_write_reg_io((a), E1000_##reg, val) - -/* PCI Device IDs */ -#define E1000_DEV_ID_82542 0x1000 -#define E1000_DEV_ID_82543GC_FIBER 0x1001 -#define E1000_DEV_ID_82543GC_COPPER 0x1004 -#define E1000_DEV_ID_82544EI_COPPER 0x1008 -#define E1000_DEV_ID_82544EI_FIBER 0x1009 -#define E1000_DEV_ID_82544GC_COPPER 0x100C -#define E1000_DEV_ID_82544GC_LOM 0x100D -#define E1000_DEV_ID_82540EM 0x100E -#define E1000_DEV_ID_82540EM_LOM 0x1015 -#define E1000_DEV_ID_82540EP_LOM 0x1016 -#define E1000_DEV_ID_82540EP 0x1017 -#define E1000_DEV_ID_82540EP_LP 0x101E -#define E1000_DEV_ID_82545EM_COPPER 0x100F -#define E1000_DEV_ID_82545EM_FIBER 0x1011 -#define E1000_DEV_ID_82545GM_COPPER 0x1026 -#define E1000_DEV_ID_82545GM_FIBER 0x1027 -#define E1000_DEV_ID_82545GM_SERDES 0x1028 -#define E1000_DEV_ID_82546EB_COPPER 0x1010 -#define E1000_DEV_ID_82546EB_FIBER 0x1012 -#define E1000_DEV_ID_82546EB_QUAD_COPPER 0x101D -#define E1000_DEV_ID_82541EI 0x1013 -#define E1000_DEV_ID_82541EI_MOBILE 0x1018 -#define E1000_DEV_ID_82541ER_LOM 0x1014 -#define E1000_DEV_ID_82541ER 0x1078 -#define E1000_DEV_ID_82547GI 0x1075 -#define E1000_DEV_ID_82541GI 0x1076 -#define E1000_DEV_ID_82541GI_MOBILE 0x1077 -#define E1000_DEV_ID_82541GI_LF 0x107C -#define E1000_DEV_ID_82546GB_COPPER 0x1079 -#define E1000_DEV_ID_82546GB_FIBER 0x107A -#define E1000_DEV_ID_82546GB_SERDES 0x107B -#define E1000_DEV_ID_82546GB_PCIE 0x108A -#define E1000_DEV_ID_82546GB_QUAD_COPPER 0x1099 -#define E1000_DEV_ID_82547EI 0x1019 -#define E1000_DEV_ID_82547EI_MOBILE 0x101A -#define E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3 0x10B5 -#define E1000_DEV_ID_INTEL_CE4100_GBE 0x2E6E - -#define NODE_ADDRESS_SIZE 6 - -/* MAC decode size is 128K - This is the size of BAR0 */ -#define MAC_DECODE_SIZE (128 * 1024) - -#define E1000_82542_2_0_REV_ID 2 -#define E1000_82542_2_1_REV_ID 3 -#define E1000_REVISION_0 0 -#define E1000_REVISION_1 1 -#define E1000_REVISION_2 2 -#define E1000_REVISION_3 3 - -#define SPEED_10 10 -#define SPEED_100 100 -#define SPEED_1000 1000 -#define HALF_DUPLEX 1 -#define FULL_DUPLEX 2 - -/* The sizes (in bytes) of a ethernet packet */ -#define ENET_HEADER_SIZE 14 -#define MINIMUM_ETHERNET_FRAME_SIZE 64 /* With FCS */ -#define ETHERNET_FCS_SIZE 4 -#define MINIMUM_ETHERNET_PACKET_SIZE \ - (MINIMUM_ETHERNET_FRAME_SIZE - ETHERNET_FCS_SIZE) -#define CRC_LENGTH ETHERNET_FCS_SIZE -#define MAX_JUMBO_FRAME_SIZE 0x3F00 - -/* 802.1q VLAN Packet Sizes */ -#define VLAN_TAG_SIZE 4 /* 802.3ac tag (not DMAed) */ - -/* Ethertype field values */ -#define ETHERNET_IEEE_VLAN_TYPE 0x8100 /* 802.3ac packet */ -#define ETHERNET_IP_TYPE 0x0800 /* IP packets */ -#define ETHERNET_ARP_TYPE 0x0806 /* Address Resolution Protocol (ARP) */ - -/* Packet Header defines */ -#define IP_PROTOCOL_TCP 6 -#define IP_PROTOCOL_UDP 0x11 - -/* This defines the bits that are set in the Interrupt Mask - * Set/Read Register. Each bit is documented below: - * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) - * o RXSEQ = Receive Sequence Error - */ -#define POLL_IMS_ENABLE_MASK ( \ - E1000_IMS_RXDMT0 | \ - E1000_IMS_RXSEQ) - -/* This defines the bits that are set in the Interrupt Mask - * Set/Read Register. Each bit is documented below: - * o RXT0 = Receiver Timer Interrupt (ring 0) - * o TXDW = Transmit Descriptor Written Back - * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) - * o RXSEQ = Receive Sequence Error - * o LSC = Link Status Change - */ -#define IMS_ENABLE_MASK ( \ - E1000_IMS_RXT0 | \ - E1000_IMS_TXDW | \ - E1000_IMS_RXDMT0 | \ - E1000_IMS_RXSEQ | \ - E1000_IMS_LSC) - -/* Number of high/low register pairs in the RAR. The RAR (Receive Address - * Registers) holds the directed and multicast addresses that we monitor. We - * reserve one of these spots for our directed address, allowing us room for - * E1000_RAR_ENTRIES - 1 multicast addresses. - */ -#define E1000_RAR_ENTRIES 15 - -#define MIN_NUMBER_OF_DESCRIPTORS 8 -#define MAX_NUMBER_OF_DESCRIPTORS 0xFFF8 - -/* Receive Descriptor */ -struct e1000_rx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - __le16 length; /* Length of data DMAed into data buffer */ - __le16 csum; /* Packet checksum */ - u8 status; /* Descriptor status */ - u8 errors; /* Descriptor Errors */ - __le16 special; -}; - -/* Receive Descriptor - Extended */ -union e1000_rx_desc_extended { - struct { - __le64 buffer_addr; - __le64 reserved; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length; - __le16 vlan; /* VLAN tag */ - } upper; - } wb; /* writeback */ -}; - -#define MAX_PS_BUFFERS 4 -/* Receive Descriptor - Packet Split */ -union e1000_rx_desc_packet_split { - struct { - /* one buffer for protocol header(s), three data buffers */ - __le64 buffer_addr[MAX_PS_BUFFERS]; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length0; /* length of buffer 0 */ - __le16 vlan; /* VLAN tag */ - } middle; - struct { - __le16 header_status; - __le16 length[3]; /* length of buffers 1-3 */ - } upper; - __le64 reserved; - } wb; /* writeback */ -}; - -/* Receive Descriptor bit definitions */ -#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ -#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */ -#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */ -#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ -#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ -#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ -#define E1000_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ -#define E1000_RXD_STAT_PIF 0x80 /* passed in-exact filter */ -#define E1000_RXD_STAT_IPIDV 0x200 /* IP identification valid */ -#define E1000_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */ -#define E1000_RXD_STAT_ACK 0x8000 /* ACK Packet indication */ -#define E1000_RXD_ERR_CE 0x01 /* CRC Error */ -#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ -#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ -#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */ -#define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */ -#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */ -#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ -#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ -#define E1000_RXD_SPC_PRI_MASK 0xE000 /* Priority is in upper 3 bits */ -#define E1000_RXD_SPC_PRI_SHIFT 13 -#define E1000_RXD_SPC_CFI_MASK 0x1000 /* CFI is bit 12 */ -#define E1000_RXD_SPC_CFI_SHIFT 12 - -#define E1000_RXDEXT_STATERR_CE 0x01000000 -#define E1000_RXDEXT_STATERR_SE 0x02000000 -#define E1000_RXDEXT_STATERR_SEQ 0x04000000 -#define E1000_RXDEXT_STATERR_CXE 0x10000000 -#define E1000_RXDEXT_STATERR_TCPE 0x20000000 -#define E1000_RXDEXT_STATERR_IPE 0x40000000 -#define E1000_RXDEXT_STATERR_RXE 0x80000000 - -#define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000 -#define E1000_RXDPS_HDRSTAT_HDRLEN_MASK 0x000003FF - -/* mask to determine if packets should be dropped due to frame errors */ -#define E1000_RXD_ERR_FRAME_ERR_MASK ( \ - E1000_RXD_ERR_CE | \ - E1000_RXD_ERR_SE | \ - E1000_RXD_ERR_SEQ | \ - E1000_RXD_ERR_CXE | \ - E1000_RXD_ERR_RXE) - -/* Same mask, but for extended and packet split descriptors */ -#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \ - E1000_RXDEXT_STATERR_CE | \ - E1000_RXDEXT_STATERR_SE | \ - E1000_RXDEXT_STATERR_SEQ | \ - E1000_RXDEXT_STATERR_CXE | \ - E1000_RXDEXT_STATERR_RXE) - -/* Transmit Descriptor */ -struct e1000_tx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 cso; /* Checksum offset */ - u8 cmd; /* Descriptor control */ - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 css; /* Checksum start */ - __le16 special; - } fields; - } upper; -}; - -/* Transmit Descriptor bit definitions */ -#define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */ -#define E1000_TXD_DTYP_C 0x00000000 /* Context Descriptor */ -#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ -#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ -#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ -#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ -#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */ -#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */ -#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */ -#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */ -#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ -#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */ -#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */ -#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */ -#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */ -#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */ -#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */ -#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ -#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ -#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ - -/* Offload Context Descriptor */ -struct e1000_context_desc { - union { - __le32 ip_config; - struct { - u8 ipcss; /* IP checksum start */ - u8 ipcso; /* IP checksum offset */ - __le16 ipcse; /* IP checksum end */ - } ip_fields; - } lower_setup; - union { - __le32 tcp_config; - struct { - u8 tucss; /* TCP checksum start */ - u8 tucso; /* TCP checksum offset */ - __le16 tucse; /* TCP checksum end */ - } tcp_fields; - } upper_setup; - __le32 cmd_and_length; /* */ - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 hdr_len; /* Header length */ - __le16 mss; /* Maximum segment size */ - } fields; - } tcp_seg_setup; -}; - -/* Offload data descriptor */ -struct e1000_data_desc { - __le64 buffer_addr; /* Address of the descriptor's buffer address */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 typ_len_ext; /* */ - u8 cmd; /* */ - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 popts; /* Packet Options */ - __le16 special; /* */ - } fields; - } upper; -}; - -/* Filters */ -#define E1000_NUM_UNICAST 16 /* Unicast filter entries */ -#define E1000_MC_TBL_SIZE 128 /* Multicast Filter Table (4096 bits) */ -#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ - -/* Receive Address Register */ -struct e1000_rar { - volatile __le32 low; /* receive address low */ - volatile __le32 high; /* receive address high */ -}; - -/* Number of entries in the Multicast Table Array (MTA). */ -#define E1000_NUM_MTA_REGISTERS 128 - -/* IPv4 Address Table Entry */ -struct e1000_ipv4_at_entry { - volatile u32 ipv4_addr; /* IP Address (RW) */ - volatile u32 reserved; -}; - -/* Four wakeup IP addresses are supported */ -#define E1000_WAKEUP_IP_ADDRESS_COUNT_MAX 4 -#define E1000_IP4AT_SIZE E1000_WAKEUP_IP_ADDRESS_COUNT_MAX -#define E1000_IP6AT_SIZE 1 - -/* IPv6 Address Table Entry */ -struct e1000_ipv6_at_entry { - volatile u8 ipv6_addr[16]; -}; - -/* Flexible Filter Length Table Entry */ -struct e1000_fflt_entry { - volatile u32 length; /* Flexible Filter Length (RW) */ - volatile u32 reserved; -}; - -/* Flexible Filter Mask Table Entry */ -struct e1000_ffmt_entry { - volatile u32 mask; /* Flexible Filter Mask (RW) */ - volatile u32 reserved; -}; - -/* Flexible Filter Value Table Entry */ -struct e1000_ffvt_entry { - volatile u32 value; /* Flexible Filter Value (RW) */ - volatile u32 reserved; -}; - -/* Four Flexible Filters are supported */ -#define E1000_FLEXIBLE_FILTER_COUNT_MAX 4 - -/* Each Flexible Filter is at most 128 (0x80) bytes in length */ -#define E1000_FLEXIBLE_FILTER_SIZE_MAX 128 - -#define E1000_FFLT_SIZE E1000_FLEXIBLE_FILTER_COUNT_MAX -#define E1000_FFMT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX -#define E1000_FFVT_SIZE E1000_FLEXIBLE_FILTER_SIZE_MAX - -#define E1000_DISABLE_SERDES_LOOPBACK 0x0400 - -/* Register Set. (82543, 82544) - * - * Registers are defined to be 32 bits and should be accessed as 32 bit values. - * These registers are physically located on the NIC, but are mapped into the - * host memory address space. - * - * RW - register is both readable and writable - * RO - register is read only - * WO - register is write only - * R/clr - register is read only and is cleared when read - * A - register array - */ -#define E1000_CTRL 0x00000 /* Device Control - RW */ -#define E1000_CTRL_DUP 0x00004 /* Device Control Duplicate (Shadow) - RW */ -#define E1000_STATUS 0x00008 /* Device Status - RO */ -#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ -#define E1000_EERD 0x00014 /* EEPROM Read - RW */ -#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ -#define E1000_FLA 0x0001C /* Flash Access - RW */ -#define E1000_MDIC 0x00020 /* MDI Control - RW */ - -#define INTEL_CE_GBE_MDIO_RCOMP_BASE (hw->ce4100_gbe_mdio_base_virt) -#define E1000_MDIO_STS (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0) -#define E1000_MDIO_CMD (INTEL_CE_GBE_MDIO_RCOMP_BASE + 4) -#define E1000_MDIO_DRV (INTEL_CE_GBE_MDIO_RCOMP_BASE + 8) -#define E1000_MDC_CMD (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0xC) -#define E1000_RCOMP_CTL (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0x20) -#define E1000_RCOMP_STS (INTEL_CE_GBE_MDIO_RCOMP_BASE + 0x24) - -#define E1000_SCTL 0x00024 /* SerDes Control - RW */ -#define E1000_FEXTNVM 0x00028 /* Future Extended NVM register */ -#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ -#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ -#define E1000_FCT 0x00030 /* Flow Control Type - RW */ -#define E1000_VET 0x00038 /* VLAN Ether Type - RW */ -#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ -#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ -#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ -#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ -#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ -#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ - -/* Auxiliary Control Register. This register is CE4100 specific, - * RMII/RGMII function is switched by this register - RW - * Following are bits definitions of the Auxiliary Control Register - */ -#define E1000_CTL_AUX 0x000E0 -#define E1000_CTL_AUX_END_SEL_SHIFT 10 -#define E1000_CTL_AUX_ENDIANESS_SHIFT 8 -#define E1000_CTL_AUX_RGMII_RMII_SHIFT 0 - -/* descriptor and packet transfer use CTL_AUX.ENDIANESS */ -#define E1000_CTL_AUX_DES_PKT (0x0 << E1000_CTL_AUX_END_SEL_SHIFT) -/* descriptor use CTL_AUX.ENDIANESS, packet use default */ -#define E1000_CTL_AUX_DES (0x1 << E1000_CTL_AUX_END_SEL_SHIFT) -/* descriptor use default, packet use CTL_AUX.ENDIANESS */ -#define E1000_CTL_AUX_PKT (0x2 << E1000_CTL_AUX_END_SEL_SHIFT) -/* all use CTL_AUX.ENDIANESS */ -#define E1000_CTL_AUX_ALL (0x3 << E1000_CTL_AUX_END_SEL_SHIFT) - -#define E1000_CTL_AUX_RGMII (0x0 << E1000_CTL_AUX_RGMII_RMII_SHIFT) -#define E1000_CTL_AUX_RMII (0x1 << E1000_CTL_AUX_RGMII_RMII_SHIFT) - -/* LW little endian, Byte big endian */ -#define E1000_CTL_AUX_LWLE_BBE (0x0 << E1000_CTL_AUX_ENDIANESS_SHIFT) -#define E1000_CTL_AUX_LWLE_BLE (0x1 << E1000_CTL_AUX_ENDIANESS_SHIFT) -#define E1000_CTL_AUX_LWBE_BBE (0x2 << E1000_CTL_AUX_ENDIANESS_SHIFT) -#define E1000_CTL_AUX_LWBE_BLE (0x3 << E1000_CTL_AUX_ENDIANESS_SHIFT) - -#define E1000_RCTL 0x00100 /* RX Control - RW */ -#define E1000_RDTR1 0x02820 /* RX Delay Timer (1) - RW */ -#define E1000_RDBAL1 0x02900 /* RX Descriptor Base Address Low (1) - RW */ -#define E1000_RDBAH1 0x02904 /* RX Descriptor Base Address High (1) - RW */ -#define E1000_RDLEN1 0x02908 /* RX Descriptor Length (1) - RW */ -#define E1000_RDH1 0x02910 /* RX Descriptor Head (1) - RW */ -#define E1000_RDT1 0x02918 /* RX Descriptor Tail (1) - RW */ -#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ -#define E1000_TXCW 0x00178 /* TX Configuration Word - RW */ -#define E1000_RXCW 0x00180 /* RX Configuration Word - RO */ -#define E1000_TCTL 0x00400 /* TX Control - RW */ -#define E1000_TCTL_EXT 0x00404 /* Extended TX Control - RW */ -#define E1000_TIPG 0x00410 /* TX Inter-packet gap -RW */ -#define E1000_TBT 0x00448 /* TX Burst Timer - RW */ -#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ -#define E1000_LEDCTL 0x00E00 /* LED Control - RW */ -#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */ -#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */ -#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */ -#define FEXTNVM_SW_CONFIG 0x0001 -#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ -#define E1000_PBS 0x01008 /* Packet Buffer Size */ -#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ -#define E1000_FLASH_UPDATES 1000 -#define E1000_EEARBC 0x01024 /* EEPROM Auto Read Bus Control */ -#define E1000_FLASHT 0x01028 /* FLASH Timer Register */ -#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */ -#define E1000_FLSWCTL 0x01030 /* FLASH control register */ -#define E1000_FLSWDATA 0x01034 /* FLASH data register */ -#define E1000_FLSWCNT 0x01038 /* FLASH Access Counter */ -#define E1000_FLOP 0x0103C /* FLASH Opcode Register */ -#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ -#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ -#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ -#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */ -#define E1000_RDFH 0x02410 /* RX Data FIFO Head - RW */ -#define E1000_RDFT 0x02418 /* RX Data FIFO Tail - RW */ -#define E1000_RDFHS 0x02420 /* RX Data FIFO Head Saved - RW */ -#define E1000_RDFTS 0x02428 /* RX Data FIFO Tail Saved - RW */ -#define E1000_RDFPC 0x02430 /* RX Data FIFO Packet Count - RW */ -#define E1000_RDBAL 0x02800 /* RX Descriptor Base Address Low - RW */ -#define E1000_RDBAH 0x02804 /* RX Descriptor Base Address High - RW */ -#define E1000_RDLEN 0x02808 /* RX Descriptor Length - RW */ -#define E1000_RDH 0x02810 /* RX Descriptor Head - RW */ -#define E1000_RDT 0x02818 /* RX Descriptor Tail - RW */ -#define E1000_RDTR 0x02820 /* RX Delay Timer - RW */ -#define E1000_RDBAL0 E1000_RDBAL /* RX Desc Base Address Low (0) - RW */ -#define E1000_RDBAH0 E1000_RDBAH /* RX Desc Base Address High (0) - RW */ -#define E1000_RDLEN0 E1000_RDLEN /* RX Desc Length (0) - RW */ -#define E1000_RDH0 E1000_RDH /* RX Desc Head (0) - RW */ -#define E1000_RDT0 E1000_RDT /* RX Desc Tail (0) - RW */ -#define E1000_RDTR0 E1000_RDTR /* RX Delay Timer (0) - RW */ -#define E1000_RXDCTL 0x02828 /* RX Descriptor Control queue 0 - RW */ -#define E1000_RXDCTL1 0x02928 /* RX Descriptor Control queue 1 - RW */ -#define E1000_RADV 0x0282C /* RX Interrupt Absolute Delay Timer - RW */ -#define E1000_RSRPD 0x02C00 /* RX Small Packet Detect - RW */ -#define E1000_RAID 0x02C08 /* Receive Ack Interrupt Delay - RW */ -#define E1000_TXDMAC 0x03000 /* TX DMA Control - RW */ -#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */ -#define E1000_TDFH 0x03410 /* TX Data FIFO Head - RW */ -#define E1000_TDFT 0x03418 /* TX Data FIFO Tail - RW */ -#define E1000_TDFHS 0x03420 /* TX Data FIFO Head Saved - RW */ -#define E1000_TDFTS 0x03428 /* TX Data FIFO Tail Saved - RW */ -#define E1000_TDFPC 0x03430 /* TX Data FIFO Packet Count - RW */ -#define E1000_TDBAL 0x03800 /* TX Descriptor Base Address Low - RW */ -#define E1000_TDBAH 0x03804 /* TX Descriptor Base Address High - RW */ -#define E1000_TDLEN 0x03808 /* TX Descriptor Length - RW */ -#define E1000_TDH 0x03810 /* TX Descriptor Head - RW */ -#define E1000_TDT 0x03818 /* TX Descripotr Tail - RW */ -#define E1000_TIDV 0x03820 /* TX Interrupt Delay Value - RW */ -#define E1000_TXDCTL 0x03828 /* TX Descriptor Control - RW */ -#define E1000_TADV 0x0382C /* TX Interrupt Absolute Delay Val - RW */ -#define E1000_TSPMT 0x03830 /* TCP Segmentation PAD & Min Threshold - RW */ -#define E1000_TARC0 0x03840 /* TX Arbitration Count (0) */ -#define E1000_TDBAL1 0x03900 /* TX Desc Base Address Low (1) - RW */ -#define E1000_TDBAH1 0x03904 /* TX Desc Base Address High (1) - RW */ -#define E1000_TDLEN1 0x03908 /* TX Desc Length (1) - RW */ -#define E1000_TDH1 0x03910 /* TX Desc Head (1) - RW */ -#define E1000_TDT1 0x03918 /* TX Desc Tail (1) - RW */ -#define E1000_TXDCTL1 0x03928 /* TX Descriptor Control (1) - RW */ -#define E1000_TARC1 0x03940 /* TX Arbitration Count (1) */ -#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ -#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ -#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ -#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */ -#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */ -#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */ -#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */ -#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */ -#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */ -#define E1000_COLC 0x04028 /* Collision Count - R/clr */ -#define E1000_DC 0x04030 /* Defer Count - R/clr */ -#define E1000_TNCRS 0x04034 /* TX-No CRS - R/clr */ -#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ -#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ -#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ -#define E1000_XONRXC 0x04048 /* XON RX Count - R/clr */ -#define E1000_XONTXC 0x0404C /* XON TX Count - R/clr */ -#define E1000_XOFFRXC 0x04050 /* XOFF RX Count - R/clr */ -#define E1000_XOFFTXC 0x04054 /* XOFF TX Count - R/clr */ -#define E1000_FCRUC 0x04058 /* Flow Control RX Unsupported Count- R/clr */ -#define E1000_PRC64 0x0405C /* Packets RX (64 bytes) - R/clr */ -#define E1000_PRC127 0x04060 /* Packets RX (65-127 bytes) - R/clr */ -#define E1000_PRC255 0x04064 /* Packets RX (128-255 bytes) - R/clr */ -#define E1000_PRC511 0x04068 /* Packets RX (255-511 bytes) - R/clr */ -#define E1000_PRC1023 0x0406C /* Packets RX (512-1023 bytes) - R/clr */ -#define E1000_PRC1522 0x04070 /* Packets RX (1024-1522 bytes) - R/clr */ -#define E1000_GPRC 0x04074 /* Good Packets RX Count - R/clr */ -#define E1000_BPRC 0x04078 /* Broadcast Packets RX Count - R/clr */ -#define E1000_MPRC 0x0407C /* Multicast Packets RX Count - R/clr */ -#define E1000_GPTC 0x04080 /* Good Packets TX Count - R/clr */ -#define E1000_GORCL 0x04088 /* Good Octets RX Count Low - R/clr */ -#define E1000_GORCH 0x0408C /* Good Octets RX Count High - R/clr */ -#define E1000_GOTCL 0x04090 /* Good Octets TX Count Low - R/clr */ -#define E1000_GOTCH 0x04094 /* Good Octets TX Count High - R/clr */ -#define E1000_RNBC 0x040A0 /* RX No Buffers Count - R/clr */ -#define E1000_RUC 0x040A4 /* RX Undersize Count - R/clr */ -#define E1000_RFC 0x040A8 /* RX Fragment Count - R/clr */ -#define E1000_ROC 0x040AC /* RX Oversize Count - R/clr */ -#define E1000_RJC 0x040B0 /* RX Jabber Count - R/clr */ -#define E1000_MGTPRC 0x040B4 /* Management Packets RX Count - R/clr */ -#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ -#define E1000_MGTPTC 0x040BC /* Management Packets TX Count - R/clr */ -#define E1000_TORL 0x040C0 /* Total Octets RX Low - R/clr */ -#define E1000_TORH 0x040C4 /* Total Octets RX High - R/clr */ -#define E1000_TOTL 0x040C8 /* Total Octets TX Low - R/clr */ -#define E1000_TOTH 0x040CC /* Total Octets TX High - R/clr */ -#define E1000_TPR 0x040D0 /* Total Packets RX - R/clr */ -#define E1000_TPT 0x040D4 /* Total Packets TX - R/clr */ -#define E1000_PTC64 0x040D8 /* Packets TX (64 bytes) - R/clr */ -#define E1000_PTC127 0x040DC /* Packets TX (65-127 bytes) - R/clr */ -#define E1000_PTC255 0x040E0 /* Packets TX (128-255 bytes) - R/clr */ -#define E1000_PTC511 0x040E4 /* Packets TX (256-511 bytes) - R/clr */ -#define E1000_PTC1023 0x040E8 /* Packets TX (512-1023 bytes) - R/clr */ -#define E1000_PTC1522 0x040EC /* Packets TX (1024-1522 Bytes) - R/clr */ -#define E1000_MPTC 0x040F0 /* Multicast Packets TX Count - R/clr */ -#define E1000_BPTC 0x040F4 /* Broadcast Packets TX Count - R/clr */ -#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context TX - R/clr */ -#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context TX Fail - R/clr */ -#define E1000_IAC 0x04100 /* Interrupt Assertion Count */ -#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Packet Timer Expire Count */ -#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Absolute Timer Expire Count */ -#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Packet Timer Expire Count */ -#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Absolute Timer Expire Count */ -#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */ -#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Minimum Threshold Count */ -#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Descriptor Minimum Threshold Count */ -#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */ -#define E1000_RXCSUM 0x05000 /* RX Checksum Control - RW */ -#define E1000_RFCTL 0x05008 /* Receive Filter Control */ -#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ -#define E1000_RA 0x05400 /* Receive Address - RW Array */ -#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ -#define E1000_WUC 0x05800 /* Wakeup Control - RW */ -#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ -#define E1000_WUS 0x05810 /* Wakeup Status - RO */ -#define E1000_MANC 0x05820 /* Management Control - RW */ -#define E1000_IPAV 0x05838 /* IP Address Valid - RW */ -#define E1000_IP4AT 0x05840 /* IPv4 Address Table - RW Array */ -#define E1000_IP6AT 0x05880 /* IPv6 Address Table - RW Array */ -#define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */ -#define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */ -#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ -#define E1000_HOST_IF 0x08800 /* Host Interface */ -#define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ -#define E1000_FFVT 0x09800 /* Flexible Filter Value Table - RW Array */ - -#define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */ -#define E1000_MDPHYA 0x0003C /* PHY address - RW */ -#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */ -#define E1000_SW_FW_SYNC 0x05B5C /* Software-Firmware Synchronization - RW */ - -#define E1000_GCR 0x05B00 /* PCI-Ex Control */ -#define E1000_GSCL_1 0x05B10 /* PCI-Ex Statistic Control #1 */ -#define E1000_GSCL_2 0x05B14 /* PCI-Ex Statistic Control #2 */ -#define E1000_GSCL_3 0x05B18 /* PCI-Ex Statistic Control #3 */ -#define E1000_GSCL_4 0x05B1C /* PCI-Ex Statistic Control #4 */ -#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ -#define E1000_SWSM 0x05B50 /* SW Semaphore */ -#define E1000_FWSM 0x05B54 /* FW Semaphore */ -#define E1000_FFLT_DBG 0x05F04 /* Debug Register */ -#define E1000_HICR 0x08F00 /* Host Interface Control */ - -/* RSS registers */ -#define E1000_CPUVEC 0x02C10 /* CPU Vector Register - RW */ -#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */ -#define E1000_RETA 0x05C00 /* Redirection Table - RW Array */ -#define E1000_RSSRK 0x05C80 /* RSS Random Key - RW Array */ -#define E1000_RSSIM 0x05864 /* RSS Interrupt Mask */ -#define E1000_RSSIR 0x05868 /* RSS Interrupt Request */ -/* Register Set (82542) - * - * Some of the 82542 registers are located at different offsets than they are - * in more current versions of the 8254x. Despite the difference in location, - * the registers function in the same manner. - */ -#define E1000_82542_CTL_AUX E1000_CTL_AUX -#define E1000_82542_CTRL E1000_CTRL -#define E1000_82542_CTRL_DUP E1000_CTRL_DUP -#define E1000_82542_STATUS E1000_STATUS -#define E1000_82542_EECD E1000_EECD -#define E1000_82542_EERD E1000_EERD -#define E1000_82542_CTRL_EXT E1000_CTRL_EXT -#define E1000_82542_FLA E1000_FLA -#define E1000_82542_MDIC E1000_MDIC -#define E1000_82542_SCTL E1000_SCTL -#define E1000_82542_FEXTNVM E1000_FEXTNVM -#define E1000_82542_FCAL E1000_FCAL -#define E1000_82542_FCAH E1000_FCAH -#define E1000_82542_FCT E1000_FCT -#define E1000_82542_VET E1000_VET -#define E1000_82542_RA 0x00040 -#define E1000_82542_ICR E1000_ICR -#define E1000_82542_ITR E1000_ITR -#define E1000_82542_ICS E1000_ICS -#define E1000_82542_IMS E1000_IMS -#define E1000_82542_IMC E1000_IMC -#define E1000_82542_RCTL E1000_RCTL -#define E1000_82542_RDTR 0x00108 -#define E1000_82542_RDFH E1000_RDFH -#define E1000_82542_RDFT E1000_RDFT -#define E1000_82542_RDFHS E1000_RDFHS -#define E1000_82542_RDFTS E1000_RDFTS -#define E1000_82542_RDFPC E1000_RDFPC -#define E1000_82542_RDBAL 0x00110 -#define E1000_82542_RDBAH 0x00114 -#define E1000_82542_RDLEN 0x00118 -#define E1000_82542_RDH 0x00120 -#define E1000_82542_RDT 0x00128 -#define E1000_82542_RDTR0 E1000_82542_RDTR -#define E1000_82542_RDBAL0 E1000_82542_RDBAL -#define E1000_82542_RDBAH0 E1000_82542_RDBAH -#define E1000_82542_RDLEN0 E1000_82542_RDLEN -#define E1000_82542_RDH0 E1000_82542_RDH -#define E1000_82542_RDT0 E1000_82542_RDT -#define E1000_82542_SRRCTL(_n) (0x280C + ((_n) << 8)) /* Split and Replication - * RX Control - RW */ -#define E1000_82542_DCA_RXCTRL(_n) (0x02814 + ((_n) << 8)) -#define E1000_82542_RDBAH3 0x02B04 /* RX Desc Base High Queue 3 - RW */ -#define E1000_82542_RDBAL3 0x02B00 /* RX Desc Low Queue 3 - RW */ -#define E1000_82542_RDLEN3 0x02B08 /* RX Desc Length Queue 3 - RW */ -#define E1000_82542_RDH3 0x02B10 /* RX Desc Head Queue 3 - RW */ -#define E1000_82542_RDT3 0x02B18 /* RX Desc Tail Queue 3 - RW */ -#define E1000_82542_RDBAL2 0x02A00 /* RX Desc Base Low Queue 2 - RW */ -#define E1000_82542_RDBAH2 0x02A04 /* RX Desc Base High Queue 2 - RW */ -#define E1000_82542_RDLEN2 0x02A08 /* RX Desc Length Queue 2 - RW */ -#define E1000_82542_RDH2 0x02A10 /* RX Desc Head Queue 2 - RW */ -#define E1000_82542_RDT2 0x02A18 /* RX Desc Tail Queue 2 - RW */ -#define E1000_82542_RDTR1 0x00130 -#define E1000_82542_RDBAL1 0x00138 -#define E1000_82542_RDBAH1 0x0013C -#define E1000_82542_RDLEN1 0x00140 -#define E1000_82542_RDH1 0x00148 -#define E1000_82542_RDT1 0x00150 -#define E1000_82542_FCRTH 0x00160 -#define E1000_82542_FCRTL 0x00168 -#define E1000_82542_FCTTV E1000_FCTTV -#define E1000_82542_TXCW E1000_TXCW -#define E1000_82542_RXCW E1000_RXCW -#define E1000_82542_MTA 0x00200 -#define E1000_82542_TCTL E1000_TCTL -#define E1000_82542_TCTL_EXT E1000_TCTL_EXT -#define E1000_82542_TIPG E1000_TIPG -#define E1000_82542_TDBAL 0x00420 -#define E1000_82542_TDBAH 0x00424 -#define E1000_82542_TDLEN 0x00428 -#define E1000_82542_TDH 0x00430 -#define E1000_82542_TDT 0x00438 -#define E1000_82542_TIDV 0x00440 -#define E1000_82542_TBT E1000_TBT -#define E1000_82542_AIT E1000_AIT -#define E1000_82542_VFTA 0x00600 -#define E1000_82542_LEDCTL E1000_LEDCTL -#define E1000_82542_PBA E1000_PBA -#define E1000_82542_PBS E1000_PBS -#define E1000_82542_EEMNGCTL E1000_EEMNGCTL -#define E1000_82542_EEARBC E1000_EEARBC -#define E1000_82542_FLASHT E1000_FLASHT -#define E1000_82542_EEWR E1000_EEWR -#define E1000_82542_FLSWCTL E1000_FLSWCTL -#define E1000_82542_FLSWDATA E1000_FLSWDATA -#define E1000_82542_FLSWCNT E1000_FLSWCNT -#define E1000_82542_FLOP E1000_FLOP -#define E1000_82542_EXTCNF_CTRL E1000_EXTCNF_CTRL -#define E1000_82542_EXTCNF_SIZE E1000_EXTCNF_SIZE -#define E1000_82542_PHY_CTRL E1000_PHY_CTRL -#define E1000_82542_ERT E1000_ERT -#define E1000_82542_RXDCTL E1000_RXDCTL -#define E1000_82542_RXDCTL1 E1000_RXDCTL1 -#define E1000_82542_RADV E1000_RADV -#define E1000_82542_RSRPD E1000_RSRPD -#define E1000_82542_TXDMAC E1000_TXDMAC -#define E1000_82542_KABGTXD E1000_KABGTXD -#define E1000_82542_TDFHS E1000_TDFHS -#define E1000_82542_TDFTS E1000_TDFTS -#define E1000_82542_TDFPC E1000_TDFPC -#define E1000_82542_TXDCTL E1000_TXDCTL -#define E1000_82542_TADV E1000_TADV -#define E1000_82542_TSPMT E1000_TSPMT -#define E1000_82542_CRCERRS E1000_CRCERRS -#define E1000_82542_ALGNERRC E1000_ALGNERRC -#define E1000_82542_SYMERRS E1000_SYMERRS -#define E1000_82542_RXERRC E1000_RXERRC -#define E1000_82542_MPC E1000_MPC -#define E1000_82542_SCC E1000_SCC -#define E1000_82542_ECOL E1000_ECOL -#define E1000_82542_MCC E1000_MCC -#define E1000_82542_LATECOL E1000_LATECOL -#define E1000_82542_COLC E1000_COLC -#define E1000_82542_DC E1000_DC -#define E1000_82542_TNCRS E1000_TNCRS -#define E1000_82542_SEC E1000_SEC -#define E1000_82542_CEXTERR E1000_CEXTERR -#define E1000_82542_RLEC E1000_RLEC -#define E1000_82542_XONRXC E1000_XONRXC -#define E1000_82542_XONTXC E1000_XONTXC -#define E1000_82542_XOFFRXC E1000_XOFFRXC -#define E1000_82542_XOFFTXC E1000_XOFFTXC -#define E1000_82542_FCRUC E1000_FCRUC -#define E1000_82542_PRC64 E1000_PRC64 -#define E1000_82542_PRC127 E1000_PRC127 -#define E1000_82542_PRC255 E1000_PRC255 -#define E1000_82542_PRC511 E1000_PRC511 -#define E1000_82542_PRC1023 E1000_PRC1023 -#define E1000_82542_PRC1522 E1000_PRC1522 -#define E1000_82542_GPRC E1000_GPRC -#define E1000_82542_BPRC E1000_BPRC -#define E1000_82542_MPRC E1000_MPRC -#define E1000_82542_GPTC E1000_GPTC -#define E1000_82542_GORCL E1000_GORCL -#define E1000_82542_GORCH E1000_GORCH -#define E1000_82542_GOTCL E1000_GOTCL -#define E1000_82542_GOTCH E1000_GOTCH -#define E1000_82542_RNBC E1000_RNBC -#define E1000_82542_RUC E1000_RUC -#define E1000_82542_RFC E1000_RFC -#define E1000_82542_ROC E1000_ROC -#define E1000_82542_RJC E1000_RJC -#define E1000_82542_MGTPRC E1000_MGTPRC -#define E1000_82542_MGTPDC E1000_MGTPDC -#define E1000_82542_MGTPTC E1000_MGTPTC -#define E1000_82542_TORL E1000_TORL -#define E1000_82542_TORH E1000_TORH -#define E1000_82542_TOTL E1000_TOTL -#define E1000_82542_TOTH E1000_TOTH -#define E1000_82542_TPR E1000_TPR -#define E1000_82542_TPT E1000_TPT -#define E1000_82542_PTC64 E1000_PTC64 -#define E1000_82542_PTC127 E1000_PTC127 -#define E1000_82542_PTC255 E1000_PTC255 -#define E1000_82542_PTC511 E1000_PTC511 -#define E1000_82542_PTC1023 E1000_PTC1023 -#define E1000_82542_PTC1522 E1000_PTC1522 -#define E1000_82542_MPTC E1000_MPTC -#define E1000_82542_BPTC E1000_BPTC -#define E1000_82542_TSCTC E1000_TSCTC -#define E1000_82542_TSCTFC E1000_TSCTFC -#define E1000_82542_RXCSUM E1000_RXCSUM -#define E1000_82542_WUC E1000_WUC -#define E1000_82542_WUFC E1000_WUFC -#define E1000_82542_WUS E1000_WUS -#define E1000_82542_MANC E1000_MANC -#define E1000_82542_IPAV E1000_IPAV -#define E1000_82542_IP4AT E1000_IP4AT -#define E1000_82542_IP6AT E1000_IP6AT -#define E1000_82542_WUPL E1000_WUPL -#define E1000_82542_WUPM E1000_WUPM -#define E1000_82542_FFLT E1000_FFLT -#define E1000_82542_TDFH 0x08010 -#define E1000_82542_TDFT 0x08018 -#define E1000_82542_FFMT E1000_FFMT -#define E1000_82542_FFVT E1000_FFVT -#define E1000_82542_HOST_IF E1000_HOST_IF -#define E1000_82542_IAM E1000_IAM -#define E1000_82542_EEMNGCTL E1000_EEMNGCTL -#define E1000_82542_PSRCTL E1000_PSRCTL -#define E1000_82542_RAID E1000_RAID -#define E1000_82542_TARC0 E1000_TARC0 -#define E1000_82542_TDBAL1 E1000_TDBAL1 -#define E1000_82542_TDBAH1 E1000_TDBAH1 -#define E1000_82542_TDLEN1 E1000_TDLEN1 -#define E1000_82542_TDH1 E1000_TDH1 -#define E1000_82542_TDT1 E1000_TDT1 -#define E1000_82542_TXDCTL1 E1000_TXDCTL1 -#define E1000_82542_TARC1 E1000_TARC1 -#define E1000_82542_RFCTL E1000_RFCTL -#define E1000_82542_GCR E1000_GCR -#define E1000_82542_GSCL_1 E1000_GSCL_1 -#define E1000_82542_GSCL_2 E1000_GSCL_2 -#define E1000_82542_GSCL_3 E1000_GSCL_3 -#define E1000_82542_GSCL_4 E1000_GSCL_4 -#define E1000_82542_FACTPS E1000_FACTPS -#define E1000_82542_SWSM E1000_SWSM -#define E1000_82542_FWSM E1000_FWSM -#define E1000_82542_FFLT_DBG E1000_FFLT_DBG -#define E1000_82542_IAC E1000_IAC -#define E1000_82542_ICRXPTC E1000_ICRXPTC -#define E1000_82542_ICRXATC E1000_ICRXATC -#define E1000_82542_ICTXPTC E1000_ICTXPTC -#define E1000_82542_ICTXATC E1000_ICTXATC -#define E1000_82542_ICTXQEC E1000_ICTXQEC -#define E1000_82542_ICTXQMTC E1000_ICTXQMTC -#define E1000_82542_ICRXDMTC E1000_ICRXDMTC -#define E1000_82542_ICRXOC E1000_ICRXOC -#define E1000_82542_HICR E1000_HICR - -#define E1000_82542_CPUVEC E1000_CPUVEC -#define E1000_82542_MRQC E1000_MRQC -#define E1000_82542_RETA E1000_RETA -#define E1000_82542_RSSRK E1000_RSSRK -#define E1000_82542_RSSIM E1000_RSSIM -#define E1000_82542_RSSIR E1000_RSSIR -#define E1000_82542_KUMCTRLSTA E1000_KUMCTRLSTA -#define E1000_82542_SW_FW_SYNC E1000_SW_FW_SYNC - -/* Statistics counters collected by the MAC */ -struct e1000_hw_stats { - u64 crcerrs; - u64 algnerrc; - u64 symerrs; - u64 rxerrc; - u64 txerrc; - u64 mpc; - u64 scc; - u64 ecol; - u64 mcc; - u64 latecol; - u64 colc; - u64 dc; - u64 tncrs; - u64 sec; - u64 cexterr; - u64 rlec; - u64 xonrxc; - u64 xontxc; - u64 xoffrxc; - u64 xofftxc; - u64 fcruc; - u64 prc64; - u64 prc127; - u64 prc255; - u64 prc511; - u64 prc1023; - u64 prc1522; - u64 gprc; - u64 bprc; - u64 mprc; - u64 gptc; - u64 gorcl; - u64 gorch; - u64 gotcl; - u64 gotch; - u64 rnbc; - u64 ruc; - u64 rfc; - u64 roc; - u64 rlerrc; - u64 rjc; - u64 mgprc; - u64 mgpdc; - u64 mgptc; - u64 torl; - u64 torh; - u64 totl; - u64 toth; - u64 tpr; - u64 tpt; - u64 ptc64; - u64 ptc127; - u64 ptc255; - u64 ptc511; - u64 ptc1023; - u64 ptc1522; - u64 mptc; - u64 bptc; - u64 tsctc; - u64 tsctfc; - u64 iac; - u64 icrxptc; - u64 icrxatc; - u64 ictxptc; - u64 ictxatc; - u64 ictxqec; - u64 ictxqmtc; - u64 icrxdmtc; - u64 icrxoc; -}; - -/* Structure containing variables used by the shared code (e1000_hw.c) */ -struct e1000_hw { - u8 __iomem *hw_addr; - u8 __iomem *flash_address; - void __iomem *ce4100_gbe_mdio_base_virt; - e1000_mac_type mac_type; - e1000_phy_type phy_type; - u32 phy_init_script; - e1000_media_type media_type; - void *back; - struct e1000_shadow_ram *eeprom_shadow_ram; - u32 flash_bank_size; - u32 flash_base_addr; - e1000_fc_type fc; - e1000_bus_speed bus_speed; - e1000_bus_width bus_width; - e1000_bus_type bus_type; - struct e1000_eeprom_info eeprom; - e1000_ms_type master_slave; - e1000_ms_type original_master_slave; - e1000_ffe_config ffe_config_state; - u32 asf_firmware_present; - u32 eeprom_semaphore_present; - unsigned long io_base; - u32 phy_id; - u32 phy_revision; - u32 phy_addr; - u32 original_fc; - u32 txcw; - u32 autoneg_failed; - u32 max_frame_size; - u32 min_frame_size; - u32 mc_filter_type; - u32 num_mc_addrs; - u32 collision_delta; - u32 tx_packet_delta; - u32 ledctl_default; - u32 ledctl_mode1; - u32 ledctl_mode2; - bool tx_pkt_filtering; - struct e1000_host_mng_dhcp_cookie mng_cookie; - u16 phy_spd_default; - u16 autoneg_advertised; - u16 pci_cmd_word; - u16 fc_high_water; - u16 fc_low_water; - u16 fc_pause_time; - u16 current_ifs_val; - u16 ifs_min_val; - u16 ifs_max_val; - u16 ifs_step_size; - u16 ifs_ratio; - u16 device_id; - u16 vendor_id; - u16 subsystem_id; - u16 subsystem_vendor_id; - u8 revision_id; - u8 autoneg; - u8 mdix; - u8 forced_speed_duplex; - u8 wait_autoneg_complete; - u8 dma_fairness; - u8 mac_addr[NODE_ADDRESS_SIZE]; - u8 perm_mac_addr[NODE_ADDRESS_SIZE]; - bool disable_polarity_correction; - bool speed_downgraded; - e1000_smart_speed smart_speed; - e1000_dsp_config dsp_config_state; - bool get_link_status; - bool serdes_has_link; - bool tbi_compatibility_en; - bool tbi_compatibility_on; - bool laa_is_present; - bool phy_reset_disable; - bool initialize_hw_bits_disable; - bool fc_send_xon; - bool fc_strict_ieee; - bool report_tx_early; - bool adaptive_ifs; - bool ifs_params_forced; - bool in_ifs_mode; - bool mng_reg_access_disabled; - bool leave_av_bit_off; - bool bad_tx_carr_stats_fd; - bool has_smbus; -}; - -#define E1000_EEPROM_SWDPIN0 0x0001 /* SWDPIN 0 EEPROM Value */ -#define E1000_EEPROM_LED_LOGIC 0x0020 /* Led Logic Word */ -#define E1000_EEPROM_RW_REG_DATA 16 /* Offset to data in EEPROM read/write registers */ -#define E1000_EEPROM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ -#define E1000_EEPROM_RW_REG_START 1 /* First bit for telling part to start operation */ -#define E1000_EEPROM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ -#define E1000_EEPROM_POLL_WRITE 1 /* Flag for polling for write complete */ -#define E1000_EEPROM_POLL_READ 0 /* Flag for polling for read complete */ -/* Register Bit Masks */ -/* Device Control */ -#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ -#define E1000_CTRL_BEM 0x00000002 /* Endian Mode.0=little,1=big */ -#define E1000_CTRL_PRIOR 0x00000004 /* Priority on PCI. 0=rx,1=fair */ -#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */ -#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ -#define E1000_CTRL_TME 0x00000010 /* Test mode. 0=normal,1=test */ -#define E1000_CTRL_SLE 0x00000020 /* Serial Link on 0=dis,1=en */ -#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */ -#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ -#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */ -#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */ -#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */ -#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */ -#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */ -#define E1000_CTRL_BEM32 0x00000400 /* Big Endian 32 mode */ -#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ -#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ -#define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */ -#define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */ -#define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */ -#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */ -#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ -#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ -#define E1000_CTRL_SWDPIN2 0x00100000 /* SWDPIN 2 value */ -#define E1000_CTRL_SWDPIN3 0x00200000 /* SWDPIN 3 value */ -#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ -#define E1000_CTRL_SWDPIO1 0x00800000 /* SWDPIN 1 input or output */ -#define E1000_CTRL_SWDPIO2 0x01000000 /* SWDPIN 2 input or output */ -#define E1000_CTRL_SWDPIO3 0x02000000 /* SWDPIN 3 input or output */ -#define E1000_CTRL_RST 0x04000000 /* Global reset */ -#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ -#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ -#define E1000_CTRL_RTE 0x20000000 /* Routing tag enable */ -#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ -#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ -#define E1000_CTRL_SW2FW_INT 0x02000000 /* Initiate an interrupt to manageability engine */ - -/* Device Status */ -#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ -#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ -#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ -#define E1000_STATUS_FUNC_SHIFT 2 -#define E1000_STATUS_FUNC_0 0x00000000 /* Function 0 */ -#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ -#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ -#define E1000_STATUS_TBIMODE 0x00000020 /* TBI mode */ -#define E1000_STATUS_SPEED_MASK 0x000000C0 -#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ -#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ -#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ -#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion - by EEPROM/Flash */ -#define E1000_STATUS_ASDV 0x00000300 /* Auto speed detect value */ -#define E1000_STATUS_DOCK_CI 0x00000800 /* Change in Dock/Undock state. Clear on write '0'. */ -#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Status of Master requests. */ -#define E1000_STATUS_MTXCKOK 0x00000400 /* MTX clock running OK */ -#define E1000_STATUS_PCI66 0x00000800 /* In 66Mhz slot */ -#define E1000_STATUS_BUS64 0x00001000 /* In 64 bit slot */ -#define E1000_STATUS_PCIX_MODE 0x00002000 /* PCI-X mode */ -#define E1000_STATUS_PCIX_SPEED 0x0000C000 /* PCI-X bus speed */ -#define E1000_STATUS_BMC_SKU_0 0x00100000 /* BMC USB redirect disabled */ -#define E1000_STATUS_BMC_SKU_1 0x00200000 /* BMC SRAM disabled */ -#define E1000_STATUS_BMC_SKU_2 0x00400000 /* BMC SDRAM disabled */ -#define E1000_STATUS_BMC_CRYPTO 0x00800000 /* BMC crypto disabled */ -#define E1000_STATUS_BMC_LITE 0x01000000 /* BMC external code execution disabled */ -#define E1000_STATUS_RGMII_ENABLE 0x02000000 /* RGMII disabled */ -#define E1000_STATUS_FUSE_8 0x04000000 -#define E1000_STATUS_FUSE_9 0x08000000 -#define E1000_STATUS_SERDES0_DIS 0x10000000 /* SERDES disabled on port 0 */ -#define E1000_STATUS_SERDES1_DIS 0x20000000 /* SERDES disabled on port 1 */ - -/* Constants used to interpret the masked PCI-X bus speed. */ -#define E1000_STATUS_PCIX_SPEED_66 0x00000000 /* PCI-X bus speed 50-66 MHz */ -#define E1000_STATUS_PCIX_SPEED_100 0x00004000 /* PCI-X bus speed 66-100 MHz */ -#define E1000_STATUS_PCIX_SPEED_133 0x00008000 /* PCI-X bus speed 100-133 MHz */ - -/* EEPROM/Flash Control */ -#define E1000_EECD_SK 0x00000001 /* EEPROM Clock */ -#define E1000_EECD_CS 0x00000002 /* EEPROM Chip Select */ -#define E1000_EECD_DI 0x00000004 /* EEPROM Data In */ -#define E1000_EECD_DO 0x00000008 /* EEPROM Data Out */ -#define E1000_EECD_FWE_MASK 0x00000030 -#define E1000_EECD_FWE_DIS 0x00000010 /* Disable FLASH writes */ -#define E1000_EECD_FWE_EN 0x00000020 /* Enable FLASH writes */ -#define E1000_EECD_FWE_SHIFT 4 -#define E1000_EECD_REQ 0x00000040 /* EEPROM Access Request */ -#define E1000_EECD_GNT 0x00000080 /* EEPROM Access Grant */ -#define E1000_EECD_PRES 0x00000100 /* EEPROM Present */ -#define E1000_EECD_SIZE 0x00000200 /* EEPROM Size (0=64 word 1=256 word) */ -#define E1000_EECD_ADDR_BITS 0x00000400 /* EEPROM Addressing bits based on type - * (0-small, 1-large) */ -#define E1000_EECD_TYPE 0x00002000 /* EEPROM Type (1-SPI, 0-Microwire) */ -#ifndef E1000_EEPROM_GRANT_ATTEMPTS -#define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */ -#endif -#define E1000_EECD_AUTO_RD 0x00000200 /* EEPROM Auto Read done */ -#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* EEprom Size */ -#define E1000_EECD_SIZE_EX_SHIFT 11 -#define E1000_EECD_NVADDS 0x00018000 /* NVM Address Size */ -#define E1000_EECD_SELSHAD 0x00020000 /* Select Shadow RAM */ -#define E1000_EECD_INITSRAM 0x00040000 /* Initialize Shadow RAM */ -#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */ -#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */ -#define E1000_EECD_SHADV 0x00200000 /* Shadow RAM Data Valid */ -#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */ -#define E1000_EECD_SECVAL_SHIFT 22 -#define E1000_STM_OPCODE 0xDB00 -#define E1000_HICR_FW_RESET 0xC0 - -#define E1000_SHADOW_RAM_WORDS 2048 -#define E1000_ICH_NVM_SIG_WORD 0x13 -#define E1000_ICH_NVM_SIG_MASK 0xC0 - -/* EEPROM Read */ -#define E1000_EERD_START 0x00000001 /* Start Read */ -#define E1000_EERD_DONE 0x00000010 /* Read Done */ -#define E1000_EERD_ADDR_SHIFT 8 -#define E1000_EERD_ADDR_MASK 0x0000FF00 /* Read Address */ -#define E1000_EERD_DATA_SHIFT 16 -#define E1000_EERD_DATA_MASK 0xFFFF0000 /* Read Data */ - -/* SPI EEPROM Status Register */ -#define EEPROM_STATUS_RDY_SPI 0x01 -#define EEPROM_STATUS_WEN_SPI 0x02 -#define EEPROM_STATUS_BP0_SPI 0x04 -#define EEPROM_STATUS_BP1_SPI 0x08 -#define EEPROM_STATUS_WPEN_SPI 0x80 - -/* Extended Device Control */ -#define E1000_CTRL_EXT_GPI0_EN 0x00000001 /* Maps SDP4 to GPI0 */ -#define E1000_CTRL_EXT_GPI1_EN 0x00000002 /* Maps SDP5 to GPI1 */ -#define E1000_CTRL_EXT_PHYINT_EN E1000_CTRL_EXT_GPI1_EN -#define E1000_CTRL_EXT_GPI2_EN 0x00000004 /* Maps SDP6 to GPI2 */ -#define E1000_CTRL_EXT_GPI3_EN 0x00000008 /* Maps SDP7 to GPI3 */ -#define E1000_CTRL_EXT_SDP4_DATA 0x00000010 /* Value of SW Defineable Pin 4 */ -#define E1000_CTRL_EXT_SDP5_DATA 0x00000020 /* Value of SW Defineable Pin 5 */ -#define E1000_CTRL_EXT_PHY_INT E1000_CTRL_EXT_SDP5_DATA -#define E1000_CTRL_EXT_SDP6_DATA 0x00000040 /* Value of SW Defineable Pin 6 */ -#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Defineable Pin 7 */ -#define E1000_CTRL_EXT_SDP4_DIR 0x00000100 /* Direction of SDP4 0=in 1=out */ -#define E1000_CTRL_EXT_SDP5_DIR 0x00000200 /* Direction of SDP5 0=in 1=out */ -#define E1000_CTRL_EXT_SDP6_DIR 0x00000400 /* Direction of SDP6 0=in 1=out */ -#define E1000_CTRL_EXT_SDP7_DIR 0x00000800 /* Direction of SDP7 0=in 1=out */ -#define E1000_CTRL_EXT_ASDCHK 0x00001000 /* Initiate an ASD sequence */ -#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ -#define E1000_CTRL_EXT_IPS 0x00004000 /* Invert Power State */ -#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ -#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ -#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 -#define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000 -#define E1000_CTRL_EXT_LINK_MODE_TBI 0x00C00000 -#define E1000_CTRL_EXT_LINK_MODE_KMRN 0x00000000 -#define E1000_CTRL_EXT_LINK_MODE_SERDES 0x00C00000 -#define E1000_CTRL_EXT_LINK_MODE_SGMII 0x00800000 -#define E1000_CTRL_EXT_WR_WMARK_MASK 0x03000000 -#define E1000_CTRL_EXT_WR_WMARK_256 0x00000000 -#define E1000_CTRL_EXT_WR_WMARK_320 0x01000000 -#define E1000_CTRL_EXT_WR_WMARK_384 0x02000000 -#define E1000_CTRL_EXT_WR_WMARK_448 0x03000000 -#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ -#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */ -#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */ -#define E1000_CRTL_EXT_PB_PAREN 0x01000000 /* packet buffer parity error detection enabled */ -#define E1000_CTRL_EXT_DF_PAREN 0x02000000 /* descriptor FIFO parity error detection enable */ -#define E1000_CTRL_EXT_GHOST_PAREN 0x40000000 - -/* MDI Control */ -#define E1000_MDIC_DATA_MASK 0x0000FFFF -#define E1000_MDIC_REG_MASK 0x001F0000 -#define E1000_MDIC_REG_SHIFT 16 -#define E1000_MDIC_PHY_MASK 0x03E00000 -#define E1000_MDIC_PHY_SHIFT 21 -#define E1000_MDIC_OP_WRITE 0x04000000 -#define E1000_MDIC_OP_READ 0x08000000 -#define E1000_MDIC_READY 0x10000000 -#define E1000_MDIC_INT_EN 0x20000000 -#define E1000_MDIC_ERROR 0x40000000 - -#define INTEL_CE_GBE_MDIC_OP_WRITE 0x04000000 -#define INTEL_CE_GBE_MDIC_OP_READ 0x00000000 -#define INTEL_CE_GBE_MDIC_GO 0x80000000 -#define INTEL_CE_GBE_MDIC_READ_ERROR 0x80000000 - -#define E1000_KUMCTRLSTA_MASK 0x0000FFFF -#define E1000_KUMCTRLSTA_OFFSET 0x001F0000 -#define E1000_KUMCTRLSTA_OFFSET_SHIFT 16 -#define E1000_KUMCTRLSTA_REN 0x00200000 - -#define E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL 0x00000000 -#define E1000_KUMCTRLSTA_OFFSET_CTRL 0x00000001 -#define E1000_KUMCTRLSTA_OFFSET_INB_CTRL 0x00000002 -#define E1000_KUMCTRLSTA_OFFSET_DIAG 0x00000003 -#define E1000_KUMCTRLSTA_OFFSET_TIMEOUTS 0x00000004 -#define E1000_KUMCTRLSTA_OFFSET_INB_PARAM 0x00000009 -#define E1000_KUMCTRLSTA_OFFSET_HD_CTRL 0x00000010 -#define E1000_KUMCTRLSTA_OFFSET_M2P_SERDES 0x0000001E -#define E1000_KUMCTRLSTA_OFFSET_M2P_MODES 0x0000001F - -/* FIFO Control */ -#define E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS 0x00000008 -#define E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS 0x00000800 - -/* In-Band Control */ -#define E1000_KUMCTRLSTA_INB_CTRL_LINK_STATUS_TX_TIMEOUT_DEFAULT 0x00000500 -#define E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING 0x00000010 - -/* Half-Duplex Control */ -#define E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004 -#define E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT 0x00000000 - -#define E1000_KUMCTRLSTA_OFFSET_K0S_CTRL 0x0000001E - -#define E1000_KUMCTRLSTA_DIAG_FELPBK 0x2000 -#define E1000_KUMCTRLSTA_DIAG_NELPBK 0x1000 - -#define E1000_KUMCTRLSTA_K0S_100_EN 0x2000 -#define E1000_KUMCTRLSTA_K0S_GBE_EN 0x1000 -#define E1000_KUMCTRLSTA_K0S_ENTRY_LATENCY_MASK 0x0003 - -#define E1000_KABGTXD_BGSQLBIAS 0x00050000 - -#define E1000_PHY_CTRL_SPD_EN 0x00000001 -#define E1000_PHY_CTRL_D0A_LPLU 0x00000002 -#define E1000_PHY_CTRL_NOND0A_LPLU 0x00000004 -#define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008 -#define E1000_PHY_CTRL_GBE_DISABLE 0x00000040 -#define E1000_PHY_CTRL_B2B_EN 0x00000080 - -/* LED Control */ -#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F -#define E1000_LEDCTL_LED0_MODE_SHIFT 0 -#define E1000_LEDCTL_LED0_BLINK_RATE 0x0000020 -#define E1000_LEDCTL_LED0_IVRT 0x00000040 -#define E1000_LEDCTL_LED0_BLINK 0x00000080 -#define E1000_LEDCTL_LED1_MODE_MASK 0x00000F00 -#define E1000_LEDCTL_LED1_MODE_SHIFT 8 -#define E1000_LEDCTL_LED1_BLINK_RATE 0x0002000 -#define E1000_LEDCTL_LED1_IVRT 0x00004000 -#define E1000_LEDCTL_LED1_BLINK 0x00008000 -#define E1000_LEDCTL_LED2_MODE_MASK 0x000F0000 -#define E1000_LEDCTL_LED2_MODE_SHIFT 16 -#define E1000_LEDCTL_LED2_BLINK_RATE 0x00200000 -#define E1000_LEDCTL_LED2_IVRT 0x00400000 -#define E1000_LEDCTL_LED2_BLINK 0x00800000 -#define E1000_LEDCTL_LED3_MODE_MASK 0x0F000000 -#define E1000_LEDCTL_LED3_MODE_SHIFT 24 -#define E1000_LEDCTL_LED3_BLINK_RATE 0x20000000 -#define E1000_LEDCTL_LED3_IVRT 0x40000000 -#define E1000_LEDCTL_LED3_BLINK 0x80000000 - -#define E1000_LEDCTL_MODE_LINK_10_1000 0x0 -#define E1000_LEDCTL_MODE_LINK_100_1000 0x1 -#define E1000_LEDCTL_MODE_LINK_UP 0x2 -#define E1000_LEDCTL_MODE_ACTIVITY 0x3 -#define E1000_LEDCTL_MODE_LINK_ACTIVITY 0x4 -#define E1000_LEDCTL_MODE_LINK_10 0x5 -#define E1000_LEDCTL_MODE_LINK_100 0x6 -#define E1000_LEDCTL_MODE_LINK_1000 0x7 -#define E1000_LEDCTL_MODE_PCIX_MODE 0x8 -#define E1000_LEDCTL_MODE_FULL_DUPLEX 0x9 -#define E1000_LEDCTL_MODE_COLLISION 0xA -#define E1000_LEDCTL_MODE_BUS_SPEED 0xB -#define E1000_LEDCTL_MODE_BUS_SIZE 0xC -#define E1000_LEDCTL_MODE_PAUSED 0xD -#define E1000_LEDCTL_MODE_LED_ON 0xE -#define E1000_LEDCTL_MODE_LED_OFF 0xF - -/* Receive Address */ -#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ - -/* Interrupt Cause Read */ -#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ -#define E1000_ICR_TXQE 0x00000002 /* Transmit Queue empty */ -#define E1000_ICR_LSC 0x00000004 /* Link Status Change */ -#define E1000_ICR_RXSEQ 0x00000008 /* rx sequence error */ -#define E1000_ICR_RXDMT0 0x00000010 /* rx desc min. threshold (0) */ -#define E1000_ICR_RXO 0x00000040 /* rx overrun */ -#define E1000_ICR_RXT0 0x00000080 /* rx timer intr (ring 0) */ -#define E1000_ICR_MDAC 0x00000200 /* MDIO access complete */ -#define E1000_ICR_RXCFG 0x00000400 /* RX /c/ ordered set */ -#define E1000_ICR_GPI_EN0 0x00000800 /* GP Int 0 */ -#define E1000_ICR_GPI_EN1 0x00001000 /* GP Int 1 */ -#define E1000_ICR_GPI_EN2 0x00002000 /* GP Int 2 */ -#define E1000_ICR_GPI_EN3 0x00004000 /* GP Int 3 */ -#define E1000_ICR_TXD_LOW 0x00008000 -#define E1000_ICR_SRPD 0x00010000 -#define E1000_ICR_ACK 0x00020000 /* Receive Ack frame */ -#define E1000_ICR_MNG 0x00040000 /* Manageability event */ -#define E1000_ICR_DOCK 0x00080000 /* Dock/Undock */ -#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */ -#define E1000_ICR_RXD_FIFO_PAR0 0x00100000 /* queue 0 Rx descriptor FIFO parity error */ -#define E1000_ICR_TXD_FIFO_PAR0 0x00200000 /* queue 0 Tx descriptor FIFO parity error */ -#define E1000_ICR_HOST_ARB_PAR 0x00400000 /* host arb read buffer parity error */ -#define E1000_ICR_PB_PAR 0x00800000 /* packet buffer parity error */ -#define E1000_ICR_RXD_FIFO_PAR1 0x01000000 /* queue 1 Rx descriptor FIFO parity error */ -#define E1000_ICR_TXD_FIFO_PAR1 0x02000000 /* queue 1 Tx descriptor FIFO parity error */ -#define E1000_ICR_ALL_PARITY 0x03F00000 /* all parity error bits */ -#define E1000_ICR_DSW 0x00000020 /* FW changed the status of DISSW bit in the FWSM */ -#define E1000_ICR_PHYINT 0x00001000 /* LAN connected device generates an interrupt */ -#define E1000_ICR_EPRST 0x00100000 /* ME hardware reset occurs */ - -/* Interrupt Cause Set */ -#define E1000_ICS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_ICS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_ICS_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_ICS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_ICS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_ICS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_ICS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_ICS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_ICS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_ICS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_ICS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_ICS_SRPD E1000_ICR_SRPD -#define E1000_ICS_ACK E1000_ICR_ACK /* Receive Ack frame */ -#define E1000_ICS_MNG E1000_ICR_MNG /* Manageability event */ -#define E1000_ICS_DOCK E1000_ICR_DOCK /* Dock/Undock */ -#define E1000_ICS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ -#define E1000_ICS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ -#define E1000_ICS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ -#define E1000_ICS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ -#define E1000_ICS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ -#define E1000_ICS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ -#define E1000_ICS_DSW E1000_ICR_DSW -#define E1000_ICS_PHYINT E1000_ICR_PHYINT -#define E1000_ICS_EPRST E1000_ICR_EPRST - -/* Interrupt Mask Set */ -#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMS_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_IMS_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_IMS_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_IMS_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_IMS_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_IMS_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_IMS_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_IMS_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_IMS_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_IMS_SRPD E1000_ICR_SRPD -#define E1000_IMS_ACK E1000_ICR_ACK /* Receive Ack frame */ -#define E1000_IMS_MNG E1000_ICR_MNG /* Manageability event */ -#define E1000_IMS_DOCK E1000_ICR_DOCK /* Dock/Undock */ -#define E1000_IMS_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ -#define E1000_IMS_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ -#define E1000_IMS_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ -#define E1000_IMS_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ -#define E1000_IMS_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ -#define E1000_IMS_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ -#define E1000_IMS_DSW E1000_ICR_DSW -#define E1000_IMS_PHYINT E1000_ICR_PHYINT -#define E1000_IMS_EPRST E1000_ICR_EPRST - -/* Interrupt Mask Clear */ -#define E1000_IMC_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMC_TXQE E1000_ICR_TXQE /* Transmit Queue empty */ -#define E1000_IMC_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMC_RXSEQ E1000_ICR_RXSEQ /* rx sequence error */ -#define E1000_IMC_RXDMT0 E1000_ICR_RXDMT0 /* rx desc min. threshold */ -#define E1000_IMC_RXO E1000_ICR_RXO /* rx overrun */ -#define E1000_IMC_RXT0 E1000_ICR_RXT0 /* rx timer intr */ -#define E1000_IMC_MDAC E1000_ICR_MDAC /* MDIO access complete */ -#define E1000_IMC_RXCFG E1000_ICR_RXCFG /* RX /c/ ordered set */ -#define E1000_IMC_GPI_EN0 E1000_ICR_GPI_EN0 /* GP Int 0 */ -#define E1000_IMC_GPI_EN1 E1000_ICR_GPI_EN1 /* GP Int 1 */ -#define E1000_IMC_GPI_EN2 E1000_ICR_GPI_EN2 /* GP Int 2 */ -#define E1000_IMC_GPI_EN3 E1000_ICR_GPI_EN3 /* GP Int 3 */ -#define E1000_IMC_TXD_LOW E1000_ICR_TXD_LOW -#define E1000_IMC_SRPD E1000_ICR_SRPD -#define E1000_IMC_ACK E1000_ICR_ACK /* Receive Ack frame */ -#define E1000_IMC_MNG E1000_ICR_MNG /* Manageability event */ -#define E1000_IMC_DOCK E1000_ICR_DOCK /* Dock/Undock */ -#define E1000_IMC_RXD_FIFO_PAR0 E1000_ICR_RXD_FIFO_PAR0 /* queue 0 Rx descriptor FIFO parity error */ -#define E1000_IMC_TXD_FIFO_PAR0 E1000_ICR_TXD_FIFO_PAR0 /* queue 0 Tx descriptor FIFO parity error */ -#define E1000_IMC_HOST_ARB_PAR E1000_ICR_HOST_ARB_PAR /* host arb read buffer parity error */ -#define E1000_IMC_PB_PAR E1000_ICR_PB_PAR /* packet buffer parity error */ -#define E1000_IMC_RXD_FIFO_PAR1 E1000_ICR_RXD_FIFO_PAR1 /* queue 1 Rx descriptor FIFO parity error */ -#define E1000_IMC_TXD_FIFO_PAR1 E1000_ICR_TXD_FIFO_PAR1 /* queue 1 Tx descriptor FIFO parity error */ -#define E1000_IMC_DSW E1000_ICR_DSW -#define E1000_IMC_PHYINT E1000_ICR_PHYINT -#define E1000_IMC_EPRST E1000_ICR_EPRST - -/* Receive Control */ -#define E1000_RCTL_RST 0x00000001 /* Software reset */ -#define E1000_RCTL_EN 0x00000002 /* enable */ -#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ -#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ -#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ -#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ -#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ -#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ -#define E1000_RCTL_LBM_SLP 0x00000080 /* serial link loopback mode */ -#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ -#define E1000_RCTL_DTYP_MASK 0x00000C00 /* Descriptor type mask */ -#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */ -#define E1000_RCTL_RDMTS_HALF 0x00000000 /* rx desc min threshold size */ -#define E1000_RCTL_RDMTS_QUAT 0x00000100 /* rx desc min threshold size */ -#define E1000_RCTL_RDMTS_EIGTH 0x00000200 /* rx desc min threshold size */ -#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ -#define E1000_RCTL_MO_0 0x00000000 /* multicast offset 11:0 */ -#define E1000_RCTL_MO_1 0x00001000 /* multicast offset 12:1 */ -#define E1000_RCTL_MO_2 0x00002000 /* multicast offset 13:2 */ -#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ -#define E1000_RCTL_MDR 0x00004000 /* multicast desc ring 0 */ -#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ -/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ -#define E1000_RCTL_SZ_2048 0x00000000 /* rx buffer size 2048 */ -#define E1000_RCTL_SZ_1024 0x00010000 /* rx buffer size 1024 */ -#define E1000_RCTL_SZ_512 0x00020000 /* rx buffer size 512 */ -#define E1000_RCTL_SZ_256 0x00030000 /* rx buffer size 256 */ -/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */ -#define E1000_RCTL_SZ_16384 0x00010000 /* rx buffer size 16384 */ -#define E1000_RCTL_SZ_8192 0x00020000 /* rx buffer size 8192 */ -#define E1000_RCTL_SZ_4096 0x00030000 /* rx buffer size 4096 */ -#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ -#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ -#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ -#define E1000_RCTL_DPF 0x00400000 /* discard pause frames */ -#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ -#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ -#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ -#define E1000_RCTL_FLXBUF_MASK 0x78000000 /* Flexible buffer size */ -#define E1000_RCTL_FLXBUF_SHIFT 27 /* Flexible buffer shift */ - -/* Use byte values for the following shift parameters - * Usage: - * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) & - * E1000_PSRCTL_BSIZE0_MASK) | - * ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) & - * E1000_PSRCTL_BSIZE1_MASK) | - * ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) & - * E1000_PSRCTL_BSIZE2_MASK) | - * ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |; - * E1000_PSRCTL_BSIZE3_MASK)) - * where value0 = [128..16256], default=256 - * value1 = [1024..64512], default=4096 - * value2 = [0..64512], default=4096 - * value3 = [0..64512], default=0 - */ - -#define E1000_PSRCTL_BSIZE0_MASK 0x0000007F -#define E1000_PSRCTL_BSIZE1_MASK 0x00003F00 -#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000 -#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000 - -#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */ -#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */ -#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */ -#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */ - -/* SW_W_SYNC definitions */ -#define E1000_SWFW_EEP_SM 0x0001 -#define E1000_SWFW_PHY0_SM 0x0002 -#define E1000_SWFW_PHY1_SM 0x0004 -#define E1000_SWFW_MAC_CSR_SM 0x0008 - -/* Receive Descriptor */ -#define E1000_RDT_DELAY 0x0000ffff /* Delay timer (1=1024us) */ -#define E1000_RDT_FPDB 0x80000000 /* Flush descriptor block */ -#define E1000_RDLEN_LEN 0x0007ff80 /* descriptor length */ -#define E1000_RDH_RDH 0x0000ffff /* receive descriptor head */ -#define E1000_RDT_RDT 0x0000ffff /* receive descriptor tail */ - -/* Flow Control */ -#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */ -#define E1000_FCRTH_XFCE 0x80000000 /* External Flow Control Enable */ -#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ -#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ - -/* Header split receive */ -#define E1000_RFCTL_ISCSI_DIS 0x00000001 -#define E1000_RFCTL_ISCSI_DWC_MASK 0x0000003E -#define E1000_RFCTL_ISCSI_DWC_SHIFT 1 -#define E1000_RFCTL_NFSW_DIS 0x00000040 -#define E1000_RFCTL_NFSR_DIS 0x00000080 -#define E1000_RFCTL_NFS_VER_MASK 0x00000300 -#define E1000_RFCTL_NFS_VER_SHIFT 8 -#define E1000_RFCTL_IPV6_DIS 0x00000400 -#define E1000_RFCTL_IPV6_XSUM_DIS 0x00000800 -#define E1000_RFCTL_ACK_DIS 0x00001000 -#define E1000_RFCTL_ACKD_DIS 0x00002000 -#define E1000_RFCTL_IPFRSP_DIS 0x00004000 -#define E1000_RFCTL_EXTEN 0x00008000 -#define E1000_RFCTL_IPV6_EX_DIS 0x00010000 -#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000 - -/* Receive Descriptor Control */ -#define E1000_RXDCTL_PTHRESH 0x0000003F /* RXDCTL Prefetch Threshold */ -#define E1000_RXDCTL_HTHRESH 0x00003F00 /* RXDCTL Host Threshold */ -#define E1000_RXDCTL_WTHRESH 0x003F0000 /* RXDCTL Writeback Threshold */ -#define E1000_RXDCTL_GRAN 0x01000000 /* RXDCTL Granularity */ - -/* Transmit Descriptor Control */ -#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */ -#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */ -#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */ -#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ -#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */ -#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ -#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc. - still to be processed. */ -/* Transmit Configuration Word */ -#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ -#define E1000_TXCW_HD 0x00000040 /* TXCW half duplex */ -#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ -#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ -#define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */ -#define E1000_TXCW_RF 0x00003000 /* TXCW remote fault */ -#define E1000_TXCW_NP 0x00008000 /* TXCW next page */ -#define E1000_TXCW_CW 0x0000ffff /* TxConfigWord mask */ -#define E1000_TXCW_TXC 0x40000000 /* Transmit Config control */ -#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */ - -/* Receive Configuration Word */ -#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */ -#define E1000_RXCW_NC 0x04000000 /* Receive config no carrier */ -#define E1000_RXCW_IV 0x08000000 /* Receive config invalid */ -#define E1000_RXCW_CC 0x10000000 /* Receive config change */ -#define E1000_RXCW_C 0x20000000 /* Receive config */ -#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ -#define E1000_RXCW_ANC 0x80000000 /* Auto-neg complete */ - -/* Transmit Control */ -#define E1000_TCTL_RST 0x00000001 /* software reset */ -#define E1000_TCTL_EN 0x00000002 /* enable tx */ -#define E1000_TCTL_BCE 0x00000004 /* busy check enable */ -#define E1000_TCTL_PSP 0x00000008 /* pad short packets */ -#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */ -#define E1000_TCTL_COLD 0x003ff000 /* collision distance */ -#define E1000_TCTL_SWXOFF 0x00400000 /* SW Xoff transmission */ -#define E1000_TCTL_PBE 0x00800000 /* Packet Burst Enable */ -#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ -#define E1000_TCTL_NRTU 0x02000000 /* No Re-transmit on underrun */ -#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */ -/* Extended Transmit Control */ -#define E1000_TCTL_EXT_BST_MASK 0x000003FF /* Backoff Slot Time */ -#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gigabit Carry Extend Padding */ - -/* Receive Checksum Control */ -#define E1000_RXCSUM_PCSS_MASK 0x000000FF /* Packet Checksum Start */ -#define E1000_RXCSUM_IPOFL 0x00000100 /* IPv4 checksum offload */ -#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ -#define E1000_RXCSUM_IPV6OFL 0x00000400 /* IPv6 checksum offload */ -#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ -#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ - -/* Multiple Receive Queue Control */ -#define E1000_MRQC_ENABLE_MASK 0x00000003 -#define E1000_MRQC_ENABLE_RSS_2Q 0x00000001 -#define E1000_MRQC_ENABLE_RSS_INT 0x00000004 -#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000 -#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 -#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000 -#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000 -#define E1000_MRQC_RSS_FIELD_IPV6_EX 0x00080000 -#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000 -#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 - -/* Definitions for power management and wakeup registers */ -/* Wake Up Control */ -#define E1000_WUC_APME 0x00000001 /* APM Enable */ -#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ -#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */ -#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */ -#define E1000_WUC_SPM 0x80000000 /* Enable SPM */ - -/* Wake Up Filter Control */ -#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ -#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ -#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ -#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ -#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ -#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ -#define E1000_WUFC_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Enable */ -#define E1000_WUFC_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Enable */ -#define E1000_WUFC_IGNORE_TCO 0x00008000 /* Ignore WakeOn TCO packets */ -#define E1000_WUFC_FLX0 0x00010000 /* Flexible Filter 0 Enable */ -#define E1000_WUFC_FLX1 0x00020000 /* Flexible Filter 1 Enable */ -#define E1000_WUFC_FLX2 0x00040000 /* Flexible Filter 2 Enable */ -#define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */ -#define E1000_WUFC_ALL_FILTERS 0x000F00FF /* Mask for all wakeup filters */ -#define E1000_WUFC_FLX_OFFSET 16 /* Offset to the Flexible Filters bits */ -#define E1000_WUFC_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ - -/* Wake Up Status */ -#define E1000_WUS_LNKC 0x00000001 /* Link Status Changed */ -#define E1000_WUS_MAG 0x00000002 /* Magic Packet Received */ -#define E1000_WUS_EX 0x00000004 /* Directed Exact Received */ -#define E1000_WUS_MC 0x00000008 /* Directed Multicast Received */ -#define E1000_WUS_BC 0x00000010 /* Broadcast Received */ -#define E1000_WUS_ARP 0x00000020 /* ARP Request Packet Received */ -#define E1000_WUS_IPV4 0x00000040 /* Directed IPv4 Packet Wakeup Received */ -#define E1000_WUS_IPV6 0x00000080 /* Directed IPv6 Packet Wakeup Received */ -#define E1000_WUS_FLX0 0x00010000 /* Flexible Filter 0 Match */ -#define E1000_WUS_FLX1 0x00020000 /* Flexible Filter 1 Match */ -#define E1000_WUS_FLX2 0x00040000 /* Flexible Filter 2 Match */ -#define E1000_WUS_FLX3 0x00080000 /* Flexible Filter 3 Match */ -#define E1000_WUS_FLX_FILTERS 0x000F0000 /* Mask for the 4 flexible filters */ - -/* Management Control */ -#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ -#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ -#define E1000_MANC_R_ON_FORCE 0x00000004 /* Reset on Force TCO - RO */ -#define E1000_MANC_RMCP_EN 0x00000100 /* Enable RCMP 026Fh Filtering */ -#define E1000_MANC_0298_EN 0x00000200 /* Enable RCMP 0298h Filtering */ -#define E1000_MANC_IPV4_EN 0x00000400 /* Enable IPv4 */ -#define E1000_MANC_IPV6_EN 0x00000800 /* Enable IPv6 */ -#define E1000_MANC_SNAP_EN 0x00001000 /* Accept LLC/SNAP */ -#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ -#define E1000_MANC_NEIGHBOR_EN 0x00004000 /* Enable Neighbor Discovery - * Filtering */ -#define E1000_MANC_ARP_RES_EN 0x00008000 /* Enable ARP response Filtering */ -#define E1000_MANC_TCO_RESET 0x00010000 /* TCO Reset Occurred */ -#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ -#define E1000_MANC_REPORT_STATUS 0x00040000 /* Status Reporting Enabled */ -#define E1000_MANC_RCV_ALL 0x00080000 /* Receive All Enabled */ -#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ -#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 /* Enable MAC address - * filtering */ -#define E1000_MANC_EN_MNG2HOST 0x00200000 /* Enable MNG packets to host - * memory */ -#define E1000_MANC_EN_IP_ADDR_FILTER 0x00400000 /* Enable IP address - * filtering */ -#define E1000_MANC_EN_XSUM_FILTER 0x00800000 /* Enable checksum filtering */ -#define E1000_MANC_BR_EN 0x01000000 /* Enable broadcast filtering */ -#define E1000_MANC_SMB_REQ 0x01000000 /* SMBus Request */ -#define E1000_MANC_SMB_GNT 0x02000000 /* SMBus Grant */ -#define E1000_MANC_SMB_CLK_IN 0x04000000 /* SMBus Clock In */ -#define E1000_MANC_SMB_DATA_IN 0x08000000 /* SMBus Data In */ -#define E1000_MANC_SMB_DATA_OUT 0x10000000 /* SMBus Data Out */ -#define E1000_MANC_SMB_CLK_OUT 0x20000000 /* SMBus Clock Out */ - -#define E1000_MANC_SMB_DATA_OUT_SHIFT 28 /* SMBus Data Out Shift */ -#define E1000_MANC_SMB_CLK_OUT_SHIFT 29 /* SMBus Clock Out Shift */ - -/* SW Semaphore Register */ -#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ -#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ -#define E1000_SWSM_WMNG 0x00000004 /* Wake MNG Clock */ -#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */ - -/* FW Semaphore Register */ -#define E1000_FWSM_MODE_MASK 0x0000000E /* FW mode */ -#define E1000_FWSM_MODE_SHIFT 1 -#define E1000_FWSM_FW_VALID 0x00008000 /* FW established a valid mode */ - -#define E1000_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI reset */ -#define E1000_FWSM_DISSW 0x10000000 /* FW disable SW Write Access */ -#define E1000_FWSM_SKUSEL_MASK 0x60000000 /* LAN SKU select */ -#define E1000_FWSM_SKUEL_SHIFT 29 -#define E1000_FWSM_SKUSEL_EMB 0x0 /* Embedded SKU */ -#define E1000_FWSM_SKUSEL_CONS 0x1 /* Consumer SKU */ -#define E1000_FWSM_SKUSEL_PERF_100 0x2 /* Perf & Corp 10/100 SKU */ -#define E1000_FWSM_SKUSEL_PERF_GBE 0x3 /* Perf & Copr GbE SKU */ - -/* FFLT Debug Register */ -#define E1000_FFLT_DBG_INVC 0x00100000 /* Invalid /C/ code handling */ - -typedef enum { - e1000_mng_mode_none = 0, - e1000_mng_mode_asf, - e1000_mng_mode_pt, - e1000_mng_mode_ipmi, - e1000_mng_mode_host_interface_only -} e1000_mng_mode; - -/* Host Interface Control Register */ -#define E1000_HICR_EN 0x00000001 /* Enable Bit - RO */ -#define E1000_HICR_C 0x00000002 /* Driver sets this bit when done - * to put command in RAM */ -#define E1000_HICR_SV 0x00000004 /* Status Validity */ -#define E1000_HICR_FWR 0x00000080 /* FW reset. Set by the Host */ - -/* Host Interface Command Interface - Address range 0x8800-0x8EFF */ -#define E1000_HI_MAX_DATA_LENGTH 252 /* Host Interface data length */ -#define E1000_HI_MAX_BLOCK_BYTE_LENGTH 1792 /* Number of bytes in range */ -#define E1000_HI_MAX_BLOCK_DWORD_LENGTH 448 /* Number of dwords in range */ -#define E1000_HI_COMMAND_TIMEOUT 500 /* Time in ms to process HI command */ - -struct e1000_host_command_header { - u8 command_id; - u8 command_length; - u8 command_options; /* I/F bits for command, status for return */ - u8 checksum; -}; -struct e1000_host_command_info { - struct e1000_host_command_header command_header; /* Command Head/Command Result Head has 4 bytes */ - u8 command_data[E1000_HI_MAX_DATA_LENGTH]; /* Command data can length 0..252 */ -}; - -/* Host SMB register #0 */ -#define E1000_HSMC0R_CLKIN 0x00000001 /* SMB Clock in */ -#define E1000_HSMC0R_DATAIN 0x00000002 /* SMB Data in */ -#define E1000_HSMC0R_DATAOUT 0x00000004 /* SMB Data out */ -#define E1000_HSMC0R_CLKOUT 0x00000008 /* SMB Clock out */ - -/* Host SMB register #1 */ -#define E1000_HSMC1R_CLKIN E1000_HSMC0R_CLKIN -#define E1000_HSMC1R_DATAIN E1000_HSMC0R_DATAIN -#define E1000_HSMC1R_DATAOUT E1000_HSMC0R_DATAOUT -#define E1000_HSMC1R_CLKOUT E1000_HSMC0R_CLKOUT - -/* FW Status Register */ -#define E1000_FWSTS_FWS_MASK 0x000000FF /* FW Status */ - -/* Wake Up Packet Length */ -#define E1000_WUPL_LENGTH_MASK 0x0FFF /* Only the lower 12 bits are valid */ - -#define E1000_MDALIGN 4096 - -/* PCI-Ex registers*/ - -/* PCI-Ex Control Register */ -#define E1000_GCR_RXD_NO_SNOOP 0x00000001 -#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 -#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004 -#define E1000_GCR_TXD_NO_SNOOP 0x00000008 -#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 -#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 - -#define PCI_EX_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ - E1000_GCR_RXDSCW_NO_SNOOP | \ - E1000_GCR_RXDSCR_NO_SNOOP | \ - E1000_GCR_TXD_NO_SNOOP | \ - E1000_GCR_TXDSCW_NO_SNOOP | \ - E1000_GCR_TXDSCR_NO_SNOOP) - -#define PCI_EX_82566_SNOOP_ALL PCI_EX_NO_SNOOP_ALL - -#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 -/* Function Active and Power State to MNG */ -#define E1000_FACTPS_FUNC0_POWER_STATE_MASK 0x00000003 -#define E1000_FACTPS_LAN0_VALID 0x00000004 -#define E1000_FACTPS_FUNC0_AUX_EN 0x00000008 -#define E1000_FACTPS_FUNC1_POWER_STATE_MASK 0x000000C0 -#define E1000_FACTPS_FUNC1_POWER_STATE_SHIFT 6 -#define E1000_FACTPS_LAN1_VALID 0x00000100 -#define E1000_FACTPS_FUNC1_AUX_EN 0x00000200 -#define E1000_FACTPS_FUNC2_POWER_STATE_MASK 0x00003000 -#define E1000_FACTPS_FUNC2_POWER_STATE_SHIFT 12 -#define E1000_FACTPS_IDE_ENABLE 0x00004000 -#define E1000_FACTPS_FUNC2_AUX_EN 0x00008000 -#define E1000_FACTPS_FUNC3_POWER_STATE_MASK 0x000C0000 -#define E1000_FACTPS_FUNC3_POWER_STATE_SHIFT 18 -#define E1000_FACTPS_SP_ENABLE 0x00100000 -#define E1000_FACTPS_FUNC3_AUX_EN 0x00200000 -#define E1000_FACTPS_FUNC4_POWER_STATE_MASK 0x03000000 -#define E1000_FACTPS_FUNC4_POWER_STATE_SHIFT 24 -#define E1000_FACTPS_IPMI_ENABLE 0x04000000 -#define E1000_FACTPS_FUNC4_AUX_EN 0x08000000 -#define E1000_FACTPS_MNGCG 0x20000000 -#define E1000_FACTPS_LAN_FUNC_SEL 0x40000000 -#define E1000_FACTPS_PM_STATE_CHANGED 0x80000000 - -/* PCI-Ex Config Space */ -#define PCI_EX_LINK_STATUS 0x12 -#define PCI_EX_LINK_WIDTH_MASK 0x3F0 -#define PCI_EX_LINK_WIDTH_SHIFT 4 - -/* EEPROM Commands - Microwire */ -#define EEPROM_READ_OPCODE_MICROWIRE 0x6 /* EEPROM read opcode */ -#define EEPROM_WRITE_OPCODE_MICROWIRE 0x5 /* EEPROM write opcode */ -#define EEPROM_ERASE_OPCODE_MICROWIRE 0x7 /* EEPROM erase opcode */ -#define EEPROM_EWEN_OPCODE_MICROWIRE 0x13 /* EEPROM erase/write enable */ -#define EEPROM_EWDS_OPCODE_MICROWIRE 0x10 /* EEPROM erase/write disable */ - -/* EEPROM Commands - SPI */ -#define EEPROM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ -#define EEPROM_READ_OPCODE_SPI 0x03 /* EEPROM read opcode */ -#define EEPROM_WRITE_OPCODE_SPI 0x02 /* EEPROM write opcode */ -#define EEPROM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */ -#define EEPROM_WREN_OPCODE_SPI 0x06 /* EEPROM set Write Enable latch */ -#define EEPROM_WRDI_OPCODE_SPI 0x04 /* EEPROM reset Write Enable latch */ -#define EEPROM_RDSR_OPCODE_SPI 0x05 /* EEPROM read Status register */ -#define EEPROM_WRSR_OPCODE_SPI 0x01 /* EEPROM write Status register */ -#define EEPROM_ERASE4K_OPCODE_SPI 0x20 /* EEPROM ERASE 4KB */ -#define EEPROM_ERASE64K_OPCODE_SPI 0xD8 /* EEPROM ERASE 64KB */ -#define EEPROM_ERASE256_OPCODE_SPI 0xDB /* EEPROM ERASE 256B */ - -/* EEPROM Size definitions */ -#define EEPROM_WORD_SIZE_SHIFT 6 -#define EEPROM_SIZE_SHIFT 10 -#define EEPROM_SIZE_MASK 0x1C00 - -/* EEPROM Word Offsets */ -#define EEPROM_COMPAT 0x0003 -#define EEPROM_ID_LED_SETTINGS 0x0004 -#define EEPROM_VERSION 0x0005 -#define EEPROM_SERDES_AMPLITUDE 0x0006 /* For SERDES output amplitude adjustment. */ -#define EEPROM_PHY_CLASS_WORD 0x0007 -#define EEPROM_INIT_CONTROL1_REG 0x000A -#define EEPROM_INIT_CONTROL2_REG 0x000F -#define EEPROM_SWDEF_PINS_CTRL_PORT_1 0x0010 -#define EEPROM_INIT_CONTROL3_PORT_B 0x0014 -#define EEPROM_INIT_3GIO_3 0x001A -#define EEPROM_SWDEF_PINS_CTRL_PORT_0 0x0020 -#define EEPROM_INIT_CONTROL3_PORT_A 0x0024 -#define EEPROM_CFG 0x0012 -#define EEPROM_FLASH_VERSION 0x0032 -#define EEPROM_CHECKSUM_REG 0x003F - -#define E1000_EEPROM_CFG_DONE 0x00040000 /* MNG config cycle done */ -#define E1000_EEPROM_CFG_DONE_PORT_1 0x00080000 /* ...for second port */ - -/* Word definitions for ID LED Settings */ -#define ID_LED_RESERVED_0000 0x0000 -#define ID_LED_RESERVED_FFFF 0xFFFF -#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ - (ID_LED_OFF1_OFF2 << 8) | \ - (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_DEF1_DEF2)) -#define ID_LED_DEF1_DEF2 0x1 -#define ID_LED_DEF1_ON2 0x2 -#define ID_LED_DEF1_OFF2 0x3 -#define ID_LED_ON1_DEF2 0x4 -#define ID_LED_ON1_ON2 0x5 -#define ID_LED_ON1_OFF2 0x6 -#define ID_LED_OFF1_DEF2 0x7 -#define ID_LED_OFF1_ON2 0x8 -#define ID_LED_OFF1_OFF2 0x9 - -#define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF -#define IGP_ACTIVITY_LED_ENABLE 0x0300 -#define IGP_LED3_MODE 0x07000000 - -/* Mask bits for SERDES amplitude adjustment in Word 6 of the EEPROM */ -#define EEPROM_SERDES_AMPLITUDE_MASK 0x000F - -/* Mask bit for PHY class in Word 7 of the EEPROM */ -#define EEPROM_PHY_CLASS_A 0x8000 - -/* Mask bits for fields in Word 0x0a of the EEPROM */ -#define EEPROM_WORD0A_ILOS 0x0010 -#define EEPROM_WORD0A_SWDPIO 0x01E0 -#define EEPROM_WORD0A_LRST 0x0200 -#define EEPROM_WORD0A_FD 0x0400 -#define EEPROM_WORD0A_66MHZ 0x0800 - -/* Mask bits for fields in Word 0x0f of the EEPROM */ -#define EEPROM_WORD0F_PAUSE_MASK 0x3000 -#define EEPROM_WORD0F_PAUSE 0x1000 -#define EEPROM_WORD0F_ASM_DIR 0x2000 -#define EEPROM_WORD0F_ANE 0x0800 -#define EEPROM_WORD0F_SWPDIO_EXT 0x00F0 -#define EEPROM_WORD0F_LPLU 0x0001 - -/* Mask bits for fields in Word 0x10/0x20 of the EEPROM */ -#define EEPROM_WORD1020_GIGA_DISABLE 0x0010 -#define EEPROM_WORD1020_GIGA_DISABLE_NON_D0A 0x0008 - -/* Mask bits for fields in Word 0x1a of the EEPROM */ -#define EEPROM_WORD1A_ASPM_MASK 0x000C - -/* For checksumming, the sum of all words in the EEPROM should equal 0xBABA. */ -#define EEPROM_SUM 0xBABA - -/* EEPROM Map defines (WORD OFFSETS)*/ -#define EEPROM_NODE_ADDRESS_BYTE_0 0 -#define EEPROM_PBA_BYTE_1 8 - -#define EEPROM_RESERVED_WORD 0xFFFF - -/* EEPROM Map Sizes (Byte Counts) */ -#define PBA_SIZE 4 - -/* Collision related configuration parameters */ -#define E1000_COLLISION_THRESHOLD 15 -#define E1000_CT_SHIFT 4 -/* Collision distance is a 0-based value that applies to - * half-duplex-capable hardware only. */ -#define E1000_COLLISION_DISTANCE 63 -#define E1000_COLLISION_DISTANCE_82542 64 -#define E1000_FDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE -#define E1000_HDX_COLLISION_DISTANCE E1000_COLLISION_DISTANCE -#define E1000_COLD_SHIFT 12 - -/* Number of Transmit and Receive Descriptors must be a multiple of 8 */ -#define REQ_TX_DESCRIPTOR_MULTIPLE 8 -#define REQ_RX_DESCRIPTOR_MULTIPLE 8 - -/* Default values for the transmit IPG register */ -#define DEFAULT_82542_TIPG_IPGT 10 -#define DEFAULT_82543_TIPG_IPGT_FIBER 9 -#define DEFAULT_82543_TIPG_IPGT_COPPER 8 - -#define E1000_TIPG_IPGT_MASK 0x000003FF -#define E1000_TIPG_IPGR1_MASK 0x000FFC00 -#define E1000_TIPG_IPGR2_MASK 0x3FF00000 - -#define DEFAULT_82542_TIPG_IPGR1 2 -#define DEFAULT_82543_TIPG_IPGR1 8 -#define E1000_TIPG_IPGR1_SHIFT 10 - -#define DEFAULT_82542_TIPG_IPGR2 10 -#define DEFAULT_82543_TIPG_IPGR2 6 -#define E1000_TIPG_IPGR2_SHIFT 20 - -#define E1000_TXDMAC_DPP 0x00000001 - -/* Adaptive IFS defines */ -#define TX_THRESHOLD_START 8 -#define TX_THRESHOLD_INCREMENT 10 -#define TX_THRESHOLD_DECREMENT 1 -#define TX_THRESHOLD_STOP 190 -#define TX_THRESHOLD_DISABLE 0 -#define TX_THRESHOLD_TIMER_MS 10000 -#define MIN_NUM_XMITS 1000 -#define IFS_MAX 80 -#define IFS_STEP 10 -#define IFS_MIN 40 -#define IFS_RATIO 4 - -/* Extended Configuration Control and Size */ -#define E1000_EXTCNF_CTRL_PCIE_WRITE_ENABLE 0x00000001 -#define E1000_EXTCNF_CTRL_PHY_WRITE_ENABLE 0x00000002 -#define E1000_EXTCNF_CTRL_D_UD_ENABLE 0x00000004 -#define E1000_EXTCNF_CTRL_D_UD_LATENCY 0x00000008 -#define E1000_EXTCNF_CTRL_D_UD_OWNER 0x00000010 -#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 -#define E1000_EXTCNF_CTRL_MDIO_HW_OWNERSHIP 0x00000040 -#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER 0x0FFF0000 - -#define E1000_EXTCNF_SIZE_EXT_PHY_LENGTH 0x000000FF -#define E1000_EXTCNF_SIZE_EXT_DOCK_LENGTH 0x0000FF00 -#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH 0x00FF0000 -#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 -#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 - -/* PBA constants */ -#define E1000_PBA_8K 0x0008 /* 8KB, default Rx allocation */ -#define E1000_PBA_12K 0x000C /* 12KB, default Rx allocation */ -#define E1000_PBA_16K 0x0010 /* 16KB, default TX allocation */ -#define E1000_PBA_20K 0x0014 -#define E1000_PBA_22K 0x0016 -#define E1000_PBA_24K 0x0018 -#define E1000_PBA_30K 0x001E -#define E1000_PBA_32K 0x0020 -#define E1000_PBA_34K 0x0022 -#define E1000_PBA_38K 0x0026 -#define E1000_PBA_40K 0x0028 -#define E1000_PBA_48K 0x0030 /* 48KB, default RX allocation */ - -#define E1000_PBS_16K E1000_PBA_16K - -/* Flow Control Constants */ -#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 -#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 -#define FLOW_CONTROL_TYPE 0x8808 - -/* The historical defaults for the flow control values are given below. */ -#define FC_DEFAULT_HI_THRESH (0x8000) /* 32KB */ -#define FC_DEFAULT_LO_THRESH (0x4000) /* 16KB */ -#define FC_DEFAULT_TX_TIMER (0x100) /* ~130 us */ - -/* PCIX Config space */ -#define PCIX_COMMAND_REGISTER 0xE6 -#define PCIX_STATUS_REGISTER_LO 0xE8 -#define PCIX_STATUS_REGISTER_HI 0xEA - -#define PCIX_COMMAND_MMRBC_MASK 0x000C -#define PCIX_COMMAND_MMRBC_SHIFT 0x2 -#define PCIX_STATUS_HI_MMRBC_MASK 0x0060 -#define PCIX_STATUS_HI_MMRBC_SHIFT 0x5 -#define PCIX_STATUS_HI_MMRBC_4K 0x3 -#define PCIX_STATUS_HI_MMRBC_2K 0x2 - -/* Number of bits required to shift right the "pause" bits from the - * EEPROM (bits 13:12) to the "pause" (bits 8:7) field in the TXCW register. - */ -#define PAUSE_SHIFT 5 - -/* Number of bits required to shift left the "SWDPIO" bits from the - * EEPROM (bits 8:5) to the "SWDPIO" (bits 25:22) field in the CTRL register. - */ -#define SWDPIO_SHIFT 17 - -/* Number of bits required to shift left the "SWDPIO_EXT" bits from the - * EEPROM word F (bits 7:4) to the bits 11:8 of The Extended CTRL register. - */ -#define SWDPIO__EXT_SHIFT 4 - -/* Number of bits required to shift left the "ILOS" bit from the EEPROM - * (bit 4) to the "ILOS" (bit 7) field in the CTRL register. - */ -#define ILOS_SHIFT 3 - -#define RECEIVE_BUFFER_ALIGN_SIZE (256) - -/* Number of milliseconds we wait for auto-negotiation to complete */ -#define LINK_UP_TIMEOUT 500 - -/* Number of milliseconds we wait for Eeprom auto read bit done after MAC reset */ -#define AUTO_READ_DONE_TIMEOUT 10 -/* Number of milliseconds we wait for PHY configuration done after MAC reset */ -#define PHY_CFG_TIMEOUT 100 - -#define E1000_TX_BUFFER_SIZE ((u32)1514) - -/* The carrier extension symbol, as received by the NIC. */ -#define CARRIER_EXTENSION 0x0F - -/* TBI_ACCEPT macro definition: - * - * This macro requires: - * adapter = a pointer to struct e1000_hw - * status = the 8 bit status field of the RX descriptor with EOP set - * error = the 8 bit error field of the RX descriptor with EOP set - * length = the sum of all the length fields of the RX descriptors that - * make up the current frame - * last_byte = the last byte of the frame DMAed by the hardware - * max_frame_length = the maximum frame length we want to accept. - * min_frame_length = the minimum frame length we want to accept. - * - * This macro is a conditional that should be used in the interrupt - * handler's Rx processing routine when RxErrors have been detected. - * - * Typical use: - * ... - * if (TBI_ACCEPT) { - * accept_frame = true; - * e1000_tbi_adjust_stats(adapter, MacAddress); - * frame_length--; - * } else { - * accept_frame = false; - * } - * ... - */ - -#define TBI_ACCEPT(adapter, status, errors, length, last_byte) \ - ((adapter)->tbi_compatibility_on && \ - (((errors) & E1000_RXD_ERR_FRAME_ERR_MASK) == E1000_RXD_ERR_CE) && \ - ((last_byte) == CARRIER_EXTENSION) && \ - (((status) & E1000_RXD_STAT_VP) ? \ - (((length) > ((adapter)->min_frame_size - VLAN_TAG_SIZE)) && \ - ((length) <= ((adapter)->max_frame_size + 1))) : \ - (((length) > (adapter)->min_frame_size) && \ - ((length) <= ((adapter)->max_frame_size + VLAN_TAG_SIZE + 1))))) - -/* Structures, enums, and macros for the PHY */ - -/* Bit definitions for the Management Data IO (MDIO) and Management Data - * Clock (MDC) pins in the Device Control Register. - */ -#define E1000_CTRL_PHY_RESET_DIR E1000_CTRL_SWDPIO0 -#define E1000_CTRL_PHY_RESET E1000_CTRL_SWDPIN0 -#define E1000_CTRL_MDIO_DIR E1000_CTRL_SWDPIO2 -#define E1000_CTRL_MDIO E1000_CTRL_SWDPIN2 -#define E1000_CTRL_MDC_DIR E1000_CTRL_SWDPIO3 -#define E1000_CTRL_MDC E1000_CTRL_SWDPIN3 -#define E1000_CTRL_PHY_RESET_DIR4 E1000_CTRL_EXT_SDP4_DIR -#define E1000_CTRL_PHY_RESET4 E1000_CTRL_EXT_SDP4_DATA - -/* PHY 1000 MII Register/Bit Definitions */ -/* PHY Registers defined by IEEE */ -#define PHY_CTRL 0x00 /* Control Register */ -#define PHY_STATUS 0x01 /* Status Register */ -#define PHY_ID1 0x02 /* Phy Id Reg (word 1) */ -#define PHY_ID2 0x03 /* Phy Id Reg (word 2) */ -#define PHY_AUTONEG_ADV 0x04 /* Autoneg Advertisement */ -#define PHY_LP_ABILITY 0x05 /* Link Partner Ability (Base Page) */ -#define PHY_AUTONEG_EXP 0x06 /* Autoneg Expansion Reg */ -#define PHY_NEXT_PAGE_TX 0x07 /* Next Page TX */ -#define PHY_LP_NEXT_PAGE 0x08 /* Link Partner Next Page */ -#define PHY_1000T_CTRL 0x09 /* 1000Base-T Control Reg */ -#define PHY_1000T_STATUS 0x0A /* 1000Base-T Status Reg */ -#define PHY_EXT_STATUS 0x0F /* Extended Status Reg */ - -#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ -#define MAX_PHY_MULTI_PAGE_REG 0xF /* Registers equal on all pages */ - -/* M88E1000 Specific Registers */ -#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ -#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */ -#define M88E1000_INT_ENABLE 0x12 /* Interrupt Enable Register */ -#define M88E1000_INT_STATUS 0x13 /* Interrupt Status Register */ -#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ -#define M88E1000_RX_ERR_CNTR 0x15 /* Receive Error Counter */ - -#define M88E1000_PHY_EXT_CTRL 0x1A /* PHY extend control register */ -#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */ -#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */ -#define M88E1000_PHY_VCO_REG_BIT8 0x100 /* Bits 8 & 11 are adjusted for */ -#define M88E1000_PHY_VCO_REG_BIT11 0x800 /* improved BER performance */ - -#define IGP01E1000_IEEE_REGS_PAGE 0x0000 -#define IGP01E1000_IEEE_RESTART_AUTONEG 0x3300 -#define IGP01E1000_IEEE_FORCE_GIGA 0x0140 - -/* IGP01E1000 Specific Registers */ -#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* PHY Specific Port Config Register */ -#define IGP01E1000_PHY_PORT_STATUS 0x11 /* PHY Specific Status Register */ -#define IGP01E1000_PHY_PORT_CTRL 0x12 /* PHY Specific Control Register */ -#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health Register */ -#define IGP01E1000_GMII_FIFO 0x14 /* GMII FIFO Register */ -#define IGP01E1000_PHY_CHANNEL_QUALITY 0x15 /* PHY Channel Quality Register */ -#define IGP02E1000_PHY_POWER_MGMT 0x19 -#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* PHY Page Select Core Register */ - -/* IGP01E1000 AGC Registers - stores the cable length values*/ -#define IGP01E1000_PHY_AGC_A 0x1172 -#define IGP01E1000_PHY_AGC_B 0x1272 -#define IGP01E1000_PHY_AGC_C 0x1472 -#define IGP01E1000_PHY_AGC_D 0x1872 - -/* IGP02E1000 AGC Registers for cable length values */ -#define IGP02E1000_PHY_AGC_A 0x11B1 -#define IGP02E1000_PHY_AGC_B 0x12B1 -#define IGP02E1000_PHY_AGC_C 0x14B1 -#define IGP02E1000_PHY_AGC_D 0x18B1 - -/* IGP01E1000 DSP Reset Register */ -#define IGP01E1000_PHY_DSP_RESET 0x1F33 -#define IGP01E1000_PHY_DSP_SET 0x1F71 -#define IGP01E1000_PHY_DSP_FFE 0x1F35 - -#define IGP01E1000_PHY_CHANNEL_NUM 4 -#define IGP02E1000_PHY_CHANNEL_NUM 4 - -#define IGP01E1000_PHY_AGC_PARAM_A 0x1171 -#define IGP01E1000_PHY_AGC_PARAM_B 0x1271 -#define IGP01E1000_PHY_AGC_PARAM_C 0x1471 -#define IGP01E1000_PHY_AGC_PARAM_D 0x1871 - -#define IGP01E1000_PHY_EDAC_MU_INDEX 0xC000 -#define IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS 0x8000 - -#define IGP01E1000_PHY_ANALOG_TX_STATE 0x2890 -#define IGP01E1000_PHY_ANALOG_CLASS_A 0x2000 -#define IGP01E1000_PHY_FORCE_ANALOG_ENABLE 0x0004 -#define IGP01E1000_PHY_DSP_FFE_CM_CP 0x0069 - -#define IGP01E1000_PHY_DSP_FFE_DEFAULT 0x002A -/* IGP01E1000 PCS Initialization register - stores the polarity status when - * speed = 1000 Mbps. */ -#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 -#define IGP01E1000_PHY_PCS_CTRL_REG 0x00B5 - -#define IGP01E1000_ANALOG_REGS_PAGE 0x20C0 - -/* PHY Control Register */ -#define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ -#define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ -#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ -#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ -#define MII_CR_ISOLATE 0x0400 /* Isolate PHY from MII */ -#define MII_CR_POWER_DOWN 0x0800 /* Power down */ -#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ -#define MII_CR_SPEED_SELECT_LSB 0x2000 /* bits 6,13: 10=1000, 01=100, 00=10 */ -#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ -#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ - -/* PHY Status Register */ -#define MII_SR_EXTENDED_CAPS 0x0001 /* Extended register capabilities */ -#define MII_SR_JABBER_DETECT 0x0002 /* Jabber Detected */ -#define MII_SR_LINK_STATUS 0x0004 /* Link Status 1 = link */ -#define MII_SR_AUTONEG_CAPS 0x0008 /* Auto Neg Capable */ -#define MII_SR_REMOTE_FAULT 0x0010 /* Remote Fault Detect */ -#define MII_SR_AUTONEG_COMPLETE 0x0020 /* Auto Neg Complete */ -#define MII_SR_PREAMBLE_SUPPRESS 0x0040 /* Preamble may be suppressed */ -#define MII_SR_EXTENDED_STATUS 0x0100 /* Ext. status info in Reg 0x0F */ -#define MII_SR_100T2_HD_CAPS 0x0200 /* 100T2 Half Duplex Capable */ -#define MII_SR_100T2_FD_CAPS 0x0400 /* 100T2 Full Duplex Capable */ -#define MII_SR_10T_HD_CAPS 0x0800 /* 10T Half Duplex Capable */ -#define MII_SR_10T_FD_CAPS 0x1000 /* 10T Full Duplex Capable */ -#define MII_SR_100X_HD_CAPS 0x2000 /* 100X Half Duplex Capable */ -#define MII_SR_100X_FD_CAPS 0x4000 /* 100X Full Duplex Capable */ -#define MII_SR_100T4_CAPS 0x8000 /* 100T4 Capable */ - -/* Autoneg Advertisement Register */ -#define NWAY_AR_SELECTOR_FIELD 0x0001 /* indicates IEEE 802.3 CSMA/CD */ -#define NWAY_AR_10T_HD_CAPS 0x0020 /* 10T Half Duplex Capable */ -#define NWAY_AR_10T_FD_CAPS 0x0040 /* 10T Full Duplex Capable */ -#define NWAY_AR_100TX_HD_CAPS 0x0080 /* 100TX Half Duplex Capable */ -#define NWAY_AR_100TX_FD_CAPS 0x0100 /* 100TX Full Duplex Capable */ -#define NWAY_AR_100T4_CAPS 0x0200 /* 100T4 Capable */ -#define NWAY_AR_PAUSE 0x0400 /* Pause operation desired */ -#define NWAY_AR_ASM_DIR 0x0800 /* Asymmetric Pause Direction bit */ -#define NWAY_AR_REMOTE_FAULT 0x2000 /* Remote Fault detected */ -#define NWAY_AR_NEXT_PAGE 0x8000 /* Next Page ability supported */ - -/* Link Partner Ability Register (Base Page) */ -#define NWAY_LPAR_SELECTOR_FIELD 0x0000 /* LP protocol selector field */ -#define NWAY_LPAR_10T_HD_CAPS 0x0020 /* LP is 10T Half Duplex Capable */ -#define NWAY_LPAR_10T_FD_CAPS 0x0040 /* LP is 10T Full Duplex Capable */ -#define NWAY_LPAR_100TX_HD_CAPS 0x0080 /* LP is 100TX Half Duplex Capable */ -#define NWAY_LPAR_100TX_FD_CAPS 0x0100 /* LP is 100TX Full Duplex Capable */ -#define NWAY_LPAR_100T4_CAPS 0x0200 /* LP is 100T4 Capable */ -#define NWAY_LPAR_PAUSE 0x0400 /* LP Pause operation desired */ -#define NWAY_LPAR_ASM_DIR 0x0800 /* LP Asymmetric Pause Direction bit */ -#define NWAY_LPAR_REMOTE_FAULT 0x2000 /* LP has detected Remote Fault */ -#define NWAY_LPAR_ACKNOWLEDGE 0x4000 /* LP has rx'd link code word */ -#define NWAY_LPAR_NEXT_PAGE 0x8000 /* Next Page ability supported */ - -/* Autoneg Expansion Register */ -#define NWAY_ER_LP_NWAY_CAPS 0x0001 /* LP has Auto Neg Capability */ -#define NWAY_ER_PAGE_RXD 0x0002 /* LP is 10T Half Duplex Capable */ -#define NWAY_ER_NEXT_PAGE_CAPS 0x0004 /* LP is 10T Full Duplex Capable */ -#define NWAY_ER_LP_NEXT_PAGE_CAPS 0x0008 /* LP is 100TX Half Duplex Capable */ -#define NWAY_ER_PAR_DETECT_FAULT 0x0010 /* LP is 100TX Full Duplex Capable */ - -/* Next Page TX Register */ -#define NPTX_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ -#define NPTX_TOGGLE 0x0800 /* Toggles between exchanges - * of different NP - */ -#define NPTX_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg - * 0 = cannot comply with msg - */ -#define NPTX_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ -#define NPTX_NEXT_PAGE 0x8000 /* 1 = addition NP will follow - * 0 = sending last NP - */ - -/* Link Partner Next Page Register */ -#define LP_RNPR_MSG_CODE_FIELD 0x0001 /* NP msg code or unformatted data */ -#define LP_RNPR_TOGGLE 0x0800 /* Toggles between exchanges - * of different NP - */ -#define LP_RNPR_ACKNOWLDGE2 0x1000 /* 1 = will comply with msg - * 0 = cannot comply with msg - */ -#define LP_RNPR_MSG_PAGE 0x2000 /* formatted(1)/unformatted(0) pg */ -#define LP_RNPR_ACKNOWLDGE 0x4000 /* 1 = ACK / 0 = NO ACK */ -#define LP_RNPR_NEXT_PAGE 0x8000 /* 1 = addition NP will follow - * 0 = sending last NP - */ - -/* 1000BASE-T Control Register */ -#define CR_1000T_ASYM_PAUSE 0x0080 /* Advertise asymmetric pause bit */ -#define CR_1000T_HD_CAPS 0x0100 /* Advertise 1000T HD capability */ -#define CR_1000T_FD_CAPS 0x0200 /* Advertise 1000T FD capability */ -#define CR_1000T_REPEATER_DTE 0x0400 /* 1=Repeater/switch device port */ - /* 0=DTE device */ -#define CR_1000T_MS_VALUE 0x0800 /* 1=Configure PHY as Master */ - /* 0=Configure PHY as Slave */ -#define CR_1000T_MS_ENABLE 0x1000 /* 1=Master/Slave manual config value */ - /* 0=Automatic Master/Slave config */ -#define CR_1000T_TEST_MODE_NORMAL 0x0000 /* Normal Operation */ -#define CR_1000T_TEST_MODE_1 0x2000 /* Transmit Waveform test */ -#define CR_1000T_TEST_MODE_2 0x4000 /* Master Transmit Jitter test */ -#define CR_1000T_TEST_MODE_3 0x6000 /* Slave Transmit Jitter test */ -#define CR_1000T_TEST_MODE_4 0x8000 /* Transmitter Distortion test */ - -/* 1000BASE-T Status Register */ -#define SR_1000T_IDLE_ERROR_CNT 0x00FF /* Num idle errors since last read */ -#define SR_1000T_ASYM_PAUSE_DIR 0x0100 /* LP asymmetric pause direction bit */ -#define SR_1000T_LP_HD_CAPS 0x0400 /* LP is 1000T HD capable */ -#define SR_1000T_LP_FD_CAPS 0x0800 /* LP is 1000T FD capable */ -#define SR_1000T_REMOTE_RX_STATUS 0x1000 /* Remote receiver OK */ -#define SR_1000T_LOCAL_RX_STATUS 0x2000 /* Local receiver OK */ -#define SR_1000T_MS_CONFIG_RES 0x4000 /* 1=Local TX is Master, 0=Slave */ -#define SR_1000T_MS_CONFIG_FAULT 0x8000 /* Master/Slave config fault */ -#define SR_1000T_REMOTE_RX_STATUS_SHIFT 12 -#define SR_1000T_LOCAL_RX_STATUS_SHIFT 13 -#define SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT 5 -#define FFE_IDLE_ERR_COUNT_TIMEOUT_20 20 -#define FFE_IDLE_ERR_COUNT_TIMEOUT_100 100 - -/* Extended Status Register */ -#define IEEE_ESR_1000T_HD_CAPS 0x1000 /* 1000T HD capable */ -#define IEEE_ESR_1000T_FD_CAPS 0x2000 /* 1000T FD capable */ -#define IEEE_ESR_1000X_HD_CAPS 0x4000 /* 1000X HD capable */ -#define IEEE_ESR_1000X_FD_CAPS 0x8000 /* 1000X FD capable */ - -#define PHY_TX_POLARITY_MASK 0x0100 /* register 10h bit 8 (polarity bit) */ -#define PHY_TX_NORMAL_POLARITY 0 /* register 10h bit 8 (normal polarity) */ - -#define AUTO_POLARITY_DISABLE 0x0010 /* register 11h bit 4 */ - /* (0=enable, 1=disable) */ - -/* M88E1000 PHY Specific Control Register */ -#define M88E1000_PSCR_JABBER_DISABLE 0x0001 /* 1=Jabber Function disabled */ -#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ -#define M88E1000_PSCR_SQE_TEST 0x0004 /* 1=SQE Test enabled */ -#define M88E1000_PSCR_CLK125_DISABLE 0x0010 /* 1=CLK125 low, - * 0=CLK125 toggling - */ -#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ - /* Manual MDI configuration */ -#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ -#define M88E1000_PSCR_AUTO_X_1000T 0x0040 /* 1000BASE-T: Auto crossover, - * 100BASE-TX/10BASE-T: - * MDI Mode - */ -#define M88E1000_PSCR_AUTO_X_MODE 0x0060 /* Auto crossover enabled - * all speeds. - */ -#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE 0x0080 - /* 1=Enable Extended 10BASE-T distance - * (Lower 10BASE-T RX Threshold) - * 0=Normal 10BASE-T RX Threshold */ -#define M88E1000_PSCR_MII_5BIT_ENABLE 0x0100 - /* 1=5-Bit interface in 100BASE-TX - * 0=MII interface in 100BASE-TX */ -#define M88E1000_PSCR_SCRAMBLER_DISABLE 0x0200 /* 1=Scrambler disable */ -#define M88E1000_PSCR_FORCE_LINK_GOOD 0x0400 /* 1=Force link good */ -#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ - -#define M88E1000_PSCR_POLARITY_REVERSAL_SHIFT 1 -#define M88E1000_PSCR_AUTO_X_MODE_SHIFT 5 -#define M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT 7 - -/* M88E1000 PHY Specific Status Register */ -#define M88E1000_PSSR_JABBER 0x0001 /* 1=Jabber */ -#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ -#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */ -#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ -#define M88E1000_PSSR_CABLE_LENGTH 0x0380 /* 0=<50M;1=50-80M;2=80-110M; - * 3=110-140M;4=>140M */ -#define M88E1000_PSSR_LINK 0x0400 /* 1=Link up, 0=Link down */ -#define M88E1000_PSSR_SPD_DPLX_RESOLVED 0x0800 /* 1=Speed & Duplex resolved */ -#define M88E1000_PSSR_PAGE_RCVD 0x1000 /* 1=Page received */ -#define M88E1000_PSSR_DPLX 0x2000 /* 1=Duplex 0=Half Duplex */ -#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ -#define M88E1000_PSSR_10MBS 0x0000 /* 00=10Mbs */ -#define M88E1000_PSSR_100MBS 0x4000 /* 01=100Mbs */ -#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ - -#define M88E1000_PSSR_REV_POLARITY_SHIFT 1 -#define M88E1000_PSSR_DOWNSHIFT_SHIFT 5 -#define M88E1000_PSSR_MDIX_SHIFT 6 -#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 - -/* M88E1000 Extended PHY Specific Control Register */ -#define M88E1000_EPSCR_FIBER_LOOPBACK 0x4000 /* 1=Fiber loopback */ -#define M88E1000_EPSCR_DOWN_NO_IDLE 0x8000 /* 1=Lost lock detect enabled. - * Will assert lost lock and bring - * link down if idle not seen - * within 1ms in 1000BASE-T - */ -/* Number of times we will attempt to autonegotiate before downshifting if we - * are the master */ -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_2X 0x0400 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_3X 0x0800 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_4X 0x0C00 -/* Number of times we will attempt to autonegotiate before downshifting if we - * are the slave */ -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_DIS 0x0000 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X 0x0200 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X 0x0300 -#define M88E1000_EPSCR_TX_CLK_2_5 0x0060 /* 2.5 MHz TX_CLK */ -#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ -#define M88E1000_EPSCR_TX_CLK_0 0x0000 /* NO TX_CLK */ - -/* M88EC018 Rev 2 specific DownShift settings */ -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_1X 0x0000 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_2X 0x0200 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_3X 0x0400 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_4X 0x0600 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_6X 0x0A00 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_7X 0x0C00 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_8X 0x0E00 - -/* IGP01E1000 Specific Port Config Register - R/W */ -#define IGP01E1000_PSCFR_AUTO_MDIX_PAR_DETECT 0x0010 -#define IGP01E1000_PSCFR_PRE_EN 0x0020 -#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 -#define IGP01E1000_PSCFR_DISABLE_TPLOOPBACK 0x0100 -#define IGP01E1000_PSCFR_DISABLE_JABBER 0x0400 -#define IGP01E1000_PSCFR_DISABLE_TRANSMIT 0x2000 - -/* IGP01E1000 Specific Port Status Register - R/O */ -#define IGP01E1000_PSSR_AUTONEG_FAILED 0x0001 /* RO LH SC */ -#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 -#define IGP01E1000_PSSR_CABLE_LENGTH 0x007C -#define IGP01E1000_PSSR_FULL_DUPLEX 0x0200 -#define IGP01E1000_PSSR_LINK_UP 0x0400 -#define IGP01E1000_PSSR_MDIX 0x0800 -#define IGP01E1000_PSSR_SPEED_MASK 0xC000 /* speed bits mask */ -#define IGP01E1000_PSSR_SPEED_10MBPS 0x4000 -#define IGP01E1000_PSSR_SPEED_100MBPS 0x8000 -#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 -#define IGP01E1000_PSSR_CABLE_LENGTH_SHIFT 0x0002 /* shift right 2 */ -#define IGP01E1000_PSSR_MDIX_SHIFT 0x000B /* shift right 11 */ - -/* IGP01E1000 Specific Port Control Register - R/W */ -#define IGP01E1000_PSCR_TP_LOOPBACK 0x0010 -#define IGP01E1000_PSCR_CORRECT_NC_SCMBLR 0x0200 -#define IGP01E1000_PSCR_TEN_CRS_SELECT 0x0400 -#define IGP01E1000_PSCR_FLIP_CHIP 0x0800 -#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 -#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0-MDI, 1-MDIX */ - -/* IGP01E1000 Specific Port Link Health Register */ -#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 -#define IGP01E1000_PLHR_GIG_SCRAMBLER_ERROR 0x4000 -#define IGP01E1000_PLHR_MASTER_FAULT 0x2000 -#define IGP01E1000_PLHR_MASTER_RESOLUTION 0x1000 -#define IGP01E1000_PLHR_GIG_REM_RCVR_NOK 0x0800 /* LH */ -#define IGP01E1000_PLHR_IDLE_ERROR_CNT_OFLOW 0x0400 /* LH */ -#define IGP01E1000_PLHR_DATA_ERR_1 0x0200 /* LH */ -#define IGP01E1000_PLHR_DATA_ERR_0 0x0100 -#define IGP01E1000_PLHR_AUTONEG_FAULT 0x0040 -#define IGP01E1000_PLHR_AUTONEG_ACTIVE 0x0010 -#define IGP01E1000_PLHR_VALID_CHANNEL_D 0x0008 -#define IGP01E1000_PLHR_VALID_CHANNEL_C 0x0004 -#define IGP01E1000_PLHR_VALID_CHANNEL_B 0x0002 -#define IGP01E1000_PLHR_VALID_CHANNEL_A 0x0001 - -/* IGP01E1000 Channel Quality Register */ -#define IGP01E1000_MSE_CHANNEL_D 0x000F -#define IGP01E1000_MSE_CHANNEL_C 0x00F0 -#define IGP01E1000_MSE_CHANNEL_B 0x0F00 -#define IGP01E1000_MSE_CHANNEL_A 0xF000 - -#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ -#define IGP02E1000_PM_D3_LPLU 0x0004 /* Enable LPLU in non-D0a modes */ -#define IGP02E1000_PM_D0_LPLU 0x0002 /* Enable LPLU in D0a mode */ - -/* IGP01E1000 DSP reset macros */ -#define DSP_RESET_ENABLE 0x0 -#define DSP_RESET_DISABLE 0x2 -#define E1000_MAX_DSP_RESETS 10 - -/* IGP01E1000 & IGP02E1000 AGC Registers */ - -#define IGP01E1000_AGC_LENGTH_SHIFT 7 /* Coarse - 13:11, Fine - 10:7 */ -#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Coarse - 15:13, Fine - 12:9 */ - -/* IGP02E1000 AGC Register Length 9-bit mask */ -#define IGP02E1000_AGC_LENGTH_MASK 0x7F - -/* 7 bits (3 Coarse + 4 Fine) --> 128 optional values */ -#define IGP01E1000_AGC_LENGTH_TABLE_SIZE 128 -#define IGP02E1000_AGC_LENGTH_TABLE_SIZE 113 - -/* The precision error of the cable length is +/- 10 meters */ -#define IGP01E1000_AGC_RANGE 10 -#define IGP02E1000_AGC_RANGE 15 - -/* IGP01E1000 PCS Initialization register */ -/* bits 3:6 in the PCS registers stores the channels polarity */ -#define IGP01E1000_PHY_POLARITY_MASK 0x0078 - -/* IGP01E1000 GMII FIFO Register */ -#define IGP01E1000_GMII_FLEX_SPD 0x10 /* Enable flexible speed - * on Link-Up */ -#define IGP01E1000_GMII_SPD 0x20 /* Enable SPD */ - -/* IGP01E1000 Analog Register */ -#define IGP01E1000_ANALOG_SPARE_FUSE_STATUS 0x20D1 -#define IGP01E1000_ANALOG_FUSE_STATUS 0x20D0 -#define IGP01E1000_ANALOG_FUSE_CONTROL 0x20DC -#define IGP01E1000_ANALOG_FUSE_BYPASS 0x20DE - -#define IGP01E1000_ANALOG_FUSE_POLY_MASK 0xF000 -#define IGP01E1000_ANALOG_FUSE_FINE_MASK 0x0F80 -#define IGP01E1000_ANALOG_FUSE_COARSE_MASK 0x0070 -#define IGP01E1000_ANALOG_SPARE_FUSE_ENABLED 0x0100 -#define IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL 0x0002 - -#define IGP01E1000_ANALOG_FUSE_COARSE_THRESH 0x0040 -#define IGP01E1000_ANALOG_FUSE_COARSE_10 0x0010 -#define IGP01E1000_ANALOG_FUSE_FINE_1 0x0080 -#define IGP01E1000_ANALOG_FUSE_FINE_10 0x0500 - -/* Bit definitions for valid PHY IDs. */ -/* I = Integrated - * E = External - */ -#define M88_VENDOR 0x0141 -#define M88E1000_E_PHY_ID 0x01410C50 -#define M88E1000_I_PHY_ID 0x01410C30 -#define M88E1011_I_PHY_ID 0x01410C20 -#define IGP01E1000_I_PHY_ID 0x02A80380 -#define M88E1000_12_PHY_ID M88E1000_E_PHY_ID -#define M88E1000_14_PHY_ID M88E1000_E_PHY_ID -#define M88E1011_I_REV_4 0x04 -#define M88E1111_I_PHY_ID 0x01410CC0 -#define M88E1118_E_PHY_ID 0x01410E40 -#define L1LXT971A_PHY_ID 0x001378E0 - -#define RTL8211B_PHY_ID 0x001CC910 -#define RTL8201N_PHY_ID 0x8200 -#define RTL_PHY_CTRL_FD 0x0100 /* Full duplex.0=half; 1=full */ -#define RTL_PHY_CTRL_SPD_100 0x200000 /* Force 100Mb */ - -/* Bits... - * 15-5: page - * 4-0: register offset - */ -#define PHY_PAGE_SHIFT 5 -#define PHY_REG(page, reg) \ - (((page) << PHY_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS)) - -#define IGP3_PHY_PORT_CTRL \ - PHY_REG(769, 17) /* Port General Configuration */ -#define IGP3_PHY_RATE_ADAPT_CTRL \ - PHY_REG(769, 25) /* Rate Adapter Control Register */ - -#define IGP3_KMRN_FIFO_CTRL_STATS \ - PHY_REG(770, 16) /* KMRN FIFO's control/status register */ -#define IGP3_KMRN_POWER_MNG_CTRL \ - PHY_REG(770, 17) /* KMRN Power Management Control Register */ -#define IGP3_KMRN_INBAND_CTRL \ - PHY_REG(770, 18) /* KMRN Inband Control Register */ -#define IGP3_KMRN_DIAG \ - PHY_REG(770, 19) /* KMRN Diagnostic register */ -#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 /* RX PCS is not synced */ -#define IGP3_KMRN_ACK_TIMEOUT \ - PHY_REG(770, 20) /* KMRN Acknowledge Timeouts register */ - -#define IGP3_VR_CTRL \ - PHY_REG(776, 18) /* Voltage regulator control register */ -#define IGP3_VR_CTRL_MODE_SHUT 0x0200 /* Enter powerdown, shutdown VRs */ -#define IGP3_VR_CTRL_MODE_MASK 0x0300 /* Shutdown VR Mask */ - -#define IGP3_CAPABILITY \ - PHY_REG(776, 19) /* IGP3 Capability Register */ - -/* Capabilities for SKU Control */ -#define IGP3_CAP_INITIATE_TEAM 0x0001 /* Able to initiate a team */ -#define IGP3_CAP_WFM 0x0002 /* Support WoL and PXE */ -#define IGP3_CAP_ASF 0x0004 /* Support ASF */ -#define IGP3_CAP_LPLU 0x0008 /* Support Low Power Link Up */ -#define IGP3_CAP_DC_AUTO_SPEED 0x0010 /* Support AC/DC Auto Link Speed */ -#define IGP3_CAP_SPD 0x0020 /* Support Smart Power Down */ -#define IGP3_CAP_MULT_QUEUE 0x0040 /* Support 2 tx & 2 rx queues */ -#define IGP3_CAP_RSS 0x0080 /* Support RSS */ -#define IGP3_CAP_8021PQ 0x0100 /* Support 802.1Q & 802.1p */ -#define IGP3_CAP_AMT_CB 0x0200 /* Support active manageability and circuit breaker */ - -#define IGP3_PPC_JORDAN_EN 0x0001 -#define IGP3_PPC_JORDAN_GIGA_SPEED 0x0002 - -#define IGP3_KMRN_PMC_EE_IDLE_LINK_DIS 0x0001 -#define IGP3_KMRN_PMC_K0S_ENTRY_LATENCY_MASK 0x001E -#define IGP3_KMRN_PMC_K0S_MODE1_EN_GIGA 0x0020 -#define IGP3_KMRN_PMC_K0S_MODE1_EN_100 0x0040 - -#define IGP3E1000_PHY_MISC_CTRL 0x1B /* Misc. Ctrl register */ -#define IGP3_PHY_MISC_DUPLEX_MANUAL_SET 0x1000 /* Duplex Manual Set */ - -#define IGP3_KMRN_EXT_CTRL PHY_REG(770, 18) -#define IGP3_KMRN_EC_DIS_INBAND 0x0080 - -#define IGP03E1000_E_PHY_ID 0x02A80390 -#define IFE_E_PHY_ID 0x02A80330 /* 10/100 PHY */ -#define IFE_PLUS_E_PHY_ID 0x02A80320 -#define IFE_C_E_PHY_ID 0x02A80310 - -#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 /* 100BaseTx Extended Status, Control and Address */ -#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY special control register */ -#define IFE_PHY_RCV_FALSE_CARRIER 0x13 /* 100BaseTx Receive False Carrier Counter */ -#define IFE_PHY_RCV_DISCONNECT 0x14 /* 100BaseTx Receive Disconnect Counter */ -#define IFE_PHY_RCV_ERROT_FRAME 0x15 /* 100BaseTx Receive Error Frame Counter */ -#define IFE_PHY_RCV_SYMBOL_ERR 0x16 /* Receive Symbol Error Counter */ -#define IFE_PHY_PREM_EOF_ERR 0x17 /* 100BaseTx Receive Premature End Of Frame Error Counter */ -#define IFE_PHY_RCV_EOF_ERR 0x18 /* 10BaseT Receive End Of Frame Error Counter */ -#define IFE_PHY_TX_JABBER_DETECT 0x19 /* 10BaseT Transmit Jabber Detect Counter */ -#define IFE_PHY_EQUALIZER 0x1A /* PHY Equalizer Control and Status */ -#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY special control and LED configuration */ -#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control register */ -#define IFE_PHY_HWI_CONTROL 0x1D /* Hardware Integrity Control (HWI) */ - -#define IFE_PESC_REDUCED_POWER_DOWN_DISABLE 0x2000 /* Default 1 = Disable auto reduced power down */ -#define IFE_PESC_100BTX_POWER_DOWN 0x0400 /* Indicates the power state of 100BASE-TX */ -#define IFE_PESC_10BTX_POWER_DOWN 0x0200 /* Indicates the power state of 10BASE-T */ -#define IFE_PESC_POLARITY_REVERSED 0x0100 /* Indicates 10BASE-T polarity */ -#define IFE_PESC_PHY_ADDR_MASK 0x007C /* Bit 6:2 for sampled PHY address */ -#define IFE_PESC_SPEED 0x0002 /* Auto-negotiation speed result 1=100Mbs, 0=10Mbs */ -#define IFE_PESC_DUPLEX 0x0001 /* Auto-negotiation duplex result 1=Full, 0=Half */ -#define IFE_PESC_POLARITY_REVERSED_SHIFT 8 - -#define IFE_PSC_DISABLE_DYNAMIC_POWER_DOWN 0x0100 /* 1 = Dynamic Power Down disabled */ -#define IFE_PSC_FORCE_POLARITY 0x0020 /* 1=Reversed Polarity, 0=Normal */ -#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 /* 1=Auto Polarity Disabled, 0=Enabled */ -#define IFE_PSC_JABBER_FUNC_DISABLE 0x0001 /* 1=Jabber Disabled, 0=Normal Jabber Operation */ -#define IFE_PSC_FORCE_POLARITY_SHIFT 5 -#define IFE_PSC_AUTO_POLARITY_DISABLE_SHIFT 4 - -#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable MDI/MDI-X feature, default 0=disabled */ -#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDIX-X, 0=force MDI */ -#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ -#define IFE_PMC_AUTO_MDIX_COMPLETE 0x0010 /* Resolution algorithm is completed */ -#define IFE_PMC_MDIX_MODE_SHIFT 6 -#define IFE_PHC_MDIX_RESET_ALL_MASK 0x0000 /* Disable auto MDI-X */ - -#define IFE_PHC_HWI_ENABLE 0x8000 /* Enable the HWI feature */ -#define IFE_PHC_ABILITY_CHECK 0x4000 /* 1= Test Passed, 0=failed */ -#define IFE_PHC_TEST_EXEC 0x2000 /* PHY launch test pulses on the wire */ -#define IFE_PHC_HIGHZ 0x0200 /* 1 = Open Circuit */ -#define IFE_PHC_LOWZ 0x0400 /* 1 = Short Circuit */ -#define IFE_PHC_LOW_HIGH_Z_MASK 0x0600 /* Mask for indication type of problem on the line */ -#define IFE_PHC_DISTANCE_MASK 0x01FF /* Mask for distance to the cable problem, in 80cm granularity */ -#define IFE_PHC_RESET_ALL_MASK 0x0000 /* Disable HWI */ -#define IFE_PSCL_PROBE_MODE 0x0020 /* LED Probe mode */ -#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ -#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ - -#define ICH_FLASH_COMMAND_TIMEOUT 5000 /* 5000 uSecs - adjusted */ -#define ICH_FLASH_ERASE_TIMEOUT 3000000 /* Up to 3 seconds - worst case */ -#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 /* 10 cycles */ -#define ICH_FLASH_SEG_SIZE_256 256 -#define ICH_FLASH_SEG_SIZE_4K 4096 -#define ICH_FLASH_SEG_SIZE_64K 65536 - -#define ICH_CYCLE_READ 0x0 -#define ICH_CYCLE_RESERVED 0x1 -#define ICH_CYCLE_WRITE 0x2 -#define ICH_CYCLE_ERASE 0x3 - -#define ICH_FLASH_GFPREG 0x0000 -#define ICH_FLASH_HSFSTS 0x0004 -#define ICH_FLASH_HSFCTL 0x0006 -#define ICH_FLASH_FADDR 0x0008 -#define ICH_FLASH_FDATA0 0x0010 -#define ICH_FLASH_FRACC 0x0050 -#define ICH_FLASH_FREG0 0x0054 -#define ICH_FLASH_FREG1 0x0058 -#define ICH_FLASH_FREG2 0x005C -#define ICH_FLASH_FREG3 0x0060 -#define ICH_FLASH_FPR0 0x0074 -#define ICH_FLASH_FPR1 0x0078 -#define ICH_FLASH_SSFSTS 0x0090 -#define ICH_FLASH_SSFCTL 0x0092 -#define ICH_FLASH_PREOP 0x0094 -#define ICH_FLASH_OPTYPE 0x0096 -#define ICH_FLASH_OPMENU 0x0098 - -#define ICH_FLASH_REG_MAPSIZE 0x00A0 -#define ICH_FLASH_SECTOR_SIZE 4096 -#define ICH_GFPREG_BASE_MASK 0x1FFF -#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF - -/* Miscellaneous PHY bit definitions. */ -#define PHY_PREAMBLE 0xFFFFFFFF -#define PHY_SOF 0x01 -#define PHY_OP_READ 0x02 -#define PHY_OP_WRITE 0x01 -#define PHY_TURNAROUND 0x02 -#define PHY_PREAMBLE_SIZE 32 -#define MII_CR_SPEED_1000 0x0040 -#define MII_CR_SPEED_100 0x2000 -#define MII_CR_SPEED_10 0x0000 -#define E1000_PHY_ADDRESS 0x01 -#define PHY_AUTO_NEG_TIME 45 /* 4.5 Seconds */ -#define PHY_FORCE_TIME 20 /* 2.0 Seconds */ -#define PHY_REVISION_MASK 0xFFFFFFF0 -#define DEVICE_SPEED_MASK 0x00000300 /* Device Ctrl Reg Speed Mask */ -#define REG4_SPEED_MASK 0x01E0 -#define REG9_SPEED_MASK 0x0300 -#define ADVERTISE_10_HALF 0x0001 -#define ADVERTISE_10_FULL 0x0002 -#define ADVERTISE_100_HALF 0x0004 -#define ADVERTISE_100_FULL 0x0008 -#define ADVERTISE_1000_HALF 0x0010 -#define ADVERTISE_1000_FULL 0x0020 -#define AUTONEG_ADVERTISE_SPEED_DEFAULT 0x002F /* Everything but 1000-Half */ -#define AUTONEG_ADVERTISE_10_100_ALL 0x000F /* All 10/100 speeds */ -#define AUTONEG_ADVERTISE_10_ALL 0x0003 /* 10Mbps Full & Half speeds */ - -#endif /* _E1000_HW_H_ */ diff --git a/addons/e1000/src/4.4.180/e1000_main.c b/addons/e1000/src/4.4.180/e1000_main.c deleted file mode 100644 index 1f84f2fa..00000000 --- a/addons/e1000/src/4.4.180/e1000_main.c +++ /dev/null @@ -1,5344 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include "e1000.h" -#include -#include -#include -#include -#include - -char e1000_driver_name[] = "e1000"; -static char e1000_driver_string[] = "Intel(R) PRO/1000 Network Driver"; -#define DRV_VERSION "7.3.21-k8-NAPI" -const char e1000_driver_version[] = DRV_VERSION; -static const char e1000_copyright[] = "Copyright (c) 1999-2006 Intel Corporation."; - -/* e1000_pci_tbl - PCI Device ID Table - * - * Last entry must be all 0s - * - * Macro expands to... - * {PCI_DEVICE(PCI_VENDOR_ID_INTEL, device_id)} - */ -static const struct pci_device_id e1000_pci_tbl[] = { - INTEL_E1000_ETHERNET_DEVICE(0x1000), - INTEL_E1000_ETHERNET_DEVICE(0x1001), - INTEL_E1000_ETHERNET_DEVICE(0x1004), - INTEL_E1000_ETHERNET_DEVICE(0x1008), - INTEL_E1000_ETHERNET_DEVICE(0x1009), - INTEL_E1000_ETHERNET_DEVICE(0x100C), - INTEL_E1000_ETHERNET_DEVICE(0x100D), - INTEL_E1000_ETHERNET_DEVICE(0x100E), - INTEL_E1000_ETHERNET_DEVICE(0x100F), - INTEL_E1000_ETHERNET_DEVICE(0x1010), - INTEL_E1000_ETHERNET_DEVICE(0x1011), - INTEL_E1000_ETHERNET_DEVICE(0x1012), - INTEL_E1000_ETHERNET_DEVICE(0x1013), - INTEL_E1000_ETHERNET_DEVICE(0x1014), - INTEL_E1000_ETHERNET_DEVICE(0x1015), - INTEL_E1000_ETHERNET_DEVICE(0x1016), - INTEL_E1000_ETHERNET_DEVICE(0x1017), - INTEL_E1000_ETHERNET_DEVICE(0x1018), - INTEL_E1000_ETHERNET_DEVICE(0x1019), - INTEL_E1000_ETHERNET_DEVICE(0x101A), - INTEL_E1000_ETHERNET_DEVICE(0x101D), - INTEL_E1000_ETHERNET_DEVICE(0x101E), - INTEL_E1000_ETHERNET_DEVICE(0x1026), - INTEL_E1000_ETHERNET_DEVICE(0x1027), - INTEL_E1000_ETHERNET_DEVICE(0x1028), - INTEL_E1000_ETHERNET_DEVICE(0x1075), - INTEL_E1000_ETHERNET_DEVICE(0x1076), - INTEL_E1000_ETHERNET_DEVICE(0x1077), - INTEL_E1000_ETHERNET_DEVICE(0x1078), - INTEL_E1000_ETHERNET_DEVICE(0x1079), - INTEL_E1000_ETHERNET_DEVICE(0x107A), - INTEL_E1000_ETHERNET_DEVICE(0x107B), - INTEL_E1000_ETHERNET_DEVICE(0x107C), - INTEL_E1000_ETHERNET_DEVICE(0x108A), - INTEL_E1000_ETHERNET_DEVICE(0x1099), - INTEL_E1000_ETHERNET_DEVICE(0x10B5), - INTEL_E1000_ETHERNET_DEVICE(0x2E6E), - /* required last entry */ - {0,} -}; - -MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); - -int e1000_up(struct e1000_adapter *adapter); -void e1000_down(struct e1000_adapter *adapter); -void e1000_reinit_locked(struct e1000_adapter *adapter); -void e1000_reset(struct e1000_adapter *adapter); -int e1000_setup_all_tx_resources(struct e1000_adapter *adapter); -int e1000_setup_all_rx_resources(struct e1000_adapter *adapter); -void e1000_free_all_tx_resources(struct e1000_adapter *adapter); -void e1000_free_all_rx_resources(struct e1000_adapter *adapter); -static int e1000_setup_tx_resources(struct e1000_adapter *adapter, - struct e1000_tx_ring *txdr); -static int e1000_setup_rx_resources(struct e1000_adapter *adapter, - struct e1000_rx_ring *rxdr); -static void e1000_free_tx_resources(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring); -static void e1000_free_rx_resources(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring); -void e1000_update_stats(struct e1000_adapter *adapter); - -static int e1000_init_module(void); -static void e1000_exit_module(void); -static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent); -static void e1000_remove(struct pci_dev *pdev); -static int e1000_alloc_queues(struct e1000_adapter *adapter); -static int e1000_sw_init(struct e1000_adapter *adapter); -static int e1000_open(struct net_device *netdev); -static int e1000_close(struct net_device *netdev); -static void e1000_configure_tx(struct e1000_adapter *adapter); -static void e1000_configure_rx(struct e1000_adapter *adapter); -static void e1000_setup_rctl(struct e1000_adapter *adapter); -static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter); -static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter); -static void e1000_clean_tx_ring(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring); -static void e1000_clean_rx_ring(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring); -static void e1000_set_rx_mode(struct net_device *netdev); -static void e1000_update_phy_info_task(struct work_struct *work); -static void e1000_watchdog(struct work_struct *work); -static void e1000_82547_tx_fifo_stall_task(struct work_struct *work); -static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, - struct net_device *netdev); -static struct net_device_stats * e1000_get_stats(struct net_device *netdev); -static int e1000_change_mtu(struct net_device *netdev, int new_mtu); -static int e1000_set_mac(struct net_device *netdev, void *p); -static irqreturn_t e1000_intr(int irq, void *data); -static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring); -static int e1000_clean(struct napi_struct *napi, int budget); -static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int *work_done, int work_to_do); -static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int *work_done, int work_to_do); -static void e1000_alloc_dummy_rx_buffers(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count) -{ -} -static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count); -static void e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count); -static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); -static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, - int cmd); -static void e1000_enter_82542_rst(struct e1000_adapter *adapter); -static void e1000_leave_82542_rst(struct e1000_adapter *adapter); -static void e1000_tx_timeout(struct net_device *dev); -static void e1000_reset_task(struct work_struct *work); -static void e1000_smartspeed(struct e1000_adapter *adapter); -static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, - struct sk_buff *skb); - -static bool e1000_vlan_used(struct e1000_adapter *adapter); -static void e1000_vlan_mode(struct net_device *netdev, - netdev_features_t features); -static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter, - bool filter_on); -static int e1000_vlan_rx_add_vid(struct net_device *netdev, - __be16 proto, u16 vid); -static int e1000_vlan_rx_kill_vid(struct net_device *netdev, - __be16 proto, u16 vid); -static void e1000_restore_vlan(struct e1000_adapter *adapter); - -#ifdef CONFIG_PM -static int e1000_suspend(struct pci_dev *pdev, pm_message_t state); -static int e1000_resume(struct pci_dev *pdev); -#endif -static void e1000_shutdown(struct pci_dev *pdev); - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* for netdump / net console */ -static void e1000_netpoll (struct net_device *netdev); -#endif - -#define COPYBREAK_DEFAULT 256 -static unsigned int copybreak __read_mostly = COPYBREAK_DEFAULT; -module_param(copybreak, uint, 0644); -MODULE_PARM_DESC(copybreak, - "Maximum size of packet that is copied to a new buffer on receive"); - -static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, - pci_channel_state_t state); -static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev); -static void e1000_io_resume(struct pci_dev *pdev); - -static const struct pci_error_handlers e1000_err_handler = { - .error_detected = e1000_io_error_detected, - .slot_reset = e1000_io_slot_reset, - .resume = e1000_io_resume, -}; - -static struct pci_driver e1000_driver = { - .name = e1000_driver_name, - .id_table = e1000_pci_tbl, - .probe = e1000_probe, - .remove = e1000_remove, -#ifdef CONFIG_PM - /* Power Management Hooks */ - .suspend = e1000_suspend, - .resume = e1000_resume, -#endif - .shutdown = e1000_shutdown, - .err_handler = &e1000_err_handler -}; - -MODULE_AUTHOR("Intel Corporation, "); -MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) -static int debug = -1; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); - -/** - * e1000_get_hw_dev - return device - * used by hardware layer to print debugging information - * - **/ -struct net_device *e1000_get_hw_dev(struct e1000_hw *hw) -{ - struct e1000_adapter *adapter = hw->back; - return adapter->netdev; -} - -/** - * e1000_init_module - Driver Registration Routine - * - * e1000_init_module is the first routine called when the driver is - * loaded. All it does is register with the PCI subsystem. - **/ -static int __init e1000_init_module(void) -{ - int ret; - pr_info("%s - version %s\n", e1000_driver_string, e1000_driver_version); - - pr_info("%s\n", e1000_copyright); - - ret = pci_register_driver(&e1000_driver); - if (copybreak != COPYBREAK_DEFAULT) { - if (copybreak == 0) - pr_info("copybreak disabled\n"); - else - pr_info("copybreak enabled for " - "packets <= %u bytes\n", copybreak); - } - return ret; -} - -module_init(e1000_init_module); - -/** - * e1000_exit_module - Driver Exit Cleanup Routine - * - * e1000_exit_module is called just before the driver is removed - * from memory. - **/ -static void __exit e1000_exit_module(void) -{ - pci_unregister_driver(&e1000_driver); -} - -module_exit(e1000_exit_module); - -static int e1000_request_irq(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - irq_handler_t handler = e1000_intr; - int irq_flags = IRQF_SHARED; - int err; - - err = request_irq(adapter->pdev->irq, handler, irq_flags, netdev->name, - netdev); - if (err) { - e_err(probe, "Unable to allocate interrupt Error: %d\n", err); - } - - return err; -} - -static void e1000_free_irq(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - free_irq(adapter->pdev->irq, netdev); -} - -/** - * e1000_irq_disable - Mask off interrupt generation on the NIC - * @adapter: board private structure - **/ -static void e1000_irq_disable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - ew32(IMC, ~0); - E1000_WRITE_FLUSH(); - synchronize_irq(adapter->pdev->irq); -} - -/** - * e1000_irq_enable - Enable default interrupt generation settings - * @adapter: board private structure - **/ -static void e1000_irq_enable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - ew32(IMS, IMS_ENABLE_MASK); - E1000_WRITE_FLUSH(); -} - -static void e1000_update_mng_vlan(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - u16 vid = hw->mng_cookie.vlan_id; - u16 old_vid = adapter->mng_vlan_id; - - if (!e1000_vlan_used(adapter)) - return; - - if (!test_bit(vid, adapter->active_vlans)) { - if (hw->mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) { - e1000_vlan_rx_add_vid(netdev, htons(ETH_P_8021Q), vid); - adapter->mng_vlan_id = vid; - } else { - adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; - } - if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && - (vid != old_vid) && - !test_bit(old_vid, adapter->active_vlans)) - e1000_vlan_rx_kill_vid(netdev, htons(ETH_P_8021Q), - old_vid); - } else { - adapter->mng_vlan_id = vid; - } -} - -static void e1000_init_manageability(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - if (adapter->en_mng_pt) { - u32 manc = er32(MANC); - - /* disable hardware interception of ARP */ - manc &= ~(E1000_MANC_ARP_EN); - - ew32(MANC, manc); - } -} - -static void e1000_release_manageability(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - if (adapter->en_mng_pt) { - u32 manc = er32(MANC); - - /* re-enable hardware interception of ARP */ - manc |= E1000_MANC_ARP_EN; - - ew32(MANC, manc); - } -} - -/** - * e1000_configure - configure the hardware for RX and TX - * @adapter = private board structure - **/ -static void e1000_configure(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - int i; - - e1000_set_rx_mode(netdev); - - e1000_restore_vlan(adapter); - e1000_init_manageability(adapter); - - e1000_configure_tx(adapter); - e1000_setup_rctl(adapter); - e1000_configure_rx(adapter); - /* call E1000_DESC_UNUSED which always leaves - * at least 1 descriptor unused to make sure - * next_to_use != next_to_clean - */ - for (i = 0; i < adapter->num_rx_queues; i++) { - struct e1000_rx_ring *ring = &adapter->rx_ring[i]; - adapter->alloc_rx_buf(adapter, ring, - E1000_DESC_UNUSED(ring)); - } -} - -int e1000_up(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - /* hardware has been reset, we need to reload some things */ - e1000_configure(adapter); - - clear_bit(__E1000_DOWN, &adapter->flags); - - napi_enable(&adapter->napi); - - e1000_irq_enable(adapter); - - netif_wake_queue(adapter->netdev); - - /* fire a link change interrupt to start the watchdog */ - ew32(ICS, E1000_ICS_LSC); - return 0; -} - -/** - * e1000_power_up_phy - restore link in case the phy was powered down - * @adapter: address of board private structure - * - * The phy may be powered down to save power and turn off link when the - * driver is unloaded and wake on lan is not enabled (among others) - * *** this routine MUST be followed by a call to e1000_reset *** - **/ -void e1000_power_up_phy(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u16 mii_reg = 0; - - /* Just clear the power down bit to wake the phy back up */ - if (hw->media_type == e1000_media_type_copper) { - /* according to the manual, the phy will retain its - * settings across a power-down/up cycle - */ - e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg); - mii_reg &= ~MII_CR_POWER_DOWN; - e1000_write_phy_reg(hw, PHY_CTRL, mii_reg); - } -} - -static void e1000_power_down_phy(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - /* Power down the PHY so no link is implied when interface is down * - * The PHY cannot be powered down if any of the following is true * - * (a) WoL is enabled - * (b) AMT is active - * (c) SoL/IDER session is active - */ - if (!adapter->wol && hw->mac_type >= e1000_82540 && - hw->media_type == e1000_media_type_copper) { - u16 mii_reg = 0; - - switch (hw->mac_type) { - case e1000_82540: - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_ce4100: - case e1000_82546_rev_3: - case e1000_82541: - case e1000_82541_rev_2: - case e1000_82547: - case e1000_82547_rev_2: - if (er32(MANC) & E1000_MANC_SMBUS_EN) - goto out; - break; - default: - goto out; - } - e1000_read_phy_reg(hw, PHY_CTRL, &mii_reg); - mii_reg |= MII_CR_POWER_DOWN; - e1000_write_phy_reg(hw, PHY_CTRL, mii_reg); - msleep(1); - } -out: - return; -} - -static void e1000_down_and_stop(struct e1000_adapter *adapter) -{ - set_bit(__E1000_DOWN, &adapter->flags); - - cancel_delayed_work_sync(&adapter->watchdog_task); - - /* - * Since the watchdog task can reschedule other tasks, we should cancel - * it first, otherwise we can run into the situation when a work is - * still running after the adapter has been turned down. - */ - - cancel_delayed_work_sync(&adapter->phy_info_task); - cancel_delayed_work_sync(&adapter->fifo_stall_task); - - /* Only kill reset task if adapter is not resetting */ - if (!test_bit(__E1000_RESETTING, &adapter->flags)) - cancel_work_sync(&adapter->reset_task); -} - -void e1000_down(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - u32 rctl, tctl; - - /* disable receives in the hardware */ - rctl = er32(RCTL); - ew32(RCTL, rctl & ~E1000_RCTL_EN); - /* flush and sleep below */ - - netif_tx_disable(netdev); - - /* disable transmits in the hardware */ - tctl = er32(TCTL); - tctl &= ~E1000_TCTL_EN; - ew32(TCTL, tctl); - /* flush both disables and wait for them to finish */ - E1000_WRITE_FLUSH(); - msleep(10); - - /* Set the carrier off after transmits have been disabled in the - * hardware, to avoid race conditions with e1000_watchdog() (which - * may be running concurrently to us, checking for the carrier - * bit to decide whether it should enable transmits again). Such - * a race condition would result into transmission being disabled - * in the hardware until the next IFF_DOWN+IFF_UP cycle. - */ - netif_carrier_off(netdev); - - napi_disable(&adapter->napi); - - e1000_irq_disable(adapter); - - /* Setting DOWN must be after irq_disable to prevent - * a screaming interrupt. Setting DOWN also prevents - * tasks from rescheduling. - */ - e1000_down_and_stop(adapter); - - adapter->link_speed = 0; - adapter->link_duplex = 0; - - e1000_reset(adapter); - e1000_clean_all_tx_rings(adapter); - e1000_clean_all_rx_rings(adapter); -} - -void e1000_reinit_locked(struct e1000_adapter *adapter) -{ - WARN_ON(in_interrupt()); - while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) - msleep(1); - e1000_down(adapter); - e1000_up(adapter); - clear_bit(__E1000_RESETTING, &adapter->flags); -} - -void e1000_reset(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 pba = 0, tx_space, min_tx_space, min_rx_space; - bool legacy_pba_adjust = false; - u16 hwm; - - /* Repartition Pba for greater than 9k mtu - * To take effect CTRL.RST is required. - */ - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - case e1000_82544: - case e1000_82540: - case e1000_82541: - case e1000_82541_rev_2: - legacy_pba_adjust = true; - pba = E1000_PBA_48K; - break; - case e1000_82545: - case e1000_82545_rev_3: - case e1000_82546: - case e1000_ce4100: - case e1000_82546_rev_3: - pba = E1000_PBA_48K; - break; - case e1000_82547: - case e1000_82547_rev_2: - legacy_pba_adjust = true; - pba = E1000_PBA_30K; - break; - case e1000_undefined: - case e1000_num_macs: - break; - } - - if (legacy_pba_adjust) { - if (hw->max_frame_size > E1000_RXBUFFER_8192) - pba -= 8; /* allocate more FIFO for Tx */ - - if (hw->mac_type == e1000_82547) { - adapter->tx_fifo_head = 0; - adapter->tx_head_addr = pba << E1000_TX_HEAD_ADDR_SHIFT; - adapter->tx_fifo_size = - (E1000_PBA_40K - pba) << E1000_PBA_BYTES_SHIFT; - atomic_set(&adapter->tx_fifo_stall, 0); - } - } else if (hw->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) { - /* adjust PBA for jumbo frames */ - ew32(PBA, pba); - - /* To maintain wire speed transmits, the Tx FIFO should be - * large enough to accommodate two full transmit packets, - * rounded up to the next 1KB and expressed in KB. Likewise, - * the Rx FIFO should be large enough to accommodate at least - * one full receive packet and is similarly rounded up and - * expressed in KB. - */ - pba = er32(PBA); - /* upper 16 bits has Tx packet buffer allocation size in KB */ - tx_space = pba >> 16; - /* lower 16 bits has Rx packet buffer allocation size in KB */ - pba &= 0xffff; - /* the Tx fifo also stores 16 bytes of information about the Tx - * but don't include ethernet FCS because hardware appends it - */ - min_tx_space = (hw->max_frame_size + - sizeof(struct e1000_tx_desc) - - ETH_FCS_LEN) * 2; - min_tx_space = ALIGN(min_tx_space, 1024); - min_tx_space >>= 10; - /* software strips receive CRC, so leave room for it */ - min_rx_space = hw->max_frame_size; - min_rx_space = ALIGN(min_rx_space, 1024); - min_rx_space >>= 10; - - /* If current Tx allocation is less than the min Tx FIFO size, - * and the min Tx FIFO size is less than the current Rx FIFO - * allocation, take space away from current Rx allocation - */ - if (tx_space < min_tx_space && - ((min_tx_space - tx_space) < pba)) { - pba = pba - (min_tx_space - tx_space); - - /* PCI/PCIx hardware has PBA alignment constraints */ - switch (hw->mac_type) { - case e1000_82545 ... e1000_82546_rev_3: - pba &= ~(E1000_PBA_8K - 1); - break; - default: - break; - } - - /* if short on Rx space, Rx wins and must trump Tx - * adjustment or use Early Receive if available - */ - if (pba < min_rx_space) - pba = min_rx_space; - } - } - - ew32(PBA, pba); - - /* flow control settings: - * The high water mark must be low enough to fit one full frame - * (or the size used for early receive) above it in the Rx FIFO. - * Set it to the lower of: - * - 90% of the Rx FIFO size, and - * - the full Rx FIFO size minus the early receive size (for parts - * with ERT support assuming ERT set to E1000_ERT_2048), or - * - the full Rx FIFO size minus one full frame - */ - hwm = min(((pba << 10) * 9 / 10), - ((pba << 10) - hw->max_frame_size)); - - hw->fc_high_water = hwm & 0xFFF8; /* 8-byte granularity */ - hw->fc_low_water = hw->fc_high_water - 8; - hw->fc_pause_time = E1000_FC_PAUSE_TIME; - hw->fc_send_xon = 1; - hw->fc = hw->original_fc; - - /* Allow time for pending master requests to run */ - e1000_reset_hw(hw); - if (hw->mac_type >= e1000_82544) - ew32(WUC, 0); - - if (e1000_init_hw(hw)) - e_dev_err("Hardware Error\n"); - e1000_update_mng_vlan(adapter); - - /* if (adapter->hwflags & HWFLAGS_PHY_PWR_BIT) { */ - if (hw->mac_type >= e1000_82544 && - hw->autoneg == 1 && - hw->autoneg_advertised == ADVERTISE_1000_FULL) { - u32 ctrl = er32(CTRL); - /* clear phy power management bit if we are in gig only mode, - * which if enabled will attempt negotiation to 100Mb, which - * can cause a loss of link at power off or driver unload - */ - ctrl &= ~E1000_CTRL_SWDPIN3; - ew32(CTRL, ctrl); - } - - /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ - ew32(VET, ETHERNET_IEEE_VLAN_TYPE); - - e1000_reset_adaptive(hw); - e1000_phy_get_info(hw, &adapter->phy_info); - - e1000_release_manageability(adapter); -} - -/* Dump the eeprom for users having checksum issues */ -static void e1000_dump_eeprom(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct ethtool_eeprom eeprom; - const struct ethtool_ops *ops = netdev->ethtool_ops; - u8 *data; - int i; - u16 csum_old, csum_new = 0; - - eeprom.len = ops->get_eeprom_len(netdev); - eeprom.offset = 0; - - data = kmalloc(eeprom.len, GFP_KERNEL); - if (!data) - return; - - ops->get_eeprom(netdev, &eeprom, data); - - csum_old = (data[EEPROM_CHECKSUM_REG * 2]) + - (data[EEPROM_CHECKSUM_REG * 2 + 1] << 8); - for (i = 0; i < EEPROM_CHECKSUM_REG * 2; i += 2) - csum_new += data[i] + (data[i + 1] << 8); - csum_new = EEPROM_SUM - csum_new; - - pr_err("/*********************/\n"); - pr_err("Current EEPROM Checksum : 0x%04x\n", csum_old); - pr_err("Calculated : 0x%04x\n", csum_new); - - pr_err("Offset Values\n"); - pr_err("======== ======\n"); - print_hex_dump(KERN_ERR, "", DUMP_PREFIX_OFFSET, 16, 1, data, 128, 0); - - pr_err("Include this output when contacting your support provider.\n"); - pr_err("This is not a software error! Something bad happened to\n"); - pr_err("your hardware or EEPROM image. Ignoring this problem could\n"); - pr_err("result in further problems, possibly loss of data,\n"); - pr_err("corruption or system hangs!\n"); - pr_err("The MAC Address will be reset to 00:00:00:00:00:00,\n"); - pr_err("which is invalid and requires you to set the proper MAC\n"); - pr_err("address manually before continuing to enable this network\n"); - pr_err("device. Please inspect the EEPROM dump and report the\n"); - pr_err("issue to your hardware vendor or Intel Customer Support.\n"); - pr_err("/*********************/\n"); - - kfree(data); -} - -/** - * e1000_is_need_ioport - determine if an adapter needs ioport resources or not - * @pdev: PCI device information struct - * - * Return true if an adapter needs ioport resources - **/ -static int e1000_is_need_ioport(struct pci_dev *pdev) -{ - switch (pdev->device) { - case E1000_DEV_ID_82540EM: - case E1000_DEV_ID_82540EM_LOM: - case E1000_DEV_ID_82540EP: - case E1000_DEV_ID_82540EP_LOM: - case E1000_DEV_ID_82540EP_LP: - case E1000_DEV_ID_82541EI: - case E1000_DEV_ID_82541EI_MOBILE: - case E1000_DEV_ID_82541ER: - case E1000_DEV_ID_82541ER_LOM: - case E1000_DEV_ID_82541GI: - case E1000_DEV_ID_82541GI_LF: - case E1000_DEV_ID_82541GI_MOBILE: - case E1000_DEV_ID_82544EI_COPPER: - case E1000_DEV_ID_82544EI_FIBER: - case E1000_DEV_ID_82544GC_COPPER: - case E1000_DEV_ID_82544GC_LOM: - case E1000_DEV_ID_82545EM_COPPER: - case E1000_DEV_ID_82545EM_FIBER: - case E1000_DEV_ID_82546EB_COPPER: - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546EB_QUAD_COPPER: - return true; - default: - return false; - } -} - -static netdev_features_t e1000_fix_features(struct net_device *netdev, - netdev_features_t 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_CTAG_RX) - features |= NETIF_F_HW_VLAN_CTAG_TX; - else - features &= ~NETIF_F_HW_VLAN_CTAG_TX; - - return features; -} - -static int e1000_set_features(struct net_device *netdev, - netdev_features_t features) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - netdev_features_t changed = features ^ netdev->features; - - if (changed & NETIF_F_HW_VLAN_CTAG_RX) - e1000_vlan_mode(netdev, features); - - if (!(changed & (NETIF_F_RXCSUM | NETIF_F_RXALL))) - return 0; - - netdev->features = features; - adapter->rx_csum = !!(features & NETIF_F_RXCSUM); - - if (netif_running(netdev)) - e1000_reinit_locked(adapter); - else - e1000_reset(adapter); - - return 0; -} - -static const struct net_device_ops e1000_netdev_ops = { - .ndo_open = e1000_open, - .ndo_stop = e1000_close, - .ndo_start_xmit = e1000_xmit_frame, - .ndo_get_stats = e1000_get_stats, - .ndo_set_rx_mode = e1000_set_rx_mode, - .ndo_set_mac_address = e1000_set_mac, - .ndo_tx_timeout = e1000_tx_timeout, - .ndo_change_mtu = e1000_change_mtu, - .ndo_do_ioctl = e1000_ioctl, - .ndo_validate_addr = eth_validate_addr, - .ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = e1000_vlan_rx_kill_vid, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e1000_netpoll, -#endif - .ndo_fix_features = e1000_fix_features, - .ndo_set_features = e1000_set_features, -}; - -/** - * e1000_init_hw_struct - initialize members of hw struct - * @adapter: board private struct - * @hw: structure used by e1000_hw.c - * - * Factors out initialization of the e1000_hw struct to its own function - * that can be called very early at init (just after struct allocation). - * Fields are initialized based on PCI device information and - * OS network device settings (MTU size). - * Returns negative error codes if MAC type setup fails. - */ -static int e1000_init_hw_struct(struct e1000_adapter *adapter, - struct e1000_hw *hw) -{ - struct pci_dev *pdev = adapter->pdev; - - /* PCI config space info */ - hw->vendor_id = pdev->vendor; - hw->device_id = pdev->device; - hw->subsystem_vendor_id = pdev->subsystem_vendor; - hw->subsystem_id = pdev->subsystem_device; - hw->revision_id = pdev->revision; - - pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word); - - hw->max_frame_size = adapter->netdev->mtu + - ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - hw->min_frame_size = MINIMUM_ETHERNET_FRAME_SIZE; - - /* identify the MAC */ - if (e1000_set_mac_type(hw)) { - e_err(probe, "Unknown MAC Type\n"); - return -EIO; - } - - switch (hw->mac_type) { - default: - break; - case e1000_82541: - case e1000_82547: - case e1000_82541_rev_2: - case e1000_82547_rev_2: - hw->phy_init_script = 1; - break; - } - - e1000_set_media_type(hw); - e1000_get_bus_info(hw); - - hw->wait_autoneg_complete = false; - hw->tbi_compatibility_en = true; - hw->adaptive_ifs = true; - - /* Copper options */ - - if (hw->media_type == e1000_media_type_copper) { - hw->mdix = AUTO_ALL_MODES; - hw->disable_polarity_correction = false; - hw->master_slave = E1000_MASTER_SLAVE; - } - - return 0; -} - -/** - * e1000_probe - Device Initialization Routine - * @pdev: PCI device information struct - * @ent: entry in e1000_pci_tbl - * - * Returns 0 on success, negative on failure - * - * e1000_probe initializes an adapter identified by a pci_dev structure. - * The OS initialization, configuring of the adapter private structure, - * and a hardware reset occur. - **/ -static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct e1000_adapter *adapter = NULL; - struct e1000_hw *hw; - - static int cards_found = 0; - static int global_quad_port_a = 0; /* global ksp3 port a indication */ - int i, err, pci_using_dac; - u16 eeprom_data = 0; - u16 tmp = 0; - u16 eeprom_apme_mask = E1000_EEPROM_APME; - int bars, need_ioport; - bool disable_dev = false; - - /* do not allocate ioport bars when not needed */ - need_ioport = e1000_is_need_ioport(pdev); - if (need_ioport) { - bars = pci_select_bars(pdev, IORESOURCE_MEM | IORESOURCE_IO); - err = pci_enable_device(pdev); - } else { - bars = pci_select_bars(pdev, IORESOURCE_MEM); - err = pci_enable_device_mem(pdev); - } - if (err) - return err; - - err = pci_request_selected_regions(pdev, bars, e1000_driver_name); - if (err) - goto err_pci_reg; - - pci_set_master(pdev); - err = pci_save_state(pdev); - if (err) - goto err_alloc_etherdev; - - err = -ENOMEM; - netdev = alloc_etherdev(sizeof(struct e1000_adapter)); - if (!netdev) - goto err_alloc_etherdev; - - SET_NETDEV_DEV(netdev, &pdev->dev); - - pci_set_drvdata(pdev, netdev); - adapter = netdev_priv(netdev); - adapter->netdev = netdev; - adapter->pdev = pdev; - adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); - adapter->bars = bars; - adapter->need_ioport = need_ioport; - - hw = &adapter->hw; - hw->back = adapter; - - err = -EIO; - hw->hw_addr = pci_ioremap_bar(pdev, BAR_0); - if (!hw->hw_addr) - goto err_ioremap; - - if (adapter->need_ioport) { - for (i = BAR_1; i <= BAR_5; i++) { - if (pci_resource_len(pdev, i) == 0) - continue; - if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { - hw->io_base = pci_resource_start(pdev, i); - break; - } - } - } - - /* make ready for any if (hw->...) below */ - err = e1000_init_hw_struct(adapter, hw); - if (err) - goto err_sw_init; - - /* there is a workaround being applied below that limits - * 64-bit DMA addresses to 64-bit hardware. There are some - * 32-bit adapters that Tx hang when given 64-bit DMA addresses - */ - pci_using_dac = 0; - if ((hw->bus_type == e1000_bus_type_pcix) && - !dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64))) { - pci_using_dac = 1; - } else { - err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); - if (err) { - pr_err("No usable DMA config, aborting\n"); - goto err_dma; - } - } - - netdev->netdev_ops = &e1000_netdev_ops; - e1000_set_ethtool_ops(netdev); - netdev->watchdog_timeo = 5 * HZ; - netif_napi_add(netdev, &adapter->napi, e1000_clean, 64); - - strncpy(netdev->name, pci_name(pdev), sizeof(netdev->name) - 1); - - adapter->bd_number = cards_found; - - /* setup the private structure */ - - err = e1000_sw_init(adapter); - if (err) - goto err_sw_init; - - err = -EIO; - if (hw->mac_type == e1000_ce4100) { - hw->ce4100_gbe_mdio_base_virt = - ioremap(pci_resource_start(pdev, BAR_1), - pci_resource_len(pdev, BAR_1)); - - if (!hw->ce4100_gbe_mdio_base_virt) - goto err_mdio_ioremap; - } - - if (hw->mac_type >= e1000_82543) { - netdev->hw_features = NETIF_F_SG | - NETIF_F_HW_CSUM | - NETIF_F_HW_VLAN_CTAG_RX; - netdev->features = NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_FILTER; - } - - if ((hw->mac_type >= e1000_82544) && - (hw->mac_type != e1000_82547)) - netdev->hw_features |= NETIF_F_TSO; - - netdev->priv_flags |= IFF_SUPP_NOFCS; - - netdev->features |= netdev->hw_features; - netdev->hw_features |= (NETIF_F_RXCSUM | - NETIF_F_RXALL | - NETIF_F_RXFCS); - - if (pci_using_dac) { - netdev->features |= NETIF_F_HIGHDMA; - netdev->vlan_features |= NETIF_F_HIGHDMA; - } - - netdev->vlan_features |= (NETIF_F_TSO | - NETIF_F_HW_CSUM | - NETIF_F_SG); - - /* Do not set IFF_UNICAST_FLT for VMWare's 82545EM */ - if (hw->device_id != E1000_DEV_ID_82545EM_COPPER || - hw->subsystem_vendor_id != PCI_VENDOR_ID_VMWARE) - netdev->priv_flags |= IFF_UNICAST_FLT; - - adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw); - - /* initialize eeprom parameters */ - if (e1000_init_eeprom_params(hw)) { - e_err(probe, "EEPROM initialization failed\n"); - goto err_eeprom; - } - - /* before reading the EEPROM, reset the controller to - * put the device in a known good starting state - */ - - e1000_reset_hw(hw); - - /* make sure the EEPROM is good */ - if (e1000_validate_eeprom_checksum(hw) < 0) { - e_err(probe, "The EEPROM Checksum Is Not Valid\n"); - e1000_dump_eeprom(adapter); - /* set MAC address to all zeroes to invalidate and temporary - * disable this device for the user. This blocks regular - * traffic while still permitting ethtool ioctls from reaching - * the hardware as well as allowing the user to run the - * interface after manually setting a hw addr using - * `ip set address` - */ - memset(hw->mac_addr, 0, netdev->addr_len); - } else { - /* copy the MAC address out of the EEPROM */ - if (e1000_read_mac_addr(hw)) - e_err(probe, "EEPROM Read Error\n"); - } - /* don't block initialization here due to bad MAC address */ - memcpy(netdev->dev_addr, hw->mac_addr, netdev->addr_len); - - if (!is_valid_ether_addr(netdev->dev_addr)) - e_err(probe, "Invalid MAC Address\n"); - - - INIT_DELAYED_WORK(&adapter->watchdog_task, e1000_watchdog); - INIT_DELAYED_WORK(&adapter->fifo_stall_task, - e1000_82547_tx_fifo_stall_task); - INIT_DELAYED_WORK(&adapter->phy_info_task, e1000_update_phy_info_task); - INIT_WORK(&adapter->reset_task, e1000_reset_task); - - e1000_check_options(adapter); - - /* Initial Wake on LAN setting - * If APM wake is enabled in the EEPROM, - * enable the ACPI Magic Packet filter - */ - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - case e1000_82543: - break; - case e1000_82544: - e1000_read_eeprom(hw, - EEPROM_INIT_CONTROL2_REG, 1, &eeprom_data); - eeprom_apme_mask = E1000_EEPROM_82544_APM; - break; - case e1000_82546: - case e1000_82546_rev_3: - if (er32(STATUS) & E1000_STATUS_FUNC_1){ - e1000_read_eeprom(hw, - EEPROM_INIT_CONTROL3_PORT_B, 1, &eeprom_data); - break; - } - /* Fall Through */ - default: - e1000_read_eeprom(hw, - EEPROM_INIT_CONTROL3_PORT_A, 1, &eeprom_data); - break; - } - if (eeprom_data & eeprom_apme_mask) - adapter->eeprom_wol |= E1000_WUFC_MAG; - - /* now that we have the eeprom settings, apply the special cases - * where the eeprom may be wrong or the board simply won't support - * wake on lan on a particular port - */ - switch (pdev->device) { - case E1000_DEV_ID_82546GB_PCIE: - adapter->eeprom_wol = 0; - break; - case E1000_DEV_ID_82546EB_FIBER: - case E1000_DEV_ID_82546GB_FIBER: - /* Wake events only supported on port A for dual fiber - * regardless of eeprom setting - */ - if (er32(STATUS) & E1000_STATUS_FUNC_1) - adapter->eeprom_wol = 0; - break; - case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: - /* if quad port adapter, disable WoL on all but port A */ - if (global_quad_port_a != 0) - adapter->eeprom_wol = 0; - else - adapter->quad_port_a = true; - /* Reset for multiple quad port adapters */ - if (++global_quad_port_a == 4) - global_quad_port_a = 0; - break; - } - - /* initialize the wol settings based on the eeprom settings */ - adapter->wol = adapter->eeprom_wol; - device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); - - /* Auto detect PHY address */ - if (hw->mac_type == e1000_ce4100) { - for (i = 0; i < 32; i++) { - hw->phy_addr = i; - e1000_read_phy_reg(hw, PHY_ID2, &tmp); - if (tmp == 0 || tmp == 0xFF) { - if (i == 31) - goto err_eeprom; - continue; - } else - break; - } - } - - /* reset the hardware with the new settings */ - e1000_reset(adapter); - - strcpy(netdev->name, "eth%d"); - err = register_netdev(netdev); - if (err) - goto err_register; - - e1000_vlan_filter_on_off(adapter, false); - - /* print bus type/speed/width info */ - e_info(probe, "(PCI%s:%dMHz:%d-bit) %pM\n", - ((hw->bus_type == e1000_bus_type_pcix) ? "-X" : ""), - ((hw->bus_speed == e1000_bus_speed_133) ? 133 : - (hw->bus_speed == e1000_bus_speed_120) ? 120 : - (hw->bus_speed == e1000_bus_speed_100) ? 100 : - (hw->bus_speed == e1000_bus_speed_66) ? 66 : 33), - ((hw->bus_width == e1000_bus_width_64) ? 64 : 32), - netdev->dev_addr); - - /* carrier off reporting is important to ethtool even BEFORE open */ - netif_carrier_off(netdev); - - e_info(probe, "Intel(R) PRO/1000 Network Connection\n"); - - cards_found++; - return 0; - -err_register: -err_eeprom: - e1000_phy_hw_reset(hw); - - if (hw->flash_address) - iounmap(hw->flash_address); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); -err_dma: -err_sw_init: -err_mdio_ioremap: - iounmap(hw->ce4100_gbe_mdio_base_virt); - iounmap(hw->hw_addr); -err_ioremap: - disable_dev = !test_and_set_bit(__E1000_DISABLED, &adapter->flags); - free_netdev(netdev); -err_alloc_etherdev: - pci_release_selected_regions(pdev, bars); -err_pci_reg: - if (!adapter || disable_dev) - pci_disable_device(pdev); - return err; -} - -/** - * e1000_remove - Device Removal Routine - * @pdev: PCI device information struct - * - * e1000_remove is called by the PCI subsystem to alert the driver - * that it should release a PCI device. The could be caused by a - * Hot-Plug event, or because the driver is going to be removed from - * memory. - **/ -static void e1000_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - bool disable_dev; - - e1000_down_and_stop(adapter); - e1000_release_manageability(adapter); - - unregister_netdev(netdev); - - e1000_phy_hw_reset(hw); - - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - - if (hw->mac_type == e1000_ce4100) - iounmap(hw->ce4100_gbe_mdio_base_virt); - iounmap(hw->hw_addr); - if (hw->flash_address) - iounmap(hw->flash_address); - pci_release_selected_regions(pdev, adapter->bars); - - disable_dev = !test_and_set_bit(__E1000_DISABLED, &adapter->flags); - free_netdev(netdev); - - if (disable_dev) - pci_disable_device(pdev); -} - -/** - * e1000_sw_init - Initialize general software structures (struct e1000_adapter) - * @adapter: board private structure to initialize - * - * e1000_sw_init initializes the Adapter private data structure. - * e1000_init_hw_struct MUST be called before this function - **/ -static int e1000_sw_init(struct e1000_adapter *adapter) -{ - adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; - - adapter->num_tx_queues = 1; - adapter->num_rx_queues = 1; - - if (e1000_alloc_queues(adapter)) { - e_err(probe, "Unable to allocate memory for queues\n"); - return -ENOMEM; - } - - /* Explicitly disable IRQ since the NIC can be in any state. */ - e1000_irq_disable(adapter); - - spin_lock_init(&adapter->stats_lock); - - set_bit(__E1000_DOWN, &adapter->flags); - - return 0; -} - -/** - * e1000_alloc_queues - Allocate memory for all rings - * @adapter: board private structure to initialize - * - * We allocate one ring per queue at run-time since we don't know the - * number of queues at compile-time. - **/ -static int e1000_alloc_queues(struct e1000_adapter *adapter) -{ - adapter->tx_ring = kcalloc(adapter->num_tx_queues, - sizeof(struct e1000_tx_ring), GFP_KERNEL); - if (!adapter->tx_ring) - return -ENOMEM; - - adapter->rx_ring = kcalloc(adapter->num_rx_queues, - sizeof(struct e1000_rx_ring), GFP_KERNEL); - if (!adapter->rx_ring) { - kfree(adapter->tx_ring); - return -ENOMEM; - } - - return E1000_SUCCESS; -} - -/** - * e1000_open - Called when a network interface is made active - * @netdev: network interface device structure - * - * Returns 0 on success, negative value on failure - * - * The open entry point is called when a network interface is made - * active by the system (IFF_UP). At this point all resources needed - * for transmit and receive operations are allocated, the interrupt - * handler is registered with the OS, the watchdog task is started, - * and the stack is notified that the interface is ready. - **/ -static int e1000_open(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - int err; - - /* disallow open during test */ - if (test_bit(__E1000_TESTING, &adapter->flags)) - return -EBUSY; - - netif_carrier_off(netdev); - - /* allocate transmit descriptors */ - err = e1000_setup_all_tx_resources(adapter); - if (err) - goto err_setup_tx; - - /* allocate receive descriptors */ - err = e1000_setup_all_rx_resources(adapter); - if (err) - goto err_setup_rx; - - e1000_power_up_phy(adapter); - - adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; - if ((hw->mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT)) { - e1000_update_mng_vlan(adapter); - } - - /* before we allocate an interrupt, we must be ready to handle it. - * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt - * as soon as we call pci_request_irq, so we have to setup our - * clean_rx handler before we do so. - */ - e1000_configure(adapter); - - err = e1000_request_irq(adapter); - if (err) - goto err_req_irq; - - /* From here on the code is the same as e1000_up() */ - clear_bit(__E1000_DOWN, &adapter->flags); - - napi_enable(&adapter->napi); - - e1000_irq_enable(adapter); - - netif_start_queue(netdev); - - /* fire a link status change interrupt to start the watchdog */ - ew32(ICS, E1000_ICS_LSC); - - return E1000_SUCCESS; - -err_req_irq: - e1000_power_down_phy(adapter); - e1000_free_all_rx_resources(adapter); -err_setup_rx: - e1000_free_all_tx_resources(adapter); -err_setup_tx: - e1000_reset(adapter); - - return err; -} - -/** - * e1000_close - Disables a network interface - * @netdev: network interface device structure - * - * Returns 0, this is not allowed to fail - * - * The close entry point is called when an interface is de-activated - * by the OS. The hardware is still under the drivers control, but - * needs to be disabled. A global MAC reset is issued to stop the - * hardware, and all transmit and receive resources are freed. - **/ -static int e1000_close(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - int count = E1000_CHECK_RESET_COUNT; - - while (test_bit(__E1000_RESETTING, &adapter->flags) && count--) - usleep_range(10000, 20000); - - WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); - e1000_down(adapter); - e1000_power_down_phy(adapter); - e1000_free_irq(adapter); - - e1000_free_all_tx_resources(adapter); - e1000_free_all_rx_resources(adapter); - - /* kill manageability vlan ID if supported, but not if a vlan with - * the same ID is registered on the host OS (let 8021q kill it) - */ - if ((hw->mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && - !test_bit(adapter->mng_vlan_id, adapter->active_vlans)) { - e1000_vlan_rx_kill_vid(netdev, htons(ETH_P_8021Q), - adapter->mng_vlan_id); - } - - return 0; -} - -/** - * e1000_check_64k_bound - check that memory doesn't cross 64kB boundary - * @adapter: address of board private structure - * @start: address of beginning of memory - * @len: length of memory - **/ -static bool e1000_check_64k_bound(struct e1000_adapter *adapter, void *start, - unsigned long len) -{ - struct e1000_hw *hw = &adapter->hw; - unsigned long begin = (unsigned long)start; - unsigned long end = begin + len; - - /* First rev 82545 and 82546 need to not allow any memory - * write location to cross 64k boundary due to errata 23 - */ - if (hw->mac_type == e1000_82545 || - hw->mac_type == e1000_ce4100 || - hw->mac_type == e1000_82546) { - return ((begin ^ (end - 1)) >> 16) != 0 ? false : true; - } - - return true; -} - -/** - * e1000_setup_tx_resources - allocate Tx resources (Descriptors) - * @adapter: board private structure - * @txdr: tx descriptor ring (for a specific queue) to setup - * - * Return 0 on success, negative on failure - **/ -static int e1000_setup_tx_resources(struct e1000_adapter *adapter, - struct e1000_tx_ring *txdr) -{ - struct pci_dev *pdev = adapter->pdev; - int size; - - size = sizeof(struct e1000_tx_buffer) * txdr->count; - txdr->buffer_info = vzalloc(size); - if (!txdr->buffer_info) - return -ENOMEM; - - /* round up to nearest 4K */ - - txdr->size = txdr->count * sizeof(struct e1000_tx_desc); - txdr->size = ALIGN(txdr->size, 4096); - - txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma, - GFP_KERNEL); - if (!txdr->desc) { -setup_tx_desc_die: - vfree(txdr->buffer_info); - return -ENOMEM; - } - - /* Fix for errata 23, can't cross 64kB boundary */ - if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) { - void *olddesc = txdr->desc; - dma_addr_t olddma = txdr->dma; - e_err(tx_err, "txdr align check failed: %u bytes at %p\n", - txdr->size, txdr->desc); - /* Try again, without freeing the previous */ - txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, - &txdr->dma, GFP_KERNEL); - /* Failed allocation, critical failure */ - if (!txdr->desc) { - dma_free_coherent(&pdev->dev, txdr->size, olddesc, - olddma); - goto setup_tx_desc_die; - } - - if (!e1000_check_64k_bound(adapter, txdr->desc, txdr->size)) { - /* give up */ - dma_free_coherent(&pdev->dev, txdr->size, txdr->desc, - txdr->dma); - dma_free_coherent(&pdev->dev, txdr->size, olddesc, - olddma); - e_err(probe, "Unable to allocate aligned memory " - "for the transmit descriptor ring\n"); - vfree(txdr->buffer_info); - return -ENOMEM; - } else { - /* Free old allocation, new allocation was successful */ - dma_free_coherent(&pdev->dev, txdr->size, olddesc, - olddma); - } - } - memset(txdr->desc, 0, txdr->size); - - txdr->next_to_use = 0; - txdr->next_to_clean = 0; - - return 0; -} - -/** - * e1000_setup_all_tx_resources - wrapper to allocate Tx resources - * (Descriptors) for all queues - * @adapter: board private structure - * - * Return 0 on success, negative on failure - **/ -int e1000_setup_all_tx_resources(struct e1000_adapter *adapter) -{ - int i, err = 0; - - for (i = 0; i < adapter->num_tx_queues; i++) { - err = e1000_setup_tx_resources(adapter, &adapter->tx_ring[i]); - if (err) { - e_err(probe, "Allocation for Tx Queue %u failed\n", i); - for (i-- ; i >= 0; i--) - e1000_free_tx_resources(adapter, - &adapter->tx_ring[i]); - break; - } - } - - return err; -} - -/** - * e1000_configure_tx - Configure 8254x Transmit Unit after Reset - * @adapter: board private structure - * - * Configure the Tx unit of the MAC after a reset. - **/ -static void e1000_configure_tx(struct e1000_adapter *adapter) -{ - u64 tdba; - struct e1000_hw *hw = &adapter->hw; - u32 tdlen, tctl, tipg; - u32 ipgr1, ipgr2; - - /* Setup the HW Tx Head and Tail descriptor pointers */ - - switch (adapter->num_tx_queues) { - case 1: - default: - tdba = adapter->tx_ring[0].dma; - tdlen = adapter->tx_ring[0].count * - sizeof(struct e1000_tx_desc); - ew32(TDLEN, tdlen); - ew32(TDBAH, (tdba >> 32)); - ew32(TDBAL, (tdba & 0x00000000ffffffffULL)); - ew32(TDT, 0); - ew32(TDH, 0); - adapter->tx_ring[0].tdh = ((hw->mac_type >= e1000_82543) ? - E1000_TDH : E1000_82542_TDH); - adapter->tx_ring[0].tdt = ((hw->mac_type >= e1000_82543) ? - E1000_TDT : E1000_82542_TDT); - break; - } - - /* Set the default values for the Tx Inter Packet Gap timer */ - if ((hw->media_type == e1000_media_type_fiber || - hw->media_type == e1000_media_type_internal_serdes)) - tipg = DEFAULT_82543_TIPG_IPGT_FIBER; - else - tipg = DEFAULT_82543_TIPG_IPGT_COPPER; - - switch (hw->mac_type) { - case e1000_82542_rev2_0: - case e1000_82542_rev2_1: - tipg = DEFAULT_82542_TIPG_IPGT; - ipgr1 = DEFAULT_82542_TIPG_IPGR1; - ipgr2 = DEFAULT_82542_TIPG_IPGR2; - break; - default: - ipgr1 = DEFAULT_82543_TIPG_IPGR1; - ipgr2 = DEFAULT_82543_TIPG_IPGR2; - break; - } - tipg |= ipgr1 << E1000_TIPG_IPGR1_SHIFT; - tipg |= ipgr2 << E1000_TIPG_IPGR2_SHIFT; - ew32(TIPG, tipg); - - /* Set the Tx Interrupt Delay register */ - - ew32(TIDV, adapter->tx_int_delay); - if (hw->mac_type >= e1000_82540) - ew32(TADV, adapter->tx_abs_int_delay); - - /* Program the Transmit Control Register */ - - tctl = er32(TCTL); - tctl &= ~E1000_TCTL_CT; - tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | - (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); - - e1000_config_collision_dist(hw); - - /* Setup Transmit Descriptor Settings for eop descriptor */ - adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS; - - /* only set IDE if we are delaying interrupts using the timers */ - if (adapter->tx_int_delay) - adapter->txd_cmd |= E1000_TXD_CMD_IDE; - - if (hw->mac_type < e1000_82543) - adapter->txd_cmd |= E1000_TXD_CMD_RPS; - else - adapter->txd_cmd |= E1000_TXD_CMD_RS; - - /* Cache if we're 82544 running in PCI-X because we'll - * need this to apply a workaround later in the send path. - */ - if (hw->mac_type == e1000_82544 && - hw->bus_type == e1000_bus_type_pcix) - adapter->pcix_82544 = true; - - ew32(TCTL, tctl); - -} - -/** - * e1000_setup_rx_resources - allocate Rx resources (Descriptors) - * @adapter: board private structure - * @rxdr: rx descriptor ring (for a specific queue) to setup - * - * Returns 0 on success, negative on failure - **/ -static int e1000_setup_rx_resources(struct e1000_adapter *adapter, - struct e1000_rx_ring *rxdr) -{ - struct pci_dev *pdev = adapter->pdev; - int size, desc_len; - - size = sizeof(struct e1000_rx_buffer) * rxdr->count; - rxdr->buffer_info = vzalloc(size); - if (!rxdr->buffer_info) - return -ENOMEM; - - desc_len = sizeof(struct e1000_rx_desc); - - /* Round up to nearest 4K */ - - rxdr->size = rxdr->count * desc_len; - rxdr->size = ALIGN(rxdr->size, 4096); - - rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma, - GFP_KERNEL); - if (!rxdr->desc) { -setup_rx_desc_die: - vfree(rxdr->buffer_info); - return -ENOMEM; - } - - /* Fix for errata 23, can't cross 64kB boundary */ - if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { - void *olddesc = rxdr->desc; - dma_addr_t olddma = rxdr->dma; - e_err(rx_err, "rxdr align check failed: %u bytes at %p\n", - rxdr->size, rxdr->desc); - /* Try again, without freeing the previous */ - rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, - &rxdr->dma, GFP_KERNEL); - /* Failed allocation, critical failure */ - if (!rxdr->desc) { - dma_free_coherent(&pdev->dev, rxdr->size, olddesc, - olddma); - goto setup_rx_desc_die; - } - - if (!e1000_check_64k_bound(adapter, rxdr->desc, rxdr->size)) { - /* give up */ - dma_free_coherent(&pdev->dev, rxdr->size, rxdr->desc, - rxdr->dma); - dma_free_coherent(&pdev->dev, rxdr->size, olddesc, - olddma); - e_err(probe, "Unable to allocate aligned memory for " - "the Rx descriptor ring\n"); - goto setup_rx_desc_die; - } else { - /* Free old allocation, new allocation was successful */ - dma_free_coherent(&pdev->dev, rxdr->size, olddesc, - olddma); - } - } - memset(rxdr->desc, 0, rxdr->size); - - rxdr->next_to_clean = 0; - rxdr->next_to_use = 0; - rxdr->rx_skb_top = NULL; - - return 0; -} - -/** - * e1000_setup_all_rx_resources - wrapper to allocate Rx resources - * (Descriptors) for all queues - * @adapter: board private structure - * - * Return 0 on success, negative on failure - **/ -int e1000_setup_all_rx_resources(struct e1000_adapter *adapter) -{ - int i, err = 0; - - for (i = 0; i < adapter->num_rx_queues; i++) { - err = e1000_setup_rx_resources(adapter, &adapter->rx_ring[i]); - if (err) { - e_err(probe, "Allocation for Rx Queue %u failed\n", i); - for (i-- ; i >= 0; i--) - e1000_free_rx_resources(adapter, - &adapter->rx_ring[i]); - break; - } - } - - return err; -} - -/** - * e1000_setup_rctl - configure the receive control registers - * @adapter: Board private structure - **/ -static void e1000_setup_rctl(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - rctl = er32(RCTL); - - rctl &= ~(3 << E1000_RCTL_MO_SHIFT); - - rctl |= E1000_RCTL_BAM | E1000_RCTL_LBM_NO | - E1000_RCTL_RDMTS_HALF | - (hw->mc_filter_type << E1000_RCTL_MO_SHIFT); - - if (hw->tbi_compatibility_on == 1) - rctl |= E1000_RCTL_SBP; - else - rctl &= ~E1000_RCTL_SBP; - - if (adapter->netdev->mtu <= ETH_DATA_LEN) - rctl &= ~E1000_RCTL_LPE; - else - rctl |= E1000_RCTL_LPE; - - /* Setup buffer sizes */ - rctl &= ~E1000_RCTL_SZ_4096; - rctl |= E1000_RCTL_BSEX; - switch (adapter->rx_buffer_len) { - case E1000_RXBUFFER_2048: - default: - rctl |= E1000_RCTL_SZ_2048; - rctl &= ~E1000_RCTL_BSEX; - break; - case E1000_RXBUFFER_4096: - rctl |= E1000_RCTL_SZ_4096; - break; - case E1000_RXBUFFER_8192: - rctl |= E1000_RCTL_SZ_8192; - break; - case E1000_RXBUFFER_16384: - rctl |= E1000_RCTL_SZ_16384; - break; - } - - /* This is useful for sniffing bad packets. */ - if (adapter->netdev->features & NETIF_F_RXALL) { - /* UPE and MPE will be handled by normal PROMISC logic - * in e1000e_set_rx_mode - */ - rctl |= (E1000_RCTL_SBP | /* Receive bad packets */ - E1000_RCTL_BAM | /* RX All Bcast Pkts */ - E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */ - - rctl &= ~(E1000_RCTL_VFE | /* Disable VLAN filter */ - E1000_RCTL_DPF | /* Allow filtered pause */ - E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */ - /* Do not mess with E1000_CTRL_VME, it affects transmit as well, - * and that breaks VLANs. - */ - } - - ew32(RCTL, rctl); -} - -/** - * e1000_configure_rx - Configure 8254x Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Rx unit of the MAC after a reset. - **/ -static void e1000_configure_rx(struct e1000_adapter *adapter) -{ - u64 rdba; - struct e1000_hw *hw = &adapter->hw; - u32 rdlen, rctl, rxcsum; - - if (adapter->netdev->mtu > ETH_DATA_LEN) { - rdlen = adapter->rx_ring[0].count * - sizeof(struct e1000_rx_desc); - adapter->clean_rx = e1000_clean_jumbo_rx_irq; - adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers; - } else { - rdlen = adapter->rx_ring[0].count * - sizeof(struct e1000_rx_desc); - adapter->clean_rx = e1000_clean_rx_irq; - adapter->alloc_rx_buf = e1000_alloc_rx_buffers; - } - - /* disable receives while setting up the descriptors */ - rctl = er32(RCTL); - ew32(RCTL, rctl & ~E1000_RCTL_EN); - - /* set the Receive Delay Timer Register */ - ew32(RDTR, adapter->rx_int_delay); - - if (hw->mac_type >= e1000_82540) { - ew32(RADV, adapter->rx_abs_int_delay); - if (adapter->itr_setting != 0) - ew32(ITR, 1000000000 / (adapter->itr * 256)); - } - - /* Setup the HW Rx Head and Tail Descriptor Pointers and - * the Base and Length of the Rx Descriptor Ring - */ - switch (adapter->num_rx_queues) { - case 1: - default: - rdba = adapter->rx_ring[0].dma; - ew32(RDLEN, rdlen); - ew32(RDBAH, (rdba >> 32)); - ew32(RDBAL, (rdba & 0x00000000ffffffffULL)); - ew32(RDT, 0); - ew32(RDH, 0); - adapter->rx_ring[0].rdh = ((hw->mac_type >= e1000_82543) ? - E1000_RDH : E1000_82542_RDH); - adapter->rx_ring[0].rdt = ((hw->mac_type >= e1000_82543) ? - E1000_RDT : E1000_82542_RDT); - break; - } - - /* Enable 82543 Receive Checksum Offload for TCP and UDP */ - if (hw->mac_type >= e1000_82543) { - rxcsum = er32(RXCSUM); - if (adapter->rx_csum) - rxcsum |= E1000_RXCSUM_TUOFL; - else - /* don't need to clear IPPCSE as it defaults to 0 */ - rxcsum &= ~E1000_RXCSUM_TUOFL; - ew32(RXCSUM, rxcsum); - } - - /* Enable Receives */ - ew32(RCTL, rctl | E1000_RCTL_EN); -} - -/** - * e1000_free_tx_resources - Free Tx Resources per Queue - * @adapter: board private structure - * @tx_ring: Tx descriptor ring for a specific queue - * - * Free all transmit software resources - **/ -static void e1000_free_tx_resources(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring) -{ - struct pci_dev *pdev = adapter->pdev; - - e1000_clean_tx_ring(adapter, tx_ring); - - vfree(tx_ring->buffer_info); - tx_ring->buffer_info = NULL; - - dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, - tx_ring->dma); - - tx_ring->desc = NULL; -} - -/** - * e1000_free_all_tx_resources - Free Tx Resources for All Queues - * @adapter: board private structure - * - * Free all transmit software resources - **/ -void e1000_free_all_tx_resources(struct e1000_adapter *adapter) -{ - int i; - - for (i = 0; i < adapter->num_tx_queues; i++) - e1000_free_tx_resources(adapter, &adapter->tx_ring[i]); -} - -static void -e1000_unmap_and_free_tx_resource(struct e1000_adapter *adapter, - struct e1000_tx_buffer *buffer_info) -{ - if (buffer_info->dma) { - if (buffer_info->mapped_as_page) - dma_unmap_page(&adapter->pdev->dev, buffer_info->dma, - buffer_info->length, DMA_TO_DEVICE); - else - dma_unmap_single(&adapter->pdev->dev, buffer_info->dma, - buffer_info->length, - DMA_TO_DEVICE); - buffer_info->dma = 0; - } - if (buffer_info->skb) { - dev_kfree_skb_any(buffer_info->skb); - buffer_info->skb = NULL; - } - buffer_info->time_stamp = 0; - /* buffer_info must be completely set up in the transmit path */ -} - -/** - * e1000_clean_tx_ring - Free Tx Buffers - * @adapter: board private structure - * @tx_ring: ring to be cleaned - **/ -static void e1000_clean_tx_ring(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_tx_buffer *buffer_info; - unsigned long size; - unsigned int i; - - /* Free all the Tx ring sk_buffs */ - - for (i = 0; i < tx_ring->count; i++) { - buffer_info = &tx_ring->buffer_info[i]; - e1000_unmap_and_free_tx_resource(adapter, buffer_info); - } - - netdev_reset_queue(adapter->netdev); - size = sizeof(struct e1000_tx_buffer) * tx_ring->count; - memset(tx_ring->buffer_info, 0, size); - - /* Zero out the descriptor ring */ - - memset(tx_ring->desc, 0, tx_ring->size); - - tx_ring->next_to_use = 0; - tx_ring->next_to_clean = 0; - tx_ring->last_tx_tso = false; - - writel(0, hw->hw_addr + tx_ring->tdh); - writel(0, hw->hw_addr + tx_ring->tdt); -} - -/** - * e1000_clean_all_tx_rings - Free Tx Buffers for all queues - * @adapter: board private structure - **/ -static void e1000_clean_all_tx_rings(struct e1000_adapter *adapter) -{ - int i; - - for (i = 0; i < adapter->num_tx_queues; i++) - e1000_clean_tx_ring(adapter, &adapter->tx_ring[i]); -} - -/** - * e1000_free_rx_resources - Free Rx Resources - * @adapter: board private structure - * @rx_ring: ring to clean the resources from - * - * Free all receive software resources - **/ -static void e1000_free_rx_resources(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring) -{ - struct pci_dev *pdev = adapter->pdev; - - e1000_clean_rx_ring(adapter, rx_ring); - - vfree(rx_ring->buffer_info); - rx_ring->buffer_info = NULL; - - dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, - rx_ring->dma); - - rx_ring->desc = NULL; -} - -/** - * e1000_free_all_rx_resources - Free Rx Resources for All Queues - * @adapter: board private structure - * - * Free all receive software resources - **/ -void e1000_free_all_rx_resources(struct e1000_adapter *adapter) -{ - int i; - - for (i = 0; i < adapter->num_rx_queues; i++) - e1000_free_rx_resources(adapter, &adapter->rx_ring[i]); -} - -#define E1000_HEADROOM (NET_SKB_PAD + NET_IP_ALIGN) -static unsigned int e1000_frag_len(const struct e1000_adapter *a) -{ - return SKB_DATA_ALIGN(a->rx_buffer_len + E1000_HEADROOM) + - SKB_DATA_ALIGN(sizeof(struct skb_shared_info)); -} - -static void *e1000_alloc_frag(const struct e1000_adapter *a) -{ - unsigned int len = e1000_frag_len(a); - u8 *data = netdev_alloc_frag(len); - - if (likely(data)) - data += E1000_HEADROOM; - return data; -} - -/** - * e1000_clean_rx_ring - Free Rx Buffers per Queue - * @adapter: board private structure - * @rx_ring: ring to free buffers from - **/ -static void e1000_clean_rx_ring(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_rx_buffer *buffer_info; - struct pci_dev *pdev = adapter->pdev; - unsigned long size; - unsigned int i; - - /* Free all the Rx netfrags */ - for (i = 0; i < rx_ring->count; i++) { - buffer_info = &rx_ring->buffer_info[i]; - if (adapter->clean_rx == e1000_clean_rx_irq) { - if (buffer_info->dma) - dma_unmap_single(&pdev->dev, buffer_info->dma, - adapter->rx_buffer_len, - DMA_FROM_DEVICE); - if (buffer_info->rxbuf.data) { - skb_free_frag(buffer_info->rxbuf.data); - buffer_info->rxbuf.data = NULL; - } - } else if (adapter->clean_rx == e1000_clean_jumbo_rx_irq) { - if (buffer_info->dma) - dma_unmap_page(&pdev->dev, buffer_info->dma, - adapter->rx_buffer_len, - DMA_FROM_DEVICE); - if (buffer_info->rxbuf.page) { - put_page(buffer_info->rxbuf.page); - buffer_info->rxbuf.page = NULL; - } - } - - buffer_info->dma = 0; - } - - /* there also may be some cached data from a chained receive */ - napi_free_frags(&adapter->napi); - rx_ring->rx_skb_top = NULL; - - size = sizeof(struct e1000_rx_buffer) * rx_ring->count; - memset(rx_ring->buffer_info, 0, size); - - /* Zero out the descriptor ring */ - memset(rx_ring->desc, 0, rx_ring->size); - - rx_ring->next_to_clean = 0; - rx_ring->next_to_use = 0; - - writel(0, hw->hw_addr + rx_ring->rdh); - writel(0, hw->hw_addr + rx_ring->rdt); -} - -/** - * e1000_clean_all_rx_rings - Free Rx Buffers for all queues - * @adapter: board private structure - **/ -static void e1000_clean_all_rx_rings(struct e1000_adapter *adapter) -{ - int i; - - for (i = 0; i < adapter->num_rx_queues; i++) - e1000_clean_rx_ring(adapter, &adapter->rx_ring[i]); -} - -/* The 82542 2.0 (revision 2) needs to have the receive unit in reset - * and memory write and invalidate disabled for certain operations - */ -static void e1000_enter_82542_rst(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - u32 rctl; - - e1000_pci_clear_mwi(hw); - - rctl = er32(RCTL); - rctl |= E1000_RCTL_RST; - ew32(RCTL, rctl); - E1000_WRITE_FLUSH(); - mdelay(5); - - if (netif_running(netdev)) - e1000_clean_all_rx_rings(adapter); -} - -static void e1000_leave_82542_rst(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - u32 rctl; - - rctl = er32(RCTL); - rctl &= ~E1000_RCTL_RST; - ew32(RCTL, rctl); - E1000_WRITE_FLUSH(); - mdelay(5); - - if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE) - e1000_pci_set_mwi(hw); - - if (netif_running(netdev)) { - /* No need to loop, because 82542 supports only 1 queue */ - struct e1000_rx_ring *ring = &adapter->rx_ring[0]; - e1000_configure_rx(adapter); - adapter->alloc_rx_buf(adapter, ring, E1000_DESC_UNUSED(ring)); - } -} - -/** - * e1000_set_mac - Change the Ethernet Address of the NIC - * @netdev: network interface device structure - * @p: pointer to an address structure - * - * Returns 0 on success, negative on failure - **/ -static int e1000_set_mac(struct net_device *netdev, void *p) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - /* 82542 2.0 needs to be in reset to write receive address registers */ - - if (hw->mac_type == e1000_82542_rev2_0) - e1000_enter_82542_rst(adapter); - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - memcpy(hw->mac_addr, addr->sa_data, netdev->addr_len); - - e1000_rar_set(hw, hw->mac_addr, 0); - - if (hw->mac_type == e1000_82542_rev2_0) - e1000_leave_82542_rst(adapter); - - return 0; -} - -/** - * e1000_set_rx_mode - Secondary Unicast, Multicast and Promiscuous mode set - * @netdev: network interface device structure - * - * The set_rx_mode entry point is called whenever the unicast or multicast - * address lists or the network interface flags are updated. This routine is - * responsible for configuring the hardware for proper unicast, multicast, - * promiscuous mode, and all-multi behavior. - **/ -static void e1000_set_rx_mode(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct netdev_hw_addr *ha; - bool use_uc = false; - u32 rctl; - u32 hash_value; - int i, rar_entries = E1000_RAR_ENTRIES; - int mta_reg_count = E1000_NUM_MTA_REGISTERS; - u32 *mcarray = kcalloc(mta_reg_count, sizeof(u32), GFP_ATOMIC); - - if (!mcarray) - return; - - /* Check for Promiscuous and All Multicast modes */ - - rctl = er32(RCTL); - - if (netdev->flags & IFF_PROMISC) { - rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); - rctl &= ~E1000_RCTL_VFE; - } else { - if (netdev->flags & IFF_ALLMULTI) - rctl |= E1000_RCTL_MPE; - else - rctl &= ~E1000_RCTL_MPE; - /* Enable VLAN filter if there is a VLAN */ - if (e1000_vlan_used(adapter)) - rctl |= E1000_RCTL_VFE; - } - - if (netdev_uc_count(netdev) > rar_entries - 1) { - rctl |= E1000_RCTL_UPE; - } else if (!(netdev->flags & IFF_PROMISC)) { - rctl &= ~E1000_RCTL_UPE; - use_uc = true; - } - - ew32(RCTL, rctl); - - /* 82542 2.0 needs to be in reset to write receive address registers */ - - if (hw->mac_type == e1000_82542_rev2_0) - e1000_enter_82542_rst(adapter); - - /* load the first 14 addresses into the exact filters 1-14. Unicast - * addresses take precedence to avoid disabling unicast filtering - * when possible. - * - * RAR 0 is used for the station MAC address - * if there are not 14 addresses, go ahead and clear the filters - */ - i = 1; - if (use_uc) - netdev_for_each_uc_addr(ha, netdev) { - if (i == rar_entries) - break; - e1000_rar_set(hw, ha->addr, i++); - } - - netdev_for_each_mc_addr(ha, netdev) { - if (i == rar_entries) { - /* load any remaining addresses into the hash table */ - u32 hash_reg, hash_bit, mta; - hash_value = e1000_hash_mc_addr(hw, ha->addr); - hash_reg = (hash_value >> 5) & 0x7F; - hash_bit = hash_value & 0x1F; - mta = (1 << hash_bit); - mcarray[hash_reg] |= mta; - } else { - e1000_rar_set(hw, ha->addr, i++); - } - } - - for (; i < rar_entries; i++) { - E1000_WRITE_REG_ARRAY(hw, RA, i << 1, 0); - E1000_WRITE_FLUSH(); - E1000_WRITE_REG_ARRAY(hw, RA, (i << 1) + 1, 0); - E1000_WRITE_FLUSH(); - } - - /* write the hash table completely, write from bottom to avoid - * both stupid write combining chipsets, and flushing each write - */ - for (i = mta_reg_count - 1; i >= 0 ; i--) { - /* If we are on an 82544 has an errata where writing odd - * offsets overwrites the previous even offset, but writing - * backwards over the range solves the issue by always - * writing the odd offset first - */ - E1000_WRITE_REG_ARRAY(hw, MTA, i, mcarray[i]); - } - E1000_WRITE_FLUSH(); - - if (hw->mac_type == e1000_82542_rev2_0) - e1000_leave_82542_rst(adapter); - - kfree(mcarray); -} - -/** - * e1000_update_phy_info_task - get phy info - * @work: work struct contained inside adapter struct - * - * Need to wait a few seconds after link up to get diagnostic information from - * the phy - */ -static void e1000_update_phy_info_task(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - phy_info_task.work); - - e1000_phy_get_info(&adapter->hw, &adapter->phy_info); -} - -/** - * e1000_82547_tx_fifo_stall_task - task to complete work - * @work: work struct contained inside adapter struct - **/ -static void e1000_82547_tx_fifo_stall_task(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - fifo_stall_task.work); - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - u32 tctl; - - if (atomic_read(&adapter->tx_fifo_stall)) { - if ((er32(TDT) == er32(TDH)) && - (er32(TDFT) == er32(TDFH)) && - (er32(TDFTS) == er32(TDFHS))) { - tctl = er32(TCTL); - ew32(TCTL, tctl & ~E1000_TCTL_EN); - ew32(TDFT, adapter->tx_head_addr); - ew32(TDFH, adapter->tx_head_addr); - ew32(TDFTS, adapter->tx_head_addr); - ew32(TDFHS, adapter->tx_head_addr); - ew32(TCTL, tctl); - E1000_WRITE_FLUSH(); - - adapter->tx_fifo_head = 0; - atomic_set(&adapter->tx_fifo_stall, 0); - netif_wake_queue(netdev); - } else if (!test_bit(__E1000_DOWN, &adapter->flags)) { - schedule_delayed_work(&adapter->fifo_stall_task, 1); - } - } -} - -bool e1000_has_link(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - bool link_active = false; - - /* get_link_status is set on LSC (link status) interrupt or rx - * sequence error interrupt (except on intel ce4100). - * get_link_status will stay false until the - * e1000_check_for_link establishes link for copper adapters - * ONLY - */ - switch (hw->media_type) { - case e1000_media_type_copper: - if (hw->mac_type == e1000_ce4100) - hw->get_link_status = 1; - if (hw->get_link_status) { - e1000_check_for_link(hw); - link_active = !hw->get_link_status; - } else { - link_active = true; - } - break; - case e1000_media_type_fiber: - e1000_check_for_link(hw); - link_active = !!(er32(STATUS) & E1000_STATUS_LU); - break; - case e1000_media_type_internal_serdes: - e1000_check_for_link(hw); - link_active = hw->serdes_has_link; - break; - default: - break; - } - - return link_active; -} - -/** - * e1000_watchdog - work function - * @work: work struct contained inside adapter struct - **/ -static void e1000_watchdog(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - watchdog_task.work); - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - struct e1000_tx_ring *txdr = adapter->tx_ring; - u32 link, tctl; - - link = e1000_has_link(adapter); - if ((netif_carrier_ok(netdev)) && link) - goto link_up; - - if (link) { - if (!netif_carrier_ok(netdev)) { - u32 ctrl; - bool txb2b = true; - /* update snapshot of PHY registers on LSC */ - e1000_get_speed_and_duplex(hw, - &adapter->link_speed, - &adapter->link_duplex); - - ctrl = er32(CTRL); - pr_info("%s NIC Link is Up %d Mbps %s, " - "Flow Control: %s\n", - netdev->name, - adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? - "Full Duplex" : "Half Duplex", - ((ctrl & E1000_CTRL_TFCE) && (ctrl & - E1000_CTRL_RFCE)) ? "RX/TX" : ((ctrl & - E1000_CTRL_RFCE) ? "RX" : ((ctrl & - E1000_CTRL_TFCE) ? "TX" : "None"))); - - /* adjust timeout factor according to speed/duplex */ - adapter->tx_timeout_factor = 1; - switch (adapter->link_speed) { - case SPEED_10: - txb2b = false; - adapter->tx_timeout_factor = 16; - break; - case SPEED_100: - txb2b = false; - /* maybe add some timeout factor ? */ - break; - } - - /* enable transmits in the hardware */ - tctl = er32(TCTL); - tctl |= E1000_TCTL_EN; - ew32(TCTL, tctl); - - netif_carrier_on(netdev); - if (!test_bit(__E1000_DOWN, &adapter->flags)) - schedule_delayed_work(&adapter->phy_info_task, - 2 * HZ); - adapter->smartspeed = 0; - } - } else { - if (netif_carrier_ok(netdev)) { - adapter->link_speed = 0; - adapter->link_duplex = 0; - pr_info("%s NIC Link is Down\n", - netdev->name); - netif_carrier_off(netdev); - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - schedule_delayed_work(&adapter->phy_info_task, - 2 * HZ); - } - - e1000_smartspeed(adapter); - } - -link_up: - e1000_update_stats(adapter); - - hw->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; - adapter->tpt_old = adapter->stats.tpt; - hw->collision_delta = adapter->stats.colc - adapter->colc_old; - adapter->colc_old = adapter->stats.colc; - - adapter->gorcl = adapter->stats.gorcl - adapter->gorcl_old; - adapter->gorcl_old = adapter->stats.gorcl; - adapter->gotcl = adapter->stats.gotcl - adapter->gotcl_old; - adapter->gotcl_old = adapter->stats.gotcl; - - e1000_update_adaptive(hw); - - if (!netif_carrier_ok(netdev)) { - if (E1000_DESC_UNUSED(txdr) + 1 < txdr->count) { - /* We've lost link, so the controller stops DMA, - * but we've got queued Tx work that's never going - * to get done, so reset controller to flush Tx. - * (Do the reset outside of interrupt context). - */ - adapter->tx_timeout_count++; - schedule_work(&adapter->reset_task); - /* exit immediately since reset is imminent */ - return; - } - } - - /* Simple mode for Interrupt Throttle Rate (ITR) */ - if (hw->mac_type >= e1000_82540 && adapter->itr_setting == 4) { - /* Symmetric Tx/Rx gets a reduced ITR=2000; - * Total asymmetrical Tx or Rx gets ITR=8000; - * everyone else is between 2000-8000. - */ - u32 goc = (adapter->gotcl + adapter->gorcl) / 10000; - u32 dif = (adapter->gotcl > adapter->gorcl ? - adapter->gotcl - adapter->gorcl : - adapter->gorcl - adapter->gotcl) / 10000; - u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000; - - ew32(ITR, 1000000000 / (itr * 256)); - } - - /* Cause software interrupt to ensure rx ring is cleaned */ - ew32(ICS, E1000_ICS_RXDMT0); - - /* Force detection of hung controller every watchdog period */ - adapter->detect_tx_hung = true; - - /* Reschedule the task */ - if (!test_bit(__E1000_DOWN, &adapter->flags)) - schedule_delayed_work(&adapter->watchdog_task, 2 * HZ); -} - -enum latency_range { - lowest_latency = 0, - low_latency = 1, - bulk_latency = 2, - latency_invalid = 255 -}; - -/** - * e1000_update_itr - update the dynamic ITR value based on statistics - * @adapter: pointer to adapter - * @itr_setting: current adapter->itr - * @packets: the number of packets during this measurement interval - * @bytes: the number of bytes during this measurement interval - * - * Stores a new ITR value based on packets and byte - * counts during the last interrupt. The advantage of per interrupt - * computation is faster updates and more accurate ITR for the current - * traffic pattern. Constants in this function were computed - * based on theoretical maximum wire speed and thresholds were set based - * on testing data as well as attempting to minimize response time - * while increasing bulk throughput. - * this functionality is controlled by the InterruptThrottleRate module - * parameter (see e1000_param.c) - **/ -static unsigned int e1000_update_itr(struct e1000_adapter *adapter, - u16 itr_setting, int packets, int bytes) -{ - unsigned int retval = itr_setting; - struct e1000_hw *hw = &adapter->hw; - - if (unlikely(hw->mac_type < e1000_82540)) - goto update_itr_done; - - if (packets == 0) - goto update_itr_done; - - switch (itr_setting) { - case lowest_latency: - /* jumbo frames get bulk treatment*/ - if (bytes/packets > 8000) - retval = bulk_latency; - else if ((packets < 5) && (bytes > 512)) - retval = low_latency; - break; - case low_latency: /* 50 usec aka 20000 ints/s */ - if (bytes > 10000) { - /* jumbo frames need bulk latency setting */ - if (bytes/packets > 8000) - retval = bulk_latency; - else if ((packets < 10) || ((bytes/packets) > 1200)) - retval = bulk_latency; - else if ((packets > 35)) - retval = lowest_latency; - } else if (bytes/packets > 2000) - retval = bulk_latency; - else if (packets <= 2 && bytes < 512) - retval = lowest_latency; - break; - case bulk_latency: /* 250 usec aka 4000 ints/s */ - if (bytes > 25000) { - if (packets > 35) - retval = low_latency; - } else if (bytes < 6000) { - retval = low_latency; - } - break; - } - -update_itr_done: - return retval; -} - -static void e1000_set_itr(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u16 current_itr; - u32 new_itr = adapter->itr; - - if (unlikely(hw->mac_type < e1000_82540)) - return; - - /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ - if (unlikely(adapter->link_speed != SPEED_1000)) { - current_itr = 0; - new_itr = 4000; - goto set_itr_now; - } - - adapter->tx_itr = e1000_update_itr(adapter, adapter->tx_itr, - adapter->total_tx_packets, - adapter->total_tx_bytes); - /* conservative mode (itr 3) eliminates the lowest_latency setting */ - if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency) - adapter->tx_itr = low_latency; - - adapter->rx_itr = e1000_update_itr(adapter, adapter->rx_itr, - adapter->total_rx_packets, - adapter->total_rx_bytes); - /* conservative mode (itr 3) eliminates the lowest_latency setting */ - if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency) - adapter->rx_itr = low_latency; - - current_itr = max(adapter->rx_itr, adapter->tx_itr); - - switch (current_itr) { - /* counts and packets in update_itr are dependent on these numbers */ - case lowest_latency: - new_itr = 70000; - break; - case low_latency: - new_itr = 20000; /* aka hwitr = ~200 */ - break; - case bulk_latency: - new_itr = 4000; - break; - default: - break; - } - -set_itr_now: - if (new_itr != adapter->itr) { - /* this attempts to bias the interrupt rate towards Bulk - * by adding intermediate steps when interrupt rate is - * increasing - */ - new_itr = new_itr > adapter->itr ? - min(adapter->itr + (new_itr >> 2), new_itr) : - new_itr; - adapter->itr = new_itr; - ew32(ITR, 1000000000 / (new_itr * 256)); - } -} - -#define E1000_TX_FLAGS_CSUM 0x00000001 -#define E1000_TX_FLAGS_VLAN 0x00000002 -#define E1000_TX_FLAGS_TSO 0x00000004 -#define E1000_TX_FLAGS_IPV4 0x00000008 -#define E1000_TX_FLAGS_NO_FCS 0x00000010 -#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 -#define E1000_TX_FLAGS_VLAN_SHIFT 16 - -static int e1000_tso(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring, struct sk_buff *skb, - __be16 protocol) -{ - struct e1000_context_desc *context_desc; - struct e1000_tx_buffer *buffer_info; - unsigned int i; - u32 cmd_length = 0; - u16 ipcse = 0, tucse, mss; - u8 ipcss, ipcso, tucss, tucso, hdr_len; - - if (skb_is_gso(skb)) { - int err; - - err = skb_cow_head(skb, 0); - if (err < 0) - return err; - - hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - mss = skb_shinfo(skb)->gso_size; - if (protocol == htons(ETH_P_IP)) { - struct iphdr *iph = ip_hdr(skb); - iph->tot_len = 0; - iph->check = 0; - tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, - iph->daddr, 0, - IPPROTO_TCP, - 0); - cmd_length = E1000_TXD_CMD_IP; - ipcse = skb_transport_offset(skb) - 1; - } else if (skb_is_gso_v6(skb)) { - ipv6_hdr(skb)->payload_len = 0; - tcp_hdr(skb)->check = - ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); - ipcse = 0; - } - ipcss = skb_network_offset(skb); - ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data; - tucss = skb_transport_offset(skb); - tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data; - tucse = 0; - - cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | - E1000_TXD_CMD_TCP | (skb->len - (hdr_len))); - - i = tx_ring->next_to_use; - context_desc = E1000_CONTEXT_DESC(*tx_ring, i); - buffer_info = &tx_ring->buffer_info[i]; - - context_desc->lower_setup.ip_fields.ipcss = ipcss; - context_desc->lower_setup.ip_fields.ipcso = ipcso; - context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse); - context_desc->upper_setup.tcp_fields.tucss = tucss; - context_desc->upper_setup.tcp_fields.tucso = tucso; - context_desc->upper_setup.tcp_fields.tucse = cpu_to_le16(tucse); - context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss); - context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; - context_desc->cmd_and_length = cpu_to_le32(cmd_length); - - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; - - if (++i == tx_ring->count) i = 0; - tx_ring->next_to_use = i; - - return true; - } - return false; -} - -static bool e1000_tx_csum(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring, struct sk_buff *skb, - __be16 protocol) -{ - struct e1000_context_desc *context_desc; - struct e1000_tx_buffer *buffer_info; - unsigned int i; - u8 css; - u32 cmd_len = E1000_TXD_CMD_DEXT; - - if (skb->ip_summed != CHECKSUM_PARTIAL) - return false; - - switch (protocol) { - case cpu_to_be16(ETH_P_IP): - if (ip_hdr(skb)->protocol == IPPROTO_TCP) - cmd_len |= E1000_TXD_CMD_TCP; - break; - case cpu_to_be16(ETH_P_IPV6): - /* XXX not handling all IPV6 headers */ - if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) - cmd_len |= E1000_TXD_CMD_TCP; - break; - default: - if (unlikely(net_ratelimit())) - e_warn(drv, "checksum_partial proto=%x!\n", - skb->protocol); - break; - } - - css = skb_checksum_start_offset(skb); - - i = tx_ring->next_to_use; - buffer_info = &tx_ring->buffer_info[i]; - context_desc = E1000_CONTEXT_DESC(*tx_ring, i); - - context_desc->lower_setup.ip_config = 0; - context_desc->upper_setup.tcp_fields.tucss = css; - context_desc->upper_setup.tcp_fields.tucso = - css + skb->csum_offset; - context_desc->upper_setup.tcp_fields.tucse = 0; - context_desc->tcp_seg_setup.data = 0; - context_desc->cmd_and_length = cpu_to_le32(cmd_len); - - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; - - if (unlikely(++i == tx_ring->count)) i = 0; - tx_ring->next_to_use = i; - - return true; -} - -#define E1000_MAX_TXD_PWR 12 -#define E1000_MAX_DATA_PER_TXD (1<hw; - struct pci_dev *pdev = adapter->pdev; - struct e1000_tx_buffer *buffer_info; - unsigned int len = skb_headlen(skb); - unsigned int offset = 0, size, count = 0, i; - unsigned int f, bytecount, segs; - - i = tx_ring->next_to_use; - - while (len) { - buffer_info = &tx_ring->buffer_info[i]; - size = min(len, max_per_txd); - /* Workaround for Controller erratum -- - * descriptor for non-tso packet in a linear SKB that follows a - * tso gets written back prematurely before the data is fully - * DMA'd to the controller - */ - if (!skb->data_len && tx_ring->last_tx_tso && - !skb_is_gso(skb)) { - tx_ring->last_tx_tso = false; - size -= 4; - } - - /* Workaround for premature desc write-backs - * in TSO mode. Append 4-byte sentinel desc - */ - if (unlikely(mss && !nr_frags && size == len && size > 8)) - size -= 4; - /* work-around for errata 10 and it applies - * to all controllers in PCI-X mode - * The fix is to make sure that the first descriptor of a - * packet is smaller than 2048 - 16 - 16 (or 2016) bytes - */ - if (unlikely((hw->bus_type == e1000_bus_type_pcix) && - (size > 2015) && count == 0)) - size = 2015; - - /* Workaround for potential 82544 hang in PCI-X. Avoid - * terminating buffers within evenly-aligned dwords. - */ - if (unlikely(adapter->pcix_82544 && - !((unsigned long)(skb->data + offset + size - 1) & 4) && - size > 4)) - size -= 4; - - buffer_info->length = size; - /* set time_stamp *before* dma to help avoid a possible race */ - buffer_info->time_stamp = jiffies; - buffer_info->mapped_as_page = false; - buffer_info->dma = dma_map_single(&pdev->dev, - skb->data + offset, - size, DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) - goto dma_error; - buffer_info->next_to_watch = i; - - len -= size; - offset += size; - count++; - if (len) { - i++; - if (unlikely(i == tx_ring->count)) - i = 0; - } - } - - for (f = 0; f < nr_frags; f++) { - const struct skb_frag_struct *frag; - - frag = &skb_shinfo(skb)->frags[f]; - len = skb_frag_size(frag); - offset = 0; - - while (len) { - unsigned long bufend; - i++; - if (unlikely(i == tx_ring->count)) - i = 0; - - buffer_info = &tx_ring->buffer_info[i]; - size = min(len, max_per_txd); - /* Workaround for premature desc write-backs - * in TSO mode. Append 4-byte sentinel desc - */ - if (unlikely(mss && f == (nr_frags-1) && - size == len && size > 8)) - size -= 4; - /* Workaround for potential 82544 hang in PCI-X. - * Avoid terminating buffers within evenly-aligned - * dwords. - */ - bufend = (unsigned long) - page_to_phys(skb_frag_page(frag)); - bufend += offset + size - 1; - if (unlikely(adapter->pcix_82544 && - !(bufend & 4) && - size > 4)) - size -= 4; - - buffer_info->length = size; - buffer_info->time_stamp = jiffies; - buffer_info->mapped_as_page = true; - buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag, - offset, size, DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) - goto dma_error; - buffer_info->next_to_watch = i; - - len -= size; - offset += size; - count++; - } - } - - segs = skb_shinfo(skb)->gso_segs ?: 1; - /* multiply data chunks by size of headers */ - bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len; - - tx_ring->buffer_info[i].skb = skb; - tx_ring->buffer_info[i].segs = segs; - tx_ring->buffer_info[i].bytecount = bytecount; - tx_ring->buffer_info[first].next_to_watch = i; - - return count; - -dma_error: - dev_err(&pdev->dev, "TX DMA map failed\n"); - buffer_info->dma = 0; - if (count) - count--; - - while (count--) { - if (i==0) - i += tx_ring->count; - i--; - buffer_info = &tx_ring->buffer_info[i]; - e1000_unmap_and_free_tx_resource(adapter, buffer_info); - } - - return 0; -} - -static void e1000_tx_queue(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring, int tx_flags, - int count) -{ - struct e1000_tx_desc *tx_desc = NULL; - struct e1000_tx_buffer *buffer_info; - u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; - unsigned int i; - - if (likely(tx_flags & E1000_TX_FLAGS_TSO)) { - txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | - E1000_TXD_CMD_TSE; - txd_upper |= E1000_TXD_POPTS_TXSM << 8; - - if (likely(tx_flags & E1000_TX_FLAGS_IPV4)) - txd_upper |= E1000_TXD_POPTS_IXSM << 8; - } - - if (likely(tx_flags & E1000_TX_FLAGS_CSUM)) { - txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; - txd_upper |= E1000_TXD_POPTS_TXSM << 8; - } - - if (unlikely(tx_flags & E1000_TX_FLAGS_VLAN)) { - txd_lower |= E1000_TXD_CMD_VLE; - txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); - } - - if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS)) - txd_lower &= ~(E1000_TXD_CMD_IFCS); - - i = tx_ring->next_to_use; - - while (count--) { - buffer_info = &tx_ring->buffer_info[i]; - tx_desc = E1000_TX_DESC(*tx_ring, i); - tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - tx_desc->lower.data = - cpu_to_le32(txd_lower | buffer_info->length); - tx_desc->upper.data = cpu_to_le32(txd_upper); - if (unlikely(++i == tx_ring->count)) i = 0; - } - - tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); - - /* txd_cmd re-enables FCS, so we'll re-disable it here as desired. */ - if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS)) - tx_desc->lower.data &= ~(cpu_to_le32(E1000_TXD_CMD_IFCS)); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - - tx_ring->next_to_use = i; -} - -/* 82547 workaround to avoid controller hang in half-duplex environment. - * The workaround is to avoid queuing a large packet that would span - * the internal Tx FIFO ring boundary by notifying the stack to resend - * the packet at a later time. This gives the Tx FIFO an opportunity to - * flush all packets. When that occurs, we reset the Tx FIFO pointers - * to the beginning of the Tx FIFO. - */ - -#define E1000_FIFO_HDR 0x10 -#define E1000_82547_PAD_LEN 0x3E0 - -static int e1000_82547_fifo_workaround(struct e1000_adapter *adapter, - struct sk_buff *skb) -{ - u32 fifo_space = adapter->tx_fifo_size - adapter->tx_fifo_head; - u32 skb_fifo_len = skb->len + E1000_FIFO_HDR; - - skb_fifo_len = ALIGN(skb_fifo_len, E1000_FIFO_HDR); - - if (adapter->link_duplex != HALF_DUPLEX) - goto no_fifo_stall_required; - - if (atomic_read(&adapter->tx_fifo_stall)) - return 1; - - if (skb_fifo_len >= (E1000_82547_PAD_LEN + fifo_space)) { - atomic_set(&adapter->tx_fifo_stall, 1); - return 1; - } - -no_fifo_stall_required: - adapter->tx_fifo_head += skb_fifo_len; - if (adapter->tx_fifo_head >= adapter->tx_fifo_size) - adapter->tx_fifo_head -= adapter->tx_fifo_size; - return 0; -} - -static int __e1000_maybe_stop_tx(struct net_device *netdev, int size) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_tx_ring *tx_ring = adapter->tx_ring; - - netif_stop_queue(netdev); - /* Herbert's original patch had: - * smp_mb__after_netif_stop_queue(); - * but since that doesn't exist yet, just open code it. - */ - smp_mb(); - - /* We need to check again in a case another CPU has just - * made room available. - */ - if (likely(E1000_DESC_UNUSED(tx_ring) < size)) - return -EBUSY; - - /* A reprieve! */ - netif_start_queue(netdev); - ++adapter->restart_queue; - return 0; -} - -static int e1000_maybe_stop_tx(struct net_device *netdev, - struct e1000_tx_ring *tx_ring, int size) -{ - if (likely(E1000_DESC_UNUSED(tx_ring) >= size)) - return 0; - return __e1000_maybe_stop_tx(netdev, size); -} - -#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1 ) -static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct e1000_tx_ring *tx_ring; - unsigned int first, max_per_txd = E1000_MAX_DATA_PER_TXD; - unsigned int max_txd_pwr = E1000_MAX_TXD_PWR; - unsigned int tx_flags = 0; - unsigned int len = skb_headlen(skb); - unsigned int nr_frags; - unsigned int mss; - int count = 0; - int tso; - unsigned int f; - __be16 protocol = vlan_get_protocol(skb); - - /* This goes back to the question of how to logically map a Tx queue - * to a flow. Right now, performance is impacted slightly negatively - * if using multiple Tx queues. If the stack breaks away from a - * single qdisc implementation, we can look at this again. - */ - tx_ring = adapter->tx_ring; - - /* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN, - * packets may get corrupted during padding by HW. - * To WA this issue, pad all small packets manually. - */ - if (eth_skb_pad(skb)) - return NETDEV_TX_OK; - - mss = skb_shinfo(skb)->gso_size; - /* The controller does a simple calculation to - * make sure there is enough room in the FIFO before - * initiating the DMA for each buffer. The calc is: - * 4 = ceil(buffer len/mss). To make sure we don't - * overrun the FIFO, adjust the max buffer len if mss - * drops. - */ - if (mss) { - u8 hdr_len; - max_per_txd = min(mss << 2, max_per_txd); - max_txd_pwr = fls(max_per_txd) - 1; - - hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - if (skb->data_len && hdr_len == len) { - switch (hw->mac_type) { - unsigned int pull_size; - case e1000_82544: - /* Make sure we have room to chop off 4 bytes, - * and that the end alignment will work out to - * this hardware's requirements - * NOTE: this is a TSO only workaround - * if end byte alignment not correct move us - * into the next dword - */ - if ((unsigned long)(skb_tail_pointer(skb) - 1) - & 4) - break; - /* fall through */ - pull_size = min((unsigned int)4, skb->data_len); - if (!__pskb_pull_tail(skb, pull_size)) { - e_err(drv, "__pskb_pull_tail " - "failed.\n"); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - len = skb_headlen(skb); - break; - default: - /* do nothing */ - break; - } - } - } - - /* reserve a descriptor for the offload context */ - if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL)) - count++; - count++; - - /* Controller Erratum workaround */ - if (!skb->data_len && tx_ring->last_tx_tso && !skb_is_gso(skb)) - count++; - - count += TXD_USE_COUNT(len, max_txd_pwr); - - if (adapter->pcix_82544) - count++; - - /* work-around for errata 10 and it applies to all controllers - * in PCI-X mode, so add one more descriptor to the count - */ - if (unlikely((hw->bus_type == e1000_bus_type_pcix) && - (len > 2015))) - count++; - - nr_frags = skb_shinfo(skb)->nr_frags; - for (f = 0; f < nr_frags; f++) - count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f]), - max_txd_pwr); - if (adapter->pcix_82544) - count += nr_frags; - - /* need: count + 2 desc gap to keep tail from touching - * head, otherwise try next time - */ - if (unlikely(e1000_maybe_stop_tx(netdev, tx_ring, count + 2))) - return NETDEV_TX_BUSY; - - if (unlikely((hw->mac_type == e1000_82547) && - (e1000_82547_fifo_workaround(adapter, skb)))) { - netif_stop_queue(netdev); - if (!test_bit(__E1000_DOWN, &adapter->flags)) - schedule_delayed_work(&adapter->fifo_stall_task, 1); - return NETDEV_TX_BUSY; - } - - if (skb_vlan_tag_present(skb)) { - tx_flags |= E1000_TX_FLAGS_VLAN; - tx_flags |= (skb_vlan_tag_get(skb) << - E1000_TX_FLAGS_VLAN_SHIFT); - } - - first = tx_ring->next_to_use; - - tso = e1000_tso(adapter, tx_ring, skb, protocol); - if (tso < 0) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if (likely(tso)) { - if (likely(hw->mac_type != e1000_82544)) - tx_ring->last_tx_tso = true; - tx_flags |= E1000_TX_FLAGS_TSO; - } else if (likely(e1000_tx_csum(adapter, tx_ring, skb, protocol))) - tx_flags |= E1000_TX_FLAGS_CSUM; - - if (protocol == htons(ETH_P_IP)) - tx_flags |= E1000_TX_FLAGS_IPV4; - - if (unlikely(skb->no_fcs)) - tx_flags |= E1000_TX_FLAGS_NO_FCS; - - count = e1000_tx_map(adapter, tx_ring, skb, first, max_per_txd, - nr_frags, mss); - - if (count) { - netdev_sent_queue(netdev, skb->len); - skb_tx_timestamp(skb); - - e1000_tx_queue(adapter, tx_ring, tx_flags, count); - /* Make sure there is space in the ring for the next send. */ - e1000_maybe_stop_tx(netdev, tx_ring, MAX_SKB_FRAGS + 2); - - if (!skb->xmit_more || - netif_xmit_stopped(netdev_get_tx_queue(netdev, 0))) { - writel(tx_ring->next_to_use, hw->hw_addr + tx_ring->tdt); - /* we need this if more than one processor can write to - * our tail at a time, it synchronizes IO on IA64/Altix - * systems - */ - mmiowb(); - } - } else { - dev_kfree_skb_any(skb); - tx_ring->buffer_info[first].time_stamp = 0; - tx_ring->next_to_use = first; - } - - return NETDEV_TX_OK; -} - -#define NUM_REGS 38 /* 1 based count */ -static void e1000_regdump(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 regs[NUM_REGS]; - u32 *regs_buff = regs; - int i = 0; - - static const char * const reg_name[] = { - "CTRL", "STATUS", - "RCTL", "RDLEN", "RDH", "RDT", "RDTR", - "TCTL", "TDBAL", "TDBAH", "TDLEN", "TDH", "TDT", - "TIDV", "TXDCTL", "TADV", "TARC0", - "TDBAL1", "TDBAH1", "TDLEN1", "TDH1", "TDT1", - "TXDCTL1", "TARC1", - "CTRL_EXT", "ERT", "RDBAL", "RDBAH", - "TDFH", "TDFT", "TDFHS", "TDFTS", "TDFPC", - "RDFH", "RDFT", "RDFHS", "RDFTS", "RDFPC" - }; - - regs_buff[0] = er32(CTRL); - regs_buff[1] = er32(STATUS); - - regs_buff[2] = er32(RCTL); - regs_buff[3] = er32(RDLEN); - regs_buff[4] = er32(RDH); - regs_buff[5] = er32(RDT); - regs_buff[6] = er32(RDTR); - - regs_buff[7] = er32(TCTL); - regs_buff[8] = er32(TDBAL); - regs_buff[9] = er32(TDBAH); - regs_buff[10] = er32(TDLEN); - regs_buff[11] = er32(TDH); - regs_buff[12] = er32(TDT); - regs_buff[13] = er32(TIDV); - regs_buff[14] = er32(TXDCTL); - regs_buff[15] = er32(TADV); - regs_buff[16] = er32(TARC0); - - regs_buff[17] = er32(TDBAL1); - regs_buff[18] = er32(TDBAH1); - regs_buff[19] = er32(TDLEN1); - regs_buff[20] = er32(TDH1); - regs_buff[21] = er32(TDT1); - regs_buff[22] = er32(TXDCTL1); - regs_buff[23] = er32(TARC1); - regs_buff[24] = er32(CTRL_EXT); - regs_buff[25] = er32(ERT); - regs_buff[26] = er32(RDBAL0); - regs_buff[27] = er32(RDBAH0); - regs_buff[28] = er32(TDFH); - regs_buff[29] = er32(TDFT); - regs_buff[30] = er32(TDFHS); - regs_buff[31] = er32(TDFTS); - regs_buff[32] = er32(TDFPC); - regs_buff[33] = er32(RDFH); - regs_buff[34] = er32(RDFT); - regs_buff[35] = er32(RDFHS); - regs_buff[36] = er32(RDFTS); - regs_buff[37] = er32(RDFPC); - - pr_info("Register dump\n"); - for (i = 0; i < NUM_REGS; i++) - pr_info("%-15s %08x\n", reg_name[i], regs_buff[i]); -} - -/* - * e1000_dump: Print registers, tx ring and rx ring - */ -static void e1000_dump(struct e1000_adapter *adapter) -{ - /* this code doesn't handle multiple rings */ - struct e1000_tx_ring *tx_ring = adapter->tx_ring; - struct e1000_rx_ring *rx_ring = adapter->rx_ring; - int i; - - if (!netif_msg_hw(adapter)) - return; - - /* Print Registers */ - e1000_regdump(adapter); - - /* transmit dump */ - pr_info("TX Desc ring0 dump\n"); - - /* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended) - * - * Legacy Transmit Descriptor - * +--------------------------------------------------------------+ - * 0 | Buffer Address [63:0] (Reserved on Write Back) | - * +--------------------------------------------------------------+ - * 8 | Special | CSS | Status | CMD | CSO | Length | - * +--------------------------------------------------------------+ - * 63 48 47 36 35 32 31 24 23 16 15 0 - * - * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload - * 63 48 47 40 39 32 31 16 15 8 7 0 - * +----------------------------------------------------------------+ - * 0 | TUCSE | TUCS0 | TUCSS | IPCSE | IPCS0 | IPCSS | - * +----------------------------------------------------------------+ - * 8 | MSS | HDRLEN | RSV | STA | TUCMD | DTYP | PAYLEN | - * +----------------------------------------------------------------+ - * 63 48 47 40 39 36 35 32 31 24 23 20 19 0 - * - * Extended Data Descriptor (DTYP=0x1) - * +----------------------------------------------------------------+ - * 0 | Buffer Address [63:0] | - * +----------------------------------------------------------------+ - * 8 | VLAN tag | POPTS | Rsvd | Status | Command | DTYP | DTALEN | - * +----------------------------------------------------------------+ - * 63 48 47 40 39 36 35 32 31 24 23 20 19 0 - */ - pr_info("Tc[desc] [Ce CoCsIpceCoS] [MssHlRSCm0Plen] [bi->dma ] leng ntw timestmp bi->skb\n"); - pr_info("Td[desc] [address 63:0 ] [VlaPoRSCm1Dlen] [bi->dma ] leng ntw timestmp bi->skb\n"); - - if (!netif_msg_tx_done(adapter)) - goto rx_ring_summary; - - for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { - struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i); - struct e1000_tx_buffer *buffer_info = &tx_ring->buffer_info[i]; - struct my_u { __le64 a; __le64 b; }; - struct my_u *u = (struct my_u *)tx_desc; - const char *type; - - if (i == tx_ring->next_to_use && i == tx_ring->next_to_clean) - type = "NTC/U"; - else if (i == tx_ring->next_to_use) - type = "NTU"; - else if (i == tx_ring->next_to_clean) - type = "NTC"; - else - type = ""; - - pr_info("T%c[0x%03X] %016llX %016llX %016llX %04X %3X %016llX %p %s\n", - ((le64_to_cpu(u->b) & (1<<20)) ? 'd' : 'c'), i, - le64_to_cpu(u->a), le64_to_cpu(u->b), - (u64)buffer_info->dma, buffer_info->length, - buffer_info->next_to_watch, - (u64)buffer_info->time_stamp, buffer_info->skb, type); - } - -rx_ring_summary: - /* receive dump */ - pr_info("\nRX Desc ring dump\n"); - - /* Legacy Receive Descriptor Format - * - * +-----------------------------------------------------+ - * | Buffer Address [63:0] | - * +-----------------------------------------------------+ - * | VLAN Tag | Errors | Status 0 | Packet csum | Length | - * +-----------------------------------------------------+ - * 63 48 47 40 39 32 31 16 15 0 - */ - pr_info("R[desc] [address 63:0 ] [vl er S cks ln] [bi->dma ] [bi->skb]\n"); - - if (!netif_msg_rx_status(adapter)) - goto exit; - - for (i = 0; rx_ring->desc && (i < rx_ring->count); i++) { - struct e1000_rx_desc *rx_desc = E1000_RX_DESC(*rx_ring, i); - struct e1000_rx_buffer *buffer_info = &rx_ring->buffer_info[i]; - struct my_u { __le64 a; __le64 b; }; - struct my_u *u = (struct my_u *)rx_desc; - const char *type; - - if (i == rx_ring->next_to_use) - type = "NTU"; - else if (i == rx_ring->next_to_clean) - type = "NTC"; - else - type = ""; - - pr_info("R[0x%03X] %016llX %016llX %016llX %p %s\n", - i, le64_to_cpu(u->a), le64_to_cpu(u->b), - (u64)buffer_info->dma, buffer_info->rxbuf.data, type); - } /* for */ - - /* dump the descriptor caches */ - /* rx */ - pr_info("Rx descriptor cache in 64bit format\n"); - for (i = 0x6000; i <= 0x63FF ; i += 0x10) { - pr_info("R%04X: %08X|%08X %08X|%08X\n", - i, - readl(adapter->hw.hw_addr + i+4), - readl(adapter->hw.hw_addr + i), - readl(adapter->hw.hw_addr + i+12), - readl(adapter->hw.hw_addr + i+8)); - } - /* tx */ - pr_info("Tx descriptor cache in 64bit format\n"); - for (i = 0x7000; i <= 0x73FF ; i += 0x10) { - pr_info("T%04X: %08X|%08X %08X|%08X\n", - i, - readl(adapter->hw.hw_addr + i+4), - readl(adapter->hw.hw_addr + i), - readl(adapter->hw.hw_addr + i+12), - readl(adapter->hw.hw_addr + i+8)); - } -exit: - return; -} - -/** - * e1000_tx_timeout - Respond to a Tx Hang - * @netdev: network interface device structure - **/ -static void e1000_tx_timeout(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - /* Do the reset outside of interrupt context */ - adapter->tx_timeout_count++; - schedule_work(&adapter->reset_task); -} - -static void e1000_reset_task(struct work_struct *work) -{ - struct e1000_adapter *adapter = - container_of(work, struct e1000_adapter, reset_task); - - e_err(drv, "Reset adapter\n"); - e1000_reinit_locked(adapter); -} - -/** - * e1000_get_stats - Get System Network Statistics - * @netdev: network interface device structure - * - * Returns the address of the device statistics structure. - * The statistics are actually updated from the watchdog. - **/ -static struct net_device_stats *e1000_get_stats(struct net_device *netdev) -{ - /* only return the current stats */ - return &netdev->stats; -} - -/** - * e1000_change_mtu - Change the Maximum Transfer Unit - * @netdev: network interface device structure - * @new_mtu: new value for maximum frame size - * - * Returns 0 on success, negative on failure - **/ -static int e1000_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - int max_frame = new_mtu + ENET_HEADER_SIZE + ETHERNET_FCS_SIZE; - - if ((max_frame < MINIMUM_ETHERNET_FRAME_SIZE) || - (max_frame > MAX_JUMBO_FRAME_SIZE)) { - e_err(probe, "Invalid MTU setting\n"); - return -EINVAL; - } - - /* Adapter-specific max frame size limits. */ - switch (hw->mac_type) { - case e1000_undefined ... e1000_82542_rev2_1: - if (max_frame > (ETH_FRAME_LEN + ETH_FCS_LEN)) { - e_err(probe, "Jumbo Frames not supported.\n"); - return -EINVAL; - } - break; - default: - /* Capable of supporting up to MAX_JUMBO_FRAME_SIZE limit. */ - break; - } - - while (test_and_set_bit(__E1000_RESETTING, &adapter->flags)) - msleep(1); - /* e1000_down has a dependency on max_frame_size */ - hw->max_frame_size = max_frame; - if (netif_running(netdev)) { - /* prevent buffers from being reallocated */ - adapter->alloc_rx_buf = e1000_alloc_dummy_rx_buffers; - e1000_down(adapter); - } - - /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN - * means we reserve 2 more, this pushes us to allocate from the next - * larger slab size. - * i.e. RXBUFFER_2048 --> size-4096 slab - * however with the new *_jumbo_rx* routines, jumbo receives will use - * fragmented skbs - */ - - if (max_frame <= E1000_RXBUFFER_2048) - adapter->rx_buffer_len = E1000_RXBUFFER_2048; - else -#if (PAGE_SIZE >= E1000_RXBUFFER_16384) - adapter->rx_buffer_len = E1000_RXBUFFER_16384; -#elif (PAGE_SIZE >= E1000_RXBUFFER_4096) - adapter->rx_buffer_len = PAGE_SIZE; -#endif - - /* adjust allocation if LPE protects us, and we aren't using SBP */ - if (!hw->tbi_compatibility_on && - ((max_frame == (ETH_FRAME_LEN + ETH_FCS_LEN)) || - (max_frame == MAXIMUM_ETHERNET_VLAN_SIZE))) - adapter->rx_buffer_len = MAXIMUM_ETHERNET_VLAN_SIZE; - - pr_info("%s changing MTU from %d to %d\n", - netdev->name, netdev->mtu, new_mtu); - netdev->mtu = new_mtu; - - if (netif_running(netdev)) - e1000_up(adapter); - else - e1000_reset(adapter); - - clear_bit(__E1000_RESETTING, &adapter->flags); - - return 0; -} - -/** - * e1000_update_stats - Update the board statistics counters - * @adapter: board private structure - **/ -void e1000_update_stats(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - struct pci_dev *pdev = adapter->pdev; - unsigned long flags; - u16 phy_tmp; - -#define PHY_IDLE_ERROR_COUNT_MASK 0x00FF - - /* Prevent stats update while adapter is being reset, or if the pci - * connection is down. - */ - if (adapter->link_speed == 0) - return; - if (pci_channel_offline(pdev)) - return; - - spin_lock_irqsave(&adapter->stats_lock, flags); - - /* these counters are modified from e1000_tbi_adjust_stats, - * called from the interrupt context, so they must only - * be written while holding adapter->stats_lock - */ - - adapter->stats.crcerrs += er32(CRCERRS); - adapter->stats.gprc += er32(GPRC); - adapter->stats.gorcl += er32(GORCL); - adapter->stats.gorch += er32(GORCH); - adapter->stats.bprc += er32(BPRC); - adapter->stats.mprc += er32(MPRC); - adapter->stats.roc += er32(ROC); - - adapter->stats.prc64 += er32(PRC64); - adapter->stats.prc127 += er32(PRC127); - adapter->stats.prc255 += er32(PRC255); - adapter->stats.prc511 += er32(PRC511); - adapter->stats.prc1023 += er32(PRC1023); - adapter->stats.prc1522 += er32(PRC1522); - - adapter->stats.symerrs += er32(SYMERRS); - adapter->stats.mpc += er32(MPC); - adapter->stats.scc += er32(SCC); - adapter->stats.ecol += er32(ECOL); - adapter->stats.mcc += er32(MCC); - adapter->stats.latecol += er32(LATECOL); - adapter->stats.dc += er32(DC); - adapter->stats.sec += er32(SEC); - adapter->stats.rlec += er32(RLEC); - adapter->stats.xonrxc += er32(XONRXC); - adapter->stats.xontxc += er32(XONTXC); - adapter->stats.xoffrxc += er32(XOFFRXC); - adapter->stats.xofftxc += er32(XOFFTXC); - adapter->stats.fcruc += er32(FCRUC); - adapter->stats.gptc += er32(GPTC); - adapter->stats.gotcl += er32(GOTCL); - adapter->stats.gotch += er32(GOTCH); - adapter->stats.rnbc += er32(RNBC); - adapter->stats.ruc += er32(RUC); - adapter->stats.rfc += er32(RFC); - adapter->stats.rjc += er32(RJC); - adapter->stats.torl += er32(TORL); - adapter->stats.torh += er32(TORH); - adapter->stats.totl += er32(TOTL); - adapter->stats.toth += er32(TOTH); - adapter->stats.tpr += er32(TPR); - - adapter->stats.ptc64 += er32(PTC64); - adapter->stats.ptc127 += er32(PTC127); - adapter->stats.ptc255 += er32(PTC255); - adapter->stats.ptc511 += er32(PTC511); - adapter->stats.ptc1023 += er32(PTC1023); - adapter->stats.ptc1522 += er32(PTC1522); - - adapter->stats.mptc += er32(MPTC); - adapter->stats.bptc += er32(BPTC); - - /* used for adaptive IFS */ - - hw->tx_packet_delta = er32(TPT); - adapter->stats.tpt += hw->tx_packet_delta; - hw->collision_delta = er32(COLC); - adapter->stats.colc += hw->collision_delta; - - if (hw->mac_type >= e1000_82543) { - adapter->stats.algnerrc += er32(ALGNERRC); - adapter->stats.rxerrc += er32(RXERRC); - adapter->stats.tncrs += er32(TNCRS); - adapter->stats.cexterr += er32(CEXTERR); - adapter->stats.tsctc += er32(TSCTC); - adapter->stats.tsctfc += er32(TSCTFC); - } - - /* Fill out the OS statistics structure */ - netdev->stats.multicast = adapter->stats.mprc; - netdev->stats.collisions = adapter->stats.colc; - - /* Rx Errors */ - - /* RLEC on some newer hardware can be incorrect so build - * our own version based on RUC and ROC - */ - netdev->stats.rx_errors = adapter->stats.rxerrc + - adapter->stats.crcerrs + adapter->stats.algnerrc + - adapter->stats.ruc + adapter->stats.roc + - adapter->stats.cexterr; - adapter->stats.rlerrc = adapter->stats.ruc + adapter->stats.roc; - netdev->stats.rx_length_errors = adapter->stats.rlerrc; - netdev->stats.rx_crc_errors = adapter->stats.crcerrs; - netdev->stats.rx_frame_errors = adapter->stats.algnerrc; - netdev->stats.rx_missed_errors = adapter->stats.mpc; - - /* Tx Errors */ - adapter->stats.txerrc = adapter->stats.ecol + adapter->stats.latecol; - netdev->stats.tx_errors = adapter->stats.txerrc; - netdev->stats.tx_aborted_errors = adapter->stats.ecol; - netdev->stats.tx_window_errors = adapter->stats.latecol; - netdev->stats.tx_carrier_errors = adapter->stats.tncrs; - if (hw->bad_tx_carr_stats_fd && - adapter->link_duplex == FULL_DUPLEX) { - netdev->stats.tx_carrier_errors = 0; - adapter->stats.tncrs = 0; - } - - /* Tx Dropped needs to be maintained elsewhere */ - - /* Phy Stats */ - if (hw->media_type == e1000_media_type_copper) { - if ((adapter->link_speed == SPEED_1000) && - (!e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_tmp))) { - phy_tmp &= PHY_IDLE_ERROR_COUNT_MASK; - adapter->phy_stats.idle_errors += phy_tmp; - } - - if ((hw->mac_type <= e1000_82546) && - (hw->phy_type == e1000_phy_m88) && - !e1000_read_phy_reg(hw, M88E1000_RX_ERR_CNTR, &phy_tmp)) - adapter->phy_stats.receive_errors += phy_tmp; - } - - /* Management Stats */ - if (hw->has_smbus) { - adapter->stats.mgptc += er32(MGTPTC); - adapter->stats.mgprc += er32(MGTPRC); - adapter->stats.mgpdc += er32(MGTPDC); - } - - spin_unlock_irqrestore(&adapter->stats_lock, flags); -} - -/** - * e1000_intr - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - **/ -static irqreturn_t e1000_intr(int irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 icr = er32(ICR); - - if (unlikely((!icr))) - return IRQ_NONE; /* Not our interrupt */ - - /* we might have caused the interrupt, but the above - * read cleared it, and just in case the driver is - * down there is nothing to do so return handled - */ - if (unlikely(test_bit(__E1000_DOWN, &adapter->flags))) - return IRQ_HANDLED; - - if (unlikely(icr & (E1000_ICR_RXSEQ | E1000_ICR_LSC))) { - hw->get_link_status = 1; - /* guard against interrupt when we're going down */ - if (!test_bit(__E1000_DOWN, &adapter->flags)) - schedule_delayed_work(&adapter->watchdog_task, 1); - } - - /* disable interrupts, without the synchronize_irq bit */ - ew32(IMC, ~0); - E1000_WRITE_FLUSH(); - - if (likely(napi_schedule_prep(&adapter->napi))) { - adapter->total_tx_bytes = 0; - adapter->total_tx_packets = 0; - adapter->total_rx_bytes = 0; - adapter->total_rx_packets = 0; - __napi_schedule(&adapter->napi); - } else { - /* this really should not happen! if it does it is basically a - * bug, but not a hard error, so enable ints and continue - */ - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_enable(adapter); - } - - return IRQ_HANDLED; -} - -/** - * e1000_clean - NAPI Rx polling callback - * @adapter: board private structure - **/ -static int e1000_clean(struct napi_struct *napi, int budget) -{ - struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, - napi); - int tx_clean_complete = 0, work_done = 0; - - tx_clean_complete = e1000_clean_tx_irq(adapter, &adapter->tx_ring[0]); - - adapter->clean_rx(adapter, &adapter->rx_ring[0], &work_done, budget); - - if (!tx_clean_complete) - work_done = budget; - - /* If budget not fully consumed, exit the polling mode */ - if (work_done < budget) { - if (likely(adapter->itr_setting & 3)) - e1000_set_itr(adapter); - napi_complete_done(napi, work_done); - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_enable(adapter); - } - - return work_done; -} - -/** - * e1000_clean_tx_irq - Reclaim resources after transmit completes - * @adapter: board private structure - **/ -static bool e1000_clean_tx_irq(struct e1000_adapter *adapter, - struct e1000_tx_ring *tx_ring) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - struct e1000_tx_desc *tx_desc, *eop_desc; - struct e1000_tx_buffer *buffer_info; - unsigned int i, eop; - unsigned int count = 0; - unsigned int total_tx_bytes=0, total_tx_packets=0; - unsigned int bytes_compl = 0, pkts_compl = 0; - - i = tx_ring->next_to_clean; - eop = tx_ring->buffer_info[i].next_to_watch; - eop_desc = E1000_TX_DESC(*tx_ring, eop); - - while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && - (count < tx_ring->count)) { - bool cleaned = false; - dma_rmb(); /* read buffer_info after eop_desc */ - for ( ; !cleaned; count++) { - tx_desc = E1000_TX_DESC(*tx_ring, i); - buffer_info = &tx_ring->buffer_info[i]; - cleaned = (i == eop); - - if (cleaned) { - total_tx_packets += buffer_info->segs; - total_tx_bytes += buffer_info->bytecount; - if (buffer_info->skb) { - bytes_compl += buffer_info->skb->len; - pkts_compl++; - } - - } - e1000_unmap_and_free_tx_resource(adapter, buffer_info); - tx_desc->upper.data = 0; - - if (unlikely(++i == tx_ring->count)) i = 0; - } - - eop = tx_ring->buffer_info[i].next_to_watch; - eop_desc = E1000_TX_DESC(*tx_ring, eop); - } - - /* Synchronize with E1000_DESC_UNUSED called from e1000_xmit_frame, - * which will reuse the cleaned buffers. - */ - smp_store_release(&tx_ring->next_to_clean, i); - - netdev_completed_queue(netdev, pkts_compl, bytes_compl); - -#define TX_WAKE_THRESHOLD 32 - if (unlikely(count && netif_carrier_ok(netdev) && - E1000_DESC_UNUSED(tx_ring) >= TX_WAKE_THRESHOLD)) { - /* Make sure that anybody stopping the queue after this - * sees the new next_to_clean. - */ - smp_mb(); - - if (netif_queue_stopped(netdev) && - !(test_bit(__E1000_DOWN, &adapter->flags))) { - netif_wake_queue(netdev); - ++adapter->restart_queue; - } - } - - if (adapter->detect_tx_hung) { - /* Detect a transmit hang in hardware, this serializes the - * check with the clearing of time_stamp and movement of i - */ - adapter->detect_tx_hung = false; - if (tx_ring->buffer_info[eop].time_stamp && - time_after(jiffies, tx_ring->buffer_info[eop].time_stamp + - (adapter->tx_timeout_factor * HZ)) && - !(er32(STATUS) & E1000_STATUS_TXOFF)) { - - /* detected Tx unit hang */ - e_err(drv, "Detected Tx Unit Hang\n" - " Tx Queue <%lu>\n" - " TDH <%x>\n" - " TDT <%x>\n" - " next_to_use <%x>\n" - " next_to_clean <%x>\n" - "buffer_info[next_to_clean]\n" - " time_stamp <%lx>\n" - " next_to_watch <%x>\n" - " jiffies <%lx>\n" - " next_to_watch.status <%x>\n", - (unsigned long)(tx_ring - adapter->tx_ring), - readl(hw->hw_addr + tx_ring->tdh), - readl(hw->hw_addr + tx_ring->tdt), - tx_ring->next_to_use, - tx_ring->next_to_clean, - tx_ring->buffer_info[eop].time_stamp, - eop, - jiffies, - eop_desc->upper.fields.status); - e1000_dump(adapter); - netif_stop_queue(netdev); - } - } - adapter->total_tx_bytes += total_tx_bytes; - adapter->total_tx_packets += total_tx_packets; - netdev->stats.tx_bytes += total_tx_bytes; - netdev->stats.tx_packets += total_tx_packets; - return count < tx_ring->count; -} - -/** - * e1000_rx_checksum - Receive Checksum Offload for 82543 - * @adapter: board private structure - * @status_err: receive descriptor status and error fields - * @csum: receive descriptor csum field - * @sk_buff: socket buffer with received data - **/ -static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, - u32 csum, struct sk_buff *skb) -{ - struct e1000_hw *hw = &adapter->hw; - u16 status = (u16)status_err; - u8 errors = (u8)(status_err >> 24); - - skb_checksum_none_assert(skb); - - /* 82543 or newer only */ - if (unlikely(hw->mac_type < e1000_82543)) return; - /* Ignore Checksum bit is set */ - if (unlikely(status & E1000_RXD_STAT_IXSM)) return; - /* TCP/UDP checksum error bit is set */ - if (unlikely(errors & E1000_RXD_ERR_TCPE)) { - /* let the stack verify checksum errors */ - adapter->hw_csum_err++; - return; - } - /* TCP/UDP Checksum has not been calculated */ - if (!(status & E1000_RXD_STAT_TCPCS)) - return; - - /* It must be a TCP or UDP packet with a valid checksum */ - if (likely(status & E1000_RXD_STAT_TCPCS)) { - /* TCP checksum is good */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - } - adapter->hw_csum_good++; -} - -/** - * e1000_consume_page - helper function for jumbo Rx path - **/ -static void e1000_consume_page(struct e1000_rx_buffer *bi, struct sk_buff *skb, - u16 length) -{ - bi->rxbuf.page = NULL; - skb->len += length; - skb->data_len += length; - skb->truesize += PAGE_SIZE; -} - -/** - * e1000_receive_skb - helper function to handle rx indications - * @adapter: board private structure - * @status: descriptor status field as written by hardware - * @vlan: descriptor vlan field as written by hardware (no le/be conversion) - * @skb: pointer to sk_buff to be indicated to stack - */ -static void e1000_receive_skb(struct e1000_adapter *adapter, u8 status, - __le16 vlan, struct sk_buff *skb) -{ - skb->protocol = eth_type_trans(skb, adapter->netdev); - - if (status & E1000_RXD_STAT_VP) { - u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; - - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); - } - napi_gro_receive(&adapter->napi, skb); -} - -/** - * e1000_tbi_adjust_stats - * @hw: Struct containing variables accessed by shared code - * @frame_len: The length of the frame in question - * @mac_addr: The Ethernet destination address of the frame in question - * - * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT - */ -static void e1000_tbi_adjust_stats(struct e1000_hw *hw, - struct e1000_hw_stats *stats, - u32 frame_len, const u8 *mac_addr) -{ - u64 carry_bit; - - /* First adjust the frame length. */ - frame_len--; - /* We need to adjust the statistics counters, since the hardware - * counters overcount this packet as a CRC error and undercount - * the packet as a good packet - */ - /* This packet should not be counted as a CRC error. */ - stats->crcerrs--; - /* This packet does count as a Good Packet Received. */ - stats->gprc++; - - /* Adjust the Good Octets received counters */ - carry_bit = 0x80000000 & stats->gorcl; - stats->gorcl += frame_len; - /* If the high bit of Gorcl (the low 32 bits of the Good Octets - * Received Count) was one before the addition, - * AND it is zero after, then we lost the carry out, - * need to add one to Gorch (Good Octets Received Count High). - * This could be simplified if all environments supported - * 64-bit integers. - */ - if (carry_bit && ((stats->gorcl & 0x80000000) == 0)) - stats->gorch++; - /* Is this a broadcast or multicast? Check broadcast first, - * since the test for a multicast frame will test positive on - * a broadcast frame. - */ - if (is_broadcast_ether_addr(mac_addr)) - stats->bprc++; - else if (is_multicast_ether_addr(mac_addr)) - stats->mprc++; - - if (frame_len == hw->max_frame_size) { - /* In this case, the hardware has overcounted the number of - * oversize frames. - */ - if (stats->roc > 0) - stats->roc--; - } - - /* Adjust the bin counters when the extra byte put the frame in the - * wrong bin. Remember that the frame_len was adjusted above. - */ - if (frame_len == 64) { - stats->prc64++; - stats->prc127--; - } else if (frame_len == 127) { - stats->prc127++; - stats->prc255--; - } else if (frame_len == 255) { - stats->prc255++; - stats->prc511--; - } else if (frame_len == 511) { - stats->prc511++; - stats->prc1023--; - } else if (frame_len == 1023) { - stats->prc1023++; - stats->prc1522--; - } else if (frame_len == 1522) { - stats->prc1522++; - } -} - -static bool e1000_tbi_should_accept(struct e1000_adapter *adapter, - u8 status, u8 errors, - u32 length, const u8 *data) -{ - struct e1000_hw *hw = &adapter->hw; - u8 last_byte = *(data + length - 1); - - if (TBI_ACCEPT(hw, status, errors, length, last_byte)) { - unsigned long irq_flags; - - spin_lock_irqsave(&adapter->stats_lock, irq_flags); - e1000_tbi_adjust_stats(hw, &adapter->stats, length, data); - spin_unlock_irqrestore(&adapter->stats_lock, irq_flags); - - return true; - } - - return false; -} - -static struct sk_buff *e1000_alloc_rx_skb(struct e1000_adapter *adapter, - unsigned int bufsz) -{ - struct sk_buff *skb = napi_alloc_skb(&adapter->napi, bufsz); - - if (unlikely(!skb)) - adapter->alloc_rx_buff_failed++; - return skb; -} - -/** - * e1000_clean_jumbo_rx_irq - Send received data up the network stack; legacy - * @adapter: board private structure - * @rx_ring: ring to clean - * @work_done: amount of napi work completed this call - * @work_to_do: max amount of work allowed for this call to do - * - * the return value indicates whether actual cleaning was done, there - * is no guarantee that everything was cleaned - */ -static bool e1000_clean_jumbo_rx_irq(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int *work_done, int work_to_do) -{ - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_rx_desc *rx_desc, *next_rxd; - struct e1000_rx_buffer *buffer_info, *next_buffer; - u32 length; - unsigned int i; - int cleaned_count = 0; - bool cleaned = false; - unsigned int total_rx_bytes=0, total_rx_packets=0; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC(*rx_ring, i); - buffer_info = &rx_ring->buffer_info[i]; - - while (rx_desc->status & E1000_RXD_STAT_DD) { - struct sk_buff *skb; - u8 status; - - if (*work_done >= work_to_do) - break; - (*work_done)++; - dma_rmb(); /* read descriptor and rx_buffer_info after status DD */ - - status = rx_desc->status; - - if (++i == rx_ring->count) i = 0; - next_rxd = E1000_RX_DESC(*rx_ring, i); - prefetch(next_rxd); - - next_buffer = &rx_ring->buffer_info[i]; - - cleaned = true; - cleaned_count++; - dma_unmap_page(&pdev->dev, buffer_info->dma, - adapter->rx_buffer_len, DMA_FROM_DEVICE); - buffer_info->dma = 0; - - length = le16_to_cpu(rx_desc->length); - - /* errors is only valid for DD + EOP descriptors */ - if (unlikely((status & E1000_RXD_STAT_EOP) && - (rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK))) { - u8 *mapped = page_address(buffer_info->rxbuf.page); - - if (e1000_tbi_should_accept(adapter, status, - rx_desc->errors, - length, mapped)) { - length--; - } else if (netdev->features & NETIF_F_RXALL) { - goto process_skb; - } else { - /* an error means any chain goes out the window - * too - */ - if (rx_ring->rx_skb_top) - dev_kfree_skb(rx_ring->rx_skb_top); - rx_ring->rx_skb_top = NULL; - goto next_desc; - } - } - -#define rxtop rx_ring->rx_skb_top -process_skb: - if (!(status & E1000_RXD_STAT_EOP)) { - /* this descriptor is only the beginning (or middle) */ - if (!rxtop) { - /* this is the beginning of a chain */ - rxtop = napi_get_frags(&adapter->napi); - if (!rxtop) - break; - - skb_fill_page_desc(rxtop, 0, - buffer_info->rxbuf.page, - 0, length); - } else { - /* this is the middle of a chain */ - skb_fill_page_desc(rxtop, - skb_shinfo(rxtop)->nr_frags, - buffer_info->rxbuf.page, 0, length); - } - e1000_consume_page(buffer_info, rxtop, length); - goto next_desc; - } else { - if (rxtop) { - /* end of the chain */ - skb_fill_page_desc(rxtop, - skb_shinfo(rxtop)->nr_frags, - buffer_info->rxbuf.page, 0, length); - skb = rxtop; - rxtop = NULL; - e1000_consume_page(buffer_info, skb, length); - } else { - struct page *p; - /* no chain, got EOP, this buf is the packet - * copybreak to save the put_page/alloc_page - */ - p = buffer_info->rxbuf.page; - if (length <= copybreak) { - u8 *vaddr; - - if (likely(!(netdev->features & NETIF_F_RXFCS))) - length -= 4; - skb = e1000_alloc_rx_skb(adapter, - length); - if (!skb) - break; - - vaddr = kmap_atomic(p); - memcpy(skb_tail_pointer(skb), vaddr, - length); - kunmap_atomic(vaddr); - /* re-use the page, so don't erase - * buffer_info->rxbuf.page - */ - skb_put(skb, length); - e1000_rx_checksum(adapter, - status | rx_desc->errors << 24, - le16_to_cpu(rx_desc->csum), skb); - - total_rx_bytes += skb->len; - total_rx_packets++; - - e1000_receive_skb(adapter, status, - rx_desc->special, skb); - goto next_desc; - } else { - skb = napi_get_frags(&adapter->napi); - if (!skb) { - adapter->alloc_rx_buff_failed++; - break; - } - skb_fill_page_desc(skb, 0, p, 0, - length); - e1000_consume_page(buffer_info, skb, - length); - } - } - } - - /* Receive Checksum Offload XXX recompute due to CRC strip? */ - e1000_rx_checksum(adapter, - (u32)(status) | - ((u32)(rx_desc->errors) << 24), - le16_to_cpu(rx_desc->csum), skb); - - total_rx_bytes += (skb->len - 4); /* don't count FCS */ - if (likely(!(netdev->features & NETIF_F_RXFCS))) - pskb_trim(skb, skb->len - 4); - total_rx_packets++; - - if (status & E1000_RXD_STAT_VP) { - __le16 vlan = rx_desc->special; - u16 vid = le16_to_cpu(vlan) & E1000_RXD_SPC_VLAN_MASK; - - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), vid); - } - - napi_gro_frags(&adapter->napi); - -next_desc: - rx_desc->status = 0; - - /* return some buffers to hardware, one at a time is too slow */ - if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { - adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); - cleaned_count = 0; - } - - /* use prefetched values */ - rx_desc = next_rxd; - buffer_info = next_buffer; - } - rx_ring->next_to_clean = i; - - cleaned_count = E1000_DESC_UNUSED(rx_ring); - if (cleaned_count) - adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); - - adapter->total_rx_packets += total_rx_packets; - adapter->total_rx_bytes += total_rx_bytes; - netdev->stats.rx_bytes += total_rx_bytes; - netdev->stats.rx_packets += total_rx_packets; - return cleaned; -} - -/* this should improve performance for small packets with large amounts - * of reassembly being done in the stack - */ -static struct sk_buff *e1000_copybreak(struct e1000_adapter *adapter, - struct e1000_rx_buffer *buffer_info, - u32 length, const void *data) -{ - struct sk_buff *skb; - - if (length > copybreak) - return NULL; - - skb = e1000_alloc_rx_skb(adapter, length); - if (!skb) - return NULL; - - dma_sync_single_for_cpu(&adapter->pdev->dev, buffer_info->dma, - length, DMA_FROM_DEVICE); - - memcpy(skb_put(skb, length), data, length); - - return skb; -} - -/** - * e1000_clean_rx_irq - Send received data up the network stack; legacy - * @adapter: board private structure - * @rx_ring: ring to clean - * @work_done: amount of napi work completed this call - * @work_to_do: max amount of work allowed for this call to do - */ -static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int *work_done, int work_to_do) -{ - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_rx_desc *rx_desc, *next_rxd; - struct e1000_rx_buffer *buffer_info, *next_buffer; - u32 length; - unsigned int i; - int cleaned_count = 0; - bool cleaned = false; - unsigned int total_rx_bytes=0, total_rx_packets=0; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC(*rx_ring, i); - buffer_info = &rx_ring->buffer_info[i]; - - while (rx_desc->status & E1000_RXD_STAT_DD) { - struct sk_buff *skb; - u8 *data; - u8 status; - - if (*work_done >= work_to_do) - break; - (*work_done)++; - dma_rmb(); /* read descriptor and rx_buffer_info after status DD */ - - status = rx_desc->status; - length = le16_to_cpu(rx_desc->length); - - data = buffer_info->rxbuf.data; - prefetch(data); - skb = e1000_copybreak(adapter, buffer_info, length, data); - if (!skb) { - unsigned int frag_len = e1000_frag_len(adapter); - - skb = build_skb(data - E1000_HEADROOM, frag_len); - if (!skb) { - adapter->alloc_rx_buff_failed++; - break; - } - - skb_reserve(skb, E1000_HEADROOM); - dma_unmap_single(&pdev->dev, buffer_info->dma, - adapter->rx_buffer_len, - DMA_FROM_DEVICE); - buffer_info->dma = 0; - buffer_info->rxbuf.data = NULL; - } - - if (++i == rx_ring->count) i = 0; - next_rxd = E1000_RX_DESC(*rx_ring, i); - prefetch(next_rxd); - - next_buffer = &rx_ring->buffer_info[i]; - - cleaned = true; - cleaned_count++; - - /* !EOP means multiple descriptors were used to store a single - * packet, if thats the case we need to toss it. In fact, we - * to toss every packet with the EOP bit clear and the next - * frame that _does_ have the EOP bit set, as it is by - * definition only a frame fragment - */ - if (unlikely(!(status & E1000_RXD_STAT_EOP))) - adapter->discarding = true; - - if (adapter->discarding) { - /* All receives must fit into a single buffer */ - netdev_dbg(netdev, "Receive packet consumed multiple buffers\n"); - dev_kfree_skb(skb); - if (status & E1000_RXD_STAT_EOP) - adapter->discarding = false; - goto next_desc; - } - - if (unlikely(rx_desc->errors & E1000_RXD_ERR_FRAME_ERR_MASK)) { - if (e1000_tbi_should_accept(adapter, status, - rx_desc->errors, - length, data)) { - length--; - } else if (netdev->features & NETIF_F_RXALL) { - goto process_skb; - } else { - dev_kfree_skb(skb); - goto next_desc; - } - } - -process_skb: - total_rx_bytes += (length - 4); /* don't count FCS */ - total_rx_packets++; - - if (likely(!(netdev->features & NETIF_F_RXFCS))) - /* adjust length to remove Ethernet CRC, this must be - * done after the TBI_ACCEPT workaround above - */ - length -= 4; - - if (buffer_info->rxbuf.data == NULL) - skb_put(skb, length); - else /* copybreak skb */ - skb_trim(skb, length); - - /* Receive Checksum Offload */ - e1000_rx_checksum(adapter, - (u32)(status) | - ((u32)(rx_desc->errors) << 24), - le16_to_cpu(rx_desc->csum), skb); - - e1000_receive_skb(adapter, status, rx_desc->special, skb); - -next_desc: - rx_desc->status = 0; - - /* return some buffers to hardware, one at a time is too slow */ - if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { - adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); - cleaned_count = 0; - } - - /* use prefetched values */ - rx_desc = next_rxd; - buffer_info = next_buffer; - } - rx_ring->next_to_clean = i; - - cleaned_count = E1000_DESC_UNUSED(rx_ring); - if (cleaned_count) - adapter->alloc_rx_buf(adapter, rx_ring, cleaned_count); - - adapter->total_rx_packets += total_rx_packets; - adapter->total_rx_bytes += total_rx_bytes; - netdev->stats.rx_bytes += total_rx_bytes; - netdev->stats.rx_packets += total_rx_packets; - return cleaned; -} - -/** - * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers - * @adapter: address of board private structure - * @rx_ring: pointer to receive ring structure - * @cleaned_count: number of buffers to allocate this pass - **/ -static void -e1000_alloc_jumbo_rx_buffers(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, int cleaned_count) -{ - struct pci_dev *pdev = adapter->pdev; - struct e1000_rx_desc *rx_desc; - struct e1000_rx_buffer *buffer_info; - unsigned int i; - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - - while (cleaned_count--) { - /* allocate a new page if necessary */ - if (!buffer_info->rxbuf.page) { - buffer_info->rxbuf.page = alloc_page(GFP_ATOMIC); - if (unlikely(!buffer_info->rxbuf.page)) { - adapter->alloc_rx_buff_failed++; - break; - } - } - - if (!buffer_info->dma) { - buffer_info->dma = dma_map_page(&pdev->dev, - buffer_info->rxbuf.page, 0, - adapter->rx_buffer_len, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { - put_page(buffer_info->rxbuf.page); - buffer_info->rxbuf.page = NULL; - buffer_info->dma = 0; - adapter->alloc_rx_buff_failed++; - break; - } - } - - rx_desc = E1000_RX_DESC(*rx_ring, i); - rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - - if (unlikely(++i == rx_ring->count)) - i = 0; - buffer_info = &rx_ring->buffer_info[i]; - } - - if (likely(rx_ring->next_to_use != i)) { - rx_ring->next_to_use = i; - if (unlikely(i-- == 0)) - i = (rx_ring->count - 1); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - writel(i, adapter->hw.hw_addr + rx_ring->rdt); - } -} - -/** - * e1000_alloc_rx_buffers - Replace used receive buffers; legacy & extended - * @adapter: address of board private structure - **/ -static void e1000_alloc_rx_buffers(struct e1000_adapter *adapter, - struct e1000_rx_ring *rx_ring, - int cleaned_count) -{ - struct e1000_hw *hw = &adapter->hw; - struct pci_dev *pdev = adapter->pdev; - struct e1000_rx_desc *rx_desc; - struct e1000_rx_buffer *buffer_info; - unsigned int i; - unsigned int bufsz = adapter->rx_buffer_len; - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - - while (cleaned_count--) { - void *data; - - if (buffer_info->rxbuf.data) - goto skip; - - data = e1000_alloc_frag(adapter); - if (!data) { - /* Better luck next round */ - adapter->alloc_rx_buff_failed++; - break; - } - - /* Fix for errata 23, can't cross 64kB boundary */ - if (!e1000_check_64k_bound(adapter, data, bufsz)) { - void *olddata = data; - e_err(rx_err, "skb align check failed: %u bytes at " - "%p\n", bufsz, data); - /* Try again, without freeing the previous */ - data = e1000_alloc_frag(adapter); - /* Failed allocation, critical failure */ - if (!data) { - skb_free_frag(olddata); - adapter->alloc_rx_buff_failed++; - break; - } - - if (!e1000_check_64k_bound(adapter, data, bufsz)) { - /* give up */ - skb_free_frag(data); - skb_free_frag(olddata); - adapter->alloc_rx_buff_failed++; - break; - } - - /* Use new allocation */ - skb_free_frag(olddata); - } - buffer_info->dma = dma_map_single(&pdev->dev, - data, - adapter->rx_buffer_len, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { - skb_free_frag(data); - buffer_info->dma = 0; - adapter->alloc_rx_buff_failed++; - break; - } - - /* XXX if it was allocated cleanly it will never map to a - * boundary crossing - */ - - /* Fix for errata 23, can't cross 64kB boundary */ - if (!e1000_check_64k_bound(adapter, - (void *)(unsigned long)buffer_info->dma, - adapter->rx_buffer_len)) { - e_err(rx_err, "dma align check failed: %u bytes at " - "%p\n", adapter->rx_buffer_len, - (void *)(unsigned long)buffer_info->dma); - - dma_unmap_single(&pdev->dev, buffer_info->dma, - adapter->rx_buffer_len, - DMA_FROM_DEVICE); - - skb_free_frag(data); - buffer_info->rxbuf.data = NULL; - buffer_info->dma = 0; - - adapter->alloc_rx_buff_failed++; - break; - } - buffer_info->rxbuf.data = data; - skip: - rx_desc = E1000_RX_DESC(*rx_ring, i); - rx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - - if (unlikely(++i == rx_ring->count)) - i = 0; - buffer_info = &rx_ring->buffer_info[i]; - } - - if (likely(rx_ring->next_to_use != i)) { - rx_ring->next_to_use = i; - if (unlikely(i-- == 0)) - i = (rx_ring->count - 1); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - writel(i, hw->hw_addr + rx_ring->rdt); - } -} - -/** - * e1000_smartspeed - Workaround for SmartSpeed on 82541 and 82547 controllers. - * @adapter: - **/ -static void e1000_smartspeed(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u16 phy_status; - u16 phy_ctrl; - - if ((hw->phy_type != e1000_phy_igp) || !hw->autoneg || - !(hw->autoneg_advertised & ADVERTISE_1000_FULL)) - return; - - if (adapter->smartspeed == 0) { - /* If Master/Slave config fault is asserted twice, - * we assume back-to-back - */ - e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status); - if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return; - e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_status); - if (!(phy_status & SR_1000T_MS_CONFIG_FAULT)) return; - e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl); - if (phy_ctrl & CR_1000T_MS_ENABLE) { - phy_ctrl &= ~CR_1000T_MS_ENABLE; - e1000_write_phy_reg(hw, PHY_1000T_CTRL, - phy_ctrl); - adapter->smartspeed++; - if (!e1000_phy_setup_autoneg(hw) && - !e1000_read_phy_reg(hw, PHY_CTRL, - &phy_ctrl)) { - phy_ctrl |= (MII_CR_AUTO_NEG_EN | - MII_CR_RESTART_AUTO_NEG); - e1000_write_phy_reg(hw, PHY_CTRL, - phy_ctrl); - } - } - return; - } else if (adapter->smartspeed == E1000_SMARTSPEED_DOWNSHIFT) { - /* If still no link, perhaps using 2/3 pair cable */ - e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_ctrl); - phy_ctrl |= CR_1000T_MS_ENABLE; - e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_ctrl); - if (!e1000_phy_setup_autoneg(hw) && - !e1000_read_phy_reg(hw, PHY_CTRL, &phy_ctrl)) { - phy_ctrl |= (MII_CR_AUTO_NEG_EN | - MII_CR_RESTART_AUTO_NEG); - e1000_write_phy_reg(hw, PHY_CTRL, phy_ctrl); - } - } - /* Restart process after E1000_SMARTSPEED_MAX iterations */ - if (adapter->smartspeed++ == E1000_SMARTSPEED_MAX) - adapter->smartspeed = 0; -} - -/** - * e1000_ioctl - - * @netdev: - * @ifreq: - * @cmd: - **/ -static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return e1000_mii_ioctl(netdev, ifr, cmd); - default: - return -EOPNOTSUPP; - } -} - -/** - * e1000_mii_ioctl - - * @netdev: - * @ifreq: - * @cmd: - **/ -static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, - int cmd) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct mii_ioctl_data *data = if_mii(ifr); - int retval; - u16 mii_reg; - unsigned long flags; - - if (hw->media_type != e1000_media_type_copper) - return -EOPNOTSUPP; - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = hw->phy_addr; - break; - case SIOCGMIIREG: - spin_lock_irqsave(&adapter->stats_lock, flags); - if (e1000_read_phy_reg(hw, data->reg_num & 0x1F, - &data->val_out)) { - spin_unlock_irqrestore(&adapter->stats_lock, flags); - return -EIO; - } - spin_unlock_irqrestore(&adapter->stats_lock, flags); - break; - case SIOCSMIIREG: - if (data->reg_num & ~(0x1F)) - return -EFAULT; - mii_reg = data->val_in; - spin_lock_irqsave(&adapter->stats_lock, flags); - if (e1000_write_phy_reg(hw, data->reg_num, - mii_reg)) { - spin_unlock_irqrestore(&adapter->stats_lock, flags); - return -EIO; - } - spin_unlock_irqrestore(&adapter->stats_lock, flags); - if (hw->media_type == e1000_media_type_copper) { - switch (data->reg_num) { - case PHY_CTRL: - if (mii_reg & MII_CR_POWER_DOWN) - break; - if (mii_reg & MII_CR_AUTO_NEG_EN) { - hw->autoneg = 1; - hw->autoneg_advertised = 0x2F; - } else { - u32 speed; - if (mii_reg & 0x40) - speed = SPEED_1000; - else if (mii_reg & 0x2000) - speed = SPEED_100; - else - speed = SPEED_10; - retval = e1000_set_spd_dplx( - adapter, speed, - ((mii_reg & 0x100) - ? DUPLEX_FULL : - DUPLEX_HALF)); - if (retval) - return retval; - } - if (netif_running(adapter->netdev)) - e1000_reinit_locked(adapter); - else - e1000_reset(adapter); - break; - case M88E1000_PHY_SPEC_CTRL: - case M88E1000_EXT_PHY_SPEC_CTRL: - if (e1000_phy_reset(hw)) - return -EIO; - break; - } - } else { - switch (data->reg_num) { - case PHY_CTRL: - if (mii_reg & MII_CR_POWER_DOWN) - break; - if (netif_running(adapter->netdev)) - e1000_reinit_locked(adapter); - else - e1000_reset(adapter); - break; - } - } - break; - default: - return -EOPNOTSUPP; - } - return E1000_SUCCESS; -} - -void e1000_pci_set_mwi(struct e1000_hw *hw) -{ - struct e1000_adapter *adapter = hw->back; - int ret_val = pci_set_mwi(adapter->pdev); - - if (ret_val) - e_err(probe, "Error in setting MWI\n"); -} - -void e1000_pci_clear_mwi(struct e1000_hw *hw) -{ - struct e1000_adapter *adapter = hw->back; - - pci_clear_mwi(adapter->pdev); -} - -int e1000_pcix_get_mmrbc(struct e1000_hw *hw) -{ - struct e1000_adapter *adapter = hw->back; - return pcix_get_mmrbc(adapter->pdev); -} - -void e1000_pcix_set_mmrbc(struct e1000_hw *hw, int mmrbc) -{ - struct e1000_adapter *adapter = hw->back; - pcix_set_mmrbc(adapter->pdev, mmrbc); -} - -void e1000_io_write(struct e1000_hw *hw, unsigned long port, u32 value) -{ - outl(value, port); -} - -static bool e1000_vlan_used(struct e1000_adapter *adapter) -{ - u16 vid; - - for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) - return true; - return false; -} - -static void __e1000_vlan_mode(struct e1000_adapter *adapter, - netdev_features_t features) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl; - - ctrl = er32(CTRL); - if (features & NETIF_F_HW_VLAN_CTAG_RX) { - /* enable VLAN tag insert/strip */ - ctrl |= E1000_CTRL_VME; - } else { - /* disable VLAN tag insert/strip */ - ctrl &= ~E1000_CTRL_VME; - } - ew32(CTRL, ctrl); -} -static void e1000_vlan_filter_on_off(struct e1000_adapter *adapter, - bool filter_on) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_disable(adapter); - - __e1000_vlan_mode(adapter, adapter->netdev->features); - if (filter_on) { - /* enable VLAN receive filtering */ - rctl = er32(RCTL); - rctl &= ~E1000_RCTL_CFIEN; - if (!(adapter->netdev->flags & IFF_PROMISC)) - rctl |= E1000_RCTL_VFE; - ew32(RCTL, rctl); - e1000_update_mng_vlan(adapter); - } else { - /* disable VLAN receive filtering */ - rctl = er32(RCTL); - rctl &= ~E1000_RCTL_VFE; - ew32(RCTL, rctl); - } - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_enable(adapter); -} - -static void e1000_vlan_mode(struct net_device *netdev, - netdev_features_t features) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_disable(adapter); - - __e1000_vlan_mode(adapter, features); - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_enable(adapter); -} - -static int e1000_vlan_rx_add_vid(struct net_device *netdev, - __be16 proto, u16 vid) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 vfta, index; - - if ((hw->mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN_SUPPORT) && - (vid == adapter->mng_vlan_id)) - return 0; - - if (!e1000_vlan_used(adapter)) - e1000_vlan_filter_on_off(adapter, true); - - /* add VID to filter table */ - index = (vid >> 5) & 0x7F; - vfta = E1000_READ_REG_ARRAY(hw, VFTA, index); - vfta |= (1 << (vid & 0x1F)); - e1000_write_vfta(hw, index, vfta); - - set_bit(vid, adapter->active_vlans); - - return 0; -} - -static int e1000_vlan_rx_kill_vid(struct net_device *netdev, - __be16 proto, u16 vid) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 vfta, index; - - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_disable(adapter); - if (!test_bit(__E1000_DOWN, &adapter->flags)) - e1000_irq_enable(adapter); - - /* remove VID from filter table */ - index = (vid >> 5) & 0x7F; - vfta = E1000_READ_REG_ARRAY(hw, VFTA, index); - vfta &= ~(1 << (vid & 0x1F)); - e1000_write_vfta(hw, index, vfta); - - clear_bit(vid, adapter->active_vlans); - - if (!e1000_vlan_used(adapter)) - e1000_vlan_filter_on_off(adapter, false); - - return 0; -} - -static void e1000_restore_vlan(struct e1000_adapter *adapter) -{ - u16 vid; - - if (!e1000_vlan_used(adapter)) - return; - - e1000_vlan_filter_on_off(adapter, true); - for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) - e1000_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid); -} - -int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx) -{ - struct e1000_hw *hw = &adapter->hw; - - hw->autoneg = 0; - - /* Make sure dplx is at most 1 bit and lsb of speed is not set - * for the switch() below to work - */ - if ((spd & 1) || (dplx & ~1)) - goto err_inval; - - /* Fiber NICs only allow 1000 gbps Full duplex */ - if ((hw->media_type == e1000_media_type_fiber) && - spd != SPEED_1000 && - dplx != DUPLEX_FULL) - goto err_inval; - - switch (spd + dplx) { - case SPEED_10 + DUPLEX_HALF: - hw->forced_speed_duplex = e1000_10_half; - break; - case SPEED_10 + DUPLEX_FULL: - hw->forced_speed_duplex = e1000_10_full; - break; - case SPEED_100 + DUPLEX_HALF: - hw->forced_speed_duplex = e1000_100_half; - break; - case SPEED_100 + DUPLEX_FULL: - hw->forced_speed_duplex = e1000_100_full; - break; - case SPEED_1000 + DUPLEX_FULL: - hw->autoneg = 1; - hw->autoneg_advertised = ADVERTISE_1000_FULL; - break; - case SPEED_1000 + DUPLEX_HALF: /* not supported */ - default: - goto err_inval; - } - - /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ - hw->mdix = AUTO_ALL_MODES; - - return 0; - -err_inval: - e_err(probe, "Unsupported Speed/Duplex configuration\n"); - return -EINVAL; -} - -static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 ctrl, ctrl_ext, rctl, status; - u32 wufc = adapter->wol; -#ifdef CONFIG_PM - int retval = 0; -#endif - - netif_device_detach(netdev); - - if (netif_running(netdev)) { - int count = E1000_CHECK_RESET_COUNT; - - while (test_bit(__E1000_RESETTING, &adapter->flags) && count--) - usleep_range(10000, 20000); - - WARN_ON(test_bit(__E1000_RESETTING, &adapter->flags)); - e1000_down(adapter); - } - -#ifdef CONFIG_PM - retval = pci_save_state(pdev); - if (retval) - return retval; -#endif - - status = er32(STATUS); - if (status & E1000_STATUS_LU) - wufc &= ~E1000_WUFC_LNKC; - - if (wufc) { - e1000_setup_rctl(adapter); - e1000_set_rx_mode(netdev); - - rctl = er32(RCTL); - - /* turn on all-multi mode if wake on multicast is enabled */ - if (wufc & E1000_WUFC_MC) - rctl |= E1000_RCTL_MPE; - - /* enable receives in the hardware */ - ew32(RCTL, rctl | E1000_RCTL_EN); - - if (hw->mac_type >= e1000_82540) { - ctrl = er32(CTRL); - /* advertise wake from D3Cold */ - #define E1000_CTRL_ADVD3WUC 0x00100000 - /* phy power management enable */ - #define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 - ctrl |= E1000_CTRL_ADVD3WUC | - E1000_CTRL_EN_PHY_PWR_MGMT; - ew32(CTRL, ctrl); - } - - if (hw->media_type == e1000_media_type_fiber || - hw->media_type == e1000_media_type_internal_serdes) { - /* keep the laser running in D3 */ - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_SDP7_DATA; - ew32(CTRL_EXT, ctrl_ext); - } - - ew32(WUC, E1000_WUC_PME_EN); - ew32(WUFC, wufc); - } else { - ew32(WUC, 0); - ew32(WUFC, 0); - } - - e1000_release_manageability(adapter); - - *enable_wake = !!wufc; - - /* make sure adapter isn't asleep if manageability is enabled */ - if (adapter->en_mng_pt) - *enable_wake = true; - - if (netif_running(netdev)) - e1000_free_irq(adapter); - - if (!test_and_set_bit(__E1000_DISABLED, &adapter->flags)) - pci_disable_device(pdev); - - return 0; -} - -#ifdef CONFIG_PM -static int e1000_suspend(struct pci_dev *pdev, pm_message_t state) -{ - int retval; - bool wake; - - retval = __e1000_shutdown(pdev, &wake); - if (retval) - return retval; - - if (wake) { - pci_prepare_to_sleep(pdev); - } else { - pci_wake_from_d3(pdev, false); - pci_set_power_state(pdev, PCI_D3hot); - } - - return 0; -} - -static int e1000_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 err; - - pci_set_power_state(pdev, PCI_D0); - pci_restore_state(pdev); - pci_save_state(pdev); - - if (adapter->need_ioport) - err = pci_enable_device(pdev); - else - err = pci_enable_device_mem(pdev); - if (err) { - pr_err("Cannot enable PCI device from suspend\n"); - return err; - } - - /* flush memory to make sure state is correct */ - smp_mb__before_atomic(); - clear_bit(__E1000_DISABLED, &adapter->flags); - pci_set_master(pdev); - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - if (netif_running(netdev)) { - err = e1000_request_irq(adapter); - if (err) - return err; - } - - e1000_power_up_phy(adapter); - e1000_reset(adapter); - ew32(WUS, ~0); - - e1000_init_manageability(adapter); - - if (netif_running(netdev)) - e1000_up(adapter); - - netif_device_attach(netdev); - - return 0; -} -#endif - -static void e1000_shutdown(struct pci_dev *pdev) -{ - bool wake; - - __e1000_shutdown(pdev, &wake); - - if (system_state == SYSTEM_POWER_OFF) { - pci_wake_from_d3(pdev, wake); - pci_set_power_state(pdev, PCI_D3hot); - } -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void e1000_netpoll(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - disable_irq(adapter->pdev->irq); - e1000_intr(adapter->pdev->irq, netdev); - enable_irq(adapter->pdev->irq); -} -#endif - -/** - * e1000_io_error_detected - called when PCI error is detected - * @pdev: Pointer to PCI device - * @state: The current pci connection state - * - * This function is called after a PCI bus error affecting - * this device has been detected. - */ -static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, - pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e1000_down(adapter); - - if (!test_and_set_bit(__E1000_DISABLED, &adapter->flags)) - pci_disable_device(pdev); - - /* Request a slot slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e1000_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch, as if from a cold-boot. Implementation - * resembles the first-half of the e1000_resume routine. - */ -static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - int err; - - if (adapter->need_ioport) - err = pci_enable_device(pdev); - else - err = pci_enable_device_mem(pdev); - if (err) { - pr_err("Cannot re-enable PCI device after reset.\n"); - return PCI_ERS_RESULT_DISCONNECT; - } - - /* flush memory to make sure state is correct */ - smp_mb__before_atomic(); - clear_bit(__E1000_DISABLED, &adapter->flags); - pci_set_master(pdev); - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - e1000_reset(adapter); - ew32(WUS, ~0); - - return PCI_ERS_RESULT_RECOVERED; -} - -/** - * e1000_io_resume - called when traffic can start flowing again. - * @pdev: Pointer to PCI device - * - * This callback is called when the error recovery driver tells us that - * its OK to resume normal operation. Implementation resembles the - * second-half of the e1000_resume routine. - */ -static void e1000_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - - e1000_init_manageability(adapter); - - if (netif_running(netdev)) { - if (e1000_up(adapter)) { - pr_info("can't bring device back up after reset\n"); - return; - } - } - - netif_device_attach(netdev); -} - -/* e1000_main.c */ diff --git a/addons/e1000/src/4.4.180/e1000_osdep.h b/addons/e1000/src/4.4.180/e1000_osdep.h deleted file mode 100644 index 33e7c45a..00000000 --- a/addons/e1000/src/4.4.180/e1000_osdep.h +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - - -/* glue for the OS independent part of e1000 - * includes register access macros - */ - -#ifndef _E1000_OSDEP_H_ -#define _E1000_OSDEP_H_ - -#include - -#define CONFIG_RAM_BASE 0x60000 -#define GBE_CONFIG_OFFSET 0x0 - -#define GBE_CONFIG_RAM_BASE \ - ((unsigned int)(CONFIG_RAM_BASE + GBE_CONFIG_OFFSET)) - -#define GBE_CONFIG_BASE_VIRT \ - ((void __iomem *)phys_to_virt(GBE_CONFIG_RAM_BASE)) - -#define GBE_CONFIG_FLASH_WRITE(base, offset, count, data) \ - (iowrite16_rep(base + offset, data, count)) - -#define GBE_CONFIG_FLASH_READ(base, offset, count, data) \ - (ioread16_rep(base + (offset << 1), data, count)) - -#define er32(reg) \ - (readl(hw->hw_addr + ((hw->mac_type >= e1000_82543) \ - ? E1000_##reg : E1000_82542_##reg))) - -#define ew32(reg, value) \ - (writel((value), (hw->hw_addr + ((hw->mac_type >= e1000_82543) \ - ? E1000_##reg : E1000_82542_##reg)))) - -#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) ( \ - writel((value), ((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - ((offset) << 2)))) - -#define E1000_READ_REG_ARRAY(a, reg, offset) ( \ - readl((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - ((offset) << 2))) - -#define E1000_READ_REG_ARRAY_DWORD E1000_READ_REG_ARRAY -#define E1000_WRITE_REG_ARRAY_DWORD E1000_WRITE_REG_ARRAY - -#define E1000_WRITE_REG_ARRAY_WORD(a, reg, offset, value) ( \ - writew((value), ((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - ((offset) << 1)))) - -#define E1000_READ_REG_ARRAY_WORD(a, reg, offset) ( \ - readw((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - ((offset) << 1))) - -#define E1000_WRITE_REG_ARRAY_BYTE(a, reg, offset, value) ( \ - writeb((value), ((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - (offset)))) - -#define E1000_READ_REG_ARRAY_BYTE(a, reg, offset) ( \ - readb((a)->hw_addr + \ - (((a)->mac_type >= e1000_82543) ? E1000_##reg : E1000_82542_##reg) + \ - (offset))) - -#define E1000_WRITE_FLUSH() er32(STATUS) - -#define E1000_WRITE_ICH_FLASH_REG(a, reg, value) ( \ - writel((value), ((a)->flash_address + reg))) - -#define E1000_READ_ICH_FLASH_REG(a, reg) ( \ - readl((a)->flash_address + reg)) - -#define E1000_WRITE_ICH_FLASH_REG16(a, reg, value) ( \ - writew((value), ((a)->flash_address + reg))) - -#define E1000_READ_ICH_FLASH_REG16(a, reg) ( \ - readw((a)->flash_address + reg)) - -#endif /* _E1000_OSDEP_H_ */ diff --git a/addons/e1000/src/4.4.180/e1000_param.c b/addons/e1000/src/4.4.180/e1000_param.c deleted file mode 100644 index c9cde352..00000000 --- a/addons/e1000/src/4.4.180/e1000_param.c +++ /dev/null @@ -1,754 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2006 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include "e1000.h" - -/* This is the only thing that needs to be changed to adjust the - * maximum number of ports that the driver can manage. - */ - -#define E1000_MAX_NIC 32 - -#define OPTION_UNSET -1 -#define OPTION_DISABLED 0 -#define OPTION_ENABLED 1 - -/* All parameters are treated the same, as an integer array of values. - * This macro just reduces the need to repeat the same declaration code - * over and over (plus this helps to avoid typo bugs). - */ - -#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } -#define E1000_PARAM(X, desc) \ - static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ - static unsigned int num_##X; \ - module_param_array_named(X, X, int, &num_##X, 0); \ - MODULE_PARM_DESC(X, desc); - -/* Transmit Descriptor Count - * - * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers - * Valid Range: 80-4096 for 82544 and newer - * - * Default Value: 256 - */ -E1000_PARAM(TxDescriptors, "Number of transmit descriptors"); - -/* Receive Descriptor Count - * - * Valid Range: 80-256 for 82542 and 82543 gigabit ethernet controllers - * Valid Range: 80-4096 for 82544 and newer - * - * Default Value: 256 - */ -E1000_PARAM(RxDescriptors, "Number of receive descriptors"); - -/* User Specified Speed Override - * - * Valid Range: 0, 10, 100, 1000 - * - 0 - auto-negotiate at all supported speeds - * - 10 - only link at 10 Mbps - * - 100 - only link at 100 Mbps - * - 1000 - only link at 1000 Mbps - * - * Default Value: 0 - */ -E1000_PARAM(Speed, "Speed setting"); - -/* User Specified Duplex Override - * - * Valid Range: 0-2 - * - 0 - auto-negotiate for duplex - * - 1 - only link at half duplex - * - 2 - only link at full duplex - * - * Default Value: 0 - */ -E1000_PARAM(Duplex, "Duplex setting"); - -/* Auto-negotiation Advertisement Override - * - * Valid Range: 0x01-0x0F, 0x20-0x2F (copper); 0x20 (fiber) - * - * The AutoNeg value is a bit mask describing which speed and duplex - * combinations should be advertised during auto-negotiation. - * The supported speed and duplex modes are listed below - * - * Bit 7 6 5 4 3 2 1 0 - * Speed (Mbps) N/A N/A 1000 N/A 100 100 10 10 - * Duplex Full Full Half Full Half - * - * Default Value: 0x2F (copper); 0x20 (fiber) - */ -E1000_PARAM(AutoNeg, "Advertised auto-negotiation setting"); -#define AUTONEG_ADV_DEFAULT 0x2F -#define AUTONEG_ADV_MASK 0x2F - -/* User Specified Flow Control Override - * - * Valid Range: 0-3 - * - 0 - No Flow Control - * - 1 - Rx only, respond to PAUSE frames but do not generate them - * - 2 - Tx only, generate PAUSE frames but ignore them on receive - * - 3 - Full Flow Control Support - * - * Default Value: Read flow control settings from the EEPROM - */ -E1000_PARAM(FlowControl, "Flow Control setting"); -#define FLOW_CONTROL_DEFAULT FLOW_CONTROL_FULL - -/* XsumRX - Receive Checksum Offload Enable/Disable - * - * Valid Range: 0, 1 - * - 0 - disables all checksum offload - * - 1 - enables receive IP/TCP/UDP checksum offload - * on 82543 and newer -based NICs - * - * Default Value: 1 - */ -E1000_PARAM(XsumRX, "Disable or enable Receive Checksum offload"); - -/* Transmit Interrupt Delay in units of 1.024 microseconds - * Tx interrupt delay needs to typically be set to something non zero - * - * Valid Range: 0-65535 - */ -E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay"); -#define DEFAULT_TIDV 8 -#define MAX_TXDELAY 0xFFFF -#define MIN_TXDELAY 0 - -/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds - * - * Valid Range: 0-65535 - */ -E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay"); -#define DEFAULT_TADV 32 -#define MAX_TXABSDELAY 0xFFFF -#define MIN_TXABSDELAY 0 - -/* Receive Interrupt Delay in units of 1.024 microseconds - * hardware will likely hang if you set this to anything but zero. - * - * Valid Range: 0-65535 - */ -E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); -#define DEFAULT_RDTR 0 -#define MAX_RXDELAY 0xFFFF -#define MIN_RXDELAY 0 - -/* Receive Absolute Interrupt Delay in units of 1.024 microseconds - * - * Valid Range: 0-65535 - */ -E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); -#define DEFAULT_RADV 8 -#define MAX_RXABSDELAY 0xFFFF -#define MIN_RXABSDELAY 0 - -/* Interrupt Throttle Rate (interrupts/sec) - * - * Valid Range: 100-100000 (0=off, 1=dynamic, 3=dynamic conservative) - */ -E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); -#define DEFAULT_ITR 3 -#define MAX_ITR 100000 -#define MIN_ITR 100 - -/* Enable Smart Power Down of the PHY - * - * Valid Range: 0, 1 - * - * Default Value: 0 (disabled) - */ -E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down"); - -struct e1000_option { - enum { enable_option, range_option, list_option } type; - const char *name; - const char *err; - int def; - union { - struct { /* range_option info */ - int min; - int max; - } r; - struct { /* list_option info */ - int nr; - const struct e1000_opt_list { int i; char *str; } *p; - } l; - } arg; -}; - -static int e1000_validate_option(unsigned int *value, - const struct e1000_option *opt, - struct e1000_adapter *adapter) -{ - if (*value == OPTION_UNSET) { - *value = opt->def; - return 0; - } - - switch (opt->type) { - case enable_option: - switch (*value) { - case OPTION_ENABLED: - e_dev_info("%s Enabled\n", opt->name); - return 0; - case OPTION_DISABLED: - e_dev_info("%s Disabled\n", opt->name); - return 0; - } - break; - case range_option: - if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { - e_dev_info("%s set to %i\n", opt->name, *value); - return 0; - } - break; - case list_option: { - int i; - const struct e1000_opt_list *ent; - - for (i = 0; i < opt->arg.l.nr; i++) { - ent = &opt->arg.l.p[i]; - if (*value == ent->i) { - if (ent->str[0] != '\0') - e_dev_info("%s\n", ent->str); - return 0; - } - } - } - break; - default: - BUG(); - } - - e_dev_info("Invalid %s value specified (%i) %s\n", - opt->name, *value, opt->err); - *value = opt->def; - return -1; -} - -static void e1000_check_fiber_options(struct e1000_adapter *adapter); -static void e1000_check_copper_options(struct e1000_adapter *adapter); - -/** - * e1000_check_options - Range Checking for Command Line Parameters - * @adapter: board private structure - * - * This routine checks all command line parameters for valid user - * input. If an invalid value is given, or if no user specified - * value exists, a default value is used. The final value is stored - * in a variable in the adapter structure. - **/ -void e1000_check_options(struct e1000_adapter *adapter) -{ - struct e1000_option opt; - int bd = adapter->bd_number; - - if (bd >= E1000_MAX_NIC) { - e_dev_warn("Warning: no configuration for board #%i " - "using defaults for all values\n", bd); - } - - { /* Transmit Descriptor Count */ - struct e1000_tx_ring *tx_ring = adapter->tx_ring; - int i; - e1000_mac_type mac_type = adapter->hw.mac_type; - - opt = (struct e1000_option) { - .type = range_option, - .name = "Transmit Descriptors", - .err = "using default of " - __MODULE_STRING(E1000_DEFAULT_TXD), - .def = E1000_DEFAULT_TXD, - .arg = { .r = { - .min = E1000_MIN_TXD, - .max = mac_type < e1000_82544 ? E1000_MAX_TXD : E1000_MAX_82544_TXD - }} - }; - - if (num_TxDescriptors > bd) { - tx_ring->count = TxDescriptors[bd]; - e1000_validate_option(&tx_ring->count, &opt, adapter); - tx_ring->count = ALIGN(tx_ring->count, - REQ_TX_DESCRIPTOR_MULTIPLE); - } else { - tx_ring->count = opt.def; - } - for (i = 0; i < adapter->num_tx_queues; i++) - tx_ring[i].count = tx_ring->count; - } - { /* Receive Descriptor Count */ - struct e1000_rx_ring *rx_ring = adapter->rx_ring; - int i; - e1000_mac_type mac_type = adapter->hw.mac_type; - - opt = (struct e1000_option) { - .type = range_option, - .name = "Receive Descriptors", - .err = "using default of " - __MODULE_STRING(E1000_DEFAULT_RXD), - .def = E1000_DEFAULT_RXD, - .arg = { .r = { - .min = E1000_MIN_RXD, - .max = mac_type < e1000_82544 ? E1000_MAX_RXD : - E1000_MAX_82544_RXD - }} - }; - - if (num_RxDescriptors > bd) { - rx_ring->count = RxDescriptors[bd]; - e1000_validate_option(&rx_ring->count, &opt, adapter); - rx_ring->count = ALIGN(rx_ring->count, - REQ_RX_DESCRIPTOR_MULTIPLE); - } else { - rx_ring->count = opt.def; - } - for (i = 0; i < adapter->num_rx_queues; i++) - rx_ring[i].count = rx_ring->count; - } - { /* Checksum Offload Enable/Disable */ - opt = (struct e1000_option) { - .type = enable_option, - .name = "Checksum Offload", - .err = "defaulting to Enabled", - .def = OPTION_ENABLED - }; - - if (num_XsumRX > bd) { - unsigned int rx_csum = XsumRX[bd]; - e1000_validate_option(&rx_csum, &opt, adapter); - adapter->rx_csum = rx_csum; - } else { - adapter->rx_csum = opt.def; - } - } - { /* Flow Control */ - - static const struct e1000_opt_list fc_list[] = { - { E1000_FC_NONE, "Flow Control Disabled" }, - { E1000_FC_RX_PAUSE, "Flow Control Receive Only" }, - { E1000_FC_TX_PAUSE, "Flow Control Transmit Only" }, - { E1000_FC_FULL, "Flow Control Enabled" }, - { E1000_FC_DEFAULT, "Flow Control Hardware Default" } - }; - - opt = (struct e1000_option) { - .type = list_option, - .name = "Flow Control", - .err = "reading default settings from EEPROM", - .def = E1000_FC_DEFAULT, - .arg = { .l = { .nr = ARRAY_SIZE(fc_list), - .p = fc_list }} - }; - - if (num_FlowControl > bd) { - unsigned int fc = FlowControl[bd]; - e1000_validate_option(&fc, &opt, adapter); - adapter->hw.fc = adapter->hw.original_fc = fc; - } else { - adapter->hw.fc = adapter->hw.original_fc = opt.def; - } - } - { /* Transmit Interrupt Delay */ - opt = (struct e1000_option) { - .type = range_option, - .name = "Transmit Interrupt Delay", - .err = "using default of " __MODULE_STRING(DEFAULT_TIDV), - .def = DEFAULT_TIDV, - .arg = { .r = { .min = MIN_TXDELAY, - .max = MAX_TXDELAY }} - }; - - if (num_TxIntDelay > bd) { - adapter->tx_int_delay = TxIntDelay[bd]; - e1000_validate_option(&adapter->tx_int_delay, &opt, - adapter); - } else { - adapter->tx_int_delay = opt.def; - } - } - { /* Transmit Absolute Interrupt Delay */ - opt = (struct e1000_option) { - .type = range_option, - .name = "Transmit Absolute Interrupt Delay", - .err = "using default of " __MODULE_STRING(DEFAULT_TADV), - .def = DEFAULT_TADV, - .arg = { .r = { .min = MIN_TXABSDELAY, - .max = MAX_TXABSDELAY }} - }; - - if (num_TxAbsIntDelay > bd) { - adapter->tx_abs_int_delay = TxAbsIntDelay[bd]; - e1000_validate_option(&adapter->tx_abs_int_delay, &opt, - adapter); - } else { - adapter->tx_abs_int_delay = opt.def; - } - } - { /* Receive Interrupt Delay */ - opt = (struct e1000_option) { - .type = range_option, - .name = "Receive Interrupt Delay", - .err = "using default of " __MODULE_STRING(DEFAULT_RDTR), - .def = DEFAULT_RDTR, - .arg = { .r = { .min = MIN_RXDELAY, - .max = MAX_RXDELAY }} - }; - - if (num_RxIntDelay > bd) { - adapter->rx_int_delay = RxIntDelay[bd]; - e1000_validate_option(&adapter->rx_int_delay, &opt, - adapter); - } else { - adapter->rx_int_delay = opt.def; - } - } - { /* Receive Absolute Interrupt Delay */ - opt = (struct e1000_option) { - .type = range_option, - .name = "Receive Absolute Interrupt Delay", - .err = "using default of " __MODULE_STRING(DEFAULT_RADV), - .def = DEFAULT_RADV, - .arg = { .r = { .min = MIN_RXABSDELAY, - .max = MAX_RXABSDELAY }} - }; - - if (num_RxAbsIntDelay > bd) { - adapter->rx_abs_int_delay = RxAbsIntDelay[bd]; - e1000_validate_option(&adapter->rx_abs_int_delay, &opt, - adapter); - } else { - adapter->rx_abs_int_delay = opt.def; - } - } - { /* Interrupt Throttling Rate */ - opt = (struct e1000_option) { - .type = range_option, - .name = "Interrupt Throttling Rate (ints/sec)", - .err = "using default of " __MODULE_STRING(DEFAULT_ITR), - .def = DEFAULT_ITR, - .arg = { .r = { .min = MIN_ITR, - .max = MAX_ITR }} - }; - - if (num_InterruptThrottleRate > bd) { - adapter->itr = InterruptThrottleRate[bd]; - switch (adapter->itr) { - case 0: - e_dev_info("%s turned off\n", opt.name); - break; - case 1: - e_dev_info("%s set to dynamic mode\n", - opt.name); - adapter->itr_setting = adapter->itr; - adapter->itr = 20000; - break; - case 3: - e_dev_info("%s set to dynamic conservative " - "mode\n", opt.name); - adapter->itr_setting = adapter->itr; - adapter->itr = 20000; - break; - case 4: - e_dev_info("%s set to simplified " - "(2000-8000) ints mode\n", opt.name); - adapter->itr_setting = adapter->itr; - break; - default: - e1000_validate_option(&adapter->itr, &opt, - adapter); - /* save the setting, because the dynamic bits - * change itr. - * clear the lower two bits because they are - * used as control - */ - adapter->itr_setting = adapter->itr & ~3; - break; - } - } else { - adapter->itr_setting = opt.def; - adapter->itr = 20000; - } - } - { /* Smart Power Down */ - opt = (struct e1000_option) { - .type = enable_option, - .name = "PHY Smart Power Down", - .err = "defaulting to Disabled", - .def = OPTION_DISABLED - }; - - if (num_SmartPowerDownEnable > bd) { - unsigned int spd = SmartPowerDownEnable[bd]; - e1000_validate_option(&spd, &opt, adapter); - adapter->smart_power_down = spd; - } else { - adapter->smart_power_down = opt.def; - } - } - - switch (adapter->hw.media_type) { - case e1000_media_type_fiber: - case e1000_media_type_internal_serdes: - e1000_check_fiber_options(adapter); - break; - case e1000_media_type_copper: - e1000_check_copper_options(adapter); - break; - default: - BUG(); - } -} - -/** - * e1000_check_fiber_options - Range Checking for Link Options, Fiber Version - * @adapter: board private structure - * - * Handles speed and duplex options on fiber adapters - **/ -static void e1000_check_fiber_options(struct e1000_adapter *adapter) -{ - int bd = adapter->bd_number; - if (num_Speed > bd) { - e_dev_info("Speed not valid for fiber adapters, parameter " - "ignored\n"); - } - - if (num_Duplex > bd) { - e_dev_info("Duplex not valid for fiber adapters, parameter " - "ignored\n"); - } - - if ((num_AutoNeg > bd) && (AutoNeg[bd] != 0x20)) { - e_dev_info("AutoNeg other than 1000/Full is not valid for fiber" - "adapters, parameter ignored\n"); - } -} - -/** - * e1000_check_copper_options - Range Checking for Link Options, Copper Version - * @adapter: board private structure - * - * Handles speed and duplex options on copper adapters - **/ -static void e1000_check_copper_options(struct e1000_adapter *adapter) -{ - struct e1000_option opt; - unsigned int speed, dplx, an; - int bd = adapter->bd_number; - - { /* Speed */ - static const struct e1000_opt_list speed_list[] = { - { 0, "" }, - { SPEED_10, "" }, - { SPEED_100, "" }, - { SPEED_1000, "" }}; - - opt = (struct e1000_option) { - .type = list_option, - .name = "Speed", - .err = "parameter ignored", - .def = 0, - .arg = { .l = { .nr = ARRAY_SIZE(speed_list), - .p = speed_list }} - }; - - if (num_Speed > bd) { - speed = Speed[bd]; - e1000_validate_option(&speed, &opt, adapter); - } else { - speed = opt.def; - } - } - { /* Duplex */ - static const struct e1000_opt_list dplx_list[] = { - { 0, "" }, - { HALF_DUPLEX, "" }, - { FULL_DUPLEX, "" }}; - - opt = (struct e1000_option) { - .type = list_option, - .name = "Duplex", - .err = "parameter ignored", - .def = 0, - .arg = { .l = { .nr = ARRAY_SIZE(dplx_list), - .p = dplx_list }} - }; - - if (num_Duplex > bd) { - dplx = Duplex[bd]; - e1000_validate_option(&dplx, &opt, adapter); - } else { - dplx = opt.def; - } - } - - if ((num_AutoNeg > bd) && (speed != 0 || dplx != 0)) { - e_dev_info("AutoNeg specified along with Speed or Duplex, " - "parameter ignored\n"); - adapter->hw.autoneg_advertised = AUTONEG_ADV_DEFAULT; - } else { /* Autoneg */ - static const struct e1000_opt_list an_list[] = - #define AA "AutoNeg advertising " - {{ 0x01, AA "10/HD" }, - { 0x02, AA "10/FD" }, - { 0x03, AA "10/FD, 10/HD" }, - { 0x04, AA "100/HD" }, - { 0x05, AA "100/HD, 10/HD" }, - { 0x06, AA "100/HD, 10/FD" }, - { 0x07, AA "100/HD, 10/FD, 10/HD" }, - { 0x08, AA "100/FD" }, - { 0x09, AA "100/FD, 10/HD" }, - { 0x0a, AA "100/FD, 10/FD" }, - { 0x0b, AA "100/FD, 10/FD, 10/HD" }, - { 0x0c, AA "100/FD, 100/HD" }, - { 0x0d, AA "100/FD, 100/HD, 10/HD" }, - { 0x0e, AA "100/FD, 100/HD, 10/FD" }, - { 0x0f, AA "100/FD, 100/HD, 10/FD, 10/HD" }, - { 0x20, AA "1000/FD" }, - { 0x21, AA "1000/FD, 10/HD" }, - { 0x22, AA "1000/FD, 10/FD" }, - { 0x23, AA "1000/FD, 10/FD, 10/HD" }, - { 0x24, AA "1000/FD, 100/HD" }, - { 0x25, AA "1000/FD, 100/HD, 10/HD" }, - { 0x26, AA "1000/FD, 100/HD, 10/FD" }, - { 0x27, AA "1000/FD, 100/HD, 10/FD, 10/HD" }, - { 0x28, AA "1000/FD, 100/FD" }, - { 0x29, AA "1000/FD, 100/FD, 10/HD" }, - { 0x2a, AA "1000/FD, 100/FD, 10/FD" }, - { 0x2b, AA "1000/FD, 100/FD, 10/FD, 10/HD" }, - { 0x2c, AA "1000/FD, 100/FD, 100/HD" }, - { 0x2d, AA "1000/FD, 100/FD, 100/HD, 10/HD" }, - { 0x2e, AA "1000/FD, 100/FD, 100/HD, 10/FD" }, - { 0x2f, AA "1000/FD, 100/FD, 100/HD, 10/FD, 10/HD" }}; - - opt = (struct e1000_option) { - .type = list_option, - .name = "AutoNeg", - .err = "parameter ignored", - .def = AUTONEG_ADV_DEFAULT, - .arg = { .l = { .nr = ARRAY_SIZE(an_list), - .p = an_list }} - }; - - if (num_AutoNeg > bd) { - an = AutoNeg[bd]; - e1000_validate_option(&an, &opt, adapter); - } else { - an = opt.def; - } - adapter->hw.autoneg_advertised = an; - } - - switch (speed + dplx) { - case 0: - adapter->hw.autoneg = adapter->fc_autoneg = 1; - if ((num_Speed > bd) && (speed != 0 || dplx != 0)) - e_dev_info("Speed and duplex autonegotiation " - "enabled\n"); - break; - case HALF_DUPLEX: - e_dev_info("Half Duplex specified without Speed\n"); - e_dev_info("Using Autonegotiation at Half Duplex only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | - ADVERTISE_100_HALF; - break; - case FULL_DUPLEX: - e_dev_info("Full Duplex specified without Speed\n"); - e_dev_info("Using Autonegotiation at Full Duplex only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_10_FULL | - ADVERTISE_100_FULL | - ADVERTISE_1000_FULL; - break; - case SPEED_10: - e_dev_info("10 Mbps Speed specified without Duplex\n"); - e_dev_info("Using Autonegotiation at 10 Mbps only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_10_HALF | - ADVERTISE_10_FULL; - break; - case SPEED_10 + HALF_DUPLEX: - e_dev_info("Forcing to 10 Mbps Half Duplex\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 0; - adapter->hw.forced_speed_duplex = e1000_10_half; - adapter->hw.autoneg_advertised = 0; - break; - case SPEED_10 + FULL_DUPLEX: - e_dev_info("Forcing to 10 Mbps Full Duplex\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 0; - adapter->hw.forced_speed_duplex = e1000_10_full; - adapter->hw.autoneg_advertised = 0; - break; - case SPEED_100: - e_dev_info("100 Mbps Speed specified without Duplex\n"); - e_dev_info("Using Autonegotiation at 100 Mbps only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_100_HALF | - ADVERTISE_100_FULL; - break; - case SPEED_100 + HALF_DUPLEX: - e_dev_info("Forcing to 100 Mbps Half Duplex\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 0; - adapter->hw.forced_speed_duplex = e1000_100_half; - adapter->hw.autoneg_advertised = 0; - break; - case SPEED_100 + FULL_DUPLEX: - e_dev_info("Forcing to 100 Mbps Full Duplex\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 0; - adapter->hw.forced_speed_duplex = e1000_100_full; - adapter->hw.autoneg_advertised = 0; - break; - case SPEED_1000: - e_dev_info("1000 Mbps Speed specified without Duplex\n"); - goto full_duplex_only; - case SPEED_1000 + HALF_DUPLEX: - e_dev_info("Half Duplex is not supported at 1000 Mbps\n"); - /* fall through */ - case SPEED_1000 + FULL_DUPLEX: -full_duplex_only: - e_dev_info("Using Autonegotiation at 1000 Mbps Full Duplex " - "only\n"); - adapter->hw.autoneg = adapter->fc_autoneg = 1; - adapter->hw.autoneg_advertised = ADVERTISE_1000_FULL; - break; - default: - BUG(); - } - - /* Speed, AutoNeg and MDI/MDI-X must all play nice */ - if (e1000_validate_mdi_setting(&(adapter->hw)) < 0) { - e_dev_info("Speed, AutoNeg and MDI-X specs are incompatible. " - "Setting MDI-X to a compatible value.\n"); - } -} - diff --git a/addons/e1000e/install.sh b/addons/e1000e/install.sh deleted file mode 100644 index 716c13d5..00000000 --- a/addons/e1000e/install.sh +++ /dev/null @@ -1,4 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Installing module for Intel(R) PRO/1000 Gigabit Ethernet PCI-e adapter" - ${INSMOD} "/modules/e1000e.ko" ${PARAMS} -fi diff --git a/addons/e1000e/manifest.yml b/addons/e1000e/manifest.yml deleted file mode 100644 index fe6ad631..00000000 --- a/addons/e1000e/manifest.yml +++ /dev/null @@ -1,29 +0,0 @@ -version: 1 -name: e1000e -description: "Driver for Intel(R) PRO/1000 Gigabit Ethernet PCI-e adapters" -available-for: - bromolow-3.10.108: - install-script: &script "install.sh" - modules: true - apollolake-4.4.180: - install-script: *script - modules: true - broadwell-4.4.180: - install-script: *script - modules: true - broadwellnk-4.4.180: - install-script: *script - modules: true - denverton-4.4.180: - install-script: *script - modules: true - geminilake-4.4.180: - install-script: *script - modules: true - v1000-4.4.180: - install-script: *script - modules: true - purley-4.4.180: - install-script: *script - modules: true - diff --git a/addons/e1000e/src/3.10.108/80003es2lan.c b/addons/e1000e/src/3.10.108/80003es2lan.c deleted file mode 100644 index b71c8502..00000000 --- a/addons/e1000e/src/3.10.108/80003es2lan.c +++ /dev/null @@ -1,1421 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* 80003ES2LAN Gigabit Ethernet Controller (Copper) - * 80003ES2LAN Gigabit Ethernet Controller (Serdes) - */ - -#include "e1000.h" - -/* A table for the GG82563 cable length where the range is defined - * with a lower bound at "index" and the upper bound at - * "index + 5". - */ -static const u16 e1000_gg82563_cable_length_table[] = { - 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF -}; - -#define GG82563_CABLE_LENGTH_TABLE_SIZE \ - ARRAY_SIZE(e1000_gg82563_cable_length_table) - -static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw); -static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); -static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); -static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw); -static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw); -static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw); -static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex); -static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, - u16 *data); -static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, - u16 data); -static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw); - -/** - * e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - - if (hw->phy.media_type != e1000_media_type_copper) { - phy->type = e1000_phy_none; - return 0; - } else { - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan; - } - - phy->addr = 1; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->reset_delay_us = 100; - phy->type = e1000_phy_gg82563; - - /* This can only be done after all function pointers are setup. */ - ret_val = e1000e_get_phy_id(hw); - - /* Verify phy id */ - if (phy->id != GG82563_E_PHY_ID) - return -E1000_ERR_PHY; - - return ret_val; -} - -/** - * e1000_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - u16 size; - - nvm->opcode_bits = 8; - nvm->delay_usec = 1; - switch (nvm->override) { - case e1000_nvm_override_spi_large: - nvm->page_size = 32; - nvm->address_bits = 16; - break; - case e1000_nvm_override_spi_small: - nvm->page_size = 8; - nvm->address_bits = 8; - break; - default: - nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; - nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; - break; - } - - nvm->type = e1000_nvm_eeprom_spi; - - size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> - E1000_EECD_SIZE_EX_SHIFT); - - /* Added to a constant, "size" becomes the left-shift value - * for setting word_size. - */ - size += NVM_WORD_SIZE_BASE_SHIFT; - - /* EEPROM access above 16k is unsupported */ - if (size > 14) - size = 14; - nvm->word_size = 1 << size; - - return 0; -} - -/** - * e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - /* Set media type and media-dependent function pointers */ - switch (hw->adapter->pdev->device) { - case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: - hw->phy.media_type = e1000_media_type_internal_serdes; - mac->ops.check_for_link = e1000e_check_for_serdes_link; - mac->ops.setup_physical_interface = - e1000e_setup_fiber_serdes_link; - break; - default: - hw->phy.media_type = e1000_media_type_copper; - mac->ops.check_for_link = e1000e_check_for_copper_link; - mac->ops.setup_physical_interface = - e1000_setup_copper_link_80003es2lan; - break; - } - - /* Set mta register count */ - mac->mta_reg_count = 128; - /* Set rar entry count */ - mac->rar_entry_count = E1000_RAR_ENTRIES; - /* FWSM register */ - mac->has_fwsm = true; - /* ARC supported; valid only if manageability features are enabled. */ - mac->arc_subsystem_valid = !!(er32(FWSM) & E1000_FWSM_MODE_MASK); - /* Adaptive IFS not supported */ - mac->adaptive_ifs = false; - - /* set lan id for port to determine which phy lock to use */ - hw->mac.ops.set_lan_id(hw); - - return 0; -} - -static s32 e1000_get_variants_80003es2lan(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - s32 rc; - - rc = e1000_init_mac_params_80003es2lan(hw); - if (rc) - return rc; - - rc = e1000_init_nvm_params_80003es2lan(hw); - if (rc) - return rc; - - rc = e1000_init_phy_params_80003es2lan(hw); - if (rc) - return rc; - - return 0; -} - -/** - * e1000_acquire_phy_80003es2lan - Acquire rights to access PHY - * @hw: pointer to the HW structure - * - * A wrapper to acquire access rights to the correct PHY. - **/ -static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw) -{ - u16 mask; - - mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; - return e1000_acquire_swfw_sync_80003es2lan(hw, mask); -} - -/** - * e1000_release_phy_80003es2lan - Release rights to access PHY - * @hw: pointer to the HW structure - * - * A wrapper to release access rights to the correct PHY. - **/ -static void e1000_release_phy_80003es2lan(struct e1000_hw *hw) -{ - u16 mask; - - mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; - e1000_release_swfw_sync_80003es2lan(hw, mask); -} - -/** - * e1000_acquire_mac_csr_80003es2lan - Acquire right to access Kumeran register - * @hw: pointer to the HW structure - * - * Acquire the semaphore to access the Kumeran interface. - * - **/ -static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw) -{ - u16 mask; - - mask = E1000_SWFW_CSR_SM; - - return e1000_acquire_swfw_sync_80003es2lan(hw, mask); -} - -/** - * e1000_release_mac_csr_80003es2lan - Release right to access Kumeran Register - * @hw: pointer to the HW structure - * - * Release the semaphore used to access the Kumeran interface - **/ -static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw) -{ - u16 mask; - - mask = E1000_SWFW_CSR_SM; - - e1000_release_swfw_sync_80003es2lan(hw, mask); -} - -/** - * e1000_acquire_nvm_80003es2lan - Acquire rights to access NVM - * @hw: pointer to the HW structure - * - * Acquire the semaphore to access the EEPROM. - **/ -static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val; - - ret_val = e1000_acquire_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); - if (ret_val) - return ret_val; - - ret_val = e1000e_acquire_nvm(hw); - - if (ret_val) - e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); - - return ret_val; -} - -/** - * e1000_release_nvm_80003es2lan - Relinquish rights to access NVM - * @hw: pointer to the HW structure - * - * Release the semaphore used to access the EEPROM. - **/ -static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw) -{ - e1000e_release_nvm(hw); - e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); -} - -/** - * e1000_acquire_swfw_sync_80003es2lan - Acquire SW/FW semaphore - * @hw: pointer to the HW structure - * @mask: specifies which semaphore to acquire - * - * Acquire the SW/FW semaphore to access the PHY or NVM. The mask - * will also specify which port we're acquiring the lock for. - **/ -static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) -{ - u32 swfw_sync; - u32 swmask = mask; - u32 fwmask = mask << 16; - s32 i = 0; - s32 timeout = 50; - - while (i < timeout) { - if (e1000e_get_hw_semaphore(hw)) - return -E1000_ERR_SWFW_SYNC; - - swfw_sync = er32(SW_FW_SYNC); - if (!(swfw_sync & (fwmask | swmask))) - break; - - /* Firmware currently using resource (fwmask) - * or other software thread using resource (swmask) - */ - e1000e_put_hw_semaphore(hw); - mdelay(5); - i++; - } - - if (i == timeout) { - e_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); - return -E1000_ERR_SWFW_SYNC; - } - - swfw_sync |= swmask; - ew32(SW_FW_SYNC, swfw_sync); - - e1000e_put_hw_semaphore(hw); - - return 0; -} - -/** - * e1000_release_swfw_sync_80003es2lan - Release SW/FW semaphore - * @hw: pointer to the HW structure - * @mask: specifies which semaphore to acquire - * - * Release the SW/FW semaphore used to access the PHY or NVM. The mask - * will also specify which port we're releasing the lock for. - **/ -static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) -{ - u32 swfw_sync; - - while (e1000e_get_hw_semaphore(hw) != 0) - ; /* Empty */ - - swfw_sync = er32(SW_FW_SYNC); - swfw_sync &= ~mask; - ew32(SW_FW_SYNC, swfw_sync); - - e1000e_put_hw_semaphore(hw); -} - -/** - * e1000_read_phy_reg_gg82563_80003es2lan - Read GG82563 PHY register - * @hw: pointer to the HW structure - * @offset: offset of the register to read - * @data: pointer to the data returned from the operation - * - * Read the GG82563 PHY register. - **/ -static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, - u32 offset, u16 *data) -{ - s32 ret_val; - u32 page_select; - u16 temp; - - ret_val = e1000_acquire_phy_80003es2lan(hw); - if (ret_val) - return ret_val; - - /* Select Configuration Page */ - if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { - page_select = GG82563_PHY_PAGE_SELECT; - } else { - /* Use Alternative Page Select register to access - * registers 30 and 31 - */ - page_select = GG82563_PHY_PAGE_SELECT_ALT; - } - - temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); - ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp); - if (ret_val) { - e1000_release_phy_80003es2lan(hw); - return ret_val; - } - - if (hw->dev_spec.e80003es2lan.mdic_wa_enable) { - /* The "ready" bit in the MDIC register may be incorrectly set - * before the device has completed the "Page Select" MDI - * transaction. So we wait 200us after each MDI command... - */ - usleep_range(200, 400); - - /* ...and verify the command was successful. */ - ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); - - if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { - e1000_release_phy_80003es2lan(hw); - return -E1000_ERR_PHY; - } - - usleep_range(200, 400); - - ret_val = e1000e_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - - usleep_range(200, 400); - } else { - ret_val = e1000e_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - } - - e1000_release_phy_80003es2lan(hw); - - return ret_val; -} - -/** - * e1000_write_phy_reg_gg82563_80003es2lan - Write GG82563 PHY register - * @hw: pointer to the HW structure - * @offset: offset of the register to read - * @data: value to write to the register - * - * Write to the GG82563 PHY register. - **/ -static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, - u32 offset, u16 data) -{ - s32 ret_val; - u32 page_select; - u16 temp; - - ret_val = e1000_acquire_phy_80003es2lan(hw); - if (ret_val) - return ret_val; - - /* Select Configuration Page */ - if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { - page_select = GG82563_PHY_PAGE_SELECT; - } else { - /* Use Alternative Page Select register to access - * registers 30 and 31 - */ - page_select = GG82563_PHY_PAGE_SELECT_ALT; - } - - temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); - ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp); - if (ret_val) { - e1000_release_phy_80003es2lan(hw); - return ret_val; - } - - if (hw->dev_spec.e80003es2lan.mdic_wa_enable) { - /* The "ready" bit in the MDIC register may be incorrectly set - * before the device has completed the "Page Select" MDI - * transaction. So we wait 200us after each MDI command... - */ - usleep_range(200, 400); - - /* ...and verify the command was successful. */ - ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); - - if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { - e1000_release_phy_80003es2lan(hw); - return -E1000_ERR_PHY; - } - - usleep_range(200, 400); - - ret_val = e1000e_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & - offset, data); - - usleep_range(200, 400); - } else { - ret_val = e1000e_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & - offset, data); - } - - e1000_release_phy_80003es2lan(hw); - - return ret_val; -} - -/** - * e1000_write_nvm_80003es2lan - Write to ESB2 NVM - * @hw: pointer to the HW structure - * @offset: offset of the register to read - * @words: number of words to write - * @data: buffer of data to write to the NVM - * - * Write "words" of data to the ESB2 NVM. - **/ -static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data) -{ - return e1000e_write_nvm_spi(hw, offset, words, data); -} - -/** - * e1000_get_cfg_done_80003es2lan - Wait for configuration to complete - * @hw: pointer to the HW structure - * - * Wait a specific amount of time for manageability processes to complete. - * This is a function pointer entry point called by the phy module. - **/ -static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw) -{ - s32 timeout = PHY_CFG_TIMEOUT; - u32 mask = E1000_NVM_CFG_DONE_PORT_0; - - if (hw->bus.func == 1) - mask = E1000_NVM_CFG_DONE_PORT_1; - - while (timeout) { - if (er32(EEMNGCTL) & mask) - break; - usleep_range(1000, 2000); - timeout--; - } - if (!timeout) { - e_dbg("MNG configuration cycle has not completed.\n"); - return -E1000_ERR_RESET; - } - - return 0; -} - -/** - * e1000_phy_force_speed_duplex_80003es2lan - Force PHY speed and duplex - * @hw: pointer to the HW structure - * - * Force the speed and duplex settings onto the PHY. This is a - * function pointer entry point called by the phy module. - **/ -static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - bool link; - - /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO; - ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - e_dbg("GG82563 PSCR: %X\n", phy_data); - - ret_val = e1e_rphy(hw, MII_BMCR, &phy_data); - if (ret_val) - return ret_val; - - e1000e_phy_force_speed_duplex_setup(hw, &phy_data); - - /* Reset the phy to commit changes. */ - phy_data |= BMCR_RESET; - - ret_val = e1e_wphy(hw, MII_BMCR, phy_data); - if (ret_val) - return ret_val; - - udelay(1); - - if (hw->phy.autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on GG82563 phy.\n"); - - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - - if (!link) { - /* We didn't get link. - * Reset the DSP and cross our fingers. - */ - ret_val = e1000e_phy_reset_dsp(hw); - if (ret_val) - return ret_val; - } - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - } - - ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - /* Resetting the phy means we need to verify the TX_CLK corresponds - * to the link speed. 10Mbps -> 2.5MHz, else 25MHz. - */ - phy_data &= ~GG82563_MSCR_TX_CLK_MASK; - if (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED) - phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5; - else - phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25; - - /* In addition, we must re-enable CRS on Tx for both half and full - * duplex. - */ - phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; - ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data); - - return ret_val; -} - -/** - * e1000_get_cable_length_80003es2lan - Set approximate cable length - * @hw: pointer to the HW structure - * - * Find the approximate cable length as measured by the GG82563 PHY. - * This is a function pointer entry point called by the phy module. - **/ -static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, index; - - ret_val = e1e_rphy(hw, GG82563_PHY_DSP_DISTANCE, &phy_data); - if (ret_val) - return ret_val; - - index = phy_data & GG82563_DSPD_CABLE_LENGTH; - - if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5) - return -E1000_ERR_PHY; - - phy->min_cable_length = e1000_gg82563_cable_length_table[index]; - phy->max_cable_length = e1000_gg82563_cable_length_table[index + 5]; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - - return 0; -} - -/** - * e1000_get_link_up_info_80003es2lan - Report speed and duplex - * @hw: pointer to the HW structure - * @speed: pointer to speed buffer - * @duplex: pointer to duplex buffer - * - * Retrieve the current speed and duplex configuration. - **/ -static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, - u16 *duplex) -{ - s32 ret_val; - - if (hw->phy.media_type == e1000_media_type_copper) { - ret_val = e1000e_get_speed_and_duplex_copper(hw, speed, duplex); - hw->phy.ops.cfg_on_link_up(hw); - } else { - ret_val = e1000e_get_speed_and_duplex_fiber_serdes(hw, - speed, - duplex); - } - - return ret_val; -} - -/** - * e1000_reset_hw_80003es2lan - Reset the ESB2 controller - * @hw: pointer to the HW structure - * - * Perform a global reset to the ESB2 controller. - **/ -static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 kum_reg_data; - - /* Prevent the PCI-E bus from sticking if there is no TLP connection - * on the last TLP read/write transaction when MAC is reset. - */ - ret_val = e1000e_disable_pcie_master(hw); - if (ret_val) - e_dbg("PCI-E Master disable polling has failed.\n"); - - e_dbg("Masking off all interrupts\n"); - ew32(IMC, 0xffffffff); - - ew32(RCTL, 0); - ew32(TCTL, E1000_TCTL_PSP); - e1e_flush(); - - usleep_range(10000, 20000); - - ctrl = er32(CTRL); - - ret_val = e1000_acquire_phy_80003es2lan(hw); - if (ret_val) - return ret_val; - - e_dbg("Issuing a global reset to MAC\n"); - ew32(CTRL, ctrl | E1000_CTRL_RST); - e1000_release_phy_80003es2lan(hw); - - /* Disable IBIST slave mode (far-end loopback) */ - e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - &kum_reg_data); - kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; - e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - kum_reg_data); - - ret_val = e1000e_get_auto_rd_done(hw); - if (ret_val) - /* We don't want to continue accessing MAC registers. */ - return ret_val; - - /* Clear any pending interrupt events. */ - ew32(IMC, 0xffffffff); - er32(ICR); - - return e1000_check_alt_mac_addr_generic(hw); -} - -/** - * e1000_init_hw_80003es2lan - Initialize the ESB2 controller - * @hw: pointer to the HW structure - * - * Initialize the hw bits, LED, VFTA, MTA, link and hw counters. - **/ -static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 reg_data; - s32 ret_val; - u16 kum_reg_data; - u16 i; - - e1000_initialize_hw_bits_80003es2lan(hw); - - /* Initialize identification LED */ - ret_val = mac->ops.id_led_init(hw); - /* An error is not fatal and we should not stop init due to this */ - if (ret_val) - e_dbg("Error initializing identification LED\n"); - - /* Disabling VLAN filtering */ - e_dbg("Initializing the IEEE VLAN\n"); - mac->ops.clear_vfta(hw); - - /* Setup the receive address. */ - e1000e_init_rx_addrs(hw, mac->rar_entry_count); - - /* Zero out the Multicast HASH table */ - e_dbg("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - - /* Setup link and flow control */ - ret_val = mac->ops.setup_link(hw); - if (ret_val) - return ret_val; - - /* Disable IBIST slave mode (far-end loopback) */ - e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - &kum_reg_data); - kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; - e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - kum_reg_data); - - /* Set the transmit descriptor write-back policy */ - reg_data = er32(TXDCTL(0)); - reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC); - ew32(TXDCTL(0), reg_data); - - /* ...for both queues. */ - reg_data = er32(TXDCTL(1)); - reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC); - ew32(TXDCTL(1), reg_data); - - /* Enable retransmit on late collisions */ - reg_data = er32(TCTL); - reg_data |= E1000_TCTL_RTLC; - ew32(TCTL, reg_data); - - /* Configure Gigabit Carry Extend Padding */ - reg_data = er32(TCTL_EXT); - reg_data &= ~E1000_TCTL_EXT_GCEX_MASK; - reg_data |= DEFAULT_TCTL_EXT_GCEX_80003ES2LAN; - ew32(TCTL_EXT, reg_data); - - /* Configure Transmit Inter-Packet Gap */ - reg_data = er32(TIPG); - reg_data &= ~E1000_TIPG_IPGT_MASK; - reg_data |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; - ew32(TIPG, reg_data); - - reg_data = E1000_READ_REG_ARRAY(hw, E1000_FFLT, 0x0001); - reg_data &= ~0x00100000; - E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data); - - /* default to true to enable the MDIC W/A */ - hw->dev_spec.e80003es2lan.mdic_wa_enable = true; - - ret_val = - e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET >> - E1000_KMRNCTRLSTA_OFFSET_SHIFT, &i); - if (!ret_val) { - if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) == - E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO) - hw->dev_spec.e80003es2lan.mdic_wa_enable = false; - } - - /* Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs_80003es2lan(hw); - - return ret_val; -} - -/** - * e1000_initialize_hw_bits_80003es2lan - Init hw bits of ESB2 - * @hw: pointer to the HW structure - * - * Initializes required hardware-dependent bits needed for normal operation. - **/ -static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw) -{ - u32 reg; - - /* Transmit Descriptor Control 0 */ - reg = er32(TXDCTL(0)); - reg |= (1 << 22); - ew32(TXDCTL(0), reg); - - /* Transmit Descriptor Control 1 */ - reg = er32(TXDCTL(1)); - reg |= (1 << 22); - ew32(TXDCTL(1), reg); - - /* Transmit Arbitration Control 0 */ - reg = er32(TARC(0)); - reg &= ~(0xF << 27); /* 30:27 */ - if (hw->phy.media_type != e1000_media_type_copper) - reg &= ~(1 << 20); - ew32(TARC(0), reg); - - /* Transmit Arbitration Control 1 */ - reg = er32(TARC(1)); - if (er32(TCTL) & E1000_TCTL_MULR) - reg &= ~(1 << 28); - else - reg |= (1 << 28); - ew32(TARC(1), reg); - - /* Disable IPv6 extension header parsing because some malformed - * IPv6 headers can hang the Rx. - */ - reg = er32(RFCTL); - reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); - ew32(RFCTL, reg); -} - -/** - * e1000_copper_link_setup_gg82563_80003es2lan - Configure GG82563 Link - * @hw: pointer to the HW structure - * - * Setup some GG82563 PHY registers for obtaining link - **/ -static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u32 reg; - u16 data; - - ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &data); - if (ret_val) - return ret_val; - - data |= GG82563_MSCR_ASSERT_CRS_ON_TX; - /* Use 25MHz for both link down and 1000Base-T for Tx clock. */ - data |= GG82563_MSCR_TX_CLK_1000MBPS_25; - - ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, data); - if (ret_val) - return ret_val; - - /* Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL, &data); - if (ret_val) - return ret_val; - - data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK; - - switch (phy->mdix) { - case 1: - data |= GG82563_PSCR_CROSSOVER_MODE_MDI; - break; - case 2: - data |= GG82563_PSCR_CROSSOVER_MODE_MDIX; - break; - case 0: - default: - data |= GG82563_PSCR_CROSSOVER_MODE_AUTO; - break; - } - - /* Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE; - if (phy->disable_polarity_correction) - data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE; - - ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL, data); - if (ret_val) - return ret_val; - - /* SW Reset the PHY so all changes take effect */ - ret_val = hw->phy.ops.commit(hw); - if (ret_val) { - e_dbg("Error Resetting the PHY\n"); - return ret_val; - } - - /* Bypass Rx and Tx FIFO's */ - reg = E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL; - data = (E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS | - E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS); - ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data); - if (ret_val) - return ret_val; - - reg = E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE; - ret_val = e1000_read_kmrn_reg_80003es2lan(hw, reg, &data); - if (ret_val) - return ret_val; - data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE; - ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL_2, &data); - if (ret_val) - return ret_val; - - data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG; - ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL_2, data); - if (ret_val) - return ret_val; - - reg = er32(CTRL_EXT); - reg &= ~E1000_CTRL_EXT_LINK_MODE_MASK; - ew32(CTRL_EXT, reg); - - ret_val = e1e_rphy(hw, GG82563_PHY_PWR_MGMT_CTRL, &data); - if (ret_val) - return ret_val; - - /* Do not init these registers when the HW is in IAMT mode, since the - * firmware will have already initialized them. We only initialize - * them if the HW is not in IAMT mode. - */ - if (!hw->mac.ops.check_mng_mode(hw)) { - /* Enable Electrical Idle on the PHY */ - data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; - ret_val = e1e_wphy(hw, GG82563_PHY_PWR_MGMT_CTRL, data); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &data); - if (ret_val) - return ret_val; - - data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; - ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, data); - if (ret_val) - return ret_val; - } - - /* Workaround: Disable padding in Kumeran interface in the MAC - * and in the PHY to avoid CRC errors. - */ - ret_val = e1e_rphy(hw, GG82563_PHY_INBAND_CTRL, &data); - if (ret_val) - return ret_val; - - data |= GG82563_ICR_DIS_PADDING; - ret_val = e1e_wphy(hw, GG82563_PHY_INBAND_CTRL, data); - if (ret_val) - return ret_val; - - return 0; -} - -/** - * e1000_setup_copper_link_80003es2lan - Setup Copper Link for ESB2 - * @hw: pointer to the HW structure - * - * Essentially a wrapper for setting up all things "copper" related. - * This is a function pointer entry point called by the mac module. - **/ -static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 reg_data; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ew32(CTRL, ctrl); - - /* Set the mac to wait the maximum time between each - * iteration and increase the max iterations when - * polling the phy; this fixes erroneous timeouts at 10Mbps. - */ - ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4), - 0xFFFF); - if (ret_val) - return ret_val; - ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), - ®_data); - if (ret_val) - return ret_val; - reg_data |= 0x3F; - ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), - reg_data); - if (ret_val) - return ret_val; - ret_val = - e1000_read_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, - ®_data); - if (ret_val) - return ret_val; - reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING; - ret_val = - e1000_write_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, - reg_data); - if (ret_val) - return ret_val; - - ret_val = e1000_copper_link_setup_gg82563_80003es2lan(hw); - if (ret_val) - return ret_val; - - return e1000e_setup_copper_link(hw); -} - -/** - * e1000_cfg_on_link_up_80003es2lan - es2 link configuration after link-up - * @hw: pointer to the HW structure - * @duplex: current duplex setting - * - * Configure the KMRN interface by applying last minute quirks for - * 10/100 operation. - **/ -static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u16 speed; - u16 duplex; - - if (hw->phy.media_type == e1000_media_type_copper) { - ret_val = e1000e_get_speed_and_duplex_copper(hw, &speed, - &duplex); - if (ret_val) - return ret_val; - - if (speed == SPEED_1000) - ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw); - else - ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, duplex); - } - - return ret_val; -} - -/** - * e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation - * @hw: pointer to the HW structure - * @duplex: current duplex setting - * - * Configure the KMRN interface by applying last minute quirks for - * 10/100 operation. - **/ -static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex) -{ - s32 ret_val; - u32 tipg; - u32 i = 0; - u16 reg_data, reg_data2; - - reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT; - ret_val = - e1000_write_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, - reg_data); - if (ret_val) - return ret_val; - - /* Configure Transmit Inter-Packet Gap */ - tipg = er32(TIPG); - tipg &= ~E1000_TIPG_IPGT_MASK; - tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN; - ew32(TIPG, tipg); - - do { - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data2); - if (ret_val) - return ret_val; - i++; - } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); - - if (duplex == HALF_DUPLEX) - reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER; - else - reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; - - return e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); -} - -/** - * e1000_cfg_kmrn_1000_80003es2lan - Apply "quirks" for gigabit operation - * @hw: pointer to the HW structure - * - * Configure the KMRN interface by applying last minute quirks for - * gigabit operation. - **/ -static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val; - u16 reg_data, reg_data2; - u32 tipg; - u32 i = 0; - - reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT; - ret_val = - e1000_write_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, - reg_data); - if (ret_val) - return ret_val; - - /* Configure Transmit Inter-Packet Gap */ - tipg = er32(TIPG); - tipg &= ~E1000_TIPG_IPGT_MASK; - tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; - ew32(TIPG, tipg); - - do { - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data2); - if (ret_val) - return ret_val; - i++; - } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); - - reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; - - return e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); -} - -/** - * e1000_read_kmrn_reg_80003es2lan - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquire semaphore, then read the PHY register at offset - * using the kumeran interface. The information retrieved is stored in data. - * Release the semaphore before exiting. - **/ -static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, - u16 *data) -{ - u32 kmrnctrlsta; - s32 ret_val; - - ret_val = e1000_acquire_mac_csr_80003es2lan(hw); - if (ret_val) - return ret_val; - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; - ew32(KMRNCTRLSTA, kmrnctrlsta); - e1e_flush(); - - udelay(2); - - kmrnctrlsta = er32(KMRNCTRLSTA); - *data = (u16)kmrnctrlsta; - - e1000_release_mac_csr_80003es2lan(hw); - - return ret_val; -} - -/** - * e1000_write_kmrn_reg_80003es2lan - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquire semaphore, then write the data to PHY register - * at the offset using the kumeran interface. Release semaphore - * before exiting. - **/ -static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, - u16 data) -{ - u32 kmrnctrlsta; - s32 ret_val; - - ret_val = e1000_acquire_mac_csr_80003es2lan(hw); - if (ret_val) - return ret_val; - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | data; - ew32(KMRNCTRLSTA, kmrnctrlsta); - e1e_flush(); - - udelay(2); - - e1000_release_mac_csr_80003es2lan(hw); - - return ret_val; -} - -/** - * e1000_read_mac_addr_80003es2lan - Read device MAC address - * @hw: pointer to the HW structure - **/ -static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val; - - /* If there's an alternate MAC address place it in RAR0 - * so that it will override the Si installed default perm - * address. - */ - ret_val = e1000_check_alt_mac_addr_generic(hw); - if (ret_val) - return ret_val; - - return e1000_read_mac_addr_generic(hw); -} - -/** - * e1000_power_down_phy_copper_80003es2lan - Remove link during PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, remove the link. - **/ -static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw) -{ - /* If the management interface is not enabled, then power down */ - if (!(hw->mac.ops.check_mng_mode(hw) || - hw->phy.ops.check_reset_block(hw))) - e1000_power_down_phy_copper(hw); -} - -/** - * e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters - * @hw: pointer to the HW structure - * - * Clears the hardware counters by reading the counter registers. - **/ -static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw) -{ - e1000e_clear_hw_cntrs_base(hw); - - er32(PRC64); - er32(PRC127); - er32(PRC255); - er32(PRC511); - er32(PRC1023); - er32(PRC1522); - er32(PTC64); - er32(PTC127); - er32(PTC255); - er32(PTC511); - er32(PTC1023); - er32(PTC1522); - - er32(ALGNERRC); - er32(RXERRC); - er32(TNCRS); - er32(CEXTERR); - er32(TSCTC); - er32(TSCTFC); - - er32(MGTPRC); - er32(MGTPDC); - er32(MGTPTC); - - er32(IAC); - er32(ICRXOC); - - er32(ICRXPTC); - er32(ICRXATC); - er32(ICTXPTC); - er32(ICTXATC); - er32(ICTXQEC); - er32(ICTXQMTC); - er32(ICRXDMTC); -} - -static const struct e1000_mac_operations es2_mac_ops = { - .read_mac_addr = e1000_read_mac_addr_80003es2lan, - .id_led_init = e1000e_id_led_init_generic, - .blink_led = e1000e_blink_led_generic, - .check_mng_mode = e1000e_check_mng_mode_generic, - /* check_for_link dependent on media type */ - .cleanup_led = e1000e_cleanup_led_generic, - .clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan, - .get_bus_info = e1000e_get_bus_info_pcie, - .set_lan_id = e1000_set_lan_id_multi_port_pcie, - .get_link_up_info = e1000_get_link_up_info_80003es2lan, - .led_on = e1000e_led_on_generic, - .led_off = e1000e_led_off_generic, - .update_mc_addr_list = e1000e_update_mc_addr_list_generic, - .write_vfta = e1000_write_vfta_generic, - .clear_vfta = e1000_clear_vfta_generic, - .reset_hw = e1000_reset_hw_80003es2lan, - .init_hw = e1000_init_hw_80003es2lan, - .setup_link = e1000e_setup_link_generic, - /* setup_physical_interface dependent on media type */ - .setup_led = e1000e_setup_led_generic, - .config_collision_dist = e1000e_config_collision_dist_generic, - .rar_set = e1000e_rar_set_generic, -}; - -static const struct e1000_phy_operations es2_phy_ops = { - .acquire = e1000_acquire_phy_80003es2lan, - .check_polarity = e1000_check_polarity_m88, - .check_reset_block = e1000e_check_reset_block_generic, - .commit = e1000e_phy_sw_reset, - .force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan, - .get_cfg_done = e1000_get_cfg_done_80003es2lan, - .get_cable_length = e1000_get_cable_length_80003es2lan, - .get_info = e1000e_get_phy_info_m88, - .read_reg = e1000_read_phy_reg_gg82563_80003es2lan, - .release = e1000_release_phy_80003es2lan, - .reset = e1000e_phy_hw_reset_generic, - .set_d0_lplu_state = NULL, - .set_d3_lplu_state = e1000e_set_d3_lplu_state, - .write_reg = e1000_write_phy_reg_gg82563_80003es2lan, - .cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan, -}; - -static const struct e1000_nvm_operations es2_nvm_ops = { - .acquire = e1000_acquire_nvm_80003es2lan, - .read = e1000e_read_nvm_eerd, - .release = e1000_release_nvm_80003es2lan, - .reload = e1000e_reload_nvm_generic, - .update = e1000e_update_nvm_checksum_generic, - .valid_led_default = e1000e_valid_led_default, - .validate = e1000e_validate_nvm_checksum_generic, - .write = e1000_write_nvm_80003es2lan, -}; - -const struct e1000_info e1000_es2_info = { - .mac = e1000_80003es2lan, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_RX_NEEDS_RESTART /* errata */ - | FLAG_TARC_SET_BIT_ZERO /* errata */ - | FLAG_APME_CHECK_PORT_B - | FLAG_DISABLE_FC_PAUSE_TIME, /* errata */ - .flags2 = FLAG2_DMA_BURST, - .pba = 38, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_80003es2lan, - .mac_ops = &es2_mac_ops, - .phy_ops = &es2_phy_ops, - .nvm_ops = &es2_nvm_ops, -}; diff --git a/addons/e1000e/src/3.10.108/80003es2lan.h b/addons/e1000e/src/3.10.108/80003es2lan.h deleted file mode 100644 index 90d363b2..00000000 --- a/addons/e1000e/src/3.10.108/80003es2lan.h +++ /dev/null @@ -1,95 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#ifndef _E1000E_80003ES2LAN_H_ -#define _E1000E_80003ES2LAN_H_ - -#define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL 0x00 -#define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL 0x02 -#define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL 0x10 -#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE 0x1F - -#define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS 0x0008 -#define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS 0x0800 -#define E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING 0x0010 - -#define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004 -#define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000 -#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000 - -#define E1000_KMRNCTRLSTA_OPMODE_MASK 0x000C -#define E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO 0x0004 - -#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gig Carry Extend Padding */ -#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000 - -#define DEFAULT_TIPG_IPGT_1000_80003ES2LAN 0x8 -#define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN 0x9 - -/* GG82563 PHY Specific Status Register (Page 0, Register 16 */ -#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Reversal Dis */ -#define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060 -#define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI */ -#define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX */ -#define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Auto crossover */ - -/* PHY Specific Control Register 2 (Page 0, Register 26) */ -#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 /* 1=Reverse Auto-Neg */ - -/* MAC Specific Control Register (Page 2, Register 21) */ -/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */ -#define GG82563_MSCR_TX_CLK_MASK 0x0007 -#define GG82563_MSCR_TX_CLK_10MBPS_2_5 0x0004 -#define GG82563_MSCR_TX_CLK_100MBPS_25 0x0005 -#define GG82563_MSCR_TX_CLK_1000MBPS_25 0x0007 - -#define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */ - -/* DSP Distance Register (Page 5, Register 26) - * 0 = <50M - * 1 = 50-80M - * 2 = 80-100M - * 3 = 110-140M - * 4 = >140M - */ -#define GG82563_DSPD_CABLE_LENGTH 0x0007 - -/* Kumeran Mode Control Register (Page 193, Register 16) */ -#define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800 - -/* Max number of times Kumeran read/write should be validated */ -#define GG82563_MAX_KMRN_RETRY 0x5 - -/* Power Management Control Register (Page 193, Register 20) */ -/* 1=Enable SERDES Electrical Idle */ -#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001 - -/* In-Band Control Register (Page 194, Register 18) */ -#define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding */ - -#endif diff --git a/addons/e1000e/src/3.10.108/82571.c b/addons/e1000e/src/3.10.108/82571.c deleted file mode 100644 index 7380442a..00000000 --- a/addons/e1000e/src/3.10.108/82571.c +++ /dev/null @@ -1,2067 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* 82571EB Gigabit Ethernet Controller - * 82571EB Gigabit Ethernet Controller (Copper) - * 82571EB Gigabit Ethernet Controller (Fiber) - * 82571EB Dual Port Gigabit Mezzanine Adapter - * 82571EB Quad Port Gigabit Mezzanine Adapter - * 82571PT Gigabit PT Quad Port Server ExpressModule - * 82572EI Gigabit Ethernet Controller (Copper) - * 82572EI Gigabit Ethernet Controller (Fiber) - * 82572EI Gigabit Ethernet Controller - * 82573V Gigabit Ethernet Controller (Copper) - * 82573E Gigabit Ethernet Controller (Copper) - * 82573L Gigabit Ethernet Controller - * 82574L Gigabit Network Connection - * 82583V Gigabit Network Connection - */ - -#include "e1000.h" - -static s32 e1000_get_phy_id_82571(struct e1000_hw *hw); -static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw); -static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw); -static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw); -static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw); -static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw); -static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw); -static bool e1000_check_mng_mode_82574(struct e1000_hw *hw); -static s32 e1000_led_on_82574(struct e1000_hw *hw); -static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw); -static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw); -static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw); -static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw); -static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw); -static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active); -static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active); - -/** - * e1000_init_phy_params_82571 - Init PHY func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - - if (hw->phy.media_type != e1000_media_type_copper) { - phy->type = e1000_phy_none; - return 0; - } - - phy->addr = 1; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->reset_delay_us = 100; - - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_82571; - - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - phy->type = e1000_phy_igp_2; - break; - case e1000_82573: - phy->type = e1000_phy_m88; - break; - case e1000_82574: - case e1000_82583: - phy->type = e1000_phy_bm; - phy->ops.acquire = e1000_get_hw_semaphore_82574; - phy->ops.release = e1000_put_hw_semaphore_82574; - phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82574; - phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82574; - break; - default: - return -E1000_ERR_PHY; - break; - } - - /* This can only be done after all function pointers are setup. */ - ret_val = e1000_get_phy_id_82571(hw); - if (ret_val) { - e_dbg("Error getting PHY ID\n"); - return ret_val; - } - - /* Verify phy id */ - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - if (phy->id != IGP01E1000_I_PHY_ID) - ret_val = -E1000_ERR_PHY; - break; - case e1000_82573: - if (phy->id != M88E1111_I_PHY_ID) - ret_val = -E1000_ERR_PHY; - break; - case e1000_82574: - case e1000_82583: - if (phy->id != BME1000_E_PHY_ID_R2) - ret_val = -E1000_ERR_PHY; - break; - default: - ret_val = -E1000_ERR_PHY; - break; - } - - if (ret_val) - e_dbg("PHY ID unknown: type = 0x%08x\n", phy->id); - - return ret_val; -} - -/** - * e1000_init_nvm_params_82571 - Init NVM func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - u16 size; - - nvm->opcode_bits = 8; - nvm->delay_usec = 1; - switch (nvm->override) { - case e1000_nvm_override_spi_large: - nvm->page_size = 32; - nvm->address_bits = 16; - break; - case e1000_nvm_override_spi_small: - nvm->page_size = 8; - nvm->address_bits = 8; - break; - default: - nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; - nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; - break; - } - - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - if (((eecd >> 15) & 0x3) == 0x3) { - nvm->type = e1000_nvm_flash_hw; - nvm->word_size = 2048; - /* Autonomous Flash update bit must be cleared due - * to Flash update issue. - */ - eecd &= ~E1000_EECD_AUPDEN; - ew32(EECD, eecd); - break; - } - /* Fall Through */ - default: - nvm->type = e1000_nvm_eeprom_spi; - size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> - E1000_EECD_SIZE_EX_SHIFT); - /* Added to a constant, "size" becomes the left-shift value - * for setting word_size. - */ - size += NVM_WORD_SIZE_BASE_SHIFT; - - /* EEPROM access above 16k is unsupported */ - if (size > 14) - size = 14; - nvm->word_size = 1 << size; - break; - } - - /* Function Pointers */ - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - nvm->ops.acquire = e1000_get_hw_semaphore_82574; - nvm->ops.release = e1000_put_hw_semaphore_82574; - break; - default: - break; - } - - return 0; -} - -/** - * e1000_init_mac_params_82571 - Init MAC func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 swsm = 0; - u32 swsm2 = 0; - bool force_clear_smbi = false; - - /* Set media type and media-dependent function pointers */ - switch (hw->adapter->pdev->device) { - case E1000_DEV_ID_82571EB_FIBER: - case E1000_DEV_ID_82572EI_FIBER: - case E1000_DEV_ID_82571EB_QUAD_FIBER: - hw->phy.media_type = e1000_media_type_fiber; - mac->ops.setup_physical_interface = - e1000_setup_fiber_serdes_link_82571; - mac->ops.check_for_link = e1000e_check_for_fiber_link; - mac->ops.get_link_up_info = - e1000e_get_speed_and_duplex_fiber_serdes; - break; - case E1000_DEV_ID_82571EB_SERDES: - case E1000_DEV_ID_82571EB_SERDES_DUAL: - case E1000_DEV_ID_82571EB_SERDES_QUAD: - case E1000_DEV_ID_82572EI_SERDES: - hw->phy.media_type = e1000_media_type_internal_serdes; - mac->ops.setup_physical_interface = - e1000_setup_fiber_serdes_link_82571; - mac->ops.check_for_link = e1000_check_for_serdes_link_82571; - mac->ops.get_link_up_info = - e1000e_get_speed_and_duplex_fiber_serdes; - break; - default: - hw->phy.media_type = e1000_media_type_copper; - mac->ops.setup_physical_interface = - e1000_setup_copper_link_82571; - mac->ops.check_for_link = e1000e_check_for_copper_link; - mac->ops.get_link_up_info = e1000e_get_speed_and_duplex_copper; - break; - } - - /* Set mta register count */ - mac->mta_reg_count = 128; - /* Set rar entry count */ - mac->rar_entry_count = E1000_RAR_ENTRIES; - /* Adaptive IFS supported */ - mac->adaptive_ifs = true; - - /* MAC-specific function pointers */ - switch (hw->mac.type) { - case e1000_82573: - mac->ops.set_lan_id = e1000_set_lan_id_single_port; - mac->ops.check_mng_mode = e1000e_check_mng_mode_generic; - mac->ops.led_on = e1000e_led_on_generic; - mac->ops.blink_led = e1000e_blink_led_generic; - - /* FWSM register */ - mac->has_fwsm = true; - /* ARC supported; valid only if manageability features are - * enabled. - */ - mac->arc_subsystem_valid = !!(er32(FWSM) & - E1000_FWSM_MODE_MASK); - break; - case e1000_82574: - case e1000_82583: - mac->ops.set_lan_id = e1000_set_lan_id_single_port; - mac->ops.check_mng_mode = e1000_check_mng_mode_82574; - mac->ops.led_on = e1000_led_on_82574; - break; - default: - mac->ops.check_mng_mode = e1000e_check_mng_mode_generic; - mac->ops.led_on = e1000e_led_on_generic; - mac->ops.blink_led = e1000e_blink_led_generic; - - /* FWSM register */ - mac->has_fwsm = true; - break; - } - - /* Ensure that the inter-port SWSM.SMBI lock bit is clear before - * first NVM or PHY access. This should be done for single-port - * devices, and for one port only on dual-port devices so that - * for those devices we can still use the SMBI lock to synchronize - * inter-port accesses to the PHY & NVM. - */ - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - swsm2 = er32(SWSM2); - - if (!(swsm2 & E1000_SWSM2_LOCK)) { - /* Only do this for the first interface on this card */ - ew32(SWSM2, swsm2 | E1000_SWSM2_LOCK); - force_clear_smbi = true; - } else { - force_clear_smbi = false; - } - break; - default: - force_clear_smbi = true; - break; - } - - if (force_clear_smbi) { - /* Make sure SWSM.SMBI is clear */ - swsm = er32(SWSM); - if (swsm & E1000_SWSM_SMBI) { - /* This bit should not be set on a first interface, and - * indicates that the bootagent or EFI code has - * improperly left this bit enabled - */ - e_dbg("Please update your 82571 Bootagent\n"); - } - ew32(SWSM, swsm & ~E1000_SWSM_SMBI); - } - - /* Initialize device specific counter of SMBI acquisition timeouts. */ - hw->dev_spec.e82571.smb_counter = 0; - - return 0; -} - -static s32 e1000_get_variants_82571(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - static int global_quad_port_a; /* global port a indication */ - struct pci_dev *pdev = adapter->pdev; - int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1; - s32 rc; - - rc = e1000_init_mac_params_82571(hw); - if (rc) - return rc; - - rc = e1000_init_nvm_params_82571(hw); - if (rc) - return rc; - - rc = e1000_init_phy_params_82571(hw); - if (rc) - return rc; - - /* tag quad port adapters first, it's used below */ - switch (pdev->device) { - case E1000_DEV_ID_82571EB_QUAD_COPPER: - case E1000_DEV_ID_82571EB_QUAD_FIBER: - case E1000_DEV_ID_82571EB_QUAD_COPPER_LP: - case E1000_DEV_ID_82571PT_QUAD_COPPER: - adapter->flags |= FLAG_IS_QUAD_PORT; - /* mark the first port */ - if (global_quad_port_a == 0) - adapter->flags |= FLAG_IS_QUAD_PORT_A; - /* Reset for multiple quad port adapters */ - global_quad_port_a++; - if (global_quad_port_a == 4) - global_quad_port_a = 0; - break; - default: - break; - } - - switch (adapter->hw.mac.type) { - case e1000_82571: - /* these dual ports don't have WoL on port B at all */ - if (((pdev->device == E1000_DEV_ID_82571EB_FIBER) || - (pdev->device == E1000_DEV_ID_82571EB_SERDES) || - (pdev->device == E1000_DEV_ID_82571EB_COPPER)) && - (is_port_b)) - adapter->flags &= ~FLAG_HAS_WOL; - /* quad ports only support WoL on port A */ - if (adapter->flags & FLAG_IS_QUAD_PORT && - (!(adapter->flags & FLAG_IS_QUAD_PORT_A))) - adapter->flags &= ~FLAG_HAS_WOL; - /* Does not support WoL on any port */ - if (pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) - adapter->flags &= ~FLAG_HAS_WOL; - break; - case e1000_82573: - if (pdev->device == E1000_DEV_ID_82573L) { - adapter->flags |= FLAG_HAS_JUMBO_FRAMES; - adapter->max_hw_frame_size = DEFAULT_JUMBO; - } - break; - default: - break; - } - - return 0; -} - -/** - * e1000_get_phy_id_82571 - Retrieve the PHY ID and revision - * @hw: pointer to the HW structure - * - * Reads the PHY registers and stores the PHY ID and possibly the PHY - * revision in the hardware structure. - **/ -static s32 e1000_get_phy_id_82571(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_id = 0; - - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - /* The 82571 firmware may still be configuring the PHY. - * In this case, we cannot access the PHY until the - * configuration is done. So we explicitly set the - * PHY ID. - */ - phy->id = IGP01E1000_I_PHY_ID; - break; - case e1000_82573: - return e1000e_get_phy_id(hw); - break; - case e1000_82574: - case e1000_82583: - ret_val = e1e_rphy(hw, MII_PHYSID1, &phy_id); - if (ret_val) - return ret_val; - - phy->id = (u32)(phy_id << 16); - usleep_range(20, 40); - ret_val = e1e_rphy(hw, MII_PHYSID2, &phy_id); - if (ret_val) - return ret_val; - - phy->id |= (u32)(phy_id); - phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); - break; - default: - return -E1000_ERR_PHY; - break; - } - - return 0; -} - -/** - * e1000_get_hw_semaphore_82571 - Acquire hardware semaphore - * @hw: pointer to the HW structure - * - * Acquire the HW semaphore to access the PHY or NVM - **/ -static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) -{ - u32 swsm; - s32 sw_timeout = hw->nvm.word_size + 1; - s32 fw_timeout = hw->nvm.word_size + 1; - s32 i = 0; - - /* If we have timedout 3 times on trying to acquire - * the inter-port SMBI semaphore, there is old code - * operating on the other port, and it is not - * releasing SMBI. Modify the number of times that - * we try for the semaphore to interwork with this - * older code. - */ - if (hw->dev_spec.e82571.smb_counter > 2) - sw_timeout = 1; - - /* Get the SW semaphore */ - while (i < sw_timeout) { - swsm = er32(SWSM); - if (!(swsm & E1000_SWSM_SMBI)) - break; - - usleep_range(50, 100); - i++; - } - - if (i == sw_timeout) { - e_dbg("Driver can't access device - SMBI bit is set.\n"); - hw->dev_spec.e82571.smb_counter++; - } - /* Get the FW semaphore. */ - for (i = 0; i < fw_timeout; i++) { - swsm = er32(SWSM); - ew32(SWSM, swsm | E1000_SWSM_SWESMBI); - - /* Semaphore acquired if bit latched */ - if (er32(SWSM) & E1000_SWSM_SWESMBI) - break; - - usleep_range(50, 100); - } - - if (i == fw_timeout) { - /* Release semaphores */ - e1000_put_hw_semaphore_82571(hw); - e_dbg("Driver can't access the NVM\n"); - return -E1000_ERR_NVM; - } - - return 0; -} - -/** - * e1000_put_hw_semaphore_82571 - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used to access the PHY or NVM - **/ -static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw) -{ - u32 swsm; - - swsm = er32(SWSM); - swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); - ew32(SWSM, swsm); -} - -/** - * e1000_get_hw_semaphore_82573 - Acquire hardware semaphore - * @hw: pointer to the HW structure - * - * Acquire the HW semaphore during reset. - * - **/ -static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw) -{ - u32 extcnf_ctrl; - s32 i = 0; - - extcnf_ctrl = er32(EXTCNF_CTRL); - do { - extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; - ew32(EXTCNF_CTRL, extcnf_ctrl); - extcnf_ctrl = er32(EXTCNF_CTRL); - - if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP) - break; - - usleep_range(2000, 4000); - i++; - } while (i < MDIO_OWNERSHIP_TIMEOUT); - - if (i == MDIO_OWNERSHIP_TIMEOUT) { - /* Release semaphores */ - e1000_put_hw_semaphore_82573(hw); - e_dbg("Driver can't access the PHY\n"); - return -E1000_ERR_PHY; - } - - return 0; -} - -/** - * e1000_put_hw_semaphore_82573 - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used during reset. - * - **/ -static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw) -{ - u32 extcnf_ctrl; - - extcnf_ctrl = er32(EXTCNF_CTRL); - extcnf_ctrl &= ~E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; - ew32(EXTCNF_CTRL, extcnf_ctrl); -} - -static DEFINE_MUTEX(swflag_mutex); - -/** - * e1000_get_hw_semaphore_82574 - Acquire hardware semaphore - * @hw: pointer to the HW structure - * - * Acquire the HW semaphore to access the PHY or NVM. - * - **/ -static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw) -{ - s32 ret_val; - - mutex_lock(&swflag_mutex); - ret_val = e1000_get_hw_semaphore_82573(hw); - if (ret_val) - mutex_unlock(&swflag_mutex); - return ret_val; -} - -/** - * e1000_put_hw_semaphore_82574 - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used to access the PHY or NVM - * - **/ -static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw) -{ - e1000_put_hw_semaphore_82573(hw); - mutex_unlock(&swflag_mutex); -} - -/** - * e1000_set_d0_lplu_state_82574 - Set Low Power Linkup D0 state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU D0 state according to the active flag. - * LPLU will not be activated unless the - * device autonegotiation advertisement meets standards of - * either 10 or 10/100 or 10/100/1000 at all duplexes. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active) -{ - u32 data = er32(POEMB); - - if (active) - data |= E1000_PHY_CTRL_D0A_LPLU; - else - data &= ~E1000_PHY_CTRL_D0A_LPLU; - - ew32(POEMB, data); - return 0; -} - -/** - * e1000_set_d3_lplu_state_82574 - Sets low power link up state for D3 - * @hw: pointer to the HW structure - * @active: boolean used to enable/disable lplu - * - * The low power link up (lplu) state is set to the power management level D3 - * when active is true, else clear lplu for D3. LPLU - * is used during Dx states where the power conservation is most important. - * During driver activity, SmartSpeed should be enabled so performance is - * maintained. - **/ -static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active) -{ - u32 data = er32(POEMB); - - if (!active) { - data &= ~E1000_PHY_CTRL_NOND0A_LPLU; - } else if ((hw->phy.autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || - (hw->phy.autoneg_advertised == E1000_ALL_NOT_GIG) || - (hw->phy.autoneg_advertised == E1000_ALL_10_SPEED)) { - data |= E1000_PHY_CTRL_NOND0A_LPLU; - } - - ew32(POEMB, data); - return 0; -} - -/** - * e1000_acquire_nvm_82571 - Request for access to the EEPROM - * @hw: pointer to the HW structure - * - * To gain access to the EEPROM, first we must obtain a hardware semaphore. - * Then for non-82573 hardware, set the EEPROM access request bit and wait - * for EEPROM access grant bit. If the access grant bit is not set, release - * hardware semaphore. - **/ -static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw) -{ - s32 ret_val; - - ret_val = e1000_get_hw_semaphore_82571(hw); - if (ret_val) - return ret_val; - - switch (hw->mac.type) { - case e1000_82573: - break; - default: - ret_val = e1000e_acquire_nvm(hw); - break; - } - - if (ret_val) - e1000_put_hw_semaphore_82571(hw); - - return ret_val; -} - -/** - * e1000_release_nvm_82571 - Release exclusive access to EEPROM - * @hw: pointer to the HW structure - * - * Stop any current commands to the EEPROM and clear the EEPROM request bit. - **/ -static void e1000_release_nvm_82571(struct e1000_hw *hw) -{ - e1000e_release_nvm(hw); - e1000_put_hw_semaphore_82571(hw); -} - -/** - * e1000_write_nvm_82571 - Write to EEPROM using appropriate interface - * @hw: pointer to the HW structure - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the EEPROM - * - * For non-82573 silicon, write data to EEPROM at offset using SPI interface. - * - * If e1000e_update_nvm_checksum is not called after this function, the - * EEPROM will most likely contain an invalid checksum. - **/ -static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - s32 ret_val; - - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data); - break; - case e1000_82571: - case e1000_82572: - ret_val = e1000e_write_nvm_spi(hw, offset, words, data); - break; - default: - ret_val = -E1000_ERR_NVM; - break; - } - - return ret_val; -} - -/** - * e1000_update_nvm_checksum_82571 - Update EEPROM checksum - * @hw: pointer to the HW structure - * - * Updates the EEPROM checksum by reading/adding each word of the EEPROM - * up to the checksum. Then calculates the EEPROM checksum and writes the - * value to the EEPROM. - **/ -static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw) -{ - u32 eecd; - s32 ret_val; - u16 i; - - ret_val = e1000e_update_nvm_checksum_generic(hw); - if (ret_val) - return ret_val; - - /* If our nvm is an EEPROM, then we're done - * otherwise, commit the checksum to the flash NVM. - */ - if (hw->nvm.type != e1000_nvm_flash_hw) - return 0; - - /* Check for pending operations. */ - for (i = 0; i < E1000_FLASH_UPDATES; i++) { - usleep_range(1000, 2000); - if (!(er32(EECD) & E1000_EECD_FLUPD)) - break; - } - - if (i == E1000_FLASH_UPDATES) - return -E1000_ERR_NVM; - - /* Reset the firmware if using STM opcode. */ - if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) { - /* The enabling of and the actual reset must be done - * in two write cycles. - */ - ew32(HICR, E1000_HICR_FW_RESET_ENABLE); - e1e_flush(); - ew32(HICR, E1000_HICR_FW_RESET); - } - - /* Commit the write to flash */ - eecd = er32(EECD) | E1000_EECD_FLUPD; - ew32(EECD, eecd); - - for (i = 0; i < E1000_FLASH_UPDATES; i++) { - usleep_range(1000, 2000); - if (!(er32(EECD) & E1000_EECD_FLUPD)) - break; - } - - if (i == E1000_FLASH_UPDATES) - return -E1000_ERR_NVM; - - return 0; -} - -/** - * e1000_validate_nvm_checksum_82571 - Validate EEPROM checksum - * @hw: pointer to the HW structure - * - * Calculates the EEPROM checksum by reading/adding each word of the EEPROM - * and then verifies that the sum of the EEPROM is equal to 0xBABA. - **/ -static s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw) -{ - if (hw->nvm.type == e1000_nvm_flash_hw) - e1000_fix_nvm_checksum_82571(hw); - - return e1000e_validate_nvm_checksum_generic(hw); -} - -/** - * e1000_write_nvm_eewr_82571 - Write to EEPROM for 82573 silicon - * @hw: pointer to the HW structure - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the EEPROM - * - * After checking for invalid values, poll the EEPROM to ensure the previous - * command has completed before trying to write the next word. After write - * poll for completion. - * - * If e1000e_update_nvm_checksum is not called after this function, the - * EEPROM will most likely contain an invalid checksum. - **/ -static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 i, eewr = 0; - s32 ret_val = 0; - - /* A check for invalid values: offset too large, too many words, - * and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - return -E1000_ERR_NVM; - } - - for (i = 0; i < words; i++) { - eewr = ((data[i] << E1000_NVM_RW_REG_DATA) | - ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) | - E1000_NVM_RW_REG_START); - - ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); - if (ret_val) - break; - - ew32(EEWR, eewr); - - ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); - if (ret_val) - break; - } - - return ret_val; -} - -/** - * e1000_get_cfg_done_82571 - Poll for configuration done - * @hw: pointer to the HW structure - * - * Reads the management control register for the config done bit to be set. - **/ -static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw) -{ - s32 timeout = PHY_CFG_TIMEOUT; - - while (timeout) { - if (er32(EEMNGCTL) & E1000_NVM_CFG_DONE_PORT_0) - break; - usleep_range(1000, 2000); - timeout--; - } - if (!timeout) { - e_dbg("MNG configuration cycle has not completed.\n"); - return -E1000_ERR_RESET; - } - - return 0; -} - -/** - * e1000_set_d0_lplu_state_82571 - Set Low Power Linkup D0 state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU D0 state according to the active flag. When activating LPLU - * this function also disables smart speed and vice versa. LPLU will not be - * activated unless the device autonegotiation advertisement meets standards - * of either 10 or 10/100 or 10/100/1000 at all duplexes. This is a function - * pointer entry point only called by PHY setup routines. - **/ -static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - ret_val = e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &data); - if (ret_val) - return ret_val; - - if (active) { - data |= IGP02E1000_PM_D0_LPLU; - ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); - if (ret_val) - return ret_val; - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data); - if (ret_val) - return ret_val; - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data); - if (ret_val) - return ret_val; - } else { - data &= ~IGP02E1000_PM_D0_LPLU; - ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); - /* LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } - } - - return 0; -} - -/** - * e1000_reset_hw_82571 - Reset hardware - * @hw: pointer to the HW structure - * - * This resets the hardware into a known state. - **/ -static s32 e1000_reset_hw_82571(struct e1000_hw *hw) -{ - u32 ctrl, ctrl_ext, eecd, tctl; - s32 ret_val; - - /* Prevent the PCI-E bus from sticking if there is no TLP connection - * on the last TLP read/write transaction when MAC is reset. - */ - ret_val = e1000e_disable_pcie_master(hw); - if (ret_val) - e_dbg("PCI-E Master disable polling has failed.\n"); - - e_dbg("Masking off all interrupts\n"); - ew32(IMC, 0xffffffff); - - ew32(RCTL, 0); - tctl = er32(TCTL); - tctl &= ~E1000_TCTL_EN; - ew32(TCTL, tctl); - e1e_flush(); - - usleep_range(10000, 20000); - - /* Must acquire the MDIO ownership before MAC reset. - * Ownership defaults to firmware after a reset. - */ - switch (hw->mac.type) { - case e1000_82573: - ret_val = e1000_get_hw_semaphore_82573(hw); - break; - case e1000_82574: - case e1000_82583: - ret_val = e1000_get_hw_semaphore_82574(hw); - break; - default: - break; - } - if (ret_val) - e_dbg("Cannot acquire MDIO ownership\n"); - - ctrl = er32(CTRL); - - e_dbg("Issuing a global reset to MAC\n"); - ew32(CTRL, ctrl | E1000_CTRL_RST); - - /* Must release MDIO ownership and mutex after MAC reset. */ - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - e1000_put_hw_semaphore_82574(hw); - break; - default: - break; - } - - if (hw->nvm.type == e1000_nvm_flash_hw) { - usleep_range(10, 20); - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - ew32(CTRL_EXT, ctrl_ext); - e1e_flush(); - } - - ret_val = e1000e_get_auto_rd_done(hw); - if (ret_val) - /* We don't want to continue accessing MAC registers. */ - return ret_val; - - /* Phy configuration from NVM just starts after EECD_AUTO_RD is set. - * Need to wait for Phy configuration completion before accessing - * NVM and Phy. - */ - - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - /* REQ and GNT bits need to be cleared when using AUTO_RD - * to access the EEPROM. - */ - eecd = er32(EECD); - eecd &= ~(E1000_EECD_REQ | E1000_EECD_GNT); - ew32(EECD, eecd); - break; - case e1000_82573: - case e1000_82574: - case e1000_82583: - msleep(25); - break; - default: - break; - } - - /* Clear any pending interrupt events. */ - ew32(IMC, 0xffffffff); - er32(ICR); - - if (hw->mac.type == e1000_82571) { - /* Install any alternate MAC address into RAR0 */ - ret_val = e1000_check_alt_mac_addr_generic(hw); - if (ret_val) - return ret_val; - - e1000e_set_laa_state_82571(hw, true); - } - - /* Reinitialize the 82571 serdes link state machine */ - if (hw->phy.media_type == e1000_media_type_internal_serdes) - hw->mac.serdes_link_state = e1000_serdes_link_down; - - return 0; -} - -/** - * e1000_init_hw_82571 - Initialize hardware - * @hw: pointer to the HW structure - * - * This inits the hardware readying it for operation. - **/ -static s32 e1000_init_hw_82571(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 reg_data; - s32 ret_val; - u16 i, rar_count = mac->rar_entry_count; - - e1000_initialize_hw_bits_82571(hw); - - /* Initialize identification LED */ - ret_val = mac->ops.id_led_init(hw); - /* An error is not fatal and we should not stop init due to this */ - if (ret_val) - e_dbg("Error initializing identification LED\n"); - - /* Disabling VLAN filtering */ - e_dbg("Initializing the IEEE VLAN\n"); - mac->ops.clear_vfta(hw); - - /* Setup the receive address. - * If, however, a locally administered address was assigned to the - * 82571, we must reserve a RAR for it to work around an issue where - * resetting one port will reload the MAC on the other port. - */ - if (e1000e_get_laa_state_82571(hw)) - rar_count--; - e1000e_init_rx_addrs(hw, rar_count); - - /* Zero out the Multicast HASH table */ - e_dbg("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - - /* Setup link and flow control */ - ret_val = mac->ops.setup_link(hw); - - /* Set the transmit descriptor write-back policy */ - reg_data = er32(TXDCTL(0)); - reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC); - ew32(TXDCTL(0), reg_data); - - /* ...for both queues. */ - switch (mac->type) { - case e1000_82573: - e1000e_enable_tx_pkt_filtering(hw); - /* fall through */ - case e1000_82574: - case e1000_82583: - reg_data = er32(GCR); - reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX; - ew32(GCR, reg_data); - break; - default: - reg_data = er32(TXDCTL(1)); - reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB | - E1000_TXDCTL_COUNT_DESC); - ew32(TXDCTL(1), reg_data); - break; - } - - /* Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs_82571(hw); - - return ret_val; -} - -/** - * e1000_initialize_hw_bits_82571 - Initialize hardware-dependent bits - * @hw: pointer to the HW structure - * - * Initializes required hardware-dependent bits needed for normal operation. - **/ -static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) -{ - u32 reg; - - /* Transmit Descriptor Control 0 */ - reg = er32(TXDCTL(0)); - reg |= (1 << 22); - ew32(TXDCTL(0), reg); - - /* Transmit Descriptor Control 1 */ - reg = er32(TXDCTL(1)); - reg |= (1 << 22); - ew32(TXDCTL(1), reg); - - /* Transmit Arbitration Control 0 */ - reg = er32(TARC(0)); - reg &= ~(0xF << 27); /* 30:27 */ - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - reg |= (1 << 23) | (1 << 24) | (1 << 25) | (1 << 26); - break; - case e1000_82574: - case e1000_82583: - reg |= (1 << 26); - break; - default: - break; - } - ew32(TARC(0), reg); - - /* Transmit Arbitration Control 1 */ - reg = er32(TARC(1)); - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - reg &= ~((1 << 29) | (1 << 30)); - reg |= (1 << 22) | (1 << 24) | (1 << 25) | (1 << 26); - if (er32(TCTL) & E1000_TCTL_MULR) - reg &= ~(1 << 28); - else - reg |= (1 << 28); - ew32(TARC(1), reg); - break; - default: - break; - } - - /* Device Control */ - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - reg = er32(CTRL); - reg &= ~(1 << 29); - ew32(CTRL, reg); - break; - default: - break; - } - - /* Extended Device Control */ - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - reg = er32(CTRL_EXT); - reg &= ~(1 << 23); - reg |= (1 << 22); - ew32(CTRL_EXT, reg); - break; - default: - break; - } - - if (hw->mac.type == e1000_82571) { - reg = er32(PBA_ECC); - reg |= E1000_PBA_ECC_CORR_EN; - ew32(PBA_ECC, reg); - } - - /* Workaround for hardware errata. - * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572 - */ - if ((hw->mac.type == e1000_82571) || (hw->mac.type == e1000_82572)) { - reg = er32(CTRL_EXT); - reg &= ~E1000_CTRL_EXT_DMA_DYN_CLK_EN; - ew32(CTRL_EXT, reg); - } - - /* Disable IPv6 extension header parsing because some malformed - * IPv6 headers can hang the Rx. - */ - if (hw->mac.type <= e1000_82573) { - reg = er32(RFCTL); - reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); - ew32(RFCTL, reg); - } - - /* PCI-Ex Control Registers */ - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - reg = er32(GCR); - reg |= (1 << 22); - ew32(GCR, reg); - - /* Workaround for hardware errata. - * apply workaround for hardware errata documented in errata - * docs Fixes issue where some error prone or unreliable PCIe - * completions are occurring, particularly with ASPM enabled. - * Without fix, issue can cause Tx timeouts. - */ - reg = er32(GCR2); - reg |= 1; - ew32(GCR2, reg); - break; - default: - break; - } -} - -/** - * e1000_clear_vfta_82571 - Clear VLAN filter table - * @hw: pointer to the HW structure - * - * Clears the register array which contains the VLAN filter table by - * setting all the values to 0. - **/ -static void e1000_clear_vfta_82571(struct e1000_hw *hw) -{ - u32 offset; - u32 vfta_value = 0; - u32 vfta_offset = 0; - u32 vfta_bit_in_reg = 0; - - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - if (hw->mng_cookie.vlan_id != 0) { - /* The VFTA is a 4096b bit-field, each identifying - * a single VLAN ID. The following operations - * determine which 32b entry (i.e. offset) into the - * array we want to set the VLAN ID (i.e. bit) of - * the manageability unit. - */ - vfta_offset = (hw->mng_cookie.vlan_id >> - E1000_VFTA_ENTRY_SHIFT) & - E1000_VFTA_ENTRY_MASK; - vfta_bit_in_reg = - 1 << (hw->mng_cookie.vlan_id & - E1000_VFTA_ENTRY_BIT_SHIFT_MASK); - } - break; - default: - break; - } - for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { - /* If the offset we want to clear is the same offset of the - * manageability VLAN ID, then clear all bits except that of - * the manageability unit. - */ - vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0; - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, vfta_value); - e1e_flush(); - } -} - -/** - * e1000_check_mng_mode_82574 - Check manageability is enabled - * @hw: pointer to the HW structure - * - * Reads the NVM Initialization Control Word 2 and returns true - * (>0) if any manageability is enabled, else false (0). - **/ -static bool e1000_check_mng_mode_82574(struct e1000_hw *hw) -{ - u16 data; - - e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data); - return (data & E1000_NVM_INIT_CTRL2_MNGM) != 0; -} - -/** - * e1000_led_on_82574 - Turn LED on - * @hw: pointer to the HW structure - * - * Turn LED on. - **/ -static s32 e1000_led_on_82574(struct e1000_hw *hw) -{ - u32 ctrl; - u32 i; - - ctrl = hw->mac.ledctl_mode2; - if (!(E1000_STATUS_LU & er32(STATUS))) { - /* If no link, then turn LED on by setting the invert bit - * for each LED that's "on" (0x0E) in ledctl_mode2. - */ - for (i = 0; i < 4; i++) - if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == - E1000_LEDCTL_MODE_LED_ON) - ctrl |= (E1000_LEDCTL_LED0_IVRT << (i * 8)); - } - ew32(LEDCTL, ctrl); - - return 0; -} - -/** - * e1000_check_phy_82574 - check 82574 phy hung state - * @hw: pointer to the HW structure - * - * Returns whether phy is hung or not - **/ -bool e1000_check_phy_82574(struct e1000_hw *hw) -{ - u16 status_1kbt = 0; - u16 receive_errors = 0; - s32 ret_val; - - /* Read PHY Receive Error counter first, if its is max - all F's then - * read the Base1000T status register If both are max then PHY is hung. - */ - ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors); - if (ret_val) - return false; - if (receive_errors == E1000_RECEIVE_ERROR_MAX) { - ret_val = e1e_rphy(hw, E1000_BASE1000T_STATUS, &status_1kbt); - if (ret_val) - return false; - if ((status_1kbt & E1000_IDLE_ERROR_COUNT_MASK) == - E1000_IDLE_ERROR_COUNT_MASK) - return true; - } - - return false; -} - -/** - * e1000_setup_link_82571 - Setup flow control and link settings - * @hw: pointer to the HW structure - * - * Determines which flow control settings to use, then configures flow - * control. Calls the appropriate media-specific link configuration - * function. Assuming the adapter has a valid link partner, a valid link - * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. - **/ -static s32 e1000_setup_link_82571(struct e1000_hw *hw) -{ - /* 82573 does not have a word in the NVM to determine - * the default flow control setting, so we explicitly - * set it to full. - */ - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - if (hw->fc.requested_mode == e1000_fc_default) - hw->fc.requested_mode = e1000_fc_full; - break; - default: - break; - } - - return e1000e_setup_link_generic(hw); -} - -/** - * e1000_setup_copper_link_82571 - Configure copper link settings - * @hw: pointer to the HW structure - * - * Configures the link for auto-neg or forced speed and duplex. Then we check - * for link, once link is established calls to configure collision distance - * and flow control are called. - **/ -static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ew32(CTRL, ctrl); - - switch (hw->phy.type) { - case e1000_phy_m88: - case e1000_phy_bm: - ret_val = e1000e_copper_link_setup_m88(hw); - break; - case e1000_phy_igp_2: - ret_val = e1000e_copper_link_setup_igp(hw); - break; - default: - return -E1000_ERR_PHY; - break; - } - - if (ret_val) - return ret_val; - - return e1000e_setup_copper_link(hw); -} - -/** - * e1000_setup_fiber_serdes_link_82571 - Setup link for fiber/serdes - * @hw: pointer to the HW structure - * - * Configures collision distance and flow control for fiber and serdes links. - * Upon successful setup, poll for link. - **/ -static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw) -{ - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - /* If SerDes loopback mode is entered, there is no form - * of reset to take the adapter out of that mode. So we - * have to explicitly take the adapter out of loopback - * mode. This prevents drivers from twiddling their thumbs - * if another tool failed to take it out of loopback mode. - */ - ew32(SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); - break; - default: - break; - } - - return e1000e_setup_fiber_serdes_link(hw); -} - -/** - * e1000_check_for_serdes_link_82571 - Check for link (Serdes) - * @hw: pointer to the HW structure - * - * Reports the link state as up or down. - * - * If autonegotiation is supported by the link partner, the link state is - * determined by the result of autonegotiation. This is the most likely case. - * If autonegotiation is not supported by the link partner, and the link - * has a valid signal, force the link up. - * - * The link state is represented internally here by 4 states: - * - * 1) down - * 2) autoneg_progress - * 3) autoneg_complete (the link successfully autonegotiated) - * 4) forced_up (the link has been forced up, it did not autonegotiate) - * - **/ -static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw; - u32 ctrl; - u32 status; - u32 txcw; - u32 i; - s32 ret_val = 0; - - ctrl = er32(CTRL); - status = er32(STATUS); - er32(RXCW); - /* SYNCH bit and IV bit are sticky */ - usleep_range(10, 20); - rxcw = er32(RXCW); - - if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) { - /* Receiver is synchronized with no invalid bits. */ - switch (mac->serdes_link_state) { - case e1000_serdes_link_autoneg_complete: - if (!(status & E1000_STATUS_LU)) { - /* We have lost link, retry autoneg before - * reporting link failure - */ - mac->serdes_link_state = - e1000_serdes_link_autoneg_progress; - mac->serdes_has_link = false; - e_dbg("AN_UP -> AN_PROG\n"); - } else { - mac->serdes_has_link = true; - } - break; - - case e1000_serdes_link_forced_up: - /* If we are receiving /C/ ordered sets, re-enable - * auto-negotiation in the TXCW register and disable - * forced link in the Device Control register in an - * attempt to auto-negotiate with our link partner. - */ - if (rxcw & E1000_RXCW_C) { - /* Enable autoneg, and unforce link up */ - ew32(TXCW, mac->txcw); - ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - mac->serdes_link_state = - e1000_serdes_link_autoneg_progress; - mac->serdes_has_link = false; - e_dbg("FORCED_UP -> AN_PROG\n"); - } else { - mac->serdes_has_link = true; - } - break; - - case e1000_serdes_link_autoneg_progress: - if (rxcw & E1000_RXCW_C) { - /* We received /C/ ordered sets, meaning the - * link partner has autonegotiated, and we can - * trust the Link Up (LU) status bit. - */ - if (status & E1000_STATUS_LU) { - mac->serdes_link_state = - e1000_serdes_link_autoneg_complete; - e_dbg("AN_PROG -> AN_UP\n"); - mac->serdes_has_link = true; - } else { - /* Autoneg completed, but failed. */ - mac->serdes_link_state = - e1000_serdes_link_down; - e_dbg("AN_PROG -> DOWN\n"); - } - } else { - /* The link partner did not autoneg. - * Force link up and full duplex, and change - * state to forced. - */ - ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - ew32(CTRL, ctrl); - - /* Configure Flow Control after link up. */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error config flow control\n"); - break; - } - mac->serdes_link_state = - e1000_serdes_link_forced_up; - mac->serdes_has_link = true; - e_dbg("AN_PROG -> FORCED_UP\n"); - } - break; - - case e1000_serdes_link_down: - default: - /* The link was down but the receiver has now gained - * valid sync, so lets see if we can bring the link - * up. - */ - ew32(TXCW, mac->txcw); - ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - mac->serdes_link_state = - e1000_serdes_link_autoneg_progress; - mac->serdes_has_link = false; - e_dbg("DOWN -> AN_PROG\n"); - break; - } - } else { - if (!(rxcw & E1000_RXCW_SYNCH)) { - mac->serdes_has_link = false; - mac->serdes_link_state = e1000_serdes_link_down; - e_dbg("ANYSTATE -> DOWN\n"); - } else { - /* Check several times, if SYNCH bit and CONFIG - * bit both are consistently 1 then simply ignore - * the IV bit and restart Autoneg - */ - for (i = 0; i < AN_RETRY_COUNT; i++) { - usleep_range(10, 20); - rxcw = er32(RXCW); - if ((rxcw & E1000_RXCW_SYNCH) && - (rxcw & E1000_RXCW_C)) - continue; - - if (rxcw & E1000_RXCW_IV) { - mac->serdes_has_link = false; - mac->serdes_link_state = - e1000_serdes_link_down; - e_dbg("ANYSTATE -> DOWN\n"); - break; - } - } - - if (i == AN_RETRY_COUNT) { - txcw = er32(TXCW); - txcw |= E1000_TXCW_ANE; - ew32(TXCW, txcw); - mac->serdes_link_state = - e1000_serdes_link_autoneg_progress; - mac->serdes_has_link = false; - e_dbg("ANYSTATE -> AN_PROG\n"); - } - } - } - - return ret_val; -} - -/** - * e1000_valid_led_default_82571 - Verify a valid default LED config - * @hw: pointer to the HW structure - * @data: pointer to the NVM (EEPROM) - * - * Read the EEPROM for the current default LED configuration. If the - * LED configuration is not valid, set to a valid LED configuration. - **/ -static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data) -{ - s32 ret_val; - - ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - if (*data == ID_LED_RESERVED_F746) - *data = ID_LED_DEFAULT_82573; - break; - default: - if (*data == ID_LED_RESERVED_0000 || - *data == ID_LED_RESERVED_FFFF) - *data = ID_LED_DEFAULT; - break; - } - - return 0; -} - -/** - * e1000e_get_laa_state_82571 - Get locally administered address state - * @hw: pointer to the HW structure - * - * Retrieve and return the current locally administered address state. - **/ -bool e1000e_get_laa_state_82571(struct e1000_hw *hw) -{ - if (hw->mac.type != e1000_82571) - return false; - - return hw->dev_spec.e82571.laa_is_present; -} - -/** - * e1000e_set_laa_state_82571 - Set locally administered address state - * @hw: pointer to the HW structure - * @state: enable/disable locally administered address - * - * Enable/Disable the current locally administered address state. - **/ -void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state) -{ - if (hw->mac.type != e1000_82571) - return; - - hw->dev_spec.e82571.laa_is_present = state; - - /* If workaround is activated... */ - if (state) - /* Hold a copy of the LAA in RAR[14] This is done so that - * between the time RAR[0] gets clobbered and the time it - * gets fixed, the actual LAA is in one of the RARs and no - * incoming packets directed to this port are dropped. - * Eventually the LAA will be in RAR[0] and RAR[14]. - */ - hw->mac.ops.rar_set(hw, hw->mac.addr, - hw->mac.rar_entry_count - 1); -} - -/** - * e1000_fix_nvm_checksum_82571 - Fix EEPROM checksum - * @hw: pointer to the HW structure - * - * Verifies that the EEPROM has completed the update. After updating the - * EEPROM, we need to check bit 15 in work 0x23 for the checksum fix. If - * the checksum fix is not implemented, we need to set the bit and update - * the checksum. Otherwise, if bit 15 is set and the checksum is incorrect, - * we need to return bad checksum. - **/ -static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val; - u16 data; - - if (nvm->type != e1000_nvm_flash_hw) - return 0; - - /* Check bit 4 of word 10h. If it is 0, firmware is done updating - * 10h-12h. Checksum may need to be fixed. - */ - ret_val = e1000_read_nvm(hw, 0x10, 1, &data); - if (ret_val) - return ret_val; - - if (!(data & 0x10)) { - /* Read 0x23 and check bit 15. This bit is a 1 - * when the checksum has already been fixed. If - * the checksum is still wrong and this bit is a - * 1, we need to return bad checksum. Otherwise, - * we need to set this bit to a 1 and update the - * checksum. - */ - ret_val = e1000_read_nvm(hw, 0x23, 1, &data); - if (ret_val) - return ret_val; - - if (!(data & 0x8000)) { - data |= 0x8000; - ret_val = e1000_write_nvm(hw, 0x23, 1, &data); - if (ret_val) - return ret_val; - ret_val = e1000e_update_nvm_checksum(hw); - if (ret_val) - return ret_val; - } - } - - return 0; -} - -/** - * e1000_read_mac_addr_82571 - Read device MAC address - * @hw: pointer to the HW structure - **/ -static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw) -{ - if (hw->mac.type == e1000_82571) { - s32 ret_val; - - /* If there's an alternate MAC address place it in RAR0 - * so that it will override the Si installed default perm - * address. - */ - ret_val = e1000_check_alt_mac_addr_generic(hw); - if (ret_val) - return ret_val; - } - - return e1000_read_mac_addr_generic(hw); -} - -/** - * e1000_power_down_phy_copper_82571 - Remove link during PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, remove the link. - **/ -static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - struct e1000_mac_info *mac = &hw->mac; - - if (!phy->ops.check_reset_block) - return; - - /* If the management interface is not enabled, then power down */ - if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw))) - e1000_power_down_phy_copper(hw); -} - -/** - * e1000_clear_hw_cntrs_82571 - Clear device specific hardware counters - * @hw: pointer to the HW structure - * - * Clears the hardware counters by reading the counter registers. - **/ -static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw) -{ - e1000e_clear_hw_cntrs_base(hw); - - er32(PRC64); - er32(PRC127); - er32(PRC255); - er32(PRC511); - er32(PRC1023); - er32(PRC1522); - er32(PTC64); - er32(PTC127); - er32(PTC255); - er32(PTC511); - er32(PTC1023); - er32(PTC1522); - - er32(ALGNERRC); - er32(RXERRC); - er32(TNCRS); - er32(CEXTERR); - er32(TSCTC); - er32(TSCTFC); - - er32(MGTPRC); - er32(MGTPDC); - er32(MGTPTC); - - er32(IAC); - er32(ICRXOC); - - er32(ICRXPTC); - er32(ICRXATC); - er32(ICTXPTC); - er32(ICTXATC); - er32(ICTXQEC); - er32(ICTXQMTC); - er32(ICRXDMTC); -} - -static const struct e1000_mac_operations e82571_mac_ops = { - /* .check_mng_mode: mac type dependent */ - /* .check_for_link: media type dependent */ - .id_led_init = e1000e_id_led_init_generic, - .cleanup_led = e1000e_cleanup_led_generic, - .clear_hw_cntrs = e1000_clear_hw_cntrs_82571, - .get_bus_info = e1000e_get_bus_info_pcie, - .set_lan_id = e1000_set_lan_id_multi_port_pcie, - /* .get_link_up_info: media type dependent */ - /* .led_on: mac type dependent */ - .led_off = e1000e_led_off_generic, - .update_mc_addr_list = e1000e_update_mc_addr_list_generic, - .write_vfta = e1000_write_vfta_generic, - .clear_vfta = e1000_clear_vfta_82571, - .reset_hw = e1000_reset_hw_82571, - .init_hw = e1000_init_hw_82571, - .setup_link = e1000_setup_link_82571, - /* .setup_physical_interface: media type dependent */ - .setup_led = e1000e_setup_led_generic, - .config_collision_dist = e1000e_config_collision_dist_generic, - .read_mac_addr = e1000_read_mac_addr_82571, - .rar_set = e1000e_rar_set_generic, -}; - -static const struct e1000_phy_operations e82_phy_ops_igp = { - .acquire = e1000_get_hw_semaphore_82571, - .check_polarity = e1000_check_polarity_igp, - .check_reset_block = e1000e_check_reset_block_generic, - .commit = NULL, - .force_speed_duplex = e1000e_phy_force_speed_duplex_igp, - .get_cfg_done = e1000_get_cfg_done_82571, - .get_cable_length = e1000e_get_cable_length_igp_2, - .get_info = e1000e_get_phy_info_igp, - .read_reg = e1000e_read_phy_reg_igp, - .release = e1000_put_hw_semaphore_82571, - .reset = e1000e_phy_hw_reset_generic, - .set_d0_lplu_state = e1000_set_d0_lplu_state_82571, - .set_d3_lplu_state = e1000e_set_d3_lplu_state, - .write_reg = e1000e_write_phy_reg_igp, - .cfg_on_link_up = NULL, -}; - -static const struct e1000_phy_operations e82_phy_ops_m88 = { - .acquire = e1000_get_hw_semaphore_82571, - .check_polarity = e1000_check_polarity_m88, - .check_reset_block = e1000e_check_reset_block_generic, - .commit = e1000e_phy_sw_reset, - .force_speed_duplex = e1000e_phy_force_speed_duplex_m88, - .get_cfg_done = e1000e_get_cfg_done_generic, - .get_cable_length = e1000e_get_cable_length_m88, - .get_info = e1000e_get_phy_info_m88, - .read_reg = e1000e_read_phy_reg_m88, - .release = e1000_put_hw_semaphore_82571, - .reset = e1000e_phy_hw_reset_generic, - .set_d0_lplu_state = e1000_set_d0_lplu_state_82571, - .set_d3_lplu_state = e1000e_set_d3_lplu_state, - .write_reg = e1000e_write_phy_reg_m88, - .cfg_on_link_up = NULL, -}; - -static const struct e1000_phy_operations e82_phy_ops_bm = { - .acquire = e1000_get_hw_semaphore_82571, - .check_polarity = e1000_check_polarity_m88, - .check_reset_block = e1000e_check_reset_block_generic, - .commit = e1000e_phy_sw_reset, - .force_speed_duplex = e1000e_phy_force_speed_duplex_m88, - .get_cfg_done = e1000e_get_cfg_done_generic, - .get_cable_length = e1000e_get_cable_length_m88, - .get_info = e1000e_get_phy_info_m88, - .read_reg = e1000e_read_phy_reg_bm2, - .release = e1000_put_hw_semaphore_82571, - .reset = e1000e_phy_hw_reset_generic, - .set_d0_lplu_state = e1000_set_d0_lplu_state_82571, - .set_d3_lplu_state = e1000e_set_d3_lplu_state, - .write_reg = e1000e_write_phy_reg_bm2, - .cfg_on_link_up = NULL, -}; - -static const struct e1000_nvm_operations e82571_nvm_ops = { - .acquire = e1000_acquire_nvm_82571, - .read = e1000e_read_nvm_eerd, - .release = e1000_release_nvm_82571, - .reload = e1000e_reload_nvm_generic, - .update = e1000_update_nvm_checksum_82571, - .valid_led_default = e1000_valid_led_default_82571, - .validate = e1000_validate_nvm_checksum_82571, - .write = e1000_write_nvm_82571, -}; - -const struct e1000_info e1000_82571_info = { - .mac = e1000_82571, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_SMART_POWER_DOWN - | FLAG_RESET_OVERWRITES_LAA /* errata */ - | FLAG_TARC_SPEED_MODE_BIT /* errata */ - | FLAG_APME_CHECK_PORT_B, - .flags2 = FLAG2_DISABLE_ASPM_L1 /* errata 13 */ - | FLAG2_DMA_BURST, - .pba = 38, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_82571, - .mac_ops = &e82571_mac_ops, - .phy_ops = &e82_phy_ops_igp, - .nvm_ops = &e82571_nvm_ops, -}; - -const struct e1000_info e1000_82572_info = { - .mac = e1000_82572, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_TARC_SPEED_MODE_BIT, /* errata */ - .flags2 = FLAG2_DISABLE_ASPM_L1 /* errata 13 */ - | FLAG2_DMA_BURST, - .pba = 38, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_82571, - .mac_ops = &e82571_mac_ops, - .phy_ops = &e82_phy_ops_igp, - .nvm_ops = &e82571_nvm_ops, -}; - -const struct e1000_info e1000_82573_info = { - .mac = e1000_82573, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_HAS_SMART_POWER_DOWN - | FLAG_HAS_AMT - | FLAG_HAS_SWSM_ON_LOAD, - .flags2 = FLAG2_DISABLE_ASPM_L1 - | FLAG2_DISABLE_ASPM_L0S, - .pba = 20, - .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, - .get_variants = e1000_get_variants_82571, - .mac_ops = &e82571_mac_ops, - .phy_ops = &e82_phy_ops_m88, - .nvm_ops = &e82571_nvm_ops, -}; - -const struct e1000_info e1000_82574_info = { - .mac = e1000_82574, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_MSIX - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_WOL - | FLAG_HAS_HW_TIMESTAMP - | FLAG_APME_IN_CTRL3 - | FLAG_HAS_SMART_POWER_DOWN - | FLAG_HAS_AMT - | FLAG_HAS_CTRLEXT_ON_LOAD, - .flags2 = FLAG2_CHECK_PHY_HANG - | FLAG2_DISABLE_ASPM_L0S - | FLAG2_DISABLE_ASPM_L1 - | FLAG2_NO_DISABLE_RX - | FLAG2_DMA_BURST, - .pba = 32, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_82571, - .mac_ops = &e82571_mac_ops, - .phy_ops = &e82_phy_ops_bm, - .nvm_ops = &e82571_nvm_ops, -}; - -const struct e1000_info e1000_82583_info = { - .mac = e1000_82583, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_WOL - | FLAG_HAS_HW_TIMESTAMP - | FLAG_APME_IN_CTRL3 - | FLAG_HAS_SMART_POWER_DOWN - | FLAG_HAS_AMT - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_CTRLEXT_ON_LOAD, - .flags2 = FLAG2_DISABLE_ASPM_L0S - | FLAG2_NO_DISABLE_RX, - .pba = 32, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_82571, - .mac_ops = &e82571_mac_ops, - .phy_ops = &e82_phy_ops_bm, - .nvm_ops = &e82571_nvm_ops, -}; diff --git a/addons/e1000e/src/3.10.108/82571.h b/addons/e1000e/src/3.10.108/82571.h deleted file mode 100644 index 08e24dc3..00000000 --- a/addons/e1000e/src/3.10.108/82571.h +++ /dev/null @@ -1,60 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#ifndef _E1000E_82571_H_ -#define _E1000E_82571_H_ - -#define ID_LED_RESERVED_F746 0xF746 -#define ID_LED_DEFAULT_82573 ((ID_LED_DEF1_DEF2 << 12) | \ - (ID_LED_OFF1_ON2 << 8) | \ - (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_DEF1_DEF2)) - -#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 -#define AN_RETRY_COUNT 5 /* Autoneg Retry Count value */ - -/* Intr Throttling - RW */ -#define E1000_EITR_82574(_n) (0x000E8 + (0x4 * (_n))) - -#define E1000_EIAC_82574 0x000DC /* Ext. Interrupt Auto Clear - RW */ -#define E1000_EIAC_MASK_82574 0x01F00000 - -#define E1000_IVAR_INT_ALLOC_VALID 0x8 - -/* Manageability Operation Mode mask */ -#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 - -#define E1000_BASE1000T_STATUS 10 -#define E1000_IDLE_ERROR_COUNT_MASK 0xFF -#define E1000_RECEIVE_ERROR_COUNTER 21 -#define E1000_RECEIVE_ERROR_MAX 0xFFFF -bool e1000_check_phy_82574(struct e1000_hw *hw); -bool e1000e_get_laa_state_82571(struct e1000_hw *hw); -void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state); - -#endif diff --git a/addons/e1000e/src/3.10.108/Makefile b/addons/e1000e/src/3.10.108/Makefile deleted file mode 100644 index 9393a936..00000000 --- a/addons/e1000e/src/3.10.108/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-m += e1000e.o -e1000e-objs := 82571.o ich8lan.o 80003es2lan.o \ - mac.o manage.o nvm.o phy.o \ - param.o ethtool.o netdev.o ptp.o - diff --git a/addons/e1000e/src/3.10.108/defines.h b/addons/e1000e/src/3.10.108/defines.h deleted file mode 100644 index 351c94a0..00000000 --- a/addons/e1000e/src/3.10.108/defines.h +++ /dev/null @@ -1,803 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#ifndef _E1000_DEFINES_H_ -#define _E1000_DEFINES_H_ - -/* Number of Transmit and Receive Descriptors must be a multiple of 8 */ -#define REQ_TX_DESCRIPTOR_MULTIPLE 8 -#define REQ_RX_DESCRIPTOR_MULTIPLE 8 - -/* Definitions for power management and wakeup registers */ -/* Wake Up Control */ -#define E1000_WUC_APME 0x00000001 /* APM Enable */ -#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ -#define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */ - -/* Wake Up Filter Control */ -#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ -#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ -#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ -#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ -#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ -#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ - -/* Wake Up Status */ -#define E1000_WUS_LNKC E1000_WUFC_LNKC -#define E1000_WUS_MAG E1000_WUFC_MAG -#define E1000_WUS_EX E1000_WUFC_EX -#define E1000_WUS_MC E1000_WUFC_MC -#define E1000_WUS_BC E1000_WUFC_BC - -/* Extended Device Control */ -#define E1000_CTRL_EXT_LPCD 0x00000004 /* LCD Power Cycle Done */ -#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Definable Pin 3 */ -#define E1000_CTRL_EXT_FORCE_SMBUS 0x00000800 /* Force SMBus mode */ -#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ -#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ -#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ -#define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */ -#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 -#define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 -#define E1000_CTRL_EXT_EIAME 0x01000000 -#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ -#define E1000_CTRL_EXT_IAME 0x08000000 /* Int ACK Auto-mask */ -#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ -#define E1000_CTRL_EXT_LSECCK 0x00001000 -#define E1000_CTRL_EXT_PHYPDEN 0x00100000 - -/* Receive Descriptor bit definitions */ -#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ -#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */ -#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */ -#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ -#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ -#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ -#define E1000_RXD_ERR_CE 0x01 /* CRC Error */ -#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ -#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ -#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */ -#define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */ -#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */ -#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ -#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ - -#define E1000_RXDEXT_STATERR_TST 0x00000100 /* Time Stamp taken */ -#define E1000_RXDEXT_STATERR_CE 0x01000000 -#define E1000_RXDEXT_STATERR_SE 0x02000000 -#define E1000_RXDEXT_STATERR_SEQ 0x04000000 -#define E1000_RXDEXT_STATERR_CXE 0x10000000 -#define E1000_RXDEXT_STATERR_RXE 0x80000000 - -/* mask to determine if packets should be dropped due to frame errors */ -#define E1000_RXD_ERR_FRAME_ERR_MASK ( \ - E1000_RXD_ERR_CE | \ - E1000_RXD_ERR_SE | \ - E1000_RXD_ERR_SEQ | \ - E1000_RXD_ERR_CXE | \ - E1000_RXD_ERR_RXE) - -/* Same mask, but for extended and packet split descriptors */ -#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \ - E1000_RXDEXT_STATERR_CE | \ - E1000_RXDEXT_STATERR_SE | \ - E1000_RXDEXT_STATERR_SEQ | \ - E1000_RXDEXT_STATERR_CXE | \ - E1000_RXDEXT_STATERR_RXE) - -#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000 -#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 -#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000 -#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000 -#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000 -#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 - -#define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000 - -/* Management Control */ -#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ -#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ -#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ -#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ -#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ -/* Enable MAC address filtering */ -#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 -/* Enable MNG packets to host memory */ -#define E1000_MANC_EN_MNG2HOST 0x00200000 - -#define E1000_MANC2H_PORT_623 0x00000020 /* Port 0x26f */ -#define E1000_MANC2H_PORT_664 0x00000040 /* Port 0x298 */ -#define E1000_MDEF_PORT_623 0x00000800 /* Port 0x26f */ -#define E1000_MDEF_PORT_664 0x00000400 /* Port 0x298 */ - -/* Receive Control */ -#define E1000_RCTL_EN 0x00000002 /* enable */ -#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ -#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ -#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ -#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ -#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ -#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ -#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ -#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */ -#define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min threshold size */ -#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ -#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ -#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ -/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ -#define E1000_RCTL_SZ_2048 0x00000000 /* Rx buffer size 2048 */ -#define E1000_RCTL_SZ_1024 0x00010000 /* Rx buffer size 1024 */ -#define E1000_RCTL_SZ_512 0x00020000 /* Rx buffer size 512 */ -#define E1000_RCTL_SZ_256 0x00030000 /* Rx buffer size 256 */ -/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */ -#define E1000_RCTL_SZ_16384 0x00010000 /* Rx buffer size 16384 */ -#define E1000_RCTL_SZ_8192 0x00020000 /* Rx buffer size 8192 */ -#define E1000_RCTL_SZ_4096 0x00030000 /* Rx buffer size 4096 */ -#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ -#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ -#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ -#define E1000_RCTL_DPF 0x00400000 /* Discard Pause Frames */ -#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ -#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ -#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ - -/* Use byte values for the following shift parameters - * Usage: - * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) & - * E1000_PSRCTL_BSIZE0_MASK) | - * ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) & - * E1000_PSRCTL_BSIZE1_MASK) | - * ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) & - * E1000_PSRCTL_BSIZE2_MASK) | - * ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |; - * E1000_PSRCTL_BSIZE3_MASK)) - * where value0 = [128..16256], default=256 - * value1 = [1024..64512], default=4096 - * value2 = [0..64512], default=4096 - * value3 = [0..64512], default=0 - */ - -#define E1000_PSRCTL_BSIZE0_MASK 0x0000007F -#define E1000_PSRCTL_BSIZE1_MASK 0x00003F00 -#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000 -#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000 - -#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */ -#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */ -#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */ -#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */ - -/* SWFW_SYNC Definitions */ -#define E1000_SWFW_EEP_SM 0x1 -#define E1000_SWFW_PHY0_SM 0x2 -#define E1000_SWFW_PHY1_SM 0x4 -#define E1000_SWFW_CSR_SM 0x8 - -/* Device Control */ -#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ -#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */ -#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ -#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */ -#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ -#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */ -#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */ -#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */ -#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */ -#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */ -#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ -#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ -#define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */ -#define E1000_CTRL_LANPHYPC_VALUE 0x00020000 /* SW value of LANPHYPC */ -#define E1000_CTRL_MEHE 0x00080000 /* Memory Error Handling Enable */ -#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ -#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ -#define E1000_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */ -#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 /* PHY PM enable */ -#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ -#define E1000_CTRL_RST 0x04000000 /* Global reset */ -#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ -#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ -#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ -#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ - -#define E1000_PCS_LCTL_FORCE_FCTRL 0x80 - -#define E1000_PCS_LSTS_AN_COMPLETE 0x10000 - -/* Device Status */ -#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ -#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ -#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ -#define E1000_STATUS_FUNC_SHIFT 2 -#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ -#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ -#define E1000_STATUS_SPEED_MASK 0x000000C0 -#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ -#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ -#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ -#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */ -#define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */ -#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master Req status */ - -#define HALF_DUPLEX 1 -#define FULL_DUPLEX 2 - -#define ADVERTISE_10_HALF 0x0001 -#define ADVERTISE_10_FULL 0x0002 -#define ADVERTISE_100_HALF 0x0004 -#define ADVERTISE_100_FULL 0x0008 -#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */ -#define ADVERTISE_1000_FULL 0x0020 - -/* 1000/H is not supported, nor spec-compliant. */ -#define E1000_ALL_SPEED_DUPLEX ( \ - ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \ - ADVERTISE_100_FULL | ADVERTISE_1000_FULL) -#define E1000_ALL_NOT_GIG ( \ - ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \ - ADVERTISE_100_FULL) -#define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL) -#define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL) -#define E1000_ALL_HALF_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_100_HALF) - -#define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX - -/* LED Control */ -#define E1000_PHY_LED0_MODE_MASK 0x00000007 -#define E1000_PHY_LED0_IVRT 0x00000008 -#define E1000_PHY_LED0_MASK 0x0000001F - -#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F -#define E1000_LEDCTL_LED0_MODE_SHIFT 0 -#define E1000_LEDCTL_LED0_IVRT 0x00000040 -#define E1000_LEDCTL_LED0_BLINK 0x00000080 - -#define E1000_LEDCTL_MODE_LINK_UP 0x2 -#define E1000_LEDCTL_MODE_LED_ON 0xE -#define E1000_LEDCTL_MODE_LED_OFF 0xF - -/* Transmit Descriptor bit definitions */ -#define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */ -#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ -#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ -#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ -#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ -#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */ -#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */ -#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */ -#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */ -#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ -#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */ -#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */ -#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */ -#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */ -#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */ -#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */ -#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ -#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ -#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ -#define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */ - -/* Transmit Control */ -#define E1000_TCTL_EN 0x00000002 /* enable Tx */ -#define E1000_TCTL_PSP 0x00000008 /* pad short packets */ -#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */ -#define E1000_TCTL_COLD 0x003ff000 /* collision distance */ -#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ -#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */ - -/* SerDes Control */ -#define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400 -#define E1000_SCTL_ENABLE_SERDES_LOOPBACK 0x0410 - -/* Receive Checksum Control */ -#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ -#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ -#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ - -/* Header split receive */ -#define E1000_RFCTL_NFSW_DIS 0x00000040 -#define E1000_RFCTL_NFSR_DIS 0x00000080 -#define E1000_RFCTL_ACK_DIS 0x00001000 -#define E1000_RFCTL_EXTEN 0x00008000 -#define E1000_RFCTL_IPV6_EX_DIS 0x00010000 -#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000 - -/* Collision related configuration parameters */ -#define E1000_COLLISION_THRESHOLD 15 -#define E1000_CT_SHIFT 4 -#define E1000_COLLISION_DISTANCE 63 -#define E1000_COLD_SHIFT 12 - -/* Default values for the transmit IPG register */ -#define DEFAULT_82543_TIPG_IPGT_COPPER 8 - -#define E1000_TIPG_IPGT_MASK 0x000003FF - -#define DEFAULT_82543_TIPG_IPGR1 8 -#define E1000_TIPG_IPGR1_SHIFT 10 - -#define DEFAULT_82543_TIPG_IPGR2 6 -#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7 -#define E1000_TIPG_IPGR2_SHIFT 20 - -#define MAX_JUMBO_FRAME_SIZE 0x3F00 - -/* Extended Configuration Control and Size */ -#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 -#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 -#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008 -#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 -#define E1000_EXTCNF_CTRL_GATE_PHY_CFG 0x00000080 -#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000 -#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16 -#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000 -#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT 16 - -#define E1000_PHY_CTRL_D0A_LPLU 0x00000002 -#define E1000_PHY_CTRL_NOND0A_LPLU 0x00000004 -#define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008 -#define E1000_PHY_CTRL_GBE_DISABLE 0x00000040 - -#define E1000_KABGTXD_BGSQLBIAS 0x00050000 - -/* Low Power IDLE Control */ -#define E1000_LPIC_LPIET_SHIFT 24 /* Low Power Idle Entry Time */ - -/* PBA constants */ -#define E1000_PBA_8K 0x0008 /* 8KB */ -#define E1000_PBA_16K 0x0010 /* 16KB */ - -#define E1000_PBA_RXA_MASK 0xFFFF - -#define E1000_PBS_16K E1000_PBA_16K - -/* Uncorrectable/correctable ECC Error counts and enable bits */ -#define E1000_PBECCSTS_CORR_ERR_CNT_MASK 0x000000FF -#define E1000_PBECCSTS_UNCORR_ERR_CNT_MASK 0x0000FF00 -#define E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT 8 -#define E1000_PBECCSTS_ECC_ENABLE 0x00010000 - -#define IFS_MAX 80 -#define IFS_MIN 40 -#define IFS_RATIO 4 -#define IFS_STEP 10 -#define MIN_NUM_XMITS 1000 - -/* SW Semaphore Register */ -#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ -#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ -#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */ - -#define E1000_SWSM2_LOCK 0x00000002 /* Secondary driver semaphore bit */ - -/* Interrupt Cause Read */ -#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ -#define E1000_ICR_LSC 0x00000004 /* Link Status Change */ -#define E1000_ICR_RXSEQ 0x00000008 /* Rx sequence error */ -#define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */ -#define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */ -#define E1000_ICR_ECCER 0x00400000 /* Uncorrectable ECC Error */ -/* If this bit asserted, the driver should claim the interrupt */ -#define E1000_ICR_INT_ASSERTED 0x80000000 -#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */ -#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ -#define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */ -#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */ -#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */ - -/* PBA ECC Register */ -#define E1000_PBA_ECC_COUNTER_MASK 0xFFF00000 /* ECC counter mask */ -#define E1000_PBA_ECC_COUNTER_SHIFT 20 /* ECC counter shift value */ -#define E1000_PBA_ECC_CORR_EN 0x00000001 /* ECC correction enable */ -#define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */ -#define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 for ECC */ - -/* This defines the bits that are set in the Interrupt Mask - * Set/Read Register. Each bit is documented below: - * o RXT0 = Receiver Timer Interrupt (ring 0) - * o TXDW = Transmit Descriptor Written Back - * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) - * o RXSEQ = Receive Sequence Error - * o LSC = Link Status Change - */ -#define IMS_ENABLE_MASK ( \ - E1000_IMS_RXT0 | \ - E1000_IMS_TXDW | \ - E1000_IMS_RXDMT0 | \ - E1000_IMS_RXSEQ | \ - E1000_IMS_LSC) - -/* Interrupt Mask Set */ -#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ -#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ -#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */ -#define E1000_IMS_ECCER E1000_ICR_ECCER /* Uncorrectable ECC Error */ -#define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */ -#define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */ -#define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */ -#define E1000_IMS_TXQ1 E1000_ICR_TXQ1 /* Tx Queue 1 Interrupt */ -#define E1000_IMS_OTHER E1000_ICR_OTHER /* Other Interrupts */ - -/* Interrupt Cause Set */ -#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ -#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ - -/* Transmit Descriptor Control */ -#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */ -#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */ -#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */ -#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ -#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ -#define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */ -/* Enable the counting of desc. still to be processed. */ -#define E1000_TXDCTL_COUNT_DESC 0x00400000 - -/* Flow Control Constants */ -#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 -#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 -#define FLOW_CONTROL_TYPE 0x8808 - -/* 802.1q VLAN Packet Size */ -#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ - -/* Receive Address - * Number of high/low register pairs in the RAR. The RAR (Receive Address - * Registers) holds the directed and multicast addresses that we monitor. - * Technically, we have 16 spots. However, we reserve one of these spots - * (RAR[15]) for our directed address used by controllers with - * manageability enabled, allowing us room for 15 multicast addresses. - */ -#define E1000_RAR_ENTRIES 15 -#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ -#define E1000_RAL_MAC_ADDR_LEN 4 -#define E1000_RAH_MAC_ADDR_LEN 2 - -/* Error Codes */ -#define E1000_ERR_NVM 1 -#define E1000_ERR_PHY 2 -#define E1000_ERR_CONFIG 3 -#define E1000_ERR_PARAM 4 -#define E1000_ERR_MAC_INIT 5 -#define E1000_ERR_PHY_TYPE 6 -#define E1000_ERR_RESET 9 -#define E1000_ERR_MASTER_REQUESTS_PENDING 10 -#define E1000_ERR_HOST_INTERFACE_COMMAND 11 -#define E1000_BLK_PHY_RESET 12 -#define E1000_ERR_SWFW_SYNC 13 -#define E1000_NOT_IMPLEMENTED 14 -#define E1000_ERR_INVALID_ARGUMENT 16 -#define E1000_ERR_NO_SPACE 17 -#define E1000_ERR_NVM_PBA_SECTION 18 - -/* Loop limit on how long we wait for auto-negotiation to complete */ -#define FIBER_LINK_UP_LIMIT 50 -#define COPPER_LINK_UP_LIMIT 10 -#define PHY_AUTO_NEG_LIMIT 45 -#define PHY_FORCE_LIMIT 20 -/* Number of 100 microseconds we wait for PCI Express master disable */ -#define MASTER_DISABLE_TIMEOUT 800 -/* Number of milliseconds we wait for PHY configuration done after MAC reset */ -#define PHY_CFG_TIMEOUT 100 -/* Number of 2 milliseconds we wait for acquiring MDIO ownership. */ -#define MDIO_OWNERSHIP_TIMEOUT 10 -/* Number of milliseconds for NVM auto read done after MAC reset. */ -#define AUTO_READ_DONE_TIMEOUT 10 - -/* Flow Control */ -#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */ -#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ -#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ - -/* Transmit Configuration Word */ -#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ -#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ -#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ -#define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */ -#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */ - -/* Receive Configuration Word */ -#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */ -#define E1000_RXCW_IV 0x08000000 /* Receive config invalid */ -#define E1000_RXCW_C 0x20000000 /* Receive config */ -#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ - -#define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */ -#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */ - -#define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */ -#define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */ -#define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00 -#define E1000_TSYNCRXCTL_TYPE_L4_V1 0x02 -#define E1000_TSYNCRXCTL_TYPE_L2_L4_V2 0x04 -#define E1000_TSYNCRXCTL_TYPE_ALL 0x08 -#define E1000_TSYNCRXCTL_TYPE_EVENT_V2 0x0A -#define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */ -#define E1000_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */ - -#define E1000_RXMTRL_PTP_V1_SYNC_MESSAGE 0x00000000 -#define E1000_RXMTRL_PTP_V1_DELAY_REQ_MESSAGE 0x00010000 - -#define E1000_RXMTRL_PTP_V2_SYNC_MESSAGE 0x00000000 -#define E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE 0x01000000 - -#define E1000_TIMINCA_INCPERIOD_SHIFT 24 -#define E1000_TIMINCA_INCVALUE_MASK 0x00FFFFFF - -/* PCI Express Control */ -#define E1000_GCR_RXD_NO_SNOOP 0x00000001 -#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 -#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004 -#define E1000_GCR_TXD_NO_SNOOP 0x00000008 -#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 -#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 - -#define PCIE_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ - E1000_GCR_RXDSCW_NO_SNOOP | \ - E1000_GCR_RXDSCR_NO_SNOOP | \ - E1000_GCR_TXD_NO_SNOOP | \ - E1000_GCR_TXDSCW_NO_SNOOP | \ - E1000_GCR_TXDSCR_NO_SNOOP) - -/* NVM Control */ -#define E1000_EECD_SK 0x00000001 /* NVM Clock */ -#define E1000_EECD_CS 0x00000002 /* NVM Chip Select */ -#define E1000_EECD_DI 0x00000004 /* NVM Data In */ -#define E1000_EECD_DO 0x00000008 /* NVM Data Out */ -#define E1000_EECD_REQ 0x00000040 /* NVM Access Request */ -#define E1000_EECD_GNT 0x00000080 /* NVM Access Grant */ -#define E1000_EECD_PRES 0x00000100 /* NVM Present */ -#define E1000_EECD_SIZE 0x00000200 /* NVM Size (0=64 word 1=256 word) */ -/* NVM Addressing bits based on type (0-small, 1-large) */ -#define E1000_EECD_ADDR_BITS 0x00000400 -#define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */ -#define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */ -#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */ -#define E1000_EECD_SIZE_EX_SHIFT 11 -#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */ -#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */ -#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */ -#define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES) - -#define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM r/w regs */ -#define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ -#define E1000_NVM_RW_REG_START 1 /* Start operation */ -#define E1000_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ -#define E1000_NVM_POLL_WRITE 1 /* Flag for polling write complete */ -#define E1000_NVM_POLL_READ 0 /* Flag for polling read complete */ -#define E1000_FLASH_UPDATES 2000 - -/* NVM Word Offsets */ -#define NVM_COMPAT 0x0003 -#define NVM_ID_LED_SETTINGS 0x0004 -#define NVM_FUTURE_INIT_WORD1 0x0019 -#define NVM_COMPAT_VALID_CSUM 0x0001 -#define NVM_FUTURE_INIT_WORD1_VALID_CSUM 0x0040 - -#define NVM_INIT_CONTROL2_REG 0x000F -#define NVM_INIT_CONTROL3_PORT_B 0x0014 -#define NVM_INIT_3GIO_3 0x001A -#define NVM_INIT_CONTROL3_PORT_A 0x0024 -#define NVM_CFG 0x0012 -#define NVM_ALT_MAC_ADDR_PTR 0x0037 -#define NVM_CHECKSUM_REG 0x003F - -#define E1000_NVM_CFG_DONE_PORT_0 0x40000 /* MNG config cycle done */ -#define E1000_NVM_CFG_DONE_PORT_1 0x80000 /* ...for second port */ - -/* Mask bits for fields in Word 0x0f of the NVM */ -#define NVM_WORD0F_PAUSE_MASK 0x3000 -#define NVM_WORD0F_PAUSE 0x1000 -#define NVM_WORD0F_ASM_DIR 0x2000 - -/* Mask bits for fields in Word 0x1a of the NVM */ -#define NVM_WORD1A_ASPM_MASK 0x000C - -/* Mask bits for fields in Word 0x03 of the EEPROM */ -#define NVM_COMPAT_LOM 0x0800 - -/* length of string needed to store PBA number */ -#define E1000_PBANUM_LENGTH 11 - -/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ -#define NVM_SUM 0xBABA - -/* PBA (printed board assembly) number words */ -#define NVM_PBA_OFFSET_0 8 -#define NVM_PBA_OFFSET_1 9 -#define NVM_PBA_PTR_GUARD 0xFAFA -#define NVM_WORD_SIZE_BASE_SHIFT 6 - -/* NVM Commands - SPI */ -#define NVM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ -#define NVM_READ_OPCODE_SPI 0x03 /* NVM read opcode */ -#define NVM_WRITE_OPCODE_SPI 0x02 /* NVM write opcode */ -#define NVM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */ -#define NVM_WREN_OPCODE_SPI 0x06 /* NVM set Write Enable latch */ -#define NVM_RDSR_OPCODE_SPI 0x05 /* NVM read Status register */ - -/* SPI NVM Status Register */ -#define NVM_STATUS_RDY_SPI 0x01 - -/* Word definitions for ID LED Settings */ -#define ID_LED_RESERVED_0000 0x0000 -#define ID_LED_RESERVED_FFFF 0xFFFF -#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ - (ID_LED_OFF1_OFF2 << 8) | \ - (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_DEF1_DEF2)) -#define ID_LED_DEF1_DEF2 0x1 -#define ID_LED_DEF1_ON2 0x2 -#define ID_LED_DEF1_OFF2 0x3 -#define ID_LED_ON1_DEF2 0x4 -#define ID_LED_ON1_ON2 0x5 -#define ID_LED_ON1_OFF2 0x6 -#define ID_LED_OFF1_DEF2 0x7 -#define ID_LED_OFF1_ON2 0x8 -#define ID_LED_OFF1_OFF2 0x9 - -#define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF -#define IGP_ACTIVITY_LED_ENABLE 0x0300 -#define IGP_LED3_MODE 0x07000000 - -/* PCI/PCI-X/PCI-EX Config space */ -#define PCI_HEADER_TYPE_REGISTER 0x0E -#define PCIE_LINK_STATUS 0x12 - -#define PCI_HEADER_TYPE_MULTIFUNC 0x80 -#define PCIE_LINK_WIDTH_MASK 0x3F0 -#define PCIE_LINK_WIDTH_SHIFT 4 - -#define PHY_REVISION_MASK 0xFFFFFFF0 -#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ -#define MAX_PHY_MULTI_PAGE_REG 0xF - -/* Bit definitions for valid PHY IDs. - * I = Integrated - * E = External - */ -#define M88E1000_E_PHY_ID 0x01410C50 -#define M88E1000_I_PHY_ID 0x01410C30 -#define M88E1011_I_PHY_ID 0x01410C20 -#define IGP01E1000_I_PHY_ID 0x02A80380 -#define M88E1111_I_PHY_ID 0x01410CC0 -#define GG82563_E_PHY_ID 0x01410CA0 -#define IGP03E1000_E_PHY_ID 0x02A80390 -#define IFE_E_PHY_ID 0x02A80330 -#define IFE_PLUS_E_PHY_ID 0x02A80320 -#define IFE_C_E_PHY_ID 0x02A80310 -#define BME1000_E_PHY_ID 0x01410CB0 -#define BME1000_E_PHY_ID_R2 0x01410CB1 -#define I82577_E_PHY_ID 0x01540050 -#define I82578_E_PHY_ID 0x004DD040 -#define I82579_E_PHY_ID 0x01540090 -#define I217_E_PHY_ID 0x015400A0 - -/* M88E1000 Specific Registers */ -#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ -#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */ -#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ - -#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */ -#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */ - -/* M88E1000 PHY Specific Control Register */ -#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ -#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ - /* Manual MDI configuration */ -#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ -/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */ -#define M88E1000_PSCR_AUTO_X_1000T 0x0040 -/* Auto crossover enabled all speeds */ -#define M88E1000_PSCR_AUTO_X_MODE 0x0060 -#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ - -/* M88E1000 PHY Specific Status Register */ -#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ -#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */ -#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ -/* 0=<50M; 1=50-80M; 2=80-110M; 3=110-140M; 4=>140M */ -#define M88E1000_PSSR_CABLE_LENGTH 0x0380 -#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ -#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ - -#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 - -/* Number of times we will attempt to autonegotiate before downshifting if we - * are the master - */ -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 -/* Number of times we will attempt to autonegotiate before downshifting if we - * are the slave - */ -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100 -#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ - -/* M88EC018 Rev 2 specific DownShift settings */ -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800 - -#define I82578_EPSCR_DOWNSHIFT_ENABLE 0x0020 -#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK 0x001C - -/* BME1000 PHY Specific Control Register */ -#define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */ - -/* Bits... - * 15-5: page - * 4-0: register offset - */ -#define GG82563_PAGE_SHIFT 5 -#define GG82563_REG(page, reg) \ - (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS)) -#define GG82563_MIN_ALT_REG 30 - -/* GG82563 Specific Registers */ -#define GG82563_PHY_SPEC_CTRL \ - GG82563_REG(0, 16) /* PHY Specific Control */ -#define GG82563_PHY_PAGE_SELECT \ - GG82563_REG(0, 22) /* Page Select */ -#define GG82563_PHY_SPEC_CTRL_2 \ - GG82563_REG(0, 26) /* PHY Specific Control 2 */ -#define GG82563_PHY_PAGE_SELECT_ALT \ - GG82563_REG(0, 29) /* Alternate Page Select */ - -#define GG82563_PHY_MAC_SPEC_CTRL \ - GG82563_REG(2, 21) /* MAC Specific Control Register */ - -#define GG82563_PHY_DSP_DISTANCE \ - GG82563_REG(5, 26) /* DSP Distance */ - -/* Page 193 - Port Control Registers */ -#define GG82563_PHY_KMRN_MODE_CTRL \ - GG82563_REG(193, 16) /* Kumeran Mode Control */ -#define GG82563_PHY_PWR_MGMT_CTRL \ - GG82563_REG(193, 20) /* Power Management Control */ - -/* Page 194 - KMRN Registers */ -#define GG82563_PHY_INBAND_CTRL \ - GG82563_REG(194, 18) /* Inband Control */ - -/* MDI Control */ -#define E1000_MDIC_REG_MASK 0x001F0000 -#define E1000_MDIC_REG_SHIFT 16 -#define E1000_MDIC_PHY_SHIFT 21 -#define E1000_MDIC_OP_WRITE 0x04000000 -#define E1000_MDIC_OP_READ 0x08000000 -#define E1000_MDIC_READY 0x10000000 -#define E1000_MDIC_ERROR 0x40000000 - -/* SerDes Control */ -#define E1000_GEN_POLL_TIMEOUT 640 - -#endif /* _E1000_DEFINES_H_ */ diff --git a/addons/e1000e/src/3.10.108/e1000.h b/addons/e1000e/src/3.10.108/e1000.h deleted file mode 100644 index ffbc08f5..00000000 --- a/addons/e1000e/src/3.10.108/e1000.h +++ /dev/null @@ -1,626 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* Linux PRO/1000 Ethernet Driver main header file */ - -#ifndef _E1000_H_ -#define _E1000_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hw.h" - -struct e1000_info; - -#define e_dbg(format, arg...) \ - netdev_dbg(hw->adapter->netdev, format, ## arg) -#define e_err(format, arg...) \ - netdev_err(adapter->netdev, format, ## arg) -#define e_info(format, arg...) \ - netdev_info(adapter->netdev, format, ## arg) -#define e_warn(format, arg...) \ - netdev_warn(adapter->netdev, format, ## arg) -#define e_notice(format, arg...) \ - netdev_notice(adapter->netdev, format, ## arg) - -/* Interrupt modes, as used by the IntMode parameter */ -#define E1000E_INT_MODE_LEGACY 0 -#define E1000E_INT_MODE_MSI 1 -#define E1000E_INT_MODE_MSIX 2 - -/* Tx/Rx descriptor defines */ -#define E1000_DEFAULT_TXD 256 -#define E1000_MAX_TXD 4096 -#define E1000_MIN_TXD 64 - -#define E1000_DEFAULT_RXD 256 -#define E1000_MAX_RXD 4096 -#define E1000_MIN_RXD 64 - -#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */ -#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */ - -#define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */ - -/* How many Tx Descriptors do we need to call netif_wake_queue ? */ -/* How many Rx Buffers do we bundle into one write to the hardware ? */ -#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ - -#define AUTO_ALL_MODES 0 -#define E1000_EEPROM_APME 0x0400 - -#define E1000_MNG_VLAN_NONE (-1) - -/* Number of packet split data buffers (not including the header buffer) */ -#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) - -#define DEFAULT_JUMBO 9234 - -/* Time to wait before putting the device into D3 if there's no link (in ms). */ -#define LINK_TIMEOUT 100 - -/* Count for polling __E1000_RESET condition every 10-20msec. - * Experimentation has shown the reset can take approximately 210msec. - */ -#define E1000_CHECK_RESET_COUNT 25 - -#define DEFAULT_RDTR 0 -#define DEFAULT_RADV 8 -#define BURST_RDTR 0x20 -#define BURST_RADV 0x20 - -/* in the case of WTHRESH, it appears at least the 82571/2 hardware - * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when - * WTHRESH=4, so a setting of 5 gives the most efficient bus - * utilization but to avoid possible Tx stalls, set it to 1 - */ -#define E1000_TXDCTL_DMA_BURST_ENABLE \ - (E1000_TXDCTL_GRAN | /* set descriptor granularity */ \ - E1000_TXDCTL_COUNT_DESC | \ - (1 << 16) | /* wthresh must be +1 more than desired */\ - (1 << 8) | /* hthresh */ \ - 0x1f) /* pthresh */ - -#define E1000_RXDCTL_DMA_BURST_ENABLE \ - (0x01000000 | /* set descriptor granularity */ \ - (4 << 16) | /* set writeback threshold */ \ - (4 << 8) | /* set prefetch threshold */ \ - 0x20) /* set hthresh */ - -#define E1000_TIDV_FPD (1 << 31) -#define E1000_RDTR_FPD (1 << 31) - -enum e1000_boards { - board_82571, - board_82572, - board_82573, - board_82574, - board_82583, - board_80003es2lan, - board_ich8lan, - board_ich9lan, - board_ich10lan, - board_pchlan, - board_pch2lan, - board_pch_lpt, -}; - -struct e1000_ps_page { - struct page *page; - u64 dma; /* must be u64 - written to hw */ -}; - -/* wrappers around a pointer to a socket buffer, - * so a DMA handle can be stored along with the buffer - */ -struct e1000_buffer { - dma_addr_t dma; - struct sk_buff *skb; - union { - /* Tx */ - struct { - unsigned long time_stamp; - u16 length; - u16 next_to_watch; - unsigned int segs; - unsigned int bytecount; - u16 mapped_as_page; - }; - /* Rx */ - struct { - /* arrays of page information for packet split */ - struct e1000_ps_page *ps_pages; - struct page *page; - }; - }; -}; - -struct e1000_ring { - struct e1000_adapter *adapter; /* back pointer to adapter */ - void *desc; /* pointer to ring memory */ - dma_addr_t dma; /* phys address of ring */ - unsigned int size; /* length of ring in bytes */ - unsigned int count; /* number of desc. in ring */ - - u16 next_to_use; - u16 next_to_clean; - - void __iomem *head; - void __iomem *tail; - - /* array of buffer information structs */ - struct e1000_buffer *buffer_info; - - char name[IFNAMSIZ + 5]; - u32 ims_val; - u32 itr_val; - void __iomem *itr_register; - int set_itr; - - struct sk_buff *rx_skb_top; -}; - -/* PHY register snapshot values */ -struct e1000_phy_regs { - u16 bmcr; /* basic mode control register */ - u16 bmsr; /* basic mode status register */ - u16 advertise; /* auto-negotiation advertisement */ - u16 lpa; /* link partner ability register */ - u16 expansion; /* auto-negotiation expansion reg */ - u16 ctrl1000; /* 1000BASE-T control register */ - u16 stat1000; /* 1000BASE-T status register */ - u16 estatus; /* extended status register */ -}; - -/* board specific private data structure */ -struct e1000_adapter { - struct timer_list watchdog_timer; - struct timer_list phy_info_timer; - struct timer_list blink_timer; - - struct work_struct reset_task; - struct work_struct watchdog_task; - - const struct e1000_info *ei; - - unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; - u32 bd_number; - u32 rx_buffer_len; - u16 mng_vlan_id; - u16 link_speed; - u16 link_duplex; - u16 eeprom_vers; - - /* track device up/down/testing state */ - unsigned long state; - - /* Interrupt Throttle Rate */ - u32 itr; - u32 itr_setting; - u16 tx_itr; - u16 rx_itr; - - /* Tx - one ring per active queue */ - struct e1000_ring *tx_ring ____cacheline_aligned_in_smp; - u32 tx_fifo_limit; - - struct napi_struct napi; - - unsigned int uncorr_errors; /* uncorrectable ECC errors */ - unsigned int corr_errors; /* correctable ECC errors */ - unsigned int restart_queue; - u32 txd_cmd; - - bool detect_tx_hung; - bool tx_hang_recheck; - u8 tx_timeout_factor; - - u32 tx_int_delay; - u32 tx_abs_int_delay; - - unsigned int total_tx_bytes; - unsigned int total_tx_packets; - unsigned int total_rx_bytes; - unsigned int total_rx_packets; - - /* Tx stats */ - u64 tpt_old; - u64 colc_old; - u32 gotc; - u64 gotc_old; - u32 tx_timeout_count; - u32 tx_fifo_head; - u32 tx_head_addr; - u32 tx_fifo_size; - u32 tx_dma_failed; - - /* Rx */ - bool (*clean_rx) (struct e1000_ring *ring, int *work_done, - int work_to_do) ____cacheline_aligned_in_smp; - void (*alloc_rx_buf) (struct e1000_ring *ring, int cleaned_count, - gfp_t gfp); - struct e1000_ring *rx_ring; - - u32 rx_int_delay; - u32 rx_abs_int_delay; - - /* Rx stats */ - u64 hw_csum_err; - u64 hw_csum_good; - u64 rx_hdr_split; - u32 gorc; - u64 gorc_old; - u32 alloc_rx_buff_failed; - u32 rx_dma_failed; - u32 rx_hwtstamp_cleared; - - unsigned int rx_ps_pages; - u16 rx_ps_bsize0; - u32 max_frame_size; - u32 min_frame_size; - - /* OS defined structs */ - struct net_device *netdev; - struct pci_dev *pdev; - - /* structs defined in e1000_hw.h */ - struct e1000_hw hw; - - spinlock_t stats64_lock; /* protects statistics counters */ - struct e1000_hw_stats stats; - struct e1000_phy_info phy_info; - struct e1000_phy_stats phy_stats; - - /* Snapshot of PHY registers */ - struct e1000_phy_regs phy_regs; - - struct e1000_ring test_tx_ring; - struct e1000_ring test_rx_ring; - u32 test_icr; - - u32 msg_enable; - unsigned int num_vectors; - struct msix_entry *msix_entries; - int int_mode; - u32 eiac_mask; - - u32 eeprom_wol; - u32 wol; - u32 pba; - u32 max_hw_frame_size; - - bool fc_autoneg; - - unsigned int flags; - unsigned int flags2; - struct work_struct downshift_task; - struct work_struct update_phy_task; - struct work_struct print_hang_task; - - bool idle_check; - int phy_hang_count; - - u16 tx_ring_count; - u16 rx_ring_count; - - struct hwtstamp_config hwtstamp_config; - struct delayed_work systim_overflow_work; - struct sk_buff *tx_hwtstamp_skb; - struct work_struct tx_hwtstamp_work; - spinlock_t systim_lock; /* protects SYSTIML/H regsters */ - struct cyclecounter cc; - struct timecounter tc; - struct ptp_clock *ptp_clock; - struct ptp_clock_info ptp_clock_info; - - u16 eee_advert; -}; - -struct e1000_info { - enum e1000_mac_type mac; - unsigned int flags; - unsigned int flags2; - u32 pba; - u32 max_hw_frame_size; - s32 (*get_variants)(struct e1000_adapter *); - const struct e1000_mac_operations *mac_ops; - const struct e1000_phy_operations *phy_ops; - const struct e1000_nvm_operations *nvm_ops; -}; - -s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca); - -/* The system time is maintained by a 64-bit counter comprised of the 32-bit - * SYSTIMH and SYSTIML registers. How the counter increments (and therefore - * its resolution) is based on the contents of the TIMINCA register - it - * increments every incperiod (bits 31:24) clock ticks by incvalue (bits 23:0). - * For the best accuracy, the incperiod should be as small as possible. The - * incvalue is scaled by a factor as large as possible (while still fitting - * in bits 23:0) so that relatively small clock corrections can be made. - * - * As a result, a shift of INCVALUE_SHIFT_n is used to fit a value of - * INCVALUE_n into the TIMINCA register allowing 32+8+(24-INCVALUE_SHIFT_n) - * bits to count nanoseconds leaving the rest for fractional nonseconds. - */ -#define INCVALUE_96MHz 125 -#define INCVALUE_SHIFT_96MHz 17 -#define INCPERIOD_SHIFT_96MHz 2 -#define INCPERIOD_96MHz (12 >> INCPERIOD_SHIFT_96MHz) - -#define INCVALUE_25MHz 40 -#define INCVALUE_SHIFT_25MHz 18 -#define INCPERIOD_25MHz 1 - -/* Another drawback of scaling the incvalue by a large factor is the - * 64-bit SYSTIM register overflows more quickly. This is dealt with - * by simply reading the clock before it overflows. - * - * Clock ns bits Overflows after - * ~~~~~~ ~~~~~~~ ~~~~~~~~~~~~~~~ - * 96MHz 47-bit 2^(47-INCPERIOD_SHIFT_96MHz) / 10^9 / 3600 = 9.77 hrs - * 25MHz 46-bit 2^46 / 10^9 / 3600 = 19.55 hours - */ -#define E1000_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 60 * 4) - -/* hardware capability, feature, and workaround flags */ -#define FLAG_HAS_AMT (1 << 0) -#define FLAG_HAS_FLASH (1 << 1) -#define FLAG_HAS_HW_VLAN_FILTER (1 << 2) -#define FLAG_HAS_WOL (1 << 3) -/* reserved bit4 */ -#define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5) -#define FLAG_HAS_SWSM_ON_LOAD (1 << 6) -#define FLAG_HAS_JUMBO_FRAMES (1 << 7) -#define FLAG_READ_ONLY_NVM (1 << 8) -#define FLAG_IS_ICH (1 << 9) -#define FLAG_HAS_MSIX (1 << 10) -#define FLAG_HAS_SMART_POWER_DOWN (1 << 11) -#define FLAG_IS_QUAD_PORT_A (1 << 12) -#define FLAG_IS_QUAD_PORT (1 << 13) -#define FLAG_HAS_HW_TIMESTAMP (1 << 14) -#define FLAG_APME_IN_WUC (1 << 15) -#define FLAG_APME_IN_CTRL3 (1 << 16) -#define FLAG_APME_CHECK_PORT_B (1 << 17) -#define FLAG_DISABLE_FC_PAUSE_TIME (1 << 18) -#define FLAG_NO_WAKE_UCAST (1 << 19) -#define FLAG_MNG_PT_ENABLED (1 << 20) -#define FLAG_RESET_OVERWRITES_LAA (1 << 21) -#define FLAG_TARC_SPEED_MODE_BIT (1 << 22) -#define FLAG_TARC_SET_BIT_ZERO (1 << 23) -#define FLAG_RX_NEEDS_RESTART (1 << 24) -#define FLAG_LSC_GIG_SPEED_DROP (1 << 25) -#define FLAG_SMART_POWER_DOWN (1 << 26) -#define FLAG_MSI_ENABLED (1 << 27) -/* reserved (1 << 28) */ -#define FLAG_TSO_FORCE (1 << 29) -#define FLAG_RESTART_NOW (1 << 30) -#define FLAG_MSI_TEST_FAILED (1 << 31) - -#define FLAG2_CRC_STRIPPING (1 << 0) -#define FLAG2_HAS_PHY_WAKEUP (1 << 1) -#define FLAG2_IS_DISCARDING (1 << 2) -#define FLAG2_DISABLE_ASPM_L1 (1 << 3) -#define FLAG2_HAS_PHY_STATS (1 << 4) -#define FLAG2_HAS_EEE (1 << 5) -#define FLAG2_DMA_BURST (1 << 6) -#define FLAG2_DISABLE_ASPM_L0S (1 << 7) -#define FLAG2_DISABLE_AIM (1 << 8) -#define FLAG2_CHECK_PHY_HANG (1 << 9) -#define FLAG2_NO_DISABLE_RX (1 << 10) -#define FLAG2_PCIM2PCI_ARBITER_WA (1 << 11) -#define FLAG2_DFLT_CRC_STRIPPING (1 << 12) -#define FLAG2_CHECK_RX_HWTSTAMP (1 << 13) - -#define E1000_RX_DESC_PS(R, i) \ - (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) -#define E1000_RX_DESC_EXT(R, i) \ - (&(((union e1000_rx_desc_extended *)((R).desc))[i])) -#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) -#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) -#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc) - -enum e1000_state_t { - __E1000_TESTING, - __E1000_RESETTING, - __E1000_ACCESS_SHARED_RESOURCE, - __E1000_DOWN -}; - -enum latency_range { - lowest_latency = 0, - low_latency = 1, - bulk_latency = 2, - latency_invalid = 255 -}; - -extern char e1000e_driver_name[]; -extern const char e1000e_driver_version[]; - -extern void e1000e_check_options(struct e1000_adapter *adapter); -extern void e1000e_set_ethtool_ops(struct net_device *netdev); - -extern int e1000e_up(struct e1000_adapter *adapter); -extern void e1000e_down(struct e1000_adapter *adapter); -extern void e1000e_reinit_locked(struct e1000_adapter *adapter); -extern void e1000e_reset(struct e1000_adapter *adapter); -extern void e1000e_power_up_phy(struct e1000_adapter *adapter); -extern int e1000e_setup_rx_resources(struct e1000_ring *ring); -extern int e1000e_setup_tx_resources(struct e1000_ring *ring); -extern void e1000e_free_rx_resources(struct e1000_ring *ring); -extern void e1000e_free_tx_resources(struct e1000_ring *ring); -extern struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 - *stats); -extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); -extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); -extern void e1000e_get_hw_control(struct e1000_adapter *adapter); -extern void e1000e_release_hw_control(struct e1000_adapter *adapter); -extern void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr); - -extern unsigned int copybreak; - -extern const struct e1000_info e1000_82571_info; -extern const struct e1000_info e1000_82572_info; -extern const struct e1000_info e1000_82573_info; -extern const struct e1000_info e1000_82574_info; -extern const struct e1000_info e1000_82583_info; -extern const struct e1000_info e1000_ich8_info; -extern const struct e1000_info e1000_ich9_info; -extern const struct e1000_info e1000_ich10_info; -extern const struct e1000_info e1000_pch_info; -extern const struct e1000_info e1000_pch2_info; -extern const struct e1000_info e1000_pch_lpt_info; -extern const struct e1000_info e1000_es2_info; - -extern void e1000e_ptp_init(struct e1000_adapter *adapter); -extern void e1000e_ptp_remove(struct e1000_adapter *adapter); - -static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) -{ - return hw->phy.ops.reset(hw); -} - -static inline s32 e1e_rphy(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return hw->phy.ops.read_reg(hw, offset, data); -} - -static inline s32 e1e_rphy_locked(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return hw->phy.ops.read_reg_locked(hw, offset, data); -} - -static inline s32 e1e_wphy(struct e1000_hw *hw, u32 offset, u16 data) -{ - return hw->phy.ops.write_reg(hw, offset, data); -} - -static inline s32 e1e_wphy_locked(struct e1000_hw *hw, u32 offset, u16 data) -{ - return hw->phy.ops.write_reg_locked(hw, offset, data); -} - -extern void e1000e_reload_nvm_generic(struct e1000_hw *hw); - -static inline s32 e1000e_read_mac_addr(struct e1000_hw *hw) -{ - if (hw->mac.ops.read_mac_addr) - return hw->mac.ops.read_mac_addr(hw); - - return e1000_read_mac_addr_generic(hw); -} - -static inline s32 e1000_validate_nvm_checksum(struct e1000_hw *hw) -{ - return hw->nvm.ops.validate(hw); -} - -static inline s32 e1000e_update_nvm_checksum(struct e1000_hw *hw) -{ - return hw->nvm.ops.update(hw); -} - -static inline s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - return hw->nvm.ops.read(hw, offset, words, data); -} - -static inline s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - return hw->nvm.ops.write(hw, offset, words, data); -} - -static inline s32 e1000_get_phy_info(struct e1000_hw *hw) -{ - return hw->phy.ops.get_info(hw); -} - -static inline u32 __er32(struct e1000_hw *hw, unsigned long reg) -{ - return readl(hw->hw_addr + reg); -} - -#define er32(reg) __er32(hw, E1000_##reg) - -/** - * __ew32_prepare - prepare to write to MAC CSR register on certain parts - * @hw: pointer to the HW structure - * - * When updating the MAC CSR registers, the Manageability Engine (ME) could - * be accessing the registers at the same time. Normally, this is handled in - * h/w by an arbiter but on some parts there is a bug that acknowledges Host - * accesses later than it should which could result in the register to have - * an incorrect value. Workaround this by checking the FWSM register which - * has bit 24 set while ME is accessing MAC CSR registers, wait if it is set - * and try again a number of times. - **/ -static inline s32 __ew32_prepare(struct e1000_hw *hw) -{ - s32 i = E1000_ICH_FWSM_PCIM2PCI_COUNT; - - while ((er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI) && --i) - udelay(50); - - return i; -} - -static inline void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val) -{ - if (hw->adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - __ew32_prepare(hw); - - writel(val, hw->hw_addr + reg); -} - -#define ew32(reg, val) __ew32(hw, E1000_##reg, (val)) - -#define e1e_flush() er32(STATUS) - -#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) \ - (__ew32((a), (reg + ((offset) << 2)), (value))) - -#define E1000_READ_REG_ARRAY(a, reg, offset) \ - (readl((a)->hw_addr + reg + ((offset) << 2))) - -#endif /* _E1000_H_ */ diff --git a/addons/e1000e/src/3.10.108/ethtool.c b/addons/e1000e/src/3.10.108/ethtool.c deleted file mode 100644 index 7c8ca658..00000000 --- a/addons/e1000e/src/3.10.108/ethtool.c +++ /dev/null @@ -1,2262 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* ethtool support for e1000 */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "e1000.h" - -enum { NETDEV_STATS, E1000_STATS }; - -struct e1000_stats { - char stat_string[ETH_GSTRING_LEN]; - int type; - int sizeof_stat; - int stat_offset; -}; - -#define E1000_STAT(str, m) { \ - .stat_string = str, \ - .type = E1000_STATS, \ - .sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \ - .stat_offset = offsetof(struct e1000_adapter, m) } -#define E1000_NETDEV_STAT(str, m) { \ - .stat_string = str, \ - .type = NETDEV_STATS, \ - .sizeof_stat = sizeof(((struct rtnl_link_stats64 *)0)->m), \ - .stat_offset = offsetof(struct rtnl_link_stats64, m) } - -static const struct e1000_stats e1000_gstrings_stats[] = { - E1000_STAT("rx_packets", stats.gprc), - E1000_STAT("tx_packets", stats.gptc), - E1000_STAT("rx_bytes", stats.gorc), - E1000_STAT("tx_bytes", stats.gotc), - E1000_STAT("rx_broadcast", stats.bprc), - E1000_STAT("tx_broadcast", stats.bptc), - E1000_STAT("rx_multicast", stats.mprc), - E1000_STAT("tx_multicast", stats.mptc), - E1000_NETDEV_STAT("rx_errors", rx_errors), - E1000_NETDEV_STAT("tx_errors", tx_errors), - E1000_NETDEV_STAT("tx_dropped", tx_dropped), - E1000_STAT("multicast", stats.mprc), - E1000_STAT("collisions", stats.colc), - E1000_NETDEV_STAT("rx_length_errors", rx_length_errors), - E1000_NETDEV_STAT("rx_over_errors", rx_over_errors), - E1000_STAT("rx_crc_errors", stats.crcerrs), - E1000_NETDEV_STAT("rx_frame_errors", rx_frame_errors), - E1000_STAT("rx_no_buffer_count", stats.rnbc), - E1000_STAT("rx_missed_errors", stats.mpc), - E1000_STAT("tx_aborted_errors", stats.ecol), - E1000_STAT("tx_carrier_errors", stats.tncrs), - E1000_NETDEV_STAT("tx_fifo_errors", tx_fifo_errors), - E1000_NETDEV_STAT("tx_heartbeat_errors", tx_heartbeat_errors), - E1000_STAT("tx_window_errors", stats.latecol), - E1000_STAT("tx_abort_late_coll", stats.latecol), - E1000_STAT("tx_deferred_ok", stats.dc), - E1000_STAT("tx_single_coll_ok", stats.scc), - E1000_STAT("tx_multi_coll_ok", stats.mcc), - E1000_STAT("tx_timeout_count", tx_timeout_count), - E1000_STAT("tx_restart_queue", restart_queue), - E1000_STAT("rx_long_length_errors", stats.roc), - E1000_STAT("rx_short_length_errors", stats.ruc), - E1000_STAT("rx_align_errors", stats.algnerrc), - E1000_STAT("tx_tcp_seg_good", stats.tsctc), - E1000_STAT("tx_tcp_seg_failed", stats.tsctfc), - E1000_STAT("rx_flow_control_xon", stats.xonrxc), - E1000_STAT("rx_flow_control_xoff", stats.xoffrxc), - E1000_STAT("tx_flow_control_xon", stats.xontxc), - E1000_STAT("tx_flow_control_xoff", stats.xofftxc), - E1000_STAT("rx_csum_offload_good", hw_csum_good), - E1000_STAT("rx_csum_offload_errors", hw_csum_err), - E1000_STAT("rx_header_split", rx_hdr_split), - E1000_STAT("alloc_rx_buff_failed", alloc_rx_buff_failed), - E1000_STAT("tx_smbus", stats.mgptc), - E1000_STAT("rx_smbus", stats.mgprc), - E1000_STAT("dropped_smbus", stats.mgpdc), - E1000_STAT("rx_dma_failed", rx_dma_failed), - E1000_STAT("tx_dma_failed", tx_dma_failed), - E1000_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared), - E1000_STAT("uncorr_ecc_errors", uncorr_errors), - E1000_STAT("corr_ecc_errors", corr_errors), -}; - -#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats) -#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN) -static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { - "Register test (offline)", "Eeprom test (offline)", - "Interrupt test (offline)", "Loopback test (offline)", - "Link test (on/offline)" -}; - -#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test) - -static int e1000_get_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 speed; - - if (hw->phy.media_type == e1000_media_type_copper) { - ecmd->supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP); - if (hw->phy.type == e1000_phy_ife) - ecmd->supported &= ~SUPPORTED_1000baseT_Full; - ecmd->advertising = ADVERTISED_TP; - - if (hw->mac.autoneg == 1) { - ecmd->advertising |= ADVERTISED_Autoneg; - /* the e1000 autoneg seems to match ethtool nicely */ - ecmd->advertising |= hw->phy.autoneg_advertised; - } - - ecmd->port = PORT_TP; - ecmd->phy_address = hw->phy.addr; - ecmd->transceiver = XCVR_INTERNAL; - - } else { - ecmd->supported = (SUPPORTED_1000baseT_Full | - SUPPORTED_FIBRE | - SUPPORTED_Autoneg); - - ecmd->advertising = (ADVERTISED_1000baseT_Full | - ADVERTISED_FIBRE | - ADVERTISED_Autoneg); - - ecmd->port = PORT_FIBRE; - ecmd->transceiver = XCVR_EXTERNAL; - } - - speed = -1; - ecmd->duplex = -1; - - if (netif_running(netdev)) { - if (netif_carrier_ok(netdev)) { - speed = adapter->link_speed; - ecmd->duplex = adapter->link_duplex - 1; - } - } else { - u32 status = er32(STATUS); - if (status & E1000_STATUS_LU) { - if (status & E1000_STATUS_SPEED_1000) - speed = SPEED_1000; - else if (status & E1000_STATUS_SPEED_100) - speed = SPEED_100; - else - speed = SPEED_10; - - if (status & E1000_STATUS_FD) - ecmd->duplex = DUPLEX_FULL; - else - ecmd->duplex = DUPLEX_HALF; - } - } - - ethtool_cmd_speed_set(ecmd, speed); - ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) || - hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; - - /* MDI-X => 2; MDI =>1; Invalid =>0 */ - if ((hw->phy.media_type == e1000_media_type_copper) && - netif_carrier_ok(netdev)) - ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : ETH_TP_MDI; - else - ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; - - if (hw->phy.mdix == AUTO_ALL_MODES) - ecmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; - else - ecmd->eth_tp_mdix_ctrl = hw->phy.mdix; - - return 0; -} - -static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx) -{ - struct e1000_mac_info *mac = &adapter->hw.mac; - - mac->autoneg = 0; - - /* Make sure dplx is at most 1 bit and lsb of speed is not set - * for the switch() below to work - */ - if ((spd & 1) || (dplx & ~1)) - goto err_inval; - - /* Fiber NICs only allow 1000 gbps Full duplex */ - if ((adapter->hw.phy.media_type == e1000_media_type_fiber) && - (spd != SPEED_1000) && (dplx != DUPLEX_FULL)) { - goto err_inval; - } - - switch (spd + dplx) { - case SPEED_10 + DUPLEX_HALF: - mac->forced_speed_duplex = ADVERTISE_10_HALF; - break; - case SPEED_10 + DUPLEX_FULL: - mac->forced_speed_duplex = ADVERTISE_10_FULL; - break; - case SPEED_100 + DUPLEX_HALF: - mac->forced_speed_duplex = ADVERTISE_100_HALF; - break; - case SPEED_100 + DUPLEX_FULL: - mac->forced_speed_duplex = ADVERTISE_100_FULL; - break; - case SPEED_1000 + DUPLEX_FULL: - mac->autoneg = 1; - adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; - break; - case SPEED_1000 + DUPLEX_HALF: /* not supported */ - default: - goto err_inval; - } - - /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ - adapter->hw.phy.mdix = AUTO_ALL_MODES; - - return 0; - -err_inval: - e_err("Unsupported Speed/Duplex configuration\n"); - return -EINVAL; -} - -static int e1000_set_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - /* When SoL/IDER sessions are active, autoneg/speed/duplex - * cannot be changed - */ - if (hw->phy.ops.check_reset_block && - hw->phy.ops.check_reset_block(hw)) { - e_err("Cannot change link characteristics when SoL/IDER is active.\n"); - return -EINVAL; - } - - /* MDI setting is only allowed when autoneg enabled because - * some hardware doesn't allow MDI setting when speed or - * duplex is forced. - */ - if (ecmd->eth_tp_mdix_ctrl) { - if (hw->phy.media_type != e1000_media_type_copper) - return -EOPNOTSUPP; - - if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) && - (ecmd->autoneg != AUTONEG_ENABLE)) { - e_err("forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n"); - return -EINVAL; - } - } - - while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - usleep_range(1000, 2000); - - if (ecmd->autoneg == AUTONEG_ENABLE) { - hw->mac.autoneg = 1; - if (hw->phy.media_type == e1000_media_type_fiber) - hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full | - ADVERTISED_FIBRE | ADVERTISED_Autoneg; - else - hw->phy.autoneg_advertised = ecmd->advertising | - ADVERTISED_TP | ADVERTISED_Autoneg; - ecmd->advertising = hw->phy.autoneg_advertised; - if (adapter->fc_autoneg) - hw->fc.requested_mode = e1000_fc_default; - } else { - u32 speed = ethtool_cmd_speed(ecmd); - /* calling this overrides forced MDI setting */ - if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) { - clear_bit(__E1000_RESETTING, &adapter->state); - return -EINVAL; - } - } - - /* MDI-X => 2; MDI => 1; Auto => 3 */ - if (ecmd->eth_tp_mdix_ctrl) { - /* fix up the value for auto (3 => 0) as zero is mapped - * internally to auto - */ - if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) - hw->phy.mdix = AUTO_ALL_MODES; - else - hw->phy.mdix = ecmd->eth_tp_mdix_ctrl; - } - - /* reset the link */ - if (netif_running(adapter->netdev)) { - e1000e_down(adapter); - e1000e_up(adapter); - } else { - e1000e_reset(adapter); - } - - clear_bit(__E1000_RESETTING, &adapter->state); - return 0; -} - -static void e1000_get_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - pause->autoneg = - (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); - - if (hw->fc.current_mode == e1000_fc_rx_pause) { - pause->rx_pause = 1; - } else if (hw->fc.current_mode == e1000_fc_tx_pause) { - pause->tx_pause = 1; - } else if (hw->fc.current_mode == e1000_fc_full) { - pause->rx_pause = 1; - pause->tx_pause = 1; - } -} - -static int e1000_set_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - int retval = 0; - - adapter->fc_autoneg = pause->autoneg; - - while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - usleep_range(1000, 2000); - - if (adapter->fc_autoneg == AUTONEG_ENABLE) { - hw->fc.requested_mode = e1000_fc_default; - if (netif_running(adapter->netdev)) { - e1000e_down(adapter); - e1000e_up(adapter); - } else { - e1000e_reset(adapter); - } - } else { - if (pause->rx_pause && pause->tx_pause) - hw->fc.requested_mode = e1000_fc_full; - else if (pause->rx_pause && !pause->tx_pause) - hw->fc.requested_mode = e1000_fc_rx_pause; - else if (!pause->rx_pause && pause->tx_pause) - hw->fc.requested_mode = e1000_fc_tx_pause; - else if (!pause->rx_pause && !pause->tx_pause) - hw->fc.requested_mode = e1000_fc_none; - - hw->fc.current_mode = hw->fc.requested_mode; - - if (hw->phy.media_type == e1000_media_type_fiber) { - retval = hw->mac.ops.setup_link(hw); - /* implicit goto out */ - } else { - retval = e1000e_force_mac_fc(hw); - if (retval) - goto out; - e1000e_set_fc_watermarks(hw); - } - } - -out: - clear_bit(__E1000_RESETTING, &adapter->state); - return retval; -} - -static u32 e1000_get_msglevel(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - return adapter->msg_enable; -} - -static void e1000_set_msglevel(struct net_device *netdev, u32 data) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - adapter->msg_enable = data; -} - -static int e1000_get_regs_len(struct net_device __always_unused *netdev) -{ -#define E1000_REGS_LEN 32 /* overestimate */ - return E1000_REGS_LEN * sizeof(u32); -} - -static void e1000_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 *regs_buff = p; - u16 phy_data; - - memset(p, 0, E1000_REGS_LEN * sizeof(u32)); - - regs->version = (1 << 24) | (adapter->pdev->revision << 16) | - adapter->pdev->device; - - regs_buff[0] = er32(CTRL); - regs_buff[1] = er32(STATUS); - - regs_buff[2] = er32(RCTL); - regs_buff[3] = er32(RDLEN(0)); - regs_buff[4] = er32(RDH(0)); - regs_buff[5] = er32(RDT(0)); - regs_buff[6] = er32(RDTR); - - regs_buff[7] = er32(TCTL); - regs_buff[8] = er32(TDLEN(0)); - regs_buff[9] = er32(TDH(0)); - regs_buff[10] = er32(TDT(0)); - regs_buff[11] = er32(TIDV); - - regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */ - - /* ethtool doesn't use anything past this point, so all this - * code is likely legacy junk for apps that may or may not exist - */ - if (hw->phy.type == e1000_phy_m88) { - e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - regs_buff[13] = (u32)phy_data; /* cable length */ - regs_buff[14] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[15] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[16] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - regs_buff[17] = (u32)phy_data; /* extended 10bt distance */ - regs_buff[18] = regs_buff[13]; /* cable polarity */ - regs_buff[19] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[20] = regs_buff[17]; /* polarity correction */ - /* phy receive errors */ - regs_buff[22] = adapter->phy_stats.receive_errors; - regs_buff[23] = regs_buff[13]; /* mdix mode */ - } - regs_buff[21] = 0; /* was idle_errors */ - e1e_rphy(hw, MII_STAT1000, &phy_data); - regs_buff[24] = (u32)phy_data; /* phy local receiver status */ - regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ -} - -static int e1000_get_eeprom_len(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - return adapter->hw.nvm.word_size * 2; -} - -static int e1000_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 *eeprom_buff; - int first_word; - int last_word; - int ret_val = 0; - u16 i; - - if (eeprom->len == 0) - return -EINVAL; - - eeprom->magic = adapter->pdev->vendor | (adapter->pdev->device << 16); - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - - eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1), - GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - if (hw->nvm.type == e1000_nvm_eeprom_spi) { - ret_val = e1000_read_nvm(hw, first_word, - last_word - first_word + 1, - eeprom_buff); - } else { - for (i = 0; i < last_word - first_word + 1; i++) { - ret_val = e1000_read_nvm(hw, first_word + i, 1, - &eeprom_buff[i]); - if (ret_val) - break; - } - } - - if (ret_val) { - /* a read error occurred, throw away the result */ - memset(eeprom_buff, 0xff, sizeof(u16) * - (last_word - first_word + 1)); - } else { - /* Device's eeprom is always little-endian, word addressable */ - for (i = 0; i < last_word - first_word + 1; i++) - le16_to_cpus(&eeprom_buff[i]); - } - - memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); - kfree(eeprom_buff); - - return ret_val; -} - -static int e1000_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 *eeprom_buff; - void *ptr; - int max_len; - int first_word; - int last_word; - int ret_val = 0; - u16 i; - - if (eeprom->len == 0) - return -EOPNOTSUPP; - - if (eeprom->magic != - (adapter->pdev->vendor | (adapter->pdev->device << 16))) - return -EFAULT; - - if (adapter->flags & FLAG_READ_ONLY_NVM) - return -EINVAL; - - max_len = hw->nvm.word_size * 2; - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(max_len, GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - ptr = (void *)eeprom_buff; - - if (eeprom->offset & 1) { - /* need read/modify/write of first changed EEPROM word */ - /* only the second byte of the word is being modified */ - ret_val = e1000_read_nvm(hw, first_word, 1, &eeprom_buff[0]); - ptr++; - } - if (((eeprom->offset + eeprom->len) & 1) && (!ret_val)) - /* need read/modify/write of last changed EEPROM word */ - /* only the first byte of the word is being modified */ - ret_val = e1000_read_nvm(hw, last_word, 1, - &eeprom_buff[last_word - first_word]); - - if (ret_val) - goto out; - - /* Device's eeprom is always little-endian, word addressable */ - for (i = 0; i < last_word - first_word + 1; i++) - le16_to_cpus(&eeprom_buff[i]); - - memcpy(ptr, bytes, eeprom->len); - - for (i = 0; i < last_word - first_word + 1; i++) - cpu_to_le16s(&eeprom_buff[i]); - - ret_val = e1000_write_nvm(hw, first_word, - last_word - first_word + 1, eeprom_buff); - - if (ret_val) - goto out; - - /* Update the checksum over the first part of the EEPROM if needed - * and flush shadow RAM for applicable controllers - */ - if ((first_word <= NVM_CHECKSUM_REG) || - (hw->mac.type == e1000_82583) || - (hw->mac.type == e1000_82574) || - (hw->mac.type == e1000_82573)) - ret_val = e1000e_update_nvm_checksum(hw); - -out: - kfree(eeprom_buff); - return ret_val; -} - -static void e1000_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - strlcpy(drvinfo->driver, e1000e_driver_name, sizeof(drvinfo->driver)); - strlcpy(drvinfo->version, e1000e_driver_version, - sizeof(drvinfo->version)); - - /* EEPROM image version # is reported as firmware version # for - * PCI-E controllers - */ - snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), - "%d.%d-%d", - (adapter->eeprom_vers & 0xF000) >> 12, - (adapter->eeprom_vers & 0x0FF0) >> 4, - (adapter->eeprom_vers & 0x000F)); - - strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), - sizeof(drvinfo->bus_info)); - drvinfo->regdump_len = e1000_get_regs_len(netdev); - drvinfo->eedump_len = e1000_get_eeprom_len(netdev); -} - -static void e1000_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - ring->rx_max_pending = E1000_MAX_RXD; - ring->tx_max_pending = E1000_MAX_TXD; - ring->rx_pending = adapter->rx_ring_count; - ring->tx_pending = adapter->tx_ring_count; -} - -static int e1000_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_ring *temp_tx = NULL, *temp_rx = NULL; - int err = 0, size = sizeof(struct e1000_ring); - bool set_tx = false, set_rx = false; - u16 new_rx_count, new_tx_count; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - new_rx_count = clamp_t(u32, ring->rx_pending, E1000_MIN_RXD, - E1000_MAX_RXD); - new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE); - - new_tx_count = clamp_t(u32, ring->tx_pending, E1000_MIN_TXD, - E1000_MAX_TXD); - new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE); - - if ((new_tx_count == adapter->tx_ring_count) && - (new_rx_count == adapter->rx_ring_count)) - /* nothing to do */ - return 0; - - while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - usleep_range(1000, 2000); - - if (!netif_running(adapter->netdev)) { - /* Set counts now and allocate resources during open() */ - adapter->tx_ring->count = new_tx_count; - adapter->rx_ring->count = new_rx_count; - adapter->tx_ring_count = new_tx_count; - adapter->rx_ring_count = new_rx_count; - goto clear_reset; - } - - set_tx = (new_tx_count != adapter->tx_ring_count); - set_rx = (new_rx_count != adapter->rx_ring_count); - - /* Allocate temporary storage for ring updates */ - if (set_tx) { - temp_tx = vmalloc(size); - if (!temp_tx) { - err = -ENOMEM; - goto free_temp; - } - } - if (set_rx) { - temp_rx = vmalloc(size); - if (!temp_rx) { - err = -ENOMEM; - goto free_temp; - } - } - - e1000e_down(adapter); - - /* We can't just free everything and then setup again, because the - * ISRs in MSI-X mode get passed pointers to the Tx and Rx ring - * structs. First, attempt to allocate new resources... - */ - if (set_tx) { - memcpy(temp_tx, adapter->tx_ring, size); - temp_tx->count = new_tx_count; - err = e1000e_setup_tx_resources(temp_tx); - if (err) - goto err_setup; - } - if (set_rx) { - memcpy(temp_rx, adapter->rx_ring, size); - temp_rx->count = new_rx_count; - err = e1000e_setup_rx_resources(temp_rx); - if (err) - goto err_setup_rx; - } - - /* ...then free the old resources and copy back any new ring data */ - if (set_tx) { - e1000e_free_tx_resources(adapter->tx_ring); - memcpy(adapter->tx_ring, temp_tx, size); - adapter->tx_ring_count = new_tx_count; - } - if (set_rx) { - e1000e_free_rx_resources(adapter->rx_ring); - memcpy(adapter->rx_ring, temp_rx, size); - adapter->rx_ring_count = new_rx_count; - } - -err_setup_rx: - if (err && set_tx) - e1000e_free_tx_resources(temp_tx); -err_setup: - e1000e_up(adapter); -free_temp: - vfree(temp_tx); - vfree(temp_rx); -clear_reset: - clear_bit(__E1000_RESETTING, &adapter->state); - return err; -} - -static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, - int reg, int offset, u32 mask, u32 write) -{ - u32 pat, val; - static const u32 test[] = { - 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF - }; - for (pat = 0; pat < ARRAY_SIZE(test); pat++) { - E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset, - (test[pat] & write)); - val = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset); - if (val != (test[pat] & write & mask)) { - e_err("pattern test failed (reg 0x%05X): got 0x%08X expected 0x%08X\n", - reg + (offset << 2), val, - (test[pat] & write & mask)); - *data = reg; - return 1; - } - } - return 0; -} - -static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, - int reg, u32 mask, u32 write) -{ - u32 val; - __ew32(&adapter->hw, reg, write & mask); - val = __er32(&adapter->hw, reg); - if ((write & mask) != (val & mask)) { - e_err("set/check test failed (reg 0x%05X): got 0x%08X expected 0x%08X\n", - reg, (val & mask), (write & mask)); - *data = reg; - return 1; - } - return 0; -} - -#define REG_PATTERN_TEST_ARRAY(reg, offset, mask, write) \ - do { \ - if (reg_pattern_test(adapter, data, reg, offset, mask, write)) \ - return 1; \ - } while (0) -#define REG_PATTERN_TEST(reg, mask, write) \ - REG_PATTERN_TEST_ARRAY(reg, 0, mask, write) - -#define REG_SET_AND_CHECK(reg, mask, write) \ - do { \ - if (reg_set_and_check(adapter, data, reg, mask, write)) \ - return 1; \ - } while (0) - -static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_mac_info *mac = &adapter->hw.mac; - u32 value; - u32 before; - u32 after; - u32 i; - u32 toggle; - u32 mask; - u32 wlock_mac = 0; - - /* The status register is Read Only, so a write should fail. - * Some bits that get toggled are ignored. There are several bits - * on newer hardware that are r/w. - */ - switch (mac->type) { - case e1000_82571: - case e1000_82572: - case e1000_80003es2lan: - toggle = 0x7FFFF3FF; - break; - default: - toggle = 0x7FFFF033; - break; - } - - before = er32(STATUS); - value = (er32(STATUS) & toggle); - ew32(STATUS, toggle); - after = er32(STATUS) & toggle; - if (value != after) { - e_err("failed STATUS register test got: 0x%08X expected: 0x%08X\n", - after, value); - *data = 1; - return 1; - } - /* restore previous status */ - ew32(STATUS, before); - - if (!(adapter->flags & FLAG_IS_ICH)) { - REG_PATTERN_TEST(E1000_FCAL, 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_FCAH, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_FCT, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_VET, 0x0000FFFF, 0xFFFFFFFF); - } - - REG_PATTERN_TEST(E1000_RDTR, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_RDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_RDLEN(0), 0x000FFF80, 0x000FFFFF); - REG_PATTERN_TEST(E1000_RDH(0), 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(E1000_RDT(0), 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(E1000_FCRTH, 0x0000FFF8, 0x0000FFF8); - REG_PATTERN_TEST(E1000_FCTTV, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(E1000_TIPG, 0x3FFFFFFF, 0x3FFFFFFF); - REG_PATTERN_TEST(E1000_TDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_TDLEN(0), 0x000FFF80, 0x000FFFFF); - - REG_SET_AND_CHECK(E1000_RCTL, 0xFFFFFFFF, 0x00000000); - - before = ((adapter->flags & FLAG_IS_ICH) ? 0x06C3B33E : 0x06DFB3FE); - REG_SET_AND_CHECK(E1000_RCTL, before, 0x003FFFFB); - REG_SET_AND_CHECK(E1000_TCTL, 0xFFFFFFFF, 0x00000000); - - REG_SET_AND_CHECK(E1000_RCTL, before, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_RDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF); - if (!(adapter->flags & FLAG_IS_ICH)) - REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(E1000_TDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF); - mask = 0x8003FFFF; - switch (mac->type) { - case e1000_ich10lan: - case e1000_pchlan: - case e1000_pch2lan: - case e1000_pch_lpt: - mask |= (1 << 18); - break; - default: - break; - } - - if (mac->type == e1000_pch_lpt) - wlock_mac = (er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK) >> - E1000_FWSM_WLOCK_MAC_SHIFT; - - for (i = 0; i < mac->rar_entry_count; i++) { - if (mac->type == e1000_pch_lpt) { - /* Cannot test write-protected SHRAL[n] registers */ - if ((wlock_mac == 1) || (wlock_mac && (i > wlock_mac))) - continue; - - /* SHRAH[9] different than the others */ - if (i == 10) - mask |= (1 << 30); - else - mask &= ~(1 << 30); - } - - REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1), mask, - 0xFFFFFFFF); - } - - for (i = 0; i < mac->mta_reg_count; i++) - REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF); - - *data = 0; - - return 0; -} - -static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data) -{ - u16 temp; - u16 checksum = 0; - u16 i; - - *data = 0; - /* Read and add up the contents of the EEPROM */ - for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { - if ((e1000_read_nvm(&adapter->hw, i, 1, &temp)) < 0) { - *data = 1; - return *data; - } - checksum += temp; - } - - /* If Checksum is not Correct return error else test passed */ - if ((checksum != (u16)NVM_SUM) && !(*data)) - *data = 2; - - return *data; -} - -static irqreturn_t e1000_test_intr(int __always_unused irq, void *data) -{ - struct net_device *netdev = (struct net_device *)data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - adapter->test_icr |= er32(ICR); - - return IRQ_HANDLED; -} - -static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - u32 mask; - u32 shared_int = 1; - u32 irq = adapter->pdev->irq; - int i; - int ret_val = 0; - int int_mode = E1000E_INT_MODE_LEGACY; - - *data = 0; - - /* NOTE: we don't test MSI/MSI-X interrupts here, yet */ - if (adapter->int_mode == E1000E_INT_MODE_MSIX) { - int_mode = adapter->int_mode; - e1000e_reset_interrupt_capability(adapter); - adapter->int_mode = E1000E_INT_MODE_LEGACY; - e1000e_set_interrupt_capability(adapter); - } - /* Hook up test interrupt handler just for this test */ - if (!request_irq(irq, e1000_test_intr, IRQF_PROBE_SHARED, netdev->name, - netdev)) { - shared_int = 0; - } else if (request_irq(irq, e1000_test_intr, IRQF_SHARED, netdev->name, - netdev)) { - *data = 1; - ret_val = -1; - goto out; - } - e_info("testing %s interrupt\n", (shared_int ? "shared" : "unshared")); - - /* Disable all the interrupts */ - ew32(IMC, 0xFFFFFFFF); - e1e_flush(); - usleep_range(10000, 20000); - - /* Test each interrupt */ - for (i = 0; i < 10; i++) { - /* Interrupt to test */ - mask = 1 << i; - - if (adapter->flags & FLAG_IS_ICH) { - switch (mask) { - case E1000_ICR_RXSEQ: - continue; - case 0x00000100: - if (adapter->hw.mac.type == e1000_ich8lan || - adapter->hw.mac.type == e1000_ich9lan) - continue; - break; - default: - break; - } - } - - if (!shared_int) { - /* Disable the interrupt to be reported in - * the cause register and then force the same - * interrupt and see if one gets posted. If - * an interrupt was posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - ew32(IMC, mask); - ew32(ICS, mask); - e1e_flush(); - usleep_range(10000, 20000); - - if (adapter->test_icr & mask) { - *data = 3; - break; - } - } - - /* Enable the interrupt to be reported in - * the cause register and then force the same - * interrupt and see if one gets posted. If - * an interrupt was not posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - ew32(IMS, mask); - ew32(ICS, mask); - e1e_flush(); - usleep_range(10000, 20000); - - if (!(adapter->test_icr & mask)) { - *data = 4; - break; - } - - if (!shared_int) { - /* Disable the other interrupts to be reported in - * the cause register and then force the other - * interrupts and see if any get posted. If - * an interrupt was posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - ew32(IMC, ~mask & 0x00007FFF); - ew32(ICS, ~mask & 0x00007FFF); - e1e_flush(); - usleep_range(10000, 20000); - - if (adapter->test_icr) { - *data = 5; - break; - } - } - } - - /* Disable all the interrupts */ - ew32(IMC, 0xFFFFFFFF); - e1e_flush(); - usleep_range(10000, 20000); - - /* Unhook test interrupt handler */ - free_irq(irq, netdev); - -out: - if (int_mode == E1000E_INT_MODE_MSIX) { - e1000e_reset_interrupt_capability(adapter); - adapter->int_mode = int_mode; - e1000e_set_interrupt_capability(adapter); - } - - return ret_val; -} - -static void e1000_free_desc_rings(struct e1000_adapter *adapter) -{ - struct e1000_ring *tx_ring = &adapter->test_tx_ring; - struct e1000_ring *rx_ring = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - struct e1000_buffer *buffer_info; - int i; - - if (tx_ring->desc && tx_ring->buffer_info) { - for (i = 0; i < tx_ring->count; i++) { - buffer_info = &tx_ring->buffer_info[i]; - - if (buffer_info->dma) - dma_unmap_single(&pdev->dev, - buffer_info->dma, - buffer_info->length, - DMA_TO_DEVICE); - if (buffer_info->skb) - dev_kfree_skb(buffer_info->skb); - } - } - - if (rx_ring->desc && rx_ring->buffer_info) { - for (i = 0; i < rx_ring->count; i++) { - buffer_info = &rx_ring->buffer_info[i]; - - if (buffer_info->dma) - dma_unmap_single(&pdev->dev, - buffer_info->dma, - 2048, DMA_FROM_DEVICE); - if (buffer_info->skb) - dev_kfree_skb(buffer_info->skb); - } - } - - if (tx_ring->desc) { - dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, - tx_ring->dma); - tx_ring->desc = NULL; - } - if (rx_ring->desc) { - dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, - rx_ring->dma); - rx_ring->desc = NULL; - } - - kfree(tx_ring->buffer_info); - tx_ring->buffer_info = NULL; - kfree(rx_ring->buffer_info); - rx_ring->buffer_info = NULL; -} - -static int e1000_setup_desc_rings(struct e1000_adapter *adapter) -{ - struct e1000_ring *tx_ring = &adapter->test_tx_ring; - struct e1000_ring *rx_ring = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - int i; - int ret_val; - - /* Setup Tx descriptor ring and Tx buffers */ - - if (!tx_ring->count) - tx_ring->count = E1000_DEFAULT_TXD; - - tx_ring->buffer_info = kcalloc(tx_ring->count, - sizeof(struct e1000_buffer), GFP_KERNEL); - if (!tx_ring->buffer_info) { - ret_val = 1; - goto err_nomem; - } - - tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); - tx_ring->size = ALIGN(tx_ring->size, 4096); - tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size, - &tx_ring->dma, GFP_KERNEL); - if (!tx_ring->desc) { - ret_val = 2; - goto err_nomem; - } - tx_ring->next_to_use = 0; - tx_ring->next_to_clean = 0; - - ew32(TDBAL(0), ((u64)tx_ring->dma & 0x00000000FFFFFFFF)); - ew32(TDBAH(0), ((u64)tx_ring->dma >> 32)); - ew32(TDLEN(0), tx_ring->count * sizeof(struct e1000_tx_desc)); - ew32(TDH(0), 0); - ew32(TDT(0), 0); - ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | E1000_TCTL_MULR | - E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | - E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT); - - for (i = 0; i < tx_ring->count; i++) { - struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i); - struct sk_buff *skb; - unsigned int skb_size = 1024; - - skb = alloc_skb(skb_size, GFP_KERNEL); - if (!skb) { - ret_val = 3; - goto err_nomem; - } - skb_put(skb, skb_size); - tx_ring->buffer_info[i].skb = skb; - tx_ring->buffer_info[i].length = skb->len; - tx_ring->buffer_info[i].dma = - dma_map_single(&pdev->dev, skb->data, skb->len, - DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, - tx_ring->buffer_info[i].dma)) { - ret_val = 4; - goto err_nomem; - } - tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma); - tx_desc->lower.data = cpu_to_le32(skb->len); - tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP | - E1000_TXD_CMD_IFCS | - E1000_TXD_CMD_RS); - tx_desc->upper.data = 0; - } - - /* Setup Rx descriptor ring and Rx buffers */ - - if (!rx_ring->count) - rx_ring->count = E1000_DEFAULT_RXD; - - rx_ring->buffer_info = kcalloc(rx_ring->count, - sizeof(struct e1000_buffer), GFP_KERNEL); - if (!rx_ring->buffer_info) { - ret_val = 5; - goto err_nomem; - } - - rx_ring->size = rx_ring->count * sizeof(union e1000_rx_desc_extended); - rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size, - &rx_ring->dma, GFP_KERNEL); - if (!rx_ring->desc) { - ret_val = 6; - goto err_nomem; - } - rx_ring->next_to_use = 0; - rx_ring->next_to_clean = 0; - - rctl = er32(RCTL); - if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX)) - ew32(RCTL, rctl & ~E1000_RCTL_EN); - ew32(RDBAL(0), ((u64)rx_ring->dma & 0xFFFFFFFF)); - ew32(RDBAH(0), ((u64)rx_ring->dma >> 32)); - ew32(RDLEN(0), rx_ring->size); - ew32(RDH(0), 0); - ew32(RDT(0), 0); - rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | - E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE | - E1000_RCTL_SBP | E1000_RCTL_SECRC | - E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | - (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); - ew32(RCTL, rctl); - - for (i = 0; i < rx_ring->count; i++) { - union e1000_rx_desc_extended *rx_desc; - struct sk_buff *skb; - - skb = alloc_skb(2048 + NET_IP_ALIGN, GFP_KERNEL); - if (!skb) { - ret_val = 7; - goto err_nomem; - } - skb_reserve(skb, NET_IP_ALIGN); - rx_ring->buffer_info[i].skb = skb; - rx_ring->buffer_info[i].dma = - dma_map_single(&pdev->dev, skb->data, 2048, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, - rx_ring->buffer_info[i].dma)) { - ret_val = 8; - goto err_nomem; - } - rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); - rx_desc->read.buffer_addr = - cpu_to_le64(rx_ring->buffer_info[i].dma); - memset(skb->data, 0x00, skb->len); - } - - return 0; - -err_nomem: - e1000_free_desc_rings(adapter); - return ret_val; -} - -static void e1000_phy_disable_receiver(struct e1000_adapter *adapter) -{ - /* Write out to PHY registers 29 and 30 to disable the Receiver. */ - e1e_wphy(&adapter->hw, 29, 0x001F); - e1e_wphy(&adapter->hw, 30, 0x8FFC); - e1e_wphy(&adapter->hw, 29, 0x001A); - e1e_wphy(&adapter->hw, 30, 0x8FF0); -} - -static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl_reg = 0; - u16 phy_reg = 0; - s32 ret_val = 0; - - hw->mac.autoneg = 0; - - if (hw->phy.type == e1000_phy_ife) { - /* force 100, set loopback */ - e1e_wphy(hw, MII_BMCR, 0x6100); - - /* Now set up the MAC to the same speed/duplex as the PHY. */ - ctrl_reg = er32(CTRL); - ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ - ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ - E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ - E1000_CTRL_SPD_100 |/* Force Speed to 100 */ - E1000_CTRL_FD); /* Force Duplex to FULL */ - - ew32(CTRL, ctrl_reg); - e1e_flush(); - usleep_range(500, 1000); - - return 0; - } - - /* Specific PHY configuration for loopback */ - switch (hw->phy.type) { - case e1000_phy_m88: - /* Auto-MDI/MDIX Off */ - e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); - /* reset to update Auto-MDI/MDIX */ - e1e_wphy(hw, MII_BMCR, 0x9140); - /* autoneg off */ - e1e_wphy(hw, MII_BMCR, 0x8140); - break; - case e1000_phy_gg82563: - e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC); - break; - case e1000_phy_bm: - /* Set Default MAC Interface speed to 1GB */ - e1e_rphy(hw, PHY_REG(2, 21), &phy_reg); - phy_reg &= ~0x0007; - phy_reg |= 0x006; - e1e_wphy(hw, PHY_REG(2, 21), phy_reg); - /* Assert SW reset for above settings to take effect */ - hw->phy.ops.commit(hw); - usleep_range(1000, 2000); - /* Force Full Duplex */ - e1e_rphy(hw, PHY_REG(769, 16), &phy_reg); - e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x000C); - /* Set Link Up (in force link) */ - e1e_rphy(hw, PHY_REG(776, 16), &phy_reg); - e1e_wphy(hw, PHY_REG(776, 16), phy_reg | 0x0040); - /* Force Link */ - e1e_rphy(hw, PHY_REG(769, 16), &phy_reg); - e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x0040); - /* Set Early Link Enable */ - e1e_rphy(hw, PHY_REG(769, 20), &phy_reg); - e1e_wphy(hw, PHY_REG(769, 20), phy_reg | 0x0400); - break; - case e1000_phy_82577: - case e1000_phy_82578: - /* Workaround: K1 must be disabled for stable 1Gbps operation */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) { - e_err("Cannot setup 1Gbps loopback.\n"); - return ret_val; - } - e1000_configure_k1_ich8lan(hw, false); - hw->phy.ops.release(hw); - break; - case e1000_phy_82579: - /* Disable PHY energy detect power down */ - e1e_rphy(hw, PHY_REG(0, 21), &phy_reg); - e1e_wphy(hw, PHY_REG(0, 21), phy_reg & ~(1 << 3)); - /* Disable full chip energy detect */ - e1e_rphy(hw, PHY_REG(776, 18), &phy_reg); - e1e_wphy(hw, PHY_REG(776, 18), phy_reg | 1); - /* Enable loopback on the PHY */ - e1e_wphy(hw, I82577_PHY_LBK_CTRL, 0x8001); - break; - default: - break; - } - - /* force 1000, set loopback */ - e1e_wphy(hw, MII_BMCR, 0x4140); - msleep(250); - - /* Now set up the MAC to the same speed/duplex as the PHY. */ - ctrl_reg = er32(CTRL); - ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ - ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ - E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ - E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ - E1000_CTRL_FD); /* Force Duplex to FULL */ - - if (adapter->flags & FLAG_IS_ICH) - ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */ - - if (hw->phy.media_type == e1000_media_type_copper && - hw->phy.type == e1000_phy_m88) { - ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ - } else { - /* Set the ILOS bit on the fiber Nic if half duplex link is - * detected. - */ - if ((er32(STATUS) & E1000_STATUS_FD) == 0) - ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU); - } - - ew32(CTRL, ctrl_reg); - - /* Disable the receiver on the PHY so when a cable is plugged in, the - * PHY does not begin to autoneg when a cable is reconnected to the NIC. - */ - if (hw->phy.type == e1000_phy_m88) - e1000_phy_disable_receiver(adapter); - - usleep_range(500, 1000); - - return 0; -} - -static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl = er32(CTRL); - int link; - - /* special requirements for 82571/82572 fiber adapters */ - - /* jump through hoops to make sure link is up because serdes - * link is hardwired up - */ - ctrl |= E1000_CTRL_SLU; - ew32(CTRL, ctrl); - - /* disable autoneg */ - ctrl = er32(TXCW); - ctrl &= ~(1 << 31); - ew32(TXCW, ctrl); - - link = (er32(STATUS) & E1000_STATUS_LU); - - if (!link) { - /* set invert loss of signal */ - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_ILOS; - ew32(CTRL, ctrl); - } - - /* special write to serdes control register to enable SerDes analog - * loopback - */ - ew32(SCTL, E1000_SCTL_ENABLE_SERDES_LOOPBACK); - e1e_flush(); - usleep_range(10000, 20000); - - return 0; -} - -/* only call this for fiber/serdes connections to es2lan */ -static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrlext = er32(CTRL_EXT); - u32 ctrl = er32(CTRL); - - /* save CTRL_EXT to restore later, reuse an empty variable (unused - * on mac_type 80003es2lan) - */ - adapter->tx_fifo_head = ctrlext; - - /* clear the serdes mode bits, putting the device into mac loopback */ - ctrlext &= ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; - ew32(CTRL_EXT, ctrlext); - - /* force speed to 1000/FD, link up */ - ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | - E1000_CTRL_SPD_1000 | E1000_CTRL_FD); - ew32(CTRL, ctrl); - - /* set mac loopback */ - ctrl = er32(RCTL); - ctrl |= E1000_RCTL_LBM_MAC; - ew32(RCTL, ctrl); - - /* set testing mode parameters (no need to reset later) */ -#define KMRNCTRLSTA_OPMODE (0x1F << 16) -#define KMRNCTRLSTA_OPMODE_1GB_FD_GMII 0x0582 - ew32(KMRNCTRLSTA, - (KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII)); - - return 0; -} - -static int e1000_setup_loopback_test(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - if (hw->phy.media_type == e1000_media_type_fiber || - hw->phy.media_type == e1000_media_type_internal_serdes) { - switch (hw->mac.type) { - case e1000_80003es2lan: - return e1000_set_es2lan_mac_loopback(adapter); - break; - case e1000_82571: - case e1000_82572: - return e1000_set_82571_fiber_loopback(adapter); - break; - default: - rctl = er32(RCTL); - rctl |= E1000_RCTL_LBM_TCVR; - ew32(RCTL, rctl); - return 0; - } - } else if (hw->phy.media_type == e1000_media_type_copper) { - return e1000_integrated_phy_loopback(adapter); - } - - return 7; -} - -static void e1000_loopback_cleanup(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - u16 phy_reg; - - rctl = er32(RCTL); - rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); - ew32(RCTL, rctl); - - switch (hw->mac.type) { - case e1000_80003es2lan: - if (hw->phy.media_type == e1000_media_type_fiber || - hw->phy.media_type == e1000_media_type_internal_serdes) { - /* restore CTRL_EXT, stealing space from tx_fifo_head */ - ew32(CTRL_EXT, adapter->tx_fifo_head); - adapter->tx_fifo_head = 0; - } - /* fall through */ - case e1000_82571: - case e1000_82572: - if (hw->phy.media_type == e1000_media_type_fiber || - hw->phy.media_type == e1000_media_type_internal_serdes) { - ew32(SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); - e1e_flush(); - usleep_range(10000, 20000); - break; - } - /* Fall Through */ - default: - hw->mac.autoneg = 1; - if (hw->phy.type == e1000_phy_gg82563) - e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x180); - e1e_rphy(hw, MII_BMCR, &phy_reg); - if (phy_reg & BMCR_LOOPBACK) { - phy_reg &= ~BMCR_LOOPBACK; - e1e_wphy(hw, MII_BMCR, phy_reg); - if (hw->phy.ops.commit) - hw->phy.ops.commit(hw); - } - break; - } -} - -static void e1000_create_lbtest_frame(struct sk_buff *skb, - unsigned int frame_size) -{ - memset(skb->data, 0xFF, frame_size); - frame_size &= ~1; - memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1); - memset(&skb->data[frame_size / 2 + 10], 0xBE, 1); - memset(&skb->data[frame_size / 2 + 12], 0xAF, 1); -} - -static int e1000_check_lbtest_frame(struct sk_buff *skb, - unsigned int frame_size) -{ - frame_size &= ~1; - if (*(skb->data + 3) == 0xFF) - if ((*(skb->data + frame_size / 2 + 10) == 0xBE) && - (*(skb->data + frame_size / 2 + 12) == 0xAF)) - return 0; - return 13; -} - -static int e1000_run_loopback_test(struct e1000_adapter *adapter) -{ - struct e1000_ring *tx_ring = &adapter->test_tx_ring; - struct e1000_ring *rx_ring = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - struct e1000_hw *hw = &adapter->hw; - struct e1000_buffer *buffer_info; - int i, j, k, l; - int lc; - int good_cnt; - int ret_val = 0; - unsigned long time; - - ew32(RDT(0), rx_ring->count - 1); - - /* Calculate the loop count based on the largest descriptor ring - * The idea is to wrap the largest ring a number of times using 64 - * send/receive pairs during each loop - */ - - if (rx_ring->count <= tx_ring->count) - lc = ((tx_ring->count / 64) * 2) + 1; - else - lc = ((rx_ring->count / 64) * 2) + 1; - - k = 0; - l = 0; - /* loop count loop */ - for (j = 0; j <= lc; j++) { - /* send the packets */ - for (i = 0; i < 64; i++) { - buffer_info = &tx_ring->buffer_info[k]; - - e1000_create_lbtest_frame(buffer_info->skb, 1024); - dma_sync_single_for_device(&pdev->dev, - buffer_info->dma, - buffer_info->length, - DMA_TO_DEVICE); - k++; - if (k == tx_ring->count) - k = 0; - } - ew32(TDT(0), k); - e1e_flush(); - msleep(200); - time = jiffies; /* set the start time for the receive */ - good_cnt = 0; - /* receive the sent packets */ - do { - buffer_info = &rx_ring->buffer_info[l]; - - dma_sync_single_for_cpu(&pdev->dev, - buffer_info->dma, 2048, - DMA_FROM_DEVICE); - - ret_val = e1000_check_lbtest_frame(buffer_info->skb, - 1024); - if (!ret_val) - good_cnt++; - l++; - if (l == rx_ring->count) - l = 0; - /* time + 20 msecs (200 msecs on 2.4) is more than - * enough time to complete the receives, if it's - * exceeded, break and error off - */ - } while ((good_cnt < 64) && !time_after(jiffies, time + 20)); - if (good_cnt != 64) { - ret_val = 13; /* ret_val is the same as mis-compare */ - break; - } - if (jiffies >= (time + 20)) { - ret_val = 14; /* error code for time out error */ - break; - } - } - return ret_val; -} - -static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) -{ - struct e1000_hw *hw = &adapter->hw; - - /* PHY loopback cannot be performed if SoL/IDER sessions are active */ - if (hw->phy.ops.check_reset_block && - hw->phy.ops.check_reset_block(hw)) { - e_err("Cannot do PHY loopback test when SoL/IDER is active.\n"); - *data = 0; - goto out; - } - - *data = e1000_setup_desc_rings(adapter); - if (*data) - goto out; - - *data = e1000_setup_loopback_test(adapter); - if (*data) - goto err_loopback; - - *data = e1000_run_loopback_test(adapter); - e1000_loopback_cleanup(adapter); - -err_loopback: - e1000_free_desc_rings(adapter); -out: - return *data; -} - -static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) -{ - struct e1000_hw *hw = &adapter->hw; - - *data = 0; - if (hw->phy.media_type == e1000_media_type_internal_serdes) { - int i = 0; - hw->mac.serdes_has_link = false; - - /* On some blade server designs, link establishment - * could take as long as 2-3 minutes - */ - do { - hw->mac.ops.check_for_link(hw); - if (hw->mac.serdes_has_link) - return *data; - msleep(20); - } while (i++ < 3750); - - *data = 1; - } else { - hw->mac.ops.check_for_link(hw); - if (hw->mac.autoneg) - /* On some Phy/switch combinations, link establishment - * can take a few seconds more than expected. - */ - msleep_interruptible(5000); - - if (!(er32(STATUS) & E1000_STATUS_LU)) - *data = 1; - } - return *data; -} - -static int e1000e_get_sset_count(struct net_device __always_unused *netdev, - int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E1000_TEST_LEN; - case ETH_SS_STATS: - return E1000_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e1000_diag_test(struct net_device *netdev, - struct ethtool_test *eth_test, u64 *data) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - u16 autoneg_advertised; - u8 forced_speed_duplex; - u8 autoneg; - bool if_running = netif_running(netdev); - - set_bit(__E1000_TESTING, &adapter->state); - - if (!if_running) { - /* Get control of and reset hardware */ - if (adapter->flags & FLAG_HAS_AMT) - e1000e_get_hw_control(adapter); - - e1000e_power_up_phy(adapter); - - adapter->hw.phy.autoneg_wait_to_complete = 1; - e1000e_reset(adapter); - adapter->hw.phy.autoneg_wait_to_complete = 0; - } - - if (eth_test->flags == ETH_TEST_FL_OFFLINE) { - /* Offline tests */ - - /* save speed, duplex, autoneg settings */ - autoneg_advertised = adapter->hw.phy.autoneg_advertised; - forced_speed_duplex = adapter->hw.mac.forced_speed_duplex; - autoneg = adapter->hw.mac.autoneg; - - e_info("offline testing starting\n"); - - if (if_running) - /* indicate we're in test mode */ - dev_close(netdev); - - if (e1000_reg_test(adapter, &data[0])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000e_reset(adapter); - if (e1000_eeprom_test(adapter, &data[1])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000e_reset(adapter); - if (e1000_intr_test(adapter, &data[2])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000e_reset(adapter); - if (e1000_loopback_test(adapter, &data[3])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - /* force this routine to wait until autoneg complete/timeout */ - adapter->hw.phy.autoneg_wait_to_complete = 1; - e1000e_reset(adapter); - adapter->hw.phy.autoneg_wait_to_complete = 0; - - if (e1000_link_test(adapter, &data[4])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - /* restore speed, duplex, autoneg settings */ - adapter->hw.phy.autoneg_advertised = autoneg_advertised; - adapter->hw.mac.forced_speed_duplex = forced_speed_duplex; - adapter->hw.mac.autoneg = autoneg; - e1000e_reset(adapter); - - clear_bit(__E1000_TESTING, &adapter->state); - if (if_running) - dev_open(netdev); - } else { - /* Online tests */ - - e_info("online testing starting\n"); - - /* register, eeprom, intr and loopback tests not run online */ - data[0] = 0; - data[1] = 0; - data[2] = 0; - data[3] = 0; - - if (e1000_link_test(adapter, &data[4])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - clear_bit(__E1000_TESTING, &adapter->state); - } - - if (!if_running) { - e1000e_reset(adapter); - - if (adapter->flags & FLAG_HAS_AMT) - e1000e_release_hw_control(adapter); - } - - msleep_interruptible(4 * 1000); -} - -static void e1000_get_wol(struct net_device *netdev, - struct ethtool_wolinfo *wol) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - wol->supported = 0; - wol->wolopts = 0; - - if (!(adapter->flags & FLAG_HAS_WOL) || - !device_can_wakeup(&adapter->pdev->dev)) - return; - - wol->supported = WAKE_UCAST | WAKE_MCAST | - WAKE_BCAST | WAKE_MAGIC | WAKE_PHY; - - /* apply any specific unsupported masks here */ - if (adapter->flags & FLAG_NO_WAKE_UCAST) { - wol->supported &= ~WAKE_UCAST; - - if (adapter->wol & E1000_WUFC_EX) - e_err("Interface does not support directed (unicast) frame wake-up packets\n"); - } - - if (adapter->wol & E1000_WUFC_EX) - wol->wolopts |= WAKE_UCAST; - if (adapter->wol & E1000_WUFC_MC) - wol->wolopts |= WAKE_MCAST; - if (adapter->wol & E1000_WUFC_BC) - wol->wolopts |= WAKE_BCAST; - if (adapter->wol & E1000_WUFC_MAG) - wol->wolopts |= WAKE_MAGIC; - if (adapter->wol & E1000_WUFC_LNKC) - wol->wolopts |= WAKE_PHY; -} - -static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (!(adapter->flags & FLAG_HAS_WOL) || - !device_can_wakeup(&adapter->pdev->dev) || - (wol->wolopts & ~(WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | - WAKE_MAGIC | WAKE_PHY))) - return -EOPNOTSUPP; - - /* these settings will always override what we currently have */ - adapter->wol = 0; - - if (wol->wolopts & WAKE_UCAST) - adapter->wol |= E1000_WUFC_EX; - if (wol->wolopts & WAKE_MCAST) - adapter->wol |= E1000_WUFC_MC; - if (wol->wolopts & WAKE_BCAST) - adapter->wol |= E1000_WUFC_BC; - if (wol->wolopts & WAKE_MAGIC) - adapter->wol |= E1000_WUFC_MAG; - if (wol->wolopts & WAKE_PHY) - adapter->wol |= E1000_WUFC_LNKC; - - device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); - - return 0; -} - -static int e1000_set_phys_id(struct net_device *netdev, - enum ethtool_phys_id_state state) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - switch (state) { - case ETHTOOL_ID_ACTIVE: - if (!hw->mac.ops.blink_led) - return 2; /* cycle on/off twice per second */ - - hw->mac.ops.blink_led(hw); - break; - - case ETHTOOL_ID_INACTIVE: - if (hw->phy.type == e1000_phy_ife) - e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0); - hw->mac.ops.led_off(hw); - hw->mac.ops.cleanup_led(hw); - break; - - case ETHTOOL_ID_ON: - hw->mac.ops.led_on(hw); - break; - - case ETHTOOL_ID_OFF: - hw->mac.ops.led_off(hw); - break; - } - return 0; -} - -static int e1000_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (adapter->itr_setting <= 4) - ec->rx_coalesce_usecs = adapter->itr_setting; - else - ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting; - - return 0; -} - -static int e1000_set_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || - ((ec->rx_coalesce_usecs > 4) && - (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) || - (ec->rx_coalesce_usecs == 2)) - return -EINVAL; - - if (ec->rx_coalesce_usecs == 4) { - adapter->itr_setting = 4; - adapter->itr = adapter->itr_setting; - } else if (ec->rx_coalesce_usecs <= 3) { - adapter->itr = 20000; - adapter->itr_setting = ec->rx_coalesce_usecs; - } else { - adapter->itr = (1000000 / ec->rx_coalesce_usecs); - adapter->itr_setting = adapter->itr & ~3; - } - - if (adapter->itr_setting != 0) - e1000e_write_itr(adapter, adapter->itr); - else - e1000e_write_itr(adapter, 0); - - return 0; -} - -static int e1000_nway_reset(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (!netif_running(netdev)) - return -EAGAIN; - - if (!adapter->hw.mac.autoneg) - return -EINVAL; - - e1000e_reinit_locked(adapter); - - return 0; -} - -static void e1000_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats __always_unused *stats, - u64 *data) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct rtnl_link_stats64 net_stats; - int i; - char *p = NULL; - - e1000e_get_stats64(netdev, &net_stats); - for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { - switch (e1000_gstrings_stats[i].type) { - case NETDEV_STATS: - p = (char *)&net_stats + - e1000_gstrings_stats[i].stat_offset; - break; - case E1000_STATS: - p = (char *)adapter + - e1000_gstrings_stats[i].stat_offset; - break; - default: - data[i] = 0; - continue; - } - - data[i] = (e1000_gstrings_stats[i].sizeof_stat == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } -} - -static void e1000_get_strings(struct net_device __always_unused *netdev, - u32 stringset, u8 *data) -{ - u8 *p = data; - int i; - - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, e1000_gstrings_test, sizeof(e1000_gstrings_test)); - break; - case ETH_SS_STATS: - for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { - memcpy(p, e1000_gstrings_stats[i].stat_string, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - } - break; - } -} - -static int e1000_get_rxnfc(struct net_device *netdev, - struct ethtool_rxnfc *info, - u32 __always_unused *rule_locs) -{ - info->data = 0; - - switch (info->cmd) { - case ETHTOOL_GRXFH: { - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 mrqc = er32(MRQC); - - if (!(mrqc & E1000_MRQC_RSS_FIELD_MASK)) - return 0; - - switch (info->flow_type) { - case TCP_V4_FLOW: - if (mrqc & E1000_MRQC_RSS_FIELD_IPV4_TCP) - info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fall through */ - case UDP_V4_FLOW: - case SCTP_V4_FLOW: - case AH_ESP_V4_FLOW: - case IPV4_FLOW: - if (mrqc & E1000_MRQC_RSS_FIELD_IPV4) - info->data |= RXH_IP_SRC | RXH_IP_DST; - break; - case TCP_V6_FLOW: - if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_TCP) - info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fall through */ - case UDP_V6_FLOW: - case SCTP_V6_FLOW: - case AH_ESP_V6_FLOW: - case IPV6_FLOW: - if (mrqc & E1000_MRQC_RSS_FIELD_IPV6) - info->data |= RXH_IP_SRC | RXH_IP_DST; - break; - default: - break; - } - return 0; - } - default: - return -EOPNOTSUPP; - } -} - -static int e1000e_get_eee(struct net_device *netdev, struct ethtool_eee *edata) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 cap_addr, lpa_addr, pcs_stat_addr, phy_data; - u32 ret_val; - - if (!(adapter->flags2 & FLAG2_HAS_EEE)) - return -EOPNOTSUPP; - - switch (hw->phy.type) { - case e1000_phy_82579: - cap_addr = I82579_EEE_CAPABILITY; - lpa_addr = I82579_EEE_LP_ABILITY; - pcs_stat_addr = I82579_EEE_PCS_STATUS; - break; - case e1000_phy_i217: - cap_addr = I217_EEE_CAPABILITY; - lpa_addr = I217_EEE_LP_ABILITY; - pcs_stat_addr = I217_EEE_PCS_STATUS; - break; - default: - return -EOPNOTSUPP; - } - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return -EBUSY; - - /* EEE Capability */ - ret_val = e1000_read_emi_reg_locked(hw, cap_addr, &phy_data); - if (ret_val) - goto release; - edata->supported = mmd_eee_cap_to_ethtool_sup_t(phy_data); - - /* EEE Advertised */ - edata->advertised = mmd_eee_adv_to_ethtool_adv_t(adapter->eee_advert); - - /* EEE Link Partner Advertised */ - ret_val = e1000_read_emi_reg_locked(hw, lpa_addr, &phy_data); - if (ret_val) - goto release; - edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data); - - /* EEE PCS Status */ - ret_val = e1000_read_emi_reg_locked(hw, pcs_stat_addr, &phy_data); - if (hw->phy.type == e1000_phy_82579) - phy_data <<= 8; - -release: - hw->phy.ops.release(hw); - if (ret_val) - return -ENODATA; - - /* Result of the EEE auto negotiation - there is no register that - * has the status of the EEE negotiation so do a best-guess based - * on whether Tx or Rx LPI indications have been received. - */ - if (phy_data & (E1000_EEE_TX_LPI_RCVD | E1000_EEE_RX_LPI_RCVD)) - edata->eee_active = true; - - edata->eee_enabled = !hw->dev_spec.ich8lan.eee_disable; - edata->tx_lpi_enabled = true; - edata->tx_lpi_timer = er32(LPIC) >> E1000_LPIC_LPIET_SHIFT; - - return 0; -} - -static int e1000e_set_eee(struct net_device *netdev, struct ethtool_eee *edata) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct ethtool_eee eee_curr; - s32 ret_val; - - ret_val = e1000e_get_eee(netdev, &eee_curr); - if (ret_val) - return ret_val; - - if (eee_curr.tx_lpi_enabled != edata->tx_lpi_enabled) { - e_err("Setting EEE tx-lpi is not supported\n"); - return -EINVAL; - } - - if (eee_curr.tx_lpi_timer != edata->tx_lpi_timer) { - e_err("Setting EEE Tx LPI timer is not supported\n"); - return -EINVAL; - } - - if (edata->advertised & ~(ADVERTISE_100_FULL | ADVERTISE_1000_FULL)) { - e_err("EEE advertisement supports only 100TX and/or 1000T full-duplex\n"); - return -EINVAL; - } - - adapter->eee_advert = ethtool_adv_to_mmd_eee_adv_t(edata->advertised); - - hw->dev_spec.ich8lan.eee_disable = !edata->eee_enabled; - - /* reset the link */ - if (netif_running(netdev)) - e1000e_reinit_locked(adapter); - else - e1000e_reset(adapter); - - return 0; -} - -static int e1000e_get_ts_info(struct net_device *netdev, - struct ethtool_ts_info *info) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - ethtool_op_get_ts_info(netdev, info); - - if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP)) - return 0; - - info->so_timestamping |= (SOF_TIMESTAMPING_TX_HARDWARE | - SOF_TIMESTAMPING_RX_HARDWARE | - SOF_TIMESTAMPING_RAW_HARDWARE); - - info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); - - info->rx_filters = ((1 << HWTSTAMP_FILTER_NONE) | - (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | - (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_ALL)); - - if (adapter->ptp_clock) - info->phc_index = ptp_clock_index(adapter->ptp_clock); - - return 0; -} - -static int e1000e_ethtool_begin(struct net_device *netdev) -{ - return pm_runtime_get_sync(netdev->dev.parent); -} - -static void e1000e_ethtool_complete(struct net_device *netdev) -{ - pm_runtime_put_sync(netdev->dev.parent); -} - -static const struct ethtool_ops e1000_ethtool_ops = { - .begin = e1000e_ethtool_begin, - .complete = e1000e_ethtool_complete, - .get_settings = e1000_get_settings, - .set_settings = e1000_set_settings, - .get_drvinfo = e1000_get_drvinfo, - .get_regs_len = e1000_get_regs_len, - .get_regs = e1000_get_regs, - .get_wol = e1000_get_wol, - .set_wol = e1000_set_wol, - .get_msglevel = e1000_get_msglevel, - .set_msglevel = e1000_set_msglevel, - .nway_reset = e1000_nway_reset, - .get_link = ethtool_op_get_link, - .get_eeprom_len = e1000_get_eeprom_len, - .get_eeprom = e1000_get_eeprom, - .set_eeprom = e1000_set_eeprom, - .get_ringparam = e1000_get_ringparam, - .set_ringparam = e1000_set_ringparam, - .get_pauseparam = e1000_get_pauseparam, - .set_pauseparam = e1000_set_pauseparam, - .self_test = e1000_diag_test, - .get_strings = e1000_get_strings, - .set_phys_id = e1000_set_phys_id, - .get_ethtool_stats = e1000_get_ethtool_stats, - .get_sset_count = e1000e_get_sset_count, - .get_coalesce = e1000_get_coalesce, - .set_coalesce = e1000_set_coalesce, - .get_rxnfc = e1000_get_rxnfc, - .get_ts_info = e1000e_get_ts_info, - .get_eee = e1000e_get_eee, - .set_eee = e1000e_set_eee, -}; - -void e1000e_set_ethtool_ops(struct net_device *netdev) -{ - SET_ETHTOOL_OPS(netdev, &e1000_ethtool_ops); -} diff --git a/addons/e1000e/src/3.10.108/hw.h b/addons/e1000e/src/3.10.108/hw.h deleted file mode 100644 index 84850f7a..00000000 --- a/addons/e1000e/src/3.10.108/hw.h +++ /dev/null @@ -1,681 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#ifndef _E1000_HW_H_ -#define _E1000_HW_H_ - -#include "regs.h" -#include "defines.h" - -struct e1000_hw; - -#define E1000_DEV_ID_82571EB_COPPER 0x105E -#define E1000_DEV_ID_82571EB_FIBER 0x105F -#define E1000_DEV_ID_82571EB_SERDES 0x1060 -#define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4 -#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5 -#define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5 -#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP 0x10BC -#define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9 -#define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA -#define E1000_DEV_ID_82572EI_COPPER 0x107D -#define E1000_DEV_ID_82572EI_FIBER 0x107E -#define E1000_DEV_ID_82572EI_SERDES 0x107F -#define E1000_DEV_ID_82572EI 0x10B9 -#define E1000_DEV_ID_82573E 0x108B -#define E1000_DEV_ID_82573E_IAMT 0x108C -#define E1000_DEV_ID_82573L 0x109A -#define E1000_DEV_ID_82574L 0x10D3 -#define E1000_DEV_ID_82574LA 0x10F6 -#define E1000_DEV_ID_82583V 0x150C -#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 -#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 -#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA -#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB -#define E1000_DEV_ID_ICH8_82567V_3 0x1501 -#define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049 -#define E1000_DEV_ID_ICH8_IGP_AMT 0x104A -#define E1000_DEV_ID_ICH8_IGP_C 0x104B -#define E1000_DEV_ID_ICH8_IFE 0x104C -#define E1000_DEV_ID_ICH8_IFE_GT 0x10C4 -#define E1000_DEV_ID_ICH8_IFE_G 0x10C5 -#define E1000_DEV_ID_ICH8_IGP_M 0x104D -#define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD -#define E1000_DEV_ID_ICH9_BM 0x10E5 -#define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5 -#define E1000_DEV_ID_ICH9_IGP_M 0x10BF -#define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB -#define E1000_DEV_ID_ICH9_IGP_C 0x294C -#define E1000_DEV_ID_ICH9_IFE 0x10C0 -#define E1000_DEV_ID_ICH9_IFE_GT 0x10C3 -#define E1000_DEV_ID_ICH9_IFE_G 0x10C2 -#define E1000_DEV_ID_ICH10_R_BM_LM 0x10CC -#define E1000_DEV_ID_ICH10_R_BM_LF 0x10CD -#define E1000_DEV_ID_ICH10_R_BM_V 0x10CE -#define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE -#define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF -#define E1000_DEV_ID_ICH10_D_BM_V 0x1525 -#define E1000_DEV_ID_PCH_M_HV_LM 0x10EA -#define E1000_DEV_ID_PCH_M_HV_LC 0x10EB -#define E1000_DEV_ID_PCH_D_HV_DM 0x10EF -#define E1000_DEV_ID_PCH_D_HV_DC 0x10F0 -#define E1000_DEV_ID_PCH2_LV_LM 0x1502 -#define E1000_DEV_ID_PCH2_LV_V 0x1503 -#define E1000_DEV_ID_PCH_LPT_I217_LM 0x153A -#define E1000_DEV_ID_PCH_LPT_I217_V 0x153B -#define E1000_DEV_ID_PCH_LPTLP_I218_LM 0x155A -#define E1000_DEV_ID_PCH_LPTLP_I218_V 0x1559 - -#define E1000_REVISION_4 4 - -#define E1000_FUNC_1 1 - -#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0 -#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3 - -enum e1000_mac_type { - e1000_82571, - e1000_82572, - e1000_82573, - e1000_82574, - e1000_82583, - e1000_80003es2lan, - e1000_ich8lan, - e1000_ich9lan, - e1000_ich10lan, - e1000_pchlan, - e1000_pch2lan, - e1000_pch_lpt, -}; - -enum e1000_media_type { - e1000_media_type_unknown = 0, - e1000_media_type_copper = 1, - e1000_media_type_fiber = 2, - e1000_media_type_internal_serdes = 3, - e1000_num_media_types -}; - -enum e1000_nvm_type { - e1000_nvm_unknown = 0, - e1000_nvm_none, - e1000_nvm_eeprom_spi, - e1000_nvm_flash_hw, - e1000_nvm_flash_sw -}; - -enum e1000_nvm_override { - e1000_nvm_override_none = 0, - e1000_nvm_override_spi_small, - e1000_nvm_override_spi_large -}; - -enum e1000_phy_type { - e1000_phy_unknown = 0, - e1000_phy_none, - e1000_phy_m88, - e1000_phy_igp, - e1000_phy_igp_2, - e1000_phy_gg82563, - e1000_phy_igp_3, - e1000_phy_ife, - e1000_phy_bm, - e1000_phy_82578, - e1000_phy_82577, - e1000_phy_82579, - e1000_phy_i217, -}; - -enum e1000_bus_width { - e1000_bus_width_unknown = 0, - e1000_bus_width_pcie_x1, - e1000_bus_width_pcie_x2, - e1000_bus_width_pcie_x4 = 4, - e1000_bus_width_32, - e1000_bus_width_64, - e1000_bus_width_reserved -}; - -enum e1000_1000t_rx_status { - e1000_1000t_rx_status_not_ok = 0, - e1000_1000t_rx_status_ok, - e1000_1000t_rx_status_undefined = 0xFF -}; - -enum e1000_rev_polarity { - e1000_rev_polarity_normal = 0, - e1000_rev_polarity_reversed, - e1000_rev_polarity_undefined = 0xFF -}; - -enum e1000_fc_mode { - e1000_fc_none = 0, - e1000_fc_rx_pause, - e1000_fc_tx_pause, - e1000_fc_full, - e1000_fc_default = 0xFF -}; - -enum e1000_ms_type { - e1000_ms_hw_default = 0, - e1000_ms_force_master, - e1000_ms_force_slave, - e1000_ms_auto -}; - -enum e1000_smart_speed { - e1000_smart_speed_default = 0, - e1000_smart_speed_on, - e1000_smart_speed_off -}; - -enum e1000_serdes_link_state { - e1000_serdes_link_down = 0, - e1000_serdes_link_autoneg_progress, - e1000_serdes_link_autoneg_complete, - e1000_serdes_link_forced_up -}; - -/* Receive Descriptor - Extended */ -union e1000_rx_desc_extended { - struct { - __le64 buffer_addr; - __le64 reserved; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length; - __le16 vlan; /* VLAN tag */ - } upper; - } wb; /* writeback */ -}; - -#define MAX_PS_BUFFERS 4 -/* Receive Descriptor - Packet Split */ -union e1000_rx_desc_packet_split { - struct { - /* one buffer for protocol header(s), three data buffers */ - __le64 buffer_addr[MAX_PS_BUFFERS]; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length0; /* length of buffer 0 */ - __le16 vlan; /* VLAN tag */ - } middle; - struct { - __le16 header_status; - __le16 length[3]; /* length of buffers 1-3 */ - } upper; - __le64 reserved; - } wb; /* writeback */ -}; - -/* Transmit Descriptor */ -struct e1000_tx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 cso; /* Checksum offset */ - u8 cmd; /* Descriptor control */ - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 css; /* Checksum start */ - __le16 special; - } fields; - } upper; -}; - -/* Offload Context Descriptor */ -struct e1000_context_desc { - union { - __le32 ip_config; - struct { - u8 ipcss; /* IP checksum start */ - u8 ipcso; /* IP checksum offset */ - __le16 ipcse; /* IP checksum end */ - } ip_fields; - } lower_setup; - union { - __le32 tcp_config; - struct { - u8 tucss; /* TCP checksum start */ - u8 tucso; /* TCP checksum offset */ - __le16 tucse; /* TCP checksum end */ - } tcp_fields; - } upper_setup; - __le32 cmd_and_length; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 hdr_len; /* Header length */ - __le16 mss; /* Maximum segment size */ - } fields; - } tcp_seg_setup; -}; - -/* Offload data descriptor */ -struct e1000_data_desc { - __le64 buffer_addr; /* Address of the descriptor's buffer address */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 typ_len_ext; - u8 cmd; - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 popts; /* Packet Options */ - __le16 special; - } fields; - } upper; -}; - -/* Statistics counters collected by the MAC */ -struct e1000_hw_stats { - u64 crcerrs; - u64 algnerrc; - u64 symerrs; - u64 rxerrc; - u64 mpc; - u64 scc; - u64 ecol; - u64 mcc; - u64 latecol; - u64 colc; - u64 dc; - u64 tncrs; - u64 sec; - u64 cexterr; - u64 rlec; - u64 xonrxc; - u64 xontxc; - u64 xoffrxc; - u64 xofftxc; - u64 fcruc; - u64 prc64; - u64 prc127; - u64 prc255; - u64 prc511; - u64 prc1023; - u64 prc1522; - u64 gprc; - u64 bprc; - u64 mprc; - u64 gptc; - u64 gorc; - u64 gotc; - u64 rnbc; - u64 ruc; - u64 rfc; - u64 roc; - u64 rjc; - u64 mgprc; - u64 mgpdc; - u64 mgptc; - u64 tor; - u64 tot; - u64 tpr; - u64 tpt; - u64 ptc64; - u64 ptc127; - u64 ptc255; - u64 ptc511; - u64 ptc1023; - u64 ptc1522; - u64 mptc; - u64 bptc; - u64 tsctc; - u64 tsctfc; - u64 iac; - u64 icrxptc; - u64 icrxatc; - u64 ictxptc; - u64 ictxatc; - u64 ictxqec; - u64 ictxqmtc; - u64 icrxdmtc; - u64 icrxoc; -}; - -struct e1000_phy_stats { - u32 idle_errors; - u32 receive_errors; -}; - -struct e1000_host_mng_dhcp_cookie { - u32 signature; - u8 status; - u8 reserved0; - u16 vlan_id; - u32 reserved1; - u16 reserved2; - u8 reserved3; - u8 checksum; -}; - -/* Host Interface "Rev 1" */ -struct e1000_host_command_header { - u8 command_id; - u8 command_length; - u8 command_options; - u8 checksum; -}; - -#define E1000_HI_MAX_DATA_LENGTH 252 -struct e1000_host_command_info { - struct e1000_host_command_header command_header; - u8 command_data[E1000_HI_MAX_DATA_LENGTH]; -}; - -/* Host Interface "Rev 2" */ -struct e1000_host_mng_command_header { - u8 command_id; - u8 checksum; - u16 reserved1; - u16 reserved2; - u16 command_length; -}; - -#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 -struct e1000_host_mng_command_info { - struct e1000_host_mng_command_header command_header; - u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; -}; - -#include "mac.h" -#include "phy.h" -#include "nvm.h" -#include "manage.h" - -/* Function pointers for the MAC. */ -struct e1000_mac_operations { - s32 (*id_led_init)(struct e1000_hw *); - s32 (*blink_led)(struct e1000_hw *); - bool (*check_mng_mode)(struct e1000_hw *); - s32 (*check_for_link)(struct e1000_hw *); - s32 (*cleanup_led)(struct e1000_hw *); - void (*clear_hw_cntrs)(struct e1000_hw *); - void (*clear_vfta)(struct e1000_hw *); - s32 (*get_bus_info)(struct e1000_hw *); - void (*set_lan_id)(struct e1000_hw *); - s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *); - s32 (*led_on)(struct e1000_hw *); - s32 (*led_off)(struct e1000_hw *); - void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32); - s32 (*reset_hw)(struct e1000_hw *); - s32 (*init_hw)(struct e1000_hw *); - s32 (*setup_link)(struct e1000_hw *); - s32 (*setup_physical_interface)(struct e1000_hw *); - s32 (*setup_led)(struct e1000_hw *); - void (*write_vfta)(struct e1000_hw *, u32, u32); - void (*config_collision_dist)(struct e1000_hw *); - void (*rar_set)(struct e1000_hw *, u8 *, u32); - s32 (*read_mac_addr)(struct e1000_hw *); -}; - -/* When to use various PHY register access functions: - * - * Func Caller - * Function Does Does When to use - * ~~~~~~~~~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * X_reg L,P,A n/a for simple PHY reg accesses - * X_reg_locked P,A L for multiple accesses of different regs - * on different pages - * X_reg_page A L,P for multiple accesses of different regs - * on the same page - * - * Where X=[read|write], L=locking, P=sets page, A=register access - * - */ -struct e1000_phy_operations { - s32 (*acquire)(struct e1000_hw *); - s32 (*cfg_on_link_up)(struct e1000_hw *); - s32 (*check_polarity)(struct e1000_hw *); - s32 (*check_reset_block)(struct e1000_hw *); - s32 (*commit)(struct e1000_hw *); - s32 (*force_speed_duplex)(struct e1000_hw *); - s32 (*get_cfg_done)(struct e1000_hw *hw); - s32 (*get_cable_length)(struct e1000_hw *); - s32 (*get_info)(struct e1000_hw *); - s32 (*set_page)(struct e1000_hw *, u16); - s32 (*read_reg)(struct e1000_hw *, u32, u16 *); - s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *); - s32 (*read_reg_page)(struct e1000_hw *, u32, u16 *); - void (*release)(struct e1000_hw *); - s32 (*reset)(struct e1000_hw *); - s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); - s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); - s32 (*write_reg)(struct e1000_hw *, u32, u16); - s32 (*write_reg_locked)(struct e1000_hw *, u32, u16); - s32 (*write_reg_page)(struct e1000_hw *, u32, u16); - void (*power_up)(struct e1000_hw *); - void (*power_down)(struct e1000_hw *); -}; - -/* Function pointers for the NVM. */ -struct e1000_nvm_operations { - s32 (*acquire)(struct e1000_hw *); - s32 (*read)(struct e1000_hw *, u16, u16, u16 *); - void (*release)(struct e1000_hw *); - void (*reload)(struct e1000_hw *); - s32 (*update)(struct e1000_hw *); - s32 (*valid_led_default)(struct e1000_hw *, u16 *); - s32 (*validate)(struct e1000_hw *); - s32 (*write)(struct e1000_hw *, u16, u16, u16 *); -}; - -struct e1000_mac_info { - struct e1000_mac_operations ops; - u8 addr[ETH_ALEN]; - u8 perm_addr[ETH_ALEN]; - - enum e1000_mac_type type; - - u32 collision_delta; - u32 ledctl_default; - u32 ledctl_mode1; - u32 ledctl_mode2; - u32 mc_filter_type; - u32 tx_packet_delta; - u32 txcw; - - u16 current_ifs_val; - u16 ifs_max_val; - u16 ifs_min_val; - u16 ifs_ratio; - u16 ifs_step_size; - u16 mta_reg_count; - - /* Maximum size of the MTA register table in all supported adapters */ -#define MAX_MTA_REG 128 - u32 mta_shadow[MAX_MTA_REG]; - u16 rar_entry_count; - - u8 forced_speed_duplex; - - bool adaptive_ifs; - bool has_fwsm; - bool arc_subsystem_valid; - bool autoneg; - bool autoneg_failed; - bool get_link_status; - bool in_ifs_mode; - bool serdes_has_link; - bool tx_pkt_filtering; - enum e1000_serdes_link_state serdes_link_state; -}; - -struct e1000_phy_info { - struct e1000_phy_operations ops; - - enum e1000_phy_type type; - - enum e1000_1000t_rx_status local_rx; - enum e1000_1000t_rx_status remote_rx; - enum e1000_ms_type ms_type; - enum e1000_ms_type original_ms_type; - enum e1000_rev_polarity cable_polarity; - enum e1000_smart_speed smart_speed; - - u32 addr; - u32 id; - u32 reset_delay_us; /* in usec */ - u32 revision; - - enum e1000_media_type media_type; - - u16 autoneg_advertised; - u16 autoneg_mask; - u16 cable_length; - u16 max_cable_length; - u16 min_cable_length; - - u8 mdix; - - bool disable_polarity_correction; - bool is_mdix; - bool polarity_correction; - bool speed_downgraded; - bool autoneg_wait_to_complete; -}; - -struct e1000_nvm_info { - struct e1000_nvm_operations ops; - - enum e1000_nvm_type type; - enum e1000_nvm_override override; - - u32 flash_bank_size; - u32 flash_base_addr; - - u16 word_size; - u16 delay_usec; - u16 address_bits; - u16 opcode_bits; - u16 page_size; -}; - -struct e1000_bus_info { - enum e1000_bus_width width; - - u16 func; -}; - -struct e1000_fc_info { - u32 high_water; /* Flow control high-water mark */ - u32 low_water; /* Flow control low-water mark */ - u16 pause_time; /* Flow control pause timer */ - u16 refresh_time; /* Flow control refresh timer */ - bool send_xon; /* Flow control send XON */ - bool strict_ieee; /* Strict IEEE mode */ - enum e1000_fc_mode current_mode; /* FC mode in effect */ - enum e1000_fc_mode requested_mode; /* FC mode requested by caller */ -}; - -struct e1000_dev_spec_82571 { - bool laa_is_present; - u32 smb_counter; -}; - -struct e1000_dev_spec_80003es2lan { - bool mdic_wa_enable; -}; - -struct e1000_shadow_ram { - u16 value; - bool modified; -}; - -#define E1000_ICH8_SHADOW_RAM_WORDS 2048 - -struct e1000_dev_spec_ich8lan { - bool kmrn_lock_loss_workaround_enabled; - struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS]; - bool nvm_k1_enabled; - bool eee_disable; - u16 eee_lp_ability; -}; - -struct e1000_hw { - struct e1000_adapter *adapter; - - void __iomem *hw_addr; - void __iomem *flash_address; - - struct e1000_mac_info mac; - struct e1000_fc_info fc; - struct e1000_phy_info phy; - struct e1000_nvm_info nvm; - struct e1000_bus_info bus; - struct e1000_host_mng_dhcp_cookie mng_cookie; - - union { - struct e1000_dev_spec_82571 e82571; - struct e1000_dev_spec_80003es2lan e80003es2lan; - struct e1000_dev_spec_ich8lan ich8lan; - } dev_spec; -}; - -#include "82571.h" -#include "80003es2lan.h" -#include "ich8lan.h" - -#endif diff --git a/addons/e1000e/src/3.10.108/ich8lan.c b/addons/e1000e/src/3.10.108/ich8lan.c deleted file mode 100644 index ad9d8f2d..00000000 --- a/addons/e1000e/src/3.10.108/ich8lan.c +++ /dev/null @@ -1,4738 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* 82562G 10/100 Network Connection - * 82562G-2 10/100 Network Connection - * 82562GT 10/100 Network Connection - * 82562GT-2 10/100 Network Connection - * 82562V 10/100 Network Connection - * 82562V-2 10/100 Network Connection - * 82566DC-2 Gigabit Network Connection - * 82566DC Gigabit Network Connection - * 82566DM-2 Gigabit Network Connection - * 82566DM Gigabit Network Connection - * 82566MC Gigabit Network Connection - * 82566MM Gigabit Network Connection - * 82567LM Gigabit Network Connection - * 82567LF Gigabit Network Connection - * 82567V Gigabit Network Connection - * 82567LM-2 Gigabit Network Connection - * 82567LF-2 Gigabit Network Connection - * 82567V-2 Gigabit Network Connection - * 82567LF-3 Gigabit Network Connection - * 82567LM-3 Gigabit Network Connection - * 82567LM-4 Gigabit Network Connection - * 82577LM Gigabit Network Connection - * 82577LC Gigabit Network Connection - * 82578DM Gigabit Network Connection - * 82578DC Gigabit Network Connection - * 82579LM Gigabit Network Connection - * 82579V Gigabit Network Connection - */ - -#include "e1000.h" - -/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ -/* Offset 04h HSFSTS */ -union ich8_hws_flash_status { - struct ich8_hsfsts { - u16 flcdone:1; /* bit 0 Flash Cycle Done */ - u16 flcerr:1; /* bit 1 Flash Cycle Error */ - u16 dael:1; /* bit 2 Direct Access error Log */ - u16 berasesz:2; /* bit 4:3 Sector Erase Size */ - u16 flcinprog:1; /* bit 5 flash cycle in Progress */ - u16 reserved1:2; /* bit 13:6 Reserved */ - u16 reserved2:6; /* bit 13:6 Reserved */ - u16 fldesvalid:1; /* bit 14 Flash Descriptor Valid */ - u16 flockdn:1; /* bit 15 Flash Config Lock-Down */ - } hsf_status; - u16 regval; -}; - -/* ICH GbE Flash Hardware Sequencing Flash control Register bit breakdown */ -/* Offset 06h FLCTL */ -union ich8_hws_flash_ctrl { - struct ich8_hsflctl { - u16 flcgo:1; /* 0 Flash Cycle Go */ - u16 flcycle:2; /* 2:1 Flash Cycle */ - u16 reserved:5; /* 7:3 Reserved */ - u16 fldbcount:2; /* 9:8 Flash Data Byte Count */ - u16 flockdn:6; /* 15:10 Reserved */ - } hsf_ctrl; - u16 regval; -}; - -/* ICH Flash Region Access Permissions */ -union ich8_hws_flash_regacc { - struct ich8_flracc { - u32 grra:8; /* 0:7 GbE region Read Access */ - u32 grwa:8; /* 8:15 GbE region Write Access */ - u32 gmrag:8; /* 23:16 GbE Master Read Access Grant */ - u32 gmwag:8; /* 31:24 GbE Master Write Access Grant */ - } hsf_flregacc; - u16 regval; -}; - -/* ICH Flash Protected Region */ -union ich8_flash_protected_range { - struct ich8_pr { - u32 base:13; /* 0:12 Protected Range Base */ - u32 reserved1:2; /* 13:14 Reserved */ - u32 rpe:1; /* 15 Read Protection Enable */ - u32 limit:13; /* 16:28 Protected Range Limit */ - u32 reserved2:2; /* 29:30 Reserved */ - u32 wpe:1; /* 31 Write Protection Enable */ - } range; - u32 regval; -}; - -static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); -static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); -static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank); -static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, - u32 offset, u8 byte); -static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, - u8 *data); -static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, - u16 *data); -static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, - u8 size, u16 *data); -static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw); -static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw); -static s32 e1000_led_on_ich8lan(struct e1000_hw *hw); -static s32 e1000_led_off_ich8lan(struct e1000_hw *hw); -static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw); -static s32 e1000_setup_led_pchlan(struct e1000_hw *hw); -static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw); -static s32 e1000_led_on_pchlan(struct e1000_hw *hw); -static s32 e1000_led_off_pchlan(struct e1000_hw *hw); -static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); -static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); -static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); -static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); -static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw); -static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); -static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw); -static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index); -static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index); -static s32 e1000_k1_workaround_lv(struct e1000_hw *hw); -static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate); -static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw); - -static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) -{ - return readw(hw->flash_address + reg); -} - -static inline u32 __er32flash(struct e1000_hw *hw, unsigned long reg) -{ - return readl(hw->flash_address + reg); -} - -static inline void __ew16flash(struct e1000_hw *hw, unsigned long reg, u16 val) -{ - writew(val, hw->flash_address + reg); -} - -static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val) -{ - writel(val, hw->flash_address + reg); -} - -#define er16flash(reg) __er16flash(hw, (reg)) -#define er32flash(reg) __er32flash(hw, (reg)) -#define ew16flash(reg, val) __ew16flash(hw, (reg), (val)) -#define ew32flash(reg, val) __ew32flash(hw, (reg), (val)) - -/** - * e1000_phy_is_accessible_pchlan - Check if able to access PHY registers - * @hw: pointer to the HW structure - * - * Test access to the PHY registers by reading the PHY ID registers. If - * the PHY ID is already known (e.g. resume path) compare it with known ID, - * otherwise assume the read PHY ID is correct if it is valid. - * - * Assumes the sw/fw/hw semaphore is already acquired. - **/ -static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw) -{ - u16 phy_reg = 0; - u32 phy_id = 0; - s32 ret_val; - u16 retry_count; - - for (retry_count = 0; retry_count < 2; retry_count++) { - ret_val = e1e_rphy_locked(hw, MII_PHYSID1, &phy_reg); - if (ret_val || (phy_reg == 0xFFFF)) - continue; - phy_id = (u32)(phy_reg << 16); - - ret_val = e1e_rphy_locked(hw, MII_PHYSID2, &phy_reg); - if (ret_val || (phy_reg == 0xFFFF)) { - phy_id = 0; - continue; - } - phy_id |= (u32)(phy_reg & PHY_REVISION_MASK); - break; - } - - if (hw->phy.id) { - if (hw->phy.id == phy_id) - return true; - } else if (phy_id) { - hw->phy.id = phy_id; - hw->phy.revision = (u32)(phy_reg & ~PHY_REVISION_MASK); - return true; - } - - /* In case the PHY needs to be in mdio slow mode, - * set slow mode and try to get the PHY id again. - */ - hw->phy.ops.release(hw); - ret_val = e1000_set_mdio_slow_mode_hv(hw); - if (!ret_val) - ret_val = e1000e_get_phy_id(hw); - hw->phy.ops.acquire(hw); - - return !ret_val; -} - -/** - * e1000_init_phy_workarounds_pchlan - PHY initialization workarounds - * @hw: pointer to the HW structure - * - * Workarounds/flow necessary for PHY initialization during driver load - * and resume paths. - **/ -static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) -{ - u32 mac_reg, fwsm = er32(FWSM); - s32 ret_val; - u16 phy_reg; - - /* Gate automatic PHY configuration by hardware on managed and - * non-managed 82579 and newer adapters. - */ - e1000_gate_hw_phy_config_ich8lan(hw, true); - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) { - e_dbg("Failed to initialize PHY flow\n"); - goto out; - } - - /* The MAC-PHY interconnect may be in SMBus mode. If the PHY is - * inaccessible and resetting the PHY is not blocked, toggle the - * LANPHYPC Value bit to force the interconnect to PCIe mode. - */ - switch (hw->mac.type) { - case e1000_pch_lpt: - if (e1000_phy_is_accessible_pchlan(hw)) - break; - - /* Before toggling LANPHYPC, see if PHY is accessible by - * forcing MAC to SMBus mode first. - */ - mac_reg = er32(CTRL_EXT); - mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; - ew32(CTRL_EXT, mac_reg); - - /* fall-through */ - case e1000_pch2lan: - if (e1000_phy_is_accessible_pchlan(hw)) { - if (hw->mac.type == e1000_pch_lpt) { - /* Unforce SMBus mode in PHY */ - e1e_rphy_locked(hw, CV_SMB_CTRL, &phy_reg); - phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; - e1e_wphy_locked(hw, CV_SMB_CTRL, phy_reg); - - /* Unforce SMBus mode in MAC */ - mac_reg = er32(CTRL_EXT); - mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; - ew32(CTRL_EXT, mac_reg); - } - break; - } - - /* fall-through */ - case e1000_pchlan: - if ((hw->mac.type == e1000_pchlan) && - (fwsm & E1000_ICH_FWSM_FW_VALID)) - break; - - if (hw->phy.ops.check_reset_block(hw)) { - e_dbg("Required LANPHYPC toggle blocked by ME\n"); - break; - } - - e_dbg("Toggling LANPHYPC\n"); - - /* Set Phy Config Counter to 50msec */ - mac_reg = er32(FEXTNVM3); - mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; - mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; - ew32(FEXTNVM3, mac_reg); - - if (hw->mac.type == e1000_pch_lpt) { - /* Toggling LANPHYPC brings the PHY out of SMBus mode - * So ensure that the MAC is also out of SMBus mode - */ - mac_reg = er32(CTRL_EXT); - mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; - ew32(CTRL_EXT, mac_reg); - } - - /* Toggle LANPHYPC Value bit */ - mac_reg = er32(CTRL); - mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE; - mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE; - ew32(CTRL, mac_reg); - e1e_flush(); - usleep_range(10, 20); - mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE; - ew32(CTRL, mac_reg); - e1e_flush(); - if (hw->mac.type < e1000_pch_lpt) { - msleep(50); - } else { - u16 count = 20; - do { - usleep_range(5000, 10000); - } while (!(er32(CTRL_EXT) & - E1000_CTRL_EXT_LPCD) && count--); - } - break; - default: - break; - } - - hw->phy.ops.release(hw); - - /* Reset the PHY before any access to it. Doing so, ensures - * that the PHY is in a known good state before we read/write - * PHY registers. The generic reset is sufficient here, - * because we haven't determined the PHY type yet. - */ - ret_val = e1000e_phy_hw_reset_generic(hw); - -out: - /* Ungate automatic PHY configuration on non-managed 82579 */ - if ((hw->mac.type == e1000_pch2lan) && - !(fwsm & E1000_ICH_FWSM_FW_VALID)) { - usleep_range(10000, 20000); - e1000_gate_hw_phy_config_ich8lan(hw, false); - } - - return ret_val; -} - -/** - * e1000_init_phy_params_pchlan - Initialize PHY function pointers - * @hw: pointer to the HW structure - * - * Initialize family-specific PHY parameters and function pointers. - **/ -static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - - phy->addr = 1; - phy->reset_delay_us = 100; - - phy->ops.set_page = e1000_set_page_igp; - phy->ops.read_reg = e1000_read_phy_reg_hv; - phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked; - phy->ops.read_reg_page = e1000_read_phy_reg_page_hv; - phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan; - phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan; - phy->ops.write_reg = e1000_write_phy_reg_hv; - phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked; - phy->ops.write_reg_page = e1000_write_phy_reg_page_hv; - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - - phy->id = e1000_phy_unknown; - - ret_val = e1000_init_phy_workarounds_pchlan(hw); - if (ret_val) - return ret_val; - - if (phy->id == e1000_phy_unknown) - switch (hw->mac.type) { - default: - ret_val = e1000e_get_phy_id(hw); - if (ret_val) - return ret_val; - if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK)) - break; - /* fall-through */ - case e1000_pch2lan: - case e1000_pch_lpt: - /* In case the PHY needs to be in mdio slow mode, - * set slow mode and try to get the PHY id again. - */ - ret_val = e1000_set_mdio_slow_mode_hv(hw); - if (ret_val) - return ret_val; - ret_val = e1000e_get_phy_id(hw); - if (ret_val) - return ret_val; - break; - } - phy->type = e1000e_get_phy_type_from_id(phy->id); - - switch (phy->type) { - case e1000_phy_82577: - case e1000_phy_82579: - case e1000_phy_i217: - phy->ops.check_polarity = e1000_check_polarity_82577; - phy->ops.force_speed_duplex = - e1000_phy_force_speed_duplex_82577; - phy->ops.get_cable_length = e1000_get_cable_length_82577; - phy->ops.get_info = e1000_get_phy_info_82577; - phy->ops.commit = e1000e_phy_sw_reset; - break; - case e1000_phy_82578: - phy->ops.check_polarity = e1000_check_polarity_m88; - phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_m88; - phy->ops.get_cable_length = e1000e_get_cable_length_m88; - phy->ops.get_info = e1000e_get_phy_info_m88; - break; - default: - ret_val = -E1000_ERR_PHY; - break; - } - - return ret_val; -} - -/** - * e1000_init_phy_params_ich8lan - Initialize PHY function pointers - * @hw: pointer to the HW structure - * - * Initialize family-specific PHY parameters and function pointers. - **/ -static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 i = 0; - - phy->addr = 1; - phy->reset_delay_us = 100; - - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; - - /* We may need to do this twice - once for IGP and if that fails, - * we'll set BM func pointers and try again - */ - ret_val = e1000e_determine_phy_address(hw); - if (ret_val) { - phy->ops.write_reg = e1000e_write_phy_reg_bm; - phy->ops.read_reg = e1000e_read_phy_reg_bm; - ret_val = e1000e_determine_phy_address(hw); - if (ret_val) { - e_dbg("Cannot determine PHY addr. Erroring out\n"); - return ret_val; - } - } - - phy->id = 0; - while ((e1000_phy_unknown == e1000e_get_phy_type_from_id(phy->id)) && - (i++ < 100)) { - usleep_range(1000, 2000); - ret_val = e1000e_get_phy_id(hw); - if (ret_val) - return ret_val; - } - - /* Verify phy id */ - switch (phy->id) { - case IGP03E1000_E_PHY_ID: - phy->type = e1000_phy_igp_3; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->ops.read_reg_locked = e1000e_read_phy_reg_igp_locked; - phy->ops.write_reg_locked = e1000e_write_phy_reg_igp_locked; - phy->ops.get_info = e1000e_get_phy_info_igp; - phy->ops.check_polarity = e1000_check_polarity_igp; - phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_igp; - break; - case IFE_E_PHY_ID: - case IFE_PLUS_E_PHY_ID: - case IFE_C_E_PHY_ID: - phy->type = e1000_phy_ife; - phy->autoneg_mask = E1000_ALL_NOT_GIG; - phy->ops.get_info = e1000_get_phy_info_ife; - phy->ops.check_polarity = e1000_check_polarity_ife; - phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_ife; - break; - case BME1000_E_PHY_ID: - phy->type = e1000_phy_bm; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->ops.read_reg = e1000e_read_phy_reg_bm; - phy->ops.write_reg = e1000e_write_phy_reg_bm; - phy->ops.commit = e1000e_phy_sw_reset; - phy->ops.get_info = e1000e_get_phy_info_m88; - phy->ops.check_polarity = e1000_check_polarity_m88; - phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_m88; - break; - default: - return -E1000_ERR_PHY; - break; - } - - return 0; -} - -/** - * e1000_init_nvm_params_ich8lan - Initialize NVM function pointers - * @hw: pointer to the HW structure - * - * Initialize family-specific NVM parameters and function - * pointers. - **/ -static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 gfpreg, sector_base_addr, sector_end_addr; - u16 i; - - /* Can't read flash registers if the register set isn't mapped. */ - if (!hw->flash_address) { - e_dbg("ERROR: Flash registers not mapped\n"); - return -E1000_ERR_CONFIG; - } - - nvm->type = e1000_nvm_flash_sw; - - gfpreg = er32flash(ICH_FLASH_GFPREG); - - /* sector_X_addr is a "sector"-aligned address (4096 bytes) - * Add 1 to sector_end_addr since this sector is included in - * the overall size. - */ - sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK; - sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; - - /* flash_base_addr is byte-aligned */ - nvm->flash_base_addr = sector_base_addr << FLASH_SECTOR_ADDR_SHIFT; - - /* find total size of the NVM, then cut in half since the total - * size represents two separate NVM banks. - */ - nvm->flash_bank_size = ((sector_end_addr - sector_base_addr) - << FLASH_SECTOR_ADDR_SHIFT); - nvm->flash_bank_size /= 2; - /* Adjust to word count */ - nvm->flash_bank_size /= sizeof(u16); - - nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS; - - /* Clear shadow ram */ - for (i = 0; i < nvm->word_size; i++) { - dev_spec->shadow_ram[i].modified = false; - dev_spec->shadow_ram[i].value = 0xFFFF; - } - - return 0; -} - -/** - * e1000_init_mac_params_ich8lan - Initialize MAC function pointers - * @hw: pointer to the HW structure - * - * Initialize family-specific MAC parameters and function - * pointers. - **/ -static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - /* Set media type function pointer */ - hw->phy.media_type = e1000_media_type_copper; - - /* Set mta register count */ - mac->mta_reg_count = 32; - /* Set rar entry count */ - mac->rar_entry_count = E1000_ICH_RAR_ENTRIES; - if (mac->type == e1000_ich8lan) - mac->rar_entry_count--; - /* FWSM register */ - mac->has_fwsm = true; - /* ARC subsystem not supported */ - mac->arc_subsystem_valid = false; - /* Adaptive IFS supported */ - mac->adaptive_ifs = true; - - /* LED and other operations */ - switch (mac->type) { - case e1000_ich8lan: - case e1000_ich9lan: - case e1000_ich10lan: - /* check management mode */ - mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan; - /* ID LED init */ - mac->ops.id_led_init = e1000e_id_led_init_generic; - /* blink LED */ - mac->ops.blink_led = e1000e_blink_led_generic; - /* setup LED */ - mac->ops.setup_led = e1000e_setup_led_generic; - /* cleanup LED */ - mac->ops.cleanup_led = e1000_cleanup_led_ich8lan; - /* turn on/off LED */ - mac->ops.led_on = e1000_led_on_ich8lan; - mac->ops.led_off = e1000_led_off_ich8lan; - break; - case e1000_pch2lan: - mac->rar_entry_count = E1000_PCH2_RAR_ENTRIES; - mac->ops.rar_set = e1000_rar_set_pch2lan; - /* fall-through */ - case e1000_pch_lpt: - case e1000_pchlan: - /* check management mode */ - mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan; - /* ID LED init */ - mac->ops.id_led_init = e1000_id_led_init_pchlan; - /* setup LED */ - mac->ops.setup_led = e1000_setup_led_pchlan; - /* cleanup LED */ - mac->ops.cleanup_led = e1000_cleanup_led_pchlan; - /* turn on/off LED */ - mac->ops.led_on = e1000_led_on_pchlan; - mac->ops.led_off = e1000_led_off_pchlan; - break; - default: - break; - } - - if (mac->type == e1000_pch_lpt) { - mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES; - mac->ops.rar_set = e1000_rar_set_pch_lpt; - mac->ops.setup_physical_interface = - e1000_setup_copper_link_pch_lpt; - } - - /* Enable PCS Lock-loss workaround for ICH8 */ - if (mac->type == e1000_ich8lan) - e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true); - - return 0; -} - -/** - * __e1000_access_emi_reg_locked - Read/write EMI register - * @hw: pointer to the HW structure - * @addr: EMI address to program - * @data: pointer to value to read/write from/to the EMI address - * @read: boolean flag to indicate read or write - * - * This helper function assumes the SW/FW/HW Semaphore is already acquired. - **/ -static s32 __e1000_access_emi_reg_locked(struct e1000_hw *hw, u16 address, - u16 *data, bool read) -{ - s32 ret_val; - - ret_val = e1e_wphy_locked(hw, I82579_EMI_ADDR, address); - if (ret_val) - return ret_val; - - if (read) - ret_val = e1e_rphy_locked(hw, I82579_EMI_DATA, data); - else - ret_val = e1e_wphy_locked(hw, I82579_EMI_DATA, *data); - - return ret_val; -} - -/** - * e1000_read_emi_reg_locked - Read Extended Management Interface register - * @hw: pointer to the HW structure - * @addr: EMI address to program - * @data: value to be read from the EMI address - * - * Assumes the SW/FW/HW Semaphore is already acquired. - **/ -s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data) -{ - return __e1000_access_emi_reg_locked(hw, addr, data, true); -} - -/** - * e1000_write_emi_reg_locked - Write Extended Management Interface register - * @hw: pointer to the HW structure - * @addr: EMI address to program - * @data: value to be written to the EMI address - * - * Assumes the SW/FW/HW Semaphore is already acquired. - **/ -s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data) -{ - return __e1000_access_emi_reg_locked(hw, addr, &data, false); -} - -/** - * e1000_set_eee_pchlan - Enable/disable EEE support - * @hw: pointer to the HW structure - * - * Enable/disable EEE based on setting in dev_spec structure, the duplex of - * the link and the EEE capabilities of the link partner. The LPI Control - * register bits will remain set only if/when link is up. - **/ -static s32 e1000_set_eee_pchlan(struct e1000_hw *hw) -{ - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - s32 ret_val; - u16 lpa, pcs_status, adv, adv_addr, lpi_ctrl, data; - - switch (hw->phy.type) { - case e1000_phy_82579: - lpa = I82579_EEE_LP_ABILITY; - pcs_status = I82579_EEE_PCS_STATUS; - adv_addr = I82579_EEE_ADVERTISEMENT; - break; - case e1000_phy_i217: - lpa = I217_EEE_LP_ABILITY; - pcs_status = I217_EEE_PCS_STATUS; - adv_addr = I217_EEE_ADVERTISEMENT; - break; - default: - return 0; - } - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy_locked(hw, I82579_LPI_CTRL, &lpi_ctrl); - if (ret_val) - goto release; - - /* Clear bits that enable EEE in various speeds */ - lpi_ctrl &= ~I82579_LPI_CTRL_ENABLE_MASK; - - /* Enable EEE if not disabled by user */ - if (!dev_spec->eee_disable) { - /* Save off link partner's EEE ability */ - ret_val = e1000_read_emi_reg_locked(hw, lpa, - &dev_spec->eee_lp_ability); - if (ret_val) - goto release; - - /* Read EEE advertisement */ - ret_val = e1000_read_emi_reg_locked(hw, adv_addr, &adv); - if (ret_val) - goto release; - - /* Enable EEE only for speeds in which the link partner is - * EEE capable and for which we advertise EEE. - */ - if (adv & dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED) - lpi_ctrl |= I82579_LPI_CTRL_1000_ENABLE; - - if (adv & dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) { - e1e_rphy_locked(hw, MII_LPA, &data); - if (data & LPA_100FULL) - lpi_ctrl |= I82579_LPI_CTRL_100_ENABLE; - else - /* EEE is not supported in 100Half, so ignore - * partner's EEE in 100 ability if full-duplex - * is not advertised. - */ - dev_spec->eee_lp_ability &= - ~I82579_EEE_100_SUPPORTED; - } - } - - /* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */ - ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data); - if (ret_val) - goto release; - - ret_val = e1e_wphy_locked(hw, I82579_LPI_CTRL, lpi_ctrl); -release: - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP - * @hw: pointer to the HW structure - * @link: link up bool flag - * - * When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications - * preventing further DMA write requests. Workaround the issue by disabling - * the de-assertion of the clock request when in 1Gpbs mode. - **/ -static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link) -{ - u32 fextnvm6 = er32(FEXTNVM6); - s32 ret_val = 0; - - if (link && (er32(STATUS) & E1000_STATUS_SPEED_1000)) { - u16 kmrn_reg; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - ret_val = - e1000e_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, - &kmrn_reg); - if (ret_val) - goto release; - - ret_val = - e1000e_write_kmrn_reg_locked(hw, - E1000_KMRNCTRLSTA_K1_CONFIG, - kmrn_reg & - ~E1000_KMRNCTRLSTA_K1_ENABLE); - if (ret_val) - goto release; - - usleep_range(10, 20); - - ew32(FEXTNVM6, fextnvm6 | E1000_FEXTNVM6_REQ_PLL_CLK); - - ret_val = - e1000e_write_kmrn_reg_locked(hw, - E1000_KMRNCTRLSTA_K1_CONFIG, - kmrn_reg); -release: - hw->phy.ops.release(hw); - } else { - /* clear FEXTNVM6 bit 8 on link down or 10/100 */ - ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK); - } - - return ret_val; -} - -/** - * e1000_platform_pm_pch_lpt - Set platform power management values - * @hw: pointer to the HW structure - * @link: bool indicating link status - * - * Set the Latency Tolerance Reporting (LTR) values for the "PCIe-like" - * GbE MAC in the Lynx Point PCH based on Rx buffer size and link speed - * when link is up (which must not exceed the maximum latency supported - * by the platform), otherwise specify there is no LTR requirement. - * Unlike true-PCIe devices which set the LTR maximum snoop/no-snoop - * latencies in the LTR Extended Capability Structure in the PCIe Extended - * Capability register set, on this device LTR is set by writing the - * equivalent snoop/no-snoop latencies in the LTRV register in the MAC and - * set the SEND bit to send an Intel On-chip System Fabric sideband (IOSF-SB) - * message to the PMC. - **/ -static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link) -{ - u32 reg = link << (E1000_LTRV_REQ_SHIFT + E1000_LTRV_NOSNOOP_SHIFT) | - link << E1000_LTRV_REQ_SHIFT | E1000_LTRV_SEND; - u16 lat_enc = 0; /* latency encoded */ - - if (link) { - u16 speed, duplex, scale = 0; - u16 max_snoop, max_nosnoop; - u16 max_ltr_enc; /* max LTR latency encoded */ - s64 lat_ns; /* latency (ns) */ - s64 value; - u32 rxa; - - if (!hw->adapter->max_frame_size) { - e_dbg("max_frame_size not set.\n"); - return -E1000_ERR_CONFIG; - } - - hw->mac.ops.get_link_up_info(hw, &speed, &duplex); - if (!speed) { - e_dbg("Speed not set.\n"); - return -E1000_ERR_CONFIG; - } - - /* Rx Packet Buffer Allocation size (KB) */ - rxa = er32(PBA) & E1000_PBA_RXA_MASK; - - /* Determine the maximum latency tolerated by the device. - * - * Per the PCIe spec, the tolerated latencies are encoded as - * a 3-bit encoded scale (only 0-5 are valid) multiplied by - * a 10-bit value (0-1023) to provide a range from 1 ns to - * 2^25*(2^10-1) ns. The scale is encoded as 0=2^0ns, - * 1=2^5ns, 2=2^10ns,...5=2^25ns. - */ - lat_ns = ((s64)rxa * 1024 - - (2 * (s64)hw->adapter->max_frame_size)) * 8 * 1000; - if (lat_ns < 0) - lat_ns = 0; - else - do_div(lat_ns, speed); - - value = lat_ns; - while (value > PCI_LTR_VALUE_MASK) { - scale++; - value = DIV_ROUND_UP(value, (1 << 5)); - } - if (scale > E1000_LTRV_SCALE_MAX) { - e_dbg("Invalid LTR latency scale %d\n", scale); - return -E1000_ERR_CONFIG; - } - lat_enc = (u16)((scale << PCI_LTR_SCALE_SHIFT) | value); - - /* Determine the maximum latency tolerated by the platform */ - pci_read_config_word(hw->adapter->pdev, E1000_PCI_LTR_CAP_LPT, - &max_snoop); - pci_read_config_word(hw->adapter->pdev, - E1000_PCI_LTR_CAP_LPT + 2, &max_nosnoop); - max_ltr_enc = max_t(u16, max_snoop, max_nosnoop); - - if (lat_enc > max_ltr_enc) - lat_enc = max_ltr_enc; - } - - /* Set Snoop and No-Snoop latencies the same */ - reg |= lat_enc | (lat_enc << E1000_LTRV_NOSNOOP_SHIFT); - ew32(LTRV, reg); - - return 0; -} - -/** - * e1000_check_for_copper_link_ich8lan - Check for link (Copper) - * @hw: pointer to the HW structure - * - * Checks to see of the link status of the hardware has changed. If a - * change in link status has been detected, then we read the PHY registers - * to get the current speed/duplex if link exists. - **/ -static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - bool link; - u16 phy_reg; - - /* We only want to go out to the PHY registers to see if Auto-Neg - * has completed and/or if our link status has changed. The - * get_link_status flag is set upon receiving a Link Status - * Change or Rx Sequence Error interrupt. - */ - if (!mac->get_link_status) - return 0; - - /* First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * of the PHY. - */ - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (hw->mac.type == e1000_pchlan) { - ret_val = e1000_k1_gig_workaround_hv(hw, link); - if (ret_val) - return ret_val; - } - - /* When connected at 10Mbps half-duplex, 82579 parts are excessively - * aggressive resulting in many collisions. To avoid this, increase - * the IPG and reduce Rx latency in the PHY. - */ - if ((hw->mac.type == e1000_pch2lan) && link) { - u32 reg; - reg = er32(STATUS); - if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) { - reg = er32(TIPG); - reg &= ~E1000_TIPG_IPGT_MASK; - reg |= 0xFF; - ew32(TIPG, reg); - - /* Reduce Rx latency in analog PHY */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - ret_val = - e1000_write_emi_reg_locked(hw, I82579_RX_CONFIG, 0); - - hw->phy.ops.release(hw); - - if (ret_val) - return ret_val; - } - } - - /* Work-around I218 hang issue */ - if ((hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_LM) || - (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_V)) { - ret_val = e1000_k1_workaround_lpt_lp(hw, link); - if (ret_val) - return ret_val; - } - - if (hw->mac.type == e1000_pch_lpt) { - /* Set platform power management values for - * Latency Tolerance Reporting (LTR) - */ - ret_val = e1000_platform_pm_pch_lpt(hw, link); - if (ret_val) - return ret_val; - } - - /* Clear link partner's EEE ability */ - hw->dev_spec.ich8lan.eee_lp_ability = 0; - - if (!link) - return 0; /* No link detected */ - - mac->get_link_status = false; - - switch (hw->mac.type) { - case e1000_pch2lan: - ret_val = e1000_k1_workaround_lv(hw); - if (ret_val) - return ret_val; - /* fall-thru */ - case e1000_pchlan: - if (hw->phy.type == e1000_phy_82578) { - ret_val = e1000_link_stall_workaround_hv(hw); - if (ret_val) - return ret_val; - } - - /* Workaround for PCHx parts in half-duplex: - * Set the number of preambles removed from the packet - * when it is passed from the PHY to the MAC to prevent - * the MAC from misinterpreting the packet type. - */ - e1e_rphy(hw, HV_KMRN_FIFO_CTRLSTA, &phy_reg); - phy_reg &= ~HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK; - - if ((er32(STATUS) & E1000_STATUS_FD) != E1000_STATUS_FD) - phy_reg |= (1 << HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT); - - e1e_wphy(hw, HV_KMRN_FIFO_CTRLSTA, phy_reg); - break; - default: - break; - } - - /* Check if there was DownShift, must be checked - * immediately after link-up - */ - e1000e_check_downshift(hw); - - /* Enable/Disable EEE after link up */ - ret_val = e1000_set_eee_pchlan(hw); - if (ret_val) - return ret_val; - - /* If we are forcing speed/duplex, then we simply return since - * we have already determined whether we have link or not. - */ - if (!mac->autoneg) - return -E1000_ERR_CONFIG; - - /* Auto-Neg is enabled. Auto Speed Detection takes care - * of MAC speed/duplex configuration. So we only need to - * configure Collision Distance in the MAC. - */ - mac->ops.config_collision_dist(hw); - - /* Configure Flow Control now that Auto-Neg has completed. - * First, we need to restore the desired flow control - * settings because we may have had to re-autoneg with a - * different link partner. - */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) - e_dbg("Error configuring flow control\n"); - - return ret_val; -} - -static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - s32 rc; - - rc = e1000_init_mac_params_ich8lan(hw); - if (rc) - return rc; - - rc = e1000_init_nvm_params_ich8lan(hw); - if (rc) - return rc; - - switch (hw->mac.type) { - case e1000_ich8lan: - case e1000_ich9lan: - case e1000_ich10lan: - rc = e1000_init_phy_params_ich8lan(hw); - break; - case e1000_pchlan: - case e1000_pch2lan: - case e1000_pch_lpt: - rc = e1000_init_phy_params_pchlan(hw); - break; - default: - break; - } - if (rc) - return rc; - - /* Disable Jumbo Frame support on parts with Intel 10/100 PHY or - * on parts with MACsec enabled in NVM (reflected in CTRL_EXT). - */ - if ((adapter->hw.phy.type == e1000_phy_ife) || - ((adapter->hw.mac.type >= e1000_pch2lan) && - (!(er32(CTRL_EXT) & E1000_CTRL_EXT_LSECCK)))) { - adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES; - adapter->max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN; - - hw->mac.ops.blink_led = NULL; - } - - if ((adapter->hw.mac.type == e1000_ich8lan) && - (adapter->hw.phy.type != e1000_phy_ife)) - adapter->flags |= FLAG_LSC_GIG_SPEED_DROP; - - /* Enable workaround for 82579 w/ ME enabled */ - if ((adapter->hw.mac.type == e1000_pch2lan) && - (er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) - adapter->flags2 |= FLAG2_PCIM2PCI_ARBITER_WA; - - return 0; -} - -static DEFINE_MUTEX(nvm_mutex); - -/** - * e1000_acquire_nvm_ich8lan - Acquire NVM mutex - * @hw: pointer to the HW structure - * - * Acquires the mutex for performing NVM operations. - **/ -static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw __always_unused *hw) -{ - mutex_lock(&nvm_mutex); - - return 0; -} - -/** - * e1000_release_nvm_ich8lan - Release NVM mutex - * @hw: pointer to the HW structure - * - * Releases the mutex used while performing NVM operations. - **/ -static void e1000_release_nvm_ich8lan(struct e1000_hw __always_unused *hw) -{ - mutex_unlock(&nvm_mutex); -} - -/** - * e1000_acquire_swflag_ich8lan - Acquire software control flag - * @hw: pointer to the HW structure - * - * Acquires the software control flag for performing PHY and select - * MAC CSR accesses. - **/ -static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) -{ - u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT; - s32 ret_val = 0; - - if (test_and_set_bit(__E1000_ACCESS_SHARED_RESOURCE, - &hw->adapter->state)) { - e_dbg("contention for Phy access\n"); - return -E1000_ERR_PHY; - } - - while (timeout) { - extcnf_ctrl = er32(EXTCNF_CTRL); - if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)) - break; - - mdelay(1); - timeout--; - } - - if (!timeout) { - e_dbg("SW has already locked the resource.\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - timeout = SW_FLAG_TIMEOUT; - - extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; - ew32(EXTCNF_CTRL, extcnf_ctrl); - - while (timeout) { - extcnf_ctrl = er32(EXTCNF_CTRL); - if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) - break; - - mdelay(1); - timeout--; - } - - if (!timeout) { - e_dbg("Failed to acquire the semaphore, FW or HW has it: FWSM=0x%8.8x EXTCNF_CTRL=0x%8.8x)\n", - er32(FWSM), extcnf_ctrl); - extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; - ew32(EXTCNF_CTRL, extcnf_ctrl); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - -out: - if (ret_val) - clear_bit(__E1000_ACCESS_SHARED_RESOURCE, &hw->adapter->state); - - return ret_val; -} - -/** - * e1000_release_swflag_ich8lan - Release software control flag - * @hw: pointer to the HW structure - * - * Releases the software control flag for performing PHY and select - * MAC CSR accesses. - **/ -static void e1000_release_swflag_ich8lan(struct e1000_hw *hw) -{ - u32 extcnf_ctrl; - - extcnf_ctrl = er32(EXTCNF_CTRL); - - if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) { - extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; - ew32(EXTCNF_CTRL, extcnf_ctrl); - } else { - e_dbg("Semaphore unexpectedly released by sw/fw/hw\n"); - } - - clear_bit(__E1000_ACCESS_SHARED_RESOURCE, &hw->adapter->state); -} - -/** - * e1000_check_mng_mode_ich8lan - Checks management mode - * @hw: pointer to the HW structure - * - * This checks if the adapter has any manageability enabled. - * This is a function pointer entry point only called by read/write - * routines for the PHY and NVM parts. - **/ -static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw) -{ - u32 fwsm; - - fwsm = er32(FWSM); - return ((fwsm & E1000_ICH_FWSM_FW_VALID) && - ((fwsm & E1000_FWSM_MODE_MASK) == - (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT))); -} - -/** - * e1000_check_mng_mode_pchlan - Checks management mode - * @hw: pointer to the HW structure - * - * This checks if the adapter has iAMT enabled. - * This is a function pointer entry point only called by read/write - * routines for the PHY and NVM parts. - **/ -static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw) -{ - u32 fwsm; - - fwsm = er32(FWSM); - return (fwsm & E1000_ICH_FWSM_FW_VALID) && - (fwsm & (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); -} - -/** - * e1000_rar_set_pch2lan - Set receive address register - * @hw: pointer to the HW structure - * @addr: pointer to the receive address - * @index: receive address array register - * - * Sets the receive address array register at index to the address passed - * in by addr. For 82579, RAR[0] is the base address register that is to - * contain the MAC address but RAR[1-6] are reserved for manageability (ME). - * Use SHRA[0-3] in place of those reserved for ME. - **/ -static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) -{ - u32 rar_low, rar_high; - - /* HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian - */ - rar_low = ((u32)addr[0] | - ((u32)addr[1] << 8) | - ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); - - rar_high = ((u32)addr[4] | ((u32)addr[5] << 8)); - - /* If MAC address zero, no need to set the AV bit */ - if (rar_low || rar_high) - rar_high |= E1000_RAH_AV; - - if (index == 0) { - ew32(RAL(index), rar_low); - e1e_flush(); - ew32(RAH(index), rar_high); - e1e_flush(); - return; - } - - if (index < hw->mac.rar_entry_count) { - s32 ret_val; - - ret_val = e1000_acquire_swflag_ich8lan(hw); - if (ret_val) - goto out; - - ew32(SHRAL(index - 1), rar_low); - e1e_flush(); - ew32(SHRAH(index - 1), rar_high); - e1e_flush(); - - e1000_release_swflag_ich8lan(hw); - - /* verify the register updates */ - if ((er32(SHRAL(index - 1)) == rar_low) && - (er32(SHRAH(index - 1)) == rar_high)) - return; - - e_dbg("SHRA[%d] might be locked by ME - FWSM=0x%8.8x\n", - (index - 1), er32(FWSM)); - } - -out: - e_dbg("Failed to write receive address at index %d\n", index); -} - -/** - * e1000_rar_set_pch_lpt - Set receive address registers - * @hw: pointer to the HW structure - * @addr: pointer to the receive address - * @index: receive address array register - * - * Sets the receive address register array at index to the address passed - * in by addr. For LPT, RAR[0] is the base address register that is to - * contain the MAC address. SHRA[0-10] are the shared receive address - * registers that are shared between the Host and manageability engine (ME). - **/ -static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index) -{ - u32 rar_low, rar_high; - u32 wlock_mac; - - /* HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian - */ - rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) | - ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); - - rar_high = ((u32)addr[4] | ((u32)addr[5] << 8)); - - /* If MAC address zero, no need to set the AV bit */ - if (rar_low || rar_high) - rar_high |= E1000_RAH_AV; - - if (index == 0) { - ew32(RAL(index), rar_low); - e1e_flush(); - ew32(RAH(index), rar_high); - e1e_flush(); - return; - } - - /* The manageability engine (ME) can lock certain SHRAR registers that - * it is using - those registers are unavailable for use. - */ - if (index < hw->mac.rar_entry_count) { - wlock_mac = er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK; - wlock_mac >>= E1000_FWSM_WLOCK_MAC_SHIFT; - - /* Check if all SHRAR registers are locked */ - if (wlock_mac == 1) - goto out; - - if ((wlock_mac == 0) || (index <= wlock_mac)) { - s32 ret_val; - - ret_val = e1000_acquire_swflag_ich8lan(hw); - - if (ret_val) - goto out; - - ew32(SHRAL_PCH_LPT(index - 1), rar_low); - e1e_flush(); - ew32(SHRAH_PCH_LPT(index - 1), rar_high); - e1e_flush(); - - e1000_release_swflag_ich8lan(hw); - - /* verify the register updates */ - if ((er32(SHRAL_PCH_LPT(index - 1)) == rar_low) && - (er32(SHRAH_PCH_LPT(index - 1)) == rar_high)) - return; - } - } - -out: - e_dbg("Failed to write receive address at index %d\n", index); -} - -/** - * e1000_check_reset_block_ich8lan - Check if PHY reset is blocked - * @hw: pointer to the HW structure - * - * Checks if firmware is blocking the reset of the PHY. - * This is a function pointer entry point only called by - * reset routines. - **/ -static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) -{ - u32 fwsm; - - fwsm = er32(FWSM); - - return (fwsm & E1000_ICH_FWSM_RSPCIPHY) ? 0 : E1000_BLK_PHY_RESET; -} - -/** - * e1000_write_smbus_addr - Write SMBus address to PHY needed during Sx states - * @hw: pointer to the HW structure - * - * Assumes semaphore already acquired. - * - **/ -static s32 e1000_write_smbus_addr(struct e1000_hw *hw) -{ - u16 phy_data; - u32 strap = er32(STRAP); - u32 freq = (strap & E1000_STRAP_SMT_FREQ_MASK) >> - E1000_STRAP_SMT_FREQ_SHIFT; - s32 ret_val; - - strap &= E1000_STRAP_SMBUS_ADDRESS_MASK; - - ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~HV_SMB_ADDR_MASK; - phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT); - phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; - - if (hw->phy.type == e1000_phy_i217) { - /* Restore SMBus frequency */ - if (freq--) { - phy_data &= ~HV_SMB_ADDR_FREQ_MASK; - phy_data |= (freq & (1 << 0)) << - HV_SMB_ADDR_FREQ_LOW_SHIFT; - phy_data |= (freq & (1 << 1)) << - (HV_SMB_ADDR_FREQ_HIGH_SHIFT - 1); - } else { - e_dbg("Unsupported SMB frequency in PHY\n"); - } - } - - return e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data); -} - -/** - * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration - * @hw: pointer to the HW structure - * - * SW should configure the LCD from the NVM extended configuration region - * as a workaround for certain parts. - **/ -static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; - s32 ret_val = 0; - u16 word_addr, reg_data, reg_addr, phy_page = 0; - - /* Initialize the PHY from the NVM on ICH platforms. This - * is needed due to an issue where the NVM configuration is - * not properly autoloaded after power transitions. - * Therefore, after each PHY reset, we will load the - * configuration data out of the NVM manually. - */ - switch (hw->mac.type) { - case e1000_ich8lan: - if (phy->type != e1000_phy_igp_3) - return ret_val; - - if ((hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) || - (hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_C)) { - sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; - break; - } - /* Fall-thru */ - case e1000_pchlan: - case e1000_pch2lan: - case e1000_pch_lpt: - sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; - break; - default: - return ret_val; - } - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - data = er32(FEXTNVM); - if (!(data & sw_cfg_mask)) - goto release; - - /* Make sure HW does not configure LCD from PHY - * extended configuration before SW configuration - */ - data = er32(EXTCNF_CTRL); - if ((hw->mac.type < e1000_pch2lan) && - (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)) - goto release; - - cnf_size = er32(EXTCNF_SIZE); - cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; - cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; - if (!cnf_size) - goto release; - - cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; - cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; - - if (((hw->mac.type == e1000_pchlan) && - !(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)) || - (hw->mac.type > e1000_pchlan)) { - /* HW configures the SMBus address and LEDs when the - * OEM and LCD Write Enable bits are set in the NVM. - * When both NVM bits are cleared, SW will configure - * them instead. - */ - ret_val = e1000_write_smbus_addr(hw); - if (ret_val) - goto release; - - data = er32(LEDCTL); - ret_val = e1000_write_phy_reg_hv_locked(hw, HV_LED_CONFIG, - (u16)data); - if (ret_val) - goto release; - } - - /* Configure LCD from extended configuration region. */ - - /* cnf_base_addr is in DWORD */ - word_addr = (u16)(cnf_base_addr << 1); - - for (i = 0; i < cnf_size; i++) { - ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1, ®_data); - if (ret_val) - goto release; - - ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1), - 1, ®_addr); - if (ret_val) - goto release; - - /* Save off the PHY page for future writes. */ - if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { - phy_page = reg_data; - continue; - } - - reg_addr &= PHY_REG_MASK; - reg_addr |= phy_page; - - ret_val = e1e_wphy_locked(hw, (u32)reg_addr, reg_data); - if (ret_val) - goto release; - } - -release: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000_k1_gig_workaround_hv - K1 Si workaround - * @hw: pointer to the HW structure - * @link: link up bool flag - * - * If K1 is enabled for 1Gbps, the MAC might stall when transitioning - * from a lower speed. This workaround disables K1 whenever link is at 1Gig - * If link is down, the function will restore the default K1 setting located - * in the NVM. - **/ -static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) -{ - s32 ret_val = 0; - u16 status_reg = 0; - bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled; - - if (hw->mac.type != e1000_pchlan) - return 0; - - /* Wrap the whole flow with the sw flag */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */ - if (link) { - if (hw->phy.type == e1000_phy_82578) { - ret_val = e1e_rphy_locked(hw, BM_CS_STATUS, - &status_reg); - if (ret_val) - goto release; - - status_reg &= (BM_CS_STATUS_LINK_UP | - BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_MASK); - - if (status_reg == (BM_CS_STATUS_LINK_UP | - BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_1000)) - k1_enable = false; - } - - if (hw->phy.type == e1000_phy_82577) { - ret_val = e1e_rphy_locked(hw, HV_M_STATUS, &status_reg); - if (ret_val) - goto release; - - status_reg &= (HV_M_STATUS_LINK_UP | - HV_M_STATUS_AUTONEG_COMPLETE | - HV_M_STATUS_SPEED_MASK); - - if (status_reg == (HV_M_STATUS_LINK_UP | - HV_M_STATUS_AUTONEG_COMPLETE | - HV_M_STATUS_SPEED_1000)) - k1_enable = false; - } - - /* Link stall fix for link up */ - ret_val = e1e_wphy_locked(hw, PHY_REG(770, 19), 0x0100); - if (ret_val) - goto release; - - } else { - /* Link stall fix for link down */ - ret_val = e1e_wphy_locked(hw, PHY_REG(770, 19), 0x4100); - if (ret_val) - goto release; - } - - ret_val = e1000_configure_k1_ich8lan(hw, k1_enable); - -release: - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_configure_k1_ich8lan - Configure K1 power state - * @hw: pointer to the HW structure - * @enable: K1 state to configure - * - * Configure the K1 power state based on the provided parameter. - * Assumes semaphore already acquired. - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - **/ -s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) -{ - s32 ret_val; - u32 ctrl_reg = 0; - u32 ctrl_ext = 0; - u32 reg = 0; - u16 kmrn_reg = 0; - - ret_val = e1000e_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, - &kmrn_reg); - if (ret_val) - return ret_val; - - if (k1_enable) - kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE; - else - kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE; - - ret_val = e1000e_write_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, - kmrn_reg); - if (ret_val) - return ret_val; - - usleep_range(20, 40); - ctrl_ext = er32(CTRL_EXT); - ctrl_reg = er32(CTRL); - - reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - reg |= E1000_CTRL_FRCSPD; - ew32(CTRL, reg); - - ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS); - e1e_flush(); - usleep_range(20, 40); - ew32(CTRL, ctrl_reg); - ew32(CTRL_EXT, ctrl_ext); - e1e_flush(); - usleep_range(20, 40); - - return 0; -} - -/** - * e1000_oem_bits_config_ich8lan - SW-based LCD Configuration - * @hw: pointer to the HW structure - * @d0_state: boolean if entering d0 or d3 device state - * - * SW will configure Gbe Disable and LPLU based on the NVM. The four bits are - * collectively called OEM bits. The OEM Write Enable bit and SW Config bit - * in NVM determines whether HW should configure LPLU and Gbe Disable. - **/ -static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) -{ - s32 ret_val = 0; - u32 mac_reg; - u16 oem_reg; - - if (hw->mac.type < e1000_pchlan) - return ret_val; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - if (hw->mac.type == e1000_pchlan) { - mac_reg = er32(EXTCNF_CTRL); - if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) - goto release; - } - - mac_reg = er32(FEXTNVM); - if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M)) - goto release; - - mac_reg = er32(PHY_CTRL); - - ret_val = e1e_rphy_locked(hw, HV_OEM_BITS, &oem_reg); - if (ret_val) - goto release; - - oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU); - - if (d0_state) { - if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE) - oem_reg |= HV_OEM_BITS_GBE_DIS; - - if (mac_reg & E1000_PHY_CTRL_D0A_LPLU) - oem_reg |= HV_OEM_BITS_LPLU; - } else { - if (mac_reg & (E1000_PHY_CTRL_GBE_DISABLE | - E1000_PHY_CTRL_NOND0A_GBE_DISABLE)) - oem_reg |= HV_OEM_BITS_GBE_DIS; - - if (mac_reg & (E1000_PHY_CTRL_D0A_LPLU | - E1000_PHY_CTRL_NOND0A_LPLU)) - oem_reg |= HV_OEM_BITS_LPLU; - } - - /* Set Restart auto-neg to activate the bits */ - if ((d0_state || (hw->mac.type != e1000_pchlan)) && - !hw->phy.ops.check_reset_block(hw)) - oem_reg |= HV_OEM_BITS_RESTART_AN; - - ret_val = e1e_wphy_locked(hw, HV_OEM_BITS, oem_reg); - -release: - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode - * @hw: pointer to the HW structure - **/ -static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw) -{ - s32 ret_val; - u16 data; - - ret_val = e1e_rphy(hw, HV_KMRN_MODE_CTRL, &data); - if (ret_val) - return ret_val; - - data |= HV_KMRN_MDIO_SLOW; - - ret_val = e1e_wphy(hw, HV_KMRN_MODE_CTRL, data); - - return ret_val; -} - -/** - * e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be - * done after every PHY reset. - **/ -static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u16 phy_data; - - if (hw->mac.type != e1000_pchlan) - return 0; - - /* Set MDIO slow mode before any other MDIO access */ - if (hw->phy.type == e1000_phy_82577) { - ret_val = e1000_set_mdio_slow_mode_hv(hw); - if (ret_val) - return ret_val; - } - - if (((hw->phy.type == e1000_phy_82577) && - ((hw->phy.revision == 1) || (hw->phy.revision == 2))) || - ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) { - /* Disable generation of early preamble */ - ret_val = e1e_wphy(hw, PHY_REG(769, 25), 0x4431); - if (ret_val) - return ret_val; - - /* Preamble tuning for SSC */ - ret_val = e1e_wphy(hw, HV_KMRN_FIFO_CTRLSTA, 0xA204); - if (ret_val) - return ret_val; - } - - if (hw->phy.type == e1000_phy_82578) { - /* Return registers to default by doing a soft reset then - * writing 0x3140 to the control register. - */ - if (hw->phy.revision < 2) { - e1000e_phy_sw_reset(hw); - ret_val = e1e_wphy(hw, MII_BMCR, 0x3140); - } - } - - /* Select page 0 */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - hw->phy.addr = 1; - ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); - hw->phy.ops.release(hw); - if (ret_val) - return ret_val; - - /* Configure the K1 Si workaround during phy reset assuming there is - * link so that it disables K1 if link is in 1Gbps. - */ - ret_val = e1000_k1_gig_workaround_hv(hw, true); - if (ret_val) - return ret_val; - - /* Workaround for link disconnects on a busy hub in half duplex */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - ret_val = e1e_rphy_locked(hw, BM_PORT_GEN_CFG, &phy_data); - if (ret_val) - goto release; - ret_val = e1e_wphy_locked(hw, BM_PORT_GEN_CFG, phy_data & 0x00FF); - if (ret_val) - goto release; - - /* set MSE higher to enable link to stay up when noise is high */ - ret_val = e1000_write_emi_reg_locked(hw, I82577_MSE_THRESHOLD, 0x0034); -release: - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_copy_rx_addrs_to_phy_ich8lan - Copy Rx addresses from MAC to PHY - * @hw: pointer to the HW structure - **/ -void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw) -{ - u32 mac_reg; - u16 i, phy_reg = 0; - s32 ret_val; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return; - ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg); - if (ret_val) - goto release; - - /* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */ - for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { - mac_reg = er32(RAL(i)); - hw->phy.ops.write_reg_page(hw, BM_RAR_L(i), - (u16)(mac_reg & 0xFFFF)); - hw->phy.ops.write_reg_page(hw, BM_RAR_M(i), - (u16)((mac_reg >> 16) & 0xFFFF)); - - mac_reg = er32(RAH(i)); - hw->phy.ops.write_reg_page(hw, BM_RAR_H(i), - (u16)(mac_reg & 0xFFFF)); - hw->phy.ops.write_reg_page(hw, BM_RAR_CTRL(i), - (u16)((mac_reg & E1000_RAH_AV) - >> 16)); - } - - e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg); - -release: - hw->phy.ops.release(hw); -} - -/** - * e1000_lv_jumbo_workaround_ich8lan - required for jumbo frame operation - * with 82579 PHY - * @hw: pointer to the HW structure - * @enable: flag to enable/disable workaround when enabling/disabling jumbos - **/ -s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) -{ - s32 ret_val = 0; - u16 phy_reg, data; - u32 mac_reg; - u16 i; - - if (hw->mac.type < e1000_pch2lan) - return 0; - - /* disable Rx path while enabling/disabling workaround */ - e1e_rphy(hw, PHY_REG(769, 20), &phy_reg); - ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg | (1 << 14)); - if (ret_val) - return ret_val; - - if (enable) { - /* Write Rx addresses (rar_entry_count for RAL/H, +4 for - * SHRAL/H) and initial CRC values to the MAC - */ - for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { - u8 mac_addr[ETH_ALEN] = { 0 }; - u32 addr_high, addr_low; - - addr_high = er32(RAH(i)); - if (!(addr_high & E1000_RAH_AV)) - continue; - addr_low = er32(RAL(i)); - mac_addr[0] = (addr_low & 0xFF); - mac_addr[1] = ((addr_low >> 8) & 0xFF); - mac_addr[2] = ((addr_low >> 16) & 0xFF); - mac_addr[3] = ((addr_low >> 24) & 0xFF); - mac_addr[4] = (addr_high & 0xFF); - mac_addr[5] = ((addr_high >> 8) & 0xFF); - - ew32(PCH_RAICC(i), ~ether_crc_le(ETH_ALEN, mac_addr)); - } - - /* Write Rx addresses to the PHY */ - e1000_copy_rx_addrs_to_phy_ich8lan(hw); - - /* Enable jumbo frame workaround in the MAC */ - mac_reg = er32(FFLT_DBG); - mac_reg &= ~(1 << 14); - mac_reg |= (7 << 15); - ew32(FFLT_DBG, mac_reg); - - mac_reg = er32(RCTL); - mac_reg |= E1000_RCTL_SECRC; - ew32(RCTL, mac_reg); - - ret_val = e1000e_read_kmrn_reg(hw, - E1000_KMRNCTRLSTA_CTRL_OFFSET, - &data); - if (ret_val) - return ret_val; - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_CTRL_OFFSET, - data | (1 << 0)); - if (ret_val) - return ret_val; - ret_val = e1000e_read_kmrn_reg(hw, - E1000_KMRNCTRLSTA_HD_CTRL, - &data); - if (ret_val) - return ret_val; - data &= ~(0xF << 8); - data |= (0xB << 8); - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_HD_CTRL, - data); - if (ret_val) - return ret_val; - - /* Enable jumbo frame workaround in the PHY */ - e1e_rphy(hw, PHY_REG(769, 23), &data); - data &= ~(0x7F << 5); - data |= (0x37 << 5); - ret_val = e1e_wphy(hw, PHY_REG(769, 23), data); - if (ret_val) - return ret_val; - e1e_rphy(hw, PHY_REG(769, 16), &data); - data &= ~(1 << 13); - ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); - if (ret_val) - return ret_val; - e1e_rphy(hw, PHY_REG(776, 20), &data); - data &= ~(0x3FF << 2); - data |= (0x1A << 2); - ret_val = e1e_wphy(hw, PHY_REG(776, 20), data); - if (ret_val) - return ret_val; - ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0xF100); - if (ret_val) - return ret_val; - e1e_rphy(hw, HV_PM_CTRL, &data); - ret_val = e1e_wphy(hw, HV_PM_CTRL, data | (1 << 10)); - if (ret_val) - return ret_val; - } else { - /* Write MAC register values back to h/w defaults */ - mac_reg = er32(FFLT_DBG); - mac_reg &= ~(0xF << 14); - ew32(FFLT_DBG, mac_reg); - - mac_reg = er32(RCTL); - mac_reg &= ~E1000_RCTL_SECRC; - ew32(RCTL, mac_reg); - - ret_val = e1000e_read_kmrn_reg(hw, - E1000_KMRNCTRLSTA_CTRL_OFFSET, - &data); - if (ret_val) - return ret_val; - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_CTRL_OFFSET, - data & ~(1 << 0)); - if (ret_val) - return ret_val; - ret_val = e1000e_read_kmrn_reg(hw, - E1000_KMRNCTRLSTA_HD_CTRL, - &data); - if (ret_val) - return ret_val; - data &= ~(0xF << 8); - data |= (0xB << 8); - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_HD_CTRL, - data); - if (ret_val) - return ret_val; - - /* Write PHY register values back to h/w defaults */ - e1e_rphy(hw, PHY_REG(769, 23), &data); - data &= ~(0x7F << 5); - ret_val = e1e_wphy(hw, PHY_REG(769, 23), data); - if (ret_val) - return ret_val; - e1e_rphy(hw, PHY_REG(769, 16), &data); - data |= (1 << 13); - ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); - if (ret_val) - return ret_val; - e1e_rphy(hw, PHY_REG(776, 20), &data); - data &= ~(0x3FF << 2); - data |= (0x8 << 2); - ret_val = e1e_wphy(hw, PHY_REG(776, 20), data); - if (ret_val) - return ret_val; - ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0x7E00); - if (ret_val) - return ret_val; - e1e_rphy(hw, HV_PM_CTRL, &data); - ret_val = e1e_wphy(hw, HV_PM_CTRL, data & ~(1 << 10)); - if (ret_val) - return ret_val; - } - - /* re-enable Rx path after enabling/disabling workaround */ - return e1e_wphy(hw, PHY_REG(769, 20), phy_reg & ~(1 << 14)); -} - -/** - * e1000_lv_phy_workarounds_ich8lan - A series of Phy workarounds to be - * done after every PHY reset. - **/ -static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = 0; - - if (hw->mac.type != e1000_pch2lan) - return 0; - - /* Set MDIO slow mode before any other MDIO access */ - ret_val = e1000_set_mdio_slow_mode_hv(hw); - if (ret_val) - return ret_val; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - /* set MSE higher to enable link to stay up when noise is high */ - ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_THRESHOLD, 0x0034); - if (ret_val) - goto release; - /* drop link after 5 times MSE threshold was reached */ - ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_LINK_DOWN, 0x0005); -release: - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_k1_gig_workaround_lv - K1 Si workaround - * @hw: pointer to the HW structure - * - * Workaround to set the K1 beacon duration for 82579 parts - **/ -static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u16 status_reg = 0; - u32 mac_reg; - u16 phy_reg; - - if (hw->mac.type != e1000_pch2lan) - return 0; - - /* Set K1 beacon duration based on 1Gbps speed or otherwise */ - ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg); - if (ret_val) - return ret_val; - - if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) - == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) { - mac_reg = er32(FEXTNVM4); - mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; - - ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg); - if (ret_val) - return ret_val; - - if (status_reg & HV_M_STATUS_SPEED_1000) { - u16 pm_phy_reg; - - mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; - phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; - /* LV 1G Packet drop issue wa */ - ret_val = e1e_rphy(hw, HV_PM_CTRL, &pm_phy_reg); - if (ret_val) - return ret_val; - pm_phy_reg &= ~HV_PM_CTRL_PLL_STOP_IN_K1_GIGA; - ret_val = e1e_wphy(hw, HV_PM_CTRL, pm_phy_reg); - if (ret_val) - return ret_val; - } else { - mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; - phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; - } - ew32(FEXTNVM4, mac_reg); - ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg); - } - - return ret_val; -} - -/** - * e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware - * @hw: pointer to the HW structure - * @gate: boolean set to true to gate, false to ungate - * - * Gate/ungate the automatic PHY configuration via hardware; perform - * the configuration via software instead. - **/ -static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate) -{ - u32 extcnf_ctrl; - - if (hw->mac.type < e1000_pch2lan) - return; - - extcnf_ctrl = er32(EXTCNF_CTRL); - - if (gate) - extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG; - else - extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG; - - ew32(EXTCNF_CTRL, extcnf_ctrl); -} - -/** - * e1000_lan_init_done_ich8lan - Check for PHY config completion - * @hw: pointer to the HW structure - * - * Check the appropriate indication the MAC has finished configuring the - * PHY after a software reset. - **/ -static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) -{ - u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT; - - /* Wait for basic configuration completes before proceeding */ - do { - data = er32(STATUS); - data &= E1000_STATUS_LAN_INIT_DONE; - usleep_range(100, 200); - } while ((!data) && --loop); - - /* If basic configuration is incomplete before the above loop - * count reaches 0, loading the configuration from NVM will - * leave the PHY in a bad state possibly resulting in no link. - */ - if (loop == 0) - e_dbg("LAN_INIT_DONE not set, increase timeout\n"); - - /* Clear the Init Done bit for the next init event */ - data = er32(STATUS); - data &= ~E1000_STATUS_LAN_INIT_DONE; - ew32(STATUS, data); -} - -/** - * e1000_post_phy_reset_ich8lan - Perform steps required after a PHY reset - * @hw: pointer to the HW structure - **/ -static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u16 reg; - - if (hw->phy.ops.check_reset_block(hw)) - return 0; - - /* Allow time for h/w to get to quiescent state after reset */ - usleep_range(10000, 20000); - - /* Perform any necessary post-reset workarounds */ - switch (hw->mac.type) { - case e1000_pchlan: - ret_val = e1000_hv_phy_workarounds_ich8lan(hw); - if (ret_val) - return ret_val; - break; - case e1000_pch2lan: - ret_val = e1000_lv_phy_workarounds_ich8lan(hw); - if (ret_val) - return ret_val; - break; - default: - break; - } - - /* Clear the host wakeup bit after lcd reset */ - if (hw->mac.type >= e1000_pchlan) { - e1e_rphy(hw, BM_PORT_GEN_CFG, ®); - reg &= ~BM_WUC_HOST_WU_BIT; - e1e_wphy(hw, BM_PORT_GEN_CFG, reg); - } - - /* Configure the LCD with the extended configuration region in NVM */ - ret_val = e1000_sw_lcd_config_ich8lan(hw); - if (ret_val) - return ret_val; - - /* Configure the LCD with the OEM bits in NVM */ - ret_val = e1000_oem_bits_config_ich8lan(hw, true); - - if (hw->mac.type == e1000_pch2lan) { - /* Ungate automatic PHY configuration on non-managed 82579 */ - if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { - usleep_range(10000, 20000); - e1000_gate_hw_phy_config_ich8lan(hw, false); - } - - /* Set EEE LPI Update Timer to 200usec */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - ret_val = e1000_write_emi_reg_locked(hw, - I82579_LPI_UPDATE_TIMER, - 0x1387); - hw->phy.ops.release(hw); - } - - return ret_val; -} - -/** - * e1000_phy_hw_reset_ich8lan - Performs a PHY reset - * @hw: pointer to the HW structure - * - * Resets the PHY - * This is a function pointer entry point called by drivers - * or other shared routines. - **/ -static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = 0; - - /* Gate automatic PHY configuration by hardware on non-managed 82579 */ - if ((hw->mac.type == e1000_pch2lan) && - !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) - e1000_gate_hw_phy_config_ich8lan(hw, true); - - ret_val = e1000e_phy_hw_reset_generic(hw); - if (ret_val) - return ret_val; - - return e1000_post_phy_reset_ich8lan(hw); -} - -/** - * e1000_set_lplu_state_pchlan - Set Low Power Link Up state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU state according to the active flag. For PCH, if OEM write - * bit are disabled in the NVM, writing the LPLU bits in the MAC will not set - * the phy speed. This function will manually set the LPLU bit and restart - * auto-neg as hw would do. D3 and D0 LPLU will call the same function - * since it configures the same bit. - **/ -static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active) -{ - s32 ret_val; - u16 oem_reg; - - ret_val = e1e_rphy(hw, HV_OEM_BITS, &oem_reg); - if (ret_val) - return ret_val; - - if (active) - oem_reg |= HV_OEM_BITS_LPLU; - else - oem_reg &= ~HV_OEM_BITS_LPLU; - - if (!hw->phy.ops.check_reset_block(hw)) - oem_reg |= HV_OEM_BITS_RESTART_AN; - - return e1e_wphy(hw, HV_OEM_BITS, oem_reg); -} - -/** - * e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU D0 state according to the active flag. When - * activating LPLU this function also disables smart speed - * and vice versa. LPLU will not be activated unless the - * device autonegotiation advertisement meets standards of - * either 10 or 10/100 or 10/100/1000 at all duplexes. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 phy_ctrl; - s32 ret_val = 0; - u16 data; - - if (phy->type == e1000_phy_ife) - return 0; - - phy_ctrl = er32(PHY_CTRL); - - if (active) { - phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; - ew32(PHY_CTRL, phy_ctrl); - - if (phy->type != e1000_phy_igp_3) - return 0; - - /* Call gig speed drop workaround on LPLU before accessing - * any PHY registers - */ - if (hw->mac.type == e1000_ich8lan) - e1000e_gig_downshift_workaround_ich8lan(hw); - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data); - if (ret_val) - return ret_val; - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data); - if (ret_val) - return ret_val; - } else { - phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; - ew32(PHY_CTRL, phy_ctrl); - - if (phy->type != e1000_phy_igp_3) - return 0; - - /* LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } - } - - return 0; -} - -/** - * e1000_set_d3_lplu_state_ich8lan - Set Low Power Linkup D3 state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU D3 state according to the active flag. When - * activating LPLU this function also disables smart speed - * and vice versa. LPLU will not be activated unless the - * device autonegotiation advertisement meets standards of - * either 10 or 10/100 or 10/100/1000 at all duplexes. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 phy_ctrl; - s32 ret_val = 0; - u16 data; - - phy_ctrl = er32(PHY_CTRL); - - if (!active) { - phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; - ew32(PHY_CTRL, phy_ctrl); - - if (phy->type != e1000_phy_igp_3) - return 0; - - /* LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } - } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || - (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || - (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { - phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; - ew32(PHY_CTRL, phy_ctrl); - - if (phy->type != e1000_phy_igp_3) - return 0; - - /* Call gig speed drop workaround on LPLU before accessing - * any PHY registers - */ - if (hw->mac.type == e1000_ich8lan) - e1000e_gig_downshift_workaround_ich8lan(hw); - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data); - } - - return ret_val; -} - -/** - * e1000_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1 - * @hw: pointer to the HW structure - * @bank: pointer to the variable that returns the active bank - * - * Reads signature byte from the NVM using the flash access registers. - * Word 0x13 bits 15:14 = 10b indicate a valid signature for that bank. - **/ -static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) -{ - u32 eecd; - struct e1000_nvm_info *nvm = &hw->nvm; - u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); - u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; - u8 sig_byte = 0; - s32 ret_val; - - switch (hw->mac.type) { - case e1000_ich8lan: - case e1000_ich9lan: - eecd = er32(EECD); - if ((eecd & E1000_EECD_SEC1VAL_VALID_MASK) == - E1000_EECD_SEC1VAL_VALID_MASK) { - if (eecd & E1000_EECD_SEC1VAL) - *bank = 1; - else - *bank = 0; - - return 0; - } - e_dbg("Unable to determine valid NVM bank via EEC - reading flash signature\n"); - /* fall-thru */ - default: - /* set bank to 0 in case flash read fails */ - *bank = 0; - - /* Check bank 0 */ - ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset, - &sig_byte); - if (ret_val) - return ret_val; - if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == - E1000_ICH_NVM_SIG_VALUE) { - *bank = 0; - return 0; - } - - /* Check bank 1 */ - ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset + - bank1_offset, - &sig_byte); - if (ret_val) - return ret_val; - if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == - E1000_ICH_NVM_SIG_VALUE) { - *bank = 1; - return 0; - } - - e_dbg("ERROR: No valid NVM bank present\n"); - return -E1000_ERR_NVM; - } -} - -/** - * e1000_read_nvm_ich8lan - Read word(s) from the NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the word(s) to read. - * @words: Size of data to read in words - * @data: Pointer to the word(s) to read at offset. - * - * Reads a word(s) from the NVM using the flash access registers. - **/ -static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 act_offset; - s32 ret_val = 0; - u32 bank = 0; - u16 i, word; - - if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - nvm->ops.acquire(hw); - - ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); - if (ret_val) { - e_dbg("Could not detect valid bank, assuming bank 0\n"); - bank = 0; - } - - act_offset = (bank) ? nvm->flash_bank_size : 0; - act_offset += offset; - - ret_val = 0; - for (i = 0; i < words; i++) { - if (dev_spec->shadow_ram[offset + i].modified) { - data[i] = dev_spec->shadow_ram[offset + i].value; - } else { - ret_val = e1000_read_flash_word_ich8lan(hw, - act_offset + i, - &word); - if (ret_val) - break; - data[i] = word; - } - } - - nvm->ops.release(hw); - -out: - if (ret_val) - e_dbg("NVM read error: %d\n", ret_val); - - return ret_val; -} - -/** - * e1000_flash_cycle_init_ich8lan - Initialize flash - * @hw: pointer to the HW structure - * - * This function does initial flash setup so that a new read/write/erase cycle - * can be started. - **/ -static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) -{ - union ich8_hws_flash_status hsfsts; - s32 ret_val = -E1000_ERR_NVM; - - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - - /* Check if the flash descriptor is valid */ - if (!hsfsts.hsf_status.fldesvalid) { - e_dbg("Flash descriptor invalid. SW Sequencing must be used.\n"); - return -E1000_ERR_NVM; - } - - /* Clear FCERR and DAEL in hw status by writing 1 */ - hsfsts.hsf_status.flcerr = 1; - hsfsts.hsf_status.dael = 1; - - ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval); - - /* Either we should have a hardware SPI cycle in progress - * bit to check against, in order to start a new cycle or - * FDONE bit should be changed in the hardware so that it - * is 1 after hardware reset, which can then be used as an - * indication whether a cycle is in progress or has been - * completed. - */ - - if (!hsfsts.hsf_status.flcinprog) { - /* There is no cycle running at present, - * so we can start a cycle. - * Begin by setting Flash Cycle Done. - */ - hsfsts.hsf_status.flcdone = 1; - ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval); - ret_val = 0; - } else { - s32 i; - - /* Otherwise poll for sometime so the current - * cycle has a chance to end before giving up. - */ - for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) { - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (!hsfsts.hsf_status.flcinprog) { - ret_val = 0; - break; - } - udelay(1); - } - if (!ret_val) { - /* Successful in waiting for previous cycle to timeout, - * now set the Flash Cycle Done. - */ - hsfsts.hsf_status.flcdone = 1; - ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval); - } else { - e_dbg("Flash controller busy, cannot get access\n"); - } - } - - return ret_val; -} - -/** - * e1000_flash_cycle_ich8lan - Starts flash cycle (read/write/erase) - * @hw: pointer to the HW structure - * @timeout: maximum time to wait for completion - * - * This function starts a flash cycle and waits for its completion. - **/ -static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) -{ - union ich8_hws_flash_ctrl hsflctl; - union ich8_hws_flash_status hsfsts; - u32 i = 0; - - /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ - hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); - hsflctl.hsf_ctrl.flcgo = 1; - ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); - - /* wait till FDONE bit is set to 1 */ - do { - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcdone) - break; - udelay(1); - } while (i++ < timeout); - - if (hsfsts.hsf_status.flcdone && !hsfsts.hsf_status.flcerr) - return 0; - - return -E1000_ERR_NVM; -} - -/** - * e1000_read_flash_word_ich8lan - Read word from flash - * @hw: pointer to the HW structure - * @offset: offset to data location - * @data: pointer to the location for storing the data - * - * Reads the flash word at offset into data. Offset is converted - * to bytes before read. - **/ -static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, - u16 *data) -{ - /* Must convert offset into bytes. */ - offset <<= 1; - - return e1000_read_flash_data_ich8lan(hw, offset, 2, data); -} - -/** - * e1000_read_flash_byte_ich8lan - Read byte from flash - * @hw: pointer to the HW structure - * @offset: The offset of the byte to read. - * @data: Pointer to a byte to store the value read. - * - * Reads a single byte from the NVM using the flash access registers. - **/ -static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, - u8 *data) -{ - s32 ret_val; - u16 word = 0; - - ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); - if (ret_val) - return ret_val; - - *data = (u8)word; - - return 0; -} - -/** - * e1000_read_flash_data_ich8lan - Read byte or word from NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the byte or word to read. - * @size: Size of data to read, 1=byte 2=word - * @data: Pointer to the word to store the value read. - * - * Reads a byte or word from the NVM using the flash access registers. - **/ -static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, - u8 size, u16 *data) -{ - union ich8_hws_flash_status hsfsts; - union ich8_hws_flash_ctrl hsflctl; - u32 flash_linear_addr; - u32 flash_data = 0; - s32 ret_val = -E1000_ERR_NVM; - u8 count = 0; - - if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) - return -E1000_ERR_NVM; - - flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + - hw->nvm.flash_base_addr); - - do { - udelay(1); - /* Steps */ - ret_val = e1000_flash_cycle_init_ich8lan(hw); - if (ret_val) - break; - - hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); - /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ - hsflctl.hsf_ctrl.fldbcount = size - 1; - hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; - ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); - - ew32flash(ICH_FLASH_FADDR, flash_linear_addr); - - ret_val = - e1000_flash_cycle_ich8lan(hw, - ICH_FLASH_READ_COMMAND_TIMEOUT); - - /* Check if FCERR is set to 1, if set to 1, clear it - * and try the whole sequence a few more times, else - * read in (shift in) the Flash Data0, the order is - * least significant byte first msb to lsb - */ - if (!ret_val) { - flash_data = er32flash(ICH_FLASH_FDATA0); - if (size == 1) - *data = (u8)(flash_data & 0x000000FF); - else if (size == 2) - *data = (u16)(flash_data & 0x0000FFFF); - break; - } else { - /* If we've gotten here, then things are probably - * completely hosed, but if the error condition is - * detected, it won't hurt to give it another try... - * ICH_FLASH_CYCLE_REPEAT_COUNT times. - */ - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr) { - /* Repeat for some time before giving up. */ - continue; - } else if (!hsfsts.hsf_status.flcdone) { - e_dbg("Timeout error - flash cycle did not complete.\n"); - break; - } - } - } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); - - return ret_val; -} - -/** - * e1000_write_nvm_ich8lan - Write word(s) to the NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the word(s) to write. - * @words: Size of data to write in words - * @data: Pointer to the word(s) to write at offset. - * - * Writes a byte or word to the NVM using the flash access registers. - **/ -static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u16 i; - - if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - return -E1000_ERR_NVM; - } - - nvm->ops.acquire(hw); - - for (i = 0; i < words; i++) { - dev_spec->shadow_ram[offset + i].modified = true; - dev_spec->shadow_ram[offset + i].value = data[i]; - } - - nvm->ops.release(hw); - - return 0; -} - -/** - * e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM - * @hw: pointer to the HW structure - * - * The NVM checksum is updated by calling the generic update_nvm_checksum, - * which writes the checksum to the shadow ram. The changes in the shadow - * ram are then committed to the EEPROM by processing each bank at a time - * checking for the modified bit and writing only the pending changes. - * After a successful commit, the shadow ram is cleared and is ready for - * future writes. - **/ -static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 i, act_offset, new_bank_offset, old_bank_offset, bank; - s32 ret_val; - u16 data; - - ret_val = e1000e_update_nvm_checksum_generic(hw); - if (ret_val) - goto out; - - if (nvm->type != e1000_nvm_flash_sw) - goto out; - - nvm->ops.acquire(hw); - - /* We're writing to the opposite bank so if we're on bank 1, - * write to bank 0 etc. We also need to erase the segment that - * is going to be written - */ - ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); - if (ret_val) { - e_dbg("Could not detect valid bank, assuming bank 0\n"); - bank = 0; - } - - if (bank == 0) { - new_bank_offset = nvm->flash_bank_size; - old_bank_offset = 0; - ret_val = e1000_erase_flash_bank_ich8lan(hw, 1); - if (ret_val) - goto release; - } else { - old_bank_offset = nvm->flash_bank_size; - new_bank_offset = 0; - ret_val = e1000_erase_flash_bank_ich8lan(hw, 0); - if (ret_val) - goto release; - } - - for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) { - /* Determine whether to write the value stored - * in the other NVM bank or a modified value stored - * in the shadow RAM - */ - if (dev_spec->shadow_ram[i].modified) { - data = dev_spec->shadow_ram[i].value; - } else { - ret_val = e1000_read_flash_word_ich8lan(hw, i + - old_bank_offset, - &data); - if (ret_val) - break; - } - - /* If the word is 0x13, then make sure the signature bits - * (15:14) are 11b until the commit has completed. - * This will allow us to write 10b which indicates the - * signature is valid. We want to do this after the write - * has completed so that we don't mark the segment valid - * while the write is still in progress - */ - if (i == E1000_ICH_NVM_SIG_WORD) - data |= E1000_ICH_NVM_SIG_MASK; - - /* Convert offset to bytes. */ - act_offset = (i + new_bank_offset) << 1; - - usleep_range(100, 200); - /* Write the bytes to the new bank. */ - ret_val = e1000_retry_write_flash_byte_ich8lan(hw, - act_offset, - (u8)data); - if (ret_val) - break; - - usleep_range(100, 200); - ret_val = e1000_retry_write_flash_byte_ich8lan(hw, - act_offset + 1, - (u8)(data >> 8)); - if (ret_val) - break; - } - - /* Don't bother writing the segment valid bits if sector - * programming failed. - */ - if (ret_val) { - /* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */ - e_dbg("Flash commit failed.\n"); - goto release; - } - - /* Finally validate the new segment by setting bit 15:14 - * to 10b in word 0x13 , this can be done without an - * erase as well since these bits are 11 to start with - * and we need to change bit 14 to 0b - */ - act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD; - ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data); - if (ret_val) - goto release; - - data &= 0xBFFF; - ret_val = e1000_retry_write_flash_byte_ich8lan(hw, - act_offset * 2 + 1, - (u8)(data >> 8)); - if (ret_val) - goto release; - - /* And invalidate the previously valid segment by setting - * its signature word (0x13) high_byte to 0b. This can be - * done without an erase because flash erase sets all bits - * to 1's. We can write 1's to 0's without an erase - */ - act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1; - ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0); - if (ret_val) - goto release; - - /* Great! Everything worked, we can now clear the cached entries. */ - for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) { - dev_spec->shadow_ram[i].modified = false; - dev_spec->shadow_ram[i].value = 0xFFFF; - } - -release: - nvm->ops.release(hw); - - /* Reload the EEPROM, or else modifications will not appear - * until after the next adapter reset. - */ - if (!ret_val) { - nvm->ops.reload(hw); - usleep_range(10000, 20000); - } - -out: - if (ret_val) - e_dbg("NVM update error: %d\n", ret_val); - - return ret_val; -} - -/** - * e1000_validate_nvm_checksum_ich8lan - Validate EEPROM checksum - * @hw: pointer to the HW structure - * - * Check to see if checksum needs to be fixed by reading bit 6 in word 0x19. - * If the bit is 0, that the EEPROM had been modified, but the checksum was not - * calculated, in which case we need to calculate the checksum and set bit 6. - **/ -static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val; - u16 data; - u16 word; - u16 valid_csum_mask; - - /* Read NVM and check Invalid Image CSUM bit. If this bit is 0, - * the checksum needs to be fixed. This bit is an indication that - * the NVM was prepared by OEM software and did not calculate - * the checksum...a likely scenario. - */ - switch (hw->mac.type) { - case e1000_pch_lpt: - word = NVM_COMPAT; - valid_csum_mask = NVM_COMPAT_VALID_CSUM; - break; - default: - word = NVM_FUTURE_INIT_WORD1; - valid_csum_mask = NVM_FUTURE_INIT_WORD1_VALID_CSUM; - break; - } - - ret_val = e1000_read_nvm(hw, word, 1, &data); - if (ret_val) - return ret_val; - - if (!(data & valid_csum_mask)) { - data |= valid_csum_mask; - ret_val = e1000_write_nvm(hw, word, 1, &data); - if (ret_val) - return ret_val; - ret_val = e1000e_update_nvm_checksum(hw); - if (ret_val) - return ret_val; - } - - return e1000e_validate_nvm_checksum_generic(hw); -} - -/** - * e1000e_write_protect_nvm_ich8lan - Make the NVM read-only - * @hw: pointer to the HW structure - * - * To prevent malicious write/erase of the NVM, set it to be read-only - * so that the hardware ignores all write/erase cycles of the NVM via - * the flash control registers. The shadow-ram copy of the NVM will - * still be updated, however any updates to this copy will not stick - * across driver reloads. - **/ -void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - union ich8_flash_protected_range pr0; - union ich8_hws_flash_status hsfsts; - u32 gfpreg; - - nvm->ops.acquire(hw); - - gfpreg = er32flash(ICH_FLASH_GFPREG); - - /* Write-protect GbE Sector of NVM */ - pr0.regval = er32flash(ICH_FLASH_PR0); - pr0.range.base = gfpreg & FLASH_GFPREG_BASE_MASK; - pr0.range.limit = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK); - pr0.range.wpe = true; - ew32flash(ICH_FLASH_PR0, pr0.regval); - - /* Lock down a subset of GbE Flash Control Registers, e.g. - * PR0 to prevent the write-protection from being lifted. - * Once FLOCKDN is set, the registers protected by it cannot - * be written until FLOCKDN is cleared by a hardware reset. - */ - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - hsfsts.hsf_status.flockdn = true; - ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval); - - nvm->ops.release(hw); -} - -/** - * e1000_write_flash_data_ich8lan - Writes bytes to the NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the byte/word to read. - * @size: Size of data to read, 1=byte 2=word - * @data: The byte(s) to write to the NVM. - * - * Writes one/two bytes to the NVM using the flash access registers. - **/ -static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, - u8 size, u16 data) -{ - union ich8_hws_flash_status hsfsts; - union ich8_hws_flash_ctrl hsflctl; - u32 flash_linear_addr; - u32 flash_data = 0; - s32 ret_val; - u8 count = 0; - - if (size < 1 || size > 2 || data > size * 0xff || - offset > ICH_FLASH_LINEAR_ADDR_MASK) - return -E1000_ERR_NVM; - - flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + - hw->nvm.flash_base_addr); - - do { - udelay(1); - /* Steps */ - ret_val = e1000_flash_cycle_init_ich8lan(hw); - if (ret_val) - break; - - hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); - /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ - hsflctl.hsf_ctrl.fldbcount = size - 1; - hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; - ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); - - ew32flash(ICH_FLASH_FADDR, flash_linear_addr); - - if (size == 1) - flash_data = (u32)data & 0x00FF; - else - flash_data = (u32)data; - - ew32flash(ICH_FLASH_FDATA0, flash_data); - - /* check if FCERR is set to 1 , if set to 1, clear it - * and try the whole sequence a few more times else done - */ - ret_val = - e1000_flash_cycle_ich8lan(hw, - ICH_FLASH_WRITE_COMMAND_TIMEOUT); - if (!ret_val) - break; - - /* If we're here, then things are most likely - * completely hosed, but if the error condition - * is detected, it won't hurt to give it another - * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. - */ - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr) - /* Repeat for some time before giving up. */ - continue; - if (!hsfsts.hsf_status.flcdone) { - e_dbg("Timeout error - flash cycle did not complete.\n"); - break; - } - } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); - - return ret_val; -} - -/** - * e1000_write_flash_byte_ich8lan - Write a single byte to NVM - * @hw: pointer to the HW structure - * @offset: The index of the byte to read. - * @data: The byte to write to the NVM. - * - * Writes a single byte to the NVM using the flash access registers. - **/ -static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, - u8 data) -{ - u16 word = (u16)data; - - return e1000_write_flash_data_ich8lan(hw, offset, 1, word); -} - -/** - * e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM - * @hw: pointer to the HW structure - * @offset: The offset of the byte to write. - * @byte: The byte to write to the NVM. - * - * Writes a single byte to the NVM using the flash access registers. - * Goes through a retry algorithm before giving up. - **/ -static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, - u32 offset, u8 byte) -{ - s32 ret_val; - u16 program_retries; - - ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); - if (!ret_val) - return ret_val; - - for (program_retries = 0; program_retries < 100; program_retries++) { - e_dbg("Retrying Byte %2.2X at offset %u\n", byte, offset); - usleep_range(100, 200); - ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); - if (!ret_val) - break; - } - if (program_retries == 100) - return -E1000_ERR_NVM; - - return 0; -} - -/** - * e1000_erase_flash_bank_ich8lan - Erase a bank (4k) from NVM - * @hw: pointer to the HW structure - * @bank: 0 for first bank, 1 for second bank, etc. - * - * Erases the bank specified. Each bank is a 4k block. Banks are 0 based. - * bank N is 4096 * N + flash_reg_addr. - **/ -static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - union ich8_hws_flash_status hsfsts; - union ich8_hws_flash_ctrl hsflctl; - u32 flash_linear_addr; - /* bank size is in 16bit words - adjust to bytes */ - u32 flash_bank_size = nvm->flash_bank_size * 2; - s32 ret_val; - s32 count = 0; - s32 j, iteration, sector_size; - - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - - /* Determine HW Sector size: Read BERASE bits of hw flash status - * register - * 00: The Hw sector is 256 bytes, hence we need to erase 16 - * consecutive sectors. The start index for the nth Hw sector - * can be calculated as = bank * 4096 + n * 256 - * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector. - * The start index for the nth Hw sector can be calculated - * as = bank * 4096 - * 10: The Hw sector is 8K bytes, nth sector = bank * 8192 - * (ich9 only, otherwise error condition) - * 11: The Hw sector is 64K bytes, nth sector = bank * 65536 - */ - switch (hsfsts.hsf_status.berasesz) { - case 0: - /* Hw sector size 256 */ - sector_size = ICH_FLASH_SEG_SIZE_256; - iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_256; - break; - case 1: - sector_size = ICH_FLASH_SEG_SIZE_4K; - iteration = 1; - break; - case 2: - sector_size = ICH_FLASH_SEG_SIZE_8K; - iteration = 1; - break; - case 3: - sector_size = ICH_FLASH_SEG_SIZE_64K; - iteration = 1; - break; - default: - return -E1000_ERR_NVM; - } - - /* Start with the base address, then add the sector offset. */ - flash_linear_addr = hw->nvm.flash_base_addr; - flash_linear_addr += (bank) ? flash_bank_size : 0; - - for (j = 0; j < iteration; j++) { - do { - u32 timeout = ICH_FLASH_ERASE_COMMAND_TIMEOUT; - - /* Steps */ - ret_val = e1000_flash_cycle_init_ich8lan(hw); - if (ret_val) - return ret_val; - - /* Write a value 11 (block Erase) in Flash - * Cycle field in hw flash control - */ - hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); - hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; - ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); - - /* Write the last 24 bits of an index within the - * block into Flash Linear address field in Flash - * Address. - */ - flash_linear_addr += (j * sector_size); - ew32flash(ICH_FLASH_FADDR, flash_linear_addr); - - ret_val = e1000_flash_cycle_ich8lan(hw, timeout); - if (!ret_val) - break; - - /* Check if FCERR is set to 1. If 1, - * clear it and try the whole sequence - * a few more times else Done - */ - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr) - /* repeat for some time before giving up */ - continue; - else if (!hsfsts.hsf_status.flcdone) - return ret_val; - } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT); - } - - return 0; -} - -/** - * e1000_valid_led_default_ich8lan - Set the default LED settings - * @hw: pointer to the HW structure - * @data: Pointer to the LED settings - * - * Reads the LED default settings from the NVM to data. If the NVM LED - * settings is all 0's or F's, set the LED default to a valid LED default - * setting. - **/ -static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data) -{ - s32 ret_val; - - ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) - *data = ID_LED_DEFAULT_ICH8LAN; - - return 0; -} - -/** - * e1000_id_led_init_pchlan - store LED configurations - * @hw: pointer to the HW structure - * - * PCH does not control LEDs via the LEDCTL register, rather it uses - * the PHY LED configuration register. - * - * PCH also does not have an "always on" or "always off" mode which - * complicates the ID feature. Instead of using the "on" mode to indicate - * in ledctl_mode2 the LEDs to use for ID (see e1000e_id_led_init_generic()), - * use "link_up" mode. The LEDs will still ID on request if there is no - * link based on logic in e1000_led_[on|off]_pchlan(). - **/ -static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - const u32 ledctl_on = E1000_LEDCTL_MODE_LINK_UP; - const u32 ledctl_off = E1000_LEDCTL_MODE_LINK_UP | E1000_PHY_LED0_IVRT; - u16 data, i, temp, shift; - - /* Get default ID LED modes */ - ret_val = hw->nvm.ops.valid_led_default(hw, &data); - if (ret_val) - return ret_val; - - mac->ledctl_default = er32(LEDCTL); - mac->ledctl_mode1 = mac->ledctl_default; - mac->ledctl_mode2 = mac->ledctl_default; - - for (i = 0; i < 4; i++) { - temp = (data >> (i << 2)) & E1000_LEDCTL_LED0_MODE_MASK; - shift = (i * 5); - switch (temp) { - case ID_LED_ON1_DEF2: - case ID_LED_ON1_ON2: - case ID_LED_ON1_OFF2: - mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); - mac->ledctl_mode1 |= (ledctl_on << shift); - break; - case ID_LED_OFF1_DEF2: - case ID_LED_OFF1_ON2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); - mac->ledctl_mode1 |= (ledctl_off << shift); - break; - default: - /* Do nothing */ - break; - } - switch (temp) { - case ID_LED_DEF1_ON2: - case ID_LED_ON1_ON2: - case ID_LED_OFF1_ON2: - mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); - mac->ledctl_mode2 |= (ledctl_on << shift); - break; - case ID_LED_DEF1_OFF2: - case ID_LED_ON1_OFF2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); - mac->ledctl_mode2 |= (ledctl_off << shift); - break; - default: - /* Do nothing */ - break; - } - } - - return 0; -} - -/** - * e1000_get_bus_info_ich8lan - Get/Set the bus type and width - * @hw: pointer to the HW structure - * - * ICH8 use the PCI Express bus, but does not contain a PCI Express Capability - * register, so the the bus width is hard coded. - **/ -static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - s32 ret_val; - - ret_val = e1000e_get_bus_info_pcie(hw); - - /* ICH devices are "PCI Express"-ish. They have - * a configuration space, but do not contain - * PCI Express Capability registers, so bus width - * must be hardcoded. - */ - if (bus->width == e1000_bus_width_unknown) - bus->width = e1000_bus_width_pcie_x1; - - return ret_val; -} - -/** - * e1000_reset_hw_ich8lan - Reset the hardware - * @hw: pointer to the HW structure - * - * Does a full reset of the hardware which includes a reset of the PHY and - * MAC. - **/ -static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) -{ - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u16 kum_cfg; - u32 ctrl, reg; - s32 ret_val; - - /* Prevent the PCI-E bus from sticking if there is no TLP connection - * on the last TLP read/write transaction when MAC is reset. - */ - ret_val = e1000e_disable_pcie_master(hw); - if (ret_val) - e_dbg("PCI-E Master disable polling has failed.\n"); - - e_dbg("Masking off all interrupts\n"); - ew32(IMC, 0xffffffff); - - /* Disable the Transmit and Receive units. Then delay to allow - * any pending transactions to complete before we hit the MAC - * with the global reset. - */ - ew32(RCTL, 0); - ew32(TCTL, E1000_TCTL_PSP); - e1e_flush(); - - usleep_range(10000, 20000); - - /* Workaround for ICH8 bit corruption issue in FIFO memory */ - if (hw->mac.type == e1000_ich8lan) { - /* Set Tx and Rx buffer allocation to 8k apiece. */ - ew32(PBA, E1000_PBA_8K); - /* Set Packet Buffer Size to 16k. */ - ew32(PBS, E1000_PBS_16K); - } - - if (hw->mac.type == e1000_pchlan) { - /* Save the NVM K1 bit setting */ - ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &kum_cfg); - if (ret_val) - return ret_val; - - if (kum_cfg & E1000_NVM_K1_ENABLE) - dev_spec->nvm_k1_enabled = true; - else - dev_spec->nvm_k1_enabled = false; - } - - ctrl = er32(CTRL); - - if (!hw->phy.ops.check_reset_block(hw)) { - /* Full-chip reset requires MAC and PHY reset at the same - * time to make sure the interface between MAC and the - * external PHY is reset. - */ - ctrl |= E1000_CTRL_PHY_RST; - - /* Gate automatic PHY configuration by hardware on - * non-managed 82579 - */ - if ((hw->mac.type == e1000_pch2lan) && - !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) - e1000_gate_hw_phy_config_ich8lan(hw, true); - } - ret_val = e1000_acquire_swflag_ich8lan(hw); - e_dbg("Issuing a global reset to ich8lan\n"); - ew32(CTRL, (ctrl | E1000_CTRL_RST)); - /* cannot issue a flush here because it hangs the hardware */ - msleep(20); - - /* Set Phy Config Counter to 50msec */ - if (hw->mac.type == e1000_pch2lan) { - reg = er32(FEXTNVM3); - reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; - reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; - ew32(FEXTNVM3, reg); - } - - if (!ret_val) - clear_bit(__E1000_ACCESS_SHARED_RESOURCE, &hw->adapter->state); - - if (ctrl & E1000_CTRL_PHY_RST) { - ret_val = hw->phy.ops.get_cfg_done(hw); - if (ret_val) - return ret_val; - - ret_val = e1000_post_phy_reset_ich8lan(hw); - if (ret_val) - return ret_val; - } - - /* For PCH, this write will make sure that any noise - * will be detected as a CRC error and be dropped rather than show up - * as a bad packet to the DMA engine. - */ - if (hw->mac.type == e1000_pchlan) - ew32(CRC_OFFSET, 0x65656565); - - ew32(IMC, 0xffffffff); - er32(ICR); - - reg = er32(KABGTXD); - reg |= E1000_KABGTXD_BGSQLBIAS; - ew32(KABGTXD, reg); - - return 0; -} - -/** - * e1000_init_hw_ich8lan - Initialize the hardware - * @hw: pointer to the HW structure - * - * Prepares the hardware for transmit and receive by doing the following: - * - initialize hardware bits - * - initialize LED identification - * - setup receive address registers - * - setup flow control - * - setup transmit descriptors - * - clear statistics - **/ -static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 ctrl_ext, txdctl, snoop; - s32 ret_val; - u16 i; - - e1000_initialize_hw_bits_ich8lan(hw); - - /* Initialize identification LED */ - ret_val = mac->ops.id_led_init(hw); - /* An error is not fatal and we should not stop init due to this */ - if (ret_val) - e_dbg("Error initializing identification LED\n"); - - /* Setup the receive address. */ - e1000e_init_rx_addrs(hw, mac->rar_entry_count); - - /* Zero out the Multicast HASH table */ - e_dbg("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - - /* The 82578 Rx buffer will stall if wakeup is enabled in host and - * the ME. Disable wakeup by clearing the host wakeup bit. - * Reset the phy after disabling host wakeup to reset the Rx buffer. - */ - if (hw->phy.type == e1000_phy_82578) { - e1e_rphy(hw, BM_PORT_GEN_CFG, &i); - i &= ~BM_WUC_HOST_WU_BIT; - e1e_wphy(hw, BM_PORT_GEN_CFG, i); - ret_val = e1000_phy_hw_reset_ich8lan(hw); - if (ret_val) - return ret_val; - } - - /* Setup link and flow control */ - ret_val = mac->ops.setup_link(hw); - - /* Set the transmit descriptor write-back policy for both queues */ - txdctl = er32(TXDCTL(0)); - txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB); - txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) | - E1000_TXDCTL_MAX_TX_DESC_PREFETCH); - ew32(TXDCTL(0), txdctl); - txdctl = er32(TXDCTL(1)); - txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB); - txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) | - E1000_TXDCTL_MAX_TX_DESC_PREFETCH); - ew32(TXDCTL(1), txdctl); - - /* ICH8 has opposite polarity of no_snoop bits. - * By default, we should use snoop behavior. - */ - if (mac->type == e1000_ich8lan) - snoop = PCIE_ICH8_SNOOP_ALL; - else - snoop = (u32)~(PCIE_NO_SNOOP_ALL); - e1000e_set_pcie_no_snoop(hw, snoop); - - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_RO_DIS; - ew32(CTRL_EXT, ctrl_ext); - - /* Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs_ich8lan(hw); - - return ret_val; -} - -/** - * e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits - * @hw: pointer to the HW structure - * - * Sets/Clears required hardware bits necessary for correctly setting up the - * hardware for transmit and receive. - **/ -static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) -{ - u32 reg; - - /* Extended Device Control */ - reg = er32(CTRL_EXT); - reg |= (1 << 22); - /* Enable PHY low-power state when MAC is at D3 w/o WoL */ - if (hw->mac.type >= e1000_pchlan) - reg |= E1000_CTRL_EXT_PHYPDEN; - ew32(CTRL_EXT, reg); - - /* Transmit Descriptor Control 0 */ - reg = er32(TXDCTL(0)); - reg |= (1 << 22); - ew32(TXDCTL(0), reg); - - /* Transmit Descriptor Control 1 */ - reg = er32(TXDCTL(1)); - reg |= (1 << 22); - ew32(TXDCTL(1), reg); - - /* Transmit Arbitration Control 0 */ - reg = er32(TARC(0)); - if (hw->mac.type == e1000_ich8lan) - reg |= (1 << 28) | (1 << 29); - reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27); - ew32(TARC(0), reg); - - /* Transmit Arbitration Control 1 */ - reg = er32(TARC(1)); - if (er32(TCTL) & E1000_TCTL_MULR) - reg &= ~(1 << 28); - else - reg |= (1 << 28); - reg |= (1 << 24) | (1 << 26) | (1 << 30); - ew32(TARC(1), reg); - - /* Device Status */ - if (hw->mac.type == e1000_ich8lan) { - reg = er32(STATUS); - reg &= ~(1 << 31); - ew32(STATUS, reg); - } - - /* work-around descriptor data corruption issue during nfs v2 udp - * traffic, just disable the nfs filtering capability - */ - reg = er32(RFCTL); - reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS); - - /* Disable IPv6 extension header parsing because some malformed - * IPv6 headers can hang the Rx. - */ - if (hw->mac.type == e1000_ich8lan) - reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); - ew32(RFCTL, reg); - - /* Enable ECC on Lynxpoint */ - if (hw->mac.type == e1000_pch_lpt) { - reg = er32(PBECCSTS); - reg |= E1000_PBECCSTS_ECC_ENABLE; - ew32(PBECCSTS, reg); - - reg = er32(CTRL); - reg |= E1000_CTRL_MEHE; - ew32(CTRL, reg); - } -} - -/** - * e1000_setup_link_ich8lan - Setup flow control and link settings - * @hw: pointer to the HW structure - * - * Determines which flow control settings to use, then configures flow - * control. Calls the appropriate media-specific link configuration - * function. Assuming the adapter has a valid link partner, a valid link - * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. - **/ -static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val; - - if (hw->phy.ops.check_reset_block(hw)) - return 0; - - /* ICH parts do not have a word in the NVM to determine - * the default flow control setting, so we explicitly - * set it to full. - */ - if (hw->fc.requested_mode == e1000_fc_default) { - /* Workaround h/w hang when Tx flow control enabled */ - if (hw->mac.type == e1000_pchlan) - hw->fc.requested_mode = e1000_fc_rx_pause; - else - hw->fc.requested_mode = e1000_fc_full; - } - - /* Save off the requested flow control mode for use later. Depending - * on the link partner's capabilities, we may or may not use this mode. - */ - hw->fc.current_mode = hw->fc.requested_mode; - - e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode); - - /* Continue to configure the copper link. */ - ret_val = hw->mac.ops.setup_physical_interface(hw); - if (ret_val) - return ret_val; - - ew32(FCTTV, hw->fc.pause_time); - if ((hw->phy.type == e1000_phy_82578) || - (hw->phy.type == e1000_phy_82579) || - (hw->phy.type == e1000_phy_i217) || - (hw->phy.type == e1000_phy_82577)) { - ew32(FCRTV_PCH, hw->fc.refresh_time); - - ret_val = e1e_wphy(hw, PHY_REG(BM_PORT_CTRL_PAGE, 27), - hw->fc.pause_time); - if (ret_val) - return ret_val; - } - - return e1000e_set_fc_watermarks(hw); -} - -/** - * e1000_setup_copper_link_ich8lan - Configure MAC/PHY interface - * @hw: pointer to the HW structure - * - * Configures the kumeran interface to the PHY to wait the appropriate time - * when polling the PHY, then call the generic setup_copper_link to finish - * configuring the copper link. - **/ -static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 reg_data; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ew32(CTRL, ctrl); - - /* Set the mac to wait the maximum time between each iteration - * and increase the max iterations when polling the phy; - * this fixes erroneous timeouts at 10Mbps. - */ - ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_TIMEOUTS, 0xFFFF); - if (ret_val) - return ret_val; - ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - ®_data); - if (ret_val) - return ret_val; - reg_data |= 0x3F; - ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - reg_data); - if (ret_val) - return ret_val; - - switch (hw->phy.type) { - case e1000_phy_igp_3: - ret_val = e1000e_copper_link_setup_igp(hw); - if (ret_val) - return ret_val; - break; - case e1000_phy_bm: - case e1000_phy_82578: - ret_val = e1000e_copper_link_setup_m88(hw); - if (ret_val) - return ret_val; - break; - case e1000_phy_82577: - case e1000_phy_82579: - ret_val = e1000_copper_link_setup_82577(hw); - if (ret_val) - return ret_val; - break; - case e1000_phy_ife: - ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, ®_data); - if (ret_val) - return ret_val; - - reg_data &= ~IFE_PMC_AUTO_MDIX; - - switch (hw->phy.mdix) { - case 1: - reg_data &= ~IFE_PMC_FORCE_MDIX; - break; - case 2: - reg_data |= IFE_PMC_FORCE_MDIX; - break; - case 0: - default: - reg_data |= IFE_PMC_AUTO_MDIX; - break; - } - ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, reg_data); - if (ret_val) - return ret_val; - break; - default: - break; - } - - return e1000e_setup_copper_link(hw); -} - -/** - * e1000_setup_copper_link_pch_lpt - Configure MAC/PHY interface - * @hw: pointer to the HW structure - * - * Calls the PHY specific link setup function and then calls the - * generic setup_copper_link to finish configuring the link for - * Lynxpoint PCH devices - **/ -static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ew32(CTRL, ctrl); - - ret_val = e1000_copper_link_setup_82577(hw); - if (ret_val) - return ret_val; - - return e1000e_setup_copper_link(hw); -} - -/** - * e1000_get_link_up_info_ich8lan - Get current link speed and duplex - * @hw: pointer to the HW structure - * @speed: pointer to store current link speed - * @duplex: pointer to store the current link duplex - * - * Calls the generic get_speed_and_duplex to retrieve the current link - * information and then calls the Kumeran lock loss workaround for links at - * gigabit speeds. - **/ -static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, - u16 *duplex) -{ - s32 ret_val; - - ret_val = e1000e_get_speed_and_duplex_copper(hw, speed, duplex); - if (ret_val) - return ret_val; - - if ((hw->mac.type == e1000_ich8lan) && - (hw->phy.type == e1000_phy_igp_3) && (*speed == SPEED_1000)) { - ret_val = e1000_kmrn_lock_loss_workaround_ich8lan(hw); - } - - return ret_val; -} - -/** - * e1000_kmrn_lock_loss_workaround_ich8lan - Kumeran workaround - * @hw: pointer to the HW structure - * - * Work-around for 82566 Kumeran PCS lock loss: - * On link status change (i.e. PCI reset, speed change) and link is up and - * speed is gigabit- - * 0) if workaround is optionally disabled do nothing - * 1) wait 1ms for Kumeran link to come up - * 2) check Kumeran Diagnostic register PCS lock loss bit - * 3) if not set the link is locked (all is good), otherwise... - * 4) reset the PHY - * 5) repeat up to 10 times - * Note: this is only called for IGP3 copper when speed is 1gb. - **/ -static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) -{ - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 phy_ctrl; - s32 ret_val; - u16 i, data; - bool link; - - if (!dev_spec->kmrn_lock_loss_workaround_enabled) - return 0; - - /* Make sure link is up before proceeding. If not just return. - * Attempting this while link is negotiating fouled up link - * stability - */ - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (!link) - return 0; - - for (i = 0; i < 10; i++) { - /* read once to clear */ - ret_val = e1e_rphy(hw, IGP3_KMRN_DIAG, &data); - if (ret_val) - return ret_val; - /* and again to get new status */ - ret_val = e1e_rphy(hw, IGP3_KMRN_DIAG, &data); - if (ret_val) - return ret_val; - - /* check for PCS lock */ - if (!(data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS)) - return 0; - - /* Issue PHY reset */ - e1000_phy_hw_reset(hw); - mdelay(5); - } - /* Disable GigE link negotiation */ - phy_ctrl = er32(PHY_CTRL); - phy_ctrl |= (E1000_PHY_CTRL_GBE_DISABLE | - E1000_PHY_CTRL_NOND0A_GBE_DISABLE); - ew32(PHY_CTRL, phy_ctrl); - - /* Call gig speed drop workaround on Gig disable before accessing - * any PHY registers - */ - e1000e_gig_downshift_workaround_ich8lan(hw); - - /* unable to acquire PCS lock */ - return -E1000_ERR_PHY; -} - -/** - * e1000e_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state - * @hw: pointer to the HW structure - * @state: boolean value used to set the current Kumeran workaround state - * - * If ICH8, set the current Kumeran workaround state (enabled - true - * /disabled - false). - **/ -void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, - bool state) -{ - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - - if (hw->mac.type != e1000_ich8lan) { - e_dbg("Workaround applies to ICH8 only.\n"); - return; - } - - dev_spec->kmrn_lock_loss_workaround_enabled = state; -} - -/** - * e1000_ipg3_phy_powerdown_workaround_ich8lan - Power down workaround on D3 - * @hw: pointer to the HW structure - * - * Workaround for 82566 power-down on D3 entry: - * 1) disable gigabit link - * 2) write VR power-down enable - * 3) read it back - * Continue if successful, else issue LCD reset and repeat - **/ -void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) -{ - u32 reg; - u16 data; - u8 retry = 0; - - if (hw->phy.type != e1000_phy_igp_3) - return; - - /* Try the workaround twice (if needed) */ - do { - /* Disable link */ - reg = er32(PHY_CTRL); - reg |= (E1000_PHY_CTRL_GBE_DISABLE | - E1000_PHY_CTRL_NOND0A_GBE_DISABLE); - ew32(PHY_CTRL, reg); - - /* Call gig speed drop workaround on Gig disable before - * accessing any PHY registers - */ - if (hw->mac.type == e1000_ich8lan) - e1000e_gig_downshift_workaround_ich8lan(hw); - - /* Write VR power-down enable */ - e1e_rphy(hw, IGP3_VR_CTRL, &data); - data &= ~IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; - e1e_wphy(hw, IGP3_VR_CTRL, data | IGP3_VR_CTRL_MODE_SHUTDOWN); - - /* Read it back and test */ - e1e_rphy(hw, IGP3_VR_CTRL, &data); - data &= IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; - if ((data == IGP3_VR_CTRL_MODE_SHUTDOWN) || retry) - break; - - /* Issue PHY reset and repeat at most one more time */ - reg = er32(CTRL); - ew32(CTRL, reg | E1000_CTRL_PHY_RST); - retry++; - } while (retry); -} - -/** - * e1000e_gig_downshift_workaround_ich8lan - WoL from S5 stops working - * @hw: pointer to the HW structure - * - * Steps to take when dropping from 1Gb/s (eg. link cable removal (LSC), - * LPLU, Gig disable, MDIC PHY reset): - * 1) Set Kumeran Near-end loopback - * 2) Clear Kumeran Near-end loopback - * Should only be called for ICH8[m] devices with any 1G Phy. - **/ -void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val; - u16 reg_data; - - if ((hw->mac.type != e1000_ich8lan) || (hw->phy.type == e1000_phy_ife)) - return; - - ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, - ®_data); - if (ret_val) - return; - reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK; - ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, - reg_data); - if (ret_val) - return; - reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK; - e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, reg_data); -} - -/** - * e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx - * @hw: pointer to the HW structure - * - * During S0 to Sx transition, it is possible the link remains at gig - * instead of negotiating to a lower speed. Before going to Sx, set - * 'Gig Disable' to force link speed negotiation to a lower speed based on - * the LPLU setting in the NVM or custom setting. For PCH and newer parts, - * the OEM bits PHY register (LED, GbE disable and LPLU configurations) also - * needs to be written. - * Parts that support (and are linked to a partner which support) EEE in - * 100Mbps should disable LPLU since 100Mbps w/ EEE requires less power - * than 10Mbps w/o EEE. - **/ -void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) -{ - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 phy_ctrl; - s32 ret_val; - - phy_ctrl = er32(PHY_CTRL); - phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE; - - if (hw->phy.type == e1000_phy_i217) { - u16 phy_reg, device_id = hw->adapter->pdev->device; - - if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) || - (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V)) { - u32 fextnvm6 = er32(FEXTNVM6); - - ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK); - } - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - if (!dev_spec->eee_disable) { - u16 eee_advert; - - ret_val = - e1000_read_emi_reg_locked(hw, - I217_EEE_ADVERTISEMENT, - &eee_advert); - if (ret_val) - goto release; - - /* Disable LPLU if both link partners support 100BaseT - * EEE and 100Full is advertised on both ends of the - * link. - */ - if ((eee_advert & I82579_EEE_100_SUPPORTED) && - (dev_spec->eee_lp_ability & - I82579_EEE_100_SUPPORTED) && - (hw->phy.autoneg_advertised & ADVERTISE_100_FULL)) - phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU | - E1000_PHY_CTRL_NOND0A_LPLU); - } - - /* For i217 Intel Rapid Start Technology support, - * when the system is going into Sx and no manageability engine - * is present, the driver must configure proxy to reset only on - * power good. LPI (Low Power Idle) state must also reset only - * on power good, as well as the MTA (Multicast table array). - * The SMBus release must also be disabled on LCD reset. - */ - if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { - /* Enable proxy to reset only on power good. */ - e1e_rphy_locked(hw, I217_PROXY_CTRL, &phy_reg); - phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE; - e1e_wphy_locked(hw, I217_PROXY_CTRL, phy_reg); - - /* Set bit enable LPI (EEE) to reset only on - * power good. - */ - e1e_rphy_locked(hw, I217_SxCTRL, &phy_reg); - phy_reg |= I217_SxCTRL_ENABLE_LPI_RESET; - e1e_wphy_locked(hw, I217_SxCTRL, phy_reg); - - /* Disable the SMB release on LCD reset. */ - e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg); - phy_reg &= ~I217_MEMPWR_DISABLE_SMB_RELEASE; - e1e_wphy_locked(hw, I217_MEMPWR, phy_reg); - } - - /* Enable MTA to reset for Intel Rapid Start Technology - * Support - */ - e1e_rphy_locked(hw, I217_CGFREG, &phy_reg); - phy_reg |= I217_CGFREG_ENABLE_MTA_RESET; - e1e_wphy_locked(hw, I217_CGFREG, phy_reg); - -release: - hw->phy.ops.release(hw); - } -out: - ew32(PHY_CTRL, phy_ctrl); - - if (hw->mac.type == e1000_ich8lan) - e1000e_gig_downshift_workaround_ich8lan(hw); - - if (hw->mac.type >= e1000_pchlan) { - e1000_oem_bits_config_ich8lan(hw, false); - - /* Reset PHY to activate OEM bits on 82577/8 */ - if (hw->mac.type == e1000_pchlan) - e1000e_phy_hw_reset_generic(hw); - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return; - e1000_write_smbus_addr(hw); - hw->phy.ops.release(hw); - } -} - -/** - * e1000_resume_workarounds_pchlan - workarounds needed during Sx->S0 - * @hw: pointer to the HW structure - * - * During Sx to S0 transitions on non-managed devices or managed devices - * on which PHY resets are not blocked, if the PHY registers cannot be - * accessed properly by the s/w toggle the LANPHYPC value to power cycle - * the PHY. - * On i217, setup Intel Rapid Start Technology. - **/ -void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) -{ - s32 ret_val; - - if (hw->mac.type < e1000_pch2lan) - return; - - ret_val = e1000_init_phy_workarounds_pchlan(hw); - if (ret_val) { - e_dbg("Failed to init PHY flow ret_val=%d\n", ret_val); - return; - } - - /* For i217 Intel Rapid Start Technology support when the system - * is transitioning from Sx and no manageability engine is present - * configure SMBus to restore on reset, disable proxy, and enable - * the reset on MTA (Multicast table array). - */ - if (hw->phy.type == e1000_phy_i217) { - u16 phy_reg; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) { - e_dbg("Failed to setup iRST\n"); - return; - } - - if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { - /* Restore clear on SMB if no manageability engine - * is present - */ - ret_val = e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg); - if (ret_val) - goto release; - phy_reg |= I217_MEMPWR_DISABLE_SMB_RELEASE; - e1e_wphy_locked(hw, I217_MEMPWR, phy_reg); - - /* Disable Proxy */ - e1e_wphy_locked(hw, I217_PROXY_CTRL, 0); - } - /* Enable reset on MTA */ - ret_val = e1e_rphy_locked(hw, I217_CGFREG, &phy_reg); - if (ret_val) - goto release; - phy_reg &= ~I217_CGFREG_ENABLE_MTA_RESET; - e1e_wphy_locked(hw, I217_CGFREG, phy_reg); -release: - if (ret_val) - e_dbg("Error %d in resume workarounds\n", ret_val); - hw->phy.ops.release(hw); - } -} - -/** - * e1000_cleanup_led_ich8lan - Restore the default LED operation - * @hw: pointer to the HW structure - * - * Return the LED back to the default configuration. - **/ -static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw) -{ - if (hw->phy.type == e1000_phy_ife) - return e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0); - - ew32(LEDCTL, hw->mac.ledctl_default); - return 0; -} - -/** - * e1000_led_on_ich8lan - Turn LEDs on - * @hw: pointer to the HW structure - * - * Turn on the LEDs. - **/ -static s32 e1000_led_on_ich8lan(struct e1000_hw *hw) -{ - if (hw->phy.type == e1000_phy_ife) - return e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, - (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON)); - - ew32(LEDCTL, hw->mac.ledctl_mode2); - return 0; -} - -/** - * e1000_led_off_ich8lan - Turn LEDs off - * @hw: pointer to the HW structure - * - * Turn off the LEDs. - **/ -static s32 e1000_led_off_ich8lan(struct e1000_hw *hw) -{ - if (hw->phy.type == e1000_phy_ife) - return e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, - (IFE_PSCL_PROBE_MODE | - IFE_PSCL_PROBE_LEDS_OFF)); - - ew32(LEDCTL, hw->mac.ledctl_mode1); - return 0; -} - -/** - * e1000_setup_led_pchlan - Configures SW controllable LED - * @hw: pointer to the HW structure - * - * This prepares the SW controllable LED for use. - **/ -static s32 e1000_setup_led_pchlan(struct e1000_hw *hw) -{ - return e1e_wphy(hw, HV_LED_CONFIG, (u16)hw->mac.ledctl_mode1); -} - -/** - * e1000_cleanup_led_pchlan - Restore the default LED operation - * @hw: pointer to the HW structure - * - * Return the LED back to the default configuration. - **/ -static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw) -{ - return e1e_wphy(hw, HV_LED_CONFIG, (u16)hw->mac.ledctl_default); -} - -/** - * e1000_led_on_pchlan - Turn LEDs on - * @hw: pointer to the HW structure - * - * Turn on the LEDs. - **/ -static s32 e1000_led_on_pchlan(struct e1000_hw *hw) -{ - u16 data = (u16)hw->mac.ledctl_mode2; - u32 i, led; - - /* If no link, then turn LED on by setting the invert bit - * for each LED that's mode is "link_up" in ledctl_mode2. - */ - if (!(er32(STATUS) & E1000_STATUS_LU)) { - for (i = 0; i < 3; i++) { - led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; - if ((led & E1000_PHY_LED0_MODE_MASK) != - E1000_LEDCTL_MODE_LINK_UP) - continue; - if (led & E1000_PHY_LED0_IVRT) - data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); - else - data |= (E1000_PHY_LED0_IVRT << (i * 5)); - } - } - - return e1e_wphy(hw, HV_LED_CONFIG, data); -} - -/** - * e1000_led_off_pchlan - Turn LEDs off - * @hw: pointer to the HW structure - * - * Turn off the LEDs. - **/ -static s32 e1000_led_off_pchlan(struct e1000_hw *hw) -{ - u16 data = (u16)hw->mac.ledctl_mode1; - u32 i, led; - - /* If no link, then turn LED off by clearing the invert bit - * for each LED that's mode is "link_up" in ledctl_mode1. - */ - if (!(er32(STATUS) & E1000_STATUS_LU)) { - for (i = 0; i < 3; i++) { - led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; - if ((led & E1000_PHY_LED0_MODE_MASK) != - E1000_LEDCTL_MODE_LINK_UP) - continue; - if (led & E1000_PHY_LED0_IVRT) - data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); - else - data |= (E1000_PHY_LED0_IVRT << (i * 5)); - } - } - - return e1e_wphy(hw, HV_LED_CONFIG, data); -} - -/** - * e1000_get_cfg_done_ich8lan - Read config done bit after Full or PHY reset - * @hw: pointer to the HW structure - * - * Read appropriate register for the config done bit for completion status - * and configure the PHY through s/w for EEPROM-less parts. - * - * NOTE: some silicon which is EEPROM-less will fail trying to read the - * config done bit, so only an error is logged and continues. If we were - * to return with error, EEPROM-less silicon would not be able to be reset - * or change link. - **/ -static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u32 bank = 0; - u32 status; - - e1000e_get_cfg_done_generic(hw); - - /* Wait for indication from h/w that it has completed basic config */ - if (hw->mac.type >= e1000_ich10lan) { - e1000_lan_init_done_ich8lan(hw); - } else { - ret_val = e1000e_get_auto_rd_done(hw); - if (ret_val) { - /* When auto config read does not complete, do not - * return with an error. This can happen in situations - * where there is no eeprom and prevents getting link. - */ - e_dbg("Auto Read Done did not complete\n"); - ret_val = 0; - } - } - - /* Clear PHY Reset Asserted bit */ - status = er32(STATUS); - if (status & E1000_STATUS_PHYRA) - ew32(STATUS, status & ~E1000_STATUS_PHYRA); - else - e_dbg("PHY Reset Asserted not set - needs delay\n"); - - /* If EEPROM is not marked present, init the IGP 3 PHY manually */ - if (hw->mac.type <= e1000_ich9lan) { - if (!(er32(EECD) & E1000_EECD_PRES) && - (hw->phy.type == e1000_phy_igp_3)) { - e1000e_phy_init_script_igp3(hw); - } - } else { - if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) { - /* Maybe we should do a basic PHY config */ - e_dbg("EEPROM not present\n"); - ret_val = -E1000_ERR_CONFIG; - } - } - - return ret_val; -} - -/** - * e1000_power_down_phy_copper_ich8lan - Remove link during PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, remove the link. - **/ -static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw) -{ - /* If the management interface is not enabled, then power down */ - if (!(hw->mac.ops.check_mng_mode(hw) || - hw->phy.ops.check_reset_block(hw))) - e1000_power_down_phy_copper(hw); -} - -/** - * e1000_clear_hw_cntrs_ich8lan - Clear statistical counters - * @hw: pointer to the HW structure - * - * Clears hardware counters specific to the silicon family and calls - * clear_hw_cntrs_generic to clear all general purpose counters. - **/ -static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) -{ - u16 phy_data; - s32 ret_val; - - e1000e_clear_hw_cntrs_base(hw); - - er32(ALGNERRC); - er32(RXERRC); - er32(TNCRS); - er32(CEXTERR); - er32(TSCTC); - er32(TSCTFC); - - er32(MGTPRC); - er32(MGTPDC); - er32(MGTPTC); - - er32(IAC); - er32(ICRXOC); - - /* Clear PHY statistics registers */ - if ((hw->phy.type == e1000_phy_82578) || - (hw->phy.type == e1000_phy_82579) || - (hw->phy.type == e1000_phy_i217) || - (hw->phy.type == e1000_phy_82577)) { - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return; - ret_val = hw->phy.ops.set_page(hw, - HV_STATS_PAGE << IGP_PAGE_SHIFT); - if (ret_val) - goto release; - hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data); -release: - hw->phy.ops.release(hw); - } -} - -static const struct e1000_mac_operations ich8_mac_ops = { - /* check_mng_mode dependent on mac type */ - .check_for_link = e1000_check_for_copper_link_ich8lan, - /* cleanup_led dependent on mac type */ - .clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan, - .get_bus_info = e1000_get_bus_info_ich8lan, - .set_lan_id = e1000_set_lan_id_single_port, - .get_link_up_info = e1000_get_link_up_info_ich8lan, - /* led_on dependent on mac type */ - /* led_off dependent on mac type */ - .update_mc_addr_list = e1000e_update_mc_addr_list_generic, - .reset_hw = e1000_reset_hw_ich8lan, - .init_hw = e1000_init_hw_ich8lan, - .setup_link = e1000_setup_link_ich8lan, - .setup_physical_interface = e1000_setup_copper_link_ich8lan, - /* id_led_init dependent on mac type */ - .config_collision_dist = e1000e_config_collision_dist_generic, - .rar_set = e1000e_rar_set_generic, -}; - -static const struct e1000_phy_operations ich8_phy_ops = { - .acquire = e1000_acquire_swflag_ich8lan, - .check_reset_block = e1000_check_reset_block_ich8lan, - .commit = NULL, - .get_cfg_done = e1000_get_cfg_done_ich8lan, - .get_cable_length = e1000e_get_cable_length_igp_2, - .read_reg = e1000e_read_phy_reg_igp, - .release = e1000_release_swflag_ich8lan, - .reset = e1000_phy_hw_reset_ich8lan, - .set_d0_lplu_state = e1000_set_d0_lplu_state_ich8lan, - .set_d3_lplu_state = e1000_set_d3_lplu_state_ich8lan, - .write_reg = e1000e_write_phy_reg_igp, -}; - -static const struct e1000_nvm_operations ich8_nvm_ops = { - .acquire = e1000_acquire_nvm_ich8lan, - .read = e1000_read_nvm_ich8lan, - .release = e1000_release_nvm_ich8lan, - .reload = e1000e_reload_nvm_generic, - .update = e1000_update_nvm_checksum_ich8lan, - .valid_led_default = e1000_valid_led_default_ich8lan, - .validate = e1000_validate_nvm_checksum_ich8lan, - .write = e1000_write_nvm_ich8lan, -}; - -const struct e1000_info e1000_ich8_info = { - .mac = e1000_ich8lan, - .flags = FLAG_HAS_WOL - | FLAG_IS_ICH - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_APME_IN_WUC, - .pba = 8, - .max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN, - .get_variants = e1000_get_variants_ich8lan, - .mac_ops = &ich8_mac_ops, - .phy_ops = &ich8_phy_ops, - .nvm_ops = &ich8_nvm_ops, -}; - -const struct e1000_info e1000_ich9_info = { - .mac = e1000_ich9lan, - .flags = FLAG_HAS_JUMBO_FRAMES - | FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_APME_IN_WUC, - .pba = 18, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_ich8lan, - .mac_ops = &ich8_mac_ops, - .phy_ops = &ich8_phy_ops, - .nvm_ops = &ich8_nvm_ops, -}; - -const struct e1000_info e1000_ich10_info = { - .mac = e1000_ich10lan, - .flags = FLAG_HAS_JUMBO_FRAMES - | FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_APME_IN_WUC, - .pba = 18, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_ich8lan, - .mac_ops = &ich8_mac_ops, - .phy_ops = &ich8_phy_ops, - .nvm_ops = &ich8_nvm_ops, -}; - -const struct e1000_info e1000_pch_info = { - .mac = e1000_pchlan, - .flags = FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_HAS_JUMBO_FRAMES - | FLAG_DISABLE_FC_PAUSE_TIME /* errata */ - | FLAG_APME_IN_WUC, - .flags2 = FLAG2_HAS_PHY_STATS, - .pba = 26, - .max_hw_frame_size = 4096, - .get_variants = e1000_get_variants_ich8lan, - .mac_ops = &ich8_mac_ops, - .phy_ops = &ich8_phy_ops, - .nvm_ops = &ich8_nvm_ops, -}; - -const struct e1000_info e1000_pch2_info = { - .mac = e1000_pch2lan, - .flags = FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_HAS_HW_TIMESTAMP - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_HAS_JUMBO_FRAMES - | FLAG_APME_IN_WUC, - .flags2 = FLAG2_HAS_PHY_STATS - | FLAG2_HAS_EEE, - .pba = 26, - .max_hw_frame_size = 9018, - .get_variants = e1000_get_variants_ich8lan, - .mac_ops = &ich8_mac_ops, - .phy_ops = &ich8_phy_ops, - .nvm_ops = &ich8_nvm_ops, -}; - -const struct e1000_info e1000_pch_lpt_info = { - .mac = e1000_pch_lpt, - .flags = FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_HAS_HW_TIMESTAMP - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_HAS_JUMBO_FRAMES - | FLAG_APME_IN_WUC, - .flags2 = FLAG2_HAS_PHY_STATS - | FLAG2_HAS_EEE, - .pba = 26, - .max_hw_frame_size = 9018, - .get_variants = e1000_get_variants_ich8lan, - .mac_ops = &ich8_mac_ops, - .phy_ops = &ich8_phy_ops, - .nvm_ops = &ich8_nvm_ops, -}; diff --git a/addons/e1000e/src/3.10.108/ich8lan.h b/addons/e1000e/src/3.10.108/ich8lan.h deleted file mode 100644 index 80034a2b..00000000 --- a/addons/e1000e/src/3.10.108/ich8lan.h +++ /dev/null @@ -1,265 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#ifndef _E1000E_ICH8LAN_H_ -#define _E1000E_ICH8LAN_H_ - -#define ICH_FLASH_GFPREG 0x0000 -#define ICH_FLASH_HSFSTS 0x0004 -#define ICH_FLASH_HSFCTL 0x0006 -#define ICH_FLASH_FADDR 0x0008 -#define ICH_FLASH_FDATA0 0x0010 -#define ICH_FLASH_PR0 0x0074 - -/* Requires up to 10 seconds when MNG might be accessing part. */ -#define ICH_FLASH_READ_COMMAND_TIMEOUT 10000000 -#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 10000000 -#define ICH_FLASH_ERASE_COMMAND_TIMEOUT 10000000 -#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF -#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 - -#define ICH_CYCLE_READ 0 -#define ICH_CYCLE_WRITE 2 -#define ICH_CYCLE_ERASE 3 - -#define FLASH_GFPREG_BASE_MASK 0x1FFF -#define FLASH_SECTOR_ADDR_SHIFT 12 - -#define ICH_FLASH_SEG_SIZE_256 256 -#define ICH_FLASH_SEG_SIZE_4K 4096 -#define ICH_FLASH_SEG_SIZE_8K 8192 -#define ICH_FLASH_SEG_SIZE_64K 65536 - -#define E1000_ICH_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI Reset */ -/* FW established a valid mode */ -#define E1000_ICH_FWSM_FW_VALID 0x00008000 -#define E1000_ICH_FWSM_PCIM2PCI 0x01000000 /* ME PCIm-to-PCI active */ -#define E1000_ICH_FWSM_PCIM2PCI_COUNT 2000 - -#define E1000_ICH_MNG_IAMT_MODE 0x2 - -#define E1000_FWSM_WLOCK_MAC_MASK 0x0380 -#define E1000_FWSM_WLOCK_MAC_SHIFT 7 - -/* Shared Receive Address Registers */ -#define E1000_SHRAL_PCH_LPT(_i) (0x05408 + ((_i) * 8)) -#define E1000_SHRAH_PCH_LPT(_i) (0x0540C + ((_i) * 8)) - -#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \ - (ID_LED_OFF1_OFF2 << 8) | \ - (ID_LED_OFF1_ON2 << 4) | \ - (ID_LED_DEF1_DEF2)) - -#define E1000_ICH_NVM_SIG_WORD 0x13 -#define E1000_ICH_NVM_SIG_MASK 0xC000 -#define E1000_ICH_NVM_VALID_SIG_MASK 0xC0 -#define E1000_ICH_NVM_SIG_VALUE 0x80 - -#define E1000_ICH8_LAN_INIT_TIMEOUT 1500 - -#define E1000_FEXTNVM_SW_CONFIG 1 -#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* different on ICH8M */ - -#define E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK 0x0C000000 -#define E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC 0x08000000 - -#define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7 -#define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7 -#define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3 - -#define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100 - -#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL - -#define E1000_ICH_RAR_ENTRIES 7 -#define E1000_PCH2_RAR_ENTRIES 5 /* RAR[0], SHRA[0-3] */ -#define E1000_PCH_LPT_RAR_ENTRIES 12 /* RAR[0], SHRA[0-10] */ - -#define PHY_PAGE_SHIFT 5 -#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \ - ((reg) & MAX_PHY_REG_ADDRESS)) -#define IGP3_KMRN_DIAG PHY_REG(770, 19) /* KMRN Diagnostic */ -#define IGP3_VR_CTRL PHY_REG(776, 18) /* Voltage Regulator Control */ - -#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 -#define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300 -#define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200 - -/* PHY Wakeup Registers and defines */ -#define BM_PORT_GEN_CFG PHY_REG(BM_PORT_CTRL_PAGE, 17) -#define BM_RCTL PHY_REG(BM_WUC_PAGE, 0) -#define BM_WUC PHY_REG(BM_WUC_PAGE, 1) -#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2) -#define BM_WUS PHY_REG(BM_WUC_PAGE, 3) -#define BM_RAR_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2))) -#define BM_RAR_M(_i) (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2))) -#define BM_RAR_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2))) -#define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2))) -#define BM_MTA(_i) (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1))) - -#define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */ -#define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */ -#define BM_RCTL_MO_SHIFT 3 /* Multicast Offset Shift */ -#define BM_RCTL_MO_MASK (3 << 3) /* Multicast Offset Mask */ -#define BM_RCTL_BAM 0x0020 /* Broadcast Accept Mode */ -#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */ -#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */ - -#define HV_LED_CONFIG PHY_REG(768, 30) /* LED Configuration */ -#define HV_MUX_DATA_CTRL PHY_REG(776, 16) -#define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 -#define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 -#define HV_STATS_PAGE 778 -/* Half-duplex collision counts */ -#define HV_SCC_UPPER PHY_REG(HV_STATS_PAGE, 16) /* Single Collision */ -#define HV_SCC_LOWER PHY_REG(HV_STATS_PAGE, 17) -#define HV_ECOL_UPPER PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. */ -#define HV_ECOL_LOWER PHY_REG(HV_STATS_PAGE, 19) -#define HV_MCC_UPPER PHY_REG(HV_STATS_PAGE, 20) /* Multiple Collision */ -#define HV_MCC_LOWER PHY_REG(HV_STATS_PAGE, 21) -#define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision */ -#define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24) -#define HV_COLC_UPPER PHY_REG(HV_STATS_PAGE, 25) /* Collision */ -#define HV_COLC_LOWER PHY_REG(HV_STATS_PAGE, 26) -#define HV_DC_UPPER PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */ -#define HV_DC_LOWER PHY_REG(HV_STATS_PAGE, 28) -#define HV_TNCRS_UPPER PHY_REG(HV_STATS_PAGE, 29) /* Tx with no CRS */ -#define HV_TNCRS_LOWER PHY_REG(HV_STATS_PAGE, 30) - -#define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */ - -#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ -#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ - -/* SMBus Control Phy Register */ -#define CV_SMB_CTRL PHY_REG(769, 23) -#define CV_SMB_CTRL_FORCE_SMBUS 0x0001 - -/* SMBus Address Phy Register */ -#define HV_SMB_ADDR PHY_REG(768, 26) -#define HV_SMB_ADDR_MASK 0x007F -#define HV_SMB_ADDR_PEC_EN 0x0200 -#define HV_SMB_ADDR_VALID 0x0080 -#define HV_SMB_ADDR_FREQ_MASK 0x1100 -#define HV_SMB_ADDR_FREQ_LOW_SHIFT 8 -#define HV_SMB_ADDR_FREQ_HIGH_SHIFT 12 - -/* Strapping Option Register - RO */ -#define E1000_STRAP 0x0000C -#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000 -#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17 -#define E1000_STRAP_SMT_FREQ_MASK 0x00003000 -#define E1000_STRAP_SMT_FREQ_SHIFT 12 - -/* OEM Bits Phy Register */ -#define HV_OEM_BITS PHY_REG(768, 25) -#define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */ -#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ -#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ - -/* KMRN Mode Control */ -#define HV_KMRN_MODE_CTRL PHY_REG(769, 16) -#define HV_KMRN_MDIO_SLOW 0x0400 - -/* KMRN FIFO Control and Status */ -#define HV_KMRN_FIFO_CTRLSTA PHY_REG(770, 16) -#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK 0x7000 -#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT 12 - -/* PHY Power Management Control */ -#define HV_PM_CTRL PHY_REG(770, 17) -#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 - -#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */ - -/* PHY Low Power Idle Control */ -#define I82579_LPI_CTRL PHY_REG(772, 20) -#define I82579_LPI_CTRL_100_ENABLE 0x2000 -#define I82579_LPI_CTRL_1000_ENABLE 0x4000 -#define I82579_LPI_CTRL_ENABLE_MASK 0x6000 -#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT 0x80 - -/* Extended Management Interface (EMI) Registers */ -#define I82579_EMI_ADDR 0x10 -#define I82579_EMI_DATA 0x11 -#define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */ -#define I82579_MSE_THRESHOLD 0x084F /* 82579 Mean Square Error Threshold */ -#define I82577_MSE_THRESHOLD 0x0887 /* 82577 Mean Square Error Threshold */ -#define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */ -#define I82579_RX_CONFIG 0x3412 /* Receive configuration */ -#define I82579_EEE_PCS_STATUS 0x182E /* IEEE MMD Register 3.1 >> 8 */ -#define I82579_EEE_CAPABILITY 0x0410 /* IEEE MMD Register 3.20 */ -#define I82579_EEE_ADVERTISEMENT 0x040E /* IEEE MMD Register 7.60 */ -#define I82579_EEE_LP_ABILITY 0x040F /* IEEE MMD Register 7.61 */ -#define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE */ -#define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE */ -#define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */ -#define I217_EEE_CAPABILITY 0x8000 /* IEEE MMD Register 3.20 */ -#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */ -#define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */ - -#define E1000_EEE_RX_LPI_RCVD 0x0400 /* Tx LP idle received */ -#define E1000_EEE_TX_LPI_RCVD 0x0800 /* Rx LP idle received */ - -/* Intel Rapid Start Technology Support */ -#define I217_PROXY_CTRL BM_PHY_REG(BM_WUC_PAGE, 70) -#define I217_PROXY_CTRL_AUTO_DISABLE 0x0080 -#define I217_SxCTRL PHY_REG(BM_PORT_CTRL_PAGE, 28) -#define I217_SxCTRL_ENABLE_LPI_RESET 0x1000 -#define I217_CGFREG PHY_REG(772, 29) -#define I217_CGFREG_ENABLE_MTA_RESET 0x0002 -#define I217_MEMPWR PHY_REG(772, 26) -#define I217_MEMPWR_DISABLE_SMB_RELEASE 0x0010 - -/* Receive Address Initial CRC Calculation */ -#define E1000_PCH_RAICC(_n) (0x05F50 + ((_n) * 4)) - -/* Latency Tolerance Reporting */ -#define E1000_LTRV 0x000F8 -#define E1000_LTRV_SCALE_MAX 5 -#define E1000_LTRV_SCALE_FACTOR 5 -#define E1000_LTRV_REQ_SHIFT 15 -#define E1000_LTRV_NOSNOOP_SHIFT 16 -#define E1000_LTRV_SEND (1 << 30) - -/* Proprietary Latency Tolerance Reporting PCI Capability */ -#define E1000_PCI_LTR_CAP_LPT 0xA8 - -void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw); -void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, - bool state); -void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); -void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); -void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw); -void e1000_resume_workarounds_pchlan(struct e1000_hw *hw); -s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); -void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw); -s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable); -s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data); -s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data); -#endif /* _E1000E_ICH8LAN_H_ */ diff --git a/addons/e1000e/src/3.10.108/mac.c b/addons/e1000e/src/3.10.108/mac.c deleted file mode 100644 index 2480c109..00000000 --- a/addons/e1000e/src/3.10.108/mac.c +++ /dev/null @@ -1,1801 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include "e1000.h" - -/** - * e1000e_get_bus_info_pcie - Get PCIe bus information - * @hw: pointer to the HW structure - * - * Determines and stores the system bus information for a particular - * network interface. The following bus information is determined and stored: - * bus speed, bus width, type (PCIe), and PCIe function. - **/ -s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - struct e1000_bus_info *bus = &hw->bus; - struct e1000_adapter *adapter = hw->adapter; - u16 pcie_link_status, cap_offset; - - cap_offset = adapter->pdev->pcie_cap; - if (!cap_offset) { - bus->width = e1000_bus_width_unknown; - } else { - pci_read_config_word(adapter->pdev, - cap_offset + PCIE_LINK_STATUS, - &pcie_link_status); - bus->width = (enum e1000_bus_width)((pcie_link_status & - PCIE_LINK_WIDTH_MASK) >> - PCIE_LINK_WIDTH_SHIFT); - } - - mac->ops.set_lan_id(hw); - - return 0; -} - -/** - * e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices - * - * @hw: pointer to the HW structure - * - * Determines the LAN function id by reading memory-mapped registers - * and swaps the port value if requested. - **/ -void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - u32 reg; - - /* The status register reports the correct function number - * for the device regardless of function swap state. - */ - reg = er32(STATUS); - bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; -} - -/** - * e1000_set_lan_id_single_port - Set LAN id for a single port device - * @hw: pointer to the HW structure - * - * Sets the LAN function id to zero for a single port device. - **/ -void e1000_set_lan_id_single_port(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - - bus->func = 0; -} - -/** - * e1000_clear_vfta_generic - Clear VLAN filter table - * @hw: pointer to the HW structure - * - * Clears the register array which contains the VLAN filter table by - * setting all the values to 0. - **/ -void e1000_clear_vfta_generic(struct e1000_hw *hw) -{ - u32 offset; - - for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); - e1e_flush(); - } -} - -/** - * e1000_write_vfta_generic - Write value to VLAN filter table - * @hw: pointer to the HW structure - * @offset: register offset in VLAN filter table - * @value: register value written to VLAN filter table - * - * Writes value at the given offset in the register array which stores - * the VLAN filter table. - **/ -void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) -{ - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); - e1e_flush(); -} - -/** - * e1000e_init_rx_addrs - Initialize receive address's - * @hw: pointer to the HW structure - * @rar_count: receive address registers - * - * Setup the receive address registers by setting the base receive address - * register to the devices MAC address and clearing all the other receive - * address registers to 0. - **/ -void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count) -{ - u32 i; - u8 mac_addr[ETH_ALEN] = { 0 }; - - /* Setup the receive address */ - e_dbg("Programming MAC Address into RAR[0]\n"); - - hw->mac.ops.rar_set(hw, hw->mac.addr, 0); - - /* Zero out the other (rar_entry_count - 1) receive addresses */ - e_dbg("Clearing RAR[1-%u]\n", rar_count - 1); - for (i = 1; i < rar_count; i++) - hw->mac.ops.rar_set(hw, mac_addr, i); -} - -/** - * e1000_check_alt_mac_addr_generic - Check for alternate MAC addr - * @hw: pointer to the HW structure - * - * Checks the nvm for an alternate MAC address. An alternate MAC address - * can be setup by pre-boot software and must be treated like a permanent - * address and must override the actual permanent MAC address. If an - * alternate MAC address is found it is programmed into RAR0, replacing - * the permanent address that was installed into RAR0 by the Si on reset. - * This function will return SUCCESS unless it encounters an error while - * reading the EEPROM. - **/ -s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) -{ - u32 i; - s32 ret_val; - u16 offset, nvm_alt_mac_addr_offset, nvm_data; - u8 alt_mac_addr[ETH_ALEN]; - - ret_val = e1000_read_nvm(hw, NVM_COMPAT, 1, &nvm_data); - if (ret_val) - return ret_val; - - /* not supported on 82573 */ - if (hw->mac.type == e1000_82573) - return 0; - - ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, - &nvm_alt_mac_addr_offset); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - if ((nvm_alt_mac_addr_offset == 0xFFFF) || - (nvm_alt_mac_addr_offset == 0x0000)) - /* There is no Alternate MAC Address */ - return 0; - - if (hw->bus.func == E1000_FUNC_1) - nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1; - for (i = 0; i < ETH_ALEN; i += 2) { - offset = nvm_alt_mac_addr_offset + (i >> 1); - ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - alt_mac_addr[i] = (u8)(nvm_data & 0xFF); - alt_mac_addr[i + 1] = (u8)(nvm_data >> 8); - } - - /* if multicast bit is set, the alternate address will not be used */ - if (is_multicast_ether_addr(alt_mac_addr)) { - e_dbg("Ignoring Alternate Mac Address with MC bit set\n"); - return 0; - } - - /* We have a valid alternate MAC address, and we want to treat it the - * same as the normal permanent MAC address stored by the HW into the - * RAR. Do this by mapping this address into RAR0. - */ - hw->mac.ops.rar_set(hw, alt_mac_addr, 0); - - return 0; -} - -/** - * e1000e_rar_set_generic - Set receive address register - * @hw: pointer to the HW structure - * @addr: pointer to the receive address - * @index: receive address array register - * - * Sets the receive address array register at index to the address passed - * in by addr. - **/ -void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) -{ - u32 rar_low, rar_high; - - /* HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian - */ - rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) | - ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); - - rar_high = ((u32)addr[4] | ((u32)addr[5] << 8)); - - /* If MAC address zero, no need to set the AV bit */ - if (rar_low || rar_high) - rar_high |= E1000_RAH_AV; - - /* Some bridges will combine consecutive 32-bit writes into - * a single burst write, which will malfunction on some parts. - * The flushes avoid this. - */ - ew32(RAL(index), rar_low); - e1e_flush(); - ew32(RAH(index), rar_high); - e1e_flush(); -} - -/** - * e1000_hash_mc_addr - Generate a multicast hash value - * @hw: pointer to the HW structure - * @mc_addr: pointer to a multicast address - * - * Generates a multicast address hash value which is used to determine - * the multicast filter table array address and new table value. - **/ -static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) -{ - u32 hash_value, hash_mask; - u8 bit_shift = 0; - - /* Register count multiplied by bits per register */ - hash_mask = (hw->mac.mta_reg_count * 32) - 1; - - /* For a mc_filter_type of 0, bit_shift is the number of left-shifts - * where 0xFF would still fall within the hash mask. - */ - while (hash_mask >> bit_shift != 0xFF) - bit_shift++; - - /* The portion of the address that is used for the hash table - * is determined by the mc_filter_type setting. - * The algorithm is such that there is a total of 8 bits of shifting. - * The bit_shift for a mc_filter_type of 0 represents the number of - * left-shifts where the MSB of mc_addr[5] would still fall within - * the hash_mask. Case 0 does this exactly. Since there are a total - * of 8 bits of shifting, then mc_addr[4] will shift right the - * remaining number of bits. Thus 8 - bit_shift. The rest of the - * cases are a variation of this algorithm...essentially raising the - * number of bits to shift mc_addr[5] left, while still keeping the - * 8-bit shifting total. - * - * For example, given the following Destination MAC Address and an - * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask), - * we can see that the bit_shift for case 0 is 4. These are the hash - * values resulting from each mc_filter_type... - * [0] [1] [2] [3] [4] [5] - * 01 AA 00 12 34 56 - * LSB MSB - * - * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563 - * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6 - * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163 - * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634 - */ - switch (hw->mac.mc_filter_type) { - default: - case 0: - break; - case 1: - bit_shift += 1; - break; - case 2: - bit_shift += 2; - break; - case 3: - bit_shift += 4; - break; - } - - hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | - (((u16)mc_addr[5]) << bit_shift))); - - return hash_value; -} - -/** - * e1000e_update_mc_addr_list_generic - Update Multicast addresses - * @hw: pointer to the HW structure - * @mc_addr_list: array of multicast addresses to program - * @mc_addr_count: number of multicast addresses to program - * - * Updates entire Multicast Table Array. - * The caller must have a packed mc_addr_list of multicast addresses. - **/ -void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count) -{ - u32 hash_value, hash_bit, hash_reg; - int i; - - /* clear mta_shadow */ - memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); - - /* update mta_shadow from mc_addr_list */ - for (i = 0; (u32)i < mc_addr_count; i++) { - hash_value = e1000_hash_mc_addr(hw, mc_addr_list); - - hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); - hash_bit = hash_value & 0x1F; - - hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); - mc_addr_list += (ETH_ALEN); - } - - /* replace the entire MTA table */ - for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); - e1e_flush(); -} - -/** - * e1000e_clear_hw_cntrs_base - Clear base hardware counters - * @hw: pointer to the HW structure - * - * Clears the base hardware counters by reading the counter registers. - **/ -void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw) -{ - er32(CRCERRS); - er32(SYMERRS); - er32(MPC); - er32(SCC); - er32(ECOL); - er32(MCC); - er32(LATECOL); - er32(COLC); - er32(DC); - er32(SEC); - er32(RLEC); - er32(XONRXC); - er32(XONTXC); - er32(XOFFRXC); - er32(XOFFTXC); - er32(FCRUC); - er32(GPRC); - er32(BPRC); - er32(MPRC); - er32(GPTC); - er32(GORCL); - er32(GORCH); - er32(GOTCL); - er32(GOTCH); - er32(RNBC); - er32(RUC); - er32(RFC); - er32(ROC); - er32(RJC); - er32(TORL); - er32(TORH); - er32(TOTL); - er32(TOTH); - er32(TPR); - er32(TPT); - er32(MPTC); - er32(BPTC); -} - -/** - * e1000e_check_for_copper_link - Check for link (Copper) - * @hw: pointer to the HW structure - * - * Checks to see of the link status of the hardware has changed. If a - * change in link status has been detected, then we read the PHY registers - * to get the current speed/duplex if link exists. - **/ -s32 e1000e_check_for_copper_link(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - bool link; - - /* We only want to go out to the PHY registers to see if Auto-Neg - * has completed and/or if our link status has changed. The - * get_link_status flag is set upon receiving a Link Status - * Change or Rx Sequence Error interrupt. - */ - if (!mac->get_link_status) - return 0; - - /* First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * of the PHY. - */ - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (!link) - return 0; /* No link detected */ - - mac->get_link_status = false; - - /* Check if there was DownShift, must be checked - * immediately after link-up - */ - e1000e_check_downshift(hw); - - /* If we are forcing speed/duplex, then we simply return since - * we have already determined whether we have link or not. - */ - if (!mac->autoneg) - return -E1000_ERR_CONFIG; - - /* Auto-Neg is enabled. Auto Speed Detection takes care - * of MAC speed/duplex configuration. So we only need to - * configure Collision Distance in the MAC. - */ - mac->ops.config_collision_dist(hw); - - /* Configure Flow Control now that Auto-Neg has completed. - * First, we need to restore the desired flow control - * settings because we may have had to re-autoneg with a - * different link partner. - */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) - e_dbg("Error configuring flow control\n"); - - return ret_val; -} - -/** - * e1000e_check_for_fiber_link - Check for link (Fiber) - * @hw: pointer to the HW structure - * - * Checks for link up on the hardware. If link is not up and we have - * a signal, then we need to force link up. - **/ -s32 e1000e_check_for_fiber_link(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw; - u32 ctrl; - u32 status; - s32 ret_val; - - ctrl = er32(CTRL); - status = er32(STATUS); - rxcw = er32(RXCW); - - /* If we don't have link (auto-negotiation failed or link partner - * cannot auto-negotiate), the cable is plugged in (we have signal), - * and our link partner is not trying to auto-negotiate with us (we - * are receiving idles or data), we need to force link up. We also - * need to give auto-negotiation time to complete, in case the cable - * was just plugged in. The autoneg_failed flag does this. - */ - /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((ctrl & E1000_CTRL_SWDPIN1) && !(status & E1000_STATUS_LU) && - !(rxcw & E1000_RXCW_C)) { - if (!mac->autoneg_failed) { - mac->autoneg_failed = true; - return 0; - } - e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); - - /* Disable auto-negotiation in the TXCW register */ - ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = er32(CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - ew32(CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error configuring flow control\n"); - return ret_val; - } - } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* If we are forcing link and we are receiving /C/ ordered - * sets, re-enable auto-negotiation in the TXCW register - * and disable forced link in the Device Control register - * in an attempt to auto-negotiate with our link partner. - */ - e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); - ew32(TXCW, mac->txcw); - ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - - mac->serdes_has_link = true; - } - - return 0; -} - -/** - * e1000e_check_for_serdes_link - Check for link (Serdes) - * @hw: pointer to the HW structure - * - * Checks for link up on the hardware. If link is not up and we have - * a signal, then we need to force link up. - **/ -s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw; - u32 ctrl; - u32 status; - s32 ret_val; - - ctrl = er32(CTRL); - status = er32(STATUS); - rxcw = er32(RXCW); - - /* If we don't have link (auto-negotiation failed or link partner - * cannot auto-negotiate), and our link partner is not trying to - * auto-negotiate with us (we are receiving idles or data), - * we need to force link up. We also need to give auto-negotiation - * time to complete. - */ - /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if (!(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) { - if (!mac->autoneg_failed) { - mac->autoneg_failed = true; - return 0; - } - e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); - - /* Disable auto-negotiation in the TXCW register */ - ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = er32(CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - ew32(CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error configuring flow control\n"); - return ret_val; - } - } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* If we are forcing link and we are receiving /C/ ordered - * sets, re-enable auto-negotiation in the TXCW register - * and disable forced link in the Device Control register - * in an attempt to auto-negotiate with our link partner. - */ - e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); - ew32(TXCW, mac->txcw); - ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - - mac->serdes_has_link = true; - } else if (!(E1000_TXCW_ANE & er32(TXCW))) { - /* If we force link for non-auto-negotiation switch, check - * link status based on MAC synchronization for internal - * serdes media type. - */ - /* SYNCH bit and IV bit are sticky. */ - usleep_range(10, 20); - rxcw = er32(RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - mac->serdes_has_link = true; - e_dbg("SERDES: Link up - forced.\n"); - } - } else { - mac->serdes_has_link = false; - e_dbg("SERDES: Link down - force failed.\n"); - } - } - - if (E1000_TXCW_ANE & er32(TXCW)) { - status = er32(STATUS); - if (status & E1000_STATUS_LU) { - /* SYNCH bit and IV bit are sticky, so reread rxcw. */ - usleep_range(10, 20); - rxcw = er32(RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - mac->serdes_has_link = true; - e_dbg("SERDES: Link up - autoneg completed successfully.\n"); - } else { - mac->serdes_has_link = false; - e_dbg("SERDES: Link down - invalid codewords detected in autoneg.\n"); - } - } else { - mac->serdes_has_link = false; - e_dbg("SERDES: Link down - no sync.\n"); - } - } else { - mac->serdes_has_link = false; - e_dbg("SERDES: Link down - autoneg failed\n"); - } - } - - return 0; -} - -/** - * e1000_set_default_fc_generic - Set flow control default values - * @hw: pointer to the HW structure - * - * Read the EEPROM for the default values for flow control and store the - * values. - **/ -static s32 e1000_set_default_fc_generic(struct e1000_hw *hw) -{ - s32 ret_val; - u16 nvm_data; - - /* Read and store word 0x0F of the EEPROM. This word contains bits - * that determine the hardware's default PAUSE (flow control) mode, - * a bit that determines whether the HW defaults to enabling or - * disabling auto-negotiation, and the direction of the - * SW defined pins. If there is no SW over-ride of the flow - * control setting, then the variable hw->fc will - * be initialized based on a value in the EEPROM. - */ - ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); - - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - if (!(nvm_data & NVM_WORD0F_PAUSE_MASK)) - hw->fc.requested_mode = e1000_fc_none; - else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == NVM_WORD0F_ASM_DIR) - hw->fc.requested_mode = e1000_fc_tx_pause; - else - hw->fc.requested_mode = e1000_fc_full; - - return 0; -} - -/** - * e1000e_setup_link_generic - Setup flow control and link settings - * @hw: pointer to the HW structure - * - * Determines which flow control settings to use, then configures flow - * control. Calls the appropriate media-specific link configuration - * function. Assuming the adapter has a valid link partner, a valid link - * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. - **/ -s32 e1000e_setup_link_generic(struct e1000_hw *hw) -{ - s32 ret_val; - - /* In the case of the phy reset being blocked, we already have a link. - * We do not need to set it up again. - */ - if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) - return 0; - - /* If requested flow control is set to default, set flow control - * based on the EEPROM flow control settings. - */ - if (hw->fc.requested_mode == e1000_fc_default) { - ret_val = e1000_set_default_fc_generic(hw); - if (ret_val) - return ret_val; - } - - /* Save off the requested flow control mode for use later. Depending - * on the link partner's capabilities, we may or may not use this mode. - */ - hw->fc.current_mode = hw->fc.requested_mode; - - e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode); - - /* Call the necessary media_type subroutine to configure the link. */ - ret_val = hw->mac.ops.setup_physical_interface(hw); - if (ret_val) - return ret_val; - - /* Initialize the flow control address, type, and PAUSE timer - * registers to their default values. This is done even if flow - * control is disabled, because it does not hurt anything to - * initialize these registers. - */ - e_dbg("Initializing the Flow Control address, type and timer regs\n"); - ew32(FCT, FLOW_CONTROL_TYPE); - ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH); - ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW); - - ew32(FCTTV, hw->fc.pause_time); - - return e1000e_set_fc_watermarks(hw); -} - -/** - * e1000_commit_fc_settings_generic - Configure flow control - * @hw: pointer to the HW structure - * - * Write the flow control settings to the Transmit Config Word Register (TXCW) - * base on the flow control settings in e1000_mac_info. - **/ -static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 txcw; - - /* Check for a software override of the flow control settings, and - * setup the device accordingly. If auto-negotiation is enabled, then - * software will have to set the "PAUSE" bits to the correct value in - * the Transmit Config Word Register (TXCW) and re-start auto- - * negotiation. However, if auto-negotiation is disabled, then - * software will have to manually configure the two flow control enable - * bits in the CTRL register. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames, - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but we - * do not support receiving pause frames). - * 3: Both Rx and Tx flow control (symmetric) are enabled. - */ - switch (hw->fc.current_mode) { - case e1000_fc_none: - /* Flow control completely disabled by a software over-ride. */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); - break; - case e1000_fc_rx_pause: - /* Rx Flow control is enabled and Tx Flow control is disabled - * by a software over-ride. Since there really isn't a way to - * advertise that we are capable of Rx Pause ONLY, we will - * advertise that we support both symmetric and asymmetric Rx - * PAUSE. Later, we will disable the adapter's ability to send - * PAUSE frames. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - case e1000_fc_tx_pause: - /* Tx Flow control is enabled, and Rx Flow control is disabled, - * by a software over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); - break; - case e1000_fc_full: - /* Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - break; - } - - ew32(TXCW, txcw); - mac->txcw = txcw; - - return 0; -} - -/** - * e1000_poll_fiber_serdes_link_generic - Poll for link up - * @hw: pointer to the HW structure - * - * Polls for link up by reading the status register, if link fails to come - * up with auto-negotiation, then the link is forced if a signal is detected. - **/ -static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 i, status; - s32 ret_val; - - /* If we have a signal (the cable is plugged in, or assumed true for - * serdes media) then poll for a "Link-Up" indication in the Device - * Status Register. Time-out if a link isn't seen in 500 milliseconds - * seconds (Auto-negotiation should complete in less than 500 - * milliseconds even if the other end is doing it in SW). - */ - for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { - usleep_range(10000, 20000); - status = er32(STATUS); - if (status & E1000_STATUS_LU) - break; - } - if (i == FIBER_LINK_UP_LIMIT) { - e_dbg("Never got a valid link from auto-neg!!!\n"); - mac->autoneg_failed = true; - /* AutoNeg failed to achieve a link, so we'll call - * mac->check_for_link. This routine will force the - * link up if we detect a signal. This will allow us to - * communicate with non-autonegotiating link partners. - */ - ret_val = mac->ops.check_for_link(hw); - if (ret_val) { - e_dbg("Error while checking for link\n"); - return ret_val; - } - mac->autoneg_failed = false; - } else { - mac->autoneg_failed = false; - e_dbg("Valid Link Found\n"); - } - - return 0; -} - -/** - * e1000e_setup_fiber_serdes_link - Setup link for fiber/serdes - * @hw: pointer to the HW structure - * - * Configures collision distance and flow control for fiber and serdes - * links. Upon successful setup, poll for link. - **/ -s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - - ctrl = er32(CTRL); - - /* Take the link out of reset */ - ctrl &= ~E1000_CTRL_LRST; - - hw->mac.ops.config_collision_dist(hw); - - ret_val = e1000_commit_fc_settings_generic(hw); - if (ret_val) - return ret_val; - - /* Since auto-negotiation is enabled, take the link out of reset (the - * link will be in reset, because we previously reset the chip). This - * will restart auto-negotiation. If auto-negotiation is successful - * then the link-up status bit will be set and the flow control enable - * bits (RFCE and TFCE) will be set according to their negotiated value. - */ - e_dbg("Auto-negotiation enabled\n"); - - ew32(CTRL, ctrl); - e1e_flush(); - usleep_range(1000, 2000); - - /* For these adapters, the SW definable pin 1 is set when the optics - * detect a signal. If we have a signal, then poll for a "Link-Up" - * indication. - */ - if (hw->phy.media_type == e1000_media_type_internal_serdes || - (er32(CTRL) & E1000_CTRL_SWDPIN1)) { - ret_val = e1000_poll_fiber_serdes_link_generic(hw); - } else { - e_dbg("No signal detected\n"); - } - - return ret_val; -} - -/** - * e1000e_config_collision_dist_generic - Configure collision distance - * @hw: pointer to the HW structure - * - * Configures the collision distance to the default value and is used - * during link setup. - **/ -void e1000e_config_collision_dist_generic(struct e1000_hw *hw) -{ - u32 tctl; - - tctl = er32(TCTL); - - tctl &= ~E1000_TCTL_COLD; - tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; - - ew32(TCTL, tctl); - e1e_flush(); -} - -/** - * e1000e_set_fc_watermarks - Set flow control high/low watermarks - * @hw: pointer to the HW structure - * - * Sets the flow control high/low threshold (watermark) registers. If - * flow control XON frame transmission is enabled, then set XON frame - * transmission as well. - **/ -s32 e1000e_set_fc_watermarks(struct e1000_hw *hw) -{ - u32 fcrtl = 0, fcrth = 0; - - /* Set the flow control receive threshold registers. Normally, - * these registers will be set to a default threshold that may be - * adjusted later by the driver's runtime code. However, if the - * ability to transmit pause frames is not enabled, then these - * registers will be set to 0. - */ - if (hw->fc.current_mode & e1000_fc_tx_pause) { - /* We need to set up the Receive Threshold high and low water - * marks as well as (optionally) enabling the transmission of - * XON frames. - */ - fcrtl = hw->fc.low_water; - if (hw->fc.send_xon) - fcrtl |= E1000_FCRTL_XONE; - - fcrth = hw->fc.high_water; - } - ew32(FCRTL, fcrtl); - ew32(FCRTH, fcrth); - - return 0; -} - -/** - * e1000e_force_mac_fc - Force the MAC's flow control settings - * @hw: pointer to the HW structure - * - * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the - * device control register to reflect the adapter settings. TFCE and RFCE - * need to be explicitly set by software when a copper PHY is used because - * autonegotiation is managed by the PHY rather than the MAC. Software must - * also configure these bits when link is forced on a fiber connection. - **/ -s32 e1000e_force_mac_fc(struct e1000_hw *hw) -{ - u32 ctrl; - - ctrl = er32(CTRL); - - /* Because we didn't get link via the internal auto-negotiation - * mechanism (we either forced link or we got link via PHY - * auto-neg), we have to manually enable/disable transmit an - * receive flow control. - * - * The "Case" statement below enables/disable flow control - * according to the "hw->fc.current_mode" parameter. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause - * frames but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * frames but we do not receive pause frames). - * 3: Both Rx and Tx flow control (symmetric) is enabled. - * other: No other values should be possible at this point. - */ - e_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode); - - switch (hw->fc.current_mode) { - case e1000_fc_none: - ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); - break; - case e1000_fc_rx_pause: - ctrl &= (~E1000_CTRL_TFCE); - ctrl |= E1000_CTRL_RFCE; - break; - case e1000_fc_tx_pause: - ctrl &= (~E1000_CTRL_RFCE); - ctrl |= E1000_CTRL_TFCE; - break; - case e1000_fc_full: - ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - } - - ew32(CTRL, ctrl); - - return 0; -} - -/** - * e1000e_config_fc_after_link_up - Configures flow control after link - * @hw: pointer to the HW structure - * - * Checks the status of auto-negotiation after link up to ensure that the - * speed and duplex were not forced. If the link needed to be forced, then - * flow control needs to be forced also. If auto-negotiation is enabled - * and did not fail, then we configure flow control based on our link - * partner. - **/ -s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = 0; - u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg; - u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; - u16 speed, duplex; - - /* Check for the case where we have fiber media and auto-neg failed - * so we had to force link. In this case, we need to force the - * configuration of the MAC to match the "fc" parameter. - */ - if (mac->autoneg_failed) { - if (hw->phy.media_type == e1000_media_type_fiber || - hw->phy.media_type == e1000_media_type_internal_serdes) - ret_val = e1000e_force_mac_fc(hw); - } else { - if (hw->phy.media_type == e1000_media_type_copper) - ret_val = e1000e_force_mac_fc(hw); - } - - if (ret_val) { - e_dbg("Error forcing flow control settings\n"); - return ret_val; - } - - /* Check for the case where we have copper media and auto-neg is - * enabled. In this case, we need to check and see if Auto-Neg - * has completed, and if so, how the PHY and link partner has - * flow control configured. - */ - if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { - /* Read the MII Status Register and check to see if AutoNeg - * has completed. We read this twice because this reg has - * some "sticky" (latched) bits. - */ - ret_val = e1e_rphy(hw, MII_BMSR, &mii_status_reg); - if (ret_val) - return ret_val; - ret_val = e1e_rphy(hw, MII_BMSR, &mii_status_reg); - if (ret_val) - return ret_val; - - if (!(mii_status_reg & BMSR_ANEGCOMPLETE)) { - e_dbg("Copper PHY and Auto Neg has not completed.\n"); - return ret_val; - } - - /* The AutoNeg process has completed, so we now need to - * read both the Auto Negotiation Advertisement - * Register (Address 4) and the Auto_Negotiation Base - * Page Ability Register (Address 5) to determine how - * flow control was negotiated. - */ - ret_val = e1e_rphy(hw, MII_ADVERTISE, &mii_nway_adv_reg); - if (ret_val) - return ret_val; - ret_val = e1e_rphy(hw, MII_LPA, &mii_nway_lp_ability_reg); - if (ret_val) - return ret_val; - - /* Two bits in the Auto Negotiation Advertisement Register - * (Address 4) and two bits in the Auto Negotiation Base - * Page Ability Register (Address 5) determine flow control - * for both the PHY and the link partner. The following - * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, - * 1999, describes these PAUSE resolution bits and how flow - * control is determined based upon these settings. - * NOTE: DC = Don't Care - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution - *-------|---------|-------|---------|-------------------- - * 0 | 0 | DC | DC | e1000_fc_none - * 0 | 1 | 0 | DC | e1000_fc_none - * 0 | 1 | 1 | 0 | e1000_fc_none - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - * 1 | 0 | 0 | DC | e1000_fc_none - * 1 | DC | 1 | DC | e1000_fc_full - * 1 | 1 | 0 | 0 | e1000_fc_none - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - * - * Are both PAUSE bits set to 1? If so, this implies - * Symmetric Flow Control is enabled at both ends. The - * ASM_DIR bits are irrelevant per the spec. - * - * For Symmetric Flow Control: - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | DC | 1 | DC | E1000_fc_full - * - */ - if ((mii_nway_adv_reg & ADVERTISE_PAUSE_CAP) && - (mii_nway_lp_ability_reg & LPA_PAUSE_CAP)) { - /* Now we need to check if the user selected Rx ONLY - * of pause frames. In this case, we had to advertise - * FULL flow control because we could not advertise Rx - * ONLY. Hence, we must now check to see if we need to - * turn OFF the TRANSMISSION of PAUSE frames. - */ - if (hw->fc.requested_mode == e1000_fc_full) { - hw->fc.current_mode = e1000_fc_full; - e_dbg("Flow Control = FULL.\n"); - } else { - hw->fc.current_mode = e1000_fc_rx_pause; - e_dbg("Flow Control = Rx PAUSE frames only.\n"); - } - } - /* For receiving PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - */ - else if (!(mii_nway_adv_reg & ADVERTISE_PAUSE_CAP) && - (mii_nway_adv_reg & ADVERTISE_PAUSE_ASYM) && - (mii_nway_lp_ability_reg & LPA_PAUSE_CAP) && - (mii_nway_lp_ability_reg & LPA_PAUSE_ASYM)) { - hw->fc.current_mode = e1000_fc_tx_pause; - e_dbg("Flow Control = Tx PAUSE frames only.\n"); - } - /* For transmitting PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - */ - else if ((mii_nway_adv_reg & ADVERTISE_PAUSE_CAP) && - (mii_nway_adv_reg & ADVERTISE_PAUSE_ASYM) && - !(mii_nway_lp_ability_reg & LPA_PAUSE_CAP) && - (mii_nway_lp_ability_reg & LPA_PAUSE_ASYM)) { - hw->fc.current_mode = e1000_fc_rx_pause; - e_dbg("Flow Control = Rx PAUSE frames only.\n"); - } else { - /* Per the IEEE spec, at this point flow control - * should be disabled. - */ - hw->fc.current_mode = e1000_fc_none; - e_dbg("Flow Control = NONE.\n"); - } - - /* Now we need to do one last check... If we auto- - * negotiated to HALF DUPLEX, flow control should not be - * enabled per IEEE 802.3 spec. - */ - ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); - if (ret_val) { - e_dbg("Error getting link speed and duplex\n"); - return ret_val; - } - - if (duplex == HALF_DUPLEX) - hw->fc.current_mode = e1000_fc_none; - - /* Now we call a subroutine to actually force the MAC - * controller to use the correct flow control settings. - */ - ret_val = e1000e_force_mac_fc(hw); - if (ret_val) { - e_dbg("Error forcing flow control settings\n"); - return ret_val; - } - } - - /* Check for the case where we have SerDes media and auto-neg is - * enabled. In this case, we need to check and see if Auto-Neg - * has completed, and if so, how the PHY and link partner has - * flow control configured. - */ - if ((hw->phy.media_type == e1000_media_type_internal_serdes) && - mac->autoneg) { - /* Read the PCS_LSTS and check to see if AutoNeg - * has completed. - */ - pcs_status_reg = er32(PCS_LSTAT); - - if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) { - e_dbg("PCS Auto Neg has not completed.\n"); - return ret_val; - } - - /* The AutoNeg process has completed, so we now need to - * read both the Auto Negotiation Advertisement - * Register (PCS_ANADV) and the Auto_Negotiation Base - * Page Ability Register (PCS_LPAB) to determine how - * flow control was negotiated. - */ - pcs_adv_reg = er32(PCS_ANADV); - pcs_lp_ability_reg = er32(PCS_LPAB); - - /* Two bits in the Auto Negotiation Advertisement Register - * (PCS_ANADV) and two bits in the Auto Negotiation Base - * Page Ability Register (PCS_LPAB) determine flow control - * for both the PHY and the link partner. The following - * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, - * 1999, describes these PAUSE resolution bits and how flow - * control is determined based upon these settings. - * NOTE: DC = Don't Care - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution - *-------|---------|-------|---------|-------------------- - * 0 | 0 | DC | DC | e1000_fc_none - * 0 | 1 | 0 | DC | e1000_fc_none - * 0 | 1 | 1 | 0 | e1000_fc_none - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - * 1 | 0 | 0 | DC | e1000_fc_none - * 1 | DC | 1 | DC | e1000_fc_full - * 1 | 1 | 0 | 0 | e1000_fc_none - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - * - * Are both PAUSE bits set to 1? If so, this implies - * Symmetric Flow Control is enabled at both ends. The - * ASM_DIR bits are irrelevant per the spec. - * - * For Symmetric Flow Control: - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | DC | 1 | DC | e1000_fc_full - * - */ - if ((pcs_adv_reg & E1000_TXCW_PAUSE) && - (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) { - /* Now we need to check if the user selected Rx ONLY - * of pause frames. In this case, we had to advertise - * FULL flow control because we could not advertise Rx - * ONLY. Hence, we must now check to see if we need to - * turn OFF the TRANSMISSION of PAUSE frames. - */ - if (hw->fc.requested_mode == e1000_fc_full) { - hw->fc.current_mode = e1000_fc_full; - e_dbg("Flow Control = FULL.\n"); - } else { - hw->fc.current_mode = e1000_fc_rx_pause; - e_dbg("Flow Control = Rx PAUSE frames only.\n"); - } - } - /* For receiving PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - */ - else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) && - (pcs_adv_reg & E1000_TXCW_ASM_DIR) && - (pcs_lp_ability_reg & E1000_TXCW_PAUSE) && - (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { - hw->fc.current_mode = e1000_fc_tx_pause; - e_dbg("Flow Control = Tx PAUSE frames only.\n"); - } - /* For transmitting PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - */ - else if ((pcs_adv_reg & E1000_TXCW_PAUSE) && - (pcs_adv_reg & E1000_TXCW_ASM_DIR) && - !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) && - (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { - hw->fc.current_mode = e1000_fc_rx_pause; - e_dbg("Flow Control = Rx PAUSE frames only.\n"); - } else { - /* Per the IEEE spec, at this point flow control - * should be disabled. - */ - hw->fc.current_mode = e1000_fc_none; - e_dbg("Flow Control = NONE.\n"); - } - - /* Now we call a subroutine to actually force the MAC - * controller to use the correct flow control settings. - */ - pcs_ctrl_reg = er32(PCS_LCTL); - pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL; - ew32(PCS_LCTL, pcs_ctrl_reg); - - ret_val = e1000e_force_mac_fc(hw); - if (ret_val) { - e_dbg("Error forcing flow control settings\n"); - return ret_val; - } - } - - return 0; -} - -/** - * e1000e_get_speed_and_duplex_copper - Retrieve current speed/duplex - * @hw: pointer to the HW structure - * @speed: stores the current speed - * @duplex: stores the current duplex - * - * Read the status register for the current speed/duplex and store the current - * speed and duplex for copper connections. - **/ -s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, - u16 *duplex) -{ - u32 status; - - status = er32(STATUS); - if (status & E1000_STATUS_SPEED_1000) - *speed = SPEED_1000; - else if (status & E1000_STATUS_SPEED_100) - *speed = SPEED_100; - else - *speed = SPEED_10; - - if (status & E1000_STATUS_FD) - *duplex = FULL_DUPLEX; - else - *duplex = HALF_DUPLEX; - - e_dbg("%u Mbps, %s Duplex\n", - *speed == SPEED_1000 ? 1000 : *speed == SPEED_100 ? 100 : 10, - *duplex == FULL_DUPLEX ? "Full" : "Half"); - - return 0; -} - -/** - * e1000e_get_speed_and_duplex_fiber_serdes - Retrieve current speed/duplex - * @hw: pointer to the HW structure - * @speed: stores the current speed - * @duplex: stores the current duplex - * - * Sets the speed and duplex to gigabit full duplex (the only possible option) - * for fiber/serdes links. - **/ -s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw __always_unused - *hw, u16 *speed, u16 *duplex) -{ - *speed = SPEED_1000; - *duplex = FULL_DUPLEX; - - return 0; -} - -/** - * e1000e_get_hw_semaphore - Acquire hardware semaphore - * @hw: pointer to the HW structure - * - * Acquire the HW semaphore to access the PHY or NVM - **/ -s32 e1000e_get_hw_semaphore(struct e1000_hw *hw) -{ - u32 swsm; - s32 timeout = hw->nvm.word_size + 1; - s32 i = 0; - - /* Get the SW semaphore */ - while (i < timeout) { - swsm = er32(SWSM); - if (!(swsm & E1000_SWSM_SMBI)) - break; - - usleep_range(50, 100); - i++; - } - - if (i == timeout) { - e_dbg("Driver can't access device - SMBI bit is set.\n"); - return -E1000_ERR_NVM; - } - - /* Get the FW semaphore. */ - for (i = 0; i < timeout; i++) { - swsm = er32(SWSM); - ew32(SWSM, swsm | E1000_SWSM_SWESMBI); - - /* Semaphore acquired if bit latched */ - if (er32(SWSM) & E1000_SWSM_SWESMBI) - break; - - usleep_range(50, 100); - } - - if (i == timeout) { - /* Release semaphores */ - e1000e_put_hw_semaphore(hw); - e_dbg("Driver can't access the NVM\n"); - return -E1000_ERR_NVM; - } - - return 0; -} - -/** - * e1000e_put_hw_semaphore - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used to access the PHY or NVM - **/ -void e1000e_put_hw_semaphore(struct e1000_hw *hw) -{ - u32 swsm; - - swsm = er32(SWSM); - swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); - ew32(SWSM, swsm); -} - -/** - * e1000e_get_auto_rd_done - Check for auto read completion - * @hw: pointer to the HW structure - * - * Check EEPROM for Auto Read done bit. - **/ -s32 e1000e_get_auto_rd_done(struct e1000_hw *hw) -{ - s32 i = 0; - - while (i < AUTO_READ_DONE_TIMEOUT) { - if (er32(EECD) & E1000_EECD_AUTO_RD) - break; - usleep_range(1000, 2000); - i++; - } - - if (i == AUTO_READ_DONE_TIMEOUT) { - e_dbg("Auto read by HW from NVM has not completed.\n"); - return -E1000_ERR_RESET; - } - - return 0; -} - -/** - * e1000e_valid_led_default - Verify a valid default LED config - * @hw: pointer to the HW structure - * @data: pointer to the NVM (EEPROM) - * - * Read the EEPROM for the current default LED configuration. If the - * LED configuration is not valid, set to a valid LED configuration. - **/ -s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data) -{ - s32 ret_val; - - ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) - *data = ID_LED_DEFAULT; - - return 0; -} - -/** - * e1000e_id_led_init_generic - - * @hw: pointer to the HW structure - * - **/ -s32 e1000e_id_led_init_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - const u32 ledctl_mask = 0x000000FF; - const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; - const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; - u16 data, i, temp; - const u16 led_mask = 0x0F; - - ret_val = hw->nvm.ops.valid_led_default(hw, &data); - if (ret_val) - return ret_val; - - mac->ledctl_default = er32(LEDCTL); - mac->ledctl_mode1 = mac->ledctl_default; - mac->ledctl_mode2 = mac->ledctl_default; - - for (i = 0; i < 4; i++) { - temp = (data >> (i << 2)) & led_mask; - switch (temp) { - case ID_LED_ON1_DEF2: - case ID_LED_ON1_ON2: - case ID_LED_ON1_OFF2: - mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode1 |= ledctl_on << (i << 3); - break; - case ID_LED_OFF1_DEF2: - case ID_LED_OFF1_ON2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode1 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - switch (temp) { - case ID_LED_DEF1_ON2: - case ID_LED_ON1_ON2: - case ID_LED_OFF1_ON2: - mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode2 |= ledctl_on << (i << 3); - break; - case ID_LED_DEF1_OFF2: - case ID_LED_ON1_OFF2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode2 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - } - - return 0; -} - -/** - * e1000e_setup_led_generic - Configures SW controllable LED - * @hw: pointer to the HW structure - * - * This prepares the SW controllable LED for use and saves the current state - * of the LED so it can be later restored. - **/ -s32 e1000e_setup_led_generic(struct e1000_hw *hw) -{ - u32 ledctl; - - if (hw->mac.ops.setup_led != e1000e_setup_led_generic) - return -E1000_ERR_CONFIG; - - if (hw->phy.media_type == e1000_media_type_fiber) { - ledctl = er32(LEDCTL); - hw->mac.ledctl_default = ledctl; - /* Turn off LED0 */ - ledctl &= ~(E1000_LEDCTL_LED0_IVRT | E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_LED0_MODE_MASK); - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << - E1000_LEDCTL_LED0_MODE_SHIFT); - ew32(LEDCTL, ledctl); - } else if (hw->phy.media_type == e1000_media_type_copper) { - ew32(LEDCTL, hw->mac.ledctl_mode1); - } - - return 0; -} - -/** - * e1000e_cleanup_led_generic - Set LED config to default operation - * @hw: pointer to the HW structure - * - * Remove the current LED configuration and set the LED configuration - * to the default value, saved from the EEPROM. - **/ -s32 e1000e_cleanup_led_generic(struct e1000_hw *hw) -{ - ew32(LEDCTL, hw->mac.ledctl_default); - return 0; -} - -/** - * e1000e_blink_led_generic - Blink LED - * @hw: pointer to the HW structure - * - * Blink the LEDs which are set to be on. - **/ -s32 e1000e_blink_led_generic(struct e1000_hw *hw) -{ - u32 ledctl_blink = 0; - u32 i; - - if (hw->phy.media_type == e1000_media_type_fiber) { - /* always blink LED0 for PCI-E fiber */ - ledctl_blink = E1000_LEDCTL_LED0_BLINK | - (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); - } else { - /* Set the blink bit for each LED that's "on" (0x0E) - * (or "off" if inverted) in ledctl_mode2. The blink - * logic in hardware only works when mode is set to "on" - * so it must be changed accordingly when the mode is - * "off" and inverted. - */ - ledctl_blink = hw->mac.ledctl_mode2; - for (i = 0; i < 32; i += 8) { - u32 mode = (hw->mac.ledctl_mode2 >> i) & - E1000_LEDCTL_LED0_MODE_MASK; - u32 led_default = hw->mac.ledctl_default >> i; - - if ((!(led_default & E1000_LEDCTL_LED0_IVRT) && - (mode == E1000_LEDCTL_MODE_LED_ON)) || - ((led_default & E1000_LEDCTL_LED0_IVRT) && - (mode == E1000_LEDCTL_MODE_LED_OFF))) { - ledctl_blink &= - ~(E1000_LEDCTL_LED0_MODE_MASK << i); - ledctl_blink |= (E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_MODE_LED_ON) << i; - } - } - } - - ew32(LEDCTL, ledctl_blink); - - return 0; -} - -/** - * e1000e_led_on_generic - Turn LED on - * @hw: pointer to the HW structure - * - * Turn LED on. - **/ -s32 e1000e_led_on_generic(struct e1000_hw *hw) -{ - u32 ctrl; - - switch (hw->phy.media_type) { - case e1000_media_type_fiber: - ctrl = er32(CTRL); - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - ew32(CTRL, ctrl); - break; - case e1000_media_type_copper: - ew32(LEDCTL, hw->mac.ledctl_mode2); - break; - default: - break; - } - - return 0; -} - -/** - * e1000e_led_off_generic - Turn LED off - * @hw: pointer to the HW structure - * - * Turn LED off. - **/ -s32 e1000e_led_off_generic(struct e1000_hw *hw) -{ - u32 ctrl; - - switch (hw->phy.media_type) { - case e1000_media_type_fiber: - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - ew32(CTRL, ctrl); - break; - case e1000_media_type_copper: - ew32(LEDCTL, hw->mac.ledctl_mode1); - break; - default: - break; - } - - return 0; -} - -/** - * e1000e_set_pcie_no_snoop - Set PCI-express capabilities - * @hw: pointer to the HW structure - * @no_snoop: bitmap of snoop events - * - * Set the PCI-express register to snoop for events enabled in 'no_snoop'. - **/ -void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop) -{ - u32 gcr; - - if (no_snoop) { - gcr = er32(GCR); - gcr &= ~(PCIE_NO_SNOOP_ALL); - gcr |= no_snoop; - ew32(GCR, gcr); - } -} - -/** - * e1000e_disable_pcie_master - Disables PCI-express master access - * @hw: pointer to the HW structure - * - * Returns 0 if successful, else returns -10 - * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused - * the master requests to be disabled. - * - * Disables PCI-Express master access and verifies there are no pending - * requests. - **/ -s32 e1000e_disable_pcie_master(struct e1000_hw *hw) -{ - u32 ctrl; - s32 timeout = MASTER_DISABLE_TIMEOUT; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; - ew32(CTRL, ctrl); - - while (timeout) { - if (!(er32(STATUS) & E1000_STATUS_GIO_MASTER_ENABLE)) - break; - usleep_range(100, 200); - timeout--; - } - - if (!timeout) { - e_dbg("Master requests are pending.\n"); - return -E1000_ERR_MASTER_REQUESTS_PENDING; - } - - return 0; -} - -/** - * e1000e_reset_adaptive - Reset Adaptive Interframe Spacing - * @hw: pointer to the HW structure - * - * Reset the Adaptive Interframe Spacing throttle to default values. - **/ -void e1000e_reset_adaptive(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - if (!mac->adaptive_ifs) { - e_dbg("Not in Adaptive IFS mode!\n"); - return; - } - - mac->current_ifs_val = 0; - mac->ifs_min_val = IFS_MIN; - mac->ifs_max_val = IFS_MAX; - mac->ifs_step_size = IFS_STEP; - mac->ifs_ratio = IFS_RATIO; - - mac->in_ifs_mode = false; - ew32(AIT, 0); -} - -/** - * e1000e_update_adaptive - Update Adaptive Interframe Spacing - * @hw: pointer to the HW structure - * - * Update the Adaptive Interframe Spacing Throttle value based on the - * time between transmitted packets and time between collisions. - **/ -void e1000e_update_adaptive(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - if (!mac->adaptive_ifs) { - e_dbg("Not in Adaptive IFS mode!\n"); - return; - } - - if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { - if (mac->tx_packet_delta > MIN_NUM_XMITS) { - mac->in_ifs_mode = true; - if (mac->current_ifs_val < mac->ifs_max_val) { - if (!mac->current_ifs_val) - mac->current_ifs_val = mac->ifs_min_val; - else - mac->current_ifs_val += - mac->ifs_step_size; - ew32(AIT, mac->current_ifs_val); - } - } - } else { - if (mac->in_ifs_mode && - (mac->tx_packet_delta <= MIN_NUM_XMITS)) { - mac->current_ifs_val = 0; - mac->in_ifs_mode = false; - ew32(AIT, 0); - } - } -} diff --git a/addons/e1000e/src/3.10.108/mac.h b/addons/e1000e/src/3.10.108/mac.h deleted file mode 100644 index a61fee40..00000000 --- a/addons/e1000e/src/3.10.108/mac.h +++ /dev/null @@ -1,74 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#ifndef _E1000E_MAC_H_ -#define _E1000E_MAC_H_ - -s32 e1000e_blink_led_generic(struct e1000_hw *hw); -s32 e1000e_check_for_copper_link(struct e1000_hw *hw); -s32 e1000e_check_for_fiber_link(struct e1000_hw *hw); -s32 e1000e_check_for_serdes_link(struct e1000_hw *hw); -s32 e1000e_cleanup_led_generic(struct e1000_hw *hw); -s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw); -s32 e1000e_disable_pcie_master(struct e1000_hw *hw); -s32 e1000e_force_mac_fc(struct e1000_hw *hw); -s32 e1000e_get_auto_rd_done(struct e1000_hw *hw); -s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw); -void e1000_set_lan_id_single_port(struct e1000_hw *hw); -s32 e1000e_get_hw_semaphore(struct e1000_hw *hw); -s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, - u16 *duplex); -s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, - u16 *speed, u16 *duplex); -s32 e1000e_id_led_init_generic(struct e1000_hw *hw); -s32 e1000e_led_on_generic(struct e1000_hw *hw); -s32 e1000e_led_off_generic(struct e1000_hw *hw); -void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count); -s32 e1000e_set_fc_watermarks(struct e1000_hw *hw); -s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw); -s32 e1000e_setup_led_generic(struct e1000_hw *hw); -s32 e1000e_setup_link_generic(struct e1000_hw *hw); -s32 e1000e_validate_mdi_setting_generic(struct e1000_hw *hw); -s32 e1000e_validate_mdi_setting_crossover_generic(struct e1000_hw *hw); - -void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw); -void e1000_clear_vfta_generic(struct e1000_hw *hw); -void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); -void e1000e_put_hw_semaphore(struct e1000_hw *hw); -s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw); -void e1000e_reset_adaptive(struct e1000_hw *hw); -void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop); -void e1000e_update_adaptive(struct e1000_hw *hw); -void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); - -void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw); -void e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); -void e1000e_config_collision_dist_generic(struct e1000_hw *hw); - -#endif diff --git a/addons/e1000e/src/3.10.108/manage.c b/addons/e1000e/src/3.10.108/manage.c deleted file mode 100644 index e4b0f1ef..00000000 --- a/addons/e1000e/src/3.10.108/manage.c +++ /dev/null @@ -1,351 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include "e1000.h" - -/** - * e1000_calculate_checksum - Calculate checksum for buffer - * @buffer: pointer to EEPROM - * @length: size of EEPROM to calculate a checksum for - * - * Calculates the checksum for some buffer on a specified length. The - * checksum calculated is returned. - **/ -static u8 e1000_calculate_checksum(u8 *buffer, u32 length) -{ - u32 i; - u8 sum = 0; - - if (!buffer) - return 0; - - for (i = 0; i < length; i++) - sum += buffer[i]; - - return (u8)(0 - sum); -} - -/** - * e1000_mng_enable_host_if - Checks host interface is enabled - * @hw: pointer to the HW structure - * - * Returns E1000_success upon success, else E1000_ERR_HOST_INTERFACE_COMMAND - * - * This function checks whether the HOST IF is enabled for command operation - * and also checks whether the previous command is completed. It busy waits - * in case of previous command is not completed. - **/ -static s32 e1000_mng_enable_host_if(struct e1000_hw *hw) -{ - u32 hicr; - u8 i; - - if (!hw->mac.arc_subsystem_valid) { - e_dbg("ARC subsystem not valid.\n"); - return -E1000_ERR_HOST_INTERFACE_COMMAND; - } - - /* Check that the host interface is enabled. */ - hicr = er32(HICR); - if (!(hicr & E1000_HICR_EN)) { - e_dbg("E1000_HOST_EN bit disabled.\n"); - return -E1000_ERR_HOST_INTERFACE_COMMAND; - } - /* check the previous command is completed */ - for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { - hicr = er32(HICR); - if (!(hicr & E1000_HICR_C)) - break; - mdelay(1); - } - - if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { - e_dbg("Previous command timeout failed .\n"); - return -E1000_ERR_HOST_INTERFACE_COMMAND; - } - - return 0; -} - -/** - * e1000e_check_mng_mode_generic - Generic check management mode - * @hw: pointer to the HW structure - * - * Reads the firmware semaphore register and returns true (>0) if - * manageability is enabled, else false (0). - **/ -bool e1000e_check_mng_mode_generic(struct e1000_hw *hw) -{ - u32 fwsm = er32(FWSM); - - return (fwsm & E1000_FWSM_MODE_MASK) == - (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); -} - -/** - * e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx - * @hw: pointer to the HW structure - * - * Enables packet filtering on transmit packets if manageability is enabled - * and host interface is enabled. - **/ -bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw) -{ - struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; - u32 *buffer = (u32 *)&hw->mng_cookie; - u32 offset; - s32 ret_val, hdr_csum, csum; - u8 i, len; - - hw->mac.tx_pkt_filtering = true; - - /* No manageability, no filtering */ - if (!hw->mac.ops.check_mng_mode(hw)) { - hw->mac.tx_pkt_filtering = false; - return hw->mac.tx_pkt_filtering; - } - - /* If we can't read from the host interface for whatever - * reason, disable filtering. - */ - ret_val = e1000_mng_enable_host_if(hw); - if (ret_val) { - hw->mac.tx_pkt_filtering = false; - return hw->mac.tx_pkt_filtering; - } - - /* Read in the header. Length and offset are in dwords. */ - len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; - offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; - for (i = 0; i < len; i++) - *(buffer + i) = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, - offset + i); - hdr_csum = hdr->checksum; - hdr->checksum = 0; - csum = e1000_calculate_checksum((u8 *)hdr, - E1000_MNG_DHCP_COOKIE_LENGTH); - /* If either the checksums or signature don't match, then - * the cookie area isn't considered valid, in which case we - * take the safe route of assuming Tx filtering is enabled. - */ - if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) { - hw->mac.tx_pkt_filtering = true; - return hw->mac.tx_pkt_filtering; - } - - /* Cookie area is valid, make the final check for filtering. */ - if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) - hw->mac.tx_pkt_filtering = false; - - return hw->mac.tx_pkt_filtering; -} - -/** - * e1000_mng_write_cmd_header - Writes manageability command header - * @hw: pointer to the HW structure - * @hdr: pointer to the host interface command header - * - * Writes the command header after does the checksum calculation. - **/ -static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, - struct e1000_host_mng_command_header *hdr) -{ - u16 i, length = sizeof(struct e1000_host_mng_command_header); - - /* Write the whole command header structure with new checksum. */ - - hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); - - length >>= 2; - /* Write the relevant command block into the ram area. */ - for (i = 0; i < length; i++) { - E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, i, *((u32 *)hdr + i)); - e1e_flush(); - } - - return 0; -} - -/** - * e1000_mng_host_if_write - Write to the manageability host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface buffer - * @length: size of the buffer - * @offset: location in the buffer to write to - * @sum: sum of the data (not checksum) - * - * This function writes the buffer content at the offset given on the host if. - * It also does alignment considerations to do the writes in most efficient - * way. Also fills up the sum of the buffer in *buffer parameter. - **/ -static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, - u16 length, u16 offset, u8 *sum) -{ - u8 *tmp; - u8 *bufptr = buffer; - u32 data = 0; - u16 remaining, i, j, prev_bytes; - - /* sum = only sum of the data and it is not checksum */ - - if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) - return -E1000_ERR_PARAM; - - tmp = (u8 *)&data; - prev_bytes = offset & 0x3; - offset >>= 2; - - if (prev_bytes) { - data = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset); - for (j = prev_bytes; j < sizeof(u32); j++) { - *(tmp + j) = *bufptr++; - *sum += *(tmp + j); - } - E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset, data); - length -= j - prev_bytes; - offset++; - } - - remaining = length & 0x3; - length -= remaining; - - /* Calculate length in DWORDs */ - length >>= 2; - - /* The device driver writes the relevant command block into the - * ram area. - */ - for (i = 0; i < length; i++) { - for (j = 0; j < sizeof(u32); j++) { - *(tmp + j) = *bufptr++; - *sum += *(tmp + j); - } - - E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data); - } - if (remaining) { - for (j = 0; j < sizeof(u32); j++) { - if (j < remaining) - *(tmp + j) = *bufptr++; - else - *(tmp + j) = 0; - - *sum += *(tmp + j); - } - E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data); - } - - return 0; -} - -/** - * e1000e_mng_write_dhcp_info - Writes DHCP info to host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface - * @length: size of the buffer - * - * Writes the DHCP information to the host interface. - **/ -s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length) -{ - struct e1000_host_mng_command_header hdr; - s32 ret_val; - u32 hicr; - - hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; - hdr.command_length = length; - hdr.reserved1 = 0; - hdr.reserved2 = 0; - hdr.checksum = 0; - - /* Enable the host interface */ - ret_val = e1000_mng_enable_host_if(hw); - if (ret_val) - return ret_val; - - /* Populate the host interface with the contents of "buffer". */ - ret_val = e1000_mng_host_if_write(hw, buffer, length, - sizeof(hdr), &(hdr.checksum)); - if (ret_val) - return ret_val; - - /* Write the manageability command header */ - ret_val = e1000_mng_write_cmd_header(hw, &hdr); - if (ret_val) - return ret_val; - - /* Tell the ARC a new command is pending. */ - hicr = er32(HICR); - ew32(HICR, hicr | E1000_HICR_C); - - return 0; -} - -/** - * e1000e_enable_mng_pass_thru - Check if management passthrough is needed - * @hw: pointer to the HW structure - * - * Verifies the hardware needs to leave interface enabled so that frames can - * be directed to and from the management interface. - **/ -bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw) -{ - u32 manc; - u32 fwsm, factps; - - manc = er32(MANC); - - if (!(manc & E1000_MANC_RCV_TCO_EN)) - return false; - - if (hw->mac.has_fwsm) { - fwsm = er32(FWSM); - factps = er32(FACTPS); - - if (!(factps & E1000_FACTPS_MNGCG) && - ((fwsm & E1000_FWSM_MODE_MASK) == - (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) - return true; - } else if ((hw->mac.type == e1000_82574) || - (hw->mac.type == e1000_82583)) { - u16 data; - - factps = er32(FACTPS); - e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data); - - if (!(factps & E1000_FACTPS_MNGCG) && - ((data & E1000_NVM_INIT_CTRL2_MNGM) == - (e1000_mng_mode_pt << 13))) - return true; - } else if ((manc & E1000_MANC_SMBUS_EN) && - !(manc & E1000_MANC_ASF_EN)) { - return true; - } - - return false; -} diff --git a/addons/e1000e/src/3.10.108/manage.h b/addons/e1000e/src/3.10.108/manage.h deleted file mode 100644 index 326897c2..00000000 --- a/addons/e1000e/src/3.10.108/manage.h +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#ifndef _E1000E_MANAGE_H_ -#define _E1000E_MANAGE_H_ - -bool e1000e_check_mng_mode_generic(struct e1000_hw *hw); -bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw); -s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length); -bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw); - -enum e1000_mng_mode { - e1000_mng_mode_none = 0, - e1000_mng_mode_asf, - e1000_mng_mode_pt, - e1000_mng_mode_ipmi, - e1000_mng_mode_host_if_only -}; - -#define E1000_FACTPS_MNGCG 0x20000000 - -#define E1000_FWSM_MODE_MASK 0xE -#define E1000_FWSM_MODE_SHIFT 1 - -#define E1000_MNG_IAMT_MODE 0x3 -#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 -#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 -#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 -#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64 -#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1 -#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 - -#define E1000_VFTA_ENTRY_SHIFT 5 -#define E1000_VFTA_ENTRY_MASK 0x7F -#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F - -#define E1000_HICR_EN 0x01 /* Enable bit - RO */ -/* Driver sets this bit when done to put command in RAM */ -#define E1000_HICR_C 0x02 -#define E1000_HICR_SV 0x04 /* Status Validity */ -#define E1000_HICR_FW_RESET_ENABLE 0x40 -#define E1000_HICR_FW_RESET 0x80 - -/* Intel(R) Active Management Technology signature */ -#define E1000_IAMT_SIGNATURE 0x544D4149 - -#endif diff --git a/addons/e1000e/src/3.10.108/netdev.c b/addons/e1000e/src/3.10.108/netdev.c deleted file mode 100644 index a27e3bcc..00000000 --- a/addons/e1000e/src/3.10.108/netdev.c +++ /dev/null @@ -1,7043 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "e1000.h" - -#define DRV_EXTRAVERSION "-k" - -#define DRV_VERSION "2.3.2" DRV_EXTRAVERSION -char e1000e_driver_name[] = "e1000e"; -const char e1000e_driver_version[] = DRV_VERSION; - -#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) -static int debug = -1; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); - -static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state); - -static const struct e1000_info *e1000_info_tbl[] = { - [board_82571] = &e1000_82571_info, - [board_82572] = &e1000_82572_info, - [board_82573] = &e1000_82573_info, - [board_82574] = &e1000_82574_info, - [board_82583] = &e1000_82583_info, - [board_80003es2lan] = &e1000_es2_info, - [board_ich8lan] = &e1000_ich8_info, - [board_ich9lan] = &e1000_ich9_info, - [board_ich10lan] = &e1000_ich10_info, - [board_pchlan] = &e1000_pch_info, - [board_pch2lan] = &e1000_pch2_info, - [board_pch_lpt] = &e1000_pch_lpt_info, -}; - -struct e1000_reg_info { - u32 ofs; - char *name; -}; - -static const struct e1000_reg_info e1000_reg_info_tbl[] = { - /* General Registers */ - {E1000_CTRL, "CTRL"}, - {E1000_STATUS, "STATUS"}, - {E1000_CTRL_EXT, "CTRL_EXT"}, - - /* Interrupt Registers */ - {E1000_ICR, "ICR"}, - - /* Rx Registers */ - {E1000_RCTL, "RCTL"}, - {E1000_RDLEN(0), "RDLEN"}, - {E1000_RDH(0), "RDH"}, - {E1000_RDT(0), "RDT"}, - {E1000_RDTR, "RDTR"}, - {E1000_RXDCTL(0), "RXDCTL"}, - {E1000_ERT, "ERT"}, - {E1000_RDBAL(0), "RDBAL"}, - {E1000_RDBAH(0), "RDBAH"}, - {E1000_RDFH, "RDFH"}, - {E1000_RDFT, "RDFT"}, - {E1000_RDFHS, "RDFHS"}, - {E1000_RDFTS, "RDFTS"}, - {E1000_RDFPC, "RDFPC"}, - - /* Tx Registers */ - {E1000_TCTL, "TCTL"}, - {E1000_TDBAL(0), "TDBAL"}, - {E1000_TDBAH(0), "TDBAH"}, - {E1000_TDLEN(0), "TDLEN"}, - {E1000_TDH(0), "TDH"}, - {E1000_TDT(0), "TDT"}, - {E1000_TIDV, "TIDV"}, - {E1000_TXDCTL(0), "TXDCTL"}, - {E1000_TADV, "TADV"}, - {E1000_TARC(0), "TARC"}, - {E1000_TDFH, "TDFH"}, - {E1000_TDFT, "TDFT"}, - {E1000_TDFHS, "TDFHS"}, - {E1000_TDFTS, "TDFTS"}, - {E1000_TDFPC, "TDFPC"}, - - /* List Terminator */ - {0, NULL} -}; - -/** - * e1000_regdump - register printout routine - * @hw: pointer to the HW structure - * @reginfo: pointer to the register info table - **/ -static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo) -{ - int n = 0; - char rname[16]; - u32 regs[8]; - - switch (reginfo->ofs) { - case E1000_RXDCTL(0): - for (n = 0; n < 2; n++) - regs[n] = __er32(hw, E1000_RXDCTL(n)); - break; - case E1000_TXDCTL(0): - for (n = 0; n < 2; n++) - regs[n] = __er32(hw, E1000_TXDCTL(n)); - break; - case E1000_TARC(0): - for (n = 0; n < 2; n++) - regs[n] = __er32(hw, E1000_TARC(n)); - break; - default: - pr_info("%-15s %08x\n", - reginfo->name, __er32(hw, reginfo->ofs)); - return; - } - - snprintf(rname, 16, "%s%s", reginfo->name, "[0-1]"); - pr_info("%-15s %08x %08x\n", rname, regs[0], regs[1]); -} - -static void e1000e_dump_ps_pages(struct e1000_adapter *adapter, - struct e1000_buffer *bi) -{ - int i; - struct e1000_ps_page *ps_page; - - for (i = 0; i < adapter->rx_ps_pages; i++) { - ps_page = &bi->ps_pages[i]; - - if (ps_page->page) { - pr_info("packet dump for ps_page %d:\n", i); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, - 16, 1, page_address(ps_page->page), - PAGE_SIZE, true); - } - } -} - -/** - * e1000e_dump - Print registers, Tx-ring and Rx-ring - * @adapter: board private structure - **/ -static void e1000e_dump(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - struct e1000_reg_info *reginfo; - struct e1000_ring *tx_ring = adapter->tx_ring; - struct e1000_tx_desc *tx_desc; - struct my_u0 { - __le64 a; - __le64 b; - } *u0; - struct e1000_buffer *buffer_info; - struct e1000_ring *rx_ring = adapter->rx_ring; - union e1000_rx_desc_packet_split *rx_desc_ps; - union e1000_rx_desc_extended *rx_desc; - struct my_u1 { - __le64 a; - __le64 b; - __le64 c; - __le64 d; - } *u1; - u32 staterr; - int i = 0; - - if (!netif_msg_hw(adapter)) - return; - - /* Print netdevice Info */ - if (netdev) { - dev_info(&adapter->pdev->dev, "Net device Info\n"); - pr_info("Device Name state trans_start last_rx\n"); - pr_info("%-15s %016lX %016lX %016lX\n", netdev->name, - netdev->state, netdev->trans_start, netdev->last_rx); - } - - /* Print Registers */ - dev_info(&adapter->pdev->dev, "Register Dump\n"); - pr_info(" Register Name Value\n"); - for (reginfo = (struct e1000_reg_info *)e1000_reg_info_tbl; - reginfo->name; reginfo++) { - e1000_regdump(hw, reginfo); - } - - /* Print Tx Ring Summary */ - if (!netdev || !netif_running(netdev)) - return; - - dev_info(&adapter->pdev->dev, "Tx Ring Summary\n"); - pr_info("Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n"); - buffer_info = &tx_ring->buffer_info[tx_ring->next_to_clean]; - pr_info(" %5d %5X %5X %016llX %04X %3X %016llX\n", - 0, tx_ring->next_to_use, tx_ring->next_to_clean, - (unsigned long long)buffer_info->dma, - buffer_info->length, - buffer_info->next_to_watch, - (unsigned long long)buffer_info->time_stamp); - - /* Print Tx Ring */ - if (!netif_msg_tx_done(adapter)) - goto rx_ring_summary; - - dev_info(&adapter->pdev->dev, "Tx Ring Dump\n"); - - /* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended) - * - * Legacy Transmit Descriptor - * +--------------------------------------------------------------+ - * 0 | Buffer Address [63:0] (Reserved on Write Back) | - * +--------------------------------------------------------------+ - * 8 | Special | CSS | Status | CMD | CSO | Length | - * +--------------------------------------------------------------+ - * 63 48 47 36 35 32 31 24 23 16 15 0 - * - * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload - * 63 48 47 40 39 32 31 16 15 8 7 0 - * +----------------------------------------------------------------+ - * 0 | TUCSE | TUCS0 | TUCSS | IPCSE | IPCS0 | IPCSS | - * +----------------------------------------------------------------+ - * 8 | MSS | HDRLEN | RSV | STA | TUCMD | DTYP | PAYLEN | - * +----------------------------------------------------------------+ - * 63 48 47 40 39 36 35 32 31 24 23 20 19 0 - * - * Extended Data Descriptor (DTYP=0x1) - * +----------------------------------------------------------------+ - * 0 | Buffer Address [63:0] | - * +----------------------------------------------------------------+ - * 8 | VLAN tag | POPTS | Rsvd | Status | Command | DTYP | DTALEN | - * +----------------------------------------------------------------+ - * 63 48 47 40 39 36 35 32 31 24 23 20 19 0 - */ - pr_info("Tl[desc] [address 63:0 ] [SpeCssSCmCsLen] [bi->dma ] leng ntw timestamp bi->skb <-- Legacy format\n"); - pr_info("Tc[desc] [Ce CoCsIpceCoS] [MssHlRSCm0Plen] [bi->dma ] leng ntw timestamp bi->skb <-- Ext Context format\n"); - pr_info("Td[desc] [address 63:0 ] [VlaPoRSCm1Dlen] [bi->dma ] leng ntw timestamp bi->skb <-- Ext Data format\n"); - for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { - const char *next_desc; - tx_desc = E1000_TX_DESC(*tx_ring, i); - buffer_info = &tx_ring->buffer_info[i]; - u0 = (struct my_u0 *)tx_desc; - if (i == tx_ring->next_to_use && i == tx_ring->next_to_clean) - next_desc = " NTC/U"; - else if (i == tx_ring->next_to_use) - next_desc = " NTU"; - else if (i == tx_ring->next_to_clean) - next_desc = " NTC"; - else - next_desc = ""; - pr_info("T%c[0x%03X] %016llX %016llX %016llX %04X %3X %016llX %p%s\n", - (!(le64_to_cpu(u0->b) & (1 << 29)) ? 'l' : - ((le64_to_cpu(u0->b) & (1 << 20)) ? 'd' : 'c')), - i, - (unsigned long long)le64_to_cpu(u0->a), - (unsigned long long)le64_to_cpu(u0->b), - (unsigned long long)buffer_info->dma, - buffer_info->length, buffer_info->next_to_watch, - (unsigned long long)buffer_info->time_stamp, - buffer_info->skb, next_desc); - - if (netif_msg_pktdata(adapter) && buffer_info->skb) - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, - 16, 1, buffer_info->skb->data, - buffer_info->skb->len, true); - } - - /* Print Rx Ring Summary */ -rx_ring_summary: - dev_info(&adapter->pdev->dev, "Rx Ring Summary\n"); - pr_info("Queue [NTU] [NTC]\n"); - pr_info(" %5d %5X %5X\n", - 0, rx_ring->next_to_use, rx_ring->next_to_clean); - - /* Print Rx Ring */ - if (!netif_msg_rx_status(adapter)) - return; - - dev_info(&adapter->pdev->dev, "Rx Ring Dump\n"); - switch (adapter->rx_ps_pages) { - case 1: - case 2: - case 3: - /* [Extended] Packet Split Receive Descriptor Format - * - * +-----------------------------------------------------+ - * 0 | Buffer Address 0 [63:0] | - * +-----------------------------------------------------+ - * 8 | Buffer Address 1 [63:0] | - * +-----------------------------------------------------+ - * 16 | Buffer Address 2 [63:0] | - * +-----------------------------------------------------+ - * 24 | Buffer Address 3 [63:0] | - * +-----------------------------------------------------+ - */ - pr_info("R [desc] [buffer 0 63:0 ] [buffer 1 63:0 ] [buffer 2 63:0 ] [buffer 3 63:0 ] [bi->dma ] [bi->skb] <-- Ext Pkt Split format\n"); - /* [Extended] Receive Descriptor (Write-Back) Format - * - * 63 48 47 32 31 13 12 8 7 4 3 0 - * +------------------------------------------------------+ - * 0 | Packet | IP | Rsvd | MRQ | Rsvd | MRQ RSS | - * | Checksum | Ident | | Queue | | Type | - * +------------------------------------------------------+ - * 8 | VLAN Tag | Length | Extended Error | Extended Status | - * +------------------------------------------------------+ - * 63 48 47 32 31 20 19 0 - */ - pr_info("RWB[desc] [ck ipid mrqhsh] [vl l0 ee es] [ l3 l2 l1 hs] [reserved ] ---------------- [bi->skb] <-- Ext Rx Write-Back format\n"); - for (i = 0; i < rx_ring->count; i++) { - const char *next_desc; - buffer_info = &rx_ring->buffer_info[i]; - rx_desc_ps = E1000_RX_DESC_PS(*rx_ring, i); - u1 = (struct my_u1 *)rx_desc_ps; - staterr = - le32_to_cpu(rx_desc_ps->wb.middle.status_error); - - if (i == rx_ring->next_to_use) - next_desc = " NTU"; - else if (i == rx_ring->next_to_clean) - next_desc = " NTC"; - else - next_desc = ""; - - if (staterr & E1000_RXD_STAT_DD) { - /* Descriptor Done */ - pr_info("%s[0x%03X] %016llX %016llX %016llX %016llX ---------------- %p%s\n", - "RWB", i, - (unsigned long long)le64_to_cpu(u1->a), - (unsigned long long)le64_to_cpu(u1->b), - (unsigned long long)le64_to_cpu(u1->c), - (unsigned long long)le64_to_cpu(u1->d), - buffer_info->skb, next_desc); - } else { - pr_info("%s[0x%03X] %016llX %016llX %016llX %016llX %016llX %p%s\n", - "R ", i, - (unsigned long long)le64_to_cpu(u1->a), - (unsigned long long)le64_to_cpu(u1->b), - (unsigned long long)le64_to_cpu(u1->c), - (unsigned long long)le64_to_cpu(u1->d), - (unsigned long long)buffer_info->dma, - buffer_info->skb, next_desc); - - if (netif_msg_pktdata(adapter)) - e1000e_dump_ps_pages(adapter, - buffer_info); - } - } - break; - default: - case 0: - /* Extended Receive Descriptor (Read) Format - * - * +-----------------------------------------------------+ - * 0 | Buffer Address [63:0] | - * +-----------------------------------------------------+ - * 8 | Reserved | - * +-----------------------------------------------------+ - */ - pr_info("R [desc] [buf addr 63:0 ] [reserved 63:0 ] [bi->dma ] [bi->skb] <-- Ext (Read) format\n"); - /* Extended Receive Descriptor (Write-Back) Format - * - * 63 48 47 32 31 24 23 4 3 0 - * +------------------------------------------------------+ - * | RSS Hash | | | | - * 0 +-------------------+ Rsvd | Reserved | MRQ RSS | - * | Packet | IP | | | Type | - * | Checksum | Ident | | | | - * +------------------------------------------------------+ - * 8 | VLAN Tag | Length | Extended Error | Extended Status | - * +------------------------------------------------------+ - * 63 48 47 32 31 20 19 0 - */ - pr_info("RWB[desc] [cs ipid mrq] [vt ln xe xs] [bi->skb] <-- Ext (Write-Back) format\n"); - - for (i = 0; i < rx_ring->count; i++) { - const char *next_desc; - - buffer_info = &rx_ring->buffer_info[i]; - rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); - u1 = (struct my_u1 *)rx_desc; - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); - - if (i == rx_ring->next_to_use) - next_desc = " NTU"; - else if (i == rx_ring->next_to_clean) - next_desc = " NTC"; - else - next_desc = ""; - - if (staterr & E1000_RXD_STAT_DD) { - /* Descriptor Done */ - pr_info("%s[0x%03X] %016llX %016llX ---------------- %p%s\n", - "RWB", i, - (unsigned long long)le64_to_cpu(u1->a), - (unsigned long long)le64_to_cpu(u1->b), - buffer_info->skb, next_desc); - } else { - pr_info("%s[0x%03X] %016llX %016llX %016llX %p%s\n", - "R ", i, - (unsigned long long)le64_to_cpu(u1->a), - (unsigned long long)le64_to_cpu(u1->b), - (unsigned long long)buffer_info->dma, - buffer_info->skb, next_desc); - - if (netif_msg_pktdata(adapter) && - buffer_info->skb) - print_hex_dump(KERN_INFO, "", - DUMP_PREFIX_ADDRESS, 16, - 1, - buffer_info->skb->data, - adapter->rx_buffer_len, - true); - } - } - } -} - -/** - * e1000_desc_unused - calculate if we have unused descriptors - **/ -static int e1000_desc_unused(struct e1000_ring *ring) -{ - if (ring->next_to_clean > ring->next_to_use) - return ring->next_to_clean - ring->next_to_use - 1; - - return ring->count + ring->next_to_clean - ring->next_to_use - 1; -} - -/** - * e1000e_systim_to_hwtstamp - convert system time value to hw time stamp - * @adapter: board private structure - * @hwtstamps: time stamp structure to update - * @systim: unsigned 64bit system time value. - * - * Convert the system time value stored in the RX/TXSTMP registers into a - * hwtstamp which can be used by the upper level time stamping functions. - * - * The 'systim_lock' spinlock is used to protect the consistency of the - * system time value. This is needed because reading the 64 bit time - * value involves reading two 32 bit registers. The first read latches the - * value. - **/ -static void e1000e_systim_to_hwtstamp(struct e1000_adapter *adapter, - struct skb_shared_hwtstamps *hwtstamps, - u64 systim) -{ - u64 ns; - unsigned long flags; - - spin_lock_irqsave(&adapter->systim_lock, flags); - ns = timecounter_cyc2time(&adapter->tc, systim); - spin_unlock_irqrestore(&adapter->systim_lock, flags); - - memset(hwtstamps, 0, sizeof(*hwtstamps)); - hwtstamps->hwtstamp = ns_to_ktime(ns); -} - -/** - * e1000e_rx_hwtstamp - utility function which checks for Rx time stamp - * @adapter: board private structure - * @status: descriptor extended error and status field - * @skb: particular skb to include time stamp - * - * If the time stamp is valid, convert it into the timecounter ns value - * and store that result into the shhwtstamps structure which is passed - * up the network stack. - **/ -static void e1000e_rx_hwtstamp(struct e1000_adapter *adapter, u32 status, - struct sk_buff *skb) -{ - struct e1000_hw *hw = &adapter->hw; - u64 rxstmp; - - if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP) || - !(status & E1000_RXDEXT_STATERR_TST) || - !(er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID)) - return; - - /* The Rx time stamp registers contain the time stamp. No other - * received packet will be time stamped until the Rx time stamp - * registers are read. Because only one packet can be time stamped - * at a time, the register values must belong to this packet and - * therefore none of the other additional attributes need to be - * compared. - */ - rxstmp = (u64)er32(RXSTMPL); - rxstmp |= (u64)er32(RXSTMPH) << 32; - e1000e_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), rxstmp); - - adapter->flags2 &= ~FLAG2_CHECK_RX_HWTSTAMP; -} - -/** - * e1000_receive_skb - helper function to handle Rx indications - * @adapter: board private structure - * @staterr: descriptor extended error and status field as written by hardware - * @vlan: descriptor vlan field as written by hardware (no le/be conversion) - * @skb: pointer to sk_buff to be indicated to stack - **/ -static void e1000_receive_skb(struct e1000_adapter *adapter, - struct net_device *netdev, struct sk_buff *skb, - u32 staterr, __le16 vlan) -{ - u16 tag = le16_to_cpu(vlan); - - e1000e_rx_hwtstamp(adapter, staterr, skb); - - skb->protocol = eth_type_trans(skb, netdev); - - if (staterr & E1000_RXD_STAT_VP) - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tag); - - napi_gro_receive(&adapter->napi, skb); -} - -/** - * e1000_rx_checksum - Receive Checksum Offload - * @adapter: board private structure - * @status_err: receive descriptor status and error fields - * @csum: receive descriptor csum field - * @sk_buff: socket buffer with received data - **/ -static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, - struct sk_buff *skb) -{ - u16 status = (u16)status_err; - u8 errors = (u8)(status_err >> 24); - - skb_checksum_none_assert(skb); - - /* Rx checksum disabled */ - if (!(adapter->netdev->features & NETIF_F_RXCSUM)) - return; - - /* Ignore Checksum bit is set */ - if (status & E1000_RXD_STAT_IXSM) - return; - - /* TCP/UDP checksum error bit or IP checksum error bit is set */ - if (errors & (E1000_RXD_ERR_TCPE | E1000_RXD_ERR_IPE)) { - /* let the stack verify checksum errors */ - adapter->hw_csum_err++; - return; - } - - /* TCP/UDP Checksum has not been calculated */ - if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))) - return; - - /* It must be a TCP or UDP packet with a valid checksum */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - adapter->hw_csum_good++; -} - -static void e1000e_update_rdt_wa(struct e1000_ring *rx_ring, unsigned int i) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct e1000_hw *hw = &adapter->hw; - s32 ret_val = __ew32_prepare(hw); - - writel(i, rx_ring->tail); - - if (unlikely(!ret_val && (i != readl(rx_ring->tail)))) { - u32 rctl = er32(RCTL); - ew32(RCTL, rctl & ~E1000_RCTL_EN); - e_err("ME firmware caused invalid RDT - resetting\n"); - schedule_work(&adapter->reset_task); - } -} - -static void e1000e_update_tdt_wa(struct e1000_ring *tx_ring, unsigned int i) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct e1000_hw *hw = &adapter->hw; - s32 ret_val = __ew32_prepare(hw); - - writel(i, tx_ring->tail); - - if (unlikely(!ret_val && (i != readl(tx_ring->tail)))) { - u32 tctl = er32(TCTL); - ew32(TCTL, tctl & ~E1000_TCTL_EN); - e_err("ME firmware caused invalid TDT - resetting\n"); - schedule_work(&adapter->reset_task); - } -} - -/** - * e1000_alloc_rx_buffers - Replace used receive buffers - * @rx_ring: Rx descriptor ring - **/ -static void e1000_alloc_rx_buffers(struct e1000_ring *rx_ring, - int cleaned_count, gfp_t gfp) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - union e1000_rx_desc_extended *rx_desc; - struct e1000_buffer *buffer_info; - struct sk_buff *skb; - unsigned int i; - unsigned int bufsz = adapter->rx_buffer_len; - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - - while (cleaned_count--) { - skb = buffer_info->skb; - if (skb) { - skb_trim(skb, 0); - goto map_skb; - } - - skb = __netdev_alloc_skb_ip_align(netdev, bufsz, gfp); - if (!skb) { - /* Better luck next round */ - adapter->alloc_rx_buff_failed++; - break; - } - - buffer_info->skb = skb; -map_skb: - buffer_info->dma = dma_map_single(&pdev->dev, skb->data, - adapter->rx_buffer_len, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { - dev_err(&pdev->dev, "Rx DMA map failed\n"); - adapter->rx_dma_failed++; - break; - } - - rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); - rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma); - - if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) { - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_rdt_wa(rx_ring, i); - else - writel(i, rx_ring->tail); - } - i++; - if (i == rx_ring->count) - i = 0; - buffer_info = &rx_ring->buffer_info[i]; - } - - rx_ring->next_to_use = i; -} - -/** - * e1000_alloc_rx_buffers_ps - Replace used receive buffers; packet split - * @rx_ring: Rx descriptor ring - **/ -static void e1000_alloc_rx_buffers_ps(struct e1000_ring *rx_ring, - int cleaned_count, gfp_t gfp) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - union e1000_rx_desc_packet_split *rx_desc; - struct e1000_buffer *buffer_info; - struct e1000_ps_page *ps_page; - struct sk_buff *skb; - unsigned int i, j; - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - - while (cleaned_count--) { - rx_desc = E1000_RX_DESC_PS(*rx_ring, i); - - for (j = 0; j < PS_PAGE_BUFFERS; j++) { - ps_page = &buffer_info->ps_pages[j]; - if (j >= adapter->rx_ps_pages) { - /* all unused desc entries get hw null ptr */ - rx_desc->read.buffer_addr[j + 1] = - ~cpu_to_le64(0); - continue; - } - if (!ps_page->page) { - ps_page->page = alloc_page(gfp); - if (!ps_page->page) { - adapter->alloc_rx_buff_failed++; - goto no_buffers; - } - ps_page->dma = dma_map_page(&pdev->dev, - ps_page->page, - 0, PAGE_SIZE, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, - ps_page->dma)) { - dev_err(&adapter->pdev->dev, - "Rx DMA page map failed\n"); - adapter->rx_dma_failed++; - goto no_buffers; - } - } - /* Refresh the desc even if buffer_addrs - * didn't change because each write-back - * erases this info. - */ - rx_desc->read.buffer_addr[j + 1] = - cpu_to_le64(ps_page->dma); - } - - skb = __netdev_alloc_skb_ip_align(netdev, adapter->rx_ps_bsize0, - gfp); - - if (!skb) { - adapter->alloc_rx_buff_failed++; - break; - } - - buffer_info->skb = skb; - buffer_info->dma = dma_map_single(&pdev->dev, skb->data, - adapter->rx_ps_bsize0, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { - dev_err(&pdev->dev, "Rx DMA map failed\n"); - adapter->rx_dma_failed++; - /* cleanup skb */ - dev_kfree_skb_any(skb); - buffer_info->skb = NULL; - break; - } - - rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma); - - if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) { - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_rdt_wa(rx_ring, i << 1); - else - writel(i << 1, rx_ring->tail); - } - - i++; - if (i == rx_ring->count) - i = 0; - buffer_info = &rx_ring->buffer_info[i]; - } - -no_buffers: - rx_ring->next_to_use = i; -} - -/** - * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers - * @rx_ring: Rx descriptor ring - * @cleaned_count: number of buffers to allocate this pass - **/ - -static void e1000_alloc_jumbo_rx_buffers(struct e1000_ring *rx_ring, - int cleaned_count, gfp_t gfp) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - union e1000_rx_desc_extended *rx_desc; - struct e1000_buffer *buffer_info; - struct sk_buff *skb; - unsigned int i; - unsigned int bufsz = 256 - 16; /* for skb_reserve */ - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - - while (cleaned_count--) { - skb = buffer_info->skb; - if (skb) { - skb_trim(skb, 0); - goto check_page; - } - - skb = __netdev_alloc_skb_ip_align(netdev, bufsz, gfp); - if (unlikely(!skb)) { - /* Better luck next round */ - adapter->alloc_rx_buff_failed++; - break; - } - - buffer_info->skb = skb; -check_page: - /* allocate a new page if necessary */ - if (!buffer_info->page) { - buffer_info->page = alloc_page(gfp); - if (unlikely(!buffer_info->page)) { - adapter->alloc_rx_buff_failed++; - break; - } - } - - if (!buffer_info->dma) { - buffer_info->dma = dma_map_page(&pdev->dev, - buffer_info->page, 0, - PAGE_SIZE, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { - adapter->alloc_rx_buff_failed++; - break; - } - } - - rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); - rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma); - - if (unlikely(++i == rx_ring->count)) - i = 0; - buffer_info = &rx_ring->buffer_info[i]; - } - - if (likely(rx_ring->next_to_use != i)) { - rx_ring->next_to_use = i; - if (unlikely(i-- == 0)) - i = (rx_ring->count - 1); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_rdt_wa(rx_ring, i); - else - writel(i, rx_ring->tail); - } -} - -static inline void e1000_rx_hash(struct net_device *netdev, __le32 rss, - struct sk_buff *skb) -{ - if (netdev->features & NETIF_F_RXHASH) - skb->rxhash = le32_to_cpu(rss); -} - -/** - * e1000_clean_rx_irq - Send received data up the network stack - * @rx_ring: Rx descriptor ring - * - * the return value indicates whether actual cleaning was done, there - * is no guarantee that everything was cleaned - **/ -static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done, - int work_to_do) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_hw *hw = &adapter->hw; - union e1000_rx_desc_extended *rx_desc, *next_rxd; - struct e1000_buffer *buffer_info, *next_buffer; - u32 length, staterr; - unsigned int i; - int cleaned_count = 0; - bool cleaned = false; - unsigned int total_rx_bytes = 0, total_rx_packets = 0; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); - buffer_info = &rx_ring->buffer_info[i]; - - while (staterr & E1000_RXD_STAT_DD) { - struct sk_buff *skb; - - if (*work_done >= work_to_do) - break; - (*work_done)++; - rmb(); /* read descriptor and rx_buffer_info after status DD */ - - skb = buffer_info->skb; - buffer_info->skb = NULL; - - prefetch(skb->data - NET_IP_ALIGN); - - i++; - if (i == rx_ring->count) - i = 0; - next_rxd = E1000_RX_DESC_EXT(*rx_ring, i); - prefetch(next_rxd); - - next_buffer = &rx_ring->buffer_info[i]; - - cleaned = true; - cleaned_count++; - dma_unmap_single(&pdev->dev, buffer_info->dma, - adapter->rx_buffer_len, DMA_FROM_DEVICE); - buffer_info->dma = 0; - - length = le16_to_cpu(rx_desc->wb.upper.length); - - /* !EOP means multiple descriptors were used to store a single - * packet, if that's the case we need to toss it. In fact, we - * need to toss every packet with the EOP bit clear and the - * next frame that _does_ have the EOP bit set, as it is by - * definition only a frame fragment - */ - if (unlikely(!(staterr & E1000_RXD_STAT_EOP))) - adapter->flags2 |= FLAG2_IS_DISCARDING; - - if (adapter->flags2 & FLAG2_IS_DISCARDING) { - /* All receives must fit into a single buffer */ - e_dbg("Receive packet consumed multiple buffers\n"); - /* recycle */ - buffer_info->skb = skb; - if (staterr & E1000_RXD_STAT_EOP) - adapter->flags2 &= ~FLAG2_IS_DISCARDING; - goto next_desc; - } - - if (unlikely((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) && - !(netdev->features & NETIF_F_RXALL))) { - /* recycle */ - buffer_info->skb = skb; - goto next_desc; - } - - /* adjust length to remove Ethernet CRC */ - if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) { - /* If configured to store CRC, don't subtract FCS, - * but keep the FCS bytes out of the total_rx_bytes - * counter - */ - if (netdev->features & NETIF_F_RXFCS) - total_rx_bytes -= 4; - else - length -= 4; - } - - total_rx_bytes += length; - total_rx_packets++; - - /* code added for copybreak, this should improve - * performance for small packets with large amounts - * of reassembly being done in the stack - */ - if (length < copybreak) { - struct sk_buff *new_skb = - netdev_alloc_skb_ip_align(netdev, length); - if (new_skb) { - skb_copy_to_linear_data_offset(new_skb, - -NET_IP_ALIGN, - (skb->data - - NET_IP_ALIGN), - (length + - NET_IP_ALIGN)); - /* save the skb in buffer_info as good */ - buffer_info->skb = skb; - skb = new_skb; - } - /* else just continue with the old one */ - } - /* end copybreak code */ - skb_put(skb, length); - - /* Receive Checksum Offload */ - e1000_rx_checksum(adapter, staterr, skb); - - e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); - - e1000_receive_skb(adapter, netdev, skb, staterr, - rx_desc->wb.upper.vlan); - -next_desc: - rx_desc->wb.upper.status_error &= cpu_to_le32(~0xFF); - - /* return some buffers to hardware, one at a time is too slow */ - if (cleaned_count >= E1000_RX_BUFFER_WRITE) { - adapter->alloc_rx_buf(rx_ring, cleaned_count, - GFP_ATOMIC); - cleaned_count = 0; - } - - /* use prefetched values */ - rx_desc = next_rxd; - buffer_info = next_buffer; - - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); - } - rx_ring->next_to_clean = i; - - cleaned_count = e1000_desc_unused(rx_ring); - if (cleaned_count) - adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); - - adapter->total_rx_bytes += total_rx_bytes; - adapter->total_rx_packets += total_rx_packets; - return cleaned; -} - -static void e1000_put_txbuf(struct e1000_ring *tx_ring, - struct e1000_buffer *buffer_info) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - - if (buffer_info->dma) { - if (buffer_info->mapped_as_page) - dma_unmap_page(&adapter->pdev->dev, buffer_info->dma, - buffer_info->length, DMA_TO_DEVICE); - else - dma_unmap_single(&adapter->pdev->dev, buffer_info->dma, - buffer_info->length, DMA_TO_DEVICE); - buffer_info->dma = 0; - } - if (buffer_info->skb) { - dev_kfree_skb_any(buffer_info->skb); - buffer_info->skb = NULL; - } - buffer_info->time_stamp = 0; -} - -static void e1000_print_hw_hang(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - print_hang_task); - struct net_device *netdev = adapter->netdev; - struct e1000_ring *tx_ring = adapter->tx_ring; - unsigned int i = tx_ring->next_to_clean; - unsigned int eop = tx_ring->buffer_info[i].next_to_watch; - struct e1000_tx_desc *eop_desc = E1000_TX_DESC(*tx_ring, eop); - struct e1000_hw *hw = &adapter->hw; - u16 phy_status, phy_1000t_status, phy_ext_status; - u16 pci_status; - - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - - if (!adapter->tx_hang_recheck && (adapter->flags2 & FLAG2_DMA_BURST)) { - /* May be block on write-back, flush and detect again - * flush pending descriptor writebacks to memory - */ - ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); - /* execute the writes immediately */ - e1e_flush(); - /* Due to rare timing issues, write to TIDV again to ensure - * the write is successful - */ - ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); - /* execute the writes immediately */ - e1e_flush(); - adapter->tx_hang_recheck = true; - return; - } - /* Real hang detected */ - adapter->tx_hang_recheck = false; - netif_stop_queue(netdev); - - e1e_rphy(hw, MII_BMSR, &phy_status); - e1e_rphy(hw, MII_STAT1000, &phy_1000t_status); - e1e_rphy(hw, MII_ESTATUS, &phy_ext_status); - - pci_read_config_word(adapter->pdev, PCI_STATUS, &pci_status); - - /* detected Hardware unit hang */ - e_err("Detected Hardware Unit Hang:\n" - " TDH <%x>\n" - " TDT <%x>\n" - " next_to_use <%x>\n" - " next_to_clean <%x>\n" - "buffer_info[next_to_clean]:\n" - " time_stamp <%lx>\n" - " next_to_watch <%x>\n" - " jiffies <%lx>\n" - " next_to_watch.status <%x>\n" - "MAC Status <%x>\n" - "PHY Status <%x>\n" - "PHY 1000BASE-T Status <%x>\n" - "PHY Extended Status <%x>\n" - "PCI Status <%x>\n", - readl(tx_ring->head), readl(tx_ring->tail), tx_ring->next_to_use, - tx_ring->next_to_clean, tx_ring->buffer_info[eop].time_stamp, - eop, jiffies, eop_desc->upper.fields.status, er32(STATUS), - phy_status, phy_1000t_status, phy_ext_status, pci_status); - - /* Suggest workaround for known h/w issue */ - if ((hw->mac.type == e1000_pchlan) && (er32(CTRL) & E1000_CTRL_TFCE)) - e_err("Try turning off Tx pause (flow control) via ethtool\n"); -} - -/** - * e1000e_tx_hwtstamp_work - check for Tx time stamp - * @work: pointer to work struct - * - * This work function polls the TSYNCTXCTL valid bit to determine when a - * timestamp has been taken for the current stored skb. The timestamp must - * be for this skb because only one such packet is allowed in the queue. - */ -static void e1000e_tx_hwtstamp_work(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, struct e1000_adapter, - tx_hwtstamp_work); - struct e1000_hw *hw = &adapter->hw; - - if (!adapter->tx_hwtstamp_skb) - return; - - if (er32(TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID) { - struct skb_shared_hwtstamps shhwtstamps; - u64 txstmp; - - txstmp = er32(TXSTMPL); - txstmp |= (u64)er32(TXSTMPH) << 32; - - e1000e_systim_to_hwtstamp(adapter, &shhwtstamps, txstmp); - - skb_tstamp_tx(adapter->tx_hwtstamp_skb, &shhwtstamps); - dev_kfree_skb_any(adapter->tx_hwtstamp_skb); - adapter->tx_hwtstamp_skb = NULL; - } else { - /* reschedule to check later */ - schedule_work(&adapter->tx_hwtstamp_work); - } -} - -/** - * e1000_clean_tx_irq - Reclaim resources after transmit completes - * @tx_ring: Tx descriptor ring - * - * the return value indicates whether actual cleaning was done, there - * is no guarantee that everything was cleaned - **/ -static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - struct e1000_tx_desc *tx_desc, *eop_desc; - struct e1000_buffer *buffer_info; - unsigned int i, eop; - unsigned int count = 0; - unsigned int total_tx_bytes = 0, total_tx_packets = 0; - unsigned int bytes_compl = 0, pkts_compl = 0; - - i = tx_ring->next_to_clean; - eop = tx_ring->buffer_info[i].next_to_watch; - eop_desc = E1000_TX_DESC(*tx_ring, eop); - - while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && - (count < tx_ring->count)) { - bool cleaned = false; - rmb(); /* read buffer_info after eop_desc */ - for (; !cleaned; count++) { - tx_desc = E1000_TX_DESC(*tx_ring, i); - buffer_info = &tx_ring->buffer_info[i]; - cleaned = (i == eop); - - if (cleaned) { - total_tx_packets += buffer_info->segs; - total_tx_bytes += buffer_info->bytecount; - if (buffer_info->skb) { - bytes_compl += buffer_info->skb->len; - pkts_compl++; - } - } - - e1000_put_txbuf(tx_ring, buffer_info); - tx_desc->upper.data = 0; - - i++; - if (i == tx_ring->count) - i = 0; - } - - if (i == tx_ring->next_to_use) - break; - eop = tx_ring->buffer_info[i].next_to_watch; - eop_desc = E1000_TX_DESC(*tx_ring, eop); - } - - tx_ring->next_to_clean = i; - - netdev_completed_queue(netdev, pkts_compl, bytes_compl); - -#define TX_WAKE_THRESHOLD 32 - if (count && netif_carrier_ok(netdev) && - e1000_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD) { - /* Make sure that anybody stopping the queue after this - * sees the new next_to_clean. - */ - smp_mb(); - - if (netif_queue_stopped(netdev) && - !(test_bit(__E1000_DOWN, &adapter->state))) { - netif_wake_queue(netdev); - ++adapter->restart_queue; - } - } - - if (adapter->detect_tx_hung) { - /* Detect a transmit hang in hardware, this serializes the - * check with the clearing of time_stamp and movement of i - */ - adapter->detect_tx_hung = false; - if (tx_ring->buffer_info[i].time_stamp && - time_after(jiffies, tx_ring->buffer_info[i].time_stamp - + (adapter->tx_timeout_factor * HZ)) && - !(er32(STATUS) & E1000_STATUS_TXOFF)) - schedule_work(&adapter->print_hang_task); - else - adapter->tx_hang_recheck = false; - } - adapter->total_tx_bytes += total_tx_bytes; - adapter->total_tx_packets += total_tx_packets; - return count < tx_ring->count; -} - -/** - * e1000_clean_rx_irq_ps - Send received data up the network stack; packet split - * @rx_ring: Rx descriptor ring - * - * the return value indicates whether actual cleaning was done, there - * is no guarantee that everything was cleaned - **/ -static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done, - int work_to_do) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct e1000_hw *hw = &adapter->hw; - union e1000_rx_desc_packet_split *rx_desc, *next_rxd; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_buffer *buffer_info, *next_buffer; - struct e1000_ps_page *ps_page; - struct sk_buff *skb; - unsigned int i, j; - u32 length, staterr; - int cleaned_count = 0; - bool cleaned = false; - unsigned int total_rx_bytes = 0, total_rx_packets = 0; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC_PS(*rx_ring, i); - staterr = le32_to_cpu(rx_desc->wb.middle.status_error); - buffer_info = &rx_ring->buffer_info[i]; - - while (staterr & E1000_RXD_STAT_DD) { - if (*work_done >= work_to_do) - break; - (*work_done)++; - skb = buffer_info->skb; - rmb(); /* read descriptor and rx_buffer_info after status DD */ - - /* in the packet split case this is header only */ - prefetch(skb->data - NET_IP_ALIGN); - - i++; - if (i == rx_ring->count) - i = 0; - next_rxd = E1000_RX_DESC_PS(*rx_ring, i); - prefetch(next_rxd); - - next_buffer = &rx_ring->buffer_info[i]; - - cleaned = true; - cleaned_count++; - dma_unmap_single(&pdev->dev, buffer_info->dma, - adapter->rx_ps_bsize0, DMA_FROM_DEVICE); - buffer_info->dma = 0; - - /* see !EOP comment in other Rx routine */ - if (!(staterr & E1000_RXD_STAT_EOP)) - adapter->flags2 |= FLAG2_IS_DISCARDING; - - if (adapter->flags2 & FLAG2_IS_DISCARDING) { - e_dbg("Packet Split buffers didn't pick up the full packet\n"); - dev_kfree_skb_irq(skb); - if (staterr & E1000_RXD_STAT_EOP) - adapter->flags2 &= ~FLAG2_IS_DISCARDING; - goto next_desc; - } - - if (unlikely((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) && - !(netdev->features & NETIF_F_RXALL))) { - dev_kfree_skb_irq(skb); - goto next_desc; - } - - length = le16_to_cpu(rx_desc->wb.middle.length0); - - if (!length) { - e_dbg("Last part of the packet spanning multiple descriptors\n"); - dev_kfree_skb_irq(skb); - goto next_desc; - } - - /* Good Receive */ - skb_put(skb, length); - - { - /* this looks ugly, but it seems compiler issues make - * it more efficient than reusing j - */ - int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]); - - /* page alloc/put takes too long and effects small - * packet throughput, so unsplit small packets and - * save the alloc/put only valid in softirq (napi) - * context to call kmap_* - */ - if (l1 && (l1 <= copybreak) && - ((length + l1) <= adapter->rx_ps_bsize0)) { - u8 *vaddr; - - ps_page = &buffer_info->ps_pages[0]; - - /* there is no documentation about how to call - * kmap_atomic, so we can't hold the mapping - * very long - */ - dma_sync_single_for_cpu(&pdev->dev, - ps_page->dma, - PAGE_SIZE, - DMA_FROM_DEVICE); - vaddr = kmap_atomic(ps_page->page); - memcpy(skb_tail_pointer(skb), vaddr, l1); - kunmap_atomic(vaddr); - dma_sync_single_for_device(&pdev->dev, - ps_page->dma, - PAGE_SIZE, - DMA_FROM_DEVICE); - - /* remove the CRC */ - if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) { - if (!(netdev->features & NETIF_F_RXFCS)) - l1 -= 4; - } - - skb_put(skb, l1); - goto copydone; - } /* if */ - } - - for (j = 0; j < PS_PAGE_BUFFERS; j++) { - length = le16_to_cpu(rx_desc->wb.upper.length[j]); - if (!length) - break; - - ps_page = &buffer_info->ps_pages[j]; - dma_unmap_page(&pdev->dev, ps_page->dma, PAGE_SIZE, - DMA_FROM_DEVICE); - ps_page->dma = 0; - skb_fill_page_desc(skb, j, ps_page->page, 0, length); - ps_page->page = NULL; - skb->len += length; - skb->data_len += length; - skb->truesize += PAGE_SIZE; - } - - /* strip the ethernet crc, problem is we're using pages now so - * this whole operation can get a little cpu intensive - */ - if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) { - if (!(netdev->features & NETIF_F_RXFCS)) - pskb_trim(skb, skb->len - 4); - } - -copydone: - total_rx_bytes += skb->len; - total_rx_packets++; - - e1000_rx_checksum(adapter, staterr, skb); - - e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); - - if (rx_desc->wb.upper.header_status & - cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)) - adapter->rx_hdr_split++; - - e1000_receive_skb(adapter, netdev, skb, staterr, - rx_desc->wb.middle.vlan); - -next_desc: - rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF); - buffer_info->skb = NULL; - - /* return some buffers to hardware, one at a time is too slow */ - if (cleaned_count >= E1000_RX_BUFFER_WRITE) { - adapter->alloc_rx_buf(rx_ring, cleaned_count, - GFP_ATOMIC); - cleaned_count = 0; - } - - /* use prefetched values */ - rx_desc = next_rxd; - buffer_info = next_buffer; - - staterr = le32_to_cpu(rx_desc->wb.middle.status_error); - } - rx_ring->next_to_clean = i; - - cleaned_count = e1000_desc_unused(rx_ring); - if (cleaned_count) - adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); - - adapter->total_rx_bytes += total_rx_bytes; - adapter->total_rx_packets += total_rx_packets; - return cleaned; -} - -/** - * e1000_consume_page - helper function - **/ -static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb, - u16 length) -{ - bi->page = NULL; - skb->len += length; - skb->data_len += length; - skb->truesize += PAGE_SIZE; -} - -/** - * e1000_clean_jumbo_rx_irq - Send received data up the network stack; legacy - * @adapter: board private structure - * - * the return value indicates whether actual cleaning was done, there - * is no guarantee that everything was cleaned - **/ -static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done, - int work_to_do) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - union e1000_rx_desc_extended *rx_desc, *next_rxd; - struct e1000_buffer *buffer_info, *next_buffer; - u32 length, staterr; - unsigned int i; - int cleaned_count = 0; - bool cleaned = false; - unsigned int total_rx_bytes = 0, total_rx_packets = 0; - struct skb_shared_info *shinfo; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); - buffer_info = &rx_ring->buffer_info[i]; - - while (staterr & E1000_RXD_STAT_DD) { - struct sk_buff *skb; - - if (*work_done >= work_to_do) - break; - (*work_done)++; - rmb(); /* read descriptor and rx_buffer_info after status DD */ - - skb = buffer_info->skb; - buffer_info->skb = NULL; - - ++i; - if (i == rx_ring->count) - i = 0; - next_rxd = E1000_RX_DESC_EXT(*rx_ring, i); - prefetch(next_rxd); - - next_buffer = &rx_ring->buffer_info[i]; - - cleaned = true; - cleaned_count++; - dma_unmap_page(&pdev->dev, buffer_info->dma, PAGE_SIZE, - DMA_FROM_DEVICE); - buffer_info->dma = 0; - - length = le16_to_cpu(rx_desc->wb.upper.length); - - /* errors is only valid for DD + EOP descriptors */ - if (unlikely((staterr & E1000_RXD_STAT_EOP) && - ((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) && - !(netdev->features & NETIF_F_RXALL)))) { - /* recycle both page and skb */ - buffer_info->skb = skb; - /* an error means any chain goes out the window too */ - if (rx_ring->rx_skb_top) - dev_kfree_skb_irq(rx_ring->rx_skb_top); - rx_ring->rx_skb_top = NULL; - goto next_desc; - } -#define rxtop (rx_ring->rx_skb_top) - if (!(staterr & E1000_RXD_STAT_EOP)) { - /* this descriptor is only the beginning (or middle) */ - if (!rxtop) { - /* this is the beginning of a chain */ - rxtop = skb; - skb_fill_page_desc(rxtop, 0, buffer_info->page, - 0, length); - } else { - /* this is the middle of a chain */ - shinfo = skb_shinfo(rxtop); - skb_fill_page_desc(rxtop, shinfo->nr_frags, - buffer_info->page, 0, - length); - /* re-use the skb, only consumed the page */ - buffer_info->skb = skb; - } - e1000_consume_page(buffer_info, rxtop, length); - goto next_desc; - } else { - if (rxtop) { - /* end of the chain */ - shinfo = skb_shinfo(rxtop); - skb_fill_page_desc(rxtop, shinfo->nr_frags, - buffer_info->page, 0, - length); - /* re-use the current skb, we only consumed the - * page - */ - buffer_info->skb = skb; - skb = rxtop; - rxtop = NULL; - e1000_consume_page(buffer_info, skb, length); - } else { - /* no chain, got EOP, this buf is the packet - * copybreak to save the put_page/alloc_page - */ - if (length <= copybreak && - skb_tailroom(skb) >= length) { - u8 *vaddr; - vaddr = kmap_atomic(buffer_info->page); - memcpy(skb_tail_pointer(skb), vaddr, - length); - kunmap_atomic(vaddr); - /* re-use the page, so don't erase - * buffer_info->page - */ - skb_put(skb, length); - } else { - skb_fill_page_desc(skb, 0, - buffer_info->page, 0, - length); - e1000_consume_page(buffer_info, skb, - length); - } - } - } - - /* Receive Checksum Offload */ - e1000_rx_checksum(adapter, staterr, skb); - - e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); - - /* probably a little skewed due to removing CRC */ - total_rx_bytes += skb->len; - total_rx_packets++; - - /* eth type trans needs skb->data to point to something */ - if (!pskb_may_pull(skb, ETH_HLEN)) { - e_err("pskb_may_pull failed.\n"); - dev_kfree_skb_irq(skb); - goto next_desc; - } - - e1000_receive_skb(adapter, netdev, skb, staterr, - rx_desc->wb.upper.vlan); - -next_desc: - rx_desc->wb.upper.status_error &= cpu_to_le32(~0xFF); - - /* return some buffers to hardware, one at a time is too slow */ - if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { - adapter->alloc_rx_buf(rx_ring, cleaned_count, - GFP_ATOMIC); - cleaned_count = 0; - } - - /* use prefetched values */ - rx_desc = next_rxd; - buffer_info = next_buffer; - - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); - } - rx_ring->next_to_clean = i; - - cleaned_count = e1000_desc_unused(rx_ring); - if (cleaned_count) - adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); - - adapter->total_rx_bytes += total_rx_bytes; - adapter->total_rx_packets += total_rx_packets; - return cleaned; -} - -/** - * e1000_clean_rx_ring - Free Rx Buffers per Queue - * @rx_ring: Rx descriptor ring - **/ -static void e1000_clean_rx_ring(struct e1000_ring *rx_ring) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct e1000_buffer *buffer_info; - struct e1000_ps_page *ps_page; - struct pci_dev *pdev = adapter->pdev; - unsigned int i, j; - - /* Free all the Rx ring sk_buffs */ - for (i = 0; i < rx_ring->count; i++) { - buffer_info = &rx_ring->buffer_info[i]; - if (buffer_info->dma) { - if (adapter->clean_rx == e1000_clean_rx_irq) - dma_unmap_single(&pdev->dev, buffer_info->dma, - adapter->rx_buffer_len, - DMA_FROM_DEVICE); - else if (adapter->clean_rx == e1000_clean_jumbo_rx_irq) - dma_unmap_page(&pdev->dev, buffer_info->dma, - PAGE_SIZE, DMA_FROM_DEVICE); - else if (adapter->clean_rx == e1000_clean_rx_irq_ps) - dma_unmap_single(&pdev->dev, buffer_info->dma, - adapter->rx_ps_bsize0, - DMA_FROM_DEVICE); - buffer_info->dma = 0; - } - - if (buffer_info->page) { - put_page(buffer_info->page); - buffer_info->page = NULL; - } - - if (buffer_info->skb) { - dev_kfree_skb(buffer_info->skb); - buffer_info->skb = NULL; - } - - for (j = 0; j < PS_PAGE_BUFFERS; j++) { - ps_page = &buffer_info->ps_pages[j]; - if (!ps_page->page) - break; - dma_unmap_page(&pdev->dev, ps_page->dma, PAGE_SIZE, - DMA_FROM_DEVICE); - ps_page->dma = 0; - put_page(ps_page->page); - ps_page->page = NULL; - } - } - - /* there also may be some cached data from a chained receive */ - if (rx_ring->rx_skb_top) { - dev_kfree_skb(rx_ring->rx_skb_top); - rx_ring->rx_skb_top = NULL; - } - - /* Zero out the descriptor ring */ - memset(rx_ring->desc, 0, rx_ring->size); - - rx_ring->next_to_clean = 0; - rx_ring->next_to_use = 0; - adapter->flags2 &= ~FLAG2_IS_DISCARDING; - - writel(0, rx_ring->head); - if (rx_ring->adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_rdt_wa(rx_ring, 0); - else - writel(0, rx_ring->tail); -} - -static void e1000e_downshift_workaround(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - downshift_task); - - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - - e1000e_gig_downshift_workaround_ich8lan(&adapter->hw); -} - -/** - * e1000_intr_msi - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - **/ -static irqreturn_t e1000_intr_msi(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 icr = er32(ICR); - - /* read ICR disables interrupts using IAM */ - if (icr & E1000_ICR_LSC) { - hw->mac.get_link_status = true; - /* ICH8 workaround-- Call gig speed drop workaround on cable - * disconnect (LSC) before accessing any PHY registers - */ - if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && - (!(er32(STATUS) & E1000_STATUS_LU))) - schedule_work(&adapter->downshift_task); - - /* 80003ES2LAN workaround-- For packet buffer work-around on - * link down event; disable receives here in the ISR and reset - * adapter in watchdog - */ - if (netif_carrier_ok(netdev) && - adapter->flags & FLAG_RX_NEEDS_RESTART) { - /* disable receives */ - u32 rctl = er32(RCTL); - ew32(RCTL, rctl & ~E1000_RCTL_EN); - adapter->flags |= FLAG_RESTART_NOW; - } - /* guard against interrupt when we're going down */ - if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_timer(&adapter->watchdog_timer, jiffies + 1); - } - - /* Reset on uncorrectable ECC error */ - if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) { - u32 pbeccsts = er32(PBECCSTS); - - adapter->corr_errors += - pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; - adapter->uncorr_errors += - (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> - E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; - - /* Do the reset outside of interrupt context */ - schedule_work(&adapter->reset_task); - - /* return immediately since reset is imminent */ - return IRQ_HANDLED; - } - - if (napi_schedule_prep(&adapter->napi)) { - adapter->total_tx_bytes = 0; - adapter->total_tx_packets = 0; - adapter->total_rx_bytes = 0; - adapter->total_rx_packets = 0; - __napi_schedule(&adapter->napi); - } - - return IRQ_HANDLED; -} - -/** - * e1000_intr - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - **/ -static irqreturn_t e1000_intr(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 rctl, icr = er32(ICR); - - if (!icr || test_bit(__E1000_DOWN, &adapter->state)) - return IRQ_NONE; /* Not our interrupt */ - - /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is - * not set, then the adapter didn't send an interrupt - */ - if (!(icr & E1000_ICR_INT_ASSERTED)) - return IRQ_NONE; - - /* Interrupt Auto-Mask...upon reading ICR, - * interrupts are masked. No need for the - * IMC write - */ - - if (icr & E1000_ICR_LSC) { - hw->mac.get_link_status = true; - /* ICH8 workaround-- Call gig speed drop workaround on cable - * disconnect (LSC) before accessing any PHY registers - */ - if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && - (!(er32(STATUS) & E1000_STATUS_LU))) - schedule_work(&adapter->downshift_task); - - /* 80003ES2LAN workaround-- - * For packet buffer work-around on link down event; - * disable receives here in the ISR and - * reset adapter in watchdog - */ - if (netif_carrier_ok(netdev) && - (adapter->flags & FLAG_RX_NEEDS_RESTART)) { - /* disable receives */ - rctl = er32(RCTL); - ew32(RCTL, rctl & ~E1000_RCTL_EN); - adapter->flags |= FLAG_RESTART_NOW; - } - /* guard against interrupt when we're going down */ - if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_timer(&adapter->watchdog_timer, jiffies + 1); - } - - /* Reset on uncorrectable ECC error */ - if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) { - u32 pbeccsts = er32(PBECCSTS); - - adapter->corr_errors += - pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; - adapter->uncorr_errors += - (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> - E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; - - /* Do the reset outside of interrupt context */ - schedule_work(&adapter->reset_task); - - /* return immediately since reset is imminent */ - return IRQ_HANDLED; - } - - if (napi_schedule_prep(&adapter->napi)) { - adapter->total_tx_bytes = 0; - adapter->total_tx_packets = 0; - adapter->total_rx_bytes = 0; - adapter->total_rx_packets = 0; - __napi_schedule(&adapter->napi); - } - - return IRQ_HANDLED; -} - -static irqreturn_t e1000_msix_other(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 icr = er32(ICR); - - if (!(icr & E1000_ICR_INT_ASSERTED)) { - if (!test_bit(__E1000_DOWN, &adapter->state)) - ew32(IMS, E1000_IMS_OTHER); - return IRQ_NONE; - } - - if (icr & adapter->eiac_mask) - ew32(ICS, (icr & adapter->eiac_mask)); - - if (icr & E1000_ICR_OTHER) { - if (!(icr & E1000_ICR_LSC)) - goto no_link_interrupt; - hw->mac.get_link_status = true; - /* guard against interrupt when we're going down */ - if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_timer(&adapter->watchdog_timer, jiffies + 1); - } - -no_link_interrupt: - if (!test_bit(__E1000_DOWN, &adapter->state)) - ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER); - - return IRQ_HANDLED; -} - -static irqreturn_t e1000_intr_msix_tx(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct e1000_ring *tx_ring = adapter->tx_ring; - - adapter->total_tx_bytes = 0; - adapter->total_tx_packets = 0; - - if (!e1000_clean_tx_irq(tx_ring)) - /* Ring was not completely cleaned, so fire another interrupt */ - ew32(ICS, tx_ring->ims_val); - - return IRQ_HANDLED; -} - -static irqreturn_t e1000_intr_msix_rx(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_ring *rx_ring = adapter->rx_ring; - - /* Write the ITR value calculated at the end of the - * previous interrupt. - */ - if (rx_ring->set_itr) { - writel(1000000000 / (rx_ring->itr_val * 256), - rx_ring->itr_register); - rx_ring->set_itr = 0; - } - - if (napi_schedule_prep(&adapter->napi)) { - adapter->total_rx_bytes = 0; - adapter->total_rx_packets = 0; - __napi_schedule(&adapter->napi); - } - return IRQ_HANDLED; -} - -/** - * e1000_configure_msix - Configure MSI-X hardware - * - * e1000_configure_msix sets up the hardware to properly - * generate MSI-X interrupts. - **/ -static void e1000_configure_msix(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_ring *rx_ring = adapter->rx_ring; - struct e1000_ring *tx_ring = adapter->tx_ring; - int vector = 0; - u32 ctrl_ext, ivar = 0; - - adapter->eiac_mask = 0; - - /* Workaround issue with spurious interrupts on 82574 in MSI-X mode */ - if (hw->mac.type == e1000_82574) { - u32 rfctl = er32(RFCTL); - rfctl |= E1000_RFCTL_ACK_DIS; - ew32(RFCTL, rfctl); - } - - /* Configure Rx vector */ - rx_ring->ims_val = E1000_IMS_RXQ0; - adapter->eiac_mask |= rx_ring->ims_val; - if (rx_ring->itr_val) - writel(1000000000 / (rx_ring->itr_val * 256), - rx_ring->itr_register); - else - writel(1, rx_ring->itr_register); - ivar = E1000_IVAR_INT_ALLOC_VALID | vector; - - /* Configure Tx vector */ - tx_ring->ims_val = E1000_IMS_TXQ0; - vector++; - if (tx_ring->itr_val) - writel(1000000000 / (tx_ring->itr_val * 256), - tx_ring->itr_register); - else - writel(1, tx_ring->itr_register); - adapter->eiac_mask |= tx_ring->ims_val; - ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 8); - - /* set vector for Other Causes, e.g. link changes */ - vector++; - ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 16); - if (rx_ring->itr_val) - writel(1000000000 / (rx_ring->itr_val * 256), - hw->hw_addr + E1000_EITR_82574(vector)); - else - writel(1, hw->hw_addr + E1000_EITR_82574(vector)); - - /* Cause Tx interrupts on every write back */ - ivar |= (1 << 31); - - ew32(IVAR, ivar); - - /* enable MSI-X PBA support */ - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_PBA_CLR; - - /* Auto-Mask Other interrupts upon ICR read */ - ew32(IAM, ~E1000_EIAC_MASK_82574 | E1000_IMS_OTHER); - ctrl_ext |= E1000_CTRL_EXT_EIAME; - ew32(CTRL_EXT, ctrl_ext); - e1e_flush(); -} - -void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter) -{ - if (adapter->msix_entries) { - pci_disable_msix(adapter->pdev); - kfree(adapter->msix_entries); - adapter->msix_entries = NULL; - } else if (adapter->flags & FLAG_MSI_ENABLED) { - pci_disable_msi(adapter->pdev); - adapter->flags &= ~FLAG_MSI_ENABLED; - } -} - -/** - * e1000e_set_interrupt_capability - set MSI or MSI-X if supported - * - * Attempt to configure interrupts using the best available - * capabilities of the hardware and kernel. - **/ -void e1000e_set_interrupt_capability(struct e1000_adapter *adapter) -{ - int err; - int i; - - switch (adapter->int_mode) { - case E1000E_INT_MODE_MSIX: - if (adapter->flags & FLAG_HAS_MSIX) { - adapter->num_vectors = 3; /* RxQ0, TxQ0 and other */ - adapter->msix_entries = kcalloc(adapter->num_vectors, - sizeof(struct - msix_entry), - GFP_KERNEL); - if (adapter->msix_entries) { - for (i = 0; i < adapter->num_vectors; i++) - adapter->msix_entries[i].entry = i; - - err = pci_enable_msix(adapter->pdev, - adapter->msix_entries, - adapter->num_vectors); - if (err == 0) - return; - } - /* MSI-X failed, so fall through and try MSI */ - e_err("Failed to initialize MSI-X interrupts. Falling back to MSI interrupts.\n"); - e1000e_reset_interrupt_capability(adapter); - } - adapter->int_mode = E1000E_INT_MODE_MSI; - /* Fall through */ - case E1000E_INT_MODE_MSI: - if (!pci_enable_msi(adapter->pdev)) { - adapter->flags |= FLAG_MSI_ENABLED; - } else { - adapter->int_mode = E1000E_INT_MODE_LEGACY; - e_err("Failed to initialize MSI interrupts. Falling back to legacy interrupts.\n"); - } - /* Fall through */ - case E1000E_INT_MODE_LEGACY: - /* Don't do anything; this is the system default */ - break; - } - - /* store the number of vectors being used */ - adapter->num_vectors = 1; -} - -/** - * e1000_request_msix - Initialize MSI-X interrupts - * - * e1000_request_msix allocates MSI-X vectors and requests interrupts from the - * kernel. - **/ -static int e1000_request_msix(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - int err = 0, vector = 0; - - if (strlen(netdev->name) < (IFNAMSIZ - 5)) - snprintf(adapter->rx_ring->name, - sizeof(adapter->rx_ring->name) - 1, - "%s-rx-0", netdev->name); - else - memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ); - err = request_irq(adapter->msix_entries[vector].vector, - e1000_intr_msix_rx, 0, adapter->rx_ring->name, - netdev); - if (err) - return err; - adapter->rx_ring->itr_register = adapter->hw.hw_addr + - E1000_EITR_82574(vector); - adapter->rx_ring->itr_val = adapter->itr; - vector++; - - if (strlen(netdev->name) < (IFNAMSIZ - 5)) - snprintf(adapter->tx_ring->name, - sizeof(adapter->tx_ring->name) - 1, - "%s-tx-0", netdev->name); - else - memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ); - err = request_irq(adapter->msix_entries[vector].vector, - e1000_intr_msix_tx, 0, adapter->tx_ring->name, - netdev); - if (err) - return err; - adapter->tx_ring->itr_register = adapter->hw.hw_addr + - E1000_EITR_82574(vector); - adapter->tx_ring->itr_val = adapter->itr; - vector++; - - err = request_irq(adapter->msix_entries[vector].vector, - e1000_msix_other, 0, netdev->name, netdev); - if (err) - return err; - - e1000_configure_msix(adapter); - - return 0; -} - -/** - * e1000_request_irq - initialize interrupts - * - * Attempts to configure interrupts using the best available - * capabilities of the hardware and kernel. - **/ -static int e1000_request_irq(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - int err; - - if (adapter->msix_entries) { - err = e1000_request_msix(adapter); - if (!err) - return err; - /* fall back to MSI */ - e1000e_reset_interrupt_capability(adapter); - adapter->int_mode = E1000E_INT_MODE_MSI; - e1000e_set_interrupt_capability(adapter); - } - if (adapter->flags & FLAG_MSI_ENABLED) { - err = request_irq(adapter->pdev->irq, e1000_intr_msi, 0, - netdev->name, netdev); - if (!err) - return err; - - /* fall back to legacy interrupt */ - e1000e_reset_interrupt_capability(adapter); - adapter->int_mode = E1000E_INT_MODE_LEGACY; - } - - err = request_irq(adapter->pdev->irq, e1000_intr, IRQF_SHARED, - netdev->name, netdev); - if (err) - e_err("Unable to allocate interrupt, Error: %d\n", err); - - return err; -} - -static void e1000_free_irq(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - if (adapter->msix_entries) { - int vector = 0; - - free_irq(adapter->msix_entries[vector].vector, netdev); - vector++; - - free_irq(adapter->msix_entries[vector].vector, netdev); - vector++; - - /* Other Causes interrupt vector */ - free_irq(adapter->msix_entries[vector].vector, netdev); - return; - } - - free_irq(adapter->pdev->irq, netdev); -} - -/** - * e1000_irq_disable - Mask off interrupt generation on the NIC - **/ -static void e1000_irq_disable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - ew32(IMC, ~0); - if (adapter->msix_entries) - ew32(EIAC_82574, 0); - e1e_flush(); - - if (adapter->msix_entries) { - int i; - for (i = 0; i < adapter->num_vectors; i++) - synchronize_irq(adapter->msix_entries[i].vector); - } else { - synchronize_irq(adapter->pdev->irq); - } -} - -/** - * e1000_irq_enable - Enable default interrupt generation settings - **/ -static void e1000_irq_enable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - if (adapter->msix_entries) { - ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574); - ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC); - } else if (hw->mac.type == e1000_pch_lpt) { - ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER); - } else { - ew32(IMS, IMS_ENABLE_MASK); - } - e1e_flush(); -} - -/** - * e1000e_get_hw_control - get control of the h/w from f/w - * @adapter: address of board private structure - * - * e1000e_get_hw_control sets {CTRL_EXT|SWSM}:DRV_LOAD bit. - * For ASF and Pass Through versions of f/w this means that - * the driver is loaded. For AMT version (only with 82573) - * of the f/w this means that the network i/f is open. - **/ -void e1000e_get_hw_control(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl_ext; - u32 swsm; - - /* Let firmware know the driver has taken over */ - if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) { - swsm = er32(SWSM); - ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD); - } else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) { - ctrl_ext = er32(CTRL_EXT); - ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); - } -} - -/** - * e1000e_release_hw_control - release control of the h/w to f/w - * @adapter: address of board private structure - * - * e1000e_release_hw_control resets {CTRL_EXT|SWSM}:DRV_LOAD bit. - * For ASF and Pass Through versions of f/w this means that the - * driver is no longer loaded. For AMT version (only with 82573) i - * of the f/w this means that the network i/f is closed. - * - **/ -void e1000e_release_hw_control(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl_ext; - u32 swsm; - - /* Let firmware taken over control of h/w */ - if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) { - swsm = er32(SWSM); - ew32(SWSM, swsm & ~E1000_SWSM_DRV_LOAD); - } else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) { - ctrl_ext = er32(CTRL_EXT); - ew32(CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); - } -} - -/** - * e1000_alloc_ring_dma - allocate memory for a ring structure - **/ -static int e1000_alloc_ring_dma(struct e1000_adapter *adapter, - struct e1000_ring *ring) -{ - struct pci_dev *pdev = adapter->pdev; - - ring->desc = dma_alloc_coherent(&pdev->dev, ring->size, &ring->dma, - GFP_KERNEL); - if (!ring->desc) - return -ENOMEM; - - return 0; -} - -/** - * e1000e_setup_tx_resources - allocate Tx resources (Descriptors) - * @tx_ring: Tx descriptor ring - * - * Return 0 on success, negative on failure - **/ -int e1000e_setup_tx_resources(struct e1000_ring *tx_ring) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - int err = -ENOMEM, size; - - size = sizeof(struct e1000_buffer) * tx_ring->count; - tx_ring->buffer_info = vzalloc(size); - if (!tx_ring->buffer_info) - goto err; - - /* round up to nearest 4K */ - tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); - tx_ring->size = ALIGN(tx_ring->size, 4096); - - err = e1000_alloc_ring_dma(adapter, tx_ring); - if (err) - goto err; - - tx_ring->next_to_use = 0; - tx_ring->next_to_clean = 0; - - return 0; -err: - vfree(tx_ring->buffer_info); - e_err("Unable to allocate memory for the transmit descriptor ring\n"); - return err; -} - -/** - * e1000e_setup_rx_resources - allocate Rx resources (Descriptors) - * @rx_ring: Rx descriptor ring - * - * Returns 0 on success, negative on failure - **/ -int e1000e_setup_rx_resources(struct e1000_ring *rx_ring) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct e1000_buffer *buffer_info; - int i, size, desc_len, err = -ENOMEM; - - size = sizeof(struct e1000_buffer) * rx_ring->count; - rx_ring->buffer_info = vzalloc(size); - if (!rx_ring->buffer_info) - goto err; - - for (i = 0; i < rx_ring->count; i++) { - buffer_info = &rx_ring->buffer_info[i]; - buffer_info->ps_pages = kcalloc(PS_PAGE_BUFFERS, - sizeof(struct e1000_ps_page), - GFP_KERNEL); - if (!buffer_info->ps_pages) - goto err_pages; - } - - desc_len = sizeof(union e1000_rx_desc_packet_split); - - /* Round up to nearest 4K */ - rx_ring->size = rx_ring->count * desc_len; - rx_ring->size = ALIGN(rx_ring->size, 4096); - - err = e1000_alloc_ring_dma(adapter, rx_ring); - if (err) - goto err_pages; - - rx_ring->next_to_clean = 0; - rx_ring->next_to_use = 0; - rx_ring->rx_skb_top = NULL; - - return 0; - -err_pages: - for (i = 0; i < rx_ring->count; i++) { - buffer_info = &rx_ring->buffer_info[i]; - kfree(buffer_info->ps_pages); - } -err: - vfree(rx_ring->buffer_info); - e_err("Unable to allocate memory for the receive descriptor ring\n"); - return err; -} - -/** - * e1000_clean_tx_ring - Free Tx Buffers - * @tx_ring: Tx descriptor ring - **/ -static void e1000_clean_tx_ring(struct e1000_ring *tx_ring) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct e1000_buffer *buffer_info; - unsigned long size; - unsigned int i; - - for (i = 0; i < tx_ring->count; i++) { - buffer_info = &tx_ring->buffer_info[i]; - e1000_put_txbuf(tx_ring, buffer_info); - } - - netdev_reset_queue(adapter->netdev); - size = sizeof(struct e1000_buffer) * tx_ring->count; - memset(tx_ring->buffer_info, 0, size); - - memset(tx_ring->desc, 0, tx_ring->size); - - tx_ring->next_to_use = 0; - tx_ring->next_to_clean = 0; - - writel(0, tx_ring->head); - if (tx_ring->adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_tdt_wa(tx_ring, 0); - else - writel(0, tx_ring->tail); -} - -/** - * e1000e_free_tx_resources - Free Tx Resources per Queue - * @tx_ring: Tx descriptor ring - * - * Free all transmit software resources - **/ -void e1000e_free_tx_resources(struct e1000_ring *tx_ring) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct pci_dev *pdev = adapter->pdev; - - e1000_clean_tx_ring(tx_ring); - - vfree(tx_ring->buffer_info); - tx_ring->buffer_info = NULL; - - dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, - tx_ring->dma); - tx_ring->desc = NULL; -} - -/** - * e1000e_free_rx_resources - Free Rx Resources - * @rx_ring: Rx descriptor ring - * - * Free all receive software resources - **/ -void e1000e_free_rx_resources(struct e1000_ring *rx_ring) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct pci_dev *pdev = adapter->pdev; - int i; - - e1000_clean_rx_ring(rx_ring); - - for (i = 0; i < rx_ring->count; i++) - kfree(rx_ring->buffer_info[i].ps_pages); - - vfree(rx_ring->buffer_info); - rx_ring->buffer_info = NULL; - - dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, - rx_ring->dma); - rx_ring->desc = NULL; -} - -/** - * e1000_update_itr - update the dynamic ITR value based on statistics - * @adapter: pointer to adapter - * @itr_setting: current adapter->itr - * @packets: the number of packets during this measurement interval - * @bytes: the number of bytes during this measurement interval - * - * Stores a new ITR value based on packets and byte - * counts during the last interrupt. The advantage of per interrupt - * computation is faster updates and more accurate ITR for the current - * traffic pattern. Constants in this function were computed - * based on theoretical maximum wire speed and thresholds were set based - * on testing data as well as attempting to minimize response time - * while increasing bulk throughput. This functionality is controlled - * by the InterruptThrottleRate module parameter. - **/ -static unsigned int e1000_update_itr(u16 itr_setting, int packets, int bytes) -{ - unsigned int retval = itr_setting; - - if (packets == 0) - return itr_setting; - - switch (itr_setting) { - case lowest_latency: - /* handle TSO and jumbo frames */ - if (bytes / packets > 8000) - retval = bulk_latency; - else if ((packets < 5) && (bytes > 512)) - retval = low_latency; - break; - case low_latency: /* 50 usec aka 20000 ints/s */ - if (bytes > 10000) { - /* this if handles the TSO accounting */ - if (bytes / packets > 8000) - retval = bulk_latency; - else if ((packets < 10) || ((bytes / packets) > 1200)) - retval = bulk_latency; - else if ((packets > 35)) - retval = lowest_latency; - } else if (bytes / packets > 2000) { - retval = bulk_latency; - } else if (packets <= 2 && bytes < 512) { - retval = lowest_latency; - } - break; - case bulk_latency: /* 250 usec aka 4000 ints/s */ - if (bytes > 25000) { - if (packets > 35) - retval = low_latency; - } else if (bytes < 6000) { - retval = low_latency; - } - break; - } - - return retval; -} - -static void e1000_set_itr(struct e1000_adapter *adapter) -{ - u16 current_itr; - u32 new_itr = adapter->itr; - - /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ - if (adapter->link_speed != SPEED_1000) { - current_itr = 0; - new_itr = 4000; - goto set_itr_now; - } - - if (adapter->flags2 & FLAG2_DISABLE_AIM) { - new_itr = 0; - goto set_itr_now; - } - - adapter->tx_itr = e1000_update_itr(adapter->tx_itr, - adapter->total_tx_packets, - adapter->total_tx_bytes); - /* conservative mode (itr 3) eliminates the lowest_latency setting */ - if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency) - adapter->tx_itr = low_latency; - - adapter->rx_itr = e1000_update_itr(adapter->rx_itr, - adapter->total_rx_packets, - adapter->total_rx_bytes); - /* conservative mode (itr 3) eliminates the lowest_latency setting */ - if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency) - adapter->rx_itr = low_latency; - - current_itr = max(adapter->rx_itr, adapter->tx_itr); - - /* counts and packets in update_itr are dependent on these numbers */ - switch (current_itr) { - case lowest_latency: - new_itr = 70000; - break; - case low_latency: - new_itr = 20000; /* aka hwitr = ~200 */ - break; - case bulk_latency: - new_itr = 4000; - break; - default: - break; - } - -set_itr_now: - if (new_itr != adapter->itr) { - /* this attempts to bias the interrupt rate towards Bulk - * by adding intermediate steps when interrupt rate is - * increasing - */ - new_itr = new_itr > adapter->itr ? - min(adapter->itr + (new_itr >> 2), new_itr) : new_itr; - adapter->itr = new_itr; - adapter->rx_ring->itr_val = new_itr; - if (adapter->msix_entries) - adapter->rx_ring->set_itr = 1; - else - e1000e_write_itr(adapter, new_itr); - } -} - -/** - * e1000e_write_itr - write the ITR value to the appropriate registers - * @adapter: address of board private structure - * @itr: new ITR value to program - * - * e1000e_write_itr determines if the adapter is in MSI-X mode - * and, if so, writes the EITR registers with the ITR value. - * Otherwise, it writes the ITR value into the ITR register. - **/ -void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr) -{ - struct e1000_hw *hw = &adapter->hw; - u32 new_itr = itr ? 1000000000 / (itr * 256) : 0; - - if (adapter->msix_entries) { - int vector; - - for (vector = 0; vector < adapter->num_vectors; vector++) - writel(new_itr, hw->hw_addr + E1000_EITR_82574(vector)); - } else { - ew32(ITR, new_itr); - } -} - -/** - * e1000_alloc_queues - Allocate memory for all rings - * @adapter: board private structure to initialize - **/ -static int e1000_alloc_queues(struct e1000_adapter *adapter) -{ - int size = sizeof(struct e1000_ring); - - adapter->tx_ring = kzalloc(size, GFP_KERNEL); - if (!adapter->tx_ring) - goto err; - adapter->tx_ring->count = adapter->tx_ring_count; - adapter->tx_ring->adapter = adapter; - - adapter->rx_ring = kzalloc(size, GFP_KERNEL); - if (!adapter->rx_ring) - goto err; - adapter->rx_ring->count = adapter->rx_ring_count; - adapter->rx_ring->adapter = adapter; - - return 0; -err: - e_err("Unable to allocate memory for queues\n"); - kfree(adapter->rx_ring); - kfree(adapter->tx_ring); - return -ENOMEM; -} - -/** - * e1000e_poll - NAPI Rx polling callback - * @napi: struct associated with this polling callback - * @weight: number of packets driver is allowed to process this poll - **/ -static int e1000e_poll(struct napi_struct *napi, int weight) -{ - struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, - napi); - struct e1000_hw *hw = &adapter->hw; - struct net_device *poll_dev = adapter->netdev; - int tx_cleaned = 1, work_done = 0; - - adapter = netdev_priv(poll_dev); - - if (!adapter->msix_entries || - (adapter->rx_ring->ims_val & adapter->tx_ring->ims_val)) - tx_cleaned = e1000_clean_tx_irq(adapter->tx_ring); - - adapter->clean_rx(adapter->rx_ring, &work_done, weight); - - if (!tx_cleaned) - work_done = weight; - - /* If weight not fully consumed, exit the polling mode */ - if (work_done < weight) { - if (adapter->itr_setting & 3) - e1000_set_itr(adapter); - napi_complete(napi); - if (!test_bit(__E1000_DOWN, &adapter->state)) { - if (adapter->msix_entries) - ew32(IMS, adapter->rx_ring->ims_val); - else - e1000_irq_enable(adapter); - } - } - - return work_done; -} - -static int e1000_vlan_rx_add_vid(struct net_device *netdev, - __be16 proto, u16 vid) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 vfta, index; - - /* don't update vlan cookie if already programmed */ - if ((adapter->hw.mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && - (vid == adapter->mng_vlan_id)) - return 0; - - /* add VID to filter table */ - if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { - index = (vid >> 5) & 0x7F; - vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); - vfta |= (1 << (vid & 0x1F)); - hw->mac.ops.write_vfta(hw, index, vfta); - } - - set_bit(vid, adapter->active_vlans); - - return 0; -} - -static int e1000_vlan_rx_kill_vid(struct net_device *netdev, - __be16 proto, u16 vid) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 vfta, index; - - if ((adapter->hw.mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && - (vid == adapter->mng_vlan_id)) { - /* release control to f/w */ - e1000e_release_hw_control(adapter); - return 0; - } - - /* remove VID from filter table */ - if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { - index = (vid >> 5) & 0x7F; - vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); - vfta &= ~(1 << (vid & 0x1F)); - hw->mac.ops.write_vfta(hw, index, vfta); - } - - clear_bit(vid, adapter->active_vlans); - - return 0; -} - -/** - * e1000e_vlan_filter_disable - helper to disable hw VLAN filtering - * @adapter: board private structure to initialize - **/ -static void e1000e_vlan_filter_disable(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { - /* disable VLAN receive filtering */ - rctl = er32(RCTL); - rctl &= ~(E1000_RCTL_VFE | E1000_RCTL_CFIEN); - ew32(RCTL, rctl); - - if (adapter->mng_vlan_id != (u16)E1000_MNG_VLAN_NONE) { - e1000_vlan_rx_kill_vid(netdev, htons(ETH_P_8021Q), - adapter->mng_vlan_id); - adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; - } - } -} - -/** - * e1000e_vlan_filter_enable - helper to enable HW VLAN filtering - * @adapter: board private structure to initialize - **/ -static void e1000e_vlan_filter_enable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { - /* enable VLAN receive filtering */ - rctl = er32(RCTL); - rctl |= E1000_RCTL_VFE; - rctl &= ~E1000_RCTL_CFIEN; - ew32(RCTL, rctl); - } -} - -/** - * e1000e_vlan_strip_enable - helper to disable HW VLAN stripping - * @adapter: board private structure to initialize - **/ -static void e1000e_vlan_strip_disable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl; - - /* disable VLAN tag insert/strip */ - ctrl = er32(CTRL); - ctrl &= ~E1000_CTRL_VME; - ew32(CTRL, ctrl); -} - -/** - * e1000e_vlan_strip_enable - helper to enable HW VLAN stripping - * @adapter: board private structure to initialize - **/ -static void e1000e_vlan_strip_enable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl; - - /* enable VLAN tag insert/strip */ - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_VME; - ew32(CTRL, ctrl); -} - -static void e1000_update_mng_vlan(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - u16 vid = adapter->hw.mng_cookie.vlan_id; - u16 old_vid = adapter->mng_vlan_id; - - if (adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) { - e1000_vlan_rx_add_vid(netdev, htons(ETH_P_8021Q), vid); - adapter->mng_vlan_id = vid; - } - - if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && (vid != old_vid)) - e1000_vlan_rx_kill_vid(netdev, htons(ETH_P_8021Q), old_vid); -} - -static void e1000_restore_vlan(struct e1000_adapter *adapter) -{ - u16 vid; - - e1000_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), 0); - - for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) - e1000_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid); -} - -static void e1000_init_manageability_pt(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 manc, manc2h, mdef, i, j; - - if (!(adapter->flags & FLAG_MNG_PT_ENABLED)) - return; - - manc = er32(MANC); - - /* enable receiving management packets to the host. this will probably - * generate destination unreachable messages from the host OS, but - * the packets will be handled on SMBUS - */ - manc |= E1000_MANC_EN_MNG2HOST; - manc2h = er32(MANC2H); - - switch (hw->mac.type) { - default: - manc2h |= (E1000_MANC2H_PORT_623 | E1000_MANC2H_PORT_664); - break; - case e1000_82574: - case e1000_82583: - /* Check if IPMI pass-through decision filter already exists; - * if so, enable it. - */ - for (i = 0, j = 0; i < 8; i++) { - mdef = er32(MDEF(i)); - - /* Ignore filters with anything other than IPMI ports */ - if (mdef & ~(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664)) - continue; - - /* Enable this decision filter in MANC2H */ - if (mdef) - manc2h |= (1 << i); - - j |= mdef; - } - - if (j == (E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664)) - break; - - /* Create new decision filter in an empty filter */ - for (i = 0, j = 0; i < 8; i++) - if (er32(MDEF(i)) == 0) { - ew32(MDEF(i), (E1000_MDEF_PORT_623 | - E1000_MDEF_PORT_664)); - manc2h |= (1 << 1); - j++; - break; - } - - if (!j) - e_warn("Unable to create IPMI pass-through filter\n"); - break; - } - - ew32(MANC2H, manc2h); - ew32(MANC, manc); -} - -/** - * e1000_configure_tx - Configure Transmit Unit after Reset - * @adapter: board private structure - * - * Configure the Tx unit of the MAC after a reset. - **/ -static void e1000_configure_tx(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_ring *tx_ring = adapter->tx_ring; - u64 tdba; - u32 tdlen, tarc; - - /* Setup the HW Tx Head and Tail descriptor pointers */ - tdba = tx_ring->dma; - tdlen = tx_ring->count * sizeof(struct e1000_tx_desc); - ew32(TDBAL(0), (tdba & DMA_BIT_MASK(32))); - ew32(TDBAH(0), (tdba >> 32)); - ew32(TDLEN(0), tdlen); - ew32(TDH(0), 0); - ew32(TDT(0), 0); - tx_ring->head = adapter->hw.hw_addr + E1000_TDH(0); - tx_ring->tail = adapter->hw.hw_addr + E1000_TDT(0); - - /* Set the Tx Interrupt Delay register */ - ew32(TIDV, adapter->tx_int_delay); - /* Tx irq moderation */ - ew32(TADV, adapter->tx_abs_int_delay); - - if (adapter->flags2 & FLAG2_DMA_BURST) { - u32 txdctl = er32(TXDCTL(0)); - txdctl &= ~(E1000_TXDCTL_PTHRESH | E1000_TXDCTL_HTHRESH | - E1000_TXDCTL_WTHRESH); - /* set up some performance related parameters to encourage the - * hardware to use the bus more efficiently in bursts, depends - * on the tx_int_delay to be enabled, - * wthresh = 1 ==> burst write is disabled to avoid Tx stalls - * hthresh = 1 ==> prefetch when one or more available - * pthresh = 0x1f ==> prefetch if internal cache 31 or less - * BEWARE: this seems to work but should be considered first if - * there are Tx hangs or other Tx related bugs - */ - txdctl |= E1000_TXDCTL_DMA_BURST_ENABLE; - ew32(TXDCTL(0), txdctl); - } - /* erratum work around: set txdctl the same for both queues */ - ew32(TXDCTL(1), er32(TXDCTL(0))); - - if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) { - tarc = er32(TARC(0)); - /* set the speed mode bit, we'll clear it if we're not at - * gigabit link later - */ -#define SPEED_MODE_BIT (1 << 21) - tarc |= SPEED_MODE_BIT; - ew32(TARC(0), tarc); - } - - /* errata: program both queues to unweighted RR */ - if (adapter->flags & FLAG_TARC_SET_BIT_ZERO) { - tarc = er32(TARC(0)); - tarc |= 1; - ew32(TARC(0), tarc); - tarc = er32(TARC(1)); - tarc |= 1; - ew32(TARC(1), tarc); - } - - /* Setup Transmit Descriptor Settings for eop descriptor */ - adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS; - - /* only set IDE if we are delaying interrupts using the timers */ - if (adapter->tx_int_delay) - adapter->txd_cmd |= E1000_TXD_CMD_IDE; - - /* enable Report Status bit */ - adapter->txd_cmd |= E1000_TXD_CMD_RS; - - hw->mac.ops.config_collision_dist(hw); -} - -/** - * e1000_setup_rctl - configure the receive control registers - * @adapter: Board private structure - **/ -#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \ - (((S) & (PAGE_SIZE - 1)) ? 1 : 0)) -static void e1000_setup_rctl(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl, rfctl; - u32 pages = 0; - - /* Workaround Si errata on PCHx - configure jumbo frame flow */ - if (hw->mac.type >= e1000_pch2lan) { - s32 ret_val; - - if (adapter->netdev->mtu > ETH_DATA_LEN) - ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true); - else - ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false); - - if (ret_val) - e_dbg("failed to enable jumbo frame workaround mode\n"); - } - - /* Program MC offset vector base */ - rctl = er32(RCTL); - rctl &= ~(3 << E1000_RCTL_MO_SHIFT); - rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | - E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | - (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); - - /* Do not Store bad packets */ - rctl &= ~E1000_RCTL_SBP; - - /* Enable Long Packet receive */ - if (adapter->netdev->mtu <= ETH_DATA_LEN) - rctl &= ~E1000_RCTL_LPE; - else - rctl |= E1000_RCTL_LPE; - - /* Some systems expect that the CRC is included in SMBUS traffic. The - * hardware strips the CRC before sending to both SMBUS (BMC) and to - * host memory when this is enabled - */ - if (adapter->flags2 & FLAG2_CRC_STRIPPING) - rctl |= E1000_RCTL_SECRC; - - /* Workaround Si errata on 82577 PHY - configure IPG for jumbos */ - if ((hw->phy.type == e1000_phy_82577) && (rctl & E1000_RCTL_LPE)) { - u16 phy_data; - - e1e_rphy(hw, PHY_REG(770, 26), &phy_data); - phy_data &= 0xfff8; - phy_data |= (1 << 2); - e1e_wphy(hw, PHY_REG(770, 26), phy_data); - - e1e_rphy(hw, 22, &phy_data); - phy_data &= 0x0fff; - phy_data |= (1 << 14); - e1e_wphy(hw, 0x10, 0x2823); - e1e_wphy(hw, 0x11, 0x0003); - e1e_wphy(hw, 22, phy_data); - } - - /* Setup buffer sizes */ - rctl &= ~E1000_RCTL_SZ_4096; - rctl |= E1000_RCTL_BSEX; - switch (adapter->rx_buffer_len) { - case 2048: - default: - rctl |= E1000_RCTL_SZ_2048; - rctl &= ~E1000_RCTL_BSEX; - break; - case 4096: - rctl |= E1000_RCTL_SZ_4096; - break; - case 8192: - rctl |= E1000_RCTL_SZ_8192; - break; - case 16384: - rctl |= E1000_RCTL_SZ_16384; - break; - } - - /* Enable Extended Status in all Receive Descriptors */ - rfctl = er32(RFCTL); - rfctl |= E1000_RFCTL_EXTEN; - ew32(RFCTL, rfctl); - - /* 82571 and greater support packet-split where the protocol - * header is placed in skb->data and the packet data is - * placed in pages hanging off of skb_shinfo(skb)->nr_frags. - * In the case of a non-split, skb->data is linearly filled, - * followed by the page buffers. Therefore, skb->data is - * sized to hold the largest protocol header. - * - * allocations using alloc_page take too long for regular MTU - * so only enable packet split for jumbo frames - * - * Using pages when the page size is greater than 16k wastes - * a lot of memory, since we allocate 3 pages at all times - * per packet. - */ - pages = PAGE_USE_COUNT(adapter->netdev->mtu); - if ((pages <= 3) && (PAGE_SIZE <= 16384) && (rctl & E1000_RCTL_LPE)) - adapter->rx_ps_pages = pages; - else - adapter->rx_ps_pages = 0; - - if (adapter->rx_ps_pages) { - u32 psrctl = 0; - - /* Enable Packet split descriptors */ - rctl |= E1000_RCTL_DTYP_PS; - - psrctl |= adapter->rx_ps_bsize0 >> E1000_PSRCTL_BSIZE0_SHIFT; - - switch (adapter->rx_ps_pages) { - case 3: - psrctl |= PAGE_SIZE << E1000_PSRCTL_BSIZE3_SHIFT; - /* fall-through */ - case 2: - psrctl |= PAGE_SIZE << E1000_PSRCTL_BSIZE2_SHIFT; - /* fall-through */ - case 1: - psrctl |= PAGE_SIZE >> E1000_PSRCTL_BSIZE1_SHIFT; - break; - } - - ew32(PSRCTL, psrctl); - } - - /* This is useful for sniffing bad packets. */ - if (adapter->netdev->features & NETIF_F_RXALL) { - /* UPE and MPE will be handled by normal PROMISC logic - * in e1000e_set_rx_mode - */ - rctl |= (E1000_RCTL_SBP | /* Receive bad packets */ - E1000_RCTL_BAM | /* RX All Bcast Pkts */ - E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */ - - rctl &= ~(E1000_RCTL_VFE | /* Disable VLAN filter */ - E1000_RCTL_DPF | /* Allow filtered pause */ - E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */ - /* Do not mess with E1000_CTRL_VME, it affects transmit as well, - * and that breaks VLANs. - */ - } - - ew32(RCTL, rctl); - /* just started the receive unit, no need to restart */ - adapter->flags &= ~FLAG_RESTART_NOW; -} - -/** - * e1000_configure_rx - Configure Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Rx unit of the MAC after a reset. - **/ -static void e1000_configure_rx(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_ring *rx_ring = adapter->rx_ring; - u64 rdba; - u32 rdlen, rctl, rxcsum, ctrl_ext; - - if (adapter->rx_ps_pages) { - /* this is a 32 byte descriptor */ - rdlen = rx_ring->count * - sizeof(union e1000_rx_desc_packet_split); - adapter->clean_rx = e1000_clean_rx_irq_ps; - adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps; - } else if (adapter->netdev->mtu > ETH_FRAME_LEN + ETH_FCS_LEN) { - rdlen = rx_ring->count * sizeof(union e1000_rx_desc_extended); - adapter->clean_rx = e1000_clean_jumbo_rx_irq; - adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers; - } else { - rdlen = rx_ring->count * sizeof(union e1000_rx_desc_extended); - adapter->clean_rx = e1000_clean_rx_irq; - adapter->alloc_rx_buf = e1000_alloc_rx_buffers; - } - - /* disable receives while setting up the descriptors */ - rctl = er32(RCTL); - if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX)) - ew32(RCTL, rctl & ~E1000_RCTL_EN); - e1e_flush(); - usleep_range(10000, 20000); - - if (adapter->flags2 & FLAG2_DMA_BURST) { - /* set the writeback threshold (only takes effect if the RDTR - * is set). set GRAN=1 and write back up to 0x4 worth, and - * enable prefetching of 0x20 Rx descriptors - * granularity = 01 - * wthresh = 04, - * hthresh = 04, - * pthresh = 0x20 - */ - ew32(RXDCTL(0), E1000_RXDCTL_DMA_BURST_ENABLE); - ew32(RXDCTL(1), E1000_RXDCTL_DMA_BURST_ENABLE); - - /* override the delay timers for enabling bursting, only if - * the value was not set by the user via module options - */ - if (adapter->rx_int_delay == DEFAULT_RDTR) - adapter->rx_int_delay = BURST_RDTR; - if (adapter->rx_abs_int_delay == DEFAULT_RADV) - adapter->rx_abs_int_delay = BURST_RADV; - } - - /* set the Receive Delay Timer Register */ - ew32(RDTR, adapter->rx_int_delay); - - /* irq moderation */ - ew32(RADV, adapter->rx_abs_int_delay); - if ((adapter->itr_setting != 0) && (adapter->itr != 0)) - e1000e_write_itr(adapter, adapter->itr); - - ctrl_ext = er32(CTRL_EXT); - /* Auto-Mask interrupts upon ICR access */ - ctrl_ext |= E1000_CTRL_EXT_IAME; - ew32(IAM, 0xffffffff); - ew32(CTRL_EXT, ctrl_ext); - e1e_flush(); - - /* Setup the HW Rx Head and Tail Descriptor Pointers and - * the Base and Length of the Rx Descriptor Ring - */ - rdba = rx_ring->dma; - ew32(RDBAL(0), (rdba & DMA_BIT_MASK(32))); - ew32(RDBAH(0), (rdba >> 32)); - ew32(RDLEN(0), rdlen); - ew32(RDH(0), 0); - ew32(RDT(0), 0); - rx_ring->head = adapter->hw.hw_addr + E1000_RDH(0); - rx_ring->tail = adapter->hw.hw_addr + E1000_RDT(0); - - /* Enable Receive Checksum Offload for TCP and UDP */ - rxcsum = er32(RXCSUM); - if (adapter->netdev->features & NETIF_F_RXCSUM) - rxcsum |= E1000_RXCSUM_TUOFL; - else - rxcsum &= ~E1000_RXCSUM_TUOFL; - ew32(RXCSUM, rxcsum); - - /* With jumbo frames, excessive C-state transition latencies result - * in dropped transactions. - */ - if (adapter->netdev->mtu > ETH_DATA_LEN) { - u32 lat = - ((er32(PBA) & E1000_PBA_RXA_MASK) * 1024 - - adapter->max_frame_size) * 8 / 1000; - - if (adapter->flags & FLAG_IS_ICH) { - u32 rxdctl = er32(RXDCTL(0)); - ew32(RXDCTL(0), rxdctl | 0x3); - } - - pm_qos_update_request(&adapter->netdev->pm_qos_req, lat); - } else { - pm_qos_update_request(&adapter->netdev->pm_qos_req, - PM_QOS_DEFAULT_VALUE); - } - - /* Enable Receives */ - ew32(RCTL, rctl); -} - -/** - * e1000e_write_mc_addr_list - write multicast addresses to MTA - * @netdev: network interface device structure - * - * Writes multicast address list to the MTA hash table. - * Returns: -ENOMEM on failure - * 0 on no addresses written - * X on writing X addresses to MTA - */ -static int e1000e_write_mc_addr_list(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct netdev_hw_addr *ha; - u8 *mta_list; - int i; - - if (netdev_mc_empty(netdev)) { - /* nothing to program, so clear mc list */ - hw->mac.ops.update_mc_addr_list(hw, NULL, 0); - return 0; - } - - mta_list = kzalloc(netdev_mc_count(netdev) * ETH_ALEN, GFP_ATOMIC); - if (!mta_list) - return -ENOMEM; - - /* update_mc_addr_list expects a packed array of only addresses. */ - i = 0; - netdev_for_each_mc_addr(ha, netdev) - memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN); - - hw->mac.ops.update_mc_addr_list(hw, mta_list, i); - kfree(mta_list); - - return netdev_mc_count(netdev); -} - -/** - * e1000e_write_uc_addr_list - write unicast addresses to RAR table - * @netdev: network interface device structure - * - * Writes unicast address list to the RAR table. - * Returns: -ENOMEM on failure/insufficient address space - * 0 on no addresses written - * X on writing X addresses to the RAR table - **/ -static int e1000e_write_uc_addr_list(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - unsigned int rar_entries = hw->mac.rar_entry_count; - int count = 0; - - /* save a rar entry for our hardware address */ - rar_entries--; - - /* save a rar entry for the LAA workaround */ - if (adapter->flags & FLAG_RESET_OVERWRITES_LAA) - rar_entries--; - - /* return ENOMEM indicating insufficient memory for addresses */ - if (netdev_uc_count(netdev) > rar_entries) - return -ENOMEM; - - if (!netdev_uc_empty(netdev) && rar_entries) { - struct netdev_hw_addr *ha; - - /* write the addresses in reverse order to avoid write - * combining - */ - netdev_for_each_uc_addr(ha, netdev) { - if (!rar_entries) - break; - hw->mac.ops.rar_set(hw, ha->addr, rar_entries--); - count++; - } - } - - /* zero out the remaining RAR entries not used above */ - for (; rar_entries > 0; rar_entries--) { - ew32(RAH(rar_entries), 0); - ew32(RAL(rar_entries), 0); - } - e1e_flush(); - - return count; -} - -/** - * e1000e_set_rx_mode - secondary unicast, Multicast and Promiscuous mode set - * @netdev: network interface device structure - * - * The ndo_set_rx_mode entry point is called whenever the unicast or multicast - * address list or the network interface flags are updated. This routine is - * responsible for configuring the hardware for proper unicast, multicast, - * promiscuous mode, and all-multi behavior. - **/ -static void e1000e_set_rx_mode(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - /* Check for Promiscuous and All Multicast modes */ - rctl = er32(RCTL); - - /* clear the affected bits */ - rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); - - if (netdev->flags & IFF_PROMISC) { - rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); - /* Do not hardware filter VLANs in promisc mode */ - e1000e_vlan_filter_disable(adapter); - } else { - int count; - - if (netdev->flags & IFF_ALLMULTI) { - rctl |= E1000_RCTL_MPE; - } else { - /* Write addresses to the MTA, if the attempt fails - * then we should just turn on promiscuous mode so - * that we can at least receive multicast traffic - */ - count = e1000e_write_mc_addr_list(netdev); - if (count < 0) - rctl |= E1000_RCTL_MPE; - } - e1000e_vlan_filter_enable(adapter); - /* Write addresses to available RAR registers, if there is not - * sufficient space to store all the addresses then enable - * unicast promiscuous mode - */ - count = e1000e_write_uc_addr_list(netdev); - if (count < 0) - rctl |= E1000_RCTL_UPE; - } - - ew32(RCTL, rctl); - - if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) - e1000e_vlan_strip_enable(adapter); - else - e1000e_vlan_strip_disable(adapter); -} - -static void e1000e_setup_rss_hash(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 mrqc, rxcsum; - int i; - static const u32 rsskey[10] = { - 0xda565a6d, 0xc20e5b25, 0x3d256741, 0xb08fa343, 0xcb2bcad0, - 0xb4307bae, 0xa32dcb77, 0x0cf23080, 0x3bb7426a, 0xfa01acbe - }; - - /* Fill out hash function seed */ - for (i = 0; i < 10; i++) - ew32(RSSRK(i), rsskey[i]); - - /* Direct all traffic to queue 0 */ - for (i = 0; i < 32; i++) - ew32(RETA(i), 0); - - /* Disable raw packet checksumming so that RSS hash is placed in - * descriptor on writeback. - */ - rxcsum = er32(RXCSUM); - rxcsum |= E1000_RXCSUM_PCSD; - - ew32(RXCSUM, rxcsum); - - mrqc = (E1000_MRQC_RSS_FIELD_IPV4 | - E1000_MRQC_RSS_FIELD_IPV4_TCP | - E1000_MRQC_RSS_FIELD_IPV6 | - E1000_MRQC_RSS_FIELD_IPV6_TCP | - E1000_MRQC_RSS_FIELD_IPV6_TCP_EX); - - ew32(MRQC, mrqc); -} - -/** - * e1000e_get_base_timinca - get default SYSTIM time increment attributes - * @adapter: board private structure - * @timinca: pointer to returned time increment attributes - * - * Get attributes for incrementing the System Time Register SYSTIML/H at - * the default base frequency, and set the cyclecounter shift value. - **/ -s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) -{ - struct e1000_hw *hw = &adapter->hw; - u32 incvalue, incperiod, shift; - - /* Make sure clock is enabled on I217 before checking the frequency */ - if ((hw->mac.type == e1000_pch_lpt) && - !(er32(TSYNCTXCTL) & E1000_TSYNCTXCTL_ENABLED) && - !(er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_ENABLED)) { - u32 fextnvm7 = er32(FEXTNVM7); - - if (!(fextnvm7 & (1 << 0))) { - ew32(FEXTNVM7, fextnvm7 | (1 << 0)); - e1e_flush(); - } - } - - switch (hw->mac.type) { - case e1000_pch2lan: - case e1000_pch_lpt: - /* On I217, the clock frequency is 25MHz or 96MHz as - * indicated by the System Clock Frequency Indication - */ - if ((hw->mac.type != e1000_pch_lpt) || - (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)) { - /* Stable 96MHz frequency */ - incperiod = INCPERIOD_96MHz; - incvalue = INCVALUE_96MHz; - shift = INCVALUE_SHIFT_96MHz; - adapter->cc.shift = shift + INCPERIOD_SHIFT_96MHz; - break; - } - /* fall-through */ - case e1000_82574: - case e1000_82583: - /* Stable 25MHz frequency */ - incperiod = INCPERIOD_25MHz; - incvalue = INCVALUE_25MHz; - shift = INCVALUE_SHIFT_25MHz; - adapter->cc.shift = shift; - break; - default: - return -EINVAL; - } - - *timinca = ((incperiod << E1000_TIMINCA_INCPERIOD_SHIFT) | - ((incvalue << shift) & E1000_TIMINCA_INCVALUE_MASK)); - - return 0; -} - -/** - * e1000e_config_hwtstamp - configure the hwtstamp registers and enable/disable - * @adapter: board private structure - * - * Outgoing time stamping can be enabled and disabled. Play nice and - * disable it when requested, although it shouldn't cause any overhead - * when no packet needs it. At most one packet in the queue may be - * marked for time stamping, otherwise it would be impossible to tell - * for sure to which packet the hardware time stamp belongs. - * - * Incoming time stamping has to be configured via the hardware filters. - * Not all combinations are supported, in particular event type has to be - * specified. Matching the kind of event packet is not supported, with the - * exception of "all V2 events regardless of level 2 or 4". - **/ -static int e1000e_config_hwtstamp(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct hwtstamp_config *config = &adapter->hwtstamp_config; - u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED; - u32 tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; - u32 rxmtrl = 0; - u16 rxudp = 0; - bool is_l4 = false; - bool is_l2 = false; - u32 regval; - s32 ret_val; - - if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP)) - return -EINVAL; - - /* flags reserved for future extensions - must be zero */ - if (config->flags) - return -EINVAL; - - switch (config->tx_type) { - case HWTSTAMP_TX_OFF: - tsync_tx_ctl = 0; - break; - case HWTSTAMP_TX_ON: - break; - default: - return -ERANGE; - } - - switch (config->rx_filter) { - case HWTSTAMP_FILTER_NONE: - tsync_rx_ctl = 0; - break; - case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; - rxmtrl = E1000_RXMTRL_PTP_V1_SYNC_MESSAGE; - is_l4 = true; - break; - case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; - rxmtrl = E1000_RXMTRL_PTP_V1_DELAY_REQ_MESSAGE; - is_l4 = true; - break; - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - /* Also time stamps V2 L2 Path Delay Request/Response */ - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_V2; - rxmtrl = E1000_RXMTRL_PTP_V2_SYNC_MESSAGE; - is_l2 = true; - break; - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - /* Also time stamps V2 L2 Path Delay Request/Response. */ - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_V2; - rxmtrl = E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE; - is_l2 = true; - break; - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - /* Hardware cannot filter just V2 L4 Sync messages; - * fall-through to V2 (both L2 and L4) Sync. - */ - case HWTSTAMP_FILTER_PTP_V2_SYNC: - /* Also time stamps V2 Path Delay Request/Response. */ - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; - rxmtrl = E1000_RXMTRL_PTP_V2_SYNC_MESSAGE; - is_l2 = true; - is_l4 = true; - break; - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - /* Hardware cannot filter just V2 L4 Delay Request messages; - * fall-through to V2 (both L2 and L4) Delay Request. - */ - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - /* Also time stamps V2 Path Delay Request/Response. */ - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; - rxmtrl = E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE; - is_l2 = true; - is_l4 = true; - break; - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - /* Hardware cannot filter just V2 L4 or L2 Event messages; - * fall-through to all V2 (both L2 and L4) Events. - */ - case HWTSTAMP_FILTER_PTP_V2_EVENT: - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2; - config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; - is_l2 = true; - is_l4 = true; - break; - case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: - /* For V1, the hardware can only filter Sync messages or - * Delay Request messages but not both so fall-through to - * time stamp all packets. - */ - case HWTSTAMP_FILTER_ALL: - is_l2 = true; - is_l4 = true; - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; - config->rx_filter = HWTSTAMP_FILTER_ALL; - break; - default: - return -ERANGE; - } - - /* enable/disable Tx h/w time stamping */ - regval = er32(TSYNCTXCTL); - regval &= ~E1000_TSYNCTXCTL_ENABLED; - regval |= tsync_tx_ctl; - ew32(TSYNCTXCTL, regval); - if ((er32(TSYNCTXCTL) & E1000_TSYNCTXCTL_ENABLED) != - (regval & E1000_TSYNCTXCTL_ENABLED)) { - e_err("Timesync Tx Control register not set as expected\n"); - return -EAGAIN; - } - - /* enable/disable Rx h/w time stamping */ - regval = er32(TSYNCRXCTL); - regval &= ~(E1000_TSYNCRXCTL_ENABLED | E1000_TSYNCRXCTL_TYPE_MASK); - regval |= tsync_rx_ctl; - ew32(TSYNCRXCTL, regval); - if ((er32(TSYNCRXCTL) & (E1000_TSYNCRXCTL_ENABLED | - E1000_TSYNCRXCTL_TYPE_MASK)) != - (regval & (E1000_TSYNCRXCTL_ENABLED | - E1000_TSYNCRXCTL_TYPE_MASK))) { - e_err("Timesync Rx Control register not set as expected\n"); - return -EAGAIN; - } - - /* L2: define ethertype filter for time stamped packets */ - if (is_l2) - rxmtrl |= ETH_P_1588; - - /* define which PTP packets get time stamped */ - ew32(RXMTRL, rxmtrl); - - /* Filter by destination port */ - if (is_l4) { - rxudp = PTP_EV_PORT; - cpu_to_be16s(&rxudp); - } - ew32(RXUDP, rxudp); - - e1e_flush(); - - /* Clear TSYNCRXCTL_VALID & TSYNCTXCTL_VALID bit */ - er32(RXSTMPH); - er32(TXSTMPH); - - /* Get and set the System Time Register SYSTIM base frequency */ - ret_val = e1000e_get_base_timinca(adapter, ®val); - if (ret_val) - return ret_val; - ew32(TIMINCA, regval); - - /* reset the ns time counter */ - timecounter_init(&adapter->tc, &adapter->cc, - ktime_to_ns(ktime_get_real())); - - return 0; -} - -/** - * e1000_configure - configure the hardware for Rx and Tx - * @adapter: private board structure - **/ -static void e1000_configure(struct e1000_adapter *adapter) -{ - struct e1000_ring *rx_ring = adapter->rx_ring; - - e1000e_set_rx_mode(adapter->netdev); - - e1000_restore_vlan(adapter); - e1000_init_manageability_pt(adapter); - - e1000_configure_tx(adapter); - - if (adapter->netdev->features & NETIF_F_RXHASH) - e1000e_setup_rss_hash(adapter); - e1000_setup_rctl(adapter); - e1000_configure_rx(adapter); - adapter->alloc_rx_buf(rx_ring, e1000_desc_unused(rx_ring), GFP_KERNEL); -} - -/** - * e1000e_power_up_phy - restore link in case the phy was powered down - * @adapter: address of board private structure - * - * The phy may be powered down to save power and turn off link when the - * driver is unloaded and wake on lan is not enabled (among others) - * *** this routine MUST be followed by a call to e1000e_reset *** - **/ -void e1000e_power_up_phy(struct e1000_adapter *adapter) -{ - if (adapter->hw.phy.ops.power_up) - adapter->hw.phy.ops.power_up(&adapter->hw); - - adapter->hw.mac.ops.setup_link(&adapter->hw); -} - -/** - * e1000_power_down_phy - Power down the PHY - * - * Power down the PHY so no link is implied when interface is down. - * The PHY cannot be powered down if management or WoL is active. - */ -static void e1000_power_down_phy(struct e1000_adapter *adapter) -{ - /* WoL is enabled */ - if (adapter->wol) - return; - - if (adapter->hw.phy.ops.power_down) - adapter->hw.phy.ops.power_down(&adapter->hw); -} - -/** - * e1000e_reset - bring the hardware into a known good state - * - * This function boots the hardware and enables some settings that - * require a configuration cycle of the hardware - those cannot be - * set/changed during runtime. After reset the device needs to be - * properly configured for Rx, Tx etc. - */ -void e1000e_reset(struct e1000_adapter *adapter) -{ - struct e1000_mac_info *mac = &adapter->hw.mac; - struct e1000_fc_info *fc = &adapter->hw.fc; - struct e1000_hw *hw = &adapter->hw; - u32 tx_space, min_tx_space, min_rx_space; - u32 pba = adapter->pba; - u16 hwm; - - /* reset Packet Buffer Allocation to default */ - ew32(PBA, pba); - - if (adapter->max_frame_size > ETH_FRAME_LEN + ETH_FCS_LEN) { - /* To maintain wire speed transmits, the Tx FIFO should be - * large enough to accommodate two full transmit packets, - * rounded up to the next 1KB and expressed in KB. Likewise, - * the Rx FIFO should be large enough to accommodate at least - * one full receive packet and is similarly rounded up and - * expressed in KB. - */ - pba = er32(PBA); - /* upper 16 bits has Tx packet buffer allocation size in KB */ - tx_space = pba >> 16; - /* lower 16 bits has Rx packet buffer allocation size in KB */ - pba &= 0xffff; - /* the Tx fifo also stores 16 bytes of information about the Tx - * but don't include ethernet FCS because hardware appends it - */ - min_tx_space = (adapter->max_frame_size + - sizeof(struct e1000_tx_desc) - ETH_FCS_LEN) * 2; - min_tx_space = ALIGN(min_tx_space, 1024); - min_tx_space >>= 10; - /* software strips receive CRC, so leave room for it */ - min_rx_space = adapter->max_frame_size; - min_rx_space = ALIGN(min_rx_space, 1024); - min_rx_space >>= 10; - - /* If current Tx allocation is less than the min Tx FIFO size, - * and the min Tx FIFO size is less than the current Rx FIFO - * allocation, take space away from current Rx allocation - */ - if ((tx_space < min_tx_space) && - ((min_tx_space - tx_space) < pba)) { - pba -= min_tx_space - tx_space; - - /* if short on Rx space, Rx wins and must trump Tx - * adjustment - */ - if (pba < min_rx_space) - pba = min_rx_space; - } - - ew32(PBA, pba); - } - - /* flow control settings - * - * The high water mark must be low enough to fit one full frame - * (or the size used for early receive) above it in the Rx FIFO. - * Set it to the lower of: - * - 90% of the Rx FIFO size, and - * - the full Rx FIFO size minus one full frame - */ - if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME) - fc->pause_time = 0xFFFF; - else - fc->pause_time = E1000_FC_PAUSE_TIME; - fc->send_xon = true; - fc->current_mode = fc->requested_mode; - - switch (hw->mac.type) { - case e1000_ich9lan: - case e1000_ich10lan: - if (adapter->netdev->mtu > ETH_DATA_LEN) { - pba = 14; - ew32(PBA, pba); - fc->high_water = 0x2800; - fc->low_water = fc->high_water - 8; - break; - } - /* fall-through */ - default: - hwm = min(((pba << 10) * 9 / 10), - ((pba << 10) - adapter->max_frame_size)); - - fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ - fc->low_water = fc->high_water - 8; - break; - case e1000_pchlan: - /* Workaround PCH LOM adapter hangs with certain network - * loads. If hangs persist, try disabling Tx flow control. - */ - if (adapter->netdev->mtu > ETH_DATA_LEN) { - fc->high_water = 0x3500; - fc->low_water = 0x1500; - } else { - fc->high_water = 0x5000; - fc->low_water = 0x3000; - } - fc->refresh_time = 0x1000; - break; - case e1000_pch2lan: - case e1000_pch_lpt: - fc->refresh_time = 0x0400; - - if (adapter->netdev->mtu <= ETH_DATA_LEN) { - fc->high_water = 0x05C20; - fc->low_water = 0x05048; - fc->pause_time = 0x0650; - break; - } - - fc->high_water = ((pba << 10) * 9 / 10) & E1000_FCRTH_RTH; - fc->low_water = ((pba << 10) * 8 / 10) & E1000_FCRTL_RTL; - break; - } - - /* Alignment of Tx data is on an arbitrary byte boundary with the - * maximum size per Tx descriptor limited only to the transmit - * allocation of the packet buffer minus 96 bytes with an upper - * limit of 24KB due to receive synchronization limitations. - */ - adapter->tx_fifo_limit = min_t(u32, ((er32(PBA) >> 16) << 10) - 96, - 24 << 10); - - /* Disable Adaptive Interrupt Moderation if 2 full packets cannot - * fit in receive buffer. - */ - if (adapter->itr_setting & 0x3) { - if ((adapter->max_frame_size * 2) > (pba << 10)) { - if (!(adapter->flags2 & FLAG2_DISABLE_AIM)) { - dev_info(&adapter->pdev->dev, - "Interrupt Throttle Rate off\n"); - adapter->flags2 |= FLAG2_DISABLE_AIM; - e1000e_write_itr(adapter, 0); - } - } else if (adapter->flags2 & FLAG2_DISABLE_AIM) { - dev_info(&adapter->pdev->dev, - "Interrupt Throttle Rate on\n"); - adapter->flags2 &= ~FLAG2_DISABLE_AIM; - adapter->itr = 20000; - e1000e_write_itr(adapter, adapter->itr); - } - } - - /* Allow time for pending master requests to run */ - mac->ops.reset_hw(hw); - - /* For parts with AMT enabled, let the firmware know - * that the network interface is in control - */ - if (adapter->flags & FLAG_HAS_AMT) - e1000e_get_hw_control(adapter); - - ew32(WUC, 0); - - if (mac->ops.init_hw(hw)) - e_err("Hardware Error\n"); - - e1000_update_mng_vlan(adapter); - - /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ - ew32(VET, ETH_P_8021Q); - - e1000e_reset_adaptive(hw); - - /* initialize systim and reset the ns time counter */ - e1000e_config_hwtstamp(adapter); - - /* Set EEE advertisement as appropriate */ - if (adapter->flags2 & FLAG2_HAS_EEE) { - s32 ret_val; - u16 adv_addr; - - switch (hw->phy.type) { - case e1000_phy_82579: - adv_addr = I82579_EEE_ADVERTISEMENT; - break; - case e1000_phy_i217: - adv_addr = I217_EEE_ADVERTISEMENT; - break; - default: - dev_err(&adapter->pdev->dev, - "Invalid PHY type setting EEE advertisement\n"); - return; - } - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) { - dev_err(&adapter->pdev->dev, - "EEE advertisement - unable to acquire PHY\n"); - return; - } - - e1000_write_emi_reg_locked(hw, adv_addr, - hw->dev_spec.ich8lan.eee_disable ? - 0 : adapter->eee_advert); - - hw->phy.ops.release(hw); - } - - if (!netif_running(adapter->netdev) && - !test_bit(__E1000_TESTING, &adapter->state)) { - e1000_power_down_phy(adapter); - return; - } - - e1000_get_phy_info(hw); - - if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && - !(adapter->flags & FLAG_SMART_POWER_DOWN)) { - u16 phy_data = 0; - /* speed up time to link by disabling smart power down, ignore - * the return value of this function because there is nothing - * different we would do if it failed - */ - e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data); - phy_data &= ~IGP02E1000_PM_SPD; - e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); - } -} - -int e1000e_up(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - /* hardware has been reset, we need to reload some things */ - e1000_configure(adapter); - - clear_bit(__E1000_DOWN, &adapter->state); - - if (adapter->msix_entries) - e1000_configure_msix(adapter); - e1000_irq_enable(adapter); - - netif_start_queue(adapter->netdev); - - /* fire a link change interrupt to start the watchdog */ - if (adapter->msix_entries) - ew32(ICS, E1000_ICS_LSC | E1000_ICR_OTHER); - else - ew32(ICS, E1000_ICS_LSC); - - return 0; -} - -static void e1000e_flush_descriptors(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - if (!(adapter->flags2 & FLAG2_DMA_BURST)) - return; - - /* flush pending descriptor writebacks to memory */ - ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); - ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD); - - /* execute the writes immediately */ - e1e_flush(); - - /* due to rare timing issues, write to TIDV/RDTR again to ensure the - * write is successful - */ - ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); - ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD); - - /* execute the writes immediately */ - e1e_flush(); -} - -static void e1000e_update_stats(struct e1000_adapter *adapter); - -void e1000e_down(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - u32 tctl, rctl; - - /* signal that we're down so the interrupt handler does not - * reschedule our watchdog timer - */ - set_bit(__E1000_DOWN, &adapter->state); - - /* disable receives in the hardware */ - rctl = er32(RCTL); - if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX)) - ew32(RCTL, rctl & ~E1000_RCTL_EN); - /* flush and sleep below */ - - netif_stop_queue(netdev); - - /* disable transmits in the hardware */ - tctl = er32(TCTL); - tctl &= ~E1000_TCTL_EN; - ew32(TCTL, tctl); - - /* flush both disables and wait for them to finish */ - e1e_flush(); - usleep_range(10000, 20000); - - e1000_irq_disable(adapter); - - napi_synchronize(&adapter->napi); - - del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->phy_info_timer); - - netif_carrier_off(netdev); - - spin_lock(&adapter->stats64_lock); - e1000e_update_stats(adapter); - spin_unlock(&adapter->stats64_lock); - - e1000e_flush_descriptors(adapter); - e1000_clean_tx_ring(adapter->tx_ring); - e1000_clean_rx_ring(adapter->rx_ring); - - adapter->link_speed = 0; - adapter->link_duplex = 0; - - if (!pci_channel_offline(adapter->pdev)) - e1000e_reset(adapter); - - /* TODO: for power management, we could drop the link and - * pci_disable_device here. - */ -} - -void e1000e_reinit_locked(struct e1000_adapter *adapter) -{ - might_sleep(); - while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - usleep_range(1000, 2000); - e1000e_down(adapter); - e1000e_up(adapter); - clear_bit(__E1000_RESETTING, &adapter->state); -} - -/** - * e1000e_cyclecounter_read - read raw cycle counter (used by time counter) - * @cc: cyclecounter structure - **/ -static cycle_t e1000e_cyclecounter_read(const struct cyclecounter *cc) -{ - struct e1000_adapter *adapter = container_of(cc, struct e1000_adapter, - cc); - struct e1000_hw *hw = &adapter->hw; - cycle_t systim; - - /* latch SYSTIMH on read of SYSTIML */ - systim = (cycle_t)er32(SYSTIML); - systim |= (cycle_t)er32(SYSTIMH) << 32; - - return systim; -} - -/** - * e1000_sw_init - Initialize general software structures (struct e1000_adapter) - * @adapter: board private structure to initialize - * - * e1000_sw_init initializes the Adapter private data structure. - * Fields are initialized based on PCI device information and - * OS network device settings (MTU size). - **/ -static int e1000_sw_init(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN; - adapter->rx_ps_bsize0 = 128; - adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN; - adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; - adapter->tx_ring_count = E1000_DEFAULT_TXD; - adapter->rx_ring_count = E1000_DEFAULT_RXD; - - spin_lock_init(&adapter->stats64_lock); - - e1000e_set_interrupt_capability(adapter); - - if (e1000_alloc_queues(adapter)) - return -ENOMEM; - - /* Setup hardware time stamping cyclecounter */ - if (adapter->flags & FLAG_HAS_HW_TIMESTAMP) { - adapter->cc.read = e1000e_cyclecounter_read; - adapter->cc.mask = CLOCKSOURCE_MASK(64); - adapter->cc.mult = 1; - /* cc.shift set in e1000e_get_base_tininca() */ - - spin_lock_init(&adapter->systim_lock); - INIT_WORK(&adapter->tx_hwtstamp_work, e1000e_tx_hwtstamp_work); - } - - /* Explicitly disable IRQ since the NIC can be in any state. */ - e1000_irq_disable(adapter); - - set_bit(__E1000_DOWN, &adapter->state); - return 0; -} - -/** - * e1000_intr_msi_test - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - **/ -static irqreturn_t e1000_intr_msi_test(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 icr = er32(ICR); - - e_dbg("icr is %08X\n", icr); - if (icr & E1000_ICR_RXSEQ) { - adapter->flags &= ~FLAG_MSI_TEST_FAILED; - /* Force memory writes to complete before acknowledging the - * interrupt is handled. - */ - wmb(); - } - - return IRQ_HANDLED; -} - -/** - * e1000_test_msi_interrupt - Returns 0 for successful test - * @adapter: board private struct - * - * code flow taken from tg3.c - **/ -static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - int err; - - /* poll_enable hasn't been called yet, so don't need disable */ - /* clear any pending events */ - er32(ICR); - - /* free the real vector and request a test handler */ - e1000_free_irq(adapter); - e1000e_reset_interrupt_capability(adapter); - - /* Assume that the test fails, if it succeeds then the test - * MSI irq handler will unset this flag - */ - adapter->flags |= FLAG_MSI_TEST_FAILED; - - err = pci_enable_msi(adapter->pdev); - if (err) - goto msi_test_failed; - - err = request_irq(adapter->pdev->irq, e1000_intr_msi_test, 0, - netdev->name, netdev); - if (err) { - pci_disable_msi(adapter->pdev); - goto msi_test_failed; - } - - /* Force memory writes to complete before enabling and firing an - * interrupt. - */ - wmb(); - - e1000_irq_enable(adapter); - - /* fire an unusual interrupt on the test handler */ - ew32(ICS, E1000_ICS_RXSEQ); - e1e_flush(); - msleep(100); - - e1000_irq_disable(adapter); - - rmb(); /* read flags after interrupt has been fired */ - - if (adapter->flags & FLAG_MSI_TEST_FAILED) { - adapter->int_mode = E1000E_INT_MODE_LEGACY; - e_info("MSI interrupt test failed, using legacy interrupt.\n"); - } else { - e_dbg("MSI interrupt test succeeded!\n"); - } - - free_irq(adapter->pdev->irq, netdev); - pci_disable_msi(adapter->pdev); - -msi_test_failed: - e1000e_set_interrupt_capability(adapter); - return e1000_request_irq(adapter); -} - -/** - * e1000_test_msi - Returns 0 if MSI test succeeds or INTx mode is restored - * @adapter: board private struct - * - * code flow taken from tg3.c, called with e1000 interrupts disabled. - **/ -static int e1000_test_msi(struct e1000_adapter *adapter) -{ - int err; - u16 pci_cmd; - - if (!(adapter->flags & FLAG_MSI_ENABLED)) - return 0; - - /* disable SERR in case the MSI write causes a master abort */ - pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd); - if (pci_cmd & PCI_COMMAND_SERR) - pci_write_config_word(adapter->pdev, PCI_COMMAND, - pci_cmd & ~PCI_COMMAND_SERR); - - err = e1000_test_msi_interrupt(adapter); - - /* re-enable SERR */ - if (pci_cmd & PCI_COMMAND_SERR) { - pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd); - pci_cmd |= PCI_COMMAND_SERR; - pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd); - } - - return err; -} - -/** - * e1000_open - Called when a network interface is made active - * @netdev: network interface device structure - * - * Returns 0 on success, negative value on failure - * - * The open entry point is called when a network interface is made - * active by the system (IFF_UP). At this point all resources needed - * for transmit and receive operations are allocated, the interrupt - * handler is registered with the OS, the watchdog timer is started, - * and the stack is notified that the interface is ready. - **/ -static int e1000_open(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct pci_dev *pdev = adapter->pdev; - int err; - - /* disallow open during test */ - if (test_bit(__E1000_TESTING, &adapter->state)) - return -EBUSY; - - pm_runtime_get_sync(&pdev->dev); - - netif_carrier_off(netdev); - - /* allocate transmit descriptors */ - err = e1000e_setup_tx_resources(adapter->tx_ring); - if (err) - goto err_setup_tx; - - /* allocate receive descriptors */ - err = e1000e_setup_rx_resources(adapter->rx_ring); - if (err) - goto err_setup_rx; - - /* If AMT is enabled, let the firmware know that the network - * interface is now open and reset the part to a known state. - */ - if (adapter->flags & FLAG_HAS_AMT) { - e1000e_get_hw_control(adapter); - e1000e_reset(adapter); - } - - e1000e_power_up_phy(adapter); - - adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; - if ((adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN)) - e1000_update_mng_vlan(adapter); - - /* DMA latency requirement to workaround jumbo issue */ - pm_qos_add_request(&adapter->netdev->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, - PM_QOS_DEFAULT_VALUE); - - /* before we allocate an interrupt, we must be ready to handle it. - * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt - * as soon as we call pci_request_irq, so we have to setup our - * clean_rx handler before we do so. - */ - e1000_configure(adapter); - - err = e1000_request_irq(adapter); - if (err) - goto err_req_irq; - - /* Work around PCIe errata with MSI interrupts causing some chipsets to - * ignore e1000e MSI messages, which means we need to test our MSI - * interrupt now - */ - if (adapter->int_mode != E1000E_INT_MODE_LEGACY) { - err = e1000_test_msi(adapter); - if (err) { - e_err("Interrupt allocation failed\n"); - goto err_req_irq; - } - } - - /* From here on the code is the same as e1000e_up() */ - clear_bit(__E1000_DOWN, &adapter->state); - - napi_enable(&adapter->napi); - - e1000_irq_enable(adapter); - - adapter->tx_hang_recheck = false; - netif_start_queue(netdev); - - adapter->idle_check = true; - hw->mac.get_link_status = true; - pm_runtime_put(&pdev->dev); - - /* fire a link status change interrupt to start the watchdog */ - if (adapter->msix_entries) - ew32(ICS, E1000_ICS_LSC | E1000_ICR_OTHER); - else - ew32(ICS, E1000_ICS_LSC); - - return 0; - -err_req_irq: - e1000e_release_hw_control(adapter); - e1000_power_down_phy(adapter); - e1000e_free_rx_resources(adapter->rx_ring); -err_setup_rx: - e1000e_free_tx_resources(adapter->tx_ring); -err_setup_tx: - e1000e_reset(adapter); - pm_runtime_put_sync(&pdev->dev); - - return err; -} - -/** - * e1000_close - Disables a network interface - * @netdev: network interface device structure - * - * Returns 0, this is not allowed to fail - * - * The close entry point is called when an interface is de-activated - * by the OS. The hardware is still under the drivers control, but - * needs to be disabled. A global MAC reset is issued to stop the - * hardware, and all transmit and receive resources are freed. - **/ -static int e1000_close(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct pci_dev *pdev = adapter->pdev; - int count = E1000_CHECK_RESET_COUNT; - - while (test_bit(__E1000_RESETTING, &adapter->state) && count--) - usleep_range(10000, 20000); - - WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); - - pm_runtime_get_sync(&pdev->dev); - - if (!test_bit(__E1000_DOWN, &adapter->state)) { - e1000e_down(adapter); - e1000_free_irq(adapter); - } - - napi_disable(&adapter->napi); - - e1000_power_down_phy(adapter); - - e1000e_free_tx_resources(adapter->tx_ring); - e1000e_free_rx_resources(adapter->rx_ring); - - /* kill manageability vlan ID if supported, but not if a vlan with - * the same ID is registered on the host OS (let 8021q kill it) - */ - if (adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) - e1000_vlan_rx_kill_vid(netdev, htons(ETH_P_8021Q), - adapter->mng_vlan_id); - - /* If AMT is enabled, let the firmware know that the network - * interface is now closed - */ - if ((adapter->flags & FLAG_HAS_AMT) && - !test_bit(__E1000_TESTING, &adapter->state)) - e1000e_release_hw_control(adapter); - - pm_qos_remove_request(&adapter->netdev->pm_qos_req); - - pm_runtime_put_sync(&pdev->dev); - - return 0; -} - -/** - * e1000_set_mac - Change the Ethernet Address of the NIC - * @netdev: network interface device structure - * @p: pointer to an address structure - * - * Returns 0 on success, negative on failure - **/ -static int e1000_set_mac(struct net_device *netdev, void *p) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - memcpy(adapter->hw.mac.addr, addr->sa_data, netdev->addr_len); - - hw->mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, 0); - - if (adapter->flags & FLAG_RESET_OVERWRITES_LAA) { - /* activate the work around */ - e1000e_set_laa_state_82571(&adapter->hw, 1); - - /* Hold a copy of the LAA in RAR[14] This is done so that - * between the time RAR[0] gets clobbered and the time it - * gets fixed (in e1000_watchdog), the actual LAA is in one - * of the RARs and no incoming packets directed to this port - * are dropped. Eventually the LAA will be in RAR[0] and - * RAR[14] - */ - hw->mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, - adapter->hw.mac.rar_entry_count - 1); - } - - return 0; -} - -/** - * e1000e_update_phy_task - work thread to update phy - * @work: pointer to our work struct - * - * this worker thread exists because we must acquire a - * semaphore to read the phy, which we could msleep while - * waiting for it, and we can't msleep in a timer. - **/ -static void e1000e_update_phy_task(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - update_phy_task); - - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - - e1000_get_phy_info(&adapter->hw); -} - -/** - * e1000_update_phy_info - timre call-back to update PHY info - * @data: pointer to adapter cast into an unsigned long - * - * Need to wait a few seconds after link up to get diagnostic information from - * the phy - **/ -static void e1000_update_phy_info(unsigned long data) -{ - struct e1000_adapter *adapter = (struct e1000_adapter *)data; - - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - - schedule_work(&adapter->update_phy_task); -} - -/** - * e1000e_update_phy_stats - Update the PHY statistics counters - * @adapter: board private structure - * - * Read/clear the upper 16-bit PHY registers and read/accumulate lower - **/ -static void e1000e_update_phy_stats(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - s32 ret_val; - u16 phy_data; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return; - - /* A page set is expensive so check if already on desired page. - * If not, set to the page with the PHY status registers. - */ - hw->phy.addr = 1; - ret_val = e1000e_read_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, - &phy_data); - if (ret_val) - goto release; - if (phy_data != (HV_STATS_PAGE << IGP_PAGE_SHIFT)) { - ret_val = hw->phy.ops.set_page(hw, - HV_STATS_PAGE << IGP_PAGE_SHIFT); - if (ret_val) - goto release; - } - - /* Single Collision Count */ - hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data); - if (!ret_val) - adapter->stats.scc += phy_data; - - /* Excessive Collision Count */ - hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data); - if (!ret_val) - adapter->stats.ecol += phy_data; - - /* Multiple Collision Count */ - hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data); - if (!ret_val) - adapter->stats.mcc += phy_data; - - /* Late Collision Count */ - hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data); - if (!ret_val) - adapter->stats.latecol += phy_data; - - /* Collision Count - also used for adaptive IFS */ - hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data); - if (!ret_val) - hw->mac.collision_delta = phy_data; - - /* Defer Count */ - hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data); - if (!ret_val) - adapter->stats.dc += phy_data; - - /* Transmit with no CRS */ - hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data); - if (!ret_val) - adapter->stats.tncrs += phy_data; - -release: - hw->phy.ops.release(hw); -} - -/** - * e1000e_update_stats - Update the board statistics counters - * @adapter: board private structure - **/ -static void e1000e_update_stats(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - struct pci_dev *pdev = adapter->pdev; - - /* Prevent stats update while adapter is being reset, or if the pci - * connection is down. - */ - if (adapter->link_speed == 0) - return; - if (pci_channel_offline(pdev)) - return; - - adapter->stats.crcerrs += er32(CRCERRS); - adapter->stats.gprc += er32(GPRC); - adapter->stats.gorc += er32(GORCL); - er32(GORCH); /* Clear gorc */ - adapter->stats.bprc += er32(BPRC); - adapter->stats.mprc += er32(MPRC); - adapter->stats.roc += er32(ROC); - - adapter->stats.mpc += er32(MPC); - - /* Half-duplex statistics */ - if (adapter->link_duplex == HALF_DUPLEX) { - if (adapter->flags2 & FLAG2_HAS_PHY_STATS) { - e1000e_update_phy_stats(adapter); - } else { - adapter->stats.scc += er32(SCC); - adapter->stats.ecol += er32(ECOL); - adapter->stats.mcc += er32(MCC); - adapter->stats.latecol += er32(LATECOL); - adapter->stats.dc += er32(DC); - - hw->mac.collision_delta = er32(COLC); - - if ((hw->mac.type != e1000_82574) && - (hw->mac.type != e1000_82583)) - adapter->stats.tncrs += er32(TNCRS); - } - adapter->stats.colc += hw->mac.collision_delta; - } - - adapter->stats.xonrxc += er32(XONRXC); - adapter->stats.xontxc += er32(XONTXC); - adapter->stats.xoffrxc += er32(XOFFRXC); - adapter->stats.xofftxc += er32(XOFFTXC); - adapter->stats.gptc += er32(GPTC); - adapter->stats.gotc += er32(GOTCL); - er32(GOTCH); /* Clear gotc */ - adapter->stats.rnbc += er32(RNBC); - adapter->stats.ruc += er32(RUC); - - adapter->stats.mptc += er32(MPTC); - adapter->stats.bptc += er32(BPTC); - - /* used for adaptive IFS */ - - hw->mac.tx_packet_delta = er32(TPT); - adapter->stats.tpt += hw->mac.tx_packet_delta; - - adapter->stats.algnerrc += er32(ALGNERRC); - adapter->stats.rxerrc += er32(RXERRC); - adapter->stats.cexterr += er32(CEXTERR); - adapter->stats.tsctc += er32(TSCTC); - adapter->stats.tsctfc += er32(TSCTFC); - - /* Fill out the OS statistics structure */ - netdev->stats.multicast = adapter->stats.mprc; - netdev->stats.collisions = adapter->stats.colc; - - /* Rx Errors */ - - /* RLEC on some newer hardware can be incorrect so build - * our own version based on RUC and ROC - */ - netdev->stats.rx_errors = adapter->stats.rxerrc + - adapter->stats.crcerrs + adapter->stats.algnerrc + - adapter->stats.ruc + adapter->stats.roc + adapter->stats.cexterr; - netdev->stats.rx_length_errors = adapter->stats.ruc + - adapter->stats.roc; - netdev->stats.rx_crc_errors = adapter->stats.crcerrs; - netdev->stats.rx_frame_errors = adapter->stats.algnerrc; - netdev->stats.rx_missed_errors = adapter->stats.mpc; - - /* Tx Errors */ - netdev->stats.tx_errors = adapter->stats.ecol + adapter->stats.latecol; - netdev->stats.tx_aborted_errors = adapter->stats.ecol; - netdev->stats.tx_window_errors = adapter->stats.latecol; - netdev->stats.tx_carrier_errors = adapter->stats.tncrs; - - /* Tx Dropped needs to be maintained elsewhere */ - - /* Management Stats */ - adapter->stats.mgptc += er32(MGTPTC); - adapter->stats.mgprc += er32(MGTPRC); - adapter->stats.mgpdc += er32(MGTPDC); - - /* Correctable ECC Errors */ - if (hw->mac.type == e1000_pch_lpt) { - u32 pbeccsts = er32(PBECCSTS); - adapter->corr_errors += - pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; - adapter->uncorr_errors += - (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> - E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; - } -} - -/** - * e1000_phy_read_status - Update the PHY register status snapshot - * @adapter: board private structure - **/ -static void e1000_phy_read_status(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_phy_regs *phy = &adapter->phy_regs; - - if ((er32(STATUS) & E1000_STATUS_LU) && - (adapter->hw.phy.media_type == e1000_media_type_copper)) { - int ret_val; - - pm_runtime_get_sync(&adapter->pdev->dev); - ret_val = e1e_rphy(hw, MII_BMCR, &phy->bmcr); - ret_val |= e1e_rphy(hw, MII_BMSR, &phy->bmsr); - ret_val |= e1e_rphy(hw, MII_ADVERTISE, &phy->advertise); - ret_val |= e1e_rphy(hw, MII_LPA, &phy->lpa); - ret_val |= e1e_rphy(hw, MII_EXPANSION, &phy->expansion); - ret_val |= e1e_rphy(hw, MII_CTRL1000, &phy->ctrl1000); - ret_val |= e1e_rphy(hw, MII_STAT1000, &phy->stat1000); - ret_val |= e1e_rphy(hw, MII_ESTATUS, &phy->estatus); - if (ret_val) - e_warn("Error reading PHY register\n"); - pm_runtime_put_sync(&adapter->pdev->dev); - } else { - /* Do not read PHY registers if link is not up - * Set values to typical power-on defaults - */ - phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX); - phy->bmsr = (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | - BMSR_10HALF | BMSR_ESTATEN | BMSR_ANEGCAPABLE | - BMSR_ERCAP); - phy->advertise = (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP | - ADVERTISE_ALL | ADVERTISE_CSMA); - phy->lpa = 0; - phy->expansion = EXPANSION_ENABLENPAGE; - phy->ctrl1000 = ADVERTISE_1000FULL; - phy->stat1000 = 0; - phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF); - } -} - -static void e1000_print_link_info(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl = er32(CTRL); - - /* Link status message must follow this format for user tools */ - pr_info("%s NIC Link is Up %d Mbps %s Duplex, Flow Control: %s\n", - adapter->netdev->name, adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? "Full" : "Half", - (ctrl & E1000_CTRL_TFCE) && (ctrl & E1000_CTRL_RFCE) ? "Rx/Tx" : - (ctrl & E1000_CTRL_RFCE) ? "Rx" : - (ctrl & E1000_CTRL_TFCE) ? "Tx" : "None"); -} - -static bool e1000e_has_link(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - bool link_active = false; - s32 ret_val = 0; - - /* get_link_status is set on LSC (link status) interrupt or - * Rx sequence error interrupt. get_link_status will stay - * false until the check_for_link establishes link - * for copper adapters ONLY - */ - switch (hw->phy.media_type) { - case e1000_media_type_copper: - if (hw->mac.get_link_status) { - ret_val = hw->mac.ops.check_for_link(hw); - link_active = !hw->mac.get_link_status; - } else { - link_active = true; - } - break; - case e1000_media_type_fiber: - ret_val = hw->mac.ops.check_for_link(hw); - link_active = !!(er32(STATUS) & E1000_STATUS_LU); - break; - case e1000_media_type_internal_serdes: - ret_val = hw->mac.ops.check_for_link(hw); - link_active = adapter->hw.mac.serdes_has_link; - break; - default: - case e1000_media_type_unknown: - break; - } - - if ((ret_val == E1000_ERR_PHY) && (hw->phy.type == e1000_phy_igp_3) && - (er32(CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) { - /* See e1000_kmrn_lock_loss_workaround_ich8lan() */ - e_info("Gigabit has been disabled, downgrading speed\n"); - } - - return link_active; -} - -static void e1000e_enable_receives(struct e1000_adapter *adapter) -{ - /* make sure the receive unit is started */ - if ((adapter->flags & FLAG_RX_NEEDS_RESTART) && - (adapter->flags & FLAG_RESTART_NOW)) { - struct e1000_hw *hw = &adapter->hw; - u32 rctl = er32(RCTL); - ew32(RCTL, rctl | E1000_RCTL_EN); - adapter->flags &= ~FLAG_RESTART_NOW; - } -} - -static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - /* With 82574 controllers, PHY needs to be checked periodically - * for hung state and reset, if two calls return true - */ - if (e1000_check_phy_82574(hw)) - adapter->phy_hang_count++; - else - adapter->phy_hang_count = 0; - - if (adapter->phy_hang_count > 1) { - adapter->phy_hang_count = 0; - schedule_work(&adapter->reset_task); - } -} - -/** - * e1000_watchdog - Timer Call-back - * @data: pointer to adapter cast into an unsigned long - **/ -static void e1000_watchdog(unsigned long data) -{ - struct e1000_adapter *adapter = (struct e1000_adapter *)data; - - /* Do the rest outside of interrupt context */ - schedule_work(&adapter->watchdog_task); - - /* TODO: make this use queue_delayed_work() */ -} - -static void e1000_watchdog_task(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - watchdog_task); - struct net_device *netdev = adapter->netdev; - struct e1000_mac_info *mac = &adapter->hw.mac; - struct e1000_phy_info *phy = &adapter->hw.phy; - struct e1000_ring *tx_ring = adapter->tx_ring; - struct e1000_hw *hw = &adapter->hw; - u32 link, tctl; - - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - - link = e1000e_has_link(adapter); - if ((netif_carrier_ok(netdev)) && link) { - /* Cancel scheduled suspend requests. */ - pm_runtime_resume(netdev->dev.parent); - - e1000e_enable_receives(adapter); - goto link_up; - } - - if ((e1000e_enable_tx_pkt_filtering(hw)) && - (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)) - e1000_update_mng_vlan(adapter); - - if (link) { - if (!netif_carrier_ok(netdev)) { - bool txb2b = true; - - /* Cancel scheduled suspend requests. */ - pm_runtime_resume(netdev->dev.parent); - - /* update snapshot of PHY registers on LSC */ - e1000_phy_read_status(adapter); - mac->ops.get_link_up_info(&adapter->hw, - &adapter->link_speed, - &adapter->link_duplex); - e1000_print_link_info(adapter); - - /* check if SmartSpeed worked */ - e1000e_check_downshift(hw); - if (phy->speed_downgraded) - netdev_warn(netdev, - "Link Speed was downgraded by SmartSpeed\n"); - - /* On supported PHYs, check for duplex mismatch only - * if link has autonegotiated at 10/100 half - */ - if ((hw->phy.type == e1000_phy_igp_3 || - hw->phy.type == e1000_phy_bm) && - (hw->mac.autoneg == true) && - (adapter->link_speed == SPEED_10 || - adapter->link_speed == SPEED_100) && - (adapter->link_duplex == HALF_DUPLEX)) { - u16 autoneg_exp; - - e1e_rphy(hw, MII_EXPANSION, &autoneg_exp); - - if (!(autoneg_exp & EXPANSION_NWAY)) - e_info("Autonegotiated half duplex but link partner cannot autoneg. Try forcing full duplex if link gets many collisions.\n"); - } - - /* adjust timeout factor according to speed/duplex */ - adapter->tx_timeout_factor = 1; - switch (adapter->link_speed) { - case SPEED_10: - txb2b = false; - adapter->tx_timeout_factor = 16; - break; - case SPEED_100: - txb2b = false; - adapter->tx_timeout_factor = 10; - break; - } - - /* workaround: re-program speed mode bit after - * link-up event - */ - if ((adapter->flags & FLAG_TARC_SPEED_MODE_BIT) && - !txb2b) { - u32 tarc0; - tarc0 = er32(TARC(0)); - tarc0 &= ~SPEED_MODE_BIT; - ew32(TARC(0), tarc0); - } - - /* disable TSO for pcie and 10/100 speeds, to avoid - * some hardware issues - */ - if (!(adapter->flags & FLAG_TSO_FORCE)) { - switch (adapter->link_speed) { - case SPEED_10: - case SPEED_100: - e_info("10/100 speed: disabling TSO\n"); - netdev->features &= ~NETIF_F_TSO; - netdev->features &= ~NETIF_F_TSO6; - break; - case SPEED_1000: - netdev->features |= NETIF_F_TSO; - netdev->features |= NETIF_F_TSO6; - break; - default: - /* oops */ - break; - } - } - - /* enable transmits in the hardware, need to do this - * after setting TARC(0) - */ - tctl = er32(TCTL); - tctl |= E1000_TCTL_EN; - ew32(TCTL, tctl); - - /* Perform any post-link-up configuration before - * reporting link up. - */ - if (phy->ops.cfg_on_link_up) - phy->ops.cfg_on_link_up(hw); - - netif_carrier_on(netdev); - - if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_timer(&adapter->phy_info_timer, - round_jiffies(jiffies + 2 * HZ)); - } - } else { - if (netif_carrier_ok(netdev)) { - adapter->link_speed = 0; - adapter->link_duplex = 0; - /* Link status message must follow this format */ - pr_info("%s NIC Link is Down\n", adapter->netdev->name); - netif_carrier_off(netdev); - if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_timer(&adapter->phy_info_timer, - round_jiffies(jiffies + 2 * HZ)); - - /* The link is lost so the controller stops DMA. - * If there is queued Tx work that cannot be done - * or if on an 8000ES2LAN which requires a Rx packet - * buffer work-around on link down event, reset the - * controller to flush the Tx/Rx packet buffers. - * (Do the reset outside of interrupt context). - */ - if ((adapter->flags & FLAG_RX_NEEDS_RESTART) || - (e1000_desc_unused(tx_ring) + 1 < tx_ring->count)) - adapter->flags |= FLAG_RESTART_NOW; - else - pm_schedule_suspend(netdev->dev.parent, - LINK_TIMEOUT); - } - } - -link_up: - spin_lock(&adapter->stats64_lock); - e1000e_update_stats(adapter); - - mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; - adapter->tpt_old = adapter->stats.tpt; - mac->collision_delta = adapter->stats.colc - adapter->colc_old; - adapter->colc_old = adapter->stats.colc; - - adapter->gorc = adapter->stats.gorc - adapter->gorc_old; - adapter->gorc_old = adapter->stats.gorc; - adapter->gotc = adapter->stats.gotc - adapter->gotc_old; - adapter->gotc_old = adapter->stats.gotc; - spin_unlock(&adapter->stats64_lock); - - if (adapter->flags & FLAG_RESTART_NOW) { - schedule_work(&adapter->reset_task); - /* return immediately since reset is imminent */ - return; - } - - e1000e_update_adaptive(&adapter->hw); - - /* Simple mode for Interrupt Throttle Rate (ITR) */ - if (adapter->itr_setting == 4) { - /* Symmetric Tx/Rx gets a reduced ITR=2000; - * Total asymmetrical Tx or Rx gets ITR=8000; - * everyone else is between 2000-8000. - */ - u32 goc = (adapter->gotc + adapter->gorc) / 10000; - u32 dif = (adapter->gotc > adapter->gorc ? - adapter->gotc - adapter->gorc : - adapter->gorc - adapter->gotc) / 10000; - u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000; - - e1000e_write_itr(adapter, itr); - } - - /* Cause software interrupt to ensure Rx ring is cleaned */ - if (adapter->msix_entries) - ew32(ICS, adapter->rx_ring->ims_val); - else - ew32(ICS, E1000_ICS_RXDMT0); - - /* flush pending descriptors to memory before detecting Tx hang */ - e1000e_flush_descriptors(adapter); - - /* Force detection of hung controller every watchdog period */ - adapter->detect_tx_hung = true; - - /* With 82571 controllers, LAA may be overwritten due to controller - * reset from the other port. Set the appropriate LAA in RAR[0] - */ - if (e1000e_get_laa_state_82571(hw)) - hw->mac.ops.rar_set(hw, adapter->hw.mac.addr, 0); - - if (adapter->flags2 & FLAG2_CHECK_PHY_HANG) - e1000e_check_82574_phy_workaround(adapter); - - /* Clear valid timestamp stuck in RXSTMPL/H due to a Rx error */ - if (adapter->hwtstamp_config.rx_filter != HWTSTAMP_FILTER_NONE) { - if ((adapter->flags2 & FLAG2_CHECK_RX_HWTSTAMP) && - (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID)) { - er32(RXSTMPH); - adapter->rx_hwtstamp_cleared++; - } else { - adapter->flags2 |= FLAG2_CHECK_RX_HWTSTAMP; - } - } - - /* Reset the timer */ - if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_timer(&adapter->watchdog_timer, - round_jiffies(jiffies + 2 * HZ)); -} - -#define E1000_TX_FLAGS_CSUM 0x00000001 -#define E1000_TX_FLAGS_VLAN 0x00000002 -#define E1000_TX_FLAGS_TSO 0x00000004 -#define E1000_TX_FLAGS_IPV4 0x00000008 -#define E1000_TX_FLAGS_NO_FCS 0x00000010 -#define E1000_TX_FLAGS_HWTSTAMP 0x00000020 -#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 -#define E1000_TX_FLAGS_VLAN_SHIFT 16 - -static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb) -{ - struct e1000_context_desc *context_desc; - struct e1000_buffer *buffer_info; - unsigned int i; - u32 cmd_length = 0; - u16 ipcse = 0, mss; - u8 ipcss, ipcso, tucss, tucso, hdr_len; - - if (!skb_is_gso(skb)) - return 0; - - if (skb_header_cloned(skb)) { - int err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC); - - if (err) - return err; - } - - hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - mss = skb_shinfo(skb)->gso_size; - if (skb->protocol == htons(ETH_P_IP)) { - struct iphdr *iph = ip_hdr(skb); - iph->tot_len = 0; - iph->check = 0; - tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - 0, IPPROTO_TCP, 0); - cmd_length = E1000_TXD_CMD_IP; - ipcse = skb_transport_offset(skb) - 1; - } else if (skb_is_gso_v6(skb)) { - ipv6_hdr(skb)->payload_len = 0; - tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); - ipcse = 0; - } - ipcss = skb_network_offset(skb); - ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data; - tucss = skb_transport_offset(skb); - tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data; - - cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | - E1000_TXD_CMD_TCP | (skb->len - (hdr_len))); - - i = tx_ring->next_to_use; - context_desc = E1000_CONTEXT_DESC(*tx_ring, i); - buffer_info = &tx_ring->buffer_info[i]; - - context_desc->lower_setup.ip_fields.ipcss = ipcss; - context_desc->lower_setup.ip_fields.ipcso = ipcso; - context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse); - context_desc->upper_setup.tcp_fields.tucss = tucss; - context_desc->upper_setup.tcp_fields.tucso = tucso; - context_desc->upper_setup.tcp_fields.tucse = 0; - context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss); - context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; - context_desc->cmd_and_length = cpu_to_le32(cmd_length); - - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; - - i++; - if (i == tx_ring->count) - i = 0; - tx_ring->next_to_use = i; - - return 1; -} - -static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct e1000_context_desc *context_desc; - struct e1000_buffer *buffer_info; - unsigned int i; - u8 css; - u32 cmd_len = E1000_TXD_CMD_DEXT; - __be16 protocol; - - if (skb->ip_summed != CHECKSUM_PARTIAL) - return 0; - - if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) - protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; - else - protocol = skb->protocol; - - switch (protocol) { - case cpu_to_be16(ETH_P_IP): - if (ip_hdr(skb)->protocol == IPPROTO_TCP) - cmd_len |= E1000_TXD_CMD_TCP; - break; - case cpu_to_be16(ETH_P_IPV6): - /* XXX not handling all IPV6 headers */ - if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) - cmd_len |= E1000_TXD_CMD_TCP; - break; - default: - if (unlikely(net_ratelimit())) - e_warn("checksum_partial proto=%x!\n", - be16_to_cpu(protocol)); - break; - } - - css = skb_checksum_start_offset(skb); - - i = tx_ring->next_to_use; - buffer_info = &tx_ring->buffer_info[i]; - context_desc = E1000_CONTEXT_DESC(*tx_ring, i); - - context_desc->lower_setup.ip_config = 0; - context_desc->upper_setup.tcp_fields.tucss = css; - context_desc->upper_setup.tcp_fields.tucso = css + skb->csum_offset; - context_desc->upper_setup.tcp_fields.tucse = 0; - context_desc->tcp_seg_setup.data = 0; - context_desc->cmd_and_length = cpu_to_le32(cmd_len); - - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; - - i++; - if (i == tx_ring->count) - i = 0; - tx_ring->next_to_use = i; - - return 1; -} - -static int e1000_tx_map(struct e1000_ring *tx_ring, struct sk_buff *skb, - unsigned int first, unsigned int max_per_txd, - unsigned int nr_frags) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct pci_dev *pdev = adapter->pdev; - struct e1000_buffer *buffer_info; - unsigned int len = skb_headlen(skb); - unsigned int offset = 0, size, count = 0, i; - unsigned int f, bytecount, segs; - - i = tx_ring->next_to_use; - - while (len) { - buffer_info = &tx_ring->buffer_info[i]; - size = min(len, max_per_txd); - - buffer_info->length = size; - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; - buffer_info->dma = dma_map_single(&pdev->dev, - skb->data + offset, - size, DMA_TO_DEVICE); - buffer_info->mapped_as_page = false; - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) - goto dma_error; - - len -= size; - offset += size; - count++; - - if (len) { - i++; - if (i == tx_ring->count) - i = 0; - } - } - - for (f = 0; f < nr_frags; f++) { - const struct skb_frag_struct *frag; - - frag = &skb_shinfo(skb)->frags[f]; - len = skb_frag_size(frag); - offset = 0; - - while (len) { - i++; - if (i == tx_ring->count) - i = 0; - - buffer_info = &tx_ring->buffer_info[i]; - size = min(len, max_per_txd); - - buffer_info->length = size; - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; - buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag, - offset, size, - DMA_TO_DEVICE); - buffer_info->mapped_as_page = true; - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) - goto dma_error; - - len -= size; - offset += size; - count++; - } - } - - segs = skb_shinfo(skb)->gso_segs ? : 1; - /* multiply data chunks by size of headers */ - bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len; - - tx_ring->buffer_info[i].skb = skb; - tx_ring->buffer_info[i].segs = segs; - tx_ring->buffer_info[i].bytecount = bytecount; - tx_ring->buffer_info[first].next_to_watch = i; - - return count; - -dma_error: - dev_err(&pdev->dev, "Tx DMA map failed\n"); - buffer_info->dma = 0; - if (count) - count--; - - while (count--) { - if (i == 0) - i += tx_ring->count; - i--; - buffer_info = &tx_ring->buffer_info[i]; - e1000_put_txbuf(tx_ring, buffer_info); - } - - return 0; -} - -static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct e1000_tx_desc *tx_desc = NULL; - struct e1000_buffer *buffer_info; - u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; - unsigned int i; - - if (tx_flags & E1000_TX_FLAGS_TSO) { - txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | - E1000_TXD_CMD_TSE; - txd_upper |= E1000_TXD_POPTS_TXSM << 8; - - if (tx_flags & E1000_TX_FLAGS_IPV4) - txd_upper |= E1000_TXD_POPTS_IXSM << 8; - } - - if (tx_flags & E1000_TX_FLAGS_CSUM) { - txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; - txd_upper |= E1000_TXD_POPTS_TXSM << 8; - } - - if (tx_flags & E1000_TX_FLAGS_VLAN) { - txd_lower |= E1000_TXD_CMD_VLE; - txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); - } - - if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS)) - txd_lower &= ~(E1000_TXD_CMD_IFCS); - - if (unlikely(tx_flags & E1000_TX_FLAGS_HWTSTAMP)) { - txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; - txd_upper |= E1000_TXD_EXTCMD_TSTAMP; - } - - i = tx_ring->next_to_use; - - do { - buffer_info = &tx_ring->buffer_info[i]; - tx_desc = E1000_TX_DESC(*tx_ring, i); - tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - tx_desc->lower.data = cpu_to_le32(txd_lower | - buffer_info->length); - tx_desc->upper.data = cpu_to_le32(txd_upper); - - i++; - if (i == tx_ring->count) - i = 0; - } while (--count > 0); - - tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); - - /* txd_cmd re-enables FCS, so we'll re-disable it here as desired. */ - if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS)) - tx_desc->lower.data &= ~(cpu_to_le32(E1000_TXD_CMD_IFCS)); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - - tx_ring->next_to_use = i; - - if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_tdt_wa(tx_ring, i); - else - writel(i, tx_ring->tail); - - /* we need this if more than one processor can write to our tail - * at a time, it synchronizes IO on IA64/Altix systems - */ - mmiowb(); -} - -#define MINIMUM_DHCP_PACKET_SIZE 282 -static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter, - struct sk_buff *skb) -{ - struct e1000_hw *hw = &adapter->hw; - u16 length, offset; - - if (vlan_tx_tag_present(skb) && - !((vlan_tx_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) && - (adapter->hw.mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN))) - return 0; - - if (skb->len <= MINIMUM_DHCP_PACKET_SIZE) - return 0; - - if (((struct ethhdr *)skb->data)->h_proto != htons(ETH_P_IP)) - return 0; - - { - const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data + 14); - struct udphdr *udp; - - if (ip->protocol != IPPROTO_UDP) - return 0; - - udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2)); - if (ntohs(udp->dest) != 67) - return 0; - - offset = (u8 *)udp + 8 - skb->data; - length = skb->len - offset; - return e1000e_mng_write_dhcp_info(hw, (u8 *)udp + 8, length); - } - - return 0; -} - -static int __e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - - netif_stop_queue(adapter->netdev); - /* Herbert's original patch had: - * smp_mb__after_netif_stop_queue(); - * but since that doesn't exist yet, just open code it. - */ - smp_mb(); - - /* We need to check again in a case another CPU has just - * made room available. - */ - if (e1000_desc_unused(tx_ring) < size) - return -EBUSY; - - /* A reprieve! */ - netif_start_queue(adapter->netdev); - ++adapter->restart_queue; - return 0; -} - -static int e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) -{ - BUG_ON(size > tx_ring->count); - - if (e1000_desc_unused(tx_ring) >= size) - return 0; - return __e1000_maybe_stop_tx(tx_ring, size); -} - -static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_ring *tx_ring = adapter->tx_ring; - unsigned int first; - unsigned int tx_flags = 0; - unsigned int len = skb_headlen(skb); - unsigned int nr_frags; - unsigned int mss; - int count = 0; - int tso; - unsigned int f; - - if (test_bit(__E1000_DOWN, &adapter->state)) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if (skb->len <= 0) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - /* The minimum packet size with TCTL.PSP set is 17 bytes so - * pad skb in order to meet this minimum size requirement - */ - if (unlikely(skb->len < 17)) { - if (skb_pad(skb, 17 - skb->len)) - return NETDEV_TX_OK; - skb->len = 17; - skb_set_tail_pointer(skb, 17); - } - - mss = skb_shinfo(skb)->gso_size; - if (mss) { - u8 hdr_len; - - /* TSO Workaround for 82571/2/3 Controllers -- if skb->data - * points to just header, pull a few bytes of payload from - * frags into skb->data - */ - hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - /* we do this workaround for ES2LAN, but it is un-necessary, - * avoiding it could save a lot of cycles - */ - if (skb->data_len && (hdr_len == len)) { - unsigned int pull_size; - - pull_size = min_t(unsigned int, 4, skb->data_len); - if (!__pskb_pull_tail(skb, pull_size)) { - e_err("__pskb_pull_tail failed.\n"); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - len = skb_headlen(skb); - } - } - - /* reserve a descriptor for the offload context */ - if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL)) - count++; - count++; - - count += DIV_ROUND_UP(len, adapter->tx_fifo_limit); - - nr_frags = skb_shinfo(skb)->nr_frags; - for (f = 0; f < nr_frags; f++) - count += DIV_ROUND_UP(skb_frag_size(&skb_shinfo(skb)->frags[f]), - adapter->tx_fifo_limit); - - if (adapter->hw.mac.tx_pkt_filtering) - e1000_transfer_dhcp_info(adapter, skb); - - /* need: count + 2 desc gap to keep tail from touching - * head, otherwise try next time - */ - if (e1000_maybe_stop_tx(tx_ring, count + 2)) - return NETDEV_TX_BUSY; - - if (vlan_tx_tag_present(skb)) { - tx_flags |= E1000_TX_FLAGS_VLAN; - tx_flags |= (vlan_tx_tag_get(skb) << E1000_TX_FLAGS_VLAN_SHIFT); - } - - first = tx_ring->next_to_use; - - tso = e1000_tso(tx_ring, skb); - if (tso < 0) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if (tso) - tx_flags |= E1000_TX_FLAGS_TSO; - else if (e1000_tx_csum(tx_ring, skb)) - tx_flags |= E1000_TX_FLAGS_CSUM; - - /* Old method was to assume IPv4 packet by default if TSO was enabled. - * 82571 hardware supports TSO capabilities for IPv6 as well... - * no longer assume, we must. - */ - if (skb->protocol == htons(ETH_P_IP)) - tx_flags |= E1000_TX_FLAGS_IPV4; - - if (unlikely(skb->no_fcs)) - tx_flags |= E1000_TX_FLAGS_NO_FCS; - - /* if count is 0 then mapping error has occurred */ - count = e1000_tx_map(tx_ring, skb, first, adapter->tx_fifo_limit, - nr_frags); - if (count) { - if (unlikely((skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && - !adapter->tx_hwtstamp_skb)) { - skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - tx_flags |= E1000_TX_FLAGS_HWTSTAMP; - adapter->tx_hwtstamp_skb = skb_get(skb); - schedule_work(&adapter->tx_hwtstamp_work); - } else { - skb_tx_timestamp(skb); - } - - netdev_sent_queue(netdev, skb->len); - e1000_tx_queue(tx_ring, tx_flags, count); - /* Make sure there is space in the ring for the next send. */ - e1000_maybe_stop_tx(tx_ring, - (MAX_SKB_FRAGS * - DIV_ROUND_UP(PAGE_SIZE, - adapter->tx_fifo_limit) + 2)); - } else { - dev_kfree_skb_any(skb); - tx_ring->buffer_info[first].time_stamp = 0; - tx_ring->next_to_use = first; - } - - return NETDEV_TX_OK; -} - -/** - * e1000_tx_timeout - Respond to a Tx Hang - * @netdev: network interface device structure - **/ -static void e1000_tx_timeout(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - /* Do the reset outside of interrupt context */ - adapter->tx_timeout_count++; - schedule_work(&adapter->reset_task); -} - -static void e1000_reset_task(struct work_struct *work) -{ - struct e1000_adapter *adapter; - adapter = container_of(work, struct e1000_adapter, reset_task); - - /* don't run the task if already down */ - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - - if (!(adapter->flags & FLAG_RESTART_NOW)) { - e1000e_dump(adapter); - e_err("Reset adapter unexpectedly\n"); - } - e1000e_reinit_locked(adapter); -} - -/** - * e1000_get_stats64 - Get System Network Statistics - * @netdev: network interface device structure - * @stats: rtnl_link_stats64 pointer - * - * Returns the address of the device statistics structure. - **/ -struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 *stats) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - memset(stats, 0, sizeof(struct rtnl_link_stats64)); - spin_lock(&adapter->stats64_lock); - e1000e_update_stats(adapter); - /* Fill out the OS statistics structure */ - stats->rx_bytes = adapter->stats.gorc; - stats->rx_packets = adapter->stats.gprc; - stats->tx_bytes = adapter->stats.gotc; - stats->tx_packets = adapter->stats.gptc; - stats->multicast = adapter->stats.mprc; - stats->collisions = adapter->stats.colc; - - /* Rx Errors */ - - /* RLEC on some newer hardware can be incorrect so build - * our own version based on RUC and ROC - */ - stats->rx_errors = adapter->stats.rxerrc + - adapter->stats.crcerrs + adapter->stats.algnerrc + - adapter->stats.ruc + adapter->stats.roc + adapter->stats.cexterr; - stats->rx_length_errors = adapter->stats.ruc + adapter->stats.roc; - stats->rx_crc_errors = adapter->stats.crcerrs; - stats->rx_frame_errors = adapter->stats.algnerrc; - stats->rx_missed_errors = adapter->stats.mpc; - - /* Tx Errors */ - stats->tx_errors = adapter->stats.ecol + adapter->stats.latecol; - stats->tx_aborted_errors = adapter->stats.ecol; - stats->tx_window_errors = adapter->stats.latecol; - stats->tx_carrier_errors = adapter->stats.tncrs; - - /* Tx Dropped needs to be maintained elsewhere */ - - spin_unlock(&adapter->stats64_lock); - return stats; -} - -/** - * e1000_change_mtu - Change the Maximum Transfer Unit - * @netdev: network interface device structure - * @new_mtu: new value for maximum frame size - * - * Returns 0 on success, negative on failure - **/ -static int e1000_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN; - - /* Jumbo frame support */ - if ((max_frame > ETH_FRAME_LEN + ETH_FCS_LEN) && - !(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { - e_err("Jumbo Frames not supported.\n"); - return -EINVAL; - } - - /* Supported frame sizes */ - if ((new_mtu < ETH_ZLEN + ETH_FCS_LEN + VLAN_HLEN) || - (max_frame > adapter->max_hw_frame_size)) { - e_err("Unsupported MTU setting\n"); - return -EINVAL; - } - - /* Jumbo frame workaround on 82579 and newer requires CRC be stripped */ - if ((adapter->hw.mac.type >= e1000_pch2lan) && - !(adapter->flags2 & FLAG2_CRC_STRIPPING) && - (new_mtu > ETH_DATA_LEN)) { - e_err("Jumbo Frames not supported on this device when CRC stripping is disabled.\n"); - return -EINVAL; - } - - while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - usleep_range(1000, 2000); - /* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */ - adapter->max_frame_size = max_frame; - e_info("changing MTU from %d to %d\n", netdev->mtu, new_mtu); - netdev->mtu = new_mtu; - if (netif_running(netdev)) - e1000e_down(adapter); - - /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN - * means we reserve 2 more, this pushes us to allocate from the next - * larger slab size. - * i.e. RXBUFFER_2048 --> size-4096 slab - * However with the new *_jumbo_rx* routines, jumbo receives will use - * fragmented skbs - */ - - if (max_frame <= 2048) - adapter->rx_buffer_len = 2048; - else - adapter->rx_buffer_len = 4096; - - /* adjust allocation if LPE protects us, and we aren't using SBP */ - if ((max_frame == ETH_FRAME_LEN + ETH_FCS_LEN) || - (max_frame == ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN)) - adapter->rx_buffer_len = ETH_FRAME_LEN + VLAN_HLEN - + ETH_FCS_LEN; - - if (netif_running(netdev)) - e1000e_up(adapter); - else - e1000e_reset(adapter); - - clear_bit(__E1000_RESETTING, &adapter->state); - - return 0; -} - -static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, - int cmd) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct mii_ioctl_data *data = if_mii(ifr); - - if (adapter->hw.phy.media_type != e1000_media_type_copper) - return -EOPNOTSUPP; - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = adapter->hw.phy.addr; - break; - case SIOCGMIIREG: - e1000_phy_read_status(adapter); - - switch (data->reg_num & 0x1F) { - case MII_BMCR: - data->val_out = adapter->phy_regs.bmcr; - break; - case MII_BMSR: - data->val_out = adapter->phy_regs.bmsr; - break; - case MII_PHYSID1: - data->val_out = (adapter->hw.phy.id >> 16); - break; - case MII_PHYSID2: - data->val_out = (adapter->hw.phy.id & 0xFFFF); - break; - case MII_ADVERTISE: - data->val_out = adapter->phy_regs.advertise; - break; - case MII_LPA: - data->val_out = adapter->phy_regs.lpa; - break; - case MII_EXPANSION: - data->val_out = adapter->phy_regs.expansion; - break; - case MII_CTRL1000: - data->val_out = adapter->phy_regs.ctrl1000; - break; - case MII_STAT1000: - data->val_out = adapter->phy_regs.stat1000; - break; - case MII_ESTATUS: - data->val_out = adapter->phy_regs.estatus; - break; - default: - return -EIO; - } - break; - case SIOCSMIIREG: - default: - return -EOPNOTSUPP; - } - return 0; -} - -/** - * e1000e_hwtstamp_ioctl - control hardware time stamping - * @netdev: network interface device structure - * @ifreq: interface request - * - * Outgoing time stamping can be enabled and disabled. Play nice and - * disable it when requested, although it shouldn't cause any overhead - * when no packet needs it. At most one packet in the queue may be - * marked for time stamping, otherwise it would be impossible to tell - * for sure to which packet the hardware time stamp belongs. - * - * Incoming time stamping has to be configured via the hardware filters. - * Not all combinations are supported, in particular event type has to be - * specified. Matching the kind of event packet is not supported, with the - * exception of "all V2 events regardless of level 2 or 4". - **/ -static int e1000e_hwtstamp_ioctl(struct net_device *netdev, struct ifreq *ifr) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct hwtstamp_config config; - int ret_val; - - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - adapter->hwtstamp_config = config; - - ret_val = e1000e_config_hwtstamp(adapter); - if (ret_val) - return ret_val; - - config = adapter->hwtstamp_config; - - switch (config.rx_filter) { - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - /* With V2 type filters which specify a Sync or Delay Request, - * Path Delay Request/Response messages are also time stamped - * by hardware so notify the caller the requested packets plus - * some others are time stamped. - */ - config.rx_filter = HWTSTAMP_FILTER_SOME; - break; - default: - break; - } - - return copy_to_user(ifr->ifr_data, &config, - sizeof(config)) ? -EFAULT : 0; -} - -static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return e1000_mii_ioctl(netdev, ifr, cmd); - case SIOCSHWTSTAMP: - return e1000e_hwtstamp_ioctl(netdev, ifr); - default: - return -EOPNOTSUPP; - } -} - -static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) -{ - struct e1000_hw *hw = &adapter->hw; - u32 i, mac_reg; - u16 phy_reg, wuc_enable; - int retval; - - /* copy MAC RARs to PHY RARs */ - e1000_copy_rx_addrs_to_phy_ich8lan(hw); - - retval = hw->phy.ops.acquire(hw); - if (retval) { - e_err("Could not acquire PHY\n"); - return retval; - } - - /* Enable access to wakeup registers on and set page to BM_WUC_PAGE */ - retval = e1000_enable_phy_wakeup_reg_access_bm(hw, &wuc_enable); - if (retval) - goto release; - - /* copy MAC MTA to PHY MTA - only needed for pchlan */ - for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) { - mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i); - hw->phy.ops.write_reg_page(hw, BM_MTA(i), - (u16)(mac_reg & 0xFFFF)); - hw->phy.ops.write_reg_page(hw, BM_MTA(i) + 1, - (u16)((mac_reg >> 16) & 0xFFFF)); - } - - /* configure PHY Rx Control register */ - hw->phy.ops.read_reg_page(&adapter->hw, BM_RCTL, &phy_reg); - mac_reg = er32(RCTL); - if (mac_reg & E1000_RCTL_UPE) - phy_reg |= BM_RCTL_UPE; - if (mac_reg & E1000_RCTL_MPE) - phy_reg |= BM_RCTL_MPE; - phy_reg &= ~(BM_RCTL_MO_MASK); - if (mac_reg & E1000_RCTL_MO_3) - phy_reg |= (((mac_reg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT) - << BM_RCTL_MO_SHIFT); - if (mac_reg & E1000_RCTL_BAM) - phy_reg |= BM_RCTL_BAM; - if (mac_reg & E1000_RCTL_PMCF) - phy_reg |= BM_RCTL_PMCF; - mac_reg = er32(CTRL); - if (mac_reg & E1000_CTRL_RFCE) - phy_reg |= BM_RCTL_RFCE; - hw->phy.ops.write_reg_page(&adapter->hw, BM_RCTL, phy_reg); - - /* enable PHY wakeup in MAC register */ - ew32(WUFC, wufc); - ew32(WUC, E1000_WUC_PHY_WAKE | E1000_WUC_PME_EN); - - /* configure and enable PHY wakeup in PHY registers */ - hw->phy.ops.write_reg_page(&adapter->hw, BM_WUFC, wufc); - hw->phy.ops.write_reg_page(&adapter->hw, BM_WUC, E1000_WUC_PME_EN); - - /* activate PHY wakeup */ - wuc_enable |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT; - retval = e1000_disable_phy_wakeup_reg_access_bm(hw, &wuc_enable); - if (retval) - e_err("Could not set PHY Host Wakeup bit\n"); -release: - hw->phy.ops.release(hw); - - return retval; -} - -static int __e1000_shutdown(struct pci_dev *pdev, bool runtime) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 ctrl, ctrl_ext, rctl, status; - /* Runtime suspend should only enable wakeup for link changes */ - u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol; - int retval = 0; - - netif_device_detach(netdev); - - if (netif_running(netdev)) { - int count = E1000_CHECK_RESET_COUNT; - - while (test_bit(__E1000_RESETTING, &adapter->state) && count--) - usleep_range(10000, 20000); - - WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); - e1000e_down(adapter); - e1000_free_irq(adapter); - } - e1000e_reset_interrupt_capability(adapter); - - status = er32(STATUS); - if (status & E1000_STATUS_LU) - wufc &= ~E1000_WUFC_LNKC; - - if (wufc) { - e1000_setup_rctl(adapter); - e1000e_set_rx_mode(netdev); - - /* turn on all-multi mode if wake on multicast is enabled */ - if (wufc & E1000_WUFC_MC) { - rctl = er32(RCTL); - rctl |= E1000_RCTL_MPE; - ew32(RCTL, rctl); - } - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_ADVD3WUC; - if (!(adapter->flags2 & FLAG2_HAS_PHY_WAKEUP)) - ctrl |= E1000_CTRL_EN_PHY_PWR_MGMT; - ew32(CTRL, ctrl); - - if (adapter->hw.phy.media_type == e1000_media_type_fiber || - adapter->hw.phy.media_type == - e1000_media_type_internal_serdes) { - /* keep the laser running in D3 */ - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA; - ew32(CTRL_EXT, ctrl_ext); - } - - if (adapter->flags & FLAG_IS_ICH) - e1000_suspend_workarounds_ich8lan(&adapter->hw); - - /* Allow time for pending master requests to run */ - e1000e_disable_pcie_master(&adapter->hw); - - if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) { - /* enable wakeup by the PHY */ - retval = e1000_init_phy_wakeup(adapter, wufc); - if (retval) - return retval; - } else { - /* enable wakeup by the MAC */ - ew32(WUFC, wufc); - ew32(WUC, E1000_WUC_PME_EN); - } - } else { - ew32(WUC, 0); - ew32(WUFC, 0); - } - - if (adapter->hw.phy.type == e1000_phy_igp_3) - e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); - - /* Release control of h/w to f/w. If f/w is AMT enabled, this - * would have already happened in close and is redundant. - */ - e1000e_release_hw_control(adapter); - - /* The pci-e switch on some quad port adapters will report a - * correctable error when the MAC transitions from D0 to D3. To - * prevent this we need to mask off the correctable errors on the - * downstream port of the pci-e switch. - */ - if (adapter->flags & FLAG_IS_QUAD_PORT) { - struct pci_dev *us_dev = pdev->bus->self; - u16 devctl; - - pcie_capability_read_word(us_dev, PCI_EXP_DEVCTL, &devctl); - pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, - (devctl & ~PCI_EXP_DEVCTL_CERE)); - - pci_save_state(pdev); - pci_prepare_to_sleep(pdev); - - pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, devctl); - } - - return 0; -} - -#ifdef CONFIG_PCIEASPM -static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) -{ - pci_disable_link_state_locked(pdev, state); -} -#else -static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) -{ - u16 aspm_ctl = 0; - - if (state & PCIE_LINK_STATE_L0S) - aspm_ctl |= PCI_EXP_LNKCTL_ASPM_L0S; - if (state & PCIE_LINK_STATE_L1) - aspm_ctl |= PCI_EXP_LNKCTL_ASPM_L1; - - /* Both device and parent should have the same ASPM setting. - * Disable ASPM in downstream component first and then upstream. - */ - pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, aspm_ctl); - - if (pdev->bus->self) - pcie_capability_clear_word(pdev->bus->self, PCI_EXP_LNKCTL, - aspm_ctl); -} -#endif -static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state) -{ - dev_info(&pdev->dev, "Disabling ASPM %s %s\n", - (state & PCIE_LINK_STATE_L0S) ? "L0s" : "", - (state & PCIE_LINK_STATE_L1) ? "L1" : ""); - - __e1000e_disable_aspm(pdev, state); -} - -#ifdef CONFIG_PM -static bool e1000e_pm_ready(struct e1000_adapter *adapter) -{ - return !!adapter->tx_ring->buffer_info; -} - -static int __e1000_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 aspm_disable_flag = 0; - u32 err; - - if (adapter->flags2 & FLAG2_DISABLE_ASPM_L0S) - aspm_disable_flag = PCIE_LINK_STATE_L0S; - if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) - aspm_disable_flag |= PCIE_LINK_STATE_L1; - if (aspm_disable_flag) - e1000e_disable_aspm(pdev, aspm_disable_flag); - - pci_set_master(pdev); - - e1000e_set_interrupt_capability(adapter); - if (netif_running(netdev)) { - err = e1000_request_irq(adapter); - if (err) - return err; - } - - if (hw->mac.type >= e1000_pch2lan) - e1000_resume_workarounds_pchlan(&adapter->hw); - - e1000e_power_up_phy(adapter); - - /* report the system wakeup cause from S3/S4 */ - if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) { - u16 phy_data; - - e1e_rphy(&adapter->hw, BM_WUS, &phy_data); - if (phy_data) { - e_info("PHY Wakeup cause - %s\n", - phy_data & E1000_WUS_EX ? "Unicast Packet" : - phy_data & E1000_WUS_MC ? "Multicast Packet" : - phy_data & E1000_WUS_BC ? "Broadcast Packet" : - phy_data & E1000_WUS_MAG ? "Magic Packet" : - phy_data & E1000_WUS_LNKC ? - "Link Status Change" : "other"); - } - e1e_wphy(&adapter->hw, BM_WUS, ~0); - } else { - u32 wus = er32(WUS); - if (wus) { - e_info("MAC Wakeup cause - %s\n", - wus & E1000_WUS_EX ? "Unicast Packet" : - wus & E1000_WUS_MC ? "Multicast Packet" : - wus & E1000_WUS_BC ? "Broadcast Packet" : - wus & E1000_WUS_MAG ? "Magic Packet" : - wus & E1000_WUS_LNKC ? "Link Status Change" : - "other"); - } - ew32(WUS, ~0); - } - - e1000e_reset(adapter); - - e1000_init_manageability_pt(adapter); - - if (netif_running(netdev)) - e1000e_up(adapter); - - netif_device_attach(netdev); - - /* If the controller has AMT, do not set DRV_LOAD until the interface - * is up. For all other cases, let the f/w know that the h/w is now - * under the control of the driver. - */ - if (!(adapter->flags & FLAG_HAS_AMT)) - e1000e_get_hw_control(adapter); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int e1000_suspend(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - - return __e1000_shutdown(pdev, false); -} - -static int e1000_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (e1000e_pm_ready(adapter)) - adapter->idle_check = true; - - return __e1000_resume(pdev); -} -#endif /* CONFIG_PM_SLEEP */ - -#ifdef CONFIG_PM_RUNTIME -static int e1000_runtime_suspend(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (!e1000e_pm_ready(adapter)) - return 0; - - return __e1000_shutdown(pdev, true); -} - -static int e1000_idle(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (!e1000e_pm_ready(adapter)) - return 0; - - if (adapter->idle_check) { - adapter->idle_check = false; - if (!e1000e_has_link(adapter)) - pm_schedule_suspend(dev, MSEC_PER_SEC); - } - - return -EBUSY; -} - -static int e1000_runtime_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (!e1000e_pm_ready(adapter)) - return 0; - - adapter->idle_check = !dev->power.runtime_auto; - return __e1000_resume(pdev); -} -#endif /* CONFIG_PM_RUNTIME */ -#endif /* CONFIG_PM */ - -static void e1000_shutdown(struct pci_dev *pdev) -{ - __e1000_shutdown(pdev, false); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER - -static irqreturn_t e1000_intr_msix(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (adapter->msix_entries) { - int vector, msix_irq; - - vector = 0; - msix_irq = adapter->msix_entries[vector].vector; - disable_irq(msix_irq); - e1000_intr_msix_rx(msix_irq, netdev); - enable_irq(msix_irq); - - vector++; - msix_irq = adapter->msix_entries[vector].vector; - disable_irq(msix_irq); - e1000_intr_msix_tx(msix_irq, netdev); - enable_irq(msix_irq); - - vector++; - msix_irq = adapter->msix_entries[vector].vector; - disable_irq(msix_irq); - e1000_msix_other(msix_irq, netdev); - enable_irq(msix_irq); - } - - return IRQ_HANDLED; -} - -/** - * e1000_netpoll - * @netdev: network interface device structure - * - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void e1000_netpoll(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - switch (adapter->int_mode) { - case E1000E_INT_MODE_MSIX: - e1000_intr_msix(adapter->pdev->irq, netdev); - break; - case E1000E_INT_MODE_MSI: - disable_irq(adapter->pdev->irq); - e1000_intr_msi(adapter->pdev->irq, netdev); - enable_irq(adapter->pdev->irq); - break; - default: /* E1000E_INT_MODE_LEGACY */ - disable_irq(adapter->pdev->irq); - e1000_intr(adapter->pdev->irq, netdev); - enable_irq(adapter->pdev->irq); - break; - } -} -#endif - -/** - * e1000_io_error_detected - called when PCI error is detected - * @pdev: Pointer to PCI device - * @state: The current pci connection state - * - * This function is called after a PCI bus error affecting - * this device has been detected. - */ -static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, - pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e1000e_down(adapter); - pci_disable_device(pdev); - - /* Request a slot slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e1000_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch, as if from a cold-boot. Implementation - * resembles the first-half of the e1000_resume routine. - */ -static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 aspm_disable_flag = 0; - int err; - pci_ers_result_t result; - - if (adapter->flags2 & FLAG2_DISABLE_ASPM_L0S) - aspm_disable_flag = PCIE_LINK_STATE_L0S; - if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) - aspm_disable_flag |= PCIE_LINK_STATE_L1; - if (aspm_disable_flag) - e1000e_disable_aspm(pdev, aspm_disable_flag); - - err = pci_enable_device_mem(pdev); - if (err) { - dev_err(&pdev->dev, - "Cannot re-enable PCI device after reset.\n"); - result = PCI_ERS_RESULT_DISCONNECT; - } else { - pdev->state_saved = true; - pci_restore_state(pdev); - pci_set_master(pdev); - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - e1000e_reset(adapter); - ew32(WUS, ~0); - result = PCI_ERS_RESULT_RECOVERED; - } - - pci_cleanup_aer_uncorrect_error_status(pdev); - - return result; -} - -/** - * e1000_io_resume - called when traffic can start flowing again. - * @pdev: Pointer to PCI device - * - * This callback is called when the error recovery driver tells us that - * its OK to resume normal operation. Implementation resembles the - * second-half of the e1000_resume routine. - */ -static void e1000_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - - e1000_init_manageability_pt(adapter); - - if (netif_running(netdev)) { - if (e1000e_up(adapter)) { - dev_err(&pdev->dev, - "can't bring device back up after reset\n"); - return; - } - } - - netif_device_attach(netdev); - - /* If the controller has AMT, do not set DRV_LOAD until the interface - * is up. For all other cases, let the f/w know that the h/w is now - * under the control of the driver. - */ - if (!(adapter->flags & FLAG_HAS_AMT)) - e1000e_get_hw_control(adapter); -} - -static void e1000_print_device_info(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - u32 ret_val; - u8 pba_str[E1000_PBANUM_LENGTH]; - - /* print bus type/speed/width info */ - e_info("(PCI Express:2.5GT/s:%s) %pM\n", - /* bus width */ - ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" : - "Width x1"), - /* MAC address */ - netdev->dev_addr); - e_info("Intel(R) PRO/%s Network Connection\n", - (hw->phy.type == e1000_phy_ife) ? "10/100" : "1000"); - ret_val = e1000_read_pba_string_generic(hw, pba_str, - E1000_PBANUM_LENGTH); - if (ret_val) - strlcpy((char *)pba_str, "Unknown", sizeof(pba_str)); - e_info("MAC: %d, PHY: %d, PBA No: %s\n", - hw->mac.type, hw->phy.type, pba_str); -} - -static void e1000_eeprom_checks(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - int ret_val; - u16 buf = 0; - - if (hw->mac.type != e1000_82573) - return; - - ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &buf); - le16_to_cpus(&buf); - if (!ret_val && (!(buf & (1 << 0)))) { - /* Deep Smart Power Down (DSPD) */ - dev_warn(&adapter->pdev->dev, - "Warning: detected DSPD enabled in EEPROM\n"); - } -} - -static int e1000_set_features(struct net_device *netdev, - netdev_features_t features) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - netdev_features_t changed = features ^ netdev->features; - - if (changed & (NETIF_F_TSO | NETIF_F_TSO6)) - adapter->flags |= FLAG_TSO_FORCE; - - if (!(changed & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_RXCSUM | NETIF_F_RXHASH | NETIF_F_RXFCS | - NETIF_F_RXALL))) - return 0; - - if (changed & NETIF_F_RXFCS) { - if (features & NETIF_F_RXFCS) { - adapter->flags2 &= ~FLAG2_CRC_STRIPPING; - } else { - /* We need to take it back to defaults, which might mean - * stripping is still disabled at the adapter level. - */ - if (adapter->flags2 & FLAG2_DFLT_CRC_STRIPPING) - adapter->flags2 |= FLAG2_CRC_STRIPPING; - else - adapter->flags2 &= ~FLAG2_CRC_STRIPPING; - } - } - - netdev->features = features; - - if (netif_running(netdev)) - e1000e_reinit_locked(adapter); - else - e1000e_reset(adapter); - - return 0; -} - -static const struct net_device_ops e1000e_netdev_ops = { - .ndo_open = e1000_open, - .ndo_stop = e1000_close, - .ndo_start_xmit = e1000_xmit_frame, - .ndo_get_stats64 = e1000e_get_stats64, - .ndo_set_rx_mode = e1000e_set_rx_mode, - .ndo_set_mac_address = e1000_set_mac, - .ndo_change_mtu = e1000_change_mtu, - .ndo_do_ioctl = e1000_ioctl, - .ndo_tx_timeout = e1000_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - - .ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = e1000_vlan_rx_kill_vid, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e1000_netpoll, -#endif - .ndo_set_features = e1000_set_features, -}; - -/** - * e1000_probe - Device Initialization Routine - * @pdev: PCI device information struct - * @ent: entry in e1000_pci_tbl - * - * Returns 0 on success, negative on failure - * - * e1000_probe initializes an adapter identified by a pci_dev structure. - * The OS initialization, configuring of the adapter private structure, - * and a hardware reset occur. - **/ -static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct e1000_adapter *adapter; - struct e1000_hw *hw; - const struct e1000_info *ei = e1000_info_tbl[ent->driver_data]; - resource_size_t mmio_start, mmio_len; - resource_size_t flash_start, flash_len; - static int cards_found; - u16 aspm_disable_flag = 0; - int bars, i, err, pci_using_dac; - u16 eeprom_data = 0; - u16 eeprom_apme_mask = E1000_EEPROM_APME; - - if (ei->flags2 & FLAG2_DISABLE_ASPM_L0S) - aspm_disable_flag = PCIE_LINK_STATE_L0S; - if (ei->flags2 & FLAG2_DISABLE_ASPM_L1) - aspm_disable_flag |= PCIE_LINK_STATE_L1; - if (aspm_disable_flag) - e1000e_disable_aspm(pdev, aspm_disable_flag); - - err = pci_enable_device_mem(pdev); - if (err) - return err; - - pci_using_dac = 0; - err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)); - if (!err) { - err = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64)); - if (!err) - pci_using_dac = 1; - } else { - err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32)); - if (err) { - err = dma_set_coherent_mask(&pdev->dev, - DMA_BIT_MASK(32)); - if (err) { - dev_err(&pdev->dev, - "No usable DMA configuration, aborting\n"); - goto err_dma; - } - } - } - - bars = pci_select_bars(pdev, IORESOURCE_MEM); - err = pci_request_selected_regions_exclusive(pdev, bars, - e1000e_driver_name); - if (err) - goto err_pci_reg; - - /* AER (Advanced Error Reporting) hooks */ - pci_enable_pcie_error_reporting(pdev); - - pci_set_master(pdev); - /* PCI config space info */ - err = pci_save_state(pdev); - if (err) - goto err_alloc_etherdev; - - err = -ENOMEM; - netdev = alloc_etherdev(sizeof(struct e1000_adapter)); - if (!netdev) - goto err_alloc_etherdev; - - SET_NETDEV_DEV(netdev, &pdev->dev); - - netdev->irq = pdev->irq; - - pci_set_drvdata(pdev, netdev); - adapter = netdev_priv(netdev); - hw = &adapter->hw; - adapter->netdev = netdev; - adapter->pdev = pdev; - adapter->ei = ei; - adapter->pba = ei->pba; - adapter->flags = ei->flags; - adapter->flags2 = ei->flags2; - adapter->hw.adapter = adapter; - adapter->hw.mac.type = ei->mac; - adapter->max_hw_frame_size = ei->max_hw_frame_size; - adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); - - mmio_start = pci_resource_start(pdev, 0); - mmio_len = pci_resource_len(pdev, 0); - - err = -EIO; - adapter->hw.hw_addr = ioremap(mmio_start, mmio_len); - if (!adapter->hw.hw_addr) - goto err_ioremap; - - if ((adapter->flags & FLAG_HAS_FLASH) && - (pci_resource_flags(pdev, 1) & IORESOURCE_MEM)) { - flash_start = pci_resource_start(pdev, 1); - flash_len = pci_resource_len(pdev, 1); - adapter->hw.flash_address = ioremap(flash_start, flash_len); - if (!adapter->hw.flash_address) - goto err_flashmap; - } - - /* Set default EEE advertisement */ - if (adapter->flags2 & FLAG2_HAS_EEE) - adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T; - - /* construct the net_device struct */ - netdev->netdev_ops = &e1000e_netdev_ops; - e1000e_set_ethtool_ops(netdev); - netdev->watchdog_timeo = 5 * HZ; - netif_napi_add(netdev, &adapter->napi, e1000e_poll, 64); - strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name)); - - netdev->mem_start = mmio_start; - netdev->mem_end = mmio_start + mmio_len; - - adapter->bd_number = cards_found++; - - e1000e_check_options(adapter); - - /* setup adapter struct */ - err = e1000_sw_init(adapter); - if (err) - goto err_sw_init; - - memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops)); - memcpy(&hw->nvm.ops, ei->nvm_ops, sizeof(hw->nvm.ops)); - memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops)); - - err = ei->get_variants(adapter); - if (err) - goto err_hw_init; - - if ((adapter->flags & FLAG_IS_ICH) && - (adapter->flags & FLAG_READ_ONLY_NVM)) - e1000e_write_protect_nvm_ich8lan(&adapter->hw); - - hw->mac.ops.get_bus_info(&adapter->hw); - - adapter->hw.phy.autoneg_wait_to_complete = 0; - - /* Copper options */ - if (adapter->hw.phy.media_type == e1000_media_type_copper) { - adapter->hw.phy.mdix = AUTO_ALL_MODES; - adapter->hw.phy.disable_polarity_correction = 0; - adapter->hw.phy.ms_type = e1000_ms_hw_default; - } - - if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) - dev_info(&pdev->dev, - "PHY reset is blocked due to SOL/IDER session.\n"); - - /* Set initial default active device features */ - netdev->features = (NETIF_F_SG | - NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_TSO | - NETIF_F_TSO6 | - NETIF_F_RXHASH | - NETIF_F_RXCSUM | - NETIF_F_HW_CSUM); - - /* Set user-changeable features (subset of all device features) */ - netdev->hw_features = netdev->features; - netdev->hw_features |= NETIF_F_RXFCS; - netdev->priv_flags |= IFF_SUPP_NOFCS; - netdev->hw_features |= NETIF_F_RXALL; - - if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) - netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; - - netdev->vlan_features |= (NETIF_F_SG | - NETIF_F_TSO | - NETIF_F_TSO6 | - NETIF_F_HW_CSUM); - - netdev->priv_flags |= IFF_UNICAST_FLT; - - if (pci_using_dac) { - netdev->features |= NETIF_F_HIGHDMA; - netdev->vlan_features |= NETIF_F_HIGHDMA; - } - - if (e1000e_enable_mng_pass_thru(&adapter->hw)) - adapter->flags |= FLAG_MNG_PT_ENABLED; - - /* before reading the NVM, reset the controller to - * put the device in a known good starting state - */ - adapter->hw.mac.ops.reset_hw(&adapter->hw); - - /* systems with ASPM and others may see the checksum fail on the first - * attempt. Let's give it a few tries - */ - for (i = 0;; i++) { - if (e1000_validate_nvm_checksum(&adapter->hw) >= 0) - break; - if (i == 2) { - dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n"); - err = -EIO; - goto err_eeprom; - } - } - - e1000_eeprom_checks(adapter); - - /* copy the MAC address */ - if (e1000e_read_mac_addr(&adapter->hw)) - dev_err(&pdev->dev, - "NVM Read Error while reading MAC address\n"); - - memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len); - - if (!is_valid_ether_addr(netdev->dev_addr)) { - dev_err(&pdev->dev, "Invalid MAC Address: %pM\n", - netdev->dev_addr); - err = -EIO; - goto err_eeprom; - } - - init_timer(&adapter->watchdog_timer); - adapter->watchdog_timer.function = e1000_watchdog; - adapter->watchdog_timer.data = (unsigned long)adapter; - - init_timer(&adapter->phy_info_timer); - adapter->phy_info_timer.function = e1000_update_phy_info; - adapter->phy_info_timer.data = (unsigned long)adapter; - - INIT_WORK(&adapter->reset_task, e1000_reset_task); - INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task); - INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround); - INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task); - INIT_WORK(&adapter->print_hang_task, e1000_print_hw_hang); - - /* Initialize link parameters. User can change them with ethtool */ - adapter->hw.mac.autoneg = 1; - adapter->fc_autoneg = true; - adapter->hw.fc.requested_mode = e1000_fc_default; - adapter->hw.fc.current_mode = e1000_fc_default; - adapter->hw.phy.autoneg_advertised = 0x2f; - - /* ring size defaults */ - adapter->rx_ring->count = E1000_DEFAULT_RXD; - adapter->tx_ring->count = E1000_DEFAULT_TXD; - - /* Initial Wake on LAN setting - If APM wake is enabled in - * the EEPROM, enable the ACPI Magic Packet filter - */ - if (adapter->flags & FLAG_APME_IN_WUC) { - /* APME bit in EEPROM is mapped to WUC.APME */ - eeprom_data = er32(WUC); - eeprom_apme_mask = E1000_WUC_APME; - if ((hw->mac.type > e1000_ich10lan) && - (eeprom_data & E1000_WUC_PHY_WAKE)) - adapter->flags2 |= FLAG2_HAS_PHY_WAKEUP; - } else if (adapter->flags & FLAG_APME_IN_CTRL3) { - if (adapter->flags & FLAG_APME_CHECK_PORT_B && - (adapter->hw.bus.func == 1)) - e1000_read_nvm(&adapter->hw, NVM_INIT_CONTROL3_PORT_B, - 1, &eeprom_data); - else - e1000_read_nvm(&adapter->hw, NVM_INIT_CONTROL3_PORT_A, - 1, &eeprom_data); - } - - /* fetch WoL from EEPROM */ - if (eeprom_data & eeprom_apme_mask) - adapter->eeprom_wol |= E1000_WUFC_MAG; - - /* now that we have the eeprom settings, apply the special cases - * where the eeprom may be wrong or the board simply won't support - * wake on lan on a particular port - */ - if (!(adapter->flags & FLAG_HAS_WOL)) - adapter->eeprom_wol = 0; - - /* initialize the wol settings based on the eeprom settings */ - adapter->wol = adapter->eeprom_wol; - - /* make sure adapter isn't asleep if manageability is enabled */ - if (adapter->wol || (adapter->flags & FLAG_MNG_PT_ENABLED) || - (hw->mac.ops.check_mng_mode(hw))) - device_wakeup_enable(&pdev->dev); - - /* save off EEPROM version number */ - e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers); - - /* reset the hardware with the new settings */ - e1000e_reset(adapter); - - /* If the controller has AMT, do not set DRV_LOAD until the interface - * is up. For all other cases, let the f/w know that the h/w is now - * under the control of the driver. - */ - if (!(adapter->flags & FLAG_HAS_AMT)) - e1000e_get_hw_control(adapter); - - strlcpy(netdev->name, "eth%d", sizeof(netdev->name)); - err = register_netdev(netdev); - if (err) - goto err_register; - - /* carrier off reporting is important to ethtool even BEFORE open */ - netif_carrier_off(netdev); - - /* init PTP hardware clock */ - e1000e_ptp_init(adapter); - - e1000_print_device_info(adapter); - - if (pci_dev_run_wake(pdev)) - pm_runtime_put_noidle(&pdev->dev); - - return 0; - -err_register: - if (!(adapter->flags & FLAG_HAS_AMT)) - e1000e_release_hw_control(adapter); -err_eeprom: - if (hw->phy.ops.check_reset_block && !hw->phy.ops.check_reset_block(hw)) - e1000_phy_hw_reset(&adapter->hw); -err_hw_init: - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); -err_sw_init: - if (adapter->hw.flash_address) - iounmap(adapter->hw.flash_address); - e1000e_reset_interrupt_capability(adapter); -err_flashmap: - iounmap(adapter->hw.hw_addr); -err_ioremap: - free_netdev(netdev); -err_alloc_etherdev: - pci_release_selected_regions(pdev, - pci_select_bars(pdev, IORESOURCE_MEM)); -err_pci_reg: -err_dma: - pci_disable_device(pdev); - return err; -} - -/** - * e1000_remove - Device Removal Routine - * @pdev: PCI device information struct - * - * e1000_remove is called by the PCI subsystem to alert the driver - * that it should release a PCI device. The could be caused by a - * Hot-Plug event, or because the driver is going to be removed from - * memory. - **/ -static void e1000_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - bool down = test_bit(__E1000_DOWN, &adapter->state); - - e1000e_ptp_remove(adapter); - - /* The timers may be rescheduled, so explicitly disable them - * from being rescheduled. - */ - if (!down) - set_bit(__E1000_DOWN, &adapter->state); - del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->phy_info_timer); - - cancel_work_sync(&adapter->reset_task); - cancel_work_sync(&adapter->watchdog_task); - cancel_work_sync(&adapter->downshift_task); - cancel_work_sync(&adapter->update_phy_task); - cancel_work_sync(&adapter->print_hang_task); - - if (adapter->flags & FLAG_HAS_HW_TIMESTAMP) { - cancel_work_sync(&adapter->tx_hwtstamp_work); - if (adapter->tx_hwtstamp_skb) { - dev_kfree_skb_any(adapter->tx_hwtstamp_skb); - adapter->tx_hwtstamp_skb = NULL; - } - } - - if (!(netdev->flags & IFF_UP)) - e1000_power_down_phy(adapter); - - /* Don't lie to e1000_close() down the road. */ - if (!down) - clear_bit(__E1000_DOWN, &adapter->state); - unregister_netdev(netdev); - - if (pci_dev_run_wake(pdev)) - pm_runtime_get_noresume(&pdev->dev); - - /* Release control of h/w to f/w. If f/w is AMT enabled, this - * would have already happened in close and is redundant. - */ - e1000e_release_hw_control(adapter); - - e1000e_reset_interrupt_capability(adapter); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - - iounmap(adapter->hw.hw_addr); - if (adapter->hw.flash_address) - iounmap(adapter->hw.flash_address); - pci_release_selected_regions(pdev, - pci_select_bars(pdev, IORESOURCE_MEM)); - - free_netdev(netdev); - - /* AER disable */ - pci_disable_pcie_error_reporting(pdev); - - pci_disable_device(pdev); -} - -/* PCI Error Recovery (ERS) */ -static const struct pci_error_handlers e1000_err_handler = { - .error_detected = e1000_io_error_detected, - .slot_reset = e1000_io_slot_reset, - .resume = e1000_io_resume, -}; - -static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_COPPER), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_FIBER), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_LP), - board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_FIBER), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_DUAL), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_QUAD), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571PT_QUAD_COPPER), board_82571 }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI), board_82572 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_COPPER), board_82572 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_FIBER), board_82572 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_SERDES), board_82572 }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573E), board_82573 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573E_IAMT), board_82573 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573L), board_82573 }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82574L), board_82574 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82574LA), board_82574 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82583V), board_82583 }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_DPT), - board_80003es2lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_SPT), - board_80003es2lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_SERDES_DPT), - board_80003es2lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_SERDES_SPT), - board_80003es2lan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE_G), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE_GT), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_AMT), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_C), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M_AMT), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_82567V_3), board_ich8lan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_G), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_GT), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_AMT), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_C), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_BM), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_AMT), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_V), board_ich9lan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LM), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LF), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_V), board_ich9lan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich10lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich10lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_V), board_ich10lan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LM), board_pchlan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LC), board_pchlan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DM), board_pchlan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DC), board_pchlan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_LM), board_pch2lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_V), board_pch2lan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_LM), board_pch_lpt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_V), board_pch_lpt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPTLP_I218_LM), board_pch_lpt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPTLP_I218_V), board_pch_lpt }, - - { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */ -}; -MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); - -#ifdef CONFIG_PM -static const struct dev_pm_ops e1000_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume) - SET_RUNTIME_PM_OPS(e1000_runtime_suspend, e1000_runtime_resume, - e1000_idle) -}; -#endif - -/* PCI Device API Driver */ -static struct pci_driver e1000_driver = { - .name = e1000e_driver_name, - .id_table = e1000_pci_tbl, - .probe = e1000_probe, - .remove = e1000_remove, -#ifdef CONFIG_PM - .driver = { - .pm = &e1000_pm_ops, - }, -#endif - .shutdown = e1000_shutdown, - .err_handler = &e1000_err_handler -}; - -/** - * e1000_init_module - Driver Registration Routine - * - * e1000_init_module is the first routine called when the driver is - * loaded. All it does is register with the PCI subsystem. - **/ -static int __init e1000_init_module(void) -{ - int ret; - pr_info("Intel(R) PRO/1000 Network Driver - %s\n", - e1000e_driver_version); - pr_info("Copyright(c) 1999 - 2013 Intel Corporation.\n"); - ret = pci_register_driver(&e1000_driver); - - return ret; -} -module_init(e1000_init_module); - -/** - * e1000_exit_module - Driver Exit Cleanup Routine - * - * e1000_exit_module is called just before the driver is removed - * from memory. - **/ -static void __exit e1000_exit_module(void) -{ - pci_unregister_driver(&e1000_driver); -} -module_exit(e1000_exit_module); - - -MODULE_AUTHOR("Intel Corporation, "); -MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -/* netdev.c */ diff --git a/addons/e1000e/src/3.10.108/nvm.c b/addons/e1000e/src/3.10.108/nvm.c deleted file mode 100644 index 44ddc0a0..00000000 --- a/addons/e1000e/src/3.10.108/nvm.c +++ /dev/null @@ -1,638 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include "e1000.h" - -/** - * e1000_raise_eec_clk - Raise EEPROM clock - * @hw: pointer to the HW structure - * @eecd: pointer to the EEPROM - * - * Enable/Raise the EEPROM clock bit. - **/ -static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) -{ - *eecd = *eecd | E1000_EECD_SK; - ew32(EECD, *eecd); - e1e_flush(); - udelay(hw->nvm.delay_usec); -} - -/** - * e1000_lower_eec_clk - Lower EEPROM clock - * @hw: pointer to the HW structure - * @eecd: pointer to the EEPROM - * - * Clear/Lower the EEPROM clock bit. - **/ -static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) -{ - *eecd = *eecd & ~E1000_EECD_SK; - ew32(EECD, *eecd); - e1e_flush(); - udelay(hw->nvm.delay_usec); -} - -/** - * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM - * @hw: pointer to the HW structure - * @data: data to send to the EEPROM - * @count: number of bits to shift out - * - * We need to shift 'count' bits out to the EEPROM. So, the value in the - * "data" parameter will be shifted out to the EEPROM one bit at a time. - * In order to do this, "data" must be broken down into bits. - **/ -static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - u32 mask; - - mask = 0x01 << (count - 1); - if (nvm->type == e1000_nvm_eeprom_spi) - eecd |= E1000_EECD_DO; - - do { - eecd &= ~E1000_EECD_DI; - - if (data & mask) - eecd |= E1000_EECD_DI; - - ew32(EECD, eecd); - e1e_flush(); - - udelay(nvm->delay_usec); - - e1000_raise_eec_clk(hw, &eecd); - e1000_lower_eec_clk(hw, &eecd); - - mask >>= 1; - } while (mask); - - eecd &= ~E1000_EECD_DI; - ew32(EECD, eecd); -} - -/** - * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM - * @hw: pointer to the HW structure - * @count: number of bits to shift in - * - * In order to read a register from the EEPROM, we need to shift 'count' bits - * in from the EEPROM. Bits are "shifted in" by raising the clock input to - * the EEPROM (setting the SK bit), and then reading the value of the data out - * "DO" bit. During this "shifting in" process the data in "DI" bit should - * always be clear. - **/ -static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) -{ - u32 eecd; - u32 i; - u16 data; - - eecd = er32(EECD); - - eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); - data = 0; - - for (i = 0; i < count; i++) { - data <<= 1; - e1000_raise_eec_clk(hw, &eecd); - - eecd = er32(EECD); - - eecd &= ~E1000_EECD_DI; - if (eecd & E1000_EECD_DO) - data |= 1; - - e1000_lower_eec_clk(hw, &eecd); - } - - return data; -} - -/** - * e1000e_poll_eerd_eewr_done - Poll for EEPROM read/write completion - * @hw: pointer to the HW structure - * @ee_reg: EEPROM flag for polling - * - * Polls the EEPROM status bit for either read or write completion based - * upon the value of 'ee_reg'. - **/ -s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) -{ - u32 attempts = 100000; - u32 i, reg = 0; - - for (i = 0; i < attempts; i++) { - if (ee_reg == E1000_NVM_POLL_READ) - reg = er32(EERD); - else - reg = er32(EEWR); - - if (reg & E1000_NVM_RW_REG_DONE) - return 0; - - udelay(5); - } - - return -E1000_ERR_NVM; -} - -/** - * e1000e_acquire_nvm - Generic request for access to EEPROM - * @hw: pointer to the HW structure - * - * Set the EEPROM access request bit and wait for EEPROM access grant bit. - * Return successful if access grant bit set, else clear the request for - * EEPROM access and return -E1000_ERR_NVM (-1). - **/ -s32 e1000e_acquire_nvm(struct e1000_hw *hw) -{ - u32 eecd = er32(EECD); - s32 timeout = E1000_NVM_GRANT_ATTEMPTS; - - ew32(EECD, eecd | E1000_EECD_REQ); - eecd = er32(EECD); - - while (timeout) { - if (eecd & E1000_EECD_GNT) - break; - udelay(5); - eecd = er32(EECD); - timeout--; - } - - if (!timeout) { - eecd &= ~E1000_EECD_REQ; - ew32(EECD, eecd); - e_dbg("Could not acquire NVM grant\n"); - return -E1000_ERR_NVM; - } - - return 0; -} - -/** - * e1000_standby_nvm - Return EEPROM to standby state - * @hw: pointer to the HW structure - * - * Return the EEPROM to a standby state. - **/ -static void e1000_standby_nvm(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - - if (nvm->type == e1000_nvm_eeprom_spi) { - /* Toggle CS to flush commands */ - eecd |= E1000_EECD_CS; - ew32(EECD, eecd); - e1e_flush(); - udelay(nvm->delay_usec); - eecd &= ~E1000_EECD_CS; - ew32(EECD, eecd); - e1e_flush(); - udelay(nvm->delay_usec); - } -} - -/** - * e1000_stop_nvm - Terminate EEPROM command - * @hw: pointer to the HW structure - * - * Terminates the current command by inverting the EEPROM's chip select pin. - **/ -static void e1000_stop_nvm(struct e1000_hw *hw) -{ - u32 eecd; - - eecd = er32(EECD); - if (hw->nvm.type == e1000_nvm_eeprom_spi) { - /* Pull CS high */ - eecd |= E1000_EECD_CS; - e1000_lower_eec_clk(hw, &eecd); - } -} - -/** - * e1000e_release_nvm - Release exclusive access to EEPROM - * @hw: pointer to the HW structure - * - * Stop any current commands to the EEPROM and clear the EEPROM request bit. - **/ -void e1000e_release_nvm(struct e1000_hw *hw) -{ - u32 eecd; - - e1000_stop_nvm(hw); - - eecd = er32(EECD); - eecd &= ~E1000_EECD_REQ; - ew32(EECD, eecd); -} - -/** - * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write - * @hw: pointer to the HW structure - * - * Setups the EEPROM for reading and writing. - **/ -static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - u8 spi_stat_reg; - - if (nvm->type == e1000_nvm_eeprom_spi) { - u16 timeout = NVM_MAX_RETRY_SPI; - - /* Clear SK and CS */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - ew32(EECD, eecd); - e1e_flush(); - udelay(1); - - /* Read "Status Register" repeatedly until the LSB is cleared. - * The EEPROM will signal that the command has been completed - * by clearing bit 0 of the internal status register. If it's - * not cleared within 'timeout', then error out. - */ - while (timeout) { - e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, - hw->nvm.opcode_bits); - spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8); - if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) - break; - - udelay(5); - e1000_standby_nvm(hw); - timeout--; - } - - if (!timeout) { - e_dbg("SPI NVM Status error\n"); - return -E1000_ERR_NVM; - } - } - - return 0; -} - -/** - * e1000e_read_nvm_eerd - Reads EEPROM using EERD register - * @hw: pointer to the HW structure - * @offset: offset of word in the EEPROM to read - * @words: number of words to read - * @data: word read from the EEPROM - * - * Reads a 16 bit word from the EEPROM using the EERD register. - **/ -s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 i, eerd = 0; - s32 ret_val = 0; - - /* A check for invalid values: offset too large, too many words, - * too many words for the offset, and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - return -E1000_ERR_NVM; - } - - for (i = 0; i < words; i++) { - eerd = ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) + - E1000_NVM_RW_REG_START; - - ew32(EERD, eerd); - ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); - if (ret_val) - break; - - data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA); - } - - return ret_val; -} - -/** - * e1000e_write_nvm_spi - Write to EEPROM using SPI - * @hw: pointer to the HW structure - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the EEPROM - * - * Writes data to EEPROM at offset using SPI interface. - * - * If e1000e_update_nvm_checksum is not called after this function , the - * EEPROM will most likely contain an invalid checksum. - **/ -s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val = -E1000_ERR_NVM; - u16 widx = 0; - - /* A check for invalid values: offset too large, too many words, - * and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - return -E1000_ERR_NVM; - } - - while (widx < words) { - u8 write_opcode = NVM_WRITE_OPCODE_SPI; - - ret_val = nvm->ops.acquire(hw); - if (ret_val) - return ret_val; - - ret_val = e1000_ready_nvm_eeprom(hw); - if (ret_val) { - nvm->ops.release(hw); - return ret_val; - } - - e1000_standby_nvm(hw); - - /* Send the WRITE ENABLE command (8 bit opcode) */ - e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, - nvm->opcode_bits); - - e1000_standby_nvm(hw); - - /* Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((nvm->address_bits == 8) && (offset >= 128)) - write_opcode |= NVM_A8_OPCODE_SPI; - - /* Send the Write command (8-bit opcode + addr) */ - e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); - e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), - nvm->address_bits); - - /* Loop to allow for up to whole page write of eeprom */ - while (widx < words) { - u16 word_out = data[widx]; - word_out = (word_out >> 8) | (word_out << 8); - e1000_shift_out_eec_bits(hw, word_out, 16); - widx++; - - if ((((offset + widx) * 2) % nvm->page_size) == 0) { - e1000_standby_nvm(hw); - break; - } - } - usleep_range(10000, 20000); - nvm->ops.release(hw); - } - - return ret_val; -} - -/** - * e1000_read_pba_string_generic - Read device part number - * @hw: pointer to the HW structure - * @pba_num: pointer to device part number - * @pba_num_size: size of part number buffer - * - * Reads the product board assembly (PBA) number from the EEPROM and stores - * the value in pba_num. - **/ -s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, - u32 pba_num_size) -{ - s32 ret_val; - u16 nvm_data; - u16 pba_ptr; - u16 offset; - u16 length; - - if (pba_num == NULL) { - e_dbg("PBA string buffer was null\n"); - return -E1000_ERR_INVALID_ARGUMENT; - } - - ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - /* if nvm_data is not ptr guard the PBA must be in legacy format which - * means pba_ptr is actually our second data word for the PBA number - * and we can decode it into an ascii string - */ - if (nvm_data != NVM_PBA_PTR_GUARD) { - e_dbg("NVM PBA number is not stored as string\n"); - - /* make sure callers buffer is big enough to store the PBA */ - if (pba_num_size < E1000_PBANUM_LENGTH) { - e_dbg("PBA string buffer too small\n"); - return E1000_ERR_NO_SPACE; - } - - /* extract hex string from data and pba_ptr */ - pba_num[0] = (nvm_data >> 12) & 0xF; - pba_num[1] = (nvm_data >> 8) & 0xF; - pba_num[2] = (nvm_data >> 4) & 0xF; - pba_num[3] = nvm_data & 0xF; - pba_num[4] = (pba_ptr >> 12) & 0xF; - pba_num[5] = (pba_ptr >> 8) & 0xF; - pba_num[6] = '-'; - pba_num[7] = 0; - pba_num[8] = (pba_ptr >> 4) & 0xF; - pba_num[9] = pba_ptr & 0xF; - - /* put a null character on the end of our string */ - pba_num[10] = '\0'; - - /* switch all the data but the '-' to hex char */ - for (offset = 0; offset < 10; offset++) { - if (pba_num[offset] < 0xA) - pba_num[offset] += '0'; - else if (pba_num[offset] < 0x10) - pba_num[offset] += 'A' - 0xA; - } - - return 0; - } - - ret_val = e1000_read_nvm(hw, pba_ptr, 1, &length); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - if (length == 0xFFFF || length == 0) { - e_dbg("NVM PBA number section invalid length\n"); - return -E1000_ERR_NVM_PBA_SECTION; - } - /* check if pba_num buffer is big enough */ - if (pba_num_size < (((u32)length * 2) - 1)) { - e_dbg("PBA string buffer too small\n"); - return -E1000_ERR_NO_SPACE; - } - - /* trim pba length from start of string */ - pba_ptr++; - length--; - - for (offset = 0; offset < length; offset++) { - ret_val = e1000_read_nvm(hw, pba_ptr + offset, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - pba_num[offset * 2] = (u8)(nvm_data >> 8); - pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF); - } - pba_num[offset * 2] = '\0'; - - return 0; -} - -/** - * e1000_read_mac_addr_generic - Read device MAC address - * @hw: pointer to the HW structure - * - * Reads the device MAC address from the EEPROM and stores the value. - * Since devices with two ports use the same EEPROM, we increment the - * last bit in the MAC address for the second port. - **/ -s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) -{ - u32 rar_high; - u32 rar_low; - u16 i; - - rar_high = er32(RAH(0)); - rar_low = er32(RAL(0)); - - for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) - hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8)); - - for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) - hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8)); - - for (i = 0; i < ETH_ALEN; i++) - hw->mac.addr[i] = hw->mac.perm_addr[i]; - - return 0; -} - -/** - * e1000e_validate_nvm_checksum_generic - Validate EEPROM checksum - * @hw: pointer to the HW structure - * - * Calculates the EEPROM checksum by reading/adding each word of the EEPROM - * and then verifies that the sum of the EEPROM is equal to 0xBABA. - **/ -s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw) -{ - s32 ret_val; - u16 checksum = 0; - u16 i, nvm_data; - - for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { - ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - checksum += nvm_data; - } - - if (checksum != (u16)NVM_SUM) { - e_dbg("NVM Checksum Invalid\n"); - return -E1000_ERR_NVM; - } - - return 0; -} - -/** - * e1000e_update_nvm_checksum_generic - Update EEPROM checksum - * @hw: pointer to the HW structure - * - * Updates the EEPROM checksum by reading/adding each word of the EEPROM - * up to the checksum. Then calculates the EEPROM checksum and writes the - * value to the EEPROM. - **/ -s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw) -{ - s32 ret_val; - u16 checksum = 0; - u16 i, nvm_data; - - for (i = 0; i < NVM_CHECKSUM_REG; i++) { - ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error while updating checksum.\n"); - return ret_val; - } - checksum += nvm_data; - } - checksum = (u16)NVM_SUM - checksum; - ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum); - if (ret_val) - e_dbg("NVM Write Error while updating checksum.\n"); - - return ret_val; -} - -/** - * e1000e_reload_nvm_generic - Reloads EEPROM - * @hw: pointer to the HW structure - * - * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the - * extended control register. - **/ -void e1000e_reload_nvm_generic(struct e1000_hw *hw) -{ - u32 ctrl_ext; - - usleep_range(10, 20); - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - ew32(CTRL_EXT, ctrl_ext); - e1e_flush(); -} diff --git a/addons/e1000e/src/3.10.108/nvm.h b/addons/e1000e/src/3.10.108/nvm.h deleted file mode 100644 index 45fc6956..00000000 --- a/addons/e1000e/src/3.10.108/nvm.h +++ /dev/null @@ -1,47 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#ifndef _E1000E_NVM_H_ -#define _E1000E_NVM_H_ - -s32 e1000e_acquire_nvm(struct e1000_hw *hw); - -s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); -s32 e1000_read_mac_addr_generic(struct e1000_hw *hw); -s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, - u32 pba_num_size); -s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); -s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data); -s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw); -s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); -s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw); -void e1000e_release_nvm(struct e1000_hw *hw); - -#define E1000_STM_OPCODE 0xDB00 - -#endif diff --git a/addons/e1000e/src/3.10.108/param.c b/addons/e1000e/src/3.10.108/param.c deleted file mode 100644 index c16bd75b..00000000 --- a/addons/e1000e/src/3.10.108/param.c +++ /dev/null @@ -1,530 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include -#include -#include - -#include "e1000.h" - -/* This is the only thing that needs to be changed to adjust the - * maximum number of ports that the driver can manage. - */ -#define E1000_MAX_NIC 32 - -#define OPTION_UNSET -1 -#define OPTION_DISABLED 0 -#define OPTION_ENABLED 1 - -#define COPYBREAK_DEFAULT 256 -unsigned int copybreak = COPYBREAK_DEFAULT; -module_param(copybreak, uint, 0644); -MODULE_PARM_DESC(copybreak, - "Maximum size of packet that is copied to a new buffer on receive"); - -/* All parameters are treated the same, as an integer array of values. - * This macro just reduces the need to repeat the same declaration code - * over and over (plus this helps to avoid typo bugs). - */ -#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } -#define E1000_PARAM(X, desc) \ - static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ - static unsigned int num_##X; \ - module_param_array_named(X, X, int, &num_##X, 0); \ - MODULE_PARM_DESC(X, desc); - -/* Transmit Interrupt Delay in units of 1.024 microseconds - * Tx interrupt delay needs to typically be set to something non-zero - * - * Valid Range: 0-65535 - */ -E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay"); -#define DEFAULT_TIDV 8 -#define MAX_TXDELAY 0xFFFF -#define MIN_TXDELAY 0 - -/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds - * - * Valid Range: 0-65535 - */ -E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay"); -#define DEFAULT_TADV 32 -#define MAX_TXABSDELAY 0xFFFF -#define MIN_TXABSDELAY 0 - -/* Receive Interrupt Delay in units of 1.024 microseconds - * hardware will likely hang if you set this to anything but zero. - * - * Valid Range: 0-65535 - */ -E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); -#define MAX_RXDELAY 0xFFFF -#define MIN_RXDELAY 0 - -/* Receive Absolute Interrupt Delay in units of 1.024 microseconds - * - * Valid Range: 0-65535 - */ -E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); -#define MAX_RXABSDELAY 0xFFFF -#define MIN_RXABSDELAY 0 - -/* Interrupt Throttle Rate (interrupts/sec) - * - * Valid Range: 100-100000 or one of: 0=off, 1=dynamic, 3=dynamic conservative - */ -E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); -#define DEFAULT_ITR 3 -#define MAX_ITR 100000 -#define MIN_ITR 100 - -/* IntMode (Interrupt Mode) - * - * Valid Range: varies depending on kernel configuration & hardware support - * - * legacy=0, MSI=1, MSI-X=2 - * - * When MSI/MSI-X support is enabled in kernel- - * Default Value: 2 (MSI-X) when supported by hardware, 1 (MSI) otherwise - * When MSI/MSI-X support is not enabled in kernel- - * Default Value: 0 (legacy) - * - * When a mode is specified that is not allowed/supported, it will be - * demoted to the most advanced interrupt mode available. - */ -E1000_PARAM(IntMode, "Interrupt Mode"); -#define MAX_INTMODE 2 -#define MIN_INTMODE 0 - -/* Enable Smart Power Down of the PHY - * - * Valid Range: 0, 1 - * - * Default Value: 0 (disabled) - */ -E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down"); - -/* Enable Kumeran Lock Loss workaround - * - * Valid Range: 0, 1 - * - * Default Value: 1 (enabled) - */ -E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); - -/* Write Protect NVM - * - * Valid Range: 0, 1 - * - * Default Value: 1 (enabled) - */ -E1000_PARAM(WriteProtectNVM, - "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]"); - -/* Enable CRC Stripping - * - * Valid Range: 0, 1 - * - * Default Value: 1 (enabled) - */ -E1000_PARAM(CrcStripping, - "Enable CRC Stripping, disable if your BMC needs the CRC"); - -struct e1000_option { - enum { enable_option, range_option, list_option } type; - const char *name; - const char *err; - int def; - union { - /* range_option info */ - struct { - int min; - int max; - } r; - /* list_option info */ - struct { - int nr; - struct e1000_opt_list { - int i; - char *str; - } *p; - } l; - } arg; -}; - -static int e1000_validate_option(unsigned int *value, - const struct e1000_option *opt, - struct e1000_adapter *adapter) -{ - if (*value == OPTION_UNSET) { - *value = opt->def; - return 0; - } - - switch (opt->type) { - case enable_option: - switch (*value) { - case OPTION_ENABLED: - dev_info(&adapter->pdev->dev, "%s Enabled\n", - opt->name); - return 0; - case OPTION_DISABLED: - dev_info(&adapter->pdev->dev, "%s Disabled\n", - opt->name); - return 0; - } - break; - case range_option: - if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { - dev_info(&adapter->pdev->dev, "%s set to %i\n", - opt->name, *value); - return 0; - } - break; - case list_option: { - int i; - struct e1000_opt_list *ent; - - for (i = 0; i < opt->arg.l.nr; i++) { - ent = &opt->arg.l.p[i]; - if (*value == ent->i) { - if (ent->str[0] != '\0') - dev_info(&adapter->pdev->dev, "%s\n", - ent->str); - return 0; - } - } - } - break; - default: - BUG(); - } - - dev_info(&adapter->pdev->dev, "Invalid %s value specified (%i) %s\n", - opt->name, *value, opt->err); - *value = opt->def; - return -1; -} - -/** - * e1000e_check_options - Range Checking for Command Line Parameters - * @adapter: board private structure - * - * This routine checks all command line parameters for valid user - * input. If an invalid value is given, or if no user specified - * value exists, a default value is used. The final value is stored - * in a variable in the adapter structure. - **/ -void e1000e_check_options(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - int bd = adapter->bd_number; - - if (bd >= E1000_MAX_NIC) { - dev_notice(&adapter->pdev->dev, - "Warning: no configuration for board #%i\n", bd); - dev_notice(&adapter->pdev->dev, - "Using defaults for all values\n"); - } - - /* Transmit Interrupt Delay */ - { - static const struct e1000_option opt = { - .type = range_option, - .name = "Transmit Interrupt Delay", - .err = "using default of " - __MODULE_STRING(DEFAULT_TIDV), - .def = DEFAULT_TIDV, - .arg = { .r = { .min = MIN_TXDELAY, - .max = MAX_TXDELAY } } - }; - - if (num_TxIntDelay > bd) { - adapter->tx_int_delay = TxIntDelay[bd]; - e1000_validate_option(&adapter->tx_int_delay, &opt, - adapter); - } else { - adapter->tx_int_delay = opt.def; - } - } - /* Transmit Absolute Interrupt Delay */ - { - static const struct e1000_option opt = { - .type = range_option, - .name = "Transmit Absolute Interrupt Delay", - .err = "using default of " - __MODULE_STRING(DEFAULT_TADV), - .def = DEFAULT_TADV, - .arg = { .r = { .min = MIN_TXABSDELAY, - .max = MAX_TXABSDELAY } } - }; - - if (num_TxAbsIntDelay > bd) { - adapter->tx_abs_int_delay = TxAbsIntDelay[bd]; - e1000_validate_option(&adapter->tx_abs_int_delay, &opt, - adapter); - } else { - adapter->tx_abs_int_delay = opt.def; - } - } - /* Receive Interrupt Delay */ - { - static struct e1000_option opt = { - .type = range_option, - .name = "Receive Interrupt Delay", - .err = "using default of " - __MODULE_STRING(DEFAULT_RDTR), - .def = DEFAULT_RDTR, - .arg = { .r = { .min = MIN_RXDELAY, - .max = MAX_RXDELAY } } - }; - - if (num_RxIntDelay > bd) { - adapter->rx_int_delay = RxIntDelay[bd]; - e1000_validate_option(&adapter->rx_int_delay, &opt, - adapter); - } else { - adapter->rx_int_delay = opt.def; - } - } - /* Receive Absolute Interrupt Delay */ - { - static const struct e1000_option opt = { - .type = range_option, - .name = "Receive Absolute Interrupt Delay", - .err = "using default of " - __MODULE_STRING(DEFAULT_RADV), - .def = DEFAULT_RADV, - .arg = { .r = { .min = MIN_RXABSDELAY, - .max = MAX_RXABSDELAY } } - }; - - if (num_RxAbsIntDelay > bd) { - adapter->rx_abs_int_delay = RxAbsIntDelay[bd]; - e1000_validate_option(&adapter->rx_abs_int_delay, &opt, - adapter); - } else { - adapter->rx_abs_int_delay = opt.def; - } - } - /* Interrupt Throttling Rate */ - { - static const struct e1000_option opt = { - .type = range_option, - .name = "Interrupt Throttling Rate (ints/sec)", - .err = "using default of " - __MODULE_STRING(DEFAULT_ITR), - .def = DEFAULT_ITR, - .arg = { .r = { .min = MIN_ITR, - .max = MAX_ITR } } - }; - - if (num_InterruptThrottleRate > bd) { - adapter->itr = InterruptThrottleRate[bd]; - - /* Make sure a message is printed for non-special - * values. And in case of an invalid option, display - * warning, use default and go through itr/itr_setting - * adjustment logic below - */ - if ((adapter->itr > 4) && - e1000_validate_option(&adapter->itr, &opt, adapter)) - adapter->itr = opt.def; - } else { - /* If no option specified, use default value and go - * through the logic below to adjust itr/itr_setting - */ - adapter->itr = opt.def; - - /* Make sure a message is printed for non-special - * default values - */ - if (adapter->itr > 4) - dev_info(&adapter->pdev->dev, - "%s set to default %d\n", opt.name, - adapter->itr); - } - - adapter->itr_setting = adapter->itr; - switch (adapter->itr) { - case 0: - dev_info(&adapter->pdev->dev, "%s turned off\n", - opt.name); - break; - case 1: - dev_info(&adapter->pdev->dev, - "%s set to dynamic mode\n", opt.name); - adapter->itr = 20000; - break; - case 3: - dev_info(&adapter->pdev->dev, - "%s set to dynamic conservative mode\n", - opt.name); - adapter->itr = 20000; - break; - case 4: - dev_info(&adapter->pdev->dev, - "%s set to simplified (2000-8000 ints) mode\n", - opt.name); - break; - default: - /* Save the setting, because the dynamic bits - * change itr. - * - * Clear the lower two bits because - * they are used as control. - */ - adapter->itr_setting &= ~3; - break; - } - } - /* Interrupt Mode */ - { - static struct e1000_option opt = { - .type = range_option, - .name = "Interrupt Mode", -#ifndef CONFIG_PCI_MSI - .err = "defaulting to 0 (legacy)", - .def = E1000E_INT_MODE_LEGACY, - .arg = { .r = { .min = 0, - .max = 0 } } -#endif - }; - -#ifdef CONFIG_PCI_MSI - if (adapter->flags & FLAG_HAS_MSIX) { - opt.err = kstrdup("defaulting to 2 (MSI-X)", - GFP_KERNEL); - opt.def = E1000E_INT_MODE_MSIX; - opt.arg.r.max = E1000E_INT_MODE_MSIX; - } else { - opt.err = kstrdup("defaulting to 1 (MSI)", GFP_KERNEL); - opt.def = E1000E_INT_MODE_MSI; - opt.arg.r.max = E1000E_INT_MODE_MSI; - } - - if (!opt.err) { - dev_err(&adapter->pdev->dev, - "Failed to allocate memory\n"); - return; - } -#endif - - if (num_IntMode > bd) { - unsigned int int_mode = IntMode[bd]; - e1000_validate_option(&int_mode, &opt, adapter); - adapter->int_mode = int_mode; - } else { - adapter->int_mode = opt.def; - } - -#ifdef CONFIG_PCI_MSI - kfree(opt.err); -#endif - } - /* Smart Power Down */ - { - static const struct e1000_option opt = { - .type = enable_option, - .name = "PHY Smart Power Down", - .err = "defaulting to Disabled", - .def = OPTION_DISABLED - }; - - if (num_SmartPowerDownEnable > bd) { - unsigned int spd = SmartPowerDownEnable[bd]; - e1000_validate_option(&spd, &opt, adapter); - if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && spd) - adapter->flags |= FLAG_SMART_POWER_DOWN; - } - } - /* CRC Stripping */ - { - static const struct e1000_option opt = { - .type = enable_option, - .name = "CRC Stripping", - .err = "defaulting to Enabled", - .def = OPTION_ENABLED - }; - - if (num_CrcStripping > bd) { - unsigned int crc_stripping = CrcStripping[bd]; - e1000_validate_option(&crc_stripping, &opt, adapter); - if (crc_stripping == OPTION_ENABLED) { - adapter->flags2 |= FLAG2_CRC_STRIPPING; - adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING; - } - } else { - adapter->flags2 |= FLAG2_CRC_STRIPPING; - adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING; - } - } - /* Kumeran Lock Loss Workaround */ - { - static const struct e1000_option opt = { - .type = enable_option, - .name = "Kumeran Lock Loss Workaround", - .err = "defaulting to Enabled", - .def = OPTION_ENABLED - }; - bool enabled = opt.def; - - if (num_KumeranLockLoss > bd) { - unsigned int kmrn_lock_loss = KumeranLockLoss[bd]; - e1000_validate_option(&kmrn_lock_loss, &opt, adapter); - enabled = kmrn_lock_loss; - } - - if (hw->mac.type == e1000_ich8lan) - e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, - enabled); - } - /* Write-protect NVM */ - { - static const struct e1000_option opt = { - .type = enable_option, - .name = "Write-protect NVM", - .err = "defaulting to Enabled", - .def = OPTION_ENABLED - }; - - if (adapter->flags & FLAG_IS_ICH) { - if (num_WriteProtectNVM > bd) { - unsigned int write_protect_nvm = - WriteProtectNVM[bd]; - e1000_validate_option(&write_protect_nvm, &opt, - adapter); - if (write_protect_nvm) - adapter->flags |= FLAG_READ_ONLY_NVM; - } else { - if (opt.def) - adapter->flags |= FLAG_READ_ONLY_NVM; - } - } - } -} diff --git a/addons/e1000e/src/3.10.108/phy.c b/addons/e1000e/src/3.10.108/phy.c deleted file mode 100644 index be4d7c1e..00000000 --- a/addons/e1000e/src/3.10.108/phy.c +++ /dev/null @@ -1,3243 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#include "e1000.h" - -static s32 e1000_wait_autoneg(struct e1000_hw *hw); -static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, - u16 *data, bool read, bool page_set); -static u32 e1000_get_phy_addr_for_hv_page(u32 page); -static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, - u16 *data, bool read); - -/* Cable length tables */ -static const u16 e1000_m88_cable_length_table[] = { - 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED -}; - -#define M88E1000_CABLE_LENGTH_TABLE_SIZE \ - ARRAY_SIZE(e1000_m88_cable_length_table) - -static const u16 e1000_igp_2_cable_length_table[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3, - 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 6, 10, 14, 18, 22, - 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 21, 26, 31, 35, 40, - 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 40, 45, 51, 56, 61, - 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82, - 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95, - 100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121, - 124 -}; - -#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ - ARRAY_SIZE(e1000_igp_2_cable_length_table) - -/** - * e1000e_check_reset_block_generic - Check if PHY reset is blocked - * @hw: pointer to the HW structure - * - * Read the PHY management control register and check whether a PHY reset - * is blocked. If a reset is not blocked return 0, otherwise - * return E1000_BLK_PHY_RESET (12). - **/ -s32 e1000e_check_reset_block_generic(struct e1000_hw *hw) -{ - u32 manc; - - manc = er32(MANC); - - return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? E1000_BLK_PHY_RESET : 0; -} - -/** - * e1000e_get_phy_id - Retrieve the PHY ID and revision - * @hw: pointer to the HW structure - * - * Reads the PHY registers and stores the PHY ID and possibly the PHY - * revision in the hardware structure. - **/ -s32 e1000e_get_phy_id(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = 0; - u16 phy_id; - u16 retry_count = 0; - - if (!phy->ops.read_reg) - return 0; - - while (retry_count < 2) { - ret_val = e1e_rphy(hw, MII_PHYSID1, &phy_id); - if (ret_val) - return ret_val; - - phy->id = (u32)(phy_id << 16); - usleep_range(20, 40); - ret_val = e1e_rphy(hw, MII_PHYSID2, &phy_id); - if (ret_val) - return ret_val; - - phy->id |= (u32)(phy_id & PHY_REVISION_MASK); - phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); - - if (phy->id != 0 && phy->id != PHY_REVISION_MASK) - return 0; - - retry_count++; - } - - return 0; -} - -/** - * e1000e_phy_reset_dsp - Reset PHY DSP - * @hw: pointer to the HW structure - * - * Reset the digital signal processor. - **/ -s32 e1000e_phy_reset_dsp(struct e1000_hw *hw) -{ - s32 ret_val; - - ret_val = e1e_wphy(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); - if (ret_val) - return ret_val; - - return e1e_wphy(hw, M88E1000_PHY_GEN_CONTROL, 0); -} - -/** - * e1000e_read_phy_reg_mdic - Read MDI control register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the MDI control register in the PHY at offset and stores the - * information read to data. - **/ -s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, mdic = 0; - - if (offset > MAX_PHY_REG_ADDRESS) { - e_dbg("PHY Address %d is out of range\n", offset); - return -E1000_ERR_PARAM; - } - - /* Set up Op-code, Phy Address, and register offset in the MDI - * Control register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - mdic = ((offset << E1000_MDIC_REG_SHIFT) | - (phy->addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_READ)); - - ew32(MDIC, mdic); - - /* Poll the ready bit to see if the MDI read completed - * Increasing the time out as testing showed failures with - * the lower time out - */ - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { - udelay(50); - mdic = er32(MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - e_dbg("MDI Read did not complete\n"); - return -E1000_ERR_PHY; - } - if (mdic & E1000_MDIC_ERROR) { - e_dbg("MDI Error\n"); - return -E1000_ERR_PHY; - } - if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) { - e_dbg("MDI Read offset error - requested %d, returned %d\n", - offset, - (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); - return -E1000_ERR_PHY; - } - *data = (u16)mdic; - - /* Allow some time after each MDIC transaction to avoid - * reading duplicate data in the next MDIC transaction. - */ - if (hw->mac.type == e1000_pch2lan) - udelay(100); - - return 0; -} - -/** - * e1000e_write_phy_reg_mdic - Write MDI control register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write to register at offset - * - * Writes data to MDI control register in the PHY at offset. - **/ -s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, mdic = 0; - - if (offset > MAX_PHY_REG_ADDRESS) { - e_dbg("PHY Address %d is out of range\n", offset); - return -E1000_ERR_PARAM; - } - - /* Set up Op-code, Phy Address, and register offset in the MDI - * Control register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - mdic = (((u32)data) | - (offset << E1000_MDIC_REG_SHIFT) | - (phy->addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_WRITE)); - - ew32(MDIC, mdic); - - /* Poll the ready bit to see if the MDI read completed - * Increasing the time out as testing showed failures with - * the lower time out - */ - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { - udelay(50); - mdic = er32(MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - e_dbg("MDI Write did not complete\n"); - return -E1000_ERR_PHY; - } - if (mdic & E1000_MDIC_ERROR) { - e_dbg("MDI Error\n"); - return -E1000_ERR_PHY; - } - if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) { - e_dbg("MDI Write offset error - requested %d, returned %d\n", - offset, - (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); - return -E1000_ERR_PHY; - } - - /* Allow some time after each MDIC transaction to avoid - * reading duplicate data in the next MDIC transaction. - */ - if (hw->mac.type == e1000_pch2lan) - udelay(100); - - return 0; -} - -/** - * e1000e_read_phy_reg_m88 - Read m88 PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000e_write_phy_reg_m88 - Write m88 PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_set_page_igp - Set page as on IGP-like PHY(s) - * @hw: pointer to the HW structure - * @page: page to set (shifted left when necessary) - * - * Sets PHY page required for PHY register access. Assumes semaphore is - * already acquired. Note, this function sets phy.addr to 1 so the caller - * must set it appropriately (if necessary) after this function returns. - **/ -s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page) -{ - e_dbg("Setting page 0x%x\n", page); - - hw->phy.addr = 1; - - return e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page); -} - -/** - * __e1000e_read_phy_reg_igp - Read igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and stores the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data, - bool locked) -{ - s32 ret_val = 0; - - if (!locked) { - if (!hw->phy.ops.acquire) - return 0; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - if (offset > MAX_PHY_MULTI_PAGE_REG) - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (u16)offset); - if (!ret_val) - ret_val = e1000e_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - if (!locked) - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000e_read_phy_reg_igp - Read igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore then reads the PHY register at offset and stores the - * retrieved information in data. - * Release the acquired semaphore before exiting. - **/ -s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000e_read_phy_reg_igp(hw, offset, data, false); -} - -/** - * e1000e_read_phy_reg_igp_locked - Read igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY register at offset and stores the retrieved information - * in data. Assumes semaphore already acquired. - **/ -s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000e_read_phy_reg_igp(hw, offset, data, true); -} - -/** - * e1000e_write_phy_reg_igp - Write igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data, - bool locked) -{ - s32 ret_val = 0; - - if (!locked) { - if (!hw->phy.ops.acquire) - return 0; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - if (offset > MAX_PHY_MULTI_PAGE_REG) - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (u16)offset); - if (!ret_val) - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & - offset, data); - if (!locked) - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000e_write_phy_reg_igp - Write igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000e_write_phy_reg_igp(hw, offset, data, false); -} - -/** - * e1000e_write_phy_reg_igp_locked - Write igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Writes the data to PHY register at the offset. - * Assumes semaphore already acquired. - **/ -s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000e_write_phy_reg_igp(hw, offset, data, true); -} - -/** - * __e1000_read_kmrn_reg - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary. Then reads the PHY register at offset - * using the kumeran interface. The information retrieved is stored in data. - * Release any acquired semaphores before exiting. - **/ -static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, - bool locked) -{ - u32 kmrnctrlsta; - - if (!locked) { - s32 ret_val = 0; - - if (!hw->phy.ops.acquire) - return 0; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; - ew32(KMRNCTRLSTA, kmrnctrlsta); - e1e_flush(); - - udelay(2); - - kmrnctrlsta = er32(KMRNCTRLSTA); - *data = (u16)kmrnctrlsta; - - if (!locked) - hw->phy.ops.release(hw); - - return 0; -} - -/** - * e1000e_read_kmrn_reg - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore then reads the PHY register at offset using the - * kumeran interface. The information retrieved is stored in data. - * Release the acquired semaphore before exiting. - **/ -s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000_read_kmrn_reg(hw, offset, data, false); -} - -/** - * e1000e_read_kmrn_reg_locked - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY register at offset using the kumeran interface. The - * information retrieved is stored in data. - * Assumes semaphore already acquired. - **/ -s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000_read_kmrn_reg(hw, offset, data, true); -} - -/** - * __e1000_write_kmrn_reg - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary. Then write the data to PHY register - * at the offset using the kumeran interface. Release any acquired semaphores - * before exiting. - **/ -static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, - bool locked) -{ - u32 kmrnctrlsta; - - if (!locked) { - s32 ret_val = 0; - - if (!hw->phy.ops.acquire) - return 0; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | data; - ew32(KMRNCTRLSTA, kmrnctrlsta); - e1e_flush(); - - udelay(2); - - if (!locked) - hw->phy.ops.release(hw); - - return 0; -} - -/** - * e1000e_write_kmrn_reg - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore then writes the data to the PHY register at the offset - * using the kumeran interface. Release the acquired semaphore before exiting. - **/ -s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000_write_kmrn_reg(hw, offset, data, false); -} - -/** - * e1000e_write_kmrn_reg_locked - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Write the data to PHY register at the offset using the kumeran interface. - * Assumes semaphore already acquired. - **/ -s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000_write_kmrn_reg(hw, offset, data, true); -} - -/** - * e1000_set_master_slave_mode - Setup PHY for Master/slave mode - * @hw: pointer to the HW structure - * - * Sets up Master/slave mode - **/ -static s32 e1000_set_master_slave_mode(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - - /* Resolve Master/Slave mode */ - ret_val = e1e_rphy(hw, MII_CTRL1000, &phy_data); - if (ret_val) - return ret_val; - - /* load defaults for future use */ - hw->phy.original_ms_type = (phy_data & CTL1000_ENABLE_MASTER) ? - ((phy_data & CTL1000_AS_MASTER) ? - e1000_ms_force_master : e1000_ms_force_slave) : e1000_ms_auto; - - switch (hw->phy.ms_type) { - case e1000_ms_force_master: - phy_data |= (CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER); - break; - case e1000_ms_force_slave: - phy_data |= CTL1000_ENABLE_MASTER; - phy_data &= ~(CTL1000_AS_MASTER); - break; - case e1000_ms_auto: - phy_data &= ~CTL1000_ENABLE_MASTER; - /* fall-through */ - default: - break; - } - - return e1e_wphy(hw, MII_CTRL1000, phy_data); -} - -/** - * e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link - * @hw: pointer to the HW structure - * - * Sets up Carrier-sense on Transmit and downshift values. - **/ -s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - - /* Enable CRS on Tx. This must be set for half-duplex operation. */ - ret_val = e1e_rphy(hw, I82577_CFG_REG, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= I82577_CFG_ASSERT_CRS_ON_TX; - - /* Enable downshift */ - phy_data |= I82577_CFG_ENABLE_DOWNSHIFT; - - ret_val = e1e_wphy(hw, I82577_CFG_REG, phy_data); - if (ret_val) - return ret_val; - - /* Set MDI/MDIX mode */ - ret_val = e1e_rphy(hw, I82577_PHY_CTRL_2, &phy_data); - if (ret_val) - return ret_val; - phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK; - /* Options: - * 0 - Auto (default) - * 1 - MDI mode - * 2 - MDI-X mode - */ - switch (hw->phy.mdix) { - case 1: - break; - case 2: - phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX; - break; - case 0: - default: - phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX; - break; - } - ret_val = e1e_wphy(hw, I82577_PHY_CTRL_2, phy_data); - if (ret_val) - return ret_val; - - return e1000_set_master_slave_mode(hw); -} - -/** - * e1000e_copper_link_setup_m88 - Setup m88 PHY's for copper link - * @hw: pointer to the HW structure - * - * Sets up MDI/MDI-X and polarity for m88 PHY's. If necessary, transmit clock - * and downshift values are set also. - **/ -s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - - /* Enable CRS on Tx. This must be set for half-duplex operation. */ - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - /* For BM PHY this bit is downshift enable */ - if (phy->type != e1000_phy_bm) - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - - /* Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - - switch (phy->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } - - /* Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if (phy->disable_polarity_correction) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - - /* Enable downshift on BM (disabled by default) */ - if (phy->type == e1000_phy_bm) { - /* For 82574/82583, first disable then enable downshift */ - if (phy->id == BME1000_E_PHY_ID_R2) { - phy_data &= ~BME1000_PSCR_ENABLE_DOWNSHIFT; - ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, - phy_data); - if (ret_val) - return ret_val; - /* Commit the changes. */ - ret_val = phy->ops.commit(hw); - if (ret_val) { - e_dbg("Error committing the PHY changes\n"); - return ret_val; - } - } - - phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT; - } - - ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - if ((phy->type == e1000_phy_m88) && - (phy->revision < E1000_REVISION_4) && - (phy->id != BME1000_E_PHY_ID_R2)) { - /* Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_EPSCR_TX_CLK_25; - - if ((phy->revision == 2) && (phy->id == M88E1111_I_PHY_ID)) { - /* 82573L PHY - set the downshift counter to 5x. */ - phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK; - phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; - } else { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - } - ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - } - - if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) { - /* Set PHY page 0, register 29 to 0x0003 */ - ret_val = e1e_wphy(hw, 29, 0x0003); - if (ret_val) - return ret_val; - - /* Set PHY page 0, register 30 to 0x0000 */ - ret_val = e1e_wphy(hw, 30, 0x0000); - if (ret_val) - return ret_val; - } - - /* Commit the changes. */ - if (phy->ops.commit) { - ret_val = phy->ops.commit(hw); - if (ret_val) { - e_dbg("Error committing the PHY changes\n"); - return ret_val; - } - } - - if (phy->type == e1000_phy_82578) { - ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - /* 82578 PHY - set the downshift count to 1x. */ - phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE; - phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK; - ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - } - - return 0; -} - -/** - * e1000e_copper_link_setup_igp - Setup igp PHY's for copper link - * @hw: pointer to the HW structure - * - * Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for - * igp PHY's. - **/ -s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - ret_val = e1000_phy_hw_reset(hw); - if (ret_val) { - e_dbg("Error resetting the PHY.\n"); - return ret_val; - } - - /* Wait 100ms for MAC to configure PHY from NVM settings, to avoid - * timeout issues when LFS is enabled. - */ - msleep(100); - - /* disable lplu d0 during driver init */ - if (hw->phy.ops.set_d0_lplu_state) { - ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); - if (ret_val) { - e_dbg("Error Disabling LPLU D0\n"); - return ret_val; - } - } - /* Configure mdi-mdix settings */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCR_AUTO_MDIX; - - switch (phy->mdix) { - case 1: - data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 2: - data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 0: - default: - data |= IGP01E1000_PSCR_AUTO_MDIX; - break; - } - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CTRL, data); - if (ret_val) - return ret_val; - - /* set auto-master slave resolution settings */ - if (hw->mac.autoneg) { - /* when autonegotiation advertisement is only 1000Mbps then we - * should disable SmartSpeed and enable Auto MasterSlave - * resolution as hardware default. - */ - if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - - /* Set auto Master/Slave resolution process */ - ret_val = e1e_rphy(hw, MII_CTRL1000, &data); - if (ret_val) - return ret_val; - - data &= ~CTL1000_ENABLE_MASTER; - ret_val = e1e_wphy(hw, MII_CTRL1000, data); - if (ret_val) - return ret_val; - } - - ret_val = e1000_set_master_slave_mode(hw); - } - - return ret_val; -} - -/** - * e1000_phy_setup_autoneg - Configure PHY for auto-negotiation - * @hw: pointer to the HW structure - * - * Reads the MII auto-neg advertisement register and/or the 1000T control - * register and if the PHY is already setup for auto-negotiation, then - * return successful. Otherwise, setup advertisement and flow control to - * the appropriate values for the wanted auto-negotiation. - **/ -static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 mii_autoneg_adv_reg; - u16 mii_1000t_ctrl_reg = 0; - - phy->autoneg_advertised &= phy->autoneg_mask; - - /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - ret_val = e1e_rphy(hw, MII_ADVERTISE, &mii_autoneg_adv_reg); - if (ret_val) - return ret_val; - - if (phy->autoneg_mask & ADVERTISE_1000_FULL) { - /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = e1e_rphy(hw, MII_CTRL1000, &mii_1000t_ctrl_reg); - if (ret_val) - return ret_val; - } - - /* Need to parse both autoneg_advertised and fc and set up - * the appropriate PHY registers. First we will parse for - * autoneg_advertised software override. Since we can advertise - * a plethora of combinations, we need to check each bit - * individually. - */ - - /* First we clear all the 10/100 mb speed bits in the Auto-Neg - * Advertisement Register (Address 4) and the 1000 mb speed bits in - * the 1000Base-T Control Register (Address 9). - */ - mii_autoneg_adv_reg &= ~(ADVERTISE_100FULL | - ADVERTISE_100HALF | - ADVERTISE_10FULL | ADVERTISE_10HALF); - mii_1000t_ctrl_reg &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - - e_dbg("autoneg_advertised %x\n", phy->autoneg_advertised); - - /* Do we want to advertise 10 Mb Half Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_10_HALF) { - e_dbg("Advertise 10mb Half duplex\n"); - mii_autoneg_adv_reg |= ADVERTISE_10HALF; - } - - /* Do we want to advertise 10 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_10_FULL) { - e_dbg("Advertise 10mb Full duplex\n"); - mii_autoneg_adv_reg |= ADVERTISE_10FULL; - } - - /* Do we want to advertise 100 Mb Half Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_100_HALF) { - e_dbg("Advertise 100mb Half duplex\n"); - mii_autoneg_adv_reg |= ADVERTISE_100HALF; - } - - /* Do we want to advertise 100 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_100_FULL) { - e_dbg("Advertise 100mb Full duplex\n"); - mii_autoneg_adv_reg |= ADVERTISE_100FULL; - } - - /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ - if (phy->autoneg_advertised & ADVERTISE_1000_HALF) - e_dbg("Advertise 1000mb Half duplex request denied!\n"); - - /* Do we want to advertise 1000 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { - e_dbg("Advertise 1000mb Full duplex\n"); - mii_1000t_ctrl_reg |= ADVERTISE_1000FULL; - } - - /* Check for a software override of the flow control settings, and - * setup the PHY advertisement registers accordingly. If - * auto-negotiation is enabled, then software will have to set the - * "PAUSE" bits to the correct value in the Auto-Negotiation - * Advertisement Register (MII_ADVERTISE) and re-start auto- - * negotiation. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * but we do not support receiving pause frames). - * 3: Both Rx and Tx flow control (symmetric) are enabled. - * other: No software override. The flow control configuration - * in the EEPROM is used. - */ - switch (hw->fc.current_mode) { - case e1000_fc_none: - /* Flow control (Rx & Tx) is completely disabled by a - * software over-ride. - */ - mii_autoneg_adv_reg &= - ~(ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP); - break; - case e1000_fc_rx_pause: - /* Rx Flow control is enabled, and Tx Flow control is - * disabled, by a software over-ride. - * - * Since there really isn't a way to advertise that we are - * capable of Rx Pause ONLY, we will advertise that we - * support both symmetric and asymmetric Rx PAUSE. Later - * (in e1000e_config_fc_after_link_up) we will disable the - * hw's ability to send PAUSE frames. - */ - mii_autoneg_adv_reg |= - (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP); - break; - case e1000_fc_tx_pause: - /* Tx Flow control is enabled, and Rx Flow control is - * disabled, by a software over-ride. - */ - mii_autoneg_adv_reg |= ADVERTISE_PAUSE_ASYM; - mii_autoneg_adv_reg &= ~ADVERTISE_PAUSE_CAP; - break; - case e1000_fc_full: - /* Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - mii_autoneg_adv_reg |= - (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - } - - ret_val = e1e_wphy(hw, MII_ADVERTISE, mii_autoneg_adv_reg); - if (ret_val) - return ret_val; - - e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - - if (phy->autoneg_mask & ADVERTISE_1000_FULL) - ret_val = e1e_wphy(hw, MII_CTRL1000, mii_1000t_ctrl_reg); - - return ret_val; -} - -/** - * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link - * @hw: pointer to the HW structure - * - * Performs initial bounds checking on autoneg advertisement parameter, then - * configure to advertise the full capability. Setup the PHY to autoneg - * and restart the negotiation process between the link partner. If - * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. - **/ -static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_ctrl; - - /* Perform some bounds checking on the autoneg advertisement - * parameter. - */ - phy->autoneg_advertised &= phy->autoneg_mask; - - /* If autoneg_advertised is zero, we assume it was not defaulted - * by the calling code so we set to advertise full capability. - */ - if (!phy->autoneg_advertised) - phy->autoneg_advertised = phy->autoneg_mask; - - e_dbg("Reconfiguring auto-neg advertisement params\n"); - ret_val = e1000_phy_setup_autoneg(hw); - if (ret_val) { - e_dbg("Error Setting up Auto-Negotiation\n"); - return ret_val; - } - e_dbg("Restarting Auto-Neg\n"); - - /* Restart auto-negotiation by setting the Auto Neg Enable bit and - * the Auto Neg Restart bit in the PHY control register. - */ - ret_val = e1e_rphy(hw, MII_BMCR, &phy_ctrl); - if (ret_val) - return ret_val; - - phy_ctrl |= (BMCR_ANENABLE | BMCR_ANRESTART); - ret_val = e1e_wphy(hw, MII_BMCR, phy_ctrl); - if (ret_val) - return ret_val; - - /* Does the user want to wait for Auto-Neg to complete here, or - * check at a later time (for example, callback routine). - */ - if (phy->autoneg_wait_to_complete) { - ret_val = e1000_wait_autoneg(hw); - if (ret_val) { - e_dbg("Error while waiting for autoneg to complete\n"); - return ret_val; - } - } - - hw->mac.get_link_status = true; - - return ret_val; -} - -/** - * e1000e_setup_copper_link - Configure copper link settings - * @hw: pointer to the HW structure - * - * Calls the appropriate function to configure the link for auto-neg or forced - * speed and duplex. Then we check for link, once link is established calls - * to configure collision distance and flow control are called. If link is - * not established, we return -E1000_ERR_PHY (-2). - **/ -s32 e1000e_setup_copper_link(struct e1000_hw *hw) -{ - s32 ret_val; - bool link; - - if (hw->mac.autoneg) { - /* Setup autoneg and flow control advertisement and perform - * autonegotiation. - */ - ret_val = e1000_copper_link_autoneg(hw); - if (ret_val) - return ret_val; - } else { - /* PHY will be set to 10H, 10F, 100H or 100F - * depending on user settings. - */ - e_dbg("Forcing Speed and Duplex\n"); - ret_val = hw->phy.ops.force_speed_duplex(hw); - if (ret_val) { - e_dbg("Error Forcing Speed and Duplex\n"); - return ret_val; - } - } - - /* Check link status. Wait up to 100 microseconds for link to become - * valid. - */ - ret_val = e1000e_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10, - &link); - if (ret_val) - return ret_val; - - if (link) { - e_dbg("Valid link established!!!\n"); - hw->mac.ops.config_collision_dist(hw); - ret_val = e1000e_config_fc_after_link_up(hw); - } else { - e_dbg("Unable to establish link!!!\n"); - } - - return ret_val; -} - -/** - * e1000e_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY - * @hw: pointer to the HW structure - * - * Calls the PHY setup function to force speed and duplex. Clears the - * auto-crossover to force MDI manually. Waits for link and returns - * successful if link up is successful, else -E1000_ERR_PHY (-2). - **/ -s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - ret_val = e1e_rphy(hw, MII_BMCR, &phy_data); - if (ret_val) - return ret_val; - - e1000e_phy_force_speed_duplex_setup(hw, &phy_data); - - ret_val = e1e_wphy(hw, MII_BMCR, phy_data); - if (ret_val) - return ret_val; - - /* Clear Auto-Crossover to force MDI manually. IGP requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); - if (ret_val) - return ret_val; - - e_dbg("IGP PSCR: %X\n", phy_data); - - udelay(1); - - if (phy->autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on IGP phy.\n"); - - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - - if (!link) - e_dbg("Link taking longer than expected.\n"); - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - } - - return ret_val; -} - -/** - * e1000e_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY - * @hw: pointer to the HW structure - * - * Calls the PHY setup function to force speed and duplex. Clears the - * auto-crossover to force MDI manually. Resets the PHY to commit the - * changes. If time expires while waiting for link up, we reset the DSP. - * After reset, TX_CLK and CRS on Tx must be set. Return successful upon - * successful completion, else return corresponding error code. - **/ -s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - e_dbg("M88E1000 PSCR: %X\n", phy_data); - - ret_val = e1e_rphy(hw, MII_BMCR, &phy_data); - if (ret_val) - return ret_val; - - e1000e_phy_force_speed_duplex_setup(hw, &phy_data); - - ret_val = e1e_wphy(hw, MII_BMCR, phy_data); - if (ret_val) - return ret_val; - - /* Reset the phy to commit changes. */ - if (hw->phy.ops.commit) { - ret_val = hw->phy.ops.commit(hw); - if (ret_val) - return ret_val; - } - - if (phy->autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on M88 phy.\n"); - - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - - if (!link) { - if (hw->phy.type != e1000_phy_m88) { - e_dbg("Link taking longer than expected.\n"); - } else { - /* We didn't get link. - * Reset the DSP and cross our fingers. - */ - ret_val = e1e_wphy(hw, M88E1000_PHY_PAGE_SELECT, - 0x001d); - if (ret_val) - return ret_val; - ret_val = e1000e_phy_reset_dsp(hw); - if (ret_val) - return ret_val; - } - } - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - } - - if (hw->phy.type != e1000_phy_m88) - return 0; - - ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - /* Resetting the phy means we need to re-force TX_CLK in the - * Extended PHY Specific Control Register to 25MHz clock from - * the reset value of 2.5MHz. - */ - phy_data |= M88E1000_EPSCR_TX_CLK_25; - ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - /* In addition, we must re-enable CRS on Tx for both half and full - * duplex. - */ - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - - return ret_val; -} - -/** - * e1000_phy_force_speed_duplex_ife - Force PHY speed & duplex - * @hw: pointer to the HW structure - * - * Forces the speed and duplex settings of the PHY. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - ret_val = e1e_rphy(hw, MII_BMCR, &data); - if (ret_val) - return ret_val; - - e1000e_phy_force_speed_duplex_setup(hw, &data); - - ret_val = e1e_wphy(hw, MII_BMCR, data); - if (ret_val) - return ret_val; - - /* Disable MDI-X support for 10/100 */ - ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data); - if (ret_val) - return ret_val; - - data &= ~IFE_PMC_AUTO_MDIX; - data &= ~IFE_PMC_FORCE_MDIX; - - ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, data); - if (ret_val) - return ret_val; - - e_dbg("IFE PMC: %X\n", data); - - udelay(1); - - if (phy->autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on IFE phy.\n"); - - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - - if (!link) - e_dbg("Link taking longer than expected.\n"); - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - } - - return 0; -} - -/** - * e1000e_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex - * @hw: pointer to the HW structure - * @phy_ctrl: pointer to current value of MII_BMCR - * - * Forces speed and duplex on the PHY by doing the following: disable flow - * control, force speed/duplex on the MAC, disable auto speed detection, - * disable auto-negotiation, configure duplex, configure speed, configure - * the collision distance, write configuration to CTRL register. The - * caller must write to the MII_BMCR register for these settings to - * take affect. - **/ -void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 ctrl; - - /* Turn off flow control when forcing speed/duplex */ - hw->fc.current_mode = e1000_fc_none; - - /* Force speed/duplex on the mac */ - ctrl = er32(CTRL); - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ctrl &= ~E1000_CTRL_SPD_SEL; - - /* Disable Auto Speed Detection */ - ctrl &= ~E1000_CTRL_ASDE; - - /* Disable autoneg on the phy */ - *phy_ctrl &= ~BMCR_ANENABLE; - - /* Forcing Full or Half Duplex? */ - if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) { - ctrl &= ~E1000_CTRL_FD; - *phy_ctrl &= ~BMCR_FULLDPLX; - e_dbg("Half Duplex\n"); - } else { - ctrl |= E1000_CTRL_FD; - *phy_ctrl |= BMCR_FULLDPLX; - e_dbg("Full Duplex\n"); - } - - /* Forcing 10mb or 100mb? */ - if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) { - ctrl |= E1000_CTRL_SPD_100; - *phy_ctrl |= BMCR_SPEED100; - *phy_ctrl &= ~BMCR_SPEED1000; - e_dbg("Forcing 100mb\n"); - } else { - ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - *phy_ctrl &= ~(BMCR_SPEED1000 | BMCR_SPEED100); - e_dbg("Forcing 10mb\n"); - } - - hw->mac.ops.config_collision_dist(hw); - - ew32(CTRL, ctrl); -} - -/** - * e1000e_set_d3_lplu_state - Sets low power link up state for D3 - * @hw: pointer to the HW structure - * @active: boolean used to enable/disable lplu - * - * Success returns 0, Failure returns 1 - * - * The low power link up (lplu) state is set to the power management level D3 - * and SmartSpeed is disabled when active is true, else clear lplu for D3 - * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU - * is used during Dx states where the power conservation is most important. - * During driver activity, SmartSpeed should be enabled so performance is - * maintained. - **/ -s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - ret_val = e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &data); - if (ret_val) - return ret_val; - - if (!active) { - data &= ~IGP02E1000_PM_D3_LPLU; - ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); - if (ret_val) - return ret_val; - /* LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } - } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || - (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || - (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { - data |= IGP02E1000_PM_D3_LPLU; - ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); - if (ret_val) - return ret_val; - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data); - } - - return ret_val; -} - -/** - * e1000e_check_downshift - Checks whether a downshift in speed occurred - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns 1 - * - * A downshift is detected by querying the PHY link health. - **/ -s32 e1000e_check_downshift(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, offset, mask; - - switch (phy->type) { - case e1000_phy_m88: - case e1000_phy_gg82563: - case e1000_phy_bm: - case e1000_phy_82578: - offset = M88E1000_PHY_SPEC_STATUS; - mask = M88E1000_PSSR_DOWNSHIFT; - break; - case e1000_phy_igp_2: - case e1000_phy_igp_3: - offset = IGP01E1000_PHY_LINK_HEALTH; - mask = IGP01E1000_PLHR_SS_DOWNGRADE; - break; - default: - /* speed downshift not supported */ - phy->speed_downgraded = false; - return 0; - } - - ret_val = e1e_rphy(hw, offset, &phy_data); - - if (!ret_val) - phy->speed_downgraded = !!(phy_data & mask); - - return ret_val; -} - -/** - * e1000_check_polarity_m88 - Checks the polarity. - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - * - * Polarity is determined based on the PHY specific status register. - **/ -s32 e1000_check_polarity_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &data); - - if (!ret_val) - phy->cable_polarity = ((data & M88E1000_PSSR_REV_POLARITY) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal); - - return ret_val; -} - -/** - * e1000_check_polarity_igp - Checks the polarity. - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - * - * Polarity is determined based on the PHY port status register, and the - * current speed (since there is no polarity at 100Mbps). - **/ -s32 e1000_check_polarity_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data, offset, mask; - - /* Polarity is determined based on the speed of - * our connection. - */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data); - if (ret_val) - return ret_val; - - if ((data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - offset = IGP01E1000_PHY_PCS_INIT_REG; - mask = IGP01E1000_PHY_POLARITY_MASK; - } else { - /* This really only applies to 10Mbps since - * there is no polarity for 100Mbps (always 0). - */ - offset = IGP01E1000_PHY_PORT_STATUS; - mask = IGP01E1000_PSSR_POLARITY_REVERSED; - } - - ret_val = e1e_rphy(hw, offset, &data); - - if (!ret_val) - phy->cable_polarity = ((data & mask) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal); - - return ret_val; -} - -/** - * e1000_check_polarity_ife - Check cable polarity for IFE PHY - * @hw: pointer to the HW structure - * - * Polarity is determined on the polarity reversal feature being enabled. - **/ -s32 e1000_check_polarity_ife(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, offset, mask; - - /* Polarity is determined based on the reversal feature being enabled. - */ - if (phy->polarity_correction) { - offset = IFE_PHY_EXTENDED_STATUS_CONTROL; - mask = IFE_PESC_POLARITY_REVERSED; - } else { - offset = IFE_PHY_SPECIAL_CONTROL; - mask = IFE_PSC_FORCE_POLARITY; - } - - ret_val = e1e_rphy(hw, offset, &phy_data); - - if (!ret_val) - phy->cable_polarity = ((phy_data & mask) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal); - - return ret_val; -} - -/** - * e1000_wait_autoneg - Wait for auto-neg completion - * @hw: pointer to the HW structure - * - * Waits for auto-negotiation to complete or for the auto-negotiation time - * limit to expire, which ever happens first. - **/ -static s32 e1000_wait_autoneg(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u16 i, phy_status; - - /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ - for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { - ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); - if (ret_val) - break; - ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); - if (ret_val) - break; - if (phy_status & BMSR_ANEGCOMPLETE) - break; - msleep(100); - } - - /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation - * has completed. - */ - return ret_val; -} - -/** - * e1000e_phy_has_link_generic - Polls PHY for link - * @hw: pointer to the HW structure - * @iterations: number of times to poll for link - * @usec_interval: delay between polling attempts - * @success: pointer to whether polling was successful or not - * - * Polls the PHY status register for link, 'iterations' number of times. - **/ -s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, - u32 usec_interval, bool *success) -{ - s32 ret_val = 0; - u16 i, phy_status; - - for (i = 0; i < iterations; i++) { - /* Some PHYs require the MII_BMSR register to be read - * twice due to the link bit being sticky. No harm doing - * it across the board. - */ - ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); - if (ret_val) { - /* If the first read fails, another entity may have - * ownership of the resources, wait and try again to - * see if they have relinquished the resources yet. - */ - if (usec_interval >= 1000) - msleep(usec_interval / 1000); - else - udelay(usec_interval); - } - ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); - if (ret_val) - break; - if (phy_status & BMSR_LSTATUS) - break; - if (usec_interval >= 1000) - msleep(usec_interval / 1000); - else - udelay(usec_interval); - } - - *success = (i < iterations); - - return ret_val; -} - -/** - * e1000e_get_cable_length_m88 - Determine cable length for m88 PHY - * @hw: pointer to the HW structure - * - * Reads the PHY specific status register to retrieve the cable length - * information. The cable length is determined by averaging the minimum and - * maximum values to get the "average" cable length. The m88 PHY has four - * possible cable length values, which are: - * Register Value Cable Length - * 0 < 50 meters - * 1 50 - 80 meters - * 2 80 - 110 meters - * 3 110 - 140 meters - * 4 > 140 meters - **/ -s32 e1000e_get_cable_length_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, index; - - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if (ret_val) - return ret_val; - - index = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT); - - if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) - return -E1000_ERR_PHY; - - phy->min_cable_length = e1000_m88_cable_length_table[index]; - phy->max_cable_length = e1000_m88_cable_length_table[index + 1]; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - - return 0; -} - -/** - * e1000e_get_cable_length_igp_2 - Determine cable length for igp2 PHY - * @hw: pointer to the HW structure - * - * The automatic gain control (agc) normalizes the amplitude of the - * received signal, adjusting for the attenuation produced by the - * cable. By reading the AGC registers, which represent the - * combination of coarse and fine gain value, the value can be put - * into a lookup table to obtain the approximate cable length - * for each channel. - **/ -s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, i, agc_value = 0; - u16 cur_agc_index, max_agc_index = 0; - u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; - static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = { - IGP02E1000_PHY_AGC_A, - IGP02E1000_PHY_AGC_B, - IGP02E1000_PHY_AGC_C, - IGP02E1000_PHY_AGC_D - }; - - /* Read the AGC registers for all channels */ - for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { - ret_val = e1e_rphy(hw, agc_reg_array[i], &phy_data); - if (ret_val) - return ret_val; - - /* Getting bits 15:9, which represent the combination of - * coarse and fine gain values. The result is a number - * that can be put into the lookup table to obtain the - * approximate cable length. - */ - cur_agc_index = ((phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & - IGP02E1000_AGC_LENGTH_MASK); - - /* Array index bound check. */ - if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) || - (cur_agc_index == 0)) - return -E1000_ERR_PHY; - - /* Remove min & max AGC values from calculation. */ - if (e1000_igp_2_cable_length_table[min_agc_index] > - e1000_igp_2_cable_length_table[cur_agc_index]) - min_agc_index = cur_agc_index; - if (e1000_igp_2_cable_length_table[max_agc_index] < - e1000_igp_2_cable_length_table[cur_agc_index]) - max_agc_index = cur_agc_index; - - agc_value += e1000_igp_2_cable_length_table[cur_agc_index]; - } - - agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] + - e1000_igp_2_cable_length_table[max_agc_index]); - agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); - - /* Calculate cable length with the error range of +/- 10 meters. */ - phy->min_cable_length = (((agc_value - IGP02E1000_AGC_RANGE) > 0) ? - (agc_value - IGP02E1000_AGC_RANGE) : 0); - phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - - return 0; -} - -/** - * e1000e_get_phy_info_m88 - Retrieve PHY information - * @hw: pointer to the HW structure - * - * Valid for only copper links. Read the PHY status register (sticky read) - * to verify that link is up. Read the PHY special control register to - * determine the polarity and 10base-T extended distance. Read the PHY - * special status register to determine MDI/MDIx and current speed. If - * speed is 1000, then determine cable length, local and remote receiver. - **/ -s32 e1000e_get_phy_info_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - if (phy->media_type != e1000_media_type_copper) { - e_dbg("Phy info is only valid for copper media\n"); - return -E1000_ERR_CONFIG; - } - - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (!link) { - e_dbg("Phy info is only valid if link is up\n"); - return -E1000_ERR_CONFIG; - } - - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy->polarity_correction = !!(phy_data & - M88E1000_PSCR_POLARITY_REVERSAL); - - ret_val = e1000_check_polarity_m88(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if (ret_val) - return ret_val; - - phy->is_mdix = !!(phy_data & M88E1000_PSSR_MDIX); - - if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { - ret_val = hw->phy.ops.get_cable_length(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, MII_STAT1000, &phy_data); - if (ret_val) - return ret_val; - - phy->local_rx = (phy_data & LPA_1000LOCALRXOK) - ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - - phy->remote_rx = (phy_data & LPA_1000REMRXOK) - ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - } else { - /* Set values to "undefined" */ - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - } - - return ret_val; -} - -/** - * e1000e_get_phy_info_igp - Retrieve igp PHY information - * @hw: pointer to the HW structure - * - * Read PHY status to determine if link is up. If link is up, then - * set/determine 10base-T extended distance and polarity correction. Read - * PHY port status to determine MDI/MDIx and speed. Based on the speed, - * determine on the cable length, local and remote receiver. - **/ -s32 e1000e_get_phy_info_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (!link) { - e_dbg("Phy info is only valid if link is up\n"); - return -E1000_ERR_CONFIG; - } - - phy->polarity_correction = true; - - ret_val = e1000_check_polarity_igp(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data); - if (ret_val) - return ret_val; - - phy->is_mdix = !!(data & IGP01E1000_PSSR_MDIX); - - if ((data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - ret_val = phy->ops.get_cable_length(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, MII_STAT1000, &data); - if (ret_val) - return ret_val; - - phy->local_rx = (data & LPA_1000LOCALRXOK) - ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - - phy->remote_rx = (data & LPA_1000REMRXOK) - ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - } else { - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - } - - return ret_val; -} - -/** - * e1000_get_phy_info_ife - Retrieves various IFE PHY states - * @hw: pointer to the HW structure - * - * Populates "phy" structure with various feature states. - **/ -s32 e1000_get_phy_info_ife(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (!link) { - e_dbg("Phy info is only valid if link is up\n"); - return -E1000_ERR_CONFIG; - } - - ret_val = e1e_rphy(hw, IFE_PHY_SPECIAL_CONTROL, &data); - if (ret_val) - return ret_val; - phy->polarity_correction = !(data & IFE_PSC_AUTO_POLARITY_DISABLE); - - if (phy->polarity_correction) { - ret_val = e1000_check_polarity_ife(hw); - if (ret_val) - return ret_val; - } else { - /* Polarity is forced */ - phy->cable_polarity = ((data & IFE_PSC_FORCE_POLARITY) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal); - } - - ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data); - if (ret_val) - return ret_val; - - phy->is_mdix = !!(data & IFE_PMC_MDIX_STATUS); - - /* The following parameters are undefined for 10/100 operation. */ - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - - return 0; -} - -/** - * e1000e_phy_sw_reset - PHY software reset - * @hw: pointer to the HW structure - * - * Does a software reset of the PHY by reading the PHY control register and - * setting/write the control register reset bit to the PHY. - **/ -s32 e1000e_phy_sw_reset(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_ctrl; - - ret_val = e1e_rphy(hw, MII_BMCR, &phy_ctrl); - if (ret_val) - return ret_val; - - phy_ctrl |= BMCR_RESET; - ret_val = e1e_wphy(hw, MII_BMCR, phy_ctrl); - if (ret_val) - return ret_val; - - udelay(1); - - return ret_val; -} - -/** - * e1000e_phy_hw_reset_generic - PHY hardware reset - * @hw: pointer to the HW structure - * - * Verify the reset block is not blocking us from resetting. Acquire - * semaphore (if necessary) and read/set/write the device control reset - * bit in the PHY. Wait the appropriate delay time for the device to - * reset and release the semaphore (if necessary). - **/ -s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u32 ctrl; - - if (phy->ops.check_reset_block) { - ret_val = phy->ops.check_reset_block(hw); - if (ret_val) - return 0; - } - - ret_val = phy->ops.acquire(hw); - if (ret_val) - return ret_val; - - ctrl = er32(CTRL); - ew32(CTRL, ctrl | E1000_CTRL_PHY_RST); - e1e_flush(); - - udelay(phy->reset_delay_us); - - ew32(CTRL, ctrl); - e1e_flush(); - - usleep_range(150, 300); - - phy->ops.release(hw); - - return phy->ops.get_cfg_done(hw); -} - -/** - * e1000e_get_cfg_done_generic - Generic configuration done - * @hw: pointer to the HW structure - * - * Generic function to wait 10 milli-seconds for configuration to complete - * and return success. - **/ -s32 e1000e_get_cfg_done_generic(struct e1000_hw __always_unused *hw) -{ - mdelay(10); - - return 0; -} - -/** - * e1000e_phy_init_script_igp3 - Inits the IGP3 PHY - * @hw: pointer to the HW structure - * - * Initializes a Intel Gigabit PHY3 when an EEPROM is not present. - **/ -s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw) -{ - e_dbg("Running IGP 3 PHY init script\n"); - - /* PHY init IGP 3 */ - /* Enable rise/fall, 10-mode work in class-A */ - e1e_wphy(hw, 0x2F5B, 0x9018); - /* Remove all caps from Replica path filter */ - e1e_wphy(hw, 0x2F52, 0x0000); - /* Bias trimming for ADC, AFE and Driver (Default) */ - e1e_wphy(hw, 0x2FB1, 0x8B24); - /* Increase Hybrid poly bias */ - e1e_wphy(hw, 0x2FB2, 0xF8F0); - /* Add 4% to Tx amplitude in Gig mode */ - e1e_wphy(hw, 0x2010, 0x10B0); - /* Disable trimming (TTT) */ - e1e_wphy(hw, 0x2011, 0x0000); - /* Poly DC correction to 94.6% + 2% for all channels */ - e1e_wphy(hw, 0x20DD, 0x249A); - /* ABS DC correction to 95.9% */ - e1e_wphy(hw, 0x20DE, 0x00D3); - /* BG temp curve trim */ - e1e_wphy(hw, 0x28B4, 0x04CE); - /* Increasing ADC OPAMP stage 1 currents to max */ - e1e_wphy(hw, 0x2F70, 0x29E4); - /* Force 1000 ( required for enabling PHY regs configuration) */ - e1e_wphy(hw, 0x0000, 0x0140); - /* Set upd_freq to 6 */ - e1e_wphy(hw, 0x1F30, 0x1606); - /* Disable NPDFE */ - e1e_wphy(hw, 0x1F31, 0xB814); - /* Disable adaptive fixed FFE (Default) */ - e1e_wphy(hw, 0x1F35, 0x002A); - /* Enable FFE hysteresis */ - e1e_wphy(hw, 0x1F3E, 0x0067); - /* Fixed FFE for short cable lengths */ - e1e_wphy(hw, 0x1F54, 0x0065); - /* Fixed FFE for medium cable lengths */ - e1e_wphy(hw, 0x1F55, 0x002A); - /* Fixed FFE for long cable lengths */ - e1e_wphy(hw, 0x1F56, 0x002A); - /* Enable Adaptive Clip Threshold */ - e1e_wphy(hw, 0x1F72, 0x3FB0); - /* AHT reset limit to 1 */ - e1e_wphy(hw, 0x1F76, 0xC0FF); - /* Set AHT master delay to 127 msec */ - e1e_wphy(hw, 0x1F77, 0x1DEC); - /* Set scan bits for AHT */ - e1e_wphy(hw, 0x1F78, 0xF9EF); - /* Set AHT Preset bits */ - e1e_wphy(hw, 0x1F79, 0x0210); - /* Change integ_factor of channel A to 3 */ - e1e_wphy(hw, 0x1895, 0x0003); - /* Change prop_factor of channels BCD to 8 */ - e1e_wphy(hw, 0x1796, 0x0008); - /* Change cg_icount + enable integbp for channels BCD */ - e1e_wphy(hw, 0x1798, 0xD008); - /* Change cg_icount + enable integbp + change prop_factor_master - * to 8 for channel A - */ - e1e_wphy(hw, 0x1898, 0xD918); - /* Disable AHT in Slave mode on channel A */ - e1e_wphy(hw, 0x187A, 0x0800); - /* Enable LPLU and disable AN to 1000 in non-D0a states, - * Enable SPD+B2B - */ - e1e_wphy(hw, 0x0019, 0x008D); - /* Enable restart AN on an1000_dis change */ - e1e_wphy(hw, 0x001B, 0x2080); - /* Enable wh_fifo read clock in 10/100 modes */ - e1e_wphy(hw, 0x0014, 0x0045); - /* Restart AN, Speed selection is 1000 */ - e1e_wphy(hw, 0x0000, 0x1340); - - return 0; -} - -/** - * e1000e_get_phy_type_from_id - Get PHY type from id - * @phy_id: phy_id read from the phy - * - * Returns the phy type from the id. - **/ -enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id) -{ - enum e1000_phy_type phy_type = e1000_phy_unknown; - - switch (phy_id) { - case M88E1000_I_PHY_ID: - case M88E1000_E_PHY_ID: - case M88E1111_I_PHY_ID: - case M88E1011_I_PHY_ID: - phy_type = e1000_phy_m88; - break; - case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ - phy_type = e1000_phy_igp_2; - break; - case GG82563_E_PHY_ID: - phy_type = e1000_phy_gg82563; - break; - case IGP03E1000_E_PHY_ID: - phy_type = e1000_phy_igp_3; - break; - case IFE_E_PHY_ID: - case IFE_PLUS_E_PHY_ID: - case IFE_C_E_PHY_ID: - phy_type = e1000_phy_ife; - break; - case BME1000_E_PHY_ID: - case BME1000_E_PHY_ID_R2: - phy_type = e1000_phy_bm; - break; - case I82578_E_PHY_ID: - phy_type = e1000_phy_82578; - break; - case I82577_E_PHY_ID: - phy_type = e1000_phy_82577; - break; - case I82579_E_PHY_ID: - phy_type = e1000_phy_82579; - break; - case I217_E_PHY_ID: - phy_type = e1000_phy_i217; - break; - default: - phy_type = e1000_phy_unknown; - break; - } - return phy_type; -} - -/** - * e1000e_determine_phy_address - Determines PHY address. - * @hw: pointer to the HW structure - * - * This uses a trial and error method to loop through possible PHY - * addresses. It tests each by reading the PHY ID registers and - * checking for a match. - **/ -s32 e1000e_determine_phy_address(struct e1000_hw *hw) -{ - u32 phy_addr = 0; - u32 i; - enum e1000_phy_type phy_type = e1000_phy_unknown; - - hw->phy.id = phy_type; - - for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) { - hw->phy.addr = phy_addr; - i = 0; - - do { - e1000e_get_phy_id(hw); - phy_type = e1000e_get_phy_type_from_id(hw->phy.id); - - /* If phy_type is valid, break - we found our - * PHY address - */ - if (phy_type != e1000_phy_unknown) - return 0; - - usleep_range(1000, 2000); - i++; - } while (i < 10); - } - - return -E1000_ERR_PHY_TYPE; -} - -/** - * e1000_get_phy_addr_for_bm_page - Retrieve PHY page address - * @page: page to access - * - * Returns the phy address for the page requested. - **/ -static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg) -{ - u32 phy_addr = 2; - - if ((page >= 768) || (page == 0 && reg == 25) || (reg == 31)) - phy_addr = 1; - - return phy_addr; -} - -/** - * e1000e_write_phy_reg_bm - Write BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val; - u32 page = offset >> IGP_PAGE_SHIFT; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, - false, false); - goto release; - } - - hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - u32 page_shift, page_select; - - /* Page select is register 31 for phy address 1 and 22 for - * phy address 2 and 3. Page select is shifted only for - * phy address 1. - */ - if (hw->phy.addr == 1) { - page_shift = IGP_PAGE_SHIFT; - page_select = IGP01E1000_PHY_PAGE_SELECT; - } else { - page_shift = 0; - page_select = BM_PHY_PAGE_SELECT; - } - - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, page_select, - (page << page_shift)); - if (ret_val) - goto release; - } - - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - -release: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000e_read_phy_reg_bm - Read BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val; - u32 page = offset >> IGP_PAGE_SHIFT; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, - true, false); - goto release; - } - - hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - u32 page_shift, page_select; - - /* Page select is register 31 for phy address 1 and 22 for - * phy address 2 and 3. Page select is shifted only for - * phy address 1. - */ - if (hw->phy.addr == 1) { - page_shift = IGP_PAGE_SHIFT; - page_select = IGP01E1000_PHY_PAGE_SELECT; - } else { - page_shift = 0; - page_select = BM_PHY_PAGE_SELECT; - } - - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, page_select, - (page << page_shift)); - if (ret_val) - goto release; - } - - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); -release: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000e_read_phy_reg_bm2 - Read BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val; - u16 page = (u16)(offset >> IGP_PAGE_SHIFT); - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, - true, false); - goto release; - } - - hw->phy.addr = 1; - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, - page); - - if (ret_val) - goto release; - } - - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); -release: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000e_write_phy_reg_bm2 - Write BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val; - u16 page = (u16)(offset >> IGP_PAGE_SHIFT); - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, - false, false); - goto release; - } - - hw->phy.addr = 1; - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, - page); - - if (ret_val) - goto release; - } - - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - -release: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers - * @hw: pointer to the HW structure - * @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG - * - * Assumes semaphore already acquired and phy_reg points to a valid memory - * address to store contents of the BM_WUC_ENABLE_REG register. - **/ -s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) -{ - s32 ret_val; - u16 temp; - - /* All page select, port ctrl and wakeup registers use phy address 1 */ - hw->phy.addr = 1; - - /* Select Port Control Registers page */ - ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); - if (ret_val) { - e_dbg("Could not set Port Control page\n"); - return ret_val; - } - - ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); - if (ret_val) { - e_dbg("Could not read PHY register %d.%d\n", - BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); - return ret_val; - } - - /* Enable both PHY wakeup mode and Wakeup register page writes. - * Prevent a power state change by disabling ME and Host PHY wakeup. - */ - temp = *phy_reg; - temp |= BM_WUC_ENABLE_BIT; - temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT); - - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp); - if (ret_val) { - e_dbg("Could not write PHY register %d.%d\n", - BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); - return ret_val; - } - - /* Select Host Wakeup Registers page - caller now able to write - * registers on the Wakeup registers page - */ - return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT)); -} - -/** - * e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs - * @hw: pointer to the HW structure - * @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG - * - * Restore BM_WUC_ENABLE_REG to its original value. - * - * Assumes semaphore already acquired and *phy_reg is the contents of the - * BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by - * caller. - **/ -s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) -{ - s32 ret_val; - - /* Select Port Control Registers page */ - ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); - if (ret_val) { - e_dbg("Could not set Port Control page\n"); - return ret_val; - } - - /* Restore 769.17 to its original value */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg); - if (ret_val) - e_dbg("Could not restore PHY register %d.%d\n", - BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); - - return ret_val; -} - -/** - * e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register - * @hw: pointer to the HW structure - * @offset: register offset to be read or written - * @data: pointer to the data to read or write - * @read: determines if operation is read or write - * @page_set: BM_WUC_PAGE already set and access enabled - * - * Read the PHY register at offset and store the retrieved information in - * data, or write data to PHY register at offset. Note the procedure to - * access the PHY wakeup registers is different than reading the other PHY - * registers. It works as such: - * 1) Set 769.17.2 (page 769, register 17, bit 2) = 1 - * 2) Set page to 800 for host (801 if we were manageability) - * 3) Write the address using the address opcode (0x11) - * 4) Read or write the data using the data opcode (0x12) - * 5) Restore 769.17.2 to its original value - * - * Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and - * step 5 is done by e1000_disable_phy_wakeup_reg_access_bm(). - * - * Assumes semaphore is already acquired. When page_set==true, assumes - * the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack - * is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()). - **/ -static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, - u16 *data, bool read, bool page_set) -{ - s32 ret_val; - u16 reg = BM_PHY_REG_NUM(offset); - u16 page = BM_PHY_REG_PAGE(offset); - u16 phy_reg = 0; - - /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */ - if ((hw->mac.type == e1000_pchlan) && - (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) - e_dbg("Attempting to access page %d while gig enabled.\n", - page); - - if (!page_set) { - /* Enable access to PHY wakeup registers */ - ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg); - if (ret_val) { - e_dbg("Could not enable PHY wakeup reg access\n"); - return ret_val; - } - } - - e_dbg("Accessing PHY page %d reg 0x%x\n", page, reg); - - /* Write the Wakeup register page offset value using opcode 0x11 */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg); - if (ret_val) { - e_dbg("Could not write address opcode to page %d\n", page); - return ret_val; - } - - if (read) { - /* Read the Wakeup register page value using opcode 0x12 */ - ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, - data); - } else { - /* Write the Wakeup register page value using opcode 0x12 */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, - *data); - } - - if (ret_val) { - e_dbg("Could not access PHY reg %d.%d\n", page, reg); - return ret_val; - } - - if (!page_set) - ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg); - - return ret_val; -} - -/** - * e1000_power_up_phy_copper - Restore copper link in case of PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, restore the link to previous - * settings. - **/ -void e1000_power_up_phy_copper(struct e1000_hw *hw) -{ - u16 mii_reg = 0; - - /* The PHY will retain its settings across a power down/up cycle */ - e1e_rphy(hw, MII_BMCR, &mii_reg); - mii_reg &= ~BMCR_PDOWN; - e1e_wphy(hw, MII_BMCR, mii_reg); -} - -/** - * e1000_power_down_phy_copper - Restore copper link in case of PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, restore the link to previous - * settings. - **/ -void e1000_power_down_phy_copper(struct e1000_hw *hw) -{ - u16 mii_reg = 0; - - /* The PHY will retain its settings across a power down/up cycle */ - e1e_rphy(hw, MII_BMCR, &mii_reg); - mii_reg |= BMCR_PDOWN; - e1e_wphy(hw, MII_BMCR, mii_reg); - usleep_range(1000, 2000); -} - -/** - * __e1000_read_phy_reg_hv - Read HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and stores the retrieved information in data. Release any acquired - * semaphore before exiting. - **/ -static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, - bool locked, bool page_set) -{ - s32 ret_val; - u16 page = BM_PHY_REG_PAGE(offset); - u16 reg = BM_PHY_REG_NUM(offset); - u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); - - if (!locked) { - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, - true, page_set); - goto out; - } - - if (page > 0 && page < HV_INTC_FC_PAGE_START) { - ret_val = e1000_access_phy_debug_regs_hv(hw, offset, - data, true); - goto out; - } - - if (!page_set) { - if (page == HV_INTC_FC_PAGE_START) - page = 0; - - if (reg > MAX_PHY_MULTI_PAGE_REG) { - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000_set_page_igp(hw, - (page << IGP_PAGE_SHIFT)); - - hw->phy.addr = phy_addr; - - if (ret_val) - goto out; - } - } - - e_dbg("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page, - page << IGP_PAGE_SHIFT, reg); - - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, data); -out: - if (!locked) - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_read_phy_reg_hv - Read HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore then reads the PHY register at offset and stores - * the retrieved information in data. Release the acquired semaphore - * before exiting. - **/ -s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000_read_phy_reg_hv(hw, offset, data, false, false); -} - -/** - * e1000_read_phy_reg_hv_locked - Read HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY register at offset and stores the retrieved information - * in data. Assumes semaphore already acquired. - **/ -s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000_read_phy_reg_hv(hw, offset, data, true, false); -} - -/** - * e1000_read_phy_reg_page_hv - Read HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Reads the PHY register at offset and stores the retrieved information - * in data. Assumes semaphore already acquired and page already set. - **/ -s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000_read_phy_reg_hv(hw, offset, data, true, true); -} - -/** - * __e1000_write_phy_reg_hv - Write HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, - bool locked, bool page_set) -{ - s32 ret_val; - u16 page = BM_PHY_REG_PAGE(offset); - u16 reg = BM_PHY_REG_NUM(offset); - u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); - - if (!locked) { - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, - false, page_set); - goto out; - } - - if (page > 0 && page < HV_INTC_FC_PAGE_START) { - ret_val = e1000_access_phy_debug_regs_hv(hw, offset, - &data, false); - goto out; - } - - if (!page_set) { - if (page == HV_INTC_FC_PAGE_START) - page = 0; - - /* Workaround MDIO accesses being disabled after entering IEEE - * Power Down (when bit 11 of the PHY Control register is set) - */ - if ((hw->phy.type == e1000_phy_82578) && - (hw->phy.revision >= 1) && - (hw->phy.addr == 2) && - !(MAX_PHY_REG_ADDRESS & reg) && (data & (1 << 11))) { - u16 data2 = 0x7EFF; - ret_val = e1000_access_phy_debug_regs_hv(hw, - (1 << 6) | 0x3, - &data2, false); - if (ret_val) - goto out; - } - - if (reg > MAX_PHY_MULTI_PAGE_REG) { - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000_set_page_igp(hw, - (page << IGP_PAGE_SHIFT)); - - hw->phy.addr = phy_addr; - - if (ret_val) - goto out; - } - } - - e_dbg("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page, - page << IGP_PAGE_SHIFT, reg); - - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, - data); - -out: - if (!locked) - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_write_phy_reg_hv - Write HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore then writes the data to PHY register at the offset. - * Release the acquired semaphores before exiting. - **/ -s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000_write_phy_reg_hv(hw, offset, data, false, false); -} - -/** - * e1000_write_phy_reg_hv_locked - Write HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Writes the data to PHY register at the offset. Assumes semaphore - * already acquired. - **/ -s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000_write_phy_reg_hv(hw, offset, data, true, false); -} - -/** - * e1000_write_phy_reg_page_hv - Write HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Writes the data to PHY register at the offset. Assumes semaphore - * already acquired and page already set. - **/ -s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000_write_phy_reg_hv(hw, offset, data, true, true); -} - -/** - * e1000_get_phy_addr_for_hv_page - Get PHY address based on page - * @page: page to be accessed - **/ -static u32 e1000_get_phy_addr_for_hv_page(u32 page) -{ - u32 phy_addr = 2; - - if (page >= HV_INTC_FC_PAGE_START) - phy_addr = 1; - - return phy_addr; -} - -/** - * e1000_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers - * @hw: pointer to the HW structure - * @offset: register offset to be read or written - * @data: pointer to the data to be read or written - * @read: determines if operation is read or write - * - * Reads the PHY register at offset and stores the retreived information - * in data. Assumes semaphore already acquired. Note that the procedure - * to access these regs uses the address port and data port to read/write. - * These accesses done with PHY address 2 and without using pages. - **/ -static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, - u16 *data, bool read) -{ - s32 ret_val; - u32 addr_reg; - u32 data_reg; - - /* This takes care of the difference with desktop vs mobile phy */ - addr_reg = ((hw->phy.type == e1000_phy_82578) ? - I82578_ADDR_REG : I82577_ADDR_REG); - data_reg = addr_reg + 1; - - /* All operations in this function are phy address 2 */ - hw->phy.addr = 2; - - /* masking with 0x3F to remove the page from offset */ - ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F); - if (ret_val) { - e_dbg("Could not write the Address Offset port register\n"); - return ret_val; - } - - /* Read or write the data value next */ - if (read) - ret_val = e1000e_read_phy_reg_mdic(hw, data_reg, data); - else - ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data); - - if (ret_val) - e_dbg("Could not access the Data port register\n"); - - return ret_val; -} - -/** - * e1000_link_stall_workaround_hv - Si workaround - * @hw: pointer to the HW structure - * - * This function works around a Si bug where the link partner can get - * a link up indication before the PHY does. If small packets are sent - * by the link partner they can be placed in the packet buffer without - * being properly accounted for by the PHY and will stall preventing - * further packets from being received. The workaround is to clear the - * packet buffer after the PHY detects link up. - **/ -s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u16 data; - - if (hw->phy.type != e1000_phy_82578) - return 0; - - /* Do not apply workaround if in PHY loopback bit 14 set */ - e1e_rphy(hw, MII_BMCR, &data); - if (data & BMCR_LOOPBACK) - return 0; - - /* check if link is up and at 1Gbps */ - ret_val = e1e_rphy(hw, BM_CS_STATUS, &data); - if (ret_val) - return ret_val; - - data &= (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_MASK); - - if (data != (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_1000)) - return 0; - - msleep(200); - - /* flush the packets in the fifo buffer */ - ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, - (HV_MUX_DATA_CTRL_GEN_TO_MAC | - HV_MUX_DATA_CTRL_FORCE_SPEED)); - if (ret_val) - return ret_val; - - return e1e_wphy(hw, HV_MUX_DATA_CTRL, HV_MUX_DATA_CTRL_GEN_TO_MAC); -} - -/** - * e1000_check_polarity_82577 - Checks the polarity. - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - * - * Polarity is determined based on the PHY specific status register. - **/ -s32 e1000_check_polarity_82577(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data); - - if (!ret_val) - phy->cable_polarity = ((data & I82577_PHY_STATUS2_REV_POLARITY) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal); - - return ret_val; -} - -/** - * e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY - * @hw: pointer to the HW structure - * - * Calls the PHY setup function to force speed and duplex. - **/ -s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - ret_val = e1e_rphy(hw, MII_BMCR, &phy_data); - if (ret_val) - return ret_val; - - e1000e_phy_force_speed_duplex_setup(hw, &phy_data); - - ret_val = e1e_wphy(hw, MII_BMCR, phy_data); - if (ret_val) - return ret_val; - - udelay(1); - - if (phy->autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on 82577 phy\n"); - - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - - if (!link) - e_dbg("Link taking longer than expected.\n"); - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - } - - return ret_val; -} - -/** - * e1000_get_phy_info_82577 - Retrieve I82577 PHY information - * @hw: pointer to the HW structure - * - * Read PHY status to determine if link is up. If link is up, then - * set/determine 10base-T extended distance and polarity correction. Read - * PHY port status to determine MDI/MDIx and speed. Based on the speed, - * determine on the cable length, local and remote receiver. - **/ -s32 e1000_get_phy_info_82577(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (!link) { - e_dbg("Phy info is only valid if link is up\n"); - return -E1000_ERR_CONFIG; - } - - phy->polarity_correction = true; - - ret_val = e1000_check_polarity_82577(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data); - if (ret_val) - return ret_val; - - phy->is_mdix = !!(data & I82577_PHY_STATUS2_MDIX); - - if ((data & I82577_PHY_STATUS2_SPEED_MASK) == - I82577_PHY_STATUS2_SPEED_1000MBPS) { - ret_val = hw->phy.ops.get_cable_length(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, MII_STAT1000, &data); - if (ret_val) - return ret_val; - - phy->local_rx = (data & LPA_1000LOCALRXOK) - ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - - phy->remote_rx = (data & LPA_1000REMRXOK) - ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - } else { - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - } - - return 0; -} - -/** - * e1000_get_cable_length_82577 - Determine cable length for 82577 PHY - * @hw: pointer to the HW structure - * - * Reads the diagnostic status register and verifies result is valid before - * placing it in the phy_cable_length field. - **/ -s32 e1000_get_cable_length_82577(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, length; - - ret_val = e1e_rphy(hw, I82577_PHY_DIAG_STATUS, &phy_data); - if (ret_val) - return ret_val; - - length = ((phy_data & I82577_DSTATUS_CABLE_LENGTH) >> - I82577_DSTATUS_CABLE_LENGTH_SHIFT); - - if (length == E1000_CABLE_LENGTH_UNDEFINED) - return -E1000_ERR_PHY; - - phy->cable_length = length; - - return 0; -} diff --git a/addons/e1000e/src/3.10.108/phy.h b/addons/e1000e/src/3.10.108/phy.h deleted file mode 100644 index f4f71b99..00000000 --- a/addons/e1000e/src/3.10.108/phy.h +++ /dev/null @@ -1,242 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#ifndef _E1000E_PHY_H_ -#define _E1000E_PHY_H_ - -s32 e1000e_check_downshift(struct e1000_hw *hw); -s32 e1000_check_polarity_m88(struct e1000_hw *hw); -s32 e1000_check_polarity_igp(struct e1000_hw *hw); -s32 e1000_check_polarity_ife(struct e1000_hw *hw); -s32 e1000e_check_reset_block_generic(struct e1000_hw *hw); -s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw); -s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw); -s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw); -s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw); -s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); -s32 e1000e_get_cable_length_m88(struct e1000_hw *hw); -s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw); -s32 e1000e_get_cfg_done_generic(struct e1000_hw *hw); -s32 e1000e_get_phy_id(struct e1000_hw *hw); -s32 e1000e_get_phy_info_igp(struct e1000_hw *hw); -s32 e1000e_get_phy_info_m88(struct e1000_hw *hw); -s32 e1000_get_phy_info_ife(struct e1000_hw *hw); -s32 e1000e_phy_sw_reset(struct e1000_hw *hw); -void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); -s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw); -s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); -s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page); -s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active); -s32 e1000e_setup_copper_link(struct e1000_hw *hw); -s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, - u32 usec_interval, bool *success); -s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw); -enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id); -s32 e1000e_determine_phy_address(struct e1000_hw *hw); -s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg); -s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg); -s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data); -void e1000_power_up_phy_copper(struct e1000_hw *hw); -void e1000_power_down_phy_copper(struct e1000_hw *hw); -s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw); -s32 e1000_copper_link_setup_82577(struct e1000_hw *hw); -s32 e1000_check_polarity_82577(struct e1000_hw *hw); -s32 e1000_get_phy_info_82577(struct e1000_hw *hw); -s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw); -s32 e1000_get_cable_length_82577(struct e1000_hw *hw); - -#define E1000_MAX_PHY_ADDR 8 - -/* IGP01E1000 Specific Registers */ -#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */ -#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */ -#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */ -#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */ -#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */ -#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ -#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */ -#define IGP_PAGE_SHIFT 5 -#define PHY_REG_MASK 0x1F - -/* BM/HV Specific Registers */ -#define BM_PORT_CTRL_PAGE 769 -#define BM_WUC_PAGE 800 -#define BM_WUC_ADDRESS_OPCODE 0x11 -#define BM_WUC_DATA_OPCODE 0x12 -#define BM_WUC_ENABLE_PAGE BM_PORT_CTRL_PAGE -#define BM_WUC_ENABLE_REG 17 -#define BM_WUC_ENABLE_BIT (1 << 2) -#define BM_WUC_HOST_WU_BIT (1 << 4) -#define BM_WUC_ME_WU_BIT (1 << 5) - -#define PHY_UPPER_SHIFT 21 -#define BM_PHY_REG(page, reg) \ - (((reg) & MAX_PHY_REG_ADDRESS) |\ - (((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\ - (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT))) -#define BM_PHY_REG_PAGE(offset) \ - ((u16)(((offset) >> PHY_PAGE_SHIFT) & 0xFFFF)) -#define BM_PHY_REG_NUM(offset) \ - ((u16)(((offset) & MAX_PHY_REG_ADDRESS) |\ - (((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\ - ~MAX_PHY_REG_ADDRESS))) - -#define HV_INTC_FC_PAGE_START 768 -#define I82578_ADDR_REG 29 -#define I82577_ADDR_REG 16 -#define I82577_CFG_REG 22 -#define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15) -#define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift */ -#define I82577_CTRL_REG 23 - -/* 82577 specific PHY registers */ -#define I82577_PHY_CTRL_2 18 -#define I82577_PHY_LBK_CTRL 19 -#define I82577_PHY_STATUS_2 26 -#define I82577_PHY_DIAG_STATUS 31 - -/* I82577 PHY Status 2 */ -#define I82577_PHY_STATUS2_REV_POLARITY 0x0400 -#define I82577_PHY_STATUS2_MDIX 0x0800 -#define I82577_PHY_STATUS2_SPEED_MASK 0x0300 -#define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200 - -/* I82577 PHY Control 2 */ -#define I82577_PHY_CTRL2_MANUAL_MDIX 0x0200 -#define I82577_PHY_CTRL2_AUTO_MDI_MDIX 0x0400 -#define I82577_PHY_CTRL2_MDIX_CFG_MASK 0x0600 - -/* I82577 PHY Diagnostics Status */ -#define I82577_DSTATUS_CABLE_LENGTH 0x03FC -#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2 - -/* BM PHY Copper Specific Control 1 */ -#define BM_CS_CTRL1 16 - -/* BM PHY Copper Specific Status */ -#define BM_CS_STATUS 17 -#define BM_CS_STATUS_LINK_UP 0x0400 -#define BM_CS_STATUS_RESOLVED 0x0800 -#define BM_CS_STATUS_SPEED_MASK 0xC000 -#define BM_CS_STATUS_SPEED_1000 0x8000 - -/* 82577 Mobile Phy Status Register */ -#define HV_M_STATUS 26 -#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000 -#define HV_M_STATUS_SPEED_MASK 0x0300 -#define HV_M_STATUS_SPEED_1000 0x0200 -#define HV_M_STATUS_LINK_UP 0x0040 - -#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 -#define IGP01E1000_PHY_POLARITY_MASK 0x0078 - -#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 -#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */ - -#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 - -#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ -#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ -#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ - -#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 - -#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 -#define IGP01E1000_PSSR_MDIX 0x0800 -#define IGP01E1000_PSSR_SPEED_MASK 0xC000 -#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 - -#define IGP02E1000_PHY_CHANNEL_NUM 4 -#define IGP02E1000_PHY_AGC_A 0x11B1 -#define IGP02E1000_PHY_AGC_B 0x12B1 -#define IGP02E1000_PHY_AGC_C 0x14B1 -#define IGP02E1000_PHY_AGC_D 0x18B1 - -#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course=15:13, Fine=12:9 */ -#define IGP02E1000_AGC_LENGTH_MASK 0x7F -#define IGP02E1000_AGC_RANGE 15 - -#define E1000_CABLE_LENGTH_UNDEFINED 0xFF - -#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 -#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 -#define E1000_KMRNCTRLSTA_REN 0x00200000 -#define E1000_KMRNCTRLSTA_CTRL_OFFSET 0x1 /* Kumeran Control */ -#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ -#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ -#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ -#define E1000_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */ -#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ -#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 -#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002 /* enable K1 */ -#define E1000_KMRNCTRLSTA_HD_CTRL 0x10 /* Kumeran HD Control */ - -#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 -#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Ctrl */ -#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Ctrl */ -#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */ - -/* IFE PHY Extended Status Control */ -#define IFE_PESC_POLARITY_REVERSED 0x0100 - -/* IFE PHY Special Control */ -#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 -#define IFE_PSC_FORCE_POLARITY 0x0020 - -/* IFE PHY Special Control and LED Control */ -#define IFE_PSCL_PROBE_MODE 0x0020 -#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ -#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ - -/* IFE PHY MDIX Control */ -#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ -#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */ -#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto, 0=disable */ - -#endif diff --git a/addons/e1000e/src/3.10.108/ptp.c b/addons/e1000e/src/3.10.108/ptp.c deleted file mode 100644 index 065f8c80..00000000 --- a/addons/e1000e/src/3.10.108/ptp.c +++ /dev/null @@ -1,276 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -/* PTP 1588 Hardware Clock (PHC) - * Derived from PTP Hardware Clock driver for Intel 82576 and 82580 (igb) - * Copyright (C) 2011 Richard Cochran - */ - -#include "e1000.h" - -/** - * e1000e_phc_adjfreq - adjust the frequency of the hardware clock - * @ptp: ptp clock structure - * @delta: Desired frequency change in parts per billion - * - * Adjust the frequency of the PHC cycle counter by the indicated delta from - * the base frequency. - **/ -static int e1000e_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) -{ - struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, - ptp_clock_info); - struct e1000_hw *hw = &adapter->hw; - bool neg_adj = false; - u64 adjustment; - u32 timinca, incvalue; - s32 ret_val; - - if ((delta > ptp->max_adj) || (delta <= -1000000000)) - return -EINVAL; - - if (delta < 0) { - neg_adj = true; - delta = -delta; - } - - /* Get the System Time Register SYSTIM base frequency */ - ret_val = e1000e_get_base_timinca(adapter, &timinca); - if (ret_val) - return ret_val; - - incvalue = timinca & E1000_TIMINCA_INCVALUE_MASK; - - adjustment = incvalue; - adjustment *= delta; - adjustment = div_u64(adjustment, 1000000000); - - incvalue = neg_adj ? (incvalue - adjustment) : (incvalue + adjustment); - - timinca &= ~E1000_TIMINCA_INCVALUE_MASK; - timinca |= incvalue; - - ew32(TIMINCA, timinca); - - return 0; -} - -/** - * e1000e_phc_adjtime - Shift the time of the hardware clock - * @ptp: ptp clock structure - * @delta: Desired change in nanoseconds - * - * Adjust the timer by resetting the timecounter structure. - **/ -static int e1000e_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) -{ - struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, - ptp_clock_info); - unsigned long flags; - s64 now; - - spin_lock_irqsave(&adapter->systim_lock, flags); - now = timecounter_read(&adapter->tc); - now += delta; - timecounter_init(&adapter->tc, &adapter->cc, now); - spin_unlock_irqrestore(&adapter->systim_lock, flags); - - return 0; -} - -/** - * e1000e_phc_gettime - Reads the current time from the hardware clock - * @ptp: ptp clock structure - * @ts: timespec structure to hold the current time value - * - * Read the timecounter and return the correct value in ns after converting - * it into a struct timespec. - **/ -static int e1000e_phc_gettime(struct ptp_clock_info *ptp, struct timespec *ts) -{ - struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, - ptp_clock_info); - unsigned long flags; - u32 remainder; - u64 ns; - - spin_lock_irqsave(&adapter->systim_lock, flags); - ns = timecounter_read(&adapter->tc); - spin_unlock_irqrestore(&adapter->systim_lock, flags); - - ts->tv_sec = div_u64_rem(ns, NSEC_PER_SEC, &remainder); - ts->tv_nsec = remainder; - - return 0; -} - -/** - * e1000e_phc_settime - Set the current time on the hardware clock - * @ptp: ptp clock structure - * @ts: timespec containing the new time for the cycle counter - * - * Reset the timecounter to use a new base value instead of the kernel - * wall timer value. - **/ -static int e1000e_phc_settime(struct ptp_clock_info *ptp, - const struct timespec *ts) -{ - struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, - ptp_clock_info); - unsigned long flags; - u64 ns; - - ns = timespec_to_ns(ts); - - /* reset the timecounter */ - spin_lock_irqsave(&adapter->systim_lock, flags); - timecounter_init(&adapter->tc, &adapter->cc, ns); - spin_unlock_irqrestore(&adapter->systim_lock, flags); - - return 0; -} - -/** - * e1000e_phc_enable - enable or disable an ancillary feature - * @ptp: ptp clock structure - * @request: Desired resource to enable or disable - * @on: Caller passes one to enable or zero to disable - * - * Enable (or disable) ancillary features of the PHC subsystem. - * Currently, no ancillary features are supported. - **/ -static int e1000e_phc_enable(struct ptp_clock_info __always_unused *ptp, - struct ptp_clock_request __always_unused *request, - int __always_unused on) -{ - return -EOPNOTSUPP; -} - -static void e1000e_systim_overflow_work(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, struct e1000_adapter, - systim_overflow_work.work); - struct e1000_hw *hw = &adapter->hw; - struct timespec ts; - - adapter->ptp_clock_info.gettime(&adapter->ptp_clock_info, &ts); - - e_dbg("SYSTIM overflow check at %ld.%09lu\n", ts.tv_sec, ts.tv_nsec); - - schedule_delayed_work(&adapter->systim_overflow_work, - E1000_SYSTIM_OVERFLOW_PERIOD); -} - -static const struct ptp_clock_info e1000e_ptp_clock_info = { - .owner = THIS_MODULE, - .n_alarm = 0, - .n_ext_ts = 0, - .n_per_out = 0, - .pps = 0, - .adjfreq = e1000e_phc_adjfreq, - .adjtime = e1000e_phc_adjtime, - .gettime = e1000e_phc_gettime, - .settime = e1000e_phc_settime, - .enable = e1000e_phc_enable, -}; - -/** - * e1000e_ptp_init - initialize PTP for devices which support it - * @adapter: board private structure - * - * This function performs the required steps for enabling PTP support. - * If PTP support has already been loaded it simply calls the cyclecounter - * init routine and exits. - **/ -void e1000e_ptp_init(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - adapter->ptp_clock = NULL; - - if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP)) - return; - - adapter->ptp_clock_info = e1000e_ptp_clock_info; - - snprintf(adapter->ptp_clock_info.name, - sizeof(adapter->ptp_clock_info.name), "%pm", - adapter->netdev->perm_addr); - - switch (hw->mac.type) { - case e1000_pch2lan: - case e1000_pch_lpt: - if ((hw->mac.type != e1000_pch_lpt) || - (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)) { - adapter->ptp_clock_info.max_adj = 24000000 - 1; - break; - } - /* fall-through */ - case e1000_82574: - case e1000_82583: - adapter->ptp_clock_info.max_adj = 600000000 - 1; - break; - default: - break; - } - - INIT_DELAYED_WORK(&adapter->systim_overflow_work, - e1000e_systim_overflow_work); - - schedule_delayed_work(&adapter->systim_overflow_work, - E1000_SYSTIM_OVERFLOW_PERIOD); - - adapter->ptp_clock = ptp_clock_register(&adapter->ptp_clock_info, - &adapter->pdev->dev); - if (IS_ERR(adapter->ptp_clock)) { - adapter->ptp_clock = NULL; - e_err("ptp_clock_register failed\n"); - } else { - e_info("registered PHC clock\n"); - } -} - -/** - * e1000e_ptp_remove - disable PTP device and stop the overflow check - * @adapter: board private structure - * - * Stop the PTP support, and cancel the delayed work. - **/ -void e1000e_ptp_remove(struct e1000_adapter *adapter) -{ - if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP)) - return; - - cancel_delayed_work_sync(&adapter->systim_overflow_work); - - if (adapter->ptp_clock) { - ptp_clock_unregister(adapter->ptp_clock); - adapter->ptp_clock = NULL; - e_info("removed PHC\n"); - } -} diff --git a/addons/e1000e/src/3.10.108/regs.h b/addons/e1000e/src/3.10.108/regs.h deleted file mode 100644 index a7e6a3e3..00000000 --- a/addons/e1000e/src/3.10.108/regs.h +++ /dev/null @@ -1,253 +0,0 @@ -/******************************************************************************* - - Intel PRO/1000 Linux driver - Copyright(c) 1999 - 2013 Intel Corporation. - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information: - Linux NICS - e1000-devel Mailing List - Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ - -#ifndef _E1000E_REGS_H_ -#define _E1000E_REGS_H_ - -#define E1000_CTRL 0x00000 /* Device Control - RW */ -#define E1000_STATUS 0x00008 /* Device Status - RO */ -#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ -#define E1000_EERD 0x00014 /* EEPROM Read - RW */ -#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ -#define E1000_FLA 0x0001C /* Flash Access - RW */ -#define E1000_MDIC 0x00020 /* MDI Control - RW */ -#define E1000_SCTL 0x00024 /* SerDes Control - RW */ -#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ -#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ -#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ -#define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */ -#define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ -#define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */ -#define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */ -#define E1000_FCT 0x00030 /* Flow Control Type - RW */ -#define E1000_VET 0x00038 /* VLAN Ether Type - RW */ -#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ -#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ -#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ -#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ -#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ -#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ -#define E1000_IVAR 0x000E4 /* Interrupt Vector Allocation Register - RW */ -#define E1000_SVCR 0x000F0 -#define E1000_SVT 0x000F4 -#define E1000_LPIC 0x000FC /* Low Power IDLE control */ -#define E1000_RCTL 0x00100 /* Rx Control - RW */ -#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ -#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */ -#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */ -#define E1000_PBA_ECC 0x01100 /* PBA ECC Register */ -#define E1000_TCTL 0x00400 /* Tx Control - RW */ -#define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */ -#define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */ -#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ -#define E1000_LEDCTL 0x00E00 /* LED Control - RW */ -#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */ -#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */ -#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */ -#define E1000_POEMB E1000_PHY_CTRL /* PHY OEM Bits */ -#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ -#define E1000_PBS 0x01008 /* Packet Buffer Size */ -#define E1000_PBECCSTS 0x0100C /* Packet Buffer ECC Status - RW */ -#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ -#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */ -#define E1000_FLOP 0x0103C /* FLASH Opcode Register */ -#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ -#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ -#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ -#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */ -#define E1000_RDFH 0x02410 /* Rx Data FIFO Head - RW */ -#define E1000_RDFT 0x02418 /* Rx Data FIFO Tail - RW */ -#define E1000_RDFHS 0x02420 /* Rx Data FIFO Head Saved - RW */ -#define E1000_RDFTS 0x02428 /* Rx Data FIFO Tail Saved - RW */ -#define E1000_RDFPC 0x02430 /* Rx Data FIFO Packet Count - RW */ -/* Split and Replication Rx Control - RW */ -#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */ -#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */ -/* Convenience macros - * - * Note: "_n" is the queue number of the register to be written to. - * - * Example usage: - * E1000_RDBAL_REG(current_rx_queue) - */ -#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \ - (0x0C000 + ((_n) * 0x40))) -#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \ - (0x0C004 + ((_n) * 0x40))) -#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \ - (0x0C008 + ((_n) * 0x40))) -#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \ - (0x0C010 + ((_n) * 0x40))) -#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \ - (0x0C018 + ((_n) * 0x40))) -#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \ - (0x0C028 + ((_n) * 0x40))) -#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \ - (0x0E000 + ((_n) * 0x40))) -#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \ - (0x0E004 + ((_n) * 0x40))) -#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \ - (0x0E008 + ((_n) * 0x40))) -#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \ - (0x0E010 + ((_n) * 0x40))) -#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \ - (0x0E018 + ((_n) * 0x40))) -#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \ - (0x0E028 + ((_n) * 0x40))) -#define E1000_TARC(_n) (0x03840 + ((_n) * 0x100)) -#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */ -#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \ - (0x054E0 + ((_i - 16) * 8))) -#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \ - (0x054E4 + ((_i - 16) * 8))) -#define E1000_SHRAL(_i) (0x05438 + ((_i) * 8)) -#define E1000_SHRAH(_i) (0x0543C + ((_i) * 8)) -#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */ -#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */ -#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */ -#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */ -#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */ -#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */ -#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */ -#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ -#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ -#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ -#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */ -#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */ -#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */ -#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */ -#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */ -#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */ -#define E1000_COLC 0x04028 /* Collision Count - R/clr */ -#define E1000_DC 0x04030 /* Defer Count - R/clr */ -#define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */ -#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ -#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ -#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ -#define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */ -#define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */ -#define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */ -#define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */ -#define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */ -#define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */ -#define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */ -#define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */ -#define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */ -#define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */ -#define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */ -#define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */ -#define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */ -#define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */ -#define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */ -#define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */ -#define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */ -#define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */ -#define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */ -#define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */ -#define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */ -#define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */ -#define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */ -#define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */ -#define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */ -#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ -#define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */ -#define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */ -#define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */ -#define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */ -#define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */ -#define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */ -#define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */ -#define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */ -#define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */ -#define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */ -#define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */ -#define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */ -#define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */ -#define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */ -#define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */ -#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */ -#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */ -#define E1000_IAC 0x04100 /* Interrupt Assertion Count */ -#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */ -#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */ -#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */ -#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */ -#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */ -#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */ -#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */ -#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */ -#define E1000_CRC_OFFSET 0x05F50 /* CRC Offset register */ - -#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */ -#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */ -#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */ -#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */ -#define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */ -#define E1000_RFCTL 0x05008 /* Receive Filter Control */ -#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ -#define E1000_RA 0x05400 /* Receive Address - RW Array */ -#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ -#define E1000_WUC 0x05800 /* Wakeup Control - RW */ -#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ -#define E1000_WUS 0x05810 /* Wakeup Status - RO */ -#define E1000_MANC 0x05820 /* Management Control - RW */ -#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ -#define E1000_HOST_IF 0x08800 /* Host Interface */ - -#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */ -#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */ -/* Management Decision Filters */ -#define E1000_MDEF(_n) (0x05890 + (4 * (_n))) -#define E1000_SW_FW_SYNC 0x05B5C /* SW-FW Synchronization - RW */ -#define E1000_GCR 0x05B00 /* PCI-Ex Control */ -#define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */ -#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ -#define E1000_SWSM 0x05B50 /* SW Semaphore */ -#define E1000_FWSM 0x05B54 /* FW Semaphore */ -/* Driver-only SW semaphore (not used by BOOT agents) */ -#define E1000_SWSM2 0x05B58 -#define E1000_FFLT_DBG 0x05F04 /* Debug Register */ -#define E1000_HICR 0x08F00 /* Host Interface Control */ - -/* RSS registers */ -#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */ -#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */ -#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */ -#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */ -#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */ -#define E1000_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */ -#define E1000_RXSTMPH 0x0B628 /* Rx timestamp High - RO */ -#define E1000_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */ -#define E1000_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */ -#define E1000_SYSTIML 0x0B600 /* System time register Low - RO */ -#define E1000_SYSTIMH 0x0B604 /* System time register High - RO */ -#define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */ -#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */ -#define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */ - -#endif diff --git a/addons/e1000e/src/4.4.180/80003es2lan.c b/addons/e1000e/src/4.4.180/80003es2lan.c deleted file mode 100644 index 2af603f3..00000000 --- a/addons/e1000e/src/4.4.180/80003es2lan.c +++ /dev/null @@ -1,1418 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -/* 80003ES2LAN Gigabit Ethernet Controller (Copper) - * 80003ES2LAN Gigabit Ethernet Controller (Serdes) - */ - -#include "e1000.h" - -/* A table for the GG82563 cable length where the range is defined - * with a lower bound at "index" and the upper bound at - * "index + 5". - */ -static const u16 e1000_gg82563_cable_length_table[] = { - 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF -}; - -#define GG82563_CABLE_LENGTH_TABLE_SIZE \ - ARRAY_SIZE(e1000_gg82563_cable_length_table) - -static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw); -static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); -static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask); -static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw); -static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw); -static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw); -static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex); -static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, - u16 *data); -static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, - u16 data); -static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw); - -/** - * e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - - if (hw->phy.media_type != e1000_media_type_copper) { - phy->type = e1000_phy_none; - return 0; - } else { - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan; - } - - phy->addr = 1; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->reset_delay_us = 100; - phy->type = e1000_phy_gg82563; - - /* This can only be done after all function pointers are setup. */ - ret_val = e1000e_get_phy_id(hw); - - /* Verify phy id */ - if (phy->id != GG82563_E_PHY_ID) - return -E1000_ERR_PHY; - - return ret_val; -} - -/** - * e1000_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - u16 size; - - nvm->opcode_bits = 8; - nvm->delay_usec = 1; - switch (nvm->override) { - case e1000_nvm_override_spi_large: - nvm->page_size = 32; - nvm->address_bits = 16; - break; - case e1000_nvm_override_spi_small: - nvm->page_size = 8; - nvm->address_bits = 8; - break; - default: - nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; - nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; - break; - } - - nvm->type = e1000_nvm_eeprom_spi; - - size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> - E1000_EECD_SIZE_EX_SHIFT); - - /* Added to a constant, "size" becomes the left-shift value - * for setting word_size. - */ - size += NVM_WORD_SIZE_BASE_SHIFT; - - /* EEPROM access above 16k is unsupported */ - if (size > 14) - size = 14; - nvm->word_size = 1 << size; - - return 0; -} - -/** - * e1000_init_mac_params_80003es2lan - Init ESB2 MAC func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_mac_params_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - /* Set media type and media-dependent function pointers */ - switch (hw->adapter->pdev->device) { - case E1000_DEV_ID_80003ES2LAN_SERDES_DPT: - hw->phy.media_type = e1000_media_type_internal_serdes; - mac->ops.check_for_link = e1000e_check_for_serdes_link; - mac->ops.setup_physical_interface = - e1000e_setup_fiber_serdes_link; - break; - default: - hw->phy.media_type = e1000_media_type_copper; - mac->ops.check_for_link = e1000e_check_for_copper_link; - mac->ops.setup_physical_interface = - e1000_setup_copper_link_80003es2lan; - break; - } - - /* Set mta register count */ - mac->mta_reg_count = 128; - /* Set rar entry count */ - mac->rar_entry_count = E1000_RAR_ENTRIES; - /* FWSM register */ - mac->has_fwsm = true; - /* ARC supported; valid only if manageability features are enabled. */ - mac->arc_subsystem_valid = !!(er32(FWSM) & E1000_FWSM_MODE_MASK); - /* Adaptive IFS not supported */ - mac->adaptive_ifs = false; - - /* set lan id for port to determine which phy lock to use */ - hw->mac.ops.set_lan_id(hw); - - return 0; -} - -static s32 e1000_get_variants_80003es2lan(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - s32 rc; - - rc = e1000_init_mac_params_80003es2lan(hw); - if (rc) - return rc; - - rc = e1000_init_nvm_params_80003es2lan(hw); - if (rc) - return rc; - - rc = e1000_init_phy_params_80003es2lan(hw); - if (rc) - return rc; - - return 0; -} - -/** - * e1000_acquire_phy_80003es2lan - Acquire rights to access PHY - * @hw: pointer to the HW structure - * - * A wrapper to acquire access rights to the correct PHY. - **/ -static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw) -{ - u16 mask; - - mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; - return e1000_acquire_swfw_sync_80003es2lan(hw, mask); -} - -/** - * e1000_release_phy_80003es2lan - Release rights to access PHY - * @hw: pointer to the HW structure - * - * A wrapper to release access rights to the correct PHY. - **/ -static void e1000_release_phy_80003es2lan(struct e1000_hw *hw) -{ - u16 mask; - - mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM; - e1000_release_swfw_sync_80003es2lan(hw, mask); -} - -/** - * e1000_acquire_mac_csr_80003es2lan - Acquire right to access Kumeran register - * @hw: pointer to the HW structure - * - * Acquire the semaphore to access the Kumeran interface. - * - **/ -static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw) -{ - u16 mask; - - mask = E1000_SWFW_CSR_SM; - - return e1000_acquire_swfw_sync_80003es2lan(hw, mask); -} - -/** - * e1000_release_mac_csr_80003es2lan - Release right to access Kumeran Register - * @hw: pointer to the HW structure - * - * Release the semaphore used to access the Kumeran interface - **/ -static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw) -{ - u16 mask; - - mask = E1000_SWFW_CSR_SM; - - e1000_release_swfw_sync_80003es2lan(hw, mask); -} - -/** - * e1000_acquire_nvm_80003es2lan - Acquire rights to access NVM - * @hw: pointer to the HW structure - * - * Acquire the semaphore to access the EEPROM. - **/ -static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val; - - ret_val = e1000_acquire_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); - if (ret_val) - return ret_val; - - ret_val = e1000e_acquire_nvm(hw); - - if (ret_val) - e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); - - return ret_val; -} - -/** - * e1000_release_nvm_80003es2lan - Relinquish rights to access NVM - * @hw: pointer to the HW structure - * - * Release the semaphore used to access the EEPROM. - **/ -static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw) -{ - e1000e_release_nvm(hw); - e1000_release_swfw_sync_80003es2lan(hw, E1000_SWFW_EEP_SM); -} - -/** - * e1000_acquire_swfw_sync_80003es2lan - Acquire SW/FW semaphore - * @hw: pointer to the HW structure - * @mask: specifies which semaphore to acquire - * - * Acquire the SW/FW semaphore to access the PHY or NVM. The mask - * will also specify which port we're acquiring the lock for. - **/ -static s32 e1000_acquire_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) -{ - u32 swfw_sync; - u32 swmask = mask; - u32 fwmask = mask << 16; - s32 i = 0; - s32 timeout = 50; - - while (i < timeout) { - if (e1000e_get_hw_semaphore(hw)) - return -E1000_ERR_SWFW_SYNC; - - swfw_sync = er32(SW_FW_SYNC); - if (!(swfw_sync & (fwmask | swmask))) - break; - - /* Firmware currently using resource (fwmask) - * or other software thread using resource (swmask) - */ - e1000e_put_hw_semaphore(hw); - mdelay(5); - i++; - } - - if (i == timeout) { - e_dbg("Driver can't access resource, SW_FW_SYNC timeout.\n"); - return -E1000_ERR_SWFW_SYNC; - } - - swfw_sync |= swmask; - ew32(SW_FW_SYNC, swfw_sync); - - e1000e_put_hw_semaphore(hw); - - return 0; -} - -/** - * e1000_release_swfw_sync_80003es2lan - Release SW/FW semaphore - * @hw: pointer to the HW structure - * @mask: specifies which semaphore to acquire - * - * Release the SW/FW semaphore used to access the PHY or NVM. The mask - * will also specify which port we're releasing the lock for. - **/ -static void e1000_release_swfw_sync_80003es2lan(struct e1000_hw *hw, u16 mask) -{ - u32 swfw_sync; - - while (e1000e_get_hw_semaphore(hw) != 0) - ; /* Empty */ - - swfw_sync = er32(SW_FW_SYNC); - swfw_sync &= ~mask; - ew32(SW_FW_SYNC, swfw_sync); - - e1000e_put_hw_semaphore(hw); -} - -/** - * e1000_read_phy_reg_gg82563_80003es2lan - Read GG82563 PHY register - * @hw: pointer to the HW structure - * @offset: offset of the register to read - * @data: pointer to the data returned from the operation - * - * Read the GG82563 PHY register. - **/ -static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, - u32 offset, u16 *data) -{ - s32 ret_val; - u32 page_select; - u16 temp; - - ret_val = e1000_acquire_phy_80003es2lan(hw); - if (ret_val) - return ret_val; - - /* Select Configuration Page */ - if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { - page_select = GG82563_PHY_PAGE_SELECT; - } else { - /* Use Alternative Page Select register to access - * registers 30 and 31 - */ - page_select = GG82563_PHY_PAGE_SELECT_ALT; - } - - temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); - ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp); - if (ret_val) { - e1000_release_phy_80003es2lan(hw); - return ret_val; - } - - if (hw->dev_spec.e80003es2lan.mdic_wa_enable) { - /* The "ready" bit in the MDIC register may be incorrectly set - * before the device has completed the "Page Select" MDI - * transaction. So we wait 200us after each MDI command... - */ - usleep_range(200, 400); - - /* ...and verify the command was successful. */ - ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); - - if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { - e1000_release_phy_80003es2lan(hw); - return -E1000_ERR_PHY; - } - - usleep_range(200, 400); - - ret_val = e1000e_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - - usleep_range(200, 400); - } else { - ret_val = e1000e_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - } - - e1000_release_phy_80003es2lan(hw); - - return ret_val; -} - -/** - * e1000_write_phy_reg_gg82563_80003es2lan - Write GG82563 PHY register - * @hw: pointer to the HW structure - * @offset: offset of the register to read - * @data: value to write to the register - * - * Write to the GG82563 PHY register. - **/ -static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw, - u32 offset, u16 data) -{ - s32 ret_val; - u32 page_select; - u16 temp; - - ret_val = e1000_acquire_phy_80003es2lan(hw); - if (ret_val) - return ret_val; - - /* Select Configuration Page */ - if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) { - page_select = GG82563_PHY_PAGE_SELECT; - } else { - /* Use Alternative Page Select register to access - * registers 30 and 31 - */ - page_select = GG82563_PHY_PAGE_SELECT_ALT; - } - - temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT); - ret_val = e1000e_write_phy_reg_mdic(hw, page_select, temp); - if (ret_val) { - e1000_release_phy_80003es2lan(hw); - return ret_val; - } - - if (hw->dev_spec.e80003es2lan.mdic_wa_enable) { - /* The "ready" bit in the MDIC register may be incorrectly set - * before the device has completed the "Page Select" MDI - * transaction. So we wait 200us after each MDI command... - */ - usleep_range(200, 400); - - /* ...and verify the command was successful. */ - ret_val = e1000e_read_phy_reg_mdic(hw, page_select, &temp); - - if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) { - e1000_release_phy_80003es2lan(hw); - return -E1000_ERR_PHY; - } - - usleep_range(200, 400); - - ret_val = e1000e_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & - offset, data); - - usleep_range(200, 400); - } else { - ret_val = e1000e_write_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & - offset, data); - } - - e1000_release_phy_80003es2lan(hw); - - return ret_val; -} - -/** - * e1000_write_nvm_80003es2lan - Write to ESB2 NVM - * @hw: pointer to the HW structure - * @offset: offset of the register to read - * @words: number of words to write - * @data: buffer of data to write to the NVM - * - * Write "words" of data to the ESB2 NVM. - **/ -static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data) -{ - return e1000e_write_nvm_spi(hw, offset, words, data); -} - -/** - * e1000_get_cfg_done_80003es2lan - Wait for configuration to complete - * @hw: pointer to the HW structure - * - * Wait a specific amount of time for manageability processes to complete. - * This is a function pointer entry point called by the phy module. - **/ -static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw) -{ - s32 timeout = PHY_CFG_TIMEOUT; - u32 mask = E1000_NVM_CFG_DONE_PORT_0; - - if (hw->bus.func == 1) - mask = E1000_NVM_CFG_DONE_PORT_1; - - while (timeout) { - if (er32(EEMNGCTL) & mask) - break; - usleep_range(1000, 2000); - timeout--; - } - if (!timeout) { - e_dbg("MNG configuration cycle has not completed.\n"); - return -E1000_ERR_RESET; - } - - return 0; -} - -/** - * e1000_phy_force_speed_duplex_80003es2lan - Force PHY speed and duplex - * @hw: pointer to the HW structure - * - * Force the speed and duplex settings onto the PHY. This is a - * function pointer entry point called by the phy module. - **/ -static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - bool link; - - /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO; - ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - e_dbg("GG82563 PSCR: %X\n", phy_data); - - ret_val = e1e_rphy(hw, MII_BMCR, &phy_data); - if (ret_val) - return ret_val; - - e1000e_phy_force_speed_duplex_setup(hw, &phy_data); - - /* Reset the phy to commit changes. */ - phy_data |= BMCR_RESET; - - ret_val = e1e_wphy(hw, MII_BMCR, phy_data); - if (ret_val) - return ret_val; - - udelay(1); - - if (hw->phy.autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on GG82563 phy.\n"); - - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - - if (!link) { - /* We didn't get link. - * Reset the DSP and cross our fingers. - */ - ret_val = e1000e_phy_reset_dsp(hw); - if (ret_val) - return ret_val; - } - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - } - - ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - /* Resetting the phy means we need to verify the TX_CLK corresponds - * to the link speed. 10Mbps -> 2.5MHz, else 25MHz. - */ - phy_data &= ~GG82563_MSCR_TX_CLK_MASK; - if (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED) - phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5; - else - phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25; - - /* In addition, we must re-enable CRS on Tx for both half and full - * duplex. - */ - phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX; - ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, phy_data); - - return ret_val; -} - -/** - * e1000_get_cable_length_80003es2lan - Set approximate cable length - * @hw: pointer to the HW structure - * - * Find the approximate cable length as measured by the GG82563 PHY. - * This is a function pointer entry point called by the phy module. - **/ -static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, index; - - ret_val = e1e_rphy(hw, GG82563_PHY_DSP_DISTANCE, &phy_data); - if (ret_val) - return ret_val; - - index = phy_data & GG82563_DSPD_CABLE_LENGTH; - - if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5) - return -E1000_ERR_PHY; - - phy->min_cable_length = e1000_gg82563_cable_length_table[index]; - phy->max_cable_length = e1000_gg82563_cable_length_table[index + 5]; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - - return 0; -} - -/** - * e1000_get_link_up_info_80003es2lan - Report speed and duplex - * @hw: pointer to the HW structure - * @speed: pointer to speed buffer - * @duplex: pointer to duplex buffer - * - * Retrieve the current speed and duplex configuration. - **/ -static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed, - u16 *duplex) -{ - s32 ret_val; - - if (hw->phy.media_type == e1000_media_type_copper) { - ret_val = e1000e_get_speed_and_duplex_copper(hw, speed, duplex); - hw->phy.ops.cfg_on_link_up(hw); - } else { - ret_val = e1000e_get_speed_and_duplex_fiber_serdes(hw, - speed, - duplex); - } - - return ret_val; -} - -/** - * e1000_reset_hw_80003es2lan - Reset the ESB2 controller - * @hw: pointer to the HW structure - * - * Perform a global reset to the ESB2 controller. - **/ -static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 kum_reg_data; - - /* Prevent the PCI-E bus from sticking if there is no TLP connection - * on the last TLP read/write transaction when MAC is reset. - */ - ret_val = e1000e_disable_pcie_master(hw); - if (ret_val) - e_dbg("PCI-E Master disable polling has failed.\n"); - - e_dbg("Masking off all interrupts\n"); - ew32(IMC, 0xffffffff); - - ew32(RCTL, 0); - ew32(TCTL, E1000_TCTL_PSP); - e1e_flush(); - - usleep_range(10000, 20000); - - ctrl = er32(CTRL); - - ret_val = e1000_acquire_phy_80003es2lan(hw); - if (ret_val) - return ret_val; - - e_dbg("Issuing a global reset to MAC\n"); - ew32(CTRL, ctrl | E1000_CTRL_RST); - e1000_release_phy_80003es2lan(hw); - - /* Disable IBIST slave mode (far-end loopback) */ - ret_val = - e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - &kum_reg_data); - if (ret_val) - return ret_val; - kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; - e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - kum_reg_data); - - ret_val = e1000e_get_auto_rd_done(hw); - if (ret_val) - /* We don't want to continue accessing MAC registers. */ - return ret_val; - - /* Clear any pending interrupt events. */ - ew32(IMC, 0xffffffff); - er32(ICR); - - return e1000_check_alt_mac_addr_generic(hw); -} - -/** - * e1000_init_hw_80003es2lan - Initialize the ESB2 controller - * @hw: pointer to the HW structure - * - * Initialize the hw bits, LED, VFTA, MTA, link and hw counters. - **/ -static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 reg_data; - s32 ret_val; - u16 kum_reg_data; - u16 i; - - e1000_initialize_hw_bits_80003es2lan(hw); - - /* Initialize identification LED */ - ret_val = mac->ops.id_led_init(hw); - /* An error is not fatal and we should not stop init due to this */ - if (ret_val) - e_dbg("Error initializing identification LED\n"); - - /* Disabling VLAN filtering */ - e_dbg("Initializing the IEEE VLAN\n"); - mac->ops.clear_vfta(hw); - - /* Setup the receive address. */ - e1000e_init_rx_addrs(hw, mac->rar_entry_count); - - /* Zero out the Multicast HASH table */ - e_dbg("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - - /* Setup link and flow control */ - ret_val = mac->ops.setup_link(hw); - if (ret_val) - return ret_val; - - /* Disable IBIST slave mode (far-end loopback) */ - e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - &kum_reg_data); - kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE; - e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - kum_reg_data); - - /* Set the transmit descriptor write-back policy */ - reg_data = er32(TXDCTL(0)); - reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC); - ew32(TXDCTL(0), reg_data); - - /* ...for both queues. */ - reg_data = er32(TXDCTL(1)); - reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC); - ew32(TXDCTL(1), reg_data); - - /* Enable retransmit on late collisions */ - reg_data = er32(TCTL); - reg_data |= E1000_TCTL_RTLC; - ew32(TCTL, reg_data); - - /* Configure Gigabit Carry Extend Padding */ - reg_data = er32(TCTL_EXT); - reg_data &= ~E1000_TCTL_EXT_GCEX_MASK; - reg_data |= DEFAULT_TCTL_EXT_GCEX_80003ES2LAN; - ew32(TCTL_EXT, reg_data); - - /* Configure Transmit Inter-Packet Gap */ - reg_data = er32(TIPG); - reg_data &= ~E1000_TIPG_IPGT_MASK; - reg_data |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; - ew32(TIPG, reg_data); - - reg_data = E1000_READ_REG_ARRAY(hw, E1000_FFLT, 0x0001); - reg_data &= ~0x00100000; - E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data); - - /* default to true to enable the MDIC W/A */ - hw->dev_spec.e80003es2lan.mdic_wa_enable = true; - - ret_val = - e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET >> - E1000_KMRNCTRLSTA_OFFSET_SHIFT, &i); - if (!ret_val) { - if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) == - E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO) - hw->dev_spec.e80003es2lan.mdic_wa_enable = false; - } - - /* Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs_80003es2lan(hw); - - return ret_val; -} - -/** - * e1000_initialize_hw_bits_80003es2lan - Init hw bits of ESB2 - * @hw: pointer to the HW structure - * - * Initializes required hardware-dependent bits needed for normal operation. - **/ -static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw) -{ - u32 reg; - - /* Transmit Descriptor Control 0 */ - reg = er32(TXDCTL(0)); - reg |= (1 << 22); - ew32(TXDCTL(0), reg); - - /* Transmit Descriptor Control 1 */ - reg = er32(TXDCTL(1)); - reg |= (1 << 22); - ew32(TXDCTL(1), reg); - - /* Transmit Arbitration Control 0 */ - reg = er32(TARC(0)); - reg &= ~(0xF << 27); /* 30:27 */ - if (hw->phy.media_type != e1000_media_type_copper) - reg &= ~(1 << 20); - ew32(TARC(0), reg); - - /* Transmit Arbitration Control 1 */ - reg = er32(TARC(1)); - if (er32(TCTL) & E1000_TCTL_MULR) - reg &= ~(1 << 28); - else - reg |= (1 << 28); - ew32(TARC(1), reg); - - /* Disable IPv6 extension header parsing because some malformed - * IPv6 headers can hang the Rx. - */ - reg = er32(RFCTL); - reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); - ew32(RFCTL, reg); -} - -/** - * e1000_copper_link_setup_gg82563_80003es2lan - Configure GG82563 Link - * @hw: pointer to the HW structure - * - * Setup some GG82563 PHY registers for obtaining link - **/ -static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u32 reg; - u16 data; - - ret_val = e1e_rphy(hw, GG82563_PHY_MAC_SPEC_CTRL, &data); - if (ret_val) - return ret_val; - - data |= GG82563_MSCR_ASSERT_CRS_ON_TX; - /* Use 25MHz for both link down and 1000Base-T for Tx clock. */ - data |= GG82563_MSCR_TX_CLK_1000MBPS_25; - - ret_val = e1e_wphy(hw, GG82563_PHY_MAC_SPEC_CTRL, data); - if (ret_val) - return ret_val; - - /* Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL, &data); - if (ret_val) - return ret_val; - - data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK; - - switch (phy->mdix) { - case 1: - data |= GG82563_PSCR_CROSSOVER_MODE_MDI; - break; - case 2: - data |= GG82563_PSCR_CROSSOVER_MODE_MDIX; - break; - case 0: - default: - data |= GG82563_PSCR_CROSSOVER_MODE_AUTO; - break; - } - - /* Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE; - if (phy->disable_polarity_correction) - data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE; - - ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL, data); - if (ret_val) - return ret_val; - - /* SW Reset the PHY so all changes take effect */ - ret_val = hw->phy.ops.commit(hw); - if (ret_val) { - e_dbg("Error Resetting the PHY\n"); - return ret_val; - } - - /* Bypass Rx and Tx FIFO's */ - reg = E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL; - data = (E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS | - E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS); - ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data); - if (ret_val) - return ret_val; - - reg = E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE; - ret_val = e1000_read_kmrn_reg_80003es2lan(hw, reg, &data); - if (ret_val) - return ret_val; - data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE; - ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, GG82563_PHY_SPEC_CTRL_2, &data); - if (ret_val) - return ret_val; - - data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG; - ret_val = e1e_wphy(hw, GG82563_PHY_SPEC_CTRL_2, data); - if (ret_val) - return ret_val; - - reg = er32(CTRL_EXT); - reg &= ~E1000_CTRL_EXT_LINK_MODE_MASK; - ew32(CTRL_EXT, reg); - - ret_val = e1e_rphy(hw, GG82563_PHY_PWR_MGMT_CTRL, &data); - if (ret_val) - return ret_val; - - /* Do not init these registers when the HW is in IAMT mode, since the - * firmware will have already initialized them. We only initialize - * them if the HW is not in IAMT mode. - */ - if (!hw->mac.ops.check_mng_mode(hw)) { - /* Enable Electrical Idle on the PHY */ - data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE; - ret_val = e1e_wphy(hw, GG82563_PHY_PWR_MGMT_CTRL, data); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, &data); - if (ret_val) - return ret_val; - - data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; - ret_val = e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, data); - if (ret_val) - return ret_val; - } - - /* Workaround: Disable padding in Kumeran interface in the MAC - * and in the PHY to avoid CRC errors. - */ - ret_val = e1e_rphy(hw, GG82563_PHY_INBAND_CTRL, &data); - if (ret_val) - return ret_val; - - data |= GG82563_ICR_DIS_PADDING; - ret_val = e1e_wphy(hw, GG82563_PHY_INBAND_CTRL, data); - if (ret_val) - return ret_val; - - return 0; -} - -/** - * e1000_setup_copper_link_80003es2lan - Setup Copper Link for ESB2 - * @hw: pointer to the HW structure - * - * Essentially a wrapper for setting up all things "copper" related. - * This is a function pointer entry point called by the mac module. - **/ -static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 reg_data; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ew32(CTRL, ctrl); - - /* Set the mac to wait the maximum time between each - * iteration and increase the max iterations when - * polling the phy; this fixes erroneous timeouts at 10Mbps. - */ - ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4), - 0xFFFF); - if (ret_val) - return ret_val; - ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), - ®_data); - if (ret_val) - return ret_val; - reg_data |= 0x3F; - ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9), - reg_data); - if (ret_val) - return ret_val; - ret_val = - e1000_read_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, - ®_data); - if (ret_val) - return ret_val; - reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING; - ret_val = - e1000_write_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_INB_CTRL, - reg_data); - if (ret_val) - return ret_val; - - ret_val = e1000_copper_link_setup_gg82563_80003es2lan(hw); - if (ret_val) - return ret_val; - - return e1000e_setup_copper_link(hw); -} - -/** - * e1000_cfg_on_link_up_80003es2lan - es2 link configuration after link-up - * @hw: pointer to the HW structure - * @duplex: current duplex setting - * - * Configure the KMRN interface by applying last minute quirks for - * 10/100 operation. - **/ -static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u16 speed; - u16 duplex; - - if (hw->phy.media_type == e1000_media_type_copper) { - ret_val = e1000e_get_speed_and_duplex_copper(hw, &speed, - &duplex); - if (ret_val) - return ret_val; - - if (speed == SPEED_1000) - ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw); - else - ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, duplex); - } - - return ret_val; -} - -/** - * e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation - * @hw: pointer to the HW structure - * @duplex: current duplex setting - * - * Configure the KMRN interface by applying last minute quirks for - * 10/100 operation. - **/ -static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex) -{ - s32 ret_val; - u32 tipg; - u32 i = 0; - u16 reg_data, reg_data2; - - reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT; - ret_val = - e1000_write_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, - reg_data); - if (ret_val) - return ret_val; - - /* Configure Transmit Inter-Packet Gap */ - tipg = er32(TIPG); - tipg &= ~E1000_TIPG_IPGT_MASK; - tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN; - ew32(TIPG, tipg); - - do { - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data2); - if (ret_val) - return ret_val; - i++; - } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); - - if (duplex == HALF_DUPLEX) - reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER; - else - reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; - - return e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); -} - -/** - * e1000_cfg_kmrn_1000_80003es2lan - Apply "quirks" for gigabit operation - * @hw: pointer to the HW structure - * - * Configure the KMRN interface by applying last minute quirks for - * gigabit operation. - **/ -static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val; - u16 reg_data, reg_data2; - u32 tipg; - u32 i = 0; - - reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT; - ret_val = - e1000_write_kmrn_reg_80003es2lan(hw, - E1000_KMRNCTRLSTA_OFFSET_HD_CTRL, - reg_data); - if (ret_val) - return ret_val; - - /* Configure Transmit Inter-Packet Gap */ - tipg = er32(TIPG); - tipg &= ~E1000_TIPG_IPGT_MASK; - tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN; - ew32(TIPG, tipg); - - do { - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, GG82563_PHY_KMRN_MODE_CTRL, ®_data2); - if (ret_val) - return ret_val; - i++; - } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY)); - - reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER; - - return e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data); -} - -/** - * e1000_read_kmrn_reg_80003es2lan - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquire semaphore, then read the PHY register at offset - * using the kumeran interface. The information retrieved is stored in data. - * Release the semaphore before exiting. - **/ -static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, - u16 *data) -{ - u32 kmrnctrlsta; - s32 ret_val; - - ret_val = e1000_acquire_mac_csr_80003es2lan(hw); - if (ret_val) - return ret_val; - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; - ew32(KMRNCTRLSTA, kmrnctrlsta); - e1e_flush(); - - udelay(2); - - kmrnctrlsta = er32(KMRNCTRLSTA); - *data = (u16)kmrnctrlsta; - - e1000_release_mac_csr_80003es2lan(hw); - - return ret_val; -} - -/** - * e1000_write_kmrn_reg_80003es2lan - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquire semaphore, then write the data to PHY register - * at the offset using the kumeran interface. Release semaphore - * before exiting. - **/ -static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset, - u16 data) -{ - u32 kmrnctrlsta; - s32 ret_val; - - ret_val = e1000_acquire_mac_csr_80003es2lan(hw); - if (ret_val) - return ret_val; - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | data; - ew32(KMRNCTRLSTA, kmrnctrlsta); - e1e_flush(); - - udelay(2); - - e1000_release_mac_csr_80003es2lan(hw); - - return ret_val; -} - -/** - * e1000_read_mac_addr_80003es2lan - Read device MAC address - * @hw: pointer to the HW structure - **/ -static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw) -{ - s32 ret_val; - - /* If there's an alternate MAC address place it in RAR0 - * so that it will override the Si installed default perm - * address. - */ - ret_val = e1000_check_alt_mac_addr_generic(hw); - if (ret_val) - return ret_val; - - return e1000_read_mac_addr_generic(hw); -} - -/** - * e1000_power_down_phy_copper_80003es2lan - Remove link during PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, remove the link. - **/ -static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw) -{ - /* If the management interface is not enabled, then power down */ - if (!(hw->mac.ops.check_mng_mode(hw) || - hw->phy.ops.check_reset_block(hw))) - e1000_power_down_phy_copper(hw); -} - -/** - * e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters - * @hw: pointer to the HW structure - * - * Clears the hardware counters by reading the counter registers. - **/ -static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw) -{ - e1000e_clear_hw_cntrs_base(hw); - - er32(PRC64); - er32(PRC127); - er32(PRC255); - er32(PRC511); - er32(PRC1023); - er32(PRC1522); - er32(PTC64); - er32(PTC127); - er32(PTC255); - er32(PTC511); - er32(PTC1023); - er32(PTC1522); - - er32(ALGNERRC); - er32(RXERRC); - er32(TNCRS); - er32(CEXTERR); - er32(TSCTC); - er32(TSCTFC); - - er32(MGTPRC); - er32(MGTPDC); - er32(MGTPTC); - - er32(IAC); - er32(ICRXOC); - - er32(ICRXPTC); - er32(ICRXATC); - er32(ICTXPTC); - er32(ICTXATC); - er32(ICTXQEC); - er32(ICTXQMTC); - er32(ICRXDMTC); -} - -static const struct e1000_mac_operations es2_mac_ops = { - .read_mac_addr = e1000_read_mac_addr_80003es2lan, - .id_led_init = e1000e_id_led_init_generic, - .blink_led = e1000e_blink_led_generic, - .check_mng_mode = e1000e_check_mng_mode_generic, - /* check_for_link dependent on media type */ - .cleanup_led = e1000e_cleanup_led_generic, - .clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan, - .get_bus_info = e1000e_get_bus_info_pcie, - .set_lan_id = e1000_set_lan_id_multi_port_pcie, - .get_link_up_info = e1000_get_link_up_info_80003es2lan, - .led_on = e1000e_led_on_generic, - .led_off = e1000e_led_off_generic, - .update_mc_addr_list = e1000e_update_mc_addr_list_generic, - .write_vfta = e1000_write_vfta_generic, - .clear_vfta = e1000_clear_vfta_generic, - .reset_hw = e1000_reset_hw_80003es2lan, - .init_hw = e1000_init_hw_80003es2lan, - .setup_link = e1000e_setup_link_generic, - /* setup_physical_interface dependent on media type */ - .setup_led = e1000e_setup_led_generic, - .config_collision_dist = e1000e_config_collision_dist_generic, - .rar_set = e1000e_rar_set_generic, - .rar_get_count = e1000e_rar_get_count_generic, -}; - -static const struct e1000_phy_operations es2_phy_ops = { - .acquire = e1000_acquire_phy_80003es2lan, - .check_polarity = e1000_check_polarity_m88, - .check_reset_block = e1000e_check_reset_block_generic, - .commit = e1000e_phy_sw_reset, - .force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan, - .get_cfg_done = e1000_get_cfg_done_80003es2lan, - .get_cable_length = e1000_get_cable_length_80003es2lan, - .get_info = e1000e_get_phy_info_m88, - .read_reg = e1000_read_phy_reg_gg82563_80003es2lan, - .release = e1000_release_phy_80003es2lan, - .reset = e1000e_phy_hw_reset_generic, - .set_d0_lplu_state = NULL, - .set_d3_lplu_state = e1000e_set_d3_lplu_state, - .write_reg = e1000_write_phy_reg_gg82563_80003es2lan, - .cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan, -}; - -static const struct e1000_nvm_operations es2_nvm_ops = { - .acquire = e1000_acquire_nvm_80003es2lan, - .read = e1000e_read_nvm_eerd, - .release = e1000_release_nvm_80003es2lan, - .reload = e1000e_reload_nvm_generic, - .update = e1000e_update_nvm_checksum_generic, - .valid_led_default = e1000e_valid_led_default, - .validate = e1000e_validate_nvm_checksum_generic, - .write = e1000_write_nvm_80003es2lan, -}; - -const struct e1000_info e1000_es2_info = { - .mac = e1000_80003es2lan, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_RX_NEEDS_RESTART /* errata */ - | FLAG_TARC_SET_BIT_ZERO /* errata */ - | FLAG_APME_CHECK_PORT_B - | FLAG_DISABLE_FC_PAUSE_TIME, /* errata */ - .flags2 = FLAG2_DMA_BURST, - .pba = 38, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_80003es2lan, - .mac_ops = &es2_mac_ops, - .phy_ops = &es2_phy_ops, - .nvm_ops = &es2_nvm_ops, -}; diff --git a/addons/e1000e/src/4.4.180/80003es2lan.h b/addons/e1000e/src/4.4.180/80003es2lan.h deleted file mode 100644 index a2162e11..00000000 --- a/addons/e1000e/src/4.4.180/80003es2lan.h +++ /dev/null @@ -1,88 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#ifndef _E1000E_80003ES2LAN_H_ -#define _E1000E_80003ES2LAN_H_ - -#define E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL 0x00 -#define E1000_KMRNCTRLSTA_OFFSET_INB_CTRL 0x02 -#define E1000_KMRNCTRLSTA_OFFSET_HD_CTRL 0x10 -#define E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE 0x1F - -#define E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS 0x0008 -#define E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS 0x0800 -#define E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING 0x0010 - -#define E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT 0x0004 -#define E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT 0x0000 -#define E1000_KMRNCTRLSTA_OPMODE_E_IDLE 0x2000 - -#define E1000_KMRNCTRLSTA_OPMODE_MASK 0x000C -#define E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO 0x0004 - -#define E1000_TCTL_EXT_GCEX_MASK 0x000FFC00 /* Gig Carry Extend Padding */ -#define DEFAULT_TCTL_EXT_GCEX_80003ES2LAN 0x00010000 - -#define DEFAULT_TIPG_IPGT_1000_80003ES2LAN 0x8 -#define DEFAULT_TIPG_IPGT_10_100_80003ES2LAN 0x9 - -/* GG82563 PHY Specific Status Register (Page 0, Register 16 */ -#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE 0x0002 /* 1=Reversal Dis */ -#define GG82563_PSCR_CROSSOVER_MODE_MASK 0x0060 -#define GG82563_PSCR_CROSSOVER_MODE_MDI 0x0000 /* 00=Manual MDI */ -#define GG82563_PSCR_CROSSOVER_MODE_MDIX 0x0020 /* 01=Manual MDIX */ -#define GG82563_PSCR_CROSSOVER_MODE_AUTO 0x0060 /* 11=Auto crossover */ - -/* PHY Specific Control Register 2 (Page 0, Register 26) */ -#define GG82563_PSCR2_REVERSE_AUTO_NEG 0x2000 /* 1=Reverse Auto-Neg */ - -/* MAC Specific Control Register (Page 2, Register 21) */ -/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */ -#define GG82563_MSCR_TX_CLK_MASK 0x0007 -#define GG82563_MSCR_TX_CLK_10MBPS_2_5 0x0004 -#define GG82563_MSCR_TX_CLK_100MBPS_25 0x0005 -#define GG82563_MSCR_TX_CLK_1000MBPS_25 0x0007 - -#define GG82563_MSCR_ASSERT_CRS_ON_TX 0x0010 /* 1=Assert */ - -/* DSP Distance Register (Page 5, Register 26) - * 0 = <50M - * 1 = 50-80M - * 2 = 80-100M - * 3 = 110-140M - * 4 = >140M - */ -#define GG82563_DSPD_CABLE_LENGTH 0x0007 - -/* Kumeran Mode Control Register (Page 193, Register 16) */ -#define GG82563_KMCR_PASS_FALSE_CARRIER 0x0800 - -/* Max number of times Kumeran read/write should be validated */ -#define GG82563_MAX_KMRN_RETRY 0x5 - -/* Power Management Control Register (Page 193, Register 20) */ -/* 1=Enable SERDES Electrical Idle */ -#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE 0x0001 - -/* In-Band Control Register (Page 194, Register 18) */ -#define GG82563_ICR_DIS_PADDING 0x0010 /* Disable Padding */ - -#endif diff --git a/addons/e1000e/src/4.4.180/82571.c b/addons/e1000e/src/4.4.180/82571.c deleted file mode 100644 index 5f701644..00000000 --- a/addons/e1000e/src/4.4.180/82571.c +++ /dev/null @@ -1,2063 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -/* 82571EB Gigabit Ethernet Controller - * 82571EB Gigabit Ethernet Controller (Copper) - * 82571EB Gigabit Ethernet Controller (Fiber) - * 82571EB Dual Port Gigabit Mezzanine Adapter - * 82571EB Quad Port Gigabit Mezzanine Adapter - * 82571PT Gigabit PT Quad Port Server ExpressModule - * 82572EI Gigabit Ethernet Controller (Copper) - * 82572EI Gigabit Ethernet Controller (Fiber) - * 82572EI Gigabit Ethernet Controller - * 82573V Gigabit Ethernet Controller (Copper) - * 82573E Gigabit Ethernet Controller (Copper) - * 82573L Gigabit Ethernet Controller - * 82574L Gigabit Network Connection - * 82583V Gigabit Network Connection - */ - -#include "e1000.h" - -static s32 e1000_get_phy_id_82571(struct e1000_hw *hw); -static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw); -static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw); -static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw); -static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data); -static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw); -static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw); -static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw); -static bool e1000_check_mng_mode_82574(struct e1000_hw *hw); -static s32 e1000_led_on_82574(struct e1000_hw *hw); -static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw); -static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw); -static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw); -static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw); -static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw); -static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active); -static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active); - -/** - * e1000_init_phy_params_82571 - Init PHY func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_phy_params_82571(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - - if (hw->phy.media_type != e1000_media_type_copper) { - phy->type = e1000_phy_none; - return 0; - } - - phy->addr = 1; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->reset_delay_us = 100; - - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_82571; - - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - phy->type = e1000_phy_igp_2; - break; - case e1000_82573: - phy->type = e1000_phy_m88; - break; - case e1000_82574: - case e1000_82583: - phy->type = e1000_phy_bm; - phy->ops.acquire = e1000_get_hw_semaphore_82574; - phy->ops.release = e1000_put_hw_semaphore_82574; - phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82574; - phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82574; - break; - default: - return -E1000_ERR_PHY; - } - - /* This can only be done after all function pointers are setup. */ - ret_val = e1000_get_phy_id_82571(hw); - if (ret_val) { - e_dbg("Error getting PHY ID\n"); - return ret_val; - } - - /* Verify phy id */ - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - if (phy->id != IGP01E1000_I_PHY_ID) - ret_val = -E1000_ERR_PHY; - break; - case e1000_82573: - if (phy->id != M88E1111_I_PHY_ID) - ret_val = -E1000_ERR_PHY; - break; - case e1000_82574: - case e1000_82583: - if (phy->id != BME1000_E_PHY_ID_R2) - ret_val = -E1000_ERR_PHY; - break; - default: - ret_val = -E1000_ERR_PHY; - break; - } - - if (ret_val) - e_dbg("PHY ID unknown: type = 0x%08x\n", phy->id); - - return ret_val; -} - -/** - * e1000_init_nvm_params_82571 - Init NVM func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - u16 size; - - nvm->opcode_bits = 8; - nvm->delay_usec = 1; - switch (nvm->override) { - case e1000_nvm_override_spi_large: - nvm->page_size = 32; - nvm->address_bits = 16; - break; - case e1000_nvm_override_spi_small: - nvm->page_size = 8; - nvm->address_bits = 8; - break; - default: - nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; - nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; - break; - } - - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - if (((eecd >> 15) & 0x3) == 0x3) { - nvm->type = e1000_nvm_flash_hw; - nvm->word_size = 2048; - /* Autonomous Flash update bit must be cleared due - * to Flash update issue. - */ - eecd &= ~E1000_EECD_AUPDEN; - ew32(EECD, eecd); - break; - } - /* Fall Through */ - default: - nvm->type = e1000_nvm_eeprom_spi; - size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> - E1000_EECD_SIZE_EX_SHIFT); - /* Added to a constant, "size" becomes the left-shift value - * for setting word_size. - */ - size += NVM_WORD_SIZE_BASE_SHIFT; - - /* EEPROM access above 16k is unsupported */ - if (size > 14) - size = 14; - nvm->word_size = 1 << size; - break; - } - - /* Function Pointers */ - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - nvm->ops.acquire = e1000_get_hw_semaphore_82574; - nvm->ops.release = e1000_put_hw_semaphore_82574; - break; - default: - break; - } - - return 0; -} - -/** - * e1000_init_mac_params_82571 - Init MAC func ptrs. - * @hw: pointer to the HW structure - **/ -static s32 e1000_init_mac_params_82571(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 swsm = 0; - u32 swsm2 = 0; - bool force_clear_smbi = false; - - /* Set media type and media-dependent function pointers */ - switch (hw->adapter->pdev->device) { - case E1000_DEV_ID_82571EB_FIBER: - case E1000_DEV_ID_82572EI_FIBER: - case E1000_DEV_ID_82571EB_QUAD_FIBER: - hw->phy.media_type = e1000_media_type_fiber; - mac->ops.setup_physical_interface = - e1000_setup_fiber_serdes_link_82571; - mac->ops.check_for_link = e1000e_check_for_fiber_link; - mac->ops.get_link_up_info = - e1000e_get_speed_and_duplex_fiber_serdes; - break; - case E1000_DEV_ID_82571EB_SERDES: - case E1000_DEV_ID_82571EB_SERDES_DUAL: - case E1000_DEV_ID_82571EB_SERDES_QUAD: - case E1000_DEV_ID_82572EI_SERDES: - hw->phy.media_type = e1000_media_type_internal_serdes; - mac->ops.setup_physical_interface = - e1000_setup_fiber_serdes_link_82571; - mac->ops.check_for_link = e1000_check_for_serdes_link_82571; - mac->ops.get_link_up_info = - e1000e_get_speed_and_duplex_fiber_serdes; - break; - default: - hw->phy.media_type = e1000_media_type_copper; - mac->ops.setup_physical_interface = - e1000_setup_copper_link_82571; - mac->ops.check_for_link = e1000e_check_for_copper_link; - mac->ops.get_link_up_info = e1000e_get_speed_and_duplex_copper; - break; - } - - /* Set mta register count */ - mac->mta_reg_count = 128; - /* Set rar entry count */ - mac->rar_entry_count = E1000_RAR_ENTRIES; - /* Adaptive IFS supported */ - mac->adaptive_ifs = true; - - /* MAC-specific function pointers */ - switch (hw->mac.type) { - case e1000_82573: - mac->ops.set_lan_id = e1000_set_lan_id_single_port; - mac->ops.check_mng_mode = e1000e_check_mng_mode_generic; - mac->ops.led_on = e1000e_led_on_generic; - mac->ops.blink_led = e1000e_blink_led_generic; - - /* FWSM register */ - mac->has_fwsm = true; - /* ARC supported; valid only if manageability features are - * enabled. - */ - mac->arc_subsystem_valid = !!(er32(FWSM) & - E1000_FWSM_MODE_MASK); - break; - case e1000_82574: - case e1000_82583: - mac->ops.set_lan_id = e1000_set_lan_id_single_port; - mac->ops.check_mng_mode = e1000_check_mng_mode_82574; - mac->ops.led_on = e1000_led_on_82574; - break; - default: - mac->ops.check_mng_mode = e1000e_check_mng_mode_generic; - mac->ops.led_on = e1000e_led_on_generic; - mac->ops.blink_led = e1000e_blink_led_generic; - - /* FWSM register */ - mac->has_fwsm = true; - break; - } - - /* Ensure that the inter-port SWSM.SMBI lock bit is clear before - * first NVM or PHY access. This should be done for single-port - * devices, and for one port only on dual-port devices so that - * for those devices we can still use the SMBI lock to synchronize - * inter-port accesses to the PHY & NVM. - */ - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - swsm2 = er32(SWSM2); - - if (!(swsm2 & E1000_SWSM2_LOCK)) { - /* Only do this for the first interface on this card */ - ew32(SWSM2, swsm2 | E1000_SWSM2_LOCK); - force_clear_smbi = true; - } else { - force_clear_smbi = false; - } - break; - default: - force_clear_smbi = true; - break; - } - - if (force_clear_smbi) { - /* Make sure SWSM.SMBI is clear */ - swsm = er32(SWSM); - if (swsm & E1000_SWSM_SMBI) { - /* This bit should not be set on a first interface, and - * indicates that the bootagent or EFI code has - * improperly left this bit enabled - */ - e_dbg("Please update your 82571 Bootagent\n"); - } - ew32(SWSM, swsm & ~E1000_SWSM_SMBI); - } - - /* Initialize device specific counter of SMBI acquisition timeouts. */ - hw->dev_spec.e82571.smb_counter = 0; - - return 0; -} - -static s32 e1000_get_variants_82571(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - static int global_quad_port_a; /* global port a indication */ - struct pci_dev *pdev = adapter->pdev; - int is_port_b = er32(STATUS) & E1000_STATUS_FUNC_1; - s32 rc; - - rc = e1000_init_mac_params_82571(hw); - if (rc) - return rc; - - rc = e1000_init_nvm_params_82571(hw); - if (rc) - return rc; - - rc = e1000_init_phy_params_82571(hw); - if (rc) - return rc; - - /* tag quad port adapters first, it's used below */ - switch (pdev->device) { - case E1000_DEV_ID_82571EB_QUAD_COPPER: - case E1000_DEV_ID_82571EB_QUAD_FIBER: - case E1000_DEV_ID_82571EB_QUAD_COPPER_LP: - case E1000_DEV_ID_82571PT_QUAD_COPPER: - adapter->flags |= FLAG_IS_QUAD_PORT; - /* mark the first port */ - if (global_quad_port_a == 0) - adapter->flags |= FLAG_IS_QUAD_PORT_A; - /* Reset for multiple quad port adapters */ - global_quad_port_a++; - if (global_quad_port_a == 4) - global_quad_port_a = 0; - break; - default: - break; - } - - switch (adapter->hw.mac.type) { - case e1000_82571: - /* these dual ports don't have WoL on port B at all */ - if (((pdev->device == E1000_DEV_ID_82571EB_FIBER) || - (pdev->device == E1000_DEV_ID_82571EB_SERDES) || - (pdev->device == E1000_DEV_ID_82571EB_COPPER)) && - (is_port_b)) - adapter->flags &= ~FLAG_HAS_WOL; - /* quad ports only support WoL on port A */ - if (adapter->flags & FLAG_IS_QUAD_PORT && - (!(adapter->flags & FLAG_IS_QUAD_PORT_A))) - adapter->flags &= ~FLAG_HAS_WOL; - /* Does not support WoL on any port */ - if (pdev->device == E1000_DEV_ID_82571EB_SERDES_QUAD) - adapter->flags &= ~FLAG_HAS_WOL; - break; - case e1000_82573: - if (pdev->device == E1000_DEV_ID_82573L) { - adapter->flags |= FLAG_HAS_JUMBO_FRAMES; - adapter->max_hw_frame_size = DEFAULT_JUMBO; - } - break; - default: - break; - } - - return 0; -} - -/** - * e1000_get_phy_id_82571 - Retrieve the PHY ID and revision - * @hw: pointer to the HW structure - * - * Reads the PHY registers and stores the PHY ID and possibly the PHY - * revision in the hardware structure. - **/ -static s32 e1000_get_phy_id_82571(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_id = 0; - - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - /* The 82571 firmware may still be configuring the PHY. - * In this case, we cannot access the PHY until the - * configuration is done. So we explicitly set the - * PHY ID. - */ - phy->id = IGP01E1000_I_PHY_ID; - break; - case e1000_82573: - return e1000e_get_phy_id(hw); - case e1000_82574: - case e1000_82583: - ret_val = e1e_rphy(hw, MII_PHYSID1, &phy_id); - if (ret_val) - return ret_val; - - phy->id = (u32)(phy_id << 16); - usleep_range(20, 40); - ret_val = e1e_rphy(hw, MII_PHYSID2, &phy_id); - if (ret_val) - return ret_val; - - phy->id |= (u32)(phy_id); - phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); - break; - default: - return -E1000_ERR_PHY; - } - - return 0; -} - -/** - * e1000_get_hw_semaphore_82571 - Acquire hardware semaphore - * @hw: pointer to the HW structure - * - * Acquire the HW semaphore to access the PHY or NVM - **/ -static s32 e1000_get_hw_semaphore_82571(struct e1000_hw *hw) -{ - u32 swsm; - s32 sw_timeout = hw->nvm.word_size + 1; - s32 fw_timeout = hw->nvm.word_size + 1; - s32 i = 0; - - /* If we have timedout 3 times on trying to acquire - * the inter-port SMBI semaphore, there is old code - * operating on the other port, and it is not - * releasing SMBI. Modify the number of times that - * we try for the semaphore to interwork with this - * older code. - */ - if (hw->dev_spec.e82571.smb_counter > 2) - sw_timeout = 1; - - /* Get the SW semaphore */ - while (i < sw_timeout) { - swsm = er32(SWSM); - if (!(swsm & E1000_SWSM_SMBI)) - break; - - usleep_range(50, 100); - i++; - } - - if (i == sw_timeout) { - e_dbg("Driver can't access device - SMBI bit is set.\n"); - hw->dev_spec.e82571.smb_counter++; - } - /* Get the FW semaphore. */ - for (i = 0; i < fw_timeout; i++) { - swsm = er32(SWSM); - ew32(SWSM, swsm | E1000_SWSM_SWESMBI); - - /* Semaphore acquired if bit latched */ - if (er32(SWSM) & E1000_SWSM_SWESMBI) - break; - - usleep_range(50, 100); - } - - if (i == fw_timeout) { - /* Release semaphores */ - e1000_put_hw_semaphore_82571(hw); - e_dbg("Driver can't access the NVM\n"); - return -E1000_ERR_NVM; - } - - return 0; -} - -/** - * e1000_put_hw_semaphore_82571 - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used to access the PHY or NVM - **/ -static void e1000_put_hw_semaphore_82571(struct e1000_hw *hw) -{ - u32 swsm; - - swsm = er32(SWSM); - swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); - ew32(SWSM, swsm); -} - -/** - * e1000_get_hw_semaphore_82573 - Acquire hardware semaphore - * @hw: pointer to the HW structure - * - * Acquire the HW semaphore during reset. - * - **/ -static s32 e1000_get_hw_semaphore_82573(struct e1000_hw *hw) -{ - u32 extcnf_ctrl; - s32 i = 0; - - extcnf_ctrl = er32(EXTCNF_CTRL); - do { - extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; - ew32(EXTCNF_CTRL, extcnf_ctrl); - extcnf_ctrl = er32(EXTCNF_CTRL); - - if (extcnf_ctrl & E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP) - break; - - usleep_range(2000, 4000); - i++; - } while (i < MDIO_OWNERSHIP_TIMEOUT); - - if (i == MDIO_OWNERSHIP_TIMEOUT) { - /* Release semaphores */ - e1000_put_hw_semaphore_82573(hw); - e_dbg("Driver can't access the PHY\n"); - return -E1000_ERR_PHY; - } - - return 0; -} - -/** - * e1000_put_hw_semaphore_82573 - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used during reset. - * - **/ -static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw) -{ - u32 extcnf_ctrl; - - extcnf_ctrl = er32(EXTCNF_CTRL); - extcnf_ctrl &= ~E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP; - ew32(EXTCNF_CTRL, extcnf_ctrl); -} - -static DEFINE_MUTEX(swflag_mutex); - -/** - * e1000_get_hw_semaphore_82574 - Acquire hardware semaphore - * @hw: pointer to the HW structure - * - * Acquire the HW semaphore to access the PHY or NVM. - * - **/ -static s32 e1000_get_hw_semaphore_82574(struct e1000_hw *hw) -{ - s32 ret_val; - - mutex_lock(&swflag_mutex); - ret_val = e1000_get_hw_semaphore_82573(hw); - if (ret_val) - mutex_unlock(&swflag_mutex); - return ret_val; -} - -/** - * e1000_put_hw_semaphore_82574 - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used to access the PHY or NVM - * - **/ -static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw) -{ - e1000_put_hw_semaphore_82573(hw); - mutex_unlock(&swflag_mutex); -} - -/** - * e1000_set_d0_lplu_state_82574 - Set Low Power Linkup D0 state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU D0 state according to the active flag. - * LPLU will not be activated unless the - * device autonegotiation advertisement meets standards of - * either 10 or 10/100 or 10/100/1000 at all duplexes. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active) -{ - u32 data = er32(POEMB); - - if (active) - data |= E1000_PHY_CTRL_D0A_LPLU; - else - data &= ~E1000_PHY_CTRL_D0A_LPLU; - - ew32(POEMB, data); - return 0; -} - -/** - * e1000_set_d3_lplu_state_82574 - Sets low power link up state for D3 - * @hw: pointer to the HW structure - * @active: boolean used to enable/disable lplu - * - * The low power link up (lplu) state is set to the power management level D3 - * when active is true, else clear lplu for D3. LPLU - * is used during Dx states where the power conservation is most important. - * During driver activity, SmartSpeed should be enabled so performance is - * maintained. - **/ -static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active) -{ - u32 data = er32(POEMB); - - if (!active) { - data &= ~E1000_PHY_CTRL_NOND0A_LPLU; - } else if ((hw->phy.autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || - (hw->phy.autoneg_advertised == E1000_ALL_NOT_GIG) || - (hw->phy.autoneg_advertised == E1000_ALL_10_SPEED)) { - data |= E1000_PHY_CTRL_NOND0A_LPLU; - } - - ew32(POEMB, data); - return 0; -} - -/** - * e1000_acquire_nvm_82571 - Request for access to the EEPROM - * @hw: pointer to the HW structure - * - * To gain access to the EEPROM, first we must obtain a hardware semaphore. - * Then for non-82573 hardware, set the EEPROM access request bit and wait - * for EEPROM access grant bit. If the access grant bit is not set, release - * hardware semaphore. - **/ -static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw) -{ - s32 ret_val; - - ret_val = e1000_get_hw_semaphore_82571(hw); - if (ret_val) - return ret_val; - - switch (hw->mac.type) { - case e1000_82573: - break; - default: - ret_val = e1000e_acquire_nvm(hw); - break; - } - - if (ret_val) - e1000_put_hw_semaphore_82571(hw); - - return ret_val; -} - -/** - * e1000_release_nvm_82571 - Release exclusive access to EEPROM - * @hw: pointer to the HW structure - * - * Stop any current commands to the EEPROM and clear the EEPROM request bit. - **/ -static void e1000_release_nvm_82571(struct e1000_hw *hw) -{ - e1000e_release_nvm(hw); - e1000_put_hw_semaphore_82571(hw); -} - -/** - * e1000_write_nvm_82571 - Write to EEPROM using appropriate interface - * @hw: pointer to the HW structure - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the EEPROM - * - * For non-82573 silicon, write data to EEPROM at offset using SPI interface. - * - * If e1000e_update_nvm_checksum is not called after this function, the - * EEPROM will most likely contain an invalid checksum. - **/ -static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - s32 ret_val; - - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data); - break; - case e1000_82571: - case e1000_82572: - ret_val = e1000e_write_nvm_spi(hw, offset, words, data); - break; - default: - ret_val = -E1000_ERR_NVM; - break; - } - - return ret_val; -} - -/** - * e1000_update_nvm_checksum_82571 - Update EEPROM checksum - * @hw: pointer to the HW structure - * - * Updates the EEPROM checksum by reading/adding each word of the EEPROM - * up to the checksum. Then calculates the EEPROM checksum and writes the - * value to the EEPROM. - **/ -static s32 e1000_update_nvm_checksum_82571(struct e1000_hw *hw) -{ - u32 eecd; - s32 ret_val; - u16 i; - - ret_val = e1000e_update_nvm_checksum_generic(hw); - if (ret_val) - return ret_val; - - /* If our nvm is an EEPROM, then we're done - * otherwise, commit the checksum to the flash NVM. - */ - if (hw->nvm.type != e1000_nvm_flash_hw) - return 0; - - /* Check for pending operations. */ - for (i = 0; i < E1000_FLASH_UPDATES; i++) { - usleep_range(1000, 2000); - if (!(er32(EECD) & E1000_EECD_FLUPD)) - break; - } - - if (i == E1000_FLASH_UPDATES) - return -E1000_ERR_NVM; - - /* Reset the firmware if using STM opcode. */ - if ((er32(FLOP) & 0xFF00) == E1000_STM_OPCODE) { - /* The enabling of and the actual reset must be done - * in two write cycles. - */ - ew32(HICR, E1000_HICR_FW_RESET_ENABLE); - e1e_flush(); - ew32(HICR, E1000_HICR_FW_RESET); - } - - /* Commit the write to flash */ - eecd = er32(EECD) | E1000_EECD_FLUPD; - ew32(EECD, eecd); - - for (i = 0; i < E1000_FLASH_UPDATES; i++) { - usleep_range(1000, 2000); - if (!(er32(EECD) & E1000_EECD_FLUPD)) - break; - } - - if (i == E1000_FLASH_UPDATES) - return -E1000_ERR_NVM; - - return 0; -} - -/** - * e1000_validate_nvm_checksum_82571 - Validate EEPROM checksum - * @hw: pointer to the HW structure - * - * Calculates the EEPROM checksum by reading/adding each word of the EEPROM - * and then verifies that the sum of the EEPROM is equal to 0xBABA. - **/ -static s32 e1000_validate_nvm_checksum_82571(struct e1000_hw *hw) -{ - if (hw->nvm.type == e1000_nvm_flash_hw) - e1000_fix_nvm_checksum_82571(hw); - - return e1000e_validate_nvm_checksum_generic(hw); -} - -/** - * e1000_write_nvm_eewr_82571 - Write to EEPROM for 82573 silicon - * @hw: pointer to the HW structure - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the EEPROM - * - * After checking for invalid values, poll the EEPROM to ensure the previous - * command has completed before trying to write the next word. After write - * poll for completion. - * - * If e1000e_update_nvm_checksum is not called after this function, the - * EEPROM will most likely contain an invalid checksum. - **/ -static s32 e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset, - u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 i, eewr = 0; - s32 ret_val = 0; - - /* A check for invalid values: offset too large, too many words, - * and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - return -E1000_ERR_NVM; - } - - for (i = 0; i < words; i++) { - eewr = ((data[i] << E1000_NVM_RW_REG_DATA) | - ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) | - E1000_NVM_RW_REG_START); - - ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); - if (ret_val) - break; - - ew32(EEWR, eewr); - - ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_WRITE); - if (ret_val) - break; - } - - return ret_val; -} - -/** - * e1000_get_cfg_done_82571 - Poll for configuration done - * @hw: pointer to the HW structure - * - * Reads the management control register for the config done bit to be set. - **/ -static s32 e1000_get_cfg_done_82571(struct e1000_hw *hw) -{ - s32 timeout = PHY_CFG_TIMEOUT; - - while (timeout) { - if (er32(EEMNGCTL) & E1000_NVM_CFG_DONE_PORT_0) - break; - usleep_range(1000, 2000); - timeout--; - } - if (!timeout) { - e_dbg("MNG configuration cycle has not completed.\n"); - return -E1000_ERR_RESET; - } - - return 0; -} - -/** - * e1000_set_d0_lplu_state_82571 - Set Low Power Linkup D0 state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU D0 state according to the active flag. When activating LPLU - * this function also disables smart speed and vice versa. LPLU will not be - * activated unless the device autonegotiation advertisement meets standards - * of either 10 or 10/100 or 10/100/1000 at all duplexes. This is a function - * pointer entry point only called by PHY setup routines. - **/ -static s32 e1000_set_d0_lplu_state_82571(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - ret_val = e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &data); - if (ret_val) - return ret_val; - - if (active) { - data |= IGP02E1000_PM_D0_LPLU; - ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); - if (ret_val) - return ret_val; - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data); - if (ret_val) - return ret_val; - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data); - if (ret_val) - return ret_val; - } else { - data &= ~IGP02E1000_PM_D0_LPLU; - ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); - /* LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } - } - - return 0; -} - -/** - * e1000_reset_hw_82571 - Reset hardware - * @hw: pointer to the HW structure - * - * This resets the hardware into a known state. - **/ -static s32 e1000_reset_hw_82571(struct e1000_hw *hw) -{ - u32 ctrl, ctrl_ext, eecd, tctl; - s32 ret_val; - - /* Prevent the PCI-E bus from sticking if there is no TLP connection - * on the last TLP read/write transaction when MAC is reset. - */ - ret_val = e1000e_disable_pcie_master(hw); - if (ret_val) - e_dbg("PCI-E Master disable polling has failed.\n"); - - e_dbg("Masking off all interrupts\n"); - ew32(IMC, 0xffffffff); - - ew32(RCTL, 0); - tctl = er32(TCTL); - tctl &= ~E1000_TCTL_EN; - ew32(TCTL, tctl); - e1e_flush(); - - usleep_range(10000, 20000); - - /* Must acquire the MDIO ownership before MAC reset. - * Ownership defaults to firmware after a reset. - */ - switch (hw->mac.type) { - case e1000_82573: - ret_val = e1000_get_hw_semaphore_82573(hw); - break; - case e1000_82574: - case e1000_82583: - ret_val = e1000_get_hw_semaphore_82574(hw); - break; - default: - break; - } - - ctrl = er32(CTRL); - - e_dbg("Issuing a global reset to MAC\n"); - ew32(CTRL, ctrl | E1000_CTRL_RST); - - /* Must release MDIO ownership and mutex after MAC reset. */ - switch (hw->mac.type) { - case e1000_82573: - /* Release mutex only if the hw semaphore is acquired */ - if (!ret_val) - e1000_put_hw_semaphore_82573(hw); - break; - case e1000_82574: - case e1000_82583: - /* Release mutex only if the hw semaphore is acquired */ - if (!ret_val) - e1000_put_hw_semaphore_82574(hw); - break; - default: - break; - } - - if (hw->nvm.type == e1000_nvm_flash_hw) { - usleep_range(10, 20); - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - ew32(CTRL_EXT, ctrl_ext); - e1e_flush(); - } - - ret_val = e1000e_get_auto_rd_done(hw); - if (ret_val) - /* We don't want to continue accessing MAC registers. */ - return ret_val; - - /* Phy configuration from NVM just starts after EECD_AUTO_RD is set. - * Need to wait for Phy configuration completion before accessing - * NVM and Phy. - */ - - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - /* REQ and GNT bits need to be cleared when using AUTO_RD - * to access the EEPROM. - */ - eecd = er32(EECD); - eecd &= ~(E1000_EECD_REQ | E1000_EECD_GNT); - ew32(EECD, eecd); - break; - case e1000_82573: - case e1000_82574: - case e1000_82583: - msleep(25); - break; - default: - break; - } - - /* Clear any pending interrupt events. */ - ew32(IMC, 0xffffffff); - er32(ICR); - - if (hw->mac.type == e1000_82571) { - /* Install any alternate MAC address into RAR0 */ - ret_val = e1000_check_alt_mac_addr_generic(hw); - if (ret_val) - return ret_val; - - e1000e_set_laa_state_82571(hw, true); - } - - /* Reinitialize the 82571 serdes link state machine */ - if (hw->phy.media_type == e1000_media_type_internal_serdes) - hw->mac.serdes_link_state = e1000_serdes_link_down; - - return 0; -} - -/** - * e1000_init_hw_82571 - Initialize hardware - * @hw: pointer to the HW structure - * - * This inits the hardware readying it for operation. - **/ -static s32 e1000_init_hw_82571(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 reg_data; - s32 ret_val; - u16 i, rar_count = mac->rar_entry_count; - - e1000_initialize_hw_bits_82571(hw); - - /* Initialize identification LED */ - ret_val = mac->ops.id_led_init(hw); - /* An error is not fatal and we should not stop init due to this */ - if (ret_val) - e_dbg("Error initializing identification LED\n"); - - /* Disabling VLAN filtering */ - e_dbg("Initializing the IEEE VLAN\n"); - mac->ops.clear_vfta(hw); - - /* Setup the receive address. - * If, however, a locally administered address was assigned to the - * 82571, we must reserve a RAR for it to work around an issue where - * resetting one port will reload the MAC on the other port. - */ - if (e1000e_get_laa_state_82571(hw)) - rar_count--; - e1000e_init_rx_addrs(hw, rar_count); - - /* Zero out the Multicast HASH table */ - e_dbg("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - - /* Setup link and flow control */ - ret_val = mac->ops.setup_link(hw); - - /* Set the transmit descriptor write-back policy */ - reg_data = er32(TXDCTL(0)); - reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC); - ew32(TXDCTL(0), reg_data); - - /* ...for both queues. */ - switch (mac->type) { - case e1000_82573: - e1000e_enable_tx_pkt_filtering(hw); - /* fall through */ - case e1000_82574: - case e1000_82583: - reg_data = er32(GCR); - reg_data |= E1000_GCR_L1_ACT_WITHOUT_L0S_RX; - ew32(GCR, reg_data); - break; - default: - reg_data = er32(TXDCTL(1)); - reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB | - E1000_TXDCTL_COUNT_DESC); - ew32(TXDCTL(1), reg_data); - break; - } - - /* Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs_82571(hw); - - return ret_val; -} - -/** - * e1000_initialize_hw_bits_82571 - Initialize hardware-dependent bits - * @hw: pointer to the HW structure - * - * Initializes required hardware-dependent bits needed for normal operation. - **/ -static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw) -{ - u32 reg; - - /* Transmit Descriptor Control 0 */ - reg = er32(TXDCTL(0)); - reg |= (1 << 22); - ew32(TXDCTL(0), reg); - - /* Transmit Descriptor Control 1 */ - reg = er32(TXDCTL(1)); - reg |= (1 << 22); - ew32(TXDCTL(1), reg); - - /* Transmit Arbitration Control 0 */ - reg = er32(TARC(0)); - reg &= ~(0xF << 27); /* 30:27 */ - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - reg |= (1 << 23) | (1 << 24) | (1 << 25) | (1 << 26); - break; - case e1000_82574: - case e1000_82583: - reg |= (1 << 26); - break; - default: - break; - } - ew32(TARC(0), reg); - - /* Transmit Arbitration Control 1 */ - reg = er32(TARC(1)); - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - reg &= ~((1 << 29) | (1 << 30)); - reg |= (1 << 22) | (1 << 24) | (1 << 25) | (1 << 26); - if (er32(TCTL) & E1000_TCTL_MULR) - reg &= ~(1 << 28); - else - reg |= (1 << 28); - ew32(TARC(1), reg); - break; - default: - break; - } - - /* Device Control */ - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - reg = er32(CTRL); - reg &= ~(1 << 29); - ew32(CTRL, reg); - break; - default: - break; - } - - /* Extended Device Control */ - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - reg = er32(CTRL_EXT); - reg &= ~(1 << 23); - reg |= (1 << 22); - ew32(CTRL_EXT, reg); - break; - default: - break; - } - - if (hw->mac.type == e1000_82571) { - reg = er32(PBA_ECC); - reg |= E1000_PBA_ECC_CORR_EN; - ew32(PBA_ECC, reg); - } - - /* Workaround for hardware errata. - * Ensure that DMA Dynamic Clock gating is disabled on 82571 and 82572 - */ - if ((hw->mac.type == e1000_82571) || (hw->mac.type == e1000_82572)) { - reg = er32(CTRL_EXT); - reg &= ~E1000_CTRL_EXT_DMA_DYN_CLK_EN; - ew32(CTRL_EXT, reg); - } - - /* Disable IPv6 extension header parsing because some malformed - * IPv6 headers can hang the Rx. - */ - if (hw->mac.type <= e1000_82573) { - reg = er32(RFCTL); - reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); - ew32(RFCTL, reg); - } - - /* PCI-Ex Control Registers */ - switch (hw->mac.type) { - case e1000_82574: - case e1000_82583: - reg = er32(GCR); - reg |= (1 << 22); - ew32(GCR, reg); - - /* Workaround for hardware errata. - * apply workaround for hardware errata documented in errata - * docs Fixes issue where some error prone or unreliable PCIe - * completions are occurring, particularly with ASPM enabled. - * Without fix, issue can cause Tx timeouts. - */ - reg = er32(GCR2); - reg |= 1; - ew32(GCR2, reg); - break; - default: - break; - } -} - -/** - * e1000_clear_vfta_82571 - Clear VLAN filter table - * @hw: pointer to the HW structure - * - * Clears the register array which contains the VLAN filter table by - * setting all the values to 0. - **/ -static void e1000_clear_vfta_82571(struct e1000_hw *hw) -{ - u32 offset; - u32 vfta_value = 0; - u32 vfta_offset = 0; - u32 vfta_bit_in_reg = 0; - - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - if (hw->mng_cookie.vlan_id != 0) { - /* The VFTA is a 4096b bit-field, each identifying - * a single VLAN ID. The following operations - * determine which 32b entry (i.e. offset) into the - * array we want to set the VLAN ID (i.e. bit) of - * the manageability unit. - */ - vfta_offset = (hw->mng_cookie.vlan_id >> - E1000_VFTA_ENTRY_SHIFT) & - E1000_VFTA_ENTRY_MASK; - vfta_bit_in_reg = - 1 << (hw->mng_cookie.vlan_id & - E1000_VFTA_ENTRY_BIT_SHIFT_MASK); - } - break; - default: - break; - } - for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { - /* If the offset we want to clear is the same offset of the - * manageability VLAN ID, then clear all bits except that of - * the manageability unit. - */ - vfta_value = (offset == vfta_offset) ? vfta_bit_in_reg : 0; - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, vfta_value); - e1e_flush(); - } -} - -/** - * e1000_check_mng_mode_82574 - Check manageability is enabled - * @hw: pointer to the HW structure - * - * Reads the NVM Initialization Control Word 2 and returns true - * (>0) if any manageability is enabled, else false (0). - **/ -static bool e1000_check_mng_mode_82574(struct e1000_hw *hw) -{ - u16 data; - - e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data); - return (data & E1000_NVM_INIT_CTRL2_MNGM) != 0; -} - -/** - * e1000_led_on_82574 - Turn LED on - * @hw: pointer to the HW structure - * - * Turn LED on. - **/ -static s32 e1000_led_on_82574(struct e1000_hw *hw) -{ - u32 ctrl; - u32 i; - - ctrl = hw->mac.ledctl_mode2; - if (!(E1000_STATUS_LU & er32(STATUS))) { - /* If no link, then turn LED on by setting the invert bit - * for each LED that's "on" (0x0E) in ledctl_mode2. - */ - for (i = 0; i < 4; i++) - if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) == - E1000_LEDCTL_MODE_LED_ON) - ctrl |= (E1000_LEDCTL_LED0_IVRT << (i * 8)); - } - ew32(LEDCTL, ctrl); - - return 0; -} - -/** - * e1000_check_phy_82574 - check 82574 phy hung state - * @hw: pointer to the HW structure - * - * Returns whether phy is hung or not - **/ -bool e1000_check_phy_82574(struct e1000_hw *hw) -{ - u16 status_1kbt = 0; - u16 receive_errors = 0; - s32 ret_val; - - /* Read PHY Receive Error counter first, if its is max - all F's then - * read the Base1000T status register If both are max then PHY is hung. - */ - ret_val = e1e_rphy(hw, E1000_RECEIVE_ERROR_COUNTER, &receive_errors); - if (ret_val) - return false; - if (receive_errors == E1000_RECEIVE_ERROR_MAX) { - ret_val = e1e_rphy(hw, E1000_BASE1000T_STATUS, &status_1kbt); - if (ret_val) - return false; - if ((status_1kbt & E1000_IDLE_ERROR_COUNT_MASK) == - E1000_IDLE_ERROR_COUNT_MASK) - return true; - } - - return false; -} - -/** - * e1000_setup_link_82571 - Setup flow control and link settings - * @hw: pointer to the HW structure - * - * Determines which flow control settings to use, then configures flow - * control. Calls the appropriate media-specific link configuration - * function. Assuming the adapter has a valid link partner, a valid link - * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. - **/ -static s32 e1000_setup_link_82571(struct e1000_hw *hw) -{ - /* 82573 does not have a word in the NVM to determine - * the default flow control setting, so we explicitly - * set it to full. - */ - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - if (hw->fc.requested_mode == e1000_fc_default) - hw->fc.requested_mode = e1000_fc_full; - break; - default: - break; - } - - return e1000e_setup_link_generic(hw); -} - -/** - * e1000_setup_copper_link_82571 - Configure copper link settings - * @hw: pointer to the HW structure - * - * Configures the link for auto-neg or forced speed and duplex. Then we check - * for link, once link is established calls to configure collision distance - * and flow control are called. - **/ -static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ew32(CTRL, ctrl); - - switch (hw->phy.type) { - case e1000_phy_m88: - case e1000_phy_bm: - ret_val = e1000e_copper_link_setup_m88(hw); - break; - case e1000_phy_igp_2: - ret_val = e1000e_copper_link_setup_igp(hw); - break; - default: - return -E1000_ERR_PHY; - } - - if (ret_val) - return ret_val; - - return e1000e_setup_copper_link(hw); -} - -/** - * e1000_setup_fiber_serdes_link_82571 - Setup link for fiber/serdes - * @hw: pointer to the HW structure - * - * Configures collision distance and flow control for fiber and serdes links. - * Upon successful setup, poll for link. - **/ -static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw) -{ - switch (hw->mac.type) { - case e1000_82571: - case e1000_82572: - /* If SerDes loopback mode is entered, there is no form - * of reset to take the adapter out of that mode. So we - * have to explicitly take the adapter out of loopback - * mode. This prevents drivers from twiddling their thumbs - * if another tool failed to take it out of loopback mode. - */ - ew32(SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); - break; - default: - break; - } - - return e1000e_setup_fiber_serdes_link(hw); -} - -/** - * e1000_check_for_serdes_link_82571 - Check for link (Serdes) - * @hw: pointer to the HW structure - * - * Reports the link state as up or down. - * - * If autonegotiation is supported by the link partner, the link state is - * determined by the result of autonegotiation. This is the most likely case. - * If autonegotiation is not supported by the link partner, and the link - * has a valid signal, force the link up. - * - * The link state is represented internally here by 4 states: - * - * 1) down - * 2) autoneg_progress - * 3) autoneg_complete (the link successfully autonegotiated) - * 4) forced_up (the link has been forced up, it did not autonegotiate) - * - **/ -static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw; - u32 ctrl; - u32 status; - u32 txcw; - u32 i; - s32 ret_val = 0; - - ctrl = er32(CTRL); - status = er32(STATUS); - er32(RXCW); - /* SYNCH bit and IV bit are sticky */ - usleep_range(10, 20); - rxcw = er32(RXCW); - - if ((rxcw & E1000_RXCW_SYNCH) && !(rxcw & E1000_RXCW_IV)) { - /* Receiver is synchronized with no invalid bits. */ - switch (mac->serdes_link_state) { - case e1000_serdes_link_autoneg_complete: - if (!(status & E1000_STATUS_LU)) { - /* We have lost link, retry autoneg before - * reporting link failure - */ - mac->serdes_link_state = - e1000_serdes_link_autoneg_progress; - mac->serdes_has_link = false; - e_dbg("AN_UP -> AN_PROG\n"); - } else { - mac->serdes_has_link = true; - } - break; - - case e1000_serdes_link_forced_up: - /* If we are receiving /C/ ordered sets, re-enable - * auto-negotiation in the TXCW register and disable - * forced link in the Device Control register in an - * attempt to auto-negotiate with our link partner. - */ - if (rxcw & E1000_RXCW_C) { - /* Enable autoneg, and unforce link up */ - ew32(TXCW, mac->txcw); - ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - mac->serdes_link_state = - e1000_serdes_link_autoneg_progress; - mac->serdes_has_link = false; - e_dbg("FORCED_UP -> AN_PROG\n"); - } else { - mac->serdes_has_link = true; - } - break; - - case e1000_serdes_link_autoneg_progress: - if (rxcw & E1000_RXCW_C) { - /* We received /C/ ordered sets, meaning the - * link partner has autonegotiated, and we can - * trust the Link Up (LU) status bit. - */ - if (status & E1000_STATUS_LU) { - mac->serdes_link_state = - e1000_serdes_link_autoneg_complete; - e_dbg("AN_PROG -> AN_UP\n"); - mac->serdes_has_link = true; - } else { - /* Autoneg completed, but failed. */ - mac->serdes_link_state = - e1000_serdes_link_down; - e_dbg("AN_PROG -> DOWN\n"); - } - } else { - /* The link partner did not autoneg. - * Force link up and full duplex, and change - * state to forced. - */ - ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - ew32(CTRL, ctrl); - - /* Configure Flow Control after link up. */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error config flow control\n"); - break; - } - mac->serdes_link_state = - e1000_serdes_link_forced_up; - mac->serdes_has_link = true; - e_dbg("AN_PROG -> FORCED_UP\n"); - } - break; - - case e1000_serdes_link_down: - default: - /* The link was down but the receiver has now gained - * valid sync, so lets see if we can bring the link - * up. - */ - ew32(TXCW, mac->txcw); - ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - mac->serdes_link_state = - e1000_serdes_link_autoneg_progress; - mac->serdes_has_link = false; - e_dbg("DOWN -> AN_PROG\n"); - break; - } - } else { - if (!(rxcw & E1000_RXCW_SYNCH)) { - mac->serdes_has_link = false; - mac->serdes_link_state = e1000_serdes_link_down; - e_dbg("ANYSTATE -> DOWN\n"); - } else { - /* Check several times, if SYNCH bit and CONFIG - * bit both are consistently 1 then simply ignore - * the IV bit and restart Autoneg - */ - for (i = 0; i < AN_RETRY_COUNT; i++) { - usleep_range(10, 20); - rxcw = er32(RXCW); - if ((rxcw & E1000_RXCW_SYNCH) && - (rxcw & E1000_RXCW_C)) - continue; - - if (rxcw & E1000_RXCW_IV) { - mac->serdes_has_link = false; - mac->serdes_link_state = - e1000_serdes_link_down; - e_dbg("ANYSTATE -> DOWN\n"); - break; - } - } - - if (i == AN_RETRY_COUNT) { - txcw = er32(TXCW); - txcw |= E1000_TXCW_ANE; - ew32(TXCW, txcw); - mac->serdes_link_state = - e1000_serdes_link_autoneg_progress; - mac->serdes_has_link = false; - e_dbg("ANYSTATE -> AN_PROG\n"); - } - } - } - - return ret_val; -} - -/** - * e1000_valid_led_default_82571 - Verify a valid default LED config - * @hw: pointer to the HW structure - * @data: pointer to the NVM (EEPROM) - * - * Read the EEPROM for the current default LED configuration. If the - * LED configuration is not valid, set to a valid LED configuration. - **/ -static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data) -{ - s32 ret_val; - - ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - switch (hw->mac.type) { - case e1000_82573: - case e1000_82574: - case e1000_82583: - if (*data == ID_LED_RESERVED_F746) - *data = ID_LED_DEFAULT_82573; - break; - default: - if (*data == ID_LED_RESERVED_0000 || - *data == ID_LED_RESERVED_FFFF) - *data = ID_LED_DEFAULT; - break; - } - - return 0; -} - -/** - * e1000e_get_laa_state_82571 - Get locally administered address state - * @hw: pointer to the HW structure - * - * Retrieve and return the current locally administered address state. - **/ -bool e1000e_get_laa_state_82571(struct e1000_hw *hw) -{ - if (hw->mac.type != e1000_82571) - return false; - - return hw->dev_spec.e82571.laa_is_present; -} - -/** - * e1000e_set_laa_state_82571 - Set locally administered address state - * @hw: pointer to the HW structure - * @state: enable/disable locally administered address - * - * Enable/Disable the current locally administered address state. - **/ -void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state) -{ - if (hw->mac.type != e1000_82571) - return; - - hw->dev_spec.e82571.laa_is_present = state; - - /* If workaround is activated... */ - if (state) - /* Hold a copy of the LAA in RAR[14] This is done so that - * between the time RAR[0] gets clobbered and the time it - * gets fixed, the actual LAA is in one of the RARs and no - * incoming packets directed to this port are dropped. - * Eventually the LAA will be in RAR[0] and RAR[14]. - */ - hw->mac.ops.rar_set(hw, hw->mac.addr, - hw->mac.rar_entry_count - 1); -} - -/** - * e1000_fix_nvm_checksum_82571 - Fix EEPROM checksum - * @hw: pointer to the HW structure - * - * Verifies that the EEPROM has completed the update. After updating the - * EEPROM, we need to check bit 15 in work 0x23 for the checksum fix. If - * the checksum fix is not implemented, we need to set the bit and update - * the checksum. Otherwise, if bit 15 is set and the checksum is incorrect, - * we need to return bad checksum. - **/ -static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val; - u16 data; - - if (nvm->type != e1000_nvm_flash_hw) - return 0; - - /* Check bit 4 of word 10h. If it is 0, firmware is done updating - * 10h-12h. Checksum may need to be fixed. - */ - ret_val = e1000_read_nvm(hw, 0x10, 1, &data); - if (ret_val) - return ret_val; - - if (!(data & 0x10)) { - /* Read 0x23 and check bit 15. This bit is a 1 - * when the checksum has already been fixed. If - * the checksum is still wrong and this bit is a - * 1, we need to return bad checksum. Otherwise, - * we need to set this bit to a 1 and update the - * checksum. - */ - ret_val = e1000_read_nvm(hw, 0x23, 1, &data); - if (ret_val) - return ret_val; - - if (!(data & 0x8000)) { - data |= 0x8000; - ret_val = e1000_write_nvm(hw, 0x23, 1, &data); - if (ret_val) - return ret_val; - ret_val = e1000e_update_nvm_checksum(hw); - if (ret_val) - return ret_val; - } - } - - return 0; -} - -/** - * e1000_read_mac_addr_82571 - Read device MAC address - * @hw: pointer to the HW structure - **/ -static s32 e1000_read_mac_addr_82571(struct e1000_hw *hw) -{ - if (hw->mac.type == e1000_82571) { - s32 ret_val; - - /* If there's an alternate MAC address place it in RAR0 - * so that it will override the Si installed default perm - * address. - */ - ret_val = e1000_check_alt_mac_addr_generic(hw); - if (ret_val) - return ret_val; - } - - return e1000_read_mac_addr_generic(hw); -} - -/** - * e1000_power_down_phy_copper_82571 - Remove link during PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, remove the link. - **/ -static void e1000_power_down_phy_copper_82571(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - struct e1000_mac_info *mac = &hw->mac; - - if (!phy->ops.check_reset_block) - return; - - /* If the management interface is not enabled, then power down */ - if (!(mac->ops.check_mng_mode(hw) || phy->ops.check_reset_block(hw))) - e1000_power_down_phy_copper(hw); -} - -/** - * e1000_clear_hw_cntrs_82571 - Clear device specific hardware counters - * @hw: pointer to the HW structure - * - * Clears the hardware counters by reading the counter registers. - **/ -static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw) -{ - e1000e_clear_hw_cntrs_base(hw); - - er32(PRC64); - er32(PRC127); - er32(PRC255); - er32(PRC511); - er32(PRC1023); - er32(PRC1522); - er32(PTC64); - er32(PTC127); - er32(PTC255); - er32(PTC511); - er32(PTC1023); - er32(PTC1522); - - er32(ALGNERRC); - er32(RXERRC); - er32(TNCRS); - er32(CEXTERR); - er32(TSCTC); - er32(TSCTFC); - - er32(MGTPRC); - er32(MGTPDC); - er32(MGTPTC); - - er32(IAC); - er32(ICRXOC); - - er32(ICRXPTC); - er32(ICRXATC); - er32(ICTXPTC); - er32(ICTXATC); - er32(ICTXQEC); - er32(ICTXQMTC); - er32(ICRXDMTC); -} - -static const struct e1000_mac_operations e82571_mac_ops = { - /* .check_mng_mode: mac type dependent */ - /* .check_for_link: media type dependent */ - .id_led_init = e1000e_id_led_init_generic, - .cleanup_led = e1000e_cleanup_led_generic, - .clear_hw_cntrs = e1000_clear_hw_cntrs_82571, - .get_bus_info = e1000e_get_bus_info_pcie, - .set_lan_id = e1000_set_lan_id_multi_port_pcie, - /* .get_link_up_info: media type dependent */ - /* .led_on: mac type dependent */ - .led_off = e1000e_led_off_generic, - .update_mc_addr_list = e1000e_update_mc_addr_list_generic, - .write_vfta = e1000_write_vfta_generic, - .clear_vfta = e1000_clear_vfta_82571, - .reset_hw = e1000_reset_hw_82571, - .init_hw = e1000_init_hw_82571, - .setup_link = e1000_setup_link_82571, - /* .setup_physical_interface: media type dependent */ - .setup_led = e1000e_setup_led_generic, - .config_collision_dist = e1000e_config_collision_dist_generic, - .read_mac_addr = e1000_read_mac_addr_82571, - .rar_set = e1000e_rar_set_generic, - .rar_get_count = e1000e_rar_get_count_generic, -}; - -static const struct e1000_phy_operations e82_phy_ops_igp = { - .acquire = e1000_get_hw_semaphore_82571, - .check_polarity = e1000_check_polarity_igp, - .check_reset_block = e1000e_check_reset_block_generic, - .commit = NULL, - .force_speed_duplex = e1000e_phy_force_speed_duplex_igp, - .get_cfg_done = e1000_get_cfg_done_82571, - .get_cable_length = e1000e_get_cable_length_igp_2, - .get_info = e1000e_get_phy_info_igp, - .read_reg = e1000e_read_phy_reg_igp, - .release = e1000_put_hw_semaphore_82571, - .reset = e1000e_phy_hw_reset_generic, - .set_d0_lplu_state = e1000_set_d0_lplu_state_82571, - .set_d3_lplu_state = e1000e_set_d3_lplu_state, - .write_reg = e1000e_write_phy_reg_igp, - .cfg_on_link_up = NULL, -}; - -static const struct e1000_phy_operations e82_phy_ops_m88 = { - .acquire = e1000_get_hw_semaphore_82571, - .check_polarity = e1000_check_polarity_m88, - .check_reset_block = e1000e_check_reset_block_generic, - .commit = e1000e_phy_sw_reset, - .force_speed_duplex = e1000e_phy_force_speed_duplex_m88, - .get_cfg_done = e1000e_get_cfg_done_generic, - .get_cable_length = e1000e_get_cable_length_m88, - .get_info = e1000e_get_phy_info_m88, - .read_reg = e1000e_read_phy_reg_m88, - .release = e1000_put_hw_semaphore_82571, - .reset = e1000e_phy_hw_reset_generic, - .set_d0_lplu_state = e1000_set_d0_lplu_state_82571, - .set_d3_lplu_state = e1000e_set_d3_lplu_state, - .write_reg = e1000e_write_phy_reg_m88, - .cfg_on_link_up = NULL, -}; - -static const struct e1000_phy_operations e82_phy_ops_bm = { - .acquire = e1000_get_hw_semaphore_82571, - .check_polarity = e1000_check_polarity_m88, - .check_reset_block = e1000e_check_reset_block_generic, - .commit = e1000e_phy_sw_reset, - .force_speed_duplex = e1000e_phy_force_speed_duplex_m88, - .get_cfg_done = e1000e_get_cfg_done_generic, - .get_cable_length = e1000e_get_cable_length_m88, - .get_info = e1000e_get_phy_info_m88, - .read_reg = e1000e_read_phy_reg_bm2, - .release = e1000_put_hw_semaphore_82571, - .reset = e1000e_phy_hw_reset_generic, - .set_d0_lplu_state = e1000_set_d0_lplu_state_82571, - .set_d3_lplu_state = e1000e_set_d3_lplu_state, - .write_reg = e1000e_write_phy_reg_bm2, - .cfg_on_link_up = NULL, -}; - -static const struct e1000_nvm_operations e82571_nvm_ops = { - .acquire = e1000_acquire_nvm_82571, - .read = e1000e_read_nvm_eerd, - .release = e1000_release_nvm_82571, - .reload = e1000e_reload_nvm_generic, - .update = e1000_update_nvm_checksum_82571, - .valid_led_default = e1000_valid_led_default_82571, - .validate = e1000_validate_nvm_checksum_82571, - .write = e1000_write_nvm_82571, -}; - -const struct e1000_info e1000_82571_info = { - .mac = e1000_82571, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_SMART_POWER_DOWN - | FLAG_RESET_OVERWRITES_LAA /* errata */ - | FLAG_TARC_SPEED_MODE_BIT /* errata */ - | FLAG_APME_CHECK_PORT_B, - .flags2 = FLAG2_DISABLE_ASPM_L1 /* errata 13 */ - | FLAG2_DMA_BURST, - .pba = 38, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_82571, - .mac_ops = &e82571_mac_ops, - .phy_ops = &e82_phy_ops_igp, - .nvm_ops = &e82571_nvm_ops, -}; - -const struct e1000_info e1000_82572_info = { - .mac = e1000_82572, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_TARC_SPEED_MODE_BIT, /* errata */ - .flags2 = FLAG2_DISABLE_ASPM_L1 /* errata 13 */ - | FLAG2_DMA_BURST, - .pba = 38, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_82571, - .mac_ops = &e82571_mac_ops, - .phy_ops = &e82_phy_ops_igp, - .nvm_ops = &e82571_nvm_ops, -}; - -const struct e1000_info e1000_82573_info = { - .mac = e1000_82573, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_WOL - | FLAG_APME_IN_CTRL3 - | FLAG_HAS_SMART_POWER_DOWN - | FLAG_HAS_AMT - | FLAG_HAS_SWSM_ON_LOAD, - .flags2 = FLAG2_DISABLE_ASPM_L1 - | FLAG2_DISABLE_ASPM_L0S, - .pba = 20, - .max_hw_frame_size = VLAN_ETH_FRAME_LEN + ETH_FCS_LEN, - .get_variants = e1000_get_variants_82571, - .mac_ops = &e82571_mac_ops, - .phy_ops = &e82_phy_ops_m88, - .nvm_ops = &e82571_nvm_ops, -}; - -const struct e1000_info e1000_82574_info = { - .mac = e1000_82574, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_MSIX - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_WOL - | FLAG_HAS_HW_TIMESTAMP - | FLAG_APME_IN_CTRL3 - | FLAG_HAS_SMART_POWER_DOWN - | FLAG_HAS_AMT - | FLAG_HAS_CTRLEXT_ON_LOAD, - .flags2 = FLAG2_CHECK_PHY_HANG - | FLAG2_DISABLE_ASPM_L0S - | FLAG2_DISABLE_ASPM_L1 - | FLAG2_NO_DISABLE_RX - | FLAG2_DMA_BURST, - .pba = 32, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_82571, - .mac_ops = &e82571_mac_ops, - .phy_ops = &e82_phy_ops_bm, - .nvm_ops = &e82571_nvm_ops, -}; - -const struct e1000_info e1000_82583_info = { - .mac = e1000_82583, - .flags = FLAG_HAS_HW_VLAN_FILTER - | FLAG_HAS_WOL - | FLAG_HAS_HW_TIMESTAMP - | FLAG_APME_IN_CTRL3 - | FLAG_HAS_SMART_POWER_DOWN - | FLAG_HAS_AMT - | FLAG_HAS_JUMBO_FRAMES - | FLAG_HAS_CTRLEXT_ON_LOAD, - .flags2 = FLAG2_DISABLE_ASPM_L0S - | FLAG2_DISABLE_ASPM_L1 - | FLAG2_NO_DISABLE_RX, - .pba = 32, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_82571, - .mac_ops = &e82571_mac_ops, - .phy_ops = &e82_phy_ops_bm, - .nvm_ops = &e82571_nvm_ops, -}; diff --git a/addons/e1000e/src/4.4.180/82571.h b/addons/e1000e/src/4.4.180/82571.h deleted file mode 100644 index abc6a9ab..00000000 --- a/addons/e1000e/src/4.4.180/82571.h +++ /dev/null @@ -1,53 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#ifndef _E1000E_82571_H_ -#define _E1000E_82571_H_ - -#define ID_LED_RESERVED_F746 0xF746 -#define ID_LED_DEFAULT_82573 ((ID_LED_DEF1_DEF2 << 12) | \ - (ID_LED_OFF1_ON2 << 8) | \ - (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_DEF1_DEF2)) - -#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000 -#define AN_RETRY_COUNT 5 /* Autoneg Retry Count value */ - -/* Intr Throttling - RW */ -#define E1000_EITR_82574(_n) (0x000E8 + (0x4 * (_n))) - -#define E1000_EIAC_82574 0x000DC /* Ext. Interrupt Auto Clear - RW */ -#define E1000_EIAC_MASK_82574 0x01F00000 - -#define E1000_IVAR_INT_ALLOC_VALID 0x8 - -/* Manageability Operation Mode mask */ -#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 - -#define E1000_BASE1000T_STATUS 10 -#define E1000_IDLE_ERROR_COUNT_MASK 0xFF -#define E1000_RECEIVE_ERROR_COUNTER 21 -#define E1000_RECEIVE_ERROR_MAX 0xFFFF -bool e1000_check_phy_82574(struct e1000_hw *hw); -bool e1000e_get_laa_state_82571(struct e1000_hw *hw); -void e1000e_set_laa_state_82571(struct e1000_hw *hw, bool state); - -#endif diff --git a/addons/e1000e/src/4.4.180/Makefile b/addons/e1000e/src/4.4.180/Makefile deleted file mode 100644 index 9393a936..00000000 --- a/addons/e1000e/src/4.4.180/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-m += e1000e.o -e1000e-objs := 82571.o ich8lan.o 80003es2lan.o \ - mac.o manage.o nvm.o phy.o \ - param.o ethtool.o netdev.o ptp.o - diff --git a/addons/e1000e/src/4.4.180/defines.h b/addons/e1000e/src/4.4.180/defines.h deleted file mode 100644 index 133d4074..00000000 --- a/addons/e1000e/src/4.4.180/defines.h +++ /dev/null @@ -1,800 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#ifndef _E1000_DEFINES_H_ -#define _E1000_DEFINES_H_ - -/* Number of Transmit and Receive Descriptors must be a multiple of 8 */ -#define REQ_TX_DESCRIPTOR_MULTIPLE 8 -#define REQ_RX_DESCRIPTOR_MULTIPLE 8 - -/* Definitions for power management and wakeup registers */ -/* Wake Up Control */ -#define E1000_WUC_APME 0x00000001 /* APM Enable */ -#define E1000_WUC_PME_EN 0x00000002 /* PME Enable */ -#define E1000_WUC_PME_STATUS 0x00000004 /* PME Status */ -#define E1000_WUC_APMPME 0x00000008 /* Assert PME on APM Wakeup */ -#define E1000_WUC_PHY_WAKE 0x00000100 /* if PHY supports wakeup */ - -/* Wake Up Filter Control */ -#define E1000_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */ -#define E1000_WUFC_MAG 0x00000002 /* Magic Packet Wakeup Enable */ -#define E1000_WUFC_EX 0x00000004 /* Directed Exact Wakeup Enable */ -#define E1000_WUFC_MC 0x00000008 /* Directed Multicast Wakeup Enable */ -#define E1000_WUFC_BC 0x00000010 /* Broadcast Wakeup Enable */ -#define E1000_WUFC_ARP 0x00000020 /* ARP Request Packet Wakeup Enable */ - -/* Wake Up Status */ -#define E1000_WUS_LNKC E1000_WUFC_LNKC -#define E1000_WUS_MAG E1000_WUFC_MAG -#define E1000_WUS_EX E1000_WUFC_EX -#define E1000_WUS_MC E1000_WUFC_MC -#define E1000_WUS_BC E1000_WUFC_BC - -/* Extended Device Control */ -#define E1000_CTRL_EXT_LPCD 0x00000004 /* LCD Power Cycle Done */ -#define E1000_CTRL_EXT_SDP3_DATA 0x00000080 /* Value of SW Definable Pin 3 */ -#define E1000_CTRL_EXT_FORCE_SMBUS 0x00000800 /* Force SMBus mode */ -#define E1000_CTRL_EXT_EE_RST 0x00002000 /* Reinitialize from EEPROM */ -#define E1000_CTRL_EXT_SPD_BYPS 0x00008000 /* Speed Select Bypass */ -#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */ -#define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */ -#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000 -#define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000 -#define E1000_CTRL_EXT_EIAME 0x01000000 -#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */ -#define E1000_CTRL_EXT_IAME 0x08000000 /* Int ACK Auto-mask */ -#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */ -#define E1000_CTRL_EXT_LSECCK 0x00001000 -#define E1000_CTRL_EXT_PHYPDEN 0x00100000 - -/* Receive Descriptor bit definitions */ -#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */ -#define E1000_RXD_STAT_EOP 0x02 /* End of Packet */ -#define E1000_RXD_STAT_IXSM 0x04 /* Ignore checksum */ -#define E1000_RXD_STAT_VP 0x08 /* IEEE VLAN Packet */ -#define E1000_RXD_STAT_UDPCS 0x10 /* UDP xsum calculated */ -#define E1000_RXD_STAT_TCPCS 0x20 /* TCP xsum calculated */ -#define E1000_RXD_ERR_CE 0x01 /* CRC Error */ -#define E1000_RXD_ERR_SE 0x02 /* Symbol Error */ -#define E1000_RXD_ERR_SEQ 0x04 /* Sequence Error */ -#define E1000_RXD_ERR_CXE 0x10 /* Carrier Extension Error */ -#define E1000_RXD_ERR_TCPE 0x20 /* TCP/UDP Checksum Error */ -#define E1000_RXD_ERR_IPE 0x40 /* IP Checksum Error */ -#define E1000_RXD_ERR_RXE 0x80 /* Rx Data Error */ -#define E1000_RXD_SPC_VLAN_MASK 0x0FFF /* VLAN ID is in lower 12 bits */ - -#define E1000_RXDEXT_STATERR_TST 0x00000100 /* Time Stamp taken */ -#define E1000_RXDEXT_STATERR_CE 0x01000000 -#define E1000_RXDEXT_STATERR_SE 0x02000000 -#define E1000_RXDEXT_STATERR_SEQ 0x04000000 -#define E1000_RXDEXT_STATERR_CXE 0x10000000 -#define E1000_RXDEXT_STATERR_RXE 0x80000000 - -/* mask to determine if packets should be dropped due to frame errors */ -#define E1000_RXD_ERR_FRAME_ERR_MASK ( \ - E1000_RXD_ERR_CE | \ - E1000_RXD_ERR_SE | \ - E1000_RXD_ERR_SEQ | \ - E1000_RXD_ERR_CXE | \ - E1000_RXD_ERR_RXE) - -/* Same mask, but for extended and packet split descriptors */ -#define E1000_RXDEXT_ERR_FRAME_ERR_MASK ( \ - E1000_RXDEXT_STATERR_CE | \ - E1000_RXDEXT_STATERR_SE | \ - E1000_RXDEXT_STATERR_SEQ | \ - E1000_RXDEXT_STATERR_CXE | \ - E1000_RXDEXT_STATERR_RXE) - -#define E1000_MRQC_RSS_FIELD_MASK 0xFFFF0000 -#define E1000_MRQC_RSS_FIELD_IPV4_TCP 0x00010000 -#define E1000_MRQC_RSS_FIELD_IPV4 0x00020000 -#define E1000_MRQC_RSS_FIELD_IPV6_TCP_EX 0x00040000 -#define E1000_MRQC_RSS_FIELD_IPV6 0x00100000 -#define E1000_MRQC_RSS_FIELD_IPV6_TCP 0x00200000 - -#define E1000_RXDPS_HDRSTAT_HDRSP 0x00008000 - -/* Management Control */ -#define E1000_MANC_SMBUS_EN 0x00000001 /* SMBus Enabled - RO */ -#define E1000_MANC_ASF_EN 0x00000002 /* ASF Enabled - RO */ -#define E1000_MANC_ARP_EN 0x00002000 /* Enable ARP Request Filtering */ -#define E1000_MANC_RCV_TCO_EN 0x00020000 /* Receive TCO Packets Enabled */ -#define E1000_MANC_BLK_PHY_RST_ON_IDE 0x00040000 /* Block phy resets */ -/* Enable MAC address filtering */ -#define E1000_MANC_EN_MAC_ADDR_FILTER 0x00100000 -/* Enable MNG packets to host memory */ -#define E1000_MANC_EN_MNG2HOST 0x00200000 - -#define E1000_MANC2H_PORT_623 0x00000020 /* Port 0x26f */ -#define E1000_MANC2H_PORT_664 0x00000040 /* Port 0x298 */ -#define E1000_MDEF_PORT_623 0x00000800 /* Port 0x26f */ -#define E1000_MDEF_PORT_664 0x00000400 /* Port 0x298 */ - -/* Receive Control */ -#define E1000_RCTL_EN 0x00000002 /* enable */ -#define E1000_RCTL_SBP 0x00000004 /* store bad packet */ -#define E1000_RCTL_UPE 0x00000008 /* unicast promiscuous enable */ -#define E1000_RCTL_MPE 0x00000010 /* multicast promiscuous enab */ -#define E1000_RCTL_LPE 0x00000020 /* long packet enable */ -#define E1000_RCTL_LBM_NO 0x00000000 /* no loopback mode */ -#define E1000_RCTL_LBM_MAC 0x00000040 /* MAC loopback mode */ -#define E1000_RCTL_LBM_TCVR 0x000000C0 /* tcvr loopback mode */ -#define E1000_RCTL_DTYP_PS 0x00000400 /* Packet Split descriptor */ -#define E1000_RCTL_RDMTS_HALF 0x00000000 /* Rx desc min threshold size */ -#define E1000_RCTL_RDMTS_HEX 0x00010000 -#define E1000_RCTL_MO_SHIFT 12 /* multicast offset shift */ -#define E1000_RCTL_MO_3 0x00003000 /* multicast offset 15:4 */ -#define E1000_RCTL_BAM 0x00008000 /* broadcast enable */ -/* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */ -#define E1000_RCTL_SZ_2048 0x00000000 /* Rx buffer size 2048 */ -#define E1000_RCTL_SZ_1024 0x00010000 /* Rx buffer size 1024 */ -#define E1000_RCTL_SZ_512 0x00020000 /* Rx buffer size 512 */ -#define E1000_RCTL_SZ_256 0x00030000 /* Rx buffer size 256 */ -/* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */ -#define E1000_RCTL_SZ_16384 0x00010000 /* Rx buffer size 16384 */ -#define E1000_RCTL_SZ_8192 0x00020000 /* Rx buffer size 8192 */ -#define E1000_RCTL_SZ_4096 0x00030000 /* Rx buffer size 4096 */ -#define E1000_RCTL_VFE 0x00040000 /* vlan filter enable */ -#define E1000_RCTL_CFIEN 0x00080000 /* canonical form enable */ -#define E1000_RCTL_CFI 0x00100000 /* canonical form indicator */ -#define E1000_RCTL_DPF 0x00400000 /* Discard Pause Frames */ -#define E1000_RCTL_PMCF 0x00800000 /* pass MAC control frames */ -#define E1000_RCTL_BSEX 0x02000000 /* Buffer size extension */ -#define E1000_RCTL_SECRC 0x04000000 /* Strip Ethernet CRC */ - -/* Use byte values for the following shift parameters - * Usage: - * psrctl |= (((ROUNDUP(value0, 128) >> E1000_PSRCTL_BSIZE0_SHIFT) & - * E1000_PSRCTL_BSIZE0_MASK) | - * ((ROUNDUP(value1, 1024) >> E1000_PSRCTL_BSIZE1_SHIFT) & - * E1000_PSRCTL_BSIZE1_MASK) | - * ((ROUNDUP(value2, 1024) << E1000_PSRCTL_BSIZE2_SHIFT) & - * E1000_PSRCTL_BSIZE2_MASK) | - * ((ROUNDUP(value3, 1024) << E1000_PSRCTL_BSIZE3_SHIFT) |; - * E1000_PSRCTL_BSIZE3_MASK)) - * where value0 = [128..16256], default=256 - * value1 = [1024..64512], default=4096 - * value2 = [0..64512], default=4096 - * value3 = [0..64512], default=0 - */ - -#define E1000_PSRCTL_BSIZE0_MASK 0x0000007F -#define E1000_PSRCTL_BSIZE1_MASK 0x00003F00 -#define E1000_PSRCTL_BSIZE2_MASK 0x003F0000 -#define E1000_PSRCTL_BSIZE3_MASK 0x3F000000 - -#define E1000_PSRCTL_BSIZE0_SHIFT 7 /* Shift _right_ 7 */ -#define E1000_PSRCTL_BSIZE1_SHIFT 2 /* Shift _right_ 2 */ -#define E1000_PSRCTL_BSIZE2_SHIFT 6 /* Shift _left_ 6 */ -#define E1000_PSRCTL_BSIZE3_SHIFT 14 /* Shift _left_ 14 */ - -/* SWFW_SYNC Definitions */ -#define E1000_SWFW_EEP_SM 0x1 -#define E1000_SWFW_PHY0_SM 0x2 -#define E1000_SWFW_PHY1_SM 0x4 -#define E1000_SWFW_CSR_SM 0x8 - -/* Device Control */ -#define E1000_CTRL_FD 0x00000001 /* Full duplex.0=half; 1=full */ -#define E1000_CTRL_GIO_MASTER_DISABLE 0x00000004 /*Blocks new Master requests */ -#define E1000_CTRL_LRST 0x00000008 /* Link reset. 0=normal,1=reset */ -#define E1000_CTRL_ASDE 0x00000020 /* Auto-speed detect enable */ -#define E1000_CTRL_SLU 0x00000040 /* Set link up (Force Link) */ -#define E1000_CTRL_ILOS 0x00000080 /* Invert Loss-Of Signal */ -#define E1000_CTRL_SPD_SEL 0x00000300 /* Speed Select Mask */ -#define E1000_CTRL_SPD_10 0x00000000 /* Force 10Mb */ -#define E1000_CTRL_SPD_100 0x00000100 /* Force 100Mb */ -#define E1000_CTRL_SPD_1000 0x00000200 /* Force 1Gb */ -#define E1000_CTRL_FRCSPD 0x00000800 /* Force Speed */ -#define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ -#define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */ -#define E1000_CTRL_LANPHYPC_VALUE 0x00020000 /* SW value of LANPHYPC */ -#define E1000_CTRL_MEHE 0x00080000 /* Memory Error Handling Enable */ -#define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ -#define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ -#define E1000_CTRL_ADVD3WUC 0x00100000 /* D3 WUC */ -#define E1000_CTRL_EN_PHY_PWR_MGMT 0x00200000 /* PHY PM enable */ -#define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ -#define E1000_CTRL_RST 0x04000000 /* Global reset */ -#define E1000_CTRL_RFCE 0x08000000 /* Receive Flow Control enable */ -#define E1000_CTRL_TFCE 0x10000000 /* Transmit flow control enable */ -#define E1000_CTRL_VME 0x40000000 /* IEEE VLAN mode enable */ -#define E1000_CTRL_PHY_RST 0x80000000 /* PHY Reset */ - -#define E1000_PCS_LCTL_FORCE_FCTRL 0x80 - -#define E1000_PCS_LSTS_AN_COMPLETE 0x10000 - -/* Device Status */ -#define E1000_STATUS_FD 0x00000001 /* Full duplex.0=half,1=full */ -#define E1000_STATUS_LU 0x00000002 /* Link up.0=no,1=link */ -#define E1000_STATUS_FUNC_MASK 0x0000000C /* PCI Function Mask */ -#define E1000_STATUS_FUNC_SHIFT 2 -#define E1000_STATUS_FUNC_1 0x00000004 /* Function 1 */ -#define E1000_STATUS_TXOFF 0x00000010 /* transmission paused */ -#define E1000_STATUS_SPEED_MASK 0x000000C0 -#define E1000_STATUS_SPEED_10 0x00000000 /* Speed 10Mb/s */ -#define E1000_STATUS_SPEED_100 0x00000040 /* Speed 100Mb/s */ -#define E1000_STATUS_SPEED_1000 0x00000080 /* Speed 1000Mb/s */ -#define E1000_STATUS_LAN_INIT_DONE 0x00000200 /* Lan Init Completion by NVM */ -#define E1000_STATUS_PHYRA 0x00000400 /* PHY Reset Asserted */ -#define E1000_STATUS_GIO_MASTER_ENABLE 0x00080000 /* Master Req status */ - -#define HALF_DUPLEX 1 -#define FULL_DUPLEX 2 - -#define ADVERTISE_10_HALF 0x0001 -#define ADVERTISE_10_FULL 0x0002 -#define ADVERTISE_100_HALF 0x0004 -#define ADVERTISE_100_FULL 0x0008 -#define ADVERTISE_1000_HALF 0x0010 /* Not used, just FYI */ -#define ADVERTISE_1000_FULL 0x0020 - -/* 1000/H is not supported, nor spec-compliant. */ -#define E1000_ALL_SPEED_DUPLEX ( \ - ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \ - ADVERTISE_100_FULL | ADVERTISE_1000_FULL) -#define E1000_ALL_NOT_GIG ( \ - ADVERTISE_10_HALF | ADVERTISE_10_FULL | ADVERTISE_100_HALF | \ - ADVERTISE_100_FULL) -#define E1000_ALL_100_SPEED (ADVERTISE_100_HALF | ADVERTISE_100_FULL) -#define E1000_ALL_10_SPEED (ADVERTISE_10_HALF | ADVERTISE_10_FULL) -#define E1000_ALL_HALF_DUPLEX (ADVERTISE_10_HALF | ADVERTISE_100_HALF) - -#define AUTONEG_ADVERTISE_SPEED_DEFAULT E1000_ALL_SPEED_DUPLEX - -/* LED Control */ -#define E1000_PHY_LED0_MODE_MASK 0x00000007 -#define E1000_PHY_LED0_IVRT 0x00000008 -#define E1000_PHY_LED0_MASK 0x0000001F - -#define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F -#define E1000_LEDCTL_LED0_MODE_SHIFT 0 -#define E1000_LEDCTL_LED0_IVRT 0x00000040 -#define E1000_LEDCTL_LED0_BLINK 0x00000080 - -#define E1000_LEDCTL_MODE_LINK_UP 0x2 -#define E1000_LEDCTL_MODE_LED_ON 0xE -#define E1000_LEDCTL_MODE_LED_OFF 0xF - -/* Transmit Descriptor bit definitions */ -#define E1000_TXD_DTYP_D 0x00100000 /* Data Descriptor */ -#define E1000_TXD_POPTS_IXSM 0x01 /* Insert IP checksum */ -#define E1000_TXD_POPTS_TXSM 0x02 /* Insert TCP/UDP checksum */ -#define E1000_TXD_CMD_EOP 0x01000000 /* End of Packet */ -#define E1000_TXD_CMD_IFCS 0x02000000 /* Insert FCS (Ethernet CRC) */ -#define E1000_TXD_CMD_IC 0x04000000 /* Insert Checksum */ -#define E1000_TXD_CMD_RS 0x08000000 /* Report Status */ -#define E1000_TXD_CMD_RPS 0x10000000 /* Report Packet Sent */ -#define E1000_TXD_CMD_DEXT 0x20000000 /* Descriptor extension (0 = legacy) */ -#define E1000_TXD_CMD_VLE 0x40000000 /* Add VLAN tag */ -#define E1000_TXD_CMD_IDE 0x80000000 /* Enable Tidv register */ -#define E1000_TXD_STAT_DD 0x00000001 /* Descriptor Done */ -#define E1000_TXD_STAT_EC 0x00000002 /* Excess Collisions */ -#define E1000_TXD_STAT_LC 0x00000004 /* Late Collisions */ -#define E1000_TXD_STAT_TU 0x00000008 /* Transmit underrun */ -#define E1000_TXD_CMD_TCP 0x01000000 /* TCP packet */ -#define E1000_TXD_CMD_IP 0x02000000 /* IP packet */ -#define E1000_TXD_CMD_TSE 0x04000000 /* TCP Seg enable */ -#define E1000_TXD_STAT_TC 0x00000004 /* Tx Underrun */ -#define E1000_TXD_EXTCMD_TSTAMP 0x00000010 /* IEEE1588 Timestamp packet */ - -/* Transmit Control */ -#define E1000_TCTL_EN 0x00000002 /* enable Tx */ -#define E1000_TCTL_PSP 0x00000008 /* pad short packets */ -#define E1000_TCTL_CT 0x00000ff0 /* collision threshold */ -#define E1000_TCTL_COLD 0x003ff000 /* collision distance */ -#define E1000_TCTL_RTLC 0x01000000 /* Re-transmit on late collision */ -#define E1000_TCTL_MULR 0x10000000 /* Multiple request support */ - -/* SerDes Control */ -#define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400 -#define E1000_SCTL_ENABLE_SERDES_LOOPBACK 0x0410 - -/* Receive Checksum Control */ -#define E1000_RXCSUM_TUOFL 0x00000200 /* TCP / UDP checksum offload */ -#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */ -#define E1000_RXCSUM_PCSD 0x00002000 /* packet checksum disabled */ - -/* Header split receive */ -#define E1000_RFCTL_NFSW_DIS 0x00000040 -#define E1000_RFCTL_NFSR_DIS 0x00000080 -#define E1000_RFCTL_ACK_DIS 0x00001000 -#define E1000_RFCTL_EXTEN 0x00008000 -#define E1000_RFCTL_IPV6_EX_DIS 0x00010000 -#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000 - -/* Collision related configuration parameters */ -#define E1000_COLLISION_THRESHOLD 15 -#define E1000_CT_SHIFT 4 -#define E1000_COLLISION_DISTANCE 63 -#define E1000_COLD_SHIFT 12 - -/* Default values for the transmit IPG register */ -#define DEFAULT_82543_TIPG_IPGT_COPPER 8 - -#define E1000_TIPG_IPGT_MASK 0x000003FF - -#define DEFAULT_82543_TIPG_IPGR1 8 -#define E1000_TIPG_IPGR1_SHIFT 10 - -#define DEFAULT_82543_TIPG_IPGR2 6 -#define DEFAULT_80003ES2LAN_TIPG_IPGR2 7 -#define E1000_TIPG_IPGR2_SHIFT 20 - -#define MAX_JUMBO_FRAME_SIZE 0x3F00 -#define E1000_TX_PTR_GAP 0x1F - -/* Extended Configuration Control and Size */ -#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP 0x00000020 -#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 -#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008 -#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 -#define E1000_EXTCNF_CTRL_GATE_PHY_CFG 0x00000080 -#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000 -#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16 -#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000 -#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT 16 - -#define E1000_PHY_CTRL_D0A_LPLU 0x00000002 -#define E1000_PHY_CTRL_NOND0A_LPLU 0x00000004 -#define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008 -#define E1000_PHY_CTRL_GBE_DISABLE 0x00000040 - -#define E1000_KABGTXD_BGSQLBIAS 0x00050000 - -/* Low Power IDLE Control */ -#define E1000_LPIC_LPIET_SHIFT 24 /* Low Power Idle Entry Time */ - -/* PBA constants */ -#define E1000_PBA_8K 0x0008 /* 8KB */ -#define E1000_PBA_16K 0x0010 /* 16KB */ - -#define E1000_PBA_RXA_MASK 0xFFFF - -#define E1000_PBS_16K E1000_PBA_16K - -/* Uncorrectable/correctable ECC Error counts and enable bits */ -#define E1000_PBECCSTS_CORR_ERR_CNT_MASK 0x000000FF -#define E1000_PBECCSTS_UNCORR_ERR_CNT_MASK 0x0000FF00 -#define E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT 8 -#define E1000_PBECCSTS_ECC_ENABLE 0x00010000 - -#define IFS_MAX 80 -#define IFS_MIN 40 -#define IFS_RATIO 4 -#define IFS_STEP 10 -#define MIN_NUM_XMITS 1000 - -/* SW Semaphore Register */ -#define E1000_SWSM_SMBI 0x00000001 /* Driver Semaphore bit */ -#define E1000_SWSM_SWESMBI 0x00000002 /* FW Semaphore bit */ -#define E1000_SWSM_DRV_LOAD 0x00000008 /* Driver Loaded Bit */ - -#define E1000_SWSM2_LOCK 0x00000002 /* Secondary driver semaphore bit */ - -/* Interrupt Cause Read */ -#define E1000_ICR_TXDW 0x00000001 /* Transmit desc written back */ -#define E1000_ICR_LSC 0x00000004 /* Link Status Change */ -#define E1000_ICR_RXSEQ 0x00000008 /* Rx sequence error */ -#define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */ -#define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */ -#define E1000_ICR_ECCER 0x00400000 /* Uncorrectable ECC Error */ -/* If this bit asserted, the driver should claim the interrupt */ -#define E1000_ICR_INT_ASSERTED 0x80000000 -#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */ -#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ -#define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */ -#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */ -#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */ - -/* PBA ECC Register */ -#define E1000_PBA_ECC_COUNTER_MASK 0xFFF00000 /* ECC counter mask */ -#define E1000_PBA_ECC_COUNTER_SHIFT 20 /* ECC counter shift value */ -#define E1000_PBA_ECC_CORR_EN 0x00000001 /* ECC correction enable */ -#define E1000_PBA_ECC_STAT_CLR 0x00000002 /* Clear ECC error counter */ -#define E1000_PBA_ECC_INT_EN 0x00000004 /* Enable ICR bit 5 for ECC */ - -/* This defines the bits that are set in the Interrupt Mask - * Set/Read Register. Each bit is documented below: - * o RXT0 = Receiver Timer Interrupt (ring 0) - * o TXDW = Transmit Descriptor Written Back - * o RXDMT0 = Receive Descriptor Minimum Threshold hit (ring 0) - * o RXSEQ = Receive Sequence Error - * o LSC = Link Status Change - */ -#define IMS_ENABLE_MASK ( \ - E1000_IMS_RXT0 | \ - E1000_IMS_TXDW | \ - E1000_IMS_RXDMT0 | \ - E1000_IMS_RXSEQ | \ - E1000_IMS_LSC) - -/* Interrupt Mask Set */ -#define E1000_IMS_TXDW E1000_ICR_TXDW /* Transmit desc written back */ -#define E1000_IMS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ -#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ -#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */ -#define E1000_IMS_ECCER E1000_ICR_ECCER /* Uncorrectable ECC Error */ -#define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */ -#define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */ -#define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */ -#define E1000_IMS_TXQ1 E1000_ICR_TXQ1 /* Tx Queue 1 Interrupt */ -#define E1000_IMS_OTHER E1000_ICR_OTHER /* Other Interrupts */ - -/* Interrupt Cause Set */ -#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */ -#define E1000_ICS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ -#define E1000_ICS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ - -/* Transmit Descriptor Control */ -#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */ -#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */ -#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */ -#define E1000_TXDCTL_GRAN 0x01000000 /* TXDCTL Granularity */ -#define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */ -#define E1000_TXDCTL_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */ -/* Enable the counting of desc. still to be processed. */ -#define E1000_TXDCTL_COUNT_DESC 0x00400000 - -/* Flow Control Constants */ -#define FLOW_CONTROL_ADDRESS_LOW 0x00C28001 -#define FLOW_CONTROL_ADDRESS_HIGH 0x00000100 -#define FLOW_CONTROL_TYPE 0x8808 - -/* 802.1q VLAN Packet Size */ -#define E1000_VLAN_FILTER_TBL_SIZE 128 /* VLAN Filter Table (4096 bits) */ - -/* Receive Address - * Number of high/low register pairs in the RAR. The RAR (Receive Address - * Registers) holds the directed and multicast addresses that we monitor. - * Technically, we have 16 spots. However, we reserve one of these spots - * (RAR[15]) for our directed address used by controllers with - * manageability enabled, allowing us room for 15 multicast addresses. - */ -#define E1000_RAR_ENTRIES 15 -#define E1000_RAH_AV 0x80000000 /* Receive descriptor valid */ -#define E1000_RAL_MAC_ADDR_LEN 4 -#define E1000_RAH_MAC_ADDR_LEN 2 - -/* Error Codes */ -#define E1000_ERR_NVM 1 -#define E1000_ERR_PHY 2 -#define E1000_ERR_CONFIG 3 -#define E1000_ERR_PARAM 4 -#define E1000_ERR_MAC_INIT 5 -#define E1000_ERR_PHY_TYPE 6 -#define E1000_ERR_RESET 9 -#define E1000_ERR_MASTER_REQUESTS_PENDING 10 -#define E1000_ERR_HOST_INTERFACE_COMMAND 11 -#define E1000_BLK_PHY_RESET 12 -#define E1000_ERR_SWFW_SYNC 13 -#define E1000_NOT_IMPLEMENTED 14 -#define E1000_ERR_INVALID_ARGUMENT 16 -#define E1000_ERR_NO_SPACE 17 -#define E1000_ERR_NVM_PBA_SECTION 18 - -/* Loop limit on how long we wait for auto-negotiation to complete */ -#define FIBER_LINK_UP_LIMIT 50 -#define COPPER_LINK_UP_LIMIT 10 -#define PHY_AUTO_NEG_LIMIT 45 -#define PHY_FORCE_LIMIT 20 -/* Number of 100 microseconds we wait for PCI Express master disable */ -#define MASTER_DISABLE_TIMEOUT 800 -/* Number of milliseconds we wait for PHY configuration done after MAC reset */ -#define PHY_CFG_TIMEOUT 100 -/* Number of 2 milliseconds we wait for acquiring MDIO ownership. */ -#define MDIO_OWNERSHIP_TIMEOUT 10 -/* Number of milliseconds for NVM auto read done after MAC reset. */ -#define AUTO_READ_DONE_TIMEOUT 10 - -/* Flow Control */ -#define E1000_FCRTH_RTH 0x0000FFF8 /* Mask Bits[15:3] for RTH */ -#define E1000_FCRTL_RTL 0x0000FFF8 /* Mask Bits[15:3] for RTL */ -#define E1000_FCRTL_XONE 0x80000000 /* Enable XON frame transmission */ - -/* Transmit Configuration Word */ -#define E1000_TXCW_FD 0x00000020 /* TXCW full duplex */ -#define E1000_TXCW_PAUSE 0x00000080 /* TXCW sym pause request */ -#define E1000_TXCW_ASM_DIR 0x00000100 /* TXCW astm pause direction */ -#define E1000_TXCW_PAUSE_MASK 0x00000180 /* TXCW pause request mask */ -#define E1000_TXCW_ANE 0x80000000 /* Auto-neg enable */ - -/* Receive Configuration Word */ -#define E1000_RXCW_CW 0x0000ffff /* RxConfigWord mask */ -#define E1000_RXCW_IV 0x08000000 /* Receive config invalid */ -#define E1000_RXCW_C 0x20000000 /* Receive config */ -#define E1000_RXCW_SYNCH 0x40000000 /* Receive config synch */ - -#define E1000_TSYNCTXCTL_VALID 0x00000001 /* Tx timestamp valid */ -#define E1000_TSYNCTXCTL_ENABLED 0x00000010 /* enable Tx timestamping */ - -#define E1000_TSYNCRXCTL_VALID 0x00000001 /* Rx timestamp valid */ -#define E1000_TSYNCRXCTL_TYPE_MASK 0x0000000E /* Rx type mask */ -#define E1000_TSYNCRXCTL_TYPE_L2_V2 0x00 -#define E1000_TSYNCRXCTL_TYPE_L4_V1 0x02 -#define E1000_TSYNCRXCTL_TYPE_L2_L4_V2 0x04 -#define E1000_TSYNCRXCTL_TYPE_ALL 0x08 -#define E1000_TSYNCRXCTL_TYPE_EVENT_V2 0x0A -#define E1000_TSYNCRXCTL_ENABLED 0x00000010 /* enable Rx timestamping */ -#define E1000_TSYNCRXCTL_SYSCFI 0x00000020 /* Sys clock frequency */ - -#define E1000_RXMTRL_PTP_V1_SYNC_MESSAGE 0x00000000 -#define E1000_RXMTRL_PTP_V1_DELAY_REQ_MESSAGE 0x00010000 - -#define E1000_RXMTRL_PTP_V2_SYNC_MESSAGE 0x00000000 -#define E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE 0x01000000 - -#define E1000_TIMINCA_INCPERIOD_SHIFT 24 -#define E1000_TIMINCA_INCVALUE_MASK 0x00FFFFFF - -/* PCI Express Control */ -#define E1000_GCR_RXD_NO_SNOOP 0x00000001 -#define E1000_GCR_RXDSCW_NO_SNOOP 0x00000002 -#define E1000_GCR_RXDSCR_NO_SNOOP 0x00000004 -#define E1000_GCR_TXD_NO_SNOOP 0x00000008 -#define E1000_GCR_TXDSCW_NO_SNOOP 0x00000010 -#define E1000_GCR_TXDSCR_NO_SNOOP 0x00000020 - -#define PCIE_NO_SNOOP_ALL (E1000_GCR_RXD_NO_SNOOP | \ - E1000_GCR_RXDSCW_NO_SNOOP | \ - E1000_GCR_RXDSCR_NO_SNOOP | \ - E1000_GCR_TXD_NO_SNOOP | \ - E1000_GCR_TXDSCW_NO_SNOOP | \ - E1000_GCR_TXDSCR_NO_SNOOP) - -/* NVM Control */ -#define E1000_EECD_SK 0x00000001 /* NVM Clock */ -#define E1000_EECD_CS 0x00000002 /* NVM Chip Select */ -#define E1000_EECD_DI 0x00000004 /* NVM Data In */ -#define E1000_EECD_DO 0x00000008 /* NVM Data Out */ -#define E1000_EECD_REQ 0x00000040 /* NVM Access Request */ -#define E1000_EECD_GNT 0x00000080 /* NVM Access Grant */ -#define E1000_EECD_PRES 0x00000100 /* NVM Present */ -#define E1000_EECD_SIZE 0x00000200 /* NVM Size (0=64 word 1=256 word) */ -/* NVM Addressing bits based on type (0-small, 1-large) */ -#define E1000_EECD_ADDR_BITS 0x00000400 -#define E1000_NVM_GRANT_ATTEMPTS 1000 /* NVM # attempts to gain grant */ -#define E1000_EECD_AUTO_RD 0x00000200 /* NVM Auto Read done */ -#define E1000_EECD_SIZE_EX_MASK 0x00007800 /* NVM Size */ -#define E1000_EECD_SIZE_EX_SHIFT 11 -#define E1000_EECD_FLUPD 0x00080000 /* Update FLASH */ -#define E1000_EECD_AUPDEN 0x00100000 /* Enable Autonomous FLASH update */ -#define E1000_EECD_SEC1VAL 0x00400000 /* Sector One Valid */ -#define E1000_EECD_SEC1VAL_VALID_MASK (E1000_EECD_AUTO_RD | E1000_EECD_PRES) - -#define E1000_NVM_RW_REG_DATA 16 /* Offset to data in NVM r/w regs */ -#define E1000_NVM_RW_REG_DONE 2 /* Offset to READ/WRITE done bit */ -#define E1000_NVM_RW_REG_START 1 /* Start operation */ -#define E1000_NVM_RW_ADDR_SHIFT 2 /* Shift to the address bits */ -#define E1000_NVM_POLL_WRITE 1 /* Flag for polling write complete */ -#define E1000_NVM_POLL_READ 0 /* Flag for polling read complete */ -#define E1000_FLASH_UPDATES 2000 - -/* NVM Word Offsets */ -#define NVM_COMPAT 0x0003 -#define NVM_ID_LED_SETTINGS 0x0004 -#define NVM_FUTURE_INIT_WORD1 0x0019 -#define NVM_COMPAT_VALID_CSUM 0x0001 -#define NVM_FUTURE_INIT_WORD1_VALID_CSUM 0x0040 - -#define NVM_INIT_CONTROL2_REG 0x000F -#define NVM_INIT_CONTROL3_PORT_B 0x0014 -#define NVM_INIT_3GIO_3 0x001A -#define NVM_INIT_CONTROL3_PORT_A 0x0024 -#define NVM_CFG 0x0012 -#define NVM_ALT_MAC_ADDR_PTR 0x0037 -#define NVM_CHECKSUM_REG 0x003F - -#define E1000_NVM_CFG_DONE_PORT_0 0x40000 /* MNG config cycle done */ -#define E1000_NVM_CFG_DONE_PORT_1 0x80000 /* ...for second port */ - -/* Mask bits for fields in Word 0x0f of the NVM */ -#define NVM_WORD0F_PAUSE_MASK 0x3000 -#define NVM_WORD0F_PAUSE 0x1000 -#define NVM_WORD0F_ASM_DIR 0x2000 - -/* Mask bits for fields in Word 0x1a of the NVM */ -#define NVM_WORD1A_ASPM_MASK 0x000C - -/* Mask bits for fields in Word 0x03 of the EEPROM */ -#define NVM_COMPAT_LOM 0x0800 - -/* length of string needed to store PBA number */ -#define E1000_PBANUM_LENGTH 11 - -/* For checksumming, the sum of all words in the NVM should equal 0xBABA. */ -#define NVM_SUM 0xBABA - -/* PBA (printed board assembly) number words */ -#define NVM_PBA_OFFSET_0 8 -#define NVM_PBA_OFFSET_1 9 -#define NVM_PBA_PTR_GUARD 0xFAFA -#define NVM_WORD_SIZE_BASE_SHIFT 6 - -/* NVM Commands - SPI */ -#define NVM_MAX_RETRY_SPI 5000 /* Max wait of 5ms, for RDY signal */ -#define NVM_READ_OPCODE_SPI 0x03 /* NVM read opcode */ -#define NVM_WRITE_OPCODE_SPI 0x02 /* NVM write opcode */ -#define NVM_A8_OPCODE_SPI 0x08 /* opcode bit-3 = address bit-8 */ -#define NVM_WREN_OPCODE_SPI 0x06 /* NVM set Write Enable latch */ -#define NVM_RDSR_OPCODE_SPI 0x05 /* NVM read Status register */ - -/* SPI NVM Status Register */ -#define NVM_STATUS_RDY_SPI 0x01 - -/* Word definitions for ID LED Settings */ -#define ID_LED_RESERVED_0000 0x0000 -#define ID_LED_RESERVED_FFFF 0xFFFF -#define ID_LED_DEFAULT ((ID_LED_OFF1_ON2 << 12) | \ - (ID_LED_OFF1_OFF2 << 8) | \ - (ID_LED_DEF1_DEF2 << 4) | \ - (ID_LED_DEF1_DEF2)) -#define ID_LED_DEF1_DEF2 0x1 -#define ID_LED_DEF1_ON2 0x2 -#define ID_LED_DEF1_OFF2 0x3 -#define ID_LED_ON1_DEF2 0x4 -#define ID_LED_ON1_ON2 0x5 -#define ID_LED_ON1_OFF2 0x6 -#define ID_LED_OFF1_DEF2 0x7 -#define ID_LED_OFF1_ON2 0x8 -#define ID_LED_OFF1_OFF2 0x9 - -#define IGP_ACTIVITY_LED_MASK 0xFFFFF0FF -#define IGP_ACTIVITY_LED_ENABLE 0x0300 -#define IGP_LED3_MODE 0x07000000 - -/* PCI/PCI-X/PCI-EX Config space */ -#define PCI_HEADER_TYPE_REGISTER 0x0E -#define PCIE_LINK_STATUS 0x12 - -#define PCI_HEADER_TYPE_MULTIFUNC 0x80 -#define PCIE_LINK_WIDTH_MASK 0x3F0 -#define PCIE_LINK_WIDTH_SHIFT 4 - -#define PHY_REVISION_MASK 0xFFFFFFF0 -#define MAX_PHY_REG_ADDRESS 0x1F /* 5 bit address bus (0-0x1F) */ -#define MAX_PHY_MULTI_PAGE_REG 0xF - -/* Bit definitions for valid PHY IDs. - * I = Integrated - * E = External - */ -#define M88E1000_E_PHY_ID 0x01410C50 -#define M88E1000_I_PHY_ID 0x01410C30 -#define M88E1011_I_PHY_ID 0x01410C20 -#define IGP01E1000_I_PHY_ID 0x02A80380 -#define M88E1111_I_PHY_ID 0x01410CC0 -#define GG82563_E_PHY_ID 0x01410CA0 -#define IGP03E1000_E_PHY_ID 0x02A80390 -#define IFE_E_PHY_ID 0x02A80330 -#define IFE_PLUS_E_PHY_ID 0x02A80320 -#define IFE_C_E_PHY_ID 0x02A80310 -#define BME1000_E_PHY_ID 0x01410CB0 -#define BME1000_E_PHY_ID_R2 0x01410CB1 -#define I82577_E_PHY_ID 0x01540050 -#define I82578_E_PHY_ID 0x004DD040 -#define I82579_E_PHY_ID 0x01540090 -#define I217_E_PHY_ID 0x015400A0 - -/* M88E1000 Specific Registers */ -#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ -#define M88E1000_PHY_SPEC_STATUS 0x11 /* PHY Specific Status Register */ -#define M88E1000_EXT_PHY_SPEC_CTRL 0x14 /* Extended PHY Specific Control */ - -#define M88E1000_PHY_PAGE_SELECT 0x1D /* Reg 29 for page number setting */ -#define M88E1000_PHY_GEN_CONTROL 0x1E /* Its meaning depends on reg 29 */ - -/* M88E1000 PHY Specific Control Register */ -#define M88E1000_PSCR_POLARITY_REVERSAL 0x0002 /* 1=Polarity Reversal enabled */ -#define M88E1000_PSCR_MDI_MANUAL_MODE 0x0000 /* MDI Crossover Mode bits 6:5 */ - /* Manual MDI configuration */ -#define M88E1000_PSCR_MDIX_MANUAL_MODE 0x0020 /* Manual MDIX configuration */ -/* 1000BASE-T: Auto crossover, 100BASE-TX/10BASE-T: MDI Mode */ -#define M88E1000_PSCR_AUTO_X_1000T 0x0040 -/* Auto crossover enabled all speeds */ -#define M88E1000_PSCR_AUTO_X_MODE 0x0060 -#define M88E1000_PSCR_ASSERT_CRS_ON_TX 0x0800 /* 1=Assert CRS on Transmit */ - -/* M88E1000 PHY Specific Status Register */ -#define M88E1000_PSSR_REV_POLARITY 0x0002 /* 1=Polarity reversed */ -#define M88E1000_PSSR_DOWNSHIFT 0x0020 /* 1=Downshifted */ -#define M88E1000_PSSR_MDIX 0x0040 /* 1=MDIX; 0=MDI */ -/* 0=<50M; 1=50-80M; 2=80-110M; 3=110-140M; 4=>140M */ -#define M88E1000_PSSR_CABLE_LENGTH 0x0380 -#define M88E1000_PSSR_SPEED 0xC000 /* Speed, bits 14:15 */ -#define M88E1000_PSSR_1000MBS 0x8000 /* 10=1000Mbs */ - -#define M88E1000_PSSR_CABLE_LENGTH_SHIFT 7 - -/* Number of times we will attempt to autonegotiate before downshifting if we - * are the master - */ -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK 0x0C00 -#define M88E1000_EPSCR_MASTER_DOWNSHIFT_1X 0x0000 -/* Number of times we will attempt to autonegotiate before downshifting if we - * are the slave - */ -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK 0x0300 -#define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X 0x0100 -#define M88E1000_EPSCR_TX_CLK_25 0x0070 /* 25 MHz TX_CLK */ - -/* M88EC018 Rev 2 specific DownShift settings */ -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK 0x0E00 -#define M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X 0x0800 - -#define I82578_EPSCR_DOWNSHIFT_ENABLE 0x0020 -#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK 0x001C - -/* BME1000 PHY Specific Control Register */ -#define BME1000_PSCR_ENABLE_DOWNSHIFT 0x0800 /* 1 = enable downshift */ - -/* Bits... - * 15-5: page - * 4-0: register offset - */ -#define GG82563_PAGE_SHIFT 5 -#define GG82563_REG(page, reg) \ - (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS)) -#define GG82563_MIN_ALT_REG 30 - -/* GG82563 Specific Registers */ -#define GG82563_PHY_SPEC_CTRL \ - GG82563_REG(0, 16) /* PHY Specific Control */ -#define GG82563_PHY_PAGE_SELECT \ - GG82563_REG(0, 22) /* Page Select */ -#define GG82563_PHY_SPEC_CTRL_2 \ - GG82563_REG(0, 26) /* PHY Specific Control 2 */ -#define GG82563_PHY_PAGE_SELECT_ALT \ - GG82563_REG(0, 29) /* Alternate Page Select */ - -#define GG82563_PHY_MAC_SPEC_CTRL \ - GG82563_REG(2, 21) /* MAC Specific Control Register */ - -#define GG82563_PHY_DSP_DISTANCE \ - GG82563_REG(5, 26) /* DSP Distance */ - -/* Page 193 - Port Control Registers */ -#define GG82563_PHY_KMRN_MODE_CTRL \ - GG82563_REG(193, 16) /* Kumeran Mode Control */ -#define GG82563_PHY_PWR_MGMT_CTRL \ - GG82563_REG(193, 20) /* Power Management Control */ - -/* Page 194 - KMRN Registers */ -#define GG82563_PHY_INBAND_CTRL \ - GG82563_REG(194, 18) /* Inband Control */ - -/* MDI Control */ -#define E1000_MDIC_REG_MASK 0x001F0000 -#define E1000_MDIC_REG_SHIFT 16 -#define E1000_MDIC_PHY_SHIFT 21 -#define E1000_MDIC_OP_WRITE 0x04000000 -#define E1000_MDIC_OP_READ 0x08000000 -#define E1000_MDIC_READY 0x10000000 -#define E1000_MDIC_ERROR 0x40000000 - -/* SerDes Control */ -#define E1000_GEN_POLL_TIMEOUT 640 - -#endif /* _E1000_DEFINES_H_ */ diff --git a/addons/e1000e/src/4.4.180/e1000.h b/addons/e1000e/src/4.4.180/e1000.h deleted file mode 100644 index 0b748d19..00000000 --- a/addons/e1000e/src/4.4.180/e1000.h +++ /dev/null @@ -1,601 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -/* Linux PRO/1000 Ethernet Driver main header file */ - -#ifndef _E1000_H_ -#define _E1000_H_ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hw.h" - -struct e1000_info; - -#define e_dbg(format, arg...) \ - netdev_dbg(hw->adapter->netdev, format, ## arg) -#define e_err(format, arg...) \ - netdev_err(adapter->netdev, format, ## arg) -#define e_info(format, arg...) \ - netdev_info(adapter->netdev, format, ## arg) -#define e_warn(format, arg...) \ - netdev_warn(adapter->netdev, format, ## arg) -#define e_notice(format, arg...) \ - netdev_notice(adapter->netdev, format, ## arg) - -/* Interrupt modes, as used by the IntMode parameter */ -#define E1000E_INT_MODE_LEGACY 0 -#define E1000E_INT_MODE_MSI 1 -#define E1000E_INT_MODE_MSIX 2 - -/* Tx/Rx descriptor defines */ -#define E1000_DEFAULT_TXD 256 -#define E1000_MAX_TXD 4096 -#define E1000_MIN_TXD 64 - -#define E1000_DEFAULT_RXD 256 -#define E1000_MAX_RXD 4096 -#define E1000_MIN_RXD 64 - -#define E1000_MIN_ITR_USECS 10 /* 100000 irq/sec */ -#define E1000_MAX_ITR_USECS 10000 /* 100 irq/sec */ - -#define E1000_FC_PAUSE_TIME 0x0680 /* 858 usec */ - -/* How many Tx Descriptors do we need to call netif_wake_queue ? */ -/* How many Rx Buffers do we bundle into one write to the hardware ? */ -#define E1000_RX_BUFFER_WRITE 16 /* Must be power of 2 */ - -#define AUTO_ALL_MODES 0 -#define E1000_EEPROM_APME 0x0400 - -#define E1000_MNG_VLAN_NONE (-1) - -#define DEFAULT_JUMBO 9234 - -/* Time to wait before putting the device into D3 if there's no link (in ms). */ -#define LINK_TIMEOUT 100 - -/* Count for polling __E1000_RESET condition every 10-20msec. - * Experimentation has shown the reset can take approximately 210msec. - */ -#define E1000_CHECK_RESET_COUNT 25 - -#define DEFAULT_RDTR 0 -#define DEFAULT_RADV 8 -#define BURST_RDTR 0x20 -#define BURST_RADV 0x20 -#define PCICFG_DESC_RING_STATUS 0xe4 -#define FLUSH_DESC_REQUIRED 0x100 - -/* in the case of WTHRESH, it appears at least the 82571/2 hardware - * writes back 4 descriptors when WTHRESH=5, and 3 descriptors when - * WTHRESH=4, so a setting of 5 gives the most efficient bus - * utilization but to avoid possible Tx stalls, set it to 1 - */ -#define E1000_TXDCTL_DMA_BURST_ENABLE \ - (E1000_TXDCTL_GRAN | /* set descriptor granularity */ \ - E1000_TXDCTL_COUNT_DESC | \ - (1 << 16) | /* wthresh must be +1 more than desired */\ - (1 << 8) | /* hthresh */ \ - 0x1f) /* pthresh */ - -#define E1000_RXDCTL_DMA_BURST_ENABLE \ - (0x01000000 | /* set descriptor granularity */ \ - (4 << 16) | /* set writeback threshold */ \ - (4 << 8) | /* set prefetch threshold */ \ - 0x20) /* set hthresh */ - -#define E1000_TIDV_FPD (1 << 31) -#define E1000_RDTR_FPD (1 << 31) - -enum e1000_boards { - board_82571, - board_82572, - board_82573, - board_82574, - board_82583, - board_80003es2lan, - board_ich8lan, - board_ich9lan, - board_ich10lan, - board_pchlan, - board_pch2lan, - board_pch_lpt, - board_pch_spt -}; - -struct e1000_ps_page { - struct page *page; - u64 dma; /* must be u64 - written to hw */ -}; - -/* wrappers around a pointer to a socket buffer, - * so a DMA handle can be stored along with the buffer - */ -struct e1000_buffer { - dma_addr_t dma; - struct sk_buff *skb; - union { - /* Tx */ - struct { - unsigned long time_stamp; - u16 length; - u16 next_to_watch; - unsigned int segs; - unsigned int bytecount; - u16 mapped_as_page; - }; - /* Rx */ - struct { - /* arrays of page information for packet split */ - struct e1000_ps_page *ps_pages; - struct page *page; - }; - }; -}; - -struct e1000_ring { - struct e1000_adapter *adapter; /* back pointer to adapter */ - void *desc; /* pointer to ring memory */ - dma_addr_t dma; /* phys address of ring */ - unsigned int size; /* length of ring in bytes */ - unsigned int count; /* number of desc. in ring */ - - u16 next_to_use; - u16 next_to_clean; - - void __iomem *head; - void __iomem *tail; - - /* array of buffer information structs */ - struct e1000_buffer *buffer_info; - - char name[IFNAMSIZ + 5]; - u32 ims_val; - u32 itr_val; - void __iomem *itr_register; - int set_itr; - - struct sk_buff *rx_skb_top; -}; - -/* PHY register snapshot values */ -struct e1000_phy_regs { - u16 bmcr; /* basic mode control register */ - u16 bmsr; /* basic mode status register */ - u16 advertise; /* auto-negotiation advertisement */ - u16 lpa; /* link partner ability register */ - u16 expansion; /* auto-negotiation expansion reg */ - u16 ctrl1000; /* 1000BASE-T control register */ - u16 stat1000; /* 1000BASE-T status register */ - u16 estatus; /* extended status register */ -}; - -/* board specific private data structure */ -struct e1000_adapter { - struct timer_list watchdog_timer; - struct timer_list phy_info_timer; - struct timer_list blink_timer; - - struct work_struct reset_task; - struct work_struct watchdog_task; - - const struct e1000_info *ei; - - unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)]; - u32 bd_number; - u32 rx_buffer_len; - u16 mng_vlan_id; - u16 link_speed; - u16 link_duplex; - u16 eeprom_vers; - - /* track device up/down/testing state */ - unsigned long state; - - /* Interrupt Throttle Rate */ - u32 itr; - u32 itr_setting; - u16 tx_itr; - u16 rx_itr; - - /* Tx - one ring per active queue */ - struct e1000_ring *tx_ring ____cacheline_aligned_in_smp; - u32 tx_fifo_limit; - - struct napi_struct napi; - - unsigned int uncorr_errors; /* uncorrectable ECC errors */ - unsigned int corr_errors; /* correctable ECC errors */ - unsigned int restart_queue; - u32 txd_cmd; - - bool detect_tx_hung; - bool tx_hang_recheck; - u8 tx_timeout_factor; - - u32 tx_int_delay; - u32 tx_abs_int_delay; - - unsigned int total_tx_bytes; - unsigned int total_tx_packets; - unsigned int total_rx_bytes; - unsigned int total_rx_packets; - - /* Tx stats */ - u64 tpt_old; - u64 colc_old; - u32 gotc; - u64 gotc_old; - u32 tx_timeout_count; - u32 tx_fifo_head; - u32 tx_head_addr; - u32 tx_fifo_size; - u32 tx_dma_failed; - u32 tx_hwtstamp_timeouts; - - /* Rx */ - bool (*clean_rx)(struct e1000_ring *ring, int *work_done, - int work_to_do) ____cacheline_aligned_in_smp; - void (*alloc_rx_buf)(struct e1000_ring *ring, int cleaned_count, - gfp_t gfp); - struct e1000_ring *rx_ring; - - u32 rx_int_delay; - u32 rx_abs_int_delay; - - /* Rx stats */ - u64 hw_csum_err; - u64 hw_csum_good; - u64 rx_hdr_split; - u32 gorc; - u64 gorc_old; - u32 alloc_rx_buff_failed; - u32 rx_dma_failed; - u32 rx_hwtstamp_cleared; - - unsigned int rx_ps_pages; - u16 rx_ps_bsize0; - u32 max_frame_size; - u32 min_frame_size; - - /* OS defined structs */ - struct net_device *netdev; - struct pci_dev *pdev; - - /* structs defined in e1000_hw.h */ - struct e1000_hw hw; - - spinlock_t stats64_lock; /* protects statistics counters */ - struct e1000_hw_stats stats; - struct e1000_phy_info phy_info; - struct e1000_phy_stats phy_stats; - - /* Snapshot of PHY registers */ - struct e1000_phy_regs phy_regs; - - struct e1000_ring test_tx_ring; - struct e1000_ring test_rx_ring; - u32 test_icr; - - u32 msg_enable; - unsigned int num_vectors; - struct msix_entry *msix_entries; - int int_mode; - u32 eiac_mask; - - u32 eeprom_wol; - u32 wol; - u32 pba; - u32 max_hw_frame_size; - - bool fc_autoneg; - - unsigned int flags; - unsigned int flags2; - struct work_struct downshift_task; - struct work_struct update_phy_task; - struct work_struct print_hang_task; - - int phy_hang_count; - - u16 tx_ring_count; - u16 rx_ring_count; - - struct hwtstamp_config hwtstamp_config; - struct delayed_work systim_overflow_work; - struct sk_buff *tx_hwtstamp_skb; - unsigned long tx_hwtstamp_start; - struct work_struct tx_hwtstamp_work; - spinlock_t systim_lock; /* protects SYSTIML/H regsters */ - struct cyclecounter cc; - struct timecounter tc; - struct ptp_clock *ptp_clock; - struct ptp_clock_info ptp_clock_info; - struct pm_qos_request pm_qos_req; - - u16 eee_advert; -}; - -struct e1000_info { - enum e1000_mac_type mac; - unsigned int flags; - unsigned int flags2; - u32 pba; - u32 max_hw_frame_size; - s32 (*get_variants)(struct e1000_adapter *); - const struct e1000_mac_operations *mac_ops; - const struct e1000_phy_operations *phy_ops; - const struct e1000_nvm_operations *nvm_ops; -}; - -s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca); - -/* The system time is maintained by a 64-bit counter comprised of the 32-bit - * SYSTIMH and SYSTIML registers. How the counter increments (and therefore - * its resolution) is based on the contents of the TIMINCA register - it - * increments every incperiod (bits 31:24) clock ticks by incvalue (bits 23:0). - * For the best accuracy, the incperiod should be as small as possible. The - * incvalue is scaled by a factor as large as possible (while still fitting - * in bits 23:0) so that relatively small clock corrections can be made. - * - * As a result, a shift of INCVALUE_SHIFT_n is used to fit a value of - * INCVALUE_n into the TIMINCA register allowing 32+8+(24-INCVALUE_SHIFT_n) - * bits to count nanoseconds leaving the rest for fractional nonseconds. - */ -#define INCVALUE_96MHz 125 -#define INCVALUE_SHIFT_96MHz 17 -#define INCPERIOD_SHIFT_96MHz 2 -#define INCPERIOD_96MHz (12 >> INCPERIOD_SHIFT_96MHz) - -#define INCVALUE_25MHz 40 -#define INCVALUE_SHIFT_25MHz 18 -#define INCPERIOD_25MHz 1 - -#define INCVALUE_24MHz 125 -#define INCVALUE_SHIFT_24MHz 14 -#define INCPERIOD_24MHz 3 - -/* Another drawback of scaling the incvalue by a large factor is the - * 64-bit SYSTIM register overflows more quickly. This is dealt with - * by simply reading the clock before it overflows. - * - * Clock ns bits Overflows after - * ~~~~~~ ~~~~~~~ ~~~~~~~~~~~~~~~ - * 96MHz 47-bit 2^(47-INCPERIOD_SHIFT_96MHz) / 10^9 / 3600 = 9.77 hrs - * 25MHz 46-bit 2^46 / 10^9 / 3600 = 19.55 hours - */ -#define E1000_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 60 * 4) -#define E1000_MAX_82574_SYSTIM_REREADS 50 -#define E1000_82574_SYSTIM_EPSILON (1ULL << 35ULL) - -/* hardware capability, feature, and workaround flags */ -#define FLAG_HAS_AMT (1 << 0) -#define FLAG_HAS_FLASH (1 << 1) -#define FLAG_HAS_HW_VLAN_FILTER (1 << 2) -#define FLAG_HAS_WOL (1 << 3) -/* reserved bit4 */ -#define FLAG_HAS_CTRLEXT_ON_LOAD (1 << 5) -#define FLAG_HAS_SWSM_ON_LOAD (1 << 6) -#define FLAG_HAS_JUMBO_FRAMES (1 << 7) -#define FLAG_READ_ONLY_NVM (1 << 8) -#define FLAG_IS_ICH (1 << 9) -#define FLAG_HAS_MSIX (1 << 10) -#define FLAG_HAS_SMART_POWER_DOWN (1 << 11) -#define FLAG_IS_QUAD_PORT_A (1 << 12) -#define FLAG_IS_QUAD_PORT (1 << 13) -#define FLAG_HAS_HW_TIMESTAMP (1 << 14) -#define FLAG_APME_IN_WUC (1 << 15) -#define FLAG_APME_IN_CTRL3 (1 << 16) -#define FLAG_APME_CHECK_PORT_B (1 << 17) -#define FLAG_DISABLE_FC_PAUSE_TIME (1 << 18) -#define FLAG_NO_WAKE_UCAST (1 << 19) -#define FLAG_MNG_PT_ENABLED (1 << 20) -#define FLAG_RESET_OVERWRITES_LAA (1 << 21) -#define FLAG_TARC_SPEED_MODE_BIT (1 << 22) -#define FLAG_TARC_SET_BIT_ZERO (1 << 23) -#define FLAG_RX_NEEDS_RESTART (1 << 24) -#define FLAG_LSC_GIG_SPEED_DROP (1 << 25) -#define FLAG_SMART_POWER_DOWN (1 << 26) -#define FLAG_MSI_ENABLED (1 << 27) -/* reserved (1 << 28) */ -#define FLAG_TSO_FORCE (1 << 29) -#define FLAG_RESTART_NOW (1 << 30) -#define FLAG_MSI_TEST_FAILED (1 << 31) - -#define FLAG2_CRC_STRIPPING (1 << 0) -#define FLAG2_HAS_PHY_WAKEUP (1 << 1) -#define FLAG2_IS_DISCARDING (1 << 2) -#define FLAG2_DISABLE_ASPM_L1 (1 << 3) -#define FLAG2_HAS_PHY_STATS (1 << 4) -#define FLAG2_HAS_EEE (1 << 5) -#define FLAG2_DMA_BURST (1 << 6) -#define FLAG2_DISABLE_ASPM_L0S (1 << 7) -#define FLAG2_DISABLE_AIM (1 << 8) -#define FLAG2_CHECK_PHY_HANG (1 << 9) -#define FLAG2_NO_DISABLE_RX (1 << 10) -#define FLAG2_PCIM2PCI_ARBITER_WA (1 << 11) -#define FLAG2_DFLT_CRC_STRIPPING (1 << 12) -#define FLAG2_CHECK_RX_HWTSTAMP (1 << 13) - -#define E1000_RX_DESC_PS(R, i) \ - (&(((union e1000_rx_desc_packet_split *)((R).desc))[i])) -#define E1000_RX_DESC_EXT(R, i) \ - (&(((union e1000_rx_desc_extended *)((R).desc))[i])) -#define E1000_GET_DESC(R, i, type) (&(((struct type *)((R).desc))[i])) -#define E1000_TX_DESC(R, i) E1000_GET_DESC(R, i, e1000_tx_desc) -#define E1000_CONTEXT_DESC(R, i) E1000_GET_DESC(R, i, e1000_context_desc) - -enum e1000_state_t { - __E1000_TESTING, - __E1000_RESETTING, - __E1000_ACCESS_SHARED_RESOURCE, - __E1000_DOWN -}; - -enum latency_range { - lowest_latency = 0, - low_latency = 1, - bulk_latency = 2, - latency_invalid = 255 -}; - -extern char e1000e_driver_name[]; -extern const char e1000e_driver_version[]; - -void e1000e_check_options(struct e1000_adapter *adapter); -void e1000e_set_ethtool_ops(struct net_device *netdev); - -int e1000e_up(struct e1000_adapter *adapter); -void e1000e_down(struct e1000_adapter *adapter, bool reset); -void e1000e_reinit_locked(struct e1000_adapter *adapter); -void e1000e_reset(struct e1000_adapter *adapter); -void e1000e_power_up_phy(struct e1000_adapter *adapter); -int e1000e_setup_rx_resources(struct e1000_ring *ring); -int e1000e_setup_tx_resources(struct e1000_ring *ring); -void e1000e_free_rx_resources(struct e1000_ring *ring); -void e1000e_free_tx_resources(struct e1000_ring *ring); -struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 *stats); -void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); -void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); -void e1000e_get_hw_control(struct e1000_adapter *adapter); -void e1000e_release_hw_control(struct e1000_adapter *adapter); -void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr); - -extern unsigned int copybreak; - -extern const struct e1000_info e1000_82571_info; -extern const struct e1000_info e1000_82572_info; -extern const struct e1000_info e1000_82573_info; -extern const struct e1000_info e1000_82574_info; -extern const struct e1000_info e1000_82583_info; -extern const struct e1000_info e1000_ich8_info; -extern const struct e1000_info e1000_ich9_info; -extern const struct e1000_info e1000_ich10_info; -extern const struct e1000_info e1000_pch_info; -extern const struct e1000_info e1000_pch2_info; -extern const struct e1000_info e1000_pch_lpt_info; -extern const struct e1000_info e1000_pch_spt_info; -extern const struct e1000_info e1000_es2_info; - -void e1000e_ptp_init(struct e1000_adapter *adapter); -void e1000e_ptp_remove(struct e1000_adapter *adapter); - -static inline s32 e1000_phy_hw_reset(struct e1000_hw *hw) -{ - return hw->phy.ops.reset(hw); -} - -static inline s32 e1e_rphy(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return hw->phy.ops.read_reg(hw, offset, data); -} - -static inline s32 e1e_rphy_locked(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return hw->phy.ops.read_reg_locked(hw, offset, data); -} - -static inline s32 e1e_wphy(struct e1000_hw *hw, u32 offset, u16 data) -{ - return hw->phy.ops.write_reg(hw, offset, data); -} - -static inline s32 e1e_wphy_locked(struct e1000_hw *hw, u32 offset, u16 data) -{ - return hw->phy.ops.write_reg_locked(hw, offset, data); -} - -void e1000e_reload_nvm_generic(struct e1000_hw *hw); - -static inline s32 e1000e_read_mac_addr(struct e1000_hw *hw) -{ - if (hw->mac.ops.read_mac_addr) - return hw->mac.ops.read_mac_addr(hw); - - return e1000_read_mac_addr_generic(hw); -} - -static inline s32 e1000_validate_nvm_checksum(struct e1000_hw *hw) -{ - return hw->nvm.ops.validate(hw); -} - -static inline s32 e1000e_update_nvm_checksum(struct e1000_hw *hw) -{ - return hw->nvm.ops.update(hw); -} - -static inline s32 e1000_read_nvm(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - return hw->nvm.ops.read(hw, offset, words, data); -} - -static inline s32 e1000_write_nvm(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - return hw->nvm.ops.write(hw, offset, words, data); -} - -static inline s32 e1000_get_phy_info(struct e1000_hw *hw) -{ - return hw->phy.ops.get_info(hw); -} - -static inline u32 __er32(struct e1000_hw *hw, unsigned long reg) -{ - return readl(hw->hw_addr + reg); -} - -#define er32(reg) __er32(hw, E1000_##reg) - -s32 __ew32_prepare(struct e1000_hw *hw); -void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val); - -#define ew32(reg, val) __ew32(hw, E1000_##reg, (val)) - -#define e1e_flush() er32(STATUS) - -#define E1000_WRITE_REG_ARRAY(a, reg, offset, value) \ - (__ew32((a), (reg + ((offset) << 2)), (value))) - -#define E1000_READ_REG_ARRAY(a, reg, offset) \ - (readl((a)->hw_addr + reg + ((offset) << 2))) - -#endif /* _E1000_H_ */ diff --git a/addons/e1000e/src/4.4.180/ethtool.c b/addons/e1000e/src/4.4.180/ethtool.c deleted file mode 100644 index 6cab1f30..00000000 --- a/addons/e1000e/src/4.4.180/ethtool.c +++ /dev/null @@ -1,2341 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -/* ethtool support for e1000 */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "e1000.h" - -enum { NETDEV_STATS, E1000_STATS }; - -struct e1000_stats { - char stat_string[ETH_GSTRING_LEN]; - int type; - int sizeof_stat; - int stat_offset; -}; - -#define E1000_STAT(str, m) { \ - .stat_string = str, \ - .type = E1000_STATS, \ - .sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \ - .stat_offset = offsetof(struct e1000_adapter, m) } -#define E1000_NETDEV_STAT(str, m) { \ - .stat_string = str, \ - .type = NETDEV_STATS, \ - .sizeof_stat = sizeof(((struct rtnl_link_stats64 *)0)->m), \ - .stat_offset = offsetof(struct rtnl_link_stats64, m) } - -static const struct e1000_stats e1000_gstrings_stats[] = { - E1000_STAT("rx_packets", stats.gprc), - E1000_STAT("tx_packets", stats.gptc), - E1000_STAT("rx_bytes", stats.gorc), - E1000_STAT("tx_bytes", stats.gotc), - E1000_STAT("rx_broadcast", stats.bprc), - E1000_STAT("tx_broadcast", stats.bptc), - E1000_STAT("rx_multicast", stats.mprc), - E1000_STAT("tx_multicast", stats.mptc), - E1000_NETDEV_STAT("rx_errors", rx_errors), - E1000_NETDEV_STAT("tx_errors", tx_errors), - E1000_NETDEV_STAT("tx_dropped", tx_dropped), - E1000_STAT("multicast", stats.mprc), - E1000_STAT("collisions", stats.colc), - E1000_NETDEV_STAT("rx_length_errors", rx_length_errors), - E1000_NETDEV_STAT("rx_over_errors", rx_over_errors), - E1000_STAT("rx_crc_errors", stats.crcerrs), - E1000_NETDEV_STAT("rx_frame_errors", rx_frame_errors), - E1000_STAT("rx_no_buffer_count", stats.rnbc), - E1000_STAT("rx_missed_errors", stats.mpc), - E1000_STAT("tx_aborted_errors", stats.ecol), - E1000_STAT("tx_carrier_errors", stats.tncrs), - E1000_NETDEV_STAT("tx_fifo_errors", tx_fifo_errors), - E1000_NETDEV_STAT("tx_heartbeat_errors", tx_heartbeat_errors), - E1000_STAT("tx_window_errors", stats.latecol), - E1000_STAT("tx_abort_late_coll", stats.latecol), - E1000_STAT("tx_deferred_ok", stats.dc), - E1000_STAT("tx_single_coll_ok", stats.scc), - E1000_STAT("tx_multi_coll_ok", stats.mcc), - E1000_STAT("tx_timeout_count", tx_timeout_count), - E1000_STAT("tx_restart_queue", restart_queue), - E1000_STAT("rx_long_length_errors", stats.roc), - E1000_STAT("rx_short_length_errors", stats.ruc), - E1000_STAT("rx_align_errors", stats.algnerrc), - E1000_STAT("tx_tcp_seg_good", stats.tsctc), - E1000_STAT("tx_tcp_seg_failed", stats.tsctfc), - E1000_STAT("rx_flow_control_xon", stats.xonrxc), - E1000_STAT("rx_flow_control_xoff", stats.xoffrxc), - E1000_STAT("tx_flow_control_xon", stats.xontxc), - E1000_STAT("tx_flow_control_xoff", stats.xofftxc), - E1000_STAT("rx_csum_offload_good", hw_csum_good), - E1000_STAT("rx_csum_offload_errors", hw_csum_err), - E1000_STAT("rx_header_split", rx_hdr_split), - E1000_STAT("alloc_rx_buff_failed", alloc_rx_buff_failed), - E1000_STAT("tx_smbus", stats.mgptc), - E1000_STAT("rx_smbus", stats.mgprc), - E1000_STAT("dropped_smbus", stats.mgpdc), - E1000_STAT("rx_dma_failed", rx_dma_failed), - E1000_STAT("tx_dma_failed", tx_dma_failed), - E1000_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared), - E1000_STAT("uncorr_ecc_errors", uncorr_errors), - E1000_STAT("corr_ecc_errors", corr_errors), - E1000_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts), -}; - -#define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats) -#define E1000_STATS_LEN (E1000_GLOBAL_STATS_LEN) -static const char e1000_gstrings_test[][ETH_GSTRING_LEN] = { - "Register test (offline)", "Eeprom test (offline)", - "Interrupt test (offline)", "Loopback test (offline)", - "Link test (on/offline)" -}; - -#define E1000_TEST_LEN ARRAY_SIZE(e1000_gstrings_test) - -static int e1000_get_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 speed; - - if (hw->phy.media_type == e1000_media_type_copper) { - ecmd->supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP); - if (hw->phy.type == e1000_phy_ife) - ecmd->supported &= ~SUPPORTED_1000baseT_Full; - ecmd->advertising = ADVERTISED_TP; - - if (hw->mac.autoneg == 1) { - ecmd->advertising |= ADVERTISED_Autoneg; - /* the e1000 autoneg seems to match ethtool nicely */ - ecmd->advertising |= hw->phy.autoneg_advertised; - } - - ecmd->port = PORT_TP; - ecmd->phy_address = hw->phy.addr; - ecmd->transceiver = XCVR_INTERNAL; - - } else { - ecmd->supported = (SUPPORTED_1000baseT_Full | - SUPPORTED_FIBRE | - SUPPORTED_Autoneg); - - ecmd->advertising = (ADVERTISED_1000baseT_Full | - ADVERTISED_FIBRE | - ADVERTISED_Autoneg); - - ecmd->port = PORT_FIBRE; - ecmd->transceiver = XCVR_EXTERNAL; - } - - speed = SPEED_UNKNOWN; - ecmd->duplex = DUPLEX_UNKNOWN; - - if (netif_running(netdev)) { - if (netif_carrier_ok(netdev)) { - speed = adapter->link_speed; - ecmd->duplex = adapter->link_duplex - 1; - } - } else if (!pm_runtime_suspended(netdev->dev.parent)) { - u32 status = er32(STATUS); - - if (status & E1000_STATUS_LU) { - if (status & E1000_STATUS_SPEED_1000) - speed = SPEED_1000; - else if (status & E1000_STATUS_SPEED_100) - speed = SPEED_100; - else - speed = SPEED_10; - - if (status & E1000_STATUS_FD) - ecmd->duplex = DUPLEX_FULL; - else - ecmd->duplex = DUPLEX_HALF; - } - } - - ethtool_cmd_speed_set(ecmd, speed); - ecmd->autoneg = ((hw->phy.media_type == e1000_media_type_fiber) || - hw->mac.autoneg) ? AUTONEG_ENABLE : AUTONEG_DISABLE; - - /* MDI-X => 2; MDI =>1; Invalid =>0 */ - if ((hw->phy.media_type == e1000_media_type_copper) && - netif_carrier_ok(netdev)) - ecmd->eth_tp_mdix = hw->phy.is_mdix ? ETH_TP_MDI_X : ETH_TP_MDI; - else - ecmd->eth_tp_mdix = ETH_TP_MDI_INVALID; - - if (hw->phy.mdix == AUTO_ALL_MODES) - ecmd->eth_tp_mdix_ctrl = ETH_TP_MDI_AUTO; - else - ecmd->eth_tp_mdix_ctrl = hw->phy.mdix; - - return 0; -} - -static int e1000_set_spd_dplx(struct e1000_adapter *adapter, u32 spd, u8 dplx) -{ - struct e1000_mac_info *mac = &adapter->hw.mac; - - mac->autoneg = 0; - - /* Make sure dplx is at most 1 bit and lsb of speed is not set - * for the switch() below to work - */ - if ((spd & 1) || (dplx & ~1)) - goto err_inval; - - /* Fiber NICs only allow 1000 gbps Full duplex */ - if ((adapter->hw.phy.media_type == e1000_media_type_fiber) && - (spd != SPEED_1000) && (dplx != DUPLEX_FULL)) { - goto err_inval; - } - - switch (spd + dplx) { - case SPEED_10 + DUPLEX_HALF: - mac->forced_speed_duplex = ADVERTISE_10_HALF; - break; - case SPEED_10 + DUPLEX_FULL: - mac->forced_speed_duplex = ADVERTISE_10_FULL; - break; - case SPEED_100 + DUPLEX_HALF: - mac->forced_speed_duplex = ADVERTISE_100_HALF; - break; - case SPEED_100 + DUPLEX_FULL: - mac->forced_speed_duplex = ADVERTISE_100_FULL; - break; - case SPEED_1000 + DUPLEX_FULL: - mac->autoneg = 1; - adapter->hw.phy.autoneg_advertised = ADVERTISE_1000_FULL; - break; - case SPEED_1000 + DUPLEX_HALF: /* not supported */ - default: - goto err_inval; - } - - /* clear MDI, MDI(-X) override is only allowed when autoneg enabled */ - adapter->hw.phy.mdix = AUTO_ALL_MODES; - - return 0; - -err_inval: - e_err("Unsupported Speed/Duplex configuration\n"); - return -EINVAL; -} - -static int e1000_set_settings(struct net_device *netdev, - struct ethtool_cmd *ecmd) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - int ret_val = 0; - - pm_runtime_get_sync(netdev->dev.parent); - - /* When SoL/IDER sessions are active, autoneg/speed/duplex - * cannot be changed - */ - if (hw->phy.ops.check_reset_block && - hw->phy.ops.check_reset_block(hw)) { - e_err("Cannot change link characteristics when SoL/IDER is active.\n"); - ret_val = -EINVAL; - goto out; - } - - /* MDI setting is only allowed when autoneg enabled because - * some hardware doesn't allow MDI setting when speed or - * duplex is forced. - */ - if (ecmd->eth_tp_mdix_ctrl) { - if (hw->phy.media_type != e1000_media_type_copper) { - ret_val = -EOPNOTSUPP; - goto out; - } - - if ((ecmd->eth_tp_mdix_ctrl != ETH_TP_MDI_AUTO) && - (ecmd->autoneg != AUTONEG_ENABLE)) { - e_err("forcing MDI/MDI-X state is not supported when link speed and/or duplex are forced\n"); - ret_val = -EINVAL; - goto out; - } - } - - while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - usleep_range(1000, 2000); - - if (ecmd->autoneg == AUTONEG_ENABLE) { - hw->mac.autoneg = 1; - if (hw->phy.media_type == e1000_media_type_fiber) - hw->phy.autoneg_advertised = ADVERTISED_1000baseT_Full | - ADVERTISED_FIBRE | ADVERTISED_Autoneg; - else - hw->phy.autoneg_advertised = ecmd->advertising | - ADVERTISED_TP | ADVERTISED_Autoneg; - ecmd->advertising = hw->phy.autoneg_advertised; - if (adapter->fc_autoneg) - hw->fc.requested_mode = e1000_fc_default; - } else { - u32 speed = ethtool_cmd_speed(ecmd); - /* calling this overrides forced MDI setting */ - if (e1000_set_spd_dplx(adapter, speed, ecmd->duplex)) { - ret_val = -EINVAL; - goto out; - } - } - - /* MDI-X => 2; MDI => 1; Auto => 3 */ - if (ecmd->eth_tp_mdix_ctrl) { - /* fix up the value for auto (3 => 0) as zero is mapped - * internally to auto - */ - if (ecmd->eth_tp_mdix_ctrl == ETH_TP_MDI_AUTO) - hw->phy.mdix = AUTO_ALL_MODES; - else - hw->phy.mdix = ecmd->eth_tp_mdix_ctrl; - } - - /* reset the link */ - if (netif_running(adapter->netdev)) { - e1000e_down(adapter, true); - e1000e_up(adapter); - } else { - e1000e_reset(adapter); - } - -out: - pm_runtime_put_sync(netdev->dev.parent); - clear_bit(__E1000_RESETTING, &adapter->state); - return ret_val; -} - -static void e1000_get_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - pause->autoneg = - (adapter->fc_autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); - - if (hw->fc.current_mode == e1000_fc_rx_pause) { - pause->rx_pause = 1; - } else if (hw->fc.current_mode == e1000_fc_tx_pause) { - pause->tx_pause = 1; - } else if (hw->fc.current_mode == e1000_fc_full) { - pause->rx_pause = 1; - pause->tx_pause = 1; - } -} - -static int e1000_set_pauseparam(struct net_device *netdev, - struct ethtool_pauseparam *pause) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - int retval = 0; - - adapter->fc_autoneg = pause->autoneg; - - while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - usleep_range(1000, 2000); - - pm_runtime_get_sync(netdev->dev.parent); - - if (adapter->fc_autoneg == AUTONEG_ENABLE) { - hw->fc.requested_mode = e1000_fc_default; - if (netif_running(adapter->netdev)) { - e1000e_down(adapter, true); - e1000e_up(adapter); - } else { - e1000e_reset(adapter); - } - } else { - if (pause->rx_pause && pause->tx_pause) - hw->fc.requested_mode = e1000_fc_full; - else if (pause->rx_pause && !pause->tx_pause) - hw->fc.requested_mode = e1000_fc_rx_pause; - else if (!pause->rx_pause && pause->tx_pause) - hw->fc.requested_mode = e1000_fc_tx_pause; - else if (!pause->rx_pause && !pause->tx_pause) - hw->fc.requested_mode = e1000_fc_none; - - hw->fc.current_mode = hw->fc.requested_mode; - - if (hw->phy.media_type == e1000_media_type_fiber) { - retval = hw->mac.ops.setup_link(hw); - /* implicit goto out */ - } else { - retval = e1000e_force_mac_fc(hw); - if (retval) - goto out; - e1000e_set_fc_watermarks(hw); - } - } - -out: - pm_runtime_put_sync(netdev->dev.parent); - clear_bit(__E1000_RESETTING, &adapter->state); - return retval; -} - -static u32 e1000_get_msglevel(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - return adapter->msg_enable; -} - -static void e1000_set_msglevel(struct net_device *netdev, u32 data) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - adapter->msg_enable = data; -} - -static int e1000_get_regs_len(struct net_device __always_unused *netdev) -{ -#define E1000_REGS_LEN 32 /* overestimate */ - return E1000_REGS_LEN * sizeof(u32); -} - -static void e1000_get_regs(struct net_device *netdev, - struct ethtool_regs *regs, void *p) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 *regs_buff = p; - u16 phy_data; - - pm_runtime_get_sync(netdev->dev.parent); - - memset(p, 0, E1000_REGS_LEN * sizeof(u32)); - - regs->version = (1 << 24) | (adapter->pdev->revision << 16) | - adapter->pdev->device; - - regs_buff[0] = er32(CTRL); - regs_buff[1] = er32(STATUS); - - regs_buff[2] = er32(RCTL); - regs_buff[3] = er32(RDLEN(0)); - regs_buff[4] = er32(RDH(0)); - regs_buff[5] = er32(RDT(0)); - regs_buff[6] = er32(RDTR); - - regs_buff[7] = er32(TCTL); - regs_buff[8] = er32(TDLEN(0)); - regs_buff[9] = er32(TDH(0)); - regs_buff[10] = er32(TDT(0)); - regs_buff[11] = er32(TIDV); - - regs_buff[12] = adapter->hw.phy.type; /* PHY type (IGP=1, M88=0) */ - - /* ethtool doesn't use anything past this point, so all this - * code is likely legacy junk for apps that may or may not exist - */ - if (hw->phy.type == e1000_phy_m88) { - e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - regs_buff[13] = (u32)phy_data; /* cable length */ - regs_buff[14] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[15] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[16] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - regs_buff[17] = (u32)phy_data; /* extended 10bt distance */ - regs_buff[18] = regs_buff[13]; /* cable polarity */ - regs_buff[19] = 0; /* Dummy (to align w/ IGP phy reg dump) */ - regs_buff[20] = regs_buff[17]; /* polarity correction */ - /* phy receive errors */ - regs_buff[22] = adapter->phy_stats.receive_errors; - regs_buff[23] = regs_buff[13]; /* mdix mode */ - } - regs_buff[21] = 0; /* was idle_errors */ - e1e_rphy(hw, MII_STAT1000, &phy_data); - regs_buff[24] = (u32)phy_data; /* phy local receiver status */ - regs_buff[25] = regs_buff[24]; /* phy remote receiver status */ - - pm_runtime_put_sync(netdev->dev.parent); -} - -static int e1000_get_eeprom_len(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - return adapter->hw.nvm.word_size * 2; -} - -static int e1000_get_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 *eeprom_buff; - int first_word; - int last_word; - int ret_val = 0; - u16 i; - - if (eeprom->len == 0) - return -EINVAL; - - eeprom->magic = adapter->pdev->vendor | (adapter->pdev->device << 16); - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - - eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1), - GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - pm_runtime_get_sync(netdev->dev.parent); - - if (hw->nvm.type == e1000_nvm_eeprom_spi) { - ret_val = e1000_read_nvm(hw, first_word, - last_word - first_word + 1, - eeprom_buff); - } else { - for (i = 0; i < last_word - first_word + 1; i++) { - ret_val = e1000_read_nvm(hw, first_word + i, 1, - &eeprom_buff[i]); - if (ret_val) - break; - } - } - - pm_runtime_put_sync(netdev->dev.parent); - - if (ret_val) { - /* a read error occurred, throw away the result */ - memset(eeprom_buff, 0xff, sizeof(u16) * - (last_word - first_word + 1)); - } else { - /* Device's eeprom is always little-endian, word addressable */ - for (i = 0; i < last_word - first_word + 1; i++) - le16_to_cpus(&eeprom_buff[i]); - } - - memcpy(bytes, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); - kfree(eeprom_buff); - - return ret_val; -} - -static int e1000_set_eeprom(struct net_device *netdev, - struct ethtool_eeprom *eeprom, u8 *bytes) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 *eeprom_buff; - void *ptr; - int max_len; - int first_word; - int last_word; - int ret_val = 0; - u16 i; - - if (eeprom->len == 0) - return -EOPNOTSUPP; - - if (eeprom->magic != - (adapter->pdev->vendor | (adapter->pdev->device << 16))) - return -EFAULT; - - if (adapter->flags & FLAG_READ_ONLY_NVM) - return -EINVAL; - - max_len = hw->nvm.word_size * 2; - - first_word = eeprom->offset >> 1; - last_word = (eeprom->offset + eeprom->len - 1) >> 1; - eeprom_buff = kmalloc(max_len, GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - ptr = (void *)eeprom_buff; - - pm_runtime_get_sync(netdev->dev.parent); - - if (eeprom->offset & 1) { - /* need read/modify/write of first changed EEPROM word */ - /* only the second byte of the word is being modified */ - ret_val = e1000_read_nvm(hw, first_word, 1, &eeprom_buff[0]); - ptr++; - } - if (((eeprom->offset + eeprom->len) & 1) && (!ret_val)) - /* need read/modify/write of last changed EEPROM word */ - /* only the first byte of the word is being modified */ - ret_val = e1000_read_nvm(hw, last_word, 1, - &eeprom_buff[last_word - first_word]); - - if (ret_val) - goto out; - - /* Device's eeprom is always little-endian, word addressable */ - for (i = 0; i < last_word - first_word + 1; i++) - le16_to_cpus(&eeprom_buff[i]); - - memcpy(ptr, bytes, eeprom->len); - - for (i = 0; i < last_word - first_word + 1; i++) - cpu_to_le16s(&eeprom_buff[i]); - - ret_val = e1000_write_nvm(hw, first_word, - last_word - first_word + 1, eeprom_buff); - - if (ret_val) - goto out; - - /* Update the checksum over the first part of the EEPROM if needed - * and flush shadow RAM for applicable controllers - */ - if ((first_word <= NVM_CHECKSUM_REG) || - (hw->mac.type == e1000_82583) || - (hw->mac.type == e1000_82574) || - (hw->mac.type == e1000_82573)) - ret_val = e1000e_update_nvm_checksum(hw); - -out: - pm_runtime_put_sync(netdev->dev.parent); - kfree(eeprom_buff); - return ret_val; -} - -static void e1000_get_drvinfo(struct net_device *netdev, - struct ethtool_drvinfo *drvinfo) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - strlcpy(drvinfo->driver, e1000e_driver_name, sizeof(drvinfo->driver)); - strlcpy(drvinfo->version, e1000e_driver_version, - sizeof(drvinfo->version)); - - /* EEPROM image version # is reported as firmware version # for - * PCI-E controllers - */ - snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), - "%d.%d-%d", - (adapter->eeprom_vers & 0xF000) >> 12, - (adapter->eeprom_vers & 0x0FF0) >> 4, - (adapter->eeprom_vers & 0x000F)); - - strlcpy(drvinfo->bus_info, pci_name(adapter->pdev), - sizeof(drvinfo->bus_info)); -} - -static void e1000_get_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - ring->rx_max_pending = E1000_MAX_RXD; - ring->tx_max_pending = E1000_MAX_TXD; - ring->rx_pending = adapter->rx_ring_count; - ring->tx_pending = adapter->tx_ring_count; -} - -static int e1000_set_ringparam(struct net_device *netdev, - struct ethtool_ringparam *ring) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_ring *temp_tx = NULL, *temp_rx = NULL; - int err = 0, size = sizeof(struct e1000_ring); - bool set_tx = false, set_rx = false; - u16 new_rx_count, new_tx_count; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - new_rx_count = clamp_t(u32, ring->rx_pending, E1000_MIN_RXD, - E1000_MAX_RXD); - new_rx_count = ALIGN(new_rx_count, REQ_RX_DESCRIPTOR_MULTIPLE); - - new_tx_count = clamp_t(u32, ring->tx_pending, E1000_MIN_TXD, - E1000_MAX_TXD); - new_tx_count = ALIGN(new_tx_count, REQ_TX_DESCRIPTOR_MULTIPLE); - - if ((new_tx_count == adapter->tx_ring_count) && - (new_rx_count == adapter->rx_ring_count)) - /* nothing to do */ - return 0; - - while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - usleep_range(1000, 2000); - - if (!netif_running(adapter->netdev)) { - /* Set counts now and allocate resources during open() */ - adapter->tx_ring->count = new_tx_count; - adapter->rx_ring->count = new_rx_count; - adapter->tx_ring_count = new_tx_count; - adapter->rx_ring_count = new_rx_count; - goto clear_reset; - } - - set_tx = (new_tx_count != adapter->tx_ring_count); - set_rx = (new_rx_count != adapter->rx_ring_count); - - /* Allocate temporary storage for ring updates */ - if (set_tx) { - temp_tx = vmalloc(size); - if (!temp_tx) { - err = -ENOMEM; - goto free_temp; - } - } - if (set_rx) { - temp_rx = vmalloc(size); - if (!temp_rx) { - err = -ENOMEM; - goto free_temp; - } - } - - pm_runtime_get_sync(netdev->dev.parent); - - e1000e_down(adapter, true); - - /* We can't just free everything and then setup again, because the - * ISRs in MSI-X mode get passed pointers to the Tx and Rx ring - * structs. First, attempt to allocate new resources... - */ - if (set_tx) { - memcpy(temp_tx, adapter->tx_ring, size); - temp_tx->count = new_tx_count; - err = e1000e_setup_tx_resources(temp_tx); - if (err) - goto err_setup; - } - if (set_rx) { - memcpy(temp_rx, adapter->rx_ring, size); - temp_rx->count = new_rx_count; - err = e1000e_setup_rx_resources(temp_rx); - if (err) - goto err_setup_rx; - } - - /* ...then free the old resources and copy back any new ring data */ - if (set_tx) { - e1000e_free_tx_resources(adapter->tx_ring); - memcpy(adapter->tx_ring, temp_tx, size); - adapter->tx_ring_count = new_tx_count; - } - if (set_rx) { - e1000e_free_rx_resources(adapter->rx_ring); - memcpy(adapter->rx_ring, temp_rx, size); - adapter->rx_ring_count = new_rx_count; - } - -err_setup_rx: - if (err && set_tx) - e1000e_free_tx_resources(temp_tx); -err_setup: - e1000e_up(adapter); - pm_runtime_put_sync(netdev->dev.parent); -free_temp: - vfree(temp_tx); - vfree(temp_rx); -clear_reset: - clear_bit(__E1000_RESETTING, &adapter->state); - return err; -} - -static bool reg_pattern_test(struct e1000_adapter *adapter, u64 *data, - int reg, int offset, u32 mask, u32 write) -{ - u32 pat, val; - static const u32 test[] = { - 0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF - }; - for (pat = 0; pat < ARRAY_SIZE(test); pat++) { - E1000_WRITE_REG_ARRAY(&adapter->hw, reg, offset, - (test[pat] & write)); - val = E1000_READ_REG_ARRAY(&adapter->hw, reg, offset); - if (val != (test[pat] & write & mask)) { - e_err("pattern test failed (reg 0x%05X): got 0x%08X expected 0x%08X\n", - reg + (offset << 2), val, - (test[pat] & write & mask)); - *data = reg; - return true; - } - } - return false; -} - -static bool reg_set_and_check(struct e1000_adapter *adapter, u64 *data, - int reg, u32 mask, u32 write) -{ - u32 val; - - __ew32(&adapter->hw, reg, write & mask); - val = __er32(&adapter->hw, reg); - if ((write & mask) != (val & mask)) { - e_err("set/check test failed (reg 0x%05X): got 0x%08X expected 0x%08X\n", - reg, (val & mask), (write & mask)); - *data = reg; - return true; - } - return false; -} - -#define REG_PATTERN_TEST_ARRAY(reg, offset, mask, write) \ - do { \ - if (reg_pattern_test(adapter, data, reg, offset, mask, write)) \ - return 1; \ - } while (0) -#define REG_PATTERN_TEST(reg, mask, write) \ - REG_PATTERN_TEST_ARRAY(reg, 0, mask, write) - -#define REG_SET_AND_CHECK(reg, mask, write) \ - do { \ - if (reg_set_and_check(adapter, data, reg, mask, write)) \ - return 1; \ - } while (0) - -static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_mac_info *mac = &adapter->hw.mac; - u32 value; - u32 before; - u32 after; - u32 i; - u32 toggle; - u32 mask; - u32 wlock_mac = 0; - - /* The status register is Read Only, so a write should fail. - * Some bits that get toggled are ignored. There are several bits - * on newer hardware that are r/w. - */ - switch (mac->type) { - case e1000_82571: - case e1000_82572: - case e1000_80003es2lan: - toggle = 0x7FFFF3FF; - break; - default: - toggle = 0x7FFFF033; - break; - } - - before = er32(STATUS); - value = (er32(STATUS) & toggle); - ew32(STATUS, toggle); - after = er32(STATUS) & toggle; - if (value != after) { - e_err("failed STATUS register test got: 0x%08X expected: 0x%08X\n", - after, value); - *data = 1; - return 1; - } - /* restore previous status */ - ew32(STATUS, before); - - if (!(adapter->flags & FLAG_IS_ICH)) { - REG_PATTERN_TEST(E1000_FCAL, 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_FCAH, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_FCT, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_VET, 0x0000FFFF, 0xFFFFFFFF); - } - - REG_PATTERN_TEST(E1000_RDTR, 0x0000FFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_RDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_RDLEN(0), 0x000FFF80, 0x000FFFFF); - REG_PATTERN_TEST(E1000_RDH(0), 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(E1000_RDT(0), 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(E1000_FCRTH, 0x0000FFF8, 0x0000FFF8); - REG_PATTERN_TEST(E1000_FCTTV, 0x0000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(E1000_TIPG, 0x3FFFFFFF, 0x3FFFFFFF); - REG_PATTERN_TEST(E1000_TDBAH(0), 0xFFFFFFFF, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_TDLEN(0), 0x000FFF80, 0x000FFFFF); - - REG_SET_AND_CHECK(E1000_RCTL, 0xFFFFFFFF, 0x00000000); - - before = ((adapter->flags & FLAG_IS_ICH) ? 0x06C3B33E : 0x06DFB3FE); - REG_SET_AND_CHECK(E1000_RCTL, before, 0x003FFFFB); - REG_SET_AND_CHECK(E1000_TCTL, 0xFFFFFFFF, 0x00000000); - - REG_SET_AND_CHECK(E1000_RCTL, before, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_RDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF); - if (!(adapter->flags & FLAG_IS_ICH)) - REG_PATTERN_TEST(E1000_TXCW, 0xC000FFFF, 0x0000FFFF); - REG_PATTERN_TEST(E1000_TDBAL(0), 0xFFFFFFF0, 0xFFFFFFFF); - REG_PATTERN_TEST(E1000_TIDV, 0x0000FFFF, 0x0000FFFF); - mask = 0x8003FFFF; - switch (mac->type) { - case e1000_ich10lan: - case e1000_pchlan: - case e1000_pch2lan: - case e1000_pch_lpt: - case e1000_pch_spt: - mask |= (1 << 18); - break; - default: - break; - } - - if ((mac->type == e1000_pch_lpt) || (mac->type == e1000_pch_spt)) - wlock_mac = (er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK) >> - E1000_FWSM_WLOCK_MAC_SHIFT; - - for (i = 0; i < mac->rar_entry_count; i++) { - if ((mac->type == e1000_pch_lpt) || - (mac->type == e1000_pch_spt)) { - /* Cannot test write-protected SHRAL[n] registers */ - if ((wlock_mac == 1) || (wlock_mac && (i > wlock_mac))) - continue; - - /* SHRAH[9] different than the others */ - if (i == 10) - mask |= (1 << 30); - else - mask &= ~(1 << 30); - } - if (mac->type == e1000_pch2lan) { - /* SHRAH[0,1,2] different than previous */ - if (i == 1) - mask &= 0xFFF4FFFF; - /* SHRAH[3] different than SHRAH[0,1,2] */ - if (i == 4) - mask |= (1 << 30); - /* RAR[1-6] owned by management engine - skipping */ - if (i > 0) - i += 6; - } - - REG_PATTERN_TEST_ARRAY(E1000_RA, ((i << 1) + 1), mask, - 0xFFFFFFFF); - /* reset index to actual value */ - if ((mac->type == e1000_pch2lan) && (i > 6)) - i -= 6; - } - - for (i = 0; i < mac->mta_reg_count; i++) - REG_PATTERN_TEST_ARRAY(E1000_MTA, i, 0xFFFFFFFF, 0xFFFFFFFF); - - *data = 0; - - return 0; -} - -static int e1000_eeprom_test(struct e1000_adapter *adapter, u64 *data) -{ - u16 temp; - u16 checksum = 0; - u16 i; - - *data = 0; - /* Read and add up the contents of the EEPROM */ - for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { - if ((e1000_read_nvm(&adapter->hw, i, 1, &temp)) < 0) { - *data = 1; - return *data; - } - checksum += temp; - } - - /* If Checksum is not Correct return error else test passed */ - if ((checksum != (u16)NVM_SUM) && !(*data)) - *data = 2; - - return *data; -} - -static irqreturn_t e1000_test_intr(int __always_unused irq, void *data) -{ - struct net_device *netdev = (struct net_device *)data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - adapter->test_icr |= er32(ICR); - - return IRQ_HANDLED; -} - -static int e1000_intr_test(struct e1000_adapter *adapter, u64 *data) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - u32 mask; - u32 shared_int = 1; - u32 irq = adapter->pdev->irq; - int i; - int ret_val = 0; - int int_mode = E1000E_INT_MODE_LEGACY; - - *data = 0; - - /* NOTE: we don't test MSI/MSI-X interrupts here, yet */ - if (adapter->int_mode == E1000E_INT_MODE_MSIX) { - int_mode = adapter->int_mode; - e1000e_reset_interrupt_capability(adapter); - adapter->int_mode = E1000E_INT_MODE_LEGACY; - e1000e_set_interrupt_capability(adapter); - } - /* Hook up test interrupt handler just for this test */ - if (!request_irq(irq, e1000_test_intr, IRQF_PROBE_SHARED, netdev->name, - netdev)) { - shared_int = 0; - } else if (request_irq(irq, e1000_test_intr, IRQF_SHARED, netdev->name, - netdev)) { - *data = 1; - ret_val = -1; - goto out; - } - e_info("testing %s interrupt\n", (shared_int ? "shared" : "unshared")); - - /* Disable all the interrupts */ - ew32(IMC, 0xFFFFFFFF); - e1e_flush(); - usleep_range(10000, 20000); - - /* Test each interrupt */ - for (i = 0; i < 10; i++) { - /* Interrupt to test */ - mask = 1 << i; - - if (adapter->flags & FLAG_IS_ICH) { - switch (mask) { - case E1000_ICR_RXSEQ: - continue; - case 0x00000100: - if (adapter->hw.mac.type == e1000_ich8lan || - adapter->hw.mac.type == e1000_ich9lan) - continue; - break; - default: - break; - } - } - - if (!shared_int) { - /* Disable the interrupt to be reported in - * the cause register and then force the same - * interrupt and see if one gets posted. If - * an interrupt was posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - ew32(IMC, mask); - ew32(ICS, mask); - e1e_flush(); - usleep_range(10000, 20000); - - if (adapter->test_icr & mask) { - *data = 3; - break; - } - } - - /* Enable the interrupt to be reported in - * the cause register and then force the same - * interrupt and see if one gets posted. If - * an interrupt was not posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - ew32(IMS, mask); - ew32(ICS, mask); - e1e_flush(); - usleep_range(10000, 20000); - - if (!(adapter->test_icr & mask)) { - *data = 4; - break; - } - - if (!shared_int) { - /* Disable the other interrupts to be reported in - * the cause register and then force the other - * interrupts and see if any get posted. If - * an interrupt was posted to the bus, the - * test failed. - */ - adapter->test_icr = 0; - ew32(IMC, ~mask & 0x00007FFF); - ew32(ICS, ~mask & 0x00007FFF); - e1e_flush(); - usleep_range(10000, 20000); - - if (adapter->test_icr) { - *data = 5; - break; - } - } - } - - /* Disable all the interrupts */ - ew32(IMC, 0xFFFFFFFF); - e1e_flush(); - usleep_range(10000, 20000); - - /* Unhook test interrupt handler */ - free_irq(irq, netdev); - -out: - if (int_mode == E1000E_INT_MODE_MSIX) { - e1000e_reset_interrupt_capability(adapter); - adapter->int_mode = int_mode; - e1000e_set_interrupt_capability(adapter); - } - - return ret_val; -} - -static void e1000_free_desc_rings(struct e1000_adapter *adapter) -{ - struct e1000_ring *tx_ring = &adapter->test_tx_ring; - struct e1000_ring *rx_ring = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - struct e1000_buffer *buffer_info; - int i; - - if (tx_ring->desc && tx_ring->buffer_info) { - for (i = 0; i < tx_ring->count; i++) { - buffer_info = &tx_ring->buffer_info[i]; - - if (buffer_info->dma) - dma_unmap_single(&pdev->dev, - buffer_info->dma, - buffer_info->length, - DMA_TO_DEVICE); - if (buffer_info->skb) - dev_kfree_skb(buffer_info->skb); - } - } - - if (rx_ring->desc && rx_ring->buffer_info) { - for (i = 0; i < rx_ring->count; i++) { - buffer_info = &rx_ring->buffer_info[i]; - - if (buffer_info->dma) - dma_unmap_single(&pdev->dev, - buffer_info->dma, - 2048, DMA_FROM_DEVICE); - if (buffer_info->skb) - dev_kfree_skb(buffer_info->skb); - } - } - - if (tx_ring->desc) { - dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, - tx_ring->dma); - tx_ring->desc = NULL; - } - if (rx_ring->desc) { - dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, - rx_ring->dma); - rx_ring->desc = NULL; - } - - kfree(tx_ring->buffer_info); - tx_ring->buffer_info = NULL; - kfree(rx_ring->buffer_info); - rx_ring->buffer_info = NULL; -} - -static int e1000_setup_desc_rings(struct e1000_adapter *adapter) -{ - struct e1000_ring *tx_ring = &adapter->test_tx_ring; - struct e1000_ring *rx_ring = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - int i; - int ret_val; - - /* Setup Tx descriptor ring and Tx buffers */ - - if (!tx_ring->count) - tx_ring->count = E1000_DEFAULT_TXD; - - tx_ring->buffer_info = kcalloc(tx_ring->count, - sizeof(struct e1000_buffer), GFP_KERNEL); - if (!tx_ring->buffer_info) { - ret_val = 1; - goto err_nomem; - } - - tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); - tx_ring->size = ALIGN(tx_ring->size, 4096); - tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size, - &tx_ring->dma, GFP_KERNEL); - if (!tx_ring->desc) { - ret_val = 2; - goto err_nomem; - } - tx_ring->next_to_use = 0; - tx_ring->next_to_clean = 0; - - ew32(TDBAL(0), ((u64)tx_ring->dma & 0x00000000FFFFFFFF)); - ew32(TDBAH(0), ((u64)tx_ring->dma >> 32)); - ew32(TDLEN(0), tx_ring->count * sizeof(struct e1000_tx_desc)); - ew32(TDH(0), 0); - ew32(TDT(0), 0); - ew32(TCTL, E1000_TCTL_PSP | E1000_TCTL_EN | E1000_TCTL_MULR | - E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT | - E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT); - - for (i = 0; i < tx_ring->count; i++) { - struct e1000_tx_desc *tx_desc = E1000_TX_DESC(*tx_ring, i); - struct sk_buff *skb; - unsigned int skb_size = 1024; - - skb = alloc_skb(skb_size, GFP_KERNEL); - if (!skb) { - ret_val = 3; - goto err_nomem; - } - skb_put(skb, skb_size); - tx_ring->buffer_info[i].skb = skb; - tx_ring->buffer_info[i].length = skb->len; - tx_ring->buffer_info[i].dma = - dma_map_single(&pdev->dev, skb->data, skb->len, - DMA_TO_DEVICE); - if (dma_mapping_error(&pdev->dev, - tx_ring->buffer_info[i].dma)) { - ret_val = 4; - goto err_nomem; - } - tx_desc->buffer_addr = cpu_to_le64(tx_ring->buffer_info[i].dma); - tx_desc->lower.data = cpu_to_le32(skb->len); - tx_desc->lower.data |= cpu_to_le32(E1000_TXD_CMD_EOP | - E1000_TXD_CMD_IFCS | - E1000_TXD_CMD_RS); - tx_desc->upper.data = 0; - } - - /* Setup Rx descriptor ring and Rx buffers */ - - if (!rx_ring->count) - rx_ring->count = E1000_DEFAULT_RXD; - - rx_ring->buffer_info = kcalloc(rx_ring->count, - sizeof(struct e1000_buffer), GFP_KERNEL); - if (!rx_ring->buffer_info) { - ret_val = 5; - goto err_nomem; - } - - rx_ring->size = rx_ring->count * sizeof(union e1000_rx_desc_extended); - rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size, - &rx_ring->dma, GFP_KERNEL); - if (!rx_ring->desc) { - ret_val = 6; - goto err_nomem; - } - rx_ring->next_to_use = 0; - rx_ring->next_to_clean = 0; - - rctl = er32(RCTL); - if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX)) - ew32(RCTL, rctl & ~E1000_RCTL_EN); - ew32(RDBAL(0), ((u64)rx_ring->dma & 0xFFFFFFFF)); - ew32(RDBAH(0), ((u64)rx_ring->dma >> 32)); - ew32(RDLEN(0), rx_ring->size); - ew32(RDH(0), 0); - ew32(RDT(0), 0); - rctl = E1000_RCTL_EN | E1000_RCTL_BAM | E1000_RCTL_SZ_2048 | - E1000_RCTL_UPE | E1000_RCTL_MPE | E1000_RCTL_LPE | - E1000_RCTL_SBP | E1000_RCTL_SECRC | - E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | - (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); - ew32(RCTL, rctl); - - for (i = 0; i < rx_ring->count; i++) { - union e1000_rx_desc_extended *rx_desc; - struct sk_buff *skb; - - skb = alloc_skb(2048 + NET_IP_ALIGN, GFP_KERNEL); - if (!skb) { - ret_val = 7; - goto err_nomem; - } - skb_reserve(skb, NET_IP_ALIGN); - rx_ring->buffer_info[i].skb = skb; - rx_ring->buffer_info[i].dma = - dma_map_single(&pdev->dev, skb->data, 2048, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, - rx_ring->buffer_info[i].dma)) { - ret_val = 8; - goto err_nomem; - } - rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); - rx_desc->read.buffer_addr = - cpu_to_le64(rx_ring->buffer_info[i].dma); - memset(skb->data, 0x00, skb->len); - } - - return 0; - -err_nomem: - e1000_free_desc_rings(adapter); - return ret_val; -} - -static void e1000_phy_disable_receiver(struct e1000_adapter *adapter) -{ - /* Write out to PHY registers 29 and 30 to disable the Receiver. */ - e1e_wphy(&adapter->hw, 29, 0x001F); - e1e_wphy(&adapter->hw, 30, 0x8FFC); - e1e_wphy(&adapter->hw, 29, 0x001A); - e1e_wphy(&adapter->hw, 30, 0x8FF0); -} - -static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl_reg = 0; - u16 phy_reg = 0; - s32 ret_val = 0; - - hw->mac.autoneg = 0; - - if (hw->phy.type == e1000_phy_ife) { - /* force 100, set loopback */ - e1e_wphy(hw, MII_BMCR, 0x6100); - - /* Now set up the MAC to the same speed/duplex as the PHY. */ - ctrl_reg = er32(CTRL); - ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ - ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ - E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ - E1000_CTRL_SPD_100 |/* Force Speed to 100 */ - E1000_CTRL_FD); /* Force Duplex to FULL */ - - ew32(CTRL, ctrl_reg); - e1e_flush(); - usleep_range(500, 1000); - - return 0; - } - - /* Specific PHY configuration for loopback */ - switch (hw->phy.type) { - case e1000_phy_m88: - /* Auto-MDI/MDIX Off */ - e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, 0x0808); - /* reset to update Auto-MDI/MDIX */ - e1e_wphy(hw, MII_BMCR, 0x9140); - /* autoneg off */ - e1e_wphy(hw, MII_BMCR, 0x8140); - break; - case e1000_phy_gg82563: - e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x1CC); - break; - case e1000_phy_bm: - /* Set Default MAC Interface speed to 1GB */ - e1e_rphy(hw, PHY_REG(2, 21), &phy_reg); - phy_reg &= ~0x0007; - phy_reg |= 0x006; - e1e_wphy(hw, PHY_REG(2, 21), phy_reg); - /* Assert SW reset for above settings to take effect */ - hw->phy.ops.commit(hw); - usleep_range(1000, 2000); - /* Force Full Duplex */ - e1e_rphy(hw, PHY_REG(769, 16), &phy_reg); - e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x000C); - /* Set Link Up (in force link) */ - e1e_rphy(hw, PHY_REG(776, 16), &phy_reg); - e1e_wphy(hw, PHY_REG(776, 16), phy_reg | 0x0040); - /* Force Link */ - e1e_rphy(hw, PHY_REG(769, 16), &phy_reg); - e1e_wphy(hw, PHY_REG(769, 16), phy_reg | 0x0040); - /* Set Early Link Enable */ - e1e_rphy(hw, PHY_REG(769, 20), &phy_reg); - e1e_wphy(hw, PHY_REG(769, 20), phy_reg | 0x0400); - break; - case e1000_phy_82577: - case e1000_phy_82578: - /* Workaround: K1 must be disabled for stable 1Gbps operation */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) { - e_err("Cannot setup 1Gbps loopback.\n"); - return ret_val; - } - e1000_configure_k1_ich8lan(hw, false); - hw->phy.ops.release(hw); - break; - case e1000_phy_82579: - /* Disable PHY energy detect power down */ - e1e_rphy(hw, PHY_REG(0, 21), &phy_reg); - e1e_wphy(hw, PHY_REG(0, 21), phy_reg & ~(1 << 3)); - /* Disable full chip energy detect */ - e1e_rphy(hw, PHY_REG(776, 18), &phy_reg); - e1e_wphy(hw, PHY_REG(776, 18), phy_reg | 1); - /* Enable loopback on the PHY */ - e1e_wphy(hw, I82577_PHY_LBK_CTRL, 0x8001); - break; - default: - break; - } - - /* force 1000, set loopback */ - e1e_wphy(hw, MII_BMCR, 0x4140); - msleep(250); - - /* Now set up the MAC to the same speed/duplex as the PHY. */ - ctrl_reg = er32(CTRL); - ctrl_reg &= ~E1000_CTRL_SPD_SEL; /* Clear the speed sel bits */ - ctrl_reg |= (E1000_CTRL_FRCSPD | /* Set the Force Speed Bit */ - E1000_CTRL_FRCDPX | /* Set the Force Duplex Bit */ - E1000_CTRL_SPD_1000 |/* Force Speed to 1000 */ - E1000_CTRL_FD); /* Force Duplex to FULL */ - - if (adapter->flags & FLAG_IS_ICH) - ctrl_reg |= E1000_CTRL_SLU; /* Set Link Up */ - - if (hw->phy.media_type == e1000_media_type_copper && - hw->phy.type == e1000_phy_m88) { - ctrl_reg |= E1000_CTRL_ILOS; /* Invert Loss of Signal */ - } else { - /* Set the ILOS bit on the fiber Nic if half duplex link is - * detected. - */ - if ((er32(STATUS) & E1000_STATUS_FD) == 0) - ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU); - } - - ew32(CTRL, ctrl_reg); - - /* Disable the receiver on the PHY so when a cable is plugged in, the - * PHY does not begin to autoneg when a cable is reconnected to the NIC. - */ - if (hw->phy.type == e1000_phy_m88) - e1000_phy_disable_receiver(adapter); - - usleep_range(500, 1000); - - return 0; -} - -static int e1000_set_82571_fiber_loopback(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl = er32(CTRL); - int link; - - /* special requirements for 82571/82572 fiber adapters */ - - /* jump through hoops to make sure link is up because serdes - * link is hardwired up - */ - ctrl |= E1000_CTRL_SLU; - ew32(CTRL, ctrl); - - /* disable autoneg */ - ctrl = er32(TXCW); - ctrl &= ~(1 << 31); - ew32(TXCW, ctrl); - - link = (er32(STATUS) & E1000_STATUS_LU); - - if (!link) { - /* set invert loss of signal */ - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_ILOS; - ew32(CTRL, ctrl); - } - - /* special write to serdes control register to enable SerDes analog - * loopback - */ - ew32(SCTL, E1000_SCTL_ENABLE_SERDES_LOOPBACK); - e1e_flush(); - usleep_range(10000, 20000); - - return 0; -} - -/* only call this for fiber/serdes connections to es2lan */ -static int e1000_set_es2lan_mac_loopback(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrlext = er32(CTRL_EXT); - u32 ctrl = er32(CTRL); - - /* save CTRL_EXT to restore later, reuse an empty variable (unused - * on mac_type 80003es2lan) - */ - adapter->tx_fifo_head = ctrlext; - - /* clear the serdes mode bits, putting the device into mac loopback */ - ctrlext &= ~E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; - ew32(CTRL_EXT, ctrlext); - - /* force speed to 1000/FD, link up */ - ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | - E1000_CTRL_SPD_1000 | E1000_CTRL_FD); - ew32(CTRL, ctrl); - - /* set mac loopback */ - ctrl = er32(RCTL); - ctrl |= E1000_RCTL_LBM_MAC; - ew32(RCTL, ctrl); - - /* set testing mode parameters (no need to reset later) */ -#define KMRNCTRLSTA_OPMODE (0x1F << 16) -#define KMRNCTRLSTA_OPMODE_1GB_FD_GMII 0x0582 - ew32(KMRNCTRLSTA, - (KMRNCTRLSTA_OPMODE | KMRNCTRLSTA_OPMODE_1GB_FD_GMII)); - - return 0; -} - -static int e1000_setup_loopback_test(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl, fext_nvm11, tarc0; - - if (hw->mac.type == e1000_pch_spt) { - fext_nvm11 = er32(FEXTNVM11); - fext_nvm11 |= E1000_FEXTNVM11_DISABLE_MULR_FIX; - ew32(FEXTNVM11, fext_nvm11); - tarc0 = er32(TARC(0)); - /* clear bits 28 & 29 (control of MULR concurrent requests) */ - tarc0 &= 0xcfffffff; - /* set bit 29 (value of MULR requests is now 2) */ - tarc0 |= 0x20000000; - ew32(TARC(0), tarc0); - } - if (hw->phy.media_type == e1000_media_type_fiber || - hw->phy.media_type == e1000_media_type_internal_serdes) { - switch (hw->mac.type) { - case e1000_80003es2lan: - return e1000_set_es2lan_mac_loopback(adapter); - case e1000_82571: - case e1000_82572: - return e1000_set_82571_fiber_loopback(adapter); - default: - rctl = er32(RCTL); - rctl |= E1000_RCTL_LBM_TCVR; - ew32(RCTL, rctl); - return 0; - } - } else if (hw->phy.media_type == e1000_media_type_copper) { - return e1000_integrated_phy_loopback(adapter); - } - - return 7; -} - -static void e1000_loopback_cleanup(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl, fext_nvm11, tarc0; - u16 phy_reg; - - rctl = er32(RCTL); - rctl &= ~(E1000_RCTL_LBM_TCVR | E1000_RCTL_LBM_MAC); - ew32(RCTL, rctl); - - switch (hw->mac.type) { - case e1000_pch_spt: - fext_nvm11 = er32(FEXTNVM11); - fext_nvm11 &= ~E1000_FEXTNVM11_DISABLE_MULR_FIX; - ew32(FEXTNVM11, fext_nvm11); - tarc0 = er32(TARC(0)); - /* clear bits 28 & 29 (control of MULR concurrent requests) */ - /* set bit 29 (value of MULR requests is now 0) */ - tarc0 &= 0xcfffffff; - ew32(TARC(0), tarc0); - /* fall through */ - case e1000_80003es2lan: - if (hw->phy.media_type == e1000_media_type_fiber || - hw->phy.media_type == e1000_media_type_internal_serdes) { - /* restore CTRL_EXT, stealing space from tx_fifo_head */ - ew32(CTRL_EXT, adapter->tx_fifo_head); - adapter->tx_fifo_head = 0; - } - /* fall through */ - case e1000_82571: - case e1000_82572: - if (hw->phy.media_type == e1000_media_type_fiber || - hw->phy.media_type == e1000_media_type_internal_serdes) { - ew32(SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); - e1e_flush(); - usleep_range(10000, 20000); - break; - } - /* Fall Through */ - default: - hw->mac.autoneg = 1; - if (hw->phy.type == e1000_phy_gg82563) - e1e_wphy(hw, GG82563_PHY_KMRN_MODE_CTRL, 0x180); - e1e_rphy(hw, MII_BMCR, &phy_reg); - if (phy_reg & BMCR_LOOPBACK) { - phy_reg &= ~BMCR_LOOPBACK; - e1e_wphy(hw, MII_BMCR, phy_reg); - if (hw->phy.ops.commit) - hw->phy.ops.commit(hw); - } - break; - } -} - -static void e1000_create_lbtest_frame(struct sk_buff *skb, - unsigned int frame_size) -{ - memset(skb->data, 0xFF, frame_size); - frame_size &= ~1; - memset(&skb->data[frame_size / 2], 0xAA, frame_size / 2 - 1); - memset(&skb->data[frame_size / 2 + 10], 0xBE, 1); - memset(&skb->data[frame_size / 2 + 12], 0xAF, 1); -} - -static int e1000_check_lbtest_frame(struct sk_buff *skb, - unsigned int frame_size) -{ - frame_size &= ~1; - if (*(skb->data + 3) == 0xFF) - if ((*(skb->data + frame_size / 2 + 10) == 0xBE) && - (*(skb->data + frame_size / 2 + 12) == 0xAF)) - return 0; - return 13; -} - -static int e1000_run_loopback_test(struct e1000_adapter *adapter) -{ - struct e1000_ring *tx_ring = &adapter->test_tx_ring; - struct e1000_ring *rx_ring = &adapter->test_rx_ring; - struct pci_dev *pdev = adapter->pdev; - struct e1000_hw *hw = &adapter->hw; - struct e1000_buffer *buffer_info; - int i, j, k, l; - int lc; - int good_cnt; - int ret_val = 0; - unsigned long time; - - ew32(RDT(0), rx_ring->count - 1); - - /* Calculate the loop count based on the largest descriptor ring - * The idea is to wrap the largest ring a number of times using 64 - * send/receive pairs during each loop - */ - - if (rx_ring->count <= tx_ring->count) - lc = ((tx_ring->count / 64) * 2) + 1; - else - lc = ((rx_ring->count / 64) * 2) + 1; - - k = 0; - l = 0; - /* loop count loop */ - for (j = 0; j <= lc; j++) { - /* send the packets */ - for (i = 0; i < 64; i++) { - buffer_info = &tx_ring->buffer_info[k]; - - e1000_create_lbtest_frame(buffer_info->skb, 1024); - dma_sync_single_for_device(&pdev->dev, - buffer_info->dma, - buffer_info->length, - DMA_TO_DEVICE); - k++; - if (k == tx_ring->count) - k = 0; - } - ew32(TDT(0), k); - e1e_flush(); - msleep(200); - time = jiffies; /* set the start time for the receive */ - good_cnt = 0; - /* receive the sent packets */ - do { - buffer_info = &rx_ring->buffer_info[l]; - - dma_sync_single_for_cpu(&pdev->dev, - buffer_info->dma, 2048, - DMA_FROM_DEVICE); - - ret_val = e1000_check_lbtest_frame(buffer_info->skb, - 1024); - if (!ret_val) - good_cnt++; - l++; - if (l == rx_ring->count) - l = 0; - /* time + 20 msecs (200 msecs on 2.4) is more than - * enough time to complete the receives, if it's - * exceeded, break and error off - */ - } while ((good_cnt < 64) && !time_after(jiffies, time + 20)); - if (good_cnt != 64) { - ret_val = 13; /* ret_val is the same as mis-compare */ - break; - } - if (time_after(jiffies, time + 20)) { - ret_val = 14; /* error code for time out error */ - break; - } - } - return ret_val; -} - -static int e1000_loopback_test(struct e1000_adapter *adapter, u64 *data) -{ - struct e1000_hw *hw = &adapter->hw; - - /* PHY loopback cannot be performed if SoL/IDER sessions are active */ - if (hw->phy.ops.check_reset_block && - hw->phy.ops.check_reset_block(hw)) { - e_err("Cannot do PHY loopback test when SoL/IDER is active.\n"); - *data = 0; - goto out; - } - - *data = e1000_setup_desc_rings(adapter); - if (*data) - goto out; - - *data = e1000_setup_loopback_test(adapter); - if (*data) - goto err_loopback; - - *data = e1000_run_loopback_test(adapter); - e1000_loopback_cleanup(adapter); - -err_loopback: - e1000_free_desc_rings(adapter); -out: - return *data; -} - -static int e1000_link_test(struct e1000_adapter *adapter, u64 *data) -{ - struct e1000_hw *hw = &adapter->hw; - - *data = 0; - if (hw->phy.media_type == e1000_media_type_internal_serdes) { - int i = 0; - - hw->mac.serdes_has_link = false; - - /* On some blade server designs, link establishment - * could take as long as 2-3 minutes - */ - do { - hw->mac.ops.check_for_link(hw); - if (hw->mac.serdes_has_link) - return *data; - msleep(20); - } while (i++ < 3750); - - *data = 1; - } else { - hw->mac.ops.check_for_link(hw); - if (hw->mac.autoneg) - /* On some Phy/switch combinations, link establishment - * can take a few seconds more than expected. - */ - msleep_interruptible(5000); - - if (!(er32(STATUS) & E1000_STATUS_LU)) - *data = 1; - } - return *data; -} - -static int e1000e_get_sset_count(struct net_device __always_unused *netdev, - int sset) -{ - switch (sset) { - case ETH_SS_TEST: - return E1000_TEST_LEN; - case ETH_SS_STATS: - return E1000_STATS_LEN; - default: - return -EOPNOTSUPP; - } -} - -static void e1000_diag_test(struct net_device *netdev, - struct ethtool_test *eth_test, u64 *data) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - u16 autoneg_advertised; - u8 forced_speed_duplex; - u8 autoneg; - bool if_running = netif_running(netdev); - - pm_runtime_get_sync(netdev->dev.parent); - - set_bit(__E1000_TESTING, &adapter->state); - - if (!if_running) { - /* Get control of and reset hardware */ - if (adapter->flags & FLAG_HAS_AMT) - e1000e_get_hw_control(adapter); - - e1000e_power_up_phy(adapter); - - adapter->hw.phy.autoneg_wait_to_complete = 1; - e1000e_reset(adapter); - adapter->hw.phy.autoneg_wait_to_complete = 0; - } - - if (eth_test->flags == ETH_TEST_FL_OFFLINE) { - /* Offline tests */ - - /* save speed, duplex, autoneg settings */ - autoneg_advertised = adapter->hw.phy.autoneg_advertised; - forced_speed_duplex = adapter->hw.mac.forced_speed_duplex; - autoneg = adapter->hw.mac.autoneg; - - e_info("offline testing starting\n"); - - if (if_running) - /* indicate we're in test mode */ - dev_close(netdev); - - if (e1000_reg_test(adapter, &data[0])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000e_reset(adapter); - if (e1000_eeprom_test(adapter, &data[1])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000e_reset(adapter); - if (e1000_intr_test(adapter, &data[2])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - e1000e_reset(adapter); - if (e1000_loopback_test(adapter, &data[3])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - /* force this routine to wait until autoneg complete/timeout */ - adapter->hw.phy.autoneg_wait_to_complete = 1; - e1000e_reset(adapter); - adapter->hw.phy.autoneg_wait_to_complete = 0; - - if (e1000_link_test(adapter, &data[4])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - /* restore speed, duplex, autoneg settings */ - adapter->hw.phy.autoneg_advertised = autoneg_advertised; - adapter->hw.mac.forced_speed_duplex = forced_speed_duplex; - adapter->hw.mac.autoneg = autoneg; - e1000e_reset(adapter); - - clear_bit(__E1000_TESTING, &adapter->state); - if (if_running) - dev_open(netdev); - } else { - /* Online tests */ - - e_info("online testing starting\n"); - - /* register, eeprom, intr and loopback tests not run online */ - data[0] = 0; - data[1] = 0; - data[2] = 0; - data[3] = 0; - - if (e1000_link_test(adapter, &data[4])) - eth_test->flags |= ETH_TEST_FL_FAILED; - - clear_bit(__E1000_TESTING, &adapter->state); - } - - if (!if_running) { - e1000e_reset(adapter); - - if (adapter->flags & FLAG_HAS_AMT) - e1000e_release_hw_control(adapter); - } - - msleep_interruptible(4 * 1000); - - pm_runtime_put_sync(netdev->dev.parent); -} - -static void e1000_get_wol(struct net_device *netdev, - struct ethtool_wolinfo *wol) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - wol->supported = 0; - wol->wolopts = 0; - - if (!(adapter->flags & FLAG_HAS_WOL) || - !device_can_wakeup(&adapter->pdev->dev)) - return; - - wol->supported = WAKE_UCAST | WAKE_MCAST | - WAKE_BCAST | WAKE_MAGIC | WAKE_PHY; - - /* apply any specific unsupported masks here */ - if (adapter->flags & FLAG_NO_WAKE_UCAST) { - wol->supported &= ~WAKE_UCAST; - - if (adapter->wol & E1000_WUFC_EX) - e_err("Interface does not support directed (unicast) frame wake-up packets\n"); - } - - if (adapter->wol & E1000_WUFC_EX) - wol->wolopts |= WAKE_UCAST; - if (adapter->wol & E1000_WUFC_MC) - wol->wolopts |= WAKE_MCAST; - if (adapter->wol & E1000_WUFC_BC) - wol->wolopts |= WAKE_BCAST; - if (adapter->wol & E1000_WUFC_MAG) - wol->wolopts |= WAKE_MAGIC; - if (adapter->wol & E1000_WUFC_LNKC) - wol->wolopts |= WAKE_PHY; -} - -static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (!(adapter->flags & FLAG_HAS_WOL) || - !device_can_wakeup(&adapter->pdev->dev) || - (wol->wolopts & ~(WAKE_UCAST | WAKE_MCAST | WAKE_BCAST | - WAKE_MAGIC | WAKE_PHY))) - return -EOPNOTSUPP; - - /* these settings will always override what we currently have */ - adapter->wol = 0; - - if (wol->wolopts & WAKE_UCAST) - adapter->wol |= E1000_WUFC_EX; - if (wol->wolopts & WAKE_MCAST) - adapter->wol |= E1000_WUFC_MC; - if (wol->wolopts & WAKE_BCAST) - adapter->wol |= E1000_WUFC_BC; - if (wol->wolopts & WAKE_MAGIC) - adapter->wol |= E1000_WUFC_MAG; - if (wol->wolopts & WAKE_PHY) - adapter->wol |= E1000_WUFC_LNKC; - - device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); - - return 0; -} - -static int e1000_set_phys_id(struct net_device *netdev, - enum ethtool_phys_id_state state) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - switch (state) { - case ETHTOOL_ID_ACTIVE: - pm_runtime_get_sync(netdev->dev.parent); - - if (!hw->mac.ops.blink_led) - return 2; /* cycle on/off twice per second */ - - hw->mac.ops.blink_led(hw); - break; - - case ETHTOOL_ID_INACTIVE: - if (hw->phy.type == e1000_phy_ife) - e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0); - hw->mac.ops.led_off(hw); - hw->mac.ops.cleanup_led(hw); - pm_runtime_put_sync(netdev->dev.parent); - break; - - case ETHTOOL_ID_ON: - hw->mac.ops.led_on(hw); - break; - - case ETHTOOL_ID_OFF: - hw->mac.ops.led_off(hw); - break; - } - - return 0; -} - -static int e1000_get_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (adapter->itr_setting <= 4) - ec->rx_coalesce_usecs = adapter->itr_setting; - else - ec->rx_coalesce_usecs = 1000000 / adapter->itr_setting; - - return 0; -} - -static int e1000_set_coalesce(struct net_device *netdev, - struct ethtool_coalesce *ec) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - if ((ec->rx_coalesce_usecs > E1000_MAX_ITR_USECS) || - ((ec->rx_coalesce_usecs > 4) && - (ec->rx_coalesce_usecs < E1000_MIN_ITR_USECS)) || - (ec->rx_coalesce_usecs == 2)) - return -EINVAL; - - if (ec->rx_coalesce_usecs == 4) { - adapter->itr_setting = 4; - adapter->itr = adapter->itr_setting; - } else if (ec->rx_coalesce_usecs <= 3) { - adapter->itr = 20000; - adapter->itr_setting = ec->rx_coalesce_usecs; - } else { - adapter->itr = (1000000 / ec->rx_coalesce_usecs); - adapter->itr_setting = adapter->itr & ~3; - } - - pm_runtime_get_sync(netdev->dev.parent); - - if (adapter->itr_setting != 0) - e1000e_write_itr(adapter, adapter->itr); - else - e1000e_write_itr(adapter, 0); - - pm_runtime_put_sync(netdev->dev.parent); - - return 0; -} - -static int e1000_nway_reset(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (!netif_running(netdev)) - return -EAGAIN; - - if (!adapter->hw.mac.autoneg) - return -EINVAL; - - pm_runtime_get_sync(netdev->dev.parent); - e1000e_reinit_locked(adapter); - pm_runtime_put_sync(netdev->dev.parent); - - return 0; -} - -static void e1000_get_ethtool_stats(struct net_device *netdev, - struct ethtool_stats __always_unused *stats, - u64 *data) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct rtnl_link_stats64 net_stats; - int i; - char *p = NULL; - - pm_runtime_get_sync(netdev->dev.parent); - - e1000e_get_stats64(netdev, &net_stats); - - pm_runtime_put_sync(netdev->dev.parent); - - for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { - switch (e1000_gstrings_stats[i].type) { - case NETDEV_STATS: - p = (char *)&net_stats + - e1000_gstrings_stats[i].stat_offset; - break; - case E1000_STATS: - p = (char *)adapter + - e1000_gstrings_stats[i].stat_offset; - break; - default: - data[i] = 0; - continue; - } - - data[i] = (e1000_gstrings_stats[i].sizeof_stat == - sizeof(u64)) ? *(u64 *)p : *(u32 *)p; - } -} - -static void e1000_get_strings(struct net_device __always_unused *netdev, - u32 stringset, u8 *data) -{ - u8 *p = data; - int i; - - switch (stringset) { - case ETH_SS_TEST: - memcpy(data, e1000_gstrings_test, sizeof(e1000_gstrings_test)); - break; - case ETH_SS_STATS: - for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) { - memcpy(p, e1000_gstrings_stats[i].stat_string, - ETH_GSTRING_LEN); - p += ETH_GSTRING_LEN; - } - break; - } -} - -static int e1000_get_rxnfc(struct net_device *netdev, - struct ethtool_rxnfc *info, - u32 __always_unused *rule_locs) -{ - info->data = 0; - - switch (info->cmd) { - case ETHTOOL_GRXFH: { - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 mrqc; - - pm_runtime_get_sync(netdev->dev.parent); - mrqc = er32(MRQC); - pm_runtime_put_sync(netdev->dev.parent); - - if (!(mrqc & E1000_MRQC_RSS_FIELD_MASK)) - return 0; - - switch (info->flow_type) { - case TCP_V4_FLOW: - if (mrqc & E1000_MRQC_RSS_FIELD_IPV4_TCP) - info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fall through */ - case UDP_V4_FLOW: - case SCTP_V4_FLOW: - case AH_ESP_V4_FLOW: - case IPV4_FLOW: - if (mrqc & E1000_MRQC_RSS_FIELD_IPV4) - info->data |= RXH_IP_SRC | RXH_IP_DST; - break; - case TCP_V6_FLOW: - if (mrqc & E1000_MRQC_RSS_FIELD_IPV6_TCP) - info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fall through */ - case UDP_V6_FLOW: - case SCTP_V6_FLOW: - case AH_ESP_V6_FLOW: - case IPV6_FLOW: - if (mrqc & E1000_MRQC_RSS_FIELD_IPV6) - info->data |= RXH_IP_SRC | RXH_IP_DST; - break; - default: - break; - } - return 0; - } - default: - return -EOPNOTSUPP; - } -} - -static int e1000e_get_eee(struct net_device *netdev, struct ethtool_eee *edata) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 cap_addr, lpa_addr, pcs_stat_addr, phy_data; - u32 ret_val; - - if (!(adapter->flags2 & FLAG2_HAS_EEE)) - return -EOPNOTSUPP; - - switch (hw->phy.type) { - case e1000_phy_82579: - cap_addr = I82579_EEE_CAPABILITY; - lpa_addr = I82579_EEE_LP_ABILITY; - pcs_stat_addr = I82579_EEE_PCS_STATUS; - break; - case e1000_phy_i217: - cap_addr = I217_EEE_CAPABILITY; - lpa_addr = I217_EEE_LP_ABILITY; - pcs_stat_addr = I217_EEE_PCS_STATUS; - break; - default: - return -EOPNOTSUPP; - } - - pm_runtime_get_sync(netdev->dev.parent); - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) { - pm_runtime_put_sync(netdev->dev.parent); - return -EBUSY; - } - - /* EEE Capability */ - ret_val = e1000_read_emi_reg_locked(hw, cap_addr, &phy_data); - if (ret_val) - goto release; - edata->supported = mmd_eee_cap_to_ethtool_sup_t(phy_data); - - /* EEE Advertised */ - edata->advertised = mmd_eee_adv_to_ethtool_adv_t(adapter->eee_advert); - - /* EEE Link Partner Advertised */ - ret_val = e1000_read_emi_reg_locked(hw, lpa_addr, &phy_data); - if (ret_val) - goto release; - edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data); - - /* EEE PCS Status */ - ret_val = e1000_read_emi_reg_locked(hw, pcs_stat_addr, &phy_data); - if (ret_val) - goto release; - if (hw->phy.type == e1000_phy_82579) - phy_data <<= 8; - - /* Result of the EEE auto negotiation - there is no register that - * has the status of the EEE negotiation so do a best-guess based - * on whether Tx or Rx LPI indications have been received. - */ - if (phy_data & (E1000_EEE_TX_LPI_RCVD | E1000_EEE_RX_LPI_RCVD)) - edata->eee_active = true; - - edata->eee_enabled = !hw->dev_spec.ich8lan.eee_disable; - edata->tx_lpi_enabled = true; - edata->tx_lpi_timer = er32(LPIC) >> E1000_LPIC_LPIET_SHIFT; - -release: - hw->phy.ops.release(hw); - if (ret_val) - ret_val = -ENODATA; - - pm_runtime_put_sync(netdev->dev.parent); - - return ret_val; -} - -static int e1000e_set_eee(struct net_device *netdev, struct ethtool_eee *edata) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct ethtool_eee eee_curr; - s32 ret_val; - - ret_val = e1000e_get_eee(netdev, &eee_curr); - if (ret_val) - return ret_val; - - if (eee_curr.tx_lpi_enabled != edata->tx_lpi_enabled) { - e_err("Setting EEE tx-lpi is not supported\n"); - return -EINVAL; - } - - if (eee_curr.tx_lpi_timer != edata->tx_lpi_timer) { - e_err("Setting EEE Tx LPI timer is not supported\n"); - return -EINVAL; - } - - if (edata->advertised & ~(ADVERTISE_100_FULL | ADVERTISE_1000_FULL)) { - e_err("EEE advertisement supports only 100TX and/or 1000T full-duplex\n"); - return -EINVAL; - } - - adapter->eee_advert = ethtool_adv_to_mmd_eee_adv_t(edata->advertised); - - hw->dev_spec.ich8lan.eee_disable = !edata->eee_enabled; - - pm_runtime_get_sync(netdev->dev.parent); - - /* reset the link */ - if (netif_running(netdev)) - e1000e_reinit_locked(adapter); - else - e1000e_reset(adapter); - - pm_runtime_put_sync(netdev->dev.parent); - - return 0; -} - -static int e1000e_get_ts_info(struct net_device *netdev, - struct ethtool_ts_info *info) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - ethtool_op_get_ts_info(netdev, info); - - if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP)) - return 0; - - info->so_timestamping |= (SOF_TIMESTAMPING_TX_HARDWARE | - SOF_TIMESTAMPING_RX_HARDWARE | - SOF_TIMESTAMPING_RAW_HARDWARE); - - info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON); - - info->rx_filters = ((1 << HWTSTAMP_FILTER_NONE) | - (1 << HWTSTAMP_FILTER_PTP_V1_L4_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_PTP_V2_L2_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_PTP_V2_EVENT) | - (1 << HWTSTAMP_FILTER_PTP_V2_SYNC) | - (1 << HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | - (1 << HWTSTAMP_FILTER_ALL)); - - if (adapter->ptp_clock) - info->phc_index = ptp_clock_index(adapter->ptp_clock); - - return 0; -} - -static const struct ethtool_ops e1000_ethtool_ops = { - .get_settings = e1000_get_settings, - .set_settings = e1000_set_settings, - .get_drvinfo = e1000_get_drvinfo, - .get_regs_len = e1000_get_regs_len, - .get_regs = e1000_get_regs, - .get_wol = e1000_get_wol, - .set_wol = e1000_set_wol, - .get_msglevel = e1000_get_msglevel, - .set_msglevel = e1000_set_msglevel, - .nway_reset = e1000_nway_reset, - .get_link = ethtool_op_get_link, - .get_eeprom_len = e1000_get_eeprom_len, - .get_eeprom = e1000_get_eeprom, - .set_eeprom = e1000_set_eeprom, - .get_ringparam = e1000_get_ringparam, - .set_ringparam = e1000_set_ringparam, - .get_pauseparam = e1000_get_pauseparam, - .set_pauseparam = e1000_set_pauseparam, - .self_test = e1000_diag_test, - .get_strings = e1000_get_strings, - .set_phys_id = e1000_set_phys_id, - .get_ethtool_stats = e1000_get_ethtool_stats, - .get_sset_count = e1000e_get_sset_count, - .get_coalesce = e1000_get_coalesce, - .set_coalesce = e1000_set_coalesce, - .get_rxnfc = e1000_get_rxnfc, - .get_ts_info = e1000e_get_ts_info, - .get_eee = e1000e_get_eee, - .set_eee = e1000e_set_eee, -}; - -void e1000e_set_ethtool_ops(struct net_device *netdev) -{ - netdev->ethtool_ops = &e1000_ethtool_ops; -} diff --git a/addons/e1000e/src/4.4.180/hw.h b/addons/e1000e/src/4.4.180/hw.h deleted file mode 100644 index c9da4654..00000000 --- a/addons/e1000e/src/4.4.180/hw.h +++ /dev/null @@ -1,698 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#ifndef _E1000_HW_H_ -#define _E1000_HW_H_ - -#include "regs.h" -#include "defines.h" - -struct e1000_hw; - -#define E1000_DEV_ID_82571EB_COPPER 0x105E -#define E1000_DEV_ID_82571EB_FIBER 0x105F -#define E1000_DEV_ID_82571EB_SERDES 0x1060 -#define E1000_DEV_ID_82571EB_QUAD_COPPER 0x10A4 -#define E1000_DEV_ID_82571PT_QUAD_COPPER 0x10D5 -#define E1000_DEV_ID_82571EB_QUAD_FIBER 0x10A5 -#define E1000_DEV_ID_82571EB_QUAD_COPPER_LP 0x10BC -#define E1000_DEV_ID_82571EB_SERDES_DUAL 0x10D9 -#define E1000_DEV_ID_82571EB_SERDES_QUAD 0x10DA -#define E1000_DEV_ID_82572EI_COPPER 0x107D -#define E1000_DEV_ID_82572EI_FIBER 0x107E -#define E1000_DEV_ID_82572EI_SERDES 0x107F -#define E1000_DEV_ID_82572EI 0x10B9 -#define E1000_DEV_ID_82573E 0x108B -#define E1000_DEV_ID_82573E_IAMT 0x108C -#define E1000_DEV_ID_82573L 0x109A -#define E1000_DEV_ID_82574L 0x10D3 -#define E1000_DEV_ID_82574LA 0x10F6 -#define E1000_DEV_ID_82583V 0x150C -#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT 0x1096 -#define E1000_DEV_ID_80003ES2LAN_SERDES_DPT 0x1098 -#define E1000_DEV_ID_80003ES2LAN_COPPER_SPT 0x10BA -#define E1000_DEV_ID_80003ES2LAN_SERDES_SPT 0x10BB -#define E1000_DEV_ID_ICH8_82567V_3 0x1501 -#define E1000_DEV_ID_ICH8_IGP_M_AMT 0x1049 -#define E1000_DEV_ID_ICH8_IGP_AMT 0x104A -#define E1000_DEV_ID_ICH8_IGP_C 0x104B -#define E1000_DEV_ID_ICH8_IFE 0x104C -#define E1000_DEV_ID_ICH8_IFE_GT 0x10C4 -#define E1000_DEV_ID_ICH8_IFE_G 0x10C5 -#define E1000_DEV_ID_ICH8_IGP_M 0x104D -#define E1000_DEV_ID_ICH9_IGP_AMT 0x10BD -#define E1000_DEV_ID_ICH9_BM 0x10E5 -#define E1000_DEV_ID_ICH9_IGP_M_AMT 0x10F5 -#define E1000_DEV_ID_ICH9_IGP_M 0x10BF -#define E1000_DEV_ID_ICH9_IGP_M_V 0x10CB -#define E1000_DEV_ID_ICH9_IGP_C 0x294C -#define E1000_DEV_ID_ICH9_IFE 0x10C0 -#define E1000_DEV_ID_ICH9_IFE_GT 0x10C3 -#define E1000_DEV_ID_ICH9_IFE_G 0x10C2 -#define E1000_DEV_ID_ICH10_R_BM_LM 0x10CC -#define E1000_DEV_ID_ICH10_R_BM_LF 0x10CD -#define E1000_DEV_ID_ICH10_R_BM_V 0x10CE -#define E1000_DEV_ID_ICH10_D_BM_LM 0x10DE -#define E1000_DEV_ID_ICH10_D_BM_LF 0x10DF -#define E1000_DEV_ID_ICH10_D_BM_V 0x1525 -#define E1000_DEV_ID_PCH_M_HV_LM 0x10EA -#define E1000_DEV_ID_PCH_M_HV_LC 0x10EB -#define E1000_DEV_ID_PCH_D_HV_DM 0x10EF -#define E1000_DEV_ID_PCH_D_HV_DC 0x10F0 -#define E1000_DEV_ID_PCH2_LV_LM 0x1502 -#define E1000_DEV_ID_PCH2_LV_V 0x1503 -#define E1000_DEV_ID_PCH_LPT_I217_LM 0x153A -#define E1000_DEV_ID_PCH_LPT_I217_V 0x153B -#define E1000_DEV_ID_PCH_LPTLP_I218_LM 0x155A -#define E1000_DEV_ID_PCH_LPTLP_I218_V 0x1559 -#define E1000_DEV_ID_PCH_I218_LM2 0x15A0 -#define E1000_DEV_ID_PCH_I218_V2 0x15A1 -#define E1000_DEV_ID_PCH_I218_LM3 0x15A2 /* Wildcat Point PCH */ -#define E1000_DEV_ID_PCH_I218_V3 0x15A3 /* Wildcat Point PCH */ -#define E1000_DEV_ID_PCH_SPT_I219_LM 0x156F /* SPT PCH */ -#define E1000_DEV_ID_PCH_SPT_I219_V 0x1570 /* SPT PCH */ -#define E1000_DEV_ID_PCH_SPT_I219_LM2 0x15B7 /* SPT-H PCH */ -#define E1000_DEV_ID_PCH_SPT_I219_V2 0x15B8 /* SPT-H PCH */ - -#define E1000_REVISION_4 4 - -#define E1000_FUNC_1 1 - -#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN0 0 -#define E1000_ALT_MAC_ADDRESS_OFFSET_LAN1 3 - -enum e1000_mac_type { - e1000_82571, - e1000_82572, - e1000_82573, - e1000_82574, - e1000_82583, - e1000_80003es2lan, - e1000_ich8lan, - e1000_ich9lan, - e1000_ich10lan, - e1000_pchlan, - e1000_pch2lan, - e1000_pch_lpt, - e1000_pch_spt, -}; - -enum e1000_media_type { - e1000_media_type_unknown = 0, - e1000_media_type_copper = 1, - e1000_media_type_fiber = 2, - e1000_media_type_internal_serdes = 3, - e1000_num_media_types -}; - -enum e1000_nvm_type { - e1000_nvm_unknown = 0, - e1000_nvm_none, - e1000_nvm_eeprom_spi, - e1000_nvm_flash_hw, - e1000_nvm_flash_sw -}; - -enum e1000_nvm_override { - e1000_nvm_override_none = 0, - e1000_nvm_override_spi_small, - e1000_nvm_override_spi_large -}; - -enum e1000_phy_type { - e1000_phy_unknown = 0, - e1000_phy_none, - e1000_phy_m88, - e1000_phy_igp, - e1000_phy_igp_2, - e1000_phy_gg82563, - e1000_phy_igp_3, - e1000_phy_ife, - e1000_phy_bm, - e1000_phy_82578, - e1000_phy_82577, - e1000_phy_82579, - e1000_phy_i217, -}; - -enum e1000_bus_width { - e1000_bus_width_unknown = 0, - e1000_bus_width_pcie_x1, - e1000_bus_width_pcie_x2, - e1000_bus_width_pcie_x4 = 4, - e1000_bus_width_pcie_x8 = 8, - e1000_bus_width_32, - e1000_bus_width_64, - e1000_bus_width_reserved -}; - -enum e1000_1000t_rx_status { - e1000_1000t_rx_status_not_ok = 0, - e1000_1000t_rx_status_ok, - e1000_1000t_rx_status_undefined = 0xFF -}; - -enum e1000_rev_polarity { - e1000_rev_polarity_normal = 0, - e1000_rev_polarity_reversed, - e1000_rev_polarity_undefined = 0xFF -}; - -enum e1000_fc_mode { - e1000_fc_none = 0, - e1000_fc_rx_pause, - e1000_fc_tx_pause, - e1000_fc_full, - e1000_fc_default = 0xFF -}; - -enum e1000_ms_type { - e1000_ms_hw_default = 0, - e1000_ms_force_master, - e1000_ms_force_slave, - e1000_ms_auto -}; - -enum e1000_smart_speed { - e1000_smart_speed_default = 0, - e1000_smart_speed_on, - e1000_smart_speed_off -}; - -enum e1000_serdes_link_state { - e1000_serdes_link_down = 0, - e1000_serdes_link_autoneg_progress, - e1000_serdes_link_autoneg_complete, - e1000_serdes_link_forced_up -}; - -/* Receive Descriptor - Extended */ -union e1000_rx_desc_extended { - struct { - __le64 buffer_addr; - __le64 reserved; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length; - __le16 vlan; /* VLAN tag */ - } upper; - } wb; /* writeback */ -}; - -#define MAX_PS_BUFFERS 4 - -/* Number of packet split data buffers (not including the header buffer) */ -#define PS_PAGE_BUFFERS (MAX_PS_BUFFERS - 1) - -/* Receive Descriptor - Packet Split */ -union e1000_rx_desc_packet_split { - struct { - /* one buffer for protocol header(s), three data buffers */ - __le64 buffer_addr[MAX_PS_BUFFERS]; - } read; - struct { - struct { - __le32 mrq; /* Multiple Rx Queues */ - union { - __le32 rss; /* RSS Hash */ - struct { - __le16 ip_id; /* IP id */ - __le16 csum; /* Packet Checksum */ - } csum_ip; - } hi_dword; - } lower; - struct { - __le32 status_error; /* ext status/error */ - __le16 length0; /* length of buffer 0 */ - __le16 vlan; /* VLAN tag */ - } middle; - struct { - __le16 header_status; - /* length of buffers 1-3 */ - __le16 length[PS_PAGE_BUFFERS]; - } upper; - __le64 reserved; - } wb; /* writeback */ -}; - -/* Transmit Descriptor */ -struct e1000_tx_desc { - __le64 buffer_addr; /* Address of the descriptor's data buffer */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 cso; /* Checksum offset */ - u8 cmd; /* Descriptor control */ - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 css; /* Checksum start */ - __le16 special; - } fields; - } upper; -}; - -/* Offload Context Descriptor */ -struct e1000_context_desc { - union { - __le32 ip_config; - struct { - u8 ipcss; /* IP checksum start */ - u8 ipcso; /* IP checksum offset */ - __le16 ipcse; /* IP checksum end */ - } ip_fields; - } lower_setup; - union { - __le32 tcp_config; - struct { - u8 tucss; /* TCP checksum start */ - u8 tucso; /* TCP checksum offset */ - __le16 tucse; /* TCP checksum end */ - } tcp_fields; - } upper_setup; - __le32 cmd_and_length; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 hdr_len; /* Header length */ - __le16 mss; /* Maximum segment size */ - } fields; - } tcp_seg_setup; -}; - -/* Offload data descriptor */ -struct e1000_data_desc { - __le64 buffer_addr; /* Address of the descriptor's buffer address */ - union { - __le32 data; - struct { - __le16 length; /* Data buffer length */ - u8 typ_len_ext; - u8 cmd; - } flags; - } lower; - union { - __le32 data; - struct { - u8 status; /* Descriptor status */ - u8 popts; /* Packet Options */ - __le16 special; - } fields; - } upper; -}; - -/* Statistics counters collected by the MAC */ -struct e1000_hw_stats { - u64 crcerrs; - u64 algnerrc; - u64 symerrs; - u64 rxerrc; - u64 mpc; - u64 scc; - u64 ecol; - u64 mcc; - u64 latecol; - u64 colc; - u64 dc; - u64 tncrs; - u64 sec; - u64 cexterr; - u64 rlec; - u64 xonrxc; - u64 xontxc; - u64 xoffrxc; - u64 xofftxc; - u64 fcruc; - u64 prc64; - u64 prc127; - u64 prc255; - u64 prc511; - u64 prc1023; - u64 prc1522; - u64 gprc; - u64 bprc; - u64 mprc; - u64 gptc; - u64 gorc; - u64 gotc; - u64 rnbc; - u64 ruc; - u64 rfc; - u64 roc; - u64 rjc; - u64 mgprc; - u64 mgpdc; - u64 mgptc; - u64 tor; - u64 tot; - u64 tpr; - u64 tpt; - u64 ptc64; - u64 ptc127; - u64 ptc255; - u64 ptc511; - u64 ptc1023; - u64 ptc1522; - u64 mptc; - u64 bptc; - u64 tsctc; - u64 tsctfc; - u64 iac; - u64 icrxptc; - u64 icrxatc; - u64 ictxptc; - u64 ictxatc; - u64 ictxqec; - u64 ictxqmtc; - u64 icrxdmtc; - u64 icrxoc; -}; - -struct e1000_phy_stats { - u32 idle_errors; - u32 receive_errors; -}; - -struct e1000_host_mng_dhcp_cookie { - u32 signature; - u8 status; - u8 reserved0; - u16 vlan_id; - u32 reserved1; - u16 reserved2; - u8 reserved3; - u8 checksum; -}; - -/* Host Interface "Rev 1" */ -struct e1000_host_command_header { - u8 command_id; - u8 command_length; - u8 command_options; - u8 checksum; -}; - -#define E1000_HI_MAX_DATA_LENGTH 252 -struct e1000_host_command_info { - struct e1000_host_command_header command_header; - u8 command_data[E1000_HI_MAX_DATA_LENGTH]; -}; - -/* Host Interface "Rev 2" */ -struct e1000_host_mng_command_header { - u8 command_id; - u8 checksum; - u16 reserved1; - u16 reserved2; - u16 command_length; -}; - -#define E1000_HI_MAX_MNG_DATA_LENGTH 0x6F8 -struct e1000_host_mng_command_info { - struct e1000_host_mng_command_header command_header; - u8 command_data[E1000_HI_MAX_MNG_DATA_LENGTH]; -}; - -#include "mac.h" -#include "phy.h" -#include "nvm.h" -#include "manage.h" - -/* Function pointers for the MAC. */ -struct e1000_mac_operations { - s32 (*id_led_init)(struct e1000_hw *); - s32 (*blink_led)(struct e1000_hw *); - bool (*check_mng_mode)(struct e1000_hw *); - s32 (*check_for_link)(struct e1000_hw *); - s32 (*cleanup_led)(struct e1000_hw *); - void (*clear_hw_cntrs)(struct e1000_hw *); - void (*clear_vfta)(struct e1000_hw *); - s32 (*get_bus_info)(struct e1000_hw *); - void (*set_lan_id)(struct e1000_hw *); - s32 (*get_link_up_info)(struct e1000_hw *, u16 *, u16 *); - s32 (*led_on)(struct e1000_hw *); - s32 (*led_off)(struct e1000_hw *); - void (*update_mc_addr_list)(struct e1000_hw *, u8 *, u32); - s32 (*reset_hw)(struct e1000_hw *); - s32 (*init_hw)(struct e1000_hw *); - s32 (*setup_link)(struct e1000_hw *); - s32 (*setup_physical_interface)(struct e1000_hw *); - s32 (*setup_led)(struct e1000_hw *); - void (*write_vfta)(struct e1000_hw *, u32, u32); - void (*config_collision_dist)(struct e1000_hw *); - int (*rar_set)(struct e1000_hw *, u8 *, u32); - s32 (*read_mac_addr)(struct e1000_hw *); - u32 (*rar_get_count)(struct e1000_hw *); -}; - -/* When to use various PHY register access functions: - * - * Func Caller - * Function Does Does When to use - * ~~~~~~~~~~~~ ~~~~~ ~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - * X_reg L,P,A n/a for simple PHY reg accesses - * X_reg_locked P,A L for multiple accesses of different regs - * on different pages - * X_reg_page A L,P for multiple accesses of different regs - * on the same page - * - * Where X=[read|write], L=locking, P=sets page, A=register access - * - */ -struct e1000_phy_operations { - s32 (*acquire)(struct e1000_hw *); - s32 (*cfg_on_link_up)(struct e1000_hw *); - s32 (*check_polarity)(struct e1000_hw *); - s32 (*check_reset_block)(struct e1000_hw *); - s32 (*commit)(struct e1000_hw *); - s32 (*force_speed_duplex)(struct e1000_hw *); - s32 (*get_cfg_done)(struct e1000_hw *hw); - s32 (*get_cable_length)(struct e1000_hw *); - s32 (*get_info)(struct e1000_hw *); - s32 (*set_page)(struct e1000_hw *, u16); - s32 (*read_reg)(struct e1000_hw *, u32, u16 *); - s32 (*read_reg_locked)(struct e1000_hw *, u32, u16 *); - s32 (*read_reg_page)(struct e1000_hw *, u32, u16 *); - void (*release)(struct e1000_hw *); - s32 (*reset)(struct e1000_hw *); - s32 (*set_d0_lplu_state)(struct e1000_hw *, bool); - s32 (*set_d3_lplu_state)(struct e1000_hw *, bool); - s32 (*write_reg)(struct e1000_hw *, u32, u16); - s32 (*write_reg_locked)(struct e1000_hw *, u32, u16); - s32 (*write_reg_page)(struct e1000_hw *, u32, u16); - void (*power_up)(struct e1000_hw *); - void (*power_down)(struct e1000_hw *); -}; - -/* Function pointers for the NVM. */ -struct e1000_nvm_operations { - s32 (*acquire)(struct e1000_hw *); - s32 (*read)(struct e1000_hw *, u16, u16, u16 *); - void (*release)(struct e1000_hw *); - void (*reload)(struct e1000_hw *); - s32 (*update)(struct e1000_hw *); - s32 (*valid_led_default)(struct e1000_hw *, u16 *); - s32 (*validate)(struct e1000_hw *); - s32 (*write)(struct e1000_hw *, u16, u16, u16 *); -}; - -struct e1000_mac_info { - struct e1000_mac_operations ops; - u8 addr[ETH_ALEN]; - u8 perm_addr[ETH_ALEN]; - - enum e1000_mac_type type; - - u32 collision_delta; - u32 ledctl_default; - u32 ledctl_mode1; - u32 ledctl_mode2; - u32 mc_filter_type; - u32 tx_packet_delta; - u32 txcw; - - u16 current_ifs_val; - u16 ifs_max_val; - u16 ifs_min_val; - u16 ifs_ratio; - u16 ifs_step_size; - u16 mta_reg_count; - - /* Maximum size of the MTA register table in all supported adapters */ -#define MAX_MTA_REG 128 - u32 mta_shadow[MAX_MTA_REG]; - u16 rar_entry_count; - - u8 forced_speed_duplex; - - bool adaptive_ifs; - bool has_fwsm; - bool arc_subsystem_valid; - bool autoneg; - bool autoneg_failed; - bool get_link_status; - bool in_ifs_mode; - bool serdes_has_link; - bool tx_pkt_filtering; - enum e1000_serdes_link_state serdes_link_state; -}; - -struct e1000_phy_info { - struct e1000_phy_operations ops; - - enum e1000_phy_type type; - - enum e1000_1000t_rx_status local_rx; - enum e1000_1000t_rx_status remote_rx; - enum e1000_ms_type ms_type; - enum e1000_ms_type original_ms_type; - enum e1000_rev_polarity cable_polarity; - enum e1000_smart_speed smart_speed; - - u32 addr; - u32 id; - u32 reset_delay_us; /* in usec */ - u32 revision; - - enum e1000_media_type media_type; - - u16 autoneg_advertised; - u16 autoneg_mask; - u16 cable_length; - u16 max_cable_length; - u16 min_cable_length; - - u8 mdix; - - bool disable_polarity_correction; - bool is_mdix; - bool polarity_correction; - bool speed_downgraded; - bool autoneg_wait_to_complete; -}; - -struct e1000_nvm_info { - struct e1000_nvm_operations ops; - - enum e1000_nvm_type type; - enum e1000_nvm_override override; - - u32 flash_bank_size; - u32 flash_base_addr; - - u16 word_size; - u16 delay_usec; - u16 address_bits; - u16 opcode_bits; - u16 page_size; -}; - -struct e1000_bus_info { - enum e1000_bus_width width; - - u16 func; -}; - -struct e1000_fc_info { - u32 high_water; /* Flow control high-water mark */ - u32 low_water; /* Flow control low-water mark */ - u16 pause_time; /* Flow control pause timer */ - u16 refresh_time; /* Flow control refresh timer */ - bool send_xon; /* Flow control send XON */ - bool strict_ieee; /* Strict IEEE mode */ - enum e1000_fc_mode current_mode; /* FC mode in effect */ - enum e1000_fc_mode requested_mode; /* FC mode requested by caller */ -}; - -struct e1000_dev_spec_82571 { - bool laa_is_present; - u32 smb_counter; -}; - -struct e1000_dev_spec_80003es2lan { - bool mdic_wa_enable; -}; - -struct e1000_shadow_ram { - u16 value; - bool modified; -}; - -#define E1000_ICH8_SHADOW_RAM_WORDS 2048 - -/* I218 PHY Ultra Low Power (ULP) states */ -enum e1000_ulp_state { - e1000_ulp_state_unknown, - e1000_ulp_state_off, - e1000_ulp_state_on, -}; - -struct e1000_dev_spec_ich8lan { - bool kmrn_lock_loss_workaround_enabled; - struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS]; - bool nvm_k1_enabled; - bool eee_disable; - u16 eee_lp_ability; - enum e1000_ulp_state ulp_state; -}; - -struct e1000_hw { - struct e1000_adapter *adapter; - - void __iomem *hw_addr; - void __iomem *flash_address; - - struct e1000_mac_info mac; - struct e1000_fc_info fc; - struct e1000_phy_info phy; - struct e1000_nvm_info nvm; - struct e1000_bus_info bus; - struct e1000_host_mng_dhcp_cookie mng_cookie; - - union { - struct e1000_dev_spec_82571 e82571; - struct e1000_dev_spec_80003es2lan e80003es2lan; - struct e1000_dev_spec_ich8lan ich8lan; - } dev_spec; -}; - -#include "82571.h" -#include "80003es2lan.h" -#include "ich8lan.h" - -#endif diff --git a/addons/e1000e/src/4.4.180/ich8lan.c b/addons/e1000e/src/4.4.180/ich8lan.c deleted file mode 100644 index 485b9cc5..00000000 --- a/addons/e1000e/src/4.4.180/ich8lan.c +++ /dev/null @@ -1,5873 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -/* 82562G 10/100 Network Connection - * 82562G-2 10/100 Network Connection - * 82562GT 10/100 Network Connection - * 82562GT-2 10/100 Network Connection - * 82562V 10/100 Network Connection - * 82562V-2 10/100 Network Connection - * 82566DC-2 Gigabit Network Connection - * 82566DC Gigabit Network Connection - * 82566DM-2 Gigabit Network Connection - * 82566DM Gigabit Network Connection - * 82566MC Gigabit Network Connection - * 82566MM Gigabit Network Connection - * 82567LM Gigabit Network Connection - * 82567LF Gigabit Network Connection - * 82567V Gigabit Network Connection - * 82567LM-2 Gigabit Network Connection - * 82567LF-2 Gigabit Network Connection - * 82567V-2 Gigabit Network Connection - * 82567LF-3 Gigabit Network Connection - * 82567LM-3 Gigabit Network Connection - * 82567LM-4 Gigabit Network Connection - * 82577LM Gigabit Network Connection - * 82577LC Gigabit Network Connection - * 82578DM Gigabit Network Connection - * 82578DC Gigabit Network Connection - * 82579LM Gigabit Network Connection - * 82579V Gigabit Network Connection - * Ethernet Connection I217-LM - * Ethernet Connection I217-V - * Ethernet Connection I218-V - * Ethernet Connection I218-LM - * Ethernet Connection (2) I218-LM - * Ethernet Connection (2) I218-V - * Ethernet Connection (3) I218-LM - * Ethernet Connection (3) I218-V - */ - -#include "e1000.h" - -/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */ -/* Offset 04h HSFSTS */ -union ich8_hws_flash_status { - struct ich8_hsfsts { - u16 flcdone:1; /* bit 0 Flash Cycle Done */ - u16 flcerr:1; /* bit 1 Flash Cycle Error */ - u16 dael:1; /* bit 2 Direct Access error Log */ - u16 berasesz:2; /* bit 4:3 Sector Erase Size */ - u16 flcinprog:1; /* bit 5 flash cycle in Progress */ - u16 reserved1:2; /* bit 13:6 Reserved */ - u16 reserved2:6; /* bit 13:6 Reserved */ - u16 fldesvalid:1; /* bit 14 Flash Descriptor Valid */ - u16 flockdn:1; /* bit 15 Flash Config Lock-Down */ - } hsf_status; - u16 regval; -}; - -/* ICH GbE Flash Hardware Sequencing Flash control Register bit breakdown */ -/* Offset 06h FLCTL */ -union ich8_hws_flash_ctrl { - struct ich8_hsflctl { - u16 flcgo:1; /* 0 Flash Cycle Go */ - u16 flcycle:2; /* 2:1 Flash Cycle */ - u16 reserved:5; /* 7:3 Reserved */ - u16 fldbcount:2; /* 9:8 Flash Data Byte Count */ - u16 flockdn:6; /* 15:10 Reserved */ - } hsf_ctrl; - u16 regval; -}; - -/* ICH Flash Region Access Permissions */ -union ich8_hws_flash_regacc { - struct ich8_flracc { - u32 grra:8; /* 0:7 GbE region Read Access */ - u32 grwa:8; /* 8:15 GbE region Write Access */ - u32 gmrag:8; /* 23:16 GbE Master Read Access Grant */ - u32 gmwag:8; /* 31:24 GbE Master Write Access Grant */ - } hsf_flregacc; - u16 regval; -}; - -/* ICH Flash Protected Region */ -union ich8_flash_protected_range { - struct ich8_pr { - u32 base:13; /* 0:12 Protected Range Base */ - u32 reserved1:2; /* 13:14 Reserved */ - u32 rpe:1; /* 15 Read Protection Enable */ - u32 limit:13; /* 16:28 Protected Range Limit */ - u32 reserved2:2; /* 29:30 Reserved */ - u32 wpe:1; /* 31 Write Protection Enable */ - } range; - u32 regval; -}; - -static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw); -static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw); -static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank); -static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, - u32 offset, u8 byte); -static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, - u8 *data); -static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, - u16 *data); -static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, - u8 size, u16 *data); -static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, - u32 *data); -static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, - u32 offset, u32 *data); -static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, - u32 offset, u32 data); -static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw, - u32 offset, u32 dword); -static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw); -static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw); -static s32 e1000_led_on_ich8lan(struct e1000_hw *hw); -static s32 e1000_led_off_ich8lan(struct e1000_hw *hw); -static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw); -static s32 e1000_setup_led_pchlan(struct e1000_hw *hw); -static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw); -static s32 e1000_led_on_pchlan(struct e1000_hw *hw); -static s32 e1000_led_off_pchlan(struct e1000_hw *hw); -static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active); -static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw); -static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw); -static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link); -static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw); -static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw); -static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw); -static int e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index); -static int e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index); -static u32 e1000_rar_get_count_pch_lpt(struct e1000_hw *hw); -static s32 e1000_k1_workaround_lv(struct e1000_hw *hw); -static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate); -static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force); -static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw); -static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state); - -static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg) -{ - return readw(hw->flash_address + reg); -} - -static inline u32 __er32flash(struct e1000_hw *hw, unsigned long reg) -{ - return readl(hw->flash_address + reg); -} - -static inline void __ew16flash(struct e1000_hw *hw, unsigned long reg, u16 val) -{ - writew(val, hw->flash_address + reg); -} - -static inline void __ew32flash(struct e1000_hw *hw, unsigned long reg, u32 val) -{ - writel(val, hw->flash_address + reg); -} - -#define er16flash(reg) __er16flash(hw, (reg)) -#define er32flash(reg) __er32flash(hw, (reg)) -#define ew16flash(reg, val) __ew16flash(hw, (reg), (val)) -#define ew32flash(reg, val) __ew32flash(hw, (reg), (val)) - -/** - * e1000_phy_is_accessible_pchlan - Check if able to access PHY registers - * @hw: pointer to the HW structure - * - * Test access to the PHY registers by reading the PHY ID registers. If - * the PHY ID is already known (e.g. resume path) compare it with known ID, - * otherwise assume the read PHY ID is correct if it is valid. - * - * Assumes the sw/fw/hw semaphore is already acquired. - **/ -static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw) -{ - u16 phy_reg = 0; - u32 phy_id = 0; - s32 ret_val = 0; - u16 retry_count; - u32 mac_reg = 0; - - for (retry_count = 0; retry_count < 2; retry_count++) { - ret_val = e1e_rphy_locked(hw, MII_PHYSID1, &phy_reg); - if (ret_val || (phy_reg == 0xFFFF)) - continue; - phy_id = (u32)(phy_reg << 16); - - ret_val = e1e_rphy_locked(hw, MII_PHYSID2, &phy_reg); - if (ret_val || (phy_reg == 0xFFFF)) { - phy_id = 0; - continue; - } - phy_id |= (u32)(phy_reg & PHY_REVISION_MASK); - break; - } - - if (hw->phy.id) { - if (hw->phy.id == phy_id) - goto out; - } else if (phy_id) { - hw->phy.id = phy_id; - hw->phy.revision = (u32)(phy_reg & ~PHY_REVISION_MASK); - goto out; - } - - /* In case the PHY needs to be in mdio slow mode, - * set slow mode and try to get the PHY id again. - */ - if (hw->mac.type < e1000_pch_lpt) { - hw->phy.ops.release(hw); - ret_val = e1000_set_mdio_slow_mode_hv(hw); - if (!ret_val) - ret_val = e1000e_get_phy_id(hw); - hw->phy.ops.acquire(hw); - } - - if (ret_val) - return false; -out: - if ((hw->mac.type == e1000_pch_lpt) || (hw->mac.type == e1000_pch_spt)) { - /* Only unforce SMBus if ME is not active */ - if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { - /* Unforce SMBus mode in PHY */ - e1e_rphy_locked(hw, CV_SMB_CTRL, &phy_reg); - phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; - e1e_wphy_locked(hw, CV_SMB_CTRL, phy_reg); - - /* Unforce SMBus mode in MAC */ - mac_reg = er32(CTRL_EXT); - mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; - ew32(CTRL_EXT, mac_reg); - } - } - - return true; -} - -/** - * e1000_toggle_lanphypc_pch_lpt - toggle the LANPHYPC pin value - * @hw: pointer to the HW structure - * - * Toggling the LANPHYPC pin value fully power-cycles the PHY and is - * used to reset the PHY to a quiescent state when necessary. - **/ -static void e1000_toggle_lanphypc_pch_lpt(struct e1000_hw *hw) -{ - u32 mac_reg; - - /* Set Phy Config Counter to 50msec */ - mac_reg = er32(FEXTNVM3); - mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; - mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; - ew32(FEXTNVM3, mac_reg); - - /* Toggle LANPHYPC Value bit */ - mac_reg = er32(CTRL); - mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE; - mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE; - ew32(CTRL, mac_reg); - e1e_flush(); - usleep_range(10, 20); - mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE; - ew32(CTRL, mac_reg); - e1e_flush(); - - if (hw->mac.type < e1000_pch_lpt) { - msleep(50); - } else { - u16 count = 20; - - do { - usleep_range(5000, 10000); - } while (!(er32(CTRL_EXT) & E1000_CTRL_EXT_LPCD) && count--); - - msleep(30); - } -} - -/** - * e1000_init_phy_workarounds_pchlan - PHY initialization workarounds - * @hw: pointer to the HW structure - * - * Workarounds/flow necessary for PHY initialization during driver load - * and resume paths. - **/ -static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw) -{ - struct e1000_adapter *adapter = hw->adapter; - u32 mac_reg, fwsm = er32(FWSM); - s32 ret_val; - - /* Gate automatic PHY configuration by hardware on managed and - * non-managed 82579 and newer adapters. - */ - e1000_gate_hw_phy_config_ich8lan(hw, true); - - /* It is not possible to be certain of the current state of ULP - * so forcibly disable it. - */ - hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_unknown; - e1000_disable_ulp_lpt_lp(hw, true); - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) { - e_dbg("Failed to initialize PHY flow\n"); - goto out; - } - - /* The MAC-PHY interconnect may be in SMBus mode. If the PHY is - * inaccessible and resetting the PHY is not blocked, toggle the - * LANPHYPC Value bit to force the interconnect to PCIe mode. - */ - switch (hw->mac.type) { - case e1000_pch_lpt: - case e1000_pch_spt: - if (e1000_phy_is_accessible_pchlan(hw)) - break; - - /* Before toggling LANPHYPC, see if PHY is accessible by - * forcing MAC to SMBus mode first. - */ - mac_reg = er32(CTRL_EXT); - mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; - ew32(CTRL_EXT, mac_reg); - - /* Wait 50 milliseconds for MAC to finish any retries - * that it might be trying to perform from previous - * attempts to acknowledge any phy read requests. - */ - msleep(50); - - /* fall-through */ - case e1000_pch2lan: - if (e1000_phy_is_accessible_pchlan(hw)) - break; - - /* fall-through */ - case e1000_pchlan: - if ((hw->mac.type == e1000_pchlan) && - (fwsm & E1000_ICH_FWSM_FW_VALID)) - break; - - if (hw->phy.ops.check_reset_block(hw)) { - e_dbg("Required LANPHYPC toggle blocked by ME\n"); - ret_val = -E1000_ERR_PHY; - break; - } - - /* Toggle LANPHYPC Value bit */ - e1000_toggle_lanphypc_pch_lpt(hw); - if (hw->mac.type >= e1000_pch_lpt) { - if (e1000_phy_is_accessible_pchlan(hw)) - break; - - /* Toggling LANPHYPC brings the PHY out of SMBus mode - * so ensure that the MAC is also out of SMBus mode - */ - mac_reg = er32(CTRL_EXT); - mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; - ew32(CTRL_EXT, mac_reg); - - if (e1000_phy_is_accessible_pchlan(hw)) - break; - - ret_val = -E1000_ERR_PHY; - } - break; - default: - break; - } - - hw->phy.ops.release(hw); - if (!ret_val) { - - /* Check to see if able to reset PHY. Print error if not */ - if (hw->phy.ops.check_reset_block(hw)) { - e_err("Reset blocked by ME\n"); - goto out; - } - - /* Reset the PHY before any access to it. Doing so, ensures - * that the PHY is in a known good state before we read/write - * PHY registers. The generic reset is sufficient here, - * because we haven't determined the PHY type yet. - */ - ret_val = e1000e_phy_hw_reset_generic(hw); - if (ret_val) - goto out; - - /* On a successful reset, possibly need to wait for the PHY - * to quiesce to an accessible state before returning control - * to the calling function. If the PHY does not quiesce, then - * return E1000E_BLK_PHY_RESET, as this is the condition that - * the PHY is in. - */ - ret_val = hw->phy.ops.check_reset_block(hw); - if (ret_val) - e_err("ME blocked access to PHY after reset\n"); - } - -out: - /* Ungate automatic PHY configuration on non-managed 82579 */ - if ((hw->mac.type == e1000_pch2lan) && - !(fwsm & E1000_ICH_FWSM_FW_VALID)) { - usleep_range(10000, 20000); - e1000_gate_hw_phy_config_ich8lan(hw, false); - } - - return ret_val; -} - -/** - * e1000_init_phy_params_pchlan - Initialize PHY function pointers - * @hw: pointer to the HW structure - * - * Initialize family-specific PHY parameters and function pointers. - **/ -static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - - phy->addr = 1; - phy->reset_delay_us = 100; - - phy->ops.set_page = e1000_set_page_igp; - phy->ops.read_reg = e1000_read_phy_reg_hv; - phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked; - phy->ops.read_reg_page = e1000_read_phy_reg_page_hv; - phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan; - phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan; - phy->ops.write_reg = e1000_write_phy_reg_hv; - phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked; - phy->ops.write_reg_page = e1000_write_phy_reg_page_hv; - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - - phy->id = e1000_phy_unknown; - - ret_val = e1000_init_phy_workarounds_pchlan(hw); - if (ret_val) - return ret_val; - - if (phy->id == e1000_phy_unknown) - switch (hw->mac.type) { - default: - ret_val = e1000e_get_phy_id(hw); - if (ret_val) - return ret_val; - if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK)) - break; - /* fall-through */ - case e1000_pch2lan: - case e1000_pch_lpt: - case e1000_pch_spt: - /* In case the PHY needs to be in mdio slow mode, - * set slow mode and try to get the PHY id again. - */ - ret_val = e1000_set_mdio_slow_mode_hv(hw); - if (ret_val) - return ret_val; - ret_val = e1000e_get_phy_id(hw); - if (ret_val) - return ret_val; - break; - } - phy->type = e1000e_get_phy_type_from_id(phy->id); - - switch (phy->type) { - case e1000_phy_82577: - case e1000_phy_82579: - case e1000_phy_i217: - phy->ops.check_polarity = e1000_check_polarity_82577; - phy->ops.force_speed_duplex = - e1000_phy_force_speed_duplex_82577; - phy->ops.get_cable_length = e1000_get_cable_length_82577; - phy->ops.get_info = e1000_get_phy_info_82577; - phy->ops.commit = e1000e_phy_sw_reset; - break; - case e1000_phy_82578: - phy->ops.check_polarity = e1000_check_polarity_m88; - phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_m88; - phy->ops.get_cable_length = e1000e_get_cable_length_m88; - phy->ops.get_info = e1000e_get_phy_info_m88; - break; - default: - ret_val = -E1000_ERR_PHY; - break; - } - - return ret_val; -} - -/** - * e1000_init_phy_params_ich8lan - Initialize PHY function pointers - * @hw: pointer to the HW structure - * - * Initialize family-specific PHY parameters and function pointers. - **/ -static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 i = 0; - - phy->addr = 1; - phy->reset_delay_us = 100; - - phy->ops.power_up = e1000_power_up_phy_copper; - phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; - - /* We may need to do this twice - once for IGP and if that fails, - * we'll set BM func pointers and try again - */ - ret_val = e1000e_determine_phy_address(hw); - if (ret_val) { - phy->ops.write_reg = e1000e_write_phy_reg_bm; - phy->ops.read_reg = e1000e_read_phy_reg_bm; - ret_val = e1000e_determine_phy_address(hw); - if (ret_val) { - e_dbg("Cannot determine PHY addr. Erroring out\n"); - return ret_val; - } - } - - phy->id = 0; - while ((e1000_phy_unknown == e1000e_get_phy_type_from_id(phy->id)) && - (i++ < 100)) { - usleep_range(1000, 2000); - ret_val = e1000e_get_phy_id(hw); - if (ret_val) - return ret_val; - } - - /* Verify phy id */ - switch (phy->id) { - case IGP03E1000_E_PHY_ID: - phy->type = e1000_phy_igp_3; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->ops.read_reg_locked = e1000e_read_phy_reg_igp_locked; - phy->ops.write_reg_locked = e1000e_write_phy_reg_igp_locked; - phy->ops.get_info = e1000e_get_phy_info_igp; - phy->ops.check_polarity = e1000_check_polarity_igp; - phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_igp; - break; - case IFE_E_PHY_ID: - case IFE_PLUS_E_PHY_ID: - case IFE_C_E_PHY_ID: - phy->type = e1000_phy_ife; - phy->autoneg_mask = E1000_ALL_NOT_GIG; - phy->ops.get_info = e1000_get_phy_info_ife; - phy->ops.check_polarity = e1000_check_polarity_ife; - phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_ife; - break; - case BME1000_E_PHY_ID: - phy->type = e1000_phy_bm; - phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; - phy->ops.read_reg = e1000e_read_phy_reg_bm; - phy->ops.write_reg = e1000e_write_phy_reg_bm; - phy->ops.commit = e1000e_phy_sw_reset; - phy->ops.get_info = e1000e_get_phy_info_m88; - phy->ops.check_polarity = e1000_check_polarity_m88; - phy->ops.force_speed_duplex = e1000e_phy_force_speed_duplex_m88; - break; - default: - return -E1000_ERR_PHY; - } - - return 0; -} - -/** - * e1000_init_nvm_params_ich8lan - Initialize NVM function pointers - * @hw: pointer to the HW structure - * - * Initialize family-specific NVM parameters and function - * pointers. - **/ -static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 gfpreg, sector_base_addr, sector_end_addr; - u16 i; - u32 nvm_size; - - nvm->type = e1000_nvm_flash_sw; - - if (hw->mac.type == e1000_pch_spt) { - /* in SPT, gfpreg doesn't exist. NVM size is taken from the - * STRAP register. This is because in SPT the GbE Flash region - * is no longer accessed through the flash registers. Instead, - * the mechanism has changed, and the Flash region access - * registers are now implemented in GbE memory space. - */ - nvm->flash_base_addr = 0; - nvm_size = (((er32(STRAP) >> 1) & 0x1F) + 1) - * NVM_SIZE_MULTIPLIER; - nvm->flash_bank_size = nvm_size / 2; - /* Adjust to word count */ - nvm->flash_bank_size /= sizeof(u16); - /* Set the base address for flash register access */ - hw->flash_address = hw->hw_addr + E1000_FLASH_BASE_ADDR; - } else { - /* Can't read flash registers if register set isn't mapped. */ - if (!hw->flash_address) { - e_dbg("ERROR: Flash registers not mapped\n"); - return -E1000_ERR_CONFIG; - } - - gfpreg = er32flash(ICH_FLASH_GFPREG); - - /* sector_X_addr is a "sector"-aligned address (4096 bytes) - * Add 1 to sector_end_addr since this sector is included in - * the overall size. - */ - sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK; - sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1; - - /* flash_base_addr is byte-aligned */ - nvm->flash_base_addr = sector_base_addr - << FLASH_SECTOR_ADDR_SHIFT; - - /* find total size of the NVM, then cut in half since the total - * size represents two separate NVM banks. - */ - nvm->flash_bank_size = ((sector_end_addr - sector_base_addr) - << FLASH_SECTOR_ADDR_SHIFT); - nvm->flash_bank_size /= 2; - /* Adjust to word count */ - nvm->flash_bank_size /= sizeof(u16); - } - - nvm->word_size = E1000_ICH8_SHADOW_RAM_WORDS; - - /* Clear shadow ram */ - for (i = 0; i < nvm->word_size; i++) { - dev_spec->shadow_ram[i].modified = false; - dev_spec->shadow_ram[i].value = 0xFFFF; - } - - return 0; -} - -/** - * e1000_init_mac_params_ich8lan - Initialize MAC function pointers - * @hw: pointer to the HW structure - * - * Initialize family-specific MAC parameters and function - * pointers. - **/ -static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - /* Set media type function pointer */ - hw->phy.media_type = e1000_media_type_copper; - - /* Set mta register count */ - mac->mta_reg_count = 32; - /* Set rar entry count */ - mac->rar_entry_count = E1000_ICH_RAR_ENTRIES; - if (mac->type == e1000_ich8lan) - mac->rar_entry_count--; - /* FWSM register */ - mac->has_fwsm = true; - /* ARC subsystem not supported */ - mac->arc_subsystem_valid = false; - /* Adaptive IFS supported */ - mac->adaptive_ifs = true; - - /* LED and other operations */ - switch (mac->type) { - case e1000_ich8lan: - case e1000_ich9lan: - case e1000_ich10lan: - /* check management mode */ - mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan; - /* ID LED init */ - mac->ops.id_led_init = e1000e_id_led_init_generic; - /* blink LED */ - mac->ops.blink_led = e1000e_blink_led_generic; - /* setup LED */ - mac->ops.setup_led = e1000e_setup_led_generic; - /* cleanup LED */ - mac->ops.cleanup_led = e1000_cleanup_led_ich8lan; - /* turn on/off LED */ - mac->ops.led_on = e1000_led_on_ich8lan; - mac->ops.led_off = e1000_led_off_ich8lan; - break; - case e1000_pch2lan: - mac->rar_entry_count = E1000_PCH2_RAR_ENTRIES; - mac->ops.rar_set = e1000_rar_set_pch2lan; - /* fall-through */ - case e1000_pch_lpt: - case e1000_pch_spt: - case e1000_pchlan: - /* check management mode */ - mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan; - /* ID LED init */ - mac->ops.id_led_init = e1000_id_led_init_pchlan; - /* setup LED */ - mac->ops.setup_led = e1000_setup_led_pchlan; - /* cleanup LED */ - mac->ops.cleanup_led = e1000_cleanup_led_pchlan; - /* turn on/off LED */ - mac->ops.led_on = e1000_led_on_pchlan; - mac->ops.led_off = e1000_led_off_pchlan; - break; - default: - break; - } - - if ((mac->type == e1000_pch_lpt) || (mac->type == e1000_pch_spt)) { - mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES; - mac->ops.rar_set = e1000_rar_set_pch_lpt; - mac->ops.setup_physical_interface = - e1000_setup_copper_link_pch_lpt; - mac->ops.rar_get_count = e1000_rar_get_count_pch_lpt; - } - - /* Enable PCS Lock-loss workaround for ICH8 */ - if (mac->type == e1000_ich8lan) - e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true); - - return 0; -} - -/** - * __e1000_access_emi_reg_locked - Read/write EMI register - * @hw: pointer to the HW structure - * @addr: EMI address to program - * @data: pointer to value to read/write from/to the EMI address - * @read: boolean flag to indicate read or write - * - * This helper function assumes the SW/FW/HW Semaphore is already acquired. - **/ -static s32 __e1000_access_emi_reg_locked(struct e1000_hw *hw, u16 address, - u16 *data, bool read) -{ - s32 ret_val; - - ret_val = e1e_wphy_locked(hw, I82579_EMI_ADDR, address); - if (ret_val) - return ret_val; - - if (read) - ret_val = e1e_rphy_locked(hw, I82579_EMI_DATA, data); - else - ret_val = e1e_wphy_locked(hw, I82579_EMI_DATA, *data); - - return ret_val; -} - -/** - * e1000_read_emi_reg_locked - Read Extended Management Interface register - * @hw: pointer to the HW structure - * @addr: EMI address to program - * @data: value to be read from the EMI address - * - * Assumes the SW/FW/HW Semaphore is already acquired. - **/ -s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data) -{ - return __e1000_access_emi_reg_locked(hw, addr, data, true); -} - -/** - * e1000_write_emi_reg_locked - Write Extended Management Interface register - * @hw: pointer to the HW structure - * @addr: EMI address to program - * @data: value to be written to the EMI address - * - * Assumes the SW/FW/HW Semaphore is already acquired. - **/ -s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data) -{ - return __e1000_access_emi_reg_locked(hw, addr, &data, false); -} - -/** - * e1000_set_eee_pchlan - Enable/disable EEE support - * @hw: pointer to the HW structure - * - * Enable/disable EEE based on setting in dev_spec structure, the duplex of - * the link and the EEE capabilities of the link partner. The LPI Control - * register bits will remain set only if/when link is up. - * - * EEE LPI must not be asserted earlier than one second after link is up. - * On 82579, EEE LPI should not be enabled until such time otherwise there - * can be link issues with some switches. Other devices can have EEE LPI - * enabled immediately upon link up since they have a timer in hardware which - * prevents LPI from being asserted too early. - **/ -s32 e1000_set_eee_pchlan(struct e1000_hw *hw) -{ - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - s32 ret_val; - u16 lpa, pcs_status, adv, adv_addr, lpi_ctrl, data; - - switch (hw->phy.type) { - case e1000_phy_82579: - lpa = I82579_EEE_LP_ABILITY; - pcs_status = I82579_EEE_PCS_STATUS; - adv_addr = I82579_EEE_ADVERTISEMENT; - break; - case e1000_phy_i217: - lpa = I217_EEE_LP_ABILITY; - pcs_status = I217_EEE_PCS_STATUS; - adv_addr = I217_EEE_ADVERTISEMENT; - break; - default: - return 0; - } - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy_locked(hw, I82579_LPI_CTRL, &lpi_ctrl); - if (ret_val) - goto release; - - /* Clear bits that enable EEE in various speeds */ - lpi_ctrl &= ~I82579_LPI_CTRL_ENABLE_MASK; - - /* Enable EEE if not disabled by user */ - if (!dev_spec->eee_disable) { - /* Save off link partner's EEE ability */ - ret_val = e1000_read_emi_reg_locked(hw, lpa, - &dev_spec->eee_lp_ability); - if (ret_val) - goto release; - - /* Read EEE advertisement */ - ret_val = e1000_read_emi_reg_locked(hw, adv_addr, &adv); - if (ret_val) - goto release; - - /* Enable EEE only for speeds in which the link partner is - * EEE capable and for which we advertise EEE. - */ - if (adv & dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED) - lpi_ctrl |= I82579_LPI_CTRL_1000_ENABLE; - - if (adv & dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) { - e1e_rphy_locked(hw, MII_LPA, &data); - if (data & LPA_100FULL) - lpi_ctrl |= I82579_LPI_CTRL_100_ENABLE; - else - /* EEE is not supported in 100Half, so ignore - * partner's EEE in 100 ability if full-duplex - * is not advertised. - */ - dev_spec->eee_lp_ability &= - ~I82579_EEE_100_SUPPORTED; - } - } - - if (hw->phy.type == e1000_phy_82579) { - ret_val = e1000_read_emi_reg_locked(hw, I82579_LPI_PLL_SHUT, - &data); - if (ret_val) - goto release; - - data &= ~I82579_LPI_100_PLL_SHUT; - ret_val = e1000_write_emi_reg_locked(hw, I82579_LPI_PLL_SHUT, - data); - } - - /* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */ - ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data); - if (ret_val) - goto release; - - ret_val = e1e_wphy_locked(hw, I82579_LPI_CTRL, lpi_ctrl); -release: - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP - * @hw: pointer to the HW structure - * @link: link up bool flag - * - * When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications - * preventing further DMA write requests. Workaround the issue by disabling - * the de-assertion of the clock request when in 1Gpbs mode. - * Also, set appropriate Tx re-transmission timeouts for 10 and 100Half link - * speeds in order to avoid Tx hangs. - **/ -static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link) -{ - u32 fextnvm6 = er32(FEXTNVM6); - u32 status = er32(STATUS); - s32 ret_val = 0; - u16 reg; - - if (link && (status & E1000_STATUS_SPEED_1000)) { - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - ret_val = - e1000e_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, - ®); - if (ret_val) - goto release; - - ret_val = - e1000e_write_kmrn_reg_locked(hw, - E1000_KMRNCTRLSTA_K1_CONFIG, - reg & - ~E1000_KMRNCTRLSTA_K1_ENABLE); - if (ret_val) - goto release; - - usleep_range(10, 20); - - ew32(FEXTNVM6, fextnvm6 | E1000_FEXTNVM6_REQ_PLL_CLK); - - ret_val = - e1000e_write_kmrn_reg_locked(hw, - E1000_KMRNCTRLSTA_K1_CONFIG, - reg); -release: - hw->phy.ops.release(hw); - } else { - /* clear FEXTNVM6 bit 8 on link down or 10/100 */ - fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK; - - if ((hw->phy.revision > 5) || !link || - ((status & E1000_STATUS_SPEED_100) && - (status & E1000_STATUS_FD))) - goto update_fextnvm6; - - ret_val = e1e_rphy(hw, I217_INBAND_CTRL, ®); - if (ret_val) - return ret_val; - - /* Clear link status transmit timeout */ - reg &= ~I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK; - - if (status & E1000_STATUS_SPEED_100) { - /* Set inband Tx timeout to 5x10us for 100Half */ - reg |= 5 << I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT; - - /* Do not extend the K1 entry latency for 100Half */ - fextnvm6 &= ~E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION; - } else { - /* Set inband Tx timeout to 50x10us for 10Full/Half */ - reg |= 50 << - I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT; - - /* Extend the K1 entry latency for 10 Mbps */ - fextnvm6 |= E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION; - } - - ret_val = e1e_wphy(hw, I217_INBAND_CTRL, reg); - if (ret_val) - return ret_val; - -update_fextnvm6: - ew32(FEXTNVM6, fextnvm6); - } - - return ret_val; -} - -/** - * e1000_platform_pm_pch_lpt - Set platform power management values - * @hw: pointer to the HW structure - * @link: bool indicating link status - * - * Set the Latency Tolerance Reporting (LTR) values for the "PCIe-like" - * GbE MAC in the Lynx Point PCH based on Rx buffer size and link speed - * when link is up (which must not exceed the maximum latency supported - * by the platform), otherwise specify there is no LTR requirement. - * Unlike true-PCIe devices which set the LTR maximum snoop/no-snoop - * latencies in the LTR Extended Capability Structure in the PCIe Extended - * Capability register set, on this device LTR is set by writing the - * equivalent snoop/no-snoop latencies in the LTRV register in the MAC and - * set the SEND bit to send an Intel On-chip System Fabric sideband (IOSF-SB) - * message to the PMC. - **/ -static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link) -{ - u32 reg = link << (E1000_LTRV_REQ_SHIFT + E1000_LTRV_NOSNOOP_SHIFT) | - link << E1000_LTRV_REQ_SHIFT | E1000_LTRV_SEND; - u16 lat_enc = 0; /* latency encoded */ - - if (link) { - u16 speed, duplex, scale = 0; - u16 max_snoop, max_nosnoop; - u16 max_ltr_enc; /* max LTR latency encoded */ - u64 value; - u32 rxa; - - if (!hw->adapter->max_frame_size) { - e_dbg("max_frame_size not set.\n"); - return -E1000_ERR_CONFIG; - } - - hw->mac.ops.get_link_up_info(hw, &speed, &duplex); - if (!speed) { - e_dbg("Speed not set.\n"); - return -E1000_ERR_CONFIG; - } - - /* Rx Packet Buffer Allocation size (KB) */ - rxa = er32(PBA) & E1000_PBA_RXA_MASK; - - /* Determine the maximum latency tolerated by the device. - * - * Per the PCIe spec, the tolerated latencies are encoded as - * a 3-bit encoded scale (only 0-5 are valid) multiplied by - * a 10-bit value (0-1023) to provide a range from 1 ns to - * 2^25*(2^10-1) ns. The scale is encoded as 0=2^0ns, - * 1=2^5ns, 2=2^10ns,...5=2^25ns. - */ - rxa *= 512; - value = (rxa > hw->adapter->max_frame_size) ? - (rxa - hw->adapter->max_frame_size) * (16000 / speed) : - 0; - - while (value > PCI_LTR_VALUE_MASK) { - scale++; - value = DIV_ROUND_UP(value, (1 << 5)); - } - if (scale > E1000_LTRV_SCALE_MAX) { - e_dbg("Invalid LTR latency scale %d\n", scale); - return -E1000_ERR_CONFIG; - } - lat_enc = (u16)((scale << PCI_LTR_SCALE_SHIFT) | value); - - /* Determine the maximum latency tolerated by the platform */ - pci_read_config_word(hw->adapter->pdev, E1000_PCI_LTR_CAP_LPT, - &max_snoop); - pci_read_config_word(hw->adapter->pdev, - E1000_PCI_LTR_CAP_LPT + 2, &max_nosnoop); - max_ltr_enc = max_t(u16, max_snoop, max_nosnoop); - - if (lat_enc > max_ltr_enc) - lat_enc = max_ltr_enc; - } - - /* Set Snoop and No-Snoop latencies the same */ - reg |= lat_enc | (lat_enc << E1000_LTRV_NOSNOOP_SHIFT); - ew32(LTRV, reg); - - return 0; -} - -/** - * e1000_enable_ulp_lpt_lp - configure Ultra Low Power mode for LynxPoint-LP - * @hw: pointer to the HW structure - * @to_sx: boolean indicating a system power state transition to Sx - * - * When link is down, configure ULP mode to significantly reduce the power - * to the PHY. If on a Manageability Engine (ME) enabled system, tell the - * ME firmware to start the ULP configuration. If not on an ME enabled - * system, configure the ULP mode by software. - */ -s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) -{ - u32 mac_reg; - s32 ret_val = 0; - u16 phy_reg; - u16 oem_reg = 0; - - if ((hw->mac.type < e1000_pch_lpt) || - (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_LM) || - (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_V) || - (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_LM2) || - (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V2) || - (hw->dev_spec.ich8lan.ulp_state == e1000_ulp_state_on)) - return 0; - - if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID) { - /* Request ME configure ULP mode in the PHY */ - mac_reg = er32(H2ME); - mac_reg |= E1000_H2ME_ULP | E1000_H2ME_ENFORCE_SETTINGS; - ew32(H2ME, mac_reg); - - goto out; - } - - if (!to_sx) { - int i = 0; - - /* Poll up to 5 seconds for Cable Disconnected indication */ - while (!(er32(FEXT) & E1000_FEXT_PHY_CABLE_DISCONNECTED)) { - /* Bail if link is re-acquired */ - if (er32(STATUS) & E1000_STATUS_LU) - return -E1000_ERR_PHY; - - if (i++ == 100) - break; - - msleep(50); - } - e_dbg("CABLE_DISCONNECTED %s set after %dmsec\n", - (er32(FEXT) & - E1000_FEXT_PHY_CABLE_DISCONNECTED) ? "" : "not", i * 50); - } - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - /* Force SMBus mode in PHY */ - ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg); - if (ret_val) - goto release; - phy_reg |= CV_SMB_CTRL_FORCE_SMBUS; - e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg); - - /* Force SMBus mode in MAC */ - mac_reg = er32(CTRL_EXT); - mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; - ew32(CTRL_EXT, mac_reg); - - /* Si workaround for ULP entry flow on i127/rev6 h/w. Enable - * LPLU and disable Gig speed when entering ULP - */ - if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) { - ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS, - &oem_reg); - if (ret_val) - goto release; - - phy_reg = oem_reg; - phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS; - - ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS, - phy_reg); - - if (ret_val) - goto release; - } - - /* Set Inband ULP Exit, Reset to SMBus mode and - * Disable SMBus Release on PERST# in PHY - */ - ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg); - if (ret_val) - goto release; - phy_reg |= (I218_ULP_CONFIG1_RESET_TO_SMBUS | - I218_ULP_CONFIG1_DISABLE_SMB_PERST); - if (to_sx) { - if (er32(WUFC) & E1000_WUFC_LNKC) - phy_reg |= I218_ULP_CONFIG1_WOL_HOST; - else - phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST; - - phy_reg |= I218_ULP_CONFIG1_STICKY_ULP; - phy_reg &= ~I218_ULP_CONFIG1_INBAND_EXIT; - } else { - phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT; - phy_reg &= ~I218_ULP_CONFIG1_STICKY_ULP; - phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST; - } - e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); - - /* Set Disable SMBus Release on PERST# in MAC */ - mac_reg = er32(FEXTNVM7); - mac_reg |= E1000_FEXTNVM7_DISABLE_SMB_PERST; - ew32(FEXTNVM7, mac_reg); - - /* Commit ULP changes in PHY by starting auto ULP configuration */ - phy_reg |= I218_ULP_CONFIG1_START; - e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); - - if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6) && - to_sx && (er32(STATUS) & E1000_STATUS_LU)) { - ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS, - oem_reg); - if (ret_val) - goto release; - } - -release: - hw->phy.ops.release(hw); -out: - if (ret_val) - e_dbg("Error in ULP enable flow: %d\n", ret_val); - else - hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_on; - - return ret_val; -} - -/** - * e1000_disable_ulp_lpt_lp - unconfigure Ultra Low Power mode for LynxPoint-LP - * @hw: pointer to the HW structure - * @force: boolean indicating whether or not to force disabling ULP - * - * Un-configure ULP mode when link is up, the system is transitioned from - * Sx or the driver is unloaded. If on a Manageability Engine (ME) enabled - * system, poll for an indication from ME that ULP has been un-configured. - * If not on an ME enabled system, un-configure the ULP mode by software. - * - * During nominal operation, this function is called when link is acquired - * to disable ULP mode (force=false); otherwise, for example when unloading - * the driver or during Sx->S0 transitions, this is called with force=true - * to forcibly disable ULP. - */ -static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) -{ - s32 ret_val = 0; - u32 mac_reg; - u16 phy_reg; - int i = 0; - - if ((hw->mac.type < e1000_pch_lpt) || - (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_LM) || - (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_V) || - (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_LM2) || - (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V2) || - (hw->dev_spec.ich8lan.ulp_state == e1000_ulp_state_off)) - return 0; - - if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID) { - if (force) { - /* Request ME un-configure ULP mode in the PHY */ - mac_reg = er32(H2ME); - mac_reg &= ~E1000_H2ME_ULP; - mac_reg |= E1000_H2ME_ENFORCE_SETTINGS; - ew32(H2ME, mac_reg); - } - - /* Poll up to 100msec for ME to clear ULP_CFG_DONE */ - while (er32(FWSM) & E1000_FWSM_ULP_CFG_DONE) { - if (i++ == 10) { - ret_val = -E1000_ERR_PHY; - goto out; - } - - usleep_range(10000, 20000); - } - e_dbg("ULP_CONFIG_DONE cleared after %dmsec\n", i * 10); - - if (force) { - mac_reg = er32(H2ME); - mac_reg &= ~E1000_H2ME_ENFORCE_SETTINGS; - ew32(H2ME, mac_reg); - } else { - /* Clear H2ME.ULP after ME ULP configuration */ - mac_reg = er32(H2ME); - mac_reg &= ~E1000_H2ME_ULP; - ew32(H2ME, mac_reg); - } - - goto out; - } - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - if (force) - /* Toggle LANPHYPC Value bit */ - e1000_toggle_lanphypc_pch_lpt(hw); - - /* Unforce SMBus mode in PHY */ - ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg); - if (ret_val) { - /* The MAC might be in PCIe mode, so temporarily force to - * SMBus mode in order to access the PHY. - */ - mac_reg = er32(CTRL_EXT); - mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; - ew32(CTRL_EXT, mac_reg); - - msleep(50); - - ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, - &phy_reg); - if (ret_val) - goto release; - } - phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; - e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg); - - /* Unforce SMBus mode in MAC */ - mac_reg = er32(CTRL_EXT); - mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; - ew32(CTRL_EXT, mac_reg); - - /* When ULP mode was previously entered, K1 was disabled by the - * hardware. Re-Enable K1 in the PHY when exiting ULP. - */ - ret_val = e1000_read_phy_reg_hv_locked(hw, HV_PM_CTRL, &phy_reg); - if (ret_val) - goto release; - phy_reg |= HV_PM_CTRL_K1_ENABLE; - e1000_write_phy_reg_hv_locked(hw, HV_PM_CTRL, phy_reg); - - /* Clear ULP enabled configuration */ - ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg); - if (ret_val) - goto release; - phy_reg &= ~(I218_ULP_CONFIG1_IND | - I218_ULP_CONFIG1_STICKY_ULP | - I218_ULP_CONFIG1_RESET_TO_SMBUS | - I218_ULP_CONFIG1_WOL_HOST | - I218_ULP_CONFIG1_INBAND_EXIT | - I218_ULP_CONFIG1_DISABLE_SMB_PERST); - e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); - - /* Commit ULP changes by starting auto ULP configuration */ - phy_reg |= I218_ULP_CONFIG1_START; - e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); - - /* Clear Disable SMBus Release on PERST# in MAC */ - mac_reg = er32(FEXTNVM7); - mac_reg &= ~E1000_FEXTNVM7_DISABLE_SMB_PERST; - ew32(FEXTNVM7, mac_reg); - -release: - hw->phy.ops.release(hw); - if (force) { - e1000_phy_hw_reset(hw); - msleep(50); - } -out: - if (ret_val) - e_dbg("Error in ULP disable flow: %d\n", ret_val); - else - hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_off; - - return ret_val; -} - -/** - * e1000_check_for_copper_link_ich8lan - Check for link (Copper) - * @hw: pointer to the HW structure - * - * Checks to see of the link status of the hardware has changed. If a - * change in link status has been detected, then we read the PHY registers - * to get the current speed/duplex if link exists. - * - * Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link - * up). - **/ -static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val, tipg_reg = 0; - u16 emi_addr, emi_val = 0; - bool link; - u16 phy_reg; - - /* We only want to go out to the PHY registers to see if Auto-Neg - * has completed and/or if our link status has changed. The - * get_link_status flag is set upon receiving a Link Status - * Change or Rx Sequence Error interrupt. - */ - if (!mac->get_link_status) - return 1; - - /* First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * of the PHY. - */ - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (hw->mac.type == e1000_pchlan) { - ret_val = e1000_k1_gig_workaround_hv(hw, link); - if (ret_val) - return ret_val; - } - - /* When connected at 10Mbps half-duplex, some parts are excessively - * aggressive resulting in many collisions. To avoid this, increase - * the IPG and reduce Rx latency in the PHY. - */ - if (((hw->mac.type == e1000_pch2lan) || - (hw->mac.type == e1000_pch_lpt) || - (hw->mac.type == e1000_pch_spt)) && link) { - u16 speed, duplex; - - e1000e_get_speed_and_duplex_copper(hw, &speed, &duplex); - tipg_reg = er32(TIPG); - tipg_reg &= ~E1000_TIPG_IPGT_MASK; - - if (duplex == HALF_DUPLEX && speed == SPEED_10) { - tipg_reg |= 0xFF; - /* Reduce Rx latency in analog PHY */ - emi_val = 0; - } else if (hw->mac.type == e1000_pch_spt && - duplex == FULL_DUPLEX && speed != SPEED_1000) { - tipg_reg |= 0xC; - emi_val = 1; - } else { - - /* Roll back the default values */ - tipg_reg |= 0x08; - emi_val = 1; - } - - ew32(TIPG, tipg_reg); - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - if (hw->mac.type == e1000_pch2lan) - emi_addr = I82579_RX_CONFIG; - else - emi_addr = I217_RX_CONFIG; - ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val); - - hw->phy.ops.release(hw); - - if (ret_val) - return ret_val; - - if (hw->mac.type == e1000_pch_spt) { - u16 data; - u16 ptr_gap; - - if (speed == SPEED_1000) { - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy_locked(hw, - PHY_REG(776, 20), - &data); - if (ret_val) { - hw->phy.ops.release(hw); - return ret_val; - } - - ptr_gap = (data & (0x3FF << 2)) >> 2; - if (ptr_gap < 0x18) { - data &= ~(0x3FF << 2); - data |= (0x18 << 2); - ret_val = - e1e_wphy_locked(hw, - PHY_REG(776, 20), - data); - } - hw->phy.ops.release(hw); - if (ret_val) - return ret_val; - } - } - } - - /* I217 Packet Loss issue: - * ensure that FEXTNVM4 Beacon Duration is set correctly - * on power up. - * Set the Beacon Duration for I217 to 8 usec - */ - if ((hw->mac.type == e1000_pch_lpt) || (hw->mac.type == e1000_pch_spt)) { - u32 mac_reg; - - mac_reg = er32(FEXTNVM4); - mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; - mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; - ew32(FEXTNVM4, mac_reg); - } - - /* Work-around I218 hang issue */ - if ((hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_LM) || - (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_V) || - (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_LM3) || - (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V3)) { - ret_val = e1000_k1_workaround_lpt_lp(hw, link); - if (ret_val) - return ret_val; - } - if ((hw->mac.type == e1000_pch_lpt) || - (hw->mac.type == e1000_pch_spt)) { - /* Set platform power management values for - * Latency Tolerance Reporting (LTR) - */ - ret_val = e1000_platform_pm_pch_lpt(hw, link); - if (ret_val) - return ret_val; - } - - /* Clear link partner's EEE ability */ - hw->dev_spec.ich8lan.eee_lp_ability = 0; - - /* FEXTNVM6 K1-off workaround */ - if (hw->mac.type == e1000_pch_spt) { - u32 pcieanacfg = er32(PCIEANACFG); - u32 fextnvm6 = er32(FEXTNVM6); - - if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE) - fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE; - else - fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE; - - ew32(FEXTNVM6, fextnvm6); - } - - if (!link) - return 0; /* No link detected */ - - mac->get_link_status = false; - - switch (hw->mac.type) { - case e1000_pch2lan: - ret_val = e1000_k1_workaround_lv(hw); - if (ret_val) - return ret_val; - /* fall-thru */ - case e1000_pchlan: - if (hw->phy.type == e1000_phy_82578) { - ret_val = e1000_link_stall_workaround_hv(hw); - if (ret_val) - return ret_val; - } - - /* Workaround for PCHx parts in half-duplex: - * Set the number of preambles removed from the packet - * when it is passed from the PHY to the MAC to prevent - * the MAC from misinterpreting the packet type. - */ - e1e_rphy(hw, HV_KMRN_FIFO_CTRLSTA, &phy_reg); - phy_reg &= ~HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK; - - if ((er32(STATUS) & E1000_STATUS_FD) != E1000_STATUS_FD) - phy_reg |= (1 << HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT); - - e1e_wphy(hw, HV_KMRN_FIFO_CTRLSTA, phy_reg); - break; - default: - break; - } - - /* Check if there was DownShift, must be checked - * immediately after link-up - */ - e1000e_check_downshift(hw); - - /* Enable/Disable EEE after link up */ - if (hw->phy.type > e1000_phy_82579) { - ret_val = e1000_set_eee_pchlan(hw); - if (ret_val) - return ret_val; - } - - /* If we are forcing speed/duplex, then we simply return since - * we have already determined whether we have link or not. - */ - if (!mac->autoneg) - return 1; - - /* Auto-Neg is enabled. Auto Speed Detection takes care - * of MAC speed/duplex configuration. So we only need to - * configure Collision Distance in the MAC. - */ - mac->ops.config_collision_dist(hw); - - /* Configure Flow Control now that Auto-Neg has completed. - * First, we need to restore the desired flow control - * settings because we may have had to re-autoneg with a - * different link partner. - */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error configuring flow control\n"); - return ret_val; - } - - return 1; -} - -static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - s32 rc; - - rc = e1000_init_mac_params_ich8lan(hw); - if (rc) - return rc; - - rc = e1000_init_nvm_params_ich8lan(hw); - if (rc) - return rc; - - switch (hw->mac.type) { - case e1000_ich8lan: - case e1000_ich9lan: - case e1000_ich10lan: - rc = e1000_init_phy_params_ich8lan(hw); - break; - case e1000_pchlan: - case e1000_pch2lan: - case e1000_pch_lpt: - case e1000_pch_spt: - rc = e1000_init_phy_params_pchlan(hw); - break; - default: - break; - } - if (rc) - return rc; - - /* Disable Jumbo Frame support on parts with Intel 10/100 PHY or - * on parts with MACsec enabled in NVM (reflected in CTRL_EXT). - */ - if ((adapter->hw.phy.type == e1000_phy_ife) || - ((adapter->hw.mac.type >= e1000_pch2lan) && - (!(er32(CTRL_EXT) & E1000_CTRL_EXT_LSECCK)))) { - adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES; - adapter->max_hw_frame_size = VLAN_ETH_FRAME_LEN + ETH_FCS_LEN; - - hw->mac.ops.blink_led = NULL; - } - - if ((adapter->hw.mac.type == e1000_ich8lan) && - (adapter->hw.phy.type != e1000_phy_ife)) - adapter->flags |= FLAG_LSC_GIG_SPEED_DROP; - - /* Enable workaround for 82579 w/ ME enabled */ - if ((adapter->hw.mac.type == e1000_pch2lan) && - (er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) - adapter->flags2 |= FLAG2_PCIM2PCI_ARBITER_WA; - - return 0; -} - -static DEFINE_MUTEX(nvm_mutex); - -/** - * e1000_acquire_nvm_ich8lan - Acquire NVM mutex - * @hw: pointer to the HW structure - * - * Acquires the mutex for performing NVM operations. - **/ -static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw __always_unused *hw) -{ - mutex_lock(&nvm_mutex); - - return 0; -} - -/** - * e1000_release_nvm_ich8lan - Release NVM mutex - * @hw: pointer to the HW structure - * - * Releases the mutex used while performing NVM operations. - **/ -static void e1000_release_nvm_ich8lan(struct e1000_hw __always_unused *hw) -{ - mutex_unlock(&nvm_mutex); -} - -/** - * e1000_acquire_swflag_ich8lan - Acquire software control flag - * @hw: pointer to the HW structure - * - * Acquires the software control flag for performing PHY and select - * MAC CSR accesses. - **/ -static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw) -{ - u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT; - s32 ret_val = 0; - - if (test_and_set_bit(__E1000_ACCESS_SHARED_RESOURCE, - &hw->adapter->state)) { - e_dbg("contention for Phy access\n"); - return -E1000_ERR_PHY; - } - - while (timeout) { - extcnf_ctrl = er32(EXTCNF_CTRL); - if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)) - break; - - mdelay(1); - timeout--; - } - - if (!timeout) { - e_dbg("SW has already locked the resource.\n"); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - - timeout = SW_FLAG_TIMEOUT; - - extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG; - ew32(EXTCNF_CTRL, extcnf_ctrl); - - while (timeout) { - extcnf_ctrl = er32(EXTCNF_CTRL); - if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) - break; - - mdelay(1); - timeout--; - } - - if (!timeout) { - e_dbg("Failed to acquire the semaphore, FW or HW has it: FWSM=0x%8.8x EXTCNF_CTRL=0x%8.8x)\n", - er32(FWSM), extcnf_ctrl); - extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; - ew32(EXTCNF_CTRL, extcnf_ctrl); - ret_val = -E1000_ERR_CONFIG; - goto out; - } - -out: - if (ret_val) - clear_bit(__E1000_ACCESS_SHARED_RESOURCE, &hw->adapter->state); - - return ret_val; -} - -/** - * e1000_release_swflag_ich8lan - Release software control flag - * @hw: pointer to the HW structure - * - * Releases the software control flag for performing PHY and select - * MAC CSR accesses. - **/ -static void e1000_release_swflag_ich8lan(struct e1000_hw *hw) -{ - u32 extcnf_ctrl; - - extcnf_ctrl = er32(EXTCNF_CTRL); - - if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) { - extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG; - ew32(EXTCNF_CTRL, extcnf_ctrl); - } else { - e_dbg("Semaphore unexpectedly released by sw/fw/hw\n"); - } - - clear_bit(__E1000_ACCESS_SHARED_RESOURCE, &hw->adapter->state); -} - -/** - * e1000_check_mng_mode_ich8lan - Checks management mode - * @hw: pointer to the HW structure - * - * This checks if the adapter has any manageability enabled. - * This is a function pointer entry point only called by read/write - * routines for the PHY and NVM parts. - **/ -static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw) -{ - u32 fwsm; - - fwsm = er32(FWSM); - return (fwsm & E1000_ICH_FWSM_FW_VALID) && - ((fwsm & E1000_FWSM_MODE_MASK) == - (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); -} - -/** - * e1000_check_mng_mode_pchlan - Checks management mode - * @hw: pointer to the HW structure - * - * This checks if the adapter has iAMT enabled. - * This is a function pointer entry point only called by read/write - * routines for the PHY and NVM parts. - **/ -static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw) -{ - u32 fwsm; - - fwsm = er32(FWSM); - return (fwsm & E1000_ICH_FWSM_FW_VALID) && - (fwsm & (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT)); -} - -/** - * e1000_rar_set_pch2lan - Set receive address register - * @hw: pointer to the HW structure - * @addr: pointer to the receive address - * @index: receive address array register - * - * Sets the receive address array register at index to the address passed - * in by addr. For 82579, RAR[0] is the base address register that is to - * contain the MAC address but RAR[1-6] are reserved for manageability (ME). - * Use SHRA[0-3] in place of those reserved for ME. - **/ -static int e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) -{ - u32 rar_low, rar_high; - - /* HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian - */ - rar_low = ((u32)addr[0] | - ((u32)addr[1] << 8) | - ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); - - rar_high = ((u32)addr[4] | ((u32)addr[5] << 8)); - - /* If MAC address zero, no need to set the AV bit */ - if (rar_low || rar_high) - rar_high |= E1000_RAH_AV; - - if (index == 0) { - ew32(RAL(index), rar_low); - e1e_flush(); - ew32(RAH(index), rar_high); - e1e_flush(); - return 0; - } - - /* RAR[1-6] are owned by manageability. Skip those and program the - * next address into the SHRA register array. - */ - if (index < (u32)(hw->mac.rar_entry_count)) { - s32 ret_val; - - ret_val = e1000_acquire_swflag_ich8lan(hw); - if (ret_val) - goto out; - - ew32(SHRAL(index - 1), rar_low); - e1e_flush(); - ew32(SHRAH(index - 1), rar_high); - e1e_flush(); - - e1000_release_swflag_ich8lan(hw); - - /* verify the register updates */ - if ((er32(SHRAL(index - 1)) == rar_low) && - (er32(SHRAH(index - 1)) == rar_high)) - return 0; - - e_dbg("SHRA[%d] might be locked by ME - FWSM=0x%8.8x\n", - (index - 1), er32(FWSM)); - } - -out: - e_dbg("Failed to write receive address at index %d\n", index); - return -E1000_ERR_CONFIG; -} - -/** - * e1000_rar_get_count_pch_lpt - Get the number of available SHRA - * @hw: pointer to the HW structure - * - * Get the number of available receive registers that the Host can - * program. SHRA[0-10] are the shared receive address registers - * that are shared between the Host and manageability engine (ME). - * ME can reserve any number of addresses and the host needs to be - * able to tell how many available registers it has access to. - **/ -static u32 e1000_rar_get_count_pch_lpt(struct e1000_hw *hw) -{ - u32 wlock_mac; - u32 num_entries; - - wlock_mac = er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK; - wlock_mac >>= E1000_FWSM_WLOCK_MAC_SHIFT; - - switch (wlock_mac) { - case 0: - /* All SHRA[0..10] and RAR[0] available */ - num_entries = hw->mac.rar_entry_count; - break; - case 1: - /* Only RAR[0] available */ - num_entries = 1; - break; - default: - /* SHRA[0..(wlock_mac - 1)] available + RAR[0] */ - num_entries = wlock_mac + 1; - break; - } - - return num_entries; -} - -/** - * e1000_rar_set_pch_lpt - Set receive address registers - * @hw: pointer to the HW structure - * @addr: pointer to the receive address - * @index: receive address array register - * - * Sets the receive address register array at index to the address passed - * in by addr. For LPT, RAR[0] is the base address register that is to - * contain the MAC address. SHRA[0-10] are the shared receive address - * registers that are shared between the Host and manageability engine (ME). - **/ -static int e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index) -{ - u32 rar_low, rar_high; - u32 wlock_mac; - - /* HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian - */ - rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) | - ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); - - rar_high = ((u32)addr[4] | ((u32)addr[5] << 8)); - - /* If MAC address zero, no need to set the AV bit */ - if (rar_low || rar_high) - rar_high |= E1000_RAH_AV; - - if (index == 0) { - ew32(RAL(index), rar_low); - e1e_flush(); - ew32(RAH(index), rar_high); - e1e_flush(); - return 0; - } - - /* The manageability engine (ME) can lock certain SHRAR registers that - * it is using - those registers are unavailable for use. - */ - if (index < hw->mac.rar_entry_count) { - wlock_mac = er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK; - wlock_mac >>= E1000_FWSM_WLOCK_MAC_SHIFT; - - /* Check if all SHRAR registers are locked */ - if (wlock_mac == 1) - goto out; - - if ((wlock_mac == 0) || (index <= wlock_mac)) { - s32 ret_val; - - ret_val = e1000_acquire_swflag_ich8lan(hw); - - if (ret_val) - goto out; - - ew32(SHRAL_PCH_LPT(index - 1), rar_low); - e1e_flush(); - ew32(SHRAH_PCH_LPT(index - 1), rar_high); - e1e_flush(); - - e1000_release_swflag_ich8lan(hw); - - /* verify the register updates */ - if ((er32(SHRAL_PCH_LPT(index - 1)) == rar_low) && - (er32(SHRAH_PCH_LPT(index - 1)) == rar_high)) - return 0; - } - } - -out: - e_dbg("Failed to write receive address at index %d\n", index); - return -E1000_ERR_CONFIG; -} - -/** - * e1000_check_reset_block_ich8lan - Check if PHY reset is blocked - * @hw: pointer to the HW structure - * - * Checks if firmware is blocking the reset of the PHY. - * This is a function pointer entry point only called by - * reset routines. - **/ -static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw) -{ - bool blocked = false; - int i = 0; - - while ((blocked = !(er32(FWSM) & E1000_ICH_FWSM_RSPCIPHY)) && - (i++ < 10)) - usleep_range(10000, 20000); - return blocked ? E1000_BLK_PHY_RESET : 0; -} - -/** - * e1000_write_smbus_addr - Write SMBus address to PHY needed during Sx states - * @hw: pointer to the HW structure - * - * Assumes semaphore already acquired. - * - **/ -static s32 e1000_write_smbus_addr(struct e1000_hw *hw) -{ - u16 phy_data; - u32 strap = er32(STRAP); - u32 freq = (strap & E1000_STRAP_SMT_FREQ_MASK) >> - E1000_STRAP_SMT_FREQ_SHIFT; - s32 ret_val; - - strap &= E1000_STRAP_SMBUS_ADDRESS_MASK; - - ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~HV_SMB_ADDR_MASK; - phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT); - phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID; - - if (hw->phy.type == e1000_phy_i217) { - /* Restore SMBus frequency */ - if (freq--) { - phy_data &= ~HV_SMB_ADDR_FREQ_MASK; - phy_data |= (freq & (1 << 0)) << - HV_SMB_ADDR_FREQ_LOW_SHIFT; - phy_data |= (freq & (1 << 1)) << - (HV_SMB_ADDR_FREQ_HIGH_SHIFT - 1); - } else { - e_dbg("Unsupported SMB frequency in PHY\n"); - } - } - - return e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data); -} - -/** - * e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration - * @hw: pointer to the HW structure - * - * SW should configure the LCD from the NVM extended configuration region - * as a workaround for certain parts. - **/ -static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask; - s32 ret_val = 0; - u16 word_addr, reg_data, reg_addr, phy_page = 0; - - /* Initialize the PHY from the NVM on ICH platforms. This - * is needed due to an issue where the NVM configuration is - * not properly autoloaded after power transitions. - * Therefore, after each PHY reset, we will load the - * configuration data out of the NVM manually. - */ - switch (hw->mac.type) { - case e1000_ich8lan: - if (phy->type != e1000_phy_igp_3) - return ret_val; - - if ((hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_AMT) || - (hw->adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_C)) { - sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG; - break; - } - /* Fall-thru */ - case e1000_pchlan: - case e1000_pch2lan: - case e1000_pch_lpt: - case e1000_pch_spt: - sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; - break; - default: - return ret_val; - } - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - data = er32(FEXTNVM); - if (!(data & sw_cfg_mask)) - goto release; - - /* Make sure HW does not configure LCD from PHY - * extended configuration before SW configuration - */ - data = er32(EXTCNF_CTRL); - if ((hw->mac.type < e1000_pch2lan) && - (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)) - goto release; - - cnf_size = er32(EXTCNF_SIZE); - cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; - cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT; - if (!cnf_size) - goto release; - - cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK; - cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; - - if (((hw->mac.type == e1000_pchlan) && - !(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)) || - (hw->mac.type > e1000_pchlan)) { - /* HW configures the SMBus address and LEDs when the - * OEM and LCD Write Enable bits are set in the NVM. - * When both NVM bits are cleared, SW will configure - * them instead. - */ - ret_val = e1000_write_smbus_addr(hw); - if (ret_val) - goto release; - - data = er32(LEDCTL); - ret_val = e1000_write_phy_reg_hv_locked(hw, HV_LED_CONFIG, - (u16)data); - if (ret_val) - goto release; - } - - /* Configure LCD from extended configuration region. */ - - /* cnf_base_addr is in DWORD */ - word_addr = (u16)(cnf_base_addr << 1); - - for (i = 0; i < cnf_size; i++) { - ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1, ®_data); - if (ret_val) - goto release; - - ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1), - 1, ®_addr); - if (ret_val) - goto release; - - /* Save off the PHY page for future writes. */ - if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) { - phy_page = reg_data; - continue; - } - - reg_addr &= PHY_REG_MASK; - reg_addr |= phy_page; - - ret_val = e1e_wphy_locked(hw, (u32)reg_addr, reg_data); - if (ret_val) - goto release; - } - -release: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000_k1_gig_workaround_hv - K1 Si workaround - * @hw: pointer to the HW structure - * @link: link up bool flag - * - * If K1 is enabled for 1Gbps, the MAC might stall when transitioning - * from a lower speed. This workaround disables K1 whenever link is at 1Gig - * If link is down, the function will restore the default K1 setting located - * in the NVM. - **/ -static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link) -{ - s32 ret_val = 0; - u16 status_reg = 0; - bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled; - - if (hw->mac.type != e1000_pchlan) - return 0; - - /* Wrap the whole flow with the sw flag */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Disable K1 when link is 1Gbps, otherwise use the NVM setting */ - if (link) { - if (hw->phy.type == e1000_phy_82578) { - ret_val = e1e_rphy_locked(hw, BM_CS_STATUS, - &status_reg); - if (ret_val) - goto release; - - status_reg &= (BM_CS_STATUS_LINK_UP | - BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_MASK); - - if (status_reg == (BM_CS_STATUS_LINK_UP | - BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_1000)) - k1_enable = false; - } - - if (hw->phy.type == e1000_phy_82577) { - ret_val = e1e_rphy_locked(hw, HV_M_STATUS, &status_reg); - if (ret_val) - goto release; - - status_reg &= (HV_M_STATUS_LINK_UP | - HV_M_STATUS_AUTONEG_COMPLETE | - HV_M_STATUS_SPEED_MASK); - - if (status_reg == (HV_M_STATUS_LINK_UP | - HV_M_STATUS_AUTONEG_COMPLETE | - HV_M_STATUS_SPEED_1000)) - k1_enable = false; - } - - /* Link stall fix for link up */ - ret_val = e1e_wphy_locked(hw, PHY_REG(770, 19), 0x0100); - if (ret_val) - goto release; - - } else { - /* Link stall fix for link down */ - ret_val = e1e_wphy_locked(hw, PHY_REG(770, 19), 0x4100); - if (ret_val) - goto release; - } - - ret_val = e1000_configure_k1_ich8lan(hw, k1_enable); - -release: - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_configure_k1_ich8lan - Configure K1 power state - * @hw: pointer to the HW structure - * @enable: K1 state to configure - * - * Configure the K1 power state based on the provided parameter. - * Assumes semaphore already acquired. - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - **/ -s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable) -{ - s32 ret_val; - u32 ctrl_reg = 0; - u32 ctrl_ext = 0; - u32 reg = 0; - u16 kmrn_reg = 0; - - ret_val = e1000e_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, - &kmrn_reg); - if (ret_val) - return ret_val; - - if (k1_enable) - kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE; - else - kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE; - - ret_val = e1000e_write_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, - kmrn_reg); - if (ret_val) - return ret_val; - - usleep_range(20, 40); - ctrl_ext = er32(CTRL_EXT); - ctrl_reg = er32(CTRL); - - reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - reg |= E1000_CTRL_FRCSPD; - ew32(CTRL, reg); - - ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS); - e1e_flush(); - usleep_range(20, 40); - ew32(CTRL, ctrl_reg); - ew32(CTRL_EXT, ctrl_ext); - e1e_flush(); - usleep_range(20, 40); - - return 0; -} - -/** - * e1000_oem_bits_config_ich8lan - SW-based LCD Configuration - * @hw: pointer to the HW structure - * @d0_state: boolean if entering d0 or d3 device state - * - * SW will configure Gbe Disable and LPLU based on the NVM. The four bits are - * collectively called OEM bits. The OEM Write Enable bit and SW Config bit - * in NVM determines whether HW should configure LPLU and Gbe Disable. - **/ -static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) -{ - s32 ret_val = 0; - u32 mac_reg; - u16 oem_reg; - - if (hw->mac.type < e1000_pchlan) - return ret_val; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - if (hw->mac.type == e1000_pchlan) { - mac_reg = er32(EXTCNF_CTRL); - if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) - goto release; - } - - mac_reg = er32(FEXTNVM); - if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M)) - goto release; - - mac_reg = er32(PHY_CTRL); - - ret_val = e1e_rphy_locked(hw, HV_OEM_BITS, &oem_reg); - if (ret_val) - goto release; - - oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU); - - if (d0_state) { - if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE) - oem_reg |= HV_OEM_BITS_GBE_DIS; - - if (mac_reg & E1000_PHY_CTRL_D0A_LPLU) - oem_reg |= HV_OEM_BITS_LPLU; - } else { - if (mac_reg & (E1000_PHY_CTRL_GBE_DISABLE | - E1000_PHY_CTRL_NOND0A_GBE_DISABLE)) - oem_reg |= HV_OEM_BITS_GBE_DIS; - - if (mac_reg & (E1000_PHY_CTRL_D0A_LPLU | - E1000_PHY_CTRL_NOND0A_LPLU)) - oem_reg |= HV_OEM_BITS_LPLU; - } - - /* Set Restart auto-neg to activate the bits */ - if ((d0_state || (hw->mac.type != e1000_pchlan)) && - !hw->phy.ops.check_reset_block(hw)) - oem_reg |= HV_OEM_BITS_RESTART_AN; - - ret_val = e1e_wphy_locked(hw, HV_OEM_BITS, oem_reg); - -release: - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode - * @hw: pointer to the HW structure - **/ -static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw) -{ - s32 ret_val; - u16 data; - - ret_val = e1e_rphy(hw, HV_KMRN_MODE_CTRL, &data); - if (ret_val) - return ret_val; - - data |= HV_KMRN_MDIO_SLOW; - - ret_val = e1e_wphy(hw, HV_KMRN_MODE_CTRL, data); - - return ret_val; -} - -/** - * e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be - * done after every PHY reset. - **/ -static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u16 phy_data; - - if (hw->mac.type != e1000_pchlan) - return 0; - - /* Set MDIO slow mode before any other MDIO access */ - if (hw->phy.type == e1000_phy_82577) { - ret_val = e1000_set_mdio_slow_mode_hv(hw); - if (ret_val) - return ret_val; - } - - if (((hw->phy.type == e1000_phy_82577) && - ((hw->phy.revision == 1) || (hw->phy.revision == 2))) || - ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) { - /* Disable generation of early preamble */ - ret_val = e1e_wphy(hw, PHY_REG(769, 25), 0x4431); - if (ret_val) - return ret_val; - - /* Preamble tuning for SSC */ - ret_val = e1e_wphy(hw, HV_KMRN_FIFO_CTRLSTA, 0xA204); - if (ret_val) - return ret_val; - } - - if (hw->phy.type == e1000_phy_82578) { - /* Return registers to default by doing a soft reset then - * writing 0x3140 to the control register. - */ - if (hw->phy.revision < 2) { - e1000e_phy_sw_reset(hw); - ret_val = e1e_wphy(hw, MII_BMCR, 0x3140); - } - } - - /* Select page 0 */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - hw->phy.addr = 1; - ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0); - hw->phy.ops.release(hw); - if (ret_val) - return ret_val; - - /* Configure the K1 Si workaround during phy reset assuming there is - * link so that it disables K1 if link is in 1Gbps. - */ - ret_val = e1000_k1_gig_workaround_hv(hw, true); - if (ret_val) - return ret_val; - - /* Workaround for link disconnects on a busy hub in half duplex */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - ret_val = e1e_rphy_locked(hw, BM_PORT_GEN_CFG, &phy_data); - if (ret_val) - goto release; - ret_val = e1e_wphy_locked(hw, BM_PORT_GEN_CFG, phy_data & 0x00FF); - if (ret_val) - goto release; - - /* set MSE higher to enable link to stay up when noise is high */ - ret_val = e1000_write_emi_reg_locked(hw, I82577_MSE_THRESHOLD, 0x0034); -release: - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_copy_rx_addrs_to_phy_ich8lan - Copy Rx addresses from MAC to PHY - * @hw: pointer to the HW structure - **/ -void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw) -{ - u32 mac_reg; - u16 i, phy_reg = 0; - s32 ret_val; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return; - ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg); - if (ret_val) - goto release; - - /* Copy both RAL/H (rar_entry_count) and SHRAL/H to PHY */ - for (i = 0; i < (hw->mac.rar_entry_count); i++) { - mac_reg = er32(RAL(i)); - hw->phy.ops.write_reg_page(hw, BM_RAR_L(i), - (u16)(mac_reg & 0xFFFF)); - hw->phy.ops.write_reg_page(hw, BM_RAR_M(i), - (u16)((mac_reg >> 16) & 0xFFFF)); - - mac_reg = er32(RAH(i)); - hw->phy.ops.write_reg_page(hw, BM_RAR_H(i), - (u16)(mac_reg & 0xFFFF)); - hw->phy.ops.write_reg_page(hw, BM_RAR_CTRL(i), - (u16)((mac_reg & E1000_RAH_AV) - >> 16)); - } - - e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg); - -release: - hw->phy.ops.release(hw); -} - -/** - * e1000_lv_jumbo_workaround_ich8lan - required for jumbo frame operation - * with 82579 PHY - * @hw: pointer to the HW structure - * @enable: flag to enable/disable workaround when enabling/disabling jumbos - **/ -s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable) -{ - s32 ret_val = 0; - u16 phy_reg, data; - u32 mac_reg; - u16 i; - - if (hw->mac.type < e1000_pch2lan) - return 0; - - /* disable Rx path while enabling/disabling workaround */ - e1e_rphy(hw, PHY_REG(769, 20), &phy_reg); - ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg | (1 << 14)); - if (ret_val) - return ret_val; - - if (enable) { - /* Write Rx addresses (rar_entry_count for RAL/H, and - * SHRAL/H) and initial CRC values to the MAC - */ - for (i = 0; i < hw->mac.rar_entry_count; i++) { - u8 mac_addr[ETH_ALEN] = { 0 }; - u32 addr_high, addr_low; - - addr_high = er32(RAH(i)); - if (!(addr_high & E1000_RAH_AV)) - continue; - addr_low = er32(RAL(i)); - mac_addr[0] = (addr_low & 0xFF); - mac_addr[1] = ((addr_low >> 8) & 0xFF); - mac_addr[2] = ((addr_low >> 16) & 0xFF); - mac_addr[3] = ((addr_low >> 24) & 0xFF); - mac_addr[4] = (addr_high & 0xFF); - mac_addr[5] = ((addr_high >> 8) & 0xFF); - - ew32(PCH_RAICC(i), ~ether_crc_le(ETH_ALEN, mac_addr)); - } - - /* Write Rx addresses to the PHY */ - e1000_copy_rx_addrs_to_phy_ich8lan(hw); - - /* Enable jumbo frame workaround in the MAC */ - mac_reg = er32(FFLT_DBG); - mac_reg &= ~(1 << 14); - mac_reg |= (7 << 15); - ew32(FFLT_DBG, mac_reg); - - mac_reg = er32(RCTL); - mac_reg |= E1000_RCTL_SECRC; - ew32(RCTL, mac_reg); - - ret_val = e1000e_read_kmrn_reg(hw, - E1000_KMRNCTRLSTA_CTRL_OFFSET, - &data); - if (ret_val) - return ret_val; - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_CTRL_OFFSET, - data | (1 << 0)); - if (ret_val) - return ret_val; - ret_val = e1000e_read_kmrn_reg(hw, - E1000_KMRNCTRLSTA_HD_CTRL, - &data); - if (ret_val) - return ret_val; - data &= ~(0xF << 8); - data |= (0xB << 8); - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_HD_CTRL, - data); - if (ret_val) - return ret_val; - - /* Enable jumbo frame workaround in the PHY */ - e1e_rphy(hw, PHY_REG(769, 23), &data); - data &= ~(0x7F << 5); - data |= (0x37 << 5); - ret_val = e1e_wphy(hw, PHY_REG(769, 23), data); - if (ret_val) - return ret_val; - e1e_rphy(hw, PHY_REG(769, 16), &data); - data &= ~(1 << 13); - ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); - if (ret_val) - return ret_val; - e1e_rphy(hw, PHY_REG(776, 20), &data); - data &= ~(0x3FF << 2); - data |= (E1000_TX_PTR_GAP << 2); - ret_val = e1e_wphy(hw, PHY_REG(776, 20), data); - if (ret_val) - return ret_val; - ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0xF100); - if (ret_val) - return ret_val; - e1e_rphy(hw, HV_PM_CTRL, &data); - ret_val = e1e_wphy(hw, HV_PM_CTRL, data | (1 << 10)); - if (ret_val) - return ret_val; - } else { - /* Write MAC register values back to h/w defaults */ - mac_reg = er32(FFLT_DBG); - mac_reg &= ~(0xF << 14); - ew32(FFLT_DBG, mac_reg); - - mac_reg = er32(RCTL); - mac_reg &= ~E1000_RCTL_SECRC; - ew32(RCTL, mac_reg); - - ret_val = e1000e_read_kmrn_reg(hw, - E1000_KMRNCTRLSTA_CTRL_OFFSET, - &data); - if (ret_val) - return ret_val; - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_CTRL_OFFSET, - data & ~(1 << 0)); - if (ret_val) - return ret_val; - ret_val = e1000e_read_kmrn_reg(hw, - E1000_KMRNCTRLSTA_HD_CTRL, - &data); - if (ret_val) - return ret_val; - data &= ~(0xF << 8); - data |= (0xB << 8); - ret_val = e1000e_write_kmrn_reg(hw, - E1000_KMRNCTRLSTA_HD_CTRL, - data); - if (ret_val) - return ret_val; - - /* Write PHY register values back to h/w defaults */ - e1e_rphy(hw, PHY_REG(769, 23), &data); - data &= ~(0x7F << 5); - ret_val = e1e_wphy(hw, PHY_REG(769, 23), data); - if (ret_val) - return ret_val; - e1e_rphy(hw, PHY_REG(769, 16), &data); - data |= (1 << 13); - ret_val = e1e_wphy(hw, PHY_REG(769, 16), data); - if (ret_val) - return ret_val; - e1e_rphy(hw, PHY_REG(776, 20), &data); - data &= ~(0x3FF << 2); - data |= (0x8 << 2); - ret_val = e1e_wphy(hw, PHY_REG(776, 20), data); - if (ret_val) - return ret_val; - ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0x7E00); - if (ret_val) - return ret_val; - e1e_rphy(hw, HV_PM_CTRL, &data); - ret_val = e1e_wphy(hw, HV_PM_CTRL, data & ~(1 << 10)); - if (ret_val) - return ret_val; - } - - /* re-enable Rx path after enabling/disabling workaround */ - return e1e_wphy(hw, PHY_REG(769, 20), phy_reg & ~(1 << 14)); -} - -/** - * e1000_lv_phy_workarounds_ich8lan - A series of Phy workarounds to be - * done after every PHY reset. - **/ -static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = 0; - - if (hw->mac.type != e1000_pch2lan) - return 0; - - /* Set MDIO slow mode before any other MDIO access */ - ret_val = e1000_set_mdio_slow_mode_hv(hw); - if (ret_val) - return ret_val; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - /* set MSE higher to enable link to stay up when noise is high */ - ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_THRESHOLD, 0x0034); - if (ret_val) - goto release; - /* drop link after 5 times MSE threshold was reached */ - ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_LINK_DOWN, 0x0005); -release: - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_k1_gig_workaround_lv - K1 Si workaround - * @hw: pointer to the HW structure - * - * Workaround to set the K1 beacon duration for 82579 parts in 10Mbps - * Disable K1 in 1000Mbps and 100Mbps - **/ -static s32 e1000_k1_workaround_lv(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u16 status_reg = 0; - - if (hw->mac.type != e1000_pch2lan) - return 0; - - /* Set K1 beacon duration based on 10Mbs speed */ - ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg); - if (ret_val) - return ret_val; - - if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) - == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) { - if (status_reg & - (HV_M_STATUS_SPEED_1000 | HV_M_STATUS_SPEED_100)) { - u16 pm_phy_reg; - - /* LV 1G/100 Packet drop issue wa */ - ret_val = e1e_rphy(hw, HV_PM_CTRL, &pm_phy_reg); - if (ret_val) - return ret_val; - pm_phy_reg &= ~HV_PM_CTRL_K1_ENABLE; - ret_val = e1e_wphy(hw, HV_PM_CTRL, pm_phy_reg); - if (ret_val) - return ret_val; - } else { - u32 mac_reg; - - mac_reg = er32(FEXTNVM4); - mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; - mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; - ew32(FEXTNVM4, mac_reg); - } - } - - return ret_val; -} - -/** - * e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware - * @hw: pointer to the HW structure - * @gate: boolean set to true to gate, false to ungate - * - * Gate/ungate the automatic PHY configuration via hardware; perform - * the configuration via software instead. - **/ -static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate) -{ - u32 extcnf_ctrl; - - if (hw->mac.type < e1000_pch2lan) - return; - - extcnf_ctrl = er32(EXTCNF_CTRL); - - if (gate) - extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG; - else - extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG; - - ew32(EXTCNF_CTRL, extcnf_ctrl); -} - -/** - * e1000_lan_init_done_ich8lan - Check for PHY config completion - * @hw: pointer to the HW structure - * - * Check the appropriate indication the MAC has finished configuring the - * PHY after a software reset. - **/ -static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw) -{ - u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT; - - /* Wait for basic configuration completes before proceeding */ - do { - data = er32(STATUS); - data &= E1000_STATUS_LAN_INIT_DONE; - usleep_range(100, 200); - } while ((!data) && --loop); - - /* If basic configuration is incomplete before the above loop - * count reaches 0, loading the configuration from NVM will - * leave the PHY in a bad state possibly resulting in no link. - */ - if (loop == 0) - e_dbg("LAN_INIT_DONE not set, increase timeout\n"); - - /* Clear the Init Done bit for the next init event */ - data = er32(STATUS); - data &= ~E1000_STATUS_LAN_INIT_DONE; - ew32(STATUS, data); -} - -/** - * e1000_post_phy_reset_ich8lan - Perform steps required after a PHY reset - * @hw: pointer to the HW structure - **/ -static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u16 reg; - - if (hw->phy.ops.check_reset_block(hw)) - return 0; - - /* Allow time for h/w to get to quiescent state after reset */ - usleep_range(10000, 20000); - - /* Perform any necessary post-reset workarounds */ - switch (hw->mac.type) { - case e1000_pchlan: - ret_val = e1000_hv_phy_workarounds_ich8lan(hw); - if (ret_val) - return ret_val; - break; - case e1000_pch2lan: - ret_val = e1000_lv_phy_workarounds_ich8lan(hw); - if (ret_val) - return ret_val; - break; - default: - break; - } - - /* Clear the host wakeup bit after lcd reset */ - if (hw->mac.type >= e1000_pchlan) { - e1e_rphy(hw, BM_PORT_GEN_CFG, ®); - reg &= ~BM_WUC_HOST_WU_BIT; - e1e_wphy(hw, BM_PORT_GEN_CFG, reg); - } - - /* Configure the LCD with the extended configuration region in NVM */ - ret_val = e1000_sw_lcd_config_ich8lan(hw); - if (ret_val) - return ret_val; - - /* Configure the LCD with the OEM bits in NVM */ - ret_val = e1000_oem_bits_config_ich8lan(hw, true); - - if (hw->mac.type == e1000_pch2lan) { - /* Ungate automatic PHY configuration on non-managed 82579 */ - if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { - usleep_range(10000, 20000); - e1000_gate_hw_phy_config_ich8lan(hw, false); - } - - /* Set EEE LPI Update Timer to 200usec */ - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - ret_val = e1000_write_emi_reg_locked(hw, - I82579_LPI_UPDATE_TIMER, - 0x1387); - hw->phy.ops.release(hw); - } - - return ret_val; -} - -/** - * e1000_phy_hw_reset_ich8lan - Performs a PHY reset - * @hw: pointer to the HW structure - * - * Resets the PHY - * This is a function pointer entry point called by drivers - * or other shared routines. - **/ -static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = 0; - - /* Gate automatic PHY configuration by hardware on non-managed 82579 */ - if ((hw->mac.type == e1000_pch2lan) && - !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) - e1000_gate_hw_phy_config_ich8lan(hw, true); - - ret_val = e1000e_phy_hw_reset_generic(hw); - if (ret_val) - return ret_val; - - return e1000_post_phy_reset_ich8lan(hw); -} - -/** - * e1000_set_lplu_state_pchlan - Set Low Power Link Up state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU state according to the active flag. For PCH, if OEM write - * bit are disabled in the NVM, writing the LPLU bits in the MAC will not set - * the phy speed. This function will manually set the LPLU bit and restart - * auto-neg as hw would do. D3 and D0 LPLU will call the same function - * since it configures the same bit. - **/ -static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active) -{ - s32 ret_val; - u16 oem_reg; - - ret_val = e1e_rphy(hw, HV_OEM_BITS, &oem_reg); - if (ret_val) - return ret_val; - - if (active) - oem_reg |= HV_OEM_BITS_LPLU; - else - oem_reg &= ~HV_OEM_BITS_LPLU; - - if (!hw->phy.ops.check_reset_block(hw)) - oem_reg |= HV_OEM_BITS_RESTART_AN; - - return e1e_wphy(hw, HV_OEM_BITS, oem_reg); -} - -/** - * e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU D0 state according to the active flag. When - * activating LPLU this function also disables smart speed - * and vice versa. LPLU will not be activated unless the - * device autonegotiation advertisement meets standards of - * either 10 or 10/100 or 10/100/1000 at all duplexes. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 phy_ctrl; - s32 ret_val = 0; - u16 data; - - if (phy->type == e1000_phy_ife) - return 0; - - phy_ctrl = er32(PHY_CTRL); - - if (active) { - phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU; - ew32(PHY_CTRL, phy_ctrl); - - if (phy->type != e1000_phy_igp_3) - return 0; - - /* Call gig speed drop workaround on LPLU before accessing - * any PHY registers - */ - if (hw->mac.type == e1000_ich8lan) - e1000e_gig_downshift_workaround_ich8lan(hw); - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data); - if (ret_val) - return ret_val; - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data); - if (ret_val) - return ret_val; - } else { - phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU; - ew32(PHY_CTRL, phy_ctrl); - - if (phy->type != e1000_phy_igp_3) - return 0; - - /* LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } - } - - return 0; -} - -/** - * e1000_set_d3_lplu_state_ich8lan - Set Low Power Linkup D3 state - * @hw: pointer to the HW structure - * @active: true to enable LPLU, false to disable - * - * Sets the LPLU D3 state according to the active flag. When - * activating LPLU this function also disables smart speed - * and vice versa. LPLU will not be activated unless the - * device autonegotiation advertisement meets standards of - * either 10 or 10/100 or 10/100/1000 at all duplexes. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 phy_ctrl; - s32 ret_val = 0; - u16 data; - - phy_ctrl = er32(PHY_CTRL); - - if (!active) { - phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU; - ew32(PHY_CTRL, phy_ctrl); - - if (phy->type != e1000_phy_igp_3) - return 0; - - /* LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } - } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || - (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || - (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { - phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU; - ew32(PHY_CTRL, phy_ctrl); - - if (phy->type != e1000_phy_igp_3) - return 0; - - /* Call gig speed drop workaround on LPLU before accessing - * any PHY registers - */ - if (hw->mac.type == e1000_ich8lan) - e1000e_gig_downshift_workaround_ich8lan(hw); - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data); - } - - return ret_val; -} - -/** - * e1000_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1 - * @hw: pointer to the HW structure - * @bank: pointer to the variable that returns the active bank - * - * Reads signature byte from the NVM using the flash access registers. - * Word 0x13 bits 15:14 = 10b indicate a valid signature for that bank. - **/ -static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank) -{ - u32 eecd; - struct e1000_nvm_info *nvm = &hw->nvm; - u32 bank1_offset = nvm->flash_bank_size * sizeof(u16); - u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1; - u8 sig_byte = 0; - s32 ret_val; - - switch (hw->mac.type) { - /* In SPT, read from the CTRL_EXT reg instead of - * accessing the sector valid bits from the nvm - */ - case e1000_pch_spt: - *bank = er32(CTRL_EXT) - & E1000_CTRL_EXT_NVMVS; - if ((*bank == 0) || (*bank == 1)) { - e_dbg("ERROR: No valid NVM bank present\n"); - return -E1000_ERR_NVM; - } else { - *bank = *bank - 2; - return 0; - } - break; - case e1000_ich8lan: - case e1000_ich9lan: - eecd = er32(EECD); - if ((eecd & E1000_EECD_SEC1VAL_VALID_MASK) == - E1000_EECD_SEC1VAL_VALID_MASK) { - if (eecd & E1000_EECD_SEC1VAL) - *bank = 1; - else - *bank = 0; - - return 0; - } - e_dbg("Unable to determine valid NVM bank via EEC - reading flash signature\n"); - /* fall-thru */ - default: - /* set bank to 0 in case flash read fails */ - *bank = 0; - - /* Check bank 0 */ - ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset, - &sig_byte); - if (ret_val) - return ret_val; - if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == - E1000_ICH_NVM_SIG_VALUE) { - *bank = 0; - return 0; - } - - /* Check bank 1 */ - ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset + - bank1_offset, - &sig_byte); - if (ret_val) - return ret_val; - if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) == - E1000_ICH_NVM_SIG_VALUE) { - *bank = 1; - return 0; - } - - e_dbg("ERROR: No valid NVM bank present\n"); - return -E1000_ERR_NVM; - } -} - -/** - * e1000_read_nvm_spt - NVM access for SPT - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the word(s) to read. - * @words: Size of data to read in words. - * @data: pointer to the word(s) to read at offset. - * - * Reads a word(s) from the NVM - **/ -static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 act_offset; - s32 ret_val = 0; - u32 bank = 0; - u32 dword = 0; - u16 offset_to_read; - u16 i; - - if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - nvm->ops.acquire(hw); - - ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); - if (ret_val) { - e_dbg("Could not detect valid bank, assuming bank 0\n"); - bank = 0; - } - - act_offset = (bank) ? nvm->flash_bank_size : 0; - act_offset += offset; - - ret_val = 0; - - for (i = 0; i < words; i += 2) { - if (words - i == 1) { - if (dev_spec->shadow_ram[offset + i].modified) { - data[i] = - dev_spec->shadow_ram[offset + i].value; - } else { - offset_to_read = act_offset + i - - ((act_offset + i) % 2); - ret_val = - e1000_read_flash_dword_ich8lan(hw, - offset_to_read, - &dword); - if (ret_val) - break; - if ((act_offset + i) % 2 == 0) - data[i] = (u16)(dword & 0xFFFF); - else - data[i] = (u16)((dword >> 16) & 0xFFFF); - } - } else { - offset_to_read = act_offset + i; - if (!(dev_spec->shadow_ram[offset + i].modified) || - !(dev_spec->shadow_ram[offset + i + 1].modified)) { - ret_val = - e1000_read_flash_dword_ich8lan(hw, - offset_to_read, - &dword); - if (ret_val) - break; - } - if (dev_spec->shadow_ram[offset + i].modified) - data[i] = - dev_spec->shadow_ram[offset + i].value; - else - data[i] = (u16)(dword & 0xFFFF); - if (dev_spec->shadow_ram[offset + i].modified) - data[i + 1] = - dev_spec->shadow_ram[offset + i + 1].value; - else - data[i + 1] = (u16)(dword >> 16 & 0xFFFF); - } - } - - nvm->ops.release(hw); - -out: - if (ret_val) - e_dbg("NVM read error: %d\n", ret_val); - - return ret_val; -} - -/** - * e1000_read_nvm_ich8lan - Read word(s) from the NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the word(s) to read. - * @words: Size of data to read in words - * @data: Pointer to the word(s) to read at offset. - * - * Reads a word(s) from the NVM using the flash access registers. - **/ -static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 act_offset; - s32 ret_val = 0; - u32 bank = 0; - u16 i, word; - - if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - ret_val = -E1000_ERR_NVM; - goto out; - } - - nvm->ops.acquire(hw); - - ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); - if (ret_val) { - e_dbg("Could not detect valid bank, assuming bank 0\n"); - bank = 0; - } - - act_offset = (bank) ? nvm->flash_bank_size : 0; - act_offset += offset; - - ret_val = 0; - for (i = 0; i < words; i++) { - if (dev_spec->shadow_ram[offset + i].modified) { - data[i] = dev_spec->shadow_ram[offset + i].value; - } else { - ret_val = e1000_read_flash_word_ich8lan(hw, - act_offset + i, - &word); - if (ret_val) - break; - data[i] = word; - } - } - - nvm->ops.release(hw); - -out: - if (ret_val) - e_dbg("NVM read error: %d\n", ret_val); - - return ret_val; -} - -/** - * e1000_flash_cycle_init_ich8lan - Initialize flash - * @hw: pointer to the HW structure - * - * This function does initial flash setup so that a new read/write/erase cycle - * can be started. - **/ -static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw) -{ - union ich8_hws_flash_status hsfsts; - s32 ret_val = -E1000_ERR_NVM; - - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - - /* Check if the flash descriptor is valid */ - if (!hsfsts.hsf_status.fldesvalid) { - e_dbg("Flash descriptor invalid. SW Sequencing must be used.\n"); - return -E1000_ERR_NVM; - } - - /* Clear FCERR and DAEL in hw status by writing 1 */ - hsfsts.hsf_status.flcerr = 1; - hsfsts.hsf_status.dael = 1; - if (hw->mac.type == e1000_pch_spt) - ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval & 0xFFFF); - else - ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval); - - /* Either we should have a hardware SPI cycle in progress - * bit to check against, in order to start a new cycle or - * FDONE bit should be changed in the hardware so that it - * is 1 after hardware reset, which can then be used as an - * indication whether a cycle is in progress or has been - * completed. - */ - - if (!hsfsts.hsf_status.flcinprog) { - /* There is no cycle running at present, - * so we can start a cycle. - * Begin by setting Flash Cycle Done. - */ - hsfsts.hsf_status.flcdone = 1; - if (hw->mac.type == e1000_pch_spt) - ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval & 0xFFFF); - else - ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval); - ret_val = 0; - } else { - s32 i; - - /* Otherwise poll for sometime so the current - * cycle has a chance to end before giving up. - */ - for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) { - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (!hsfsts.hsf_status.flcinprog) { - ret_val = 0; - break; - } - udelay(1); - } - if (!ret_val) { - /* Successful in waiting for previous cycle to timeout, - * now set the Flash Cycle Done. - */ - hsfsts.hsf_status.flcdone = 1; - if (hw->mac.type == e1000_pch_spt) - ew32flash(ICH_FLASH_HSFSTS, - hsfsts.regval & 0xFFFF); - else - ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval); - } else { - e_dbg("Flash controller busy, cannot get access\n"); - } - } - - return ret_val; -} - -/** - * e1000_flash_cycle_ich8lan - Starts flash cycle (read/write/erase) - * @hw: pointer to the HW structure - * @timeout: maximum time to wait for completion - * - * This function starts a flash cycle and waits for its completion. - **/ -static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout) -{ - union ich8_hws_flash_ctrl hsflctl; - union ich8_hws_flash_status hsfsts; - u32 i = 0; - - /* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */ - if (hw->mac.type == e1000_pch_spt) - hsflctl.regval = er32flash(ICH_FLASH_HSFSTS) >> 16; - else - hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); - hsflctl.hsf_ctrl.flcgo = 1; - - if (hw->mac.type == e1000_pch_spt) - ew32flash(ICH_FLASH_HSFSTS, hsflctl.regval << 16); - else - ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); - - /* wait till FDONE bit is set to 1 */ - do { - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcdone) - break; - udelay(1); - } while (i++ < timeout); - - if (hsfsts.hsf_status.flcdone && !hsfsts.hsf_status.flcerr) - return 0; - - return -E1000_ERR_NVM; -} - -/** - * e1000_read_flash_dword_ich8lan - Read dword from flash - * @hw: pointer to the HW structure - * @offset: offset to data location - * @data: pointer to the location for storing the data - * - * Reads the flash dword at offset into data. Offset is converted - * to bytes before read. - **/ -static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, u32 offset, - u32 *data) -{ - /* Must convert word offset into bytes. */ - offset <<= 1; - return e1000_read_flash_data32_ich8lan(hw, offset, data); -} - -/** - * e1000_read_flash_word_ich8lan - Read word from flash - * @hw: pointer to the HW structure - * @offset: offset to data location - * @data: pointer to the location for storing the data - * - * Reads the flash word at offset into data. Offset is converted - * to bytes before read. - **/ -static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset, - u16 *data) -{ - /* Must convert offset into bytes. */ - offset <<= 1; - - return e1000_read_flash_data_ich8lan(hw, offset, 2, data); -} - -/** - * e1000_read_flash_byte_ich8lan - Read byte from flash - * @hw: pointer to the HW structure - * @offset: The offset of the byte to read. - * @data: Pointer to a byte to store the value read. - * - * Reads a single byte from the NVM using the flash access registers. - **/ -static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, - u8 *data) -{ - s32 ret_val; - u16 word = 0; - - /* In SPT, only 32 bits access is supported, - * so this function should not be called. - */ - if (hw->mac.type == e1000_pch_spt) - return -E1000_ERR_NVM; - else - ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word); - - if (ret_val) - return ret_val; - - *data = (u8)word; - - return 0; -} - -/** - * e1000_read_flash_data_ich8lan - Read byte or word from NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the byte or word to read. - * @size: Size of data to read, 1=byte 2=word - * @data: Pointer to the word to store the value read. - * - * Reads a byte or word from the NVM using the flash access registers. - **/ -static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, - u8 size, u16 *data) -{ - union ich8_hws_flash_status hsfsts; - union ich8_hws_flash_ctrl hsflctl; - u32 flash_linear_addr; - u32 flash_data = 0; - s32 ret_val = -E1000_ERR_NVM; - u8 count = 0; - - if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) - return -E1000_ERR_NVM; - - flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + - hw->nvm.flash_base_addr); - - do { - udelay(1); - /* Steps */ - ret_val = e1000_flash_cycle_init_ich8lan(hw); - if (ret_val) - break; - - hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); - /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ - hsflctl.hsf_ctrl.fldbcount = size - 1; - hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; - ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); - - ew32flash(ICH_FLASH_FADDR, flash_linear_addr); - - ret_val = - e1000_flash_cycle_ich8lan(hw, - ICH_FLASH_READ_COMMAND_TIMEOUT); - - /* Check if FCERR is set to 1, if set to 1, clear it - * and try the whole sequence a few more times, else - * read in (shift in) the Flash Data0, the order is - * least significant byte first msb to lsb - */ - if (!ret_val) { - flash_data = er32flash(ICH_FLASH_FDATA0); - if (size == 1) - *data = (u8)(flash_data & 0x000000FF); - else if (size == 2) - *data = (u16)(flash_data & 0x0000FFFF); - break; - } else { - /* If we've gotten here, then things are probably - * completely hosed, but if the error condition is - * detected, it won't hurt to give it another try... - * ICH_FLASH_CYCLE_REPEAT_COUNT times. - */ - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr) { - /* Repeat for some time before giving up. */ - continue; - } else if (!hsfsts.hsf_status.flcdone) { - e_dbg("Timeout error - flash cycle did not complete.\n"); - break; - } - } - } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); - - return ret_val; -} - -/** - * e1000_read_flash_data32_ich8lan - Read dword from NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the dword to read. - * @data: Pointer to the dword to store the value read. - * - * Reads a byte or word from the NVM using the flash access registers. - **/ - -static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, - u32 *data) -{ - union ich8_hws_flash_status hsfsts; - union ich8_hws_flash_ctrl hsflctl; - u32 flash_linear_addr; - s32 ret_val = -E1000_ERR_NVM; - u8 count = 0; - - if (offset > ICH_FLASH_LINEAR_ADDR_MASK || - hw->mac.type != e1000_pch_spt) - return -E1000_ERR_NVM; - flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + - hw->nvm.flash_base_addr); - - do { - udelay(1); - /* Steps */ - ret_val = e1000_flash_cycle_init_ich8lan(hw); - if (ret_val) - break; - /* In SPT, This register is in Lan memory space, not flash. - * Therefore, only 32 bit access is supported - */ - hsflctl.regval = er32flash(ICH_FLASH_HSFSTS) >> 16; - - /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ - hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1; - hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ; - /* In SPT, This register is in Lan memory space, not flash. - * Therefore, only 32 bit access is supported - */ - ew32flash(ICH_FLASH_HSFSTS, (u32)hsflctl.regval << 16); - ew32flash(ICH_FLASH_FADDR, flash_linear_addr); - - ret_val = - e1000_flash_cycle_ich8lan(hw, - ICH_FLASH_READ_COMMAND_TIMEOUT); - - /* Check if FCERR is set to 1, if set to 1, clear it - * and try the whole sequence a few more times, else - * read in (shift in) the Flash Data0, the order is - * least significant byte first msb to lsb - */ - if (!ret_val) { - *data = er32flash(ICH_FLASH_FDATA0); - break; - } else { - /* If we've gotten here, then things are probably - * completely hosed, but if the error condition is - * detected, it won't hurt to give it another try... - * ICH_FLASH_CYCLE_REPEAT_COUNT times. - */ - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr) { - /* Repeat for some time before giving up. */ - continue; - } else if (!hsfsts.hsf_status.flcdone) { - e_dbg("Timeout error - flash cycle did not complete.\n"); - break; - } - } - } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); - - return ret_val; -} - -/** - * e1000_write_nvm_ich8lan - Write word(s) to the NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the word(s) to write. - * @words: Size of data to write in words - * @data: Pointer to the word(s) to write at offset. - * - * Writes a byte or word to the NVM using the flash access registers. - **/ -static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words, - u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u16 i; - - if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - return -E1000_ERR_NVM; - } - - nvm->ops.acquire(hw); - - for (i = 0; i < words; i++) { - dev_spec->shadow_ram[offset + i].modified = true; - dev_spec->shadow_ram[offset + i].value = data[i]; - } - - nvm->ops.release(hw); - - return 0; -} - -/** - * e1000_update_nvm_checksum_spt - Update the checksum for NVM - * @hw: pointer to the HW structure - * - * The NVM checksum is updated by calling the generic update_nvm_checksum, - * which writes the checksum to the shadow ram. The changes in the shadow - * ram are then committed to the EEPROM by processing each bank at a time - * checking for the modified bit and writing only the pending changes. - * After a successful commit, the shadow ram is cleared and is ready for - * future writes. - **/ -static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 i, act_offset, new_bank_offset, old_bank_offset, bank; - s32 ret_val; - u32 dword = 0; - - ret_val = e1000e_update_nvm_checksum_generic(hw); - if (ret_val) - goto out; - - if (nvm->type != e1000_nvm_flash_sw) - goto out; - - nvm->ops.acquire(hw); - - /* We're writing to the opposite bank so if we're on bank 1, - * write to bank 0 etc. We also need to erase the segment that - * is going to be written - */ - ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); - if (ret_val) { - e_dbg("Could not detect valid bank, assuming bank 0\n"); - bank = 0; - } - - if (bank == 0) { - new_bank_offset = nvm->flash_bank_size; - old_bank_offset = 0; - ret_val = e1000_erase_flash_bank_ich8lan(hw, 1); - if (ret_val) - goto release; - } else { - old_bank_offset = nvm->flash_bank_size; - new_bank_offset = 0; - ret_val = e1000_erase_flash_bank_ich8lan(hw, 0); - if (ret_val) - goto release; - } - for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i += 2) { - /* Determine whether to write the value stored - * in the other NVM bank or a modified value stored - * in the shadow RAM - */ - ret_val = e1000_read_flash_dword_ich8lan(hw, - i + old_bank_offset, - &dword); - - if (dev_spec->shadow_ram[i].modified) { - dword &= 0xffff0000; - dword |= (dev_spec->shadow_ram[i].value & 0xffff); - } - if (dev_spec->shadow_ram[i + 1].modified) { - dword &= 0x0000ffff; - dword |= ((dev_spec->shadow_ram[i + 1].value & 0xffff) - << 16); - } - if (ret_val) - break; - - /* If the word is 0x13, then make sure the signature bits - * (15:14) are 11b until the commit has completed. - * This will allow us to write 10b which indicates the - * signature is valid. We want to do this after the write - * has completed so that we don't mark the segment valid - * while the write is still in progress - */ - if (i == E1000_ICH_NVM_SIG_WORD - 1) - dword |= E1000_ICH_NVM_SIG_MASK << 16; - - /* Convert offset to bytes. */ - act_offset = (i + new_bank_offset) << 1; - - usleep_range(100, 200); - - /* Write the data to the new bank. Offset in words */ - act_offset = i + new_bank_offset; - ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, - dword); - if (ret_val) - break; - } - - /* Don't bother writing the segment valid bits if sector - * programming failed. - */ - if (ret_val) { - /* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */ - e_dbg("Flash commit failed.\n"); - goto release; - } - - /* Finally validate the new segment by setting bit 15:14 - * to 10b in word 0x13 , this can be done without an - * erase as well since these bits are 11 to start with - * and we need to change bit 14 to 0b - */ - act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD; - - /*offset in words but we read dword */ - --act_offset; - ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword); - - if (ret_val) - goto release; - - dword &= 0xBFFFFFFF; - ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword); - - if (ret_val) - goto release; - - /* And invalidate the previously valid segment by setting - * its signature word (0x13) high_byte to 0b. This can be - * done without an erase because flash erase sets all bits - * to 1's. We can write 1's to 0's without an erase - */ - act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1; - - /* offset in words but we read dword */ - act_offset = old_bank_offset + E1000_ICH_NVM_SIG_WORD - 1; - ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword); - - if (ret_val) - goto release; - - dword &= 0x00FFFFFF; - ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword); - - if (ret_val) - goto release; - - /* Great! Everything worked, we can now clear the cached entries. */ - for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) { - dev_spec->shadow_ram[i].modified = false; - dev_spec->shadow_ram[i].value = 0xFFFF; - } - -release: - nvm->ops.release(hw); - - /* Reload the EEPROM, or else modifications will not appear - * until after the next adapter reset. - */ - if (!ret_val) { - nvm->ops.reload(hw); - usleep_range(10000, 20000); - } - -out: - if (ret_val) - e_dbg("NVM update error: %d\n", ret_val); - - return ret_val; -} - -/** - * e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM - * @hw: pointer to the HW structure - * - * The NVM checksum is updated by calling the generic update_nvm_checksum, - * which writes the checksum to the shadow ram. The changes in the shadow - * ram are then committed to the EEPROM by processing each bank at a time - * checking for the modified bit and writing only the pending changes. - * After a successful commit, the shadow ram is cleared and is ready for - * future writes. - **/ -static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 i, act_offset, new_bank_offset, old_bank_offset, bank; - s32 ret_val; - u16 data = 0; - - ret_val = e1000e_update_nvm_checksum_generic(hw); - if (ret_val) - goto out; - - if (nvm->type != e1000_nvm_flash_sw) - goto out; - - nvm->ops.acquire(hw); - - /* We're writing to the opposite bank so if we're on bank 1, - * write to bank 0 etc. We also need to erase the segment that - * is going to be written - */ - ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank); - if (ret_val) { - e_dbg("Could not detect valid bank, assuming bank 0\n"); - bank = 0; - } - - if (bank == 0) { - new_bank_offset = nvm->flash_bank_size; - old_bank_offset = 0; - ret_val = e1000_erase_flash_bank_ich8lan(hw, 1); - if (ret_val) - goto release; - } else { - old_bank_offset = nvm->flash_bank_size; - new_bank_offset = 0; - ret_val = e1000_erase_flash_bank_ich8lan(hw, 0); - if (ret_val) - goto release; - } - for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) { - if (dev_spec->shadow_ram[i].modified) { - data = dev_spec->shadow_ram[i].value; - } else { - ret_val = e1000_read_flash_word_ich8lan(hw, i + - old_bank_offset, - &data); - if (ret_val) - break; - } - - /* If the word is 0x13, then make sure the signature bits - * (15:14) are 11b until the commit has completed. - * This will allow us to write 10b which indicates the - * signature is valid. We want to do this after the write - * has completed so that we don't mark the segment valid - * while the write is still in progress - */ - if (i == E1000_ICH_NVM_SIG_WORD) - data |= E1000_ICH_NVM_SIG_MASK; - - /* Convert offset to bytes. */ - act_offset = (i + new_bank_offset) << 1; - - usleep_range(100, 200); - /* Write the bytes to the new bank. */ - ret_val = e1000_retry_write_flash_byte_ich8lan(hw, - act_offset, - (u8)data); - if (ret_val) - break; - - usleep_range(100, 200); - ret_val = e1000_retry_write_flash_byte_ich8lan(hw, - act_offset + 1, - (u8)(data >> 8)); - if (ret_val) - break; - } - - /* Don't bother writing the segment valid bits if sector - * programming failed. - */ - if (ret_val) { - /* Possibly read-only, see e1000e_write_protect_nvm_ich8lan() */ - e_dbg("Flash commit failed.\n"); - goto release; - } - - /* Finally validate the new segment by setting bit 15:14 - * to 10b in word 0x13 , this can be done without an - * erase as well since these bits are 11 to start with - * and we need to change bit 14 to 0b - */ - act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD; - ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data); - if (ret_val) - goto release; - - data &= 0xBFFF; - ret_val = e1000_retry_write_flash_byte_ich8lan(hw, - act_offset * 2 + 1, - (u8)(data >> 8)); - if (ret_val) - goto release; - - /* And invalidate the previously valid segment by setting - * its signature word (0x13) high_byte to 0b. This can be - * done without an erase because flash erase sets all bits - * to 1's. We can write 1's to 0's without an erase - */ - act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1; - ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0); - if (ret_val) - goto release; - - /* Great! Everything worked, we can now clear the cached entries. */ - for (i = 0; i < E1000_ICH8_SHADOW_RAM_WORDS; i++) { - dev_spec->shadow_ram[i].modified = false; - dev_spec->shadow_ram[i].value = 0xFFFF; - } - -release: - nvm->ops.release(hw); - - /* Reload the EEPROM, or else modifications will not appear - * until after the next adapter reset. - */ - if (!ret_val) { - nvm->ops.reload(hw); - usleep_range(10000, 20000); - } - -out: - if (ret_val) - e_dbg("NVM update error: %d\n", ret_val); - - return ret_val; -} - -/** - * e1000_validate_nvm_checksum_ich8lan - Validate EEPROM checksum - * @hw: pointer to the HW structure - * - * Check to see if checksum needs to be fixed by reading bit 6 in word 0x19. - * If the bit is 0, that the EEPROM had been modified, but the checksum was not - * calculated, in which case we need to calculate the checksum and set bit 6. - **/ -static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val; - u16 data; - u16 word; - u16 valid_csum_mask; - - /* Read NVM and check Invalid Image CSUM bit. If this bit is 0, - * the checksum needs to be fixed. This bit is an indication that - * the NVM was prepared by OEM software and did not calculate - * the checksum...a likely scenario. - */ - switch (hw->mac.type) { - case e1000_pch_lpt: - case e1000_pch_spt: - word = NVM_COMPAT; - valid_csum_mask = NVM_COMPAT_VALID_CSUM; - break; - default: - word = NVM_FUTURE_INIT_WORD1; - valid_csum_mask = NVM_FUTURE_INIT_WORD1_VALID_CSUM; - break; - } - - ret_val = e1000_read_nvm(hw, word, 1, &data); - if (ret_val) - return ret_val; - - if (!(data & valid_csum_mask)) { - data |= valid_csum_mask; - ret_val = e1000_write_nvm(hw, word, 1, &data); - if (ret_val) - return ret_val; - ret_val = e1000e_update_nvm_checksum(hw); - if (ret_val) - return ret_val; - } - - return e1000e_validate_nvm_checksum_generic(hw); -} - -/** - * e1000e_write_protect_nvm_ich8lan - Make the NVM read-only - * @hw: pointer to the HW structure - * - * To prevent malicious write/erase of the NVM, set it to be read-only - * so that the hardware ignores all write/erase cycles of the NVM via - * the flash control registers. The shadow-ram copy of the NVM will - * still be updated, however any updates to this copy will not stick - * across driver reloads. - **/ -void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - union ich8_flash_protected_range pr0; - union ich8_hws_flash_status hsfsts; - u32 gfpreg; - - nvm->ops.acquire(hw); - - gfpreg = er32flash(ICH_FLASH_GFPREG); - - /* Write-protect GbE Sector of NVM */ - pr0.regval = er32flash(ICH_FLASH_PR0); - pr0.range.base = gfpreg & FLASH_GFPREG_BASE_MASK; - pr0.range.limit = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK); - pr0.range.wpe = true; - ew32flash(ICH_FLASH_PR0, pr0.regval); - - /* Lock down a subset of GbE Flash Control Registers, e.g. - * PR0 to prevent the write-protection from being lifted. - * Once FLOCKDN is set, the registers protected by it cannot - * be written until FLOCKDN is cleared by a hardware reset. - */ - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - hsfsts.hsf_status.flockdn = true; - ew32flash(ICH_FLASH_HSFSTS, hsfsts.regval); - - nvm->ops.release(hw); -} - -/** - * e1000_write_flash_data_ich8lan - Writes bytes to the NVM - * @hw: pointer to the HW structure - * @offset: The offset (in bytes) of the byte/word to read. - * @size: Size of data to read, 1=byte 2=word - * @data: The byte(s) to write to the NVM. - * - * Writes one/two bytes to the NVM using the flash access registers. - **/ -static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset, - u8 size, u16 data) -{ - union ich8_hws_flash_status hsfsts; - union ich8_hws_flash_ctrl hsflctl; - u32 flash_linear_addr; - u32 flash_data = 0; - s32 ret_val; - u8 count = 0; - - if (hw->mac.type == e1000_pch_spt) { - if (size != 4 || offset > ICH_FLASH_LINEAR_ADDR_MASK) - return -E1000_ERR_NVM; - } else { - if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK) - return -E1000_ERR_NVM; - } - - flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + - hw->nvm.flash_base_addr); - - do { - udelay(1); - /* Steps */ - ret_val = e1000_flash_cycle_init_ich8lan(hw); - if (ret_val) - break; - /* In SPT, This register is in Lan memory space, not - * flash. Therefore, only 32 bit access is supported - */ - if (hw->mac.type == e1000_pch_spt) - hsflctl.regval = er32flash(ICH_FLASH_HSFSTS) >> 16; - else - hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); - - /* 0b/1b corresponds to 1 or 2 byte size, respectively. */ - hsflctl.hsf_ctrl.fldbcount = size - 1; - hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; - /* In SPT, This register is in Lan memory space, - * not flash. Therefore, only 32 bit access is - * supported - */ - if (hw->mac.type == e1000_pch_spt) - ew32flash(ICH_FLASH_HSFSTS, hsflctl.regval << 16); - else - ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); - - ew32flash(ICH_FLASH_FADDR, flash_linear_addr); - - if (size == 1) - flash_data = (u32)data & 0x00FF; - else - flash_data = (u32)data; - - ew32flash(ICH_FLASH_FDATA0, flash_data); - - /* check if FCERR is set to 1 , if set to 1, clear it - * and try the whole sequence a few more times else done - */ - ret_val = - e1000_flash_cycle_ich8lan(hw, - ICH_FLASH_WRITE_COMMAND_TIMEOUT); - if (!ret_val) - break; - - /* If we're here, then things are most likely - * completely hosed, but if the error condition - * is detected, it won't hurt to give it another - * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. - */ - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr) - /* Repeat for some time before giving up. */ - continue; - if (!hsfsts.hsf_status.flcdone) { - e_dbg("Timeout error - flash cycle did not complete.\n"); - break; - } - } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); - - return ret_val; -} - -/** -* e1000_write_flash_data32_ich8lan - Writes 4 bytes to the NVM -* @hw: pointer to the HW structure -* @offset: The offset (in bytes) of the dwords to read. -* @data: The 4 bytes to write to the NVM. -* -* Writes one/two/four bytes to the NVM using the flash access registers. -**/ -static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset, - u32 data) -{ - union ich8_hws_flash_status hsfsts; - union ich8_hws_flash_ctrl hsflctl; - u32 flash_linear_addr; - s32 ret_val; - u8 count = 0; - - if (hw->mac.type == e1000_pch_spt) { - if (offset > ICH_FLASH_LINEAR_ADDR_MASK) - return -E1000_ERR_NVM; - } - flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) + - hw->nvm.flash_base_addr); - do { - udelay(1); - /* Steps */ - ret_val = e1000_flash_cycle_init_ich8lan(hw); - if (ret_val) - break; - - /* In SPT, This register is in Lan memory space, not - * flash. Therefore, only 32 bit access is supported - */ - if (hw->mac.type == e1000_pch_spt) - hsflctl.regval = er32flash(ICH_FLASH_HSFSTS) - >> 16; - else - hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); - - hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1; - hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE; - - /* In SPT, This register is in Lan memory space, - * not flash. Therefore, only 32 bit access is - * supported - */ - if (hw->mac.type == e1000_pch_spt) - ew32flash(ICH_FLASH_HSFSTS, hsflctl.regval << 16); - else - ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); - - ew32flash(ICH_FLASH_FADDR, flash_linear_addr); - - ew32flash(ICH_FLASH_FDATA0, data); - - /* check if FCERR is set to 1 , if set to 1, clear it - * and try the whole sequence a few more times else done - */ - ret_val = - e1000_flash_cycle_ich8lan(hw, - ICH_FLASH_WRITE_COMMAND_TIMEOUT); - - if (!ret_val) - break; - - /* If we're here, then things are most likely - * completely hosed, but if the error condition - * is detected, it won't hurt to give it another - * try...ICH_FLASH_CYCLE_REPEAT_COUNT times. - */ - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - - if (hsfsts.hsf_status.flcerr) - /* Repeat for some time before giving up. */ - continue; - if (!hsfsts.hsf_status.flcdone) { - e_dbg("Timeout error - flash cycle did not complete.\n"); - break; - } - } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT); - - return ret_val; -} - -/** - * e1000_write_flash_byte_ich8lan - Write a single byte to NVM - * @hw: pointer to the HW structure - * @offset: The index of the byte to read. - * @data: The byte to write to the NVM. - * - * Writes a single byte to the NVM using the flash access registers. - **/ -static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset, - u8 data) -{ - u16 word = (u16)data; - - return e1000_write_flash_data_ich8lan(hw, offset, 1, word); -} - -/** -* e1000_retry_write_flash_dword_ich8lan - Writes a dword to NVM -* @hw: pointer to the HW structure -* @offset: The offset of the word to write. -* @dword: The dword to write to the NVM. -* -* Writes a single dword to the NVM using the flash access registers. -* Goes through a retry algorithm before giving up. -**/ -static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw, - u32 offset, u32 dword) -{ - s32 ret_val; - u16 program_retries; - - /* Must convert word offset into bytes. */ - offset <<= 1; - ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword); - - if (!ret_val) - return ret_val; - for (program_retries = 0; program_retries < 100; program_retries++) { - e_dbg("Retrying Byte %8.8X at offset %u\n", dword, offset); - usleep_range(100, 200); - ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword); - if (!ret_val) - break; - } - if (program_retries == 100) - return -E1000_ERR_NVM; - - return 0; -} - -/** - * e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM - * @hw: pointer to the HW structure - * @offset: The offset of the byte to write. - * @byte: The byte to write to the NVM. - * - * Writes a single byte to the NVM using the flash access registers. - * Goes through a retry algorithm before giving up. - **/ -static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw, - u32 offset, u8 byte) -{ - s32 ret_val; - u16 program_retries; - - ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); - if (!ret_val) - return ret_val; - - for (program_retries = 0; program_retries < 100; program_retries++) { - e_dbg("Retrying Byte %2.2X at offset %u\n", byte, offset); - usleep_range(100, 200); - ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte); - if (!ret_val) - break; - } - if (program_retries == 100) - return -E1000_ERR_NVM; - - return 0; -} - -/** - * e1000_erase_flash_bank_ich8lan - Erase a bank (4k) from NVM - * @hw: pointer to the HW structure - * @bank: 0 for first bank, 1 for second bank, etc. - * - * Erases the bank specified. Each bank is a 4k block. Banks are 0 based. - * bank N is 4096 * N + flash_reg_addr. - **/ -static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - union ich8_hws_flash_status hsfsts; - union ich8_hws_flash_ctrl hsflctl; - u32 flash_linear_addr; - /* bank size is in 16bit words - adjust to bytes */ - u32 flash_bank_size = nvm->flash_bank_size * 2; - s32 ret_val; - s32 count = 0; - s32 j, iteration, sector_size; - - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - - /* Determine HW Sector size: Read BERASE bits of hw flash status - * register - * 00: The Hw sector is 256 bytes, hence we need to erase 16 - * consecutive sectors. The start index for the nth Hw sector - * can be calculated as = bank * 4096 + n * 256 - * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector. - * The start index for the nth Hw sector can be calculated - * as = bank * 4096 - * 10: The Hw sector is 8K bytes, nth sector = bank * 8192 - * (ich9 only, otherwise error condition) - * 11: The Hw sector is 64K bytes, nth sector = bank * 65536 - */ - switch (hsfsts.hsf_status.berasesz) { - case 0: - /* Hw sector size 256 */ - sector_size = ICH_FLASH_SEG_SIZE_256; - iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_256; - break; - case 1: - sector_size = ICH_FLASH_SEG_SIZE_4K; - iteration = 1; - break; - case 2: - sector_size = ICH_FLASH_SEG_SIZE_8K; - iteration = 1; - break; - case 3: - sector_size = ICH_FLASH_SEG_SIZE_64K; - iteration = 1; - break; - default: - return -E1000_ERR_NVM; - } - - /* Start with the base address, then add the sector offset. */ - flash_linear_addr = hw->nvm.flash_base_addr; - flash_linear_addr += (bank) ? flash_bank_size : 0; - - for (j = 0; j < iteration; j++) { - do { - u32 timeout = ICH_FLASH_ERASE_COMMAND_TIMEOUT; - - /* Steps */ - ret_val = e1000_flash_cycle_init_ich8lan(hw); - if (ret_val) - return ret_val; - - /* Write a value 11 (block Erase) in Flash - * Cycle field in hw flash control - */ - if (hw->mac.type == e1000_pch_spt) - hsflctl.regval = - er32flash(ICH_FLASH_HSFSTS) >> 16; - else - hsflctl.regval = er16flash(ICH_FLASH_HSFCTL); - - hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE; - if (hw->mac.type == e1000_pch_spt) - ew32flash(ICH_FLASH_HSFSTS, - hsflctl.regval << 16); - else - ew16flash(ICH_FLASH_HSFCTL, hsflctl.regval); - - /* Write the last 24 bits of an index within the - * block into Flash Linear address field in Flash - * Address. - */ - flash_linear_addr += (j * sector_size); - ew32flash(ICH_FLASH_FADDR, flash_linear_addr); - - ret_val = e1000_flash_cycle_ich8lan(hw, timeout); - if (!ret_val) - break; - - /* Check if FCERR is set to 1. If 1, - * clear it and try the whole sequence - * a few more times else Done - */ - hsfsts.regval = er16flash(ICH_FLASH_HSFSTS); - if (hsfsts.hsf_status.flcerr) - /* repeat for some time before giving up */ - continue; - else if (!hsfsts.hsf_status.flcdone) - return ret_val; - } while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT); - } - - return 0; -} - -/** - * e1000_valid_led_default_ich8lan - Set the default LED settings - * @hw: pointer to the HW structure - * @data: Pointer to the LED settings - * - * Reads the LED default settings from the NVM to data. If the NVM LED - * settings is all 0's or F's, set the LED default to a valid LED default - * setting. - **/ -static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data) -{ - s32 ret_val; - - ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) - *data = ID_LED_DEFAULT_ICH8LAN; - - return 0; -} - -/** - * e1000_id_led_init_pchlan - store LED configurations - * @hw: pointer to the HW structure - * - * PCH does not control LEDs via the LEDCTL register, rather it uses - * the PHY LED configuration register. - * - * PCH also does not have an "always on" or "always off" mode which - * complicates the ID feature. Instead of using the "on" mode to indicate - * in ledctl_mode2 the LEDs to use for ID (see e1000e_id_led_init_generic()), - * use "link_up" mode. The LEDs will still ID on request if there is no - * link based on logic in e1000_led_[on|off]_pchlan(). - **/ -static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - const u32 ledctl_on = E1000_LEDCTL_MODE_LINK_UP; - const u32 ledctl_off = E1000_LEDCTL_MODE_LINK_UP | E1000_PHY_LED0_IVRT; - u16 data, i, temp, shift; - - /* Get default ID LED modes */ - ret_val = hw->nvm.ops.valid_led_default(hw, &data); - if (ret_val) - return ret_val; - - mac->ledctl_default = er32(LEDCTL); - mac->ledctl_mode1 = mac->ledctl_default; - mac->ledctl_mode2 = mac->ledctl_default; - - for (i = 0; i < 4; i++) { - temp = (data >> (i << 2)) & E1000_LEDCTL_LED0_MODE_MASK; - shift = (i * 5); - switch (temp) { - case ID_LED_ON1_DEF2: - case ID_LED_ON1_ON2: - case ID_LED_ON1_OFF2: - mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); - mac->ledctl_mode1 |= (ledctl_on << shift); - break; - case ID_LED_OFF1_DEF2: - case ID_LED_OFF1_ON2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift); - mac->ledctl_mode1 |= (ledctl_off << shift); - break; - default: - /* Do nothing */ - break; - } - switch (temp) { - case ID_LED_DEF1_ON2: - case ID_LED_ON1_ON2: - case ID_LED_OFF1_ON2: - mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); - mac->ledctl_mode2 |= (ledctl_on << shift); - break; - case ID_LED_DEF1_OFF2: - case ID_LED_ON1_OFF2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift); - mac->ledctl_mode2 |= (ledctl_off << shift); - break; - default: - /* Do nothing */ - break; - } - } - - return 0; -} - -/** - * e1000_get_bus_info_ich8lan - Get/Set the bus type and width - * @hw: pointer to the HW structure - * - * ICH8 use the PCI Express bus, but does not contain a PCI Express Capability - * register, so the the bus width is hard coded. - **/ -static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - s32 ret_val; - - ret_val = e1000e_get_bus_info_pcie(hw); - - /* ICH devices are "PCI Express"-ish. They have - * a configuration space, but do not contain - * PCI Express Capability registers, so bus width - * must be hardcoded. - */ - if (bus->width == e1000_bus_width_unknown) - bus->width = e1000_bus_width_pcie_x1; - - return ret_val; -} - -/** - * e1000_reset_hw_ich8lan - Reset the hardware - * @hw: pointer to the HW structure - * - * Does a full reset of the hardware which includes a reset of the PHY and - * MAC. - **/ -static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw) -{ - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u16 kum_cfg; - u32 ctrl, reg; - s32 ret_val; - - /* Prevent the PCI-E bus from sticking if there is no TLP connection - * on the last TLP read/write transaction when MAC is reset. - */ - ret_val = e1000e_disable_pcie_master(hw); - if (ret_val) - e_dbg("PCI-E Master disable polling has failed.\n"); - - e_dbg("Masking off all interrupts\n"); - ew32(IMC, 0xffffffff); - - /* Disable the Transmit and Receive units. Then delay to allow - * any pending transactions to complete before we hit the MAC - * with the global reset. - */ - ew32(RCTL, 0); - ew32(TCTL, E1000_TCTL_PSP); - e1e_flush(); - - usleep_range(10000, 20000); - - /* Workaround for ICH8 bit corruption issue in FIFO memory */ - if (hw->mac.type == e1000_ich8lan) { - /* Set Tx and Rx buffer allocation to 8k apiece. */ - ew32(PBA, E1000_PBA_8K); - /* Set Packet Buffer Size to 16k. */ - ew32(PBS, E1000_PBS_16K); - } - - if (hw->mac.type == e1000_pchlan) { - /* Save the NVM K1 bit setting */ - ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &kum_cfg); - if (ret_val) - return ret_val; - - if (kum_cfg & E1000_NVM_K1_ENABLE) - dev_spec->nvm_k1_enabled = true; - else - dev_spec->nvm_k1_enabled = false; - } - - ctrl = er32(CTRL); - - if (!hw->phy.ops.check_reset_block(hw)) { - /* Full-chip reset requires MAC and PHY reset at the same - * time to make sure the interface between MAC and the - * external PHY is reset. - */ - ctrl |= E1000_CTRL_PHY_RST; - - /* Gate automatic PHY configuration by hardware on - * non-managed 82579 - */ - if ((hw->mac.type == e1000_pch2lan) && - !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) - e1000_gate_hw_phy_config_ich8lan(hw, true); - } - ret_val = e1000_acquire_swflag_ich8lan(hw); - e_dbg("Issuing a global reset to ich8lan\n"); - ew32(CTRL, (ctrl | E1000_CTRL_RST)); - /* cannot issue a flush here because it hangs the hardware */ - msleep(20); - - /* Set Phy Config Counter to 50msec */ - if (hw->mac.type == e1000_pch2lan) { - reg = er32(FEXTNVM3); - reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; - reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; - ew32(FEXTNVM3, reg); - } - - if (!ret_val) - clear_bit(__E1000_ACCESS_SHARED_RESOURCE, &hw->adapter->state); - - if (ctrl & E1000_CTRL_PHY_RST) { - ret_val = hw->phy.ops.get_cfg_done(hw); - if (ret_val) - return ret_val; - - ret_val = e1000_post_phy_reset_ich8lan(hw); - if (ret_val) - return ret_val; - } - - /* For PCH, this write will make sure that any noise - * will be detected as a CRC error and be dropped rather than show up - * as a bad packet to the DMA engine. - */ - if (hw->mac.type == e1000_pchlan) - ew32(CRC_OFFSET, 0x65656565); - - ew32(IMC, 0xffffffff); - er32(ICR); - - reg = er32(KABGTXD); - reg |= E1000_KABGTXD_BGSQLBIAS; - ew32(KABGTXD, reg); - - return 0; -} - -/** - * e1000_init_hw_ich8lan - Initialize the hardware - * @hw: pointer to the HW structure - * - * Prepares the hardware for transmit and receive by doing the following: - * - initialize hardware bits - * - initialize LED identification - * - setup receive address registers - * - setup flow control - * - setup transmit descriptors - * - clear statistics - **/ -static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 ctrl_ext, txdctl, snoop; - s32 ret_val; - u16 i; - - e1000_initialize_hw_bits_ich8lan(hw); - - /* Initialize identification LED */ - ret_val = mac->ops.id_led_init(hw); - /* An error is not fatal and we should not stop init due to this */ - if (ret_val) - e_dbg("Error initializing identification LED\n"); - - /* Setup the receive address. */ - e1000e_init_rx_addrs(hw, mac->rar_entry_count); - - /* Zero out the Multicast HASH table */ - e_dbg("Zeroing the MTA\n"); - for (i = 0; i < mac->mta_reg_count; i++) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); - - /* The 82578 Rx buffer will stall if wakeup is enabled in host and - * the ME. Disable wakeup by clearing the host wakeup bit. - * Reset the phy after disabling host wakeup to reset the Rx buffer. - */ - if (hw->phy.type == e1000_phy_82578) { - e1e_rphy(hw, BM_PORT_GEN_CFG, &i); - i &= ~BM_WUC_HOST_WU_BIT; - e1e_wphy(hw, BM_PORT_GEN_CFG, i); - ret_val = e1000_phy_hw_reset_ich8lan(hw); - if (ret_val) - return ret_val; - } - - /* Setup link and flow control */ - ret_val = mac->ops.setup_link(hw); - - /* Set the transmit descriptor write-back policy for both queues */ - txdctl = er32(TXDCTL(0)); - txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB); - txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) | - E1000_TXDCTL_MAX_TX_DESC_PREFETCH); - ew32(TXDCTL(0), txdctl); - txdctl = er32(TXDCTL(1)); - txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) | - E1000_TXDCTL_FULL_TX_DESC_WB); - txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) | - E1000_TXDCTL_MAX_TX_DESC_PREFETCH); - ew32(TXDCTL(1), txdctl); - - /* ICH8 has opposite polarity of no_snoop bits. - * By default, we should use snoop behavior. - */ - if (mac->type == e1000_ich8lan) - snoop = PCIE_ICH8_SNOOP_ALL; - else - snoop = (u32)~(PCIE_NO_SNOOP_ALL); - e1000e_set_pcie_no_snoop(hw, snoop); - - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_RO_DIS; - ew32(CTRL_EXT, ctrl_ext); - - /* Clear all of the statistics registers (clear on read). It is - * important that we do this after we have tried to establish link - * because the symbol error count will increment wildly if there - * is no link. - */ - e1000_clear_hw_cntrs_ich8lan(hw); - - return ret_val; -} - -/** - * e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits - * @hw: pointer to the HW structure - * - * Sets/Clears required hardware bits necessary for correctly setting up the - * hardware for transmit and receive. - **/ -static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) -{ - u32 reg; - - /* Extended Device Control */ - reg = er32(CTRL_EXT); - reg |= (1 << 22); - /* Enable PHY low-power state when MAC is at D3 w/o WoL */ - if (hw->mac.type >= e1000_pchlan) - reg |= E1000_CTRL_EXT_PHYPDEN; - ew32(CTRL_EXT, reg); - - /* Transmit Descriptor Control 0 */ - reg = er32(TXDCTL(0)); - reg |= (1 << 22); - ew32(TXDCTL(0), reg); - - /* Transmit Descriptor Control 1 */ - reg = er32(TXDCTL(1)); - reg |= (1 << 22); - ew32(TXDCTL(1), reg); - - /* Transmit Arbitration Control 0 */ - reg = er32(TARC(0)); - if (hw->mac.type == e1000_ich8lan) - reg |= (1 << 28) | (1 << 29); - reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27); - ew32(TARC(0), reg); - - /* Transmit Arbitration Control 1 */ - reg = er32(TARC(1)); - if (er32(TCTL) & E1000_TCTL_MULR) - reg &= ~(1 << 28); - else - reg |= (1 << 28); - reg |= (1 << 24) | (1 << 26) | (1 << 30); - ew32(TARC(1), reg); - - /* Device Status */ - if (hw->mac.type == e1000_ich8lan) { - reg = er32(STATUS); - reg &= ~(1 << 31); - ew32(STATUS, reg); - } - - /* work-around descriptor data corruption issue during nfs v2 udp - * traffic, just disable the nfs filtering capability - */ - reg = er32(RFCTL); - reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS); - - /* Disable IPv6 extension header parsing because some malformed - * IPv6 headers can hang the Rx. - */ - if (hw->mac.type == e1000_ich8lan) - reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); - ew32(RFCTL, reg); - - /* Enable ECC on Lynxpoint */ - if ((hw->mac.type == e1000_pch_lpt) || - (hw->mac.type == e1000_pch_spt)) { - reg = er32(PBECCSTS); - reg |= E1000_PBECCSTS_ECC_ENABLE; - ew32(PBECCSTS, reg); - - reg = er32(CTRL); - reg |= E1000_CTRL_MEHE; - ew32(CTRL, reg); - } -} - -/** - * e1000_setup_link_ich8lan - Setup flow control and link settings - * @hw: pointer to the HW structure - * - * Determines which flow control settings to use, then configures flow - * control. Calls the appropriate media-specific link configuration - * function. Assuming the adapter has a valid link partner, a valid link - * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. - **/ -static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val; - - if (hw->phy.ops.check_reset_block(hw)) - return 0; - - /* ICH parts do not have a word in the NVM to determine - * the default flow control setting, so we explicitly - * set it to full. - */ - if (hw->fc.requested_mode == e1000_fc_default) { - /* Workaround h/w hang when Tx flow control enabled */ - if (hw->mac.type == e1000_pchlan) - hw->fc.requested_mode = e1000_fc_rx_pause; - else - hw->fc.requested_mode = e1000_fc_full; - } - - /* Save off the requested flow control mode for use later. Depending - * on the link partner's capabilities, we may or may not use this mode. - */ - hw->fc.current_mode = hw->fc.requested_mode; - - e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode); - - /* Continue to configure the copper link. */ - ret_val = hw->mac.ops.setup_physical_interface(hw); - if (ret_val) - return ret_val; - - ew32(FCTTV, hw->fc.pause_time); - if ((hw->phy.type == e1000_phy_82578) || - (hw->phy.type == e1000_phy_82579) || - (hw->phy.type == e1000_phy_i217) || - (hw->phy.type == e1000_phy_82577)) { - ew32(FCRTV_PCH, hw->fc.refresh_time); - - ret_val = e1e_wphy(hw, PHY_REG(BM_PORT_CTRL_PAGE, 27), - hw->fc.pause_time); - if (ret_val) - return ret_val; - } - - return e1000e_set_fc_watermarks(hw); -} - -/** - * e1000_setup_copper_link_ich8lan - Configure MAC/PHY interface - * @hw: pointer to the HW structure - * - * Configures the kumeran interface to the PHY to wait the appropriate time - * when polling the PHY, then call the generic setup_copper_link to finish - * configuring the copper link. - **/ -static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - u16 reg_data; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ew32(CTRL, ctrl); - - /* Set the mac to wait the maximum time between each iteration - * and increase the max iterations when polling the phy; - * this fixes erroneous timeouts at 10Mbps. - */ - ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_TIMEOUTS, 0xFFFF); - if (ret_val) - return ret_val; - ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - ®_data); - if (ret_val) - return ret_val; - reg_data |= 0x3F; - ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_INBAND_PARAM, - reg_data); - if (ret_val) - return ret_val; - - switch (hw->phy.type) { - case e1000_phy_igp_3: - ret_val = e1000e_copper_link_setup_igp(hw); - if (ret_val) - return ret_val; - break; - case e1000_phy_bm: - case e1000_phy_82578: - ret_val = e1000e_copper_link_setup_m88(hw); - if (ret_val) - return ret_val; - break; - case e1000_phy_82577: - case e1000_phy_82579: - ret_val = e1000_copper_link_setup_82577(hw); - if (ret_val) - return ret_val; - break; - case e1000_phy_ife: - ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, ®_data); - if (ret_val) - return ret_val; - - reg_data &= ~IFE_PMC_AUTO_MDIX; - - switch (hw->phy.mdix) { - case 1: - reg_data &= ~IFE_PMC_FORCE_MDIX; - break; - case 2: - reg_data |= IFE_PMC_FORCE_MDIX; - break; - case 0: - default: - reg_data |= IFE_PMC_AUTO_MDIX; - break; - } - ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, reg_data); - if (ret_val) - return ret_val; - break; - default: - break; - } - - return e1000e_setup_copper_link(hw); -} - -/** - * e1000_setup_copper_link_pch_lpt - Configure MAC/PHY interface - * @hw: pointer to the HW structure - * - * Calls the PHY specific link setup function and then calls the - * generic setup_copper_link to finish configuring the link for - * Lynxpoint PCH devices - **/ -static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SLU; - ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ew32(CTRL, ctrl); - - ret_val = e1000_copper_link_setup_82577(hw); - if (ret_val) - return ret_val; - - return e1000e_setup_copper_link(hw); -} - -/** - * e1000_get_link_up_info_ich8lan - Get current link speed and duplex - * @hw: pointer to the HW structure - * @speed: pointer to store current link speed - * @duplex: pointer to store the current link duplex - * - * Calls the generic get_speed_and_duplex to retrieve the current link - * information and then calls the Kumeran lock loss workaround for links at - * gigabit speeds. - **/ -static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed, - u16 *duplex) -{ - s32 ret_val; - - ret_val = e1000e_get_speed_and_duplex_copper(hw, speed, duplex); - if (ret_val) - return ret_val; - - if ((hw->mac.type == e1000_ich8lan) && - (hw->phy.type == e1000_phy_igp_3) && (*speed == SPEED_1000)) { - ret_val = e1000_kmrn_lock_loss_workaround_ich8lan(hw); - } - - return ret_val; -} - -/** - * e1000_kmrn_lock_loss_workaround_ich8lan - Kumeran workaround - * @hw: pointer to the HW structure - * - * Work-around for 82566 Kumeran PCS lock loss: - * On link status change (i.e. PCI reset, speed change) and link is up and - * speed is gigabit- - * 0) if workaround is optionally disabled do nothing - * 1) wait 1ms for Kumeran link to come up - * 2) check Kumeran Diagnostic register PCS lock loss bit - * 3) if not set the link is locked (all is good), otherwise... - * 4) reset the PHY - * 5) repeat up to 10 times - * Note: this is only called for IGP3 copper when speed is 1gb. - **/ -static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw) -{ - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 phy_ctrl; - s32 ret_val; - u16 i, data; - bool link; - - if (!dev_spec->kmrn_lock_loss_workaround_enabled) - return 0; - - /* Make sure link is up before proceeding. If not just return. - * Attempting this while link is negotiating fouled up link - * stability - */ - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (!link) - return 0; - - for (i = 0; i < 10; i++) { - /* read once to clear */ - ret_val = e1e_rphy(hw, IGP3_KMRN_DIAG, &data); - if (ret_val) - return ret_val; - /* and again to get new status */ - ret_val = e1e_rphy(hw, IGP3_KMRN_DIAG, &data); - if (ret_val) - return ret_val; - - /* check for PCS lock */ - if (!(data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS)) - return 0; - - /* Issue PHY reset */ - e1000_phy_hw_reset(hw); - mdelay(5); - } - /* Disable GigE link negotiation */ - phy_ctrl = er32(PHY_CTRL); - phy_ctrl |= (E1000_PHY_CTRL_GBE_DISABLE | - E1000_PHY_CTRL_NOND0A_GBE_DISABLE); - ew32(PHY_CTRL, phy_ctrl); - - /* Call gig speed drop workaround on Gig disable before accessing - * any PHY registers - */ - e1000e_gig_downshift_workaround_ich8lan(hw); - - /* unable to acquire PCS lock */ - return -E1000_ERR_PHY; -} - -/** - * e1000e_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state - * @hw: pointer to the HW structure - * @state: boolean value used to set the current Kumeran workaround state - * - * If ICH8, set the current Kumeran workaround state (enabled - true - * /disabled - false). - **/ -void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, - bool state) -{ - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - - if (hw->mac.type != e1000_ich8lan) { - e_dbg("Workaround applies to ICH8 only.\n"); - return; - } - - dev_spec->kmrn_lock_loss_workaround_enabled = state; -} - -/** - * e1000_ipg3_phy_powerdown_workaround_ich8lan - Power down workaround on D3 - * @hw: pointer to the HW structure - * - * Workaround for 82566 power-down on D3 entry: - * 1) disable gigabit link - * 2) write VR power-down enable - * 3) read it back - * Continue if successful, else issue LCD reset and repeat - **/ -void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw) -{ - u32 reg; - u16 data; - u8 retry = 0; - - if (hw->phy.type != e1000_phy_igp_3) - return; - - /* Try the workaround twice (if needed) */ - do { - /* Disable link */ - reg = er32(PHY_CTRL); - reg |= (E1000_PHY_CTRL_GBE_DISABLE | - E1000_PHY_CTRL_NOND0A_GBE_DISABLE); - ew32(PHY_CTRL, reg); - - /* Call gig speed drop workaround on Gig disable before - * accessing any PHY registers - */ - if (hw->mac.type == e1000_ich8lan) - e1000e_gig_downshift_workaround_ich8lan(hw); - - /* Write VR power-down enable */ - e1e_rphy(hw, IGP3_VR_CTRL, &data); - data &= ~IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; - e1e_wphy(hw, IGP3_VR_CTRL, data | IGP3_VR_CTRL_MODE_SHUTDOWN); - - /* Read it back and test */ - e1e_rphy(hw, IGP3_VR_CTRL, &data); - data &= IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK; - if ((data == IGP3_VR_CTRL_MODE_SHUTDOWN) || retry) - break; - - /* Issue PHY reset and repeat at most one more time */ - reg = er32(CTRL); - ew32(CTRL, reg | E1000_CTRL_PHY_RST); - retry++; - } while (retry); -} - -/** - * e1000e_gig_downshift_workaround_ich8lan - WoL from S5 stops working - * @hw: pointer to the HW structure - * - * Steps to take when dropping from 1Gb/s (eg. link cable removal (LSC), - * LPLU, Gig disable, MDIC PHY reset): - * 1) Set Kumeran Near-end loopback - * 2) Clear Kumeran Near-end loopback - * Should only be called for ICH8[m] devices with any 1G Phy. - **/ -void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val; - u16 reg_data; - - if ((hw->mac.type != e1000_ich8lan) || (hw->phy.type == e1000_phy_ife)) - return; - - ret_val = e1000e_read_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, - ®_data); - if (ret_val) - return; - reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK; - ret_val = e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, - reg_data); - if (ret_val) - return; - reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK; - e1000e_write_kmrn_reg(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET, reg_data); -} - -/** - * e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx - * @hw: pointer to the HW structure - * - * During S0 to Sx transition, it is possible the link remains at gig - * instead of negotiating to a lower speed. Before going to Sx, set - * 'Gig Disable' to force link speed negotiation to a lower speed based on - * the LPLU setting in the NVM or custom setting. For PCH and newer parts, - * the OEM bits PHY register (LED, GbE disable and LPLU configurations) also - * needs to be written. - * Parts that support (and are linked to a partner which support) EEE in - * 100Mbps should disable LPLU since 100Mbps w/ EEE requires less power - * than 10Mbps w/o EEE. - **/ -void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) -{ - struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan; - u32 phy_ctrl; - s32 ret_val; - - phy_ctrl = er32(PHY_CTRL); - phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE; - - if (hw->phy.type == e1000_phy_i217) { - u16 phy_reg, device_id = hw->adapter->pdev->device; - - if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) || - (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) || - (device_id == E1000_DEV_ID_PCH_I218_LM3) || - (device_id == E1000_DEV_ID_PCH_I218_V3) || - (hw->mac.type == e1000_pch_spt)) { - u32 fextnvm6 = er32(FEXTNVM6); - - ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK); - } - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto out; - - if (!dev_spec->eee_disable) { - u16 eee_advert; - - ret_val = - e1000_read_emi_reg_locked(hw, - I217_EEE_ADVERTISEMENT, - &eee_advert); - if (ret_val) - goto release; - - /* Disable LPLU if both link partners support 100BaseT - * EEE and 100Full is advertised on both ends of the - * link, and enable Auto Enable LPI since there will - * be no driver to enable LPI while in Sx. - */ - if ((eee_advert & I82579_EEE_100_SUPPORTED) && - (dev_spec->eee_lp_ability & - I82579_EEE_100_SUPPORTED) && - (hw->phy.autoneg_advertised & ADVERTISE_100_FULL)) { - phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU | - E1000_PHY_CTRL_NOND0A_LPLU); - - /* Set Auto Enable LPI after link up */ - e1e_rphy_locked(hw, - I217_LPI_GPIO_CTRL, &phy_reg); - phy_reg |= I217_LPI_GPIO_CTRL_AUTO_EN_LPI; - e1e_wphy_locked(hw, - I217_LPI_GPIO_CTRL, phy_reg); - } - } - - /* For i217 Intel Rapid Start Technology support, - * when the system is going into Sx and no manageability engine - * is present, the driver must configure proxy to reset only on - * power good. LPI (Low Power Idle) state must also reset only - * on power good, as well as the MTA (Multicast table array). - * The SMBus release must also be disabled on LCD reset. - */ - if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { - /* Enable proxy to reset only on power good. */ - e1e_rphy_locked(hw, I217_PROXY_CTRL, &phy_reg); - phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE; - e1e_wphy_locked(hw, I217_PROXY_CTRL, phy_reg); - - /* Set bit enable LPI (EEE) to reset only on - * power good. - */ - e1e_rphy_locked(hw, I217_SxCTRL, &phy_reg); - phy_reg |= I217_SxCTRL_ENABLE_LPI_RESET; - e1e_wphy_locked(hw, I217_SxCTRL, phy_reg); - - /* Disable the SMB release on LCD reset. */ - e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg); - phy_reg &= ~I217_MEMPWR_DISABLE_SMB_RELEASE; - e1e_wphy_locked(hw, I217_MEMPWR, phy_reg); - } - - /* Enable MTA to reset for Intel Rapid Start Technology - * Support - */ - e1e_rphy_locked(hw, I217_CGFREG, &phy_reg); - phy_reg |= I217_CGFREG_ENABLE_MTA_RESET; - e1e_wphy_locked(hw, I217_CGFREG, phy_reg); - -release: - hw->phy.ops.release(hw); - } -out: - ew32(PHY_CTRL, phy_ctrl); - - if (hw->mac.type == e1000_ich8lan) - e1000e_gig_downshift_workaround_ich8lan(hw); - - if (hw->mac.type >= e1000_pchlan) { - e1000_oem_bits_config_ich8lan(hw, false); - - /* Reset PHY to activate OEM bits on 82577/8 */ - if (hw->mac.type == e1000_pchlan) - e1000e_phy_hw_reset_generic(hw); - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return; - e1000_write_smbus_addr(hw); - hw->phy.ops.release(hw); - } -} - -/** - * e1000_resume_workarounds_pchlan - workarounds needed during Sx->S0 - * @hw: pointer to the HW structure - * - * During Sx to S0 transitions on non-managed devices or managed devices - * on which PHY resets are not blocked, if the PHY registers cannot be - * accessed properly by the s/w toggle the LANPHYPC value to power cycle - * the PHY. - * On i217, setup Intel Rapid Start Technology. - **/ -void e1000_resume_workarounds_pchlan(struct e1000_hw *hw) -{ - s32 ret_val; - - if (hw->mac.type < e1000_pch2lan) - return; - - ret_val = e1000_init_phy_workarounds_pchlan(hw); - if (ret_val) { - e_dbg("Failed to init PHY flow ret_val=%d\n", ret_val); - return; - } - - /* For i217 Intel Rapid Start Technology support when the system - * is transitioning from Sx and no manageability engine is present - * configure SMBus to restore on reset, disable proxy, and enable - * the reset on MTA (Multicast table array). - */ - if (hw->phy.type == e1000_phy_i217) { - u16 phy_reg; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) { - e_dbg("Failed to setup iRST\n"); - return; - } - - /* Clear Auto Enable LPI after link up */ - e1e_rphy_locked(hw, I217_LPI_GPIO_CTRL, &phy_reg); - phy_reg &= ~I217_LPI_GPIO_CTRL_AUTO_EN_LPI; - e1e_wphy_locked(hw, I217_LPI_GPIO_CTRL, phy_reg); - - if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { - /* Restore clear on SMB if no manageability engine - * is present - */ - ret_val = e1e_rphy_locked(hw, I217_MEMPWR, &phy_reg); - if (ret_val) - goto release; - phy_reg |= I217_MEMPWR_DISABLE_SMB_RELEASE; - e1e_wphy_locked(hw, I217_MEMPWR, phy_reg); - - /* Disable Proxy */ - e1e_wphy_locked(hw, I217_PROXY_CTRL, 0); - } - /* Enable reset on MTA */ - ret_val = e1e_rphy_locked(hw, I217_CGFREG, &phy_reg); - if (ret_val) - goto release; - phy_reg &= ~I217_CGFREG_ENABLE_MTA_RESET; - e1e_wphy_locked(hw, I217_CGFREG, phy_reg); -release: - if (ret_val) - e_dbg("Error %d in resume workarounds\n", ret_val); - hw->phy.ops.release(hw); - } -} - -/** - * e1000_cleanup_led_ich8lan - Restore the default LED operation - * @hw: pointer to the HW structure - * - * Return the LED back to the default configuration. - **/ -static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw) -{ - if (hw->phy.type == e1000_phy_ife) - return e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, 0); - - ew32(LEDCTL, hw->mac.ledctl_default); - return 0; -} - -/** - * e1000_led_on_ich8lan - Turn LEDs on - * @hw: pointer to the HW structure - * - * Turn on the LEDs. - **/ -static s32 e1000_led_on_ich8lan(struct e1000_hw *hw) -{ - if (hw->phy.type == e1000_phy_ife) - return e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, - (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON)); - - ew32(LEDCTL, hw->mac.ledctl_mode2); - return 0; -} - -/** - * e1000_led_off_ich8lan - Turn LEDs off - * @hw: pointer to the HW structure - * - * Turn off the LEDs. - **/ -static s32 e1000_led_off_ich8lan(struct e1000_hw *hw) -{ - if (hw->phy.type == e1000_phy_ife) - return e1e_wphy(hw, IFE_PHY_SPECIAL_CONTROL_LED, - (IFE_PSCL_PROBE_MODE | - IFE_PSCL_PROBE_LEDS_OFF)); - - ew32(LEDCTL, hw->mac.ledctl_mode1); - return 0; -} - -/** - * e1000_setup_led_pchlan - Configures SW controllable LED - * @hw: pointer to the HW structure - * - * This prepares the SW controllable LED for use. - **/ -static s32 e1000_setup_led_pchlan(struct e1000_hw *hw) -{ - return e1e_wphy(hw, HV_LED_CONFIG, (u16)hw->mac.ledctl_mode1); -} - -/** - * e1000_cleanup_led_pchlan - Restore the default LED operation - * @hw: pointer to the HW structure - * - * Return the LED back to the default configuration. - **/ -static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw) -{ - return e1e_wphy(hw, HV_LED_CONFIG, (u16)hw->mac.ledctl_default); -} - -/** - * e1000_led_on_pchlan - Turn LEDs on - * @hw: pointer to the HW structure - * - * Turn on the LEDs. - **/ -static s32 e1000_led_on_pchlan(struct e1000_hw *hw) -{ - u16 data = (u16)hw->mac.ledctl_mode2; - u32 i, led; - - /* If no link, then turn LED on by setting the invert bit - * for each LED that's mode is "link_up" in ledctl_mode2. - */ - if (!(er32(STATUS) & E1000_STATUS_LU)) { - for (i = 0; i < 3; i++) { - led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; - if ((led & E1000_PHY_LED0_MODE_MASK) != - E1000_LEDCTL_MODE_LINK_UP) - continue; - if (led & E1000_PHY_LED0_IVRT) - data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); - else - data |= (E1000_PHY_LED0_IVRT << (i * 5)); - } - } - - return e1e_wphy(hw, HV_LED_CONFIG, data); -} - -/** - * e1000_led_off_pchlan - Turn LEDs off - * @hw: pointer to the HW structure - * - * Turn off the LEDs. - **/ -static s32 e1000_led_off_pchlan(struct e1000_hw *hw) -{ - u16 data = (u16)hw->mac.ledctl_mode1; - u32 i, led; - - /* If no link, then turn LED off by clearing the invert bit - * for each LED that's mode is "link_up" in ledctl_mode1. - */ - if (!(er32(STATUS) & E1000_STATUS_LU)) { - for (i = 0; i < 3; i++) { - led = (data >> (i * 5)) & E1000_PHY_LED0_MASK; - if ((led & E1000_PHY_LED0_MODE_MASK) != - E1000_LEDCTL_MODE_LINK_UP) - continue; - if (led & E1000_PHY_LED0_IVRT) - data &= ~(E1000_PHY_LED0_IVRT << (i * 5)); - else - data |= (E1000_PHY_LED0_IVRT << (i * 5)); - } - } - - return e1e_wphy(hw, HV_LED_CONFIG, data); -} - -/** - * e1000_get_cfg_done_ich8lan - Read config done bit after Full or PHY reset - * @hw: pointer to the HW structure - * - * Read appropriate register for the config done bit for completion status - * and configure the PHY through s/w for EEPROM-less parts. - * - * NOTE: some silicon which is EEPROM-less will fail trying to read the - * config done bit, so only an error is logged and continues. If we were - * to return with error, EEPROM-less silicon would not be able to be reset - * or change link. - **/ -static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u32 bank = 0; - u32 status; - - e1000e_get_cfg_done_generic(hw); - - /* Wait for indication from h/w that it has completed basic config */ - if (hw->mac.type >= e1000_ich10lan) { - e1000_lan_init_done_ich8lan(hw); - } else { - ret_val = e1000e_get_auto_rd_done(hw); - if (ret_val) { - /* When auto config read does not complete, do not - * return with an error. This can happen in situations - * where there is no eeprom and prevents getting link. - */ - e_dbg("Auto Read Done did not complete\n"); - ret_val = 0; - } - } - - /* Clear PHY Reset Asserted bit */ - status = er32(STATUS); - if (status & E1000_STATUS_PHYRA) - ew32(STATUS, status & ~E1000_STATUS_PHYRA); - else - e_dbg("PHY Reset Asserted not set - needs delay\n"); - - /* If EEPROM is not marked present, init the IGP 3 PHY manually */ - if (hw->mac.type <= e1000_ich9lan) { - if (!(er32(EECD) & E1000_EECD_PRES) && - (hw->phy.type == e1000_phy_igp_3)) { - e1000e_phy_init_script_igp3(hw); - } - } else { - if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) { - /* Maybe we should do a basic PHY config */ - e_dbg("EEPROM not present\n"); - ret_val = -E1000_ERR_CONFIG; - } - } - - return ret_val; -} - -/** - * e1000_power_down_phy_copper_ich8lan - Remove link during PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, remove the link. - **/ -static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw) -{ - /* If the management interface is not enabled, then power down */ - if (!(hw->mac.ops.check_mng_mode(hw) || - hw->phy.ops.check_reset_block(hw))) - e1000_power_down_phy_copper(hw); -} - -/** - * e1000_clear_hw_cntrs_ich8lan - Clear statistical counters - * @hw: pointer to the HW structure - * - * Clears hardware counters specific to the silicon family and calls - * clear_hw_cntrs_generic to clear all general purpose counters. - **/ -static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) -{ - u16 phy_data; - s32 ret_val; - - e1000e_clear_hw_cntrs_base(hw); - - er32(ALGNERRC); - er32(RXERRC); - er32(TNCRS); - er32(CEXTERR); - er32(TSCTC); - er32(TSCTFC); - - er32(MGTPRC); - er32(MGTPDC); - er32(MGTPTC); - - er32(IAC); - er32(ICRXOC); - - /* Clear PHY statistics registers */ - if ((hw->phy.type == e1000_phy_82578) || - (hw->phy.type == e1000_phy_82579) || - (hw->phy.type == e1000_phy_i217) || - (hw->phy.type == e1000_phy_82577)) { - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return; - ret_val = hw->phy.ops.set_page(hw, - HV_STATS_PAGE << IGP_PAGE_SHIFT); - if (ret_val) - goto release; - hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data); - hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data); -release: - hw->phy.ops.release(hw); - } -} - -static const struct e1000_mac_operations ich8_mac_ops = { - /* check_mng_mode dependent on mac type */ - .check_for_link = e1000_check_for_copper_link_ich8lan, - /* cleanup_led dependent on mac type */ - .clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan, - .get_bus_info = e1000_get_bus_info_ich8lan, - .set_lan_id = e1000_set_lan_id_single_port, - .get_link_up_info = e1000_get_link_up_info_ich8lan, - /* led_on dependent on mac type */ - /* led_off dependent on mac type */ - .update_mc_addr_list = e1000e_update_mc_addr_list_generic, - .reset_hw = e1000_reset_hw_ich8lan, - .init_hw = e1000_init_hw_ich8lan, - .setup_link = e1000_setup_link_ich8lan, - .setup_physical_interface = e1000_setup_copper_link_ich8lan, - /* id_led_init dependent on mac type */ - .config_collision_dist = e1000e_config_collision_dist_generic, - .rar_set = e1000e_rar_set_generic, - .rar_get_count = e1000e_rar_get_count_generic, -}; - -static const struct e1000_phy_operations ich8_phy_ops = { - .acquire = e1000_acquire_swflag_ich8lan, - .check_reset_block = e1000_check_reset_block_ich8lan, - .commit = NULL, - .get_cfg_done = e1000_get_cfg_done_ich8lan, - .get_cable_length = e1000e_get_cable_length_igp_2, - .read_reg = e1000e_read_phy_reg_igp, - .release = e1000_release_swflag_ich8lan, - .reset = e1000_phy_hw_reset_ich8lan, - .set_d0_lplu_state = e1000_set_d0_lplu_state_ich8lan, - .set_d3_lplu_state = e1000_set_d3_lplu_state_ich8lan, - .write_reg = e1000e_write_phy_reg_igp, -}; - -static const struct e1000_nvm_operations ich8_nvm_ops = { - .acquire = e1000_acquire_nvm_ich8lan, - .read = e1000_read_nvm_ich8lan, - .release = e1000_release_nvm_ich8lan, - .reload = e1000e_reload_nvm_generic, - .update = e1000_update_nvm_checksum_ich8lan, - .valid_led_default = e1000_valid_led_default_ich8lan, - .validate = e1000_validate_nvm_checksum_ich8lan, - .write = e1000_write_nvm_ich8lan, -}; - -static const struct e1000_nvm_operations spt_nvm_ops = { - .acquire = e1000_acquire_nvm_ich8lan, - .release = e1000_release_nvm_ich8lan, - .read = e1000_read_nvm_spt, - .update = e1000_update_nvm_checksum_spt, - .reload = e1000e_reload_nvm_generic, - .valid_led_default = e1000_valid_led_default_ich8lan, - .validate = e1000_validate_nvm_checksum_ich8lan, - .write = e1000_write_nvm_ich8lan, -}; - -const struct e1000_info e1000_ich8_info = { - .mac = e1000_ich8lan, - .flags = FLAG_HAS_WOL - | FLAG_IS_ICH - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_APME_IN_WUC, - .pba = 8, - .max_hw_frame_size = VLAN_ETH_FRAME_LEN + ETH_FCS_LEN, - .get_variants = e1000_get_variants_ich8lan, - .mac_ops = &ich8_mac_ops, - .phy_ops = &ich8_phy_ops, - .nvm_ops = &ich8_nvm_ops, -}; - -const struct e1000_info e1000_ich9_info = { - .mac = e1000_ich9lan, - .flags = FLAG_HAS_JUMBO_FRAMES - | FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_APME_IN_WUC, - .pba = 18, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_ich8lan, - .mac_ops = &ich8_mac_ops, - .phy_ops = &ich8_phy_ops, - .nvm_ops = &ich8_nvm_ops, -}; - -const struct e1000_info e1000_ich10_info = { - .mac = e1000_ich10lan, - .flags = FLAG_HAS_JUMBO_FRAMES - | FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_APME_IN_WUC, - .pba = 18, - .max_hw_frame_size = DEFAULT_JUMBO, - .get_variants = e1000_get_variants_ich8lan, - .mac_ops = &ich8_mac_ops, - .phy_ops = &ich8_phy_ops, - .nvm_ops = &ich8_nvm_ops, -}; - -const struct e1000_info e1000_pch_info = { - .mac = e1000_pchlan, - .flags = FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_HAS_JUMBO_FRAMES - | FLAG_DISABLE_FC_PAUSE_TIME /* errata */ - | FLAG_APME_IN_WUC, - .flags2 = FLAG2_HAS_PHY_STATS, - .pba = 26, - .max_hw_frame_size = 4096, - .get_variants = e1000_get_variants_ich8lan, - .mac_ops = &ich8_mac_ops, - .phy_ops = &ich8_phy_ops, - .nvm_ops = &ich8_nvm_ops, -}; - -const struct e1000_info e1000_pch2_info = { - .mac = e1000_pch2lan, - .flags = FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_HAS_HW_TIMESTAMP - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_HAS_JUMBO_FRAMES - | FLAG_APME_IN_WUC, - .flags2 = FLAG2_HAS_PHY_STATS - | FLAG2_HAS_EEE, - .pba = 26, - .max_hw_frame_size = 9022, - .get_variants = e1000_get_variants_ich8lan, - .mac_ops = &ich8_mac_ops, - .phy_ops = &ich8_phy_ops, - .nvm_ops = &ich8_nvm_ops, -}; - -const struct e1000_info e1000_pch_lpt_info = { - .mac = e1000_pch_lpt, - .flags = FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_HAS_HW_TIMESTAMP - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_HAS_JUMBO_FRAMES - | FLAG_APME_IN_WUC, - .flags2 = FLAG2_HAS_PHY_STATS - | FLAG2_HAS_EEE, - .pba = 26, - .max_hw_frame_size = 9022, - .get_variants = e1000_get_variants_ich8lan, - .mac_ops = &ich8_mac_ops, - .phy_ops = &ich8_phy_ops, - .nvm_ops = &ich8_nvm_ops, -}; - -const struct e1000_info e1000_pch_spt_info = { - .mac = e1000_pch_spt, - .flags = FLAG_IS_ICH - | FLAG_HAS_WOL - | FLAG_HAS_HW_TIMESTAMP - | FLAG_HAS_CTRLEXT_ON_LOAD - | FLAG_HAS_AMT - | FLAG_HAS_FLASH - | FLAG_HAS_JUMBO_FRAMES - | FLAG_APME_IN_WUC, - .flags2 = FLAG2_HAS_PHY_STATS - | FLAG2_HAS_EEE, - .pba = 26, - .max_hw_frame_size = 9022, - .get_variants = e1000_get_variants_ich8lan, - .mac_ops = &ich8_mac_ops, - .phy_ops = &ich8_phy_ops, - .nvm_ops = &spt_nvm_ops, -}; diff --git a/addons/e1000e/src/4.4.180/ich8lan.h b/addons/e1000e/src/4.4.180/ich8lan.h deleted file mode 100644 index 34c551e3..00000000 --- a/addons/e1000e/src/4.4.180/ich8lan.h +++ /dev/null @@ -1,310 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#ifndef _E1000E_ICH8LAN_H_ -#define _E1000E_ICH8LAN_H_ - -#define ICH_FLASH_GFPREG 0x0000 -#define ICH_FLASH_HSFSTS 0x0004 -#define ICH_FLASH_HSFCTL 0x0006 -#define ICH_FLASH_FADDR 0x0008 -#define ICH_FLASH_FDATA0 0x0010 -#define ICH_FLASH_PR0 0x0074 - -/* Requires up to 10 seconds when MNG might be accessing part. */ -#define ICH_FLASH_READ_COMMAND_TIMEOUT 10000000 -#define ICH_FLASH_WRITE_COMMAND_TIMEOUT 10000000 -#define ICH_FLASH_ERASE_COMMAND_TIMEOUT 10000000 -#define ICH_FLASH_LINEAR_ADDR_MASK 0x00FFFFFF -#define ICH_FLASH_CYCLE_REPEAT_COUNT 10 - -#define ICH_CYCLE_READ 0 -#define ICH_CYCLE_WRITE 2 -#define ICH_CYCLE_ERASE 3 - -#define FLASH_GFPREG_BASE_MASK 0x1FFF -#define FLASH_SECTOR_ADDR_SHIFT 12 - -#define ICH_FLASH_SEG_SIZE_256 256 -#define ICH_FLASH_SEG_SIZE_4K 4096 -#define ICH_FLASH_SEG_SIZE_8K 8192 -#define ICH_FLASH_SEG_SIZE_64K 65536 - -#define E1000_ICH_FWSM_RSPCIPHY 0x00000040 /* Reset PHY on PCI Reset */ -/* FW established a valid mode */ -#define E1000_ICH_FWSM_FW_VALID 0x00008000 -#define E1000_ICH_FWSM_PCIM2PCI 0x01000000 /* ME PCIm-to-PCI active */ -#define E1000_ICH_FWSM_PCIM2PCI_COUNT 2000 - -#define E1000_ICH_MNG_IAMT_MODE 0x2 - -#define E1000_FWSM_WLOCK_MAC_MASK 0x0380 -#define E1000_FWSM_WLOCK_MAC_SHIFT 7 -#define E1000_FWSM_ULP_CFG_DONE 0x00000400 /* Low power cfg done */ - -/* Shared Receive Address Registers */ -#define E1000_SHRAL_PCH_LPT(_i) (0x05408 + ((_i) * 8)) -#define E1000_SHRAH_PCH_LPT(_i) (0x0540C + ((_i) * 8)) - -#define E1000_H2ME 0x05B50 /* Host to ME */ -#define E1000_H2ME_ULP 0x00000800 /* ULP Indication Bit */ -#define E1000_H2ME_ENFORCE_SETTINGS 0x00001000 /* Enforce Settings */ - -#define ID_LED_DEFAULT_ICH8LAN ((ID_LED_DEF1_DEF2 << 12) | \ - (ID_LED_OFF1_OFF2 << 8) | \ - (ID_LED_OFF1_ON2 << 4) | \ - (ID_LED_DEF1_DEF2)) - -#define E1000_ICH_NVM_SIG_WORD 0x13 -#define E1000_ICH_NVM_SIG_MASK 0xC000 -#define E1000_ICH_NVM_VALID_SIG_MASK 0xC0 -#define E1000_ICH_NVM_SIG_VALUE 0x80 - -#define E1000_ICH8_LAN_INIT_TIMEOUT 1500 - -/* FEXT register bit definition */ -#define E1000_FEXT_PHY_CABLE_DISCONNECTED 0x00000004 - -#define E1000_FEXTNVM_SW_CONFIG 1 -#define E1000_FEXTNVM_SW_CONFIG_ICH8M (1 << 27) /* different on ICH8M */ - -#define E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK 0x0C000000 -#define E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC 0x08000000 - -#define E1000_FEXTNVM4_BEACON_DURATION_MASK 0x7 -#define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7 -#define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3 - -#define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100 -#define E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION 0x00000200 -#define E1000_FEXTNVM6_K1_OFF_ENABLE 0x80000000 -/* bit for disabling packet buffer read */ -#define E1000_FEXTNVM7_DISABLE_PB_READ 0x00040000 -#define E1000_FEXTNVM7_SIDE_CLK_UNGATE 0x00000004 -#define E1000_FEXTNVM7_DISABLE_SMB_PERST 0x00000020 -#define E1000_FEXTNVM9_IOSFSB_CLKGATE_DIS 0x00000800 -#define E1000_FEXTNVM9_IOSFSB_CLKREQ_DIS 0x00001000 -#define E1000_FEXTNVM11_DISABLE_PB_READ 0x00000200 -#define E1000_FEXTNVM11_DISABLE_MULR_FIX 0x00002000 - -/* bit24: RXDCTL thresholds granularity: 0 - cache lines, 1 - descriptors */ -#define E1000_RXDCTL_THRESH_UNIT_DESC 0x01000000 - -#define K1_ENTRY_LATENCY 0 -#define K1_MIN_TIME 1 -#define NVM_SIZE_MULTIPLIER 4096 /*multiplier for NVMS field */ -#define E1000_FLASH_BASE_ADDR 0xE000 /*offset of NVM access regs */ -#define E1000_CTRL_EXT_NVMVS 0x3 /*NVM valid sector */ -#define E1000_TARC0_CB_MULTIQ_3_REQ (1 << 28 | 1 << 29) -#define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL - -#define E1000_ICH_RAR_ENTRIES 7 -#define E1000_PCH2_RAR_ENTRIES 5 /* RAR[0], SHRA[0-3] */ -#define E1000_PCH_LPT_RAR_ENTRIES 12 /* RAR[0], SHRA[0-10] */ - -#define PHY_PAGE_SHIFT 5 -#define PHY_REG(page, reg) (((page) << PHY_PAGE_SHIFT) | \ - ((reg) & MAX_PHY_REG_ADDRESS)) -#define IGP3_KMRN_DIAG PHY_REG(770, 19) /* KMRN Diagnostic */ -#define IGP3_VR_CTRL PHY_REG(776, 18) /* Voltage Regulator Control */ - -#define IGP3_KMRN_DIAG_PCS_LOCK_LOSS 0x0002 -#define IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK 0x0300 -#define IGP3_VR_CTRL_MODE_SHUTDOWN 0x0200 - -/* PHY Wakeup Registers and defines */ -#define BM_PORT_GEN_CFG PHY_REG(BM_PORT_CTRL_PAGE, 17) -#define BM_RCTL PHY_REG(BM_WUC_PAGE, 0) -#define BM_WUC PHY_REG(BM_WUC_PAGE, 1) -#define BM_WUFC PHY_REG(BM_WUC_PAGE, 2) -#define BM_WUS PHY_REG(BM_WUC_PAGE, 3) -#define BM_RAR_L(_i) (BM_PHY_REG(BM_WUC_PAGE, 16 + ((_i) << 2))) -#define BM_RAR_M(_i) (BM_PHY_REG(BM_WUC_PAGE, 17 + ((_i) << 2))) -#define BM_RAR_H(_i) (BM_PHY_REG(BM_WUC_PAGE, 18 + ((_i) << 2))) -#define BM_RAR_CTRL(_i) (BM_PHY_REG(BM_WUC_PAGE, 19 + ((_i) << 2))) -#define BM_MTA(_i) (BM_PHY_REG(BM_WUC_PAGE, 128 + ((_i) << 1))) - -#define BM_RCTL_UPE 0x0001 /* Unicast Promiscuous Mode */ -#define BM_RCTL_MPE 0x0002 /* Multicast Promiscuous Mode */ -#define BM_RCTL_MO_SHIFT 3 /* Multicast Offset Shift */ -#define BM_RCTL_MO_MASK (3 << 3) /* Multicast Offset Mask */ -#define BM_RCTL_BAM 0x0020 /* Broadcast Accept Mode */ -#define BM_RCTL_PMCF 0x0040 /* Pass MAC Control Frames */ -#define BM_RCTL_RFCE 0x0080 /* Rx Flow Control Enable */ - -#define HV_LED_CONFIG PHY_REG(768, 30) /* LED Configuration */ -#define HV_MUX_DATA_CTRL PHY_REG(776, 16) -#define HV_MUX_DATA_CTRL_GEN_TO_MAC 0x0400 -#define HV_MUX_DATA_CTRL_FORCE_SPEED 0x0004 -#define HV_STATS_PAGE 778 -/* Half-duplex collision counts */ -#define HV_SCC_UPPER PHY_REG(HV_STATS_PAGE, 16) /* Single Collision */ -#define HV_SCC_LOWER PHY_REG(HV_STATS_PAGE, 17) -#define HV_ECOL_UPPER PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. */ -#define HV_ECOL_LOWER PHY_REG(HV_STATS_PAGE, 19) -#define HV_MCC_UPPER PHY_REG(HV_STATS_PAGE, 20) /* Multiple Collision */ -#define HV_MCC_LOWER PHY_REG(HV_STATS_PAGE, 21) -#define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision */ -#define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24) -#define HV_COLC_UPPER PHY_REG(HV_STATS_PAGE, 25) /* Collision */ -#define HV_COLC_LOWER PHY_REG(HV_STATS_PAGE, 26) -#define HV_DC_UPPER PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */ -#define HV_DC_LOWER PHY_REG(HV_STATS_PAGE, 28) -#define HV_TNCRS_UPPER PHY_REG(HV_STATS_PAGE, 29) /* Tx with no CRS */ -#define HV_TNCRS_LOWER PHY_REG(HV_STATS_PAGE, 30) - -#define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */ - -#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ -#define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ - -/* SMBus Control Phy Register */ -#define CV_SMB_CTRL PHY_REG(769, 23) -#define CV_SMB_CTRL_FORCE_SMBUS 0x0001 - -/* I218 Ultra Low Power Configuration 1 Register */ -#define I218_ULP_CONFIG1 PHY_REG(779, 16) -#define I218_ULP_CONFIG1_START 0x0001 /* Start auto ULP config */ -#define I218_ULP_CONFIG1_IND 0x0004 /* Pwr up from ULP indication */ -#define I218_ULP_CONFIG1_STICKY_ULP 0x0010 /* Set sticky ULP mode */ -#define I218_ULP_CONFIG1_INBAND_EXIT 0x0020 /* Inband on ULP exit */ -#define I218_ULP_CONFIG1_WOL_HOST 0x0040 /* WoL Host on ULP exit */ -#define I218_ULP_CONFIG1_RESET_TO_SMBUS 0x0100 /* Reset to SMBus mode */ -#define I218_ULP_CONFIG1_DISABLE_SMB_PERST 0x1000 /* Disable on PERST# */ - -/* SMBus Address Phy Register */ -#define HV_SMB_ADDR PHY_REG(768, 26) -#define HV_SMB_ADDR_MASK 0x007F -#define HV_SMB_ADDR_PEC_EN 0x0200 -#define HV_SMB_ADDR_VALID 0x0080 -#define HV_SMB_ADDR_FREQ_MASK 0x1100 -#define HV_SMB_ADDR_FREQ_LOW_SHIFT 8 -#define HV_SMB_ADDR_FREQ_HIGH_SHIFT 12 - -/* Strapping Option Register - RO */ -#define E1000_STRAP 0x0000C -#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000 -#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17 -#define E1000_STRAP_SMT_FREQ_MASK 0x00003000 -#define E1000_STRAP_SMT_FREQ_SHIFT 12 - -/* OEM Bits Phy Register */ -#define HV_OEM_BITS PHY_REG(768, 25) -#define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */ -#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ -#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ - -/* KMRN Mode Control */ -#define HV_KMRN_MODE_CTRL PHY_REG(769, 16) -#define HV_KMRN_MDIO_SLOW 0x0400 - -/* KMRN FIFO Control and Status */ -#define HV_KMRN_FIFO_CTRLSTA PHY_REG(770, 16) -#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK 0x7000 -#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT 12 - -/* PHY Power Management Control */ -#define HV_PM_CTRL PHY_REG(770, 17) -#define HV_PM_CTRL_PLL_STOP_IN_K1_GIGA 0x100 -#define HV_PM_CTRL_K1_ENABLE 0x4000 - -#define SW_FLAG_TIMEOUT 1000 /* SW Semaphore flag timeout in ms */ - -/* Inband Control */ -#define I217_INBAND_CTRL PHY_REG(770, 18) -#define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK 0x3F00 -#define I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT 8 - -/* Low Power Idle GPIO Control */ -#define I217_LPI_GPIO_CTRL PHY_REG(772, 18) -#define I217_LPI_GPIO_CTRL_AUTO_EN_LPI 0x0800 - -/* PHY Low Power Idle Control */ -#define I82579_LPI_CTRL PHY_REG(772, 20) -#define I82579_LPI_CTRL_100_ENABLE 0x2000 -#define I82579_LPI_CTRL_1000_ENABLE 0x4000 -#define I82579_LPI_CTRL_ENABLE_MASK 0x6000 -#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT 0x80 - -/* Extended Management Interface (EMI) Registers */ -#define I82579_EMI_ADDR 0x10 -#define I82579_EMI_DATA 0x11 -#define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */ -#define I82579_MSE_THRESHOLD 0x084F /* 82579 Mean Square Error Threshold */ -#define I82577_MSE_THRESHOLD 0x0887 /* 82577 Mean Square Error Threshold */ -#define I82579_MSE_LINK_DOWN 0x2411 /* MSE count before dropping link */ -#define I82579_RX_CONFIG 0x3412 /* Receive configuration */ -#define I82579_LPI_PLL_SHUT 0x4412 /* LPI PLL Shut Enable */ -#define I82579_EEE_PCS_STATUS 0x182E /* IEEE MMD Register 3.1 >> 8 */ -#define I82579_EEE_CAPABILITY 0x0410 /* IEEE MMD Register 3.20 */ -#define I82579_EEE_ADVERTISEMENT 0x040E /* IEEE MMD Register 7.60 */ -#define I82579_EEE_LP_ABILITY 0x040F /* IEEE MMD Register 7.61 */ -#define I82579_EEE_100_SUPPORTED (1 << 1) /* 100BaseTx EEE */ -#define I82579_EEE_1000_SUPPORTED (1 << 2) /* 1000BaseTx EEE */ -#define I82579_LPI_100_PLL_SHUT (1 << 2) /* 100M LPI PLL Shut Enabled */ -#define I217_EEE_PCS_STATUS 0x9401 /* IEEE MMD Register 3.1 */ -#define I217_EEE_CAPABILITY 0x8000 /* IEEE MMD Register 3.20 */ -#define I217_EEE_ADVERTISEMENT 0x8001 /* IEEE MMD Register 7.60 */ -#define I217_EEE_LP_ABILITY 0x8002 /* IEEE MMD Register 7.61 */ -#define I217_RX_CONFIG 0xB20C /* Receive configuration */ - -#define E1000_EEE_RX_LPI_RCVD 0x0400 /* Tx LP idle received */ -#define E1000_EEE_TX_LPI_RCVD 0x0800 /* Rx LP idle received */ - -/* Intel Rapid Start Technology Support */ -#define I217_PROXY_CTRL BM_PHY_REG(BM_WUC_PAGE, 70) -#define I217_PROXY_CTRL_AUTO_DISABLE 0x0080 -#define I217_SxCTRL PHY_REG(BM_PORT_CTRL_PAGE, 28) -#define I217_SxCTRL_ENABLE_LPI_RESET 0x1000 -#define I217_CGFREG PHY_REG(772, 29) -#define I217_CGFREG_ENABLE_MTA_RESET 0x0002 -#define I217_MEMPWR PHY_REG(772, 26) -#define I217_MEMPWR_DISABLE_SMB_RELEASE 0x0010 - -/* Receive Address Initial CRC Calculation */ -#define E1000_PCH_RAICC(_n) (0x05F50 + ((_n) * 4)) - -/* Latency Tolerance Reporting */ -#define E1000_LTRV 0x000F8 -#define E1000_LTRV_SCALE_MAX 5 -#define E1000_LTRV_SCALE_FACTOR 5 -#define E1000_LTRV_REQ_SHIFT 15 -#define E1000_LTRV_NOSNOOP_SHIFT 16 -#define E1000_LTRV_SEND (1 << 30) - -/* Proprietary Latency Tolerance Reporting PCI Capability */ -#define E1000_PCI_LTR_CAP_LPT 0xA8 - -void e1000e_write_protect_nvm_ich8lan(struct e1000_hw *hw); -void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw, - bool state); -void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); -void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); -void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw); -void e1000_resume_workarounds_pchlan(struct e1000_hw *hw); -s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); -void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw); -s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable); -s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data); -s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data); -s32 e1000_set_eee_pchlan(struct e1000_hw *hw); -s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx); -#endif /* _E1000E_ICH8LAN_H_ */ diff --git a/addons/e1000e/src/4.4.180/mac.c b/addons/e1000e/src/4.4.180/mac.c deleted file mode 100644 index fe133f33..00000000 --- a/addons/e1000e/src/4.4.180/mac.c +++ /dev/null @@ -1,1805 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#include "e1000.h" - -/** - * e1000e_get_bus_info_pcie - Get PCIe bus information - * @hw: pointer to the HW structure - * - * Determines and stores the system bus information for a particular - * network interface. The following bus information is determined and stored: - * bus speed, bus width, type (PCIe), and PCIe function. - **/ -s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - struct e1000_bus_info *bus = &hw->bus; - struct e1000_adapter *adapter = hw->adapter; - u16 pcie_link_status, cap_offset; - - cap_offset = adapter->pdev->pcie_cap; - if (!cap_offset) { - bus->width = e1000_bus_width_unknown; - } else { - pci_read_config_word(adapter->pdev, - cap_offset + PCIE_LINK_STATUS, - &pcie_link_status); - bus->width = (enum e1000_bus_width)((pcie_link_status & - PCIE_LINK_WIDTH_MASK) >> - PCIE_LINK_WIDTH_SHIFT); - } - - mac->ops.set_lan_id(hw); - - return 0; -} - -/** - * e1000_set_lan_id_multi_port_pcie - Set LAN id for PCIe multiple port devices - * - * @hw: pointer to the HW structure - * - * Determines the LAN function id by reading memory-mapped registers - * and swaps the port value if requested. - **/ -void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - u32 reg; - - /* The status register reports the correct function number - * for the device regardless of function swap state. - */ - reg = er32(STATUS); - bus->func = (reg & E1000_STATUS_FUNC_MASK) >> E1000_STATUS_FUNC_SHIFT; -} - -/** - * e1000_set_lan_id_single_port - Set LAN id for a single port device - * @hw: pointer to the HW structure - * - * Sets the LAN function id to zero for a single port device. - **/ -void e1000_set_lan_id_single_port(struct e1000_hw *hw) -{ - struct e1000_bus_info *bus = &hw->bus; - - bus->func = 0; -} - -/** - * e1000_clear_vfta_generic - Clear VLAN filter table - * @hw: pointer to the HW structure - * - * Clears the register array which contains the VLAN filter table by - * setting all the values to 0. - **/ -void e1000_clear_vfta_generic(struct e1000_hw *hw) -{ - u32 offset; - - for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); - e1e_flush(); - } -} - -/** - * e1000_write_vfta_generic - Write value to VLAN filter table - * @hw: pointer to the HW structure - * @offset: register offset in VLAN filter table - * @value: register value written to VLAN filter table - * - * Writes value at the given offset in the register array which stores - * the VLAN filter table. - **/ -void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value) -{ - E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); - e1e_flush(); -} - -/** - * e1000e_init_rx_addrs - Initialize receive address's - * @hw: pointer to the HW structure - * @rar_count: receive address registers - * - * Setup the receive address registers by setting the base receive address - * register to the devices MAC address and clearing all the other receive - * address registers to 0. - **/ -void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count) -{ - u32 i; - u8 mac_addr[ETH_ALEN] = { 0 }; - - /* Setup the receive address */ - e_dbg("Programming MAC Address into RAR[0]\n"); - - hw->mac.ops.rar_set(hw, hw->mac.addr, 0); - - /* Zero out the other (rar_entry_count - 1) receive addresses */ - e_dbg("Clearing RAR[1-%u]\n", rar_count - 1); - for (i = 1; i < rar_count; i++) - hw->mac.ops.rar_set(hw, mac_addr, i); -} - -/** - * e1000_check_alt_mac_addr_generic - Check for alternate MAC addr - * @hw: pointer to the HW structure - * - * Checks the nvm for an alternate MAC address. An alternate MAC address - * can be setup by pre-boot software and must be treated like a permanent - * address and must override the actual permanent MAC address. If an - * alternate MAC address is found it is programmed into RAR0, replacing - * the permanent address that was installed into RAR0 by the Si on reset. - * This function will return SUCCESS unless it encounters an error while - * reading the EEPROM. - **/ -s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw) -{ - u32 i; - s32 ret_val; - u16 offset, nvm_alt_mac_addr_offset, nvm_data; - u8 alt_mac_addr[ETH_ALEN]; - - ret_val = e1000_read_nvm(hw, NVM_COMPAT, 1, &nvm_data); - if (ret_val) - return ret_val; - - /* not supported on 82573 */ - if (hw->mac.type == e1000_82573) - return 0; - - ret_val = e1000_read_nvm(hw, NVM_ALT_MAC_ADDR_PTR, 1, - &nvm_alt_mac_addr_offset); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - if ((nvm_alt_mac_addr_offset == 0xFFFF) || - (nvm_alt_mac_addr_offset == 0x0000)) - /* There is no Alternate MAC Address */ - return 0; - - if (hw->bus.func == E1000_FUNC_1) - nvm_alt_mac_addr_offset += E1000_ALT_MAC_ADDRESS_OFFSET_LAN1; - for (i = 0; i < ETH_ALEN; i += 2) { - offset = nvm_alt_mac_addr_offset + (i >> 1); - ret_val = e1000_read_nvm(hw, offset, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - alt_mac_addr[i] = (u8)(nvm_data & 0xFF); - alt_mac_addr[i + 1] = (u8)(nvm_data >> 8); - } - - /* if multicast bit is set, the alternate address will not be used */ - if (is_multicast_ether_addr(alt_mac_addr)) { - e_dbg("Ignoring Alternate Mac Address with MC bit set\n"); - return 0; - } - - /* We have a valid alternate MAC address, and we want to treat it the - * same as the normal permanent MAC address stored by the HW into the - * RAR. Do this by mapping this address into RAR0. - */ - hw->mac.ops.rar_set(hw, alt_mac_addr, 0); - - return 0; -} - -u32 e1000e_rar_get_count_generic(struct e1000_hw *hw) -{ - return hw->mac.rar_entry_count; -} - -/** - * e1000e_rar_set_generic - Set receive address register - * @hw: pointer to the HW structure - * @addr: pointer to the receive address - * @index: receive address array register - * - * Sets the receive address array register at index to the address passed - * in by addr. - **/ -int e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index) -{ - u32 rar_low, rar_high; - - /* HW expects these in little endian so we reverse the byte order - * from network order (big endian) to little endian - */ - rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) | - ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); - - rar_high = ((u32)addr[4] | ((u32)addr[5] << 8)); - - /* If MAC address zero, no need to set the AV bit */ - if (rar_low || rar_high) - rar_high |= E1000_RAH_AV; - - /* Some bridges will combine consecutive 32-bit writes into - * a single burst write, which will malfunction on some parts. - * The flushes avoid this. - */ - ew32(RAL(index), rar_low); - e1e_flush(); - ew32(RAH(index), rar_high); - e1e_flush(); - - return 0; -} - -/** - * e1000_hash_mc_addr - Generate a multicast hash value - * @hw: pointer to the HW structure - * @mc_addr: pointer to a multicast address - * - * Generates a multicast address hash value which is used to determine - * the multicast filter table array address and new table value. - **/ -static u32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) -{ - u32 hash_value, hash_mask; - u8 bit_shift = 0; - - /* Register count multiplied by bits per register */ - hash_mask = (hw->mac.mta_reg_count * 32) - 1; - - /* For a mc_filter_type of 0, bit_shift is the number of left-shifts - * where 0xFF would still fall within the hash mask. - */ - while (hash_mask >> bit_shift != 0xFF) - bit_shift++; - - /* The portion of the address that is used for the hash table - * is determined by the mc_filter_type setting. - * The algorithm is such that there is a total of 8 bits of shifting. - * The bit_shift for a mc_filter_type of 0 represents the number of - * left-shifts where the MSB of mc_addr[5] would still fall within - * the hash_mask. Case 0 does this exactly. Since there are a total - * of 8 bits of shifting, then mc_addr[4] will shift right the - * remaining number of bits. Thus 8 - bit_shift. The rest of the - * cases are a variation of this algorithm...essentially raising the - * number of bits to shift mc_addr[5] left, while still keeping the - * 8-bit shifting total. - * - * For example, given the following Destination MAC Address and an - * mta register count of 128 (thus a 4096-bit vector and 0xFFF mask), - * we can see that the bit_shift for case 0 is 4. These are the hash - * values resulting from each mc_filter_type... - * [0] [1] [2] [3] [4] [5] - * 01 AA 00 12 34 56 - * LSB MSB - * - * case 0: hash_value = ((0x34 >> 4) | (0x56 << 4)) & 0xFFF = 0x563 - * case 1: hash_value = ((0x34 >> 3) | (0x56 << 5)) & 0xFFF = 0xAC6 - * case 2: hash_value = ((0x34 >> 2) | (0x56 << 6)) & 0xFFF = 0x163 - * case 3: hash_value = ((0x34 >> 0) | (0x56 << 8)) & 0xFFF = 0x634 - */ - switch (hw->mac.mc_filter_type) { - default: - case 0: - break; - case 1: - bit_shift += 1; - break; - case 2: - bit_shift += 2; - break; - case 3: - bit_shift += 4; - break; - } - - hash_value = hash_mask & (((mc_addr[4] >> (8 - bit_shift)) | - (((u16)mc_addr[5]) << bit_shift))); - - return hash_value; -} - -/** - * e1000e_update_mc_addr_list_generic - Update Multicast addresses - * @hw: pointer to the HW structure - * @mc_addr_list: array of multicast addresses to program - * @mc_addr_count: number of multicast addresses to program - * - * Updates entire Multicast Table Array. - * The caller must have a packed mc_addr_list of multicast addresses. - **/ -void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count) -{ - u32 hash_value, hash_bit, hash_reg; - int i; - - /* clear mta_shadow */ - memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow)); - - /* update mta_shadow from mc_addr_list */ - for (i = 0; (u32)i < mc_addr_count; i++) { - hash_value = e1000_hash_mc_addr(hw, mc_addr_list); - - hash_reg = (hash_value >> 5) & (hw->mac.mta_reg_count - 1); - hash_bit = hash_value & 0x1F; - - hw->mac.mta_shadow[hash_reg] |= (1 << hash_bit); - mc_addr_list += (ETH_ALEN); - } - - /* replace the entire MTA table */ - for (i = hw->mac.mta_reg_count - 1; i >= 0; i--) - E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, hw->mac.mta_shadow[i]); - e1e_flush(); -} - -/** - * e1000e_clear_hw_cntrs_base - Clear base hardware counters - * @hw: pointer to the HW structure - * - * Clears the base hardware counters by reading the counter registers. - **/ -void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw) -{ - er32(CRCERRS); - er32(SYMERRS); - er32(MPC); - er32(SCC); - er32(ECOL); - er32(MCC); - er32(LATECOL); - er32(COLC); - er32(DC); - er32(SEC); - er32(RLEC); - er32(XONRXC); - er32(XONTXC); - er32(XOFFRXC); - er32(XOFFTXC); - er32(FCRUC); - er32(GPRC); - er32(BPRC); - er32(MPRC); - er32(GPTC); - er32(GORCL); - er32(GORCH); - er32(GOTCL); - er32(GOTCH); - er32(RNBC); - er32(RUC); - er32(RFC); - er32(ROC); - er32(RJC); - er32(TORL); - er32(TORH); - er32(TOTL); - er32(TOTH); - er32(TPR); - er32(TPT); - er32(MPTC); - er32(BPTC); -} - -/** - * e1000e_check_for_copper_link - Check for link (Copper) - * @hw: pointer to the HW structure - * - * Checks to see of the link status of the hardware has changed. If a - * change in link status has been detected, then we read the PHY registers - * to get the current speed/duplex if link exists. - * - * Returns a negative error code (-E1000_ERR_*) or 0 (link down) or 1 (link - * up). - **/ -s32 e1000e_check_for_copper_link(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - bool link; - - /* We only want to go out to the PHY registers to see if Auto-Neg - * has completed and/or if our link status has changed. The - * get_link_status flag is set upon receiving a Link Status - * Change or Rx Sequence Error interrupt. - */ - if (!mac->get_link_status) - return 1; - - /* First we want to see if the MII Status Register reports - * link. If so, then we want to get the current speed/duplex - * of the PHY. - */ - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (!link) - return 0; /* No link detected */ - - mac->get_link_status = false; - - /* Check if there was DownShift, must be checked - * immediately after link-up - */ - e1000e_check_downshift(hw); - - /* If we are forcing speed/duplex, then we simply return since - * we have already determined whether we have link or not. - */ - if (!mac->autoneg) - return 1; - - /* Auto-Neg is enabled. Auto Speed Detection takes care - * of MAC speed/duplex configuration. So we only need to - * configure Collision Distance in the MAC. - */ - mac->ops.config_collision_dist(hw); - - /* Configure Flow Control now that Auto-Neg has completed. - * First, we need to restore the desired flow control - * settings because we may have had to re-autoneg with a - * different link partner. - */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error configuring flow control\n"); - return ret_val; - } - - return 1; -} - -/** - * e1000e_check_for_fiber_link - Check for link (Fiber) - * @hw: pointer to the HW structure - * - * Checks for link up on the hardware. If link is not up and we have - * a signal, then we need to force link up. - **/ -s32 e1000e_check_for_fiber_link(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw; - u32 ctrl; - u32 status; - s32 ret_val; - - ctrl = er32(CTRL); - status = er32(STATUS); - rxcw = er32(RXCW); - - /* If we don't have link (auto-negotiation failed or link partner - * cannot auto-negotiate), the cable is plugged in (we have signal), - * and our link partner is not trying to auto-negotiate with us (we - * are receiving idles or data), we need to force link up. We also - * need to give auto-negotiation time to complete, in case the cable - * was just plugged in. The autoneg_failed flag does this. - */ - /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if ((ctrl & E1000_CTRL_SWDPIN1) && !(status & E1000_STATUS_LU) && - !(rxcw & E1000_RXCW_C)) { - if (!mac->autoneg_failed) { - mac->autoneg_failed = true; - return 0; - } - e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); - - /* Disable auto-negotiation in the TXCW register */ - ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = er32(CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - ew32(CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error configuring flow control\n"); - return ret_val; - } - } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* If we are forcing link and we are receiving /C/ ordered - * sets, re-enable auto-negotiation in the TXCW register - * and disable forced link in the Device Control register - * in an attempt to auto-negotiate with our link partner. - */ - e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); - ew32(TXCW, mac->txcw); - ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - - mac->serdes_has_link = true; - } - - return 0; -} - -/** - * e1000e_check_for_serdes_link - Check for link (Serdes) - * @hw: pointer to the HW structure - * - * Checks for link up on the hardware. If link is not up and we have - * a signal, then we need to force link up. - **/ -s32 e1000e_check_for_serdes_link(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 rxcw; - u32 ctrl; - u32 status; - s32 ret_val; - - ctrl = er32(CTRL); - status = er32(STATUS); - rxcw = er32(RXCW); - - /* If we don't have link (auto-negotiation failed or link partner - * cannot auto-negotiate), and our link partner is not trying to - * auto-negotiate with us (we are receiving idles or data), - * we need to force link up. We also need to give auto-negotiation - * time to complete. - */ - /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ - if (!(status & E1000_STATUS_LU) && !(rxcw & E1000_RXCW_C)) { - if (!mac->autoneg_failed) { - mac->autoneg_failed = true; - return 0; - } - e_dbg("NOT Rx'ing /C/, disable AutoNeg and force link.\n"); - - /* Disable auto-negotiation in the TXCW register */ - ew32(TXCW, (mac->txcw & ~E1000_TXCW_ANE)); - - /* Force link-up and also force full-duplex. */ - ctrl = er32(CTRL); - ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); - ew32(CTRL, ctrl); - - /* Configure Flow Control after forcing link up. */ - ret_val = e1000e_config_fc_after_link_up(hw); - if (ret_val) { - e_dbg("Error configuring flow control\n"); - return ret_val; - } - } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { - /* If we are forcing link and we are receiving /C/ ordered - * sets, re-enable auto-negotiation in the TXCW register - * and disable forced link in the Device Control register - * in an attempt to auto-negotiate with our link partner. - */ - e_dbg("Rx'ing /C/, enable AutoNeg and stop forcing link.\n"); - ew32(TXCW, mac->txcw); - ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); - - mac->serdes_has_link = true; - } else if (!(E1000_TXCW_ANE & er32(TXCW))) { - /* If we force link for non-auto-negotiation switch, check - * link status based on MAC synchronization for internal - * serdes media type. - */ - /* SYNCH bit and IV bit are sticky. */ - usleep_range(10, 20); - rxcw = er32(RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - mac->serdes_has_link = true; - e_dbg("SERDES: Link up - forced.\n"); - } - } else { - mac->serdes_has_link = false; - e_dbg("SERDES: Link down - force failed.\n"); - } - } - - if (E1000_TXCW_ANE & er32(TXCW)) { - status = er32(STATUS); - if (status & E1000_STATUS_LU) { - /* SYNCH bit and IV bit are sticky, so reread rxcw. */ - usleep_range(10, 20); - rxcw = er32(RXCW); - if (rxcw & E1000_RXCW_SYNCH) { - if (!(rxcw & E1000_RXCW_IV)) { - mac->serdes_has_link = true; - e_dbg("SERDES: Link up - autoneg completed successfully.\n"); - } else { - mac->serdes_has_link = false; - e_dbg("SERDES: Link down - invalid codewords detected in autoneg.\n"); - } - } else { - mac->serdes_has_link = false; - e_dbg("SERDES: Link down - no sync.\n"); - } - } else { - mac->serdes_has_link = false; - e_dbg("SERDES: Link down - autoneg failed\n"); - } - } - - return 0; -} - -/** - * e1000_set_default_fc_generic - Set flow control default values - * @hw: pointer to the HW structure - * - * Read the EEPROM for the default values for flow control and store the - * values. - **/ -static s32 e1000_set_default_fc_generic(struct e1000_hw *hw) -{ - s32 ret_val; - u16 nvm_data; - - /* Read and store word 0x0F of the EEPROM. This word contains bits - * that determine the hardware's default PAUSE (flow control) mode, - * a bit that determines whether the HW defaults to enabling or - * disabling auto-negotiation, and the direction of the - * SW defined pins. If there is no SW over-ride of the flow - * control setting, then the variable hw->fc will - * be initialized based on a value in the EEPROM. - */ - ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &nvm_data); - - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - if (!(nvm_data & NVM_WORD0F_PAUSE_MASK)) - hw->fc.requested_mode = e1000_fc_none; - else if ((nvm_data & NVM_WORD0F_PAUSE_MASK) == NVM_WORD0F_ASM_DIR) - hw->fc.requested_mode = e1000_fc_tx_pause; - else - hw->fc.requested_mode = e1000_fc_full; - - return 0; -} - -/** - * e1000e_setup_link_generic - Setup flow control and link settings - * @hw: pointer to the HW structure - * - * Determines which flow control settings to use, then configures flow - * control. Calls the appropriate media-specific link configuration - * function. Assuming the adapter has a valid link partner, a valid link - * should be established. Assumes the hardware has previously been reset - * and the transmitter and receiver are not enabled. - **/ -s32 e1000e_setup_link_generic(struct e1000_hw *hw) -{ - s32 ret_val; - - /* In the case of the phy reset being blocked, we already have a link. - * We do not need to set it up again. - */ - if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) - return 0; - - /* If requested flow control is set to default, set flow control - * based on the EEPROM flow control settings. - */ - if (hw->fc.requested_mode == e1000_fc_default) { - ret_val = e1000_set_default_fc_generic(hw); - if (ret_val) - return ret_val; - } - - /* Save off the requested flow control mode for use later. Depending - * on the link partner's capabilities, we may or may not use this mode. - */ - hw->fc.current_mode = hw->fc.requested_mode; - - e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc.current_mode); - - /* Call the necessary media_type subroutine to configure the link. */ - ret_val = hw->mac.ops.setup_physical_interface(hw); - if (ret_val) - return ret_val; - - /* Initialize the flow control address, type, and PAUSE timer - * registers to their default values. This is done even if flow - * control is disabled, because it does not hurt anything to - * initialize these registers. - */ - e_dbg("Initializing the Flow Control address, type and timer regs\n"); - ew32(FCT, FLOW_CONTROL_TYPE); - ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH); - ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW); - - ew32(FCTTV, hw->fc.pause_time); - - return e1000e_set_fc_watermarks(hw); -} - -/** - * e1000_commit_fc_settings_generic - Configure flow control - * @hw: pointer to the HW structure - * - * Write the flow control settings to the Transmit Config Word Register (TXCW) - * base on the flow control settings in e1000_mac_info. - **/ -static s32 e1000_commit_fc_settings_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 txcw; - - /* Check for a software override of the flow control settings, and - * setup the device accordingly. If auto-negotiation is enabled, then - * software will have to set the "PAUSE" bits to the correct value in - * the Transmit Config Word Register (TXCW) and re-start auto- - * negotiation. However, if auto-negotiation is disabled, then - * software will have to manually configure the two flow control enable - * bits in the CTRL register. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames, - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames but we - * do not support receiving pause frames). - * 3: Both Rx and Tx flow control (symmetric) are enabled. - */ - switch (hw->fc.current_mode) { - case e1000_fc_none: - /* Flow control completely disabled by a software over-ride. */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); - break; - case e1000_fc_rx_pause: - /* Rx Flow control is enabled and Tx Flow control is disabled - * by a software over-ride. Since there really isn't a way to - * advertise that we are capable of Rx Pause ONLY, we will - * advertise that we support both symmetric and asymmetric Rx - * PAUSE. Later, we will disable the adapter's ability to send - * PAUSE frames. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - case e1000_fc_tx_pause: - /* Tx Flow control is enabled, and Rx Flow control is disabled, - * by a software over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); - break; - case e1000_fc_full: - /* Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - } - - ew32(TXCW, txcw); - mac->txcw = txcw; - - return 0; -} - -/** - * e1000_poll_fiber_serdes_link_generic - Poll for link up - * @hw: pointer to the HW structure - * - * Polls for link up by reading the status register, if link fails to come - * up with auto-negotiation, then the link is forced if a signal is detected. - **/ -static s32 e1000_poll_fiber_serdes_link_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 i, status; - s32 ret_val; - - /* If we have a signal (the cable is plugged in, or assumed true for - * serdes media) then poll for a "Link-Up" indication in the Device - * Status Register. Time-out if a link isn't seen in 500 milliseconds - * seconds (Auto-negotiation should complete in less than 500 - * milliseconds even if the other end is doing it in SW). - */ - for (i = 0; i < FIBER_LINK_UP_LIMIT; i++) { - usleep_range(10000, 20000); - status = er32(STATUS); - if (status & E1000_STATUS_LU) - break; - } - if (i == FIBER_LINK_UP_LIMIT) { - e_dbg("Never got a valid link from auto-neg!!!\n"); - mac->autoneg_failed = true; - /* AutoNeg failed to achieve a link, so we'll call - * mac->check_for_link. This routine will force the - * link up if we detect a signal. This will allow us to - * communicate with non-autonegotiating link partners. - */ - ret_val = mac->ops.check_for_link(hw); - if (ret_val) { - e_dbg("Error while checking for link\n"); - return ret_val; - } - mac->autoneg_failed = false; - } else { - mac->autoneg_failed = false; - e_dbg("Valid Link Found\n"); - } - - return 0; -} - -/** - * e1000e_setup_fiber_serdes_link - Setup link for fiber/serdes - * @hw: pointer to the HW structure - * - * Configures collision distance and flow control for fiber and serdes - * links. Upon successful setup, poll for link. - **/ -s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw) -{ - u32 ctrl; - s32 ret_val; - - ctrl = er32(CTRL); - - /* Take the link out of reset */ - ctrl &= ~E1000_CTRL_LRST; - - hw->mac.ops.config_collision_dist(hw); - - ret_val = e1000_commit_fc_settings_generic(hw); - if (ret_val) - return ret_val; - - /* Since auto-negotiation is enabled, take the link out of reset (the - * link will be in reset, because we previously reset the chip). This - * will restart auto-negotiation. If auto-negotiation is successful - * then the link-up status bit will be set and the flow control enable - * bits (RFCE and TFCE) will be set according to their negotiated value. - */ - e_dbg("Auto-negotiation enabled\n"); - - ew32(CTRL, ctrl); - e1e_flush(); - usleep_range(1000, 2000); - - /* For these adapters, the SW definable pin 1 is set when the optics - * detect a signal. If we have a signal, then poll for a "Link-Up" - * indication. - */ - if (hw->phy.media_type == e1000_media_type_internal_serdes || - (er32(CTRL) & E1000_CTRL_SWDPIN1)) { - ret_val = e1000_poll_fiber_serdes_link_generic(hw); - } else { - e_dbg("No signal detected\n"); - } - - return ret_val; -} - -/** - * e1000e_config_collision_dist_generic - Configure collision distance - * @hw: pointer to the HW structure - * - * Configures the collision distance to the default value and is used - * during link setup. - **/ -void e1000e_config_collision_dist_generic(struct e1000_hw *hw) -{ - u32 tctl; - - tctl = er32(TCTL); - - tctl &= ~E1000_TCTL_COLD; - tctl |= E1000_COLLISION_DISTANCE << E1000_COLD_SHIFT; - - ew32(TCTL, tctl); - e1e_flush(); -} - -/** - * e1000e_set_fc_watermarks - Set flow control high/low watermarks - * @hw: pointer to the HW structure - * - * Sets the flow control high/low threshold (watermark) registers. If - * flow control XON frame transmission is enabled, then set XON frame - * transmission as well. - **/ -s32 e1000e_set_fc_watermarks(struct e1000_hw *hw) -{ - u32 fcrtl = 0, fcrth = 0; - - /* Set the flow control receive threshold registers. Normally, - * these registers will be set to a default threshold that may be - * adjusted later by the driver's runtime code. However, if the - * ability to transmit pause frames is not enabled, then these - * registers will be set to 0. - */ - if (hw->fc.current_mode & e1000_fc_tx_pause) { - /* We need to set up the Receive Threshold high and low water - * marks as well as (optionally) enabling the transmission of - * XON frames. - */ - fcrtl = hw->fc.low_water; - if (hw->fc.send_xon) - fcrtl |= E1000_FCRTL_XONE; - - fcrth = hw->fc.high_water; - } - ew32(FCRTL, fcrtl); - ew32(FCRTH, fcrth); - - return 0; -} - -/** - * e1000e_force_mac_fc - Force the MAC's flow control settings - * @hw: pointer to the HW structure - * - * Force the MAC's flow control settings. Sets the TFCE and RFCE bits in the - * device control register to reflect the adapter settings. TFCE and RFCE - * need to be explicitly set by software when a copper PHY is used because - * autonegotiation is managed by the PHY rather than the MAC. Software must - * also configure these bits when link is forced on a fiber connection. - **/ -s32 e1000e_force_mac_fc(struct e1000_hw *hw) -{ - u32 ctrl; - - ctrl = er32(CTRL); - - /* Because we didn't get link via the internal auto-negotiation - * mechanism (we either forced link or we got link via PHY - * auto-neg), we have to manually enable/disable transmit an - * receive flow control. - * - * The "Case" statement below enables/disable flow control - * according to the "hw->fc.current_mode" parameter. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause - * frames but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * frames but we do not receive pause frames). - * 3: Both Rx and Tx flow control (symmetric) is enabled. - * other: No other values should be possible at this point. - */ - e_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode); - - switch (hw->fc.current_mode) { - case e1000_fc_none: - ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); - break; - case e1000_fc_rx_pause: - ctrl &= (~E1000_CTRL_TFCE); - ctrl |= E1000_CTRL_RFCE; - break; - case e1000_fc_tx_pause: - ctrl &= (~E1000_CTRL_RFCE); - ctrl |= E1000_CTRL_TFCE; - break; - case e1000_fc_full: - ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - } - - ew32(CTRL, ctrl); - - return 0; -} - -/** - * e1000e_config_fc_after_link_up - Configures flow control after link - * @hw: pointer to the HW structure - * - * Checks the status of auto-negotiation after link up to ensure that the - * speed and duplex were not forced. If the link needed to be forced, then - * flow control needs to be forced also. If auto-negotiation is enabled - * and did not fail, then we configure flow control based on our link - * partner. - **/ -s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val = 0; - u32 pcs_status_reg, pcs_adv_reg, pcs_lp_ability_reg, pcs_ctrl_reg; - u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg; - u16 speed, duplex; - - /* Check for the case where we have fiber media and auto-neg failed - * so we had to force link. In this case, we need to force the - * configuration of the MAC to match the "fc" parameter. - */ - if (mac->autoneg_failed) { - if (hw->phy.media_type == e1000_media_type_fiber || - hw->phy.media_type == e1000_media_type_internal_serdes) - ret_val = e1000e_force_mac_fc(hw); - } else { - if (hw->phy.media_type == e1000_media_type_copper) - ret_val = e1000e_force_mac_fc(hw); - } - - if (ret_val) { - e_dbg("Error forcing flow control settings\n"); - return ret_val; - } - - /* Check for the case where we have copper media and auto-neg is - * enabled. In this case, we need to check and see if Auto-Neg - * has completed, and if so, how the PHY and link partner has - * flow control configured. - */ - if ((hw->phy.media_type == e1000_media_type_copper) && mac->autoneg) { - /* Read the MII Status Register and check to see if AutoNeg - * has completed. We read this twice because this reg has - * some "sticky" (latched) bits. - */ - ret_val = e1e_rphy(hw, MII_BMSR, &mii_status_reg); - if (ret_val) - return ret_val; - ret_val = e1e_rphy(hw, MII_BMSR, &mii_status_reg); - if (ret_val) - return ret_val; - - if (!(mii_status_reg & BMSR_ANEGCOMPLETE)) { - e_dbg("Copper PHY and Auto Neg has not completed.\n"); - return ret_val; - } - - /* The AutoNeg process has completed, so we now need to - * read both the Auto Negotiation Advertisement - * Register (Address 4) and the Auto_Negotiation Base - * Page Ability Register (Address 5) to determine how - * flow control was negotiated. - */ - ret_val = e1e_rphy(hw, MII_ADVERTISE, &mii_nway_adv_reg); - if (ret_val) - return ret_val; - ret_val = e1e_rphy(hw, MII_LPA, &mii_nway_lp_ability_reg); - if (ret_val) - return ret_val; - - /* Two bits in the Auto Negotiation Advertisement Register - * (Address 4) and two bits in the Auto Negotiation Base - * Page Ability Register (Address 5) determine flow control - * for both the PHY and the link partner. The following - * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, - * 1999, describes these PAUSE resolution bits and how flow - * control is determined based upon these settings. - * NOTE: DC = Don't Care - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution - *-------|---------|-------|---------|-------------------- - * 0 | 0 | DC | DC | e1000_fc_none - * 0 | 1 | 0 | DC | e1000_fc_none - * 0 | 1 | 1 | 0 | e1000_fc_none - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - * 1 | 0 | 0 | DC | e1000_fc_none - * 1 | DC | 1 | DC | e1000_fc_full - * 1 | 1 | 0 | 0 | e1000_fc_none - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - * - * Are both PAUSE bits set to 1? If so, this implies - * Symmetric Flow Control is enabled at both ends. The - * ASM_DIR bits are irrelevant per the spec. - * - * For Symmetric Flow Control: - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | DC | 1 | DC | E1000_fc_full - * - */ - if ((mii_nway_adv_reg & ADVERTISE_PAUSE_CAP) && - (mii_nway_lp_ability_reg & LPA_PAUSE_CAP)) { - /* Now we need to check if the user selected Rx ONLY - * of pause frames. In this case, we had to advertise - * FULL flow control because we could not advertise Rx - * ONLY. Hence, we must now check to see if we need to - * turn OFF the TRANSMISSION of PAUSE frames. - */ - if (hw->fc.requested_mode == e1000_fc_full) { - hw->fc.current_mode = e1000_fc_full; - e_dbg("Flow Control = FULL.\n"); - } else { - hw->fc.current_mode = e1000_fc_rx_pause; - e_dbg("Flow Control = Rx PAUSE frames only.\n"); - } - } - /* For receiving PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - */ - else if (!(mii_nway_adv_reg & ADVERTISE_PAUSE_CAP) && - (mii_nway_adv_reg & ADVERTISE_PAUSE_ASYM) && - (mii_nway_lp_ability_reg & LPA_PAUSE_CAP) && - (mii_nway_lp_ability_reg & LPA_PAUSE_ASYM)) { - hw->fc.current_mode = e1000_fc_tx_pause; - e_dbg("Flow Control = Tx PAUSE frames only.\n"); - } - /* For transmitting PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - */ - else if ((mii_nway_adv_reg & ADVERTISE_PAUSE_CAP) && - (mii_nway_adv_reg & ADVERTISE_PAUSE_ASYM) && - !(mii_nway_lp_ability_reg & LPA_PAUSE_CAP) && - (mii_nway_lp_ability_reg & LPA_PAUSE_ASYM)) { - hw->fc.current_mode = e1000_fc_rx_pause; - e_dbg("Flow Control = Rx PAUSE frames only.\n"); - } else { - /* Per the IEEE spec, at this point flow control - * should be disabled. - */ - hw->fc.current_mode = e1000_fc_none; - e_dbg("Flow Control = NONE.\n"); - } - - /* Now we need to do one last check... If we auto- - * negotiated to HALF DUPLEX, flow control should not be - * enabled per IEEE 802.3 spec. - */ - ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); - if (ret_val) { - e_dbg("Error getting link speed and duplex\n"); - return ret_val; - } - - if (duplex == HALF_DUPLEX) - hw->fc.current_mode = e1000_fc_none; - - /* Now we call a subroutine to actually force the MAC - * controller to use the correct flow control settings. - */ - ret_val = e1000e_force_mac_fc(hw); - if (ret_val) { - e_dbg("Error forcing flow control settings\n"); - return ret_val; - } - } - - /* Check for the case where we have SerDes media and auto-neg is - * enabled. In this case, we need to check and see if Auto-Neg - * has completed, and if so, how the PHY and link partner has - * flow control configured. - */ - if ((hw->phy.media_type == e1000_media_type_internal_serdes) && - mac->autoneg) { - /* Read the PCS_LSTS and check to see if AutoNeg - * has completed. - */ - pcs_status_reg = er32(PCS_LSTAT); - - if (!(pcs_status_reg & E1000_PCS_LSTS_AN_COMPLETE)) { - e_dbg("PCS Auto Neg has not completed.\n"); - return ret_val; - } - - /* The AutoNeg process has completed, so we now need to - * read both the Auto Negotiation Advertisement - * Register (PCS_ANADV) and the Auto_Negotiation Base - * Page Ability Register (PCS_LPAB) to determine how - * flow control was negotiated. - */ - pcs_adv_reg = er32(PCS_ANADV); - pcs_lp_ability_reg = er32(PCS_LPAB); - - /* Two bits in the Auto Negotiation Advertisement Register - * (PCS_ANADV) and two bits in the Auto Negotiation Base - * Page Ability Register (PCS_LPAB) determine flow control - * for both the PHY and the link partner. The following - * table, taken out of the IEEE 802.3ab/D6.0 dated March 25, - * 1999, describes these PAUSE resolution bits and how flow - * control is determined based upon these settings. - * NOTE: DC = Don't Care - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution - *-------|---------|-------|---------|-------------------- - * 0 | 0 | DC | DC | e1000_fc_none - * 0 | 1 | 0 | DC | e1000_fc_none - * 0 | 1 | 1 | 0 | e1000_fc_none - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - * 1 | 0 | 0 | DC | e1000_fc_none - * 1 | DC | 1 | DC | e1000_fc_full - * 1 | 1 | 0 | 0 | e1000_fc_none - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - * - * Are both PAUSE bits set to 1? If so, this implies - * Symmetric Flow Control is enabled at both ends. The - * ASM_DIR bits are irrelevant per the spec. - * - * For Symmetric Flow Control: - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | DC | 1 | DC | e1000_fc_full - * - */ - if ((pcs_adv_reg & E1000_TXCW_PAUSE) && - (pcs_lp_ability_reg & E1000_TXCW_PAUSE)) { - /* Now we need to check if the user selected Rx ONLY - * of pause frames. In this case, we had to advertise - * FULL flow control because we could not advertise Rx - * ONLY. Hence, we must now check to see if we need to - * turn OFF the TRANSMISSION of PAUSE frames. - */ - if (hw->fc.requested_mode == e1000_fc_full) { - hw->fc.current_mode = e1000_fc_full; - e_dbg("Flow Control = FULL.\n"); - } else { - hw->fc.current_mode = e1000_fc_rx_pause; - e_dbg("Flow Control = Rx PAUSE frames only.\n"); - } - } - /* For receiving PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 0 | 1 | 1 | 1 | e1000_fc_tx_pause - */ - else if (!(pcs_adv_reg & E1000_TXCW_PAUSE) && - (pcs_adv_reg & E1000_TXCW_ASM_DIR) && - (pcs_lp_ability_reg & E1000_TXCW_PAUSE) && - (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { - hw->fc.current_mode = e1000_fc_tx_pause; - e_dbg("Flow Control = Tx PAUSE frames only.\n"); - } - /* For transmitting PAUSE frames ONLY. - * - * LOCAL DEVICE | LINK PARTNER - * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result - *-------|---------|-------|---------|-------------------- - * 1 | 1 | 0 | 1 | e1000_fc_rx_pause - */ - else if ((pcs_adv_reg & E1000_TXCW_PAUSE) && - (pcs_adv_reg & E1000_TXCW_ASM_DIR) && - !(pcs_lp_ability_reg & E1000_TXCW_PAUSE) && - (pcs_lp_ability_reg & E1000_TXCW_ASM_DIR)) { - hw->fc.current_mode = e1000_fc_rx_pause; - e_dbg("Flow Control = Rx PAUSE frames only.\n"); - } else { - /* Per the IEEE spec, at this point flow control - * should be disabled. - */ - hw->fc.current_mode = e1000_fc_none; - e_dbg("Flow Control = NONE.\n"); - } - - /* Now we call a subroutine to actually force the MAC - * controller to use the correct flow control settings. - */ - pcs_ctrl_reg = er32(PCS_LCTL); - pcs_ctrl_reg |= E1000_PCS_LCTL_FORCE_FCTRL; - ew32(PCS_LCTL, pcs_ctrl_reg); - - ret_val = e1000e_force_mac_fc(hw); - if (ret_val) { - e_dbg("Error forcing flow control settings\n"); - return ret_val; - } - } - - return 0; -} - -/** - * e1000e_get_speed_and_duplex_copper - Retrieve current speed/duplex - * @hw: pointer to the HW structure - * @speed: stores the current speed - * @duplex: stores the current duplex - * - * Read the status register for the current speed/duplex and store the current - * speed and duplex for copper connections. - **/ -s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, - u16 *duplex) -{ - u32 status; - - status = er32(STATUS); - if (status & E1000_STATUS_SPEED_1000) - *speed = SPEED_1000; - else if (status & E1000_STATUS_SPEED_100) - *speed = SPEED_100; - else - *speed = SPEED_10; - - if (status & E1000_STATUS_FD) - *duplex = FULL_DUPLEX; - else - *duplex = HALF_DUPLEX; - - e_dbg("%u Mbps, %s Duplex\n", - *speed == SPEED_1000 ? 1000 : *speed == SPEED_100 ? 100 : 10, - *duplex == FULL_DUPLEX ? "Full" : "Half"); - - return 0; -} - -/** - * e1000e_get_speed_and_duplex_fiber_serdes - Retrieve current speed/duplex - * @hw: pointer to the HW structure - * @speed: stores the current speed - * @duplex: stores the current duplex - * - * Sets the speed and duplex to gigabit full duplex (the only possible option) - * for fiber/serdes links. - **/ -s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw __always_unused - *hw, u16 *speed, u16 *duplex) -{ - *speed = SPEED_1000; - *duplex = FULL_DUPLEX; - - return 0; -} - -/** - * e1000e_get_hw_semaphore - Acquire hardware semaphore - * @hw: pointer to the HW structure - * - * Acquire the HW semaphore to access the PHY or NVM - **/ -s32 e1000e_get_hw_semaphore(struct e1000_hw *hw) -{ - u32 swsm; - s32 timeout = hw->nvm.word_size + 1; - s32 i = 0; - - /* Get the SW semaphore */ - while (i < timeout) { - swsm = er32(SWSM); - if (!(swsm & E1000_SWSM_SMBI)) - break; - - usleep_range(50, 100); - i++; - } - - if (i == timeout) { - e_dbg("Driver can't access device - SMBI bit is set.\n"); - return -E1000_ERR_NVM; - } - - /* Get the FW semaphore. */ - for (i = 0; i < timeout; i++) { - swsm = er32(SWSM); - ew32(SWSM, swsm | E1000_SWSM_SWESMBI); - - /* Semaphore acquired if bit latched */ - if (er32(SWSM) & E1000_SWSM_SWESMBI) - break; - - usleep_range(50, 100); - } - - if (i == timeout) { - /* Release semaphores */ - e1000e_put_hw_semaphore(hw); - e_dbg("Driver can't access the NVM\n"); - return -E1000_ERR_NVM; - } - - return 0; -} - -/** - * e1000e_put_hw_semaphore - Release hardware semaphore - * @hw: pointer to the HW structure - * - * Release hardware semaphore used to access the PHY or NVM - **/ -void e1000e_put_hw_semaphore(struct e1000_hw *hw) -{ - u32 swsm; - - swsm = er32(SWSM); - swsm &= ~(E1000_SWSM_SMBI | E1000_SWSM_SWESMBI); - ew32(SWSM, swsm); -} - -/** - * e1000e_get_auto_rd_done - Check for auto read completion - * @hw: pointer to the HW structure - * - * Check EEPROM for Auto Read done bit. - **/ -s32 e1000e_get_auto_rd_done(struct e1000_hw *hw) -{ - s32 i = 0; - - while (i < AUTO_READ_DONE_TIMEOUT) { - if (er32(EECD) & E1000_EECD_AUTO_RD) - break; - usleep_range(1000, 2000); - i++; - } - - if (i == AUTO_READ_DONE_TIMEOUT) { - e_dbg("Auto read by HW from NVM has not completed.\n"); - return -E1000_ERR_RESET; - } - - return 0; -} - -/** - * e1000e_valid_led_default - Verify a valid default LED config - * @hw: pointer to the HW structure - * @data: pointer to the NVM (EEPROM) - * - * Read the EEPROM for the current default LED configuration. If the - * LED configuration is not valid, set to a valid LED configuration. - **/ -s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data) -{ - s32 ret_val; - - ret_val = e1000_read_nvm(hw, NVM_ID_LED_SETTINGS, 1, data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) - *data = ID_LED_DEFAULT; - - return 0; -} - -/** - * e1000e_id_led_init_generic - - * @hw: pointer to the HW structure - * - **/ -s32 e1000e_id_led_init_generic(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - s32 ret_val; - const u32 ledctl_mask = 0x000000FF; - const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; - const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; - u16 data, i, temp; - const u16 led_mask = 0x0F; - - ret_val = hw->nvm.ops.valid_led_default(hw, &data); - if (ret_val) - return ret_val; - - mac->ledctl_default = er32(LEDCTL); - mac->ledctl_mode1 = mac->ledctl_default; - mac->ledctl_mode2 = mac->ledctl_default; - - for (i = 0; i < 4; i++) { - temp = (data >> (i << 2)) & led_mask; - switch (temp) { - case ID_LED_ON1_DEF2: - case ID_LED_ON1_ON2: - case ID_LED_ON1_OFF2: - mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode1 |= ledctl_on << (i << 3); - break; - case ID_LED_OFF1_DEF2: - case ID_LED_OFF1_ON2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode1 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - switch (temp) { - case ID_LED_DEF1_ON2: - case ID_LED_ON1_ON2: - case ID_LED_OFF1_ON2: - mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode2 |= ledctl_on << (i << 3); - break; - case ID_LED_DEF1_OFF2: - case ID_LED_ON1_OFF2: - case ID_LED_OFF1_OFF2: - mac->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); - mac->ledctl_mode2 |= ledctl_off << (i << 3); - break; - default: - /* Do nothing */ - break; - } - } - - return 0; -} - -/** - * e1000e_setup_led_generic - Configures SW controllable LED - * @hw: pointer to the HW structure - * - * This prepares the SW controllable LED for use and saves the current state - * of the LED so it can be later restored. - **/ -s32 e1000e_setup_led_generic(struct e1000_hw *hw) -{ - u32 ledctl; - - if (hw->mac.ops.setup_led != e1000e_setup_led_generic) - return -E1000_ERR_CONFIG; - - if (hw->phy.media_type == e1000_media_type_fiber) { - ledctl = er32(LEDCTL); - hw->mac.ledctl_default = ledctl; - /* Turn off LED0 */ - ledctl &= ~(E1000_LEDCTL_LED0_IVRT | E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_LED0_MODE_MASK); - ledctl |= (E1000_LEDCTL_MODE_LED_OFF << - E1000_LEDCTL_LED0_MODE_SHIFT); - ew32(LEDCTL, ledctl); - } else if (hw->phy.media_type == e1000_media_type_copper) { - ew32(LEDCTL, hw->mac.ledctl_mode1); - } - - return 0; -} - -/** - * e1000e_cleanup_led_generic - Set LED config to default operation - * @hw: pointer to the HW structure - * - * Remove the current LED configuration and set the LED configuration - * to the default value, saved from the EEPROM. - **/ -s32 e1000e_cleanup_led_generic(struct e1000_hw *hw) -{ - ew32(LEDCTL, hw->mac.ledctl_default); - return 0; -} - -/** - * e1000e_blink_led_generic - Blink LED - * @hw: pointer to the HW structure - * - * Blink the LEDs which are set to be on. - **/ -s32 e1000e_blink_led_generic(struct e1000_hw *hw) -{ - u32 ledctl_blink = 0; - u32 i; - - if (hw->phy.media_type == e1000_media_type_fiber) { - /* always blink LED0 for PCI-E fiber */ - ledctl_blink = E1000_LEDCTL_LED0_BLINK | - (E1000_LEDCTL_MODE_LED_ON << E1000_LEDCTL_LED0_MODE_SHIFT); - } else { - /* Set the blink bit for each LED that's "on" (0x0E) - * (or "off" if inverted) in ledctl_mode2. The blink - * logic in hardware only works when mode is set to "on" - * so it must be changed accordingly when the mode is - * "off" and inverted. - */ - ledctl_blink = hw->mac.ledctl_mode2; - for (i = 0; i < 32; i += 8) { - u32 mode = (hw->mac.ledctl_mode2 >> i) & - E1000_LEDCTL_LED0_MODE_MASK; - u32 led_default = hw->mac.ledctl_default >> i; - - if ((!(led_default & E1000_LEDCTL_LED0_IVRT) && - (mode == E1000_LEDCTL_MODE_LED_ON)) || - ((led_default & E1000_LEDCTL_LED0_IVRT) && - (mode == E1000_LEDCTL_MODE_LED_OFF))) { - ledctl_blink &= - ~(E1000_LEDCTL_LED0_MODE_MASK << i); - ledctl_blink |= (E1000_LEDCTL_LED0_BLINK | - E1000_LEDCTL_MODE_LED_ON) << i; - } - } - } - - ew32(LEDCTL, ledctl_blink); - - return 0; -} - -/** - * e1000e_led_on_generic - Turn LED on - * @hw: pointer to the HW structure - * - * Turn LED on. - **/ -s32 e1000e_led_on_generic(struct e1000_hw *hw) -{ - u32 ctrl; - - switch (hw->phy.media_type) { - case e1000_media_type_fiber: - ctrl = er32(CTRL); - ctrl &= ~E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - ew32(CTRL, ctrl); - break; - case e1000_media_type_copper: - ew32(LEDCTL, hw->mac.ledctl_mode2); - break; - default: - break; - } - - return 0; -} - -/** - * e1000e_led_off_generic - Turn LED off - * @hw: pointer to the HW structure - * - * Turn LED off. - **/ -s32 e1000e_led_off_generic(struct e1000_hw *hw) -{ - u32 ctrl; - - switch (hw->phy.media_type) { - case e1000_media_type_fiber: - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_SWDPIN0; - ctrl |= E1000_CTRL_SWDPIO0; - ew32(CTRL, ctrl); - break; - case e1000_media_type_copper: - ew32(LEDCTL, hw->mac.ledctl_mode1); - break; - default: - break; - } - - return 0; -} - -/** - * e1000e_set_pcie_no_snoop - Set PCI-express capabilities - * @hw: pointer to the HW structure - * @no_snoop: bitmap of snoop events - * - * Set the PCI-express register to snoop for events enabled in 'no_snoop'. - **/ -void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop) -{ - u32 gcr; - - if (no_snoop) { - gcr = er32(GCR); - gcr &= ~(PCIE_NO_SNOOP_ALL); - gcr |= no_snoop; - ew32(GCR, gcr); - } -} - -/** - * e1000e_disable_pcie_master - Disables PCI-express master access - * @hw: pointer to the HW structure - * - * Returns 0 if successful, else returns -10 - * (-E1000_ERR_MASTER_REQUESTS_PENDING) if master disable bit has not caused - * the master requests to be disabled. - * - * Disables PCI-Express master access and verifies there are no pending - * requests. - **/ -s32 e1000e_disable_pcie_master(struct e1000_hw *hw) -{ - u32 ctrl; - s32 timeout = MASTER_DISABLE_TIMEOUT; - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_GIO_MASTER_DISABLE; - ew32(CTRL, ctrl); - - while (timeout) { - if (!(er32(STATUS) & E1000_STATUS_GIO_MASTER_ENABLE)) - break; - usleep_range(100, 200); - timeout--; - } - - if (!timeout) { - e_dbg("Master requests are pending.\n"); - return -E1000_ERR_MASTER_REQUESTS_PENDING; - } - - return 0; -} - -/** - * e1000e_reset_adaptive - Reset Adaptive Interframe Spacing - * @hw: pointer to the HW structure - * - * Reset the Adaptive Interframe Spacing throttle to default values. - **/ -void e1000e_reset_adaptive(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - if (!mac->adaptive_ifs) { - e_dbg("Not in Adaptive IFS mode!\n"); - return; - } - - mac->current_ifs_val = 0; - mac->ifs_min_val = IFS_MIN; - mac->ifs_max_val = IFS_MAX; - mac->ifs_step_size = IFS_STEP; - mac->ifs_ratio = IFS_RATIO; - - mac->in_ifs_mode = false; - ew32(AIT, 0); -} - -/** - * e1000e_update_adaptive - Update Adaptive Interframe Spacing - * @hw: pointer to the HW structure - * - * Update the Adaptive Interframe Spacing Throttle value based on the - * time between transmitted packets and time between collisions. - **/ -void e1000e_update_adaptive(struct e1000_hw *hw) -{ - struct e1000_mac_info *mac = &hw->mac; - - if (!mac->adaptive_ifs) { - e_dbg("Not in Adaptive IFS mode!\n"); - return; - } - - if ((mac->collision_delta * mac->ifs_ratio) > mac->tx_packet_delta) { - if (mac->tx_packet_delta > MIN_NUM_XMITS) { - mac->in_ifs_mode = true; - if (mac->current_ifs_val < mac->ifs_max_val) { - if (!mac->current_ifs_val) - mac->current_ifs_val = mac->ifs_min_val; - else - mac->current_ifs_val += - mac->ifs_step_size; - ew32(AIT, mac->current_ifs_val); - } - } - } else { - if (mac->in_ifs_mode && - (mac->tx_packet_delta <= MIN_NUM_XMITS)) { - mac->current_ifs_val = 0; - mac->in_ifs_mode = false; - ew32(AIT, 0); - } - } -} diff --git a/addons/e1000e/src/4.4.180/mac.h b/addons/e1000e/src/4.4.180/mac.h deleted file mode 100644 index 8284618a..00000000 --- a/addons/e1000e/src/4.4.180/mac.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#ifndef _E1000E_MAC_H_ -#define _E1000E_MAC_H_ - -s32 e1000e_blink_led_generic(struct e1000_hw *hw); -s32 e1000e_check_for_copper_link(struct e1000_hw *hw); -s32 e1000e_check_for_fiber_link(struct e1000_hw *hw); -s32 e1000e_check_for_serdes_link(struct e1000_hw *hw); -s32 e1000e_cleanup_led_generic(struct e1000_hw *hw); -s32 e1000e_config_fc_after_link_up(struct e1000_hw *hw); -s32 e1000e_disable_pcie_master(struct e1000_hw *hw); -s32 e1000e_force_mac_fc(struct e1000_hw *hw); -s32 e1000e_get_auto_rd_done(struct e1000_hw *hw); -s32 e1000e_get_bus_info_pcie(struct e1000_hw *hw); -void e1000_set_lan_id_single_port(struct e1000_hw *hw); -s32 e1000e_get_hw_semaphore(struct e1000_hw *hw); -s32 e1000e_get_speed_and_duplex_copper(struct e1000_hw *hw, u16 *speed, - u16 *duplex); -s32 e1000e_get_speed_and_duplex_fiber_serdes(struct e1000_hw *hw, - u16 *speed, u16 *duplex); -s32 e1000e_id_led_init_generic(struct e1000_hw *hw); -s32 e1000e_led_on_generic(struct e1000_hw *hw); -s32 e1000e_led_off_generic(struct e1000_hw *hw); -void e1000e_update_mc_addr_list_generic(struct e1000_hw *hw, - u8 *mc_addr_list, u32 mc_addr_count); -s32 e1000e_set_fc_watermarks(struct e1000_hw *hw); -s32 e1000e_setup_fiber_serdes_link(struct e1000_hw *hw); -s32 e1000e_setup_led_generic(struct e1000_hw *hw); -s32 e1000e_setup_link_generic(struct e1000_hw *hw); -s32 e1000e_validate_mdi_setting_generic(struct e1000_hw *hw); -s32 e1000e_validate_mdi_setting_crossover_generic(struct e1000_hw *hw); - -void e1000e_clear_hw_cntrs_base(struct e1000_hw *hw); -void e1000_clear_vfta_generic(struct e1000_hw *hw); -void e1000e_init_rx_addrs(struct e1000_hw *hw, u16 rar_count); -void e1000e_put_hw_semaphore(struct e1000_hw *hw); -s32 e1000_check_alt_mac_addr_generic(struct e1000_hw *hw); -void e1000e_reset_adaptive(struct e1000_hw *hw); -void e1000e_set_pcie_no_snoop(struct e1000_hw *hw, u32 no_snoop); -void e1000e_update_adaptive(struct e1000_hw *hw); -void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value); - -void e1000_set_lan_id_multi_port_pcie(struct e1000_hw *hw); -u32 e1000e_rar_get_count_generic(struct e1000_hw *hw); -int e1000e_rar_set_generic(struct e1000_hw *hw, u8 *addr, u32 index); -void e1000e_config_collision_dist_generic(struct e1000_hw *hw); - -#endif diff --git a/addons/e1000e/src/4.4.180/manage.c b/addons/e1000e/src/4.4.180/manage.c deleted file mode 100644 index cc9b3bef..00000000 --- a/addons/e1000e/src/4.4.180/manage.c +++ /dev/null @@ -1,347 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#include "e1000.h" - -/** - * e1000_calculate_checksum - Calculate checksum for buffer - * @buffer: pointer to EEPROM - * @length: size of EEPROM to calculate a checksum for - * - * Calculates the checksum for some buffer on a specified length. The - * checksum calculated is returned. - **/ -static u8 e1000_calculate_checksum(u8 *buffer, u32 length) -{ - u32 i; - u8 sum = 0; - - if (!buffer) - return 0; - - for (i = 0; i < length; i++) - sum += buffer[i]; - - return (u8)(0 - sum); -} - -/** - * e1000_mng_enable_host_if - Checks host interface is enabled - * @hw: pointer to the HW structure - * - * Returns 0 upon success, else -E1000_ERR_HOST_INTERFACE_COMMAND - * - * This function checks whether the HOST IF is enabled for command operation - * and also checks whether the previous command is completed. It busy waits - * in case of previous command is not completed. - **/ -static s32 e1000_mng_enable_host_if(struct e1000_hw *hw) -{ - u32 hicr; - u8 i; - - if (!hw->mac.arc_subsystem_valid) { - e_dbg("ARC subsystem not valid.\n"); - return -E1000_ERR_HOST_INTERFACE_COMMAND; - } - - /* Check that the host interface is enabled. */ - hicr = er32(HICR); - if (!(hicr & E1000_HICR_EN)) { - e_dbg("E1000_HOST_EN bit disabled.\n"); - return -E1000_ERR_HOST_INTERFACE_COMMAND; - } - /* check the previous command is completed */ - for (i = 0; i < E1000_MNG_DHCP_COMMAND_TIMEOUT; i++) { - hicr = er32(HICR); - if (!(hicr & E1000_HICR_C)) - break; - mdelay(1); - } - - if (i == E1000_MNG_DHCP_COMMAND_TIMEOUT) { - e_dbg("Previous command timeout failed.\n"); - return -E1000_ERR_HOST_INTERFACE_COMMAND; - } - - return 0; -} - -/** - * e1000e_check_mng_mode_generic - Generic check management mode - * @hw: pointer to the HW structure - * - * Reads the firmware semaphore register and returns true (>0) if - * manageability is enabled, else false (0). - **/ -bool e1000e_check_mng_mode_generic(struct e1000_hw *hw) -{ - u32 fwsm = er32(FWSM); - - return (fwsm & E1000_FWSM_MODE_MASK) == - (E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT); -} - -/** - * e1000e_enable_tx_pkt_filtering - Enable packet filtering on Tx - * @hw: pointer to the HW structure - * - * Enables packet filtering on transmit packets if manageability is enabled - * and host interface is enabled. - **/ -bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw) -{ - struct e1000_host_mng_dhcp_cookie *hdr = &hw->mng_cookie; - u32 *buffer = (u32 *)&hw->mng_cookie; - u32 offset; - s32 ret_val, hdr_csum, csum; - u8 i, len; - - hw->mac.tx_pkt_filtering = true; - - /* No manageability, no filtering */ - if (!hw->mac.ops.check_mng_mode(hw)) { - hw->mac.tx_pkt_filtering = false; - return hw->mac.tx_pkt_filtering; - } - - /* If we can't read from the host interface for whatever - * reason, disable filtering. - */ - ret_val = e1000_mng_enable_host_if(hw); - if (ret_val) { - hw->mac.tx_pkt_filtering = false; - return hw->mac.tx_pkt_filtering; - } - - /* Read in the header. Length and offset are in dwords. */ - len = E1000_MNG_DHCP_COOKIE_LENGTH >> 2; - offset = E1000_MNG_DHCP_COOKIE_OFFSET >> 2; - for (i = 0; i < len; i++) - *(buffer + i) = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, - offset + i); - hdr_csum = hdr->checksum; - hdr->checksum = 0; - csum = e1000_calculate_checksum((u8 *)hdr, - E1000_MNG_DHCP_COOKIE_LENGTH); - /* If either the checksums or signature don't match, then - * the cookie area isn't considered valid, in which case we - * take the safe route of assuming Tx filtering is enabled. - */ - if ((hdr_csum != csum) || (hdr->signature != E1000_IAMT_SIGNATURE)) { - hw->mac.tx_pkt_filtering = true; - return hw->mac.tx_pkt_filtering; - } - - /* Cookie area is valid, make the final check for filtering. */ - if (!(hdr->status & E1000_MNG_DHCP_COOKIE_STATUS_PARSING)) - hw->mac.tx_pkt_filtering = false; - - return hw->mac.tx_pkt_filtering; -} - -/** - * e1000_mng_write_cmd_header - Writes manageability command header - * @hw: pointer to the HW structure - * @hdr: pointer to the host interface command header - * - * Writes the command header after does the checksum calculation. - **/ -static s32 e1000_mng_write_cmd_header(struct e1000_hw *hw, - struct e1000_host_mng_command_header *hdr) -{ - u16 i, length = sizeof(struct e1000_host_mng_command_header); - - /* Write the whole command header structure with new checksum. */ - - hdr->checksum = e1000_calculate_checksum((u8 *)hdr, length); - - length >>= 2; - /* Write the relevant command block into the ram area. */ - for (i = 0; i < length; i++) { - E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, i, *((u32 *)hdr + i)); - e1e_flush(); - } - - return 0; -} - -/** - * e1000_mng_host_if_write - Write to the manageability host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface buffer - * @length: size of the buffer - * @offset: location in the buffer to write to - * @sum: sum of the data (not checksum) - * - * This function writes the buffer content at the offset given on the host if. - * It also does alignment considerations to do the writes in most efficient - * way. Also fills up the sum of the buffer in *buffer parameter. - **/ -static s32 e1000_mng_host_if_write(struct e1000_hw *hw, u8 *buffer, - u16 length, u16 offset, u8 *sum) -{ - u8 *tmp; - u8 *bufptr = buffer; - u32 data = 0; - u16 remaining, i, j, prev_bytes; - - /* sum = only sum of the data and it is not checksum */ - - if (length == 0 || offset + length > E1000_HI_MAX_MNG_DATA_LENGTH) - return -E1000_ERR_PARAM; - - tmp = (u8 *)&data; - prev_bytes = offset & 0x3; - offset >>= 2; - - if (prev_bytes) { - data = E1000_READ_REG_ARRAY(hw, E1000_HOST_IF, offset); - for (j = prev_bytes; j < sizeof(u32); j++) { - *(tmp + j) = *bufptr++; - *sum += *(tmp + j); - } - E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset, data); - length -= j - prev_bytes; - offset++; - } - - remaining = length & 0x3; - length -= remaining; - - /* Calculate length in DWORDs */ - length >>= 2; - - /* The device driver writes the relevant command block into the - * ram area. - */ - for (i = 0; i < length; i++) { - for (j = 0; j < sizeof(u32); j++) { - *(tmp + j) = *bufptr++; - *sum += *(tmp + j); - } - - E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data); - } - if (remaining) { - for (j = 0; j < sizeof(u32); j++) { - if (j < remaining) - *(tmp + j) = *bufptr++; - else - *(tmp + j) = 0; - - *sum += *(tmp + j); - } - E1000_WRITE_REG_ARRAY(hw, E1000_HOST_IF, offset + i, data); - } - - return 0; -} - -/** - * e1000e_mng_write_dhcp_info - Writes DHCP info to host interface - * @hw: pointer to the HW structure - * @buffer: pointer to the host interface - * @length: size of the buffer - * - * Writes the DHCP information to the host interface. - **/ -s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length) -{ - struct e1000_host_mng_command_header hdr; - s32 ret_val; - u32 hicr; - - hdr.command_id = E1000_MNG_DHCP_TX_PAYLOAD_CMD; - hdr.command_length = length; - hdr.reserved1 = 0; - hdr.reserved2 = 0; - hdr.checksum = 0; - - /* Enable the host interface */ - ret_val = e1000_mng_enable_host_if(hw); - if (ret_val) - return ret_val; - - /* Populate the host interface with the contents of "buffer". */ - ret_val = e1000_mng_host_if_write(hw, buffer, length, - sizeof(hdr), &(hdr.checksum)); - if (ret_val) - return ret_val; - - /* Write the manageability command header */ - ret_val = e1000_mng_write_cmd_header(hw, &hdr); - if (ret_val) - return ret_val; - - /* Tell the ARC a new command is pending. */ - hicr = er32(HICR); - ew32(HICR, hicr | E1000_HICR_C); - - return 0; -} - -/** - * e1000e_enable_mng_pass_thru - Check if management passthrough is needed - * @hw: pointer to the HW structure - * - * Verifies the hardware needs to leave interface enabled so that frames can - * be directed to and from the management interface. - **/ -bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw) -{ - u32 manc; - u32 fwsm, factps; - - manc = er32(MANC); - - if (!(manc & E1000_MANC_RCV_TCO_EN)) - return false; - - if (hw->mac.has_fwsm) { - fwsm = er32(FWSM); - factps = er32(FACTPS); - - if (!(factps & E1000_FACTPS_MNGCG) && - ((fwsm & E1000_FWSM_MODE_MASK) == - (e1000_mng_mode_pt << E1000_FWSM_MODE_SHIFT))) - return true; - } else if ((hw->mac.type == e1000_82574) || - (hw->mac.type == e1000_82583)) { - u16 data; - s32 ret_val; - - factps = er32(FACTPS); - ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data); - if (ret_val) - return false; - - if (!(factps & E1000_FACTPS_MNGCG) && - ((data & E1000_NVM_INIT_CTRL2_MNGM) == - (e1000_mng_mode_pt << 13))) - return true; - } else if ((manc & E1000_MANC_SMBUS_EN) && - !(manc & E1000_MANC_ASF_EN)) { - return true; - } - - return false; -} diff --git a/addons/e1000e/src/4.4.180/manage.h b/addons/e1000e/src/4.4.180/manage.h deleted file mode 100644 index 0b9ea595..00000000 --- a/addons/e1000e/src/4.4.180/manage.h +++ /dev/null @@ -1,65 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#ifndef _E1000E_MANAGE_H_ -#define _E1000E_MANAGE_H_ - -bool e1000e_check_mng_mode_generic(struct e1000_hw *hw); -bool e1000e_enable_tx_pkt_filtering(struct e1000_hw *hw); -s32 e1000e_mng_write_dhcp_info(struct e1000_hw *hw, u8 *buffer, u16 length); -bool e1000e_enable_mng_pass_thru(struct e1000_hw *hw); - -enum e1000_mng_mode { - e1000_mng_mode_none = 0, - e1000_mng_mode_asf, - e1000_mng_mode_pt, - e1000_mng_mode_ipmi, - e1000_mng_mode_host_if_only -}; - -#define E1000_FACTPS_MNGCG 0x20000000 - -#define E1000_FWSM_MODE_MASK 0xE -#define E1000_FWSM_MODE_SHIFT 1 - -#define E1000_MNG_IAMT_MODE 0x3 -#define E1000_MNG_DHCP_COOKIE_LENGTH 0x10 -#define E1000_MNG_DHCP_COOKIE_OFFSET 0x6F0 -#define E1000_MNG_DHCP_COMMAND_TIMEOUT 10 -#define E1000_MNG_DHCP_TX_PAYLOAD_CMD 64 -#define E1000_MNG_DHCP_COOKIE_STATUS_PARSING 0x1 -#define E1000_MNG_DHCP_COOKIE_STATUS_VLAN 0x2 - -#define E1000_VFTA_ENTRY_SHIFT 5 -#define E1000_VFTA_ENTRY_MASK 0x7F -#define E1000_VFTA_ENTRY_BIT_SHIFT_MASK 0x1F - -#define E1000_HICR_EN 0x01 /* Enable bit - RO */ -/* Driver sets this bit when done to put command in RAM */ -#define E1000_HICR_C 0x02 -#define E1000_HICR_SV 0x04 /* Status Validity */ -#define E1000_HICR_FW_RESET_ENABLE 0x40 -#define E1000_HICR_FW_RESET 0x80 - -/* Intel(R) Active Management Technology signature */ -#define E1000_IAMT_SIGNATURE 0x544D4149 - -#endif diff --git a/addons/e1000e/src/4.4.180/netdev.c b/addons/e1000e/src/4.4.180/netdev.c deleted file mode 100644 index 6b1cacd8..00000000 --- a/addons/e1000e/src/4.4.180/netdev.c +++ /dev/null @@ -1,7554 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "e1000.h" - -#define DRV_EXTRAVERSION "-k" - -#define DRV_VERSION "3.2.6" DRV_EXTRAVERSION -char e1000e_driver_name[] = "e1000e"; -const char e1000e_driver_version[] = DRV_VERSION; - -#define DEFAULT_MSG_ENABLE (NETIF_MSG_DRV|NETIF_MSG_PROBE|NETIF_MSG_LINK) -static int debug = -1; -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); - -static const struct e1000_info *e1000_info_tbl[] = { - [board_82571] = &e1000_82571_info, - [board_82572] = &e1000_82572_info, - [board_82573] = &e1000_82573_info, - [board_82574] = &e1000_82574_info, - [board_82583] = &e1000_82583_info, - [board_80003es2lan] = &e1000_es2_info, - [board_ich8lan] = &e1000_ich8_info, - [board_ich9lan] = &e1000_ich9_info, - [board_ich10lan] = &e1000_ich10_info, - [board_pchlan] = &e1000_pch_info, - [board_pch2lan] = &e1000_pch2_info, - [board_pch_lpt] = &e1000_pch_lpt_info, - [board_pch_spt] = &e1000_pch_spt_info, -}; - -struct e1000_reg_info { - u32 ofs; - char *name; -}; - -static const struct e1000_reg_info e1000_reg_info_tbl[] = { - /* General Registers */ - {E1000_CTRL, "CTRL"}, - {E1000_STATUS, "STATUS"}, - {E1000_CTRL_EXT, "CTRL_EXT"}, - - /* Interrupt Registers */ - {E1000_ICR, "ICR"}, - - /* Rx Registers */ - {E1000_RCTL, "RCTL"}, - {E1000_RDLEN(0), "RDLEN"}, - {E1000_RDH(0), "RDH"}, - {E1000_RDT(0), "RDT"}, - {E1000_RDTR, "RDTR"}, - {E1000_RXDCTL(0), "RXDCTL"}, - {E1000_ERT, "ERT"}, - {E1000_RDBAL(0), "RDBAL"}, - {E1000_RDBAH(0), "RDBAH"}, - {E1000_RDFH, "RDFH"}, - {E1000_RDFT, "RDFT"}, - {E1000_RDFHS, "RDFHS"}, - {E1000_RDFTS, "RDFTS"}, - {E1000_RDFPC, "RDFPC"}, - - /* Tx Registers */ - {E1000_TCTL, "TCTL"}, - {E1000_TDBAL(0), "TDBAL"}, - {E1000_TDBAH(0), "TDBAH"}, - {E1000_TDLEN(0), "TDLEN"}, - {E1000_TDH(0), "TDH"}, - {E1000_TDT(0), "TDT"}, - {E1000_TIDV, "TIDV"}, - {E1000_TXDCTL(0), "TXDCTL"}, - {E1000_TADV, "TADV"}, - {E1000_TARC(0), "TARC"}, - {E1000_TDFH, "TDFH"}, - {E1000_TDFT, "TDFT"}, - {E1000_TDFHS, "TDFHS"}, - {E1000_TDFTS, "TDFTS"}, - {E1000_TDFPC, "TDFPC"}, - - /* List Terminator */ - {0, NULL} -}; - -/** - * __ew32_prepare - prepare to write to MAC CSR register on certain parts - * @hw: pointer to the HW structure - * - * When updating the MAC CSR registers, the Manageability Engine (ME) could - * be accessing the registers at the same time. Normally, this is handled in - * h/w by an arbiter but on some parts there is a bug that acknowledges Host - * accesses later than it should which could result in the register to have - * an incorrect value. Workaround this by checking the FWSM register which - * has bit 24 set while ME is accessing MAC CSR registers, wait if it is set - * and try again a number of times. - **/ -s32 __ew32_prepare(struct e1000_hw *hw) -{ - s32 i = E1000_ICH_FWSM_PCIM2PCI_COUNT; - - while ((er32(FWSM) & E1000_ICH_FWSM_PCIM2PCI) && --i) - udelay(50); - - return i; -} - -void __ew32(struct e1000_hw *hw, unsigned long reg, u32 val) -{ - if (hw->adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - __ew32_prepare(hw); - - writel(val, hw->hw_addr + reg); -} - -/** - * e1000_regdump - register printout routine - * @hw: pointer to the HW structure - * @reginfo: pointer to the register info table - **/ -static void e1000_regdump(struct e1000_hw *hw, struct e1000_reg_info *reginfo) -{ - int n = 0; - char rname[16]; - u32 regs[8]; - - switch (reginfo->ofs) { - case E1000_RXDCTL(0): - for (n = 0; n < 2; n++) - regs[n] = __er32(hw, E1000_RXDCTL(n)); - break; - case E1000_TXDCTL(0): - for (n = 0; n < 2; n++) - regs[n] = __er32(hw, E1000_TXDCTL(n)); - break; - case E1000_TARC(0): - for (n = 0; n < 2; n++) - regs[n] = __er32(hw, E1000_TARC(n)); - break; - default: - pr_info("%-15s %08x\n", - reginfo->name, __er32(hw, reginfo->ofs)); - return; - } - - snprintf(rname, 16, "%s%s", reginfo->name, "[0-1]"); - pr_info("%-15s %08x %08x\n", rname, regs[0], regs[1]); -} - -static void e1000e_dump_ps_pages(struct e1000_adapter *adapter, - struct e1000_buffer *bi) -{ - int i; - struct e1000_ps_page *ps_page; - - for (i = 0; i < adapter->rx_ps_pages; i++) { - ps_page = &bi->ps_pages[i]; - - if (ps_page->page) { - pr_info("packet dump for ps_page %d:\n", i); - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, - 16, 1, page_address(ps_page->page), - PAGE_SIZE, true); - } - } -} - -/** - * e1000e_dump - Print registers, Tx-ring and Rx-ring - * @adapter: board private structure - **/ -static void e1000e_dump(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - struct e1000_reg_info *reginfo; - struct e1000_ring *tx_ring = adapter->tx_ring; - struct e1000_tx_desc *tx_desc; - struct my_u0 { - __le64 a; - __le64 b; - } *u0; - struct e1000_buffer *buffer_info; - struct e1000_ring *rx_ring = adapter->rx_ring; - union e1000_rx_desc_packet_split *rx_desc_ps; - union e1000_rx_desc_extended *rx_desc; - struct my_u1 { - __le64 a; - __le64 b; - __le64 c; - __le64 d; - } *u1; - u32 staterr; - int i = 0; - - if (!netif_msg_hw(adapter)) - return; - - /* Print netdevice Info */ - if (netdev) { - dev_info(&adapter->pdev->dev, "Net device Info\n"); - pr_info("Device Name state trans_start last_rx\n"); - pr_info("%-15s %016lX %016lX %016lX\n", netdev->name, - netdev->state, netdev->trans_start, netdev->last_rx); - } - - /* Print Registers */ - dev_info(&adapter->pdev->dev, "Register Dump\n"); - pr_info(" Register Name Value\n"); - for (reginfo = (struct e1000_reg_info *)e1000_reg_info_tbl; - reginfo->name; reginfo++) { - e1000_regdump(hw, reginfo); - } - - /* Print Tx Ring Summary */ - if (!netdev || !netif_running(netdev)) - return; - - dev_info(&adapter->pdev->dev, "Tx Ring Summary\n"); - pr_info("Queue [NTU] [NTC] [bi(ntc)->dma ] leng ntw timestamp\n"); - buffer_info = &tx_ring->buffer_info[tx_ring->next_to_clean]; - pr_info(" %5d %5X %5X %016llX %04X %3X %016llX\n", - 0, tx_ring->next_to_use, tx_ring->next_to_clean, - (unsigned long long)buffer_info->dma, - buffer_info->length, - buffer_info->next_to_watch, - (unsigned long long)buffer_info->time_stamp); - - /* Print Tx Ring */ - if (!netif_msg_tx_done(adapter)) - goto rx_ring_summary; - - dev_info(&adapter->pdev->dev, "Tx Ring Dump\n"); - - /* Transmit Descriptor Formats - DEXT[29] is 0 (Legacy) or 1 (Extended) - * - * Legacy Transmit Descriptor - * +--------------------------------------------------------------+ - * 0 | Buffer Address [63:0] (Reserved on Write Back) | - * +--------------------------------------------------------------+ - * 8 | Special | CSS | Status | CMD | CSO | Length | - * +--------------------------------------------------------------+ - * 63 48 47 36 35 32 31 24 23 16 15 0 - * - * Extended Context Descriptor (DTYP=0x0) for TSO or checksum offload - * 63 48 47 40 39 32 31 16 15 8 7 0 - * +----------------------------------------------------------------+ - * 0 | TUCSE | TUCS0 | TUCSS | IPCSE | IPCS0 | IPCSS | - * +----------------------------------------------------------------+ - * 8 | MSS | HDRLEN | RSV | STA | TUCMD | DTYP | PAYLEN | - * +----------------------------------------------------------------+ - * 63 48 47 40 39 36 35 32 31 24 23 20 19 0 - * - * Extended Data Descriptor (DTYP=0x1) - * +----------------------------------------------------------------+ - * 0 | Buffer Address [63:0] | - * +----------------------------------------------------------------+ - * 8 | VLAN tag | POPTS | Rsvd | Status | Command | DTYP | DTALEN | - * +----------------------------------------------------------------+ - * 63 48 47 40 39 36 35 32 31 24 23 20 19 0 - */ - pr_info("Tl[desc] [address 63:0 ] [SpeCssSCmCsLen] [bi->dma ] leng ntw timestamp bi->skb <-- Legacy format\n"); - pr_info("Tc[desc] [Ce CoCsIpceCoS] [MssHlRSCm0Plen] [bi->dma ] leng ntw timestamp bi->skb <-- Ext Context format\n"); - pr_info("Td[desc] [address 63:0 ] [VlaPoRSCm1Dlen] [bi->dma ] leng ntw timestamp bi->skb <-- Ext Data format\n"); - for (i = 0; tx_ring->desc && (i < tx_ring->count); i++) { - const char *next_desc; - tx_desc = E1000_TX_DESC(*tx_ring, i); - buffer_info = &tx_ring->buffer_info[i]; - u0 = (struct my_u0 *)tx_desc; - if (i == tx_ring->next_to_use && i == tx_ring->next_to_clean) - next_desc = " NTC/U"; - else if (i == tx_ring->next_to_use) - next_desc = " NTU"; - else if (i == tx_ring->next_to_clean) - next_desc = " NTC"; - else - next_desc = ""; - pr_info("T%c[0x%03X] %016llX %016llX %016llX %04X %3X %016llX %p%s\n", - (!(le64_to_cpu(u0->b) & (1 << 29)) ? 'l' : - ((le64_to_cpu(u0->b) & (1 << 20)) ? 'd' : 'c')), - i, - (unsigned long long)le64_to_cpu(u0->a), - (unsigned long long)le64_to_cpu(u0->b), - (unsigned long long)buffer_info->dma, - buffer_info->length, buffer_info->next_to_watch, - (unsigned long long)buffer_info->time_stamp, - buffer_info->skb, next_desc); - - if (netif_msg_pktdata(adapter) && buffer_info->skb) - print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, - 16, 1, buffer_info->skb->data, - buffer_info->skb->len, true); - } - - /* Print Rx Ring Summary */ -rx_ring_summary: - dev_info(&adapter->pdev->dev, "Rx Ring Summary\n"); - pr_info("Queue [NTU] [NTC]\n"); - pr_info(" %5d %5X %5X\n", - 0, rx_ring->next_to_use, rx_ring->next_to_clean); - - /* Print Rx Ring */ - if (!netif_msg_rx_status(adapter)) - return; - - dev_info(&adapter->pdev->dev, "Rx Ring Dump\n"); - switch (adapter->rx_ps_pages) { - case 1: - case 2: - case 3: - /* [Extended] Packet Split Receive Descriptor Format - * - * +-----------------------------------------------------+ - * 0 | Buffer Address 0 [63:0] | - * +-----------------------------------------------------+ - * 8 | Buffer Address 1 [63:0] | - * +-----------------------------------------------------+ - * 16 | Buffer Address 2 [63:0] | - * +-----------------------------------------------------+ - * 24 | Buffer Address 3 [63:0] | - * +-----------------------------------------------------+ - */ - pr_info("R [desc] [buffer 0 63:0 ] [buffer 1 63:0 ] [buffer 2 63:0 ] [buffer 3 63:0 ] [bi->dma ] [bi->skb] <-- Ext Pkt Split format\n"); - /* [Extended] Receive Descriptor (Write-Back) Format - * - * 63 48 47 32 31 13 12 8 7 4 3 0 - * +------------------------------------------------------+ - * 0 | Packet | IP | Rsvd | MRQ | Rsvd | MRQ RSS | - * | Checksum | Ident | | Queue | | Type | - * +------------------------------------------------------+ - * 8 | VLAN Tag | Length | Extended Error | Extended Status | - * +------------------------------------------------------+ - * 63 48 47 32 31 20 19 0 - */ - pr_info("RWB[desc] [ck ipid mrqhsh] [vl l0 ee es] [ l3 l2 l1 hs] [reserved ] ---------------- [bi->skb] <-- Ext Rx Write-Back format\n"); - for (i = 0; i < rx_ring->count; i++) { - const char *next_desc; - buffer_info = &rx_ring->buffer_info[i]; - rx_desc_ps = E1000_RX_DESC_PS(*rx_ring, i); - u1 = (struct my_u1 *)rx_desc_ps; - staterr = - le32_to_cpu(rx_desc_ps->wb.middle.status_error); - - if (i == rx_ring->next_to_use) - next_desc = " NTU"; - else if (i == rx_ring->next_to_clean) - next_desc = " NTC"; - else - next_desc = ""; - - if (staterr & E1000_RXD_STAT_DD) { - /* Descriptor Done */ - pr_info("%s[0x%03X] %016llX %016llX %016llX %016llX ---------------- %p%s\n", - "RWB", i, - (unsigned long long)le64_to_cpu(u1->a), - (unsigned long long)le64_to_cpu(u1->b), - (unsigned long long)le64_to_cpu(u1->c), - (unsigned long long)le64_to_cpu(u1->d), - buffer_info->skb, next_desc); - } else { - pr_info("%s[0x%03X] %016llX %016llX %016llX %016llX %016llX %p%s\n", - "R ", i, - (unsigned long long)le64_to_cpu(u1->a), - (unsigned long long)le64_to_cpu(u1->b), - (unsigned long long)le64_to_cpu(u1->c), - (unsigned long long)le64_to_cpu(u1->d), - (unsigned long long)buffer_info->dma, - buffer_info->skb, next_desc); - - if (netif_msg_pktdata(adapter)) - e1000e_dump_ps_pages(adapter, - buffer_info); - } - } - break; - default: - case 0: - /* Extended Receive Descriptor (Read) Format - * - * +-----------------------------------------------------+ - * 0 | Buffer Address [63:0] | - * +-----------------------------------------------------+ - * 8 | Reserved | - * +-----------------------------------------------------+ - */ - pr_info("R [desc] [buf addr 63:0 ] [reserved 63:0 ] [bi->dma ] [bi->skb] <-- Ext (Read) format\n"); - /* Extended Receive Descriptor (Write-Back) Format - * - * 63 48 47 32 31 24 23 4 3 0 - * +------------------------------------------------------+ - * | RSS Hash | | | | - * 0 +-------------------+ Rsvd | Reserved | MRQ RSS | - * | Packet | IP | | | Type | - * | Checksum | Ident | | | | - * +------------------------------------------------------+ - * 8 | VLAN Tag | Length | Extended Error | Extended Status | - * +------------------------------------------------------+ - * 63 48 47 32 31 20 19 0 - */ - pr_info("RWB[desc] [cs ipid mrq] [vt ln xe xs] [bi->skb] <-- Ext (Write-Back) format\n"); - - for (i = 0; i < rx_ring->count; i++) { - const char *next_desc; - - buffer_info = &rx_ring->buffer_info[i]; - rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); - u1 = (struct my_u1 *)rx_desc; - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); - - if (i == rx_ring->next_to_use) - next_desc = " NTU"; - else if (i == rx_ring->next_to_clean) - next_desc = " NTC"; - else - next_desc = ""; - - if (staterr & E1000_RXD_STAT_DD) { - /* Descriptor Done */ - pr_info("%s[0x%03X] %016llX %016llX ---------------- %p%s\n", - "RWB", i, - (unsigned long long)le64_to_cpu(u1->a), - (unsigned long long)le64_to_cpu(u1->b), - buffer_info->skb, next_desc); - } else { - pr_info("%s[0x%03X] %016llX %016llX %016llX %p%s\n", - "R ", i, - (unsigned long long)le64_to_cpu(u1->a), - (unsigned long long)le64_to_cpu(u1->b), - (unsigned long long)buffer_info->dma, - buffer_info->skb, next_desc); - - if (netif_msg_pktdata(adapter) && - buffer_info->skb) - print_hex_dump(KERN_INFO, "", - DUMP_PREFIX_ADDRESS, 16, - 1, - buffer_info->skb->data, - adapter->rx_buffer_len, - true); - } - } - } -} - -/** - * e1000_desc_unused - calculate if we have unused descriptors - **/ -static int e1000_desc_unused(struct e1000_ring *ring) -{ - if (ring->next_to_clean > ring->next_to_use) - return ring->next_to_clean - ring->next_to_use - 1; - - return ring->count + ring->next_to_clean - ring->next_to_use - 1; -} - -/** - * e1000e_systim_to_hwtstamp - convert system time value to hw time stamp - * @adapter: board private structure - * @hwtstamps: time stamp structure to update - * @systim: unsigned 64bit system time value. - * - * Convert the system time value stored in the RX/TXSTMP registers into a - * hwtstamp which can be used by the upper level time stamping functions. - * - * The 'systim_lock' spinlock is used to protect the consistency of the - * system time value. This is needed because reading the 64 bit time - * value involves reading two 32 bit registers. The first read latches the - * value. - **/ -static void e1000e_systim_to_hwtstamp(struct e1000_adapter *adapter, - struct skb_shared_hwtstamps *hwtstamps, - u64 systim) -{ - u64 ns; - unsigned long flags; - - spin_lock_irqsave(&adapter->systim_lock, flags); - ns = timecounter_cyc2time(&adapter->tc, systim); - spin_unlock_irqrestore(&adapter->systim_lock, flags); - - memset(hwtstamps, 0, sizeof(*hwtstamps)); - hwtstamps->hwtstamp = ns_to_ktime(ns); -} - -/** - * e1000e_rx_hwtstamp - utility function which checks for Rx time stamp - * @adapter: board private structure - * @status: descriptor extended error and status field - * @skb: particular skb to include time stamp - * - * If the time stamp is valid, convert it into the timecounter ns value - * and store that result into the shhwtstamps structure which is passed - * up the network stack. - **/ -static void e1000e_rx_hwtstamp(struct e1000_adapter *adapter, u32 status, - struct sk_buff *skb) -{ - struct e1000_hw *hw = &adapter->hw; - u64 rxstmp; - - if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP) || - !(status & E1000_RXDEXT_STATERR_TST) || - !(er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID)) - return; - - /* The Rx time stamp registers contain the time stamp. No other - * received packet will be time stamped until the Rx time stamp - * registers are read. Because only one packet can be time stamped - * at a time, the register values must belong to this packet and - * therefore none of the other additional attributes need to be - * compared. - */ - rxstmp = (u64)er32(RXSTMPL); - rxstmp |= (u64)er32(RXSTMPH) << 32; - e1000e_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), rxstmp); - - adapter->flags2 &= ~FLAG2_CHECK_RX_HWTSTAMP; -} - -/** - * e1000_receive_skb - helper function to handle Rx indications - * @adapter: board private structure - * @staterr: descriptor extended error and status field as written by hardware - * @vlan: descriptor vlan field as written by hardware (no le/be conversion) - * @skb: pointer to sk_buff to be indicated to stack - **/ -static void e1000_receive_skb(struct e1000_adapter *adapter, - struct net_device *netdev, struct sk_buff *skb, - u32 staterr, __le16 vlan) -{ - u16 tag = le16_to_cpu(vlan); - - e1000e_rx_hwtstamp(adapter, staterr, skb); - - skb->protocol = eth_type_trans(skb, netdev); - - if (staterr & E1000_RXD_STAT_VP) - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), tag); - - napi_gro_receive(&adapter->napi, skb); -} - -/** - * e1000_rx_checksum - Receive Checksum Offload - * @adapter: board private structure - * @status_err: receive descriptor status and error fields - * @csum: receive descriptor csum field - * @sk_buff: socket buffer with received data - **/ -static void e1000_rx_checksum(struct e1000_adapter *adapter, u32 status_err, - struct sk_buff *skb) -{ - u16 status = (u16)status_err; - u8 errors = (u8)(status_err >> 24); - - skb_checksum_none_assert(skb); - - /* Rx checksum disabled */ - if (!(adapter->netdev->features & NETIF_F_RXCSUM)) - return; - - /* Ignore Checksum bit is set */ - if (status & E1000_RXD_STAT_IXSM) - return; - - /* TCP/UDP checksum error bit or IP checksum error bit is set */ - if (errors & (E1000_RXD_ERR_TCPE | E1000_RXD_ERR_IPE)) { - /* let the stack verify checksum errors */ - adapter->hw_csum_err++; - return; - } - - /* TCP/UDP Checksum has not been calculated */ - if (!(status & (E1000_RXD_STAT_TCPCS | E1000_RXD_STAT_UDPCS))) - return; - - /* It must be a TCP or UDP packet with a valid checksum */ - skb->ip_summed = CHECKSUM_UNNECESSARY; - adapter->hw_csum_good++; -} - -static void e1000e_update_rdt_wa(struct e1000_ring *rx_ring, unsigned int i) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct e1000_hw *hw = &adapter->hw; - s32 ret_val = __ew32_prepare(hw); - - writel(i, rx_ring->tail); - - if (unlikely(!ret_val && (i != readl(rx_ring->tail)))) { - u32 rctl = er32(RCTL); - - ew32(RCTL, rctl & ~E1000_RCTL_EN); - e_err("ME firmware caused invalid RDT - resetting\n"); - schedule_work(&adapter->reset_task); - } -} - -static void e1000e_update_tdt_wa(struct e1000_ring *tx_ring, unsigned int i) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct e1000_hw *hw = &adapter->hw; - s32 ret_val = __ew32_prepare(hw); - - writel(i, tx_ring->tail); - - if (unlikely(!ret_val && (i != readl(tx_ring->tail)))) { - u32 tctl = er32(TCTL); - - ew32(TCTL, tctl & ~E1000_TCTL_EN); - e_err("ME firmware caused invalid TDT - resetting\n"); - schedule_work(&adapter->reset_task); - } -} - -/** - * e1000_alloc_rx_buffers - Replace used receive buffers - * @rx_ring: Rx descriptor ring - **/ -static void e1000_alloc_rx_buffers(struct e1000_ring *rx_ring, - int cleaned_count, gfp_t gfp) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - union e1000_rx_desc_extended *rx_desc; - struct e1000_buffer *buffer_info; - struct sk_buff *skb; - unsigned int i; - unsigned int bufsz = adapter->rx_buffer_len; - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - - while (cleaned_count--) { - skb = buffer_info->skb; - if (skb) { - skb_trim(skb, 0); - goto map_skb; - } - - skb = __netdev_alloc_skb_ip_align(netdev, bufsz, gfp); - if (!skb) { - /* Better luck next round */ - adapter->alloc_rx_buff_failed++; - break; - } - - buffer_info->skb = skb; -map_skb: - buffer_info->dma = dma_map_single(&pdev->dev, skb->data, - adapter->rx_buffer_len, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { - dev_err(&pdev->dev, "Rx DMA map failed\n"); - adapter->rx_dma_failed++; - break; - } - - rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); - rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma); - - if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) { - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_rdt_wa(rx_ring, i); - else - writel(i, rx_ring->tail); - } - i++; - if (i == rx_ring->count) - i = 0; - buffer_info = &rx_ring->buffer_info[i]; - } - - rx_ring->next_to_use = i; -} - -/** - * e1000_alloc_rx_buffers_ps - Replace used receive buffers; packet split - * @rx_ring: Rx descriptor ring - **/ -static void e1000_alloc_rx_buffers_ps(struct e1000_ring *rx_ring, - int cleaned_count, gfp_t gfp) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - union e1000_rx_desc_packet_split *rx_desc; - struct e1000_buffer *buffer_info; - struct e1000_ps_page *ps_page; - struct sk_buff *skb; - unsigned int i, j; - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - - while (cleaned_count--) { - rx_desc = E1000_RX_DESC_PS(*rx_ring, i); - - for (j = 0; j < PS_PAGE_BUFFERS; j++) { - ps_page = &buffer_info->ps_pages[j]; - if (j >= adapter->rx_ps_pages) { - /* all unused desc entries get hw null ptr */ - rx_desc->read.buffer_addr[j + 1] = - ~cpu_to_le64(0); - continue; - } - if (!ps_page->page) { - ps_page->page = alloc_page(gfp); - if (!ps_page->page) { - adapter->alloc_rx_buff_failed++; - goto no_buffers; - } - ps_page->dma = dma_map_page(&pdev->dev, - ps_page->page, - 0, PAGE_SIZE, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, - ps_page->dma)) { - dev_err(&adapter->pdev->dev, - "Rx DMA page map failed\n"); - adapter->rx_dma_failed++; - goto no_buffers; - } - } - /* Refresh the desc even if buffer_addrs - * didn't change because each write-back - * erases this info. - */ - rx_desc->read.buffer_addr[j + 1] = - cpu_to_le64(ps_page->dma); - } - - skb = __netdev_alloc_skb_ip_align(netdev, adapter->rx_ps_bsize0, - gfp); - - if (!skb) { - adapter->alloc_rx_buff_failed++; - break; - } - - buffer_info->skb = skb; - buffer_info->dma = dma_map_single(&pdev->dev, skb->data, - adapter->rx_ps_bsize0, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { - dev_err(&pdev->dev, "Rx DMA map failed\n"); - adapter->rx_dma_failed++; - /* cleanup skb */ - dev_kfree_skb_any(skb); - buffer_info->skb = NULL; - break; - } - - rx_desc->read.buffer_addr[0] = cpu_to_le64(buffer_info->dma); - - if (unlikely(!(i & (E1000_RX_BUFFER_WRITE - 1)))) { - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_rdt_wa(rx_ring, i << 1); - else - writel(i << 1, rx_ring->tail); - } - - i++; - if (i == rx_ring->count) - i = 0; - buffer_info = &rx_ring->buffer_info[i]; - } - -no_buffers: - rx_ring->next_to_use = i; -} - -/** - * e1000_alloc_jumbo_rx_buffers - Replace used jumbo receive buffers - * @rx_ring: Rx descriptor ring - * @cleaned_count: number of buffers to allocate this pass - **/ - -static void e1000_alloc_jumbo_rx_buffers(struct e1000_ring *rx_ring, - int cleaned_count, gfp_t gfp) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - union e1000_rx_desc_extended *rx_desc; - struct e1000_buffer *buffer_info; - struct sk_buff *skb; - unsigned int i; - unsigned int bufsz = 256 - 16; /* for skb_reserve */ - - i = rx_ring->next_to_use; - buffer_info = &rx_ring->buffer_info[i]; - - while (cleaned_count--) { - skb = buffer_info->skb; - if (skb) { - skb_trim(skb, 0); - goto check_page; - } - - skb = __netdev_alloc_skb_ip_align(netdev, bufsz, gfp); - if (unlikely(!skb)) { - /* Better luck next round */ - adapter->alloc_rx_buff_failed++; - break; - } - - buffer_info->skb = skb; -check_page: - /* allocate a new page if necessary */ - if (!buffer_info->page) { - buffer_info->page = alloc_page(gfp); - if (unlikely(!buffer_info->page)) { - adapter->alloc_rx_buff_failed++; - break; - } - } - - if (!buffer_info->dma) { - buffer_info->dma = dma_map_page(&pdev->dev, - buffer_info->page, 0, - PAGE_SIZE, - DMA_FROM_DEVICE); - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) { - adapter->alloc_rx_buff_failed++; - break; - } - } - - rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); - rx_desc->read.buffer_addr = cpu_to_le64(buffer_info->dma); - - if (unlikely(++i == rx_ring->count)) - i = 0; - buffer_info = &rx_ring->buffer_info[i]; - } - - if (likely(rx_ring->next_to_use != i)) { - rx_ring->next_to_use = i; - if (unlikely(i-- == 0)) - i = (rx_ring->count - 1); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_rdt_wa(rx_ring, i); - else - writel(i, rx_ring->tail); - } -} - -static inline void e1000_rx_hash(struct net_device *netdev, __le32 rss, - struct sk_buff *skb) -{ - if (netdev->features & NETIF_F_RXHASH) - skb_set_hash(skb, le32_to_cpu(rss), PKT_HASH_TYPE_L3); -} - -/** - * e1000_clean_rx_irq - Send received data up the network stack - * @rx_ring: Rx descriptor ring - * - * the return value indicates whether actual cleaning was done, there - * is no guarantee that everything was cleaned - **/ -static bool e1000_clean_rx_irq(struct e1000_ring *rx_ring, int *work_done, - int work_to_do) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_hw *hw = &adapter->hw; - union e1000_rx_desc_extended *rx_desc, *next_rxd; - struct e1000_buffer *buffer_info, *next_buffer; - u32 length, staterr; - unsigned int i; - int cleaned_count = 0; - bool cleaned = false; - unsigned int total_rx_bytes = 0, total_rx_packets = 0; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); - buffer_info = &rx_ring->buffer_info[i]; - - while (staterr & E1000_RXD_STAT_DD) { - struct sk_buff *skb; - - if (*work_done >= work_to_do) - break; - (*work_done)++; - dma_rmb(); /* read descriptor and rx_buffer_info after status DD */ - - skb = buffer_info->skb; - buffer_info->skb = NULL; - - prefetch(skb->data - NET_IP_ALIGN); - - i++; - if (i == rx_ring->count) - i = 0; - next_rxd = E1000_RX_DESC_EXT(*rx_ring, i); - prefetch(next_rxd); - - next_buffer = &rx_ring->buffer_info[i]; - - cleaned = true; - cleaned_count++; - dma_unmap_single(&pdev->dev, buffer_info->dma, - adapter->rx_buffer_len, DMA_FROM_DEVICE); - buffer_info->dma = 0; - - length = le16_to_cpu(rx_desc->wb.upper.length); - - /* !EOP means multiple descriptors were used to store a single - * packet, if that's the case we need to toss it. In fact, we - * need to toss every packet with the EOP bit clear and the - * next frame that _does_ have the EOP bit set, as it is by - * definition only a frame fragment - */ - if (unlikely(!(staterr & E1000_RXD_STAT_EOP))) - adapter->flags2 |= FLAG2_IS_DISCARDING; - - if (adapter->flags2 & FLAG2_IS_DISCARDING) { - /* All receives must fit into a single buffer */ - e_dbg("Receive packet consumed multiple buffers\n"); - /* recycle */ - buffer_info->skb = skb; - if (staterr & E1000_RXD_STAT_EOP) - adapter->flags2 &= ~FLAG2_IS_DISCARDING; - goto next_desc; - } - - if (unlikely((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) && - !(netdev->features & NETIF_F_RXALL))) { - /* recycle */ - buffer_info->skb = skb; - goto next_desc; - } - - /* adjust length to remove Ethernet CRC */ - if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) { - /* If configured to store CRC, don't subtract FCS, - * but keep the FCS bytes out of the total_rx_bytes - * counter - */ - if (netdev->features & NETIF_F_RXFCS) - total_rx_bytes -= 4; - else - length -= 4; - } - - total_rx_bytes += length; - total_rx_packets++; - - /* code added for copybreak, this should improve - * performance for small packets with large amounts - * of reassembly being done in the stack - */ - if (length < copybreak) { - struct sk_buff *new_skb = - napi_alloc_skb(&adapter->napi, length); - if (new_skb) { - skb_copy_to_linear_data_offset(new_skb, - -NET_IP_ALIGN, - (skb->data - - NET_IP_ALIGN), - (length + - NET_IP_ALIGN)); - /* save the skb in buffer_info as good */ - buffer_info->skb = skb; - skb = new_skb; - } - /* else just continue with the old one */ - } - /* end copybreak code */ - skb_put(skb, length); - - /* Receive Checksum Offload */ - e1000_rx_checksum(adapter, staterr, skb); - - e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); - - e1000_receive_skb(adapter, netdev, skb, staterr, - rx_desc->wb.upper.vlan); - -next_desc: - rx_desc->wb.upper.status_error &= cpu_to_le32(~0xFF); - - /* return some buffers to hardware, one at a time is too slow */ - if (cleaned_count >= E1000_RX_BUFFER_WRITE) { - adapter->alloc_rx_buf(rx_ring, cleaned_count, - GFP_ATOMIC); - cleaned_count = 0; - } - - /* use prefetched values */ - rx_desc = next_rxd; - buffer_info = next_buffer; - - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); - } - rx_ring->next_to_clean = i; - - cleaned_count = e1000_desc_unused(rx_ring); - if (cleaned_count) - adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); - - adapter->total_rx_bytes += total_rx_bytes; - adapter->total_rx_packets += total_rx_packets; - return cleaned; -} - -static void e1000_put_txbuf(struct e1000_ring *tx_ring, - struct e1000_buffer *buffer_info) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - - if (buffer_info->dma) { - if (buffer_info->mapped_as_page) - dma_unmap_page(&adapter->pdev->dev, buffer_info->dma, - buffer_info->length, DMA_TO_DEVICE); - else - dma_unmap_single(&adapter->pdev->dev, buffer_info->dma, - buffer_info->length, DMA_TO_DEVICE); - buffer_info->dma = 0; - } - if (buffer_info->skb) { - dev_kfree_skb_any(buffer_info->skb); - buffer_info->skb = NULL; - } - buffer_info->time_stamp = 0; -} - -static void e1000_print_hw_hang(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - print_hang_task); - struct net_device *netdev = adapter->netdev; - struct e1000_ring *tx_ring = adapter->tx_ring; - unsigned int i = tx_ring->next_to_clean; - unsigned int eop = tx_ring->buffer_info[i].next_to_watch; - struct e1000_tx_desc *eop_desc = E1000_TX_DESC(*tx_ring, eop); - struct e1000_hw *hw = &adapter->hw; - u16 phy_status, phy_1000t_status, phy_ext_status; - u16 pci_status; - - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - - if (!adapter->tx_hang_recheck && (adapter->flags2 & FLAG2_DMA_BURST)) { - /* May be block on write-back, flush and detect again - * flush pending descriptor writebacks to memory - */ - ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); - /* execute the writes immediately */ - e1e_flush(); - /* Due to rare timing issues, write to TIDV again to ensure - * the write is successful - */ - ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); - /* execute the writes immediately */ - e1e_flush(); - adapter->tx_hang_recheck = true; - return; - } - adapter->tx_hang_recheck = false; - - if (er32(TDH(0)) == er32(TDT(0))) { - e_dbg("false hang detected, ignoring\n"); - return; - } - - /* Real hang detected */ - netif_stop_queue(netdev); - - e1e_rphy(hw, MII_BMSR, &phy_status); - e1e_rphy(hw, MII_STAT1000, &phy_1000t_status); - e1e_rphy(hw, MII_ESTATUS, &phy_ext_status); - - pci_read_config_word(adapter->pdev, PCI_STATUS, &pci_status); - - /* detected Hardware unit hang */ - e_err("Detected Hardware Unit Hang:\n" - " TDH <%x>\n" - " TDT <%x>\n" - " next_to_use <%x>\n" - " next_to_clean <%x>\n" - "buffer_info[next_to_clean]:\n" - " time_stamp <%lx>\n" - " next_to_watch <%x>\n" - " jiffies <%lx>\n" - " next_to_watch.status <%x>\n" - "MAC Status <%x>\n" - "PHY Status <%x>\n" - "PHY 1000BASE-T Status <%x>\n" - "PHY Extended Status <%x>\n" - "PCI Status <%x>\n", - readl(tx_ring->head), readl(tx_ring->tail), tx_ring->next_to_use, - tx_ring->next_to_clean, tx_ring->buffer_info[eop].time_stamp, - eop, jiffies, eop_desc->upper.fields.status, er32(STATUS), - phy_status, phy_1000t_status, phy_ext_status, pci_status); - - e1000e_dump(adapter); - - /* Suggest workaround for known h/w issue */ - if ((hw->mac.type == e1000_pchlan) && (er32(CTRL) & E1000_CTRL_TFCE)) - e_err("Try turning off Tx pause (flow control) via ethtool\n"); -} - -/** - * e1000e_tx_hwtstamp_work - check for Tx time stamp - * @work: pointer to work struct - * - * This work function polls the TSYNCTXCTL valid bit to determine when a - * timestamp has been taken for the current stored skb. The timestamp must - * be for this skb because only one such packet is allowed in the queue. - */ -static void e1000e_tx_hwtstamp_work(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, struct e1000_adapter, - tx_hwtstamp_work); - struct e1000_hw *hw = &adapter->hw; - - if (er32(TSYNCTXCTL) & E1000_TSYNCTXCTL_VALID) { - struct sk_buff *skb = adapter->tx_hwtstamp_skb; - struct skb_shared_hwtstamps shhwtstamps; - u64 txstmp; - - txstmp = er32(TXSTMPL); - txstmp |= (u64)er32(TXSTMPH) << 32; - - e1000e_systim_to_hwtstamp(adapter, &shhwtstamps, txstmp); - - /* Clear the global tx_hwtstamp_skb pointer and force writes - * prior to notifying the stack of a Tx timestamp. - */ - adapter->tx_hwtstamp_skb = NULL; - wmb(); /* force write prior to skb_tstamp_tx */ - - skb_tstamp_tx(skb, &shhwtstamps); - dev_kfree_skb_any(skb); - } else if (time_after(jiffies, adapter->tx_hwtstamp_start - + adapter->tx_timeout_factor * HZ)) { - dev_kfree_skb_any(adapter->tx_hwtstamp_skb); - adapter->tx_hwtstamp_skb = NULL; - adapter->tx_hwtstamp_timeouts++; - e_warn("clearing Tx timestamp hang\n"); - } else { - /* reschedule to check later */ - schedule_work(&adapter->tx_hwtstamp_work); - } -} - -/** - * e1000_clean_tx_irq - Reclaim resources after transmit completes - * @tx_ring: Tx descriptor ring - * - * the return value indicates whether actual cleaning was done, there - * is no guarantee that everything was cleaned - **/ -static bool e1000_clean_tx_irq(struct e1000_ring *tx_ring) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - struct e1000_tx_desc *tx_desc, *eop_desc; - struct e1000_buffer *buffer_info; - unsigned int i, eop; - unsigned int count = 0; - unsigned int total_tx_bytes = 0, total_tx_packets = 0; - unsigned int bytes_compl = 0, pkts_compl = 0; - - i = tx_ring->next_to_clean; - eop = tx_ring->buffer_info[i].next_to_watch; - eop_desc = E1000_TX_DESC(*tx_ring, eop); - - while ((eop_desc->upper.data & cpu_to_le32(E1000_TXD_STAT_DD)) && - (count < tx_ring->count)) { - bool cleaned = false; - - dma_rmb(); /* read buffer_info after eop_desc */ - for (; !cleaned; count++) { - tx_desc = E1000_TX_DESC(*tx_ring, i); - buffer_info = &tx_ring->buffer_info[i]; - cleaned = (i == eop); - - if (cleaned) { - total_tx_packets += buffer_info->segs; - total_tx_bytes += buffer_info->bytecount; - if (buffer_info->skb) { - bytes_compl += buffer_info->skb->len; - pkts_compl++; - } - } - - e1000_put_txbuf(tx_ring, buffer_info); - tx_desc->upper.data = 0; - - i++; - if (i == tx_ring->count) - i = 0; - } - - if (i == tx_ring->next_to_use) - break; - eop = tx_ring->buffer_info[i].next_to_watch; - eop_desc = E1000_TX_DESC(*tx_ring, eop); - } - - tx_ring->next_to_clean = i; - - netdev_completed_queue(netdev, pkts_compl, bytes_compl); - -#define TX_WAKE_THRESHOLD 32 - if (count && netif_carrier_ok(netdev) && - e1000_desc_unused(tx_ring) >= TX_WAKE_THRESHOLD) { - /* Make sure that anybody stopping the queue after this - * sees the new next_to_clean. - */ - smp_mb(); - - if (netif_queue_stopped(netdev) && - !(test_bit(__E1000_DOWN, &adapter->state))) { - netif_wake_queue(netdev); - ++adapter->restart_queue; - } - } - - if (adapter->detect_tx_hung) { - /* Detect a transmit hang in hardware, this serializes the - * check with the clearing of time_stamp and movement of i - */ - adapter->detect_tx_hung = false; - if (tx_ring->buffer_info[i].time_stamp && - time_after(jiffies, tx_ring->buffer_info[i].time_stamp - + (adapter->tx_timeout_factor * HZ)) && - !(er32(STATUS) & E1000_STATUS_TXOFF)) - schedule_work(&adapter->print_hang_task); - else - adapter->tx_hang_recheck = false; - } - adapter->total_tx_bytes += total_tx_bytes; - adapter->total_tx_packets += total_tx_packets; - return count < tx_ring->count; -} - -/** - * e1000_clean_rx_irq_ps - Send received data up the network stack; packet split - * @rx_ring: Rx descriptor ring - * - * the return value indicates whether actual cleaning was done, there - * is no guarantee that everything was cleaned - **/ -static bool e1000_clean_rx_irq_ps(struct e1000_ring *rx_ring, int *work_done, - int work_to_do) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct e1000_hw *hw = &adapter->hw; - union e1000_rx_desc_packet_split *rx_desc, *next_rxd; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - struct e1000_buffer *buffer_info, *next_buffer; - struct e1000_ps_page *ps_page; - struct sk_buff *skb; - unsigned int i, j; - u32 length, staterr; - int cleaned_count = 0; - bool cleaned = false; - unsigned int total_rx_bytes = 0, total_rx_packets = 0; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC_PS(*rx_ring, i); - staterr = le32_to_cpu(rx_desc->wb.middle.status_error); - buffer_info = &rx_ring->buffer_info[i]; - - while (staterr & E1000_RXD_STAT_DD) { - if (*work_done >= work_to_do) - break; - (*work_done)++; - skb = buffer_info->skb; - dma_rmb(); /* read descriptor and rx_buffer_info after status DD */ - - /* in the packet split case this is header only */ - prefetch(skb->data - NET_IP_ALIGN); - - i++; - if (i == rx_ring->count) - i = 0; - next_rxd = E1000_RX_DESC_PS(*rx_ring, i); - prefetch(next_rxd); - - next_buffer = &rx_ring->buffer_info[i]; - - cleaned = true; - cleaned_count++; - dma_unmap_single(&pdev->dev, buffer_info->dma, - adapter->rx_ps_bsize0, DMA_FROM_DEVICE); - buffer_info->dma = 0; - - /* see !EOP comment in other Rx routine */ - if (!(staterr & E1000_RXD_STAT_EOP)) - adapter->flags2 |= FLAG2_IS_DISCARDING; - - if (adapter->flags2 & FLAG2_IS_DISCARDING) { - e_dbg("Packet Split buffers didn't pick up the full packet\n"); - dev_kfree_skb_irq(skb); - if (staterr & E1000_RXD_STAT_EOP) - adapter->flags2 &= ~FLAG2_IS_DISCARDING; - goto next_desc; - } - - if (unlikely((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) && - !(netdev->features & NETIF_F_RXALL))) { - dev_kfree_skb_irq(skb); - goto next_desc; - } - - length = le16_to_cpu(rx_desc->wb.middle.length0); - - if (!length) { - e_dbg("Last part of the packet spanning multiple descriptors\n"); - dev_kfree_skb_irq(skb); - goto next_desc; - } - - /* Good Receive */ - skb_put(skb, length); - - { - /* this looks ugly, but it seems compiler issues make - * it more efficient than reusing j - */ - int l1 = le16_to_cpu(rx_desc->wb.upper.length[0]); - - /* page alloc/put takes too long and effects small - * packet throughput, so unsplit small packets and - * save the alloc/put only valid in softirq (napi) - * context to call kmap_* - */ - if (l1 && (l1 <= copybreak) && - ((length + l1) <= adapter->rx_ps_bsize0)) { - u8 *vaddr; - - ps_page = &buffer_info->ps_pages[0]; - - /* there is no documentation about how to call - * kmap_atomic, so we can't hold the mapping - * very long - */ - dma_sync_single_for_cpu(&pdev->dev, - ps_page->dma, - PAGE_SIZE, - DMA_FROM_DEVICE); - vaddr = kmap_atomic(ps_page->page); - memcpy(skb_tail_pointer(skb), vaddr, l1); - kunmap_atomic(vaddr); - dma_sync_single_for_device(&pdev->dev, - ps_page->dma, - PAGE_SIZE, - DMA_FROM_DEVICE); - - /* remove the CRC */ - if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) { - if (!(netdev->features & NETIF_F_RXFCS)) - l1 -= 4; - } - - skb_put(skb, l1); - goto copydone; - } /* if */ - } - - for (j = 0; j < PS_PAGE_BUFFERS; j++) { - length = le16_to_cpu(rx_desc->wb.upper.length[j]); - if (!length) - break; - - ps_page = &buffer_info->ps_pages[j]; - dma_unmap_page(&pdev->dev, ps_page->dma, PAGE_SIZE, - DMA_FROM_DEVICE); - ps_page->dma = 0; - skb_fill_page_desc(skb, j, ps_page->page, 0, length); - ps_page->page = NULL; - skb->len += length; - skb->data_len += length; - skb->truesize += PAGE_SIZE; - } - - /* strip the ethernet crc, problem is we're using pages now so - * this whole operation can get a little cpu intensive - */ - if (!(adapter->flags2 & FLAG2_CRC_STRIPPING)) { - if (!(netdev->features & NETIF_F_RXFCS)) - pskb_trim(skb, skb->len - 4); - } - -copydone: - total_rx_bytes += skb->len; - total_rx_packets++; - - e1000_rx_checksum(adapter, staterr, skb); - - e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); - - if (rx_desc->wb.upper.header_status & - cpu_to_le16(E1000_RXDPS_HDRSTAT_HDRSP)) - adapter->rx_hdr_split++; - - e1000_receive_skb(adapter, netdev, skb, staterr, - rx_desc->wb.middle.vlan); - -next_desc: - rx_desc->wb.middle.status_error &= cpu_to_le32(~0xFF); - buffer_info->skb = NULL; - - /* return some buffers to hardware, one at a time is too slow */ - if (cleaned_count >= E1000_RX_BUFFER_WRITE) { - adapter->alloc_rx_buf(rx_ring, cleaned_count, - GFP_ATOMIC); - cleaned_count = 0; - } - - /* use prefetched values */ - rx_desc = next_rxd; - buffer_info = next_buffer; - - staterr = le32_to_cpu(rx_desc->wb.middle.status_error); - } - rx_ring->next_to_clean = i; - - cleaned_count = e1000_desc_unused(rx_ring); - if (cleaned_count) - adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); - - adapter->total_rx_bytes += total_rx_bytes; - adapter->total_rx_packets += total_rx_packets; - return cleaned; -} - -/** - * e1000_consume_page - helper function - **/ -static void e1000_consume_page(struct e1000_buffer *bi, struct sk_buff *skb, - u16 length) -{ - bi->page = NULL; - skb->len += length; - skb->data_len += length; - skb->truesize += PAGE_SIZE; -} - -/** - * e1000_clean_jumbo_rx_irq - Send received data up the network stack; legacy - * @adapter: board private structure - * - * the return value indicates whether actual cleaning was done, there - * is no guarantee that everything was cleaned - **/ -static bool e1000_clean_jumbo_rx_irq(struct e1000_ring *rx_ring, int *work_done, - int work_to_do) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct net_device *netdev = adapter->netdev; - struct pci_dev *pdev = adapter->pdev; - union e1000_rx_desc_extended *rx_desc, *next_rxd; - struct e1000_buffer *buffer_info, *next_buffer; - u32 length, staterr; - unsigned int i; - int cleaned_count = 0; - bool cleaned = false; - unsigned int total_rx_bytes = 0, total_rx_packets = 0; - struct skb_shared_info *shinfo; - - i = rx_ring->next_to_clean; - rx_desc = E1000_RX_DESC_EXT(*rx_ring, i); - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); - buffer_info = &rx_ring->buffer_info[i]; - - while (staterr & E1000_RXD_STAT_DD) { - struct sk_buff *skb; - - if (*work_done >= work_to_do) - break; - (*work_done)++; - dma_rmb(); /* read descriptor and rx_buffer_info after status DD */ - - skb = buffer_info->skb; - buffer_info->skb = NULL; - - ++i; - if (i == rx_ring->count) - i = 0; - next_rxd = E1000_RX_DESC_EXT(*rx_ring, i); - prefetch(next_rxd); - - next_buffer = &rx_ring->buffer_info[i]; - - cleaned = true; - cleaned_count++; - dma_unmap_page(&pdev->dev, buffer_info->dma, PAGE_SIZE, - DMA_FROM_DEVICE); - buffer_info->dma = 0; - - length = le16_to_cpu(rx_desc->wb.upper.length); - - /* errors is only valid for DD + EOP descriptors */ - if (unlikely((staterr & E1000_RXD_STAT_EOP) && - ((staterr & E1000_RXDEXT_ERR_FRAME_ERR_MASK) && - !(netdev->features & NETIF_F_RXALL)))) { - /* recycle both page and skb */ - buffer_info->skb = skb; - /* an error means any chain goes out the window too */ - if (rx_ring->rx_skb_top) - dev_kfree_skb_irq(rx_ring->rx_skb_top); - rx_ring->rx_skb_top = NULL; - goto next_desc; - } -#define rxtop (rx_ring->rx_skb_top) - if (!(staterr & E1000_RXD_STAT_EOP)) { - /* this descriptor is only the beginning (or middle) */ - if (!rxtop) { - /* this is the beginning of a chain */ - rxtop = skb; - skb_fill_page_desc(rxtop, 0, buffer_info->page, - 0, length); - } else { - /* this is the middle of a chain */ - shinfo = skb_shinfo(rxtop); - skb_fill_page_desc(rxtop, shinfo->nr_frags, - buffer_info->page, 0, - length); - /* re-use the skb, only consumed the page */ - buffer_info->skb = skb; - } - e1000_consume_page(buffer_info, rxtop, length); - goto next_desc; - } else { - if (rxtop) { - /* end of the chain */ - shinfo = skb_shinfo(rxtop); - skb_fill_page_desc(rxtop, shinfo->nr_frags, - buffer_info->page, 0, - length); - /* re-use the current skb, we only consumed the - * page - */ - buffer_info->skb = skb; - skb = rxtop; - rxtop = NULL; - e1000_consume_page(buffer_info, skb, length); - } else { - /* no chain, got EOP, this buf is the packet - * copybreak to save the put_page/alloc_page - */ - if (length <= copybreak && - skb_tailroom(skb) >= length) { - u8 *vaddr; - vaddr = kmap_atomic(buffer_info->page); - memcpy(skb_tail_pointer(skb), vaddr, - length); - kunmap_atomic(vaddr); - /* re-use the page, so don't erase - * buffer_info->page - */ - skb_put(skb, length); - } else { - skb_fill_page_desc(skb, 0, - buffer_info->page, 0, - length); - e1000_consume_page(buffer_info, skb, - length); - } - } - } - - /* Receive Checksum Offload */ - e1000_rx_checksum(adapter, staterr, skb); - - e1000_rx_hash(netdev, rx_desc->wb.lower.hi_dword.rss, skb); - - /* probably a little skewed due to removing CRC */ - total_rx_bytes += skb->len; - total_rx_packets++; - - /* eth type trans needs skb->data to point to something */ - if (!pskb_may_pull(skb, ETH_HLEN)) { - e_err("pskb_may_pull failed.\n"); - dev_kfree_skb_irq(skb); - goto next_desc; - } - - e1000_receive_skb(adapter, netdev, skb, staterr, - rx_desc->wb.upper.vlan); - -next_desc: - rx_desc->wb.upper.status_error &= cpu_to_le32(~0xFF); - - /* return some buffers to hardware, one at a time is too slow */ - if (unlikely(cleaned_count >= E1000_RX_BUFFER_WRITE)) { - adapter->alloc_rx_buf(rx_ring, cleaned_count, - GFP_ATOMIC); - cleaned_count = 0; - } - - /* use prefetched values */ - rx_desc = next_rxd; - buffer_info = next_buffer; - - staterr = le32_to_cpu(rx_desc->wb.upper.status_error); - } - rx_ring->next_to_clean = i; - - cleaned_count = e1000_desc_unused(rx_ring); - if (cleaned_count) - adapter->alloc_rx_buf(rx_ring, cleaned_count, GFP_ATOMIC); - - adapter->total_rx_bytes += total_rx_bytes; - adapter->total_rx_packets += total_rx_packets; - return cleaned; -} - -/** - * e1000_clean_rx_ring - Free Rx Buffers per Queue - * @rx_ring: Rx descriptor ring - **/ -static void e1000_clean_rx_ring(struct e1000_ring *rx_ring) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct e1000_buffer *buffer_info; - struct e1000_ps_page *ps_page; - struct pci_dev *pdev = adapter->pdev; - unsigned int i, j; - - /* Free all the Rx ring sk_buffs */ - for (i = 0; i < rx_ring->count; i++) { - buffer_info = &rx_ring->buffer_info[i]; - if (buffer_info->dma) { - if (adapter->clean_rx == e1000_clean_rx_irq) - dma_unmap_single(&pdev->dev, buffer_info->dma, - adapter->rx_buffer_len, - DMA_FROM_DEVICE); - else if (adapter->clean_rx == e1000_clean_jumbo_rx_irq) - dma_unmap_page(&pdev->dev, buffer_info->dma, - PAGE_SIZE, DMA_FROM_DEVICE); - else if (adapter->clean_rx == e1000_clean_rx_irq_ps) - dma_unmap_single(&pdev->dev, buffer_info->dma, - adapter->rx_ps_bsize0, - DMA_FROM_DEVICE); - buffer_info->dma = 0; - } - - if (buffer_info->page) { - put_page(buffer_info->page); - buffer_info->page = NULL; - } - - if (buffer_info->skb) { - dev_kfree_skb(buffer_info->skb); - buffer_info->skb = NULL; - } - - for (j = 0; j < PS_PAGE_BUFFERS; j++) { - ps_page = &buffer_info->ps_pages[j]; - if (!ps_page->page) - break; - dma_unmap_page(&pdev->dev, ps_page->dma, PAGE_SIZE, - DMA_FROM_DEVICE); - ps_page->dma = 0; - put_page(ps_page->page); - ps_page->page = NULL; - } - } - - /* there also may be some cached data from a chained receive */ - if (rx_ring->rx_skb_top) { - dev_kfree_skb(rx_ring->rx_skb_top); - rx_ring->rx_skb_top = NULL; - } - - /* Zero out the descriptor ring */ - memset(rx_ring->desc, 0, rx_ring->size); - - rx_ring->next_to_clean = 0; - rx_ring->next_to_use = 0; - adapter->flags2 &= ~FLAG2_IS_DISCARDING; -} - -static void e1000e_downshift_workaround(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - downshift_task); - - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - - e1000e_gig_downshift_workaround_ich8lan(&adapter->hw); -} - -/** - * e1000_intr_msi - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - **/ -static irqreturn_t e1000_intr_msi(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 icr = er32(ICR); - - /* read ICR disables interrupts using IAM */ - if (icr & E1000_ICR_LSC) { - hw->mac.get_link_status = true; - /* ICH8 workaround-- Call gig speed drop workaround on cable - * disconnect (LSC) before accessing any PHY registers - */ - if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && - (!(er32(STATUS) & E1000_STATUS_LU))) - schedule_work(&adapter->downshift_task); - - /* 80003ES2LAN workaround-- For packet buffer work-around on - * link down event; disable receives here in the ISR and reset - * adapter in watchdog - */ - if (netif_carrier_ok(netdev) && - adapter->flags & FLAG_RX_NEEDS_RESTART) { - /* disable receives */ - u32 rctl = er32(RCTL); - - ew32(RCTL, rctl & ~E1000_RCTL_EN); - adapter->flags |= FLAG_RESTART_NOW; - } - /* guard against interrupt when we're going down */ - if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_timer(&adapter->watchdog_timer, jiffies + 1); - } - - /* Reset on uncorrectable ECC error */ - if ((icr & E1000_ICR_ECCER) && ((hw->mac.type == e1000_pch_lpt) || - (hw->mac.type == e1000_pch_spt))) { - u32 pbeccsts = er32(PBECCSTS); - - adapter->corr_errors += - pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; - adapter->uncorr_errors += - (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> - E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; - - /* Do the reset outside of interrupt context */ - schedule_work(&adapter->reset_task); - - /* return immediately since reset is imminent */ - return IRQ_HANDLED; - } - - if (napi_schedule_prep(&adapter->napi)) { - adapter->total_tx_bytes = 0; - adapter->total_tx_packets = 0; - adapter->total_rx_bytes = 0; - adapter->total_rx_packets = 0; - __napi_schedule(&adapter->napi); - } - - return IRQ_HANDLED; -} - -/** - * e1000_intr - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - **/ -static irqreturn_t e1000_intr(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 rctl, icr = er32(ICR); - - if (!icr || test_bit(__E1000_DOWN, &adapter->state)) - return IRQ_NONE; /* Not our interrupt */ - - /* IMS will not auto-mask if INT_ASSERTED is not set, and if it is - * not set, then the adapter didn't send an interrupt - */ - if (!(icr & E1000_ICR_INT_ASSERTED)) - return IRQ_NONE; - - /* Interrupt Auto-Mask...upon reading ICR, - * interrupts are masked. No need for the - * IMC write - */ - - if (icr & E1000_ICR_LSC) { - hw->mac.get_link_status = true; - /* ICH8 workaround-- Call gig speed drop workaround on cable - * disconnect (LSC) before accessing any PHY registers - */ - if ((adapter->flags & FLAG_LSC_GIG_SPEED_DROP) && - (!(er32(STATUS) & E1000_STATUS_LU))) - schedule_work(&adapter->downshift_task); - - /* 80003ES2LAN workaround-- - * For packet buffer work-around on link down event; - * disable receives here in the ISR and - * reset adapter in watchdog - */ - if (netif_carrier_ok(netdev) && - (adapter->flags & FLAG_RX_NEEDS_RESTART)) { - /* disable receives */ - rctl = er32(RCTL); - ew32(RCTL, rctl & ~E1000_RCTL_EN); - adapter->flags |= FLAG_RESTART_NOW; - } - /* guard against interrupt when we're going down */ - if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_timer(&adapter->watchdog_timer, jiffies + 1); - } - - /* Reset on uncorrectable ECC error */ - if ((icr & E1000_ICR_ECCER) && ((hw->mac.type == e1000_pch_lpt) || - (hw->mac.type == e1000_pch_spt))) { - u32 pbeccsts = er32(PBECCSTS); - - adapter->corr_errors += - pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; - adapter->uncorr_errors += - (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> - E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; - - /* Do the reset outside of interrupt context */ - schedule_work(&adapter->reset_task); - - /* return immediately since reset is imminent */ - return IRQ_HANDLED; - } - - if (napi_schedule_prep(&adapter->napi)) { - adapter->total_tx_bytes = 0; - adapter->total_tx_packets = 0; - adapter->total_rx_bytes = 0; - adapter->total_rx_packets = 0; - __napi_schedule(&adapter->napi); - } - - return IRQ_HANDLED; -} - -static irqreturn_t e1000_msix_other(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 icr = er32(ICR); - - if (!(icr & E1000_ICR_INT_ASSERTED)) { - if (!test_bit(__E1000_DOWN, &adapter->state)) - ew32(IMS, E1000_IMS_OTHER); - return IRQ_NONE; - } - - if (icr & adapter->eiac_mask) - ew32(ICS, (icr & adapter->eiac_mask)); - - if (icr & E1000_ICR_OTHER) { - if (!(icr & E1000_ICR_LSC)) - goto no_link_interrupt; - hw->mac.get_link_status = true; - /* guard against interrupt when we're going down */ - if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_timer(&adapter->watchdog_timer, jiffies + 1); - } - -no_link_interrupt: - if (!test_bit(__E1000_DOWN, &adapter->state)) - ew32(IMS, E1000_IMS_LSC | E1000_IMS_OTHER); - - return IRQ_HANDLED; -} - -static irqreturn_t e1000_intr_msix_tx(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct e1000_ring *tx_ring = adapter->tx_ring; - - adapter->total_tx_bytes = 0; - adapter->total_tx_packets = 0; - - if (!e1000_clean_tx_irq(tx_ring)) - /* Ring was not completely cleaned, so fire another interrupt */ - ew32(ICS, tx_ring->ims_val); - - return IRQ_HANDLED; -} - -static irqreturn_t e1000_intr_msix_rx(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_ring *rx_ring = adapter->rx_ring; - - /* Write the ITR value calculated at the end of the - * previous interrupt. - */ - if (rx_ring->set_itr) { - u32 itr = rx_ring->itr_val ? - 1000000000 / (rx_ring->itr_val * 256) : 0; - - writel(itr, rx_ring->itr_register); - rx_ring->set_itr = 0; - } - - if (napi_schedule_prep(&adapter->napi)) { - adapter->total_rx_bytes = 0; - adapter->total_rx_packets = 0; - __napi_schedule(&adapter->napi); - } - return IRQ_HANDLED; -} - -/** - * e1000_configure_msix - Configure MSI-X hardware - * - * e1000_configure_msix sets up the hardware to properly - * generate MSI-X interrupts. - **/ -static void e1000_configure_msix(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_ring *rx_ring = adapter->rx_ring; - struct e1000_ring *tx_ring = adapter->tx_ring; - int vector = 0; - u32 ctrl_ext, ivar = 0; - - adapter->eiac_mask = 0; - - /* Workaround issue with spurious interrupts on 82574 in MSI-X mode */ - if (hw->mac.type == e1000_82574) { - u32 rfctl = er32(RFCTL); - - rfctl |= E1000_RFCTL_ACK_DIS; - ew32(RFCTL, rfctl); - } - - /* Configure Rx vector */ - rx_ring->ims_val = E1000_IMS_RXQ0; - adapter->eiac_mask |= rx_ring->ims_val; - if (rx_ring->itr_val) - writel(1000000000 / (rx_ring->itr_val * 256), - rx_ring->itr_register); - else - writel(1, rx_ring->itr_register); - ivar = E1000_IVAR_INT_ALLOC_VALID | vector; - - /* Configure Tx vector */ - tx_ring->ims_val = E1000_IMS_TXQ0; - vector++; - if (tx_ring->itr_val) - writel(1000000000 / (tx_ring->itr_val * 256), - tx_ring->itr_register); - else - writel(1, tx_ring->itr_register); - adapter->eiac_mask |= tx_ring->ims_val; - ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 8); - - /* set vector for Other Causes, e.g. link changes */ - vector++; - ivar |= ((E1000_IVAR_INT_ALLOC_VALID | vector) << 16); - if (rx_ring->itr_val) - writel(1000000000 / (rx_ring->itr_val * 256), - hw->hw_addr + E1000_EITR_82574(vector)); - else - writel(1, hw->hw_addr + E1000_EITR_82574(vector)); - - /* Cause Tx interrupts on every write back */ - ivar |= (1 << 31); - - ew32(IVAR, ivar); - - /* enable MSI-X PBA support */ - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_PBA_CLR; - - /* Auto-Mask Other interrupts upon ICR read */ - ew32(IAM, ~E1000_EIAC_MASK_82574 | E1000_IMS_OTHER); - ctrl_ext |= E1000_CTRL_EXT_EIAME; - ew32(CTRL_EXT, ctrl_ext); - e1e_flush(); -} - -void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter) -{ - if (adapter->msix_entries) { - pci_disable_msix(adapter->pdev); - kfree(adapter->msix_entries); - adapter->msix_entries = NULL; - } else if (adapter->flags & FLAG_MSI_ENABLED) { - pci_disable_msi(adapter->pdev); - adapter->flags &= ~FLAG_MSI_ENABLED; - } -} - -/** - * e1000e_set_interrupt_capability - set MSI or MSI-X if supported - * - * Attempt to configure interrupts using the best available - * capabilities of the hardware and kernel. - **/ -void e1000e_set_interrupt_capability(struct e1000_adapter *adapter) -{ - int err; - int i; - - switch (adapter->int_mode) { - case E1000E_INT_MODE_MSIX: - if (adapter->flags & FLAG_HAS_MSIX) { - adapter->num_vectors = 3; /* RxQ0, TxQ0 and other */ - adapter->msix_entries = kcalloc(adapter->num_vectors, - sizeof(struct - msix_entry), - GFP_KERNEL); - if (adapter->msix_entries) { - struct e1000_adapter *a = adapter; - - for (i = 0; i < adapter->num_vectors; i++) - adapter->msix_entries[i].entry = i; - - err = pci_enable_msix_range(a->pdev, - a->msix_entries, - a->num_vectors, - a->num_vectors); - if (err > 0) - return; - } - /* MSI-X failed, so fall through and try MSI */ - e_err("Failed to initialize MSI-X interrupts. Falling back to MSI interrupts.\n"); - e1000e_reset_interrupt_capability(adapter); - } - adapter->int_mode = E1000E_INT_MODE_MSI; - /* Fall through */ - case E1000E_INT_MODE_MSI: - if (!pci_enable_msi(adapter->pdev)) { - adapter->flags |= FLAG_MSI_ENABLED; - } else { - adapter->int_mode = E1000E_INT_MODE_LEGACY; - e_err("Failed to initialize MSI interrupts. Falling back to legacy interrupts.\n"); - } - /* Fall through */ - case E1000E_INT_MODE_LEGACY: - /* Don't do anything; this is the system default */ - break; - } - - /* store the number of vectors being used */ - adapter->num_vectors = 1; -} - -/** - * e1000_request_msix - Initialize MSI-X interrupts - * - * e1000_request_msix allocates MSI-X vectors and requests interrupts from the - * kernel. - **/ -static int e1000_request_msix(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - int err = 0, vector = 0; - - if (strlen(netdev->name) < (IFNAMSIZ - 5)) - snprintf(adapter->rx_ring->name, - sizeof(adapter->rx_ring->name) - 1, - "%.14s-rx-0", netdev->name); - else - memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ); - err = request_irq(adapter->msix_entries[vector].vector, - e1000_intr_msix_rx, 0, adapter->rx_ring->name, - netdev); - if (err) - return err; - adapter->rx_ring->itr_register = adapter->hw.hw_addr + - E1000_EITR_82574(vector); - adapter->rx_ring->itr_val = adapter->itr; - vector++; - - if (strlen(netdev->name) < (IFNAMSIZ - 5)) - snprintf(adapter->tx_ring->name, - sizeof(adapter->tx_ring->name) - 1, - "%.14s-tx-0", netdev->name); - else - memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ); - err = request_irq(adapter->msix_entries[vector].vector, - e1000_intr_msix_tx, 0, adapter->tx_ring->name, - netdev); - if (err) - return err; - adapter->tx_ring->itr_register = adapter->hw.hw_addr + - E1000_EITR_82574(vector); - adapter->tx_ring->itr_val = adapter->itr; - vector++; - - err = request_irq(adapter->msix_entries[vector].vector, - e1000_msix_other, 0, netdev->name, netdev); - if (err) - return err; - - e1000_configure_msix(adapter); - - return 0; -} - -/** - * e1000_request_irq - initialize interrupts - * - * Attempts to configure interrupts using the best available - * capabilities of the hardware and kernel. - **/ -static int e1000_request_irq(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - int err; - - if (adapter->msix_entries) { - err = e1000_request_msix(adapter); - if (!err) - return err; - /* fall back to MSI */ - e1000e_reset_interrupt_capability(adapter); - adapter->int_mode = E1000E_INT_MODE_MSI; - e1000e_set_interrupt_capability(adapter); - } - if (adapter->flags & FLAG_MSI_ENABLED) { - err = request_irq(adapter->pdev->irq, e1000_intr_msi, 0, - netdev->name, netdev); - if (!err) - return err; - - /* fall back to legacy interrupt */ - e1000e_reset_interrupt_capability(adapter); - adapter->int_mode = E1000E_INT_MODE_LEGACY; - } - - err = request_irq(adapter->pdev->irq, e1000_intr, IRQF_SHARED, - netdev->name, netdev); - if (err) - e_err("Unable to allocate interrupt, Error: %d\n", err); - - return err; -} - -static void e1000_free_irq(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - if (adapter->msix_entries) { - int vector = 0; - - free_irq(adapter->msix_entries[vector].vector, netdev); - vector++; - - free_irq(adapter->msix_entries[vector].vector, netdev); - vector++; - - /* Other Causes interrupt vector */ - free_irq(adapter->msix_entries[vector].vector, netdev); - return; - } - - free_irq(adapter->pdev->irq, netdev); -} - -/** - * e1000_irq_disable - Mask off interrupt generation on the NIC - **/ -static void e1000_irq_disable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - ew32(IMC, ~0); - if (adapter->msix_entries) - ew32(EIAC_82574, 0); - e1e_flush(); - - if (adapter->msix_entries) { - int i; - - for (i = 0; i < adapter->num_vectors; i++) - synchronize_irq(adapter->msix_entries[i].vector); - } else { - synchronize_irq(adapter->pdev->irq); - } -} - -/** - * e1000_irq_enable - Enable default interrupt generation settings - **/ -static void e1000_irq_enable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - if (adapter->msix_entries) { - ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574); - ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC); - } else if ((hw->mac.type == e1000_pch_lpt) || - (hw->mac.type == e1000_pch_spt)) { - ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER); - } else { - ew32(IMS, IMS_ENABLE_MASK); - } - e1e_flush(); -} - -/** - * e1000e_get_hw_control - get control of the h/w from f/w - * @adapter: address of board private structure - * - * e1000e_get_hw_control sets {CTRL_EXT|SWSM}:DRV_LOAD bit. - * For ASF and Pass Through versions of f/w this means that - * the driver is loaded. For AMT version (only with 82573) - * of the f/w this means that the network i/f is open. - **/ -void e1000e_get_hw_control(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl_ext; - u32 swsm; - - /* Let firmware know the driver has taken over */ - if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) { - swsm = er32(SWSM); - ew32(SWSM, swsm | E1000_SWSM_DRV_LOAD); - } else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) { - ctrl_ext = er32(CTRL_EXT); - ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_DRV_LOAD); - } -} - -/** - * e1000e_release_hw_control - release control of the h/w to f/w - * @adapter: address of board private structure - * - * e1000e_release_hw_control resets {CTRL_EXT|SWSM}:DRV_LOAD bit. - * For ASF and Pass Through versions of f/w this means that the - * driver is no longer loaded. For AMT version (only with 82573) i - * of the f/w this means that the network i/f is closed. - * - **/ -void e1000e_release_hw_control(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl_ext; - u32 swsm; - - /* Let firmware taken over control of h/w */ - if (adapter->flags & FLAG_HAS_SWSM_ON_LOAD) { - swsm = er32(SWSM); - ew32(SWSM, swsm & ~E1000_SWSM_DRV_LOAD); - } else if (adapter->flags & FLAG_HAS_CTRLEXT_ON_LOAD) { - ctrl_ext = er32(CTRL_EXT); - ew32(CTRL_EXT, ctrl_ext & ~E1000_CTRL_EXT_DRV_LOAD); - } -} - -/** - * e1000_alloc_ring_dma - allocate memory for a ring structure - **/ -static int e1000_alloc_ring_dma(struct e1000_adapter *adapter, - struct e1000_ring *ring) -{ - struct pci_dev *pdev = adapter->pdev; - - ring->desc = dma_zalloc_coherent(&pdev->dev, ring->size, &ring->dma, - GFP_KERNEL); - if (!ring->desc) - return -ENOMEM; - - return 0; -} - -/** - * e1000e_setup_tx_resources - allocate Tx resources (Descriptors) - * @tx_ring: Tx descriptor ring - * - * Return 0 on success, negative on failure - **/ -int e1000e_setup_tx_resources(struct e1000_ring *tx_ring) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - int err = -ENOMEM, size; - - size = sizeof(struct e1000_buffer) * tx_ring->count; - tx_ring->buffer_info = vzalloc(size); - if (!tx_ring->buffer_info) - goto err; - - /* round up to nearest 4K */ - tx_ring->size = tx_ring->count * sizeof(struct e1000_tx_desc); - tx_ring->size = ALIGN(tx_ring->size, 4096); - - err = e1000_alloc_ring_dma(adapter, tx_ring); - if (err) - goto err; - - tx_ring->next_to_use = 0; - tx_ring->next_to_clean = 0; - - return 0; -err: - vfree(tx_ring->buffer_info); - e_err("Unable to allocate memory for the transmit descriptor ring\n"); - return err; -} - -/** - * e1000e_setup_rx_resources - allocate Rx resources (Descriptors) - * @rx_ring: Rx descriptor ring - * - * Returns 0 on success, negative on failure - **/ -int e1000e_setup_rx_resources(struct e1000_ring *rx_ring) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct e1000_buffer *buffer_info; - int i, size, desc_len, err = -ENOMEM; - - size = sizeof(struct e1000_buffer) * rx_ring->count; - rx_ring->buffer_info = vzalloc(size); - if (!rx_ring->buffer_info) - goto err; - - for (i = 0; i < rx_ring->count; i++) { - buffer_info = &rx_ring->buffer_info[i]; - buffer_info->ps_pages = kcalloc(PS_PAGE_BUFFERS, - sizeof(struct e1000_ps_page), - GFP_KERNEL); - if (!buffer_info->ps_pages) - goto err_pages; - } - - desc_len = sizeof(union e1000_rx_desc_packet_split); - - /* Round up to nearest 4K */ - rx_ring->size = rx_ring->count * desc_len; - rx_ring->size = ALIGN(rx_ring->size, 4096); - - err = e1000_alloc_ring_dma(adapter, rx_ring); - if (err) - goto err_pages; - - rx_ring->next_to_clean = 0; - rx_ring->next_to_use = 0; - rx_ring->rx_skb_top = NULL; - - return 0; - -err_pages: - for (i = 0; i < rx_ring->count; i++) { - buffer_info = &rx_ring->buffer_info[i]; - kfree(buffer_info->ps_pages); - } -err: - vfree(rx_ring->buffer_info); - e_err("Unable to allocate memory for the receive descriptor ring\n"); - return err; -} - -/** - * e1000_clean_tx_ring - Free Tx Buffers - * @tx_ring: Tx descriptor ring - **/ -static void e1000_clean_tx_ring(struct e1000_ring *tx_ring) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct e1000_buffer *buffer_info; - unsigned long size; - unsigned int i; - - for (i = 0; i < tx_ring->count; i++) { - buffer_info = &tx_ring->buffer_info[i]; - e1000_put_txbuf(tx_ring, buffer_info); - } - - netdev_reset_queue(adapter->netdev); - size = sizeof(struct e1000_buffer) * tx_ring->count; - memset(tx_ring->buffer_info, 0, size); - - memset(tx_ring->desc, 0, tx_ring->size); - - tx_ring->next_to_use = 0; - tx_ring->next_to_clean = 0; -} - -/** - * e1000e_free_tx_resources - Free Tx Resources per Queue - * @tx_ring: Tx descriptor ring - * - * Free all transmit software resources - **/ -void e1000e_free_tx_resources(struct e1000_ring *tx_ring) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct pci_dev *pdev = adapter->pdev; - - e1000_clean_tx_ring(tx_ring); - - vfree(tx_ring->buffer_info); - tx_ring->buffer_info = NULL; - - dma_free_coherent(&pdev->dev, tx_ring->size, tx_ring->desc, - tx_ring->dma); - tx_ring->desc = NULL; -} - -/** - * e1000e_free_rx_resources - Free Rx Resources - * @rx_ring: Rx descriptor ring - * - * Free all receive software resources - **/ -void e1000e_free_rx_resources(struct e1000_ring *rx_ring) -{ - struct e1000_adapter *adapter = rx_ring->adapter; - struct pci_dev *pdev = adapter->pdev; - int i; - - e1000_clean_rx_ring(rx_ring); - - for (i = 0; i < rx_ring->count; i++) - kfree(rx_ring->buffer_info[i].ps_pages); - - vfree(rx_ring->buffer_info); - rx_ring->buffer_info = NULL; - - dma_free_coherent(&pdev->dev, rx_ring->size, rx_ring->desc, - rx_ring->dma); - rx_ring->desc = NULL; -} - -/** - * e1000_update_itr - update the dynamic ITR value based on statistics - * @adapter: pointer to adapter - * @itr_setting: current adapter->itr - * @packets: the number of packets during this measurement interval - * @bytes: the number of bytes during this measurement interval - * - * Stores a new ITR value based on packets and byte - * counts during the last interrupt. The advantage of per interrupt - * computation is faster updates and more accurate ITR for the current - * traffic pattern. Constants in this function were computed - * based on theoretical maximum wire speed and thresholds were set based - * on testing data as well as attempting to minimize response time - * while increasing bulk throughput. This functionality is controlled - * by the InterruptThrottleRate module parameter. - **/ -static unsigned int e1000_update_itr(u16 itr_setting, int packets, int bytes) -{ - unsigned int retval = itr_setting; - - if (packets == 0) - return itr_setting; - - switch (itr_setting) { - case lowest_latency: - /* handle TSO and jumbo frames */ - if (bytes / packets > 8000) - retval = bulk_latency; - else if ((packets < 5) && (bytes > 512)) - retval = low_latency; - break; - case low_latency: /* 50 usec aka 20000 ints/s */ - if (bytes > 10000) { - /* this if handles the TSO accounting */ - if (bytes / packets > 8000) - retval = bulk_latency; - else if ((packets < 10) || ((bytes / packets) > 1200)) - retval = bulk_latency; - else if ((packets > 35)) - retval = lowest_latency; - } else if (bytes / packets > 2000) { - retval = bulk_latency; - } else if (packets <= 2 && bytes < 512) { - retval = lowest_latency; - } - break; - case bulk_latency: /* 250 usec aka 4000 ints/s */ - if (bytes > 25000) { - if (packets > 35) - retval = low_latency; - } else if (bytes < 6000) { - retval = low_latency; - } - break; - } - - return retval; -} - -static void e1000_set_itr(struct e1000_adapter *adapter) -{ - u16 current_itr; - u32 new_itr = adapter->itr; - - /* for non-gigabit speeds, just fix the interrupt rate at 4000 */ - if (adapter->link_speed != SPEED_1000) { - current_itr = 0; - new_itr = 4000; - goto set_itr_now; - } - - if (adapter->flags2 & FLAG2_DISABLE_AIM) { - new_itr = 0; - goto set_itr_now; - } - - adapter->tx_itr = e1000_update_itr(adapter->tx_itr, - adapter->total_tx_packets, - adapter->total_tx_bytes); - /* conservative mode (itr 3) eliminates the lowest_latency setting */ - if (adapter->itr_setting == 3 && adapter->tx_itr == lowest_latency) - adapter->tx_itr = low_latency; - - adapter->rx_itr = e1000_update_itr(adapter->rx_itr, - adapter->total_rx_packets, - adapter->total_rx_bytes); - /* conservative mode (itr 3) eliminates the lowest_latency setting */ - if (adapter->itr_setting == 3 && adapter->rx_itr == lowest_latency) - adapter->rx_itr = low_latency; - - current_itr = max(adapter->rx_itr, adapter->tx_itr); - - /* counts and packets in update_itr are dependent on these numbers */ - switch (current_itr) { - case lowest_latency: - new_itr = 70000; - break; - case low_latency: - new_itr = 20000; /* aka hwitr = ~200 */ - break; - case bulk_latency: - new_itr = 4000; - break; - default: - break; - } - -set_itr_now: - if (new_itr != adapter->itr) { - /* this attempts to bias the interrupt rate towards Bulk - * by adding intermediate steps when interrupt rate is - * increasing - */ - new_itr = new_itr > adapter->itr ? - min(adapter->itr + (new_itr >> 2), new_itr) : new_itr; - adapter->itr = new_itr; - adapter->rx_ring->itr_val = new_itr; - if (adapter->msix_entries) - adapter->rx_ring->set_itr = 1; - else - e1000e_write_itr(adapter, new_itr); - } -} - -/** - * e1000e_write_itr - write the ITR value to the appropriate registers - * @adapter: address of board private structure - * @itr: new ITR value to program - * - * e1000e_write_itr determines if the adapter is in MSI-X mode - * and, if so, writes the EITR registers with the ITR value. - * Otherwise, it writes the ITR value into the ITR register. - **/ -void e1000e_write_itr(struct e1000_adapter *adapter, u32 itr) -{ - struct e1000_hw *hw = &adapter->hw; - u32 new_itr = itr ? 1000000000 / (itr * 256) : 0; - - if (adapter->msix_entries) { - int vector; - - for (vector = 0; vector < adapter->num_vectors; vector++) - writel(new_itr, hw->hw_addr + E1000_EITR_82574(vector)); - } else { - ew32(ITR, new_itr); - } -} - -/** - * e1000_alloc_queues - Allocate memory for all rings - * @adapter: board private structure to initialize - **/ -static int e1000_alloc_queues(struct e1000_adapter *adapter) -{ - int size = sizeof(struct e1000_ring); - - adapter->tx_ring = kzalloc(size, GFP_KERNEL); - if (!adapter->tx_ring) - goto err; - adapter->tx_ring->count = adapter->tx_ring_count; - adapter->tx_ring->adapter = adapter; - - adapter->rx_ring = kzalloc(size, GFP_KERNEL); - if (!adapter->rx_ring) - goto err; - adapter->rx_ring->count = adapter->rx_ring_count; - adapter->rx_ring->adapter = adapter; - - return 0; -err: - e_err("Unable to allocate memory for queues\n"); - kfree(adapter->rx_ring); - kfree(adapter->tx_ring); - return -ENOMEM; -} - -/** - * e1000e_poll - NAPI Rx polling callback - * @napi: struct associated with this polling callback - * @weight: number of packets driver is allowed to process this poll - **/ -static int e1000e_poll(struct napi_struct *napi, int weight) -{ - struct e1000_adapter *adapter = container_of(napi, struct e1000_adapter, - napi); - struct e1000_hw *hw = &adapter->hw; - struct net_device *poll_dev = adapter->netdev; - int tx_cleaned = 1, work_done = 0; - - adapter = netdev_priv(poll_dev); - - if (!adapter->msix_entries || - (adapter->rx_ring->ims_val & adapter->tx_ring->ims_val)) - tx_cleaned = e1000_clean_tx_irq(adapter->tx_ring); - - adapter->clean_rx(adapter->rx_ring, &work_done, weight); - - if (!tx_cleaned) - work_done = weight; - - /* If weight not fully consumed, exit the polling mode */ - if (work_done < weight) { - if (adapter->itr_setting & 3) - e1000_set_itr(adapter); - napi_complete_done(napi, work_done); - if (!test_bit(__E1000_DOWN, &adapter->state)) { - if (adapter->msix_entries) - ew32(IMS, adapter->rx_ring->ims_val); - else - e1000_irq_enable(adapter); - } - } - - return work_done; -} - -static int e1000_vlan_rx_add_vid(struct net_device *netdev, - __always_unused __be16 proto, u16 vid) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 vfta, index; - - /* don't update vlan cookie if already programmed */ - if ((adapter->hw.mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && - (vid == adapter->mng_vlan_id)) - return 0; - - /* add VID to filter table */ - if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { - index = (vid >> 5) & 0x7F; - vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); - vfta |= (1 << (vid & 0x1F)); - hw->mac.ops.write_vfta(hw, index, vfta); - } - - set_bit(vid, adapter->active_vlans); - - return 0; -} - -static int e1000_vlan_rx_kill_vid(struct net_device *netdev, - __always_unused __be16 proto, u16 vid) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 vfta, index; - - if ((adapter->hw.mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && - (vid == adapter->mng_vlan_id)) { - /* release control to f/w */ - e1000e_release_hw_control(adapter); - return 0; - } - - /* remove VID from filter table */ - if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { - index = (vid >> 5) & 0x7F; - vfta = E1000_READ_REG_ARRAY(hw, E1000_VFTA, index); - vfta &= ~(1 << (vid & 0x1F)); - hw->mac.ops.write_vfta(hw, index, vfta); - } - - clear_bit(vid, adapter->active_vlans); - - return 0; -} - -/** - * e1000e_vlan_filter_disable - helper to disable hw VLAN filtering - * @adapter: board private structure to initialize - **/ -static void e1000e_vlan_filter_disable(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { - /* disable VLAN receive filtering */ - rctl = er32(RCTL); - rctl &= ~(E1000_RCTL_VFE | E1000_RCTL_CFIEN); - ew32(RCTL, rctl); - - if (adapter->mng_vlan_id != (u16)E1000_MNG_VLAN_NONE) { - e1000_vlan_rx_kill_vid(netdev, htons(ETH_P_8021Q), - adapter->mng_vlan_id); - adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; - } - } -} - -/** - * e1000e_vlan_filter_enable - helper to enable HW VLAN filtering - * @adapter: board private structure to initialize - **/ -static void e1000e_vlan_filter_enable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) { - /* enable VLAN receive filtering */ - rctl = er32(RCTL); - rctl |= E1000_RCTL_VFE; - rctl &= ~E1000_RCTL_CFIEN; - ew32(RCTL, rctl); - } -} - -/** - * e1000e_vlan_strip_enable - helper to disable HW VLAN stripping - * @adapter: board private structure to initialize - **/ -static void e1000e_vlan_strip_disable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl; - - /* disable VLAN tag insert/strip */ - ctrl = er32(CTRL); - ctrl &= ~E1000_CTRL_VME; - ew32(CTRL, ctrl); -} - -/** - * e1000e_vlan_strip_enable - helper to enable HW VLAN stripping - * @adapter: board private structure to initialize - **/ -static void e1000e_vlan_strip_enable(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl; - - /* enable VLAN tag insert/strip */ - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_VME; - ew32(CTRL, ctrl); -} - -static void e1000_update_mng_vlan(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - u16 vid = adapter->hw.mng_cookie.vlan_id; - u16 old_vid = adapter->mng_vlan_id; - - if (adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) { - e1000_vlan_rx_add_vid(netdev, htons(ETH_P_8021Q), vid); - adapter->mng_vlan_id = vid; - } - - if ((old_vid != (u16)E1000_MNG_VLAN_NONE) && (vid != old_vid)) - e1000_vlan_rx_kill_vid(netdev, htons(ETH_P_8021Q), old_vid); -} - -static void e1000_restore_vlan(struct e1000_adapter *adapter) -{ - u16 vid; - - e1000_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), 0); - - for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID) - e1000_vlan_rx_add_vid(adapter->netdev, htons(ETH_P_8021Q), vid); -} - -static void e1000_init_manageability_pt(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 manc, manc2h, mdef, i, j; - - if (!(adapter->flags & FLAG_MNG_PT_ENABLED)) - return; - - manc = er32(MANC); - - /* enable receiving management packets to the host. this will probably - * generate destination unreachable messages from the host OS, but - * the packets will be handled on SMBUS - */ - manc |= E1000_MANC_EN_MNG2HOST; - manc2h = er32(MANC2H); - - switch (hw->mac.type) { - default: - manc2h |= (E1000_MANC2H_PORT_623 | E1000_MANC2H_PORT_664); - break; - case e1000_82574: - case e1000_82583: - /* Check if IPMI pass-through decision filter already exists; - * if so, enable it. - */ - for (i = 0, j = 0; i < 8; i++) { - mdef = er32(MDEF(i)); - - /* Ignore filters with anything other than IPMI ports */ - if (mdef & ~(E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664)) - continue; - - /* Enable this decision filter in MANC2H */ - if (mdef) - manc2h |= (1 << i); - - j |= mdef; - } - - if (j == (E1000_MDEF_PORT_623 | E1000_MDEF_PORT_664)) - break; - - /* Create new decision filter in an empty filter */ - for (i = 0, j = 0; i < 8; i++) - if (er32(MDEF(i)) == 0) { - ew32(MDEF(i), (E1000_MDEF_PORT_623 | - E1000_MDEF_PORT_664)); - manc2h |= (1 << 1); - j++; - break; - } - - if (!j) - e_warn("Unable to create IPMI pass-through filter\n"); - break; - } - - ew32(MANC2H, manc2h); - ew32(MANC, manc); -} - -/** - * e1000_configure_tx - Configure Transmit Unit after Reset - * @adapter: board private structure - * - * Configure the Tx unit of the MAC after a reset. - **/ -static void e1000_configure_tx(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_ring *tx_ring = adapter->tx_ring; - u64 tdba; - u32 tdlen, tctl, tarc; - - /* Setup the HW Tx Head and Tail descriptor pointers */ - tdba = tx_ring->dma; - tdlen = tx_ring->count * sizeof(struct e1000_tx_desc); - ew32(TDBAL(0), (tdba & DMA_BIT_MASK(32))); - ew32(TDBAH(0), (tdba >> 32)); - ew32(TDLEN(0), tdlen); - ew32(TDH(0), 0); - ew32(TDT(0), 0); - tx_ring->head = adapter->hw.hw_addr + E1000_TDH(0); - tx_ring->tail = adapter->hw.hw_addr + E1000_TDT(0); - - writel(0, tx_ring->head); - if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_tdt_wa(tx_ring, 0); - else - writel(0, tx_ring->tail); - - /* Set the Tx Interrupt Delay register */ - ew32(TIDV, adapter->tx_int_delay); - /* Tx irq moderation */ - ew32(TADV, adapter->tx_abs_int_delay); - - if (adapter->flags2 & FLAG2_DMA_BURST) { - u32 txdctl = er32(TXDCTL(0)); - - txdctl &= ~(E1000_TXDCTL_PTHRESH | E1000_TXDCTL_HTHRESH | - E1000_TXDCTL_WTHRESH); - /* set up some performance related parameters to encourage the - * hardware to use the bus more efficiently in bursts, depends - * on the tx_int_delay to be enabled, - * wthresh = 1 ==> burst write is disabled to avoid Tx stalls - * hthresh = 1 ==> prefetch when one or more available - * pthresh = 0x1f ==> prefetch if internal cache 31 or less - * BEWARE: this seems to work but should be considered first if - * there are Tx hangs or other Tx related bugs - */ - txdctl |= E1000_TXDCTL_DMA_BURST_ENABLE; - ew32(TXDCTL(0), txdctl); - } - /* erratum work around: set txdctl the same for both queues */ - ew32(TXDCTL(1), er32(TXDCTL(0))); - - /* Program the Transmit Control Register */ - tctl = er32(TCTL); - tctl &= ~E1000_TCTL_CT; - tctl |= E1000_TCTL_PSP | E1000_TCTL_RTLC | - (E1000_COLLISION_THRESHOLD << E1000_CT_SHIFT); - - if (adapter->flags & FLAG_TARC_SPEED_MODE_BIT) { - tarc = er32(TARC(0)); - /* set the speed mode bit, we'll clear it if we're not at - * gigabit link later - */ -#define SPEED_MODE_BIT (1 << 21) - tarc |= SPEED_MODE_BIT; - ew32(TARC(0), tarc); - } - - /* errata: program both queues to unweighted RR */ - if (adapter->flags & FLAG_TARC_SET_BIT_ZERO) { - tarc = er32(TARC(0)); - tarc |= 1; - ew32(TARC(0), tarc); - tarc = er32(TARC(1)); - tarc |= 1; - ew32(TARC(1), tarc); - } - - /* Setup Transmit Descriptor Settings for eop descriptor */ - adapter->txd_cmd = E1000_TXD_CMD_EOP | E1000_TXD_CMD_IFCS; - - /* only set IDE if we are delaying interrupts using the timers */ - if (adapter->tx_int_delay) - adapter->txd_cmd |= E1000_TXD_CMD_IDE; - - /* enable Report Status bit */ - adapter->txd_cmd |= E1000_TXD_CMD_RS; - - ew32(TCTL, tctl); - - hw->mac.ops.config_collision_dist(hw); - - /* SPT Si errata workaround to avoid data corruption */ - if (hw->mac.type == e1000_pch_spt) { - u32 reg_val; - - reg_val = er32(IOSFPC); - reg_val |= E1000_RCTL_RDMTS_HEX; - ew32(IOSFPC, reg_val); - - reg_val = er32(TARC(0)); - reg_val |= E1000_TARC0_CB_MULTIQ_3_REQ; - ew32(TARC(0), reg_val); - } -} - -/** - * e1000_setup_rctl - configure the receive control registers - * @adapter: Board private structure - **/ -#define PAGE_USE_COUNT(S) (((S) >> PAGE_SHIFT) + \ - (((S) & (PAGE_SIZE - 1)) ? 1 : 0)) -static void e1000_setup_rctl(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 rctl, rfctl; - u32 pages = 0; - - /* Workaround Si errata on PCHx - configure jumbo frame flow. - * If jumbo frames not set, program related MAC/PHY registers - * to h/w defaults - */ - if (hw->mac.type >= e1000_pch2lan) { - s32 ret_val; - - if (adapter->netdev->mtu > ETH_DATA_LEN) - ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true); - else - ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false); - - if (ret_val) - e_dbg("failed to enable|disable jumbo frame workaround mode\n"); - } - - /* Program MC offset vector base */ - rctl = er32(RCTL); - rctl &= ~(3 << E1000_RCTL_MO_SHIFT); - rctl |= E1000_RCTL_EN | E1000_RCTL_BAM | - E1000_RCTL_LBM_NO | E1000_RCTL_RDMTS_HALF | - (adapter->hw.mac.mc_filter_type << E1000_RCTL_MO_SHIFT); - - /* Do not Store bad packets */ - rctl &= ~E1000_RCTL_SBP; - - /* Enable Long Packet receive */ - if (adapter->netdev->mtu <= ETH_DATA_LEN) - rctl &= ~E1000_RCTL_LPE; - else - rctl |= E1000_RCTL_LPE; - - /* Some systems expect that the CRC is included in SMBUS traffic. The - * hardware strips the CRC before sending to both SMBUS (BMC) and to - * host memory when this is enabled - */ - if (adapter->flags2 & FLAG2_CRC_STRIPPING) - rctl |= E1000_RCTL_SECRC; - - /* Workaround Si errata on 82577 PHY - configure IPG for jumbos */ - if ((hw->phy.type == e1000_phy_82577) && (rctl & E1000_RCTL_LPE)) { - u16 phy_data; - - e1e_rphy(hw, PHY_REG(770, 26), &phy_data); - phy_data &= 0xfff8; - phy_data |= (1 << 2); - e1e_wphy(hw, PHY_REG(770, 26), phy_data); - - e1e_rphy(hw, 22, &phy_data); - phy_data &= 0x0fff; - phy_data |= (1 << 14); - e1e_wphy(hw, 0x10, 0x2823); - e1e_wphy(hw, 0x11, 0x0003); - e1e_wphy(hw, 22, phy_data); - } - - /* Setup buffer sizes */ - rctl &= ~E1000_RCTL_SZ_4096; - rctl |= E1000_RCTL_BSEX; - switch (adapter->rx_buffer_len) { - case 2048: - default: - rctl |= E1000_RCTL_SZ_2048; - rctl &= ~E1000_RCTL_BSEX; - break; - case 4096: - rctl |= E1000_RCTL_SZ_4096; - break; - case 8192: - rctl |= E1000_RCTL_SZ_8192; - break; - case 16384: - rctl |= E1000_RCTL_SZ_16384; - break; - } - - /* Enable Extended Status in all Receive Descriptors */ - rfctl = er32(RFCTL); - rfctl |= E1000_RFCTL_EXTEN; - ew32(RFCTL, rfctl); - - /* 82571 and greater support packet-split where the protocol - * header is placed in skb->data and the packet data is - * placed in pages hanging off of skb_shinfo(skb)->nr_frags. - * In the case of a non-split, skb->data is linearly filled, - * followed by the page buffers. Therefore, skb->data is - * sized to hold the largest protocol header. - * - * allocations using alloc_page take too long for regular MTU - * so only enable packet split for jumbo frames - * - * Using pages when the page size is greater than 16k wastes - * a lot of memory, since we allocate 3 pages at all times - * per packet. - */ - pages = PAGE_USE_COUNT(adapter->netdev->mtu); - if ((pages <= 3) && (PAGE_SIZE <= 16384) && (rctl & E1000_RCTL_LPE)) - adapter->rx_ps_pages = pages; - else - adapter->rx_ps_pages = 0; - - if (adapter->rx_ps_pages) { - u32 psrctl = 0; - - /* Enable Packet split descriptors */ - rctl |= E1000_RCTL_DTYP_PS; - - psrctl |= adapter->rx_ps_bsize0 >> E1000_PSRCTL_BSIZE0_SHIFT; - - switch (adapter->rx_ps_pages) { - case 3: - psrctl |= PAGE_SIZE << E1000_PSRCTL_BSIZE3_SHIFT; - /* fall-through */ - case 2: - psrctl |= PAGE_SIZE << E1000_PSRCTL_BSIZE2_SHIFT; - /* fall-through */ - case 1: - psrctl |= PAGE_SIZE >> E1000_PSRCTL_BSIZE1_SHIFT; - break; - } - - ew32(PSRCTL, psrctl); - } - - /* This is useful for sniffing bad packets. */ - if (adapter->netdev->features & NETIF_F_RXALL) { - /* UPE and MPE will be handled by normal PROMISC logic - * in e1000e_set_rx_mode - */ - rctl |= (E1000_RCTL_SBP | /* Receive bad packets */ - E1000_RCTL_BAM | /* RX All Bcast Pkts */ - E1000_RCTL_PMCF); /* RX All MAC Ctrl Pkts */ - - rctl &= ~(E1000_RCTL_VFE | /* Disable VLAN filter */ - E1000_RCTL_DPF | /* Allow filtered pause */ - E1000_RCTL_CFIEN); /* Dis VLAN CFIEN Filter */ - /* Do not mess with E1000_CTRL_VME, it affects transmit as well, - * and that breaks VLANs. - */ - } - - ew32(RCTL, rctl); - /* just started the receive unit, no need to restart */ - adapter->flags &= ~FLAG_RESTART_NOW; -} - -/** - * e1000_configure_rx - Configure Receive Unit after Reset - * @adapter: board private structure - * - * Configure the Rx unit of the MAC after a reset. - **/ -static void e1000_configure_rx(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_ring *rx_ring = adapter->rx_ring; - u64 rdba; - u32 rdlen, rctl, rxcsum, ctrl_ext; - - if (adapter->rx_ps_pages) { - /* this is a 32 byte descriptor */ - rdlen = rx_ring->count * - sizeof(union e1000_rx_desc_packet_split); - adapter->clean_rx = e1000_clean_rx_irq_ps; - adapter->alloc_rx_buf = e1000_alloc_rx_buffers_ps; - } else if (adapter->netdev->mtu > ETH_FRAME_LEN + ETH_FCS_LEN) { - rdlen = rx_ring->count * sizeof(union e1000_rx_desc_extended); - adapter->clean_rx = e1000_clean_jumbo_rx_irq; - adapter->alloc_rx_buf = e1000_alloc_jumbo_rx_buffers; - } else { - rdlen = rx_ring->count * sizeof(union e1000_rx_desc_extended); - adapter->clean_rx = e1000_clean_rx_irq; - adapter->alloc_rx_buf = e1000_alloc_rx_buffers; - } - - /* disable receives while setting up the descriptors */ - rctl = er32(RCTL); - if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX)) - ew32(RCTL, rctl & ~E1000_RCTL_EN); - e1e_flush(); - usleep_range(10000, 20000); - - if (adapter->flags2 & FLAG2_DMA_BURST) { - /* set the writeback threshold (only takes effect if the RDTR - * is set). set GRAN=1 and write back up to 0x4 worth, and - * enable prefetching of 0x20 Rx descriptors - * granularity = 01 - * wthresh = 04, - * hthresh = 04, - * pthresh = 0x20 - */ - ew32(RXDCTL(0), E1000_RXDCTL_DMA_BURST_ENABLE); - ew32(RXDCTL(1), E1000_RXDCTL_DMA_BURST_ENABLE); - - /* override the delay timers for enabling bursting, only if - * the value was not set by the user via module options - */ - if (adapter->rx_int_delay == DEFAULT_RDTR) - adapter->rx_int_delay = BURST_RDTR; - if (adapter->rx_abs_int_delay == DEFAULT_RADV) - adapter->rx_abs_int_delay = BURST_RADV; - } - - /* set the Receive Delay Timer Register */ - ew32(RDTR, adapter->rx_int_delay); - - /* irq moderation */ - ew32(RADV, adapter->rx_abs_int_delay); - if ((adapter->itr_setting != 0) && (adapter->itr != 0)) - e1000e_write_itr(adapter, adapter->itr); - - ctrl_ext = er32(CTRL_EXT); - /* Auto-Mask interrupts upon ICR access */ - ctrl_ext |= E1000_CTRL_EXT_IAME; - ew32(IAM, 0xffffffff); - ew32(CTRL_EXT, ctrl_ext); - e1e_flush(); - - /* Setup the HW Rx Head and Tail Descriptor Pointers and - * the Base and Length of the Rx Descriptor Ring - */ - rdba = rx_ring->dma; - ew32(RDBAL(0), (rdba & DMA_BIT_MASK(32))); - ew32(RDBAH(0), (rdba >> 32)); - ew32(RDLEN(0), rdlen); - ew32(RDH(0), 0); - ew32(RDT(0), 0); - rx_ring->head = adapter->hw.hw_addr + E1000_RDH(0); - rx_ring->tail = adapter->hw.hw_addr + E1000_RDT(0); - - writel(0, rx_ring->head); - if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_rdt_wa(rx_ring, 0); - else - writel(0, rx_ring->tail); - - /* Enable Receive Checksum Offload for TCP and UDP */ - rxcsum = er32(RXCSUM); - if (adapter->netdev->features & NETIF_F_RXCSUM) - rxcsum |= E1000_RXCSUM_TUOFL; - else - rxcsum &= ~E1000_RXCSUM_TUOFL; - ew32(RXCSUM, rxcsum); - - /* With jumbo frames, excessive C-state transition latencies result - * in dropped transactions. - */ - if (adapter->netdev->mtu > ETH_DATA_LEN) { - u32 lat = - ((er32(PBA) & E1000_PBA_RXA_MASK) * 1024 - - adapter->max_frame_size) * 8 / 1000; - - if (adapter->flags & FLAG_IS_ICH) { - u32 rxdctl = er32(RXDCTL(0)); - - ew32(RXDCTL(0), rxdctl | 0x3); - } - - pm_qos_update_request(&adapter->pm_qos_req, lat); - } else { - pm_qos_update_request(&adapter->pm_qos_req, - PM_QOS_DEFAULT_VALUE); - } - - /* Enable Receives */ - ew32(RCTL, rctl); -} - -/** - * e1000e_write_mc_addr_list - write multicast addresses to MTA - * @netdev: network interface device structure - * - * Writes multicast address list to the MTA hash table. - * Returns: -ENOMEM on failure - * 0 on no addresses written - * X on writing X addresses to MTA - */ -static int e1000e_write_mc_addr_list(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct netdev_hw_addr *ha; - u8 *mta_list; - int i; - - if (netdev_mc_empty(netdev)) { - /* nothing to program, so clear mc list */ - hw->mac.ops.update_mc_addr_list(hw, NULL, 0); - return 0; - } - - mta_list = kzalloc(netdev_mc_count(netdev) * ETH_ALEN, GFP_ATOMIC); - if (!mta_list) - return -ENOMEM; - - /* update_mc_addr_list expects a packed array of only addresses. */ - i = 0; - netdev_for_each_mc_addr(ha, netdev) - memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN); - - hw->mac.ops.update_mc_addr_list(hw, mta_list, i); - kfree(mta_list); - - return netdev_mc_count(netdev); -} - -/** - * e1000e_write_uc_addr_list - write unicast addresses to RAR table - * @netdev: network interface device structure - * - * Writes unicast address list to the RAR table. - * Returns: -ENOMEM on failure/insufficient address space - * 0 on no addresses written - * X on writing X addresses to the RAR table - **/ -static int e1000e_write_uc_addr_list(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - unsigned int rar_entries; - int count = 0; - - rar_entries = hw->mac.ops.rar_get_count(hw); - - /* save a rar entry for our hardware address */ - rar_entries--; - - /* save a rar entry for the LAA workaround */ - if (adapter->flags & FLAG_RESET_OVERWRITES_LAA) - rar_entries--; - - /* return ENOMEM indicating insufficient memory for addresses */ - if (netdev_uc_count(netdev) > rar_entries) - return -ENOMEM; - - if (!netdev_uc_empty(netdev) && rar_entries) { - struct netdev_hw_addr *ha; - - /* write the addresses in reverse order to avoid write - * combining - */ - netdev_for_each_uc_addr(ha, netdev) { - int rval; - - if (!rar_entries) - break; - rval = hw->mac.ops.rar_set(hw, ha->addr, rar_entries--); - if (rval < 0) - return -ENOMEM; - count++; - } - } - - /* zero out the remaining RAR entries not used above */ - for (; rar_entries > 0; rar_entries--) { - ew32(RAH(rar_entries), 0); - ew32(RAL(rar_entries), 0); - } - e1e_flush(); - - return count; -} - -/** - * e1000e_set_rx_mode - secondary unicast, Multicast and Promiscuous mode set - * @netdev: network interface device structure - * - * The ndo_set_rx_mode entry point is called whenever the unicast or multicast - * address list or the network interface flags are updated. This routine is - * responsible for configuring the hardware for proper unicast, multicast, - * promiscuous mode, and all-multi behavior. - **/ -static void e1000e_set_rx_mode(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 rctl; - - if (pm_runtime_suspended(netdev->dev.parent)) - return; - - /* Check for Promiscuous and All Multicast modes */ - rctl = er32(RCTL); - - /* clear the affected bits */ - rctl &= ~(E1000_RCTL_UPE | E1000_RCTL_MPE); - - if (netdev->flags & IFF_PROMISC) { - rctl |= (E1000_RCTL_UPE | E1000_RCTL_MPE); - /* Do not hardware filter VLANs in promisc mode */ - e1000e_vlan_filter_disable(adapter); - } else { - int count; - - if (netdev->flags & IFF_ALLMULTI) { - rctl |= E1000_RCTL_MPE; - } else { - /* Write addresses to the MTA, if the attempt fails - * then we should just turn on promiscuous mode so - * that we can at least receive multicast traffic - */ - count = e1000e_write_mc_addr_list(netdev); - if (count < 0) - rctl |= E1000_RCTL_MPE; - } - e1000e_vlan_filter_enable(adapter); - /* Write addresses to available RAR registers, if there is not - * sufficient space to store all the addresses then enable - * unicast promiscuous mode - */ - count = e1000e_write_uc_addr_list(netdev); - if (count < 0) - rctl |= E1000_RCTL_UPE; - } - - ew32(RCTL, rctl); - - if (netdev->features & NETIF_F_HW_VLAN_CTAG_RX) - e1000e_vlan_strip_enable(adapter); - else - e1000e_vlan_strip_disable(adapter); -} - -static void e1000e_setup_rss_hash(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 mrqc, rxcsum; - u32 rss_key[10]; - int i; - - netdev_rss_key_fill(rss_key, sizeof(rss_key)); - for (i = 0; i < 10; i++) - ew32(RSSRK(i), rss_key[i]); - - /* Direct all traffic to queue 0 */ - for (i = 0; i < 32; i++) - ew32(RETA(i), 0); - - /* Disable raw packet checksumming so that RSS hash is placed in - * descriptor on writeback. - */ - rxcsum = er32(RXCSUM); - rxcsum |= E1000_RXCSUM_PCSD; - - ew32(RXCSUM, rxcsum); - - mrqc = (E1000_MRQC_RSS_FIELD_IPV4 | - E1000_MRQC_RSS_FIELD_IPV4_TCP | - E1000_MRQC_RSS_FIELD_IPV6 | - E1000_MRQC_RSS_FIELD_IPV6_TCP | - E1000_MRQC_RSS_FIELD_IPV6_TCP_EX); - - ew32(MRQC, mrqc); -} - -/** - * e1000e_get_base_timinca - get default SYSTIM time increment attributes - * @adapter: board private structure - * @timinca: pointer to returned time increment attributes - * - * Get attributes for incrementing the System Time Register SYSTIML/H at - * the default base frequency, and set the cyclecounter shift value. - **/ -s32 e1000e_get_base_timinca(struct e1000_adapter *adapter, u32 *timinca) -{ - struct e1000_hw *hw = &adapter->hw; - u32 incvalue, incperiod, shift; - - /* Make sure clock is enabled on I217/I218/I219 before checking - * the frequency - */ - if (((hw->mac.type == e1000_pch_lpt) || - (hw->mac.type == e1000_pch_spt)) && - !(er32(TSYNCTXCTL) & E1000_TSYNCTXCTL_ENABLED) && - !(er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_ENABLED)) { - u32 fextnvm7 = er32(FEXTNVM7); - - if (!(fextnvm7 & (1 << 0))) { - ew32(FEXTNVM7, fextnvm7 | (1 << 0)); - e1e_flush(); - } - } - - switch (hw->mac.type) { - case e1000_pch2lan: - /* Stable 96MHz frequency */ - incperiod = INCPERIOD_96MHz; - incvalue = INCVALUE_96MHz; - shift = INCVALUE_SHIFT_96MHz; - adapter->cc.shift = shift + INCPERIOD_SHIFT_96MHz; - break; - case e1000_pch_lpt: - if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI) { - /* Stable 96MHz frequency */ - incperiod = INCPERIOD_96MHz; - incvalue = INCVALUE_96MHz; - shift = INCVALUE_SHIFT_96MHz; - adapter->cc.shift = shift + INCPERIOD_SHIFT_96MHz; - } else { - /* Stable 25MHz frequency */ - incperiod = INCPERIOD_25MHz; - incvalue = INCVALUE_25MHz; - shift = INCVALUE_SHIFT_25MHz; - adapter->cc.shift = shift; - } - break; - case e1000_pch_spt: - if (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI) { - /* Stable 24MHz frequency */ - incperiod = INCPERIOD_24MHz; - incvalue = INCVALUE_24MHz; - shift = INCVALUE_SHIFT_24MHz; - adapter->cc.shift = shift; - break; - } - return -EINVAL; - case e1000_82574: - case e1000_82583: - /* Stable 25MHz frequency */ - incperiod = INCPERIOD_25MHz; - incvalue = INCVALUE_25MHz; - shift = INCVALUE_SHIFT_25MHz; - adapter->cc.shift = shift; - break; - default: - return -EINVAL; - } - - *timinca = ((incperiod << E1000_TIMINCA_INCPERIOD_SHIFT) | - ((incvalue << shift) & E1000_TIMINCA_INCVALUE_MASK)); - - return 0; -} - -/** - * e1000e_config_hwtstamp - configure the hwtstamp registers and enable/disable - * @adapter: board private structure - * - * Outgoing time stamping can be enabled and disabled. Play nice and - * disable it when requested, although it shouldn't cause any overhead - * when no packet needs it. At most one packet in the queue may be - * marked for time stamping, otherwise it would be impossible to tell - * for sure to which packet the hardware time stamp belongs. - * - * Incoming time stamping has to be configured via the hardware filters. - * Not all combinations are supported, in particular event type has to be - * specified. Matching the kind of event packet is not supported, with the - * exception of "all V2 events regardless of level 2 or 4". - **/ -static int e1000e_config_hwtstamp(struct e1000_adapter *adapter, - struct hwtstamp_config *config) -{ - struct e1000_hw *hw = &adapter->hw; - u32 tsync_tx_ctl = E1000_TSYNCTXCTL_ENABLED; - u32 tsync_rx_ctl = E1000_TSYNCRXCTL_ENABLED; - u32 rxmtrl = 0; - u16 rxudp = 0; - bool is_l4 = false; - bool is_l2 = false; - u32 regval; - s32 ret_val; - - if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP)) - return -EINVAL; - - /* flags reserved for future extensions - must be zero */ - if (config->flags) - return -EINVAL; - - switch (config->tx_type) { - case HWTSTAMP_TX_OFF: - tsync_tx_ctl = 0; - break; - case HWTSTAMP_TX_ON: - break; - default: - return -ERANGE; - } - - switch (config->rx_filter) { - case HWTSTAMP_FILTER_NONE: - tsync_rx_ctl = 0; - break; - case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; - rxmtrl = E1000_RXMTRL_PTP_V1_SYNC_MESSAGE; - is_l4 = true; - break; - case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L4_V1; - rxmtrl = E1000_RXMTRL_PTP_V1_DELAY_REQ_MESSAGE; - is_l4 = true; - break; - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - /* Also time stamps V2 L2 Path Delay Request/Response */ - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_V2; - rxmtrl = E1000_RXMTRL_PTP_V2_SYNC_MESSAGE; - is_l2 = true; - break; - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - /* Also time stamps V2 L2 Path Delay Request/Response. */ - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_V2; - rxmtrl = E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE; - is_l2 = true; - break; - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - /* Hardware cannot filter just V2 L4 Sync messages; - * fall-through to V2 (both L2 and L4) Sync. - */ - case HWTSTAMP_FILTER_PTP_V2_SYNC: - /* Also time stamps V2 Path Delay Request/Response. */ - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; - rxmtrl = E1000_RXMTRL_PTP_V2_SYNC_MESSAGE; - is_l2 = true; - is_l4 = true; - break; - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - /* Hardware cannot filter just V2 L4 Delay Request messages; - * fall-through to V2 (both L2 and L4) Delay Request. - */ - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - /* Also time stamps V2 Path Delay Request/Response. */ - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_L2_L4_V2; - rxmtrl = E1000_RXMTRL_PTP_V2_DELAY_REQ_MESSAGE; - is_l2 = true; - is_l4 = true; - break; - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - /* Hardware cannot filter just V2 L4 or L2 Event messages; - * fall-through to all V2 (both L2 and L4) Events. - */ - case HWTSTAMP_FILTER_PTP_V2_EVENT: - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_EVENT_V2; - config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; - is_l2 = true; - is_l4 = true; - break; - case HWTSTAMP_FILTER_PTP_V1_L4_EVENT: - /* For V1, the hardware can only filter Sync messages or - * Delay Request messages but not both so fall-through to - * time stamp all packets. - */ - case HWTSTAMP_FILTER_ALL: - is_l2 = true; - is_l4 = true; - tsync_rx_ctl |= E1000_TSYNCRXCTL_TYPE_ALL; - config->rx_filter = HWTSTAMP_FILTER_ALL; - break; - default: - return -ERANGE; - } - - adapter->hwtstamp_config = *config; - - /* enable/disable Tx h/w time stamping */ - regval = er32(TSYNCTXCTL); - regval &= ~E1000_TSYNCTXCTL_ENABLED; - regval |= tsync_tx_ctl; - ew32(TSYNCTXCTL, regval); - if ((er32(TSYNCTXCTL) & E1000_TSYNCTXCTL_ENABLED) != - (regval & E1000_TSYNCTXCTL_ENABLED)) { - e_err("Timesync Tx Control register not set as expected\n"); - return -EAGAIN; - } - - /* enable/disable Rx h/w time stamping */ - regval = er32(TSYNCRXCTL); - regval &= ~(E1000_TSYNCRXCTL_ENABLED | E1000_TSYNCRXCTL_TYPE_MASK); - regval |= tsync_rx_ctl; - ew32(TSYNCRXCTL, regval); - if ((er32(TSYNCRXCTL) & (E1000_TSYNCRXCTL_ENABLED | - E1000_TSYNCRXCTL_TYPE_MASK)) != - (regval & (E1000_TSYNCRXCTL_ENABLED | - E1000_TSYNCRXCTL_TYPE_MASK))) { - e_err("Timesync Rx Control register not set as expected\n"); - return -EAGAIN; - } - - /* L2: define ethertype filter for time stamped packets */ - if (is_l2) - rxmtrl |= ETH_P_1588; - - /* define which PTP packets get time stamped */ - ew32(RXMTRL, rxmtrl); - - /* Filter by destination port */ - if (is_l4) { - rxudp = PTP_EV_PORT; - cpu_to_be16s(&rxudp); - } - ew32(RXUDP, rxudp); - - e1e_flush(); - - /* Clear TSYNCRXCTL_VALID & TSYNCTXCTL_VALID bit */ - er32(RXSTMPH); - er32(TXSTMPH); - - /* Get and set the System Time Register SYSTIM base frequency */ - ret_val = e1000e_get_base_timinca(adapter, ®val); - if (ret_val) - return ret_val; - ew32(TIMINCA, regval); - - /* reset the ns time counter */ - timecounter_init(&adapter->tc, &adapter->cc, - ktime_to_ns(ktime_get_real())); - - return 0; -} - -/** - * e1000_configure - configure the hardware for Rx and Tx - * @adapter: private board structure - **/ -static void e1000_configure(struct e1000_adapter *adapter) -{ - struct e1000_ring *rx_ring = adapter->rx_ring; - - e1000e_set_rx_mode(adapter->netdev); - - e1000_restore_vlan(adapter); - e1000_init_manageability_pt(adapter); - - e1000_configure_tx(adapter); - - if (adapter->netdev->features & NETIF_F_RXHASH) - e1000e_setup_rss_hash(adapter); - e1000_setup_rctl(adapter); - e1000_configure_rx(adapter); - adapter->alloc_rx_buf(rx_ring, e1000_desc_unused(rx_ring), GFP_KERNEL); -} - -/** - * e1000e_power_up_phy - restore link in case the phy was powered down - * @adapter: address of board private structure - * - * The phy may be powered down to save power and turn off link when the - * driver is unloaded and wake on lan is not enabled (among others) - * *** this routine MUST be followed by a call to e1000e_reset *** - **/ -void e1000e_power_up_phy(struct e1000_adapter *adapter) -{ - if (adapter->hw.phy.ops.power_up) - adapter->hw.phy.ops.power_up(&adapter->hw); - - adapter->hw.mac.ops.setup_link(&adapter->hw); -} - -/** - * e1000_power_down_phy - Power down the PHY - * - * Power down the PHY so no link is implied when interface is down. - * The PHY cannot be powered down if management or WoL is active. - */ -static void e1000_power_down_phy(struct e1000_adapter *adapter) -{ - if (adapter->hw.phy.ops.power_down) - adapter->hw.phy.ops.power_down(&adapter->hw); -} - -/** - * e1000_flush_tx_ring - remove all descriptors from the tx_ring - * - * We want to clear all pending descriptors from the TX ring. - * zeroing happens when the HW reads the regs. We assign the ring itself as - * the data of the next descriptor. We don't care about the data we are about - * to reset the HW. - */ -static void e1000_flush_tx_ring(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_ring *tx_ring = adapter->tx_ring; - struct e1000_tx_desc *tx_desc = NULL; - u32 tdt, tctl, txd_lower = E1000_TXD_CMD_IFCS; - u16 size = 512; - - tctl = er32(TCTL); - ew32(TCTL, tctl | E1000_TCTL_EN); - tdt = er32(TDT(0)); - BUG_ON(tdt != tx_ring->next_to_use); - tx_desc = E1000_TX_DESC(*tx_ring, tx_ring->next_to_use); - tx_desc->buffer_addr = tx_ring->dma; - - tx_desc->lower.data = cpu_to_le32(txd_lower | size); - tx_desc->upper.data = 0; - /* flush descriptors to memory before notifying the HW */ - wmb(); - tx_ring->next_to_use++; - if (tx_ring->next_to_use == tx_ring->count) - tx_ring->next_to_use = 0; - ew32(TDT(0), tx_ring->next_to_use); - mmiowb(); - usleep_range(200, 250); -} - -/** - * e1000_flush_rx_ring - remove all descriptors from the rx_ring - * - * Mark all descriptors in the RX ring as consumed and disable the rx ring - */ -static void e1000_flush_rx_ring(struct e1000_adapter *adapter) -{ - u32 rctl, rxdctl; - struct e1000_hw *hw = &adapter->hw; - - rctl = er32(RCTL); - ew32(RCTL, rctl & ~E1000_RCTL_EN); - e1e_flush(); - usleep_range(100, 150); - - rxdctl = er32(RXDCTL(0)); - /* zero the lower 14 bits (prefetch and host thresholds) */ - rxdctl &= 0xffffc000; - - /* update thresholds: prefetch threshold to 31, host threshold to 1 - * and make sure the granularity is "descriptors" and not "cache lines" - */ - rxdctl |= (0x1F | (1 << 8) | E1000_RXDCTL_THRESH_UNIT_DESC); - - ew32(RXDCTL(0), rxdctl); - /* momentarily enable the RX ring for the changes to take effect */ - ew32(RCTL, rctl | E1000_RCTL_EN); - e1e_flush(); - usleep_range(100, 150); - ew32(RCTL, rctl & ~E1000_RCTL_EN); -} - -/** - * e1000_flush_desc_rings - remove all descriptors from the descriptor rings - * - * In i219, the descriptor rings must be emptied before resetting the HW - * or before changing the device state to D3 during runtime (runtime PM). - * - * Failure to do this will cause the HW to enter a unit hang state which can - * only be released by PCI reset on the device - * - */ - -static void e1000_flush_desc_rings(struct e1000_adapter *adapter) -{ - u16 hang_state; - u32 fext_nvm11, tdlen; - struct e1000_hw *hw = &adapter->hw; - - /* First, disable MULR fix in FEXTNVM11 */ - fext_nvm11 = er32(FEXTNVM11); - fext_nvm11 |= E1000_FEXTNVM11_DISABLE_MULR_FIX; - ew32(FEXTNVM11, fext_nvm11); - /* do nothing if we're not in faulty state, or if the queue is empty */ - tdlen = er32(TDLEN(0)); - pci_read_config_word(adapter->pdev, PCICFG_DESC_RING_STATUS, - &hang_state); - if (!(hang_state & FLUSH_DESC_REQUIRED) || !tdlen) - return; - e1000_flush_tx_ring(adapter); - /* recheck, maybe the fault is caused by the rx ring */ - pci_read_config_word(adapter->pdev, PCICFG_DESC_RING_STATUS, - &hang_state); - if (hang_state & FLUSH_DESC_REQUIRED) - e1000_flush_rx_ring(adapter); -} - -/** - * e1000e_reset - bring the hardware into a known good state - * - * This function boots the hardware and enables some settings that - * require a configuration cycle of the hardware - those cannot be - * set/changed during runtime. After reset the device needs to be - * properly configured for Rx, Tx etc. - */ -void e1000e_reset(struct e1000_adapter *adapter) -{ - struct e1000_mac_info *mac = &adapter->hw.mac; - struct e1000_fc_info *fc = &adapter->hw.fc; - struct e1000_hw *hw = &adapter->hw; - u32 tx_space, min_tx_space, min_rx_space; - u32 pba = adapter->pba; - u16 hwm; - - /* reset Packet Buffer Allocation to default */ - ew32(PBA, pba); - - if (adapter->max_frame_size > (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)) { - /* To maintain wire speed transmits, the Tx FIFO should be - * large enough to accommodate two full transmit packets, - * rounded up to the next 1KB and expressed in KB. Likewise, - * the Rx FIFO should be large enough to accommodate at least - * one full receive packet and is similarly rounded up and - * expressed in KB. - */ - pba = er32(PBA); - /* upper 16 bits has Tx packet buffer allocation size in KB */ - tx_space = pba >> 16; - /* lower 16 bits has Rx packet buffer allocation size in KB */ - pba &= 0xffff; - /* the Tx fifo also stores 16 bytes of information about the Tx - * but don't include ethernet FCS because hardware appends it - */ - min_tx_space = (adapter->max_frame_size + - sizeof(struct e1000_tx_desc) - ETH_FCS_LEN) * 2; - min_tx_space = ALIGN(min_tx_space, 1024); - min_tx_space >>= 10; - /* software strips receive CRC, so leave room for it */ - min_rx_space = adapter->max_frame_size; - min_rx_space = ALIGN(min_rx_space, 1024); - min_rx_space >>= 10; - - /* If current Tx allocation is less than the min Tx FIFO size, - * and the min Tx FIFO size is less than the current Rx FIFO - * allocation, take space away from current Rx allocation - */ - if ((tx_space < min_tx_space) && - ((min_tx_space - tx_space) < pba)) { - pba -= min_tx_space - tx_space; - - /* if short on Rx space, Rx wins and must trump Tx - * adjustment - */ - if (pba < min_rx_space) - pba = min_rx_space; - } - - ew32(PBA, pba); - } - - /* flow control settings - * - * The high water mark must be low enough to fit one full frame - * (or the size used for early receive) above it in the Rx FIFO. - * Set it to the lower of: - * - 90% of the Rx FIFO size, and - * - the full Rx FIFO size minus one full frame - */ - if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME) - fc->pause_time = 0xFFFF; - else - fc->pause_time = E1000_FC_PAUSE_TIME; - fc->send_xon = true; - fc->current_mode = fc->requested_mode; - - switch (hw->mac.type) { - case e1000_ich9lan: - case e1000_ich10lan: - if (adapter->netdev->mtu > ETH_DATA_LEN) { - pba = 14; - ew32(PBA, pba); - fc->high_water = 0x2800; - fc->low_water = fc->high_water - 8; - break; - } - /* fall-through */ - default: - hwm = min(((pba << 10) * 9 / 10), - ((pba << 10) - adapter->max_frame_size)); - - fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */ - fc->low_water = fc->high_water - 8; - break; - case e1000_pchlan: - /* Workaround PCH LOM adapter hangs with certain network - * loads. If hangs persist, try disabling Tx flow control. - */ - if (adapter->netdev->mtu > ETH_DATA_LEN) { - fc->high_water = 0x3500; - fc->low_water = 0x1500; - } else { - fc->high_water = 0x5000; - fc->low_water = 0x3000; - } - fc->refresh_time = 0x1000; - break; - case e1000_pch2lan: - case e1000_pch_lpt: - case e1000_pch_spt: - fc->refresh_time = 0x0400; - - if (adapter->netdev->mtu <= ETH_DATA_LEN) { - fc->high_water = 0x05C20; - fc->low_water = 0x05048; - fc->pause_time = 0x0650; - break; - } - - pba = 14; - ew32(PBA, pba); - fc->high_water = ((pba << 10) * 9 / 10) & E1000_FCRTH_RTH; - fc->low_water = ((pba << 10) * 8 / 10) & E1000_FCRTL_RTL; - break; - } - - /* Alignment of Tx data is on an arbitrary byte boundary with the - * maximum size per Tx descriptor limited only to the transmit - * allocation of the packet buffer minus 96 bytes with an upper - * limit of 24KB due to receive synchronization limitations. - */ - adapter->tx_fifo_limit = min_t(u32, ((er32(PBA) >> 16) << 10) - 96, - 24 << 10); - - /* Disable Adaptive Interrupt Moderation if 2 full packets cannot - * fit in receive buffer. - */ - if (adapter->itr_setting & 0x3) { - if ((adapter->max_frame_size * 2) > (pba << 10)) { - if (!(adapter->flags2 & FLAG2_DISABLE_AIM)) { - dev_info(&adapter->pdev->dev, - "Interrupt Throttle Rate off\n"); - adapter->flags2 |= FLAG2_DISABLE_AIM; - e1000e_write_itr(adapter, 0); - } - } else if (adapter->flags2 & FLAG2_DISABLE_AIM) { - dev_info(&adapter->pdev->dev, - "Interrupt Throttle Rate on\n"); - adapter->flags2 &= ~FLAG2_DISABLE_AIM; - adapter->itr = 20000; - e1000e_write_itr(adapter, adapter->itr); - } - } - - if (hw->mac.type == e1000_pch_spt) - e1000_flush_desc_rings(adapter); - /* Allow time for pending master requests to run */ - mac->ops.reset_hw(hw); - - /* For parts with AMT enabled, let the firmware know - * that the network interface is in control - */ - if (adapter->flags & FLAG_HAS_AMT) - e1000e_get_hw_control(adapter); - - ew32(WUC, 0); - - if (mac->ops.init_hw(hw)) - e_err("Hardware Error\n"); - - e1000_update_mng_vlan(adapter); - - /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ - ew32(VET, ETH_P_8021Q); - - e1000e_reset_adaptive(hw); - - /* initialize systim and reset the ns time counter */ - e1000e_config_hwtstamp(adapter, &adapter->hwtstamp_config); - - /* Set EEE advertisement as appropriate */ - if (adapter->flags2 & FLAG2_HAS_EEE) { - s32 ret_val; - u16 adv_addr; - - switch (hw->phy.type) { - case e1000_phy_82579: - adv_addr = I82579_EEE_ADVERTISEMENT; - break; - case e1000_phy_i217: - adv_addr = I217_EEE_ADVERTISEMENT; - break; - default: - dev_err(&adapter->pdev->dev, - "Invalid PHY type setting EEE advertisement\n"); - return; - } - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) { - dev_err(&adapter->pdev->dev, - "EEE advertisement - unable to acquire PHY\n"); - return; - } - - e1000_write_emi_reg_locked(hw, adv_addr, - hw->dev_spec.ich8lan.eee_disable ? - 0 : adapter->eee_advert); - - hw->phy.ops.release(hw); - } - - if (!netif_running(adapter->netdev) && - !test_bit(__E1000_TESTING, &adapter->state)) - e1000_power_down_phy(adapter); - - e1000_get_phy_info(hw); - - if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && - !(adapter->flags & FLAG_SMART_POWER_DOWN)) { - u16 phy_data = 0; - /* speed up time to link by disabling smart power down, ignore - * the return value of this function because there is nothing - * different we would do if it failed - */ - e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &phy_data); - phy_data &= ~IGP02E1000_PM_SPD; - e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, phy_data); - } - if (hw->mac.type == e1000_pch_spt && adapter->int_mode == 0) { - u32 reg; - - /* Fextnvm7 @ 0xe4[2] = 1 */ - reg = er32(FEXTNVM7); - reg |= E1000_FEXTNVM7_SIDE_CLK_UNGATE; - ew32(FEXTNVM7, reg); - /* Fextnvm9 @ 0x5bb4[13:12] = 11 */ - reg = er32(FEXTNVM9); - reg |= E1000_FEXTNVM9_IOSFSB_CLKGATE_DIS | - E1000_FEXTNVM9_IOSFSB_CLKREQ_DIS; - ew32(FEXTNVM9, reg); - } - -} - -int e1000e_up(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - /* hardware has been reset, we need to reload some things */ - e1000_configure(adapter); - - clear_bit(__E1000_DOWN, &adapter->state); - - if (adapter->msix_entries) - e1000_configure_msix(adapter); - e1000_irq_enable(adapter); - - netif_start_queue(adapter->netdev); - - /* fire a link change interrupt to start the watchdog */ - if (adapter->msix_entries) - ew32(ICS, E1000_ICS_LSC | E1000_ICR_OTHER); - else - ew32(ICS, E1000_ICS_LSC); - - return 0; -} - -static void e1000e_flush_descriptors(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - if (!(adapter->flags2 & FLAG2_DMA_BURST)) - return; - - /* flush pending descriptor writebacks to memory */ - ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); - ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD); - - /* execute the writes immediately */ - e1e_flush(); - - /* due to rare timing issues, write to TIDV/RDTR again to ensure the - * write is successful - */ - ew32(TIDV, adapter->tx_int_delay | E1000_TIDV_FPD); - ew32(RDTR, adapter->rx_int_delay | E1000_RDTR_FPD); - - /* execute the writes immediately */ - e1e_flush(); -} - -static void e1000e_update_stats(struct e1000_adapter *adapter); - -/** - * e1000e_down - quiesce the device and optionally reset the hardware - * @adapter: board private structure - * @reset: boolean flag to reset the hardware or not - */ -void e1000e_down(struct e1000_adapter *adapter, bool reset) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - u32 tctl, rctl; - - /* signal that we're down so the interrupt handler does not - * reschedule our watchdog timer - */ - set_bit(__E1000_DOWN, &adapter->state); - - netif_carrier_off(netdev); - - /* disable receives in the hardware */ - rctl = er32(RCTL); - if (!(adapter->flags2 & FLAG2_NO_DISABLE_RX)) - ew32(RCTL, rctl & ~E1000_RCTL_EN); - /* flush and sleep below */ - - netif_stop_queue(netdev); - - /* disable transmits in the hardware */ - tctl = er32(TCTL); - tctl &= ~E1000_TCTL_EN; - ew32(TCTL, tctl); - - /* flush both disables and wait for them to finish */ - e1e_flush(); - usleep_range(10000, 20000); - - e1000_irq_disable(adapter); - - napi_synchronize(&adapter->napi); - - del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->phy_info_timer); - - spin_lock(&adapter->stats64_lock); - e1000e_update_stats(adapter); - spin_unlock(&adapter->stats64_lock); - - e1000e_flush_descriptors(adapter); - - adapter->link_speed = 0; - adapter->link_duplex = 0; - - /* Disable Si errata workaround on PCHx for jumbo frame flow */ - if ((hw->mac.type >= e1000_pch2lan) && - (adapter->netdev->mtu > ETH_DATA_LEN) && - e1000_lv_jumbo_workaround_ich8lan(hw, false)) - e_dbg("failed to disable jumbo frame workaround mode\n"); - - if (!pci_channel_offline(adapter->pdev)) { - if (reset) - e1000e_reset(adapter); - else if (hw->mac.type == e1000_pch_spt) - e1000_flush_desc_rings(adapter); - } - e1000_clean_tx_ring(adapter->tx_ring); - e1000_clean_rx_ring(adapter->rx_ring); -} - -void e1000e_reinit_locked(struct e1000_adapter *adapter) -{ - might_sleep(); - while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - usleep_range(1000, 2000); - e1000e_down(adapter, true); - e1000e_up(adapter); - clear_bit(__E1000_RESETTING, &adapter->state); -} - -/** - * e1000e_cyclecounter_read - read raw cycle counter (used by time counter) - * @cc: cyclecounter structure - **/ -static cycle_t e1000e_cyclecounter_read(const struct cyclecounter *cc) -{ - struct e1000_adapter *adapter = container_of(cc, struct e1000_adapter, - cc); - struct e1000_hw *hw = &adapter->hw; - u32 systimel_1, systimel_2, systimeh; - cycle_t systim, systim_next; - /* SYSTIMH latching upon SYSTIML read does not work well. - * This means that if SYSTIML overflows after we read it but before - * we read SYSTIMH, the value of SYSTIMH has been incremented and we - * will experience a huge non linear increment in the systime value - * to fix that we test for overflow and if true, we re-read systime. - */ - systimel_1 = er32(SYSTIML); - systimeh = er32(SYSTIMH); - systimel_2 = er32(SYSTIML); - /* Check for overflow. If there was no overflow, use the values */ - if (systimel_1 < systimel_2) { - systim = (cycle_t)systimel_1; - systim |= (cycle_t)systimeh << 32; - } else { - /* There was an overflow, read again SYSTIMH, and use - * systimel_2 - */ - systimeh = er32(SYSTIMH); - systim = (cycle_t)systimel_2; - systim |= (cycle_t)systimeh << 32; - } - - if ((hw->mac.type == e1000_82574) || (hw->mac.type == e1000_82583)) { - u64 incvalue, time_delta, rem, temp; - int i; - - /* errata for 82574/82583 possible bad bits read from SYSTIMH/L - * check to see that the time is incrementing at a reasonable - * rate and is a multiple of incvalue - */ - incvalue = er32(TIMINCA) & E1000_TIMINCA_INCVALUE_MASK; - for (i = 0; i < E1000_MAX_82574_SYSTIM_REREADS; i++) { - /* latch SYSTIMH on read of SYSTIML */ - systim_next = (cycle_t)er32(SYSTIML); - systim_next |= (cycle_t)er32(SYSTIMH) << 32; - - time_delta = systim_next - systim; - temp = time_delta; - rem = do_div(temp, incvalue); - - systim = systim_next; - - if ((time_delta < E1000_82574_SYSTIM_EPSILON) && - (rem == 0)) - break; - } - } - return systim; -} - -/** - * e1000_sw_init - Initialize general software structures (struct e1000_adapter) - * @adapter: board private structure to initialize - * - * e1000_sw_init initializes the Adapter private data structure. - * Fields are initialized based on PCI device information and - * OS network device settings (MTU size). - **/ -static int e1000_sw_init(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - - adapter->rx_buffer_len = VLAN_ETH_FRAME_LEN + ETH_FCS_LEN; - adapter->rx_ps_bsize0 = 128; - adapter->max_frame_size = netdev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; - adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN; - adapter->tx_ring_count = E1000_DEFAULT_TXD; - adapter->rx_ring_count = E1000_DEFAULT_RXD; - - spin_lock_init(&adapter->stats64_lock); - - e1000e_set_interrupt_capability(adapter); - - if (e1000_alloc_queues(adapter)) - return -ENOMEM; - - /* Setup hardware time stamping cyclecounter */ - if (adapter->flags & FLAG_HAS_HW_TIMESTAMP) { - adapter->cc.read = e1000e_cyclecounter_read; - adapter->cc.mask = CYCLECOUNTER_MASK(64); - adapter->cc.mult = 1; - /* cc.shift set in e1000e_get_base_tininca() */ - - spin_lock_init(&adapter->systim_lock); - INIT_WORK(&adapter->tx_hwtstamp_work, e1000e_tx_hwtstamp_work); - } - - /* Explicitly disable IRQ since the NIC can be in any state. */ - e1000_irq_disable(adapter); - - set_bit(__E1000_DOWN, &adapter->state); - return 0; -} - -/** - * e1000_intr_msi_test - Interrupt Handler - * @irq: interrupt number - * @data: pointer to a network interface device structure - **/ -static irqreturn_t e1000_intr_msi_test(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 icr = er32(ICR); - - e_dbg("icr is %08X\n", icr); - if (icr & E1000_ICR_RXSEQ) { - adapter->flags &= ~FLAG_MSI_TEST_FAILED; - /* Force memory writes to complete before acknowledging the - * interrupt is handled. - */ - wmb(); - } - - return IRQ_HANDLED; -} - -/** - * e1000_test_msi_interrupt - Returns 0 for successful test - * @adapter: board private struct - * - * code flow taken from tg3.c - **/ -static int e1000_test_msi_interrupt(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - int err; - - /* poll_enable hasn't been called yet, so don't need disable */ - /* clear any pending events */ - er32(ICR); - - /* free the real vector and request a test handler */ - e1000_free_irq(adapter); - e1000e_reset_interrupt_capability(adapter); - - /* Assume that the test fails, if it succeeds then the test - * MSI irq handler will unset this flag - */ - adapter->flags |= FLAG_MSI_TEST_FAILED; - - err = pci_enable_msi(adapter->pdev); - if (err) - goto msi_test_failed; - - err = request_irq(adapter->pdev->irq, e1000_intr_msi_test, 0, - netdev->name, netdev); - if (err) { - pci_disable_msi(adapter->pdev); - goto msi_test_failed; - } - - /* Force memory writes to complete before enabling and firing an - * interrupt. - */ - wmb(); - - e1000_irq_enable(adapter); - - /* fire an unusual interrupt on the test handler */ - ew32(ICS, E1000_ICS_RXSEQ); - e1e_flush(); - msleep(100); - - e1000_irq_disable(adapter); - - rmb(); /* read flags after interrupt has been fired */ - - if (adapter->flags & FLAG_MSI_TEST_FAILED) { - adapter->int_mode = E1000E_INT_MODE_LEGACY; - e_info("MSI interrupt test failed, using legacy interrupt.\n"); - } else { - e_dbg("MSI interrupt test succeeded!\n"); - } - - free_irq(adapter->pdev->irq, netdev); - pci_disable_msi(adapter->pdev); - -msi_test_failed: - e1000e_set_interrupt_capability(adapter); - return e1000_request_irq(adapter); -} - -/** - * e1000_test_msi - Returns 0 if MSI test succeeds or INTx mode is restored - * @adapter: board private struct - * - * code flow taken from tg3.c, called with e1000 interrupts disabled. - **/ -static int e1000_test_msi(struct e1000_adapter *adapter) -{ - int err; - u16 pci_cmd; - - if (!(adapter->flags & FLAG_MSI_ENABLED)) - return 0; - - /* disable SERR in case the MSI write causes a master abort */ - pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd); - if (pci_cmd & PCI_COMMAND_SERR) - pci_write_config_word(adapter->pdev, PCI_COMMAND, - pci_cmd & ~PCI_COMMAND_SERR); - - err = e1000_test_msi_interrupt(adapter); - - /* re-enable SERR */ - if (pci_cmd & PCI_COMMAND_SERR) { - pci_read_config_word(adapter->pdev, PCI_COMMAND, &pci_cmd); - pci_cmd |= PCI_COMMAND_SERR; - pci_write_config_word(adapter->pdev, PCI_COMMAND, pci_cmd); - } - - return err; -} - -/** - * e1000_open - Called when a network interface is made active - * @netdev: network interface device structure - * - * Returns 0 on success, negative value on failure - * - * The open entry point is called when a network interface is made - * active by the system (IFF_UP). At this point all resources needed - * for transmit and receive operations are allocated, the interrupt - * handler is registered with the OS, the watchdog timer is started, - * and the stack is notified that the interface is ready. - **/ -static int e1000_open(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct pci_dev *pdev = adapter->pdev; - int err; - - /* disallow open during test */ - if (test_bit(__E1000_TESTING, &adapter->state)) - return -EBUSY; - - pm_runtime_get_sync(&pdev->dev); - - netif_carrier_off(netdev); - - /* allocate transmit descriptors */ - err = e1000e_setup_tx_resources(adapter->tx_ring); - if (err) - goto err_setup_tx; - - /* allocate receive descriptors */ - err = e1000e_setup_rx_resources(adapter->rx_ring); - if (err) - goto err_setup_rx; - - /* If AMT is enabled, let the firmware know that the network - * interface is now open and reset the part to a known state. - */ - if (adapter->flags & FLAG_HAS_AMT) { - e1000e_get_hw_control(adapter); - e1000e_reset(adapter); - } - - e1000e_power_up_phy(adapter); - - adapter->mng_vlan_id = E1000_MNG_VLAN_NONE; - if ((adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN)) - e1000_update_mng_vlan(adapter); - - /* DMA latency requirement to workaround jumbo issue */ - pm_qos_add_request(&adapter->pm_qos_req, PM_QOS_CPU_DMA_LATENCY, - PM_QOS_DEFAULT_VALUE); - - /* before we allocate an interrupt, we must be ready to handle it. - * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt - * as soon as we call pci_request_irq, so we have to setup our - * clean_rx handler before we do so. - */ - e1000_configure(adapter); - - err = e1000_request_irq(adapter); - if (err) - goto err_req_irq; - - /* Work around PCIe errata with MSI interrupts causing some chipsets to - * ignore e1000e MSI messages, which means we need to test our MSI - * interrupt now - */ - if (adapter->int_mode != E1000E_INT_MODE_LEGACY) { - err = e1000_test_msi(adapter); - if (err) { - e_err("Interrupt allocation failed\n"); - goto err_req_irq; - } - } - - /* From here on the code is the same as e1000e_up() */ - clear_bit(__E1000_DOWN, &adapter->state); - - napi_enable(&adapter->napi); - - e1000_irq_enable(adapter); - - adapter->tx_hang_recheck = false; - netif_start_queue(netdev); - - hw->mac.get_link_status = true; - pm_runtime_put(&pdev->dev); - - /* fire a link status change interrupt to start the watchdog */ - if (adapter->msix_entries) - ew32(ICS, E1000_ICS_LSC | E1000_ICR_OTHER); - else - ew32(ICS, E1000_ICS_LSC); - - return 0; - -err_req_irq: - pm_qos_remove_request(&adapter->pm_qos_req); - e1000e_release_hw_control(adapter); - e1000_power_down_phy(adapter); - e1000e_free_rx_resources(adapter->rx_ring); -err_setup_rx: - e1000e_free_tx_resources(adapter->tx_ring); -err_setup_tx: - e1000e_reset(adapter); - pm_runtime_put_sync(&pdev->dev); - - return err; -} - -/** - * e1000_close - Disables a network interface - * @netdev: network interface device structure - * - * Returns 0, this is not allowed to fail - * - * The close entry point is called when an interface is de-activated - * by the OS. The hardware is still under the drivers control, but - * needs to be disabled. A global MAC reset is issued to stop the - * hardware, and all transmit and receive resources are freed. - **/ -static int e1000_close(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct pci_dev *pdev = adapter->pdev; - int count = E1000_CHECK_RESET_COUNT; - - while (test_bit(__E1000_RESETTING, &adapter->state) && count--) - usleep_range(10000, 20000); - - WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); - - pm_runtime_get_sync(&pdev->dev); - - if (!test_bit(__E1000_DOWN, &adapter->state)) { - e1000e_down(adapter, true); - e1000_free_irq(adapter); - - /* Link status message must follow this format */ - pr_info("%s NIC Link is Down\n", adapter->netdev->name); - } - - napi_disable(&adapter->napi); - - e1000e_free_tx_resources(adapter->tx_ring); - e1000e_free_rx_resources(adapter->rx_ring); - - /* kill manageability vlan ID if supported, but not if a vlan with - * the same ID is registered on the host OS (let 8021q kill it) - */ - if (adapter->hw.mng_cookie.status & E1000_MNG_DHCP_COOKIE_STATUS_VLAN) - e1000_vlan_rx_kill_vid(netdev, htons(ETH_P_8021Q), - adapter->mng_vlan_id); - - /* If AMT is enabled, let the firmware know that the network - * interface is now closed - */ - if ((adapter->flags & FLAG_HAS_AMT) && - !test_bit(__E1000_TESTING, &adapter->state)) - e1000e_release_hw_control(adapter); - - pm_qos_remove_request(&adapter->pm_qos_req); - - pm_runtime_put_sync(&pdev->dev); - - return 0; -} - -/** - * e1000_set_mac - Change the Ethernet Address of the NIC - * @netdev: network interface device structure - * @p: pointer to an address structure - * - * Returns 0 on success, negative on failure - **/ -static int e1000_set_mac(struct net_device *netdev, void *p) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len); - memcpy(adapter->hw.mac.addr, addr->sa_data, netdev->addr_len); - - hw->mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, 0); - - if (adapter->flags & FLAG_RESET_OVERWRITES_LAA) { - /* activate the work around */ - e1000e_set_laa_state_82571(&adapter->hw, 1); - - /* Hold a copy of the LAA in RAR[14] This is done so that - * between the time RAR[0] gets clobbered and the time it - * gets fixed (in e1000_watchdog), the actual LAA is in one - * of the RARs and no incoming packets directed to this port - * are dropped. Eventually the LAA will be in RAR[0] and - * RAR[14] - */ - hw->mac.ops.rar_set(&adapter->hw, adapter->hw.mac.addr, - adapter->hw.mac.rar_entry_count - 1); - } - - return 0; -} - -/** - * e1000e_update_phy_task - work thread to update phy - * @work: pointer to our work struct - * - * this worker thread exists because we must acquire a - * semaphore to read the phy, which we could msleep while - * waiting for it, and we can't msleep in a timer. - **/ -static void e1000e_update_phy_task(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - update_phy_task); - struct e1000_hw *hw = &adapter->hw; - - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - - e1000_get_phy_info(hw); - - /* Enable EEE on 82579 after link up */ - if (hw->phy.type >= e1000_phy_82579) - e1000_set_eee_pchlan(hw); -} - -/** - * e1000_update_phy_info - timre call-back to update PHY info - * @data: pointer to adapter cast into an unsigned long - * - * Need to wait a few seconds after link up to get diagnostic information from - * the phy - **/ -static void e1000_update_phy_info(unsigned long data) -{ - struct e1000_adapter *adapter = (struct e1000_adapter *)data; - - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - - schedule_work(&adapter->update_phy_task); -} - -/** - * e1000e_update_phy_stats - Update the PHY statistics counters - * @adapter: board private structure - * - * Read/clear the upper 16-bit PHY registers and read/accumulate lower - **/ -static void e1000e_update_phy_stats(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - s32 ret_val; - u16 phy_data; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return; - - /* A page set is expensive so check if already on desired page. - * If not, set to the page with the PHY status registers. - */ - hw->phy.addr = 1; - ret_val = e1000e_read_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, - &phy_data); - if (ret_val) - goto release; - if (phy_data != (HV_STATS_PAGE << IGP_PAGE_SHIFT)) { - ret_val = hw->phy.ops.set_page(hw, - HV_STATS_PAGE << IGP_PAGE_SHIFT); - if (ret_val) - goto release; - } - - /* Single Collision Count */ - hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data); - if (!ret_val) - adapter->stats.scc += phy_data; - - /* Excessive Collision Count */ - hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data); - if (!ret_val) - adapter->stats.ecol += phy_data; - - /* Multiple Collision Count */ - hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data); - if (!ret_val) - adapter->stats.mcc += phy_data; - - /* Late Collision Count */ - hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data); - if (!ret_val) - adapter->stats.latecol += phy_data; - - /* Collision Count - also used for adaptive IFS */ - hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data); - if (!ret_val) - hw->mac.collision_delta = phy_data; - - /* Defer Count */ - hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data); - if (!ret_val) - adapter->stats.dc += phy_data; - - /* Transmit with no CRS */ - hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data); - ret_val = hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data); - if (!ret_val) - adapter->stats.tncrs += phy_data; - -release: - hw->phy.ops.release(hw); -} - -/** - * e1000e_update_stats - Update the board statistics counters - * @adapter: board private structure - **/ -static void e1000e_update_stats(struct e1000_adapter *adapter) -{ - struct net_device *netdev = adapter->netdev; - struct e1000_hw *hw = &adapter->hw; - struct pci_dev *pdev = adapter->pdev; - - /* Prevent stats update while adapter is being reset, or if the pci - * connection is down. - */ - if (adapter->link_speed == 0) - return; - if (pci_channel_offline(pdev)) - return; - - adapter->stats.crcerrs += er32(CRCERRS); - adapter->stats.gprc += er32(GPRC); - adapter->stats.gorc += er32(GORCL); - er32(GORCH); /* Clear gorc */ - adapter->stats.bprc += er32(BPRC); - adapter->stats.mprc += er32(MPRC); - adapter->stats.roc += er32(ROC); - - adapter->stats.mpc += er32(MPC); - - /* Half-duplex statistics */ - if (adapter->link_duplex == HALF_DUPLEX) { - if (adapter->flags2 & FLAG2_HAS_PHY_STATS) { - e1000e_update_phy_stats(adapter); - } else { - adapter->stats.scc += er32(SCC); - adapter->stats.ecol += er32(ECOL); - adapter->stats.mcc += er32(MCC); - adapter->stats.latecol += er32(LATECOL); - adapter->stats.dc += er32(DC); - - hw->mac.collision_delta = er32(COLC); - - if ((hw->mac.type != e1000_82574) && - (hw->mac.type != e1000_82583)) - adapter->stats.tncrs += er32(TNCRS); - } - adapter->stats.colc += hw->mac.collision_delta; - } - - adapter->stats.xonrxc += er32(XONRXC); - adapter->stats.xontxc += er32(XONTXC); - adapter->stats.xoffrxc += er32(XOFFRXC); - adapter->stats.xofftxc += er32(XOFFTXC); - adapter->stats.gptc += er32(GPTC); - adapter->stats.gotc += er32(GOTCL); - er32(GOTCH); /* Clear gotc */ - adapter->stats.rnbc += er32(RNBC); - adapter->stats.ruc += er32(RUC); - - adapter->stats.mptc += er32(MPTC); - adapter->stats.bptc += er32(BPTC); - - /* used for adaptive IFS */ - - hw->mac.tx_packet_delta = er32(TPT); - adapter->stats.tpt += hw->mac.tx_packet_delta; - - adapter->stats.algnerrc += er32(ALGNERRC); - adapter->stats.rxerrc += er32(RXERRC); - adapter->stats.cexterr += er32(CEXTERR); - adapter->stats.tsctc += er32(TSCTC); - adapter->stats.tsctfc += er32(TSCTFC); - - /* Fill out the OS statistics structure */ - netdev->stats.multicast = adapter->stats.mprc; - netdev->stats.collisions = adapter->stats.colc; - - /* Rx Errors */ - - /* RLEC on some newer hardware can be incorrect so build - * our own version based on RUC and ROC - */ - netdev->stats.rx_errors = adapter->stats.rxerrc + - adapter->stats.crcerrs + adapter->stats.algnerrc + - adapter->stats.ruc + adapter->stats.roc + adapter->stats.cexterr; - netdev->stats.rx_length_errors = adapter->stats.ruc + - adapter->stats.roc; - netdev->stats.rx_crc_errors = adapter->stats.crcerrs; - netdev->stats.rx_frame_errors = adapter->stats.algnerrc; - netdev->stats.rx_missed_errors = adapter->stats.mpc; - - /* Tx Errors */ - netdev->stats.tx_errors = adapter->stats.ecol + adapter->stats.latecol; - netdev->stats.tx_aborted_errors = adapter->stats.ecol; - netdev->stats.tx_window_errors = adapter->stats.latecol; - netdev->stats.tx_carrier_errors = adapter->stats.tncrs; - - /* Tx Dropped needs to be maintained elsewhere */ - - /* Management Stats */ - adapter->stats.mgptc += er32(MGTPTC); - adapter->stats.mgprc += er32(MGTPRC); - adapter->stats.mgpdc += er32(MGTPDC); - - /* Correctable ECC Errors */ - if ((hw->mac.type == e1000_pch_lpt) || - (hw->mac.type == e1000_pch_spt)) { - u32 pbeccsts = er32(PBECCSTS); - - adapter->corr_errors += - pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; - adapter->uncorr_errors += - (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> - E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; - } -} - -/** - * e1000_phy_read_status - Update the PHY register status snapshot - * @adapter: board private structure - **/ -static void e1000_phy_read_status(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct e1000_phy_regs *phy = &adapter->phy_regs; - - if (!pm_runtime_suspended((&adapter->pdev->dev)->parent) && - (er32(STATUS) & E1000_STATUS_LU) && - (adapter->hw.phy.media_type == e1000_media_type_copper)) { - int ret_val; - - ret_val = e1e_rphy(hw, MII_BMCR, &phy->bmcr); - ret_val |= e1e_rphy(hw, MII_BMSR, &phy->bmsr); - ret_val |= e1e_rphy(hw, MII_ADVERTISE, &phy->advertise); - ret_val |= e1e_rphy(hw, MII_LPA, &phy->lpa); - ret_val |= e1e_rphy(hw, MII_EXPANSION, &phy->expansion); - ret_val |= e1e_rphy(hw, MII_CTRL1000, &phy->ctrl1000); - ret_val |= e1e_rphy(hw, MII_STAT1000, &phy->stat1000); - ret_val |= e1e_rphy(hw, MII_ESTATUS, &phy->estatus); - if (ret_val) - e_warn("Error reading PHY register\n"); - } else { - /* Do not read PHY registers if link is not up - * Set values to typical power-on defaults - */ - phy->bmcr = (BMCR_SPEED1000 | BMCR_ANENABLE | BMCR_FULLDPLX); - phy->bmsr = (BMSR_100FULL | BMSR_100HALF | BMSR_10FULL | - BMSR_10HALF | BMSR_ESTATEN | BMSR_ANEGCAPABLE | - BMSR_ERCAP); - phy->advertise = (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP | - ADVERTISE_ALL | ADVERTISE_CSMA); - phy->lpa = 0; - phy->expansion = EXPANSION_ENABLENPAGE; - phy->ctrl1000 = ADVERTISE_1000FULL; - phy->stat1000 = 0; - phy->estatus = (ESTATUS_1000_TFULL | ESTATUS_1000_THALF); - } -} - -static void e1000_print_link_info(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - u32 ctrl = er32(CTRL); - - /* Link status message must follow this format for user tools */ - pr_info("%s NIC Link is Up %d Mbps %s Duplex, Flow Control: %s\n", - adapter->netdev->name, adapter->link_speed, - adapter->link_duplex == FULL_DUPLEX ? "Full" : "Half", - (ctrl & E1000_CTRL_TFCE) && (ctrl & E1000_CTRL_RFCE) ? "Rx/Tx" : - (ctrl & E1000_CTRL_RFCE) ? "Rx" : - (ctrl & E1000_CTRL_TFCE) ? "Tx" : "None"); -} - -static bool e1000e_has_link(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - bool link_active = false; - s32 ret_val = 0; - - /* get_link_status is set on LSC (link status) interrupt or - * Rx sequence error interrupt. get_link_status will stay - * false until the check_for_link establishes link - * for copper adapters ONLY - */ - switch (hw->phy.media_type) { - case e1000_media_type_copper: - if (hw->mac.get_link_status) { - ret_val = hw->mac.ops.check_for_link(hw); - link_active = ret_val > 0; - } else { - link_active = true; - } - break; - case e1000_media_type_fiber: - ret_val = hw->mac.ops.check_for_link(hw); - link_active = !!(er32(STATUS) & E1000_STATUS_LU); - break; - case e1000_media_type_internal_serdes: - ret_val = hw->mac.ops.check_for_link(hw); - link_active = adapter->hw.mac.serdes_has_link; - break; - default: - case e1000_media_type_unknown: - break; - } - - if ((ret_val == -E1000_ERR_PHY) && (hw->phy.type == e1000_phy_igp_3) && - (er32(CTRL) & E1000_PHY_CTRL_GBE_DISABLE)) { - /* See e1000_kmrn_lock_loss_workaround_ich8lan() */ - e_info("Gigabit has been disabled, downgrading speed\n"); - } - - return link_active; -} - -static void e1000e_enable_receives(struct e1000_adapter *adapter) -{ - /* make sure the receive unit is started */ - if ((adapter->flags & FLAG_RX_NEEDS_RESTART) && - (adapter->flags & FLAG_RESTART_NOW)) { - struct e1000_hw *hw = &adapter->hw; - u32 rctl = er32(RCTL); - - ew32(RCTL, rctl | E1000_RCTL_EN); - adapter->flags &= ~FLAG_RESTART_NOW; - } -} - -static void e1000e_check_82574_phy_workaround(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - /* With 82574 controllers, PHY needs to be checked periodically - * for hung state and reset, if two calls return true - */ - if (e1000_check_phy_82574(hw)) - adapter->phy_hang_count++; - else - adapter->phy_hang_count = 0; - - if (adapter->phy_hang_count > 1) { - adapter->phy_hang_count = 0; - e_dbg("PHY appears hung - resetting\n"); - schedule_work(&adapter->reset_task); - } -} - -/** - * e1000_watchdog - Timer Call-back - * @data: pointer to adapter cast into an unsigned long - **/ -static void e1000_watchdog(unsigned long data) -{ - struct e1000_adapter *adapter = (struct e1000_adapter *)data; - - /* Do the rest outside of interrupt context */ - schedule_work(&adapter->watchdog_task); - - /* TODO: make this use queue_delayed_work() */ -} - -static void e1000_watchdog_task(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, - struct e1000_adapter, - watchdog_task); - struct net_device *netdev = adapter->netdev; - struct e1000_mac_info *mac = &adapter->hw.mac; - struct e1000_phy_info *phy = &adapter->hw.phy; - struct e1000_ring *tx_ring = adapter->tx_ring; - struct e1000_hw *hw = &adapter->hw; - u32 link, tctl; - - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - - link = e1000e_has_link(adapter); - if ((netif_carrier_ok(netdev)) && link) { - /* Cancel scheduled suspend requests. */ - pm_runtime_resume(netdev->dev.parent); - - e1000e_enable_receives(adapter); - goto link_up; - } - - if ((e1000e_enable_tx_pkt_filtering(hw)) && - (adapter->mng_vlan_id != adapter->hw.mng_cookie.vlan_id)) - e1000_update_mng_vlan(adapter); - - if (link) { - if (!netif_carrier_ok(netdev)) { - bool txb2b = true; - - /* Cancel scheduled suspend requests. */ - pm_runtime_resume(netdev->dev.parent); - - /* update snapshot of PHY registers on LSC */ - e1000_phy_read_status(adapter); - mac->ops.get_link_up_info(&adapter->hw, - &adapter->link_speed, - &adapter->link_duplex); - e1000_print_link_info(adapter); - - /* check if SmartSpeed worked */ - e1000e_check_downshift(hw); - if (phy->speed_downgraded) - netdev_warn(netdev, - "Link Speed was downgraded by SmartSpeed\n"); - - /* On supported PHYs, check for duplex mismatch only - * if link has autonegotiated at 10/100 half - */ - if ((hw->phy.type == e1000_phy_igp_3 || - hw->phy.type == e1000_phy_bm) && - hw->mac.autoneg && - (adapter->link_speed == SPEED_10 || - adapter->link_speed == SPEED_100) && - (adapter->link_duplex == HALF_DUPLEX)) { - u16 autoneg_exp; - - e1e_rphy(hw, MII_EXPANSION, &autoneg_exp); - - if (!(autoneg_exp & EXPANSION_NWAY)) - e_info("Autonegotiated half duplex but link partner cannot autoneg. Try forcing full duplex if link gets many collisions.\n"); - } - - /* adjust timeout factor according to speed/duplex */ - adapter->tx_timeout_factor = 1; - switch (adapter->link_speed) { - case SPEED_10: - txb2b = false; - adapter->tx_timeout_factor = 16; - break; - case SPEED_100: - txb2b = false; - adapter->tx_timeout_factor = 10; - break; - } - - /* workaround: re-program speed mode bit after - * link-up event - */ - if ((adapter->flags & FLAG_TARC_SPEED_MODE_BIT) && - !txb2b) { - u32 tarc0; - - tarc0 = er32(TARC(0)); - tarc0 &= ~SPEED_MODE_BIT; - ew32(TARC(0), tarc0); - } - - /* disable TSO for pcie and 10/100 speeds, to avoid - * some hardware issues - */ - if (!(adapter->flags & FLAG_TSO_FORCE)) { - switch (adapter->link_speed) { - case SPEED_10: - case SPEED_100: - e_info("10/100 speed: disabling TSO\n"); - netdev->features &= ~NETIF_F_TSO; - netdev->features &= ~NETIF_F_TSO6; - break; - case SPEED_1000: - netdev->features |= NETIF_F_TSO; - netdev->features |= NETIF_F_TSO6; - break; - default: - /* oops */ - break; - } - } - - /* enable transmits in the hardware, need to do this - * after setting TARC(0) - */ - tctl = er32(TCTL); - tctl |= E1000_TCTL_EN; - ew32(TCTL, tctl); - - /* Perform any post-link-up configuration before - * reporting link up. - */ - if (phy->ops.cfg_on_link_up) - phy->ops.cfg_on_link_up(hw); - - netif_carrier_on(netdev); - - if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_timer(&adapter->phy_info_timer, - round_jiffies(jiffies + 2 * HZ)); - } - } else { - if (netif_carrier_ok(netdev)) { - adapter->link_speed = 0; - adapter->link_duplex = 0; - /* Link status message must follow this format */ - pr_info("%s NIC Link is Down\n", adapter->netdev->name); - netif_carrier_off(netdev); - if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_timer(&adapter->phy_info_timer, - round_jiffies(jiffies + 2 * HZ)); - - /* 8000ES2LAN requires a Rx packet buffer work-around - * on link down event; reset the controller to flush - * the Rx packet buffer. - */ - if (adapter->flags & FLAG_RX_NEEDS_RESTART) - adapter->flags |= FLAG_RESTART_NOW; - else - pm_schedule_suspend(netdev->dev.parent, - LINK_TIMEOUT); - } - } - -link_up: - spin_lock(&adapter->stats64_lock); - e1000e_update_stats(adapter); - - mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old; - adapter->tpt_old = adapter->stats.tpt; - mac->collision_delta = adapter->stats.colc - adapter->colc_old; - adapter->colc_old = adapter->stats.colc; - - adapter->gorc = adapter->stats.gorc - adapter->gorc_old; - adapter->gorc_old = adapter->stats.gorc; - adapter->gotc = adapter->stats.gotc - adapter->gotc_old; - adapter->gotc_old = adapter->stats.gotc; - spin_unlock(&adapter->stats64_lock); - - /* If the link is lost the controller stops DMA, but - * if there is queued Tx work it cannot be done. So - * reset the controller to flush the Tx packet buffers. - */ - if (!netif_carrier_ok(netdev) && - (e1000_desc_unused(tx_ring) + 1 < tx_ring->count)) - adapter->flags |= FLAG_RESTART_NOW; - - /* If reset is necessary, do it outside of interrupt context. */ - if (adapter->flags & FLAG_RESTART_NOW) { - schedule_work(&adapter->reset_task); - /* return immediately since reset is imminent */ - return; - } - - e1000e_update_adaptive(&adapter->hw); - - /* Simple mode for Interrupt Throttle Rate (ITR) */ - if (adapter->itr_setting == 4) { - /* Symmetric Tx/Rx gets a reduced ITR=2000; - * Total asymmetrical Tx or Rx gets ITR=8000; - * everyone else is between 2000-8000. - */ - u32 goc = (adapter->gotc + adapter->gorc) / 10000; - u32 dif = (adapter->gotc > adapter->gorc ? - adapter->gotc - adapter->gorc : - adapter->gorc - adapter->gotc) / 10000; - u32 itr = goc > 0 ? (dif * 6000 / goc + 2000) : 8000; - - e1000e_write_itr(adapter, itr); - } - - /* Cause software interrupt to ensure Rx ring is cleaned */ - if (adapter->msix_entries) - ew32(ICS, adapter->rx_ring->ims_val); - else - ew32(ICS, E1000_ICS_RXDMT0); - - /* flush pending descriptors to memory before detecting Tx hang */ - e1000e_flush_descriptors(adapter); - - /* Force detection of hung controller every watchdog period */ - adapter->detect_tx_hung = true; - - /* With 82571 controllers, LAA may be overwritten due to controller - * reset from the other port. Set the appropriate LAA in RAR[0] - */ - if (e1000e_get_laa_state_82571(hw)) - hw->mac.ops.rar_set(hw, adapter->hw.mac.addr, 0); - - if (adapter->flags2 & FLAG2_CHECK_PHY_HANG) - e1000e_check_82574_phy_workaround(adapter); - - /* Clear valid timestamp stuck in RXSTMPL/H due to a Rx error */ - if (adapter->hwtstamp_config.rx_filter != HWTSTAMP_FILTER_NONE) { - if ((adapter->flags2 & FLAG2_CHECK_RX_HWTSTAMP) && - (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_VALID)) { - er32(RXSTMPH); - adapter->rx_hwtstamp_cleared++; - } else { - adapter->flags2 |= FLAG2_CHECK_RX_HWTSTAMP; - } - } - - /* Reset the timer */ - if (!test_bit(__E1000_DOWN, &adapter->state)) - mod_timer(&adapter->watchdog_timer, - round_jiffies(jiffies + 2 * HZ)); -} - -#define E1000_TX_FLAGS_CSUM 0x00000001 -#define E1000_TX_FLAGS_VLAN 0x00000002 -#define E1000_TX_FLAGS_TSO 0x00000004 -#define E1000_TX_FLAGS_IPV4 0x00000008 -#define E1000_TX_FLAGS_NO_FCS 0x00000010 -#define E1000_TX_FLAGS_HWTSTAMP 0x00000020 -#define E1000_TX_FLAGS_VLAN_MASK 0xffff0000 -#define E1000_TX_FLAGS_VLAN_SHIFT 16 - -static int e1000_tso(struct e1000_ring *tx_ring, struct sk_buff *skb, - __be16 protocol) -{ - struct e1000_context_desc *context_desc; - struct e1000_buffer *buffer_info; - unsigned int i; - u32 cmd_length = 0; - u16 ipcse = 0, mss; - u8 ipcss, ipcso, tucss, tucso, hdr_len; - int err; - - if (!skb_is_gso(skb)) - return 0; - - err = skb_cow_head(skb, 0); - if (err < 0) - return err; - - hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - mss = skb_shinfo(skb)->gso_size; - if (protocol == htons(ETH_P_IP)) { - struct iphdr *iph = ip_hdr(skb); - iph->tot_len = 0; - iph->check = 0; - tcp_hdr(skb)->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, - 0, IPPROTO_TCP, 0); - cmd_length = E1000_TXD_CMD_IP; - ipcse = skb_transport_offset(skb) - 1; - } else if (skb_is_gso_v6(skb)) { - ipv6_hdr(skb)->payload_len = 0; - tcp_hdr(skb)->check = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, - &ipv6_hdr(skb)->daddr, - 0, IPPROTO_TCP, 0); - ipcse = 0; - } - ipcss = skb_network_offset(skb); - ipcso = (void *)&(ip_hdr(skb)->check) - (void *)skb->data; - tucss = skb_transport_offset(skb); - tucso = (void *)&(tcp_hdr(skb)->check) - (void *)skb->data; - - cmd_length |= (E1000_TXD_CMD_DEXT | E1000_TXD_CMD_TSE | - E1000_TXD_CMD_TCP | (skb->len - (hdr_len))); - - i = tx_ring->next_to_use; - context_desc = E1000_CONTEXT_DESC(*tx_ring, i); - buffer_info = &tx_ring->buffer_info[i]; - - context_desc->lower_setup.ip_fields.ipcss = ipcss; - context_desc->lower_setup.ip_fields.ipcso = ipcso; - context_desc->lower_setup.ip_fields.ipcse = cpu_to_le16(ipcse); - context_desc->upper_setup.tcp_fields.tucss = tucss; - context_desc->upper_setup.tcp_fields.tucso = tucso; - context_desc->upper_setup.tcp_fields.tucse = 0; - context_desc->tcp_seg_setup.fields.mss = cpu_to_le16(mss); - context_desc->tcp_seg_setup.fields.hdr_len = hdr_len; - context_desc->cmd_and_length = cpu_to_le32(cmd_length); - - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; - - i++; - if (i == tx_ring->count) - i = 0; - tx_ring->next_to_use = i; - - return 1; -} - -static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb, - __be16 protocol) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct e1000_context_desc *context_desc; - struct e1000_buffer *buffer_info; - unsigned int i; - u8 css; - u32 cmd_len = E1000_TXD_CMD_DEXT; - - if (skb->ip_summed != CHECKSUM_PARTIAL) - return false; - - switch (protocol) { - case cpu_to_be16(ETH_P_IP): - if (ip_hdr(skb)->protocol == IPPROTO_TCP) - cmd_len |= E1000_TXD_CMD_TCP; - break; - case cpu_to_be16(ETH_P_IPV6): - /* XXX not handling all IPV6 headers */ - if (ipv6_hdr(skb)->nexthdr == IPPROTO_TCP) - cmd_len |= E1000_TXD_CMD_TCP; - break; - default: - if (unlikely(net_ratelimit())) - e_warn("checksum_partial proto=%x!\n", - be16_to_cpu(protocol)); - break; - } - - css = skb_checksum_start_offset(skb); - - i = tx_ring->next_to_use; - buffer_info = &tx_ring->buffer_info[i]; - context_desc = E1000_CONTEXT_DESC(*tx_ring, i); - - context_desc->lower_setup.ip_config = 0; - context_desc->upper_setup.tcp_fields.tucss = css; - context_desc->upper_setup.tcp_fields.tucso = css + skb->csum_offset; - context_desc->upper_setup.tcp_fields.tucse = 0; - context_desc->tcp_seg_setup.data = 0; - context_desc->cmd_and_length = cpu_to_le32(cmd_len); - - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; - - i++; - if (i == tx_ring->count) - i = 0; - tx_ring->next_to_use = i; - - return true; -} - -static int e1000_tx_map(struct e1000_ring *tx_ring, struct sk_buff *skb, - unsigned int first, unsigned int max_per_txd, - unsigned int nr_frags) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct pci_dev *pdev = adapter->pdev; - struct e1000_buffer *buffer_info; - unsigned int len = skb_headlen(skb); - unsigned int offset = 0, size, count = 0, i; - unsigned int f, bytecount, segs; - - i = tx_ring->next_to_use; - - while (len) { - buffer_info = &tx_ring->buffer_info[i]; - size = min(len, max_per_txd); - - buffer_info->length = size; - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; - buffer_info->dma = dma_map_single(&pdev->dev, - skb->data + offset, - size, DMA_TO_DEVICE); - buffer_info->mapped_as_page = false; - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) - goto dma_error; - - len -= size; - offset += size; - count++; - - if (len) { - i++; - if (i == tx_ring->count) - i = 0; - } - } - - for (f = 0; f < nr_frags; f++) { - const struct skb_frag_struct *frag; - - frag = &skb_shinfo(skb)->frags[f]; - len = skb_frag_size(frag); - offset = 0; - - while (len) { - i++; - if (i == tx_ring->count) - i = 0; - - buffer_info = &tx_ring->buffer_info[i]; - size = min(len, max_per_txd); - - buffer_info->length = size; - buffer_info->time_stamp = jiffies; - buffer_info->next_to_watch = i; - buffer_info->dma = skb_frag_dma_map(&pdev->dev, frag, - offset, size, - DMA_TO_DEVICE); - buffer_info->mapped_as_page = true; - if (dma_mapping_error(&pdev->dev, buffer_info->dma)) - goto dma_error; - - len -= size; - offset += size; - count++; - } - } - - segs = skb_shinfo(skb)->gso_segs ? : 1; - /* multiply data chunks by size of headers */ - bytecount = ((segs - 1) * skb_headlen(skb)) + skb->len; - - tx_ring->buffer_info[i].skb = skb; - tx_ring->buffer_info[i].segs = segs; - tx_ring->buffer_info[i].bytecount = bytecount; - tx_ring->buffer_info[first].next_to_watch = i; - - return count; - -dma_error: - dev_err(&pdev->dev, "Tx DMA map failed\n"); - buffer_info->dma = 0; - if (count) - count--; - - while (count--) { - if (i == 0) - i += tx_ring->count; - i--; - buffer_info = &tx_ring->buffer_info[i]; - e1000_put_txbuf(tx_ring, buffer_info); - } - - return 0; -} - -static void e1000_tx_queue(struct e1000_ring *tx_ring, int tx_flags, int count) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - struct e1000_tx_desc *tx_desc = NULL; - struct e1000_buffer *buffer_info; - u32 txd_upper = 0, txd_lower = E1000_TXD_CMD_IFCS; - unsigned int i; - - if (tx_flags & E1000_TX_FLAGS_TSO) { - txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D | - E1000_TXD_CMD_TSE; - txd_upper |= E1000_TXD_POPTS_TXSM << 8; - - if (tx_flags & E1000_TX_FLAGS_IPV4) - txd_upper |= E1000_TXD_POPTS_IXSM << 8; - } - - if (tx_flags & E1000_TX_FLAGS_CSUM) { - txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; - txd_upper |= E1000_TXD_POPTS_TXSM << 8; - } - - if (tx_flags & E1000_TX_FLAGS_VLAN) { - txd_lower |= E1000_TXD_CMD_VLE; - txd_upper |= (tx_flags & E1000_TX_FLAGS_VLAN_MASK); - } - - if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS)) - txd_lower &= ~(E1000_TXD_CMD_IFCS); - - if (unlikely(tx_flags & E1000_TX_FLAGS_HWTSTAMP)) { - txd_lower |= E1000_TXD_CMD_DEXT | E1000_TXD_DTYP_D; - txd_upper |= E1000_TXD_EXTCMD_TSTAMP; - } - - i = tx_ring->next_to_use; - - do { - buffer_info = &tx_ring->buffer_info[i]; - tx_desc = E1000_TX_DESC(*tx_ring, i); - tx_desc->buffer_addr = cpu_to_le64(buffer_info->dma); - tx_desc->lower.data = cpu_to_le32(txd_lower | - buffer_info->length); - tx_desc->upper.data = cpu_to_le32(txd_upper); - - i++; - if (i == tx_ring->count) - i = 0; - } while (--count > 0); - - tx_desc->lower.data |= cpu_to_le32(adapter->txd_cmd); - - /* txd_cmd re-enables FCS, so we'll re-disable it here as desired. */ - if (unlikely(tx_flags & E1000_TX_FLAGS_NO_FCS)) - tx_desc->lower.data &= ~(cpu_to_le32(E1000_TXD_CMD_IFCS)); - - /* Force memory writes to complete before letting h/w - * know there are new descriptors to fetch. (Only - * applicable for weak-ordered memory model archs, - * such as IA-64). - */ - wmb(); - - tx_ring->next_to_use = i; -} - -#define MINIMUM_DHCP_PACKET_SIZE 282 -static int e1000_transfer_dhcp_info(struct e1000_adapter *adapter, - struct sk_buff *skb) -{ - struct e1000_hw *hw = &adapter->hw; - u16 length, offset; - - if (skb_vlan_tag_present(skb) && - !((skb_vlan_tag_get(skb) == adapter->hw.mng_cookie.vlan_id) && - (adapter->hw.mng_cookie.status & - E1000_MNG_DHCP_COOKIE_STATUS_VLAN))) - return 0; - - if (skb->len <= MINIMUM_DHCP_PACKET_SIZE) - return 0; - - if (((struct ethhdr *)skb->data)->h_proto != htons(ETH_P_IP)) - return 0; - - { - const struct iphdr *ip = (struct iphdr *)((u8 *)skb->data + 14); - struct udphdr *udp; - - if (ip->protocol != IPPROTO_UDP) - return 0; - - udp = (struct udphdr *)((u8 *)ip + (ip->ihl << 2)); - if (ntohs(udp->dest) != 67) - return 0; - - offset = (u8 *)udp + 8 - skb->data; - length = skb->len - offset; - return e1000e_mng_write_dhcp_info(hw, (u8 *)udp + 8, length); - } - - return 0; -} - -static int __e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) -{ - struct e1000_adapter *adapter = tx_ring->adapter; - - netif_stop_queue(adapter->netdev); - /* Herbert's original patch had: - * smp_mb__after_netif_stop_queue(); - * but since that doesn't exist yet, just open code it. - */ - smp_mb(); - - /* We need to check again in a case another CPU has just - * made room available. - */ - if (e1000_desc_unused(tx_ring) < size) - return -EBUSY; - - /* A reprieve! */ - netif_start_queue(adapter->netdev); - ++adapter->restart_queue; - return 0; -} - -static int e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size) -{ - BUG_ON(size > tx_ring->count); - - if (e1000_desc_unused(tx_ring) >= size) - return 0; - return __e1000_maybe_stop_tx(tx_ring, size); -} - -static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, - struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_ring *tx_ring = adapter->tx_ring; - unsigned int first; - unsigned int tx_flags = 0; - unsigned int len = skb_headlen(skb); - unsigned int nr_frags; - unsigned int mss; - int count = 0; - int tso; - unsigned int f; - __be16 protocol = vlan_get_protocol(skb); - - if (test_bit(__E1000_DOWN, &adapter->state)) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if (skb->len <= 0) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - /* The minimum packet size with TCTL.PSP set is 17 bytes so - * pad skb in order to meet this minimum size requirement - */ - if (skb_put_padto(skb, 17)) - return NETDEV_TX_OK; - - mss = skb_shinfo(skb)->gso_size; - if (mss) { - u8 hdr_len; - - /* TSO Workaround for 82571/2/3 Controllers -- if skb->data - * points to just header, pull a few bytes of payload from - * frags into skb->data - */ - hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb); - /* we do this workaround for ES2LAN, but it is un-necessary, - * avoiding it could save a lot of cycles - */ - if (skb->data_len && (hdr_len == len)) { - unsigned int pull_size; - - pull_size = min_t(unsigned int, 4, skb->data_len); - if (!__pskb_pull_tail(skb, pull_size)) { - e_err("__pskb_pull_tail failed.\n"); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - len = skb_headlen(skb); - } - } - - /* reserve a descriptor for the offload context */ - if ((mss) || (skb->ip_summed == CHECKSUM_PARTIAL)) - count++; - count++; - - count += DIV_ROUND_UP(len, adapter->tx_fifo_limit); - - nr_frags = skb_shinfo(skb)->nr_frags; - for (f = 0; f < nr_frags; f++) - count += DIV_ROUND_UP(skb_frag_size(&skb_shinfo(skb)->frags[f]), - adapter->tx_fifo_limit); - - if (adapter->hw.mac.tx_pkt_filtering) - e1000_transfer_dhcp_info(adapter, skb); - - /* need: count + 2 desc gap to keep tail from touching - * head, otherwise try next time - */ - if (e1000_maybe_stop_tx(tx_ring, count + 2)) - return NETDEV_TX_BUSY; - - if (skb_vlan_tag_present(skb)) { - tx_flags |= E1000_TX_FLAGS_VLAN; - tx_flags |= (skb_vlan_tag_get(skb) << - E1000_TX_FLAGS_VLAN_SHIFT); - } - - first = tx_ring->next_to_use; - - tso = e1000_tso(tx_ring, skb, protocol); - if (tso < 0) { - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - if (tso) - tx_flags |= E1000_TX_FLAGS_TSO; - else if (e1000_tx_csum(tx_ring, skb, protocol)) - tx_flags |= E1000_TX_FLAGS_CSUM; - - /* Old method was to assume IPv4 packet by default if TSO was enabled. - * 82571 hardware supports TSO capabilities for IPv6 as well... - * no longer assume, we must. - */ - if (protocol == htons(ETH_P_IP)) - tx_flags |= E1000_TX_FLAGS_IPV4; - - if (unlikely(skb->no_fcs)) - tx_flags |= E1000_TX_FLAGS_NO_FCS; - - /* if count is 0 then mapping error has occurred */ - count = e1000_tx_map(tx_ring, skb, first, adapter->tx_fifo_limit, - nr_frags); - if (count) { - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && - (adapter->flags & FLAG_HAS_HW_TIMESTAMP) && - !adapter->tx_hwtstamp_skb) { - skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - tx_flags |= E1000_TX_FLAGS_HWTSTAMP; - adapter->tx_hwtstamp_skb = skb_get(skb); - adapter->tx_hwtstamp_start = jiffies; - schedule_work(&adapter->tx_hwtstamp_work); - } else { - skb_tx_timestamp(skb); - } - - netdev_sent_queue(netdev, skb->len); - e1000_tx_queue(tx_ring, tx_flags, count); - /* Make sure there is space in the ring for the next send. */ - e1000_maybe_stop_tx(tx_ring, - (MAX_SKB_FRAGS * - DIV_ROUND_UP(PAGE_SIZE, - adapter->tx_fifo_limit) + 2)); - - if (!skb->xmit_more || - netif_xmit_stopped(netdev_get_tx_queue(netdev, 0))) { - if (adapter->flags2 & FLAG2_PCIM2PCI_ARBITER_WA) - e1000e_update_tdt_wa(tx_ring, - tx_ring->next_to_use); - else - writel(tx_ring->next_to_use, tx_ring->tail); - - /* we need this if more than one processor can write - * to our tail at a time, it synchronizes IO on - *IA64/Altix systems - */ - mmiowb(); - } - } else { - dev_kfree_skb_any(skb); - tx_ring->buffer_info[first].time_stamp = 0; - tx_ring->next_to_use = first; - } - - return NETDEV_TX_OK; -} - -/** - * e1000_tx_timeout - Respond to a Tx Hang - * @netdev: network interface device structure - **/ -static void e1000_tx_timeout(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - /* Do the reset outside of interrupt context */ - adapter->tx_timeout_count++; - schedule_work(&adapter->reset_task); -} - -static void e1000_reset_task(struct work_struct *work) -{ - struct e1000_adapter *adapter; - adapter = container_of(work, struct e1000_adapter, reset_task); - - /* don't run the task if already down */ - if (test_bit(__E1000_DOWN, &adapter->state)) - return; - - if (!(adapter->flags & FLAG_RESTART_NOW)) { - e1000e_dump(adapter); - e_err("Reset adapter unexpectedly\n"); - } - e1000e_reinit_locked(adapter); -} - -/** - * e1000_get_stats64 - Get System Network Statistics - * @netdev: network interface device structure - * @stats: rtnl_link_stats64 pointer - * - * Returns the address of the device statistics structure. - **/ -struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev, - struct rtnl_link_stats64 *stats) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - memset(stats, 0, sizeof(struct rtnl_link_stats64)); - spin_lock(&adapter->stats64_lock); - e1000e_update_stats(adapter); - /* Fill out the OS statistics structure */ - stats->rx_bytes = adapter->stats.gorc; - stats->rx_packets = adapter->stats.gprc; - stats->tx_bytes = adapter->stats.gotc; - stats->tx_packets = adapter->stats.gptc; - stats->multicast = adapter->stats.mprc; - stats->collisions = adapter->stats.colc; - - /* Rx Errors */ - - /* RLEC on some newer hardware can be incorrect so build - * our own version based on RUC and ROC - */ - stats->rx_errors = adapter->stats.rxerrc + - adapter->stats.crcerrs + adapter->stats.algnerrc + - adapter->stats.ruc + adapter->stats.roc + adapter->stats.cexterr; - stats->rx_length_errors = adapter->stats.ruc + adapter->stats.roc; - stats->rx_crc_errors = adapter->stats.crcerrs; - stats->rx_frame_errors = adapter->stats.algnerrc; - stats->rx_missed_errors = adapter->stats.mpc; - - /* Tx Errors */ - stats->tx_errors = adapter->stats.ecol + adapter->stats.latecol; - stats->tx_aborted_errors = adapter->stats.ecol; - stats->tx_window_errors = adapter->stats.latecol; - stats->tx_carrier_errors = adapter->stats.tncrs; - - /* Tx Dropped needs to be maintained elsewhere */ - - spin_unlock(&adapter->stats64_lock); - return stats; -} - -/** - * e1000_change_mtu - Change the Maximum Transfer Unit - * @netdev: network interface device structure - * @new_mtu: new value for maximum frame size - * - * Returns 0 on success, negative on failure - **/ -static int e1000_change_mtu(struct net_device *netdev, int new_mtu) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - int max_frame = new_mtu + VLAN_ETH_HLEN + ETH_FCS_LEN; - - /* Jumbo frame support */ - if ((max_frame > (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)) && - !(adapter->flags & FLAG_HAS_JUMBO_FRAMES)) { - e_err("Jumbo Frames not supported.\n"); - return -EINVAL; - } - - /* Supported frame sizes */ - if ((new_mtu < (VLAN_ETH_ZLEN + ETH_FCS_LEN)) || - (max_frame > adapter->max_hw_frame_size)) { - e_err("Unsupported MTU setting\n"); - return -EINVAL; - } - - /* Jumbo frame workaround on 82579 and newer requires CRC be stripped */ - if ((adapter->hw.mac.type >= e1000_pch2lan) && - !(adapter->flags2 & FLAG2_CRC_STRIPPING) && - (new_mtu > ETH_DATA_LEN)) { - e_err("Jumbo Frames not supported on this device when CRC stripping is disabled.\n"); - return -EINVAL; - } - - while (test_and_set_bit(__E1000_RESETTING, &adapter->state)) - usleep_range(1000, 2000); - /* e1000e_down -> e1000e_reset dependent on max_frame_size & mtu */ - adapter->max_frame_size = max_frame; - e_info("changing MTU from %d to %d\n", netdev->mtu, new_mtu); - netdev->mtu = new_mtu; - - pm_runtime_get_sync(netdev->dev.parent); - - if (netif_running(netdev)) - e1000e_down(adapter, true); - - /* NOTE: netdev_alloc_skb reserves 16 bytes, and typically NET_IP_ALIGN - * means we reserve 2 more, this pushes us to allocate from the next - * larger slab size. - * i.e. RXBUFFER_2048 --> size-4096 slab - * However with the new *_jumbo_rx* routines, jumbo receives will use - * fragmented skbs - */ - - if (max_frame <= 2048) - adapter->rx_buffer_len = 2048; - else - adapter->rx_buffer_len = 4096; - - /* adjust allocation if LPE protects us, and we aren't using SBP */ - if (max_frame <= (VLAN_ETH_FRAME_LEN + ETH_FCS_LEN)) - adapter->rx_buffer_len = VLAN_ETH_FRAME_LEN + ETH_FCS_LEN; - - if (netif_running(netdev)) - e1000e_up(adapter); - else - e1000e_reset(adapter); - - pm_runtime_put_sync(netdev->dev.parent); - - clear_bit(__E1000_RESETTING, &adapter->state); - - return 0; -} - -static int e1000_mii_ioctl(struct net_device *netdev, struct ifreq *ifr, - int cmd) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct mii_ioctl_data *data = if_mii(ifr); - - if (adapter->hw.phy.media_type != e1000_media_type_copper) - return -EOPNOTSUPP; - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = adapter->hw.phy.addr; - break; - case SIOCGMIIREG: - e1000_phy_read_status(adapter); - - switch (data->reg_num & 0x1F) { - case MII_BMCR: - data->val_out = adapter->phy_regs.bmcr; - break; - case MII_BMSR: - data->val_out = adapter->phy_regs.bmsr; - break; - case MII_PHYSID1: - data->val_out = (adapter->hw.phy.id >> 16); - break; - case MII_PHYSID2: - data->val_out = (adapter->hw.phy.id & 0xFFFF); - break; - case MII_ADVERTISE: - data->val_out = adapter->phy_regs.advertise; - break; - case MII_LPA: - data->val_out = adapter->phy_regs.lpa; - break; - case MII_EXPANSION: - data->val_out = adapter->phy_regs.expansion; - break; - case MII_CTRL1000: - data->val_out = adapter->phy_regs.ctrl1000; - break; - case MII_STAT1000: - data->val_out = adapter->phy_regs.stat1000; - break; - case MII_ESTATUS: - data->val_out = adapter->phy_regs.estatus; - break; - default: - return -EIO; - } - break; - case SIOCSMIIREG: - default: - return -EOPNOTSUPP; - } - return 0; -} - -/** - * e1000e_hwtstamp_ioctl - control hardware time stamping - * @netdev: network interface device structure - * @ifreq: interface request - * - * Outgoing time stamping can be enabled and disabled. Play nice and - * disable it when requested, although it shouldn't cause any overhead - * when no packet needs it. At most one packet in the queue may be - * marked for time stamping, otherwise it would be impossible to tell - * for sure to which packet the hardware time stamp belongs. - * - * Incoming time stamping has to be configured via the hardware filters. - * Not all combinations are supported, in particular event type has to be - * specified. Matching the kind of event packet is not supported, with the - * exception of "all V2 events regardless of level 2 or 4". - **/ -static int e1000e_hwtstamp_set(struct net_device *netdev, struct ifreq *ifr) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct hwtstamp_config config; - int ret_val; - - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - ret_val = e1000e_config_hwtstamp(adapter, &config); - if (ret_val) - return ret_val; - - switch (config.rx_filter) { - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - /* With V2 type filters which specify a Sync or Delay Request, - * Path Delay Request/Response messages are also time stamped - * by hardware so notify the caller the requested packets plus - * some others are time stamped. - */ - config.rx_filter = HWTSTAMP_FILTER_SOME; - break; - default: - break; - } - - return copy_to_user(ifr->ifr_data, &config, - sizeof(config)) ? -EFAULT : 0; -} - -static int e1000e_hwtstamp_get(struct net_device *netdev, struct ifreq *ifr) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - return copy_to_user(ifr->ifr_data, &adapter->hwtstamp_config, - sizeof(adapter->hwtstamp_config)) ? -EFAULT : 0; -} - -static int e1000_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - case SIOCGMIIREG: - case SIOCSMIIREG: - return e1000_mii_ioctl(netdev, ifr, cmd); - case SIOCSHWTSTAMP: - return e1000e_hwtstamp_set(netdev, ifr); - case SIOCGHWTSTAMP: - return e1000e_hwtstamp_get(netdev, ifr); - default: - return -EOPNOTSUPP; - } -} - -static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) -{ - struct e1000_hw *hw = &adapter->hw; - u32 i, mac_reg, wuc; - u16 phy_reg, wuc_enable; - int retval; - - /* copy MAC RARs to PHY RARs */ - e1000_copy_rx_addrs_to_phy_ich8lan(hw); - - retval = hw->phy.ops.acquire(hw); - if (retval) { - e_err("Could not acquire PHY\n"); - return retval; - } - - /* Enable access to wakeup registers on and set page to BM_WUC_PAGE */ - retval = e1000_enable_phy_wakeup_reg_access_bm(hw, &wuc_enable); - if (retval) - goto release; - - /* copy MAC MTA to PHY MTA - only needed for pchlan */ - for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) { - mac_reg = E1000_READ_REG_ARRAY(hw, E1000_MTA, i); - hw->phy.ops.write_reg_page(hw, BM_MTA(i), - (u16)(mac_reg & 0xFFFF)); - hw->phy.ops.write_reg_page(hw, BM_MTA(i) + 1, - (u16)((mac_reg >> 16) & 0xFFFF)); - } - - /* configure PHY Rx Control register */ - hw->phy.ops.read_reg_page(&adapter->hw, BM_RCTL, &phy_reg); - mac_reg = er32(RCTL); - if (mac_reg & E1000_RCTL_UPE) - phy_reg |= BM_RCTL_UPE; - if (mac_reg & E1000_RCTL_MPE) - phy_reg |= BM_RCTL_MPE; - phy_reg &= ~(BM_RCTL_MO_MASK); - if (mac_reg & E1000_RCTL_MO_3) - phy_reg |= (((mac_reg & E1000_RCTL_MO_3) >> E1000_RCTL_MO_SHIFT) - << BM_RCTL_MO_SHIFT); - if (mac_reg & E1000_RCTL_BAM) - phy_reg |= BM_RCTL_BAM; - if (mac_reg & E1000_RCTL_PMCF) - phy_reg |= BM_RCTL_PMCF; - mac_reg = er32(CTRL); - if (mac_reg & E1000_CTRL_RFCE) - phy_reg |= BM_RCTL_RFCE; - hw->phy.ops.write_reg_page(&adapter->hw, BM_RCTL, phy_reg); - - wuc = E1000_WUC_PME_EN; - if (wufc & (E1000_WUFC_MAG | E1000_WUFC_LNKC)) - wuc |= E1000_WUC_APME; - - /* enable PHY wakeup in MAC register */ - ew32(WUFC, wufc); - ew32(WUC, (E1000_WUC_PHY_WAKE | E1000_WUC_APMPME | - E1000_WUC_PME_STATUS | wuc)); - - /* configure and enable PHY wakeup in PHY registers */ - hw->phy.ops.write_reg_page(&adapter->hw, BM_WUFC, wufc); - hw->phy.ops.write_reg_page(&adapter->hw, BM_WUC, wuc); - - /* activate PHY wakeup */ - wuc_enable |= BM_WUC_ENABLE_BIT | BM_WUC_HOST_WU_BIT; - retval = e1000_disable_phy_wakeup_reg_access_bm(hw, &wuc_enable); - if (retval) - e_err("Could not set PHY Host Wakeup bit\n"); -release: - hw->phy.ops.release(hw); - - return retval; -} - -static void e1000e_flush_lpic(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 ret_val; - - pm_runtime_get_sync(netdev->dev.parent); - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - goto fl_out; - - pr_info("EEE TX LPI TIMER: %08X\n", - er32(LPIC) >> E1000_LPIC_LPIET_SHIFT); - - hw->phy.ops.release(hw); - -fl_out: - pm_runtime_put_sync(netdev->dev.parent); -} - -static int e1000e_pm_freeze(struct device *dev) -{ - struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev)); - struct e1000_adapter *adapter = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (netif_running(netdev)) { - int count = E1000_CHECK_RESET_COUNT; - - while (test_bit(__E1000_RESETTING, &adapter->state) && count--) - usleep_range(10000, 20000); - - WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); - - /* Quiesce the device without resetting the hardware */ - e1000e_down(adapter, false); - e1000_free_irq(adapter); - } - e1000e_reset_interrupt_capability(adapter); - - /* Allow time for pending master requests to run */ - e1000e_disable_pcie_master(&adapter->hw); - - return 0; -} - -static int __e1000_shutdown(struct pci_dev *pdev, bool runtime) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u32 ctrl, ctrl_ext, rctl, status; - /* Runtime suspend should only enable wakeup for link changes */ - u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol; - int retval = 0; - - status = er32(STATUS); - if (status & E1000_STATUS_LU) - wufc &= ~E1000_WUFC_LNKC; - - if (wufc) { - e1000_setup_rctl(adapter); - e1000e_set_rx_mode(netdev); - - /* turn on all-multi mode if wake on multicast is enabled */ - if (wufc & E1000_WUFC_MC) { - rctl = er32(RCTL); - rctl |= E1000_RCTL_MPE; - ew32(RCTL, rctl); - } - - ctrl = er32(CTRL); - ctrl |= E1000_CTRL_ADVD3WUC; - if (!(adapter->flags2 & FLAG2_HAS_PHY_WAKEUP)) - ctrl |= E1000_CTRL_EN_PHY_PWR_MGMT; - ew32(CTRL, ctrl); - - if (adapter->hw.phy.media_type == e1000_media_type_fiber || - adapter->hw.phy.media_type == - e1000_media_type_internal_serdes) { - /* keep the laser running in D3 */ - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_SDP3_DATA; - ew32(CTRL_EXT, ctrl_ext); - } - - if (!runtime) - e1000e_power_up_phy(adapter); - - if (adapter->flags & FLAG_IS_ICH) - e1000_suspend_workarounds_ich8lan(&adapter->hw); - - if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) { - /* enable wakeup by the PHY */ - retval = e1000_init_phy_wakeup(adapter, wufc); - if (retval) - return retval; - } else { - /* enable wakeup by the MAC */ - ew32(WUFC, wufc); - ew32(WUC, E1000_WUC_PME_EN); - } - } else { - ew32(WUC, 0); - ew32(WUFC, 0); - - e1000_power_down_phy(adapter); - } - - if (adapter->hw.phy.type == e1000_phy_igp_3) { - e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); - } else if ((hw->mac.type == e1000_pch_lpt) || - (hw->mac.type == e1000_pch_spt)) { - if (!(wufc & (E1000_WUFC_EX | E1000_WUFC_MC | E1000_WUFC_BC))) - /* ULP does not support wake from unicast, multicast - * or broadcast. - */ - retval = e1000_enable_ulp_lpt_lp(hw, !runtime); - - if (retval) - return retval; - } - - /* Ensure that the appropriate bits are set in LPI_CTRL - * for EEE in Sx - */ - if ((hw->phy.type >= e1000_phy_i217) && - adapter->eee_advert && hw->dev_spec.ich8lan.eee_lp_ability) { - u16 lpi_ctrl = 0; - - retval = hw->phy.ops.acquire(hw); - if (!retval) { - retval = e1e_rphy_locked(hw, I82579_LPI_CTRL, - &lpi_ctrl); - if (!retval) { - if (adapter->eee_advert & - hw->dev_spec.ich8lan.eee_lp_ability & - I82579_EEE_100_SUPPORTED) - lpi_ctrl |= I82579_LPI_CTRL_100_ENABLE; - if (adapter->eee_advert & - hw->dev_spec.ich8lan.eee_lp_ability & - I82579_EEE_1000_SUPPORTED) - lpi_ctrl |= I82579_LPI_CTRL_1000_ENABLE; - - retval = e1e_wphy_locked(hw, I82579_LPI_CTRL, - lpi_ctrl); - } - } - hw->phy.ops.release(hw); - } - - /* Release control of h/w to f/w. If f/w is AMT enabled, this - * would have already happened in close and is redundant. - */ - e1000e_release_hw_control(adapter); - - pci_clear_master(pdev); - - /* The pci-e switch on some quad port adapters will report a - * correctable error when the MAC transitions from D0 to D3. To - * prevent this we need to mask off the correctable errors on the - * downstream port of the pci-e switch. - * - * We don't have the associated upstream bridge while assigning - * the PCI device into guest. For example, the KVM on power is - * one of the cases. - */ - if (adapter->flags & FLAG_IS_QUAD_PORT) { - struct pci_dev *us_dev = pdev->bus->self; - u16 devctl; - - if (!us_dev) - return 0; - - pcie_capability_read_word(us_dev, PCI_EXP_DEVCTL, &devctl); - pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, - (devctl & ~PCI_EXP_DEVCTL_CERE)); - - pci_save_state(pdev); - pci_prepare_to_sleep(pdev); - - pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, devctl); - } - - return 0; -} - -/** - * __e1000e_disable_aspm - Disable ASPM states - * @pdev: pointer to PCI device struct - * @state: bit-mask of ASPM states to disable - * @locked: indication if this context holds pci_bus_sem locked. - * - * Some devices *must* have certain ASPM states disabled per hardware errata. - **/ -static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state, int locked) -{ - struct pci_dev *parent = pdev->bus->self; - u16 aspm_dis_mask = 0; - u16 pdev_aspmc, parent_aspmc; - - switch (state) { - case PCIE_LINK_STATE_L0S: - case PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1: - aspm_dis_mask |= PCI_EXP_LNKCTL_ASPM_L0S; - /* fall-through - can't have L1 without L0s */ - case PCIE_LINK_STATE_L1: - aspm_dis_mask |= PCI_EXP_LNKCTL_ASPM_L1; - break; - default: - return; - } - - pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &pdev_aspmc); - pdev_aspmc &= PCI_EXP_LNKCTL_ASPMC; - - if (parent) { - pcie_capability_read_word(parent, PCI_EXP_LNKCTL, - &parent_aspmc); - parent_aspmc &= PCI_EXP_LNKCTL_ASPMC; - } - - /* Nothing to do if the ASPM states to be disabled already are */ - if (!(pdev_aspmc & aspm_dis_mask) && - (!parent || !(parent_aspmc & aspm_dis_mask))) - return; - - dev_info(&pdev->dev, "Disabling ASPM %s %s\n", - (aspm_dis_mask & pdev_aspmc & PCI_EXP_LNKCTL_ASPM_L0S) ? - "L0s" : "", - (aspm_dis_mask & pdev_aspmc & PCI_EXP_LNKCTL_ASPM_L1) ? - "L1" : ""); - -#ifdef CONFIG_PCIEASPM - if (locked) - pci_disable_link_state_locked(pdev, state); - else - pci_disable_link_state(pdev, state); - - /* Double-check ASPM control. If not disabled by the above, the - * BIOS is preventing that from happening (or CONFIG_PCIEASPM is - * not enabled); override by writing PCI config space directly. - */ - pcie_capability_read_word(pdev, PCI_EXP_LNKCTL, &pdev_aspmc); - pdev_aspmc &= PCI_EXP_LNKCTL_ASPMC; - - if (!(aspm_dis_mask & pdev_aspmc)) - return; -#endif - - /* Both device and parent should have the same ASPM setting. - * Disable ASPM in downstream component first and then upstream. - */ - pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, aspm_dis_mask); - - if (parent) - pcie_capability_clear_word(parent, PCI_EXP_LNKCTL, - aspm_dis_mask); -} - -/** - * e1000e_disable_aspm - Disable ASPM states. - * @pdev: pointer to PCI device struct - * @state: bit-mask of ASPM states to disable - * - * This function acquires the pci_bus_sem! - * Some devices *must* have certain ASPM states disabled per hardware errata. - **/ -static void e1000e_disable_aspm(struct pci_dev *pdev, u16 state) -{ - __e1000e_disable_aspm(pdev, state, 0); -} - -/** - * e1000e_disable_aspm_locked Disable ASPM states. - * @pdev: pointer to PCI device struct - * @state: bit-mask of ASPM states to disable - * - * This function must be called with pci_bus_sem acquired! - * Some devices *must* have certain ASPM states disabled per hardware errata. - **/ -static void e1000e_disable_aspm_locked(struct pci_dev *pdev, u16 state) -{ - __e1000e_disable_aspm(pdev, state, 1); -} - -#ifdef CONFIG_PM -static int __e1000_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 aspm_disable_flag = 0; - - if (adapter->flags2 & FLAG2_DISABLE_ASPM_L0S) - aspm_disable_flag = PCIE_LINK_STATE_L0S; - if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) - aspm_disable_flag |= PCIE_LINK_STATE_L1; - if (aspm_disable_flag) - e1000e_disable_aspm(pdev, aspm_disable_flag); - - pci_set_master(pdev); - - if (hw->mac.type >= e1000_pch2lan) - e1000_resume_workarounds_pchlan(&adapter->hw); - - e1000e_power_up_phy(adapter); - - /* report the system wakeup cause from S3/S4 */ - if (adapter->flags2 & FLAG2_HAS_PHY_WAKEUP) { - u16 phy_data; - - e1e_rphy(&adapter->hw, BM_WUS, &phy_data); - if (phy_data) { - e_info("PHY Wakeup cause - %s\n", - phy_data & E1000_WUS_EX ? "Unicast Packet" : - phy_data & E1000_WUS_MC ? "Multicast Packet" : - phy_data & E1000_WUS_BC ? "Broadcast Packet" : - phy_data & E1000_WUS_MAG ? "Magic Packet" : - phy_data & E1000_WUS_LNKC ? - "Link Status Change" : "other"); - } - e1e_wphy(&adapter->hw, BM_WUS, ~0); - } else { - u32 wus = er32(WUS); - - if (wus) { - e_info("MAC Wakeup cause - %s\n", - wus & E1000_WUS_EX ? "Unicast Packet" : - wus & E1000_WUS_MC ? "Multicast Packet" : - wus & E1000_WUS_BC ? "Broadcast Packet" : - wus & E1000_WUS_MAG ? "Magic Packet" : - wus & E1000_WUS_LNKC ? "Link Status Change" : - "other"); - } - ew32(WUS, ~0); - } - - e1000e_reset(adapter); - - e1000_init_manageability_pt(adapter); - - /* If the controller has AMT, do not set DRV_LOAD until the interface - * is up. For all other cases, let the f/w know that the h/w is now - * under the control of the driver. - */ - if (!(adapter->flags & FLAG_HAS_AMT)) - e1000e_get_hw_control(adapter); - - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int e1000e_pm_thaw(struct device *dev) -{ - struct net_device *netdev = pci_get_drvdata(to_pci_dev(dev)); - struct e1000_adapter *adapter = netdev_priv(netdev); - - e1000e_set_interrupt_capability(adapter); - if (netif_running(netdev)) { - u32 err = e1000_request_irq(adapter); - - if (err) - return err; - - e1000e_up(adapter); - } - - netif_device_attach(netdev); - - return 0; -} - -static int e1000e_pm_suspend(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - int rc; - - e1000e_flush_lpic(pdev); - - e1000e_pm_freeze(dev); - - rc = __e1000_shutdown(pdev, false); - if (rc) - e1000e_pm_thaw(dev); - - return rc; -} - -static int e1000e_pm_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - int rc; - - rc = __e1000_resume(pdev); - if (rc) - return rc; - - return e1000e_pm_thaw(dev); -} -#endif /* CONFIG_PM_SLEEP */ - -static int e1000e_pm_runtime_idle(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - u16 eee_lp; - - eee_lp = adapter->hw.dev_spec.ich8lan.eee_lp_ability; - - if (!e1000e_has_link(adapter)) { - adapter->hw.dev_spec.ich8lan.eee_lp_ability = eee_lp; - pm_schedule_suspend(dev, 5 * MSEC_PER_SEC); - } - - return -EBUSY; -} - -static int e1000e_pm_runtime_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - int rc; - - rc = __e1000_resume(pdev); - if (rc) - return rc; - - if (netdev->flags & IFF_UP) - rc = e1000e_up(adapter); - - return rc; -} - -static int e1000e_pm_runtime_suspend(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (netdev->flags & IFF_UP) { - int count = E1000_CHECK_RESET_COUNT; - - while (test_bit(__E1000_RESETTING, &adapter->state) && count--) - usleep_range(10000, 20000); - - WARN_ON(test_bit(__E1000_RESETTING, &adapter->state)); - - /* Down the device without resetting the hardware */ - e1000e_down(adapter, false); - } - - if (__e1000_shutdown(pdev, true)) { - e1000e_pm_runtime_resume(dev); - return -EBUSY; - } - - return 0; -} -#endif /* CONFIG_PM */ - -static void e1000_shutdown(struct pci_dev *pdev) -{ - e1000e_flush_lpic(pdev); - - e1000e_pm_freeze(&pdev->dev); - - __e1000_shutdown(pdev, false); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER - -static irqreturn_t e1000_intr_msix(int __always_unused irq, void *data) -{ - struct net_device *netdev = data; - struct e1000_adapter *adapter = netdev_priv(netdev); - - if (adapter->msix_entries) { - int vector, msix_irq; - - vector = 0; - msix_irq = adapter->msix_entries[vector].vector; - disable_irq(msix_irq); - e1000_intr_msix_rx(msix_irq, netdev); - enable_irq(msix_irq); - - vector++; - msix_irq = adapter->msix_entries[vector].vector; - disable_irq(msix_irq); - e1000_intr_msix_tx(msix_irq, netdev); - enable_irq(msix_irq); - - vector++; - msix_irq = adapter->msix_entries[vector].vector; - disable_irq(msix_irq); - e1000_msix_other(msix_irq, netdev); - enable_irq(msix_irq); - } - - return IRQ_HANDLED; -} - -/** - * e1000_netpoll - * @netdev: network interface device structure - * - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void e1000_netpoll(struct net_device *netdev) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - - switch (adapter->int_mode) { - case E1000E_INT_MODE_MSIX: - e1000_intr_msix(adapter->pdev->irq, netdev); - break; - case E1000E_INT_MODE_MSI: - disable_irq(adapter->pdev->irq); - e1000_intr_msi(adapter->pdev->irq, netdev); - enable_irq(adapter->pdev->irq); - break; - default: /* E1000E_INT_MODE_LEGACY */ - disable_irq(adapter->pdev->irq); - e1000_intr(adapter->pdev->irq, netdev); - enable_irq(adapter->pdev->irq); - break; - } -} -#endif - -/** - * e1000_io_error_detected - called when PCI error is detected - * @pdev: Pointer to PCI device - * @state: The current pci connection state - * - * This function is called after a PCI bus error affecting - * this device has been detected. - */ -static pci_ers_result_t e1000_io_error_detected(struct pci_dev *pdev, - pci_channel_state_t state) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - - netif_device_detach(netdev); - - if (state == pci_channel_io_perm_failure) - return PCI_ERS_RESULT_DISCONNECT; - - if (netif_running(netdev)) - e1000e_down(adapter, true); - pci_disable_device(pdev); - - /* Request a slot slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * e1000_io_slot_reset - called after the pci bus has been reset. - * @pdev: Pointer to PCI device - * - * Restart the card from scratch, as if from a cold-boot. Implementation - * resembles the first-half of the e1000e_pm_resume routine. - */ -static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - u16 aspm_disable_flag = 0; - int err; - pci_ers_result_t result; - - if (adapter->flags2 & FLAG2_DISABLE_ASPM_L0S) - aspm_disable_flag = PCIE_LINK_STATE_L0S; - if (adapter->flags2 & FLAG2_DISABLE_ASPM_L1) - aspm_disable_flag |= PCIE_LINK_STATE_L1; - if (aspm_disable_flag) - e1000e_disable_aspm_locked(pdev, aspm_disable_flag); - - err = pci_enable_device_mem(pdev); - if (err) { - dev_err(&pdev->dev, - "Cannot re-enable PCI device after reset.\n"); - result = PCI_ERS_RESULT_DISCONNECT; - } else { - pdev->state_saved = true; - pci_restore_state(pdev); - pci_set_master(pdev); - - pci_enable_wake(pdev, PCI_D3hot, 0); - pci_enable_wake(pdev, PCI_D3cold, 0); - - e1000e_reset(adapter); - ew32(WUS, ~0); - result = PCI_ERS_RESULT_RECOVERED; - } - - pci_cleanup_aer_uncorrect_error_status(pdev); - - return result; -} - -/** - * e1000_io_resume - called when traffic can start flowing again. - * @pdev: Pointer to PCI device - * - * This callback is called when the error recovery driver tells us that - * its OK to resume normal operation. Implementation resembles the - * second-half of the e1000e_pm_resume routine. - */ -static void e1000_io_resume(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - - e1000_init_manageability_pt(adapter); - - if (netif_running(netdev)) { - if (e1000e_up(adapter)) { - dev_err(&pdev->dev, - "can't bring device back up after reset\n"); - return; - } - } - - netif_device_attach(netdev); - - /* If the controller has AMT, do not set DRV_LOAD until the interface - * is up. For all other cases, let the f/w know that the h/w is now - * under the control of the driver. - */ - if (!(adapter->flags & FLAG_HAS_AMT)) - e1000e_get_hw_control(adapter); -} - -static void e1000_print_device_info(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - struct net_device *netdev = adapter->netdev; - u32 ret_val; - u8 pba_str[E1000_PBANUM_LENGTH]; - - /* print bus type/speed/width info */ - e_info("(PCI Express:2.5GT/s:%s) %pM\n", - /* bus width */ - ((hw->bus.width == e1000_bus_width_pcie_x4) ? "Width x4" : - "Width x1"), - /* MAC address */ - netdev->dev_addr); - e_info("Intel(R) PRO/%s Network Connection\n", - (hw->phy.type == e1000_phy_ife) ? "10/100" : "1000"); - ret_val = e1000_read_pba_string_generic(hw, pba_str, - E1000_PBANUM_LENGTH); - if (ret_val) - strlcpy((char *)pba_str, "Unknown", sizeof(pba_str)); - e_info("MAC: %d, PHY: %d, PBA No: %s\n", - hw->mac.type, hw->phy.type, pba_str); -} - -static void e1000_eeprom_checks(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - int ret_val; - u16 buf = 0; - - if (hw->mac.type != e1000_82573) - return; - - ret_val = e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &buf); - le16_to_cpus(&buf); - if (!ret_val && (!(buf & (1 << 0)))) { - /* Deep Smart Power Down (DSPD) */ - dev_warn(&adapter->pdev->dev, - "Warning: detected DSPD enabled in EEPROM\n"); - } -} - -static netdev_features_t e1000_fix_features(struct net_device *netdev, - netdev_features_t features) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - struct e1000_hw *hw = &adapter->hw; - - /* Jumbo frame workaround on 82579 and newer requires CRC be stripped */ - if ((hw->mac.type >= e1000_pch2lan) && (netdev->mtu > ETH_DATA_LEN)) - features &= ~NETIF_F_RXFCS; - - return features; -} - -static int e1000_set_features(struct net_device *netdev, - netdev_features_t features) -{ - struct e1000_adapter *adapter = netdev_priv(netdev); - netdev_features_t changed = features ^ netdev->features; - - if (changed & (NETIF_F_TSO | NETIF_F_TSO6)) - adapter->flags |= FLAG_TSO_FORCE; - - if (!(changed & (NETIF_F_HW_VLAN_CTAG_RX | NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_RXCSUM | NETIF_F_RXHASH | NETIF_F_RXFCS | - NETIF_F_RXALL))) - return 0; - - if (changed & NETIF_F_RXFCS) { - if (features & NETIF_F_RXFCS) { - adapter->flags2 &= ~FLAG2_CRC_STRIPPING; - } else { - /* We need to take it back to defaults, which might mean - * stripping is still disabled at the adapter level. - */ - if (adapter->flags2 & FLAG2_DFLT_CRC_STRIPPING) - adapter->flags2 |= FLAG2_CRC_STRIPPING; - else - adapter->flags2 &= ~FLAG2_CRC_STRIPPING; - } - } - - netdev->features = features; - - if (netif_running(netdev)) - e1000e_reinit_locked(adapter); - else - e1000e_reset(adapter); - - return 0; -} - -static const struct net_device_ops e1000e_netdev_ops = { - .ndo_open = e1000_open, - .ndo_stop = e1000_close, - .ndo_start_xmit = e1000_xmit_frame, - .ndo_get_stats64 = e1000e_get_stats64, - .ndo_set_rx_mode = e1000e_set_rx_mode, - .ndo_set_mac_address = e1000_set_mac, - .ndo_change_mtu = e1000_change_mtu, - .ndo_do_ioctl = e1000_ioctl, - .ndo_tx_timeout = e1000_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - - .ndo_vlan_rx_add_vid = e1000_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = e1000_vlan_rx_kill_vid, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = e1000_netpoll, -#endif - .ndo_set_features = e1000_set_features, - .ndo_fix_features = e1000_fix_features, - .ndo_features_check = passthru_features_check, -}; - -/** - * e1000_probe - Device Initialization Routine - * @pdev: PCI device information struct - * @ent: entry in e1000_pci_tbl - * - * Returns 0 on success, negative on failure - * - * e1000_probe initializes an adapter identified by a pci_dev structure. - * The OS initialization, configuring of the adapter private structure, - * and a hardware reset occur. - **/ -static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct net_device *netdev; - struct e1000_adapter *adapter; - struct e1000_hw *hw; - const struct e1000_info *ei = e1000_info_tbl[ent->driver_data]; - resource_size_t mmio_start, mmio_len; - resource_size_t flash_start, flash_len; - static int cards_found; - u16 aspm_disable_flag = 0; - int bars, i, err, pci_using_dac; - u16 eeprom_data = 0; - u16 eeprom_apme_mask = E1000_EEPROM_APME; - s32 rval = 0; - - if (ei->flags2 & FLAG2_DISABLE_ASPM_L0S) - aspm_disable_flag = PCIE_LINK_STATE_L0S; - if (ei->flags2 & FLAG2_DISABLE_ASPM_L1) - aspm_disable_flag |= PCIE_LINK_STATE_L1; - if (aspm_disable_flag) - e1000e_disable_aspm(pdev, aspm_disable_flag); - - err = pci_enable_device_mem(pdev); - if (err) - return err; - - pci_using_dac = 0; - err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)); - if (!err) { - pci_using_dac = 1; - } else { - err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); - if (err) { - dev_err(&pdev->dev, - "No usable DMA configuration, aborting\n"); - goto err_dma; - } - } - - bars = pci_select_bars(pdev, IORESOURCE_MEM); - err = pci_request_selected_regions_exclusive(pdev, bars, - e1000e_driver_name); - if (err) - goto err_pci_reg; - - /* AER (Advanced Error Reporting) hooks */ - pci_enable_pcie_error_reporting(pdev); - - pci_set_master(pdev); - /* PCI config space info */ - err = pci_save_state(pdev); - if (err) - goto err_alloc_etherdev; - - err = -ENOMEM; - netdev = alloc_etherdev(sizeof(struct e1000_adapter)); - if (!netdev) - goto err_alloc_etherdev; - - SET_NETDEV_DEV(netdev, &pdev->dev); - - netdev->irq = pdev->irq; - - pci_set_drvdata(pdev, netdev); - adapter = netdev_priv(netdev); - hw = &adapter->hw; - adapter->netdev = netdev; - adapter->pdev = pdev; - adapter->ei = ei; - adapter->pba = ei->pba; - adapter->flags = ei->flags; - adapter->flags2 = ei->flags2; - adapter->hw.adapter = adapter; - adapter->hw.mac.type = ei->mac; - adapter->max_hw_frame_size = ei->max_hw_frame_size; - adapter->msg_enable = netif_msg_init(debug, DEFAULT_MSG_ENABLE); - - mmio_start = pci_resource_start(pdev, 0); - mmio_len = pci_resource_len(pdev, 0); - - err = -EIO; - adapter->hw.hw_addr = ioremap(mmio_start, mmio_len); - if (!adapter->hw.hw_addr) - goto err_ioremap; - - if ((adapter->flags & FLAG_HAS_FLASH) && - (pci_resource_flags(pdev, 1) & IORESOURCE_MEM) && - (hw->mac.type < e1000_pch_spt)) { - flash_start = pci_resource_start(pdev, 1); - flash_len = pci_resource_len(pdev, 1); - adapter->hw.flash_address = ioremap(flash_start, flash_len); - if (!adapter->hw.flash_address) - goto err_flashmap; - } - - /* Set default EEE advertisement */ - if (adapter->flags2 & FLAG2_HAS_EEE) - adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T; - - /* construct the net_device struct */ - netdev->netdev_ops = &e1000e_netdev_ops; - e1000e_set_ethtool_ops(netdev); - netdev->watchdog_timeo = 5 * HZ; - netif_napi_add(netdev, &adapter->napi, e1000e_poll, 64); - strlcpy(netdev->name, pci_name(pdev), sizeof(netdev->name)); - - netdev->mem_start = mmio_start; - netdev->mem_end = mmio_start + mmio_len; - - adapter->bd_number = cards_found++; - - e1000e_check_options(adapter); - - /* setup adapter struct */ - err = e1000_sw_init(adapter); - if (err) - goto err_sw_init; - - memcpy(&hw->mac.ops, ei->mac_ops, sizeof(hw->mac.ops)); - memcpy(&hw->nvm.ops, ei->nvm_ops, sizeof(hw->nvm.ops)); - memcpy(&hw->phy.ops, ei->phy_ops, sizeof(hw->phy.ops)); - - err = ei->get_variants(adapter); - if (err) - goto err_hw_init; - - if ((adapter->flags & FLAG_IS_ICH) && - (adapter->flags & FLAG_READ_ONLY_NVM) && - (hw->mac.type < e1000_pch_spt)) - e1000e_write_protect_nvm_ich8lan(&adapter->hw); - - hw->mac.ops.get_bus_info(&adapter->hw); - - adapter->hw.phy.autoneg_wait_to_complete = 0; - - /* Copper options */ - if (adapter->hw.phy.media_type == e1000_media_type_copper) { - adapter->hw.phy.mdix = AUTO_ALL_MODES; - adapter->hw.phy.disable_polarity_correction = 0; - adapter->hw.phy.ms_type = e1000_ms_hw_default; - } - - if (hw->phy.ops.check_reset_block && hw->phy.ops.check_reset_block(hw)) - dev_info(&pdev->dev, - "PHY reset is blocked due to SOL/IDER session.\n"); - - /* Set initial default active device features */ - netdev->features = (NETIF_F_SG | - NETIF_F_HW_VLAN_CTAG_RX | - NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_TSO | - NETIF_F_TSO6 | - NETIF_F_RXHASH | - NETIF_F_RXCSUM | - NETIF_F_HW_CSUM); - - /* Set user-changeable features (subset of all device features) */ - netdev->hw_features = netdev->features; - netdev->hw_features |= NETIF_F_RXFCS; - netdev->priv_flags |= IFF_SUPP_NOFCS; - netdev->hw_features |= NETIF_F_RXALL; - - if (adapter->flags & FLAG_HAS_HW_VLAN_FILTER) - netdev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; - - netdev->vlan_features |= (NETIF_F_SG | - NETIF_F_TSO | - NETIF_F_TSO6 | - NETIF_F_HW_CSUM); - - netdev->priv_flags |= IFF_UNICAST_FLT; - - if (pci_using_dac) { - netdev->features |= NETIF_F_HIGHDMA; - netdev->vlan_features |= NETIF_F_HIGHDMA; - } - - if (e1000e_enable_mng_pass_thru(&adapter->hw)) - adapter->flags |= FLAG_MNG_PT_ENABLED; - - /* before reading the NVM, reset the controller to - * put the device in a known good starting state - */ - adapter->hw.mac.ops.reset_hw(&adapter->hw); - - /* systems with ASPM and others may see the checksum fail on the first - * attempt. Let's give it a few tries - */ - for (i = 0;; i++) { - if (e1000_validate_nvm_checksum(&adapter->hw) >= 0) - break; - if (i == 2) { - dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n"); - err = -EIO; - goto err_eeprom; - } - } - - e1000_eeprom_checks(adapter); - - /* copy the MAC address */ - if (e1000e_read_mac_addr(&adapter->hw)) - dev_err(&pdev->dev, - "NVM Read Error while reading MAC address\n"); - - memcpy(netdev->dev_addr, adapter->hw.mac.addr, netdev->addr_len); - - if (!is_valid_ether_addr(netdev->dev_addr)) { - dev_err(&pdev->dev, "Invalid MAC Address: %pM\n", - netdev->dev_addr); - err = -EIO; - goto err_eeprom; - } - - init_timer(&adapter->watchdog_timer); - adapter->watchdog_timer.function = e1000_watchdog; - adapter->watchdog_timer.data = (unsigned long)adapter; - - init_timer(&adapter->phy_info_timer); - adapter->phy_info_timer.function = e1000_update_phy_info; - adapter->phy_info_timer.data = (unsigned long)adapter; - - INIT_WORK(&adapter->reset_task, e1000_reset_task); - INIT_WORK(&adapter->watchdog_task, e1000_watchdog_task); - INIT_WORK(&adapter->downshift_task, e1000e_downshift_workaround); - INIT_WORK(&adapter->update_phy_task, e1000e_update_phy_task); - INIT_WORK(&adapter->print_hang_task, e1000_print_hw_hang); - - /* Initialize link parameters. User can change them with ethtool */ - adapter->hw.mac.autoneg = 1; - adapter->fc_autoneg = true; - adapter->hw.fc.requested_mode = e1000_fc_default; - adapter->hw.fc.current_mode = e1000_fc_default; - adapter->hw.phy.autoneg_advertised = 0x2f; - - /* Initial Wake on LAN setting - If APM wake is enabled in - * the EEPROM, enable the ACPI Magic Packet filter - */ - if (adapter->flags & FLAG_APME_IN_WUC) { - /* APME bit in EEPROM is mapped to WUC.APME */ - eeprom_data = er32(WUC); - eeprom_apme_mask = E1000_WUC_APME; - if ((hw->mac.type > e1000_ich10lan) && - (eeprom_data & E1000_WUC_PHY_WAKE)) - adapter->flags2 |= FLAG2_HAS_PHY_WAKEUP; - } else if (adapter->flags & FLAG_APME_IN_CTRL3) { - if (adapter->flags & FLAG_APME_CHECK_PORT_B && - (adapter->hw.bus.func == 1)) - rval = e1000_read_nvm(&adapter->hw, - NVM_INIT_CONTROL3_PORT_B, - 1, &eeprom_data); - else - rval = e1000_read_nvm(&adapter->hw, - NVM_INIT_CONTROL3_PORT_A, - 1, &eeprom_data); - } - - /* fetch WoL from EEPROM */ - if (rval) - e_dbg("NVM read error getting WoL initial values: %d\n", rval); - else if (eeprom_data & eeprom_apme_mask) - adapter->eeprom_wol |= E1000_WUFC_MAG; - - /* now that we have the eeprom settings, apply the special cases - * where the eeprom may be wrong or the board simply won't support - * wake on lan on a particular port - */ - if (!(adapter->flags & FLAG_HAS_WOL)) - adapter->eeprom_wol = 0; - - /* initialize the wol settings based on the eeprom settings */ - adapter->wol = adapter->eeprom_wol; - - /* make sure adapter isn't asleep if manageability is enabled */ - if (adapter->wol || (adapter->flags & FLAG_MNG_PT_ENABLED) || - (hw->mac.ops.check_mng_mode(hw))) - device_wakeup_enable(&pdev->dev); - - /* save off EEPROM version number */ - rval = e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers); - - if (rval) { - e_dbg("NVM read error getting EEPROM version: %d\n", rval); - adapter->eeprom_vers = 0; - } - - /* reset the hardware with the new settings */ - e1000e_reset(adapter); - - /* If the controller has AMT, do not set DRV_LOAD until the interface - * is up. For all other cases, let the f/w know that the h/w is now - * under the control of the driver. - */ - if (!(adapter->flags & FLAG_HAS_AMT)) - e1000e_get_hw_control(adapter); - - strlcpy(netdev->name, "eth%d", sizeof(netdev->name)); - err = register_netdev(netdev); - if (err) - goto err_register; - - /* carrier off reporting is important to ethtool even BEFORE open */ - netif_carrier_off(netdev); - - /* init PTP hardware clock */ - e1000e_ptp_init(adapter); - - e1000_print_device_info(adapter); - - if (pci_dev_run_wake(pdev)) - pm_runtime_put_noidle(&pdev->dev); - - return 0; - -err_register: - if (!(adapter->flags & FLAG_HAS_AMT)) - e1000e_release_hw_control(adapter); -err_eeprom: - if (hw->phy.ops.check_reset_block && !hw->phy.ops.check_reset_block(hw)) - e1000_phy_hw_reset(&adapter->hw); -err_hw_init: - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); -err_sw_init: - if ((adapter->hw.flash_address) && (hw->mac.type < e1000_pch_spt)) - iounmap(adapter->hw.flash_address); - e1000e_reset_interrupt_capability(adapter); -err_flashmap: - iounmap(adapter->hw.hw_addr); -err_ioremap: - free_netdev(netdev); -err_alloc_etherdev: - pci_release_selected_regions(pdev, - pci_select_bars(pdev, IORESOURCE_MEM)); -err_pci_reg: -err_dma: - pci_disable_device(pdev); - return err; -} - -/** - * e1000_remove - Device Removal Routine - * @pdev: PCI device information struct - * - * e1000_remove is called by the PCI subsystem to alert the driver - * that it should release a PCI device. The could be caused by a - * Hot-Plug event, or because the driver is going to be removed from - * memory. - **/ -static void e1000_remove(struct pci_dev *pdev) -{ - struct net_device *netdev = pci_get_drvdata(pdev); - struct e1000_adapter *adapter = netdev_priv(netdev); - bool down = test_bit(__E1000_DOWN, &adapter->state); - - e1000e_ptp_remove(adapter); - - /* The timers may be rescheduled, so explicitly disable them - * from being rescheduled. - */ - if (!down) - set_bit(__E1000_DOWN, &adapter->state); - del_timer_sync(&adapter->watchdog_timer); - del_timer_sync(&adapter->phy_info_timer); - - cancel_work_sync(&adapter->reset_task); - cancel_work_sync(&adapter->watchdog_task); - cancel_work_sync(&adapter->downshift_task); - cancel_work_sync(&adapter->update_phy_task); - cancel_work_sync(&adapter->print_hang_task); - - if (adapter->flags & FLAG_HAS_HW_TIMESTAMP) { - cancel_work_sync(&adapter->tx_hwtstamp_work); - if (adapter->tx_hwtstamp_skb) { - dev_kfree_skb_any(adapter->tx_hwtstamp_skb); - adapter->tx_hwtstamp_skb = NULL; - } - } - - /* Don't lie to e1000_close() down the road. */ - if (!down) - clear_bit(__E1000_DOWN, &adapter->state); - unregister_netdev(netdev); - - if (pci_dev_run_wake(pdev)) - pm_runtime_get_noresume(&pdev->dev); - - /* Release control of h/w to f/w. If f/w is AMT enabled, this - * would have already happened in close and is redundant. - */ - e1000e_release_hw_control(adapter); - - e1000e_reset_interrupt_capability(adapter); - kfree(adapter->tx_ring); - kfree(adapter->rx_ring); - - iounmap(adapter->hw.hw_addr); - if ((adapter->hw.flash_address) && - (adapter->hw.mac.type < e1000_pch_spt)) - iounmap(adapter->hw.flash_address); - pci_release_selected_regions(pdev, - pci_select_bars(pdev, IORESOURCE_MEM)); - - free_netdev(netdev); - - /* AER disable */ - pci_disable_pcie_error_reporting(pdev); - - pci_disable_device(pdev); -} - -/* PCI Error Recovery (ERS) */ -static const struct pci_error_handlers e1000_err_handler = { - .error_detected = e1000_io_error_detected, - .slot_reset = e1000_io_slot_reset, - .resume = e1000_io_resume, -}; - -static const struct pci_device_id e1000_pci_tbl[] = { - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_COPPER), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_FIBER), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_COPPER_LP), - board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_QUAD_FIBER), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_DUAL), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571EB_SERDES_QUAD), board_82571 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82571PT_QUAD_COPPER), board_82571 }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI), board_82572 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_COPPER), board_82572 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_FIBER), board_82572 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82572EI_SERDES), board_82572 }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573E), board_82573 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573E_IAMT), board_82573 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82573L), board_82573 }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82574L), board_82574 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82574LA), board_82574 }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_82583V), board_82583 }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_DPT), - board_80003es2lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_COPPER_SPT), - board_80003es2lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_SERDES_DPT), - board_80003es2lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_80003ES2LAN_SERDES_SPT), - board_80003es2lan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE_G), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IFE_GT), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_AMT), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_C), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_IGP_M_AMT), board_ich8lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH8_82567V_3), board_ich8lan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_G), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IFE_GT), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_AMT), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_C), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_BM), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_AMT), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH9_IGP_M_V), board_ich9lan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LM), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_LF), board_ich9lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_R_BM_V), board_ich9lan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LM), board_ich10lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_LF), board_ich10lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_ICH10_D_BM_V), board_ich10lan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LM), board_pchlan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_M_HV_LC), board_pchlan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DM), board_pchlan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DC), board_pchlan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_LM), board_pch2lan }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_V), board_pch2lan }, - - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_LM), board_pch_lpt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPT_I217_V), board_pch_lpt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPTLP_I218_LM), board_pch_lpt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_LPTLP_I218_V), board_pch_lpt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_LM2), board_pch_lpt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_V2), board_pch_lpt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_LM3), board_pch_lpt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_I218_V3), board_pch_lpt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_LM), board_pch_spt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_V), board_pch_spt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_LM2), board_pch_spt }, - { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_SPT_I219_V2), board_pch_spt }, - - { 0, 0, 0, 0, 0, 0, 0 } /* terminate list */ -}; -MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); - -static const struct dev_pm_ops e1000_pm_ops = { -#ifdef CONFIG_PM_SLEEP - .suspend = e1000e_pm_suspend, - .resume = e1000e_pm_resume, - .freeze = e1000e_pm_freeze, - .thaw = e1000e_pm_thaw, - .poweroff = e1000e_pm_suspend, - .restore = e1000e_pm_resume, -#endif - SET_RUNTIME_PM_OPS(e1000e_pm_runtime_suspend, e1000e_pm_runtime_resume, - e1000e_pm_runtime_idle) -}; - -/* PCI Device API Driver */ -static struct pci_driver e1000_driver = { - .name = e1000e_driver_name, - .id_table = e1000_pci_tbl, - .probe = e1000_probe, - .remove = e1000_remove, - .driver = { - .pm = &e1000_pm_ops, - }, - .shutdown = e1000_shutdown, - .err_handler = &e1000_err_handler -}; - -/** - * e1000_init_module - Driver Registration Routine - * - * e1000_init_module is the first routine called when the driver is - * loaded. All it does is register with the PCI subsystem. - **/ -static int __init e1000_init_module(void) -{ - int ret; - - pr_info("Intel(R) PRO/1000 Network Driver - %s\n", - e1000e_driver_version); - pr_info("Copyright(c) 1999 - 2015 Intel Corporation.\n"); - ret = pci_register_driver(&e1000_driver); - - return ret; -} -module_init(e1000_init_module); - -/** - * e1000_exit_module - Driver Exit Cleanup Routine - * - * e1000_exit_module is called just before the driver is removed - * from memory. - **/ -static void __exit e1000_exit_module(void) -{ - pci_unregister_driver(&e1000_driver); -} -module_exit(e1000_exit_module); - -MODULE_AUTHOR("Intel Corporation, "); -MODULE_DESCRIPTION("Intel(R) PRO/1000 Network Driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -/* netdev.c */ diff --git a/addons/e1000e/src/4.4.180/nvm.c b/addons/e1000e/src/4.4.180/nvm.c deleted file mode 100644 index 49f205c0..00000000 --- a/addons/e1000e/src/4.4.180/nvm.c +++ /dev/null @@ -1,633 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#include "e1000.h" - -/** - * e1000_raise_eec_clk - Raise EEPROM clock - * @hw: pointer to the HW structure - * @eecd: pointer to the EEPROM - * - * Enable/Raise the EEPROM clock bit. - **/ -static void e1000_raise_eec_clk(struct e1000_hw *hw, u32 *eecd) -{ - *eecd = *eecd | E1000_EECD_SK; - ew32(EECD, *eecd); - e1e_flush(); - udelay(hw->nvm.delay_usec); -} - -/** - * e1000_lower_eec_clk - Lower EEPROM clock - * @hw: pointer to the HW structure - * @eecd: pointer to the EEPROM - * - * Clear/Lower the EEPROM clock bit. - **/ -static void e1000_lower_eec_clk(struct e1000_hw *hw, u32 *eecd) -{ - *eecd = *eecd & ~E1000_EECD_SK; - ew32(EECD, *eecd); - e1e_flush(); - udelay(hw->nvm.delay_usec); -} - -/** - * e1000_shift_out_eec_bits - Shift data bits our to the EEPROM - * @hw: pointer to the HW structure - * @data: data to send to the EEPROM - * @count: number of bits to shift out - * - * We need to shift 'count' bits out to the EEPROM. So, the value in the - * "data" parameter will be shifted out to the EEPROM one bit at a time. - * In order to do this, "data" must be broken down into bits. - **/ -static void e1000_shift_out_eec_bits(struct e1000_hw *hw, u16 data, u16 count) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - u32 mask; - - mask = 0x01 << (count - 1); - if (nvm->type == e1000_nvm_eeprom_spi) - eecd |= E1000_EECD_DO; - - do { - eecd &= ~E1000_EECD_DI; - - if (data & mask) - eecd |= E1000_EECD_DI; - - ew32(EECD, eecd); - e1e_flush(); - - udelay(nvm->delay_usec); - - e1000_raise_eec_clk(hw, &eecd); - e1000_lower_eec_clk(hw, &eecd); - - mask >>= 1; - } while (mask); - - eecd &= ~E1000_EECD_DI; - ew32(EECD, eecd); -} - -/** - * e1000_shift_in_eec_bits - Shift data bits in from the EEPROM - * @hw: pointer to the HW structure - * @count: number of bits to shift in - * - * In order to read a register from the EEPROM, we need to shift 'count' bits - * in from the EEPROM. Bits are "shifted in" by raising the clock input to - * the EEPROM (setting the SK bit), and then reading the value of the data out - * "DO" bit. During this "shifting in" process the data in "DI" bit should - * always be clear. - **/ -static u16 e1000_shift_in_eec_bits(struct e1000_hw *hw, u16 count) -{ - u32 eecd; - u32 i; - u16 data; - - eecd = er32(EECD); - eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); - data = 0; - - for (i = 0; i < count; i++) { - data <<= 1; - e1000_raise_eec_clk(hw, &eecd); - - eecd = er32(EECD); - - eecd &= ~E1000_EECD_DI; - if (eecd & E1000_EECD_DO) - data |= 1; - - e1000_lower_eec_clk(hw, &eecd); - } - - return data; -} - -/** - * e1000e_poll_eerd_eewr_done - Poll for EEPROM read/write completion - * @hw: pointer to the HW structure - * @ee_reg: EEPROM flag for polling - * - * Polls the EEPROM status bit for either read or write completion based - * upon the value of 'ee_reg'. - **/ -s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg) -{ - u32 attempts = 100000; - u32 i, reg = 0; - - for (i = 0; i < attempts; i++) { - if (ee_reg == E1000_NVM_POLL_READ) - reg = er32(EERD); - else - reg = er32(EEWR); - - if (reg & E1000_NVM_RW_REG_DONE) - return 0; - - udelay(5); - } - - return -E1000_ERR_NVM; -} - -/** - * e1000e_acquire_nvm - Generic request for access to EEPROM - * @hw: pointer to the HW structure - * - * Set the EEPROM access request bit and wait for EEPROM access grant bit. - * Return successful if access grant bit set, else clear the request for - * EEPROM access and return -E1000_ERR_NVM (-1). - **/ -s32 e1000e_acquire_nvm(struct e1000_hw *hw) -{ - u32 eecd = er32(EECD); - s32 timeout = E1000_NVM_GRANT_ATTEMPTS; - - ew32(EECD, eecd | E1000_EECD_REQ); - eecd = er32(EECD); - - while (timeout) { - if (eecd & E1000_EECD_GNT) - break; - udelay(5); - eecd = er32(EECD); - timeout--; - } - - if (!timeout) { - eecd &= ~E1000_EECD_REQ; - ew32(EECD, eecd); - e_dbg("Could not acquire NVM grant\n"); - return -E1000_ERR_NVM; - } - - return 0; -} - -/** - * e1000_standby_nvm - Return EEPROM to standby state - * @hw: pointer to the HW structure - * - * Return the EEPROM to a standby state. - **/ -static void e1000_standby_nvm(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - - if (nvm->type == e1000_nvm_eeprom_spi) { - /* Toggle CS to flush commands */ - eecd |= E1000_EECD_CS; - ew32(EECD, eecd); - e1e_flush(); - udelay(nvm->delay_usec); - eecd &= ~E1000_EECD_CS; - ew32(EECD, eecd); - e1e_flush(); - udelay(nvm->delay_usec); - } -} - -/** - * e1000_stop_nvm - Terminate EEPROM command - * @hw: pointer to the HW structure - * - * Terminates the current command by inverting the EEPROM's chip select pin. - **/ -static void e1000_stop_nvm(struct e1000_hw *hw) -{ - u32 eecd; - - eecd = er32(EECD); - if (hw->nvm.type == e1000_nvm_eeprom_spi) { - /* Pull CS high */ - eecd |= E1000_EECD_CS; - e1000_lower_eec_clk(hw, &eecd); - } -} - -/** - * e1000e_release_nvm - Release exclusive access to EEPROM - * @hw: pointer to the HW structure - * - * Stop any current commands to the EEPROM and clear the EEPROM request bit. - **/ -void e1000e_release_nvm(struct e1000_hw *hw) -{ - u32 eecd; - - e1000_stop_nvm(hw); - - eecd = er32(EECD); - eecd &= ~E1000_EECD_REQ; - ew32(EECD, eecd); -} - -/** - * e1000_ready_nvm_eeprom - Prepares EEPROM for read/write - * @hw: pointer to the HW structure - * - * Setups the EEPROM for reading and writing. - **/ -static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 eecd = er32(EECD); - u8 spi_stat_reg; - - if (nvm->type == e1000_nvm_eeprom_spi) { - u16 timeout = NVM_MAX_RETRY_SPI; - - /* Clear SK and CS */ - eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); - ew32(EECD, eecd); - e1e_flush(); - udelay(1); - - /* Read "Status Register" repeatedly until the LSB is cleared. - * The EEPROM will signal that the command has been completed - * by clearing bit 0 of the internal status register. If it's - * not cleared within 'timeout', then error out. - */ - while (timeout) { - e1000_shift_out_eec_bits(hw, NVM_RDSR_OPCODE_SPI, - hw->nvm.opcode_bits); - spi_stat_reg = (u8)e1000_shift_in_eec_bits(hw, 8); - if (!(spi_stat_reg & NVM_STATUS_RDY_SPI)) - break; - - udelay(5); - e1000_standby_nvm(hw); - timeout--; - } - - if (!timeout) { - e_dbg("SPI NVM Status error\n"); - return -E1000_ERR_NVM; - } - } - - return 0; -} - -/** - * e1000e_read_nvm_eerd - Reads EEPROM using EERD register - * @hw: pointer to the HW structure - * @offset: offset of word in the EEPROM to read - * @words: number of words to read - * @data: word read from the EEPROM - * - * Reads a 16 bit word from the EEPROM using the EERD register. - **/ -s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - u32 i, eerd = 0; - s32 ret_val = 0; - - /* A check for invalid values: offset too large, too many words, - * too many words for the offset, and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - return -E1000_ERR_NVM; - } - - for (i = 0; i < words; i++) { - eerd = ((offset + i) << E1000_NVM_RW_ADDR_SHIFT) + - E1000_NVM_RW_REG_START; - - ew32(EERD, eerd); - ret_val = e1000e_poll_eerd_eewr_done(hw, E1000_NVM_POLL_READ); - if (ret_val) { - e_dbg("NVM read error: %d\n", ret_val); - break; - } - - data[i] = (er32(EERD) >> E1000_NVM_RW_REG_DATA); - } - - return ret_val; -} - -/** - * e1000e_write_nvm_spi - Write to EEPROM using SPI - * @hw: pointer to the HW structure - * @offset: offset within the EEPROM to be written to - * @words: number of words to write - * @data: 16 bit word(s) to be written to the EEPROM - * - * Writes data to EEPROM at offset using SPI interface. - * - * If e1000e_update_nvm_checksum is not called after this function , the - * EEPROM will most likely contain an invalid checksum. - **/ -s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) -{ - struct e1000_nvm_info *nvm = &hw->nvm; - s32 ret_val = -E1000_ERR_NVM; - u16 widx = 0; - - /* A check for invalid values: offset too large, too many words, - * and not enough words. - */ - if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) || - (words == 0)) { - e_dbg("nvm parameter(s) out of bounds\n"); - return -E1000_ERR_NVM; - } - - while (widx < words) { - u8 write_opcode = NVM_WRITE_OPCODE_SPI; - - ret_val = nvm->ops.acquire(hw); - if (ret_val) - return ret_val; - - ret_val = e1000_ready_nvm_eeprom(hw); - if (ret_val) { - nvm->ops.release(hw); - return ret_val; - } - - e1000_standby_nvm(hw); - - /* Send the WRITE ENABLE command (8 bit opcode) */ - e1000_shift_out_eec_bits(hw, NVM_WREN_OPCODE_SPI, - nvm->opcode_bits); - - e1000_standby_nvm(hw); - - /* Some SPI eeproms use the 8th address bit embedded in the - * opcode - */ - if ((nvm->address_bits == 8) && (offset >= 128)) - write_opcode |= NVM_A8_OPCODE_SPI; - - /* Send the Write command (8-bit opcode + addr) */ - e1000_shift_out_eec_bits(hw, write_opcode, nvm->opcode_bits); - e1000_shift_out_eec_bits(hw, (u16)((offset + widx) * 2), - nvm->address_bits); - - /* Loop to allow for up to whole page write of eeprom */ - while (widx < words) { - u16 word_out = data[widx]; - - word_out = (word_out >> 8) | (word_out << 8); - e1000_shift_out_eec_bits(hw, word_out, 16); - widx++; - - if ((((offset + widx) * 2) % nvm->page_size) == 0) { - e1000_standby_nvm(hw); - break; - } - } - usleep_range(10000, 20000); - nvm->ops.release(hw); - } - - return ret_val; -} - -/** - * e1000_read_pba_string_generic - Read device part number - * @hw: pointer to the HW structure - * @pba_num: pointer to device part number - * @pba_num_size: size of part number buffer - * - * Reads the product board assembly (PBA) number from the EEPROM and stores - * the value in pba_num. - **/ -s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, - u32 pba_num_size) -{ - s32 ret_val; - u16 nvm_data; - u16 pba_ptr; - u16 offset; - u16 length; - - if (pba_num == NULL) { - e_dbg("PBA string buffer was null\n"); - return -E1000_ERR_INVALID_ARGUMENT; - } - - ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_0, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - ret_val = e1000_read_nvm(hw, NVM_PBA_OFFSET_1, 1, &pba_ptr); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - /* if nvm_data is not ptr guard the PBA must be in legacy format which - * means pba_ptr is actually our second data word for the PBA number - * and we can decode it into an ascii string - */ - if (nvm_data != NVM_PBA_PTR_GUARD) { - e_dbg("NVM PBA number is not stored as string\n"); - - /* make sure callers buffer is big enough to store the PBA */ - if (pba_num_size < E1000_PBANUM_LENGTH) { - e_dbg("PBA string buffer too small\n"); - return E1000_ERR_NO_SPACE; - } - - /* extract hex string from data and pba_ptr */ - pba_num[0] = (nvm_data >> 12) & 0xF; - pba_num[1] = (nvm_data >> 8) & 0xF; - pba_num[2] = (nvm_data >> 4) & 0xF; - pba_num[3] = nvm_data & 0xF; - pba_num[4] = (pba_ptr >> 12) & 0xF; - pba_num[5] = (pba_ptr >> 8) & 0xF; - pba_num[6] = '-'; - pba_num[7] = 0; - pba_num[8] = (pba_ptr >> 4) & 0xF; - pba_num[9] = pba_ptr & 0xF; - - /* put a null character on the end of our string */ - pba_num[10] = '\0'; - - /* switch all the data but the '-' to hex char */ - for (offset = 0; offset < 10; offset++) { - if (pba_num[offset] < 0xA) - pba_num[offset] += '0'; - else if (pba_num[offset] < 0x10) - pba_num[offset] += 'A' - 0xA; - } - - return 0; - } - - ret_val = e1000_read_nvm(hw, pba_ptr, 1, &length); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - - if (length == 0xFFFF || length == 0) { - e_dbg("NVM PBA number section invalid length\n"); - return -E1000_ERR_NVM_PBA_SECTION; - } - /* check if pba_num buffer is big enough */ - if (pba_num_size < (((u32)length * 2) - 1)) { - e_dbg("PBA string buffer too small\n"); - return -E1000_ERR_NO_SPACE; - } - - /* trim pba length from start of string */ - pba_ptr++; - length--; - - for (offset = 0; offset < length; offset++) { - ret_val = e1000_read_nvm(hw, pba_ptr + offset, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - pba_num[offset * 2] = (u8)(nvm_data >> 8); - pba_num[(offset * 2) + 1] = (u8)(nvm_data & 0xFF); - } - pba_num[offset * 2] = '\0'; - - return 0; -} - -/** - * e1000_read_mac_addr_generic - Read device MAC address - * @hw: pointer to the HW structure - * - * Reads the device MAC address from the EEPROM and stores the value. - * Since devices with two ports use the same EEPROM, we increment the - * last bit in the MAC address for the second port. - **/ -s32 e1000_read_mac_addr_generic(struct e1000_hw *hw) -{ - u32 rar_high; - u32 rar_low; - u16 i; - - rar_high = er32(RAH(0)); - rar_low = er32(RAL(0)); - - for (i = 0; i < E1000_RAL_MAC_ADDR_LEN; i++) - hw->mac.perm_addr[i] = (u8)(rar_low >> (i * 8)); - - for (i = 0; i < E1000_RAH_MAC_ADDR_LEN; i++) - hw->mac.perm_addr[i + 4] = (u8)(rar_high >> (i * 8)); - - for (i = 0; i < ETH_ALEN; i++) - hw->mac.addr[i] = hw->mac.perm_addr[i]; - - return 0; -} - -/** - * e1000e_validate_nvm_checksum_generic - Validate EEPROM checksum - * @hw: pointer to the HW structure - * - * Calculates the EEPROM checksum by reading/adding each word of the EEPROM - * and then verifies that the sum of the EEPROM is equal to 0xBABA. - **/ -s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw) -{ - s32 ret_val; - u16 checksum = 0; - u16 i, nvm_data; - - for (i = 0; i < (NVM_CHECKSUM_REG + 1); i++) { - ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error\n"); - return ret_val; - } - checksum += nvm_data; - } - - if (checksum != (u16)NVM_SUM) { - e_dbg("NVM Checksum Invalid\n"); - return -E1000_ERR_NVM; - } - - return 0; -} - -/** - * e1000e_update_nvm_checksum_generic - Update EEPROM checksum - * @hw: pointer to the HW structure - * - * Updates the EEPROM checksum by reading/adding each word of the EEPROM - * up to the checksum. Then calculates the EEPROM checksum and writes the - * value to the EEPROM. - **/ -s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw) -{ - s32 ret_val; - u16 checksum = 0; - u16 i, nvm_data; - - for (i = 0; i < NVM_CHECKSUM_REG; i++) { - ret_val = e1000_read_nvm(hw, i, 1, &nvm_data); - if (ret_val) { - e_dbg("NVM Read Error while updating checksum.\n"); - return ret_val; - } - checksum += nvm_data; - } - checksum = (u16)NVM_SUM - checksum; - ret_val = e1000_write_nvm(hw, NVM_CHECKSUM_REG, 1, &checksum); - if (ret_val) - e_dbg("NVM Write Error while updating checksum.\n"); - - return ret_val; -} - -/** - * e1000e_reload_nvm_generic - Reloads EEPROM - * @hw: pointer to the HW structure - * - * Reloads the EEPROM by setting the "Reinitialize from EEPROM" bit in the - * extended control register. - **/ -void e1000e_reload_nvm_generic(struct e1000_hw *hw) -{ - u32 ctrl_ext; - - usleep_range(10, 20); - ctrl_ext = er32(CTRL_EXT); - ctrl_ext |= E1000_CTRL_EXT_EE_RST; - ew32(CTRL_EXT, ctrl_ext); - e1e_flush(); -} diff --git a/addons/e1000e/src/4.4.180/nvm.h b/addons/e1000e/src/4.4.180/nvm.h deleted file mode 100644 index 5d46967e..00000000 --- a/addons/e1000e/src/4.4.180/nvm.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#ifndef _E1000E_NVM_H_ -#define _E1000E_NVM_H_ - -s32 e1000e_acquire_nvm(struct e1000_hw *hw); - -s32 e1000e_poll_eerd_eewr_done(struct e1000_hw *hw, int ee_reg); -s32 e1000_read_mac_addr_generic(struct e1000_hw *hw); -s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, - u32 pba_num_size); -s32 e1000e_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); -s32 e1000e_valid_led_default(struct e1000_hw *hw, u16 *data); -s32 e1000e_validate_nvm_checksum_generic(struct e1000_hw *hw); -s32 e1000e_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data); -s32 e1000e_update_nvm_checksum_generic(struct e1000_hw *hw); -void e1000e_release_nvm(struct e1000_hw *hw); - -#define E1000_STM_OPCODE 0xDB00 - -#endif diff --git a/addons/e1000e/src/4.4.180/param.c b/addons/e1000e/src/4.4.180/param.c deleted file mode 100644 index 6d8c39ab..00000000 --- a/addons/e1000e/src/4.4.180/param.c +++ /dev/null @@ -1,533 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#include -#include -#include - -#include "e1000.h" - -/* This is the only thing that needs to be changed to adjust the - * maximum number of ports that the driver can manage. - */ -#define E1000_MAX_NIC 32 - -#define OPTION_UNSET -1 -#define OPTION_DISABLED 0 -#define OPTION_ENABLED 1 - -#define COPYBREAK_DEFAULT 256 -unsigned int copybreak = COPYBREAK_DEFAULT; -module_param(copybreak, uint, 0644); -MODULE_PARM_DESC(copybreak, - "Maximum size of packet that is copied to a new buffer on receive"); - -/* All parameters are treated the same, as an integer array of values. - * This macro just reduces the need to repeat the same declaration code - * over and over (plus this helps to avoid typo bugs). - */ -#define E1000_PARAM_INIT { [0 ... E1000_MAX_NIC] = OPTION_UNSET } -#define E1000_PARAM(X, desc) \ - static int X[E1000_MAX_NIC+1] = E1000_PARAM_INIT; \ - static unsigned int num_##X; \ - module_param_array_named(X, X, int, &num_##X, 0); \ - MODULE_PARM_DESC(X, desc); - -/* Transmit Interrupt Delay in units of 1.024 microseconds - * Tx interrupt delay needs to typically be set to something non-zero - * - * Valid Range: 0-65535 - */ -E1000_PARAM(TxIntDelay, "Transmit Interrupt Delay"); -#define DEFAULT_TIDV 8 -#define MAX_TXDELAY 0xFFFF -#define MIN_TXDELAY 0 - -/* Transmit Absolute Interrupt Delay in units of 1.024 microseconds - * - * Valid Range: 0-65535 - */ -E1000_PARAM(TxAbsIntDelay, "Transmit Absolute Interrupt Delay"); -#define DEFAULT_TADV 32 -#define MAX_TXABSDELAY 0xFFFF -#define MIN_TXABSDELAY 0 - -/* Receive Interrupt Delay in units of 1.024 microseconds - * hardware will likely hang if you set this to anything but zero. - * - * Valid Range: 0-65535 - */ -E1000_PARAM(RxIntDelay, "Receive Interrupt Delay"); -#define MAX_RXDELAY 0xFFFF -#define MIN_RXDELAY 0 - -/* Receive Absolute Interrupt Delay in units of 1.024 microseconds - * - * Valid Range: 0-65535 - */ -E1000_PARAM(RxAbsIntDelay, "Receive Absolute Interrupt Delay"); -#define MAX_RXABSDELAY 0xFFFF -#define MIN_RXABSDELAY 0 - -/* Interrupt Throttle Rate (interrupts/sec) - * - * Valid Range: 100-100000 or one of: 0=off, 1=dynamic, 3=dynamic conservative - */ -E1000_PARAM(InterruptThrottleRate, "Interrupt Throttling Rate"); -#define DEFAULT_ITR 3 -#define MAX_ITR 100000 -#define MIN_ITR 100 - -/* IntMode (Interrupt Mode) - * - * Valid Range: varies depending on kernel configuration & hardware support - * - * legacy=0, MSI=1, MSI-X=2 - * - * When MSI/MSI-X support is enabled in kernel- - * Default Value: 2 (MSI-X) when supported by hardware, 1 (MSI) otherwise - * When MSI/MSI-X support is not enabled in kernel- - * Default Value: 0 (legacy) - * - * When a mode is specified that is not allowed/supported, it will be - * demoted to the most advanced interrupt mode available. - */ -E1000_PARAM(IntMode, "Interrupt Mode"); -#define MAX_INTMODE 2 -#define MIN_INTMODE 0 - -/* Enable Smart Power Down of the PHY - * - * Valid Range: 0, 1 - * - * Default Value: 0 (disabled) - */ -E1000_PARAM(SmartPowerDownEnable, "Enable PHY smart power down"); - -/* Enable Kumeran Lock Loss workaround - * - * Valid Range: 0, 1 - * - * Default Value: 1 (enabled) - */ -E1000_PARAM(KumeranLockLoss, "Enable Kumeran lock loss workaround"); - -/* Write Protect NVM - * - * Valid Range: 0, 1 - * - * Default Value: 1 (enabled) - */ -E1000_PARAM(WriteProtectNVM, - "Write-protect NVM [WARNING: disabling this can lead to corrupted NVM]"); - -/* Enable CRC Stripping - * - * Valid Range: 0, 1 - * - * Default Value: 1 (enabled) - */ -E1000_PARAM(CrcStripping, - "Enable CRC Stripping, disable if your BMC needs the CRC"); - -struct e1000_option { - enum { enable_option, range_option, list_option } type; - const char *name; - const char *err; - int def; - union { - /* range_option info */ - struct { - int min; - int max; - } r; - /* list_option info */ - struct { - int nr; - struct e1000_opt_list { - int i; - char *str; - } *p; - } l; - } arg; -}; - -static int e1000_validate_option(unsigned int *value, - const struct e1000_option *opt, - struct e1000_adapter *adapter) -{ - if (*value == OPTION_UNSET) { - *value = opt->def; - return 0; - } - - switch (opt->type) { - case enable_option: - switch (*value) { - case OPTION_ENABLED: - dev_info(&adapter->pdev->dev, "%s Enabled\n", - opt->name); - return 0; - case OPTION_DISABLED: - dev_info(&adapter->pdev->dev, "%s Disabled\n", - opt->name); - return 0; - } - break; - case range_option: - if (*value >= opt->arg.r.min && *value <= opt->arg.r.max) { - dev_info(&adapter->pdev->dev, "%s set to %i\n", - opt->name, *value); - return 0; - } - break; - case list_option: { - int i; - struct e1000_opt_list *ent; - - for (i = 0; i < opt->arg.l.nr; i++) { - ent = &opt->arg.l.p[i]; - if (*value == ent->i) { - if (ent->str[0] != '\0') - dev_info(&adapter->pdev->dev, "%s\n", - ent->str); - return 0; - } - } - } - break; - default: - BUG(); - } - - dev_info(&adapter->pdev->dev, "Invalid %s value specified (%i) %s\n", - opt->name, *value, opt->err); - *value = opt->def; - return -1; -} - -/** - * e1000e_check_options - Range Checking for Command Line Parameters - * @adapter: board private structure - * - * This routine checks all command line parameters for valid user - * input. If an invalid value is given, or if no user specified - * value exists, a default value is used. The final value is stored - * in a variable in the adapter structure. - **/ -void e1000e_check_options(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - int bd = adapter->bd_number; - - if (bd >= E1000_MAX_NIC) { - dev_notice(&adapter->pdev->dev, - "Warning: no configuration for board #%i\n", bd); - dev_notice(&adapter->pdev->dev, - "Using defaults for all values\n"); - } - - /* Transmit Interrupt Delay */ - { - static const struct e1000_option opt = { - .type = range_option, - .name = "Transmit Interrupt Delay", - .err = "using default of " - __MODULE_STRING(DEFAULT_TIDV), - .def = DEFAULT_TIDV, - .arg = { .r = { .min = MIN_TXDELAY, - .max = MAX_TXDELAY } } - }; - - if (num_TxIntDelay > bd) { - adapter->tx_int_delay = TxIntDelay[bd]; - e1000_validate_option(&adapter->tx_int_delay, &opt, - adapter); - } else { - adapter->tx_int_delay = opt.def; - } - } - /* Transmit Absolute Interrupt Delay */ - { - static const struct e1000_option opt = { - .type = range_option, - .name = "Transmit Absolute Interrupt Delay", - .err = "using default of " - __MODULE_STRING(DEFAULT_TADV), - .def = DEFAULT_TADV, - .arg = { .r = { .min = MIN_TXABSDELAY, - .max = MAX_TXABSDELAY } } - }; - - if (num_TxAbsIntDelay > bd) { - adapter->tx_abs_int_delay = TxAbsIntDelay[bd]; - e1000_validate_option(&adapter->tx_abs_int_delay, &opt, - adapter); - } else { - adapter->tx_abs_int_delay = opt.def; - } - } - /* Receive Interrupt Delay */ - { - static struct e1000_option opt = { - .type = range_option, - .name = "Receive Interrupt Delay", - .err = "using default of " - __MODULE_STRING(DEFAULT_RDTR), - .def = DEFAULT_RDTR, - .arg = { .r = { .min = MIN_RXDELAY, - .max = MAX_RXDELAY } } - }; - - if (num_RxIntDelay > bd) { - adapter->rx_int_delay = RxIntDelay[bd]; - e1000_validate_option(&adapter->rx_int_delay, &opt, - adapter); - } else { - adapter->rx_int_delay = opt.def; - } - } - /* Receive Absolute Interrupt Delay */ - { - static const struct e1000_option opt = { - .type = range_option, - .name = "Receive Absolute Interrupt Delay", - .err = "using default of " - __MODULE_STRING(DEFAULT_RADV), - .def = DEFAULT_RADV, - .arg = { .r = { .min = MIN_RXABSDELAY, - .max = MAX_RXABSDELAY } } - }; - - if (num_RxAbsIntDelay > bd) { - adapter->rx_abs_int_delay = RxAbsIntDelay[bd]; - e1000_validate_option(&adapter->rx_abs_int_delay, &opt, - adapter); - } else { - adapter->rx_abs_int_delay = opt.def; - } - } - /* Interrupt Throttling Rate */ - { - static const struct e1000_option opt = { - .type = range_option, - .name = "Interrupt Throttling Rate (ints/sec)", - .err = "using default of " - __MODULE_STRING(DEFAULT_ITR), - .def = DEFAULT_ITR, - .arg = { .r = { .min = MIN_ITR, - .max = MAX_ITR } } - }; - - if (num_InterruptThrottleRate > bd) { - adapter->itr = InterruptThrottleRate[bd]; - - /* Make sure a message is printed for non-special - * values. And in case of an invalid option, display - * warning, use default and go through itr/itr_setting - * adjustment logic below - */ - if ((adapter->itr > 4) && - e1000_validate_option(&adapter->itr, &opt, adapter)) - adapter->itr = opt.def; - } else { - /* If no option specified, use default value and go - * through the logic below to adjust itr/itr_setting - */ - adapter->itr = opt.def; - - /* Make sure a message is printed for non-special - * default values - */ - if (adapter->itr > 4) - dev_info(&adapter->pdev->dev, - "%s set to default %d\n", opt.name, - adapter->itr); - } - - adapter->itr_setting = adapter->itr; - switch (adapter->itr) { - case 0: - dev_info(&adapter->pdev->dev, "%s turned off\n", - opt.name); - break; - case 1: - dev_info(&adapter->pdev->dev, - "%s set to dynamic mode\n", opt.name); - adapter->itr = 20000; - break; - case 2: - dev_info(&adapter->pdev->dev, - "%s Invalid mode - setting default\n", - opt.name); - adapter->itr_setting = opt.def; - /* fall-through */ - case 3: - dev_info(&adapter->pdev->dev, - "%s set to dynamic conservative mode\n", - opt.name); - adapter->itr = 20000; - break; - case 4: - dev_info(&adapter->pdev->dev, - "%s set to simplified (2000-8000 ints) mode\n", - opt.name); - break; - default: - /* Save the setting, because the dynamic bits - * change itr. - * - * Clear the lower two bits because - * they are used as control. - */ - adapter->itr_setting &= ~3; - break; - } - } - /* Interrupt Mode */ - { - static struct e1000_option opt = { - .type = range_option, - .name = "Interrupt Mode", -#ifndef CONFIG_PCI_MSI - .err = "defaulting to 0 (legacy)", - .def = E1000E_INT_MODE_LEGACY, - .arg = { .r = { .min = 0, - .max = 0 } } -#endif - }; - -#ifdef CONFIG_PCI_MSI - if (adapter->flags & FLAG_HAS_MSIX) { - opt.err = kstrdup("defaulting to 2 (MSI-X)", - GFP_KERNEL); - opt.def = E1000E_INT_MODE_MSIX; - opt.arg.r.max = E1000E_INT_MODE_MSIX; - } else { - opt.err = kstrdup("defaulting to 1 (MSI)", GFP_KERNEL); - opt.def = E1000E_INT_MODE_MSI; - opt.arg.r.max = E1000E_INT_MODE_MSI; - } - - if (!opt.err) { - dev_err(&adapter->pdev->dev, - "Failed to allocate memory\n"); - return; - } -#endif - - if (num_IntMode > bd) { - unsigned int int_mode = IntMode[bd]; - - e1000_validate_option(&int_mode, &opt, adapter); - adapter->int_mode = int_mode; - } else { - adapter->int_mode = opt.def; - } - -#ifdef CONFIG_PCI_MSI - kfree(opt.err); -#endif - } - /* Smart Power Down */ - { - static const struct e1000_option opt = { - .type = enable_option, - .name = "PHY Smart Power Down", - .err = "defaulting to Disabled", - .def = OPTION_DISABLED - }; - - if (num_SmartPowerDownEnable > bd) { - unsigned int spd = SmartPowerDownEnable[bd]; - - e1000_validate_option(&spd, &opt, adapter); - if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && spd) - adapter->flags |= FLAG_SMART_POWER_DOWN; - } - } - /* CRC Stripping */ - { - static const struct e1000_option opt = { - .type = enable_option, - .name = "CRC Stripping", - .err = "defaulting to Enabled", - .def = OPTION_ENABLED - }; - - if (num_CrcStripping > bd) { - unsigned int crc_stripping = CrcStripping[bd]; - - e1000_validate_option(&crc_stripping, &opt, adapter); - if (crc_stripping == OPTION_ENABLED) { - adapter->flags2 |= FLAG2_CRC_STRIPPING; - adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING; - } - } else { - adapter->flags2 |= FLAG2_CRC_STRIPPING; - adapter->flags2 |= FLAG2_DFLT_CRC_STRIPPING; - } - } - /* Kumeran Lock Loss Workaround */ - { - static const struct e1000_option opt = { - .type = enable_option, - .name = "Kumeran Lock Loss Workaround", - .err = "defaulting to Enabled", - .def = OPTION_ENABLED - }; - bool enabled = opt.def; - - if (num_KumeranLockLoss > bd) { - unsigned int kmrn_lock_loss = KumeranLockLoss[bd]; - - e1000_validate_option(&kmrn_lock_loss, &opt, adapter); - enabled = kmrn_lock_loss; - } - - if (hw->mac.type == e1000_ich8lan) - e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, - enabled); - } - /* Write-protect NVM */ - { - static const struct e1000_option opt = { - .type = enable_option, - .name = "Write-protect NVM", - .err = "defaulting to Enabled", - .def = OPTION_ENABLED - }; - - if (adapter->flags & FLAG_IS_ICH) { - if (num_WriteProtectNVM > bd) { - unsigned int write_protect_nvm = - WriteProtectNVM[bd]; - e1000_validate_option(&write_protect_nvm, &opt, - adapter); - if (write_protect_nvm) - adapter->flags |= FLAG_READ_ONLY_NVM; - } else { - if (opt.def) - adapter->flags |= FLAG_READ_ONLY_NVM; - } - } - } -} diff --git a/addons/e1000e/src/4.4.180/phy.c b/addons/e1000e/src/4.4.180/phy.c deleted file mode 100644 index 8e674a09..00000000 --- a/addons/e1000e/src/4.4.180/phy.c +++ /dev/null @@ -1,3238 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#include "e1000.h" - -static s32 e1000_wait_autoneg(struct e1000_hw *hw); -static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, - u16 *data, bool read, bool page_set); -static u32 e1000_get_phy_addr_for_hv_page(u32 page); -static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, - u16 *data, bool read); - -/* Cable length tables */ -static const u16 e1000_m88_cable_length_table[] = { - 0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED -}; - -#define M88E1000_CABLE_LENGTH_TABLE_SIZE \ - ARRAY_SIZE(e1000_m88_cable_length_table) - -static const u16 e1000_igp_2_cable_length_table[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3, - 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 6, 10, 14, 18, 22, - 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 21, 26, 31, 35, 40, - 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 40, 45, 51, 56, 61, - 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82, - 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95, - 100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121, - 124 -}; - -#define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ - ARRAY_SIZE(e1000_igp_2_cable_length_table) - -/** - * e1000e_check_reset_block_generic - Check if PHY reset is blocked - * @hw: pointer to the HW structure - * - * Read the PHY management control register and check whether a PHY reset - * is blocked. If a reset is not blocked return 0, otherwise - * return E1000_BLK_PHY_RESET (12). - **/ -s32 e1000e_check_reset_block_generic(struct e1000_hw *hw) -{ - u32 manc; - - manc = er32(MANC); - - return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? E1000_BLK_PHY_RESET : 0; -} - -/** - * e1000e_get_phy_id - Retrieve the PHY ID and revision - * @hw: pointer to the HW structure - * - * Reads the PHY registers and stores the PHY ID and possibly the PHY - * revision in the hardware structure. - **/ -s32 e1000e_get_phy_id(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val = 0; - u16 phy_id; - u16 retry_count = 0; - - if (!phy->ops.read_reg) - return 0; - - while (retry_count < 2) { - ret_val = e1e_rphy(hw, MII_PHYSID1, &phy_id); - if (ret_val) - return ret_val; - - phy->id = (u32)(phy_id << 16); - usleep_range(20, 40); - ret_val = e1e_rphy(hw, MII_PHYSID2, &phy_id); - if (ret_val) - return ret_val; - - phy->id |= (u32)(phy_id & PHY_REVISION_MASK); - phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); - - if (phy->id != 0 && phy->id != PHY_REVISION_MASK) - return 0; - - retry_count++; - } - - return 0; -} - -/** - * e1000e_phy_reset_dsp - Reset PHY DSP - * @hw: pointer to the HW structure - * - * Reset the digital signal processor. - **/ -s32 e1000e_phy_reset_dsp(struct e1000_hw *hw) -{ - s32 ret_val; - - ret_val = e1e_wphy(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); - if (ret_val) - return ret_val; - - return e1e_wphy(hw, M88E1000_PHY_GEN_CONTROL, 0); -} - -/** - * e1000e_read_phy_reg_mdic - Read MDI control register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the MDI control register in the PHY at offset and stores the - * information read to data. - **/ -s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, mdic = 0; - - if (offset > MAX_PHY_REG_ADDRESS) { - e_dbg("PHY Address %d is out of range\n", offset); - return -E1000_ERR_PARAM; - } - - /* Set up Op-code, Phy Address, and register offset in the MDI - * Control register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - mdic = ((offset << E1000_MDIC_REG_SHIFT) | - (phy->addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_READ)); - - ew32(MDIC, mdic); - - /* Poll the ready bit to see if the MDI read completed - * Increasing the time out as testing showed failures with - * the lower time out - */ - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { - udelay(50); - mdic = er32(MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - e_dbg("MDI Read did not complete\n"); - return -E1000_ERR_PHY; - } - if (mdic & E1000_MDIC_ERROR) { - e_dbg("MDI Error\n"); - return -E1000_ERR_PHY; - } - if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) { - e_dbg("MDI Read offset error - requested %d, returned %d\n", - offset, - (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); - return -E1000_ERR_PHY; - } - *data = (u16)mdic; - - /* Allow some time after each MDIC transaction to avoid - * reading duplicate data in the next MDIC transaction. - */ - if (hw->mac.type == e1000_pch2lan) - udelay(100); - - return 0; -} - -/** - * e1000e_write_phy_reg_mdic - Write MDI control register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write to register at offset - * - * Writes data to MDI control register in the PHY at offset. - **/ -s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) -{ - struct e1000_phy_info *phy = &hw->phy; - u32 i, mdic = 0; - - if (offset > MAX_PHY_REG_ADDRESS) { - e_dbg("PHY Address %d is out of range\n", offset); - return -E1000_ERR_PARAM; - } - - /* Set up Op-code, Phy Address, and register offset in the MDI - * Control register. The MAC will take care of interfacing with the - * PHY to retrieve the desired data. - */ - mdic = (((u32)data) | - (offset << E1000_MDIC_REG_SHIFT) | - (phy->addr << E1000_MDIC_PHY_SHIFT) | - (E1000_MDIC_OP_WRITE)); - - ew32(MDIC, mdic); - - /* Poll the ready bit to see if the MDI read completed - * Increasing the time out as testing showed failures with - * the lower time out - */ - for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { - udelay(50); - mdic = er32(MDIC); - if (mdic & E1000_MDIC_READY) - break; - } - if (!(mdic & E1000_MDIC_READY)) { - e_dbg("MDI Write did not complete\n"); - return -E1000_ERR_PHY; - } - if (mdic & E1000_MDIC_ERROR) { - e_dbg("MDI Error\n"); - return -E1000_ERR_PHY; - } - if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) { - e_dbg("MDI Write offset error - requested %d, returned %d\n", - offset, - (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT); - return -E1000_ERR_PHY; - } - - /* Allow some time after each MDIC transaction to avoid - * reading duplicate data in the next MDIC transaction. - */ - if (hw->mac.type == e1000_pch2lan) - udelay(100); - - return 0; -} - -/** - * e1000e_read_phy_reg_m88 - Read m88 PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000e_write_phy_reg_m88 - Write m88 PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_set_page_igp - Set page as on IGP-like PHY(s) - * @hw: pointer to the HW structure - * @page: page to set (shifted left when necessary) - * - * Sets PHY page required for PHY register access. Assumes semaphore is - * already acquired. Note, this function sets phy.addr to 1 so the caller - * must set it appropriately (if necessary) after this function returns. - **/ -s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page) -{ - e_dbg("Setting page 0x%x\n", page); - - hw->phy.addr = 1; - - return e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page); -} - -/** - * __e1000e_read_phy_reg_igp - Read igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and stores the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -static s32 __e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data, - bool locked) -{ - s32 ret_val = 0; - - if (!locked) { - if (!hw->phy.ops.acquire) - return 0; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - if (offset > MAX_PHY_MULTI_PAGE_REG) - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (u16)offset); - if (!ret_val) - ret_val = e1000e_read_phy_reg_mdic(hw, - MAX_PHY_REG_ADDRESS & offset, - data); - if (!locked) - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000e_read_phy_reg_igp - Read igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore then reads the PHY register at offset and stores the - * retrieved information in data. - * Release the acquired semaphore before exiting. - **/ -s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000e_read_phy_reg_igp(hw, offset, data, false); -} - -/** - * e1000e_read_phy_reg_igp_locked - Read igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY register at offset and stores the retrieved information - * in data. Assumes semaphore already acquired. - **/ -s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000e_read_phy_reg_igp(hw, offset, data, true); -} - -/** - * e1000e_write_phy_reg_igp - Write igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -static s32 __e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data, - bool locked) -{ - s32 ret_val = 0; - - if (!locked) { - if (!hw->phy.ops.acquire) - return 0; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - if (offset > MAX_PHY_MULTI_PAGE_REG) - ret_val = e1000e_write_phy_reg_mdic(hw, - IGP01E1000_PHY_PAGE_SELECT, - (u16)offset); - if (!ret_val) - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & - offset, data); - if (!locked) - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000e_write_phy_reg_igp - Write igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000e_write_phy_reg_igp(hw, offset, data, false); -} - -/** - * e1000e_write_phy_reg_igp_locked - Write igp PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Writes the data to PHY register at the offset. - * Assumes semaphore already acquired. - **/ -s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000e_write_phy_reg_igp(hw, offset, data, true); -} - -/** - * __e1000_read_kmrn_reg - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary. Then reads the PHY register at offset - * using the kumeran interface. The information retrieved is stored in data. - * Release any acquired semaphores before exiting. - **/ -static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data, - bool locked) -{ - u32 kmrnctrlsta; - - if (!locked) { - s32 ret_val = 0; - - if (!hw->phy.ops.acquire) - return 0; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; - ew32(KMRNCTRLSTA, kmrnctrlsta); - e1e_flush(); - - udelay(2); - - kmrnctrlsta = er32(KMRNCTRLSTA); - *data = (u16)kmrnctrlsta; - - if (!locked) - hw->phy.ops.release(hw); - - return 0; -} - -/** - * e1000e_read_kmrn_reg - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore then reads the PHY register at offset using the - * kumeran interface. The information retrieved is stored in data. - * Release the acquired semaphore before exiting. - **/ -s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000_read_kmrn_reg(hw, offset, data, false); -} - -/** - * e1000e_read_kmrn_reg_locked - Read kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY register at offset using the kumeran interface. The - * information retrieved is stored in data. - * Assumes semaphore already acquired. - **/ -s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000_read_kmrn_reg(hw, offset, data, true); -} - -/** - * __e1000_write_kmrn_reg - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary. Then write the data to PHY register - * at the offset using the kumeran interface. Release any acquired semaphores - * before exiting. - **/ -static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data, - bool locked) -{ - u32 kmrnctrlsta; - - if (!locked) { - s32 ret_val = 0; - - if (!hw->phy.ops.acquire) - return 0; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & - E1000_KMRNCTRLSTA_OFFSET) | data; - ew32(KMRNCTRLSTA, kmrnctrlsta); - e1e_flush(); - - udelay(2); - - if (!locked) - hw->phy.ops.release(hw); - - return 0; -} - -/** - * e1000e_write_kmrn_reg - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore then writes the data to the PHY register at the offset - * using the kumeran interface. Release the acquired semaphore before exiting. - **/ -s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000_write_kmrn_reg(hw, offset, data, false); -} - -/** - * e1000e_write_kmrn_reg_locked - Write kumeran register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Write the data to PHY register at the offset using the kumeran interface. - * Assumes semaphore already acquired. - **/ -s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000_write_kmrn_reg(hw, offset, data, true); -} - -/** - * e1000_set_master_slave_mode - Setup PHY for Master/slave mode - * @hw: pointer to the HW structure - * - * Sets up Master/slave mode - **/ -static s32 e1000_set_master_slave_mode(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - - /* Resolve Master/Slave mode */ - ret_val = e1e_rphy(hw, MII_CTRL1000, &phy_data); - if (ret_val) - return ret_val; - - /* load defaults for future use */ - hw->phy.original_ms_type = (phy_data & CTL1000_ENABLE_MASTER) ? - ((phy_data & CTL1000_AS_MASTER) ? - e1000_ms_force_master : e1000_ms_force_slave) : e1000_ms_auto; - - switch (hw->phy.ms_type) { - case e1000_ms_force_master: - phy_data |= (CTL1000_ENABLE_MASTER | CTL1000_AS_MASTER); - break; - case e1000_ms_force_slave: - phy_data |= CTL1000_ENABLE_MASTER; - phy_data &= ~(CTL1000_AS_MASTER); - break; - case e1000_ms_auto: - phy_data &= ~CTL1000_ENABLE_MASTER; - /* fall-through */ - default: - break; - } - - return e1e_wphy(hw, MII_CTRL1000, phy_data); -} - -/** - * e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link - * @hw: pointer to the HW structure - * - * Sets up Carrier-sense on Transmit and downshift values. - **/ -s32 e1000_copper_link_setup_82577(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_data; - - /* Enable CRS on Tx. This must be set for half-duplex operation. */ - ret_val = e1e_rphy(hw, I82577_CFG_REG, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= I82577_CFG_ASSERT_CRS_ON_TX; - - /* Enable downshift */ - phy_data |= I82577_CFG_ENABLE_DOWNSHIFT; - - ret_val = e1e_wphy(hw, I82577_CFG_REG, phy_data); - if (ret_val) - return ret_val; - - /* Set MDI/MDIX mode */ - ret_val = e1e_rphy(hw, I82577_PHY_CTRL_2, &phy_data); - if (ret_val) - return ret_val; - phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK; - /* Options: - * 0 - Auto (default) - * 1 - MDI mode - * 2 - MDI-X mode - */ - switch (hw->phy.mdix) { - case 1: - break; - case 2: - phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX; - break; - case 0: - default: - phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX; - break; - } - ret_val = e1e_wphy(hw, I82577_PHY_CTRL_2, phy_data); - if (ret_val) - return ret_val; - - return e1000_set_master_slave_mode(hw); -} - -/** - * e1000e_copper_link_setup_m88 - Setup m88 PHY's for copper link - * @hw: pointer to the HW structure - * - * Sets up MDI/MDI-X and polarity for m88 PHY's. If necessary, transmit clock - * and downshift values are set also. - **/ -s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - - /* Enable CRS on Tx. This must be set for half-duplex operation. */ - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - /* For BM PHY this bit is downshift enable */ - if (phy->type != e1000_phy_bm) - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - - /* Options: - * MDI/MDI-X = 0 (default) - * 0 - Auto for all speeds - * 1 - MDI mode - * 2 - MDI-X mode - * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) - */ - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - - switch (phy->mdix) { - case 1: - phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; - break; - case 2: - phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; - break; - case 3: - phy_data |= M88E1000_PSCR_AUTO_X_1000T; - break; - case 0: - default: - phy_data |= M88E1000_PSCR_AUTO_X_MODE; - break; - } - - /* Options: - * disable_polarity_correction = 0 (default) - * Automatic Correction for Reversed Cable Polarity - * 0 - Disabled - * 1 - Enabled - */ - phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; - if (phy->disable_polarity_correction) - phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; - - /* Enable downshift on BM (disabled by default) */ - if (phy->type == e1000_phy_bm) { - /* For 82574/82583, first disable then enable downshift */ - if (phy->id == BME1000_E_PHY_ID_R2) { - phy_data &= ~BME1000_PSCR_ENABLE_DOWNSHIFT; - ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, - phy_data); - if (ret_val) - return ret_val; - /* Commit the changes. */ - ret_val = phy->ops.commit(hw); - if (ret_val) { - e_dbg("Error committing the PHY changes\n"); - return ret_val; - } - } - - phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT; - } - - ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - if ((phy->type == e1000_phy_m88) && - (phy->revision < E1000_REVISION_4) && - (phy->id != BME1000_E_PHY_ID_R2)) { - /* Force TX_CLK in the Extended PHY Specific Control Register - * to 25MHz clock. - */ - ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_EPSCR_TX_CLK_25; - - if ((phy->revision == 2) && (phy->id == M88E1111_I_PHY_ID)) { - /* 82573L PHY - set the downshift counter to 5x. */ - phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK; - phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; - } else { - /* Configure Master and Slave downshift values */ - phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); - phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | - M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); - } - ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - } - - if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) { - /* Set PHY page 0, register 29 to 0x0003 */ - ret_val = e1e_wphy(hw, 29, 0x0003); - if (ret_val) - return ret_val; - - /* Set PHY page 0, register 30 to 0x0000 */ - ret_val = e1e_wphy(hw, 30, 0x0000); - if (ret_val) - return ret_val; - } - - /* Commit the changes. */ - if (phy->ops.commit) { - ret_val = phy->ops.commit(hw); - if (ret_val) { - e_dbg("Error committing the PHY changes\n"); - return ret_val; - } - } - - if (phy->type == e1000_phy_82578) { - ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - /* 82578 PHY - set the downshift count to 1x. */ - phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE; - phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK; - ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - } - - return 0; -} - -/** - * e1000e_copper_link_setup_igp - Setup igp PHY's for copper link - * @hw: pointer to the HW structure - * - * Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for - * igp PHY's. - **/ -s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - ret_val = e1000_phy_hw_reset(hw); - if (ret_val) { - e_dbg("Error resetting the PHY.\n"); - return ret_val; - } - - /* Wait 100ms for MAC to configure PHY from NVM settings, to avoid - * timeout issues when LFS is enabled. - */ - msleep(100); - - /* disable lplu d0 during driver init */ - if (hw->phy.ops.set_d0_lplu_state) { - ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); - if (ret_val) { - e_dbg("Error Disabling LPLU D0\n"); - return ret_val; - } - } - /* Configure mdi-mdix settings */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCR_AUTO_MDIX; - - switch (phy->mdix) { - case 1: - data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 2: - data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; - break; - case 0: - default: - data |= IGP01E1000_PSCR_AUTO_MDIX; - break; - } - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CTRL, data); - if (ret_val) - return ret_val; - - /* set auto-master slave resolution settings */ - if (hw->mac.autoneg) { - /* when autonegotiation advertisement is only 1000Mbps then we - * should disable SmartSpeed and enable Auto MasterSlave - * resolution as hardware default. - */ - if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { - /* Disable SmartSpeed */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - - /* Set auto Master/Slave resolution process */ - ret_val = e1e_rphy(hw, MII_CTRL1000, &data); - if (ret_val) - return ret_val; - - data &= ~CTL1000_ENABLE_MASTER; - ret_val = e1e_wphy(hw, MII_CTRL1000, data); - if (ret_val) - return ret_val; - } - - ret_val = e1000_set_master_slave_mode(hw); - } - - return ret_val; -} - -/** - * e1000_phy_setup_autoneg - Configure PHY for auto-negotiation - * @hw: pointer to the HW structure - * - * Reads the MII auto-neg advertisement register and/or the 1000T control - * register and if the PHY is already setup for auto-negotiation, then - * return successful. Otherwise, setup advertisement and flow control to - * the appropriate values for the wanted auto-negotiation. - **/ -static s32 e1000_phy_setup_autoneg(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 mii_autoneg_adv_reg; - u16 mii_1000t_ctrl_reg = 0; - - phy->autoneg_advertised &= phy->autoneg_mask; - - /* Read the MII Auto-Neg Advertisement Register (Address 4). */ - ret_val = e1e_rphy(hw, MII_ADVERTISE, &mii_autoneg_adv_reg); - if (ret_val) - return ret_val; - - if (phy->autoneg_mask & ADVERTISE_1000_FULL) { - /* Read the MII 1000Base-T Control Register (Address 9). */ - ret_val = e1e_rphy(hw, MII_CTRL1000, &mii_1000t_ctrl_reg); - if (ret_val) - return ret_val; - } - - /* Need to parse both autoneg_advertised and fc and set up - * the appropriate PHY registers. First we will parse for - * autoneg_advertised software override. Since we can advertise - * a plethora of combinations, we need to check each bit - * individually. - */ - - /* First we clear all the 10/100 mb speed bits in the Auto-Neg - * Advertisement Register (Address 4) and the 1000 mb speed bits in - * the 1000Base-T Control Register (Address 9). - */ - mii_autoneg_adv_reg &= ~(ADVERTISE_100FULL | - ADVERTISE_100HALF | - ADVERTISE_10FULL | ADVERTISE_10HALF); - mii_1000t_ctrl_reg &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - - e_dbg("autoneg_advertised %x\n", phy->autoneg_advertised); - - /* Do we want to advertise 10 Mb Half Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_10_HALF) { - e_dbg("Advertise 10mb Half duplex\n"); - mii_autoneg_adv_reg |= ADVERTISE_10HALF; - } - - /* Do we want to advertise 10 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_10_FULL) { - e_dbg("Advertise 10mb Full duplex\n"); - mii_autoneg_adv_reg |= ADVERTISE_10FULL; - } - - /* Do we want to advertise 100 Mb Half Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_100_HALF) { - e_dbg("Advertise 100mb Half duplex\n"); - mii_autoneg_adv_reg |= ADVERTISE_100HALF; - } - - /* Do we want to advertise 100 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_100_FULL) { - e_dbg("Advertise 100mb Full duplex\n"); - mii_autoneg_adv_reg |= ADVERTISE_100FULL; - } - - /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ - if (phy->autoneg_advertised & ADVERTISE_1000_HALF) - e_dbg("Advertise 1000mb Half duplex request denied!\n"); - - /* Do we want to advertise 1000 Mb Full Duplex? */ - if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { - e_dbg("Advertise 1000mb Full duplex\n"); - mii_1000t_ctrl_reg |= ADVERTISE_1000FULL; - } - - /* Check for a software override of the flow control settings, and - * setup the PHY advertisement registers accordingly. If - * auto-negotiation is enabled, then software will have to set the - * "PAUSE" bits to the correct value in the Auto-Negotiation - * Advertisement Register (MII_ADVERTISE) and re-start auto- - * negotiation. - * - * The possible values of the "fc" parameter are: - * 0: Flow control is completely disabled - * 1: Rx flow control is enabled (we can receive pause frames - * but not send pause frames). - * 2: Tx flow control is enabled (we can send pause frames - * but we do not support receiving pause frames). - * 3: Both Rx and Tx flow control (symmetric) are enabled. - * other: No software override. The flow control configuration - * in the EEPROM is used. - */ - switch (hw->fc.current_mode) { - case e1000_fc_none: - /* Flow control (Rx & Tx) is completely disabled by a - * software over-ride. - */ - mii_autoneg_adv_reg &= - ~(ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP); - break; - case e1000_fc_rx_pause: - /* Rx Flow control is enabled, and Tx Flow control is - * disabled, by a software over-ride. - * - * Since there really isn't a way to advertise that we are - * capable of Rx Pause ONLY, we will advertise that we - * support both symmetric and asymmetric Rx PAUSE. Later - * (in e1000e_config_fc_after_link_up) we will disable the - * hw's ability to send PAUSE frames. - */ - mii_autoneg_adv_reg |= - (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP); - break; - case e1000_fc_tx_pause: - /* Tx Flow control is enabled, and Rx Flow control is - * disabled, by a software over-ride. - */ - mii_autoneg_adv_reg |= ADVERTISE_PAUSE_ASYM; - mii_autoneg_adv_reg &= ~ADVERTISE_PAUSE_CAP; - break; - case e1000_fc_full: - /* Flow control (both Rx and Tx) is enabled by a software - * over-ride. - */ - mii_autoneg_adv_reg |= - (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP); - break; - default: - e_dbg("Flow control param set incorrectly\n"); - return -E1000_ERR_CONFIG; - } - - ret_val = e1e_wphy(hw, MII_ADVERTISE, mii_autoneg_adv_reg); - if (ret_val) - return ret_val; - - e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); - - if (phy->autoneg_mask & ADVERTISE_1000_FULL) - ret_val = e1e_wphy(hw, MII_CTRL1000, mii_1000t_ctrl_reg); - - return ret_val; -} - -/** - * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link - * @hw: pointer to the HW structure - * - * Performs initial bounds checking on autoneg advertisement parameter, then - * configure to advertise the full capability. Setup the PHY to autoneg - * and restart the negotiation process between the link partner. If - * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. - **/ -static s32 e1000_copper_link_autoneg(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_ctrl; - - /* Perform some bounds checking on the autoneg advertisement - * parameter. - */ - phy->autoneg_advertised &= phy->autoneg_mask; - - /* If autoneg_advertised is zero, we assume it was not defaulted - * by the calling code so we set to advertise full capability. - */ - if (!phy->autoneg_advertised) - phy->autoneg_advertised = phy->autoneg_mask; - - e_dbg("Reconfiguring auto-neg advertisement params\n"); - ret_val = e1000_phy_setup_autoneg(hw); - if (ret_val) { - e_dbg("Error Setting up Auto-Negotiation\n"); - return ret_val; - } - e_dbg("Restarting Auto-Neg\n"); - - /* Restart auto-negotiation by setting the Auto Neg Enable bit and - * the Auto Neg Restart bit in the PHY control register. - */ - ret_val = e1e_rphy(hw, MII_BMCR, &phy_ctrl); - if (ret_val) - return ret_val; - - phy_ctrl |= (BMCR_ANENABLE | BMCR_ANRESTART); - ret_val = e1e_wphy(hw, MII_BMCR, phy_ctrl); - if (ret_val) - return ret_val; - - /* Does the user want to wait for Auto-Neg to complete here, or - * check at a later time (for example, callback routine). - */ - if (phy->autoneg_wait_to_complete) { - ret_val = e1000_wait_autoneg(hw); - if (ret_val) { - e_dbg("Error while waiting for autoneg to complete\n"); - return ret_val; - } - } - - hw->mac.get_link_status = true; - - return ret_val; -} - -/** - * e1000e_setup_copper_link - Configure copper link settings - * @hw: pointer to the HW structure - * - * Calls the appropriate function to configure the link for auto-neg or forced - * speed and duplex. Then we check for link, once link is established calls - * to configure collision distance and flow control are called. If link is - * not established, we return -E1000_ERR_PHY (-2). - **/ -s32 e1000e_setup_copper_link(struct e1000_hw *hw) -{ - s32 ret_val; - bool link; - - if (hw->mac.autoneg) { - /* Setup autoneg and flow control advertisement and perform - * autonegotiation. - */ - ret_val = e1000_copper_link_autoneg(hw); - if (ret_val) - return ret_val; - } else { - /* PHY will be set to 10H, 10F, 100H or 100F - * depending on user settings. - */ - e_dbg("Forcing Speed and Duplex\n"); - ret_val = hw->phy.ops.force_speed_duplex(hw); - if (ret_val) { - e_dbg("Error Forcing Speed and Duplex\n"); - return ret_val; - } - } - - /* Check link status. Wait up to 100 microseconds for link to become - * valid. - */ - ret_val = e1000e_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10, - &link); - if (ret_val) - return ret_val; - - if (link) { - e_dbg("Valid link established!!!\n"); - hw->mac.ops.config_collision_dist(hw); - ret_val = e1000e_config_fc_after_link_up(hw); - } else { - e_dbg("Unable to establish link!!!\n"); - } - - return ret_val; -} - -/** - * e1000e_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY - * @hw: pointer to the HW structure - * - * Calls the PHY setup function to force speed and duplex. Clears the - * auto-crossover to force MDI manually. Waits for link and returns - * successful if link up is successful, else -E1000_ERR_PHY (-2). - **/ -s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - ret_val = e1e_rphy(hw, MII_BMCR, &phy_data); - if (ret_val) - return ret_val; - - e1000e_phy_force_speed_duplex_setup(hw, &phy_data); - - ret_val = e1e_wphy(hw, MII_BMCR, phy_data); - if (ret_val) - return ret_val; - - /* Clear Auto-Crossover to force MDI manually. IGP requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; - phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; - - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); - if (ret_val) - return ret_val; - - e_dbg("IGP PSCR: %X\n", phy_data); - - udelay(1); - - if (phy->autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on IGP phy.\n"); - - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - - if (!link) - e_dbg("Link taking longer than expected.\n"); - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - } - - return ret_val; -} - -/** - * e1000e_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY - * @hw: pointer to the HW structure - * - * Calls the PHY setup function to force speed and duplex. Clears the - * auto-crossover to force MDI manually. Resets the PHY to commit the - * changes. If time expires while waiting for link up, we reset the DSP. - * After reset, TX_CLK and CRS on Tx must be set. Return successful upon - * successful completion, else return corresponding error code. - **/ -s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI - * forced whenever speed and duplex are forced. - */ - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; - ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - e_dbg("M88E1000 PSCR: %X\n", phy_data); - - ret_val = e1e_rphy(hw, MII_BMCR, &phy_data); - if (ret_val) - return ret_val; - - e1000e_phy_force_speed_duplex_setup(hw, &phy_data); - - ret_val = e1e_wphy(hw, MII_BMCR, phy_data); - if (ret_val) - return ret_val; - - /* Reset the phy to commit changes. */ - if (hw->phy.ops.commit) { - ret_val = hw->phy.ops.commit(hw); - if (ret_val) - return ret_val; - } - - if (phy->autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on M88 phy.\n"); - - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - - if (!link) { - if (hw->phy.type != e1000_phy_m88) { - e_dbg("Link taking longer than expected.\n"); - } else { - /* We didn't get link. - * Reset the DSP and cross our fingers. - */ - ret_val = e1e_wphy(hw, M88E1000_PHY_PAGE_SELECT, - 0x001d); - if (ret_val) - return ret_val; - ret_val = e1000e_phy_reset_dsp(hw); - if (ret_val) - return ret_val; - } - } - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - } - - if (hw->phy.type != e1000_phy_m88) - return 0; - - ret_val = e1e_rphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - /* Resetting the phy means we need to re-force TX_CLK in the - * Extended PHY Specific Control Register to 25MHz clock from - * the reset value of 2.5MHz. - */ - phy_data |= M88E1000_EPSCR_TX_CLK_25; - ret_val = e1e_wphy(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); - if (ret_val) - return ret_val; - - /* In addition, we must re-enable CRS on Tx for both half and full - * duplex. - */ - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; - ret_val = e1e_wphy(hw, M88E1000_PHY_SPEC_CTRL, phy_data); - - return ret_val; -} - -/** - * e1000_phy_force_speed_duplex_ife - Force PHY speed & duplex - * @hw: pointer to the HW structure - * - * Forces the speed and duplex settings of the PHY. - * This is a function pointer entry point only called by - * PHY setup routines. - **/ -s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - ret_val = e1e_rphy(hw, MII_BMCR, &data); - if (ret_val) - return ret_val; - - e1000e_phy_force_speed_duplex_setup(hw, &data); - - ret_val = e1e_wphy(hw, MII_BMCR, data); - if (ret_val) - return ret_val; - - /* Disable MDI-X support for 10/100 */ - ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data); - if (ret_val) - return ret_val; - - data &= ~IFE_PMC_AUTO_MDIX; - data &= ~IFE_PMC_FORCE_MDIX; - - ret_val = e1e_wphy(hw, IFE_PHY_MDIX_CONTROL, data); - if (ret_val) - return ret_val; - - e_dbg("IFE PMC: %X\n", data); - - udelay(1); - - if (phy->autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on IFE phy.\n"); - - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - - if (!link) - e_dbg("Link taking longer than expected.\n"); - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - } - - return 0; -} - -/** - * e1000e_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex - * @hw: pointer to the HW structure - * @phy_ctrl: pointer to current value of MII_BMCR - * - * Forces speed and duplex on the PHY by doing the following: disable flow - * control, force speed/duplex on the MAC, disable auto speed detection, - * disable auto-negotiation, configure duplex, configure speed, configure - * the collision distance, write configuration to CTRL register. The - * caller must write to the MII_BMCR register for these settings to - * take affect. - **/ -void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) -{ - struct e1000_mac_info *mac = &hw->mac; - u32 ctrl; - - /* Turn off flow control when forcing speed/duplex */ - hw->fc.current_mode = e1000_fc_none; - - /* Force speed/duplex on the mac */ - ctrl = er32(CTRL); - ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); - ctrl &= ~E1000_CTRL_SPD_SEL; - - /* Disable Auto Speed Detection */ - ctrl &= ~E1000_CTRL_ASDE; - - /* Disable autoneg on the phy */ - *phy_ctrl &= ~BMCR_ANENABLE; - - /* Forcing Full or Half Duplex? */ - if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) { - ctrl &= ~E1000_CTRL_FD; - *phy_ctrl &= ~BMCR_FULLDPLX; - e_dbg("Half Duplex\n"); - } else { - ctrl |= E1000_CTRL_FD; - *phy_ctrl |= BMCR_FULLDPLX; - e_dbg("Full Duplex\n"); - } - - /* Forcing 10mb or 100mb? */ - if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) { - ctrl |= E1000_CTRL_SPD_100; - *phy_ctrl |= BMCR_SPEED100; - *phy_ctrl &= ~BMCR_SPEED1000; - e_dbg("Forcing 100mb\n"); - } else { - ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); - *phy_ctrl &= ~(BMCR_SPEED1000 | BMCR_SPEED100); - e_dbg("Forcing 10mb\n"); - } - - hw->mac.ops.config_collision_dist(hw); - - ew32(CTRL, ctrl); -} - -/** - * e1000e_set_d3_lplu_state - Sets low power link up state for D3 - * @hw: pointer to the HW structure - * @active: boolean used to enable/disable lplu - * - * Success returns 0, Failure returns 1 - * - * The low power link up (lplu) state is set to the power management level D3 - * and SmartSpeed is disabled when active is true, else clear lplu for D3 - * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU - * is used during Dx states where the power conservation is most important. - * During driver activity, SmartSpeed should be enabled so performance is - * maintained. - **/ -s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - ret_val = e1e_rphy(hw, IGP02E1000_PHY_POWER_MGMT, &data); - if (ret_val) - return ret_val; - - if (!active) { - data &= ~IGP02E1000_PM_D3_LPLU; - ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); - if (ret_val) - return ret_val; - /* LPLU and SmartSpeed are mutually exclusive. LPLU is used - * during Dx states where the power conservation is most - * important. During driver activity we should enable - * SmartSpeed, so performance is maintained. - */ - if (phy->smart_speed == e1000_smart_speed_on) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data |= IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } else if (phy->smart_speed == e1000_smart_speed_off) { - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, - &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, - data); - if (ret_val) - return ret_val; - } - } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || - (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || - (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { - data |= IGP02E1000_PM_D3_LPLU; - ret_val = e1e_wphy(hw, IGP02E1000_PHY_POWER_MGMT, data); - if (ret_val) - return ret_val; - - /* When LPLU is enabled, we should disable SmartSpeed */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_CONFIG, &data); - if (ret_val) - return ret_val; - - data &= ~IGP01E1000_PSCFR_SMART_SPEED; - ret_val = e1e_wphy(hw, IGP01E1000_PHY_PORT_CONFIG, data); - } - - return ret_val; -} - -/** - * e1000e_check_downshift - Checks whether a downshift in speed occurred - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns 1 - * - * A downshift is detected by querying the PHY link health. - **/ -s32 e1000e_check_downshift(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, offset, mask; - - switch (phy->type) { - case e1000_phy_m88: - case e1000_phy_gg82563: - case e1000_phy_bm: - case e1000_phy_82578: - offset = M88E1000_PHY_SPEC_STATUS; - mask = M88E1000_PSSR_DOWNSHIFT; - break; - case e1000_phy_igp_2: - case e1000_phy_igp_3: - offset = IGP01E1000_PHY_LINK_HEALTH; - mask = IGP01E1000_PLHR_SS_DOWNGRADE; - break; - default: - /* speed downshift not supported */ - phy->speed_downgraded = false; - return 0; - } - - ret_val = e1e_rphy(hw, offset, &phy_data); - - if (!ret_val) - phy->speed_downgraded = !!(phy_data & mask); - - return ret_val; -} - -/** - * e1000_check_polarity_m88 - Checks the polarity. - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - * - * Polarity is determined based on the PHY specific status register. - **/ -s32 e1000_check_polarity_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &data); - - if (!ret_val) - phy->cable_polarity = ((data & M88E1000_PSSR_REV_POLARITY) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal); - - return ret_val; -} - -/** - * e1000_check_polarity_igp - Checks the polarity. - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - * - * Polarity is determined based on the PHY port status register, and the - * current speed (since there is no polarity at 100Mbps). - **/ -s32 e1000_check_polarity_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data, offset, mask; - - /* Polarity is determined based on the speed of - * our connection. - */ - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data); - if (ret_val) - return ret_val; - - if ((data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - offset = IGP01E1000_PHY_PCS_INIT_REG; - mask = IGP01E1000_PHY_POLARITY_MASK; - } else { - /* This really only applies to 10Mbps since - * there is no polarity for 100Mbps (always 0). - */ - offset = IGP01E1000_PHY_PORT_STATUS; - mask = IGP01E1000_PSSR_POLARITY_REVERSED; - } - - ret_val = e1e_rphy(hw, offset, &data); - - if (!ret_val) - phy->cable_polarity = ((data & mask) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal); - - return ret_val; -} - -/** - * e1000_check_polarity_ife - Check cable polarity for IFE PHY - * @hw: pointer to the HW structure - * - * Polarity is determined on the polarity reversal feature being enabled. - **/ -s32 e1000_check_polarity_ife(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, offset, mask; - - /* Polarity is determined based on the reversal feature being enabled. - */ - if (phy->polarity_correction) { - offset = IFE_PHY_EXTENDED_STATUS_CONTROL; - mask = IFE_PESC_POLARITY_REVERSED; - } else { - offset = IFE_PHY_SPECIAL_CONTROL; - mask = IFE_PSC_FORCE_POLARITY; - } - - ret_val = e1e_rphy(hw, offset, &phy_data); - - if (!ret_val) - phy->cable_polarity = ((phy_data & mask) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal); - - return ret_val; -} - -/** - * e1000_wait_autoneg - Wait for auto-neg completion - * @hw: pointer to the HW structure - * - * Waits for auto-negotiation to complete or for the auto-negotiation time - * limit to expire, which ever happens first. - **/ -static s32 e1000_wait_autoneg(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u16 i, phy_status; - - /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ - for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { - ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); - if (ret_val) - break; - ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); - if (ret_val) - break; - if (phy_status & BMSR_ANEGCOMPLETE) - break; - msleep(100); - } - - /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation - * has completed. - */ - return ret_val; -} - -/** - * e1000e_phy_has_link_generic - Polls PHY for link - * @hw: pointer to the HW structure - * @iterations: number of times to poll for link - * @usec_interval: delay between polling attempts - * @success: pointer to whether polling was successful or not - * - * Polls the PHY status register for link, 'iterations' number of times. - **/ -s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, - u32 usec_interval, bool *success) -{ - s32 ret_val = 0; - u16 i, phy_status; - - *success = false; - for (i = 0; i < iterations; i++) { - /* Some PHYs require the MII_BMSR register to be read - * twice due to the link bit being sticky. No harm doing - * it across the board. - */ - ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); - if (ret_val) { - /* If the first read fails, another entity may have - * ownership of the resources, wait and try again to - * see if they have relinquished the resources yet. - */ - if (usec_interval >= 1000) - msleep(usec_interval / 1000); - else - udelay(usec_interval); - } - ret_val = e1e_rphy(hw, MII_BMSR, &phy_status); - if (ret_val) - break; - if (phy_status & BMSR_LSTATUS) { - *success = true; - break; - } - if (usec_interval >= 1000) - msleep(usec_interval / 1000); - else - udelay(usec_interval); - } - - return ret_val; -} - -/** - * e1000e_get_cable_length_m88 - Determine cable length for m88 PHY - * @hw: pointer to the HW structure - * - * Reads the PHY specific status register to retrieve the cable length - * information. The cable length is determined by averaging the minimum and - * maximum values to get the "average" cable length. The m88 PHY has four - * possible cable length values, which are: - * Register Value Cable Length - * 0 < 50 meters - * 1 50 - 80 meters - * 2 80 - 110 meters - * 3 110 - 140 meters - * 4 > 140 meters - **/ -s32 e1000e_get_cable_length_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, index; - - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if (ret_val) - return ret_val; - - index = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >> - M88E1000_PSSR_CABLE_LENGTH_SHIFT); - - if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) - return -E1000_ERR_PHY; - - phy->min_cable_length = e1000_m88_cable_length_table[index]; - phy->max_cable_length = e1000_m88_cable_length_table[index + 1]; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - - return 0; -} - -/** - * e1000e_get_cable_length_igp_2 - Determine cable length for igp2 PHY - * @hw: pointer to the HW structure - * - * The automatic gain control (agc) normalizes the amplitude of the - * received signal, adjusting for the attenuation produced by the - * cable. By reading the AGC registers, which represent the - * combination of coarse and fine gain value, the value can be put - * into a lookup table to obtain the approximate cable length - * for each channel. - **/ -s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, i, agc_value = 0; - u16 cur_agc_index, max_agc_index = 0; - u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; - static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = { - IGP02E1000_PHY_AGC_A, - IGP02E1000_PHY_AGC_B, - IGP02E1000_PHY_AGC_C, - IGP02E1000_PHY_AGC_D - }; - - /* Read the AGC registers for all channels */ - for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { - ret_val = e1e_rphy(hw, agc_reg_array[i], &phy_data); - if (ret_val) - return ret_val; - - /* Getting bits 15:9, which represent the combination of - * coarse and fine gain values. The result is a number - * that can be put into the lookup table to obtain the - * approximate cable length. - */ - cur_agc_index = ((phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & - IGP02E1000_AGC_LENGTH_MASK); - - /* Array index bound check. */ - if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) || - (cur_agc_index == 0)) - return -E1000_ERR_PHY; - - /* Remove min & max AGC values from calculation. */ - if (e1000_igp_2_cable_length_table[min_agc_index] > - e1000_igp_2_cable_length_table[cur_agc_index]) - min_agc_index = cur_agc_index; - if (e1000_igp_2_cable_length_table[max_agc_index] < - e1000_igp_2_cable_length_table[cur_agc_index]) - max_agc_index = cur_agc_index; - - agc_value += e1000_igp_2_cable_length_table[cur_agc_index]; - } - - agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] + - e1000_igp_2_cable_length_table[max_agc_index]); - agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); - - /* Calculate cable length with the error range of +/- 10 meters. */ - phy->min_cable_length = (((agc_value - IGP02E1000_AGC_RANGE) > 0) ? - (agc_value - IGP02E1000_AGC_RANGE) : 0); - phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE; - - phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; - - return 0; -} - -/** - * e1000e_get_phy_info_m88 - Retrieve PHY information - * @hw: pointer to the HW structure - * - * Valid for only copper links. Read the PHY status register (sticky read) - * to verify that link is up. Read the PHY special control register to - * determine the polarity and 10base-T extended distance. Read the PHY - * special status register to determine MDI/MDIx and current speed. If - * speed is 1000, then determine cable length, local and remote receiver. - **/ -s32 e1000e_get_phy_info_m88(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - if (phy->media_type != e1000_media_type_copper) { - e_dbg("Phy info is only valid for copper media\n"); - return -E1000_ERR_CONFIG; - } - - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (!link) { - e_dbg("Phy info is only valid if link is up\n"); - return -E1000_ERR_CONFIG; - } - - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); - if (ret_val) - return ret_val; - - phy->polarity_correction = !!(phy_data & - M88E1000_PSCR_POLARITY_REVERSAL); - - ret_val = e1000_check_polarity_m88(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); - if (ret_val) - return ret_val; - - phy->is_mdix = !!(phy_data & M88E1000_PSSR_MDIX); - - if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { - ret_val = hw->phy.ops.get_cable_length(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, MII_STAT1000, &phy_data); - if (ret_val) - return ret_val; - - phy->local_rx = (phy_data & LPA_1000LOCALRXOK) - ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - - phy->remote_rx = (phy_data & LPA_1000REMRXOK) - ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - } else { - /* Set values to "undefined" */ - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - } - - return ret_val; -} - -/** - * e1000e_get_phy_info_igp - Retrieve igp PHY information - * @hw: pointer to the HW structure - * - * Read PHY status to determine if link is up. If link is up, then - * set/determine 10base-T extended distance and polarity correction. Read - * PHY port status to determine MDI/MDIx and speed. Based on the speed, - * determine on the cable length, local and remote receiver. - **/ -s32 e1000e_get_phy_info_igp(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (!link) { - e_dbg("Phy info is only valid if link is up\n"); - return -E1000_ERR_CONFIG; - } - - phy->polarity_correction = true; - - ret_val = e1000_check_polarity_igp(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, IGP01E1000_PHY_PORT_STATUS, &data); - if (ret_val) - return ret_val; - - phy->is_mdix = !!(data & IGP01E1000_PSSR_MDIX); - - if ((data & IGP01E1000_PSSR_SPEED_MASK) == - IGP01E1000_PSSR_SPEED_1000MBPS) { - ret_val = phy->ops.get_cable_length(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, MII_STAT1000, &data); - if (ret_val) - return ret_val; - - phy->local_rx = (data & LPA_1000LOCALRXOK) - ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - - phy->remote_rx = (data & LPA_1000REMRXOK) - ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - } else { - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - } - - return ret_val; -} - -/** - * e1000_get_phy_info_ife - Retrieves various IFE PHY states - * @hw: pointer to the HW structure - * - * Populates "phy" structure with various feature states. - **/ -s32 e1000_get_phy_info_ife(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (!link) { - e_dbg("Phy info is only valid if link is up\n"); - return -E1000_ERR_CONFIG; - } - - ret_val = e1e_rphy(hw, IFE_PHY_SPECIAL_CONTROL, &data); - if (ret_val) - return ret_val; - phy->polarity_correction = !(data & IFE_PSC_AUTO_POLARITY_DISABLE); - - if (phy->polarity_correction) { - ret_val = e1000_check_polarity_ife(hw); - if (ret_val) - return ret_val; - } else { - /* Polarity is forced */ - phy->cable_polarity = ((data & IFE_PSC_FORCE_POLARITY) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal); - } - - ret_val = e1e_rphy(hw, IFE_PHY_MDIX_CONTROL, &data); - if (ret_val) - return ret_val; - - phy->is_mdix = !!(data & IFE_PMC_MDIX_STATUS); - - /* The following parameters are undefined for 10/100 operation. */ - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - - return 0; -} - -/** - * e1000e_phy_sw_reset - PHY software reset - * @hw: pointer to the HW structure - * - * Does a software reset of the PHY by reading the PHY control register and - * setting/write the control register reset bit to the PHY. - **/ -s32 e1000e_phy_sw_reset(struct e1000_hw *hw) -{ - s32 ret_val; - u16 phy_ctrl; - - ret_val = e1e_rphy(hw, MII_BMCR, &phy_ctrl); - if (ret_val) - return ret_val; - - phy_ctrl |= BMCR_RESET; - ret_val = e1e_wphy(hw, MII_BMCR, phy_ctrl); - if (ret_val) - return ret_val; - - udelay(1); - - return ret_val; -} - -/** - * e1000e_phy_hw_reset_generic - PHY hardware reset - * @hw: pointer to the HW structure - * - * Verify the reset block is not blocking us from resetting. Acquire - * semaphore (if necessary) and read/set/write the device control reset - * bit in the PHY. Wait the appropriate delay time for the device to - * reset and release the semaphore (if necessary). - **/ -s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u32 ctrl; - - if (phy->ops.check_reset_block) { - ret_val = phy->ops.check_reset_block(hw); - if (ret_val) - return 0; - } - - ret_val = phy->ops.acquire(hw); - if (ret_val) - return ret_val; - - ctrl = er32(CTRL); - ew32(CTRL, ctrl | E1000_CTRL_PHY_RST); - e1e_flush(); - - udelay(phy->reset_delay_us); - - ew32(CTRL, ctrl); - e1e_flush(); - - usleep_range(150, 300); - - phy->ops.release(hw); - - return phy->ops.get_cfg_done(hw); -} - -/** - * e1000e_get_cfg_done_generic - Generic configuration done - * @hw: pointer to the HW structure - * - * Generic function to wait 10 milli-seconds for configuration to complete - * and return success. - **/ -s32 e1000e_get_cfg_done_generic(struct e1000_hw __always_unused *hw) -{ - mdelay(10); - - return 0; -} - -/** - * e1000e_phy_init_script_igp3 - Inits the IGP3 PHY - * @hw: pointer to the HW structure - * - * Initializes a Intel Gigabit PHY3 when an EEPROM is not present. - **/ -s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw) -{ - e_dbg("Running IGP 3 PHY init script\n"); - - /* PHY init IGP 3 */ - /* Enable rise/fall, 10-mode work in class-A */ - e1e_wphy(hw, 0x2F5B, 0x9018); - /* Remove all caps from Replica path filter */ - e1e_wphy(hw, 0x2F52, 0x0000); - /* Bias trimming for ADC, AFE and Driver (Default) */ - e1e_wphy(hw, 0x2FB1, 0x8B24); - /* Increase Hybrid poly bias */ - e1e_wphy(hw, 0x2FB2, 0xF8F0); - /* Add 4% to Tx amplitude in Gig mode */ - e1e_wphy(hw, 0x2010, 0x10B0); - /* Disable trimming (TTT) */ - e1e_wphy(hw, 0x2011, 0x0000); - /* Poly DC correction to 94.6% + 2% for all channels */ - e1e_wphy(hw, 0x20DD, 0x249A); - /* ABS DC correction to 95.9% */ - e1e_wphy(hw, 0x20DE, 0x00D3); - /* BG temp curve trim */ - e1e_wphy(hw, 0x28B4, 0x04CE); - /* Increasing ADC OPAMP stage 1 currents to max */ - e1e_wphy(hw, 0x2F70, 0x29E4); - /* Force 1000 ( required for enabling PHY regs configuration) */ - e1e_wphy(hw, 0x0000, 0x0140); - /* Set upd_freq to 6 */ - e1e_wphy(hw, 0x1F30, 0x1606); - /* Disable NPDFE */ - e1e_wphy(hw, 0x1F31, 0xB814); - /* Disable adaptive fixed FFE (Default) */ - e1e_wphy(hw, 0x1F35, 0x002A); - /* Enable FFE hysteresis */ - e1e_wphy(hw, 0x1F3E, 0x0067); - /* Fixed FFE for short cable lengths */ - e1e_wphy(hw, 0x1F54, 0x0065); - /* Fixed FFE for medium cable lengths */ - e1e_wphy(hw, 0x1F55, 0x002A); - /* Fixed FFE for long cable lengths */ - e1e_wphy(hw, 0x1F56, 0x002A); - /* Enable Adaptive Clip Threshold */ - e1e_wphy(hw, 0x1F72, 0x3FB0); - /* AHT reset limit to 1 */ - e1e_wphy(hw, 0x1F76, 0xC0FF); - /* Set AHT master delay to 127 msec */ - e1e_wphy(hw, 0x1F77, 0x1DEC); - /* Set scan bits for AHT */ - e1e_wphy(hw, 0x1F78, 0xF9EF); - /* Set AHT Preset bits */ - e1e_wphy(hw, 0x1F79, 0x0210); - /* Change integ_factor of channel A to 3 */ - e1e_wphy(hw, 0x1895, 0x0003); - /* Change prop_factor of channels BCD to 8 */ - e1e_wphy(hw, 0x1796, 0x0008); - /* Change cg_icount + enable integbp for channels BCD */ - e1e_wphy(hw, 0x1798, 0xD008); - /* Change cg_icount + enable integbp + change prop_factor_master - * to 8 for channel A - */ - e1e_wphy(hw, 0x1898, 0xD918); - /* Disable AHT in Slave mode on channel A */ - e1e_wphy(hw, 0x187A, 0x0800); - /* Enable LPLU and disable AN to 1000 in non-D0a states, - * Enable SPD+B2B - */ - e1e_wphy(hw, 0x0019, 0x008D); - /* Enable restart AN on an1000_dis change */ - e1e_wphy(hw, 0x001B, 0x2080); - /* Enable wh_fifo read clock in 10/100 modes */ - e1e_wphy(hw, 0x0014, 0x0045); - /* Restart AN, Speed selection is 1000 */ - e1e_wphy(hw, 0x0000, 0x1340); - - return 0; -} - -/** - * e1000e_get_phy_type_from_id - Get PHY type from id - * @phy_id: phy_id read from the phy - * - * Returns the phy type from the id. - **/ -enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id) -{ - enum e1000_phy_type phy_type = e1000_phy_unknown; - - switch (phy_id) { - case M88E1000_I_PHY_ID: - case M88E1000_E_PHY_ID: - case M88E1111_I_PHY_ID: - case M88E1011_I_PHY_ID: - phy_type = e1000_phy_m88; - break; - case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ - phy_type = e1000_phy_igp_2; - break; - case GG82563_E_PHY_ID: - phy_type = e1000_phy_gg82563; - break; - case IGP03E1000_E_PHY_ID: - phy_type = e1000_phy_igp_3; - break; - case IFE_E_PHY_ID: - case IFE_PLUS_E_PHY_ID: - case IFE_C_E_PHY_ID: - phy_type = e1000_phy_ife; - break; - case BME1000_E_PHY_ID: - case BME1000_E_PHY_ID_R2: - phy_type = e1000_phy_bm; - break; - case I82578_E_PHY_ID: - phy_type = e1000_phy_82578; - break; - case I82577_E_PHY_ID: - phy_type = e1000_phy_82577; - break; - case I82579_E_PHY_ID: - phy_type = e1000_phy_82579; - break; - case I217_E_PHY_ID: - phy_type = e1000_phy_i217; - break; - default: - phy_type = e1000_phy_unknown; - break; - } - return phy_type; -} - -/** - * e1000e_determine_phy_address - Determines PHY address. - * @hw: pointer to the HW structure - * - * This uses a trial and error method to loop through possible PHY - * addresses. It tests each by reading the PHY ID registers and - * checking for a match. - **/ -s32 e1000e_determine_phy_address(struct e1000_hw *hw) -{ - u32 phy_addr = 0; - u32 i; - enum e1000_phy_type phy_type = e1000_phy_unknown; - - hw->phy.id = phy_type; - - for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) { - hw->phy.addr = phy_addr; - i = 0; - - do { - e1000e_get_phy_id(hw); - phy_type = e1000e_get_phy_type_from_id(hw->phy.id); - - /* If phy_type is valid, break - we found our - * PHY address - */ - if (phy_type != e1000_phy_unknown) - return 0; - - usleep_range(1000, 2000); - i++; - } while (i < 10); - } - - return -E1000_ERR_PHY_TYPE; -} - -/** - * e1000_get_phy_addr_for_bm_page - Retrieve PHY page address - * @page: page to access - * - * Returns the phy address for the page requested. - **/ -static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg) -{ - u32 phy_addr = 2; - - if ((page >= 768) || (page == 0 && reg == 25) || (reg == 31)) - phy_addr = 1; - - return phy_addr; -} - -/** - * e1000e_write_phy_reg_bm - Write BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val; - u32 page = offset >> IGP_PAGE_SHIFT; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, - false, false); - goto release; - } - - hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - u32 page_shift, page_select; - - /* Page select is register 31 for phy address 1 and 22 for - * phy address 2 and 3. Page select is shifted only for - * phy address 1. - */ - if (hw->phy.addr == 1) { - page_shift = IGP_PAGE_SHIFT; - page_select = IGP01E1000_PHY_PAGE_SELECT; - } else { - page_shift = 0; - page_select = BM_PHY_PAGE_SELECT; - } - - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, page_select, - (page << page_shift)); - if (ret_val) - goto release; - } - - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - -release: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000e_read_phy_reg_bm - Read BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val; - u32 page = offset >> IGP_PAGE_SHIFT; - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, - true, false); - goto release; - } - - hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - u32 page_shift, page_select; - - /* Page select is register 31 for phy address 1 and 22 for - * phy address 2 and 3. Page select is shifted only for - * phy address 1. - */ - if (hw->phy.addr == 1) { - page_shift = IGP_PAGE_SHIFT; - page_select = IGP01E1000_PHY_PAGE_SELECT; - } else { - page_shift = 0; - page_select = BM_PHY_PAGE_SELECT; - } - - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, page_select, - (page << page_shift)); - if (ret_val) - goto release; - } - - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); -release: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000e_read_phy_reg_bm2 - Read BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and storing the retrieved information in data. Release any acquired - * semaphores before exiting. - **/ -s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) -{ - s32 ret_val; - u16 page = (u16)(offset >> IGP_PAGE_SHIFT); - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, - true, false); - goto release; - } - - hw->phy.addr = 1; - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, - page); - - if (ret_val) - goto release; - } - - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); -release: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000e_write_phy_reg_bm2 - Write BM PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) -{ - s32 ret_val; - u16 page = (u16)(offset >> IGP_PAGE_SHIFT); - - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, - false, false); - goto release; - } - - hw->phy.addr = 1; - - if (offset > MAX_PHY_MULTI_PAGE_REG) { - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, - page); - - if (ret_val) - goto release; - } - - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, - data); - -release: - hw->phy.ops.release(hw); - return ret_val; -} - -/** - * e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers - * @hw: pointer to the HW structure - * @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG - * - * Assumes semaphore already acquired and phy_reg points to a valid memory - * address to store contents of the BM_WUC_ENABLE_REG register. - **/ -s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) -{ - s32 ret_val; - u16 temp; - - /* All page select, port ctrl and wakeup registers use phy address 1 */ - hw->phy.addr = 1; - - /* Select Port Control Registers page */ - ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); - if (ret_val) { - e_dbg("Could not set Port Control page\n"); - return ret_val; - } - - ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); - if (ret_val) { - e_dbg("Could not read PHY register %d.%d\n", - BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); - return ret_val; - } - - /* Enable both PHY wakeup mode and Wakeup register page writes. - * Prevent a power state change by disabling ME and Host PHY wakeup. - */ - temp = *phy_reg; - temp |= BM_WUC_ENABLE_BIT; - temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT); - - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp); - if (ret_val) { - e_dbg("Could not write PHY register %d.%d\n", - BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); - return ret_val; - } - - /* Select Host Wakeup Registers page - caller now able to write - * registers on the Wakeup registers page - */ - return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT)); -} - -/** - * e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs - * @hw: pointer to the HW structure - * @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG - * - * Restore BM_WUC_ENABLE_REG to its original value. - * - * Assumes semaphore already acquired and *phy_reg is the contents of the - * BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by - * caller. - **/ -s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg) -{ - s32 ret_val; - - /* Select Port Control Registers page */ - ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); - if (ret_val) { - e_dbg("Could not set Port Control page\n"); - return ret_val; - } - - /* Restore 769.17 to its original value */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg); - if (ret_val) - e_dbg("Could not restore PHY register %d.%d\n", - BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG); - - return ret_val; -} - -/** - * e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register - * @hw: pointer to the HW structure - * @offset: register offset to be read or written - * @data: pointer to the data to read or write - * @read: determines if operation is read or write - * @page_set: BM_WUC_PAGE already set and access enabled - * - * Read the PHY register at offset and store the retrieved information in - * data, or write data to PHY register at offset. Note the procedure to - * access the PHY wakeup registers is different than reading the other PHY - * registers. It works as such: - * 1) Set 769.17.2 (page 769, register 17, bit 2) = 1 - * 2) Set page to 800 for host (801 if we were manageability) - * 3) Write the address using the address opcode (0x11) - * 4) Read or write the data using the data opcode (0x12) - * 5) Restore 769.17.2 to its original value - * - * Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and - * step 5 is done by e1000_disable_phy_wakeup_reg_access_bm(). - * - * Assumes semaphore is already acquired. When page_set==true, assumes - * the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack - * is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()). - **/ -static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, - u16 *data, bool read, bool page_set) -{ - s32 ret_val; - u16 reg = BM_PHY_REG_NUM(offset); - u16 page = BM_PHY_REG_PAGE(offset); - u16 phy_reg = 0; - - /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */ - if ((hw->mac.type == e1000_pchlan) && - (!(er32(PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) - e_dbg("Attempting to access page %d while gig enabled.\n", - page); - - if (!page_set) { - /* Enable access to PHY wakeup registers */ - ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg); - if (ret_val) { - e_dbg("Could not enable PHY wakeup reg access\n"); - return ret_val; - } - } - - e_dbg("Accessing PHY page %d reg 0x%x\n", page, reg); - - /* Write the Wakeup register page offset value using opcode 0x11 */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg); - if (ret_val) { - e_dbg("Could not write address opcode to page %d\n", page); - return ret_val; - } - - if (read) { - /* Read the Wakeup register page value using opcode 0x12 */ - ret_val = e1000e_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, - data); - } else { - /* Write the Wakeup register page value using opcode 0x12 */ - ret_val = e1000e_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, - *data); - } - - if (ret_val) { - e_dbg("Could not access PHY reg %d.%d\n", page, reg); - return ret_val; - } - - if (!page_set) - ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg); - - return ret_val; -} - -/** - * e1000_power_up_phy_copper - Restore copper link in case of PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, restore the link to previous - * settings. - **/ -void e1000_power_up_phy_copper(struct e1000_hw *hw) -{ - u16 mii_reg = 0; - - /* The PHY will retain its settings across a power down/up cycle */ - e1e_rphy(hw, MII_BMCR, &mii_reg); - mii_reg &= ~BMCR_PDOWN; - e1e_wphy(hw, MII_BMCR, mii_reg); -} - -/** - * e1000_power_down_phy_copper - Restore copper link in case of PHY power down - * @hw: pointer to the HW structure - * - * In the case of a PHY power down to save power, or to turn off link during a - * driver unload, or wake on lan is not enabled, restore the link to previous - * settings. - **/ -void e1000_power_down_phy_copper(struct e1000_hw *hw) -{ - u16 mii_reg = 0; - - /* The PHY will retain its settings across a power down/up cycle */ - e1e_rphy(hw, MII_BMCR, &mii_reg); - mii_reg |= BMCR_PDOWN; - e1e_wphy(hw, MII_BMCR, mii_reg); - usleep_range(1000, 2000); -} - -/** - * __e1000_read_phy_reg_hv - Read HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then reads the PHY register at offset - * and stores the retrieved information in data. Release any acquired - * semaphore before exiting. - **/ -static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data, - bool locked, bool page_set) -{ - s32 ret_val; - u16 page = BM_PHY_REG_PAGE(offset); - u16 reg = BM_PHY_REG_NUM(offset); - u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); - - if (!locked) { - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, - true, page_set); - goto out; - } - - if (page > 0 && page < HV_INTC_FC_PAGE_START) { - ret_val = e1000_access_phy_debug_regs_hv(hw, offset, - data, true); - goto out; - } - - if (!page_set) { - if (page == HV_INTC_FC_PAGE_START) - page = 0; - - if (reg > MAX_PHY_MULTI_PAGE_REG) { - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000_set_page_igp(hw, - (page << IGP_PAGE_SHIFT)); - - hw->phy.addr = phy_addr; - - if (ret_val) - goto out; - } - } - - e_dbg("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page, - page << IGP_PAGE_SHIFT, reg); - - ret_val = e1000e_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, data); -out: - if (!locked) - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_read_phy_reg_hv - Read HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Acquires semaphore then reads the PHY register at offset and stores - * the retrieved information in data. Release the acquired semaphore - * before exiting. - **/ -s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000_read_phy_reg_hv(hw, offset, data, false, false); -} - -/** - * e1000_read_phy_reg_hv_locked - Read HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to be read - * @data: pointer to the read data - * - * Reads the PHY register at offset and stores the retrieved information - * in data. Assumes semaphore already acquired. - **/ -s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000_read_phy_reg_hv(hw, offset, data, true, false); -} - -/** - * e1000_read_phy_reg_page_hv - Read HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Reads the PHY register at offset and stores the retrieved information - * in data. Assumes semaphore already acquired and page already set. - **/ -s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data) -{ - return __e1000_read_phy_reg_hv(hw, offset, data, true, true); -} - -/** - * __e1000_write_phy_reg_hv - Write HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * @locked: semaphore has already been acquired or not - * - * Acquires semaphore, if necessary, then writes the data to PHY register - * at the offset. Release any acquired semaphores before exiting. - **/ -static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data, - bool locked, bool page_set) -{ - s32 ret_val; - u16 page = BM_PHY_REG_PAGE(offset); - u16 reg = BM_PHY_REG_NUM(offset); - u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); - - if (!locked) { - ret_val = hw->phy.ops.acquire(hw); - if (ret_val) - return ret_val; - } - - /* Page 800 works differently than the rest so it has its own func */ - if (page == BM_WUC_PAGE) { - ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, - false, page_set); - goto out; - } - - if (page > 0 && page < HV_INTC_FC_PAGE_START) { - ret_val = e1000_access_phy_debug_regs_hv(hw, offset, - &data, false); - goto out; - } - - if (!page_set) { - if (page == HV_INTC_FC_PAGE_START) - page = 0; - - /* Workaround MDIO accesses being disabled after entering IEEE - * Power Down (when bit 11 of the PHY Control register is set) - */ - if ((hw->phy.type == e1000_phy_82578) && - (hw->phy.revision >= 1) && - (hw->phy.addr == 2) && - !(MAX_PHY_REG_ADDRESS & reg) && (data & (1 << 11))) { - u16 data2 = 0x7EFF; - - ret_val = e1000_access_phy_debug_regs_hv(hw, - (1 << 6) | 0x3, - &data2, false); - if (ret_val) - goto out; - } - - if (reg > MAX_PHY_MULTI_PAGE_REG) { - /* Page is shifted left, PHY expects (page x 32) */ - ret_val = e1000_set_page_igp(hw, - (page << IGP_PAGE_SHIFT)); - - hw->phy.addr = phy_addr; - - if (ret_val) - goto out; - } - } - - e_dbg("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page, - page << IGP_PAGE_SHIFT, reg); - - ret_val = e1000e_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, - data); - -out: - if (!locked) - hw->phy.ops.release(hw); - - return ret_val; -} - -/** - * e1000_write_phy_reg_hv - Write HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Acquires semaphore then writes the data to PHY register at the offset. - * Release the acquired semaphores before exiting. - **/ -s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000_write_phy_reg_hv(hw, offset, data, false, false); -} - -/** - * e1000_write_phy_reg_hv_locked - Write HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Writes the data to PHY register at the offset. Assumes semaphore - * already acquired. - **/ -s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000_write_phy_reg_hv(hw, offset, data, true, false); -} - -/** - * e1000_write_phy_reg_page_hv - Write HV PHY register - * @hw: pointer to the HW structure - * @offset: register offset to write to - * @data: data to write at register offset - * - * Writes the data to PHY register at the offset. Assumes semaphore - * already acquired and page already set. - **/ -s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data) -{ - return __e1000_write_phy_reg_hv(hw, offset, data, true, true); -} - -/** - * e1000_get_phy_addr_for_hv_page - Get PHY address based on page - * @page: page to be accessed - **/ -static u32 e1000_get_phy_addr_for_hv_page(u32 page) -{ - u32 phy_addr = 2; - - if (page >= HV_INTC_FC_PAGE_START) - phy_addr = 1; - - return phy_addr; -} - -/** - * e1000_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers - * @hw: pointer to the HW structure - * @offset: register offset to be read or written - * @data: pointer to the data to be read or written - * @read: determines if operation is read or write - * - * Reads the PHY register at offset and stores the retreived information - * in data. Assumes semaphore already acquired. Note that the procedure - * to access these regs uses the address port and data port to read/write. - * These accesses done with PHY address 2 and without using pages. - **/ -static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, - u16 *data, bool read) -{ - s32 ret_val; - u32 addr_reg; - u32 data_reg; - - /* This takes care of the difference with desktop vs mobile phy */ - addr_reg = ((hw->phy.type == e1000_phy_82578) ? - I82578_ADDR_REG : I82577_ADDR_REG); - data_reg = addr_reg + 1; - - /* All operations in this function are phy address 2 */ - hw->phy.addr = 2; - - /* masking with 0x3F to remove the page from offset */ - ret_val = e1000e_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F); - if (ret_val) { - e_dbg("Could not write the Address Offset port register\n"); - return ret_val; - } - - /* Read or write the data value next */ - if (read) - ret_val = e1000e_read_phy_reg_mdic(hw, data_reg, data); - else - ret_val = e1000e_write_phy_reg_mdic(hw, data_reg, *data); - - if (ret_val) - e_dbg("Could not access the Data port register\n"); - - return ret_val; -} - -/** - * e1000_link_stall_workaround_hv - Si workaround - * @hw: pointer to the HW structure - * - * This function works around a Si bug where the link partner can get - * a link up indication before the PHY does. If small packets are sent - * by the link partner they can be placed in the packet buffer without - * being properly accounted for by the PHY and will stall preventing - * further packets from being received. The workaround is to clear the - * packet buffer after the PHY detects link up. - **/ -s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw) -{ - s32 ret_val = 0; - u16 data; - - if (hw->phy.type != e1000_phy_82578) - return 0; - - /* Do not apply workaround if in PHY loopback bit 14 set */ - e1e_rphy(hw, MII_BMCR, &data); - if (data & BMCR_LOOPBACK) - return 0; - - /* check if link is up and at 1Gbps */ - ret_val = e1e_rphy(hw, BM_CS_STATUS, &data); - if (ret_val) - return ret_val; - - data &= (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_MASK); - - if (data != (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED | - BM_CS_STATUS_SPEED_1000)) - return 0; - - msleep(200); - - /* flush the packets in the fifo buffer */ - ret_val = e1e_wphy(hw, HV_MUX_DATA_CTRL, - (HV_MUX_DATA_CTRL_GEN_TO_MAC | - HV_MUX_DATA_CTRL_FORCE_SPEED)); - if (ret_val) - return ret_val; - - return e1e_wphy(hw, HV_MUX_DATA_CTRL, HV_MUX_DATA_CTRL_GEN_TO_MAC); -} - -/** - * e1000_check_polarity_82577 - Checks the polarity. - * @hw: pointer to the HW structure - * - * Success returns 0, Failure returns -E1000_ERR_PHY (-2) - * - * Polarity is determined based on the PHY specific status register. - **/ -s32 e1000_check_polarity_82577(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - - ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data); - - if (!ret_val) - phy->cable_polarity = ((data & I82577_PHY_STATUS2_REV_POLARITY) - ? e1000_rev_polarity_reversed - : e1000_rev_polarity_normal); - - return ret_val; -} - -/** - * e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY - * @hw: pointer to the HW structure - * - * Calls the PHY setup function to force speed and duplex. - **/ -s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data; - bool link; - - ret_val = e1e_rphy(hw, MII_BMCR, &phy_data); - if (ret_val) - return ret_val; - - e1000e_phy_force_speed_duplex_setup(hw, &phy_data); - - ret_val = e1e_wphy(hw, MII_BMCR, phy_data); - if (ret_val) - return ret_val; - - udelay(1); - - if (phy->autoneg_wait_to_complete) { - e_dbg("Waiting for forced speed/duplex link on 82577 phy\n"); - - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - if (ret_val) - return ret_val; - - if (!link) - e_dbg("Link taking longer than expected.\n"); - - /* Try once more */ - ret_val = e1000e_phy_has_link_generic(hw, PHY_FORCE_LIMIT, - 100000, &link); - } - - return ret_val; -} - -/** - * e1000_get_phy_info_82577 - Retrieve I82577 PHY information - * @hw: pointer to the HW structure - * - * Read PHY status to determine if link is up. If link is up, then - * set/determine 10base-T extended distance and polarity correction. Read - * PHY port status to determine MDI/MDIx and speed. Based on the speed, - * determine on the cable length, local and remote receiver. - **/ -s32 e1000_get_phy_info_82577(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 data; - bool link; - - ret_val = e1000e_phy_has_link_generic(hw, 1, 0, &link); - if (ret_val) - return ret_val; - - if (!link) { - e_dbg("Phy info is only valid if link is up\n"); - return -E1000_ERR_CONFIG; - } - - phy->polarity_correction = true; - - ret_val = e1000_check_polarity_82577(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, I82577_PHY_STATUS_2, &data); - if (ret_val) - return ret_val; - - phy->is_mdix = !!(data & I82577_PHY_STATUS2_MDIX); - - if ((data & I82577_PHY_STATUS2_SPEED_MASK) == - I82577_PHY_STATUS2_SPEED_1000MBPS) { - ret_val = hw->phy.ops.get_cable_length(hw); - if (ret_val) - return ret_val; - - ret_val = e1e_rphy(hw, MII_STAT1000, &data); - if (ret_val) - return ret_val; - - phy->local_rx = (data & LPA_1000LOCALRXOK) - ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - - phy->remote_rx = (data & LPA_1000REMRXOK) - ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; - } else { - phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; - phy->local_rx = e1000_1000t_rx_status_undefined; - phy->remote_rx = e1000_1000t_rx_status_undefined; - } - - return 0; -} - -/** - * e1000_get_cable_length_82577 - Determine cable length for 82577 PHY - * @hw: pointer to the HW structure - * - * Reads the diagnostic status register and verifies result is valid before - * placing it in the phy_cable_length field. - **/ -s32 e1000_get_cable_length_82577(struct e1000_hw *hw) -{ - struct e1000_phy_info *phy = &hw->phy; - s32 ret_val; - u16 phy_data, length; - - ret_val = e1e_rphy(hw, I82577_PHY_DIAG_STATUS, &phy_data); - if (ret_val) - return ret_val; - - length = ((phy_data & I82577_DSTATUS_CABLE_LENGTH) >> - I82577_DSTATUS_CABLE_LENGTH_SHIFT); - - if (length == E1000_CABLE_LENGTH_UNDEFINED) - return -E1000_ERR_PHY; - - phy->cable_length = length; - - return 0; -} diff --git a/addons/e1000e/src/4.4.180/phy.h b/addons/e1000e/src/4.4.180/phy.h deleted file mode 100644 index 55bfe473..00000000 --- a/addons/e1000e/src/4.4.180/phy.h +++ /dev/null @@ -1,236 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#ifndef _E1000E_PHY_H_ -#define _E1000E_PHY_H_ - -s32 e1000e_check_downshift(struct e1000_hw *hw); -s32 e1000_check_polarity_m88(struct e1000_hw *hw); -s32 e1000_check_polarity_igp(struct e1000_hw *hw); -s32 e1000_check_polarity_ife(struct e1000_hw *hw); -s32 e1000e_check_reset_block_generic(struct e1000_hw *hw); -s32 e1000e_copper_link_setup_igp(struct e1000_hw *hw); -s32 e1000e_copper_link_setup_m88(struct e1000_hw *hw); -s32 e1000e_phy_force_speed_duplex_igp(struct e1000_hw *hw); -s32 e1000e_phy_force_speed_duplex_m88(struct e1000_hw *hw); -s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw); -s32 e1000e_get_cable_length_m88(struct e1000_hw *hw); -s32 e1000e_get_cable_length_igp_2(struct e1000_hw *hw); -s32 e1000e_get_cfg_done_generic(struct e1000_hw *hw); -s32 e1000e_get_phy_id(struct e1000_hw *hw); -s32 e1000e_get_phy_info_igp(struct e1000_hw *hw); -s32 e1000e_get_phy_info_m88(struct e1000_hw *hw); -s32 e1000_get_phy_info_ife(struct e1000_hw *hw); -s32 e1000e_phy_sw_reset(struct e1000_hw *hw); -void e1000e_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl); -s32 e1000e_phy_hw_reset_generic(struct e1000_hw *hw); -s32 e1000e_phy_reset_dsp(struct e1000_hw *hw); -s32 e1000e_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page); -s32 e1000e_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_set_d3_lplu_state(struct e1000_hw *hw, bool active); -s32 e1000e_setup_copper_link(struct e1000_hw *hw); -s32 e1000e_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, - u32 usec_interval, bool *success); -s32 e1000e_phy_init_script_igp3(struct e1000_hw *hw); -enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id); -s32 e1000e_determine_phy_address(struct e1000_hw *hw); -s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg); -s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg); -s32 e1000e_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data); -void e1000_power_up_phy_copper(struct e1000_hw *hw); -void e1000_power_down_phy_copper(struct e1000_hw *hw); -s32 e1000e_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000e_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data); -s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data); -s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw); -s32 e1000_copper_link_setup_82577(struct e1000_hw *hw); -s32 e1000_check_polarity_82577(struct e1000_hw *hw); -s32 e1000_get_phy_info_82577(struct e1000_hw *hw); -s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw); -s32 e1000_get_cable_length_82577(struct e1000_hw *hw); - -#define E1000_MAX_PHY_ADDR 8 - -/* IGP01E1000 Specific Registers */ -#define IGP01E1000_PHY_PORT_CONFIG 0x10 /* Port Config */ -#define IGP01E1000_PHY_PORT_STATUS 0x11 /* Status */ -#define IGP01E1000_PHY_PORT_CTRL 0x12 /* Control */ -#define IGP01E1000_PHY_LINK_HEALTH 0x13 /* PHY Link Health */ -#define IGP02E1000_PHY_POWER_MGMT 0x19 /* Power Management */ -#define IGP01E1000_PHY_PAGE_SELECT 0x1F /* Page Select */ -#define BM_PHY_PAGE_SELECT 22 /* Page Select for BM */ -#define IGP_PAGE_SHIFT 5 -#define PHY_REG_MASK 0x1F - -/* BM/HV Specific Registers */ -#define BM_PORT_CTRL_PAGE 769 -#define BM_WUC_PAGE 800 -#define BM_WUC_ADDRESS_OPCODE 0x11 -#define BM_WUC_DATA_OPCODE 0x12 -#define BM_WUC_ENABLE_PAGE BM_PORT_CTRL_PAGE -#define BM_WUC_ENABLE_REG 17 -#define BM_WUC_ENABLE_BIT (1 << 2) -#define BM_WUC_HOST_WU_BIT (1 << 4) -#define BM_WUC_ME_WU_BIT (1 << 5) - -#define PHY_UPPER_SHIFT 21 -#define BM_PHY_REG(page, reg) \ - (((reg) & MAX_PHY_REG_ADDRESS) |\ - (((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\ - (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT))) -#define BM_PHY_REG_PAGE(offset) \ - ((u16)(((offset) >> PHY_PAGE_SHIFT) & 0xFFFF)) -#define BM_PHY_REG_NUM(offset) \ - ((u16)(((offset) & MAX_PHY_REG_ADDRESS) |\ - (((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\ - ~MAX_PHY_REG_ADDRESS))) - -#define HV_INTC_FC_PAGE_START 768 -#define I82578_ADDR_REG 29 -#define I82577_ADDR_REG 16 -#define I82577_CFG_REG 22 -#define I82577_CFG_ASSERT_CRS_ON_TX (1 << 15) -#define I82577_CFG_ENABLE_DOWNSHIFT (3 << 10) /* auto downshift */ -#define I82577_CTRL_REG 23 - -/* 82577 specific PHY registers */ -#define I82577_PHY_CTRL_2 18 -#define I82577_PHY_LBK_CTRL 19 -#define I82577_PHY_STATUS_2 26 -#define I82577_PHY_DIAG_STATUS 31 - -/* I82577 PHY Status 2 */ -#define I82577_PHY_STATUS2_REV_POLARITY 0x0400 -#define I82577_PHY_STATUS2_MDIX 0x0800 -#define I82577_PHY_STATUS2_SPEED_MASK 0x0300 -#define I82577_PHY_STATUS2_SPEED_1000MBPS 0x0200 - -/* I82577 PHY Control 2 */ -#define I82577_PHY_CTRL2_MANUAL_MDIX 0x0200 -#define I82577_PHY_CTRL2_AUTO_MDI_MDIX 0x0400 -#define I82577_PHY_CTRL2_MDIX_CFG_MASK 0x0600 - -/* I82577 PHY Diagnostics Status */ -#define I82577_DSTATUS_CABLE_LENGTH 0x03FC -#define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2 - -/* BM PHY Copper Specific Control 1 */ -#define BM_CS_CTRL1 16 - -/* BM PHY Copper Specific Status */ -#define BM_CS_STATUS 17 -#define BM_CS_STATUS_LINK_UP 0x0400 -#define BM_CS_STATUS_RESOLVED 0x0800 -#define BM_CS_STATUS_SPEED_MASK 0xC000 -#define BM_CS_STATUS_SPEED_1000 0x8000 - -/* 82577 Mobile Phy Status Register */ -#define HV_M_STATUS 26 -#define HV_M_STATUS_AUTONEG_COMPLETE 0x1000 -#define HV_M_STATUS_SPEED_MASK 0x0300 -#define HV_M_STATUS_SPEED_1000 0x0200 -#define HV_M_STATUS_SPEED_100 0x0100 -#define HV_M_STATUS_LINK_UP 0x0040 - -#define IGP01E1000_PHY_PCS_INIT_REG 0x00B4 -#define IGP01E1000_PHY_POLARITY_MASK 0x0078 - -#define IGP01E1000_PSCR_AUTO_MDIX 0x1000 -#define IGP01E1000_PSCR_FORCE_MDI_MDIX 0x2000 /* 0=MDI, 1=MDIX */ - -#define IGP01E1000_PSCFR_SMART_SPEED 0x0080 - -#define IGP02E1000_PM_SPD 0x0001 /* Smart Power Down */ -#define IGP02E1000_PM_D0_LPLU 0x0002 /* For D0a states */ -#define IGP02E1000_PM_D3_LPLU 0x0004 /* For all other states */ - -#define IGP01E1000_PLHR_SS_DOWNGRADE 0x8000 - -#define IGP01E1000_PSSR_POLARITY_REVERSED 0x0002 -#define IGP01E1000_PSSR_MDIX 0x0800 -#define IGP01E1000_PSSR_SPEED_MASK 0xC000 -#define IGP01E1000_PSSR_SPEED_1000MBPS 0xC000 - -#define IGP02E1000_PHY_CHANNEL_NUM 4 -#define IGP02E1000_PHY_AGC_A 0x11B1 -#define IGP02E1000_PHY_AGC_B 0x12B1 -#define IGP02E1000_PHY_AGC_C 0x14B1 -#define IGP02E1000_PHY_AGC_D 0x18B1 - -#define IGP02E1000_AGC_LENGTH_SHIFT 9 /* Course=15:13, Fine=12:9 */ -#define IGP02E1000_AGC_LENGTH_MASK 0x7F -#define IGP02E1000_AGC_RANGE 15 - -#define E1000_CABLE_LENGTH_UNDEFINED 0xFF - -#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 -#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 -#define E1000_KMRNCTRLSTA_REN 0x00200000 -#define E1000_KMRNCTRLSTA_CTRL_OFFSET 0x1 /* Kumeran Control */ -#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ -#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ -#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ -#define E1000_KMRNCTRLSTA_IBIST_DISABLE 0x0200 /* Kumeran IBIST Disable */ -#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ -#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 -#define E1000_KMRNCTRLSTA_K1_ENABLE 0x0002 /* enable K1 */ -#define E1000_KMRNCTRLSTA_HD_CTRL 0x10 /* Kumeran HD Control */ - -#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 -#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Ctrl */ -#define IFE_PHY_SPECIAL_CONTROL_LED 0x1B /* PHY Special and LED Ctrl */ -#define IFE_PHY_MDIX_CONTROL 0x1C /* MDI/MDI-X Control */ - -/* IFE PHY Extended Status Control */ -#define IFE_PESC_POLARITY_REVERSED 0x0100 - -/* IFE PHY Special Control */ -#define IFE_PSC_AUTO_POLARITY_DISABLE 0x0010 -#define IFE_PSC_FORCE_POLARITY 0x0020 - -/* IFE PHY Special Control and LED Control */ -#define IFE_PSCL_PROBE_MODE 0x0020 -#define IFE_PSCL_PROBE_LEDS_OFF 0x0006 /* Force LEDs 0 and 2 off */ -#define IFE_PSCL_PROBE_LEDS_ON 0x0007 /* Force LEDs 0 and 2 on */ - -/* IFE PHY MDIX Control */ -#define IFE_PMC_MDIX_STATUS 0x0020 /* 1=MDI-X, 0=MDI */ -#define IFE_PMC_FORCE_MDIX 0x0040 /* 1=force MDI-X, 0=force MDI */ -#define IFE_PMC_AUTO_MDIX 0x0080 /* 1=enable auto, 0=disable */ - -#endif diff --git a/addons/e1000e/src/4.4.180/ptp.c b/addons/e1000e/src/4.4.180/ptp.c deleted file mode 100644 index 855cf8c1..00000000 --- a/addons/e1000e/src/4.4.180/ptp.c +++ /dev/null @@ -1,280 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -/* PTP 1588 Hardware Clock (PHC) - * Derived from PTP Hardware Clock driver for Intel 82576 and 82580 (igb) - * Copyright (C) 2011 Richard Cochran - */ - -#include "e1000.h" - -/** - * e1000e_phc_adjfreq - adjust the frequency of the hardware clock - * @ptp: ptp clock structure - * @delta: Desired frequency change in parts per billion - * - * Adjust the frequency of the PHC cycle counter by the indicated delta from - * the base frequency. - **/ -static int e1000e_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) -{ - struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, - ptp_clock_info); - struct e1000_hw *hw = &adapter->hw; - bool neg_adj = false; - unsigned long flags; - u64 adjustment; - u32 timinca, incvalue; - s32 ret_val; - - if ((delta > ptp->max_adj) || (delta <= -1000000000)) - return -EINVAL; - - if (delta < 0) { - neg_adj = true; - delta = -delta; - } - - /* Get the System Time Register SYSTIM base frequency */ - ret_val = e1000e_get_base_timinca(adapter, &timinca); - if (ret_val) - return ret_val; - - spin_lock_irqsave(&adapter->systim_lock, flags); - - incvalue = timinca & E1000_TIMINCA_INCVALUE_MASK; - - adjustment = incvalue; - adjustment *= delta; - adjustment = div_u64(adjustment, 1000000000); - - incvalue = neg_adj ? (incvalue - adjustment) : (incvalue + adjustment); - - timinca &= ~E1000_TIMINCA_INCVALUE_MASK; - timinca |= incvalue; - - ew32(TIMINCA, timinca); - - spin_unlock_irqrestore(&adapter->systim_lock, flags); - - return 0; -} - -/** - * e1000e_phc_adjtime - Shift the time of the hardware clock - * @ptp: ptp clock structure - * @delta: Desired change in nanoseconds - * - * Adjust the timer by resetting the timecounter structure. - **/ -static int e1000e_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) -{ - struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, - ptp_clock_info); - unsigned long flags; - - spin_lock_irqsave(&adapter->systim_lock, flags); - timecounter_adjtime(&adapter->tc, delta); - spin_unlock_irqrestore(&adapter->systim_lock, flags); - - return 0; -} - -/** - * e1000e_phc_gettime - Reads the current time from the hardware clock - * @ptp: ptp clock structure - * @ts: timespec structure to hold the current time value - * - * Read the timecounter and return the correct value in ns after converting - * it into a struct timespec. - **/ -static int e1000e_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts) -{ - struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, - ptp_clock_info); - unsigned long flags; - u64 cycles, ns; - - spin_lock_irqsave(&adapter->systim_lock, flags); - - /* Use timecounter_cyc2time() to allow non-monotonic SYSTIM readings */ - cycles = adapter->cc.read(&adapter->cc); - ns = timecounter_cyc2time(&adapter->tc, cycles); - - spin_unlock_irqrestore(&adapter->systim_lock, flags); - - *ts = ns_to_timespec64(ns); - - return 0; -} - -/** - * e1000e_phc_settime - Set the current time on the hardware clock - * @ptp: ptp clock structure - * @ts: timespec containing the new time for the cycle counter - * - * Reset the timecounter to use a new base value instead of the kernel - * wall timer value. - **/ -static int e1000e_phc_settime(struct ptp_clock_info *ptp, - const struct timespec64 *ts) -{ - struct e1000_adapter *adapter = container_of(ptp, struct e1000_adapter, - ptp_clock_info); - unsigned long flags; - u64 ns; - - ns = timespec64_to_ns(ts); - - /* reset the timecounter */ - spin_lock_irqsave(&adapter->systim_lock, flags); - timecounter_init(&adapter->tc, &adapter->cc, ns); - spin_unlock_irqrestore(&adapter->systim_lock, flags); - - return 0; -} - -/** - * e1000e_phc_enable - enable or disable an ancillary feature - * @ptp: ptp clock structure - * @request: Desired resource to enable or disable - * @on: Caller passes one to enable or zero to disable - * - * Enable (or disable) ancillary features of the PHC subsystem. - * Currently, no ancillary features are supported. - **/ -static int e1000e_phc_enable(struct ptp_clock_info __always_unused *ptp, - struct ptp_clock_request __always_unused *request, - int __always_unused on) -{ - return -EOPNOTSUPP; -} - -static void e1000e_systim_overflow_work(struct work_struct *work) -{ - struct e1000_adapter *adapter = container_of(work, struct e1000_adapter, - systim_overflow_work.work); - struct e1000_hw *hw = &adapter->hw; - struct timespec64 ts; - u64 ns; - - /* Update the timecounter */ - ns = timecounter_read(&adapter->tc); - - ts = ns_to_timespec64(ns); - e_dbg("SYSTIM overflow check at %lld.%09lu\n", - (long long) ts.tv_sec, ts.tv_nsec); - - schedule_delayed_work(&adapter->systim_overflow_work, - E1000_SYSTIM_OVERFLOW_PERIOD); -} - -static const struct ptp_clock_info e1000e_ptp_clock_info = { - .owner = THIS_MODULE, - .n_alarm = 0, - .n_ext_ts = 0, - .n_per_out = 0, - .n_pins = 0, - .pps = 0, - .adjfreq = e1000e_phc_adjfreq, - .adjtime = e1000e_phc_adjtime, - .gettime64 = e1000e_phc_gettime, - .settime64 = e1000e_phc_settime, - .enable = e1000e_phc_enable, -}; - -/** - * e1000e_ptp_init - initialize PTP for devices which support it - * @adapter: board private structure - * - * This function performs the required steps for enabling PTP support. - * If PTP support has already been loaded it simply calls the cyclecounter - * init routine and exits. - **/ -void e1000e_ptp_init(struct e1000_adapter *adapter) -{ - struct e1000_hw *hw = &adapter->hw; - - adapter->ptp_clock = NULL; - - if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP)) - return; - - adapter->ptp_clock_info = e1000e_ptp_clock_info; - - snprintf(adapter->ptp_clock_info.name, - sizeof(adapter->ptp_clock_info.name), "%pm", - adapter->netdev->perm_addr); - - switch (hw->mac.type) { - case e1000_pch2lan: - case e1000_pch_lpt: - case e1000_pch_spt: - if (((hw->mac.type != e1000_pch_lpt) && - (hw->mac.type != e1000_pch_spt)) || - (er32(TSYNCRXCTL) & E1000_TSYNCRXCTL_SYSCFI)) { - adapter->ptp_clock_info.max_adj = 24000000 - 1; - break; - } - /* fall-through */ - case e1000_82574: - case e1000_82583: - adapter->ptp_clock_info.max_adj = 600000000 - 1; - break; - default: - break; - } - - INIT_DELAYED_WORK(&adapter->systim_overflow_work, - e1000e_systim_overflow_work); - - schedule_delayed_work(&adapter->systim_overflow_work, - E1000_SYSTIM_OVERFLOW_PERIOD); - - adapter->ptp_clock = ptp_clock_register(&adapter->ptp_clock_info, - &adapter->pdev->dev); - if (IS_ERR(adapter->ptp_clock)) { - adapter->ptp_clock = NULL; - e_err("ptp_clock_register failed\n"); - } else { - e_info("registered PHC clock\n"); - } -} - -/** - * e1000e_ptp_remove - disable PTP device and stop the overflow check - * @adapter: board private structure - * - * Stop the PTP support, and cancel the delayed work. - **/ -void e1000e_ptp_remove(struct e1000_adapter *adapter) -{ - if (!(adapter->flags & FLAG_HAS_HW_TIMESTAMP)) - return; - - cancel_delayed_work_sync(&adapter->systim_overflow_work); - - if (adapter->ptp_clock) { - ptp_clock_unregister(adapter->ptp_clock); - adapter->ptp_clock = NULL; - e_info("removed PHC\n"); - } -} diff --git a/addons/e1000e/src/4.4.180/regs.h b/addons/e1000e/src/4.4.180/regs.h deleted file mode 100644 index 1d5e0b77..00000000 --- a/addons/e1000e/src/4.4.180/regs.h +++ /dev/null @@ -1,251 +0,0 @@ -/* Intel PRO/1000 Linux driver - * Copyright(c) 1999 - 2015 Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - * - * The full GNU General Public License is included in this distribution in - * the file called "COPYING". - * - * Contact Information: - * Linux NICS - * e1000-devel Mailing List - * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - */ - -#ifndef _E1000E_REGS_H_ -#define _E1000E_REGS_H_ - -#define E1000_CTRL 0x00000 /* Device Control - RW */ -#define E1000_STATUS 0x00008 /* Device Status - RO */ -#define E1000_EECD 0x00010 /* EEPROM/Flash Control - RW */ -#define E1000_EERD 0x00014 /* EEPROM Read - RW */ -#define E1000_CTRL_EXT 0x00018 /* Extended Device Control - RW */ -#define E1000_FLA 0x0001C /* Flash Access - RW */ -#define E1000_MDIC 0x00020 /* MDI Control - RW */ -#define E1000_SCTL 0x00024 /* SerDes Control - RW */ -#define E1000_FCAL 0x00028 /* Flow Control Address Low - RW */ -#define E1000_FCAH 0x0002C /* Flow Control Address High -RW */ -#define E1000_FEXT 0x0002C /* Future Extended - RW */ -#define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ -#define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */ -#define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ -#define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */ -#define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */ -#define E1000_FEXTNVM9 0x5BB4 /* Future Extended NVM 9 - RW */ -#define E1000_FEXTNVM11 0x5BBC /* Future Extended NVM 11 - RW */ -#define E1000_PCIEANACFG 0x00F18 /* PCIE Analog Config */ -#define E1000_FCT 0x00030 /* Flow Control Type - RW */ -#define E1000_VET 0x00038 /* VLAN Ether Type - RW */ -#define E1000_ICR 0x000C0 /* Interrupt Cause Read - R/clr */ -#define E1000_ITR 0x000C4 /* Interrupt Throttling Rate - RW */ -#define E1000_ICS 0x000C8 /* Interrupt Cause Set - WO */ -#define E1000_IMS 0x000D0 /* Interrupt Mask Set - RW */ -#define E1000_IMC 0x000D8 /* Interrupt Mask Clear - WO */ -#define E1000_IAM 0x000E0 /* Interrupt Acknowledge Auto Mask */ -#define E1000_IVAR 0x000E4 /* Interrupt Vector Allocation Register - RW */ -#define E1000_SVCR 0x000F0 -#define E1000_SVT 0x000F4 -#define E1000_LPIC 0x000FC /* Low Power IDLE control */ -#define E1000_RCTL 0x00100 /* Rx Control - RW */ -#define E1000_FCTTV 0x00170 /* Flow Control Transmit Timer Value - RW */ -#define E1000_TXCW 0x00178 /* Tx Configuration Word - RW */ -#define E1000_RXCW 0x00180 /* Rx Configuration Word - RO */ -#define E1000_PBA_ECC 0x01100 /* PBA ECC Register */ -#define E1000_TCTL 0x00400 /* Tx Control - RW */ -#define E1000_TCTL_EXT 0x00404 /* Extended Tx Control - RW */ -#define E1000_TIPG 0x00410 /* Tx Inter-packet gap -RW */ -#define E1000_AIT 0x00458 /* Adaptive Interframe Spacing Throttle - RW */ -#define E1000_LEDCTL 0x00E00 /* LED Control - RW */ -#define E1000_EXTCNF_CTRL 0x00F00 /* Extended Configuration Control */ -#define E1000_EXTCNF_SIZE 0x00F08 /* Extended Configuration Size */ -#define E1000_PHY_CTRL 0x00F10 /* PHY Control Register in CSR */ -#define E1000_POEMB E1000_PHY_CTRL /* PHY OEM Bits */ -#define E1000_PBA 0x01000 /* Packet Buffer Allocation - RW */ -#define E1000_PBS 0x01008 /* Packet Buffer Size */ -#define E1000_PBECCSTS 0x0100C /* Packet Buffer ECC Status - RW */ -#define E1000_IOSFPC 0x00F28 /* TX corrupted data */ -#define E1000_EEMNGCTL 0x01010 /* MNG EEprom Control */ -#define E1000_EEWR 0x0102C /* EEPROM Write Register - RW */ -#define E1000_FLOP 0x0103C /* FLASH Opcode Register */ -#define E1000_ERT 0x02008 /* Early Rx Threshold - RW */ -#define E1000_FCRTL 0x02160 /* Flow Control Receive Threshold Low - RW */ -#define E1000_FCRTH 0x02168 /* Flow Control Receive Threshold High - RW */ -#define E1000_PSRCTL 0x02170 /* Packet Split Receive Control - RW */ -#define E1000_RDFH 0x02410 /* Rx Data FIFO Head - RW */ -#define E1000_RDFT 0x02418 /* Rx Data FIFO Tail - RW */ -#define E1000_RDFHS 0x02420 /* Rx Data FIFO Head Saved - RW */ -#define E1000_RDFTS 0x02428 /* Rx Data FIFO Tail Saved - RW */ -#define E1000_RDFPC 0x02430 /* Rx Data FIFO Packet Count - RW */ -/* Split and Replication Rx Control - RW */ -#define E1000_RDTR 0x02820 /* Rx Delay Timer - RW */ -#define E1000_RADV 0x0282C /* Rx Interrupt Absolute Delay Timer - RW */ -/* Convenience macros - * - * Note: "_n" is the queue number of the register to be written to. - * - * Example usage: - * E1000_RDBAL_REG(current_rx_queue) - */ -#define E1000_RDBAL(_n) ((_n) < 4 ? (0x02800 + ((_n) * 0x100)) : \ - (0x0C000 + ((_n) * 0x40))) -#define E1000_RDBAH(_n) ((_n) < 4 ? (0x02804 + ((_n) * 0x100)) : \ - (0x0C004 + ((_n) * 0x40))) -#define E1000_RDLEN(_n) ((_n) < 4 ? (0x02808 + ((_n) * 0x100)) : \ - (0x0C008 + ((_n) * 0x40))) -#define E1000_RDH(_n) ((_n) < 4 ? (0x02810 + ((_n) * 0x100)) : \ - (0x0C010 + ((_n) * 0x40))) -#define E1000_RDT(_n) ((_n) < 4 ? (0x02818 + ((_n) * 0x100)) : \ - (0x0C018 + ((_n) * 0x40))) -#define E1000_RXDCTL(_n) ((_n) < 4 ? (0x02828 + ((_n) * 0x100)) : \ - (0x0C028 + ((_n) * 0x40))) -#define E1000_TDBAL(_n) ((_n) < 4 ? (0x03800 + ((_n) * 0x100)) : \ - (0x0E000 + ((_n) * 0x40))) -#define E1000_TDBAH(_n) ((_n) < 4 ? (0x03804 + ((_n) * 0x100)) : \ - (0x0E004 + ((_n) * 0x40))) -#define E1000_TDLEN(_n) ((_n) < 4 ? (0x03808 + ((_n) * 0x100)) : \ - (0x0E008 + ((_n) * 0x40))) -#define E1000_TDH(_n) ((_n) < 4 ? (0x03810 + ((_n) * 0x100)) : \ - (0x0E010 + ((_n) * 0x40))) -#define E1000_TDT(_n) ((_n) < 4 ? (0x03818 + ((_n) * 0x100)) : \ - (0x0E018 + ((_n) * 0x40))) -#define E1000_TXDCTL(_n) ((_n) < 4 ? (0x03828 + ((_n) * 0x100)) : \ - (0x0E028 + ((_n) * 0x40))) -#define E1000_TARC(_n) (0x03840 + ((_n) * 0x100)) -#define E1000_KABGTXD 0x03004 /* AFE Band Gap Transmit Ref Data */ -#define E1000_RAL(_i) (((_i) <= 15) ? (0x05400 + ((_i) * 8)) : \ - (0x054E0 + ((_i - 16) * 8))) -#define E1000_RAH(_i) (((_i) <= 15) ? (0x05404 + ((_i) * 8)) : \ - (0x054E4 + ((_i - 16) * 8))) -#define E1000_SHRAL(_i) (0x05438 + ((_i) * 8)) -#define E1000_SHRAH(_i) (0x0543C + ((_i) * 8)) -#define E1000_TDFH 0x03410 /* Tx Data FIFO Head - RW */ -#define E1000_TDFT 0x03418 /* Tx Data FIFO Tail - RW */ -#define E1000_TDFHS 0x03420 /* Tx Data FIFO Head Saved - RW */ -#define E1000_TDFTS 0x03428 /* Tx Data FIFO Tail Saved - RW */ -#define E1000_TDFPC 0x03430 /* Tx Data FIFO Packet Count - RW */ -#define E1000_TIDV 0x03820 /* Tx Interrupt Delay Value - RW */ -#define E1000_TADV 0x0382C /* Tx Interrupt Absolute Delay Val - RW */ -#define E1000_CRCERRS 0x04000 /* CRC Error Count - R/clr */ -#define E1000_ALGNERRC 0x04004 /* Alignment Error Count - R/clr */ -#define E1000_SYMERRS 0x04008 /* Symbol Error Count - R/clr */ -#define E1000_RXERRC 0x0400C /* Receive Error Count - R/clr */ -#define E1000_MPC 0x04010 /* Missed Packet Count - R/clr */ -#define E1000_SCC 0x04014 /* Single Collision Count - R/clr */ -#define E1000_ECOL 0x04018 /* Excessive Collision Count - R/clr */ -#define E1000_MCC 0x0401C /* Multiple Collision Count - R/clr */ -#define E1000_LATECOL 0x04020 /* Late Collision Count - R/clr */ -#define E1000_COLC 0x04028 /* Collision Count - R/clr */ -#define E1000_DC 0x04030 /* Defer Count - R/clr */ -#define E1000_TNCRS 0x04034 /* Tx-No CRS - R/clr */ -#define E1000_SEC 0x04038 /* Sequence Error Count - R/clr */ -#define E1000_CEXTERR 0x0403C /* Carrier Extension Error Count - R/clr */ -#define E1000_RLEC 0x04040 /* Receive Length Error Count - R/clr */ -#define E1000_XONRXC 0x04048 /* XON Rx Count - R/clr */ -#define E1000_XONTXC 0x0404C /* XON Tx Count - R/clr */ -#define E1000_XOFFRXC 0x04050 /* XOFF Rx Count - R/clr */ -#define E1000_XOFFTXC 0x04054 /* XOFF Tx Count - R/clr */ -#define E1000_FCRUC 0x04058 /* Flow Control Rx Unsupported Count- R/clr */ -#define E1000_PRC64 0x0405C /* Packets Rx (64 bytes) - R/clr */ -#define E1000_PRC127 0x04060 /* Packets Rx (65-127 bytes) - R/clr */ -#define E1000_PRC255 0x04064 /* Packets Rx (128-255 bytes) - R/clr */ -#define E1000_PRC511 0x04068 /* Packets Rx (255-511 bytes) - R/clr */ -#define E1000_PRC1023 0x0406C /* Packets Rx (512-1023 bytes) - R/clr */ -#define E1000_PRC1522 0x04070 /* Packets Rx (1024-1522 bytes) - R/clr */ -#define E1000_GPRC 0x04074 /* Good Packets Rx Count - R/clr */ -#define E1000_BPRC 0x04078 /* Broadcast Packets Rx Count - R/clr */ -#define E1000_MPRC 0x0407C /* Multicast Packets Rx Count - R/clr */ -#define E1000_GPTC 0x04080 /* Good Packets Tx Count - R/clr */ -#define E1000_GORCL 0x04088 /* Good Octets Rx Count Low - R/clr */ -#define E1000_GORCH 0x0408C /* Good Octets Rx Count High - R/clr */ -#define E1000_GOTCL 0x04090 /* Good Octets Tx Count Low - R/clr */ -#define E1000_GOTCH 0x04094 /* Good Octets Tx Count High - R/clr */ -#define E1000_RNBC 0x040A0 /* Rx No Buffers Count - R/clr */ -#define E1000_RUC 0x040A4 /* Rx Undersize Count - R/clr */ -#define E1000_RFC 0x040A8 /* Rx Fragment Count - R/clr */ -#define E1000_ROC 0x040AC /* Rx Oversize Count - R/clr */ -#define E1000_RJC 0x040B0 /* Rx Jabber Count - R/clr */ -#define E1000_MGTPRC 0x040B4 /* Management Packets Rx Count - R/clr */ -#define E1000_MGTPDC 0x040B8 /* Management Packets Dropped Count - R/clr */ -#define E1000_MGTPTC 0x040BC /* Management Packets Tx Count - R/clr */ -#define E1000_TORL 0x040C0 /* Total Octets Rx Low - R/clr */ -#define E1000_TORH 0x040C4 /* Total Octets Rx High - R/clr */ -#define E1000_TOTL 0x040C8 /* Total Octets Tx Low - R/clr */ -#define E1000_TOTH 0x040CC /* Total Octets Tx High - R/clr */ -#define E1000_TPR 0x040D0 /* Total Packets Rx - R/clr */ -#define E1000_TPT 0x040D4 /* Total Packets Tx - R/clr */ -#define E1000_PTC64 0x040D8 /* Packets Tx (64 bytes) - R/clr */ -#define E1000_PTC127 0x040DC /* Packets Tx (65-127 bytes) - R/clr */ -#define E1000_PTC255 0x040E0 /* Packets Tx (128-255 bytes) - R/clr */ -#define E1000_PTC511 0x040E4 /* Packets Tx (256-511 bytes) - R/clr */ -#define E1000_PTC1023 0x040E8 /* Packets Tx (512-1023 bytes) - R/clr */ -#define E1000_PTC1522 0x040EC /* Packets Tx (1024-1522 Bytes) - R/clr */ -#define E1000_MPTC 0x040F0 /* Multicast Packets Tx Count - R/clr */ -#define E1000_BPTC 0x040F4 /* Broadcast Packets Tx Count - R/clr */ -#define E1000_TSCTC 0x040F8 /* TCP Segmentation Context Tx - R/clr */ -#define E1000_TSCTFC 0x040FC /* TCP Segmentation Context Tx Fail - R/clr */ -#define E1000_IAC 0x04100 /* Interrupt Assertion Count */ -#define E1000_ICRXPTC 0x04104 /* Interrupt Cause Rx Pkt Timer Expire Count */ -#define E1000_ICRXATC 0x04108 /* Interrupt Cause Rx Abs Timer Expire Count */ -#define E1000_ICTXPTC 0x0410C /* Interrupt Cause Tx Pkt Timer Expire Count */ -#define E1000_ICTXATC 0x04110 /* Interrupt Cause Tx Abs Timer Expire Count */ -#define E1000_ICTXQEC 0x04118 /* Interrupt Cause Tx Queue Empty Count */ -#define E1000_ICTXQMTC 0x0411C /* Interrupt Cause Tx Queue Min Thresh Count */ -#define E1000_ICRXDMTC 0x04120 /* Interrupt Cause Rx Desc Min Thresh Count */ -#define E1000_ICRXOC 0x04124 /* Interrupt Cause Receiver Overrun Count */ -#define E1000_CRC_OFFSET 0x05F50 /* CRC Offset register */ - -#define E1000_PCS_LCTL 0x04208 /* PCS Link Control - RW */ -#define E1000_PCS_LSTAT 0x0420C /* PCS Link Status - RO */ -#define E1000_PCS_ANADV 0x04218 /* AN advertisement - RW */ -#define E1000_PCS_LPAB 0x0421C /* Link Partner Ability - RW */ -#define E1000_RXCSUM 0x05000 /* Rx Checksum Control - RW */ -#define E1000_RFCTL 0x05008 /* Receive Filter Control */ -#define E1000_MTA 0x05200 /* Multicast Table Array - RW Array */ -#define E1000_RA 0x05400 /* Receive Address - RW Array */ -#define E1000_VFTA 0x05600 /* VLAN Filter Table Array - RW Array */ -#define E1000_WUC 0x05800 /* Wakeup Control - RW */ -#define E1000_WUFC 0x05808 /* Wakeup Filter Control - RW */ -#define E1000_WUS 0x05810 /* Wakeup Status - RO */ -#define E1000_MANC 0x05820 /* Management Control - RW */ -#define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ -#define E1000_HOST_IF 0x08800 /* Host Interface */ - -#define E1000_KMRNCTRLSTA 0x00034 /* MAC-PHY interface - RW */ -#define E1000_MANC2H 0x05860 /* Management Control To Host - RW */ -/* Management Decision Filters */ -#define E1000_MDEF(_n) (0x05890 + (4 * (_n))) -#define E1000_SW_FW_SYNC 0x05B5C /* SW-FW Synchronization - RW */ -#define E1000_GCR 0x05B00 /* PCI-Ex Control */ -#define E1000_GCR2 0x05B64 /* PCI-Ex Control #2 */ -#define E1000_FACTPS 0x05B30 /* Function Active and Power State to MNG */ -#define E1000_SWSM 0x05B50 /* SW Semaphore */ -#define E1000_FWSM 0x05B54 /* FW Semaphore */ -/* Driver-only SW semaphore (not used by BOOT agents) */ -#define E1000_SWSM2 0x05B58 -#define E1000_FFLT_DBG 0x05F04 /* Debug Register */ -#define E1000_HICR 0x08F00 /* Host Interface Control */ - -/* RSS registers */ -#define E1000_MRQC 0x05818 /* Multiple Receive Control - RW */ -#define E1000_RETA(_i) (0x05C00 + ((_i) * 4)) /* Redirection Table - RW */ -#define E1000_RSSRK(_i) (0x05C80 + ((_i) * 4)) /* RSS Random Key - RW */ -#define E1000_TSYNCRXCTL 0x0B620 /* Rx Time Sync Control register - RW */ -#define E1000_TSYNCTXCTL 0x0B614 /* Tx Time Sync Control register - RW */ -#define E1000_RXSTMPL 0x0B624 /* Rx timestamp Low - RO */ -#define E1000_RXSTMPH 0x0B628 /* Rx timestamp High - RO */ -#define E1000_TXSTMPL 0x0B618 /* Tx timestamp value Low - RO */ -#define E1000_TXSTMPH 0x0B61C /* Tx timestamp value High - RO */ -#define E1000_SYSTIML 0x0B600 /* System time register Low - RO */ -#define E1000_SYSTIMH 0x0B604 /* System time register High - RO */ -#define E1000_TIMINCA 0x0B608 /* Increment attributes register - RW */ -#define E1000_RXMTRL 0x0B634 /* Time sync Rx EtherType and Msg Type - RW */ -#define E1000_RXUDP 0x0B638 /* Time Sync Rx UDP Port - RW */ - -#endif diff --git a/addons/ehci-pci/install-bromolow-3.10.108.sh b/addons/ehci-pci/install-bromolow-3.10.108.sh deleted file mode 100644 index 69c8294b..00000000 --- a/addons/ehci-pci/install-bromolow-3.10.108.sh +++ /dev/null @@ -1,6 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Installing module(s) for ehci-pci" - ${INSMOD} "/modules/pci-quirks.ko" - ${INSMOD} "/modules/ehci-hcd.ko" - ${INSMOD} "/modules/ehci-pci.ko" ${PARAMS} -fi diff --git a/addons/ehci-pci/install.sh b/addons/ehci-pci/install.sh deleted file mode 100644 index 02f75ca5..00000000 --- a/addons/ehci-pci/install.sh +++ /dev/null @@ -1,5 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Installing modules for ehci-pci" - ${INSMOD} "/modules/ehci-hcd.ko" - ${INSMOD} "/modules/ehci-pci.ko" ${PARAMS} -fi diff --git a/addons/ehci-pci/manifest.yml b/addons/ehci-pci/manifest.yml deleted file mode 100644 index dd29813d..00000000 --- a/addons/ehci-pci/manifest.yml +++ /dev/null @@ -1,7 +0,0 @@ -version: 1 -name: ehci-pci -description: "Driver for USB 2.0 Host Controller" -available-for: - broadwell-4.4.180: - install-script: &script "install.sh" - modules: true diff --git a/addons/ehci-pci/src/3.10.108/Makefile b/addons/ehci-pci/src/3.10.108/Makefile deleted file mode 100644 index 898ba621..00000000 --- a/addons/ehci-pci/src/3.10.108/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-y += pci-quirks.o -obj-m += ehci-hcd.o -obj-m += ehci-pci.o diff --git a/addons/ehci-pci/src/3.10.108/ehci-dbg.c b/addons/ehci-pci/src/3.10.108/ehci-dbg.c deleted file mode 100644 index 5429d264..00000000 --- a/addons/ehci-pci/src/3.10.108/ehci-dbg.c +++ /dev/null @@ -1,980 +0,0 @@ -/* - * Copyright (c) 2001-2002 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -#ifdef DEBUG - -/* check the values in the HCSPARAMS register - * (host controller _Structural_ parameters) - * see EHCI spec, Table 2-4 for each value - */ -static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) -{ - u32 params = ehci_readl(ehci, &ehci->caps->hcs_params); - - ehci_dbg (ehci, - "%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d\n", - label, params, - HCS_DEBUG_PORT (params), - HCS_INDICATOR (params) ? " ind" : "", - HCS_N_CC (params), - HCS_N_PCC (params), - HCS_PORTROUTED (params) ? "" : " ordered", - HCS_PPC (params) ? "" : " !ppc", - HCS_N_PORTS (params) - ); - /* Port routing, per EHCI 0.95 Spec, Section 2.2.5 */ - if (HCS_PORTROUTED (params)) { - int i; - char buf [46], tmp [7], byte; - - buf[0] = 0; - for (i = 0; i < HCS_N_PORTS (params); i++) { - // FIXME MIPS won't readb() ... - byte = readb (&ehci->caps->portroute[(i>>1)]); - sprintf(tmp, "%d ", - ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf))); - strcat(buf, tmp); - } - ehci_dbg (ehci, "%s portroute %s\n", - label, buf); - } -} -#else - -static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {} - -#endif - -#ifdef DEBUG - -/* check the values in the HCCPARAMS register - * (host controller _Capability_ parameters) - * see EHCI Spec, Table 2-5 for each value - * */ -static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) -{ - u32 params = ehci_readl(ehci, &ehci->caps->hcc_params); - - if (HCC_ISOC_CACHE (params)) { - ehci_dbg (ehci, - "%s hcc_params %04x caching frame %s%s%s\n", - label, params, - HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", - HCC_CANPARK(params) ? " park" : "", - HCC_64BIT_ADDR(params) ? " 64 bit addr" : ""); - } else { - ehci_dbg (ehci, - "%s hcc_params %04x thresh %d uframes %s%s%s%s%s%s%s\n", - label, - params, - HCC_ISOC_THRES(params), - HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", - HCC_CANPARK(params) ? " park" : "", - HCC_64BIT_ADDR(params) ? " 64 bit addr" : "", - HCC_LPM(params) ? " LPM" : "", - HCC_PER_PORT_CHANGE_EVENT(params) ? " ppce" : "", - HCC_HW_PREFETCH(params) ? " hw prefetch" : "", - HCC_32FRAME_PERIODIC_LIST(params) ? - " 32 periodic list" : ""); - } -} -#else - -static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {} - -#endif - -#ifdef DEBUG - -static void __maybe_unused -dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) -{ - ehci_dbg(ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, - hc32_to_cpup(ehci, &qtd->hw_next), - hc32_to_cpup(ehci, &qtd->hw_alt_next), - hc32_to_cpup(ehci, &qtd->hw_token), - hc32_to_cpup(ehci, &qtd->hw_buf [0])); - if (qtd->hw_buf [1]) - ehci_dbg(ehci, " p1=%08x p2=%08x p3=%08x p4=%08x\n", - hc32_to_cpup(ehci, &qtd->hw_buf[1]), - hc32_to_cpup(ehci, &qtd->hw_buf[2]), - hc32_to_cpup(ehci, &qtd->hw_buf[3]), - hc32_to_cpup(ehci, &qtd->hw_buf[4])); -} - -static void __maybe_unused -dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - struct ehci_qh_hw *hw = qh->hw; - - ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label, - qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current); - dbg_qtd("overlay", ehci, (struct ehci_qtd *) &hw->hw_qtd_next); -} - -static void __maybe_unused -dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) -{ - ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n", - label, itd->frame, itd, hc32_to_cpu(ehci, itd->hw_next), - itd->urb); - ehci_dbg (ehci, - " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", - hc32_to_cpu(ehci, itd->hw_transaction[0]), - hc32_to_cpu(ehci, itd->hw_transaction[1]), - hc32_to_cpu(ehci, itd->hw_transaction[2]), - hc32_to_cpu(ehci, itd->hw_transaction[3]), - hc32_to_cpu(ehci, itd->hw_transaction[4]), - hc32_to_cpu(ehci, itd->hw_transaction[5]), - hc32_to_cpu(ehci, itd->hw_transaction[6]), - hc32_to_cpu(ehci, itd->hw_transaction[7])); - ehci_dbg (ehci, - " buf: %08x %08x %08x %08x %08x %08x %08x\n", - hc32_to_cpu(ehci, itd->hw_bufp[0]), - hc32_to_cpu(ehci, itd->hw_bufp[1]), - hc32_to_cpu(ehci, itd->hw_bufp[2]), - hc32_to_cpu(ehci, itd->hw_bufp[3]), - hc32_to_cpu(ehci, itd->hw_bufp[4]), - hc32_to_cpu(ehci, itd->hw_bufp[5]), - hc32_to_cpu(ehci, itd->hw_bufp[6])); - ehci_dbg (ehci, " index: %d %d %d %d %d %d %d %d\n", - itd->index[0], itd->index[1], itd->index[2], - itd->index[3], itd->index[4], itd->index[5], - itd->index[6], itd->index[7]); -} - -static void __maybe_unused -dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) -{ - ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n", - label, sitd->frame, sitd, hc32_to_cpu(ehci, sitd->hw_next), - sitd->urb); - ehci_dbg (ehci, - " addr %08x sched %04x result %08x buf %08x %08x\n", - hc32_to_cpu(ehci, sitd->hw_fullspeed_ep), - hc32_to_cpu(ehci, sitd->hw_uframe), - hc32_to_cpu(ehci, sitd->hw_results), - hc32_to_cpu(ehci, sitd->hw_buf[0]), - hc32_to_cpu(ehci, sitd->hw_buf[1])); -} - -static int __maybe_unused -dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) -{ - return scnprintf (buf, len, - "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s%s", - label, label [0] ? " " : "", status, - (status & STS_PPCE_MASK) ? " PPCE" : "", - (status & STS_ASS) ? " Async" : "", - (status & STS_PSS) ? " Periodic" : "", - (status & STS_RECL) ? " Recl" : "", - (status & STS_HALT) ? " Halt" : "", - (status & STS_IAA) ? " IAA" : "", - (status & STS_FATAL) ? " FATAL" : "", - (status & STS_FLR) ? " FLR" : "", - (status & STS_PCD) ? " PCD" : "", - (status & STS_ERR) ? " ERR" : "", - (status & STS_INT) ? " INT" : "" - ); -} - -static int __maybe_unused -dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) -{ - return scnprintf (buf, len, - "%s%sintrenable %02x%s%s%s%s%s%s%s", - label, label [0] ? " " : "", enable, - (enable & STS_PPCE_MASK) ? " PPCE" : "", - (enable & STS_IAA) ? " IAA" : "", - (enable & STS_FATAL) ? " FATAL" : "", - (enable & STS_FLR) ? " FLR" : "", - (enable & STS_PCD) ? " PCD" : "", - (enable & STS_ERR) ? " ERR" : "", - (enable & STS_INT) ? " INT" : "" - ); -} - -static const char *const fls_strings [] = - { "1024", "512", "256", "??" }; - -static int -dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) -{ - return scnprintf (buf, len, - "%s%scommand %07x %s%s%s%s%s%s=%d ithresh=%d%s%s%s%s " - "period=%s%s %s", - label, label [0] ? " " : "", command, - (command & CMD_HIRD) ? " HIRD" : "", - (command & CMD_PPCEE) ? " PPCEE" : "", - (command & CMD_FSP) ? " FSP" : "", - (command & CMD_ASPE) ? " ASPE" : "", - (command & CMD_PSPE) ? " PSPE" : "", - (command & CMD_PARK) ? " park" : "(park)", - CMD_PARK_CNT (command), - (command >> 16) & 0x3f, - (command & CMD_LRESET) ? " LReset" : "", - (command & CMD_IAAD) ? " IAAD" : "", - (command & CMD_ASE) ? " Async" : "", - (command & CMD_PSE) ? " Periodic" : "", - fls_strings [(command >> 2) & 0x3], - (command & CMD_RESET) ? " Reset" : "", - (command & CMD_RUN) ? "RUN" : "HALT" - ); -} - -static int -dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) -{ - char *sig; - - /* signaling state */ - switch (status & (3 << 10)) { - case 0 << 10: sig = "se0"; break; - case 1 << 10: sig = "k"; break; /* low speed */ - case 2 << 10: sig = "j"; break; - default: sig = "?"; break; - } - - return scnprintf (buf, len, - "%s%sport:%d status %06x %d %s%s%s%s%s%s " - "sig=%s%s%s%s%s%s%s%s%s%s%s", - label, label [0] ? " " : "", port, status, - status>>25,/*device address */ - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ACK ? - " ACK" : "", - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_NYET ? - " NYET" : "", - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_STALL ? - " STALL" : "", - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ERR ? - " ERR" : "", - (status & PORT_POWER) ? " POWER" : "", - (status & PORT_OWNER) ? " OWNER" : "", - sig, - (status & PORT_LPM) ? " LPM" : "", - (status & PORT_RESET) ? " RESET" : "", - (status & PORT_SUSPEND) ? " SUSPEND" : "", - (status & PORT_RESUME) ? " RESUME" : "", - (status & PORT_OCC) ? " OCC" : "", - (status & PORT_OC) ? " OC" : "", - (status & PORT_PEC) ? " PEC" : "", - (status & PORT_PE) ? " PE" : "", - (status & PORT_CSC) ? " CSC" : "", - (status & PORT_CONNECT) ? " CONNECT" : ""); -} - -#else -static inline void __maybe_unused -dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) -{} - -static inline int __maybe_unused -dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) -{ return 0; } - -static inline int __maybe_unused -dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) -{ return 0; } - -static inline int __maybe_unused -dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) -{ return 0; } - -static inline int __maybe_unused -dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) -{ return 0; } - -#endif /* DEBUG */ - -/* functions have the "wrong" filename when they're output... */ -#define dbg_status(ehci, label, status) { \ - char _buf [80]; \ - dbg_status_buf (_buf, sizeof _buf, label, status); \ - ehci_dbg (ehci, "%s\n", _buf); \ -} - -#define dbg_cmd(ehci, label, command) { \ - char _buf [80]; \ - dbg_command_buf (_buf, sizeof _buf, label, command); \ - ehci_dbg (ehci, "%s\n", _buf); \ -} - -#define dbg_port(ehci, label, port, status) { \ - char _buf [80]; \ - dbg_port_buf (_buf, sizeof _buf, label, port, status); \ - ehci_dbg (ehci, "%s\n", _buf); \ -} - -/*-------------------------------------------------------------------------*/ - -#ifdef STUB_DEBUG_FILES - -static inline void create_debug_files (struct ehci_hcd *bus) { } -static inline void remove_debug_files (struct ehci_hcd *bus) { } - -#else - -/* troubleshooting help: expose state in debugfs */ - -static int debug_async_open(struct inode *, struct file *); -static int debug_periodic_open(struct inode *, struct file *); -static int debug_registers_open(struct inode *, struct file *); -static int debug_async_open(struct inode *, struct file *); - -static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); -static int debug_close(struct inode *, struct file *); - -static const struct file_operations debug_async_fops = { - .owner = THIS_MODULE, - .open = debug_async_open, - .read = debug_output, - .release = debug_close, - .llseek = default_llseek, -}; -static const struct file_operations debug_periodic_fops = { - .owner = THIS_MODULE, - .open = debug_periodic_open, - .read = debug_output, - .release = debug_close, - .llseek = default_llseek, -}; -static const struct file_operations debug_registers_fops = { - .owner = THIS_MODULE, - .open = debug_registers_open, - .read = debug_output, - .release = debug_close, - .llseek = default_llseek, -}; - -static struct dentry *ehci_debug_root; - -struct debug_buffer { - ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ - struct usb_bus *bus; - struct mutex mutex; /* protect filling of buffer */ - size_t count; /* number of characters filled into buffer */ - char *output_buf; - size_t alloc_size; -}; - -#define speed_char(info1) ({ char tmp; \ - switch (info1 & (3 << 12)) { \ - case QH_FULL_SPEED: tmp = 'f'; break; \ - case QH_LOW_SPEED: tmp = 'l'; break; \ - case QH_HIGH_SPEED: tmp = 'h'; break; \ - default: tmp = '?'; break; \ - }; tmp; }) - -static inline char token_mark(struct ehci_hcd *ehci, __hc32 token) -{ - __u32 v = hc32_to_cpu(ehci, token); - - if (v & QTD_STS_ACTIVE) - return '*'; - if (v & QTD_STS_HALT) - return '-'; - if (!IS_SHORT_READ (v)) - return ' '; - /* tries to advance through hw_alt_next */ - return '/'; -} - -static void qh_lines ( - struct ehci_hcd *ehci, - struct ehci_qh *qh, - char **nextp, - unsigned *sizep -) -{ - u32 scratch; - u32 hw_curr; - struct list_head *entry; - struct ehci_qtd *td; - unsigned temp; - unsigned size = *sizep; - char *next = *nextp; - char mark; - __le32 list_end = EHCI_LIST_END(ehci); - struct ehci_qh_hw *hw = qh->hw; - - if (hw->hw_qtd_next == list_end) /* NEC does this */ - mark = '@'; - else - mark = token_mark(ehci, hw->hw_token); - if (mark == '/') { /* qh_alt_next controls qh advance? */ - if ((hw->hw_alt_next & QTD_MASK(ehci)) - == ehci->async->hw->hw_alt_next) - mark = '#'; /* blocked */ - else if (hw->hw_alt_next == list_end) - mark = '.'; /* use hw_qtd_next */ - /* else alt_next points to some other qtd */ - } - scratch = hc32_to_cpup(ehci, &hw->hw_info1); - hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &hw->hw_current) : 0; - temp = scnprintf (next, size, - "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)", - qh, scratch & 0x007f, - speed_char (scratch), - (scratch >> 8) & 0x000f, - scratch, hc32_to_cpup(ehci, &hw->hw_info2), - hc32_to_cpup(ehci, &hw->hw_token), mark, - (cpu_to_hc32(ehci, QTD_TOGGLE) & hw->hw_token) - ? "data1" : "data0", - (hc32_to_cpup(ehci, &hw->hw_alt_next) >> 1) & 0x0f); - size -= temp; - next += temp; - - /* hc may be modifying the list as we read it ... */ - list_for_each (entry, &qh->qtd_list) { - td = list_entry (entry, struct ehci_qtd, qtd_list); - scratch = hc32_to_cpup(ehci, &td->hw_token); - mark = ' '; - if (hw_curr == td->qtd_dma) - mark = '*'; - else if (hw->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma)) - mark = '+'; - else if (QTD_LENGTH (scratch)) { - if (td->hw_alt_next == ehci->async->hw->hw_alt_next) - mark = '#'; - else if (td->hw_alt_next != list_end) - mark = '/'; - } - temp = snprintf (next, size, - "\n\t%p%c%s len=%d %08x urb %p", - td, mark, ({ char *tmp; - switch ((scratch>>8)&0x03) { - case 0: tmp = "out"; break; - case 1: tmp = "in"; break; - case 2: tmp = "setup"; break; - default: tmp = "?"; break; - } tmp;}), - (scratch >> 16) & 0x7fff, - scratch, - td->urb); - if (size < temp) - temp = size; - size -= temp; - next += temp; - if (temp == size) - goto done; - } - - temp = snprintf (next, size, "\n"); - if (size < temp) - temp = size; - size -= temp; - next += temp; - -done: - *sizep = size; - *nextp = next; -} - -static ssize_t fill_async_buffer(struct debug_buffer *buf) -{ - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - unsigned long flags; - unsigned temp, size; - char *next; - struct ehci_qh *qh; - - hcd = bus_to_hcd(buf->bus); - ehci = hcd_to_ehci (hcd); - next = buf->output_buf; - size = buf->alloc_size; - - *next = 0; - - /* dumps a snapshot of the async schedule. - * usually empty except for long-term bulk reads, or head. - * one QH per line, and TDs we know about - */ - spin_lock_irqsave (&ehci->lock, flags); - for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh) - qh_lines (ehci, qh, &next, &size); - if (!list_empty(&ehci->async_unlink) && size > 0) { - temp = scnprintf(next, size, "\nunlink =\n"); - size -= temp; - next += temp; - - list_for_each_entry(qh, &ehci->async_unlink, unlink_node) { - if (size <= 0) - break; - qh_lines(ehci, qh, &next, &size); - } - } - spin_unlock_irqrestore (&ehci->lock, flags); - - return strlen(buf->output_buf); -} - -#define DBG_SCHED_LIMIT 64 -static ssize_t fill_periodic_buffer(struct debug_buffer *buf) -{ - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - unsigned long flags; - union ehci_shadow p, *seen; - unsigned temp, size, seen_count; - char *next; - unsigned i; - __hc32 tag; - - if (!(seen = kmalloc (DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC))) - return 0; - seen_count = 0; - - hcd = bus_to_hcd(buf->bus); - ehci = hcd_to_ehci (hcd); - next = buf->output_buf; - size = buf->alloc_size; - - temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size); - size -= temp; - next += temp; - - /* dump a snapshot of the periodic schedule. - * iso changes, interrupt usually doesn't. - */ - spin_lock_irqsave (&ehci->lock, flags); - for (i = 0; i < ehci->periodic_size; i++) { - p = ehci->pshadow [i]; - if (likely (!p.ptr)) - continue; - tag = Q_NEXT_TYPE(ehci, ehci->periodic [i]); - - temp = scnprintf (next, size, "%4d: ", i); - size -= temp; - next += temp; - - do { - struct ehci_qh_hw *hw; - - switch (hc32_to_cpu(ehci, tag)) { - case Q_TYPE_QH: - hw = p.qh->hw; - temp = scnprintf (next, size, " qh%d-%04x/%p", - p.qh->period, - hc32_to_cpup(ehci, - &hw->hw_info2) - /* uframe masks */ - & (QH_CMASK | QH_SMASK), - p.qh); - size -= temp; - next += temp; - /* don't repeat what follows this qh */ - for (temp = 0; temp < seen_count; temp++) { - if (seen [temp].ptr != p.ptr) - continue; - if (p.qh->qh_next.ptr) { - temp = scnprintf (next, size, - " ..."); - size -= temp; - next += temp; - } - break; - } - /* show more info the first time around */ - if (temp == seen_count) { - u32 scratch = hc32_to_cpup(ehci, - &hw->hw_info1); - struct ehci_qtd *qtd; - char *type = ""; - - /* count tds, get ep direction */ - temp = 0; - list_for_each_entry (qtd, - &p.qh->qtd_list, - qtd_list) { - temp++; - switch (0x03 & (hc32_to_cpu( - ehci, - qtd->hw_token) >> 8)) { - case 0: type = "out"; continue; - case 1: type = "in"; continue; - } - } - - temp = scnprintf (next, size, - " (%c%d ep%d%s " - "[%d/%d] q%d p%d)", - speed_char (scratch), - scratch & 0x007f, - (scratch >> 8) & 0x000f, type, - p.qh->usecs, p.qh->c_usecs, - temp, - 0x7ff & (scratch >> 16)); - - if (seen_count < DBG_SCHED_LIMIT) - seen [seen_count++].qh = p.qh; - } else - temp = 0; - tag = Q_NEXT_TYPE(ehci, hw->hw_next); - p = p.qh->qh_next; - break; - case Q_TYPE_FSTN: - temp = scnprintf (next, size, - " fstn-%8x/%p", p.fstn->hw_prev, - p.fstn); - tag = Q_NEXT_TYPE(ehci, p.fstn->hw_next); - p = p.fstn->fstn_next; - break; - case Q_TYPE_ITD: - temp = scnprintf (next, size, - " itd/%p", p.itd); - tag = Q_NEXT_TYPE(ehci, p.itd->hw_next); - p = p.itd->itd_next; - break; - case Q_TYPE_SITD: - temp = scnprintf (next, size, - " sitd%d-%04x/%p", - p.sitd->stream->interval, - hc32_to_cpup(ehci, &p.sitd->hw_uframe) - & 0x0000ffff, - p.sitd); - tag = Q_NEXT_TYPE(ehci, p.sitd->hw_next); - p = p.sitd->sitd_next; - break; - } - size -= temp; - next += temp; - } while (p.ptr); - - temp = scnprintf (next, size, "\n"); - size -= temp; - next += temp; - } - spin_unlock_irqrestore (&ehci->lock, flags); - kfree (seen); - - return buf->alloc_size - size; -} -#undef DBG_SCHED_LIMIT - -static const char *rh_state_string(struct ehci_hcd *ehci) -{ - switch (ehci->rh_state) { - case EHCI_RH_HALTED: - return "halted"; - case EHCI_RH_SUSPENDED: - return "suspended"; - case EHCI_RH_RUNNING: - return "running"; - case EHCI_RH_STOPPING: - return "stopping"; - } - return "?"; -} - -static ssize_t fill_registers_buffer(struct debug_buffer *buf) -{ - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - unsigned long flags; - unsigned temp, size, i; - char *next, scratch [80]; - static char fmt [] = "%*s\n"; - static char label [] = ""; - - hcd = bus_to_hcd(buf->bus); - ehci = hcd_to_ehci (hcd); - next = buf->output_buf; - size = buf->alloc_size; - - spin_lock_irqsave (&ehci->lock, flags); - - if (!HCD_HW_ACCESSIBLE(hcd)) { - size = scnprintf (next, size, - "bus %s, device %s\n" - "%s\n" - "SUSPENDED (no register access)\n", - hcd->self.controller->bus->name, - dev_name(hcd->self.controller), - hcd->product_desc); - goto done; - } - - /* Capability Registers */ - i = HC_VERSION(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - temp = scnprintf (next, size, - "bus %s, device %s\n" - "%s\n" - "EHCI %x.%02x, rh state %s\n", - hcd->self.controller->bus->name, - dev_name(hcd->self.controller), - hcd->product_desc, - i >> 8, i & 0x0ff, rh_state_string(ehci)); - size -= temp; - next += temp; - -#ifdef CONFIG_PCI - /* EHCI 0.96 and later may have "extended capabilities" */ - if (hcd->self.controller->bus == &pci_bus_type) { - struct pci_dev *pdev; - u32 offset, cap, cap2; - unsigned count = 256/4; - - pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); - offset = HCC_EXT_CAPS(ehci_readl(ehci, - &ehci->caps->hcc_params)); - while (offset && count--) { - pci_read_config_dword (pdev, offset, &cap); - switch (cap & 0xff) { - case 1: - temp = scnprintf (next, size, - "ownership %08x%s%s\n", cap, - (cap & (1 << 24)) ? " linux" : "", - (cap & (1 << 16)) ? " firmware" : ""); - size -= temp; - next += temp; - - offset += 4; - pci_read_config_dword (pdev, offset, &cap2); - temp = scnprintf (next, size, - "SMI sts/enable 0x%08x\n", cap2); - size -= temp; - next += temp; - break; - case 0: /* illegal reserved capability */ - cap = 0; - /* FALLTHROUGH */ - default: /* unknown */ - break; - } - temp = (cap >> 8) & 0xff; - } - } -#endif - - // FIXME interpret both types of params - i = ehci_readl(ehci, &ehci->caps->hcs_params); - temp = scnprintf (next, size, "structural params 0x%08x\n", i); - size -= temp; - next += temp; - - i = ehci_readl(ehci, &ehci->caps->hcc_params); - temp = scnprintf (next, size, "capability params 0x%08x\n", i); - size -= temp; - next += temp; - - /* Operational Registers */ - temp = dbg_status_buf (scratch, sizeof scratch, label, - ehci_readl(ehci, &ehci->regs->status)); - temp = scnprintf (next, size, fmt, temp, scratch); - size -= temp; - next += temp; - - temp = dbg_command_buf (scratch, sizeof scratch, label, - ehci_readl(ehci, &ehci->regs->command)); - temp = scnprintf (next, size, fmt, temp, scratch); - size -= temp; - next += temp; - - temp = dbg_intr_buf (scratch, sizeof scratch, label, - ehci_readl(ehci, &ehci->regs->intr_enable)); - temp = scnprintf (next, size, fmt, temp, scratch); - size -= temp; - next += temp; - - temp = scnprintf (next, size, "uframe %04x\n", - ehci_read_frame_index(ehci)); - size -= temp; - next += temp; - - for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) { - temp = dbg_port_buf (scratch, sizeof scratch, label, i, - ehci_readl(ehci, - &ehci->regs->port_status[i - 1])); - temp = scnprintf (next, size, fmt, temp, scratch); - size -= temp; - next += temp; - if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) { - temp = scnprintf (next, size, - " debug control %08x\n", - ehci_readl(ehci, - &ehci->debug->control)); - size -= temp; - next += temp; - } - } - - if (!list_empty(&ehci->async_unlink)) { - temp = scnprintf(next, size, "async unlink qh %p\n", - list_first_entry(&ehci->async_unlink, - struct ehci_qh, unlink_node)); - size -= temp; - next += temp; - } - -#ifdef EHCI_STATS - temp = scnprintf (next, size, - "irq normal %ld err %ld iaa %ld (lost %ld)\n", - ehci->stats.normal, ehci->stats.error, ehci->stats.iaa, - ehci->stats.lost_iaa); - size -= temp; - next += temp; - - temp = scnprintf (next, size, "complete %ld unlink %ld\n", - ehci->stats.complete, ehci->stats.unlink); - size -= temp; - next += temp; -#endif - -done: - spin_unlock_irqrestore (&ehci->lock, flags); - - return buf->alloc_size - size; -} - -static struct debug_buffer *alloc_buffer(struct usb_bus *bus, - ssize_t (*fill_func)(struct debug_buffer *)) -{ - struct debug_buffer *buf; - - buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); - - if (buf) { - buf->bus = bus; - buf->fill_func = fill_func; - mutex_init(&buf->mutex); - buf->alloc_size = PAGE_SIZE; - } - - return buf; -} - -static int fill_buffer(struct debug_buffer *buf) -{ - int ret = 0; - - if (!buf->output_buf) - buf->output_buf = vmalloc(buf->alloc_size); - - if (!buf->output_buf) { - ret = -ENOMEM; - goto out; - } - - ret = buf->fill_func(buf); - - if (ret >= 0) { - buf->count = ret; - ret = 0; - } - -out: - return ret; -} - -static ssize_t debug_output(struct file *file, char __user *user_buf, - size_t len, loff_t *offset) -{ - struct debug_buffer *buf = file->private_data; - int ret = 0; - - mutex_lock(&buf->mutex); - if (buf->count == 0) { - ret = fill_buffer(buf); - if (ret != 0) { - mutex_unlock(&buf->mutex); - goto out; - } - } - mutex_unlock(&buf->mutex); - - ret = simple_read_from_buffer(user_buf, len, offset, - buf->output_buf, buf->count); - -out: - return ret; - -} - -static int debug_close(struct inode *inode, struct file *file) -{ - struct debug_buffer *buf = file->private_data; - - if (buf) { - vfree(buf->output_buf); - kfree(buf); - } - - return 0; -} -static int debug_async_open(struct inode *inode, struct file *file) -{ - file->private_data = alloc_buffer(inode->i_private, fill_async_buffer); - - return file->private_data ? 0 : -ENOMEM; -} - -static int debug_periodic_open(struct inode *inode, struct file *file) -{ - struct debug_buffer *buf; - buf = alloc_buffer(inode->i_private, fill_periodic_buffer); - if (!buf) - return -ENOMEM; - - buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE; - file->private_data = buf; - return 0; -} - -static int debug_registers_open(struct inode *inode, struct file *file) -{ - file->private_data = alloc_buffer(inode->i_private, - fill_registers_buffer); - - return file->private_data ? 0 : -ENOMEM; -} - -static inline void create_debug_files (struct ehci_hcd *ehci) -{ - struct usb_bus *bus = &ehci_to_hcd(ehci)->self; - - ehci->debug_dir = debugfs_create_dir(bus->bus_name, ehci_debug_root); - if (!ehci->debug_dir) - return; - - if (!debugfs_create_file("async", S_IRUGO, ehci->debug_dir, bus, - &debug_async_fops)) - goto file_error; - - if (!debugfs_create_file("periodic", S_IRUGO, ehci->debug_dir, bus, - &debug_periodic_fops)) - goto file_error; - - if (!debugfs_create_file("registers", S_IRUGO, ehci->debug_dir, bus, - &debug_registers_fops)) - goto file_error; - - return; - -file_error: - debugfs_remove_recursive(ehci->debug_dir); -} - -static inline void remove_debug_files (struct ehci_hcd *ehci) -{ - debugfs_remove_recursive(ehci->debug_dir); -} - -#endif /* STUB_DEBUG_FILES */ diff --git a/addons/ehci-pci/src/3.10.108/ehci-hcd.c b/addons/ehci-pci/src/3.10.108/ehci-hcd.c deleted file mode 100644 index 5a160063..00000000 --- a/addons/ehci-pci/src/3.10.108/ehci-hcd.c +++ /dev/null @@ -1,1391 +0,0 @@ -/* - * Enhanced Host Controller Interface (EHCI) driver for USB. - * - * Maintainer: Alan Stern - * - * Copyright (c) 2000-2004 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#if defined(CONFIG_PPC_PS3) -#include -#endif - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI hc_driver implementation ... experimental, incomplete. - * Based on the final 1.0 register interface specification. - * - * USB 2.0 shows up in upcoming www.pcmcia.org technology. - * First was PCMCIA, like ISA; then CardBus, which is PCI. - * Next comes "CardBay", using USB 2.0 signals. - * - * Contains additional contributions by Brad Hards, Rory Bolt, and others. - * Special thanks to Intel and VIA for providing host controllers to - * test this driver on, and Cypress (including In-System Design) for - * providing early devices for those host controllers to talk to! - */ - -#define DRIVER_AUTHOR "David Brownell" -#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver" - -static const char hcd_name [] = "ehci_hcd"; - - -#undef VERBOSE_DEBUG -#undef EHCI_URB_TRACE - -/* magic numbers that can affect system performance */ -#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ -#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ -#define EHCI_TUNE_RL_TT 0 -#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ -#define EHCI_TUNE_MULT_TT 1 -/* - * Some drivers think it's safe to schedule isochronous transfers more than - * 256 ms into the future (partly as a result of an old bug in the scheduling - * code). In an attempt to avoid trouble, we will use a minimum scheduling - * length of 512 frames instead of 256. - */ -#define EHCI_TUNE_FLS 1 /* (medium) 512-frame schedule */ - -/* Initial IRQ latency: faster than hw default */ -static int log2_irq_thresh = 0; // 0 to 6 -module_param (log2_irq_thresh, int, S_IRUGO); -MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes"); - -/* initial park setting: slower than hw default */ -static unsigned park = 0; -module_param (park, uint, S_IRUGO); -MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets"); - -/* for flakey hardware, ignore overcurrent indicators */ -static bool ignore_oc = 0; -module_param (ignore_oc, bool, S_IRUGO); -MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); - -#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) - -/*-------------------------------------------------------------------------*/ - -#include "ehci.h" -#include "pci-quirks.h" - -/* - * The MosChip MCS9990 controller updates its microframe counter - * a little before the frame counter, and occasionally we will read - * the invalid intermediate value. Avoid problems by checking the - * microframe number (the low-order 3 bits); if they are 0 then - * re-read the register to get the correct value. - */ -static unsigned ehci_moschip_read_frame_index(struct ehci_hcd *ehci) -{ - unsigned uf; - - uf = ehci_readl(ehci, &ehci->regs->frame_index); - if (unlikely((uf & 7) == 0)) - uf = ehci_readl(ehci, &ehci->regs->frame_index); - return uf; -} - -static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) -{ - if (ehci->frame_index_bug) - return ehci_moschip_read_frame_index(ehci); - return ehci_readl(ehci, &ehci->regs->frame_index); -} - -#include "ehci-dbg.c" - -/*-------------------------------------------------------------------------*/ - -/* - * handshake - spin reading hc until handshake completes or fails - * @ptr: address of hc register to be read - * @mask: bits to look at in result of read - * @done: value of those bits when handshake succeeds - * @usec: timeout in microseconds - * - * Returns negative errno, or zero on success - * - * Success happens when the "mask" bits have the specified value (hardware - * handshake done). There are two failure modes: "usec" have passed (major - * hardware flakeout), or the register reads as all-ones (hardware removed). - * - * That last failure should_only happen in cases like physical cardbus eject - * before driver shutdown. But it also seems to be caused by bugs in cardbus - * bridge shutdown: shutting down the bridge before the devices using it. - */ -static int handshake (struct ehci_hcd *ehci, void __iomem *ptr, - u32 mask, u32 done, int usec) -{ - u32 result; - - do { - result = ehci_readl(ehci, ptr); - if (result == ~(u32)0) /* card removed */ - return -ENODEV; - result &= mask; - if (result == done) - return 0; - udelay (1); - usec--; - } while (usec > 0); - return -ETIMEDOUT; -} - -/* check TDI/ARC silicon is in host mode */ -static int tdi_in_host_mode (struct ehci_hcd *ehci) -{ - u32 tmp; - - tmp = ehci_readl(ehci, &ehci->regs->usbmode); - return (tmp & 3) == USBMODE_CM_HC; -} - -/* - * Force HC to halt state from unknown (EHCI spec section 2.3). - * Must be called with interrupts enabled and the lock not held. - */ -static int ehci_halt (struct ehci_hcd *ehci) -{ - u32 temp; - - spin_lock_irq(&ehci->lock); - - /* disable any irqs left enabled by previous code */ - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - - if (ehci_is_TDI(ehci) && !tdi_in_host_mode(ehci)) { - spin_unlock_irq(&ehci->lock); - return 0; - } - - /* - * This routine gets called during probe before ehci->command - * has been initialized, so we can't rely on its value. - */ - ehci->command &= ~CMD_RUN; - temp = ehci_readl(ehci, &ehci->regs->command); - temp &= ~(CMD_RUN | CMD_IAAD); - ehci_writel(ehci, temp, &ehci->regs->command); - - spin_unlock_irq(&ehci->lock); - synchronize_irq(ehci_to_hcd(ehci)->irq); - - return handshake(ehci, &ehci->regs->status, - STS_HALT, STS_HALT, 16 * 125); -} - -/* put TDI/ARC silicon into EHCI mode */ -static void tdi_reset (struct ehci_hcd *ehci) -{ - u32 tmp; - - tmp = ehci_readl(ehci, &ehci->regs->usbmode); - tmp |= USBMODE_CM_HC; - /* The default byte access to MMR space is LE after - * controller reset. Set the required endian mode - * for transfer buffers to match the host microprocessor - */ - if (ehci_big_endian_mmio(ehci)) - tmp |= USBMODE_BE; - ehci_writel(ehci, tmp, &ehci->regs->usbmode); -} - -/* - * Reset a non-running (STS_HALT == 1) controller. - * Must be called with interrupts enabled and the lock not held. - */ -static int ehci_reset (struct ehci_hcd *ehci) -{ - int retval; - u32 command = ehci_readl(ehci, &ehci->regs->command); - - /* If the EHCI debug controller is active, special care must be - * taken before and after a host controller reset */ - if (ehci->debug && !dbgp_reset_prep(ehci_to_hcd(ehci))) - ehci->debug = NULL; - - command |= CMD_RESET; - dbg_cmd (ehci, "reset", command); - ehci_writel(ehci, command, &ehci->regs->command); - ehci->rh_state = EHCI_RH_HALTED; - ehci->next_statechange = jiffies; - retval = handshake (ehci, &ehci->regs->command, - CMD_RESET, 0, 250 * 1000); - - if (ehci->has_hostpc) { - ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS, - &ehci->regs->usbmode_ex); - ehci_writel(ehci, TXFIFO_DEFAULT, &ehci->regs->txfill_tuning); - } - if (retval) - return retval; - - if (ehci_is_TDI(ehci)) - tdi_reset (ehci); - - if (ehci->debug) - dbgp_external_startup(ehci_to_hcd(ehci)); - - ehci->port_c_suspend = ehci->suspended_ports = - ehci->resuming_ports = 0; - return retval; -} - -/* - * Idle the controller (turn off the schedules). - * Must be called with interrupts enabled and the lock not held. - */ -static void ehci_quiesce (struct ehci_hcd *ehci) -{ - u32 temp; - - if (ehci->rh_state != EHCI_RH_RUNNING) - return; - - /* wait for any schedule enables/disables to take effect */ - temp = (ehci->command << 10) & (STS_ASS | STS_PSS); - handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, 16 * 125); - - /* then disable anything that's still active */ - spin_lock_irq(&ehci->lock); - ehci->command &= ~(CMD_ASE | CMD_PSE); - ehci_writel(ehci, ehci->command, &ehci->regs->command); - spin_unlock_irq(&ehci->lock); - - /* hardware can take 16 microframes to turn off ... */ - handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, 16 * 125); -} - -/*-------------------------------------------------------------------------*/ - -static void end_unlink_async(struct ehci_hcd *ehci); -static void unlink_empty_async(struct ehci_hcd *ehci); -static void unlink_empty_async_suspended(struct ehci_hcd *ehci); -static void ehci_work(struct ehci_hcd *ehci); -static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); -static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); - -#include "ehci-timer.c" -#include "ehci-hub.c" -#include "ehci-mem.c" -#include "ehci-q.c" -#include "ehci-sched.c" -#include "ehci-sysfs.c" - -/*-------------------------------------------------------------------------*/ - -/* On some systems, leaving remote wakeup enabled prevents system shutdown. - * The firmware seems to think that powering off is a wakeup event! - * This routine turns off remote wakeup and everything else, on all ports. - */ -static void ehci_turn_off_all_ports(struct ehci_hcd *ehci) -{ - int port = HCS_N_PORTS(ehci->hcs_params); - - while (port--) - ehci_writel(ehci, PORT_RWC_BITS, - &ehci->regs->port_status[port]); -} - -/* - * Halt HC, turn off all ports, and let the BIOS use the companion controllers. - * Must be called with interrupts enabled and the lock not held. - */ -static void ehci_silence_controller(struct ehci_hcd *ehci) -{ - ehci_halt(ehci); - - spin_lock_irq(&ehci->lock); - ehci->rh_state = EHCI_RH_HALTED; - ehci_turn_off_all_ports(ehci); - - /* make BIOS/etc use companion controller during reboot */ - ehci_writel(ehci, 0, &ehci->regs->configured_flag); - - /* unblock posted writes */ - ehci_readl(ehci, &ehci->regs->configured_flag); - spin_unlock_irq(&ehci->lock); -} - -/* ehci_shutdown kick in for silicon on any bus (not just pci, etc). - * This forcibly disables dma and IRQs, helping kexec and other cases - * where the next system software may expect clean state. - */ -static void ehci_shutdown(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - spin_lock_irq(&ehci->lock); - ehci->shutdown = true; - ehci->rh_state = EHCI_RH_STOPPING; - ehci->enabled_hrtimer_events = 0; - spin_unlock_irq(&ehci->lock); - - ehci_silence_controller(ehci); - - hrtimer_cancel(&ehci->hrtimer); -} - -/*-------------------------------------------------------------------------*/ - -/* - * ehci_work is called from some interrupts, timers, and so on. - * it calls driver completion functions, after dropping ehci->lock. - */ -static void ehci_work (struct ehci_hcd *ehci) -{ - /* another CPU may drop ehci->lock during a schedule scan while - * it reports urb completions. this flag guards against bogus - * attempts at re-entrant schedule scanning. - */ - if (ehci->scanning) { - ehci->need_rescan = true; - return; - } - ehci->scanning = true; - - rescan: - ehci->need_rescan = false; - if (ehci->async_count) - scan_async(ehci); - if (ehci->intr_count > 0) - scan_intr(ehci); - if (ehci->isoc_count > 0) - scan_isoc(ehci); - if (ehci->need_rescan) - goto rescan; - ehci->scanning = false; - - /* the IO watchdog guards against hardware or driver bugs that - * misplace IRQs, and should let us run completely without IRQs. - * such lossage has been observed on both VT6202 and VT8235. - */ - turn_on_io_watchdog(ehci); -} - -/* - * Called when the ehci_hcd module is removed. - */ -static void ehci_stop (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - - ehci_dbg (ehci, "stop\n"); - - /* no more interrupts ... */ - - spin_lock_irq(&ehci->lock); - ehci->enabled_hrtimer_events = 0; - spin_unlock_irq(&ehci->lock); - - ehci_quiesce(ehci); - ehci_silence_controller(ehci); - ehci_reset (ehci); - - hrtimer_cancel(&ehci->hrtimer); - remove_sysfs_files(ehci); - remove_debug_files (ehci); - - /* root hub is shut down separately (first, when possible) */ - spin_lock_irq (&ehci->lock); - end_free_itds(ehci); - spin_unlock_irq (&ehci->lock); - ehci_mem_cleanup (ehci); - - if (ehci->amd_pll_fix == 1) - usb_amd_dev_put(); - -#ifdef EHCI_STATS - ehci_dbg(ehci, "irq normal %ld err %ld iaa %ld (lost %ld)\n", - ehci->stats.normal, ehci->stats.error, ehci->stats.iaa, - ehci->stats.lost_iaa); - ehci_dbg (ehci, "complete %ld unlink %ld\n", - ehci->stats.complete, ehci->stats.unlink); -#endif - - dbg_status (ehci, "ehci_stop completed", - ehci_readl(ehci, &ehci->regs->status)); -} - -/* one-time init, only for memory state */ -static int ehci_init(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - u32 temp; - int retval; - u32 hcc_params; - struct ehci_qh_hw *hw; - - spin_lock_init(&ehci->lock); - - /* - * keep io watchdog by default, those good HCDs could turn off it later - */ - ehci->need_io_watchdog = 1; - - hrtimer_init(&ehci->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); - ehci->hrtimer.function = ehci_hrtimer_func; - ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT; - - hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); - - /* - * by default set standard 80% (== 100 usec/uframe) max periodic - * bandwidth as required by USB 2.0 - */ - ehci->uframe_periodic_max = 100; - - /* - * hw default: 1K periodic list heads, one per frame. - * periodic_size can shrink by USBCMD update if hcc_params allows. - */ - ehci->periodic_size = DEFAULT_I_TDPS; - INIT_LIST_HEAD(&ehci->async_unlink); - INIT_LIST_HEAD(&ehci->async_idle); - INIT_LIST_HEAD(&ehci->intr_unlink); - INIT_LIST_HEAD(&ehci->intr_qh_list); - INIT_LIST_HEAD(&ehci->cached_itd_list); - INIT_LIST_HEAD(&ehci->cached_sitd_list); - - if (HCC_PGM_FRAMELISTLEN(hcc_params)) { - /* periodic schedule size can be smaller than default */ - switch (EHCI_TUNE_FLS) { - case 0: ehci->periodic_size = 1024; break; - case 1: ehci->periodic_size = 512; break; - case 2: ehci->periodic_size = 256; break; - default: BUG(); - } - } - if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) - return retval; - - /* controllers may cache some of the periodic schedule ... */ - if (HCC_ISOC_CACHE(hcc_params)) // full frame cache - ehci->i_thresh = 0; - else // N microframes cached - ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); - - /* - * dedicate a qh for the async ring head, since we couldn't unlink - * a 'real' qh without stopping the async schedule [4.8]. use it - * as the 'reclamation list head' too. - * its dummy is used in hw_alt_next of many tds, to prevent the qh - * from automatically advancing to the next td after short reads. - */ - ehci->async->qh_next.qh = NULL; - hw = ehci->async->hw; - hw->hw_next = QH_NEXT(ehci, ehci->async->qh_dma); - hw->hw_info1 = cpu_to_hc32(ehci, QH_HEAD); -#if defined(CONFIG_PPC_PS3) - hw->hw_info1 |= cpu_to_hc32(ehci, QH_INACTIVATE); -#endif - hw->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); - hw->hw_qtd_next = EHCI_LIST_END(ehci); - ehci->async->qh_state = QH_STATE_LINKED; - hw->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma); - - /* clear interrupt enables, set irq latency */ - if (log2_irq_thresh < 0 || log2_irq_thresh > 6) - log2_irq_thresh = 0; - temp = 1 << (16 + log2_irq_thresh); - if (HCC_PER_PORT_CHANGE_EVENT(hcc_params)) { - ehci->has_ppcd = 1; - ehci_dbg(ehci, "enable per-port change event\n"); - temp |= CMD_PPCEE; - } - if (HCC_CANPARK(hcc_params)) { - /* HW default park == 3, on hardware that supports it (like - * NVidia and ALI silicon), maximizes throughput on the async - * schedule by avoiding QH fetches between transfers. - * - * With fast usb storage devices and NForce2, "park" seems to - * make problems: throughput reduction (!), data errors... - */ - if (park) { - park = min(park, (unsigned) 3); - temp |= CMD_PARK; - temp |= park << 8; - } - ehci_dbg(ehci, "park %d\n", park); - } - if (HCC_PGM_FRAMELISTLEN(hcc_params)) { - /* periodic schedule size can be smaller than default */ - temp &= ~(3 << 2); - temp |= (EHCI_TUNE_FLS << 2); - } - ehci->command = temp; - - /* Accept arbitrarily long scatter-gather lists */ - if (!(hcd->driver->flags & HCD_LOCAL_MEM)) - hcd->self.sg_tablesize = ~0; - return 0; -} - -/* start HC running; it's halted, ehci_init() has been run (once) */ -static int ehci_run (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 temp; - u32 hcc_params; - - hcd->uses_new_polling = 1; - - /* EHCI spec section 4.1 */ - - ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); - ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next); - - /* - * hcc_params controls whether ehci->regs->segment must (!!!) - * be used; it constrains QH/ITD/SITD and QTD locations. - * pci_pool consistent memory always uses segment zero. - * streaming mappings for I/O buffers, like pci_map_single(), - * can return segments above 4GB, if the device allows. - * - * NOTE: the dma mask is visible through dma_supported(), so - * drivers can pass this info along ... like NETIF_F_HIGHDMA, - * Scsi_Host.highmem_io, and so forth. It's readonly to all - * host side drivers though. - */ - hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); - if (HCC_64BIT_ADDR(hcc_params)) { - ehci_writel(ehci, 0, &ehci->regs->segment); -#if 0 -// this is deeply broken on almost all architectures - if (!dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64))) - ehci_info(ehci, "enabled 64bit DMA\n"); -#endif - } - - - // Philips, Intel, and maybe others need CMD_RUN before the - // root hub will detect new devices (why?); NEC doesn't - ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); - ehci->command |= CMD_RUN; - ehci_writel(ehci, ehci->command, &ehci->regs->command); - dbg_cmd (ehci, "init", ehci->command); - - /* - * Start, enabling full USB 2.0 functionality ... usb 1.1 devices - * are explicitly handed to companion controller(s), so no TT is - * involved with the root hub. (Except where one is integrated, - * and there's no companion controller unless maybe for USB OTG.) - * - * Turning on the CF flag will transfer ownership of all ports - * from the companions to the EHCI controller. If any of the - * companions are in the middle of a port reset at the time, it - * could cause trouble. Write-locking ehci_cf_port_reset_rwsem - * guarantees that no resets are in progress. After we set CF, - * a short delay lets the hardware catch up; new resets shouldn't - * be started before the port switching actions could complete. - */ - down_write(&ehci_cf_port_reset_rwsem); - ehci->rh_state = EHCI_RH_RUNNING; - ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ - msleep(5); - up_write(&ehci_cf_port_reset_rwsem); - ehci->last_periodic_enable = ktime_get_real(); - - temp = HC_VERSION(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - ehci_info (ehci, - "USB %x.%x started, EHCI %x.%02x%s\n", - ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), - temp >> 8, temp & 0xff, - ignore_oc ? ", overcurrent ignored" : ""); - - ehci_writel(ehci, INTR_MASK, - &ehci->regs->intr_enable); /* Turn On Interrupts */ - - /* GRR this is run-once init(), being done every time the HC starts. - * So long as they're part of class devices, we can't do it init() - * since the class device isn't created that early. - */ - create_debug_files(ehci); - create_sysfs_files(ehci); - - return 0; -} - -int ehci_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - ehci->regs = (void __iomem *)ehci->caps + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - - ehci->sbrn = HCD_USB2; - - /* data structure init */ - retval = ehci_init(hcd); - if (retval) - return retval; - - retval = ehci_halt(ehci); - if (retval) - return retval; - - ehci_reset(ehci); - - return 0; -} -EXPORT_SYMBOL_GPL(ehci_setup); - -/*-------------------------------------------------------------------------*/ - -static irqreturn_t ehci_irq (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 status, masked_status, pcd_status = 0, cmd; - int bh; - unsigned long flags; - - /* - * For threadirqs option we use spin_lock_irqsave() variant to prevent - * deadlock with ehci hrtimer callback, because hrtimer callbacks run - * in interrupt context even when threadirqs is specified. We can go - * back to spin_lock() variant when hrtimer callbacks become threaded. - */ - spin_lock_irqsave(&ehci->lock, flags); - - status = ehci_readl(ehci, &ehci->regs->status); - - /* e.g. cardbus physical eject */ - if (status == ~(u32) 0) { - ehci_dbg (ehci, "device removed\n"); - goto dead; - } - - /* - * We don't use STS_FLR, but some controllers don't like it to - * remain on, so mask it out along with the other status bits. - */ - masked_status = status & (INTR_MASK | STS_FLR); - - /* Shared IRQ? */ - if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) { - spin_unlock_irqrestore(&ehci->lock, flags); - return IRQ_NONE; - } - - /* clear (just) interrupts */ - ehci_writel(ehci, masked_status, &ehci->regs->status); - cmd = ehci_readl(ehci, &ehci->regs->command); - bh = 0; - -#ifdef VERBOSE_DEBUG - /* unrequested/ignored: Frame List Rollover */ - dbg_status (ehci, "irq", status); -#endif - - /* INT, ERR, and IAA interrupt rates can be throttled */ - - /* normal [4.15.1.2] or error [4.15.1.1] completion */ - if (likely ((status & (STS_INT|STS_ERR)) != 0)) { - if (likely ((status & STS_ERR) == 0)) - COUNT (ehci->stats.normal); - else - COUNT (ehci->stats.error); - bh = 1; - } - - /* complete the unlinking of some qh [4.15.2.3] */ - if (status & STS_IAA) { - - /* Turn off the IAA watchdog */ - ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_IAA_WATCHDOG); - - /* - * Mild optimization: Allow another IAAD to reset the - * hrtimer, if one occurs before the next expiration. - * In theory we could always cancel the hrtimer, but - * tests show that about half the time it will be reset - * for some other event anyway. - */ - if (ehci->next_hrtimer_event == EHCI_HRTIMER_IAA_WATCHDOG) - ++ehci->next_hrtimer_event; - - /* guard against (alleged) silicon errata */ - if (cmd & CMD_IAAD) - ehci_dbg(ehci, "IAA with IAAD still set?\n"); - if (ehci->iaa_in_progress) - COUNT(ehci->stats.iaa); - end_unlink_async(ehci); - } - - /* remote wakeup [4.3.1] */ - if (status & STS_PCD) { - unsigned i = HCS_N_PORTS (ehci->hcs_params); - u32 ppcd = ~0; - - /* kick root hub later */ - pcd_status = status; - - /* resume root hub? */ - if (ehci->rh_state == EHCI_RH_SUSPENDED) - usb_hcd_resume_root_hub(hcd); - - /* get per-port change detect bits */ - if (ehci->has_ppcd) - ppcd = status >> 16; - - while (i--) { - int pstatus; - - /* leverage per-port change bits feature */ - if (!(ppcd & (1 << i))) - continue; - pstatus = ehci_readl(ehci, - &ehci->regs->port_status[i]); - - if (pstatus & PORT_OWNER) - continue; - if (!(test_bit(i, &ehci->suspended_ports) && - ((pstatus & PORT_RESUME) || - !(pstatus & PORT_SUSPEND)) && - (pstatus & PORT_PE) && - ehci->reset_done[i] == 0)) - continue; - - /* start 20 msec resume signaling from this port, - * and make khubd collect PORT_STAT_C_SUSPEND to - * stop that signaling. Use 5 ms extra for safety, - * like usb_port_resume() does. - */ - ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); - set_bit(i, &ehci->resuming_ports); - ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); - usb_hcd_start_port_resume(&hcd->self, i); - mod_timer(&hcd->rh_timer, ehci->reset_done[i]); - } - } - - /* PCI errors [4.15.2.4] */ - if (unlikely ((status & STS_FATAL) != 0)) { - ehci_err(ehci, "fatal error\n"); - dbg_cmd(ehci, "fatal", cmd); - dbg_status(ehci, "fatal", status); -dead: - usb_hc_died(hcd); - - /* Don't let the controller do anything more */ - ehci->shutdown = true; - ehci->rh_state = EHCI_RH_STOPPING; - ehci->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE); - ehci_writel(ehci, ehci->command, &ehci->regs->command); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - ehci_handle_controller_death(ehci); - - /* Handle completions when the controller stops */ - bh = 0; - } - - if (bh) - ehci_work (ehci); - spin_unlock_irqrestore(&ehci->lock, flags); - if (pcd_status) - usb_hcd_poll_rh_status(hcd); - return IRQ_HANDLED; -} - -/*-------------------------------------------------------------------------*/ - -/* - * non-error returns are a promise to giveback() the urb later - * we drop ownership so next owner (or urb unlink) can get it - * - * urb + dev is in hcd.self.controller.urb_list - * we're queueing TDs onto software and hardware lists - * - * hcd-specific init for hcpriv hasn't been done yet - * - * NOTE: control, bulk, and interrupt share the same code to append TDs - * to a (possibly active) QH, and the same QH scanning code. - */ -static int ehci_urb_enqueue ( - struct usb_hcd *hcd, - struct urb *urb, - gfp_t mem_flags -) { - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - struct list_head qtd_list; - - INIT_LIST_HEAD (&qtd_list); - - switch (usb_pipetype (urb->pipe)) { - case PIPE_CONTROL: - /* qh_completions() code doesn't handle all the fault cases - * in multi-TD control transfers. Even 1KB is rare anyway. - */ - if (urb->transfer_buffer_length > (16 * 1024)) - return -EMSGSIZE; - /* FALLTHROUGH */ - /* case PIPE_BULK: */ - default: - if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) - return -ENOMEM; - return submit_async(ehci, urb, &qtd_list, mem_flags); - - case PIPE_INTERRUPT: - if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) - return -ENOMEM; - return intr_submit(ehci, urb, &qtd_list, mem_flags); - - case PIPE_ISOCHRONOUS: - if (urb->dev->speed == USB_SPEED_HIGH) - return itd_submit (ehci, urb, mem_flags); - else - return sitd_submit (ehci, urb, mem_flags); - } -} - -/* remove from hardware lists - * completions normally happen asynchronously - */ - -static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - struct ehci_qh *qh; - unsigned long flags; - int rc; - - spin_lock_irqsave (&ehci->lock, flags); - rc = usb_hcd_check_unlink_urb(hcd, urb, status); - if (rc) - goto done; - - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - /* - * We don't expedite dequeue for isochronous URBs. - * Just wait until they complete normally or their - * time slot expires. - */ - } else { - qh = (struct ehci_qh *) urb->hcpriv; - qh->exception = 1; - switch (qh->qh_state) { - case QH_STATE_LINKED: - if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) - start_unlink_intr(ehci, qh); - else - start_unlink_async(ehci, qh); - break; - case QH_STATE_COMPLETING: - qh->dequeue_during_giveback = 1; - break; - case QH_STATE_UNLINK: - case QH_STATE_UNLINK_WAIT: - /* already started */ - break; - case QH_STATE_IDLE: - /* QH might be waiting for a Clear-TT-Buffer */ - qh_completions(ehci, qh); - break; - } - } -done: - spin_unlock_irqrestore (&ehci->lock, flags); - return rc; -} - -/*-------------------------------------------------------------------------*/ - -// bulk qh holds the data toggle - -static void -ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - unsigned long flags; - struct ehci_qh *qh, *tmp; - - /* ASSERT: any requests/urbs are being unlinked */ - /* ASSERT: nobody can be submitting urbs for this any more */ - -rescan: - spin_lock_irqsave (&ehci->lock, flags); - qh = ep->hcpriv; - if (!qh) - goto done; - - /* endpoints can be iso streams. for now, we don't - * accelerate iso completions ... so spin a while. - */ - if (qh->hw == NULL) { - struct ehci_iso_stream *stream = ep->hcpriv; - - if (!list_empty(&stream->td_list)) - goto idle_timeout; - - /* BUG_ON(!list_empty(&stream->free_list)); */ - kfree(stream); - goto done; - } - - qh->exception = 1; - switch (qh->qh_state) { - case QH_STATE_LINKED: - case QH_STATE_COMPLETING: - for (tmp = ehci->async->qh_next.qh; - tmp && tmp != qh; - tmp = tmp->qh_next.qh) - continue; - /* periodic qh self-unlinks on empty, and a COMPLETING qh - * may already be unlinked. - */ - if (tmp) - start_unlink_async(ehci, qh); - /* FALL THROUGH */ - case QH_STATE_UNLINK: /* wait for hw to finish? */ - case QH_STATE_UNLINK_WAIT: -idle_timeout: - spin_unlock_irqrestore (&ehci->lock, flags); - schedule_timeout_uninterruptible(1); - goto rescan; - case QH_STATE_IDLE: /* fully unlinked */ - if (qh->clearing_tt) - goto idle_timeout; - if (list_empty (&qh->qtd_list)) { - qh_destroy(ehci, qh); - break; - } - /* else FALL THROUGH */ - default: - /* caller was supposed to have unlinked any requests; - * that's not our job. just leak this memory. - */ - ehci_err (ehci, "qh %p (#%02x) state %d%s\n", - qh, ep->desc.bEndpointAddress, qh->qh_state, - list_empty (&qh->qtd_list) ? "" : "(has tds)"); - break; - } - done: - ep->hcpriv = NULL; - spin_unlock_irqrestore (&ehci->lock, flags); -} - -static void -ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct ehci_qh *qh; - int eptype = usb_endpoint_type(&ep->desc); - int epnum = usb_endpoint_num(&ep->desc); - int is_out = usb_endpoint_dir_out(&ep->desc); - unsigned long flags; - - if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) - return; - - spin_lock_irqsave(&ehci->lock, flags); - qh = ep->hcpriv; - - /* For Bulk and Interrupt endpoints we maintain the toggle state - * in the hardware; the toggle bits in udev aren't used at all. - * When an endpoint is reset by usb_clear_halt() we must reset - * the toggle bit in the QH. - */ - if (qh) { - usb_settoggle(qh->dev, epnum, is_out, 0); - if (!list_empty(&qh->qtd_list)) { - WARN_ONCE(1, "clear_halt for a busy endpoint\n"); - } else { - /* The toggle value in the QH can't be updated - * while the QH is active. Unlink it now; - * re-linking will call qh_refresh(). - */ - qh->exception = 1; - if (eptype == USB_ENDPOINT_XFER_BULK) - start_unlink_async(ehci, qh); - else - start_unlink_intr(ehci, qh); - } - } - spin_unlock_irqrestore(&ehci->lock, flags); -} - -static int ehci_get_frame (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - return (ehci_read_frame_index(ehci) >> 3) % ehci->periodic_size; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_PM - -/* suspend/resume, section 4.3 */ - -/* These routines handle the generic parts of controller suspend/resume */ - -int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - if (time_before(jiffies, ehci->next_statechange)) - msleep(10); - - /* - * Root hub was already suspended. Disable IRQ emission and - * mark HW unaccessible. The PM and USB cores make sure that - * the root hub is either suspended or stopped. - */ - ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup); - - spin_lock_irq(&ehci->lock); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - (void) ehci_readl(ehci, &ehci->regs->intr_enable); - - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - spin_unlock_irq(&ehci->lock); - - return 0; -} -EXPORT_SYMBOL_GPL(ehci_suspend); - -/* Returns 0 if power was preserved, 1 if power was lost */ -int ehci_resume(struct usb_hcd *hcd, bool hibernated) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - if (time_before(jiffies, ehci->next_statechange)) - msleep(100); - - /* Mark hardware accessible again as we are back to full power by now */ - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - if (ehci->shutdown) - return 0; /* Controller is dead */ - - /* - * If CF is still set and we aren't resuming from hibernation - * then we maintained suspend power. - * Just undo the effect of ehci_suspend(). - */ - if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF && - !hibernated) { - int mask = INTR_MASK; - - ehci_prepare_ports_for_controller_resume(ehci); - - spin_lock_irq(&ehci->lock); - if (ehci->shutdown) - goto skip; - - if (!hcd->self.root_hub->do_remote_wakeup) - mask &= ~STS_PCD; - ehci_writel(ehci, mask, &ehci->regs->intr_enable); - ehci_readl(ehci, &ehci->regs->intr_enable); - skip: - spin_unlock_irq(&ehci->lock); - return 0; - } - - /* - * Else reset, to cope with power loss or resume from hibernation - * having let the firmware kick in during reboot. - */ - usb_root_hub_lost_power(hcd->self.root_hub); - (void) ehci_halt(ehci); - (void) ehci_reset(ehci); - - spin_lock_irq(&ehci->lock); - if (ehci->shutdown) - goto skip; - - ehci_writel(ehci, ehci->command, &ehci->regs->command); - ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ - - ehci->rh_state = EHCI_RH_SUSPENDED; - spin_unlock_irq(&ehci->lock); - - return 1; -} -EXPORT_SYMBOL_GPL(ehci_resume); - -#endif - -/*-------------------------------------------------------------------------*/ - -/* - * Generic structure: This gets copied for platform drivers so that - * individual entries can be overridden as needed. - */ - -static const struct hc_driver ehci_hc_driver = { - .description = hcd_name, - .product_desc = "EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - /* - * basic lifecycle operations - */ - .reset = ehci_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, -}; - -void ehci_init_driver(struct hc_driver *drv, - const struct ehci_driver_overrides *over) -{ - /* Copy the generic table to drv and then apply the overrides */ - *drv = ehci_hc_driver; - - if (over) { - drv->hcd_priv_size += over->extra_priv_size; - if (over->reset) - drv->reset = over->reset; - } -} -EXPORT_SYMBOL_GPL(ehci_init_driver); - -/*-------------------------------------------------------------------------*/ - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR (DRIVER_AUTHOR); -MODULE_LICENSE ("GPL"); - -#ifdef CONFIG_USB_EHCI_FSL -#include "ehci-fsl.c" -#define PLATFORM_DRIVER ehci_fsl_driver -#endif - -#ifdef CONFIG_USB_EHCI_SH -#include "ehci-sh.c" -#define PLATFORM_DRIVER ehci_hcd_sh_driver -#endif - -#ifdef CONFIG_PPC_PS3 -#include "ehci-ps3.c" -#define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver -#endif - -#ifdef CONFIG_USB_EHCI_HCD_PPC_OF -#include "ehci-ppc-of.c" -#define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver -#endif - -#ifdef CONFIG_XPS_USB_HCD_XILINX -#include "ehci-xilinx-of.c" -#define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver -#endif - -#ifdef CONFIG_USB_W90X900_EHCI -#include "ehci-w90x900.c" -#define PLATFORM_DRIVER ehci_hcd_w90x900_driver -#endif - -#ifdef CONFIG_USB_OCTEON_EHCI -#include "ehci-octeon.c" -#define PLATFORM_DRIVER ehci_octeon_driver -#endif - -#ifdef CONFIG_TILE_USB -#include "ehci-tilegx.c" -#define PLATFORM_DRIVER ehci_hcd_tilegx_driver -#endif - -#ifdef CONFIG_USB_EHCI_HCD_PMC_MSP -#include "ehci-pmcmsp.c" -#define PLATFORM_DRIVER ehci_hcd_msp_driver -#endif - -#ifdef CONFIG_USB_EHCI_TEGRA -#include "ehci-tegra.c" -#define PLATFORM_DRIVER tegra_ehci_driver -#endif - -#ifdef CONFIG_SPARC_LEON -#include "ehci-grlib.c" -#define PLATFORM_DRIVER ehci_grlib_driver -#endif - -#ifdef CONFIG_USB_EHCI_MV -#include "ehci-mv.c" -#define PLATFORM_DRIVER ehci_mv_driver -#endif - -#ifdef CONFIG_MIPS_SEAD3 -#include "ehci-sead3.c" -#define PLATFORM_DRIVER ehci_hcd_sead3_driver -#endif - -static int __init ehci_hcd_init(void) -{ - int retval = 0; - - if (usb_disabled()) - return -ENODEV; - - printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name); - set_bit(USB_EHCI_LOADED, &usb_hcds_loaded); - if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) || - test_bit(USB_OHCI_LOADED, &usb_hcds_loaded)) - printk(KERN_WARNING "Warning! ehci_hcd should always be loaded" - " before uhci_hcd and ohci_hcd, not after\n"); - - pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", - hcd_name, - sizeof(struct ehci_qh), sizeof(struct ehci_qtd), - sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); - -#ifdef DEBUG - ehci_debug_root = debugfs_create_dir("ehci", usb_debug_root); - if (!ehci_debug_root) { - retval = -ENOENT; - goto err_debug; - } -#endif - -#ifdef PLATFORM_DRIVER - retval = platform_driver_register(&PLATFORM_DRIVER); - if (retval < 0) - goto clean0; -#endif - -#ifdef PS3_SYSTEM_BUS_DRIVER - retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER); - if (retval < 0) - goto clean2; -#endif - -#ifdef OF_PLATFORM_DRIVER - retval = platform_driver_register(&OF_PLATFORM_DRIVER); - if (retval < 0) - goto clean3; -#endif - -#ifdef XILINX_OF_PLATFORM_DRIVER - retval = platform_driver_register(&XILINX_OF_PLATFORM_DRIVER); - if (retval < 0) - goto clean4; -#endif - return retval; - -#ifdef XILINX_OF_PLATFORM_DRIVER - /* platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); */ -clean4: -#endif -#ifdef OF_PLATFORM_DRIVER - platform_driver_unregister(&OF_PLATFORM_DRIVER); -clean3: -#endif -#ifdef PS3_SYSTEM_BUS_DRIVER - ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); -clean2: -#endif -#ifdef PLATFORM_DRIVER - platform_driver_unregister(&PLATFORM_DRIVER); -clean0: -#endif -#ifdef DEBUG - debugfs_remove(ehci_debug_root); - ehci_debug_root = NULL; -err_debug: -#endif - clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); - return retval; -} -module_init(ehci_hcd_init); - -static void __exit ehci_hcd_cleanup(void) -{ -#ifdef XILINX_OF_PLATFORM_DRIVER - platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); -#endif -#ifdef OF_PLATFORM_DRIVER - platform_driver_unregister(&OF_PLATFORM_DRIVER); -#endif -#ifdef PLATFORM_DRIVER - platform_driver_unregister(&PLATFORM_DRIVER); -#endif -#ifdef PS3_SYSTEM_BUS_DRIVER - ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); -#endif -#ifdef DEBUG - debugfs_remove(ehci_debug_root); -#endif - clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); -} -module_exit(ehci_hcd_cleanup); diff --git a/addons/ehci-pci/src/3.10.108/ehci-hub.c b/addons/ehci-pci/src/3.10.108/ehci-hub.c deleted file mode 100644 index ca6289b4..00000000 --- a/addons/ehci-pci/src/3.10.108/ehci-hub.c +++ /dev/null @@ -1,1139 +0,0 @@ -/* - * Copyright (C) 2001-2004 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Root Hub ... the nonsharable stuff - * - * Registers don't need cpu_to_le32, that happens transparently - */ - -/*-------------------------------------------------------------------------*/ -#include - -#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) - -#ifdef CONFIG_PM - -static int ehci_hub_control( - struct usb_hcd *hcd, - u16 typeReq, - u16 wValue, - u16 wIndex, - char *buf, - u16 wLength -); - -/* After a power loss, ports that were owned by the companion must be - * reset so that the companion can still own them. - */ -static void ehci_handover_companion_ports(struct ehci_hcd *ehci) -{ - u32 __iomem *reg; - u32 status; - int port; - __le32 buf; - struct usb_hcd *hcd = ehci_to_hcd(ehci); - - if (!ehci->owned_ports) - return; - - /* Make sure the ports are powered */ - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - if (test_bit(port, &ehci->owned_ports)) { - reg = &ehci->regs->port_status[port]; - status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; - if (!(status & PORT_POWER)) { - status |= PORT_POWER; - ehci_writel(ehci, status, reg); - } - } - } - - /* Give the connections some time to appear */ - msleep(20); - - spin_lock_irq(&ehci->lock); - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - if (test_bit(port, &ehci->owned_ports)) { - reg = &ehci->regs->port_status[port]; - status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; - - /* Port already owned by companion? */ - if (status & PORT_OWNER) - clear_bit(port, &ehci->owned_ports); - else if (test_bit(port, &ehci->companion_ports)) - ehci_writel(ehci, status & ~PORT_PE, reg); - else { - spin_unlock_irq(&ehci->lock); - ehci_hub_control(hcd, SetPortFeature, - USB_PORT_FEAT_RESET, port + 1, - NULL, 0); - spin_lock_irq(&ehci->lock); - } - } - } - spin_unlock_irq(&ehci->lock); - - if (!ehci->owned_ports) - return; - msleep(90); /* Wait for resets to complete */ - - spin_lock_irq(&ehci->lock); - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - if (test_bit(port, &ehci->owned_ports)) { - spin_unlock_irq(&ehci->lock); - ehci_hub_control(hcd, GetPortStatus, - 0, port + 1, - (char *) &buf, sizeof(buf)); - spin_lock_irq(&ehci->lock); - - /* The companion should now own the port, - * but if something went wrong the port must not - * remain enabled. - */ - reg = &ehci->regs->port_status[port]; - status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; - if (status & PORT_OWNER) - ehci_writel(ehci, status | PORT_CSC, reg); - else { - ehci_dbg(ehci, "failed handover port %d: %x\n", - port + 1, status); - ehci_writel(ehci, status & ~PORT_PE, reg); - } - } - } - - ehci->owned_ports = 0; - spin_unlock_irq(&ehci->lock); -} - -static int ehci_port_change(struct ehci_hcd *ehci) -{ - int i = HCS_N_PORTS(ehci->hcs_params); - - /* First check if the controller indicates a change event */ - - if (ehci_readl(ehci, &ehci->regs->status) & STS_PCD) - return 1; - - /* - * Not all controllers appear to update this while going from D3 to D0, - * so check the individual port status registers as well - */ - - while (i--) - if (ehci_readl(ehci, &ehci->regs->port_status[i]) & PORT_CSC) - return 1; - - return 0; -} - -static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, - bool suspending, bool do_wakeup) -{ - int port; - u32 temp; - - /* If remote wakeup is enabled for the root hub but disabled - * for the controller, we must adjust all the port wakeup flags - * when the controller is suspended or resumed. In all other - * cases they don't need to be changed. - */ - if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup) - return; - - spin_lock_irq(&ehci->lock); - - /* clear phy low-power mode before changing wakeup flags */ - if (ehci->has_hostpc) { - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; - - temp = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg); - } - spin_unlock_irq(&ehci->lock); - msleep(5); - spin_lock_irq(&ehci->lock); - } - - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - u32 __iomem *reg = &ehci->regs->port_status[port]; - u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; - u32 t2 = t1 & ~PORT_WAKE_BITS; - - /* If we are suspending the controller, clear the flags. - * If we are resuming the controller, set the wakeup flags. - */ - if (!suspending) { - if (t1 & PORT_CONNECT) - t2 |= PORT_WKOC_E | PORT_WKDISC_E; - else - t2 |= PORT_WKOC_E | PORT_WKCONN_E; - } - ehci_vdbg(ehci, "port %d, %08x -> %08x\n", - port + 1, t1, t2); - ehci_writel(ehci, t2, reg); - } - - /* enter phy low-power mode again */ - if (ehci->has_hostpc) { - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; - - temp = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); - } - } - - /* Does the root hub have a port wakeup pending? */ - if (!suspending && ehci_port_change(ehci)) - usb_hcd_resume_root_hub(ehci_to_hcd(ehci)); - - spin_unlock_irq(&ehci->lock); -} - -static int ehci_bus_suspend (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - int port; - int mask; - int changed; - - ehci_dbg(ehci, "suspend root hub\n"); - - if (time_before (jiffies, ehci->next_statechange)) - msleep(5); - - /* stop the schedules */ - ehci_quiesce(ehci); - - spin_lock_irq (&ehci->lock); - if (ehci->rh_state < EHCI_RH_RUNNING) - goto done; - - /* Once the controller is stopped, port resumes that are already - * in progress won't complete. Hence if remote wakeup is enabled - * for the root hub and any ports are in the middle of a resume or - * remote wakeup, we must fail the suspend. - */ - if (hcd->self.root_hub->do_remote_wakeup) { - if (ehci->resuming_ports) { - spin_unlock_irq(&ehci->lock); - ehci_dbg(ehci, "suspend failed because a port is resuming\n"); - return -EBUSY; - } - } - - /* Unlike other USB host controller types, EHCI doesn't have - * any notion of "global" or bus-wide suspend. The driver has - * to manually suspend all the active unsuspended ports, and - * then manually resume them in the bus_resume() routine. - */ - ehci->bus_suspended = 0; - ehci->owned_ports = 0; - changed = 0; - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - u32 __iomem *reg = &ehci->regs->port_status [port]; - u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; - u32 t2 = t1 & ~PORT_WAKE_BITS; - - /* keep track of which ports we suspend */ - if (t1 & PORT_OWNER) - set_bit(port, &ehci->owned_ports); - else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) { - t2 |= PORT_SUSPEND; - set_bit(port, &ehci->bus_suspended); - } - - /* enable remote wakeup on all ports, if told to do so */ - if (hcd->self.root_hub->do_remote_wakeup) { - /* only enable appropriate wake bits, otherwise the - * hardware can not go phy low power mode. If a race - * condition happens here(connection change during bits - * set), the port change detection will finally fix it. - */ - if (t1 & PORT_CONNECT) - t2 |= PORT_WKOC_E | PORT_WKDISC_E; - else - t2 |= PORT_WKOC_E | PORT_WKCONN_E; - } - - if (t1 != t2) { - ehci_vdbg (ehci, "port %d, %08x -> %08x\n", - port + 1, t1, t2); - ehci_writel(ehci, t2, reg); - changed = 1; - } - } - - if (changed && ehci->has_hostpc) { - spin_unlock_irq(&ehci->lock); - msleep(5); /* 5 ms for HCD to enter low-power mode */ - spin_lock_irq(&ehci->lock); - - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; - u32 t3; - - t3 = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg); - t3 = ehci_readl(ehci, hostpc_reg); - ehci_dbg(ehci, "Port %d phy low-power mode %s\n", - port, (t3 & HOSTPC_PHCD) ? - "succeeded" : "failed"); - } - } - spin_unlock_irq(&ehci->lock); - - /* Apparently some devices need a >= 1-uframe delay here */ - if (ehci->bus_suspended) - udelay(150); - - /* turn off now-idle HC */ - ehci_halt (ehci); - - spin_lock_irq(&ehci->lock); - if (ehci->enabled_hrtimer_events & BIT(EHCI_HRTIMER_POLL_DEAD)) - ehci_handle_controller_death(ehci); - if (ehci->rh_state != EHCI_RH_RUNNING) - goto done; - ehci->rh_state = EHCI_RH_SUSPENDED; - - end_unlink_async(ehci); - unlink_empty_async_suspended(ehci); - ehci_handle_intr_unlinks(ehci); - end_free_itds(ehci); - - /* allow remote wakeup */ - mask = INTR_MASK; - if (!hcd->self.root_hub->do_remote_wakeup) - mask &= ~STS_PCD; - ehci_writel(ehci, mask, &ehci->regs->intr_enable); - ehci_readl(ehci, &ehci->regs->intr_enable); - - done: - ehci->next_statechange = jiffies + msecs_to_jiffies(10); - ehci->enabled_hrtimer_events = 0; - ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT; - spin_unlock_irq (&ehci->lock); - - hrtimer_cancel(&ehci->hrtimer); - return 0; -} - - -/* caller has locked the root hub, and should reset/reinit on error */ -static int ehci_bus_resume (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 temp; - u32 power_okay; - int i; - unsigned long resume_needed = 0; - - if (time_before (jiffies, ehci->next_statechange)) - msleep(5); - spin_lock_irq (&ehci->lock); - if (!HCD_HW_ACCESSIBLE(hcd) || ehci->shutdown) - goto shutdown; - - if (unlikely(ehci->debug)) { - if (!dbgp_reset_prep(hcd)) - ehci->debug = NULL; - else - dbgp_external_startup(hcd); - } - - /* Ideally and we've got a real resume here, and no port's power - * was lost. (For PCI, that means Vaux was maintained.) But we - * could instead be restoring a swsusp snapshot -- so that BIOS was - * the last user of the controller, not reset/pm hardware keeping - * state we gave to it. - */ - power_okay = ehci_readl(ehci, &ehci->regs->intr_enable); - ehci_dbg(ehci, "resume root hub%s\n", - power_okay ? "" : " after power loss"); - - /* at least some APM implementations will try to deliver - * IRQs right away, so delay them until we're ready. - */ - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - - /* re-init operational registers */ - ehci_writel(ehci, 0, &ehci->regs->segment); - ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); - ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next); - - /* restore CMD_RUN, framelist size, and irq threshold */ - ehci->command |= CMD_RUN; - ehci_writel(ehci, ehci->command, &ehci->regs->command); - ehci->rh_state = EHCI_RH_RUNNING; - - /* - * According to Bugzilla #8190, the port status for some controllers - * will be wrong without a delay. At their wrong status, the port - * is enabled, but not suspended neither resumed. - */ - i = HCS_N_PORTS(ehci->hcs_params); - while (i--) { - temp = ehci_readl(ehci, &ehci->regs->port_status[i]); - if ((temp & PORT_PE) && - !(temp & (PORT_SUSPEND | PORT_RESUME))) { - ehci_dbg(ehci, "Port status(0x%x) is wrong\n", temp); - spin_unlock_irq(&ehci->lock); - msleep(8); - spin_lock_irq(&ehci->lock); - break; - } - } - - if (ehci->shutdown) - goto shutdown; - - /* clear phy low-power mode before resume */ - if (ehci->bus_suspended && ehci->has_hostpc) { - i = HCS_N_PORTS(ehci->hcs_params); - while (i--) { - if (test_bit(i, &ehci->bus_suspended)) { - u32 __iomem *hostpc_reg = - &ehci->regs->hostpc[i]; - - temp = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp & ~HOSTPC_PHCD, - hostpc_reg); - } - } - spin_unlock_irq(&ehci->lock); - msleep(5); - spin_lock_irq(&ehci->lock); - if (ehci->shutdown) - goto shutdown; - } - - /* manually resume the ports we suspended during bus_suspend() */ - i = HCS_N_PORTS (ehci->hcs_params); - while (i--) { - temp = ehci_readl(ehci, &ehci->regs->port_status [i]); - temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); - if (test_bit(i, &ehci->bus_suspended) && - (temp & PORT_SUSPEND)) { - temp |= PORT_RESUME; - set_bit(i, &resume_needed); - } - ehci_writel(ehci, temp, &ehci->regs->port_status [i]); - } - - /* msleep for 20ms only if code is trying to resume port */ - if (resume_needed) { - spin_unlock_irq(&ehci->lock); - msleep(20); - spin_lock_irq(&ehci->lock); - if (ehci->shutdown) - goto shutdown; - } - - i = HCS_N_PORTS (ehci->hcs_params); - while (i--) { - temp = ehci_readl(ehci, &ehci->regs->port_status [i]); - if (test_bit(i, &resume_needed)) { - temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME); - ehci_writel(ehci, temp, &ehci->regs->port_status [i]); - ehci_vdbg (ehci, "resumed port %d\n", i + 1); - } - } - - ehci->next_statechange = jiffies + msecs_to_jiffies(5); - spin_unlock_irq(&ehci->lock); - - ehci_handover_companion_ports(ehci); - - /* Now we can safely re-enable irqs */ - spin_lock_irq(&ehci->lock); - if (ehci->shutdown) - goto shutdown; - ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); - (void) ehci_readl(ehci, &ehci->regs->intr_enable); - spin_unlock_irq(&ehci->lock); - - return 0; - - shutdown: - spin_unlock_irq(&ehci->lock); - return -ESHUTDOWN; -} - -#else - -#define ehci_bus_suspend NULL -#define ehci_bus_resume NULL - -#endif /* CONFIG_PM */ - -/*-------------------------------------------------------------------------*/ - -/* - * Sets the owner of a port - */ -static void set_owner(struct ehci_hcd *ehci, int portnum, int new_owner) -{ - u32 __iomem *status_reg; - u32 port_status; - int try; - - status_reg = &ehci->regs->port_status[portnum]; - - /* - * The controller won't set the OWNER bit if the port is - * enabled, so this loop will sometimes require at least two - * iterations: one to disable the port and one to set OWNER. - */ - for (try = 4; try > 0; --try) { - spin_lock_irq(&ehci->lock); - port_status = ehci_readl(ehci, status_reg); - if ((port_status & PORT_OWNER) == new_owner - || (port_status & (PORT_OWNER | PORT_CONNECT)) - == 0) - try = 0; - else { - port_status ^= PORT_OWNER; - port_status &= ~(PORT_PE | PORT_RWC_BITS); - ehci_writel(ehci, port_status, status_reg); - } - spin_unlock_irq(&ehci->lock); - if (try > 1) - msleep(5); - } -} - -/*-------------------------------------------------------------------------*/ - -static int check_reset_complete ( - struct ehci_hcd *ehci, - int index, - u32 __iomem *status_reg, - int port_status -) { - if (!(port_status & PORT_CONNECT)) - return port_status; - - /* if reset finished and it's still not enabled -- handoff */ - if (!(port_status & PORT_PE)) { - - /* with integrated TT, there's nobody to hand it to! */ - if (ehci_is_TDI(ehci)) { - ehci_dbg (ehci, - "Failed to enable port %d on root hub TT\n", - index+1); - return port_status; - } - - ehci_dbg (ehci, "port %d full speed --> companion\n", - index + 1); - - // what happens if HCS_N_CC(params) == 0 ? - port_status |= PORT_OWNER; - port_status &= ~PORT_RWC_BITS; - ehci_writel(ehci, port_status, status_reg); - - /* ensure 440EPX ohci controller state is operational */ - if (ehci->has_amcc_usb23) - set_ohci_hcfs(ehci, 1); - } else { - ehci_dbg(ehci, "port %d reset complete, port enabled\n", - index + 1); - /* ensure 440EPx ohci controller state is suspended */ - if (ehci->has_amcc_usb23) - set_ohci_hcfs(ehci, 0); - } - - return port_status; -} - -/*-------------------------------------------------------------------------*/ - - -/* build "status change" packet (one or two bytes) from HC registers */ - -static int -ehci_hub_status_data (struct usb_hcd *hcd, char *buf) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 temp, status; - u32 mask; - int ports, i, retval = 1; - unsigned long flags; - u32 ppcd = ~0; - - /* init status to no-changes */ - buf [0] = 0; - ports = HCS_N_PORTS (ehci->hcs_params); - if (ports > 7) { - buf [1] = 0; - retval++; - } - - /* Inform the core about resumes-in-progress by returning - * a non-zero value even if there are no status changes. - */ - status = ehci->resuming_ports; - - /* Some boards (mostly VIA?) report bogus overcurrent indications, - * causing massive log spam unless we completely ignore them. It - * may be relevant that VIA VT8235 controllers, where PORT_POWER is - * always set, seem to clear PORT_OCC and PORT_CSC when writing to - * PORT_POWER; that's surprising, but maybe within-spec. - */ - if (!ignore_oc) - mask = PORT_CSC | PORT_PEC | PORT_OCC; - else - mask = PORT_CSC | PORT_PEC; - // PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND - - /* no hub change reports (bit 0) for now (power, ...) */ - - /* port N changes (bit N)? */ - spin_lock_irqsave (&ehci->lock, flags); - - /* get per-port change detect bits */ - if (ehci->has_ppcd) - ppcd = ehci_readl(ehci, &ehci->regs->status) >> 16; - - for (i = 0; i < ports; i++) { - /* leverage per-port change bits feature */ - if (ppcd & (1 << i)) - temp = ehci_readl(ehci, &ehci->regs->port_status[i]); - else - temp = 0; - - /* - * Return status information even for ports with OWNER set. - * Otherwise khubd wouldn't see the disconnect event when a - * high-speed device is switched over to the companion - * controller by the user. - */ - - if ((temp & mask) != 0 || test_bit(i, &ehci->port_c_suspend) - || (ehci->reset_done[i] && time_after_eq( - jiffies, ehci->reset_done[i]))) { - if (i < 7) - buf [0] |= 1 << (i + 1); - else - buf [1] |= 1 << (i - 7); - status = STS_PCD; - } - } - - /* If a resume is in progress, make sure it can finish */ - if (ehci->resuming_ports) - mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25)); - - spin_unlock_irqrestore (&ehci->lock, flags); - return status ? retval : 0; -} - -/*-------------------------------------------------------------------------*/ - -static void -ehci_hub_descriptor ( - struct ehci_hcd *ehci, - struct usb_hub_descriptor *desc -) { - int ports = HCS_N_PORTS (ehci->hcs_params); - u16 temp; - - desc->bDescriptorType = 0x29; - desc->bPwrOn2PwrGood = 10; /* ehci 1.0, 2.3.9 says 20ms max */ - desc->bHubContrCurrent = 0; - - desc->bNbrPorts = ports; - temp = 1 + (ports / 8); - desc->bDescLength = 7 + 2 * temp; - - /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ - memset(&desc->u.hs.DeviceRemovable[0], 0, temp); - memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); - - temp = 0x0008; /* per-port overcurrent reporting */ - if (HCS_PPC (ehci->hcs_params)) - temp |= 0x0001; /* per-port power control */ - else - temp |= 0x0002; /* no power switching */ -#if 0 -// re-enable when we support USB_PORT_FEAT_INDICATOR below. - if (HCS_INDICATOR (ehci->hcs_params)) - temp |= 0x0080; /* per-port indicators (LEDs) */ -#endif - desc->wHubCharacteristics = cpu_to_le16(temp); -} - -/*-------------------------------------------------------------------------*/ - -static int ehci_hub_control ( - struct usb_hcd *hcd, - u16 typeReq, - u16 wValue, - u16 wIndex, - char *buf, - u16 wLength -) { - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - int ports = HCS_N_PORTS (ehci->hcs_params); - u32 __iomem *status_reg = &ehci->regs->port_status[ - (wIndex & 0xff) - 1]; - u32 __iomem *hostpc_reg = &ehci->regs->hostpc[(wIndex & 0xff) - 1]; - u32 temp, temp1, status; - unsigned long flags; - int retval = 0; - unsigned selector; - - /* - * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. - * HCS_INDICATOR may say we can change LEDs to off/amber/green. - * (track current state ourselves) ... blink for diagnostics, - * power, "this is the one", etc. EHCI spec supports this. - */ - - spin_lock_irqsave (&ehci->lock, flags); - switch (typeReq) { - case ClearHubFeature: - switch (wValue) { - case C_HUB_LOCAL_POWER: - case C_HUB_OVER_CURRENT: - /* no hub-wide feature/status flags */ - break; - default: - goto error; - } - break; - case ClearPortFeature: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - temp = ehci_readl(ehci, status_reg); - temp &= ~PORT_RWC_BITS; - - /* - * Even if OWNER is set, so the port is owned by the - * companion controller, khubd needs to be able to clear - * the port-change status bits (especially - * USB_PORT_STAT_C_CONNECTION). - */ - - switch (wValue) { - case USB_PORT_FEAT_ENABLE: - ehci_writel(ehci, temp & ~PORT_PE, status_reg); - break; - case USB_PORT_FEAT_C_ENABLE: - ehci_writel(ehci, temp | PORT_PEC, status_reg); - break; - case USB_PORT_FEAT_SUSPEND: - if (temp & PORT_RESET) - goto error; - if (ehci->no_selective_suspend) - break; -#ifdef CONFIG_USB_OTG - if ((hcd->self.otg_port == (wIndex + 1)) - && hcd->self.b_hnp_enable) { - otg_start_hnp(hcd->phy->otg); - break; - } -#endif - if (!(temp & PORT_SUSPEND)) - break; - if ((temp & PORT_PE) == 0) - goto error; - - /* clear phy low-power mode before resume */ - if (ehci->has_hostpc) { - temp1 = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp1 & ~HOSTPC_PHCD, - hostpc_reg); - spin_unlock_irqrestore(&ehci->lock, flags); - msleep(5);/* wait to leave low-power mode */ - spin_lock_irqsave(&ehci->lock, flags); - } - /* resume signaling for 20 msec */ - temp &= ~PORT_WAKE_BITS; - ehci_writel(ehci, temp | PORT_RESUME, status_reg); - ehci->reset_done[wIndex] = jiffies - + msecs_to_jiffies(20); - break; - case USB_PORT_FEAT_C_SUSPEND: - clear_bit(wIndex, &ehci->port_c_suspend); - break; - case USB_PORT_FEAT_POWER: - if (HCS_PPC (ehci->hcs_params)) - ehci_writel(ehci, temp & ~PORT_POWER, - status_reg); - break; - case USB_PORT_FEAT_C_CONNECTION: - ehci_writel(ehci, temp | PORT_CSC, status_reg); - break; - case USB_PORT_FEAT_C_OVER_CURRENT: - ehci_writel(ehci, temp | PORT_OCC, status_reg); - break; - case USB_PORT_FEAT_C_RESET: - /* GetPortStatus clears reset */ - break; - default: - goto error; - } - ehci_readl(ehci, &ehci->regs->command); /* unblock posted write */ - break; - case GetHubDescriptor: - ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *) - buf); - break; - case GetHubStatus: - /* no hub-wide feature/status flags */ - memset (buf, 0, 4); - //cpu_to_le32s ((u32 *) buf); - break; - case GetPortStatus: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - status = 0; - temp = ehci_readl(ehci, status_reg); - - // wPortChange bits - if (temp & PORT_CSC) - status |= USB_PORT_STAT_C_CONNECTION << 16; - if (temp & PORT_PEC) - status |= USB_PORT_STAT_C_ENABLE << 16; - - if ((temp & PORT_OCC) && !ignore_oc){ - status |= USB_PORT_STAT_C_OVERCURRENT << 16; - - /* - * Hubs should disable port power on over-current. - * However, not all EHCI implementations do this - * automatically, even if they _do_ support per-port - * power switching; they're allowed to just limit the - * current. khubd will turn the power back on. - */ - if (((temp & PORT_OC) || (ehci->need_oc_pp_cycle)) - && HCS_PPC(ehci->hcs_params)) { - ehci_writel(ehci, - temp & ~(PORT_RWC_BITS | PORT_POWER), - status_reg); - temp = ehci_readl(ehci, status_reg); - } - } - - /* whoever resumes must GetPortStatus to complete it!! */ - if (temp & PORT_RESUME) { - - /* Remote Wakeup received? */ - if (!ehci->reset_done[wIndex]) { - /* resume signaling for 20 msec */ - ehci->reset_done[wIndex] = jiffies - + msecs_to_jiffies(20); - usb_hcd_start_port_resume(&hcd->self, wIndex); - set_bit(wIndex, &ehci->resuming_ports); - /* check the port again */ - mod_timer(&ehci_to_hcd(ehci)->rh_timer, - ehci->reset_done[wIndex]); - } - - /* resume completed? */ - else if (time_after_eq(jiffies, - ehci->reset_done[wIndex])) { - clear_bit(wIndex, &ehci->suspended_ports); - set_bit(wIndex, &ehci->port_c_suspend); - ehci->reset_done[wIndex] = 0; - usb_hcd_end_port_resume(&hcd->self, wIndex); - - /* stop resume signaling */ - temp &= ~(PORT_RWC_BITS | - PORT_SUSPEND | PORT_RESUME); - ehci_writel(ehci, temp, status_reg); - clear_bit(wIndex, &ehci->resuming_ports); - retval = handshake(ehci, status_reg, - PORT_RESUME, 0, 2000 /* 2msec */); - if (retval != 0) { - ehci_err(ehci, - "port %d resume error %d\n", - wIndex + 1, retval); - goto error; - } - temp = ehci_readl(ehci, status_reg); - } - } - - /* whoever resets must GetPortStatus to complete it!! */ - if ((temp & PORT_RESET) - && time_after_eq(jiffies, - ehci->reset_done[wIndex])) { - status |= USB_PORT_STAT_C_RESET << 16; - ehci->reset_done [wIndex] = 0; - clear_bit(wIndex, &ehci->resuming_ports); - - /* force reset to complete */ - ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET), - status_reg); - /* REVISIT: some hardware needs 550+ usec to clear - * this bit; seems too long to spin routinely... - */ - retval = handshake(ehci, status_reg, - PORT_RESET, 0, 1000); - if (retval != 0) { - ehci_err (ehci, "port %d reset error %d\n", - wIndex + 1, retval); - goto error; - } - - /* see what we found out */ - temp = check_reset_complete (ehci, wIndex, status_reg, - ehci_readl(ehci, status_reg)); - } - - if (!(temp & (PORT_RESUME|PORT_RESET))) { - ehci->reset_done[wIndex] = 0; - clear_bit(wIndex, &ehci->resuming_ports); - } - - /* transfer dedicated ports to the companion hc */ - if ((temp & PORT_CONNECT) && - test_bit(wIndex, &ehci->companion_ports)) { - temp &= ~PORT_RWC_BITS; - temp |= PORT_OWNER; - ehci_writel(ehci, temp, status_reg); - ehci_dbg(ehci, "port %d --> companion\n", wIndex + 1); - temp = ehci_readl(ehci, status_reg); - } - - /* - * Even if OWNER is set, there's no harm letting khubd - * see the wPortStatus values (they should all be 0 except - * for PORT_POWER anyway). - */ - - if (temp & PORT_CONNECT) { - status |= USB_PORT_STAT_CONNECTION; - // status may be from integrated TT - if (ehci->has_hostpc) { - temp1 = ehci_readl(ehci, hostpc_reg); - status |= ehci_port_speed(ehci, temp1); - } else - status |= ehci_port_speed(ehci, temp); - } - if (temp & PORT_PE) - status |= USB_PORT_STAT_ENABLE; - - /* maybe the port was unsuspended without our knowledge */ - if (temp & (PORT_SUSPEND|PORT_RESUME)) { - status |= USB_PORT_STAT_SUSPEND; - } else if (test_bit(wIndex, &ehci->suspended_ports)) { - clear_bit(wIndex, &ehci->suspended_ports); - clear_bit(wIndex, &ehci->resuming_ports); - ehci->reset_done[wIndex] = 0; - if (temp & PORT_PE) - set_bit(wIndex, &ehci->port_c_suspend); - usb_hcd_end_port_resume(&hcd->self, wIndex); - } - - if (temp & PORT_OC) - status |= USB_PORT_STAT_OVERCURRENT; - if (temp & PORT_RESET) - status |= USB_PORT_STAT_RESET; - if (temp & PORT_POWER) - status |= USB_PORT_STAT_POWER; - if (test_bit(wIndex, &ehci->port_c_suspend)) - status |= USB_PORT_STAT_C_SUSPEND << 16; - -#ifndef VERBOSE_DEBUG - if (status & ~0xffff) /* only if wPortChange is interesting */ -#endif - dbg_port (ehci, "GetStatus", wIndex + 1, temp); - put_unaligned_le32(status, buf); - break; - case SetHubFeature: - switch (wValue) { - case C_HUB_LOCAL_POWER: - case C_HUB_OVER_CURRENT: - /* no hub-wide feature/status flags */ - break; - default: - goto error; - } - break; - case SetPortFeature: - selector = wIndex >> 8; - wIndex &= 0xff; - if (unlikely(ehci->debug)) { - /* If the debug port is active any port - * feature requests should get denied */ - if (wIndex == HCS_DEBUG_PORT(ehci->hcs_params) && - (readl(&ehci->debug->control) & DBGP_ENABLED)) { - retval = -ENODEV; - goto error_exit; - } - } - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - temp = ehci_readl(ehci, status_reg); - if (temp & PORT_OWNER) - break; - - temp &= ~PORT_RWC_BITS; - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - if (ehci->no_selective_suspend) - break; - if ((temp & PORT_PE) == 0 - || (temp & PORT_RESET) != 0) - goto error; - - /* After above check the port must be connected. - * Set appropriate bit thus could put phy into low power - * mode if we have hostpc feature - */ - temp &= ~PORT_WKCONN_E; - temp |= PORT_WKDISC_E | PORT_WKOC_E; - ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); - if (ehci->has_hostpc) { - spin_unlock_irqrestore(&ehci->lock, flags); - msleep(5);/* 5ms for HCD enter low pwr mode */ - spin_lock_irqsave(&ehci->lock, flags); - temp1 = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp1 | HOSTPC_PHCD, - hostpc_reg); - temp1 = ehci_readl(ehci, hostpc_reg); - ehci_dbg(ehci, "Port%d phy low pwr mode %s\n", - wIndex, (temp1 & HOSTPC_PHCD) ? - "succeeded" : "failed"); - } - set_bit(wIndex, &ehci->suspended_ports); - break; - case USB_PORT_FEAT_POWER: - if (HCS_PPC (ehci->hcs_params)) - ehci_writel(ehci, temp | PORT_POWER, - status_reg); - break; - case USB_PORT_FEAT_RESET: - if (temp & PORT_RESUME) - goto error; - /* line status bits may report this as low speed, - * which can be fine if this root hub has a - * transaction translator built in. - */ - if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT - && !ehci_is_TDI(ehci) - && PORT_USB11 (temp)) { - ehci_dbg (ehci, - "port %d low speed --> companion\n", - wIndex + 1); - temp |= PORT_OWNER; - } else { - ehci_vdbg (ehci, "port %d reset\n", wIndex + 1); - temp |= PORT_RESET; - temp &= ~PORT_PE; - - /* - * caller must wait, then call GetPortStatus - * usb 2.0 spec says 50 ms resets on root - */ - ehci->reset_done [wIndex] = jiffies - + msecs_to_jiffies (50); - } - ehci_writel(ehci, temp, status_reg); - break; - - /* For downstream facing ports (these): one hub port is put - * into test mode according to USB2 11.24.2.13, then the hub - * must be reset (which for root hub now means rmmod+modprobe, - * or else system reboot). See EHCI 2.3.9 and 4.14 for info - * about the EHCI-specific stuff. - */ - case USB_PORT_FEAT_TEST: - if (!selector || selector > 5) - goto error; - spin_unlock_irqrestore(&ehci->lock, flags); - ehci_quiesce(ehci); - spin_lock_irqsave(&ehci->lock, flags); - - /* Put all enabled ports into suspend */ - while (ports--) { - u32 __iomem *sreg = - &ehci->regs->port_status[ports]; - - temp = ehci_readl(ehci, sreg) & ~PORT_RWC_BITS; - if (temp & PORT_PE) - ehci_writel(ehci, temp | PORT_SUSPEND, - sreg); - } - - spin_unlock_irqrestore(&ehci->lock, flags); - ehci_halt(ehci); - spin_lock_irqsave(&ehci->lock, flags); - - temp = ehci_readl(ehci, status_reg); - temp |= selector << 16; - ehci_writel(ehci, temp, status_reg); - break; - - default: - goto error; - } - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ - break; - - default: -error: - /* "stall" on error */ - retval = -EPIPE; - } -error_exit: - spin_unlock_irqrestore (&ehci->lock, flags); - return retval; -} - -static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - if (ehci_is_TDI(ehci)) - return; - set_owner(ehci, --portnum, PORT_OWNER); -} - -static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - u32 __iomem *reg; - - if (ehci_is_TDI(ehci)) - return 0; - reg = &ehci->regs->port_status[portnum - 1]; - return ehci_readl(ehci, reg) & PORT_OWNER; -} diff --git a/addons/ehci-pci/src/3.10.108/ehci-mem.c b/addons/ehci-pci/src/3.10.108/ehci-mem.c deleted file mode 100644 index ef2c3a1e..00000000 --- a/addons/ehci-pci/src/3.10.108/ehci-mem.c +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2001 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* - * There's basically three types of memory: - * - data used only by the HCD ... kmalloc is fine - * - async and periodic schedules, shared by HC and HCD ... these - * need to use dma_pool or dma_alloc_coherent - * - driver buffers, read/written by HC ... single shot DMA mapped - * - * There's also "register" data (e.g. PCI or SOC), which is memory mapped. - * No memory seen by this driver is pageable. - */ - -/*-------------------------------------------------------------------------*/ - -/* Allocate the key transfer structures from the previously allocated pool */ - -static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd, - dma_addr_t dma) -{ - memset (qtd, 0, sizeof *qtd); - qtd->qtd_dma = dma; - qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); - qtd->hw_next = EHCI_LIST_END(ehci); - qtd->hw_alt_next = EHCI_LIST_END(ehci); - INIT_LIST_HEAD (&qtd->qtd_list); -} - -static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags) -{ - struct ehci_qtd *qtd; - dma_addr_t dma; - - qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma); - if (qtd != NULL) { - ehci_qtd_init(ehci, qtd, dma); - } - return qtd; -} - -static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd) -{ - dma_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma); -} - - -static void qh_destroy(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - /* clean qtds first, and know this is not linked */ - if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) { - ehci_dbg (ehci, "unused qh not empty!\n"); - BUG (); - } - if (qh->dummy) - ehci_qtd_free (ehci, qh->dummy); - dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma); - kfree(qh); -} - -static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) -{ - struct ehci_qh *qh; - dma_addr_t dma; - - qh = kzalloc(sizeof *qh, GFP_ATOMIC); - if (!qh) - goto done; - qh->hw = (struct ehci_qh_hw *) - dma_pool_alloc(ehci->qh_pool, flags, &dma); - if (!qh->hw) - goto fail; - memset(qh->hw, 0, sizeof *qh->hw); - qh->qh_dma = dma; - // INIT_LIST_HEAD (&qh->qh_list); - INIT_LIST_HEAD (&qh->qtd_list); - - /* dummy td enables safe urb queuing */ - qh->dummy = ehci_qtd_alloc (ehci, flags); - if (qh->dummy == NULL) { - ehci_dbg (ehci, "no dummy td\n"); - goto fail1; - } -done: - return qh; -fail1: - dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma); -fail: - kfree(qh); - return NULL; -} - -/*-------------------------------------------------------------------------*/ - -/* The queue heads and transfer descriptors are managed from pools tied - * to each of the "per device" structures. - * This is the initialisation and cleanup code. - */ - -static void ehci_mem_cleanup (struct ehci_hcd *ehci) -{ - if (ehci->async) - qh_destroy(ehci, ehci->async); - ehci->async = NULL; - - if (ehci->dummy) - qh_destroy(ehci, ehci->dummy); - ehci->dummy = NULL; - - /* DMA consistent memory and pools */ - if (ehci->qtd_pool) - dma_pool_destroy (ehci->qtd_pool); - ehci->qtd_pool = NULL; - - if (ehci->qh_pool) { - dma_pool_destroy (ehci->qh_pool); - ehci->qh_pool = NULL; - } - - if (ehci->itd_pool) - dma_pool_destroy (ehci->itd_pool); - ehci->itd_pool = NULL; - - if (ehci->sitd_pool) - dma_pool_destroy (ehci->sitd_pool); - ehci->sitd_pool = NULL; - - if (ehci->periodic) - dma_free_coherent (ehci_to_hcd(ehci)->self.controller, - ehci->periodic_size * sizeof (u32), - ehci->periodic, ehci->periodic_dma); - ehci->periodic = NULL; - - /* shadow periodic table */ - kfree(ehci->pshadow); - ehci->pshadow = NULL; -} - -/* remember to add cleanup code (above) if you add anything here */ -static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) -{ - int i; - - /* QTDs for control/bulk/intr transfers */ - ehci->qtd_pool = dma_pool_create ("ehci_qtd", - ehci_to_hcd(ehci)->self.controller, - sizeof (struct ehci_qtd), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */); - if (!ehci->qtd_pool) { - goto fail; - } - - /* QHs for control/bulk/intr transfers */ - ehci->qh_pool = dma_pool_create ("ehci_qh", - ehci_to_hcd(ehci)->self.controller, - sizeof(struct ehci_qh_hw), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */); - if (!ehci->qh_pool) { - goto fail; - } - ehci->async = ehci_qh_alloc (ehci, flags); - if (!ehci->async) { - goto fail; - } - - /* ITD for high speed ISO transfers */ - ehci->itd_pool = dma_pool_create ("ehci_itd", - ehci_to_hcd(ehci)->self.controller, - sizeof (struct ehci_itd), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */); - if (!ehci->itd_pool) { - goto fail; - } - - /* SITD for full/low speed split ISO transfers */ - ehci->sitd_pool = dma_pool_create ("ehci_sitd", - ehci_to_hcd(ehci)->self.controller, - sizeof (struct ehci_sitd), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */); - if (!ehci->sitd_pool) { - goto fail; - } - - /* Hardware periodic table */ - ehci->periodic = (__le32 *) - dma_alloc_coherent (ehci_to_hcd(ehci)->self.controller, - ehci->periodic_size * sizeof(__le32), - &ehci->periodic_dma, 0); - if (ehci->periodic == NULL) { - goto fail; - } - - if (ehci->use_dummy_qh) { - struct ehci_qh_hw *hw; - ehci->dummy = ehci_qh_alloc(ehci, flags); - if (!ehci->dummy) - goto fail; - - hw = ehci->dummy->hw; - hw->hw_next = EHCI_LIST_END(ehci); - hw->hw_qtd_next = EHCI_LIST_END(ehci); - hw->hw_alt_next = EHCI_LIST_END(ehci); - hw->hw_token &= ~QTD_STS_ACTIVE; - ehci->dummy->hw = hw; - - for (i = 0; i < ehci->periodic_size; i++) - ehci->periodic[i] = ehci->dummy->qh_dma; - } else { - for (i = 0; i < ehci->periodic_size; i++) - ehci->periodic[i] = EHCI_LIST_END(ehci); - } - - /* software shadow of hardware table */ - ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags); - if (ehci->pshadow != NULL) - return 0; - -fail: - ehci_dbg (ehci, "couldn't init memory\n"); - ehci_mem_cleanup (ehci); - return -ENOMEM; -} diff --git a/addons/ehci-pci/src/3.10.108/ehci-pci.c b/addons/ehci-pci/src/3.10.108/ehci-pci.c deleted file mode 100644 index fe131565..00000000 --- a/addons/ehci-pci/src/3.10.108/ehci-pci.c +++ /dev/null @@ -1,464 +0,0 @@ -/* - * EHCI HCD (Host Controller Driver) PCI Bus Glue. - * - * Copyright (c) 2000-2004 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include - -#include "ehci.h" -#include "pci-quirks.h" - -#define DRIVER_DESC "EHCI PCI platform driver" - -static const char hcd_name[] = "ehci-pci"; - -/* defined here to avoid adding to pci_ids.h for single instance use */ -#define PCI_DEVICE_ID_INTEL_CE4100_USB 0x2e70 - -/*-------------------------------------------------------------------------*/ -#define PCI_DEVICE_ID_INTEL_QUARK_X1000_SOC 0x0939 -static inline bool is_intel_quark_x1000(struct pci_dev *pdev) -{ - return pdev->vendor == PCI_VENDOR_ID_INTEL && - pdev->device == PCI_DEVICE_ID_INTEL_QUARK_X1000_SOC; -} - -/* - * 0x84 is the offset of in/out threshold register, - * and it is the same offset as the register of 'hostpc'. - */ -#define intel_quark_x1000_insnreg01 hostpc - -/* Maximum usable threshold value is 0x7f dwords for both IN and OUT */ -#define INTEL_QUARK_X1000_EHCI_MAX_THRESHOLD 0x007f007f - -/* called after powerup, by probe or system-pm "wakeup" */ -static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) -{ - int retval; - - /* we expect static quirk code to handle the "extended capabilities" - * (currently just BIOS handoff) allowed starting with EHCI 0.96 - */ - - /* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */ - retval = pci_set_mwi(pdev); - if (!retval) - ehci_dbg(ehci, "MWI active\n"); - - /* Reset the threshold limit */ - if (is_intel_quark_x1000(pdev)) { - /* - * For the Intel QUARK X1000, raise the I/O threshold to the - * maximum usable value in order to improve performance. - */ - ehci_writel(ehci, INTEL_QUARK_X1000_EHCI_MAX_THRESHOLD, - ehci->regs->intel_quark_x1000_insnreg01); - } - - return 0; -} - -/* called during probe() after chip reset completes */ -static int ehci_pci_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - struct pci_dev *p_smbus; - u8 rev; - u32 temp; - int retval; - - ehci->caps = hcd->regs; - - /* - * ehci_init() causes memory for DMA transfers to be - * allocated. Thus, any vendor-specific workarounds based on - * limiting the type of memory used for DMA transfers must - * happen before ehci_setup() is called. - * - * Most other workarounds can be done either before or after - * init and reset; they are located here too. - */ - switch (pdev->vendor) { - case PCI_VENDOR_ID_TOSHIBA_2: - /* celleb's companion chip */ - if (pdev->device == 0x01b5) { -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO - ehci->big_endian_mmio = 1; -#else - ehci_warn(ehci, - "unsupported big endian Toshiba quirk\n"); -#endif - } - break; - case PCI_VENDOR_ID_NVIDIA: - /* NVidia reports that certain chips don't handle - * QH, ITD, or SITD addresses above 2GB. (But TD, - * data buffer, and periodic schedule are normal.) - */ - switch (pdev->device) { - case 0x003c: /* MCP04 */ - case 0x005b: /* CK804 */ - case 0x00d8: /* CK8 */ - case 0x00e8: /* CK8S */ - if (pci_set_consistent_dma_mask(pdev, - DMA_BIT_MASK(31)) < 0) - ehci_warn(ehci, "can't enable NVidia " - "workaround for >2GB RAM\n"); - break; - - /* Some NForce2 chips have problems with selective suspend; - * fixed in newer silicon. - */ - case 0x0068: - if (pdev->revision < 0xa4) - ehci->no_selective_suspend = 1; - break; - } - break; - case PCI_VENDOR_ID_INTEL: - if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) - hcd->has_tt = 1; - break; - case PCI_VENDOR_ID_TDI: - if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) - hcd->has_tt = 1; - break; - case PCI_VENDOR_ID_AMD: - /* AMD PLL quirk */ - if (usb_amd_find_chipset_info()) - ehci->amd_pll_fix = 1; - /* AMD8111 EHCI doesn't work, according to AMD errata */ - if (pdev->device == 0x7463) { - ehci_info(ehci, "ignoring AMD8111 (errata)\n"); - retval = -EIO; - goto done; - } - - /* - * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may - * read/write memory space which does not belong to it when - * there is NULL pointer with T-bit set to 1 in the frame list - * table. To avoid the issue, the frame list link pointer - * should always contain a valid pointer to a inactive qh. - */ - if (pdev->device == 0x7808) { - ehci->use_dummy_qh = 1; - ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n"); - } - break; - case PCI_VENDOR_ID_VIA: - if (pdev->device == 0x3104 && (pdev->revision & 0xf0) == 0x60) { - u8 tmp; - - /* The VT6212 defaults to a 1 usec EHCI sleep time which - * hogs the PCI bus *badly*. Setting bit 5 of 0x4B makes - * that sleep time use the conventional 10 usec. - */ - pci_read_config_byte(pdev, 0x4b, &tmp); - if (tmp & 0x20) - break; - pci_write_config_byte(pdev, 0x4b, tmp | 0x20); - } - break; - case PCI_VENDOR_ID_ATI: - /* AMD PLL quirk */ - if (usb_amd_find_chipset_info()) - ehci->amd_pll_fix = 1; - - /* - * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may - * read/write memory space which does not belong to it when - * there is NULL pointer with T-bit set to 1 in the frame list - * table. To avoid the issue, the frame list link pointer - * should always contain a valid pointer to a inactive qh. - */ - if (pdev->device == 0x4396) { - ehci->use_dummy_qh = 1; - ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n"); - } - /* SB600 and old version of SB700 have a bug in EHCI controller, - * which causes usb devices lose response in some cases. - */ - if ((pdev->device == 0x4386) || (pdev->device == 0x4396)) { - p_smbus = pci_get_device(PCI_VENDOR_ID_ATI, - PCI_DEVICE_ID_ATI_SBX00_SMBUS, - NULL); - if (!p_smbus) - break; - rev = p_smbus->revision; - if ((pdev->device == 0x4386) || (rev == 0x3a) - || (rev == 0x3b)) { - u8 tmp; - ehci_info(ehci, "applying AMD SB600/SB700 USB " - "freeze workaround\n"); - pci_read_config_byte(pdev, 0x53, &tmp); - pci_write_config_byte(pdev, 0x53, tmp | (1<<3)); - } - pci_dev_put(p_smbus); - } - break; - case PCI_VENDOR_ID_NETMOS: - /* MosChip frame-index-register bug */ - ehci_info(ehci, "applying MosChip frame-index workaround\n"); - ehci->frame_index_bug = 1; - break; - } - - /* optional debug port, normally in the first BAR */ - temp = pci_find_capability(pdev, PCI_CAP_ID_DBG); - if (temp) { - pci_read_config_dword(pdev, temp, &temp); - temp >>= 16; - if (((temp >> 13) & 7) == 1) { - u32 hcs_params = ehci_readl(ehci, - &ehci->caps->hcs_params); - - temp &= 0x1fff; - ehci->debug = hcd->regs + temp; - temp = ehci_readl(ehci, &ehci->debug->control); - ehci_info(ehci, "debug port %d%s\n", - HCS_DEBUG_PORT(hcs_params), - (temp & DBGP_ENABLED) ? " IN USE" : ""); - if (!(temp & DBGP_ENABLED)) - ehci->debug = NULL; - } - } - - retval = ehci_setup(hcd); - if (retval) - return retval; - - /* These workarounds need to be applied after ehci_setup() */ - switch (pdev->vendor) { - case PCI_VENDOR_ID_NEC: - ehci->need_io_watchdog = 0; - break; - case PCI_VENDOR_ID_INTEL: - ehci->need_io_watchdog = 0; - break; - case PCI_VENDOR_ID_NVIDIA: - switch (pdev->device) { - /* MCP89 chips on the MacBookAir3,1 give EPROTO when - * fetching device descriptors unless LPM is disabled. - * There are also intermittent problems enumerating - * devices with PPCD enabled. - */ - case 0x0d9d: - ehci_info(ehci, "disable ppcd for nvidia mcp89\n"); - ehci->has_ppcd = 0; - ehci->command &= ~CMD_PPCEE; - break; - } - break; - } - - /* at least the Genesys GL880S needs fixup here */ - temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); - temp &= 0x0f; - if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) { - ehci_dbg(ehci, "bogus port configuration: " - "cc=%d x pcc=%d < ports=%d\n", - HCS_N_CC(ehci->hcs_params), - HCS_N_PCC(ehci->hcs_params), - HCS_N_PORTS(ehci->hcs_params)); - - switch (pdev->vendor) { - case 0x17a0: /* GENESYS */ - /* GL880S: should be PORTS=2 */ - temp |= (ehci->hcs_params & ~0xf); - ehci->hcs_params = temp; - break; - case PCI_VENDOR_ID_NVIDIA: - /* NF4: should be PCC=10 */ - break; - } - } - - /* Serial Bus Release Number is at PCI 0x60 offset */ - if (pdev->vendor == PCI_VENDOR_ID_STMICRO - && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST) - ; /* ConneXT has no sbrn register */ - else - pci_read_config_byte(pdev, 0x60, &ehci->sbrn); - - /* Keep this around for a while just in case some EHCI - * implementation uses legacy PCI PM support. This test - * can be removed on 17 Dec 2009 if the dev_warn() hasn't - * been triggered by then. - */ - if (!device_can_wakeup(&pdev->dev)) { - u16 port_wake; - - pci_read_config_word(pdev, 0x62, &port_wake); - if (port_wake & 0x0001) { - dev_warn(&pdev->dev, "Enabling legacy PCI PM\n"); - device_set_wakeup_capable(&pdev->dev, 1); - } - } - -#ifdef CONFIG_PM_RUNTIME - if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev)) - ehci_warn(ehci, "selective suspend/wakeup unavailable\n"); -#endif - - retval = ehci_pci_reinit(ehci, pdev); -done: - return retval; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_PM - -/* suspend/resume, section 4.3 */ - -/* These routines rely on the PCI bus glue - * to handle powerdown and wakeup, and currently also on - * transceivers that don't need any software attention to set up - * the right sort of wakeup. - * Also they depend on separate root hub suspend/resume. - */ - -static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev) -{ - return pdev->class == PCI_CLASS_SERIAL_USB_EHCI && - pdev->vendor == PCI_VENDOR_ID_INTEL && - (pdev->device == 0x1E26 || - pdev->device == 0x8C2D || - pdev->device == 0x8C26 || - pdev->device == 0x9C26); -} - -static void ehci_enable_xhci_companion(void) -{ - struct pci_dev *companion = NULL; - - /* The xHCI and EHCI controllers are not on the same PCI slot */ - for_each_pci_dev(companion) { - if (!usb_is_intel_switchable_xhci(companion)) - continue; - usb_enable_xhci_ports(companion); - return; - } -} - -static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - - /* The BIOS on systems with the Intel Panther Point chipset may or may - * not support xHCI natively. That means that during system resume, it - * may switch the ports back to EHCI so that users can use their - * keyboard to select a kernel from GRUB after resume from hibernate. - * - * The BIOS is supposed to remember whether the OS had xHCI ports - * enabled before resume, and switch the ports back to xHCI when the - * BIOS/OS semaphore is written, but we all know we can't trust BIOS - * writers. - * - * Unconditionally switch the ports back to xHCI after a system resume. - * We can't tell whether the EHCI or xHCI controller will be resumed - * first, so we have to do the port switchover in both drivers. Writing - * a '1' to the port switchover registers should have no effect if the - * port was already switched over. - */ - if (usb_is_intel_switchable_ehci(pdev)) - ehci_enable_xhci_companion(); - - if (ehci_resume(hcd, hibernated) != 0) - (void) ehci_pci_reinit(ehci, pdev); - return 0; -} - -#else - -#define ehci_suspend NULL -#define ehci_pci_resume NULL -#endif /* CONFIG_PM */ - -static struct hc_driver __read_mostly ehci_pci_hc_driver; - -static const struct ehci_driver_overrides pci_overrides __initconst = { - .reset = ehci_pci_setup, -}; - -/*-------------------------------------------------------------------------*/ - -/* PCI driver selection metadata; PCI hotplugging uses this */ -static const struct pci_device_id pci_ids [] = { { - /* handle any USB 2.0 EHCI controller */ - PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0), - .driver_data = (unsigned long) &ehci_pci_hc_driver, - }, { - PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_HOST), - .driver_data = (unsigned long) &ehci_pci_hc_driver, - }, - { /* end: all zeroes */ } -}; -MODULE_DEVICE_TABLE(pci, pci_ids); - -/* pci driver glue; this is a "new style" PCI driver module */ -static struct pci_driver ehci_pci_driver = { - .name = (char *) hcd_name, - .id_table = pci_ids, - - .probe = usb_hcd_pci_probe, - .remove = usb_hcd_pci_remove, - .shutdown = usb_hcd_pci_shutdown, - -#ifdef CONFIG_PM - .driver = { - .pm = &usb_hcd_pci_pm_ops - }, -#endif -}; - -static int __init ehci_pci_init(void) -{ - if (usb_disabled()) - return -ENODEV; - - pr_info("%s: " DRIVER_DESC "\n", hcd_name); - - ehci_init_driver(&ehci_pci_hc_driver, &pci_overrides); - - /* Entries for the PCI suspend/resume callbacks are special */ - ehci_pci_hc_driver.pci_suspend = ehci_suspend; - ehci_pci_hc_driver.pci_resume = ehci_pci_resume; - - return pci_register_driver(&ehci_pci_driver); -} -module_init(ehci_pci_init); - -static void __exit ehci_pci_cleanup(void) -{ - pci_unregister_driver(&ehci_pci_driver); -} -module_exit(ehci_pci_cleanup); - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR("David Brownell"); -MODULE_AUTHOR("Alan Stern"); -MODULE_LICENSE("GPL"); diff --git a/addons/ehci-pci/src/3.10.108/ehci-q.c b/addons/ehci-pci/src/3.10.108/ehci-q.c deleted file mode 100644 index d34b399b..00000000 --- a/addons/ehci-pci/src/3.10.108/ehci-q.c +++ /dev/null @@ -1,1368 +0,0 @@ -/* - * Copyright (C) 2001-2004 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI hardware queue manipulation ... the core. QH/QTD manipulation. - * - * Control, bulk, and interrupt traffic all use "qh" lists. They list "qtd" - * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned - * buffers needed for the larger number). We use one QH per endpoint, queue - * multiple urbs (all three types) per endpoint. URBs may need several qtds. - * - * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with - * interrupts) needs careful scheduling. Performance improvements can be - * an ongoing challenge. That's in "ehci-sched.c". - * - * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs, - * or otherwise through transaction translators (TTs) in USB 2.0 hubs using - * (b) special fields in qh entries or (c) split iso entries. TTs will - * buffer low/full speed data so the host collects it at high speed. - */ - -/*-------------------------------------------------------------------------*/ - -/* fill a qtd, returning how much of the buffer we were able to queue up */ - -static int -qtd_fill(struct ehci_hcd *ehci, struct ehci_qtd *qtd, dma_addr_t buf, - size_t len, int token, int maxpacket) -{ - int i, count; - u64 addr = buf; - - /* one buffer entry per 4K ... first might be short or unaligned */ - qtd->hw_buf[0] = cpu_to_hc32(ehci, (u32)addr); - qtd->hw_buf_hi[0] = cpu_to_hc32(ehci, (u32)(addr >> 32)); - count = 0x1000 - (buf & 0x0fff); /* rest of that page */ - if (likely (len < count)) /* ... iff needed */ - count = len; - else { - buf += 0x1000; - buf &= ~0x0fff; - - /* per-qtd limit: from 16K to 20K (best alignment) */ - for (i = 1; count < len && i < 5; i++) { - addr = buf; - qtd->hw_buf[i] = cpu_to_hc32(ehci, (u32)addr); - qtd->hw_buf_hi[i] = cpu_to_hc32(ehci, - (u32)(addr >> 32)); - buf += 0x1000; - if ((count + 0x1000) < len) - count += 0x1000; - else - count = len; - } - - /* short packets may only terminate transfers */ - if (count != len) - count -= (count % maxpacket); - } - qtd->hw_token = cpu_to_hc32(ehci, (count << 16) | token); - qtd->length = count; - - return count; -} - -/*-------------------------------------------------------------------------*/ - -static inline void -qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) -{ - struct ehci_qh_hw *hw = qh->hw; - - /* writes to an active overlay are unsafe */ - WARN_ON(qh->qh_state != QH_STATE_IDLE); - - hw->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); - hw->hw_alt_next = EHCI_LIST_END(ehci); - - /* Except for control endpoints, we make hardware maintain data - * toggle (like OHCI) ... here (re)initialize the toggle in the QH, - * and set the pseudo-toggle in udev. Only usb_clear_halt() will - * ever clear it. - */ - if (!(hw->hw_info1 & cpu_to_hc32(ehci, QH_TOGGLE_CTL))) { - unsigned is_out, epnum; - - is_out = qh->is_out; - epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f; - if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { - hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); - usb_settoggle (qh->dev, epnum, is_out, 1); - } - } - - hw->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); -} - -/* if it weren't for a common silicon quirk (writing the dummy into the qh - * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault - * recovery (including urb dequeue) would need software changes to a QH... - */ -static void -qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - struct ehci_qtd *qtd; - - qtd = list_entry(qh->qtd_list.next, struct ehci_qtd, qtd_list); - - /* - * first qtd may already be partially processed. - * If we come here during unlink, the QH overlay region - * might have reference to the just unlinked qtd. The - * qtd is updated in qh_completions(). Update the QH - * overlay here. - */ - if (qh->hw->hw_token & ACTIVE_BIT(ehci)) - qh->hw->hw_qtd_next = qtd->hw_next; - else - qh_update(ehci, qh, qtd); -} - -/*-------------------------------------------------------------------------*/ - -static void qh_link_async(struct ehci_hcd *ehci, struct ehci_qh *qh); - -static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd, - struct usb_host_endpoint *ep) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct ehci_qh *qh = ep->hcpriv; - unsigned long flags; - - spin_lock_irqsave(&ehci->lock, flags); - qh->clearing_tt = 0; - if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list) - && ehci->rh_state == EHCI_RH_RUNNING) - qh_link_async(ehci, qh); - spin_unlock_irqrestore(&ehci->lock, flags); -} - -static void ehci_clear_tt_buffer(struct ehci_hcd *ehci, struct ehci_qh *qh, - struct urb *urb, u32 token) -{ - - /* If an async split transaction gets an error or is unlinked, - * the TT buffer may be left in an indeterminate state. We - * have to clear the TT buffer. - * - * Note: this routine is never called for Isochronous transfers. - */ - if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) { -#ifdef DEBUG - struct usb_device *tt = urb->dev->tt->hub; - dev_dbg(&tt->dev, - "clear tt buffer port %d, a%d ep%d t%08x\n", - urb->dev->ttport, urb->dev->devnum, - usb_pipeendpoint(urb->pipe), token); -#endif /* DEBUG */ - if (!ehci_is_TDI(ehci) - || urb->dev->tt->hub != - ehci_to_hcd(ehci)->self.root_hub) { - if (usb_hub_clear_tt_buffer(urb) == 0) - qh->clearing_tt = 1; - } else { - - /* REVISIT ARC-derived cores don't clear the root - * hub TT buffer in this way... - */ - } - } -} - -static int qtd_copy_status ( - struct ehci_hcd *ehci, - struct urb *urb, - size_t length, - u32 token -) -{ - int status = -EINPROGRESS; - - /* count IN/OUT bytes, not SETUP (even short packets) */ - if (likely (QTD_PID (token) != 2)) - urb->actual_length += length - QTD_LENGTH (token); - - /* don't modify error codes */ - if (unlikely(urb->unlinked)) - return status; - - /* force cleanup after short read; not always an error */ - if (unlikely (IS_SHORT_READ (token))) - status = -EREMOTEIO; - - /* serious "can't proceed" faults reported by the hardware */ - if (token & QTD_STS_HALT) { - if (token & QTD_STS_BABBLE) { - /* FIXME "must" disable babbling device's port too */ - status = -EOVERFLOW; - /* CERR nonzero + halt --> stall */ - } else if (QTD_CERR(token)) { - status = -EPIPE; - - /* In theory, more than one of the following bits can be set - * since they are sticky and the transaction is retried. - * Which to test first is rather arbitrary. - */ - } else if (token & QTD_STS_MMF) { - /* fs/ls interrupt xfer missed the complete-split */ - status = -EPROTO; - } else if (token & QTD_STS_DBE) { - status = (QTD_PID (token) == 1) /* IN ? */ - ? -ENOSR /* hc couldn't read data */ - : -ECOMM; /* hc couldn't write data */ - } else if (token & QTD_STS_XACT) { - /* timeout, bad CRC, wrong PID, etc */ - ehci_dbg(ehci, "devpath %s ep%d%s 3strikes\n", - urb->dev->devpath, - usb_pipeendpoint(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out"); - status = -EPROTO; - } else { /* unknown */ - status = -EPROTO; - } - - ehci_vdbg (ehci, - "dev%d ep%d%s qtd token %08x --> status %d\n", - usb_pipedevice (urb->pipe), - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", - token, status); - } - - return status; -} - -static void -ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status) -__releases(ehci->lock) -__acquires(ehci->lock) -{ - if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { - /* ... update hc-wide periodic stats */ - ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; - } - - if (unlikely(urb->unlinked)) { - COUNT(ehci->stats.unlink); - } else { - /* report non-error and short read status as zero */ - if (status == -EINPROGRESS || status == -EREMOTEIO) - status = 0; - COUNT(ehci->stats.complete); - } - -#ifdef EHCI_URB_TRACE - ehci_dbg (ehci, - "%s %s urb %p ep%d%s status %d len %d/%d\n", - __func__, urb->dev->devpath, urb, - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", - status, - urb->actual_length, urb->transfer_buffer_length); -#endif - - /* complete() can reenter this HCD */ - usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); - spin_unlock (&ehci->lock); - usb_hcd_giveback_urb(ehci_to_hcd(ehci), urb, status); - spin_lock (&ehci->lock); -} - -static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh); - -/* - * Process and free completed qtds for a qh, returning URBs to drivers. - * Chases up to qh->hw_current. Returns nonzero if the caller should - * unlink qh. - */ -static unsigned -qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - struct ehci_qtd *last, *end = qh->dummy; - struct list_head *entry, *tmp; - int last_status; - int stopped; - u8 state; - struct ehci_qh_hw *hw = qh->hw; - - /* completions (or tasks on other cpus) must never clobber HALT - * till we've gone through and cleaned everything up, even when - * they add urbs to this qh's queue or mark them for unlinking. - * - * NOTE: unlinking expects to be done in queue order. - * - * It's a bug for qh->qh_state to be anything other than - * QH_STATE_IDLE, unless our caller is scan_async() or - * scan_intr(). - */ - state = qh->qh_state; - qh->qh_state = QH_STATE_COMPLETING; - stopped = (state == QH_STATE_IDLE); - - rescan: - last = NULL; - last_status = -EINPROGRESS; - qh->dequeue_during_giveback = 0; - - /* remove de-activated QTDs from front of queue. - * after faults (including short reads), cleanup this urb - * then let the queue advance. - * if queue is stopped, handles unlinks. - */ - list_for_each_safe (entry, tmp, &qh->qtd_list) { - struct ehci_qtd *qtd; - struct urb *urb; - u32 token = 0; - - qtd = list_entry (entry, struct ehci_qtd, qtd_list); - urb = qtd->urb; - - /* clean up any state from previous QTD ...*/ - if (last) { - if (likely (last->urb != urb)) { - ehci_urb_done(ehci, last->urb, last_status); - last_status = -EINPROGRESS; - } - ehci_qtd_free (ehci, last); - last = NULL; - } - - /* ignore urbs submitted during completions we reported */ - if (qtd == end) - break; - - /* hardware copies qtd out of qh overlay */ - rmb (); - token = hc32_to_cpu(ehci, qtd->hw_token); - - /* always clean up qtds the hc de-activated */ - retry_xacterr: - if ((token & QTD_STS_ACTIVE) == 0) { - - /* Report Data Buffer Error: non-fatal but useful */ - if (token & QTD_STS_DBE) - ehci_dbg(ehci, - "detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n", - urb, - usb_endpoint_num(&urb->ep->desc), - usb_endpoint_dir_in(&urb->ep->desc) ? "in" : "out", - urb->transfer_buffer_length, - qtd, - qh); - - /* on STALL, error, and short reads this urb must - * complete and all its qtds must be recycled. - */ - if ((token & QTD_STS_HALT) != 0) { - - /* retry transaction errors until we - * reach the software xacterr limit - */ - if ((token & QTD_STS_XACT) && - QTD_CERR(token) == 0 && - ++qh->xacterrs < QH_XACTERR_MAX && - !urb->unlinked) { - ehci_dbg(ehci, - "detected XactErr len %zu/%zu retry %d\n", - qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs); - - /* reset the token in the qtd and the - * qh overlay (which still contains - * the qtd) so that we pick up from - * where we left off - */ - token &= ~QTD_STS_HALT; - token |= QTD_STS_ACTIVE | - (EHCI_TUNE_CERR << 10); - qtd->hw_token = cpu_to_hc32(ehci, - token); - wmb(); - hw->hw_token = cpu_to_hc32(ehci, - token); - goto retry_xacterr; - } - stopped = 1; - - /* magic dummy for some short reads; qh won't advance. - * that silicon quirk can kick in with this dummy too. - * - * other short reads won't stop the queue, including - * control transfers (status stage handles that) or - * most other single-qtd reads ... the queue stops if - * URB_SHORT_NOT_OK was set so the driver submitting - * the urbs could clean it up. - */ - } else if (IS_SHORT_READ (token) - && !(qtd->hw_alt_next - & EHCI_LIST_END(ehci))) { - stopped = 1; - } - - /* stop scanning when we reach qtds the hc is using */ - } else if (likely (!stopped - && ehci->rh_state >= EHCI_RH_RUNNING)) { - break; - - /* scan the whole queue for unlinks whenever it stops */ - } else { - stopped = 1; - - /* cancel everything if we halt, suspend, etc */ - if (ehci->rh_state < EHCI_RH_RUNNING) - last_status = -ESHUTDOWN; - - /* this qtd is active; skip it unless a previous qtd - * for its urb faulted, or its urb was canceled. - */ - else if (last_status == -EINPROGRESS && !urb->unlinked) - continue; - - /* - * If this was the active qtd when the qh was unlinked - * and the overlay's token is active, then the overlay - * hasn't been written back to the qtd yet so use its - * token instead of the qtd's. After the qtd is - * processed and removed, the overlay won't be valid - * any more. - */ - if (state == QH_STATE_IDLE && - qh->qtd_list.next == &qtd->qtd_list && - (hw->hw_token & ACTIVE_BIT(ehci))) { - token = hc32_to_cpu(ehci, hw->hw_token); - hw->hw_token &= ~ACTIVE_BIT(ehci); - - /* An unlink may leave an incomplete - * async transaction in the TT buffer. - * We have to clear it. - */ - ehci_clear_tt_buffer(ehci, qh, urb, token); - } - } - - /* unless we already know the urb's status, collect qtd status - * and update count of bytes transferred. in common short read - * cases with only one data qtd (including control transfers), - * queue processing won't halt. but with two or more qtds (for - * example, with a 32 KB transfer), when the first qtd gets a - * short read the second must be removed by hand. - */ - if (last_status == -EINPROGRESS) { - last_status = qtd_copy_status(ehci, urb, - qtd->length, token); - if (last_status == -EREMOTEIO - && (qtd->hw_alt_next - & EHCI_LIST_END(ehci))) - last_status = -EINPROGRESS; - - /* As part of low/full-speed endpoint-halt processing - * we must clear the TT buffer (11.17.5). - */ - if (unlikely(last_status != -EINPROGRESS && - last_status != -EREMOTEIO)) { - /* The TT's in some hubs malfunction when they - * receive this request following a STALL (they - * stop sending isochronous packets). Since a - * STALL can't leave the TT buffer in a busy - * state (if you believe Figures 11-48 - 11-51 - * in the USB 2.0 spec), we won't clear the TT - * buffer in this case. Strictly speaking this - * is a violation of the spec. - */ - if (last_status != -EPIPE) - ehci_clear_tt_buffer(ehci, qh, urb, - token); - } - } - - /* if we're removing something not at the queue head, - * patch the hardware queue pointer. - */ - if (stopped && qtd->qtd_list.prev != &qh->qtd_list) { - last = list_entry (qtd->qtd_list.prev, - struct ehci_qtd, qtd_list); - last->hw_next = qtd->hw_next; - } - - /* remove qtd; it's recycled after possible urb completion */ - list_del (&qtd->qtd_list); - last = qtd; - - /* reinit the xacterr counter for the next qtd */ - qh->xacterrs = 0; - } - - /* last urb's completion might still need calling */ - if (likely (last != NULL)) { - ehci_urb_done(ehci, last->urb, last_status); - ehci_qtd_free (ehci, last); - } - - /* Do we need to rescan for URBs dequeued during a giveback? */ - if (unlikely(qh->dequeue_during_giveback)) { - /* If the QH is already unlinked, do the rescan now. */ - if (state == QH_STATE_IDLE) - goto rescan; - - /* Otherwise the caller must unlink the QH. */ - } - - /* restore original state; caller must unlink or relink */ - qh->qh_state = state; - - /* be sure the hardware's done with the qh before refreshing - * it after fault cleanup, or recovering from silicon wrongly - * overlaying the dummy qtd (which reduces DMA chatter). - * - * We won't refresh a QH that's linked (after the HC - * stopped the queue). That avoids a race: - * - HC reads first part of QH; - * - CPU updates that first part and the token; - * - HC reads rest of that QH, including token - * Result: HC gets an inconsistent image, and then - * DMAs to/from the wrong memory (corrupting it). - * - * That should be rare for interrupt transfers, - * except maybe high bandwidth ... - */ - if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) - qh->exception = 1; - - /* Let the caller know if the QH needs to be unlinked. */ - return qh->exception; -} - -/*-------------------------------------------------------------------------*/ - -// high bandwidth multiplier, as encoded in highspeed endpoint descriptors -#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) -// ... and packet size, for any kind of endpoint descriptor -#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) - -/* - * reverse of qh_urb_transaction: free a list of TDs. - * used for cleanup after errors, before HC sees an URB's TDs. - */ -static void qtd_list_free ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *qtd_list -) { - struct list_head *entry, *temp; - - list_for_each_safe (entry, temp, qtd_list) { - struct ehci_qtd *qtd; - - qtd = list_entry (entry, struct ehci_qtd, qtd_list); - list_del (&qtd->qtd_list); - ehci_qtd_free (ehci, qtd); - } -} - -/* - * create a list of filled qtds for this URB; won't link into qh. - */ -static struct list_head * -qh_urb_transaction ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *head, - gfp_t flags -) { - struct ehci_qtd *qtd, *qtd_prev; - dma_addr_t buf; - int len, this_sg_len, maxpacket; - int is_input; - u32 token; - int i; - struct scatterlist *sg; - - /* - * URBs map to sequences of QTDs: one logical transaction - */ - qtd = ehci_qtd_alloc (ehci, flags); - if (unlikely (!qtd)) - return NULL; - list_add_tail (&qtd->qtd_list, head); - qtd->urb = urb; - - token = QTD_STS_ACTIVE; - token |= (EHCI_TUNE_CERR << 10); - /* for split transactions, SplitXState initialized to zero */ - - len = urb->transfer_buffer_length; - is_input = usb_pipein (urb->pipe); - if (usb_pipecontrol (urb->pipe)) { - /* SETUP pid */ - qtd_fill(ehci, qtd, urb->setup_dma, - sizeof (struct usb_ctrlrequest), - token | (2 /* "setup" */ << 8), 8); - - /* ... and always at least one more pid */ - token ^= QTD_TOGGLE; - qtd_prev = qtd; - qtd = ehci_qtd_alloc (ehci, flags); - if (unlikely (!qtd)) - goto cleanup; - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma); - list_add_tail (&qtd->qtd_list, head); - - /* for zero length DATA stages, STATUS is always IN */ - if (len == 0) - token |= (1 /* "in" */ << 8); - } - - /* - * data transfer stage: buffer setup - */ - i = urb->num_mapped_sgs; - if (len > 0 && i > 0) { - sg = urb->sg; - buf = sg_dma_address(sg); - - /* urb->transfer_buffer_length may be smaller than the - * size of the scatterlist (or vice versa) - */ - this_sg_len = min_t(int, sg_dma_len(sg), len); - } else { - sg = NULL; - buf = urb->transfer_dma; - this_sg_len = len; - } - - if (is_input) - token |= (1 /* "in" */ << 8); - /* else it's already initted to "out" pid (0 << 8) */ - - maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input)); - - /* - * buffer gets wrapped in one or more qtds; - * last one may be "short" (including zero len) - * and may serve as a control status ack - */ - for (;;) { - int this_qtd_len; - - this_qtd_len = qtd_fill(ehci, qtd, buf, this_sg_len, token, - maxpacket); - this_sg_len -= this_qtd_len; - len -= this_qtd_len; - buf += this_qtd_len; - - /* - * short reads advance to a "magic" dummy instead of the next - * qtd ... that forces the queue to stop, for manual cleanup. - * (this will usually be overridden later.) - */ - if (is_input) - qtd->hw_alt_next = ehci->async->hw->hw_alt_next; - - /* qh makes control packets use qtd toggle; maybe switch it */ - if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) - token ^= QTD_TOGGLE; - - if (likely(this_sg_len <= 0)) { - if (--i <= 0 || len <= 0) - break; - sg = sg_next(sg); - buf = sg_dma_address(sg); - this_sg_len = min_t(int, sg_dma_len(sg), len); - } - - qtd_prev = qtd; - qtd = ehci_qtd_alloc (ehci, flags); - if (unlikely (!qtd)) - goto cleanup; - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma); - list_add_tail (&qtd->qtd_list, head); - } - - /* - * unless the caller requires manual cleanup after short reads, - * have the alt_next mechanism keep the queue running after the - * last data qtd (the only one, for control and most other cases). - */ - if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0 - || usb_pipecontrol (urb->pipe))) - qtd->hw_alt_next = EHCI_LIST_END(ehci); - - /* - * control requests may need a terminating data "status" ack; - * other OUT ones may need a terminating short packet - * (zero length). - */ - if (likely (urb->transfer_buffer_length != 0)) { - int one_more = 0; - - if (usb_pipecontrol (urb->pipe)) { - one_more = 1; - token ^= 0x0100; /* "in" <--> "out" */ - token |= QTD_TOGGLE; /* force DATA1 */ - } else if (usb_pipeout(urb->pipe) - && (urb->transfer_flags & URB_ZERO_PACKET) - && !(urb->transfer_buffer_length % maxpacket)) { - one_more = 1; - } - if (one_more) { - qtd_prev = qtd; - qtd = ehci_qtd_alloc (ehci, flags); - if (unlikely (!qtd)) - goto cleanup; - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma); - list_add_tail (&qtd->qtd_list, head); - - /* never any data in such packets */ - qtd_fill(ehci, qtd, 0, 0, token, 0); - } - } - - /* by default, enable interrupt on urb completion */ - if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT))) - qtd->hw_token |= cpu_to_hc32(ehci, QTD_IOC); - return head; - -cleanup: - qtd_list_free (ehci, urb, head); - return NULL; -} - -/*-------------------------------------------------------------------------*/ - -// Would be best to create all qh's from config descriptors, -// when each interface/altsetting is established. Unlink -// any previous qh and cancel its urbs first; endpoints are -// implicitly reset then (data toggle too). -// That'd mean updating how usbcore talks to HCDs. (2.7?) - - -/* - * Each QH holds a qtd list; a QH is used for everything except iso. - * - * For interrupt urbs, the scheduler must set the microframe scheduling - * mask(s) each time the QH gets scheduled. For highspeed, that's - * just one microframe in the s-mask. For split interrupt transactions - * there are additional complications: c-mask, maybe FSTNs. - */ -static struct ehci_qh * -qh_make ( - struct ehci_hcd *ehci, - struct urb *urb, - gfp_t flags -) { - struct ehci_qh *qh = ehci_qh_alloc (ehci, flags); - u32 info1 = 0, info2 = 0; - int is_input, type; - int maxp = 0; - struct usb_tt *tt = urb->dev->tt; - struct ehci_qh_hw *hw; - - if (!qh) - return qh; - - /* - * init endpoint/device data for this QH - */ - info1 |= usb_pipeendpoint (urb->pipe) << 8; - info1 |= usb_pipedevice (urb->pipe) << 0; - - is_input = usb_pipein (urb->pipe); - type = usb_pipetype (urb->pipe); - maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input); - - /* 1024 byte maxpacket is a hardware ceiling. High bandwidth - * acts like up to 3KB, but is built from smaller packets. - */ - if (max_packet(maxp) > 1024) { - ehci_dbg(ehci, "bogus qh maxpacket %d\n", max_packet(maxp)); - goto done; - } - - /* Compute interrupt scheduling parameters just once, and save. - * - allowing for high bandwidth, how many nsec/uframe are used? - * - split transactions need a second CSPLIT uframe; same question - * - splits also need a schedule gap (for full/low speed I/O) - * - qh has a polling interval - * - * For control/bulk requests, the HC or TT handles these. - */ - if (type == PIPE_INTERRUPT) { - qh->usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH, - is_input, 0, - hb_mult(maxp) * max_packet(maxp))); - qh->start = NO_FRAME; - - if (urb->dev->speed == USB_SPEED_HIGH) { - qh->c_usecs = 0; - qh->gap_uf = 0; - - qh->period = urb->interval >> 3; - if (qh->period == 0 && urb->interval != 1) { - /* NOTE interval 2 or 4 uframes could work. - * But interval 1 scheduling is simpler, and - * includes high bandwidth. - */ - urb->interval = 1; - } else if (qh->period > ehci->periodic_size) { - qh->period = ehci->periodic_size; - urb->interval = qh->period << 3; - } - } else { - int think_time; - - /* gap is f(FS/LS transfer times) */ - qh->gap_uf = 1 + usb_calc_bus_time (urb->dev->speed, - is_input, 0, maxp) / (125 * 1000); - - /* FIXME this just approximates SPLIT/CSPLIT times */ - if (is_input) { // SPLIT, gap, CSPLIT+DATA - qh->c_usecs = qh->usecs + HS_USECS (0); - qh->usecs = HS_USECS (1); - } else { // SPLIT+DATA, gap, CSPLIT - qh->usecs += HS_USECS (1); - qh->c_usecs = HS_USECS (0); - } - - think_time = tt ? tt->think_time : 0; - qh->tt_usecs = NS_TO_US (think_time + - usb_calc_bus_time (urb->dev->speed, - is_input, 0, max_packet (maxp))); - qh->period = urb->interval; - if (qh->period > ehci->periodic_size) { - qh->period = ehci->periodic_size; - urb->interval = qh->period; - } - } - } - - /* support for tt scheduling, and access to toggles */ - qh->dev = urb->dev; - - /* using TT? */ - switch (urb->dev->speed) { - case USB_SPEED_LOW: - info1 |= QH_LOW_SPEED; - /* FALL THROUGH */ - - case USB_SPEED_FULL: - /* EPS 0 means "full" */ - if (type != PIPE_INTERRUPT) - info1 |= (EHCI_TUNE_RL_TT << 28); - if (type == PIPE_CONTROL) { - info1 |= QH_CONTROL_EP; /* for TT */ - info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ - } - info1 |= maxp << 16; - - info2 |= (EHCI_TUNE_MULT_TT << 30); - - /* Some Freescale processors have an erratum in which the - * port number in the queue head was 0..N-1 instead of 1..N. - */ - if (ehci_has_fsl_portno_bug(ehci)) - info2 |= (urb->dev->ttport-1) << 23; - else - info2 |= urb->dev->ttport << 23; - - /* set the address of the TT; for TDI's integrated - * root hub tt, leave it zeroed. - */ - if (tt && tt->hub != ehci_to_hcd(ehci)->self.root_hub) - info2 |= tt->hub->devnum << 16; - - /* NOTE: if (PIPE_INTERRUPT) { scheduler sets c-mask } */ - - break; - - case USB_SPEED_HIGH: /* no TT involved */ - info1 |= QH_HIGH_SPEED; - if (type == PIPE_CONTROL) { - info1 |= (EHCI_TUNE_RL_HS << 28); - info1 |= 64 << 16; /* usb2 fixed maxpacket */ - info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ - info2 |= (EHCI_TUNE_MULT_HS << 30); - } else if (type == PIPE_BULK) { - info1 |= (EHCI_TUNE_RL_HS << 28); - /* The USB spec says that high speed bulk endpoints - * always use 512 byte maxpacket. But some device - * vendors decided to ignore that, and MSFT is happy - * to help them do so. So now people expect to use - * such nonconformant devices with Linux too; sigh. - */ - info1 |= max_packet(maxp) << 16; - info2 |= (EHCI_TUNE_MULT_HS << 30); - } else { /* PIPE_INTERRUPT */ - info1 |= max_packet (maxp) << 16; - info2 |= hb_mult (maxp) << 30; - } - break; - default: - ehci_dbg(ehci, "bogus dev %p speed %d\n", urb->dev, - urb->dev->speed); -done: - qh_destroy(ehci, qh); - return NULL; - } - - /* NOTE: if (PIPE_INTERRUPT) { scheduler sets s-mask } */ - - /* init as live, toggle clear */ - qh->qh_state = QH_STATE_IDLE; - hw = qh->hw; - hw->hw_info1 = cpu_to_hc32(ehci, info1); - hw->hw_info2 = cpu_to_hc32(ehci, info2); - qh->is_out = !is_input; - usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); - return qh; -} - -/*-------------------------------------------------------------------------*/ - -static void enable_async(struct ehci_hcd *ehci) -{ - if (ehci->async_count++) - return; - - /* Stop waiting to turn off the async schedule */ - ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_DISABLE_ASYNC); - - /* Don't start the schedule until ASS is 0 */ - ehci_poll_ASS(ehci); - turn_on_io_watchdog(ehci); -} - -static void disable_async(struct ehci_hcd *ehci) -{ - if (--ehci->async_count) - return; - - /* The async schedule and unlink lists are supposed to be empty */ - WARN_ON(ehci->async->qh_next.qh || !list_empty(&ehci->async_unlink) || - !list_empty(&ehci->async_idle)); - - /* Don't turn off the schedule until ASS is 1 */ - ehci_poll_ASS(ehci); -} - -/* move qh (and its qtds) onto async queue; maybe enable queue. */ - -static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - __hc32 dma = QH_NEXT(ehci, qh->qh_dma); - struct ehci_qh *head; - - /* Don't link a QH if there's a Clear-TT-Buffer pending */ - if (unlikely(qh->clearing_tt)) - return; - - WARN_ON(qh->qh_state != QH_STATE_IDLE); - - /* clear halt and/or toggle; and maybe recover from silicon quirk */ - qh_refresh(ehci, qh); - - /* splice right after start */ - head = ehci->async; - qh->qh_next = head->qh_next; - qh->hw->hw_next = head->hw->hw_next; - wmb (); - - head->qh_next.qh = qh; - head->hw->hw_next = dma; - - qh->qh_state = QH_STATE_LINKED; - qh->xacterrs = 0; - qh->exception = 0; - /* qtd completions reported later by interrupt */ - - enable_async(ehci); -} - -/*-------------------------------------------------------------------------*/ - -/* - * For control/bulk/interrupt, return QH with these TDs appended. - * Allocates and initializes the QH if necessary. - * Returns null if it can't allocate a QH it needs to. - * If the QH has TDs (urbs) already, that's great. - */ -static struct ehci_qh *qh_append_tds ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *qtd_list, - int epnum, - void **ptr -) -{ - struct ehci_qh *qh = NULL; - __hc32 qh_addr_mask = cpu_to_hc32(ehci, 0x7f); - - qh = (struct ehci_qh *) *ptr; - if (unlikely (qh == NULL)) { - /* can't sleep here, we have ehci->lock... */ - qh = qh_make (ehci, urb, GFP_ATOMIC); - *ptr = qh; - } - if (likely (qh != NULL)) { - struct ehci_qtd *qtd; - - if (unlikely (list_empty (qtd_list))) - qtd = NULL; - else - qtd = list_entry (qtd_list->next, struct ehci_qtd, - qtd_list); - - /* control qh may need patching ... */ - if (unlikely (epnum == 0)) { - - /* usb_reset_device() briefly reverts to address 0 */ - if (usb_pipedevice (urb->pipe) == 0) - qh->hw->hw_info1 &= ~qh_addr_mask; - } - - /* just one way to queue requests: swap with the dummy qtd. - * only hc or qh_refresh() ever modify the overlay. - */ - if (likely (qtd != NULL)) { - struct ehci_qtd *dummy; - dma_addr_t dma; - __hc32 token; - - /* to avoid racing the HC, use the dummy td instead of - * the first td of our list (becomes new dummy). both - * tds stay deactivated until we're done, when the - * HC is allowed to fetch the old dummy (4.10.2). - */ - token = qtd->hw_token; - qtd->hw_token = HALT_BIT(ehci); - - dummy = qh->dummy; - - dma = dummy->qtd_dma; - *dummy = *qtd; - dummy->qtd_dma = dma; - - list_del (&qtd->qtd_list); - list_add (&dummy->qtd_list, qtd_list); - list_splice_tail(qtd_list, &qh->qtd_list); - - ehci_qtd_init(ehci, qtd, qtd->qtd_dma); - qh->dummy = qtd; - - /* hc must see the new dummy at list end */ - dma = qtd->qtd_dma; - qtd = list_entry (qh->qtd_list.prev, - struct ehci_qtd, qtd_list); - qtd->hw_next = QTD_NEXT(ehci, dma); - - /* let the hc process these next qtds */ - wmb (); - dummy->hw_token = token; - - urb->hcpriv = qh; - } - } - return qh; -} - -/*-------------------------------------------------------------------------*/ - -static int -submit_async ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *qtd_list, - gfp_t mem_flags -) { - int epnum; - unsigned long flags; - struct ehci_qh *qh = NULL; - int rc; - - epnum = urb->ep->desc.bEndpointAddress; - -#ifdef EHCI_URB_TRACE - { - struct ehci_qtd *qtd; - qtd = list_entry(qtd_list->next, struct ehci_qtd, qtd_list); - ehci_dbg(ehci, - "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n", - __func__, urb->dev->devpath, urb, - epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out", - urb->transfer_buffer_length, - qtd, urb->ep->hcpriv); - } -#endif - - spin_lock_irqsave (&ehci->lock, flags); - if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { - rc = -ESHUTDOWN; - goto done; - } - rc = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); - if (unlikely(rc)) - goto done; - - qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv); - if (unlikely(qh == NULL)) { - usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); - rc = -ENOMEM; - goto done; - } - - /* Control/bulk operations through TTs don't need scheduling, - * the HC and TT handle it when the TT has a buffer ready. - */ - if (likely (qh->qh_state == QH_STATE_IDLE)) - qh_link_async(ehci, qh); - done: - spin_unlock_irqrestore (&ehci->lock, flags); - if (unlikely (qh == NULL)) - qtd_list_free (ehci, urb, qtd_list); - return rc; -} - -/*-------------------------------------------------------------------------*/ - -static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - struct ehci_qh *prev; - - /* Add to the end of the list of QHs waiting for the next IAAD */ - qh->qh_state = QH_STATE_UNLINK_WAIT; - list_add_tail(&qh->unlink_node, &ehci->async_unlink); - - /* Unlink it from the schedule */ - prev = ehci->async; - while (prev->qh_next.qh != qh) - prev = prev->qh_next.qh; - - prev->hw->hw_next = qh->hw->hw_next; - prev->qh_next = qh->qh_next; - if (ehci->qh_scan_next == qh) - ehci->qh_scan_next = qh->qh_next.qh; -} - -static void start_iaa_cycle(struct ehci_hcd *ehci) -{ - /* Do nothing if an IAA cycle is already running */ - if (ehci->iaa_in_progress) - return; - ehci->iaa_in_progress = true; - - /* If the controller isn't running, we don't have to wait for it */ - if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) { - end_unlink_async(ehci); - - /* Otherwise start a new IAA cycle */ - } else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { - - /* Make sure the unlinks are all visible to the hardware */ - wmb(); - - ehci_writel(ehci, ehci->command | CMD_IAAD, - &ehci->regs->command); - ehci_readl(ehci, &ehci->regs->command); - ehci_enable_event(ehci, EHCI_HRTIMER_IAA_WATCHDOG, true); - } -} - -/* the async qh for the qtds being unlinked are now gone from the HC */ - -static void end_unlink_async(struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - bool early_exit; - - if (ehci->has_synopsys_hc_bug) - ehci_writel(ehci, (u32) ehci->async->qh_dma, - &ehci->regs->async_next); - - /* The current IAA cycle has ended */ - ehci->iaa_in_progress = false; - - if (list_empty(&ehci->async_unlink)) - return; - qh = list_first_entry(&ehci->async_unlink, struct ehci_qh, - unlink_node); /* QH whose IAA cycle just ended */ - - /* - * If async_unlinking is set then this routine is already running, - * either on the stack or on another CPU. - */ - early_exit = ehci->async_unlinking; - - /* If the controller isn't running, process all the waiting QHs */ - if (ehci->rh_state < EHCI_RH_RUNNING) - list_splice_tail_init(&ehci->async_unlink, &ehci->async_idle); - - /* - * Intel (?) bug: The HC can write back the overlay region even - * after the IAA interrupt occurs. In self-defense, always go - * through two IAA cycles for each QH. - */ - else if (qh->qh_state == QH_STATE_UNLINK_WAIT) { - qh->qh_state = QH_STATE_UNLINK; - early_exit = true; - } - - /* Otherwise process only the first waiting QH (NVIDIA bug?) */ - else - list_move_tail(&qh->unlink_node, &ehci->async_idle); - - /* Start a new IAA cycle if any QHs are waiting for it */ - if (!list_empty(&ehci->async_unlink)) - start_iaa_cycle(ehci); - - /* - * Don't allow nesting or concurrent calls, - * or wait for the second IAA cycle for the next QH. - */ - if (early_exit) - return; - - /* Process the idle QHs */ - ehci->async_unlinking = true; - while (!list_empty(&ehci->async_idle)) { - qh = list_first_entry(&ehci->async_idle, struct ehci_qh, - unlink_node); - list_del(&qh->unlink_node); - - qh->qh_state = QH_STATE_IDLE; - qh->qh_next.qh = NULL; - - if (!list_empty(&qh->qtd_list)) - qh_completions(ehci, qh); - if (!list_empty(&qh->qtd_list) && - ehci->rh_state == EHCI_RH_RUNNING) - qh_link_async(ehci, qh); - disable_async(ehci); - } - ehci->async_unlinking = false; -} - -static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh); - -static void unlink_empty_async(struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - struct ehci_qh *qh_to_unlink = NULL; - int count = 0; - - /* Find the last async QH which has been empty for a timer cycle */ - for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh) { - if (list_empty(&qh->qtd_list) && - qh->qh_state == QH_STATE_LINKED) { - ++count; - if (qh->unlink_cycle != ehci->async_unlink_cycle) - qh_to_unlink = qh; - } - } - - /* If nothing else is being unlinked, unlink the last empty QH */ - if (list_empty(&ehci->async_unlink) && qh_to_unlink) { - start_unlink_async(ehci, qh_to_unlink); - --count; - } - - /* Other QHs will be handled later */ - if (count > 0) { - ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true); - ++ehci->async_unlink_cycle; - } -} - -/* The root hub is suspended; unlink all the async QHs */ -static void __maybe_unused unlink_empty_async_suspended(struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - - while (ehci->async->qh_next.qh) { - qh = ehci->async->qh_next.qh; - WARN_ON(!list_empty(&qh->qtd_list)); - single_unlink_async(ehci, qh); - } - start_iaa_cycle(ehci); -} - -/* makes sure the async qh will become idle */ -/* caller must own ehci->lock */ - -static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - /* If the QH isn't linked then there's nothing we can do. */ - if (qh->qh_state != QH_STATE_LINKED) - return; - - single_unlink_async(ehci, qh); - start_iaa_cycle(ehci); -} - -/*-------------------------------------------------------------------------*/ - -static void scan_async (struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - bool check_unlinks_later = false; - - ehci->qh_scan_next = ehci->async->qh_next.qh; - while (ehci->qh_scan_next) { - qh = ehci->qh_scan_next; - ehci->qh_scan_next = qh->qh_next.qh; - - /* clean any finished work for this qh */ - if (!list_empty(&qh->qtd_list)) { - int temp; - - /* - * Unlinks could happen here; completion reporting - * drops the lock. That's why ehci->qh_scan_next - * always holds the next qh to scan; if the next qh - * gets unlinked then ehci->qh_scan_next is adjusted - * in single_unlink_async(). - */ - temp = qh_completions(ehci, qh); - if (unlikely(temp)) { - start_unlink_async(ehci, qh); - } else if (list_empty(&qh->qtd_list) - && qh->qh_state == QH_STATE_LINKED) { - qh->unlink_cycle = ehci->async_unlink_cycle; - check_unlinks_later = true; - } - } - } - - /* - * Unlink empty entries, reducing DMA usage as well - * as HCD schedule-scanning costs. Delay for any qh - * we just scanned, there's a not-unusual case that it - * doesn't stay idle for long. - */ - if (check_unlinks_later && ehci->rh_state == EHCI_RH_RUNNING && - !(ehci->enabled_hrtimer_events & - BIT(EHCI_HRTIMER_ASYNC_UNLINKS))) { - ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true); - ++ehci->async_unlink_cycle; - } -} diff --git a/addons/ehci-pci/src/3.10.108/ehci-sched.c b/addons/ehci-pci/src/3.10.108/ehci-sched.c deleted file mode 100644 index 8e3c878f..00000000 --- a/addons/ehci-pci/src/3.10.108/ehci-sched.c +++ /dev/null @@ -1,2327 +0,0 @@ -/* - * Copyright (c) 2001-2004 by David Brownell - * Copyright (c) 2003 Michal Sojka, for high-speed iso transfers - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI scheduled transaction support: interrupt, iso, split iso - * These are called "periodic" transactions in the EHCI spec. - * - * Note that for interrupt transfers, the QH/QTD manipulation is shared - * with the "asynchronous" transaction support (control/bulk transfers). - * The only real difference is in how interrupt transfers are scheduled. - * - * For ISO, we make an "iso_stream" head to serve the same role as a QH. - * It keeps track of every ITD (or SITD) that's linked, and holds enough - * pre-calculated schedule data to make appending to the queue be quick. - */ - -static int ehci_get_frame (struct usb_hcd *hcd); - -/* - * periodic_next_shadow - return "next" pointer on shadow list - * @periodic: host pointer to qh/itd/sitd - * @tag: hardware tag for type of this record - */ -static union ehci_shadow * -periodic_next_shadow(struct ehci_hcd *ehci, union ehci_shadow *periodic, - __hc32 tag) -{ - switch (hc32_to_cpu(ehci, tag)) { - case Q_TYPE_QH: - return &periodic->qh->qh_next; - case Q_TYPE_FSTN: - return &periodic->fstn->fstn_next; - case Q_TYPE_ITD: - return &periodic->itd->itd_next; - // case Q_TYPE_SITD: - default: - return &periodic->sitd->sitd_next; - } -} - -static __hc32 * -shadow_next_periodic(struct ehci_hcd *ehci, union ehci_shadow *periodic, - __hc32 tag) -{ - switch (hc32_to_cpu(ehci, tag)) { - /* our ehci_shadow.qh is actually software part */ - case Q_TYPE_QH: - return &periodic->qh->hw->hw_next; - /* others are hw parts */ - default: - return periodic->hw_next; - } -} - -/* caller must hold ehci->lock */ -static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) -{ - union ehci_shadow *prev_p = &ehci->pshadow[frame]; - __hc32 *hw_p = &ehci->periodic[frame]; - union ehci_shadow here = *prev_p; - - /* find predecessor of "ptr"; hw and shadow lists are in sync */ - while (here.ptr && here.ptr != ptr) { - prev_p = periodic_next_shadow(ehci, prev_p, - Q_NEXT_TYPE(ehci, *hw_p)); - hw_p = shadow_next_periodic(ehci, &here, - Q_NEXT_TYPE(ehci, *hw_p)); - here = *prev_p; - } - /* an interrupt entry (at list end) could have been shared */ - if (!here.ptr) - return; - - /* update shadow and hardware lists ... the old "next" pointers - * from ptr may still be in use, the caller updates them. - */ - *prev_p = *periodic_next_shadow(ehci, &here, - Q_NEXT_TYPE(ehci, *hw_p)); - - if (!ehci->use_dummy_qh || - *shadow_next_periodic(ehci, &here, Q_NEXT_TYPE(ehci, *hw_p)) - != EHCI_LIST_END(ehci)) - *hw_p = *shadow_next_periodic(ehci, &here, - Q_NEXT_TYPE(ehci, *hw_p)); - else - *hw_p = ehci->dummy->qh_dma; -} - -/* how many of the uframe's 125 usecs are allocated? */ -static unsigned short -periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) -{ - __hc32 *hw_p = &ehci->periodic [frame]; - union ehci_shadow *q = &ehci->pshadow [frame]; - unsigned usecs = 0; - struct ehci_qh_hw *hw; - - while (q->ptr) { - switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) { - case Q_TYPE_QH: - hw = q->qh->hw; - /* is it in the S-mask? */ - if (hw->hw_info2 & cpu_to_hc32(ehci, 1 << uframe)) - usecs += q->qh->usecs; - /* ... or C-mask? */ - if (hw->hw_info2 & cpu_to_hc32(ehci, - 1 << (8 + uframe))) - usecs += q->qh->c_usecs; - hw_p = &hw->hw_next; - q = &q->qh->qh_next; - break; - // case Q_TYPE_FSTN: - default: - /* for "save place" FSTNs, count the relevant INTR - * bandwidth from the previous frame - */ - if (q->fstn->hw_prev != EHCI_LIST_END(ehci)) { - ehci_dbg (ehci, "ignoring FSTN cost ...\n"); - } - hw_p = &q->fstn->hw_next; - q = &q->fstn->fstn_next; - break; - case Q_TYPE_ITD: - if (q->itd->hw_transaction[uframe]) - usecs += q->itd->stream->usecs; - hw_p = &q->itd->hw_next; - q = &q->itd->itd_next; - break; - case Q_TYPE_SITD: - /* is it in the S-mask? (count SPLIT, DATA) */ - if (q->sitd->hw_uframe & cpu_to_hc32(ehci, - 1 << uframe)) { - if (q->sitd->hw_fullspeed_ep & - cpu_to_hc32(ehci, 1<<31)) - usecs += q->sitd->stream->usecs; - else /* worst case for OUT start-split */ - usecs += HS_USECS_ISO (188); - } - - /* ... C-mask? (count CSPLIT, DATA) */ - if (q->sitd->hw_uframe & - cpu_to_hc32(ehci, 1 << (8 + uframe))) { - /* worst case for IN complete-split */ - usecs += q->sitd->stream->c_usecs; - } - - hw_p = &q->sitd->hw_next; - q = &q->sitd->sitd_next; - break; - } - } -#ifdef DEBUG - if (usecs > ehci->uframe_periodic_max) - ehci_err (ehci, "uframe %d sched overrun: %d usecs\n", - frame * 8 + uframe, usecs); -#endif - return usecs; -} - -/*-------------------------------------------------------------------------*/ - -static int same_tt (struct usb_device *dev1, struct usb_device *dev2) -{ - if (!dev1->tt || !dev2->tt) - return 0; - if (dev1->tt != dev2->tt) - return 0; - if (dev1->tt->multi) - return dev1->ttport == dev2->ttport; - else - return 1; -} - -#ifdef CONFIG_USB_EHCI_TT_NEWSCHED - -/* Which uframe does the low/fullspeed transfer start in? - * - * The parameter is the mask of ssplits in "H-frame" terms - * and this returns the transfer start uframe in "B-frame" terms, - * which allows both to match, e.g. a ssplit in "H-frame" uframe 0 - * will cause a transfer in "B-frame" uframe 0. "B-frames" lag - * "H-frames" by 1 uframe. See the EHCI spec sec 4.5 and figure 4.7. - */ -static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) -{ - unsigned char smask = QH_SMASK & hc32_to_cpu(ehci, mask); - if (!smask) { - ehci_err(ehci, "invalid empty smask!\n"); - /* uframe 7 can't have bw so this will indicate failure */ - return 7; - } - return ffs(smask) - 1; -} - -static const unsigned char -max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; - -/* carryover low/fullspeed bandwidth that crosses uframe boundries */ -static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) -{ - int i; - for (i=0; i<7; i++) { - if (max_tt_usecs[i] < tt_usecs[i]) { - tt_usecs[i+1] += tt_usecs[i] - max_tt_usecs[i]; - tt_usecs[i] = max_tt_usecs[i]; - } - } -} - -/* How many of the tt's periodic downstream 1000 usecs are allocated? - * - * While this measures the bandwidth in terms of usecs/uframe, - * the low/fullspeed bus has no notion of uframes, so any particular - * low/fullspeed transfer can "carry over" from one uframe to the next, - * since the TT just performs downstream transfers in sequence. - * - * For example two separate 100 usec transfers can start in the same uframe, - * and the second one would "carry over" 75 usecs into the next uframe. - */ -static void -periodic_tt_usecs ( - struct ehci_hcd *ehci, - struct usb_device *dev, - unsigned frame, - unsigned short tt_usecs[8] -) -{ - __hc32 *hw_p = &ehci->periodic [frame]; - union ehci_shadow *q = &ehci->pshadow [frame]; - unsigned char uf; - - memset(tt_usecs, 0, 16); - - while (q->ptr) { - switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) { - case Q_TYPE_ITD: - hw_p = &q->itd->hw_next; - q = &q->itd->itd_next; - continue; - case Q_TYPE_QH: - if (same_tt(dev, q->qh->dev)) { - uf = tt_start_uframe(ehci, q->qh->hw->hw_info2); - tt_usecs[uf] += q->qh->tt_usecs; - } - hw_p = &q->qh->hw->hw_next; - q = &q->qh->qh_next; - continue; - case Q_TYPE_SITD: - if (same_tt(dev, q->sitd->urb->dev)) { - uf = tt_start_uframe(ehci, q->sitd->hw_uframe); - tt_usecs[uf] += q->sitd->stream->tt_usecs; - } - hw_p = &q->sitd->hw_next; - q = &q->sitd->sitd_next; - continue; - // case Q_TYPE_FSTN: - default: - ehci_dbg(ehci, "ignoring periodic frame %d FSTN\n", - frame); - hw_p = &q->fstn->hw_next; - q = &q->fstn->fstn_next; - } - } - - carryover_tt_bandwidth(tt_usecs); - - if (max_tt_usecs[7] < tt_usecs[7]) - ehci_err(ehci, "frame %d tt sched overrun: %d usecs\n", - frame, tt_usecs[7] - max_tt_usecs[7]); -} - -/* - * Return true if the device's tt's downstream bus is available for a - * periodic transfer of the specified length (usecs), starting at the - * specified frame/uframe. Note that (as summarized in section 11.19 - * of the usb 2.0 spec) TTs can buffer multiple transactions for each - * uframe. - * - * The uframe parameter is when the fullspeed/lowspeed transfer - * should be executed in "B-frame" terms, which is the same as the - * highspeed ssplit's uframe (which is in "H-frame" terms). For example - * a ssplit in "H-frame" 0 causes a transfer in "B-frame" 0. - * See the EHCI spec sec 4.5 and fig 4.7. - * - * This checks if the full/lowspeed bus, at the specified starting uframe, - * has the specified bandwidth available, according to rules listed - * in USB 2.0 spec section 11.18.1 fig 11-60. - * - * This does not check if the transfer would exceed the max ssplit - * limit of 16, specified in USB 2.0 spec section 11.18.4 requirement #4, - * since proper scheduling limits ssplits to less than 16 per uframe. - */ -static int tt_available ( - struct ehci_hcd *ehci, - unsigned period, - struct usb_device *dev, - unsigned frame, - unsigned uframe, - u16 usecs -) -{ - if ((period == 0) || (uframe >= 7)) /* error */ - return 0; - - for (; frame < ehci->periodic_size; frame += period) { - unsigned short tt_usecs[8]; - - periodic_tt_usecs (ehci, dev, frame, tt_usecs); - - ehci_vdbg(ehci, "tt frame %d check %d usecs start uframe %d in" - " schedule %d/%d/%d/%d/%d/%d/%d/%d\n", - frame, usecs, uframe, - tt_usecs[0], tt_usecs[1], tt_usecs[2], tt_usecs[3], - tt_usecs[4], tt_usecs[5], tt_usecs[6], tt_usecs[7]); - - if (max_tt_usecs[uframe] <= tt_usecs[uframe]) { - ehci_vdbg(ehci, "frame %d uframe %d fully scheduled\n", - frame, uframe); - return 0; - } - - /* special case for isoc transfers larger than 125us: - * the first and each subsequent fully used uframe - * must be empty, so as to not illegally delay - * already scheduled transactions - */ - if (125 < usecs) { - int ufs = (usecs / 125); - int i; - for (i = uframe; i < (uframe + ufs) && i < 8; i++) - if (0 < tt_usecs[i]) { - ehci_vdbg(ehci, - "multi-uframe xfer can't fit " - "in frame %d uframe %d\n", - frame, i); - return 0; - } - } - - tt_usecs[uframe] += usecs; - - carryover_tt_bandwidth(tt_usecs); - - /* fail if the carryover pushed bw past the last uframe's limit */ - if (max_tt_usecs[7] < tt_usecs[7]) { - ehci_vdbg(ehci, - "tt unavailable usecs %d frame %d uframe %d\n", - usecs, frame, uframe); - return 0; - } - } - - return 1; -} - -#else - -/* return true iff the device's transaction translator is available - * for a periodic transfer starting at the specified frame, using - * all the uframes in the mask. - */ -static int tt_no_collision ( - struct ehci_hcd *ehci, - unsigned period, - struct usb_device *dev, - unsigned frame, - u32 uf_mask -) -{ - if (period == 0) /* error */ - return 0; - - /* note bandwidth wastage: split never follows csplit - * (different dev or endpoint) until the next uframe. - * calling convention doesn't make that distinction. - */ - for (; frame < ehci->periodic_size; frame += period) { - union ehci_shadow here; - __hc32 type; - struct ehci_qh_hw *hw; - - here = ehci->pshadow [frame]; - type = Q_NEXT_TYPE(ehci, ehci->periodic [frame]); - while (here.ptr) { - switch (hc32_to_cpu(ehci, type)) { - case Q_TYPE_ITD: - type = Q_NEXT_TYPE(ehci, here.itd->hw_next); - here = here.itd->itd_next; - continue; - case Q_TYPE_QH: - hw = here.qh->hw; - if (same_tt (dev, here.qh->dev)) { - u32 mask; - - mask = hc32_to_cpu(ehci, - hw->hw_info2); - /* "knows" no gap is needed */ - mask |= mask >> 8; - if (mask & uf_mask) - break; - } - type = Q_NEXT_TYPE(ehci, hw->hw_next); - here = here.qh->qh_next; - continue; - case Q_TYPE_SITD: - if (same_tt (dev, here.sitd->urb->dev)) { - u16 mask; - - mask = hc32_to_cpu(ehci, here.sitd - ->hw_uframe); - /* FIXME assumes no gap for IN! */ - mask |= mask >> 8; - if (mask & uf_mask) - break; - } - type = Q_NEXT_TYPE(ehci, here.sitd->hw_next); - here = here.sitd->sitd_next; - continue; - // case Q_TYPE_FSTN: - default: - ehci_dbg (ehci, - "periodic frame %d bogus type %d\n", - frame, type); - } - - /* collision or error */ - return 0; - } - } - - /* no collision */ - return 1; -} - -#endif /* CONFIG_USB_EHCI_TT_NEWSCHED */ - -/*-------------------------------------------------------------------------*/ - -static void enable_periodic(struct ehci_hcd *ehci) -{ - if (ehci->periodic_count++) - return; - - /* Stop waiting to turn off the periodic schedule */ - ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_DISABLE_PERIODIC); - - /* Don't start the schedule until PSS is 0 */ - ehci_poll_PSS(ehci); - turn_on_io_watchdog(ehci); -} - -static void disable_periodic(struct ehci_hcd *ehci) -{ - if (--ehci->periodic_count) - return; - - /* Don't turn off the schedule until PSS is 1 */ - ehci_poll_PSS(ehci); -} - -/*-------------------------------------------------------------------------*/ - -/* periodic schedule slots have iso tds (normal or split) first, then a - * sparse tree for active interrupt transfers. - * - * this just links in a qh; caller guarantees uframe masks are set right. - * no FSTN support (yet; ehci 0.96+) - */ -static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - unsigned i; - unsigned period = qh->period; - - dev_dbg (&qh->dev->dev, - "link qh%d-%04x/%p start %d [%d/%d us]\n", - period, hc32_to_cpup(ehci, &qh->hw->hw_info2) - & (QH_CMASK | QH_SMASK), - qh, qh->start, qh->usecs, qh->c_usecs); - - /* high bandwidth, or otherwise every microframe */ - if (period == 0) - period = 1; - - for (i = qh->start; i < ehci->periodic_size; i += period) { - union ehci_shadow *prev = &ehci->pshadow[i]; - __hc32 *hw_p = &ehci->periodic[i]; - union ehci_shadow here = *prev; - __hc32 type = 0; - - /* skip the iso nodes at list head */ - while (here.ptr) { - type = Q_NEXT_TYPE(ehci, *hw_p); - if (type == cpu_to_hc32(ehci, Q_TYPE_QH)) - break; - prev = periodic_next_shadow(ehci, prev, type); - hw_p = shadow_next_periodic(ehci, &here, type); - here = *prev; - } - - /* sorting each branch by period (slow-->fast) - * enables sharing interior tree nodes - */ - while (here.ptr && qh != here.qh) { - if (qh->period > here.qh->period) - break; - prev = &here.qh->qh_next; - hw_p = &here.qh->hw->hw_next; - here = *prev; - } - /* link in this qh, unless some earlier pass did that */ - if (qh != here.qh) { - qh->qh_next = here; - if (here.qh) - qh->hw->hw_next = *hw_p; - wmb (); - prev->qh = qh; - *hw_p = QH_NEXT (ehci, qh->qh_dma); - } - } - qh->qh_state = QH_STATE_LINKED; - qh->xacterrs = 0; - qh->exception = 0; - - /* update per-qh bandwidth for usbfs */ - ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->period - ? ((qh->usecs + qh->c_usecs) / qh->period) - : (qh->usecs * 8); - - list_add(&qh->intr_node, &ehci->intr_qh_list); - - /* maybe enable periodic schedule processing */ - ++ehci->intr_count; - enable_periodic(ehci); -} - -static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - unsigned i; - unsigned period; - - /* - * If qh is for a low/full-speed device, simply unlinking it - * could interfere with an ongoing split transaction. To unlink - * it safely would require setting the QH_INACTIVATE bit and - * waiting at least one frame, as described in EHCI 4.12.2.5. - * - * We won't bother with any of this. Instead, we assume that the - * only reason for unlinking an interrupt QH while the current URB - * is still active is to dequeue all the URBs (flush the whole - * endpoint queue). - * - * If rebalancing the periodic schedule is ever implemented, this - * approach will no longer be valid. - */ - - /* high bandwidth, or otherwise part of every microframe */ - if ((period = qh->period) == 0) - period = 1; - - for (i = qh->start; i < ehci->periodic_size; i += period) - periodic_unlink (ehci, i, qh); - - /* update per-qh bandwidth for usbfs */ - ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->period - ? ((qh->usecs + qh->c_usecs) / qh->period) - : (qh->usecs * 8); - - dev_dbg (&qh->dev->dev, - "unlink qh%d-%04x/%p start %d [%d/%d us]\n", - qh->period, - hc32_to_cpup(ehci, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK), - qh, qh->start, qh->usecs, qh->c_usecs); - - /* qh->qh_next still "live" to HC */ - qh->qh_state = QH_STATE_UNLINK; - qh->qh_next.ptr = NULL; - - if (ehci->qh_scan_next == qh) - ehci->qh_scan_next = list_entry(qh->intr_node.next, - struct ehci_qh, intr_node); - list_del(&qh->intr_node); -} - -static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - /* If the QH isn't linked then there's nothing we can do. */ - if (qh->qh_state != QH_STATE_LINKED) - return; - - qh_unlink_periodic (ehci, qh); - - /* Make sure the unlinks are visible before starting the timer */ - wmb(); - - /* - * The EHCI spec doesn't say how long it takes the controller to - * stop accessing an unlinked interrupt QH. The timer delay is - * 9 uframes; presumably that will be long enough. - */ - qh->unlink_cycle = ehci->intr_unlink_cycle; - - /* New entries go at the end of the intr_unlink list */ - list_add_tail(&qh->unlink_node, &ehci->intr_unlink); - - if (ehci->intr_unlinking) - ; /* Avoid recursive calls */ - else if (ehci->rh_state < EHCI_RH_RUNNING) - ehci_handle_intr_unlinks(ehci); - else if (ehci->intr_unlink.next == &qh->unlink_node) { - ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true); - ++ehci->intr_unlink_cycle; - } -} - -static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - struct ehci_qh_hw *hw = qh->hw; - int rc; - - qh->qh_state = QH_STATE_IDLE; - hw->hw_next = EHCI_LIST_END(ehci); - - if (!list_empty(&qh->qtd_list)) - qh_completions(ehci, qh); - - /* reschedule QH iff another request is queued */ - if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) { - rc = qh_schedule(ehci, qh); - if (rc == 0) { - qh_refresh(ehci, qh); - qh_link_periodic(ehci, qh); - } - - /* An error here likely indicates handshake failure - * or no space left in the schedule. Neither fault - * should happen often ... - * - * FIXME kill the now-dysfunctional queued urbs - */ - else { - ehci_err(ehci, "can't reschedule qh %p, err %d\n", - qh, rc); - } - } - - /* maybe turn off periodic schedule */ - --ehci->intr_count; - disable_periodic(ehci); -} - -/*-------------------------------------------------------------------------*/ - -static int check_period ( - struct ehci_hcd *ehci, - unsigned frame, - unsigned uframe, - unsigned period, - unsigned usecs -) { - int claimed; - - /* complete split running into next frame? - * given FSTN support, we could sometimes check... - */ - if (uframe >= 8) - return 0; - - /* convert "usecs we need" to "max already claimed" */ - usecs = ehci->uframe_periodic_max - usecs; - - /* we "know" 2 and 4 uframe intervals were rejected; so - * for period 0, check _every_ microframe in the schedule. - */ - if (unlikely (period == 0)) { - do { - for (uframe = 0; uframe < 7; uframe++) { - claimed = periodic_usecs (ehci, frame, uframe); - if (claimed > usecs) - return 0; - } - } while ((frame += 1) < ehci->periodic_size); - - /* just check the specified uframe, at that period */ - } else { - do { - claimed = periodic_usecs (ehci, frame, uframe); - if (claimed > usecs) - return 0; - } while ((frame += period) < ehci->periodic_size); - } - - // success! - return 1; -} - -static int check_intr_schedule ( - struct ehci_hcd *ehci, - unsigned frame, - unsigned uframe, - const struct ehci_qh *qh, - __hc32 *c_maskp -) -{ - int retval = -ENOSPC; - u8 mask = 0; - - if (qh->c_usecs && uframe >= 6) /* FSTN territory? */ - goto done; - - if (!check_period (ehci, frame, uframe, qh->period, qh->usecs)) - goto done; - if (!qh->c_usecs) { - retval = 0; - *c_maskp = 0; - goto done; - } - -#ifdef CONFIG_USB_EHCI_TT_NEWSCHED - if (tt_available (ehci, qh->period, qh->dev, frame, uframe, - qh->tt_usecs)) { - unsigned i; - - /* TODO : this may need FSTN for SSPLIT in uframe 5. */ - for (i=uframe+1; i<8 && iperiod, qh->c_usecs)) - goto done; - else - mask |= 1 << i; - - retval = 0; - - *c_maskp = cpu_to_hc32(ehci, mask << 8); - } -#else - /* Make sure this tt's buffer is also available for CSPLITs. - * We pessimize a bit; probably the typical full speed case - * doesn't need the second CSPLIT. - * - * NOTE: both SPLIT and CSPLIT could be checked in just - * one smart pass... - */ - mask = 0x03 << (uframe + qh->gap_uf); - *c_maskp = cpu_to_hc32(ehci, mask << 8); - - mask |= 1 << uframe; - if (tt_no_collision (ehci, qh->period, qh->dev, frame, mask)) { - if (!check_period (ehci, frame, uframe + qh->gap_uf + 1, - qh->period, qh->c_usecs)) - goto done; - if (!check_period (ehci, frame, uframe + qh->gap_uf, - qh->period, qh->c_usecs)) - goto done; - retval = 0; - } -#endif -done: - return retval; -} - -/* "first fit" scheduling policy used the first time through, - * or when the previous schedule slot can't be re-used. - */ -static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - int status; - unsigned uframe; - __hc32 c_mask; - unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ - struct ehci_qh_hw *hw = qh->hw; - - hw->hw_next = EHCI_LIST_END(ehci); - frame = qh->start; - - /* reuse the previous schedule slots, if we can */ - if (frame < qh->period) { - uframe = ffs(hc32_to_cpup(ehci, &hw->hw_info2) & QH_SMASK); - status = check_intr_schedule (ehci, frame, --uframe, - qh, &c_mask); - } else { - uframe = 0; - c_mask = 0; - status = -ENOSPC; - } - - /* else scan the schedule to find a group of slots such that all - * uframes have enough periodic bandwidth available. - */ - if (status) { - /* "normal" case, uframing flexible except with splits */ - if (qh->period) { - int i; - - for (i = qh->period; status && i > 0; --i) { - frame = ++ehci->random_frame % qh->period; - for (uframe = 0; uframe < 8; uframe++) { - status = check_intr_schedule (ehci, - frame, uframe, qh, - &c_mask); - if (status == 0) - break; - } - } - - /* qh->period == 0 means every uframe */ - } else { - frame = 0; - status = check_intr_schedule (ehci, 0, 0, qh, &c_mask); - } - if (status) - goto done; - qh->start = frame; - - /* reset S-frame and (maybe) C-frame masks */ - hw->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK)); - hw->hw_info2 |= qh->period - ? cpu_to_hc32(ehci, 1 << uframe) - : cpu_to_hc32(ehci, QH_SMASK); - hw->hw_info2 |= c_mask; - } else - ehci_dbg (ehci, "reused qh %p schedule\n", qh); - -done: - return status; -} - -static int intr_submit ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *qtd_list, - gfp_t mem_flags -) { - unsigned epnum; - unsigned long flags; - struct ehci_qh *qh; - int status; - struct list_head empty; - - /* get endpoint and transfer/schedule data */ - epnum = urb->ep->desc.bEndpointAddress; - - spin_lock_irqsave (&ehci->lock, flags); - - if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { - status = -ESHUTDOWN; - goto done_not_linked; - } - status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); - if (unlikely(status)) - goto done_not_linked; - - /* get qh and force any scheduling errors */ - INIT_LIST_HEAD (&empty); - qh = qh_append_tds(ehci, urb, &empty, epnum, &urb->ep->hcpriv); - if (qh == NULL) { - status = -ENOMEM; - goto done; - } - if (qh->qh_state == QH_STATE_IDLE) { - if ((status = qh_schedule (ehci, qh)) != 0) - goto done; - } - - /* then queue the urb's tds to the qh */ - qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv); - BUG_ON (qh == NULL); - - /* stuff into the periodic schedule */ - if (qh->qh_state == QH_STATE_IDLE) { - qh_refresh(ehci, qh); - qh_link_periodic(ehci, qh); - } - - /* ... update usbfs periodic stats */ - ehci_to_hcd(ehci)->self.bandwidth_int_reqs++; - -done: - if (unlikely(status)) - usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); -done_not_linked: - spin_unlock_irqrestore (&ehci->lock, flags); - if (status) - qtd_list_free (ehci, urb, qtd_list); - - return status; -} - -static void scan_intr(struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - - list_for_each_entry_safe(qh, ehci->qh_scan_next, &ehci->intr_qh_list, - intr_node) { - - /* clean any finished work for this qh */ - if (!list_empty(&qh->qtd_list)) { - int temp; - - /* - * Unlinks could happen here; completion reporting - * drops the lock. That's why ehci->qh_scan_next - * always holds the next qh to scan; if the next qh - * gets unlinked then ehci->qh_scan_next is adjusted - * in qh_unlink_periodic(). - */ - temp = qh_completions(ehci, qh); - if (unlikely(temp || (list_empty(&qh->qtd_list) && - qh->qh_state == QH_STATE_LINKED))) - start_unlink_intr(ehci, qh); - } - } -} - -/*-------------------------------------------------------------------------*/ - -/* ehci_iso_stream ops work with both ITD and SITD */ - -static struct ehci_iso_stream * -iso_stream_alloc (gfp_t mem_flags) -{ - struct ehci_iso_stream *stream; - - stream = kzalloc(sizeof *stream, mem_flags); - if (likely (stream != NULL)) { - INIT_LIST_HEAD(&stream->td_list); - INIT_LIST_HEAD(&stream->free_list); - stream->next_uframe = -1; - } - return stream; -} - -static void -iso_stream_init ( - struct ehci_hcd *ehci, - struct ehci_iso_stream *stream, - struct usb_device *dev, - int pipe, - unsigned interval -) -{ - static const u8 smask_out [] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f }; - - u32 buf1; - unsigned epnum, maxp; - int is_input; - long bandwidth; - - /* - * this might be a "high bandwidth" highspeed endpoint, - * as encoded in the ep descriptor's wMaxPacket field - */ - epnum = usb_pipeendpoint (pipe); - is_input = usb_pipein (pipe) ? USB_DIR_IN : 0; - maxp = usb_maxpacket(dev, pipe, !is_input); - if (is_input) { - buf1 = (1 << 11); - } else { - buf1 = 0; - } - - /* knows about ITD vs SITD */ - if (dev->speed == USB_SPEED_HIGH) { - unsigned multi = hb_mult(maxp); - - stream->highspeed = 1; - - maxp = max_packet(maxp); - buf1 |= maxp; - maxp *= multi; - - stream->buf0 = cpu_to_hc32(ehci, (epnum << 8) | dev->devnum); - stream->buf1 = cpu_to_hc32(ehci, buf1); - stream->buf2 = cpu_to_hc32(ehci, multi); - - /* usbfs wants to report the average usecs per frame tied up - * when transfers on this endpoint are scheduled ... - */ - stream->usecs = HS_USECS_ISO (maxp); - bandwidth = stream->usecs * 8; - bandwidth /= interval; - - } else { - u32 addr; - int think_time; - int hs_transfers; - - addr = dev->ttport << 24; - if (!ehci_is_TDI(ehci) - || (dev->tt->hub != - ehci_to_hcd(ehci)->self.root_hub)) - addr |= dev->tt->hub->devnum << 16; - addr |= epnum << 8; - addr |= dev->devnum; - stream->usecs = HS_USECS_ISO (maxp); - think_time = dev->tt ? dev->tt->think_time : 0; - stream->tt_usecs = NS_TO_US (think_time + usb_calc_bus_time ( - dev->speed, is_input, 1, maxp)); - hs_transfers = max (1u, (maxp + 187) / 188); - if (is_input) { - u32 tmp; - - addr |= 1 << 31; - stream->c_usecs = stream->usecs; - stream->usecs = HS_USECS_ISO (1); - stream->raw_mask = 1; - - /* c-mask as specified in USB 2.0 11.18.4 3.c */ - tmp = (1 << (hs_transfers + 2)) - 1; - stream->raw_mask |= tmp << (8 + 2); - } else - stream->raw_mask = smask_out [hs_transfers - 1]; - bandwidth = stream->usecs + stream->c_usecs; - bandwidth /= interval << 3; - - /* stream->splits gets created from raw_mask later */ - stream->address = cpu_to_hc32(ehci, addr); - } - stream->bandwidth = bandwidth; - - stream->udev = dev; - - stream->bEndpointAddress = is_input | epnum; - stream->interval = interval; - stream->maxp = maxp; -} - -static struct ehci_iso_stream * -iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) -{ - unsigned epnum; - struct ehci_iso_stream *stream; - struct usb_host_endpoint *ep; - unsigned long flags; - - epnum = usb_pipeendpoint (urb->pipe); - if (usb_pipein(urb->pipe)) - ep = urb->dev->ep_in[epnum]; - else - ep = urb->dev->ep_out[epnum]; - - spin_lock_irqsave (&ehci->lock, flags); - stream = ep->hcpriv; - - if (unlikely (stream == NULL)) { - stream = iso_stream_alloc(GFP_ATOMIC); - if (likely (stream != NULL)) { - ep->hcpriv = stream; - stream->ep = ep; - iso_stream_init(ehci, stream, urb->dev, urb->pipe, - urb->interval); - } - - /* if dev->ep [epnum] is a QH, hw is set */ - } else if (unlikely (stream->hw != NULL)) { - ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n", - urb->dev->devpath, epnum, - usb_pipein(urb->pipe) ? "in" : "out"); - stream = NULL; - } - - spin_unlock_irqrestore (&ehci->lock, flags); - return stream; -} - -/*-------------------------------------------------------------------------*/ - -/* ehci_iso_sched ops can be ITD-only or SITD-only */ - -static struct ehci_iso_sched * -iso_sched_alloc (unsigned packets, gfp_t mem_flags) -{ - struct ehci_iso_sched *iso_sched; - int size = sizeof *iso_sched; - - size += packets * sizeof (struct ehci_iso_packet); - iso_sched = kzalloc(size, mem_flags); - if (likely (iso_sched != NULL)) { - INIT_LIST_HEAD (&iso_sched->td_list); - } - return iso_sched; -} - -static inline void -itd_sched_init( - struct ehci_hcd *ehci, - struct ehci_iso_sched *iso_sched, - struct ehci_iso_stream *stream, - struct urb *urb -) -{ - unsigned i; - dma_addr_t dma = urb->transfer_dma; - - /* how many uframes are needed for these transfers */ - iso_sched->span = urb->number_of_packets * stream->interval; - - /* figure out per-uframe itd fields that we'll need later - * when we fit new itds into the schedule. - */ - for (i = 0; i < urb->number_of_packets; i++) { - struct ehci_iso_packet *uframe = &iso_sched->packet [i]; - unsigned length; - dma_addr_t buf; - u32 trans; - - length = urb->iso_frame_desc [i].length; - buf = dma + urb->iso_frame_desc [i].offset; - - trans = EHCI_ISOC_ACTIVE; - trans |= buf & 0x0fff; - if (unlikely (((i + 1) == urb->number_of_packets)) - && !(urb->transfer_flags & URB_NO_INTERRUPT)) - trans |= EHCI_ITD_IOC; - trans |= length << 16; - uframe->transaction = cpu_to_hc32(ehci, trans); - - /* might need to cross a buffer page within a uframe */ - uframe->bufp = (buf & ~(u64)0x0fff); - buf += length; - if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff)))) - uframe->cross = 1; - } -} - -static void -iso_sched_free ( - struct ehci_iso_stream *stream, - struct ehci_iso_sched *iso_sched -) -{ - if (!iso_sched) - return; - // caller must hold ehci->lock! - list_splice (&iso_sched->td_list, &stream->free_list); - kfree (iso_sched); -} - -static int -itd_urb_transaction ( - struct ehci_iso_stream *stream, - struct ehci_hcd *ehci, - struct urb *urb, - gfp_t mem_flags -) -{ - struct ehci_itd *itd; - dma_addr_t itd_dma; - int i; - unsigned num_itds; - struct ehci_iso_sched *sched; - unsigned long flags; - - sched = iso_sched_alloc (urb->number_of_packets, mem_flags); - if (unlikely (sched == NULL)) - return -ENOMEM; - - itd_sched_init(ehci, sched, stream, urb); - - if (urb->interval < 8) - num_itds = 1 + (sched->span + 7) / 8; - else - num_itds = urb->number_of_packets; - - /* allocate/init ITDs */ - spin_lock_irqsave (&ehci->lock, flags); - for (i = 0; i < num_itds; i++) { - - /* - * Use iTDs from the free list, but not iTDs that may - * still be in use by the hardware. - */ - if (likely(!list_empty(&stream->free_list))) { - itd = list_first_entry(&stream->free_list, - struct ehci_itd, itd_list); - if (itd->frame == ehci->now_frame) - goto alloc_itd; - list_del (&itd->itd_list); - itd_dma = itd->itd_dma; - } else { - alloc_itd: - spin_unlock_irqrestore (&ehci->lock, flags); - itd = dma_pool_alloc (ehci->itd_pool, mem_flags, - &itd_dma); - spin_lock_irqsave (&ehci->lock, flags); - if (!itd) { - iso_sched_free(stream, sched); - spin_unlock_irqrestore(&ehci->lock, flags); - return -ENOMEM; - } - } - - memset (itd, 0, sizeof *itd); - itd->itd_dma = itd_dma; - itd->frame = 9999; /* an invalid value */ - list_add (&itd->itd_list, &sched->td_list); - } - spin_unlock_irqrestore (&ehci->lock, flags); - - /* temporarily store schedule info in hcpriv */ - urb->hcpriv = sched; - urb->error_count = 0; - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static inline int -itd_slot_ok ( - struct ehci_hcd *ehci, - u32 mod, - u32 uframe, - u8 usecs, - u32 period -) -{ - uframe %= period; - do { - /* can't commit more than uframe_periodic_max usec */ - if (periodic_usecs (ehci, uframe >> 3, uframe & 0x7) - > (ehci->uframe_periodic_max - usecs)) - return 0; - - /* we know urb->interval is 2^N uframes */ - uframe += period; - } while (uframe < mod); - return 1; -} - -static inline int -sitd_slot_ok ( - struct ehci_hcd *ehci, - u32 mod, - struct ehci_iso_stream *stream, - u32 uframe, - struct ehci_iso_sched *sched, - u32 period_uframes -) -{ - u32 mask, tmp; - u32 frame, uf; - - mask = stream->raw_mask << (uframe & 7); - - /* for IN, don't wrap CSPLIT into the next frame */ - if (mask & ~0xffff) - return 0; - - /* check bandwidth */ - uframe %= period_uframes; - frame = uframe >> 3; - -#ifdef CONFIG_USB_EHCI_TT_NEWSCHED - /* The tt's fullspeed bus bandwidth must be available. - * tt_available scheduling guarantees 10+% for control/bulk. - */ - uf = uframe & 7; - if (!tt_available(ehci, period_uframes >> 3, - stream->udev, frame, uf, stream->tt_usecs)) - return 0; -#else - /* tt must be idle for start(s), any gap, and csplit. - * assume scheduling slop leaves 10+% for control/bulk. - */ - if (!tt_no_collision(ehci, period_uframes >> 3, - stream->udev, frame, mask)) - return 0; -#endif - - /* this multi-pass logic is simple, but performance may - * suffer when the schedule data isn't cached. - */ - do { - u32 max_used; - - frame = uframe >> 3; - uf = uframe & 7; - - /* check starts (OUT uses more than one) */ - max_used = ehci->uframe_periodic_max - stream->usecs; - for (tmp = stream->raw_mask & 0xff; tmp; tmp >>= 1, uf++) { - if (periodic_usecs (ehci, frame, uf) > max_used) - return 0; - } - - /* for IN, check CSPLIT */ - if (stream->c_usecs) { - uf = uframe & 7; - max_used = ehci->uframe_periodic_max - stream->c_usecs; - do { - tmp = 1 << uf; - tmp <<= 8; - if ((stream->raw_mask & tmp) == 0) - continue; - if (periodic_usecs (ehci, frame, uf) - > max_used) - return 0; - } while (++uf < 8); - } - - /* we know urb->interval is 2^N uframes */ - uframe += period_uframes; - } while (uframe < mod); - - stream->splits = cpu_to_hc32(ehci, stream->raw_mask << (uframe & 7)); - return 1; -} - -/* - * This scheduler plans almost as far into the future as it has actual - * periodic schedule slots. (Affected by TUNE_FLS, which defaults to - * "as small as possible" to be cache-friendlier.) That limits the size - * transfers you can stream reliably; avoid more than 64 msec per urb. - * Also avoid queue depths of less than ehci's worst irq latency (affected - * by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter, - * and other factors); or more than about 230 msec total (for portability, - * given EHCI_TUNE_FLS and the slop). Or, write a smarter scheduler! - */ - -#define SCHEDULING_DELAY 40 /* microframes */ - -static int -iso_stream_schedule ( - struct ehci_hcd *ehci, - struct urb *urb, - struct ehci_iso_stream *stream -) -{ - u32 now, base, next, start, period, span; - int status; - unsigned mod = ehci->periodic_size << 3; - struct ehci_iso_sched *sched = urb->hcpriv; - - period = urb->interval; - span = sched->span; - if (!stream->highspeed) { - period <<= 3; - span <<= 3; - } - - now = ehci_read_frame_index(ehci) & (mod - 1); - - /* Typical case: reuse current schedule, stream is still active. - * Hopefully there are no gaps from the host falling behind - * (irq delays etc). If there are, the behavior depends on - * whether URB_ISO_ASAP is set. - */ - if (likely (!list_empty (&stream->td_list))) { - - /* Take the isochronous scheduling threshold into account */ - if (ehci->i_thresh) - next = now + ehci->i_thresh; /* uframe cache */ - else - next = (now + 2 + 7) & ~0x07; /* full frame cache */ - - /* - * Use ehci->last_iso_frame as the base. There can't be any - * TDs scheduled for earlier than that. - */ - base = ehci->last_iso_frame << 3; - next = (next - base) & (mod - 1); - start = (stream->next_uframe - base) & (mod - 1); - - /* Is the schedule already full? */ - if (unlikely(start < period)) { - ehci_dbg(ehci, "iso sched full %p (%u-%u < %u mod %u)\n", - urb, stream->next_uframe, base, - period, mod); - status = -ENOSPC; - goto fail; - } - - /* Behind the scheduling threshold? */ - if (unlikely(start < next)) { - unsigned now2 = (now - base) & (mod - 1); - - /* USB_ISO_ASAP: Round up to the first available slot */ - if (urb->transfer_flags & URB_ISO_ASAP) - start += (next - start + period - 1) & -period; - - /* - * Not ASAP: Use the next slot in the stream, - * no matter what. - */ - else if (start + span - period < now2) { - ehci_dbg(ehci, "iso underrun %p (%u+%u < %u)\n", - urb, start + base, - span - period, now2 + base); - } - } - - start += base; - } - - /* need to schedule; when's the next (u)frame we could start? - * this is bigger than ehci->i_thresh allows; scheduling itself - * isn't free, the delay should handle reasonably slow cpus. it - * can also help high bandwidth if the dma and irq loads don't - * jump until after the queue is primed. - */ - else { - int done = 0; - - base = now & ~0x07; - start = base + SCHEDULING_DELAY; - - /* find a uframe slot with enough bandwidth. - * Early uframes are more precious because full-speed - * iso IN transfers can't use late uframes, - * and therefore they should be allocated last. - */ - next = start; - start += period; - do { - start--; - /* check schedule: enough space? */ - if (stream->highspeed) { - if (itd_slot_ok(ehci, mod, start, - stream->usecs, period)) - done = 1; - } else { - if ((start % 8) >= 6) - continue; - if (sitd_slot_ok(ehci, mod, stream, - start, sched, period)) - done = 1; - } - } while (start > next && !done); - - /* no room in the schedule */ - if (!done) { - ehci_dbg(ehci, "iso sched full %p", urb); - status = -ENOSPC; - goto fail; - } - } - - /* Tried to schedule too far into the future? */ - if (unlikely(start - base + span - period >= mod)) { - ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n", - urb, start - base, span - period, mod); - status = -EFBIG; - goto fail; - } - - stream->next_uframe = start & (mod - 1); - - /* report high speed start in uframes; full speed, in frames */ - urb->start_frame = stream->next_uframe; - if (!stream->highspeed) - urb->start_frame >>= 3; - - /* Make sure scan_isoc() sees these */ - if (ehci->isoc_count == 0) - ehci->last_iso_frame = now >> 3; - return 0; - - fail: - iso_sched_free(stream, sched); - urb->hcpriv = NULL; - return status; -} - -/*-------------------------------------------------------------------------*/ - -static inline void -itd_init(struct ehci_hcd *ehci, struct ehci_iso_stream *stream, - struct ehci_itd *itd) -{ - int i; - - /* it's been recently zeroed */ - itd->hw_next = EHCI_LIST_END(ehci); - itd->hw_bufp [0] = stream->buf0; - itd->hw_bufp [1] = stream->buf1; - itd->hw_bufp [2] = stream->buf2; - - for (i = 0; i < 8; i++) - itd->index[i] = -1; - - /* All other fields are filled when scheduling */ -} - -static inline void -itd_patch( - struct ehci_hcd *ehci, - struct ehci_itd *itd, - struct ehci_iso_sched *iso_sched, - unsigned index, - u16 uframe -) -{ - struct ehci_iso_packet *uf = &iso_sched->packet [index]; - unsigned pg = itd->pg; - - // BUG_ON (pg == 6 && uf->cross); - - uframe &= 0x07; - itd->index [uframe] = index; - - itd->hw_transaction[uframe] = uf->transaction; - itd->hw_transaction[uframe] |= cpu_to_hc32(ehci, pg << 12); - itd->hw_bufp[pg] |= cpu_to_hc32(ehci, uf->bufp & ~(u32)0); - itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(uf->bufp >> 32)); - - /* iso_frame_desc[].offset must be strictly increasing */ - if (unlikely (uf->cross)) { - u64 bufp = uf->bufp + 4096; - - itd->pg = ++pg; - itd->hw_bufp[pg] |= cpu_to_hc32(ehci, bufp & ~(u32)0); - itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(bufp >> 32)); - } -} - -static inline void -itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) -{ - union ehci_shadow *prev = &ehci->pshadow[frame]; - __hc32 *hw_p = &ehci->periodic[frame]; - union ehci_shadow here = *prev; - __hc32 type = 0; - - /* skip any iso nodes which might belong to previous microframes */ - while (here.ptr) { - type = Q_NEXT_TYPE(ehci, *hw_p); - if (type == cpu_to_hc32(ehci, Q_TYPE_QH)) - break; - prev = periodic_next_shadow(ehci, prev, type); - hw_p = shadow_next_periodic(ehci, &here, type); - here = *prev; - } - - itd->itd_next = here; - itd->hw_next = *hw_p; - prev->itd = itd; - itd->frame = frame; - wmb (); - *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); -} - -/* fit urb's itds into the selected schedule slot; activate as needed */ -static void itd_link_urb( - struct ehci_hcd *ehci, - struct urb *urb, - unsigned mod, - struct ehci_iso_stream *stream -) -{ - int packet; - unsigned next_uframe, uframe, frame; - struct ehci_iso_sched *iso_sched = urb->hcpriv; - struct ehci_itd *itd; - - next_uframe = stream->next_uframe & (mod - 1); - - if (unlikely (list_empty(&stream->td_list))) { - ehci_to_hcd(ehci)->self.bandwidth_allocated - += stream->bandwidth; - ehci_vdbg (ehci, - "schedule devp %s ep%d%s-iso period %d start %d.%d\n", - urb->dev->devpath, stream->bEndpointAddress & 0x0f, - (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", - urb->interval, - next_uframe >> 3, next_uframe & 0x7); - } - - if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { - if (ehci->amd_pll_fix == 1) - usb_amd_quirk_pll_disable(); - } - - ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; - - /* fill iTDs uframe by uframe */ - for (packet = 0, itd = NULL; packet < urb->number_of_packets; ) { - if (itd == NULL) { - /* ASSERT: we have all necessary itds */ - // BUG_ON (list_empty (&iso_sched->td_list)); - - /* ASSERT: no itds for this endpoint in this uframe */ - - itd = list_entry (iso_sched->td_list.next, - struct ehci_itd, itd_list); - list_move_tail (&itd->itd_list, &stream->td_list); - itd->stream = stream; - itd->urb = urb; - itd_init (ehci, stream, itd); - } - - uframe = next_uframe & 0x07; - frame = next_uframe >> 3; - - itd_patch(ehci, itd, iso_sched, packet, uframe); - - next_uframe += stream->interval; - next_uframe &= mod - 1; - packet++; - - /* link completed itds into the schedule */ - if (((next_uframe >> 3) != frame) - || packet == urb->number_of_packets) { - itd_link(ehci, frame & (ehci->periodic_size - 1), itd); - itd = NULL; - } - } - stream->next_uframe = next_uframe; - - /* don't need that schedule data any more */ - iso_sched_free (stream, iso_sched); - urb->hcpriv = stream; - - ++ehci->isoc_count; - enable_periodic(ehci); -} - -#define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR) - -/* Process and recycle a completed ITD. Return true iff its urb completed, - * and hence its completion callback probably added things to the hardware - * schedule. - * - * Note that we carefully avoid recycling this descriptor until after any - * completion callback runs, so that it won't be reused quickly. That is, - * assuming (a) no more than two urbs per frame on this endpoint, and also - * (b) only this endpoint's completions submit URBs. It seems some silicon - * corrupts things if you reuse completed descriptors very quickly... - */ -static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) -{ - struct urb *urb = itd->urb; - struct usb_iso_packet_descriptor *desc; - u32 t; - unsigned uframe; - int urb_index = -1; - struct ehci_iso_stream *stream = itd->stream; - struct usb_device *dev; - bool retval = false; - - /* for each uframe with a packet */ - for (uframe = 0; uframe < 8; uframe++) { - if (likely (itd->index[uframe] == -1)) - continue; - urb_index = itd->index[uframe]; - desc = &urb->iso_frame_desc [urb_index]; - - t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]); - itd->hw_transaction [uframe] = 0; - - /* report transfer status */ - if (unlikely (t & ISO_ERRS)) { - urb->error_count++; - if (t & EHCI_ISOC_BUF_ERR) - desc->status = usb_pipein (urb->pipe) - ? -ENOSR /* hc couldn't read */ - : -ECOMM; /* hc couldn't write */ - else if (t & EHCI_ISOC_BABBLE) - desc->status = -EOVERFLOW; - else /* (t & EHCI_ISOC_XACTERR) */ - desc->status = -EPROTO; - - /* HC need not update length with this error */ - if (!(t & EHCI_ISOC_BABBLE)) { - desc->actual_length = EHCI_ITD_LENGTH(t); - urb->actual_length += desc->actual_length; - } - } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) { - desc->status = 0; - desc->actual_length = EHCI_ITD_LENGTH(t); - urb->actual_length += desc->actual_length; - } else { - /* URB was too late */ - urb->error_count++; - } - } - - /* handle completion now? */ - if (likely ((urb_index + 1) != urb->number_of_packets)) - goto done; - - /* ASSERT: it's really the last itd for this urb - list_for_each_entry (itd, &stream->td_list, itd_list) - BUG_ON (itd->urb == urb); - */ - - /* give urb back to the driver; completion often (re)submits */ - dev = urb->dev; - ehci_urb_done(ehci, urb, 0); - retval = true; - urb = NULL; - - --ehci->isoc_count; - disable_periodic(ehci); - - ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { - if (ehci->amd_pll_fix == 1) - usb_amd_quirk_pll_enable(); - } - - if (unlikely(list_is_singular(&stream->td_list))) { - ehci_to_hcd(ehci)->self.bandwidth_allocated - -= stream->bandwidth; - ehci_vdbg (ehci, - "deschedule devp %s ep%d%s-iso\n", - dev->devpath, stream->bEndpointAddress & 0x0f, - (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); - } - -done: - itd->urb = NULL; - - /* Add to the end of the free list for later reuse */ - list_move_tail(&itd->itd_list, &stream->free_list); - - /* Recycle the iTDs when the pipeline is empty (ep no longer in use) */ - if (list_empty(&stream->td_list)) { - list_splice_tail_init(&stream->free_list, - &ehci->cached_itd_list); - start_free_itds(ehci); - } - - return retval; -} - -/*-------------------------------------------------------------------------*/ - -static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, - gfp_t mem_flags) -{ - int status = -EINVAL; - unsigned long flags; - struct ehci_iso_stream *stream; - - /* Get iso_stream head */ - stream = iso_stream_find (ehci, urb); - if (unlikely (stream == NULL)) { - ehci_dbg (ehci, "can't get iso stream\n"); - return -ENOMEM; - } - if (unlikely (urb->interval != stream->interval)) { - ehci_dbg (ehci, "can't change iso interval %d --> %d\n", - stream->interval, urb->interval); - goto done; - } - -#ifdef EHCI_URB_TRACE - ehci_dbg (ehci, - "%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n", - __func__, urb->dev->devpath, urb, - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", - urb->transfer_buffer_length, - urb->number_of_packets, urb->interval, - stream); -#endif - - /* allocate ITDs w/o locking anything */ - status = itd_urb_transaction (stream, ehci, urb, mem_flags); - if (unlikely (status < 0)) { - ehci_dbg (ehci, "can't init itds\n"); - goto done; - } - - /* schedule ... need to lock */ - spin_lock_irqsave (&ehci->lock, flags); - if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { - status = -ESHUTDOWN; - goto done_not_linked; - } - status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); - if (unlikely(status)) - goto done_not_linked; - status = iso_stream_schedule(ehci, urb, stream); - if (likely (status == 0)) - itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); - else - usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); - done_not_linked: - spin_unlock_irqrestore (&ehci->lock, flags); - done: - return status; -} - -/*-------------------------------------------------------------------------*/ - -/* - * "Split ISO TDs" ... used for USB 1.1 devices going through the - * TTs in USB 2.0 hubs. These need microframe scheduling. - */ - -static inline void -sitd_sched_init( - struct ehci_hcd *ehci, - struct ehci_iso_sched *iso_sched, - struct ehci_iso_stream *stream, - struct urb *urb -) -{ - unsigned i; - dma_addr_t dma = urb->transfer_dma; - - /* how many frames are needed for these transfers */ - iso_sched->span = urb->number_of_packets * stream->interval; - - /* figure out per-frame sitd fields that we'll need later - * when we fit new sitds into the schedule. - */ - for (i = 0; i < urb->number_of_packets; i++) { - struct ehci_iso_packet *packet = &iso_sched->packet [i]; - unsigned length; - dma_addr_t buf; - u32 trans; - - length = urb->iso_frame_desc [i].length & 0x03ff; - buf = dma + urb->iso_frame_desc [i].offset; - - trans = SITD_STS_ACTIVE; - if (((i + 1) == urb->number_of_packets) - && !(urb->transfer_flags & URB_NO_INTERRUPT)) - trans |= SITD_IOC; - trans |= length << 16; - packet->transaction = cpu_to_hc32(ehci, trans); - - /* might need to cross a buffer page within a td */ - packet->bufp = buf; - packet->buf1 = (buf + length) & ~0x0fff; - if (packet->buf1 != (buf & ~(u64)0x0fff)) - packet->cross = 1; - - /* OUT uses multiple start-splits */ - if (stream->bEndpointAddress & USB_DIR_IN) - continue; - length = (length + 187) / 188; - if (length > 1) /* BEGIN vs ALL */ - length |= 1 << 3; - packet->buf1 |= length; - } -} - -static int -sitd_urb_transaction ( - struct ehci_iso_stream *stream, - struct ehci_hcd *ehci, - struct urb *urb, - gfp_t mem_flags -) -{ - struct ehci_sitd *sitd; - dma_addr_t sitd_dma; - int i; - struct ehci_iso_sched *iso_sched; - unsigned long flags; - - iso_sched = iso_sched_alloc (urb->number_of_packets, mem_flags); - if (iso_sched == NULL) - return -ENOMEM; - - sitd_sched_init(ehci, iso_sched, stream, urb); - - /* allocate/init sITDs */ - spin_lock_irqsave (&ehci->lock, flags); - for (i = 0; i < urb->number_of_packets; i++) { - - /* NOTE: for now, we don't try to handle wraparound cases - * for IN (using sitd->hw_backpointer, like a FSTN), which - * means we never need two sitds for full speed packets. - */ - - /* - * Use siTDs from the free list, but not siTDs that may - * still be in use by the hardware. - */ - if (likely(!list_empty(&stream->free_list))) { - sitd = list_first_entry(&stream->free_list, - struct ehci_sitd, sitd_list); - if (sitd->frame == ehci->now_frame) - goto alloc_sitd; - list_del (&sitd->sitd_list); - sitd_dma = sitd->sitd_dma; - } else { - alloc_sitd: - spin_unlock_irqrestore (&ehci->lock, flags); - sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags, - &sitd_dma); - spin_lock_irqsave (&ehci->lock, flags); - if (!sitd) { - iso_sched_free(stream, iso_sched); - spin_unlock_irqrestore(&ehci->lock, flags); - return -ENOMEM; - } - } - - memset (sitd, 0, sizeof *sitd); - sitd->sitd_dma = sitd_dma; - sitd->frame = 9999; /* an invalid value */ - list_add (&sitd->sitd_list, &iso_sched->td_list); - } - - /* temporarily store schedule info in hcpriv */ - urb->hcpriv = iso_sched; - urb->error_count = 0; - - spin_unlock_irqrestore (&ehci->lock, flags); - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static inline void -sitd_patch( - struct ehci_hcd *ehci, - struct ehci_iso_stream *stream, - struct ehci_sitd *sitd, - struct ehci_iso_sched *iso_sched, - unsigned index -) -{ - struct ehci_iso_packet *uf = &iso_sched->packet [index]; - u64 bufp = uf->bufp; - - sitd->hw_next = EHCI_LIST_END(ehci); - sitd->hw_fullspeed_ep = stream->address; - sitd->hw_uframe = stream->splits; - sitd->hw_results = uf->transaction; - sitd->hw_backpointer = EHCI_LIST_END(ehci); - - bufp = uf->bufp; - sitd->hw_buf[0] = cpu_to_hc32(ehci, bufp); - sitd->hw_buf_hi[0] = cpu_to_hc32(ehci, bufp >> 32); - - sitd->hw_buf[1] = cpu_to_hc32(ehci, uf->buf1); - if (uf->cross) - bufp += 4096; - sitd->hw_buf_hi[1] = cpu_to_hc32(ehci, bufp >> 32); - sitd->index = index; -} - -static inline void -sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd) -{ - /* note: sitd ordering could matter (CSPLIT then SSPLIT) */ - sitd->sitd_next = ehci->pshadow [frame]; - sitd->hw_next = ehci->periodic [frame]; - ehci->pshadow [frame].sitd = sitd; - sitd->frame = frame; - wmb (); - ehci->periodic[frame] = cpu_to_hc32(ehci, sitd->sitd_dma | Q_TYPE_SITD); -} - -/* fit urb's sitds into the selected schedule slot; activate as needed */ -static void sitd_link_urb( - struct ehci_hcd *ehci, - struct urb *urb, - unsigned mod, - struct ehci_iso_stream *stream -) -{ - int packet; - unsigned next_uframe; - struct ehci_iso_sched *sched = urb->hcpriv; - struct ehci_sitd *sitd; - - next_uframe = stream->next_uframe; - - if (list_empty(&stream->td_list)) { - /* usbfs ignores TT bandwidth */ - ehci_to_hcd(ehci)->self.bandwidth_allocated - += stream->bandwidth; - ehci_vdbg (ehci, - "sched devp %s ep%d%s-iso [%d] %dms/%04x\n", - urb->dev->devpath, stream->bEndpointAddress & 0x0f, - (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out", - (next_uframe >> 3) & (ehci->periodic_size - 1), - stream->interval, hc32_to_cpu(ehci, stream->splits)); - } - - if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { - if (ehci->amd_pll_fix == 1) - usb_amd_quirk_pll_disable(); - } - - ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; - - /* fill sITDs frame by frame */ - for (packet = 0, sitd = NULL; - packet < urb->number_of_packets; - packet++) { - - /* ASSERT: we have all necessary sitds */ - BUG_ON (list_empty (&sched->td_list)); - - /* ASSERT: no itds for this endpoint in this frame */ - - sitd = list_entry (sched->td_list.next, - struct ehci_sitd, sitd_list); - list_move_tail (&sitd->sitd_list, &stream->td_list); - sitd->stream = stream; - sitd->urb = urb; - - sitd_patch(ehci, stream, sitd, sched, packet); - sitd_link(ehci, (next_uframe >> 3) & (ehci->periodic_size - 1), - sitd); - - next_uframe += stream->interval << 3; - } - stream->next_uframe = next_uframe & (mod - 1); - - /* don't need that schedule data any more */ - iso_sched_free (stream, sched); - urb->hcpriv = stream; - - ++ehci->isoc_count; - enable_periodic(ehci); -} - -/*-------------------------------------------------------------------------*/ - -#define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \ - | SITD_STS_XACT | SITD_STS_MMF) - -/* Process and recycle a completed SITD. Return true iff its urb completed, - * and hence its completion callback probably added things to the hardware - * schedule. - * - * Note that we carefully avoid recycling this descriptor until after any - * completion callback runs, so that it won't be reused quickly. That is, - * assuming (a) no more than two urbs per frame on this endpoint, and also - * (b) only this endpoint's completions submit URBs. It seems some silicon - * corrupts things if you reuse completed descriptors very quickly... - */ -static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) -{ - struct urb *urb = sitd->urb; - struct usb_iso_packet_descriptor *desc; - u32 t; - int urb_index = -1; - struct ehci_iso_stream *stream = sitd->stream; - struct usb_device *dev; - bool retval = false; - - urb_index = sitd->index; - desc = &urb->iso_frame_desc [urb_index]; - t = hc32_to_cpup(ehci, &sitd->hw_results); - - /* report transfer status */ - if (unlikely(t & SITD_ERRS)) { - urb->error_count++; - if (t & SITD_STS_DBE) - desc->status = usb_pipein (urb->pipe) - ? -ENOSR /* hc couldn't read */ - : -ECOMM; /* hc couldn't write */ - else if (t & SITD_STS_BABBLE) - desc->status = -EOVERFLOW; - else /* XACT, MMF, etc */ - desc->status = -EPROTO; - } else if (unlikely(t & SITD_STS_ACTIVE)) { - /* URB was too late */ - urb->error_count++; - } else { - desc->status = 0; - desc->actual_length = desc->length - SITD_LENGTH(t); - urb->actual_length += desc->actual_length; - } - - /* handle completion now? */ - if ((urb_index + 1) != urb->number_of_packets) - goto done; - - /* ASSERT: it's really the last sitd for this urb - list_for_each_entry (sitd, &stream->td_list, sitd_list) - BUG_ON (sitd->urb == urb); - */ - - /* give urb back to the driver; completion often (re)submits */ - dev = urb->dev; - ehci_urb_done(ehci, urb, 0); - retval = true; - urb = NULL; - - --ehci->isoc_count; - disable_periodic(ehci); - - ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { - if (ehci->amd_pll_fix == 1) - usb_amd_quirk_pll_enable(); - } - - if (list_is_singular(&stream->td_list)) { - ehci_to_hcd(ehci)->self.bandwidth_allocated - -= stream->bandwidth; - ehci_vdbg (ehci, - "deschedule devp %s ep%d%s-iso\n", - dev->devpath, stream->bEndpointAddress & 0x0f, - (stream->bEndpointAddress & USB_DIR_IN) ? "in" : "out"); - } - -done: - sitd->urb = NULL; - - /* Add to the end of the free list for later reuse */ - list_move_tail(&sitd->sitd_list, &stream->free_list); - - /* Recycle the siTDs when the pipeline is empty (ep no longer in use) */ - if (list_empty(&stream->td_list)) { - list_splice_tail_init(&stream->free_list, - &ehci->cached_sitd_list); - start_free_itds(ehci); - } - - return retval; -} - - -static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, - gfp_t mem_flags) -{ - int status = -EINVAL; - unsigned long flags; - struct ehci_iso_stream *stream; - - /* Get iso_stream head */ - stream = iso_stream_find (ehci, urb); - if (stream == NULL) { - ehci_dbg (ehci, "can't get iso stream\n"); - return -ENOMEM; - } - if (urb->interval != stream->interval) { - ehci_dbg (ehci, "can't change iso interval %d --> %d\n", - stream->interval, urb->interval); - goto done; - } - -#ifdef EHCI_URB_TRACE - ehci_dbg (ehci, - "submit %p dev%s ep%d%s-iso len %d\n", - urb, urb->dev->devpath, - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", - urb->transfer_buffer_length); -#endif - - /* allocate SITDs */ - status = sitd_urb_transaction (stream, ehci, urb, mem_flags); - if (status < 0) { - ehci_dbg (ehci, "can't init sitds\n"); - goto done; - } - - /* schedule ... need to lock */ - spin_lock_irqsave (&ehci->lock, flags); - if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { - status = -ESHUTDOWN; - goto done_not_linked; - } - status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); - if (unlikely(status)) - goto done_not_linked; - status = iso_stream_schedule(ehci, urb, stream); - if (status == 0) - sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); - else - usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); - done_not_linked: - spin_unlock_irqrestore (&ehci->lock, flags); - done: - return status; -} - -/*-------------------------------------------------------------------------*/ - -static void scan_isoc(struct ehci_hcd *ehci) -{ - unsigned uf, now_frame, frame; - unsigned fmask = ehci->periodic_size - 1; - bool modified, live; - - /* - * When running, scan from last scan point up to "now" - * else clean up by scanning everything that's left. - * Touches as few pages as possible: cache-friendly. - */ - if (ehci->rh_state >= EHCI_RH_RUNNING) { - uf = ehci_read_frame_index(ehci); - now_frame = (uf >> 3) & fmask; - live = true; - } else { - now_frame = (ehci->last_iso_frame - 1) & fmask; - live = false; - } - ehci->now_frame = now_frame; - - frame = ehci->last_iso_frame; - for (;;) { - union ehci_shadow q, *q_p; - __hc32 type, *hw_p; - -restart: - /* scan each element in frame's queue for completions */ - q_p = &ehci->pshadow [frame]; - hw_p = &ehci->periodic [frame]; - q.ptr = q_p->ptr; - type = Q_NEXT_TYPE(ehci, *hw_p); - modified = false; - - while (q.ptr != NULL) { - switch (hc32_to_cpu(ehci, type)) { - case Q_TYPE_ITD: - /* If this ITD is still active, leave it for - * later processing ... check the next entry. - * No need to check for activity unless the - * frame is current. - */ - if (frame == now_frame && live) { - rmb(); - for (uf = 0; uf < 8; uf++) { - if (q.itd->hw_transaction[uf] & - ITD_ACTIVE(ehci)) - break; - } - if (uf < 8) { - q_p = &q.itd->itd_next; - hw_p = &q.itd->hw_next; - type = Q_NEXT_TYPE(ehci, - q.itd->hw_next); - q = *q_p; - break; - } - } - - /* Take finished ITDs out of the schedule - * and process them: recycle, maybe report - * URB completion. HC won't cache the - * pointer for much longer, if at all. - */ - *q_p = q.itd->itd_next; - if (!ehci->use_dummy_qh || - q.itd->hw_next != EHCI_LIST_END(ehci)) - *hw_p = q.itd->hw_next; - else - *hw_p = ehci->dummy->qh_dma; - type = Q_NEXT_TYPE(ehci, q.itd->hw_next); - wmb(); - modified = itd_complete (ehci, q.itd); - q = *q_p; - break; - case Q_TYPE_SITD: - /* If this SITD is still active, leave it for - * later processing ... check the next entry. - * No need to check for activity unless the - * frame is current. - */ - if (((frame == now_frame) || - (((frame + 1) & fmask) == now_frame)) - && live - && (q.sitd->hw_results & - SITD_ACTIVE(ehci))) { - - q_p = &q.sitd->sitd_next; - hw_p = &q.sitd->hw_next; - type = Q_NEXT_TYPE(ehci, - q.sitd->hw_next); - q = *q_p; - break; - } - - /* Take finished SITDs out of the schedule - * and process them: recycle, maybe report - * URB completion. - */ - *q_p = q.sitd->sitd_next; - if (!ehci->use_dummy_qh || - q.sitd->hw_next != EHCI_LIST_END(ehci)) - *hw_p = q.sitd->hw_next; - else - *hw_p = ehci->dummy->qh_dma; - type = Q_NEXT_TYPE(ehci, q.sitd->hw_next); - wmb(); - modified = sitd_complete (ehci, q.sitd); - q = *q_p; - break; - default: - ehci_dbg(ehci, "corrupt type %d frame %d shadow %p\n", - type, frame, q.ptr); - // BUG (); - /* FALL THROUGH */ - case Q_TYPE_QH: - case Q_TYPE_FSTN: - /* End of the iTDs and siTDs */ - q.ptr = NULL; - break; - } - - /* assume completion callbacks modify the queue */ - if (unlikely(modified && ehci->isoc_count > 0)) - goto restart; - } - - /* Stop when we have reached the current frame */ - if (frame == now_frame) - break; - - /* The last frame may still have active siTDs */ - ehci->last_iso_frame = frame; - frame = (frame + 1) & fmask; - } -} diff --git a/addons/ehci-pci/src/3.10.108/ehci-sysfs.c b/addons/ehci-pci/src/3.10.108/ehci-sysfs.c deleted file mode 100644 index 06590242..00000000 --- a/addons/ehci-pci/src/3.10.108/ehci-sysfs.c +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright (C) 2007 by Alan Stern - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - - -/* Display the ports dedicated to the companion controller */ -static ssize_t show_companion(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ehci_hcd *ehci; - int nports, index, n; - int count = PAGE_SIZE; - char *ptr = buf; - - ehci = hcd_to_ehci(dev_get_drvdata(dev)); - nports = HCS_N_PORTS(ehci->hcs_params); - - for (index = 0; index < nports; ++index) { - if (test_bit(index, &ehci->companion_ports)) { - n = scnprintf(ptr, count, "%d\n", index + 1); - ptr += n; - count -= n; - } - } - return ptr - buf; -} - -/* - * Dedicate or undedicate a port to the companion controller. - * Syntax is "[-]portnum", where a leading '-' sign means - * return control of the port to the EHCI controller. - */ -static ssize_t store_companion(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ehci_hcd *ehci; - int portnum, new_owner; - - ehci = hcd_to_ehci(dev_get_drvdata(dev)); - new_owner = PORT_OWNER; /* Owned by companion */ - if (sscanf(buf, "%d", &portnum) != 1) - return -EINVAL; - if (portnum < 0) { - portnum = - portnum; - new_owner = 0; /* Owned by EHCI */ - } - if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params)) - return -ENOENT; - portnum--; - if (new_owner) - set_bit(portnum, &ehci->companion_ports); - else - clear_bit(portnum, &ehci->companion_ports); - set_owner(ehci, portnum, new_owner); - return count; -} -static DEVICE_ATTR(companion, 0644, show_companion, store_companion); - - -/* - * Display / Set uframe_periodic_max - */ -static ssize_t show_uframe_periodic_max(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ehci_hcd *ehci; - int n; - - ehci = hcd_to_ehci(dev_get_drvdata(dev)); - n = scnprintf(buf, PAGE_SIZE, "%d\n", ehci->uframe_periodic_max); - return n; -} - - -static ssize_t store_uframe_periodic_max(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ehci_hcd *ehci; - unsigned uframe_periodic_max; - unsigned frame, uframe; - unsigned short allocated_max; - unsigned long flags; - ssize_t ret; - - ehci = hcd_to_ehci(dev_get_drvdata(dev)); - if (kstrtouint(buf, 0, &uframe_periodic_max) < 0) - return -EINVAL; - - if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) { - ehci_info(ehci, "rejecting invalid request for " - "uframe_periodic_max=%u\n", uframe_periodic_max); - return -EINVAL; - } - - ret = -EINVAL; - - /* - * lock, so that our checking does not race with possible periodic - * bandwidth allocation through submitting new urbs. - */ - spin_lock_irqsave (&ehci->lock, flags); - - /* - * for request to decrease max periodic bandwidth, we have to check - * every microframe in the schedule to see whether the decrease is - * possible. - */ - if (uframe_periodic_max < ehci->uframe_periodic_max) { - allocated_max = 0; - - for (frame = 0; frame < ehci->periodic_size; ++frame) - for (uframe = 0; uframe < 7; ++uframe) - allocated_max = max(allocated_max, - periodic_usecs (ehci, frame, uframe)); - - if (allocated_max > uframe_periodic_max) { - ehci_info(ehci, - "cannot decrease uframe_periodic_max becase " - "periodic bandwidth is already allocated " - "(%u > %u)\n", - allocated_max, uframe_periodic_max); - goto out_unlock; - } - } - - /* increasing is always ok */ - - ehci_info(ehci, "setting max periodic bandwidth to %u%% " - "(== %u usec/uframe)\n", - 100*uframe_periodic_max/125, uframe_periodic_max); - - if (uframe_periodic_max != 100) - ehci_warn(ehci, "max periodic bandwidth set is non-standard\n"); - - ehci->uframe_periodic_max = uframe_periodic_max; - ret = count; - -out_unlock: - spin_unlock_irqrestore (&ehci->lock, flags); - return ret; -} -static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, store_uframe_periodic_max); - - -static inline int create_sysfs_files(struct ehci_hcd *ehci) -{ - struct device *controller = ehci_to_hcd(ehci)->self.controller; - int i = 0; - - /* with integrated TT there is no companion! */ - if (!ehci_is_TDI(ehci)) - i = device_create_file(controller, &dev_attr_companion); - if (i) - goto out; - - i = device_create_file(controller, &dev_attr_uframe_periodic_max); -out: - return i; -} - -static inline void remove_sysfs_files(struct ehci_hcd *ehci) -{ - struct device *controller = ehci_to_hcd(ehci)->self.controller; - - /* with integrated TT there is no companion! */ - if (!ehci_is_TDI(ehci)) - device_remove_file(controller, &dev_attr_companion); - - device_remove_file(controller, &dev_attr_uframe_periodic_max); -} diff --git a/addons/ehci-pci/src/3.10.108/ehci-timer.c b/addons/ehci-pci/src/3.10.108/ehci-timer.c deleted file mode 100644 index 11e5b32f..00000000 --- a/addons/ehci-pci/src/3.10.108/ehci-timer.c +++ /dev/null @@ -1,401 +0,0 @@ -/* - * Copyright (C) 2012 by Alan Stern - * - * 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. - */ - -/* This file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* Set a bit in the USBCMD register */ -static void ehci_set_command_bit(struct ehci_hcd *ehci, u32 bit) -{ - ehci->command |= bit; - ehci_writel(ehci, ehci->command, &ehci->regs->command); - - /* unblock posted write */ - ehci_readl(ehci, &ehci->regs->command); -} - -/* Clear a bit in the USBCMD register */ -static void ehci_clear_command_bit(struct ehci_hcd *ehci, u32 bit) -{ - ehci->command &= ~bit; - ehci_writel(ehci, ehci->command, &ehci->regs->command); - - /* unblock posted write */ - ehci_readl(ehci, &ehci->regs->command); -} - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI timer support... Now using hrtimers. - * - * Lots of different events are triggered from ehci->hrtimer. Whenever - * the timer routine runs, it checks each possible event; events that are - * currently enabled and whose expiration time has passed get handled. - * The set of enabled events is stored as a collection of bitflags in - * ehci->enabled_hrtimer_events, and they are numbered in order of - * increasing delay values (ranging between 1 ms and 100 ms). - * - * Rather than implementing a sorted list or tree of all pending events, - * we keep track only of the lowest-numbered pending event, in - * ehci->next_hrtimer_event. Whenever ehci->hrtimer gets restarted, its - * expiration time is set to the timeout value for this event. - * - * As a result, events might not get handled right away; the actual delay - * could be anywhere up to twice the requested delay. This doesn't - * matter, because none of the events are especially time-critical. The - * ones that matter most all have a delay of 1 ms, so they will be - * handled after 2 ms at most, which is okay. In addition to this, we - * allow for an expiration range of 1 ms. - */ - -/* - * Delay lengths for the hrtimer event types. - * Keep this list sorted by delay length, in the same order as - * the event types indexed by enum ehci_hrtimer_event in ehci.h. - */ -static unsigned event_delays_ns[] = { - 1 * NSEC_PER_MSEC, /* EHCI_HRTIMER_POLL_ASS */ - 1 * NSEC_PER_MSEC, /* EHCI_HRTIMER_POLL_PSS */ - 1 * NSEC_PER_MSEC, /* EHCI_HRTIMER_POLL_DEAD */ - 1125 * NSEC_PER_USEC, /* EHCI_HRTIMER_UNLINK_INTR */ - 2 * NSEC_PER_MSEC, /* EHCI_HRTIMER_FREE_ITDS */ - 6 * NSEC_PER_MSEC, /* EHCI_HRTIMER_ASYNC_UNLINKS */ - 10 * NSEC_PER_MSEC, /* EHCI_HRTIMER_IAA_WATCHDOG */ - 10 * NSEC_PER_MSEC, /* EHCI_HRTIMER_DISABLE_PERIODIC */ - 15 * NSEC_PER_MSEC, /* EHCI_HRTIMER_DISABLE_ASYNC */ - 100 * NSEC_PER_MSEC, /* EHCI_HRTIMER_IO_WATCHDOG */ -}; - -/* Enable a pending hrtimer event */ -static void ehci_enable_event(struct ehci_hcd *ehci, unsigned event, - bool resched) -{ - ktime_t *timeout = &ehci->hr_timeouts[event]; - - if (resched) - *timeout = ktime_add(ktime_get(), - ktime_set(0, event_delays_ns[event])); - ehci->enabled_hrtimer_events |= (1 << event); - - /* Track only the lowest-numbered pending event */ - if (event < ehci->next_hrtimer_event) { - ehci->next_hrtimer_event = event; - hrtimer_start_range_ns(&ehci->hrtimer, *timeout, - NSEC_PER_MSEC, HRTIMER_MODE_ABS); - } -} - - -/* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */ -static void ehci_poll_ASS(struct ehci_hcd *ehci) -{ - unsigned actual, want; - - /* Don't enable anything if the controller isn't running (e.g., died) */ - if (ehci->rh_state != EHCI_RH_RUNNING) - return; - - want = (ehci->command & CMD_ASE) ? STS_ASS : 0; - actual = ehci_readl(ehci, &ehci->regs->status) & STS_ASS; - - if (want != actual) { - - /* Poll again later, but give up after about 2-4 ms */ - if (ehci->ASS_poll_count++ < 2) { - ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); - return; - } - ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n", - want, actual); - } - ehci->ASS_poll_count = 0; - - /* The status is up-to-date; restart or stop the schedule as needed */ - if (want == 0) { /* Stopped */ - if (ehci->async_count > 0) - ehci_set_command_bit(ehci, CMD_ASE); - - } else { /* Running */ - if (ehci->async_count == 0) { - - /* Turn off the schedule after a while */ - ehci_enable_event(ehci, EHCI_HRTIMER_DISABLE_ASYNC, - true); - } - } -} - -/* Turn off the async schedule after a brief delay */ -static void ehci_disable_ASE(struct ehci_hcd *ehci) -{ - ehci_clear_command_bit(ehci, CMD_ASE); -} - - -/* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */ -static void ehci_poll_PSS(struct ehci_hcd *ehci) -{ - unsigned actual, want; - - /* Don't do anything if the controller isn't running (e.g., died) */ - if (ehci->rh_state != EHCI_RH_RUNNING) - return; - - want = (ehci->command & CMD_PSE) ? STS_PSS : 0; - actual = ehci_readl(ehci, &ehci->regs->status) & STS_PSS; - - if (want != actual) { - - /* Poll again later, but give up after about 2-4 ms */ - if (ehci->PSS_poll_count++ < 2) { - ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); - return; - } - ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n", - want, actual); - } - ehci->PSS_poll_count = 0; - - /* The status is up-to-date; restart or stop the schedule as needed */ - if (want == 0) { /* Stopped */ - if (ehci->periodic_count > 0) - ehci_set_command_bit(ehci, CMD_PSE); - - } else { /* Running */ - if (ehci->periodic_count == 0) { - - /* Turn off the schedule after a while */ - ehci_enable_event(ehci, EHCI_HRTIMER_DISABLE_PERIODIC, - true); - } - } -} - -/* Turn off the periodic schedule after a brief delay */ -static void ehci_disable_PSE(struct ehci_hcd *ehci) -{ - ehci_clear_command_bit(ehci, CMD_PSE); -} - - -/* Poll the STS_HALT status bit; see when a dead controller stops */ -static void ehci_handle_controller_death(struct ehci_hcd *ehci) -{ - if (!(ehci_readl(ehci, &ehci->regs->status) & STS_HALT)) { - - /* Give up after a few milliseconds */ - if (ehci->died_poll_count++ < 5) { - /* Try again later */ - ehci_enable_event(ehci, EHCI_HRTIMER_POLL_DEAD, true); - return; - } - ehci_warn(ehci, "Waited too long for the controller to stop, giving up\n"); - } - - /* Clean up the mess */ - ehci->rh_state = EHCI_RH_HALTED; - ehci_writel(ehci, 0, &ehci->regs->configured_flag); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - ehci_work(ehci); - end_unlink_async(ehci); - - /* Not in process context, so don't try to reset the controller */ -} - - -/* Handle unlinked interrupt QHs once they are gone from the hardware */ -static void ehci_handle_intr_unlinks(struct ehci_hcd *ehci) -{ - bool stopped = (ehci->rh_state < EHCI_RH_RUNNING); - - /* - * Process all the QHs on the intr_unlink list that were added - * before the current unlink cycle began. The list is in - * temporal order, so stop when we reach the first entry in the - * current cycle. But if the root hub isn't running then - * process all the QHs on the list. - */ - ehci->intr_unlinking = true; - while (!list_empty(&ehci->intr_unlink)) { - struct ehci_qh *qh; - - qh = list_first_entry(&ehci->intr_unlink, struct ehci_qh, - unlink_node); - if (!stopped && qh->unlink_cycle == ehci->intr_unlink_cycle) - break; - list_del(&qh->unlink_node); - end_unlink_intr(ehci, qh); - } - - /* Handle remaining entries later */ - if (!list_empty(&ehci->intr_unlink)) { - ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true); - ++ehci->intr_unlink_cycle; - } - ehci->intr_unlinking = false; -} - - -/* Start another free-iTDs/siTDs cycle */ -static void start_free_itds(struct ehci_hcd *ehci) -{ - if (!(ehci->enabled_hrtimer_events & BIT(EHCI_HRTIMER_FREE_ITDS))) { - ehci->last_itd_to_free = list_entry( - ehci->cached_itd_list.prev, - struct ehci_itd, itd_list); - ehci->last_sitd_to_free = list_entry( - ehci->cached_sitd_list.prev, - struct ehci_sitd, sitd_list); - ehci_enable_event(ehci, EHCI_HRTIMER_FREE_ITDS, true); - } -} - -/* Wait for controller to stop using old iTDs and siTDs */ -static void end_free_itds(struct ehci_hcd *ehci) -{ - struct ehci_itd *itd, *n; - struct ehci_sitd *sitd, *sn; - - if (ehci->rh_state < EHCI_RH_RUNNING) { - ehci->last_itd_to_free = NULL; - ehci->last_sitd_to_free = NULL; - } - - list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) { - list_del(&itd->itd_list); - dma_pool_free(ehci->itd_pool, itd, itd->itd_dma); - if (itd == ehci->last_itd_to_free) - break; - } - list_for_each_entry_safe(sitd, sn, &ehci->cached_sitd_list, sitd_list) { - list_del(&sitd->sitd_list); - dma_pool_free(ehci->sitd_pool, sitd, sitd->sitd_dma); - if (sitd == ehci->last_sitd_to_free) - break; - } - - if (!list_empty(&ehci->cached_itd_list) || - !list_empty(&ehci->cached_sitd_list)) - start_free_itds(ehci); -} - - -/* Handle lost (or very late) IAA interrupts */ -static void ehci_iaa_watchdog(struct ehci_hcd *ehci) -{ - u32 cmd, status; - - /* - * Lost IAA irqs wedge things badly; seen first with a vt8235. - * So we need this watchdog, but must protect it against both - * (a) SMP races against real IAA firing and retriggering, and - * (b) clean HC shutdown, when IAA watchdog was pending. - */ - if (!ehci->iaa_in_progress || ehci->rh_state != EHCI_RH_RUNNING) - return; - - /* If we get here, IAA is *REALLY* late. It's barely - * conceivable that the system is so busy that CMD_IAAD - * is still legitimately set, so let's be sure it's - * clear before we read STS_IAA. (The HC should clear - * CMD_IAAD when it sets STS_IAA.) - */ - cmd = ehci_readl(ehci, &ehci->regs->command); - - /* - * If IAA is set here it either legitimately triggered - * after the watchdog timer expired (_way_ late, so we'll - * still count it as lost) ... or a silicon erratum: - * - VIA seems to set IAA without triggering the IRQ; - * - IAAD potentially cleared without setting IAA. - */ - status = ehci_readl(ehci, &ehci->regs->status); - if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { - COUNT(ehci->stats.lost_iaa); - ehci_writel(ehci, STS_IAA, &ehci->regs->status); - } - - ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd); - end_unlink_async(ehci); -} - - -/* Enable the I/O watchdog, if appropriate */ -static void turn_on_io_watchdog(struct ehci_hcd *ehci) -{ - /* Not needed if the controller isn't running or it's already enabled */ - if (ehci->rh_state != EHCI_RH_RUNNING || - (ehci->enabled_hrtimer_events & - BIT(EHCI_HRTIMER_IO_WATCHDOG))) - return; - - /* - * Isochronous transfers always need the watchdog. - * For other sorts we use it only if the flag is set. - */ - if (ehci->isoc_count > 0 || (ehci->need_io_watchdog && - ehci->async_count + ehci->intr_count > 0)) - ehci_enable_event(ehci, EHCI_HRTIMER_IO_WATCHDOG, true); -} - - -/* - * Handler functions for the hrtimer event types. - * Keep this array in the same order as the event types indexed by - * enum ehci_hrtimer_event in ehci.h. - */ -static void (*event_handlers[])(struct ehci_hcd *) = { - ehci_poll_ASS, /* EHCI_HRTIMER_POLL_ASS */ - ehci_poll_PSS, /* EHCI_HRTIMER_POLL_PSS */ - ehci_handle_controller_death, /* EHCI_HRTIMER_POLL_DEAD */ - ehci_handle_intr_unlinks, /* EHCI_HRTIMER_UNLINK_INTR */ - end_free_itds, /* EHCI_HRTIMER_FREE_ITDS */ - unlink_empty_async, /* EHCI_HRTIMER_ASYNC_UNLINKS */ - ehci_iaa_watchdog, /* EHCI_HRTIMER_IAA_WATCHDOG */ - ehci_disable_PSE, /* EHCI_HRTIMER_DISABLE_PERIODIC */ - ehci_disable_ASE, /* EHCI_HRTIMER_DISABLE_ASYNC */ - ehci_work, /* EHCI_HRTIMER_IO_WATCHDOG */ -}; - -static enum hrtimer_restart ehci_hrtimer_func(struct hrtimer *t) -{ - struct ehci_hcd *ehci = container_of(t, struct ehci_hcd, hrtimer); - ktime_t now; - unsigned long events; - unsigned long flags; - unsigned e; - - spin_lock_irqsave(&ehci->lock, flags); - - events = ehci->enabled_hrtimer_events; - ehci->enabled_hrtimer_events = 0; - ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT; - - /* - * Check each pending event. If its time has expired, handle - * the event; otherwise re-enable it. - */ - now = ktime_get(); - for_each_set_bit(e, &events, EHCI_HRTIMER_NUM_EVENTS) { - if (now.tv64 >= ehci->hr_timeouts[e].tv64) - event_handlers[e](ehci); - else - ehci_enable_event(ehci, e, false); - } - - spin_unlock_irqrestore(&ehci->lock, flags); - return HRTIMER_NORESTART; -} diff --git a/addons/ehci-pci/src/3.10.108/ehci.h b/addons/ehci-pci/src/3.10.108/ehci.h deleted file mode 100644 index 03322d9c..00000000 --- a/addons/ehci-pci/src/3.10.108/ehci.h +++ /dev/null @@ -1,825 +0,0 @@ -/* - * Copyright (c) 2001-2002 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __LINUX_EHCI_HCD_H -#define __LINUX_EHCI_HCD_H - -/* definitions used for the EHCI driver */ - -/* - * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to - * __leXX (normally) or __beXX (given EHCI_BIG_ENDIAN_DESC), depending on - * the host controller implementation. - * - * To facilitate the strongest possible byte-order checking from "sparse" - * and so on, we use __leXX unless that's not practical. - */ -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC -typedef __u32 __bitwise __hc32; -typedef __u16 __bitwise __hc16; -#else -#define __hc32 __le32 -#define __hc16 __le16 -#endif - -/* statistics can be kept for tuning/monitoring */ -#ifdef DEBUG -#define EHCI_STATS -#endif - -struct ehci_stats { - /* irq usage */ - unsigned long normal; - unsigned long error; - unsigned long iaa; - unsigned long lost_iaa; - - /* termination of urbs from core */ - unsigned long complete; - unsigned long unlink; -}; - -/* ehci_hcd->lock guards shared data against other CPUs: - * ehci_hcd: async, unlink, periodic (and shadow), ... - * usb_host_endpoint: hcpriv - * ehci_qh: qh_next, qtd_list - * ehci_qtd: qtd_list - * - * Also, hold this lock when talking to HC registers or - * when updating hw_* fields in shared qh/qtd/... structures. - */ - -#define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ - -/* - * ehci_rh_state values of EHCI_RH_RUNNING or above mean that the - * controller may be doing DMA. Lower values mean there's no DMA. - */ -enum ehci_rh_state { - EHCI_RH_HALTED, - EHCI_RH_SUSPENDED, - EHCI_RH_RUNNING, - EHCI_RH_STOPPING -}; - -/* - * Timer events, ordered by increasing delay length. - * Always update event_delays_ns[] and event_handlers[] (defined in - * ehci-timer.c) in parallel with this list. - */ -enum ehci_hrtimer_event { - EHCI_HRTIMER_POLL_ASS, /* Poll for async schedule off */ - EHCI_HRTIMER_POLL_PSS, /* Poll for periodic schedule off */ - EHCI_HRTIMER_POLL_DEAD, /* Wait for dead controller to stop */ - EHCI_HRTIMER_UNLINK_INTR, /* Wait for interrupt QH unlink */ - EHCI_HRTIMER_FREE_ITDS, /* Wait for unused iTDs and siTDs */ - EHCI_HRTIMER_ASYNC_UNLINKS, /* Unlink empty async QHs */ - EHCI_HRTIMER_IAA_WATCHDOG, /* Handle lost IAA interrupts */ - EHCI_HRTIMER_DISABLE_PERIODIC, /* Wait to disable periodic sched */ - EHCI_HRTIMER_DISABLE_ASYNC, /* Wait to disable async sched */ - EHCI_HRTIMER_IO_WATCHDOG, /* Check for missing IRQs */ - EHCI_HRTIMER_NUM_EVENTS /* Must come last */ -}; -#define EHCI_HRTIMER_NO_EVENT 99 - -struct ehci_hcd { /* one per controller */ - /* timing support */ - enum ehci_hrtimer_event next_hrtimer_event; - unsigned enabled_hrtimer_events; - ktime_t hr_timeouts[EHCI_HRTIMER_NUM_EVENTS]; - struct hrtimer hrtimer; - - int PSS_poll_count; - int ASS_poll_count; - int died_poll_count; - - /* glue to PCI and HCD framework */ - struct ehci_caps __iomem *caps; - struct ehci_regs __iomem *regs; - struct ehci_dbg_port __iomem *debug; - - __u32 hcs_params; /* cached register copy */ - spinlock_t lock; - enum ehci_rh_state rh_state; - - /* general schedule support */ - bool scanning:1; - bool need_rescan:1; - bool intr_unlinking:1; - bool iaa_in_progress:1; - bool async_unlinking:1; - bool shutdown:1; - struct ehci_qh *qh_scan_next; - - /* async schedule support */ - struct ehci_qh *async; - struct ehci_qh *dummy; /* For AMD quirk use */ - struct list_head async_unlink; - struct list_head async_idle; - unsigned async_unlink_cycle; - unsigned async_count; /* async activity count */ - - /* periodic schedule support */ -#define DEFAULT_I_TDPS 1024 /* some HCs can do less */ - unsigned periodic_size; - __hc32 *periodic; /* hw periodic table */ - dma_addr_t periodic_dma; - struct list_head intr_qh_list; - unsigned i_thresh; /* uframes HC might cache */ - - union ehci_shadow *pshadow; /* mirror hw periodic table */ - struct list_head intr_unlink; - unsigned intr_unlink_cycle; - unsigned now_frame; /* frame from HC hardware */ - unsigned last_iso_frame; /* last frame scanned for iso */ - unsigned intr_count; /* intr activity count */ - unsigned isoc_count; /* isoc activity count */ - unsigned periodic_count; /* periodic activity count */ - unsigned uframe_periodic_max; /* max periodic time per uframe */ - - - /* list of itds & sitds completed while now_frame was still active */ - struct list_head cached_itd_list; - struct ehci_itd *last_itd_to_free; - struct list_head cached_sitd_list; - struct ehci_sitd *last_sitd_to_free; - - /* per root hub port */ - unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; - - /* bit vectors (one bit per port) */ - unsigned long bus_suspended; /* which ports were - already suspended at the start of a bus suspend */ - unsigned long companion_ports; /* which ports are - dedicated to the companion controller */ - unsigned long owned_ports; /* which ports are - owned by the companion during a bus suspend */ - unsigned long port_c_suspend; /* which ports have - the change-suspend feature turned on */ - unsigned long suspended_ports; /* which ports are - suspended */ - unsigned long resuming_ports; /* which ports have - started to resume */ - - /* per-HC memory pools (could be per-bus, but ...) */ - struct dma_pool *qh_pool; /* qh per active urb */ - struct dma_pool *qtd_pool; /* one or more per qh */ - struct dma_pool *itd_pool; /* itd per iso urb */ - struct dma_pool *sitd_pool; /* sitd per split iso urb */ - - unsigned random_frame; - unsigned long next_statechange; - ktime_t last_periodic_enable; - u32 command; - - /* SILICON QUIRKS */ - unsigned no_selective_suspend:1; - unsigned has_fsl_port_bug:1; /* FreeScale */ - unsigned big_endian_mmio:1; - unsigned big_endian_desc:1; - unsigned big_endian_capbase:1; - unsigned has_amcc_usb23:1; - unsigned need_io_watchdog:1; - unsigned amd_pll_fix:1; - unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/ - unsigned has_synopsys_hc_bug:1; /* Synopsys HC */ - unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */ - unsigned need_oc_pp_cycle:1; /* MPC834X port power */ - unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ - - /* required for usb32 quirk */ - #define OHCI_CTRL_HCFS (3 << 6) - #define OHCI_USB_OPER (2 << 6) - #define OHCI_USB_SUSPEND (3 << 6) - - #define OHCI_HCCTRL_OFFSET 0x4 - #define OHCI_HCCTRL_LEN 0x4 - __hc32 *ohci_hcctrl_reg; - unsigned has_hostpc:1; - unsigned has_ppcd:1; /* support per-port change bits */ - u8 sbrn; /* packed release number */ - - /* irq statistics */ -#ifdef EHCI_STATS - struct ehci_stats stats; -# define COUNT(x) do { (x)++; } while (0) -#else -# define COUNT(x) do {} while (0) -#endif - - /* debug files */ -#ifdef DEBUG - struct dentry *debug_dir; -#endif - - /* platform-specific data -- must come last */ - unsigned long priv[0] __aligned(sizeof(s64)); -}; - -/* convert between an HCD pointer and the corresponding EHCI_HCD */ -static inline struct ehci_hcd *hcd_to_ehci (struct usb_hcd *hcd) -{ - return (struct ehci_hcd *) (hcd->hcd_priv); -} -static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci) -{ - return container_of ((void *) ehci, struct usb_hcd, hcd_priv); -} - -/*-------------------------------------------------------------------------*/ - -#include - -/*-------------------------------------------------------------------------*/ - -#define QTD_NEXT(ehci, dma) cpu_to_hc32(ehci, (u32)dma) - -/* - * EHCI Specification 0.95 Section 3.5 - * QTD: describe data transfer components (buffer, direction, ...) - * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". - * - * These are associated only with "QH" (Queue Head) structures, - * used with control, bulk, and interrupt transfers. - */ -struct ehci_qtd { - /* first part defined by EHCI spec */ - __hc32 hw_next; /* see EHCI 3.5.1 */ - __hc32 hw_alt_next; /* see EHCI 3.5.2 */ - __hc32 hw_token; /* see EHCI 3.5.3 */ -#define QTD_TOGGLE (1 << 31) /* data toggle */ -#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) -#define QTD_IOC (1 << 15) /* interrupt on complete */ -#define QTD_CERR(tok) (((tok)>>10) & 0x3) -#define QTD_PID(tok) (((tok)>>8) & 0x3) -#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ -#define QTD_STS_HALT (1 << 6) /* halted on error */ -#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ -#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ -#define QTD_STS_XACT (1 << 3) /* device gave illegal response */ -#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ -#define QTD_STS_STS (1 << 1) /* split transaction state */ -#define QTD_STS_PING (1 << 0) /* issue PING? */ - -#define ACTIVE_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_ACTIVE) -#define HALT_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_HALT) -#define STATUS_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_STS) - - __hc32 hw_buf [5]; /* see EHCI 3.5.4 */ - __hc32 hw_buf_hi [5]; /* Appendix B */ - - /* the rest is HCD-private */ - dma_addr_t qtd_dma; /* qtd address */ - struct list_head qtd_list; /* sw qtd list */ - struct urb *urb; /* qtd's urb */ - size_t length; /* length of buffer */ -} __attribute__ ((aligned (32))); - -/* mask NakCnt+T in qh->hw_alt_next */ -#define QTD_MASK(ehci) cpu_to_hc32 (ehci, ~0x1f) - -#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1) - -/*-------------------------------------------------------------------------*/ - -/* type tag from {qh,itd,sitd,fstn}->hw_next */ -#define Q_NEXT_TYPE(ehci,dma) ((dma) & cpu_to_hc32(ehci, 3 << 1)) - -/* - * Now the following defines are not converted using the - * cpu_to_le32() macro anymore, since we have to support - * "dynamic" switching between be and le support, so that the driver - * can be used on one system with SoC EHCI controller using big-endian - * descriptors as well as a normal little-endian PCI EHCI controller. - */ -/* values for that type tag */ -#define Q_TYPE_ITD (0 << 1) -#define Q_TYPE_QH (1 << 1) -#define Q_TYPE_SITD (2 << 1) -#define Q_TYPE_FSTN (3 << 1) - -/* next async queue entry, or pointer to interrupt/periodic QH */ -#define QH_NEXT(ehci,dma) (cpu_to_hc32(ehci, (((u32)dma)&~0x01f)|Q_TYPE_QH)) - -/* for periodic/async schedules and qtd lists, mark end of list */ -#define EHCI_LIST_END(ehci) cpu_to_hc32(ehci, 1) /* "null pointer" to hw */ - -/* - * Entries in periodic shadow table are pointers to one of four kinds - * of data structure. That's dictated by the hardware; a type tag is - * encoded in the low bits of the hardware's periodic schedule. Use - * Q_NEXT_TYPE to get the tag. - * - * For entries in the async schedule, the type tag always says "qh". - */ -union ehci_shadow { - struct ehci_qh *qh; /* Q_TYPE_QH */ - struct ehci_itd *itd; /* Q_TYPE_ITD */ - struct ehci_sitd *sitd; /* Q_TYPE_SITD */ - struct ehci_fstn *fstn; /* Q_TYPE_FSTN */ - __hc32 *hw_next; /* (all types) */ - void *ptr; -}; - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.6 - * QH: describes control/bulk/interrupt endpoints - * See Fig 3-7 "Queue Head Structure Layout". - * - * These appear in both the async and (for interrupt) periodic schedules. - */ - -/* first part defined by EHCI spec */ -struct ehci_qh_hw { - __hc32 hw_next; /* see EHCI 3.6.1 */ - __hc32 hw_info1; /* see EHCI 3.6.2 */ -#define QH_CONTROL_EP (1 << 27) /* FS/LS control endpoint */ -#define QH_HEAD (1 << 15) /* Head of async reclamation list */ -#define QH_TOGGLE_CTL (1 << 14) /* Data toggle control */ -#define QH_HIGH_SPEED (2 << 12) /* Endpoint speed */ -#define QH_LOW_SPEED (1 << 12) -#define QH_FULL_SPEED (0 << 12) -#define QH_INACTIVATE (1 << 7) /* Inactivate on next transaction */ - __hc32 hw_info2; /* see EHCI 3.6.2 */ -#define QH_SMASK 0x000000ff -#define QH_CMASK 0x0000ff00 -#define QH_HUBADDR 0x007f0000 -#define QH_HUBPORT 0x3f800000 -#define QH_MULT 0xc0000000 - __hc32 hw_current; /* qtd list - see EHCI 3.6.4 */ - - /* qtd overlay (hardware parts of a struct ehci_qtd) */ - __hc32 hw_qtd_next; - __hc32 hw_alt_next; - __hc32 hw_token; - __hc32 hw_buf [5]; - __hc32 hw_buf_hi [5]; -} __attribute__ ((aligned(32))); - -struct ehci_qh { - struct ehci_qh_hw *hw; /* Must come first */ - /* the rest is HCD-private */ - dma_addr_t qh_dma; /* address of qh */ - union ehci_shadow qh_next; /* ptr to qh; or periodic */ - struct list_head qtd_list; /* sw qtd list */ - struct list_head intr_node; /* list of intr QHs */ - struct ehci_qtd *dummy; - struct list_head unlink_node; - - unsigned unlink_cycle; - - u8 qh_state; -#define QH_STATE_LINKED 1 /* HC sees this */ -#define QH_STATE_UNLINK 2 /* HC may still see this */ -#define QH_STATE_IDLE 3 /* HC doesn't see this */ -#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on unlink q */ -#define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ - - u8 xacterrs; /* XactErr retry counter */ -#define QH_XACTERR_MAX 32 /* XactErr retry limit */ - - /* periodic schedule info */ - u8 usecs; /* intr bandwidth */ - u8 gap_uf; /* uframes split/csplit gap */ - u8 c_usecs; /* ... split completion bw */ - u16 tt_usecs; /* tt downstream bandwidth */ - unsigned short period; /* polling interval */ - unsigned short start; /* where polling starts */ -#define NO_FRAME ((unsigned short)~0) /* pick new start */ - - struct usb_device *dev; /* access to TT */ - unsigned is_out:1; /* bulk or intr OUT */ - unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ - unsigned dequeue_during_giveback:1; - unsigned exception:1; /* got a fault, or an unlink - was requested */ -}; - -/*-------------------------------------------------------------------------*/ - -/* description of one iso transaction (up to 3 KB data if highspeed) */ -struct ehci_iso_packet { - /* These will be copied to iTD when scheduling */ - u64 bufp; /* itd->hw_bufp{,_hi}[pg] |= */ - __hc32 transaction; /* itd->hw_transaction[i] |= */ - u8 cross; /* buf crosses pages */ - /* for full speed OUT splits */ - u32 buf1; -}; - -/* temporary schedule data for packets from iso urbs (both speeds) - * each packet is one logical usb transaction to the device (not TT), - * beginning at stream->next_uframe - */ -struct ehci_iso_sched { - struct list_head td_list; - unsigned span; - struct ehci_iso_packet packet [0]; -}; - -/* - * ehci_iso_stream - groups all (s)itds for this endpoint. - * acts like a qh would, if EHCI had them for ISO. - */ -struct ehci_iso_stream { - /* first field matches ehci_hq, but is NULL */ - struct ehci_qh_hw *hw; - - u8 bEndpointAddress; - u8 highspeed; - struct list_head td_list; /* queued itds/sitds */ - struct list_head free_list; /* list of unused itds/sitds */ - struct usb_device *udev; - struct usb_host_endpoint *ep; - - /* output of (re)scheduling */ - int next_uframe; - __hc32 splits; - - /* the rest is derived from the endpoint descriptor, - * trusting urb->interval == f(epdesc->bInterval) and - * including the extra info for hw_bufp[0..2] - */ - u8 usecs, c_usecs; - u16 interval; - u16 tt_usecs; - u16 maxp; - u16 raw_mask; - unsigned bandwidth; - - /* This is used to initialize iTD's hw_bufp fields */ - __hc32 buf0; - __hc32 buf1; - __hc32 buf2; - - /* this is used to initialize sITD's tt info */ - __hc32 address; -}; - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.3 - * Fig 3-4 "Isochronous Transaction Descriptor (iTD)" - * - * Schedule records for high speed iso xfers - */ -struct ehci_itd { - /* first part defined by EHCI spec */ - __hc32 hw_next; /* see EHCI 3.3.1 */ - __hc32 hw_transaction [8]; /* see EHCI 3.3.2 */ -#define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ -#define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */ -#define EHCI_ISOC_BABBLE (1<<29) /* babble detected */ -#define EHCI_ISOC_XACTERR (1<<28) /* XactErr - transaction error */ -#define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x0fff) -#define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */ - -#define ITD_ACTIVE(ehci) cpu_to_hc32(ehci, EHCI_ISOC_ACTIVE) - - __hc32 hw_bufp [7]; /* see EHCI 3.3.3 */ - __hc32 hw_bufp_hi [7]; /* Appendix B */ - - /* the rest is HCD-private */ - dma_addr_t itd_dma; /* for this itd */ - union ehci_shadow itd_next; /* ptr to periodic q entry */ - - struct urb *urb; - struct ehci_iso_stream *stream; /* endpoint's queue */ - struct list_head itd_list; /* list of stream's itds */ - - /* any/all hw_transactions here may be used by that urb */ - unsigned frame; /* where scheduled */ - unsigned pg; - unsigned index[8]; /* in urb->iso_frame_desc */ -} __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.4 - * siTD, aka split-transaction isochronous Transfer Descriptor - * ... describe full speed iso xfers through TT in hubs - * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD) - */ -struct ehci_sitd { - /* first part defined by EHCI spec */ - __hc32 hw_next; -/* uses bit field macros above - see EHCI 0.95 Table 3-8 */ - __hc32 hw_fullspeed_ep; /* EHCI table 3-9 */ - __hc32 hw_uframe; /* EHCI table 3-10 */ - __hc32 hw_results; /* EHCI table 3-11 */ -#define SITD_IOC (1 << 31) /* interrupt on completion */ -#define SITD_PAGE (1 << 30) /* buffer 0/1 */ -#define SITD_LENGTH(x) (0x3ff & ((x)>>16)) -#define SITD_STS_ACTIVE (1 << 7) /* HC may execute this */ -#define SITD_STS_ERR (1 << 6) /* error from TT */ -#define SITD_STS_DBE (1 << 5) /* data buffer error (in HC) */ -#define SITD_STS_BABBLE (1 << 4) /* device was babbling */ -#define SITD_STS_XACT (1 << 3) /* illegal IN response */ -#define SITD_STS_MMF (1 << 2) /* incomplete split transaction */ -#define SITD_STS_STS (1 << 1) /* split transaction state */ - -#define SITD_ACTIVE(ehci) cpu_to_hc32(ehci, SITD_STS_ACTIVE) - - __hc32 hw_buf [2]; /* EHCI table 3-12 */ - __hc32 hw_backpointer; /* EHCI table 3-13 */ - __hc32 hw_buf_hi [2]; /* Appendix B */ - - /* the rest is HCD-private */ - dma_addr_t sitd_dma; - union ehci_shadow sitd_next; /* ptr to periodic q entry */ - - struct urb *urb; - struct ehci_iso_stream *stream; /* endpoint's queue */ - struct list_head sitd_list; /* list of stream's sitds */ - unsigned frame; - unsigned index; -} __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.96 Section 3.7 - * Periodic Frame Span Traversal Node (FSTN) - * - * Manages split interrupt transactions (using TT) that span frame boundaries - * into uframes 0/1; see 4.12.2.2. In those uframes, a "save place" FSTN - * makes the HC jump (back) to a QH to scan for fs/ls QH completions until - * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work. - */ -struct ehci_fstn { - __hc32 hw_next; /* any periodic q entry */ - __hc32 hw_prev; /* qh or EHCI_LIST_END */ - - /* the rest is HCD-private */ - dma_addr_t fstn_dma; - union ehci_shadow fstn_next; /* ptr to periodic q entry */ -} __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - -/* Prepare the PORTSC wakeup flags during controller suspend/resume */ - -#define ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup) \ - ehci_adjust_port_wakeup_flags(ehci, true, do_wakeup); - -#define ehci_prepare_ports_for_controller_resume(ehci) \ - ehci_adjust_port_wakeup_flags(ehci, false, false); - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_USB_EHCI_ROOT_HUB_TT - -/* - * Some EHCI controllers have a Transaction Translator built into the - * root hub. This is a non-standard feature. Each controller will need - * to add code to the following inline functions, and call them as - * needed (mostly in root hub code). - */ - -#define ehci_is_TDI(e) (ehci_to_hcd(e)->has_tt) - -/* Returns the speed of a device attached to a port on the root hub. */ -static inline unsigned int -ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) -{ - if (ehci_is_TDI(ehci)) { - switch ((portsc >> (ehci->has_hostpc ? 25 : 26)) & 3) { - case 0: - return 0; - case 1: - return USB_PORT_STAT_LOW_SPEED; - case 2: - default: - return USB_PORT_STAT_HIGH_SPEED; - } - } - return USB_PORT_STAT_HIGH_SPEED; -} - -#else - -#define ehci_is_TDI(e) (0) - -#define ehci_port_speed(ehci, portsc) USB_PORT_STAT_HIGH_SPEED -#endif - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_PPC_83xx -/* Some Freescale processors have an erratum in which the TT - * port number in the queue head was 0..N-1 instead of 1..N. - */ -#define ehci_has_fsl_portno_bug(e) ((e)->has_fsl_port_bug) -#else -#define ehci_has_fsl_portno_bug(e) (0) -#endif - -/* - * While most USB host controllers implement their registers in - * little-endian format, a minority (celleb companion chip) implement - * them in big endian format. - * - * This attempts to support either format at compile time without a - * runtime penalty, or both formats with the additional overhead - * of checking a flag bit. - * - * ehci_big_endian_capbase is a special quirk for controllers that - * implement the HC capability registers as separate registers and not - * as fields of a 32-bit register. - */ - -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO -#define ehci_big_endian_mmio(e) ((e)->big_endian_mmio) -#define ehci_big_endian_capbase(e) ((e)->big_endian_capbase) -#else -#define ehci_big_endian_mmio(e) 0 -#define ehci_big_endian_capbase(e) 0 -#endif - -/* - * Big-endian read/write functions are arch-specific. - * Other arches can be added if/when they're needed. - */ -#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_IXP4XX) -#define readl_be(addr) __raw_readl((__force unsigned *)addr) -#define writel_be(val, addr) __raw_writel(val, (__force unsigned *)addr) -#endif - -static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, - __u32 __iomem * regs) -{ -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO - return ehci_big_endian_mmio(ehci) ? - readl_be(regs) : - readl(regs); -#else - return readl(regs); -#endif -} - -#ifdef CONFIG_SOC_IMX28 -static inline void imx28_ehci_writel(const unsigned int val, - volatile __u32 __iomem *addr) -{ - __asm__ ("swp %0, %0, [%1]" : : "r"(val), "r"(addr)); -} -#else -static inline void imx28_ehci_writel(const unsigned int val, - volatile __u32 __iomem *addr) -{ -} -#endif -static inline void ehci_writel(const struct ehci_hcd *ehci, - const unsigned int val, __u32 __iomem *regs) -{ -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO - ehci_big_endian_mmio(ehci) ? - writel_be(val, regs) : - writel(val, regs); -#else - if (ehci->imx28_write_fix) - imx28_ehci_writel(val, regs); - else - writel(val, regs); -#endif -} - -/* - * On certain ppc-44x SoC there is a HW issue, that could only worked around with - * explicit suspend/operate of OHCI. This function hereby makes sense only on that arch. - * Other common bits are dependent on has_amcc_usb23 quirk flag. - */ -#ifdef CONFIG_44x -static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational) -{ - u32 hc_control; - - hc_control = (readl_be(ehci->ohci_hcctrl_reg) & ~OHCI_CTRL_HCFS); - if (operational) - hc_control |= OHCI_USB_OPER; - else - hc_control |= OHCI_USB_SUSPEND; - - writel_be(hc_control, ehci->ohci_hcctrl_reg); - (void) readl_be(ehci->ohci_hcctrl_reg); -} -#else -static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational) -{ } -#endif - -/*-------------------------------------------------------------------------*/ - -/* - * The AMCC 440EPx not only implements its EHCI registers in big-endian - * format, but also its DMA data structures (descriptors). - * - * EHCI controllers accessed through PCI work normally (little-endian - * everywhere), so we won't bother supporting a BE-only mode for now. - */ -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC -#define ehci_big_endian_desc(e) ((e)->big_endian_desc) - -/* cpu to ehci */ -static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x) -{ - return ehci_big_endian_desc(ehci) - ? (__force __hc32)cpu_to_be32(x) - : (__force __hc32)cpu_to_le32(x); -} - -/* ehci to cpu */ -static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x) -{ - return ehci_big_endian_desc(ehci) - ? be32_to_cpu((__force __be32)x) - : le32_to_cpu((__force __le32)x); -} - -static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) -{ - return ehci_big_endian_desc(ehci) - ? be32_to_cpup((__force __be32 *)x) - : le32_to_cpup((__force __le32 *)x); -} - -#else - -/* cpu to ehci */ -static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x) -{ - return cpu_to_le32(x); -} - -/* ehci to cpu */ -static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x) -{ - return le32_to_cpu(x); -} - -static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) -{ - return le32_to_cpup(x); -} - -#endif - -/*-------------------------------------------------------------------------*/ - -#define ehci_dbg(ehci, fmt, args...) \ - dev_dbg(ehci_to_hcd(ehci)->self.controller , fmt , ## args) -#define ehci_err(ehci, fmt, args...) \ - dev_err(ehci_to_hcd(ehci)->self.controller , fmt , ## args) -#define ehci_info(ehci, fmt, args...) \ - dev_info(ehci_to_hcd(ehci)->self.controller , fmt , ## args) -#define ehci_warn(ehci, fmt, args...) \ - dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args) - -#ifdef VERBOSE_DEBUG -# define ehci_vdbg ehci_dbg -#else - static inline void ehci_vdbg(struct ehci_hcd *ehci, ...) {} -#endif - -#ifndef DEBUG -#define STUB_DEBUG_FILES -#endif /* DEBUG */ - -/*-------------------------------------------------------------------------*/ - -/* Declarations of things exported for use by ehci platform drivers */ - -struct ehci_driver_overrides { - size_t extra_priv_size; - int (*reset)(struct usb_hcd *hcd); -}; - -extern void ehci_init_driver(struct hc_driver *drv, - const struct ehci_driver_overrides *over); -extern int ehci_setup(struct usb_hcd *hcd); - -#ifdef CONFIG_PM -extern int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup); -extern int ehci_resume(struct usb_hcd *hcd, bool hibernated); -#endif /* CONFIG_PM */ - -#endif /* __LINUX_EHCI_HCD_H */ diff --git a/addons/ehci-pci/src/3.10.108/pci-quirks.c b/addons/ehci-pci/src/3.10.108/pci-quirks.c deleted file mode 100644 index 66c90588..00000000 --- a/addons/ehci-pci/src/3.10.108/pci-quirks.c +++ /dev/null @@ -1,1001 +0,0 @@ -/* - * This file contains code to reset and initialize USB host controllers. - * Some of it includes work-arounds for PCI hardware and BIOS quirks. - * It may need to run early during booting -- before USB would normally - * initialize -- to ensure that Linux doesn't use any legacy modes. - * - * Copyright (c) 1999 Martin Mares - * (and others) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pci-quirks.h" -#include "xhci-ext-caps.h" - - -#define UHCI_USBLEGSUP 0xc0 /* legacy support */ -#define UHCI_USBCMD 0 /* command register */ -#define UHCI_USBINTR 4 /* interrupt register */ -#define UHCI_USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ -#define UHCI_USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ -#define UHCI_USBCMD_RUN 0x0001 /* RUN/STOP bit */ -#define UHCI_USBCMD_HCRESET 0x0002 /* Host Controller reset */ -#define UHCI_USBCMD_EGSM 0x0008 /* Global Suspend Mode */ -#define UHCI_USBCMD_CONFIGURE 0x0040 /* Config Flag */ -#define UHCI_USBINTR_RESUME 0x0002 /* Resume interrupt enable */ - -#define OHCI_CONTROL 0x04 -#define OHCI_CMDSTATUS 0x08 -#define OHCI_INTRSTATUS 0x0c -#define OHCI_INTRENABLE 0x10 -#define OHCI_INTRDISABLE 0x14 -#define OHCI_FMINTERVAL 0x34 -#define OHCI_HCFS (3 << 6) /* hc functional state */ -#define OHCI_HCR (1 << 0) /* host controller reset */ -#define OHCI_OCR (1 << 3) /* ownership change request */ -#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ -#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ -#define OHCI_INTR_OC (1 << 30) /* ownership change */ - -#define EHCI_HCC_PARAMS 0x08 /* extended capabilities */ -#define EHCI_USBCMD 0 /* command register */ -#define EHCI_USBCMD_RUN (1 << 0) /* RUN/STOP bit */ -#define EHCI_USBSTS 4 /* status register */ -#define EHCI_USBSTS_HALTED (1 << 12) /* HCHalted bit */ -#define EHCI_USBINTR 8 /* interrupt register */ -#define EHCI_CONFIGFLAG 0x40 /* configured flag register */ -#define EHCI_USBLEGSUP 0 /* legacy support register */ -#define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */ -#define EHCI_USBLEGSUP_OS (1 << 24) /* OS semaphore */ -#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */ -#define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */ - -/* AMD quirk use */ -#define AB_REG_BAR_LOW 0xe0 -#define AB_REG_BAR_HIGH 0xe1 -#define AB_REG_BAR_SB700 0xf0 -#define AB_INDX(addr) ((addr) + 0x00) -#define AB_DATA(addr) ((addr) + 0x04) -#define AX_INDXC 0x30 -#define AX_DATAC 0x34 - -#define NB_PCIE_INDX_ADDR 0xe0 -#define NB_PCIE_INDX_DATA 0xe4 -#define PCIE_P_CNTL 0x10040 -#define BIF_NB 0x10002 -#define NB_PIF0_PWRDOWN_0 0x01100012 -#define NB_PIF0_PWRDOWN_1 0x01100013 - -#define USB_INTEL_XUSB2PR 0xD0 -#define USB_INTEL_USB2PRM 0xD4 -#define USB_INTEL_USB3_PSSEN 0xD8 -#define USB_INTEL_USB3PRM 0xDC - -static struct amd_chipset_info { - struct pci_dev *nb_dev; - struct pci_dev *smbus_dev; - int nb_type; - int sb_type; - int isoc_reqs; - int probe_count; - int probe_result; -} amd_chipset; - -static DEFINE_SPINLOCK(amd_lock); - -int usb_amd_find_chipset_info(void) -{ - u8 rev = 0; - unsigned long flags; - struct amd_chipset_info info; - int ret; - - spin_lock_irqsave(&amd_lock, flags); - - /* probe only once */ - if (amd_chipset.probe_count > 0) { - amd_chipset.probe_count++; - spin_unlock_irqrestore(&amd_lock, flags); - return amd_chipset.probe_result; - } - memset(&info, 0, sizeof(info)); - spin_unlock_irqrestore(&amd_lock, flags); - - info.smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, 0x4385, NULL); - if (info.smbus_dev) { - rev = info.smbus_dev->revision; - if (rev >= 0x40) - info.sb_type = 1; - else if (rev >= 0x30 && rev <= 0x3b) - info.sb_type = 3; - } else { - info.smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, - 0x780b, NULL); - if (!info.smbus_dev) { - ret = 0; - goto commit; - } - - rev = info.smbus_dev->revision; - if (rev >= 0x11 && rev <= 0x18) - info.sb_type = 2; - } - - if (info.sb_type == 0) { - if (info.smbus_dev) { - pci_dev_put(info.smbus_dev); - info.smbus_dev = NULL; - } - ret = 0; - goto commit; - } - - info.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9601, NULL); - if (info.nb_dev) { - info.nb_type = 1; - } else { - info.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL); - if (info.nb_dev) { - info.nb_type = 2; - } else { - info.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, - 0x9600, NULL); - if (info.nb_dev) - info.nb_type = 3; - } - } - - ret = info.probe_result = 1; - printk(KERN_DEBUG "QUIRK: Enable AMD PLL fix\n"); - -commit: - - spin_lock_irqsave(&amd_lock, flags); - if (amd_chipset.probe_count > 0) { - /* race - someone else was faster - drop devices */ - - /* Mark that we where here */ - amd_chipset.probe_count++; - ret = amd_chipset.probe_result; - - spin_unlock_irqrestore(&amd_lock, flags); - - if (info.nb_dev) - pci_dev_put(info.nb_dev); - if (info.smbus_dev) - pci_dev_put(info.smbus_dev); - - } else { - /* no race - commit the result */ - info.probe_count++; - amd_chipset = info; - spin_unlock_irqrestore(&amd_lock, flags); - } - - return ret; -} -EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info); - -/* - * The hardware normally enables the A-link power management feature, which - * lets the system lower the power consumption in idle states. - * - * This USB quirk prevents the link going into that lower power state - * during isochronous transfers. - * - * Without this quirk, isochronous stream on OHCI/EHCI/xHCI controllers of - * some AMD platforms may stutter or have breaks occasionally. - */ -static void usb_amd_quirk_pll(int disable) -{ - u32 addr, addr_low, addr_high, val; - u32 bit = disable ? 0 : 1; - unsigned long flags; - - spin_lock_irqsave(&amd_lock, flags); - - if (disable) { - amd_chipset.isoc_reqs++; - if (amd_chipset.isoc_reqs > 1) { - spin_unlock_irqrestore(&amd_lock, flags); - return; - } - } else { - amd_chipset.isoc_reqs--; - if (amd_chipset.isoc_reqs > 0) { - spin_unlock_irqrestore(&amd_lock, flags); - return; - } - } - - if (amd_chipset.sb_type == 1 || amd_chipset.sb_type == 2) { - outb_p(AB_REG_BAR_LOW, 0xcd6); - addr_low = inb_p(0xcd7); - outb_p(AB_REG_BAR_HIGH, 0xcd6); - addr_high = inb_p(0xcd7); - addr = addr_high << 8 | addr_low; - - outl_p(0x30, AB_INDX(addr)); - outl_p(0x40, AB_DATA(addr)); - outl_p(0x34, AB_INDX(addr)); - val = inl_p(AB_DATA(addr)); - } else if (amd_chipset.sb_type == 3) { - pci_read_config_dword(amd_chipset.smbus_dev, - AB_REG_BAR_SB700, &addr); - outl(AX_INDXC, AB_INDX(addr)); - outl(0x40, AB_DATA(addr)); - outl(AX_DATAC, AB_INDX(addr)); - val = inl(AB_DATA(addr)); - } else { - spin_unlock_irqrestore(&amd_lock, flags); - return; - } - - if (disable) { - val &= ~0x08; - val |= (1 << 4) | (1 << 9); - } else { - val |= 0x08; - val &= ~((1 << 4) | (1 << 9)); - } - outl_p(val, AB_DATA(addr)); - - if (!amd_chipset.nb_dev) { - spin_unlock_irqrestore(&amd_lock, flags); - return; - } - - if (amd_chipset.nb_type == 1 || amd_chipset.nb_type == 3) { - addr = PCIE_P_CNTL; - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_ADDR, addr); - pci_read_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, &val); - - val &= ~(1 | (1 << 3) | (1 << 4) | (1 << 9) | (1 << 12)); - val |= bit | (bit << 3) | (bit << 12); - val |= ((!bit) << 4) | ((!bit) << 9); - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, val); - - addr = BIF_NB; - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_ADDR, addr); - pci_read_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, &val); - val &= ~(1 << 8); - val |= bit << 8; - - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, val); - } else if (amd_chipset.nb_type == 2) { - addr = NB_PIF0_PWRDOWN_0; - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_ADDR, addr); - pci_read_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, &val); - if (disable) - val &= ~(0x3f << 7); - else - val |= 0x3f << 7; - - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, val); - - addr = NB_PIF0_PWRDOWN_1; - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_ADDR, addr); - pci_read_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, &val); - if (disable) - val &= ~(0x3f << 7); - else - val |= 0x3f << 7; - - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, val); - } - - spin_unlock_irqrestore(&amd_lock, flags); - return; -} - -void usb_amd_quirk_pll_disable(void) -{ - usb_amd_quirk_pll(1); -} -EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable); - -void usb_amd_quirk_pll_enable(void) -{ - usb_amd_quirk_pll(0); -} -EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_enable); - -void usb_amd_dev_put(void) -{ - struct pci_dev *nb, *smbus; - unsigned long flags; - - spin_lock_irqsave(&amd_lock, flags); - - amd_chipset.probe_count--; - if (amd_chipset.probe_count > 0) { - spin_unlock_irqrestore(&amd_lock, flags); - return; - } - - /* save them to pci_dev_put outside of spinlock */ - nb = amd_chipset.nb_dev; - smbus = amd_chipset.smbus_dev; - - amd_chipset.nb_dev = NULL; - amd_chipset.smbus_dev = NULL; - amd_chipset.nb_type = 0; - amd_chipset.sb_type = 0; - amd_chipset.isoc_reqs = 0; - amd_chipset.probe_result = 0; - - spin_unlock_irqrestore(&amd_lock, flags); - - if (nb) - pci_dev_put(nb); - if (smbus) - pci_dev_put(smbus); -} -EXPORT_SYMBOL_GPL(usb_amd_dev_put); - -/* - * Make sure the controller is completely inactive, unable to - * generate interrupts or do DMA. - */ -void uhci_reset_hc(struct pci_dev *pdev, unsigned long base) -{ - /* Turn off PIRQ enable and SMI enable. (This also turns off the - * BIOS's USB Legacy Support.) Turn off all the R/WC bits too. - */ - pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC); - - /* Reset the HC - this will force us to get a - * new notification of any already connected - * ports due to the virtual disconnect that it - * implies. - */ - outw(UHCI_USBCMD_HCRESET, base + UHCI_USBCMD); - mb(); - udelay(5); - if (inw(base + UHCI_USBCMD) & UHCI_USBCMD_HCRESET) - dev_warn(&pdev->dev, "HCRESET not completed yet!\n"); - - /* Just to be safe, disable interrupt requests and - * make sure the controller is stopped. - */ - outw(0, base + UHCI_USBINTR); - outw(0, base + UHCI_USBCMD); -} -EXPORT_SYMBOL_GPL(uhci_reset_hc); - -/* - * Initialize a controller that was newly discovered or has just been - * resumed. In either case we can't be sure of its previous state. - * - * Returns: 1 if the controller was reset, 0 otherwise. - */ -int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base) -{ - u16 legsup; - unsigned int cmd, intr; - - /* - * When restarting a suspended controller, we expect all the - * settings to be the same as we left them: - * - * PIRQ and SMI disabled, no R/W bits set in USBLEGSUP; - * Controller is stopped and configured with EGSM set; - * No interrupts enabled except possibly Resume Detect. - * - * If any of these conditions are violated we do a complete reset. - */ - pci_read_config_word(pdev, UHCI_USBLEGSUP, &legsup); - if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) { - dev_dbg(&pdev->dev, "%s: legsup = 0x%04x\n", - __func__, legsup); - goto reset_needed; - } - - cmd = inw(base + UHCI_USBCMD); - if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_CONFIGURE) || - !(cmd & UHCI_USBCMD_EGSM)) { - dev_dbg(&pdev->dev, "%s: cmd = 0x%04x\n", - __func__, cmd); - goto reset_needed; - } - - intr = inw(base + UHCI_USBINTR); - if (intr & (~UHCI_USBINTR_RESUME)) { - dev_dbg(&pdev->dev, "%s: intr = 0x%04x\n", - __func__, intr); - goto reset_needed; - } - return 0; - -reset_needed: - dev_dbg(&pdev->dev, "Performing full reset\n"); - uhci_reset_hc(pdev, base); - return 1; -} -EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc); - -static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask) -{ - u16 cmd; - return !pci_read_config_word(pdev, PCI_COMMAND, &cmd) && (cmd & mask); -} - -#define pio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_IO) -#define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY) - -static void quirk_usb_handoff_uhci(struct pci_dev *pdev) -{ - unsigned long base = 0; - int i; - - if (!pio_enabled(pdev)) - return; - - for (i = 0; i < PCI_ROM_RESOURCE; i++) - if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) { - base = pci_resource_start(pdev, i); - break; - } - - if (base) - uhci_check_and_reset_hc(pdev, base); -} - -static int mmio_resource_enabled(struct pci_dev *pdev, int idx) -{ - return pci_resource_start(pdev, idx) && mmio_enabled(pdev); -} - -static void quirk_usb_handoff_ohci(struct pci_dev *pdev) -{ - void __iomem *base; - u32 control; - u32 fminterval = 0; - bool no_fminterval = false; - int cnt; - - if (!mmio_resource_enabled(pdev, 0)) - return; - - base = pci_ioremap_bar(pdev, 0); - if (base == NULL) - return; - - /* - * ULi M5237 OHCI controller locks the whole system when accessing - * the OHCI_FMINTERVAL offset. - */ - if (pdev->vendor == PCI_VENDOR_ID_AL && pdev->device == 0x5237) - no_fminterval = true; - - control = readl(base + OHCI_CONTROL); - -/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ -#ifdef __hppa__ -#define OHCI_CTRL_MASK (OHCI_CTRL_RWC | OHCI_CTRL_IR) -#else -#define OHCI_CTRL_MASK OHCI_CTRL_RWC - - if (control & OHCI_CTRL_IR) { - int wait_time = 500; /* arbitrary; 5 seconds */ - writel(OHCI_INTR_OC, base + OHCI_INTRENABLE); - writel(OHCI_OCR, base + OHCI_CMDSTATUS); - while (wait_time > 0 && - readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) { - wait_time -= 10; - msleep(10); - } - if (wait_time <= 0) - dev_warn(&pdev->dev, "OHCI: BIOS handoff failed" - " (BIOS bug?) %08x\n", - readl(base + OHCI_CONTROL)); - } -#endif - - /* disable interrupts */ - writel((u32) ~0, base + OHCI_INTRDISABLE); - - /* Reset the USB bus, if the controller isn't already in RESET */ - if (control & OHCI_HCFS) { - /* Go into RESET, preserving RWC (and possibly IR) */ - writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL); - readl(base + OHCI_CONTROL); - - /* drive bus reset for at least 50 ms (7.1.7.5) */ - msleep(50); - } - - /* software reset of the controller, preserving HcFmInterval */ - if (!no_fminterval) - fminterval = readl(base + OHCI_FMINTERVAL); - - writel(OHCI_HCR, base + OHCI_CMDSTATUS); - - /* reset requires max 10 us delay */ - for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */ - if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0) - break; - udelay(1); - } - - if (!no_fminterval) - writel(fminterval, base + OHCI_FMINTERVAL); - - /* Now the controller is safely in SUSPEND and nothing can wake it up */ - iounmap(base); -} - -static const struct dmi_system_id ehci_dmi_nohandoff_table[] = { - { - /* Pegatron Lucid (ExoPC) */ - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "EXOPG06411"), - DMI_MATCH(DMI_BIOS_VERSION, "Lucid-CE-133"), - }, - }, - { - /* Pegatron Lucid (Ordissimo AIRIS) */ - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "M11JB"), - DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), - }, - }, - { - /* Pegatron Lucid (Ordissimo) */ - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"), - DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), - }, - }, - { - /* HASEE E200 */ - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "HASEE"), - DMI_MATCH(DMI_BOARD_NAME, "E210"), - DMI_MATCH(DMI_BIOS_VERSION, "6.00"), - }, - }, - { } -}; - -static void ehci_bios_handoff(struct pci_dev *pdev, - void __iomem *op_reg_base, - u32 cap, u8 offset) -{ - int try_handoff = 1, tried_handoff = 0; - - /* - * The Pegatron Lucid tablet sporadically waits for 98 seconds trying - * the handoff on its unused controller. Skip it. - * - * The HASEE E200 hangs when the semaphore is set (bugzilla #77021). - */ - if (pdev->vendor == 0x8086 && (pdev->device == 0x283a || - pdev->device == 0x27cc)) { - if (dmi_check_system(ehci_dmi_nohandoff_table)) - try_handoff = 0; - } - - if (try_handoff && (cap & EHCI_USBLEGSUP_BIOS)) { - dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n"); - -#if 0 -/* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on, - * but that seems dubious in general (the BIOS left it off intentionally) - * and is known to prevent some systems from booting. so we won't do this - * unless maybe we can determine when we're on a system that needs SMI forced. - */ - /* BIOS workaround (?): be sure the pre-Linux code - * receives the SMI - */ - pci_read_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, &val); - pci_write_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, - val | EHCI_USBLEGCTLSTS_SOOE); -#endif - - /* some systems get upset if this semaphore is - * set for any other reason than forcing a BIOS - * handoff.. - */ - pci_write_config_byte(pdev, offset + 3, 1); - } - - /* if boot firmware now owns EHCI, spin till it hands it over. */ - if (try_handoff) { - int msec = 1000; - while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { - tried_handoff = 1; - msleep(10); - msec -= 10; - pci_read_config_dword(pdev, offset, &cap); - } - } - - if (cap & EHCI_USBLEGSUP_BIOS) { - /* well, possibly buggy BIOS... try to shut it down, - * and hope nothing goes too wrong - */ - if (try_handoff) - dev_warn(&pdev->dev, "EHCI: BIOS handoff failed" - " (BIOS bug?) %08x\n", cap); - pci_write_config_byte(pdev, offset + 2, 0); - } - - /* just in case, always disable EHCI SMIs */ - pci_write_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, 0); - - /* If the BIOS ever owned the controller then we can't expect - * any power sessions to remain intact. - */ - if (tried_handoff) - writel(0, op_reg_base + EHCI_CONFIGFLAG); -} - -static void quirk_usb_disable_ehci(struct pci_dev *pdev) -{ - void __iomem *base, *op_reg_base; - u32 hcc_params, cap, val; - u8 offset, cap_length; - int wait_time, count = 256/4; - - if (!mmio_resource_enabled(pdev, 0)) - return; - - base = pci_ioremap_bar(pdev, 0); - if (base == NULL) - return; - - cap_length = readb(base); - op_reg_base = base + cap_length; - - /* EHCI 0.96 and later may have "extended capabilities" - * spec section 5.1 explains the bios handoff, e.g. for - * booting from USB disk or using a usb keyboard - */ - hcc_params = readl(base + EHCI_HCC_PARAMS); - offset = (hcc_params >> 8) & 0xff; - while (offset && --count) { - pci_read_config_dword(pdev, offset, &cap); - - switch (cap & 0xff) { - case 1: - ehci_bios_handoff(pdev, op_reg_base, cap, offset); - break; - case 0: /* Illegal reserved cap, set cap=0 so we exit */ - cap = 0; /* then fallthrough... */ - default: - dev_warn(&pdev->dev, "EHCI: unrecognized capability " - "%02x\n", cap & 0xff); - } - offset = (cap >> 8) & 0xff; - } - if (!count) - dev_printk(KERN_DEBUG, &pdev->dev, "EHCI: capability loop?\n"); - - /* - * halt EHCI & disable its interrupts in any case - */ - val = readl(op_reg_base + EHCI_USBSTS); - if ((val & EHCI_USBSTS_HALTED) == 0) { - val = readl(op_reg_base + EHCI_USBCMD); - val &= ~EHCI_USBCMD_RUN; - writel(val, op_reg_base + EHCI_USBCMD); - - wait_time = 2000; - do { - writel(0x3f, op_reg_base + EHCI_USBSTS); - udelay(100); - wait_time -= 100; - val = readl(op_reg_base + EHCI_USBSTS); - if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) { - break; - } - } while (wait_time > 0); - } - writel(0, op_reg_base + EHCI_USBINTR); - writel(0x3f, op_reg_base + EHCI_USBSTS); - - iounmap(base); -} - -/* - * handshake - spin reading a register until handshake completes - * @ptr: address of hc register to be read - * @mask: bits to look at in result of read - * @done: value of those bits when handshake succeeds - * @wait_usec: timeout in microseconds - * @delay_usec: delay in microseconds to wait between polling - * - * Polls a register every delay_usec microseconds. - * Returns 0 when the mask bits have the value done. - * Returns -ETIMEDOUT if this condition is not true after - * wait_usec microseconds have passed. - */ -static int handshake(void __iomem *ptr, u32 mask, u32 done, - int wait_usec, int delay_usec) -{ - u32 result; - - do { - result = readl(ptr); - result &= mask; - if (result == done) - return 0; - udelay(delay_usec); - wait_usec -= delay_usec; - } while (wait_usec > 0); - return -ETIMEDOUT; -} - -#define PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI 0x8C31 -#define PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI 0x9C31 - -bool usb_is_intel_ppt_switchable_xhci(struct pci_dev *pdev) -{ - return pdev->class == PCI_CLASS_SERIAL_USB_XHCI && - pdev->vendor == PCI_VENDOR_ID_INTEL && - pdev->device == PCI_DEVICE_ID_INTEL_PANTHERPOINT_XHCI; -} - -/* The Intel Lynx Point chipset also has switchable ports. */ -bool usb_is_intel_lpt_switchable_xhci(struct pci_dev *pdev) -{ - return pdev->class == PCI_CLASS_SERIAL_USB_XHCI && - pdev->vendor == PCI_VENDOR_ID_INTEL && - (pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_XHCI || - pdev->device == PCI_DEVICE_ID_INTEL_LYNX_POINT_LP_XHCI); -} - -bool usb_is_intel_switchable_xhci(struct pci_dev *pdev) -{ - return usb_is_intel_ppt_switchable_xhci(pdev) || - usb_is_intel_lpt_switchable_xhci(pdev); -} -EXPORT_SYMBOL_GPL(usb_is_intel_switchable_xhci); - -/* - * Intel's Panther Point chipset has two host controllers (EHCI and xHCI) that - * share some number of ports. These ports can be switched between either - * controller. Not all of the ports under the EHCI host controller may be - * switchable. - * - * The ports should be switched over to xHCI before PCI probes for any device - * start. This avoids active devices under EHCI being disconnected during the - * port switchover, which could cause loss of data on USB storage devices, or - * failed boot when the root file system is on a USB mass storage device and is - * enumerated under EHCI first. - * - * We write into the xHC's PCI configuration space in some Intel-specific - * registers to switch the ports over. The USB 3.0 terminations and the USB - * 2.0 data wires are switched separately. We want to enable the SuperSpeed - * terminations before switching the USB 2.0 wires over, so that USB 3.0 - * devices connect at SuperSpeed, rather than at USB 2.0 speeds. - */ -void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) -{ - u32 ports_available; - - /* Don't switchover the ports if the user hasn't compiled the xHCI - * driver. Otherwise they will see "dead" USB ports that don't power - * the devices. - */ - if (!IS_ENABLED(CONFIG_USB_XHCI_HCD)) { - dev_warn(&xhci_pdev->dev, - "CONFIG_USB_XHCI_HCD is turned off, " - "defaulting to EHCI.\n"); - dev_warn(&xhci_pdev->dev, - "USB 3.0 devices will work at USB 2.0 speeds.\n"); - usb_disable_xhci_ports(xhci_pdev); - return; - } - - /* Read USB3PRM, the USB 3.0 Port Routing Mask Register - * Indicate the ports that can be changed from OS. - */ - pci_read_config_dword(xhci_pdev, USB_INTEL_USB3PRM, - &ports_available); - - dev_dbg(&xhci_pdev->dev, "Configurable ports to enable SuperSpeed: 0x%x\n", - ports_available); - - /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable - * Register, to turn on SuperSpeed terminations for the - * switchable ports. - */ - pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, - cpu_to_le32(ports_available)); - - pci_read_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, - &ports_available); - dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled " - "under xHCI: 0x%x\n", ports_available); - - /* Read XUSB2PRM, xHCI USB 2.0 Port Routing Mask Register - * Indicate the USB 2.0 ports to be controlled by the xHCI host. - */ - - pci_read_config_dword(xhci_pdev, USB_INTEL_USB2PRM, - &ports_available); - - dev_dbg(&xhci_pdev->dev, "Configurable USB 2.0 ports to hand over to xCHI: 0x%x\n", - ports_available); - - /* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to - * switch the USB 2.0 power and data lines over to the xHCI - * host. - */ - pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, - cpu_to_le32(ports_available)); - - pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, - &ports_available); - dev_dbg(&xhci_pdev->dev, "USB 2.0 ports that are now switched over " - "to xHCI: 0x%x\n", ports_available); -} -EXPORT_SYMBOL_GPL(usb_enable_xhci_ports); - -void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) -{ - pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, 0x0); - pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, 0x0); -} -EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); - -/** - * PCI Quirks for xHCI. - * - * Takes care of the handoff between the Pre-OS (i.e. BIOS) and the OS. - * It signals to the BIOS that the OS wants control of the host controller, - * and then waits 5 seconds for the BIOS to hand over control. - * If we timeout, assume the BIOS is broken and take control anyway. - */ -static void quirk_usb_handoff_xhci(struct pci_dev *pdev) -{ - void __iomem *base; - int ext_cap_offset; - void __iomem *op_reg_base; - u32 val; - int timeout; - int len = pci_resource_len(pdev, 0); - - if (!mmio_resource_enabled(pdev, 0)) - return; - - base = ioremap_nocache(pci_resource_start(pdev, 0), len); - if (base == NULL) - return; - - /* - * Find the Legacy Support Capability register - - * this is optional for xHCI host controllers. - */ - ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET); - do { - if ((ext_cap_offset + sizeof(val)) > len) { - /* We're reading garbage from the controller */ - dev_warn(&pdev->dev, - "xHCI controller failing to respond"); - return; - } - - if (!ext_cap_offset) - /* We've reached the end of the extended capabilities */ - goto hc_init; - - val = readl(base + ext_cap_offset); - if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY) - break; - ext_cap_offset = xhci_find_next_cap_offset(base, ext_cap_offset); - } while (1); - - /* If the BIOS owns the HC, signal that the OS wants it, and wait */ - if (val & XHCI_HC_BIOS_OWNED) { - writel(val | XHCI_HC_OS_OWNED, base + ext_cap_offset); - - /* Wait for 5 seconds with 10 microsecond polling interval */ - timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED, - 0, 5000, 10); - - /* Assume a buggy BIOS and take HC ownership anyway */ - if (timeout) { - dev_warn(&pdev->dev, "xHCI BIOS handoff failed" - " (BIOS bug ?) %08x\n", val); - writel(val & ~XHCI_HC_BIOS_OWNED, base + ext_cap_offset); - } - } - - val = readl(base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); - /* Mask off (turn off) any enabled SMIs */ - val &= XHCI_LEGACY_DISABLE_SMI; - /* Mask all SMI events bits, RW1C */ - val |= XHCI_LEGACY_SMI_EVENTS; - /* Disable any BIOS SMIs and clear all SMI events*/ - writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); - -hc_init: - if (usb_is_intel_switchable_xhci(pdev)) - usb_enable_xhci_ports(pdev); - - op_reg_base = base + XHCI_HC_LENGTH(readl(base)); - - /* Wait for the host controller to be ready before writing any - * operational or runtime registers. Wait 5 seconds and no more. - */ - timeout = handshake(op_reg_base + XHCI_STS_OFFSET, XHCI_STS_CNR, 0, - 5000, 10); - /* Assume a buggy HC and start HC initialization anyway */ - if (timeout) { - val = readl(op_reg_base + XHCI_STS_OFFSET); - dev_warn(&pdev->dev, - "xHCI HW not ready after 5 sec (HC bug?) " - "status = 0x%x\n", val); - } - - /* Send the halt and disable interrupts command */ - val = readl(op_reg_base + XHCI_CMD_OFFSET); - val &= ~(XHCI_CMD_RUN | XHCI_IRQS); - writel(val, op_reg_base + XHCI_CMD_OFFSET); - - /* Wait for the HC to halt - poll every 125 usec (one microframe). */ - timeout = handshake(op_reg_base + XHCI_STS_OFFSET, XHCI_STS_HALT, 1, - XHCI_MAX_HALT_USEC, 125); - if (timeout) { - val = readl(op_reg_base + XHCI_STS_OFFSET); - dev_warn(&pdev->dev, - "xHCI HW did not halt within %d usec " - "status = 0x%x\n", XHCI_MAX_HALT_USEC, val); - } - - iounmap(base); -} - -static void quirk_usb_early_handoff(struct pci_dev *pdev) -{ - /* Skip Netlogic mips SoC's internal PCI USB controller. - * This device does not need/support EHCI/OHCI handoff - */ - if (pdev->vendor == 0x184e) /* vendor Netlogic */ - return; - if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI && - pdev->class != PCI_CLASS_SERIAL_USB_OHCI && - pdev->class != PCI_CLASS_SERIAL_USB_EHCI && - pdev->class != PCI_CLASS_SERIAL_USB_XHCI) - return; - - if (pci_enable_device(pdev) < 0) { - dev_warn(&pdev->dev, "Can't enable PCI device, " - "BIOS handoff failed.\n"); - return; - } - if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI) - quirk_usb_handoff_uhci(pdev); - else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI) - quirk_usb_handoff_ohci(pdev); - else if (pdev->class == PCI_CLASS_SERIAL_USB_EHCI) - quirk_usb_disable_ehci(pdev); - else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) - quirk_usb_handoff_xhci(pdev); - pci_disable_device(pdev); -} -DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff); diff --git a/addons/ehci-pci/src/3.10.108/pci-quirks.h b/addons/ehci-pci/src/3.10.108/pci-quirks.h deleted file mode 100644 index 7f69a391..00000000 --- a/addons/ehci-pci/src/3.10.108/pci-quirks.h +++ /dev/null @@ -1,21 +0,0 @@ -#ifndef __LINUX_USB_PCI_QUIRKS_H -#define __LINUX_USB_PCI_QUIRKS_H - -#ifdef CONFIG_PCI -void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); -int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); -int usb_amd_find_chipset_info(void); -void usb_amd_dev_put(void); -void usb_amd_quirk_pll_disable(void); -void usb_amd_quirk_pll_enable(void); -bool usb_is_intel_switchable_xhci(struct pci_dev *pdev); -void usb_enable_xhci_ports(struct pci_dev *xhci_pdev); -void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); -#else -static inline void usb_amd_quirk_pll_disable(void) {} -static inline void usb_amd_quirk_pll_enable(void) {} -static inline void usb_amd_dev_put(void) {} -static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} -#endif /* CONFIG_PCI */ - -#endif /* __LINUX_USB_PCI_QUIRKS_H */ diff --git a/addons/ehci-pci/src/3.10.108/xhci-ext-caps.h b/addons/ehci-pci/src/3.10.108/xhci-ext-caps.h deleted file mode 100644 index 377f4242..00000000 --- a/addons/ehci-pci/src/3.10.108/xhci-ext-caps.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * xHCI host controller driver - * - * Copyright (C) 2008 Intel Corp. - * - * Author: Sarah Sharp - * Some code borrowed from the Linux EHCI driver. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* Up to 16 ms to halt an HC */ -#define XHCI_MAX_HALT_USEC (16*1000) -/* HC not running - set to 1 when run/stop bit is cleared. */ -#define XHCI_STS_HALT (1<<0) - -/* HCCPARAMS offset from PCI base address */ -#define XHCI_HCC_PARAMS_OFFSET 0x10 -/* HCCPARAMS contains the first extended capability pointer */ -#define XHCI_HCC_EXT_CAPS(p) (((p)>>16)&0xffff) - -/* Command and Status registers offset from the Operational Registers address */ -#define XHCI_CMD_OFFSET 0x00 -#define XHCI_STS_OFFSET 0x04 - -#define XHCI_MAX_EXT_CAPS 50 - -/* Capability Register */ -/* bits 7:0 - how long is the Capabilities register */ -#define XHCI_HC_LENGTH(p) (((p)>>00)&0x00ff) - -/* Extended capability register fields */ -#define XHCI_EXT_CAPS_ID(p) (((p)>>0)&0xff) -#define XHCI_EXT_CAPS_NEXT(p) (((p)>>8)&0xff) -#define XHCI_EXT_CAPS_VAL(p) ((p)>>16) -/* Extended capability IDs - ID 0 reserved */ -#define XHCI_EXT_CAPS_LEGACY 1 -#define XHCI_EXT_CAPS_PROTOCOL 2 -#define XHCI_EXT_CAPS_PM 3 -#define XHCI_EXT_CAPS_VIRT 4 -#define XHCI_EXT_CAPS_ROUTE 5 -/* IDs 6-9 reserved */ -#define XHCI_EXT_CAPS_DEBUG 10 -/* USB Legacy Support Capability - section 7.1.1 */ -#define XHCI_HC_BIOS_OWNED (1 << 16) -#define XHCI_HC_OS_OWNED (1 << 24) - -/* USB Legacy Support Capability - section 7.1.1 */ -/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */ -#define XHCI_LEGACY_SUPPORT_OFFSET (0x00) - -/* USB Legacy Support Control and Status Register - section 7.1.2 */ -/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */ -#define XHCI_LEGACY_CONTROL_OFFSET (0x04) -/* bits 1:3, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */ -#define XHCI_LEGACY_DISABLE_SMI ((0x7 << 1) + (0xff << 5) + (0x7 << 17)) -#define XHCI_LEGACY_SMI_EVENTS (0x7 << 29) - -/* USB 2.0 xHCI 0.96 L1C capability - section 7.2.2.1.3.2 */ -#define XHCI_L1C (1 << 16) - -/* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */ -#define XHCI_HLC (1 << 19) - -/* command register values to disable interrupts and halt the HC */ -/* start/stop HC execution - do not write unless HC is halted*/ -#define XHCI_CMD_RUN (1 << 0) -/* Event Interrupt Enable - get irq when EINT bit is set in USBSTS register */ -#define XHCI_CMD_EIE (1 << 2) -/* Host System Error Interrupt Enable - get irq when HSEIE bit set in USBSTS */ -#define XHCI_CMD_HSEIE (1 << 3) -/* Enable Wrap Event - '1' means xHC generates an event when MFINDEX wraps. */ -#define XHCI_CMD_EWE (1 << 10) - -#define XHCI_IRQS (XHCI_CMD_EIE | XHCI_CMD_HSEIE | XHCI_CMD_EWE) - -/* true: Controller Not Ready to accept doorbell or op reg writes after reset */ -#define XHCI_STS_CNR (1 << 11) - -#include - -/** - * Return the next extended capability pointer register. - * - * @base PCI register base address. - * - * @ext_offset Offset of the 32-bit register that contains the extended - * capabilites pointer. If searching for the first extended capability, pass - * in XHCI_HCC_PARAMS_OFFSET. If searching for the next extended capability, - * pass in the offset of the current extended capability register. - * - * Returns 0 if there is no next extended capability register or returns the register offset - * from the PCI registers base address. - */ -static inline int xhci_find_next_cap_offset(void __iomem *base, int ext_offset) -{ - u32 next; - - next = readl(base + ext_offset); - - if (ext_offset == XHCI_HCC_PARAMS_OFFSET) { - /* Find the first extended capability */ - next = XHCI_HCC_EXT_CAPS(next); - ext_offset = 0; - } else { - /* Find the next extended capability */ - next = XHCI_EXT_CAPS_NEXT(next); - } - - if (!next) - return 0; - /* - * Address calculation from offset of extended capabilities - * (or HCCPARAMS) register - see section 5.3.6 and section 7. - */ - return ext_offset + (next << 2); -} - -/** - * Find the offset of the extended capabilities with capability ID id. - * - * @base PCI MMIO registers base address. - * @ext_offset Offset from base of the first extended capability to look at, - * or the address of HCCPARAMS. - * @id Extended capability ID to search for. - * - * This uses an arbitrary limit of XHCI_MAX_EXT_CAPS extended capabilities - * to make sure that the list doesn't contain a loop. - */ -static inline int xhci_find_ext_cap_by_id(void __iomem *base, int ext_offset, int id) -{ - u32 val; - int limit = XHCI_MAX_EXT_CAPS; - - while (ext_offset && limit > 0) { - val = readl(base + ext_offset); - if (XHCI_EXT_CAPS_ID(val) == id) - break; - ext_offset = xhci_find_next_cap_offset(base, ext_offset); - limit--; - } - if (limit > 0) - return ext_offset; - return 0; -} diff --git a/addons/ehci-pci/src/4.4.180/Makefile b/addons/ehci-pci/src/4.4.180/Makefile deleted file mode 100644 index 898ba621..00000000 --- a/addons/ehci-pci/src/4.4.180/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-y += pci-quirks.o -obj-m += ehci-hcd.o -obj-m += ehci-pci.o diff --git a/addons/ehci-pci/src/4.4.180/ehci-dbg.c b/addons/ehci-pci/src/4.4.180/ehci-dbg.c deleted file mode 100644 index 8e0b9377..00000000 --- a/addons/ehci-pci/src/4.4.180/ehci-dbg.c +++ /dev/null @@ -1,1085 +0,0 @@ -/* - * Copyright (c) 2001-2002 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -#ifdef CONFIG_DYNAMIC_DEBUG - -/* check the values in the HCSPARAMS register - * (host controller _Structural_ parameters) - * see EHCI spec, Table 2-4 for each value - */ -static void dbg_hcs_params (struct ehci_hcd *ehci, char *label) -{ - u32 params = ehci_readl(ehci, &ehci->caps->hcs_params); - - ehci_dbg (ehci, - "%s hcs_params 0x%x dbg=%d%s cc=%d pcc=%d%s%s ports=%d\n", - label, params, - HCS_DEBUG_PORT (params), - HCS_INDICATOR (params) ? " ind" : "", - HCS_N_CC (params), - HCS_N_PCC (params), - HCS_PORTROUTED (params) ? "" : " ordered", - HCS_PPC (params) ? "" : " !ppc", - HCS_N_PORTS (params) - ); - /* Port routing, per EHCI 0.95 Spec, Section 2.2.5 */ - if (HCS_PORTROUTED (params)) { - int i; - char buf [46], tmp [7], byte; - - buf[0] = 0; - for (i = 0; i < HCS_N_PORTS (params); i++) { - // FIXME MIPS won't readb() ... - byte = readb (&ehci->caps->portroute[(i>>1)]); - sprintf(tmp, "%d ", - ((i & 0x1) ? ((byte)&0xf) : ((byte>>4)&0xf))); - strcat(buf, tmp); - } - ehci_dbg (ehci, "%s portroute %s\n", - label, buf); - } -} -#else - -static inline void dbg_hcs_params (struct ehci_hcd *ehci, char *label) {} - -#endif - -#ifdef CONFIG_DYNAMIC_DEBUG - -/* check the values in the HCCPARAMS register - * (host controller _Capability_ parameters) - * see EHCI Spec, Table 2-5 for each value - * */ -static void dbg_hcc_params (struct ehci_hcd *ehci, char *label) -{ - u32 params = ehci_readl(ehci, &ehci->caps->hcc_params); - - if (HCC_ISOC_CACHE (params)) { - ehci_dbg (ehci, - "%s hcc_params %04x caching frame %s%s%s\n", - label, params, - HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", - HCC_CANPARK(params) ? " park" : "", - HCC_64BIT_ADDR(params) ? " 64 bit addr" : ""); - } else { - ehci_dbg (ehci, - "%s hcc_params %04x thresh %d uframes %s%s%s%s%s%s%s\n", - label, - params, - HCC_ISOC_THRES(params), - HCC_PGM_FRAMELISTLEN(params) ? "256/512/1024" : "1024", - HCC_CANPARK(params) ? " park" : "", - HCC_64BIT_ADDR(params) ? " 64 bit addr" : "", - HCC_LPM(params) ? " LPM" : "", - HCC_PER_PORT_CHANGE_EVENT(params) ? " ppce" : "", - HCC_HW_PREFETCH(params) ? " hw prefetch" : "", - HCC_32FRAME_PERIODIC_LIST(params) ? - " 32 periodic list" : ""); - } -} -#else - -static inline void dbg_hcc_params (struct ehci_hcd *ehci, char *label) {} - -#endif - -#ifdef CONFIG_DYNAMIC_DEBUG - -static void __maybe_unused -dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) -{ - ehci_dbg(ehci, "%s td %p n%08x %08x t%08x p0=%08x\n", label, qtd, - hc32_to_cpup(ehci, &qtd->hw_next), - hc32_to_cpup(ehci, &qtd->hw_alt_next), - hc32_to_cpup(ehci, &qtd->hw_token), - hc32_to_cpup(ehci, &qtd->hw_buf [0])); - if (qtd->hw_buf [1]) - ehci_dbg(ehci, " p1=%08x p2=%08x p3=%08x p4=%08x\n", - hc32_to_cpup(ehci, &qtd->hw_buf[1]), - hc32_to_cpup(ehci, &qtd->hw_buf[2]), - hc32_to_cpup(ehci, &qtd->hw_buf[3]), - hc32_to_cpup(ehci, &qtd->hw_buf[4])); -} - -static void __maybe_unused -dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - struct ehci_qh_hw *hw = qh->hw; - - ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label, - qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current); - dbg_qtd("overlay", ehci, (struct ehci_qtd *) &hw->hw_qtd_next); -} - -static void __maybe_unused -dbg_itd (const char *label, struct ehci_hcd *ehci, struct ehci_itd *itd) -{ - ehci_dbg (ehci, "%s [%d] itd %p, next %08x, urb %p\n", - label, itd->frame, itd, hc32_to_cpu(ehci, itd->hw_next), - itd->urb); - ehci_dbg (ehci, - " trans: %08x %08x %08x %08x %08x %08x %08x %08x\n", - hc32_to_cpu(ehci, itd->hw_transaction[0]), - hc32_to_cpu(ehci, itd->hw_transaction[1]), - hc32_to_cpu(ehci, itd->hw_transaction[2]), - hc32_to_cpu(ehci, itd->hw_transaction[3]), - hc32_to_cpu(ehci, itd->hw_transaction[4]), - hc32_to_cpu(ehci, itd->hw_transaction[5]), - hc32_to_cpu(ehci, itd->hw_transaction[6]), - hc32_to_cpu(ehci, itd->hw_transaction[7])); - ehci_dbg (ehci, - " buf: %08x %08x %08x %08x %08x %08x %08x\n", - hc32_to_cpu(ehci, itd->hw_bufp[0]), - hc32_to_cpu(ehci, itd->hw_bufp[1]), - hc32_to_cpu(ehci, itd->hw_bufp[2]), - hc32_to_cpu(ehci, itd->hw_bufp[3]), - hc32_to_cpu(ehci, itd->hw_bufp[4]), - hc32_to_cpu(ehci, itd->hw_bufp[5]), - hc32_to_cpu(ehci, itd->hw_bufp[6])); - ehci_dbg (ehci, " index: %d %d %d %d %d %d %d %d\n", - itd->index[0], itd->index[1], itd->index[2], - itd->index[3], itd->index[4], itd->index[5], - itd->index[6], itd->index[7]); -} - -static void __maybe_unused -dbg_sitd (const char *label, struct ehci_hcd *ehci, struct ehci_sitd *sitd) -{ - ehci_dbg (ehci, "%s [%d] sitd %p, next %08x, urb %p\n", - label, sitd->frame, sitd, hc32_to_cpu(ehci, sitd->hw_next), - sitd->urb); - ehci_dbg (ehci, - " addr %08x sched %04x result %08x buf %08x %08x\n", - hc32_to_cpu(ehci, sitd->hw_fullspeed_ep), - hc32_to_cpu(ehci, sitd->hw_uframe), - hc32_to_cpu(ehci, sitd->hw_results), - hc32_to_cpu(ehci, sitd->hw_buf[0]), - hc32_to_cpu(ehci, sitd->hw_buf[1])); -} - -static int __maybe_unused -dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) -{ - return scnprintf (buf, len, - "%s%sstatus %04x%s%s%s%s%s%s%s%s%s%s%s", - label, label [0] ? " " : "", status, - (status & STS_PPCE_MASK) ? " PPCE" : "", - (status & STS_ASS) ? " Async" : "", - (status & STS_PSS) ? " Periodic" : "", - (status & STS_RECL) ? " Recl" : "", - (status & STS_HALT) ? " Halt" : "", - (status & STS_IAA) ? " IAA" : "", - (status & STS_FATAL) ? " FATAL" : "", - (status & STS_FLR) ? " FLR" : "", - (status & STS_PCD) ? " PCD" : "", - (status & STS_ERR) ? " ERR" : "", - (status & STS_INT) ? " INT" : "" - ); -} - -static int __maybe_unused -dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) -{ - return scnprintf (buf, len, - "%s%sintrenable %02x%s%s%s%s%s%s%s", - label, label [0] ? " " : "", enable, - (enable & STS_PPCE_MASK) ? " PPCE" : "", - (enable & STS_IAA) ? " IAA" : "", - (enable & STS_FATAL) ? " FATAL" : "", - (enable & STS_FLR) ? " FLR" : "", - (enable & STS_PCD) ? " PCD" : "", - (enable & STS_ERR) ? " ERR" : "", - (enable & STS_INT) ? " INT" : "" - ); -} - -static const char *const fls_strings [] = - { "1024", "512", "256", "??" }; - -static int -dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) -{ - return scnprintf (buf, len, - "%s%scommand %07x %s%s%s%s%s%s=%d ithresh=%d%s%s%s%s " - "period=%s%s %s", - label, label [0] ? " " : "", command, - (command & CMD_HIRD) ? " HIRD" : "", - (command & CMD_PPCEE) ? " PPCEE" : "", - (command & CMD_FSP) ? " FSP" : "", - (command & CMD_ASPE) ? " ASPE" : "", - (command & CMD_PSPE) ? " PSPE" : "", - (command & CMD_PARK) ? " park" : "(park)", - CMD_PARK_CNT (command), - (command >> 16) & 0x3f, - (command & CMD_LRESET) ? " LReset" : "", - (command & CMD_IAAD) ? " IAAD" : "", - (command & CMD_ASE) ? " Async" : "", - (command & CMD_PSE) ? " Periodic" : "", - fls_strings [(command >> 2) & 0x3], - (command & CMD_RESET) ? " Reset" : "", - (command & CMD_RUN) ? "RUN" : "HALT" - ); -} - -static int -dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) -{ - char *sig; - - /* signaling state */ - switch (status & (3 << 10)) { - case 0 << 10: sig = "se0"; break; - case 1 << 10: sig = "k"; break; /* low speed */ - case 2 << 10: sig = "j"; break; - default: sig = "?"; break; - } - - return scnprintf (buf, len, - "%s%sport:%d status %06x %d %s%s%s%s%s%s " - "sig=%s%s%s%s%s%s%s%s%s%s%s", - label, label [0] ? " " : "", port, status, - status>>25,/*device address */ - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ACK ? - " ACK" : "", - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_NYET ? - " NYET" : "", - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_STALL ? - " STALL" : "", - (status & PORT_SSTS)>>23 == PORTSC_SUSPEND_STS_ERR ? - " ERR" : "", - (status & PORT_POWER) ? " POWER" : "", - (status & PORT_OWNER) ? " OWNER" : "", - sig, - (status & PORT_LPM) ? " LPM" : "", - (status & PORT_RESET) ? " RESET" : "", - (status & PORT_SUSPEND) ? " SUSPEND" : "", - (status & PORT_RESUME) ? " RESUME" : "", - (status & PORT_OCC) ? " OCC" : "", - (status & PORT_OC) ? " OC" : "", - (status & PORT_PEC) ? " PEC" : "", - (status & PORT_PE) ? " PE" : "", - (status & PORT_CSC) ? " CSC" : "", - (status & PORT_CONNECT) ? " CONNECT" : ""); -} - -#else -static inline void __maybe_unused -dbg_qh (char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) -{} - -static inline int __maybe_unused -dbg_status_buf (char *buf, unsigned len, const char *label, u32 status) -{ return 0; } - -static inline int __maybe_unused -dbg_command_buf (char *buf, unsigned len, const char *label, u32 command) -{ return 0; } - -static inline int __maybe_unused -dbg_intr_buf (char *buf, unsigned len, const char *label, u32 enable) -{ return 0; } - -static inline int __maybe_unused -dbg_port_buf (char *buf, unsigned len, const char *label, int port, u32 status) -{ return 0; } - -#endif /* CONFIG_DYNAMIC_DEBUG */ - -/* functions have the "wrong" filename when they're output... */ -#define dbg_status(ehci, label, status) { \ - char _buf [80]; \ - dbg_status_buf (_buf, sizeof _buf, label, status); \ - ehci_dbg (ehci, "%s\n", _buf); \ -} - -#define dbg_cmd(ehci, label, command) { \ - char _buf [80]; \ - dbg_command_buf (_buf, sizeof _buf, label, command); \ - ehci_dbg (ehci, "%s\n", _buf); \ -} - -#define dbg_port(ehci, label, port, status) { \ - char _buf [80]; \ - dbg_port_buf (_buf, sizeof _buf, label, port, status); \ - ehci_dbg (ehci, "%s\n", _buf); \ -} - -/*-------------------------------------------------------------------------*/ - -#ifdef STUB_DEBUG_FILES - -static inline void create_debug_files (struct ehci_hcd *bus) { } -static inline void remove_debug_files (struct ehci_hcd *bus) { } - -#else - -/* troubleshooting help: expose state in debugfs */ - -static int debug_async_open(struct inode *, struct file *); -static int debug_bandwidth_open(struct inode *, struct file *); -static int debug_periodic_open(struct inode *, struct file *); -static int debug_registers_open(struct inode *, struct file *); - -static ssize_t debug_output(struct file*, char __user*, size_t, loff_t*); -static int debug_close(struct inode *, struct file *); - -static const struct file_operations debug_async_fops = { - .owner = THIS_MODULE, - .open = debug_async_open, - .read = debug_output, - .release = debug_close, - .llseek = default_llseek, -}; -static const struct file_operations debug_bandwidth_fops = { - .owner = THIS_MODULE, - .open = debug_bandwidth_open, - .read = debug_output, - .release = debug_close, - .llseek = default_llseek, -}; -static const struct file_operations debug_periodic_fops = { - .owner = THIS_MODULE, - .open = debug_periodic_open, - .read = debug_output, - .release = debug_close, - .llseek = default_llseek, -}; -static const struct file_operations debug_registers_fops = { - .owner = THIS_MODULE, - .open = debug_registers_open, - .read = debug_output, - .release = debug_close, - .llseek = default_llseek, -}; - -static struct dentry *ehci_debug_root; - -struct debug_buffer { - ssize_t (*fill_func)(struct debug_buffer *); /* fill method */ - struct usb_bus *bus; - struct mutex mutex; /* protect filling of buffer */ - size_t count; /* number of characters filled into buffer */ - char *output_buf; - size_t alloc_size; -}; - -#define speed_char(info1) ({ char tmp; \ - switch (info1 & (3 << 12)) { \ - case QH_FULL_SPEED: tmp = 'f'; break; \ - case QH_LOW_SPEED: tmp = 'l'; break; \ - case QH_HIGH_SPEED: tmp = 'h'; break; \ - default: tmp = '?'; break; \ - } tmp; }) - -static inline char token_mark(struct ehci_hcd *ehci, __hc32 token) -{ - __u32 v = hc32_to_cpu(ehci, token); - - if (v & QTD_STS_ACTIVE) - return '*'; - if (v & QTD_STS_HALT) - return '-'; - if (!IS_SHORT_READ (v)) - return ' '; - /* tries to advance through hw_alt_next */ - return '/'; -} - -static void qh_lines ( - struct ehci_hcd *ehci, - struct ehci_qh *qh, - char **nextp, - unsigned *sizep -) -{ - u32 scratch; - u32 hw_curr; - struct list_head *entry; - struct ehci_qtd *td; - unsigned temp; - unsigned size = *sizep; - char *next = *nextp; - char mark; - __le32 list_end = EHCI_LIST_END(ehci); - struct ehci_qh_hw *hw = qh->hw; - - if (hw->hw_qtd_next == list_end) /* NEC does this */ - mark = '@'; - else - mark = token_mark(ehci, hw->hw_token); - if (mark == '/') { /* qh_alt_next controls qh advance? */ - if ((hw->hw_alt_next & QTD_MASK(ehci)) - == ehci->async->hw->hw_alt_next) - mark = '#'; /* blocked */ - else if (hw->hw_alt_next == list_end) - mark = '.'; /* use hw_qtd_next */ - /* else alt_next points to some other qtd */ - } - scratch = hc32_to_cpup(ehci, &hw->hw_info1); - hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &hw->hw_current) : 0; - temp = scnprintf (next, size, - "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)", - qh, scratch & 0x007f, - speed_char (scratch), - (scratch >> 8) & 0x000f, - scratch, hc32_to_cpup(ehci, &hw->hw_info2), - hc32_to_cpup(ehci, &hw->hw_token), mark, - (cpu_to_hc32(ehci, QTD_TOGGLE) & hw->hw_token) - ? "data1" : "data0", - (hc32_to_cpup(ehci, &hw->hw_alt_next) >> 1) & 0x0f); - size -= temp; - next += temp; - - /* hc may be modifying the list as we read it ... */ - list_for_each (entry, &qh->qtd_list) { - td = list_entry (entry, struct ehci_qtd, qtd_list); - scratch = hc32_to_cpup(ehci, &td->hw_token); - mark = ' '; - if (hw_curr == td->qtd_dma) - mark = '*'; - else if (hw->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma)) - mark = '+'; - else if (QTD_LENGTH (scratch)) { - if (td->hw_alt_next == ehci->async->hw->hw_alt_next) - mark = '#'; - else if (td->hw_alt_next != list_end) - mark = '/'; - } - temp = snprintf (next, size, - "\n\t%p%c%s len=%d %08x urb %p", - td, mark, ({ char *tmp; - switch ((scratch>>8)&0x03) { - case 0: tmp = "out"; break; - case 1: tmp = "in"; break; - case 2: tmp = "setup"; break; - default: tmp = "?"; break; - } tmp;}), - (scratch >> 16) & 0x7fff, - scratch, - td->urb); - if (size < temp) - temp = size; - size -= temp; - next += temp; - if (temp == size) - goto done; - } - - temp = snprintf (next, size, "\n"); - if (size < temp) - temp = size; - size -= temp; - next += temp; - -done: - *sizep = size; - *nextp = next; -} - -static ssize_t fill_async_buffer(struct debug_buffer *buf) -{ - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - unsigned long flags; - unsigned temp, size; - char *next; - struct ehci_qh *qh; - - hcd = bus_to_hcd(buf->bus); - ehci = hcd_to_ehci (hcd); - next = buf->output_buf; - size = buf->alloc_size; - - *next = 0; - - /* dumps a snapshot of the async schedule. - * usually empty except for long-term bulk reads, or head. - * one QH per line, and TDs we know about - */ - spin_lock_irqsave (&ehci->lock, flags); - for (qh = ehci->async->qh_next.qh; size > 0 && qh; qh = qh->qh_next.qh) - qh_lines (ehci, qh, &next, &size); - if (!list_empty(&ehci->async_unlink) && size > 0) { - temp = scnprintf(next, size, "\nunlink =\n"); - size -= temp; - next += temp; - - list_for_each_entry(qh, &ehci->async_unlink, unlink_node) { - if (size <= 0) - break; - qh_lines(ehci, qh, &next, &size); - } - } - spin_unlock_irqrestore (&ehci->lock, flags); - - return strlen(buf->output_buf); -} - -static ssize_t fill_bandwidth_buffer(struct debug_buffer *buf) -{ - struct ehci_hcd *ehci; - struct ehci_tt *tt; - struct ehci_per_sched *ps; - unsigned temp, size; - char *next; - unsigned i; - u8 *bw; - u16 *bf; - u8 budget[EHCI_BANDWIDTH_SIZE]; - - ehci = hcd_to_ehci(bus_to_hcd(buf->bus)); - next = buf->output_buf; - size = buf->alloc_size; - - *next = 0; - - spin_lock_irq(&ehci->lock); - - /* Dump the HS bandwidth table */ - temp = scnprintf(next, size, - "HS bandwidth allocation (us per microframe)\n"); - size -= temp; - next += temp; - for (i = 0; i < EHCI_BANDWIDTH_SIZE; i += 8) { - bw = &ehci->bandwidth[i]; - temp = scnprintf(next, size, - "%2u: %4u%4u%4u%4u%4u%4u%4u%4u\n", - i, bw[0], bw[1], bw[2], bw[3], - bw[4], bw[5], bw[6], bw[7]); - size -= temp; - next += temp; - } - - /* Dump all the FS/LS tables */ - list_for_each_entry(tt, &ehci->tt_list, tt_list) { - temp = scnprintf(next, size, - "\nTT %s port %d FS/LS bandwidth allocation (us per frame)\n", - dev_name(&tt->usb_tt->hub->dev), - tt->tt_port + !!tt->usb_tt->multi); - size -= temp; - next += temp; - - bf = tt->bandwidth; - temp = scnprintf(next, size, - " %5u%5u%5u%5u%5u%5u%5u%5u\n", - bf[0], bf[1], bf[2], bf[3], - bf[4], bf[5], bf[6], bf[7]); - size -= temp; - next += temp; - - temp = scnprintf(next, size, - "FS/LS budget (us per microframe)\n"); - size -= temp; - next += temp; - compute_tt_budget(budget, tt); - for (i = 0; i < EHCI_BANDWIDTH_SIZE; i += 8) { - bw = &budget[i]; - temp = scnprintf(next, size, - "%2u: %4u%4u%4u%4u%4u%4u%4u%4u\n", - i, bw[0], bw[1], bw[2], bw[3], - bw[4], bw[5], bw[6], bw[7]); - size -= temp; - next += temp; - } - list_for_each_entry(ps, &tt->ps_list, ps_list) { - temp = scnprintf(next, size, - "%s ep %02x: %4u @ %2u.%u+%u mask %04x\n", - dev_name(&ps->udev->dev), - ps->ep->desc.bEndpointAddress, - ps->tt_usecs, - ps->bw_phase, ps->phase_uf, - ps->bw_period, ps->cs_mask); - size -= temp; - next += temp; - } - } - spin_unlock_irq(&ehci->lock); - - return next - buf->output_buf; -} - -#define DBG_SCHED_LIMIT 64 -static ssize_t fill_periodic_buffer(struct debug_buffer *buf) -{ - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - unsigned long flags; - union ehci_shadow p, *seen; - unsigned temp, size, seen_count; - char *next; - unsigned i; - __hc32 tag; - - seen = kmalloc(DBG_SCHED_LIMIT * sizeof *seen, GFP_ATOMIC); - if (!seen) - return 0; - seen_count = 0; - - hcd = bus_to_hcd(buf->bus); - ehci = hcd_to_ehci (hcd); - next = buf->output_buf; - size = buf->alloc_size; - - temp = scnprintf (next, size, "size = %d\n", ehci->periodic_size); - size -= temp; - next += temp; - - /* dump a snapshot of the periodic schedule. - * iso changes, interrupt usually doesn't. - */ - spin_lock_irqsave (&ehci->lock, flags); - for (i = 0; i < ehci->periodic_size; i++) { - p = ehci->pshadow [i]; - if (likely (!p.ptr)) - continue; - tag = Q_NEXT_TYPE(ehci, ehci->periodic [i]); - - temp = scnprintf (next, size, "%4d: ", i); - size -= temp; - next += temp; - - do { - struct ehci_qh_hw *hw; - - switch (hc32_to_cpu(ehci, tag)) { - case Q_TYPE_QH: - hw = p.qh->hw; - temp = scnprintf (next, size, " qh%d-%04x/%p", - p.qh->ps.period, - hc32_to_cpup(ehci, - &hw->hw_info2) - /* uframe masks */ - & (QH_CMASK | QH_SMASK), - p.qh); - size -= temp; - next += temp; - /* don't repeat what follows this qh */ - for (temp = 0; temp < seen_count; temp++) { - if (seen [temp].ptr != p.ptr) - continue; - if (p.qh->qh_next.ptr) { - temp = scnprintf (next, size, - " ..."); - size -= temp; - next += temp; - } - break; - } - /* show more info the first time around */ - if (temp == seen_count) { - u32 scratch = hc32_to_cpup(ehci, - &hw->hw_info1); - struct ehci_qtd *qtd; - char *type = ""; - - /* count tds, get ep direction */ - temp = 0; - list_for_each_entry (qtd, - &p.qh->qtd_list, - qtd_list) { - temp++; - switch (0x03 & (hc32_to_cpu( - ehci, - qtd->hw_token) >> 8)) { - case 0: type = "out"; continue; - case 1: type = "in"; continue; - } - } - - temp = scnprintf (next, size, - " (%c%d ep%d%s " - "[%d/%d] q%d p%d)", - speed_char (scratch), - scratch & 0x007f, - (scratch >> 8) & 0x000f, type, - p.qh->ps.usecs, - p.qh->ps.c_usecs, - temp, - 0x7ff & (scratch >> 16)); - - if (seen_count < DBG_SCHED_LIMIT) - seen [seen_count++].qh = p.qh; - } else - temp = 0; - tag = Q_NEXT_TYPE(ehci, hw->hw_next); - p = p.qh->qh_next; - break; - case Q_TYPE_FSTN: - temp = scnprintf (next, size, - " fstn-%8x/%p", p.fstn->hw_prev, - p.fstn); - tag = Q_NEXT_TYPE(ehci, p.fstn->hw_next); - p = p.fstn->fstn_next; - break; - case Q_TYPE_ITD: - temp = scnprintf (next, size, - " itd/%p", p.itd); - tag = Q_NEXT_TYPE(ehci, p.itd->hw_next); - p = p.itd->itd_next; - break; - case Q_TYPE_SITD: - temp = scnprintf (next, size, - " sitd%d-%04x/%p", - p.sitd->stream->ps.period, - hc32_to_cpup(ehci, &p.sitd->hw_uframe) - & 0x0000ffff, - p.sitd); - tag = Q_NEXT_TYPE(ehci, p.sitd->hw_next); - p = p.sitd->sitd_next; - break; - } - size -= temp; - next += temp; - } while (p.ptr); - - temp = scnprintf (next, size, "\n"); - size -= temp; - next += temp; - } - spin_unlock_irqrestore (&ehci->lock, flags); - kfree (seen); - - return buf->alloc_size - size; -} -#undef DBG_SCHED_LIMIT - -static const char *rh_state_string(struct ehci_hcd *ehci) -{ - switch (ehci->rh_state) { - case EHCI_RH_HALTED: - return "halted"; - case EHCI_RH_SUSPENDED: - return "suspended"; - case EHCI_RH_RUNNING: - return "running"; - case EHCI_RH_STOPPING: - return "stopping"; - } - return "?"; -} - -static ssize_t fill_registers_buffer(struct debug_buffer *buf) -{ - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - unsigned long flags; - unsigned temp, size, i; - char *next, scratch [80]; - static char fmt [] = "%*s\n"; - static char label [] = ""; - - hcd = bus_to_hcd(buf->bus); - ehci = hcd_to_ehci (hcd); - next = buf->output_buf; - size = buf->alloc_size; - - spin_lock_irqsave (&ehci->lock, flags); - - if (!HCD_HW_ACCESSIBLE(hcd)) { - size = scnprintf (next, size, - "bus %s, device %s\n" - "%s\n" - "SUSPENDED (no register access)\n", - hcd->self.controller->bus->name, - dev_name(hcd->self.controller), - hcd->product_desc); - goto done; - } - - /* Capability Registers */ - i = HC_VERSION(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - temp = scnprintf (next, size, - "bus %s, device %s\n" - "%s\n" - "EHCI %x.%02x, rh state %s\n", - hcd->self.controller->bus->name, - dev_name(hcd->self.controller), - hcd->product_desc, - i >> 8, i & 0x0ff, rh_state_string(ehci)); - size -= temp; - next += temp; - -#ifdef CONFIG_PCI - /* EHCI 0.96 and later may have "extended capabilities" */ - if (dev_is_pci(hcd->self.controller)) { - struct pci_dev *pdev; - u32 offset, cap, cap2; - unsigned count = 256/4; - - pdev = to_pci_dev(ehci_to_hcd(ehci)->self.controller); - offset = HCC_EXT_CAPS(ehci_readl(ehci, - &ehci->caps->hcc_params)); - while (offset && count--) { - pci_read_config_dword (pdev, offset, &cap); - switch (cap & 0xff) { - case 1: - temp = scnprintf (next, size, - "ownership %08x%s%s\n", cap, - (cap & (1 << 24)) ? " linux" : "", - (cap & (1 << 16)) ? " firmware" : ""); - size -= temp; - next += temp; - - offset += 4; - pci_read_config_dword (pdev, offset, &cap2); - temp = scnprintf (next, size, - "SMI sts/enable 0x%08x\n", cap2); - size -= temp; - next += temp; - break; - case 0: /* illegal reserved capability */ - cap = 0; - /* FALLTHROUGH */ - default: /* unknown */ - break; - } - offset = (cap >> 8) & 0xff; - } - } -#endif - - // FIXME interpret both types of params - i = ehci_readl(ehci, &ehci->caps->hcs_params); - temp = scnprintf (next, size, "structural params 0x%08x\n", i); - size -= temp; - next += temp; - - i = ehci_readl(ehci, &ehci->caps->hcc_params); - temp = scnprintf (next, size, "capability params 0x%08x\n", i); - size -= temp; - next += temp; - - /* Operational Registers */ - temp = dbg_status_buf (scratch, sizeof scratch, label, - ehci_readl(ehci, &ehci->regs->status)); - temp = scnprintf (next, size, fmt, temp, scratch); - size -= temp; - next += temp; - - temp = dbg_command_buf (scratch, sizeof scratch, label, - ehci_readl(ehci, &ehci->regs->command)); - temp = scnprintf (next, size, fmt, temp, scratch); - size -= temp; - next += temp; - - temp = dbg_intr_buf (scratch, sizeof scratch, label, - ehci_readl(ehci, &ehci->regs->intr_enable)); - temp = scnprintf (next, size, fmt, temp, scratch); - size -= temp; - next += temp; - - temp = scnprintf (next, size, "uframe %04x\n", - ehci_read_frame_index(ehci)); - size -= temp; - next += temp; - - for (i = 1; i <= HCS_N_PORTS (ehci->hcs_params); i++) { - temp = dbg_port_buf (scratch, sizeof scratch, label, i, - ehci_readl(ehci, - &ehci->regs->port_status[i - 1])); - temp = scnprintf (next, size, fmt, temp, scratch); - size -= temp; - next += temp; - if (i == HCS_DEBUG_PORT(ehci->hcs_params) && ehci->debug) { - temp = scnprintf (next, size, - " debug control %08x\n", - ehci_readl(ehci, - &ehci->debug->control)); - size -= temp; - next += temp; - } - } - - if (!list_empty(&ehci->async_unlink)) { - temp = scnprintf(next, size, "async unlink qh %p\n", - list_first_entry(&ehci->async_unlink, - struct ehci_qh, unlink_node)); - size -= temp; - next += temp; - } - -#ifdef EHCI_STATS - temp = scnprintf (next, size, - "irq normal %ld err %ld iaa %ld (lost %ld)\n", - ehci->stats.normal, ehci->stats.error, ehci->stats.iaa, - ehci->stats.lost_iaa); - size -= temp; - next += temp; - - temp = scnprintf (next, size, "complete %ld unlink %ld\n", - ehci->stats.complete, ehci->stats.unlink); - size -= temp; - next += temp; -#endif - -done: - spin_unlock_irqrestore (&ehci->lock, flags); - - return buf->alloc_size - size; -} - -static struct debug_buffer *alloc_buffer(struct usb_bus *bus, - ssize_t (*fill_func)(struct debug_buffer *)) -{ - struct debug_buffer *buf; - - buf = kzalloc(sizeof(struct debug_buffer), GFP_KERNEL); - - if (buf) { - buf->bus = bus; - buf->fill_func = fill_func; - mutex_init(&buf->mutex); - buf->alloc_size = PAGE_SIZE; - } - - return buf; -} - -static int fill_buffer(struct debug_buffer *buf) -{ - int ret = 0; - - if (!buf->output_buf) - buf->output_buf = vmalloc(buf->alloc_size); - - if (!buf->output_buf) { - ret = -ENOMEM; - goto out; - } - - ret = buf->fill_func(buf); - - if (ret >= 0) { - buf->count = ret; - ret = 0; - } - -out: - return ret; -} - -static ssize_t debug_output(struct file *file, char __user *user_buf, - size_t len, loff_t *offset) -{ - struct debug_buffer *buf = file->private_data; - int ret = 0; - - mutex_lock(&buf->mutex); - if (buf->count == 0) { - ret = fill_buffer(buf); - if (ret != 0) { - mutex_unlock(&buf->mutex); - goto out; - } - } - mutex_unlock(&buf->mutex); - - ret = simple_read_from_buffer(user_buf, len, offset, - buf->output_buf, buf->count); - -out: - return ret; - -} - -static int debug_close(struct inode *inode, struct file *file) -{ - struct debug_buffer *buf = file->private_data; - - if (buf) { - vfree(buf->output_buf); - kfree(buf); - } - - return 0; -} - -static int debug_async_open(struct inode *inode, struct file *file) -{ - file->private_data = alloc_buffer(inode->i_private, fill_async_buffer); - - return file->private_data ? 0 : -ENOMEM; -} - -static int debug_bandwidth_open(struct inode *inode, struct file *file) -{ - file->private_data = alloc_buffer(inode->i_private, - fill_bandwidth_buffer); - - return file->private_data ? 0 : -ENOMEM; -} - -static int debug_periodic_open(struct inode *inode, struct file *file) -{ - struct debug_buffer *buf; - buf = alloc_buffer(inode->i_private, fill_periodic_buffer); - if (!buf) - return -ENOMEM; - - buf->alloc_size = (sizeof(void *) == 4 ? 6 : 8)*PAGE_SIZE; - file->private_data = buf; - return 0; -} - -static int debug_registers_open(struct inode *inode, struct file *file) -{ - file->private_data = alloc_buffer(inode->i_private, - fill_registers_buffer); - - return file->private_data ? 0 : -ENOMEM; -} - -static inline void create_debug_files (struct ehci_hcd *ehci) -{ - struct usb_bus *bus = &ehci_to_hcd(ehci)->self; - - ehci->debug_dir = debugfs_create_dir(bus->bus_name, ehci_debug_root); - if (!ehci->debug_dir) - return; - - if (!debugfs_create_file("async", S_IRUGO, ehci->debug_dir, bus, - &debug_async_fops)) - goto file_error; - - if (!debugfs_create_file("bandwidth", S_IRUGO, ehci->debug_dir, bus, - &debug_bandwidth_fops)) - goto file_error; - - if (!debugfs_create_file("periodic", S_IRUGO, ehci->debug_dir, bus, - &debug_periodic_fops)) - goto file_error; - - if (!debugfs_create_file("registers", S_IRUGO, ehci->debug_dir, bus, - &debug_registers_fops)) - goto file_error; - - return; - -file_error: - debugfs_remove_recursive(ehci->debug_dir); -} - -static inline void remove_debug_files (struct ehci_hcd *ehci) -{ - debugfs_remove_recursive(ehci->debug_dir); -} - -#endif /* STUB_DEBUG_FILES */ diff --git a/addons/ehci-pci/src/4.4.180/ehci-hcd.c b/addons/ehci-pci/src/4.4.180/ehci-hcd.c deleted file mode 100644 index f7661d97..00000000 --- a/addons/ehci-pci/src/4.4.180/ehci-hcd.c +++ /dev/null @@ -1,1396 +0,0 @@ -/* - * Enhanced Host Controller Interface (EHCI) driver for USB. - * - * Maintainer: Alan Stern - * - * Copyright (c) 2000-2004 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#if defined(CONFIG_PPC_PS3) -#include -#endif - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI hc_driver implementation ... experimental, incomplete. - * Based on the final 1.0 register interface specification. - * - * USB 2.0 shows up in upcoming www.pcmcia.org technology. - * First was PCMCIA, like ISA; then CardBus, which is PCI. - * Next comes "CardBay", using USB 2.0 signals. - * - * Contains additional contributions by Brad Hards, Rory Bolt, and others. - * Special thanks to Intel and VIA for providing host controllers to - * test this driver on, and Cypress (including In-System Design) for - * providing early devices for those host controllers to talk to! - */ - -#define DRIVER_AUTHOR "David Brownell" -#define DRIVER_DESC "USB 2.0 'Enhanced' Host Controller (EHCI) Driver" - -static const char hcd_name [] = "ehci_hcd"; - - -#undef EHCI_URB_TRACE - -/* magic numbers that can affect system performance */ -#define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ -#define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ -#define EHCI_TUNE_RL_TT 0 -#define EHCI_TUNE_MULT_HS 1 /* 1-3 transactions/uframe; 4.10.3 */ -#define EHCI_TUNE_MULT_TT 1 -/* - * Some drivers think it's safe to schedule isochronous transfers more than - * 256 ms into the future (partly as a result of an old bug in the scheduling - * code). In an attempt to avoid trouble, we will use a minimum scheduling - * length of 512 frames instead of 256. - */ -#define EHCI_TUNE_FLS 1 /* (medium) 512-frame schedule */ - -/* Initial IRQ latency: faster than hw default */ -static int log2_irq_thresh = 0; // 0 to 6 -module_param (log2_irq_thresh, int, S_IRUGO); -MODULE_PARM_DESC (log2_irq_thresh, "log2 IRQ latency, 1-64 microframes"); - -/* initial park setting: slower than hw default */ -static unsigned park = 0; -module_param (park, uint, S_IRUGO); -MODULE_PARM_DESC (park, "park setting; 1-3 back-to-back async packets"); - -/* for flakey hardware, ignore overcurrent indicators */ -static bool ignore_oc = 0; -module_param (ignore_oc, bool, S_IRUGO); -MODULE_PARM_DESC (ignore_oc, "ignore bogus hardware overcurrent indications"); - -#define INTR_MASK (STS_IAA | STS_FATAL | STS_PCD | STS_ERR | STS_INT) - -/*-------------------------------------------------------------------------*/ - -#include "ehci.h" -#include "pci-quirks.h" - -static void compute_tt_budget(u8 budget_table[EHCI_BANDWIDTH_SIZE], - struct ehci_tt *tt); - -/* - * The MosChip MCS9990 controller updates its microframe counter - * a little before the frame counter, and occasionally we will read - * the invalid intermediate value. Avoid problems by checking the - * microframe number (the low-order 3 bits); if they are 0 then - * re-read the register to get the correct value. - */ -static unsigned ehci_moschip_read_frame_index(struct ehci_hcd *ehci) -{ - unsigned uf; - - uf = ehci_readl(ehci, &ehci->regs->frame_index); - if (unlikely((uf & 7) == 0)) - uf = ehci_readl(ehci, &ehci->regs->frame_index); - return uf; -} - -static inline unsigned ehci_read_frame_index(struct ehci_hcd *ehci) -{ - if (ehci->frame_index_bug) - return ehci_moschip_read_frame_index(ehci); - return ehci_readl(ehci, &ehci->regs->frame_index); -} - -#include "ehci-dbg.c" - -/*-------------------------------------------------------------------------*/ - -/* - * ehci_handshake - spin reading hc until handshake completes or fails - * @ptr: address of hc register to be read - * @mask: bits to look at in result of read - * @done: value of those bits when handshake succeeds - * @usec: timeout in microseconds - * - * Returns negative errno, or zero on success - * - * Success happens when the "mask" bits have the specified value (hardware - * handshake done). There are two failure modes: "usec" have passed (major - * hardware flakeout), or the register reads as all-ones (hardware removed). - * - * That last failure should_only happen in cases like physical cardbus eject - * before driver shutdown. But it also seems to be caused by bugs in cardbus - * bridge shutdown: shutting down the bridge before the devices using it. - */ -int ehci_handshake(struct ehci_hcd *ehci, void __iomem *ptr, - u32 mask, u32 done, int usec) -{ - u32 result; - - do { - result = ehci_readl(ehci, ptr); - if (result == ~(u32)0) /* card removed */ - return -ENODEV; - result &= mask; - if (result == done) - return 0; - udelay (1); - usec--; - } while (usec > 0); - return -ETIMEDOUT; -} -EXPORT_SYMBOL_GPL(ehci_handshake); - -/* check TDI/ARC silicon is in host mode */ -static int tdi_in_host_mode (struct ehci_hcd *ehci) -{ - u32 tmp; - - tmp = ehci_readl(ehci, &ehci->regs->usbmode); - return (tmp & 3) == USBMODE_CM_HC; -} - -/* - * Force HC to halt state from unknown (EHCI spec section 2.3). - * Must be called with interrupts enabled and the lock not held. - */ -static int ehci_halt (struct ehci_hcd *ehci) -{ - u32 temp; - - spin_lock_irq(&ehci->lock); - - /* disable any irqs left enabled by previous code */ - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - - if (ehci_is_TDI(ehci) && !tdi_in_host_mode(ehci)) { - spin_unlock_irq(&ehci->lock); - return 0; - } - - /* - * This routine gets called during probe before ehci->command - * has been initialized, so we can't rely on its value. - */ - ehci->command &= ~CMD_RUN; - temp = ehci_readl(ehci, &ehci->regs->command); - temp &= ~(CMD_RUN | CMD_IAAD); - ehci_writel(ehci, temp, &ehci->regs->command); - - spin_unlock_irq(&ehci->lock); - synchronize_irq(ehci_to_hcd(ehci)->irq); - - return ehci_handshake(ehci, &ehci->regs->status, - STS_HALT, STS_HALT, 16 * 125); -} - -/* put TDI/ARC silicon into EHCI mode */ -static void tdi_reset (struct ehci_hcd *ehci) -{ - u32 tmp; - - tmp = ehci_readl(ehci, &ehci->regs->usbmode); - tmp |= USBMODE_CM_HC; - /* The default byte access to MMR space is LE after - * controller reset. Set the required endian mode - * for transfer buffers to match the host microprocessor - */ - if (ehci_big_endian_mmio(ehci)) - tmp |= USBMODE_BE; - ehci_writel(ehci, tmp, &ehci->regs->usbmode); -} - -/* - * Reset a non-running (STS_HALT == 1) controller. - * Must be called with interrupts enabled and the lock not held. - */ -int ehci_reset(struct ehci_hcd *ehci) -{ - int retval; - u32 command = ehci_readl(ehci, &ehci->regs->command); - - /* If the EHCI debug controller is active, special care must be - * taken before and after a host controller reset */ - if (ehci->debug && !dbgp_reset_prep(ehci_to_hcd(ehci))) - ehci->debug = NULL; - - command |= CMD_RESET; - dbg_cmd (ehci, "reset", command); - ehci_writel(ehci, command, &ehci->regs->command); - ehci->rh_state = EHCI_RH_HALTED; - ehci->next_statechange = jiffies; - retval = ehci_handshake(ehci, &ehci->regs->command, - CMD_RESET, 0, 250 * 1000); - - if (ehci->has_hostpc) { - ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS, - &ehci->regs->usbmode_ex); - ehci_writel(ehci, TXFIFO_DEFAULT, &ehci->regs->txfill_tuning); - } - if (retval) - return retval; - - if (ehci_is_TDI(ehci)) - tdi_reset (ehci); - - if (ehci->debug) - dbgp_external_startup(ehci_to_hcd(ehci)); - - ehci->port_c_suspend = ehci->suspended_ports = - ehci->resuming_ports = 0; - return retval; -} -EXPORT_SYMBOL_GPL(ehci_reset); - -/* - * Idle the controller (turn off the schedules). - * Must be called with interrupts enabled and the lock not held. - */ -static void ehci_quiesce (struct ehci_hcd *ehci) -{ - u32 temp; - - if (ehci->rh_state != EHCI_RH_RUNNING) - return; - - /* wait for any schedule enables/disables to take effect */ - temp = (ehci->command << 10) & (STS_ASS | STS_PSS); - ehci_handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, temp, - 16 * 125); - - /* then disable anything that's still active */ - spin_lock_irq(&ehci->lock); - ehci->command &= ~(CMD_ASE | CMD_PSE); - ehci_writel(ehci, ehci->command, &ehci->regs->command); - spin_unlock_irq(&ehci->lock); - - /* hardware can take 16 microframes to turn off ... */ - ehci_handshake(ehci, &ehci->regs->status, STS_ASS | STS_PSS, 0, - 16 * 125); -} - -/*-------------------------------------------------------------------------*/ - -static void end_unlink_async(struct ehci_hcd *ehci); -static void unlink_empty_async(struct ehci_hcd *ehci); -static void unlink_empty_async_suspended(struct ehci_hcd *ehci); -static void ehci_work(struct ehci_hcd *ehci); -static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); -static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); -static int ehci_port_power(struct ehci_hcd *ehci, int portnum, bool enable); - -#include "ehci-timer.c" -#include "ehci-hub.c" -#include "ehci-mem.c" -#include "ehci-q.c" -#include "ehci-sched.c" -#include "ehci-sysfs.c" - -/*-------------------------------------------------------------------------*/ - -/* On some systems, leaving remote wakeup enabled prevents system shutdown. - * The firmware seems to think that powering off is a wakeup event! - * This routine turns off remote wakeup and everything else, on all ports. - */ -static void ehci_turn_off_all_ports(struct ehci_hcd *ehci) -{ - int port = HCS_N_PORTS(ehci->hcs_params); - - while (port--) { - spin_unlock_irq(&ehci->lock); - ehci_port_power(ehci, port, false); - spin_lock_irq(&ehci->lock); - ehci_writel(ehci, PORT_RWC_BITS, - &ehci->regs->port_status[port]); - } -} - -/* - * Halt HC, turn off all ports, and let the BIOS use the companion controllers. - * Must be called with interrupts enabled and the lock not held. - */ -static void ehci_silence_controller(struct ehci_hcd *ehci) -{ - ehci_halt(ehci); - - spin_lock_irq(&ehci->lock); - ehci->rh_state = EHCI_RH_HALTED; - ehci_turn_off_all_ports(ehci); - - /* make BIOS/etc use companion controller during reboot */ - ehci_writel(ehci, 0, &ehci->regs->configured_flag); - - /* unblock posted writes */ - ehci_readl(ehci, &ehci->regs->configured_flag); - spin_unlock_irq(&ehci->lock); -} - -/* ehci_shutdown kick in for silicon on any bus (not just pci, etc). - * This forcibly disables dma and IRQs, helping kexec and other cases - * where the next system software may expect clean state. - */ -static void ehci_shutdown(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - spin_lock_irq(&ehci->lock); - ehci->shutdown = true; - ehci->rh_state = EHCI_RH_STOPPING; - ehci->enabled_hrtimer_events = 0; - spin_unlock_irq(&ehci->lock); - - ehci_silence_controller(ehci); - - hrtimer_cancel(&ehci->hrtimer); -} - -/*-------------------------------------------------------------------------*/ - -/* - * ehci_work is called from some interrupts, timers, and so on. - * it calls driver completion functions, after dropping ehci->lock. - */ -static void ehci_work (struct ehci_hcd *ehci) -{ - /* another CPU may drop ehci->lock during a schedule scan while - * it reports urb completions. this flag guards against bogus - * attempts at re-entrant schedule scanning. - */ - if (ehci->scanning) { - ehci->need_rescan = true; - return; - } - ehci->scanning = true; - - rescan: - ehci->need_rescan = false; - if (ehci->async_count) - scan_async(ehci); - if (ehci->intr_count > 0) - scan_intr(ehci); - if (ehci->isoc_count > 0) - scan_isoc(ehci); - if (ehci->need_rescan) - goto rescan; - ehci->scanning = false; - - /* the IO watchdog guards against hardware or driver bugs that - * misplace IRQs, and should let us run completely without IRQs. - * such lossage has been observed on both VT6202 and VT8235. - */ - turn_on_io_watchdog(ehci); -} - -/* - * Called when the ehci_hcd module is removed. - */ -static void ehci_stop (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - - ehci_dbg (ehci, "stop\n"); - - /* no more interrupts ... */ - - spin_lock_irq(&ehci->lock); - ehci->enabled_hrtimer_events = 0; - spin_unlock_irq(&ehci->lock); - - ehci_quiesce(ehci); - ehci_silence_controller(ehci); - ehci_reset (ehci); - - hrtimer_cancel(&ehci->hrtimer); - remove_sysfs_files(ehci); - remove_debug_files (ehci); - - /* root hub is shut down separately (first, when possible) */ - spin_lock_irq (&ehci->lock); - end_free_itds(ehci); - spin_unlock_irq (&ehci->lock); - ehci_mem_cleanup (ehci); - - if (ehci->amd_pll_fix == 1) - usb_amd_dev_put(); - - dbg_status (ehci, "ehci_stop completed", - ehci_readl(ehci, &ehci->regs->status)); -} - -/* one-time init, only for memory state */ -static int ehci_init(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - u32 temp; - int retval; - u32 hcc_params; - struct ehci_qh_hw *hw; - - spin_lock_init(&ehci->lock); - - /* - * keep io watchdog by default, those good HCDs could turn off it later - */ - ehci->need_io_watchdog = 1; - - hrtimer_init(&ehci->hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS); - ehci->hrtimer.function = ehci_hrtimer_func; - ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT; - - hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); - - /* - * by default set standard 80% (== 100 usec/uframe) max periodic - * bandwidth as required by USB 2.0 - */ - ehci->uframe_periodic_max = 100; - - /* - * hw default: 1K periodic list heads, one per frame. - * periodic_size can shrink by USBCMD update if hcc_params allows. - */ - ehci->periodic_size = DEFAULT_I_TDPS; - INIT_LIST_HEAD(&ehci->async_unlink); - INIT_LIST_HEAD(&ehci->async_idle); - INIT_LIST_HEAD(&ehci->intr_unlink_wait); - INIT_LIST_HEAD(&ehci->intr_unlink); - INIT_LIST_HEAD(&ehci->intr_qh_list); - INIT_LIST_HEAD(&ehci->cached_itd_list); - INIT_LIST_HEAD(&ehci->cached_sitd_list); - INIT_LIST_HEAD(&ehci->tt_list); - - if (HCC_PGM_FRAMELISTLEN(hcc_params)) { - /* periodic schedule size can be smaller than default */ - switch (EHCI_TUNE_FLS) { - case 0: ehci->periodic_size = 1024; break; - case 1: ehci->periodic_size = 512; break; - case 2: ehci->periodic_size = 256; break; - default: BUG(); - } - } - if ((retval = ehci_mem_init(ehci, GFP_KERNEL)) < 0) - return retval; - - /* controllers may cache some of the periodic schedule ... */ - if (HCC_ISOC_CACHE(hcc_params)) // full frame cache - ehci->i_thresh = 0; - else // N microframes cached - ehci->i_thresh = 2 + HCC_ISOC_THRES(hcc_params); - - /* - * dedicate a qh for the async ring head, since we couldn't unlink - * a 'real' qh without stopping the async schedule [4.8]. use it - * as the 'reclamation list head' too. - * its dummy is used in hw_alt_next of many tds, to prevent the qh - * from automatically advancing to the next td after short reads. - */ - ehci->async->qh_next.qh = NULL; - hw = ehci->async->hw; - hw->hw_next = QH_NEXT(ehci, ehci->async->qh_dma); - hw->hw_info1 = cpu_to_hc32(ehci, QH_HEAD); -#if defined(CONFIG_PPC_PS3) - hw->hw_info1 |= cpu_to_hc32(ehci, QH_INACTIVATE); -#endif - hw->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); - hw->hw_qtd_next = EHCI_LIST_END(ehci); - ehci->async->qh_state = QH_STATE_LINKED; - hw->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma); - - /* clear interrupt enables, set irq latency */ - if (log2_irq_thresh < 0 || log2_irq_thresh > 6) - log2_irq_thresh = 0; - temp = 1 << (16 + log2_irq_thresh); - if (HCC_PER_PORT_CHANGE_EVENT(hcc_params)) { - ehci->has_ppcd = 1; - ehci_dbg(ehci, "enable per-port change event\n"); - temp |= CMD_PPCEE; - } - if (HCC_CANPARK(hcc_params)) { - /* HW default park == 3, on hardware that supports it (like - * NVidia and ALI silicon), maximizes throughput on the async - * schedule by avoiding QH fetches between transfers. - * - * With fast usb storage devices and NForce2, "park" seems to - * make problems: throughput reduction (!), data errors... - */ - if (park) { - park = min(park, (unsigned) 3); - temp |= CMD_PARK; - temp |= park << 8; - } - ehci_dbg(ehci, "park %d\n", park); - } - if (HCC_PGM_FRAMELISTLEN(hcc_params)) { - /* periodic schedule size can be smaller than default */ - temp &= ~(3 << 2); - temp |= (EHCI_TUNE_FLS << 2); - } - ehci->command = temp; - - /* Accept arbitrarily long scatter-gather lists */ - if (!(hcd->driver->flags & HCD_LOCAL_MEM)) - hcd->self.sg_tablesize = ~0; - return 0; -} - -/* start HC running; it's halted, ehci_init() has been run (once) */ -static int ehci_run (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 temp; - u32 hcc_params; - - hcd->uses_new_polling = 1; - - /* EHCI spec section 4.1 */ - - ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); - ehci_writel(ehci, (u32)ehci->async->qh_dma, &ehci->regs->async_next); - - /* - * hcc_params controls whether ehci->regs->segment must (!!!) - * be used; it constrains QH/ITD/SITD and QTD locations. - * pci_pool consistent memory always uses segment zero. - * streaming mappings for I/O buffers, like pci_map_single(), - * can return segments above 4GB, if the device allows. - * - * NOTE: the dma mask is visible through dev->dma_mask, so - * drivers can pass this info along ... like NETIF_F_HIGHDMA, - * Scsi_Host.highmem_io, and so forth. It's readonly to all - * host side drivers though. - */ - hcc_params = ehci_readl(ehci, &ehci->caps->hcc_params); - if (HCC_64BIT_ADDR(hcc_params)) { - ehci_writel(ehci, 0, &ehci->regs->segment); -#if 0 -// this is deeply broken on almost all architectures - if (!dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64))) - ehci_info(ehci, "enabled 64bit DMA\n"); -#endif - } - - - // Philips, Intel, and maybe others need CMD_RUN before the - // root hub will detect new devices (why?); NEC doesn't - ehci->command &= ~(CMD_LRESET|CMD_IAAD|CMD_PSE|CMD_ASE|CMD_RESET); - ehci->command |= CMD_RUN; - ehci_writel(ehci, ehci->command, &ehci->regs->command); - dbg_cmd (ehci, "init", ehci->command); - - /* - * Start, enabling full USB 2.0 functionality ... usb 1.1 devices - * are explicitly handed to companion controller(s), so no TT is - * involved with the root hub. (Except where one is integrated, - * and there's no companion controller unless maybe for USB OTG.) - * - * Turning on the CF flag will transfer ownership of all ports - * from the companions to the EHCI controller. If any of the - * companions are in the middle of a port reset at the time, it - * could cause trouble. Write-locking ehci_cf_port_reset_rwsem - * guarantees that no resets are in progress. After we set CF, - * a short delay lets the hardware catch up; new resets shouldn't - * be started before the port switching actions could complete. - */ - down_write(&ehci_cf_port_reset_rwsem); - ehci->rh_state = EHCI_RH_RUNNING; - ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ - msleep(5); - up_write(&ehci_cf_port_reset_rwsem); - ehci->last_periodic_enable = ktime_get_real(); - - temp = HC_VERSION(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - ehci_info (ehci, - "USB %x.%x started, EHCI %x.%02x%s\n", - ((ehci->sbrn & 0xf0)>>4), (ehci->sbrn & 0x0f), - temp >> 8, temp & 0xff, - ignore_oc ? ", overcurrent ignored" : ""); - - ehci_writel(ehci, INTR_MASK, - &ehci->regs->intr_enable); /* Turn On Interrupts */ - - /* GRR this is run-once init(), being done every time the HC starts. - * So long as they're part of class devices, we can't do it init() - * since the class device isn't created that early. - */ - create_debug_files(ehci); - create_sysfs_files(ehci); - - return 0; -} - -int ehci_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; - - ehci->regs = (void __iomem *)ehci->caps + - HC_LENGTH(ehci, ehci_readl(ehci, &ehci->caps->hc_capbase)); - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - - ehci->sbrn = HCD_USB2; - - /* data structure init */ - retval = ehci_init(hcd); - if (retval) - return retval; - - retval = ehci_halt(ehci); - if (retval) - return retval; - - ehci_reset(ehci); - - return 0; -} -EXPORT_SYMBOL_GPL(ehci_setup); - -/*-------------------------------------------------------------------------*/ - -static irqreturn_t ehci_irq (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 status, masked_status, pcd_status = 0, cmd; - int bh; - unsigned long flags; - - /* - * For threadirqs option we use spin_lock_irqsave() variant to prevent - * deadlock with ehci hrtimer callback, because hrtimer callbacks run - * in interrupt context even when threadirqs is specified. We can go - * back to spin_lock() variant when hrtimer callbacks become threaded. - */ - spin_lock_irqsave(&ehci->lock, flags); - - status = ehci_readl(ehci, &ehci->regs->status); - - /* e.g. cardbus physical eject */ - if (status == ~(u32) 0) { - ehci_dbg (ehci, "device removed\n"); - goto dead; - } - - /* - * We don't use STS_FLR, but some controllers don't like it to - * remain on, so mask it out along with the other status bits. - */ - masked_status = status & (INTR_MASK | STS_FLR); - - /* Shared IRQ? */ - if (!masked_status || unlikely(ehci->rh_state == EHCI_RH_HALTED)) { - spin_unlock_irqrestore(&ehci->lock, flags); - return IRQ_NONE; - } - - /* clear (just) interrupts */ - ehci_writel(ehci, masked_status, &ehci->regs->status); - cmd = ehci_readl(ehci, &ehci->regs->command); - bh = 0; - - /* normal [4.15.1.2] or error [4.15.1.1] completion */ - if (likely ((status & (STS_INT|STS_ERR)) != 0)) { - if (likely ((status & STS_ERR) == 0)) - COUNT (ehci->stats.normal); - else - COUNT (ehci->stats.error); - bh = 1; - } - - /* complete the unlinking of some qh [4.15.2.3] */ - if (status & STS_IAA) { - - /* Turn off the IAA watchdog */ - ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_IAA_WATCHDOG); - - /* - * Mild optimization: Allow another IAAD to reset the - * hrtimer, if one occurs before the next expiration. - * In theory we could always cancel the hrtimer, but - * tests show that about half the time it will be reset - * for some other event anyway. - */ - if (ehci->next_hrtimer_event == EHCI_HRTIMER_IAA_WATCHDOG) - ++ehci->next_hrtimer_event; - - /* guard against (alleged) silicon errata */ - if (cmd & CMD_IAAD) - ehci_dbg(ehci, "IAA with IAAD still set?\n"); - if (ehci->iaa_in_progress) - COUNT(ehci->stats.iaa); - end_unlink_async(ehci); - } - - /* remote wakeup [4.3.1] */ - if (status & STS_PCD) { - unsigned i = HCS_N_PORTS (ehci->hcs_params); - u32 ppcd = ~0; - - /* kick root hub later */ - pcd_status = status; - - /* resume root hub? */ - if (ehci->rh_state == EHCI_RH_SUSPENDED) - usb_hcd_resume_root_hub(hcd); - - /* get per-port change detect bits */ - if (ehci->has_ppcd) - ppcd = status >> 16; - - while (i--) { - int pstatus; - - /* leverage per-port change bits feature */ - if (!(ppcd & (1 << i))) - continue; - pstatus = ehci_readl(ehci, - &ehci->regs->port_status[i]); - - if (pstatus & PORT_OWNER) - continue; - if (!(test_bit(i, &ehci->suspended_ports) && - ((pstatus & PORT_RESUME) || - !(pstatus & PORT_SUSPEND)) && - (pstatus & PORT_PE) && - ehci->reset_done[i] == 0)) - continue; - - /* start USB_RESUME_TIMEOUT msec resume signaling from - * this port, and make hub_wq collect - * PORT_STAT_C_SUSPEND to stop that signaling. - */ - ehci->reset_done[i] = jiffies + - msecs_to_jiffies(USB_RESUME_TIMEOUT); - set_bit(i, &ehci->resuming_ports); - ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); - usb_hcd_start_port_resume(&hcd->self, i); - mod_timer(&hcd->rh_timer, ehci->reset_done[i]); - } - } - - /* PCI errors [4.15.2.4] */ - if (unlikely ((status & STS_FATAL) != 0)) { - ehci_err(ehci, "fatal error\n"); - dbg_cmd(ehci, "fatal", cmd); - dbg_status(ehci, "fatal", status); -dead: - usb_hc_died(hcd); - - /* Don't let the controller do anything more */ - ehci->shutdown = true; - ehci->rh_state = EHCI_RH_STOPPING; - ehci->command &= ~(CMD_RUN | CMD_ASE | CMD_PSE); - ehci_writel(ehci, ehci->command, &ehci->regs->command); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - ehci_handle_controller_death(ehci); - - /* Handle completions when the controller stops */ - bh = 0; - } - - if (bh) - ehci_work (ehci); - spin_unlock_irqrestore(&ehci->lock, flags); - if (pcd_status) - usb_hcd_poll_rh_status(hcd); - return IRQ_HANDLED; -} - -/*-------------------------------------------------------------------------*/ - -/* - * non-error returns are a promise to giveback() the urb later - * we drop ownership so next owner (or urb unlink) can get it - * - * urb + dev is in hcd.self.controller.urb_list - * we're queueing TDs onto software and hardware lists - * - * hcd-specific init for hcpriv hasn't been done yet - * - * NOTE: control, bulk, and interrupt share the same code to append TDs - * to a (possibly active) QH, and the same QH scanning code. - */ -static int ehci_urb_enqueue ( - struct usb_hcd *hcd, - struct urb *urb, - gfp_t mem_flags -) { - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - struct list_head qtd_list; - - INIT_LIST_HEAD (&qtd_list); - - switch (usb_pipetype (urb->pipe)) { - case PIPE_CONTROL: - /* qh_completions() code doesn't handle all the fault cases - * in multi-TD control transfers. Even 1KB is rare anyway. - */ - if (urb->transfer_buffer_length > (16 * 1024)) - return -EMSGSIZE; - /* FALLTHROUGH */ - /* case PIPE_BULK: */ - default: - if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) - return -ENOMEM; - return submit_async(ehci, urb, &qtd_list, mem_flags); - - case PIPE_INTERRUPT: - if (!qh_urb_transaction (ehci, urb, &qtd_list, mem_flags)) - return -ENOMEM; - return intr_submit(ehci, urb, &qtd_list, mem_flags); - - case PIPE_ISOCHRONOUS: - if (urb->dev->speed == USB_SPEED_HIGH) - return itd_submit (ehci, urb, mem_flags); - else - return sitd_submit (ehci, urb, mem_flags); - } -} - -/* remove from hardware lists - * completions normally happen asynchronously - */ - -static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - struct ehci_qh *qh; - unsigned long flags; - int rc; - - spin_lock_irqsave (&ehci->lock, flags); - rc = usb_hcd_check_unlink_urb(hcd, urb, status); - if (rc) - goto done; - - if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) { - /* - * We don't expedite dequeue for isochronous URBs. - * Just wait until they complete normally or their - * time slot expires. - */ - } else { - qh = (struct ehci_qh *) urb->hcpriv; - qh->exception = 1; - switch (qh->qh_state) { - case QH_STATE_LINKED: - if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) - start_unlink_intr(ehci, qh); - else - start_unlink_async(ehci, qh); - break; - case QH_STATE_COMPLETING: - qh->dequeue_during_giveback = 1; - break; - case QH_STATE_UNLINK: - case QH_STATE_UNLINK_WAIT: - /* already started */ - break; - case QH_STATE_IDLE: - /* QH might be waiting for a Clear-TT-Buffer */ - qh_completions(ehci, qh); - break; - } - } -done: - spin_unlock_irqrestore (&ehci->lock, flags); - return rc; -} - -/*-------------------------------------------------------------------------*/ - -// bulk qh holds the data toggle - -static void -ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - unsigned long flags; - struct ehci_qh *qh; - - /* ASSERT: any requests/urbs are being unlinked */ - /* ASSERT: nobody can be submitting urbs for this any more */ - -rescan: - spin_lock_irqsave (&ehci->lock, flags); - qh = ep->hcpriv; - if (!qh) - goto done; - - /* endpoints can be iso streams. for now, we don't - * accelerate iso completions ... so spin a while. - */ - if (qh->hw == NULL) { - struct ehci_iso_stream *stream = ep->hcpriv; - - if (!list_empty(&stream->td_list)) - goto idle_timeout; - - /* BUG_ON(!list_empty(&stream->free_list)); */ - reserve_release_iso_bandwidth(ehci, stream, -1); - kfree(stream); - goto done; - } - - qh->exception = 1; - switch (qh->qh_state) { - case QH_STATE_LINKED: - WARN_ON(!list_empty(&qh->qtd_list)); - if (usb_endpoint_type(&ep->desc) != USB_ENDPOINT_XFER_INT) - start_unlink_async(ehci, qh); - else - start_unlink_intr(ehci, qh); - /* FALL THROUGH */ - case QH_STATE_COMPLETING: /* already in unlinking */ - case QH_STATE_UNLINK: /* wait for hw to finish? */ - case QH_STATE_UNLINK_WAIT: -idle_timeout: - spin_unlock_irqrestore (&ehci->lock, flags); - schedule_timeout_uninterruptible(1); - goto rescan; - case QH_STATE_IDLE: /* fully unlinked */ - if (qh->clearing_tt) - goto idle_timeout; - if (list_empty (&qh->qtd_list)) { - if (qh->ps.bw_uperiod) - reserve_release_intr_bandwidth(ehci, qh, -1); - qh_destroy(ehci, qh); - break; - } - /* else FALL THROUGH */ - default: - /* caller was supposed to have unlinked any requests; - * that's not our job. just leak this memory. - */ - ehci_err (ehci, "qh %p (#%02x) state %d%s\n", - qh, ep->desc.bEndpointAddress, qh->qh_state, - list_empty (&qh->qtd_list) ? "" : "(has tds)"); - break; - } - done: - ep->hcpriv = NULL; - spin_unlock_irqrestore (&ehci->lock, flags); -} - -static void -ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct ehci_qh *qh; - int eptype = usb_endpoint_type(&ep->desc); - int epnum = usb_endpoint_num(&ep->desc); - int is_out = usb_endpoint_dir_out(&ep->desc); - unsigned long flags; - - if (eptype != USB_ENDPOINT_XFER_BULK && eptype != USB_ENDPOINT_XFER_INT) - return; - - spin_lock_irqsave(&ehci->lock, flags); - qh = ep->hcpriv; - - /* For Bulk and Interrupt endpoints we maintain the toggle state - * in the hardware; the toggle bits in udev aren't used at all. - * When an endpoint is reset by usb_clear_halt() we must reset - * the toggle bit in the QH. - */ - if (qh) { - if (!list_empty(&qh->qtd_list)) { - WARN_ONCE(1, "clear_halt for a busy endpoint\n"); - } else { - /* The toggle value in the QH can't be updated - * while the QH is active. Unlink it now; - * re-linking will call qh_refresh(). - */ - usb_settoggle(qh->ps.udev, epnum, is_out, 0); - qh->exception = 1; - if (eptype == USB_ENDPOINT_XFER_BULK) - start_unlink_async(ehci, qh); - else - start_unlink_intr(ehci, qh); - } - } - spin_unlock_irqrestore(&ehci->lock, flags); -} - -static int ehci_get_frame (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - return (ehci_read_frame_index(ehci) >> 3) % ehci->periodic_size; -} - -/*-------------------------------------------------------------------------*/ - -/* Device addition and removal */ - -static void ehci_remove_device(struct usb_hcd *hcd, struct usb_device *udev) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - spin_lock_irq(&ehci->lock); - drop_tt(udev); - spin_unlock_irq(&ehci->lock); -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_PM - -/* suspend/resume, section 4.3 */ - -/* These routines handle the generic parts of controller suspend/resume */ - -int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - if (time_before(jiffies, ehci->next_statechange)) - msleep(10); - - /* - * Root hub was already suspended. Disable IRQ emission and - * mark HW unaccessible. The PM and USB cores make sure that - * the root hub is either suspended or stopped. - */ - ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup); - - spin_lock_irq(&ehci->lock); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - (void) ehci_readl(ehci, &ehci->regs->intr_enable); - - clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - spin_unlock_irq(&ehci->lock); - - synchronize_irq(hcd->irq); - - /* Check for race with a wakeup request */ - if (do_wakeup && HCD_WAKEUP_PENDING(hcd)) { - ehci_resume(hcd, false); - return -EBUSY; - } - - return 0; -} -EXPORT_SYMBOL_GPL(ehci_suspend); - -/* Returns 0 if power was preserved, 1 if power was lost */ -int ehci_resume(struct usb_hcd *hcd, bool force_reset) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - if (time_before(jiffies, ehci->next_statechange)) - msleep(100); - - /* Mark hardware accessible again as we are back to full power by now */ - set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); - - if (ehci->shutdown) - return 0; /* Controller is dead */ - - /* - * If CF is still set and reset isn't forced - * then we maintained suspend power. - * Just undo the effect of ehci_suspend(). - */ - if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF && - !force_reset) { - int mask = INTR_MASK; - - ehci_prepare_ports_for_controller_resume(ehci); - - spin_lock_irq(&ehci->lock); - if (ehci->shutdown) - goto skip; - - if (!hcd->self.root_hub->do_remote_wakeup) - mask &= ~STS_PCD; - ehci_writel(ehci, mask, &ehci->regs->intr_enable); - ehci_readl(ehci, &ehci->regs->intr_enable); - skip: - spin_unlock_irq(&ehci->lock); - return 0; - } - - /* - * Else reset, to cope with power loss or resume from hibernation - * having let the firmware kick in during reboot. - */ - usb_root_hub_lost_power(hcd->self.root_hub); - (void) ehci_halt(ehci); - (void) ehci_reset(ehci); - - spin_lock_irq(&ehci->lock); - if (ehci->shutdown) - goto skip; - - ehci_writel(ehci, ehci->command, &ehci->regs->command); - ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag); - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ - - ehci->rh_state = EHCI_RH_SUSPENDED; - spin_unlock_irq(&ehci->lock); - - return 1; -} -EXPORT_SYMBOL_GPL(ehci_resume); - -#endif - -/*-------------------------------------------------------------------------*/ - -/* - * Generic structure: This gets copied for platform drivers so that - * individual entries can be overridden as needed. - */ - -static const struct hc_driver ehci_hc_driver = { - .description = hcd_name, - .product_desc = "EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2 | HCD_BH, - - /* - * basic lifecycle operations - */ - .reset = ehci_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - .endpoint_reset = ehci_endpoint_reset, - .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, - - /* - * device support - */ - .free_dev = ehci_remove_device, -}; - -void ehci_init_driver(struct hc_driver *drv, - const struct ehci_driver_overrides *over) -{ - /* Copy the generic table to drv and then apply the overrides */ - *drv = ehci_hc_driver; - - if (over) { - drv->hcd_priv_size += over->extra_priv_size; - if (over->reset) - drv->reset = over->reset; - if (over->port_power) - drv->port_power = over->port_power; - } -} -EXPORT_SYMBOL_GPL(ehci_init_driver); - -/*-------------------------------------------------------------------------*/ - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR (DRIVER_AUTHOR); -MODULE_LICENSE ("GPL"); - -#ifdef CONFIG_USB_EHCI_SH -#include "ehci-sh.c" -#define PLATFORM_DRIVER ehci_hcd_sh_driver -#endif - -#ifdef CONFIG_PPC_PS3 -#include "ehci-ps3.c" -#define PS3_SYSTEM_BUS_DRIVER ps3_ehci_driver -#endif - -#ifdef CONFIG_USB_EHCI_HCD_PPC_OF -#include "ehci-ppc-of.c" -#define OF_PLATFORM_DRIVER ehci_hcd_ppc_of_driver -#endif - -#ifdef CONFIG_XPS_USB_HCD_XILINX -#include "ehci-xilinx-of.c" -#define XILINX_OF_PLATFORM_DRIVER ehci_hcd_xilinx_of_driver -#endif - -#ifdef CONFIG_TILE_USB -#include "ehci-tilegx.c" -#define PLATFORM_DRIVER ehci_hcd_tilegx_driver -#endif - -#ifdef CONFIG_USB_EHCI_HCD_PMC_MSP -#include "ehci-pmcmsp.c" -#define PLATFORM_DRIVER ehci_hcd_msp_driver -#endif - -#ifdef CONFIG_SPARC_LEON -#include "ehci-grlib.c" -#define PLATFORM_DRIVER ehci_grlib_driver -#endif - -#ifdef CONFIG_USB_EHCI_MV -#include "ehci-mv.c" -#define PLATFORM_DRIVER ehci_mv_driver -#endif - -#ifdef CONFIG_MIPS_SEAD3 -#include "ehci-sead3.c" -#define PLATFORM_DRIVER ehci_hcd_sead3_driver -#endif - -static int __init ehci_hcd_init(void) -{ - int retval = 0; - - if (usb_disabled()) - return -ENODEV; - - printk(KERN_INFO "%s: " DRIVER_DESC "\n", hcd_name); - set_bit(USB_EHCI_LOADED, &usb_hcds_loaded); - if (test_bit(USB_UHCI_LOADED, &usb_hcds_loaded) || - test_bit(USB_OHCI_LOADED, &usb_hcds_loaded)) - printk(KERN_WARNING "Warning! ehci_hcd should always be loaded" - " before uhci_hcd and ohci_hcd, not after\n"); - - pr_debug("%s: block sizes: qh %Zd qtd %Zd itd %Zd sitd %Zd\n", - hcd_name, - sizeof(struct ehci_qh), sizeof(struct ehci_qtd), - sizeof(struct ehci_itd), sizeof(struct ehci_sitd)); - -#ifdef CONFIG_DYNAMIC_DEBUG - ehci_debug_root = debugfs_create_dir("ehci", usb_debug_root); - if (!ehci_debug_root) { - retval = -ENOENT; - goto err_debug; - } -#endif - -#ifdef PLATFORM_DRIVER - retval = platform_driver_register(&PLATFORM_DRIVER); - if (retval < 0) - goto clean0; -#endif - -#ifdef PS3_SYSTEM_BUS_DRIVER - retval = ps3_ehci_driver_register(&PS3_SYSTEM_BUS_DRIVER); - if (retval < 0) - goto clean2; -#endif - -#ifdef OF_PLATFORM_DRIVER - retval = platform_driver_register(&OF_PLATFORM_DRIVER); - if (retval < 0) - goto clean3; -#endif - -#ifdef XILINX_OF_PLATFORM_DRIVER - retval = platform_driver_register(&XILINX_OF_PLATFORM_DRIVER); - if (retval < 0) - goto clean4; -#endif - return retval; - -#ifdef XILINX_OF_PLATFORM_DRIVER - /* platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); */ -clean4: -#endif -#ifdef OF_PLATFORM_DRIVER - platform_driver_unregister(&OF_PLATFORM_DRIVER); -clean3: -#endif -#ifdef PS3_SYSTEM_BUS_DRIVER - ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); -clean2: -#endif -#ifdef PLATFORM_DRIVER - platform_driver_unregister(&PLATFORM_DRIVER); -clean0: -#endif -#ifdef CONFIG_DYNAMIC_DEBUG - debugfs_remove(ehci_debug_root); - ehci_debug_root = NULL; -err_debug: -#endif - clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); - return retval; -} -module_init(ehci_hcd_init); - -static void __exit ehci_hcd_cleanup(void) -{ -#ifdef XILINX_OF_PLATFORM_DRIVER - platform_driver_unregister(&XILINX_OF_PLATFORM_DRIVER); -#endif -#ifdef OF_PLATFORM_DRIVER - platform_driver_unregister(&OF_PLATFORM_DRIVER); -#endif -#ifdef PLATFORM_DRIVER - platform_driver_unregister(&PLATFORM_DRIVER); -#endif -#ifdef PS3_SYSTEM_BUS_DRIVER - ps3_ehci_driver_unregister(&PS3_SYSTEM_BUS_DRIVER); -#endif -#ifdef CONFIG_DYNAMIC_DEBUG - debugfs_remove(ehci_debug_root); -#endif - clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded); -} -module_exit(ehci_hcd_cleanup); diff --git a/addons/ehci-pci/src/4.4.180/ehci-hub.c b/addons/ehci-pci/src/4.4.180/ehci-hub.c deleted file mode 100644 index 086a7115..00000000 --- a/addons/ehci-pci/src/4.4.180/ehci-hub.c +++ /dev/null @@ -1,1329 +0,0 @@ -/* - * Copyright (C) 2001-2004 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Root Hub ... the nonsharable stuff - * - * Registers don't need cpu_to_le32, that happens transparently - */ - -/*-------------------------------------------------------------------------*/ -#include - -#define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) - -#ifdef CONFIG_PM - -static int persist_enabled_on_companion(struct usb_device *udev, void *unused) -{ - return !udev->maxchild && udev->persist_enabled && - udev->bus->root_hub->speed < USB_SPEED_HIGH; -} - -/* After a power loss, ports that were owned by the companion must be - * reset so that the companion can still own them. - */ -static void ehci_handover_companion_ports(struct ehci_hcd *ehci) -{ - u32 __iomem *reg; - u32 status; - int port; - __le32 buf; - struct usb_hcd *hcd = ehci_to_hcd(ehci); - - if (!ehci->owned_ports) - return; - - /* - * USB 1.1 devices are mostly HIDs, which don't need to persist across - * suspends. If we ensure that none of our companion's devices have - * persist_enabled (by looking through all USB 1.1 buses in the system), - * we can skip this and avoid slowing resume down. Devices without - * persist will just get reenumerated shortly after resume anyway. - */ - if (!usb_for_each_dev(NULL, persist_enabled_on_companion)) - return; - - /* Make sure the ports are powered */ - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - if (test_bit(port, &ehci->owned_ports)) { - reg = &ehci->regs->port_status[port]; - status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; - if (!(status & PORT_POWER)) - ehci_port_power(ehci, port, true); - } - } - - /* Give the connections some time to appear */ - msleep(20); - - spin_lock_irq(&ehci->lock); - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - if (test_bit(port, &ehci->owned_ports)) { - reg = &ehci->regs->port_status[port]; - status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; - - /* Port already owned by companion? */ - if (status & PORT_OWNER) - clear_bit(port, &ehci->owned_ports); - else if (test_bit(port, &ehci->companion_ports)) - ehci_writel(ehci, status & ~PORT_PE, reg); - else { - spin_unlock_irq(&ehci->lock); - ehci_hub_control(hcd, SetPortFeature, - USB_PORT_FEAT_RESET, port + 1, - NULL, 0); - spin_lock_irq(&ehci->lock); - } - } - } - spin_unlock_irq(&ehci->lock); - - if (!ehci->owned_ports) - return; - msleep(90); /* Wait for resets to complete */ - - spin_lock_irq(&ehci->lock); - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - if (test_bit(port, &ehci->owned_ports)) { - spin_unlock_irq(&ehci->lock); - ehci_hub_control(hcd, GetPortStatus, - 0, port + 1, - (char *) &buf, sizeof(buf)); - spin_lock_irq(&ehci->lock); - - /* The companion should now own the port, - * but if something went wrong the port must not - * remain enabled. - */ - reg = &ehci->regs->port_status[port]; - status = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; - if (status & PORT_OWNER) - ehci_writel(ehci, status | PORT_CSC, reg); - else { - ehci_dbg(ehci, "failed handover port %d: %x\n", - port + 1, status); - ehci_writel(ehci, status & ~PORT_PE, reg); - } - } - } - - ehci->owned_ports = 0; - spin_unlock_irq(&ehci->lock); -} - -static int ehci_port_change(struct ehci_hcd *ehci) -{ - int i = HCS_N_PORTS(ehci->hcs_params); - - /* First check if the controller indicates a change event */ - - if (ehci_readl(ehci, &ehci->regs->status) & STS_PCD) - return 1; - - /* - * Not all controllers appear to update this while going from D3 to D0, - * so check the individual port status registers as well - */ - - while (i--) - if (ehci_readl(ehci, &ehci->regs->port_status[i]) & PORT_CSC) - return 1; - - return 0; -} - -void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, - bool suspending, bool do_wakeup) -{ - int port; - u32 temp; - - /* If remote wakeup is enabled for the root hub but disabled - * for the controller, we must adjust all the port wakeup flags - * when the controller is suspended or resumed. In all other - * cases they don't need to be changed. - */ - if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup) - return; - - spin_lock_irq(&ehci->lock); - - /* clear phy low-power mode before changing wakeup flags */ - if (ehci->has_tdi_phy_lpm) { - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; - - temp = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg); - } - spin_unlock_irq(&ehci->lock); - msleep(5); - spin_lock_irq(&ehci->lock); - } - - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - u32 __iomem *reg = &ehci->regs->port_status[port]; - u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; - u32 t2 = t1 & ~PORT_WAKE_BITS; - - /* If we are suspending the controller, clear the flags. - * If we are resuming the controller, set the wakeup flags. - */ - if (!suspending) { - if (t1 & PORT_CONNECT) - t2 |= PORT_WKOC_E | PORT_WKDISC_E; - else - t2 |= PORT_WKOC_E | PORT_WKCONN_E; - } - ehci_writel(ehci, t2, reg); - } - - /* enter phy low-power mode again */ - if (ehci->has_tdi_phy_lpm) { - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; - - temp = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); - } - } - - /* Does the root hub have a port wakeup pending? */ - if (!suspending && ehci_port_change(ehci)) - usb_hcd_resume_root_hub(ehci_to_hcd(ehci)); - - spin_unlock_irq(&ehci->lock); -} -EXPORT_SYMBOL_GPL(ehci_adjust_port_wakeup_flags); - -static int ehci_bus_suspend (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - int port; - int mask; - int changed; - bool fs_idle_delay; - - ehci_dbg(ehci, "suspend root hub\n"); - - if (time_before (jiffies, ehci->next_statechange)) - msleep(5); - - /* stop the schedules */ - ehci_quiesce(ehci); - - spin_lock_irq (&ehci->lock); - if (ehci->rh_state < EHCI_RH_RUNNING) - goto done; - - /* Once the controller is stopped, port resumes that are already - * in progress won't complete. Hence if remote wakeup is enabled - * for the root hub and any ports are in the middle of a resume or - * remote wakeup, we must fail the suspend. - */ - if (hcd->self.root_hub->do_remote_wakeup) { - if (ehci->resuming_ports) { - spin_unlock_irq(&ehci->lock); - ehci_dbg(ehci, "suspend failed because a port is resuming\n"); - return -EBUSY; - } - } - - /* Unlike other USB host controller types, EHCI doesn't have - * any notion of "global" or bus-wide suspend. The driver has - * to manually suspend all the active unsuspended ports, and - * then manually resume them in the bus_resume() routine. - */ - ehci->bus_suspended = 0; - ehci->owned_ports = 0; - changed = 0; - fs_idle_delay = false; - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - u32 __iomem *reg = &ehci->regs->port_status [port]; - u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; - u32 t2 = t1 & ~PORT_WAKE_BITS; - - /* keep track of which ports we suspend */ - if (t1 & PORT_OWNER) - set_bit(port, &ehci->owned_ports); - else if ((t1 & PORT_PE) && !(t1 & PORT_SUSPEND)) { - t2 |= PORT_SUSPEND; - set_bit(port, &ehci->bus_suspended); - } - - /* enable remote wakeup on all ports, if told to do so */ - if (hcd->self.root_hub->do_remote_wakeup) { - /* only enable appropriate wake bits, otherwise the - * hardware can not go phy low power mode. If a race - * condition happens here(connection change during bits - * set), the port change detection will finally fix it. - */ - if (t1 & PORT_CONNECT) - t2 |= PORT_WKOC_E | PORT_WKDISC_E; - else - t2 |= PORT_WKOC_E | PORT_WKCONN_E; - } - - if (t1 != t2) { - /* - * On some controllers, Wake-On-Disconnect will - * generate false wakeup signals until the bus - * switches over to full-speed idle. For their - * sake, add a delay if we need one. - */ - if ((t2 & PORT_WKDISC_E) && - ehci_port_speed(ehci, t2) == - USB_PORT_STAT_HIGH_SPEED) - fs_idle_delay = true; - ehci_writel(ehci, t2, reg); - changed = 1; - } - } - spin_unlock_irq(&ehci->lock); - - if ((changed && ehci->has_tdi_phy_lpm) || fs_idle_delay) { - /* - * Wait for HCD to enter low-power mode or for the bus - * to switch to full-speed idle. - */ - usleep_range(5000, 5500); - } - - if (changed && ehci->has_tdi_phy_lpm) { - spin_lock_irq(&ehci->lock); - port = HCS_N_PORTS(ehci->hcs_params); - while (port--) { - u32 __iomem *hostpc_reg = &ehci->regs->hostpc[port]; - u32 t3; - - t3 = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg); - t3 = ehci_readl(ehci, hostpc_reg); - ehci_dbg(ehci, "Port %d phy low-power mode %s\n", - port, (t3 & HOSTPC_PHCD) ? - "succeeded" : "failed"); - } - spin_unlock_irq(&ehci->lock); - } - - /* Apparently some devices need a >= 1-uframe delay here */ - if (ehci->bus_suspended) - udelay(150); - - /* turn off now-idle HC */ - ehci_halt (ehci); - - spin_lock_irq(&ehci->lock); - if (ehci->enabled_hrtimer_events & BIT(EHCI_HRTIMER_POLL_DEAD)) - ehci_handle_controller_death(ehci); - if (ehci->rh_state != EHCI_RH_RUNNING) - goto done; - ehci->rh_state = EHCI_RH_SUSPENDED; - - end_unlink_async(ehci); - unlink_empty_async_suspended(ehci); - ehci_handle_start_intr_unlinks(ehci); - ehci_handle_intr_unlinks(ehci); - end_free_itds(ehci); - - /* allow remote wakeup */ - mask = INTR_MASK; - if (!hcd->self.root_hub->do_remote_wakeup) - mask &= ~STS_PCD; - ehci_writel(ehci, mask, &ehci->regs->intr_enable); - ehci_readl(ehci, &ehci->regs->intr_enable); - - done: - ehci->next_statechange = jiffies + msecs_to_jiffies(10); - ehci->enabled_hrtimer_events = 0; - ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT; - spin_unlock_irq (&ehci->lock); - - hrtimer_cancel(&ehci->hrtimer); - return 0; -} - - -/* caller has locked the root hub, and should reset/reinit on error */ -static int ehci_bus_resume (struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 temp; - u32 power_okay; - int i; - unsigned long resume_needed = 0; - - if (time_before (jiffies, ehci->next_statechange)) - msleep(5); - spin_lock_irq (&ehci->lock); - if (!HCD_HW_ACCESSIBLE(hcd) || ehci->shutdown) - goto shutdown; - - if (unlikely(ehci->debug)) { - if (!dbgp_reset_prep(hcd)) - ehci->debug = NULL; - else - dbgp_external_startup(hcd); - } - - /* Ideally and we've got a real resume here, and no port's power - * was lost. (For PCI, that means Vaux was maintained.) But we - * could instead be restoring a swsusp snapshot -- so that BIOS was - * the last user of the controller, not reset/pm hardware keeping - * state we gave to it. - */ - power_okay = ehci_readl(ehci, &ehci->regs->intr_enable); - ehci_dbg(ehci, "resume root hub%s\n", - power_okay ? "" : " after power loss"); - - /* at least some APM implementations will try to deliver - * IRQs right away, so delay them until we're ready. - */ - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - - /* re-init operational registers */ - ehci_writel(ehci, 0, &ehci->regs->segment); - ehci_writel(ehci, ehci->periodic_dma, &ehci->regs->frame_list); - ehci_writel(ehci, (u32) ehci->async->qh_dma, &ehci->regs->async_next); - - /* restore CMD_RUN, framelist size, and irq threshold */ - ehci->command |= CMD_RUN; - ehci_writel(ehci, ehci->command, &ehci->regs->command); - ehci->rh_state = EHCI_RH_RUNNING; - - /* - * According to Bugzilla #8190, the port status for some controllers - * will be wrong without a delay. At their wrong status, the port - * is enabled, but not suspended neither resumed. - */ - i = HCS_N_PORTS(ehci->hcs_params); - while (i--) { - temp = ehci_readl(ehci, &ehci->regs->port_status[i]); - if ((temp & PORT_PE) && - !(temp & (PORT_SUSPEND | PORT_RESUME))) { - ehci_dbg(ehci, "Port status(0x%x) is wrong\n", temp); - spin_unlock_irq(&ehci->lock); - msleep(8); - spin_lock_irq(&ehci->lock); - break; - } - } - - if (ehci->shutdown) - goto shutdown; - - /* clear phy low-power mode before resume */ - if (ehci->bus_suspended && ehci->has_tdi_phy_lpm) { - i = HCS_N_PORTS(ehci->hcs_params); - while (i--) { - if (test_bit(i, &ehci->bus_suspended)) { - u32 __iomem *hostpc_reg = - &ehci->regs->hostpc[i]; - - temp = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp & ~HOSTPC_PHCD, - hostpc_reg); - } - } - spin_unlock_irq(&ehci->lock); - msleep(5); - spin_lock_irq(&ehci->lock); - if (ehci->shutdown) - goto shutdown; - } - - /* manually resume the ports we suspended during bus_suspend() */ - i = HCS_N_PORTS (ehci->hcs_params); - while (i--) { - temp = ehci_readl(ehci, &ehci->regs->port_status [i]); - temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); - if (test_bit(i, &ehci->bus_suspended) && - (temp & PORT_SUSPEND)) { - temp |= PORT_RESUME; - set_bit(i, &resume_needed); - } - ehci_writel(ehci, temp, &ehci->regs->port_status [i]); - } - - /* - * msleep for USB_RESUME_TIMEOUT ms only if code is trying to resume - * port - */ - if (resume_needed) { - spin_unlock_irq(&ehci->lock); - msleep(USB_RESUME_TIMEOUT); - spin_lock_irq(&ehci->lock); - if (ehci->shutdown) - goto shutdown; - } - - i = HCS_N_PORTS (ehci->hcs_params); - while (i--) { - temp = ehci_readl(ehci, &ehci->regs->port_status [i]); - if (test_bit(i, &resume_needed)) { - temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME); - ehci_writel(ehci, temp, &ehci->regs->port_status [i]); - } - } - - ehci->next_statechange = jiffies + msecs_to_jiffies(5); - spin_unlock_irq(&ehci->lock); - - ehci_handover_companion_ports(ehci); - - /* Now we can safely re-enable irqs */ - spin_lock_irq(&ehci->lock); - if (ehci->shutdown) - goto shutdown; - ehci_writel(ehci, INTR_MASK, &ehci->regs->intr_enable); - (void) ehci_readl(ehci, &ehci->regs->intr_enable); - spin_unlock_irq(&ehci->lock); - - return 0; - - shutdown: - spin_unlock_irq(&ehci->lock); - return -ESHUTDOWN; -} - -#else - -#define ehci_bus_suspend NULL -#define ehci_bus_resume NULL - -#endif /* CONFIG_PM */ - -/*-------------------------------------------------------------------------*/ - -/* - * Sets the owner of a port - */ -static void set_owner(struct ehci_hcd *ehci, int portnum, int new_owner) -{ - u32 __iomem *status_reg; - u32 port_status; - int try; - - status_reg = &ehci->regs->port_status[portnum]; - - /* - * The controller won't set the OWNER bit if the port is - * enabled, so this loop will sometimes require at least two - * iterations: one to disable the port and one to set OWNER. - */ - for (try = 4; try > 0; --try) { - spin_lock_irq(&ehci->lock); - port_status = ehci_readl(ehci, status_reg); - if ((port_status & PORT_OWNER) == new_owner - || (port_status & (PORT_OWNER | PORT_CONNECT)) - == 0) - try = 0; - else { - port_status ^= PORT_OWNER; - port_status &= ~(PORT_PE | PORT_RWC_BITS); - ehci_writel(ehci, port_status, status_reg); - } - spin_unlock_irq(&ehci->lock); - if (try > 1) - msleep(5); - } -} - -/*-------------------------------------------------------------------------*/ - -static int check_reset_complete ( - struct ehci_hcd *ehci, - int index, - u32 __iomem *status_reg, - int port_status -) { - if (!(port_status & PORT_CONNECT)) - return port_status; - - /* if reset finished and it's still not enabled -- handoff */ - if (!(port_status & PORT_PE)) { - - /* with integrated TT, there's nobody to hand it to! */ - if (ehci_is_TDI(ehci)) { - ehci_dbg (ehci, - "Failed to enable port %d on root hub TT\n", - index+1); - return port_status; - } - - ehci_dbg (ehci, "port %d full speed --> companion\n", - index + 1); - - // what happens if HCS_N_CC(params) == 0 ? - port_status |= PORT_OWNER; - port_status &= ~PORT_RWC_BITS; - ehci_writel(ehci, port_status, status_reg); - - /* ensure 440EPX ohci controller state is operational */ - if (ehci->has_amcc_usb23) - set_ohci_hcfs(ehci, 1); - } else { - ehci_dbg(ehci, "port %d reset complete, port enabled\n", - index + 1); - /* ensure 440EPx ohci controller state is suspended */ - if (ehci->has_amcc_usb23) - set_ohci_hcfs(ehci, 0); - } - - return port_status; -} - -/*-------------------------------------------------------------------------*/ - - -/* build "status change" packet (one or two bytes) from HC registers */ - -static int -ehci_hub_status_data (struct usb_hcd *hcd, char *buf) -{ - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - u32 temp, status; - u32 mask; - int ports, i, retval = 1; - unsigned long flags; - u32 ppcd = ~0; - - /* init status to no-changes */ - buf [0] = 0; - ports = HCS_N_PORTS (ehci->hcs_params); - if (ports > 7) { - buf [1] = 0; - retval++; - } - - /* Inform the core about resumes-in-progress by returning - * a non-zero value even if there are no status changes. - */ - status = ehci->resuming_ports; - - /* Some boards (mostly VIA?) report bogus overcurrent indications, - * causing massive log spam unless we completely ignore them. It - * may be relevant that VIA VT8235 controllers, where PORT_POWER is - * always set, seem to clear PORT_OCC and PORT_CSC when writing to - * PORT_POWER; that's surprising, but maybe within-spec. - */ - if (!ignore_oc) - mask = PORT_CSC | PORT_PEC | PORT_OCC; - else - mask = PORT_CSC | PORT_PEC; - // PORT_RESUME from hardware ~= PORT_STAT_C_SUSPEND - - /* no hub change reports (bit 0) for now (power, ...) */ - - /* port N changes (bit N)? */ - spin_lock_irqsave (&ehci->lock, flags); - - /* get per-port change detect bits */ - if (ehci->has_ppcd) - ppcd = ehci_readl(ehci, &ehci->regs->status) >> 16; - - for (i = 0; i < ports; i++) { - /* leverage per-port change bits feature */ - if (ppcd & (1 << i)) - temp = ehci_readl(ehci, &ehci->regs->port_status[i]); - else - temp = 0; - - /* - * Return status information even for ports with OWNER set. - * Otherwise hub_wq wouldn't see the disconnect event when a - * high-speed device is switched over to the companion - * controller by the user. - */ - - if ((temp & mask) != 0 || test_bit(i, &ehci->port_c_suspend) - || (ehci->reset_done[i] && time_after_eq( - jiffies, ehci->reset_done[i]))) { - if (i < 7) - buf [0] |= 1 << (i + 1); - else - buf [1] |= 1 << (i - 7); - status = STS_PCD; - } - } - - /* If a resume is in progress, make sure it can finish */ - if (ehci->resuming_ports) - mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25)); - - spin_unlock_irqrestore (&ehci->lock, flags); - return status ? retval : 0; -} - -/*-------------------------------------------------------------------------*/ - -static void -ehci_hub_descriptor ( - struct ehci_hcd *ehci, - struct usb_hub_descriptor *desc -) { - int ports = HCS_N_PORTS (ehci->hcs_params); - u16 temp; - - desc->bDescriptorType = USB_DT_HUB; - desc->bPwrOn2PwrGood = 10; /* ehci 1.0, 2.3.9 says 20ms max */ - desc->bHubContrCurrent = 0; - - desc->bNbrPorts = ports; - temp = 1 + (ports / 8); - desc->bDescLength = 7 + 2 * temp; - - /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ - memset(&desc->u.hs.DeviceRemovable[0], 0, temp); - memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); - - temp = HUB_CHAR_INDV_PORT_OCPM; /* per-port overcurrent reporting */ - if (HCS_PPC (ehci->hcs_params)) - temp |= HUB_CHAR_INDV_PORT_LPSM; /* per-port power control */ - else - temp |= HUB_CHAR_NO_LPSM; /* no power switching */ -#if 0 -// re-enable when we support USB_PORT_FEAT_INDICATOR below. - if (HCS_INDICATOR (ehci->hcs_params)) - temp |= HUB_CHAR_PORTIND; /* per-port indicators (LEDs) */ -#endif - desc->wHubCharacteristics = cpu_to_le16(temp); -} - -/*-------------------------------------------------------------------------*/ -#ifdef CONFIG_USB_HCD_TEST_MODE - -#define EHSET_TEST_SINGLE_STEP_SET_FEATURE 0x06 - -static void usb_ehset_completion(struct urb *urb) -{ - struct completion *done = urb->context; - - complete(done); -} -static int submit_single_step_set_feature( - struct usb_hcd *hcd, - struct urb *urb, - int is_setup -); - -/* - * Allocate and initialize a control URB. This request will be used by the - * EHSET SINGLE_STEP_SET_FEATURE test in which the DATA and STATUS stages - * of the GetDescriptor request are sent 15 seconds after the SETUP stage. - * Return NULL if failed. - */ -static struct urb *request_single_step_set_feature_urb( - struct usb_device *udev, - void *dr, - void *buf, - struct completion *done -) { - struct urb *urb; - struct usb_hcd *hcd = bus_to_hcd(udev->bus); - struct usb_host_endpoint *ep; - - urb = usb_alloc_urb(0, GFP_KERNEL); - if (!urb) - return NULL; - - urb->pipe = usb_rcvctrlpipe(udev, 0); - ep = (usb_pipein(urb->pipe) ? udev->ep_in : udev->ep_out) - [usb_pipeendpoint(urb->pipe)]; - if (!ep) { - usb_free_urb(urb); - return NULL; - } - - urb->ep = ep; - urb->dev = udev; - urb->setup_packet = (void *)dr; - urb->transfer_buffer = buf; - urb->transfer_buffer_length = USB_DT_DEVICE_SIZE; - urb->complete = usb_ehset_completion; - urb->status = -EINPROGRESS; - urb->actual_length = 0; - urb->transfer_flags = URB_DIR_IN; - usb_get_urb(urb); - atomic_inc(&urb->use_count); - atomic_inc(&urb->dev->urbnum); - urb->setup_dma = dma_map_single( - hcd->self.controller, - urb->setup_packet, - sizeof(struct usb_ctrlrequest), - DMA_TO_DEVICE); - urb->transfer_dma = dma_map_single( - hcd->self.controller, - urb->transfer_buffer, - urb->transfer_buffer_length, - DMA_FROM_DEVICE); - urb->context = done; - return urb; -} - -static int ehset_single_step_set_feature(struct usb_hcd *hcd, int port) -{ - int retval = -ENOMEM; - struct usb_ctrlrequest *dr; - struct urb *urb; - struct usb_device *udev; - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct usb_device_descriptor *buf; - DECLARE_COMPLETION_ONSTACK(done); - - /* Obtain udev of the rhub's child port */ - udev = usb_hub_find_child(hcd->self.root_hub, port); - if (!udev) { - ehci_err(ehci, "No device attached to the RootHub\n"); - return -ENODEV; - } - buf = kmalloc(USB_DT_DEVICE_SIZE, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - dr = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL); - if (!dr) { - kfree(buf); - return -ENOMEM; - } - - /* Fill Setup packet for GetDescriptor */ - dr->bRequestType = USB_DIR_IN; - dr->bRequest = USB_REQ_GET_DESCRIPTOR; - dr->wValue = cpu_to_le16(USB_DT_DEVICE << 8); - dr->wIndex = 0; - dr->wLength = cpu_to_le16(USB_DT_DEVICE_SIZE); - urb = request_single_step_set_feature_urb(udev, dr, buf, &done); - if (!urb) - goto cleanup; - - /* Submit just the SETUP stage */ - retval = submit_single_step_set_feature(hcd, urb, 1); - if (retval) - goto out1; - if (!wait_for_completion_timeout(&done, msecs_to_jiffies(2000))) { - usb_kill_urb(urb); - retval = -ETIMEDOUT; - ehci_err(ehci, "%s SETUP stage timed out on ep0\n", __func__); - goto out1; - } - msleep(15 * 1000); - - /* Complete remaining DATA and STATUS stages using the same URB */ - urb->status = -EINPROGRESS; - usb_get_urb(urb); - atomic_inc(&urb->use_count); - atomic_inc(&urb->dev->urbnum); - retval = submit_single_step_set_feature(hcd, urb, 0); - if (!retval && !wait_for_completion_timeout(&done, - msecs_to_jiffies(2000))) { - usb_kill_urb(urb); - retval = -ETIMEDOUT; - ehci_err(ehci, "%s IN stage timed out on ep0\n", __func__); - } -out1: - usb_free_urb(urb); -cleanup: - kfree(dr); - kfree(buf); - return retval; -} -#endif /* CONFIG_USB_HCD_TEST_MODE */ -/*-------------------------------------------------------------------------*/ - -int ehci_hub_control( - struct usb_hcd *hcd, - u16 typeReq, - u16 wValue, - u16 wIndex, - char *buf, - u16 wLength -) { - struct ehci_hcd *ehci = hcd_to_ehci (hcd); - int ports = HCS_N_PORTS (ehci->hcs_params); - u32 __iomem *status_reg = &ehci->regs->port_status[ - (wIndex & 0xff) - 1]; - u32 __iomem *hostpc_reg = &ehci->regs->hostpc[(wIndex & 0xff) - 1]; - u32 temp, temp1, status; - unsigned long flags; - int retval = 0; - unsigned selector; - - /* - * FIXME: support SetPortFeatures USB_PORT_FEAT_INDICATOR. - * HCS_INDICATOR may say we can change LEDs to off/amber/green. - * (track current state ourselves) ... blink for diagnostics, - * power, "this is the one", etc. EHCI spec supports this. - */ - - spin_lock_irqsave (&ehci->lock, flags); - switch (typeReq) { - case ClearHubFeature: - switch (wValue) { - case C_HUB_LOCAL_POWER: - case C_HUB_OVER_CURRENT: - /* no hub-wide feature/status flags */ - break; - default: - goto error; - } - break; - case ClearPortFeature: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - temp = ehci_readl(ehci, status_reg); - temp &= ~PORT_RWC_BITS; - - /* - * Even if OWNER is set, so the port is owned by the - * companion controller, hub_wq needs to be able to clear - * the port-change status bits (especially - * USB_PORT_STAT_C_CONNECTION). - */ - - switch (wValue) { - case USB_PORT_FEAT_ENABLE: - ehci_writel(ehci, temp & ~PORT_PE, status_reg); - break; - case USB_PORT_FEAT_C_ENABLE: - ehci_writel(ehci, temp | PORT_PEC, status_reg); - break; - case USB_PORT_FEAT_SUSPEND: - if (temp & PORT_RESET) - goto error; - if (ehci->no_selective_suspend) - break; -#ifdef CONFIG_USB_OTG - if ((hcd->self.otg_port == (wIndex + 1)) - && hcd->self.b_hnp_enable) { - otg_start_hnp(hcd->usb_phy->otg); - break; - } -#endif - if (!(temp & PORT_SUSPEND)) - break; - if ((temp & PORT_PE) == 0) - goto error; - - /* clear phy low-power mode before resume */ - if (ehci->has_tdi_phy_lpm) { - temp1 = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp1 & ~HOSTPC_PHCD, - hostpc_reg); - spin_unlock_irqrestore(&ehci->lock, flags); - msleep(5);/* wait to leave low-power mode */ - spin_lock_irqsave(&ehci->lock, flags); - } - /* resume signaling for 20 msec */ - temp &= ~PORT_WAKE_BITS; - ehci_writel(ehci, temp | PORT_RESUME, status_reg); - ehci->reset_done[wIndex] = jiffies - + msecs_to_jiffies(USB_RESUME_TIMEOUT); - set_bit(wIndex, &ehci->resuming_ports); - usb_hcd_start_port_resume(&hcd->self, wIndex); - break; - case USB_PORT_FEAT_C_SUSPEND: - clear_bit(wIndex, &ehci->port_c_suspend); - break; - case USB_PORT_FEAT_POWER: - if (HCS_PPC(ehci->hcs_params)) { - spin_unlock_irqrestore(&ehci->lock, flags); - ehci_port_power(ehci, wIndex, false); - spin_lock_irqsave(&ehci->lock, flags); - } - break; - case USB_PORT_FEAT_C_CONNECTION: - ehci_writel(ehci, temp | PORT_CSC, status_reg); - break; - case USB_PORT_FEAT_C_OVER_CURRENT: - ehci_writel(ehci, temp | PORT_OCC, status_reg); - break; - case USB_PORT_FEAT_C_RESET: - /* GetPortStatus clears reset */ - break; - default: - goto error; - } - ehci_readl(ehci, &ehci->regs->command); /* unblock posted write */ - break; - case GetHubDescriptor: - ehci_hub_descriptor (ehci, (struct usb_hub_descriptor *) - buf); - break; - case GetHubStatus: - /* no hub-wide feature/status flags */ - memset (buf, 0, 4); - //cpu_to_le32s ((u32 *) buf); - break; - case GetPortStatus: - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - status = 0; - temp = ehci_readl(ehci, status_reg); - - // wPortChange bits - if (temp & PORT_CSC) - status |= USB_PORT_STAT_C_CONNECTION << 16; - if (temp & PORT_PEC) - status |= USB_PORT_STAT_C_ENABLE << 16; - - if ((temp & PORT_OCC) && !ignore_oc){ - status |= USB_PORT_STAT_C_OVERCURRENT << 16; - - /* - * Hubs should disable port power on over-current. - * However, not all EHCI implementations do this - * automatically, even if they _do_ support per-port - * power switching; they're allowed to just limit the - * current. hub_wq will turn the power back on. - */ - if (((temp & PORT_OC) || (ehci->need_oc_pp_cycle)) - && HCS_PPC(ehci->hcs_params)) { - spin_unlock_irqrestore(&ehci->lock, flags); - ehci_port_power(ehci, wIndex, false); - spin_lock_irqsave(&ehci->lock, flags); - temp = ehci_readl(ehci, status_reg); - } - } - - /* no reset or resume pending */ - if (!ehci->reset_done[wIndex]) { - - /* Remote Wakeup received? */ - if (temp & PORT_RESUME) { - /* resume signaling for 20 msec */ - ehci->reset_done[wIndex] = jiffies - + msecs_to_jiffies(20); - usb_hcd_start_port_resume(&hcd->self, wIndex); - set_bit(wIndex, &ehci->resuming_ports); - /* check the port again */ - mod_timer(&ehci_to_hcd(ehci)->rh_timer, - ehci->reset_done[wIndex]); - } - - /* reset or resume not yet complete */ - } else if (!time_after_eq(jiffies, ehci->reset_done[wIndex])) { - ; /* wait until it is complete */ - - /* resume completed */ - } else if (test_bit(wIndex, &ehci->resuming_ports)) { - clear_bit(wIndex, &ehci->suspended_ports); - set_bit(wIndex, &ehci->port_c_suspend); - ehci->reset_done[wIndex] = 0; - usb_hcd_end_port_resume(&hcd->self, wIndex); - - /* stop resume signaling */ - temp &= ~(PORT_RWC_BITS | PORT_SUSPEND | PORT_RESUME); - ehci_writel(ehci, temp, status_reg); - clear_bit(wIndex, &ehci->resuming_ports); - retval = ehci_handshake(ehci, status_reg, - PORT_RESUME, 0, 2000 /* 2msec */); - if (retval != 0) { - ehci_err(ehci, "port %d resume error %d\n", - wIndex + 1, retval); - goto error; - } - temp = ehci_readl(ehci, status_reg); - - /* whoever resets must GetPortStatus to complete it!! */ - } else { - status |= USB_PORT_STAT_C_RESET << 16; - ehci->reset_done [wIndex] = 0; - - /* force reset to complete */ - ehci_writel(ehci, temp & ~(PORT_RWC_BITS | PORT_RESET), - status_reg); - /* REVISIT: some hardware needs 550+ usec to clear - * this bit; seems too long to spin routinely... - */ - retval = ehci_handshake(ehci, status_reg, - PORT_RESET, 0, 1000); - if (retval != 0) { - ehci_err (ehci, "port %d reset error %d\n", - wIndex + 1, retval); - goto error; - } - - /* see what we found out */ - temp = check_reset_complete (ehci, wIndex, status_reg, - ehci_readl(ehci, status_reg)); - } - - /* transfer dedicated ports to the companion hc */ - if ((temp & PORT_CONNECT) && - test_bit(wIndex, &ehci->companion_ports)) { - temp &= ~PORT_RWC_BITS; - temp |= PORT_OWNER; - ehci_writel(ehci, temp, status_reg); - ehci_dbg(ehci, "port %d --> companion\n", wIndex + 1); - temp = ehci_readl(ehci, status_reg); - } - - /* - * Even if OWNER is set, there's no harm letting hub_wq - * see the wPortStatus values (they should all be 0 except - * for PORT_POWER anyway). - */ - - if (temp & PORT_CONNECT) { - status |= USB_PORT_STAT_CONNECTION; - // status may be from integrated TT - if (ehci->has_hostpc) { - temp1 = ehci_readl(ehci, hostpc_reg); - status |= ehci_port_speed(ehci, temp1); - } else - status |= ehci_port_speed(ehci, temp); - } - if (temp & PORT_PE) - status |= USB_PORT_STAT_ENABLE; - - /* maybe the port was unsuspended without our knowledge */ - if (temp & (PORT_SUSPEND|PORT_RESUME)) { - status |= USB_PORT_STAT_SUSPEND; - } else if (test_bit(wIndex, &ehci->suspended_ports)) { - clear_bit(wIndex, &ehci->suspended_ports); - clear_bit(wIndex, &ehci->resuming_ports); - ehci->reset_done[wIndex] = 0; - if (temp & PORT_PE) - set_bit(wIndex, &ehci->port_c_suspend); - usb_hcd_end_port_resume(&hcd->self, wIndex); - } - - if (temp & PORT_OC) - status |= USB_PORT_STAT_OVERCURRENT; - if (temp & PORT_RESET) - status |= USB_PORT_STAT_RESET; - if (temp & PORT_POWER) - status |= USB_PORT_STAT_POWER; - if (test_bit(wIndex, &ehci->port_c_suspend)) - status |= USB_PORT_STAT_C_SUSPEND << 16; - - if (status & ~0xffff) /* only if wPortChange is interesting */ - dbg_port(ehci, "GetStatus", wIndex + 1, temp); - put_unaligned_le32(status, buf); - break; - case SetHubFeature: - switch (wValue) { - case C_HUB_LOCAL_POWER: - case C_HUB_OVER_CURRENT: - /* no hub-wide feature/status flags */ - break; - default: - goto error; - } - break; - case SetPortFeature: - selector = wIndex >> 8; - wIndex &= 0xff; - if (unlikely(ehci->debug)) { - /* If the debug port is active any port - * feature requests should get denied */ - if (wIndex == HCS_DEBUG_PORT(ehci->hcs_params) && - (readl(&ehci->debug->control) & DBGP_ENABLED)) { - retval = -ENODEV; - goto error_exit; - } - } - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - temp = ehci_readl(ehci, status_reg); - if (temp & PORT_OWNER) - break; - - temp &= ~PORT_RWC_BITS; - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - if (ehci->no_selective_suspend) - break; - if ((temp & PORT_PE) == 0 - || (temp & PORT_RESET) != 0) - goto error; - - /* After above check the port must be connected. - * Set appropriate bit thus could put phy into low power - * mode if we have tdi_phy_lpm feature - */ - temp &= ~PORT_WKCONN_E; - temp |= PORT_WKDISC_E | PORT_WKOC_E; - ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); - if (ehci->has_tdi_phy_lpm) { - spin_unlock_irqrestore(&ehci->lock, flags); - msleep(5);/* 5ms for HCD enter low pwr mode */ - spin_lock_irqsave(&ehci->lock, flags); - temp1 = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp1 | HOSTPC_PHCD, - hostpc_reg); - temp1 = ehci_readl(ehci, hostpc_reg); - ehci_dbg(ehci, "Port%d phy low pwr mode %s\n", - wIndex, (temp1 & HOSTPC_PHCD) ? - "succeeded" : "failed"); - } - set_bit(wIndex, &ehci->suspended_ports); - break; - case USB_PORT_FEAT_POWER: - if (HCS_PPC(ehci->hcs_params)) { - spin_unlock_irqrestore(&ehci->lock, flags); - ehci_port_power(ehci, wIndex, true); - spin_lock_irqsave(&ehci->lock, flags); - } - break; - case USB_PORT_FEAT_RESET: - if (temp & (PORT_SUSPEND|PORT_RESUME)) - goto error; - /* line status bits may report this as low speed, - * which can be fine if this root hub has a - * transaction translator built in. - */ - if ((temp & (PORT_PE|PORT_CONNECT)) == PORT_CONNECT - && !ehci_is_TDI(ehci) - && PORT_USB11 (temp)) { - ehci_dbg (ehci, - "port %d low speed --> companion\n", - wIndex + 1); - temp |= PORT_OWNER; - } else { - temp |= PORT_RESET; - temp &= ~PORT_PE; - - /* - * caller must wait, then call GetPortStatus - * usb 2.0 spec says 50 ms resets on root - */ - ehci->reset_done [wIndex] = jiffies - + msecs_to_jiffies (50); - - /* - * Force full-speed connect for FSL high-speed - * erratum; disable HS Chirp by setting PFSC bit - */ - if (ehci_has_fsl_hs_errata(ehci)) - temp |= (1 << PORTSC_FSL_PFSC); - } - ehci_writel(ehci, temp, status_reg); - break; - - /* For downstream facing ports (these): one hub port is put - * into test mode according to USB2 11.24.2.13, then the hub - * must be reset (which for root hub now means rmmod+modprobe, - * or else system reboot). See EHCI 2.3.9 and 4.14 for info - * about the EHCI-specific stuff. - */ - case USB_PORT_FEAT_TEST: -#ifdef CONFIG_USB_HCD_TEST_MODE - if (selector == EHSET_TEST_SINGLE_STEP_SET_FEATURE) { - spin_unlock_irqrestore(&ehci->lock, flags); - retval = ehset_single_step_set_feature(hcd, - wIndex + 1); - spin_lock_irqsave(&ehci->lock, flags); - break; - } -#endif - if (!selector || selector > 5) - goto error; - spin_unlock_irqrestore(&ehci->lock, flags); - ehci_quiesce(ehci); - spin_lock_irqsave(&ehci->lock, flags); - - /* Put all enabled ports into suspend */ - while (ports--) { - u32 __iomem *sreg = - &ehci->regs->port_status[ports]; - - temp = ehci_readl(ehci, sreg) & ~PORT_RWC_BITS; - if (temp & PORT_PE) - ehci_writel(ehci, temp | PORT_SUSPEND, - sreg); - } - - spin_unlock_irqrestore(&ehci->lock, flags); - ehci_halt(ehci); - spin_lock_irqsave(&ehci->lock, flags); - - temp = ehci_readl(ehci, status_reg); - temp |= selector << 16; - ehci_writel(ehci, temp, status_reg); - break; - - default: - goto error; - } - ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */ - break; - - default: -error: - /* "stall" on error */ - retval = -EPIPE; - } -error_exit: - spin_unlock_irqrestore (&ehci->lock, flags); - return retval; -} -EXPORT_SYMBOL_GPL(ehci_hub_control); - -static void ehci_relinquish_port(struct usb_hcd *hcd, int portnum) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - - if (ehci_is_TDI(ehci)) - return; - set_owner(ehci, --portnum, PORT_OWNER); -} - -static int ehci_port_handed_over(struct usb_hcd *hcd, int portnum) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - u32 __iomem *reg; - - if (ehci_is_TDI(ehci)) - return 0; - reg = &ehci->regs->port_status[portnum - 1]; - return ehci_readl(ehci, reg) & PORT_OWNER; -} - -static int ehci_port_power(struct ehci_hcd *ehci, int portnum, bool enable) -{ - struct usb_hcd *hcd = ehci_to_hcd(ehci); - u32 __iomem *status_reg = &ehci->regs->port_status[portnum]; - u32 temp = ehci_readl(ehci, status_reg) & ~PORT_RWC_BITS; - - if (enable) - ehci_writel(ehci, temp | PORT_POWER, status_reg); - else - ehci_writel(ehci, temp & ~PORT_POWER, status_reg); - - if (hcd->driver->port_power) - hcd->driver->port_power(hcd, portnum, enable); - - return 0; -} diff --git a/addons/ehci-pci/src/4.4.180/ehci-mem.c b/addons/ehci-pci/src/4.4.180/ehci-mem.c deleted file mode 100644 index b6205fac..00000000 --- a/addons/ehci-pci/src/4.4.180/ehci-mem.c +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2001 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* - * There's basically three types of memory: - * - data used only by the HCD ... kmalloc is fine - * - async and periodic schedules, shared by HC and HCD ... these - * need to use dma_pool or dma_alloc_coherent - * - driver buffers, read/written by HC ... single shot DMA mapped - * - * There's also "register" data (e.g. PCI or SOC), which is memory mapped. - * No memory seen by this driver is pageable. - */ - -/*-------------------------------------------------------------------------*/ - -/* Allocate the key transfer structures from the previously allocated pool */ - -static inline void ehci_qtd_init(struct ehci_hcd *ehci, struct ehci_qtd *qtd, - dma_addr_t dma) -{ - memset (qtd, 0, sizeof *qtd); - qtd->qtd_dma = dma; - qtd->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); - qtd->hw_next = EHCI_LIST_END(ehci); - qtd->hw_alt_next = EHCI_LIST_END(ehci); - INIT_LIST_HEAD (&qtd->qtd_list); -} - -static struct ehci_qtd *ehci_qtd_alloc (struct ehci_hcd *ehci, gfp_t flags) -{ - struct ehci_qtd *qtd; - dma_addr_t dma; - - qtd = dma_pool_alloc (ehci->qtd_pool, flags, &dma); - if (qtd != NULL) { - ehci_qtd_init(ehci, qtd, dma); - } - return qtd; -} - -static inline void ehci_qtd_free (struct ehci_hcd *ehci, struct ehci_qtd *qtd) -{ - dma_pool_free (ehci->qtd_pool, qtd, qtd->qtd_dma); -} - - -static void qh_destroy(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - /* clean qtds first, and know this is not linked */ - if (!list_empty (&qh->qtd_list) || qh->qh_next.ptr) { - ehci_dbg (ehci, "unused qh not empty!\n"); - BUG (); - } - if (qh->dummy) - ehci_qtd_free (ehci, qh->dummy); - dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma); - kfree(qh); -} - -static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) -{ - struct ehci_qh *qh; - dma_addr_t dma; - - qh = kzalloc(sizeof *qh, GFP_ATOMIC); - if (!qh) - goto done; - qh->hw = (struct ehci_qh_hw *) - dma_pool_alloc(ehci->qh_pool, flags, &dma); - if (!qh->hw) - goto fail; - memset(qh->hw, 0, sizeof *qh->hw); - qh->qh_dma = dma; - // INIT_LIST_HEAD (&qh->qh_list); - INIT_LIST_HEAD (&qh->qtd_list); - INIT_LIST_HEAD(&qh->unlink_node); - - /* dummy td enables safe urb queuing */ - qh->dummy = ehci_qtd_alloc (ehci, flags); - if (qh->dummy == NULL) { - ehci_dbg (ehci, "no dummy td\n"); - goto fail1; - } -done: - return qh; -fail1: - dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma); -fail: - kfree(qh); - return NULL; -} - -/*-------------------------------------------------------------------------*/ - -/* The queue heads and transfer descriptors are managed from pools tied - * to each of the "per device" structures. - * This is the initialisation and cleanup code. - */ - -static void ehci_mem_cleanup (struct ehci_hcd *ehci) -{ - if (ehci->async) - qh_destroy(ehci, ehci->async); - ehci->async = NULL; - - if (ehci->dummy) - qh_destroy(ehci, ehci->dummy); - ehci->dummy = NULL; - - /* DMA consistent memory and pools */ - if (ehci->qtd_pool) - dma_pool_destroy (ehci->qtd_pool); - ehci->qtd_pool = NULL; - - if (ehci->qh_pool) { - dma_pool_destroy (ehci->qh_pool); - ehci->qh_pool = NULL; - } - - if (ehci->itd_pool) - dma_pool_destroy (ehci->itd_pool); - ehci->itd_pool = NULL; - - if (ehci->sitd_pool) - dma_pool_destroy (ehci->sitd_pool); - ehci->sitd_pool = NULL; - - if (ehci->periodic) - dma_free_coherent (ehci_to_hcd(ehci)->self.controller, - ehci->periodic_size * sizeof (u32), - ehci->periodic, ehci->periodic_dma); - ehci->periodic = NULL; - - /* shadow periodic table */ - kfree(ehci->pshadow); - ehci->pshadow = NULL; -} - -/* remember to add cleanup code (above) if you add anything here */ -static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) -{ - int i; - - /* QTDs for control/bulk/intr transfers */ - ehci->qtd_pool = dma_pool_create ("ehci_qtd", - ehci_to_hcd(ehci)->self.controller, - sizeof (struct ehci_qtd), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */); - if (!ehci->qtd_pool) { - goto fail; - } - - /* QHs for control/bulk/intr transfers */ - ehci->qh_pool = dma_pool_create ("ehci_qh", - ehci_to_hcd(ehci)->self.controller, - sizeof(struct ehci_qh_hw), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */); - if (!ehci->qh_pool) { - goto fail; - } - ehci->async = ehci_qh_alloc (ehci, flags); - if (!ehci->async) { - goto fail; - } - - /* ITD for high speed ISO transfers */ - ehci->itd_pool = dma_pool_create ("ehci_itd", - ehci_to_hcd(ehci)->self.controller, - sizeof (struct ehci_itd), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */); - if (!ehci->itd_pool) { - goto fail; - } - - /* SITD for full/low speed split ISO transfers */ - ehci->sitd_pool = dma_pool_create ("ehci_sitd", - ehci_to_hcd(ehci)->self.controller, - sizeof (struct ehci_sitd), - 32 /* byte alignment (for hw parts) */, - 4096 /* can't cross 4K */); - if (!ehci->sitd_pool) { - goto fail; - } - - /* Hardware periodic table */ - ehci->periodic = (__le32 *) - dma_alloc_coherent (ehci_to_hcd(ehci)->self.controller, - ehci->periodic_size * sizeof(__le32), - &ehci->periodic_dma, flags); - if (ehci->periodic == NULL) { - goto fail; - } - - if (ehci->use_dummy_qh) { - struct ehci_qh_hw *hw; - ehci->dummy = ehci_qh_alloc(ehci, flags); - if (!ehci->dummy) - goto fail; - - hw = ehci->dummy->hw; - hw->hw_next = EHCI_LIST_END(ehci); - hw->hw_qtd_next = EHCI_LIST_END(ehci); - hw->hw_alt_next = EHCI_LIST_END(ehci); - ehci->dummy->hw = hw; - - for (i = 0; i < ehci->periodic_size; i++) - ehci->periodic[i] = cpu_to_hc32(ehci, - ehci->dummy->qh_dma); - } else { - for (i = 0; i < ehci->periodic_size; i++) - ehci->periodic[i] = EHCI_LIST_END(ehci); - } - - /* software shadow of hardware table */ - ehci->pshadow = kcalloc(ehci->periodic_size, sizeof(void *), flags); - if (ehci->pshadow != NULL) - return 0; - -fail: - ehci_dbg (ehci, "couldn't init memory\n"); - ehci_mem_cleanup (ehci); - return -ENOMEM; -} diff --git a/addons/ehci-pci/src/4.4.180/ehci-pci.c b/addons/ehci-pci/src/4.4.180/ehci-pci.c deleted file mode 100644 index 2a5d2fd7..00000000 --- a/addons/ehci-pci/src/4.4.180/ehci-pci.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * EHCI HCD (Host Controller Driver) PCI Bus Glue. - * - * Copyright (c) 2000-2004 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#include -#include -#include -#include -#include - -#include "ehci.h" -#include "pci-quirks.h" - -#define DRIVER_DESC "EHCI PCI platform driver" - -static const char hcd_name[] = "ehci-pci"; - -/* defined here to avoid adding to pci_ids.h for single instance use */ -#define PCI_DEVICE_ID_INTEL_CE4100_USB 0x2e70 - -/*-------------------------------------------------------------------------*/ -#define PCI_DEVICE_ID_INTEL_QUARK_X1000_SOC 0x0939 -static inline bool is_intel_quark_x1000(struct pci_dev *pdev) -{ - return pdev->vendor == PCI_VENDOR_ID_INTEL && - pdev->device == PCI_DEVICE_ID_INTEL_QUARK_X1000_SOC; -} - -/* - * This is the list of PCI IDs for the devices that have EHCI USB class and - * specific drivers for that. One of the example is a ChipIdea device installed - * on some Intel MID platforms. - */ -static const struct pci_device_id bypass_pci_id_table[] = { - /* ChipIdea on Intel MID platform */ - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0811), }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x0829), }, - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0xe006), }, - {} -}; - -static inline bool is_bypassed_id(struct pci_dev *pdev) -{ - return !!pci_match_id(bypass_pci_id_table, pdev); -} - -/* - * 0x84 is the offset of in/out threshold register, - * and it is the same offset as the register of 'hostpc'. - */ -#define intel_quark_x1000_insnreg01 hostpc - -/* Maximum usable threshold value is 0x7f dwords for both IN and OUT */ -#define INTEL_QUARK_X1000_EHCI_MAX_THRESHOLD 0x007f007f - -/* called after powerup, by probe or system-pm "wakeup" */ -static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) -{ - int retval; - - /* we expect static quirk code to handle the "extended capabilities" - * (currently just BIOS handoff) allowed starting with EHCI 0.96 - */ - - /* PCI Memory-Write-Invalidate cycle support is optional (uncommon) */ - retval = pci_set_mwi(pdev); - if (!retval) - ehci_dbg(ehci, "MWI active\n"); - - /* Reset the threshold limit */ - if (is_intel_quark_x1000(pdev)) { - /* - * For the Intel QUARK X1000, raise the I/O threshold to the - * maximum usable value in order to improve performance. - */ - ehci_writel(ehci, INTEL_QUARK_X1000_EHCI_MAX_THRESHOLD, - ehci->regs->intel_quark_x1000_insnreg01); - } - - return 0; -} - -/* called during probe() after chip reset completes */ -static int ehci_pci_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - u32 temp; - int retval; - - ehci->caps = hcd->regs; - - /* - * ehci_init() causes memory for DMA transfers to be - * allocated. Thus, any vendor-specific workarounds based on - * limiting the type of memory used for DMA transfers must - * happen before ehci_setup() is called. - * - * Most other workarounds can be done either before or after - * init and reset; they are located here too. - */ - switch (pdev->vendor) { - case PCI_VENDOR_ID_TOSHIBA_2: - /* celleb's companion chip */ - if (pdev->device == 0x01b5) { -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO - ehci->big_endian_mmio = 1; -#else - ehci_warn(ehci, - "unsupported big endian Toshiba quirk\n"); -#endif - } - break; - case PCI_VENDOR_ID_NVIDIA: - /* NVidia reports that certain chips don't handle - * QH, ITD, or SITD addresses above 2GB. (But TD, - * data buffer, and periodic schedule are normal.) - */ - switch (pdev->device) { - case 0x003c: /* MCP04 */ - case 0x005b: /* CK804 */ - case 0x00d8: /* CK8 */ - case 0x00e8: /* CK8S */ - if (pci_set_consistent_dma_mask(pdev, - DMA_BIT_MASK(31)) < 0) - ehci_warn(ehci, "can't enable NVidia " - "workaround for >2GB RAM\n"); - break; - - /* Some NForce2 chips have problems with selective suspend; - * fixed in newer silicon. - */ - case 0x0068: - if (pdev->revision < 0xa4) - ehci->no_selective_suspend = 1; - break; - } - break; - case PCI_VENDOR_ID_INTEL: - if (pdev->device == PCI_DEVICE_ID_INTEL_CE4100_USB) - hcd->has_tt = 1; - break; - case PCI_VENDOR_ID_TDI: - if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) - hcd->has_tt = 1; - break; - case PCI_VENDOR_ID_AMD: - /* AMD PLL quirk */ - if (usb_amd_find_chipset_info()) - ehci->amd_pll_fix = 1; - /* AMD8111 EHCI doesn't work, according to AMD errata */ - if (pdev->device == 0x7463) { - ehci_info(ehci, "ignoring AMD8111 (errata)\n"); - retval = -EIO; - goto done; - } - - /* - * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may - * read/write memory space which does not belong to it when - * there is NULL pointer with T-bit set to 1 in the frame list - * table. To avoid the issue, the frame list link pointer - * should always contain a valid pointer to a inactive qh. - */ - if (pdev->device == 0x7808) { - ehci->use_dummy_qh = 1; - ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n"); - } - break; - case PCI_VENDOR_ID_VIA: - if (pdev->device == 0x3104 && (pdev->revision & 0xf0) == 0x60) { - u8 tmp; - - /* The VT6212 defaults to a 1 usec EHCI sleep time which - * hogs the PCI bus *badly*. Setting bit 5 of 0x4B makes - * that sleep time use the conventional 10 usec. - */ - pci_read_config_byte(pdev, 0x4b, &tmp); - if (tmp & 0x20) - break; - pci_write_config_byte(pdev, 0x4b, tmp | 0x20); - } - break; - case PCI_VENDOR_ID_ATI: - /* AMD PLL quirk */ - if (usb_amd_find_chipset_info()) - ehci->amd_pll_fix = 1; - - /* - * EHCI controller on AMD SB700/SB800/Hudson-2/3 platforms may - * read/write memory space which does not belong to it when - * there is NULL pointer with T-bit set to 1 in the frame list - * table. To avoid the issue, the frame list link pointer - * should always contain a valid pointer to a inactive qh. - */ - if (pdev->device == 0x4396) { - ehci->use_dummy_qh = 1; - ehci_info(ehci, "applying AMD SB700/SB800/Hudson-2/3 EHCI dummy qh workaround\n"); - } - /* SB600 and old version of SB700 have a bug in EHCI controller, - * which causes usb devices lose response in some cases. - */ - if ((pdev->device == 0x4386 || pdev->device == 0x4396) && - usb_amd_hang_symptom_quirk()) { - u8 tmp; - ehci_info(ehci, "applying AMD SB600/SB700 USB freeze workaround\n"); - pci_read_config_byte(pdev, 0x53, &tmp); - pci_write_config_byte(pdev, 0x53, tmp | (1<<3)); - } - break; - case PCI_VENDOR_ID_NETMOS: - /* MosChip frame-index-register bug */ - ehci_info(ehci, "applying MosChip frame-index workaround\n"); - ehci->frame_index_bug = 1; - break; - } - - /* optional debug port, normally in the first BAR */ - temp = pci_find_capability(pdev, PCI_CAP_ID_DBG); - if (temp) { - pci_read_config_dword(pdev, temp, &temp); - temp >>= 16; - if (((temp >> 13) & 7) == 1) { - u32 hcs_params = ehci_readl(ehci, - &ehci->caps->hcs_params); - - temp &= 0x1fff; - ehci->debug = hcd->regs + temp; - temp = ehci_readl(ehci, &ehci->debug->control); - ehci_info(ehci, "debug port %d%s\n", - HCS_DEBUG_PORT(hcs_params), - (temp & DBGP_ENABLED) ? " IN USE" : ""); - if (!(temp & DBGP_ENABLED)) - ehci->debug = NULL; - } - } - - retval = ehci_setup(hcd); - if (retval) - return retval; - - /* These workarounds need to be applied after ehci_setup() */ - switch (pdev->vendor) { - case PCI_VENDOR_ID_NEC: - ehci->need_io_watchdog = 0; - break; - case PCI_VENDOR_ID_INTEL: - ehci->need_io_watchdog = 0; - break; - case PCI_VENDOR_ID_NVIDIA: - switch (pdev->device) { - /* MCP89 chips on the MacBookAir3,1 give EPROTO when - * fetching device descriptors unless LPM is disabled. - * There are also intermittent problems enumerating - * devices with PPCD enabled. - */ - case 0x0d9d: - ehci_info(ehci, "disable ppcd for nvidia mcp89\n"); - ehci->has_ppcd = 0; - ehci->command &= ~CMD_PPCEE; - break; - } - break; - } - - /* at least the Genesys GL880S needs fixup here */ - temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); - temp &= 0x0f; - if (temp && HCS_N_PORTS(ehci->hcs_params) > temp) { - ehci_dbg(ehci, "bogus port configuration: " - "cc=%d x pcc=%d < ports=%d\n", - HCS_N_CC(ehci->hcs_params), - HCS_N_PCC(ehci->hcs_params), - HCS_N_PORTS(ehci->hcs_params)); - - switch (pdev->vendor) { - case 0x17a0: /* GENESYS */ - /* GL880S: should be PORTS=2 */ - temp |= (ehci->hcs_params & ~0xf); - ehci->hcs_params = temp; - break; - case PCI_VENDOR_ID_NVIDIA: - /* NF4: should be PCC=10 */ - break; - } - } - - /* Serial Bus Release Number is at PCI 0x60 offset */ - if (pdev->vendor == PCI_VENDOR_ID_STMICRO - && pdev->device == PCI_DEVICE_ID_STMICRO_USB_HOST) - ; /* ConneXT has no sbrn register */ - else - pci_read_config_byte(pdev, 0x60, &ehci->sbrn); - - /* Keep this around for a while just in case some EHCI - * implementation uses legacy PCI PM support. This test - * can be removed on 17 Dec 2009 if the dev_warn() hasn't - * been triggered by then. - */ - if (!device_can_wakeup(&pdev->dev)) { - u16 port_wake; - - pci_read_config_word(pdev, 0x62, &port_wake); - if (port_wake & 0x0001) { - dev_warn(&pdev->dev, "Enabling legacy PCI PM\n"); - device_set_wakeup_capable(&pdev->dev, 1); - } - } - -#ifdef CONFIG_PM - if (ehci->no_selective_suspend && device_can_wakeup(&pdev->dev)) - ehci_warn(ehci, "selective suspend/wakeup unavailable\n"); -#endif - - retval = ehci_pci_reinit(ehci, pdev); -done: - return retval; -} - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_PM - -/* suspend/resume, section 4.3 */ - -/* These routines rely on the PCI bus glue - * to handle powerdown and wakeup, and currently also on - * transceivers that don't need any software attention to set up - * the right sort of wakeup. - * Also they depend on separate root hub suspend/resume. - */ - -static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct pci_dev *pdev = to_pci_dev(hcd->self.controller); - - if (ehci_resume(hcd, hibernated) != 0) - (void) ehci_pci_reinit(ehci, pdev); - return 0; -} - -#else - -#define ehci_suspend NULL -#define ehci_pci_resume NULL -#endif /* CONFIG_PM */ - -static struct hc_driver __read_mostly ehci_pci_hc_driver; - -static const struct ehci_driver_overrides pci_overrides __initconst = { - .reset = ehci_pci_setup, -}; - -/*-------------------------------------------------------------------------*/ - -static int ehci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - if (is_bypassed_id(pdev)) - return -ENODEV; - return usb_hcd_pci_probe(pdev, id); -} - -/* PCI driver selection metadata; PCI hotplugging uses this */ -static const struct pci_device_id pci_ids [] = { { - /* handle any USB 2.0 EHCI controller */ - PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_EHCI, ~0), - .driver_data = (unsigned long) &ehci_pci_hc_driver, - }, { - PCI_VDEVICE(STMICRO, PCI_DEVICE_ID_STMICRO_USB_HOST), - .driver_data = (unsigned long) &ehci_pci_hc_driver, - }, - { /* end: all zeroes */ } -}; -MODULE_DEVICE_TABLE(pci, pci_ids); - -/* pci driver glue; this is a "new style" PCI driver module */ -static struct pci_driver ehci_pci_driver = { - .name = (char *) hcd_name, - .id_table = pci_ids, - - .probe = ehci_pci_probe, - .remove = usb_hcd_pci_remove, - .shutdown = usb_hcd_pci_shutdown, - -#ifdef CONFIG_PM - .driver = { - .pm = &usb_hcd_pci_pm_ops - }, -#endif -}; - -static int __init ehci_pci_init(void) -{ - if (usb_disabled()) - return -ENODEV; - - pr_info("%s: " DRIVER_DESC "\n", hcd_name); - - ehci_init_driver(&ehci_pci_hc_driver, &pci_overrides); - - /* Entries for the PCI suspend/resume callbacks are special */ - ehci_pci_hc_driver.pci_suspend = ehci_suspend; - ehci_pci_hc_driver.pci_resume = ehci_pci_resume; - - return pci_register_driver(&ehci_pci_driver); -} -module_init(ehci_pci_init); - -static void __exit ehci_pci_cleanup(void) -{ - pci_unregister_driver(&ehci_pci_driver); -} -module_exit(ehci_pci_cleanup); - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_AUTHOR("David Brownell"); -MODULE_AUTHOR("Alan Stern"); -MODULE_LICENSE("GPL"); diff --git a/addons/ehci-pci/src/4.4.180/ehci-q.c b/addons/ehci-pci/src/4.4.180/ehci-q.c deleted file mode 100644 index 54f5332f..00000000 --- a/addons/ehci-pci/src/4.4.180/ehci-q.c +++ /dev/null @@ -1,1476 +0,0 @@ -/* - * Copyright (C) 2001-2004 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI hardware queue manipulation ... the core. QH/QTD manipulation. - * - * Control, bulk, and interrupt traffic all use "qh" lists. They list "qtd" - * entries describing USB transactions, max 16-20kB/entry (with 4kB-aligned - * buffers needed for the larger number). We use one QH per endpoint, queue - * multiple urbs (all three types) per endpoint. URBs may need several qtds. - * - * ISO traffic uses "ISO TD" (itd, and sitd) records, and (along with - * interrupts) needs careful scheduling. Performance improvements can be - * an ongoing challenge. That's in "ehci-sched.c". - * - * USB 1.1 devices are handled (a) by "companion" OHCI or UHCI root hubs, - * or otherwise through transaction translators (TTs) in USB 2.0 hubs using - * (b) special fields in qh entries or (c) split iso entries. TTs will - * buffer low/full speed data so the host collects it at high speed. - */ - -/*-------------------------------------------------------------------------*/ - -/* fill a qtd, returning how much of the buffer we were able to queue up */ - -static int -qtd_fill(struct ehci_hcd *ehci, struct ehci_qtd *qtd, dma_addr_t buf, - size_t len, int token, int maxpacket) -{ - int i, count; - u64 addr = buf; - - /* one buffer entry per 4K ... first might be short or unaligned */ - qtd->hw_buf[0] = cpu_to_hc32(ehci, (u32)addr); - qtd->hw_buf_hi[0] = cpu_to_hc32(ehci, (u32)(addr >> 32)); - count = 0x1000 - (buf & 0x0fff); /* rest of that page */ - if (likely (len < count)) /* ... iff needed */ - count = len; - else { - buf += 0x1000; - buf &= ~0x0fff; - - /* per-qtd limit: from 16K to 20K (best alignment) */ - for (i = 1; count < len && i < 5; i++) { - addr = buf; - qtd->hw_buf[i] = cpu_to_hc32(ehci, (u32)addr); - qtd->hw_buf_hi[i] = cpu_to_hc32(ehci, - (u32)(addr >> 32)); - buf += 0x1000; - if ((count + 0x1000) < len) - count += 0x1000; - else - count = len; - } - - /* short packets may only terminate transfers */ - if (count != len) - count -= (count % maxpacket); - } - qtd->hw_token = cpu_to_hc32(ehci, (count << 16) | token); - qtd->length = count; - - return count; -} - -/*-------------------------------------------------------------------------*/ - -static inline void -qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) -{ - struct ehci_qh_hw *hw = qh->hw; - - /* writes to an active overlay are unsafe */ - WARN_ON(qh->qh_state != QH_STATE_IDLE); - - hw->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); - hw->hw_alt_next = EHCI_LIST_END(ehci); - - /* Except for control endpoints, we make hardware maintain data - * toggle (like OHCI) ... here (re)initialize the toggle in the QH, - * and set the pseudo-toggle in udev. Only usb_clear_halt() will - * ever clear it. - */ - if (!(hw->hw_info1 & cpu_to_hc32(ehci, QH_TOGGLE_CTL))) { - unsigned is_out, epnum; - - is_out = qh->is_out; - epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f; - if (unlikely(!usb_gettoggle(qh->ps.udev, epnum, is_out))) { - hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); - usb_settoggle(qh->ps.udev, epnum, is_out, 1); - } - } - - hw->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); -} - -/* if it weren't for a common silicon quirk (writing the dummy into the qh - * overlay, so qh->hw_token wrongly becomes inactive/halted), only fault - * recovery (including urb dequeue) would need software changes to a QH... - */ -static void -qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - struct ehci_qtd *qtd; - - qtd = list_entry(qh->qtd_list.next, struct ehci_qtd, qtd_list); - - /* - * first qtd may already be partially processed. - * If we come here during unlink, the QH overlay region - * might have reference to the just unlinked qtd. The - * qtd is updated in qh_completions(). Update the QH - * overlay here. - */ - if (qh->hw->hw_token & ACTIVE_BIT(ehci)) - qh->hw->hw_qtd_next = qtd->hw_next; - else - qh_update(ehci, qh, qtd); -} - -/*-------------------------------------------------------------------------*/ - -static void qh_link_async(struct ehci_hcd *ehci, struct ehci_qh *qh); - -static void ehci_clear_tt_buffer_complete(struct usb_hcd *hcd, - struct usb_host_endpoint *ep) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct ehci_qh *qh = ep->hcpriv; - unsigned long flags; - - spin_lock_irqsave(&ehci->lock, flags); - qh->clearing_tt = 0; - if (qh->qh_state == QH_STATE_IDLE && !list_empty(&qh->qtd_list) - && ehci->rh_state == EHCI_RH_RUNNING) - qh_link_async(ehci, qh); - spin_unlock_irqrestore(&ehci->lock, flags); -} - -static void ehci_clear_tt_buffer(struct ehci_hcd *ehci, struct ehci_qh *qh, - struct urb *urb, u32 token) -{ - - /* If an async split transaction gets an error or is unlinked, - * the TT buffer may be left in an indeterminate state. We - * have to clear the TT buffer. - * - * Note: this routine is never called for Isochronous transfers. - */ - if (urb->dev->tt && !usb_pipeint(urb->pipe) && !qh->clearing_tt) { -#ifdef CONFIG_DYNAMIC_DEBUG - struct usb_device *tt = urb->dev->tt->hub; - dev_dbg(&tt->dev, - "clear tt buffer port %d, a%d ep%d t%08x\n", - urb->dev->ttport, urb->dev->devnum, - usb_pipeendpoint(urb->pipe), token); -#endif /* CONFIG_DYNAMIC_DEBUG */ - if (!ehci_is_TDI(ehci) - || urb->dev->tt->hub != - ehci_to_hcd(ehci)->self.root_hub) { - if (usb_hub_clear_tt_buffer(urb) == 0) - qh->clearing_tt = 1; - } else { - - /* REVISIT ARC-derived cores don't clear the root - * hub TT buffer in this way... - */ - } - } -} - -static int qtd_copy_status ( - struct ehci_hcd *ehci, - struct urb *urb, - size_t length, - u32 token -) -{ - int status = -EINPROGRESS; - - /* count IN/OUT bytes, not SETUP (even short packets) */ - if (likely (QTD_PID (token) != 2)) - urb->actual_length += length - QTD_LENGTH (token); - - /* don't modify error codes */ - if (unlikely(urb->unlinked)) - return status; - - /* force cleanup after short read; not always an error */ - if (unlikely (IS_SHORT_READ (token))) - status = -EREMOTEIO; - - /* serious "can't proceed" faults reported by the hardware */ - if (token & QTD_STS_HALT) { - if (token & QTD_STS_BABBLE) { - /* FIXME "must" disable babbling device's port too */ - status = -EOVERFLOW; - /* CERR nonzero + halt --> stall */ - } else if (QTD_CERR(token)) { - status = -EPIPE; - - /* In theory, more than one of the following bits can be set - * since they are sticky and the transaction is retried. - * Which to test first is rather arbitrary. - */ - } else if (token & QTD_STS_MMF) { - /* fs/ls interrupt xfer missed the complete-split */ - status = -EPROTO; - } else if (token & QTD_STS_DBE) { - status = (QTD_PID (token) == 1) /* IN ? */ - ? -ENOSR /* hc couldn't read data */ - : -ECOMM; /* hc couldn't write data */ - } else if (token & QTD_STS_XACT) { - /* timeout, bad CRC, wrong PID, etc */ - ehci_dbg(ehci, "devpath %s ep%d%s 3strikes\n", - urb->dev->devpath, - usb_pipeendpoint(urb->pipe), - usb_pipein(urb->pipe) ? "in" : "out"); - status = -EPROTO; - } else { /* unknown */ - status = -EPROTO; - } - } - - return status; -} - -static void -ehci_urb_done(struct ehci_hcd *ehci, struct urb *urb, int status) -{ - if (usb_pipetype(urb->pipe) == PIPE_INTERRUPT) { - /* ... update hc-wide periodic stats */ - ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; - } - - if (unlikely(urb->unlinked)) { - COUNT(ehci->stats.unlink); - } else { - /* report non-error and short read status as zero */ - if (status == -EINPROGRESS || status == -EREMOTEIO) - status = 0; - COUNT(ehci->stats.complete); - } - -#ifdef EHCI_URB_TRACE - ehci_dbg (ehci, - "%s %s urb %p ep%d%s status %d len %d/%d\n", - __func__, urb->dev->devpath, urb, - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", - status, - urb->actual_length, urb->transfer_buffer_length); -#endif - - usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); - usb_hcd_giveback_urb(ehci_to_hcd(ehci), urb, status); -} - -static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh); - -/* - * Process and free completed qtds for a qh, returning URBs to drivers. - * Chases up to qh->hw_current. Returns nonzero if the caller should - * unlink qh. - */ -static unsigned -qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - struct ehci_qtd *last, *end = qh->dummy; - struct list_head *entry, *tmp; - int last_status; - int stopped; - u8 state; - struct ehci_qh_hw *hw = qh->hw; - - /* completions (or tasks on other cpus) must never clobber HALT - * till we've gone through and cleaned everything up, even when - * they add urbs to this qh's queue or mark them for unlinking. - * - * NOTE: unlinking expects to be done in queue order. - * - * It's a bug for qh->qh_state to be anything other than - * QH_STATE_IDLE, unless our caller is scan_async() or - * scan_intr(). - */ - state = qh->qh_state; - qh->qh_state = QH_STATE_COMPLETING; - stopped = (state == QH_STATE_IDLE); - - rescan: - last = NULL; - last_status = -EINPROGRESS; - qh->dequeue_during_giveback = 0; - - /* remove de-activated QTDs from front of queue. - * after faults (including short reads), cleanup this urb - * then let the queue advance. - * if queue is stopped, handles unlinks. - */ - list_for_each_safe (entry, tmp, &qh->qtd_list) { - struct ehci_qtd *qtd; - struct urb *urb; - u32 token = 0; - - qtd = list_entry (entry, struct ehci_qtd, qtd_list); - urb = qtd->urb; - - /* clean up any state from previous QTD ...*/ - if (last) { - if (likely (last->urb != urb)) { - ehci_urb_done(ehci, last->urb, last_status); - last_status = -EINPROGRESS; - } - ehci_qtd_free (ehci, last); - last = NULL; - } - - /* ignore urbs submitted during completions we reported */ - if (qtd == end) - break; - - /* hardware copies qtd out of qh overlay */ - rmb (); - token = hc32_to_cpu(ehci, qtd->hw_token); - - /* always clean up qtds the hc de-activated */ - retry_xacterr: - if ((token & QTD_STS_ACTIVE) == 0) { - - /* Report Data Buffer Error: non-fatal but useful */ - if (token & QTD_STS_DBE) - ehci_dbg(ehci, - "detected DataBufferErr for urb %p ep%d%s len %d, qtd %p [qh %p]\n", - urb, - usb_endpoint_num(&urb->ep->desc), - usb_endpoint_dir_in(&urb->ep->desc) ? "in" : "out", - urb->transfer_buffer_length, - qtd, - qh); - - /* on STALL, error, and short reads this urb must - * complete and all its qtds must be recycled. - */ - if ((token & QTD_STS_HALT) != 0) { - - /* retry transaction errors until we - * reach the software xacterr limit - */ - if ((token & QTD_STS_XACT) && - QTD_CERR(token) == 0 && - ++qh->xacterrs < QH_XACTERR_MAX && - !urb->unlinked) { - ehci_dbg(ehci, - "detected XactErr len %zu/%zu retry %d\n", - qtd->length - QTD_LENGTH(token), qtd->length, qh->xacterrs); - - /* reset the token in the qtd and the - * qh overlay (which still contains - * the qtd) so that we pick up from - * where we left off - */ - token &= ~QTD_STS_HALT; - token |= QTD_STS_ACTIVE | - (EHCI_TUNE_CERR << 10); - qtd->hw_token = cpu_to_hc32(ehci, - token); - wmb(); - hw->hw_token = cpu_to_hc32(ehci, - token); - goto retry_xacterr; - } - stopped = 1; - - /* magic dummy for some short reads; qh won't advance. - * that silicon quirk can kick in with this dummy too. - * - * other short reads won't stop the queue, including - * control transfers (status stage handles that) or - * most other single-qtd reads ... the queue stops if - * URB_SHORT_NOT_OK was set so the driver submitting - * the urbs could clean it up. - */ - } else if (IS_SHORT_READ (token) - && !(qtd->hw_alt_next - & EHCI_LIST_END(ehci))) { - stopped = 1; - } - - /* stop scanning when we reach qtds the hc is using */ - } else if (likely (!stopped - && ehci->rh_state >= EHCI_RH_RUNNING)) { - break; - - /* scan the whole queue for unlinks whenever it stops */ - } else { - stopped = 1; - - /* cancel everything if we halt, suspend, etc */ - if (ehci->rh_state < EHCI_RH_RUNNING) - last_status = -ESHUTDOWN; - - /* this qtd is active; skip it unless a previous qtd - * for its urb faulted, or its urb was canceled. - */ - else if (last_status == -EINPROGRESS && !urb->unlinked) - continue; - - /* - * If this was the active qtd when the qh was unlinked - * and the overlay's token is active, then the overlay - * hasn't been written back to the qtd yet so use its - * token instead of the qtd's. After the qtd is - * processed and removed, the overlay won't be valid - * any more. - */ - if (state == QH_STATE_IDLE && - qh->qtd_list.next == &qtd->qtd_list && - (hw->hw_token & ACTIVE_BIT(ehci))) { - token = hc32_to_cpu(ehci, hw->hw_token); - hw->hw_token &= ~ACTIVE_BIT(ehci); - - /* An unlink may leave an incomplete - * async transaction in the TT buffer. - * We have to clear it. - */ - ehci_clear_tt_buffer(ehci, qh, urb, token); - } - } - - /* unless we already know the urb's status, collect qtd status - * and update count of bytes transferred. in common short read - * cases with only one data qtd (including control transfers), - * queue processing won't halt. but with two or more qtds (for - * example, with a 32 KB transfer), when the first qtd gets a - * short read the second must be removed by hand. - */ - if (last_status == -EINPROGRESS) { - last_status = qtd_copy_status(ehci, urb, - qtd->length, token); - if (last_status == -EREMOTEIO - && (qtd->hw_alt_next - & EHCI_LIST_END(ehci))) - last_status = -EINPROGRESS; - - /* As part of low/full-speed endpoint-halt processing - * we must clear the TT buffer (11.17.5). - */ - if (unlikely(last_status != -EINPROGRESS && - last_status != -EREMOTEIO)) { - /* The TT's in some hubs malfunction when they - * receive this request following a STALL (they - * stop sending isochronous packets). Since a - * STALL can't leave the TT buffer in a busy - * state (if you believe Figures 11-48 - 11-51 - * in the USB 2.0 spec), we won't clear the TT - * buffer in this case. Strictly speaking this - * is a violation of the spec. - */ - if (last_status != -EPIPE) - ehci_clear_tt_buffer(ehci, qh, urb, - token); - } - } - - /* if we're removing something not at the queue head, - * patch the hardware queue pointer. - */ - if (stopped && qtd->qtd_list.prev != &qh->qtd_list) { - last = list_entry (qtd->qtd_list.prev, - struct ehci_qtd, qtd_list); - last->hw_next = qtd->hw_next; - } - - /* remove qtd; it's recycled after possible urb completion */ - list_del (&qtd->qtd_list); - last = qtd; - - /* reinit the xacterr counter for the next qtd */ - qh->xacterrs = 0; - } - - /* last urb's completion might still need calling */ - if (likely (last != NULL)) { - ehci_urb_done(ehci, last->urb, last_status); - ehci_qtd_free (ehci, last); - } - - /* Do we need to rescan for URBs dequeued during a giveback? */ - if (unlikely(qh->dequeue_during_giveback)) { - /* If the QH is already unlinked, do the rescan now. */ - if (state == QH_STATE_IDLE) - goto rescan; - - /* Otherwise the caller must unlink the QH. */ - } - - /* restore original state; caller must unlink or relink */ - qh->qh_state = state; - - /* be sure the hardware's done with the qh before refreshing - * it after fault cleanup, or recovering from silicon wrongly - * overlaying the dummy qtd (which reduces DMA chatter). - * - * We won't refresh a QH that's linked (after the HC - * stopped the queue). That avoids a race: - * - HC reads first part of QH; - * - CPU updates that first part and the token; - * - HC reads rest of that QH, including token - * Result: HC gets an inconsistent image, and then - * DMAs to/from the wrong memory (corrupting it). - * - * That should be rare for interrupt transfers, - * except maybe high bandwidth ... - */ - if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) - qh->exception = 1; - - /* Let the caller know if the QH needs to be unlinked. */ - return qh->exception; -} - -/*-------------------------------------------------------------------------*/ - -// high bandwidth multiplier, as encoded in highspeed endpoint descriptors -#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03)) -// ... and packet size, for any kind of endpoint descriptor -#define max_packet(wMaxPacketSize) ((wMaxPacketSize) & 0x07ff) - -/* - * reverse of qh_urb_transaction: free a list of TDs. - * used for cleanup after errors, before HC sees an URB's TDs. - */ -static void qtd_list_free ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *qtd_list -) { - struct list_head *entry, *temp; - - list_for_each_safe (entry, temp, qtd_list) { - struct ehci_qtd *qtd; - - qtd = list_entry (entry, struct ehci_qtd, qtd_list); - list_del (&qtd->qtd_list); - ehci_qtd_free (ehci, qtd); - } -} - -/* - * create a list of filled qtds for this URB; won't link into qh. - */ -static struct list_head * -qh_urb_transaction ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *head, - gfp_t flags -) { - struct ehci_qtd *qtd, *qtd_prev; - dma_addr_t buf; - int len, this_sg_len, maxpacket; - int is_input; - u32 token; - int i; - struct scatterlist *sg; - - /* - * URBs map to sequences of QTDs: one logical transaction - */ - qtd = ehci_qtd_alloc (ehci, flags); - if (unlikely (!qtd)) - return NULL; - list_add_tail (&qtd->qtd_list, head); - qtd->urb = urb; - - token = QTD_STS_ACTIVE; - token |= (EHCI_TUNE_CERR << 10); - /* for split transactions, SplitXState initialized to zero */ - - len = urb->transfer_buffer_length; - is_input = usb_pipein (urb->pipe); - if (usb_pipecontrol (urb->pipe)) { - /* SETUP pid */ - qtd_fill(ehci, qtd, urb->setup_dma, - sizeof (struct usb_ctrlrequest), - token | (2 /* "setup" */ << 8), 8); - - /* ... and always at least one more pid */ - token ^= QTD_TOGGLE; - qtd_prev = qtd; - qtd = ehci_qtd_alloc (ehci, flags); - if (unlikely (!qtd)) - goto cleanup; - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma); - list_add_tail (&qtd->qtd_list, head); - - /* for zero length DATA stages, STATUS is always IN */ - if (len == 0) - token |= (1 /* "in" */ << 8); - } - - /* - * data transfer stage: buffer setup - */ - i = urb->num_mapped_sgs; - if (len > 0 && i > 0) { - sg = urb->sg; - buf = sg_dma_address(sg); - - /* urb->transfer_buffer_length may be smaller than the - * size of the scatterlist (or vice versa) - */ - this_sg_len = min_t(int, sg_dma_len(sg), len); - } else { - sg = NULL; - buf = urb->transfer_dma; - this_sg_len = len; - } - - if (is_input) - token |= (1 /* "in" */ << 8); - /* else it's already initted to "out" pid (0 << 8) */ - - maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, !is_input)); - - /* - * buffer gets wrapped in one or more qtds; - * last one may be "short" (including zero len) - * and may serve as a control status ack - */ - for (;;) { - int this_qtd_len; - - this_qtd_len = qtd_fill(ehci, qtd, buf, this_sg_len, token, - maxpacket); - this_sg_len -= this_qtd_len; - len -= this_qtd_len; - buf += this_qtd_len; - - /* - * short reads advance to a "magic" dummy instead of the next - * qtd ... that forces the queue to stop, for manual cleanup. - * (this will usually be overridden later.) - */ - if (is_input) - qtd->hw_alt_next = ehci->async->hw->hw_alt_next; - - /* qh makes control packets use qtd toggle; maybe switch it */ - if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) - token ^= QTD_TOGGLE; - - if (likely(this_sg_len <= 0)) { - if (--i <= 0 || len <= 0) - break; - sg = sg_next(sg); - buf = sg_dma_address(sg); - this_sg_len = min_t(int, sg_dma_len(sg), len); - } - - qtd_prev = qtd; - qtd = ehci_qtd_alloc (ehci, flags); - if (unlikely (!qtd)) - goto cleanup; - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma); - list_add_tail (&qtd->qtd_list, head); - } - - /* - * unless the caller requires manual cleanup after short reads, - * have the alt_next mechanism keep the queue running after the - * last data qtd (the only one, for control and most other cases). - */ - if (likely ((urb->transfer_flags & URB_SHORT_NOT_OK) == 0 - || usb_pipecontrol (urb->pipe))) - qtd->hw_alt_next = EHCI_LIST_END(ehci); - - /* - * control requests may need a terminating data "status" ack; - * other OUT ones may need a terminating short packet - * (zero length). - */ - if (likely (urb->transfer_buffer_length != 0)) { - int one_more = 0; - - if (usb_pipecontrol (urb->pipe)) { - one_more = 1; - token ^= 0x0100; /* "in" <--> "out" */ - token |= QTD_TOGGLE; /* force DATA1 */ - } else if (usb_pipeout(urb->pipe) - && (urb->transfer_flags & URB_ZERO_PACKET) - && !(urb->transfer_buffer_length % maxpacket)) { - one_more = 1; - } - if (one_more) { - qtd_prev = qtd; - qtd = ehci_qtd_alloc (ehci, flags); - if (unlikely (!qtd)) - goto cleanup; - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma); - list_add_tail (&qtd->qtd_list, head); - - /* never any data in such packets */ - qtd_fill(ehci, qtd, 0, 0, token, 0); - } - } - - /* by default, enable interrupt on urb completion */ - if (likely (!(urb->transfer_flags & URB_NO_INTERRUPT))) - qtd->hw_token |= cpu_to_hc32(ehci, QTD_IOC); - return head; - -cleanup: - qtd_list_free (ehci, urb, head); - return NULL; -} - -/*-------------------------------------------------------------------------*/ - -// Would be best to create all qh's from config descriptors, -// when each interface/altsetting is established. Unlink -// any previous qh and cancel its urbs first; endpoints are -// implicitly reset then (data toggle too). -// That'd mean updating how usbcore talks to HCDs. (2.7?) - - -/* - * Each QH holds a qtd list; a QH is used for everything except iso. - * - * For interrupt urbs, the scheduler must set the microframe scheduling - * mask(s) each time the QH gets scheduled. For highspeed, that's - * just one microframe in the s-mask. For split interrupt transactions - * there are additional complications: c-mask, maybe FSTNs. - */ -static struct ehci_qh * -qh_make ( - struct ehci_hcd *ehci, - struct urb *urb, - gfp_t flags -) { - struct ehci_qh *qh = ehci_qh_alloc (ehci, flags); - u32 info1 = 0, info2 = 0; - int is_input, type; - int maxp = 0; - struct usb_tt *tt = urb->dev->tt; - struct ehci_qh_hw *hw; - - if (!qh) - return qh; - - /* - * init endpoint/device data for this QH - */ - info1 |= usb_pipeendpoint (urb->pipe) << 8; - info1 |= usb_pipedevice (urb->pipe) << 0; - - is_input = usb_pipein (urb->pipe); - type = usb_pipetype (urb->pipe); - maxp = usb_maxpacket (urb->dev, urb->pipe, !is_input); - - /* 1024 byte maxpacket is a hardware ceiling. High bandwidth - * acts like up to 3KB, but is built from smaller packets. - */ - if (max_packet(maxp) > 1024) { - ehci_dbg(ehci, "bogus qh maxpacket %d\n", max_packet(maxp)); - goto done; - } - - /* Compute interrupt scheduling parameters just once, and save. - * - allowing for high bandwidth, how many nsec/uframe are used? - * - split transactions need a second CSPLIT uframe; same question - * - splits also need a schedule gap (for full/low speed I/O) - * - qh has a polling interval - * - * For control/bulk requests, the HC or TT handles these. - */ - if (type == PIPE_INTERRUPT) { - unsigned tmp; - - qh->ps.usecs = NS_TO_US(usb_calc_bus_time(USB_SPEED_HIGH, - is_input, 0, - hb_mult(maxp) * max_packet(maxp))); - qh->ps.phase = NO_FRAME; - - if (urb->dev->speed == USB_SPEED_HIGH) { - qh->ps.c_usecs = 0; - qh->gap_uf = 0; - - if (urb->interval > 1 && urb->interval < 8) { - /* NOTE interval 2 or 4 uframes could work. - * But interval 1 scheduling is simpler, and - * includes high bandwidth. - */ - urb->interval = 1; - } else if (urb->interval > ehci->periodic_size << 3) { - urb->interval = ehci->periodic_size << 3; - } - qh->ps.period = urb->interval >> 3; - - /* period for bandwidth allocation */ - tmp = min_t(unsigned, EHCI_BANDWIDTH_SIZE, - 1 << (urb->ep->desc.bInterval - 1)); - - /* Allow urb->interval to override */ - qh->ps.bw_uperiod = min_t(unsigned, tmp, urb->interval); - qh->ps.bw_period = qh->ps.bw_uperiod >> 3; - } else { - int think_time; - - /* gap is f(FS/LS transfer times) */ - qh->gap_uf = 1 + usb_calc_bus_time (urb->dev->speed, - is_input, 0, maxp) / (125 * 1000); - - /* FIXME this just approximates SPLIT/CSPLIT times */ - if (is_input) { // SPLIT, gap, CSPLIT+DATA - qh->ps.c_usecs = qh->ps.usecs + HS_USECS(0); - qh->ps.usecs = HS_USECS(1); - } else { // SPLIT+DATA, gap, CSPLIT - qh->ps.usecs += HS_USECS(1); - qh->ps.c_usecs = HS_USECS(0); - } - - think_time = tt ? tt->think_time : 0; - qh->ps.tt_usecs = NS_TO_US(think_time + - usb_calc_bus_time (urb->dev->speed, - is_input, 0, max_packet (maxp))); - if (urb->interval > ehci->periodic_size) - urb->interval = ehci->periodic_size; - qh->ps.period = urb->interval; - - /* period for bandwidth allocation */ - tmp = min_t(unsigned, EHCI_BANDWIDTH_FRAMES, - urb->ep->desc.bInterval); - tmp = rounddown_pow_of_two(tmp); - - /* Allow urb->interval to override */ - qh->ps.bw_period = min_t(unsigned, tmp, urb->interval); - qh->ps.bw_uperiod = qh->ps.bw_period << 3; - } - } - - /* support for tt scheduling, and access to toggles */ - qh->ps.udev = urb->dev; - qh->ps.ep = urb->ep; - - /* using TT? */ - switch (urb->dev->speed) { - case USB_SPEED_LOW: - info1 |= QH_LOW_SPEED; - /* FALL THROUGH */ - - case USB_SPEED_FULL: - /* EPS 0 means "full" */ - if (type != PIPE_INTERRUPT) - info1 |= (EHCI_TUNE_RL_TT << 28); - if (type == PIPE_CONTROL) { - info1 |= QH_CONTROL_EP; /* for TT */ - info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ - } - info1 |= maxp << 16; - - info2 |= (EHCI_TUNE_MULT_TT << 30); - - /* Some Freescale processors have an erratum in which the - * port number in the queue head was 0..N-1 instead of 1..N. - */ - if (ehci_has_fsl_portno_bug(ehci)) - info2 |= (urb->dev->ttport-1) << 23; - else - info2 |= urb->dev->ttport << 23; - - /* set the address of the TT; for TDI's integrated - * root hub tt, leave it zeroed. - */ - if (tt && tt->hub != ehci_to_hcd(ehci)->self.root_hub) - info2 |= tt->hub->devnum << 16; - - /* NOTE: if (PIPE_INTERRUPT) { scheduler sets c-mask } */ - - break; - - case USB_SPEED_HIGH: /* no TT involved */ - info1 |= QH_HIGH_SPEED; - if (type == PIPE_CONTROL) { - info1 |= (EHCI_TUNE_RL_HS << 28); - info1 |= 64 << 16; /* usb2 fixed maxpacket */ - info1 |= QH_TOGGLE_CTL; /* toggle from qtd */ - info2 |= (EHCI_TUNE_MULT_HS << 30); - } else if (type == PIPE_BULK) { - info1 |= (EHCI_TUNE_RL_HS << 28); - /* The USB spec says that high speed bulk endpoints - * always use 512 byte maxpacket. But some device - * vendors decided to ignore that, and MSFT is happy - * to help them do so. So now people expect to use - * such nonconformant devices with Linux too; sigh. - */ - info1 |= max_packet(maxp) << 16; - info2 |= (EHCI_TUNE_MULT_HS << 30); - } else { /* PIPE_INTERRUPT */ - info1 |= max_packet (maxp) << 16; - info2 |= hb_mult (maxp) << 30; - } - break; - default: - ehci_dbg(ehci, "bogus dev %p speed %d\n", urb->dev, - urb->dev->speed); -done: - qh_destroy(ehci, qh); - return NULL; - } - - /* NOTE: if (PIPE_INTERRUPT) { scheduler sets s-mask } */ - - /* init as live, toggle clear */ - qh->qh_state = QH_STATE_IDLE; - hw = qh->hw; - hw->hw_info1 = cpu_to_hc32(ehci, info1); - hw->hw_info2 = cpu_to_hc32(ehci, info2); - qh->is_out = !is_input; - usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); - return qh; -} - -/*-------------------------------------------------------------------------*/ - -static void enable_async(struct ehci_hcd *ehci) -{ - if (ehci->async_count++) - return; - - /* Stop waiting to turn off the async schedule */ - ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_DISABLE_ASYNC); - - /* Don't start the schedule until ASS is 0 */ - ehci_poll_ASS(ehci); - turn_on_io_watchdog(ehci); -} - -static void disable_async(struct ehci_hcd *ehci) -{ - if (--ehci->async_count) - return; - - /* The async schedule and unlink lists are supposed to be empty */ - WARN_ON(ehci->async->qh_next.qh || !list_empty(&ehci->async_unlink) || - !list_empty(&ehci->async_idle)); - - /* Don't turn off the schedule until ASS is 1 */ - ehci_poll_ASS(ehci); -} - -/* move qh (and its qtds) onto async queue; maybe enable queue. */ - -static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - __hc32 dma = QH_NEXT(ehci, qh->qh_dma); - struct ehci_qh *head; - - /* Don't link a QH if there's a Clear-TT-Buffer pending */ - if (unlikely(qh->clearing_tt)) - return; - - WARN_ON(qh->qh_state != QH_STATE_IDLE); - - /* clear halt and/or toggle; and maybe recover from silicon quirk */ - qh_refresh(ehci, qh); - - /* splice right after start */ - head = ehci->async; - qh->qh_next = head->qh_next; - qh->hw->hw_next = head->hw->hw_next; - wmb (); - - head->qh_next.qh = qh; - head->hw->hw_next = dma; - - qh->qh_state = QH_STATE_LINKED; - qh->xacterrs = 0; - qh->exception = 0; - /* qtd completions reported later by interrupt */ - - enable_async(ehci); -} - -/*-------------------------------------------------------------------------*/ - -/* - * For control/bulk/interrupt, return QH with these TDs appended. - * Allocates and initializes the QH if necessary. - * Returns null if it can't allocate a QH it needs to. - * If the QH has TDs (urbs) already, that's great. - */ -static struct ehci_qh *qh_append_tds ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *qtd_list, - int epnum, - void **ptr -) -{ - struct ehci_qh *qh = NULL; - __hc32 qh_addr_mask = cpu_to_hc32(ehci, 0x7f); - - qh = (struct ehci_qh *) *ptr; - if (unlikely (qh == NULL)) { - /* can't sleep here, we have ehci->lock... */ - qh = qh_make (ehci, urb, GFP_ATOMIC); - *ptr = qh; - } - if (likely (qh != NULL)) { - struct ehci_qtd *qtd; - - if (unlikely (list_empty (qtd_list))) - qtd = NULL; - else - qtd = list_entry (qtd_list->next, struct ehci_qtd, - qtd_list); - - /* control qh may need patching ... */ - if (unlikely (epnum == 0)) { - - /* usb_reset_device() briefly reverts to address 0 */ - if (usb_pipedevice (urb->pipe) == 0) - qh->hw->hw_info1 &= ~qh_addr_mask; - } - - /* just one way to queue requests: swap with the dummy qtd. - * only hc or qh_refresh() ever modify the overlay. - */ - if (likely (qtd != NULL)) { - struct ehci_qtd *dummy; - dma_addr_t dma; - __hc32 token; - - /* to avoid racing the HC, use the dummy td instead of - * the first td of our list (becomes new dummy). both - * tds stay deactivated until we're done, when the - * HC is allowed to fetch the old dummy (4.10.2). - */ - token = qtd->hw_token; - qtd->hw_token = HALT_BIT(ehci); - - dummy = qh->dummy; - - dma = dummy->qtd_dma; - *dummy = *qtd; - dummy->qtd_dma = dma; - - list_del (&qtd->qtd_list); - list_add (&dummy->qtd_list, qtd_list); - list_splice_tail(qtd_list, &qh->qtd_list); - - ehci_qtd_init(ehci, qtd, qtd->qtd_dma); - qh->dummy = qtd; - - /* hc must see the new dummy at list end */ - dma = qtd->qtd_dma; - qtd = list_entry (qh->qtd_list.prev, - struct ehci_qtd, qtd_list); - qtd->hw_next = QTD_NEXT(ehci, dma); - - /* let the hc process these next qtds */ - wmb (); - dummy->hw_token = token; - - urb->hcpriv = qh; - } - } - return qh; -} - -/*-------------------------------------------------------------------------*/ - -static int -submit_async ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *qtd_list, - gfp_t mem_flags -) { - int epnum; - unsigned long flags; - struct ehci_qh *qh = NULL; - int rc; - - epnum = urb->ep->desc.bEndpointAddress; - -#ifdef EHCI_URB_TRACE - { - struct ehci_qtd *qtd; - qtd = list_entry(qtd_list->next, struct ehci_qtd, qtd_list); - ehci_dbg(ehci, - "%s %s urb %p ep%d%s len %d, qtd %p [qh %p]\n", - __func__, urb->dev->devpath, urb, - epnum & 0x0f, (epnum & USB_DIR_IN) ? "in" : "out", - urb->transfer_buffer_length, - qtd, urb->ep->hcpriv); - } -#endif - - spin_lock_irqsave (&ehci->lock, flags); - if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { - rc = -ESHUTDOWN; - goto done; - } - rc = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); - if (unlikely(rc)) - goto done; - - qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv); - if (unlikely(qh == NULL)) { - usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); - rc = -ENOMEM; - goto done; - } - - /* Control/bulk operations through TTs don't need scheduling, - * the HC and TT handle it when the TT has a buffer ready. - */ - if (likely (qh->qh_state == QH_STATE_IDLE)) - qh_link_async(ehci, qh); - done: - spin_unlock_irqrestore (&ehci->lock, flags); - if (unlikely (qh == NULL)) - qtd_list_free (ehci, urb, qtd_list); - return rc; -} - -/*-------------------------------------------------------------------------*/ -#ifdef CONFIG_USB_HCD_TEST_MODE -/* - * This function creates the qtds and submits them for the - * SINGLE_STEP_SET_FEATURE Test. - * This is done in two parts: first SETUP req for GetDesc is sent then - * 15 seconds later, the IN stage for GetDesc starts to req data from dev - * - * is_setup : i/p arguement decides which of the two stage needs to be - * performed; TRUE - SETUP and FALSE - IN+STATUS - * Returns 0 if success - */ -static int submit_single_step_set_feature( - struct usb_hcd *hcd, - struct urb *urb, - int is_setup -) { - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - struct list_head qtd_list; - struct list_head *head; - - struct ehci_qtd *qtd, *qtd_prev; - dma_addr_t buf; - int len, maxpacket; - u32 token; - - INIT_LIST_HEAD(&qtd_list); - head = &qtd_list; - - /* URBs map to sequences of QTDs: one logical transaction */ - qtd = ehci_qtd_alloc(ehci, GFP_KERNEL); - if (unlikely(!qtd)) - return -1; - list_add_tail(&qtd->qtd_list, head); - qtd->urb = urb; - - token = QTD_STS_ACTIVE; - token |= (EHCI_TUNE_CERR << 10); - - len = urb->transfer_buffer_length; - /* - * Check if the request is to perform just the SETUP stage (getDesc) - * as in SINGLE_STEP_SET_FEATURE test, DATA stage (IN) happens - * 15 secs after the setup - */ - if (is_setup) { - /* SETUP pid */ - qtd_fill(ehci, qtd, urb->setup_dma, - sizeof(struct usb_ctrlrequest), - token | (2 /* "setup" */ << 8), 8); - - submit_async(ehci, urb, &qtd_list, GFP_ATOMIC); - return 0; /*Return now; we shall come back after 15 seconds*/ - } - - /* - * IN: data transfer stage: buffer setup : start the IN txn phase for - * the get_Desc SETUP which was sent 15seconds back - */ - token ^= QTD_TOGGLE; /*We need to start IN with DATA-1 Pid-sequence*/ - buf = urb->transfer_dma; - - token |= (1 /* "in" */ << 8); /*This is IN stage*/ - - maxpacket = max_packet(usb_maxpacket(urb->dev, urb->pipe, 0)); - - qtd_fill(ehci, qtd, buf, len, token, maxpacket); - - /* - * Our IN phase shall always be a short read; so keep the queue running - * and let it advance to the next qtd which zero length OUT status - */ - qtd->hw_alt_next = EHCI_LIST_END(ehci); - - /* STATUS stage for GetDesc control request */ - token ^= 0x0100; /* "in" <--> "out" */ - token |= QTD_TOGGLE; /* force DATA1 */ - - qtd_prev = qtd; - qtd = ehci_qtd_alloc(ehci, GFP_ATOMIC); - if (unlikely(!qtd)) - goto cleanup; - qtd->urb = urb; - qtd_prev->hw_next = QTD_NEXT(ehci, qtd->qtd_dma); - list_add_tail(&qtd->qtd_list, head); - - /* dont fill any data in such packets */ - qtd_fill(ehci, qtd, 0, 0, token, 0); - - /* by default, enable interrupt on urb completion */ - if (likely(!(urb->transfer_flags & URB_NO_INTERRUPT))) - qtd->hw_token |= cpu_to_hc32(ehci, QTD_IOC); - - submit_async(ehci, urb, &qtd_list, GFP_KERNEL); - - return 0; - -cleanup: - qtd_list_free(ehci, urb, head); - return -1; -} -#endif /* CONFIG_USB_HCD_TEST_MODE */ - -/*-------------------------------------------------------------------------*/ - -static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - struct ehci_qh *prev; - - /* Add to the end of the list of QHs waiting for the next IAAD */ - qh->qh_state = QH_STATE_UNLINK_WAIT; - list_add_tail(&qh->unlink_node, &ehci->async_unlink); - - /* Unlink it from the schedule */ - prev = ehci->async; - while (prev->qh_next.qh != qh) - prev = prev->qh_next.qh; - - prev->hw->hw_next = qh->hw->hw_next; - prev->qh_next = qh->qh_next; - if (ehci->qh_scan_next == qh) - ehci->qh_scan_next = qh->qh_next.qh; -} - -static void start_iaa_cycle(struct ehci_hcd *ehci) -{ - /* Do nothing if an IAA cycle is already running */ - if (ehci->iaa_in_progress) - return; - ehci->iaa_in_progress = true; - - /* If the controller isn't running, we don't have to wait for it */ - if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) { - end_unlink_async(ehci); - - /* Otherwise start a new IAA cycle */ - } else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { - - /* Make sure the unlinks are all visible to the hardware */ - wmb(); - - ehci_writel(ehci, ehci->command | CMD_IAAD, - &ehci->regs->command); - ehci_readl(ehci, &ehci->regs->command); - ehci_enable_event(ehci, EHCI_HRTIMER_IAA_WATCHDOG, true); - } -} - -/* the async qh for the qtds being unlinked are now gone from the HC */ - -static void end_unlink_async(struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - bool early_exit; - - if (ehci->has_synopsys_hc_bug) - ehci_writel(ehci, (u32) ehci->async->qh_dma, - &ehci->regs->async_next); - - /* The current IAA cycle has ended */ - ehci->iaa_in_progress = false; - - if (list_empty(&ehci->async_unlink)) - return; - qh = list_first_entry(&ehci->async_unlink, struct ehci_qh, - unlink_node); /* QH whose IAA cycle just ended */ - - /* - * If async_unlinking is set then this routine is already running, - * either on the stack or on another CPU. - */ - early_exit = ehci->async_unlinking; - - /* If the controller isn't running, process all the waiting QHs */ - if (ehci->rh_state < EHCI_RH_RUNNING) - list_splice_tail_init(&ehci->async_unlink, &ehci->async_idle); - - /* - * Intel (?) bug: The HC can write back the overlay region even - * after the IAA interrupt occurs. In self-defense, always go - * through two IAA cycles for each QH. - */ - else if (qh->qh_state == QH_STATE_UNLINK_WAIT) { - qh->qh_state = QH_STATE_UNLINK; - early_exit = true; - } - - /* Otherwise process only the first waiting QH (NVIDIA bug?) */ - else - list_move_tail(&qh->unlink_node, &ehci->async_idle); - - /* Start a new IAA cycle if any QHs are waiting for it */ - if (!list_empty(&ehci->async_unlink)) - start_iaa_cycle(ehci); - - /* - * Don't allow nesting or concurrent calls, - * or wait for the second IAA cycle for the next QH. - */ - if (early_exit) - return; - - /* Process the idle QHs */ - ehci->async_unlinking = true; - while (!list_empty(&ehci->async_idle)) { - qh = list_first_entry(&ehci->async_idle, struct ehci_qh, - unlink_node); - list_del(&qh->unlink_node); - - qh->qh_state = QH_STATE_IDLE; - qh->qh_next.qh = NULL; - - if (!list_empty(&qh->qtd_list)) - qh_completions(ehci, qh); - if (!list_empty(&qh->qtd_list) && - ehci->rh_state == EHCI_RH_RUNNING) - qh_link_async(ehci, qh); - disable_async(ehci); - } - ehci->async_unlinking = false; -} - -static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh); - -static void unlink_empty_async(struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - struct ehci_qh *qh_to_unlink = NULL; - int count = 0; - - /* Find the last async QH which has been empty for a timer cycle */ - for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh) { - if (list_empty(&qh->qtd_list) && - qh->qh_state == QH_STATE_LINKED) { - ++count; - if (qh->unlink_cycle != ehci->async_unlink_cycle) - qh_to_unlink = qh; - } - } - - /* If nothing else is being unlinked, unlink the last empty QH */ - if (list_empty(&ehci->async_unlink) && qh_to_unlink) { - start_unlink_async(ehci, qh_to_unlink); - --count; - } - - /* Other QHs will be handled later */ - if (count > 0) { - ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true); - ++ehci->async_unlink_cycle; - } -} - -/* The root hub is suspended; unlink all the async QHs */ -static void __maybe_unused unlink_empty_async_suspended(struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - - while (ehci->async->qh_next.qh) { - qh = ehci->async->qh_next.qh; - WARN_ON(!list_empty(&qh->qtd_list)); - single_unlink_async(ehci, qh); - } - start_iaa_cycle(ehci); -} - -/* makes sure the async qh will become idle */ -/* caller must own ehci->lock */ - -static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - /* If the QH isn't linked then there's nothing we can do. */ - if (qh->qh_state != QH_STATE_LINKED) - return; - - single_unlink_async(ehci, qh); - start_iaa_cycle(ehci); -} - -/*-------------------------------------------------------------------------*/ - -static void scan_async (struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - bool check_unlinks_later = false; - - ehci->qh_scan_next = ehci->async->qh_next.qh; - while (ehci->qh_scan_next) { - qh = ehci->qh_scan_next; - ehci->qh_scan_next = qh->qh_next.qh; - - /* clean any finished work for this qh */ - if (!list_empty(&qh->qtd_list)) { - int temp; - - /* - * Unlinks could happen here; completion reporting - * drops the lock. That's why ehci->qh_scan_next - * always holds the next qh to scan; if the next qh - * gets unlinked then ehci->qh_scan_next is adjusted - * in single_unlink_async(). - */ - temp = qh_completions(ehci, qh); - if (unlikely(temp)) { - start_unlink_async(ehci, qh); - } else if (list_empty(&qh->qtd_list) - && qh->qh_state == QH_STATE_LINKED) { - qh->unlink_cycle = ehci->async_unlink_cycle; - check_unlinks_later = true; - } - } - } - - /* - * Unlink empty entries, reducing DMA usage as well - * as HCD schedule-scanning costs. Delay for any qh - * we just scanned, there's a not-unusual case that it - * doesn't stay idle for long. - */ - if (check_unlinks_later && ehci->rh_state == EHCI_RH_RUNNING && - !(ehci->enabled_hrtimer_events & - BIT(EHCI_HRTIMER_ASYNC_UNLINKS))) { - ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true); - ++ehci->async_unlink_cycle; - } -} diff --git a/addons/ehci-pci/src/4.4.180/ehci-sched.c b/addons/ehci-pci/src/4.4.180/ehci-sched.c deleted file mode 100644 index f9a33277..00000000 --- a/addons/ehci-pci/src/4.4.180/ehci-sched.c +++ /dev/null @@ -1,2517 +0,0 @@ -/* - * Copyright (c) 2001-2004 by David Brownell - * Copyright (c) 2003 Michal Sojka, for high-speed iso transfers - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI scheduled transaction support: interrupt, iso, split iso - * These are called "periodic" transactions in the EHCI spec. - * - * Note that for interrupt transfers, the QH/QTD manipulation is shared - * with the "asynchronous" transaction support (control/bulk transfers). - * The only real difference is in how interrupt transfers are scheduled. - * - * For ISO, we make an "iso_stream" head to serve the same role as a QH. - * It keeps track of every ITD (or SITD) that's linked, and holds enough - * pre-calculated schedule data to make appending to the queue be quick. - */ - -static int ehci_get_frame (struct usb_hcd *hcd); - -/* - * periodic_next_shadow - return "next" pointer on shadow list - * @periodic: host pointer to qh/itd/sitd - * @tag: hardware tag for type of this record - */ -static union ehci_shadow * -periodic_next_shadow(struct ehci_hcd *ehci, union ehci_shadow *periodic, - __hc32 tag) -{ - switch (hc32_to_cpu(ehci, tag)) { - case Q_TYPE_QH: - return &periodic->qh->qh_next; - case Q_TYPE_FSTN: - return &periodic->fstn->fstn_next; - case Q_TYPE_ITD: - return &periodic->itd->itd_next; - // case Q_TYPE_SITD: - default: - return &periodic->sitd->sitd_next; - } -} - -static __hc32 * -shadow_next_periodic(struct ehci_hcd *ehci, union ehci_shadow *periodic, - __hc32 tag) -{ - switch (hc32_to_cpu(ehci, tag)) { - /* our ehci_shadow.qh is actually software part */ - case Q_TYPE_QH: - return &periodic->qh->hw->hw_next; - /* others are hw parts */ - default: - return periodic->hw_next; - } -} - -/* caller must hold ehci->lock */ -static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) -{ - union ehci_shadow *prev_p = &ehci->pshadow[frame]; - __hc32 *hw_p = &ehci->periodic[frame]; - union ehci_shadow here = *prev_p; - - /* find predecessor of "ptr"; hw and shadow lists are in sync */ - while (here.ptr && here.ptr != ptr) { - prev_p = periodic_next_shadow(ehci, prev_p, - Q_NEXT_TYPE(ehci, *hw_p)); - hw_p = shadow_next_periodic(ehci, &here, - Q_NEXT_TYPE(ehci, *hw_p)); - here = *prev_p; - } - /* an interrupt entry (at list end) could have been shared */ - if (!here.ptr) - return; - - /* update shadow and hardware lists ... the old "next" pointers - * from ptr may still be in use, the caller updates them. - */ - *prev_p = *periodic_next_shadow(ehci, &here, - Q_NEXT_TYPE(ehci, *hw_p)); - - if (!ehci->use_dummy_qh || - *shadow_next_periodic(ehci, &here, Q_NEXT_TYPE(ehci, *hw_p)) - != EHCI_LIST_END(ehci)) - *hw_p = *shadow_next_periodic(ehci, &here, - Q_NEXT_TYPE(ehci, *hw_p)); - else - *hw_p = cpu_to_hc32(ehci, ehci->dummy->qh_dma); -} - -/*-------------------------------------------------------------------------*/ - -/* Bandwidth and TT management */ - -/* Find the TT data structure for this device; create it if necessary */ -static struct ehci_tt *find_tt(struct usb_device *udev) -{ - struct usb_tt *utt = udev->tt; - struct ehci_tt *tt, **tt_index, **ptt; - unsigned port; - bool allocated_index = false; - - if (!utt) - return NULL; /* Not below a TT */ - - /* - * Find/create our data structure. - * For hubs with a single TT, we get it directly. - * For hubs with multiple TTs, there's an extra level of pointers. - */ - tt_index = NULL; - if (utt->multi) { - tt_index = utt->hcpriv; - if (!tt_index) { /* Create the index array */ - tt_index = kzalloc(utt->hub->maxchild * - sizeof(*tt_index), GFP_ATOMIC); - if (!tt_index) - return ERR_PTR(-ENOMEM); - utt->hcpriv = tt_index; - allocated_index = true; - } - port = udev->ttport - 1; - ptt = &tt_index[port]; - } else { - port = 0; - ptt = (struct ehci_tt **) &utt->hcpriv; - } - - tt = *ptt; - if (!tt) { /* Create the ehci_tt */ - struct ehci_hcd *ehci = - hcd_to_ehci(bus_to_hcd(udev->bus)); - - tt = kzalloc(sizeof(*tt), GFP_ATOMIC); - if (!tt) { - if (allocated_index) { - utt->hcpriv = NULL; - kfree(tt_index); - } - return ERR_PTR(-ENOMEM); - } - list_add_tail(&tt->tt_list, &ehci->tt_list); - INIT_LIST_HEAD(&tt->ps_list); - tt->usb_tt = utt; - tt->tt_port = port; - *ptt = tt; - } - - return tt; -} - -/* Release the TT above udev, if it's not in use */ -static void drop_tt(struct usb_device *udev) -{ - struct usb_tt *utt = udev->tt; - struct ehci_tt *tt, **tt_index, **ptt; - int cnt, i; - - if (!utt || !utt->hcpriv) - return; /* Not below a TT, or never allocated */ - - cnt = 0; - if (utt->multi) { - tt_index = utt->hcpriv; - ptt = &tt_index[udev->ttport - 1]; - - /* How many entries are left in tt_index? */ - for (i = 0; i < utt->hub->maxchild; ++i) - cnt += !!tt_index[i]; - } else { - tt_index = NULL; - ptt = (struct ehci_tt **) &utt->hcpriv; - } - - tt = *ptt; - if (!tt || !list_empty(&tt->ps_list)) - return; /* never allocated, or still in use */ - - list_del(&tt->tt_list); - *ptt = NULL; - kfree(tt); - if (cnt == 1) { - utt->hcpriv = NULL; - kfree(tt_index); - } -} - -static void bandwidth_dbg(struct ehci_hcd *ehci, int sign, char *type, - struct ehci_per_sched *ps) -{ - dev_dbg(&ps->udev->dev, - "ep %02x: %s %s @ %u+%u (%u.%u+%u) [%u/%u us] mask %04x\n", - ps->ep->desc.bEndpointAddress, - (sign >= 0 ? "reserve" : "release"), type, - (ps->bw_phase << 3) + ps->phase_uf, ps->bw_uperiod, - ps->phase, ps->phase_uf, ps->period, - ps->usecs, ps->c_usecs, ps->cs_mask); -} - -static void reserve_release_intr_bandwidth(struct ehci_hcd *ehci, - struct ehci_qh *qh, int sign) -{ - unsigned start_uf; - unsigned i, j, m; - int usecs = qh->ps.usecs; - int c_usecs = qh->ps.c_usecs; - int tt_usecs = qh->ps.tt_usecs; - struct ehci_tt *tt; - - if (qh->ps.phase == NO_FRAME) /* Bandwidth wasn't reserved */ - return; - start_uf = qh->ps.bw_phase << 3; - - bandwidth_dbg(ehci, sign, "intr", &qh->ps); - - if (sign < 0) { /* Release bandwidth */ - usecs = -usecs; - c_usecs = -c_usecs; - tt_usecs = -tt_usecs; - } - - /* Entire transaction (high speed) or start-split (full/low speed) */ - for (i = start_uf + qh->ps.phase_uf; i < EHCI_BANDWIDTH_SIZE; - i += qh->ps.bw_uperiod) - ehci->bandwidth[i] += usecs; - - /* Complete-split (full/low speed) */ - if (qh->ps.c_usecs) { - /* NOTE: adjustments needed for FSTN */ - for (i = start_uf; i < EHCI_BANDWIDTH_SIZE; - i += qh->ps.bw_uperiod) { - for ((j = 2, m = 1 << (j+8)); j < 8; (++j, m <<= 1)) { - if (qh->ps.cs_mask & m) - ehci->bandwidth[i+j] += c_usecs; - } - } - } - - /* FS/LS bus bandwidth */ - if (tt_usecs) { - tt = find_tt(qh->ps.udev); - if (sign > 0) - list_add_tail(&qh->ps.ps_list, &tt->ps_list); - else - list_del(&qh->ps.ps_list); - - for (i = start_uf >> 3; i < EHCI_BANDWIDTH_FRAMES; - i += qh->ps.bw_period) - tt->bandwidth[i] += tt_usecs; - } -} - -/*-------------------------------------------------------------------------*/ - -static void compute_tt_budget(u8 budget_table[EHCI_BANDWIDTH_SIZE], - struct ehci_tt *tt) -{ - struct ehci_per_sched *ps; - unsigned uframe, uf, x; - u8 *budget_line; - - if (!tt) - return; - memset(budget_table, 0, EHCI_BANDWIDTH_SIZE); - - /* Add up the contributions from all the endpoints using this TT */ - list_for_each_entry(ps, &tt->ps_list, ps_list) { - for (uframe = ps->bw_phase << 3; uframe < EHCI_BANDWIDTH_SIZE; - uframe += ps->bw_uperiod) { - budget_line = &budget_table[uframe]; - x = ps->tt_usecs; - - /* propagate the time forward */ - for (uf = ps->phase_uf; uf < 8; ++uf) { - x += budget_line[uf]; - - /* Each microframe lasts 125 us */ - if (x <= 125) { - budget_line[uf] = x; - break; - } else { - budget_line[uf] = 125; - x -= 125; - } - } - } - } -} - -static int __maybe_unused same_tt(struct usb_device *dev1, - struct usb_device *dev2) -{ - if (!dev1->tt || !dev2->tt) - return 0; - if (dev1->tt != dev2->tt) - return 0; - if (dev1->tt->multi) - return dev1->ttport == dev2->ttport; - else - return 1; -} - -#ifdef CONFIG_USB_EHCI_TT_NEWSCHED - -/* Which uframe does the low/fullspeed transfer start in? - * - * The parameter is the mask of ssplits in "H-frame" terms - * and this returns the transfer start uframe in "B-frame" terms, - * which allows both to match, e.g. a ssplit in "H-frame" uframe 0 - * will cause a transfer in "B-frame" uframe 0. "B-frames" lag - * "H-frames" by 1 uframe. See the EHCI spec sec 4.5 and figure 4.7. - */ -static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) -{ - unsigned char smask = QH_SMASK & hc32_to_cpu(ehci, mask); - if (!smask) { - ehci_err(ehci, "invalid empty smask!\n"); - /* uframe 7 can't have bw so this will indicate failure */ - return 7; - } - return ffs(smask) - 1; -} - -static const unsigned char -max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; - -/* carryover low/fullspeed bandwidth that crosses uframe boundries */ -static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) -{ - int i; - for (i=0; i<7; i++) { - if (max_tt_usecs[i] < tt_usecs[i]) { - tt_usecs[i+1] += tt_usecs[i] - max_tt_usecs[i]; - tt_usecs[i] = max_tt_usecs[i]; - } - } -} - -/* - * Return true if the device's tt's downstream bus is available for a - * periodic transfer of the specified length (usecs), starting at the - * specified frame/uframe. Note that (as summarized in section 11.19 - * of the usb 2.0 spec) TTs can buffer multiple transactions for each - * uframe. - * - * The uframe parameter is when the fullspeed/lowspeed transfer - * should be executed in "B-frame" terms, which is the same as the - * highspeed ssplit's uframe (which is in "H-frame" terms). For example - * a ssplit in "H-frame" 0 causes a transfer in "B-frame" 0. - * See the EHCI spec sec 4.5 and fig 4.7. - * - * This checks if the full/lowspeed bus, at the specified starting uframe, - * has the specified bandwidth available, according to rules listed - * in USB 2.0 spec section 11.18.1 fig 11-60. - * - * This does not check if the transfer would exceed the max ssplit - * limit of 16, specified in USB 2.0 spec section 11.18.4 requirement #4, - * since proper scheduling limits ssplits to less than 16 per uframe. - */ -static int tt_available ( - struct ehci_hcd *ehci, - struct ehci_per_sched *ps, - struct ehci_tt *tt, - unsigned frame, - unsigned uframe -) -{ - unsigned period = ps->bw_period; - unsigned usecs = ps->tt_usecs; - - if ((period == 0) || (uframe >= 7)) /* error */ - return 0; - - for (frame &= period - 1; frame < EHCI_BANDWIDTH_FRAMES; - frame += period) { - unsigned i, uf; - unsigned short tt_usecs[8]; - - if (tt->bandwidth[frame] + usecs > 900) - return 0; - - uf = frame << 3; - for (i = 0; i < 8; (++i, ++uf)) - tt_usecs[i] = ehci->tt_budget[uf]; - - if (max_tt_usecs[uframe] <= tt_usecs[uframe]) - return 0; - - /* special case for isoc transfers larger than 125us: - * the first and each subsequent fully used uframe - * must be empty, so as to not illegally delay - * already scheduled transactions - */ - if (125 < usecs) { - int ufs = (usecs / 125); - - for (i = uframe; i < (uframe + ufs) && i < 8; i++) - if (0 < tt_usecs[i]) - return 0; - } - - tt_usecs[uframe] += usecs; - - carryover_tt_bandwidth(tt_usecs); - - /* fail if the carryover pushed bw past the last uframe's limit */ - if (max_tt_usecs[7] < tt_usecs[7]) - return 0; - } - - return 1; -} - -#else - -/* return true iff the device's transaction translator is available - * for a periodic transfer starting at the specified frame, using - * all the uframes in the mask. - */ -static int tt_no_collision ( - struct ehci_hcd *ehci, - unsigned period, - struct usb_device *dev, - unsigned frame, - u32 uf_mask -) -{ - if (period == 0) /* error */ - return 0; - - /* note bandwidth wastage: split never follows csplit - * (different dev or endpoint) until the next uframe. - * calling convention doesn't make that distinction. - */ - for (; frame < ehci->periodic_size; frame += period) { - union ehci_shadow here; - __hc32 type; - struct ehci_qh_hw *hw; - - here = ehci->pshadow [frame]; - type = Q_NEXT_TYPE(ehci, ehci->periodic [frame]); - while (here.ptr) { - switch (hc32_to_cpu(ehci, type)) { - case Q_TYPE_ITD: - type = Q_NEXT_TYPE(ehci, here.itd->hw_next); - here = here.itd->itd_next; - continue; - case Q_TYPE_QH: - hw = here.qh->hw; - if (same_tt(dev, here.qh->ps.udev)) { - u32 mask; - - mask = hc32_to_cpu(ehci, - hw->hw_info2); - /* "knows" no gap is needed */ - mask |= mask >> 8; - if (mask & uf_mask) - break; - } - type = Q_NEXT_TYPE(ehci, hw->hw_next); - here = here.qh->qh_next; - continue; - case Q_TYPE_SITD: - if (same_tt (dev, here.sitd->urb->dev)) { - u16 mask; - - mask = hc32_to_cpu(ehci, here.sitd - ->hw_uframe); - /* FIXME assumes no gap for IN! */ - mask |= mask >> 8; - if (mask & uf_mask) - break; - } - type = Q_NEXT_TYPE(ehci, here.sitd->hw_next); - here = here.sitd->sitd_next; - continue; - // case Q_TYPE_FSTN: - default: - ehci_dbg (ehci, - "periodic frame %d bogus type %d\n", - frame, type); - } - - /* collision or error */ - return 0; - } - } - - /* no collision */ - return 1; -} - -#endif /* CONFIG_USB_EHCI_TT_NEWSCHED */ - -/*-------------------------------------------------------------------------*/ - -static void enable_periodic(struct ehci_hcd *ehci) -{ - if (ehci->periodic_count++) - return; - - /* Stop waiting to turn off the periodic schedule */ - ehci->enabled_hrtimer_events &= ~BIT(EHCI_HRTIMER_DISABLE_PERIODIC); - - /* Don't start the schedule until PSS is 0 */ - ehci_poll_PSS(ehci); - turn_on_io_watchdog(ehci); -} - -static void disable_periodic(struct ehci_hcd *ehci) -{ - if (--ehci->periodic_count) - return; - - /* Don't turn off the schedule until PSS is 1 */ - ehci_poll_PSS(ehci); -} - -/*-------------------------------------------------------------------------*/ - -/* periodic schedule slots have iso tds (normal or split) first, then a - * sparse tree for active interrupt transfers. - * - * this just links in a qh; caller guarantees uframe masks are set right. - * no FSTN support (yet; ehci 0.96+) - */ -static void qh_link_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - unsigned i; - unsigned period = qh->ps.period; - - dev_dbg(&qh->ps.udev->dev, - "link qh%d-%04x/%p start %d [%d/%d us]\n", - period, hc32_to_cpup(ehci, &qh->hw->hw_info2) - & (QH_CMASK | QH_SMASK), - qh, qh->ps.phase, qh->ps.usecs, qh->ps.c_usecs); - - /* high bandwidth, or otherwise every microframe */ - if (period == 0) - period = 1; - - for (i = qh->ps.phase; i < ehci->periodic_size; i += period) { - union ehci_shadow *prev = &ehci->pshadow[i]; - __hc32 *hw_p = &ehci->periodic[i]; - union ehci_shadow here = *prev; - __hc32 type = 0; - - /* skip the iso nodes at list head */ - while (here.ptr) { - type = Q_NEXT_TYPE(ehci, *hw_p); - if (type == cpu_to_hc32(ehci, Q_TYPE_QH)) - break; - prev = periodic_next_shadow(ehci, prev, type); - hw_p = shadow_next_periodic(ehci, &here, type); - here = *prev; - } - - /* sorting each branch by period (slow-->fast) - * enables sharing interior tree nodes - */ - while (here.ptr && qh != here.qh) { - if (qh->ps.period > here.qh->ps.period) - break; - prev = &here.qh->qh_next; - hw_p = &here.qh->hw->hw_next; - here = *prev; - } - /* link in this qh, unless some earlier pass did that */ - if (qh != here.qh) { - qh->qh_next = here; - if (here.qh) - qh->hw->hw_next = *hw_p; - wmb (); - prev->qh = qh; - *hw_p = QH_NEXT (ehci, qh->qh_dma); - } - } - qh->qh_state = QH_STATE_LINKED; - qh->xacterrs = 0; - qh->exception = 0; - - /* update per-qh bandwidth for debugfs */ - ehci_to_hcd(ehci)->self.bandwidth_allocated += qh->ps.bw_period - ? ((qh->ps.usecs + qh->ps.c_usecs) / qh->ps.bw_period) - : (qh->ps.usecs * 8); - - list_add(&qh->intr_node, &ehci->intr_qh_list); - - /* maybe enable periodic schedule processing */ - ++ehci->intr_count; - enable_periodic(ehci); -} - -static void qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - unsigned i; - unsigned period; - - /* - * If qh is for a low/full-speed device, simply unlinking it - * could interfere with an ongoing split transaction. To unlink - * it safely would require setting the QH_INACTIVATE bit and - * waiting at least one frame, as described in EHCI 4.12.2.5. - * - * We won't bother with any of this. Instead, we assume that the - * only reason for unlinking an interrupt QH while the current URB - * is still active is to dequeue all the URBs (flush the whole - * endpoint queue). - * - * If rebalancing the periodic schedule is ever implemented, this - * approach will no longer be valid. - */ - - /* high bandwidth, or otherwise part of every microframe */ - period = qh->ps.period ? : 1; - - for (i = qh->ps.phase; i < ehci->periodic_size; i += period) - periodic_unlink (ehci, i, qh); - - /* update per-qh bandwidth for debugfs */ - ehci_to_hcd(ehci)->self.bandwidth_allocated -= qh->ps.bw_period - ? ((qh->ps.usecs + qh->ps.c_usecs) / qh->ps.bw_period) - : (qh->ps.usecs * 8); - - dev_dbg(&qh->ps.udev->dev, - "unlink qh%d-%04x/%p start %d [%d/%d us]\n", - qh->ps.period, - hc32_to_cpup(ehci, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK), - qh, qh->ps.phase, qh->ps.usecs, qh->ps.c_usecs); - - /* qh->qh_next still "live" to HC */ - qh->qh_state = QH_STATE_UNLINK; - qh->qh_next.ptr = NULL; - - if (ehci->qh_scan_next == qh) - ehci->qh_scan_next = list_entry(qh->intr_node.next, - struct ehci_qh, intr_node); - list_del(&qh->intr_node); -} - -static void cancel_unlink_wait_intr(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - if (qh->qh_state != QH_STATE_LINKED || - list_empty(&qh->unlink_node)) - return; - - list_del_init(&qh->unlink_node); - - /* - * TODO: disable the event of EHCI_HRTIMER_START_UNLINK_INTR for - * avoiding unnecessary CPU wakeup - */ -} - -static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - /* If the QH isn't linked then there's nothing we can do. */ - if (qh->qh_state != QH_STATE_LINKED) - return; - - /* if the qh is waiting for unlink, cancel it now */ - cancel_unlink_wait_intr(ehci, qh); - - qh_unlink_periodic (ehci, qh); - - /* Make sure the unlinks are visible before starting the timer */ - wmb(); - - /* - * The EHCI spec doesn't say how long it takes the controller to - * stop accessing an unlinked interrupt QH. The timer delay is - * 9 uframes; presumably that will be long enough. - */ - qh->unlink_cycle = ehci->intr_unlink_cycle; - - /* New entries go at the end of the intr_unlink list */ - list_add_tail(&qh->unlink_node, &ehci->intr_unlink); - - if (ehci->intr_unlinking) - ; /* Avoid recursive calls */ - else if (ehci->rh_state < EHCI_RH_RUNNING) - ehci_handle_intr_unlinks(ehci); - else if (ehci->intr_unlink.next == &qh->unlink_node) { - ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true); - ++ehci->intr_unlink_cycle; - } -} - -/* - * It is common only one intr URB is scheduled on one qh, and - * given complete() is run in tasklet context, introduce a bit - * delay to avoid unlink qh too early. - */ -static void start_unlink_intr_wait(struct ehci_hcd *ehci, - struct ehci_qh *qh) -{ - qh->unlink_cycle = ehci->intr_unlink_wait_cycle; - - /* New entries go at the end of the intr_unlink_wait list */ - list_add_tail(&qh->unlink_node, &ehci->intr_unlink_wait); - - if (ehci->rh_state < EHCI_RH_RUNNING) - ehci_handle_start_intr_unlinks(ehci); - else if (ehci->intr_unlink_wait.next == &qh->unlink_node) { - ehci_enable_event(ehci, EHCI_HRTIMER_START_UNLINK_INTR, true); - ++ehci->intr_unlink_wait_cycle; - } -} - -static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - struct ehci_qh_hw *hw = qh->hw; - int rc; - - qh->qh_state = QH_STATE_IDLE; - hw->hw_next = EHCI_LIST_END(ehci); - - if (!list_empty(&qh->qtd_list)) - qh_completions(ehci, qh); - - /* reschedule QH iff another request is queued */ - if (!list_empty(&qh->qtd_list) && ehci->rh_state == EHCI_RH_RUNNING) { - rc = qh_schedule(ehci, qh); - if (rc == 0) { - qh_refresh(ehci, qh); - qh_link_periodic(ehci, qh); - } - - /* An error here likely indicates handshake failure - * or no space left in the schedule. Neither fault - * should happen often ... - * - * FIXME kill the now-dysfunctional queued urbs - */ - else { - ehci_err(ehci, "can't reschedule qh %p, err %d\n", - qh, rc); - } - } - - /* maybe turn off periodic schedule */ - --ehci->intr_count; - disable_periodic(ehci); -} - -/*-------------------------------------------------------------------------*/ - -static int check_period ( - struct ehci_hcd *ehci, - unsigned frame, - unsigned uframe, - unsigned uperiod, - unsigned usecs -) { - /* complete split running into next frame? - * given FSTN support, we could sometimes check... - */ - if (uframe >= 8) - return 0; - - /* convert "usecs we need" to "max already claimed" */ - usecs = ehci->uframe_periodic_max - usecs; - - for (uframe += frame << 3; uframe < EHCI_BANDWIDTH_SIZE; - uframe += uperiod) { - if (ehci->bandwidth[uframe] > usecs) - return 0; - } - - // success! - return 1; -} - -static int check_intr_schedule ( - struct ehci_hcd *ehci, - unsigned frame, - unsigned uframe, - struct ehci_qh *qh, - unsigned *c_maskp, - struct ehci_tt *tt -) -{ - int retval = -ENOSPC; - u8 mask = 0; - - if (qh->ps.c_usecs && uframe >= 6) /* FSTN territory? */ - goto done; - - if (!check_period(ehci, frame, uframe, qh->ps.bw_uperiod, qh->ps.usecs)) - goto done; - if (!qh->ps.c_usecs) { - retval = 0; - *c_maskp = 0; - goto done; - } - -#ifdef CONFIG_USB_EHCI_TT_NEWSCHED - if (tt_available(ehci, &qh->ps, tt, frame, uframe)) { - unsigned i; - - /* TODO : this may need FSTN for SSPLIT in uframe 5. */ - for (i = uframe+2; i < 8 && i <= uframe+4; i++) - if (!check_period(ehci, frame, i, - qh->ps.bw_uperiod, qh->ps.c_usecs)) - goto done; - else - mask |= 1 << i; - - retval = 0; - - *c_maskp = mask; - } -#else - /* Make sure this tt's buffer is also available for CSPLITs. - * We pessimize a bit; probably the typical full speed case - * doesn't need the second CSPLIT. - * - * NOTE: both SPLIT and CSPLIT could be checked in just - * one smart pass... - */ - mask = 0x03 << (uframe + qh->gap_uf); - *c_maskp = mask; - - mask |= 1 << uframe; - if (tt_no_collision(ehci, qh->ps.bw_period, qh->ps.udev, frame, mask)) { - if (!check_period(ehci, frame, uframe + qh->gap_uf + 1, - qh->ps.bw_uperiod, qh->ps.c_usecs)) - goto done; - if (!check_period(ehci, frame, uframe + qh->gap_uf, - qh->ps.bw_uperiod, qh->ps.c_usecs)) - goto done; - retval = 0; - } -#endif -done: - return retval; -} - -/* "first fit" scheduling policy used the first time through, - * or when the previous schedule slot can't be re-used. - */ -static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh) -{ - int status = 0; - unsigned uframe; - unsigned c_mask; - struct ehci_qh_hw *hw = qh->hw; - struct ehci_tt *tt; - - hw->hw_next = EHCI_LIST_END(ehci); - - /* reuse the previous schedule slots, if we can */ - if (qh->ps.phase != NO_FRAME) { - ehci_dbg(ehci, "reused qh %p schedule\n", qh); - return 0; - } - - uframe = 0; - c_mask = 0; - tt = find_tt(qh->ps.udev); - if (IS_ERR(tt)) { - status = PTR_ERR(tt); - goto done; - } - compute_tt_budget(ehci->tt_budget, tt); - - /* else scan the schedule to find a group of slots such that all - * uframes have enough periodic bandwidth available. - */ - /* "normal" case, uframing flexible except with splits */ - if (qh->ps.bw_period) { - int i; - unsigned frame; - - for (i = qh->ps.bw_period; i > 0; --i) { - frame = ++ehci->random_frame & (qh->ps.bw_period - 1); - for (uframe = 0; uframe < 8; uframe++) { - status = check_intr_schedule(ehci, - frame, uframe, qh, &c_mask, tt); - if (status == 0) - goto got_it; - } - } - - /* qh->ps.bw_period == 0 means every uframe */ - } else { - status = check_intr_schedule(ehci, 0, 0, qh, &c_mask, tt); - } - if (status) - goto done; - - got_it: - qh->ps.phase = (qh->ps.period ? ehci->random_frame & - (qh->ps.period - 1) : 0); - qh->ps.bw_phase = qh->ps.phase & (qh->ps.bw_period - 1); - qh->ps.phase_uf = uframe; - qh->ps.cs_mask = qh->ps.period ? - (c_mask << 8) | (1 << uframe) : - QH_SMASK; - - /* reset S-frame and (maybe) C-frame masks */ - hw->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK)); - hw->hw_info2 |= cpu_to_hc32(ehci, qh->ps.cs_mask); - reserve_release_intr_bandwidth(ehci, qh, 1); - -done: - return status; -} - -static int intr_submit ( - struct ehci_hcd *ehci, - struct urb *urb, - struct list_head *qtd_list, - gfp_t mem_flags -) { - unsigned epnum; - unsigned long flags; - struct ehci_qh *qh; - int status; - struct list_head empty; - - /* get endpoint and transfer/schedule data */ - epnum = urb->ep->desc.bEndpointAddress; - - spin_lock_irqsave (&ehci->lock, flags); - - if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { - status = -ESHUTDOWN; - goto done_not_linked; - } - status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); - if (unlikely(status)) - goto done_not_linked; - - /* get qh and force any scheduling errors */ - INIT_LIST_HEAD (&empty); - qh = qh_append_tds(ehci, urb, &empty, epnum, &urb->ep->hcpriv); - if (qh == NULL) { - status = -ENOMEM; - goto done; - } - if (qh->qh_state == QH_STATE_IDLE) { - if ((status = qh_schedule (ehci, qh)) != 0) - goto done; - } - - /* then queue the urb's tds to the qh */ - qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv); - BUG_ON (qh == NULL); - - /* stuff into the periodic schedule */ - if (qh->qh_state == QH_STATE_IDLE) { - qh_refresh(ehci, qh); - qh_link_periodic(ehci, qh); - } else { - /* cancel unlink wait for the qh */ - cancel_unlink_wait_intr(ehci, qh); - } - - /* ... update usbfs periodic stats */ - ehci_to_hcd(ehci)->self.bandwidth_int_reqs++; - -done: - if (unlikely(status)) - usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); -done_not_linked: - spin_unlock_irqrestore (&ehci->lock, flags); - if (status) - qtd_list_free (ehci, urb, qtd_list); - - return status; -} - -static void scan_intr(struct ehci_hcd *ehci) -{ - struct ehci_qh *qh; - - list_for_each_entry_safe(qh, ehci->qh_scan_next, &ehci->intr_qh_list, - intr_node) { - - /* clean any finished work for this qh */ - if (!list_empty(&qh->qtd_list)) { - int temp; - - /* - * Unlinks could happen here; completion reporting - * drops the lock. That's why ehci->qh_scan_next - * always holds the next qh to scan; if the next qh - * gets unlinked then ehci->qh_scan_next is adjusted - * in qh_unlink_periodic(). - */ - temp = qh_completions(ehci, qh); - if (unlikely(temp)) - start_unlink_intr(ehci, qh); - else if (unlikely(list_empty(&qh->qtd_list) && - qh->qh_state == QH_STATE_LINKED)) - start_unlink_intr_wait(ehci, qh); - } - } -} - -/*-------------------------------------------------------------------------*/ - -/* ehci_iso_stream ops work with both ITD and SITD */ - -static struct ehci_iso_stream * -iso_stream_alloc (gfp_t mem_flags) -{ - struct ehci_iso_stream *stream; - - stream = kzalloc(sizeof *stream, mem_flags); - if (likely (stream != NULL)) { - INIT_LIST_HEAD(&stream->td_list); - INIT_LIST_HEAD(&stream->free_list); - stream->next_uframe = NO_FRAME; - stream->ps.phase = NO_FRAME; - } - return stream; -} - -static void -iso_stream_init ( - struct ehci_hcd *ehci, - struct ehci_iso_stream *stream, - struct urb *urb -) -{ - static const u8 smask_out [] = { 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f }; - - struct usb_device *dev = urb->dev; - u32 buf1; - unsigned epnum, maxp; - int is_input; - unsigned tmp; - - /* - * this might be a "high bandwidth" highspeed endpoint, - * as encoded in the ep descriptor's wMaxPacket field - */ - epnum = usb_pipeendpoint(urb->pipe); - is_input = usb_pipein(urb->pipe) ? USB_DIR_IN : 0; - maxp = usb_endpoint_maxp(&urb->ep->desc); - if (is_input) { - buf1 = (1 << 11); - } else { - buf1 = 0; - } - - /* knows about ITD vs SITD */ - if (dev->speed == USB_SPEED_HIGH) { - unsigned multi = hb_mult(maxp); - - stream->highspeed = 1; - - maxp = max_packet(maxp); - buf1 |= maxp; - maxp *= multi; - - stream->buf0 = cpu_to_hc32(ehci, (epnum << 8) | dev->devnum); - stream->buf1 = cpu_to_hc32(ehci, buf1); - stream->buf2 = cpu_to_hc32(ehci, multi); - - /* usbfs wants to report the average usecs per frame tied up - * when transfers on this endpoint are scheduled ... - */ - stream->ps.usecs = HS_USECS_ISO(maxp); - - /* period for bandwidth allocation */ - tmp = min_t(unsigned, EHCI_BANDWIDTH_SIZE, - 1 << (urb->ep->desc.bInterval - 1)); - - /* Allow urb->interval to override */ - stream->ps.bw_uperiod = min_t(unsigned, tmp, urb->interval); - - stream->uperiod = urb->interval; - stream->ps.period = urb->interval >> 3; - stream->bandwidth = stream->ps.usecs * 8 / - stream->ps.bw_uperiod; - - } else { - u32 addr; - int think_time; - int hs_transfers; - - addr = dev->ttport << 24; - if (!ehci_is_TDI(ehci) - || (dev->tt->hub != - ehci_to_hcd(ehci)->self.root_hub)) - addr |= dev->tt->hub->devnum << 16; - addr |= epnum << 8; - addr |= dev->devnum; - stream->ps.usecs = HS_USECS_ISO(maxp); - think_time = dev->tt ? dev->tt->think_time : 0; - stream->ps.tt_usecs = NS_TO_US(think_time + usb_calc_bus_time( - dev->speed, is_input, 1, maxp)); - hs_transfers = max (1u, (maxp + 187) / 188); - if (is_input) { - u32 tmp; - - addr |= 1 << 31; - stream->ps.c_usecs = stream->ps.usecs; - stream->ps.usecs = HS_USECS_ISO(1); - stream->ps.cs_mask = 1; - - /* c-mask as specified in USB 2.0 11.18.4 3.c */ - tmp = (1 << (hs_transfers + 2)) - 1; - stream->ps.cs_mask |= tmp << (8 + 2); - } else - stream->ps.cs_mask = smask_out[hs_transfers - 1]; - - /* period for bandwidth allocation */ - tmp = min_t(unsigned, EHCI_BANDWIDTH_FRAMES, - 1 << (urb->ep->desc.bInterval - 1)); - - /* Allow urb->interval to override */ - stream->ps.bw_period = min_t(unsigned, tmp, urb->interval); - stream->ps.bw_uperiod = stream->ps.bw_period << 3; - - stream->ps.period = urb->interval; - stream->uperiod = urb->interval << 3; - stream->bandwidth = (stream->ps.usecs + stream->ps.c_usecs) / - stream->ps.bw_period; - - /* stream->splits gets created from cs_mask later */ - stream->address = cpu_to_hc32(ehci, addr); - } - - stream->ps.udev = dev; - stream->ps.ep = urb->ep; - - stream->bEndpointAddress = is_input | epnum; - stream->maxp = maxp; -} - -static struct ehci_iso_stream * -iso_stream_find (struct ehci_hcd *ehci, struct urb *urb) -{ - unsigned epnum; - struct ehci_iso_stream *stream; - struct usb_host_endpoint *ep; - unsigned long flags; - - epnum = usb_pipeendpoint (urb->pipe); - if (usb_pipein(urb->pipe)) - ep = urb->dev->ep_in[epnum]; - else - ep = urb->dev->ep_out[epnum]; - - spin_lock_irqsave (&ehci->lock, flags); - stream = ep->hcpriv; - - if (unlikely (stream == NULL)) { - stream = iso_stream_alloc(GFP_ATOMIC); - if (likely (stream != NULL)) { - ep->hcpriv = stream; - iso_stream_init(ehci, stream, urb); - } - - /* if dev->ep [epnum] is a QH, hw is set */ - } else if (unlikely (stream->hw != NULL)) { - ehci_dbg (ehci, "dev %s ep%d%s, not iso??\n", - urb->dev->devpath, epnum, - usb_pipein(urb->pipe) ? "in" : "out"); - stream = NULL; - } - - spin_unlock_irqrestore (&ehci->lock, flags); - return stream; -} - -/*-------------------------------------------------------------------------*/ - -/* ehci_iso_sched ops can be ITD-only or SITD-only */ - -static struct ehci_iso_sched * -iso_sched_alloc (unsigned packets, gfp_t mem_flags) -{ - struct ehci_iso_sched *iso_sched; - int size = sizeof *iso_sched; - - size += packets * sizeof (struct ehci_iso_packet); - iso_sched = kzalloc(size, mem_flags); - if (likely (iso_sched != NULL)) { - INIT_LIST_HEAD (&iso_sched->td_list); - } - return iso_sched; -} - -static inline void -itd_sched_init( - struct ehci_hcd *ehci, - struct ehci_iso_sched *iso_sched, - struct ehci_iso_stream *stream, - struct urb *urb -) -{ - unsigned i; - dma_addr_t dma = urb->transfer_dma; - - /* how many uframes are needed for these transfers */ - iso_sched->span = urb->number_of_packets * stream->uperiod; - - /* figure out per-uframe itd fields that we'll need later - * when we fit new itds into the schedule. - */ - for (i = 0; i < urb->number_of_packets; i++) { - struct ehci_iso_packet *uframe = &iso_sched->packet [i]; - unsigned length; - dma_addr_t buf; - u32 trans; - - length = urb->iso_frame_desc [i].length; - buf = dma + urb->iso_frame_desc [i].offset; - - trans = EHCI_ISOC_ACTIVE; - trans |= buf & 0x0fff; - if (unlikely (((i + 1) == urb->number_of_packets)) - && !(urb->transfer_flags & URB_NO_INTERRUPT)) - trans |= EHCI_ITD_IOC; - trans |= length << 16; - uframe->transaction = cpu_to_hc32(ehci, trans); - - /* might need to cross a buffer page within a uframe */ - uframe->bufp = (buf & ~(u64)0x0fff); - buf += length; - if (unlikely ((uframe->bufp != (buf & ~(u64)0x0fff)))) - uframe->cross = 1; - } -} - -static void -iso_sched_free ( - struct ehci_iso_stream *stream, - struct ehci_iso_sched *iso_sched -) -{ - if (!iso_sched) - return; - // caller must hold ehci->lock! - list_splice (&iso_sched->td_list, &stream->free_list); - kfree (iso_sched); -} - -static int -itd_urb_transaction ( - struct ehci_iso_stream *stream, - struct ehci_hcd *ehci, - struct urb *urb, - gfp_t mem_flags -) -{ - struct ehci_itd *itd; - dma_addr_t itd_dma; - int i; - unsigned num_itds; - struct ehci_iso_sched *sched; - unsigned long flags; - - sched = iso_sched_alloc (urb->number_of_packets, mem_flags); - if (unlikely (sched == NULL)) - return -ENOMEM; - - itd_sched_init(ehci, sched, stream, urb); - - if (urb->interval < 8) - num_itds = 1 + (sched->span + 7) / 8; - else - num_itds = urb->number_of_packets; - - /* allocate/init ITDs */ - spin_lock_irqsave (&ehci->lock, flags); - for (i = 0; i < num_itds; i++) { - - /* - * Use iTDs from the free list, but not iTDs that may - * still be in use by the hardware. - */ - if (likely(!list_empty(&stream->free_list))) { - itd = list_first_entry(&stream->free_list, - struct ehci_itd, itd_list); - if (itd->frame == ehci->now_frame) - goto alloc_itd; - list_del (&itd->itd_list); - itd_dma = itd->itd_dma; - } else { - alloc_itd: - spin_unlock_irqrestore (&ehci->lock, flags); - itd = dma_pool_alloc (ehci->itd_pool, mem_flags, - &itd_dma); - spin_lock_irqsave (&ehci->lock, flags); - if (!itd) { - iso_sched_free(stream, sched); - spin_unlock_irqrestore(&ehci->lock, flags); - return -ENOMEM; - } - } - - memset (itd, 0, sizeof *itd); - itd->itd_dma = itd_dma; - itd->frame = NO_FRAME; - list_add (&itd->itd_list, &sched->td_list); - } - spin_unlock_irqrestore (&ehci->lock, flags); - - /* temporarily store schedule info in hcpriv */ - urb->hcpriv = sched; - urb->error_count = 0; - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static void reserve_release_iso_bandwidth(struct ehci_hcd *ehci, - struct ehci_iso_stream *stream, int sign) -{ - unsigned uframe; - unsigned i, j; - unsigned s_mask, c_mask, m; - int usecs = stream->ps.usecs; - int c_usecs = stream->ps.c_usecs; - int tt_usecs = stream->ps.tt_usecs; - struct ehci_tt *tt; - - if (stream->ps.phase == NO_FRAME) /* Bandwidth wasn't reserved */ - return; - uframe = stream->ps.bw_phase << 3; - - bandwidth_dbg(ehci, sign, "iso", &stream->ps); - - if (sign < 0) { /* Release bandwidth */ - usecs = -usecs; - c_usecs = -c_usecs; - tt_usecs = -tt_usecs; - } - - if (!stream->splits) { /* High speed */ - for (i = uframe + stream->ps.phase_uf; i < EHCI_BANDWIDTH_SIZE; - i += stream->ps.bw_uperiod) - ehci->bandwidth[i] += usecs; - - } else { /* Full speed */ - s_mask = stream->ps.cs_mask; - c_mask = s_mask >> 8; - - /* NOTE: adjustment needed for frame overflow */ - for (i = uframe; i < EHCI_BANDWIDTH_SIZE; - i += stream->ps.bw_uperiod) { - for ((j = stream->ps.phase_uf, m = 1 << j); j < 8; - (++j, m <<= 1)) { - if (s_mask & m) - ehci->bandwidth[i+j] += usecs; - else if (c_mask & m) - ehci->bandwidth[i+j] += c_usecs; - } - } - - tt = find_tt(stream->ps.udev); - if (sign > 0) - list_add_tail(&stream->ps.ps_list, &tt->ps_list); - else - list_del(&stream->ps.ps_list); - - for (i = uframe >> 3; i < EHCI_BANDWIDTH_FRAMES; - i += stream->ps.bw_period) - tt->bandwidth[i] += tt_usecs; - } -} - -static inline int -itd_slot_ok ( - struct ehci_hcd *ehci, - struct ehci_iso_stream *stream, - unsigned uframe -) -{ - unsigned usecs; - - /* convert "usecs we need" to "max already claimed" */ - usecs = ehci->uframe_periodic_max - stream->ps.usecs; - - for (uframe &= stream->ps.bw_uperiod - 1; uframe < EHCI_BANDWIDTH_SIZE; - uframe += stream->ps.bw_uperiod) { - if (ehci->bandwidth[uframe] > usecs) - return 0; - } - return 1; -} - -static inline int -sitd_slot_ok ( - struct ehci_hcd *ehci, - struct ehci_iso_stream *stream, - unsigned uframe, - struct ehci_iso_sched *sched, - struct ehci_tt *tt -) -{ - unsigned mask, tmp; - unsigned frame, uf; - - mask = stream->ps.cs_mask << (uframe & 7); - - /* for OUT, don't wrap SSPLIT into H-microframe 7 */ - if (((stream->ps.cs_mask & 0xff) << (uframe & 7)) >= (1 << 7)) - return 0; - - /* for IN, don't wrap CSPLIT into the next frame */ - if (mask & ~0xffff) - return 0; - - /* check bandwidth */ - uframe &= stream->ps.bw_uperiod - 1; - frame = uframe >> 3; - -#ifdef CONFIG_USB_EHCI_TT_NEWSCHED - /* The tt's fullspeed bus bandwidth must be available. - * tt_available scheduling guarantees 10+% for control/bulk. - */ - uf = uframe & 7; - if (!tt_available(ehci, &stream->ps, tt, frame, uf)) - return 0; -#else - /* tt must be idle for start(s), any gap, and csplit. - * assume scheduling slop leaves 10+% for control/bulk. - */ - if (!tt_no_collision(ehci, stream->ps.bw_period, - stream->ps.udev, frame, mask)) - return 0; -#endif - - do { - unsigned max_used; - unsigned i; - - /* check starts (OUT uses more than one) */ - uf = uframe; - max_used = ehci->uframe_periodic_max - stream->ps.usecs; - for (tmp = stream->ps.cs_mask & 0xff; tmp; tmp >>= 1, uf++) { - if (ehci->bandwidth[uf] > max_used) - return 0; - } - - /* for IN, check CSPLIT */ - if (stream->ps.c_usecs) { - max_used = ehci->uframe_periodic_max - - stream->ps.c_usecs; - uf = uframe & ~7; - tmp = 1 << (2+8); - for (i = (uframe & 7) + 2; i < 8; (++i, tmp <<= 1)) { - if ((stream->ps.cs_mask & tmp) == 0) - continue; - if (ehci->bandwidth[uf+i] > max_used) - return 0; - } - } - - uframe += stream->ps.bw_uperiod; - } while (uframe < EHCI_BANDWIDTH_SIZE); - - stream->ps.cs_mask <<= uframe & 7; - stream->splits = cpu_to_hc32(ehci, stream->ps.cs_mask); - return 1; -} - -/* - * This scheduler plans almost as far into the future as it has actual - * periodic schedule slots. (Affected by TUNE_FLS, which defaults to - * "as small as possible" to be cache-friendlier.) That limits the size - * transfers you can stream reliably; avoid more than 64 msec per urb. - * Also avoid queue depths of less than ehci's worst irq latency (affected - * by the per-urb URB_NO_INTERRUPT hint, the log2_irq_thresh module parameter, - * and other factors); or more than about 230 msec total (for portability, - * given EHCI_TUNE_FLS and the slop). Or, write a smarter scheduler! - */ - -static int -iso_stream_schedule ( - struct ehci_hcd *ehci, - struct urb *urb, - struct ehci_iso_stream *stream -) -{ - u32 now, base, next, start, period, span, now2; - u32 wrap = 0, skip = 0; - int status = 0; - unsigned mod = ehci->periodic_size << 3; - struct ehci_iso_sched *sched = urb->hcpriv; - bool empty = list_empty(&stream->td_list); - bool new_stream = false; - - period = stream->uperiod; - span = sched->span; - if (!stream->highspeed) - span <<= 3; - - /* Start a new isochronous stream? */ - if (unlikely(empty && !hcd_periodic_completion_in_progress( - ehci_to_hcd(ehci), urb->ep))) { - - /* Schedule the endpoint */ - if (stream->ps.phase == NO_FRAME) { - int done = 0; - struct ehci_tt *tt = find_tt(stream->ps.udev); - - if (IS_ERR(tt)) { - status = PTR_ERR(tt); - goto fail; - } - compute_tt_budget(ehci->tt_budget, tt); - - start = ((-(++ehci->random_frame)) << 3) & (period - 1); - - /* find a uframe slot with enough bandwidth. - * Early uframes are more precious because full-speed - * iso IN transfers can't use late uframes, - * and therefore they should be allocated last. - */ - next = start; - start += period; - do { - start--; - /* check schedule: enough space? */ - if (stream->highspeed) { - if (itd_slot_ok(ehci, stream, start)) - done = 1; - } else { - if ((start % 8) >= 6) - continue; - if (sitd_slot_ok(ehci, stream, start, - sched, tt)) - done = 1; - } - } while (start > next && !done); - - /* no room in the schedule */ - if (!done) { - ehci_dbg(ehci, "iso sched full %p", urb); - status = -ENOSPC; - goto fail; - } - stream->ps.phase = (start >> 3) & - (stream->ps.period - 1); - stream->ps.bw_phase = stream->ps.phase & - (stream->ps.bw_period - 1); - stream->ps.phase_uf = start & 7; - reserve_release_iso_bandwidth(ehci, stream, 1); - } - - /* New stream is already scheduled; use the upcoming slot */ - else { - start = (stream->ps.phase << 3) + stream->ps.phase_uf; - } - - stream->next_uframe = start; - new_stream = true; - } - - now = ehci_read_frame_index(ehci) & (mod - 1); - - /* Take the isochronous scheduling threshold into account */ - if (ehci->i_thresh) - next = now + ehci->i_thresh; /* uframe cache */ - else - next = (now + 2 + 7) & ~0x07; /* full frame cache */ - - /* If needed, initialize last_iso_frame so that this URB will be seen */ - if (ehci->isoc_count == 0) - ehci->last_iso_frame = now >> 3; - - /* - * Use ehci->last_iso_frame as the base. There can't be any - * TDs scheduled for earlier than that. - */ - base = ehci->last_iso_frame << 3; - next = (next - base) & (mod - 1); - start = (stream->next_uframe - base) & (mod - 1); - - if (unlikely(new_stream)) - goto do_ASAP; - - /* - * Typical case: reuse current schedule, stream may still be active. - * Hopefully there are no gaps from the host falling behind - * (irq delays etc). If there are, the behavior depends on - * whether URB_ISO_ASAP is set. - */ - now2 = (now - base) & (mod - 1); - - /* Is the schedule about to wrap around? */ - if (unlikely(!empty && start < period)) { - ehci_dbg(ehci, "request %p would overflow (%u-%u < %u mod %u)\n", - urb, stream->next_uframe, base, period, mod); - status = -EFBIG; - goto fail; - } - - /* Is the next packet scheduled after the base time? */ - if (likely(!empty || start <= now2 + period)) { - - /* URB_ISO_ASAP: make sure that start >= next */ - if (unlikely(start < next && - (urb->transfer_flags & URB_ISO_ASAP))) - goto do_ASAP; - - /* Otherwise use start, if it's not in the past */ - if (likely(start >= now2)) - goto use_start; - - /* Otherwise we got an underrun while the queue was empty */ - } else { - if (urb->transfer_flags & URB_ISO_ASAP) - goto do_ASAP; - wrap = mod; - now2 += mod; - } - - /* How many uframes and packets do we need to skip? */ - skip = (now2 - start + period - 1) & -period; - if (skip >= span) { /* Entirely in the past? */ - ehci_dbg(ehci, "iso underrun %p (%u+%u < %u) [%u]\n", - urb, start + base, span - period, now2 + base, - base); - - /* Try to keep the last TD intact for scanning later */ - skip = span - period; - - /* Will it come before the current scan position? */ - if (empty) { - skip = span; /* Skip the entire URB */ - status = 1; /* and give it back immediately */ - iso_sched_free(stream, sched); - sched = NULL; - } - } - urb->error_count = skip / period; - if (sched) - sched->first_packet = urb->error_count; - goto use_start; - - do_ASAP: - /* Use the first slot after "next" */ - start = next + ((start - next) & (period - 1)); - - use_start: - /* Tried to schedule too far into the future? */ - if (unlikely(start + span - period >= mod + wrap)) { - ehci_dbg(ehci, "request %p would overflow (%u+%u >= %u)\n", - urb, start, span - period, mod + wrap); - status = -EFBIG; - goto fail; - } - - start += base; - stream->next_uframe = (start + skip) & (mod - 1); - - /* report high speed start in uframes; full speed, in frames */ - urb->start_frame = start & (mod - 1); - if (!stream->highspeed) - urb->start_frame >>= 3; - return status; - - fail: - iso_sched_free(stream, sched); - urb->hcpriv = NULL; - return status; -} - -/*-------------------------------------------------------------------------*/ - -static inline void -itd_init(struct ehci_hcd *ehci, struct ehci_iso_stream *stream, - struct ehci_itd *itd) -{ - int i; - - /* it's been recently zeroed */ - itd->hw_next = EHCI_LIST_END(ehci); - itd->hw_bufp [0] = stream->buf0; - itd->hw_bufp [1] = stream->buf1; - itd->hw_bufp [2] = stream->buf2; - - for (i = 0; i < 8; i++) - itd->index[i] = -1; - - /* All other fields are filled when scheduling */ -} - -static inline void -itd_patch( - struct ehci_hcd *ehci, - struct ehci_itd *itd, - struct ehci_iso_sched *iso_sched, - unsigned index, - u16 uframe -) -{ - struct ehci_iso_packet *uf = &iso_sched->packet [index]; - unsigned pg = itd->pg; - - // BUG_ON (pg == 6 && uf->cross); - - uframe &= 0x07; - itd->index [uframe] = index; - - itd->hw_transaction[uframe] = uf->transaction; - itd->hw_transaction[uframe] |= cpu_to_hc32(ehci, pg << 12); - itd->hw_bufp[pg] |= cpu_to_hc32(ehci, uf->bufp & ~(u32)0); - itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(uf->bufp >> 32)); - - /* iso_frame_desc[].offset must be strictly increasing */ - if (unlikely (uf->cross)) { - u64 bufp = uf->bufp + 4096; - - itd->pg = ++pg; - itd->hw_bufp[pg] |= cpu_to_hc32(ehci, bufp & ~(u32)0); - itd->hw_bufp_hi[pg] |= cpu_to_hc32(ehci, (u32)(bufp >> 32)); - } -} - -static inline void -itd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_itd *itd) -{ - union ehci_shadow *prev = &ehci->pshadow[frame]; - __hc32 *hw_p = &ehci->periodic[frame]; - union ehci_shadow here = *prev; - __hc32 type = 0; - - /* skip any iso nodes which might belong to previous microframes */ - while (here.ptr) { - type = Q_NEXT_TYPE(ehci, *hw_p); - if (type == cpu_to_hc32(ehci, Q_TYPE_QH)) - break; - prev = periodic_next_shadow(ehci, prev, type); - hw_p = shadow_next_periodic(ehci, &here, type); - here = *prev; - } - - itd->itd_next = here; - itd->hw_next = *hw_p; - prev->itd = itd; - itd->frame = frame; - wmb (); - *hw_p = cpu_to_hc32(ehci, itd->itd_dma | Q_TYPE_ITD); -} - -/* fit urb's itds into the selected schedule slot; activate as needed */ -static void itd_link_urb( - struct ehci_hcd *ehci, - struct urb *urb, - unsigned mod, - struct ehci_iso_stream *stream -) -{ - int packet; - unsigned next_uframe, uframe, frame; - struct ehci_iso_sched *iso_sched = urb->hcpriv; - struct ehci_itd *itd; - - next_uframe = stream->next_uframe & (mod - 1); - - if (unlikely (list_empty(&stream->td_list))) - ehci_to_hcd(ehci)->self.bandwidth_allocated - += stream->bandwidth; - - if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { - if (ehci->amd_pll_fix == 1) - usb_amd_quirk_pll_disable(); - } - - ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; - - /* fill iTDs uframe by uframe */ - for (packet = iso_sched->first_packet, itd = NULL; - packet < urb->number_of_packets;) { - if (itd == NULL) { - /* ASSERT: we have all necessary itds */ - // BUG_ON (list_empty (&iso_sched->td_list)); - - /* ASSERT: no itds for this endpoint in this uframe */ - - itd = list_entry (iso_sched->td_list.next, - struct ehci_itd, itd_list); - list_move_tail (&itd->itd_list, &stream->td_list); - itd->stream = stream; - itd->urb = urb; - itd_init (ehci, stream, itd); - } - - uframe = next_uframe & 0x07; - frame = next_uframe >> 3; - - itd_patch(ehci, itd, iso_sched, packet, uframe); - - next_uframe += stream->uperiod; - next_uframe &= mod - 1; - packet++; - - /* link completed itds into the schedule */ - if (((next_uframe >> 3) != frame) - || packet == urb->number_of_packets) { - itd_link(ehci, frame & (ehci->periodic_size - 1), itd); - itd = NULL; - } - } - stream->next_uframe = next_uframe; - - /* don't need that schedule data any more */ - iso_sched_free (stream, iso_sched); - urb->hcpriv = stream; - - ++ehci->isoc_count; - enable_periodic(ehci); -} - -#define ISO_ERRS (EHCI_ISOC_BUF_ERR | EHCI_ISOC_BABBLE | EHCI_ISOC_XACTERR) - -/* Process and recycle a completed ITD. Return true iff its urb completed, - * and hence its completion callback probably added things to the hardware - * schedule. - * - * Note that we carefully avoid recycling this descriptor until after any - * completion callback runs, so that it won't be reused quickly. That is, - * assuming (a) no more than two urbs per frame on this endpoint, and also - * (b) only this endpoint's completions submit URBs. It seems some silicon - * corrupts things if you reuse completed descriptors very quickly... - */ -static bool itd_complete(struct ehci_hcd *ehci, struct ehci_itd *itd) -{ - struct urb *urb = itd->urb; - struct usb_iso_packet_descriptor *desc; - u32 t; - unsigned uframe; - int urb_index = -1; - struct ehci_iso_stream *stream = itd->stream; - struct usb_device *dev; - bool retval = false; - - /* for each uframe with a packet */ - for (uframe = 0; uframe < 8; uframe++) { - if (likely (itd->index[uframe] == -1)) - continue; - urb_index = itd->index[uframe]; - desc = &urb->iso_frame_desc [urb_index]; - - t = hc32_to_cpup(ehci, &itd->hw_transaction [uframe]); - itd->hw_transaction [uframe] = 0; - - /* report transfer status */ - if (unlikely (t & ISO_ERRS)) { - urb->error_count++; - if (t & EHCI_ISOC_BUF_ERR) - desc->status = usb_pipein (urb->pipe) - ? -ENOSR /* hc couldn't read */ - : -ECOMM; /* hc couldn't write */ - else if (t & EHCI_ISOC_BABBLE) - desc->status = -EOVERFLOW; - else /* (t & EHCI_ISOC_XACTERR) */ - desc->status = -EPROTO; - - /* HC need not update length with this error */ - if (!(t & EHCI_ISOC_BABBLE)) { - desc->actual_length = EHCI_ITD_LENGTH(t); - urb->actual_length += desc->actual_length; - } - } else if (likely ((t & EHCI_ISOC_ACTIVE) == 0)) { - desc->status = 0; - desc->actual_length = EHCI_ITD_LENGTH(t); - urb->actual_length += desc->actual_length; - } else { - /* URB was too late */ - urb->error_count++; - } - } - - /* handle completion now? */ - if (likely ((urb_index + 1) != urb->number_of_packets)) - goto done; - - /* ASSERT: it's really the last itd for this urb - list_for_each_entry (itd, &stream->td_list, itd_list) - BUG_ON (itd->urb == urb); - */ - - /* give urb back to the driver; completion often (re)submits */ - dev = urb->dev; - ehci_urb_done(ehci, urb, 0); - retval = true; - urb = NULL; - - --ehci->isoc_count; - disable_periodic(ehci); - - ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { - if (ehci->amd_pll_fix == 1) - usb_amd_quirk_pll_enable(); - } - - if (unlikely(list_is_singular(&stream->td_list))) - ehci_to_hcd(ehci)->self.bandwidth_allocated - -= stream->bandwidth; - -done: - itd->urb = NULL; - - /* Add to the end of the free list for later reuse */ - list_move_tail(&itd->itd_list, &stream->free_list); - - /* Recycle the iTDs when the pipeline is empty (ep no longer in use) */ - if (list_empty(&stream->td_list)) { - list_splice_tail_init(&stream->free_list, - &ehci->cached_itd_list); - start_free_itds(ehci); - } - - return retval; -} - -/*-------------------------------------------------------------------------*/ - -static int itd_submit (struct ehci_hcd *ehci, struct urb *urb, - gfp_t mem_flags) -{ - int status = -EINVAL; - unsigned long flags; - struct ehci_iso_stream *stream; - - /* Get iso_stream head */ - stream = iso_stream_find (ehci, urb); - if (unlikely (stream == NULL)) { - ehci_dbg (ehci, "can't get iso stream\n"); - return -ENOMEM; - } - if (unlikely(urb->interval != stream->uperiod)) { - ehci_dbg (ehci, "can't change iso interval %d --> %d\n", - stream->uperiod, urb->interval); - goto done; - } - -#ifdef EHCI_URB_TRACE - ehci_dbg (ehci, - "%s %s urb %p ep%d%s len %d, %d pkts %d uframes [%p]\n", - __func__, urb->dev->devpath, urb, - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", - urb->transfer_buffer_length, - urb->number_of_packets, urb->interval, - stream); -#endif - - /* allocate ITDs w/o locking anything */ - status = itd_urb_transaction (stream, ehci, urb, mem_flags); - if (unlikely (status < 0)) { - ehci_dbg (ehci, "can't init itds\n"); - goto done; - } - - /* schedule ... need to lock */ - spin_lock_irqsave (&ehci->lock, flags); - if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { - status = -ESHUTDOWN; - goto done_not_linked; - } - status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); - if (unlikely(status)) - goto done_not_linked; - status = iso_stream_schedule(ehci, urb, stream); - if (likely(status == 0)) { - itd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); - } else if (status > 0) { - status = 0; - ehci_urb_done(ehci, urb, 0); - } else { - usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); - } - done_not_linked: - spin_unlock_irqrestore (&ehci->lock, flags); - done: - return status; -} - -/*-------------------------------------------------------------------------*/ - -/* - * "Split ISO TDs" ... used for USB 1.1 devices going through the - * TTs in USB 2.0 hubs. These need microframe scheduling. - */ - -static inline void -sitd_sched_init( - struct ehci_hcd *ehci, - struct ehci_iso_sched *iso_sched, - struct ehci_iso_stream *stream, - struct urb *urb -) -{ - unsigned i; - dma_addr_t dma = urb->transfer_dma; - - /* how many frames are needed for these transfers */ - iso_sched->span = urb->number_of_packets * stream->ps.period; - - /* figure out per-frame sitd fields that we'll need later - * when we fit new sitds into the schedule. - */ - for (i = 0; i < urb->number_of_packets; i++) { - struct ehci_iso_packet *packet = &iso_sched->packet [i]; - unsigned length; - dma_addr_t buf; - u32 trans; - - length = urb->iso_frame_desc [i].length & 0x03ff; - buf = dma + urb->iso_frame_desc [i].offset; - - trans = SITD_STS_ACTIVE; - if (((i + 1) == urb->number_of_packets) - && !(urb->transfer_flags & URB_NO_INTERRUPT)) - trans |= SITD_IOC; - trans |= length << 16; - packet->transaction = cpu_to_hc32(ehci, trans); - - /* might need to cross a buffer page within a td */ - packet->bufp = buf; - packet->buf1 = (buf + length) & ~0x0fff; - if (packet->buf1 != (buf & ~(u64)0x0fff)) - packet->cross = 1; - - /* OUT uses multiple start-splits */ - if (stream->bEndpointAddress & USB_DIR_IN) - continue; - length = (length + 187) / 188; - if (length > 1) /* BEGIN vs ALL */ - length |= 1 << 3; - packet->buf1 |= length; - } -} - -static int -sitd_urb_transaction ( - struct ehci_iso_stream *stream, - struct ehci_hcd *ehci, - struct urb *urb, - gfp_t mem_flags -) -{ - struct ehci_sitd *sitd; - dma_addr_t sitd_dma; - int i; - struct ehci_iso_sched *iso_sched; - unsigned long flags; - - iso_sched = iso_sched_alloc (urb->number_of_packets, mem_flags); - if (iso_sched == NULL) - return -ENOMEM; - - sitd_sched_init(ehci, iso_sched, stream, urb); - - /* allocate/init sITDs */ - spin_lock_irqsave (&ehci->lock, flags); - for (i = 0; i < urb->number_of_packets; i++) { - - /* NOTE: for now, we don't try to handle wraparound cases - * for IN (using sitd->hw_backpointer, like a FSTN), which - * means we never need two sitds for full speed packets. - */ - - /* - * Use siTDs from the free list, but not siTDs that may - * still be in use by the hardware. - */ - if (likely(!list_empty(&stream->free_list))) { - sitd = list_first_entry(&stream->free_list, - struct ehci_sitd, sitd_list); - if (sitd->frame == ehci->now_frame) - goto alloc_sitd; - list_del (&sitd->sitd_list); - sitd_dma = sitd->sitd_dma; - } else { - alloc_sitd: - spin_unlock_irqrestore (&ehci->lock, flags); - sitd = dma_pool_alloc (ehci->sitd_pool, mem_flags, - &sitd_dma); - spin_lock_irqsave (&ehci->lock, flags); - if (!sitd) { - iso_sched_free(stream, iso_sched); - spin_unlock_irqrestore(&ehci->lock, flags); - return -ENOMEM; - } - } - - memset (sitd, 0, sizeof *sitd); - sitd->sitd_dma = sitd_dma; - sitd->frame = NO_FRAME; - list_add (&sitd->sitd_list, &iso_sched->td_list); - } - - /* temporarily store schedule info in hcpriv */ - urb->hcpriv = iso_sched; - urb->error_count = 0; - - spin_unlock_irqrestore (&ehci->lock, flags); - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static inline void -sitd_patch( - struct ehci_hcd *ehci, - struct ehci_iso_stream *stream, - struct ehci_sitd *sitd, - struct ehci_iso_sched *iso_sched, - unsigned index -) -{ - struct ehci_iso_packet *uf = &iso_sched->packet [index]; - u64 bufp = uf->bufp; - - sitd->hw_next = EHCI_LIST_END(ehci); - sitd->hw_fullspeed_ep = stream->address; - sitd->hw_uframe = stream->splits; - sitd->hw_results = uf->transaction; - sitd->hw_backpointer = EHCI_LIST_END(ehci); - - bufp = uf->bufp; - sitd->hw_buf[0] = cpu_to_hc32(ehci, bufp); - sitd->hw_buf_hi[0] = cpu_to_hc32(ehci, bufp >> 32); - - sitd->hw_buf[1] = cpu_to_hc32(ehci, uf->buf1); - if (uf->cross) - bufp += 4096; - sitd->hw_buf_hi[1] = cpu_to_hc32(ehci, bufp >> 32); - sitd->index = index; -} - -static inline void -sitd_link (struct ehci_hcd *ehci, unsigned frame, struct ehci_sitd *sitd) -{ - /* note: sitd ordering could matter (CSPLIT then SSPLIT) */ - sitd->sitd_next = ehci->pshadow [frame]; - sitd->hw_next = ehci->periodic [frame]; - ehci->pshadow [frame].sitd = sitd; - sitd->frame = frame; - wmb (); - ehci->periodic[frame] = cpu_to_hc32(ehci, sitd->sitd_dma | Q_TYPE_SITD); -} - -/* fit urb's sitds into the selected schedule slot; activate as needed */ -static void sitd_link_urb( - struct ehci_hcd *ehci, - struct urb *urb, - unsigned mod, - struct ehci_iso_stream *stream -) -{ - int packet; - unsigned next_uframe; - struct ehci_iso_sched *sched = urb->hcpriv; - struct ehci_sitd *sitd; - - next_uframe = stream->next_uframe; - - if (list_empty(&stream->td_list)) - /* usbfs ignores TT bandwidth */ - ehci_to_hcd(ehci)->self.bandwidth_allocated - += stream->bandwidth; - - if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { - if (ehci->amd_pll_fix == 1) - usb_amd_quirk_pll_disable(); - } - - ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs++; - - /* fill sITDs frame by frame */ - for (packet = sched->first_packet, sitd = NULL; - packet < urb->number_of_packets; - packet++) { - - /* ASSERT: we have all necessary sitds */ - BUG_ON (list_empty (&sched->td_list)); - - /* ASSERT: no itds for this endpoint in this frame */ - - sitd = list_entry (sched->td_list.next, - struct ehci_sitd, sitd_list); - list_move_tail (&sitd->sitd_list, &stream->td_list); - sitd->stream = stream; - sitd->urb = urb; - - sitd_patch(ehci, stream, sitd, sched, packet); - sitd_link(ehci, (next_uframe >> 3) & (ehci->periodic_size - 1), - sitd); - - next_uframe += stream->uperiod; - } - stream->next_uframe = next_uframe & (mod - 1); - - /* don't need that schedule data any more */ - iso_sched_free (stream, sched); - urb->hcpriv = stream; - - ++ehci->isoc_count; - enable_periodic(ehci); -} - -/*-------------------------------------------------------------------------*/ - -#define SITD_ERRS (SITD_STS_ERR | SITD_STS_DBE | SITD_STS_BABBLE \ - | SITD_STS_XACT | SITD_STS_MMF) - -/* Process and recycle a completed SITD. Return true iff its urb completed, - * and hence its completion callback probably added things to the hardware - * schedule. - * - * Note that we carefully avoid recycling this descriptor until after any - * completion callback runs, so that it won't be reused quickly. That is, - * assuming (a) no more than two urbs per frame on this endpoint, and also - * (b) only this endpoint's completions submit URBs. It seems some silicon - * corrupts things if you reuse completed descriptors very quickly... - */ -static bool sitd_complete(struct ehci_hcd *ehci, struct ehci_sitd *sitd) -{ - struct urb *urb = sitd->urb; - struct usb_iso_packet_descriptor *desc; - u32 t; - int urb_index = -1; - struct ehci_iso_stream *stream = sitd->stream; - struct usb_device *dev; - bool retval = false; - - urb_index = sitd->index; - desc = &urb->iso_frame_desc [urb_index]; - t = hc32_to_cpup(ehci, &sitd->hw_results); - - /* report transfer status */ - if (unlikely(t & SITD_ERRS)) { - urb->error_count++; - if (t & SITD_STS_DBE) - desc->status = usb_pipein (urb->pipe) - ? -ENOSR /* hc couldn't read */ - : -ECOMM; /* hc couldn't write */ - else if (t & SITD_STS_BABBLE) - desc->status = -EOVERFLOW; - else /* XACT, MMF, etc */ - desc->status = -EPROTO; - } else if (unlikely(t & SITD_STS_ACTIVE)) { - /* URB was too late */ - urb->error_count++; - } else { - desc->status = 0; - desc->actual_length = desc->length - SITD_LENGTH(t); - urb->actual_length += desc->actual_length; - } - - /* handle completion now? */ - if ((urb_index + 1) != urb->number_of_packets) - goto done; - - /* ASSERT: it's really the last sitd for this urb - list_for_each_entry (sitd, &stream->td_list, sitd_list) - BUG_ON (sitd->urb == urb); - */ - - /* give urb back to the driver; completion often (re)submits */ - dev = urb->dev; - ehci_urb_done(ehci, urb, 0); - retval = true; - urb = NULL; - - --ehci->isoc_count; - disable_periodic(ehci); - - ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs--; - if (ehci_to_hcd(ehci)->self.bandwidth_isoc_reqs == 0) { - if (ehci->amd_pll_fix == 1) - usb_amd_quirk_pll_enable(); - } - - if (list_is_singular(&stream->td_list)) - ehci_to_hcd(ehci)->self.bandwidth_allocated - -= stream->bandwidth; - -done: - sitd->urb = NULL; - - /* Add to the end of the free list for later reuse */ - list_move_tail(&sitd->sitd_list, &stream->free_list); - - /* Recycle the siTDs when the pipeline is empty (ep no longer in use) */ - if (list_empty(&stream->td_list)) { - list_splice_tail_init(&stream->free_list, - &ehci->cached_sitd_list); - start_free_itds(ehci); - } - - return retval; -} - - -static int sitd_submit (struct ehci_hcd *ehci, struct urb *urb, - gfp_t mem_flags) -{ - int status = -EINVAL; - unsigned long flags; - struct ehci_iso_stream *stream; - - /* Get iso_stream head */ - stream = iso_stream_find (ehci, urb); - if (stream == NULL) { - ehci_dbg (ehci, "can't get iso stream\n"); - return -ENOMEM; - } - if (urb->interval != stream->ps.period) { - ehci_dbg (ehci, "can't change iso interval %d --> %d\n", - stream->ps.period, urb->interval); - goto done; - } - -#ifdef EHCI_URB_TRACE - ehci_dbg (ehci, - "submit %p dev%s ep%d%s-iso len %d\n", - urb, urb->dev->devpath, - usb_pipeendpoint (urb->pipe), - usb_pipein (urb->pipe) ? "in" : "out", - urb->transfer_buffer_length); -#endif - - /* allocate SITDs */ - status = sitd_urb_transaction (stream, ehci, urb, mem_flags); - if (status < 0) { - ehci_dbg (ehci, "can't init sitds\n"); - goto done; - } - - /* schedule ... need to lock */ - spin_lock_irqsave (&ehci->lock, flags); - if (unlikely(!HCD_HW_ACCESSIBLE(ehci_to_hcd(ehci)))) { - status = -ESHUTDOWN; - goto done_not_linked; - } - status = usb_hcd_link_urb_to_ep(ehci_to_hcd(ehci), urb); - if (unlikely(status)) - goto done_not_linked; - status = iso_stream_schedule(ehci, urb, stream); - if (likely(status == 0)) { - sitd_link_urb (ehci, urb, ehci->periodic_size << 3, stream); - } else if (status > 0) { - status = 0; - ehci_urb_done(ehci, urb, 0); - } else { - usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb); - } - done_not_linked: - spin_unlock_irqrestore (&ehci->lock, flags); - done: - return status; -} - -/*-------------------------------------------------------------------------*/ - -static void scan_isoc(struct ehci_hcd *ehci) -{ - unsigned uf, now_frame, frame; - unsigned fmask = ehci->periodic_size - 1; - bool modified, live; - - /* - * When running, scan from last scan point up to "now" - * else clean up by scanning everything that's left. - * Touches as few pages as possible: cache-friendly. - */ - if (ehci->rh_state >= EHCI_RH_RUNNING) { - uf = ehci_read_frame_index(ehci); - now_frame = (uf >> 3) & fmask; - live = true; - } else { - now_frame = (ehci->last_iso_frame - 1) & fmask; - live = false; - } - ehci->now_frame = now_frame; - - frame = ehci->last_iso_frame; - for (;;) { - union ehci_shadow q, *q_p; - __hc32 type, *hw_p; - -restart: - /* scan each element in frame's queue for completions */ - q_p = &ehci->pshadow [frame]; - hw_p = &ehci->periodic [frame]; - q.ptr = q_p->ptr; - type = Q_NEXT_TYPE(ehci, *hw_p); - modified = false; - - while (q.ptr != NULL) { - switch (hc32_to_cpu(ehci, type)) { - case Q_TYPE_ITD: - /* If this ITD is still active, leave it for - * later processing ... check the next entry. - * No need to check for activity unless the - * frame is current. - */ - if (frame == now_frame && live) { - rmb(); - for (uf = 0; uf < 8; uf++) { - if (q.itd->hw_transaction[uf] & - ITD_ACTIVE(ehci)) - break; - } - if (uf < 8) { - q_p = &q.itd->itd_next; - hw_p = &q.itd->hw_next; - type = Q_NEXT_TYPE(ehci, - q.itd->hw_next); - q = *q_p; - break; - } - } - - /* Take finished ITDs out of the schedule - * and process them: recycle, maybe report - * URB completion. HC won't cache the - * pointer for much longer, if at all. - */ - *q_p = q.itd->itd_next; - if (!ehci->use_dummy_qh || - q.itd->hw_next != EHCI_LIST_END(ehci)) - *hw_p = q.itd->hw_next; - else - *hw_p = cpu_to_hc32(ehci, - ehci->dummy->qh_dma); - type = Q_NEXT_TYPE(ehci, q.itd->hw_next); - wmb(); - modified = itd_complete (ehci, q.itd); - q = *q_p; - break; - case Q_TYPE_SITD: - /* If this SITD is still active, leave it for - * later processing ... check the next entry. - * No need to check for activity unless the - * frame is current. - */ - if (((frame == now_frame) || - (((frame + 1) & fmask) == now_frame)) - && live - && (q.sitd->hw_results & - SITD_ACTIVE(ehci))) { - - q_p = &q.sitd->sitd_next; - hw_p = &q.sitd->hw_next; - type = Q_NEXT_TYPE(ehci, - q.sitd->hw_next); - q = *q_p; - break; - } - - /* Take finished SITDs out of the schedule - * and process them: recycle, maybe report - * URB completion. - */ - *q_p = q.sitd->sitd_next; - if (!ehci->use_dummy_qh || - q.sitd->hw_next != EHCI_LIST_END(ehci)) - *hw_p = q.sitd->hw_next; - else - *hw_p = cpu_to_hc32(ehci, - ehci->dummy->qh_dma); - type = Q_NEXT_TYPE(ehci, q.sitd->hw_next); - wmb(); - modified = sitd_complete (ehci, q.sitd); - q = *q_p; - break; - default: - ehci_dbg(ehci, "corrupt type %d frame %d shadow %p\n", - type, frame, q.ptr); - // BUG (); - /* FALL THROUGH */ - case Q_TYPE_QH: - case Q_TYPE_FSTN: - /* End of the iTDs and siTDs */ - q.ptr = NULL; - break; - } - - /* assume completion callbacks modify the queue */ - if (unlikely(modified && ehci->isoc_count > 0)) - goto restart; - } - - /* Stop when we have reached the current frame */ - if (frame == now_frame) - break; - - /* The last frame may still have active siTDs */ - ehci->last_iso_frame = frame; - frame = (frame + 1) & fmask; - } -} diff --git a/addons/ehci-pci/src/4.4.180/ehci-sysfs.c b/addons/ehci-pci/src/4.4.180/ehci-sysfs.c deleted file mode 100644 index 5216f2b0..00000000 --- a/addons/ehci-pci/src/4.4.180/ehci-sysfs.c +++ /dev/null @@ -1,187 +0,0 @@ -/* - * Copyright (C) 2007 by Alan Stern - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* this file is part of ehci-hcd.c */ - - -/* Display the ports dedicated to the companion controller */ -static ssize_t show_companion(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ehci_hcd *ehci; - int nports, index, n; - int count = PAGE_SIZE; - char *ptr = buf; - - ehci = hcd_to_ehci(dev_get_drvdata(dev)); - nports = HCS_N_PORTS(ehci->hcs_params); - - for (index = 0; index < nports; ++index) { - if (test_bit(index, &ehci->companion_ports)) { - n = scnprintf(ptr, count, "%d\n", index + 1); - ptr += n; - count -= n; - } - } - return ptr - buf; -} - -/* - * Dedicate or undedicate a port to the companion controller. - * Syntax is "[-]portnum", where a leading '-' sign means - * return control of the port to the EHCI controller. - */ -static ssize_t store_companion(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ehci_hcd *ehci; - int portnum, new_owner; - - ehci = hcd_to_ehci(dev_get_drvdata(dev)); - new_owner = PORT_OWNER; /* Owned by companion */ - if (sscanf(buf, "%d", &portnum) != 1) - return -EINVAL; - if (portnum < 0) { - portnum = - portnum; - new_owner = 0; /* Owned by EHCI */ - } - if (portnum <= 0 || portnum > HCS_N_PORTS(ehci->hcs_params)) - return -ENOENT; - portnum--; - if (new_owner) - set_bit(portnum, &ehci->companion_ports); - else - clear_bit(portnum, &ehci->companion_ports); - set_owner(ehci, portnum, new_owner); - return count; -} -static DEVICE_ATTR(companion, 0644, show_companion, store_companion); - - -/* - * Display / Set uframe_periodic_max - */ -static ssize_t show_uframe_periodic_max(struct device *dev, - struct device_attribute *attr, - char *buf) -{ - struct ehci_hcd *ehci; - int n; - - ehci = hcd_to_ehci(dev_get_drvdata(dev)); - n = scnprintf(buf, PAGE_SIZE, "%d\n", ehci->uframe_periodic_max); - return n; -} - - -static ssize_t store_uframe_periodic_max(struct device *dev, - struct device_attribute *attr, - const char *buf, size_t count) -{ - struct ehci_hcd *ehci; - unsigned uframe_periodic_max; - unsigned uframe; - unsigned long flags; - ssize_t ret; - - ehci = hcd_to_ehci(dev_get_drvdata(dev)); - if (kstrtouint(buf, 0, &uframe_periodic_max) < 0) - return -EINVAL; - - if (uframe_periodic_max < 100 || uframe_periodic_max >= 125) { - ehci_info(ehci, "rejecting invalid request for " - "uframe_periodic_max=%u\n", uframe_periodic_max); - return -EINVAL; - } - - ret = -EINVAL; - - /* - * lock, so that our checking does not race with possible periodic - * bandwidth allocation through submitting new urbs. - */ - spin_lock_irqsave (&ehci->lock, flags); - - /* - * for request to decrease max periodic bandwidth, we have to check - * to see whether the decrease is possible. - */ - if (uframe_periodic_max < ehci->uframe_periodic_max) { - u8 allocated_max = 0; - - for (uframe = 0; uframe < EHCI_BANDWIDTH_SIZE; ++uframe) - allocated_max = max(allocated_max, - ehci->bandwidth[uframe]); - - if (allocated_max > uframe_periodic_max) { - ehci_info(ehci, - "cannot decrease uframe_periodic_max because " - "periodic bandwidth is already allocated " - "(%u > %u)\n", - allocated_max, uframe_periodic_max); - goto out_unlock; - } - } - - /* increasing is always ok */ - - ehci_info(ehci, "setting max periodic bandwidth to %u%% " - "(== %u usec/uframe)\n", - 100*uframe_periodic_max/125, uframe_periodic_max); - - if (uframe_periodic_max != 100) - ehci_warn(ehci, "max periodic bandwidth set is non-standard\n"); - - ehci->uframe_periodic_max = uframe_periodic_max; - ret = count; - -out_unlock: - spin_unlock_irqrestore (&ehci->lock, flags); - return ret; -} -static DEVICE_ATTR(uframe_periodic_max, 0644, show_uframe_periodic_max, store_uframe_periodic_max); - - -static inline int create_sysfs_files(struct ehci_hcd *ehci) -{ - struct device *controller = ehci_to_hcd(ehci)->self.controller; - int i = 0; - - /* with integrated TT there is no companion! */ - if (!ehci_is_TDI(ehci)) - i = device_create_file(controller, &dev_attr_companion); - if (i) - goto out; - - i = device_create_file(controller, &dev_attr_uframe_periodic_max); -out: - return i; -} - -static inline void remove_sysfs_files(struct ehci_hcd *ehci) -{ - struct device *controller = ehci_to_hcd(ehci)->self.controller; - - /* with integrated TT there is no companion! */ - if (!ehci_is_TDI(ehci)) - device_remove_file(controller, &dev_attr_companion); - - device_remove_file(controller, &dev_attr_uframe_periodic_max); -} diff --git a/addons/ehci-pci/src/4.4.180/ehci-timer.c b/addons/ehci-pci/src/4.4.180/ehci-timer.c deleted file mode 100644 index 424ac5d8..00000000 --- a/addons/ehci-pci/src/4.4.180/ehci-timer.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * Copyright (C) 2012 by Alan Stern - * - * 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. - */ - -/* This file is part of ehci-hcd.c */ - -/*-------------------------------------------------------------------------*/ - -/* Set a bit in the USBCMD register */ -static void ehci_set_command_bit(struct ehci_hcd *ehci, u32 bit) -{ - ehci->command |= bit; - ehci_writel(ehci, ehci->command, &ehci->regs->command); - - /* unblock posted write */ - ehci_readl(ehci, &ehci->regs->command); -} - -/* Clear a bit in the USBCMD register */ -static void ehci_clear_command_bit(struct ehci_hcd *ehci, u32 bit) -{ - ehci->command &= ~bit; - ehci_writel(ehci, ehci->command, &ehci->regs->command); - - /* unblock posted write */ - ehci_readl(ehci, &ehci->regs->command); -} - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI timer support... Now using hrtimers. - * - * Lots of different events are triggered from ehci->hrtimer. Whenever - * the timer routine runs, it checks each possible event; events that are - * currently enabled and whose expiration time has passed get handled. - * The set of enabled events is stored as a collection of bitflags in - * ehci->enabled_hrtimer_events, and they are numbered in order of - * increasing delay values (ranging between 1 ms and 100 ms). - * - * Rather than implementing a sorted list or tree of all pending events, - * we keep track only of the lowest-numbered pending event, in - * ehci->next_hrtimer_event. Whenever ehci->hrtimer gets restarted, its - * expiration time is set to the timeout value for this event. - * - * As a result, events might not get handled right away; the actual delay - * could be anywhere up to twice the requested delay. This doesn't - * matter, because none of the events are especially time-critical. The - * ones that matter most all have a delay of 1 ms, so they will be - * handled after 2 ms at most, which is okay. In addition to this, we - * allow for an expiration range of 1 ms. - */ - -/* - * Delay lengths for the hrtimer event types. - * Keep this list sorted by delay length, in the same order as - * the event types indexed by enum ehci_hrtimer_event in ehci.h. - */ -static unsigned event_delays_ns[] = { - 1 * NSEC_PER_MSEC, /* EHCI_HRTIMER_POLL_ASS */ - 1 * NSEC_PER_MSEC, /* EHCI_HRTIMER_POLL_PSS */ - 1 * NSEC_PER_MSEC, /* EHCI_HRTIMER_POLL_DEAD */ - 1125 * NSEC_PER_USEC, /* EHCI_HRTIMER_UNLINK_INTR */ - 2 * NSEC_PER_MSEC, /* EHCI_HRTIMER_FREE_ITDS */ - 5 * NSEC_PER_MSEC, /* EHCI_HRTIMER_START_UNLINK_INTR */ - 6 * NSEC_PER_MSEC, /* EHCI_HRTIMER_ASYNC_UNLINKS */ - 10 * NSEC_PER_MSEC, /* EHCI_HRTIMER_IAA_WATCHDOG */ - 10 * NSEC_PER_MSEC, /* EHCI_HRTIMER_DISABLE_PERIODIC */ - 15 * NSEC_PER_MSEC, /* EHCI_HRTIMER_DISABLE_ASYNC */ - 100 * NSEC_PER_MSEC, /* EHCI_HRTIMER_IO_WATCHDOG */ -}; - -/* Enable a pending hrtimer event */ -static void ehci_enable_event(struct ehci_hcd *ehci, unsigned event, - bool resched) -{ - ktime_t *timeout = &ehci->hr_timeouts[event]; - - if (resched) - *timeout = ktime_add(ktime_get(), - ktime_set(0, event_delays_ns[event])); - ehci->enabled_hrtimer_events |= (1 << event); - - /* Track only the lowest-numbered pending event */ - if (event < ehci->next_hrtimer_event) { - ehci->next_hrtimer_event = event; - hrtimer_start_range_ns(&ehci->hrtimer, *timeout, - NSEC_PER_MSEC, HRTIMER_MODE_ABS); - } -} - - -/* Poll the STS_ASS status bit; see when it agrees with CMD_ASE */ -static void ehci_poll_ASS(struct ehci_hcd *ehci) -{ - unsigned actual, want; - - /* Don't enable anything if the controller isn't running (e.g., died) */ - if (ehci->rh_state != EHCI_RH_RUNNING) - return; - - want = (ehci->command & CMD_ASE) ? STS_ASS : 0; - actual = ehci_readl(ehci, &ehci->regs->status) & STS_ASS; - - if (want != actual) { - - /* Poll again later, but give up after about 2-4 ms */ - if (ehci->ASS_poll_count++ < 2) { - ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); - return; - } - ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n", - want, actual); - } - ehci->ASS_poll_count = 0; - - /* The status is up-to-date; restart or stop the schedule as needed */ - if (want == 0) { /* Stopped */ - if (ehci->async_count > 0) - ehci_set_command_bit(ehci, CMD_ASE); - - } else { /* Running */ - if (ehci->async_count == 0) { - - /* Turn off the schedule after a while */ - ehci_enable_event(ehci, EHCI_HRTIMER_DISABLE_ASYNC, - true); - } - } -} - -/* Turn off the async schedule after a brief delay */ -static void ehci_disable_ASE(struct ehci_hcd *ehci) -{ - ehci_clear_command_bit(ehci, CMD_ASE); -} - - -/* Poll the STS_PSS status bit; see when it agrees with CMD_PSE */ -static void ehci_poll_PSS(struct ehci_hcd *ehci) -{ - unsigned actual, want; - - /* Don't do anything if the controller isn't running (e.g., died) */ - if (ehci->rh_state != EHCI_RH_RUNNING) - return; - - want = (ehci->command & CMD_PSE) ? STS_PSS : 0; - actual = ehci_readl(ehci, &ehci->regs->status) & STS_PSS; - - if (want != actual) { - - /* Poll again later, but give up after about 2-4 ms */ - if (ehci->PSS_poll_count++ < 2) { - ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); - return; - } - ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n", - want, actual); - } - ehci->PSS_poll_count = 0; - - /* The status is up-to-date; restart or stop the schedule as needed */ - if (want == 0) { /* Stopped */ - if (ehci->periodic_count > 0) - ehci_set_command_bit(ehci, CMD_PSE); - - } else { /* Running */ - if (ehci->periodic_count == 0) { - - /* Turn off the schedule after a while */ - ehci_enable_event(ehci, EHCI_HRTIMER_DISABLE_PERIODIC, - true); - } - } -} - -/* Turn off the periodic schedule after a brief delay */ -static void ehci_disable_PSE(struct ehci_hcd *ehci) -{ - ehci_clear_command_bit(ehci, CMD_PSE); -} - - -/* Poll the STS_HALT status bit; see when a dead controller stops */ -static void ehci_handle_controller_death(struct ehci_hcd *ehci) -{ - if (!(ehci_readl(ehci, &ehci->regs->status) & STS_HALT)) { - - /* Give up after a few milliseconds */ - if (ehci->died_poll_count++ < 5) { - /* Try again later */ - ehci_enable_event(ehci, EHCI_HRTIMER_POLL_DEAD, true); - return; - } - ehci_warn(ehci, "Waited too long for the controller to stop, giving up\n"); - } - - /* Clean up the mess */ - ehci->rh_state = EHCI_RH_HALTED; - ehci_writel(ehci, 0, &ehci->regs->configured_flag); - ehci_writel(ehci, 0, &ehci->regs->intr_enable); - ehci_work(ehci); - end_unlink_async(ehci); - - /* Not in process context, so don't try to reset the controller */ -} - -/* start to unlink interrupt QHs */ -static void ehci_handle_start_intr_unlinks(struct ehci_hcd *ehci) -{ - bool stopped = (ehci->rh_state < EHCI_RH_RUNNING); - - /* - * Process all the QHs on the intr_unlink list that were added - * before the current unlink cycle began. The list is in - * temporal order, so stop when we reach the first entry in the - * current cycle. But if the root hub isn't running then - * process all the QHs on the list. - */ - while (!list_empty(&ehci->intr_unlink_wait)) { - struct ehci_qh *qh; - - qh = list_first_entry(&ehci->intr_unlink_wait, - struct ehci_qh, unlink_node); - if (!stopped && (qh->unlink_cycle == - ehci->intr_unlink_wait_cycle)) - break; - list_del_init(&qh->unlink_node); - start_unlink_intr(ehci, qh); - } - - /* Handle remaining entries later */ - if (!list_empty(&ehci->intr_unlink_wait)) { - ehci_enable_event(ehci, EHCI_HRTIMER_START_UNLINK_INTR, true); - ++ehci->intr_unlink_wait_cycle; - } -} - -/* Handle unlinked interrupt QHs once they are gone from the hardware */ -static void ehci_handle_intr_unlinks(struct ehci_hcd *ehci) -{ - bool stopped = (ehci->rh_state < EHCI_RH_RUNNING); - - /* - * Process all the QHs on the intr_unlink list that were added - * before the current unlink cycle began. The list is in - * temporal order, so stop when we reach the first entry in the - * current cycle. But if the root hub isn't running then - * process all the QHs on the list. - */ - ehci->intr_unlinking = true; - while (!list_empty(&ehci->intr_unlink)) { - struct ehci_qh *qh; - - qh = list_first_entry(&ehci->intr_unlink, struct ehci_qh, - unlink_node); - if (!stopped && qh->unlink_cycle == ehci->intr_unlink_cycle) - break; - list_del_init(&qh->unlink_node); - end_unlink_intr(ehci, qh); - } - - /* Handle remaining entries later */ - if (!list_empty(&ehci->intr_unlink)) { - ehci_enable_event(ehci, EHCI_HRTIMER_UNLINK_INTR, true); - ++ehci->intr_unlink_cycle; - } - ehci->intr_unlinking = false; -} - - -/* Start another free-iTDs/siTDs cycle */ -static void start_free_itds(struct ehci_hcd *ehci) -{ - if (!(ehci->enabled_hrtimer_events & BIT(EHCI_HRTIMER_FREE_ITDS))) { - ehci->last_itd_to_free = list_entry( - ehci->cached_itd_list.prev, - struct ehci_itd, itd_list); - ehci->last_sitd_to_free = list_entry( - ehci->cached_sitd_list.prev, - struct ehci_sitd, sitd_list); - ehci_enable_event(ehci, EHCI_HRTIMER_FREE_ITDS, true); - } -} - -/* Wait for controller to stop using old iTDs and siTDs */ -static void end_free_itds(struct ehci_hcd *ehci) -{ - struct ehci_itd *itd, *n; - struct ehci_sitd *sitd, *sn; - - if (ehci->rh_state < EHCI_RH_RUNNING) { - ehci->last_itd_to_free = NULL; - ehci->last_sitd_to_free = NULL; - } - - list_for_each_entry_safe(itd, n, &ehci->cached_itd_list, itd_list) { - list_del(&itd->itd_list); - dma_pool_free(ehci->itd_pool, itd, itd->itd_dma); - if (itd == ehci->last_itd_to_free) - break; - } - list_for_each_entry_safe(sitd, sn, &ehci->cached_sitd_list, sitd_list) { - list_del(&sitd->sitd_list); - dma_pool_free(ehci->sitd_pool, sitd, sitd->sitd_dma); - if (sitd == ehci->last_sitd_to_free) - break; - } - - if (!list_empty(&ehci->cached_itd_list) || - !list_empty(&ehci->cached_sitd_list)) - start_free_itds(ehci); -} - - -/* Handle lost (or very late) IAA interrupts */ -static void ehci_iaa_watchdog(struct ehci_hcd *ehci) -{ - u32 cmd, status; - - /* - * Lost IAA irqs wedge things badly; seen first with a vt8235. - * So we need this watchdog, but must protect it against both - * (a) SMP races against real IAA firing and retriggering, and - * (b) clean HC shutdown, when IAA watchdog was pending. - */ - if (!ehci->iaa_in_progress || ehci->rh_state != EHCI_RH_RUNNING) - return; - - /* If we get here, IAA is *REALLY* late. It's barely - * conceivable that the system is so busy that CMD_IAAD - * is still legitimately set, so let's be sure it's - * clear before we read STS_IAA. (The HC should clear - * CMD_IAAD when it sets STS_IAA.) - */ - cmd = ehci_readl(ehci, &ehci->regs->command); - - /* - * If IAA is set here it either legitimately triggered - * after the watchdog timer expired (_way_ late, so we'll - * still count it as lost) ... or a silicon erratum: - * - VIA seems to set IAA without triggering the IRQ; - * - IAAD potentially cleared without setting IAA. - */ - status = ehci_readl(ehci, &ehci->regs->status); - if ((status & STS_IAA) || !(cmd & CMD_IAAD)) { - COUNT(ehci->stats.lost_iaa); - ehci_writel(ehci, STS_IAA, &ehci->regs->status); - } - - ehci_dbg(ehci, "IAA watchdog: status %x cmd %x\n", status, cmd); - end_unlink_async(ehci); -} - - -/* Enable the I/O watchdog, if appropriate */ -static void turn_on_io_watchdog(struct ehci_hcd *ehci) -{ - /* Not needed if the controller isn't running or it's already enabled */ - if (ehci->rh_state != EHCI_RH_RUNNING || - (ehci->enabled_hrtimer_events & - BIT(EHCI_HRTIMER_IO_WATCHDOG))) - return; - - /* - * Isochronous transfers always need the watchdog. - * For other sorts we use it only if the flag is set. - */ - if (ehci->isoc_count > 0 || (ehci->need_io_watchdog && - ehci->async_count + ehci->intr_count > 0)) - ehci_enable_event(ehci, EHCI_HRTIMER_IO_WATCHDOG, true); -} - - -/* - * Handler functions for the hrtimer event types. - * Keep this array in the same order as the event types indexed by - * enum ehci_hrtimer_event in ehci.h. - */ -static void (*event_handlers[])(struct ehci_hcd *) = { - ehci_poll_ASS, /* EHCI_HRTIMER_POLL_ASS */ - ehci_poll_PSS, /* EHCI_HRTIMER_POLL_PSS */ - ehci_handle_controller_death, /* EHCI_HRTIMER_POLL_DEAD */ - ehci_handle_intr_unlinks, /* EHCI_HRTIMER_UNLINK_INTR */ - end_free_itds, /* EHCI_HRTIMER_FREE_ITDS */ - ehci_handle_start_intr_unlinks, /* EHCI_HRTIMER_START_UNLINK_INTR */ - unlink_empty_async, /* EHCI_HRTIMER_ASYNC_UNLINKS */ - ehci_iaa_watchdog, /* EHCI_HRTIMER_IAA_WATCHDOG */ - ehci_disable_PSE, /* EHCI_HRTIMER_DISABLE_PERIODIC */ - ehci_disable_ASE, /* EHCI_HRTIMER_DISABLE_ASYNC */ - ehci_work, /* EHCI_HRTIMER_IO_WATCHDOG */ -}; - -static enum hrtimer_restart ehci_hrtimer_func(struct hrtimer *t) -{ - struct ehci_hcd *ehci = container_of(t, struct ehci_hcd, hrtimer); - ktime_t now; - unsigned long events; - unsigned long flags; - unsigned e; - - spin_lock_irqsave(&ehci->lock, flags); - - events = ehci->enabled_hrtimer_events; - ehci->enabled_hrtimer_events = 0; - ehci->next_hrtimer_event = EHCI_HRTIMER_NO_EVENT; - - /* - * Check each pending event. If its time has expired, handle - * the event; otherwise re-enable it. - */ - now = ktime_get(); - for_each_set_bit(e, &events, EHCI_HRTIMER_NUM_EVENTS) { - if (now.tv64 >= ehci->hr_timeouts[e].tv64) - event_handlers[e](ehci); - else - ehci_enable_event(ehci, e, false); - } - - spin_unlock_irqrestore(&ehci->lock, flags); - return HRTIMER_NORESTART; -} diff --git a/addons/ehci-pci/src/4.4.180/ehci.h b/addons/ehci-pci/src/4.4.180/ehci.h deleted file mode 100644 index 46f62e41..00000000 --- a/addons/ehci-pci/src/4.4.180/ehci.h +++ /dev/null @@ -1,895 +0,0 @@ -/* - * Copyright (c) 2001-2002 by David Brownell - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#ifndef __LINUX_EHCI_HCD_H -#define __LINUX_EHCI_HCD_H - -/* definitions used for the EHCI driver */ - -/* - * __hc32 and __hc16 are "Host Controller" types, they may be equivalent to - * __leXX (normally) or __beXX (given EHCI_BIG_ENDIAN_DESC), depending on - * the host controller implementation. - * - * To facilitate the strongest possible byte-order checking from "sparse" - * and so on, we use __leXX unless that's not practical. - */ -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC -typedef __u32 __bitwise __hc32; -typedef __u16 __bitwise __hc16; -#else -#define __hc32 __le32 -#define __hc16 __le16 -#endif - -/* statistics can be kept for tuning/monitoring */ -#ifdef CONFIG_DYNAMIC_DEBUG -#define EHCI_STATS -#endif - -struct ehci_stats { - /* irq usage */ - unsigned long normal; - unsigned long error; - unsigned long iaa; - unsigned long lost_iaa; - - /* termination of urbs from core */ - unsigned long complete; - unsigned long unlink; -}; - -/* - * Scheduling and budgeting information for periodic transfers, for both - * high-speed devices and full/low-speed devices lying behind a TT. - */ -struct ehci_per_sched { - struct usb_device *udev; /* access to the TT */ - struct usb_host_endpoint *ep; - struct list_head ps_list; /* node on ehci_tt's ps_list */ - u16 tt_usecs; /* time on the FS/LS bus */ - u16 cs_mask; /* C-mask and S-mask bytes */ - u16 period; /* actual period in frames */ - u16 phase; /* actual phase, frame part */ - u8 bw_phase; /* same, for bandwidth - reservation */ - u8 phase_uf; /* uframe part of the phase */ - u8 usecs, c_usecs; /* times on the HS bus */ - u8 bw_uperiod; /* period in microframes, for - bandwidth reservation */ - u8 bw_period; /* same, in frames */ -}; -#define NO_FRAME 29999 /* frame not assigned yet */ - -/* ehci_hcd->lock guards shared data against other CPUs: - * ehci_hcd: async, unlink, periodic (and shadow), ... - * usb_host_endpoint: hcpriv - * ehci_qh: qh_next, qtd_list - * ehci_qtd: qtd_list - * - * Also, hold this lock when talking to HC registers or - * when updating hw_* fields in shared qh/qtd/... structures. - */ - -#define EHCI_MAX_ROOT_PORTS 15 /* see HCS_N_PORTS */ - -/* - * ehci_rh_state values of EHCI_RH_RUNNING or above mean that the - * controller may be doing DMA. Lower values mean there's no DMA. - */ -enum ehci_rh_state { - EHCI_RH_HALTED, - EHCI_RH_SUSPENDED, - EHCI_RH_RUNNING, - EHCI_RH_STOPPING -}; - -/* - * Timer events, ordered by increasing delay length. - * Always update event_delays_ns[] and event_handlers[] (defined in - * ehci-timer.c) in parallel with this list. - */ -enum ehci_hrtimer_event { - EHCI_HRTIMER_POLL_ASS, /* Poll for async schedule off */ - EHCI_HRTIMER_POLL_PSS, /* Poll for periodic schedule off */ - EHCI_HRTIMER_POLL_DEAD, /* Wait for dead controller to stop */ - EHCI_HRTIMER_UNLINK_INTR, /* Wait for interrupt QH unlink */ - EHCI_HRTIMER_FREE_ITDS, /* Wait for unused iTDs and siTDs */ - EHCI_HRTIMER_START_UNLINK_INTR, /* Unlink empty interrupt QHs */ - EHCI_HRTIMER_ASYNC_UNLINKS, /* Unlink empty async QHs */ - EHCI_HRTIMER_IAA_WATCHDOG, /* Handle lost IAA interrupts */ - EHCI_HRTIMER_DISABLE_PERIODIC, /* Wait to disable periodic sched */ - EHCI_HRTIMER_DISABLE_ASYNC, /* Wait to disable async sched */ - EHCI_HRTIMER_IO_WATCHDOG, /* Check for missing IRQs */ - EHCI_HRTIMER_NUM_EVENTS /* Must come last */ -}; -#define EHCI_HRTIMER_NO_EVENT 99 - -struct ehci_hcd { /* one per controller */ - /* timing support */ - enum ehci_hrtimer_event next_hrtimer_event; - unsigned enabled_hrtimer_events; - ktime_t hr_timeouts[EHCI_HRTIMER_NUM_EVENTS]; - struct hrtimer hrtimer; - - int PSS_poll_count; - int ASS_poll_count; - int died_poll_count; - - /* glue to PCI and HCD framework */ - struct ehci_caps __iomem *caps; - struct ehci_regs __iomem *regs; - struct ehci_dbg_port __iomem *debug; - - __u32 hcs_params; /* cached register copy */ - spinlock_t lock; - enum ehci_rh_state rh_state; - - /* general schedule support */ - bool scanning:1; - bool need_rescan:1; - bool intr_unlinking:1; - bool iaa_in_progress:1; - bool async_unlinking:1; - bool shutdown:1; - struct ehci_qh *qh_scan_next; - - /* async schedule support */ - struct ehci_qh *async; - struct ehci_qh *dummy; /* For AMD quirk use */ - struct list_head async_unlink; - struct list_head async_idle; - unsigned async_unlink_cycle; - unsigned async_count; /* async activity count */ - - /* periodic schedule support */ -#define DEFAULT_I_TDPS 1024 /* some HCs can do less */ - unsigned periodic_size; - __hc32 *periodic; /* hw periodic table */ - dma_addr_t periodic_dma; - struct list_head intr_qh_list; - unsigned i_thresh; /* uframes HC might cache */ - - union ehci_shadow *pshadow; /* mirror hw periodic table */ - struct list_head intr_unlink_wait; - struct list_head intr_unlink; - unsigned intr_unlink_wait_cycle; - unsigned intr_unlink_cycle; - unsigned now_frame; /* frame from HC hardware */ - unsigned last_iso_frame; /* last frame scanned for iso */ - unsigned intr_count; /* intr activity count */ - unsigned isoc_count; /* isoc activity count */ - unsigned periodic_count; /* periodic activity count */ - unsigned uframe_periodic_max; /* max periodic time per uframe */ - - - /* list of itds & sitds completed while now_frame was still active */ - struct list_head cached_itd_list; - struct ehci_itd *last_itd_to_free; - struct list_head cached_sitd_list; - struct ehci_sitd *last_sitd_to_free; - - /* per root hub port */ - unsigned long reset_done [EHCI_MAX_ROOT_PORTS]; - - /* bit vectors (one bit per port) */ - unsigned long bus_suspended; /* which ports were - already suspended at the start of a bus suspend */ - unsigned long companion_ports; /* which ports are - dedicated to the companion controller */ - unsigned long owned_ports; /* which ports are - owned by the companion during a bus suspend */ - unsigned long port_c_suspend; /* which ports have - the change-suspend feature turned on */ - unsigned long suspended_ports; /* which ports are - suspended */ - unsigned long resuming_ports; /* which ports have - started to resume */ - - /* per-HC memory pools (could be per-bus, but ...) */ - struct dma_pool *qh_pool; /* qh per active urb */ - struct dma_pool *qtd_pool; /* one or more per qh */ - struct dma_pool *itd_pool; /* itd per iso urb */ - struct dma_pool *sitd_pool; /* sitd per split iso urb */ - - unsigned random_frame; - unsigned long next_statechange; - ktime_t last_periodic_enable; - u32 command; - - /* SILICON QUIRKS */ - unsigned no_selective_suspend:1; - unsigned has_fsl_port_bug:1; /* FreeScale */ - unsigned has_fsl_hs_errata:1; /* Freescale HS quirk */ - unsigned big_endian_mmio:1; - unsigned big_endian_desc:1; - unsigned big_endian_capbase:1; - unsigned has_amcc_usb23:1; - unsigned need_io_watchdog:1; - unsigned amd_pll_fix:1; - unsigned use_dummy_qh:1; /* AMD Frame List table quirk*/ - unsigned has_synopsys_hc_bug:1; /* Synopsys HC */ - unsigned frame_index_bug:1; /* MosChip (AKA NetMos) */ - unsigned need_oc_pp_cycle:1; /* MPC834X port power */ - unsigned imx28_write_fix:1; /* For Freescale i.MX28 */ - - /* required for usb32 quirk */ - #define OHCI_CTRL_HCFS (3 << 6) - #define OHCI_USB_OPER (2 << 6) - #define OHCI_USB_SUSPEND (3 << 6) - - #define OHCI_HCCTRL_OFFSET 0x4 - #define OHCI_HCCTRL_LEN 0x4 - __hc32 *ohci_hcctrl_reg; - unsigned has_hostpc:1; - unsigned has_tdi_phy_lpm:1; - unsigned has_ppcd:1; /* support per-port change bits */ - u8 sbrn; /* packed release number */ - - /* irq statistics */ -#ifdef EHCI_STATS - struct ehci_stats stats; -# define COUNT(x) do { (x)++; } while (0) -#else -# define COUNT(x) do {} while (0) -#endif - - /* debug files */ -#ifdef CONFIG_DYNAMIC_DEBUG - struct dentry *debug_dir; -#endif - - /* bandwidth usage */ -#define EHCI_BANDWIDTH_SIZE 64 -#define EHCI_BANDWIDTH_FRAMES (EHCI_BANDWIDTH_SIZE >> 3) - u8 bandwidth[EHCI_BANDWIDTH_SIZE]; - /* us allocated per uframe */ - u8 tt_budget[EHCI_BANDWIDTH_SIZE]; - /* us budgeted per uframe */ - struct list_head tt_list; - - /* platform-specific data -- must come last */ - unsigned long priv[0] __aligned(sizeof(s64)); -}; - -/* convert between an HCD pointer and the corresponding EHCI_HCD */ -static inline struct ehci_hcd *hcd_to_ehci (struct usb_hcd *hcd) -{ - return (struct ehci_hcd *) (hcd->hcd_priv); -} -static inline struct usb_hcd *ehci_to_hcd (struct ehci_hcd *ehci) -{ - return container_of ((void *) ehci, struct usb_hcd, hcd_priv); -} - -/*-------------------------------------------------------------------------*/ - -#include - -/*-------------------------------------------------------------------------*/ - -#define QTD_NEXT(ehci, dma) cpu_to_hc32(ehci, (u32)dma) - -/* - * EHCI Specification 0.95 Section 3.5 - * QTD: describe data transfer components (buffer, direction, ...) - * See Fig 3-6 "Queue Element Transfer Descriptor Block Diagram". - * - * These are associated only with "QH" (Queue Head) structures, - * used with control, bulk, and interrupt transfers. - */ -struct ehci_qtd { - /* first part defined by EHCI spec */ - __hc32 hw_next; /* see EHCI 3.5.1 */ - __hc32 hw_alt_next; /* see EHCI 3.5.2 */ - __hc32 hw_token; /* see EHCI 3.5.3 */ -#define QTD_TOGGLE (1 << 31) /* data toggle */ -#define QTD_LENGTH(tok) (((tok)>>16) & 0x7fff) -#define QTD_IOC (1 << 15) /* interrupt on complete */ -#define QTD_CERR(tok) (((tok)>>10) & 0x3) -#define QTD_PID(tok) (((tok)>>8) & 0x3) -#define QTD_STS_ACTIVE (1 << 7) /* HC may execute this */ -#define QTD_STS_HALT (1 << 6) /* halted on error */ -#define QTD_STS_DBE (1 << 5) /* data buffer error (in HC) */ -#define QTD_STS_BABBLE (1 << 4) /* device was babbling (qtd halted) */ -#define QTD_STS_XACT (1 << 3) /* device gave illegal response */ -#define QTD_STS_MMF (1 << 2) /* incomplete split transaction */ -#define QTD_STS_STS (1 << 1) /* split transaction state */ -#define QTD_STS_PING (1 << 0) /* issue PING? */ - -#define ACTIVE_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_ACTIVE) -#define HALT_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_HALT) -#define STATUS_BIT(ehci) cpu_to_hc32(ehci, QTD_STS_STS) - - __hc32 hw_buf [5]; /* see EHCI 3.5.4 */ - __hc32 hw_buf_hi [5]; /* Appendix B */ - - /* the rest is HCD-private */ - dma_addr_t qtd_dma; /* qtd address */ - struct list_head qtd_list; /* sw qtd list */ - struct urb *urb; /* qtd's urb */ - size_t length; /* length of buffer */ -} __attribute__ ((aligned (32))); - -/* mask NakCnt+T in qh->hw_alt_next */ -#define QTD_MASK(ehci) cpu_to_hc32 (ehci, ~0x1f) - -#define IS_SHORT_READ(token) (QTD_LENGTH (token) != 0 && QTD_PID (token) == 1) - -/*-------------------------------------------------------------------------*/ - -/* type tag from {qh,itd,sitd,fstn}->hw_next */ -#define Q_NEXT_TYPE(ehci,dma) ((dma) & cpu_to_hc32(ehci, 3 << 1)) - -/* - * Now the following defines are not converted using the - * cpu_to_le32() macro anymore, since we have to support - * "dynamic" switching between be and le support, so that the driver - * can be used on one system with SoC EHCI controller using big-endian - * descriptors as well as a normal little-endian PCI EHCI controller. - */ -/* values for that type tag */ -#define Q_TYPE_ITD (0 << 1) -#define Q_TYPE_QH (1 << 1) -#define Q_TYPE_SITD (2 << 1) -#define Q_TYPE_FSTN (3 << 1) - -/* next async queue entry, or pointer to interrupt/periodic QH */ -#define QH_NEXT(ehci,dma) (cpu_to_hc32(ehci, (((u32)dma)&~0x01f)|Q_TYPE_QH)) - -/* for periodic/async schedules and qtd lists, mark end of list */ -#define EHCI_LIST_END(ehci) cpu_to_hc32(ehci, 1) /* "null pointer" to hw */ - -/* - * Entries in periodic shadow table are pointers to one of four kinds - * of data structure. That's dictated by the hardware; a type tag is - * encoded in the low bits of the hardware's periodic schedule. Use - * Q_NEXT_TYPE to get the tag. - * - * For entries in the async schedule, the type tag always says "qh". - */ -union ehci_shadow { - struct ehci_qh *qh; /* Q_TYPE_QH */ - struct ehci_itd *itd; /* Q_TYPE_ITD */ - struct ehci_sitd *sitd; /* Q_TYPE_SITD */ - struct ehci_fstn *fstn; /* Q_TYPE_FSTN */ - __hc32 *hw_next; /* (all types) */ - void *ptr; -}; - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.6 - * QH: describes control/bulk/interrupt endpoints - * See Fig 3-7 "Queue Head Structure Layout". - * - * These appear in both the async and (for interrupt) periodic schedules. - */ - -/* first part defined by EHCI spec */ -struct ehci_qh_hw { - __hc32 hw_next; /* see EHCI 3.6.1 */ - __hc32 hw_info1; /* see EHCI 3.6.2 */ -#define QH_CONTROL_EP (1 << 27) /* FS/LS control endpoint */ -#define QH_HEAD (1 << 15) /* Head of async reclamation list */ -#define QH_TOGGLE_CTL (1 << 14) /* Data toggle control */ -#define QH_HIGH_SPEED (2 << 12) /* Endpoint speed */ -#define QH_LOW_SPEED (1 << 12) -#define QH_FULL_SPEED (0 << 12) -#define QH_INACTIVATE (1 << 7) /* Inactivate on next transaction */ - __hc32 hw_info2; /* see EHCI 3.6.2 */ -#define QH_SMASK 0x000000ff -#define QH_CMASK 0x0000ff00 -#define QH_HUBADDR 0x007f0000 -#define QH_HUBPORT 0x3f800000 -#define QH_MULT 0xc0000000 - __hc32 hw_current; /* qtd list - see EHCI 3.6.4 */ - - /* qtd overlay (hardware parts of a struct ehci_qtd) */ - __hc32 hw_qtd_next; - __hc32 hw_alt_next; - __hc32 hw_token; - __hc32 hw_buf [5]; - __hc32 hw_buf_hi [5]; -} __attribute__ ((aligned(32))); - -struct ehci_qh { - struct ehci_qh_hw *hw; /* Must come first */ - /* the rest is HCD-private */ - dma_addr_t qh_dma; /* address of qh */ - union ehci_shadow qh_next; /* ptr to qh; or periodic */ - struct list_head qtd_list; /* sw qtd list */ - struct list_head intr_node; /* list of intr QHs */ - struct ehci_qtd *dummy; - struct list_head unlink_node; - struct ehci_per_sched ps; /* scheduling info */ - - unsigned unlink_cycle; - - u8 qh_state; -#define QH_STATE_LINKED 1 /* HC sees this */ -#define QH_STATE_UNLINK 2 /* HC may still see this */ -#define QH_STATE_IDLE 3 /* HC doesn't see this */ -#define QH_STATE_UNLINK_WAIT 4 /* LINKED and on unlink q */ -#define QH_STATE_COMPLETING 5 /* don't touch token.HALT */ - - u8 xacterrs; /* XactErr retry counter */ -#define QH_XACTERR_MAX 32 /* XactErr retry limit */ - - u8 gap_uf; /* uframes split/csplit gap */ - - unsigned is_out:1; /* bulk or intr OUT */ - unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ - unsigned dequeue_during_giveback:1; - unsigned exception:1; /* got a fault, or an unlink - was requested */ -}; - -/*-------------------------------------------------------------------------*/ - -/* description of one iso transaction (up to 3 KB data if highspeed) */ -struct ehci_iso_packet { - /* These will be copied to iTD when scheduling */ - u64 bufp; /* itd->hw_bufp{,_hi}[pg] |= */ - __hc32 transaction; /* itd->hw_transaction[i] |= */ - u8 cross; /* buf crosses pages */ - /* for full speed OUT splits */ - u32 buf1; -}; - -/* temporary schedule data for packets from iso urbs (both speeds) - * each packet is one logical usb transaction to the device (not TT), - * beginning at stream->next_uframe - */ -struct ehci_iso_sched { - struct list_head td_list; - unsigned span; - unsigned first_packet; - struct ehci_iso_packet packet [0]; -}; - -/* - * ehci_iso_stream - groups all (s)itds for this endpoint. - * acts like a qh would, if EHCI had them for ISO. - */ -struct ehci_iso_stream { - /* first field matches ehci_hq, but is NULL */ - struct ehci_qh_hw *hw; - - u8 bEndpointAddress; - u8 highspeed; - struct list_head td_list; /* queued itds/sitds */ - struct list_head free_list; /* list of unused itds/sitds */ - - /* output of (re)scheduling */ - struct ehci_per_sched ps; /* scheduling info */ - unsigned next_uframe; - __hc32 splits; - - /* the rest is derived from the endpoint descriptor, - * including the extra info for hw_bufp[0..2] - */ - u16 uperiod; /* period in uframes */ - u16 maxp; - unsigned bandwidth; - - /* This is used to initialize iTD's hw_bufp fields */ - __hc32 buf0; - __hc32 buf1; - __hc32 buf2; - - /* this is used to initialize sITD's tt info */ - __hc32 address; -}; - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.3 - * Fig 3-4 "Isochronous Transaction Descriptor (iTD)" - * - * Schedule records for high speed iso xfers - */ -struct ehci_itd { - /* first part defined by EHCI spec */ - __hc32 hw_next; /* see EHCI 3.3.1 */ - __hc32 hw_transaction [8]; /* see EHCI 3.3.2 */ -#define EHCI_ISOC_ACTIVE (1<<31) /* activate transfer this slot */ -#define EHCI_ISOC_BUF_ERR (1<<30) /* Data buffer error */ -#define EHCI_ISOC_BABBLE (1<<29) /* babble detected */ -#define EHCI_ISOC_XACTERR (1<<28) /* XactErr - transaction error */ -#define EHCI_ITD_LENGTH(tok) (((tok)>>16) & 0x0fff) -#define EHCI_ITD_IOC (1 << 15) /* interrupt on complete */ - -#define ITD_ACTIVE(ehci) cpu_to_hc32(ehci, EHCI_ISOC_ACTIVE) - - __hc32 hw_bufp [7]; /* see EHCI 3.3.3 */ - __hc32 hw_bufp_hi [7]; /* Appendix B */ - - /* the rest is HCD-private */ - dma_addr_t itd_dma; /* for this itd */ - union ehci_shadow itd_next; /* ptr to periodic q entry */ - - struct urb *urb; - struct ehci_iso_stream *stream; /* endpoint's queue */ - struct list_head itd_list; /* list of stream's itds */ - - /* any/all hw_transactions here may be used by that urb */ - unsigned frame; /* where scheduled */ - unsigned pg; - unsigned index[8]; /* in urb->iso_frame_desc */ -} __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.95 Section 3.4 - * siTD, aka split-transaction isochronous Transfer Descriptor - * ... describe full speed iso xfers through TT in hubs - * see Figure 3-5 "Split-transaction Isochronous Transaction Descriptor (siTD) - */ -struct ehci_sitd { - /* first part defined by EHCI spec */ - __hc32 hw_next; -/* uses bit field macros above - see EHCI 0.95 Table 3-8 */ - __hc32 hw_fullspeed_ep; /* EHCI table 3-9 */ - __hc32 hw_uframe; /* EHCI table 3-10 */ - __hc32 hw_results; /* EHCI table 3-11 */ -#define SITD_IOC (1 << 31) /* interrupt on completion */ -#define SITD_PAGE (1 << 30) /* buffer 0/1 */ -#define SITD_LENGTH(x) (0x3ff & ((x)>>16)) -#define SITD_STS_ACTIVE (1 << 7) /* HC may execute this */ -#define SITD_STS_ERR (1 << 6) /* error from TT */ -#define SITD_STS_DBE (1 << 5) /* data buffer error (in HC) */ -#define SITD_STS_BABBLE (1 << 4) /* device was babbling */ -#define SITD_STS_XACT (1 << 3) /* illegal IN response */ -#define SITD_STS_MMF (1 << 2) /* incomplete split transaction */ -#define SITD_STS_STS (1 << 1) /* split transaction state */ - -#define SITD_ACTIVE(ehci) cpu_to_hc32(ehci, SITD_STS_ACTIVE) - - __hc32 hw_buf [2]; /* EHCI table 3-12 */ - __hc32 hw_backpointer; /* EHCI table 3-13 */ - __hc32 hw_buf_hi [2]; /* Appendix B */ - - /* the rest is HCD-private */ - dma_addr_t sitd_dma; - union ehci_shadow sitd_next; /* ptr to periodic q entry */ - - struct urb *urb; - struct ehci_iso_stream *stream; /* endpoint's queue */ - struct list_head sitd_list; /* list of stream's sitds */ - unsigned frame; - unsigned index; -} __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - -/* - * EHCI Specification 0.96 Section 3.7 - * Periodic Frame Span Traversal Node (FSTN) - * - * Manages split interrupt transactions (using TT) that span frame boundaries - * into uframes 0/1; see 4.12.2.2. In those uframes, a "save place" FSTN - * makes the HC jump (back) to a QH to scan for fs/ls QH completions until - * it hits a "restore" FSTN; then it returns to finish other uframe 0/1 work. - */ -struct ehci_fstn { - __hc32 hw_next; /* any periodic q entry */ - __hc32 hw_prev; /* qh or EHCI_LIST_END */ - - /* the rest is HCD-private */ - dma_addr_t fstn_dma; - union ehci_shadow fstn_next; /* ptr to periodic q entry */ -} __attribute__ ((aligned (32))); - -/*-------------------------------------------------------------------------*/ - -/* - * USB-2.0 Specification Sections 11.14 and 11.18 - * Scheduling and budgeting split transactions using TTs - * - * A hub can have a single TT for all its ports, or multiple TTs (one for each - * port). The bandwidth and budgeting information for the full/low-speed bus - * below each TT is self-contained and independent of the other TTs or the - * high-speed bus. - * - * "Bandwidth" refers to the number of microseconds on the FS/LS bus allocated - * to an interrupt or isochronous endpoint for each frame. "Budget" refers to - * the best-case estimate of the number of full-speed bytes allocated to an - * endpoint for each microframe within an allocated frame. - * - * Removal of an endpoint invalidates a TT's budget. Instead of trying to - * keep an up-to-date record, we recompute the budget when it is needed. - */ - -struct ehci_tt { - u16 bandwidth[EHCI_BANDWIDTH_FRAMES]; - - struct list_head tt_list; /* List of all ehci_tt's */ - struct list_head ps_list; /* Items using this TT */ - struct usb_tt *usb_tt; - int tt_port; /* TT port number */ -}; - -/*-------------------------------------------------------------------------*/ - -/* Prepare the PORTSC wakeup flags during controller suspend/resume */ - -#define ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup) \ - ehci_adjust_port_wakeup_flags(ehci, true, do_wakeup); - -#define ehci_prepare_ports_for_controller_resume(ehci) \ - ehci_adjust_port_wakeup_flags(ehci, false, false); - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_USB_EHCI_ROOT_HUB_TT - -/* - * Some EHCI controllers have a Transaction Translator built into the - * root hub. This is a non-standard feature. Each controller will need - * to add code to the following inline functions, and call them as - * needed (mostly in root hub code). - */ - -#define ehci_is_TDI(e) (ehci_to_hcd(e)->has_tt) - -/* Returns the speed of a device attached to a port on the root hub. */ -static inline unsigned int -ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) -{ - if (ehci_is_TDI(ehci)) { - switch ((portsc >> (ehci->has_hostpc ? 25 : 26)) & 3) { - case 0: - return 0; - case 1: - return USB_PORT_STAT_LOW_SPEED; - case 2: - default: - return USB_PORT_STAT_HIGH_SPEED; - } - } - return USB_PORT_STAT_HIGH_SPEED; -} - -#else - -#define ehci_is_TDI(e) (0) - -#define ehci_port_speed(ehci, portsc) USB_PORT_STAT_HIGH_SPEED -#endif - -/*-------------------------------------------------------------------------*/ - -#ifdef CONFIG_PPC_83xx -/* Some Freescale processors have an erratum in which the TT - * port number in the queue head was 0..N-1 instead of 1..N. - */ -#define ehci_has_fsl_portno_bug(e) ((e)->has_fsl_port_bug) -#else -#define ehci_has_fsl_portno_bug(e) (0) -#endif - -#define PORTSC_FSL_PFSC 24 /* Port Force Full-Speed Connect */ - -#if defined(CONFIG_PPC_85xx) -/* Some Freescale processors have an erratum (USB A-005275) in which - * incoming packets get corrupted in HS mode - */ -#define ehci_has_fsl_hs_errata(e) ((e)->has_fsl_hs_errata) -#else -#define ehci_has_fsl_hs_errata(e) (0) -#endif - -/* - * While most USB host controllers implement their registers in - * little-endian format, a minority (celleb companion chip) implement - * them in big endian format. - * - * This attempts to support either format at compile time without a - * runtime penalty, or both formats with the additional overhead - * of checking a flag bit. - * - * ehci_big_endian_capbase is a special quirk for controllers that - * implement the HC capability registers as separate registers and not - * as fields of a 32-bit register. - */ - -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO -#define ehci_big_endian_mmio(e) ((e)->big_endian_mmio) -#define ehci_big_endian_capbase(e) ((e)->big_endian_capbase) -#else -#define ehci_big_endian_mmio(e) 0 -#define ehci_big_endian_capbase(e) 0 -#endif - -/* - * Big-endian read/write functions are arch-specific. - * Other arches can be added if/when they're needed. - */ -#if defined(CONFIG_ARM) && defined(CONFIG_ARCH_IXP4XX) -#define readl_be(addr) __raw_readl((__force unsigned *)addr) -#define writel_be(val, addr) __raw_writel(val, (__force unsigned *)addr) -#endif - -static inline unsigned int ehci_readl(const struct ehci_hcd *ehci, - __u32 __iomem * regs) -{ -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO - return ehci_big_endian_mmio(ehci) ? - readl_be(regs) : - readl(regs); -#else - return readl(regs); -#endif -} - -#ifdef CONFIG_SOC_IMX28 -static inline void imx28_ehci_writel(const unsigned int val, - volatile __u32 __iomem *addr) -{ - __asm__ ("swp %0, %0, [%1]" : : "r"(val), "r"(addr)); -} -#else -static inline void imx28_ehci_writel(const unsigned int val, - volatile __u32 __iomem *addr) -{ -} -#endif -static inline void ehci_writel(const struct ehci_hcd *ehci, - const unsigned int val, __u32 __iomem *regs) -{ -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_MMIO - ehci_big_endian_mmio(ehci) ? - writel_be(val, regs) : - writel(val, regs); -#else - if (ehci->imx28_write_fix) - imx28_ehci_writel(val, regs); - else - writel(val, regs); -#endif -} - -/* - * On certain ppc-44x SoC there is a HW issue, that could only worked around with - * explicit suspend/operate of OHCI. This function hereby makes sense only on that arch. - * Other common bits are dependent on has_amcc_usb23 quirk flag. - */ -#ifdef CONFIG_44x -static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational) -{ - u32 hc_control; - - hc_control = (readl_be(ehci->ohci_hcctrl_reg) & ~OHCI_CTRL_HCFS); - if (operational) - hc_control |= OHCI_USB_OPER; - else - hc_control |= OHCI_USB_SUSPEND; - - writel_be(hc_control, ehci->ohci_hcctrl_reg); - (void) readl_be(ehci->ohci_hcctrl_reg); -} -#else -static inline void set_ohci_hcfs(struct ehci_hcd *ehci, int operational) -{ } -#endif - -/*-------------------------------------------------------------------------*/ - -/* - * The AMCC 440EPx not only implements its EHCI registers in big-endian - * format, but also its DMA data structures (descriptors). - * - * EHCI controllers accessed through PCI work normally (little-endian - * everywhere), so we won't bother supporting a BE-only mode for now. - */ -#ifdef CONFIG_USB_EHCI_BIG_ENDIAN_DESC -#define ehci_big_endian_desc(e) ((e)->big_endian_desc) - -/* cpu to ehci */ -static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x) -{ - return ehci_big_endian_desc(ehci) - ? (__force __hc32)cpu_to_be32(x) - : (__force __hc32)cpu_to_le32(x); -} - -/* ehci to cpu */ -static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x) -{ - return ehci_big_endian_desc(ehci) - ? be32_to_cpu((__force __be32)x) - : le32_to_cpu((__force __le32)x); -} - -static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) -{ - return ehci_big_endian_desc(ehci) - ? be32_to_cpup((__force __be32 *)x) - : le32_to_cpup((__force __le32 *)x); -} - -#else - -/* cpu to ehci */ -static inline __hc32 cpu_to_hc32 (const struct ehci_hcd *ehci, const u32 x) -{ - return cpu_to_le32(x); -} - -/* ehci to cpu */ -static inline u32 hc32_to_cpu (const struct ehci_hcd *ehci, const __hc32 x) -{ - return le32_to_cpu(x); -} - -static inline u32 hc32_to_cpup (const struct ehci_hcd *ehci, const __hc32 *x) -{ - return le32_to_cpup(x); -} - -#endif - -/*-------------------------------------------------------------------------*/ - -#define ehci_dbg(ehci, fmt, args...) \ - dev_dbg(ehci_to_hcd(ehci)->self.controller , fmt , ## args) -#define ehci_err(ehci, fmt, args...) \ - dev_err(ehci_to_hcd(ehci)->self.controller , fmt , ## args) -#define ehci_info(ehci, fmt, args...) \ - dev_info(ehci_to_hcd(ehci)->self.controller , fmt , ## args) -#define ehci_warn(ehci, fmt, args...) \ - dev_warn(ehci_to_hcd(ehci)->self.controller , fmt , ## args) - - -#ifndef CONFIG_DYNAMIC_DEBUG -#define STUB_DEBUG_FILES -#endif - -/*-------------------------------------------------------------------------*/ - -/* Declarations of things exported for use by ehci platform drivers */ - -struct ehci_driver_overrides { - size_t extra_priv_size; - int (*reset)(struct usb_hcd *hcd); - int (*port_power)(struct usb_hcd *hcd, - int portnum, bool enable); -}; - -extern void ehci_init_driver(struct hc_driver *drv, - const struct ehci_driver_overrides *over); -extern int ehci_setup(struct usb_hcd *hcd); -extern int ehci_handshake(struct ehci_hcd *ehci, void __iomem *ptr, - u32 mask, u32 done, int usec); -extern int ehci_reset(struct ehci_hcd *ehci); - -#ifdef CONFIG_PM -extern int ehci_suspend(struct usb_hcd *hcd, bool do_wakeup); -extern int ehci_resume(struct usb_hcd *hcd, bool force_reset); -extern void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, - bool suspending, bool do_wakeup); -#endif /* CONFIG_PM */ - -extern int ehci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, - u16 wIndex, char *buf, u16 wLength); - -#endif /* __LINUX_EHCI_HCD_H */ diff --git a/addons/ehci-pci/src/4.4.180/pci-quirks.c b/addons/ehci-pci/src/4.4.180/pci-quirks.c deleted file mode 100644 index 89e9494c..00000000 --- a/addons/ehci-pci/src/4.4.180/pci-quirks.c +++ /dev/null @@ -1,1105 +0,0 @@ -/* - * This file contains code to reset and initialize USB host controllers. - * Some of it includes work-arounds for PCI hardware and BIOS quirks. - * It may need to run early during booting -- before USB would normally - * initialize -- to ensure that Linux doesn't use any legacy modes. - * - * Copyright (c) 1999 Martin Mares - * (and others) - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "pci-quirks.h" -#include "xhci-ext-caps.h" - - -#define UHCI_USBLEGSUP 0xc0 /* legacy support */ -#define UHCI_USBCMD 0 /* command register */ -#define UHCI_USBINTR 4 /* interrupt register */ -#define UHCI_USBLEGSUP_RWC 0x8f00 /* the R/WC bits */ -#define UHCI_USBLEGSUP_RO 0x5040 /* R/O and reserved bits */ -#define UHCI_USBCMD_RUN 0x0001 /* RUN/STOP bit */ -#define UHCI_USBCMD_HCRESET 0x0002 /* Host Controller reset */ -#define UHCI_USBCMD_EGSM 0x0008 /* Global Suspend Mode */ -#define UHCI_USBCMD_CONFIGURE 0x0040 /* Config Flag */ -#define UHCI_USBINTR_RESUME 0x0002 /* Resume interrupt enable */ - -#define OHCI_CONTROL 0x04 -#define OHCI_CMDSTATUS 0x08 -#define OHCI_INTRSTATUS 0x0c -#define OHCI_INTRENABLE 0x10 -#define OHCI_INTRDISABLE 0x14 -#define OHCI_FMINTERVAL 0x34 -#define OHCI_HCFS (3 << 6) /* hc functional state */ -#define OHCI_HCR (1 << 0) /* host controller reset */ -#define OHCI_OCR (1 << 3) /* ownership change request */ -#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ -#define OHCI_CTRL_IR (1 << 8) /* interrupt routing */ -#define OHCI_INTR_OC (1 << 30) /* ownership change */ - -#define EHCI_HCC_PARAMS 0x08 /* extended capabilities */ -#define EHCI_USBCMD 0 /* command register */ -#define EHCI_USBCMD_RUN (1 << 0) /* RUN/STOP bit */ -#define EHCI_USBSTS 4 /* status register */ -#define EHCI_USBSTS_HALTED (1 << 12) /* HCHalted bit */ -#define EHCI_USBINTR 8 /* interrupt register */ -#define EHCI_CONFIGFLAG 0x40 /* configured flag register */ -#define EHCI_USBLEGSUP 0 /* legacy support register */ -#define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */ -#define EHCI_USBLEGSUP_OS (1 << 24) /* OS semaphore */ -#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */ -#define EHCI_USBLEGCTLSTS_SOOE (1 << 13) /* SMI on ownership change */ - -/* AMD quirk use */ -#define AB_REG_BAR_LOW 0xe0 -#define AB_REG_BAR_HIGH 0xe1 -#define AB_REG_BAR_SB700 0xf0 -#define AB_INDX(addr) ((addr) + 0x00) -#define AB_DATA(addr) ((addr) + 0x04) -#define AX_INDXC 0x30 -#define AX_DATAC 0x34 - -#define NB_PCIE_INDX_ADDR 0xe0 -#define NB_PCIE_INDX_DATA 0xe4 -#define PCIE_P_CNTL 0x10040 -#define BIF_NB 0x10002 -#define NB_PIF0_PWRDOWN_0 0x01100012 -#define NB_PIF0_PWRDOWN_1 0x01100013 - -#define USB_INTEL_XUSB2PR 0xD0 -#define USB_INTEL_USB2PRM 0xD4 -#define USB_INTEL_USB3_PSSEN 0xD8 -#define USB_INTEL_USB3PRM 0xDC - -/* - * amd_chipset_gen values represent AMD different chipset generations - */ -enum amd_chipset_gen { - NOT_AMD_CHIPSET = 0, - AMD_CHIPSET_SB600, - AMD_CHIPSET_SB700, - AMD_CHIPSET_SB800, - AMD_CHIPSET_HUDSON2, - AMD_CHIPSET_BOLTON, - AMD_CHIPSET_YANGTZE, - AMD_CHIPSET_TAISHAN, - AMD_CHIPSET_UNKNOWN, -}; - -struct amd_chipset_type { - enum amd_chipset_gen gen; - u8 rev; -}; - -static struct amd_chipset_info { - struct pci_dev *nb_dev; - struct pci_dev *smbus_dev; - int nb_type; - struct amd_chipset_type sb_type; - int isoc_reqs; - int probe_count; - int probe_result; -} amd_chipset; - -static DEFINE_SPINLOCK(amd_lock); - -/* - * amd_chipset_sb_type_init - initialize amd chipset southbridge type - * - * AMD FCH/SB generation and revision is identified by SMBus controller - * vendor, device and revision IDs. - * - * Returns: 1 if it is an AMD chipset, 0 otherwise. - */ -static int amd_chipset_sb_type_init(struct amd_chipset_info *pinfo) -{ - u8 rev = 0; - pinfo->sb_type.gen = AMD_CHIPSET_UNKNOWN; - - pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_ATI, - PCI_DEVICE_ID_ATI_SBX00_SMBUS, NULL); - if (pinfo->smbus_dev) { - rev = pinfo->smbus_dev->revision; - if (rev >= 0x10 && rev <= 0x1f) - pinfo->sb_type.gen = AMD_CHIPSET_SB600; - else if (rev >= 0x30 && rev <= 0x3f) - pinfo->sb_type.gen = AMD_CHIPSET_SB700; - else if (rev >= 0x40 && rev <= 0x4f) - pinfo->sb_type.gen = AMD_CHIPSET_SB800; - } else { - pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, - PCI_DEVICE_ID_AMD_HUDSON2_SMBUS, NULL); - - if (pinfo->smbus_dev) { - rev = pinfo->smbus_dev->revision; - if (rev >= 0x11 && rev <= 0x14) - pinfo->sb_type.gen = AMD_CHIPSET_HUDSON2; - else if (rev >= 0x15 && rev <= 0x18) - pinfo->sb_type.gen = AMD_CHIPSET_BOLTON; - else if (rev >= 0x39 && rev <= 0x3a) - pinfo->sb_type.gen = AMD_CHIPSET_YANGTZE; - } else { - pinfo->smbus_dev = pci_get_device(PCI_VENDOR_ID_AMD, - 0x145c, NULL); - if (pinfo->smbus_dev) { - rev = pinfo->smbus_dev->revision; - pinfo->sb_type.gen = AMD_CHIPSET_TAISHAN; - } else { - pinfo->sb_type.gen = NOT_AMD_CHIPSET; - return 0; - } - } - } - pinfo->sb_type.rev = rev; - return 1; -} - -void sb800_prefetch(struct device *dev, int on) -{ - u16 misc; - struct pci_dev *pdev = to_pci_dev(dev); - - pci_read_config_word(pdev, 0x50, &misc); - if (on == 0) - pci_write_config_word(pdev, 0x50, misc & 0xfcff); - else - pci_write_config_word(pdev, 0x50, misc | 0x0300); -} -EXPORT_SYMBOL_GPL(sb800_prefetch); - -int usb_amd_find_chipset_info(void) -{ - unsigned long flags; - struct amd_chipset_info info; - int ret; - - spin_lock_irqsave(&amd_lock, flags); - - /* probe only once */ - if (amd_chipset.probe_count > 0) { - amd_chipset.probe_count++; - spin_unlock_irqrestore(&amd_lock, flags); - return amd_chipset.probe_result; - } - memset(&info, 0, sizeof(info)); - spin_unlock_irqrestore(&amd_lock, flags); - - if (!amd_chipset_sb_type_init(&info)) { - ret = 0; - goto commit; - } - - /* Below chipset generations needn't enable AMD PLL quirk */ - if (info.sb_type.gen == AMD_CHIPSET_UNKNOWN || - info.sb_type.gen == AMD_CHIPSET_SB600 || - info.sb_type.gen == AMD_CHIPSET_YANGTZE || - (info.sb_type.gen == AMD_CHIPSET_SB700 && - info.sb_type.rev > 0x3b)) { - if (info.smbus_dev) { - pci_dev_put(info.smbus_dev); - info.smbus_dev = NULL; - } - ret = 0; - goto commit; - } - - info.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x9601, NULL); - if (info.nb_dev) { - info.nb_type = 1; - } else { - info.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1510, NULL); - if (info.nb_dev) { - info.nb_type = 2; - } else { - info.nb_dev = pci_get_device(PCI_VENDOR_ID_AMD, - 0x9600, NULL); - if (info.nb_dev) - info.nb_type = 3; - } - } - - ret = info.probe_result = 1; - printk(KERN_DEBUG "QUIRK: Enable AMD PLL fix\n"); - -commit: - - spin_lock_irqsave(&amd_lock, flags); - if (amd_chipset.probe_count > 0) { - /* race - someone else was faster - drop devices */ - - /* Mark that we where here */ - amd_chipset.probe_count++; - ret = amd_chipset.probe_result; - - spin_unlock_irqrestore(&amd_lock, flags); - - pci_dev_put(info.nb_dev); - pci_dev_put(info.smbus_dev); - - } else { - /* no race - commit the result */ - info.probe_count++; - amd_chipset = info; - spin_unlock_irqrestore(&amd_lock, flags); - } - - return ret; -} -EXPORT_SYMBOL_GPL(usb_amd_find_chipset_info); - -int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev) -{ - /* Make sure amd chipset type has already been initialized */ - usb_amd_find_chipset_info(); - if (amd_chipset.sb_type.gen == AMD_CHIPSET_YANGTZE || - amd_chipset.sb_type.gen == AMD_CHIPSET_TAISHAN) { - dev_dbg(&pdev->dev, "QUIRK: Enable AMD remote wakeup fix\n"); - return 1; - } - return 0; -} -EXPORT_SYMBOL_GPL(usb_hcd_amd_remote_wakeup_quirk); - -bool usb_amd_hang_symptom_quirk(void) -{ - u8 rev; - - usb_amd_find_chipset_info(); - rev = amd_chipset.sb_type.rev; - /* SB600 and old version of SB700 have hang symptom bug */ - return amd_chipset.sb_type.gen == AMD_CHIPSET_SB600 || - (amd_chipset.sb_type.gen == AMD_CHIPSET_SB700 && - rev >= 0x3a && rev <= 0x3b); -} -EXPORT_SYMBOL_GPL(usb_amd_hang_symptom_quirk); - -bool usb_amd_prefetch_quirk(void) -{ - usb_amd_find_chipset_info(); - /* SB800 needs pre-fetch fix */ - return amd_chipset.sb_type.gen == AMD_CHIPSET_SB800; -} -EXPORT_SYMBOL_GPL(usb_amd_prefetch_quirk); - -/* - * The hardware normally enables the A-link power management feature, which - * lets the system lower the power consumption in idle states. - * - * This USB quirk prevents the link going into that lower power state - * during isochronous transfers. - * - * Without this quirk, isochronous stream on OHCI/EHCI/xHCI controllers of - * some AMD platforms may stutter or have breaks occasionally. - */ -static void usb_amd_quirk_pll(int disable) -{ - u32 addr, addr_low, addr_high, val; - u32 bit = disable ? 0 : 1; - unsigned long flags; - - spin_lock_irqsave(&amd_lock, flags); - - if (disable) { - amd_chipset.isoc_reqs++; - if (amd_chipset.isoc_reqs > 1) { - spin_unlock_irqrestore(&amd_lock, flags); - return; - } - } else { - amd_chipset.isoc_reqs--; - if (amd_chipset.isoc_reqs > 0) { - spin_unlock_irqrestore(&amd_lock, flags); - return; - } - } - - if (amd_chipset.sb_type.gen == AMD_CHIPSET_SB800 || - amd_chipset.sb_type.gen == AMD_CHIPSET_HUDSON2 || - amd_chipset.sb_type.gen == AMD_CHIPSET_BOLTON) { - outb_p(AB_REG_BAR_LOW, 0xcd6); - addr_low = inb_p(0xcd7); - outb_p(AB_REG_BAR_HIGH, 0xcd6); - addr_high = inb_p(0xcd7); - addr = addr_high << 8 | addr_low; - - outl_p(0x30, AB_INDX(addr)); - outl_p(0x40, AB_DATA(addr)); - outl_p(0x34, AB_INDX(addr)); - val = inl_p(AB_DATA(addr)); - } else if (amd_chipset.sb_type.gen == AMD_CHIPSET_SB700 && - amd_chipset.sb_type.rev <= 0x3b) { - pci_read_config_dword(amd_chipset.smbus_dev, - AB_REG_BAR_SB700, &addr); - outl(AX_INDXC, AB_INDX(addr)); - outl(0x40, AB_DATA(addr)); - outl(AX_DATAC, AB_INDX(addr)); - val = inl(AB_DATA(addr)); - } else { - spin_unlock_irqrestore(&amd_lock, flags); - return; - } - - if (disable) { - val &= ~0x08; - val |= (1 << 4) | (1 << 9); - } else { - val |= 0x08; - val &= ~((1 << 4) | (1 << 9)); - } - outl_p(val, AB_DATA(addr)); - - if (!amd_chipset.nb_dev) { - spin_unlock_irqrestore(&amd_lock, flags); - return; - } - - if (amd_chipset.nb_type == 1 || amd_chipset.nb_type == 3) { - addr = PCIE_P_CNTL; - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_ADDR, addr); - pci_read_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, &val); - - val &= ~(1 | (1 << 3) | (1 << 4) | (1 << 9) | (1 << 12)); - val |= bit | (bit << 3) | (bit << 12); - val |= ((!bit) << 4) | ((!bit) << 9); - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, val); - - addr = BIF_NB; - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_ADDR, addr); - pci_read_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, &val); - val &= ~(1 << 8); - val |= bit << 8; - - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, val); - } else if (amd_chipset.nb_type == 2) { - addr = NB_PIF0_PWRDOWN_0; - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_ADDR, addr); - pci_read_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, &val); - if (disable) - val &= ~(0x3f << 7); - else - val |= 0x3f << 7; - - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, val); - - addr = NB_PIF0_PWRDOWN_1; - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_ADDR, addr); - pci_read_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, &val); - if (disable) - val &= ~(0x3f << 7); - else - val |= 0x3f << 7; - - pci_write_config_dword(amd_chipset.nb_dev, - NB_PCIE_INDX_DATA, val); - } - - spin_unlock_irqrestore(&amd_lock, flags); - return; -} - -void usb_amd_quirk_pll_disable(void) -{ - usb_amd_quirk_pll(1); -} -EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_disable); - -void usb_amd_quirk_pll_enable(void) -{ - usb_amd_quirk_pll(0); -} -EXPORT_SYMBOL_GPL(usb_amd_quirk_pll_enable); - -void usb_amd_dev_put(void) -{ - struct pci_dev *nb, *smbus; - unsigned long flags; - - spin_lock_irqsave(&amd_lock, flags); - - amd_chipset.probe_count--; - if (amd_chipset.probe_count > 0) { - spin_unlock_irqrestore(&amd_lock, flags); - return; - } - - /* save them to pci_dev_put outside of spinlock */ - nb = amd_chipset.nb_dev; - smbus = amd_chipset.smbus_dev; - - amd_chipset.nb_dev = NULL; - amd_chipset.smbus_dev = NULL; - amd_chipset.nb_type = 0; - memset(&amd_chipset.sb_type, 0, sizeof(amd_chipset.sb_type)); - amd_chipset.isoc_reqs = 0; - amd_chipset.probe_result = 0; - - spin_unlock_irqrestore(&amd_lock, flags); - - pci_dev_put(nb); - pci_dev_put(smbus); -} -EXPORT_SYMBOL_GPL(usb_amd_dev_put); - -/* - * Make sure the controller is completely inactive, unable to - * generate interrupts or do DMA. - */ -void uhci_reset_hc(struct pci_dev *pdev, unsigned long base) -{ - /* Turn off PIRQ enable and SMI enable. (This also turns off the - * BIOS's USB Legacy Support.) Turn off all the R/WC bits too. - */ - pci_write_config_word(pdev, UHCI_USBLEGSUP, UHCI_USBLEGSUP_RWC); - - /* Reset the HC - this will force us to get a - * new notification of any already connected - * ports due to the virtual disconnect that it - * implies. - */ - outw(UHCI_USBCMD_HCRESET, base + UHCI_USBCMD); - mb(); - udelay(5); - if (inw(base + UHCI_USBCMD) & UHCI_USBCMD_HCRESET) - dev_warn(&pdev->dev, "HCRESET not completed yet!\n"); - - /* Just to be safe, disable interrupt requests and - * make sure the controller is stopped. - */ - outw(0, base + UHCI_USBINTR); - outw(0, base + UHCI_USBCMD); -} -EXPORT_SYMBOL_GPL(uhci_reset_hc); - -/* - * Initialize a controller that was newly discovered or has just been - * resumed. In either case we can't be sure of its previous state. - * - * Returns: 1 if the controller was reset, 0 otherwise. - */ -int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base) -{ - u16 legsup; - unsigned int cmd, intr; - - /* - * When restarting a suspended controller, we expect all the - * settings to be the same as we left them: - * - * PIRQ and SMI disabled, no R/W bits set in USBLEGSUP; - * Controller is stopped and configured with EGSM set; - * No interrupts enabled except possibly Resume Detect. - * - * If any of these conditions are violated we do a complete reset. - */ - pci_read_config_word(pdev, UHCI_USBLEGSUP, &legsup); - if (legsup & ~(UHCI_USBLEGSUP_RO | UHCI_USBLEGSUP_RWC)) { - dev_dbg(&pdev->dev, "%s: legsup = 0x%04x\n", - __func__, legsup); - goto reset_needed; - } - - cmd = inw(base + UHCI_USBCMD); - if ((cmd & UHCI_USBCMD_RUN) || !(cmd & UHCI_USBCMD_CONFIGURE) || - !(cmd & UHCI_USBCMD_EGSM)) { - dev_dbg(&pdev->dev, "%s: cmd = 0x%04x\n", - __func__, cmd); - goto reset_needed; - } - - intr = inw(base + UHCI_USBINTR); - if (intr & (~UHCI_USBINTR_RESUME)) { - dev_dbg(&pdev->dev, "%s: intr = 0x%04x\n", - __func__, intr); - goto reset_needed; - } - return 0; - -reset_needed: - dev_dbg(&pdev->dev, "Performing full reset\n"); - uhci_reset_hc(pdev, base); - return 1; -} -EXPORT_SYMBOL_GPL(uhci_check_and_reset_hc); - -static inline int io_type_enabled(struct pci_dev *pdev, unsigned int mask) -{ - u16 cmd; - return !pci_read_config_word(pdev, PCI_COMMAND, &cmd) && (cmd & mask); -} - -#define pio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_IO) -#define mmio_enabled(dev) io_type_enabled(dev, PCI_COMMAND_MEMORY) - -static void quirk_usb_handoff_uhci(struct pci_dev *pdev) -{ - unsigned long base = 0; - int i; - - if (!pio_enabled(pdev)) - return; - - for (i = 0; i < PCI_ROM_RESOURCE; i++) - if ((pci_resource_flags(pdev, i) & IORESOURCE_IO)) { - base = pci_resource_start(pdev, i); - break; - } - - if (base) - uhci_check_and_reset_hc(pdev, base); -} - -static int mmio_resource_enabled(struct pci_dev *pdev, int idx) -{ - return pci_resource_start(pdev, idx) && mmio_enabled(pdev); -} - -static void quirk_usb_handoff_ohci(struct pci_dev *pdev) -{ - void __iomem *base; - u32 control; - u32 fminterval = 0; - bool no_fminterval = false; - int cnt; - - if (!mmio_resource_enabled(pdev, 0)) - return; - - base = pci_ioremap_bar(pdev, 0); - if (base == NULL) - return; - - /* - * ULi M5237 OHCI controller locks the whole system when accessing - * the OHCI_FMINTERVAL offset. - */ - if (pdev->vendor == PCI_VENDOR_ID_AL && pdev->device == 0x5237) - no_fminterval = true; - - control = readl(base + OHCI_CONTROL); - -/* On PA-RISC, PDC can leave IR set incorrectly; ignore it there. */ -#ifdef __hppa__ -#define OHCI_CTRL_MASK (OHCI_CTRL_RWC | OHCI_CTRL_IR) -#else -#define OHCI_CTRL_MASK OHCI_CTRL_RWC - - if (control & OHCI_CTRL_IR) { - int wait_time = 500; /* arbitrary; 5 seconds */ - writel(OHCI_INTR_OC, base + OHCI_INTRENABLE); - writel(OHCI_OCR, base + OHCI_CMDSTATUS); - while (wait_time > 0 && - readl(base + OHCI_CONTROL) & OHCI_CTRL_IR) { - wait_time -= 10; - msleep(10); - } - if (wait_time <= 0) - dev_warn(&pdev->dev, - "OHCI: BIOS handoff failed (BIOS bug?) %08x\n", - readl(base + OHCI_CONTROL)); - } -#endif - - /* disable interrupts */ - writel((u32) ~0, base + OHCI_INTRDISABLE); - - /* Reset the USB bus, if the controller isn't already in RESET */ - if (control & OHCI_HCFS) { - /* Go into RESET, preserving RWC (and possibly IR) */ - writel(control & OHCI_CTRL_MASK, base + OHCI_CONTROL); - readl(base + OHCI_CONTROL); - - /* drive bus reset for at least 50 ms (7.1.7.5) */ - msleep(50); - } - - /* software reset of the controller, preserving HcFmInterval */ - if (!no_fminterval) - fminterval = readl(base + OHCI_FMINTERVAL); - - writel(OHCI_HCR, base + OHCI_CMDSTATUS); - - /* reset requires max 10 us delay */ - for (cnt = 30; cnt > 0; --cnt) { /* ... allow extra time */ - if ((readl(base + OHCI_CMDSTATUS) & OHCI_HCR) == 0) - break; - udelay(1); - } - - if (!no_fminterval) - writel(fminterval, base + OHCI_FMINTERVAL); - - /* Now the controller is safely in SUSPEND and nothing can wake it up */ - iounmap(base); -} - -static const struct dmi_system_id ehci_dmi_nohandoff_table[] = { - { - /* Pegatron Lucid (ExoPC) */ - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "EXOPG06411"), - DMI_MATCH(DMI_BIOS_VERSION, "Lucid-CE-133"), - }, - }, - { - /* Pegatron Lucid (Ordissimo AIRIS) */ - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "M11JB"), - DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), - }, - }, - { - /* Pegatron Lucid (Ordissimo) */ - .matches = { - DMI_MATCH(DMI_BOARD_NAME, "Ordissimo"), - DMI_MATCH(DMI_BIOS_VERSION, "Lucid-"), - }, - }, - { - /* HASEE E200 */ - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "HASEE"), - DMI_MATCH(DMI_BOARD_NAME, "E210"), - DMI_MATCH(DMI_BIOS_VERSION, "6.00"), - }, - }, - { } -}; - -static void ehci_bios_handoff(struct pci_dev *pdev, - void __iomem *op_reg_base, - u32 cap, u8 offset) -{ - int try_handoff = 1, tried_handoff = 0; - - /* - * The Pegatron Lucid tablet sporadically waits for 98 seconds trying - * the handoff on its unused controller. Skip it. - * - * The HASEE E200 hangs when the semaphore is set (bugzilla #77021). - */ - if (pdev->vendor == 0x8086 && (pdev->device == 0x283a || - pdev->device == 0x27cc)) { - if (dmi_check_system(ehci_dmi_nohandoff_table)) - try_handoff = 0; - } - - if (try_handoff && (cap & EHCI_USBLEGSUP_BIOS)) { - dev_dbg(&pdev->dev, "EHCI: BIOS handoff\n"); - -#if 0 -/* aleksey_gorelov@phoenix.com reports that some systems need SMI forced on, - * but that seems dubious in general (the BIOS left it off intentionally) - * and is known to prevent some systems from booting. so we won't do this - * unless maybe we can determine when we're on a system that needs SMI forced. - */ - /* BIOS workaround (?): be sure the pre-Linux code - * receives the SMI - */ - pci_read_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, &val); - pci_write_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, - val | EHCI_USBLEGCTLSTS_SOOE); -#endif - - /* some systems get upset if this semaphore is - * set for any other reason than forcing a BIOS - * handoff.. - */ - pci_write_config_byte(pdev, offset + 3, 1); - } - - /* if boot firmware now owns EHCI, spin till it hands it over. */ - if (try_handoff) { - int msec = 1000; - while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { - tried_handoff = 1; - msleep(10); - msec -= 10; - pci_read_config_dword(pdev, offset, &cap); - } - } - - if (cap & EHCI_USBLEGSUP_BIOS) { - /* well, possibly buggy BIOS... try to shut it down, - * and hope nothing goes too wrong - */ - if (try_handoff) - dev_warn(&pdev->dev, - "EHCI: BIOS handoff failed (BIOS bug?) %08x\n", - cap); - pci_write_config_byte(pdev, offset + 2, 0); - } - - /* just in case, always disable EHCI SMIs */ - pci_write_config_dword(pdev, offset + EHCI_USBLEGCTLSTS, 0); - - /* If the BIOS ever owned the controller then we can't expect - * any power sessions to remain intact. - */ - if (tried_handoff) - writel(0, op_reg_base + EHCI_CONFIGFLAG); -} - -static void quirk_usb_disable_ehci(struct pci_dev *pdev) -{ - void __iomem *base, *op_reg_base; - u32 hcc_params, cap, val; - u8 offset, cap_length; - int wait_time, count = 256/4; - - if (!mmio_resource_enabled(pdev, 0)) - return; - - base = pci_ioremap_bar(pdev, 0); - if (base == NULL) - return; - - cap_length = readb(base); - op_reg_base = base + cap_length; - - /* EHCI 0.96 and later may have "extended capabilities" - * spec section 5.1 explains the bios handoff, e.g. for - * booting from USB disk or using a usb keyboard - */ - hcc_params = readl(base + EHCI_HCC_PARAMS); - offset = (hcc_params >> 8) & 0xff; - while (offset && --count) { - pci_read_config_dword(pdev, offset, &cap); - - switch (cap & 0xff) { - case 1: - ehci_bios_handoff(pdev, op_reg_base, cap, offset); - break; - case 0: /* Illegal reserved cap, set cap=0 so we exit */ - cap = 0; /* then fallthrough... */ - default: - dev_warn(&pdev->dev, - "EHCI: unrecognized capability %02x\n", - cap & 0xff); - } - offset = (cap >> 8) & 0xff; - } - if (!count) - dev_printk(KERN_DEBUG, &pdev->dev, "EHCI: capability loop?\n"); - - /* - * halt EHCI & disable its interrupts in any case - */ - val = readl(op_reg_base + EHCI_USBSTS); - if ((val & EHCI_USBSTS_HALTED) == 0) { - val = readl(op_reg_base + EHCI_USBCMD); - val &= ~EHCI_USBCMD_RUN; - writel(val, op_reg_base + EHCI_USBCMD); - - wait_time = 2000; - do { - writel(0x3f, op_reg_base + EHCI_USBSTS); - udelay(100); - wait_time -= 100; - val = readl(op_reg_base + EHCI_USBSTS); - if ((val == ~(u32)0) || (val & EHCI_USBSTS_HALTED)) { - break; - } - } while (wait_time > 0); - } - writel(0, op_reg_base + EHCI_USBINTR); - writel(0x3f, op_reg_base + EHCI_USBSTS); - - iounmap(base); -} - -/* - * handshake - spin reading a register until handshake completes - * @ptr: address of hc register to be read - * @mask: bits to look at in result of read - * @done: value of those bits when handshake succeeds - * @wait_usec: timeout in microseconds - * @delay_usec: delay in microseconds to wait between polling - * - * Polls a register every delay_usec microseconds. - * Returns 0 when the mask bits have the value done. - * Returns -ETIMEDOUT if this condition is not true after - * wait_usec microseconds have passed. - */ -static int handshake(void __iomem *ptr, u32 mask, u32 done, - int wait_usec, int delay_usec) -{ - u32 result; - - do { - result = readl(ptr); - result &= mask; - if (result == done) - return 0; - udelay(delay_usec); - wait_usec -= delay_usec; - } while (wait_usec > 0); - return -ETIMEDOUT; -} - -/* - * Intel's Panther Point chipset has two host controllers (EHCI and xHCI) that - * share some number of ports. These ports can be switched between either - * controller. Not all of the ports under the EHCI host controller may be - * switchable. - * - * The ports should be switched over to xHCI before PCI probes for any device - * start. This avoids active devices under EHCI being disconnected during the - * port switchover, which could cause loss of data on USB storage devices, or - * failed boot when the root file system is on a USB mass storage device and is - * enumerated under EHCI first. - * - * We write into the xHC's PCI configuration space in some Intel-specific - * registers to switch the ports over. The USB 3.0 terminations and the USB - * 2.0 data wires are switched separately. We want to enable the SuperSpeed - * terminations before switching the USB 2.0 wires over, so that USB 3.0 - * devices connect at SuperSpeed, rather than at USB 2.0 speeds. - */ -void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev) -{ - u32 ports_available; - bool ehci_found = false; - struct pci_dev *companion = NULL; - - /* Sony VAIO t-series with subsystem device ID 90a8 is not capable of - * switching ports from EHCI to xHCI - */ - if (xhci_pdev->subsystem_vendor == PCI_VENDOR_ID_SONY && - xhci_pdev->subsystem_device == 0x90a8) - return; - - /* make sure an intel EHCI controller exists */ - for_each_pci_dev(companion) { - if (companion->class == PCI_CLASS_SERIAL_USB_EHCI && - companion->vendor == PCI_VENDOR_ID_INTEL) { - ehci_found = true; - break; - } - } - - if (!ehci_found) - return; - - /* Don't switchover the ports if the user hasn't compiled the xHCI - * driver. Otherwise they will see "dead" USB ports that don't power - * the devices. - */ - if (!IS_ENABLED(CONFIG_USB_XHCI_HCD)) { - dev_warn(&xhci_pdev->dev, - "CONFIG_USB_XHCI_HCD is turned off, defaulting to EHCI.\n"); - dev_warn(&xhci_pdev->dev, - "USB 3.0 devices will work at USB 2.0 speeds.\n"); - usb_disable_xhci_ports(xhci_pdev); - return; - } - - /* Read USB3PRM, the USB 3.0 Port Routing Mask Register - * Indicate the ports that can be changed from OS. - */ - pci_read_config_dword(xhci_pdev, USB_INTEL_USB3PRM, - &ports_available); - - dev_dbg(&xhci_pdev->dev, "Configurable ports to enable SuperSpeed: 0x%x\n", - ports_available); - - /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable - * Register, to turn on SuperSpeed terminations for the - * switchable ports. - */ - pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, - ports_available); - - pci_read_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, - &ports_available); - dev_dbg(&xhci_pdev->dev, - "USB 3.0 ports that are now enabled under xHCI: 0x%x\n", - ports_available); - - /* Read XUSB2PRM, xHCI USB 2.0 Port Routing Mask Register - * Indicate the USB 2.0 ports to be controlled by the xHCI host. - */ - - pci_read_config_dword(xhci_pdev, USB_INTEL_USB2PRM, - &ports_available); - - dev_dbg(&xhci_pdev->dev, "Configurable USB 2.0 ports to hand over to xCHI: 0x%x\n", - ports_available); - - /* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to - * switch the USB 2.0 power and data lines over to the xHCI - * host. - */ - pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, - ports_available); - - pci_read_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, - &ports_available); - dev_dbg(&xhci_pdev->dev, - "USB 2.0 ports that are now switched over to xHCI: 0x%x\n", - ports_available); -} -EXPORT_SYMBOL_GPL(usb_enable_intel_xhci_ports); - -void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) -{ - pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN, 0x0); - pci_write_config_dword(xhci_pdev, USB_INTEL_XUSB2PR, 0x0); -} -EXPORT_SYMBOL_GPL(usb_disable_xhci_ports); - -/** - * PCI Quirks for xHCI. - * - * Takes care of the handoff between the Pre-OS (i.e. BIOS) and the OS. - * It signals to the BIOS that the OS wants control of the host controller, - * and then waits 1 second for the BIOS to hand over control. - * If we timeout, assume the BIOS is broken and take control anyway. - */ -static void quirk_usb_handoff_xhci(struct pci_dev *pdev) -{ - void __iomem *base; - int ext_cap_offset; - void __iomem *op_reg_base; - u32 val; - int timeout; - int len = pci_resource_len(pdev, 0); - - if (!mmio_resource_enabled(pdev, 0)) - return; - - base = ioremap_nocache(pci_resource_start(pdev, 0), len); - if (base == NULL) - return; - - /* - * Find the Legacy Support Capability register - - * this is optional for xHCI host controllers. - */ - ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET); - do { - if ((ext_cap_offset + sizeof(val)) > len) { - /* We're reading garbage from the controller */ - dev_warn(&pdev->dev, - "xHCI controller failing to respond"); - return; - } - - if (!ext_cap_offset) - /* We've reached the end of the extended capabilities */ - goto hc_init; - - val = readl(base + ext_cap_offset); - if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY) - break; - ext_cap_offset = xhci_find_next_cap_offset(base, ext_cap_offset); - } while (1); - - /* If the BIOS owns the HC, signal that the OS wants it, and wait */ - if (val & XHCI_HC_BIOS_OWNED) { - writel(val | XHCI_HC_OS_OWNED, base + ext_cap_offset); - - /* Wait for 1 second with 10 microsecond polling interval */ - timeout = handshake(base + ext_cap_offset, XHCI_HC_BIOS_OWNED, - 0, 1000000, 10); - - /* Assume a buggy BIOS and take HC ownership anyway */ - if (timeout) { - dev_warn(&pdev->dev, - "xHCI BIOS handoff failed (BIOS bug ?) %08x\n", - val); - writel(val & ~XHCI_HC_BIOS_OWNED, base + ext_cap_offset); - } - } - - val = readl(base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); - /* Mask off (turn off) any enabled SMIs */ - val &= XHCI_LEGACY_DISABLE_SMI; - /* Mask all SMI events bits, RW1C */ - val |= XHCI_LEGACY_SMI_EVENTS; - /* Disable any BIOS SMIs and clear all SMI events*/ - writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET); - -hc_init: - if (pdev->vendor == PCI_VENDOR_ID_INTEL) - usb_enable_intel_xhci_ports(pdev); - - op_reg_base = base + XHCI_HC_LENGTH(readl(base)); - - /* Wait for the host controller to be ready before writing any - * operational or runtime registers. Wait 5 seconds and no more. - */ - timeout = handshake(op_reg_base + XHCI_STS_OFFSET, XHCI_STS_CNR, 0, - 5000000, 10); - /* Assume a buggy HC and start HC initialization anyway */ - if (timeout) { - val = readl(op_reg_base + XHCI_STS_OFFSET); - dev_warn(&pdev->dev, - "xHCI HW not ready after 5 sec (HC bug?) status = 0x%x\n", - val); - } - - /* Send the halt and disable interrupts command */ - val = readl(op_reg_base + XHCI_CMD_OFFSET); - val &= ~(XHCI_CMD_RUN | XHCI_IRQS); - writel(val, op_reg_base + XHCI_CMD_OFFSET); - - /* Wait for the HC to halt - poll every 125 usec (one microframe). */ - timeout = handshake(op_reg_base + XHCI_STS_OFFSET, XHCI_STS_HALT, 1, - XHCI_MAX_HALT_USEC, 125); - if (timeout) { - val = readl(op_reg_base + XHCI_STS_OFFSET); - dev_warn(&pdev->dev, - "xHCI HW did not halt within %d usec status = 0x%x\n", - XHCI_MAX_HALT_USEC, val); - } - - iounmap(base); -} - -static void quirk_usb_early_handoff(struct pci_dev *pdev) -{ - /* Skip Netlogic mips SoC's internal PCI USB controller. - * This device does not need/support EHCI/OHCI handoff - */ - if (pdev->vendor == 0x184e) /* vendor Netlogic */ - return; - if (pdev->class != PCI_CLASS_SERIAL_USB_UHCI && - pdev->class != PCI_CLASS_SERIAL_USB_OHCI && - pdev->class != PCI_CLASS_SERIAL_USB_EHCI && - pdev->class != PCI_CLASS_SERIAL_USB_XHCI) - return; - - if (pci_enable_device(pdev) < 0) { - dev_warn(&pdev->dev, - "Can't enable PCI device, BIOS handoff failed.\n"); - return; - } - if (pdev->class == PCI_CLASS_SERIAL_USB_UHCI) - quirk_usb_handoff_uhci(pdev); - else if (pdev->class == PCI_CLASS_SERIAL_USB_OHCI) - quirk_usb_handoff_ohci(pdev); - else if (pdev->class == PCI_CLASS_SERIAL_USB_EHCI) - quirk_usb_disable_ehci(pdev); - else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) - quirk_usb_handoff_xhci(pdev); - pci_disable_device(pdev); -} -DECLARE_PCI_FIXUP_CLASS_FINAL(PCI_ANY_ID, PCI_ANY_ID, - PCI_CLASS_SERIAL_USB, 8, quirk_usb_early_handoff); diff --git a/addons/ehci-pci/src/4.4.180/pci-quirks.h b/addons/ehci-pci/src/4.4.180/pci-quirks.h deleted file mode 100644 index c622ddf2..00000000 --- a/addons/ehci-pci/src/4.4.180/pci-quirks.h +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef __LINUX_USB_PCI_QUIRKS_H -#define __LINUX_USB_PCI_QUIRKS_H - -#ifdef CONFIG_PCI -void uhci_reset_hc(struct pci_dev *pdev, unsigned long base); -int uhci_check_and_reset_hc(struct pci_dev *pdev, unsigned long base); -int usb_amd_find_chipset_info(void); -int usb_hcd_amd_remote_wakeup_quirk(struct pci_dev *pdev); -bool usb_amd_hang_symptom_quirk(void); -bool usb_amd_prefetch_quirk(void); -void usb_amd_dev_put(void); -void usb_amd_quirk_pll_disable(void); -void usb_amd_quirk_pll_enable(void); -void usb_enable_intel_xhci_ports(struct pci_dev *xhci_pdev); -void usb_disable_xhci_ports(struct pci_dev *xhci_pdev); -void sb800_prefetch(struct device *dev, int on); -#else -struct pci_dev; -static inline void usb_amd_quirk_pll_disable(void) {} -static inline void usb_amd_quirk_pll_enable(void) {} -static inline void usb_amd_dev_put(void) {} -static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {} -static inline void sb800_prefetch(struct device *dev, int on) {} -#endif /* CONFIG_PCI */ - -#endif /* __LINUX_USB_PCI_QUIRKS_H */ diff --git a/addons/ehci-pci/src/4.4.180/xhci-ext-caps.h b/addons/ehci-pci/src/4.4.180/xhci-ext-caps.h deleted file mode 100644 index 9fe3225e..00000000 --- a/addons/ehci-pci/src/4.4.180/xhci-ext-caps.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * xHCI host controller driver - * - * Copyright (C) 2008 Intel Corp. - * - * Author: Sarah Sharp - * Some code borrowed from the Linux EHCI driver. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY - * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ -/* Up to 16 ms to halt an HC */ -#define XHCI_MAX_HALT_USEC (16*1000) -/* HC not running - set to 1 when run/stop bit is cleared. */ -#define XHCI_STS_HALT (1<<0) - -/* HCCPARAMS offset from PCI base address */ -#define XHCI_HCC_PARAMS_OFFSET 0x10 -/* HCCPARAMS contains the first extended capability pointer */ -#define XHCI_HCC_EXT_CAPS(p) (((p)>>16)&0xffff) - -/* Command and Status registers offset from the Operational Registers address */ -#define XHCI_CMD_OFFSET 0x00 -#define XHCI_STS_OFFSET 0x04 - -#define XHCI_MAX_EXT_CAPS 50 - -/* Capability Register */ -/* bits 7:0 - how long is the Capabilities register */ -#define XHCI_HC_LENGTH(p) (((p)>>00)&0x00ff) - -/* Extended capability register fields */ -#define XHCI_EXT_CAPS_ID(p) (((p)>>0)&0xff) -#define XHCI_EXT_CAPS_NEXT(p) (((p)>>8)&0xff) -#define XHCI_EXT_CAPS_VAL(p) ((p)>>16) -/* Extended capability IDs - ID 0 reserved */ -#define XHCI_EXT_CAPS_LEGACY 1 -#define XHCI_EXT_CAPS_PROTOCOL 2 -#define XHCI_EXT_CAPS_PM 3 -#define XHCI_EXT_CAPS_VIRT 4 -#define XHCI_EXT_CAPS_ROUTE 5 -/* IDs 6-9 reserved */ -#define XHCI_EXT_CAPS_DEBUG 10 -/* USB Legacy Support Capability - section 7.1.1 */ -#define XHCI_HC_BIOS_OWNED (1 << 16) -#define XHCI_HC_OS_OWNED (1 << 24) - -/* USB Legacy Support Capability - section 7.1.1 */ -/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */ -#define XHCI_LEGACY_SUPPORT_OFFSET (0x00) - -/* USB Legacy Support Control and Status Register - section 7.1.2 */ -/* Add this offset, plus the value of xECP in HCCPARAMS to the base address */ -#define XHCI_LEGACY_CONTROL_OFFSET (0x04) -/* bits 1:3, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */ -#define XHCI_LEGACY_DISABLE_SMI ((0x7 << 1) + (0xff << 5) + (0x7 << 17)) -#define XHCI_LEGACY_SMI_EVENTS (0x7 << 29) - -/* USB 2.0 xHCI 0.96 L1C capability - section 7.2.2.1.3.2 */ -#define XHCI_L1C (1 << 16) - -/* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */ -#define XHCI_HLC (1 << 19) -#define XHCI_BLC (1 << 20) - -/* command register values to disable interrupts and halt the HC */ -/* start/stop HC execution - do not write unless HC is halted*/ -#define XHCI_CMD_RUN (1 << 0) -/* Event Interrupt Enable - get irq when EINT bit is set in USBSTS register */ -#define XHCI_CMD_EIE (1 << 2) -/* Host System Error Interrupt Enable - get irq when HSEIE bit set in USBSTS */ -#define XHCI_CMD_HSEIE (1 << 3) -/* Enable Wrap Event - '1' means xHC generates an event when MFINDEX wraps. */ -#define XHCI_CMD_EWE (1 << 10) - -#define XHCI_IRQS (XHCI_CMD_EIE | XHCI_CMD_HSEIE | XHCI_CMD_EWE) - -/* true: Controller Not Ready to accept doorbell or op reg writes after reset */ -#define XHCI_STS_CNR (1 << 11) - -#include - -/** - * Return the next extended capability pointer register. - * - * @base PCI register base address. - * - * @ext_offset Offset of the 32-bit register that contains the extended - * capabilites pointer. If searching for the first extended capability, pass - * in XHCI_HCC_PARAMS_OFFSET. If searching for the next extended capability, - * pass in the offset of the current extended capability register. - * - * Returns 0 if there is no next extended capability register or returns the register offset - * from the PCI registers base address. - */ -static inline int xhci_find_next_cap_offset(void __iomem *base, int ext_offset) -{ - u32 next; - - next = readl(base + ext_offset); - - if (ext_offset == XHCI_HCC_PARAMS_OFFSET) { - /* Find the first extended capability */ - next = XHCI_HCC_EXT_CAPS(next); - ext_offset = 0; - } else { - /* Find the next extended capability */ - next = XHCI_EXT_CAPS_NEXT(next); - } - - if (!next) - return 0; - /* - * Address calculation from offset of extended capabilities - * (or HCCPARAMS) register - see section 5.3.6 and section 7. - */ - return ext_offset + (next << 2); -} - -/** - * Find the offset of the extended capabilities with capability ID id. - * - * @base PCI MMIO registers base address. - * @ext_offset Offset from base of the first extended capability to look at, - * or the address of HCCPARAMS. - * @id Extended capability ID to search for. - * - * This uses an arbitrary limit of XHCI_MAX_EXT_CAPS extended capabilities - * to make sure that the list doesn't contain a loop. - */ -static inline int xhci_find_ext_cap_by_id(void __iomem *base, int ext_offset, int id) -{ - u32 val; - int limit = XHCI_MAX_EXT_CAPS; - - while (ext_offset && limit > 0) { - val = readl(base + ext_offset); - if (XHCI_EXT_CAPS_ID(val) == id) - break; - ext_offset = xhci_find_next_cap_offset(base, ext_offset); - limit--; - } - if (limit > 0) - return ext_offset; - return 0; -} diff --git a/addons/mpt3sas/install.sh b/addons/mpt3sas/install.sh deleted file mode 100644 index 89e48b44..00000000 --- a/addons/mpt3sas/install.sh +++ /dev/null @@ -1,4 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Installing module for LSI MPT Fusion SAS 3.0 Device adapter" - ${INSMOD} "/modules/mpt3sas.ko" ${PARAMS} -fi diff --git a/addons/mpt3sas/manifest.yml b/addons/mpt3sas/manifest.yml deleted file mode 100644 index 5fae0962..00000000 --- a/addons/mpt3sas/manifest.yml +++ /dev/null @@ -1,29 +0,0 @@ -version: 1 -name: mpt3sas -description: "Driver for LSI MPT Fusion SAS 3.0 Device" -available-for: - bromolow-3.10.108: - install-script: &script "install.sh" - modules: true - apollolake-4.4.180: - install-script: *script - modules: true - broadwell-4.4.180: - install-script: *script - modules: true - broadwellnk-4.4.180: - install-script: *script - modules: true - denverton-4.4.180: - install-script: *script - modules: true - geminilake-4.4.180: - install-script: *script - modules: true - v1000-4.4.180: - install-script: *script - modules: true - purley-4.4.180: - install-script: *script - modules: true - diff --git a/addons/mpt3sas/src/3.10.108/Makefile b/addons/mpt3sas/src/3.10.108/Makefile deleted file mode 100644 index 9f013afc..00000000 --- a/addons/mpt3sas/src/3.10.108/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -obj-m += mpt3sas.o -mpt3sas-y += mpt3sas_base.o \ - mpt3sas_config.o \ - mpt3sas_scsih.o \ - mpt3sas_transport.o \ - mpt3sas_ctl.o \ - mpt3sas_trigger_diag.o diff --git a/addons/mpt3sas/src/3.10.108/mpi/mpi2.h b/addons/mpt3sas/src/3.10.108/mpi/mpi2.h deleted file mode 100644 index 03317ffe..00000000 --- a/addons/mpt3sas/src/3.10.108/mpi/mpi2.h +++ /dev/null @@ -1,1164 +0,0 @@ -/* - * Copyright (c) 2000-2012 LSI Corporation. - * - * - * Name: mpi2.h - * Title: MPI Message independent structures and definitions - * including System Interface Register Set and - * scatter/gather formats. - * Creation Date: June 21, 2006 - * - * mpi2.h Version: 02.00.26 - * - * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 - * prefix are for use only on MPI v2.5 products, and must not be used - * with MPI v2.0 products. Unless otherwise noted, names beginning with - * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 06-04-07 02.00.01 Bumped MPI2_HEADER_VERSION_UNIT. - * 06-26-07 02.00.02 Bumped MPI2_HEADER_VERSION_UNIT. - * 08-31-07 02.00.03 Bumped MPI2_HEADER_VERSION_UNIT. - * Moved ReplyPostHostIndex register to offset 0x6C of the - * MPI2_SYSTEM_INTERFACE_REGS and modified the define for - * MPI2_REPLY_POST_HOST_INDEX_OFFSET. - * Added union of request descriptors. - * Added union of reply descriptors. - * 10-31-07 02.00.04 Bumped MPI2_HEADER_VERSION_UNIT. - * Added define for MPI2_VERSION_02_00. - * Fixed the size of the FunctionDependent5 field in the - * MPI2_DEFAULT_REPLY structure. - * 12-18-07 02.00.05 Bumped MPI2_HEADER_VERSION_UNIT. - * Removed the MPI-defined Fault Codes and extended the - * product specific codes up to 0xEFFF. - * Added a sixth key value for the WriteSequence register - * and changed the flush value to 0x0. - * Added message function codes for Diagnostic Buffer Post - * and Diagnsotic Release. - * New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED - * Moved MPI2_VERSION_UNION from mpi2_ioc.h. - * 02-29-08 02.00.06 Bumped MPI2_HEADER_VERSION_UNIT. - * 03-03-08 02.00.07 Bumped MPI2_HEADER_VERSION_UNIT. - * 05-21-08 02.00.08 Bumped MPI2_HEADER_VERSION_UNIT. - * Added #defines for marking a reply descriptor as unused. - * 06-27-08 02.00.09 Bumped MPI2_HEADER_VERSION_UNIT. - * 10-02-08 02.00.10 Bumped MPI2_HEADER_VERSION_UNIT. - * Moved LUN field defines from mpi2_init.h. - * 01-19-09 02.00.11 Bumped MPI2_HEADER_VERSION_UNIT. - * 05-06-09 02.00.12 Bumped MPI2_HEADER_VERSION_UNIT. - * In all request and reply descriptors, replaced VF_ID - * field with MSIxIndex field. - * Removed DevHandle field from - * MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those - * bytes reserved. - * Added RAID Accelerator functionality. - * 07-30-09 02.00.13 Bumped MPI2_HEADER_VERSION_UNIT. - * 10-28-09 02.00.14 Bumped MPI2_HEADER_VERSION_UNIT. - * Added MSI-x index mask and shift for Reply Post Host - * Index register. - * Added function code for Host Based Discovery Action. - * 02-10-10 02.00.15 Bumped MPI2_HEADER_VERSION_UNIT. - * Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL. - * Added defines for product-specific range of message - * function codes, 0xF0 to 0xFF. - * 05-12-10 02.00.16 Bumped MPI2_HEADER_VERSION_UNIT. - * Added alternative defines for the SGE Direction bit. - * 08-11-10 02.00.17 Bumped MPI2_HEADER_VERSION_UNIT. - * 11-10-10 02.00.18 Bumped MPI2_HEADER_VERSION_UNIT. - * Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define. - * 02-23-11 02.00.19 Bumped MPI2_HEADER_VERSION_UNIT. - * Added MPI2_FUNCTION_SEND_HOST_MESSAGE. - * 03-09-11 02.00.20 Bumped MPI2_HEADER_VERSION_UNIT. - * 05-25-11 02.00.21 Bumped MPI2_HEADER_VERSION_UNIT. - * 08-24-11 02.00.22 Bumped MPI2_HEADER_VERSION_UNIT. - * 11-18-11 02.00.23 Bumped MPI2_HEADER_VERSION_UNIT. - * Incorporating additions for MPI v2.5. - * 02-06-12 02.00.24 Bumped MPI2_HEADER_VERSION_UNIT. - * 03-29-12 02.00.25 Bumped MPI2_HEADER_VERSION_UNIT. - * Added Hard Reset delay timings. - * 07-10-12 02.00.26 Bumped MPI2_HEADER_VERSION_UNIT. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_H -#define MPI2_H - -/***************************************************************************** -* -* MPI Version Definitions -* -*****************************************************************************/ - -#define MPI2_VERSION_MAJOR_MASK (0xFF00) -#define MPI2_VERSION_MAJOR_SHIFT (8) -#define MPI2_VERSION_MINOR_MASK (0x00FF) -#define MPI2_VERSION_MINOR_SHIFT (0) - -/*major version for all MPI v2.x */ -#define MPI2_VERSION_MAJOR (0x02) - -/*minor version for MPI v2.0 compatible products */ -#define MPI2_VERSION_MINOR (0x00) -#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \ - MPI2_VERSION_MINOR) -#define MPI2_VERSION_02_00 (0x0200) - -/*minor version for MPI v2.5 compatible products */ -#define MPI25_VERSION_MINOR (0x05) -#define MPI25_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \ - MPI25_VERSION_MINOR) -#define MPI2_VERSION_02_05 (0x0205) - -/*Unit and Dev versioning for this MPI header set */ -#define MPI2_HEADER_VERSION_UNIT (0x1A) -#define MPI2_HEADER_VERSION_DEV (0x00) -#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) -#define MPI2_HEADER_VERSION_UNIT_SHIFT (8) -#define MPI2_HEADER_VERSION_DEV_MASK (0x00FF) -#define MPI2_HEADER_VERSION_DEV_SHIFT (0) -#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | \ - MPI2_HEADER_VERSION_DEV) - -/***************************************************************************** -* -* IOC State Definitions -* -*****************************************************************************/ - -#define MPI2_IOC_STATE_RESET (0x00000000) -#define MPI2_IOC_STATE_READY (0x10000000) -#define MPI2_IOC_STATE_OPERATIONAL (0x20000000) -#define MPI2_IOC_STATE_FAULT (0x40000000) - -#define MPI2_IOC_STATE_MASK (0xF0000000) -#define MPI2_IOC_STATE_SHIFT (28) - -/*Fault state range for prodcut specific codes */ -#define MPI2_FAULT_PRODUCT_SPECIFIC_MIN (0x0000) -#define MPI2_FAULT_PRODUCT_SPECIFIC_MAX (0xEFFF) - -/***************************************************************************** -* -* System Interface Register Definitions -* -*****************************************************************************/ - -typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS { - U32 Doorbell; /*0x00 */ - U32 WriteSequence; /*0x04 */ - U32 HostDiagnostic; /*0x08 */ - U32 Reserved1; /*0x0C */ - U32 DiagRWData; /*0x10 */ - U32 DiagRWAddressLow; /*0x14 */ - U32 DiagRWAddressHigh; /*0x18 */ - U32 Reserved2[5]; /*0x1C */ - U32 HostInterruptStatus; /*0x30 */ - U32 HostInterruptMask; /*0x34 */ - U32 DCRData; /*0x38 */ - U32 DCRAddress; /*0x3C */ - U32 Reserved3[2]; /*0x40 */ - U32 ReplyFreeHostIndex; /*0x48 */ - U32 Reserved4[8]; /*0x4C */ - U32 ReplyPostHostIndex; /*0x6C */ - U32 Reserved5; /*0x70 */ - U32 HCBSize; /*0x74 */ - U32 HCBAddressLow; /*0x78 */ - U32 HCBAddressHigh; /*0x7C */ - U32 Reserved6[16]; /*0x80 */ - U32 RequestDescriptorPostLow; /*0xC0 */ - U32 RequestDescriptorPostHigh; /*0xC4 */ - U32 Reserved7[14]; /*0xC8 */ -} MPI2_SYSTEM_INTERFACE_REGS, - *PTR_MPI2_SYSTEM_INTERFACE_REGS, - Mpi2SystemInterfaceRegs_t, - *pMpi2SystemInterfaceRegs_t; - -/* - *Defines for working with the Doorbell register. - */ -#define MPI2_DOORBELL_OFFSET (0x00000000) - -/*IOC --> System values */ -#define MPI2_DOORBELL_USED (0x08000000) -#define MPI2_DOORBELL_WHO_INIT_MASK (0x07000000) -#define MPI2_DOORBELL_WHO_INIT_SHIFT (24) -#define MPI2_DOORBELL_FAULT_CODE_MASK (0x0000FFFF) -#define MPI2_DOORBELL_DATA_MASK (0x0000FFFF) - -/*System --> IOC values */ -#define MPI2_DOORBELL_FUNCTION_MASK (0xFF000000) -#define MPI2_DOORBELL_FUNCTION_SHIFT (24) -#define MPI2_DOORBELL_ADD_DWORDS_MASK (0x00FF0000) -#define MPI2_DOORBELL_ADD_DWORDS_SHIFT (16) - -/* - *Defines for the WriteSequence register - */ -#define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004) -#define MPI2_WRSEQ_KEY_VALUE_MASK (0x0000000F) -#define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0) -#define MPI2_WRSEQ_1ST_KEY_VALUE (0xF) -#define MPI2_WRSEQ_2ND_KEY_VALUE (0x4) -#define MPI2_WRSEQ_3RD_KEY_VALUE (0xB) -#define MPI2_WRSEQ_4TH_KEY_VALUE (0x2) -#define MPI2_WRSEQ_5TH_KEY_VALUE (0x7) -#define MPI2_WRSEQ_6TH_KEY_VALUE (0xD) - -/* - *Defines for the HostDiagnostic register - */ -#define MPI2_HOST_DIAGNOSTIC_OFFSET (0x00000008) - -#define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK (0x00001800) -#define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT (0x00000000) -#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW (0x00000800) - -#define MPI2_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400) -#define MPI2_DIAG_FORCE_HCB_ON_RESET (0x00000200) -#define MPI2_DIAG_HCB_MODE (0x00000100) -#define MPI2_DIAG_DIAG_WRITE_ENABLE (0x00000080) -#define MPI2_DIAG_FLASH_BAD_SIG (0x00000040) -#define MPI2_DIAG_RESET_HISTORY (0x00000020) -#define MPI2_DIAG_DIAG_RW_ENABLE (0x00000010) -#define MPI2_DIAG_RESET_ADAPTER (0x00000004) -#define MPI2_DIAG_HOLD_IOC_RESET (0x00000002) - -/* - *Offsets for DiagRWData and address - */ -#define MPI2_DIAG_RW_DATA_OFFSET (0x00000010) -#define MPI2_DIAG_RW_ADDRESS_LOW_OFFSET (0x00000014) -#define MPI2_DIAG_RW_ADDRESS_HIGH_OFFSET (0x00000018) - -/* - *Defines for the HostInterruptStatus register - */ -#define MPI2_HOST_INTERRUPT_STATUS_OFFSET (0x00000030) -#define MPI2_HIS_SYS2IOC_DB_STATUS (0x80000000) -#define MPI2_HIS_IOP_DOORBELL_STATUS MPI2_HIS_SYS2IOC_DB_STATUS -#define MPI2_HIS_RESET_IRQ_STATUS (0x40000000) -#define MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT (0x00000008) -#define MPI2_HIS_IOC2SYS_DB_STATUS (0x00000001) -#define MPI2_HIS_DOORBELL_INTERRUPT MPI2_HIS_IOC2SYS_DB_STATUS - -/* - *Defines for the HostInterruptMask register - */ -#define MPI2_HOST_INTERRUPT_MASK_OFFSET (0x00000034) -#define MPI2_HIM_RESET_IRQ_MASK (0x40000000) -#define MPI2_HIM_REPLY_INT_MASK (0x00000008) -#define MPI2_HIM_RIM MPI2_HIM_REPLY_INT_MASK -#define MPI2_HIM_IOC2SYS_DB_MASK (0x00000001) -#define MPI2_HIM_DIM MPI2_HIM_IOC2SYS_DB_MASK - -/* - *Offsets for DCRData and address - */ -#define MPI2_DCR_DATA_OFFSET (0x00000038) -#define MPI2_DCR_ADDRESS_OFFSET (0x0000003C) - -/* - *Offset for the Reply Free Queue - */ -#define MPI2_REPLY_FREE_HOST_INDEX_OFFSET (0x00000048) - -/* - *Defines for the Reply Descriptor Post Queue - */ -#define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C) -#define MPI2_REPLY_POST_HOST_INDEX_MASK (0x00FFFFFF) -#define MPI2_RPHI_MSIX_INDEX_MASK (0xFF000000) -#define MPI2_RPHI_MSIX_INDEX_SHIFT (24) - -/* - *Defines for the HCBSize and address - */ -#define MPI2_HCB_SIZE_OFFSET (0x00000074) -#define MPI2_HCB_SIZE_SIZE_MASK (0xFFFFF000) -#define MPI2_HCB_SIZE_HCB_ENABLE (0x00000001) - -#define MPI2_HCB_ADDRESS_LOW_OFFSET (0x00000078) -#define MPI2_HCB_ADDRESS_HIGH_OFFSET (0x0000007C) - -/* - *Offsets for the Request Queue - */ -#define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET (0x000000C0) -#define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET (0x000000C4) - -/*Hard Reset delay timings */ -#define MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC (50000) -#define MPI2_HARD_RESET_PCIE_RESET_READ_WINDOW_MICRO_SEC (255000) -#define MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC (256000) - -/***************************************************************************** -* -* Message Descriptors -* -*****************************************************************************/ - -/*Request Descriptors */ - -/*Default Request Descriptor */ -typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR { - U8 RequestFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U16 LMID; /*0x04 */ - U16 DescriptorTypeDependent; /*0x06 */ -} MPI2_DEFAULT_REQUEST_DESCRIPTOR, - *PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR, - Mpi2DefaultRequestDescriptor_t, - *pMpi2DefaultRequestDescriptor_t; - -/*defines for the RequestFlags field */ -#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E) -#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00) -#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET (0x02) -#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06) -#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE (0x08) -#define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR (0x0A) -#define MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO (0x0C) - -#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01) - -/*High Priority Request Descriptor */ -typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR { - U8 RequestFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U16 LMID; /*0x04 */ - U16 Reserved1; /*0x06 */ -} MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR, - *PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR, - Mpi2HighPriorityRequestDescriptor_t, - *pMpi2HighPriorityRequestDescriptor_t; - -/*SCSI IO Request Descriptor */ -typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR { - U8 RequestFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U16 LMID; /*0x04 */ - U16 DevHandle; /*0x06 */ -} MPI2_SCSI_IO_REQUEST_DESCRIPTOR, - *PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR, - Mpi2SCSIIORequestDescriptor_t, - *pMpi2SCSIIORequestDescriptor_t; - -/*SCSI Target Request Descriptor */ -typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR { - U8 RequestFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U16 LMID; /*0x04 */ - U16 IoIndex; /*0x06 */ -} MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR, - *PTR_MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR, - Mpi2SCSITargetRequestDescriptor_t, - *pMpi2SCSITargetRequestDescriptor_t; - -/*RAID Accelerator Request Descriptor */ -typedef struct _MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR { - U8 RequestFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U16 LMID; /*0x04 */ - U16 Reserved; /*0x06 */ -} MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR, - *PTR_MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR, - Mpi2RAIDAcceleratorRequestDescriptor_t, - *pMpi2RAIDAcceleratorRequestDescriptor_t; - -/*Fast Path SCSI IO Request Descriptor */ -typedef MPI2_SCSI_IO_REQUEST_DESCRIPTOR - MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR, - *PTR_MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR, - Mpi25FastPathSCSIIORequestDescriptor_t, - *pMpi25FastPathSCSIIORequestDescriptor_t; - -/*union of Request Descriptors */ -typedef union _MPI2_REQUEST_DESCRIPTOR_UNION { - MPI2_DEFAULT_REQUEST_DESCRIPTOR Default; - MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority; - MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO; - MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget; - MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator; - MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR FastPathSCSIIO; - U64 Words; -} MPI2_REQUEST_DESCRIPTOR_UNION, - *PTR_MPI2_REQUEST_DESCRIPTOR_UNION, - Mpi2RequestDescriptorUnion_t, - *pMpi2RequestDescriptorUnion_t; - -/*Reply Descriptors */ - -/*Default Reply Descriptor */ -typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR { - U8 ReplyFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 DescriptorTypeDependent1; /*0x02 */ - U32 DescriptorTypeDependent2; /*0x04 */ -} MPI2_DEFAULT_REPLY_DESCRIPTOR, - *PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR, - Mpi2DefaultReplyDescriptor_t, - *pMpi2DefaultReplyDescriptor_t; - -/*defines for the ReplyFlags field */ -#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F) -#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00) -#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY (0x01) -#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS (0x02) -#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER (0x03) -#define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS (0x05) -#define MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS (0x06) -#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F) - -/*values for marking a reply descriptor as unused */ -#define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK (0xFFFFFFFF) -#define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK (0xFFFFFFFF) - -/*Address Reply Descriptor */ -typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR { - U8 ReplyFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U32 ReplyFrameAddress; /*0x04 */ -} MPI2_ADDRESS_REPLY_DESCRIPTOR, - *PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR, - Mpi2AddressReplyDescriptor_t, - *pMpi2AddressReplyDescriptor_t; - -#define MPI2_ADDRESS_REPLY_SMID_INVALID (0x00) - -/*SCSI IO Success Reply Descriptor */ -typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR { - U8 ReplyFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U16 TaskTag; /*0x04 */ - U16 Reserved1; /*0x06 */ -} MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, - *PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, - Mpi2SCSIIOSuccessReplyDescriptor_t, - *pMpi2SCSIIOSuccessReplyDescriptor_t; - -/*TargetAssist Success Reply Descriptor */ -typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR { - U8 ReplyFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U8 SequenceNumber; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 IoIndex; /*0x06 */ -} MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR, - *PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR, - Mpi2TargetAssistSuccessReplyDescriptor_t, - *pMpi2TargetAssistSuccessReplyDescriptor_t; - -/*Target Command Buffer Reply Descriptor */ -typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR { - U8 ReplyFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U8 VP_ID; /*0x02 */ - U8 Flags; /*0x03 */ - U16 InitiatorDevHandle; /*0x04 */ - U16 IoIndex; /*0x06 */ -} MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, - *PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, - Mpi2TargetCommandBufferReplyDescriptor_t, - *pMpi2TargetCommandBufferReplyDescriptor_t; - -/*defines for Flags field */ -#define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK (0x3F) - -/*RAID Accelerator Success Reply Descriptor */ -typedef struct _MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR { - U8 ReplyFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U32 Reserved; /*0x04 */ -} MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR, - *PTR_MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR, - Mpi2RAIDAcceleratorSuccessReplyDescriptor_t, - *pMpi2RAIDAcceleratorSuccessReplyDescriptor_t; - -/*Fast Path SCSI IO Success Reply Descriptor */ -typedef MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR - MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, - *PTR_MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, - Mpi25FastPathSCSIIOSuccessReplyDescriptor_t, - *pMpi25FastPathSCSIIOSuccessReplyDescriptor_t; - -/*union of Reply Descriptors */ -typedef union _MPI2_REPLY_DESCRIPTORS_UNION { - MPI2_DEFAULT_REPLY_DESCRIPTOR Default; - MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply; - MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess; - MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess; - MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer; - MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR RAIDAcceleratorSuccess; - MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR FastPathSCSIIOSuccess; - U64 Words; -} MPI2_REPLY_DESCRIPTORS_UNION, - *PTR_MPI2_REPLY_DESCRIPTORS_UNION, - Mpi2ReplyDescriptorsUnion_t, - *pMpi2ReplyDescriptorsUnion_t; - -/***************************************************************************** -* -* Message Functions -* -*****************************************************************************/ - -#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) -#define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01) -#define MPI2_FUNCTION_IOC_INIT (0x02) -#define MPI2_FUNCTION_IOC_FACTS (0x03) -#define MPI2_FUNCTION_CONFIG (0x04) -#define MPI2_FUNCTION_PORT_FACTS (0x05) -#define MPI2_FUNCTION_PORT_ENABLE (0x06) -#define MPI2_FUNCTION_EVENT_NOTIFICATION (0x07) -#define MPI2_FUNCTION_EVENT_ACK (0x08) -#define MPI2_FUNCTION_FW_DOWNLOAD (0x09) -#define MPI2_FUNCTION_TARGET_ASSIST (0x0B) -#define MPI2_FUNCTION_TARGET_STATUS_SEND (0x0C) -#define MPI2_FUNCTION_TARGET_MODE_ABORT (0x0D) -#define MPI2_FUNCTION_FW_UPLOAD (0x12) -#define MPI2_FUNCTION_RAID_ACTION (0x15) -#define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH (0x16) -#define MPI2_FUNCTION_TOOLBOX (0x17) -#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18) -#define MPI2_FUNCTION_SMP_PASSTHROUGH (0x1A) -#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) -#define MPI2_FUNCTION_SATA_PASSTHROUGH (0x1C) -#define MPI2_FUNCTION_DIAG_BUFFER_POST (0x1D) -#define MPI2_FUNCTION_DIAG_RELEASE (0x1E) -#define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) -#define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) -#define MPI2_FUNCTION_RAID_ACCELERATOR (0x2C) -#define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION (0x2F) -#define MPI2_FUNCTION_PWR_MGMT_CONTROL (0x30) -#define MPI2_FUNCTION_SEND_HOST_MESSAGE (0x31) -#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0) -#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC (0xFF) - -/*Doorbell functions */ -#define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET (0x40) -#define MPI2_FUNCTION_HANDSHAKE (0x42) - -/***************************************************************************** -* -* IOC Status Values -* -*****************************************************************************/ - -/*mask for IOCStatus status value */ -#define MPI2_IOCSTATUS_MASK (0x7FFF) - -/**************************************************************************** -* Common IOCStatus values for all replies -****************************************************************************/ - -#define MPI2_IOCSTATUS_SUCCESS (0x0000) -#define MPI2_IOCSTATUS_INVALID_FUNCTION (0x0001) -#define MPI2_IOCSTATUS_BUSY (0x0002) -#define MPI2_IOCSTATUS_INVALID_SGL (0x0003) -#define MPI2_IOCSTATUS_INTERNAL_ERROR (0x0004) -#define MPI2_IOCSTATUS_INVALID_VPID (0x0005) -#define MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006) -#define MPI2_IOCSTATUS_INVALID_FIELD (0x0007) -#define MPI2_IOCSTATUS_INVALID_STATE (0x0008) -#define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009) - -/**************************************************************************** -* Config IOCStatus values -****************************************************************************/ - -#define MPI2_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) -#define MPI2_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) -#define MPI2_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022) -#define MPI2_IOCSTATUS_CONFIG_INVALID_DATA (0x0023) -#define MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024) -#define MPI2_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025) - -/**************************************************************************** -* SCSI IO Reply -****************************************************************************/ - -#define MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040) -#define MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE (0x0042) -#define MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043) -#define MPI2_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044) -#define MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045) -#define MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046) -#define MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047) -#define MPI2_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048) -#define MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049) -#define MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A) -#define MPI2_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B) -#define MPI2_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) - -/**************************************************************************** -* For use by SCSI Initiator and SCSI Target end-to-end data protection -****************************************************************************/ - -#define MPI2_IOCSTATUS_EEDP_GUARD_ERROR (0x004D) -#define MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E) -#define MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F) - -/**************************************************************************** -* SCSI Target values -****************************************************************************/ - -#define MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062) -#define MPI2_IOCSTATUS_TARGET_ABORTED (0x0063) -#define MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064) -#define MPI2_IOCSTATUS_TARGET_NO_CONNECTION (0x0065) -#define MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A) -#define MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) -#define MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) -#define MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) -#define MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070) -#define MPI2_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071) - -/**************************************************************************** -* Serial Attached SCSI values -****************************************************************************/ - -#define MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) -#define MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091) - -/**************************************************************************** -* Diagnostic Buffer Post / Diagnostic Release values -****************************************************************************/ - -#define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0) - -/**************************************************************************** -* RAID Accelerator values -****************************************************************************/ - -#define MPI2_IOCSTATUS_RAID_ACCEL_ERROR (0x00B0) - -/**************************************************************************** -* IOCStatus flag to indicate that log info is available -****************************************************************************/ - -#define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000) - -/**************************************************************************** -* IOCLogInfo Types -****************************************************************************/ - -#define MPI2_IOCLOGINFO_TYPE_MASK (0xF0000000) -#define MPI2_IOCLOGINFO_TYPE_SHIFT (28) -#define MPI2_IOCLOGINFO_TYPE_NONE (0x0) -#define MPI2_IOCLOGINFO_TYPE_SCSI (0x1) -#define MPI2_IOCLOGINFO_TYPE_FC (0x2) -#define MPI2_IOCLOGINFO_TYPE_SAS (0x3) -#define MPI2_IOCLOGINFO_TYPE_ISCSI (0x4) -#define MPI2_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF) - -/***************************************************************************** -* -* Standard Message Structures -* -*****************************************************************************/ - -/**************************************************************************** -*Request Message Header for all request messages -****************************************************************************/ - -typedef struct _MPI2_REQUEST_HEADER { - U16 FunctionDependent1; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 FunctionDependent2; /*0x04 */ - U8 FunctionDependent3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ -} MPI2_REQUEST_HEADER, *PTR_MPI2_REQUEST_HEADER, - MPI2RequestHeader_t, *pMPI2RequestHeader_t; - -/**************************************************************************** -* Default Reply -****************************************************************************/ - -typedef struct _MPI2_DEFAULT_REPLY { - U16 FunctionDependent1; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 FunctionDependent2; /*0x04 */ - U8 FunctionDependent3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U16 FunctionDependent5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_DEFAULT_REPLY, *PTR_MPI2_DEFAULT_REPLY, - MPI2DefaultReply_t, *pMPI2DefaultReply_t; - -/*common version structure/union used in messages and configuration pages */ - -typedef struct _MPI2_VERSION_STRUCT { - U8 Dev; /*0x00 */ - U8 Unit; /*0x01 */ - U8 Minor; /*0x02 */ - U8 Major; /*0x03 */ -} MPI2_VERSION_STRUCT; - -typedef union _MPI2_VERSION_UNION { - MPI2_VERSION_STRUCT Struct; - U32 Word; -} MPI2_VERSION_UNION; - -/*LUN field defines, common to many structures */ -#define MPI2_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF) -#define MPI2_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000) -#define MPI2_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF) -#define MPI2_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000) -#define MPI2_LUN_LEVEL_1_WORD (0xFF00) -#define MPI2_LUN_LEVEL_1_DWORD (0x0000FF00) - -/***************************************************************************** -* -* Fusion-MPT MPI Scatter Gather Elements -* -*****************************************************************************/ - -/**************************************************************************** -* MPI Simple Element structures -****************************************************************************/ - -typedef struct _MPI2_SGE_SIMPLE32 { - U32 FlagsLength; - U32 Address; -} MPI2_SGE_SIMPLE32, *PTR_MPI2_SGE_SIMPLE32, - Mpi2SGESimple32_t, *pMpi2SGESimple32_t; - -typedef struct _MPI2_SGE_SIMPLE64 { - U32 FlagsLength; - U64 Address; -} MPI2_SGE_SIMPLE64, *PTR_MPI2_SGE_SIMPLE64, - Mpi2SGESimple64_t, *pMpi2SGESimple64_t; - -typedef struct _MPI2_SGE_SIMPLE_UNION { - U32 FlagsLength; - union { - U32 Address32; - U64 Address64; - } u; -} MPI2_SGE_SIMPLE_UNION, - *PTR_MPI2_SGE_SIMPLE_UNION, - Mpi2SGESimpleUnion_t, - *pMpi2SGESimpleUnion_t; - -/**************************************************************************** -* MPI Chain Element structures - for MPI v2.0 products only -****************************************************************************/ - -typedef struct _MPI2_SGE_CHAIN32 { - U16 Length; - U8 NextChainOffset; - U8 Flags; - U32 Address; -} MPI2_SGE_CHAIN32, *PTR_MPI2_SGE_CHAIN32, - Mpi2SGEChain32_t, *pMpi2SGEChain32_t; - -typedef struct _MPI2_SGE_CHAIN64 { - U16 Length; - U8 NextChainOffset; - U8 Flags; - U64 Address; -} MPI2_SGE_CHAIN64, *PTR_MPI2_SGE_CHAIN64, - Mpi2SGEChain64_t, *pMpi2SGEChain64_t; - -typedef struct _MPI2_SGE_CHAIN_UNION { - U16 Length; - U8 NextChainOffset; - U8 Flags; - union { - U32 Address32; - U64 Address64; - } u; -} MPI2_SGE_CHAIN_UNION, - *PTR_MPI2_SGE_CHAIN_UNION, - Mpi2SGEChainUnion_t, - *pMpi2SGEChainUnion_t; - -/**************************************************************************** -* MPI Transaction Context Element structures - for MPI v2.0 products only -****************************************************************************/ - -typedef struct _MPI2_SGE_TRANSACTION32 { - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 TransactionContext[1]; - U32 TransactionDetails[1]; -} MPI2_SGE_TRANSACTION32, - *PTR_MPI2_SGE_TRANSACTION32, - Mpi2SGETransaction32_t, - *pMpi2SGETransaction32_t; - -typedef struct _MPI2_SGE_TRANSACTION64 { - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 TransactionContext[2]; - U32 TransactionDetails[1]; -} MPI2_SGE_TRANSACTION64, - *PTR_MPI2_SGE_TRANSACTION64, - Mpi2SGETransaction64_t, - *pMpi2SGETransaction64_t; - -typedef struct _MPI2_SGE_TRANSACTION96 { - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 TransactionContext[3]; - U32 TransactionDetails[1]; -} MPI2_SGE_TRANSACTION96, *PTR_MPI2_SGE_TRANSACTION96, - Mpi2SGETransaction96_t, *pMpi2SGETransaction96_t; - -typedef struct _MPI2_SGE_TRANSACTION128 { - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 TransactionContext[4]; - U32 TransactionDetails[1]; -} MPI2_SGE_TRANSACTION128, *PTR_MPI2_SGE_TRANSACTION128, - Mpi2SGETransaction_t128, *pMpi2SGETransaction_t128; - -typedef struct _MPI2_SGE_TRANSACTION_UNION { - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - union { - U32 TransactionContext32[1]; - U32 TransactionContext64[2]; - U32 TransactionContext96[3]; - U32 TransactionContext128[4]; - } u; - U32 TransactionDetails[1]; -} MPI2_SGE_TRANSACTION_UNION, - *PTR_MPI2_SGE_TRANSACTION_UNION, - Mpi2SGETransactionUnion_t, - *pMpi2SGETransactionUnion_t; - -/**************************************************************************** -* MPI SGE union for IO SGL's - for MPI v2.0 products only -****************************************************************************/ - -typedef struct _MPI2_MPI_SGE_IO_UNION { - union { - MPI2_SGE_SIMPLE_UNION Simple; - MPI2_SGE_CHAIN_UNION Chain; - } u; -} MPI2_MPI_SGE_IO_UNION, *PTR_MPI2_MPI_SGE_IO_UNION, - Mpi2MpiSGEIOUnion_t, *pMpi2MpiSGEIOUnion_t; - -/**************************************************************************** -* MPI SGE union for SGL's with Simple and Transaction elements - for MPI v2.0 products only -****************************************************************************/ - -typedef struct _MPI2_SGE_TRANS_SIMPLE_UNION { - union { - MPI2_SGE_SIMPLE_UNION Simple; - MPI2_SGE_TRANSACTION_UNION Transaction; - } u; -} MPI2_SGE_TRANS_SIMPLE_UNION, - *PTR_MPI2_SGE_TRANS_SIMPLE_UNION, - Mpi2SGETransSimpleUnion_t, - *pMpi2SGETransSimpleUnion_t; - -/**************************************************************************** -* All MPI SGE types union -****************************************************************************/ - -typedef struct _MPI2_MPI_SGE_UNION { - union { - MPI2_SGE_SIMPLE_UNION Simple; - MPI2_SGE_CHAIN_UNION Chain; - MPI2_SGE_TRANSACTION_UNION Transaction; - } u; -} MPI2_MPI_SGE_UNION, *PTR_MPI2_MPI_SGE_UNION, - Mpi2MpiSgeUnion_t, *pMpi2MpiSgeUnion_t; - -/**************************************************************************** -* MPI SGE field definition and masks -****************************************************************************/ - -/*Flags field bit definitions */ - -#define MPI2_SGE_FLAGS_LAST_ELEMENT (0x80) -#define MPI2_SGE_FLAGS_END_OF_BUFFER (0x40) -#define MPI2_SGE_FLAGS_ELEMENT_TYPE_MASK (0x30) -#define MPI2_SGE_FLAGS_LOCAL_ADDRESS (0x08) -#define MPI2_SGE_FLAGS_DIRECTION (0x04) -#define MPI2_SGE_FLAGS_ADDRESS_SIZE (0x02) -#define MPI2_SGE_FLAGS_END_OF_LIST (0x01) - -#define MPI2_SGE_FLAGS_SHIFT (24) - -#define MPI2_SGE_LENGTH_MASK (0x00FFFFFF) -#define MPI2_SGE_CHAIN_LENGTH_MASK (0x0000FFFF) - -/*Element Type */ - -#define MPI2_SGE_FLAGS_TRANSACTION_ELEMENT (0x00) -#define MPI2_SGE_FLAGS_SIMPLE_ELEMENT (0x10) -#define MPI2_SGE_FLAGS_CHAIN_ELEMENT (0x30) -#define MPI2_SGE_FLAGS_ELEMENT_MASK (0x30) - -/*Address location */ - -#define MPI2_SGE_FLAGS_SYSTEM_ADDRESS (0x00) - -/*Direction */ - -#define MPI2_SGE_FLAGS_IOC_TO_HOST (0x00) -#define MPI2_SGE_FLAGS_HOST_TO_IOC (0x04) - -#define MPI2_SGE_FLAGS_DEST (MPI2_SGE_FLAGS_IOC_TO_HOST) -#define MPI2_SGE_FLAGS_SOURCE (MPI2_SGE_FLAGS_HOST_TO_IOC) - -/*Address Size */ - -#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING (0x00) -#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02) - -/*Context Size */ - -#define MPI2_SGE_FLAGS_32_BIT_CONTEXT (0x00) -#define MPI2_SGE_FLAGS_64_BIT_CONTEXT (0x02) -#define MPI2_SGE_FLAGS_96_BIT_CONTEXT (0x04) -#define MPI2_SGE_FLAGS_128_BIT_CONTEXT (0x06) - -#define MPI2_SGE_CHAIN_OFFSET_MASK (0x00FF0000) -#define MPI2_SGE_CHAIN_OFFSET_SHIFT (16) - -/**************************************************************************** -* MPI SGE operation Macros -****************************************************************************/ - -/*SIMPLE FlagsLength manipulations... */ -#define MPI2_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_SGE_FLAGS_SHIFT) -#define MPI2_SGE_GET_FLAGS(f) (((f) & ~MPI2_SGE_LENGTH_MASK) >> \ - MPI2_SGE_FLAGS_SHIFT) -#define MPI2_SGE_LENGTH(f) ((f) & MPI2_SGE_LENGTH_MASK) -#define MPI2_SGE_CHAIN_LENGTH(f) ((f) & MPI2_SGE_CHAIN_LENGTH_MASK) - -#define MPI2_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_SGE_SET_FLAGS(f) | \ - MPI2_SGE_LENGTH(l)) - -#define MPI2_pSGE_GET_FLAGS(psg) MPI2_SGE_GET_FLAGS((psg)->FlagsLength) -#define MPI2_pSGE_GET_LENGTH(psg) MPI2_SGE_LENGTH((psg)->FlagsLength) -#define MPI2_pSGE_SET_FLAGS_LENGTH(psg, f, l) ((psg)->FlagsLength = \ - MPI2_SGE_SET_FLAGS_LENGTH(f, l)) - -/*CAUTION - The following are READ-MODIFY-WRITE! */ -#define MPI2_pSGE_SET_FLAGS(psg, f) ((psg)->FlagsLength |= \ - MPI2_SGE_SET_FLAGS(f)) -#define MPI2_pSGE_SET_LENGTH(psg, l) ((psg)->FlagsLength |= \ - MPI2_SGE_LENGTH(l)) - -#define MPI2_GET_CHAIN_OFFSET(x) ((x & MPI2_SGE_CHAIN_OFFSET_MASK) >> \ - MPI2_SGE_CHAIN_OFFSET_SHIFT) - -/***************************************************************************** -* -* Fusion-MPT IEEE Scatter Gather Elements -* -*****************************************************************************/ - -/**************************************************************************** -* IEEE Simple Element structures -****************************************************************************/ - -/*MPI2_IEEE_SGE_SIMPLE32 is for MPI v2.0 products only */ -typedef struct _MPI2_IEEE_SGE_SIMPLE32 { - U32 Address; - U32 FlagsLength; -} MPI2_IEEE_SGE_SIMPLE32, *PTR_MPI2_IEEE_SGE_SIMPLE32, - Mpi2IeeeSgeSimple32_t, *pMpi2IeeeSgeSimple32_t; - -typedef struct _MPI2_IEEE_SGE_SIMPLE64 { - U64 Address; - U32 Length; - U16 Reserved1; - U8 Reserved2; - U8 Flags; -} MPI2_IEEE_SGE_SIMPLE64, *PTR_MPI2_IEEE_SGE_SIMPLE64, - Mpi2IeeeSgeSimple64_t, *pMpi2IeeeSgeSimple64_t; - -typedef union _MPI2_IEEE_SGE_SIMPLE_UNION { - MPI2_IEEE_SGE_SIMPLE32 Simple32; - MPI2_IEEE_SGE_SIMPLE64 Simple64; -} MPI2_IEEE_SGE_SIMPLE_UNION, - *PTR_MPI2_IEEE_SGE_SIMPLE_UNION, - Mpi2IeeeSgeSimpleUnion_t, - *pMpi2IeeeSgeSimpleUnion_t; - -/**************************************************************************** -* IEEE Chain Element structures -****************************************************************************/ - -/*MPI2_IEEE_SGE_CHAIN32 is for MPI v2.0 products only */ -typedef MPI2_IEEE_SGE_SIMPLE32 MPI2_IEEE_SGE_CHAIN32; - -/*MPI2_IEEE_SGE_CHAIN64 is for MPI v2.0 products only */ -typedef MPI2_IEEE_SGE_SIMPLE64 MPI2_IEEE_SGE_CHAIN64; - -typedef union _MPI2_IEEE_SGE_CHAIN_UNION { - MPI2_IEEE_SGE_CHAIN32 Chain32; - MPI2_IEEE_SGE_CHAIN64 Chain64; -} MPI2_IEEE_SGE_CHAIN_UNION, - *PTR_MPI2_IEEE_SGE_CHAIN_UNION, - Mpi2IeeeSgeChainUnion_t, - *pMpi2IeeeSgeChainUnion_t; - -/*MPI25_IEEE_SGE_CHAIN64 is for MPI v2.5 products only */ -typedef struct _MPI25_IEEE_SGE_CHAIN64 { - U64 Address; - U32 Length; - U16 Reserved1; - U8 NextChainOffset; - U8 Flags; -} MPI25_IEEE_SGE_CHAIN64, - *PTR_MPI25_IEEE_SGE_CHAIN64, - Mpi25IeeeSgeChain64_t, - *pMpi25IeeeSgeChain64_t; - -/**************************************************************************** -* All IEEE SGE types union -****************************************************************************/ - -/*MPI2_IEEE_SGE_UNION is for MPI v2.0 products only */ -typedef struct _MPI2_IEEE_SGE_UNION { - union { - MPI2_IEEE_SGE_SIMPLE_UNION Simple; - MPI2_IEEE_SGE_CHAIN_UNION Chain; - } u; -} MPI2_IEEE_SGE_UNION, *PTR_MPI2_IEEE_SGE_UNION, - Mpi2IeeeSgeUnion_t, *pMpi2IeeeSgeUnion_t; - -/**************************************************************************** -* IEEE SGE union for IO SGL's -****************************************************************************/ - -typedef union _MPI25_SGE_IO_UNION { - MPI2_IEEE_SGE_SIMPLE64 IeeeSimple; - MPI25_IEEE_SGE_CHAIN64 IeeeChain; -} MPI25_SGE_IO_UNION, *PTR_MPI25_SGE_IO_UNION, - Mpi25SGEIOUnion_t, *pMpi25SGEIOUnion_t; - -/**************************************************************************** -* IEEE SGE field definitions and masks -****************************************************************************/ - -/*Flags field bit definitions */ - -#define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK (0x80) -#define MPI25_IEEE_SGE_FLAGS_END_OF_LIST (0x40) - -#define MPI2_IEEE32_SGE_FLAGS_SHIFT (24) - -#define MPI2_IEEE32_SGE_LENGTH_MASK (0x00FFFFFF) - -/*Element Type */ - -#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT (0x00) -#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80) - -/*Data Location Address Space */ - -#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03) -#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00) -#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01) -#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02) -#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03) -#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR (0x03) -#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR \ - (MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR) - -/**************************************************************************** -* IEEE SGE operation Macros -****************************************************************************/ - -/*SIMPLE FlagsLength manipulations... */ -#define MPI2_IEEE32_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_IEEE32_SGE_FLAGS_SHIFT) -#define MPI2_IEEE32_SGE_GET_FLAGS(f) (((f) & ~MPI2_IEEE32_SGE_LENGTH_MASK) \ - >> MPI2_IEEE32_SGE_FLAGS_SHIFT) -#define MPI2_IEEE32_SGE_LENGTH(f) ((f) & MPI2_IEEE32_SGE_LENGTH_MASK) - -#define MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_IEEE32_SGE_SET_FLAGS(f) |\ - MPI2_IEEE32_SGE_LENGTH(l)) - -#define MPI2_IEEE32_pSGE_GET_FLAGS(psg) \ - MPI2_IEEE32_SGE_GET_FLAGS((psg)->FlagsLength) -#define MPI2_IEEE32_pSGE_GET_LENGTH(psg) \ - MPI2_IEEE32_SGE_LENGTH((psg)->FlagsLength) -#define MPI2_IEEE32_pSGE_SET_FLAGS_LENGTH(psg, f, l) ((psg)->FlagsLength = \ - MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l)) - -/*CAUTION - The following are READ-MODIFY-WRITE! */ -#define MPI2_IEEE32_pSGE_SET_FLAGS(psg, f) ((psg)->FlagsLength |= \ - MPI2_IEEE32_SGE_SET_FLAGS(f)) -#define MPI2_IEEE32_pSGE_SET_LENGTH(psg, l) ((psg)->FlagsLength |= \ - MPI2_IEEE32_SGE_LENGTH(l)) - -/***************************************************************************** -* -* Fusion-MPT MPI/IEEE Scatter Gather Unions -* -*****************************************************************************/ - -typedef union _MPI2_SIMPLE_SGE_UNION { - MPI2_SGE_SIMPLE_UNION MpiSimple; - MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; -} MPI2_SIMPLE_SGE_UNION, *PTR_MPI2_SIMPLE_SGE_UNION, - Mpi2SimpleSgeUntion_t, *pMpi2SimpleSgeUntion_t; - -typedef union _MPI2_SGE_IO_UNION { - MPI2_SGE_SIMPLE_UNION MpiSimple; - MPI2_SGE_CHAIN_UNION MpiChain; - MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; - MPI2_IEEE_SGE_CHAIN_UNION IeeeChain; -} MPI2_SGE_IO_UNION, *PTR_MPI2_SGE_IO_UNION, - Mpi2SGEIOUnion_t, *pMpi2SGEIOUnion_t; - -/**************************************************************************** -* -* Values for SGLFlags field, used in many request messages with an SGL -* -****************************************************************************/ - -/*values for MPI SGL Data Location Address Space subfield */ -#define MPI2_SGLFLAGS_ADDRESS_SPACE_MASK (0x0C) -#define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE (0x00) -#define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE (0x04) -#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08) -#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE (0x0C) -/*values for SGL Type subfield */ -#define MPI2_SGLFLAGS_SGL_TYPE_MASK (0x03) -#define MPI2_SGLFLAGS_SGL_TYPE_MPI (0x00) -#define MPI2_SGLFLAGS_SGL_TYPE_IEEE32 (0x01) -#define MPI2_SGLFLAGS_SGL_TYPE_IEEE64 (0x02) - -#endif diff --git a/addons/mpt3sas/src/3.10.108/mpi/mpi2_cnfg.h b/addons/mpt3sas/src/3.10.108/mpi/mpi2_cnfg.h deleted file mode 100644 index d8b2c3ee..00000000 --- a/addons/mpt3sas/src/3.10.108/mpi/mpi2_cnfg.h +++ /dev/null @@ -1,3323 +0,0 @@ -/* - * Copyright (c) 2000-2011 LSI Corporation. - * - * - * Name: mpi2_cnfg.h - * Title: MPI Configuration messages and pages - * Creation Date: November 10, 2006 - * - * mpi2_cnfg.h Version: 02.00.22 - * - * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 - * prefix are for use only on MPI v2.5 products, and must not be used - * with MPI v2.0 products. Unless otherwise noted, names beginning with - * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 06-04-07 02.00.01 Added defines for SAS IO Unit Page 2 PhyFlags. - * Added Manufacturing Page 11. - * Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE - * define. - * 06-26-07 02.00.02 Adding generic structure for product-specific - * Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS. - * Rework of BIOS Page 2 configuration page. - * Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the - * forms. - * Added configuration pages IOC Page 8 and Driver - * Persistent Mapping Page 0. - * 08-31-07 02.00.03 Modified configuration pages dealing with Integrated - * RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1, - * RAID Physical Disk Pages 0 and 1, RAID Configuration - * Page 0). - * Added new value for AccessStatus field of SAS Device - * Page 0 (_SATA_NEEDS_INITIALIZATION). - * 10-31-07 02.00.04 Added missing SEPDevHandle field to - * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. - * 12-18-07 02.00.05 Modified IO Unit Page 0 to use 32-bit version fields for - * NVDATA. - * Modified IOC Page 7 to use masks and added field for - * SASBroadcastPrimitiveMasks. - * Added MPI2_CONFIG_PAGE_BIOS_4. - * Added MPI2_CONFIG_PAGE_LOG_0. - * 02-29-08 02.00.06 Modified various names to make them 32-character unique. - * Added SAS Device IDs. - * Updated Integrated RAID configuration pages including - * Manufacturing Page 4, IOC Page 6, and RAID Configuration - * Page 0. - * 05-21-08 02.00.07 Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA. - * Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION. - * Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING. - * Added missing MaxNumRoutedSasAddresses field to - * MPI2_CONFIG_PAGE_EXPANDER_0. - * Added SAS Port Page 0. - * Modified structure layout for - * MPI2_CONFIG_PAGE_DRIVER_MAPPING_0. - * 06-27-08 02.00.08 Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use - * MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array. - * 10-02-08 02.00.09 Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF - * to 0x000000FF. - * Added two new values for the Physical Disk Coercion Size - * bits in the Flags field of Manufacturing Page 4. - * Added product-specific Manufacturing pages 16 to 31. - * Modified Flags bits for controlling write cache on SATA - * drives in IO Unit Page 1. - * Added new bit to AdditionalControlFlags of SAS IO Unit - * Page 1 to control Invalid Topology Correction. - * Added additional defines for RAID Volume Page 0 - * VolumeStatusFlags field. - * Modified meaning of RAID Volume Page 0 VolumeSettings - * define for auto-configure of hot-swap drives. - * Added SupportedPhysDisks field to RAID Volume Page 1 and - * added related defines. - * Added PhysDiskAttributes field (and related defines) to - * RAID Physical Disk Page 0. - * Added MPI2_SAS_PHYINFO_PHY_VACANT define. - * Added three new DiscoveryStatus bits for SAS IO Unit - * Page 0 and SAS Expander Page 0. - * Removed multiplexing information from SAS IO Unit pages. - * Added BootDeviceWaitTime field to SAS IO Unit Page 4. - * Removed Zone Address Resolved bit from PhyInfo and from - * Expander Page 0 Flags field. - * Added two new AccessStatus values to SAS Device Page 0 - * for indicating routing problems. Added 3 reserved words - * to this page. - * 01-19-09 02.00.10 Fixed defines for GPIOVal field of IO Unit Page 3. - * Inserted missing reserved field into structure for IOC - * Page 6. - * Added more pending task bits to RAID Volume Page 0 - * VolumeStatusFlags defines. - * Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define. - * Added a new DiscoveryStatus bit for SAS IO Unit Page 0 - * and SAS Expander Page 0 to flag a downstream initiator - * when in simplified routing mode. - * Removed SATA Init Failure defines for DiscoveryStatus - * fields of SAS IO Unit Page 0 and SAS Expander Page 0. - * Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define. - * Added PortGroups, DmaGroup, and ControlGroup fields to - * SAS Device Page 0. - * 05-06-09 02.00.11 Added structures and defines for IO Unit Page 5 and IO - * Unit Page 6. - * Added expander reduced functionality data to SAS - * Expander Page 0. - * Added SAS PHY Page 2 and SAS PHY Page 3. - * 07-30-09 02.00.12 Added IO Unit Page 7. - * Added new device ids. - * Added SAS IO Unit Page 5. - * Added partial and slumber power management capable flags - * to SAS Device Page 0 Flags field. - * Added PhyInfo defines for power condition. - * Added Ethernet configuration pages. - * 10-28-09 02.00.13 Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY. - * Added SAS PHY Page 4 structure and defines. - * 02-10-10 02.00.14 Modified the comments for the configuration page - * structures that contain an array of data. The host - * should use the "count" field in the page data (e.g. the - * NumPhys field) to determine the number of valid elements - * in the array. - * Added/modified some MPI2_MFGPAGE_DEVID_SAS defines. - * Added PowerManagementCapabilities to IO Unit Page 7. - * Added PortWidthModGroup field to - * MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS. - * Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines. - * Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines. - * Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines. - * 05-12-10 02.00.15 Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT - * define. - * Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define. - * Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define. - * 08-11-10 02.00.16 Removed IO Unit Page 1 device path (multi-pathing) - * defines. - * 11-10-10 02.00.17 Added ReceptacleID field (replacing Reserved1) to - * MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for - * the Pinout field. - * Added BoardTemperature and BoardTemperatureUnits fields - * to MPI2_CONFIG_PAGE_IO_UNIT_7. - * Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define - * and MPI2_CONFIG_PAGE_EXT_MAN_PS structure. - * 02-23-11 02.00.18 Added ProxyVF_ID field to MPI2_CONFIG_REQUEST. - * Added IO Unit Page 8, IO Unit Page 9, - * and IO Unit Page 10. - * Added SASNotifyPrimitiveMasks field to - * MPI2_CONFIG_PAGE_IOC_7. - * 03-09-11 02.00.19 Fixed IO Unit Page 10 (to match the spec). - * 05-25-11 02.00.20 Cleaned up a few comments. - * 08-24-11 02.00.21 Marked the IO Unit Page 7 PowerManagementCapabilities - * for PCIe link as obsolete. - * Added SpinupFlags field containing a Disable Spin-up bit - * to the MPI2_SAS_IOUNIT4_SPINUP_GROUP fields of SAS IO - * Unit Page 4. - * 11-18-11 02.00.22 Added define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT. - * Added UEFIVersion field to BIOS Page 1 and defined new - * BiosOptions bits. - * Incorporating additions for MPI v2.5. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_CNFG_H -#define MPI2_CNFG_H - -/***************************************************************************** -* Configuration Page Header and defines -*****************************************************************************/ - -/*Config Page Header */ -typedef struct _MPI2_CONFIG_PAGE_HEADER { - U8 PageVersion; /*0x00 */ - U8 PageLength; /*0x01 */ - U8 PageNumber; /*0x02 */ - U8 PageType; /*0x03 */ -} MPI2_CONFIG_PAGE_HEADER, *PTR_MPI2_CONFIG_PAGE_HEADER, - Mpi2ConfigPageHeader_t, *pMpi2ConfigPageHeader_t; - -typedef union _MPI2_CONFIG_PAGE_HEADER_UNION { - MPI2_CONFIG_PAGE_HEADER Struct; - U8 Bytes[4]; - U16 Word16[2]; - U32 Word32; -} MPI2_CONFIG_PAGE_HEADER_UNION, *PTR_MPI2_CONFIG_PAGE_HEADER_UNION, - Mpi2ConfigPageHeaderUnion, *pMpi2ConfigPageHeaderUnion; - -/*Extended Config Page Header */ -typedef struct _MPI2_CONFIG_EXTENDED_PAGE_HEADER { - U8 PageVersion; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 PageNumber; /*0x02 */ - U8 PageType; /*0x03 */ - U16 ExtPageLength; /*0x04 */ - U8 ExtPageType; /*0x06 */ - U8 Reserved2; /*0x07 */ -} MPI2_CONFIG_EXTENDED_PAGE_HEADER, - *PTR_MPI2_CONFIG_EXTENDED_PAGE_HEADER, - Mpi2ConfigExtendedPageHeader_t, - *pMpi2ConfigExtendedPageHeader_t; - -typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION { - MPI2_CONFIG_PAGE_HEADER Struct; - MPI2_CONFIG_EXTENDED_PAGE_HEADER Ext; - U8 Bytes[8]; - U16 Word16[4]; - U32 Word32[2]; -} MPI2_CONFIG_EXT_PAGE_HEADER_UNION, - *PTR_MPI2_CONFIG_EXT_PAGE_HEADER_UNION, - Mpi2ConfigPageExtendedHeaderUnion, - *pMpi2ConfigPageExtendedHeaderUnion; - - -/*PageType field values */ -#define MPI2_CONFIG_PAGEATTR_READ_ONLY (0x00) -#define MPI2_CONFIG_PAGEATTR_CHANGEABLE (0x10) -#define MPI2_CONFIG_PAGEATTR_PERSISTENT (0x20) -#define MPI2_CONFIG_PAGEATTR_MASK (0xF0) - -#define MPI2_CONFIG_PAGETYPE_IO_UNIT (0x00) -#define MPI2_CONFIG_PAGETYPE_IOC (0x01) -#define MPI2_CONFIG_PAGETYPE_BIOS (0x02) -#define MPI2_CONFIG_PAGETYPE_RAID_VOLUME (0x08) -#define MPI2_CONFIG_PAGETYPE_MANUFACTURING (0x09) -#define MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK (0x0A) -#define MPI2_CONFIG_PAGETYPE_EXTENDED (0x0F) -#define MPI2_CONFIG_PAGETYPE_MASK (0x0F) - -#define MPI2_CONFIG_TYPENUM_MASK (0x0FFF) - - -/*ExtPageType field values */ -#define MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT (0x10) -#define MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER (0x11) -#define MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE (0x12) -#define MPI2_CONFIG_EXTPAGETYPE_SAS_PHY (0x13) -#define MPI2_CONFIG_EXTPAGETYPE_LOG (0x14) -#define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE (0x15) -#define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG (0x16) -#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING (0x17) -#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18) -#define MPI2_CONFIG_EXTPAGETYPE_ETHERNET (0x19) -#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING (0x1A) - - -/***************************************************************************** -* PageAddress defines -*****************************************************************************/ - -/*RAID Volume PageAddress format */ -#define MPI2_RAID_VOLUME_PGAD_FORM_MASK (0xF0000000) -#define MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) -#define MPI2_RAID_VOLUME_PGAD_FORM_HANDLE (0x10000000) - -#define MPI2_RAID_VOLUME_PGAD_HANDLE_MASK (0x0000FFFF) - - -/*RAID Physical Disk PageAddress format */ -#define MPI2_PHYSDISK_PGAD_FORM_MASK (0xF0000000) -#define MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM (0x00000000) -#define MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM (0x10000000) -#define MPI2_PHYSDISK_PGAD_FORM_DEVHANDLE (0x20000000) - -#define MPI2_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF) -#define MPI2_PHYSDISK_PGAD_DEVHANDLE_MASK (0x0000FFFF) - - -/*SAS Expander PageAddress format */ -#define MPI2_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000) -#define MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL (0x00000000) -#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM (0x10000000) -#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL (0x20000000) - -#define MPI2_SAS_EXPAND_PGAD_HANDLE_MASK (0x0000FFFF) -#define MPI2_SAS_EXPAND_PGAD_PHYNUM_MASK (0x00FF0000) -#define MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT (16) - - -/*SAS Device PageAddress format */ -#define MPI2_SAS_DEVICE_PGAD_FORM_MASK (0xF0000000) -#define MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) -#define MPI2_SAS_DEVICE_PGAD_FORM_HANDLE (0x20000000) - -#define MPI2_SAS_DEVICE_PGAD_HANDLE_MASK (0x0000FFFF) - - -/*SAS PHY PageAddress format */ -#define MPI2_SAS_PHY_PGAD_FORM_MASK (0xF0000000) -#define MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x00000000) -#define MPI2_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX (0x10000000) - -#define MPI2_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF) -#define MPI2_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK (0x0000FFFF) - - -/*SAS Port PageAddress format */ -#define MPI2_SASPORT_PGAD_FORM_MASK (0xF0000000) -#define MPI2_SASPORT_PGAD_FORM_GET_NEXT_PORT (0x00000000) -#define MPI2_SASPORT_PGAD_FORM_PORT_NUM (0x10000000) - -#define MPI2_SASPORT_PGAD_PORTNUMBER_MASK (0x00000FFF) - - -/*SAS Enclosure PageAddress format */ -#define MPI2_SAS_ENCLOS_PGAD_FORM_MASK (0xF0000000) -#define MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) -#define MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE (0x10000000) - -#define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF) - - -/*RAID Configuration PageAddress format */ -#define MPI2_RAID_PGAD_FORM_MASK (0xF0000000) -#define MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM (0x00000000) -#define MPI2_RAID_PGAD_FORM_CONFIGNUM (0x10000000) -#define MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG (0x20000000) - -#define MPI2_RAID_PGAD_CONFIGNUM_MASK (0x000000FF) - - -/*Driver Persistent Mapping PageAddress format */ -#define MPI2_DPM_PGAD_FORM_MASK (0xF0000000) -#define MPI2_DPM_PGAD_FORM_ENTRY_RANGE (0x00000000) - -#define MPI2_DPM_PGAD_ENTRY_COUNT_MASK (0x0FFF0000) -#define MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT (16) -#define MPI2_DPM_PGAD_START_ENTRY_MASK (0x0000FFFF) - - -/*Ethernet PageAddress format */ -#define MPI2_ETHERNET_PGAD_FORM_MASK (0xF0000000) -#define MPI2_ETHERNET_PGAD_FORM_IF_NUM (0x00000000) - -#define MPI2_ETHERNET_PGAD_IF_NUMBER_MASK (0x000000FF) - - - -/**************************************************************************** -* Configuration messages -****************************************************************************/ - -/*Configuration Request Message */ -typedef struct _MPI2_CONFIG_REQUEST { - U8 Action; /*0x00 */ - U8 SGLFlags; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 ExtPageLength; /*0x04 */ - U8 ExtPageType; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U8 Reserved2; /*0x0C */ - U8 ProxyVF_ID; /*0x0D */ - U16 Reserved4; /*0x0E */ - U32 Reserved3; /*0x10 */ - MPI2_CONFIG_PAGE_HEADER Header; /*0x14 */ - U32 PageAddress; /*0x18 */ - MPI2_SGE_IO_UNION PageBufferSGE; /*0x1C */ -} MPI2_CONFIG_REQUEST, *PTR_MPI2_CONFIG_REQUEST, - Mpi2ConfigRequest_t, *pMpi2ConfigRequest_t; - -/*values for the Action field */ -#define MPI2_CONFIG_ACTION_PAGE_HEADER (0x00) -#define MPI2_CONFIG_ACTION_PAGE_READ_CURRENT (0x01) -#define MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT (0x02) -#define MPI2_CONFIG_ACTION_PAGE_DEFAULT (0x03) -#define MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM (0x04) -#define MPI2_CONFIG_ACTION_PAGE_READ_DEFAULT (0x05) -#define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM (0x06) -#define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE (0x07) - -/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ - - -/*Config Reply Message */ -typedef struct _MPI2_CONFIG_REPLY { - U8 Action; /*0x00 */ - U8 SGLFlags; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 ExtPageLength; /*0x04 */ - U8 ExtPageType; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U16 Reserved2; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - MPI2_CONFIG_PAGE_HEADER Header; /*0x14 */ -} MPI2_CONFIG_REPLY, *PTR_MPI2_CONFIG_REPLY, - Mpi2ConfigReply_t, *pMpi2ConfigReply_t; - - - -/***************************************************************************** -* -* C o n f i g u r a t i o n P a g e s -* -*****************************************************************************/ - -/**************************************************************************** -* Manufacturing Config pages -****************************************************************************/ - -#define MPI2_MFGPAGE_VENDORID_LSI (0x1000) - -/*MPI v2.0 SAS products */ -#define MPI2_MFGPAGE_DEVID_SAS2004 (0x0070) -#define MPI2_MFGPAGE_DEVID_SAS2008 (0x0072) -#define MPI2_MFGPAGE_DEVID_SAS2108_1 (0x0074) -#define MPI2_MFGPAGE_DEVID_SAS2108_2 (0x0076) -#define MPI2_MFGPAGE_DEVID_SAS2108_3 (0x0077) -#define MPI2_MFGPAGE_DEVID_SAS2116_1 (0x0064) -#define MPI2_MFGPAGE_DEVID_SAS2116_2 (0x0065) - -#define MPI2_MFGPAGE_DEVID_SSS6200 (0x007E) - -#define MPI2_MFGPAGE_DEVID_SAS2208_1 (0x0080) -#define MPI2_MFGPAGE_DEVID_SAS2208_2 (0x0081) -#define MPI2_MFGPAGE_DEVID_SAS2208_3 (0x0082) -#define MPI2_MFGPAGE_DEVID_SAS2208_4 (0x0083) -#define MPI2_MFGPAGE_DEVID_SAS2208_5 (0x0084) -#define MPI2_MFGPAGE_DEVID_SAS2208_6 (0x0085) -#define MPI2_MFGPAGE_DEVID_SAS2308_1 (0x0086) -#define MPI2_MFGPAGE_DEVID_SAS2308_2 (0x0087) -#define MPI2_MFGPAGE_DEVID_SAS2308_3 (0x006E) - -/*MPI v2.5 SAS products */ -#define MPI25_MFGPAGE_DEVID_SAS3004 (0x0096) -#define MPI25_MFGPAGE_DEVID_SAS3008 (0x0097) -#define MPI25_MFGPAGE_DEVID_SAS3108_1 (0x0090) -#define MPI25_MFGPAGE_DEVID_SAS3108_2 (0x0091) -#define MPI25_MFGPAGE_DEVID_SAS3108_5 (0x0094) -#define MPI25_MFGPAGE_DEVID_SAS3108_6 (0x0095) - - - - -/*Manufacturing Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_MAN_0 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 ChipName[16]; /*0x04 */ - U8 ChipRevision[8]; /*0x14 */ - U8 BoardName[16]; /*0x1C */ - U8 BoardAssembly[16]; /*0x2C */ - U8 BoardTracerNumber[16]; /*0x3C */ -} MPI2_CONFIG_PAGE_MAN_0, - *PTR_MPI2_CONFIG_PAGE_MAN_0, - Mpi2ManufacturingPage0_t, - *pMpi2ManufacturingPage0_t; - -#define MPI2_MANUFACTURING0_PAGEVERSION (0x00) - - -/*Manufacturing Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_MAN_1 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 VPD[256]; /*0x04 */ -} MPI2_CONFIG_PAGE_MAN_1, - *PTR_MPI2_CONFIG_PAGE_MAN_1, - Mpi2ManufacturingPage1_t, - *pMpi2ManufacturingPage1_t; - -#define MPI2_MANUFACTURING1_PAGEVERSION (0x00) - - -typedef struct _MPI2_CHIP_REVISION_ID { - U16 DeviceID; /*0x00 */ - U8 PCIRevisionID; /*0x02 */ - U8 Reserved; /*0x03 */ -} MPI2_CHIP_REVISION_ID, *PTR_MPI2_CHIP_REVISION_ID, - Mpi2ChipRevisionId_t, *pMpi2ChipRevisionId_t; - - -/*Manufacturing Page 2 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check Header.PageLength at runtime. - */ -#ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS -#define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_MAN_2 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - MPI2_CHIP_REVISION_ID ChipId; /*0x04 */ - U32 - HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/*0x08 */ -} MPI2_CONFIG_PAGE_MAN_2, - *PTR_MPI2_CONFIG_PAGE_MAN_2, - Mpi2ManufacturingPage2_t, - *pMpi2ManufacturingPage2_t; - -#define MPI2_MANUFACTURING2_PAGEVERSION (0x00) - - -/*Manufacturing Page 3 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check Header.PageLength at runtime. - */ -#ifndef MPI2_MAN_PAGE_3_INFO_WORDS -#define MPI2_MAN_PAGE_3_INFO_WORDS (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_MAN_3 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - MPI2_CHIP_REVISION_ID ChipId; /*0x04 */ - U32 - Info[MPI2_MAN_PAGE_3_INFO_WORDS];/*0x08 */ -} MPI2_CONFIG_PAGE_MAN_3, - *PTR_MPI2_CONFIG_PAGE_MAN_3, - Mpi2ManufacturingPage3_t, - *pMpi2ManufacturingPage3_t; - -#define MPI2_MANUFACTURING3_PAGEVERSION (0x00) - - -/*Manufacturing Page 4 */ - -typedef struct _MPI2_MANPAGE4_PWR_SAVE_SETTINGS { - U8 PowerSaveFlags; /*0x00 */ - U8 InternalOperationsSleepTime; /*0x01 */ - U8 InternalOperationsRunTime; /*0x02 */ - U8 HostIdleTime; /*0x03 */ -} MPI2_MANPAGE4_PWR_SAVE_SETTINGS, - *PTR_MPI2_MANPAGE4_PWR_SAVE_SETTINGS, - Mpi2ManPage4PwrSaveSettings_t, - *pMpi2ManPage4PwrSaveSettings_t; - -/*defines for the PowerSaveFlags field */ -#define MPI2_MANPAGE4_MASK_POWERSAVE_MODE (0x03) -#define MPI2_MANPAGE4_POWERSAVE_MODE_DISABLED (0x00) -#define MPI2_MANPAGE4_CUSTOM_POWERSAVE_MODE (0x01) -#define MPI2_MANPAGE4_FULL_POWERSAVE_MODE (0x02) - -typedef struct _MPI2_CONFIG_PAGE_MAN_4 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Flags; /*0x08 */ - U8 InquirySize; /*0x0C */ - U8 Reserved2; /*0x0D */ - U16 Reserved3; /*0x0E */ - U8 InquiryData[56]; /*0x10 */ - U32 RAID0VolumeSettings; /*0x48 */ - U32 RAID1EVolumeSettings; /*0x4C */ - U32 RAID1VolumeSettings; /*0x50 */ - U32 RAID10VolumeSettings; /*0x54 */ - U32 Reserved4; /*0x58 */ - U32 Reserved5; /*0x5C */ - MPI2_MANPAGE4_PWR_SAVE_SETTINGS PowerSaveSettings; /*0x60 */ - U8 MaxOCEDisks; /*0x64 */ - U8 ResyncRate; /*0x65 */ - U16 DataScrubDuration; /*0x66 */ - U8 MaxHotSpares; /*0x68 */ - U8 MaxPhysDisksPerVol; /*0x69 */ - U8 MaxPhysDisks; /*0x6A */ - U8 MaxVolumes; /*0x6B */ -} MPI2_CONFIG_PAGE_MAN_4, - *PTR_MPI2_CONFIG_PAGE_MAN_4, - Mpi2ManufacturingPage4_t, - *pMpi2ManufacturingPage4_t; - -#define MPI2_MANUFACTURING4_PAGEVERSION (0x0A) - -/*Manufacturing Page 4 Flags field */ -#define MPI2_MANPAGE4_METADATA_SIZE_MASK (0x00030000) -#define MPI2_MANPAGE4_METADATA_512MB (0x00000000) - -#define MPI2_MANPAGE4_MIX_SSD_SAS_SATA (0x00008000) -#define MPI2_MANPAGE4_MIX_SSD_AND_NON_SSD (0x00004000) -#define MPI2_MANPAGE4_HIDE_PHYSDISK_NON_IR (0x00002000) - -#define MPI2_MANPAGE4_MASK_PHYSDISK_COERCION (0x00001C00) -#define MPI2_MANPAGE4_PHYSDISK_COERCION_1GB (0x00000000) -#define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION (0x00000400) -#define MPI2_MANPAGE4_PHYSDISK_ADAPTIVE_COERCION (0x00000800) -#define MPI2_MANPAGE4_PHYSDISK_ZERO_COERCION (0x00000C00) - -#define MPI2_MANPAGE4_MASK_BAD_BLOCK_MARKING (0x00000300) -#define MPI2_MANPAGE4_DEFAULT_BAD_BLOCK_MARKING (0x00000000) -#define MPI2_MANPAGE4_TABLE_BAD_BLOCK_MARKING (0x00000100) -#define MPI2_MANPAGE4_WRITE_LONG_BAD_BLOCK_MARKING (0x00000200) - -#define MPI2_MANPAGE4_FORCE_OFFLINE_FAILOVER (0x00000080) -#define MPI2_MANPAGE4_RAID10_DISABLE (0x00000040) -#define MPI2_MANPAGE4_RAID1E_DISABLE (0x00000020) -#define MPI2_MANPAGE4_RAID1_DISABLE (0x00000010) -#define MPI2_MANPAGE4_RAID0_DISABLE (0x00000008) -#define MPI2_MANPAGE4_IR_MODEPAGE8_DISABLE (0x00000004) -#define MPI2_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x00000002) -#define MPI2_MANPAGE4_IR_NO_MIX_SAS_SATA (0x00000001) - - -/*Manufacturing Page 5 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES -#define MPI2_MAN_PAGE_5_PHY_ENTRIES (1) -#endif - -typedef struct _MPI2_MANUFACTURING5_ENTRY { - U64 WWID; /*0x00 */ - U64 DeviceName; /*0x08 */ -} MPI2_MANUFACTURING5_ENTRY, - *PTR_MPI2_MANUFACTURING5_ENTRY, - Mpi2Manufacturing5Entry_t, - *pMpi2Manufacturing5Entry_t; - -typedef struct _MPI2_CONFIG_PAGE_MAN_5 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 NumPhys; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 Reserved2; /*0x06 */ - U32 Reserved3; /*0x08 */ - U32 Reserved4; /*0x0C */ - MPI2_MANUFACTURING5_ENTRY - Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/*0x08 */ -} MPI2_CONFIG_PAGE_MAN_5, - *PTR_MPI2_CONFIG_PAGE_MAN_5, - Mpi2ManufacturingPage5_t, - *pMpi2ManufacturingPage5_t; - -#define MPI2_MANUFACTURING5_PAGEVERSION (0x03) - - -/*Manufacturing Page 6 */ - -typedef struct _MPI2_CONFIG_PAGE_MAN_6 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 ProductSpecificInfo;/*0x04 */ -} MPI2_CONFIG_PAGE_MAN_6, - *PTR_MPI2_CONFIG_PAGE_MAN_6, - Mpi2ManufacturingPage6_t, - *pMpi2ManufacturingPage6_t; - -#define MPI2_MANUFACTURING6_PAGEVERSION (0x00) - - -/*Manufacturing Page 7 */ - -typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO { - U32 Pinout; /*0x00 */ - U8 Connector[16]; /*0x04 */ - U8 Location; /*0x14 */ - U8 ReceptacleID; /*0x15 */ - U16 Slot; /*0x16 */ - U32 Reserved2; /*0x18 */ -} MPI2_MANPAGE7_CONNECTOR_INFO, - *PTR_MPI2_MANPAGE7_CONNECTOR_INFO, - Mpi2ManPage7ConnectorInfo_t, - *pMpi2ManPage7ConnectorInfo_t; - -/*defines for the Pinout field */ -#define MPI2_MANPAGE7_PINOUT_LANE_MASK (0x0000FF00) -#define MPI2_MANPAGE7_PINOUT_LANE_SHIFT (8) - -#define MPI2_MANPAGE7_PINOUT_TYPE_MASK (0x000000FF) -#define MPI2_MANPAGE7_PINOUT_TYPE_UNKNOWN (0x00) -#define MPI2_MANPAGE7_PINOUT_SATA_SINGLE (0x01) -#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x02) -#define MPI2_MANPAGE7_PINOUT_SFF_8486 (0x03) -#define MPI2_MANPAGE7_PINOUT_SFF_8484 (0x04) -#define MPI2_MANPAGE7_PINOUT_SFF_8087 (0x05) -#define MPI2_MANPAGE7_PINOUT_SFF_8643_4I (0x06) -#define MPI2_MANPAGE7_PINOUT_SFF_8643_8I (0x07) -#define MPI2_MANPAGE7_PINOUT_SFF_8470 (0x08) -#define MPI2_MANPAGE7_PINOUT_SFF_8088 (0x09) -#define MPI2_MANPAGE7_PINOUT_SFF_8644_4X (0x0A) -#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X (0x0B) -#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X (0x0C) -#define MPI2_MANPAGE7_PINOUT_SFF_8436 (0x0D) - -/*defines for the Location field */ -#define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01) -#define MPI2_MANPAGE7_LOCATION_INTERNAL (0x02) -#define MPI2_MANPAGE7_LOCATION_EXTERNAL (0x04) -#define MPI2_MANPAGE7_LOCATION_SWITCHABLE (0x08) -#define MPI2_MANPAGE7_LOCATION_AUTO (0x10) -#define MPI2_MANPAGE7_LOCATION_NOT_PRESENT (0x20) -#define MPI2_MANPAGE7_LOCATION_NOT_CONNECTED (0x80) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX -#define MPI2_MANPAGE7_CONNECTOR_INFO_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_MAN_7 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Reserved2; /*0x08 */ - U32 Flags; /*0x0C */ - U8 EnclosureName[16]; /*0x10 */ - U8 NumPhys; /*0x20 */ - U8 Reserved3; /*0x21 */ - U16 Reserved4; /*0x22 */ - MPI2_MANPAGE7_CONNECTOR_INFO - ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /*0x24 */ -} MPI2_CONFIG_PAGE_MAN_7, - *PTR_MPI2_CONFIG_PAGE_MAN_7, - Mpi2ManufacturingPage7_t, - *pMpi2ManufacturingPage7_t; - -#define MPI2_MANUFACTURING7_PAGEVERSION (0x01) - -/*defines for the Flags field */ -#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001) - - -/* - *Generic structure to use for product-specific manufacturing pages - *(currently Manufacturing Page 8 through Manufacturing Page 31). - */ - -typedef struct _MPI2_CONFIG_PAGE_MAN_PS { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 ProductSpecificInfo;/*0x04 */ -} MPI2_CONFIG_PAGE_MAN_PS, - *PTR_MPI2_CONFIG_PAGE_MAN_PS, - Mpi2ManufacturingPagePS_t, - *pMpi2ManufacturingPagePS_t; - -#define MPI2_MANUFACTURING8_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING9_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING10_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING11_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING12_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING13_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING14_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING15_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING16_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING17_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING18_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING19_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING20_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING21_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING22_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING23_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING24_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING25_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING26_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING27_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING28_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING29_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING30_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING31_PAGEVERSION (0x00) - - -/**************************************************************************** -* IO Unit Config Pages -****************************************************************************/ - -/*IO Unit Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_0 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U64 UniqueValue; /*0x04 */ - MPI2_VERSION_UNION NvdataVersionDefault; /*0x08 */ - MPI2_VERSION_UNION NvdataVersionPersistent; /*0x0A */ -} MPI2_CONFIG_PAGE_IO_UNIT_0, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_0, - Mpi2IOUnitPage0_t, *pMpi2IOUnitPage0_t; - -#define MPI2_IOUNITPAGE0_PAGEVERSION (0x02) - - -/*IO Unit Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Flags; /*0x04 */ -} MPI2_CONFIG_PAGE_IO_UNIT_1, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_1, - Mpi2IOUnitPage1_t, *pMpi2IOUnitPage1_t; - -#define MPI2_IOUNITPAGE1_PAGEVERSION (0x04) - -/*IO Unit Page 1 Flags defines */ -#define MPI25_IOUNITPAGE1_NEW_DEVICE_FAST_PATH_DISABLE (0x00002000) -#define MPI25_IOUNITPAGE1_DISABLE_FAST_PATH (0x00001000) -#define MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY (0x00000800) -#define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE (0x00000600) -#define MPI2_IOUNITPAGE1_SATA_WRITE_CACHE_SHIFT (9) -#define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE (0x00000000) -#define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE (0x00000200) -#define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE (0x00000400) -#define MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100) -#define MPI2_IOUNITPAGE1_DISABLE_IR (0x00000040) -#define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020) -#define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID (0x00000004) - - -/*IO Unit Page 3 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for GPIOCount at runtime. - */ -#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX -#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 GPIOCount; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 Reserved2; /*0x06 */ - U16 - GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/*0x08 */ -} MPI2_CONFIG_PAGE_IO_UNIT_3, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_3, - Mpi2IOUnitPage3_t, *pMpi2IOUnitPage3_t; - -#define MPI2_IOUNITPAGE3_PAGEVERSION (0x01) - -/*defines for IO Unit Page 3 GPIOVal field */ -#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_MASK (0xFFFC) -#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_SHIFT (2) -#define MPI2_IOUNITPAGE3_GPIO_SETTING_OFF (0x0000) -#define MPI2_IOUNITPAGE3_GPIO_SETTING_ON (0x0001) - - -/*IO Unit Page 5 */ - -/* - *Upper layer code (drivers, utilities, etc.) should leave this define set to - *one and check the value returned for NumDmaEngines at runtime. - */ -#ifndef MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES -#define MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U64 - RaidAcceleratorBufferBaseAddress; /*0x04 */ - U64 - RaidAcceleratorBufferSize; /*0x0C */ - U64 - RaidAcceleratorControlBaseAddress; /*0x14 */ - U8 RAControlSize; /*0x1C */ - U8 NumDmaEngines; /*0x1D */ - U8 RAMinControlSize; /*0x1E */ - U8 RAMaxControlSize; /*0x1F */ - U32 Reserved1; /*0x20 */ - U32 Reserved2; /*0x24 */ - U32 Reserved3; /*0x28 */ - U32 - DmaEngineCapabilities[MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES]; /*0x2C */ -} MPI2_CONFIG_PAGE_IO_UNIT_5, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_5, - Mpi2IOUnitPage5_t, *pMpi2IOUnitPage5_t; - -#define MPI2_IOUNITPAGE5_PAGEVERSION (0x00) - -/*defines for IO Unit Page 5 DmaEngineCapabilities field */ -#define MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS (0xFF00) -#define MPI2_IOUNITPAGE5_DMA_CAP_SHIFT_MAX_REQUESTS (16) - -#define MPI2_IOUNITPAGE5_DMA_CAP_EEDP (0x0008) -#define MPI2_IOUNITPAGE5_DMA_CAP_PARITY_GENERATION (0x0004) -#define MPI2_IOUNITPAGE5_DMA_CAP_HASHING (0x0002) -#define MPI2_IOUNITPAGE5_DMA_CAP_ENCRYPTION (0x0001) - - -/*IO Unit Page 6 */ - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_6 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U16 Flags; /*0x04 */ - U8 RAHostControlSize; /*0x06 */ - U8 Reserved0; /*0x07 */ - U64 - RaidAcceleratorHostControlBaseAddress; /*0x08 */ - U32 Reserved1; /*0x10 */ - U32 Reserved2; /*0x14 */ - U32 Reserved3; /*0x18 */ -} MPI2_CONFIG_PAGE_IO_UNIT_6, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_6, - Mpi2IOUnitPage6_t, *pMpi2IOUnitPage6_t; - -#define MPI2_IOUNITPAGE6_PAGEVERSION (0x00) - -/*defines for IO Unit Page 6 Flags field */ -#define MPI2_IOUNITPAGE6_FLAGS_ENABLE_RAID_ACCELERATOR (0x0001) - - -/*IO Unit Page 7 */ - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 CurrentPowerMode; /*0x04 */ - U8 PreviousPowerMode; /*0x05 */ - U8 PCIeWidth; /*0x06 */ - U8 PCIeSpeed; /*0x07 */ - U32 ProcessorState; /*0x08 */ - U32 - PowerManagementCapabilities; /*0x0C */ - U16 IOCTemperature; /*0x10 */ - U8 - IOCTemperatureUnits; /*0x12 */ - U8 IOCSpeed; /*0x13 */ - U16 BoardTemperature; /*0x14 */ - U8 - BoardTemperatureUnits; /*0x16 */ - U8 Reserved3; /*0x17 */ -} MPI2_CONFIG_PAGE_IO_UNIT_7, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_7, - Mpi2IOUnitPage7_t, *pMpi2IOUnitPage7_t; - -#define MPI2_IOUNITPAGE7_PAGEVERSION (0x02) - -/*defines for IO Unit Page 7 CurrentPowerMode and PreviousPowerMode fields */ -#define MPI25_IOUNITPAGE7_PM_INIT_MASK (0xC0) -#define MPI25_IOUNITPAGE7_PM_INIT_UNAVAILABLE (0x00) -#define MPI25_IOUNITPAGE7_PM_INIT_HOST (0x40) -#define MPI25_IOUNITPAGE7_PM_INIT_IO_UNIT (0x80) -#define MPI25_IOUNITPAGE7_PM_INIT_PCIE_DPA (0xC0) - -#define MPI25_IOUNITPAGE7_PM_MODE_MASK (0x07) -#define MPI25_IOUNITPAGE7_PM_MODE_UNAVAILABLE (0x00) -#define MPI25_IOUNITPAGE7_PM_MODE_UNKNOWN (0x01) -#define MPI25_IOUNITPAGE7_PM_MODE_FULL_POWER (0x04) -#define MPI25_IOUNITPAGE7_PM_MODE_REDUCED_POWER (0x05) -#define MPI25_IOUNITPAGE7_PM_MODE_STANDBY (0x06) - - -/*defines for IO Unit Page 7 PCIeWidth field */ -#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1 (0x01) -#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X2 (0x02) -#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X4 (0x04) -#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X8 (0x08) - -/*defines for IO Unit Page 7 PCIeSpeed field */ -#define MPI2_IOUNITPAGE7_PCIE_SPEED_2_5_GBPS (0x00) -#define MPI2_IOUNITPAGE7_PCIE_SPEED_5_0_GBPS (0x01) -#define MPI2_IOUNITPAGE7_PCIE_SPEED_8_0_GBPS (0x02) - -/*defines for IO Unit Page 7 ProcessorState field */ -#define MPI2_IOUNITPAGE7_PSTATE_MASK_SECOND (0x0000000F) -#define MPI2_IOUNITPAGE7_PSTATE_SHIFT_SECOND (0) - -#define MPI2_IOUNITPAGE7_PSTATE_NOT_PRESENT (0x00) -#define MPI2_IOUNITPAGE7_PSTATE_DISABLED (0x01) -#define MPI2_IOUNITPAGE7_PSTATE_ENABLED (0x02) - -/*defines for IO Unit Page 7 PowerManagementCapabilities field */ -#define MPI25_IOUNITPAGE7_PMCAP_DPA_FULL_PWR_MODE (0x00400000) -#define MPI25_IOUNITPAGE7_PMCAP_DPA_REDUCED_PWR_MODE (0x00200000) -#define MPI25_IOUNITPAGE7_PMCAP_DPA_STANDBY_MODE (0x00100000) -#define MPI25_IOUNITPAGE7_PMCAP_HOST_FULL_PWR_MODE (0x00040000) -#define MPI25_IOUNITPAGE7_PMCAP_HOST_REDUCED_PWR_MODE (0x00020000) -#define MPI25_IOUNITPAGE7_PMCAP_HOST_STANDBY_MODE (0x00010000) -#define MPI25_IOUNITPAGE7_PMCAP_IO_FULL_PWR_MODE (0x00004000) -#define MPI25_IOUNITPAGE7_PMCAP_IO_REDUCED_PWR_MODE (0x00002000) -#define MPI25_IOUNITPAGE7_PMCAP_IO_STANDBY_MODE (0x00001000) -#define MPI2_IOUNITPAGE7_PMCAP_HOST_12_5_PCT_IOCSPEED (0x00000400) -#define MPI2_IOUNITPAGE7_PMCAP_HOST_25_0_PCT_IOCSPEED (0x00000200) -#define MPI2_IOUNITPAGE7_PMCAP_HOST_50_0_PCT_IOCSPEED (0x00000100) -#define MPI25_IOUNITPAGE7_PMCAP_IO_12_5_PCT_IOCSPEED (0x00000040) -#define MPI25_IOUNITPAGE7_PMCAP_IO_25_0_PCT_IOCSPEED (0x00000020) -#define MPI25_IOUNITPAGE7_PMCAP_IO_50_0_PCT_IOCSPEED (0x00000010) -#define MPI2_IOUNITPAGE7_PMCAP_HOST_WIDTH_CHANGE_PCIE (0x00000008) -#define MPI2_IOUNITPAGE7_PMCAP_HOST_SPEED_CHANGE_PCIE (0x00000004) -#define MPI25_IOUNITPAGE7_PMCAP_IO_WIDTH_CHANGE_PCIE (0x00000002) -#define MPI25_IOUNITPAGE7_PMCAP_IO_SPEED_CHANGE_PCIE (0x00000001) - -/*obsolete names for the PowerManagementCapabilities bits (above) */ -#define MPI2_IOUNITPAGE7_PMCAP_12_5_PCT_IOCSPEED (0x00000400) -#define MPI2_IOUNITPAGE7_PMCAP_25_0_PCT_IOCSPEED (0x00000200) -#define MPI2_IOUNITPAGE7_PMCAP_50_0_PCT_IOCSPEED (0x00000100) -#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE (0x00000008) /*obsolete */ -#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE (0x00000004) /*obsolete */ - - -/*defines for IO Unit Page 7 IOCTemperatureUnits field */ -#define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT (0x00) -#define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT (0x01) -#define MPI2_IOUNITPAGE7_IOC_TEMP_CELSIUS (0x02) - -/*defines for IO Unit Page 7 IOCSpeed field */ -#define MPI2_IOUNITPAGE7_IOC_SPEED_FULL (0x01) -#define MPI2_IOUNITPAGE7_IOC_SPEED_HALF (0x02) -#define MPI2_IOUNITPAGE7_IOC_SPEED_QUARTER (0x04) -#define MPI2_IOUNITPAGE7_IOC_SPEED_EIGHTH (0x08) - -/*defines for IO Unit Page 7 BoardTemperatureUnits field */ -#define MPI2_IOUNITPAGE7_BOARD_TEMP_NOT_PRESENT (0x00) -#define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT (0x01) -#define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS (0x02) - - -/*IO Unit Page 8 */ - -#define MPI2_IOUNIT8_NUM_THRESHOLDS (4) - -typedef struct _MPI2_IOUNIT8_SENSOR { - U16 Flags; /*0x00 */ - U16 Reserved1; /*0x02 */ - U16 - Threshold[MPI2_IOUNIT8_NUM_THRESHOLDS]; /*0x04 */ - U32 Reserved2; /*0x0C */ - U32 Reserved3; /*0x10 */ - U32 Reserved4; /*0x14 */ -} MPI2_IOUNIT8_SENSOR, *PTR_MPI2_IOUNIT8_SENSOR, - Mpi2IOUnit8Sensor_t, *pMpi2IOUnit8Sensor_t; - -/*defines for IO Unit Page 8 Sensor Flags field */ -#define MPI2_IOUNIT8_SENSOR_FLAGS_T3_ENABLE (0x0008) -#define MPI2_IOUNIT8_SENSOR_FLAGS_T2_ENABLE (0x0004) -#define MPI2_IOUNIT8_SENSOR_FLAGS_T1_ENABLE (0x0002) -#define MPI2_IOUNIT8_SENSOR_FLAGS_T0_ENABLE (0x0001) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumSensors at runtime. - */ -#ifndef MPI2_IOUNITPAGE8_SENSOR_ENTRIES -#define MPI2_IOUNITPAGE8_SENSOR_ENTRIES (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Reserved2; /*0x08 */ - U8 NumSensors; /*0x0C */ - U8 PollingInterval; /*0x0D */ - U16 Reserved3; /*0x0E */ - MPI2_IOUNIT8_SENSOR - Sensor[MPI2_IOUNITPAGE8_SENSOR_ENTRIES];/*0x10 */ -} MPI2_CONFIG_PAGE_IO_UNIT_8, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_8, - Mpi2IOUnitPage8_t, *pMpi2IOUnitPage8_t; - -#define MPI2_IOUNITPAGE8_PAGEVERSION (0x00) - - -/*IO Unit Page 9 */ - -typedef struct _MPI2_IOUNIT9_SENSOR { - U16 CurrentTemperature; /*0x00 */ - U16 Reserved1; /*0x02 */ - U8 Flags; /*0x04 */ - U8 Reserved2; /*0x05 */ - U16 Reserved3; /*0x06 */ - U32 Reserved4; /*0x08 */ - U32 Reserved5; /*0x0C */ -} MPI2_IOUNIT9_SENSOR, *PTR_MPI2_IOUNIT9_SENSOR, - Mpi2IOUnit9Sensor_t, *pMpi2IOUnit9Sensor_t; - -/*defines for IO Unit Page 9 Sensor Flags field */ -#define MPI2_IOUNIT9_SENSOR_FLAGS_TEMP_VALID (0x01) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumSensors at runtime. - */ -#ifndef MPI2_IOUNITPAGE9_SENSOR_ENTRIES -#define MPI2_IOUNITPAGE9_SENSOR_ENTRIES (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Reserved2; /*0x08 */ - U8 NumSensors; /*0x0C */ - U8 Reserved4; /*0x0D */ - U16 Reserved3; /*0x0E */ - MPI2_IOUNIT9_SENSOR - Sensor[MPI2_IOUNITPAGE9_SENSOR_ENTRIES];/*0x10 */ -} MPI2_CONFIG_PAGE_IO_UNIT_9, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_9, - Mpi2IOUnitPage9_t, *pMpi2IOUnitPage9_t; - -#define MPI2_IOUNITPAGE9_PAGEVERSION (0x00) - - -/*IO Unit Page 10 */ - -typedef struct _MPI2_IOUNIT10_FUNCTION { - U8 CreditPercent; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ -} MPI2_IOUNIT10_FUNCTION, - *PTR_MPI2_IOUNIT10_FUNCTION, - Mpi2IOUnit10Function_t, - *pMpi2IOUnit10Function_t; - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumFunctions at runtime. - */ -#ifndef MPI2_IOUNITPAGE10_FUNCTION_ENTRIES -#define MPI2_IOUNITPAGE10_FUNCTION_ENTRIES (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 NumFunctions; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 Reserved2; /*0x06 */ - U32 Reserved3; /*0x08 */ - U32 Reserved4; /*0x0C */ - MPI2_IOUNIT10_FUNCTION - Function[MPI2_IOUNITPAGE10_FUNCTION_ENTRIES];/*0x10 */ -} MPI2_CONFIG_PAGE_IO_UNIT_10, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_10, - Mpi2IOUnitPage10_t, *pMpi2IOUnitPage10_t; - -#define MPI2_IOUNITPAGE10_PAGEVERSION (0x01) - - - -/**************************************************************************** -* IOC Config Pages -****************************************************************************/ - -/*IOC Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_IOC_0 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Reserved2; /*0x08 */ - U16 VendorID; /*0x0C */ - U16 DeviceID; /*0x0E */ - U8 RevisionID; /*0x10 */ - U8 Reserved3; /*0x11 */ - U16 Reserved4; /*0x12 */ - U32 ClassCode; /*0x14 */ - U16 SubsystemVendorID; /*0x18 */ - U16 SubsystemID; /*0x1A */ -} MPI2_CONFIG_PAGE_IOC_0, - *PTR_MPI2_CONFIG_PAGE_IOC_0, - Mpi2IOCPage0_t, *pMpi2IOCPage0_t; - -#define MPI2_IOCPAGE0_PAGEVERSION (0x02) - - -/*IOC Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_IOC_1 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Flags; /*0x04 */ - U32 CoalescingTimeout; /*0x08 */ - U8 CoalescingDepth; /*0x0C */ - U8 PCISlotNum; /*0x0D */ - U8 PCIBusNum; /*0x0E */ - U8 PCIDomainSegment; /*0x0F */ - U32 Reserved1; /*0x10 */ - U32 Reserved2; /*0x14 */ -} MPI2_CONFIG_PAGE_IOC_1, - *PTR_MPI2_CONFIG_PAGE_IOC_1, - Mpi2IOCPage1_t, *pMpi2IOCPage1_t; - -#define MPI2_IOCPAGE1_PAGEVERSION (0x05) - -/*defines for IOC Page 1 Flags field */ -#define MPI2_IOCPAGE1_REPLY_COALESCING (0x00000001) - -#define MPI2_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF) -#define MPI2_IOCPAGE1_PCIBUSNUM_UNKNOWN (0xFF) -#define MPI2_IOCPAGE1_PCIDOMAIN_UNKNOWN (0xFF) - -/*IOC Page 6 */ - -typedef struct _MPI2_CONFIG_PAGE_IOC_6 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 - CapabilitiesFlags; /*0x04 */ - U8 MaxDrivesRAID0; /*0x08 */ - U8 MaxDrivesRAID1; /*0x09 */ - U8 - MaxDrivesRAID1E; /*0x0A */ - U8 - MaxDrivesRAID10; /*0x0B */ - U8 MinDrivesRAID0; /*0x0C */ - U8 MinDrivesRAID1; /*0x0D */ - U8 - MinDrivesRAID1E; /*0x0E */ - U8 - MinDrivesRAID10; /*0x0F */ - U32 Reserved1; /*0x10 */ - U8 - MaxGlobalHotSpares; /*0x14 */ - U8 MaxPhysDisks; /*0x15 */ - U8 MaxVolumes; /*0x16 */ - U8 MaxConfigs; /*0x17 */ - U8 MaxOCEDisks; /*0x18 */ - U8 Reserved2; /*0x19 */ - U16 Reserved3; /*0x1A */ - U32 - SupportedStripeSizeMapRAID0; /*0x1C */ - U32 - SupportedStripeSizeMapRAID1E; /*0x20 */ - U32 - SupportedStripeSizeMapRAID10; /*0x24 */ - U32 Reserved4; /*0x28 */ - U32 Reserved5; /*0x2C */ - U16 - DefaultMetadataSize; /*0x30 */ - U16 Reserved6; /*0x32 */ - U16 - MaxBadBlockTableEntries; /*0x34 */ - U16 Reserved7; /*0x36 */ - U32 - IRNvsramVersion; /*0x38 */ -} MPI2_CONFIG_PAGE_IOC_6, - *PTR_MPI2_CONFIG_PAGE_IOC_6, - Mpi2IOCPage6_t, *pMpi2IOCPage6_t; - -#define MPI2_IOCPAGE6_PAGEVERSION (0x05) - -/*defines for IOC Page 6 CapabilitiesFlags */ -#define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT (0x00000020) -#define MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT (0x00000010) -#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT (0x00000008) -#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT (0x00000004) -#define MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT (0x00000002) -#define MPI2_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001) - - -/*IOC Page 7 */ - -#define MPI2_IOCPAGE7_EVENTMASK_WORDS (4) - -typedef struct _MPI2_CONFIG_PAGE_IOC_7 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 - EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/*0x08 */ - U16 SASBroadcastPrimitiveMasks; /*0x18 */ - U16 SASNotifyPrimitiveMasks; /*0x1A */ - U32 Reserved3; /*0x1C */ -} MPI2_CONFIG_PAGE_IOC_7, - *PTR_MPI2_CONFIG_PAGE_IOC_7, - Mpi2IOCPage7_t, *pMpi2IOCPage7_t; - -#define MPI2_IOCPAGE7_PAGEVERSION (0x02) - - -/*IOC Page 8 */ - -typedef struct _MPI2_CONFIG_PAGE_IOC_8 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 NumDevsPerEnclosure; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 Reserved2; /*0x06 */ - U16 MaxPersistentEntries; /*0x08 */ - U16 MaxNumPhysicalMappedIDs; /*0x0A */ - U16 Flags; /*0x0C */ - U16 Reserved3; /*0x0E */ - U16 IRVolumeMappingFlags; /*0x10 */ - U16 Reserved4; /*0x12 */ - U32 Reserved5; /*0x14 */ -} MPI2_CONFIG_PAGE_IOC_8, - *PTR_MPI2_CONFIG_PAGE_IOC_8, - Mpi2IOCPage8_t, *pMpi2IOCPage8_t; - -#define MPI2_IOCPAGE8_PAGEVERSION (0x00) - -/*defines for IOC Page 8 Flags field */ -#define MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1 (0x00000020) -#define MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0 (0x00000010) - -#define MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE (0x0000000E) -#define MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING (0x00000000) -#define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING (0x00000002) - -#define MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING (0x00000001) -#define MPI2_IOCPAGE8_FLAGS_ENABLE_PERSISTENT_MAPPING (0x00000000) - -/*defines for IOC Page 8 IRVolumeMappingFlags */ -#define MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE (0x00000003) -#define MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING (0x00000000) -#define MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING (0x00000001) - - -/**************************************************************************** -* BIOS Config Pages -****************************************************************************/ - -/*BIOS Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_BIOS_1 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 BiosOptions; /*0x04 */ - U32 IOCSettings; /*0x08 */ - U32 Reserved1; /*0x0C */ - U32 DeviceSettings; /*0x10 */ - U16 NumberOfDevices; /*0x14 */ - U16 UEFIVersion; /*0x16 */ - U16 IOTimeoutBlockDevicesNonRM; /*0x18 */ - U16 IOTimeoutSequential; /*0x1A */ - U16 IOTimeoutOther; /*0x1C */ - U16 IOTimeoutBlockDevicesRM; /*0x1E */ -} MPI2_CONFIG_PAGE_BIOS_1, - *PTR_MPI2_CONFIG_PAGE_BIOS_1, - Mpi2BiosPage1_t, *pMpi2BiosPage1_t; - -#define MPI2_BIOSPAGE1_PAGEVERSION (0x05) - -/*values for BIOS Page 1 BiosOptions field */ -#define MPI2_BIOSPAGE1_OPTIONS_MASK_UEFI_HII_REGISTRATION (0x00000006) -#define MPI2_BIOSPAGE1_OPTIONS_ENABLE_UEFI_HII (0x00000000) -#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_UEFI_HII (0x00000002) -#define MPI2_BIOSPAGE1_OPTIONS_VERSION_CHECK_UEFI_HII (0x00000004) - -#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) - -/*values for BIOS Page 1 IOCSettings field */ -#define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000) -#define MPI2_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000) -#define MPI2_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000) - -#define MPI2_BIOSPAGE1_IOCSET_MASK_RM_SETTING (0x000000C0) -#define MPI2_BIOSPAGE1_IOCSET_NONE_RM_SETTING (0x00000000) -#define MPI2_BIOSPAGE1_IOCSET_BOOT_RM_SETTING (0x00000040) -#define MPI2_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING (0x00000080) - -#define MPI2_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT (0x00000030) -#define MPI2_BIOSPAGE1_IOCSET_NO_SUPPORT (0x00000000) -#define MPI2_BIOSPAGE1_IOCSET_BIOS_SUPPORT (0x00000010) -#define MPI2_BIOSPAGE1_IOCSET_OS_SUPPORT (0x00000020) -#define MPI2_BIOSPAGE1_IOCSET_ALL_SUPPORT (0x00000030) - -#define MPI2_BIOSPAGE1_IOCSET_ALTERNATE_CHS (0x00000008) - -/*values for BIOS Page 1 DeviceSettings field */ -#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING (0x00000010) -#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN (0x00000008) -#define MPI2_BIOSPAGE1_DEVSET_DISABLE_RM_LUN (0x00000004) -#define MPI2_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002) -#define MPI2_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001) - -/*defines for BIOS Page 1 UEFIVersion field */ -#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_MASK (0xFF00) -#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_SHIFT (8) -#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_MASK (0x00FF) -#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_SHIFT (0) - - - -/*BIOS Page 2 */ - -typedef struct _MPI2_BOOT_DEVICE_ADAPTER_ORDER { - U32 Reserved1; /*0x00 */ - U32 Reserved2; /*0x04 */ - U32 Reserved3; /*0x08 */ - U32 Reserved4; /*0x0C */ - U32 Reserved5; /*0x10 */ - U32 Reserved6; /*0x14 */ -} MPI2_BOOT_DEVICE_ADAPTER_ORDER, - *PTR_MPI2_BOOT_DEVICE_ADAPTER_ORDER, - Mpi2BootDeviceAdapterOrder_t, - *pMpi2BootDeviceAdapterOrder_t; - -typedef struct _MPI2_BOOT_DEVICE_SAS_WWID { - U64 SASAddress; /*0x00 */ - U8 LUN[8]; /*0x08 */ - U32 Reserved1; /*0x10 */ - U32 Reserved2; /*0x14 */ -} MPI2_BOOT_DEVICE_SAS_WWID, - *PTR_MPI2_BOOT_DEVICE_SAS_WWID, - Mpi2BootDeviceSasWwid_t, - *pMpi2BootDeviceSasWwid_t; - -typedef struct _MPI2_BOOT_DEVICE_ENCLOSURE_SLOT { - U64 EnclosureLogicalID; /*0x00 */ - U32 Reserved1; /*0x08 */ - U32 Reserved2; /*0x0C */ - U16 SlotNumber; /*0x10 */ - U16 Reserved3; /*0x12 */ - U32 Reserved4; /*0x14 */ -} MPI2_BOOT_DEVICE_ENCLOSURE_SLOT, - *PTR_MPI2_BOOT_DEVICE_ENCLOSURE_SLOT, - Mpi2BootDeviceEnclosureSlot_t, - *pMpi2BootDeviceEnclosureSlot_t; - -typedef struct _MPI2_BOOT_DEVICE_DEVICE_NAME { - U64 DeviceName; /*0x00 */ - U8 LUN[8]; /*0x08 */ - U32 Reserved1; /*0x10 */ - U32 Reserved2; /*0x14 */ -} MPI2_BOOT_DEVICE_DEVICE_NAME, - *PTR_MPI2_BOOT_DEVICE_DEVICE_NAME, - Mpi2BootDeviceDeviceName_t, - *pMpi2BootDeviceDeviceName_t; - -typedef union _MPI2_MPI2_BIOSPAGE2_BOOT_DEVICE { - MPI2_BOOT_DEVICE_ADAPTER_ORDER AdapterOrder; - MPI2_BOOT_DEVICE_SAS_WWID SasWwid; - MPI2_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot; - MPI2_BOOT_DEVICE_DEVICE_NAME DeviceName; -} MPI2_BIOSPAGE2_BOOT_DEVICE, - *PTR_MPI2_BIOSPAGE2_BOOT_DEVICE, - Mpi2BiosPage2BootDevice_t, - *pMpi2BiosPage2BootDevice_t; - -typedef struct _MPI2_CONFIG_PAGE_BIOS_2 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Reserved2; /*0x08 */ - U32 Reserved3; /*0x0C */ - U32 Reserved4; /*0x10 */ - U32 Reserved5; /*0x14 */ - U32 Reserved6; /*0x18 */ - U8 ReqBootDeviceForm; /*0x1C */ - U8 Reserved7; /*0x1D */ - U16 Reserved8; /*0x1E */ - MPI2_BIOSPAGE2_BOOT_DEVICE RequestedBootDevice; /*0x20 */ - U8 ReqAltBootDeviceForm; /*0x38 */ - U8 Reserved9; /*0x39 */ - U16 Reserved10; /*0x3A */ - MPI2_BIOSPAGE2_BOOT_DEVICE RequestedAltBootDevice; /*0x3C */ - U8 CurrentBootDeviceForm; /*0x58 */ - U8 Reserved11; /*0x59 */ - U16 Reserved12; /*0x5A */ - MPI2_BIOSPAGE2_BOOT_DEVICE CurrentBootDevice; /*0x58 */ -} MPI2_CONFIG_PAGE_BIOS_2, *PTR_MPI2_CONFIG_PAGE_BIOS_2, - Mpi2BiosPage2_t, *pMpi2BiosPage2_t; - -#define MPI2_BIOSPAGE2_PAGEVERSION (0x04) - -/*values for BIOS Page 2 BootDeviceForm fields */ -#define MPI2_BIOSPAGE2_FORM_MASK (0x0F) -#define MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED (0x00) -#define MPI2_BIOSPAGE2_FORM_SAS_WWID (0x05) -#define MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06) -#define MPI2_BIOSPAGE2_FORM_DEVICE_NAME (0x07) - - -/*BIOS Page 3 */ - -typedef struct _MPI2_ADAPTER_INFO { - U8 PciBusNumber; /*0x00 */ - U8 PciDeviceAndFunctionNumber; /*0x01 */ - U16 AdapterFlags; /*0x02 */ -} MPI2_ADAPTER_INFO, *PTR_MPI2_ADAPTER_INFO, - Mpi2AdapterInfo_t, *pMpi2AdapterInfo_t; - -#define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED (0x0001) -#define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS (0x0002) - -typedef struct _MPI2_CONFIG_PAGE_BIOS_3 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 GlobalFlags; /*0x04 */ - U32 BiosVersion; /*0x08 */ - MPI2_ADAPTER_INFO AdapterOrder[4]; /*0x0C */ - U32 Reserved1; /*0x1C */ -} MPI2_CONFIG_PAGE_BIOS_3, - *PTR_MPI2_CONFIG_PAGE_BIOS_3, - Mpi2BiosPage3_t, *pMpi2BiosPage3_t; - -#define MPI2_BIOSPAGE3_PAGEVERSION (0x00) - -/*values for BIOS Page 3 GlobalFlags */ -#define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR (0x00000002) -#define MPI2_BIOSPAGE3_FLAGS_VERBOSE_ENABLE (0x00000004) -#define MPI2_BIOSPAGE3_FLAGS_HOOK_INT_40_DISABLE (0x00000010) - -#define MPI2_BIOSPAGE3_FLAGS_DEV_LIST_DISPLAY_MASK (0x000000E0) -#define MPI2_BIOSPAGE3_FLAGS_INSTALLED_DEV_DISPLAY (0x00000000) -#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DISPLAY (0x00000020) -#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DEV_DISPLAY (0x00000040) - - -/*BIOS Page 4 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES -#define MPI2_BIOS_PAGE_4_PHY_ENTRIES (1) -#endif - -typedef struct _MPI2_BIOS4_ENTRY { - U64 ReassignmentWWID; /*0x00 */ - U64 ReassignmentDeviceName; /*0x08 */ -} MPI2_BIOS4_ENTRY, *PTR_MPI2_BIOS4_ENTRY, - Mpi2MBios4Entry_t, *pMpi2Bios4Entry_t; - -typedef struct _MPI2_CONFIG_PAGE_BIOS_4 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 NumPhys; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 Reserved2; /*0x06 */ - MPI2_BIOS4_ENTRY - Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES]; /*0x08 */ -} MPI2_CONFIG_PAGE_BIOS_4, *PTR_MPI2_CONFIG_PAGE_BIOS_4, - Mpi2BiosPage4_t, *pMpi2BiosPage4_t; - -#define MPI2_BIOSPAGE4_PAGEVERSION (0x01) - - -/**************************************************************************** -* RAID Volume Config Pages -****************************************************************************/ - -/*RAID Volume Page 0 */ - -typedef struct _MPI2_RAIDVOL0_PHYS_DISK { - U8 RAIDSetNum; /*0x00 */ - U8 PhysDiskMap; /*0x01 */ - U8 PhysDiskNum; /*0x02 */ - U8 Reserved; /*0x03 */ -} MPI2_RAIDVOL0_PHYS_DISK, *PTR_MPI2_RAIDVOL0_PHYS_DISK, - Mpi2RaidVol0PhysDisk_t, *pMpi2RaidVol0PhysDisk_t; - -/*defines for the PhysDiskMap field */ -#define MPI2_RAIDVOL0_PHYSDISK_PRIMARY (0x01) -#define MPI2_RAIDVOL0_PHYSDISK_SECONDARY (0x02) - -typedef struct _MPI2_RAIDVOL0_SETTINGS { - U16 Settings; /*0x00 */ - U8 HotSparePool; /*0x01 */ - U8 Reserved; /*0x02 */ -} MPI2_RAIDVOL0_SETTINGS, *PTR_MPI2_RAIDVOL0_SETTINGS, - Mpi2RaidVol0Settings_t, - *pMpi2RaidVol0Settings_t; - -/*RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */ -#define MPI2_RAID_HOT_SPARE_POOL_0 (0x01) -#define MPI2_RAID_HOT_SPARE_POOL_1 (0x02) -#define MPI2_RAID_HOT_SPARE_POOL_2 (0x04) -#define MPI2_RAID_HOT_SPARE_POOL_3 (0x08) -#define MPI2_RAID_HOT_SPARE_POOL_4 (0x10) -#define MPI2_RAID_HOT_SPARE_POOL_5 (0x20) -#define MPI2_RAID_HOT_SPARE_POOL_6 (0x40) -#define MPI2_RAID_HOT_SPARE_POOL_7 (0x80) - -/*RAID Volume Page 0 VolumeSettings defines */ -#define MPI2_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0008) -#define MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE (0x0004) - -#define MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING (0x0003) -#define MPI2_RAIDVOL0_SETTING_UNCHANGED (0x0000) -#define MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING (0x0001) -#define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING (0x0002) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhysDisks at runtime. - */ -#ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX -#define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U16 DevHandle; /*0x04 */ - U8 VolumeState; /*0x06 */ - U8 VolumeType; /*0x07 */ - U32 VolumeStatusFlags; /*0x08 */ - MPI2_RAIDVOL0_SETTINGS VolumeSettings; /*0x0C */ - U64 MaxLBA; /*0x10 */ - U32 StripeSize; /*0x18 */ - U16 BlockSize; /*0x1C */ - U16 Reserved1; /*0x1E */ - U8 SupportedPhysDisks;/*0x20 */ - U8 ResyncRate; /*0x21 */ - U16 DataScrubDuration; /*0x22 */ - U8 NumPhysDisks; /*0x24 */ - U8 Reserved2; /*0x25 */ - U8 Reserved3; /*0x26 */ - U8 InactiveStatus; /*0x27 */ - MPI2_RAIDVOL0_PHYS_DISK - PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /*0x28 */ -} MPI2_CONFIG_PAGE_RAID_VOL_0, - *PTR_MPI2_CONFIG_PAGE_RAID_VOL_0, - Mpi2RaidVolPage0_t, *pMpi2RaidVolPage0_t; - -#define MPI2_RAIDVOLPAGE0_PAGEVERSION (0x0A) - -/*values for RAID VolumeState */ -#define MPI2_RAID_VOL_STATE_MISSING (0x00) -#define MPI2_RAID_VOL_STATE_FAILED (0x01) -#define MPI2_RAID_VOL_STATE_INITIALIZING (0x02) -#define MPI2_RAID_VOL_STATE_ONLINE (0x03) -#define MPI2_RAID_VOL_STATE_DEGRADED (0x04) -#define MPI2_RAID_VOL_STATE_OPTIMAL (0x05) - -/*values for RAID VolumeType */ -#define MPI2_RAID_VOL_TYPE_RAID0 (0x00) -#define MPI2_RAID_VOL_TYPE_RAID1E (0x01) -#define MPI2_RAID_VOL_TYPE_RAID1 (0x02) -#define MPI2_RAID_VOL_TYPE_RAID10 (0x05) -#define MPI2_RAID_VOL_TYPE_UNKNOWN (0xFF) - -/*values for RAID Volume Page 0 VolumeStatusFlags field */ -#define MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC (0x02000000) -#define MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING (0x01000000) -#define MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING (0x00800000) -#define MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING (0x00400000) -#define MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT (0x00200000) -#define MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB (0x00100000) -#define MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK (0x00080000) -#define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION (0x00040000) -#define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT (0x00020000) -#define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x00010000) -#define MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT (0x00000080) -#define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED (0x00000040) -#define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE (0x00000020) -#define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR (0x00000000) -#define MPI2_RAIDVOL0_STATUS_FLAG_1E_ADJACENT_MIRROR (0x00000010) -#define MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL (0x00000008) -#define MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x00000004) -#define MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED (0x00000002) -#define MPI2_RAIDVOL0_STATUS_FLAG_ENABLED (0x00000001) - -/*values for RAID Volume Page 0 SupportedPhysDisks field */ -#define MPI2_RAIDVOL0_SUPPORT_SOLID_STATE_DISKS (0x08) -#define MPI2_RAIDVOL0_SUPPORT_HARD_DISKS (0x04) -#define MPI2_RAIDVOL0_SUPPORT_SAS_PROTOCOL (0x02) -#define MPI2_RAIDVOL0_SUPPORT_SATA_PROTOCOL (0x01) - -/*values for RAID Volume Page 0 InactiveStatus field */ -#define MPI2_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00) -#define MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE (0x01) -#define MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE (0x02) -#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE (0x03) -#define MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE (0x04) -#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE (0x05) -#define MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED (0x06) - - -/*RAID Volume Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_1 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U16 DevHandle; /*0x04 */ - U16 Reserved0; /*0x06 */ - U8 GUID[24]; /*0x08 */ - U8 Name[16]; /*0x20 */ - U64 WWID; /*0x30 */ - U32 Reserved1; /*0x38 */ - U32 Reserved2; /*0x3C */ -} MPI2_CONFIG_PAGE_RAID_VOL_1, - *PTR_MPI2_CONFIG_PAGE_RAID_VOL_1, - Mpi2RaidVolPage1_t, *pMpi2RaidVolPage1_t; - -#define MPI2_RAIDVOLPAGE1_PAGEVERSION (0x03) - - -/**************************************************************************** -* RAID Physical Disk Config Pages -****************************************************************************/ - -/*RAID Physical Disk Page 0 */ - -typedef struct _MPI2_RAIDPHYSDISK0_SETTINGS { - U16 Reserved1; /*0x00 */ - U8 HotSparePool; /*0x02 */ - U8 Reserved2; /*0x03 */ -} MPI2_RAIDPHYSDISK0_SETTINGS, - *PTR_MPI2_RAIDPHYSDISK0_SETTINGS, - Mpi2RaidPhysDisk0Settings_t, - *pMpi2RaidPhysDisk0Settings_t; - -/*use MPI2_RAID_HOT_SPARE_POOL_ defines for the HotSparePool field */ - -typedef struct _MPI2_RAIDPHYSDISK0_INQUIRY_DATA { - U8 VendorID[8]; /*0x00 */ - U8 ProductID[16]; /*0x08 */ - U8 ProductRevLevel[4]; /*0x18 */ - U8 SerialNum[32]; /*0x1C */ -} MPI2_RAIDPHYSDISK0_INQUIRY_DATA, - *PTR_MPI2_RAIDPHYSDISK0_INQUIRY_DATA, - Mpi2RaidPhysDisk0InquiryData_t, - *pMpi2RaidPhysDisk0InquiryData_t; - -typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U16 DevHandle; /*0x04 */ - U8 Reserved1; /*0x06 */ - U8 PhysDiskNum; /*0x07 */ - MPI2_RAIDPHYSDISK0_SETTINGS PhysDiskSettings; /*0x08 */ - U32 Reserved2; /*0x0C */ - MPI2_RAIDPHYSDISK0_INQUIRY_DATA InquiryData; /*0x10 */ - U32 Reserved3; /*0x4C */ - U8 PhysDiskState; /*0x50 */ - U8 OfflineReason; /*0x51 */ - U8 IncompatibleReason; /*0x52 */ - U8 PhysDiskAttributes; /*0x53 */ - U32 PhysDiskStatusFlags;/*0x54 */ - U64 DeviceMaxLBA; /*0x58 */ - U64 HostMaxLBA; /*0x60 */ - U64 CoercedMaxLBA; /*0x68 */ - U16 BlockSize; /*0x70 */ - U16 Reserved5; /*0x72 */ - U32 Reserved6; /*0x74 */ -} MPI2_CONFIG_PAGE_RD_PDISK_0, - *PTR_MPI2_CONFIG_PAGE_RD_PDISK_0, - Mpi2RaidPhysDiskPage0_t, - *pMpi2RaidPhysDiskPage0_t; - -#define MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION (0x05) - -/*PhysDiskState defines */ -#define MPI2_RAID_PD_STATE_NOT_CONFIGURED (0x00) -#define MPI2_RAID_PD_STATE_NOT_COMPATIBLE (0x01) -#define MPI2_RAID_PD_STATE_OFFLINE (0x02) -#define MPI2_RAID_PD_STATE_ONLINE (0x03) -#define MPI2_RAID_PD_STATE_HOT_SPARE (0x04) -#define MPI2_RAID_PD_STATE_DEGRADED (0x05) -#define MPI2_RAID_PD_STATE_REBUILDING (0x06) -#define MPI2_RAID_PD_STATE_OPTIMAL (0x07) - -/*OfflineReason defines */ -#define MPI2_PHYSDISK0_ONLINE (0x00) -#define MPI2_PHYSDISK0_OFFLINE_MISSING (0x01) -#define MPI2_PHYSDISK0_OFFLINE_FAILED (0x03) -#define MPI2_PHYSDISK0_OFFLINE_INITIALIZING (0x04) -#define MPI2_PHYSDISK0_OFFLINE_REQUESTED (0x05) -#define MPI2_PHYSDISK0_OFFLINE_FAILED_REQUESTED (0x06) -#define MPI2_PHYSDISK0_OFFLINE_OTHER (0xFF) - -/*IncompatibleReason defines */ -#define MPI2_PHYSDISK0_COMPATIBLE (0x00) -#define MPI2_PHYSDISK0_INCOMPATIBLE_PROTOCOL (0x01) -#define MPI2_PHYSDISK0_INCOMPATIBLE_BLOCKSIZE (0x02) -#define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA (0x03) -#define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD (0x04) -#define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA (0x05) -#define MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE (0x06) -#define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN (0xFF) - -/*PhysDiskAttributes defines */ -#define MPI2_PHYSDISK0_ATTRIB_MEDIA_MASK (0x0C) -#define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE (0x08) -#define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE (0x04) - -#define MPI2_PHYSDISK0_ATTRIB_PROTOCOL_MASK (0x03) -#define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL (0x02) -#define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL (0x01) - -/*PhysDiskStatusFlags defines */ -#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED (0x00000040) -#define MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET (0x00000020) -#define MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED (0x00000010) -#define MPI2_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS (0x00000000) -#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x00000008) -#define MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x00000004) -#define MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED (0x00000002) -#define MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x00000001) - - -/*RAID Physical Disk Page 1 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhysDiskPaths at runtime. - */ -#ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX -#define MPI2_RAID_PHYS_DISK1_PATH_MAX (1) -#endif - -typedef struct _MPI2_RAIDPHYSDISK1_PATH { - U16 DevHandle; /*0x00 */ - U16 Reserved1; /*0x02 */ - U64 WWID; /*0x04 */ - U64 OwnerWWID; /*0x0C */ - U8 OwnerIdentifier; /*0x14 */ - U8 Reserved2; /*0x15 */ - U16 Flags; /*0x16 */ -} MPI2_RAIDPHYSDISK1_PATH, *PTR_MPI2_RAIDPHYSDISK1_PATH, - Mpi2RaidPhysDisk1Path_t, - *pMpi2RaidPhysDisk1Path_t; - -/*RAID Physical Disk Page 1 Physical Disk Path Flags field defines */ -#define MPI2_RAID_PHYSDISK1_FLAG_PRIMARY (0x0004) -#define MPI2_RAID_PHYSDISK1_FLAG_BROKEN (0x0002) -#define MPI2_RAID_PHYSDISK1_FLAG_INVALID (0x0001) - -typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 NumPhysDiskPaths; /*0x04 */ - U8 PhysDiskNum; /*0x05 */ - U16 Reserved1; /*0x06 */ - U32 Reserved2; /*0x08 */ - MPI2_RAIDPHYSDISK1_PATH - PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/*0x0C */ -} MPI2_CONFIG_PAGE_RD_PDISK_1, - *PTR_MPI2_CONFIG_PAGE_RD_PDISK_1, - Mpi2RaidPhysDiskPage1_t, - *pMpi2RaidPhysDiskPage1_t; - -#define MPI2_RAIDPHYSDISKPAGE1_PAGEVERSION (0x02) - - -/**************************************************************************** -* values for fields used by several types of SAS Config Pages -****************************************************************************/ - -/*values for NegotiatedLinkRates fields */ -#define MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL (0xF0) -#define MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL (4) -#define MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL (0x0F) -/*link rates used for Negotiated Physical and Logical Link Rate */ -#define MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE (0x00) -#define MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED (0x01) -#define MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED (0x02) -#define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE (0x03) -#define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR (0x04) -#define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS (0x05) -#define MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY (0x06) -#define MPI2_SAS_NEG_LINK_RATE_1_5 (0x08) -#define MPI2_SAS_NEG_LINK_RATE_3_0 (0x09) -#define MPI2_SAS_NEG_LINK_RATE_6_0 (0x0A) -#define MPI25_SAS_NEG_LINK_RATE_12_0 (0x0B) - - -/*values for AttachedPhyInfo fields */ -#define MPI2_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT (0x00000040) -#define MPI2_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS (0x00000020) -#define MPI2_SAS_APHYINFO_BREAK_REPLY_CAPABLE (0x00000010) - -#define MPI2_SAS_APHYINFO_REASON_MASK (0x0000000F) -#define MPI2_SAS_APHYINFO_REASON_UNKNOWN (0x00000000) -#define MPI2_SAS_APHYINFO_REASON_POWER_ON (0x00000001) -#define MPI2_SAS_APHYINFO_REASON_HARD_RESET (0x00000002) -#define MPI2_SAS_APHYINFO_REASON_SMP_PHY_CONTROL (0x00000003) -#define MPI2_SAS_APHYINFO_REASON_LOSS_OF_SYNC (0x00000004) -#define MPI2_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ (0x00000005) -#define MPI2_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00000006) -#define MPI2_SAS_APHYINFO_REASON_BREAK_TIMEOUT (0x00000007) -#define MPI2_SAS_APHYINFO_REASON_PHY_TEST_STOPPED (0x00000008) - - -/*values for PhyInfo fields */ -#define MPI2_SAS_PHYINFO_PHY_VACANT (0x80000000) - -#define MPI2_SAS_PHYINFO_PHY_POWER_CONDITION_MASK (0x18000000) -#define MPI2_SAS_PHYINFO_SHIFT_PHY_POWER_CONDITION (27) -#define MPI2_SAS_PHYINFO_PHY_POWER_ACTIVE (0x00000000) -#define MPI2_SAS_PHYINFO_PHY_POWER_PARTIAL (0x08000000) -#define MPI2_SAS_PHYINFO_PHY_POWER_SLUMBER (0x10000000) - -#define MPI2_SAS_PHYINFO_CHANGED_REQ_INSIDE_ZPSDS (0x04000000) -#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT (0x02000000) -#define MPI2_SAS_PHYINFO_REQ_INSIDE_ZPSDS (0x01000000) -#define MPI2_SAS_PHYINFO_ZONE_GROUP_PERSISTENT (0x00400000) -#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS (0x00200000) -#define MPI2_SAS_PHYINFO_ZONING_ENABLED (0x00100000) - -#define MPI2_SAS_PHYINFO_REASON_MASK (0x000F0000) -#define MPI2_SAS_PHYINFO_REASON_UNKNOWN (0x00000000) -#define MPI2_SAS_PHYINFO_REASON_POWER_ON (0x00010000) -#define MPI2_SAS_PHYINFO_REASON_HARD_RESET (0x00020000) -#define MPI2_SAS_PHYINFO_REASON_SMP_PHY_CONTROL (0x00030000) -#define MPI2_SAS_PHYINFO_REASON_LOSS_OF_SYNC (0x00040000) -#define MPI2_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ (0x00050000) -#define MPI2_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00060000) -#define MPI2_SAS_PHYINFO_REASON_BREAK_TIMEOUT (0x00070000) -#define MPI2_SAS_PHYINFO_REASON_PHY_TEST_STOPPED (0x00080000) - -#define MPI2_SAS_PHYINFO_MULTIPLEXING_SUPPORTED (0x00008000) -#define MPI2_SAS_PHYINFO_SATA_PORT_ACTIVE (0x00004000) -#define MPI2_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT (0x00002000) -#define MPI2_SAS_PHYINFO_VIRTUAL_PHY (0x00001000) - -#define MPI2_SAS_PHYINFO_MASK_PARTIAL_PATHWAY_TIME (0x00000F00) -#define MPI2_SAS_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME (8) - -#define MPI2_SAS_PHYINFO_MASK_ROUTING_ATTRIBUTE (0x000000F0) -#define MPI2_SAS_PHYINFO_DIRECT_ROUTING (0x00000000) -#define MPI2_SAS_PHYINFO_SUBTRACTIVE_ROUTING (0x00000010) -#define MPI2_SAS_PHYINFO_TABLE_ROUTING (0x00000020) - - -/*values for SAS ProgrammedLinkRate fields */ -#define MPI2_SAS_PRATE_MAX_RATE_MASK (0xF0) -#define MPI2_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE (0x00) -#define MPI2_SAS_PRATE_MAX_RATE_1_5 (0x80) -#define MPI2_SAS_PRATE_MAX_RATE_3_0 (0x90) -#define MPI2_SAS_PRATE_MAX_RATE_6_0 (0xA0) -#define MPI2_SAS_PRATE_MIN_RATE_MASK (0x0F) -#define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00) -#define MPI2_SAS_PRATE_MIN_RATE_1_5 (0x08) -#define MPI2_SAS_PRATE_MIN_RATE_3_0 (0x09) -#define MPI2_SAS_PRATE_MIN_RATE_6_0 (0x0A) -#define MPI25_SAS_PRATE_MIN_RATE_12_0 (0x0B) - - -/*values for SAS HwLinkRate fields */ -#define MPI2_SAS_HWRATE_MAX_RATE_MASK (0xF0) -#define MPI2_SAS_HWRATE_MAX_RATE_1_5 (0x80) -#define MPI2_SAS_HWRATE_MAX_RATE_3_0 (0x90) -#define MPI2_SAS_HWRATE_MAX_RATE_6_0 (0xA0) -#define MPI2_SAS_HWRATE_MIN_RATE_MASK (0x0F) -#define MPI2_SAS_HWRATE_MIN_RATE_1_5 (0x08) -#define MPI2_SAS_HWRATE_MIN_RATE_3_0 (0x09) -#define MPI2_SAS_HWRATE_MIN_RATE_6_0 (0x0A) -#define MPI25_SAS_HWRATE_MIN_RATE_12_0 (0x0B) - - - -/**************************************************************************** -* SAS IO Unit Config Pages -****************************************************************************/ - -/*SAS IO Unit Page 0 */ - -typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA { - U8 Port; /*0x00 */ - U8 PortFlags; /*0x01 */ - U8 PhyFlags; /*0x02 */ - U8 NegotiatedLinkRate; /*0x03 */ - U32 ControllerPhyDeviceInfo;/*0x04 */ - U16 AttachedDevHandle; /*0x08 */ - U16 ControllerDevHandle; /*0x0A */ - U32 DiscoveryStatus; /*0x0C */ - U32 Reserved; /*0x10 */ -} MPI2_SAS_IO_UNIT0_PHY_DATA, - *PTR_MPI2_SAS_IO_UNIT0_PHY_DATA, - Mpi2SasIOUnit0PhyData_t, - *pMpi2SasIOUnit0PhyData_t; - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_SAS_IOUNIT0_PHY_MAX -#define MPI2_SAS_IOUNIT0_PHY_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1;/*0x08 */ - U8 NumPhys; /*0x0C */ - U8 Reserved2;/*0x0D */ - U16 Reserved3;/*0x0E */ - MPI2_SAS_IO_UNIT0_PHY_DATA - PhyData[MPI2_SAS_IOUNIT0_PHY_MAX]; /*0x10 */ -} MPI2_CONFIG_PAGE_SASIOUNIT_0, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0, - Mpi2SasIOUnitPage0_t, *pMpi2SasIOUnitPage0_t; - -#define MPI2_SASIOUNITPAGE0_PAGEVERSION (0x05) - -/*values for SAS IO Unit Page 0 PortFlags */ -#define MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS (0x08) -#define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG (0x01) - -/*values for SAS IO Unit Page 0 PhyFlags */ -#define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED (0x10) -#define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08) - -/*use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ - -/*see mpi2_sas.h for values for - *SAS IO Unit Page 0 ControllerPhyDeviceInfo values */ - -/*values for SAS IO Unit Page 0 DiscoveryStatus */ -#define MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED (0x80000000) -#define MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED (0x40000000) -#define MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED (0x20000000) -#define MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) -#define MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR (0x08000000) -#define MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) -#define MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) -#define MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN (0x00002000) -#define MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) -#define MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800) -#define MPI2_SASIOUNIT0_DS_TABLE_LINK (0x00000400) -#define MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200) -#define MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR (0x00000100) -#define MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED (0x00000080) -#define MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST (0x00000040) -#define MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES (0x00000020) -#define MPI2_SASIOUNIT0_DS_SMP_TIMEOUT (0x00000010) -#define MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS (0x00000004) -#define MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE (0x00000002) -#define MPI2_SASIOUNIT0_DS_LOOP_DETECTED (0x00000001) - - -/*SAS IO Unit Page 1 */ - -typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA { - U8 Port; /*0x00 */ - U8 PortFlags; /*0x01 */ - U8 PhyFlags; /*0x02 */ - U8 MaxMinLinkRate; /*0x03 */ - U32 ControllerPhyDeviceInfo; /*0x04 */ - U16 MaxTargetPortConnectTime; /*0x08 */ - U16 Reserved1; /*0x0A */ -} MPI2_SAS_IO_UNIT1_PHY_DATA, - *PTR_MPI2_SAS_IO_UNIT1_PHY_DATA, - Mpi2SasIOUnit1PhyData_t, - *pMpi2SasIOUnit1PhyData_t; - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_SAS_IOUNIT1_PHY_MAX -#define MPI2_SAS_IOUNIT1_PHY_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U16 - ControlFlags; /*0x08 */ - U16 - SASNarrowMaxQueueDepth; /*0x0A */ - U16 - AdditionalControlFlags; /*0x0C */ - U16 - SASWideMaxQueueDepth; /*0x0E */ - U8 - NumPhys; /*0x10 */ - U8 - SATAMaxQDepth; /*0x11 */ - U8 - ReportDeviceMissingDelay; /*0x12 */ - U8 - IODeviceMissingDelay; /*0x13 */ - MPI2_SAS_IO_UNIT1_PHY_DATA - PhyData[MPI2_SAS_IOUNIT1_PHY_MAX]; /*0x14 */ -} MPI2_CONFIG_PAGE_SASIOUNIT_1, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1, - Mpi2SasIOUnitPage1_t, *pMpi2SasIOUnitPage1_t; - -#define MPI2_SASIOUNITPAGE1_PAGEVERSION (0x09) - -/*values for SAS IO Unit Page 1 ControlFlags */ -#define MPI2_SASIOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) -#define MPI2_SASIOUNIT1_CONTROL_SATA_3_0_MAX (0x4000) -#define MPI2_SASIOUNIT1_CONTROL_SATA_1_5_MAX (0x2000) -#define MPI2_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) - -#define MPI2_SASIOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600) -#define MPI2_SASIOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9) -#define MPI2_SASIOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x0) -#define MPI2_SASIOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x1) -#define MPI2_SASIOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x2) - -#define MPI2_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) -#define MPI2_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) -#define MPI2_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) -#define MPI2_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) -#define MPI2_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL (0x0008) -#define MPI2_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) -#define MPI2_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) -#define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) - -/*values for SAS IO Unit Page 1 AdditionalControlFlags */ -#define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080) -#define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040) -#define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION (0x0020) -#define MPI2_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010) -#define MPI2_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008) -#define MPI2_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004) -#define MPI2_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002) -#define MPI2_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001) - -/*defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */ -#define MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F) -#define MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16 (0x80) - -/*values for SAS IO Unit Page 1 PortFlags */ -#define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) - -/*values for SAS IO Unit Page 1 PhyFlags */ -#define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE (0x10) -#define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08) - -/*values for SAS IO Unit Page 1 MaxMinLinkRate */ -#define MPI2_SASIOUNIT1_MAX_RATE_MASK (0xF0) -#define MPI2_SASIOUNIT1_MAX_RATE_1_5 (0x80) -#define MPI2_SASIOUNIT1_MAX_RATE_3_0 (0x90) -#define MPI2_SASIOUNIT1_MAX_RATE_6_0 (0xA0) -#define MPI25_SASIOUNIT1_MAX_RATE_12_0 (0xB0) -#define MPI2_SASIOUNIT1_MIN_RATE_MASK (0x0F) -#define MPI2_SASIOUNIT1_MIN_RATE_1_5 (0x08) -#define MPI2_SASIOUNIT1_MIN_RATE_3_0 (0x09) -#define MPI2_SASIOUNIT1_MIN_RATE_6_0 (0x0A) -#define MPI25_SASIOUNIT1_MIN_RATE_12_0 (0x0B) - -/*see mpi2_sas.h for values for - *SAS IO Unit Page 1 ControllerPhyDeviceInfo values */ - - -/*SAS IO Unit Page 4 */ - -typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP { - U8 MaxTargetSpinup; /*0x00 */ - U8 SpinupDelay; /*0x01 */ - U8 SpinupFlags; /*0x02 */ - U8 Reserved1; /*0x03 */ -} MPI2_SAS_IOUNIT4_SPINUP_GROUP, - *PTR_MPI2_SAS_IOUNIT4_SPINUP_GROUP, - Mpi2SasIOUnit4SpinupGroup_t, - *pMpi2SasIOUnit4SpinupGroup_t; -/*defines for SAS IO Unit Page 4 SpinupFlags */ -#define MPI2_SASIOUNIT4_SPINUP_DISABLE_FLAG (0x01) - - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_SAS_IOUNIT4_PHY_MAX -#define MPI2_SAS_IOUNIT4_PHY_MAX (4) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header;/*0x00 */ - MPI2_SAS_IOUNIT4_SPINUP_GROUP - SpinupGroupParameters[4]; /*0x08 */ - U32 - Reserved1; /*0x18 */ - U32 - Reserved2; /*0x1C */ - U32 - Reserved3; /*0x20 */ - U8 - BootDeviceWaitTime; /*0x24 */ - U8 - Reserved4; /*0x25 */ - U16 - Reserved5; /*0x26 */ - U8 - NumPhys; /*0x28 */ - U8 - PEInitialSpinupDelay; /*0x29 */ - U8 - PEReplyDelay; /*0x2A */ - U8 - Flags; /*0x2B */ - U8 - PHY[MPI2_SAS_IOUNIT4_PHY_MAX]; /*0x2C */ -} MPI2_CONFIG_PAGE_SASIOUNIT_4, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_4, - Mpi2SasIOUnitPage4_t, *pMpi2SasIOUnitPage4_t; - -#define MPI2_SASIOUNITPAGE4_PAGEVERSION (0x02) - -/*defines for Flags field */ -#define MPI2_SASIOUNIT4_FLAGS_AUTO_PORTENABLE (0x01) - -/*defines for PHY field */ -#define MPI2_SASIOUNIT4_PHY_SPINUP_GROUP_MASK (0x03) - - -/*SAS IO Unit Page 5 */ - -typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS { - U8 ControlFlags; /*0x00 */ - U8 PortWidthModGroup; /*0x01 */ - U16 InactivityTimerExponent; /*0x02 */ - U8 SATAPartialTimeout; /*0x04 */ - U8 Reserved2; /*0x05 */ - U8 SATASlumberTimeout; /*0x06 */ - U8 Reserved3; /*0x07 */ - U8 SASPartialTimeout; /*0x08 */ - U8 Reserved4; /*0x09 */ - U8 SASSlumberTimeout; /*0x0A */ - U8 Reserved5; /*0x0B */ -} MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS, - *PTR_MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS, - Mpi2SasIOUnit5PhyPmSettings_t, - *pMpi2SasIOUnit5PhyPmSettings_t; - -/*defines for ControlFlags field */ -#define MPI2_SASIOUNIT5_CONTROL_SAS_SLUMBER_ENABLE (0x08) -#define MPI2_SASIOUNIT5_CONTROL_SAS_PARTIAL_ENABLE (0x04) -#define MPI2_SASIOUNIT5_CONTROL_SATA_SLUMBER_ENABLE (0x02) -#define MPI2_SASIOUNIT5_CONTROL_SATA_PARTIAL_ENABLE (0x01) - -/*defines for PortWidthModeGroup field */ -#define MPI2_SASIOUNIT5_PWMG_DISABLE (0xFF) - -/*defines for InactivityTimerExponent field */ -#define MPI2_SASIOUNIT5_ITE_MASK_SAS_SLUMBER (0x7000) -#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_SLUMBER (12) -#define MPI2_SASIOUNIT5_ITE_MASK_SAS_PARTIAL (0x0700) -#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_PARTIAL (8) -#define MPI2_SASIOUNIT5_ITE_MASK_SATA_SLUMBER (0x0070) -#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_SLUMBER (4) -#define MPI2_SASIOUNIT5_ITE_MASK_SATA_PARTIAL (0x0007) -#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_PARTIAL (0) - -#define MPI2_SASIOUNIT5_ITE_TEN_SECONDS (7) -#define MPI2_SASIOUNIT5_ITE_ONE_SECOND (6) -#define MPI2_SASIOUNIT5_ITE_HUNDRED_MILLISECONDS (5) -#define MPI2_SASIOUNIT5_ITE_TEN_MILLISECONDS (4) -#define MPI2_SASIOUNIT5_ITE_ONE_MILLISECOND (3) -#define MPI2_SASIOUNIT5_ITE_HUNDRED_MICROSECONDS (2) -#define MPI2_SASIOUNIT5_ITE_TEN_MICROSECONDS (1) -#define MPI2_SASIOUNIT5_ITE_ONE_MICROSECOND (0) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_SAS_IOUNIT5_PHY_MAX -#define MPI2_SAS_IOUNIT5_PHY_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U8 NumPhys; /*0x08 */ - U8 Reserved1;/*0x09 */ - U16 Reserved2;/*0x0A */ - U32 Reserved3;/*0x0C */ - MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS - SASPhyPowerManagementSettings[MPI2_SAS_IOUNIT5_PHY_MAX];/*0x10 */ -} MPI2_CONFIG_PAGE_SASIOUNIT_5, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_5, - Mpi2SasIOUnitPage5_t, *pMpi2SasIOUnitPage5_t; - -#define MPI2_SASIOUNITPAGE5_PAGEVERSION (0x01) - - -/*SAS IO Unit Page 6 */ - -typedef struct _MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS { - U8 CurrentStatus; /*0x00 */ - U8 CurrentModulation; /*0x01 */ - U8 CurrentUtilization; /*0x02 */ - U8 Reserved1; /*0x03 */ - U32 Reserved2; /*0x04 */ -} MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS, - *PTR_MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS, - Mpi2SasIOUnit6PortWidthModGroupStatus_t, - *pMpi2SasIOUnit6PortWidthModGroupStatus_t; - -/*defines for CurrentStatus field */ -#define MPI2_SASIOUNIT6_STATUS_UNAVAILABLE (0x00) -#define MPI2_SASIOUNIT6_STATUS_UNCONFIGURED (0x01) -#define MPI2_SASIOUNIT6_STATUS_INVALID_CONFIG (0x02) -#define MPI2_SASIOUNIT6_STATUS_LINK_DOWN (0x03) -#define MPI2_SASIOUNIT6_STATUS_OBSERVATION_ONLY (0x04) -#define MPI2_SASIOUNIT6_STATUS_INACTIVE (0x05) -#define MPI2_SASIOUNIT6_STATUS_ACTIVE_IOUNIT (0x06) -#define MPI2_SASIOUNIT6_STATUS_ACTIVE_HOST (0x07) - -/*defines for CurrentModulation field */ -#define MPI2_SASIOUNIT6_MODULATION_25_PERCENT (0x00) -#define MPI2_SASIOUNIT6_MODULATION_50_PERCENT (0x01) -#define MPI2_SASIOUNIT6_MODULATION_75_PERCENT (0x02) -#define MPI2_SASIOUNIT6_MODULATION_100_PERCENT (0x03) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumGroups at runtime. - */ -#ifndef MPI2_SAS_IOUNIT6_GROUP_MAX -#define MPI2_SAS_IOUNIT6_GROUP_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x08 */ - U32 Reserved2; /*0x0C */ - U8 NumGroups; /*0x10 */ - U8 Reserved3; /*0x11 */ - U16 Reserved4; /*0x12 */ - MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS - PortWidthModulationGroupStatus[MPI2_SAS_IOUNIT6_GROUP_MAX]; /*0x14 */ -} MPI2_CONFIG_PAGE_SASIOUNIT_6, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_6, - Mpi2SasIOUnitPage6_t, *pMpi2SasIOUnitPage6_t; - -#define MPI2_SASIOUNITPAGE6_PAGEVERSION (0x00) - - -/*SAS IO Unit Page 7 */ - -typedef struct _MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS { - U8 Flags; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U8 Threshold75Pct; /*0x04 */ - U8 Threshold50Pct; /*0x05 */ - U8 Threshold25Pct; /*0x06 */ - U8 Reserved3; /*0x07 */ -} MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS, - *PTR_MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS, - Mpi2SasIOUnit7PortWidthModGroupSettings_t, - *pMpi2SasIOUnit7PortWidthModGroupSettings_t; - -/*defines for Flags field */ -#define MPI2_SASIOUNIT7_FLAGS_ENABLE_PORT_WIDTH_MODULATION (0x01) - - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumGroups at runtime. - */ -#ifndef MPI2_SAS_IOUNIT7_GROUP_MAX -#define MPI2_SAS_IOUNIT7_GROUP_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U8 SamplingInterval; /*0x08 */ - U8 WindowLength; /*0x09 */ - U16 Reserved1; /*0x0A */ - U32 Reserved2; /*0x0C */ - U32 Reserved3; /*0x10 */ - U8 NumGroups; /*0x14 */ - U8 Reserved4; /*0x15 */ - U16 Reserved5; /*0x16 */ - MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS - PortWidthModulationGroupSettings[MPI2_SAS_IOUNIT7_GROUP_MAX];/*0x18 */ -} MPI2_CONFIG_PAGE_SASIOUNIT_7, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_7, - Mpi2SasIOUnitPage7_t, *pMpi2SasIOUnitPage7_t; - -#define MPI2_SASIOUNITPAGE7_PAGEVERSION (0x00) - - -/*SAS IO Unit Page 8 */ - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_8 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved1; /*0x08 */ - U32 - PowerManagementCapabilities; /*0x0C */ - U8 - TxRxSleepStatus; /*0x10 */ - U8 - Reserved2; /*0x11 */ - U16 - Reserved3; /*0x12 */ -} MPI2_CONFIG_PAGE_SASIOUNIT_8, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_8, - Mpi2SasIOUnitPage8_t, *pMpi2SasIOUnitPage8_t; - -#define MPI2_SASIOUNITPAGE8_PAGEVERSION (0x00) - -/*defines for PowerManagementCapabilities field */ -#define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD (0x00001000) -#define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE (0x00000800) -#define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE (0x00000400) -#define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE (0x00000200) -#define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE (0x00000100) -#define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD (0x00000010) -#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE (0x00000008) -#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE (0x00000004) -#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE (0x00000002) -#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE (0x00000001) - -/*defines for TxRxSleepStatus field */ -#define MPI25_SASIOUNIT8_TXRXSLEEP_UNSUPPORTED (0x00) -#define MPI25_SASIOUNIT8_TXRXSLEEP_DISENGAGED (0x01) -#define MPI25_SASIOUNIT8_TXRXSLEEP_ACTIVE (0x02) -#define MPI25_SASIOUNIT8_TXRXSLEEP_SHUTDOWN (0x03) - - - -/*SAS IO Unit Page 16 */ - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT16 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U64 - TimeStamp; /*0x08 */ - U32 - Reserved1; /*0x10 */ - U32 - Reserved2; /*0x14 */ - U32 - FastPathPendedRequests; /*0x18 */ - U32 - FastPathUnPendedRequests; /*0x1C */ - U32 - FastPathHostRequestStarts; /*0x20 */ - U32 - FastPathFirmwareRequestStarts; /*0x24 */ - U32 - FastPathHostCompletions; /*0x28 */ - U32 - FastPathFirmwareCompletions; /*0x2C */ - U32 - NonFastPathRequestStarts; /*0x30 */ - U32 - NonFastPathHostCompletions; /*0x30 */ -} MPI2_CONFIG_PAGE_SASIOUNIT16, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT16, - Mpi2SasIOUnitPage16_t, *pMpi2SasIOUnitPage16_t; - -#define MPI2_SASIOUNITPAGE16_PAGEVERSION (0x00) - - -/**************************************************************************** -* SAS Expander Config Pages -****************************************************************************/ - -/*SAS Expander Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U8 - PhysicalPort; /*0x08 */ - U8 - ReportGenLength; /*0x09 */ - U16 - EnclosureHandle; /*0x0A */ - U64 - SASAddress; /*0x0C */ - U32 - DiscoveryStatus; /*0x14 */ - U16 - DevHandle; /*0x18 */ - U16 - ParentDevHandle; /*0x1A */ - U16 - ExpanderChangeCount; /*0x1C */ - U16 - ExpanderRouteIndexes; /*0x1E */ - U8 - NumPhys; /*0x20 */ - U8 - SASLevel; /*0x21 */ - U16 - Flags; /*0x22 */ - U16 - STPBusInactivityTimeLimit; /*0x24 */ - U16 - STPMaxConnectTimeLimit; /*0x26 */ - U16 - STP_SMP_NexusLossTime; /*0x28 */ - U16 - MaxNumRoutedSasAddresses; /*0x2A */ - U64 - ActiveZoneManagerSASAddress;/*0x2C */ - U16 - ZoneLockInactivityLimit; /*0x34 */ - U16 - Reserved1; /*0x36 */ - U8 - TimeToReducedFunc; /*0x38 */ - U8 - InitialTimeToReducedFunc; /*0x39 */ - U8 - MaxReducedFuncTime; /*0x3A */ - U8 - Reserved2; /*0x3B */ -} MPI2_CONFIG_PAGE_EXPANDER_0, - *PTR_MPI2_CONFIG_PAGE_EXPANDER_0, - Mpi2ExpanderPage0_t, *pMpi2ExpanderPage0_t; - -#define MPI2_SASEXPANDER0_PAGEVERSION (0x06) - -/*values for SAS Expander Page 0 DiscoveryStatus field */ -#define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED (0x80000000) -#define MPI2_SAS_EXPANDER0_DS_MAX_EXPANDERS_EXCEED (0x40000000) -#define MPI2_SAS_EXPANDER0_DS_MAX_DEVICES_EXCEED (0x20000000) -#define MPI2_SAS_EXPANDER0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) -#define MPI2_SAS_EXPANDER0_DS_DOWNSTREAM_INITIATOR (0x08000000) -#define MPI2_SAS_EXPANDER0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) -#define MPI2_SAS_EXPANDER0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) -#define MPI2_SAS_EXPANDER0_DS_MULTI_PORT_DOMAIN (0x00002000) -#define MPI2_SAS_EXPANDER0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) -#define MPI2_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE (0x00000800) -#define MPI2_SAS_EXPANDER0_DS_TABLE_LINK (0x00000400) -#define MPI2_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK (0x00000200) -#define MPI2_SAS_EXPANDER0_DS_SMP_CRC_ERROR (0x00000100) -#define MPI2_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED (0x00000080) -#define MPI2_SAS_EXPANDER0_DS_INDEX_NOT_EXIST (0x00000040) -#define MPI2_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES (0x00000020) -#define MPI2_SAS_EXPANDER0_DS_SMP_TIMEOUT (0x00000010) -#define MPI2_SAS_EXPANDER0_DS_MULTIPLE_PORTS (0x00000004) -#define MPI2_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE (0x00000002) -#define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001) - -/*values for SAS Expander Page 0 Flags field */ -#define MPI2_SAS_EXPANDER0_FLAGS_REDUCED_FUNCTIONALITY (0x2000) -#define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED (0x1000) -#define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES (0x0800) -#define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES (0x0400) -#define MPI2_SAS_EXPANDER0_FLAGS_ZONING_SUPPORT (0x0200) -#define MPI2_SAS_EXPANDER0_FLAGS_ENABLED_ZONING (0x0100) -#define MPI2_SAS_EXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT (0x0080) -#define MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE (0x0010) -#define MPI2_SAS_EXPANDER0_FLAGS_OTHERS_CONFIG (0x0004) -#define MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x0002) -#define MPI2_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x0001) - - -/*SAS Expander Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_EXPANDER_1 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U8 - PhysicalPort; /*0x08 */ - U8 - Reserved1; /*0x09 */ - U16 - Reserved2; /*0x0A */ - U8 - NumPhys; /*0x0C */ - U8 - Phy; /*0x0D */ - U16 - NumTableEntriesProgrammed; /*0x0E */ - U8 - ProgrammedLinkRate; /*0x10 */ - U8 - HwLinkRate; /*0x11 */ - U16 - AttachedDevHandle; /*0x12 */ - U32 - PhyInfo; /*0x14 */ - U32 - AttachedDeviceInfo; /*0x18 */ - U16 - ExpanderDevHandle; /*0x1C */ - U8 - ChangeCount; /*0x1E */ - U8 - NegotiatedLinkRate; /*0x1F */ - U8 - PhyIdentifier; /*0x20 */ - U8 - AttachedPhyIdentifier; /*0x21 */ - U8 - Reserved3; /*0x22 */ - U8 - DiscoveryInfo; /*0x23 */ - U32 - AttachedPhyInfo; /*0x24 */ - U8 - ZoneGroup; /*0x28 */ - U8 - SelfConfigStatus; /*0x29 */ - U16 - Reserved4; /*0x2A */ -} MPI2_CONFIG_PAGE_EXPANDER_1, - *PTR_MPI2_CONFIG_PAGE_EXPANDER_1, - Mpi2ExpanderPage1_t, *pMpi2ExpanderPage1_t; - -#define MPI2_SASEXPANDER1_PAGEVERSION (0x02) - -/*use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */ - -/*use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */ - -/*use MPI2_SAS_PHYINFO_ for the PhyInfo field */ - -/*see mpi2_sas.h for the MPI2_SAS_DEVICE_INFO_ defines - *used for the AttachedDeviceInfo field */ - -/*use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ - -/*values for SAS Expander Page 1 DiscoveryInfo field */ -#define MPI2_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04) -#define MPI2_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02) -#define MPI2_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01) - -/*use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ - - -/**************************************************************************** -* SAS Device Config Pages -****************************************************************************/ - -/*SAS Device Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U16 - Slot; /*0x08 */ - U16 - EnclosureHandle; /*0x0A */ - U64 - SASAddress; /*0x0C */ - U16 - ParentDevHandle; /*0x14 */ - U8 - PhyNum; /*0x16 */ - U8 - AccessStatus; /*0x17 */ - U16 - DevHandle; /*0x18 */ - U8 - AttachedPhyIdentifier; /*0x1A */ - U8 - ZoneGroup; /*0x1B */ - U32 - DeviceInfo; /*0x1C */ - U16 - Flags; /*0x20 */ - U8 - PhysicalPort; /*0x22 */ - U8 - MaxPortConnections; /*0x23 */ - U64 - DeviceName; /*0x24 */ - U8 - PortGroups; /*0x2C */ - U8 - DmaGroup; /*0x2D */ - U8 - ControlGroup; /*0x2E */ - U8 - Reserved1; /*0x2F */ - U32 - Reserved2; /*0x30 */ - U32 - Reserved3; /*0x34 */ -} MPI2_CONFIG_PAGE_SAS_DEV_0, - *PTR_MPI2_CONFIG_PAGE_SAS_DEV_0, - Mpi2SasDevicePage0_t, - *pMpi2SasDevicePage0_t; - -#define MPI2_SASDEVICE0_PAGEVERSION (0x08) - -/*values for SAS Device Page 0 AccessStatus field */ -#define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00) -#define MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01) -#define MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02) -#define MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03) -#define MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION (0x04) -#define MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE (0x05) -#define MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE (0x06) -#define MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED (0x07) -/*specific values for SATA Init failures */ -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG (0x12) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x13) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x14) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN (0x15) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN (0x16) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN (0x17) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x18) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x19) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX (0x1F) - -/*see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */ - -/*values for SAS Device Page 0 Flags field */ -#define MPI2_SAS_DEVICE0_FLAGS_UNAUTHORIZED_DEVICE (0x8000) -#define MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH (0x4000) -#define MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE (0x2000) -#define MPI2_SAS_DEVICE0_FLAGS_SLUMBER_PM_CAPABLE (0x1000) -#define MPI2_SAS_DEVICE0_FLAGS_PARTIAL_PM_CAPABLE (0x0800) -#define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400) -#define MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200) -#define MPI2_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100) -#define MPI2_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080) -#define MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040) -#define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) -#define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) -#define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) -#define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) - - -/*SAS Device Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_1 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved1; /*0x08 */ - U64 - SASAddress; /*0x0C */ - U32 - Reserved2; /*0x14 */ - U16 - DevHandle; /*0x18 */ - U16 - Reserved3; /*0x1A */ - U8 - InitialRegDeviceFIS[20];/*0x1C */ -} MPI2_CONFIG_PAGE_SAS_DEV_1, - *PTR_MPI2_CONFIG_PAGE_SAS_DEV_1, - Mpi2SasDevicePage1_t, - *pMpi2SasDevicePage1_t; - -#define MPI2_SASDEVICE1_PAGEVERSION (0x01) - - -/**************************************************************************** -* SAS PHY Config Pages -****************************************************************************/ - -/*SAS PHY Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U16 - OwnerDevHandle; /*0x08 */ - U16 - Reserved1; /*0x0A */ - U16 - AttachedDevHandle; /*0x0C */ - U8 - AttachedPhyIdentifier; /*0x0E */ - U8 - Reserved2; /*0x0F */ - U32 - AttachedPhyInfo; /*0x10 */ - U8 - ProgrammedLinkRate; /*0x14 */ - U8 - HwLinkRate; /*0x15 */ - U8 - ChangeCount; /*0x16 */ - U8 - Flags; /*0x17 */ - U32 - PhyInfo; /*0x18 */ - U8 - NegotiatedLinkRate; /*0x1C */ - U8 - Reserved3; /*0x1D */ - U16 - Reserved4; /*0x1E */ -} MPI2_CONFIG_PAGE_SAS_PHY_0, - *PTR_MPI2_CONFIG_PAGE_SAS_PHY_0, - Mpi2SasPhyPage0_t, *pMpi2SasPhyPage0_t; - -#define MPI2_SASPHY0_PAGEVERSION (0x03) - -/*use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ - -/*use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */ - -/*use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */ - -/*values for SAS PHY Page 0 Flags field */ -#define MPI2_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01) - -/*use MPI2_SAS_PHYINFO_ for the PhyInfo field */ - -/*use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ - - -/*SAS PHY Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved1; /*0x08 */ - U32 - InvalidDwordCount; /*0x0C */ - U32 - RunningDisparityErrorCount; /*0x10 */ - U32 - LossDwordSynchCount; /*0x14 */ - U32 - PhyResetProblemCount; /*0x18 */ -} MPI2_CONFIG_PAGE_SAS_PHY_1, - *PTR_MPI2_CONFIG_PAGE_SAS_PHY_1, - Mpi2SasPhyPage1_t, *pMpi2SasPhyPage1_t; - -#define MPI2_SASPHY1_PAGEVERSION (0x01) - - -/*SAS PHY Page 2 */ - -typedef struct _MPI2_SASPHY2_PHY_EVENT { - U8 PhyEventCode; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 PhyEventInfo; /*0x04 */ -} MPI2_SASPHY2_PHY_EVENT, *PTR_MPI2_SASPHY2_PHY_EVENT, - Mpi2SasPhy2PhyEvent_t, *pMpi2SasPhy2PhyEvent_t; - -/*use MPI2_SASPHY3_EVENT_CODE_ for the PhyEventCode field */ - - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhyEvents at runtime. - */ -#ifndef MPI2_SASPHY2_PHY_EVENT_MAX -#define MPI2_SASPHY2_PHY_EVENT_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved1; /*0x08 */ - U8 - NumPhyEvents; /*0x0C */ - U8 - Reserved2; /*0x0D */ - U16 - Reserved3; /*0x0E */ - MPI2_SASPHY2_PHY_EVENT - PhyEvent[MPI2_SASPHY2_PHY_EVENT_MAX]; /*0x10 */ -} MPI2_CONFIG_PAGE_SAS_PHY_2, - *PTR_MPI2_CONFIG_PAGE_SAS_PHY_2, - Mpi2SasPhyPage2_t, - *pMpi2SasPhyPage2_t; - -#define MPI2_SASPHY2_PAGEVERSION (0x00) - - -/*SAS PHY Page 3 */ - -typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG { - U8 PhyEventCode; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U8 CounterType; /*0x04 */ - U8 ThresholdWindow; /*0x05 */ - U8 TimeUnits; /*0x06 */ - U8 Reserved3; /*0x07 */ - U32 EventThreshold; /*0x08 */ - U16 ThresholdFlags; /*0x0C */ - U16 Reserved4; /*0x0E */ -} MPI2_SASPHY3_PHY_EVENT_CONFIG, - *PTR_MPI2_SASPHY3_PHY_EVENT_CONFIG, - Mpi2SasPhy3PhyEventConfig_t, - *pMpi2SasPhy3PhyEventConfig_t; - -/*values for PhyEventCode field */ -#define MPI2_SASPHY3_EVENT_CODE_NO_EVENT (0x00) -#define MPI2_SASPHY3_EVENT_CODE_INVALID_DWORD (0x01) -#define MPI2_SASPHY3_EVENT_CODE_RUNNING_DISPARITY_ERROR (0x02) -#define MPI2_SASPHY3_EVENT_CODE_LOSS_DWORD_SYNC (0x03) -#define MPI2_SASPHY3_EVENT_CODE_PHY_RESET_PROBLEM (0x04) -#define MPI2_SASPHY3_EVENT_CODE_ELASTICITY_BUF_OVERFLOW (0x05) -#define MPI2_SASPHY3_EVENT_CODE_RX_ERROR (0x06) -#define MPI2_SASPHY3_EVENT_CODE_RX_ADDR_FRAME_ERROR (0x20) -#define MPI2_SASPHY3_EVENT_CODE_TX_AC_OPEN_REJECT (0x21) -#define MPI2_SASPHY3_EVENT_CODE_RX_AC_OPEN_REJECT (0x22) -#define MPI2_SASPHY3_EVENT_CODE_TX_RC_OPEN_REJECT (0x23) -#define MPI2_SASPHY3_EVENT_CODE_RX_RC_OPEN_REJECT (0x24) -#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_PARTIAL_WAITING_ON (0x25) -#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_CONNECT_WAITING_ON (0x26) -#define MPI2_SASPHY3_EVENT_CODE_TX_BREAK (0x27) -#define MPI2_SASPHY3_EVENT_CODE_RX_BREAK (0x28) -#define MPI2_SASPHY3_EVENT_CODE_BREAK_TIMEOUT (0x29) -#define MPI2_SASPHY3_EVENT_CODE_CONNECTION (0x2A) -#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_PATHWAY_BLOCKED (0x2B) -#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_ARB_WAIT_TIME (0x2C) -#define MPI2_SASPHY3_EVENT_CODE_PEAK_ARB_WAIT_TIME (0x2D) -#define MPI2_SASPHY3_EVENT_CODE_PEAK_CONNECT_TIME (0x2E) -#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_FRAMES (0x40) -#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_FRAMES (0x41) -#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_ERROR_FRAMES (0x42) -#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_ERROR_FRAMES (0x43) -#define MPI2_SASPHY3_EVENT_CODE_TX_CREDIT_BLOCKED (0x44) -#define MPI2_SASPHY3_EVENT_CODE_RX_CREDIT_BLOCKED (0x45) -#define MPI2_SASPHY3_EVENT_CODE_TX_SATA_FRAMES (0x50) -#define MPI2_SASPHY3_EVENT_CODE_RX_SATA_FRAMES (0x51) -#define MPI2_SASPHY3_EVENT_CODE_SATA_OVERFLOW (0x52) -#define MPI2_SASPHY3_EVENT_CODE_TX_SMP_FRAMES (0x60) -#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_FRAMES (0x61) -#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_ERROR_FRAMES (0x63) -#define MPI2_SASPHY3_EVENT_CODE_HOTPLUG_TIMEOUT (0xD0) -#define MPI2_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE (0xD1) -#define MPI2_SASPHY3_EVENT_CODE_RX_AIP (0xD2) - -/*values for the CounterType field */ -#define MPI2_SASPHY3_COUNTER_TYPE_WRAPPING (0x00) -#define MPI2_SASPHY3_COUNTER_TYPE_SATURATING (0x01) -#define MPI2_SASPHY3_COUNTER_TYPE_PEAK_VALUE (0x02) - -/*values for the TimeUnits field */ -#define MPI2_SASPHY3_TIME_UNITS_10_MICROSECONDS (0x00) -#define MPI2_SASPHY3_TIME_UNITS_100_MICROSECONDS (0x01) -#define MPI2_SASPHY3_TIME_UNITS_1_MILLISECOND (0x02) -#define MPI2_SASPHY3_TIME_UNITS_10_MILLISECONDS (0x03) - -/*values for the ThresholdFlags field */ -#define MPI2_SASPHY3_TFLAGS_PHY_RESET (0x0002) -#define MPI2_SASPHY3_TFLAGS_EVENT_NOTIFY (0x0001) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhyEvents at runtime. - */ -#ifndef MPI2_SASPHY3_PHY_EVENT_MAX -#define MPI2_SASPHY3_PHY_EVENT_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved1; /*0x08 */ - U8 - NumPhyEvents; /*0x0C */ - U8 - Reserved2; /*0x0D */ - U16 - Reserved3; /*0x0E */ - MPI2_SASPHY3_PHY_EVENT_CONFIG - PhyEventConfig[MPI2_SASPHY3_PHY_EVENT_MAX]; /*0x10 */ -} MPI2_CONFIG_PAGE_SAS_PHY_3, - *PTR_MPI2_CONFIG_PAGE_SAS_PHY_3, - Mpi2SasPhyPage3_t, *pMpi2SasPhyPage3_t; - -#define MPI2_SASPHY3_PAGEVERSION (0x00) - - -/*SAS PHY Page 4 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_4 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U16 - Reserved1; /*0x08 */ - U8 - Reserved2; /*0x0A */ - U8 - Flags; /*0x0B */ - U8 - InitialFrame[28]; /*0x0C */ -} MPI2_CONFIG_PAGE_SAS_PHY_4, - *PTR_MPI2_CONFIG_PAGE_SAS_PHY_4, - Mpi2SasPhyPage4_t, *pMpi2SasPhyPage4_t; - -#define MPI2_SASPHY4_PAGEVERSION (0x00) - -/*values for the Flags field */ -#define MPI2_SASPHY4_FLAGS_FRAME_VALID (0x02) -#define MPI2_SASPHY4_FLAGS_SATA_FRAME (0x01) - - - - -/**************************************************************************** -* SAS Port Config Pages -****************************************************************************/ - -/*SAS Port Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U8 - PortNumber; /*0x08 */ - U8 - PhysicalPort; /*0x09 */ - U8 - PortWidth; /*0x0A */ - U8 - PhysicalPortWidth; /*0x0B */ - U8 - ZoneGroup; /*0x0C */ - U8 - Reserved1; /*0x0D */ - U16 - Reserved2; /*0x0E */ - U64 - SASAddress; /*0x10 */ - U32 - DeviceInfo; /*0x18 */ - U32 - Reserved3; /*0x1C */ - U32 - Reserved4; /*0x20 */ -} MPI2_CONFIG_PAGE_SAS_PORT_0, - *PTR_MPI2_CONFIG_PAGE_SAS_PORT_0, - Mpi2SasPortPage0_t, *pMpi2SasPortPage0_t; - -#define MPI2_SASPORT0_PAGEVERSION (0x00) - -/*see mpi2_sas.h for values for SAS Port Page 0 DeviceInfo values */ - - -/**************************************************************************** -* SAS Enclosure Config Pages -****************************************************************************/ - -/*SAS Enclosure Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved1; /*0x08 */ - U64 - EnclosureLogicalID; /*0x0C */ - U16 - Flags; /*0x14 */ - U16 - EnclosureHandle; /*0x16 */ - U16 - NumSlots; /*0x18 */ - U16 - StartSlot; /*0x1A */ - U16 - Reserved2; /*0x1C */ - U16 - SEPDevHandle; /*0x1E */ - U32 - Reserved3; /*0x20 */ - U32 - Reserved4; /*0x24 */ -} MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0, - *PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0, - Mpi2SasEnclosurePage0_t, *pMpi2SasEnclosurePage0_t; - -#define MPI2_SASENCLOSURE0_PAGEVERSION (0x03) - -/*values for SAS Enclosure Page 0 Flags field */ -#define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F) -#define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000) -#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001) -#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002) -#define MPI2_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003) -#define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004) -#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005) - - -/**************************************************************************** -* Log Config Page -****************************************************************************/ - -/*Log Page 0 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumLogEntries at runtime. - */ -#ifndef MPI2_LOG_0_NUM_LOG_ENTRIES -#define MPI2_LOG_0_NUM_LOG_ENTRIES (1) -#endif - -#define MPI2_LOG_0_LOG_DATA_LENGTH (0x1C) - -typedef struct _MPI2_LOG_0_ENTRY { - U64 TimeStamp; /*0x00 */ - U32 Reserved1; /*0x08 */ - U16 LogSequence; /*0x0C */ - U16 LogEntryQualifier; /*0x0E */ - U8 VP_ID; /*0x10 */ - U8 VF_ID; /*0x11 */ - U16 Reserved2; /*0x12 */ - U8 - LogData[MPI2_LOG_0_LOG_DATA_LENGTH];/*0x14 */ -} MPI2_LOG_0_ENTRY, *PTR_MPI2_LOG_0_ENTRY, - Mpi2Log0Entry_t, *pMpi2Log0Entry_t; - -/*values for Log Page 0 LogEntry LogEntryQualifier field */ -#define MPI2_LOG_0_ENTRY_QUAL_ENTRY_UNUSED (0x0000) -#define MPI2_LOG_0_ENTRY_QUAL_POWER_ON_RESET (0x0001) -#define MPI2_LOG_0_ENTRY_QUAL_TIMESTAMP_UPDATE (0x0002) -#define MPI2_LOG_0_ENTRY_QUAL_MIN_IMPLEMENT_SPEC (0x8000) -#define MPI2_LOG_0_ENTRY_QUAL_MAX_IMPLEMENT_SPEC (0xFFFF) - -typedef struct _MPI2_CONFIG_PAGE_LOG_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x08 */ - U32 Reserved2; /*0x0C */ - U16 NumLogEntries;/*0x10 */ - U16 Reserved3; /*0x12 */ - MPI2_LOG_0_ENTRY - LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /*0x14 */ -} MPI2_CONFIG_PAGE_LOG_0, *PTR_MPI2_CONFIG_PAGE_LOG_0, - Mpi2LogPage0_t, *pMpi2LogPage0_t; - -#define MPI2_LOG_0_PAGEVERSION (0x02) - - -/**************************************************************************** -* RAID Config Page -****************************************************************************/ - -/*RAID Page 0 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumElements at runtime. - */ -#ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS -#define MPI2_RAIDCONFIG0_MAX_ELEMENTS (1) -#endif - -typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT { - U16 ElementFlags; /*0x00 */ - U16 VolDevHandle; /*0x02 */ - U8 HotSparePool; /*0x04 */ - U8 PhysDiskNum; /*0x05 */ - U16 PhysDiskDevHandle; /*0x06 */ -} MPI2_RAIDCONFIG0_CONFIG_ELEMENT, - *PTR_MPI2_RAIDCONFIG0_CONFIG_ELEMENT, - Mpi2RaidConfig0ConfigElement_t, - *pMpi2RaidConfig0ConfigElement_t; - -/*values for the ElementFlags field */ -#define MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE (0x000F) -#define MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT (0x0000) -#define MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT (0x0001) -#define MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT (0x0002) -#define MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT (0x0003) - - -typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U8 NumHotSpares; /*0x08 */ - U8 NumPhysDisks; /*0x09 */ - U8 NumVolumes; /*0x0A */ - U8 ConfigNum; /*0x0B */ - U32 Flags; /*0x0C */ - U8 ConfigGUID[24]; /*0x10 */ - U32 Reserved1; /*0x28 */ - U8 NumElements; /*0x2C */ - U8 Reserved2; /*0x2D */ - U16 Reserved3; /*0x2E */ - MPI2_RAIDCONFIG0_CONFIG_ELEMENT - ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /*0x30 */ -} MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0, - *PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0, - Mpi2RaidConfigurationPage0_t, - *pMpi2RaidConfigurationPage0_t; - -#define MPI2_RAIDCONFIG0_PAGEVERSION (0x00) - -/*values for RAID Configuration Page 0 Flags field */ -#define MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG (0x00000001) - - -/**************************************************************************** -* Driver Persistent Mapping Config Pages -****************************************************************************/ - -/*Driver Persistent Mapping Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY { - U64 PhysicalIdentifier; /*0x00 */ - U16 MappingInformation; /*0x08 */ - U16 DeviceIndex; /*0x0A */ - U32 PhysicalBitsMapping; /*0x0C */ - U32 Reserved1; /*0x10 */ -} MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY, - *PTR_MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY, - Mpi2DriverMap0Entry_t, *pMpi2DriverMap0Entry_t; - -typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY Entry; /*0x08 */ -} MPI2_CONFIG_PAGE_DRIVER_MAPPING_0, - *PTR_MPI2_CONFIG_PAGE_DRIVER_MAPPING_0, - Mpi2DriverMappingPage0_t, *pMpi2DriverMappingPage0_t; - -#define MPI2_DRIVERMAPPING0_PAGEVERSION (0x00) - -/*values for Driver Persistent Mapping Page 0 MappingInformation field */ -#define MPI2_DRVMAP0_MAPINFO_SLOT_MASK (0x07F0) -#define MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT (4) -#define MPI2_DRVMAP0_MAPINFO_MISSING_MASK (0x000F) - - -/**************************************************************************** -* Ethernet Config Pages -****************************************************************************/ - -/*Ethernet Page 0 */ - -/*IP address (union of IPv4 and IPv6) */ -typedef union _MPI2_ETHERNET_IP_ADDR { - U32 IPv4Addr; - U32 IPv6Addr[4]; -} MPI2_ETHERNET_IP_ADDR, *PTR_MPI2_ETHERNET_IP_ADDR, - Mpi2EthernetIpAddr_t, *pMpi2EthernetIpAddr_t; - -#define MPI2_ETHERNET_HOST_NAME_LENGTH (32) - -typedef struct _MPI2_CONFIG_PAGE_ETHERNET_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U8 NumInterfaces; /*0x08 */ - U8 Reserved0; /*0x09 */ - U16 Reserved1; /*0x0A */ - U32 Status; /*0x0C */ - U8 MediaState; /*0x10 */ - U8 Reserved2; /*0x11 */ - U16 Reserved3; /*0x12 */ - U8 MacAddress[6]; /*0x14 */ - U8 Reserved4; /*0x1A */ - U8 Reserved5; /*0x1B */ - MPI2_ETHERNET_IP_ADDR IpAddress; /*0x1C */ - MPI2_ETHERNET_IP_ADDR SubnetMask; /*0x2C */ - MPI2_ETHERNET_IP_ADDR GatewayIpAddress;/*0x3C */ - MPI2_ETHERNET_IP_ADDR DNS1IpAddress; /*0x4C */ - MPI2_ETHERNET_IP_ADDR DNS2IpAddress; /*0x5C */ - MPI2_ETHERNET_IP_ADDR DhcpIpAddress; /*0x6C */ - U8 - HostName[MPI2_ETHERNET_HOST_NAME_LENGTH];/*0x7C */ -} MPI2_CONFIG_PAGE_ETHERNET_0, - *PTR_MPI2_CONFIG_PAGE_ETHERNET_0, - Mpi2EthernetPage0_t, *pMpi2EthernetPage0_t; - -#define MPI2_ETHERNETPAGE0_PAGEVERSION (0x00) - -/*values for Ethernet Page 0 Status field */ -#define MPI2_ETHPG0_STATUS_IPV6_CAPABLE (0x80000000) -#define MPI2_ETHPG0_STATUS_IPV4_CAPABLE (0x40000000) -#define MPI2_ETHPG0_STATUS_CONSOLE_CONNECTED (0x20000000) -#define MPI2_ETHPG0_STATUS_DEFAULT_IF (0x00000100) -#define MPI2_ETHPG0_STATUS_FW_DWNLD_ENABLED (0x00000080) -#define MPI2_ETHPG0_STATUS_TELNET_ENABLED (0x00000040) -#define MPI2_ETHPG0_STATUS_SSH2_ENABLED (0x00000020) -#define MPI2_ETHPG0_STATUS_DHCP_CLIENT_ENABLED (0x00000010) -#define MPI2_ETHPG0_STATUS_IPV6_ENABLED (0x00000008) -#define MPI2_ETHPG0_STATUS_IPV4_ENABLED (0x00000004) -#define MPI2_ETHPG0_STATUS_IPV6_ADDRESSES (0x00000002) -#define MPI2_ETHPG0_STATUS_ETH_IF_ENABLED (0x00000001) - -/*values for Ethernet Page 0 MediaState field */ -#define MPI2_ETHPG0_MS_DUPLEX_MASK (0x80) -#define MPI2_ETHPG0_MS_HALF_DUPLEX (0x00) -#define MPI2_ETHPG0_MS_FULL_DUPLEX (0x80) - -#define MPI2_ETHPG0_MS_CONNECT_SPEED_MASK (0x07) -#define MPI2_ETHPG0_MS_NOT_CONNECTED (0x00) -#define MPI2_ETHPG0_MS_10MBIT (0x01) -#define MPI2_ETHPG0_MS_100MBIT (0x02) -#define MPI2_ETHPG0_MS_1GBIT (0x03) - - -/*Ethernet Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_ETHERNET_1 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved0; /*0x08 */ - U32 - Flags; /*0x0C */ - U8 - MediaState; /*0x10 */ - U8 - Reserved1; /*0x11 */ - U16 - Reserved2; /*0x12 */ - U8 - MacAddress[6]; /*0x14 */ - U8 - Reserved3; /*0x1A */ - U8 - Reserved4; /*0x1B */ - MPI2_ETHERNET_IP_ADDR - StaticIpAddress; /*0x1C */ - MPI2_ETHERNET_IP_ADDR - StaticSubnetMask; /*0x2C */ - MPI2_ETHERNET_IP_ADDR - StaticGatewayIpAddress; /*0x3C */ - MPI2_ETHERNET_IP_ADDR - StaticDNS1IpAddress; /*0x4C */ - MPI2_ETHERNET_IP_ADDR - StaticDNS2IpAddress; /*0x5C */ - U32 - Reserved5; /*0x6C */ - U32 - Reserved6; /*0x70 */ - U32 - Reserved7; /*0x74 */ - U32 - Reserved8; /*0x78 */ - U8 - HostName[MPI2_ETHERNET_HOST_NAME_LENGTH];/*0x7C */ -} MPI2_CONFIG_PAGE_ETHERNET_1, - *PTR_MPI2_CONFIG_PAGE_ETHERNET_1, - Mpi2EthernetPage1_t, *pMpi2EthernetPage1_t; - -#define MPI2_ETHERNETPAGE1_PAGEVERSION (0x00) - -/*values for Ethernet Page 1 Flags field */ -#define MPI2_ETHPG1_FLAG_SET_DEFAULT_IF (0x00000100) -#define MPI2_ETHPG1_FLAG_ENABLE_FW_DOWNLOAD (0x00000080) -#define MPI2_ETHPG1_FLAG_ENABLE_TELNET (0x00000040) -#define MPI2_ETHPG1_FLAG_ENABLE_SSH2 (0x00000020) -#define MPI2_ETHPG1_FLAG_ENABLE_DHCP_CLIENT (0x00000010) -#define MPI2_ETHPG1_FLAG_ENABLE_IPV6 (0x00000008) -#define MPI2_ETHPG1_FLAG_ENABLE_IPV4 (0x00000004) -#define MPI2_ETHPG1_FLAG_USE_IPV6_ADDRESSES (0x00000002) -#define MPI2_ETHPG1_FLAG_ENABLE_ETH_IF (0x00000001) - -/*values for Ethernet Page 1 MediaState field */ -#define MPI2_ETHPG1_MS_DUPLEX_MASK (0x80) -#define MPI2_ETHPG1_MS_HALF_DUPLEX (0x00) -#define MPI2_ETHPG1_MS_FULL_DUPLEX (0x80) - -#define MPI2_ETHPG1_MS_DATA_RATE_MASK (0x07) -#define MPI2_ETHPG1_MS_DATA_RATE_AUTO (0x00) -#define MPI2_ETHPG1_MS_DATA_RATE_10MBIT (0x01) -#define MPI2_ETHPG1_MS_DATA_RATE_100MBIT (0x02) -#define MPI2_ETHPG1_MS_DATA_RATE_1GBIT (0x03) - - -/**************************************************************************** -* Extended Manufacturing Config Pages -****************************************************************************/ - -/* - *Generic structure to use for product-specific extended manufacturing pages - *(currently Extended Manufacturing Page 40 through Extended Manufacturing - *Page 60). - */ - -typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - ProductSpecificInfo; /*0x08 */ -} MPI2_CONFIG_PAGE_EXT_MAN_PS, - *PTR_MPI2_CONFIG_PAGE_EXT_MAN_PS, - Mpi2ExtManufacturingPagePS_t, - *pMpi2ExtManufacturingPagePS_t; - -/*PageVersion should be provided by product-specific code */ - -#endif diff --git a/addons/mpt3sas/src/3.10.108/mpi/mpi2_init.h b/addons/mpt3sas/src/3.10.108/mpi/mpi2_init.h deleted file mode 100644 index a079e524..00000000 --- a/addons/mpt3sas/src/3.10.108/mpi/mpi2_init.h +++ /dev/null @@ -1,560 +0,0 @@ -/* - * Copyright (c) 2000-2012 LSI Corporation. - * - * - * Name: mpi2_init.h - * Title: MPI SCSI initiator mode messages and structures - * Creation Date: June 23, 2006 - * - * mpi2_init.h Version: 02.00.14 - * - * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 - * prefix are for use only on MPI v2.5 products, and must not be used - * with MPI v2.0 products. Unless otherwise noted, names beginning with - * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 10-31-07 02.00.01 Fixed name for pMpi2SCSITaskManagementRequest_t. - * 12-18-07 02.00.02 Modified Task Management Target Reset Method defines. - * 02-29-08 02.00.03 Added Query Task Set and Query Unit Attention. - * 03-03-08 02.00.04 Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY. - * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t. - * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO - * Control field Task Attribute flags. - * Moved LUN field defines to mpi2.h becasue they are - * common to many structures. - * 05-06-09 02.00.07 Changed task management type of Query Unit Attention to - * Query Asynchronous Event. - * Defined two new bits in the SlotStatus field of the SCSI - * Enclosure Processor Request and Reply. - * 10-28-09 02.00.08 Added defines for decoding the ResponseInfo bytes for - * both SCSI IO Error Reply and SCSI Task Management Reply. - * Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY. - * Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define. - * 02-10-10 02.00.09 Removed unused structure that had "#if 0" around it. - * 05-12-10 02.00.10 Added optional vendor-unique region to SCSI IO Request. - * 11-10-10 02.00.11 Added MPI2_SCSIIO_NUM_SGLOFFSETS define. - * 11-18-11 02.00.12 Incorporating additions for MPI v2.5. - * 02-06-12 02.00.13 Added alternate defines for Task Priority / Command - * Priority to match SAM-4. - * Added EEDPErrorOffset to MPI2_SCSI_IO_REPLY. - * 07-10-12 02.00.14 Added MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_INIT_H -#define MPI2_INIT_H - -/***************************************************************************** -* -* SCSI Initiator Messages -* -*****************************************************************************/ - -/**************************************************************************** -* SCSI IO messages and associated structures -****************************************************************************/ - -typedef struct _MPI2_SCSI_IO_CDB_EEDP32 { - U8 CDB[20]; /*0x00 */ - U32 PrimaryReferenceTag; /*0x14 */ - U16 PrimaryApplicationTag; /*0x18 */ - U16 PrimaryApplicationTagMask; /*0x1A */ - U32 TransferLength; /*0x1C */ -} MPI2_SCSI_IO_CDB_EEDP32, *PTR_MPI2_SCSI_IO_CDB_EEDP32, - Mpi2ScsiIoCdbEedp32_t, *pMpi2ScsiIoCdbEedp32_t; - -/*MPI v2.0 CDB field */ -typedef union _MPI2_SCSI_IO_CDB_UNION { - U8 CDB32[32]; - MPI2_SCSI_IO_CDB_EEDP32 EEDP32; - MPI2_SGE_SIMPLE_UNION SGE; -} MPI2_SCSI_IO_CDB_UNION, *PTR_MPI2_SCSI_IO_CDB_UNION, - Mpi2ScsiIoCdb_t, *pMpi2ScsiIoCdb_t; - -/*MPI v2.0 SCSI IO Request Message */ -typedef struct _MPI2_SCSI_IO_REQUEST { - U16 DevHandle; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved1; /*0x04 */ - U8 Reserved2; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U32 SenseBufferLowAddress; /*0x0C */ - U16 SGLFlags; /*0x10 */ - U8 SenseBufferLength; /*0x12 */ - U8 Reserved4; /*0x13 */ - U8 SGLOffset0; /*0x14 */ - U8 SGLOffset1; /*0x15 */ - U8 SGLOffset2; /*0x16 */ - U8 SGLOffset3; /*0x17 */ - U32 SkipCount; /*0x18 */ - U32 DataLength; /*0x1C */ - U32 BidirectionalDataLength; /*0x20 */ - U16 IoFlags; /*0x24 */ - U16 EEDPFlags; /*0x26 */ - U32 EEDPBlockSize; /*0x28 */ - U32 SecondaryReferenceTag; /*0x2C */ - U16 SecondaryApplicationTag; /*0x30 */ - U16 ApplicationTagTranslationMask; /*0x32 */ - U8 LUN[8]; /*0x34 */ - U32 Control; /*0x3C */ - MPI2_SCSI_IO_CDB_UNION CDB; /*0x40 */ - -#ifdef MPI2_SCSI_IO_VENDOR_UNIQUE_REGION /*typically this is left undefined */ - MPI2_SCSI_IO_VENDOR_UNIQUE VendorRegion; -#endif - - MPI2_SGE_IO_UNION SGL; /*0x60 */ - -} MPI2_SCSI_IO_REQUEST, *PTR_MPI2_SCSI_IO_REQUEST, - Mpi2SCSIIORequest_t, *pMpi2SCSIIORequest_t; - -/*SCSI IO MsgFlags bits */ - -/*MsgFlags for SenseBufferAddressSpace */ -#define MPI2_SCSIIO_MSGFLAGS_MASK_SENSE_ADDR (0x0C) -#define MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR (0x00) -#define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR (0x04) -#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR (0x08) -#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR (0x0C) - -/*SCSI IO SGLFlags bits */ - -/*base values for Data Location Address Space */ -#define MPI2_SCSIIO_SGLFLAGS_ADDR_MASK (0x0C) -#define MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR (0x00) -#define MPI2_SCSIIO_SGLFLAGS_IOCDDR_ADDR (0x04) -#define MPI2_SCSIIO_SGLFLAGS_IOCPLB_ADDR (0x08) -#define MPI2_SCSIIO_SGLFLAGS_IOCPLBNTA_ADDR (0x0C) - -/*base values for Type */ -#define MPI2_SCSIIO_SGLFLAGS_TYPE_MASK (0x03) -#define MPI2_SCSIIO_SGLFLAGS_TYPE_MPI (0x00) -#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE32 (0x01) -#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE64 (0x02) - -/*shift values for each sub-field */ -#define MPI2_SCSIIO_SGLFLAGS_SGL3_SHIFT (12) -#define MPI2_SCSIIO_SGLFLAGS_SGL2_SHIFT (8) -#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT (4) -#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT (0) - -/*number of SGLOffset fields */ -#define MPI2_SCSIIO_NUM_SGLOFFSETS (4) - -/*SCSI IO IoFlags bits */ - -/*Large CDB Address Space */ -#define MPI2_SCSIIO_CDB_ADDR_MASK (0x6000) -#define MPI2_SCSIIO_CDB_ADDR_SYSTEM (0x0000) -#define MPI2_SCSIIO_CDB_ADDR_IOCDDR (0x2000) -#define MPI2_SCSIIO_CDB_ADDR_IOCPLB (0x4000) -#define MPI2_SCSIIO_CDB_ADDR_IOCPLBNTA (0x6000) - -#define MPI2_SCSIIO_IOFLAGS_LARGE_CDB (0x1000) -#define MPI2_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800) -#define MPI2_SCSIIO_IOFLAGS_MULTICAST (0x0400) -#define MPI2_SCSIIO_IOFLAGS_CMD_DETERMINES_DATA_DIR (0x0200) -#define MPI2_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF) - -/*SCSI IO EEDPFlags bits */ - -#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000) -#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_REFTAG (0x4000) -#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG (0x2000) -#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_APPTAG (0x1000) - -#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400) -#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200) -#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100) - -#define MPI2_SCSIIO_EEDPFLAGS_PASSTHRU_REFTAG (0x0008) - -#define MPI2_SCSIIO_EEDPFLAGS_MASK_OP (0x0007) -#define MPI2_SCSIIO_EEDPFLAGS_NOOP_OP (0x0000) -#define MPI2_SCSIIO_EEDPFLAGS_CHECK_OP (0x0001) -#define MPI2_SCSIIO_EEDPFLAGS_STRIP_OP (0x0002) -#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003) -#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004) -#define MPI2_SCSIIO_EEDPFLAGS_REPLACE_OP (0x0006) -#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REGEN_OP (0x0007) - -/*SCSI IO LUN fields: use MPI2_LUN_ from mpi2.h */ - -/*SCSI IO Control bits */ -#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK (0xFC000000) -#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT (26) - -#define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK (0x03000000) -#define MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION (24) -#define MPI2_SCSIIO_CONTROL_NODATATRANSFER (0x00000000) -#define MPI2_SCSIIO_CONTROL_WRITE (0x01000000) -#define MPI2_SCSIIO_CONTROL_READ (0x02000000) -#define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL (0x03000000) - -#define MPI2_SCSIIO_CONTROL_TASKPRI_MASK (0x00007800) -#define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT (11) -/*alternate name for the previous field; called Command Priority in SAM-4 */ -#define MPI2_SCSIIO_CONTROL_CMDPRI_MASK (0x00007800) -#define MPI2_SCSIIO_CONTROL_CMDPRI_SHIFT (11) - -#define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK (0x00000700) -#define MPI2_SCSIIO_CONTROL_SIMPLEQ (0x00000000) -#define MPI2_SCSIIO_CONTROL_HEADOFQ (0x00000100) -#define MPI2_SCSIIO_CONTROL_ORDEREDQ (0x00000200) -#define MPI2_SCSIIO_CONTROL_ACAQ (0x00000400) - -#define MPI2_SCSIIO_CONTROL_TLR_MASK (0x000000C0) -#define MPI2_SCSIIO_CONTROL_NO_TLR (0x00000000) -#define MPI2_SCSIIO_CONTROL_TLR_ON (0x00000040) -#define MPI2_SCSIIO_CONTROL_TLR_OFF (0x00000080) - -/*MPI v2.5 CDB field */ -typedef union _MPI25_SCSI_IO_CDB_UNION { - U8 CDB32[32]; - MPI2_SCSI_IO_CDB_EEDP32 EEDP32; - MPI2_IEEE_SGE_SIMPLE64 SGE; -} MPI25_SCSI_IO_CDB_UNION, *PTR_MPI25_SCSI_IO_CDB_UNION, - Mpi25ScsiIoCdb_t, *pMpi25ScsiIoCdb_t; - -/*MPI v2.5 SCSI IO Request Message */ -typedef struct _MPI25_SCSI_IO_REQUEST { - U16 DevHandle; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved1; /*0x04 */ - U8 Reserved2; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U32 SenseBufferLowAddress; /*0x0C */ - U8 DMAFlags; /*0x10 */ - U8 Reserved5; /*0x11 */ - U8 SenseBufferLength; /*0x12 */ - U8 Reserved4; /*0x13 */ - U8 SGLOffset0; /*0x14 */ - U8 SGLOffset1; /*0x15 */ - U8 SGLOffset2; /*0x16 */ - U8 SGLOffset3; /*0x17 */ - U32 SkipCount; /*0x18 */ - U32 DataLength; /*0x1C */ - U32 BidirectionalDataLength; /*0x20 */ - U16 IoFlags; /*0x24 */ - U16 EEDPFlags; /*0x26 */ - U16 EEDPBlockSize; /*0x28 */ - U16 Reserved6; /*0x2A */ - U32 SecondaryReferenceTag; /*0x2C */ - U16 SecondaryApplicationTag; /*0x30 */ - U16 ApplicationTagTranslationMask; /*0x32 */ - U8 LUN[8]; /*0x34 */ - U32 Control; /*0x3C */ - MPI25_SCSI_IO_CDB_UNION CDB; /*0x40 */ - -#ifdef MPI25_SCSI_IO_VENDOR_UNIQUE_REGION /*typically this is left undefined */ - MPI25_SCSI_IO_VENDOR_UNIQUE VendorRegion; -#endif - - MPI25_SGE_IO_UNION SGL; /*0x60 */ - -} MPI25_SCSI_IO_REQUEST, *PTR_MPI25_SCSI_IO_REQUEST, - Mpi25SCSIIORequest_t, *pMpi25SCSIIORequest_t; - -/*use MPI2_SCSIIO_MSGFLAGS_ defines for the MsgFlags field */ - -/*Defines for the DMAFlags field - * Each setting affects 4 SGLS, from SGL0 to SGL3. - * D = Data - * C = Cache DIF - * I = Interleaved - * H = Host DIF - */ -#define MPI25_SCSIIO_DMAFLAGS_OP_MASK (0x0F) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_D (0x00) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_C (0x01) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_I (0x02) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_C_C (0x03) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_C_I (0x04) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_I_I (0x05) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_C_C (0x06) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_C_I (0x07) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_I_I (0x08) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_I_I_I (0x09) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_D (0x0A) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_C (0x0B) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_I (0x0C) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_C_C (0x0D) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_C_I (0x0E) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_I_I (0x0F) - -/*number of SGLOffset fields */ -#define MPI25_SCSIIO_NUM_SGLOFFSETS (4) - -/*defines for the IoFlags field */ -#define MPI25_SCSIIO_IOFLAGS_IO_PATH_MASK (0xC000) -#define MPI25_SCSIIO_IOFLAGS_NORMAL_PATH (0x0000) -#define MPI25_SCSIIO_IOFLAGS_FAST_PATH (0x4000) - -#define MPI25_SCSIIO_IOFLAGS_LARGE_CDB (0x1000) -#define MPI25_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800) -#define MPI25_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF) - -/*MPI v2.5 defines for the EEDPFlags bits */ -/*use MPI2_SCSIIO_EEDPFLAGS_ defines for the other EEDPFlags bits */ -#define MPI25_SCSIIO_EEDPFLAGS_ESCAPE_MODE_MASK (0x00C0) -#define MPI25_SCSIIO_EEDPFLAGS_COMPATIBLE_MODE (0x0000) -#define MPI25_SCSIIO_EEDPFLAGS_DO_NOT_DISABLE_MODE (0x0040) -#define MPI25_SCSIIO_EEDPFLAGS_APPTAG_DISABLE_MODE (0x0080) -#define MPI25_SCSIIO_EEDPFLAGS_APPTAG_REFTAG_DISABLE_MODE (0x00C0) - -#define MPI25_SCSIIO_EEDPFLAGS_HOST_GUARD_METHOD_MASK (0x0030) -#define MPI25_SCSIIO_EEDPFLAGS_T10_CRC_HOST_GUARD (0x0000) -#define MPI25_SCSIIO_EEDPFLAGS_IP_CHKSUM_HOST_GUARD (0x0010) - -/*use MPI2_LUN_ defines from mpi2.h for the LUN field */ - -/*use MPI2_SCSIIO_CONTROL_ defines for the Control field */ - -/*NOTE: The SCSI IO Reply is nearly the same for MPI 2.0 and MPI 2.5, so - * MPI2_SCSI_IO_REPLY is used for both. - */ - -/*SCSI IO Error Reply Message */ -typedef struct _MPI2_SCSI_IO_REPLY { - U16 DevHandle; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved1; /*0x04 */ - U8 Reserved2; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U8 SCSIStatus; /*0x0C */ - U8 SCSIState; /*0x0D */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 TransferCount; /*0x14 */ - U32 SenseCount; /*0x18 */ - U32 ResponseInfo; /*0x1C */ - U16 TaskTag; /*0x20 */ - U16 Reserved4; /*0x22 */ - U32 BidirectionalTransferCount; /*0x24 */ - U32 EEDPErrorOffset; /*0x28 *//*MPI 2.5 only; Reserved in MPI 2.0*/ - U32 Reserved6; /*0x2C */ -} MPI2_SCSI_IO_REPLY, *PTR_MPI2_SCSI_IO_REPLY, - Mpi2SCSIIOReply_t, *pMpi2SCSIIOReply_t; - -/*SCSI IO Reply SCSIStatus values (SAM-4 status codes) */ - -#define MPI2_SCSI_STATUS_GOOD (0x00) -#define MPI2_SCSI_STATUS_CHECK_CONDITION (0x02) -#define MPI2_SCSI_STATUS_CONDITION_MET (0x04) -#define MPI2_SCSI_STATUS_BUSY (0x08) -#define MPI2_SCSI_STATUS_INTERMEDIATE (0x10) -#define MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET (0x14) -#define MPI2_SCSI_STATUS_RESERVATION_CONFLICT (0x18) -#define MPI2_SCSI_STATUS_COMMAND_TERMINATED (0x22) /*obsolete */ -#define MPI2_SCSI_STATUS_TASK_SET_FULL (0x28) -#define MPI2_SCSI_STATUS_ACA_ACTIVE (0x30) -#define MPI2_SCSI_STATUS_TASK_ABORTED (0x40) - -/*SCSI IO Reply SCSIState flags */ - -#define MPI2_SCSI_STATE_RESPONSE_INFO_VALID (0x10) -#define MPI2_SCSI_STATE_TERMINATED (0x08) -#define MPI2_SCSI_STATE_NO_SCSI_STATUS (0x04) -#define MPI2_SCSI_STATE_AUTOSENSE_FAILED (0x02) -#define MPI2_SCSI_STATE_AUTOSENSE_VALID (0x01) - -/*masks and shifts for the ResponseInfo field */ - -#define MPI2_SCSI_RI_MASK_REASONCODE (0x000000FF) -#define MPI2_SCSI_RI_SHIFT_REASONCODE (0) - -#define MPI2_SCSI_TASKTAG_UNKNOWN (0xFFFF) - -/**************************************************************************** -* SCSI Task Management messages -****************************************************************************/ - -/*SCSI Task Management Request Message */ -typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST { - U16 DevHandle; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U8 Reserved1; /*0x04 */ - U8 TaskType; /*0x05 */ - U8 Reserved2; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U8 LUN[8]; /*0x0C */ - U32 Reserved4[7]; /*0x14 */ - U16 TaskMID; /*0x30 */ - U16 Reserved5; /*0x32 */ -} MPI2_SCSI_TASK_MANAGE_REQUEST, - *PTR_MPI2_SCSI_TASK_MANAGE_REQUEST, - Mpi2SCSITaskManagementRequest_t, - *pMpi2SCSITaskManagementRequest_t; - -/*TaskType values */ - -#define MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01) -#define MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x02) -#define MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03) -#define MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) -#define MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06) -#define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) -#define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08) -#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET (0x09) -#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT (0x0A) - -/*obsolete TaskType name */ -#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION \ - (MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT) - -/*MsgFlags bits */ - -#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET (0x18) -#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET (0x00) -#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST (0x08) -#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET (0x10) - -#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01) - -/*SCSI Task Management Reply Message */ -typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY { - U16 DevHandle; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U8 ResponseCode; /*0x04 */ - U8 TaskType; /*0x05 */ - U8 Reserved1; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved2; /*0x0A */ - U16 Reserved3; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 TerminationCount; /*0x14 */ - U32 ResponseInfo; /*0x18 */ -} MPI2_SCSI_TASK_MANAGE_REPLY, - *PTR_MPI2_SCSI_TASK_MANAGE_REPLY, - Mpi2SCSITaskManagementReply_t, *pMpi2SCSIManagementReply_t; - -/*ResponseCode values */ - -#define MPI2_SCSITASKMGMT_RSP_TM_COMPLETE (0x00) -#define MPI2_SCSITASKMGMT_RSP_INVALID_FRAME (0x02) -#define MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04) -#define MPI2_SCSITASKMGMT_RSP_TM_FAILED (0x05) -#define MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08) -#define MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09) -#define MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG (0x0A) -#define MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80) - -/*masks and shifts for the ResponseInfo field */ - -#define MPI2_SCSITASKMGMT_RI_MASK_REASONCODE (0x000000FF) -#define MPI2_SCSITASKMGMT_RI_SHIFT_REASONCODE (0) -#define MPI2_SCSITASKMGMT_RI_MASK_ARI2 (0x0000FF00) -#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI2 (8) -#define MPI2_SCSITASKMGMT_RI_MASK_ARI1 (0x00FF0000) -#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI1 (16) -#define MPI2_SCSITASKMGMT_RI_MASK_ARI0 (0xFF000000) -#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI0 (24) - -/**************************************************************************** -* SCSI Enclosure Processor messages -****************************************************************************/ - -/*SCSI Enclosure Processor Request Message */ -typedef struct _MPI2_SEP_REQUEST { - U16 DevHandle; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U8 Action; /*0x04 */ - U8 Flags; /*0x05 */ - U8 Reserved1; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved2; /*0x0A */ - U32 SlotStatus; /*0x0C */ - U32 Reserved3; /*0x10 */ - U32 Reserved4; /*0x14 */ - U32 Reserved5; /*0x18 */ - U16 Slot; /*0x1C */ - U16 EnclosureHandle; /*0x1E */ -} MPI2_SEP_REQUEST, *PTR_MPI2_SEP_REQUEST, - Mpi2SepRequest_t, *pMpi2SepRequest_t; - -/*Action defines */ -#define MPI2_SEP_REQ_ACTION_WRITE_STATUS (0x00) -#define MPI2_SEP_REQ_ACTION_READ_STATUS (0x01) - -/*Flags defines */ -#define MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS (0x00) -#define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01) - -/*SlotStatus defines */ -#define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000) -#define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) -#define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200) -#define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100) -#define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080) -#define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040) -#define MPI2_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) -#define MPI2_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) -#define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004) -#define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002) -#define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001) - -/*SCSI Enclosure Processor Reply Message */ -typedef struct _MPI2_SEP_REPLY { - U16 DevHandle; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U8 Action; /*0x04 */ - U8 Flags; /*0x05 */ - U8 Reserved1; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved2; /*0x0A */ - U16 Reserved3; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 SlotStatus; /*0x14 */ - U32 Reserved4; /*0x18 */ - U16 Slot; /*0x1C */ - U16 EnclosureHandle; /*0x1E */ -} MPI2_SEP_REPLY, *PTR_MPI2_SEP_REPLY, - Mpi2SepReply_t, *pMpi2SepReply_t; - -/*SlotStatus defines */ -#define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000) -#define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) -#define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200) -#define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100) -#define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080) -#define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT (0x00000040) -#define MPI2_SEP_REPLY_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) -#define MPI2_SEP_REPLY_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) -#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING (0x00000004) -#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY (0x00000002) -#define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR (0x00000001) - -#endif diff --git a/addons/mpt3sas/src/3.10.108/mpi/mpi2_ioc.h b/addons/mpt3sas/src/3.10.108/mpi/mpi2_ioc.h deleted file mode 100644 index 0de425d8..00000000 --- a/addons/mpt3sas/src/3.10.108/mpi/mpi2_ioc.h +++ /dev/null @@ -1,1665 +0,0 @@ -/* - * Copyright (c) 2000-2012 LSI Corporation. - * - * - * Name: mpi2_ioc.h - * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages - * Creation Date: October 11, 2006 - * - * mpi2_ioc.h Version: 02.00.21 - * - * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 - * prefix are for use only on MPI v2.5 products, and must not be used - * with MPI v2.0 products. Unless otherwise noted, names beginning with - * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 06-04-07 02.00.01 In IOCFacts Reply structure, renamed MaxDevices to - * MaxTargets. - * Added TotalImageSize field to FWDownload Request. - * Added reserved words to FWUpload Request. - * 06-26-07 02.00.02 Added IR Configuration Change List Event. - * 08-31-07 02.00.03 Removed SystemReplyQueueDepth field from the IOCInit - * request and replaced it with - * ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth. - * Replaced the MinReplyQueueDepth field of the IOCFacts - * reply with MaxReplyDescriptorPostQueueDepth. - * Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum - * depth for the Reply Descriptor Post Queue. - * Added SASAddress field to Initiator Device Table - * Overflow Event data. - * 10-31-07 02.00.04 Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING - * for SAS Initiator Device Status Change Event data. - * Modified Reason Code defines for SAS Topology Change - * List Event data, including adding a bit for PHY Vacant - * status, and adding a mask for the Reason Code. - * Added define for - * MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING. - * Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID. - * 12-18-07 02.00.05 Added Boot Status defines for the IOCExceptions field of - * the IOCFacts Reply. - * Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. - * Moved MPI2_VERSION_UNION to mpi2.h. - * Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks - * instead of enables, and added SASBroadcastPrimitiveMasks - * field. - * Added Log Entry Added Event and related structure. - * 02-29-08 02.00.06 Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID. - * Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET. - * Added MaxVolumes and MaxPersistentEntries fields to - * IOCFacts reply. - * Added ProtocalFlags and IOCCapabilities fields to - * MPI2_FW_IMAGE_HEADER. - * Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT. - * 03-03-08 02.00.07 Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to - * a U16 (from a U32). - * Removed extra 's' from EventMasks name. - * 06-27-08 02.00.08 Fixed an offset in a comment. - * 10-02-08 02.00.09 Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST. - * Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and - * renamed MinReplyFrameSize to ReplyFrameSize. - * Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX. - * Added two new RAIDOperation values for Integrated RAID - * Operations Status Event data. - * Added four new IR Configuration Change List Event data - * ReasonCode values. - * Added two new ReasonCode defines for SAS Device Status - * Change Event data. - * Added three new DiscoveryStatus bits for the SAS - * Discovery event data. - * Added Multiplexing Status Change bit to the PhyStatus - * field of the SAS Topology Change List event data. - * Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY. - * BootFlags are now product-specific. - * Added defines for the indivdual signature bytes - * for MPI2_INIT_IMAGE_FOOTER. - * 01-19-09 02.00.10 Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define. - * Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR - * define. - * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE - * define. - * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define. - * 05-06-09 02.00.11 Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define. - * Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define. - * Added two new reason codes for SAS Device Status Change - * Event. - * Added new event: SAS PHY Counter. - * 07-30-09 02.00.12 Added GPIO Interrupt event define and structure. - * Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. - * Added new product id family for 2208. - * 10-28-09 02.00.13 Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST. - * Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY. - * Added MinDevHandle field to MPI2_IOC_FACTS_REPLY. - * Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY. - * Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define. - * Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define. - * Added Host Based Discovery Phy Event data. - * Added defines for ProductID Product field - * (MPI2_FW_HEADER_PID_). - * Modified values for SAS ProductID Family - * (MPI2_FW_HEADER_PID_FAMILY_). - * 02-10-10 02.00.14 Added SAS Quiesce Event structure and defines. - * Added PowerManagementControl Request structures and - * defines. - * 05-12-10 02.00.15 Marked Task Set Full Event as obsolete. - * Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define. - * 11-10-10 02.00.16 Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC. - * 02-23-11 02.00.17 Added SAS NOTIFY Primitive event, and added - * SASNotifyPrimitiveMasks field to - * MPI2_EVENT_NOTIFICATION_REQUEST. - * Added Temperature Threshold Event. - * Added Host Message Event. - * Added Send Host Message request and reply. - * 05-25-11 02.00.18 For Extended Image Header, added - * MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC and - * MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC defines. - * Deprecated MPI2_EXT_IMAGE_TYPE_MAX define. - * 08-24-11 02.00.19 Added PhysicalPort field to - * MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE structure. - * Marked MPI2_PM_CONTROL_FEATURE_PCIE_LINK as obsolete. - * 11-18-11 02.00.20 Incorporating additions for MPI v2.5. - * 03-29-12 02.00.21 Added a product specific range to event values. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_IOC_H -#define MPI2_IOC_H - -/***************************************************************************** -* -* IOC Messages -* -*****************************************************************************/ - -/**************************************************************************** -* IOCInit message -****************************************************************************/ - -/*IOCInit Request message */ -typedef struct _MPI2_IOC_INIT_REQUEST { - U8 WhoInit; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 MsgVersion; /*0x0C */ - U16 HeaderVersion; /*0x0E */ - U32 Reserved5; /*0x10 */ - U16 Reserved6; /*0x14 */ - U8 Reserved7; /*0x16 */ - U8 HostMSIxVectors; /*0x17 */ - U16 Reserved8; /*0x18 */ - U16 SystemRequestFrameSize; /*0x1A */ - U16 ReplyDescriptorPostQueueDepth; /*0x1C */ - U16 ReplyFreeQueueDepth; /*0x1E */ - U32 SenseBufferAddressHigh; /*0x20 */ - U32 SystemReplyAddressHigh; /*0x24 */ - U64 SystemRequestFrameBaseAddress; /*0x28 */ - U64 ReplyDescriptorPostQueueAddress; /*0x30 */ - U64 ReplyFreeQueueAddress; /*0x38 */ - U64 TimeStamp; /*0x40 */ -} MPI2_IOC_INIT_REQUEST, *PTR_MPI2_IOC_INIT_REQUEST, - Mpi2IOCInitRequest_t, *pMpi2IOCInitRequest_t; - -/*WhoInit values */ -#define MPI2_WHOINIT_NOT_INITIALIZED (0x00) -#define MPI2_WHOINIT_SYSTEM_BIOS (0x01) -#define MPI2_WHOINIT_ROM_BIOS (0x02) -#define MPI2_WHOINIT_PCI_PEER (0x03) -#define MPI2_WHOINIT_HOST_DRIVER (0x04) -#define MPI2_WHOINIT_MANUFACTURER (0x05) - -/*MsgVersion */ -#define MPI2_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00) -#define MPI2_IOCINIT_MSGVERSION_MAJOR_SHIFT (8) -#define MPI2_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF) -#define MPI2_IOCINIT_MSGVERSION_MINOR_SHIFT (0) - -/*HeaderVersion */ -#define MPI2_IOCINIT_HDRVERSION_UNIT_MASK (0xFF00) -#define MPI2_IOCINIT_HDRVERSION_UNIT_SHIFT (8) -#define MPI2_IOCINIT_HDRVERSION_DEV_MASK (0x00FF) -#define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT (0) - -/*minimum depth for the Reply Descriptor Post Queue */ -#define MPI2_RDPQ_DEPTH_MIN (16) - -/*IOCInit Reply message */ -typedef struct _MPI2_IOC_INIT_REPLY { - U8 WhoInit; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_IOC_INIT_REPLY, *PTR_MPI2_IOC_INIT_REPLY, - Mpi2IOCInitReply_t, *pMpi2IOCInitReply_t; - -/**************************************************************************** -* IOCFacts message -****************************************************************************/ - -/*IOCFacts Request message */ -typedef struct _MPI2_IOC_FACTS_REQUEST { - U16 Reserved1; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ -} MPI2_IOC_FACTS_REQUEST, *PTR_MPI2_IOC_FACTS_REQUEST, - Mpi2IOCFactsRequest_t, *pMpi2IOCFactsRequest_t; - -/*IOCFacts Reply message */ -typedef struct _MPI2_IOC_FACTS_REPLY { - U16 MsgVersion; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 HeaderVersion; /*0x04 */ - U8 IOCNumber; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U16 IOCExceptions; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U8 MaxChainDepth; /*0x14 */ - U8 WhoInit; /*0x15 */ - U8 NumberOfPorts; /*0x16 */ - U8 MaxMSIxVectors; /*0x17 */ - U16 RequestCredit; /*0x18 */ - U16 ProductID; /*0x1A */ - U32 IOCCapabilities; /*0x1C */ - MPI2_VERSION_UNION FWVersion; /*0x20 */ - U16 IOCRequestFrameSize; /*0x24 */ - U16 IOCMaxChainSegmentSize; /*0x26 */ - U16 MaxInitiators; /*0x28 */ - U16 MaxTargets; /*0x2A */ - U16 MaxSasExpanders; /*0x2C */ - U16 MaxEnclosures; /*0x2E */ - U16 ProtocolFlags; /*0x30 */ - U16 HighPriorityCredit; /*0x32 */ - U16 MaxReplyDescriptorPostQueueDepth; /*0x34 */ - U8 ReplyFrameSize; /*0x36 */ - U8 MaxVolumes; /*0x37 */ - U16 MaxDevHandle; /*0x38 */ - U16 MaxPersistentEntries; /*0x3A */ - U16 MinDevHandle; /*0x3C */ - U16 Reserved4; /*0x3E */ -} MPI2_IOC_FACTS_REPLY, *PTR_MPI2_IOC_FACTS_REPLY, - Mpi2IOCFactsReply_t, *pMpi2IOCFactsReply_t; - -/*MsgVersion */ -#define MPI2_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00) -#define MPI2_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8) -#define MPI2_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF) -#define MPI2_IOCFACTS_MSGVERSION_MINOR_SHIFT (0) - -/*HeaderVersion */ -#define MPI2_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00) -#define MPI2_IOCFACTS_HDRVERSION_UNIT_SHIFT (8) -#define MPI2_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF) -#define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT (0) - -/*IOCExceptions */ -#define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX (0x0100) - -#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x00E0) -#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_GOOD (0x0000) -#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_BACKUP (0x0020) -#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_RESTORED (0x0040) -#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_CORRUPT_BACKUP (0x0060) - -#define MPI2_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010) -#define MPI2_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0008) -#define MPI2_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004) -#define MPI2_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002) -#define MPI2_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001) - -/*defines for WhoInit field are after the IOCInit Request */ - -/*ProductID field uses MPI2_FW_HEADER_PID_ */ - -/*IOCCapabilities */ -#define MPI25_IOCFACTS_CAPABILITY_FAST_PATH_CAPABLE (0x00020000) -#define MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY (0x00010000) -#define MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX (0x00008000) -#define MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR (0x00004000) -#define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY (0x00002000) -#define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID (0x00001000) -#define MPI2_IOCFACTS_CAPABILITY_TLR (0x00000800) -#define MPI2_IOCFACTS_CAPABILITY_MULTICAST (0x00000100) -#define MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET (0x00000080) -#define MPI2_IOCFACTS_CAPABILITY_EEDP (0x00000040) -#define MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020) -#define MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010) -#define MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008) -#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004) - -/*ProtocolFlags */ -#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001) -#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002) - -/**************************************************************************** -* PortFacts message -****************************************************************************/ - -/*PortFacts Request message */ -typedef struct _MPI2_PORT_FACTS_REQUEST { - U16 Reserved1; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 PortNumber; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ -} MPI2_PORT_FACTS_REQUEST, *PTR_MPI2_PORT_FACTS_REQUEST, - Mpi2PortFactsRequest_t, *pMpi2PortFactsRequest_t; - -/*PortFacts Reply message */ -typedef struct _MPI2_PORT_FACTS_REPLY { - U16 Reserved1; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 PortNumber; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U16 Reserved4; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U8 Reserved5; /*0x14 */ - U8 PortType; /*0x15 */ - U16 Reserved6; /*0x16 */ - U16 MaxPostedCmdBuffers; /*0x18 */ - U16 Reserved7; /*0x1A */ -} MPI2_PORT_FACTS_REPLY, *PTR_MPI2_PORT_FACTS_REPLY, - Mpi2PortFactsReply_t, *pMpi2PortFactsReply_t; - -/*PortType values */ -#define MPI2_PORTFACTS_PORTTYPE_INACTIVE (0x00) -#define MPI2_PORTFACTS_PORTTYPE_FC (0x10) -#define MPI2_PORTFACTS_PORTTYPE_ISCSI (0x20) -#define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL (0x30) -#define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL (0x31) - -/**************************************************************************** -* PortEnable message -****************************************************************************/ - -/*PortEnable Request message */ -typedef struct _MPI2_PORT_ENABLE_REQUEST { - U16 Reserved1; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U8 Reserved2; /*0x04 */ - U8 PortFlags; /*0x05 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ -} MPI2_PORT_ENABLE_REQUEST, *PTR_MPI2_PORT_ENABLE_REQUEST, - Mpi2PortEnableRequest_t, *pMpi2PortEnableRequest_t; - -/*PortEnable Reply message */ -typedef struct _MPI2_PORT_ENABLE_REPLY { - U16 Reserved1; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U8 Reserved2; /*0x04 */ - U8 PortFlags; /*0x05 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_PORT_ENABLE_REPLY, *PTR_MPI2_PORT_ENABLE_REPLY, - Mpi2PortEnableReply_t, *pMpi2PortEnableReply_t; - -/**************************************************************************** -* EventNotification message -****************************************************************************/ - -/*EventNotification Request message */ -#define MPI2_EVENT_NOTIFY_EVENTMASK_WORDS (4) - -typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST { - U16 Reserved1; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 Reserved5; /*0x0C */ - U32 Reserved6; /*0x10 */ - U32 EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; /*0x14 */ - U16 SASBroadcastPrimitiveMasks; /*0x24 */ - U16 SASNotifyPrimitiveMasks; /*0x26 */ - U32 Reserved8; /*0x28 */ -} MPI2_EVENT_NOTIFICATION_REQUEST, - *PTR_MPI2_EVENT_NOTIFICATION_REQUEST, - Mpi2EventNotificationRequest_t, - *pMpi2EventNotificationRequest_t; - -/*EventNotification Reply message */ -typedef struct _MPI2_EVENT_NOTIFICATION_REPLY { - U16 EventDataLength; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved1; /*0x04 */ - U8 AckRequired; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved2; /*0x0A */ - U16 Reserved3; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U16 Event; /*0x14 */ - U16 Reserved4; /*0x16 */ - U32 EventContext; /*0x18 */ - U32 EventData[1]; /*0x1C */ -} MPI2_EVENT_NOTIFICATION_REPLY, *PTR_MPI2_EVENT_NOTIFICATION_REPLY, - Mpi2EventNotificationReply_t, - *pMpi2EventNotificationReply_t; - -/*AckRequired */ -#define MPI2_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00) -#define MPI2_EVENT_NOTIFICATION_ACK_REQUIRED (0x01) - -/*Event */ -#define MPI2_EVENT_LOG_DATA (0x0001) -#define MPI2_EVENT_STATE_CHANGE (0x0002) -#define MPI2_EVENT_HARD_RESET_RECEIVED (0x0005) -#define MPI2_EVENT_EVENT_CHANGE (0x000A) -#define MPI2_EVENT_TASK_SET_FULL (0x000E) /*obsolete */ -#define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE (0x000F) -#define MPI2_EVENT_IR_OPERATION_STATUS (0x0014) -#define MPI2_EVENT_SAS_DISCOVERY (0x0016) -#define MPI2_EVENT_SAS_BROADCAST_PRIMITIVE (0x0017) -#define MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x0018) -#define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW (0x0019) -#define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x001C) -#define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE (0x001D) -#define MPI2_EVENT_IR_VOLUME (0x001E) -#define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F) -#define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020) -#define MPI2_EVENT_LOG_ENTRY_ADDED (0x0021) -#define MPI2_EVENT_SAS_PHY_COUNTER (0x0022) -#define MPI2_EVENT_GPIO_INTERRUPT (0x0023) -#define MPI2_EVENT_HOST_BASED_DISCOVERY_PHY (0x0024) -#define MPI2_EVENT_SAS_QUIESCE (0x0025) -#define MPI2_EVENT_SAS_NOTIFY_PRIMITIVE (0x0026) -#define MPI2_EVENT_TEMP_THRESHOLD (0x0027) -#define MPI2_EVENT_HOST_MESSAGE (0x0028) -#define MPI2_EVENT_POWER_PERFORMANCE_CHANGE (0x0029) -#define MPI2_EVENT_MIN_PRODUCT_SPECIFIC (0x006E) -#define MPI2_EVENT_MAX_PRODUCT_SPECIFIC (0x007F) - -/*Log Entry Added Event data */ - -/*the following structure matches MPI2_LOG_0_ENTRY in mpi2_cnfg.h */ -#define MPI2_EVENT_DATA_LOG_DATA_LENGTH (0x1C) - -typedef struct _MPI2_EVENT_DATA_LOG_ENTRY_ADDED { - U64 TimeStamp; /*0x00 */ - U32 Reserved1; /*0x08 */ - U16 LogSequence; /*0x0C */ - U16 LogEntryQualifier; /*0x0E */ - U8 VP_ID; /*0x10 */ - U8 VF_ID; /*0x11 */ - U16 Reserved2; /*0x12 */ - U8 LogData[MPI2_EVENT_DATA_LOG_DATA_LENGTH]; /*0x14 */ -} MPI2_EVENT_DATA_LOG_ENTRY_ADDED, - *PTR_MPI2_EVENT_DATA_LOG_ENTRY_ADDED, - Mpi2EventDataLogEntryAdded_t, - *pMpi2EventDataLogEntryAdded_t; - -/*GPIO Interrupt Event data */ - -typedef struct _MPI2_EVENT_DATA_GPIO_INTERRUPT { - U8 GPIONum; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ -} MPI2_EVENT_DATA_GPIO_INTERRUPT, - *PTR_MPI2_EVENT_DATA_GPIO_INTERRUPT, - Mpi2EventDataGpioInterrupt_t, - *pMpi2EventDataGpioInterrupt_t; - -/*Temperature Threshold Event data */ - -typedef struct _MPI2_EVENT_DATA_TEMPERATURE { - U16 Status; /*0x00 */ - U8 SensorNum; /*0x02 */ - U8 Reserved1; /*0x03 */ - U16 CurrentTemperature; /*0x04 */ - U16 Reserved2; /*0x06 */ - U32 Reserved3; /*0x08 */ - U32 Reserved4; /*0x0C */ -} MPI2_EVENT_DATA_TEMPERATURE, - *PTR_MPI2_EVENT_DATA_TEMPERATURE, - Mpi2EventDataTemperature_t, *pMpi2EventDataTemperature_t; - -/*Temperature Threshold Event data Status bits */ -#define MPI2_EVENT_TEMPERATURE3_EXCEEDED (0x0008) -#define MPI2_EVENT_TEMPERATURE2_EXCEEDED (0x0004) -#define MPI2_EVENT_TEMPERATURE1_EXCEEDED (0x0002) -#define MPI2_EVENT_TEMPERATURE0_EXCEEDED (0x0001) - -/*Host Message Event data */ - -typedef struct _MPI2_EVENT_DATA_HOST_MESSAGE { - U8 SourceVF_ID; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 Reserved3; /*0x04 */ - U32 HostData[1]; /*0x08 */ -} MPI2_EVENT_DATA_HOST_MESSAGE, *PTR_MPI2_EVENT_DATA_HOST_MESSAGE, - Mpi2EventDataHostMessage_t, *pMpi2EventDataHostMessage_t; - -/*Power Performance Change Event */ - -typedef struct _MPI2_EVENT_DATA_POWER_PERF_CHANGE { - U8 CurrentPowerMode; /*0x00 */ - U8 PreviousPowerMode; /*0x01 */ - U16 Reserved1; /*0x02 */ -} MPI2_EVENT_DATA_POWER_PERF_CHANGE, - *PTR_MPI2_EVENT_DATA_POWER_PERF_CHANGE, - Mpi2EventDataPowerPerfChange_t, - *pMpi2EventDataPowerPerfChange_t; - -/*defines for CurrentPowerMode and PreviousPowerMode fields */ -#define MPI2_EVENT_PM_INIT_MASK (0xC0) -#define MPI2_EVENT_PM_INIT_UNAVAILABLE (0x00) -#define MPI2_EVENT_PM_INIT_HOST (0x40) -#define MPI2_EVENT_PM_INIT_IO_UNIT (0x80) -#define MPI2_EVENT_PM_INIT_PCIE_DPA (0xC0) - -#define MPI2_EVENT_PM_MODE_MASK (0x07) -#define MPI2_EVENT_PM_MODE_UNAVAILABLE (0x00) -#define MPI2_EVENT_PM_MODE_UNKNOWN (0x01) -#define MPI2_EVENT_PM_MODE_FULL_POWER (0x04) -#define MPI2_EVENT_PM_MODE_REDUCED_POWER (0x05) -#define MPI2_EVENT_PM_MODE_STANDBY (0x06) - -/*Hard Reset Received Event data */ - -typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED { - U8 Reserved1; /*0x00 */ - U8 Port; /*0x01 */ - U16 Reserved2; /*0x02 */ -} MPI2_EVENT_DATA_HARD_RESET_RECEIVED, - *PTR_MPI2_EVENT_DATA_HARD_RESET_RECEIVED, - Mpi2EventDataHardResetReceived_t, - *pMpi2EventDataHardResetReceived_t; - -/*Task Set Full Event data */ -/* this event is obsolete */ - -typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL { - U16 DevHandle; /*0x00 */ - U16 CurrentDepth; /*0x02 */ -} MPI2_EVENT_DATA_TASK_SET_FULL, *PTR_MPI2_EVENT_DATA_TASK_SET_FULL, - Mpi2EventDataTaskSetFull_t, *pMpi2EventDataTaskSetFull_t; - -/*SAS Device Status Change Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE { - U16 TaskTag; /*0x00 */ - U8 ReasonCode; /*0x02 */ - U8 PhysicalPort; /*0x03 */ - U8 ASC; /*0x04 */ - U8 ASCQ; /*0x05 */ - U16 DevHandle; /*0x06 */ - U32 Reserved2; /*0x08 */ - U64 SASAddress; /*0x0C */ - U8 LUN[8]; /*0x14 */ -} MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, - *PTR_MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, - Mpi2EventDataSasDeviceStatusChange_t, - *pMpi2EventDataSasDeviceStatusChange_t; - -/*SAS Device Status Change Event data ReasonCode values */ -#define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) -#define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) -#define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08) -#define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09) -#define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A) -#define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B) -#define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C) -#define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D) -#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E) -#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F) -#define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE (0x10) -#define MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY (0x11) -#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY (0x12) - -/*Integrated RAID Operation Status Event data */ - -typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS { - U16 VolDevHandle; /*0x00 */ - U16 Reserved1; /*0x02 */ - U8 RAIDOperation; /*0x04 */ - U8 PercentComplete; /*0x05 */ - U16 Reserved2; /*0x06 */ - U32 Resereved3; /*0x08 */ -} MPI2_EVENT_DATA_IR_OPERATION_STATUS, - *PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS, - Mpi2EventDataIrOperationStatus_t, - *pMpi2EventDataIrOperationStatus_t; - -/*Integrated RAID Operation Status Event data RAIDOperation values */ -#define MPI2_EVENT_IR_RAIDOP_RESYNC (0x00) -#define MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION (0x01) -#define MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK (0x02) -#define MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT (0x03) -#define MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT (0x04) - -/*Integrated RAID Volume Event data */ - -typedef struct _MPI2_EVENT_DATA_IR_VOLUME { - U16 VolDevHandle; /*0x00 */ - U8 ReasonCode; /*0x02 */ - U8 Reserved1; /*0x03 */ - U32 NewValue; /*0x04 */ - U32 PreviousValue; /*0x08 */ -} MPI2_EVENT_DATA_IR_VOLUME, *PTR_MPI2_EVENT_DATA_IR_VOLUME, - Mpi2EventDataIrVolume_t, *pMpi2EventDataIrVolume_t; - -/*Integrated RAID Volume Event data ReasonCode values */ -#define MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED (0x01) -#define MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED (0x02) -#define MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED (0x03) - -/*Integrated RAID Physical Disk Event data */ - -typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK { - U16 Reserved1; /*0x00 */ - U8 ReasonCode; /*0x02 */ - U8 PhysDiskNum; /*0x03 */ - U16 PhysDiskDevHandle; /*0x04 */ - U16 Reserved2; /*0x06 */ - U16 Slot; /*0x08 */ - U16 EnclosureHandle; /*0x0A */ - U32 NewValue; /*0x0C */ - U32 PreviousValue; /*0x10 */ -} MPI2_EVENT_DATA_IR_PHYSICAL_DISK, - *PTR_MPI2_EVENT_DATA_IR_PHYSICAL_DISK, - Mpi2EventDataIrPhysicalDisk_t, - *pMpi2EventDataIrPhysicalDisk_t; - -/*Integrated RAID Physical Disk Event data ReasonCode values */ -#define MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED (0x01) -#define MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED (0x02) -#define MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED (0x03) - -/*Integrated RAID Configuration Change List Event data */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check NumElements at runtime. - */ -#ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT -#define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT (1) -#endif - -typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT { - U16 ElementFlags; /*0x00 */ - U16 VolDevHandle; /*0x02 */ - U8 ReasonCode; /*0x04 */ - U8 PhysDiskNum; /*0x05 */ - U16 PhysDiskDevHandle; /*0x06 */ -} MPI2_EVENT_IR_CONFIG_ELEMENT, *PTR_MPI2_EVENT_IR_CONFIG_ELEMENT, - Mpi2EventIrConfigElement_t, *pMpi2EventIrConfigElement_t; - -/*IR Configuration Change List Event data ElementFlags values */ -#define MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK (0x000F) -#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT (0x0000) -#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT (0x0001) -#define MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT (0x0002) - -/*IR Configuration Change List Event data ReasonCode values */ -#define MPI2_EVENT_IR_CHANGE_RC_ADDED (0x01) -#define MPI2_EVENT_IR_CHANGE_RC_REMOVED (0x02) -#define MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE (0x03) -#define MPI2_EVENT_IR_CHANGE_RC_HIDE (0x04) -#define MPI2_EVENT_IR_CHANGE_RC_UNHIDE (0x05) -#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED (0x06) -#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED (0x07) -#define MPI2_EVENT_IR_CHANGE_RC_PD_CREATED (0x08) -#define MPI2_EVENT_IR_CHANGE_RC_PD_DELETED (0x09) - -typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST { - U8 NumElements; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 Reserved2; /*0x02 */ - U8 ConfigNum; /*0x03 */ - U32 Flags; /*0x04 */ - MPI2_EVENT_IR_CONFIG_ELEMENT - ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT];/*0x08 */ -} MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST, - *PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST, - Mpi2EventDataIrConfigChangeList_t, - *pMpi2EventDataIrConfigChangeList_t; - -/*IR Configuration Change List Event data Flags values */ -#define MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG (0x00000001) - -/*SAS Discovery Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_DISCOVERY { - U8 Flags; /*0x00 */ - U8 ReasonCode; /*0x01 */ - U8 PhysicalPort; /*0x02 */ - U8 Reserved1; /*0x03 */ - U32 DiscoveryStatus; /*0x04 */ -} MPI2_EVENT_DATA_SAS_DISCOVERY, - *PTR_MPI2_EVENT_DATA_SAS_DISCOVERY, - Mpi2EventDataSasDiscovery_t, *pMpi2EventDataSasDiscovery_t; - -/*SAS Discovery Event data Flags values */ -#define MPI2_EVENT_SAS_DISC_DEVICE_CHANGE (0x02) -#define MPI2_EVENT_SAS_DISC_IN_PROGRESS (0x01) - -/*SAS Discovery Event data ReasonCode values */ -#define MPI2_EVENT_SAS_DISC_RC_STARTED (0x01) -#define MPI2_EVENT_SAS_DISC_RC_COMPLETED (0x02) - -/*SAS Discovery Event data DiscoveryStatus values */ -#define MPI2_EVENT_SAS_DISC_DS_MAX_ENCLOSURES_EXCEED (0x80000000) -#define MPI2_EVENT_SAS_DISC_DS_MAX_EXPANDERS_EXCEED (0x40000000) -#define MPI2_EVENT_SAS_DISC_DS_MAX_DEVICES_EXCEED (0x20000000) -#define MPI2_EVENT_SAS_DISC_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) -#define MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR (0x08000000) -#define MPI2_EVENT_SAS_DISC_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) -#define MPI2_EVENT_SAS_DISC_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) -#define MPI2_EVENT_SAS_DISC_DS_MULTI_PORT_DOMAIN (0x00002000) -#define MPI2_EVENT_SAS_DISC_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) -#define MPI2_EVENT_SAS_DISC_DS_UNSUPPORTED_DEVICE (0x00000800) -#define MPI2_EVENT_SAS_DISC_DS_TABLE_LINK (0x00000400) -#define MPI2_EVENT_SAS_DISC_DS_SUBTRACTIVE_LINK (0x00000200) -#define MPI2_EVENT_SAS_DISC_DS_SMP_CRC_ERROR (0x00000100) -#define MPI2_EVENT_SAS_DISC_DS_SMP_FUNCTION_FAILED (0x00000080) -#define MPI2_EVENT_SAS_DISC_DS_INDEX_NOT_EXIST (0x00000040) -#define MPI2_EVENT_SAS_DISC_DS_OUT_ROUTE_ENTRIES (0x00000020) -#define MPI2_EVENT_SAS_DISC_DS_SMP_TIMEOUT (0x00000010) -#define MPI2_EVENT_SAS_DISC_DS_MULTIPLE_PORTS (0x00000004) -#define MPI2_EVENT_SAS_DISC_DS_UNADDRESSABLE_DEVICE (0x00000002) -#define MPI2_EVENT_SAS_DISC_DS_LOOP_DETECTED (0x00000001) - -/*SAS Broadcast Primitive Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE { - U8 PhyNum; /*0x00 */ - U8 Port; /*0x01 */ - U8 PortWidth; /*0x02 */ - U8 Primitive; /*0x03 */ -} MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, - *PTR_MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, - Mpi2EventDataSasBroadcastPrimitive_t, - *pMpi2EventDataSasBroadcastPrimitive_t; - -/*defines for the Primitive field */ -#define MPI2_EVENT_PRIMITIVE_CHANGE (0x01) -#define MPI2_EVENT_PRIMITIVE_SES (0x02) -#define MPI2_EVENT_PRIMITIVE_EXPANDER (0x03) -#define MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT (0x04) -#define MPI2_EVENT_PRIMITIVE_RESERVED3 (0x05) -#define MPI2_EVENT_PRIMITIVE_RESERVED4 (0x06) -#define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED (0x07) -#define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED (0x08) - -/*SAS Notify Primitive Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE { - U8 PhyNum; /*0x00 */ - U8 Port; /*0x01 */ - U8 Reserved1; /*0x02 */ - U8 Primitive; /*0x03 */ -} MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, - *PTR_MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, - Mpi2EventDataSasNotifyPrimitive_t, - *pMpi2EventDataSasNotifyPrimitive_t; - -/*defines for the Primitive field */ -#define MPI2_EVENT_NOTIFY_ENABLE_SPINUP (0x01) -#define MPI2_EVENT_NOTIFY_POWER_LOSS_EXPECTED (0x02) -#define MPI2_EVENT_NOTIFY_RESERVED1 (0x03) -#define MPI2_EVENT_NOTIFY_RESERVED2 (0x04) - -/*SAS Initiator Device Status Change Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE { - U8 ReasonCode; /*0x00 */ - U8 PhysicalPort; /*0x01 */ - U16 DevHandle; /*0x02 */ - U64 SASAddress; /*0x04 */ -} MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, - *PTR_MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, - Mpi2EventDataSasInitDevStatusChange_t, - *pMpi2EventDataSasInitDevStatusChange_t; - -/*SAS Initiator Device Status Change event ReasonCode values */ -#define MPI2_EVENT_SAS_INIT_RC_ADDED (0x01) -#define MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING (0x02) - -/*SAS Initiator Device Table Overflow Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW { - U16 MaxInit; /*0x00 */ - U16 CurrentInit; /*0x02 */ - U64 SASAddress; /*0x04 */ -} MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, - *PTR_MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, - Mpi2EventDataSasInitTableOverflow_t, - *pMpi2EventDataSasInitTableOverflow_t; - -/*SAS Topology Change List Event data */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check NumEntries at runtime. - */ -#ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT -#define MPI2_EVENT_SAS_TOPO_PHY_COUNT (1) -#endif - -typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY { - U16 AttachedDevHandle; /*0x00 */ - U8 LinkRate; /*0x02 */ - U8 PhyStatus; /*0x03 */ -} MPI2_EVENT_SAS_TOPO_PHY_ENTRY, *PTR_MPI2_EVENT_SAS_TOPO_PHY_ENTRY, - Mpi2EventSasTopoPhyEntry_t, *pMpi2EventSasTopoPhyEntry_t; - -typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST { - U16 EnclosureHandle; /*0x00 */ - U16 ExpanderDevHandle; /*0x02 */ - U8 NumPhys; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 Reserved2; /*0x06 */ - U8 NumEntries; /*0x08 */ - U8 StartPhyNum; /*0x09 */ - U8 ExpStatus; /*0x0A */ - U8 PhysicalPort; /*0x0B */ - MPI2_EVENT_SAS_TOPO_PHY_ENTRY - PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /*0x0C */ -} MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, - *PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, - Mpi2EventDataSasTopologyChangeList_t, - *pMpi2EventDataSasTopologyChangeList_t; - -/*values for the ExpStatus field */ -#define MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER (0x00) -#define MPI2_EVENT_SAS_TOPO_ES_ADDED (0x01) -#define MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING (0x02) -#define MPI2_EVENT_SAS_TOPO_ES_RESPONDING (0x03) -#define MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING (0x04) - -/*defines for the LinkRate field */ -#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK (0xF0) -#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT (4) -#define MPI2_EVENT_SAS_TOPO_LR_PREV_MASK (0x0F) -#define MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT (0) - -#define MPI2_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE (0x00) -#define MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED (0x01) -#define MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED (0x02) -#define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03) -#define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04) -#define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05) -#define MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY (0x06) -#define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5 (0x08) -#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09) -#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A) -#define MPI25_EVENT_SAS_TOPO_LR_RATE_12_0 (0x0B) - -/*values for the PhyStatus field */ -#define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT (0x80) -#define MPI2_EVENT_SAS_TOPO_PS_MULTIPLEX_CHANGE (0x10) -/*values for the PhyStatus ReasonCode sub-field */ -#define MPI2_EVENT_SAS_TOPO_RC_MASK (0x0F) -#define MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED (0x01) -#define MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING (0x02) -#define MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED (0x03) -#define MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE (0x04) -#define MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING (0x05) - -/*SAS Enclosure Device Status Change Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE { - U16 EnclosureHandle; /*0x00 */ - U8 ReasonCode; /*0x02 */ - U8 PhysicalPort; /*0x03 */ - U64 EnclosureLogicalID; /*0x04 */ - U16 NumSlots; /*0x0C */ - U16 StartSlot; /*0x0E */ - U32 PhyBits; /*0x10 */ -} MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE, - *PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE, - Mpi2EventDataSasEnclDevStatusChange_t, - *pMpi2EventDataSasEnclDevStatusChange_t; - -/*SAS Enclosure Device Status Change event ReasonCode values */ -#define MPI2_EVENT_SAS_ENCL_RC_ADDED (0x01) -#define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02) - -/*SAS PHY Counter Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_PHY_COUNTER { - U64 TimeStamp; /*0x00 */ - U32 Reserved1; /*0x08 */ - U8 PhyEventCode; /*0x0C */ - U8 PhyNum; /*0x0D */ - U16 Reserved2; /*0x0E */ - U32 PhyEventInfo; /*0x10 */ - U8 CounterType; /*0x14 */ - U8 ThresholdWindow; /*0x15 */ - U8 TimeUnits; /*0x16 */ - U8 Reserved3; /*0x17 */ - U32 EventThreshold; /*0x18 */ - U16 ThresholdFlags; /*0x1C */ - U16 Reserved4; /*0x1E */ -} MPI2_EVENT_DATA_SAS_PHY_COUNTER, - *PTR_MPI2_EVENT_DATA_SAS_PHY_COUNTER, - Mpi2EventDataSasPhyCounter_t, - *pMpi2EventDataSasPhyCounter_t; - -/*use MPI2_SASPHY3_EVENT_CODE_ values from mpi2_cnfg.h - *for the PhyEventCode field */ - -/*use MPI2_SASPHY3_COUNTER_TYPE_ values from mpi2_cnfg.h - *for the CounterType field */ - -/*use MPI2_SASPHY3_TIME_UNITS_ values from mpi2_cnfg.h - *for the TimeUnits field */ - -/*use MPI2_SASPHY3_TFLAGS_ values from mpi2_cnfg.h - *for the ThresholdFlags field */ - -/*SAS Quiesce Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_QUIESCE { - U8 ReasonCode; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 Reserved3; /*0x04 */ -} MPI2_EVENT_DATA_SAS_QUIESCE, - *PTR_MPI2_EVENT_DATA_SAS_QUIESCE, - Mpi2EventDataSasQuiesce_t, *pMpi2EventDataSasQuiesce_t; - -/*SAS Quiesce Event data ReasonCode values */ -#define MPI2_EVENT_SAS_QUIESCE_RC_STARTED (0x01) -#define MPI2_EVENT_SAS_QUIESCE_RC_COMPLETED (0x02) - -/*Host Based Discovery Phy Event data */ - -typedef struct _MPI2_EVENT_HBD_PHY_SAS { - U8 Flags; /*0x00 */ - U8 NegotiatedLinkRate; /*0x01 */ - U8 PhyNum; /*0x02 */ - U8 PhysicalPort; /*0x03 */ - U32 Reserved1; /*0x04 */ - U8 InitialFrame[28]; /*0x08 */ -} MPI2_EVENT_HBD_PHY_SAS, *PTR_MPI2_EVENT_HBD_PHY_SAS, - Mpi2EventHbdPhySas_t, *pMpi2EventHbdPhySas_t; - -/*values for the Flags field */ -#define MPI2_EVENT_HBD_SAS_FLAGS_FRAME_VALID (0x02) -#define MPI2_EVENT_HBD_SAS_FLAGS_SATA_FRAME (0x01) - -/*use MPI2_SAS_NEG_LINK_RATE_ defines from mpi2_cnfg.h - *for the NegotiatedLinkRate field */ - -typedef union _MPI2_EVENT_HBD_DESCRIPTOR { - MPI2_EVENT_HBD_PHY_SAS Sas; -} MPI2_EVENT_HBD_DESCRIPTOR, *PTR_MPI2_EVENT_HBD_DESCRIPTOR, - Mpi2EventHbdDescriptor_t, *pMpi2EventHbdDescriptor_t; - -typedef struct _MPI2_EVENT_DATA_HBD_PHY { - U8 DescriptorType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 Reserved3; /*0x04 */ - MPI2_EVENT_HBD_DESCRIPTOR Descriptor; /*0x08 */ -} MPI2_EVENT_DATA_HBD_PHY, *PTR_MPI2_EVENT_DATA_HBD_PHY, - Mpi2EventDataHbdPhy_t, - *pMpi2EventDataMpi2EventDataHbdPhy_t; - -/*values for the DescriptorType field */ -#define MPI2_EVENT_HBD_DT_SAS (0x01) - -/**************************************************************************** -* EventAck message -****************************************************************************/ - -/*EventAck Request message */ -typedef struct _MPI2_EVENT_ACK_REQUEST { - U16 Reserved1; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Event; /*0x0C */ - U16 Reserved5; /*0x0E */ - U32 EventContext; /*0x10 */ -} MPI2_EVENT_ACK_REQUEST, *PTR_MPI2_EVENT_ACK_REQUEST, - Mpi2EventAckRequest_t, *pMpi2EventAckRequest_t; - -/*EventAck Reply message */ -typedef struct _MPI2_EVENT_ACK_REPLY { - U16 Reserved1; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_EVENT_ACK_REPLY, *PTR_MPI2_EVENT_ACK_REPLY, - Mpi2EventAckReply_t, *pMpi2EventAckReply_t; - -/**************************************************************************** -* SendHostMessage message -****************************************************************************/ - -/*SendHostMessage Request message */ -typedef struct _MPI2_SEND_HOST_MESSAGE_REQUEST { - U16 HostDataLength; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved1; /*0x04 */ - U8 Reserved2; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U8 Reserved4; /*0x0C */ - U8 DestVF_ID; /*0x0D */ - U16 Reserved5; /*0x0E */ - U32 Reserved6; /*0x10 */ - U32 Reserved7; /*0x14 */ - U32 Reserved8; /*0x18 */ - U32 Reserved9; /*0x1C */ - U32 Reserved10; /*0x20 */ - U32 HostData[1]; /*0x24 */ -} MPI2_SEND_HOST_MESSAGE_REQUEST, - *PTR_MPI2_SEND_HOST_MESSAGE_REQUEST, - Mpi2SendHostMessageRequest_t, - *pMpi2SendHostMessageRequest_t; - -/*SendHostMessage Reply message */ -typedef struct _MPI2_SEND_HOST_MESSAGE_REPLY { - U16 HostDataLength; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved1; /*0x04 */ - U8 Reserved2; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U16 Reserved4; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_SEND_HOST_MESSAGE_REPLY, *PTR_MPI2_SEND_HOST_MESSAGE_REPLY, - Mpi2SendHostMessageReply_t, *pMpi2SendHostMessageReply_t; - -/**************************************************************************** -* FWDownload message -****************************************************************************/ - -/*MPI v2.0 FWDownload Request message */ -typedef struct _MPI2_FW_DOWNLOAD_REQUEST { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 TotalImageSize; /*0x0C */ - U32 Reserved5; /*0x10 */ - MPI2_MPI_SGE_UNION SGL; /*0x14 */ -} MPI2_FW_DOWNLOAD_REQUEST, *PTR_MPI2_FW_DOWNLOAD_REQUEST, - Mpi2FWDownloadRequest, *pMpi2FWDownloadRequest; - -#define MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01) - -#define MPI2_FW_DOWNLOAD_ITYPE_FW (0x01) -#define MPI2_FW_DOWNLOAD_ITYPE_BIOS (0x02) -#define MPI2_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06) -#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07) -#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08) -#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09) -#define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE (0x0A) -#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) -#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0) - -/*MPI v2.0 FWDownload TransactionContext Element */ -typedef struct _MPI2_FW_DOWNLOAD_TCSGE { - U8 Reserved1; /*0x00 */ - U8 ContextSize; /*0x01 */ - U8 DetailsLength; /*0x02 */ - U8 Flags; /*0x03 */ - U32 Reserved2; /*0x04 */ - U32 ImageOffset; /*0x08 */ - U32 ImageSize; /*0x0C */ -} MPI2_FW_DOWNLOAD_TCSGE, *PTR_MPI2_FW_DOWNLOAD_TCSGE, - Mpi2FWDownloadTCSGE_t, *pMpi2FWDownloadTCSGE_t; - -/*MPI v2.5 FWDownload Request message */ -typedef struct _MPI25_FW_DOWNLOAD_REQUEST { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 TotalImageSize; /*0x0C */ - U32 Reserved5; /*0x10 */ - U32 Reserved6; /*0x14 */ - U32 ImageOffset; /*0x18 */ - U32 ImageSize; /*0x1C */ - MPI25_SGE_IO_UNION SGL; /*0x20 */ -} MPI25_FW_DOWNLOAD_REQUEST, *PTR_MPI25_FW_DOWNLOAD_REQUEST, - Mpi25FWDownloadRequest, *pMpi25FWDownloadRequest; - -/*FWDownload Reply message */ -typedef struct _MPI2_FW_DOWNLOAD_REPLY { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_FW_DOWNLOAD_REPLY, *PTR_MPI2_FW_DOWNLOAD_REPLY, - Mpi2FWDownloadReply_t, *pMpi2FWDownloadReply_t; - -/**************************************************************************** -* FWUpload message -****************************************************************************/ - -/*MPI v2.0 FWUpload Request message */ -typedef struct _MPI2_FW_UPLOAD_REQUEST { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 Reserved5; /*0x0C */ - U32 Reserved6; /*0x10 */ - MPI2_MPI_SGE_UNION SGL; /*0x14 */ -} MPI2_FW_UPLOAD_REQUEST, *PTR_MPI2_FW_UPLOAD_REQUEST, - Mpi2FWUploadRequest_t, *pMpi2FWUploadRequest_t; - -#define MPI2_FW_UPLOAD_ITYPE_FW_CURRENT (0x00) -#define MPI2_FW_UPLOAD_ITYPE_FW_FLASH (0x01) -#define MPI2_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02) -#define MPI2_FW_UPLOAD_ITYPE_FW_BACKUP (0x05) -#define MPI2_FW_UPLOAD_ITYPE_MANUFACTURING (0x06) -#define MPI2_FW_UPLOAD_ITYPE_CONFIG_1 (0x07) -#define MPI2_FW_UPLOAD_ITYPE_CONFIG_2 (0x08) -#define MPI2_FW_UPLOAD_ITYPE_MEGARAID (0x09) -#define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A) -#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) - -/*MPI v2.0 FWUpload TransactionContext Element */ -typedef struct _MPI2_FW_UPLOAD_TCSGE { - U8 Reserved1; /*0x00 */ - U8 ContextSize; /*0x01 */ - U8 DetailsLength; /*0x02 */ - U8 Flags; /*0x03 */ - U32 Reserved2; /*0x04 */ - U32 ImageOffset; /*0x08 */ - U32 ImageSize; /*0x0C */ -} MPI2_FW_UPLOAD_TCSGE, *PTR_MPI2_FW_UPLOAD_TCSGE, - Mpi2FWUploadTCSGE_t, *pMpi2FWUploadTCSGE_t; - -/*MPI v2.5 FWUpload Request message */ -typedef struct _MPI25_FW_UPLOAD_REQUEST { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 Reserved5; /*0x0C */ - U32 Reserved6; /*0x10 */ - U32 Reserved7; /*0x14 */ - U32 ImageOffset; /*0x18 */ - U32 ImageSize; /*0x1C */ - MPI25_SGE_IO_UNION SGL; /*0x20 */ -} MPI25_FW_UPLOAD_REQUEST, *PTR_MPI25_FW_UPLOAD_REQUEST, - Mpi25FWUploadRequest_t, *pMpi25FWUploadRequest_t; - -/*FWUpload Reply message */ -typedef struct _MPI2_FW_UPLOAD_REPLY { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 ActualImageSize; /*0x14 */ -} MPI2_FW_UPLOAD_REPLY, *PTR_MPI2_FW_UPLOAD_REPLY, - Mpi2FWUploadReply_t, *pMPi2FWUploadReply_t; - -/*FW Image Header */ -typedef struct _MPI2_FW_IMAGE_HEADER { - U32 Signature; /*0x00 */ - U32 Signature0; /*0x04 */ - U32 Signature1; /*0x08 */ - U32 Signature2; /*0x0C */ - MPI2_VERSION_UNION MPIVersion; /*0x10 */ - MPI2_VERSION_UNION FWVersion; /*0x14 */ - MPI2_VERSION_UNION NVDATAVersion; /*0x18 */ - MPI2_VERSION_UNION PackageVersion; /*0x1C */ - U16 VendorID; /*0x20 */ - U16 ProductID; /*0x22 */ - U16 ProtocolFlags; /*0x24 */ - U16 Reserved26; /*0x26 */ - U32 IOCCapabilities; /*0x28 */ - U32 ImageSize; /*0x2C */ - U32 NextImageHeaderOffset; /*0x30 */ - U32 Checksum; /*0x34 */ - U32 Reserved38; /*0x38 */ - U32 Reserved3C; /*0x3C */ - U32 Reserved40; /*0x40 */ - U32 Reserved44; /*0x44 */ - U32 Reserved48; /*0x48 */ - U32 Reserved4C; /*0x4C */ - U32 Reserved50; /*0x50 */ - U32 Reserved54; /*0x54 */ - U32 Reserved58; /*0x58 */ - U32 Reserved5C; /*0x5C */ - U32 Reserved60; /*0x60 */ - U32 FirmwareVersionNameWhat; /*0x64 */ - U8 FirmwareVersionName[32]; /*0x68 */ - U32 VendorNameWhat; /*0x88 */ - U8 VendorName[32]; /*0x8C */ - U32 PackageNameWhat; /*0x88 */ - U8 PackageName[32]; /*0x8C */ - U32 ReservedD0; /*0xD0 */ - U32 ReservedD4; /*0xD4 */ - U32 ReservedD8; /*0xD8 */ - U32 ReservedDC; /*0xDC */ - U32 ReservedE0; /*0xE0 */ - U32 ReservedE4; /*0xE4 */ - U32 ReservedE8; /*0xE8 */ - U32 ReservedEC; /*0xEC */ - U32 ReservedF0; /*0xF0 */ - U32 ReservedF4; /*0xF4 */ - U32 ReservedF8; /*0xF8 */ - U32 ReservedFC; /*0xFC */ -} MPI2_FW_IMAGE_HEADER, *PTR_MPI2_FW_IMAGE_HEADER, - Mpi2FWImageHeader_t, *pMpi2FWImageHeader_t; - -/*Signature field */ -#define MPI2_FW_HEADER_SIGNATURE_OFFSET (0x00) -#define MPI2_FW_HEADER_SIGNATURE_MASK (0xFF000000) -#define MPI2_FW_HEADER_SIGNATURE (0xEA000000) - -/*Signature0 field */ -#define MPI2_FW_HEADER_SIGNATURE0_OFFSET (0x04) -#define MPI2_FW_HEADER_SIGNATURE0 (0x5AFAA55A) - -/*Signature1 field */ -#define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08) -#define MPI2_FW_HEADER_SIGNATURE1 (0xA55AFAA5) - -/*Signature2 field */ -#define MPI2_FW_HEADER_SIGNATURE2_OFFSET (0x0C) -#define MPI2_FW_HEADER_SIGNATURE2 (0x5AA55AFA) - -/*defines for using the ProductID field */ -#define MPI2_FW_HEADER_PID_TYPE_MASK (0xF000) -#define MPI2_FW_HEADER_PID_TYPE_SAS (0x2000) - -#define MPI2_FW_HEADER_PID_PROD_MASK (0x0F00) -#define MPI2_FW_HEADER_PID_PROD_A (0x0000) -#define MPI2_FW_HEADER_PID_PROD_TARGET_INITIATOR_SCSI (0x0200) -#define MPI2_FW_HEADER_PID_PROD_IR_SCSI (0x0700) - -#define MPI2_FW_HEADER_PID_FAMILY_MASK (0x00FF) -/*SAS ProductID Family bits */ -#define MPI2_FW_HEADER_PID_FAMILY_2108_SAS (0x0013) -#define MPI2_FW_HEADER_PID_FAMILY_2208_SAS (0x0014) -#define MPI25_FW_HEADER_PID_FAMILY_3108_SAS (0x0021) - -/*use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */ - -/*use MPI2_IOCFACTS_CAPABILITY_ defines for IOCCapabilities field */ - -#define MPI2_FW_HEADER_IMAGESIZE_OFFSET (0x2C) -#define MPI2_FW_HEADER_NEXTIMAGE_OFFSET (0x30) -#define MPI2_FW_HEADER_VERNMHWAT_OFFSET (0x64) - -#define MPI2_FW_HEADER_WHAT_SIGNATURE (0x29232840) - -#define MPI2_FW_HEADER_SIZE (0x100) - -/*Extended Image Header */ -typedef struct _MPI2_EXT_IMAGE_HEADER { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 Checksum; /*0x04 */ - U32 ImageSize; /*0x08 */ - U32 NextImageHeaderOffset; /*0x0C */ - U32 PackageVersion; /*0x10 */ - U32 Reserved3; /*0x14 */ - U32 Reserved4; /*0x18 */ - U32 Reserved5; /*0x1C */ - U8 IdentifyString[32]; /*0x20 */ -} MPI2_EXT_IMAGE_HEADER, *PTR_MPI2_EXT_IMAGE_HEADER, - Mpi2ExtImageHeader_t, *pMpi2ExtImageHeader_t; - -/*useful offsets */ -#define MPI2_EXT_IMAGE_IMAGETYPE_OFFSET (0x00) -#define MPI2_EXT_IMAGE_IMAGESIZE_OFFSET (0x08) -#define MPI2_EXT_IMAGE_NEXTIMAGE_OFFSET (0x0C) - -#define MPI2_EXT_IMAGE_HEADER_SIZE (0x40) - -/*defines for the ImageType field */ -#define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED (0x00) -#define MPI2_EXT_IMAGE_TYPE_FW (0x01) -#define MPI2_EXT_IMAGE_TYPE_NVDATA (0x03) -#define MPI2_EXT_IMAGE_TYPE_BOOTLOADER (0x04) -#define MPI2_EXT_IMAGE_TYPE_INITIALIZATION (0x05) -#define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT (0x06) -#define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07) -#define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08) -#define MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC (0x80) -#define MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC (0xFF) - -#define MPI2_EXT_IMAGE_TYPE_MAX (MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC) - -/*FLASH Layout Extended Image Data */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check RegionsPerLayout at runtime. - */ -#ifndef MPI2_FLASH_NUMBER_OF_REGIONS -#define MPI2_FLASH_NUMBER_OF_REGIONS (1) -#endif - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check NumberOfLayouts at runtime. - */ -#ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS -#define MPI2_FLASH_NUMBER_OF_LAYOUTS (1) -#endif - -typedef struct _MPI2_FLASH_REGION { - U8 RegionType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 RegionOffset; /*0x04 */ - U32 RegionSize; /*0x08 */ - U32 Reserved3; /*0x0C */ -} MPI2_FLASH_REGION, *PTR_MPI2_FLASH_REGION, - Mpi2FlashRegion_t, *pMpi2FlashRegion_t; - -typedef struct _MPI2_FLASH_LAYOUT { - U32 FlashSize; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Reserved2; /*0x08 */ - U32 Reserved3; /*0x0C */ - MPI2_FLASH_REGION Region[MPI2_FLASH_NUMBER_OF_REGIONS]; /*0x10 */ -} MPI2_FLASH_LAYOUT, *PTR_MPI2_FLASH_LAYOUT, - Mpi2FlashLayout_t, *pMpi2FlashLayout_t; - -typedef struct _MPI2_FLASH_LAYOUT_DATA { - U8 ImageRevision; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 SizeOfRegion; /*0x02 */ - U8 Reserved2; /*0x03 */ - U16 NumberOfLayouts; /*0x04 */ - U16 RegionsPerLayout; /*0x06 */ - U16 MinimumSectorAlignment; /*0x08 */ - U16 Reserved3; /*0x0A */ - U32 Reserved4; /*0x0C */ - MPI2_FLASH_LAYOUT Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS]; /*0x10 */ -} MPI2_FLASH_LAYOUT_DATA, *PTR_MPI2_FLASH_LAYOUT_DATA, - Mpi2FlashLayoutData_t, *pMpi2FlashLayoutData_t; - -/*defines for the RegionType field */ -#define MPI2_FLASH_REGION_UNUSED (0x00) -#define MPI2_FLASH_REGION_FIRMWARE (0x01) -#define MPI2_FLASH_REGION_BIOS (0x02) -#define MPI2_FLASH_REGION_NVDATA (0x03) -#define MPI2_FLASH_REGION_FIRMWARE_BACKUP (0x05) -#define MPI2_FLASH_REGION_MFG_INFORMATION (0x06) -#define MPI2_FLASH_REGION_CONFIG_1 (0x07) -#define MPI2_FLASH_REGION_CONFIG_2 (0x08) -#define MPI2_FLASH_REGION_MEGARAID (0x09) -#define MPI2_FLASH_REGION_INIT (0x0A) - -/*ImageRevision */ -#define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00) - -/*Supported Devices Extended Image Data */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check NumberOfDevices at runtime. - */ -#ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES -#define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES (1) -#endif - -typedef struct _MPI2_SUPPORTED_DEVICE { - U16 DeviceID; /*0x00 */ - U16 VendorID; /*0x02 */ - U16 DeviceIDMask; /*0x04 */ - U16 Reserved1; /*0x06 */ - U8 LowPCIRev; /*0x08 */ - U8 HighPCIRev; /*0x09 */ - U16 Reserved2; /*0x0A */ - U32 Reserved3; /*0x0C */ -} MPI2_SUPPORTED_DEVICE, *PTR_MPI2_SUPPORTED_DEVICE, - Mpi2SupportedDevice_t, *pMpi2SupportedDevice_t; - -typedef struct _MPI2_SUPPORTED_DEVICES_DATA { - U8 ImageRevision; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 NumberOfDevices; /*0x02 */ - U8 Reserved2; /*0x03 */ - U32 Reserved3; /*0x04 */ - MPI2_SUPPORTED_DEVICE - SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES];/*0x08 */ -} MPI2_SUPPORTED_DEVICES_DATA, *PTR_MPI2_SUPPORTED_DEVICES_DATA, - Mpi2SupportedDevicesData_t, *pMpi2SupportedDevicesData_t; - -/*ImageRevision */ -#define MPI2_SUPPORTED_DEVICES_IMAGE_REVISION (0x00) - -/*Init Extended Image Data */ - -typedef struct _MPI2_INIT_IMAGE_FOOTER { - U32 BootFlags; /*0x00 */ - U32 ImageSize; /*0x04 */ - U32 Signature0; /*0x08 */ - U32 Signature1; /*0x0C */ - U32 Signature2; /*0x10 */ - U32 ResetVector; /*0x14 */ -} MPI2_INIT_IMAGE_FOOTER, *PTR_MPI2_INIT_IMAGE_FOOTER, - Mpi2InitImageFooter_t, *pMpi2InitImageFooter_t; - -/*defines for the BootFlags field */ -#define MPI2_INIT_IMAGE_BOOTFLAGS_OFFSET (0x00) - -/*defines for the ImageSize field */ -#define MPI2_INIT_IMAGE_IMAGESIZE_OFFSET (0x04) - -/*defines for the Signature0 field */ -#define MPI2_INIT_IMAGE_SIGNATURE0_OFFSET (0x08) -#define MPI2_INIT_IMAGE_SIGNATURE0 (0x5AA55AEA) - -/*defines for the Signature1 field */ -#define MPI2_INIT_IMAGE_SIGNATURE1_OFFSET (0x0C) -#define MPI2_INIT_IMAGE_SIGNATURE1 (0xA55AEAA5) - -/*defines for the Signature2 field */ -#define MPI2_INIT_IMAGE_SIGNATURE2_OFFSET (0x10) -#define MPI2_INIT_IMAGE_SIGNATURE2 (0x5AEAA55A) - -/*Signature fields as individual bytes */ -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_0 (0xEA) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_1 (0x5A) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_2 (0xA5) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_3 (0x5A) - -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_4 (0xA5) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_5 (0xEA) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_6 (0x5A) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_7 (0xA5) - -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_8 (0x5A) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_9 (0xA5) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_A (0xEA) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_B (0x5A) - -/*defines for the ResetVector field */ -#define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET (0x14) - -/**************************************************************************** -* PowerManagementControl message -****************************************************************************/ - -/*PowerManagementControl Request message */ -typedef struct _MPI2_PWR_MGMT_CONTROL_REQUEST { - U8 Feature; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U8 Parameter1; /*0x0C */ - U8 Parameter2; /*0x0D */ - U8 Parameter3; /*0x0E */ - U8 Parameter4; /*0x0F */ - U32 Reserved5; /*0x10 */ - U32 Reserved6; /*0x14 */ -} MPI2_PWR_MGMT_CONTROL_REQUEST, *PTR_MPI2_PWR_MGMT_CONTROL_REQUEST, - Mpi2PwrMgmtControlRequest_t, *pMpi2PwrMgmtControlRequest_t; - -/*defines for the Feature field */ -#define MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND (0x01) -#define MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION (0x02) -#define MPI2_PM_CONTROL_FEATURE_PCIE_LINK (0x03) /*obsolete */ -#define MPI2_PM_CONTROL_FEATURE_IOC_SPEED (0x04) -#define MPI2_PM_CONTROL_FEATURE_GLOBAL_PWR_MGMT_MODE (0x05) -#define MPI2_PM_CONTROL_FEATURE_MIN_PRODUCT_SPECIFIC (0x80) -#define MPI2_PM_CONTROL_FEATURE_MAX_PRODUCT_SPECIFIC (0xFF) - -/*parameter usage for the MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND Feature */ -/*Parameter1 contains a PHY number */ -/*Parameter2 indicates power condition action using these defines */ -#define MPI2_PM_CONTROL_PARAM2_PARTIAL (0x01) -#define MPI2_PM_CONTROL_PARAM2_SLUMBER (0x02) -#define MPI2_PM_CONTROL_PARAM2_EXIT_PWR_MGMT (0x03) -/*Parameter3 and Parameter4 are reserved */ - -/*parameter usage for the MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION - * Feature */ -/*Parameter1 contains SAS port width modulation group number */ -/*Parameter2 indicates IOC action using these defines */ -#define MPI2_PM_CONTROL_PARAM2_REQUEST_OWNERSHIP (0x01) -#define MPI2_PM_CONTROL_PARAM2_CHANGE_MODULATION (0x02) -#define MPI2_PM_CONTROL_PARAM2_RELINQUISH_OWNERSHIP (0x03) -/*Parameter3 indicates desired modulation level using these defines */ -#define MPI2_PM_CONTROL_PARAM3_25_PERCENT (0x00) -#define MPI2_PM_CONTROL_PARAM3_50_PERCENT (0x01) -#define MPI2_PM_CONTROL_PARAM3_75_PERCENT (0x02) -#define MPI2_PM_CONTROL_PARAM3_100_PERCENT (0x03) -/*Parameter4 is reserved */ - -/*this next set (_PCIE_LINK) is obsolete */ -/*parameter usage for the MPI2_PM_CONTROL_FEATURE_PCIE_LINK Feature */ -/*Parameter1 indicates desired PCIe link speed using these defines */ -#define MPI2_PM_CONTROL_PARAM1_PCIE_2_5_GBPS (0x00) /*obsolete */ -#define MPI2_PM_CONTROL_PARAM1_PCIE_5_0_GBPS (0x01) /*obsolete */ -#define MPI2_PM_CONTROL_PARAM1_PCIE_8_0_GBPS (0x02) /*obsolete */ -/*Parameter2 indicates desired PCIe link width using these defines */ -#define MPI2_PM_CONTROL_PARAM2_WIDTH_X1 (0x01) /*obsolete */ -#define MPI2_PM_CONTROL_PARAM2_WIDTH_X2 (0x02) /*obsolete */ -#define MPI2_PM_CONTROL_PARAM2_WIDTH_X4 (0x04) /*obsolete */ -#define MPI2_PM_CONTROL_PARAM2_WIDTH_X8 (0x08) /*obsolete */ -/*Parameter3 and Parameter4 are reserved */ - -/*parameter usage for the MPI2_PM_CONTROL_FEATURE_IOC_SPEED Feature */ -/*Parameter1 indicates desired IOC hardware clock speed using these defines */ -#define MPI2_PM_CONTROL_PARAM1_FULL_IOC_SPEED (0x01) -#define MPI2_PM_CONTROL_PARAM1_HALF_IOC_SPEED (0x02) -#define MPI2_PM_CONTROL_PARAM1_QUARTER_IOC_SPEED (0x04) -#define MPI2_PM_CONTROL_PARAM1_EIGHTH_IOC_SPEED (0x08) -/*Parameter2, Parameter3, and Parameter4 are reserved */ - -/*parameter usage for the MPI2_PM_CONTROL_FEATURE_GLOBAL_PWR_MGMT_MODE Feature*/ -/*Parameter1 indicates host action regarding global power management mode */ -#define MPI2_PM_CONTROL_PARAM1_TAKE_CONTROL (0x01) -#define MPI2_PM_CONTROL_PARAM1_CHANGE_GLOBAL_MODE (0x02) -#define MPI2_PM_CONTROL_PARAM1_RELEASE_CONTROL (0x03) -/*Parameter2 indicates the requested global power management mode */ -#define MPI2_PM_CONTROL_PARAM2_FULL_PWR_PERF (0x01) -#define MPI2_PM_CONTROL_PARAM2_REDUCED_PWR_PERF (0x08) -#define MPI2_PM_CONTROL_PARAM2_STANDBY (0x40) -/*Parameter3 and Parameter4 are reserved */ - -/*PowerManagementControl Reply message */ -typedef struct _MPI2_PWR_MGMT_CONTROL_REPLY { - U8 Feature; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_PWR_MGMT_CONTROL_REPLY, *PTR_MPI2_PWR_MGMT_CONTROL_REPLY, - Mpi2PwrMgmtControlReply_t, *pMpi2PwrMgmtControlReply_t; - -#endif diff --git a/addons/mpt3sas/src/3.10.108/mpi/mpi2_raid.h b/addons/mpt3sas/src/3.10.108/mpi/mpi2_raid.h deleted file mode 100644 index d1d9866c..00000000 --- a/addons/mpt3sas/src/3.10.108/mpi/mpi2_raid.h +++ /dev/null @@ -1,346 +0,0 @@ -/* - * Copyright (c) 2000-2012 LSI Corporation. - * - * - * Name: mpi2_raid.h - * Title: MPI Integrated RAID messages and structures - * Creation Date: April 26, 2007 - * - * mpi2_raid.h Version: 02.00.08 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 08-31-07 02.00.01 Modifications to RAID Action request and reply, - * including the Actions and ActionData. - * 02-29-08 02.00.02 Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD. - * 05-21-08 02.00.03 Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that - * the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT - * can be sized by the build environment. - * 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of - * VolumeCreationFlags and marked the old one as obsolete. - * 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define. - * 08-24-10 02.00.06 Added MPI2_RAID_ACTION_COMPATIBILITY_CHECK along with - * related structures and defines. - * Added product-specific range to RAID Action values. - * 11-18-11 02.00.07 Incorporating additions for MPI v2.5. - * 02-06-12 02.00.08 Added MPI2_RAID_ACTION_PHYSDISK_HIDDEN. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_RAID_H -#define MPI2_RAID_H - -/***************************************************************************** -* -* Integrated RAID Messages -* -*****************************************************************************/ - -/**************************************************************************** -* RAID Action messages -****************************************************************************/ - -/*ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */ -#define MPI2_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000) -#define MPI2_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000001) - -/*use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for - *MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */ - -/*ActionDataWord defines for use with - *MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */ -#define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD (0x00000001) - -/*ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */ -typedef struct _MPI2_RAID_ACTION_RATE_DATA { - U8 RateToChange; /*0x00 */ - U8 RateOrMode; /*0x01 */ - U16 DataScrubDuration; /*0x02 */ -} MPI2_RAID_ACTION_RATE_DATA, *PTR_MPI2_RAID_ACTION_RATE_DATA, - Mpi2RaidActionRateData_t, *pMpi2RaidActionRateData_t; - -#define MPI2_RAID_ACTION_SET_RATE_RESYNC (0x00) -#define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB (0x01) -#define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE (0x02) - -/*ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */ -typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION { - U8 RAIDFunction; /*0x00 */ - U8 Flags; /*0x01 */ - U16 Reserved1; /*0x02 */ -} MPI2_RAID_ACTION_START_RAID_FUNCTION, - *PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION, - Mpi2RaidActionStartRaidFunction_t, - *pMpi2RaidActionStartRaidFunction_t; - -/*defines for the RAIDFunction field */ -#define MPI2_RAID_ACTION_START_BACKGROUND_INIT (0x00) -#define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01) -#define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK (0x02) - -/*defines for the Flags field */ -#define MPI2_RAID_ACTION_START_NEW (0x00) -#define MPI2_RAID_ACTION_START_RESUME (0x01) - -/*ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */ -typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION { - U8 RAIDFunction; /*0x00 */ - U8 Flags; /*0x01 */ - U16 Reserved1; /*0x02 */ -} MPI2_RAID_ACTION_STOP_RAID_FUNCTION, - *PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION, - Mpi2RaidActionStopRaidFunction_t, - *pMpi2RaidActionStopRaidFunction_t; - -/*defines for the RAIDFunction field */ -#define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT (0x00) -#define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION (0x01) -#define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK (0x02) - -/*defines for the Flags field */ -#define MPI2_RAID_ACTION_STOP_ABORT (0x00) -#define MPI2_RAID_ACTION_STOP_PAUSE (0x01) - -/*ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */ -typedef struct _MPI2_RAID_ACTION_HOT_SPARE { - U8 HotSparePool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 DevHandle; /*0x02 */ -} MPI2_RAID_ACTION_HOT_SPARE, *PTR_MPI2_RAID_ACTION_HOT_SPARE, - Mpi2RaidActionHotSpare_t, *pMpi2RaidActionHotSpare_t; - -/*ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */ -typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE { - U8 Flags; /*0x00 */ - U8 DeviceFirmwareUpdateModeTimeout; /*0x01 */ - U16 Reserved1; /*0x02 */ -} MPI2_RAID_ACTION_FW_UPDATE_MODE, - *PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE, - Mpi2RaidActionFwUpdateMode_t, - *pMpi2RaidActionFwUpdateMode_t; - -/*ActionDataWord defines for use with - *MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */ -#define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE (0x00) -#define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE (0x01) - -typedef union _MPI2_RAID_ACTION_DATA { - U32 Word; - MPI2_RAID_ACTION_RATE_DATA Rates; - MPI2_RAID_ACTION_START_RAID_FUNCTION StartRaidFunction; - MPI2_RAID_ACTION_STOP_RAID_FUNCTION StopRaidFunction; - MPI2_RAID_ACTION_HOT_SPARE HotSpare; - MPI2_RAID_ACTION_FW_UPDATE_MODE FwUpdateMode; -} MPI2_RAID_ACTION_DATA, *PTR_MPI2_RAID_ACTION_DATA, - Mpi2RaidActionData_t, *pMpi2RaidActionData_t; - -/*RAID Action Request Message */ -typedef struct _MPI2_RAID_ACTION_REQUEST { - U8 Action; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 VolDevHandle; /*0x04 */ - U8 PhysDiskNum; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved2; /*0x0A */ - U32 Reserved3; /*0x0C */ - MPI2_RAID_ACTION_DATA ActionDataWord; /*0x10 */ - MPI2_SGE_SIMPLE_UNION ActionDataSGE; /*0x14 */ -} MPI2_RAID_ACTION_REQUEST, *PTR_MPI2_RAID_ACTION_REQUEST, - Mpi2RaidActionRequest_t, *pMpi2RaidActionRequest_t; - -/*RAID Action request Action values */ - -#define MPI2_RAID_ACTION_INDICATOR_STRUCT (0x01) -#define MPI2_RAID_ACTION_CREATE_VOLUME (0x02) -#define MPI2_RAID_ACTION_DELETE_VOLUME (0x03) -#define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES (0x04) -#define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES (0x05) -#define MPI2_RAID_ACTION_PHYSDISK_OFFLINE (0x0A) -#define MPI2_RAID_ACTION_PHYSDISK_ONLINE (0x0B) -#define MPI2_RAID_ACTION_FAIL_PHYSDISK (0x0F) -#define MPI2_RAID_ACTION_ACTIVATE_VOLUME (0x11) -#define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15) -#define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE (0x17) -#define MPI2_RAID_ACTION_SET_VOLUME_NAME (0x18) -#define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE (0x19) -#define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME (0x1C) -#define MPI2_RAID_ACTION_CREATE_HOT_SPARE (0x1D) -#define MPI2_RAID_ACTION_DELETE_HOT_SPARE (0x1E) -#define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED (0x20) -#define MPI2_RAID_ACTION_START_RAID_FUNCTION (0x21) -#define MPI2_RAID_ACTION_STOP_RAID_FUNCTION (0x22) -#define MPI2_RAID_ACTION_COMPATIBILITY_CHECK (0x23) -#define MPI2_RAID_ACTION_PHYSDISK_HIDDEN (0x24) -#define MPI2_RAID_ACTION_MIN_PRODUCT_SPECIFIC (0x80) -#define MPI2_RAID_ACTION_MAX_PRODUCT_SPECIFIC (0xFF) - -/*RAID Volume Creation Structure */ - -/* - *The following define can be customized for the targeted product. - */ -#ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS -#define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS (1) -#endif - -typedef struct _MPI2_RAID_VOLUME_PHYSDISK { - U8 RAIDSetNum; /*0x00 */ - U8 PhysDiskMap; /*0x01 */ - U16 PhysDiskDevHandle; /*0x02 */ -} MPI2_RAID_VOLUME_PHYSDISK, *PTR_MPI2_RAID_VOLUME_PHYSDISK, - Mpi2RaidVolumePhysDisk_t, *pMpi2RaidVolumePhysDisk_t; - -/*defines for the PhysDiskMap field */ -#define MPI2_RAIDACTION_PHYSDISK_PRIMARY (0x01) -#define MPI2_RAIDACTION_PHYSDISK_SECONDARY (0x02) - -typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT { - U8 NumPhysDisks; /*0x00 */ - U8 VolumeType; /*0x01 */ - U16 Reserved1; /*0x02 */ - U32 VolumeCreationFlags; /*0x04 */ - U32 VolumeSettings; /*0x08 */ - U8 Reserved2; /*0x0C */ - U8 ResyncRate; /*0x0D */ - U16 DataScrubDuration; /*0x0E */ - U64 VolumeMaxLBA; /*0x10 */ - U32 StripeSize; /*0x18 */ - U8 Name[16]; /*0x1C */ - MPI2_RAID_VOLUME_PHYSDISK - PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS]; /*0x2C */ -} MPI2_RAID_VOLUME_CREATION_STRUCT, - *PTR_MPI2_RAID_VOLUME_CREATION_STRUCT, - Mpi2RaidVolumeCreationStruct_t, - *pMpi2RaidVolumeCreationStruct_t; - -/*use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */ - -/*defines for the VolumeCreationFlags field */ -#define MPI2_RAID_VOL_CREATION_DEFAULT_SETTINGS (0x80000000) -#define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT (0x00000004) -#define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT (0x00000002) -#define MPI2_RAID_VOL_CREATION_MIGRATE_DATA (0x00000001) -/*The following is an obsolete define. - *It must be shifted left 24 bits in order to set the proper bit. - */ -#define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80) - -/*RAID Online Capacity Expansion Structure */ - -typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION { - U32 Flags; /*0x00 */ - U16 DevHandle0; /*0x04 */ - U16 Reserved1; /*0x06 */ - U16 DevHandle1; /*0x08 */ - U16 Reserved2; /*0x0A */ -} MPI2_RAID_ONLINE_CAPACITY_EXPANSION, - *PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION, - Mpi2RaidOnlineCapacityExpansion_t, - *pMpi2RaidOnlineCapacityExpansion_t; - -/*RAID Compatibility Input Structure */ - -typedef struct _MPI2_RAID_COMPATIBILITY_INPUT_STRUCT { - U16 SourceDevHandle; /*0x00 */ - U16 CandidateDevHandle; /*0x02 */ - U32 Flags; /*0x04 */ - U32 Reserved1; /*0x08 */ - U32 Reserved2; /*0x0C */ -} MPI2_RAID_COMPATIBILITY_INPUT_STRUCT, - *PTR_MPI2_RAID_COMPATIBILITY_INPUT_STRUCT, - Mpi2RaidCompatibilityInputStruct_t, - *pMpi2RaidCompatibilityInputStruct_t; - -/*defines for RAID Compatibility Structure Flags field */ -#define MPI2_RAID_COMPAT_SOURCE_IS_VOLUME_FLAG (0x00000002) -#define MPI2_RAID_COMPAT_REPORT_SOURCE_INFO_FLAG (0x00000001) - -/*RAID Volume Indicator Structure */ - -typedef struct _MPI2_RAID_VOL_INDICATOR { - U64 TotalBlocks; /*0x00 */ - U64 BlocksRemaining; /*0x08 */ - U32 Flags; /*0x10 */ -} MPI2_RAID_VOL_INDICATOR, *PTR_MPI2_RAID_VOL_INDICATOR, - Mpi2RaidVolIndicator_t, *pMpi2RaidVolIndicator_t; - -/*defines for RAID Volume Indicator Flags field */ -#define MPI2_RAID_VOL_FLAGS_OP_MASK (0x0000000F) -#define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT (0x00000000) -#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001) -#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK (0x00000002) -#define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003) -#define MPI2_RAID_VOL_FLAGS_OP_MDC (0x00000004) - -/*RAID Compatibility Result Structure */ - -typedef struct _MPI2_RAID_COMPATIBILITY_RESULT_STRUCT { - U8 State; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 GenericAttributes; /*0x04 */ - U32 OEMSpecificAttributes; /*0x08 */ - U32 Reserved3; /*0x0C */ - U32 Reserved4; /*0x10 */ -} MPI2_RAID_COMPATIBILITY_RESULT_STRUCT, - *PTR_MPI2_RAID_COMPATIBILITY_RESULT_STRUCT, - Mpi2RaidCompatibilityResultStruct_t, - *pMpi2RaidCompatibilityResultStruct_t; - -/*defines for RAID Compatibility Result Structure State field */ -#define MPI2_RAID_COMPAT_STATE_COMPATIBLE (0x00) -#define MPI2_RAID_COMPAT_STATE_NOT_COMPATIBLE (0x01) - -/*defines for RAID Compatibility Result Structure GenericAttributes field */ -#define MPI2_RAID_COMPAT_GENATTRIB_4K_SECTOR (0x00000010) - -#define MPI2_RAID_COMPAT_GENATTRIB_MEDIA_MASK (0x0000000C) -#define MPI2_RAID_COMPAT_GENATTRIB_SOLID_STATE_DRIVE (0x00000008) -#define MPI2_RAID_COMPAT_GENATTRIB_HARD_DISK_DRIVE (0x00000004) - -#define MPI2_RAID_COMPAT_GENATTRIB_PROTOCOL_MASK (0x00000003) -#define MPI2_RAID_COMPAT_GENATTRIB_SAS_PROTOCOL (0x00000002) -#define MPI2_RAID_COMPAT_GENATTRIB_SATA_PROTOCOL (0x00000001) - -/*RAID Action Reply ActionData union */ -typedef union _MPI2_RAID_ACTION_REPLY_DATA { - U32 Word[5]; - MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator; - U16 VolDevHandle; - U8 VolumeState; - U8 PhysDiskNum; - MPI2_RAID_COMPATIBILITY_RESULT_STRUCT RaidCompatibilityResult; -} MPI2_RAID_ACTION_REPLY_DATA, *PTR_MPI2_RAID_ACTION_REPLY_DATA, - Mpi2RaidActionReplyData_t, *pMpi2RaidActionReplyData_t; - -/*use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for - *MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */ - -/*RAID Action Reply Message */ -typedef struct _MPI2_RAID_ACTION_REPLY { - U8 Action; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 VolDevHandle; /*0x04 */ - U8 PhysDiskNum; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved2; /*0x0A */ - U16 Reserved3; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - MPI2_RAID_ACTION_REPLY_DATA ActionData; /*0x14 */ -} MPI2_RAID_ACTION_REPLY, *PTR_MPI2_RAID_ACTION_REPLY, - Mpi2RaidActionReply_t, *pMpi2RaidActionReply_t; - -#endif diff --git a/addons/mpt3sas/src/3.10.108/mpi/mpi2_sas.h b/addons/mpt3sas/src/3.10.108/mpi/mpi2_sas.h deleted file mode 100644 index b4e7084a..00000000 --- a/addons/mpt3sas/src/3.10.108/mpi/mpi2_sas.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * Copyright (c) 2000-2012 LSI Corporation. - * - * - * Name: mpi2_sas.h - * Title: MPI Serial Attached SCSI structures and definitions - * Creation Date: February 9, 2007 - * - * mpi2_sas.h Version: 02.00.07 - * - * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 - * prefix are for use only on MPI v2.5 products, and must not be used - * with MPI v2.0 products. Unless otherwise noted, names beginning with - * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 06-26-07 02.00.01 Added Clear All Persistent Operation to SAS IO Unit - * Control Request. - * 10-02-08 02.00.02 Added Set IOC Parameter Operation to SAS IO Unit Control - * Request. - * 10-28-09 02.00.03 Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST - * to MPI2_SGE_IO_UNION since it supports chained SGLs. - * 05-12-10 02.00.04 Modified some comments. - * 08-11-10 02.00.05 Added NCQ operations to SAS IO Unit Control. - * 11-18-11 02.00.06 Incorporating additions for MPI v2.5. - * 07-10-12 02.00.07 Added MPI2_SATA_PT_SGE_UNION for use in the SATA - * Passthrough Request message. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_SAS_H -#define MPI2_SAS_H - -/* - *Values for SASStatus. - */ -#define MPI2_SASSTATUS_SUCCESS (0x00) -#define MPI2_SASSTATUS_UNKNOWN_ERROR (0x01) -#define MPI2_SASSTATUS_INVALID_FRAME (0x02) -#define MPI2_SASSTATUS_UTC_BAD_DEST (0x03) -#define MPI2_SASSTATUS_UTC_BREAK_RECEIVED (0x04) -#define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05) -#define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06) -#define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07) -#define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08) -#define MPI2_SASSTATUS_UTC_WRONG_DESTINATION (0x09) -#define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A) -#define MPI2_SASSTATUS_LONG_INFORMATION_UNIT (0x0B) -#define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C) -#define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D) -#define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E) -#define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F) -#define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10) -#define MPI2_SASSTATUS_DATA_OFFSET_ERROR (0x11) -#define MPI2_SASSTATUS_SDSF_NAK_RECEIVED (0x12) -#define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED (0x13) -#define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14) - -/* - *Values for the SAS DeviceInfo field used in SAS Device Status Change Event - *data and SAS Configuration pages. - */ -#define MPI2_SAS_DEVICE_INFO_SEP (0x00004000) -#define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000) -#define MPI2_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000) -#define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800) -#define MPI2_SAS_DEVICE_INFO_SSP_TARGET (0x00000400) -#define MPI2_SAS_DEVICE_INFO_STP_TARGET (0x00000200) -#define MPI2_SAS_DEVICE_INFO_SMP_TARGET (0x00000100) -#define MPI2_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080) -#define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040) -#define MPI2_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020) -#define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010) -#define MPI2_SAS_DEVICE_INFO_SATA_HOST (0x00000008) - -#define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007) -#define MPI2_SAS_DEVICE_INFO_NO_DEVICE (0x00000000) -#define MPI2_SAS_DEVICE_INFO_END_DEVICE (0x00000001) -#define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002) -#define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003) - -/***************************************************************************** -* -* SAS Messages -* -*****************************************************************************/ - -/**************************************************************************** -* SMP Passthrough messages -****************************************************************************/ - -/*SMP Passthrough Request Message */ -typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST { - U8 PassthroughFlags; /*0x00 */ - U8 PhysicalPort; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 RequestDataLength; /*0x04 */ - U8 SGLFlags; /*0x06*//*MPI v2.0 only. Reserved on MPI v2.5*/ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U32 Reserved2; /*0x0C */ - U64 SASAddress; /*0x10 */ - U32 Reserved3; /*0x18 */ - U32 Reserved4; /*0x1C */ - MPI2_SIMPLE_SGE_UNION SGL;/*0x20 */ -} MPI2_SMP_PASSTHROUGH_REQUEST, *PTR_MPI2_SMP_PASSTHROUGH_REQUEST, - Mpi2SmpPassthroughRequest_t, *pMpi2SmpPassthroughRequest_t; - -/*values for PassthroughFlags field */ -#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80) - -/*MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ - -/*SMP Passthrough Reply Message */ -typedef struct _MPI2_SMP_PASSTHROUGH_REPLY { - U8 PassthroughFlags; /*0x00 */ - U8 PhysicalPort; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 ResponseDataLength; /*0x04 */ - U8 SGLFlags; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U8 Reserved2; /*0x0C */ - U8 SASStatus; /*0x0D */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 Reserved3; /*0x14 */ - U8 ResponseData[4]; /*0x18 */ -} MPI2_SMP_PASSTHROUGH_REPLY, *PTR_MPI2_SMP_PASSTHROUGH_REPLY, - Mpi2SmpPassthroughReply_t, *pMpi2SmpPassthroughReply_t; - -/*values for PassthroughFlags field */ -#define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80) - -/*values for SASStatus field are at the top of this file */ - -/**************************************************************************** -* SATA Passthrough messages -****************************************************************************/ - -typedef union _MPI2_SATA_PT_SGE_UNION { - MPI2_SGE_SIMPLE_UNION MpiSimple; /*MPI v2.0 only */ - MPI2_SGE_CHAIN_UNION MpiChain; /*MPI v2.0 only */ - MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; - MPI2_IEEE_SGE_CHAIN_UNION IeeeChain; /*MPI v2.0 only */ - MPI25_IEEE_SGE_CHAIN64 IeeeChain64; /*MPI v2.5 only */ -} MPI2_SATA_PT_SGE_UNION, *PTR_MPI2_SATA_PT_SGE_UNION, - Mpi2SataPTSGEUnion_t, *pMpi2SataPTSGEUnion_t; - -/*SATA Passthrough Request Message */ -typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST { - U16 DevHandle; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 PassthroughFlags; /*0x04 */ - U8 SGLFlags; /*0x06*//*MPI v2.0 only. Reserved on MPI v2.5*/ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U32 Reserved2; /*0x0C */ - U32 Reserved3; /*0x10 */ - U32 Reserved4; /*0x14 */ - U32 DataLength; /*0x18 */ - U8 CommandFIS[20]; /*0x1C */ - MPI2_SATA_PT_SGE_UNION SGL;/*0x30*//*MPI v2.5: IEEE 64 elements only*/ -} MPI2_SATA_PASSTHROUGH_REQUEST, *PTR_MPI2_SATA_PASSTHROUGH_REQUEST, - Mpi2SataPassthroughRequest_t, - *pMpi2SataPassthroughRequest_t; - -/*values for PassthroughFlags field */ -#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100) -#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA (0x0020) -#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO (0x0010) -#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004) -#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002) -#define MPI2_SATA_PT_REQ_PT_FLAGS_READ (0x0001) - -/*MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ - -/*SATA Passthrough Reply Message */ -typedef struct _MPI2_SATA_PASSTHROUGH_REPLY { - U16 DevHandle; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 PassthroughFlags; /*0x04 */ - U8 SGLFlags; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U8 Reserved2; /*0x0C */ - U8 SASStatus; /*0x0D */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U8 StatusFIS[20]; /*0x14 */ - U32 StatusControlRegisters; /*0x28 */ - U32 TransferCount; /*0x2C */ -} MPI2_SATA_PASSTHROUGH_REPLY, *PTR_MPI2_SATA_PASSTHROUGH_REPLY, - Mpi2SataPassthroughReply_t, *pMpi2SataPassthroughReply_t; - -/*values for SASStatus field are at the top of this file */ - -/**************************************************************************** -* SAS IO Unit Control messages -****************************************************************************/ - -/*SAS IO Unit Control Request Message */ -typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST { - U8 Operation; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 DevHandle; /*0x04 */ - U8 IOCParameter; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U16 Reserved4; /*0x0C */ - U8 PhyNum; /*0x0E */ - U8 PrimFlags; /*0x0F */ - U32 Primitive; /*0x10 */ - U8 LookupMethod; /*0x14 */ - U8 Reserved5; /*0x15 */ - U16 SlotNumber; /*0x16 */ - U64 LookupAddress; /*0x18 */ - U32 IOCParameterValue; /*0x20 */ - U32 Reserved7; /*0x24 */ - U32 Reserved8; /*0x28 */ -} MPI2_SAS_IOUNIT_CONTROL_REQUEST, - *PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST, - Mpi2SasIoUnitControlRequest_t, - *pMpi2SasIoUnitControlRequest_t; - -/*values for the Operation field */ -#define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT (0x02) -#define MPI2_SAS_OP_PHY_LINK_RESET (0x06) -#define MPI2_SAS_OP_PHY_HARD_RESET (0x07) -#define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08) -#define MPI2_SAS_OP_SEND_PRIMITIVE (0x0A) -#define MPI2_SAS_OP_FORCE_FULL_DISCOVERY (0x0B) -#define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C) -#define MPI2_SAS_OP_REMOVE_DEVICE (0x0D) -#define MPI2_SAS_OP_LOOKUP_MAPPING (0x0E) -#define MPI2_SAS_OP_SET_IOC_PARAMETER (0x0F) -#define MPI25_SAS_OP_ENABLE_FP_DEVICE (0x10) -#define MPI25_SAS_OP_DISABLE_FP_DEVICE (0x11) -#define MPI25_SAS_OP_ENABLE_FP_ALL (0x12) -#define MPI25_SAS_OP_DISABLE_FP_ALL (0x13) -#define MPI2_SAS_OP_DEV_ENABLE_NCQ (0x14) -#define MPI2_SAS_OP_DEV_DISABLE_NCQ (0x15) -#define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN (0x80) - -/*values for the PrimFlags field */ -#define MPI2_SAS_PRIMFLAGS_SINGLE (0x08) -#define MPI2_SAS_PRIMFLAGS_TRIPLE (0x02) -#define MPI2_SAS_PRIMFLAGS_REDUNDANT (0x01) - -/*values for the LookupMethod field */ -#define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS (0x01) -#define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT (0x02) -#define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03) - -/*SAS IO Unit Control Reply Message */ -typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY { - U8 Operation; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 DevHandle; /*0x04 */ - U8 IOCParameter; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U16 Reserved4; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_SAS_IOUNIT_CONTROL_REPLY, - *PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY, - Mpi2SasIoUnitControlReply_t, *pMpi2SasIoUnitControlReply_t; - -#endif diff --git a/addons/mpt3sas/src/3.10.108/mpi/mpi2_tool.h b/addons/mpt3sas/src/3.10.108/mpi/mpi2_tool.h deleted file mode 100644 index 71453d11..00000000 --- a/addons/mpt3sas/src/3.10.108/mpi/mpi2_tool.h +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Copyright (c) 2000-2012 LSI Corporation. - * - * - * Name: mpi2_tool.h - * Title: MPI diagnostic tool structures and definitions - * Creation Date: March 26, 2007 - * - * mpi2_tool.h Version: 02.00.09 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 12-18-07 02.00.01 Added Diagnostic Buffer Post and Diagnostic Release - * structures and defines. - * 02-29-08 02.00.02 Modified various names to make them 32-character unique. - * 05-06-09 02.00.03 Added ISTWI Read Write Tool and Diagnostic CLI Tool. - * 07-30-09 02.00.04 Added ExtendedType field to DiagnosticBufferPost request - * and reply messages. - * Added MPI2_DIAG_BUF_TYPE_EXTENDED. - * Incremented MPI2_DIAG_BUF_TYPE_COUNT. - * 05-12-10 02.00.05 Added Diagnostic Data Upload tool. - * 08-11-10 02.00.06 Added defines that were missing for Diagnostic Buffer - * Post Request. - * 05-25-11 02.00.07 Added Flags field and related defines to - * MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST. - * 11-18-11 02.00.08 Incorporating additions for MPI v2.5. - * 07-10-12 02.00.09 Add MPI v2.5 Toolbox Diagnostic CLI Tool Request - * message. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_TOOL_H -#define MPI2_TOOL_H - -/***************************************************************************** -* -* Toolbox Messages -* -*****************************************************************************/ - -/*defines for the Tools */ -#define MPI2_TOOLBOX_CLEAN_TOOL (0x00) -#define MPI2_TOOLBOX_MEMORY_MOVE_TOOL (0x01) -#define MPI2_TOOLBOX_DIAG_DATA_UPLOAD_TOOL (0x02) -#define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03) -#define MPI2_TOOLBOX_BEACON_TOOL (0x05) -#define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL (0x06) - -/**************************************************************************** -* Toolbox reply -****************************************************************************/ - -typedef struct _MPI2_TOOLBOX_REPLY { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_TOOLBOX_REPLY, *PTR_MPI2_TOOLBOX_REPLY, - Mpi2ToolboxReply_t, *pMpi2ToolboxReply_t; - -/**************************************************************************** -* Toolbox Clean Tool request -****************************************************************************/ - -typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 Flags; /*0x0C */ -} MPI2_TOOLBOX_CLEAN_REQUEST, *PTR_MPI2_TOOLBOX_CLEAN_REQUEST, - Mpi2ToolboxCleanRequest_t, *pMpi2ToolboxCleanRequest_t; - -/*values for the Flags field */ -#define MPI2_TOOLBOX_CLEAN_BOOT_SERVICES (0x80000000) -#define MPI2_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES (0x40000000) -#define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000) -#define MPI2_TOOLBOX_CLEAN_FW_CURRENT (0x10000000) -#define MPI2_TOOLBOX_CLEAN_FW_BACKUP (0x08000000) -#define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000) -#define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000) -#define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004) -#define MPI2_TOOLBOX_CLEAN_SEEPROM (0x00000002) -#define MPI2_TOOLBOX_CLEAN_NVSRAM (0x00000001) - -/**************************************************************************** -* Toolbox Memory Move request -****************************************************************************/ - -typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - MPI2_SGE_SIMPLE_UNION SGL; /*0x0C */ -} MPI2_TOOLBOX_MEM_MOVE_REQUEST, *PTR_MPI2_TOOLBOX_MEM_MOVE_REQUEST, - Mpi2ToolboxMemMoveRequest_t, *pMpi2ToolboxMemMoveRequest_t; - -/**************************************************************************** -* Toolbox Diagnostic Data Upload request -****************************************************************************/ - -typedef struct _MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U8 SGLFlags; /*0x0C */ - U8 Reserved5; /*0x0D */ - U16 Reserved6; /*0x0E */ - U32 Flags; /*0x10 */ - U32 DataLength; /*0x14 */ - MPI2_SGE_SIMPLE_UNION SGL; /*0x18 */ -} MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, - *PTR_MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, - Mpi2ToolboxDiagDataUploadRequest_t, - *pMpi2ToolboxDiagDataUploadRequest_t; - -/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ - -typedef struct _MPI2_DIAG_DATA_UPLOAD_HEADER { - U32 DiagDataLength; /*00h */ - U8 FormatCode; /*04h */ - U8 Reserved1; /*05h */ - U16 Reserved2; /*06h */ -} MPI2_DIAG_DATA_UPLOAD_HEADER, *PTR_MPI2_DIAG_DATA_UPLOAD_HEADER, - Mpi2DiagDataUploadHeader_t, *pMpi2DiagDataUploadHeader_t; - -/**************************************************************************** -* Toolbox ISTWI Read Write Tool -****************************************************************************/ - -/*Toolbox ISTWI Read Write Tool request message */ -typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 Reserved5; /*0x0C */ - U32 Reserved6; /*0x10 */ - U8 DevIndex; /*0x14 */ - U8 Action; /*0x15 */ - U8 SGLFlags; /*0x16 */ - U8 Flags; /*0x17 */ - U16 TxDataLength; /*0x18 */ - U16 RxDataLength; /*0x1A */ - U32 Reserved8; /*0x1C */ - U32 Reserved9; /*0x20 */ - U32 Reserved10; /*0x24 */ - U32 Reserved11; /*0x28 */ - U32 Reserved12; /*0x2C */ - MPI2_SGE_SIMPLE_UNION SGL; /*0x30 */ -} MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST, - *PTR_MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST, - Mpi2ToolboxIstwiReadWriteRequest_t, - *pMpi2ToolboxIstwiReadWriteRequest_t; - -/*values for the Action field */ -#define MPI2_TOOL_ISTWI_ACTION_READ_DATA (0x01) -#define MPI2_TOOL_ISTWI_ACTION_WRITE_DATA (0x02) -#define MPI2_TOOL_ISTWI_ACTION_SEQUENCE (0x03) -#define MPI2_TOOL_ISTWI_ACTION_RESERVE_BUS (0x10) -#define MPI2_TOOL_ISTWI_ACTION_RELEASE_BUS (0x11) -#define MPI2_TOOL_ISTWI_ACTION_RESET (0x12) - -/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ - -/*values for the Flags field */ -#define MPI2_TOOL_ISTWI_FLAG_AUTO_RESERVE_RELEASE (0x80) -#define MPI2_TOOL_ISTWI_FLAG_PAGE_ADDR_MASK (0x07) - -/*Toolbox ISTWI Read Write Tool reply message */ -typedef struct _MPI2_TOOLBOX_ISTWI_REPLY { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U8 DevIndex; /*0x14 */ - U8 Action; /*0x15 */ - U8 IstwiStatus; /*0x16 */ - U8 Reserved6; /*0x17 */ - U16 TxDataCount; /*0x18 */ - U16 RxDataCount; /*0x1A */ -} MPI2_TOOLBOX_ISTWI_REPLY, *PTR_MPI2_TOOLBOX_ISTWI_REPLY, - Mpi2ToolboxIstwiReply_t, *pMpi2ToolboxIstwiReply_t; - -/**************************************************************************** -* Toolbox Beacon Tool request -****************************************************************************/ - -typedef struct _MPI2_TOOLBOX_BEACON_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U8 Reserved5; /*0x0C */ - U8 PhysicalPort; /*0x0D */ - U8 Reserved6; /*0x0E */ - U8 Flags; /*0x0F */ -} MPI2_TOOLBOX_BEACON_REQUEST, *PTR_MPI2_TOOLBOX_BEACON_REQUEST, - Mpi2ToolboxBeaconRequest_t, *pMpi2ToolboxBeaconRequest_t; - -/*values for the Flags field */ -#define MPI2_TOOLBOX_FLAGS_BEACONMODE_OFF (0x00) -#define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON (0x01) - -/**************************************************************************** -* Toolbox Diagnostic CLI Tool -****************************************************************************/ - -#define MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH (0x5C) - -/*MPI v2.0 Toolbox Diagnostic CLI Tool request message */ -typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U8 SGLFlags; /*0x0C */ - U8 Reserved5; /*0x0D */ - U16 Reserved6; /*0x0E */ - U32 DataLength; /*0x10 */ - U8 DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH];/*0x14 */ - MPI2_SGE_SIMPLE_UNION SGL; /*0x70 */ -} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, - *PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, - Mpi2ToolboxDiagnosticCliRequest_t, - *pMpi2ToolboxDiagnosticCliRequest_t; - -/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ - -/*MPI v2.5 Toolbox Diagnostic CLI Tool request message */ -typedef struct _MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 Reserved5; /*0x0C */ - U32 DataLength; /*0x10 */ - U8 DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH];/*0x14 */ - MPI25_SGE_IO_UNION SGL; /*0x70 */ -} MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, - *PTR_MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, - Mpi25ToolboxDiagnosticCliRequest_t, - *pMpi25ToolboxDiagnosticCliRequest_t; - -/*Toolbox Diagnostic CLI Tool reply message */ -typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 ReturnedDataLength; /*0x14 */ -} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY, - *PTR_MPI2_TOOLBOX_DIAG_CLI_REPLY, - Mpi2ToolboxDiagnosticCliReply_t, - *pMpi2ToolboxDiagnosticCliReply_t; - -/***************************************************************************** -* -* Diagnostic Buffer Messages -* -*****************************************************************************/ - -/**************************************************************************** -* Diagnostic Buffer Post request -****************************************************************************/ - -typedef struct _MPI2_DIAG_BUFFER_POST_REQUEST { - U8 ExtendedType; /*0x00 */ - U8 BufferType; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U64 BufferAddress; /*0x0C */ - U32 BufferLength; /*0x14 */ - U32 Reserved5; /*0x18 */ - U32 Reserved6; /*0x1C */ - U32 Flags; /*0x20 */ - U32 ProductSpecific[23]; /*0x24 */ -} MPI2_DIAG_BUFFER_POST_REQUEST, *PTR_MPI2_DIAG_BUFFER_POST_REQUEST, - Mpi2DiagBufferPostRequest_t, *pMpi2DiagBufferPostRequest_t; - -/*values for the ExtendedType field */ -#define MPI2_DIAG_EXTENDED_TYPE_UTILIZATION (0x02) - -/*values for the BufferType field */ -#define MPI2_DIAG_BUF_TYPE_TRACE (0x00) -#define MPI2_DIAG_BUF_TYPE_SNAPSHOT (0x01) -#define MPI2_DIAG_BUF_TYPE_EXTENDED (0x02) -/*count of the number of buffer types */ -#define MPI2_DIAG_BUF_TYPE_COUNT (0x03) - -/*values for the Flags field */ -#define MPI2_DIAG_BUF_FLAG_RELEASE_ON_FULL (0x00000002) -#define MPI2_DIAG_BUF_FLAG_IMMEDIATE_RELEASE (0x00000001) - -/**************************************************************************** -* Diagnostic Buffer Post reply -****************************************************************************/ - -typedef struct _MPI2_DIAG_BUFFER_POST_REPLY { - U8 ExtendedType; /*0x00 */ - U8 BufferType; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 TransferLength; /*0x14 */ -} MPI2_DIAG_BUFFER_POST_REPLY, *PTR_MPI2_DIAG_BUFFER_POST_REPLY, - Mpi2DiagBufferPostReply_t, *pMpi2DiagBufferPostReply_t; - -/**************************************************************************** -* Diagnostic Release request -****************************************************************************/ - -typedef struct _MPI2_DIAG_RELEASE_REQUEST { - U8 Reserved1; /*0x00 */ - U8 BufferType; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ -} MPI2_DIAG_RELEASE_REQUEST, *PTR_MPI2_DIAG_RELEASE_REQUEST, - Mpi2DiagReleaseRequest_t, *pMpi2DiagReleaseRequest_t; - -/**************************************************************************** -* Diagnostic Buffer Post reply -****************************************************************************/ - -typedef struct _MPI2_DIAG_RELEASE_REPLY { - U8 Reserved1; /*0x00 */ - U8 BufferType; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_DIAG_RELEASE_REPLY, *PTR_MPI2_DIAG_RELEASE_REPLY, - Mpi2DiagReleaseReply_t, *pMpi2DiagReleaseReply_t; - -#endif diff --git a/addons/mpt3sas/src/3.10.108/mpi/mpi2_type.h b/addons/mpt3sas/src/3.10.108/mpi/mpi2_type.h deleted file mode 100644 index 516f9595..00000000 --- a/addons/mpt3sas/src/3.10.108/mpi/mpi2_type.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2000-2007 LSI Corporation. - * - * - * Name: mpi2_type.h - * Title: MPI basic type definitions - * Creation Date: August 16, 2006 - * - * mpi2_type.h Version: 02.00.00 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_TYPE_H -#define MPI2_TYPE_H - -/******************************************************************************* - * Define * if it hasn't already been defined. By default - * * is defined to be a near pointer. MPI2_POINTER can be defined as - * a far pointer by defining * as "far *" before this header file is - * included. - */ - -/* the basic types may have already been included by mpi_type.h */ -#ifndef MPI_TYPE_H -/***************************************************************************** -* -* Basic Types -* -*****************************************************************************/ - -typedef u8 U8; -typedef __le16 U16; -typedef __le32 U32; -typedef __le64 U64 __attribute__ ((aligned(4))); - -/***************************************************************************** -* -* Pointer Types -* -*****************************************************************************/ - -typedef U8 *PU8; -typedef U16 *PU16; -typedef U32 *PU32; -typedef U64 *PU64; - -#endif - -#endif diff --git a/addons/mpt3sas/src/3.10.108/mpt3sas_base.c b/addons/mpt3sas/src/3.10.108/mpt3sas_base.c deleted file mode 100644 index 18360032..00000000 --- a/addons/mpt3sas/src/3.10.108/mpt3sas_base.c +++ /dev/null @@ -1,4837 +0,0 @@ -/* - * This is the Fusion MPT base driver providing common API layer interface - * for access to MPT (Message Passing Technology) firmware. - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c - * Copyright (C) 2012 LSI Corporation - * (mailto:DL-MPTFusionLinux@lsi.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "mpt3sas_base.h" - -static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; - - -#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */ - - /* maximum controller queue depth */ -#define MAX_HBA_QUEUE_DEPTH 30000 -#define MAX_CHAIN_DEPTH 100000 -static int max_queue_depth = -1; -module_param(max_queue_depth, int, 0); -MODULE_PARM_DESC(max_queue_depth, " max controller queue depth "); - -static int max_sgl_entries = -1; -module_param(max_sgl_entries, int, 0); -MODULE_PARM_DESC(max_sgl_entries, " max sg entries "); - -static int msix_disable = -1; -module_param(msix_disable, int, 0); -MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)"); - - -static int mpt3sas_fwfault_debug; -MODULE_PARM_DESC(mpt3sas_fwfault_debug, - " enable detection of firmware fault and halt firmware - (default=0)"); - - -/** - * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. - * - */ -static int -_scsih_set_fwfault_debug(const char *val, struct kernel_param *kp) -{ - int ret = param_set_int(val, kp); - struct MPT3SAS_ADAPTER *ioc; - - if (ret) - return ret; - - pr_info("setting fwfault_debug(%d)\n", mpt3sas_fwfault_debug); - list_for_each_entry(ioc, &mpt3sas_ioc_list, list) - ioc->fwfault_debug = mpt3sas_fwfault_debug; - return 0; -} -module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, - param_get_int, &mpt3sas_fwfault_debug, 0644); - -/** - * mpt3sas_remove_dead_ioc_func - kthread context to remove dead ioc - * @arg: input argument, used to derive ioc - * - * Return 0 if controller is removed from pci subsystem. - * Return -1 for other case. - */ -static int mpt3sas_remove_dead_ioc_func(void *arg) -{ - struct MPT3SAS_ADAPTER *ioc = (struct MPT3SAS_ADAPTER *)arg; - struct pci_dev *pdev; - - if ((ioc == NULL)) - return -1; - - pdev = ioc->pdev; - if ((pdev == NULL)) - return -1; - pci_stop_and_remove_bus_device(pdev); - return 0; -} - -/** - * _base_fault_reset_work - workq handling ioc fault conditions - * @work: input argument, used to derive ioc - * Context: sleep. - * - * Return nothing. - */ -static void -_base_fault_reset_work(struct work_struct *work) -{ - struct MPT3SAS_ADAPTER *ioc = - container_of(work, struct MPT3SAS_ADAPTER, fault_reset_work.work); - unsigned long flags; - u32 doorbell; - int rc; - struct task_struct *p; - - - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - if (ioc->shost_recovery) - goto rearm_timer; - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); - - doorbell = mpt3sas_base_get_iocstate(ioc, 0); - if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_MASK) { - pr_err(MPT3SAS_FMT "SAS host is non-operational !!!!\n", - ioc->name); - - /* - * Call _scsih_flush_pending_cmds callback so that we flush all - * pending commands back to OS. This call is required to aovid - * deadlock at block layer. Dead IOC will fail to do diag reset, - * and this call is safe since dead ioc will never return any - * command back from HW. - */ - ioc->schedule_dead_ioc_flush_running_cmds(ioc); - /* - * Set remove_host flag early since kernel thread will - * take some time to execute. - */ - ioc->remove_host = 1; - /*Remove the Dead Host */ - p = kthread_run(mpt3sas_remove_dead_ioc_func, ioc, - "mpt3sas_dead_ioc_%d", ioc->id); - if (IS_ERR(p)) - pr_err(MPT3SAS_FMT - "%s: Running mpt3sas_dead_ioc thread failed !!!!\n", - ioc->name, __func__); - else - pr_err(MPT3SAS_FMT - "%s: Running mpt3sas_dead_ioc thread success !!!!\n", - ioc->name, __func__); - return; /* don't rearm timer */ - } - - if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) { - rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - pr_warn(MPT3SAS_FMT "%s: hard reset: %s\n", ioc->name, - __func__, (rc == 0) ? "success" : "failed"); - doorbell = mpt3sas_base_get_iocstate(ioc, 0); - if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) - mpt3sas_base_fault_info(ioc, doorbell & - MPI2_DOORBELL_DATA_MASK); - if (rc && (doorbell & MPI2_IOC_STATE_MASK) != - MPI2_IOC_STATE_OPERATIONAL) - return; /* don't rearm timer */ - } - - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - rearm_timer: - if (ioc->fault_reset_work_q) - queue_delayed_work(ioc->fault_reset_work_q, - &ioc->fault_reset_work, - msecs_to_jiffies(FAULT_POLLING_INTERVAL)); - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); -} - -/** - * mpt3sas_base_start_watchdog - start the fault_reset_work_q - * @ioc: per adapter object - * Context: sleep. - * - * Return nothing. - */ -void -mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc) -{ - unsigned long flags; - - if (ioc->fault_reset_work_q) - return; - - /* initialize fault polling */ - - INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); - snprintf(ioc->fault_reset_work_q_name, - sizeof(ioc->fault_reset_work_q_name), "poll_%d_status", ioc->id); - ioc->fault_reset_work_q = - create_singlethread_workqueue(ioc->fault_reset_work_q_name); - if (!ioc->fault_reset_work_q) { - pr_err(MPT3SAS_FMT "%s: failed (line=%d)\n", - ioc->name, __func__, __LINE__); - return; - } - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - if (ioc->fault_reset_work_q) - queue_delayed_work(ioc->fault_reset_work_q, - &ioc->fault_reset_work, - msecs_to_jiffies(FAULT_POLLING_INTERVAL)); - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); -} - -/** - * mpt3sas_base_stop_watchdog - stop the fault_reset_work_q - * @ioc: per adapter object - * Context: sleep. - * - * Return nothing. - */ -void -mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc) -{ - unsigned long flags; - struct workqueue_struct *wq; - - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - wq = ioc->fault_reset_work_q; - ioc->fault_reset_work_q = NULL; - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); - if (wq) { - if (!cancel_delayed_work(&ioc->fault_reset_work)) - flush_workqueue(wq); - destroy_workqueue(wq); - } -} - -/** - * mpt3sas_base_fault_info - verbose translation of firmware FAULT code - * @ioc: per adapter object - * @fault_code: fault code - * - * Return nothing. - */ -void -mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc , u16 fault_code) -{ - pr_err(MPT3SAS_FMT "fault_state(0x%04x)!\n", - ioc->name, fault_code); -} - -/** - * mpt3sas_halt_firmware - halt's mpt controller firmware - * @ioc: per adapter object - * - * For debugging timeout related issues. Writing 0xCOFFEE00 - * to the doorbell register will halt controller firmware. With - * the purpose to stop both driver and firmware, the enduser can - * obtain a ring buffer from controller UART. - */ -void -mpt3sas_halt_firmware(struct MPT3SAS_ADAPTER *ioc) -{ - u32 doorbell; - - if (!ioc->fwfault_debug) - return; - - dump_stack(); - - doorbell = readl(&ioc->chip->Doorbell); - if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) - mpt3sas_base_fault_info(ioc , doorbell); - else { - writel(0xC0FFEE00, &ioc->chip->Doorbell); - pr_err(MPT3SAS_FMT "Firmware is halted due to command timeout\n", - ioc->name); - } - - if (ioc->fwfault_debug == 2) - for (;;) - ; - else - panic("panic in %s\n", __func__); -} - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING -/** - * _base_sas_ioc_info - verbose translation of the ioc status - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @request_hdr: request mf - * - * Return nothing. - */ -static void -_base_sas_ioc_info(struct MPT3SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply, - MPI2RequestHeader_t *request_hdr) -{ - u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & - MPI2_IOCSTATUS_MASK; - char *desc = NULL; - u16 frame_sz; - char *func_str = NULL; - - /* SCSI_IO, RAID_PASS are handled from _scsih_scsi_ioc_info */ - if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || - request_hdr->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || - request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION) - return; - - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) - return; - - switch (ioc_status) { - -/**************************************************************************** -* Common IOCStatus values for all replies -****************************************************************************/ - - case MPI2_IOCSTATUS_INVALID_FUNCTION: - desc = "invalid function"; - break; - case MPI2_IOCSTATUS_BUSY: - desc = "busy"; - break; - case MPI2_IOCSTATUS_INVALID_SGL: - desc = "invalid sgl"; - break; - case MPI2_IOCSTATUS_INTERNAL_ERROR: - desc = "internal error"; - break; - case MPI2_IOCSTATUS_INVALID_VPID: - desc = "invalid vpid"; - break; - case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES: - desc = "insufficient resources"; - break; - case MPI2_IOCSTATUS_INVALID_FIELD: - desc = "invalid field"; - break; - case MPI2_IOCSTATUS_INVALID_STATE: - desc = "invalid state"; - break; - case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED: - desc = "op state not supported"; - break; - -/**************************************************************************** -* Config IOCStatus values -****************************************************************************/ - - case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION: - desc = "config invalid action"; - break; - case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE: - desc = "config invalid type"; - break; - case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE: - desc = "config invalid page"; - break; - case MPI2_IOCSTATUS_CONFIG_INVALID_DATA: - desc = "config invalid data"; - break; - case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS: - desc = "config no defaults"; - break; - case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT: - desc = "config cant commit"; - break; - -/**************************************************************************** -* SCSI IO Reply -****************************************************************************/ - - case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: - case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: - case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: - case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: - case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: - case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: - case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: - case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: - case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: - case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: - case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: - case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: - break; - -/**************************************************************************** -* For use by SCSI Initiator and SCSI Target end-to-end data protection -****************************************************************************/ - - case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: - desc = "eedp guard error"; - break; - case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: - desc = "eedp ref tag error"; - break; - case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: - desc = "eedp app tag error"; - break; - -/**************************************************************************** -* SCSI Target values -****************************************************************************/ - - case MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX: - desc = "target invalid io index"; - break; - case MPI2_IOCSTATUS_TARGET_ABORTED: - desc = "target aborted"; - break; - case MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: - desc = "target no conn retryable"; - break; - case MPI2_IOCSTATUS_TARGET_NO_CONNECTION: - desc = "target no connection"; - break; - case MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: - desc = "target xfer count mismatch"; - break; - case MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: - desc = "target data offset error"; - break; - case MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: - desc = "target too much write data"; - break; - case MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT: - desc = "target iu too short"; - break; - case MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: - desc = "target ack nak timeout"; - break; - case MPI2_IOCSTATUS_TARGET_NAK_RECEIVED: - desc = "target nak received"; - break; - -/**************************************************************************** -* Serial Attached SCSI values -****************************************************************************/ - - case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED: - desc = "smp request failed"; - break; - case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN: - desc = "smp data overrun"; - break; - -/**************************************************************************** -* Diagnostic Buffer Post / Diagnostic Release values -****************************************************************************/ - - case MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED: - desc = "diagnostic released"; - break; - default: - break; - } - - if (!desc) - return; - - switch (request_hdr->Function) { - case MPI2_FUNCTION_CONFIG: - frame_sz = sizeof(Mpi2ConfigRequest_t) + ioc->sge_size; - func_str = "config_page"; - break; - case MPI2_FUNCTION_SCSI_TASK_MGMT: - frame_sz = sizeof(Mpi2SCSITaskManagementRequest_t); - func_str = "task_mgmt"; - break; - case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: - frame_sz = sizeof(Mpi2SasIoUnitControlRequest_t); - func_str = "sas_iounit_ctl"; - break; - case MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR: - frame_sz = sizeof(Mpi2SepRequest_t); - func_str = "enclosure"; - break; - case MPI2_FUNCTION_IOC_INIT: - frame_sz = sizeof(Mpi2IOCInitRequest_t); - func_str = "ioc_init"; - break; - case MPI2_FUNCTION_PORT_ENABLE: - frame_sz = sizeof(Mpi2PortEnableRequest_t); - func_str = "port_enable"; - break; - case MPI2_FUNCTION_SMP_PASSTHROUGH: - frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size; - func_str = "smp_passthru"; - break; - default: - frame_sz = 32; - func_str = "unknown"; - break; - } - - pr_warn(MPT3SAS_FMT "ioc_status: %s(0x%04x), request(0x%p),(%s)\n", - ioc->name, desc, ioc_status, request_hdr, func_str); - - _debug_dump_mf(request_hdr, frame_sz/4); -} - -/** - * _base_display_event_data - verbose translation of firmware asyn events - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * - * Return nothing. - */ -static void -_base_display_event_data(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventNotificationReply_t *mpi_reply) -{ - char *desc = NULL; - u16 event; - - if (!(ioc->logging_level & MPT_DEBUG_EVENTS)) - return; - - event = le16_to_cpu(mpi_reply->Event); - - switch (event) { - case MPI2_EVENT_LOG_DATA: - desc = "Log Data"; - break; - case MPI2_EVENT_STATE_CHANGE: - desc = "Status Change"; - break; - case MPI2_EVENT_HARD_RESET_RECEIVED: - desc = "Hard Reset Received"; - break; - case MPI2_EVENT_EVENT_CHANGE: - desc = "Event Change"; - break; - case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: - desc = "Device Status Change"; - break; - case MPI2_EVENT_IR_OPERATION_STATUS: - desc = "IR Operation Status"; - break; - case MPI2_EVENT_SAS_DISCOVERY: - { - Mpi2EventDataSasDiscovery_t *event_data = - (Mpi2EventDataSasDiscovery_t *)mpi_reply->EventData; - pr_info(MPT3SAS_FMT "Discovery: (%s)", ioc->name, - (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ? - "start" : "stop"); - if (event_data->DiscoveryStatus) - pr_info("discovery_status(0x%08x)", - le32_to_cpu(event_data->DiscoveryStatus)); - pr_info("\n"); - return; - } - case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: - desc = "SAS Broadcast Primitive"; - break; - case MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: - desc = "SAS Init Device Status Change"; - break; - case MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW: - desc = "SAS Init Table Overflow"; - break; - case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: - desc = "SAS Topology Change List"; - break; - case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: - desc = "SAS Enclosure Device Status Change"; - break; - case MPI2_EVENT_IR_VOLUME: - desc = "IR Volume"; - break; - case MPI2_EVENT_IR_PHYSICAL_DISK: - desc = "IR Physical Disk"; - break; - case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: - desc = "IR Configuration Change List"; - break; - case MPI2_EVENT_LOG_ENTRY_ADDED: - desc = "Log Entry Added"; - break; - } - - if (!desc) - return; - - pr_info(MPT3SAS_FMT "%s\n", ioc->name, desc); -} -#endif - -/** - * _base_sas_log_info - verbose translation of firmware log info - * @ioc: per adapter object - * @log_info: log info - * - * Return nothing. - */ -static void -_base_sas_log_info(struct MPT3SAS_ADAPTER *ioc , u32 log_info) -{ - union loginfo_type { - u32 loginfo; - struct { - u32 subcode:16; - u32 code:8; - u32 originator:4; - u32 bus_type:4; - } dw; - }; - union loginfo_type sas_loginfo; - char *originator_str = NULL; - - sas_loginfo.loginfo = log_info; - if (sas_loginfo.dw.bus_type != 3 /*SAS*/) - return; - - /* each nexus loss loginfo */ - if (log_info == 0x31170000) - return; - - /* eat the loginfos associated with task aborts */ - if (ioc->ignore_loginfos && (log_info == 0x30050000 || log_info == - 0x31140000 || log_info == 0x31130000)) - return; - - switch (sas_loginfo.dw.originator) { - case 0: - originator_str = "IOP"; - break; - case 1: - originator_str = "PL"; - break; - case 2: - originator_str = "IR"; - break; - } - - pr_warn(MPT3SAS_FMT - "log_info(0x%08x): originator(%s), code(0x%02x), sub_code(0x%04x)\n", - ioc->name, log_info, - originator_str, sas_loginfo.dw.code, - sas_loginfo.dw.subcode); -} - -/** - * _base_display_reply_info - - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Return nothing. - */ -static void -_base_display_reply_info(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - u16 ioc_status; - u32 loginfo = 0; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (unlikely(!mpi_reply)) { - pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - ioc_status = le16_to_cpu(mpi_reply->IOCStatus); -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - if ((ioc_status & MPI2_IOCSTATUS_MASK) && - (ioc->logging_level & MPT_DEBUG_REPLY)) { - _base_sas_ioc_info(ioc , mpi_reply, - mpt3sas_base_get_msg_frame(ioc, smid)); - } -#endif - if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { - loginfo = le32_to_cpu(mpi_reply->IOCLogInfo); - _base_sas_log_info(ioc, loginfo); - } - - if (ioc_status || loginfo) { - ioc_status &= MPI2_IOCSTATUS_MASK; - mpt3sas_trigger_mpi(ioc, ioc_status, loginfo); - } -} - -/** - * mpt3sas_base_done - base internal command completion routine - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_base_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK) - return 1; - - if (ioc->base_cmds.status == MPT3_CMD_NOT_USED) - return 1; - - ioc->base_cmds.status |= MPT3_CMD_COMPLETE; - if (mpi_reply) { - ioc->base_cmds.status |= MPT3_CMD_REPLY_VALID; - memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); - } - ioc->base_cmds.status &= ~MPT3_CMD_PENDING; - - complete(&ioc->base_cmds.done); - return 1; -} - -/** - * _base_async_event - main callback handler for firmware asyn events - * @ioc: per adapter object - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply) -{ - Mpi2EventNotificationReply_t *mpi_reply; - Mpi2EventAckRequest_t *ack_request; - u16 smid; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (!mpi_reply) - return 1; - if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION) - return 1; -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - _base_display_event_data(ioc, mpi_reply); -#endif - if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED)) - goto out; - smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - goto out; - } - - ack_request = mpt3sas_base_get_msg_frame(ioc, smid); - memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t)); - ack_request->Function = MPI2_FUNCTION_EVENT_ACK; - ack_request->Event = mpi_reply->Event; - ack_request->EventContext = mpi_reply->EventContext; - ack_request->VF_ID = 0; /* TODO */ - ack_request->VP_ID = 0; - mpt3sas_base_put_smid_default(ioc, smid); - - out: - - /* scsih callback handler */ - mpt3sas_scsih_event_callback(ioc, msix_index, reply); - - /* ctl callback handler */ - mpt3sas_ctl_event_callback(ioc, msix_index, reply); - - return 1; -} - -/** - * _base_get_cb_idx - obtain the callback index - * @ioc: per adapter object - * @smid: system request message index - * - * Return callback index. - */ -static u8 -_base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - int i; - u8 cb_idx; - - if (smid < ioc->hi_priority_smid) { - i = smid - 1; - cb_idx = ioc->scsi_lookup[i].cb_idx; - } else if (smid < ioc->internal_smid) { - i = smid - ioc->hi_priority_smid; - cb_idx = ioc->hpr_lookup[i].cb_idx; - } else if (smid <= ioc->hba_queue_depth) { - i = smid - ioc->internal_smid; - cb_idx = ioc->internal_lookup[i].cb_idx; - } else - cb_idx = 0xFF; - return cb_idx; -} - -/** - * _base_mask_interrupts - disable interrupts - * @ioc: per adapter object - * - * Disabling ResetIRQ, Reply and Doorbell Interrupts - * - * Return nothing. - */ -static void -_base_mask_interrupts(struct MPT3SAS_ADAPTER *ioc) -{ - u32 him_register; - - ioc->mask_interrupts = 1; - him_register = readl(&ioc->chip->HostInterruptMask); - him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK; - writel(him_register, &ioc->chip->HostInterruptMask); - readl(&ioc->chip->HostInterruptMask); -} - -/** - * _base_unmask_interrupts - enable interrupts - * @ioc: per adapter object - * - * Enabling only Reply Interrupts - * - * Return nothing. - */ -static void -_base_unmask_interrupts(struct MPT3SAS_ADAPTER *ioc) -{ - u32 him_register; - - him_register = readl(&ioc->chip->HostInterruptMask); - him_register &= ~MPI2_HIM_RIM; - writel(him_register, &ioc->chip->HostInterruptMask); - ioc->mask_interrupts = 0; -} - -union reply_descriptor { - u64 word; - struct { - u32 low; - u32 high; - } u; -}; - -/** - * _base_interrupt - MPT adapter (IOC) specific interrupt handler. - * @irq: irq number (not used) - * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure - * @r: pt_regs pointer (not used) - * - * Return IRQ_HANDLE if processed, else IRQ_NONE. - */ -static irqreturn_t -_base_interrupt(int irq, void *bus_id) -{ - struct adapter_reply_queue *reply_q = bus_id; - union reply_descriptor rd; - u32 completed_cmds; - u8 request_desript_type; - u16 smid; - u8 cb_idx; - u32 reply; - u8 msix_index = reply_q->msix_index; - struct MPT3SAS_ADAPTER *ioc = reply_q->ioc; - Mpi2ReplyDescriptorsUnion_t *rpf; - u8 rc; - - if (ioc->mask_interrupts) - return IRQ_NONE; - - if (!atomic_add_unless(&reply_q->busy, 1, 1)) - return IRQ_NONE; - - rpf = &reply_q->reply_post_free[reply_q->reply_post_host_index]; - request_desript_type = rpf->Default.ReplyFlags - & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; - if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) { - atomic_dec(&reply_q->busy); - return IRQ_NONE; - } - - completed_cmds = 0; - cb_idx = 0xFF; - do { - rd.word = le64_to_cpu(rpf->Words); - if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX) - goto out; - reply = 0; - smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1); - if (request_desript_type == - MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS || - request_desript_type == - MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) { - cb_idx = _base_get_cb_idx(ioc, smid); - if ((likely(cb_idx < MPT_MAX_CALLBACKS)) && - (likely(mpt_callbacks[cb_idx] != NULL))) { - rc = mpt_callbacks[cb_idx](ioc, smid, - msix_index, 0); - if (rc) - mpt3sas_base_free_smid(ioc, smid); - } - } else if (request_desript_type == - MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { - reply = le32_to_cpu( - rpf->AddressReply.ReplyFrameAddress); - if (reply > ioc->reply_dma_max_address || - reply < ioc->reply_dma_min_address) - reply = 0; - if (smid) { - cb_idx = _base_get_cb_idx(ioc, smid); - if ((likely(cb_idx < MPT_MAX_CALLBACKS)) && - (likely(mpt_callbacks[cb_idx] != NULL))) { - rc = mpt_callbacks[cb_idx](ioc, smid, - msix_index, reply); - if (reply) - _base_display_reply_info(ioc, - smid, msix_index, reply); - if (rc) - mpt3sas_base_free_smid(ioc, - smid); - } - } else { - _base_async_event(ioc, msix_index, reply); - } - - /* reply free queue handling */ - if (reply) { - ioc->reply_free_host_index = - (ioc->reply_free_host_index == - (ioc->reply_free_queue_depth - 1)) ? - 0 : ioc->reply_free_host_index + 1; - ioc->reply_free[ioc->reply_free_host_index] = - cpu_to_le32(reply); - wmb(); - writel(ioc->reply_free_host_index, - &ioc->chip->ReplyFreeHostIndex); - } - } - - rpf->Words = cpu_to_le64(ULLONG_MAX); - reply_q->reply_post_host_index = - (reply_q->reply_post_host_index == - (ioc->reply_post_queue_depth - 1)) ? 0 : - reply_q->reply_post_host_index + 1; - request_desript_type = - reply_q->reply_post_free[reply_q->reply_post_host_index]. - Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; - completed_cmds++; - if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) - goto out; - if (!reply_q->reply_post_host_index) - rpf = reply_q->reply_post_free; - else - rpf++; - } while (1); - - out: - - if (!completed_cmds) { - atomic_dec(&reply_q->busy); - return IRQ_NONE; - } - - wmb(); - writel(reply_q->reply_post_host_index | (msix_index << - MPI2_RPHI_MSIX_INDEX_SHIFT), &ioc->chip->ReplyPostHostIndex); - atomic_dec(&reply_q->busy); - return IRQ_HANDLED; -} - -/** - * _base_is_controller_msix_enabled - is controller support muli-reply queues - * @ioc: per adapter object - * - */ -static inline int -_base_is_controller_msix_enabled(struct MPT3SAS_ADAPTER *ioc) -{ - return (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable; -} - -/** - * mpt3sas_base_flush_reply_queues - flushing the MSIX reply queues - * @ioc: per adapter object - * Context: ISR conext - * - * Called when a Task Management request has completed. We want - * to flush the other reply queues so all the outstanding IO has been - * completed back to OS before we process the TM completetion. - * - * Return nothing. - */ -void -mpt3sas_base_flush_reply_queues(struct MPT3SAS_ADAPTER *ioc) -{ - struct adapter_reply_queue *reply_q; - - /* If MSIX capability is turned off - * then multi-queues are not enabled - */ - if (!_base_is_controller_msix_enabled(ioc)) - return; - - list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { - if (ioc->shost_recovery) - return; - /* TMs are on msix_index == 0 */ - if (reply_q->msix_index == 0) - continue; - _base_interrupt(reply_q->vector, (void *)reply_q); - } -} - -/** - * mpt3sas_base_release_callback_handler - clear interrupt callback handler - * @cb_idx: callback index - * - * Return nothing. - */ -void -mpt3sas_base_release_callback_handler(u8 cb_idx) -{ - mpt_callbacks[cb_idx] = NULL; -} - -/** - * mpt3sas_base_register_callback_handler - obtain index for the interrupt callback handler - * @cb_func: callback function - * - * Returns cb_func. - */ -u8 -mpt3sas_base_register_callback_handler(MPT_CALLBACK cb_func) -{ - u8 cb_idx; - - for (cb_idx = MPT_MAX_CALLBACKS-1; cb_idx; cb_idx--) - if (mpt_callbacks[cb_idx] == NULL) - break; - - mpt_callbacks[cb_idx] = cb_func; - return cb_idx; -} - -/** - * mpt3sas_base_initialize_callback_handler - initialize the interrupt callback handler - * - * Return nothing. - */ -void -mpt3sas_base_initialize_callback_handler(void) -{ - u8 cb_idx; - - for (cb_idx = 0; cb_idx < MPT_MAX_CALLBACKS; cb_idx++) - mpt3sas_base_release_callback_handler(cb_idx); -} - - -/** - * _base_build_zero_len_sge - build zero length sg entry - * @ioc: per adapter object - * @paddr: virtual address for SGE - * - * Create a zero length scatter gather entry to insure the IOCs hardware has - * something to use if the target device goes brain dead and tries - * to send data even when none is asked for. - * - * Return nothing. - */ -static void -_base_build_zero_len_sge(struct MPT3SAS_ADAPTER *ioc, void *paddr) -{ - u32 flags_length = (u32)((MPI2_SGE_FLAGS_LAST_ELEMENT | - MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST | - MPI2_SGE_FLAGS_SIMPLE_ELEMENT) << - MPI2_SGE_FLAGS_SHIFT); - ioc->base_add_sg_single(paddr, flags_length, -1); -} - -/** - * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr. - * @paddr: virtual address for SGE - * @flags_length: SGE flags and data transfer length - * @dma_addr: Physical address - * - * Return nothing. - */ -static void -_base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr) -{ - Mpi2SGESimple32_t *sgel = paddr; - - flags_length |= (MPI2_SGE_FLAGS_32_BIT_ADDRESSING | - MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT; - sgel->FlagsLength = cpu_to_le32(flags_length); - sgel->Address = cpu_to_le32(dma_addr); -} - - -/** - * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr. - * @paddr: virtual address for SGE - * @flags_length: SGE flags and data transfer length - * @dma_addr: Physical address - * - * Return nothing. - */ -static void -_base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr) -{ - Mpi2SGESimple64_t *sgel = paddr; - - flags_length |= (MPI2_SGE_FLAGS_64_BIT_ADDRESSING | - MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT; - sgel->FlagsLength = cpu_to_le32(flags_length); - sgel->Address = cpu_to_le64(dma_addr); -} - -/** - * _base_get_chain_buffer_tracker - obtain chain tracker - * @ioc: per adapter object - * @smid: smid associated to an IO request - * - * Returns chain tracker(from ioc->free_chain_list) - */ -static struct chain_tracker * -_base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - struct chain_tracker *chain_req; - unsigned long flags; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - if (list_empty(&ioc->free_chain_list)) { - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "chain buffers not available\n", ioc->name)); - return NULL; - } - chain_req = list_entry(ioc->free_chain_list.next, - struct chain_tracker, tracker_list); - list_del_init(&chain_req->tracker_list); - list_add_tail(&chain_req->tracker_list, - &ioc->scsi_lookup[smid - 1].chain_list); - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return chain_req; -} - - -/** - * _base_build_sg - build generic sg - * @ioc: per adapter object - * @psge: virtual address for SGE - * @data_out_dma: physical address for WRITES - * @data_out_sz: data xfer size for WRITES - * @data_in_dma: physical address for READS - * @data_in_sz: data xfer size for READS - * - * Return nothing. - */ -static void -_base_build_sg(struct MPT3SAS_ADAPTER *ioc, void *psge, - dma_addr_t data_out_dma, size_t data_out_sz, dma_addr_t data_in_dma, - size_t data_in_sz) -{ - u32 sgl_flags; - - if (!data_out_sz && !data_in_sz) { - _base_build_zero_len_sge(ioc, psge); - return; - } - - if (data_out_sz && data_in_sz) { - /* WRITE sgel first */ - sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); - sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - ioc->base_add_sg_single(psge, sgl_flags | - data_out_sz, data_out_dma); - - /* incr sgel */ - psge += ioc->sge_size; - - /* READ sgel last */ - sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | - MPI2_SGE_FLAGS_END_OF_LIST); - sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - ioc->base_add_sg_single(psge, sgl_flags | - data_in_sz, data_in_dma); - } else if (data_out_sz) /* WRITE */ { - sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | - MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC); - sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - ioc->base_add_sg_single(psge, sgl_flags | - data_out_sz, data_out_dma); - } else if (data_in_sz) /* READ */ { - sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | - MPI2_SGE_FLAGS_END_OF_LIST); - sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - ioc->base_add_sg_single(psge, sgl_flags | - data_in_sz, data_in_dma); - } -} - -/* IEEE format sgls */ - -/** - * _base_add_sg_single_ieee - add sg element for IEEE format - * @paddr: virtual address for SGE - * @flags: SGE flags - * @chain_offset: number of 128 byte elements from start of segment - * @length: data transfer length - * @dma_addr: Physical address - * - * Return nothing. - */ -static void -_base_add_sg_single_ieee(void *paddr, u8 flags, u8 chain_offset, u32 length, - dma_addr_t dma_addr) -{ - Mpi25IeeeSgeChain64_t *sgel = paddr; - - sgel->Flags = flags; - sgel->NextChainOffset = chain_offset; - sgel->Length = cpu_to_le32(length); - sgel->Address = cpu_to_le64(dma_addr); -} - -/** - * _base_build_zero_len_sge_ieee - build zero length sg entry for IEEE format - * @ioc: per adapter object - * @paddr: virtual address for SGE - * - * Create a zero length scatter gather entry to insure the IOCs hardware has - * something to use if the target device goes brain dead and tries - * to send data even when none is asked for. - * - * Return nothing. - */ -static void -_base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr) -{ - u8 sgl_flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR | - MPI25_IEEE_SGE_FLAGS_END_OF_LIST); - _base_add_sg_single_ieee(paddr, sgl_flags, 0, 0, -1); -} - -/** - * _base_build_sg_scmd_ieee - main sg creation routine for IEEE format - * @ioc: per adapter object - * @scmd: scsi command - * @smid: system request message index - * Context: none. - * - * The main routine that builds scatter gather table from a given - * scsi request sent via the .queuecommand main handler. - * - * Returns 0 success, anything else error - */ -static int -_base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc, - struct scsi_cmnd *scmd, u16 smid) -{ - Mpi2SCSIIORequest_t *mpi_request; - dma_addr_t chain_dma; - struct scatterlist *sg_scmd; - void *sg_local, *chain; - u32 chain_offset; - u32 chain_length; - int sges_left; - u32 sges_in_segment; - u8 simple_sgl_flags; - u8 simple_sgl_flags_last; - u8 chain_sgl_flags; - struct chain_tracker *chain_req; - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - - /* init scatter gather flags */ - simple_sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR; - simple_sgl_flags_last = simple_sgl_flags | - MPI25_IEEE_SGE_FLAGS_END_OF_LIST; - chain_sgl_flags = MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT | - MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR; - - sg_scmd = scsi_sglist(scmd); - sges_left = scsi_dma_map(scmd); - if (!sges_left) { - sdev_printk(KERN_ERR, scmd->device, - "pci_map_sg failed: request for %d bytes!\n", - scsi_bufflen(scmd)); - return -ENOMEM; - } - - sg_local = &mpi_request->SGL; - sges_in_segment = (ioc->request_sz - - offsetof(Mpi2SCSIIORequest_t, SGL))/ioc->sge_size_ieee; - if (sges_left <= sges_in_segment) - goto fill_in_last_segment; - - mpi_request->ChainOffset = (sges_in_segment - 1 /* chain element */) + - (offsetof(Mpi2SCSIIORequest_t, SGL)/ioc->sge_size_ieee); - - /* fill in main message segment when there is a chain following */ - while (sges_in_segment > 1) { - _base_add_sg_single_ieee(sg_local, simple_sgl_flags, 0, - sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); - sg_scmd = sg_next(sg_scmd); - sg_local += ioc->sge_size_ieee; - sges_left--; - sges_in_segment--; - } - - /* initializing the pointers */ - chain_req = _base_get_chain_buffer_tracker(ioc, smid); - if (!chain_req) - return -1; - chain = chain_req->chain_buffer; - chain_dma = chain_req->chain_buffer_dma; - do { - sges_in_segment = (sges_left <= - ioc->max_sges_in_chain_message) ? sges_left : - ioc->max_sges_in_chain_message; - chain_offset = (sges_left == sges_in_segment) ? - 0 : sges_in_segment; - chain_length = sges_in_segment * ioc->sge_size_ieee; - if (chain_offset) - chain_length += ioc->sge_size_ieee; - _base_add_sg_single_ieee(sg_local, chain_sgl_flags, - chain_offset, chain_length, chain_dma); - - sg_local = chain; - if (!chain_offset) - goto fill_in_last_segment; - - /* fill in chain segments */ - while (sges_in_segment) { - _base_add_sg_single_ieee(sg_local, simple_sgl_flags, 0, - sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); - sg_scmd = sg_next(sg_scmd); - sg_local += ioc->sge_size_ieee; - sges_left--; - sges_in_segment--; - } - - chain_req = _base_get_chain_buffer_tracker(ioc, smid); - if (!chain_req) - return -1; - chain = chain_req->chain_buffer; - chain_dma = chain_req->chain_buffer_dma; - } while (1); - - - fill_in_last_segment: - - /* fill the last segment */ - while (sges_left) { - if (sges_left == 1) - _base_add_sg_single_ieee(sg_local, - simple_sgl_flags_last, 0, sg_dma_len(sg_scmd), - sg_dma_address(sg_scmd)); - else - _base_add_sg_single_ieee(sg_local, simple_sgl_flags, 0, - sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); - sg_scmd = sg_next(sg_scmd); - sg_local += ioc->sge_size_ieee; - sges_left--; - } - - return 0; -} - -/** - * _base_build_sg_ieee - build generic sg for IEEE format - * @ioc: per adapter object - * @psge: virtual address for SGE - * @data_out_dma: physical address for WRITES - * @data_out_sz: data xfer size for WRITES - * @data_in_dma: physical address for READS - * @data_in_sz: data xfer size for READS - * - * Return nothing. - */ -static void -_base_build_sg_ieee(struct MPT3SAS_ADAPTER *ioc, void *psge, - dma_addr_t data_out_dma, size_t data_out_sz, dma_addr_t data_in_dma, - size_t data_in_sz) -{ - u8 sgl_flags; - - if (!data_out_sz && !data_in_sz) { - _base_build_zero_len_sge_ieee(ioc, psge); - return; - } - - if (data_out_sz && data_in_sz) { - /* WRITE sgel first */ - sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR; - _base_add_sg_single_ieee(psge, sgl_flags, 0, data_out_sz, - data_out_dma); - - /* incr sgel */ - psge += ioc->sge_size_ieee; - - /* READ sgel last */ - sgl_flags |= MPI25_IEEE_SGE_FLAGS_END_OF_LIST; - _base_add_sg_single_ieee(psge, sgl_flags, 0, data_in_sz, - data_in_dma); - } else if (data_out_sz) /* WRITE */ { - sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | - MPI25_IEEE_SGE_FLAGS_END_OF_LIST | - MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR; - _base_add_sg_single_ieee(psge, sgl_flags, 0, data_out_sz, - data_out_dma); - } else if (data_in_sz) /* READ */ { - sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | - MPI25_IEEE_SGE_FLAGS_END_OF_LIST | - MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR; - _base_add_sg_single_ieee(psge, sgl_flags, 0, data_in_sz, - data_in_dma); - } -} - -#define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10)) - -/** - * _base_config_dma_addressing - set dma addressing - * @ioc: per adapter object - * @pdev: PCI device struct - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev) -{ - struct sysinfo s; - char *desc = NULL; - - if (sizeof(dma_addr_t) > 4) { - const uint64_t required_mask = - dma_get_required_mask(&pdev->dev); - if ((required_mask > DMA_BIT_MASK(32)) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && - !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { - ioc->base_add_sg_single = &_base_add_sg_single_64; - ioc->sge_size = sizeof(Mpi2SGESimple64_t); - desc = "64"; - goto out; - } - } - - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) - && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { - ioc->base_add_sg_single = &_base_add_sg_single_32; - ioc->sge_size = sizeof(Mpi2SGESimple32_t); - desc = "32"; - } else - return -ENODEV; - - out: - si_meminfo(&s); - pr_info(MPT3SAS_FMT - "%s BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n", - ioc->name, desc, convert_to_kb(s.totalram)); - - return 0; -} - -/** - * _base_check_enable_msix - checks MSIX capabable. - * @ioc: per adapter object - * - * Check to see if card is capable of MSIX, and set number - * of available msix vectors - */ -static int -_base_check_enable_msix(struct MPT3SAS_ADAPTER *ioc) -{ - int base; - u16 message_control; - - base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX); - if (!base) { - dfailprintk(ioc, pr_info(MPT3SAS_FMT "msix not supported\n", - ioc->name)); - return -EINVAL; - } - - /* get msix vector count */ - - pci_read_config_word(ioc->pdev, base + 2, &message_control); - ioc->msix_vector_count = (message_control & 0x3FF) + 1; - if (ioc->msix_vector_count > 8) - ioc->msix_vector_count = 8; - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "msix is supported, vector_count(%d)\n", - ioc->name, ioc->msix_vector_count)); - return 0; -} - -/** - * _base_free_irq - free irq - * @ioc: per adapter object - * - * Freeing respective reply_queue from the list. - */ -static void -_base_free_irq(struct MPT3SAS_ADAPTER *ioc) -{ - struct adapter_reply_queue *reply_q, *next; - - if (list_empty(&ioc->reply_queue_list)) - return; - - list_for_each_entry_safe(reply_q, next, &ioc->reply_queue_list, list) { - list_del(&reply_q->list); - synchronize_irq(reply_q->vector); - free_irq(reply_q->vector, reply_q); - kfree(reply_q); - } -} - -/** - * _base_request_irq - request irq - * @ioc: per adapter object - * @index: msix index into vector table - * @vector: irq vector - * - * Inserting respective reply_queue into the list. - */ -static int -_base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index, u32 vector) -{ - struct adapter_reply_queue *reply_q; - int r; - - reply_q = kzalloc(sizeof(struct adapter_reply_queue), GFP_KERNEL); - if (!reply_q) { - pr_err(MPT3SAS_FMT "unable to allocate memory %d!\n", - ioc->name, (int)sizeof(struct adapter_reply_queue)); - return -ENOMEM; - } - reply_q->ioc = ioc; - reply_q->msix_index = index; - reply_q->vector = vector; - atomic_set(&reply_q->busy, 0); - if (ioc->msix_enable) - snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d", - MPT3SAS_DRIVER_NAME, ioc->id, index); - else - snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d", - MPT3SAS_DRIVER_NAME, ioc->id); - r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name, - reply_q); - if (r) { - pr_err(MPT3SAS_FMT "unable to allocate interrupt %d!\n", - reply_q->name, vector); - kfree(reply_q); - return -EBUSY; - } - - INIT_LIST_HEAD(&reply_q->list); - list_add_tail(&reply_q->list, &ioc->reply_queue_list); - return 0; -} - -/** - * _base_assign_reply_queues - assigning msix index for each cpu - * @ioc: per adapter object - * - * The enduser would need to set the affinity via /proc/irq/#/smp_affinity - * - * It would nice if we could call irq_set_affinity, however it is not - * an exported symbol - */ -static void -_base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc) -{ - struct adapter_reply_queue *reply_q; - int cpu_id; - int cpu_grouping, loop, grouping, grouping_mod; - int reply_queue; - - if (!_base_is_controller_msix_enabled(ioc)) - return; - - memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz); - - /* NUMA Hardware bug workaround - drop to less reply queues */ - if (ioc->reply_queue_count > ioc->facts.MaxMSIxVectors) { - ioc->reply_queue_count = ioc->facts.MaxMSIxVectors; - reply_queue = 0; - list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { - reply_q->msix_index = reply_queue; - if (++reply_queue == ioc->reply_queue_count) - reply_queue = 0; - } - } - - /* when there are more cpus than available msix vectors, - * then group cpus togeather on same irq - */ - if (ioc->cpu_count > ioc->msix_vector_count) { - grouping = ioc->cpu_count / ioc->msix_vector_count; - grouping_mod = ioc->cpu_count % ioc->msix_vector_count; - if (grouping < 2 || (grouping == 2 && !grouping_mod)) - cpu_grouping = 2; - else if (grouping < 4 || (grouping == 4 && !grouping_mod)) - cpu_grouping = 4; - else if (grouping < 8 || (grouping == 8 && !grouping_mod)) - cpu_grouping = 8; - else - cpu_grouping = 16; - } else - cpu_grouping = 0; - - loop = 0; - reply_q = list_entry(ioc->reply_queue_list.next, - struct adapter_reply_queue, list); - for_each_online_cpu(cpu_id) { - if (!cpu_grouping) { - ioc->cpu_msix_table[cpu_id] = reply_q->msix_index; - reply_q = list_entry(reply_q->list.next, - struct adapter_reply_queue, list); - } else { - if (loop < cpu_grouping) { - ioc->cpu_msix_table[cpu_id] = - reply_q->msix_index; - loop++; - } else { - reply_q = list_entry(reply_q->list.next, - struct adapter_reply_queue, list); - ioc->cpu_msix_table[cpu_id] = - reply_q->msix_index; - loop = 1; - } - } - } -} - -/** - * _base_disable_msix - disables msix - * @ioc: per adapter object - * - */ -static void -_base_disable_msix(struct MPT3SAS_ADAPTER *ioc) -{ - if (!ioc->msix_enable) - return; - pci_disable_msix(ioc->pdev); - ioc->msix_enable = 0; -} - -/** - * _base_enable_msix - enables msix, failback to io_apic - * @ioc: per adapter object - * - */ -static int -_base_enable_msix(struct MPT3SAS_ADAPTER *ioc) -{ - struct msix_entry *entries, *a; - int r; - int i; - u8 try_msix = 0; - - INIT_LIST_HEAD(&ioc->reply_queue_list); - - if (msix_disable == -1 || msix_disable == 0) - try_msix = 1; - - if (!try_msix) - goto try_ioapic; - - if (_base_check_enable_msix(ioc) != 0) - goto try_ioapic; - - ioc->reply_queue_count = min_t(int, ioc->cpu_count, - ioc->msix_vector_count); - - entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry), - GFP_KERNEL); - if (!entries) { - dfailprintk(ioc, pr_info(MPT3SAS_FMT - "kcalloc failed @ at %s:%d/%s() !!!\n", - ioc->name, __FILE__, __LINE__, __func__)); - goto try_ioapic; - } - - for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) - a->entry = i; - - r = pci_enable_msix(ioc->pdev, entries, ioc->reply_queue_count); - if (r) { - dfailprintk(ioc, pr_info(MPT3SAS_FMT - "pci_enable_msix failed (r=%d) !!!\n", - ioc->name, r)); - kfree(entries); - goto try_ioapic; - } - - ioc->msix_enable = 1; - for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) { - r = _base_request_irq(ioc, i, a->vector); - if (r) { - _base_free_irq(ioc); - _base_disable_msix(ioc); - kfree(entries); - goto try_ioapic; - } - } - - kfree(entries); - return 0; - -/* failback to io_apic interrupt routing */ - try_ioapic: - - r = _base_request_irq(ioc, 0, ioc->pdev->irq); - - return r; -} - -/** - * mpt3sas_base_map_resources - map in controller resources (io/irq/memap) - * @ioc: per adapter object - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) -{ - struct pci_dev *pdev = ioc->pdev; - u32 memap_sz; - u32 pio_sz; - int i, r = 0; - u64 pio_chip = 0; - u64 chip_phys = 0; - struct adapter_reply_queue *reply_q; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", - ioc->name, __func__)); - - ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM); - if (pci_enable_device_mem(pdev)) { - pr_warn(MPT3SAS_FMT "pci_enable_device_mem: failed\n", - ioc->name); - return -ENODEV; - } - - - if (pci_request_selected_regions(pdev, ioc->bars, - MPT3SAS_DRIVER_NAME)) { - pr_warn(MPT3SAS_FMT "pci_request_selected_regions: failed\n", - ioc->name); - r = -ENODEV; - goto out_fail; - } - -/* AER (Advanced Error Reporting) hooks */ - pci_enable_pcie_error_reporting(pdev); - - pci_set_master(pdev); - - - if (_base_config_dma_addressing(ioc, pdev) != 0) { - pr_warn(MPT3SAS_FMT "no suitable DMA mask for %s\n", - ioc->name, pci_name(pdev)); - r = -ENODEV; - goto out_fail; - } - - for (i = 0, memap_sz = 0, pio_sz = 0 ; i < DEVICE_COUNT_RESOURCE; i++) { - if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { - if (pio_sz) - continue; - pio_chip = (u64)pci_resource_start(pdev, i); - pio_sz = pci_resource_len(pdev, i); - } else if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) { - if (memap_sz) - continue; - ioc->chip_phys = pci_resource_start(pdev, i); - chip_phys = (u64)ioc->chip_phys; - memap_sz = pci_resource_len(pdev, i); - ioc->chip = ioremap(ioc->chip_phys, memap_sz); - if (ioc->chip == NULL) { - pr_err(MPT3SAS_FMT "unable to map adapter memory!\n", - ioc->name); - r = -EINVAL; - goto out_fail; - } - } - } - - _base_mask_interrupts(ioc); - r = _base_enable_msix(ioc); - if (r) - goto out_fail; - - list_for_each_entry(reply_q, &ioc->reply_queue_list, list) - pr_info(MPT3SAS_FMT "%s: IRQ %d\n", - reply_q->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" : - "IO-APIC enabled"), reply_q->vector); - - pr_info(MPT3SAS_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n", - ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz); - pr_info(MPT3SAS_FMT "ioport(0x%016llx), size(%d)\n", - ioc->name, (unsigned long long)pio_chip, pio_sz); - - /* Save PCI configuration state for recovery from PCI AER/EEH errors */ - pci_save_state(pdev); - return 0; - - out_fail: - if (ioc->chip_phys) - iounmap(ioc->chip); - ioc->chip_phys = 0; - pci_release_selected_regions(ioc->pdev, ioc->bars); - pci_disable_pcie_error_reporting(pdev); - pci_disable_device(pdev); - return r; -} - -/** - * mpt3sas_base_get_msg_frame - obtain request mf pointer - * @ioc: per adapter object - * @smid: system request message index(smid zero is invalid) - * - * Returns virt pointer to message frame. - */ -void * -mpt3sas_base_get_msg_frame(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - return (void *)(ioc->request + (smid * ioc->request_sz)); -} - -/** - * mpt3sas_base_get_sense_buffer - obtain a sense buffer virt addr - * @ioc: per adapter object - * @smid: system request message index - * - * Returns virt pointer to sense buffer. - */ -void * -mpt3sas_base_get_sense_buffer(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - return (void *)(ioc->sense + ((smid - 1) * SCSI_SENSE_BUFFERSIZE)); -} - -/** - * mpt3sas_base_get_sense_buffer_dma - obtain a sense buffer dma addr - * @ioc: per adapter object - * @smid: system request message index - * - * Returns phys pointer to the low 32bit address of the sense buffer. - */ -__le32 -mpt3sas_base_get_sense_buffer_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - return cpu_to_le32(ioc->sense_dma + ((smid - 1) * - SCSI_SENSE_BUFFERSIZE)); -} - -/** - * mpt3sas_base_get_reply_virt_addr - obtain reply frames virt address - * @ioc: per adapter object - * @phys_addr: lower 32 physical addr of the reply - * - * Converts 32bit lower physical addr into a virt address. - */ -void * -mpt3sas_base_get_reply_virt_addr(struct MPT3SAS_ADAPTER *ioc, u32 phys_addr) -{ - if (!phys_addr) - return NULL; - return ioc->reply + (phys_addr - (u32)ioc->reply_dma); -} - -/** - * mpt3sas_base_get_smid - obtain a free smid from internal queue - * @ioc: per adapter object - * @cb_idx: callback index - * - * Returns smid (zero is invalid) - */ -u16 -mpt3sas_base_get_smid(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx) -{ - unsigned long flags; - struct request_tracker *request; - u16 smid; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - if (list_empty(&ioc->internal_free_list)) { - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - pr_err(MPT3SAS_FMT "%s: smid not available\n", - ioc->name, __func__); - return 0; - } - - request = list_entry(ioc->internal_free_list.next, - struct request_tracker, tracker_list); - request->cb_idx = cb_idx; - smid = request->smid; - list_del(&request->tracker_list); - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return smid; -} - -/** - * mpt3sas_base_get_smid_scsiio - obtain a free smid from scsiio queue - * @ioc: per adapter object - * @cb_idx: callback index - * @scmd: pointer to scsi command object - * - * Returns smid (zero is invalid) - */ -u16 -mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx, - struct scsi_cmnd *scmd) -{ - unsigned long flags; - struct scsiio_tracker *request; - u16 smid; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - if (list_empty(&ioc->free_list)) { - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - pr_err(MPT3SAS_FMT "%s: smid not available\n", - ioc->name, __func__); - return 0; - } - - request = list_entry(ioc->free_list.next, - struct scsiio_tracker, tracker_list); - request->scmd = scmd; - request->cb_idx = cb_idx; - smid = request->smid; - list_del(&request->tracker_list); - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return smid; -} - -/** - * mpt3sas_base_get_smid_hpr - obtain a free smid from hi-priority queue - * @ioc: per adapter object - * @cb_idx: callback index - * - * Returns smid (zero is invalid) - */ -u16 -mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx) -{ - unsigned long flags; - struct request_tracker *request; - u16 smid; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - if (list_empty(&ioc->hpr_free_list)) { - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return 0; - } - - request = list_entry(ioc->hpr_free_list.next, - struct request_tracker, tracker_list); - request->cb_idx = cb_idx; - smid = request->smid; - list_del(&request->tracker_list); - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return smid; -} - -/** - * mpt3sas_base_free_smid - put smid back on free_list - * @ioc: per adapter object - * @smid: system request message index - * - * Return nothing. - */ -void -mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - unsigned long flags; - int i; - struct chain_tracker *chain_req, *next; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - if (smid < ioc->hi_priority_smid) { - /* scsiio queue */ - i = smid - 1; - if (!list_empty(&ioc->scsi_lookup[i].chain_list)) { - list_for_each_entry_safe(chain_req, next, - &ioc->scsi_lookup[i].chain_list, tracker_list) { - list_del_init(&chain_req->tracker_list); - list_add(&chain_req->tracker_list, - &ioc->free_chain_list); - } - } - ioc->scsi_lookup[i].cb_idx = 0xFF; - ioc->scsi_lookup[i].scmd = NULL; - list_add(&ioc->scsi_lookup[i].tracker_list, &ioc->free_list); - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - - /* - * See _wait_for_commands_to_complete() call with regards - * to this code. - */ - if (ioc->shost_recovery && ioc->pending_io_count) { - if (ioc->pending_io_count == 1) - wake_up(&ioc->reset_wq); - ioc->pending_io_count--; - } - return; - } else if (smid < ioc->internal_smid) { - /* hi-priority */ - i = smid - ioc->hi_priority_smid; - ioc->hpr_lookup[i].cb_idx = 0xFF; - list_add(&ioc->hpr_lookup[i].tracker_list, &ioc->hpr_free_list); - } else if (smid <= ioc->hba_queue_depth) { - /* internal queue */ - i = smid - ioc->internal_smid; - ioc->internal_lookup[i].cb_idx = 0xFF; - list_add(&ioc->internal_lookup[i].tracker_list, - &ioc->internal_free_list); - } - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); -} - -/** - * _base_writeq - 64 bit write to MMIO - * @ioc: per adapter object - * @b: data payload - * @addr: address in MMIO space - * @writeq_lock: spin lock - * - * Glue for handling an atomic 64 bit word to MMIO. This special handling takes - * care of 32 bit environment where its not quarenteed to send the entire word - * in one transfer. - */ -#if defined(writeq) && defined(CONFIG_64BIT) -static inline void -_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock) -{ - writeq(cpu_to_le64(b), addr); -} -#else -static inline void -_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock) -{ - unsigned long flags; - __u64 data_out = cpu_to_le64(b); - - spin_lock_irqsave(writeq_lock, flags); - writel((u32)(data_out), addr); - writel((u32)(data_out >> 32), (addr + 4)); - spin_unlock_irqrestore(writeq_lock, flags); -} -#endif - -static inline u8 -_base_get_msix_index(struct MPT3SAS_ADAPTER *ioc) -{ - return ioc->cpu_msix_table[raw_smp_processor_id()]; -} - -/** - * mpt3sas_base_put_smid_scsi_io - send SCSI_IO request to firmware - * @ioc: per adapter object - * @smid: system request message index - * @handle: device handle - * - * Return nothing. - */ -void -mpt3sas_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) -{ - Mpi2RequestDescriptorUnion_t descriptor; - u64 *request = (u64 *)&descriptor; - - - descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; - descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc); - descriptor.SCSIIO.SMID = cpu_to_le16(smid); - descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); - descriptor.SCSIIO.LMID = 0; - _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, - &ioc->scsi_lookup_lock); -} - -/** - * mpt3sas_base_put_smid_fast_path - send fast path request to firmware - * @ioc: per adapter object - * @smid: system request message index - * @handle: device handle - * - * Return nothing. - */ -void -mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u16 handle) -{ - Mpi2RequestDescriptorUnion_t descriptor; - u64 *request = (u64 *)&descriptor; - - descriptor.SCSIIO.RequestFlags = - MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO; - descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc); - descriptor.SCSIIO.SMID = cpu_to_le16(smid); - descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); - descriptor.SCSIIO.LMID = 0; - _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, - &ioc->scsi_lookup_lock); -} - -/** - * mpt3sas_base_put_smid_hi_priority - send Task Managment request to firmware - * @ioc: per adapter object - * @smid: system request message index - * - * Return nothing. - */ -void -mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - Mpi2RequestDescriptorUnion_t descriptor; - u64 *request = (u64 *)&descriptor; - - descriptor.HighPriority.RequestFlags = - MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; - descriptor.HighPriority.MSIxIndex = 0; - descriptor.HighPriority.SMID = cpu_to_le16(smid); - descriptor.HighPriority.LMID = 0; - descriptor.HighPriority.Reserved1 = 0; - _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, - &ioc->scsi_lookup_lock); -} - -/** - * mpt3sas_base_put_smid_default - Default, primarily used for config pages - * @ioc: per adapter object - * @smid: system request message index - * - * Return nothing. - */ -void -mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - Mpi2RequestDescriptorUnion_t descriptor; - u64 *request = (u64 *)&descriptor; - - descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; - descriptor.Default.MSIxIndex = _base_get_msix_index(ioc); - descriptor.Default.SMID = cpu_to_le16(smid); - descriptor.Default.LMID = 0; - descriptor.Default.DescriptorTypeDependent = 0; - _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, - &ioc->scsi_lookup_lock); -} - - - -/** - * _base_display_ioc_capabilities - Disply IOC's capabilities. - * @ioc: per adapter object - * - * Return nothing. - */ -static void -_base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc) -{ - int i = 0; - char desc[16]; - u32 iounit_pg1_flags; - u32 bios_version; - - bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); - strncpy(desc, ioc->manu_pg0.ChipName, 16); - pr_info(MPT3SAS_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "\ - "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n", - ioc->name, desc, - (ioc->facts.FWVersion.Word & 0xFF000000) >> 24, - (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, - (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, - ioc->facts.FWVersion.Word & 0x000000FF, - ioc->pdev->revision, - (bios_version & 0xFF000000) >> 24, - (bios_version & 0x00FF0000) >> 16, - (bios_version & 0x0000FF00) >> 8, - bios_version & 0x000000FF); - - pr_info(MPT3SAS_FMT "Protocol=(", ioc->name); - - if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) { - pr_info("Initiator"); - i++; - } - - if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET) { - pr_info("%sTarget", i ? "," : ""); - i++; - } - - i = 0; - pr_info("), "); - pr_info("Capabilities=("); - - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) { - pr_info("Raid"); - i++; - } - - if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) { - pr_info("%sTLR", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_MULTICAST) { - pr_info("%sMulticast", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET) { - pr_info("%sBIDI Target", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) { - pr_info("%sEEDP", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) { - pr_info("%sSnapshot Buffer", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) { - pr_info("%sDiag Trace Buffer", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) { - pr_info("%sDiag Extended Buffer", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) { - pr_info("%sTask Set Full", i ? "," : ""); - i++; - } - - iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags); - if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) { - pr_info("%sNCQ", i ? "," : ""); - i++; - } - - pr_info(")\n"); -} - -/** - * mpt3sas_base_update_missing_delay - change the missing delay timers - * @ioc: per adapter object - * @device_missing_delay: amount of time till device is reported missing - * @io_missing_delay: interval IO is returned when there is a missing device - * - * Return nothing. - * - * Passed on the command line, this function will modify the device missing - * delay, as well as the io missing delay. This should be called at driver - * load time. - */ -void -mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc, - u16 device_missing_delay, u8 io_missing_delay) -{ - u16 dmd, dmd_new, dmd_orignal; - u8 io_missing_delay_original; - u16 sz; - Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; - Mpi2ConfigReply_t mpi_reply; - u8 num_phys = 0; - u16 ioc_status; - - mpt3sas_config_get_number_hba_phys(ioc, &num_phys); - if (!num_phys) - return; - - sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys * - sizeof(Mpi2SasIOUnit1PhyData_t)); - sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg1) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, - sas_iounit_pg1, sz))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - - /* device missing delay */ - dmd = sas_iounit_pg1->ReportDeviceMissingDelay; - if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16) - dmd = (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16; - else - dmd = dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK; - dmd_orignal = dmd; - if (device_missing_delay > 0x7F) { - dmd = (device_missing_delay > 0x7F0) ? 0x7F0 : - device_missing_delay; - dmd = dmd / 16; - dmd |= MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16; - } else - dmd = device_missing_delay; - sas_iounit_pg1->ReportDeviceMissingDelay = dmd; - - /* io missing delay */ - io_missing_delay_original = sas_iounit_pg1->IODeviceMissingDelay; - sas_iounit_pg1->IODeviceMissingDelay = io_missing_delay; - - if (!mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, - sz)) { - if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16) - dmd_new = (dmd & - MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16; - else - dmd_new = - dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK; - pr_info(MPT3SAS_FMT "device_missing_delay: old(%d), new(%d)\n", - ioc->name, dmd_orignal, dmd_new); - pr_info(MPT3SAS_FMT "ioc_missing_delay: old(%d), new(%d)\n", - ioc->name, io_missing_delay_original, - io_missing_delay); - ioc->device_missing_delay = dmd_new; - ioc->io_missing_delay = io_missing_delay; - } - -out: - kfree(sas_iounit_pg1); -} -/** - * _base_static_config_pages - static start of day config pages - * @ioc: per adapter object - * - * Return nothing. - */ -static void -_base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2ConfigReply_t mpi_reply; - u32 iounit_pg1_flags; - - mpt3sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0); - if (ioc->ir_firmware) - mpt3sas_config_get_manufacturing_pg10(ioc, &mpi_reply, - &ioc->manu_pg10); - - /* - * Ensure correct T10 PI operation if vendor left EEDPTagMode - * flag unset in NVDATA. - */ - mpt3sas_config_get_manufacturing_pg11(ioc, &mpi_reply, &ioc->manu_pg11); - if (ioc->manu_pg11.EEDPTagMode == 0) { - pr_err("%s: overriding NVDATA EEDPTagMode setting\n", - ioc->name); - ioc->manu_pg11.EEDPTagMode &= ~0x3; - ioc->manu_pg11.EEDPTagMode |= 0x1; - mpt3sas_config_set_manufacturing_pg11(ioc, &mpi_reply, - &ioc->manu_pg11); - } - - mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2); - mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3); - mpt3sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8); - mpt3sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0); - mpt3sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1); - _base_display_ioc_capabilities(ioc); - - /* - * Enable task_set_full handling in iounit_pg1 when the - * facts capabilities indicate that its supported. - */ - iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags); - if ((ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING)) - iounit_pg1_flags &= - ~MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING; - else - iounit_pg1_flags |= - MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING; - ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags); - mpt3sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1); -} - -/** - * _base_release_memory_pools - release memory - * @ioc: per adapter object - * - * Free memory allocated from _base_allocate_memory_pools. - * - * Return nothing. - */ -static void -_base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) -{ - int i; - - dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - if (ioc->request) { - pci_free_consistent(ioc->pdev, ioc->request_dma_sz, - ioc->request, ioc->request_dma); - dexitprintk(ioc, pr_info(MPT3SAS_FMT - "request_pool(0x%p): free\n", - ioc->name, ioc->request)); - ioc->request = NULL; - } - - if (ioc->sense) { - pci_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma); - if (ioc->sense_dma_pool) - pci_pool_destroy(ioc->sense_dma_pool); - dexitprintk(ioc, pr_info(MPT3SAS_FMT - "sense_pool(0x%p): free\n", - ioc->name, ioc->sense)); - ioc->sense = NULL; - } - - if (ioc->reply) { - pci_pool_free(ioc->reply_dma_pool, ioc->reply, ioc->reply_dma); - if (ioc->reply_dma_pool) - pci_pool_destroy(ioc->reply_dma_pool); - dexitprintk(ioc, pr_info(MPT3SAS_FMT - "reply_pool(0x%p): free\n", - ioc->name, ioc->reply)); - ioc->reply = NULL; - } - - if (ioc->reply_free) { - pci_pool_free(ioc->reply_free_dma_pool, ioc->reply_free, - ioc->reply_free_dma); - if (ioc->reply_free_dma_pool) - pci_pool_destroy(ioc->reply_free_dma_pool); - dexitprintk(ioc, pr_info(MPT3SAS_FMT - "reply_free_pool(0x%p): free\n", - ioc->name, ioc->reply_free)); - ioc->reply_free = NULL; - } - - if (ioc->reply_post_free) { - pci_pool_free(ioc->reply_post_free_dma_pool, - ioc->reply_post_free, ioc->reply_post_free_dma); - if (ioc->reply_post_free_dma_pool) - pci_pool_destroy(ioc->reply_post_free_dma_pool); - dexitprintk(ioc, pr_info(MPT3SAS_FMT - "reply_post_free_pool(0x%p): free\n", ioc->name, - ioc->reply_post_free)); - ioc->reply_post_free = NULL; - } - - if (ioc->config_page) { - dexitprintk(ioc, pr_info(MPT3SAS_FMT - "config_page(0x%p): free\n", ioc->name, - ioc->config_page)); - pci_free_consistent(ioc->pdev, ioc->config_page_sz, - ioc->config_page, ioc->config_page_dma); - } - - if (ioc->scsi_lookup) { - free_pages((ulong)ioc->scsi_lookup, ioc->scsi_lookup_pages); - ioc->scsi_lookup = NULL; - } - kfree(ioc->hpr_lookup); - kfree(ioc->internal_lookup); - if (ioc->chain_lookup) { - for (i = 0; i < ioc->chain_depth; i++) { - if (ioc->chain_lookup[i].chain_buffer) - pci_pool_free(ioc->chain_dma_pool, - ioc->chain_lookup[i].chain_buffer, - ioc->chain_lookup[i].chain_buffer_dma); - } - if (ioc->chain_dma_pool) - pci_pool_destroy(ioc->chain_dma_pool); - free_pages((ulong)ioc->chain_lookup, ioc->chain_pages); - ioc->chain_lookup = NULL; - } -} - -/** - * _base_allocate_memory_pools - allocate start of day memory pools - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 success, anything else error - */ -static int -_base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - struct mpt3sas_facts *facts; - u16 max_sge_elements; - u16 chains_needed_per_io; - u32 sz, total_sz, reply_post_free_sz; - u32 retry_sz; - u16 max_request_credit; - unsigned short sg_tablesize; - u16 sge_size; - int i; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - - retry_sz = 0; - facts = &ioc->facts; - - /* command line tunables for max sgl entries */ - if (max_sgl_entries != -1) - sg_tablesize = max_sgl_entries; - else - sg_tablesize = MPT3SAS_SG_DEPTH; - - if (sg_tablesize < MPT3SAS_MIN_PHYS_SEGMENTS) - sg_tablesize = MPT3SAS_MIN_PHYS_SEGMENTS; - else if (sg_tablesize > MPT3SAS_MAX_PHYS_SEGMENTS) - sg_tablesize = MPT3SAS_MAX_PHYS_SEGMENTS; - ioc->shost->sg_tablesize = sg_tablesize; - - ioc->hi_priority_depth = facts->HighPriorityCredit; - ioc->internal_depth = ioc->hi_priority_depth + (5); - /* command line tunables for max controller queue depth */ - if (max_queue_depth != -1 && max_queue_depth != 0) { - max_request_credit = min_t(u16, max_queue_depth + - ioc->hi_priority_depth + ioc->internal_depth, - facts->RequestCredit); - if (max_request_credit > MAX_HBA_QUEUE_DEPTH) - max_request_credit = MAX_HBA_QUEUE_DEPTH; - } else - max_request_credit = min_t(u16, facts->RequestCredit, - MAX_HBA_QUEUE_DEPTH); - - ioc->hba_queue_depth = max_request_credit; - - /* request frame size */ - ioc->request_sz = facts->IOCRequestFrameSize * 4; - - /* reply frame size */ - ioc->reply_sz = facts->ReplyFrameSize * 4; - - /* calculate the max scatter element size */ - sge_size = max_t(u16, ioc->sge_size, ioc->sge_size_ieee); - - retry_allocation: - total_sz = 0; - /* calculate number of sg elements left over in the 1st frame */ - max_sge_elements = ioc->request_sz - ((sizeof(Mpi2SCSIIORequest_t) - - sizeof(Mpi2SGEIOUnion_t)) + sge_size); - ioc->max_sges_in_main_message = max_sge_elements/sge_size; - - /* now do the same for a chain buffer */ - max_sge_elements = ioc->request_sz - sge_size; - ioc->max_sges_in_chain_message = max_sge_elements/sge_size; - - /* - * MPT3SAS_SG_DEPTH = CONFIG_FUSION_MAX_SGE - */ - chains_needed_per_io = ((ioc->shost->sg_tablesize - - ioc->max_sges_in_main_message)/ioc->max_sges_in_chain_message) - + 1; - if (chains_needed_per_io > facts->MaxChainDepth) { - chains_needed_per_io = facts->MaxChainDepth; - ioc->shost->sg_tablesize = min_t(u16, - ioc->max_sges_in_main_message + (ioc->max_sges_in_chain_message - * chains_needed_per_io), ioc->shost->sg_tablesize); - } - ioc->chains_needed_per_io = chains_needed_per_io; - - /* reply free queue sizing - taking into account for 64 FW events */ - ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64; - - /* calculate reply descriptor post queue depth */ - ioc->reply_post_queue_depth = ioc->hba_queue_depth + - ioc->reply_free_queue_depth + 1 ; - /* align the reply post queue on the next 16 count boundary */ - if (ioc->reply_post_queue_depth % 16) - ioc->reply_post_queue_depth += 16 - - (ioc->reply_post_queue_depth % 16); - - - if (ioc->reply_post_queue_depth > - facts->MaxReplyDescriptorPostQueueDepth) { - ioc->reply_post_queue_depth = - facts->MaxReplyDescriptorPostQueueDepth - - (facts->MaxReplyDescriptorPostQueueDepth % 16); - ioc->hba_queue_depth = - ((ioc->reply_post_queue_depth - 64) / 2) - 1; - ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64; - } - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "scatter gather: " \ - "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), " - "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message, - ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize, - ioc->chains_needed_per_io)); - - ioc->scsiio_depth = ioc->hba_queue_depth - - ioc->hi_priority_depth - ioc->internal_depth; - - /* set the scsi host can_queue depth - * with some internal commands that could be outstanding - */ - ioc->shost->can_queue = ioc->scsiio_depth; - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "scsi host: can_queue depth (%d)\n", - ioc->name, ioc->shost->can_queue)); - - - /* contiguous pool for request and chains, 16 byte align, one extra " - * "frame for smid=0 - */ - ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth; - sz = ((ioc->scsiio_depth + 1) * ioc->request_sz); - - /* hi-priority queue */ - sz += (ioc->hi_priority_depth * ioc->request_sz); - - /* internal queue */ - sz += (ioc->internal_depth * ioc->request_sz); - - ioc->request_dma_sz = sz; - ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma); - if (!ioc->request) { - pr_err(MPT3SAS_FMT "request pool: pci_alloc_consistent " \ - "failed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), " - "total(%d kB)\n", ioc->name, ioc->hba_queue_depth, - ioc->chains_needed_per_io, ioc->request_sz, sz/1024); - if (ioc->scsiio_depth < MPT3SAS_SAS_QUEUE_DEPTH) - goto out; - retry_sz += 64; - ioc->hba_queue_depth = max_request_credit - retry_sz; - goto retry_allocation; - } - - if (retry_sz) - pr_err(MPT3SAS_FMT "request pool: pci_alloc_consistent " \ - "succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), " - "total(%d kb)\n", ioc->name, ioc->hba_queue_depth, - ioc->chains_needed_per_io, ioc->request_sz, sz/1024); - - /* hi-priority queue */ - ioc->hi_priority = ioc->request + ((ioc->scsiio_depth + 1) * - ioc->request_sz); - ioc->hi_priority_dma = ioc->request_dma + ((ioc->scsiio_depth + 1) * - ioc->request_sz); - - /* internal queue */ - ioc->internal = ioc->hi_priority + (ioc->hi_priority_depth * - ioc->request_sz); - ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth * - ioc->request_sz); - - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "request pool(0x%p): depth(%d), frame_size(%d), pool_size(%d kB)\n", - ioc->name, ioc->request, ioc->hba_queue_depth, ioc->request_sz, - (ioc->hba_queue_depth * ioc->request_sz)/1024)); - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "request pool: dma(0x%llx)\n", - ioc->name, (unsigned long long) ioc->request_dma)); - total_sz += sz; - - sz = ioc->scsiio_depth * sizeof(struct scsiio_tracker); - ioc->scsi_lookup_pages = get_order(sz); - ioc->scsi_lookup = (struct scsiio_tracker *)__get_free_pages( - GFP_KERNEL, ioc->scsi_lookup_pages); - if (!ioc->scsi_lookup) { - pr_err(MPT3SAS_FMT "scsi_lookup: get_free_pages failed, sz(%d)\n", - ioc->name, (int)sz); - goto out; - } - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "scsiio(0x%p): depth(%d)\n", - ioc->name, ioc->request, ioc->scsiio_depth)); - - ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH); - sz = ioc->chain_depth * sizeof(struct chain_tracker); - ioc->chain_pages = get_order(sz); - ioc->chain_lookup = (struct chain_tracker *)__get_free_pages( - GFP_KERNEL, ioc->chain_pages); - if (!ioc->chain_lookup) { - pr_err(MPT3SAS_FMT "chain_lookup: __get_free_pages failed\n", - ioc->name); - goto out; - } - ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev, - ioc->request_sz, 16, 0); - if (!ioc->chain_dma_pool) { - pr_err(MPT3SAS_FMT "chain_dma_pool: pci_pool_create failed\n", - ioc->name); - goto out; - } - for (i = 0; i < ioc->chain_depth; i++) { - ioc->chain_lookup[i].chain_buffer = pci_pool_alloc( - ioc->chain_dma_pool , GFP_KERNEL, - &ioc->chain_lookup[i].chain_buffer_dma); - if (!ioc->chain_lookup[i].chain_buffer) { - ioc->chain_depth = i; - goto chain_done; - } - total_sz += ioc->request_sz; - } - chain_done: - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "chain pool depth(%d), frame_size(%d), pool_size(%d kB)\n", - ioc->name, ioc->chain_depth, ioc->request_sz, - ((ioc->chain_depth * ioc->request_sz))/1024)); - - /* initialize hi-priority queue smid's */ - ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth, - sizeof(struct request_tracker), GFP_KERNEL); - if (!ioc->hpr_lookup) { - pr_err(MPT3SAS_FMT "hpr_lookup: kcalloc failed\n", - ioc->name); - goto out; - } - ioc->hi_priority_smid = ioc->scsiio_depth + 1; - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "hi_priority(0x%p): depth(%d), start smid(%d)\n", - ioc->name, ioc->hi_priority, - ioc->hi_priority_depth, ioc->hi_priority_smid)); - - /* initialize internal queue smid's */ - ioc->internal_lookup = kcalloc(ioc->internal_depth, - sizeof(struct request_tracker), GFP_KERNEL); - if (!ioc->internal_lookup) { - pr_err(MPT3SAS_FMT "internal_lookup: kcalloc failed\n", - ioc->name); - goto out; - } - ioc->internal_smid = ioc->hi_priority_smid + ioc->hi_priority_depth; - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "internal(0x%p): depth(%d), start smid(%d)\n", - ioc->name, ioc->internal, - ioc->internal_depth, ioc->internal_smid)); - - /* sense buffers, 4 byte align */ - sz = ioc->scsiio_depth * SCSI_SENSE_BUFFERSIZE; - ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4, - 0); - if (!ioc->sense_dma_pool) { - pr_err(MPT3SAS_FMT "sense pool: pci_pool_create failed\n", - ioc->name); - goto out; - } - ioc->sense = pci_pool_alloc(ioc->sense_dma_pool , GFP_KERNEL, - &ioc->sense_dma); - if (!ioc->sense) { - pr_err(MPT3SAS_FMT "sense pool: pci_pool_alloc failed\n", - ioc->name); - goto out; - } - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "sense pool(0x%p): depth(%d), element_size(%d), pool_size" - "(%d kB)\n", ioc->name, ioc->sense, ioc->scsiio_depth, - SCSI_SENSE_BUFFERSIZE, sz/1024)); - dinitprintk(ioc, pr_info(MPT3SAS_FMT "sense_dma(0x%llx)\n", - ioc->name, (unsigned long long)ioc->sense_dma)); - total_sz += sz; - - /* reply pool, 4 byte align */ - sz = ioc->reply_free_queue_depth * ioc->reply_sz; - ioc->reply_dma_pool = pci_pool_create("reply pool", ioc->pdev, sz, 4, - 0); - if (!ioc->reply_dma_pool) { - pr_err(MPT3SAS_FMT "reply pool: pci_pool_create failed\n", - ioc->name); - goto out; - } - ioc->reply = pci_pool_alloc(ioc->reply_dma_pool , GFP_KERNEL, - &ioc->reply_dma); - if (!ioc->reply) { - pr_err(MPT3SAS_FMT "reply pool: pci_pool_alloc failed\n", - ioc->name); - goto out; - } - ioc->reply_dma_min_address = (u32)(ioc->reply_dma); - ioc->reply_dma_max_address = (u32)(ioc->reply_dma) + sz; - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "reply pool(0x%p): depth(%d), frame_size(%d), pool_size(%d kB)\n", - ioc->name, ioc->reply, - ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024)); - dinitprintk(ioc, pr_info(MPT3SAS_FMT "reply_dma(0x%llx)\n", - ioc->name, (unsigned long long)ioc->reply_dma)); - total_sz += sz; - - /* reply free queue, 16 byte align */ - sz = ioc->reply_free_queue_depth * 4; - ioc->reply_free_dma_pool = pci_pool_create("reply_free pool", - ioc->pdev, sz, 16, 0); - if (!ioc->reply_free_dma_pool) { - pr_err(MPT3SAS_FMT "reply_free pool: pci_pool_create failed\n", - ioc->name); - goto out; - } - ioc->reply_free = pci_pool_alloc(ioc->reply_free_dma_pool , GFP_KERNEL, - &ioc->reply_free_dma); - if (!ioc->reply_free) { - pr_err(MPT3SAS_FMT "reply_free pool: pci_pool_alloc failed\n", - ioc->name); - goto out; - } - memset(ioc->reply_free, 0, sz); - dinitprintk(ioc, pr_info(MPT3SAS_FMT "reply_free pool(0x%p): " \ - "depth(%d), element_size(%d), pool_size(%d kB)\n", ioc->name, - ioc->reply_free, ioc->reply_free_queue_depth, 4, sz/1024)); - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "reply_free_dma (0x%llx)\n", - ioc->name, (unsigned long long)ioc->reply_free_dma)); - total_sz += sz; - - /* reply post queue, 16 byte align */ - reply_post_free_sz = ioc->reply_post_queue_depth * - sizeof(Mpi2DefaultReplyDescriptor_t); - if (_base_is_controller_msix_enabled(ioc)) - sz = reply_post_free_sz * ioc->reply_queue_count; - else - sz = reply_post_free_sz; - ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool", - ioc->pdev, sz, 16, 0); - if (!ioc->reply_post_free_dma_pool) { - pr_err(MPT3SAS_FMT - "reply_post_free pool: pci_pool_create failed\n", - ioc->name); - goto out; - } - ioc->reply_post_free = pci_pool_alloc(ioc->reply_post_free_dma_pool , - GFP_KERNEL, &ioc->reply_post_free_dma); - if (!ioc->reply_post_free) { - pr_err(MPT3SAS_FMT - "reply_post_free pool: pci_pool_alloc failed\n", - ioc->name); - goto out; - } - memset(ioc->reply_post_free, 0, sz); - dinitprintk(ioc, pr_info(MPT3SAS_FMT "reply post free pool" \ - "(0x%p): depth(%d), element_size(%d), pool_size(%d kB)\n", - ioc->name, ioc->reply_post_free, ioc->reply_post_queue_depth, 8, - sz/1024)); - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "reply_post_free_dma = (0x%llx)\n", - ioc->name, (unsigned long long) - ioc->reply_post_free_dma)); - total_sz += sz; - - ioc->config_page_sz = 512; - ioc->config_page = pci_alloc_consistent(ioc->pdev, - ioc->config_page_sz, &ioc->config_page_dma); - if (!ioc->config_page) { - pr_err(MPT3SAS_FMT - "config page: pci_pool_alloc failed\n", - ioc->name); - goto out; - } - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "config page(0x%p): size(%d)\n", - ioc->name, ioc->config_page, ioc->config_page_sz)); - dinitprintk(ioc, pr_info(MPT3SAS_FMT "config_page_dma(0x%llx)\n", - ioc->name, (unsigned long long)ioc->config_page_dma)); - total_sz += ioc->config_page_sz; - - pr_info(MPT3SAS_FMT "Allocated physical memory: size(%d kB)\n", - ioc->name, total_sz/1024); - pr_info(MPT3SAS_FMT - "Current Controller Queue Depth(%d),Max Controller Queue Depth(%d)\n", - ioc->name, ioc->shost->can_queue, facts->RequestCredit); - pr_info(MPT3SAS_FMT "Scatter Gather Elements per IO(%d)\n", - ioc->name, ioc->shost->sg_tablesize); - return 0; - - out: - return -ENOMEM; -} - -/** - * mpt3sas_base_get_iocstate - Get the current state of a MPT adapter. - * @ioc: Pointer to MPT_ADAPTER structure - * @cooked: Request raw or cooked IOC state - * - * Returns all IOC Doorbell register bits if cooked==0, else just the - * Doorbell bits in MPI_IOC_STATE_MASK. - */ -u32 -mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked) -{ - u32 s, sc; - - s = readl(&ioc->chip->Doorbell); - sc = s & MPI2_IOC_STATE_MASK; - return cooked ? sc : s; -} - -/** - * _base_wait_on_iocstate - waiting on a particular ioc state - * @ioc_state: controller state { READY, OPERATIONAL, or RESET } - * @timeout: timeout in second - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout, - int sleep_flag) -{ - u32 count, cntdn; - u32 current_state; - - count = 0; - cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; - do { - current_state = mpt3sas_base_get_iocstate(ioc, 1); - if (current_state == ioc_state) - return 0; - if (count && current_state == MPI2_IOC_STATE_FAULT) - break; - if (sleep_flag == CAN_SLEEP) - usleep_range(1000, 1500); - else - udelay(500); - count++; - } while (--cntdn); - - return current_state; -} - -/** - * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by - * a write to the doorbell) - * @ioc: per adapter object - * @timeout: timeout in second - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - * - * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell. - */ -static int -_base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout, - int sleep_flag) -{ - u32 cntdn, count; - u32 int_status; - - count = 0; - cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; - do { - int_status = readl(&ioc->chip->HostInterruptStatus); - if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { - dhsprintk(ioc, pr_info(MPT3SAS_FMT - "%s: successful count(%d), timeout(%d)\n", - ioc->name, __func__, count, timeout)); - return 0; - } - if (sleep_flag == CAN_SLEEP) - usleep_range(1000, 1500); - else - udelay(500); - count++; - } while (--cntdn); - - pr_err(MPT3SAS_FMT - "%s: failed due to timeout count(%d), int_status(%x)!\n", - ioc->name, __func__, count, int_status); - return -EFAULT; -} - -/** - * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell. - * @ioc: per adapter object - * @timeout: timeout in second - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - * - * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to - * doorbell. - */ -static int -_base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout, - int sleep_flag) -{ - u32 cntdn, count; - u32 int_status; - u32 doorbell; - - count = 0; - cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; - do { - int_status = readl(&ioc->chip->HostInterruptStatus); - if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) { - dhsprintk(ioc, pr_info(MPT3SAS_FMT - "%s: successful count(%d), timeout(%d)\n", - ioc->name, __func__, count, timeout)); - return 0; - } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { - doorbell = readl(&ioc->chip->Doorbell); - if ((doorbell & MPI2_IOC_STATE_MASK) == - MPI2_IOC_STATE_FAULT) { - mpt3sas_base_fault_info(ioc , doorbell); - return -EFAULT; - } - } else if (int_status == 0xFFFFFFFF) - goto out; - - if (sleep_flag == CAN_SLEEP) - usleep_range(1000, 1500); - else - udelay(500); - count++; - } while (--cntdn); - - out: - pr_err(MPT3SAS_FMT - "%s: failed due to timeout count(%d), int_status(%x)!\n", - ioc->name, __func__, count, int_status); - return -EFAULT; -} - -/** - * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use - * @ioc: per adapter object - * @timeout: timeout in second - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - * - */ -static int -_base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout, - int sleep_flag) -{ - u32 cntdn, count; - u32 doorbell_reg; - - count = 0; - cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; - do { - doorbell_reg = readl(&ioc->chip->Doorbell); - if (!(doorbell_reg & MPI2_DOORBELL_USED)) { - dhsprintk(ioc, pr_info(MPT3SAS_FMT - "%s: successful count(%d), timeout(%d)\n", - ioc->name, __func__, count, timeout)); - return 0; - } - if (sleep_flag == CAN_SLEEP) - usleep_range(1000, 1500); - else - udelay(500); - count++; - } while (--cntdn); - - pr_err(MPT3SAS_FMT - "%s: failed due to timeout count(%d), doorbell_reg(%x)!\n", - ioc->name, __func__, count, doorbell_reg); - return -EFAULT; -} - -/** - * _base_send_ioc_reset - send doorbell reset - * @ioc: per adapter object - * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET - * @timeout: timeout in second - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout, - int sleep_flag) -{ - u32 ioc_state; - int r = 0; - - if (reset_type != MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET) { - pr_err(MPT3SAS_FMT "%s: unknown reset_type\n", - ioc->name, __func__); - return -EFAULT; - } - - if (!(ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY)) - return -EFAULT; - - pr_info(MPT3SAS_FMT "sending message unit reset !!\n", ioc->name); - - writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT, - &ioc->chip->Doorbell); - if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) { - r = -EFAULT; - goto out; - } - ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, - timeout, sleep_flag); - if (ioc_state) { - pr_err(MPT3SAS_FMT - "%s: failed going to ready state (ioc_state=0x%x)\n", - ioc->name, __func__, ioc_state); - r = -EFAULT; - goto out; - } - out: - pr_info(MPT3SAS_FMT "message unit reset: %s\n", - ioc->name, ((r == 0) ? "SUCCESS" : "FAILED")); - return r; -} - -/** - * _base_handshake_req_reply_wait - send request thru doorbell interface - * @ioc: per adapter object - * @request_bytes: request length - * @request: pointer having request payload - * @reply_bytes: reply length - * @reply: pointer to reply payload - * @timeout: timeout in second - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, - u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag) -{ - MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply; - int i; - u8 failed; - u16 dummy; - __le32 *mfp; - - /* make sure doorbell is not in use */ - if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) { - pr_err(MPT3SAS_FMT - "doorbell is in use (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - - /* clear pending doorbell interrupts from previous state changes */ - if (readl(&ioc->chip->HostInterruptStatus) & - MPI2_HIS_IOC2SYS_DB_STATUS) - writel(0, &ioc->chip->HostInterruptStatus); - - /* send message to ioc */ - writel(((MPI2_FUNCTION_HANDSHAKE<chip->Doorbell); - - if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) { - pr_err(MPT3SAS_FMT - "doorbell handshake int failed (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - writel(0, &ioc->chip->HostInterruptStatus); - - if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) { - pr_err(MPT3SAS_FMT - "doorbell handshake ack failed (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - - /* send message 32-bits at a time */ - for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) { - writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell); - if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) - failed = 1; - } - - if (failed) { - pr_err(MPT3SAS_FMT - "doorbell handshake sending request failed (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - - /* now wait for the reply */ - if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) { - pr_err(MPT3SAS_FMT - "doorbell handshake int failed (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - - /* read the first two 16-bits, it gives the total length of the reply */ - reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell) - & MPI2_DOORBELL_DATA_MASK); - writel(0, &ioc->chip->HostInterruptStatus); - if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) { - pr_err(MPT3SAS_FMT - "doorbell handshake int failed (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell) - & MPI2_DOORBELL_DATA_MASK); - writel(0, &ioc->chip->HostInterruptStatus); - - for (i = 2; i < default_reply->MsgLength * 2; i++) { - if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) { - pr_err(MPT3SAS_FMT - "doorbell handshake int failed (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - if (i >= reply_bytes/2) /* overflow case */ - dummy = readl(&ioc->chip->Doorbell); - else - reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell) - & MPI2_DOORBELL_DATA_MASK); - writel(0, &ioc->chip->HostInterruptStatus); - } - - _base_wait_for_doorbell_int(ioc, 5, sleep_flag); - if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) { - dhsprintk(ioc, pr_info(MPT3SAS_FMT - "doorbell is in use (line=%d)\n", ioc->name, __LINE__)); - } - writel(0, &ioc->chip->HostInterruptStatus); - - if (ioc->logging_level & MPT_DEBUG_INIT) { - mfp = (__le32 *)reply; - pr_info("\toffset:data\n"); - for (i = 0; i < reply_bytes/4; i++) - pr_info("\t[0x%02x]:%08x\n", i*4, - le32_to_cpu(mfp[i])); - } - return 0; -} - -/** - * mpt3sas_base_sas_iounit_control - send sas iounit control to FW - * @ioc: per adapter object - * @mpi_reply: the reply payload from FW - * @mpi_request: the request payload sent to FW - * - * The SAS IO Unit Control Request message allows the host to perform low-level - * operations, such as resets on the PHYs of the IO Unit, also allows the host - * to obtain the IOC assigned device handles for a device if it has other - * identifying information about the device, in addition allows the host to - * remove IOC resources associated with the device. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc, - Mpi2SasIoUnitControlReply_t *mpi_reply, - Mpi2SasIoUnitControlRequest_t *mpi_request) -{ - u16 smid; - u32 ioc_state; - unsigned long timeleft; - u8 issue_reset; - int rc; - void *request; - u16 wait_state_count; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - mutex_lock(&ioc->base_cmds.mutex); - - if (ioc->base_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: base_cmd in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, __func__, wait_state_count); - } - - smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - rc = 0; - ioc->base_cmds.status = MPT3_CMD_PENDING; - request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->base_cmds.smid = smid; - memcpy(request, mpi_request, sizeof(Mpi2SasIoUnitControlRequest_t)); - if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || - mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) - ioc->ioc_link_reset_in_progress = 1; - init_completion(&ioc->base_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, - msecs_to_jiffies(10000)); - if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || - mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) && - ioc->ioc_link_reset_in_progress) - ioc->ioc_link_reset_in_progress = 0; - if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SasIoUnitControlRequest_t)/4); - if (!(ioc->base_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - if (ioc->base_cmds.status & MPT3_CMD_REPLY_VALID) - memcpy(mpi_reply, ioc->base_cmds.reply, - sizeof(Mpi2SasIoUnitControlReply_t)); - else - memset(mpi_reply, 0, sizeof(Mpi2SasIoUnitControlReply_t)); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - goto out; - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - rc = -EFAULT; - out: - mutex_unlock(&ioc->base_cmds.mutex); - return rc; -} - -/** - * mpt3sas_base_scsi_enclosure_processor - sending request to sep device - * @ioc: per adapter object - * @mpi_reply: the reply payload from FW - * @mpi_request: the request payload sent to FW - * - * The SCSI Enclosure Processor request message causes the IOC to - * communicate with SES devices to control LED status signals. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, - Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request) -{ - u16 smid; - u32 ioc_state; - unsigned long timeleft; - u8 issue_reset; - int rc; - void *request; - u16 wait_state_count; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - mutex_lock(&ioc->base_cmds.mutex); - - if (ioc->base_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: base_cmd in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, - __func__, wait_state_count); - } - - smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - rc = 0; - ioc->base_cmds.status = MPT3_CMD_PENDING; - request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->base_cmds.smid = smid; - memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); - init_completion(&ioc->base_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, - msecs_to_jiffies(10000)); - if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SepRequest_t)/4); - if (!(ioc->base_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - if (ioc->base_cmds.status & MPT3_CMD_REPLY_VALID) - memcpy(mpi_reply, ioc->base_cmds.reply, - sizeof(Mpi2SepReply_t)); - else - memset(mpi_reply, 0, sizeof(Mpi2SepReply_t)); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - goto out; - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - rc = -EFAULT; - out: - mutex_unlock(&ioc->base_cmds.mutex); - return rc; -} - -/** - * _base_get_port_facts - obtain port facts reply and save in ioc - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_get_port_facts(struct MPT3SAS_ADAPTER *ioc, int port, int sleep_flag) -{ - Mpi2PortFactsRequest_t mpi_request; - Mpi2PortFactsReply_t mpi_reply; - struct mpt3sas_port_facts *pfacts; - int mpi_reply_sz, mpi_request_sz, r; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - mpi_reply_sz = sizeof(Mpi2PortFactsReply_t); - mpi_request_sz = sizeof(Mpi2PortFactsRequest_t); - memset(&mpi_request, 0, mpi_request_sz); - mpi_request.Function = MPI2_FUNCTION_PORT_FACTS; - mpi_request.PortNumber = port; - r = _base_handshake_req_reply_wait(ioc, mpi_request_sz, - (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP); - - if (r != 0) { - pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", - ioc->name, __func__, r); - return r; - } - - pfacts = &ioc->pfacts[port]; - memset(pfacts, 0, sizeof(struct mpt3sas_port_facts)); - pfacts->PortNumber = mpi_reply.PortNumber; - pfacts->VP_ID = mpi_reply.VP_ID; - pfacts->VF_ID = mpi_reply.VF_ID; - pfacts->MaxPostedCmdBuffers = - le16_to_cpu(mpi_reply.MaxPostedCmdBuffers); - - return 0; -} - -/** - * _base_get_ioc_facts - obtain ioc facts reply and save in ioc - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - Mpi2IOCFactsRequest_t mpi_request; - Mpi2IOCFactsReply_t mpi_reply; - struct mpt3sas_facts *facts; - int mpi_reply_sz, mpi_request_sz, r; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t); - mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t); - memset(&mpi_request, 0, mpi_request_sz); - mpi_request.Function = MPI2_FUNCTION_IOC_FACTS; - r = _base_handshake_req_reply_wait(ioc, mpi_request_sz, - (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP); - - if (r != 0) { - pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", - ioc->name, __func__, r); - return r; - } - - facts = &ioc->facts; - memset(facts, 0, sizeof(struct mpt3sas_facts)); - facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion); - facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion); - facts->VP_ID = mpi_reply.VP_ID; - facts->VF_ID = mpi_reply.VF_ID; - facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions); - facts->MaxChainDepth = mpi_reply.MaxChainDepth; - facts->WhoInit = mpi_reply.WhoInit; - facts->NumberOfPorts = mpi_reply.NumberOfPorts; - facts->MaxMSIxVectors = mpi_reply.MaxMSIxVectors; - facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit); - facts->MaxReplyDescriptorPostQueueDepth = - le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth); - facts->ProductID = le16_to_cpu(mpi_reply.ProductID); - facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities); - if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID)) - ioc->ir_firmware = 1; - facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word); - facts->IOCRequestFrameSize = - le16_to_cpu(mpi_reply.IOCRequestFrameSize); - facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators); - facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets); - ioc->shost->max_id = -1; - facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders); - facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures); - facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags); - facts->HighPriorityCredit = - le16_to_cpu(mpi_reply.HighPriorityCredit); - facts->ReplyFrameSize = mpi_reply.ReplyFrameSize; - facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle); - - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "hba queue depth(%d), max chains per io(%d)\n", - ioc->name, facts->RequestCredit, - facts->MaxChainDepth)); - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "request frame size(%d), reply frame size(%d)\n", ioc->name, - facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4)); - return 0; -} - -/** - * _base_send_ioc_init - send ioc_init to firmware - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - Mpi2IOCInitRequest_t mpi_request; - Mpi2IOCInitReply_t mpi_reply; - int r; - struct timeval current_time; - u16 ioc_status; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t)); - mpi_request.Function = MPI2_FUNCTION_IOC_INIT; - mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER; - mpi_request.VF_ID = 0; /* TODO */ - mpi_request.VP_ID = 0; - mpi_request.MsgVersion = cpu_to_le16(MPI2_VERSION); - mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); - - if (_base_is_controller_msix_enabled(ioc)) - mpi_request.HostMSIxVectors = ioc->reply_queue_count; - mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4); - mpi_request.ReplyDescriptorPostQueueDepth = - cpu_to_le16(ioc->reply_post_queue_depth); - mpi_request.ReplyFreeQueueDepth = - cpu_to_le16(ioc->reply_free_queue_depth); - - mpi_request.SenseBufferAddressHigh = - cpu_to_le32((u64)ioc->sense_dma >> 32); - mpi_request.SystemReplyAddressHigh = - cpu_to_le32((u64)ioc->reply_dma >> 32); - mpi_request.SystemRequestFrameBaseAddress = - cpu_to_le64((u64)ioc->request_dma); - mpi_request.ReplyFreeQueueAddress = - cpu_to_le64((u64)ioc->reply_free_dma); - mpi_request.ReplyDescriptorPostQueueAddress = - cpu_to_le64((u64)ioc->reply_post_free_dma); - - - /* This time stamp specifies number of milliseconds - * since epoch ~ midnight January 1, 1970. - */ - do_gettimeofday(¤t_time); - mpi_request.TimeStamp = cpu_to_le64((u64)current_time.tv_sec * 1000 + - (current_time.tv_usec / 1000)); - - if (ioc->logging_level & MPT_DEBUG_INIT) { - __le32 *mfp; - int i; - - mfp = (__le32 *)&mpi_request; - pr_info("\toffset:data\n"); - for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++) - pr_info("\t[0x%02x]:%08x\n", i*4, - le32_to_cpu(mfp[i])); - } - - r = _base_handshake_req_reply_wait(ioc, - sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request, - sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10, - sleep_flag); - - if (r != 0) { - pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", - ioc->name, __func__, r); - return r; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS || - mpi_reply.IOCLogInfo) { - pr_err(MPT3SAS_FMT "%s: failed\n", ioc->name, __func__); - r = -EIO; - } - - return 0; -} - -/** - * mpt3sas_port_enable_done - command completion routine for port enable - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_port_enable_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - u16 ioc_status; - - if (ioc->port_enable_cmds.status == MPT3_CMD_NOT_USED) - return 1; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (!mpi_reply) - return 1; - - if (mpi_reply->Function != MPI2_FUNCTION_PORT_ENABLE) - return 1; - - ioc->port_enable_cmds.status &= ~MPT3_CMD_PENDING; - ioc->port_enable_cmds.status |= MPT3_CMD_COMPLETE; - ioc->port_enable_cmds.status |= MPT3_CMD_REPLY_VALID; - memcpy(ioc->port_enable_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - ioc->port_enable_failed = 1; - - if (ioc->is_driver_loading) { - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { - mpt3sas_port_enable_complete(ioc); - return 1; - } else { - ioc->start_scan_failed = ioc_status; - ioc->start_scan = 0; - return 1; - } - } - complete(&ioc->port_enable_cmds.done); - return 1; -} - -/** - * _base_send_port_enable - send port_enable(discovery stuff) to firmware - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_send_port_enable(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - Mpi2PortEnableRequest_t *mpi_request; - Mpi2PortEnableReply_t *mpi_reply; - unsigned long timeleft; - int r = 0; - u16 smid; - u16 ioc_status; - - pr_info(MPT3SAS_FMT "sending port enable !!\n", ioc->name); - - if (ioc->port_enable_cmds.status & MPT3_CMD_PENDING) { - pr_err(MPT3SAS_FMT "%s: internal command already in use\n", - ioc->name, __func__); - return -EAGAIN; - } - - smid = mpt3sas_base_get_smid(ioc, ioc->port_enable_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - return -EAGAIN; - } - - ioc->port_enable_cmds.status = MPT3_CMD_PENDING; - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->port_enable_cmds.smid = smid; - memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); - mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; - - init_completion(&ioc->port_enable_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->port_enable_cmds.done, - 300*HZ); - if (!(ioc->port_enable_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2PortEnableRequest_t)/4); - if (ioc->port_enable_cmds.status & MPT3_CMD_RESET) - r = -EFAULT; - else - r = -ETIME; - goto out; - } - - mpi_reply = ioc->port_enable_cmds.reply; - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "%s: failed with (ioc_status=0x%08x)\n", - ioc->name, __func__, ioc_status); - r = -EFAULT; - goto out; - } - - out: - ioc->port_enable_cmds.status = MPT3_CMD_NOT_USED; - pr_info(MPT3SAS_FMT "port enable: %s\n", ioc->name, ((r == 0) ? - "SUCCESS" : "FAILED")); - return r; -} - -/** - * mpt3sas_port_enable - initiate firmware discovery (don't wait for reply) - * @ioc: per adapter object - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2PortEnableRequest_t *mpi_request; - u16 smid; - - pr_info(MPT3SAS_FMT "sending port enable !!\n", ioc->name); - - if (ioc->port_enable_cmds.status & MPT3_CMD_PENDING) { - pr_err(MPT3SAS_FMT "%s: internal command already in use\n", - ioc->name, __func__); - return -EAGAIN; - } - - smid = mpt3sas_base_get_smid(ioc, ioc->port_enable_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - return -EAGAIN; - } - - ioc->port_enable_cmds.status = MPT3_CMD_PENDING; - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->port_enable_cmds.smid = smid; - memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); - mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; - - mpt3sas_base_put_smid_default(ioc, smid); - return 0; -} - -/** - * _base_determine_wait_on_discovery - desposition - * @ioc: per adapter object - * - * Decide whether to wait on discovery to complete. Used to either - * locate boot device, or report volumes ahead of physical devices. - * - * Returns 1 for wait, 0 for don't wait - */ -static int -_base_determine_wait_on_discovery(struct MPT3SAS_ADAPTER *ioc) -{ - /* We wait for discovery to complete if IR firmware is loaded. - * The sas topology events arrive before PD events, so we need time to - * turn on the bit in ioc->pd_handles to indicate PD - * Also, it maybe required to report Volumes ahead of physical - * devices when MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING is set. - */ - if (ioc->ir_firmware) - return 1; - - /* if no Bios, then we don't need to wait */ - if (!ioc->bios_pg3.BiosVersion) - return 0; - - /* Bios is present, then we drop down here. - * - * If there any entries in the Bios Page 2, then we wait - * for discovery to complete. - */ - - /* Current Boot Device */ - if ((ioc->bios_pg2.CurrentBootDeviceForm & - MPI2_BIOSPAGE2_FORM_MASK) == - MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED && - /* Request Boot Device */ - (ioc->bios_pg2.ReqBootDeviceForm & - MPI2_BIOSPAGE2_FORM_MASK) == - MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED && - /* Alternate Request Boot Device */ - (ioc->bios_pg2.ReqAltBootDeviceForm & - MPI2_BIOSPAGE2_FORM_MASK) == - MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED) - return 0; - - return 1; -} - -/** - * _base_unmask_events - turn on notification for this event - * @ioc: per adapter object - * @event: firmware event - * - * The mask is stored in ioc->event_masks. - */ -static void -_base_unmask_events(struct MPT3SAS_ADAPTER *ioc, u16 event) -{ - u32 desired_event; - - if (event >= 128) - return; - - desired_event = (1 << (event % 32)); - - if (event < 32) - ioc->event_masks[0] &= ~desired_event; - else if (event < 64) - ioc->event_masks[1] &= ~desired_event; - else if (event < 96) - ioc->event_masks[2] &= ~desired_event; - else if (event < 128) - ioc->event_masks[3] &= ~desired_event; -} - -/** - * _base_event_notification - send event notification - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_event_notification(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - Mpi2EventNotificationRequest_t *mpi_request; - unsigned long timeleft; - u16 smid; - int r = 0; - int i; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - if (ioc->base_cmds.status & MPT3_CMD_PENDING) { - pr_err(MPT3SAS_FMT "%s: internal command already in use\n", - ioc->name, __func__); - return -EAGAIN; - } - - smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - return -EAGAIN; - } - ioc->base_cmds.status = MPT3_CMD_PENDING; - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->base_cmds.smid = smid; - memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t)); - mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) - mpi_request->EventMasks[i] = - cpu_to_le32(ioc->event_masks[i]); - init_completion(&ioc->base_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); - if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2EventNotificationRequest_t)/4); - if (ioc->base_cmds.status & MPT3_CMD_RESET) - r = -EFAULT; - else - r = -ETIME; - } else - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s: complete\n", - ioc->name, __func__)); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - return r; -} - -/** - * mpt3sas_base_validate_event_type - validating event types - * @ioc: per adapter object - * @event: firmware event - * - * This will turn on firmware event notification when application - * ask for that event. We don't mask events that are already enabled. - */ -void -mpt3sas_base_validate_event_type(struct MPT3SAS_ADAPTER *ioc, u32 *event_type) -{ - int i, j; - u32 event_mask, desired_event; - u8 send_update_to_fw; - - for (i = 0, send_update_to_fw = 0; i < - MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) { - event_mask = ~event_type[i]; - desired_event = 1; - for (j = 0; j < 32; j++) { - if (!(event_mask & desired_event) && - (ioc->event_masks[i] & desired_event)) { - ioc->event_masks[i] &= ~desired_event; - send_update_to_fw = 1; - } - desired_event = (desired_event << 1); - } - } - - if (!send_update_to_fw) - return; - - mutex_lock(&ioc->base_cmds.mutex); - _base_event_notification(ioc, CAN_SLEEP); - mutex_unlock(&ioc->base_cmds.mutex); -} - -/** - * _base_diag_reset - the "big hammer" start of day reset - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - u32 host_diagnostic; - u32 ioc_state; - u32 count; - u32 hcb_size; - - pr_info(MPT3SAS_FMT "sending diag reset !!\n", ioc->name); - - drsprintk(ioc, pr_info(MPT3SAS_FMT "clear interrupts\n", - ioc->name)); - - count = 0; - do { - /* Write magic sequence to WriteSequence register - * Loop until in diagnostic mode - */ - drsprintk(ioc, pr_info(MPT3SAS_FMT - "write magic sequence\n", ioc->name)); - writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence); - writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence); - writel(MPI2_WRSEQ_2ND_KEY_VALUE, &ioc->chip->WriteSequence); - writel(MPI2_WRSEQ_3RD_KEY_VALUE, &ioc->chip->WriteSequence); - writel(MPI2_WRSEQ_4TH_KEY_VALUE, &ioc->chip->WriteSequence); - writel(MPI2_WRSEQ_5TH_KEY_VALUE, &ioc->chip->WriteSequence); - writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence); - - /* wait 100 msec */ - if (sleep_flag == CAN_SLEEP) - msleep(100); - else - mdelay(100); - - if (count++ > 20) - goto out; - - host_diagnostic = readl(&ioc->chip->HostDiagnostic); - drsprintk(ioc, pr_info(MPT3SAS_FMT - "wrote magic sequence: count(%d), host_diagnostic(0x%08x)\n", - ioc->name, count, host_diagnostic)); - - } while ((host_diagnostic & MPI2_DIAG_DIAG_WRITE_ENABLE) == 0); - - hcb_size = readl(&ioc->chip->HCBSize); - - drsprintk(ioc, pr_info(MPT3SAS_FMT "diag reset: issued\n", - ioc->name)); - writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER, - &ioc->chip->HostDiagnostic); - - /* don't access any registers for 50 milliseconds */ - msleep(50); - - /* 300 second max wait */ - for (count = 0; count < 3000000 ; count++) { - - host_diagnostic = readl(&ioc->chip->HostDiagnostic); - - if (host_diagnostic == 0xFFFFFFFF) - goto out; - if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER)) - break; - - /* wait 1 msec */ - if (sleep_flag == CAN_SLEEP) - usleep_range(1000, 1500); - else - mdelay(1); - } - - if (host_diagnostic & MPI2_DIAG_HCB_MODE) { - - drsprintk(ioc, pr_info(MPT3SAS_FMT - "restart the adapter assuming the HCB Address points to good F/W\n", - ioc->name)); - host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK; - host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW; - writel(host_diagnostic, &ioc->chip->HostDiagnostic); - - drsprintk(ioc, pr_info(MPT3SAS_FMT - "re-enable the HCDW\n", ioc->name)); - writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE, - &ioc->chip->HCBSize); - } - - drsprintk(ioc, pr_info(MPT3SAS_FMT "restart the adapter\n", - ioc->name)); - writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET, - &ioc->chip->HostDiagnostic); - - drsprintk(ioc, pr_info(MPT3SAS_FMT - "disable writes to the diagnostic register\n", ioc->name)); - writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence); - - drsprintk(ioc, pr_info(MPT3SAS_FMT - "Wait for FW to go to the READY state\n", ioc->name)); - ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20, - sleep_flag); - if (ioc_state) { - pr_err(MPT3SAS_FMT - "%s: failed going to ready state (ioc_state=0x%x)\n", - ioc->name, __func__, ioc_state); - goto out; - } - - pr_info(MPT3SAS_FMT "diag reset: SUCCESS\n", ioc->name); - return 0; - - out: - pr_err(MPT3SAS_FMT "diag reset: FAILED\n", ioc->name); - return -EFAULT; -} - -/** - * _base_make_ioc_ready - put controller in READY state - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * @type: FORCE_BIG_HAMMER or SOFT_RESET - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, - enum reset_type type) -{ - u32 ioc_state; - int rc; - int count; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - if (ioc->pci_error_recovery) - return 0; - - ioc_state = mpt3sas_base_get_iocstate(ioc, 0); - dhsprintk(ioc, pr_info(MPT3SAS_FMT "%s: ioc_state(0x%08x)\n", - ioc->name, __func__, ioc_state)); - - /* if in RESET state, it should move to READY state shortly */ - count = 0; - if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_RESET) { - while ((ioc_state & MPI2_IOC_STATE_MASK) != - MPI2_IOC_STATE_READY) { - if (count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed going to ready state (ioc_state=0x%x)\n", - ioc->name, __func__, ioc_state); - return -EFAULT; - } - if (sleep_flag == CAN_SLEEP) - ssleep(1); - else - mdelay(1000); - ioc_state = mpt3sas_base_get_iocstate(ioc, 0); - } - } - - if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY) - return 0; - - if (ioc_state & MPI2_DOORBELL_USED) { - dhsprintk(ioc, pr_info(MPT3SAS_FMT - "unexpected doorbell active!\n", - ioc->name)); - goto issue_diag_reset; - } - - if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { - mpt3sas_base_fault_info(ioc, ioc_state & - MPI2_DOORBELL_DATA_MASK); - goto issue_diag_reset; - } - - if (type == FORCE_BIG_HAMMER) - goto issue_diag_reset; - - if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL) - if (!(_base_send_ioc_reset(ioc, - MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) { - return 0; - } - - issue_diag_reset: - rc = _base_diag_reset(ioc, CAN_SLEEP); - return rc; -} - -/** - * _base_make_ioc_operational - put controller in OPERATIONAL state - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - int r, i; - unsigned long flags; - u32 reply_address; - u16 smid; - struct _tr_list *delayed_tr, *delayed_tr_next; - struct adapter_reply_queue *reply_q; - long reply_post_free; - u32 reply_post_free_sz; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - /* clean the delayed target reset list */ - list_for_each_entry_safe(delayed_tr, delayed_tr_next, - &ioc->delayed_tr_list, list) { - list_del(&delayed_tr->list); - kfree(delayed_tr); - } - - - list_for_each_entry_safe(delayed_tr, delayed_tr_next, - &ioc->delayed_tr_volume_list, list) { - list_del(&delayed_tr->list); - kfree(delayed_tr); - } - - /* initialize the scsi lookup free list */ - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - INIT_LIST_HEAD(&ioc->free_list); - smid = 1; - for (i = 0; i < ioc->scsiio_depth; i++, smid++) { - INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list); - ioc->scsi_lookup[i].cb_idx = 0xFF; - ioc->scsi_lookup[i].smid = smid; - ioc->scsi_lookup[i].scmd = NULL; - list_add_tail(&ioc->scsi_lookup[i].tracker_list, - &ioc->free_list); - } - - /* hi-priority queue */ - INIT_LIST_HEAD(&ioc->hpr_free_list); - smid = ioc->hi_priority_smid; - for (i = 0; i < ioc->hi_priority_depth; i++, smid++) { - ioc->hpr_lookup[i].cb_idx = 0xFF; - ioc->hpr_lookup[i].smid = smid; - list_add_tail(&ioc->hpr_lookup[i].tracker_list, - &ioc->hpr_free_list); - } - - /* internal queue */ - INIT_LIST_HEAD(&ioc->internal_free_list); - smid = ioc->internal_smid; - for (i = 0; i < ioc->internal_depth; i++, smid++) { - ioc->internal_lookup[i].cb_idx = 0xFF; - ioc->internal_lookup[i].smid = smid; - list_add_tail(&ioc->internal_lookup[i].tracker_list, - &ioc->internal_free_list); - } - - /* chain pool */ - INIT_LIST_HEAD(&ioc->free_chain_list); - for (i = 0; i < ioc->chain_depth; i++) - list_add_tail(&ioc->chain_lookup[i].tracker_list, - &ioc->free_chain_list); - - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - - /* initialize Reply Free Queue */ - for (i = 0, reply_address = (u32)ioc->reply_dma ; - i < ioc->reply_free_queue_depth ; i++, reply_address += - ioc->reply_sz) - ioc->reply_free[i] = cpu_to_le32(reply_address); - - /* initialize reply queues */ - if (ioc->is_driver_loading) - _base_assign_reply_queues(ioc); - - /* initialize Reply Post Free Queue */ - reply_post_free = (long)ioc->reply_post_free; - reply_post_free_sz = ioc->reply_post_queue_depth * - sizeof(Mpi2DefaultReplyDescriptor_t); - list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { - reply_q->reply_post_host_index = 0; - reply_q->reply_post_free = (Mpi2ReplyDescriptorsUnion_t *) - reply_post_free; - for (i = 0; i < ioc->reply_post_queue_depth; i++) - reply_q->reply_post_free[i].Words = - cpu_to_le64(ULLONG_MAX); - if (!_base_is_controller_msix_enabled(ioc)) - goto skip_init_reply_post_free_queue; - reply_post_free += reply_post_free_sz; - } - skip_init_reply_post_free_queue: - - r = _base_send_ioc_init(ioc, sleep_flag); - if (r) - return r; - - /* initialize reply free host index */ - ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1; - writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex); - - /* initialize reply post host index */ - list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { - writel(reply_q->msix_index << MPI2_RPHI_MSIX_INDEX_SHIFT, - &ioc->chip->ReplyPostHostIndex); - if (!_base_is_controller_msix_enabled(ioc)) - goto skip_init_reply_post_host_index; - } - - skip_init_reply_post_host_index: - - _base_unmask_interrupts(ioc); - r = _base_event_notification(ioc, sleep_flag); - if (r) - return r; - - if (sleep_flag == CAN_SLEEP) - _base_static_config_pages(ioc); - - - if (ioc->is_driver_loading) { - ioc->wait_for_discovery_to_complete = - _base_determine_wait_on_discovery(ioc); - - return r; /* scan_start and scan_finished support */ - } - - r = _base_send_port_enable(ioc, sleep_flag); - if (r) - return r; - - return r; -} - -/** - * mpt3sas_base_free_resources - free resources controller resources - * @ioc: per adapter object - * - * Return nothing. - */ -void -mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc) -{ - struct pci_dev *pdev = ioc->pdev; - - dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - _base_mask_interrupts(ioc); - ioc->shost_recovery = 1; - _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); - ioc->shost_recovery = 0; - _base_free_irq(ioc); - _base_disable_msix(ioc); - if (ioc->chip_phys) - iounmap(ioc->chip); - ioc->chip_phys = 0; - pci_release_selected_regions(ioc->pdev, ioc->bars); - pci_disable_pcie_error_reporting(pdev); - pci_disable_device(pdev); - return; -} - -/** - * mpt3sas_base_attach - attach controller instance - * @ioc: per adapter object - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) -{ - int r, i; - int cpu_id, last_cpu_id = 0; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - /* setup cpu_msix_table */ - ioc->cpu_count = num_online_cpus(); - for_each_online_cpu(cpu_id) - last_cpu_id = cpu_id; - ioc->cpu_msix_table_sz = last_cpu_id + 1; - ioc->cpu_msix_table = kzalloc(ioc->cpu_msix_table_sz, GFP_KERNEL); - ioc->reply_queue_count = 1; - if (!ioc->cpu_msix_table) { - dfailprintk(ioc, pr_info(MPT3SAS_FMT - "allocation for cpu_msix_table failed!!!\n", - ioc->name)); - r = -ENOMEM; - goto out_free_resources; - } - - r = mpt3sas_base_map_resources(ioc); - if (r) - goto out_free_resources; - - - pci_set_drvdata(ioc->pdev, ioc->shost); - r = _base_get_ioc_facts(ioc, CAN_SLEEP); - if (r) - goto out_free_resources; - - /* - * In SAS3.0, - * SCSI_IO, SMP_PASSTHRU, SATA_PASSTHRU, Target Assist, and - * Target Status - all require the IEEE formated scatter gather - * elements. - */ - - ioc->build_sg_scmd = &_base_build_sg_scmd_ieee; - ioc->build_sg = &_base_build_sg_ieee; - ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee; - ioc->mpi25 = 1; - ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t); - - /* - * These function pointers for other requests that don't - * the require IEEE scatter gather elements. - * - * For example Configuration Pages and SAS IOUNIT Control don't. - */ - ioc->build_sg_mpi = &_base_build_sg; - ioc->build_zero_len_sge_mpi = &_base_build_zero_len_sge; - - r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); - if (r) - goto out_free_resources; - - ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts, - sizeof(struct mpt3sas_port_facts), GFP_KERNEL); - if (!ioc->pfacts) { - r = -ENOMEM; - goto out_free_resources; - } - - for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { - r = _base_get_port_facts(ioc, i, CAN_SLEEP); - if (r) - goto out_free_resources; - } - - r = _base_allocate_memory_pools(ioc, CAN_SLEEP); - if (r) - goto out_free_resources; - - init_waitqueue_head(&ioc->reset_wq); - - /* allocate memory pd handle bitmask list */ - ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8); - if (ioc->facts.MaxDevHandle % 8) - ioc->pd_handles_sz++; - ioc->pd_handles = kzalloc(ioc->pd_handles_sz, - GFP_KERNEL); - if (!ioc->pd_handles) { - r = -ENOMEM; - goto out_free_resources; - } - ioc->blocking_handles = kzalloc(ioc->pd_handles_sz, - GFP_KERNEL); - if (!ioc->blocking_handles) { - r = -ENOMEM; - goto out_free_resources; - } - - ioc->fwfault_debug = mpt3sas_fwfault_debug; - - /* base internal command bits */ - mutex_init(&ioc->base_cmds.mutex); - ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - - /* port_enable command bits */ - ioc->port_enable_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->port_enable_cmds.status = MPT3_CMD_NOT_USED; - - /* transport internal command bits */ - ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->transport_cmds.status = MPT3_CMD_NOT_USED; - mutex_init(&ioc->transport_cmds.mutex); - - /* scsih internal command bits */ - ioc->scsih_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; - mutex_init(&ioc->scsih_cmds.mutex); - - /* task management internal command bits */ - ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->tm_cmds.status = MPT3_CMD_NOT_USED; - mutex_init(&ioc->tm_cmds.mutex); - - /* config page internal command bits */ - ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->config_cmds.status = MPT3_CMD_NOT_USED; - mutex_init(&ioc->config_cmds.mutex); - - /* ctl module internal command bits */ - ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->ctl_cmds.sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); - ioc->ctl_cmds.status = MPT3_CMD_NOT_USED; - mutex_init(&ioc->ctl_cmds.mutex); - - if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply || - !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply || - !ioc->config_cmds.reply || !ioc->ctl_cmds.reply || - !ioc->ctl_cmds.sense) { - r = -ENOMEM; - goto out_free_resources; - } - - for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) - ioc->event_masks[i] = -1; - - /* here we enable the events we care about */ - _base_unmask_events(ioc, MPI2_EVENT_SAS_DISCOVERY); - _base_unmask_events(ioc, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE); - _base_unmask_events(ioc, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST); - _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE); - _base_unmask_events(ioc, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE); - _base_unmask_events(ioc, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST); - _base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME); - _base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK); - _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS); - _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED); - - r = _base_make_ioc_operational(ioc, CAN_SLEEP); - if (r) - goto out_free_resources; - - return 0; - - out_free_resources: - - ioc->remove_host = 1; - - mpt3sas_base_free_resources(ioc); - _base_release_memory_pools(ioc); - pci_set_drvdata(ioc->pdev, NULL); - kfree(ioc->cpu_msix_table); - kfree(ioc->pd_handles); - kfree(ioc->blocking_handles); - kfree(ioc->tm_cmds.reply); - kfree(ioc->transport_cmds.reply); - kfree(ioc->scsih_cmds.reply); - kfree(ioc->config_cmds.reply); - kfree(ioc->base_cmds.reply); - kfree(ioc->port_enable_cmds.reply); - kfree(ioc->ctl_cmds.reply); - kfree(ioc->ctl_cmds.sense); - kfree(ioc->pfacts); - ioc->ctl_cmds.reply = NULL; - ioc->base_cmds.reply = NULL; - ioc->tm_cmds.reply = NULL; - ioc->scsih_cmds.reply = NULL; - ioc->transport_cmds.reply = NULL; - ioc->config_cmds.reply = NULL; - ioc->pfacts = NULL; - return r; -} - - -/** - * mpt3sas_base_detach - remove controller instance - * @ioc: per adapter object - * - * Return nothing. - */ -void -mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc) -{ - dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - mpt3sas_base_stop_watchdog(ioc); - mpt3sas_base_free_resources(ioc); - _base_release_memory_pools(ioc); - pci_set_drvdata(ioc->pdev, NULL); - kfree(ioc->cpu_msix_table); - kfree(ioc->pd_handles); - kfree(ioc->blocking_handles); - kfree(ioc->pfacts); - kfree(ioc->ctl_cmds.reply); - kfree(ioc->ctl_cmds.sense); - kfree(ioc->base_cmds.reply); - kfree(ioc->port_enable_cmds.reply); - kfree(ioc->tm_cmds.reply); - kfree(ioc->transport_cmds.reply); - kfree(ioc->scsih_cmds.reply); - kfree(ioc->config_cmds.reply); -} - -/** - * _base_reset_handler - reset callback handler (for base) - * @ioc: per adapter object - * @reset_phase: phase - * - * The handler for doing any required cleanup or initialization. - * - * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET, - * MPT3_IOC_DONE_RESET - * - * Return nothing. - */ -static void -_base_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase) -{ - mpt3sas_scsih_reset_handler(ioc, reset_phase); - mpt3sas_ctl_reset_handler(ioc, reset_phase); - switch (reset_phase) { - case MPT3_IOC_PRE_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__)); - break; - case MPT3_IOC_AFTER_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__)); - if (ioc->transport_cmds.status & MPT3_CMD_PENDING) { - ioc->transport_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->transport_cmds.smid); - complete(&ioc->transport_cmds.done); - } - if (ioc->base_cmds.status & MPT3_CMD_PENDING) { - ioc->base_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->base_cmds.smid); - complete(&ioc->base_cmds.done); - } - if (ioc->port_enable_cmds.status & MPT3_CMD_PENDING) { - ioc->port_enable_failed = 1; - ioc->port_enable_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->port_enable_cmds.smid); - if (ioc->is_driver_loading) { - ioc->start_scan_failed = - MPI2_IOCSTATUS_INTERNAL_ERROR; - ioc->start_scan = 0; - ioc->port_enable_cmds.status = - MPT3_CMD_NOT_USED; - } else - complete(&ioc->port_enable_cmds.done); - } - if (ioc->config_cmds.status & MPT3_CMD_PENDING) { - ioc->config_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->config_cmds.smid); - ioc->config_cmds.smid = USHRT_MAX; - complete(&ioc->config_cmds.done); - } - break; - case MPT3_IOC_DONE_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__)); - break; - } -} - -/** - * _wait_for_commands_to_complete - reset controller - * @ioc: Pointer to MPT_ADAPTER structure - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * This function waiting(3s) for all pending commands to complete - * prior to putting controller in reset. - */ -static void -_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - u32 ioc_state; - unsigned long flags; - u16 i; - - ioc->pending_io_count = 0; - if (sleep_flag != CAN_SLEEP) - return; - - ioc_state = mpt3sas_base_get_iocstate(ioc, 0); - if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) - return; - - /* pending command count */ - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - for (i = 0; i < ioc->scsiio_depth; i++) - if (ioc->scsi_lookup[i].cb_idx != 0xFF) - ioc->pending_io_count++; - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - - if (!ioc->pending_io_count) - return; - - /* wait for pending commands to complete */ - wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ); -} - -/** - * mpt3sas_base_hard_reset_handler - reset controller - * @ioc: Pointer to MPT_ADAPTER structure - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * @type: FORCE_BIG_HAMMER or SOFT_RESET - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, - enum reset_type type) -{ - int r; - unsigned long flags; - u32 ioc_state; - u8 is_fault = 0, is_trigger = 0; - - dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, - __func__)); - - if (ioc->pci_error_recovery) { - pr_err(MPT3SAS_FMT "%s: pci error recovery reset\n", - ioc->name, __func__); - r = 0; - goto out_unlocked; - } - - if (mpt3sas_fwfault_debug) - mpt3sas_halt_firmware(ioc); - - /* TODO - What we really should be doing is pulling - * out all the code associated with NO_SLEEP; its never used. - * That is legacy code from mpt fusion driver, ported over. - * I will leave this BUG_ON here for now till its been resolved. - */ - BUG_ON(sleep_flag == NO_SLEEP); - - /* wait for an active reset in progress to complete */ - if (!mutex_trylock(&ioc->reset_in_progress_mutex)) { - do { - ssleep(1); - } while (ioc->shost_recovery == 1); - dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); - return ioc->ioc_reset_in_progress_status; - } - - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - ioc->shost_recovery = 1; - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); - - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) && - (!(ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED))) { - is_trigger = 1; - ioc_state = mpt3sas_base_get_iocstate(ioc, 0); - if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) - is_fault = 1; - } - _base_reset_handler(ioc, MPT3_IOC_PRE_RESET); - _wait_for_commands_to_complete(ioc, sleep_flag); - _base_mask_interrupts(ioc); - r = _base_make_ioc_ready(ioc, sleep_flag, type); - if (r) - goto out; - _base_reset_handler(ioc, MPT3_IOC_AFTER_RESET); - - /* If this hard reset is called while port enable is active, then - * there is no reason to call make_ioc_operational - */ - if (ioc->is_driver_loading && ioc->port_enable_failed) { - ioc->remove_host = 1; - r = -EFAULT; - goto out; - } - r = _base_get_ioc_facts(ioc, CAN_SLEEP); - if (r) - goto out; - r = _base_make_ioc_operational(ioc, sleep_flag); - if (!r) - _base_reset_handler(ioc, MPT3_IOC_DONE_RESET); - - out: - dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: %s\n", - ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED"))); - - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - ioc->ioc_reset_in_progress_status = r; - ioc->shost_recovery = 0; - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); - ioc->ioc_reset_count++; - mutex_unlock(&ioc->reset_in_progress_mutex); - - out_unlocked: - if ((r == 0) && is_trigger) { - if (is_fault) - mpt3sas_trigger_master(ioc, MASTER_TRIGGER_FW_FAULT); - else - mpt3sas_trigger_master(ioc, - MASTER_TRIGGER_ADAPTER_RESET); - } - dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); - return r; -} diff --git a/addons/mpt3sas/src/3.10.108/mpt3sas_base.h b/addons/mpt3sas/src/3.10.108/mpt3sas_base.h deleted file mode 100644 index 997e13f6..00000000 --- a/addons/mpt3sas/src/3.10.108/mpt3sas_base.h +++ /dev/null @@ -1,1151 +0,0 @@ -/* - * This is the Fusion MPT base driver providing common API layer interface - * for access to MPT (Message Passing Technology) firmware. - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h - * Copyright (C) 2012 LSI Corporation - * (mailto:DL-MPTFusionLinux@lsi.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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 MPT3SAS_BASE_H_INCLUDED -#define MPT3SAS_BASE_H_INCLUDED - -#include "mpi/mpi2_type.h" -#include "mpi/mpi2.h" -#include "mpi/mpi2_ioc.h" -#include "mpi/mpi2_cnfg.h" -#include "mpi/mpi2_init.h" -#include "mpi/mpi2_raid.h" -#include "mpi/mpi2_tool.h" -#include "mpi/mpi2_sas.h" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mpt3sas_debug.h" -#include "mpt3sas_trigger_diag.h" - -/* driver versioning info */ -#define MPT3SAS_DRIVER_NAME "mpt3sas" -#define MPT3SAS_AUTHOR "LSI Corporation " -#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" -#define MPT3SAS_DRIVER_VERSION "01.100.01.00" -#define MPT3SAS_MAJOR_VERSION 1 -#define MPT3SAS_MINOR_VERSION 100 -#define MPT3SAS_BUILD_VERSION 1 -#define MPT3SAS_RELEASE_VERSION 00 - -/* - * Set MPT3SAS_SG_DEPTH value based on user input. - */ -#define MPT3SAS_MAX_PHYS_SEGMENTS SCSI_MAX_SG_SEGMENTS -#define MPT3SAS_MIN_PHYS_SEGMENTS 16 -#ifdef CONFIG_SCSI_MPT3SAS_MAX_SGE -#define MPT3SAS_SG_DEPTH CONFIG_SCSI_MPT3SAS_MAX_SGE -#else -#define MPT3SAS_SG_DEPTH MPT3SAS_MAX_PHYS_SEGMENTS -#endif - - -/* - * Generic Defines - */ -#define MPT3SAS_SATA_QUEUE_DEPTH 32 -#define MPT3SAS_SAS_QUEUE_DEPTH 254 -#define MPT3SAS_RAID_QUEUE_DEPTH 128 - -#define MPT_NAME_LENGTH 32 /* generic length of strings */ -#define MPT_STRING_LENGTH 64 - -#define MPT_MAX_CALLBACKS 32 - - -#define CAN_SLEEP 1 -#define NO_SLEEP 0 - -#define INTERNAL_CMDS_COUNT 10 /* reserved cmds */ - -#define MPI3_HIM_MASK 0xFFFFFFFF /* mask every bit*/ - -#define MPT3SAS_INVALID_DEVICE_HANDLE 0xFFFF - -/* - * reset phases - */ -#define MPT3_IOC_PRE_RESET 1 /* prior to host reset */ -#define MPT3_IOC_AFTER_RESET 2 /* just after host reset */ -#define MPT3_IOC_DONE_RESET 3 /* links re-initialized */ - -/* - * logging format - */ -#define MPT3SAS_FMT "%s: " - -/* - * per target private data - */ -#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01 -#define MPT_TARGET_FLAGS_VOLUME 0x02 -#define MPT_TARGET_FLAGS_DELETED 0x04 -#define MPT_TARGET_FASTPATH_IO 0x08 - - - -/* - * status bits for ioc->diag_buffer_status - */ -#define MPT3_DIAG_BUFFER_IS_REGISTERED (0x01) -#define MPT3_DIAG_BUFFER_IS_RELEASED (0x02) -#define MPT3_DIAG_BUFFER_IS_DIAG_RESET (0x04) - - -/* OEM Identifiers */ -#define MFG10_OEM_ID_INVALID (0x00000000) -#define MFG10_OEM_ID_DELL (0x00000001) -#define MFG10_OEM_ID_FSC (0x00000002) -#define MFG10_OEM_ID_SUN (0x00000003) -#define MFG10_OEM_ID_IBM (0x00000004) - -/* GENERIC Flags 0*/ -#define MFG10_GF0_OCE_DISABLED (0x00000001) -#define MFG10_GF0_R1E_DRIVE_COUNT (0x00000002) -#define MFG10_GF0_R10_DISPLAY (0x00000004) -#define MFG10_GF0_SSD_DATA_SCRUB_DISABLE (0x00000008) -#define MFG10_GF0_SINGLE_DRIVE_R0 (0x00000010) - -/* OEM Specific Flags will come from OEM specific header files */ -struct Mpi2ManufacturingPage10_t { - MPI2_CONFIG_PAGE_HEADER Header; /* 00h */ - U8 OEMIdentifier; /* 04h */ - U8 Reserved1; /* 05h */ - U16 Reserved2; /* 08h */ - U32 Reserved3; /* 0Ch */ - U32 GenericFlags0; /* 10h */ - U32 GenericFlags1; /* 14h */ - U32 Reserved4; /* 18h */ - U32 OEMSpecificFlags0; /* 1Ch */ - U32 OEMSpecificFlags1; /* 20h */ - U32 Reserved5[18]; /* 24h - 60h*/ -}; - - -/* Miscellaneous options */ -struct Mpi2ManufacturingPage11_t { - MPI2_CONFIG_PAGE_HEADER Header; /* 00h */ - __le32 Reserved1; /* 04h */ - u8 Reserved2; /* 08h */ - u8 EEDPTagMode; /* 09h */ - u8 Reserved3; /* 0Ah */ - u8 Reserved4; /* 0Bh */ - __le32 Reserved5[23]; /* 0Ch-60h*/ -}; - -/** - * struct MPT3SAS_TARGET - starget private hostdata - * @starget: starget object - * @sas_address: target sas address - * @handle: device handle - * @num_luns: number luns - * @flags: MPT_TARGET_FLAGS_XXX flags - * @deleted: target flaged for deletion - * @tm_busy: target is busy with TM request. - */ -struct MPT3SAS_TARGET { - struct scsi_target *starget; - u64 sas_address; - u16 handle; - int num_luns; - u32 flags; - u8 deleted; - u8 tm_busy; -}; - - -/* - * per device private data - */ -#define MPT_DEVICE_FLAGS_INIT 0x01 -#define MPT_DEVICE_TLR_ON 0x02 - -/** - * struct MPT3SAS_DEVICE - sdev private hostdata - * @sas_target: starget private hostdata - * @lun: lun number - * @flags: MPT_DEVICE_XXX flags - * @configured_lun: lun is configured - * @block: device is in SDEV_BLOCK state - * @tlr_snoop_check: flag used in determining whether to disable TLR - * @eedp_enable: eedp support enable bit - * @eedp_type: 0(type_1), 1(type_2), 2(type_3) - * @eedp_block_length: block size - * @ata_command_pending: SATL passthrough outstanding for device - */ -struct MPT3SAS_DEVICE { - struct MPT3SAS_TARGET *sas_target; - unsigned int lun; - u32 flags; - u8 configured_lun; - u8 block; - u8 tlr_snoop_check; - /* - * Bug workaround for SATL handling: the mpt2/3sas firmware - * doesn't return BUSY or TASK_SET_FULL for subsequent - * commands while a SATL pass through is in operation as the - * spec requires, it simply does nothing with them until the - * pass through completes, causing them possibly to timeout if - * the passthrough is a long executing command (like format or - * secure erase). This variable allows us to do the right - * thing while a SATL command is pending. - */ - unsigned long ata_command_pending; -}; - -#define MPT3_CMD_NOT_USED 0x8000 /* free */ -#define MPT3_CMD_COMPLETE 0x0001 /* completed */ -#define MPT3_CMD_PENDING 0x0002 /* pending */ -#define MPT3_CMD_REPLY_VALID 0x0004 /* reply is valid */ -#define MPT3_CMD_RESET 0x0008 /* host reset dropped the command */ - -/** - * struct _internal_cmd - internal commands struct - * @mutex: mutex - * @done: completion - * @reply: reply message pointer - * @sense: sense data - * @status: MPT3_CMD_XXX status - * @smid: system message id - */ -struct _internal_cmd { - struct mutex mutex; - struct completion done; - void *reply; - void *sense; - u16 status; - u16 smid; -}; - - - -/** - * struct _sas_device - attached device information - * @list: sas device list - * @starget: starget object - * @sas_address: device sas address - * @device_name: retrieved from the SAS IDENTIFY frame. - * @handle: device handle - * @sas_address_parent: sas address of parent expander or sas host - * @enclosure_handle: enclosure handle - * @enclosure_logical_id: enclosure logical identifier - * @volume_handle: volume handle (valid when hidden raid member) - * @volume_wwid: volume unique identifier - * @device_info: bitfield provides detailed info about the device - * @id: target id - * @channel: target channel - * @slot: number number - * @phy: phy identifier provided in sas device page 0 - * @fast_path: fast path feature enable bit - * @responding: used in _scsih_sas_device_mark_responding - */ -struct _sas_device { - struct list_head list; - struct scsi_target *starget; - u64 sas_address; - u64 device_name; - u16 handle; - u64 sas_address_parent; - u16 enclosure_handle; - u64 enclosure_logical_id; - u16 volume_handle; - u64 volume_wwid; - u32 device_info; - int id; - int channel; - u16 slot; - u8 phy; - u8 responding; - u8 fast_path; -}; - -/** - * struct _raid_device - raid volume link list - * @list: sas device list - * @starget: starget object - * @sdev: scsi device struct (volumes are single lun) - * @wwid: unique identifier for the volume - * @handle: device handle - * @id: target id - * @channel: target channel - * @volume_type: the raid level - * @device_info: bitfield provides detailed info about the hidden components - * @num_pds: number of hidden raid components - * @responding: used in _scsih_raid_device_mark_responding - * @percent_complete: resync percent complete - */ -#define MPT_MAX_WARPDRIVE_PDS 8 -struct _raid_device { - struct list_head list; - struct scsi_target *starget; - struct scsi_device *sdev; - u64 wwid; - u16 handle; - int id; - int channel; - u8 volume_type; - u8 num_pds; - u8 responding; - u8 percent_complete; - u32 device_info; -}; - -/** - * struct _boot_device - boot device info - * @is_raid: flag to indicate whether this is volume - * @device: holds pointer for either struct _sas_device or - * struct _raid_device - */ -struct _boot_device { - u8 is_raid; - void *device; -}; - -/** - * struct _sas_port - wide/narrow sas port information - * @port_list: list of ports belonging to expander - * @num_phys: number of phys belonging to this port - * @remote_identify: attached device identification - * @rphy: sas transport rphy object - * @port: sas transport wide/narrow port object - * @phy_list: _sas_phy list objects belonging to this port - */ -struct _sas_port { - struct list_head port_list; - u8 num_phys; - struct sas_identify remote_identify; - struct sas_rphy *rphy; - struct sas_port *port; - struct list_head phy_list; -}; - -/** - * struct _sas_phy - phy information - * @port_siblings: list of phys belonging to a port - * @identify: phy identification - * @remote_identify: attached device identification - * @phy: sas transport phy object - * @phy_id: unique phy id - * @handle: device handle for this phy - * @attached_handle: device handle for attached device - * @phy_belongs_to_port: port has been created for this phy - */ -struct _sas_phy { - struct list_head port_siblings; - struct sas_identify identify; - struct sas_identify remote_identify; - struct sas_phy *phy; - u8 phy_id; - u16 handle; - u16 attached_handle; - u8 phy_belongs_to_port; -}; - -/** - * struct _sas_node - sas_host/expander information - * @list: list of expanders - * @parent_dev: parent device class - * @num_phys: number phys belonging to this sas_host/expander - * @sas_address: sas address of this sas_host/expander - * @handle: handle for this sas_host/expander - * @sas_address_parent: sas address of parent expander or sas host - * @enclosure_handle: handle for this a member of an enclosure - * @device_info: bitwise defining capabilities of this sas_host/expander - * @responding: used in _scsih_expander_device_mark_responding - * @phy: a list of phys that make up this sas_host/expander - * @sas_port_list: list of ports attached to this sas_host/expander - */ -struct _sas_node { - struct list_head list; - struct device *parent_dev; - u8 num_phys; - u64 sas_address; - u16 handle; - u64 sas_address_parent; - u16 enclosure_handle; - u64 enclosure_logical_id; - u8 responding; - struct _sas_phy *phy; - struct list_head sas_port_list; -}; - -/** - * enum reset_type - reset state - * @FORCE_BIG_HAMMER: issue diagnostic reset - * @SOFT_RESET: issue message_unit_reset, if fails to to big hammer - */ -enum reset_type { - FORCE_BIG_HAMMER, - SOFT_RESET, -}; - -/** - * struct chain_tracker - firmware chain tracker - * @chain_buffer: chain buffer - * @chain_buffer_dma: physical address - * @tracker_list: list of free request (ioc->free_chain_list) - */ -struct chain_tracker { - void *chain_buffer; - dma_addr_t chain_buffer_dma; - struct list_head tracker_list; -}; - -/** - * struct scsiio_tracker - scsi mf request tracker - * @smid: system message id - * @scmd: scsi request pointer - * @cb_idx: callback index - * @tracker_list: list of free request (ioc->free_list) - */ -struct scsiio_tracker { - u16 smid; - struct scsi_cmnd *scmd; - u8 cb_idx; - struct list_head chain_list; - struct list_head tracker_list; -}; - -/** - * struct request_tracker - firmware request tracker - * @smid: system message id - * @cb_idx: callback index - * @tracker_list: list of free request (ioc->free_list) - */ -struct request_tracker { - u16 smid; - u8 cb_idx; - struct list_head tracker_list; -}; - -/** - * struct _tr_list - target reset list - * @handle: device handle - * @state: state machine - */ -struct _tr_list { - struct list_head list; - u16 handle; - u16 state; -}; - - -/** - * struct adapter_reply_queue - the reply queue struct - * @ioc: per adapter object - * @msix_index: msix index into vector table - * @vector: irq vector - * @reply_post_host_index: head index in the pool where FW completes IO - * @reply_post_free: reply post base virt address - * @name: the name registered to request_irq() - * @busy: isr is actively processing replies on another cpu - * @list: this list -*/ -struct adapter_reply_queue { - struct MPT3SAS_ADAPTER *ioc; - u8 msix_index; - unsigned int vector; - u32 reply_post_host_index; - Mpi2ReplyDescriptorsUnion_t *reply_post_free; - char name[MPT_NAME_LENGTH]; - atomic_t busy; - struct list_head list; -}; - -typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); - -/* SAS3.0 support */ -typedef int (*MPT_BUILD_SG_SCMD)(struct MPT3SAS_ADAPTER *ioc, - struct scsi_cmnd *scmd, u16 smid); -typedef void (*MPT_BUILD_SG)(struct MPT3SAS_ADAPTER *ioc, void *psge, - dma_addr_t data_out_dma, size_t data_out_sz, - dma_addr_t data_in_dma, size_t data_in_sz); -typedef void (*MPT_BUILD_ZERO_LEN_SGE)(struct MPT3SAS_ADAPTER *ioc, - void *paddr); - - - -/* IOC Facts and Port Facts converted from little endian to cpu */ -union mpi3_version_union { - MPI2_VERSION_STRUCT Struct; - u32 Word; -}; - -struct mpt3sas_facts { - u16 MsgVersion; - u16 HeaderVersion; - u8 IOCNumber; - u8 VP_ID; - u8 VF_ID; - u16 IOCExceptions; - u16 IOCStatus; - u32 IOCLogInfo; - u8 MaxChainDepth; - u8 WhoInit; - u8 NumberOfPorts; - u8 MaxMSIxVectors; - u16 RequestCredit; - u16 ProductID; - u32 IOCCapabilities; - union mpi3_version_union FWVersion; - u16 IOCRequestFrameSize; - u16 Reserved3; - u16 MaxInitiators; - u16 MaxTargets; - u16 MaxSasExpanders; - u16 MaxEnclosures; - u16 ProtocolFlags; - u16 HighPriorityCredit; - u16 MaxReplyDescriptorPostQueueDepth; - u8 ReplyFrameSize; - u8 MaxVolumes; - u16 MaxDevHandle; - u16 MaxPersistentEntries; - u16 MinDevHandle; -}; - -struct mpt3sas_port_facts { - u8 PortNumber; - u8 VP_ID; - u8 VF_ID; - u8 PortType; - u16 MaxPostedCmdBuffers; -}; - -/** - * enum mutex_type - task management mutex type - * @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it - * @TM_MUTEX_ON: mutex is required - */ -enum mutex_type { - TM_MUTEX_OFF = 0, - TM_MUTEX_ON = 1, -}; - -typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); -/** - * struct MPT3SAS_ADAPTER - per adapter struct - * @list: ioc_list - * @shost: shost object - * @id: unique adapter id - * @cpu_count: number online cpus - * @name: generic ioc string - * @tmp_string: tmp string used for logging - * @pdev: pci pdev object - * @pio_chip: physical io register space - * @chip: memory mapped register space - * @chip_phys: physical addrss prior to mapping - * @logging_level: see mpt3sas_debug.h - * @fwfault_debug: debuging FW timeouts - * @ir_firmware: IR firmware present - * @bars: bitmask of BAR's that must be configured - * @mask_interrupts: ignore interrupt - * @fault_reset_work_q_name: fw fault work queue - * @fault_reset_work_q: "" - * @fault_reset_work: "" - * @firmware_event_name: fw event work queue - * @firmware_event_thread: "" - * @fw_event_lock: - * @fw_event_list: list of fw events - * @aen_event_read_flag: event log was read - * @broadcast_aen_busy: broadcast aen waiting to be serviced - * @shost_recovery: host reset in progress - * @ioc_reset_in_progress_lock: - * @ioc_link_reset_in_progress: phy/hard reset in progress - * @ignore_loginfos: ignore loginfos during task management - * @remove_host: flag for when driver unloads, to avoid sending dev resets - * @pci_error_recovery: flag to prevent ioc access until slot reset completes - * @wait_for_discovery_to_complete: flag set at driver load time when - * waiting on reporting devices - * @is_driver_loading: flag set at driver load time - * @port_enable_failed: flag set when port enable has failed - * @start_scan: flag set from scan_start callback, cleared from _mpt3sas_fw_work - * @start_scan_failed: means port enable failed, return's the ioc_status - * @msix_enable: flag indicating msix is enabled - * @msix_vector_count: number msix vectors - * @cpu_msix_table: table for mapping cpus to msix index - * @cpu_msix_table_sz: table size - * @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands - * @scsi_io_cb_idx: shost generated commands - * @tm_cb_idx: task management commands - * @scsih_cb_idx: scsih internal commands - * @transport_cb_idx: transport internal commands - * @ctl_cb_idx: clt internal commands - * @base_cb_idx: base internal commands - * @config_cb_idx: base internal commands - * @tm_tr_cb_idx : device removal target reset handshake - * @tm_tr_volume_cb_idx : volume removal target reset - * @base_cmds: - * @transport_cmds: - * @scsih_cmds: - * @tm_cmds: - * @ctl_cmds: - * @config_cmds: - * @base_add_sg_single: handler for either 32/64 bit sgl's - * @event_type: bits indicating which events to log - * @event_context: unique id for each logged event - * @event_log: event log pointer - * @event_masks: events that are masked - * @facts: static facts data - * @pfacts: static port facts data - * @manu_pg0: static manufacturing page 0 - * @manu_pg10: static manufacturing page 10 - * @manu_pg11: static manufacturing page 11 - * @bios_pg2: static bios page 2 - * @bios_pg3: static bios page 3 - * @ioc_pg8: static ioc page 8 - * @iounit_pg0: static iounit page 0 - * @iounit_pg1: static iounit page 1 - * @sas_hba: sas host object - * @sas_expander_list: expander object list - * @sas_node_lock: - * @sas_device_list: sas device object list - * @sas_device_init_list: sas device object list (used only at init time) - * @sas_device_lock: - * @io_missing_delay: time for IO completed by fw when PDR enabled - * @device_missing_delay: time for device missing by fw when PDR enabled - * @sas_id : used for setting volume target IDs - * @blocking_handles: bitmask used to identify which devices need blocking - * @pd_handles : bitmask for PD handles - * @pd_handles_sz : size of pd_handle bitmask - * @config_page_sz: config page size - * @config_page: reserve memory for config page payload - * @config_page_dma: - * @hba_queue_depth: hba request queue depth - * @sge_size: sg element size for either 32/64 bit - * @scsiio_depth: SCSI_IO queue depth - * @request_sz: per request frame size - * @request: pool of request frames - * @request_dma: - * @request_dma_sz: - * @scsi_lookup: firmware request tracker list - * @scsi_lookup_lock: - * @free_list: free list of request - * @pending_io_count: - * @reset_wq: - * @chain: pool of chains - * @chain_dma: - * @max_sges_in_main_message: number sg elements in main message - * @max_sges_in_chain_message: number sg elements per chain - * @chains_needed_per_io: max chains per io - * @chain_depth: total chains allocated - * @hi_priority_smid: - * @hi_priority: - * @hi_priority_dma: - * @hi_priority_depth: - * @hpr_lookup: - * @hpr_free_list: - * @internal_smid: - * @internal: - * @internal_dma: - * @internal_depth: - * @internal_lookup: - * @internal_free_list: - * @sense: pool of sense - * @sense_dma: - * @sense_dma_pool: - * @reply_depth: hba reply queue depth: - * @reply_sz: per reply frame size: - * @reply: pool of replys: - * @reply_dma: - * @reply_dma_pool: - * @reply_free_queue_depth: reply free depth - * @reply_free: pool for reply free queue (32 bit addr) - * @reply_free_dma: - * @reply_free_dma_pool: - * @reply_free_host_index: tail index in pool to insert free replys - * @reply_post_queue_depth: reply post queue depth - * @reply_post_free: pool for reply post (64bit descriptor) - * @reply_post_free_dma: - * @reply_queue_count: number of reply queue's - * @reply_queue_list: link list contaning the reply queue info - * @reply_post_host_index: head index in the pool where FW completes IO - * @delayed_tr_list: target reset link list - * @delayed_tr_volume_list: volume target reset link list - */ -struct MPT3SAS_ADAPTER { - struct list_head list; - struct Scsi_Host *shost; - u8 id; - int cpu_count; - char name[MPT_NAME_LENGTH]; - char tmp_string[MPT_STRING_LENGTH]; - struct pci_dev *pdev; - Mpi2SystemInterfaceRegs_t __iomem *chip; - resource_size_t chip_phys; - int logging_level; - int fwfault_debug; - u8 ir_firmware; - int bars; - u8 mask_interrupts; - - /* fw fault handler */ - char fault_reset_work_q_name[20]; - struct workqueue_struct *fault_reset_work_q; - struct delayed_work fault_reset_work; - - /* fw event handler */ - char firmware_event_name[20]; - struct workqueue_struct *firmware_event_thread; - spinlock_t fw_event_lock; - struct list_head fw_event_list; - - /* misc flags */ - int aen_event_read_flag; - u8 broadcast_aen_busy; - u16 broadcast_aen_pending; - u8 shost_recovery; - - struct mutex reset_in_progress_mutex; - spinlock_t ioc_reset_in_progress_lock; - u8 ioc_link_reset_in_progress; - u8 ioc_reset_in_progress_status; - - u8 ignore_loginfos; - u8 remove_host; - u8 pci_error_recovery; - u8 wait_for_discovery_to_complete; - u8 is_driver_loading; - u8 port_enable_failed; - u8 start_scan; - u16 start_scan_failed; - - u8 msix_enable; - u16 msix_vector_count; - u8 *cpu_msix_table; - u16 cpu_msix_table_sz; - u32 ioc_reset_count; - MPT3SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds; - - /* internal commands, callback index */ - u8 scsi_io_cb_idx; - u8 tm_cb_idx; - u8 transport_cb_idx; - u8 scsih_cb_idx; - u8 ctl_cb_idx; - u8 base_cb_idx; - u8 port_enable_cb_idx; - u8 config_cb_idx; - u8 tm_tr_cb_idx; - u8 tm_tr_volume_cb_idx; - u8 tm_sas_control_cb_idx; - struct _internal_cmd base_cmds; - struct _internal_cmd port_enable_cmds; - struct _internal_cmd transport_cmds; - struct _internal_cmd scsih_cmds; - struct _internal_cmd tm_cmds; - struct _internal_cmd ctl_cmds; - struct _internal_cmd config_cmds; - - MPT_ADD_SGE base_add_sg_single; - - /* function ptr for either IEEE or MPI sg elements */ - MPT_BUILD_SG_SCMD build_sg_scmd; - MPT_BUILD_SG build_sg; - MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge; - u8 mpi25; - u16 sge_size_ieee; - - /* function ptr for MPI sg elements only */ - MPT_BUILD_SG build_sg_mpi; - MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge_mpi; - - /* event log */ - u32 event_type[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; - u32 event_context; - void *event_log; - u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; - - /* static config pages */ - struct mpt3sas_facts facts; - struct mpt3sas_port_facts *pfacts; - Mpi2ManufacturingPage0_t manu_pg0; - struct Mpi2ManufacturingPage10_t manu_pg10; - struct Mpi2ManufacturingPage11_t manu_pg11; - Mpi2BiosPage2_t bios_pg2; - Mpi2BiosPage3_t bios_pg3; - Mpi2IOCPage8_t ioc_pg8; - Mpi2IOUnitPage0_t iounit_pg0; - Mpi2IOUnitPage1_t iounit_pg1; - - struct _boot_device req_boot_device; - struct _boot_device req_alt_boot_device; - struct _boot_device current_boot_device; - - /* sas hba, expander, and device list */ - struct _sas_node sas_hba; - struct list_head sas_expander_list; - spinlock_t sas_node_lock; - struct list_head sas_device_list; - struct list_head sas_device_init_list; - spinlock_t sas_device_lock; - struct list_head raid_device_list; - spinlock_t raid_device_lock; - u8 io_missing_delay; - u16 device_missing_delay; - int sas_id; - - void *blocking_handles; - void *pd_handles; - u16 pd_handles_sz; - - /* config page */ - u16 config_page_sz; - void *config_page; - dma_addr_t config_page_dma; - - /* scsiio request */ - u16 hba_queue_depth; - u16 sge_size; - u16 scsiio_depth; - u16 request_sz; - u8 *request; - dma_addr_t request_dma; - u32 request_dma_sz; - struct scsiio_tracker *scsi_lookup; - ulong scsi_lookup_pages; - spinlock_t scsi_lookup_lock; - struct list_head free_list; - int pending_io_count; - wait_queue_head_t reset_wq; - - /* chain */ - struct chain_tracker *chain_lookup; - struct list_head free_chain_list; - struct dma_pool *chain_dma_pool; - ulong chain_pages; - u16 max_sges_in_main_message; - u16 max_sges_in_chain_message; - u16 chains_needed_per_io; - u32 chain_depth; - - /* hi-priority queue */ - u16 hi_priority_smid; - u8 *hi_priority; - dma_addr_t hi_priority_dma; - u16 hi_priority_depth; - struct request_tracker *hpr_lookup; - struct list_head hpr_free_list; - - /* internal queue */ - u16 internal_smid; - u8 *internal; - dma_addr_t internal_dma; - u16 internal_depth; - struct request_tracker *internal_lookup; - struct list_head internal_free_list; - - /* sense */ - u8 *sense; - dma_addr_t sense_dma; - struct dma_pool *sense_dma_pool; - - /* reply */ - u16 reply_sz; - u8 *reply; - dma_addr_t reply_dma; - u32 reply_dma_max_address; - u32 reply_dma_min_address; - struct dma_pool *reply_dma_pool; - - /* reply free queue */ - u16 reply_free_queue_depth; - __le32 *reply_free; - dma_addr_t reply_free_dma; - struct dma_pool *reply_free_dma_pool; - u32 reply_free_host_index; - - /* reply post queue */ - u16 reply_post_queue_depth; - Mpi2ReplyDescriptorsUnion_t *reply_post_free; - dma_addr_t reply_post_free_dma; - struct dma_pool *reply_post_free_dma_pool; - u8 reply_queue_count; - struct list_head reply_queue_list; - - struct list_head delayed_tr_list; - struct list_head delayed_tr_volume_list; - - /* diag buffer support */ - u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT]; - u32 diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT]; - dma_addr_t diag_buffer_dma[MPI2_DIAG_BUF_TYPE_COUNT]; - u8 diag_buffer_status[MPI2_DIAG_BUF_TYPE_COUNT]; - u32 unique_id[MPI2_DIAG_BUF_TYPE_COUNT]; - u32 product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23]; - u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT]; - u32 ring_buffer_offset; - u32 ring_buffer_sz; - spinlock_t diag_trigger_lock; - u8 diag_trigger_active; - struct SL_WH_MASTER_TRIGGER_T diag_trigger_master; - struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event; - struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi; - struct SL_WH_MPI_TRIGGERS_T diag_trigger_mpi; -}; - -typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply); - - -/* base shared API */ -extern struct list_head mpt3sas_ioc_list; -void mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc); -void mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc); - -int mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc); -void mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc); -int mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc); -void mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc); -int mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, - enum reset_type type); - -void *mpt3sas_base_get_msg_frame(struct MPT3SAS_ADAPTER *ioc, u16 smid); -void *mpt3sas_base_get_sense_buffer(struct MPT3SAS_ADAPTER *ioc, u16 smid); -__le32 mpt3sas_base_get_sense_buffer_dma(struct MPT3SAS_ADAPTER *ioc, - u16 smid); -void mpt3sas_base_flush_reply_queues(struct MPT3SAS_ADAPTER *ioc); - -/* hi-priority queue */ -u16 mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx); -u16 mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx, - struct scsi_cmnd *scmd); - -u16 mpt3sas_base_get_smid(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx); -void mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid); -void mpt3sas_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u16 handle); -void mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u16 handle); -void mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid); -void mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid); -void mpt3sas_base_initialize_callback_handler(void); -u8 mpt3sas_base_register_callback_handler(MPT_CALLBACK cb_func); -void mpt3sas_base_release_callback_handler(u8 cb_idx); - -u8 mpt3sas_base_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply); -u8 mpt3sas_port_enable_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u8 msix_index, u32 reply); -void *mpt3sas_base_get_reply_virt_addr(struct MPT3SAS_ADAPTER *ioc, - u32 phys_addr); - -u32 mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked); - -void mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc , u16 fault_code); -int mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc, - Mpi2SasIoUnitControlReply_t *mpi_reply, - Mpi2SasIoUnitControlRequest_t *mpi_request); -int mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, - Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request); - -void mpt3sas_base_validate_event_type(struct MPT3SAS_ADAPTER *ioc, - u32 *event_type); - -void mpt3sas_halt_firmware(struct MPT3SAS_ADAPTER *ioc); - -void mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc, - u16 device_missing_delay, u8 io_missing_delay); - -int mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc); - - -/* scsih shared API */ -u8 mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, - u32 reply); -void mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase); - -int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, - uint channel, uint id, uint lun, u8 type, u16 smid_task, - ulong timeout, unsigned long serial_number, enum mutex_type m_type); -void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); -void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); -void mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address); -void mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address); - -struct _sas_node *mpt3sas_scsih_expander_find_by_handle( - struct MPT3SAS_ADAPTER *ioc, u16 handle); -struct _sas_node *mpt3sas_scsih_expander_find_by_sas_address( - struct MPT3SAS_ADAPTER *ioc, u64 sas_address); -struct _sas_device *mpt3sas_scsih_sas_device_find_by_sas_address( - struct MPT3SAS_ADAPTER *ioc, u64 sas_address); - -void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc); - -/* config shared API */ -u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply); -int mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, - u8 *num_phys); -int mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page); -int mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page, - u16 sz); -int mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, - struct Mpi2ManufacturingPage10_t *config_page); - -int mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, - struct Mpi2ManufacturingPage11_t *config_page); -int mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, - struct Mpi2ManufacturingPage11_t *config_page); - -int mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2BiosPage2_t *config_page); -int mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2BiosPage3_t *config_page); -int mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2IOUnitPage0_t *config_page); -int mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page, - u32 form, u32 handle); -int mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page, - u32 form, u32 handle); -int mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, - u16 sz); -int mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2IOUnitPage1_t *config_page); -int mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2IOUnitPage1_t *config_page); -int mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, - u16 sz); -int mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, - u16 sz); -int mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2IOCPage8_t *config_page); -int mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2ExpanderPage0_t *config_page, - u32 form, u32 handle); -int mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2ExpanderPage1_t *config_page, - u32 phy_number, u16 handle); -int mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, - u32 form, u32 handle); -int mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number); -int mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number); -int mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, - u32 handle); -int mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u8 *num_pds); -int mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, - u32 handle, u16 sz); -int mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, - u32 form, u32 form_specific); -int mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle, - u16 *volume_handle); -int mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, - u16 volume_handle, u64 *wwid); - -/* ctl shared API */ -extern struct device_attribute *mpt3sas_host_attrs[]; -extern struct device_attribute *mpt3sas_dev_attrs[]; -void mpt3sas_ctl_init(void); -void mpt3sas_ctl_exit(void); -u8 mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply); -void mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase); -u8 mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc, - u8 msix_index, u32 reply); -void mpt3sas_ctl_add_to_event_log(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventNotificationReply_t *mpi_reply); - -void mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, - u8 bits_to_regsiter); -int mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type, - u8 *issue_reset); - -/* transport shared API */ -u8 mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply); -struct _sas_port *mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, - u16 handle, u64 sas_address); -void mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, - u64 sas_address_parent); -int mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy - *mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev); -int mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, - struct _sas_phy *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1, - struct device *parent_dev); -void mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address, u16 handle, u8 phy_number, u8 link_rate); -extern struct sas_function_template mpt3sas_transport_functions; -extern struct scsi_transport_template *mpt3sas_transport_template; -extern int scsi_internal_device_block(struct scsi_device *sdev); -extern int scsi_internal_device_unblock(struct scsi_device *sdev, - enum scsi_device_state new_state); -/* trigger data externs */ -void mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc, - struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data); -void mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc, - struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data); -void mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc, - u32 tigger_bitmask); -void mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event, - u16 log_entry_qualifier); -void mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key, - u8 asc, u8 ascq); -void mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status, - u32 loginfo); -#endif /* MPT3SAS_BASE_H_INCLUDED */ diff --git a/addons/mpt3sas/src/3.10.108/mpt3sas_config.c b/addons/mpt3sas/src/3.10.108/mpt3sas_config.c deleted file mode 100644 index 4db0c7a1..00000000 --- a/addons/mpt3sas/src/3.10.108/mpt3sas_config.c +++ /dev/null @@ -1,1649 +0,0 @@ -/* - * This module provides common API for accessing firmware configuration pages - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c - * Copyright (C) 2012 LSI Corporation - * (mailto:DL-MPTFusionLinux@lsi.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mpt3sas_base.h" - -/* local definitions */ - -/* Timeout for config page request (in seconds) */ -#define MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT 15 - -/* Common sgl flags for READING a config page. */ -#define MPT3_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ - MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ - | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT) - -/* Common sgl flags for WRITING a config page. */ -#define MPT3_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ - MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ - | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \ - << MPI2_SGE_FLAGS_SHIFT) - -/** - * struct config_request - obtain dma memory via routine - * @sz: size - * @page: virt pointer - * @page_dma: phys pointer - * - */ -struct config_request { - u16 sz; - void *page; - dma_addr_t page_dma; -}; - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING -/** - * _config_display_some_debug - debug routine - * @ioc: per adapter object - * @smid: system request message index - * @calling_function_name: string pass from calling function - * @mpi_reply: reply message frame - * Context: none. - * - * Function for displaying debug info helpful when debugging issues - * in this module. - */ -static void -_config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid, - char *calling_function_name, MPI2DefaultReply_t *mpi_reply) -{ - Mpi2ConfigRequest_t *mpi_request; - char *desc = NULL; - - if (!(ioc->logging_level & MPT_DEBUG_CONFIG)) - return; - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) { - case MPI2_CONFIG_PAGETYPE_IO_UNIT: - desc = "io_unit"; - break; - case MPI2_CONFIG_PAGETYPE_IOC: - desc = "ioc"; - break; - case MPI2_CONFIG_PAGETYPE_BIOS: - desc = "bios"; - break; - case MPI2_CONFIG_PAGETYPE_RAID_VOLUME: - desc = "raid_volume"; - break; - case MPI2_CONFIG_PAGETYPE_MANUFACTURING: - desc = "manufaucturing"; - break; - case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK: - desc = "physdisk"; - break; - case MPI2_CONFIG_PAGETYPE_EXTENDED: - switch (mpi_request->ExtPageType) { - case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT: - desc = "sas_io_unit"; - break; - case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER: - desc = "sas_expander"; - break; - case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE: - desc = "sas_device"; - break; - case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY: - desc = "sas_phy"; - break; - case MPI2_CONFIG_EXTPAGETYPE_LOG: - desc = "log"; - break; - case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE: - desc = "enclosure"; - break; - case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG: - desc = "raid_config"; - break; - case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING: - desc = "driver_mapping"; - break; - } - break; - } - - if (!desc) - return; - - pr_info(MPT3SAS_FMT - "%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n", - ioc->name, calling_function_name, desc, - mpi_request->Header.PageNumber, mpi_request->Action, - le32_to_cpu(mpi_request->PageAddress), smid); - - if (!mpi_reply) - return; - - if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) - pr_info(MPT3SAS_FMT - "\tiocstatus(0x%04x), loginfo(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo)); -} -#endif - -/** - * _config_alloc_config_dma_memory - obtain physical memory - * @ioc: per adapter object - * @mem: struct config_request - * - * A wrapper for obtaining dma-able memory for config page request. - * - * Returns 0 for success, non-zero for failure. - */ -static int -_config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc, - struct config_request *mem) -{ - int r = 0; - - if (mem->sz > ioc->config_page_sz) { - mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz, - &mem->page_dma, GFP_KERNEL); - if (!mem->page) { - pr_err(MPT3SAS_FMT - "%s: dma_alloc_coherent failed asking for (%d) bytes!!\n", - ioc->name, __func__, mem->sz); - r = -ENOMEM; - } - } else { /* use tmp buffer if less than 512 bytes */ - mem->page = ioc->config_page; - mem->page_dma = ioc->config_page_dma; - } - return r; -} - -/** - * _config_free_config_dma_memory - wrapper to free the memory - * @ioc: per adapter object - * @mem: struct config_request - * - * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory. - * - * Returns 0 for success, non-zero for failure. - */ -static void -_config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc, - struct config_request *mem) -{ - if (mem->sz > ioc->config_page_sz) - dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page, - mem->page_dma); -} - -/** - * mpt3sas_config_done - config page completion routine - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: none. - * - * The callback handler when using _config_request. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - - if (ioc->config_cmds.status == MPT3_CMD_NOT_USED) - return 1; - if (ioc->config_cmds.smid != smid) - return 1; - ioc->config_cmds.status |= MPT3_CMD_COMPLETE; - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (mpi_reply) { - ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID; - memcpy(ioc->config_cmds.reply, mpi_reply, - mpi_reply->MsgLength*4); - } - ioc->config_cmds.status &= ~MPT3_CMD_PENDING; -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - _config_display_some_debug(ioc, smid, "config_done", mpi_reply); -#endif - ioc->config_cmds.smid = USHRT_MAX; - complete(&ioc->config_cmds.done); - return 1; -} - -/** - * _config_request - main routine for sending config page requests - * @ioc: per adapter object - * @mpi_request: request message frame - * @mpi_reply: reply mf payload returned from firmware - * @timeout: timeout in seconds - * @config_page: contents of the config page - * @config_page_sz: size of config page - * Context: sleep - * - * A generic API for config page requests to firmware. - * - * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling - * this API. - * - * The callback index is set inside `ioc->config_cb_idx. - * - * Returns 0 for success, non-zero for failure. - */ -static int -_config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t - *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout, - void *config_page, u16 config_page_sz) -{ - u16 smid; - u32 ioc_state; - unsigned long timeleft; - Mpi2ConfigRequest_t *config_request; - int r; - u8 retry_count, issue_host_reset = 0; - u16 wait_state_count; - struct config_request mem; - u32 ioc_status = UINT_MAX; - - mutex_lock(&ioc->config_cmds.mutex); - if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: config_cmd in use\n", - ioc->name, __func__); - mutex_unlock(&ioc->config_cmds.mutex); - return -EAGAIN; - } - - retry_count = 0; - memset(&mem, 0, sizeof(struct config_request)); - - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - - if (config_page) { - mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion; - mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber; - mpi_request->Header.PageType = mpi_reply->Header.PageType; - mpi_request->Header.PageLength = mpi_reply->Header.PageLength; - mpi_request->ExtPageLength = mpi_reply->ExtPageLength; - mpi_request->ExtPageType = mpi_reply->ExtPageType; - if (mpi_request->Header.PageLength) - mem.sz = mpi_request->Header.PageLength * 4; - else - mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; - r = _config_alloc_config_dma_memory(ioc, &mem); - if (r != 0) - goto out; - if (mpi_request->Action == - MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT || - mpi_request->Action == - MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) { - ioc->base_add_sg_single(&mpi_request->PageBufferSGE, - MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz, - mem.page_dma); - memcpy(mem.page, config_page, min_t(u16, mem.sz, - config_page_sz)); - } else { - memset(config_page, 0, config_page_sz); - ioc->base_add_sg_single(&mpi_request->PageBufferSGE, - MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma); - memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz)); - } - } - - retry_config: - if (retry_count) { - if (retry_count > 2) { /* attempt only 2 retries */ - r = -EFAULT; - goto free_mem; - } - pr_info(MPT3SAS_FMT "%s: attempting retry (%d)\n", - ioc->name, __func__, retry_count); - } - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - ioc->config_cmds.status = MPT3_CMD_NOT_USED; - r = -EFAULT; - goto free_mem; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, __func__, wait_state_count); - } - if (wait_state_count) - pr_info(MPT3SAS_FMT "%s: ioc is operational\n", - ioc->name, __func__); - - smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - ioc->config_cmds.status = MPT3_CMD_NOT_USED; - r = -EAGAIN; - goto free_mem; - } - - r = 0; - memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t)); - ioc->config_cmds.status = MPT3_CMD_PENDING; - config_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->config_cmds.smid = smid; - memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t)); -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - _config_display_some_debug(ioc, smid, "config_request", NULL); -#endif - init_completion(&ioc->config_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->config_cmds.done, - timeout*HZ); - if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2ConfigRequest_t)/4); - retry_count++; - if (ioc->config_cmds.smid == smid) - mpt3sas_base_free_smid(ioc, smid); - if ((ioc->shost_recovery) || (ioc->config_cmds.status & - MPT3_CMD_RESET) || ioc->pci_error_recovery) - goto retry_config; - issue_host_reset = 1; - r = -EFAULT; - goto free_mem; - } - - if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) { - memcpy(mpi_reply, ioc->config_cmds.reply, - sizeof(Mpi2ConfigReply_t)); - - /* Reply Frame Sanity Checks to workaround FW issues */ - if ((mpi_request->Header.PageType & 0xF) != - (mpi_reply->Header.PageType & 0xF)) { - _debug_dump_mf(mpi_request, ioc->request_sz/4); - _debug_dump_reply(mpi_reply, ioc->request_sz/4); - panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \ - " mpi_reply mismatch: Requested PageType(0x%02x)" \ - " Reply PageType(0x%02x)\n", \ - ioc->name, __func__, - (mpi_request->Header.PageType & 0xF), - (mpi_reply->Header.PageType & 0xF)); - } - - if (((mpi_request->Header.PageType & 0xF) == - MPI2_CONFIG_PAGETYPE_EXTENDED) && - mpi_request->ExtPageType != mpi_reply->ExtPageType) { - _debug_dump_mf(mpi_request, ioc->request_sz/4); - _debug_dump_reply(mpi_reply, ioc->request_sz/4); - panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \ - " mpi_reply mismatch: Requested ExtPageType(0x%02x)" - " Reply ExtPageType(0x%02x)\n", - ioc->name, __func__, mpi_request->ExtPageType, - mpi_reply->ExtPageType); - } - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) - & MPI2_IOCSTATUS_MASK; - } - - if (retry_count) - pr_info(MPT3SAS_FMT "%s: retry (%d) completed!!\n", \ - ioc->name, __func__, retry_count); - - if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) && - config_page && mpi_request->Action == - MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) { - u8 *p = (u8 *)mem.page; - - /* Config Page Sanity Checks to workaround FW issues */ - if (p) { - if ((mpi_request->Header.PageType & 0xF) != - (p[3] & 0xF)) { - _debug_dump_mf(mpi_request, ioc->request_sz/4); - _debug_dump_reply(mpi_reply, ioc->request_sz/4); - _debug_dump_config(p, min_t(u16, mem.sz, - config_page_sz)/4); - panic(KERN_WARNING MPT3SAS_FMT - "%s: Firmware BUG:" \ - " config page mismatch:" - " Requested PageType(0x%02x)" - " Reply PageType(0x%02x)\n", - ioc->name, __func__, - (mpi_request->Header.PageType & 0xF), - (p[3] & 0xF)); - } - - if (((mpi_request->Header.PageType & 0xF) == - MPI2_CONFIG_PAGETYPE_EXTENDED) && - (mpi_request->ExtPageType != p[6])) { - _debug_dump_mf(mpi_request, ioc->request_sz/4); - _debug_dump_reply(mpi_reply, ioc->request_sz/4); - _debug_dump_config(p, min_t(u16, mem.sz, - config_page_sz)/4); - panic(KERN_WARNING MPT3SAS_FMT - "%s: Firmware BUG:" \ - " config page mismatch:" - " Requested ExtPageType(0x%02x)" - " Reply ExtPageType(0x%02x)\n", - ioc->name, __func__, - mpi_request->ExtPageType, p[6]); - } - } - memcpy(config_page, mem.page, min_t(u16, mem.sz, - config_page_sz)); - } - - free_mem: - if (config_page) - _config_free_config_dma_memory(ioc, &mem); - out: - ioc->config_cmds.status = MPT3_CMD_NOT_USED; - mutex_unlock(&ioc->config_cmds.mutex); - - if (issue_host_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - return r; -} - -/** - * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @sz: size of buffer passed in config_page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page, - u16 sz) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; - mpi_request.Header.PageNumber = 7; - mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sz); - out: - return r; -} - -/** - * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, - struct Mpi2ManufacturingPage10_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; - mpi_request.Header.PageNumber = 10; - mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, - struct Mpi2ManufacturingPage11_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; - mpi_request.Header.PageNumber = 11; - mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, - struct Mpi2ManufacturingPage11_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; - mpi_request.Header.PageNumber = 11; - mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_bios_pg2 - obtain bios page 2 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; - mpi_request.Header.PageNumber = 2; - mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_bios_pg3 - obtain bios page 3 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2BiosPage3_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; - mpi_request.Header.PageNumber = 3; - mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_set_iounit_pg1 - set iounit page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; - mpi_request.Header.PageNumber = 8; - mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_HANDLE or HANDLE - * @handle: device handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page, - u32 form, u32 handle) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; - mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; - mpi_request.Header.PageNumber = 0; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_HANDLE or HANDLE - * @handle: device handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page, - u32 form, u32 handle) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; - mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION; - mpi_request.Header.PageNumber = 1; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host - * @ioc: per adapter object - * @num_phys: pointer returned with the number of phys - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - u16 ioc_status; - Mpi2ConfigReply_t mpi_reply; - Mpi2SasIOUnitPage0_t config_page; - - *num_phys = 0; - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, &mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, &mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, - sizeof(Mpi2SasIOUnitPage0_t)); - if (!r) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) - *num_phys = config_page.NumPhys; - } - out: - return r; -} - -/** - * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @sz: size of buffer passed in config_page - * Context: sleep. - * - * Calling function should call config_get_number_hba_phys prior to - * this function, so enough memory is allocated for config_page. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, - u16 sz) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); - out: - return r; -} - -/** - * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @sz: size of buffer passed in config_page - * Context: sleep. - * - * Calling function should call config_get_number_hba_phys prior to - * this function, so enough memory is allocated for config_page. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, - u16 sz) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); - out: - return r; -} - -/** - * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @sz: size of buffer passed in config_page - * Context: sleep. - * - * Calling function should call config_get_number_hba_phys prior to - * this function, so enough memory is allocated for config_page. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, - u16 sz) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; - _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); - out: - return r; -} - -/** - * mpt3sas_config_get_expander_pg0 - obtain expander page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_HANDLE or HANDLE - * @handle: expander handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_expander_pg1 - obtain expander page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @phy_number: phy number - * @handle: expander handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, - u16 handle) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = - cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM | - (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_HANDLE or HANDLE - * @handle: expander handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_phy_pg0 - obtain phy page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @phy_number: phy number - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = - cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_phy_pg1 - obtain phy page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @phy_number: phy number - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = - cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_HANDLE or HANDLE - * @handle: volume handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, - u32 handle) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume - * @ioc: per adapter object - * @handle: volume handle - * @num_pds: returns pds count - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u8 *num_pds) -{ - Mpi2ConfigRequest_t mpi_request; - Mpi2RaidVolPage0_t config_page; - Mpi2ConfigReply_t mpi_reply; - int r; - u16 ioc_status; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - *num_pds = 0; - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, &mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = - cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, &mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, - sizeof(Mpi2RaidVolPage0_t)); - if (!r) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) - *num_pds = config_page.NumPhysDisks; - } - - out: - return r; -} - -/** - * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_HANDLE or HANDLE - * @handle: volume handle - * @sz: size of buffer passed in config_page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, - u32 handle, u16 sz) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); - out: - return r; -} - -/** - * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE - * @form_specific: specific to the form - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form, - u32 form_specific) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | form_specific); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_volume_handle - returns volume handle for give hidden - * raid components - * @ioc: per adapter object - * @pd_handle: phys disk handle - * @volume_handle: volume handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle, - u16 *volume_handle) -{ - Mpi2RaidConfigurationPage0_t *config_page = NULL; - Mpi2ConfigRequest_t mpi_request; - Mpi2ConfigReply_t mpi_reply; - int r, i, config_page_sz; - u16 ioc_status; - int config_num; - u16 element_type; - u16 phys_disk_dev_handle; - - *volume_handle = 0; - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG; - mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION; - mpi_request.Header.PageNumber = 0; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, &mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4); - config_page = kmalloc(config_page_sz, GFP_KERNEL); - if (!config_page) { - r = -1; - goto out; - } - - config_num = 0xff; - while (1) { - mpi_request.PageAddress = cpu_to_le32(config_num + - MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM); - r = _config_request(ioc, &mpi_request, &mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - config_page_sz); - if (r) - goto out; - r = -1; - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - goto out; - for (i = 0; i < config_page->NumElements; i++) { - element_type = le16_to_cpu(config_page-> - ConfigElement[i].ElementFlags) & - MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE; - if (element_type == - MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT || - element_type == - MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) { - phys_disk_dev_handle = - le16_to_cpu(config_page->ConfigElement[i]. - PhysDiskDevHandle); - if (phys_disk_dev_handle == pd_handle) { - *volume_handle = - le16_to_cpu(config_page-> - ConfigElement[i].VolDevHandle); - r = 0; - goto out; - } - } else if (element_type == - MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) { - *volume_handle = 0; - r = 0; - goto out; - } - } - config_num = config_page->ConfigNum; - } - out: - kfree(config_page); - return r; -} - -/** - * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle - * @ioc: per adapter object - * @volume_handle: volume handle - * @wwid: volume wwid - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle, - u64 *wwid) -{ - Mpi2ConfigReply_t mpi_reply; - Mpi2RaidVolPage1_t raid_vol_pg1; - - *wwid = 0; - if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, - &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, - volume_handle))) { - *wwid = le64_to_cpu(raid_vol_pg1.WWID); - return 0; - } else - return -1; -} diff --git a/addons/mpt3sas/src/3.10.108/mpt3sas_ctl.c b/addons/mpt3sas/src/3.10.108/mpt3sas_ctl.c deleted file mode 100644 index 0b402b6f..00000000 --- a/addons/mpt3sas/src/3.10.108/mpt3sas_ctl.c +++ /dev/null @@ -1,3282 +0,0 @@ -/* - * Management Module Support for MPT (Message Passing Technology) based - * controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_ctl.c - * Copyright (C) 2012 LSI Corporation - * (mailto:DL-MPTFusionLinux@lsi.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "mpt3sas_base.h" -#include "mpt3sas_ctl.h" - - -static struct fasync_struct *async_queue; -static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait); - - -/** - * enum block_state - blocking state - * @NON_BLOCKING: non blocking - * @BLOCKING: blocking - * - * These states are for ioctls that need to wait for a response - * from firmware, so they probably require sleep. - */ -enum block_state { - NON_BLOCKING, - BLOCKING, -}; - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING -/** - * _ctl_sas_device_find_by_handle - sas device search - * @ioc: per adapter object - * @handle: sas device handle (assigned by firmware) - * Context: Calling function should acquire ioc->sas_device_lock - * - * This searches for sas_device based on sas_address, then return sas_device - * object. - */ -static struct _sas_device * -_ctl_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _sas_device *sas_device, *r; - - r = NULL; - list_for_each_entry(sas_device, &ioc->sas_device_list, list) { - if (sas_device->handle != handle) - continue; - r = sas_device; - goto out; - } - - out: - return r; -} - -/** - * _ctl_display_some_debug - debug routine - * @ioc: per adapter object - * @smid: system request message index - * @calling_function_name: string pass from calling function - * @mpi_reply: reply message frame - * Context: none. - * - * Function for displaying debug info helpful when debugging issues - * in this module. - */ -static void -_ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid, - char *calling_function_name, MPI2DefaultReply_t *mpi_reply) -{ - Mpi2ConfigRequest_t *mpi_request; - char *desc = NULL; - - if (!(ioc->logging_level & MPT_DEBUG_IOCTL)) - return; - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - switch (mpi_request->Function) { - case MPI2_FUNCTION_SCSI_IO_REQUEST: - { - Mpi2SCSIIORequest_t *scsi_request = - (Mpi2SCSIIORequest_t *)mpi_request; - - snprintf(ioc->tmp_string, MPT_STRING_LENGTH, - "scsi_io, cmd(0x%02x), cdb_len(%d)", - scsi_request->CDB.CDB32[0], - le16_to_cpu(scsi_request->IoFlags) & 0xF); - desc = ioc->tmp_string; - break; - } - case MPI2_FUNCTION_SCSI_TASK_MGMT: - desc = "task_mgmt"; - break; - case MPI2_FUNCTION_IOC_INIT: - desc = "ioc_init"; - break; - case MPI2_FUNCTION_IOC_FACTS: - desc = "ioc_facts"; - break; - case MPI2_FUNCTION_CONFIG: - { - Mpi2ConfigRequest_t *config_request = - (Mpi2ConfigRequest_t *)mpi_request; - - snprintf(ioc->tmp_string, MPT_STRING_LENGTH, - "config, type(0x%02x), ext_type(0x%02x), number(%d)", - (config_request->Header.PageType & - MPI2_CONFIG_PAGETYPE_MASK), config_request->ExtPageType, - config_request->Header.PageNumber); - desc = ioc->tmp_string; - break; - } - case MPI2_FUNCTION_PORT_FACTS: - desc = "port_facts"; - break; - case MPI2_FUNCTION_PORT_ENABLE: - desc = "port_enable"; - break; - case MPI2_FUNCTION_EVENT_NOTIFICATION: - desc = "event_notification"; - break; - case MPI2_FUNCTION_FW_DOWNLOAD: - desc = "fw_download"; - break; - case MPI2_FUNCTION_FW_UPLOAD: - desc = "fw_upload"; - break; - case MPI2_FUNCTION_RAID_ACTION: - desc = "raid_action"; - break; - case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH: - { - Mpi2SCSIIORequest_t *scsi_request = - (Mpi2SCSIIORequest_t *)mpi_request; - - snprintf(ioc->tmp_string, MPT_STRING_LENGTH, - "raid_pass, cmd(0x%02x), cdb_len(%d)", - scsi_request->CDB.CDB32[0], - le16_to_cpu(scsi_request->IoFlags) & 0xF); - desc = ioc->tmp_string; - break; - } - case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: - desc = "sas_iounit_cntl"; - break; - case MPI2_FUNCTION_SATA_PASSTHROUGH: - desc = "sata_pass"; - break; - case MPI2_FUNCTION_DIAG_BUFFER_POST: - desc = "diag_buffer_post"; - break; - case MPI2_FUNCTION_DIAG_RELEASE: - desc = "diag_release"; - break; - case MPI2_FUNCTION_SMP_PASSTHROUGH: - desc = "smp_passthrough"; - break; - } - - if (!desc) - return; - - pr_info(MPT3SAS_FMT "%s: %s, smid(%d)\n", - ioc->name, calling_function_name, desc, smid); - - if (!mpi_reply) - return; - - if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) - pr_info(MPT3SAS_FMT - "\tiocstatus(0x%04x), loginfo(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo)); - - if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || - mpi_request->Function == - MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { - Mpi2SCSIIOReply_t *scsi_reply = - (Mpi2SCSIIOReply_t *)mpi_reply; - struct _sas_device *sas_device = NULL; - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _ctl_sas_device_find_by_handle(ioc, - le16_to_cpu(scsi_reply->DevHandle)); - if (sas_device) { - pr_warn(MPT3SAS_FMT "\tsas_address(0x%016llx), phy(%d)\n", - ioc->name, (unsigned long long) - sas_device->sas_address, sas_device->phy); - pr_warn(MPT3SAS_FMT - "\tenclosure_logical_id(0x%016llx), slot(%d)\n", - ioc->name, (unsigned long long) - sas_device->enclosure_logical_id, sas_device->slot); - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (scsi_reply->SCSIState || scsi_reply->SCSIStatus) - pr_info(MPT3SAS_FMT - "\tscsi_state(0x%02x), scsi_status" - "(0x%02x)\n", ioc->name, - scsi_reply->SCSIState, - scsi_reply->SCSIStatus); - } -} - -#endif - -/** - * mpt3sas_ctl_done - ctl module completion routine - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: none. - * - * The callback handler when using ioc->ctl_cb_idx. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - Mpi2SCSIIOReply_t *scsiio_reply; - const void *sense_data; - u32 sz; - - if (ioc->ctl_cmds.status == MPT3_CMD_NOT_USED) - return 1; - if (ioc->ctl_cmds.smid != smid) - return 1; - ioc->ctl_cmds.status |= MPT3_CMD_COMPLETE; - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (mpi_reply) { - memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); - ioc->ctl_cmds.status |= MPT3_CMD_REPLY_VALID; - /* get sense data */ - if (mpi_reply->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || - mpi_reply->Function == - MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { - scsiio_reply = (Mpi2SCSIIOReply_t *)mpi_reply; - if (scsiio_reply->SCSIState & - MPI2_SCSI_STATE_AUTOSENSE_VALID) { - sz = min_t(u32, SCSI_SENSE_BUFFERSIZE, - le32_to_cpu(scsiio_reply->SenseCount)); - sense_data = mpt3sas_base_get_sense_buffer(ioc, - smid); - memcpy(ioc->ctl_cmds.sense, sense_data, sz); - } - } - } -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply); -#endif - ioc->ctl_cmds.status &= ~MPT3_CMD_PENDING; - complete(&ioc->ctl_cmds.done); - return 1; -} - -/** - * _ctl_check_event_type - determines when an event needs logging - * @ioc: per adapter object - * @event: firmware event - * - * The bitmask in ioc->event_type[] indicates which events should be - * be saved in the driver event_log. This bitmask is set by application. - * - * Returns 1 when event should be captured, or zero means no match. - */ -static int -_ctl_check_event_type(struct MPT3SAS_ADAPTER *ioc, u16 event) -{ - u16 i; - u32 desired_event; - - if (event >= 128 || !event || !ioc->event_log) - return 0; - - desired_event = (1 << (event % 32)); - if (!desired_event) - desired_event = 1; - i = event / 32; - return desired_event & ioc->event_type[i]; -} - -/** - * mpt3sas_ctl_add_to_event_log - add event - * @ioc: per adapter object - * @mpi_reply: reply message frame - * - * Return nothing. - */ -void -mpt3sas_ctl_add_to_event_log(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventNotificationReply_t *mpi_reply) -{ - struct MPT3_IOCTL_EVENTS *event_log; - u16 event; - int i; - u32 sz, event_data_sz; - u8 send_aen = 0; - - if (!ioc->event_log) - return; - - event = le16_to_cpu(mpi_reply->Event); - - if (_ctl_check_event_type(ioc, event)) { - - /* insert entry into circular event_log */ - i = ioc->event_context % MPT3SAS_CTL_EVENT_LOG_SIZE; - event_log = ioc->event_log; - event_log[i].event = event; - event_log[i].context = ioc->event_context++; - - event_data_sz = le16_to_cpu(mpi_reply->EventDataLength)*4; - sz = min_t(u32, event_data_sz, MPT3_EVENT_DATA_SIZE); - memset(event_log[i].data, 0, MPT3_EVENT_DATA_SIZE); - memcpy(event_log[i].data, mpi_reply->EventData, sz); - send_aen = 1; - } - - /* This aen_event_read_flag flag is set until the - * application has read the event log. - * For MPI2_EVENT_LOG_ENTRY_ADDED, we always notify. - */ - if (event == MPI2_EVENT_LOG_ENTRY_ADDED || - (send_aen && !ioc->aen_event_read_flag)) { - ioc->aen_event_read_flag = 1; - wake_up_interruptible(&ctl_poll_wait); - if (async_queue) - kill_fasync(&async_queue, SIGIO, POLL_IN); - } -} - -/** - * mpt3sas_ctl_event_callback - firmware event handler (called at ISR time) - * @ioc: per adapter object - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: interrupt. - * - * This function merely adds a new work task into ioc->firmware_event_thread. - * The tasks are worked from _firmware_event_work in user context. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, - u32 reply) -{ - Mpi2EventNotificationReply_t *mpi_reply; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - mpt3sas_ctl_add_to_event_log(ioc, mpi_reply); - return 1; -} - -/** - * _ctl_verify_adapter - validates ioc_number passed from application - * @ioc: per adapter object - * @iocpp: The ioc pointer is returned in this. - * - * Return (-1) means error, else ioc_number. - */ -static int -_ctl_verify_adapter(int ioc_number, struct MPT3SAS_ADAPTER **iocpp) -{ - struct MPT3SAS_ADAPTER *ioc; - - list_for_each_entry(ioc, &mpt3sas_ioc_list, list) { - if (ioc->id != ioc_number) - continue; - *iocpp = ioc; - return ioc_number; - } - *iocpp = NULL; - return -1; -} - -/** - * mpt3sas_ctl_reset_handler - reset callback handler (for ctl) - * @ioc: per adapter object - * @reset_phase: phase - * - * The handler for doing any required cleanup or initialization. - * - * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET, - * MPT3_IOC_DONE_RESET - */ -void -mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase) -{ - int i; - u8 issue_reset; - - switch (reset_phase) { - case MPT3_IOC_PRE_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__)); - for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { - if (!(ioc->diag_buffer_status[i] & - MPT3_DIAG_BUFFER_IS_REGISTERED)) - continue; - if ((ioc->diag_buffer_status[i] & - MPT3_DIAG_BUFFER_IS_RELEASED)) - continue; - mpt3sas_send_diag_release(ioc, i, &issue_reset); - } - break; - case MPT3_IOC_AFTER_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__)); - if (ioc->ctl_cmds.status & MPT3_CMD_PENDING) { - ioc->ctl_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->ctl_cmds.smid); - complete(&ioc->ctl_cmds.done); - } - break; - case MPT3_IOC_DONE_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__)); - - for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { - if (!(ioc->diag_buffer_status[i] & - MPT3_DIAG_BUFFER_IS_REGISTERED)) - continue; - if ((ioc->diag_buffer_status[i] & - MPT3_DIAG_BUFFER_IS_RELEASED)) - continue; - ioc->diag_buffer_status[i] |= - MPT3_DIAG_BUFFER_IS_DIAG_RESET; - } - break; - } -} - -/** - * _ctl_fasync - - * @fd - - * @filep - - * @mode - - * - * Called when application request fasyn callback handler. - */ -static int -_ctl_fasync(int fd, struct file *filep, int mode) -{ - return fasync_helper(fd, filep, mode, &async_queue); -} - -/** - * _ctl_poll - - * @file - - * @wait - - * - */ -static unsigned int -_ctl_poll(struct file *filep, poll_table *wait) -{ - struct MPT3SAS_ADAPTER *ioc; - - poll_wait(filep, &ctl_poll_wait, wait); - - list_for_each_entry(ioc, &mpt3sas_ioc_list, list) { - if (ioc->aen_event_read_flag) - return POLLIN | POLLRDNORM; - } - return 0; -} - -/** - * _ctl_set_task_mid - assign an active smid to tm request - * @ioc: per adapter object - * @karg - (struct mpt3_ioctl_command) - * @tm_request - pointer to mf from user space - * - * Returns 0 when an smid if found, else fail. - * during failure, the reply frame is filled. - */ -static int -_ctl_set_task_mid(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command *karg, - Mpi2SCSITaskManagementRequest_t *tm_request) -{ - u8 found = 0; - u16 i; - u16 handle; - struct scsi_cmnd *scmd; - struct MPT3SAS_DEVICE *priv_data; - unsigned long flags; - Mpi2SCSITaskManagementReply_t *tm_reply; - u32 sz; - u32 lun; - char *desc = NULL; - - if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) - desc = "abort_task"; - else if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) - desc = "query_task"; - else - return 0; - - lun = scsilun_to_int((struct scsi_lun *)tm_request->LUN); - - handle = le16_to_cpu(tm_request->DevHandle); - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - for (i = ioc->scsiio_depth; i && !found; i--) { - scmd = ioc->scsi_lookup[i - 1].scmd; - if (scmd == NULL || scmd->device == NULL || - scmd->device->hostdata == NULL) - continue; - if (lun != scmd->device->lun) - continue; - priv_data = scmd->device->hostdata; - if (priv_data->sas_target == NULL) - continue; - if (priv_data->sas_target->handle != handle) - continue; - tm_request->TaskMID = cpu_to_le16(ioc->scsi_lookup[i - 1].smid); - found = 1; - } - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - - if (!found) { - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), lun(%d), no active mid!!\n", - ioc->name, - desc, le16_to_cpu(tm_request->DevHandle), lun)); - tm_reply = ioc->ctl_cmds.reply; - tm_reply->DevHandle = tm_request->DevHandle; - tm_reply->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; - tm_reply->TaskType = tm_request->TaskType; - tm_reply->MsgLength = sizeof(Mpi2SCSITaskManagementReply_t)/4; - tm_reply->VP_ID = tm_request->VP_ID; - tm_reply->VF_ID = tm_request->VF_ID; - sz = min_t(u32, karg->max_reply_bytes, ioc->reply_sz); - if (copy_to_user(karg->reply_frame_buf_ptr, ioc->ctl_cmds.reply, - sz)) - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - return 1; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), lun(%d), task_mid(%d)\n", ioc->name, - desc, le16_to_cpu(tm_request->DevHandle), lun, - le16_to_cpu(tm_request->TaskMID))); - return 0; -} - -/** - * _ctl_do_mpt_command - main handler for MPT3COMMAND opcode - * @ioc: per adapter object - * @karg - (struct mpt3_ioctl_command) - * @mf - pointer to mf in user space - */ -static long -_ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, - void __user *mf) -{ - MPI2RequestHeader_t *mpi_request = NULL, *request; - MPI2DefaultReply_t *mpi_reply; - u32 ioc_state; - u16 ioc_status; - u16 smid; - unsigned long timeout, timeleft; - u8 issue_reset; - u32 sz; - void *psge; - void *data_out = NULL; - dma_addr_t data_out_dma = 0; - size_t data_out_sz = 0; - void *data_in = NULL; - dma_addr_t data_in_dma = 0; - size_t data_in_sz = 0; - long ret; - u16 wait_state_count; - - issue_reset = 0; - - if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n", - ioc->name, __func__); - ret = -EAGAIN; - goto out; - } - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - ret = -EFAULT; - goto out; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, - __func__, wait_state_count); - } - if (wait_state_count) - pr_info(MPT3SAS_FMT "%s: ioc is operational\n", - ioc->name, __func__); - - mpi_request = kzalloc(ioc->request_sz, GFP_KERNEL); - if (!mpi_request) { - pr_err(MPT3SAS_FMT - "%s: failed obtaining a memory for mpi_request\n", - ioc->name, __func__); - ret = -ENOMEM; - goto out; - } - - /* Check for overflow and wraparound */ - if (karg.data_sge_offset * 4 > ioc->request_sz || - karg.data_sge_offset > (UINT_MAX / 4)) { - ret = -EINVAL; - goto out; - } - - /* copy in request message frame from user */ - if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, __LINE__, - __func__); - ret = -EFAULT; - goto out; - } - - if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { - smid = mpt3sas_base_get_smid_hpr(ioc, ioc->ctl_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - ret = -EAGAIN; - goto out; - } - } else { - - smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - ret = -EAGAIN; - goto out; - } - } - - ret = 0; - ioc->ctl_cmds.status = MPT3_CMD_PENDING; - memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); - request = mpt3sas_base_get_msg_frame(ioc, smid); - memcpy(request, mpi_request, karg.data_sge_offset*4); - ioc->ctl_cmds.smid = smid; - data_out_sz = karg.data_out_size; - data_in_sz = karg.data_in_size; - - if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || - mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { - if (!le16_to_cpu(mpi_request->FunctionDependent1) || - le16_to_cpu(mpi_request->FunctionDependent1) > - ioc->facts.MaxDevHandle) { - ret = -EINVAL; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - } - - /* obtain dma-able memory for data transfer */ - if (data_out_sz) /* WRITE */ { - data_out = pci_alloc_consistent(ioc->pdev, data_out_sz, - &data_out_dma); - if (!data_out) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - ret = -ENOMEM; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - if (copy_from_user(data_out, karg.data_out_buf_ptr, - data_out_sz)) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - ret = -EFAULT; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - } - - if (data_in_sz) /* READ */ { - data_in = pci_alloc_consistent(ioc->pdev, data_in_sz, - &data_in_dma); - if (!data_in) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - ret = -ENOMEM; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - } - - psge = (void *)request + (karg.data_sge_offset*4); - - /* send command to firmware */ -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - _ctl_display_some_debug(ioc, smid, "ctl_request", NULL); -#endif - - init_completion(&ioc->ctl_cmds.done); - switch (mpi_request->Function) { - case MPI2_FUNCTION_SCSI_IO_REQUEST: - case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH: - { - Mpi2SCSIIORequest_t *scsiio_request = - (Mpi2SCSIIORequest_t *)request; - scsiio_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; - scsiio_request->SenseBufferLowAddress = - mpt3sas_base_get_sense_buffer_dma(ioc, smid); - memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE); - ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, - data_in_dma, data_in_sz); - - if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) - mpt3sas_base_put_smid_scsi_io(ioc, smid, - le16_to_cpu(mpi_request->FunctionDependent1)); - else - mpt3sas_base_put_smid_default(ioc, smid); - break; - } - case MPI2_FUNCTION_SCSI_TASK_MGMT: - { - Mpi2SCSITaskManagementRequest_t *tm_request = - (Mpi2SCSITaskManagementRequest_t *)request; - - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "TASK_MGMT: handle(0x%04x), task_type(0x%02x)\n", - ioc->name, - le16_to_cpu(tm_request->DevHandle), tm_request->TaskType)); - - if (tm_request->TaskType == - MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK || - tm_request->TaskType == - MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) { - if (_ctl_set_task_mid(ioc, &karg, tm_request)) { - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - } - - mpt3sas_scsih_set_tm_flag(ioc, le16_to_cpu( - tm_request->DevHandle)); - ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, - data_in_dma, data_in_sz); - mpt3sas_base_put_smid_hi_priority(ioc, smid); - break; - } - case MPI2_FUNCTION_SMP_PASSTHROUGH: - { - Mpi2SmpPassthroughRequest_t *smp_request = - (Mpi2SmpPassthroughRequest_t *)mpi_request; - u8 *data; - - /* ioc determines which port to use */ - smp_request->PhysicalPort = 0xFF; - if (smp_request->PassthroughFlags & - MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE) - data = (u8 *)&smp_request->SGL; - else { - if (unlikely(data_out == NULL)) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - mpt3sas_base_free_smid(ioc, smid); - ret = -EINVAL; - goto out; - } - data = data_out; - } - - if (data[1] == 0x91 && (data[10] == 1 || data[10] == 2)) { - ioc->ioc_link_reset_in_progress = 1; - ioc->ignore_loginfos = 1; - } - ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, - data_in_sz); - mpt3sas_base_put_smid_default(ioc, smid); - break; - } - case MPI2_FUNCTION_SATA_PASSTHROUGH: - case MPI2_FUNCTION_FW_DOWNLOAD: - case MPI2_FUNCTION_FW_UPLOAD: - { - ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, - data_in_sz); - mpt3sas_base_put_smid_default(ioc, smid); - break; - } - case MPI2_FUNCTION_TOOLBOX: - { - Mpi2ToolboxCleanRequest_t *toolbox_request = - (Mpi2ToolboxCleanRequest_t *)mpi_request; - - if (toolbox_request->Tool == MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL) { - ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, - data_in_dma, data_in_sz); - } else { - ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, - data_in_dma, data_in_sz); - } - mpt3sas_base_put_smid_default(ioc, smid); - break; - } - case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: - { - Mpi2SasIoUnitControlRequest_t *sasiounit_request = - (Mpi2SasIoUnitControlRequest_t *)mpi_request; - - if (sasiounit_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET - || sasiounit_request->Operation == - MPI2_SAS_OP_PHY_LINK_RESET) { - ioc->ioc_link_reset_in_progress = 1; - ioc->ignore_loginfos = 1; - } - /* drop to default case for posting the request */ - } - default: - ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, - data_in_dma, data_in_sz); - mpt3sas_base_put_smid_default(ioc, smid); - break; - } - - if (karg.timeout < MPT3_IOCTL_DEFAULT_TIMEOUT) - timeout = MPT3_IOCTL_DEFAULT_TIMEOUT; - else - timeout = karg.timeout; - timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, - timeout*HZ); - if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { - Mpi2SCSITaskManagementRequest_t *tm_request = - (Mpi2SCSITaskManagementRequest_t *)mpi_request; - mpt3sas_scsih_clear_tm_flag(ioc, le16_to_cpu( - tm_request->DevHandle)); - mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT); - } else if ((mpi_request->Function == MPI2_FUNCTION_SMP_PASSTHROUGH || - mpi_request->Function == MPI2_FUNCTION_SAS_IO_UNIT_CONTROL) && - ioc->ioc_link_reset_in_progress) { - ioc->ioc_link_reset_in_progress = 0; - ioc->ignore_loginfos = 0; - } - if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name, - __func__); - _debug_dump_mf(mpi_request, karg.data_sge_offset); - if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - mpi_reply = ioc->ctl_cmds.reply; - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT && - (ioc->logging_level & MPT_DEBUG_TM)) { - Mpi2SCSITaskManagementReply_t *tm_reply = - (Mpi2SCSITaskManagementReply_t *)mpi_reply; - - pr_info(MPT3SAS_FMT "TASK_MGMT: " \ - "IOCStatus(0x%04x), IOCLogInfo(0x%08x), " - "TerminationCount(0x%08x)\n", ioc->name, - le16_to_cpu(tm_reply->IOCStatus), - le32_to_cpu(tm_reply->IOCLogInfo), - le32_to_cpu(tm_reply->TerminationCount)); - } -#endif - /* copy out xdata to user */ - if (data_in_sz) { - if (copy_to_user(karg.data_in_buf_ptr, data_in, - data_in_sz)) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - ret = -ENODATA; - goto out; - } - } - - /* copy out reply message frame to user */ - if (karg.max_reply_bytes) { - sz = min_t(u32, karg.max_reply_bytes, ioc->reply_sz); - if (copy_to_user(karg.reply_frame_buf_ptr, ioc->ctl_cmds.reply, - sz)) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - ret = -ENODATA; - goto out; - } - } - - /* copy out sense to user */ - if (karg.max_sense_bytes && (mpi_request->Function == - MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function == - MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { - sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE); - if (copy_to_user(karg.sense_data_ptr, ioc->ctl_cmds.sense, - sz)) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - ret = -ENODATA; - goto out; - } - } - - issue_host_reset: - if (issue_reset) { - ret = -ENODATA; - if ((mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || - mpi_request->Function == - MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || - mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH)) { - pr_info(MPT3SAS_FMT "issue target reset: handle = (0x%04x)\n", - ioc->name, - le16_to_cpu(mpi_request->FunctionDependent1)); - mpt3sas_halt_firmware(ioc); - mpt3sas_scsih_issue_tm(ioc, - le16_to_cpu(mpi_request->FunctionDependent1), 0, 0, - 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30, - 0, TM_MUTEX_ON); - } else - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - } - - out: - - /* free memory associated with sg buffers */ - if (data_in) - pci_free_consistent(ioc->pdev, data_in_sz, data_in, - data_in_dma); - - if (data_out) - pci_free_consistent(ioc->pdev, data_out_sz, data_out, - data_out_dma); - - kfree(mpi_request); - ioc->ctl_cmds.status = MPT3_CMD_NOT_USED; - return ret; -} - -/** - * _ctl_getiocinfo - main handler for MPT3IOCINFO opcode - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_ioctl_iocinfo karg; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, - __func__)); - - memset(&karg, 0 , sizeof(karg)); - karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3; - if (ioc->pfacts) - karg.port_number = ioc->pfacts[0].PortNumber; - karg.hw_rev = ioc->pdev->revision; - karg.pci_id = ioc->pdev->device; - karg.subsystem_device = ioc->pdev->subsystem_device; - karg.subsystem_vendor = ioc->pdev->subsystem_vendor; - karg.pci_information.u.bits.bus = ioc->pdev->bus->number; - karg.pci_information.u.bits.device = PCI_SLOT(ioc->pdev->devfn); - karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn); - karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus); - karg.firmware_version = ioc->facts.FWVersion.Word; - strcpy(karg.driver_version, MPT3SAS_DRIVER_NAME); - strcat(karg.driver_version, "-"); - strcat(karg.driver_version, MPT3SAS_DRIVER_VERSION); - karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); - - if (copy_to_user(arg, &karg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - return 0; -} - -/** - * _ctl_eventquery - main handler for MPT3EVENTQUERY opcode - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_eventquery(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_ioctl_eventquery karg; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, - __func__)); - - karg.event_entries = MPT3SAS_CTL_EVENT_LOG_SIZE; - memcpy(karg.event_types, ioc->event_type, - MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32)); - - if (copy_to_user(arg, &karg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - return 0; -} - -/** - * _ctl_eventenable - main handler for MPT3EVENTENABLE opcode - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_eventenable(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_ioctl_eventenable karg; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, - __func__)); - - memcpy(ioc->event_type, karg.event_types, - MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32)); - mpt3sas_base_validate_event_type(ioc, ioc->event_type); - - if (ioc->event_log) - return 0; - /* initialize event_log */ - ioc->event_context = 0; - ioc->aen_event_read_flag = 0; - ioc->event_log = kcalloc(MPT3SAS_CTL_EVENT_LOG_SIZE, - sizeof(struct MPT3_IOCTL_EVENTS), GFP_KERNEL); - if (!ioc->event_log) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -ENOMEM; - } - return 0; -} - -/** - * _ctl_eventreport - main handler for MPT3EVENTREPORT opcode - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_eventreport(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_ioctl_eventreport karg; - u32 number_bytes, max_events, max; - struct mpt3_ioctl_eventreport __user *uarg = arg; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, - __func__)); - - number_bytes = karg.hdr.max_data_size - - sizeof(struct mpt3_ioctl_header); - max_events = number_bytes/sizeof(struct MPT3_IOCTL_EVENTS); - max = min_t(u32, MPT3SAS_CTL_EVENT_LOG_SIZE, max_events); - - /* If fewer than 1 event is requested, there must have - * been some type of error. - */ - if (!max || !ioc->event_log) - return -ENODATA; - - number_bytes = max * sizeof(struct MPT3_IOCTL_EVENTS); - if (copy_to_user(uarg->event_data, ioc->event_log, number_bytes)) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - /* reset flag so SIGIO can restart */ - ioc->aen_event_read_flag = 0; - return 0; -} - -/** - * _ctl_do_reset - main handler for MPT3HARDRESET opcode - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_do_reset(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_ioctl_diag_reset karg; - int retval; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - if (ioc->shost_recovery || ioc->pci_error_recovery || - ioc->is_driver_loading) - return -EAGAIN; - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, - __func__)); - - retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - pr_info(MPT3SAS_FMT "host reset: %s\n", - ioc->name, ((!retval) ? "SUCCESS" : "FAILED")); - return 0; -} - -/** - * _ctl_btdh_search_sas_device - searching for sas device - * @ioc: per adapter object - * @btdh: btdh ioctl payload - */ -static int -_ctl_btdh_search_sas_device(struct MPT3SAS_ADAPTER *ioc, - struct mpt3_ioctl_btdh_mapping *btdh) -{ - struct _sas_device *sas_device; - unsigned long flags; - int rc = 0; - - if (list_empty(&ioc->sas_device_list)) - return rc; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - list_for_each_entry(sas_device, &ioc->sas_device_list, list) { - if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF && - btdh->handle == sas_device->handle) { - btdh->bus = sas_device->channel; - btdh->id = sas_device->id; - rc = 1; - goto out; - } else if (btdh->bus == sas_device->channel && btdh->id == - sas_device->id && btdh->handle == 0xFFFF) { - btdh->handle = sas_device->handle; - rc = 1; - goto out; - } - } - out: - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return rc; -} - -/** - * _ctl_btdh_search_raid_device - searching for raid device - * @ioc: per adapter object - * @btdh: btdh ioctl payload - */ -static int -_ctl_btdh_search_raid_device(struct MPT3SAS_ADAPTER *ioc, - struct mpt3_ioctl_btdh_mapping *btdh) -{ - struct _raid_device *raid_device; - unsigned long flags; - int rc = 0; - - if (list_empty(&ioc->raid_device_list)) - return rc; - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - list_for_each_entry(raid_device, &ioc->raid_device_list, list) { - if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF && - btdh->handle == raid_device->handle) { - btdh->bus = raid_device->channel; - btdh->id = raid_device->id; - rc = 1; - goto out; - } else if (btdh->bus == raid_device->channel && btdh->id == - raid_device->id && btdh->handle == 0xFFFF) { - btdh->handle = raid_device->handle; - rc = 1; - goto out; - } - } - out: - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - return rc; -} - -/** - * _ctl_btdh_mapping - main handler for MPT3BTDHMAPPING opcode - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_btdh_mapping(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_ioctl_btdh_mapping karg; - int rc; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - rc = _ctl_btdh_search_sas_device(ioc, &karg); - if (!rc) - _ctl_btdh_search_raid_device(ioc, &karg); - - if (copy_to_user(arg, &karg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - return 0; -} - -/** - * _ctl_diag_capability - return diag buffer capability - * @ioc: per adapter object - * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED - * - * returns 1 when diag buffer support is enabled in firmware - */ -static u8 -_ctl_diag_capability(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type) -{ - u8 rc = 0; - - switch (buffer_type) { - case MPI2_DIAG_BUF_TYPE_TRACE: - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) - rc = 1; - break; - case MPI2_DIAG_BUF_TYPE_SNAPSHOT: - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) - rc = 1; - break; - case MPI2_DIAG_BUF_TYPE_EXTENDED: - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) - rc = 1; - } - - return rc; -} - - -/** - * _ctl_diag_register_2 - wrapper for registering diag buffer support - * @ioc: per adapter object - * @diag_register: the diag_register struct passed in from user space - * - */ -static long -_ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc, - struct mpt3_diag_register *diag_register) -{ - int rc, i; - void *request_data = NULL; - dma_addr_t request_data_dma; - u32 request_data_sz = 0; - Mpi2DiagBufferPostRequest_t *mpi_request; - Mpi2DiagBufferPostReply_t *mpi_reply; - u8 buffer_type; - unsigned long timeleft; - u16 smid; - u16 ioc_status; - u32 ioc_state; - u8 issue_reset = 0; - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - buffer_type = diag_register->buffer_type; - if (!_ctl_diag_capability(ioc, buffer_type)) { - pr_err(MPT3SAS_FMT - "%s: doesn't have capability for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -EPERM; - } - - if (ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_REGISTERED) { - pr_err(MPT3SAS_FMT - "%s: already has a registered buffer for buffer_type(0x%02x)\n", - ioc->name, __func__, - buffer_type); - return -EINVAL; - } - - if (diag_register->requested_buffer_size % 4) { - pr_err(MPT3SAS_FMT - "%s: the requested_buffer_size is not 4 byte aligned\n", - ioc->name, __func__); - return -EINVAL; - } - - smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - rc = 0; - ioc->ctl_cmds.status = MPT3_CMD_PENDING; - memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->ctl_cmds.smid = smid; - - request_data = ioc->diag_buffer[buffer_type]; - request_data_sz = diag_register->requested_buffer_size; - ioc->unique_id[buffer_type] = diag_register->unique_id; - ioc->diag_buffer_status[buffer_type] = 0; - memcpy(ioc->product_specific[buffer_type], - diag_register->product_specific, MPT3_PRODUCT_SPECIFIC_DWORDS); - ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags; - - if (request_data) { - request_data_dma = ioc->diag_buffer_dma[buffer_type]; - if (request_data_sz != ioc->diag_buffer_sz[buffer_type]) { - pci_free_consistent(ioc->pdev, - ioc->diag_buffer_sz[buffer_type], - request_data, request_data_dma); - request_data = NULL; - } - } - - if (request_data == NULL) { - ioc->diag_buffer_sz[buffer_type] = 0; - ioc->diag_buffer_dma[buffer_type] = 0; - request_data = pci_alloc_consistent( - ioc->pdev, request_data_sz, &request_data_dma); - if (request_data == NULL) { - pr_err(MPT3SAS_FMT "%s: failed allocating memory" \ - " for diag buffers, requested size(%d)\n", - ioc->name, __func__, request_data_sz); - mpt3sas_base_free_smid(ioc, smid); - return -ENOMEM; - } - ioc->diag_buffer[buffer_type] = request_data; - ioc->diag_buffer_sz[buffer_type] = request_data_sz; - ioc->diag_buffer_dma[buffer_type] = request_data_dma; - } - - mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST; - mpi_request->BufferType = diag_register->buffer_type; - mpi_request->Flags = cpu_to_le32(diag_register->diagnostic_flags); - mpi_request->BufferAddress = cpu_to_le64(request_data_dma); - mpi_request->BufferLength = cpu_to_le32(request_data_sz); - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: diag_buffer(0x%p), dma(0x%llx), sz(%d)\n", - ioc->name, __func__, request_data, - (unsigned long long)request_data_dma, - le32_to_cpu(mpi_request->BufferLength))); - - for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++) - mpi_request->ProductSpecific[i] = - cpu_to_le32(ioc->product_specific[buffer_type][i]); - - init_completion(&ioc->ctl_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, - MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); - - if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name, - __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2DiagBufferPostRequest_t)/4); - if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - /* process the completed Reply Message Frame */ - if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) { - pr_err(MPT3SAS_FMT "%s: no reply message\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - - mpi_reply = ioc->ctl_cmds.reply; - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; - - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { - ioc->diag_buffer_status[buffer_type] |= - MPT3_DIAG_BUFFER_IS_REGISTERED; - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: success\n", - ioc->name, __func__)); - } else { - pr_info(MPT3SAS_FMT - "%s: ioc_status(0x%04x) log_info(0x%08x)\n", - ioc->name, __func__, - ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); - rc = -EFAULT; - } - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - - out: - - if (rc && request_data) - pci_free_consistent(ioc->pdev, request_data_sz, - request_data, request_data_dma); - - ioc->ctl_cmds.status = MPT3_CMD_NOT_USED; - return rc; -} - -/** - * mpt3sas_enable_diag_buffer - enabling diag_buffers support driver load time - * @ioc: per adapter object - * @bits_to_register: bitwise field where trace is bit 0, and snapshot is bit 1 - * - * This is called when command line option diag_buffer_enable is enabled - * at driver load time. - */ -void -mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, u8 bits_to_register) -{ - struct mpt3_diag_register diag_register; - - memset(&diag_register, 0, sizeof(struct mpt3_diag_register)); - - if (bits_to_register & 1) { - pr_info(MPT3SAS_FMT "registering trace buffer support\n", - ioc->name); - ioc->diag_trigger_master.MasterData = - (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET); - diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE; - /* register for 2MB buffers */ - diag_register.requested_buffer_size = 2 * (1024 * 1024); - diag_register.unique_id = 0x7075900; - _ctl_diag_register_2(ioc, &diag_register); - } - - if (bits_to_register & 2) { - pr_info(MPT3SAS_FMT "registering snapshot buffer support\n", - ioc->name); - diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_SNAPSHOT; - /* register for 2MB buffers */ - diag_register.requested_buffer_size = 2 * (1024 * 1024); - diag_register.unique_id = 0x7075901; - _ctl_diag_register_2(ioc, &diag_register); - } - - if (bits_to_register & 4) { - pr_info(MPT3SAS_FMT "registering extended buffer support\n", - ioc->name); - diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_EXTENDED; - /* register for 2MB buffers */ - diag_register.requested_buffer_size = 2 * (1024 * 1024); - diag_register.unique_id = 0x7075901; - _ctl_diag_register_2(ioc, &diag_register); - } -} - -/** - * _ctl_diag_register - application register with driver - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - * - * This will allow the driver to setup any required buffers that will be - * needed by firmware to communicate with the driver. - */ -static long -_ctl_diag_register(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_diag_register karg; - long rc; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - rc = _ctl_diag_register_2(ioc, &karg); - return rc; -} - -/** - * _ctl_diag_unregister - application unregister with driver - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - * - * This will allow the driver to cleanup any memory allocated for diag - * messages and to free up any resources. - */ -static long -_ctl_diag_unregister(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_diag_unregister karg; - void *request_data; - dma_addr_t request_data_dma; - u32 request_data_sz; - u8 buffer_type; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - buffer_type = karg.unique_id & 0x000000ff; - if (!_ctl_diag_capability(ioc, buffer_type)) { - pr_err(MPT3SAS_FMT - "%s: doesn't have capability for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -EPERM; - } - - if ((ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - pr_err(MPT3SAS_FMT - "%s: buffer_type(0x%02x) is not registered\n", - ioc->name, __func__, buffer_type); - return -EINVAL; - } - if ((ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_RELEASED) == 0) { - pr_err(MPT3SAS_FMT - "%s: buffer_type(0x%02x) has not been released\n", - ioc->name, __func__, buffer_type); - return -EINVAL; - } - - if (karg.unique_id != ioc->unique_id[buffer_type]) { - pr_err(MPT3SAS_FMT - "%s: unique_id(0x%08x) is not registered\n", - ioc->name, __func__, karg.unique_id); - return -EINVAL; - } - - request_data = ioc->diag_buffer[buffer_type]; - if (!request_data) { - pr_err(MPT3SAS_FMT - "%s: doesn't have memory allocated for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -ENOMEM; - } - - request_data_sz = ioc->diag_buffer_sz[buffer_type]; - request_data_dma = ioc->diag_buffer_dma[buffer_type]; - pci_free_consistent(ioc->pdev, request_data_sz, - request_data, request_data_dma); - ioc->diag_buffer[buffer_type] = NULL; - ioc->diag_buffer_status[buffer_type] = 0; - return 0; -} - -/** - * _ctl_diag_query - query relevant info associated with diag buffers - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - * - * The application will send only buffer_type and unique_id. Driver will - * inspect unique_id first, if valid, fill in all the info. If unique_id is - * 0x00, the driver will return info specified by Buffer Type. - */ -static long -_ctl_diag_query(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_diag_query karg; - void *request_data; - int i; - u8 buffer_type; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - karg.application_flags = 0; - buffer_type = karg.buffer_type; - - if (!_ctl_diag_capability(ioc, buffer_type)) { - pr_err(MPT3SAS_FMT - "%s: doesn't have capability for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -EPERM; - } - - if ((ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - pr_err(MPT3SAS_FMT - "%s: buffer_type(0x%02x) is not registered\n", - ioc->name, __func__, buffer_type); - return -EINVAL; - } - - if (karg.unique_id & 0xffffff00) { - if (karg.unique_id != ioc->unique_id[buffer_type]) { - pr_err(MPT3SAS_FMT - "%s: unique_id(0x%08x) is not registered\n", - ioc->name, __func__, karg.unique_id); - return -EINVAL; - } - } - - request_data = ioc->diag_buffer[buffer_type]; - if (!request_data) { - pr_err(MPT3SAS_FMT - "%s: doesn't have buffer for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -ENOMEM; - } - - if (ioc->diag_buffer_status[buffer_type] & MPT3_DIAG_BUFFER_IS_RELEASED) - karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED | - MPT3_APP_FLAGS_BUFFER_VALID); - else - karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED | - MPT3_APP_FLAGS_BUFFER_VALID | - MPT3_APP_FLAGS_FW_BUFFER_ACCESS); - - for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++) - karg.product_specific[i] = - ioc->product_specific[buffer_type][i]; - - karg.total_buffer_size = ioc->diag_buffer_sz[buffer_type]; - karg.driver_added_buffer_size = 0; - karg.unique_id = ioc->unique_id[buffer_type]; - karg.diagnostic_flags = ioc->diagnostic_flags[buffer_type]; - - if (copy_to_user(arg, &karg, sizeof(struct mpt3_diag_query))) { - pr_err(MPT3SAS_FMT - "%s: unable to write mpt3_diag_query data @ %p\n", - ioc->name, __func__, arg); - return -EFAULT; - } - return 0; -} - -/** - * mpt3sas_send_diag_release - Diag Release Message - * @ioc: per adapter object - * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED - * @issue_reset - specifies whether host reset is required. - * - */ -int -mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type, - u8 *issue_reset) -{ - Mpi2DiagReleaseRequest_t *mpi_request; - Mpi2DiagReleaseReply_t *mpi_reply; - u16 smid; - u16 ioc_status; - u32 ioc_state; - int rc; - unsigned long timeleft; - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - rc = 0; - *issue_reset = 0; - - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_REGISTERED) - ioc->diag_buffer_status[buffer_type] |= - MPT3_DIAG_BUFFER_IS_RELEASED; - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: skipping due to FAULT state\n", ioc->name, - __func__)); - rc = -EAGAIN; - goto out; - } - - if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - ioc->ctl_cmds.status = MPT3_CMD_PENDING; - memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->ctl_cmds.smid = smid; - - mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE; - mpi_request->BufferType = buffer_type; - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - - init_completion(&ioc->ctl_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, - MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); - - if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name, - __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2DiagReleaseRequest_t)/4); - if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET)) - *issue_reset = 1; - rc = -EFAULT; - goto out; - } - - /* process the completed Reply Message Frame */ - if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) { - pr_err(MPT3SAS_FMT "%s: no reply message\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - - mpi_reply = ioc->ctl_cmds.reply; - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; - - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { - ioc->diag_buffer_status[buffer_type] |= - MPT3_DIAG_BUFFER_IS_RELEASED; - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: success\n", - ioc->name, __func__)); - } else { - pr_info(MPT3SAS_FMT - "%s: ioc_status(0x%04x) log_info(0x%08x)\n", - ioc->name, __func__, - ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); - rc = -EFAULT; - } - - out: - ioc->ctl_cmds.status = MPT3_CMD_NOT_USED; - return rc; -} - -/** - * _ctl_diag_release - request to send Diag Release Message to firmware - * @arg - user space buffer containing ioctl content - * - * This allows ownership of the specified buffer to returned to the driver, - * allowing an application to read the buffer without fear that firmware is - * overwritting information in the buffer. - */ -static long -_ctl_diag_release(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_diag_release karg; - void *request_data; - int rc; - u8 buffer_type; - u8 issue_reset = 0; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - buffer_type = karg.unique_id & 0x000000ff; - if (!_ctl_diag_capability(ioc, buffer_type)) { - pr_err(MPT3SAS_FMT - "%s: doesn't have capability for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -EPERM; - } - - if ((ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - pr_err(MPT3SAS_FMT - "%s: buffer_type(0x%02x) is not registered\n", - ioc->name, __func__, buffer_type); - return -EINVAL; - } - - if (karg.unique_id != ioc->unique_id[buffer_type]) { - pr_err(MPT3SAS_FMT - "%s: unique_id(0x%08x) is not registered\n", - ioc->name, __func__, karg.unique_id); - return -EINVAL; - } - - if (ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_RELEASED) { - pr_err(MPT3SAS_FMT - "%s: buffer_type(0x%02x) is already released\n", - ioc->name, __func__, - buffer_type); - return 0; - } - - request_data = ioc->diag_buffer[buffer_type]; - - if (!request_data) { - pr_err(MPT3SAS_FMT - "%s: doesn't have memory allocated for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -ENOMEM; - } - - /* buffers were released by due to host reset */ - if ((ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_DIAG_RESET)) { - ioc->diag_buffer_status[buffer_type] |= - MPT3_DIAG_BUFFER_IS_RELEASED; - ioc->diag_buffer_status[buffer_type] &= - ~MPT3_DIAG_BUFFER_IS_DIAG_RESET; - pr_err(MPT3SAS_FMT - "%s: buffer_type(0x%02x) was released due to host reset\n", - ioc->name, __func__, buffer_type); - return 0; - } - - rc = mpt3sas_send_diag_release(ioc, buffer_type, &issue_reset); - - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - - return rc; -} - -/** - * _ctl_diag_read_buffer - request for copy of the diag buffer - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_diag_read_buffer karg; - struct mpt3_diag_read_buffer __user *uarg = arg; - void *request_data, *diag_data; - Mpi2DiagBufferPostRequest_t *mpi_request; - Mpi2DiagBufferPostReply_t *mpi_reply; - int rc, i; - u8 buffer_type; - unsigned long timeleft, request_size, copy_size; - u16 smid; - u16 ioc_status; - u8 issue_reset = 0; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - buffer_type = karg.unique_id & 0x000000ff; - if (!_ctl_diag_capability(ioc, buffer_type)) { - pr_err(MPT3SAS_FMT - "%s: doesn't have capability for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -EPERM; - } - - if (karg.unique_id != ioc->unique_id[buffer_type]) { - pr_err(MPT3SAS_FMT - "%s: unique_id(0x%08x) is not registered\n", - ioc->name, __func__, karg.unique_id); - return -EINVAL; - } - - request_data = ioc->diag_buffer[buffer_type]; - if (!request_data) { - pr_err(MPT3SAS_FMT - "%s: doesn't have buffer for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -ENOMEM; - } - - request_size = ioc->diag_buffer_sz[buffer_type]; - - if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) { - pr_err(MPT3SAS_FMT "%s: either the starting_offset " \ - "or bytes_to_read are not 4 byte aligned\n", ioc->name, - __func__); - return -EINVAL; - } - - if (karg.starting_offset > request_size) - return -EINVAL; - - diag_data = (void *)(request_data + karg.starting_offset); - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: diag_buffer(%p), offset(%d), sz(%d)\n", - ioc->name, __func__, - diag_data, karg.starting_offset, karg.bytes_to_read)); - - /* Truncate data on requests that are too large */ - if ((diag_data + karg.bytes_to_read < diag_data) || - (diag_data + karg.bytes_to_read > request_data + request_size)) - copy_size = request_size - karg.starting_offset; - else - copy_size = karg.bytes_to_read; - - if (copy_to_user((void __user *)uarg->diagnostic_data, - diag_data, copy_size)) { - pr_err(MPT3SAS_FMT - "%s: Unable to write mpt_diag_read_buffer_t data @ %p\n", - ioc->name, __func__, diag_data); - return -EFAULT; - } - - if ((karg.flags & MPT3_FLAGS_REREGISTER) == 0) - return 0; - - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: Reregister buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type)); - if ((ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_RELEASED) == 0) { - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: buffer_type(0x%02x) is still registered\n", - ioc->name, __func__, buffer_type)); - return 0; - } - /* Get a free request frame and save the message context. - */ - - if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - rc = 0; - ioc->ctl_cmds.status = MPT3_CMD_PENDING; - memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->ctl_cmds.smid = smid; - - mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST; - mpi_request->BufferType = buffer_type; - mpi_request->BufferLength = - cpu_to_le32(ioc->diag_buffer_sz[buffer_type]); - mpi_request->BufferAddress = - cpu_to_le64(ioc->diag_buffer_dma[buffer_type]); - for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++) - mpi_request->ProductSpecific[i] = - cpu_to_le32(ioc->product_specific[buffer_type][i]); - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - - init_completion(&ioc->ctl_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, - MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); - - if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name, - __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2DiagBufferPostRequest_t)/4); - if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - /* process the completed Reply Message Frame */ - if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) { - pr_err(MPT3SAS_FMT "%s: no reply message\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - - mpi_reply = ioc->ctl_cmds.reply; - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; - - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { - ioc->diag_buffer_status[buffer_type] |= - MPT3_DIAG_BUFFER_IS_REGISTERED; - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: success\n", - ioc->name, __func__)); - } else { - pr_info(MPT3SAS_FMT - "%s: ioc_status(0x%04x) log_info(0x%08x)\n", - ioc->name, __func__, - ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); - rc = -EFAULT; - } - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - - out: - - ioc->ctl_cmds.status = MPT3_CMD_NOT_USED; - return rc; -} - - - -#ifdef CONFIG_COMPAT -/** - * _ctl_compat_mpt_command - convert 32bit pointers to 64bit. - * @ioc: per adapter object - * @cmd - ioctl opcode - * @arg - (struct mpt3_ioctl_command32) - * - * MPT3COMMAND32 - Handle 32bit applications running on 64bit os. - */ -static long -_ctl_compat_mpt_command(struct MPT3SAS_ADAPTER *ioc, unsigned cmd, - void __user *arg) -{ - struct mpt3_ioctl_command32 karg32; - struct mpt3_ioctl_command32 __user *uarg; - struct mpt3_ioctl_command karg; - - if (_IOC_SIZE(cmd) != sizeof(struct mpt3_ioctl_command32)) - return -EINVAL; - - uarg = (struct mpt3_ioctl_command32 __user *) arg; - - if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - memset(&karg, 0, sizeof(struct mpt3_ioctl_command)); - karg.hdr.ioc_number = karg32.hdr.ioc_number; - karg.hdr.port_number = karg32.hdr.port_number; - karg.hdr.max_data_size = karg32.hdr.max_data_size; - karg.timeout = karg32.timeout; - karg.max_reply_bytes = karg32.max_reply_bytes; - karg.data_in_size = karg32.data_in_size; - karg.data_out_size = karg32.data_out_size; - karg.max_sense_bytes = karg32.max_sense_bytes; - karg.data_sge_offset = karg32.data_sge_offset; - karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr); - karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr); - karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr); - karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr); - return _ctl_do_mpt_command(ioc, karg, &uarg->mf); -} -#endif - -/** - * _ctl_ioctl_main - main ioctl entry point - * @file - (struct file) - * @cmd - ioctl opcode - * @arg - - * compat - handles 32 bit applications in 64bit os - */ -static long -_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg, - u8 compat) -{ - struct MPT3SAS_ADAPTER *ioc; - struct mpt3_ioctl_header ioctl_header; - enum block_state state; - long ret = -EINVAL; - - /* get IOCTL header */ - if (copy_from_user(&ioctl_header, (char __user *)arg, - sizeof(struct mpt3_ioctl_header))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - if (_ctl_verify_adapter(ioctl_header.ioc_number, &ioc) == -1 || !ioc) - return -ENODEV; - - if (ioc->shost_recovery || ioc->pci_error_recovery || - ioc->is_driver_loading) - return -EAGAIN; - - state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING; - if (state == NON_BLOCKING) { - if (!mutex_trylock(&ioc->ctl_cmds.mutex)) - return -EAGAIN; - } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) - return -ERESTARTSYS; - - - switch (cmd) { - case MPT3IOCINFO: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_iocinfo)) - ret = _ctl_getiocinfo(ioc, arg); - break; -#ifdef CONFIG_COMPAT - case MPT3COMMAND32: -#endif - case MPT3COMMAND: - { - struct mpt3_ioctl_command __user *uarg; - struct mpt3_ioctl_command karg; - -#ifdef CONFIG_COMPAT - if (compat) { - ret = _ctl_compat_mpt_command(ioc, cmd, arg); - break; - } -#endif - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - ret = -EFAULT; - break; - } - - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_command)) { - uarg = arg; - ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf); - } - break; - } - case MPT3EVENTQUERY: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_eventquery)) - ret = _ctl_eventquery(ioc, arg); - break; - case MPT3EVENTENABLE: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_eventenable)) - ret = _ctl_eventenable(ioc, arg); - break; - case MPT3EVENTREPORT: - ret = _ctl_eventreport(ioc, arg); - break; - case MPT3HARDRESET: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_diag_reset)) - ret = _ctl_do_reset(ioc, arg); - break; - case MPT3BTDHMAPPING: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_btdh_mapping)) - ret = _ctl_btdh_mapping(ioc, arg); - break; - case MPT3DIAGREGISTER: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_register)) - ret = _ctl_diag_register(ioc, arg); - break; - case MPT3DIAGUNREGISTER: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_unregister)) - ret = _ctl_diag_unregister(ioc, arg); - break; - case MPT3DIAGQUERY: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_query)) - ret = _ctl_diag_query(ioc, arg); - break; - case MPT3DIAGRELEASE: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_release)) - ret = _ctl_diag_release(ioc, arg); - break; - case MPT3DIAGREADBUFFER: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_read_buffer)) - ret = _ctl_diag_read_buffer(ioc, arg); - break; - default: - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd)); - break; - } - - mutex_unlock(&ioc->ctl_cmds.mutex); - return ret; -} - -/** - * _ctl_ioctl - main ioctl entry point (unlocked) - * @file - (struct file) - * @cmd - ioctl opcode - * @arg - - */ -static long -_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - long ret; - - ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0); - return ret; -} - -#ifdef CONFIG_COMPAT -/** - * _ctl_ioctl_compat - main ioctl entry point (compat) - * @file - - * @cmd - - * @arg - - * - * This routine handles 32 bit applications in 64bit os. - */ -static long -_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) -{ - long ret; - - ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1); - return ret; -} -#endif - -/* scsi host attributes */ -/** - * _ctl_version_fw_show - firmware version - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_version_fw_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", - (ioc->facts.FWVersion.Word & 0xFF000000) >> 24, - (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, - (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, - ioc->facts.FWVersion.Word & 0x000000FF); -} -static DEVICE_ATTR(version_fw, S_IRUGO, _ctl_version_fw_show, NULL); - -/** - * _ctl_version_bios_show - bios version - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_version_bios_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - u32 version = le32_to_cpu(ioc->bios_pg3.BiosVersion); - - return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", - (version & 0xFF000000) >> 24, - (version & 0x00FF0000) >> 16, - (version & 0x0000FF00) >> 8, - version & 0x000000FF); -} -static DEVICE_ATTR(version_bios, S_IRUGO, _ctl_version_bios_show, NULL); - -/** - * _ctl_version_mpi_show - MPI (message passing interface) version - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_version_mpi_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%03x.%02x\n", - ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8); -} -static DEVICE_ATTR(version_mpi, S_IRUGO, _ctl_version_mpi_show, NULL); - -/** - * _ctl_version_product_show - product name - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_version_product_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, 16, "%s\n", ioc->manu_pg0.ChipName); -} -static DEVICE_ATTR(version_product, S_IRUGO, _ctl_version_product_show, NULL); - -/** - * _ctl_version_nvdata_persistent_show - ndvata persistent version - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_version_nvdata_persistent_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%08xh\n", - le32_to_cpu(ioc->iounit_pg0.NvdataVersionPersistent.Word)); -} -static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO, - _ctl_version_nvdata_persistent_show, NULL); - -/** - * _ctl_version_nvdata_default_show - nvdata default version - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_version_nvdata_default_show(struct device *cdev, struct device_attribute - *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%08xh\n", - le32_to_cpu(ioc->iounit_pg0.NvdataVersionDefault.Word)); -} -static DEVICE_ATTR(version_nvdata_default, S_IRUGO, - _ctl_version_nvdata_default_show, NULL); - -/** - * _ctl_board_name_show - board name - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_board_name_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardName); -} -static DEVICE_ATTR(board_name, S_IRUGO, _ctl_board_name_show, NULL); - -/** - * _ctl_board_assembly_show - board assembly name - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_board_assembly_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardAssembly); -} -static DEVICE_ATTR(board_assembly, S_IRUGO, _ctl_board_assembly_show, NULL); - -/** - * _ctl_board_tracer_show - board tracer number - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_board_tracer_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardTracerNumber); -} -static DEVICE_ATTR(board_tracer, S_IRUGO, _ctl_board_tracer_show, NULL); - -/** - * _ctl_io_delay_show - io missing delay - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is for firmware implemention for deboucing device - * removal events. - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_io_delay_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay); -} -static DEVICE_ATTR(io_delay, S_IRUGO, _ctl_io_delay_show, NULL); - -/** - * _ctl_device_delay_show - device missing delay - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is for firmware implemention for deboucing device - * removal events. - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_device_delay_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay); -} -static DEVICE_ATTR(device_delay, S_IRUGO, _ctl_device_delay_show, NULL); - -/** - * _ctl_fw_queue_depth_show - global credits - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is firmware queue depth limit - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_fw_queue_depth_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->facts.RequestCredit); -} -static DEVICE_ATTR(fw_queue_depth, S_IRUGO, _ctl_fw_queue_depth_show, NULL); - -/** - * _ctl_sas_address_show - sas address - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is the controller sas address - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_host_sas_address_show(struct device *cdev, struct device_attribute *attr, - char *buf) - -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "0x%016llx\n", - (unsigned long long)ioc->sas_hba.sas_address); -} -static DEVICE_ATTR(host_sas_address, S_IRUGO, - _ctl_host_sas_address_show, NULL); - -/** - * _ctl_logging_level_show - logging level - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_logging_level_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->logging_level); -} -static ssize_t -_ctl_logging_level_store(struct device *cdev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - int val = 0; - - if (sscanf(buf, "%x", &val) != 1) - return -EINVAL; - - ioc->logging_level = val; - pr_info(MPT3SAS_FMT "logging_level=%08xh\n", ioc->name, - ioc->logging_level); - return strlen(buf); -} -static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR, _ctl_logging_level_show, - _ctl_logging_level_store); - -/** - * _ctl_fwfault_debug_show - show/store fwfault_debug - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * mpt3sas_fwfault_debug is command line option - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_fwfault_debug_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%d\n", ioc->fwfault_debug); -} -static ssize_t -_ctl_fwfault_debug_store(struct device *cdev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - int val = 0; - - if (sscanf(buf, "%d", &val) != 1) - return -EINVAL; - - ioc->fwfault_debug = val; - pr_info(MPT3SAS_FMT "fwfault_debug=%d\n", ioc->name, - ioc->fwfault_debug); - return strlen(buf); -} -static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR, - _ctl_fwfault_debug_show, _ctl_fwfault_debug_store); - -/** - * _ctl_ioc_reset_count_show - ioc reset count - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is firmware queue depth limit - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%d\n", ioc->ioc_reset_count); -} -static DEVICE_ATTR(ioc_reset_count, S_IRUGO, _ctl_ioc_reset_count_show, NULL); - -/** - * _ctl_ioc_reply_queue_count_show - number of reply queues - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is number of reply queues - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_ioc_reply_queue_count_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - u8 reply_queue_count; - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - if ((ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable) - reply_queue_count = ioc->reply_queue_count; - else - reply_queue_count = 1; - - return snprintf(buf, PAGE_SIZE, "%d\n", reply_queue_count); -} -static DEVICE_ATTR(reply_queue_count, S_IRUGO, _ctl_ioc_reply_queue_count_show, - NULL); - -struct DIAG_BUFFER_START { - __le32 Size; - __le32 DiagVersion; - u8 BufferType; - u8 Reserved[3]; - __le32 Reserved1; - __le32 Reserved2; - __le32 Reserved3; -}; - -/** - * _ctl_host_trace_buffer_size_show - host buffer size (trace only) - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_host_trace_buffer_size_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - u32 size = 0; - struct DIAG_BUFFER_START *request_data; - - if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) { - pr_err(MPT3SAS_FMT - "%s: host_trace_buffer is not registered\n", - ioc->name, __func__); - return 0; - } - - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - pr_err(MPT3SAS_FMT - "%s: host_trace_buffer is not registered\n", - ioc->name, __func__); - return 0; - } - - request_data = (struct DIAG_BUFFER_START *) - ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]; - if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 || - le32_to_cpu(request_data->DiagVersion) == 0x01000000 || - le32_to_cpu(request_data->DiagVersion) == 0x01010000) && - le32_to_cpu(request_data->Reserved3) == 0x4742444c) - size = le32_to_cpu(request_data->Size); - - ioc->ring_buffer_sz = size; - return snprintf(buf, PAGE_SIZE, "%d\n", size); -} -static DEVICE_ATTR(host_trace_buffer_size, S_IRUGO, - _ctl_host_trace_buffer_size_show, NULL); - -/** - * _ctl_host_trace_buffer_show - firmware ring buffer (trace only) - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - * - * You will only be able to read 4k bytes of ring buffer at a time. - * In order to read beyond 4k bytes, you will have to write out the - * offset to the same attribute, it will move the pointer. - */ -static ssize_t -_ctl_host_trace_buffer_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - void *request_data; - u32 size; - - if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) { - pr_err(MPT3SAS_FMT - "%s: host_trace_buffer is not registered\n", - ioc->name, __func__); - return 0; - } - - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - pr_err(MPT3SAS_FMT - "%s: host_trace_buffer is not registered\n", - ioc->name, __func__); - return 0; - } - - if (ioc->ring_buffer_offset > ioc->ring_buffer_sz) - return 0; - - size = ioc->ring_buffer_sz - ioc->ring_buffer_offset; - size = (size >= PAGE_SIZE) ? (PAGE_SIZE - 1) : size; - request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset; - memcpy(buf, request_data, size); - return size; -} - -static ssize_t -_ctl_host_trace_buffer_store(struct device *cdev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - int val = 0; - - if (sscanf(buf, "%d", &val) != 1) - return -EINVAL; - - ioc->ring_buffer_offset = val; - return strlen(buf); -} -static DEVICE_ATTR(host_trace_buffer, S_IRUGO | S_IWUSR, - _ctl_host_trace_buffer_show, _ctl_host_trace_buffer_store); - - -/*****************************************/ - -/** - * _ctl_host_trace_buffer_enable_show - firmware ring buffer (trace only) - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - * - * This is a mechnism to post/release host_trace_buffers - */ -static ssize_t -_ctl_host_trace_buffer_enable_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) || - ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0)) - return snprintf(buf, PAGE_SIZE, "off\n"); - else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED)) - return snprintf(buf, PAGE_SIZE, "release\n"); - else - return snprintf(buf, PAGE_SIZE, "post\n"); -} - -static ssize_t -_ctl_host_trace_buffer_enable_store(struct device *cdev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - char str[10] = ""; - struct mpt3_diag_register diag_register; - u8 issue_reset = 0; - - /* don't allow post/release occurr while recovery is active */ - if (ioc->shost_recovery || ioc->remove_host || - ioc->pci_error_recovery || ioc->is_driver_loading) - return -EBUSY; - - if (sscanf(buf, "%9s", str) != 1) - return -EINVAL; - - if (!strcmp(str, "post")) { - /* exit out if host buffers are already posted */ - if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) && - (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) && - ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED) == 0)) - goto out; - memset(&diag_register, 0, sizeof(struct mpt3_diag_register)); - pr_info(MPT3SAS_FMT "posting host trace buffers\n", - ioc->name); - diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE; - diag_register.requested_buffer_size = (1024 * 1024); - diag_register.unique_id = 0x7075900; - ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0; - _ctl_diag_register_2(ioc, &diag_register); - } else if (!strcmp(str, "release")) { - /* exit out if host buffers are already released */ - if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) - goto out; - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) - goto out; - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED)) - goto out; - pr_info(MPT3SAS_FMT "releasing host trace buffer\n", - ioc->name); - mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, - &issue_reset); - } - - out: - return strlen(buf); -} -static DEVICE_ATTR(host_trace_buffer_enable, S_IRUGO | S_IWUSR, - _ctl_host_trace_buffer_enable_show, - _ctl_host_trace_buffer_enable_store); - -/*********** diagnostic trigger suppport *********************************/ - -/** - * _ctl_diag_trigger_master_show - show the diag_trigger_master attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_master_show(struct device *cdev, - struct device_attribute *attr, char *buf) - -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t rc; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - rc = sizeof(struct SL_WH_MASTER_TRIGGER_T); - memcpy(buf, &ioc->diag_trigger_master, rc); - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return rc; -} - -/** - * _ctl_diag_trigger_master_store - store the diag_trigger_master attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_master_store(struct device *cdev, - struct device_attribute *attr, const char *buf, size_t count) - -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t rc; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - rc = min(sizeof(struct SL_WH_MASTER_TRIGGER_T), count); - memset(&ioc->diag_trigger_master, 0, - sizeof(struct SL_WH_MASTER_TRIGGER_T)); - memcpy(&ioc->diag_trigger_master, buf, rc); - ioc->diag_trigger_master.MasterData |= - (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET); - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return rc; -} -static DEVICE_ATTR(diag_trigger_master, S_IRUGO | S_IWUSR, - _ctl_diag_trigger_master_show, _ctl_diag_trigger_master_store); - - -/** - * _ctl_diag_trigger_event_show - show the diag_trigger_event attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_event_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t rc; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - rc = sizeof(struct SL_WH_EVENT_TRIGGERS_T); - memcpy(buf, &ioc->diag_trigger_event, rc); - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return rc; -} - -/** - * _ctl_diag_trigger_event_store - store the diag_trigger_event attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_event_store(struct device *cdev, - struct device_attribute *attr, const char *buf, size_t count) - -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t sz; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - sz = min(sizeof(struct SL_WH_EVENT_TRIGGERS_T), count); - memset(&ioc->diag_trigger_event, 0, - sizeof(struct SL_WH_EVENT_TRIGGERS_T)); - memcpy(&ioc->diag_trigger_event, buf, sz); - if (ioc->diag_trigger_event.ValidEntries > NUM_VALID_ENTRIES) - ioc->diag_trigger_event.ValidEntries = NUM_VALID_ENTRIES; - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return sz; -} -static DEVICE_ATTR(diag_trigger_event, S_IRUGO | S_IWUSR, - _ctl_diag_trigger_event_show, _ctl_diag_trigger_event_store); - - -/** - * _ctl_diag_trigger_scsi_show - show the diag_trigger_scsi attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_scsi_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t rc; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - rc = sizeof(struct SL_WH_SCSI_TRIGGERS_T); - memcpy(buf, &ioc->diag_trigger_scsi, rc); - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return rc; -} - -/** - * _ctl_diag_trigger_scsi_store - store the diag_trigger_scsi attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_scsi_store(struct device *cdev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t sz; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - sz = min(sizeof(struct SL_WH_SCSI_TRIGGERS_T), count); - memset(&ioc->diag_trigger_scsi, 0, - sizeof(struct SL_WH_EVENT_TRIGGERS_T)); - memcpy(&ioc->diag_trigger_scsi, buf, sz); - if (ioc->diag_trigger_scsi.ValidEntries > NUM_VALID_ENTRIES) - ioc->diag_trigger_scsi.ValidEntries = NUM_VALID_ENTRIES; - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return sz; -} -static DEVICE_ATTR(diag_trigger_scsi, S_IRUGO | S_IWUSR, - _ctl_diag_trigger_scsi_show, _ctl_diag_trigger_scsi_store); - - -/** - * _ctl_diag_trigger_scsi_show - show the diag_trigger_mpi attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_mpi_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t rc; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - rc = sizeof(struct SL_WH_MPI_TRIGGERS_T); - memcpy(buf, &ioc->diag_trigger_mpi, rc); - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return rc; -} - -/** - * _ctl_diag_trigger_mpi_store - store the diag_trigger_mpi attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_mpi_store(struct device *cdev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t sz; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - sz = min(sizeof(struct SL_WH_MPI_TRIGGERS_T), count); - memset(&ioc->diag_trigger_mpi, 0, - sizeof(ioc->diag_trigger_mpi)); - memcpy(&ioc->diag_trigger_mpi, buf, sz); - if (ioc->diag_trigger_mpi.ValidEntries > NUM_VALID_ENTRIES) - ioc->diag_trigger_mpi.ValidEntries = NUM_VALID_ENTRIES; - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return sz; -} - -static DEVICE_ATTR(diag_trigger_mpi, S_IRUGO | S_IWUSR, - _ctl_diag_trigger_mpi_show, _ctl_diag_trigger_mpi_store); - -/*********** diagnostic trigger suppport *** END ****************************/ - - - -/*****************************************/ - -struct device_attribute *mpt3sas_host_attrs[] = { - &dev_attr_version_fw, - &dev_attr_version_bios, - &dev_attr_version_mpi, - &dev_attr_version_product, - &dev_attr_version_nvdata_persistent, - &dev_attr_version_nvdata_default, - &dev_attr_board_name, - &dev_attr_board_assembly, - &dev_attr_board_tracer, - &dev_attr_io_delay, - &dev_attr_device_delay, - &dev_attr_logging_level, - &dev_attr_fwfault_debug, - &dev_attr_fw_queue_depth, - &dev_attr_host_sas_address, - &dev_attr_ioc_reset_count, - &dev_attr_host_trace_buffer_size, - &dev_attr_host_trace_buffer, - &dev_attr_host_trace_buffer_enable, - &dev_attr_reply_queue_count, - &dev_attr_diag_trigger_master, - &dev_attr_diag_trigger_event, - &dev_attr_diag_trigger_scsi, - &dev_attr_diag_trigger_mpi, - NULL, -}; - -/* device attributes */ - -/** - * _ctl_device_sas_address_show - sas address - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is the sas address for the target - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_device_sas_address_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata; - - return snprintf(buf, PAGE_SIZE, "0x%016llx\n", - (unsigned long long)sas_device_priv_data->sas_target->sas_address); -} -static DEVICE_ATTR(sas_address, S_IRUGO, _ctl_device_sas_address_show, NULL); - -/** - * _ctl_device_handle_show - device handle - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is the firmware assigned device handle - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_device_handle_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata; - - return snprintf(buf, PAGE_SIZE, "0x%04x\n", - sas_device_priv_data->sas_target->handle); -} -static DEVICE_ATTR(sas_device_handle, S_IRUGO, _ctl_device_handle_show, NULL); - -struct device_attribute *mpt3sas_dev_attrs[] = { - &dev_attr_sas_address, - &dev_attr_sas_device_handle, - NULL, -}; - -static const struct file_operations ctl_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = _ctl_ioctl, - .poll = _ctl_poll, - .fasync = _ctl_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = _ctl_ioctl_compat, -#endif -}; - -static struct miscdevice ctl_dev = { - .minor = MPT3SAS_MINOR, - .name = MPT3SAS_DEV_NAME, - .fops = &ctl_fops, -}; - -/** - * mpt3sas_ctl_init - main entry point for ctl. - * - */ -void -mpt3sas_ctl_init(void) -{ - async_queue = NULL; - if (misc_register(&ctl_dev) < 0) - pr_err("%s can't register misc device [minor=%d]\n", - MPT3SAS_DRIVER_NAME, MPT3SAS_MINOR); - - init_waitqueue_head(&ctl_poll_wait); -} - -/** - * mpt3sas_ctl_exit - exit point for ctl - * - */ -void -mpt3sas_ctl_exit(void) -{ - struct MPT3SAS_ADAPTER *ioc; - int i; - - list_for_each_entry(ioc, &mpt3sas_ioc_list, list) { - - /* free memory associated to diag buffers */ - for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { - if (!ioc->diag_buffer[i]) - continue; - if (!(ioc->diag_buffer_status[i] & - MPT3_DIAG_BUFFER_IS_REGISTERED)) - continue; - if ((ioc->diag_buffer_status[i] & - MPT3_DIAG_BUFFER_IS_RELEASED)) - continue; - pci_free_consistent(ioc->pdev, ioc->diag_buffer_sz[i], - ioc->diag_buffer[i], ioc->diag_buffer_dma[i]); - ioc->diag_buffer[i] = NULL; - ioc->diag_buffer_status[i] = 0; - } - - kfree(ioc->event_log); - } - misc_deregister(&ctl_dev); -} diff --git a/addons/mpt3sas/src/3.10.108/mpt3sas_ctl.h b/addons/mpt3sas/src/3.10.108/mpt3sas_ctl.h deleted file mode 100644 index bd89f4f0..00000000 --- a/addons/mpt3sas/src/3.10.108/mpt3sas_ctl.h +++ /dev/null @@ -1,418 +0,0 @@ -/* - * Management Module Support for MPT (Message Passing Technology) based - * controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_ctl.h - * Copyright (C) 2012 LSI Corporation - * (mailto:DL-MPTFusionLinux@lsi.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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 MPT3SAS_CTL_H_INCLUDED -#define MPT3SAS_CTL_H_INCLUDED - -#ifdef __KERNEL__ -#include -#endif - - -#ifndef MPT3SAS_MINOR -#define MPT3SAS_MINOR (MPT_MINOR + 2) -#endif -#define MPT3SAS_DEV_NAME "mpt3ctl" -#define MPT3_MAGIC_NUMBER 'L' -#define MPT3_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */ - -/** - * IOCTL opcodes - */ -#define MPT3IOCINFO _IOWR(MPT3_MAGIC_NUMBER, 17, \ - struct mpt3_ioctl_iocinfo) -#define MPT3COMMAND _IOWR(MPT3_MAGIC_NUMBER, 20, \ - struct mpt3_ioctl_command) -#ifdef CONFIG_COMPAT -#define MPT3COMMAND32 _IOWR(MPT3_MAGIC_NUMBER, 20, \ - struct mpt3_ioctl_command32) -#endif -#define MPT3EVENTQUERY _IOWR(MPT3_MAGIC_NUMBER, 21, \ - struct mpt3_ioctl_eventquery) -#define MPT3EVENTENABLE _IOWR(MPT3_MAGIC_NUMBER, 22, \ - struct mpt3_ioctl_eventenable) -#define MPT3EVENTREPORT _IOWR(MPT3_MAGIC_NUMBER, 23, \ - struct mpt3_ioctl_eventreport) -#define MPT3HARDRESET _IOWR(MPT3_MAGIC_NUMBER, 24, \ - struct mpt3_ioctl_diag_reset) -#define MPT3BTDHMAPPING _IOWR(MPT3_MAGIC_NUMBER, 31, \ - struct mpt3_ioctl_btdh_mapping) - -/* diag buffer support */ -#define MPT3DIAGREGISTER _IOWR(MPT3_MAGIC_NUMBER, 26, \ - struct mpt3_diag_register) -#define MPT3DIAGRELEASE _IOWR(MPT3_MAGIC_NUMBER, 27, \ - struct mpt3_diag_release) -#define MPT3DIAGUNREGISTER _IOWR(MPT3_MAGIC_NUMBER, 28, \ - struct mpt3_diag_unregister) -#define MPT3DIAGQUERY _IOWR(MPT3_MAGIC_NUMBER, 29, \ - struct mpt3_diag_query) -#define MPT3DIAGREADBUFFER _IOWR(MPT3_MAGIC_NUMBER, 30, \ - struct mpt3_diag_read_buffer) - -/** - * struct mpt3_ioctl_header - main header structure - * @ioc_number - IOC unit number - * @port_number - IOC port number - * @max_data_size - maximum number bytes to transfer on read - */ -struct mpt3_ioctl_header { - uint32_t ioc_number; - uint32_t port_number; - uint32_t max_data_size; -}; - -/** - * struct mpt3_ioctl_diag_reset - diagnostic reset - * @hdr - generic header - */ -struct mpt3_ioctl_diag_reset { - struct mpt3_ioctl_header hdr; -}; - - -/** - * struct mpt3_ioctl_pci_info - pci device info - * @device - pci device id - * @function - pci function id - * @bus - pci bus id - * @segment_id - pci segment id - */ -struct mpt3_ioctl_pci_info { - union { - struct { - uint32_t device:5; - uint32_t function:3; - uint32_t bus:24; - } bits; - uint32_t word; - } u; - uint32_t segment_id; -}; - - -#define MPT2_IOCTL_INTERFACE_SCSI (0x00) -#define MPT2_IOCTL_INTERFACE_FC (0x01) -#define MPT2_IOCTL_INTERFACE_FC_IP (0x02) -#define MPT2_IOCTL_INTERFACE_SAS (0x03) -#define MPT2_IOCTL_INTERFACE_SAS2 (0x04) -#define MPT3_IOCTL_INTERFACE_SAS3 (0x06) -#define MPT2_IOCTL_VERSION_LENGTH (32) - -/** - * struct mpt3_ioctl_iocinfo - generic controller info - * @hdr - generic header - * @adapter_type - type of adapter (spi, fc, sas) - * @port_number - port number - * @pci_id - PCI Id - * @hw_rev - hardware revision - * @sub_system_device - PCI subsystem Device ID - * @sub_system_vendor - PCI subsystem Vendor ID - * @rsvd0 - reserved - * @firmware_version - firmware version - * @bios_version - BIOS version - * @driver_version - driver version - 32 ASCII characters - * @rsvd1 - reserved - * @scsi_id - scsi id of adapter 0 - * @rsvd2 - reserved - * @pci_information - pci info (2nd revision) - */ -struct mpt3_ioctl_iocinfo { - struct mpt3_ioctl_header hdr; - uint32_t adapter_type; - uint32_t port_number; - uint32_t pci_id; - uint32_t hw_rev; - uint32_t subsystem_device; - uint32_t subsystem_vendor; - uint32_t rsvd0; - uint32_t firmware_version; - uint32_t bios_version; - uint8_t driver_version[MPT2_IOCTL_VERSION_LENGTH]; - uint8_t rsvd1; - uint8_t scsi_id; - uint16_t rsvd2; - struct mpt3_ioctl_pci_info pci_information; -}; - - -/* number of event log entries */ -#define MPT3SAS_CTL_EVENT_LOG_SIZE (50) - -/** - * struct mpt3_ioctl_eventquery - query event count and type - * @hdr - generic header - * @event_entries - number of events returned by get_event_report - * @rsvd - reserved - * @event_types - type of events currently being captured - */ -struct mpt3_ioctl_eventquery { - struct mpt3_ioctl_header hdr; - uint16_t event_entries; - uint16_t rsvd; - uint32_t event_types[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; -}; - -/** - * struct mpt3_ioctl_eventenable - enable/disable event capturing - * @hdr - generic header - * @event_types - toggle off/on type of events to be captured - */ -struct mpt3_ioctl_eventenable { - struct mpt3_ioctl_header hdr; - uint32_t event_types[4]; -}; - -#define MPT3_EVENT_DATA_SIZE (192) -/** - * struct MPT3_IOCTL_EVENTS - - * @event - the event that was reported - * @context - unique value for each event assigned by driver - * @data - event data returned in fw reply message - */ -struct MPT3_IOCTL_EVENTS { - uint32_t event; - uint32_t context; - uint8_t data[MPT3_EVENT_DATA_SIZE]; -}; - -/** - * struct mpt3_ioctl_eventreport - returing event log - * @hdr - generic header - * @event_data - (see struct MPT3_IOCTL_EVENTS) - */ -struct mpt3_ioctl_eventreport { - struct mpt3_ioctl_header hdr; - struct MPT3_IOCTL_EVENTS event_data[1]; -}; - -/** - * struct mpt3_ioctl_command - generic mpt firmware passthru ioctl - * @hdr - generic header - * @timeout - command timeout in seconds. (if zero then use driver default - * value). - * @reply_frame_buf_ptr - reply location - * @data_in_buf_ptr - destination for read - * @data_out_buf_ptr - data source for write - * @sense_data_ptr - sense data location - * @max_reply_bytes - maximum number of reply bytes to be sent to app. - * @data_in_size - number bytes for data transfer in (read) - * @data_out_size - number bytes for data transfer out (write) - * @max_sense_bytes - maximum number of bytes for auto sense buffers - * @data_sge_offset - offset in words from the start of the request message to - * the first SGL - * @mf[1]; - */ -struct mpt3_ioctl_command { - struct mpt3_ioctl_header hdr; - uint32_t timeout; - void __user *reply_frame_buf_ptr; - void __user *data_in_buf_ptr; - void __user *data_out_buf_ptr; - void __user *sense_data_ptr; - uint32_t max_reply_bytes; - uint32_t data_in_size; - uint32_t data_out_size; - uint32_t max_sense_bytes; - uint32_t data_sge_offset; - uint8_t mf[1]; -}; - -#ifdef CONFIG_COMPAT -struct mpt3_ioctl_command32 { - struct mpt3_ioctl_header hdr; - uint32_t timeout; - uint32_t reply_frame_buf_ptr; - uint32_t data_in_buf_ptr; - uint32_t data_out_buf_ptr; - uint32_t sense_data_ptr; - uint32_t max_reply_bytes; - uint32_t data_in_size; - uint32_t data_out_size; - uint32_t max_sense_bytes; - uint32_t data_sge_offset; - uint8_t mf[1]; -}; -#endif - -/** - * struct mpt3_ioctl_btdh_mapping - mapping info - * @hdr - generic header - * @id - target device identification number - * @bus - SCSI bus number that the target device exists on - * @handle - device handle for the target device - * @rsvd - reserved - * - * To obtain a bus/id the application sets - * handle to valid handle, and bus/id to 0xFFFF. - * - * To obtain the device handle the application sets - * bus/id valid value, and the handle to 0xFFFF. - */ -struct mpt3_ioctl_btdh_mapping { - struct mpt3_ioctl_header hdr; - uint32_t id; - uint32_t bus; - uint16_t handle; - uint16_t rsvd; -}; - - - -/* application flags for mpt3_diag_register, mpt3_diag_query */ -#define MPT3_APP_FLAGS_APP_OWNED (0x0001) -#define MPT3_APP_FLAGS_BUFFER_VALID (0x0002) -#define MPT3_APP_FLAGS_FW_BUFFER_ACCESS (0x0004) - -/* flags for mpt3_diag_read_buffer */ -#define MPT3_FLAGS_REREGISTER (0x0001) - -#define MPT3_PRODUCT_SPECIFIC_DWORDS 23 - -/** - * struct mpt3_diag_register - application register with driver - * @hdr - generic header - * @reserved - - * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED - * @application_flags - misc flags - * @diagnostic_flags - specifies flags affecting command processing - * @product_specific - product specific information - * @requested_buffer_size - buffers size in bytes - * @unique_id - tag specified by application that is used to signal ownership - * of the buffer. - * - * This will allow the driver to setup any required buffers that will be - * needed by firmware to communicate with the driver. - */ -struct mpt3_diag_register { - struct mpt3_ioctl_header hdr; - uint8_t reserved; - uint8_t buffer_type; - uint16_t application_flags; - uint32_t diagnostic_flags; - uint32_t product_specific[MPT3_PRODUCT_SPECIFIC_DWORDS]; - uint32_t requested_buffer_size; - uint32_t unique_id; -}; - -/** - * struct mpt3_diag_unregister - application unregister with driver - * @hdr - generic header - * @unique_id - tag uniquely identifies the buffer to be unregistered - * - * This will allow the driver to cleanup any memory allocated for diag - * messages and to free up any resources. - */ -struct mpt3_diag_unregister { - struct mpt3_ioctl_header hdr; - uint32_t unique_id; -}; - -/** - * struct mpt3_diag_query - query relevant info associated with diag buffers - * @hdr - generic header - * @reserved - - * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED - * @application_flags - misc flags - * @diagnostic_flags - specifies flags affecting command processing - * @product_specific - product specific information - * @total_buffer_size - diag buffer size in bytes - * @driver_added_buffer_size - size of extra space appended to end of buffer - * @unique_id - unique id associated with this buffer. - * - * The application will send only buffer_type and unique_id. Driver will - * inspect unique_id first, if valid, fill in all the info. If unique_id is - * 0x00, the driver will return info specified by Buffer Type. - */ -struct mpt3_diag_query { - struct mpt3_ioctl_header hdr; - uint8_t reserved; - uint8_t buffer_type; - uint16_t application_flags; - uint32_t diagnostic_flags; - uint32_t product_specific[MPT3_PRODUCT_SPECIFIC_DWORDS]; - uint32_t total_buffer_size; - uint32_t driver_added_buffer_size; - uint32_t unique_id; -}; - -/** - * struct mpt3_diag_release - request to send Diag Release Message to firmware - * @hdr - generic header - * @unique_id - tag uniquely identifies the buffer to be released - * - * This allows ownership of the specified buffer to returned to the driver, - * allowing an application to read the buffer without fear that firmware is - * overwritting information in the buffer. - */ -struct mpt3_diag_release { - struct mpt3_ioctl_header hdr; - uint32_t unique_id; -}; - -/** - * struct mpt3_diag_read_buffer - request for copy of the diag buffer - * @hdr - generic header - * @status - - * @reserved - - * @flags - misc flags - * @starting_offset - starting offset within drivers buffer where to start - * reading data at into the specified application buffer - * @bytes_to_read - number of bytes to copy from the drivers buffer into the - * application buffer starting at starting_offset. - * @unique_id - unique id associated with this buffer. - * @diagnostic_data - data payload - */ -struct mpt3_diag_read_buffer { - struct mpt3_ioctl_header hdr; - uint8_t status; - uint8_t reserved; - uint16_t flags; - uint32_t starting_offset; - uint32_t bytes_to_read; - uint32_t unique_id; - uint32_t diagnostic_data[1]; -}; - -#endif /* MPT3SAS_CTL_H_INCLUDED */ diff --git a/addons/mpt3sas/src/3.10.108/mpt3sas_debug.h b/addons/mpt3sas/src/3.10.108/mpt3sas_debug.h deleted file mode 100644 index 35405e70..00000000 --- a/addons/mpt3sas/src/3.10.108/mpt3sas_debug.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Logging Support for MPT (Message Passing Technology) based controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_debug.c - * Copyright (C) 2012 LSI Corporation - * (mailto:DL-MPTFusionLinux@lsi.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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 MPT3SAS_DEBUG_H_INCLUDED -#define MPT3SAS_DEBUG_H_INCLUDED - -#define MPT_DEBUG 0x00000001 -#define MPT_DEBUG_MSG_FRAME 0x00000002 -#define MPT_DEBUG_SG 0x00000004 -#define MPT_DEBUG_EVENTS 0x00000008 -#define MPT_DEBUG_EVENT_WORK_TASK 0x00000010 -#define MPT_DEBUG_INIT 0x00000020 -#define MPT_DEBUG_EXIT 0x00000040 -#define MPT_DEBUG_FAIL 0x00000080 -#define MPT_DEBUG_TM 0x00000100 -#define MPT_DEBUG_REPLY 0x00000200 -#define MPT_DEBUG_HANDSHAKE 0x00000400 -#define MPT_DEBUG_CONFIG 0x00000800 -#define MPT_DEBUG_DL 0x00001000 -#define MPT_DEBUG_RESET 0x00002000 -#define MPT_DEBUG_SCSI 0x00004000 -#define MPT_DEBUG_IOCTL 0x00008000 -#define MPT_DEBUG_SAS 0x00020000 -#define MPT_DEBUG_TRANSPORT 0x00040000 -#define MPT_DEBUG_TASK_SET_FULL 0x00080000 - -#define MPT_DEBUG_TRIGGER_DIAG 0x00200000 - - -/* - * CONFIG_SCSI_MPT3SAS_LOGGING - enabled in Kconfig - */ - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING -#define MPT_CHECK_LOGGING(IOC, CMD, BITS) \ -{ \ - if (IOC->logging_level & BITS) \ - CMD; \ -} -#else -#define MPT_CHECK_LOGGING(IOC, CMD, BITS) -#endif /* CONFIG_SCSI_MPT3SAS_LOGGING */ - - -/* - * debug macros - */ - -#define dprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG) - -#define dsgprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SG) - -#define devtprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENTS) - -#define dewtprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENT_WORK_TASK) - -#define dinitprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_INIT) - -#define dexitprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EXIT) - -#define dfailprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FAIL) - -#define dtmprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TM) - -#define dreplyprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_REPLY) - -#define dhsprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_HANDSHAKE) - -#define dcprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CONFIG) - -#define ddlprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_DL) - -#define drsprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_RESET) - -#define dsprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SCSI) - -#define dctlprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_IOCTL) - -#define dsasprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS) - -#define dsastransport(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE) - -#define dmfprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_MSG_FRAME) - -#define dtsfprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TASK_SET_FULL) - -#define dtransportprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRANSPORT) - -#define dTriggerDiagPrintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRIGGER_DIAG) - - - -/* inline functions for dumping debug data*/ -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING -/** - * _debug_dump_mf - print message frame contents - * @mpi_request: pointer to message frame - * @sz: number of dwords - */ -static inline void -_debug_dump_mf(void *mpi_request, int sz) -{ - int i; - __le32 *mfp = (__le32 *)mpi_request; - - pr_info("mf:\n\t"); - for (i = 0; i < sz; i++) { - if (i && ((i % 8) == 0)) - pr_info("\n\t"); - pr_info("%08x ", le32_to_cpu(mfp[i])); - } - pr_info("\n"); -} -/** - * _debug_dump_reply - print message frame contents - * @mpi_request: pointer to message frame - * @sz: number of dwords - */ -static inline void -_debug_dump_reply(void *mpi_request, int sz) -{ - int i; - __le32 *mfp = (__le32 *)mpi_request; - - pr_info("reply:\n\t"); - for (i = 0; i < sz; i++) { - if (i && ((i % 8) == 0)) - pr_info("\n\t"); - pr_info("%08x ", le32_to_cpu(mfp[i])); - } - pr_info("\n"); -} -/** - * _debug_dump_config - print config page contents - * @mpi_request: pointer to message frame - * @sz: number of dwords - */ -static inline void -_debug_dump_config(void *mpi_request, int sz) -{ - int i; - __le32 *mfp = (__le32 *)mpi_request; - - pr_info("config:\n\t"); - for (i = 0; i < sz; i++) { - if (i && ((i % 8) == 0)) - pr_info("\n\t"); - pr_info("%08x ", le32_to_cpu(mfp[i])); - } - pr_info("\n"); -} -#else -#define _debug_dump_mf(mpi_request, sz) -#define _debug_dump_reply(mpi_request, sz) -#define _debug_dump_config(mpi_request, sz) -#endif /* CONFIG_SCSI_MPT3SAS_LOGGING */ - -#endif /* MPT3SAS_DEBUG_H_INCLUDED */ diff --git a/addons/mpt3sas/src/3.10.108/mpt3sas_scsih.c b/addons/mpt3sas/src/3.10.108/mpt3sas_scsih.c deleted file mode 100644 index 1d6e1155..00000000 --- a/addons/mpt3sas/src/3.10.108/mpt3sas_scsih.c +++ /dev/null @@ -1,8198 +0,0 @@ -/* - * Scsi Host Layer for MPT (Message Passing Technology) based controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_scsih.c - * Copyright (C) 2012 LSI Corporation - * (mailto:DL-MPTFusionLinux@lsi.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mpt3sas_base.h" - -MODULE_AUTHOR(MPT3SAS_AUTHOR); -MODULE_DESCRIPTION(MPT3SAS_DESCRIPTION); -MODULE_LICENSE("GPL"); -MODULE_VERSION(MPT3SAS_DRIVER_VERSION); - -#define RAID_CHANNEL 1 -/* forward proto's */ -static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_expander); -static void _firmware_event_work(struct work_struct *work); - -static void _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc, - struct _sas_device *sas_device); -static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u8 retry_count, u8 is_pd); - -static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid); - -static void _scsih_scan_start(struct Scsi_Host *shost); -static int _scsih_scan_finished(struct Scsi_Host *shost, unsigned long time); - -/* global parameters */ -LIST_HEAD(mpt3sas_ioc_list); - -/* local parameters */ -static u8 scsi_io_cb_idx = -1; -static u8 tm_cb_idx = -1; -static u8 ctl_cb_idx = -1; -static u8 base_cb_idx = -1; -static u8 port_enable_cb_idx = -1; -static u8 transport_cb_idx = -1; -static u8 scsih_cb_idx = -1; -static u8 config_cb_idx = -1; -static int mpt_ids; - -static u8 tm_tr_cb_idx = -1 ; -static u8 tm_tr_volume_cb_idx = -1 ; -static u8 tm_sas_control_cb_idx = -1; - -/* command line options */ -static u32 logging_level; -MODULE_PARM_DESC(logging_level, - " bits for enabling additional logging info (default=0)"); - - -static ushort max_sectors = 0xFFFF; -module_param(max_sectors, ushort, 0); -MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767 default=32767"); - - -static int missing_delay[2] = {-1, -1}; -module_param_array(missing_delay, int, NULL, 0); -MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay"); - -/* scsi-mid layer global parmeter is max_report_luns, which is 511 */ -#define MPT3SAS_MAX_LUN (16895) -static int max_lun = MPT3SAS_MAX_LUN; -module_param(max_lun, int, 0); -MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); - - - - -/* diag_buffer_enable is bitwise - * bit 0 set = TRACE - * bit 1 set = SNAPSHOT - * bit 2 set = EXTENDED - * - * Either bit can be set, or both - */ -static int diag_buffer_enable = -1; -module_param(diag_buffer_enable, int, 0); -MODULE_PARM_DESC(diag_buffer_enable, - " post diag buffers (TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)"); -static int disable_discovery = -1; -module_param(disable_discovery, int, 0); -MODULE_PARM_DESC(disable_discovery, " disable discovery "); - - -/* permit overriding the host protection capabilities mask (EEDP/T10 PI) */ -static int prot_mask = -1; -module_param(prot_mask, int, 0); -MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 "); - - -/* raid transport support */ - -static struct raid_template *mpt3sas_raid_template; - - -/** - * struct sense_info - common structure for obtaining sense keys - * @skey: sense key - * @asc: additional sense code - * @ascq: additional sense code qualifier - */ -struct sense_info { - u8 skey; - u8 asc; - u8 ascq; -}; - -#define MPT3SAS_PROCESS_TRIGGER_DIAG (0xFFFB) -#define MPT3SAS_TURN_ON_FAULT_LED (0xFFFC) -#define MPT3SAS_PORT_ENABLE_COMPLETE (0xFFFD) -#define MPT3SAS_ABRT_TASK_SET (0xFFFE) -#define MPT3SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF) -/** - * struct fw_event_work - firmware event struct - * @list: link list framework - * @work: work object (ioc->fault_reset_work_q) - * @cancel_pending_work: flag set during reset handling - * @ioc: per adapter object - * @device_handle: device handle - * @VF_ID: virtual function id - * @VP_ID: virtual port id - * @ignore: flag meaning this event has been marked to ignore - * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h - * @event_data: reply event data payload follows - * - * This object stored on ioc->fw_event_list. - */ -struct fw_event_work { - struct list_head list; - struct work_struct work; - u8 cancel_pending_work; - struct delayed_work delayed_work; - - struct MPT3SAS_ADAPTER *ioc; - u16 device_handle; - u8 VF_ID; - u8 VP_ID; - u8 ignore; - u16 event; - void *event_data; -}; - -/* raid transport support */ -static struct raid_template *mpt3sas_raid_template; - -/** - * struct _scsi_io_transfer - scsi io transfer - * @handle: sas device handle (assigned by firmware) - * @is_raid: flag set for hidden raid components - * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE, - * @data_length: data transfer length - * @data_dma: dma pointer to data - * @sense: sense data - * @lun: lun number - * @cdb_length: cdb length - * @cdb: cdb contents - * @timeout: timeout for this command - * @VF_ID: virtual function id - * @VP_ID: virtual port id - * @valid_reply: flag set for reply message - * @sense_length: sense length - * @ioc_status: ioc status - * @scsi_state: scsi state - * @scsi_status: scsi staus - * @log_info: log information - * @transfer_length: data length transfer when there is a reply message - * - * Used for sending internal scsi commands to devices within this module. - * Refer to _scsi_send_scsi_io(). - */ -struct _scsi_io_transfer { - u16 handle; - u8 is_raid; - enum dma_data_direction dir; - u32 data_length; - dma_addr_t data_dma; - u8 sense[SCSI_SENSE_BUFFERSIZE]; - u32 lun; - u8 cdb_length; - u8 cdb[32]; - u8 timeout; - u8 VF_ID; - u8 VP_ID; - u8 valid_reply; - /* the following bits are only valid when 'valid_reply = 1' */ - u32 sense_length; - u16 ioc_status; - u8 scsi_state; - u8 scsi_status; - u32 log_info; - u32 transfer_length; -}; - -/* - * The pci device ids are defined in mpi/mpi2_cnfg.h. - */ -static DEFINE_PCI_DEVICE_TABLE(scsih_pci_table) = { - /* Fury ~ 3004 and 3008 */ - { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008, - PCI_ANY_ID, PCI_ANY_ID }, - /* Invader ~ 3108 */ - { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6, - PCI_ANY_ID, PCI_ANY_ID }, - {0} /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(pci, scsih_pci_table); - -/** - * _scsih_set_debug_level - global setting of ioc->logging_level. - * - * Note: The logging levels are defined in mpt3sas_debug.h. - */ -static int -_scsih_set_debug_level(const char *val, struct kernel_param *kp) -{ - int ret = param_set_int(val, kp); - struct MPT3SAS_ADAPTER *ioc; - - if (ret) - return ret; - - pr_info("setting logging_level(0x%08x)\n", logging_level); - list_for_each_entry(ioc, &mpt3sas_ioc_list, list) - ioc->logging_level = logging_level; - return 0; -} -module_param_call(logging_level, _scsih_set_debug_level, param_get_int, - &logging_level, 0644); - -/** - * _scsih_srch_boot_sas_address - search based on sas_address - * @sas_address: sas address - * @boot_device: boot device object from bios page 2 - * - * Returns 1 when there's a match, 0 means no match. - */ -static inline int -_scsih_srch_boot_sas_address(u64 sas_address, - Mpi2BootDeviceSasWwid_t *boot_device) -{ - return (sas_address == le64_to_cpu(boot_device->SASAddress)) ? 1 : 0; -} - -/** - * _scsih_srch_boot_device_name - search based on device name - * @device_name: device name specified in INDENTIFY fram - * @boot_device: boot device object from bios page 2 - * - * Returns 1 when there's a match, 0 means no match. - */ -static inline int -_scsih_srch_boot_device_name(u64 device_name, - Mpi2BootDeviceDeviceName_t *boot_device) -{ - return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0; -} - -/** - * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot - * @enclosure_logical_id: enclosure logical id - * @slot_number: slot number - * @boot_device: boot device object from bios page 2 - * - * Returns 1 when there's a match, 0 means no match. - */ -static inline int -_scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number, - Mpi2BootDeviceEnclosureSlot_t *boot_device) -{ - return (enclosure_logical_id == le64_to_cpu(boot_device-> - EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device-> - SlotNumber)) ? 1 : 0; -} - -/** - * _scsih_is_boot_device - search for matching boot device. - * @sas_address: sas address - * @device_name: device name specified in INDENTIFY fram - * @enclosure_logical_id: enclosure logical id - * @slot_number: slot number - * @form: specifies boot device form - * @boot_device: boot device object from bios page 2 - * - * Returns 1 when there's a match, 0 means no match. - */ -static int -_scsih_is_boot_device(u64 sas_address, u64 device_name, - u64 enclosure_logical_id, u16 slot, u8 form, - Mpi2BiosPage2BootDevice_t *boot_device) -{ - int rc = 0; - - switch (form) { - case MPI2_BIOSPAGE2_FORM_SAS_WWID: - if (!sas_address) - break; - rc = _scsih_srch_boot_sas_address( - sas_address, &boot_device->SasWwid); - break; - case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT: - if (!enclosure_logical_id) - break; - rc = _scsih_srch_boot_encl_slot( - enclosure_logical_id, - slot, &boot_device->EnclosureSlot); - break; - case MPI2_BIOSPAGE2_FORM_DEVICE_NAME: - if (!device_name) - break; - rc = _scsih_srch_boot_device_name( - device_name, &boot_device->DeviceName); - break; - case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED: - break; - } - - return rc; -} - -/** - * _scsih_get_sas_address - set the sas_address for given device handle - * @handle: device handle - * @sas_address: sas address - * - * Returns 0 success, non-zero when failure - */ -static int -_scsih_get_sas_address(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u64 *sas_address) -{ - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2ConfigReply_t mpi_reply; - u32 ioc_status; - - *sas_address = 0; - - if (handle <= ioc->sas_hba.num_phys) { - *sas_address = ioc->sas_hba.sas_address; - return 0; - } - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__); - return -ENXIO; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { - *sas_address = le64_to_cpu(sas_device_pg0.SASAddress); - return 0; - } - - /* we hit this becuase the given parent handle doesn't exist */ - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) - return -ENXIO; - - /* else error case */ - pr_err(MPT3SAS_FMT - "handle(0x%04x), ioc_status(0x%04x), failure at %s:%d/%s()!\n", - ioc->name, handle, ioc_status, - __FILE__, __LINE__, __func__); - return -EIO; -} - -/** - * _scsih_determine_boot_device - determine boot device. - * @ioc: per adapter object - * @device: either sas_device or raid_device object - * @is_raid: [flag] 1 = raid object, 0 = sas object - * - * Determines whether this device should be first reported device to - * to scsi-ml or sas transport, this purpose is for persistent boot device. - * There are primary, alternate, and current entries in bios page 2. The order - * priority is primary, alternate, then current. This routine saves - * the corresponding device object and is_raid flag in the ioc object. - * The saved data to be used later in _scsih_probe_boot_devices(). - */ -static void -_scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc, - void *device, u8 is_raid) -{ - struct _sas_device *sas_device; - struct _raid_device *raid_device; - u64 sas_address; - u64 device_name; - u64 enclosure_logical_id; - u16 slot; - - /* only process this function when driver loads */ - if (!ioc->is_driver_loading) - return; - - /* no Bios, return immediately */ - if (!ioc->bios_pg3.BiosVersion) - return; - - if (!is_raid) { - sas_device = device; - sas_address = sas_device->sas_address; - device_name = sas_device->device_name; - enclosure_logical_id = sas_device->enclosure_logical_id; - slot = sas_device->slot; - } else { - raid_device = device; - sas_address = raid_device->wwid; - device_name = 0; - enclosure_logical_id = 0; - slot = 0; - } - - if (!ioc->req_boot_device.device) { - if (_scsih_is_boot_device(sas_address, device_name, - enclosure_logical_id, slot, - (ioc->bios_pg2.ReqBootDeviceForm & - MPI2_BIOSPAGE2_FORM_MASK), - &ioc->bios_pg2.RequestedBootDevice)) { - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "%s: req_boot_device(0x%016llx)\n", - ioc->name, __func__, - (unsigned long long)sas_address)); - ioc->req_boot_device.device = device; - ioc->req_boot_device.is_raid = is_raid; - } - } - - if (!ioc->req_alt_boot_device.device) { - if (_scsih_is_boot_device(sas_address, device_name, - enclosure_logical_id, slot, - (ioc->bios_pg2.ReqAltBootDeviceForm & - MPI2_BIOSPAGE2_FORM_MASK), - &ioc->bios_pg2.RequestedAltBootDevice)) { - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "%s: req_alt_boot_device(0x%016llx)\n", - ioc->name, __func__, - (unsigned long long)sas_address)); - ioc->req_alt_boot_device.device = device; - ioc->req_alt_boot_device.is_raid = is_raid; - } - } - - if (!ioc->current_boot_device.device) { - if (_scsih_is_boot_device(sas_address, device_name, - enclosure_logical_id, slot, - (ioc->bios_pg2.CurrentBootDeviceForm & - MPI2_BIOSPAGE2_FORM_MASK), - &ioc->bios_pg2.CurrentBootDevice)) { - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "%s: current_boot_device(0x%016llx)\n", - ioc->name, __func__, - (unsigned long long)sas_address)); - ioc->current_boot_device.device = device; - ioc->current_boot_device.is_raid = is_raid; - } - } -} - -/** - * mpt3sas_scsih_sas_device_find_by_sas_address - sas device search - * @ioc: per adapter object - * @sas_address: sas address - * Context: Calling function should acquire ioc->sas_device_lock - * - * This searches for sas_device based on sas_address, then return sas_device - * object. - */ -struct _sas_device * -mpt3sas_scsih_sas_device_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) -{ - struct _sas_device *sas_device; - - list_for_each_entry(sas_device, &ioc->sas_device_list, list) - if (sas_device->sas_address == sas_address) - return sas_device; - - list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) - if (sas_device->sas_address == sas_address) - return sas_device; - - return NULL; -} - -/** - * _scsih_sas_device_find_by_handle - sas device search - * @ioc: per adapter object - * @handle: sas device handle (assigned by firmware) - * Context: Calling function should acquire ioc->sas_device_lock - * - * This searches for sas_device based on sas_address, then return sas_device - * object. - */ -static struct _sas_device * -_scsih_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _sas_device *sas_device; - - list_for_each_entry(sas_device, &ioc->sas_device_list, list) - if (sas_device->handle == handle) - return sas_device; - - list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) - if (sas_device->handle == handle) - return sas_device; - - return NULL; -} - -/** - * _scsih_sas_device_remove - remove sas_device from list. - * @ioc: per adapter object - * @sas_device: the sas_device object - * Context: This function will acquire ioc->sas_device_lock. - * - * Removing object and freeing associated memory from the ioc->sas_device_list. - */ -static void -_scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc, - struct _sas_device *sas_device) -{ - unsigned long flags; - - if (!sas_device) - return; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - list_del(&sas_device->list); - kfree(sas_device); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); -} - -/** - * _scsih_device_remove_by_handle - removing device object by handle - * @ioc: per adapter object - * @handle: device handle - * - * Return nothing. - */ -static void -_scsih_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _sas_device *sas_device; - unsigned long flags; - - if (ioc->shost_recovery) - return; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _scsih_sas_device_find_by_handle(ioc, handle); - if (sas_device) - list_del(&sas_device->list); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (sas_device) - _scsih_remove_device(ioc, sas_device); -} - -/** - * mpt3sas_device_remove_by_sas_address - removing device object by sas address - * @ioc: per adapter object - * @sas_address: device sas_address - * - * Return nothing. - */ -void -mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) -{ - struct _sas_device *sas_device; - unsigned long flags; - - if (ioc->shost_recovery) - return; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - sas_address); - if (sas_device) - list_del(&sas_device->list); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (sas_device) - _scsih_remove_device(ioc, sas_device); -} - -/** - * _scsih_sas_device_add - insert sas_device to the list. - * @ioc: per adapter object - * @sas_device: the sas_device object - * Context: This function will acquire ioc->sas_device_lock. - * - * Adding new object to the ioc->sas_device_list. - */ -static void -_scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc, - struct _sas_device *sas_device) -{ - unsigned long flags; - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), sas_addr(0x%016llx)\n", - ioc->name, __func__, sas_device->handle, - (unsigned long long)sas_device->sas_address)); - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - list_add_tail(&sas_device->list, &ioc->sas_device_list); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - if (!mpt3sas_transport_port_add(ioc, sas_device->handle, - sas_device->sas_address_parent)) { - _scsih_sas_device_remove(ioc, sas_device); - } else if (!sas_device->starget) { - /* - * When asyn scanning is enabled, its not possible to remove - * devices while scanning is turned on due to an oops in - * scsi_sysfs_add_sdev()->add_device()->sysfs_addrm_start() - */ - if (!ioc->is_driver_loading) - mpt3sas_transport_port_remove(ioc, - sas_device->sas_address, - sas_device->sas_address_parent); - _scsih_sas_device_remove(ioc, sas_device); - } -} - -/** - * _scsih_sas_device_init_add - insert sas_device to the list. - * @ioc: per adapter object - * @sas_device: the sas_device object - * Context: This function will acquire ioc->sas_device_lock. - * - * Adding new object at driver load time to the ioc->sas_device_init_list. - */ -static void -_scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc, - struct _sas_device *sas_device) -{ - unsigned long flags; - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, - __func__, sas_device->handle, - (unsigned long long)sas_device->sas_address)); - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - list_add_tail(&sas_device->list, &ioc->sas_device_init_list); - _scsih_determine_boot_device(ioc, sas_device, 0); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); -} - -/** - * _scsih_raid_device_find_by_id - raid device search - * @ioc: per adapter object - * @id: sas device target id - * @channel: sas device channel - * Context: Calling function should acquire ioc->raid_device_lock - * - * This searches for raid_device based on target id, then return raid_device - * object. - */ -static struct _raid_device * -_scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel) -{ - struct _raid_device *raid_device, *r; - - r = NULL; - list_for_each_entry(raid_device, &ioc->raid_device_list, list) { - if (raid_device->id == id && raid_device->channel == channel) { - r = raid_device; - goto out; - } - } - - out: - return r; -} - -/** - * _scsih_raid_device_find_by_handle - raid device search - * @ioc: per adapter object - * @handle: sas device handle (assigned by firmware) - * Context: Calling function should acquire ioc->raid_device_lock - * - * This searches for raid_device based on handle, then return raid_device - * object. - */ -static struct _raid_device * -_scsih_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _raid_device *raid_device, *r; - - r = NULL; - list_for_each_entry(raid_device, &ioc->raid_device_list, list) { - if (raid_device->handle != handle) - continue; - r = raid_device; - goto out; - } - - out: - return r; -} - -/** - * _scsih_raid_device_find_by_wwid - raid device search - * @ioc: per adapter object - * @handle: sas device handle (assigned by firmware) - * Context: Calling function should acquire ioc->raid_device_lock - * - * This searches for raid_device based on wwid, then return raid_device - * object. - */ -static struct _raid_device * -_scsih_raid_device_find_by_wwid(struct MPT3SAS_ADAPTER *ioc, u64 wwid) -{ - struct _raid_device *raid_device, *r; - - r = NULL; - list_for_each_entry(raid_device, &ioc->raid_device_list, list) { - if (raid_device->wwid != wwid) - continue; - r = raid_device; - goto out; - } - - out: - return r; -} - -/** - * _scsih_raid_device_add - add raid_device object - * @ioc: per adapter object - * @raid_device: raid_device object - * - * This is added to the raid_device_list link list. - */ -static void -_scsih_raid_device_add(struct MPT3SAS_ADAPTER *ioc, - struct _raid_device *raid_device) -{ - unsigned long flags; - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__, - raid_device->handle, (unsigned long long)raid_device->wwid)); - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - list_add_tail(&raid_device->list, &ioc->raid_device_list); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); -} - -/** - * _scsih_raid_device_remove - delete raid_device object - * @ioc: per adapter object - * @raid_device: raid_device object - * - */ -static void -_scsih_raid_device_remove(struct MPT3SAS_ADAPTER *ioc, - struct _raid_device *raid_device) -{ - unsigned long flags; - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - list_del(&raid_device->list); - kfree(raid_device); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); -} - -/** - * mpt3sas_scsih_expander_find_by_handle - expander device search - * @ioc: per adapter object - * @handle: expander handle (assigned by firmware) - * Context: Calling function should acquire ioc->sas_device_lock - * - * This searches for expander device based on handle, then returns the - * sas_node object. - */ -struct _sas_node * -mpt3sas_scsih_expander_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _sas_node *sas_expander, *r; - - r = NULL; - list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { - if (sas_expander->handle != handle) - continue; - r = sas_expander; - goto out; - } - out: - return r; -} - -/** - * mpt3sas_scsih_expander_find_by_sas_address - expander device search - * @ioc: per adapter object - * @sas_address: sas address - * Context: Calling function should acquire ioc->sas_node_lock. - * - * This searches for expander device based on sas_address, then returns the - * sas_node object. - */ -struct _sas_node * -mpt3sas_scsih_expander_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) -{ - struct _sas_node *sas_expander, *r; - - r = NULL; - list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { - if (sas_expander->sas_address != sas_address) - continue; - r = sas_expander; - goto out; - } - out: - return r; -} - -/** - * _scsih_expander_node_add - insert expander device to the list. - * @ioc: per adapter object - * @sas_expander: the sas_device object - * Context: This function will acquire ioc->sas_node_lock. - * - * Adding new object to the ioc->sas_expander_list. - * - * Return nothing. - */ -static void -_scsih_expander_node_add(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_expander) -{ - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - list_add_tail(&sas_expander->list, &ioc->sas_expander_list); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); -} - -/** - * _scsih_is_end_device - determines if device is an end device - * @device_info: bitfield providing information about the device. - * Context: none - * - * Returns 1 if end device. - */ -static int -_scsih_is_end_device(u32 device_info) -{ - if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE && - ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) | - (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) | - (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE))) - return 1; - else - return 0; -} - -/** - * _scsih_scsi_lookup_get - returns scmd entry - * @ioc: per adapter object - * @smid: system request message index - * - * Returns the smid stored scmd pointer. - */ -static struct scsi_cmnd * -_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - return ioc->scsi_lookup[smid - 1].scmd; -} - -/** - * _scsih_scsi_lookup_get_clear - returns scmd entry - * @ioc: per adapter object - * @smid: system request message index - * - * Returns the smid stored scmd pointer. - * Then will derefrence the stored scmd pointer. - */ -static inline struct scsi_cmnd * -_scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - unsigned long flags; - struct scsi_cmnd *scmd; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - scmd = ioc->scsi_lookup[smid - 1].scmd; - ioc->scsi_lookup[smid - 1].scmd = NULL; - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - - return scmd; -} - -/** - * _scsih_scsi_lookup_find_by_scmd - scmd lookup - * @ioc: per adapter object - * @smid: system request message index - * @scmd: pointer to scsi command object - * Context: This function will acquire ioc->scsi_lookup_lock. - * - * This will search for a scmd pointer in the scsi_lookup array, - * returning the revelent smid. A returned value of zero means invalid. - */ -static u16 -_scsih_scsi_lookup_find_by_scmd(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd - *scmd) -{ - u16 smid; - unsigned long flags; - int i; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - smid = 0; - for (i = 0; i < ioc->scsiio_depth; i++) { - if (ioc->scsi_lookup[i].scmd == scmd) { - smid = ioc->scsi_lookup[i].smid; - goto out; - } - } - out: - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return smid; -} - -/** - * _scsih_scsi_lookup_find_by_target - search for matching channel:id - * @ioc: per adapter object - * @id: target id - * @channel: channel - * Context: This function will acquire ioc->scsi_lookup_lock. - * - * This will search for a matching channel:id in the scsi_lookup array, - * returning 1 if found. - */ -static u8 -_scsih_scsi_lookup_find_by_target(struct MPT3SAS_ADAPTER *ioc, int id, - int channel) -{ - u8 found; - unsigned long flags; - int i; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - found = 0; - for (i = 0 ; i < ioc->scsiio_depth; i++) { - if (ioc->scsi_lookup[i].scmd && - (ioc->scsi_lookup[i].scmd->device->id == id && - ioc->scsi_lookup[i].scmd->device->channel == channel)) { - found = 1; - goto out; - } - } - out: - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return found; -} - -/** - * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun - * @ioc: per adapter object - * @id: target id - * @lun: lun number - * @channel: channel - * Context: This function will acquire ioc->scsi_lookup_lock. - * - * This will search for a matching channel:id:lun in the scsi_lookup array, - * returning 1 if found. - */ -static u8 -_scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id, - unsigned int lun, int channel) -{ - u8 found; - unsigned long flags; - int i; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - found = 0; - for (i = 0 ; i < ioc->scsiio_depth; i++) { - if (ioc->scsi_lookup[i].scmd && - (ioc->scsi_lookup[i].scmd->device->id == id && - ioc->scsi_lookup[i].scmd->device->channel == channel && - ioc->scsi_lookup[i].scmd->device->lun == lun)) { - found = 1; - goto out; - } - } - out: - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return found; -} - - -static void -_scsih_adjust_queue_depth(struct scsi_device *sdev, int qdepth) -{ - struct Scsi_Host *shost = sdev->host; - int max_depth; - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct MPT3SAS_TARGET *sas_target_priv_data; - struct _sas_device *sas_device; - unsigned long flags; - - max_depth = shost->can_queue; - - /* limit max device queue for SATA to 32 */ - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - goto not_sata; - sas_target_priv_data = sas_device_priv_data->sas_target; - if (!sas_target_priv_data) - goto not_sata; - if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) - goto not_sata; - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - sas_device_priv_data->sas_target->sas_address); - if (sas_device && sas_device->device_info & - MPI2_SAS_DEVICE_INFO_SATA_DEVICE) - max_depth = MPT3SAS_SATA_QUEUE_DEPTH; - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - not_sata: - - if (!sdev->tagged_supported) - max_depth = 1; - if (qdepth > max_depth) - qdepth = max_depth; - scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), qdepth); -} - -/** - * _scsih_change_queue_depth - setting device queue depth - * @sdev: scsi device struct - * @qdepth: requested queue depth - * @reason: SCSI_QDEPTH_DEFAULT/SCSI_QDEPTH_QFULL/SCSI_QDEPTH_RAMP_UP - * (see include/scsi/scsi_host.h for definition) - * - * Returns queue depth. - */ -static int -_scsih_change_queue_depth(struct scsi_device *sdev, int qdepth, int reason) -{ - if (reason == SCSI_QDEPTH_DEFAULT || reason == SCSI_QDEPTH_RAMP_UP) - _scsih_adjust_queue_depth(sdev, qdepth); - else if (reason == SCSI_QDEPTH_QFULL) - scsi_track_queue_full(sdev, qdepth); - else - return -EOPNOTSUPP; - - if (sdev->inquiry_len > 7) - sdev_printk(KERN_INFO, sdev, "qdepth(%d), tagged(%d), " \ - "simple(%d), ordered(%d), scsi_level(%d), cmd_que(%d)\n", - sdev->queue_depth, sdev->tagged_supported, sdev->simple_tags, - sdev->ordered_tags, sdev->scsi_level, - (sdev->inquiry[7] & 2) >> 1); - - return sdev->queue_depth; -} - -/** - * _scsih_change_queue_type - changing device queue tag type - * @sdev: scsi device struct - * @tag_type: requested tag type - * - * Returns queue tag type. - */ -static int -_scsih_change_queue_type(struct scsi_device *sdev, int tag_type) -{ - if (sdev->tagged_supported) { - scsi_set_tag_type(sdev, tag_type); - if (tag_type) - scsi_activate_tcq(sdev, sdev->queue_depth); - else - scsi_deactivate_tcq(sdev, sdev->queue_depth); - } else - tag_type = 0; - - return tag_type; -} - - -/** - * _scsih_target_alloc - target add routine - * @starget: scsi target struct - * - * Returns 0 if ok. Any other return is assumed to be an error and - * the device is ignored. - */ -static int -_scsih_target_alloc(struct scsi_target *starget) -{ - struct Scsi_Host *shost = dev_to_shost(&starget->dev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - struct MPT3SAS_TARGET *sas_target_priv_data; - struct _sas_device *sas_device; - struct _raid_device *raid_device; - unsigned long flags; - struct sas_rphy *rphy; - - sas_target_priv_data = kzalloc(sizeof(struct scsi_target), GFP_KERNEL); - if (!sas_target_priv_data) - return -ENOMEM; - - starget->hostdata = sas_target_priv_data; - sas_target_priv_data->starget = starget; - sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE; - - /* RAID volumes */ - if (starget->channel == RAID_CHANNEL) { - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_id(ioc, starget->id, - starget->channel); - if (raid_device) { - sas_target_priv_data->handle = raid_device->handle; - sas_target_priv_data->sas_address = raid_device->wwid; - sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME; - raid_device->starget = starget; - } - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - return 0; - } - - /* sas/sata devices */ - spin_lock_irqsave(&ioc->sas_device_lock, flags); - rphy = dev_to_rphy(starget->dev.parent); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - rphy->identify.sas_address); - - if (sas_device) { - sas_target_priv_data->handle = sas_device->handle; - sas_target_priv_data->sas_address = sas_device->sas_address; - sas_device->starget = starget; - sas_device->id = starget->id; - sas_device->channel = starget->channel; - if (test_bit(sas_device->handle, ioc->pd_handles)) - sas_target_priv_data->flags |= - MPT_TARGET_FLAGS_RAID_COMPONENT; - if (sas_device->fast_path) - sas_target_priv_data->flags |= MPT_TARGET_FASTPATH_IO; - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - return 0; -} - -/** - * _scsih_target_destroy - target destroy routine - * @starget: scsi target struct - * - * Returns nothing. - */ -static void -_scsih_target_destroy(struct scsi_target *starget) -{ - struct Scsi_Host *shost = dev_to_shost(&starget->dev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - struct MPT3SAS_TARGET *sas_target_priv_data; - struct _sas_device *sas_device; - struct _raid_device *raid_device; - unsigned long flags; - struct sas_rphy *rphy; - - sas_target_priv_data = starget->hostdata; - if (!sas_target_priv_data) - return; - - if (starget->channel == RAID_CHANNEL) { - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_id(ioc, starget->id, - starget->channel); - if (raid_device) { - raid_device->starget = NULL; - raid_device->sdev = NULL; - } - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - goto out; - } - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - rphy = dev_to_rphy(starget->dev.parent); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - rphy->identify.sas_address); - if (sas_device && (sas_device->starget == starget) && - (sas_device->id == starget->id) && - (sas_device->channel == starget->channel)) - sas_device->starget = NULL; - - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - out: - kfree(sas_target_priv_data); - starget->hostdata = NULL; -} - -/** - * _scsih_slave_alloc - device add routine - * @sdev: scsi device struct - * - * Returns 0 if ok. Any other return is assumed to be an error and - * the device is ignored. - */ -static int -_scsih_slave_alloc(struct scsi_device *sdev) -{ - struct Scsi_Host *shost; - struct MPT3SAS_ADAPTER *ioc; - struct MPT3SAS_TARGET *sas_target_priv_data; - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_target *starget; - struct _raid_device *raid_device; - struct _sas_device *sas_device; - unsigned long flags; - - sas_device_priv_data = kzalloc(sizeof(struct scsi_device), GFP_KERNEL); - if (!sas_device_priv_data) - return -ENOMEM; - - sas_device_priv_data->lun = sdev->lun; - sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT; - - starget = scsi_target(sdev); - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->num_luns++; - sas_device_priv_data->sas_target = sas_target_priv_data; - sdev->hostdata = sas_device_priv_data; - if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT)) - sdev->no_uld_attach = 1; - - shost = dev_to_shost(&starget->dev); - ioc = shost_priv(shost); - if (starget->channel == RAID_CHANNEL) { - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_id(ioc, - starget->id, starget->channel); - if (raid_device) - raid_device->sdev = sdev; /* raid is single lun */ - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - } - - if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - sas_target_priv_data->sas_address); - if (sas_device && (sas_device->starget == NULL)) { - sdev_printk(KERN_INFO, sdev, - "%s : sas_device->starget set to starget @ %d\n", - __func__, __LINE__); - sas_device->starget = starget; - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - } - - return 0; -} - -/** - * _scsih_slave_destroy - device destroy routine - * @sdev: scsi device struct - * - * Returns nothing. - */ -static void -_scsih_slave_destroy(struct scsi_device *sdev) -{ - struct MPT3SAS_TARGET *sas_target_priv_data; - struct scsi_target *starget; - struct Scsi_Host *shost; - struct MPT3SAS_ADAPTER *ioc; - struct _sas_device *sas_device; - unsigned long flags; - - if (!sdev->hostdata) - return; - - starget = scsi_target(sdev); - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->num_luns--; - - shost = dev_to_shost(&starget->dev); - ioc = shost_priv(shost); - - if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - sas_target_priv_data->sas_address); - if (sas_device && !sas_target_priv_data->num_luns) - sas_device->starget = NULL; - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - } - - kfree(sdev->hostdata); - sdev->hostdata = NULL; -} - -/** - * _scsih_display_sata_capabilities - sata capabilities - * @ioc: per adapter object - * @handle: device handle - * @sdev: scsi device struct - */ -static void -_scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc, - u16 handle, struct scsi_device *sdev) -{ - Mpi2ConfigReply_t mpi_reply; - Mpi2SasDevicePage0_t sas_device_pg0; - u32 ioc_status; - u16 flags; - u32 device_info; - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - flags = le16_to_cpu(sas_device_pg0.Flags); - device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); - - sdev_printk(KERN_INFO, sdev, - "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), " - "sw_preserve(%s)\n", - (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n", - (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n", - (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" : - "n", - (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n", - (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n", - (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n"); -} - -/* - * raid transport support - - * Enabled for SLES11 and newer, in older kernels the driver will panic when - * unloading the driver followed by a load - I beleive that the subroutine - * raid_class_release() is not cleaning up properly. - */ - -/** - * _scsih_is_raid - return boolean indicating device is raid volume - * @dev the device struct object - */ -static int -_scsih_is_raid(struct device *dev) -{ - struct scsi_device *sdev = to_scsi_device(dev); - - return (sdev->channel == RAID_CHANNEL) ? 1 : 0; -} - -/** - * _scsih_get_resync - get raid volume resync percent complete - * @dev the device struct object - */ -static void -_scsih_get_resync(struct device *dev) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host); - static struct _raid_device *raid_device; - unsigned long flags; - Mpi2RaidVolPage0_t vol_pg0; - Mpi2ConfigReply_t mpi_reply; - u32 volume_status_flags; - u8 percent_complete; - u16 handle; - - percent_complete = 0; - handle = 0; - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id, - sdev->channel); - if (raid_device) { - handle = raid_device->handle; - percent_complete = raid_device->percent_complete; - } - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - - if (!handle) - goto out; - - if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0, - MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, - sizeof(Mpi2RaidVolPage0_t))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - percent_complete = 0; - goto out; - } - - volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags); - if (!(volume_status_flags & - MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS)) - percent_complete = 0; - - out: - raid_set_resync(mpt3sas_raid_template, dev, percent_complete); -} - -/** - * _scsih_get_state - get raid volume level - * @dev the device struct object - */ -static void -_scsih_get_state(struct device *dev) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host); - static struct _raid_device *raid_device; - unsigned long flags; - Mpi2RaidVolPage0_t vol_pg0; - Mpi2ConfigReply_t mpi_reply; - u32 volstate; - enum raid_state state = RAID_STATE_UNKNOWN; - u16 handle = 0; - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id, - sdev->channel); - if (raid_device) - handle = raid_device->handle; - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - - if (!raid_device) - goto out; - - if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0, - MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, - sizeof(Mpi2RaidVolPage0_t))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - - volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags); - if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) { - state = RAID_STATE_RESYNCING; - goto out; - } - - switch (vol_pg0.VolumeState) { - case MPI2_RAID_VOL_STATE_OPTIMAL: - case MPI2_RAID_VOL_STATE_ONLINE: - state = RAID_STATE_ACTIVE; - break; - case MPI2_RAID_VOL_STATE_DEGRADED: - state = RAID_STATE_DEGRADED; - break; - case MPI2_RAID_VOL_STATE_FAILED: - case MPI2_RAID_VOL_STATE_MISSING: - state = RAID_STATE_OFFLINE; - break; - } - out: - raid_set_state(mpt3sas_raid_template, dev, state); -} - -/** - * _scsih_set_level - set raid level - * @sdev: scsi device struct - * @volume_type: volume type - */ -static void -_scsih_set_level(struct scsi_device *sdev, u8 volume_type) -{ - enum raid_level level = RAID_LEVEL_UNKNOWN; - - switch (volume_type) { - case MPI2_RAID_VOL_TYPE_RAID0: - level = RAID_LEVEL_0; - break; - case MPI2_RAID_VOL_TYPE_RAID10: - level = RAID_LEVEL_10; - break; - case MPI2_RAID_VOL_TYPE_RAID1E: - level = RAID_LEVEL_1E; - break; - case MPI2_RAID_VOL_TYPE_RAID1: - level = RAID_LEVEL_1; - break; - } - - raid_set_level(mpt3sas_raid_template, &sdev->sdev_gendev, level); -} - - -/** - * _scsih_get_volume_capabilities - volume capabilities - * @ioc: per adapter object - * @sas_device: the raid_device object - * - * Returns 0 for success, else 1 - */ -static int -_scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc, - struct _raid_device *raid_device) -{ - Mpi2RaidVolPage0_t *vol_pg0; - Mpi2RaidPhysDiskPage0_t pd_pg0; - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2ConfigReply_t mpi_reply; - u16 sz; - u8 num_pds; - - if ((mpt3sas_config_get_number_pds(ioc, raid_device->handle, - &num_pds)) || !num_pds) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, - __func__)); - return 1; - } - - raid_device->num_pds = num_pds; - sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds * - sizeof(Mpi2RaidVol0PhysDisk_t)); - vol_pg0 = kzalloc(sz, GFP_KERNEL); - if (!vol_pg0) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, - __func__)); - return 1; - } - - if ((mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0, - MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, - __func__)); - kfree(vol_pg0); - return 1; - } - - raid_device->volume_type = vol_pg0->VolumeType; - - /* figure out what the underlying devices are by - * obtaining the device_info bits for the 1st device - */ - if (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply, - &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM, - vol_pg0->PhysDisk[0].PhysDiskNum))) { - if (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, - &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, - le16_to_cpu(pd_pg0.DevHandle)))) { - raid_device->device_info = - le32_to_cpu(sas_device_pg0.DeviceInfo); - } - } - - kfree(vol_pg0); - return 0; -} - - - -/** - * _scsih_enable_tlr - setting TLR flags - * @ioc: per adapter object - * @sdev: scsi device struct - * - * Enabling Transaction Layer Retries for tape devices when - * vpd page 0x90 is present - * - */ -static void -_scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev) -{ - - /* only for TAPE */ - if (sdev->type != TYPE_TAPE) - return; - - if (!(ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR)) - return; - - sas_enable_tlr(sdev); - sdev_printk(KERN_INFO, sdev, "TLR %s\n", - sas_is_tlr_enabled(sdev) ? "Enabled" : "Disabled"); - return; - -} - -/** - * _scsih_slave_configure - device configure routine. - * @sdev: scsi device struct - * - * Returns 0 if ok. Any other return is assumed to be an error and - * the device is ignored. - */ -static int -_scsih_slave_configure(struct scsi_device *sdev) -{ - struct Scsi_Host *shost = sdev->host; - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct MPT3SAS_TARGET *sas_target_priv_data; - struct _sas_device *sas_device; - struct _raid_device *raid_device; - unsigned long flags; - int qdepth; - u8 ssp_target = 0; - char *ds = ""; - char *r_level = ""; - u16 handle, volume_handle = 0; - u64 volume_wwid = 0; - - qdepth = 1; - sas_device_priv_data = sdev->hostdata; - sas_device_priv_data->configured_lun = 1; - sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT; - sas_target_priv_data = sas_device_priv_data->sas_target; - handle = sas_target_priv_data->handle; - - /* raid volume handling */ - if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) { - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_handle(ioc, handle); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - if (!raid_device) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, __FILE__, - __LINE__, __func__)); - return 1; - } - - if (_scsih_get_volume_capabilities(ioc, raid_device)) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, __FILE__, - __LINE__, __func__)); - return 1; - } - - - /* RAID Queue Depth Support - * IS volume = underlying qdepth of drive type, either - * MPT3SAS_SAS_QUEUE_DEPTH or MPT3SAS_SATA_QUEUE_DEPTH - * IM/IME/R10 = 128 (MPT3SAS_RAID_QUEUE_DEPTH) - */ - if (raid_device->device_info & - MPI2_SAS_DEVICE_INFO_SSP_TARGET) { - qdepth = MPT3SAS_SAS_QUEUE_DEPTH; - ds = "SSP"; - } else { - qdepth = MPT3SAS_SATA_QUEUE_DEPTH; - if (raid_device->device_info & - MPI2_SAS_DEVICE_INFO_SATA_DEVICE) - ds = "SATA"; - else - ds = "STP"; - } - - switch (raid_device->volume_type) { - case MPI2_RAID_VOL_TYPE_RAID0: - r_level = "RAID0"; - break; - case MPI2_RAID_VOL_TYPE_RAID1E: - qdepth = MPT3SAS_RAID_QUEUE_DEPTH; - if (ioc->manu_pg10.OEMIdentifier && - (le32_to_cpu(ioc->manu_pg10.GenericFlags0) & - MFG10_GF0_R10_DISPLAY) && - !(raid_device->num_pds % 2)) - r_level = "RAID10"; - else - r_level = "RAID1E"; - break; - case MPI2_RAID_VOL_TYPE_RAID1: - qdepth = MPT3SAS_RAID_QUEUE_DEPTH; - r_level = "RAID1"; - break; - case MPI2_RAID_VOL_TYPE_RAID10: - qdepth = MPT3SAS_RAID_QUEUE_DEPTH; - r_level = "RAID10"; - break; - case MPI2_RAID_VOL_TYPE_UNKNOWN: - default: - qdepth = MPT3SAS_RAID_QUEUE_DEPTH; - r_level = "RAIDX"; - break; - } - - sdev_printk(KERN_INFO, sdev, - "%s: handle(0x%04x), wwid(0x%016llx), pd_count(%d), type(%s)\n", - r_level, raid_device->handle, - (unsigned long long)raid_device->wwid, - raid_device->num_pds, ds); - - - _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); - -/* raid transport support */ - _scsih_set_level(sdev, raid_device->volume_type); - return 0; - } - - /* non-raid handling */ - if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) { - if (mpt3sas_config_get_volume_handle(ioc, handle, - &volume_handle)) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__)); - return 1; - } - if (volume_handle && mpt3sas_config_get_volume_wwid(ioc, - volume_handle, &volume_wwid)) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__)); - return 1; - } - } - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - sas_device_priv_data->sas_target->sas_address); - if (!sas_device) { - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, - __func__)); - return 1; - } - - sas_device->volume_handle = volume_handle; - sas_device->volume_wwid = volume_wwid; - if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) { - qdepth = MPT3SAS_SAS_QUEUE_DEPTH; - ssp_target = 1; - ds = "SSP"; - } else { - qdepth = MPT3SAS_SATA_QUEUE_DEPTH; - if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) - ds = "STP"; - else if (sas_device->device_info & - MPI2_SAS_DEVICE_INFO_SATA_DEVICE) - ds = "SATA"; - } - - sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), " \ - "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n", - ds, handle, (unsigned long long)sas_device->sas_address, - sas_device->phy, (unsigned long long)sas_device->device_name); - sdev_printk(KERN_INFO, sdev, - "%s: enclosure_logical_id(0x%016llx), slot(%d)\n", - ds, (unsigned long long) - sas_device->enclosure_logical_id, sas_device->slot); - - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - if (!ssp_target) - _scsih_display_sata_capabilities(ioc, handle, sdev); - - - _scsih_change_queue_depth(sdev, qdepth, SCSI_QDEPTH_DEFAULT); - - if (ssp_target) { - sas_read_port_mode_page(sdev); - _scsih_enable_tlr(ioc, sdev); - } - - return 0; -} - -/** - * _scsih_bios_param - fetch head, sector, cylinder info for a disk - * @sdev: scsi device struct - * @bdev: pointer to block device context - * @capacity: device size (in 512 byte sectors) - * @params: three element array to place output: - * params[0] number of heads (max 255) - * params[1] number of sectors (max 63) - * params[2] number of cylinders - * - * Return nothing. - */ -static int -_scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int params[]) -{ - int heads; - int sectors; - sector_t cylinders; - ulong dummy; - - heads = 64; - sectors = 32; - - dummy = heads * sectors; - cylinders = capacity; - sector_div(cylinders, dummy); - - /* - * Handle extended translation size for logical drives - * > 1Gb - */ - if ((ulong)capacity >= 0x200000) { - heads = 255; - sectors = 63; - dummy = heads * sectors; - cylinders = capacity; - sector_div(cylinders, dummy); - } - - /* return result */ - params[0] = heads; - params[1] = sectors; - params[2] = cylinders; - - return 0; -} - -/** - * _scsih_response_code - translation of device response code - * @ioc: per adapter object - * @response_code: response code returned by the device - * - * Return nothing. - */ -static void -_scsih_response_code(struct MPT3SAS_ADAPTER *ioc, u8 response_code) -{ - char *desc; - - switch (response_code) { - case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE: - desc = "task management request completed"; - break; - case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME: - desc = "invalid frame"; - break; - case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: - desc = "task management request not supported"; - break; - case MPI2_SCSITASKMGMT_RSP_TM_FAILED: - desc = "task management request failed"; - break; - case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED: - desc = "task management request succeeded"; - break; - case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN: - desc = "invalid lun"; - break; - case 0xA: - desc = "overlapped tag attempted"; - break; - case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: - desc = "task queued, however not sent to target"; - break; - default: - desc = "unknown"; - break; - } - pr_warn(MPT3SAS_FMT "response_code(0x%01x): %s\n", - ioc->name, response_code, desc); -} - -/** - * _scsih_tm_done - tm completion routine - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: none. - * - * The callback handler when using scsih_issue_tm. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_tm_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - - if (ioc->tm_cmds.status == MPT3_CMD_NOT_USED) - return 1; - if (ioc->tm_cmds.smid != smid) - return 1; - mpt3sas_base_flush_reply_queues(ioc); - ioc->tm_cmds.status |= MPT3_CMD_COMPLETE; - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (mpi_reply) { - memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); - ioc->tm_cmds.status |= MPT3_CMD_REPLY_VALID; - } - ioc->tm_cmds.status &= ~MPT3_CMD_PENDING; - complete(&ioc->tm_cmds.done); - return 1; -} - -/** - * mpt3sas_scsih_set_tm_flag - set per target tm_busy - * @ioc: per adapter object - * @handle: device handle - * - * During taskmangement request, we need to freeze the device queue. - */ -void -mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - u8 skip = 0; - - shost_for_each_device(sdev, ioc->shost) { - if (skip) - continue; - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - continue; - if (sas_device_priv_data->sas_target->handle == handle) { - sas_device_priv_data->sas_target->tm_busy = 1; - skip = 1; - ioc->ignore_loginfos = 1; - } - } -} - -/** - * mpt3sas_scsih_clear_tm_flag - clear per target tm_busy - * @ioc: per adapter object - * @handle: device handle - * - * During taskmangement request, we need to freeze the device queue. - */ -void -mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - u8 skip = 0; - - shost_for_each_device(sdev, ioc->shost) { - if (skip) - continue; - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - continue; - if (sas_device_priv_data->sas_target->handle == handle) { - sas_device_priv_data->sas_target->tm_busy = 0; - skip = 1; - ioc->ignore_loginfos = 0; - } - } -} - -/** - * mpt3sas_scsih_issue_tm - main routine for sending tm requests - * @ioc: per adapter struct - * @device_handle: device handle - * @channel: the channel assigned by the OS - * @id: the id assigned by the OS - * @lun: lun number - * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h) - * @smid_task: smid assigned to the task - * @timeout: timeout in seconds - * @serial_number: the serial_number from scmd - * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF - * Context: user - * - * A generic API for sending task management requests to firmware. - * - * The callback index is set inside `ioc->tm_cb_idx`. - * - * Return SUCCESS or FAILED. - */ -int -mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel, - uint id, uint lun, u8 type, u16 smid_task, ulong timeout, - unsigned long serial_number, enum mutex_type m_type) -{ - Mpi2SCSITaskManagementRequest_t *mpi_request; - Mpi2SCSITaskManagementReply_t *mpi_reply; - u16 smid = 0; - u32 ioc_state; - unsigned long timeleft; - struct scsiio_tracker *scsi_lookup = NULL; - int rc; - - if (m_type == TM_MUTEX_ON) - mutex_lock(&ioc->tm_cmds.mutex); - if (ioc->tm_cmds.status != MPT3_CMD_NOT_USED) { - pr_info(MPT3SAS_FMT "%s: tm_cmd busy!!!\n", - __func__, ioc->name); - rc = FAILED; - goto err_out; - } - - if (ioc->shost_recovery || ioc->remove_host || - ioc->pci_error_recovery) { - pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", - __func__, ioc->name); - rc = FAILED; - goto err_out; - } - - ioc_state = mpt3sas_base_get_iocstate(ioc, 0); - if (ioc_state & MPI2_DOORBELL_USED) { - dhsprintk(ioc, pr_info(MPT3SAS_FMT - "unexpected doorbell active!\n", ioc->name)); - rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - rc = (!rc) ? SUCCESS : FAILED; - goto err_out; - } - - if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { - mpt3sas_base_fault_info(ioc, ioc_state & - MPI2_DOORBELL_DATA_MASK); - rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - rc = (!rc) ? SUCCESS : FAILED; - goto err_out; - } - - smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = FAILED; - goto err_out; - } - - if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) - scsi_lookup = &ioc->scsi_lookup[smid_task - 1]; - - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "sending tm: handle(0x%04x), task_type(0x%02x), smid(%d)\n", - ioc->name, handle, type, smid_task)); - ioc->tm_cmds.status = MPT3_CMD_PENDING; - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->tm_cmds.smid = smid; - memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); - memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t)); - mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; - mpi_request->DevHandle = cpu_to_le16(handle); - mpi_request->TaskType = type; - mpi_request->TaskMID = cpu_to_le16(smid_task); - int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN); - mpt3sas_scsih_set_tm_flag(ioc, handle); - init_completion(&ioc->tm_cmds.done); - mpt3sas_base_put_smid_hi_priority(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ); - if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SCSITaskManagementRequest_t)/4); - if (!(ioc->tm_cmds.status & MPT3_CMD_RESET)) { - rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - rc = (!rc) ? SUCCESS : FAILED; - ioc->tm_cmds.status = MPT3_CMD_NOT_USED; - mpt3sas_scsih_clear_tm_flag(ioc, handle); - goto err_out; - } - } - - if (ioc->tm_cmds.status & MPT3_CMD_REPLY_VALID) { - mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT); - mpi_reply = ioc->tm_cmds.reply; - dtmprintk(ioc, pr_info(MPT3SAS_FMT "complete tm: " \ - "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo), - le32_to_cpu(mpi_reply->TerminationCount))); - if (ioc->logging_level & MPT_DEBUG_TM) { - _scsih_response_code(ioc, mpi_reply->ResponseCode); - if (mpi_reply->IOCStatus) - _debug_dump_mf(mpi_request, - sizeof(Mpi2SCSITaskManagementRequest_t)/4); - } - } - - switch (type) { - case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK: - rc = SUCCESS; - if (scsi_lookup->scmd == NULL) - break; - rc = FAILED; - break; - - case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET: - if (_scsih_scsi_lookup_find_by_target(ioc, id, channel)) - rc = FAILED; - else - rc = SUCCESS; - break; - case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET: - case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET: - if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel)) - rc = FAILED; - else - rc = SUCCESS; - break; - case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK: - rc = SUCCESS; - break; - default: - rc = FAILED; - break; - } - - mpt3sas_scsih_clear_tm_flag(ioc, handle); - ioc->tm_cmds.status = MPT3_CMD_NOT_USED; - if (m_type == TM_MUTEX_ON) - mutex_unlock(&ioc->tm_cmds.mutex); - - return rc; - - err_out: - if (m_type == TM_MUTEX_ON) - mutex_unlock(&ioc->tm_cmds.mutex); - return rc; -} - -/** - * _scsih_tm_display_info - displays info about the device - * @ioc: per adapter struct - * @scmd: pointer to scsi command object - * - * Called by task management callback handlers. - */ -static void -_scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) -{ - struct scsi_target *starget = scmd->device->sdev_target; - struct MPT3SAS_TARGET *priv_target = starget->hostdata; - struct _sas_device *sas_device = NULL; - unsigned long flags; - char *device_str = NULL; - - if (!priv_target) - return; - device_str = "volume"; - - scsi_print_command(scmd); - if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) { - starget_printk(KERN_INFO, starget, - "%s handle(0x%04x), %s wwid(0x%016llx)\n", - device_str, priv_target->handle, - device_str, (unsigned long long)priv_target->sas_address); - } else { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - priv_target->sas_address); - if (sas_device) { - if (priv_target->flags & - MPT_TARGET_FLAGS_RAID_COMPONENT) { - starget_printk(KERN_INFO, starget, - "volume handle(0x%04x), " - "volume wwid(0x%016llx)\n", - sas_device->volume_handle, - (unsigned long long)sas_device->volume_wwid); - } - starget_printk(KERN_INFO, starget, - "handle(0x%04x), sas_address(0x%016llx), phy(%d)\n", - sas_device->handle, - (unsigned long long)sas_device->sas_address, - sas_device->phy); - starget_printk(KERN_INFO, starget, - "enclosure_logical_id(0x%016llx), slot(%d)\n", - (unsigned long long)sas_device->enclosure_logical_id, - sas_device->slot); - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - } -} - -/** - * _scsih_abort - eh threads main abort routine - * @scmd: pointer to scsi command object - * - * Returns SUCCESS if command aborted else FAILED - */ -static int -_scsih_abort(struct scsi_cmnd *scmd) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); - struct MPT3SAS_DEVICE *sas_device_priv_data; - u16 smid; - u16 handle; - int r; - - sdev_printk(KERN_INFO, scmd->device, - "attempting task abort! scmd(%p)\n", scmd); - _scsih_tm_display_info(ioc, scmd); - - sas_device_priv_data = scmd->device->hostdata; - if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { - sdev_printk(KERN_INFO, scmd->device, - "device been deleted! scmd(%p)\n", scmd); - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - r = SUCCESS; - goto out; - } - - /* search for the command */ - smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd); - if (!smid) { - scmd->result = DID_RESET << 16; - r = SUCCESS; - goto out; - } - - /* for hidden raid components and volumes this is not supported */ - if (sas_device_priv_data->sas_target->flags & - MPT_TARGET_FLAGS_RAID_COMPONENT || - sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) { - scmd->result = DID_RESET << 16; - r = FAILED; - goto out; - } - - mpt3sas_halt_firmware(ioc); - - handle = sas_device_priv_data->sas_target->handle; - r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel, - scmd->device->id, scmd->device->lun, - MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, - scmd->serial_number, TM_MUTEX_ON); - - out: - sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n", - ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); - return r; -} - -/** - * _scsih_dev_reset - eh threads main device reset routine - * @scmd: pointer to scsi command object - * - * Returns SUCCESS if command aborted else FAILED - */ -static int -_scsih_dev_reset(struct scsi_cmnd *scmd) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct _sas_device *sas_device; - unsigned long flags; - u16 handle; - int r; - - sdev_printk(KERN_INFO, scmd->device, - "attempting device reset! scmd(%p)\n", scmd); - _scsih_tm_display_info(ioc, scmd); - - sas_device_priv_data = scmd->device->hostdata; - if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { - sdev_printk(KERN_INFO, scmd->device, - "device been deleted! scmd(%p)\n", scmd); - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - r = SUCCESS; - goto out; - } - - /* for hidden raid components obtain the volume_handle */ - handle = 0; - if (sas_device_priv_data->sas_target->flags & - MPT_TARGET_FLAGS_RAID_COMPONENT) { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _scsih_sas_device_find_by_handle(ioc, - sas_device_priv_data->sas_target->handle); - if (sas_device) - handle = sas_device->volume_handle; - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - } else - handle = sas_device_priv_data->sas_target->handle; - - if (!handle) { - scmd->result = DID_RESET << 16; - r = FAILED; - goto out; - } - - r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel, - scmd->device->id, scmd->device->lun, - MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, 0, - TM_MUTEX_ON); - - out: - sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n", - ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); - return r; -} - -/** - * _scsih_target_reset - eh threads main target reset routine - * @scmd: pointer to scsi command object - * - * Returns SUCCESS if command aborted else FAILED - */ -static int -_scsih_target_reset(struct scsi_cmnd *scmd) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct _sas_device *sas_device; - unsigned long flags; - u16 handle; - int r; - struct scsi_target *starget = scmd->device->sdev_target; - - starget_printk(KERN_INFO, starget, "attempting target reset! scmd(%p)\n", - scmd); - _scsih_tm_display_info(ioc, scmd); - - sas_device_priv_data = scmd->device->hostdata; - if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { - starget_printk(KERN_INFO, starget, "target been deleted! scmd(%p)\n", - scmd); - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - r = SUCCESS; - goto out; - } - - /* for hidden raid components obtain the volume_handle */ - handle = 0; - if (sas_device_priv_data->sas_target->flags & - MPT_TARGET_FLAGS_RAID_COMPONENT) { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _scsih_sas_device_find_by_handle(ioc, - sas_device_priv_data->sas_target->handle); - if (sas_device) - handle = sas_device->volume_handle; - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - } else - handle = sas_device_priv_data->sas_target->handle; - - if (!handle) { - scmd->result = DID_RESET << 16; - r = FAILED; - goto out; - } - - r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel, - scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, - 30, 0, TM_MUTEX_ON); - - out: - starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n", - ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); - return r; -} - - -/** - * _scsih_host_reset - eh threads main host reset routine - * @scmd: pointer to scsi command object - * - * Returns SUCCESS if command aborted else FAILED - */ -static int -_scsih_host_reset(struct scsi_cmnd *scmd) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); - int r, retval; - - pr_info(MPT3SAS_FMT "attempting host reset! scmd(%p)\n", - ioc->name, scmd); - scsi_print_command(scmd); - - retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - r = (retval < 0) ? FAILED : SUCCESS; - pr_info(MPT3SAS_FMT "host reset: %s scmd(%p)\n", - ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); - - return r; -} - -/** - * _scsih_fw_event_add - insert and queue up fw_event - * @ioc: per adapter object - * @fw_event: object describing the event - * Context: This function will acquire ioc->fw_event_lock. - * - * This adds the firmware event object into link list, then queues it up to - * be processed from user context. - * - * Return nothing. - */ -static void -_scsih_fw_event_add(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) -{ - unsigned long flags; - - if (ioc->firmware_event_thread == NULL) - return; - - spin_lock_irqsave(&ioc->fw_event_lock, flags); - INIT_LIST_HEAD(&fw_event->list); - list_add_tail(&fw_event->list, &ioc->fw_event_list); - INIT_WORK(&fw_event->work, _firmware_event_work); - queue_work(ioc->firmware_event_thread, &fw_event->work); - spin_unlock_irqrestore(&ioc->fw_event_lock, flags); -} - -/** - * _scsih_fw_event_free - delete fw_event - * @ioc: per adapter object - * @fw_event: object describing the event - * Context: This function will acquire ioc->fw_event_lock. - * - * This removes firmware event object from link list, frees associated memory. - * - * Return nothing. - */ -static void -_scsih_fw_event_free(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work - *fw_event) -{ - unsigned long flags; - - spin_lock_irqsave(&ioc->fw_event_lock, flags); - list_del(&fw_event->list); - kfree(fw_event->event_data); - kfree(fw_event); - spin_unlock_irqrestore(&ioc->fw_event_lock, flags); -} - - - /** - * mpt3sas_send_trigger_data_event - send event for processing trigger data - * @ioc: per adapter object - * @event_data: trigger event data - * - * Return nothing. - */ -void -mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc, - struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data) -{ - struct fw_event_work *fw_event; - - if (ioc->is_driver_loading) - return; - fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); - if (!fw_event) - return; - fw_event->event_data = kzalloc(sizeof(*event_data), GFP_ATOMIC); - if (!fw_event->event_data) - return; - fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG; - fw_event->ioc = ioc; - memcpy(fw_event->event_data, event_data, sizeof(*event_data)); - _scsih_fw_event_add(ioc, fw_event); -} - -/** - * _scsih_error_recovery_delete_devices - remove devices not responding - * @ioc: per adapter object - * - * Return nothing. - */ -static void -_scsih_error_recovery_delete_devices(struct MPT3SAS_ADAPTER *ioc) -{ - struct fw_event_work *fw_event; - - if (ioc->is_driver_loading) - return; - fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); - if (!fw_event) - return; - fw_event->event = MPT3SAS_REMOVE_UNRESPONDING_DEVICES; - fw_event->ioc = ioc; - _scsih_fw_event_add(ioc, fw_event); -} - -/** - * mpt3sas_port_enable_complete - port enable completed (fake event) - * @ioc: per adapter object - * - * Return nothing. - */ -void -mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc) -{ - struct fw_event_work *fw_event; - - fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); - if (!fw_event) - return; - fw_event->event = MPT3SAS_PORT_ENABLE_COMPLETE; - fw_event->ioc = ioc; - _scsih_fw_event_add(ioc, fw_event); -} - -/** - * _scsih_fw_event_cleanup_queue - cleanup event queue - * @ioc: per adapter object - * - * Walk the firmware event queue, either killing timers, or waiting - * for outstanding events to complete - * - * Return nothing. - */ -static void -_scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) -{ - struct fw_event_work *fw_event, *next; - - if (list_empty(&ioc->fw_event_list) || - !ioc->firmware_event_thread || in_interrupt()) - return; - - list_for_each_entry_safe(fw_event, next, &ioc->fw_event_list, list) { - if (cancel_delayed_work(&fw_event->delayed_work)) { - _scsih_fw_event_free(ioc, fw_event); - continue; - } - fw_event->cancel_pending_work = 1; - } -} - -/** - * _scsih_ublock_io_all_device - unblock every device - * @ioc: per adapter object - * - * change the device state from block to running - */ -static void -_scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - - shost_for_each_device(sdev, ioc->shost) { - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - continue; - if (!sas_device_priv_data->block) - continue; - - sas_device_priv_data->block = 0; - dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, - "device_running, handle(0x%04x)\n", - sas_device_priv_data->sas_target->handle)); - scsi_internal_device_unblock(sdev, SDEV_RUNNING); - } -} - - -/** - * _scsih_ublock_io_device - prepare device to be deleted - * @ioc: per adapter object - * @sas_addr: sas address - * - * unblock then put device in offline state - */ -static void -_scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - - shost_for_each_device(sdev, ioc->shost) { - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - continue; - if (sas_device_priv_data->sas_target->sas_address - != sas_address) - continue; - if (sas_device_priv_data->block) { - sas_device_priv_data->block = 0; - scsi_internal_device_unblock(sdev, SDEV_RUNNING); - } - } -} - -/** - * _scsih_block_io_all_device - set the device state to SDEV_BLOCK - * @ioc: per adapter object - * @handle: device handle - * - * During device pull we need to appropiately set the sdev state. - */ -static void -_scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - - shost_for_each_device(sdev, ioc->shost) { - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - continue; - if (sas_device_priv_data->block) - continue; - sas_device_priv_data->block = 1; - scsi_internal_device_block(sdev); - sdev_printk(KERN_INFO, sdev, "device_blocked, handle(0x%04x)\n", - sas_device_priv_data->sas_target->handle); - } -} - -/** - * _scsih_block_io_device - set the device state to SDEV_BLOCK - * @ioc: per adapter object - * @handle: device handle - * - * During device pull we need to appropiately set the sdev state. - */ -static void -_scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - - shost_for_each_device(sdev, ioc->shost) { - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - continue; - if (sas_device_priv_data->sas_target->handle != handle) - continue; - if (sas_device_priv_data->block) - continue; - sas_device_priv_data->block = 1; - scsi_internal_device_block(sdev); - sdev_printk(KERN_INFO, sdev, - "device_blocked, handle(0x%04x)\n", handle); - } -} - -/** - * _scsih_block_io_to_children_attached_to_ex - * @ioc: per adapter object - * @sas_expander: the sas_device object - * - * This routine set sdev state to SDEV_BLOCK for all devices - * attached to this expander. This function called when expander is - * pulled. - */ -static void -_scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_expander) -{ - struct _sas_port *mpt3sas_port; - struct _sas_device *sas_device; - struct _sas_node *expander_sibling; - unsigned long flags; - - if (!sas_expander) - return; - - list_for_each_entry(mpt3sas_port, - &sas_expander->sas_port_list, port_list) { - if (mpt3sas_port->remote_identify.device_type == - SAS_END_DEVICE) { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = - mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - mpt3sas_port->remote_identify.sas_address); - if (sas_device) - set_bit(sas_device->handle, - ioc->blocking_handles); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - } - } - - list_for_each_entry(mpt3sas_port, - &sas_expander->sas_port_list, port_list) { - - if (mpt3sas_port->remote_identify.device_type == - SAS_EDGE_EXPANDER_DEVICE || - mpt3sas_port->remote_identify.device_type == - SAS_FANOUT_EXPANDER_DEVICE) { - expander_sibling = - mpt3sas_scsih_expander_find_by_sas_address( - ioc, mpt3sas_port->remote_identify.sas_address); - _scsih_block_io_to_children_attached_to_ex(ioc, - expander_sibling); - } - } -} - -/** - * _scsih_block_io_to_children_attached_directly - * @ioc: per adapter object - * @event_data: topology change event data - * - * This routine set sdev state to SDEV_BLOCK for all devices - * direct attached during device pull. - */ -static void -_scsih_block_io_to_children_attached_directly(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataSasTopologyChangeList_t *event_data) -{ - int i; - u16 handle; - u16 reason_code; - - for (i = 0; i < event_data->NumEntries; i++) { - handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); - if (!handle) - continue; - reason_code = event_data->PHY[i].PhyStatus & - MPI2_EVENT_SAS_TOPO_RC_MASK; - if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING) - _scsih_block_io_device(ioc, handle); - } -} - -/** - * _scsih_tm_tr_send - send task management request - * @ioc: per adapter object - * @handle: device handle - * Context: interrupt time. - * - * This code is to initiate the device removal handshake protocol - * with controller firmware. This function will issue target reset - * using high priority request queue. It will send a sas iounit - * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion. - * - * This is designed to send muliple task management request at the same - * time to the fifo. If the fifo is full, we will append the request, - * and process it in a future completion. - */ -static void -_scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - Mpi2SCSITaskManagementRequest_t *mpi_request; - u16 smid; - struct _sas_device *sas_device; - struct MPT3SAS_TARGET *sas_target_priv_data = NULL; - u64 sas_address = 0; - unsigned long flags; - struct _tr_list *delayed_tr; - u32 ioc_state; - - if (ioc->remove_host) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host has been removed: handle(0x%04x)\n", - __func__, ioc->name, handle)); - return; - } else if (ioc->pci_error_recovery) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host in pci error recovery: handle(0x%04x)\n", - __func__, ioc->name, - handle)); - return; - } - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host is not operational: handle(0x%04x)\n", - __func__, ioc->name, - handle)); - return; - } - - /* if PD, then return */ - if (test_bit(handle, ioc->pd_handles)) - return; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _scsih_sas_device_find_by_handle(ioc, handle); - if (sas_device && sas_device->starget && - sas_device->starget->hostdata) { - sas_target_priv_data = sas_device->starget->hostdata; - sas_target_priv_data->deleted = 1; - sas_address = sas_device->sas_address; - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - if (sas_target_priv_data) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "setting delete flag: handle(0x%04x), sas_addr(0x%016llx)\n", - ioc->name, handle, - (unsigned long long)sas_address)); - _scsih_ublock_io_device(ioc, sas_address); - sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE; - } - - smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx); - if (!smid) { - delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); - if (!delayed_tr) - return; - INIT_LIST_HEAD(&delayed_tr->list); - delayed_tr->handle = handle; - list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "DELAYED:tr:handle(0x%04x), (open)\n", - ioc->name, handle)); - return; - } - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n", - ioc->name, handle, smid, - ioc->tm_tr_cb_idx)); - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; - mpi_request->DevHandle = cpu_to_le16(handle); - mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; - mpt3sas_base_put_smid_hi_priority(ioc, smid); - mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL); -} - -/** - * _scsih_tm_tr_complete - - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: interrupt time. - * - * This is the target reset completion routine. - * This code is part of the code to initiate the device removal - * handshake protocol with controller firmware. - * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE) - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - u16 handle; - Mpi2SCSITaskManagementRequest_t *mpi_request_tm; - Mpi2SCSITaskManagementReply_t *mpi_reply = - mpt3sas_base_get_reply_virt_addr(ioc, reply); - Mpi2SasIoUnitControlRequest_t *mpi_request; - u16 smid_sas_ctrl; - u32 ioc_state; - - if (ioc->remove_host) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host has been removed\n", __func__, ioc->name)); - return 1; - } else if (ioc->pci_error_recovery) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host in pci error recovery\n", __func__, - ioc->name)); - return 1; - } - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host is not operational\n", __func__, ioc->name)); - return 1; - } - if (unlikely(!mpi_reply)) { - pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return 1; - } - mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid); - handle = le16_to_cpu(mpi_request_tm->DevHandle); - if (handle != le16_to_cpu(mpi_reply->DevHandle)) { - dewtprintk(ioc, pr_err(MPT3SAS_FMT - "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n", - ioc->name, handle, - le16_to_cpu(mpi_reply->DevHandle), smid)); - return 0; - } - - mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT); - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), " - "loginfo(0x%08x), completed(%d)\n", ioc->name, - handle, smid, le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo), - le32_to_cpu(mpi_reply->TerminationCount))); - - smid_sas_ctrl = mpt3sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx); - if (!smid_sas_ctrl) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - return 1; - } - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "sc_send:handle(0x%04x), (open), smid(%d), cb(%d)\n", - ioc->name, handle, smid_sas_ctrl, - ioc->tm_sas_control_cb_idx)); - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid_sas_ctrl); - memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; - mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; - mpi_request->DevHandle = mpi_request_tm->DevHandle; - mpt3sas_base_put_smid_default(ioc, smid_sas_ctrl); - - return _scsih_check_for_pending_tm(ioc, smid); -} - - -/** - * _scsih_sas_control_complete - completion routine - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: interrupt time. - * - * This is the sas iounit control completion routine. - * This code is part of the code to initiate the device removal - * handshake protocol with controller firmware. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u8 msix_index, u32 reply) -{ - Mpi2SasIoUnitControlReply_t *mpi_reply = - mpt3sas_base_get_reply_virt_addr(ioc, reply); - - if (likely(mpi_reply)) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "sc_complete:handle(0x%04x), (open) " - "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid, - le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo))); - } else { - pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - } - return 1; -} - -/** - * _scsih_tm_tr_volume_send - send target reset request for volumes - * @ioc: per adapter object - * @handle: device handle - * Context: interrupt time. - * - * This is designed to send muliple task management request at the same - * time to the fifo. If the fifo is full, we will append the request, - * and process it in a future completion. - */ -static void -_scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - Mpi2SCSITaskManagementRequest_t *mpi_request; - u16 smid; - struct _tr_list *delayed_tr; - - if (ioc->shost_recovery || ioc->remove_host || - ioc->pci_error_recovery) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host reset in progress!\n", - __func__, ioc->name)); - return; - } - - smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx); - if (!smid) { - delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); - if (!delayed_tr) - return; - INIT_LIST_HEAD(&delayed_tr->list); - delayed_tr->handle = handle; - list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list); - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "DELAYED:tr:handle(0x%04x), (open)\n", - ioc->name, handle)); - return; - } - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n", - ioc->name, handle, smid, - ioc->tm_tr_volume_cb_idx)); - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; - mpi_request->DevHandle = cpu_to_le16(handle); - mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; - mpt3sas_base_put_smid_hi_priority(ioc, smid); -} - -/** - * _scsih_tm_volume_tr_complete - target reset completion - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: interrupt time. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u8 msix_index, u32 reply) -{ - u16 handle; - Mpi2SCSITaskManagementRequest_t *mpi_request_tm; - Mpi2SCSITaskManagementReply_t *mpi_reply = - mpt3sas_base_get_reply_virt_addr(ioc, reply); - - if (ioc->shost_recovery || ioc->remove_host || - ioc->pci_error_recovery) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host reset in progress!\n", - __func__, ioc->name)); - return 1; - } - if (unlikely(!mpi_reply)) { - pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return 1; - } - - mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid); - handle = le16_to_cpu(mpi_request_tm->DevHandle); - if (handle != le16_to_cpu(mpi_reply->DevHandle)) { - dewtprintk(ioc, pr_err(MPT3SAS_FMT - "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n", - ioc->name, handle, - le16_to_cpu(mpi_reply->DevHandle), smid)); - return 0; - } - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), " - "loginfo(0x%08x), completed(%d)\n", ioc->name, - handle, smid, le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo), - le32_to_cpu(mpi_reply->TerminationCount))); - - return _scsih_check_for_pending_tm(ioc, smid); -} - - -/** - * _scsih_check_for_pending_tm - check for pending task management - * @ioc: per adapter object - * @smid: system request message index - * - * This will check delayed target reset list, and feed the - * next reqeust. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - struct _tr_list *delayed_tr; - - if (!list_empty(&ioc->delayed_tr_volume_list)) { - delayed_tr = list_entry(ioc->delayed_tr_volume_list.next, - struct _tr_list, list); - mpt3sas_base_free_smid(ioc, smid); - _scsih_tm_tr_volume_send(ioc, delayed_tr->handle); - list_del(&delayed_tr->list); - kfree(delayed_tr); - return 0; - } - - if (!list_empty(&ioc->delayed_tr_list)) { - delayed_tr = list_entry(ioc->delayed_tr_list.next, - struct _tr_list, list); - mpt3sas_base_free_smid(ioc, smid); - _scsih_tm_tr_send(ioc, delayed_tr->handle); - list_del(&delayed_tr->list); - kfree(delayed_tr); - return 0; - } - - return 1; -} - -/** - * _scsih_check_topo_delete_events - sanity check on topo events - * @ioc: per adapter object - * @event_data: the event data payload - * - * This routine added to better handle cable breaker. - * - * This handles the case where driver receives multiple expander - * add and delete events in a single shot. When there is a delete event - * the routine will void any pending add events waiting in the event queue. - * - * Return nothing. - */ -static void -_scsih_check_topo_delete_events(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataSasTopologyChangeList_t *event_data) -{ - struct fw_event_work *fw_event; - Mpi2EventDataSasTopologyChangeList_t *local_event_data; - u16 expander_handle; - struct _sas_node *sas_expander; - unsigned long flags; - int i, reason_code; - u16 handle; - - for (i = 0 ; i < event_data->NumEntries; i++) { - handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); - if (!handle) - continue; - reason_code = event_data->PHY[i].PhyStatus & - MPI2_EVENT_SAS_TOPO_RC_MASK; - if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING) - _scsih_tm_tr_send(ioc, handle); - } - - expander_handle = le16_to_cpu(event_data->ExpanderDevHandle); - if (expander_handle < ioc->sas_hba.num_phys) { - _scsih_block_io_to_children_attached_directly(ioc, event_data); - return; - } - if (event_data->ExpStatus == - MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) { - /* put expander attached devices into blocking state */ - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc, - expander_handle); - _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - do { - handle = find_first_bit(ioc->blocking_handles, - ioc->facts.MaxDevHandle); - if (handle < ioc->facts.MaxDevHandle) - _scsih_block_io_device(ioc, handle); - } while (test_and_clear_bit(handle, ioc->blocking_handles)); - } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING) - _scsih_block_io_to_children_attached_directly(ioc, event_data); - - if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) - return; - - /* mark ignore flag for pending events */ - spin_lock_irqsave(&ioc->fw_event_lock, flags); - list_for_each_entry(fw_event, &ioc->fw_event_list, list) { - if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || - fw_event->ignore) - continue; - local_event_data = fw_event->event_data; - if (local_event_data->ExpStatus == - MPI2_EVENT_SAS_TOPO_ES_ADDED || - local_event_data->ExpStatus == - MPI2_EVENT_SAS_TOPO_ES_RESPONDING) { - if (le16_to_cpu(local_event_data->ExpanderDevHandle) == - expander_handle) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "setting ignoring flag\n", ioc->name)); - fw_event->ignore = 1; - } - } - } - spin_unlock_irqrestore(&ioc->fw_event_lock, flags); -} - -/** - * _scsih_set_volume_delete_flag - setting volume delete flag - * @ioc: per adapter object - * @handle: device handle - * - * This returns nothing. - */ -static void -_scsih_set_volume_delete_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _raid_device *raid_device; - struct MPT3SAS_TARGET *sas_target_priv_data; - unsigned long flags; - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_handle(ioc, handle); - if (raid_device && raid_device->starget && - raid_device->starget->hostdata) { - sas_target_priv_data = - raid_device->starget->hostdata; - sas_target_priv_data->deleted = 1; - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "setting delete flag: handle(0x%04x), " - "wwid(0x%016llx)\n", ioc->name, handle, - (unsigned long long) raid_device->wwid)); - } - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); -} - -/** - * _scsih_set_volume_handle_for_tr - set handle for target reset to volume - * @handle: input handle - * @a: handle for volume a - * @b: handle for volume b - * - * IR firmware only supports two raid volumes. The purpose of this - * routine is to set the volume handle in either a or b. When the given - * input handle is non-zero, or when a and b have not been set before. - */ -static void -_scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b) -{ - if (!handle || handle == *a || handle == *b) - return; - if (!*a) - *a = handle; - else if (!*b) - *b = handle; -} - -/** - * _scsih_check_ir_config_unhide_events - check for UNHIDE events - * @ioc: per adapter object - * @event_data: the event data payload - * Context: interrupt time. - * - * This routine will send target reset to volume, followed by target - * resets to the PDs. This is called when a PD has been removed, or - * volume has been deleted or removed. When the target reset is sent - * to volume, the PD target resets need to be queued to start upon - * completion of the volume target reset. - * - * Return nothing. - */ -static void -_scsih_check_ir_config_unhide_events(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataIrConfigChangeList_t *event_data) -{ - Mpi2EventIrConfigElement_t *element; - int i; - u16 handle, volume_handle, a, b; - struct _tr_list *delayed_tr; - - a = 0; - b = 0; - - /* Volume Resets for Deleted or Removed */ - element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; - for (i = 0; i < event_data->NumElements; i++, element++) { - if (le32_to_cpu(event_data->Flags) & - MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) - continue; - if (element->ReasonCode == - MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED || - element->ReasonCode == - MPI2_EVENT_IR_CHANGE_RC_REMOVED) { - volume_handle = le16_to_cpu(element->VolDevHandle); - _scsih_set_volume_delete_flag(ioc, volume_handle); - _scsih_set_volume_handle_for_tr(volume_handle, &a, &b); - } - } - - /* Volume Resets for UNHIDE events */ - element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; - for (i = 0; i < event_data->NumElements; i++, element++) { - if (le32_to_cpu(event_data->Flags) & - MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) - continue; - if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) { - volume_handle = le16_to_cpu(element->VolDevHandle); - _scsih_set_volume_handle_for_tr(volume_handle, &a, &b); - } - } - - if (a) - _scsih_tm_tr_volume_send(ioc, a); - if (b) - _scsih_tm_tr_volume_send(ioc, b); - - /* PD target resets */ - element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; - for (i = 0; i < event_data->NumElements; i++, element++) { - if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE) - continue; - handle = le16_to_cpu(element->PhysDiskDevHandle); - volume_handle = le16_to_cpu(element->VolDevHandle); - clear_bit(handle, ioc->pd_handles); - if (!volume_handle) - _scsih_tm_tr_send(ioc, handle); - else if (volume_handle == a || volume_handle == b) { - delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); - BUG_ON(!delayed_tr); - INIT_LIST_HEAD(&delayed_tr->list); - delayed_tr->handle = handle; - list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name, - handle)); - } else - _scsih_tm_tr_send(ioc, handle); - } -} - - -/** - * _scsih_check_volume_delete_events - set delete flag for volumes - * @ioc: per adapter object - * @event_data: the event data payload - * Context: interrupt time. - * - * This will handle the case when the cable connected to entire volume is - * pulled. We will take care of setting the deleted flag so normal IO will - * not be sent. - * - * Return nothing. - */ -static void -_scsih_check_volume_delete_events(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataIrVolume_t *event_data) -{ - u32 state; - - if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) - return; - state = le32_to_cpu(event_data->NewValue); - if (state == MPI2_RAID_VOL_STATE_MISSING || state == - MPI2_RAID_VOL_STATE_FAILED) - _scsih_set_volume_delete_flag(ioc, - le16_to_cpu(event_data->VolDevHandle)); -} - -static int _scsih_set_satl_pending(struct scsi_cmnd *scmd, bool pending) -{ - struct MPT3SAS_DEVICE *priv = scmd->device->hostdata; - - if (scmd->cmnd[0] != ATA_12 && scmd->cmnd[0] != ATA_16) - return 0; - - if (pending) - return test_and_set_bit(0, &priv->ata_command_pending); - - clear_bit(0, &priv->ata_command_pending); - return 0; -} - -/** - * _scsih_flush_running_cmds - completing outstanding commands. - * @ioc: per adapter object - * - * The flushing out of all pending scmd commands following host reset, - * where all IO is dropped to the floor. - * - * Return nothing. - */ -static void -_scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc) -{ - struct scsi_cmnd *scmd; - u16 smid; - u16 count = 0; - - for (smid = 1; smid <= ioc->scsiio_depth; smid++) { - scmd = _scsih_scsi_lookup_get_clear(ioc, smid); - if (!scmd) - continue; - count++; - _scsih_set_satl_pending(scmd, false); - mpt3sas_base_free_smid(ioc, smid); - scsi_dma_unmap(scmd); - if (ioc->pci_error_recovery) - scmd->result = DID_NO_CONNECT << 16; - else - scmd->result = DID_RESET << 16; - scmd->scsi_done(scmd); - } - dtmprintk(ioc, pr_info(MPT3SAS_FMT "completing %d cmds\n", - ioc->name, count)); -} - -/** - * _scsih_setup_eedp - setup MPI request for EEDP transfer - * @ioc: per adapter object - * @scmd: pointer to scsi command object - * @mpi_request: pointer to the SCSI_IO reqest message frame - * - * Supporting protection 1 and 3. - * - * Returns nothing - */ -static void -_scsih_setup_eedp(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, - Mpi2SCSIIORequest_t *mpi_request) -{ - u16 eedp_flags; - unsigned char prot_op = scsi_get_prot_op(scmd); - unsigned char prot_type = scsi_get_prot_type(scmd); - Mpi25SCSIIORequest_t *mpi_request_3v = - (Mpi25SCSIIORequest_t *)mpi_request; - - if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL) - return; - - if (prot_op == SCSI_PROT_READ_STRIP) - eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP; - else if (prot_op == SCSI_PROT_WRITE_INSERT) - eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP; - else - return; - - switch (prot_type) { - case SCSI_PROT_DIF_TYPE1: - case SCSI_PROT_DIF_TYPE2: - - /* - * enable ref/guard checking - * auto increment ref tag - */ - eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | - MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | - MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; - mpi_request->CDB.EEDP32.PrimaryReferenceTag = - cpu_to_be32(scsi_get_lba(scmd)); - break; - - case SCSI_PROT_DIF_TYPE3: - - /* - * enable guard checking - */ - eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; - - break; - } - - mpi_request_3v->EEDPBlockSize = - cpu_to_le16(scmd->device->sector_size); - mpi_request->EEDPFlags = cpu_to_le16(eedp_flags); -} - -/** - * _scsih_eedp_error_handling - return sense code for EEDP errors - * @scmd: pointer to scsi command object - * @ioc_status: ioc status - * - * Returns nothing - */ -static void -_scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status) -{ - u8 ascq; - - switch (ioc_status) { - case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: - ascq = 0x01; - break; - case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: - ascq = 0x02; - break; - case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: - ascq = 0x03; - break; - default: - ascq = 0x00; - break; - } - scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, 0x10, - ascq); - scmd->result = DRIVER_SENSE << 24 | (DID_ABORT << 16) | - SAM_STAT_CHECK_CONDITION; -} - -/** - * _scsih_qcmd_lck - main scsi request entry point - * @scmd: pointer to scsi command object - * @done: function pointer to be invoked on completion - * - * The callback index is set inside `ioc->scsi_io_cb_idx`. - * - * Returns 0 on success. If there's a failure, return either: - * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or - * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full - */ -static int -_scsih_qcmd_lck(struct scsi_cmnd *scmd, void (*done)(struct scsi_cmnd *)) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct MPT3SAS_TARGET *sas_target_priv_data; - Mpi2SCSIIORequest_t *mpi_request; - u32 mpi_control; - u16 smid; - u16 handle; - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - if (ioc->logging_level & MPT_DEBUG_SCSI) - scsi_print_command(scmd); -#endif - - scmd->scsi_done = done; - sas_device_priv_data = scmd->device->hostdata; - if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - return 0; - } - - if (ioc->pci_error_recovery || ioc->remove_host) { - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - return 0; - } - - /* - * Bug work around for firmware SATL handling. The loop - * is based on atomic operations and ensures consistency - * since we're lockless at this point - */ - do { - if (test_bit(0, &sas_device_priv_data->ata_command_pending)) { - scmd->result = SAM_STAT_BUSY; - scmd->scsi_done(scmd); - return 0; - } - } while (_scsih_set_satl_pending(scmd, true)); - - sas_target_priv_data = sas_device_priv_data->sas_target; - - /* invalid device handle */ - handle = sas_target_priv_data->handle; - if (handle == MPT3SAS_INVALID_DEVICE_HANDLE) { - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - return 0; - } - - - /* host recovery or link resets sent via IOCTLs */ - if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress) - return SCSI_MLQUEUE_HOST_BUSY; - - /* device has been deleted */ - else if (sas_target_priv_data->deleted) { - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - return 0; - /* device busy with task managment */ - } else if (sas_target_priv_data->tm_busy || - sas_device_priv_data->block) - return SCSI_MLQUEUE_DEVICE_BUSY; - - if (scmd->sc_data_direction == DMA_FROM_DEVICE) - mpi_control = MPI2_SCSIIO_CONTROL_READ; - else if (scmd->sc_data_direction == DMA_TO_DEVICE) - mpi_control = MPI2_SCSIIO_CONTROL_WRITE; - else - mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER; - - /* set tags */ - if (!(sas_device_priv_data->flags & MPT_DEVICE_FLAGS_INIT)) { - if (scmd->device->tagged_supported) { - if (scmd->device->ordered_tags) - mpi_control |= MPI2_SCSIIO_CONTROL_ORDEREDQ; - else - mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; - } else - mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; - } else - mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; - - if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) && - scmd->cmd_len != 32) - mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON; - - smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - goto out; - } - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t)); - _scsih_setup_eedp(ioc, scmd, mpi_request); - - if (scmd->cmd_len == 32) - mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT; - mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; - if (sas_device_priv_data->sas_target->flags & - MPT_TARGET_FLAGS_RAID_COMPONENT) - mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; - else - mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; - mpi_request->DevHandle = cpu_to_le16(handle); - mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd)); - mpi_request->Control = cpu_to_le32(mpi_control); - mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len); - mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR; - mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; - mpi_request->SenseBufferLowAddress = - mpt3sas_base_get_sense_buffer_dma(ioc, smid); - mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4; - int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *) - mpi_request->LUN); - memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len); - - if (mpi_request->DataLength) { - if (ioc->build_sg_scmd(ioc, scmd, smid)) { - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - } else - ioc->build_zero_len_sge(ioc, &mpi_request->SGL); - - if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) { - if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) { - mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len | - MPI25_SCSIIO_IOFLAGS_FAST_PATH); - mpt3sas_base_put_smid_fast_path(ioc, smid, handle); - } else - mpt3sas_base_put_smid_scsi_io(ioc, smid, handle); - } else - mpt3sas_base_put_smid_default(ioc, smid); - return 0; - - out: - return SCSI_MLQUEUE_HOST_BUSY; -} -static DEF_SCSI_QCMD(_scsih_qcmd) - - -/** - * _scsih_normalize_sense - normalize descriptor and fixed format sense data - * @sense_buffer: sense data returned by target - * @data: normalized skey/asc/ascq - * - * Return nothing. - */ -static void -_scsih_normalize_sense(char *sense_buffer, struct sense_info *data) -{ - if ((sense_buffer[0] & 0x7F) >= 0x72) { - /* descriptor format */ - data->skey = sense_buffer[1] & 0x0F; - data->asc = sense_buffer[2]; - data->ascq = sense_buffer[3]; - } else { - /* fixed format */ - data->skey = sense_buffer[2] & 0x0F; - data->asc = sense_buffer[12]; - data->ascq = sense_buffer[13]; - } -} - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING -/** - * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request - * @ioc: per adapter object - * @scmd: pointer to scsi command object - * @mpi_reply: reply mf payload returned from firmware - * - * scsi_status - SCSI Status code returned from target device - * scsi_state - state info associated with SCSI_IO determined by ioc - * ioc_status - ioc supplied status info - * - * Return nothing. - */ -static void -_scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, - Mpi2SCSIIOReply_t *mpi_reply, u16 smid) -{ - u32 response_info; - u8 *response_bytes; - u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & - MPI2_IOCSTATUS_MASK; - u8 scsi_state = mpi_reply->SCSIState; - u8 scsi_status = mpi_reply->SCSIStatus; - char *desc_ioc_state = NULL; - char *desc_scsi_status = NULL; - char *desc_scsi_state = ioc->tmp_string; - u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); - struct _sas_device *sas_device = NULL; - unsigned long flags; - struct scsi_target *starget = scmd->device->sdev_target; - struct MPT3SAS_TARGET *priv_target = starget->hostdata; - char *device_str = NULL; - - if (!priv_target) - return; - device_str = "volume"; - - if (log_info == 0x31170000) - return; - - switch (ioc_status) { - case MPI2_IOCSTATUS_SUCCESS: - desc_ioc_state = "success"; - break; - case MPI2_IOCSTATUS_INVALID_FUNCTION: - desc_ioc_state = "invalid function"; - break; - case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: - desc_ioc_state = "scsi recovered error"; - break; - case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: - desc_ioc_state = "scsi invalid dev handle"; - break; - case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: - desc_ioc_state = "scsi device not there"; - break; - case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: - desc_ioc_state = "scsi data overrun"; - break; - case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: - desc_ioc_state = "scsi data underrun"; - break; - case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: - desc_ioc_state = "scsi io data error"; - break; - case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: - desc_ioc_state = "scsi protocol error"; - break; - case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: - desc_ioc_state = "scsi task terminated"; - break; - case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: - desc_ioc_state = "scsi residual mismatch"; - break; - case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: - desc_ioc_state = "scsi task mgmt failed"; - break; - case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: - desc_ioc_state = "scsi ioc terminated"; - break; - case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: - desc_ioc_state = "scsi ext terminated"; - break; - case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: - desc_ioc_state = "eedp guard error"; - break; - case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: - desc_ioc_state = "eedp ref tag error"; - break; - case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: - desc_ioc_state = "eedp app tag error"; - break; - default: - desc_ioc_state = "unknown"; - break; - } - - switch (scsi_status) { - case MPI2_SCSI_STATUS_GOOD: - desc_scsi_status = "good"; - break; - case MPI2_SCSI_STATUS_CHECK_CONDITION: - desc_scsi_status = "check condition"; - break; - case MPI2_SCSI_STATUS_CONDITION_MET: - desc_scsi_status = "condition met"; - break; - case MPI2_SCSI_STATUS_BUSY: - desc_scsi_status = "busy"; - break; - case MPI2_SCSI_STATUS_INTERMEDIATE: - desc_scsi_status = "intermediate"; - break; - case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET: - desc_scsi_status = "intermediate condmet"; - break; - case MPI2_SCSI_STATUS_RESERVATION_CONFLICT: - desc_scsi_status = "reservation conflict"; - break; - case MPI2_SCSI_STATUS_COMMAND_TERMINATED: - desc_scsi_status = "command terminated"; - break; - case MPI2_SCSI_STATUS_TASK_SET_FULL: - desc_scsi_status = "task set full"; - break; - case MPI2_SCSI_STATUS_ACA_ACTIVE: - desc_scsi_status = "aca active"; - break; - case MPI2_SCSI_STATUS_TASK_ABORTED: - desc_scsi_status = "task aborted"; - break; - default: - desc_scsi_status = "unknown"; - break; - } - - desc_scsi_state[0] = '\0'; - if (!scsi_state) - desc_scsi_state = " "; - if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) - strcat(desc_scsi_state, "response info "); - if (scsi_state & MPI2_SCSI_STATE_TERMINATED) - strcat(desc_scsi_state, "state terminated "); - if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) - strcat(desc_scsi_state, "no status "); - if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED) - strcat(desc_scsi_state, "autosense failed "); - if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) - strcat(desc_scsi_state, "autosense valid "); - - scsi_print_command(scmd); - - if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) { - pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name, - device_str, (unsigned long long)priv_target->sas_address); - } else { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - priv_target->sas_address); - if (sas_device) { - pr_warn(MPT3SAS_FMT - "\tsas_address(0x%016llx), phy(%d)\n", - ioc->name, (unsigned long long) - sas_device->sas_address, sas_device->phy); - pr_warn(MPT3SAS_FMT - "\tenclosure_logical_id(0x%016llx), slot(%d)\n", - ioc->name, (unsigned long long) - sas_device->enclosure_logical_id, sas_device->slot); - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - } - - pr_warn(MPT3SAS_FMT - "\thandle(0x%04x), ioc_status(%s)(0x%04x), smid(%d)\n", - ioc->name, le16_to_cpu(mpi_reply->DevHandle), - desc_ioc_state, ioc_status, smid); - pr_warn(MPT3SAS_FMT - "\trequest_len(%d), underflow(%d), resid(%d)\n", - ioc->name, scsi_bufflen(scmd), scmd->underflow, - scsi_get_resid(scmd)); - pr_warn(MPT3SAS_FMT - "\ttag(%d), transfer_count(%d), sc->result(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply->TaskTag), - le32_to_cpu(mpi_reply->TransferCount), scmd->result); - pr_warn(MPT3SAS_FMT - "\tscsi_status(%s)(0x%02x), scsi_state(%s)(0x%02x)\n", - ioc->name, desc_scsi_status, - scsi_status, desc_scsi_state, scsi_state); - - if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { - struct sense_info data; - _scsih_normalize_sense(scmd->sense_buffer, &data); - pr_warn(MPT3SAS_FMT - "\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], count(%d)\n", - ioc->name, data.skey, - data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount)); - } - - if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { - response_info = le32_to_cpu(mpi_reply->ResponseInfo); - response_bytes = (u8 *)&response_info; - _scsih_response_code(ioc, response_bytes[0]); - } -} -#endif - -/** - * _scsih_turn_on_fault_led - illuminate Fault LED - * @ioc: per adapter object - * @handle: device handle - * Context: process - * - * Return nothing. - */ -static void -_scsih_turn_on_fault_led(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - Mpi2SepReply_t mpi_reply; - Mpi2SepRequest_t mpi_request; - - memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t)); - mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; - mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS; - mpi_request.SlotStatus = - cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); - mpi_request.DevHandle = cpu_to_le16(handle); - mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS; - if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply, - &mpi_request)) != 0) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__); - return; - } - - if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply.IOCStatus), - le32_to_cpu(mpi_reply.IOCLogInfo))); - return; - } -} - -/** - * _scsih_send_event_to_turn_on_fault_led - fire delayed event - * @ioc: per adapter object - * @handle: device handle - * Context: interrupt. - * - * Return nothing. - */ -static void -_scsih_send_event_to_turn_on_fault_led(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct fw_event_work *fw_event; - - fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); - if (!fw_event) - return; - fw_event->event = MPT3SAS_TURN_ON_FAULT_LED; - fw_event->device_handle = handle; - fw_event->ioc = ioc; - _scsih_fw_event_add(ioc, fw_event); -} - -/** - * _scsih_smart_predicted_fault - process smart errors - * @ioc: per adapter object - * @handle: device handle - * Context: interrupt. - * - * Return nothing. - */ -static void -_scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct scsi_target *starget; - struct MPT3SAS_TARGET *sas_target_priv_data; - Mpi2EventNotificationReply_t *event_reply; - Mpi2EventDataSasDeviceStatusChange_t *event_data; - struct _sas_device *sas_device; - ssize_t sz; - unsigned long flags; - - /* only handle non-raid devices */ - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _scsih_sas_device_find_by_handle(ioc, handle); - if (!sas_device) { - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return; - } - starget = sas_device->starget; - sas_target_priv_data = starget->hostdata; - - if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) || - ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) { - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return; - } - starget_printk(KERN_WARNING, starget, "predicted fault\n"); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) - _scsih_send_event_to_turn_on_fault_led(ioc, handle); - - /* insert into event log */ - sz = offsetof(Mpi2EventNotificationReply_t, EventData) + - sizeof(Mpi2EventDataSasDeviceStatusChange_t); - event_reply = kzalloc(sz, GFP_KERNEL); - if (!event_reply) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; - event_reply->Event = - cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE); - event_reply->MsgLength = sz/4; - event_reply->EventDataLength = - cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4); - event_data = (Mpi2EventDataSasDeviceStatusChange_t *) - event_reply->EventData; - event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA; - event_data->ASC = 0x5D; - event_data->DevHandle = cpu_to_le16(handle); - event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address); - mpt3sas_ctl_add_to_event_log(ioc, event_reply); - kfree(event_reply); -} - -/** - * _scsih_io_done - scsi request callback - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Callback handler when using _scsih_qcmd. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) -{ - Mpi2SCSIIORequest_t *mpi_request; - Mpi2SCSIIOReply_t *mpi_reply; - struct scsi_cmnd *scmd; - u16 ioc_status; - u32 xfer_cnt; - u8 scsi_state; - u8 scsi_status; - u32 log_info; - struct MPT3SAS_DEVICE *sas_device_priv_data; - u32 response_code = 0; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - scmd = _scsih_scsi_lookup_get_clear(ioc, smid); - if (scmd == NULL) - return 1; - - _scsih_set_satl_pending(scmd, false); - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - - if (mpi_reply == NULL) { - scmd->result = DID_OK << 16; - goto out; - } - - sas_device_priv_data = scmd->device->hostdata; - if (!sas_device_priv_data || !sas_device_priv_data->sas_target || - sas_device_priv_data->sas_target->deleted) { - scmd->result = DID_NO_CONNECT << 16; - goto out; - } - ioc_status = le16_to_cpu(mpi_reply->IOCStatus); - - /* turning off TLR */ - scsi_state = mpi_reply->SCSIState; - if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) - response_code = - le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF; - if (!sas_device_priv_data->tlr_snoop_check) { - sas_device_priv_data->tlr_snoop_check++; - if ((sas_device_priv_data->flags & MPT_DEVICE_TLR_ON) && - response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) - sas_device_priv_data->flags &= - ~MPT_DEVICE_TLR_ON; - } - - xfer_cnt = le32_to_cpu(mpi_reply->TransferCount); - scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt); - if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) - log_info = le32_to_cpu(mpi_reply->IOCLogInfo); - else - log_info = 0; - ioc_status &= MPI2_IOCSTATUS_MASK; - scsi_status = mpi_reply->SCSIStatus; - - if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 && - (scsi_status == MPI2_SCSI_STATUS_BUSY || - scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT || - scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) { - ioc_status = MPI2_IOCSTATUS_SUCCESS; - } - - if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { - struct sense_info data; - const void *sense_data = mpt3sas_base_get_sense_buffer(ioc, - smid); - u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE, - le32_to_cpu(mpi_reply->SenseCount)); - memcpy(scmd->sense_buffer, sense_data, sz); - _scsih_normalize_sense(scmd->sense_buffer, &data); - /* failure prediction threshold exceeded */ - if (data.asc == 0x5D) - _scsih_smart_predicted_fault(ioc, - le16_to_cpu(mpi_reply->DevHandle)); - mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq); - } - - switch (ioc_status) { - case MPI2_IOCSTATUS_BUSY: - case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES: - scmd->result = SAM_STAT_BUSY; - break; - - case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: - scmd->result = DID_NO_CONNECT << 16; - break; - - case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: - if (sas_device_priv_data->block) { - scmd->result = DID_TRANSPORT_DISRUPTED << 16; - goto out; - } - if (log_info == 0x31110630) { - if (scmd->retries > 2) { - scmd->result = DID_NO_CONNECT << 16; - scsi_device_set_state(scmd->device, - SDEV_OFFLINE); - } else { - scmd->result = DID_SOFT_ERROR << 16; - scmd->device->expecting_cc_ua = 1; - } - break; - } - scmd->result = DID_SOFT_ERROR << 16; - break; - case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: - case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: - scmd->result = DID_RESET << 16; - break; - - case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: - if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt)) - scmd->result = DID_SOFT_ERROR << 16; - else - scmd->result = (DID_OK << 16) | scsi_status; - break; - - case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: - scmd->result = (DID_OK << 16) | scsi_status; - - if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)) - break; - - if (xfer_cnt < scmd->underflow) { - if (scsi_status == SAM_STAT_BUSY) - scmd->result = SAM_STAT_BUSY; - else - scmd->result = DID_SOFT_ERROR << 16; - } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED | - MPI2_SCSI_STATE_NO_SCSI_STATUS)) - scmd->result = DID_SOFT_ERROR << 16; - else if (scsi_state & MPI2_SCSI_STATE_TERMINATED) - scmd->result = DID_RESET << 16; - else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) { - mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID; - mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION; - scmd->result = (DRIVER_SENSE << 24) | - SAM_STAT_CHECK_CONDITION; - scmd->sense_buffer[0] = 0x70; - scmd->sense_buffer[2] = ILLEGAL_REQUEST; - scmd->sense_buffer[12] = 0x20; - scmd->sense_buffer[13] = 0; - } - break; - - case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: - scsi_set_resid(scmd, 0); - case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: - case MPI2_IOCSTATUS_SUCCESS: - scmd->result = (DID_OK << 16) | scsi_status; - if (response_code == - MPI2_SCSITASKMGMT_RSP_INVALID_FRAME || - (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED | - MPI2_SCSI_STATE_NO_SCSI_STATUS))) - scmd->result = DID_SOFT_ERROR << 16; - else if (scsi_state & MPI2_SCSI_STATE_TERMINATED) - scmd->result = DID_RESET << 16; - break; - - case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: - case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: - case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: - _scsih_eedp_error_handling(scmd, ioc_status); - break; - - case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: - case MPI2_IOCSTATUS_INVALID_FUNCTION: - case MPI2_IOCSTATUS_INVALID_SGL: - case MPI2_IOCSTATUS_INTERNAL_ERROR: - case MPI2_IOCSTATUS_INVALID_FIELD: - case MPI2_IOCSTATUS_INVALID_STATE: - case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: - case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: - default: - scmd->result = DID_SOFT_ERROR << 16; - break; - - } - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY)) - _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid); -#endif - - out: - - scsi_dma_unmap(scmd); - - scmd->scsi_done(scmd); - return 1; -} - -/** - * _scsih_sas_host_refresh - refreshing sas host object contents - * @ioc: per adapter object - * Context: user - * - * During port enable, fw will send topology events for every device. Its - * possible that the handles may change from the previous setting, so this - * code keeping handles updating if changed. - * - * Return nothing. - */ -static void -_scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) -{ - u16 sz; - u16 ioc_status; - int i; - Mpi2ConfigReply_t mpi_reply; - Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; - u16 attached_handle; - u8 link_rate; - - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "updating handles for sas_host(0x%016llx)\n", - ioc->name, (unsigned long long)ioc->sas_hba.sas_address)); - - sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys - * sizeof(Mpi2SasIOUnit0PhyData_t)); - sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg0) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, - sas_iounit_pg0, sz)) != 0) - goto out; - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - goto out; - for (i = 0; i < ioc->sas_hba.num_phys ; i++) { - link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4; - if (i == 0) - ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> - PhyData[0].ControllerDevHandle); - ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; - attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i]. - AttachedDevHandle); - if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5) - link_rate = MPI2_SAS_NEG_LINK_RATE_1_5; - mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address, - attached_handle, i, link_rate); - } - out: - kfree(sas_iounit_pg0); -} - -/** - * _scsih_sas_host_add - create sas host object - * @ioc: per adapter object - * - * Creating host side data object, stored in ioc->sas_hba - * - * Return nothing. - */ -static void -_scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc) -{ - int i; - Mpi2ConfigReply_t mpi_reply; - Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; - Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; - Mpi2SasPhyPage0_t phy_pg0; - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2SasEnclosurePage0_t enclosure_pg0; - u16 ioc_status; - u16 sz; - u8 device_missing_delay; - - mpt3sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys); - if (!ioc->sas_hba.num_phys) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - /* sas_iounit page 0 */ - sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys * - sizeof(Mpi2SasIOUnit0PhyData_t)); - sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg0) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, - sas_iounit_pg0, sz))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - - /* sas_iounit page 1 */ - sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * - sizeof(Mpi2SasIOUnit1PhyData_t)); - sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg1) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, - sas_iounit_pg1, sz))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - - ioc->io_missing_delay = - sas_iounit_pg1->IODeviceMissingDelay; - device_missing_delay = - sas_iounit_pg1->ReportDeviceMissingDelay; - if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16) - ioc->device_missing_delay = (device_missing_delay & - MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16; - else - ioc->device_missing_delay = device_missing_delay & - MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK; - - ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev; - ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys, - sizeof(struct _sas_phy), GFP_KERNEL); - if (!ioc->sas_hba.phy) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - for (i = 0; i < ioc->sas_hba.num_phys ; i++) { - if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0, - i))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - - if (i == 0) - ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> - PhyData[0].ControllerDevHandle); - ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; - ioc->sas_hba.phy[i].phy_id = i; - mpt3sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i], - phy_pg0, ioc->sas_hba.parent_dev); - } - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - ioc->sas_hba.enclosure_handle = - le16_to_cpu(sas_device_pg0.EnclosureHandle); - ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress); - pr_info(MPT3SAS_FMT - "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n", - ioc->name, ioc->sas_hba.handle, - (unsigned long long) ioc->sas_hba.sas_address, - ioc->sas_hba.num_phys) ; - - if (ioc->sas_hba.enclosure_handle) { - if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply, - &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - ioc->sas_hba.enclosure_handle))) - ioc->sas_hba.enclosure_logical_id = - le64_to_cpu(enclosure_pg0.EnclosureLogicalID); - } - - out: - kfree(sas_iounit_pg1); - kfree(sas_iounit_pg0); -} - -/** - * _scsih_expander_add - creating expander object - * @ioc: per adapter object - * @handle: expander handle - * - * Creating expander object, stored in ioc->sas_expander_list. - * - * Return 0 for success, else error. - */ -static int -_scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _sas_node *sas_expander; - Mpi2ConfigReply_t mpi_reply; - Mpi2ExpanderPage0_t expander_pg0; - Mpi2ExpanderPage1_t expander_pg1; - Mpi2SasEnclosurePage0_t enclosure_pg0; - u32 ioc_status; - u16 parent_handle; - u64 sas_address, sas_address_parent = 0; - int i; - unsigned long flags; - struct _sas_port *mpt3sas_port = NULL; - - int rc = 0; - - if (!handle) - return -1; - - if (ioc->shost_recovery || ioc->pci_error_recovery) - return -1; - - if ((mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, - MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - - /* handle out of order topology events */ - parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle); - if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent) - != 0) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - if (sas_address_parent != ioc->sas_hba.sas_address) { - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address_parent); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - if (!sas_expander) { - rc = _scsih_expander_add(ioc, parent_handle); - if (rc != 0) - return rc; - } - } - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_address = le64_to_cpu(expander_pg0.SASAddress); - sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - if (sas_expander) - return 0; - - sas_expander = kzalloc(sizeof(struct _sas_node), - GFP_KERNEL); - if (!sas_expander) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - - sas_expander->handle = handle; - sas_expander->num_phys = expander_pg0.NumPhys; - sas_expander->sas_address_parent = sas_address_parent; - sas_expander->sas_address = sas_address; - - pr_info(MPT3SAS_FMT "expander_add: handle(0x%04x)," \ - " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name, - handle, parent_handle, (unsigned long long) - sas_expander->sas_address, sas_expander->num_phys); - - if (!sas_expander->num_phys) - goto out_fail; - sas_expander->phy = kcalloc(sas_expander->num_phys, - sizeof(struct _sas_phy), GFP_KERNEL); - if (!sas_expander->phy) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -1; - goto out_fail; - } - - INIT_LIST_HEAD(&sas_expander->sas_port_list); - mpt3sas_port = mpt3sas_transport_port_add(ioc, handle, - sas_address_parent); - if (!mpt3sas_port) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -1; - goto out_fail; - } - sas_expander->parent_dev = &mpt3sas_port->rphy->dev; - - for (i = 0 ; i < sas_expander->num_phys ; i++) { - if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply, - &expander_pg1, i, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -1; - goto out_fail; - } - sas_expander->phy[i].handle = handle; - sas_expander->phy[i].phy_id = i; - - if ((mpt3sas_transport_add_expander_phy(ioc, - &sas_expander->phy[i], expander_pg1, - sas_expander->parent_dev))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -1; - goto out_fail; - } - } - - if (sas_expander->enclosure_handle) { - if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply, - &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - sas_expander->enclosure_handle))) - sas_expander->enclosure_logical_id = - le64_to_cpu(enclosure_pg0.EnclosureLogicalID); - } - - _scsih_expander_node_add(ioc, sas_expander); - return 0; - - out_fail: - - if (mpt3sas_port) - mpt3sas_transport_port_remove(ioc, sas_expander->sas_address, - sas_address_parent); - kfree(sas_expander); - return rc; -} - -/** - * mpt3sas_expander_remove - removing expander object - * @ioc: per adapter object - * @sas_address: expander sas_address - * - * Return nothing. - */ -void -mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address) -{ - struct _sas_node *sas_expander; - unsigned long flags; - - if (ioc->shost_recovery) - return; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address); - if (sas_expander) - list_del(&sas_expander->list); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - if (sas_expander) - _scsih_expander_node_remove(ioc, sas_expander); -} - -/** - * _scsih_done - internal SCSI_IO callback handler. - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Callback handler when sending internal generated SCSI_IO. - * The callback index passed is `ioc->scsih_cb_idx` - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (ioc->scsih_cmds.status == MPT3_CMD_NOT_USED) - return 1; - if (ioc->scsih_cmds.smid != smid) - return 1; - ioc->scsih_cmds.status |= MPT3_CMD_COMPLETE; - if (mpi_reply) { - memcpy(ioc->scsih_cmds.reply, mpi_reply, - mpi_reply->MsgLength*4); - ioc->scsih_cmds.status |= MPT3_CMD_REPLY_VALID; - } - ioc->scsih_cmds.status &= ~MPT3_CMD_PENDING; - complete(&ioc->scsih_cmds.done); - return 1; -} - - - - -#define MPT3_MAX_LUNS (255) - - -/** - * _scsih_check_access_status - check access flags - * @ioc: per adapter object - * @sas_address: sas address - * @handle: sas device handle - * @access_flags: errors returned during discovery of the device - * - * Return 0 for success, else failure - */ -static u8 -_scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, - u16 handle, u8 access_status) -{ - u8 rc = 1; - char *desc = NULL; - - switch (access_status) { - case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS: - case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION: - rc = 0; - break; - case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED: - desc = "sata capability failed"; - break; - case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT: - desc = "sata affiliation conflict"; - break; - case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE: - desc = "route not addressable"; - break; - case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE: - desc = "smp error not addressable"; - break; - case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED: - desc = "device blocked"; - break; - case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX: - desc = "sata initialization failed"; - break; - default: - desc = "unknown"; - break; - } - - if (!rc) - return 0; - - pr_err(MPT3SAS_FMT - "discovery errors(%s): sas_address(0x%016llx), handle(0x%04x)\n", - ioc->name, desc, (unsigned long long)sas_address, handle); - return rc; -} - -/** - * _scsih_check_device - checking device responsiveness - * @ioc: per adapter object - * @parent_sas_address: sas address of parent expander or sas host - * @handle: attached device handle - * @phy_numberv: phy number - * @link_rate: new link rate - * - * Returns nothing. - */ -static void -_scsih_check_device(struct MPT3SAS_ADAPTER *ioc, - u64 parent_sas_address, u16 handle, u8 phy_number, u8 link_rate) -{ - Mpi2ConfigReply_t mpi_reply; - Mpi2SasDevicePage0_t sas_device_pg0; - struct _sas_device *sas_device; - u32 ioc_status; - unsigned long flags; - u64 sas_address; - struct scsi_target *starget; - struct MPT3SAS_TARGET *sas_target_priv_data; - u32 device_info; - - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) - return; - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - return; - - /* wide port handling ~ we need only handle device once for the phy that - * is matched in sas device page zero - */ - if (phy_number != sas_device_pg0.PhyNum) - return; - - /* check if this is end device */ - device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); - if (!(_scsih_is_end_device(device_info))) - return; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_address = le64_to_cpu(sas_device_pg0.SASAddress); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - sas_address); - - if (!sas_device) { - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return; - } - - if (unlikely(sas_device->handle != handle)) { - starget = sas_device->starget; - sas_target_priv_data = starget->hostdata; - starget_printk(KERN_INFO, starget, - "handle changed from(0x%04x) to (0x%04x)!!!\n", - sas_device->handle, handle); - sas_target_priv_data->handle = handle; - sas_device->handle = handle; - } - - /* check if device is present */ - if (!(le16_to_cpu(sas_device_pg0.Flags) & - MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) { - pr_err(MPT3SAS_FMT - "device is not present handle(0x%04x), flags!!!\n", - ioc->name, handle); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return; - } - - /* check if there were any issues with discovery */ - if (_scsih_check_access_status(ioc, sas_address, handle, - sas_device_pg0.AccessStatus)) { - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return; - } - - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - _scsih_ublock_io_device(ioc, sas_address); - -} - -/** - * _scsih_add_device - creating sas device object - * @ioc: per adapter object - * @handle: sas device handle - * @phy_num: phy number end device attached to - * @is_pd: is this hidden raid component - * - * Creating end device object, stored in ioc->sas_device_list. - * - * Returns 0 for success, non-zero for failure. - */ -static int -_scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, - u8 is_pd) -{ - Mpi2ConfigReply_t mpi_reply; - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2SasEnclosurePage0_t enclosure_pg0; - struct _sas_device *sas_device; - u32 ioc_status; - u64 sas_address; - u32 device_info; - unsigned long flags; - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - - /* check if this is end device */ - device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); - if (!(_scsih_is_end_device(device_info))) - return -1; - sas_address = le64_to_cpu(sas_device_pg0.SASAddress); - - /* check if device is present */ - if (!(le16_to_cpu(sas_device_pg0.Flags) & - MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) { - pr_err(MPT3SAS_FMT "device is not present handle(0x04%x)!!!\n", - ioc->name, handle); - return -1; - } - - /* check if there were any issues with discovery */ - if (_scsih_check_access_status(ioc, sas_address, handle, - sas_device_pg0.AccessStatus)) - return -1; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - sas_address); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - if (sas_device) - return -1; - - sas_device = kzalloc(sizeof(struct _sas_device), - GFP_KERNEL); - if (!sas_device) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return 0; - } - - sas_device->handle = handle; - if (_scsih_get_sas_address(ioc, - le16_to_cpu(sas_device_pg0.ParentDevHandle), - &sas_device->sas_address_parent) != 0) - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - sas_device->enclosure_handle = - le16_to_cpu(sas_device_pg0.EnclosureHandle); - sas_device->slot = - le16_to_cpu(sas_device_pg0.Slot); - sas_device->device_info = device_info; - sas_device->sas_address = sas_address; - sas_device->phy = sas_device_pg0.PhyNum; - sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) & - MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0; - - /* get enclosure_logical_id */ - if (sas_device->enclosure_handle && !(mpt3sas_config_get_enclosure_pg0( - ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - sas_device->enclosure_handle))) - sas_device->enclosure_logical_id = - le64_to_cpu(enclosure_pg0.EnclosureLogicalID); - - /* get device name */ - sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName); - - if (ioc->wait_for_discovery_to_complete) - _scsih_sas_device_init_add(ioc, sas_device); - else - _scsih_sas_device_add(ioc, sas_device); - - return 0; -} - -/** - * _scsih_remove_device - removing sas device object - * @ioc: per adapter object - * @sas_device_delete: the sas_device object - * - * Return nothing. - */ -static void -_scsih_remove_device(struct MPT3SAS_ADAPTER *ioc, - struct _sas_device *sas_device) -{ - struct MPT3SAS_TARGET *sas_target_priv_data; - - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: enter: handle(0x%04x), sas_addr(0x%016llx)\n", - ioc->name, __func__, - sas_device->handle, (unsigned long long) - sas_device->sas_address)); - - if (sas_device->starget && sas_device->starget->hostdata) { - sas_target_priv_data = sas_device->starget->hostdata; - sas_target_priv_data->deleted = 1; - _scsih_ublock_io_device(ioc, sas_device->sas_address); - sas_target_priv_data->handle = - MPT3SAS_INVALID_DEVICE_HANDLE; - } - mpt3sas_transport_port_remove(ioc, - sas_device->sas_address, - sas_device->sas_address_parent); - - pr_info(MPT3SAS_FMT - "removing handle(0x%04x), sas_addr(0x%016llx)\n", - ioc->name, sas_device->handle, - (unsigned long long) sas_device->sas_address); - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: exit: handle(0x%04x), sas_addr(0x%016llx)\n", - ioc->name, __func__, - sas_device->handle, (unsigned long long) - sas_device->sas_address)); - - kfree(sas_device); -} - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING -/** - * _scsih_sas_topology_change_event_debug - debug for topology event - * @ioc: per adapter object - * @event_data: event data payload - * Context: user. - */ -static void -_scsih_sas_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataSasTopologyChangeList_t *event_data) -{ - int i; - u16 handle; - u16 reason_code; - u8 phy_number; - char *status_str = NULL; - u8 link_rate, prev_link_rate; - - switch (event_data->ExpStatus) { - case MPI2_EVENT_SAS_TOPO_ES_ADDED: - status_str = "add"; - break; - case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING: - status_str = "remove"; - break; - case MPI2_EVENT_SAS_TOPO_ES_RESPONDING: - case 0: - status_str = "responding"; - break; - case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING: - status_str = "remove delay"; - break; - default: - status_str = "unknown status"; - break; - } - pr_info(MPT3SAS_FMT "sas topology change: (%s)\n", - ioc->name, status_str); - pr_info("\thandle(0x%04x), enclosure_handle(0x%04x) " \ - "start_phy(%02d), count(%d)\n", - le16_to_cpu(event_data->ExpanderDevHandle), - le16_to_cpu(event_data->EnclosureHandle), - event_data->StartPhyNum, event_data->NumEntries); - for (i = 0; i < event_data->NumEntries; i++) { - handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); - if (!handle) - continue; - phy_number = event_data->StartPhyNum + i; - reason_code = event_data->PHY[i].PhyStatus & - MPI2_EVENT_SAS_TOPO_RC_MASK; - switch (reason_code) { - case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: - status_str = "target add"; - break; - case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: - status_str = "target remove"; - break; - case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING: - status_str = "delay target remove"; - break; - case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: - status_str = "link rate change"; - break; - case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE: - status_str = "target responding"; - break; - default: - status_str = "unknown"; - break; - } - link_rate = event_data->PHY[i].LinkRate >> 4; - prev_link_rate = event_data->PHY[i].LinkRate & 0xF; - pr_info("\tphy(%02d), attached_handle(0x%04x): %s:" \ - " link rate: new(0x%02x), old(0x%02x)\n", phy_number, - handle, status_str, link_rate, prev_link_rate); - - } -} -#endif - -/** - * _scsih_sas_topology_change_event - handle topology changes - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - */ -static int -_scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - int i; - u16 parent_handle, handle; - u16 reason_code; - u8 phy_number, max_phys; - struct _sas_node *sas_expander; - u64 sas_address; - unsigned long flags; - u8 link_rate, prev_link_rate; - Mpi2EventDataSasTopologyChangeList_t *event_data = fw_event->event_data; - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) - _scsih_sas_topology_change_event_debug(ioc, event_data); -#endif - - if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery) - return 0; - - if (!ioc->sas_hba.num_phys) - _scsih_sas_host_add(ioc); - else - _scsih_sas_host_refresh(ioc); - - if (fw_event->ignore) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "ignoring expander event\n", ioc->name)); - return 0; - } - - parent_handle = le16_to_cpu(event_data->ExpanderDevHandle); - - /* handle expander add */ - if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED) - if (_scsih_expander_add(ioc, parent_handle) != 0) - return 0; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc, - parent_handle); - if (sas_expander) { - sas_address = sas_expander->sas_address; - max_phys = sas_expander->num_phys; - } else if (parent_handle < ioc->sas_hba.num_phys) { - sas_address = ioc->sas_hba.sas_address; - max_phys = ioc->sas_hba.num_phys; - } else { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return 0; - } - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - /* handle siblings events */ - for (i = 0; i < event_data->NumEntries; i++) { - if (fw_event->ignore) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "ignoring expander event\n", ioc->name)); - return 0; - } - if (ioc->remove_host || ioc->pci_error_recovery) - return 0; - phy_number = event_data->StartPhyNum + i; - if (phy_number >= max_phys) - continue; - reason_code = event_data->PHY[i].PhyStatus & - MPI2_EVENT_SAS_TOPO_RC_MASK; - if ((event_data->PHY[i].PhyStatus & - MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code != - MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) - continue; - handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); - if (!handle) - continue; - link_rate = event_data->PHY[i].LinkRate >> 4; - prev_link_rate = event_data->PHY[i].LinkRate & 0xF; - switch (reason_code) { - case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: - - if (ioc->shost_recovery) - break; - - if (link_rate == prev_link_rate) - break; - - mpt3sas_transport_update_links(ioc, sas_address, - handle, phy_number, link_rate); - - if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5) - break; - - _scsih_check_device(ioc, sas_address, handle, - phy_number, link_rate); - - - case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: - - if (ioc->shost_recovery) - break; - - mpt3sas_transport_update_links(ioc, sas_address, - handle, phy_number, link_rate); - - _scsih_add_device(ioc, handle, phy_number, 0); - - break; - case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: - - _scsih_device_remove_by_handle(ioc, handle); - break; - } - } - - /* handle expander removal */ - if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING && - sas_expander) - mpt3sas_expander_remove(ioc, sas_address); - - return 0; -} - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING -/** - * _scsih_sas_device_status_change_event_debug - debug for device event - * @event_data: event data payload - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataSasDeviceStatusChange_t *event_data) -{ - char *reason_str = NULL; - - switch (event_data->ReasonCode) { - case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA: - reason_str = "smart data"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: - reason_str = "unsupported device discovered"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: - reason_str = "internal device reset"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: - reason_str = "internal task abort"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: - reason_str = "internal task abort set"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: - reason_str = "internal clear task set"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: - reason_str = "internal query task"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE: - reason_str = "sata init failure"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET: - reason_str = "internal device reset complete"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL: - reason_str = "internal task abort complete"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION: - reason_str = "internal async notification"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY: - reason_str = "expander reduced functionality"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY: - reason_str = "expander reduced functionality complete"; - break; - default: - reason_str = "unknown reason"; - break; - } - pr_info(MPT3SAS_FMT "device status change: (%s)\n" - "\thandle(0x%04x), sas address(0x%016llx), tag(%d)", - ioc->name, reason_str, le16_to_cpu(event_data->DevHandle), - (unsigned long long)le64_to_cpu(event_data->SASAddress), - le16_to_cpu(event_data->TaskTag)); - if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA) - pr_info(MPT3SAS_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name, - event_data->ASC, event_data->ASCQ); - pr_info("\n"); -} -#endif - -/** - * _scsih_sas_device_status_change_event - handle device status change - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - struct MPT3SAS_TARGET *target_priv_data; - struct _sas_device *sas_device; - u64 sas_address; - unsigned long flags; - Mpi2EventDataSasDeviceStatusChange_t *event_data = - fw_event->event_data; - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) - _scsih_sas_device_status_change_event_debug(ioc, - event_data); -#endif - - /* In MPI Revision K (0xC), the internal device reset complete was - * implemented, so avoid setting tm_busy flag for older firmware. - */ - if ((ioc->facts.HeaderVersion >> 8) < 0xC) - return; - - if (event_data->ReasonCode != - MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET && - event_data->ReasonCode != - MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET) - return; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_address = le64_to_cpu(event_data->SASAddress); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - sas_address); - - if (!sas_device || !sas_device->starget) { - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return; - } - - target_priv_data = sas_device->starget->hostdata; - if (!target_priv_data) { - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return; - } - - if (event_data->ReasonCode == - MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET) - target_priv_data->tm_busy = 1; - else - target_priv_data->tm_busy = 0; - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); -} - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING -/** - * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure - * event - * @ioc: per adapter object - * @event_data: event data payload - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataSasEnclDevStatusChange_t *event_data) -{ - char *reason_str = NULL; - - switch (event_data->ReasonCode) { - case MPI2_EVENT_SAS_ENCL_RC_ADDED: - reason_str = "enclosure add"; - break; - case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING: - reason_str = "enclosure remove"; - break; - default: - reason_str = "unknown reason"; - break; - } - - pr_info(MPT3SAS_FMT "enclosure status change: (%s)\n" - "\thandle(0x%04x), enclosure logical id(0x%016llx)" - " number slots(%d)\n", ioc->name, reason_str, - le16_to_cpu(event_data->EnclosureHandle), - (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID), - le16_to_cpu(event_data->StartSlot)); -} -#endif - -/** - * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) - _scsih_sas_enclosure_dev_status_change_event_debug(ioc, - fw_event->event_data); -#endif -} - -/** - * _scsih_sas_broadcast_primitive_event - handle broadcast events - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - struct scsi_cmnd *scmd; - struct scsi_device *sdev; - u16 smid, handle; - u32 lun; - struct MPT3SAS_DEVICE *sas_device_priv_data; - u32 termination_count; - u32 query_count; - Mpi2SCSITaskManagementReply_t *mpi_reply; - Mpi2EventDataSasBroadcastPrimitive_t *event_data = fw_event->event_data; - u16 ioc_status; - unsigned long flags; - int r; - u8 max_retries = 0; - u8 task_abort_retries; - - mutex_lock(&ioc->tm_cmds.mutex); - pr_info(MPT3SAS_FMT - "%s: enter: phy number(%d), width(%d)\n", - ioc->name, __func__, event_data->PhyNum, - event_data->PortWidth); - - _scsih_block_io_all_device(ioc); - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - mpi_reply = ioc->tm_cmds.reply; - broadcast_aen_retry: - - /* sanity checks for retrying this loop */ - if (max_retries++ == 5) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: giving up\n", - ioc->name, __func__)); - goto out; - } else if (max_retries > 1) - dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: %d retry\n", - ioc->name, __func__, max_retries - 1)); - - termination_count = 0; - query_count = 0; - for (smid = 1; smid <= ioc->scsiio_depth; smid++) { - if (ioc->shost_recovery) - goto out; - scmd = _scsih_scsi_lookup_get(ioc, smid); - if (!scmd) - continue; - sdev = scmd->device; - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data || !sas_device_priv_data->sas_target) - continue; - /* skip hidden raid components */ - if (sas_device_priv_data->sas_target->flags & - MPT_TARGET_FLAGS_RAID_COMPONENT) - continue; - /* skip volumes */ - if (sas_device_priv_data->sas_target->flags & - MPT_TARGET_FLAGS_VOLUME) - continue; - - handle = sas_device_priv_data->sas_target->handle; - lun = sas_device_priv_data->lun; - query_count++; - - if (ioc->shost_recovery) - goto out; - - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - r = mpt3sas_scsih_issue_tm(ioc, handle, 0, 0, lun, - MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, 0, - TM_MUTEX_OFF); - if (r == FAILED) { - sdev_printk(KERN_WARNING, sdev, - "mpt3sas_scsih_issue_tm: FAILED when sending " - "QUERY_TASK: scmd(%p)\n", scmd); - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - goto broadcast_aen_retry; - } - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) - & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - sdev_printk(KERN_WARNING, sdev, - "query task: FAILED with IOCSTATUS(0x%04x), scmd(%p)\n", - ioc_status, scmd); - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - goto broadcast_aen_retry; - } - - /* see if IO is still owned by IOC and target */ - if (mpi_reply->ResponseCode == - MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED || - mpi_reply->ResponseCode == - MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) { - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - continue; - } - task_abort_retries = 0; - tm_retry: - if (task_abort_retries++ == 60) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: ABORT_TASK: giving up\n", ioc->name, - __func__)); - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - goto broadcast_aen_retry; - } - - if (ioc->shost_recovery) - goto out_no_lock; - - r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id, - sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, - scmd->serial_number, TM_MUTEX_OFF); - if (r == FAILED) { - sdev_printk(KERN_WARNING, sdev, - "mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : " - "scmd(%p)\n", scmd); - goto tm_retry; - } - - if (task_abort_retries > 1) - sdev_printk(KERN_WARNING, sdev, - "mpt3sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):" - " scmd(%p)\n", - task_abort_retries - 1, scmd); - - termination_count += le32_to_cpu(mpi_reply->TerminationCount); - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - } - - if (ioc->broadcast_aen_pending) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: loop back due to pending AEN\n", - ioc->name, __func__)); - ioc->broadcast_aen_pending = 0; - goto broadcast_aen_retry; - } - - out: - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - out_no_lock: - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s - exit, query_count = %d termination_count = %d\n", - ioc->name, __func__, query_count, termination_count)); - - ioc->broadcast_aen_busy = 0; - if (!ioc->shost_recovery) - _scsih_ublock_io_all_device(ioc); - mutex_unlock(&ioc->tm_cmds.mutex); -} - -/** - * _scsih_sas_discovery_event - handle discovery events - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - Mpi2EventDataSasDiscovery_t *event_data = fw_event->event_data; - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) { - pr_info(MPT3SAS_FMT "discovery event: (%s)", ioc->name, - (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ? - "start" : "stop"); - if (event_data->DiscoveryStatus) - pr_info("discovery_status(0x%08x)", - le32_to_cpu(event_data->DiscoveryStatus)); - pr_info("\n"); - } -#endif - - if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED && - !ioc->sas_hba.num_phys) { - if (disable_discovery > 0 && ioc->shost_recovery) { - /* Wait for the reset to complete */ - while (ioc->shost_recovery) - ssleep(1); - } - _scsih_sas_host_add(ioc); - } -} - -/** - * _scsih_ir_fastpath - turn on fastpath for IR physdisk - * @ioc: per adapter object - * @handle: device handle for physical disk - * @phys_disk_num: physical disk number - * - * Return 0 for success, else failure. - */ -static int -_scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num) -{ - Mpi2RaidActionRequest_t *mpi_request; - Mpi2RaidActionReply_t *mpi_reply; - u16 smid; - u8 issue_reset = 0; - int rc = 0; - u16 ioc_status; - u32 log_info; - - - mutex_lock(&ioc->scsih_cmds.mutex); - - if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - ioc->scsih_cmds.status = MPT3_CMD_PENDING; - - smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; - rc = -EAGAIN; - goto out; - } - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->scsih_cmds.smid = smid; - memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t)); - - mpi_request->Function = MPI2_FUNCTION_RAID_ACTION; - mpi_request->Action = MPI2_RAID_ACTION_PHYSDISK_HIDDEN; - mpi_request->PhysDiskNum = phys_disk_num; - - dewtprintk(ioc, pr_info(MPT3SAS_FMT "IR RAID_ACTION: turning fast "\ - "path on for handle(0x%04x), phys_disk_num (0x%02x)\n", ioc->name, - handle, phys_disk_num)); - - init_completion(&ioc->scsih_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); - - if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - if (!(ioc->scsih_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - rc = -EFAULT; - goto out; - } - - if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) { - - mpi_reply = ioc->scsih_cmds.reply; - ioc_status = le16_to_cpu(mpi_reply->IOCStatus); - if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) - log_info = le32_to_cpu(mpi_reply->IOCLogInfo); - else - log_info = 0; - ioc_status &= MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "IR RAID_ACTION: failed: ioc_status(0x%04x), " - "loginfo(0x%08x)!!!\n", ioc->name, ioc_status, - log_info)); - rc = -EFAULT; - } else - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "IR RAID_ACTION: completed successfully\n", - ioc->name)); - } - - out: - ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; - mutex_unlock(&ioc->scsih_cmds.mutex); - - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - return rc; -} - -/** - * _scsih_reprobe_lun - reprobing lun - * @sdev: scsi device struct - * @no_uld_attach: sdev->no_uld_attach flag setting - * - **/ -static void -_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach) -{ - int rc; - sdev->no_uld_attach = no_uld_attach ? 1 : 0; - sdev_printk(KERN_INFO, sdev, "%s raid component\n", - sdev->no_uld_attach ? "hidding" : "exposing"); - rc = scsi_device_reprobe(sdev); -} - -/** - * _scsih_sas_volume_add - add new volume - * @ioc: per adapter object - * @element: IR config element data - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_volume_add(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventIrConfigElement_t *element) -{ - struct _raid_device *raid_device; - unsigned long flags; - u64 wwid; - u16 handle = le16_to_cpu(element->VolDevHandle); - int rc; - - mpt3sas_config_get_volume_wwid(ioc, handle, &wwid); - if (!wwid) { - pr_err(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__); - return; - } - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - - if (raid_device) - return; - - raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL); - if (!raid_device) { - pr_err(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__); - return; - } - - raid_device->id = ioc->sas_id++; - raid_device->channel = RAID_CHANNEL; - raid_device->handle = handle; - raid_device->wwid = wwid; - _scsih_raid_device_add(ioc, raid_device); - if (!ioc->wait_for_discovery_to_complete) { - rc = scsi_add_device(ioc->shost, RAID_CHANNEL, - raid_device->id, 0); - if (rc) - _scsih_raid_device_remove(ioc, raid_device); - } else { - spin_lock_irqsave(&ioc->raid_device_lock, flags); - _scsih_determine_boot_device(ioc, raid_device, 1); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - } -} - -/** - * _scsih_sas_volume_delete - delete volume - * @ioc: per adapter object - * @handle: volume device handle - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_volume_delete(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _raid_device *raid_device; - unsigned long flags; - struct MPT3SAS_TARGET *sas_target_priv_data; - struct scsi_target *starget = NULL; - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_handle(ioc, handle); - if (raid_device) { - if (raid_device->starget) { - starget = raid_device->starget; - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->deleted = 1; - } - pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n", - ioc->name, raid_device->handle, - (unsigned long long) raid_device->wwid); - list_del(&raid_device->list); - kfree(raid_device); - } - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - if (starget) - scsi_remove_target(&starget->dev); -} - -/** - * _scsih_sas_pd_expose - expose pd component to /dev/sdX - * @ioc: per adapter object - * @element: IR config element data - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventIrConfigElement_t *element) -{ - struct _sas_device *sas_device; - struct scsi_target *starget = NULL; - struct MPT3SAS_TARGET *sas_target_priv_data; - unsigned long flags; - u16 handle = le16_to_cpu(element->PhysDiskDevHandle); - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _scsih_sas_device_find_by_handle(ioc, handle); - if (sas_device) { - sas_device->volume_handle = 0; - sas_device->volume_wwid = 0; - clear_bit(handle, ioc->pd_handles); - if (sas_device->starget && sas_device->starget->hostdata) { - starget = sas_device->starget; - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->flags &= - ~MPT_TARGET_FLAGS_RAID_COMPONENT; - } - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (!sas_device) - return; - - /* exposing raid component */ - if (starget) - starget_for_each_device(starget, NULL, _scsih_reprobe_lun); -} - -/** - * _scsih_sas_pd_hide - hide pd component from /dev/sdX - * @ioc: per adapter object - * @element: IR config element data - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventIrConfigElement_t *element) -{ - struct _sas_device *sas_device; - struct scsi_target *starget = NULL; - struct MPT3SAS_TARGET *sas_target_priv_data; - unsigned long flags; - u16 handle = le16_to_cpu(element->PhysDiskDevHandle); - u16 volume_handle = 0; - u64 volume_wwid = 0; - - mpt3sas_config_get_volume_handle(ioc, handle, &volume_handle); - if (volume_handle) - mpt3sas_config_get_volume_wwid(ioc, volume_handle, - &volume_wwid); - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _scsih_sas_device_find_by_handle(ioc, handle); - if (sas_device) { - set_bit(handle, ioc->pd_handles); - if (sas_device->starget && sas_device->starget->hostdata) { - starget = sas_device->starget; - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->flags |= - MPT_TARGET_FLAGS_RAID_COMPONENT; - sas_device->volume_handle = volume_handle; - sas_device->volume_wwid = volume_wwid; - } - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (!sas_device) - return; - - /* hiding raid component */ - _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum); - if (starget) - starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun); -} - -/** - * _scsih_sas_pd_delete - delete pd component - * @ioc: per adapter object - * @element: IR config element data - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_pd_delete(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventIrConfigElement_t *element) -{ - u16 handle = le16_to_cpu(element->PhysDiskDevHandle); - - _scsih_device_remove_by_handle(ioc, handle); -} - -/** - * _scsih_sas_pd_add - remove pd component - * @ioc: per adapter object - * @element: IR config element data - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventIrConfigElement_t *element) -{ - struct _sas_device *sas_device; - unsigned long flags; - u16 handle = le16_to_cpu(element->PhysDiskDevHandle); - Mpi2ConfigReply_t mpi_reply; - Mpi2SasDevicePage0_t sas_device_pg0; - u32 ioc_status; - u64 sas_address; - u16 parent_handle; - - set_bit(handle, ioc->pd_handles); - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _scsih_sas_device_find_by_handle(ioc, handle); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (sas_device) { - _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum); - return; - } - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); - if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) - mpt3sas_transport_update_links(ioc, sas_address, handle, - sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); - - _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum); - _scsih_add_device(ioc, handle, 0, 1); -} - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING -/** - * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events - * @ioc: per adapter object - * @event_data: event data payload - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_ir_config_change_event_debug(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataIrConfigChangeList_t *event_data) -{ - Mpi2EventIrConfigElement_t *element; - u8 element_type; - int i; - char *reason_str = NULL, *element_str = NULL; - - element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; - - pr_info(MPT3SAS_FMT "raid config change: (%s), elements(%d)\n", - ioc->name, (le32_to_cpu(event_data->Flags) & - MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? - "foreign" : "native", event_data->NumElements); - for (i = 0; i < event_data->NumElements; i++, element++) { - switch (element->ReasonCode) { - case MPI2_EVENT_IR_CHANGE_RC_ADDED: - reason_str = "add"; - break; - case MPI2_EVENT_IR_CHANGE_RC_REMOVED: - reason_str = "remove"; - break; - case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE: - reason_str = "no change"; - break; - case MPI2_EVENT_IR_CHANGE_RC_HIDE: - reason_str = "hide"; - break; - case MPI2_EVENT_IR_CHANGE_RC_UNHIDE: - reason_str = "unhide"; - break; - case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: - reason_str = "volume_created"; - break; - case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: - reason_str = "volume_deleted"; - break; - case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: - reason_str = "pd_created"; - break; - case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: - reason_str = "pd_deleted"; - break; - default: - reason_str = "unknown reason"; - break; - } - element_type = le16_to_cpu(element->ElementFlags) & - MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK; - switch (element_type) { - case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT: - element_str = "volume"; - break; - case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT: - element_str = "phys disk"; - break; - case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT: - element_str = "hot spare"; - break; - default: - element_str = "unknown element"; - break; - } - pr_info("\t(%s:%s), vol handle(0x%04x), " \ - "pd handle(0x%04x), pd num(0x%02x)\n", element_str, - reason_str, le16_to_cpu(element->VolDevHandle), - le16_to_cpu(element->PhysDiskDevHandle), - element->PhysDiskNum); - } -} -#endif - -/** - * _scsih_sas_ir_config_change_event - handle ir configuration change events - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - Mpi2EventIrConfigElement_t *element; - int i; - u8 foreign_config; - Mpi2EventDataIrConfigChangeList_t *event_data = fw_event->event_data; - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) - _scsih_sas_ir_config_change_event_debug(ioc, event_data); - -#endif - - foreign_config = (le32_to_cpu(event_data->Flags) & - MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; - - element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; - if (ioc->shost_recovery) { - - for (i = 0; i < event_data->NumElements; i++, element++) { - if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_HIDE) - _scsih_ir_fastpath(ioc, - le16_to_cpu(element->PhysDiskDevHandle), - element->PhysDiskNum); - } - return; - } - for (i = 0; i < event_data->NumElements; i++, element++) { - - switch (element->ReasonCode) { - case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: - case MPI2_EVENT_IR_CHANGE_RC_ADDED: - if (!foreign_config) - _scsih_sas_volume_add(ioc, element); - break; - case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: - case MPI2_EVENT_IR_CHANGE_RC_REMOVED: - if (!foreign_config) - _scsih_sas_volume_delete(ioc, - le16_to_cpu(element->VolDevHandle)); - break; - case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: - _scsih_sas_pd_hide(ioc, element); - break; - case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: - _scsih_sas_pd_expose(ioc, element); - break; - case MPI2_EVENT_IR_CHANGE_RC_HIDE: - _scsih_sas_pd_add(ioc, element); - break; - case MPI2_EVENT_IR_CHANGE_RC_UNHIDE: - _scsih_sas_pd_delete(ioc, element); - break; - } - } -} - -/** - * _scsih_sas_ir_volume_event - IR volume event - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - u64 wwid; - unsigned long flags; - struct _raid_device *raid_device; - u16 handle; - u32 state; - int rc; - Mpi2EventDataIrVolume_t *event_data = fw_event->event_data; - - if (ioc->shost_recovery) - return; - - if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) - return; - - handle = le16_to_cpu(event_data->VolDevHandle); - state = le32_to_cpu(event_data->NewValue); - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n", - ioc->name, __func__, handle, - le32_to_cpu(event_data->PreviousValue), state)); - switch (state) { - case MPI2_RAID_VOL_STATE_MISSING: - case MPI2_RAID_VOL_STATE_FAILED: - _scsih_sas_volume_delete(ioc, handle); - break; - - case MPI2_RAID_VOL_STATE_ONLINE: - case MPI2_RAID_VOL_STATE_DEGRADED: - case MPI2_RAID_VOL_STATE_OPTIMAL: - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_handle(ioc, handle); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - - if (raid_device) - break; - - mpt3sas_config_get_volume_wwid(ioc, handle, &wwid); - if (!wwid) { - pr_err(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__); - break; - } - - raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL); - if (!raid_device) { - pr_err(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__); - break; - } - - raid_device->id = ioc->sas_id++; - raid_device->channel = RAID_CHANNEL; - raid_device->handle = handle; - raid_device->wwid = wwid; - _scsih_raid_device_add(ioc, raid_device); - rc = scsi_add_device(ioc->shost, RAID_CHANNEL, - raid_device->id, 0); - if (rc) - _scsih_raid_device_remove(ioc, raid_device); - break; - - case MPI2_RAID_VOL_STATE_INITIALIZING: - default: - break; - } -} - -/** - * _scsih_sas_ir_physical_disk_event - PD event - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - u16 handle, parent_handle; - u32 state; - struct _sas_device *sas_device; - unsigned long flags; - Mpi2ConfigReply_t mpi_reply; - Mpi2SasDevicePage0_t sas_device_pg0; - u32 ioc_status; - Mpi2EventDataIrPhysicalDisk_t *event_data = fw_event->event_data; - u64 sas_address; - - if (ioc->shost_recovery) - return; - - if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) - return; - - handle = le16_to_cpu(event_data->PhysDiskDevHandle); - state = le32_to_cpu(event_data->NewValue); - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n", - ioc->name, __func__, handle, - le32_to_cpu(event_data->PreviousValue), state)); - switch (state) { - case MPI2_RAID_PD_STATE_ONLINE: - case MPI2_RAID_PD_STATE_DEGRADED: - case MPI2_RAID_PD_STATE_REBUILDING: - case MPI2_RAID_PD_STATE_OPTIMAL: - case MPI2_RAID_PD_STATE_HOT_SPARE: - - set_bit(handle, ioc->pd_handles); - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _scsih_sas_device_find_by_handle(ioc, handle); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - if (sas_device) - return; - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, - &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, - handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); - if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) - mpt3sas_transport_update_links(ioc, sas_address, handle, - sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); - - _scsih_add_device(ioc, handle, 0, 1); - - break; - - case MPI2_RAID_PD_STATE_OFFLINE: - case MPI2_RAID_PD_STATE_NOT_CONFIGURED: - case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: - default: - break; - } -} - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING -/** - * _scsih_sas_ir_operation_status_event_debug - debug for IR op event - * @ioc: per adapter object - * @event_data: event data payload - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_ir_operation_status_event_debug(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataIrOperationStatus_t *event_data) -{ - char *reason_str = NULL; - - switch (event_data->RAIDOperation) { - case MPI2_EVENT_IR_RAIDOP_RESYNC: - reason_str = "resync"; - break; - case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION: - reason_str = "online capacity expansion"; - break; - case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK: - reason_str = "consistency check"; - break; - case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT: - reason_str = "background init"; - break; - case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT: - reason_str = "make data consistent"; - break; - } - - if (!reason_str) - return; - - pr_info(MPT3SAS_FMT "raid operational status: (%s)" \ - "\thandle(0x%04x), percent complete(%d)\n", - ioc->name, reason_str, - le16_to_cpu(event_data->VolDevHandle), - event_data->PercentComplete); -} -#endif - -/** - * _scsih_sas_ir_operation_status_event - handle RAID operation events - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - Mpi2EventDataIrOperationStatus_t *event_data = fw_event->event_data; - static struct _raid_device *raid_device; - unsigned long flags; - u16 handle; - -#ifdef CONFIG_SCSI_MPT3SAS_LOGGING - if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) - _scsih_sas_ir_operation_status_event_debug(ioc, - event_data); -#endif - - /* code added for raid transport support */ - if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) { - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - handle = le16_to_cpu(event_data->VolDevHandle); - raid_device = _scsih_raid_device_find_by_handle(ioc, handle); - if (raid_device) - raid_device->percent_complete = - event_data->PercentComplete; - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - } -} - -/** - * _scsih_prep_device_scan - initialize parameters prior to device scan - * @ioc: per adapter object - * - * Set the deleted flag prior to device scan. If the device is found during - * the scan, then we clear the deleted flag. - */ -static void -_scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - - shost_for_each_device(sdev, ioc->shost) { - sas_device_priv_data = sdev->hostdata; - if (sas_device_priv_data && sas_device_priv_data->sas_target) - sas_device_priv_data->sas_target->deleted = 1; - } -} - -/** - * _scsih_mark_responding_sas_device - mark a sas_devices as responding - * @ioc: per adapter object - * @sas_address: sas address - * @slot: enclosure slot id - * @handle: device handle - * - * After host reset, find out whether devices are still responding. - * Used in _scsih_remove_unresponsive_sas_devices. - * - * Return nothing. - */ -static void -_scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, - u16 slot, u16 handle) -{ - struct MPT3SAS_TARGET *sas_target_priv_data = NULL; - struct scsi_target *starget; - struct _sas_device *sas_device; - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - list_for_each_entry(sas_device, &ioc->sas_device_list, list) { - if (sas_device->sas_address == sas_address && - sas_device->slot == slot) { - sas_device->responding = 1; - starget = sas_device->starget; - if (starget && starget->hostdata) { - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->tm_busy = 0; - sas_target_priv_data->deleted = 0; - } else - sas_target_priv_data = NULL; - if (starget) - starget_printk(KERN_INFO, starget, - "handle(0x%04x), sas_addr(0x%016llx), " - "enclosure logical id(0x%016llx), " - "slot(%d)\n", handle, - (unsigned long long)sas_device->sas_address, - (unsigned long long) - sas_device->enclosure_logical_id, - sas_device->slot); - if (sas_device->handle == handle) - goto out; - pr_info("\thandle changed from(0x%04x)!!!\n", - sas_device->handle); - sas_device->handle = handle; - if (sas_target_priv_data) - sas_target_priv_data->handle = handle; - goto out; - } - } - out: - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); -} - -/** - * _scsih_search_responding_sas_devices - - * @ioc: per adapter object - * - * After host reset, find out whether devices are still responding. - * If not remove. - * - * Return nothing. - */ -static void -_scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2ConfigReply_t mpi_reply; - u16 ioc_status; - u16 handle; - u32 device_info; - - pr_info(MPT3SAS_FMT "search for end-devices: start\n", ioc->name); - - if (list_empty(&ioc->sas_device_list)) - goto out; - - handle = 0xFFFF; - while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, - &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, - handle))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - break; - handle = le16_to_cpu(sas_device_pg0.DevHandle); - device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); - if (!(_scsih_is_end_device(device_info))) - continue; - _scsih_mark_responding_sas_device(ioc, - le64_to_cpu(sas_device_pg0.SASAddress), - le16_to_cpu(sas_device_pg0.Slot), handle); - } - - out: - pr_info(MPT3SAS_FMT "search for end-devices: complete\n", - ioc->name); -} - -/** - * _scsih_mark_responding_raid_device - mark a raid_device as responding - * @ioc: per adapter object - * @wwid: world wide identifier for raid volume - * @handle: device handle - * - * After host reset, find out whether devices are still responding. - * Used in _scsih_remove_unresponsive_raid_devices. - * - * Return nothing. - */ -static void -_scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid, - u16 handle) -{ - struct MPT3SAS_TARGET *sas_target_priv_data; - struct scsi_target *starget; - struct _raid_device *raid_device; - unsigned long flags; - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - list_for_each_entry(raid_device, &ioc->raid_device_list, list) { - if (raid_device->wwid == wwid && raid_device->starget) { - starget = raid_device->starget; - if (starget && starget->hostdata) { - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->deleted = 0; - } else - sas_target_priv_data = NULL; - raid_device->responding = 1; - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - starget_printk(KERN_INFO, raid_device->starget, - "handle(0x%04x), wwid(0x%016llx)\n", handle, - (unsigned long long)raid_device->wwid); - spin_lock_irqsave(&ioc->raid_device_lock, flags); - if (raid_device->handle == handle) { - spin_unlock_irqrestore(&ioc->raid_device_lock, - flags); - return; - } - pr_info("\thandle changed from(0x%04x)!!!\n", - raid_device->handle); - raid_device->handle = handle; - if (sas_target_priv_data) - sas_target_priv_data->handle = handle; - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - return; - } - } - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); -} - -/** - * _scsih_search_responding_raid_devices - - * @ioc: per adapter object - * - * After host reset, find out whether devices are still responding. - * If not remove. - * - * Return nothing. - */ -static void -_scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2RaidVolPage1_t volume_pg1; - Mpi2RaidVolPage0_t volume_pg0; - Mpi2RaidPhysDiskPage0_t pd_pg0; - Mpi2ConfigReply_t mpi_reply; - u16 ioc_status; - u16 handle; - u8 phys_disk_num; - - if (!ioc->ir_firmware) - return; - - pr_info(MPT3SAS_FMT "search for raid volumes: start\n", - ioc->name); - - if (list_empty(&ioc->raid_device_list)) - goto out; - - handle = 0xFFFF; - while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, - &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - break; - handle = le16_to_cpu(volume_pg1.DevHandle); - - if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, - &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, - sizeof(Mpi2RaidVolPage0_t))) - continue; - - if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL || - volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE || - volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) - _scsih_mark_responding_raid_device(ioc, - le64_to_cpu(volume_pg1.WWID), handle); - } - - /* refresh the pd_handles */ - phys_disk_num = 0xFF; - memset(ioc->pd_handles, 0, ioc->pd_handles_sz); - while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply, - &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM, - phys_disk_num))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - break; - phys_disk_num = pd_pg0.PhysDiskNum; - handle = le16_to_cpu(pd_pg0.DevHandle); - set_bit(handle, ioc->pd_handles); - } - out: - pr_info(MPT3SAS_FMT "search for responding raid volumes: complete\n", - ioc->name); -} - -/** - * _scsih_mark_responding_expander - mark a expander as responding - * @ioc: per adapter object - * @sas_address: sas address - * @handle: - * - * After host reset, find out whether devices are still responding. - * Used in _scsih_remove_unresponsive_expanders. - * - * Return nothing. - */ -static void -_scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, - u16 handle) -{ - struct _sas_node *sas_expander; - unsigned long flags; - int i; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { - if (sas_expander->sas_address != sas_address) - continue; - sas_expander->responding = 1; - if (sas_expander->handle == handle) - goto out; - pr_info("\texpander(0x%016llx): handle changed" \ - " from(0x%04x) to (0x%04x)!!!\n", - (unsigned long long)sas_expander->sas_address, - sas_expander->handle, handle); - sas_expander->handle = handle; - for (i = 0 ; i < sas_expander->num_phys ; i++) - sas_expander->phy[i].handle = handle; - goto out; - } - out: - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); -} - -/** - * _scsih_search_responding_expanders - - * @ioc: per adapter object - * - * After host reset, find out whether devices are still responding. - * If not remove. - * - * Return nothing. - */ -static void -_scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2ExpanderPage0_t expander_pg0; - Mpi2ConfigReply_t mpi_reply; - u16 ioc_status; - u64 sas_address; - u16 handle; - - pr_info(MPT3SAS_FMT "search for expanders: start\n", ioc->name); - - if (list_empty(&ioc->sas_expander_list)) - goto out; - - handle = 0xFFFF; - while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, - MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) { - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - break; - - handle = le16_to_cpu(expander_pg0.DevHandle); - sas_address = le64_to_cpu(expander_pg0.SASAddress); - pr_info("\texpander present: handle(0x%04x), sas_addr(0x%016llx)\n", - handle, - (unsigned long long)sas_address); - _scsih_mark_responding_expander(ioc, sas_address, handle); - } - - out: - pr_info(MPT3SAS_FMT "search for expanders: complete\n", ioc->name); -} - -/** - * _scsih_remove_unresponding_sas_devices - removing unresponding devices - * @ioc: per adapter object - * - * Return nothing. - */ -static void -_scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc) -{ - struct _sas_device *sas_device, *sas_device_next; - struct _sas_node *sas_expander, *sas_expander_next; - struct _raid_device *raid_device, *raid_device_next; - struct list_head tmp_list; - unsigned long flags; - - pr_info(MPT3SAS_FMT "removing unresponding devices: start\n", - ioc->name); - - /* removing unresponding end devices */ - pr_info(MPT3SAS_FMT "removing unresponding devices: end-devices\n", - ioc->name); - list_for_each_entry_safe(sas_device, sas_device_next, - &ioc->sas_device_list, list) { - if (!sas_device->responding) - mpt3sas_device_remove_by_sas_address(ioc, - sas_device->sas_address); - else - sas_device->responding = 0; - } - - /* removing unresponding volumes */ - if (ioc->ir_firmware) { - pr_info(MPT3SAS_FMT "removing unresponding devices: volumes\n", - ioc->name); - list_for_each_entry_safe(raid_device, raid_device_next, - &ioc->raid_device_list, list) { - if (!raid_device->responding) - _scsih_sas_volume_delete(ioc, - raid_device->handle); - else - raid_device->responding = 0; - } - } - - /* removing unresponding expanders */ - pr_info(MPT3SAS_FMT "removing unresponding devices: expanders\n", - ioc->name); - spin_lock_irqsave(&ioc->sas_node_lock, flags); - INIT_LIST_HEAD(&tmp_list); - list_for_each_entry_safe(sas_expander, sas_expander_next, - &ioc->sas_expander_list, list) { - if (!sas_expander->responding) - list_move_tail(&sas_expander->list, &tmp_list); - else - sas_expander->responding = 0; - } - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list, - list) { - list_del(&sas_expander->list); - _scsih_expander_node_remove(ioc, sas_expander); - } - - pr_info(MPT3SAS_FMT "removing unresponding devices: complete\n", - ioc->name); - - /* unblock devices */ - _scsih_ublock_io_all_device(ioc); -} - -static void -_scsih_refresh_expander_links(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_expander, u16 handle) -{ - Mpi2ExpanderPage1_t expander_pg1; - Mpi2ConfigReply_t mpi_reply; - int i; - - for (i = 0 ; i < sas_expander->num_phys ; i++) { - if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply, - &expander_pg1, i, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - mpt3sas_transport_update_links(ioc, sas_expander->sas_address, - le16_to_cpu(expander_pg1.AttachedDevHandle), i, - expander_pg1.NegotiatedLinkRate >> 4); - } -} - -/** - * _scsih_scan_for_devices_after_reset - scan for devices after host reset - * @ioc: per adapter object - * - * Return nothing. - */ -static void -_scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2ExpanderPage0_t expander_pg0; - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2RaidVolPage1_t volume_pg1; - Mpi2RaidVolPage0_t volume_pg0; - Mpi2RaidPhysDiskPage0_t pd_pg0; - Mpi2EventIrConfigElement_t element; - Mpi2ConfigReply_t mpi_reply; - u8 phys_disk_num; - u16 ioc_status; - u16 handle, parent_handle; - u64 sas_address; - struct _sas_device *sas_device; - struct _sas_node *expander_device; - static struct _raid_device *raid_device; - u8 retry_count; - unsigned long flags; - - pr_info(MPT3SAS_FMT "scan devices: start\n", ioc->name); - - _scsih_sas_host_refresh(ioc); - - pr_info(MPT3SAS_FMT "\tscan devices: expanders start\n", ioc->name); - - /* expanders */ - handle = 0xFFFF; - while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, - MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_info(MPT3SAS_FMT "\tbreak from expander scan: " \ - "ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, ioc_status, - le32_to_cpu(mpi_reply.IOCLogInfo)); - break; - } - handle = le16_to_cpu(expander_pg0.DevHandle); - spin_lock_irqsave(&ioc->sas_node_lock, flags); - expander_device = mpt3sas_scsih_expander_find_by_sas_address( - ioc, le64_to_cpu(expander_pg0.SASAddress)); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - if (expander_device) - _scsih_refresh_expander_links(ioc, expander_device, - handle); - else { - pr_info(MPT3SAS_FMT "\tBEFORE adding expander: " \ - "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name, - handle, (unsigned long long) - le64_to_cpu(expander_pg0.SASAddress)); - _scsih_expander_add(ioc, handle); - pr_info(MPT3SAS_FMT "\tAFTER adding expander: " \ - "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name, - handle, (unsigned long long) - le64_to_cpu(expander_pg0.SASAddress)); - } - } - - pr_info(MPT3SAS_FMT "\tscan devices: expanders complete\n", - ioc->name); - - if (!ioc->ir_firmware) - goto skip_to_sas; - - pr_info(MPT3SAS_FMT "\tscan devices: phys disk start\n", ioc->name); - - /* phys disk */ - phys_disk_num = 0xFF; - while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply, - &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM, - phys_disk_num))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_info(MPT3SAS_FMT "\tbreak from phys disk scan: "\ - "ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, ioc_status, - le32_to_cpu(mpi_reply.IOCLogInfo)); - break; - } - phys_disk_num = pd_pg0.PhysDiskNum; - handle = le16_to_cpu(pd_pg0.DevHandle); - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _scsih_sas_device_find_by_handle(ioc, handle); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (sas_device) - continue; - if (mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, - &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, - handle) != 0) - continue; - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_info(MPT3SAS_FMT "\tbreak from phys disk scan " \ - "ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, ioc_status, - le32_to_cpu(mpi_reply.IOCLogInfo)); - break; - } - parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); - if (!_scsih_get_sas_address(ioc, parent_handle, - &sas_address)) { - pr_info(MPT3SAS_FMT "\tBEFORE adding phys disk: " \ - " handle (0x%04x), sas_addr(0x%016llx)\n", - ioc->name, handle, (unsigned long long) - le64_to_cpu(sas_device_pg0.SASAddress)); - mpt3sas_transport_update_links(ioc, sas_address, - handle, sas_device_pg0.PhyNum, - MPI2_SAS_NEG_LINK_RATE_1_5); - set_bit(handle, ioc->pd_handles); - retry_count = 0; - /* This will retry adding the end device. - * _scsih_add_device() will decide on retries and - * return "1" when it should be retried - */ - while (_scsih_add_device(ioc, handle, retry_count++, - 1)) { - ssleep(1); - } - pr_info(MPT3SAS_FMT "\tAFTER adding phys disk: " \ - " handle (0x%04x), sas_addr(0x%016llx)\n", - ioc->name, handle, (unsigned long long) - le64_to_cpu(sas_device_pg0.SASAddress)); - } - } - - pr_info(MPT3SAS_FMT "\tscan devices: phys disk complete\n", - ioc->name); - - pr_info(MPT3SAS_FMT "\tscan devices: volumes start\n", ioc->name); - - /* volumes */ - handle = 0xFFFF; - while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, - &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \ - "ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, ioc_status, - le32_to_cpu(mpi_reply.IOCLogInfo)); - break; - } - handle = le16_to_cpu(volume_pg1.DevHandle); - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_wwid(ioc, - le64_to_cpu(volume_pg1.WWID)); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - if (raid_device) - continue; - if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, - &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, - sizeof(Mpi2RaidVolPage0_t))) - continue; - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \ - "ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, ioc_status, - le32_to_cpu(mpi_reply.IOCLogInfo)); - break; - } - if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL || - volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE || - volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) { - memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t)); - element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED; - element.VolDevHandle = volume_pg1.DevHandle; - pr_info(MPT3SAS_FMT - "\tBEFORE adding volume: handle (0x%04x)\n", - ioc->name, volume_pg1.DevHandle); - _scsih_sas_volume_add(ioc, &element); - pr_info(MPT3SAS_FMT - "\tAFTER adding volume: handle (0x%04x)\n", - ioc->name, volume_pg1.DevHandle); - } - } - - pr_info(MPT3SAS_FMT "\tscan devices: volumes complete\n", - ioc->name); - - skip_to_sas: - - pr_info(MPT3SAS_FMT "\tscan devices: end devices start\n", - ioc->name); - - /* sas devices */ - handle = 0xFFFF; - while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, - &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, - handle))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_info(MPT3SAS_FMT "\tbreak from end device scan:"\ - " ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, ioc_status, - le32_to_cpu(mpi_reply.IOCLogInfo)); - break; - } - handle = le16_to_cpu(sas_device_pg0.DevHandle); - if (!(_scsih_is_end_device( - le32_to_cpu(sas_device_pg0.DeviceInfo)))) - continue; - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - le64_to_cpu(sas_device_pg0.SASAddress)); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (sas_device) - continue; - parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); - if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) { - pr_info(MPT3SAS_FMT "\tBEFORE adding end device: " \ - "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name, - handle, (unsigned long long) - le64_to_cpu(sas_device_pg0.SASAddress)); - mpt3sas_transport_update_links(ioc, sas_address, handle, - sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); - retry_count = 0; - /* This will retry adding the end device. - * _scsih_add_device() will decide on retries and - * return "1" when it should be retried - */ - while (_scsih_add_device(ioc, handle, retry_count++, - 0)) { - ssleep(1); - } - pr_info(MPT3SAS_FMT "\tAFTER adding end device: " \ - "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name, - handle, (unsigned long long) - le64_to_cpu(sas_device_pg0.SASAddress)); - } - } - pr_info(MPT3SAS_FMT "\tscan devices: end devices complete\n", - ioc->name); - - pr_info(MPT3SAS_FMT "scan devices: complete\n", ioc->name); -} -/** - * mpt3sas_scsih_reset_handler - reset callback handler (for scsih) - * @ioc: per adapter object - * @reset_phase: phase - * - * The handler for doing any required cleanup or initialization. - * - * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET, - * MPT3_IOC_DONE_RESET - * - * Return nothing. - */ -void -mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase) -{ - switch (reset_phase) { - case MPT3_IOC_PRE_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__)); - break; - case MPT3_IOC_AFTER_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__)); - if (ioc->scsih_cmds.status & MPT3_CMD_PENDING) { - ioc->scsih_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->scsih_cmds.smid); - complete(&ioc->scsih_cmds.done); - } - if (ioc->tm_cmds.status & MPT3_CMD_PENDING) { - ioc->tm_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->tm_cmds.smid); - complete(&ioc->tm_cmds.done); - } - - _scsih_fw_event_cleanup_queue(ioc); - _scsih_flush_running_cmds(ioc); - break; - case MPT3_IOC_DONE_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__)); - if ((!ioc->is_driver_loading) && !(disable_discovery > 0 && - !ioc->sas_hba.num_phys)) { - _scsih_prep_device_scan(ioc); - _scsih_search_responding_sas_devices(ioc); - _scsih_search_responding_raid_devices(ioc); - _scsih_search_responding_expanders(ioc); - _scsih_error_recovery_delete_devices(ioc); - } - break; - } -} - -/** - * _mpt3sas_fw_work - delayed task for processing firmware events - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) -{ - /* the queue is being flushed so ignore this event */ - if (ioc->remove_host || fw_event->cancel_pending_work || - ioc->pci_error_recovery) { - _scsih_fw_event_free(ioc, fw_event); - return; - } - - switch (fw_event->event) { - case MPT3SAS_PROCESS_TRIGGER_DIAG: - mpt3sas_process_trigger_data(ioc, fw_event->event_data); - break; - case MPT3SAS_REMOVE_UNRESPONDING_DEVICES: - while (scsi_host_in_recovery(ioc->shost) || ioc->shost_recovery) - ssleep(1); - _scsih_remove_unresponding_sas_devices(ioc); - _scsih_scan_for_devices_after_reset(ioc); - break; - case MPT3SAS_PORT_ENABLE_COMPLETE: - ioc->start_scan = 0; - if (missing_delay[0] != -1 && missing_delay[1] != -1) - mpt3sas_base_update_missing_delay(ioc, missing_delay[0], - missing_delay[1]); - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "port enable: complete from worker thread\n", - ioc->name)); - break; - case MPT3SAS_TURN_ON_FAULT_LED: - _scsih_turn_on_fault_led(ioc, fw_event->device_handle); - break; - case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: - _scsih_sas_topology_change_event(ioc, fw_event); - break; - case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: - _scsih_sas_device_status_change_event(ioc, fw_event); - break; - case MPI2_EVENT_SAS_DISCOVERY: - _scsih_sas_discovery_event(ioc, fw_event); - break; - case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: - _scsih_sas_broadcast_primitive_event(ioc, fw_event); - break; - case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: - _scsih_sas_enclosure_dev_status_change_event(ioc, - fw_event); - break; - case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: - _scsih_sas_ir_config_change_event(ioc, fw_event); - break; - case MPI2_EVENT_IR_VOLUME: - _scsih_sas_ir_volume_event(ioc, fw_event); - break; - case MPI2_EVENT_IR_PHYSICAL_DISK: - _scsih_sas_ir_physical_disk_event(ioc, fw_event); - break; - case MPI2_EVENT_IR_OPERATION_STATUS: - _scsih_sas_ir_operation_status_event(ioc, fw_event); - break; - } - _scsih_fw_event_free(ioc, fw_event); -} - -/** - * _firmware_event_work - * @ioc: per adapter object - * @work: The fw_event_work object - * Context: user. - * - * wrappers for the work thread handling firmware events - * - * Return nothing. - */ - -static void -_firmware_event_work(struct work_struct *work) -{ - struct fw_event_work *fw_event = container_of(work, - struct fw_event_work, work); - - _mpt3sas_fw_work(fw_event->ioc, fw_event); -} - -/** - * mpt3sas_scsih_event_callback - firmware event handler (called at ISR time) - * @ioc: per adapter object - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: interrupt. - * - * This function merely adds a new work task into ioc->firmware_event_thread. - * The tasks are worked from _firmware_event_work in user context. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, - u32 reply) -{ - struct fw_event_work *fw_event; - Mpi2EventNotificationReply_t *mpi_reply; - u16 event; - u16 sz; - - /* events turned off due to host reset or driver unloading */ - if (ioc->remove_host || ioc->pci_error_recovery) - return 1; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - - if (unlikely(!mpi_reply)) { - pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return 1; - } - - event = le16_to_cpu(mpi_reply->Event); - - if (event != MPI2_EVENT_LOG_ENTRY_ADDED) - mpt3sas_trigger_event(ioc, event, 0); - - switch (event) { - /* handle these */ - case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: - { - Mpi2EventDataSasBroadcastPrimitive_t *baen_data = - (Mpi2EventDataSasBroadcastPrimitive_t *) - mpi_reply->EventData; - - if (baen_data->Primitive != - MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT) - return 1; - - if (ioc->broadcast_aen_busy) { - ioc->broadcast_aen_pending++; - return 1; - } else - ioc->broadcast_aen_busy = 1; - break; - } - - case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: - _scsih_check_topo_delete_events(ioc, - (Mpi2EventDataSasTopologyChangeList_t *) - mpi_reply->EventData); - break; - case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: - _scsih_check_ir_config_unhide_events(ioc, - (Mpi2EventDataIrConfigChangeList_t *) - mpi_reply->EventData); - break; - case MPI2_EVENT_IR_VOLUME: - _scsih_check_volume_delete_events(ioc, - (Mpi2EventDataIrVolume_t *) - mpi_reply->EventData); - break; - - case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: - case MPI2_EVENT_IR_OPERATION_STATUS: - case MPI2_EVENT_SAS_DISCOVERY: - case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: - case MPI2_EVENT_IR_PHYSICAL_DISK: - break; - - default: /* ignore the rest */ - return 1; - } - - fw_event = kzalloc(sizeof(struct fw_event_work), GFP_ATOMIC); - if (!fw_event) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return 1; - } - sz = le16_to_cpu(mpi_reply->EventDataLength) * 4; - fw_event->event_data = kzalloc(sz, GFP_ATOMIC); - if (!fw_event->event_data) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - kfree(fw_event); - return 1; - } - - memcpy(fw_event->event_data, mpi_reply->EventData, sz); - fw_event->ioc = ioc; - fw_event->VF_ID = mpi_reply->VF_ID; - fw_event->VP_ID = mpi_reply->VP_ID; - fw_event->event = event; - _scsih_fw_event_add(ioc, fw_event); - return 1; -} - -/* shost template */ -static struct scsi_host_template scsih_driver_template = { - .module = THIS_MODULE, - .name = "Fusion MPT SAS Host", - .proc_name = MPT3SAS_DRIVER_NAME, - .queuecommand = _scsih_qcmd, - .target_alloc = _scsih_target_alloc, - .slave_alloc = _scsih_slave_alloc, - .slave_configure = _scsih_slave_configure, - .target_destroy = _scsih_target_destroy, - .slave_destroy = _scsih_slave_destroy, - .scan_finished = _scsih_scan_finished, - .scan_start = _scsih_scan_start, - .change_queue_depth = _scsih_change_queue_depth, - .change_queue_type = _scsih_change_queue_type, - .eh_abort_handler = _scsih_abort, - .eh_device_reset_handler = _scsih_dev_reset, - .eh_target_reset_handler = _scsih_target_reset, - .eh_host_reset_handler = _scsih_host_reset, - .bios_param = _scsih_bios_param, - .can_queue = 1, - .this_id = -1, - .sg_tablesize = MPT3SAS_SG_DEPTH, - .max_sectors = 32767, - .cmd_per_lun = 7, - .use_clustering = ENABLE_CLUSTERING, - .shost_attrs = mpt3sas_host_attrs, - .sdev_attrs = mpt3sas_dev_attrs, -}; - -/** - * _scsih_expander_node_remove - removing expander device from list. - * @ioc: per adapter object - * @sas_expander: the sas_device object - * Context: Calling function should acquire ioc->sas_node_lock. - * - * Removing object and freeing associated memory from the - * ioc->sas_expander_list. - * - * Return nothing. - */ -static void -_scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_expander) -{ - struct _sas_port *mpt3sas_port, *next; - - /* remove sibling ports attached to this expander */ - list_for_each_entry_safe(mpt3sas_port, next, - &sas_expander->sas_port_list, port_list) { - if (ioc->shost_recovery) - return; - if (mpt3sas_port->remote_identify.device_type == - SAS_END_DEVICE) - mpt3sas_device_remove_by_sas_address(ioc, - mpt3sas_port->remote_identify.sas_address); - else if (mpt3sas_port->remote_identify.device_type == - SAS_EDGE_EXPANDER_DEVICE || - mpt3sas_port->remote_identify.device_type == - SAS_FANOUT_EXPANDER_DEVICE) - mpt3sas_expander_remove(ioc, - mpt3sas_port->remote_identify.sas_address); - } - - mpt3sas_transport_port_remove(ioc, sas_expander->sas_address, - sas_expander->sas_address_parent); - - pr_info(MPT3SAS_FMT - "expander_remove: handle(0x%04x), sas_addr(0x%016llx)\n", - ioc->name, - sas_expander->handle, (unsigned long long) - sas_expander->sas_address); - - kfree(sas_expander->phy); - kfree(sas_expander); -} - -/** - * _scsih_ir_shutdown - IR shutdown notification - * @ioc: per adapter object - * - * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that - * the host system is shutting down. - * - * Return nothing. - */ -static void -_scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2RaidActionRequest_t *mpi_request; - Mpi2RaidActionReply_t *mpi_reply; - u16 smid; - - /* is IR firmware build loaded ? */ - if (!ioc->ir_firmware) - return; - - /* are there any volumes ? */ - if (list_empty(&ioc->raid_device_list)) - return; - - mutex_lock(&ioc->scsih_cmds.mutex); - - if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n", - ioc->name, __func__); - goto out; - } - ioc->scsih_cmds.status = MPT3_CMD_PENDING; - - smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; - goto out; - } - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->scsih_cmds.smid = smid; - memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t)); - - mpi_request->Function = MPI2_FUNCTION_RAID_ACTION; - mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; - - pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name); - init_completion(&ioc->scsih_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); - - if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - goto out; - } - - if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) { - mpi_reply = ioc->scsih_cmds.reply; - pr_info(MPT3SAS_FMT - "IR shutdown (complete): ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo)); - } - - out: - ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; - mutex_unlock(&ioc->scsih_cmds.mutex); -} - -/** - * _scsih_remove - detach and remove add host - * @pdev: PCI device struct - * - * Routine called when unloading the driver. - * Return nothing. - */ -static void _scsih_remove(struct pci_dev *pdev) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - struct _sas_port *mpt3sas_port, *next_port; - struct _raid_device *raid_device, *next; - struct MPT3SAS_TARGET *sas_target_priv_data; - struct workqueue_struct *wq; - unsigned long flags; - - ioc->remove_host = 1; - _scsih_fw_event_cleanup_queue(ioc); - - spin_lock_irqsave(&ioc->fw_event_lock, flags); - wq = ioc->firmware_event_thread; - ioc->firmware_event_thread = NULL; - spin_unlock_irqrestore(&ioc->fw_event_lock, flags); - if (wq) - destroy_workqueue(wq); - - /* release all the volumes */ - _scsih_ir_shutdown(ioc); - list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list, - list) { - if (raid_device->starget) { - sas_target_priv_data = - raid_device->starget->hostdata; - sas_target_priv_data->deleted = 1; - scsi_remove_target(&raid_device->starget->dev); - } - pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n", - ioc->name, raid_device->handle, - (unsigned long long) raid_device->wwid); - _scsih_raid_device_remove(ioc, raid_device); - } - - /* free ports attached to the sas_host */ - list_for_each_entry_safe(mpt3sas_port, next_port, - &ioc->sas_hba.sas_port_list, port_list) { - if (mpt3sas_port->remote_identify.device_type == - SAS_END_DEVICE) - mpt3sas_device_remove_by_sas_address(ioc, - mpt3sas_port->remote_identify.sas_address); - else if (mpt3sas_port->remote_identify.device_type == - SAS_EDGE_EXPANDER_DEVICE || - mpt3sas_port->remote_identify.device_type == - SAS_FANOUT_EXPANDER_DEVICE) - mpt3sas_expander_remove(ioc, - mpt3sas_port->remote_identify.sas_address); - } - - /* free phys attached to the sas_host */ - if (ioc->sas_hba.num_phys) { - kfree(ioc->sas_hba.phy); - ioc->sas_hba.phy = NULL; - ioc->sas_hba.num_phys = 0; - } - - sas_remove_host(shost); - mpt3sas_base_detach(ioc); - list_del(&ioc->list); - scsi_remove_host(shost); - scsi_host_put(shost); -} - -/** - * _scsih_shutdown - routine call during system shutdown - * @pdev: PCI device struct - * - * Return nothing. - */ -static void -_scsih_shutdown(struct pci_dev *pdev) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - struct workqueue_struct *wq; - unsigned long flags; - - ioc->remove_host = 1; - _scsih_fw_event_cleanup_queue(ioc); - - spin_lock_irqsave(&ioc->fw_event_lock, flags); - wq = ioc->firmware_event_thread; - ioc->firmware_event_thread = NULL; - spin_unlock_irqrestore(&ioc->fw_event_lock, flags); - if (wq) - destroy_workqueue(wq); - - _scsih_ir_shutdown(ioc); - mpt3sas_base_detach(ioc); -} - - -/** - * _scsih_probe_boot_devices - reports 1st device - * @ioc: per adapter object - * - * If specified in bios page 2, this routine reports the 1st - * device scsi-ml or sas transport for persistent boot device - * purposes. Please refer to function _scsih_determine_boot_device() - */ -static void -_scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc) -{ - u8 is_raid; - void *device; - struct _sas_device *sas_device; - struct _raid_device *raid_device; - u16 handle; - u64 sas_address_parent; - u64 sas_address; - unsigned long flags; - int rc; - - /* no Bios, return immediately */ - if (!ioc->bios_pg3.BiosVersion) - return; - - device = NULL; - is_raid = 0; - if (ioc->req_boot_device.device) { - device = ioc->req_boot_device.device; - is_raid = ioc->req_boot_device.is_raid; - } else if (ioc->req_alt_boot_device.device) { - device = ioc->req_alt_boot_device.device; - is_raid = ioc->req_alt_boot_device.is_raid; - } else if (ioc->current_boot_device.device) { - device = ioc->current_boot_device.device; - is_raid = ioc->current_boot_device.is_raid; - } - - if (!device) - return; - - if (is_raid) { - raid_device = device; - rc = scsi_add_device(ioc->shost, RAID_CHANNEL, - raid_device->id, 0); - if (rc) - _scsih_raid_device_remove(ioc, raid_device); - } else { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = device; - handle = sas_device->handle; - sas_address_parent = sas_device->sas_address_parent; - sas_address = sas_device->sas_address; - list_move_tail(&sas_device->list, &ioc->sas_device_list); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - if (!mpt3sas_transport_port_add(ioc, handle, - sas_address_parent)) { - _scsih_sas_device_remove(ioc, sas_device); - } else if (!sas_device->starget) { - if (!ioc->is_driver_loading) - mpt3sas_transport_port_remove(ioc, sas_address, - sas_address_parent); - _scsih_sas_device_remove(ioc, sas_device); - } - } -} - -/** - * _scsih_probe_raid - reporting raid volumes to scsi-ml - * @ioc: per adapter object - * - * Called during initial loading of the driver. - */ -static void -_scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc) -{ - struct _raid_device *raid_device, *raid_next; - int rc; - - list_for_each_entry_safe(raid_device, raid_next, - &ioc->raid_device_list, list) { - if (raid_device->starget) - continue; - rc = scsi_add_device(ioc->shost, RAID_CHANNEL, - raid_device->id, 0); - if (rc) - _scsih_raid_device_remove(ioc, raid_device); - } -} - -/** - * _scsih_probe_sas - reporting sas devices to sas transport - * @ioc: per adapter object - * - * Called during initial loading of the driver. - */ -static void -_scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc) -{ - struct _sas_device *sas_device, *next; - unsigned long flags; - - /* SAS Device List */ - list_for_each_entry_safe(sas_device, next, &ioc->sas_device_init_list, - list) { - - if (!mpt3sas_transport_port_add(ioc, sas_device->handle, - sas_device->sas_address_parent)) { - list_del(&sas_device->list); - kfree(sas_device); - continue; - } else if (!sas_device->starget) { - /* - * When asyn scanning is enabled, its not possible to - * remove devices while scanning is turned on due to an - * oops in scsi_sysfs_add_sdev()->add_device()-> - * sysfs_addrm_start() - */ - if (!ioc->is_driver_loading) - mpt3sas_transport_port_remove(ioc, - sas_device->sas_address, - sas_device->sas_address_parent); - list_del(&sas_device->list); - kfree(sas_device); - continue; - } - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - list_move_tail(&sas_device->list, &ioc->sas_device_list); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - } -} - -/** - * _scsih_probe_devices - probing for devices - * @ioc: per adapter object - * - * Called during initial loading of the driver. - */ -static void -_scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc) -{ - u16 volume_mapping_flags; - - if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR)) - return; /* return when IOC doesn't support initiator mode */ - - _scsih_probe_boot_devices(ioc); - - if (ioc->ir_firmware) { - volume_mapping_flags = - le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) & - MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; - if (volume_mapping_flags == - MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) { - _scsih_probe_raid(ioc); - _scsih_probe_sas(ioc); - } else { - _scsih_probe_sas(ioc); - _scsih_probe_raid(ioc); - } - } else - _scsih_probe_sas(ioc); -} - -/** - * _scsih_scan_start - scsi lld callback for .scan_start - * @shost: SCSI host pointer - * - * The shost has the ability to discover targets on its own instead - * of scanning the entire bus. In our implemention, we will kick off - * firmware discovery. - */ -static void -_scsih_scan_start(struct Scsi_Host *shost) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - int rc; - if (diag_buffer_enable != -1 && diag_buffer_enable != 0) - mpt3sas_enable_diag_buffer(ioc, diag_buffer_enable); - - if (disable_discovery > 0) - return; - - ioc->start_scan = 1; - rc = mpt3sas_port_enable(ioc); - - if (rc != 0) - pr_info(MPT3SAS_FMT "port enable: FAILED\n", ioc->name); -} - -/** - * _scsih_scan_finished - scsi lld callback for .scan_finished - * @shost: SCSI host pointer - * @time: elapsed time of the scan in jiffies - * - * This function will be called periodicallyn until it returns 1 with the - * scsi_host and the elapsed time of the scan in jiffies. In our implemention, - * we wait for firmware discovery to complete, then return 1. - */ -static int -_scsih_scan_finished(struct Scsi_Host *shost, unsigned long time) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - if (disable_discovery > 0) { - ioc->is_driver_loading = 0; - ioc->wait_for_discovery_to_complete = 0; - return 1; - } - - if (time >= (300 * HZ)) { - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - pr_info(MPT3SAS_FMT - "port enable: FAILED with timeout (timeout=300s)\n", - ioc->name); - ioc->is_driver_loading = 0; - return 1; - } - - if (ioc->start_scan) - return 0; - - if (ioc->start_scan_failed) { - pr_info(MPT3SAS_FMT - "port enable: FAILED with (ioc_status=0x%08x)\n", - ioc->name, ioc->start_scan_failed); - ioc->is_driver_loading = 0; - ioc->wait_for_discovery_to_complete = 0; - ioc->remove_host = 1; - return 1; - } - - pr_info(MPT3SAS_FMT "port enable: SUCCESS\n", ioc->name); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - - if (ioc->wait_for_discovery_to_complete) { - ioc->wait_for_discovery_to_complete = 0; - _scsih_probe_devices(ioc); - } - mpt3sas_base_start_watchdog(ioc); - ioc->is_driver_loading = 0; - return 1; -} - -/** - * _scsih_probe - attach and add scsi host - * @pdev: PCI device struct - * @id: pci device id - * - * Returns 0 success, anything else error. - */ -static int -_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - struct MPT3SAS_ADAPTER *ioc; - struct Scsi_Host *shost; - - shost = scsi_host_alloc(&scsih_driver_template, - sizeof(struct MPT3SAS_ADAPTER)); - if (!shost) - return -ENODEV; - - /* init local params */ - ioc = shost_priv(shost); - memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER)); - INIT_LIST_HEAD(&ioc->list); - list_add_tail(&ioc->list, &mpt3sas_ioc_list); - ioc->shost = shost; - ioc->id = mpt_ids++; - sprintf(ioc->name, "%s%d", MPT3SAS_DRIVER_NAME, ioc->id); - ioc->pdev = pdev; - ioc->scsi_io_cb_idx = scsi_io_cb_idx; - ioc->tm_cb_idx = tm_cb_idx; - ioc->ctl_cb_idx = ctl_cb_idx; - ioc->base_cb_idx = base_cb_idx; - ioc->port_enable_cb_idx = port_enable_cb_idx; - ioc->transport_cb_idx = transport_cb_idx; - ioc->scsih_cb_idx = scsih_cb_idx; - ioc->config_cb_idx = config_cb_idx; - ioc->tm_tr_cb_idx = tm_tr_cb_idx; - ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx; - ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; - ioc->logging_level = logging_level; - ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds; - /* misc semaphores and spin locks */ - mutex_init(&ioc->reset_in_progress_mutex); - spin_lock_init(&ioc->ioc_reset_in_progress_lock); - spin_lock_init(&ioc->scsi_lookup_lock); - spin_lock_init(&ioc->sas_device_lock); - spin_lock_init(&ioc->sas_node_lock); - spin_lock_init(&ioc->fw_event_lock); - spin_lock_init(&ioc->raid_device_lock); - spin_lock_init(&ioc->diag_trigger_lock); - - INIT_LIST_HEAD(&ioc->sas_device_list); - INIT_LIST_HEAD(&ioc->sas_device_init_list); - INIT_LIST_HEAD(&ioc->sas_expander_list); - INIT_LIST_HEAD(&ioc->fw_event_list); - INIT_LIST_HEAD(&ioc->raid_device_list); - INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); - INIT_LIST_HEAD(&ioc->delayed_tr_list); - INIT_LIST_HEAD(&ioc->delayed_tr_volume_list); - - /* init shost parameters */ - shost->max_cmd_len = 32; - shost->max_lun = max_lun; - shost->transportt = mpt3sas_transport_template; - shost->unique_id = ioc->id; - - if (max_sectors != 0xFFFF) { - if (max_sectors < 64) { - shost->max_sectors = 64; - pr_warn(MPT3SAS_FMT "Invalid value %d passed " \ - "for max_sectors, range is 64 to 32767. Assigning " - "value of 64.\n", ioc->name, max_sectors); - } else if (max_sectors > 32767) { - shost->max_sectors = 32767; - pr_warn(MPT3SAS_FMT "Invalid value %d passed " \ - "for max_sectors, range is 64 to 32767. Assigning " - "default value of 32767.\n", ioc->name, - max_sectors); - } else { - shost->max_sectors = max_sectors & 0xFFFE; - pr_info(MPT3SAS_FMT - "The max_sectors value is set to %d\n", - ioc->name, shost->max_sectors); - } - } - - if ((scsi_add_host(shost, &pdev->dev))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - list_del(&ioc->list); - goto out_add_shost_fail; - } - - /* register EEDP capabilities with SCSI layer */ - if (prot_mask > 0) - scsi_host_set_prot(shost, prot_mask); - else - scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION - | SHOST_DIF_TYPE2_PROTECTION - | SHOST_DIF_TYPE3_PROTECTION); - - scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC); - - /* event thread */ - snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), - "fw_event%d", ioc->id); - ioc->firmware_event_thread = create_singlethread_workqueue( - ioc->firmware_event_name); - if (!ioc->firmware_event_thread) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out_thread_fail; - } - - ioc->is_driver_loading = 1; - if ((mpt3sas_base_attach(ioc))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out_attach_fail; - } - scsi_scan_host(shost); - return 0; - - out_attach_fail: - destroy_workqueue(ioc->firmware_event_thread); - out_thread_fail: - list_del(&ioc->list); - scsi_remove_host(shost); - out_add_shost_fail: - scsi_host_put(shost); - return -ENODEV; -} - -#ifdef CONFIG_PM -/** - * _scsih_suspend - power management suspend main entry point - * @pdev: PCI device struct - * @state: PM state change to (usually PCI_D3) - * - * Returns 0 success, anything else error. - */ -static int -_scsih_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - pci_power_t device_state; - - mpt3sas_base_stop_watchdog(ioc); - flush_scheduled_work(); - scsi_block_requests(shost); - device_state = pci_choose_state(pdev, state); - pr_info(MPT3SAS_FMT - "pdev=0x%p, slot=%s, entering operating state [D%d]\n", - ioc->name, pdev, pci_name(pdev), device_state); - - pci_save_state(pdev); - mpt3sas_base_free_resources(ioc); - pci_set_power_state(pdev, device_state); - return 0; -} - -/** - * _scsih_resume - power management resume main entry point - * @pdev: PCI device struct - * - * Returns 0 success, anything else error. - */ -static int -_scsih_resume(struct pci_dev *pdev) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - pci_power_t device_state = pdev->current_state; - int r; - - pr_info(MPT3SAS_FMT - "pdev=0x%p, slot=%s, previous operating state [D%d]\n", - ioc->name, pdev, pci_name(pdev), device_state); - - pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); - pci_restore_state(pdev); - ioc->pdev = pdev; - r = mpt3sas_base_map_resources(ioc); - if (r) - return r; - - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET); - scsi_unblock_requests(shost); - mpt3sas_base_start_watchdog(ioc); - return 0; -} -#endif /* CONFIG_PM */ - -/** - * _scsih_pci_error_detected - Called when a PCI error is detected. - * @pdev: PCI device struct - * @state: PCI channel state - * - * Description: Called when a PCI error is detected. - * - * Return value: - * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT - */ -static pci_ers_result_t -_scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - pr_info(MPT3SAS_FMT "PCI error: detected callback, state(%d)!!\n", - ioc->name, state); - - switch (state) { - case pci_channel_io_normal: - return PCI_ERS_RESULT_CAN_RECOVER; - case pci_channel_io_frozen: - /* Fatal error, prepare for slot reset */ - ioc->pci_error_recovery = 1; - scsi_block_requests(ioc->shost); - mpt3sas_base_stop_watchdog(ioc); - mpt3sas_base_free_resources(ioc); - return PCI_ERS_RESULT_NEED_RESET; - case pci_channel_io_perm_failure: - /* Permanent error, prepare for device removal */ - ioc->pci_error_recovery = 1; - mpt3sas_base_stop_watchdog(ioc); - _scsih_flush_running_cmds(ioc); - return PCI_ERS_RESULT_DISCONNECT; - } - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * _scsih_pci_slot_reset - Called when PCI slot has been reset. - * @pdev: PCI device struct - * - * Description: This routine is called by the pci error recovery - * code after the PCI slot has been reset, just before we - * should resume normal operations. - */ -static pci_ers_result_t -_scsih_pci_slot_reset(struct pci_dev *pdev) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - int rc; - - pr_info(MPT3SAS_FMT "PCI error: slot reset callback!!\n", - ioc->name); - - ioc->pci_error_recovery = 0; - ioc->pdev = pdev; - pci_restore_state(pdev); - rc = mpt3sas_base_map_resources(ioc); - if (rc) - return PCI_ERS_RESULT_DISCONNECT; - - rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - - pr_warn(MPT3SAS_FMT "hard reset: %s\n", ioc->name, - (rc == 0) ? "success" : "failed"); - - if (!rc) - return PCI_ERS_RESULT_RECOVERED; - else - return PCI_ERS_RESULT_DISCONNECT; -} - -/** - * _scsih_pci_resume() - resume normal ops after PCI reset - * @pdev: pointer to PCI device - * - * Called when the error recovery driver tells us that its - * OK to resume normal operation. Use completion to allow - * halted scsi ops to resume. - */ -static void -_scsih_pci_resume(struct pci_dev *pdev) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - pr_info(MPT3SAS_FMT "PCI error: resume callback!!\n", ioc->name); - - pci_cleanup_aer_uncorrect_error_status(pdev); - mpt3sas_base_start_watchdog(ioc); - scsi_unblock_requests(ioc->shost); -} - -/** - * _scsih_pci_mmio_enabled - Enable MMIO and dump debug registers - * @pdev: pointer to PCI device - */ -static pci_ers_result_t -_scsih_pci_mmio_enabled(struct pci_dev *pdev) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - pr_info(MPT3SAS_FMT "PCI error: mmio enabled callback!!\n", - ioc->name); - - /* TODO - dump whatever for debugging purposes */ - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/* raid transport support */ -static struct raid_function_template mpt3sas_raid_functions = { - .cookie = &scsih_driver_template, - .is_raid = _scsih_is_raid, - .get_resync = _scsih_get_resync, - .get_state = _scsih_get_state, -}; - -static struct pci_error_handlers _scsih_err_handler = { - .error_detected = _scsih_pci_error_detected, - .mmio_enabled = _scsih_pci_mmio_enabled, - .slot_reset = _scsih_pci_slot_reset, - .resume = _scsih_pci_resume, -}; - -static struct pci_driver scsih_driver = { - .name = MPT3SAS_DRIVER_NAME, - .id_table = scsih_pci_table, - .probe = _scsih_probe, - .remove = _scsih_remove, - .shutdown = _scsih_shutdown, - .err_handler = &_scsih_err_handler, -#ifdef CONFIG_PM - .suspend = _scsih_suspend, - .resume = _scsih_resume, -#endif -}; - - -/** - * _scsih_init - main entry point for this driver. - * - * Returns 0 success, anything else error. - */ -static int __init -_scsih_init(void) -{ - int error; - - mpt_ids = 0; - - pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME, - MPT3SAS_DRIVER_VERSION); - - mpt3sas_transport_template = - sas_attach_transport(&mpt3sas_transport_functions); - if (!mpt3sas_transport_template) - return -ENODEV; - -/* raid transport support */ - mpt3sas_raid_template = raid_class_attach(&mpt3sas_raid_functions); - if (!mpt3sas_raid_template) { - sas_release_transport(mpt3sas_transport_template); - return -ENODEV; - } - - mpt3sas_base_initialize_callback_handler(); - - /* queuecommand callback hander */ - scsi_io_cb_idx = mpt3sas_base_register_callback_handler(_scsih_io_done); - - /* task managment callback handler */ - tm_cb_idx = mpt3sas_base_register_callback_handler(_scsih_tm_done); - - /* base internal commands callback handler */ - base_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_base_done); - port_enable_cb_idx = mpt3sas_base_register_callback_handler( - mpt3sas_port_enable_done); - - /* transport internal commands callback handler */ - transport_cb_idx = mpt3sas_base_register_callback_handler( - mpt3sas_transport_done); - - /* scsih internal commands callback handler */ - scsih_cb_idx = mpt3sas_base_register_callback_handler(_scsih_done); - - /* configuration page API internal commands callback handler */ - config_cb_idx = mpt3sas_base_register_callback_handler( - mpt3sas_config_done); - - /* ctl module callback handler */ - ctl_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_ctl_done); - - tm_tr_cb_idx = mpt3sas_base_register_callback_handler( - _scsih_tm_tr_complete); - - tm_tr_volume_cb_idx = mpt3sas_base_register_callback_handler( - _scsih_tm_volume_tr_complete); - - tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler( - _scsih_sas_control_complete); - - mpt3sas_ctl_init(); - - error = pci_register_driver(&scsih_driver); - if (error) { - /* raid transport support */ - raid_class_release(mpt3sas_raid_template); - sas_release_transport(mpt3sas_transport_template); - } - - return error; -} - -/** - * _scsih_exit - exit point for this driver (when it is a module). - * - * Returns 0 success, anything else error. - */ -static void __exit -_scsih_exit(void) -{ - pr_info("mpt3sas version %s unloading\n", - MPT3SAS_DRIVER_VERSION); - - mpt3sas_ctl_exit(); - - pci_unregister_driver(&scsih_driver); - - - mpt3sas_base_release_callback_handler(scsi_io_cb_idx); - mpt3sas_base_release_callback_handler(tm_cb_idx); - mpt3sas_base_release_callback_handler(base_cb_idx); - mpt3sas_base_release_callback_handler(port_enable_cb_idx); - mpt3sas_base_release_callback_handler(transport_cb_idx); - mpt3sas_base_release_callback_handler(scsih_cb_idx); - mpt3sas_base_release_callback_handler(config_cb_idx); - mpt3sas_base_release_callback_handler(ctl_cb_idx); - - mpt3sas_base_release_callback_handler(tm_tr_cb_idx); - mpt3sas_base_release_callback_handler(tm_tr_volume_cb_idx); - mpt3sas_base_release_callback_handler(tm_sas_control_cb_idx); - -/* raid transport support */ - raid_class_release(mpt3sas_raid_template); - sas_release_transport(mpt3sas_transport_template); -} - -module_init(_scsih_init); -module_exit(_scsih_exit); diff --git a/addons/mpt3sas/src/3.10.108/mpt3sas_transport.c b/addons/mpt3sas/src/3.10.108/mpt3sas_transport.c deleted file mode 100644 index 87ca2b72..00000000 --- a/addons/mpt3sas/src/3.10.108/mpt3sas_transport.c +++ /dev/null @@ -1,2128 +0,0 @@ -/* - * SAS Transport Layer for MPT (Message Passing Technology) based controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_transport.c - * Copyright (C) 2012 LSI Corporation - * (mailto:DL-MPTFusionLinux@lsi.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "mpt3sas_base.h" - -/** - * _transport_sas_node_find_by_sas_address - sas node search - * @ioc: per adapter object - * @sas_address: sas address of expander or sas host - * Context: Calling function should acquire ioc->sas_node_lock. - * - * Search for either hba phys or expander device based on handle, then returns - * the sas_node object. - */ -static struct _sas_node * -_transport_sas_node_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) -{ - if (ioc->sas_hba.sas_address == sas_address) - return &ioc->sas_hba; - else - return mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address); -} - -/** - * _transport_convert_phy_link_rate - - * @link_rate: link rate returned from mpt firmware - * - * Convert link_rate from mpi fusion into sas_transport form. - */ -static enum sas_linkrate -_transport_convert_phy_link_rate(u8 link_rate) -{ - enum sas_linkrate rc; - - switch (link_rate) { - case MPI2_SAS_NEG_LINK_RATE_1_5: - rc = SAS_LINK_RATE_1_5_GBPS; - break; - case MPI2_SAS_NEG_LINK_RATE_3_0: - rc = SAS_LINK_RATE_3_0_GBPS; - break; - case MPI2_SAS_NEG_LINK_RATE_6_0: - rc = SAS_LINK_RATE_6_0_GBPS; - break; - case MPI25_SAS_NEG_LINK_RATE_12_0: - rc = SAS_LINK_RATE_12_0_GBPS; - break; - case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED: - rc = SAS_PHY_DISABLED; - break; - case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED: - rc = SAS_LINK_RATE_FAILED; - break; - case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR: - rc = SAS_SATA_PORT_SELECTOR; - break; - case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS: - rc = SAS_PHY_RESET_IN_PROGRESS; - break; - - default: - case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE: - case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE: - rc = SAS_LINK_RATE_UNKNOWN; - break; - } - return rc; -} - -/** - * _transport_set_identify - set identify for phys and end devices - * @ioc: per adapter object - * @handle: device handle - * @identify: sas identify info - * - * Populates sas identify info. - * - * Returns 0 for success, non-zero for failure. - */ -static int -_transport_set_identify(struct MPT3SAS_ADAPTER *ioc, u16 handle, - struct sas_identify *identify) -{ - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2ConfigReply_t mpi_reply; - u32 device_info; - u32 ioc_status; - - if (ioc->shost_recovery || ioc->pci_error_recovery) { - pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", - __func__, ioc->name); - return -EFAULT; - } - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -ENXIO; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT - "handle(0x%04x), ioc_status(0x%04x)\nfailure at %s:%d/%s()!\n", - ioc->name, handle, ioc_status, - __FILE__, __LINE__, __func__); - return -EIO; - } - - memset(identify, 0, sizeof(struct sas_identify)); - device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); - - /* sas_address */ - identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress); - - /* phy number of the parent device this device is linked to */ - identify->phy_identifier = sas_device_pg0.PhyNum; - - /* device_type */ - switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) { - case MPI2_SAS_DEVICE_INFO_NO_DEVICE: - identify->device_type = SAS_PHY_UNUSED; - break; - case MPI2_SAS_DEVICE_INFO_END_DEVICE: - identify->device_type = SAS_END_DEVICE; - break; - case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER: - identify->device_type = SAS_EDGE_EXPANDER_DEVICE; - break; - case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER: - identify->device_type = SAS_FANOUT_EXPANDER_DEVICE; - break; - } - - /* initiator_port_protocols */ - if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR) - identify->initiator_port_protocols |= SAS_PROTOCOL_SSP; - if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR) - identify->initiator_port_protocols |= SAS_PROTOCOL_STP; - if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR) - identify->initiator_port_protocols |= SAS_PROTOCOL_SMP; - if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST) - identify->initiator_port_protocols |= SAS_PROTOCOL_SATA; - - /* target_port_protocols */ - if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) - identify->target_port_protocols |= SAS_PROTOCOL_SSP; - if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) - identify->target_port_protocols |= SAS_PROTOCOL_STP; - if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) - identify->target_port_protocols |= SAS_PROTOCOL_SMP; - if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) - identify->target_port_protocols |= SAS_PROTOCOL_SATA; - - return 0; -} - -/** - * mpt3sas_transport_done - internal transport layer callback handler. - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Callback handler when sending internal generated transport cmds. - * The callback index passed is `ioc->transport_cb_idx` - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (ioc->transport_cmds.status == MPT3_CMD_NOT_USED) - return 1; - if (ioc->transport_cmds.smid != smid) - return 1; - ioc->transport_cmds.status |= MPT3_CMD_COMPLETE; - if (mpi_reply) { - memcpy(ioc->transport_cmds.reply, mpi_reply, - mpi_reply->MsgLength*4); - ioc->transport_cmds.status |= MPT3_CMD_REPLY_VALID; - } - ioc->transport_cmds.status &= ~MPT3_CMD_PENDING; - complete(&ioc->transport_cmds.done); - return 1; -} - -/* report manufacture request structure */ -struct rep_manu_request { - u8 smp_frame_type; - u8 function; - u8 reserved; - u8 request_length; -}; - -/* report manufacture reply structure */ -struct rep_manu_reply { - u8 smp_frame_type; /* 0x41 */ - u8 function; /* 0x01 */ - u8 function_result; - u8 response_length; - u16 expander_change_count; - u8 reserved0[2]; - u8 sas_format; - u8 reserved2[3]; - u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN]; - u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN]; - u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN]; - u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN]; - u16 component_id; - u8 component_revision_id; - u8 reserved3; - u8 vendor_specific[8]; -}; - -/** - * transport_expander_report_manufacture - obtain SMP report_manufacture - * @ioc: per adapter object - * @sas_address: expander sas address - * @edev: the sas_expander_device object - * - * Fills in the sas_expander_device object when SMP port is created. - * - * Returns 0 for success, non-zero for failure. - */ -static int -_transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address, struct sas_expander_device *edev) -{ - Mpi2SmpPassthroughRequest_t *mpi_request; - Mpi2SmpPassthroughReply_t *mpi_reply; - struct rep_manu_reply *manufacture_reply; - struct rep_manu_request *manufacture_request; - int rc; - u16 smid; - u32 ioc_state; - unsigned long timeleft; - void *psge; - u8 issue_reset = 0; - void *data_out = NULL; - dma_addr_t data_out_dma; - dma_addr_t data_in_dma; - size_t data_in_sz; - size_t data_out_sz; - u16 wait_state_count; - - if (ioc->shost_recovery || ioc->pci_error_recovery) { - pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", - __func__, ioc->name); - return -EFAULT; - } - - mutex_lock(&ioc->transport_cmds.mutex); - - if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - ioc->transport_cmds.status = MPT3_CMD_PENDING; - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, __func__, wait_state_count); - } - if (wait_state_count) - pr_info(MPT3SAS_FMT "%s: ioc is operational\n", - ioc->name, __func__); - - smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - rc = 0; - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->transport_cmds.smid = smid; - - data_out_sz = sizeof(struct rep_manu_request); - data_in_sz = sizeof(struct rep_manu_reply); - data_out = pci_alloc_consistent(ioc->pdev, data_out_sz + data_in_sz, - &data_out_dma); - - if (!data_out) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - rc = -ENOMEM; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - - data_in_dma = data_out_dma + sizeof(struct rep_manu_request); - - manufacture_request = data_out; - manufacture_request->smp_frame_type = 0x40; - manufacture_request->function = 1; - manufacture_request->reserved = 0; - manufacture_request->request_length = 0; - - memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; - mpi_request->PhysicalPort = 0xFF; - mpi_request->SASAddress = cpu_to_le64(sas_address); - mpi_request->RequestDataLength = cpu_to_le16(data_out_sz); - psge = &mpi_request->SGL; - - ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, - data_in_sz); - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "report_manufacture - send to sas_addr(0x%016llx)\n", - ioc->name, (unsigned long long)sas_address)); - init_completion(&ioc->transport_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, - 10*HZ); - - if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SmpPassthroughRequest_t)/4); - if (!(ioc->transport_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "report_manufacture - complete\n", ioc->name)); - - if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) { - u8 *tmp; - - mpi_reply = ioc->transport_cmds.reply; - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "report_manufacture - reply data transfer size(%d)\n", - ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength))); - - if (le16_to_cpu(mpi_reply->ResponseDataLength) != - sizeof(struct rep_manu_reply)) - goto out; - - manufacture_reply = data_out + sizeof(struct rep_manu_request); - strncpy(edev->vendor_id, manufacture_reply->vendor_id, - SAS_EXPANDER_VENDOR_ID_LEN); - strncpy(edev->product_id, manufacture_reply->product_id, - SAS_EXPANDER_PRODUCT_ID_LEN); - strncpy(edev->product_rev, manufacture_reply->product_rev, - SAS_EXPANDER_PRODUCT_REV_LEN); - edev->level = manufacture_reply->sas_format & 1; - if (edev->level) { - strncpy(edev->component_vendor_id, - manufacture_reply->component_vendor_id, - SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN); - tmp = (u8 *)&manufacture_reply->component_id; - edev->component_id = tmp[0] << 8 | tmp[1]; - edev->component_revision_id = - manufacture_reply->component_revision_id; - } - } else - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "report_manufacture - no reply\n", ioc->name)); - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - out: - ioc->transport_cmds.status = MPT3_CMD_NOT_USED; - if (data_out) - pci_free_consistent(ioc->pdev, data_out_sz + data_in_sz, - data_out, data_out_dma); - - mutex_unlock(&ioc->transport_cmds.mutex); - return rc; -} - - -/** - * _transport_delete_port - helper function to removing a port - * @ioc: per adapter object - * @mpt3sas_port: mpt3sas per port object - * - * Returns nothing. - */ -static void -_transport_delete_port(struct MPT3SAS_ADAPTER *ioc, - struct _sas_port *mpt3sas_port) -{ - u64 sas_address = mpt3sas_port->remote_identify.sas_address; - enum sas_device_type device_type = - mpt3sas_port->remote_identify.device_type; - - dev_printk(KERN_INFO, &mpt3sas_port->port->dev, - "remove: sas_addr(0x%016llx)\n", - (unsigned long long) sas_address); - - ioc->logging_level |= MPT_DEBUG_TRANSPORT; - if (device_type == SAS_END_DEVICE) - mpt3sas_device_remove_by_sas_address(ioc, sas_address); - else if (device_type == SAS_EDGE_EXPANDER_DEVICE || - device_type == SAS_FANOUT_EXPANDER_DEVICE) - mpt3sas_expander_remove(ioc, sas_address); - ioc->logging_level &= ~MPT_DEBUG_TRANSPORT; -} - -/** - * _transport_delete_phy - helper function to removing single phy from port - * @ioc: per adapter object - * @mpt3sas_port: mpt3sas per port object - * @mpt3sas_phy: mpt3sas per phy object - * - * Returns nothing. - */ -static void -_transport_delete_phy(struct MPT3SAS_ADAPTER *ioc, - struct _sas_port *mpt3sas_port, struct _sas_phy *mpt3sas_phy) -{ - u64 sas_address = mpt3sas_port->remote_identify.sas_address; - - dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev, - "remove: sas_addr(0x%016llx), phy(%d)\n", - (unsigned long long) sas_address, mpt3sas_phy->phy_id); - - list_del(&mpt3sas_phy->port_siblings); - mpt3sas_port->num_phys--; - sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy); - mpt3sas_phy->phy_belongs_to_port = 0; -} - -/** - * _transport_add_phy - helper function to adding single phy to port - * @ioc: per adapter object - * @mpt3sas_port: mpt3sas per port object - * @mpt3sas_phy: mpt3sas per phy object - * - * Returns nothing. - */ -static void -_transport_add_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_port *mpt3sas_port, - struct _sas_phy *mpt3sas_phy) -{ - u64 sas_address = mpt3sas_port->remote_identify.sas_address; - - dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev, - "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long) - sas_address, mpt3sas_phy->phy_id); - - list_add_tail(&mpt3sas_phy->port_siblings, &mpt3sas_port->phy_list); - mpt3sas_port->num_phys++; - sas_port_add_phy(mpt3sas_port->port, mpt3sas_phy->phy); - mpt3sas_phy->phy_belongs_to_port = 1; -} - -/** - * _transport_add_phy_to_an_existing_port - adding new phy to existing port - * @ioc: per adapter object - * @sas_node: sas node object (either expander or sas host) - * @mpt3sas_phy: mpt3sas per phy object - * @sas_address: sas address of device/expander were phy needs to be added to - * - * Returns nothing. - */ -static void -_transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy, - u64 sas_address) -{ - struct _sas_port *mpt3sas_port; - struct _sas_phy *phy_srch; - - if (mpt3sas_phy->phy_belongs_to_port == 1) - return; - - list_for_each_entry(mpt3sas_port, &sas_node->sas_port_list, - port_list) { - if (mpt3sas_port->remote_identify.sas_address != - sas_address) - continue; - list_for_each_entry(phy_srch, &mpt3sas_port->phy_list, - port_siblings) { - if (phy_srch == mpt3sas_phy) - return; - } - _transport_add_phy(ioc, mpt3sas_port, mpt3sas_phy); - return; - } - -} - -/** - * _transport_del_phy_from_an_existing_port - delete phy from existing port - * @ioc: per adapter object - * @sas_node: sas node object (either expander or sas host) - * @mpt3sas_phy: mpt3sas per phy object - * - * Returns nothing. - */ -static void -_transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy) -{ - struct _sas_port *mpt3sas_port, *next; - struct _sas_phy *phy_srch; - - if (mpt3sas_phy->phy_belongs_to_port == 0) - return; - - list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list, - port_list) { - list_for_each_entry(phy_srch, &mpt3sas_port->phy_list, - port_siblings) { - if (phy_srch != mpt3sas_phy) - continue; - - if (mpt3sas_port->num_phys == 1) - _transport_delete_port(ioc, mpt3sas_port); - else - _transport_delete_phy(ioc, mpt3sas_port, - mpt3sas_phy); - return; - } - } -} - -/** - * _transport_sanity_check - sanity check when adding a new port - * @ioc: per adapter object - * @sas_node: sas node object (either expander or sas host) - * @sas_address: sas address of device being added - * - * See the explanation above from _transport_delete_duplicate_port - */ -static void -_transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node, - u64 sas_address) -{ - int i; - - for (i = 0; i < sas_node->num_phys; i++) { - if (sas_node->phy[i].remote_identify.sas_address != sas_address) - continue; - if (sas_node->phy[i].phy_belongs_to_port == 1) - _transport_del_phy_from_an_existing_port(ioc, sas_node, - &sas_node->phy[i]); - } -} - -/** - * mpt3sas_transport_port_add - insert port to the list - * @ioc: per adapter object - * @handle: handle of attached device - * @sas_address: sas address of parent expander or sas host - * Context: This function will acquire ioc->sas_node_lock. - * - * Adding new port object to the sas_node->sas_port_list. - * - * Returns mpt3sas_port. - */ -struct _sas_port * -mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u64 sas_address) -{ - struct _sas_phy *mpt3sas_phy, *next; - struct _sas_port *mpt3sas_port; - unsigned long flags; - struct _sas_node *sas_node; - struct sas_rphy *rphy; - int i; - struct sas_port *port; - - mpt3sas_port = kzalloc(sizeof(struct _sas_port), - GFP_KERNEL); - if (!mpt3sas_port) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return NULL; - } - - INIT_LIST_HEAD(&mpt3sas_port->port_list); - INIT_LIST_HEAD(&mpt3sas_port->phy_list); - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - if (!sas_node) { - pr_err(MPT3SAS_FMT - "%s: Could not find parent sas_address(0x%016llx)!\n", - ioc->name, __func__, (unsigned long long)sas_address); - goto out_fail; - } - - if ((_transport_set_identify(ioc, handle, - &mpt3sas_port->remote_identify))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out_fail; - } - - if (mpt3sas_port->remote_identify.device_type == SAS_PHY_UNUSED) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out_fail; - } - - _transport_sanity_check(ioc, sas_node, - mpt3sas_port->remote_identify.sas_address); - - for (i = 0; i < sas_node->num_phys; i++) { - if (sas_node->phy[i].remote_identify.sas_address != - mpt3sas_port->remote_identify.sas_address) - continue; - list_add_tail(&sas_node->phy[i].port_siblings, - &mpt3sas_port->phy_list); - mpt3sas_port->num_phys++; - } - - if (!mpt3sas_port->num_phys) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out_fail; - } - - port = sas_port_alloc_num(sas_node->parent_dev); - if ((sas_port_add(port))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out_fail; - } - - list_for_each_entry(mpt3sas_phy, &mpt3sas_port->phy_list, - port_siblings) { - if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) - dev_printk(KERN_INFO, &port->dev, - "add: handle(0x%04x), sas_addr(0x%016llx), phy(%d)\n", - handle, (unsigned long long) - mpt3sas_port->remote_identify.sas_address, - mpt3sas_phy->phy_id); - sas_port_add_phy(port, mpt3sas_phy->phy); - mpt3sas_phy->phy_belongs_to_port = 1; - } - - mpt3sas_port->port = port; - if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) - rphy = sas_end_device_alloc(port); - else - rphy = sas_expander_alloc(port, - mpt3sas_port->remote_identify.device_type); - - rphy->identify = mpt3sas_port->remote_identify; - if ((sas_rphy_add(rphy))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - } - if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) - dev_printk(KERN_INFO, &rphy->dev, - "add: handle(0x%04x), sas_addr(0x%016llx)\n", - handle, (unsigned long long) - mpt3sas_port->remote_identify.sas_address); - mpt3sas_port->rphy = rphy; - spin_lock_irqsave(&ioc->sas_node_lock, flags); - list_add_tail(&mpt3sas_port->port_list, &sas_node->sas_port_list); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - /* fill in report manufacture */ - if (mpt3sas_port->remote_identify.device_type == - MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER || - mpt3sas_port->remote_identify.device_type == - MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) - _transport_expander_report_manufacture(ioc, - mpt3sas_port->remote_identify.sas_address, - rphy_to_expander_device(rphy)); - return mpt3sas_port; - - out_fail: - list_for_each_entry_safe(mpt3sas_phy, next, &mpt3sas_port->phy_list, - port_siblings) - list_del(&mpt3sas_phy->port_siblings); - kfree(mpt3sas_port); - return NULL; -} - -/** - * mpt3sas_transport_port_remove - remove port from the list - * @ioc: per adapter object - * @sas_address: sas address of attached device - * @sas_address_parent: sas address of parent expander or sas host - * Context: This function will acquire ioc->sas_node_lock. - * - * Removing object and freeing associated memory from the - * ioc->sas_port_list. - * - * Return nothing. - */ -void -mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, - u64 sas_address_parent) -{ - int i; - unsigned long flags; - struct _sas_port *mpt3sas_port, *next; - struct _sas_node *sas_node; - u8 found = 0; - struct _sas_phy *mpt3sas_phy, *next_phy; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_node = _transport_sas_node_find_by_sas_address(ioc, - sas_address_parent); - if (!sas_node) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return; - } - list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list, - port_list) { - if (mpt3sas_port->remote_identify.sas_address != sas_address) - continue; - found = 1; - list_del(&mpt3sas_port->port_list); - goto out; - } - out: - if (!found) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return; - } - - for (i = 0; i < sas_node->num_phys; i++) { - if (sas_node->phy[i].remote_identify.sas_address == sas_address) - memset(&sas_node->phy[i].remote_identify, 0 , - sizeof(struct sas_identify)); - } - - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - list_for_each_entry_safe(mpt3sas_phy, next_phy, - &mpt3sas_port->phy_list, port_siblings) { - if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) - dev_printk(KERN_INFO, &mpt3sas_port->port->dev, - "remove: sas_addr(0x%016llx), phy(%d)\n", - (unsigned long long) - mpt3sas_port->remote_identify.sas_address, - mpt3sas_phy->phy_id); - mpt3sas_phy->phy_belongs_to_port = 0; - sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy); - list_del(&mpt3sas_phy->port_siblings); - } - sas_port_delete(mpt3sas_port->port); - kfree(mpt3sas_port); -} - -/** - * mpt3sas_transport_add_host_phy - report sas_host phy to transport - * @ioc: per adapter object - * @mpt3sas_phy: mpt3sas per phy object - * @phy_pg0: sas phy page 0 - * @parent_dev: parent device class object - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy - *mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev) -{ - struct sas_phy *phy; - int phy_index = mpt3sas_phy->phy_id; - - - INIT_LIST_HEAD(&mpt3sas_phy->port_siblings); - phy = sas_phy_alloc(parent_dev, phy_index); - if (!phy) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - if ((_transport_set_identify(ioc, mpt3sas_phy->handle, - &mpt3sas_phy->identify))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - sas_phy_free(phy); - return -1; - } - phy->identify = mpt3sas_phy->identify; - mpt3sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle); - if (mpt3sas_phy->attached_handle) - _transport_set_identify(ioc, mpt3sas_phy->attached_handle, - &mpt3sas_phy->remote_identify); - phy->identify.phy_identifier = mpt3sas_phy->phy_id; - phy->negotiated_linkrate = _transport_convert_phy_link_rate( - phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL); - phy->minimum_linkrate_hw = _transport_convert_phy_link_rate( - phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK); - phy->maximum_linkrate_hw = _transport_convert_phy_link_rate( - phy_pg0.HwLinkRate >> 4); - phy->minimum_linkrate = _transport_convert_phy_link_rate( - phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); - phy->maximum_linkrate = _transport_convert_phy_link_rate( - phy_pg0.ProgrammedLinkRate >> 4); - - if ((sas_phy_add(phy))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - sas_phy_free(phy); - return -1; - } - if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) - dev_printk(KERN_INFO, &phy->dev, - "add: handle(0x%04x), sas_addr(0x%016llx)\n" - "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n", - mpt3sas_phy->handle, (unsigned long long) - mpt3sas_phy->identify.sas_address, - mpt3sas_phy->attached_handle, - (unsigned long long) - mpt3sas_phy->remote_identify.sas_address); - mpt3sas_phy->phy = phy; - return 0; -} - - -/** - * mpt3sas_transport_add_expander_phy - report expander phy to transport - * @ioc: per adapter object - * @mpt3sas_phy: mpt3sas per phy object - * @expander_pg1: expander page 1 - * @parent_dev: parent device class object - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy - *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1, - struct device *parent_dev) -{ - struct sas_phy *phy; - int phy_index = mpt3sas_phy->phy_id; - - INIT_LIST_HEAD(&mpt3sas_phy->port_siblings); - phy = sas_phy_alloc(parent_dev, phy_index); - if (!phy) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - if ((_transport_set_identify(ioc, mpt3sas_phy->handle, - &mpt3sas_phy->identify))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - sas_phy_free(phy); - return -1; - } - phy->identify = mpt3sas_phy->identify; - mpt3sas_phy->attached_handle = - le16_to_cpu(expander_pg1.AttachedDevHandle); - if (mpt3sas_phy->attached_handle) - _transport_set_identify(ioc, mpt3sas_phy->attached_handle, - &mpt3sas_phy->remote_identify); - phy->identify.phy_identifier = mpt3sas_phy->phy_id; - phy->negotiated_linkrate = _transport_convert_phy_link_rate( - expander_pg1.NegotiatedLinkRate & - MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL); - phy->minimum_linkrate_hw = _transport_convert_phy_link_rate( - expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK); - phy->maximum_linkrate_hw = _transport_convert_phy_link_rate( - expander_pg1.HwLinkRate >> 4); - phy->minimum_linkrate = _transport_convert_phy_link_rate( - expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); - phy->maximum_linkrate = _transport_convert_phy_link_rate( - expander_pg1.ProgrammedLinkRate >> 4); - - if ((sas_phy_add(phy))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - sas_phy_free(phy); - return -1; - } - if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) - dev_printk(KERN_INFO, &phy->dev, - "add: handle(0x%04x), sas_addr(0x%016llx)\n" - "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n", - mpt3sas_phy->handle, (unsigned long long) - mpt3sas_phy->identify.sas_address, - mpt3sas_phy->attached_handle, - (unsigned long long) - mpt3sas_phy->remote_identify.sas_address); - mpt3sas_phy->phy = phy; - return 0; -} - -/** - * mpt3sas_transport_update_links - refreshing phy link changes - * @ioc: per adapter object - * @sas_address: sas address of parent expander or sas host - * @handle: attached device handle - * @phy_numberv: phy number - * @link_rate: new link rate - * - * Returns nothing. - */ -void -mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address, u16 handle, u8 phy_number, u8 link_rate) -{ - unsigned long flags; - struct _sas_node *sas_node; - struct _sas_phy *mpt3sas_phy; - - if (ioc->shost_recovery || ioc->pci_error_recovery) - return; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address); - if (!sas_node) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return; - } - - mpt3sas_phy = &sas_node->phy[phy_number]; - mpt3sas_phy->attached_handle = handle; - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) { - _transport_set_identify(ioc, handle, - &mpt3sas_phy->remote_identify); - _transport_add_phy_to_an_existing_port(ioc, sas_node, - mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address); - } else - memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct - sas_identify)); - - if (mpt3sas_phy->phy) - mpt3sas_phy->phy->negotiated_linkrate = - _transport_convert_phy_link_rate(link_rate); - - if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) - dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev, - "refresh: parent sas_addr(0x%016llx),\n" - "\tlink_rate(0x%02x), phy(%d)\n" - "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n", - (unsigned long long)sas_address, - link_rate, phy_number, handle, (unsigned long long) - mpt3sas_phy->remote_identify.sas_address); -} - -static inline void * -phy_to_ioc(struct sas_phy *phy) -{ - struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); - return shost_priv(shost); -} - -static inline void * -rphy_to_ioc(struct sas_rphy *rphy) -{ - struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); - return shost_priv(shost); -} - -/* report phy error log structure */ -struct phy_error_log_request { - u8 smp_frame_type; /* 0x40 */ - u8 function; /* 0x11 */ - u8 allocated_response_length; - u8 request_length; /* 02 */ - u8 reserved_1[5]; - u8 phy_identifier; - u8 reserved_2[2]; -}; - -/* report phy error log reply structure */ -struct phy_error_log_reply { - u8 smp_frame_type; /* 0x41 */ - u8 function; /* 0x11 */ - u8 function_result; - u8 response_length; - __be16 expander_change_count; - u8 reserved_1[3]; - u8 phy_identifier; - u8 reserved_2[2]; - __be32 invalid_dword; - __be32 running_disparity_error; - __be32 loss_of_dword_sync; - __be32 phy_reset_problem; -}; - -/** - * _transport_get_expander_phy_error_log - return expander counters - * @ioc: per adapter object - * @phy: The sas phy object - * - * Returns 0 for success, non-zero for failure. - * - */ -static int -_transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc, - struct sas_phy *phy) -{ - Mpi2SmpPassthroughRequest_t *mpi_request; - Mpi2SmpPassthroughReply_t *mpi_reply; - struct phy_error_log_request *phy_error_log_request; - struct phy_error_log_reply *phy_error_log_reply; - int rc; - u16 smid; - u32 ioc_state; - unsigned long timeleft; - void *psge; - u8 issue_reset = 0; - void *data_out = NULL; - dma_addr_t data_out_dma; - u32 sz; - u16 wait_state_count; - - if (ioc->shost_recovery || ioc->pci_error_recovery) { - pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", - __func__, ioc->name); - return -EFAULT; - } - - mutex_lock(&ioc->transport_cmds.mutex); - - if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - ioc->transport_cmds.status = MPT3_CMD_PENDING; - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, __func__, wait_state_count); - } - if (wait_state_count) - pr_info(MPT3SAS_FMT "%s: ioc is operational\n", - ioc->name, __func__); - - smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->transport_cmds.smid = smid; - - sz = sizeof(struct phy_error_log_request) + - sizeof(struct phy_error_log_reply); - data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma); - if (!data_out) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - rc = -ENOMEM; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - - rc = -EINVAL; - memset(data_out, 0, sz); - phy_error_log_request = data_out; - phy_error_log_request->smp_frame_type = 0x40; - phy_error_log_request->function = 0x11; - phy_error_log_request->request_length = 2; - phy_error_log_request->allocated_response_length = 0; - phy_error_log_request->phy_identifier = phy->number; - - memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; - mpi_request->PhysicalPort = 0xFF; - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address); - mpi_request->RequestDataLength = - cpu_to_le16(sizeof(struct phy_error_log_request)); - psge = &mpi_request->SGL; - - ioc->build_sg(ioc, psge, data_out_dma, - sizeof(struct phy_error_log_request), - data_out_dma + sizeof(struct phy_error_log_request), - sizeof(struct phy_error_log_reply)); - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_error_log - send to sas_addr(0x%016llx), phy(%d)\n", - ioc->name, (unsigned long long)phy->identify.sas_address, - phy->number)); - init_completion(&ioc->transport_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, - 10*HZ); - - if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SmpPassthroughRequest_t)/4); - if (!(ioc->transport_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_error_log - complete\n", ioc->name)); - - if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) { - - mpi_reply = ioc->transport_cmds.reply; - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_error_log - reply data transfer size(%d)\n", - ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength))); - - if (le16_to_cpu(mpi_reply->ResponseDataLength) != - sizeof(struct phy_error_log_reply)) - goto out; - - phy_error_log_reply = data_out + - sizeof(struct phy_error_log_request); - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_error_log - function_result(%d)\n", - ioc->name, phy_error_log_reply->function_result)); - - phy->invalid_dword_count = - be32_to_cpu(phy_error_log_reply->invalid_dword); - phy->running_disparity_error_count = - be32_to_cpu(phy_error_log_reply->running_disparity_error); - phy->loss_of_dword_sync_count = - be32_to_cpu(phy_error_log_reply->loss_of_dword_sync); - phy->phy_reset_problem_count = - be32_to_cpu(phy_error_log_reply->phy_reset_problem); - rc = 0; - } else - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_error_log - no reply\n", ioc->name)); - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - out: - ioc->transport_cmds.status = MPT3_CMD_NOT_USED; - if (data_out) - pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma); - - mutex_unlock(&ioc->transport_cmds.mutex); - return rc; -} - -/** - * _transport_get_linkerrors - return phy counters for both hba and expanders - * @phy: The sas phy object - * - * Returns 0 for success, non-zero for failure. - * - */ -static int -_transport_get_linkerrors(struct sas_phy *phy) -{ - struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy); - unsigned long flags; - Mpi2ConfigReply_t mpi_reply; - Mpi2SasPhyPage1_t phy_pg1; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - if (_transport_sas_node_find_by_sas_address(ioc, - phy->identify.sas_address) == NULL) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return -EINVAL; - } - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - if (phy->identify.sas_address != ioc->sas_hba.sas_address) - return _transport_get_expander_phy_error_log(ioc, phy); - - /* get hba phy error logs */ - if ((mpt3sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1, - phy->number))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -ENXIO; - } - - if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) - pr_info(MPT3SAS_FMT - "phy(%d), ioc_status (0x%04x), loginfo(0x%08x)\n", - ioc->name, phy->number, - le16_to_cpu(mpi_reply.IOCStatus), - le32_to_cpu(mpi_reply.IOCLogInfo)); - - phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount); - phy->running_disparity_error_count = - le32_to_cpu(phy_pg1.RunningDisparityErrorCount); - phy->loss_of_dword_sync_count = - le32_to_cpu(phy_pg1.LossDwordSynchCount); - phy->phy_reset_problem_count = - le32_to_cpu(phy_pg1.PhyResetProblemCount); - return 0; -} - -/** - * _transport_get_enclosure_identifier - - * @phy: The sas phy object - * - * Obtain the enclosure logical id for an expander. - * Returns 0 for success, non-zero for failure. - */ -static int -_transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) -{ - struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy); - struct _sas_device *sas_device; - unsigned long flags; - int rc; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - rphy->identify.sas_address); - if (sas_device) { - *identifier = sas_device->enclosure_logical_id; - rc = 0; - } else { - *identifier = 0; - rc = -ENXIO; - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return rc; -} - -/** - * _transport_get_bay_identifier - - * @phy: The sas phy object - * - * Returns the slot id for a device that resides inside an enclosure. - */ -static int -_transport_get_bay_identifier(struct sas_rphy *rphy) -{ - struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy); - struct _sas_device *sas_device; - unsigned long flags; - int rc; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = mpt3sas_scsih_sas_device_find_by_sas_address(ioc, - rphy->identify.sas_address); - if (sas_device) - rc = sas_device->slot; - else - rc = -ENXIO; - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return rc; -} - -/* phy control request structure */ -struct phy_control_request { - u8 smp_frame_type; /* 0x40 */ - u8 function; /* 0x91 */ - u8 allocated_response_length; - u8 request_length; /* 0x09 */ - u16 expander_change_count; - u8 reserved_1[3]; - u8 phy_identifier; - u8 phy_operation; - u8 reserved_2[13]; - u64 attached_device_name; - u8 programmed_min_physical_link_rate; - u8 programmed_max_physical_link_rate; - u8 reserved_3[6]; -}; - -/* phy control reply structure */ -struct phy_control_reply { - u8 smp_frame_type; /* 0x41 */ - u8 function; /* 0x11 */ - u8 function_result; - u8 response_length; -}; - -#define SMP_PHY_CONTROL_LINK_RESET (0x01) -#define SMP_PHY_CONTROL_HARD_RESET (0x02) -#define SMP_PHY_CONTROL_DISABLE (0x03) - -/** - * _transport_expander_phy_control - expander phy control - * @ioc: per adapter object - * @phy: The sas phy object - * - * Returns 0 for success, non-zero for failure. - * - */ -static int -_transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc, - struct sas_phy *phy, u8 phy_operation) -{ - Mpi2SmpPassthroughRequest_t *mpi_request; - Mpi2SmpPassthroughReply_t *mpi_reply; - struct phy_control_request *phy_control_request; - struct phy_control_reply *phy_control_reply; - int rc; - u16 smid; - u32 ioc_state; - unsigned long timeleft; - void *psge; - u32 sgl_flags; - u8 issue_reset = 0; - void *data_out = NULL; - dma_addr_t data_out_dma; - u32 sz; - u16 wait_state_count; - - if (ioc->shost_recovery || ioc->pci_error_recovery) { - pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", - __func__, ioc->name); - return -EFAULT; - } - - mutex_lock(&ioc->transport_cmds.mutex); - - if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - ioc->transport_cmds.status = MPT3_CMD_PENDING; - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, __func__, wait_state_count); - } - if (wait_state_count) - pr_info(MPT3SAS_FMT "%s: ioc is operational\n", - ioc->name, __func__); - - smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->transport_cmds.smid = smid; - - sz = sizeof(struct phy_control_request) + - sizeof(struct phy_control_reply); - data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma); - if (!data_out) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - rc = -ENOMEM; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - - rc = -EINVAL; - memset(data_out, 0, sz); - phy_control_request = data_out; - phy_control_request->smp_frame_type = 0x40; - phy_control_request->function = 0x91; - phy_control_request->request_length = 9; - phy_control_request->allocated_response_length = 0; - phy_control_request->phy_identifier = phy->number; - phy_control_request->phy_operation = phy_operation; - phy_control_request->programmed_min_physical_link_rate = - phy->minimum_linkrate << 4; - phy_control_request->programmed_max_physical_link_rate = - phy->maximum_linkrate << 4; - - memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; - mpi_request->PhysicalPort = 0xFF; - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address); - mpi_request->RequestDataLength = - cpu_to_le16(sizeof(struct phy_error_log_request)); - psge = &mpi_request->SGL; - - /* WRITE sgel first */ - sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); - sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - ioc->base_add_sg_single(psge, sgl_flags | - sizeof(struct phy_control_request), data_out_dma); - - /* incr sgel */ - psge += ioc->sge_size; - - /* READ sgel last */ - sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | - MPI2_SGE_FLAGS_END_OF_LIST); - sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - ioc->base_add_sg_single(psge, sgl_flags | - sizeof(struct phy_control_reply), data_out_dma + - sizeof(struct phy_control_request)); - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_control - send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", - ioc->name, (unsigned long long)phy->identify.sas_address, - phy->number, phy_operation)); - init_completion(&ioc->transport_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, - 10*HZ); - - if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SmpPassthroughRequest_t)/4); - if (!(ioc->transport_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_control - complete\n", ioc->name)); - - if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) { - - mpi_reply = ioc->transport_cmds.reply; - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_control - reply data transfer size(%d)\n", - ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength))); - - if (le16_to_cpu(mpi_reply->ResponseDataLength) != - sizeof(struct phy_control_reply)) - goto out; - - phy_control_reply = data_out + - sizeof(struct phy_control_request); - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_control - function_result(%d)\n", - ioc->name, phy_control_reply->function_result)); - - rc = 0; - } else - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_control - no reply\n", ioc->name)); - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - out: - ioc->transport_cmds.status = MPT3_CMD_NOT_USED; - if (data_out) - pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma); - - mutex_unlock(&ioc->transport_cmds.mutex); - return rc; -} - -/** - * _transport_phy_reset - - * @phy: The sas phy object - * @hard_reset: - * - * Returns 0 for success, non-zero for failure. - */ -static int -_transport_phy_reset(struct sas_phy *phy, int hard_reset) -{ - struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy); - Mpi2SasIoUnitControlReply_t mpi_reply; - Mpi2SasIoUnitControlRequest_t mpi_request; - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - if (_transport_sas_node_find_by_sas_address(ioc, - phy->identify.sas_address) == NULL) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return -EINVAL; - } - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - /* handle expander phys */ - if (phy->identify.sas_address != ioc->sas_hba.sas_address) - return _transport_expander_phy_control(ioc, phy, - (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET : - SMP_PHY_CONTROL_LINK_RESET); - - /* handle hba phys */ - memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t)); - mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; - mpi_request.Operation = hard_reset ? - MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET; - mpi_request.PhyNum = phy->number; - - if ((mpt3sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -ENXIO; - } - - if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) - pr_info(MPT3SAS_FMT - "phy(%d), ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, phy->number, le16_to_cpu(mpi_reply.IOCStatus), - le32_to_cpu(mpi_reply.IOCLogInfo)); - - return 0; -} - -/** - * _transport_phy_enable - enable/disable phys - * @phy: The sas phy object - * @enable: enable phy when true - * - * Only support sas_host direct attached phys. - * Returns 0 for success, non-zero for failure. - */ -static int -_transport_phy_enable(struct sas_phy *phy, int enable) -{ - struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy); - Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; - Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; - Mpi2ConfigReply_t mpi_reply; - u16 ioc_status; - u16 sz; - int rc = 0; - unsigned long flags; - int i, discovery_active; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - if (_transport_sas_node_find_by_sas_address(ioc, - phy->identify.sas_address) == NULL) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return -EINVAL; - } - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - /* handle expander phys */ - if (phy->identify.sas_address != ioc->sas_hba.sas_address) - return _transport_expander_phy_control(ioc, phy, - (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET : - SMP_PHY_CONTROL_DISABLE); - - /* handle hba phys */ - - /* read sas_iounit page 0 */ - sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys * - sizeof(Mpi2SasIOUnit0PhyData_t)); - sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg0) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENOMEM; - goto out; - } - if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, - sas_iounit_pg0, sz))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENXIO; - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -EIO; - goto out; - } - - /* unable to enable/disable phys when when discovery is active */ - for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) { - if (sas_iounit_pg0->PhyData[i].PortFlags & - MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) { - pr_err(MPT3SAS_FMT "discovery is active on " \ - "port = %d, phy = %d: unable to enable/disable " - "phys, try again later!\n", ioc->name, - sas_iounit_pg0->PhyData[i].Port, i); - discovery_active = 1; - } - } - - if (discovery_active) { - rc = -EAGAIN; - goto out; - } - - /* read sas_iounit page 1 */ - sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * - sizeof(Mpi2SasIOUnit1PhyData_t)); - sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg1) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENOMEM; - goto out; - } - if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, - sas_iounit_pg1, sz))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENXIO; - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -EIO; - goto out; - } - - /* copy Port/PortFlags/PhyFlags from page 0 */ - for (i = 0; i < ioc->sas_hba.num_phys ; i++) { - sas_iounit_pg1->PhyData[i].Port = - sas_iounit_pg0->PhyData[i].Port; - sas_iounit_pg1->PhyData[i].PortFlags = - (sas_iounit_pg0->PhyData[i].PortFlags & - MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG); - sas_iounit_pg1->PhyData[i].PhyFlags = - (sas_iounit_pg0->PhyData[i].PhyFlags & - (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED + - MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED)); - } - - if (enable) - sas_iounit_pg1->PhyData[phy->number].PhyFlags - &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; - else - sas_iounit_pg1->PhyData[phy->number].PhyFlags - |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; - - mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz); - - /* link reset */ - if (enable) - _transport_phy_reset(phy, 0); - - out: - kfree(sas_iounit_pg1); - kfree(sas_iounit_pg0); - return rc; -} - -/** - * _transport_phy_speed - set phy min/max link rates - * @phy: The sas phy object - * @rates: rates defined in sas_phy_linkrates - * - * Only support sas_host direct attached phys. - * Returns 0 for success, non-zero for failure. - */ -static int -_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) -{ - struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy); - Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; - Mpi2SasPhyPage0_t phy_pg0; - Mpi2ConfigReply_t mpi_reply; - u16 ioc_status; - u16 sz; - int i; - int rc = 0; - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - if (_transport_sas_node_find_by_sas_address(ioc, - phy->identify.sas_address) == NULL) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return -EINVAL; - } - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - if (!rates->minimum_linkrate) - rates->minimum_linkrate = phy->minimum_linkrate; - else if (rates->minimum_linkrate < phy->minimum_linkrate_hw) - rates->minimum_linkrate = phy->minimum_linkrate_hw; - - if (!rates->maximum_linkrate) - rates->maximum_linkrate = phy->maximum_linkrate; - else if (rates->maximum_linkrate > phy->maximum_linkrate_hw) - rates->maximum_linkrate = phy->maximum_linkrate_hw; - - /* handle expander phys */ - if (phy->identify.sas_address != ioc->sas_hba.sas_address) { - phy->minimum_linkrate = rates->minimum_linkrate; - phy->maximum_linkrate = rates->maximum_linkrate; - return _transport_expander_phy_control(ioc, phy, - SMP_PHY_CONTROL_LINK_RESET); - } - - /* handle hba phys */ - - /* sas_iounit page 1 */ - sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * - sizeof(Mpi2SasIOUnit1PhyData_t)); - sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg1) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENOMEM; - goto out; - } - if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, - sas_iounit_pg1, sz))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENXIO; - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -EIO; - goto out; - } - - for (i = 0; i < ioc->sas_hba.num_phys; i++) { - if (phy->number != i) { - sas_iounit_pg1->PhyData[i].MaxMinLinkRate = - (ioc->sas_hba.phy[i].phy->minimum_linkrate + - (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4)); - } else { - sas_iounit_pg1->PhyData[i].MaxMinLinkRate = - (rates->minimum_linkrate + - (rates->maximum_linkrate << 4)); - } - } - - if (mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, - sz)) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENXIO; - goto out; - } - - /* link reset */ - _transport_phy_reset(phy, 0); - - /* read phy page 0, then update the rates in the sas transport phy */ - if (!mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0, - phy->number)) { - phy->minimum_linkrate = _transport_convert_phy_link_rate( - phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); - phy->maximum_linkrate = _transport_convert_phy_link_rate( - phy_pg0.ProgrammedLinkRate >> 4); - phy->negotiated_linkrate = _transport_convert_phy_link_rate( - phy_pg0.NegotiatedLinkRate & - MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL); - } - - out: - kfree(sas_iounit_pg1); - return rc; -} - -/** - * _transport_smp_handler - transport portal for smp passthru - * @shost: shost object - * @rphy: sas transport rphy object - * @req: - * - * This used primarily for smp_utils. - * Example: - * smp_rep_general /sys/class/bsg/expander-5:0 - */ -static int -_transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, - struct request *req) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - Mpi2SmpPassthroughRequest_t *mpi_request; - Mpi2SmpPassthroughReply_t *mpi_reply; - int rc, i; - u16 smid; - u32 ioc_state; - unsigned long timeleft; - void *psge; - u8 issue_reset = 0; - dma_addr_t dma_addr_in = 0; - dma_addr_t dma_addr_out = 0; - dma_addr_t pci_dma_in = 0; - dma_addr_t pci_dma_out = 0; - void *pci_addr_in = NULL; - void *pci_addr_out = NULL; - u16 wait_state_count; - struct request *rsp = req->next_rq; - struct bio_vec *bvec = NULL; - - if (!rsp) { - pr_err(MPT3SAS_FMT "%s: the smp response space is missing\n", - ioc->name, __func__); - return -EINVAL; - } - - if (ioc->shost_recovery || ioc->pci_error_recovery) { - pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", - __func__, ioc->name); - return -EFAULT; - } - - rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex); - if (rc) - return rc; - - if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", ioc->name, - __func__); - rc = -EAGAIN; - goto out; - } - ioc->transport_cmds.status = MPT3_CMD_PENDING; - - /* Check if the request is split across multiple segments */ - if (req->bio->bi_vcnt > 1) { - u32 offset = 0; - - /* Allocate memory and copy the request */ - pci_addr_out = pci_alloc_consistent(ioc->pdev, - blk_rq_bytes(req), &pci_dma_out); - if (!pci_addr_out) { - pr_info(MPT3SAS_FMT "%s(): PCI Addr out = NULL\n", - ioc->name, __func__); - rc = -ENOMEM; - goto out; - } - - bio_for_each_segment(bvec, req->bio, i) { - memcpy(pci_addr_out + offset, - page_address(bvec->bv_page) + bvec->bv_offset, - bvec->bv_len); - offset += bvec->bv_len; - } - } else { - dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio), - blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL); - if (!dma_addr_out) { - pr_info(MPT3SAS_FMT "%s(): DMA Addr out = NULL\n", - ioc->name, __func__); - rc = -ENOMEM; - goto free_pci; - } - } - - /* Check if the response needs to be populated across - * multiple segments */ - if (rsp->bio->bi_vcnt > 1) { - pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp), - &pci_dma_in); - if (!pci_addr_in) { - pr_info(MPT3SAS_FMT "%s(): PCI Addr in = NULL\n", - ioc->name, __func__); - rc = -ENOMEM; - goto unmap; - } - } else { - dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio), - blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL); - if (!dma_addr_in) { - pr_info(MPT3SAS_FMT "%s(): DMA Addr in = NULL\n", - ioc->name, __func__); - rc = -ENOMEM; - goto unmap; - } - } - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EFAULT; - goto unmap; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, __func__, wait_state_count); - } - if (wait_state_count) - pr_info(MPT3SAS_FMT "%s: ioc is operational\n", - ioc->name, __func__); - - smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto unmap; - } - - rc = 0; - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->transport_cmds.smid = smid; - - memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; - mpi_request->PhysicalPort = 0xFF; - mpi_request->SASAddress = (rphy) ? - cpu_to_le64(rphy->identify.sas_address) : - cpu_to_le64(ioc->sas_hba.sas_address); - mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4); - psge = &mpi_request->SGL; - - if (req->bio->bi_vcnt > 1) - ioc->build_sg(ioc, psge, pci_dma_out, (blk_rq_bytes(req) - 4), - pci_dma_in, (blk_rq_bytes(rsp) + 4)); - else - ioc->build_sg(ioc, psge, dma_addr_out, (blk_rq_bytes(req) - 4), - dma_addr_in, (blk_rq_bytes(rsp) + 4)); - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "%s - sending smp request\n", ioc->name, __func__)); - - init_completion(&ioc->transport_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, - 10*HZ); - - if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s : timeout\n", - __func__, ioc->name); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SmpPassthroughRequest_t)/4); - if (!(ioc->transport_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "%s - complete\n", ioc->name, __func__)); - - if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) { - - mpi_reply = ioc->transport_cmds.reply; - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "%s - reply data transfer size(%d)\n", - ioc->name, __func__, - le16_to_cpu(mpi_reply->ResponseDataLength))); - - memcpy(req->sense, mpi_reply, sizeof(*mpi_reply)); - req->sense_len = sizeof(*mpi_reply); - req->resid_len = 0; - rsp->resid_len -= - le16_to_cpu(mpi_reply->ResponseDataLength); - - /* check if the resp needs to be copied from the allocated - * pci mem */ - if (rsp->bio->bi_vcnt > 1) { - u32 offset = 0; - u32 bytes_to_copy = - le16_to_cpu(mpi_reply->ResponseDataLength); - bio_for_each_segment(bvec, rsp->bio, i) { - if (bytes_to_copy <= bvec->bv_len) { - memcpy(page_address(bvec->bv_page) + - bvec->bv_offset, pci_addr_in + - offset, bytes_to_copy); - break; - } else { - memcpy(page_address(bvec->bv_page) + - bvec->bv_offset, pci_addr_in + - offset, bvec->bv_len); - bytes_to_copy -= bvec->bv_len; - } - offset += bvec->bv_len; - } - } - } else { - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "%s - no reply\n", ioc->name, __func__)); - rc = -ENXIO; - } - - issue_host_reset: - if (issue_reset) { - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - rc = -ETIMEDOUT; - } - - unmap: - if (dma_addr_out) - pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req), - PCI_DMA_BIDIRECTIONAL); - if (dma_addr_in) - pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp), - PCI_DMA_BIDIRECTIONAL); - - free_pci: - if (pci_addr_out) - pci_free_consistent(ioc->pdev, blk_rq_bytes(req), pci_addr_out, - pci_dma_out); - - if (pci_addr_in) - pci_free_consistent(ioc->pdev, blk_rq_bytes(rsp), pci_addr_in, - pci_dma_in); - - out: - ioc->transport_cmds.status = MPT3_CMD_NOT_USED; - mutex_unlock(&ioc->transport_cmds.mutex); - return rc; -} - -struct sas_function_template mpt3sas_transport_functions = { - .get_linkerrors = _transport_get_linkerrors, - .get_enclosure_identifier = _transport_get_enclosure_identifier, - .get_bay_identifier = _transport_get_bay_identifier, - .phy_reset = _transport_phy_reset, - .phy_enable = _transport_phy_enable, - .set_phy_speed = _transport_phy_speed, - .smp_handler = _transport_smp_handler, -}; - -struct scsi_transport_template *mpt3sas_transport_template; diff --git a/addons/mpt3sas/src/3.10.108/mpt3sas_trigger_diag.c b/addons/mpt3sas/src/3.10.108/mpt3sas_trigger_diag.c deleted file mode 100644 index 6f8d6213..00000000 --- a/addons/mpt3sas/src/3.10.108/mpt3sas_trigger_diag.c +++ /dev/null @@ -1,433 +0,0 @@ -/* - * This module provides common API to set Diagnostic trigger for MPT - * (Message Passing Technology) based controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c - * Copyright (C) 2012 LSI Corporation - * (mailto:DL-MPTFusionLinux@lsi.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "mpt3sas_base.h" - -/** - * _mpt3sas_raise_sigio - notifiy app - * @ioc: per adapter object - * @event_data: - */ -static void -_mpt3sas_raise_sigio(struct MPT3SAS_ADAPTER *ioc, - struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data) -{ - Mpi2EventNotificationReply_t *mpi_reply; - u16 sz, event_data_sz; - unsigned long flags; - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", - ioc->name, __func__)); - - sz = offsetof(Mpi2EventNotificationReply_t, EventData) + - sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4; - mpi_reply = kzalloc(sz, GFP_KERNEL); - if (!mpi_reply) - goto out; - mpi_reply->Event = cpu_to_le16(MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED); - event_data_sz = (sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4) / 4; - mpi_reply->EventDataLength = cpu_to_le16(event_data_sz); - memcpy(&mpi_reply->EventData, event_data, - sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: add to driver event log\n", - ioc->name, __func__)); - mpt3sas_ctl_add_to_event_log(ioc, mpi_reply); - kfree(mpi_reply); - out: - - /* clearing the diag_trigger_active flag */ - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: clearing diag_trigger_active flag\n", - ioc->name, __func__)); - ioc->diag_trigger_active = 0; - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); -} - -/** - * mpt3sas_process_trigger_data - process the event data for the trigger - * @ioc: per adapter object - * @event_data: - */ -void -mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc, - struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data) -{ - u8 issue_reset = 0; - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", - ioc->name, __func__)); - - /* release the diag buffer trace */ - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED) == 0) { - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: release trace diag buffer\n", ioc->name, __func__)); - mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, - &issue_reset); - } - - _mpt3sas_raise_sigio(ioc, event_data); - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); -} - -/** - * mpt3sas_trigger_master - Master trigger handler - * @ioc: per adapter object - * @trigger_bitmask: - * - */ -void -mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc, u32 trigger_bitmask) -{ - struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; - unsigned long flags; - u8 found_match = 0; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - - if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT || - trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET) - goto by_pass_checks; - - /* check to see if trace buffers are currently registered */ - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - /* check to see if trace buffers are currently released */ - if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - by_pass_checks: - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: enter - trigger_bitmask = 0x%08x\n", - ioc->name, __func__, trigger_bitmask)); - - /* don't send trigger if an trigger is currently active */ - if (ioc->diag_trigger_active) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - goto out; - } - - /* check for the trigger condition */ - if (ioc->diag_trigger_master.MasterData & trigger_bitmask) { - found_match = 1; - ioc->diag_trigger_active = 1; - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: setting diag_trigger_active flag\n", - ioc->name, __func__)); - } - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - - if (!found_match) - goto out; - - memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); - event_data.trigger_type = MPT3SAS_TRIGGER_MASTER; - event_data.u.master.MasterData = trigger_bitmask; - - if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT || - trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET) - _mpt3sas_raise_sigio(ioc, &event_data); - else - mpt3sas_send_trigger_data_event(ioc, &event_data); - - out: - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); -} - -/** - * mpt3sas_trigger_event - Event trigger handler - * @ioc: per adapter object - * @event: - * @log_entry_qualifier: - * - */ -void -mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event, - u16 log_entry_qualifier) -{ - struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; - struct SL_WH_EVENT_TRIGGER_T *event_trigger; - int i; - unsigned long flags; - u8 found_match; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - - /* check to see if trace buffers are currently registered */ - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - /* check to see if trace buffers are currently released */ - if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: enter - event = 0x%04x, log_entry_qualifier = 0x%04x\n", - ioc->name, __func__, event, log_entry_qualifier)); - - /* don't send trigger if an trigger is currently active */ - if (ioc->diag_trigger_active) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - goto out; - } - - /* check for the trigger condition */ - event_trigger = ioc->diag_trigger_event.EventTriggerEntry; - for (i = 0 , found_match = 0; i < ioc->diag_trigger_event.ValidEntries - && !found_match; i++, event_trigger++) { - if (event_trigger->EventValue != event) - continue; - if (event == MPI2_EVENT_LOG_ENTRY_ADDED) { - if (event_trigger->LogEntryQualifier == - log_entry_qualifier) - found_match = 1; - continue; - } - found_match = 1; - ioc->diag_trigger_active = 1; - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: setting diag_trigger_active flag\n", - ioc->name, __func__)); - } - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - - if (!found_match) - goto out; - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: setting diag_trigger_active flag\n", - ioc->name, __func__)); - memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); - event_data.trigger_type = MPT3SAS_TRIGGER_EVENT; - event_data.u.event.EventValue = event; - event_data.u.event.LogEntryQualifier = log_entry_qualifier; - mpt3sas_send_trigger_data_event(ioc, &event_data); - out: - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); -} - -/** - * mpt3sas_trigger_scsi - SCSI trigger handler - * @ioc: per adapter object - * @sense_key: - * @asc: - * @ascq: - * - */ -void -mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key, u8 asc, - u8 ascq) -{ - struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; - struct SL_WH_SCSI_TRIGGER_T *scsi_trigger; - int i; - unsigned long flags; - u8 found_match; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - - /* check to see if trace buffers are currently registered */ - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - /* check to see if trace buffers are currently released */ - if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: enter - sense_key = 0x%02x, asc = 0x%02x, ascq = 0x%02x\n", - ioc->name, __func__, sense_key, asc, ascq)); - - /* don't send trigger if an trigger is currently active */ - if (ioc->diag_trigger_active) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - goto out; - } - - /* check for the trigger condition */ - scsi_trigger = ioc->diag_trigger_scsi.SCSITriggerEntry; - for (i = 0 , found_match = 0; i < ioc->diag_trigger_scsi.ValidEntries - && !found_match; i++, scsi_trigger++) { - if (scsi_trigger->SenseKey != sense_key) - continue; - if (!(scsi_trigger->ASC == 0xFF || scsi_trigger->ASC == asc)) - continue; - if (!(scsi_trigger->ASCQ == 0xFF || scsi_trigger->ASCQ == ascq)) - continue; - found_match = 1; - ioc->diag_trigger_active = 1; - } - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - - if (!found_match) - goto out; - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: setting diag_trigger_active flag\n", - ioc->name, __func__)); - memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); - event_data.trigger_type = MPT3SAS_TRIGGER_SCSI; - event_data.u.scsi.SenseKey = sense_key; - event_data.u.scsi.ASC = asc; - event_data.u.scsi.ASCQ = ascq; - mpt3sas_send_trigger_data_event(ioc, &event_data); - out: - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); -} - -/** - * mpt3sas_trigger_mpi - MPI trigger handler - * @ioc: per adapter object - * @ioc_status: - * @loginfo: - * - */ -void -mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status, u32 loginfo) -{ - struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; - struct SL_WH_MPI_TRIGGER_T *mpi_trigger; - int i; - unsigned long flags; - u8 found_match; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - - /* check to see if trace buffers are currently registered */ - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - /* check to see if trace buffers are currently released */ - if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: enter - ioc_status = 0x%04x, loginfo = 0x%08x\n", - ioc->name, __func__, ioc_status, loginfo)); - - /* don't send trigger if an trigger is currently active */ - if (ioc->diag_trigger_active) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - goto out; - } - - /* check for the trigger condition */ - mpi_trigger = ioc->diag_trigger_mpi.MPITriggerEntry; - for (i = 0 , found_match = 0; i < ioc->diag_trigger_mpi.ValidEntries - && !found_match; i++, mpi_trigger++) { - if (mpi_trigger->IOCStatus != ioc_status) - continue; - if (!(mpi_trigger->IocLogInfo == 0xFFFFFFFF || - mpi_trigger->IocLogInfo == loginfo)) - continue; - found_match = 1; - ioc->diag_trigger_active = 1; - } - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - - if (!found_match) - goto out; - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: setting diag_trigger_active flag\n", - ioc->name, __func__)); - memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); - event_data.trigger_type = MPT3SAS_TRIGGER_MPI; - event_data.u.mpi.IOCStatus = ioc_status; - event_data.u.mpi.IocLogInfo = loginfo; - mpt3sas_send_trigger_data_event(ioc, &event_data); - out: - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); -} diff --git a/addons/mpt3sas/src/3.10.108/mpt3sas_trigger_diag.h b/addons/mpt3sas/src/3.10.108/mpt3sas_trigger_diag.h deleted file mode 100644 index a10c3090..00000000 --- a/addons/mpt3sas/src/3.10.108/mpt3sas_trigger_diag.h +++ /dev/null @@ -1,193 +0,0 @@ -/* - * This is the Fusion MPT base driver providing common API layer interface - * to set Diagnostic triggers for MPT (Message Passing Technology) based - * controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h - * Copyright (C) 2012 LSI Corporation - * (mailto:DL-MPTFusionLinux@lsi.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - /* Diagnostic Trigger Configuration Data Structures */ - -#ifndef MPT3SAS_TRIGGER_DIAG_H_INCLUDED -#define MPT3SAS_TRIGGER_DIAG_H_INCLUDED - -/* limitation on number of entries */ -#define NUM_VALID_ENTRIES (20) - -/* trigger types */ -#define MPT3SAS_TRIGGER_MASTER (1) -#define MPT3SAS_TRIGGER_EVENT (2) -#define MPT3SAS_TRIGGER_SCSI (3) -#define MPT3SAS_TRIGGER_MPI (4) - -/* trigger names */ -#define MASTER_TRIGGER_FILE_NAME "diag_trigger_master" -#define EVENT_TRIGGERS_FILE_NAME "diag_trigger_event" -#define SCSI_TRIGGERS_FILE_NAME "diag_trigger_scsi" -#define MPI_TRIGGER_FILE_NAME "diag_trigger_mpi" - -/* master trigger bitmask */ -#define MASTER_TRIGGER_FW_FAULT (0x00000001) -#define MASTER_TRIGGER_ADAPTER_RESET (0x00000002) -#define MASTER_TRIGGER_TASK_MANAGMENT (0x00000004) -#define MASTER_TRIGGER_DEVICE_REMOVAL (0x00000008) - -/* fake firmware event for tigger */ -#define MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED (0x6E) - -/** - * MasterTrigger is a single U32 passed to/from sysfs. - * - * Bit Flags (enables) include: - * 1. FW Faults - * 2. Adapter Reset issued by driver - * 3. TMs - * 4. Device Remove Event sent by FW - */ - -struct SL_WH_MASTER_TRIGGER_T { - uint32_t MasterData; -}; - -/** - * struct SL_WH_EVENT_TRIGGER_T - Definition of an event trigger element - * @EventValue: Event Code to trigger on - * @LogEntryQualifier: Type of FW event that logged (Log Entry Added Event only) - * - * Defines an event that should induce a DIAG_TRIGGER driver event if observed. - */ -struct SL_WH_EVENT_TRIGGER_T { - uint16_t EventValue; - uint16_t LogEntryQualifier; -}; - -/** - * struct SL_WH_EVENT_TRIGGERS_T - Structure passed to/from sysfs containing a - * list of Event Triggers to be monitored for. - * @ValidEntries: Number of _SL_WH_EVENT_TRIGGER_T structures contained in this - * structure. - * @EventTriggerEntry: List of Event trigger elements. - * - * This binary structure is transferred via sysfs to get/set Event Triggers - * in the Linux Driver. - */ - -struct SL_WH_EVENT_TRIGGERS_T { - uint32_t ValidEntries; - struct SL_WH_EVENT_TRIGGER_T EventTriggerEntry[NUM_VALID_ENTRIES]; -}; - -/** - * struct SL_WH_SCSI_TRIGGER_T - Definition of a SCSI trigger element - * @ASCQ: Additional Sense Code Qualifier. Can be specific or 0xFF for - * wildcard. - * @ASC: Additional Sense Code. Can be specific or 0xFF for wildcard - * @SenseKey: SCSI Sense Key - * - * Defines a sense key (single or many variants) that should induce a - * DIAG_TRIGGER driver event if observed. - */ -struct SL_WH_SCSI_TRIGGER_T { - U8 ASCQ; - U8 ASC; - U8 SenseKey; - U8 Reserved; -}; - -/** - * struct SL_WH_SCSI_TRIGGERS_T - Structure passed to/from sysfs containing a - * list of SCSI sense codes that should trigger a DIAG_SERVICE event when - * observed. - * @ValidEntries: Number of _SL_WH_SCSI_TRIGGER_T structures contained in this - * structure. - * @SCSITriggerEntry: List of SCSI Sense Code trigger elements. - * - * This binary structure is transferred via sysfs to get/set SCSI Sense Code - * Triggers in the Linux Driver. - */ -struct SL_WH_SCSI_TRIGGERS_T { - uint32_t ValidEntries; - struct SL_WH_SCSI_TRIGGER_T SCSITriggerEntry[NUM_VALID_ENTRIES]; -}; - -/** - * struct SL_WH_MPI_TRIGGER_T - Definition of an MPI trigger element - * @IOCStatus: MPI IOCStatus - * @IocLogInfo: MPI IocLogInfo. Can be specific or 0xFFFFFFFF for wildcard - * - * Defines a MPI IOCStatus/IocLogInfo pair that should induce a DIAG_TRIGGER - * driver event if observed. - */ -struct SL_WH_MPI_TRIGGER_T { - uint16_t IOCStatus; - uint16_t Reserved; - uint32_t IocLogInfo; -}; - -/** - * struct SL_WH_MPI_TRIGGERS_T - Structure passed to/from sysfs containing a - * list of MPI IOCStatus/IocLogInfo pairs that should trigger a DIAG_SERVICE - * event when observed. - * @ValidEntries: Number of _SL_WH_MPI_TRIGGER_T structures contained in this - * structure. - * @MPITriggerEntry: List of MPI IOCStatus/IocLogInfo trigger elements. - * - * This binary structure is transferred via sysfs to get/set MPI Error Triggers - * in the Linux Driver. - */ -struct SL_WH_MPI_TRIGGERS_T { - uint32_t ValidEntries; - struct SL_WH_MPI_TRIGGER_T MPITriggerEntry[NUM_VALID_ENTRIES]; -}; - -/** - * struct SL_WH_TRIGGERS_EVENT_DATA_T - event data for trigger - * @trigger_type: trigger type (see MPT3SAS_TRIGGER_XXXX) - * @u: trigger condition that caused trigger to be sent - */ -struct SL_WH_TRIGGERS_EVENT_DATA_T { - uint32_t trigger_type; - union { - struct SL_WH_MASTER_TRIGGER_T master; - struct SL_WH_EVENT_TRIGGER_T event; - struct SL_WH_SCSI_TRIGGER_T scsi; - struct SL_WH_MPI_TRIGGER_T mpi; - } u; -}; -#endif /* MPT3SAS_TRIGGER_DIAG_H_INCLUDED */ diff --git a/addons/mpt3sas/src/4.4.180/Makefile b/addons/mpt3sas/src/4.4.180/Makefile deleted file mode 100644 index 4c824586..00000000 --- a/addons/mpt3sas/src/4.4.180/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -obj-m += mpt3sas.o -mpt3sas-y += mpt3sas_base.o \ - mpt3sas_config.o \ - mpt3sas_scsih.o \ - mpt3sas_transport.o \ - mpt3sas_ctl.o \ - mpt3sas_trigger_diag.o \ - mpt3sas_warpdrive.o diff --git a/addons/mpt3sas/src/4.4.180/mpi/mpi2.h b/addons/mpt3sas/src/4.4.180/mpi/mpi2.h deleted file mode 100644 index ec27ad2d..00000000 --- a/addons/mpt3sas/src/4.4.180/mpi/mpi2.h +++ /dev/null @@ -1,1176 +0,0 @@ -/* - * Copyright (c) 2000-2014 LSI Corporation. - * - * - * Name: mpi2.h - * Title: MPI Message independent structures and definitions - * including System Interface Register Set and - * scatter/gather formats. - * Creation Date: June 21, 2006 - * - * mpi2.h Version: 02.00.35 - * - * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 - * prefix are for use only on MPI v2.5 products, and must not be used - * with MPI v2.0 products. Unless otherwise noted, names beginning with - * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 06-04-07 02.00.01 Bumped MPI2_HEADER_VERSION_UNIT. - * 06-26-07 02.00.02 Bumped MPI2_HEADER_VERSION_UNIT. - * 08-31-07 02.00.03 Bumped MPI2_HEADER_VERSION_UNIT. - * Moved ReplyPostHostIndex register to offset 0x6C of the - * MPI2_SYSTEM_INTERFACE_REGS and modified the define for - * MPI2_REPLY_POST_HOST_INDEX_OFFSET. - * Added union of request descriptors. - * Added union of reply descriptors. - * 10-31-07 02.00.04 Bumped MPI2_HEADER_VERSION_UNIT. - * Added define for MPI2_VERSION_02_00. - * Fixed the size of the FunctionDependent5 field in the - * MPI2_DEFAULT_REPLY structure. - * 12-18-07 02.00.05 Bumped MPI2_HEADER_VERSION_UNIT. - * Removed the MPI-defined Fault Codes and extended the - * product specific codes up to 0xEFFF. - * Added a sixth key value for the WriteSequence register - * and changed the flush value to 0x0. - * Added message function codes for Diagnostic Buffer Post - * and Diagnsotic Release. - * New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED - * Moved MPI2_VERSION_UNION from mpi2_ioc.h. - * 02-29-08 02.00.06 Bumped MPI2_HEADER_VERSION_UNIT. - * 03-03-08 02.00.07 Bumped MPI2_HEADER_VERSION_UNIT. - * 05-21-08 02.00.08 Bumped MPI2_HEADER_VERSION_UNIT. - * Added #defines for marking a reply descriptor as unused. - * 06-27-08 02.00.09 Bumped MPI2_HEADER_VERSION_UNIT. - * 10-02-08 02.00.10 Bumped MPI2_HEADER_VERSION_UNIT. - * Moved LUN field defines from mpi2_init.h. - * 01-19-09 02.00.11 Bumped MPI2_HEADER_VERSION_UNIT. - * 05-06-09 02.00.12 Bumped MPI2_HEADER_VERSION_UNIT. - * In all request and reply descriptors, replaced VF_ID - * field with MSIxIndex field. - * Removed DevHandle field from - * MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those - * bytes reserved. - * Added RAID Accelerator functionality. - * 07-30-09 02.00.13 Bumped MPI2_HEADER_VERSION_UNIT. - * 10-28-09 02.00.14 Bumped MPI2_HEADER_VERSION_UNIT. - * Added MSI-x index mask and shift for Reply Post Host - * Index register. - * Added function code for Host Based Discovery Action. - * 02-10-10 02.00.15 Bumped MPI2_HEADER_VERSION_UNIT. - * Added define for MPI2_FUNCTION_PWR_MGMT_CONTROL. - * Added defines for product-specific range of message - * function codes, 0xF0 to 0xFF. - * 05-12-10 02.00.16 Bumped MPI2_HEADER_VERSION_UNIT. - * Added alternative defines for the SGE Direction bit. - * 08-11-10 02.00.17 Bumped MPI2_HEADER_VERSION_UNIT. - * 11-10-10 02.00.18 Bumped MPI2_HEADER_VERSION_UNIT. - * Added MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR define. - * 02-23-11 02.00.19 Bumped MPI2_HEADER_VERSION_UNIT. - * Added MPI2_FUNCTION_SEND_HOST_MESSAGE. - * 03-09-11 02.00.20 Bumped MPI2_HEADER_VERSION_UNIT. - * 05-25-11 02.00.21 Bumped MPI2_HEADER_VERSION_UNIT. - * 08-24-11 02.00.22 Bumped MPI2_HEADER_VERSION_UNIT. - * 11-18-11 02.00.23 Bumped MPI2_HEADER_VERSION_UNIT. - * Incorporating additions for MPI v2.5. - * 02-06-12 02.00.24 Bumped MPI2_HEADER_VERSION_UNIT. - * 03-29-12 02.00.25 Bumped MPI2_HEADER_VERSION_UNIT. - * Added Hard Reset delay timings. - * 07-10-12 02.00.26 Bumped MPI2_HEADER_VERSION_UNIT. - * 07-26-12 02.00.27 Bumped MPI2_HEADER_VERSION_UNIT. - * 11-27-12 02.00.28 Bumped MPI2_HEADER_VERSION_UNIT. - * 12-20-12 02.00.29 Bumped MPI2_HEADER_VERSION_UNIT. - * Added MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET. - * 04-09-13 02.00.30 Bumped MPI2_HEADER_VERSION_UNIT. - * 04-17-13 02.00.31 Bumped MPI2_HEADER_VERSION_UNIT. - * 08-19-13 02.00.32 Bumped MPI2_HEADER_VERSION_UNIT. - * 12-05-13 02.00.33 Bumped MPI2_HEADER_VERSION_UNIT. - * 01-08-14 02.00.34 Bumped MPI2_HEADER_VERSION_UNIT - * 06-13-14 02.00.35 Bumped MPI2_HEADER_VERSION_UNIT. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_H -#define MPI2_H - -/***************************************************************************** -* -* MPI Version Definitions -* -*****************************************************************************/ - -#define MPI2_VERSION_MAJOR_MASK (0xFF00) -#define MPI2_VERSION_MAJOR_SHIFT (8) -#define MPI2_VERSION_MINOR_MASK (0x00FF) -#define MPI2_VERSION_MINOR_SHIFT (0) - -/*major version for all MPI v2.x */ -#define MPI2_VERSION_MAJOR (0x02) - -/*minor version for MPI v2.0 compatible products */ -#define MPI2_VERSION_MINOR (0x00) -#define MPI2_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \ - MPI2_VERSION_MINOR) -#define MPI2_VERSION_02_00 (0x0200) - -/*minor version for MPI v2.5 compatible products */ -#define MPI25_VERSION_MINOR (0x05) -#define MPI25_VERSION ((MPI2_VERSION_MAJOR << MPI2_VERSION_MAJOR_SHIFT) | \ - MPI25_VERSION_MINOR) -#define MPI2_VERSION_02_05 (0x0205) - -/*Unit and Dev versioning for this MPI header set */ -#define MPI2_HEADER_VERSION_UNIT (0x23) -#define MPI2_HEADER_VERSION_DEV (0x00) -#define MPI2_HEADER_VERSION_UNIT_MASK (0xFF00) -#define MPI2_HEADER_VERSION_UNIT_SHIFT (8) -#define MPI2_HEADER_VERSION_DEV_MASK (0x00FF) -#define MPI2_HEADER_VERSION_DEV_SHIFT (0) -#define MPI2_HEADER_VERSION ((MPI2_HEADER_VERSION_UNIT << 8) | \ - MPI2_HEADER_VERSION_DEV) - -/***************************************************************************** -* -* IOC State Definitions -* -*****************************************************************************/ - -#define MPI2_IOC_STATE_RESET (0x00000000) -#define MPI2_IOC_STATE_READY (0x10000000) -#define MPI2_IOC_STATE_OPERATIONAL (0x20000000) -#define MPI2_IOC_STATE_FAULT (0x40000000) - -#define MPI2_IOC_STATE_MASK (0xF0000000) -#define MPI2_IOC_STATE_SHIFT (28) - -/*Fault state range for prodcut specific codes */ -#define MPI2_FAULT_PRODUCT_SPECIFIC_MIN (0x0000) -#define MPI2_FAULT_PRODUCT_SPECIFIC_MAX (0xEFFF) - -/***************************************************************************** -* -* System Interface Register Definitions -* -*****************************************************************************/ - -typedef volatile struct _MPI2_SYSTEM_INTERFACE_REGS { - U32 Doorbell; /*0x00 */ - U32 WriteSequence; /*0x04 */ - U32 HostDiagnostic; /*0x08 */ - U32 Reserved1; /*0x0C */ - U32 DiagRWData; /*0x10 */ - U32 DiagRWAddressLow; /*0x14 */ - U32 DiagRWAddressHigh; /*0x18 */ - U32 Reserved2[5]; /*0x1C */ - U32 HostInterruptStatus; /*0x30 */ - U32 HostInterruptMask; /*0x34 */ - U32 DCRData; /*0x38 */ - U32 DCRAddress; /*0x3C */ - U32 Reserved3[2]; /*0x40 */ - U32 ReplyFreeHostIndex; /*0x48 */ - U32 Reserved4[8]; /*0x4C */ - U32 ReplyPostHostIndex; /*0x6C */ - U32 Reserved5; /*0x70 */ - U32 HCBSize; /*0x74 */ - U32 HCBAddressLow; /*0x78 */ - U32 HCBAddressHigh; /*0x7C */ - U32 Reserved6[16]; /*0x80 */ - U32 RequestDescriptorPostLow; /*0xC0 */ - U32 RequestDescriptorPostHigh; /*0xC4 */ - U32 Reserved7[14]; /*0xC8 */ -} MPI2_SYSTEM_INTERFACE_REGS, - *PTR_MPI2_SYSTEM_INTERFACE_REGS, - Mpi2SystemInterfaceRegs_t, - *pMpi2SystemInterfaceRegs_t; - -/* - *Defines for working with the Doorbell register. - */ -#define MPI2_DOORBELL_OFFSET (0x00000000) - -/*IOC --> System values */ -#define MPI2_DOORBELL_USED (0x08000000) -#define MPI2_DOORBELL_WHO_INIT_MASK (0x07000000) -#define MPI2_DOORBELL_WHO_INIT_SHIFT (24) -#define MPI2_DOORBELL_FAULT_CODE_MASK (0x0000FFFF) -#define MPI2_DOORBELL_DATA_MASK (0x0000FFFF) - -/*System --> IOC values */ -#define MPI2_DOORBELL_FUNCTION_MASK (0xFF000000) -#define MPI2_DOORBELL_FUNCTION_SHIFT (24) -#define MPI2_DOORBELL_ADD_DWORDS_MASK (0x00FF0000) -#define MPI2_DOORBELL_ADD_DWORDS_SHIFT (16) - -/* - *Defines for the WriteSequence register - */ -#define MPI2_WRITE_SEQUENCE_OFFSET (0x00000004) -#define MPI2_WRSEQ_KEY_VALUE_MASK (0x0000000F) -#define MPI2_WRSEQ_FLUSH_KEY_VALUE (0x0) -#define MPI2_WRSEQ_1ST_KEY_VALUE (0xF) -#define MPI2_WRSEQ_2ND_KEY_VALUE (0x4) -#define MPI2_WRSEQ_3RD_KEY_VALUE (0xB) -#define MPI2_WRSEQ_4TH_KEY_VALUE (0x2) -#define MPI2_WRSEQ_5TH_KEY_VALUE (0x7) -#define MPI2_WRSEQ_6TH_KEY_VALUE (0xD) - -/* - *Defines for the HostDiagnostic register - */ -#define MPI2_HOST_DIAGNOSTIC_OFFSET (0x00000008) - -#define MPI2_DIAG_BOOT_DEVICE_SELECT_MASK (0x00001800) -#define MPI2_DIAG_BOOT_DEVICE_SELECT_DEFAULT (0x00000000) -#define MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW (0x00000800) - -#define MPI2_DIAG_CLEAR_FLASH_BAD_SIG (0x00000400) -#define MPI2_DIAG_FORCE_HCB_ON_RESET (0x00000200) -#define MPI2_DIAG_HCB_MODE (0x00000100) -#define MPI2_DIAG_DIAG_WRITE_ENABLE (0x00000080) -#define MPI2_DIAG_FLASH_BAD_SIG (0x00000040) -#define MPI2_DIAG_RESET_HISTORY (0x00000020) -#define MPI2_DIAG_DIAG_RW_ENABLE (0x00000010) -#define MPI2_DIAG_RESET_ADAPTER (0x00000004) -#define MPI2_DIAG_HOLD_IOC_RESET (0x00000002) - -/* - *Offsets for DiagRWData and address - */ -#define MPI2_DIAG_RW_DATA_OFFSET (0x00000010) -#define MPI2_DIAG_RW_ADDRESS_LOW_OFFSET (0x00000014) -#define MPI2_DIAG_RW_ADDRESS_HIGH_OFFSET (0x00000018) - -/* - *Defines for the HostInterruptStatus register - */ -#define MPI2_HOST_INTERRUPT_STATUS_OFFSET (0x00000030) -#define MPI2_HIS_SYS2IOC_DB_STATUS (0x80000000) -#define MPI2_HIS_IOP_DOORBELL_STATUS MPI2_HIS_SYS2IOC_DB_STATUS -#define MPI2_HIS_RESET_IRQ_STATUS (0x40000000) -#define MPI2_HIS_REPLY_DESCRIPTOR_INTERRUPT (0x00000008) -#define MPI2_HIS_IOC2SYS_DB_STATUS (0x00000001) -#define MPI2_HIS_DOORBELL_INTERRUPT MPI2_HIS_IOC2SYS_DB_STATUS - -/* - *Defines for the HostInterruptMask register - */ -#define MPI2_HOST_INTERRUPT_MASK_OFFSET (0x00000034) -#define MPI2_HIM_RESET_IRQ_MASK (0x40000000) -#define MPI2_HIM_REPLY_INT_MASK (0x00000008) -#define MPI2_HIM_RIM MPI2_HIM_REPLY_INT_MASK -#define MPI2_HIM_IOC2SYS_DB_MASK (0x00000001) -#define MPI2_HIM_DIM MPI2_HIM_IOC2SYS_DB_MASK - -/* - *Offsets for DCRData and address - */ -#define MPI2_DCR_DATA_OFFSET (0x00000038) -#define MPI2_DCR_ADDRESS_OFFSET (0x0000003C) - -/* - *Offset for the Reply Free Queue - */ -#define MPI2_REPLY_FREE_HOST_INDEX_OFFSET (0x00000048) - -/* - *Defines for the Reply Descriptor Post Queue - */ -#define MPI2_REPLY_POST_HOST_INDEX_OFFSET (0x0000006C) -#define MPI2_REPLY_POST_HOST_INDEX_MASK (0x00FFFFFF) -#define MPI2_RPHI_MSIX_INDEX_MASK (0xFF000000) -#define MPI2_RPHI_MSIX_INDEX_SHIFT (24) -#define MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET (0x0000030C) /*MPI v2.5 only*/ - - -/* - *Defines for the HCBSize and address - */ -#define MPI2_HCB_SIZE_OFFSET (0x00000074) -#define MPI2_HCB_SIZE_SIZE_MASK (0xFFFFF000) -#define MPI2_HCB_SIZE_HCB_ENABLE (0x00000001) - -#define MPI2_HCB_ADDRESS_LOW_OFFSET (0x00000078) -#define MPI2_HCB_ADDRESS_HIGH_OFFSET (0x0000007C) - -/* - *Offsets for the Request Queue - */ -#define MPI2_REQUEST_DESCRIPTOR_POST_LOW_OFFSET (0x000000C0) -#define MPI2_REQUEST_DESCRIPTOR_POST_HIGH_OFFSET (0x000000C4) - -/*Hard Reset delay timings */ -#define MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC (50000) -#define MPI2_HARD_RESET_PCIE_RESET_READ_WINDOW_MICRO_SEC (255000) -#define MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC (256000) - -/***************************************************************************** -* -* Message Descriptors -* -*****************************************************************************/ - -/*Request Descriptors */ - -/*Default Request Descriptor */ -typedef struct _MPI2_DEFAULT_REQUEST_DESCRIPTOR { - U8 RequestFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U16 LMID; /*0x04 */ - U16 DescriptorTypeDependent; /*0x06 */ -} MPI2_DEFAULT_REQUEST_DESCRIPTOR, - *PTR_MPI2_DEFAULT_REQUEST_DESCRIPTOR, - Mpi2DefaultRequestDescriptor_t, - *pMpi2DefaultRequestDescriptor_t; - -/*defines for the RequestFlags field */ -#define MPI2_REQ_DESCRIPT_FLAGS_TYPE_MASK (0x0E) -#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO (0x00) -#define MPI2_REQ_DESCRIPT_FLAGS_SCSI_TARGET (0x02) -#define MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY (0x06) -#define MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE (0x08) -#define MPI2_REQ_DESCRIPT_FLAGS_RAID_ACCELERATOR (0x0A) -#define MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO (0x0C) - -#define MPI2_REQ_DESCRIPT_FLAGS_IOC_FIFO_MARKER (0x01) - -/*High Priority Request Descriptor */ -typedef struct _MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR { - U8 RequestFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U16 LMID; /*0x04 */ - U16 Reserved1; /*0x06 */ -} MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR, - *PTR_MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR, - Mpi2HighPriorityRequestDescriptor_t, - *pMpi2HighPriorityRequestDescriptor_t; - -/*SCSI IO Request Descriptor */ -typedef struct _MPI2_SCSI_IO_REQUEST_DESCRIPTOR { - U8 RequestFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U16 LMID; /*0x04 */ - U16 DevHandle; /*0x06 */ -} MPI2_SCSI_IO_REQUEST_DESCRIPTOR, - *PTR_MPI2_SCSI_IO_REQUEST_DESCRIPTOR, - Mpi2SCSIIORequestDescriptor_t, - *pMpi2SCSIIORequestDescriptor_t; - -/*SCSI Target Request Descriptor */ -typedef struct _MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR { - U8 RequestFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U16 LMID; /*0x04 */ - U16 IoIndex; /*0x06 */ -} MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR, - *PTR_MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR, - Mpi2SCSITargetRequestDescriptor_t, - *pMpi2SCSITargetRequestDescriptor_t; - -/*RAID Accelerator Request Descriptor */ -typedef struct _MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR { - U8 RequestFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U16 LMID; /*0x04 */ - U16 Reserved; /*0x06 */ -} MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR, - *PTR_MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR, - Mpi2RAIDAcceleratorRequestDescriptor_t, - *pMpi2RAIDAcceleratorRequestDescriptor_t; - -/*Fast Path SCSI IO Request Descriptor */ -typedef MPI2_SCSI_IO_REQUEST_DESCRIPTOR - MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR, - *PTR_MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR, - Mpi25FastPathSCSIIORequestDescriptor_t, - *pMpi25FastPathSCSIIORequestDescriptor_t; - -/*union of Request Descriptors */ -typedef union _MPI2_REQUEST_DESCRIPTOR_UNION { - MPI2_DEFAULT_REQUEST_DESCRIPTOR Default; - MPI2_HIGH_PRIORITY_REQUEST_DESCRIPTOR HighPriority; - MPI2_SCSI_IO_REQUEST_DESCRIPTOR SCSIIO; - MPI2_SCSI_TARGET_REQUEST_DESCRIPTOR SCSITarget; - MPI2_RAID_ACCEL_REQUEST_DESCRIPTOR RAIDAccelerator; - MPI25_FP_SCSI_IO_REQUEST_DESCRIPTOR FastPathSCSIIO; - U64 Words; -} MPI2_REQUEST_DESCRIPTOR_UNION, - *PTR_MPI2_REQUEST_DESCRIPTOR_UNION, - Mpi2RequestDescriptorUnion_t, - *pMpi2RequestDescriptorUnion_t; - -/*Reply Descriptors */ - -/*Default Reply Descriptor */ -typedef struct _MPI2_DEFAULT_REPLY_DESCRIPTOR { - U8 ReplyFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 DescriptorTypeDependent1; /*0x02 */ - U32 DescriptorTypeDependent2; /*0x04 */ -} MPI2_DEFAULT_REPLY_DESCRIPTOR, - *PTR_MPI2_DEFAULT_REPLY_DESCRIPTOR, - Mpi2DefaultReplyDescriptor_t, - *pMpi2DefaultReplyDescriptor_t; - -/*defines for the ReplyFlags field */ -#define MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK (0x0F) -#define MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS (0x00) -#define MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY (0x01) -#define MPI2_RPY_DESCRIPT_FLAGS_TARGETASSIST_SUCCESS (0x02) -#define MPI2_RPY_DESCRIPT_FLAGS_TARGET_COMMAND_BUFFER (0x03) -#define MPI2_RPY_DESCRIPT_FLAGS_RAID_ACCELERATOR_SUCCESS (0x05) -#define MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS (0x06) -#define MPI2_RPY_DESCRIPT_FLAGS_UNUSED (0x0F) - -/*values for marking a reply descriptor as unused */ -#define MPI2_RPY_DESCRIPT_UNUSED_WORD0_MARK (0xFFFFFFFF) -#define MPI2_RPY_DESCRIPT_UNUSED_WORD1_MARK (0xFFFFFFFF) - -/*Address Reply Descriptor */ -typedef struct _MPI2_ADDRESS_REPLY_DESCRIPTOR { - U8 ReplyFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U32 ReplyFrameAddress; /*0x04 */ -} MPI2_ADDRESS_REPLY_DESCRIPTOR, - *PTR_MPI2_ADDRESS_REPLY_DESCRIPTOR, - Mpi2AddressReplyDescriptor_t, - *pMpi2AddressReplyDescriptor_t; - -#define MPI2_ADDRESS_REPLY_SMID_INVALID (0x00) - -/*SCSI IO Success Reply Descriptor */ -typedef struct _MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR { - U8 ReplyFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U16 TaskTag; /*0x04 */ - U16 Reserved1; /*0x06 */ -} MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, - *PTR_MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, - Mpi2SCSIIOSuccessReplyDescriptor_t, - *pMpi2SCSIIOSuccessReplyDescriptor_t; - -/*TargetAssist Success Reply Descriptor */ -typedef struct _MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR { - U8 ReplyFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U8 SequenceNumber; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 IoIndex; /*0x06 */ -} MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR, - *PTR_MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR, - Mpi2TargetAssistSuccessReplyDescriptor_t, - *pMpi2TargetAssistSuccessReplyDescriptor_t; - -/*Target Command Buffer Reply Descriptor */ -typedef struct _MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR { - U8 ReplyFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U8 VP_ID; /*0x02 */ - U8 Flags; /*0x03 */ - U16 InitiatorDevHandle; /*0x04 */ - U16 IoIndex; /*0x06 */ -} MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, - *PTR_MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR, - Mpi2TargetCommandBufferReplyDescriptor_t, - *pMpi2TargetCommandBufferReplyDescriptor_t; - -/*defines for Flags field */ -#define MPI2_RPY_DESCRIPT_TCB_FLAGS_PHYNUM_MASK (0x3F) - -/*RAID Accelerator Success Reply Descriptor */ -typedef struct _MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR { - U8 ReplyFlags; /*0x00 */ - U8 MSIxIndex; /*0x01 */ - U16 SMID; /*0x02 */ - U32 Reserved; /*0x04 */ -} MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR, - *PTR_MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR, - Mpi2RAIDAcceleratorSuccessReplyDescriptor_t, - *pMpi2RAIDAcceleratorSuccessReplyDescriptor_t; - -/*Fast Path SCSI IO Success Reply Descriptor */ -typedef MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR - MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, - *PTR_MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR, - Mpi25FastPathSCSIIOSuccessReplyDescriptor_t, - *pMpi25FastPathSCSIIOSuccessReplyDescriptor_t; - -/*union of Reply Descriptors */ -typedef union _MPI2_REPLY_DESCRIPTORS_UNION { - MPI2_DEFAULT_REPLY_DESCRIPTOR Default; - MPI2_ADDRESS_REPLY_DESCRIPTOR AddressReply; - MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR SCSIIOSuccess; - MPI2_TARGETASSIST_SUCCESS_REPLY_DESCRIPTOR TargetAssistSuccess; - MPI2_TARGET_COMMAND_BUFFER_REPLY_DESCRIPTOR TargetCommandBuffer; - MPI2_RAID_ACCELERATOR_SUCCESS_REPLY_DESCRIPTOR RAIDAcceleratorSuccess; - MPI25_FP_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR FastPathSCSIIOSuccess; - U64 Words; -} MPI2_REPLY_DESCRIPTORS_UNION, - *PTR_MPI2_REPLY_DESCRIPTORS_UNION, - Mpi2ReplyDescriptorsUnion_t, - *pMpi2ReplyDescriptorsUnion_t; - -/***************************************************************************** -* -* Message Functions -* -*****************************************************************************/ - -#define MPI2_FUNCTION_SCSI_IO_REQUEST (0x00) -#define MPI2_FUNCTION_SCSI_TASK_MGMT (0x01) -#define MPI2_FUNCTION_IOC_INIT (0x02) -#define MPI2_FUNCTION_IOC_FACTS (0x03) -#define MPI2_FUNCTION_CONFIG (0x04) -#define MPI2_FUNCTION_PORT_FACTS (0x05) -#define MPI2_FUNCTION_PORT_ENABLE (0x06) -#define MPI2_FUNCTION_EVENT_NOTIFICATION (0x07) -#define MPI2_FUNCTION_EVENT_ACK (0x08) -#define MPI2_FUNCTION_FW_DOWNLOAD (0x09) -#define MPI2_FUNCTION_TARGET_ASSIST (0x0B) -#define MPI2_FUNCTION_TARGET_STATUS_SEND (0x0C) -#define MPI2_FUNCTION_TARGET_MODE_ABORT (0x0D) -#define MPI2_FUNCTION_FW_UPLOAD (0x12) -#define MPI2_FUNCTION_RAID_ACTION (0x15) -#define MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH (0x16) -#define MPI2_FUNCTION_TOOLBOX (0x17) -#define MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR (0x18) -#define MPI2_FUNCTION_SMP_PASSTHROUGH (0x1A) -#define MPI2_FUNCTION_SAS_IO_UNIT_CONTROL (0x1B) -#define MPI2_FUNCTION_SATA_PASSTHROUGH (0x1C) -#define MPI2_FUNCTION_DIAG_BUFFER_POST (0x1D) -#define MPI2_FUNCTION_DIAG_RELEASE (0x1E) -#define MPI2_FUNCTION_TARGET_CMD_BUF_BASE_POST (0x24) -#define MPI2_FUNCTION_TARGET_CMD_BUF_LIST_POST (0x25) -#define MPI2_FUNCTION_RAID_ACCELERATOR (0x2C) -#define MPI2_FUNCTION_HOST_BASED_DISCOVERY_ACTION (0x2F) -#define MPI2_FUNCTION_PWR_MGMT_CONTROL (0x30) -#define MPI2_FUNCTION_SEND_HOST_MESSAGE (0x31) -#define MPI2_FUNCTION_MIN_PRODUCT_SPECIFIC (0xF0) -#define MPI2_FUNCTION_MAX_PRODUCT_SPECIFIC (0xFF) - -/*Doorbell functions */ -#define MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET (0x40) -#define MPI2_FUNCTION_HANDSHAKE (0x42) - -/***************************************************************************** -* -* IOC Status Values -* -*****************************************************************************/ - -/*mask for IOCStatus status value */ -#define MPI2_IOCSTATUS_MASK (0x7FFF) - -/**************************************************************************** -* Common IOCStatus values for all replies -****************************************************************************/ - -#define MPI2_IOCSTATUS_SUCCESS (0x0000) -#define MPI2_IOCSTATUS_INVALID_FUNCTION (0x0001) -#define MPI2_IOCSTATUS_BUSY (0x0002) -#define MPI2_IOCSTATUS_INVALID_SGL (0x0003) -#define MPI2_IOCSTATUS_INTERNAL_ERROR (0x0004) -#define MPI2_IOCSTATUS_INVALID_VPID (0x0005) -#define MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES (0x0006) -#define MPI2_IOCSTATUS_INVALID_FIELD (0x0007) -#define MPI2_IOCSTATUS_INVALID_STATE (0x0008) -#define MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED (0x0009) - -/**************************************************************************** -* Config IOCStatus values -****************************************************************************/ - -#define MPI2_IOCSTATUS_CONFIG_INVALID_ACTION (0x0020) -#define MPI2_IOCSTATUS_CONFIG_INVALID_TYPE (0x0021) -#define MPI2_IOCSTATUS_CONFIG_INVALID_PAGE (0x0022) -#define MPI2_IOCSTATUS_CONFIG_INVALID_DATA (0x0023) -#define MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS (0x0024) -#define MPI2_IOCSTATUS_CONFIG_CANT_COMMIT (0x0025) - -/**************************************************************************** -* SCSI IO Reply -****************************************************************************/ - -#define MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR (0x0040) -#define MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE (0x0042) -#define MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE (0x0043) -#define MPI2_IOCSTATUS_SCSI_DATA_OVERRUN (0x0044) -#define MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN (0x0045) -#define MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR (0x0046) -#define MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR (0x0047) -#define MPI2_IOCSTATUS_SCSI_TASK_TERMINATED (0x0048) -#define MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH (0x0049) -#define MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED (0x004A) -#define MPI2_IOCSTATUS_SCSI_IOC_TERMINATED (0x004B) -#define MPI2_IOCSTATUS_SCSI_EXT_TERMINATED (0x004C) - -/**************************************************************************** -* For use by SCSI Initiator and SCSI Target end-to-end data protection -****************************************************************************/ - -#define MPI2_IOCSTATUS_EEDP_GUARD_ERROR (0x004D) -#define MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR (0x004E) -#define MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR (0x004F) - -/**************************************************************************** -* SCSI Target values -****************************************************************************/ - -#define MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX (0x0062) -#define MPI2_IOCSTATUS_TARGET_ABORTED (0x0063) -#define MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE (0x0064) -#define MPI2_IOCSTATUS_TARGET_NO_CONNECTION (0x0065) -#define MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH (0x006A) -#define MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR (0x006D) -#define MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA (0x006E) -#define MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT (0x006F) -#define MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT (0x0070) -#define MPI2_IOCSTATUS_TARGET_NAK_RECEIVED (0x0071) - -/**************************************************************************** -* Serial Attached SCSI values -****************************************************************************/ - -#define MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED (0x0090) -#define MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN (0x0091) - -/**************************************************************************** -* Diagnostic Buffer Post / Diagnostic Release values -****************************************************************************/ - -#define MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED (0x00A0) - -/**************************************************************************** -* RAID Accelerator values -****************************************************************************/ - -#define MPI2_IOCSTATUS_RAID_ACCEL_ERROR (0x00B0) - -/**************************************************************************** -* IOCStatus flag to indicate that log info is available -****************************************************************************/ - -#define MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE (0x8000) - -/**************************************************************************** -* IOCLogInfo Types -****************************************************************************/ - -#define MPI2_IOCLOGINFO_TYPE_MASK (0xF0000000) -#define MPI2_IOCLOGINFO_TYPE_SHIFT (28) -#define MPI2_IOCLOGINFO_TYPE_NONE (0x0) -#define MPI2_IOCLOGINFO_TYPE_SCSI (0x1) -#define MPI2_IOCLOGINFO_TYPE_FC (0x2) -#define MPI2_IOCLOGINFO_TYPE_SAS (0x3) -#define MPI2_IOCLOGINFO_TYPE_ISCSI (0x4) -#define MPI2_IOCLOGINFO_LOG_DATA_MASK (0x0FFFFFFF) - -/***************************************************************************** -* -* Standard Message Structures -* -*****************************************************************************/ - -/**************************************************************************** -*Request Message Header for all request messages -****************************************************************************/ - -typedef struct _MPI2_REQUEST_HEADER { - U16 FunctionDependent1; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 FunctionDependent2; /*0x04 */ - U8 FunctionDependent3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ -} MPI2_REQUEST_HEADER, *PTR_MPI2_REQUEST_HEADER, - MPI2RequestHeader_t, *pMPI2RequestHeader_t; - -/**************************************************************************** -* Default Reply -****************************************************************************/ - -typedef struct _MPI2_DEFAULT_REPLY { - U16 FunctionDependent1; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 FunctionDependent2; /*0x04 */ - U8 FunctionDependent3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U16 FunctionDependent5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_DEFAULT_REPLY, *PTR_MPI2_DEFAULT_REPLY, - MPI2DefaultReply_t, *pMPI2DefaultReply_t; - -/*common version structure/union used in messages and configuration pages */ - -typedef struct _MPI2_VERSION_STRUCT { - U8 Dev; /*0x00 */ - U8 Unit; /*0x01 */ - U8 Minor; /*0x02 */ - U8 Major; /*0x03 */ -} MPI2_VERSION_STRUCT; - -typedef union _MPI2_VERSION_UNION { - MPI2_VERSION_STRUCT Struct; - U32 Word; -} MPI2_VERSION_UNION; - -/*LUN field defines, common to many structures */ -#define MPI2_LUN_FIRST_LEVEL_ADDRESSING (0x0000FFFF) -#define MPI2_LUN_SECOND_LEVEL_ADDRESSING (0xFFFF0000) -#define MPI2_LUN_THIRD_LEVEL_ADDRESSING (0x0000FFFF) -#define MPI2_LUN_FOURTH_LEVEL_ADDRESSING (0xFFFF0000) -#define MPI2_LUN_LEVEL_1_WORD (0xFF00) -#define MPI2_LUN_LEVEL_1_DWORD (0x0000FF00) - -/***************************************************************************** -* -* Fusion-MPT MPI Scatter Gather Elements -* -*****************************************************************************/ - -/**************************************************************************** -* MPI Simple Element structures -****************************************************************************/ - -typedef struct _MPI2_SGE_SIMPLE32 { - U32 FlagsLength; - U32 Address; -} MPI2_SGE_SIMPLE32, *PTR_MPI2_SGE_SIMPLE32, - Mpi2SGESimple32_t, *pMpi2SGESimple32_t; - -typedef struct _MPI2_SGE_SIMPLE64 { - U32 FlagsLength; - U64 Address; -} MPI2_SGE_SIMPLE64, *PTR_MPI2_SGE_SIMPLE64, - Mpi2SGESimple64_t, *pMpi2SGESimple64_t; - -typedef struct _MPI2_SGE_SIMPLE_UNION { - U32 FlagsLength; - union { - U32 Address32; - U64 Address64; - } u; -} MPI2_SGE_SIMPLE_UNION, - *PTR_MPI2_SGE_SIMPLE_UNION, - Mpi2SGESimpleUnion_t, - *pMpi2SGESimpleUnion_t; - -/**************************************************************************** -* MPI Chain Element structures - for MPI v2.0 products only -****************************************************************************/ - -typedef struct _MPI2_SGE_CHAIN32 { - U16 Length; - U8 NextChainOffset; - U8 Flags; - U32 Address; -} MPI2_SGE_CHAIN32, *PTR_MPI2_SGE_CHAIN32, - Mpi2SGEChain32_t, *pMpi2SGEChain32_t; - -typedef struct _MPI2_SGE_CHAIN64 { - U16 Length; - U8 NextChainOffset; - U8 Flags; - U64 Address; -} MPI2_SGE_CHAIN64, *PTR_MPI2_SGE_CHAIN64, - Mpi2SGEChain64_t, *pMpi2SGEChain64_t; - -typedef struct _MPI2_SGE_CHAIN_UNION { - U16 Length; - U8 NextChainOffset; - U8 Flags; - union { - U32 Address32; - U64 Address64; - } u; -} MPI2_SGE_CHAIN_UNION, - *PTR_MPI2_SGE_CHAIN_UNION, - Mpi2SGEChainUnion_t, - *pMpi2SGEChainUnion_t; - -/**************************************************************************** -* MPI Transaction Context Element structures - for MPI v2.0 products only -****************************************************************************/ - -typedef struct _MPI2_SGE_TRANSACTION32 { - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 TransactionContext[1]; - U32 TransactionDetails[1]; -} MPI2_SGE_TRANSACTION32, - *PTR_MPI2_SGE_TRANSACTION32, - Mpi2SGETransaction32_t, - *pMpi2SGETransaction32_t; - -typedef struct _MPI2_SGE_TRANSACTION64 { - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 TransactionContext[2]; - U32 TransactionDetails[1]; -} MPI2_SGE_TRANSACTION64, - *PTR_MPI2_SGE_TRANSACTION64, - Mpi2SGETransaction64_t, - *pMpi2SGETransaction64_t; - -typedef struct _MPI2_SGE_TRANSACTION96 { - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 TransactionContext[3]; - U32 TransactionDetails[1]; -} MPI2_SGE_TRANSACTION96, *PTR_MPI2_SGE_TRANSACTION96, - Mpi2SGETransaction96_t, *pMpi2SGETransaction96_t; - -typedef struct _MPI2_SGE_TRANSACTION128 { - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - U32 TransactionContext[4]; - U32 TransactionDetails[1]; -} MPI2_SGE_TRANSACTION128, *PTR_MPI2_SGE_TRANSACTION128, - Mpi2SGETransaction_t128, *pMpi2SGETransaction_t128; - -typedef struct _MPI2_SGE_TRANSACTION_UNION { - U8 Reserved; - U8 ContextSize; - U8 DetailsLength; - U8 Flags; - union { - U32 TransactionContext32[1]; - U32 TransactionContext64[2]; - U32 TransactionContext96[3]; - U32 TransactionContext128[4]; - } u; - U32 TransactionDetails[1]; -} MPI2_SGE_TRANSACTION_UNION, - *PTR_MPI2_SGE_TRANSACTION_UNION, - Mpi2SGETransactionUnion_t, - *pMpi2SGETransactionUnion_t; - -/**************************************************************************** -* MPI SGE union for IO SGL's - for MPI v2.0 products only -****************************************************************************/ - -typedef struct _MPI2_MPI_SGE_IO_UNION { - union { - MPI2_SGE_SIMPLE_UNION Simple; - MPI2_SGE_CHAIN_UNION Chain; - } u; -} MPI2_MPI_SGE_IO_UNION, *PTR_MPI2_MPI_SGE_IO_UNION, - Mpi2MpiSGEIOUnion_t, *pMpi2MpiSGEIOUnion_t; - -/**************************************************************************** -* MPI SGE union for SGL's with Simple and Transaction elements - for MPI v2.0 products only -****************************************************************************/ - -typedef struct _MPI2_SGE_TRANS_SIMPLE_UNION { - union { - MPI2_SGE_SIMPLE_UNION Simple; - MPI2_SGE_TRANSACTION_UNION Transaction; - } u; -} MPI2_SGE_TRANS_SIMPLE_UNION, - *PTR_MPI2_SGE_TRANS_SIMPLE_UNION, - Mpi2SGETransSimpleUnion_t, - *pMpi2SGETransSimpleUnion_t; - -/**************************************************************************** -* All MPI SGE types union -****************************************************************************/ - -typedef struct _MPI2_MPI_SGE_UNION { - union { - MPI2_SGE_SIMPLE_UNION Simple; - MPI2_SGE_CHAIN_UNION Chain; - MPI2_SGE_TRANSACTION_UNION Transaction; - } u; -} MPI2_MPI_SGE_UNION, *PTR_MPI2_MPI_SGE_UNION, - Mpi2MpiSgeUnion_t, *pMpi2MpiSgeUnion_t; - -/**************************************************************************** -* MPI SGE field definition and masks -****************************************************************************/ - -/*Flags field bit definitions */ - -#define MPI2_SGE_FLAGS_LAST_ELEMENT (0x80) -#define MPI2_SGE_FLAGS_END_OF_BUFFER (0x40) -#define MPI2_SGE_FLAGS_ELEMENT_TYPE_MASK (0x30) -#define MPI2_SGE_FLAGS_LOCAL_ADDRESS (0x08) -#define MPI2_SGE_FLAGS_DIRECTION (0x04) -#define MPI2_SGE_FLAGS_ADDRESS_SIZE (0x02) -#define MPI2_SGE_FLAGS_END_OF_LIST (0x01) - -#define MPI2_SGE_FLAGS_SHIFT (24) - -#define MPI2_SGE_LENGTH_MASK (0x00FFFFFF) -#define MPI2_SGE_CHAIN_LENGTH_MASK (0x0000FFFF) - -/*Element Type */ - -#define MPI2_SGE_FLAGS_TRANSACTION_ELEMENT (0x00) -#define MPI2_SGE_FLAGS_SIMPLE_ELEMENT (0x10) -#define MPI2_SGE_FLAGS_CHAIN_ELEMENT (0x30) -#define MPI2_SGE_FLAGS_ELEMENT_MASK (0x30) - -/*Address location */ - -#define MPI2_SGE_FLAGS_SYSTEM_ADDRESS (0x00) - -/*Direction */ - -#define MPI2_SGE_FLAGS_IOC_TO_HOST (0x00) -#define MPI2_SGE_FLAGS_HOST_TO_IOC (0x04) - -#define MPI2_SGE_FLAGS_DEST (MPI2_SGE_FLAGS_IOC_TO_HOST) -#define MPI2_SGE_FLAGS_SOURCE (MPI2_SGE_FLAGS_HOST_TO_IOC) - -/*Address Size */ - -#define MPI2_SGE_FLAGS_32_BIT_ADDRESSING (0x00) -#define MPI2_SGE_FLAGS_64_BIT_ADDRESSING (0x02) - -/*Context Size */ - -#define MPI2_SGE_FLAGS_32_BIT_CONTEXT (0x00) -#define MPI2_SGE_FLAGS_64_BIT_CONTEXT (0x02) -#define MPI2_SGE_FLAGS_96_BIT_CONTEXT (0x04) -#define MPI2_SGE_FLAGS_128_BIT_CONTEXT (0x06) - -#define MPI2_SGE_CHAIN_OFFSET_MASK (0x00FF0000) -#define MPI2_SGE_CHAIN_OFFSET_SHIFT (16) - -/**************************************************************************** -* MPI SGE operation Macros -****************************************************************************/ - -/*SIMPLE FlagsLength manipulations... */ -#define MPI2_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_SGE_FLAGS_SHIFT) -#define MPI2_SGE_GET_FLAGS(f) (((f) & ~MPI2_SGE_LENGTH_MASK) >> \ - MPI2_SGE_FLAGS_SHIFT) -#define MPI2_SGE_LENGTH(f) ((f) & MPI2_SGE_LENGTH_MASK) -#define MPI2_SGE_CHAIN_LENGTH(f) ((f) & MPI2_SGE_CHAIN_LENGTH_MASK) - -#define MPI2_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_SGE_SET_FLAGS(f) | \ - MPI2_SGE_LENGTH(l)) - -#define MPI2_pSGE_GET_FLAGS(psg) MPI2_SGE_GET_FLAGS((psg)->FlagsLength) -#define MPI2_pSGE_GET_LENGTH(psg) MPI2_SGE_LENGTH((psg)->FlagsLength) -#define MPI2_pSGE_SET_FLAGS_LENGTH(psg, f, l) ((psg)->FlagsLength = \ - MPI2_SGE_SET_FLAGS_LENGTH(f, l)) - -/*CAUTION - The following are READ-MODIFY-WRITE! */ -#define MPI2_pSGE_SET_FLAGS(psg, f) ((psg)->FlagsLength |= \ - MPI2_SGE_SET_FLAGS(f)) -#define MPI2_pSGE_SET_LENGTH(psg, l) ((psg)->FlagsLength |= \ - MPI2_SGE_LENGTH(l)) - -#define MPI2_GET_CHAIN_OFFSET(x) ((x & MPI2_SGE_CHAIN_OFFSET_MASK) >> \ - MPI2_SGE_CHAIN_OFFSET_SHIFT) - -/***************************************************************************** -* -* Fusion-MPT IEEE Scatter Gather Elements -* -*****************************************************************************/ - -/**************************************************************************** -* IEEE Simple Element structures -****************************************************************************/ - -/*MPI2_IEEE_SGE_SIMPLE32 is for MPI v2.0 products only */ -typedef struct _MPI2_IEEE_SGE_SIMPLE32 { - U32 Address; - U32 FlagsLength; -} MPI2_IEEE_SGE_SIMPLE32, *PTR_MPI2_IEEE_SGE_SIMPLE32, - Mpi2IeeeSgeSimple32_t, *pMpi2IeeeSgeSimple32_t; - -typedef struct _MPI2_IEEE_SGE_SIMPLE64 { - U64 Address; - U32 Length; - U16 Reserved1; - U8 Reserved2; - U8 Flags; -} MPI2_IEEE_SGE_SIMPLE64, *PTR_MPI2_IEEE_SGE_SIMPLE64, - Mpi2IeeeSgeSimple64_t, *pMpi2IeeeSgeSimple64_t; - -typedef union _MPI2_IEEE_SGE_SIMPLE_UNION { - MPI2_IEEE_SGE_SIMPLE32 Simple32; - MPI2_IEEE_SGE_SIMPLE64 Simple64; -} MPI2_IEEE_SGE_SIMPLE_UNION, - *PTR_MPI2_IEEE_SGE_SIMPLE_UNION, - Mpi2IeeeSgeSimpleUnion_t, - *pMpi2IeeeSgeSimpleUnion_t; - -/**************************************************************************** -* IEEE Chain Element structures -****************************************************************************/ - -/*MPI2_IEEE_SGE_CHAIN32 is for MPI v2.0 products only */ -typedef MPI2_IEEE_SGE_SIMPLE32 MPI2_IEEE_SGE_CHAIN32; - -/*MPI2_IEEE_SGE_CHAIN64 is for MPI v2.0 products only */ -typedef MPI2_IEEE_SGE_SIMPLE64 MPI2_IEEE_SGE_CHAIN64; - -typedef union _MPI2_IEEE_SGE_CHAIN_UNION { - MPI2_IEEE_SGE_CHAIN32 Chain32; - MPI2_IEEE_SGE_CHAIN64 Chain64; -} MPI2_IEEE_SGE_CHAIN_UNION, - *PTR_MPI2_IEEE_SGE_CHAIN_UNION, - Mpi2IeeeSgeChainUnion_t, - *pMpi2IeeeSgeChainUnion_t; - -/*MPI25_IEEE_SGE_CHAIN64 is for MPI v2.5 products only */ -typedef struct _MPI25_IEEE_SGE_CHAIN64 { - U64 Address; - U32 Length; - U16 Reserved1; - U8 NextChainOffset; - U8 Flags; -} MPI25_IEEE_SGE_CHAIN64, - *PTR_MPI25_IEEE_SGE_CHAIN64, - Mpi25IeeeSgeChain64_t, - *pMpi25IeeeSgeChain64_t; - -/**************************************************************************** -* All IEEE SGE types union -****************************************************************************/ - -/*MPI2_IEEE_SGE_UNION is for MPI v2.0 products only */ -typedef struct _MPI2_IEEE_SGE_UNION { - union { - MPI2_IEEE_SGE_SIMPLE_UNION Simple; - MPI2_IEEE_SGE_CHAIN_UNION Chain; - } u; -} MPI2_IEEE_SGE_UNION, *PTR_MPI2_IEEE_SGE_UNION, - Mpi2IeeeSgeUnion_t, *pMpi2IeeeSgeUnion_t; - -/**************************************************************************** -* IEEE SGE union for IO SGL's -****************************************************************************/ - -typedef union _MPI25_SGE_IO_UNION { - MPI2_IEEE_SGE_SIMPLE64 IeeeSimple; - MPI25_IEEE_SGE_CHAIN64 IeeeChain; -} MPI25_SGE_IO_UNION, *PTR_MPI25_SGE_IO_UNION, - Mpi25SGEIOUnion_t, *pMpi25SGEIOUnion_t; - -/**************************************************************************** -* IEEE SGE field definitions and masks -****************************************************************************/ - -/*Flags field bit definitions */ - -#define MPI2_IEEE_SGE_FLAGS_ELEMENT_TYPE_MASK (0x80) -#define MPI25_IEEE_SGE_FLAGS_END_OF_LIST (0x40) - -#define MPI2_IEEE32_SGE_FLAGS_SHIFT (24) - -#define MPI2_IEEE32_SGE_LENGTH_MASK (0x00FFFFFF) - -/*Element Type */ - -#define MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT (0x00) -#define MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT (0x80) - -/*Data Location Address Space */ - -#define MPI2_IEEE_SGE_FLAGS_ADDR_MASK (0x03) -#define MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR (0x00) -#define MPI2_IEEE_SGE_FLAGS_IOCDDR_ADDR (0x01) -#define MPI2_IEEE_SGE_FLAGS_IOCPLB_ADDR (0x02) -#define MPI2_IEEE_SGE_FLAGS_IOCPLBNTA_ADDR (0x03) -#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR (0x03) -#define MPI2_IEEE_SGE_FLAGS_SYSTEMPLBCPI_ADDR \ - (MPI2_IEEE_SGE_FLAGS_SYSTEMPLBPCI_ADDR) - -/**************************************************************************** -* IEEE SGE operation Macros -****************************************************************************/ - -/*SIMPLE FlagsLength manipulations... */ -#define MPI2_IEEE32_SGE_SET_FLAGS(f) ((U32)(f) << MPI2_IEEE32_SGE_FLAGS_SHIFT) -#define MPI2_IEEE32_SGE_GET_FLAGS(f) (((f) & ~MPI2_IEEE32_SGE_LENGTH_MASK) \ - >> MPI2_IEEE32_SGE_FLAGS_SHIFT) -#define MPI2_IEEE32_SGE_LENGTH(f) ((f) & MPI2_IEEE32_SGE_LENGTH_MASK) - -#define MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l) (MPI2_IEEE32_SGE_SET_FLAGS(f) |\ - MPI2_IEEE32_SGE_LENGTH(l)) - -#define MPI2_IEEE32_pSGE_GET_FLAGS(psg) \ - MPI2_IEEE32_SGE_GET_FLAGS((psg)->FlagsLength) -#define MPI2_IEEE32_pSGE_GET_LENGTH(psg) \ - MPI2_IEEE32_SGE_LENGTH((psg)->FlagsLength) -#define MPI2_IEEE32_pSGE_SET_FLAGS_LENGTH(psg, f, l) ((psg)->FlagsLength = \ - MPI2_IEEE32_SGE_SET_FLAGS_LENGTH(f, l)) - -/*CAUTION - The following are READ-MODIFY-WRITE! */ -#define MPI2_IEEE32_pSGE_SET_FLAGS(psg, f) ((psg)->FlagsLength |= \ - MPI2_IEEE32_SGE_SET_FLAGS(f)) -#define MPI2_IEEE32_pSGE_SET_LENGTH(psg, l) ((psg)->FlagsLength |= \ - MPI2_IEEE32_SGE_LENGTH(l)) - -/***************************************************************************** -* -* Fusion-MPT MPI/IEEE Scatter Gather Unions -* -*****************************************************************************/ - -typedef union _MPI2_SIMPLE_SGE_UNION { - MPI2_SGE_SIMPLE_UNION MpiSimple; - MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; -} MPI2_SIMPLE_SGE_UNION, *PTR_MPI2_SIMPLE_SGE_UNION, - Mpi2SimpleSgeUntion_t, *pMpi2SimpleSgeUntion_t; - -typedef union _MPI2_SGE_IO_UNION { - MPI2_SGE_SIMPLE_UNION MpiSimple; - MPI2_SGE_CHAIN_UNION MpiChain; - MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; - MPI2_IEEE_SGE_CHAIN_UNION IeeeChain; -} MPI2_SGE_IO_UNION, *PTR_MPI2_SGE_IO_UNION, - Mpi2SGEIOUnion_t, *pMpi2SGEIOUnion_t; - -/**************************************************************************** -* -* Values for SGLFlags field, used in many request messages with an SGL -* -****************************************************************************/ - -/*values for MPI SGL Data Location Address Space subfield */ -#define MPI2_SGLFLAGS_ADDRESS_SPACE_MASK (0x0C) -#define MPI2_SGLFLAGS_SYSTEM_ADDRESS_SPACE (0x00) -#define MPI2_SGLFLAGS_IOCDDR_ADDRESS_SPACE (0x04) -#define MPI2_SGLFLAGS_IOCPLB_ADDRESS_SPACE (0x08) -#define MPI2_SGLFLAGS_IOCPLBNTA_ADDRESS_SPACE (0x0C) -/*values for SGL Type subfield */ -#define MPI2_SGLFLAGS_SGL_TYPE_MASK (0x03) -#define MPI2_SGLFLAGS_SGL_TYPE_MPI (0x00) -#define MPI2_SGLFLAGS_SGL_TYPE_IEEE32 (0x01) -#define MPI2_SGLFLAGS_SGL_TYPE_IEEE64 (0x02) - -#endif diff --git a/addons/mpt3sas/src/4.4.180/mpi/mpi2_cnfg.h b/addons/mpt3sas/src/4.4.180/mpi/mpi2_cnfg.h deleted file mode 100644 index 581fdb37..00000000 --- a/addons/mpt3sas/src/4.4.180/mpi/mpi2_cnfg.h +++ /dev/null @@ -1,3380 +0,0 @@ -/* - * Copyright (c) 2000-2014 LSI Corporation. - * - * - * Name: mpi2_cnfg.h - * Title: MPI Configuration messages and pages - * Creation Date: November 10, 2006 - * - * mpi2_cnfg.h Version: 02.00.29 - * - * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 - * prefix are for use only on MPI v2.5 products, and must not be used - * with MPI v2.0 products. Unless otherwise noted, names beginning with - * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 06-04-07 02.00.01 Added defines for SAS IO Unit Page 2 PhyFlags. - * Added Manufacturing Page 11. - * Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE - * define. - * 06-26-07 02.00.02 Adding generic structure for product-specific - * Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS. - * Rework of BIOS Page 2 configuration page. - * Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the - * forms. - * Added configuration pages IOC Page 8 and Driver - * Persistent Mapping Page 0. - * 08-31-07 02.00.03 Modified configuration pages dealing with Integrated - * RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1, - * RAID Physical Disk Pages 0 and 1, RAID Configuration - * Page 0). - * Added new value for AccessStatus field of SAS Device - * Page 0 (_SATA_NEEDS_INITIALIZATION). - * 10-31-07 02.00.04 Added missing SEPDevHandle field to - * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. - * 12-18-07 02.00.05 Modified IO Unit Page 0 to use 32-bit version fields for - * NVDATA. - * Modified IOC Page 7 to use masks and added field for - * SASBroadcastPrimitiveMasks. - * Added MPI2_CONFIG_PAGE_BIOS_4. - * Added MPI2_CONFIG_PAGE_LOG_0. - * 02-29-08 02.00.06 Modified various names to make them 32-character unique. - * Added SAS Device IDs. - * Updated Integrated RAID configuration pages including - * Manufacturing Page 4, IOC Page 6, and RAID Configuration - * Page 0. - * 05-21-08 02.00.07 Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA. - * Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION. - * Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING. - * Added missing MaxNumRoutedSasAddresses field to - * MPI2_CONFIG_PAGE_EXPANDER_0. - * Added SAS Port Page 0. - * Modified structure layout for - * MPI2_CONFIG_PAGE_DRIVER_MAPPING_0. - * 06-27-08 02.00.08 Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use - * MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array. - * 10-02-08 02.00.09 Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF - * to 0x000000FF. - * Added two new values for the Physical Disk Coercion Size - * bits in the Flags field of Manufacturing Page 4. - * Added product-specific Manufacturing pages 16 to 31. - * Modified Flags bits for controlling write cache on SATA - * drives in IO Unit Page 1. - * Added new bit to AdditionalControlFlags of SAS IO Unit - * Page 1 to control Invalid Topology Correction. - * Added additional defines for RAID Volume Page 0 - * VolumeStatusFlags field. - * Modified meaning of RAID Volume Page 0 VolumeSettings - * define for auto-configure of hot-swap drives. - * Added SupportedPhysDisks field to RAID Volume Page 1 and - * added related defines. - * Added PhysDiskAttributes field (and related defines) to - * RAID Physical Disk Page 0. - * Added MPI2_SAS_PHYINFO_PHY_VACANT define. - * Added three new DiscoveryStatus bits for SAS IO Unit - * Page 0 and SAS Expander Page 0. - * Removed multiplexing information from SAS IO Unit pages. - * Added BootDeviceWaitTime field to SAS IO Unit Page 4. - * Removed Zone Address Resolved bit from PhyInfo and from - * Expander Page 0 Flags field. - * Added two new AccessStatus values to SAS Device Page 0 - * for indicating routing problems. Added 3 reserved words - * to this page. - * 01-19-09 02.00.10 Fixed defines for GPIOVal field of IO Unit Page 3. - * Inserted missing reserved field into structure for IOC - * Page 6. - * Added more pending task bits to RAID Volume Page 0 - * VolumeStatusFlags defines. - * Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define. - * Added a new DiscoveryStatus bit for SAS IO Unit Page 0 - * and SAS Expander Page 0 to flag a downstream initiator - * when in simplified routing mode. - * Removed SATA Init Failure defines for DiscoveryStatus - * fields of SAS IO Unit Page 0 and SAS Expander Page 0. - * Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define. - * Added PortGroups, DmaGroup, and ControlGroup fields to - * SAS Device Page 0. - * 05-06-09 02.00.11 Added structures and defines for IO Unit Page 5 and IO - * Unit Page 6. - * Added expander reduced functionality data to SAS - * Expander Page 0. - * Added SAS PHY Page 2 and SAS PHY Page 3. - * 07-30-09 02.00.12 Added IO Unit Page 7. - * Added new device ids. - * Added SAS IO Unit Page 5. - * Added partial and slumber power management capable flags - * to SAS Device Page 0 Flags field. - * Added PhyInfo defines for power condition. - * Added Ethernet configuration pages. - * 10-28-09 02.00.13 Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY. - * Added SAS PHY Page 4 structure and defines. - * 02-10-10 02.00.14 Modified the comments for the configuration page - * structures that contain an array of data. The host - * should use the "count" field in the page data (e.g. the - * NumPhys field) to determine the number of valid elements - * in the array. - * Added/modified some MPI2_MFGPAGE_DEVID_SAS defines. - * Added PowerManagementCapabilities to IO Unit Page 7. - * Added PortWidthModGroup field to - * MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS. - * Added MPI2_CONFIG_PAGE_SASIOUNIT_6 and related defines. - * Added MPI2_CONFIG_PAGE_SASIOUNIT_7 and related defines. - * Added MPI2_CONFIG_PAGE_SASIOUNIT_8 and related defines. - * 05-12-10 02.00.15 Added MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT - * define. - * Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define. - * Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define. - * 08-11-10 02.00.16 Removed IO Unit Page 1 device path (multi-pathing) - * defines. - * 11-10-10 02.00.17 Added ReceptacleID field (replacing Reserved1) to - * MPI2_MANPAGE7_CONNECTOR_INFO and reworked defines for - * the Pinout field. - * Added BoardTemperature and BoardTemperatureUnits fields - * to MPI2_CONFIG_PAGE_IO_UNIT_7. - * Added MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING define - * and MPI2_CONFIG_PAGE_EXT_MAN_PS structure. - * 02-23-11 02.00.18 Added ProxyVF_ID field to MPI2_CONFIG_REQUEST. - * Added IO Unit Page 8, IO Unit Page 9, - * and IO Unit Page 10. - * Added SASNotifyPrimitiveMasks field to - * MPI2_CONFIG_PAGE_IOC_7. - * 03-09-11 02.00.19 Fixed IO Unit Page 10 (to match the spec). - * 05-25-11 02.00.20 Cleaned up a few comments. - * 08-24-11 02.00.21 Marked the IO Unit Page 7 PowerManagementCapabilities - * for PCIe link as obsolete. - * Added SpinupFlags field containing a Disable Spin-up bit - * to the MPI2_SAS_IOUNIT4_SPINUP_GROUP fields of SAS IO - * Unit Page 4. - * 11-18-11 02.00.22 Added define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT. - * Added UEFIVersion field to BIOS Page 1 and defined new - * BiosOptions bits. - * Incorporating additions for MPI v2.5. - * 11-27-12 02.00.23 Added MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER. - * Added MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID. - * 12-20-12 02.00.24 Marked MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION as - * obsolete for MPI v2.5 and later. - * Added some defines for 12G SAS speeds. - * 04-09-13 02.00.25 Added MPI2_IOUNITPAGE1_ATA_SECURITY_FREEZE_LOCK. - * Fixed MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS to - * match the specification. - * 08-19-13 02.00.26 Added reserved words to MPI2_CONFIG_PAGE_IO_UNIT_7 for - * future use. - * 12-05-13 02.00.27 Added MPI2_MANPAGE7_FLAG_BASE_ENCLOSURE_LEVEL for - * MPI2_CONFIG_PAGE_MAN_7. - * Added EnclosureLevel and ConnectorName fields to - * MPI2_CONFIG_PAGE_SAS_DEV_0. - * Added MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID for - * MPI2_CONFIG_PAGE_SAS_DEV_0. - * Added EnclosureLevel field to - * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. - * Added MPI2_SAS_ENCLS0_FLAGS_ENCL_LEVEL_VALID for - * MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0. - * 01-08-14 02.00.28 Added more defines for the BiosOptions field of - * MPI2_CONFIG_PAGE_BIOS_1. - * 06-13-14 02.00.29 Added SSUTimeout field to MPI2_CONFIG_PAGE_BIOS_1, and - * more defines for the BiosOptions field.. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_CNFG_H -#define MPI2_CNFG_H - -/***************************************************************************** -* Configuration Page Header and defines -*****************************************************************************/ - -/*Config Page Header */ -typedef struct _MPI2_CONFIG_PAGE_HEADER { - U8 PageVersion; /*0x00 */ - U8 PageLength; /*0x01 */ - U8 PageNumber; /*0x02 */ - U8 PageType; /*0x03 */ -} MPI2_CONFIG_PAGE_HEADER, *PTR_MPI2_CONFIG_PAGE_HEADER, - Mpi2ConfigPageHeader_t, *pMpi2ConfigPageHeader_t; - -typedef union _MPI2_CONFIG_PAGE_HEADER_UNION { - MPI2_CONFIG_PAGE_HEADER Struct; - U8 Bytes[4]; - U16 Word16[2]; - U32 Word32; -} MPI2_CONFIG_PAGE_HEADER_UNION, *PTR_MPI2_CONFIG_PAGE_HEADER_UNION, - Mpi2ConfigPageHeaderUnion, *pMpi2ConfigPageHeaderUnion; - -/*Extended Config Page Header */ -typedef struct _MPI2_CONFIG_EXTENDED_PAGE_HEADER { - U8 PageVersion; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 PageNumber; /*0x02 */ - U8 PageType; /*0x03 */ - U16 ExtPageLength; /*0x04 */ - U8 ExtPageType; /*0x06 */ - U8 Reserved2; /*0x07 */ -} MPI2_CONFIG_EXTENDED_PAGE_HEADER, - *PTR_MPI2_CONFIG_EXTENDED_PAGE_HEADER, - Mpi2ConfigExtendedPageHeader_t, - *pMpi2ConfigExtendedPageHeader_t; - -typedef union _MPI2_CONFIG_EXT_PAGE_HEADER_UNION { - MPI2_CONFIG_PAGE_HEADER Struct; - MPI2_CONFIG_EXTENDED_PAGE_HEADER Ext; - U8 Bytes[8]; - U16 Word16[4]; - U32 Word32[2]; -} MPI2_CONFIG_EXT_PAGE_HEADER_UNION, - *PTR_MPI2_CONFIG_EXT_PAGE_HEADER_UNION, - Mpi2ConfigPageExtendedHeaderUnion, - *pMpi2ConfigPageExtendedHeaderUnion; - - -/*PageType field values */ -#define MPI2_CONFIG_PAGEATTR_READ_ONLY (0x00) -#define MPI2_CONFIG_PAGEATTR_CHANGEABLE (0x10) -#define MPI2_CONFIG_PAGEATTR_PERSISTENT (0x20) -#define MPI2_CONFIG_PAGEATTR_MASK (0xF0) - -#define MPI2_CONFIG_PAGETYPE_IO_UNIT (0x00) -#define MPI2_CONFIG_PAGETYPE_IOC (0x01) -#define MPI2_CONFIG_PAGETYPE_BIOS (0x02) -#define MPI2_CONFIG_PAGETYPE_RAID_VOLUME (0x08) -#define MPI2_CONFIG_PAGETYPE_MANUFACTURING (0x09) -#define MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK (0x0A) -#define MPI2_CONFIG_PAGETYPE_EXTENDED (0x0F) -#define MPI2_CONFIG_PAGETYPE_MASK (0x0F) - -#define MPI2_CONFIG_TYPENUM_MASK (0x0FFF) - - -/*ExtPageType field values */ -#define MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT (0x10) -#define MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER (0x11) -#define MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE (0x12) -#define MPI2_CONFIG_EXTPAGETYPE_SAS_PHY (0x13) -#define MPI2_CONFIG_EXTPAGETYPE_LOG (0x14) -#define MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE (0x15) -#define MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG (0x16) -#define MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING (0x17) -#define MPI2_CONFIG_EXTPAGETYPE_SAS_PORT (0x18) -#define MPI2_CONFIG_EXTPAGETYPE_ETHERNET (0x19) -#define MPI2_CONFIG_EXTPAGETYPE_EXT_MANUFACTURING (0x1A) - - -/***************************************************************************** -* PageAddress defines -*****************************************************************************/ - -/*RAID Volume PageAddress format */ -#define MPI2_RAID_VOLUME_PGAD_FORM_MASK (0xF0000000) -#define MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) -#define MPI2_RAID_VOLUME_PGAD_FORM_HANDLE (0x10000000) - -#define MPI2_RAID_VOLUME_PGAD_HANDLE_MASK (0x0000FFFF) - - -/*RAID Physical Disk PageAddress format */ -#define MPI2_PHYSDISK_PGAD_FORM_MASK (0xF0000000) -#define MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM (0x00000000) -#define MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM (0x10000000) -#define MPI2_PHYSDISK_PGAD_FORM_DEVHANDLE (0x20000000) - -#define MPI2_PHYSDISK_PGAD_PHYSDISKNUM_MASK (0x000000FF) -#define MPI2_PHYSDISK_PGAD_DEVHANDLE_MASK (0x0000FFFF) - - -/*SAS Expander PageAddress format */ -#define MPI2_SAS_EXPAND_PGAD_FORM_MASK (0xF0000000) -#define MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL (0x00000000) -#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM (0x10000000) -#define MPI2_SAS_EXPAND_PGAD_FORM_HNDL (0x20000000) - -#define MPI2_SAS_EXPAND_PGAD_HANDLE_MASK (0x0000FFFF) -#define MPI2_SAS_EXPAND_PGAD_PHYNUM_MASK (0x00FF0000) -#define MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT (16) - - -/*SAS Device PageAddress format */ -#define MPI2_SAS_DEVICE_PGAD_FORM_MASK (0xF0000000) -#define MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) -#define MPI2_SAS_DEVICE_PGAD_FORM_HANDLE (0x20000000) - -#define MPI2_SAS_DEVICE_PGAD_HANDLE_MASK (0x0000FFFF) - - -/*SAS PHY PageAddress format */ -#define MPI2_SAS_PHY_PGAD_FORM_MASK (0xF0000000) -#define MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER (0x00000000) -#define MPI2_SAS_PHY_PGAD_FORM_PHY_TBL_INDEX (0x10000000) - -#define MPI2_SAS_PHY_PGAD_PHY_NUMBER_MASK (0x000000FF) -#define MPI2_SAS_PHY_PGAD_PHY_TBL_INDEX_MASK (0x0000FFFF) - - -/*SAS Port PageAddress format */ -#define MPI2_SASPORT_PGAD_FORM_MASK (0xF0000000) -#define MPI2_SASPORT_PGAD_FORM_GET_NEXT_PORT (0x00000000) -#define MPI2_SASPORT_PGAD_FORM_PORT_NUM (0x10000000) - -#define MPI2_SASPORT_PGAD_PORTNUMBER_MASK (0x00000FFF) - - -/*SAS Enclosure PageAddress format */ -#define MPI2_SAS_ENCLOS_PGAD_FORM_MASK (0xF0000000) -#define MPI2_SAS_ENCLOS_PGAD_FORM_GET_NEXT_HANDLE (0x00000000) -#define MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE (0x10000000) - -#define MPI2_SAS_ENCLOS_PGAD_HANDLE_MASK (0x0000FFFF) - - -/*RAID Configuration PageAddress format */ -#define MPI2_RAID_PGAD_FORM_MASK (0xF0000000) -#define MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM (0x00000000) -#define MPI2_RAID_PGAD_FORM_CONFIGNUM (0x10000000) -#define MPI2_RAID_PGAD_FORM_ACTIVE_CONFIG (0x20000000) - -#define MPI2_RAID_PGAD_CONFIGNUM_MASK (0x000000FF) - - -/*Driver Persistent Mapping PageAddress format */ -#define MPI2_DPM_PGAD_FORM_MASK (0xF0000000) -#define MPI2_DPM_PGAD_FORM_ENTRY_RANGE (0x00000000) - -#define MPI2_DPM_PGAD_ENTRY_COUNT_MASK (0x0FFF0000) -#define MPI2_DPM_PGAD_ENTRY_COUNT_SHIFT (16) -#define MPI2_DPM_PGAD_START_ENTRY_MASK (0x0000FFFF) - - -/*Ethernet PageAddress format */ -#define MPI2_ETHERNET_PGAD_FORM_MASK (0xF0000000) -#define MPI2_ETHERNET_PGAD_FORM_IF_NUM (0x00000000) - -#define MPI2_ETHERNET_PGAD_IF_NUMBER_MASK (0x000000FF) - - - -/**************************************************************************** -* Configuration messages -****************************************************************************/ - -/*Configuration Request Message */ -typedef struct _MPI2_CONFIG_REQUEST { - U8 Action; /*0x00 */ - U8 SGLFlags; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 ExtPageLength; /*0x04 */ - U8 ExtPageType; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U8 Reserved2; /*0x0C */ - U8 ProxyVF_ID; /*0x0D */ - U16 Reserved4; /*0x0E */ - U32 Reserved3; /*0x10 */ - MPI2_CONFIG_PAGE_HEADER Header; /*0x14 */ - U32 PageAddress; /*0x18 */ - MPI2_SGE_IO_UNION PageBufferSGE; /*0x1C */ -} MPI2_CONFIG_REQUEST, *PTR_MPI2_CONFIG_REQUEST, - Mpi2ConfigRequest_t, *pMpi2ConfigRequest_t; - -/*values for the Action field */ -#define MPI2_CONFIG_ACTION_PAGE_HEADER (0x00) -#define MPI2_CONFIG_ACTION_PAGE_READ_CURRENT (0x01) -#define MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT (0x02) -#define MPI2_CONFIG_ACTION_PAGE_DEFAULT (0x03) -#define MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM (0x04) -#define MPI2_CONFIG_ACTION_PAGE_READ_DEFAULT (0x05) -#define MPI2_CONFIG_ACTION_PAGE_READ_NVRAM (0x06) -#define MPI2_CONFIG_ACTION_PAGE_GET_CHANGEABLE (0x07) - -/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ - - -/*Config Reply Message */ -typedef struct _MPI2_CONFIG_REPLY { - U8 Action; /*0x00 */ - U8 SGLFlags; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 ExtPageLength; /*0x04 */ - U8 ExtPageType; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U16 Reserved2; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - MPI2_CONFIG_PAGE_HEADER Header; /*0x14 */ -} MPI2_CONFIG_REPLY, *PTR_MPI2_CONFIG_REPLY, - Mpi2ConfigReply_t, *pMpi2ConfigReply_t; - - - -/***************************************************************************** -* -* C o n f i g u r a t i o n P a g e s -* -*****************************************************************************/ - -/**************************************************************************** -* Manufacturing Config pages -****************************************************************************/ - -#define MPI2_MFGPAGE_VENDORID_LSI (0x1000) - -/*MPI v2.0 SAS products */ -#define MPI2_MFGPAGE_DEVID_SAS2004 (0x0070) -#define MPI2_MFGPAGE_DEVID_SAS2008 (0x0072) -#define MPI2_MFGPAGE_DEVID_SAS2108_1 (0x0074) -#define MPI2_MFGPAGE_DEVID_SAS2108_2 (0x0076) -#define MPI2_MFGPAGE_DEVID_SAS2108_3 (0x0077) -#define MPI2_MFGPAGE_DEVID_SAS2116_1 (0x0064) -#define MPI2_MFGPAGE_DEVID_SAS2116_2 (0x0065) - -#define MPI2_MFGPAGE_DEVID_SSS6200 (0x007E) - -#define MPI2_MFGPAGE_DEVID_SAS2208_1 (0x0080) -#define MPI2_MFGPAGE_DEVID_SAS2208_2 (0x0081) -#define MPI2_MFGPAGE_DEVID_SAS2208_3 (0x0082) -#define MPI2_MFGPAGE_DEVID_SAS2208_4 (0x0083) -#define MPI2_MFGPAGE_DEVID_SAS2208_5 (0x0084) -#define MPI2_MFGPAGE_DEVID_SAS2208_6 (0x0085) -#define MPI2_MFGPAGE_DEVID_SAS2308_1 (0x0086) -#define MPI2_MFGPAGE_DEVID_SAS2308_2 (0x0087) -#define MPI2_MFGPAGE_DEVID_SAS2308_3 (0x006E) - -/*MPI v2.5 SAS products */ -#define MPI25_MFGPAGE_DEVID_SAS3004 (0x0096) -#define MPI25_MFGPAGE_DEVID_SAS3008 (0x0097) -#define MPI25_MFGPAGE_DEVID_SAS3108_1 (0x0090) -#define MPI25_MFGPAGE_DEVID_SAS3108_2 (0x0091) -#define MPI25_MFGPAGE_DEVID_SAS3108_5 (0x0094) -#define MPI25_MFGPAGE_DEVID_SAS3108_6 (0x0095) - - - - -/*Manufacturing Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_MAN_0 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 ChipName[16]; /*0x04 */ - U8 ChipRevision[8]; /*0x14 */ - U8 BoardName[16]; /*0x1C */ - U8 BoardAssembly[16]; /*0x2C */ - U8 BoardTracerNumber[16]; /*0x3C */ -} MPI2_CONFIG_PAGE_MAN_0, - *PTR_MPI2_CONFIG_PAGE_MAN_0, - Mpi2ManufacturingPage0_t, - *pMpi2ManufacturingPage0_t; - -#define MPI2_MANUFACTURING0_PAGEVERSION (0x00) - - -/*Manufacturing Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_MAN_1 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 VPD[256]; /*0x04 */ -} MPI2_CONFIG_PAGE_MAN_1, - *PTR_MPI2_CONFIG_PAGE_MAN_1, - Mpi2ManufacturingPage1_t, - *pMpi2ManufacturingPage1_t; - -#define MPI2_MANUFACTURING1_PAGEVERSION (0x00) - - -typedef struct _MPI2_CHIP_REVISION_ID { - U16 DeviceID; /*0x00 */ - U8 PCIRevisionID; /*0x02 */ - U8 Reserved; /*0x03 */ -} MPI2_CHIP_REVISION_ID, *PTR_MPI2_CHIP_REVISION_ID, - Mpi2ChipRevisionId_t, *pMpi2ChipRevisionId_t; - - -/*Manufacturing Page 2 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check Header.PageLength at runtime. - */ -#ifndef MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS -#define MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_MAN_2 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - MPI2_CHIP_REVISION_ID ChipId; /*0x04 */ - U32 - HwSettings[MPI2_MAN_PAGE_2_HW_SETTINGS_WORDS];/*0x08 */ -} MPI2_CONFIG_PAGE_MAN_2, - *PTR_MPI2_CONFIG_PAGE_MAN_2, - Mpi2ManufacturingPage2_t, - *pMpi2ManufacturingPage2_t; - -#define MPI2_MANUFACTURING2_PAGEVERSION (0x00) - - -/*Manufacturing Page 3 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check Header.PageLength at runtime. - */ -#ifndef MPI2_MAN_PAGE_3_INFO_WORDS -#define MPI2_MAN_PAGE_3_INFO_WORDS (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_MAN_3 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - MPI2_CHIP_REVISION_ID ChipId; /*0x04 */ - U32 - Info[MPI2_MAN_PAGE_3_INFO_WORDS];/*0x08 */ -} MPI2_CONFIG_PAGE_MAN_3, - *PTR_MPI2_CONFIG_PAGE_MAN_3, - Mpi2ManufacturingPage3_t, - *pMpi2ManufacturingPage3_t; - -#define MPI2_MANUFACTURING3_PAGEVERSION (0x00) - - -/*Manufacturing Page 4 */ - -typedef struct _MPI2_MANPAGE4_PWR_SAVE_SETTINGS { - U8 PowerSaveFlags; /*0x00 */ - U8 InternalOperationsSleepTime; /*0x01 */ - U8 InternalOperationsRunTime; /*0x02 */ - U8 HostIdleTime; /*0x03 */ -} MPI2_MANPAGE4_PWR_SAVE_SETTINGS, - *PTR_MPI2_MANPAGE4_PWR_SAVE_SETTINGS, - Mpi2ManPage4PwrSaveSettings_t, - *pMpi2ManPage4PwrSaveSettings_t; - -/*defines for the PowerSaveFlags field */ -#define MPI2_MANPAGE4_MASK_POWERSAVE_MODE (0x03) -#define MPI2_MANPAGE4_POWERSAVE_MODE_DISABLED (0x00) -#define MPI2_MANPAGE4_CUSTOM_POWERSAVE_MODE (0x01) -#define MPI2_MANPAGE4_FULL_POWERSAVE_MODE (0x02) - -typedef struct _MPI2_CONFIG_PAGE_MAN_4 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Flags; /*0x08 */ - U8 InquirySize; /*0x0C */ - U8 Reserved2; /*0x0D */ - U16 Reserved3; /*0x0E */ - U8 InquiryData[56]; /*0x10 */ - U32 RAID0VolumeSettings; /*0x48 */ - U32 RAID1EVolumeSettings; /*0x4C */ - U32 RAID1VolumeSettings; /*0x50 */ - U32 RAID10VolumeSettings; /*0x54 */ - U32 Reserved4; /*0x58 */ - U32 Reserved5; /*0x5C */ - MPI2_MANPAGE4_PWR_SAVE_SETTINGS PowerSaveSettings; /*0x60 */ - U8 MaxOCEDisks; /*0x64 */ - U8 ResyncRate; /*0x65 */ - U16 DataScrubDuration; /*0x66 */ - U8 MaxHotSpares; /*0x68 */ - U8 MaxPhysDisksPerVol; /*0x69 */ - U8 MaxPhysDisks; /*0x6A */ - U8 MaxVolumes; /*0x6B */ -} MPI2_CONFIG_PAGE_MAN_4, - *PTR_MPI2_CONFIG_PAGE_MAN_4, - Mpi2ManufacturingPage4_t, - *pMpi2ManufacturingPage4_t; - -#define MPI2_MANUFACTURING4_PAGEVERSION (0x0A) - -/*Manufacturing Page 4 Flags field */ -#define MPI2_MANPAGE4_METADATA_SIZE_MASK (0x00030000) -#define MPI2_MANPAGE4_METADATA_512MB (0x00000000) - -#define MPI2_MANPAGE4_MIX_SSD_SAS_SATA (0x00008000) -#define MPI2_MANPAGE4_MIX_SSD_AND_NON_SSD (0x00004000) -#define MPI2_MANPAGE4_HIDE_PHYSDISK_NON_IR (0x00002000) - -#define MPI2_MANPAGE4_MASK_PHYSDISK_COERCION (0x00001C00) -#define MPI2_MANPAGE4_PHYSDISK_COERCION_1GB (0x00000000) -#define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION (0x00000400) -#define MPI2_MANPAGE4_PHYSDISK_ADAPTIVE_COERCION (0x00000800) -#define MPI2_MANPAGE4_PHYSDISK_ZERO_COERCION (0x00000C00) - -#define MPI2_MANPAGE4_MASK_BAD_BLOCK_MARKING (0x00000300) -#define MPI2_MANPAGE4_DEFAULT_BAD_BLOCK_MARKING (0x00000000) -#define MPI2_MANPAGE4_TABLE_BAD_BLOCK_MARKING (0x00000100) -#define MPI2_MANPAGE4_WRITE_LONG_BAD_BLOCK_MARKING (0x00000200) - -#define MPI2_MANPAGE4_FORCE_OFFLINE_FAILOVER (0x00000080) -#define MPI2_MANPAGE4_RAID10_DISABLE (0x00000040) -#define MPI2_MANPAGE4_RAID1E_DISABLE (0x00000020) -#define MPI2_MANPAGE4_RAID1_DISABLE (0x00000010) -#define MPI2_MANPAGE4_RAID0_DISABLE (0x00000008) -#define MPI2_MANPAGE4_IR_MODEPAGE8_DISABLE (0x00000004) -#define MPI2_MANPAGE4_IM_RESYNC_CACHE_ENABLE (0x00000002) -#define MPI2_MANPAGE4_IR_NO_MIX_SAS_SATA (0x00000001) - - -/*Manufacturing Page 5 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_MAN_PAGE_5_PHY_ENTRIES -#define MPI2_MAN_PAGE_5_PHY_ENTRIES (1) -#endif - -typedef struct _MPI2_MANUFACTURING5_ENTRY { - U64 WWID; /*0x00 */ - U64 DeviceName; /*0x08 */ -} MPI2_MANUFACTURING5_ENTRY, - *PTR_MPI2_MANUFACTURING5_ENTRY, - Mpi2Manufacturing5Entry_t, - *pMpi2Manufacturing5Entry_t; - -typedef struct _MPI2_CONFIG_PAGE_MAN_5 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 NumPhys; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 Reserved2; /*0x06 */ - U32 Reserved3; /*0x08 */ - U32 Reserved4; /*0x0C */ - MPI2_MANUFACTURING5_ENTRY - Phy[MPI2_MAN_PAGE_5_PHY_ENTRIES];/*0x08 */ -} MPI2_CONFIG_PAGE_MAN_5, - *PTR_MPI2_CONFIG_PAGE_MAN_5, - Mpi2ManufacturingPage5_t, - *pMpi2ManufacturingPage5_t; - -#define MPI2_MANUFACTURING5_PAGEVERSION (0x03) - - -/*Manufacturing Page 6 */ - -typedef struct _MPI2_CONFIG_PAGE_MAN_6 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 ProductSpecificInfo;/*0x04 */ -} MPI2_CONFIG_PAGE_MAN_6, - *PTR_MPI2_CONFIG_PAGE_MAN_6, - Mpi2ManufacturingPage6_t, - *pMpi2ManufacturingPage6_t; - -#define MPI2_MANUFACTURING6_PAGEVERSION (0x00) - - -/*Manufacturing Page 7 */ - -typedef struct _MPI2_MANPAGE7_CONNECTOR_INFO { - U32 Pinout; /*0x00 */ - U8 Connector[16]; /*0x04 */ - U8 Location; /*0x14 */ - U8 ReceptacleID; /*0x15 */ - U16 Slot; /*0x16 */ - U32 Reserved2; /*0x18 */ -} MPI2_MANPAGE7_CONNECTOR_INFO, - *PTR_MPI2_MANPAGE7_CONNECTOR_INFO, - Mpi2ManPage7ConnectorInfo_t, - *pMpi2ManPage7ConnectorInfo_t; - -/*defines for the Pinout field */ -#define MPI2_MANPAGE7_PINOUT_LANE_MASK (0x0000FF00) -#define MPI2_MANPAGE7_PINOUT_LANE_SHIFT (8) - -#define MPI2_MANPAGE7_PINOUT_TYPE_MASK (0x000000FF) -#define MPI2_MANPAGE7_PINOUT_TYPE_UNKNOWN (0x00) -#define MPI2_MANPAGE7_PINOUT_SATA_SINGLE (0x01) -#define MPI2_MANPAGE7_PINOUT_SFF_8482 (0x02) -#define MPI2_MANPAGE7_PINOUT_SFF_8486 (0x03) -#define MPI2_MANPAGE7_PINOUT_SFF_8484 (0x04) -#define MPI2_MANPAGE7_PINOUT_SFF_8087 (0x05) -#define MPI2_MANPAGE7_PINOUT_SFF_8643_4I (0x06) -#define MPI2_MANPAGE7_PINOUT_SFF_8643_8I (0x07) -#define MPI2_MANPAGE7_PINOUT_SFF_8470 (0x08) -#define MPI2_MANPAGE7_PINOUT_SFF_8088 (0x09) -#define MPI2_MANPAGE7_PINOUT_SFF_8644_4X (0x0A) -#define MPI2_MANPAGE7_PINOUT_SFF_8644_8X (0x0B) -#define MPI2_MANPAGE7_PINOUT_SFF_8644_16X (0x0C) -#define MPI2_MANPAGE7_PINOUT_SFF_8436 (0x0D) - -/*defines for the Location field */ -#define MPI2_MANPAGE7_LOCATION_UNKNOWN (0x01) -#define MPI2_MANPAGE7_LOCATION_INTERNAL (0x02) -#define MPI2_MANPAGE7_LOCATION_EXTERNAL (0x04) -#define MPI2_MANPAGE7_LOCATION_SWITCHABLE (0x08) -#define MPI2_MANPAGE7_LOCATION_AUTO (0x10) -#define MPI2_MANPAGE7_LOCATION_NOT_PRESENT (0x20) -#define MPI2_MANPAGE7_LOCATION_NOT_CONNECTED (0x80) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_MANPAGE7_CONNECTOR_INFO_MAX -#define MPI2_MANPAGE7_CONNECTOR_INFO_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_MAN_7 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Reserved2; /*0x08 */ - U32 Flags; /*0x0C */ - U8 EnclosureName[16]; /*0x10 */ - U8 NumPhys; /*0x20 */ - U8 Reserved3; /*0x21 */ - U16 Reserved4; /*0x22 */ - MPI2_MANPAGE7_CONNECTOR_INFO - ConnectorInfo[MPI2_MANPAGE7_CONNECTOR_INFO_MAX]; /*0x24 */ -} MPI2_CONFIG_PAGE_MAN_7, - *PTR_MPI2_CONFIG_PAGE_MAN_7, - Mpi2ManufacturingPage7_t, - *pMpi2ManufacturingPage7_t; - -#define MPI2_MANUFACTURING7_PAGEVERSION (0x01) - -/*defines for the Flags field */ -#define MPI2_MANPAGE7_FLAG_BASE_ENCLOSURE_LEVEL (0x00000008) -#define MPI2_MANPAGE7_FLAG_EVENTREPLAY_SLOT_ORDER (0x00000002) -#define MPI2_MANPAGE7_FLAG_USE_SLOT_INFO (0x00000001) - - -/* - *Generic structure to use for product-specific manufacturing pages - *(currently Manufacturing Page 8 through Manufacturing Page 31). - */ - -typedef struct _MPI2_CONFIG_PAGE_MAN_PS { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 ProductSpecificInfo;/*0x04 */ -} MPI2_CONFIG_PAGE_MAN_PS, - *PTR_MPI2_CONFIG_PAGE_MAN_PS, - Mpi2ManufacturingPagePS_t, - *pMpi2ManufacturingPagePS_t; - -#define MPI2_MANUFACTURING8_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING9_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING10_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING11_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING12_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING13_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING14_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING15_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING16_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING17_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING18_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING19_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING20_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING21_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING22_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING23_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING24_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING25_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING26_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING27_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING28_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING29_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING30_PAGEVERSION (0x00) -#define MPI2_MANUFACTURING31_PAGEVERSION (0x00) - - -/**************************************************************************** -* IO Unit Config Pages -****************************************************************************/ - -/*IO Unit Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_0 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U64 UniqueValue; /*0x04 */ - MPI2_VERSION_UNION NvdataVersionDefault; /*0x08 */ - MPI2_VERSION_UNION NvdataVersionPersistent; /*0x0A */ -} MPI2_CONFIG_PAGE_IO_UNIT_0, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_0, - Mpi2IOUnitPage0_t, *pMpi2IOUnitPage0_t; - -#define MPI2_IOUNITPAGE0_PAGEVERSION (0x02) - - -/*IO Unit Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_1 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Flags; /*0x04 */ -} MPI2_CONFIG_PAGE_IO_UNIT_1, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_1, - Mpi2IOUnitPage1_t, *pMpi2IOUnitPage1_t; - -#define MPI2_IOUNITPAGE1_PAGEVERSION (0x04) - -/*IO Unit Page 1 Flags defines */ -#define MPI2_IOUNITPAGE1_ATA_SECURITY_FREEZE_LOCK (0x00004000) -#define MPI25_IOUNITPAGE1_NEW_DEVICE_FAST_PATH_DISABLE (0x00002000) -#define MPI25_IOUNITPAGE1_DISABLE_FAST_PATH (0x00001000) -#define MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY (0x00000800) -#define MPI2_IOUNITPAGE1_MASK_SATA_WRITE_CACHE (0x00000600) -#define MPI2_IOUNITPAGE1_SATA_WRITE_CACHE_SHIFT (9) -#define MPI2_IOUNITPAGE1_ENABLE_SATA_WRITE_CACHE (0x00000000) -#define MPI2_IOUNITPAGE1_DISABLE_SATA_WRITE_CACHE (0x00000200) -#define MPI2_IOUNITPAGE1_UNCHANGED_SATA_WRITE_CACHE (0x00000400) -#define MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE (0x00000100) -#define MPI2_IOUNITPAGE1_DISABLE_IR (0x00000040) -#define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020) -#define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID (0x00000004) - - -/*IO Unit Page 3 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for GPIOCount at runtime. - */ -#ifndef MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX -#define MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_3 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 GPIOCount; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 Reserved2; /*0x06 */ - U16 - GPIOVal[MPI2_IO_UNIT_PAGE_3_GPIO_VAL_MAX];/*0x08 */ -} MPI2_CONFIG_PAGE_IO_UNIT_3, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_3, - Mpi2IOUnitPage3_t, *pMpi2IOUnitPage3_t; - -#define MPI2_IOUNITPAGE3_PAGEVERSION (0x01) - -/*defines for IO Unit Page 3 GPIOVal field */ -#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_MASK (0xFFFC) -#define MPI2_IOUNITPAGE3_GPIO_FUNCTION_SHIFT (2) -#define MPI2_IOUNITPAGE3_GPIO_SETTING_OFF (0x0000) -#define MPI2_IOUNITPAGE3_GPIO_SETTING_ON (0x0001) - - -/*IO Unit Page 5 */ - -/* - *Upper layer code (drivers, utilities, etc.) should leave this define set to - *one and check the value returned for NumDmaEngines at runtime. - */ -#ifndef MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES -#define MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_5 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U64 - RaidAcceleratorBufferBaseAddress; /*0x04 */ - U64 - RaidAcceleratorBufferSize; /*0x0C */ - U64 - RaidAcceleratorControlBaseAddress; /*0x14 */ - U8 RAControlSize; /*0x1C */ - U8 NumDmaEngines; /*0x1D */ - U8 RAMinControlSize; /*0x1E */ - U8 RAMaxControlSize; /*0x1F */ - U32 Reserved1; /*0x20 */ - U32 Reserved2; /*0x24 */ - U32 Reserved3; /*0x28 */ - U32 - DmaEngineCapabilities[MPI2_IOUNITPAGE5_DMAENGINE_ENTRIES]; /*0x2C */ -} MPI2_CONFIG_PAGE_IO_UNIT_5, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_5, - Mpi2IOUnitPage5_t, *pMpi2IOUnitPage5_t; - -#define MPI2_IOUNITPAGE5_PAGEVERSION (0x00) - -/*defines for IO Unit Page 5 DmaEngineCapabilities field */ -#define MPI2_IOUNITPAGE5_DMA_CAP_MASK_MAX_REQUESTS (0xFFFF0000) -#define MPI2_IOUNITPAGE5_DMA_CAP_SHIFT_MAX_REQUESTS (16) - -#define MPI2_IOUNITPAGE5_DMA_CAP_EEDP (0x0008) -#define MPI2_IOUNITPAGE5_DMA_CAP_PARITY_GENERATION (0x0004) -#define MPI2_IOUNITPAGE5_DMA_CAP_HASHING (0x0002) -#define MPI2_IOUNITPAGE5_DMA_CAP_ENCRYPTION (0x0001) - - -/*IO Unit Page 6 */ - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_6 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U16 Flags; /*0x04 */ - U8 RAHostControlSize; /*0x06 */ - U8 Reserved0; /*0x07 */ - U64 - RaidAcceleratorHostControlBaseAddress; /*0x08 */ - U32 Reserved1; /*0x10 */ - U32 Reserved2; /*0x14 */ - U32 Reserved3; /*0x18 */ -} MPI2_CONFIG_PAGE_IO_UNIT_6, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_6, - Mpi2IOUnitPage6_t, *pMpi2IOUnitPage6_t; - -#define MPI2_IOUNITPAGE6_PAGEVERSION (0x00) - -/*defines for IO Unit Page 6 Flags field */ -#define MPI2_IOUNITPAGE6_FLAGS_ENABLE_RAID_ACCELERATOR (0x0001) - - -/*IO Unit Page 7 */ - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_7 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 CurrentPowerMode; /*0x04 */ - U8 PreviousPowerMode; /*0x05 */ - U8 PCIeWidth; /*0x06 */ - U8 PCIeSpeed; /*0x07 */ - U32 ProcessorState; /*0x08 */ - U32 - PowerManagementCapabilities; /*0x0C */ - U16 IOCTemperature; /*0x10 */ - U8 - IOCTemperatureUnits; /*0x12 */ - U8 IOCSpeed; /*0x13 */ - U16 BoardTemperature; /*0x14 */ - U8 - BoardTemperatureUnits; /*0x16 */ - U8 Reserved3; /*0x17 */ - U32 Reserved4; /* 0x18 */ - U32 Reserved5; /* 0x1C */ - U32 Reserved6; /* 0x20 */ - U32 Reserved7; /* 0x24 */ -} MPI2_CONFIG_PAGE_IO_UNIT_7, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_7, - Mpi2IOUnitPage7_t, *pMpi2IOUnitPage7_t; - -#define MPI2_IOUNITPAGE7_PAGEVERSION (0x04) - -/*defines for IO Unit Page 7 CurrentPowerMode and PreviousPowerMode fields */ -#define MPI25_IOUNITPAGE7_PM_INIT_MASK (0xC0) -#define MPI25_IOUNITPAGE7_PM_INIT_UNAVAILABLE (0x00) -#define MPI25_IOUNITPAGE7_PM_INIT_HOST (0x40) -#define MPI25_IOUNITPAGE7_PM_INIT_IO_UNIT (0x80) -#define MPI25_IOUNITPAGE7_PM_INIT_PCIE_DPA (0xC0) - -#define MPI25_IOUNITPAGE7_PM_MODE_MASK (0x07) -#define MPI25_IOUNITPAGE7_PM_MODE_UNAVAILABLE (0x00) -#define MPI25_IOUNITPAGE7_PM_MODE_UNKNOWN (0x01) -#define MPI25_IOUNITPAGE7_PM_MODE_FULL_POWER (0x04) -#define MPI25_IOUNITPAGE7_PM_MODE_REDUCED_POWER (0x05) -#define MPI25_IOUNITPAGE7_PM_MODE_STANDBY (0x06) - - -/*defines for IO Unit Page 7 PCIeWidth field */ -#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X1 (0x01) -#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X2 (0x02) -#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X4 (0x04) -#define MPI2_IOUNITPAGE7_PCIE_WIDTH_X8 (0x08) - -/*defines for IO Unit Page 7 PCIeSpeed field */ -#define MPI2_IOUNITPAGE7_PCIE_SPEED_2_5_GBPS (0x00) -#define MPI2_IOUNITPAGE7_PCIE_SPEED_5_0_GBPS (0x01) -#define MPI2_IOUNITPAGE7_PCIE_SPEED_8_0_GBPS (0x02) - -/*defines for IO Unit Page 7 ProcessorState field */ -#define MPI2_IOUNITPAGE7_PSTATE_MASK_SECOND (0x0000000F) -#define MPI2_IOUNITPAGE7_PSTATE_SHIFT_SECOND (0) - -#define MPI2_IOUNITPAGE7_PSTATE_NOT_PRESENT (0x00) -#define MPI2_IOUNITPAGE7_PSTATE_DISABLED (0x01) -#define MPI2_IOUNITPAGE7_PSTATE_ENABLED (0x02) - -/*defines for IO Unit Page 7 PowerManagementCapabilities field */ -#define MPI25_IOUNITPAGE7_PMCAP_DPA_FULL_PWR_MODE (0x00400000) -#define MPI25_IOUNITPAGE7_PMCAP_DPA_REDUCED_PWR_MODE (0x00200000) -#define MPI25_IOUNITPAGE7_PMCAP_DPA_STANDBY_MODE (0x00100000) -#define MPI25_IOUNITPAGE7_PMCAP_HOST_FULL_PWR_MODE (0x00040000) -#define MPI25_IOUNITPAGE7_PMCAP_HOST_REDUCED_PWR_MODE (0x00020000) -#define MPI25_IOUNITPAGE7_PMCAP_HOST_STANDBY_MODE (0x00010000) -#define MPI25_IOUNITPAGE7_PMCAP_IO_FULL_PWR_MODE (0x00004000) -#define MPI25_IOUNITPAGE7_PMCAP_IO_REDUCED_PWR_MODE (0x00002000) -#define MPI25_IOUNITPAGE7_PMCAP_IO_STANDBY_MODE (0x00001000) -#define MPI2_IOUNITPAGE7_PMCAP_HOST_12_5_PCT_IOCSPEED (0x00000400) -#define MPI2_IOUNITPAGE7_PMCAP_HOST_25_0_PCT_IOCSPEED (0x00000200) -#define MPI2_IOUNITPAGE7_PMCAP_HOST_50_0_PCT_IOCSPEED (0x00000100) -#define MPI25_IOUNITPAGE7_PMCAP_IO_12_5_PCT_IOCSPEED (0x00000040) -#define MPI25_IOUNITPAGE7_PMCAP_IO_25_0_PCT_IOCSPEED (0x00000020) -#define MPI25_IOUNITPAGE7_PMCAP_IO_50_0_PCT_IOCSPEED (0x00000010) -#define MPI2_IOUNITPAGE7_PMCAP_HOST_WIDTH_CHANGE_PCIE (0x00000008) -#define MPI2_IOUNITPAGE7_PMCAP_HOST_SPEED_CHANGE_PCIE (0x00000004) -#define MPI25_IOUNITPAGE7_PMCAP_IO_WIDTH_CHANGE_PCIE (0x00000002) -#define MPI25_IOUNITPAGE7_PMCAP_IO_SPEED_CHANGE_PCIE (0x00000001) - -/*obsolete names for the PowerManagementCapabilities bits (above) */ -#define MPI2_IOUNITPAGE7_PMCAP_12_5_PCT_IOCSPEED (0x00000400) -#define MPI2_IOUNITPAGE7_PMCAP_25_0_PCT_IOCSPEED (0x00000200) -#define MPI2_IOUNITPAGE7_PMCAP_50_0_PCT_IOCSPEED (0x00000100) -#define MPI2_IOUNITPAGE7_PMCAP_PCIE_WIDTH_CHANGE (0x00000008) /*obsolete */ -#define MPI2_IOUNITPAGE7_PMCAP_PCIE_SPEED_CHANGE (0x00000004) /*obsolete */ - - -/*defines for IO Unit Page 7 IOCTemperatureUnits field */ -#define MPI2_IOUNITPAGE7_IOC_TEMP_NOT_PRESENT (0x00) -#define MPI2_IOUNITPAGE7_IOC_TEMP_FAHRENHEIT (0x01) -#define MPI2_IOUNITPAGE7_IOC_TEMP_CELSIUS (0x02) - -/*defines for IO Unit Page 7 IOCSpeed field */ -#define MPI2_IOUNITPAGE7_IOC_SPEED_FULL (0x01) -#define MPI2_IOUNITPAGE7_IOC_SPEED_HALF (0x02) -#define MPI2_IOUNITPAGE7_IOC_SPEED_QUARTER (0x04) -#define MPI2_IOUNITPAGE7_IOC_SPEED_EIGHTH (0x08) - -/*defines for IO Unit Page 7 BoardTemperatureUnits field */ -#define MPI2_IOUNITPAGE7_BOARD_TEMP_NOT_PRESENT (0x00) -#define MPI2_IOUNITPAGE7_BOARD_TEMP_FAHRENHEIT (0x01) -#define MPI2_IOUNITPAGE7_BOARD_TEMP_CELSIUS (0x02) - - -/*IO Unit Page 8 */ - -#define MPI2_IOUNIT8_NUM_THRESHOLDS (4) - -typedef struct _MPI2_IOUNIT8_SENSOR { - U16 Flags; /*0x00 */ - U16 Reserved1; /*0x02 */ - U16 - Threshold[MPI2_IOUNIT8_NUM_THRESHOLDS]; /*0x04 */ - U32 Reserved2; /*0x0C */ - U32 Reserved3; /*0x10 */ - U32 Reserved4; /*0x14 */ -} MPI2_IOUNIT8_SENSOR, *PTR_MPI2_IOUNIT8_SENSOR, - Mpi2IOUnit8Sensor_t, *pMpi2IOUnit8Sensor_t; - -/*defines for IO Unit Page 8 Sensor Flags field */ -#define MPI2_IOUNIT8_SENSOR_FLAGS_T3_ENABLE (0x0008) -#define MPI2_IOUNIT8_SENSOR_FLAGS_T2_ENABLE (0x0004) -#define MPI2_IOUNIT8_SENSOR_FLAGS_T1_ENABLE (0x0002) -#define MPI2_IOUNIT8_SENSOR_FLAGS_T0_ENABLE (0x0001) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumSensors at runtime. - */ -#ifndef MPI2_IOUNITPAGE8_SENSOR_ENTRIES -#define MPI2_IOUNITPAGE8_SENSOR_ENTRIES (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_8 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Reserved2; /*0x08 */ - U8 NumSensors; /*0x0C */ - U8 PollingInterval; /*0x0D */ - U16 Reserved3; /*0x0E */ - MPI2_IOUNIT8_SENSOR - Sensor[MPI2_IOUNITPAGE8_SENSOR_ENTRIES];/*0x10 */ -} MPI2_CONFIG_PAGE_IO_UNIT_8, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_8, - Mpi2IOUnitPage8_t, *pMpi2IOUnitPage8_t; - -#define MPI2_IOUNITPAGE8_PAGEVERSION (0x00) - - -/*IO Unit Page 9 */ - -typedef struct _MPI2_IOUNIT9_SENSOR { - U16 CurrentTemperature; /*0x00 */ - U16 Reserved1; /*0x02 */ - U8 Flags; /*0x04 */ - U8 Reserved2; /*0x05 */ - U16 Reserved3; /*0x06 */ - U32 Reserved4; /*0x08 */ - U32 Reserved5; /*0x0C */ -} MPI2_IOUNIT9_SENSOR, *PTR_MPI2_IOUNIT9_SENSOR, - Mpi2IOUnit9Sensor_t, *pMpi2IOUnit9Sensor_t; - -/*defines for IO Unit Page 9 Sensor Flags field */ -#define MPI2_IOUNIT9_SENSOR_FLAGS_TEMP_VALID (0x01) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumSensors at runtime. - */ -#ifndef MPI2_IOUNITPAGE9_SENSOR_ENTRIES -#define MPI2_IOUNITPAGE9_SENSOR_ENTRIES (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_9 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Reserved2; /*0x08 */ - U8 NumSensors; /*0x0C */ - U8 Reserved4; /*0x0D */ - U16 Reserved3; /*0x0E */ - MPI2_IOUNIT9_SENSOR - Sensor[MPI2_IOUNITPAGE9_SENSOR_ENTRIES];/*0x10 */ -} MPI2_CONFIG_PAGE_IO_UNIT_9, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_9, - Mpi2IOUnitPage9_t, *pMpi2IOUnitPage9_t; - -#define MPI2_IOUNITPAGE9_PAGEVERSION (0x00) - - -/*IO Unit Page 10 */ - -typedef struct _MPI2_IOUNIT10_FUNCTION { - U8 CreditPercent; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ -} MPI2_IOUNIT10_FUNCTION, - *PTR_MPI2_IOUNIT10_FUNCTION, - Mpi2IOUnit10Function_t, - *pMpi2IOUnit10Function_t; - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumFunctions at runtime. - */ -#ifndef MPI2_IOUNITPAGE10_FUNCTION_ENTRIES -#define MPI2_IOUNITPAGE10_FUNCTION_ENTRIES (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_IO_UNIT_10 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 NumFunctions; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 Reserved2; /*0x06 */ - U32 Reserved3; /*0x08 */ - U32 Reserved4; /*0x0C */ - MPI2_IOUNIT10_FUNCTION - Function[MPI2_IOUNITPAGE10_FUNCTION_ENTRIES];/*0x10 */ -} MPI2_CONFIG_PAGE_IO_UNIT_10, - *PTR_MPI2_CONFIG_PAGE_IO_UNIT_10, - Mpi2IOUnitPage10_t, *pMpi2IOUnitPage10_t; - -#define MPI2_IOUNITPAGE10_PAGEVERSION (0x01) - - - -/**************************************************************************** -* IOC Config Pages -****************************************************************************/ - -/*IOC Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_IOC_0 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Reserved2; /*0x08 */ - U16 VendorID; /*0x0C */ - U16 DeviceID; /*0x0E */ - U8 RevisionID; /*0x10 */ - U8 Reserved3; /*0x11 */ - U16 Reserved4; /*0x12 */ - U32 ClassCode; /*0x14 */ - U16 SubsystemVendorID; /*0x18 */ - U16 SubsystemID; /*0x1A */ -} MPI2_CONFIG_PAGE_IOC_0, - *PTR_MPI2_CONFIG_PAGE_IOC_0, - Mpi2IOCPage0_t, *pMpi2IOCPage0_t; - -#define MPI2_IOCPAGE0_PAGEVERSION (0x02) - - -/*IOC Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_IOC_1 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Flags; /*0x04 */ - U32 CoalescingTimeout; /*0x08 */ - U8 CoalescingDepth; /*0x0C */ - U8 PCISlotNum; /*0x0D */ - U8 PCIBusNum; /*0x0E */ - U8 PCIDomainSegment; /*0x0F */ - U32 Reserved1; /*0x10 */ - U32 Reserved2; /*0x14 */ -} MPI2_CONFIG_PAGE_IOC_1, - *PTR_MPI2_CONFIG_PAGE_IOC_1, - Mpi2IOCPage1_t, *pMpi2IOCPage1_t; - -#define MPI2_IOCPAGE1_PAGEVERSION (0x05) - -/*defines for IOC Page 1 Flags field */ -#define MPI2_IOCPAGE1_REPLY_COALESCING (0x00000001) - -#define MPI2_IOCPAGE1_PCISLOTNUM_UNKNOWN (0xFF) -#define MPI2_IOCPAGE1_PCIBUSNUM_UNKNOWN (0xFF) -#define MPI2_IOCPAGE1_PCIDOMAIN_UNKNOWN (0xFF) - -/*IOC Page 6 */ - -typedef struct _MPI2_CONFIG_PAGE_IOC_6 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 - CapabilitiesFlags; /*0x04 */ - U8 MaxDrivesRAID0; /*0x08 */ - U8 MaxDrivesRAID1; /*0x09 */ - U8 - MaxDrivesRAID1E; /*0x0A */ - U8 - MaxDrivesRAID10; /*0x0B */ - U8 MinDrivesRAID0; /*0x0C */ - U8 MinDrivesRAID1; /*0x0D */ - U8 - MinDrivesRAID1E; /*0x0E */ - U8 - MinDrivesRAID10; /*0x0F */ - U32 Reserved1; /*0x10 */ - U8 - MaxGlobalHotSpares; /*0x14 */ - U8 MaxPhysDisks; /*0x15 */ - U8 MaxVolumes; /*0x16 */ - U8 MaxConfigs; /*0x17 */ - U8 MaxOCEDisks; /*0x18 */ - U8 Reserved2; /*0x19 */ - U16 Reserved3; /*0x1A */ - U32 - SupportedStripeSizeMapRAID0; /*0x1C */ - U32 - SupportedStripeSizeMapRAID1E; /*0x20 */ - U32 - SupportedStripeSizeMapRAID10; /*0x24 */ - U32 Reserved4; /*0x28 */ - U32 Reserved5; /*0x2C */ - U16 - DefaultMetadataSize; /*0x30 */ - U16 Reserved6; /*0x32 */ - U16 - MaxBadBlockTableEntries; /*0x34 */ - U16 Reserved7; /*0x36 */ - U32 - IRNvsramVersion; /*0x38 */ -} MPI2_CONFIG_PAGE_IOC_6, - *PTR_MPI2_CONFIG_PAGE_IOC_6, - Mpi2IOCPage6_t, *pMpi2IOCPage6_t; - -#define MPI2_IOCPAGE6_PAGEVERSION (0x05) - -/*defines for IOC Page 6 CapabilitiesFlags */ -#define MPI2_IOCPAGE6_CAP_FLAGS_4K_SECTORS_SUPPORT (0x00000020) -#define MPI2_IOCPAGE6_CAP_FLAGS_RAID10_SUPPORT (0x00000010) -#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1_SUPPORT (0x00000008) -#define MPI2_IOCPAGE6_CAP_FLAGS_RAID1E_SUPPORT (0x00000004) -#define MPI2_IOCPAGE6_CAP_FLAGS_RAID0_SUPPORT (0x00000002) -#define MPI2_IOCPAGE6_CAP_FLAGS_GLOBAL_HOT_SPARE (0x00000001) - - -/*IOC Page 7 */ - -#define MPI2_IOCPAGE7_EVENTMASK_WORDS (4) - -typedef struct _MPI2_CONFIG_PAGE_IOC_7 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 - EventMasks[MPI2_IOCPAGE7_EVENTMASK_WORDS];/*0x08 */ - U16 SASBroadcastPrimitiveMasks; /*0x18 */ - U16 SASNotifyPrimitiveMasks; /*0x1A */ - U32 Reserved3; /*0x1C */ -} MPI2_CONFIG_PAGE_IOC_7, - *PTR_MPI2_CONFIG_PAGE_IOC_7, - Mpi2IOCPage7_t, *pMpi2IOCPage7_t; - -#define MPI2_IOCPAGE7_PAGEVERSION (0x02) - - -/*IOC Page 8 */ - -typedef struct _MPI2_CONFIG_PAGE_IOC_8 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 NumDevsPerEnclosure; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 Reserved2; /*0x06 */ - U16 MaxPersistentEntries; /*0x08 */ - U16 MaxNumPhysicalMappedIDs; /*0x0A */ - U16 Flags; /*0x0C */ - U16 Reserved3; /*0x0E */ - U16 IRVolumeMappingFlags; /*0x10 */ - U16 Reserved4; /*0x12 */ - U32 Reserved5; /*0x14 */ -} MPI2_CONFIG_PAGE_IOC_8, - *PTR_MPI2_CONFIG_PAGE_IOC_8, - Mpi2IOCPage8_t, *pMpi2IOCPage8_t; - -#define MPI2_IOCPAGE8_PAGEVERSION (0x00) - -/*defines for IOC Page 8 Flags field */ -#define MPI2_IOCPAGE8_FLAGS_DA_START_SLOT_1 (0x00000020) -#define MPI2_IOCPAGE8_FLAGS_RESERVED_TARGETID_0 (0x00000010) - -#define MPI2_IOCPAGE8_FLAGS_MASK_MAPPING_MODE (0x0000000E) -#define MPI2_IOCPAGE8_FLAGS_DEVICE_PERSISTENCE_MAPPING (0x00000000) -#define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING (0x00000002) - -#define MPI2_IOCPAGE8_FLAGS_DISABLE_PERSISTENT_MAPPING (0x00000001) -#define MPI2_IOCPAGE8_FLAGS_ENABLE_PERSISTENT_MAPPING (0x00000000) - -/*defines for IOC Page 8 IRVolumeMappingFlags */ -#define MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE (0x00000003) -#define MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING (0x00000000) -#define MPI2_IOCPAGE8_IRFLAGS_HIGH_VOLUME_MAPPING (0x00000001) - - -/**************************************************************************** -* BIOS Config Pages -****************************************************************************/ - -/*BIOS Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_BIOS_1 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 BiosOptions; /*0x04 */ - U32 IOCSettings; /*0x08 */ - U8 SSUTimeout; /*0x0C */ - U8 Reserved1; /*0x0D */ - U16 Reserved2; /*0x0E */ - U32 DeviceSettings; /*0x10 */ - U16 NumberOfDevices; /*0x14 */ - U16 UEFIVersion; /*0x16 */ - U16 IOTimeoutBlockDevicesNonRM; /*0x18 */ - U16 IOTimeoutSequential; /*0x1A */ - U16 IOTimeoutOther; /*0x1C */ - U16 IOTimeoutBlockDevicesRM; /*0x1E */ -} MPI2_CONFIG_PAGE_BIOS_1, - *PTR_MPI2_CONFIG_PAGE_BIOS_1, - Mpi2BiosPage1_t, *pMpi2BiosPage1_t; - -#define MPI2_BIOSPAGE1_PAGEVERSION (0x07) - -/*values for BIOS Page 1 BiosOptions field */ -#define MPI2_BIOSPAGE1_OPTIONS_PNS_MASK (0x00003800) -#define MPI2_BIOSPAGE1_OPTIONS_PNS_PBDHL (0x00000000) -#define MPI2_BIOSPAGE1_OPTIONS_PNS_ENCSLOSURE (0x00000800) -#define MPI2_BIOSPAGE1_OPTIONS_PNS_LWWID (0x00001000) -#define MPI2_BIOSPAGE1_OPTIONS_PNS_PSENS (0x00001800) -#define MPI2_BIOSPAGE1_OPTIONS_PNS_ESPHY (0x00002000) - -#define MPI2_BIOSPAGE1_OPTIONS_X86_DISABLE_BIOS (0x00000400) - -#define MPI2_BIOSPAGE1_OPTIONS_MASK_REGISTRATION_UEFI_BSD (0x00000300) -#define MPI2_BIOSPAGE1_OPTIONS_USE_BIT0_REGISTRATION_UEFI_BSD (0x00000000) -#define MPI2_BIOSPAGE1_OPTIONS_FULL_REGISTRATION_UEFI_BSD (0x00000100) -#define MPI2_BIOSPAGE1_OPTIONS_ADAPTER_REGISTRATION_UEFI_BSD (0x00000200) -#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_REGISTRATION_UEFI_BSD (0x00000300) - -#define MPI2_BIOSPAGE1_OPTIONS_MASK_OEM_ID (0x000000F0) -#define MPI2_BIOSPAGE1_OPTIONS_LSI_OEM_ID (0x00000000) - -#define MPI2_BIOSPAGE1_OPTIONS_MASK_UEFI_HII_REGISTRATION (0x00000006) -#define MPI2_BIOSPAGE1_OPTIONS_ENABLE_UEFI_HII (0x00000000) -#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_UEFI_HII (0x00000002) -#define MPI2_BIOSPAGE1_OPTIONS_VERSION_CHECK_UEFI_HII (0x00000004) - -#define MPI2_BIOSPAGE1_OPTIONS_DISABLE_BIOS (0x00000001) - -/*values for BIOS Page 1 IOCSettings field */ -#define MPI2_BIOSPAGE1_IOCSET_MASK_BOOT_PREFERENCE (0x00030000) -#define MPI2_BIOSPAGE1_IOCSET_ENCLOSURE_SLOT_BOOT (0x00000000) -#define MPI2_BIOSPAGE1_IOCSET_SAS_ADDRESS_BOOT (0x00010000) - -#define MPI2_BIOSPAGE1_IOCSET_MASK_RM_SETTING (0x000000C0) -#define MPI2_BIOSPAGE1_IOCSET_NONE_RM_SETTING (0x00000000) -#define MPI2_BIOSPAGE1_IOCSET_BOOT_RM_SETTING (0x00000040) -#define MPI2_BIOSPAGE1_IOCSET_MEDIA_RM_SETTING (0x00000080) - -#define MPI2_BIOSPAGE1_IOCSET_MASK_ADAPTER_SUPPORT (0x00000030) -#define MPI2_BIOSPAGE1_IOCSET_NO_SUPPORT (0x00000000) -#define MPI2_BIOSPAGE1_IOCSET_BIOS_SUPPORT (0x00000010) -#define MPI2_BIOSPAGE1_IOCSET_OS_SUPPORT (0x00000020) -#define MPI2_BIOSPAGE1_IOCSET_ALL_SUPPORT (0x00000030) - -#define MPI2_BIOSPAGE1_IOCSET_ALTERNATE_CHS (0x00000008) - -/*values for BIOS Page 1 DeviceSettings field */ -#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SMART_POLLING (0x00000010) -#define MPI2_BIOSPAGE1_DEVSET_DISABLE_SEQ_LUN (0x00000008) -#define MPI2_BIOSPAGE1_DEVSET_DISABLE_RM_LUN (0x00000004) -#define MPI2_BIOSPAGE1_DEVSET_DISABLE_NON_RM_LUN (0x00000002) -#define MPI2_BIOSPAGE1_DEVSET_DISABLE_OTHER_LUN (0x00000001) - -/*defines for BIOS Page 1 UEFIVersion field */ -#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_MASK (0xFF00) -#define MPI2_BIOSPAGE1_UEFI_VER_MAJOR_SHIFT (8) -#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_MASK (0x00FF) -#define MPI2_BIOSPAGE1_UEFI_VER_MINOR_SHIFT (0) - - - -/*BIOS Page 2 */ - -typedef struct _MPI2_BOOT_DEVICE_ADAPTER_ORDER { - U32 Reserved1; /*0x00 */ - U32 Reserved2; /*0x04 */ - U32 Reserved3; /*0x08 */ - U32 Reserved4; /*0x0C */ - U32 Reserved5; /*0x10 */ - U32 Reserved6; /*0x14 */ -} MPI2_BOOT_DEVICE_ADAPTER_ORDER, - *PTR_MPI2_BOOT_DEVICE_ADAPTER_ORDER, - Mpi2BootDeviceAdapterOrder_t, - *pMpi2BootDeviceAdapterOrder_t; - -typedef struct _MPI2_BOOT_DEVICE_SAS_WWID { - U64 SASAddress; /*0x00 */ - U8 LUN[8]; /*0x08 */ - U32 Reserved1; /*0x10 */ - U32 Reserved2; /*0x14 */ -} MPI2_BOOT_DEVICE_SAS_WWID, - *PTR_MPI2_BOOT_DEVICE_SAS_WWID, - Mpi2BootDeviceSasWwid_t, - *pMpi2BootDeviceSasWwid_t; - -typedef struct _MPI2_BOOT_DEVICE_ENCLOSURE_SLOT { - U64 EnclosureLogicalID; /*0x00 */ - U32 Reserved1; /*0x08 */ - U32 Reserved2; /*0x0C */ - U16 SlotNumber; /*0x10 */ - U16 Reserved3; /*0x12 */ - U32 Reserved4; /*0x14 */ -} MPI2_BOOT_DEVICE_ENCLOSURE_SLOT, - *PTR_MPI2_BOOT_DEVICE_ENCLOSURE_SLOT, - Mpi2BootDeviceEnclosureSlot_t, - *pMpi2BootDeviceEnclosureSlot_t; - -typedef struct _MPI2_BOOT_DEVICE_DEVICE_NAME { - U64 DeviceName; /*0x00 */ - U8 LUN[8]; /*0x08 */ - U32 Reserved1; /*0x10 */ - U32 Reserved2; /*0x14 */ -} MPI2_BOOT_DEVICE_DEVICE_NAME, - *PTR_MPI2_BOOT_DEVICE_DEVICE_NAME, - Mpi2BootDeviceDeviceName_t, - *pMpi2BootDeviceDeviceName_t; - -typedef union _MPI2_MPI2_BIOSPAGE2_BOOT_DEVICE { - MPI2_BOOT_DEVICE_ADAPTER_ORDER AdapterOrder; - MPI2_BOOT_DEVICE_SAS_WWID SasWwid; - MPI2_BOOT_DEVICE_ENCLOSURE_SLOT EnclosureSlot; - MPI2_BOOT_DEVICE_DEVICE_NAME DeviceName; -} MPI2_BIOSPAGE2_BOOT_DEVICE, - *PTR_MPI2_BIOSPAGE2_BOOT_DEVICE, - Mpi2BiosPage2BootDevice_t, - *pMpi2BiosPage2BootDevice_t; - -typedef struct _MPI2_CONFIG_PAGE_BIOS_2 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Reserved2; /*0x08 */ - U32 Reserved3; /*0x0C */ - U32 Reserved4; /*0x10 */ - U32 Reserved5; /*0x14 */ - U32 Reserved6; /*0x18 */ - U8 ReqBootDeviceForm; /*0x1C */ - U8 Reserved7; /*0x1D */ - U16 Reserved8; /*0x1E */ - MPI2_BIOSPAGE2_BOOT_DEVICE RequestedBootDevice; /*0x20 */ - U8 ReqAltBootDeviceForm; /*0x38 */ - U8 Reserved9; /*0x39 */ - U16 Reserved10; /*0x3A */ - MPI2_BIOSPAGE2_BOOT_DEVICE RequestedAltBootDevice; /*0x3C */ - U8 CurrentBootDeviceForm; /*0x58 */ - U8 Reserved11; /*0x59 */ - U16 Reserved12; /*0x5A */ - MPI2_BIOSPAGE2_BOOT_DEVICE CurrentBootDevice; /*0x58 */ -} MPI2_CONFIG_PAGE_BIOS_2, *PTR_MPI2_CONFIG_PAGE_BIOS_2, - Mpi2BiosPage2_t, *pMpi2BiosPage2_t; - -#define MPI2_BIOSPAGE2_PAGEVERSION (0x04) - -/*values for BIOS Page 2 BootDeviceForm fields */ -#define MPI2_BIOSPAGE2_FORM_MASK (0x0F) -#define MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED (0x00) -#define MPI2_BIOSPAGE2_FORM_SAS_WWID (0x05) -#define MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT (0x06) -#define MPI2_BIOSPAGE2_FORM_DEVICE_NAME (0x07) - - -/*BIOS Page 3 */ - -typedef struct _MPI2_ADAPTER_INFO { - U8 PciBusNumber; /*0x00 */ - U8 PciDeviceAndFunctionNumber; /*0x01 */ - U16 AdapterFlags; /*0x02 */ -} MPI2_ADAPTER_INFO, *PTR_MPI2_ADAPTER_INFO, - Mpi2AdapterInfo_t, *pMpi2AdapterInfo_t; - -#define MPI2_ADAPTER_INFO_FLAGS_EMBEDDED (0x0001) -#define MPI2_ADAPTER_INFO_FLAGS_INIT_STATUS (0x0002) - -typedef struct _MPI2_CONFIG_PAGE_BIOS_3 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U32 GlobalFlags; /*0x04 */ - U32 BiosVersion; /*0x08 */ - MPI2_ADAPTER_INFO AdapterOrder[4]; /*0x0C */ - U32 Reserved1; /*0x1C */ -} MPI2_CONFIG_PAGE_BIOS_3, - *PTR_MPI2_CONFIG_PAGE_BIOS_3, - Mpi2BiosPage3_t, *pMpi2BiosPage3_t; - -#define MPI2_BIOSPAGE3_PAGEVERSION (0x00) - -/*values for BIOS Page 3 GlobalFlags */ -#define MPI2_BIOSPAGE3_FLAGS_PAUSE_ON_ERROR (0x00000002) -#define MPI2_BIOSPAGE3_FLAGS_VERBOSE_ENABLE (0x00000004) -#define MPI2_BIOSPAGE3_FLAGS_HOOK_INT_40_DISABLE (0x00000010) - -#define MPI2_BIOSPAGE3_FLAGS_DEV_LIST_DISPLAY_MASK (0x000000E0) -#define MPI2_BIOSPAGE3_FLAGS_INSTALLED_DEV_DISPLAY (0x00000000) -#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DISPLAY (0x00000020) -#define MPI2_BIOSPAGE3_FLAGS_ADAPTER_DEV_DISPLAY (0x00000040) - - -/*BIOS Page 4 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_BIOS_PAGE_4_PHY_ENTRIES -#define MPI2_BIOS_PAGE_4_PHY_ENTRIES (1) -#endif - -typedef struct _MPI2_BIOS4_ENTRY { - U64 ReassignmentWWID; /*0x00 */ - U64 ReassignmentDeviceName; /*0x08 */ -} MPI2_BIOS4_ENTRY, *PTR_MPI2_BIOS4_ENTRY, - Mpi2MBios4Entry_t, *pMpi2Bios4Entry_t; - -typedef struct _MPI2_CONFIG_PAGE_BIOS_4 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 NumPhys; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 Reserved2; /*0x06 */ - MPI2_BIOS4_ENTRY - Phy[MPI2_BIOS_PAGE_4_PHY_ENTRIES]; /*0x08 */ -} MPI2_CONFIG_PAGE_BIOS_4, *PTR_MPI2_CONFIG_PAGE_BIOS_4, - Mpi2BiosPage4_t, *pMpi2BiosPage4_t; - -#define MPI2_BIOSPAGE4_PAGEVERSION (0x01) - - -/**************************************************************************** -* RAID Volume Config Pages -****************************************************************************/ - -/*RAID Volume Page 0 */ - -typedef struct _MPI2_RAIDVOL0_PHYS_DISK { - U8 RAIDSetNum; /*0x00 */ - U8 PhysDiskMap; /*0x01 */ - U8 PhysDiskNum; /*0x02 */ - U8 Reserved; /*0x03 */ -} MPI2_RAIDVOL0_PHYS_DISK, *PTR_MPI2_RAIDVOL0_PHYS_DISK, - Mpi2RaidVol0PhysDisk_t, *pMpi2RaidVol0PhysDisk_t; - -/*defines for the PhysDiskMap field */ -#define MPI2_RAIDVOL0_PHYSDISK_PRIMARY (0x01) -#define MPI2_RAIDVOL0_PHYSDISK_SECONDARY (0x02) - -typedef struct _MPI2_RAIDVOL0_SETTINGS { - U16 Settings; /*0x00 */ - U8 HotSparePool; /*0x01 */ - U8 Reserved; /*0x02 */ -} MPI2_RAIDVOL0_SETTINGS, *PTR_MPI2_RAIDVOL0_SETTINGS, - Mpi2RaidVol0Settings_t, - *pMpi2RaidVol0Settings_t; - -/*RAID Volume Page 0 HotSparePool defines, also used in RAID Physical Disk */ -#define MPI2_RAID_HOT_SPARE_POOL_0 (0x01) -#define MPI2_RAID_HOT_SPARE_POOL_1 (0x02) -#define MPI2_RAID_HOT_SPARE_POOL_2 (0x04) -#define MPI2_RAID_HOT_SPARE_POOL_3 (0x08) -#define MPI2_RAID_HOT_SPARE_POOL_4 (0x10) -#define MPI2_RAID_HOT_SPARE_POOL_5 (0x20) -#define MPI2_RAID_HOT_SPARE_POOL_6 (0x40) -#define MPI2_RAID_HOT_SPARE_POOL_7 (0x80) - -/*RAID Volume Page 0 VolumeSettings defines */ -#define MPI2_RAIDVOL0_SETTING_USE_PRODUCT_ID_SUFFIX (0x0008) -#define MPI2_RAIDVOL0_SETTING_AUTO_CONFIG_HSWAP_DISABLE (0x0004) - -#define MPI2_RAIDVOL0_SETTING_MASK_WRITE_CACHING (0x0003) -#define MPI2_RAIDVOL0_SETTING_UNCHANGED (0x0000) -#define MPI2_RAIDVOL0_SETTING_DISABLE_WRITE_CACHING (0x0001) -#define MPI2_RAIDVOL0_SETTING_ENABLE_WRITE_CACHING (0x0002) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhysDisks at runtime. - */ -#ifndef MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX -#define MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_0 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U16 DevHandle; /*0x04 */ - U8 VolumeState; /*0x06 */ - U8 VolumeType; /*0x07 */ - U32 VolumeStatusFlags; /*0x08 */ - MPI2_RAIDVOL0_SETTINGS VolumeSettings; /*0x0C */ - U64 MaxLBA; /*0x10 */ - U32 StripeSize; /*0x18 */ - U16 BlockSize; /*0x1C */ - U16 Reserved1; /*0x1E */ - U8 SupportedPhysDisks;/*0x20 */ - U8 ResyncRate; /*0x21 */ - U16 DataScrubDuration; /*0x22 */ - U8 NumPhysDisks; /*0x24 */ - U8 Reserved2; /*0x25 */ - U8 Reserved3; /*0x26 */ - U8 InactiveStatus; /*0x27 */ - MPI2_RAIDVOL0_PHYS_DISK - PhysDisk[MPI2_RAID_VOL_PAGE_0_PHYSDISK_MAX]; /*0x28 */ -} MPI2_CONFIG_PAGE_RAID_VOL_0, - *PTR_MPI2_CONFIG_PAGE_RAID_VOL_0, - Mpi2RaidVolPage0_t, *pMpi2RaidVolPage0_t; - -#define MPI2_RAIDVOLPAGE0_PAGEVERSION (0x0A) - -/*values for RAID VolumeState */ -#define MPI2_RAID_VOL_STATE_MISSING (0x00) -#define MPI2_RAID_VOL_STATE_FAILED (0x01) -#define MPI2_RAID_VOL_STATE_INITIALIZING (0x02) -#define MPI2_RAID_VOL_STATE_ONLINE (0x03) -#define MPI2_RAID_VOL_STATE_DEGRADED (0x04) -#define MPI2_RAID_VOL_STATE_OPTIMAL (0x05) - -/*values for RAID VolumeType */ -#define MPI2_RAID_VOL_TYPE_RAID0 (0x00) -#define MPI2_RAID_VOL_TYPE_RAID1E (0x01) -#define MPI2_RAID_VOL_TYPE_RAID1 (0x02) -#define MPI2_RAID_VOL_TYPE_RAID10 (0x05) -#define MPI2_RAID_VOL_TYPE_UNKNOWN (0xFF) - -/*values for RAID Volume Page 0 VolumeStatusFlags field */ -#define MPI2_RAIDVOL0_STATUS_FLAG_PENDING_RESYNC (0x02000000) -#define MPI2_RAIDVOL0_STATUS_FLAG_BACKG_INIT_PENDING (0x01000000) -#define MPI2_RAIDVOL0_STATUS_FLAG_MDC_PENDING (0x00800000) -#define MPI2_RAIDVOL0_STATUS_FLAG_USER_CONSIST_PENDING (0x00400000) -#define MPI2_RAIDVOL0_STATUS_FLAG_MAKE_DATA_CONSISTENT (0x00200000) -#define MPI2_RAIDVOL0_STATUS_FLAG_DATA_SCRUB (0x00100000) -#define MPI2_RAIDVOL0_STATUS_FLAG_CONSISTENCY_CHECK (0x00080000) -#define MPI2_RAIDVOL0_STATUS_FLAG_CAPACITY_EXPANSION (0x00040000) -#define MPI2_RAIDVOL0_STATUS_FLAG_BACKGROUND_INIT (0x00020000) -#define MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS (0x00010000) -#define MPI2_RAIDVOL0_STATUS_FLAG_VOL_NOT_CONSISTENT (0x00000080) -#define MPI2_RAIDVOL0_STATUS_FLAG_OCE_ALLOWED (0x00000040) -#define MPI2_RAIDVOL0_STATUS_FLAG_BGI_COMPLETE (0x00000020) -#define MPI2_RAIDVOL0_STATUS_FLAG_1E_OFFSET_MIRROR (0x00000000) -#define MPI2_RAIDVOL0_STATUS_FLAG_1E_ADJACENT_MIRROR (0x00000010) -#define MPI2_RAIDVOL0_STATUS_FLAG_BAD_BLOCK_TABLE_FULL (0x00000008) -#define MPI2_RAIDVOL0_STATUS_FLAG_VOLUME_INACTIVE (0x00000004) -#define MPI2_RAIDVOL0_STATUS_FLAG_QUIESCED (0x00000002) -#define MPI2_RAIDVOL0_STATUS_FLAG_ENABLED (0x00000001) - -/*values for RAID Volume Page 0 SupportedPhysDisks field */ -#define MPI2_RAIDVOL0_SUPPORT_SOLID_STATE_DISKS (0x08) -#define MPI2_RAIDVOL0_SUPPORT_HARD_DISKS (0x04) -#define MPI2_RAIDVOL0_SUPPORT_SAS_PROTOCOL (0x02) -#define MPI2_RAIDVOL0_SUPPORT_SATA_PROTOCOL (0x01) - -/*values for RAID Volume Page 0 InactiveStatus field */ -#define MPI2_RAIDVOLPAGE0_UNKNOWN_INACTIVE (0x00) -#define MPI2_RAIDVOLPAGE0_STALE_METADATA_INACTIVE (0x01) -#define MPI2_RAIDVOLPAGE0_FOREIGN_VOLUME_INACTIVE (0x02) -#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_RESOURCE_INACTIVE (0x03) -#define MPI2_RAIDVOLPAGE0_CLONE_VOLUME_INACTIVE (0x04) -#define MPI2_RAIDVOLPAGE0_INSUFFICIENT_METADATA_INACTIVE (0x05) -#define MPI2_RAIDVOLPAGE0_PREVIOUSLY_DELETED (0x06) - - -/*RAID Volume Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_RAID_VOL_1 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U16 DevHandle; /*0x04 */ - U16 Reserved0; /*0x06 */ - U8 GUID[24]; /*0x08 */ - U8 Name[16]; /*0x20 */ - U64 WWID; /*0x30 */ - U32 Reserved1; /*0x38 */ - U32 Reserved2; /*0x3C */ -} MPI2_CONFIG_PAGE_RAID_VOL_1, - *PTR_MPI2_CONFIG_PAGE_RAID_VOL_1, - Mpi2RaidVolPage1_t, *pMpi2RaidVolPage1_t; - -#define MPI2_RAIDVOLPAGE1_PAGEVERSION (0x03) - - -/**************************************************************************** -* RAID Physical Disk Config Pages -****************************************************************************/ - -/*RAID Physical Disk Page 0 */ - -typedef struct _MPI2_RAIDPHYSDISK0_SETTINGS { - U16 Reserved1; /*0x00 */ - U8 HotSparePool; /*0x02 */ - U8 Reserved2; /*0x03 */ -} MPI2_RAIDPHYSDISK0_SETTINGS, - *PTR_MPI2_RAIDPHYSDISK0_SETTINGS, - Mpi2RaidPhysDisk0Settings_t, - *pMpi2RaidPhysDisk0Settings_t; - -/*use MPI2_RAID_HOT_SPARE_POOL_ defines for the HotSparePool field */ - -typedef struct _MPI2_RAIDPHYSDISK0_INQUIRY_DATA { - U8 VendorID[8]; /*0x00 */ - U8 ProductID[16]; /*0x08 */ - U8 ProductRevLevel[4]; /*0x18 */ - U8 SerialNum[32]; /*0x1C */ -} MPI2_RAIDPHYSDISK0_INQUIRY_DATA, - *PTR_MPI2_RAIDPHYSDISK0_INQUIRY_DATA, - Mpi2RaidPhysDisk0InquiryData_t, - *pMpi2RaidPhysDisk0InquiryData_t; - -typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_0 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U16 DevHandle; /*0x04 */ - U8 Reserved1; /*0x06 */ - U8 PhysDiskNum; /*0x07 */ - MPI2_RAIDPHYSDISK0_SETTINGS PhysDiskSettings; /*0x08 */ - U32 Reserved2; /*0x0C */ - MPI2_RAIDPHYSDISK0_INQUIRY_DATA InquiryData; /*0x10 */ - U32 Reserved3; /*0x4C */ - U8 PhysDiskState; /*0x50 */ - U8 OfflineReason; /*0x51 */ - U8 IncompatibleReason; /*0x52 */ - U8 PhysDiskAttributes; /*0x53 */ - U32 PhysDiskStatusFlags;/*0x54 */ - U64 DeviceMaxLBA; /*0x58 */ - U64 HostMaxLBA; /*0x60 */ - U64 CoercedMaxLBA; /*0x68 */ - U16 BlockSize; /*0x70 */ - U16 Reserved5; /*0x72 */ - U32 Reserved6; /*0x74 */ -} MPI2_CONFIG_PAGE_RD_PDISK_0, - *PTR_MPI2_CONFIG_PAGE_RD_PDISK_0, - Mpi2RaidPhysDiskPage0_t, - *pMpi2RaidPhysDiskPage0_t; - -#define MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION (0x05) - -/*PhysDiskState defines */ -#define MPI2_RAID_PD_STATE_NOT_CONFIGURED (0x00) -#define MPI2_RAID_PD_STATE_NOT_COMPATIBLE (0x01) -#define MPI2_RAID_PD_STATE_OFFLINE (0x02) -#define MPI2_RAID_PD_STATE_ONLINE (0x03) -#define MPI2_RAID_PD_STATE_HOT_SPARE (0x04) -#define MPI2_RAID_PD_STATE_DEGRADED (0x05) -#define MPI2_RAID_PD_STATE_REBUILDING (0x06) -#define MPI2_RAID_PD_STATE_OPTIMAL (0x07) - -/*OfflineReason defines */ -#define MPI2_PHYSDISK0_ONLINE (0x00) -#define MPI2_PHYSDISK0_OFFLINE_MISSING (0x01) -#define MPI2_PHYSDISK0_OFFLINE_FAILED (0x03) -#define MPI2_PHYSDISK0_OFFLINE_INITIALIZING (0x04) -#define MPI2_PHYSDISK0_OFFLINE_REQUESTED (0x05) -#define MPI2_PHYSDISK0_OFFLINE_FAILED_REQUESTED (0x06) -#define MPI2_PHYSDISK0_OFFLINE_OTHER (0xFF) - -/*IncompatibleReason defines */ -#define MPI2_PHYSDISK0_COMPATIBLE (0x00) -#define MPI2_PHYSDISK0_INCOMPATIBLE_PROTOCOL (0x01) -#define MPI2_PHYSDISK0_INCOMPATIBLE_BLOCKSIZE (0x02) -#define MPI2_PHYSDISK0_INCOMPATIBLE_MAX_LBA (0x03) -#define MPI2_PHYSDISK0_INCOMPATIBLE_SATA_EXTENDED_CMD (0x04) -#define MPI2_PHYSDISK0_INCOMPATIBLE_REMOVEABLE_MEDIA (0x05) -#define MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE (0x06) -#define MPI2_PHYSDISK0_INCOMPATIBLE_UNKNOWN (0xFF) - -/*PhysDiskAttributes defines */ -#define MPI2_PHYSDISK0_ATTRIB_MEDIA_MASK (0x0C) -#define MPI2_PHYSDISK0_ATTRIB_SOLID_STATE_DRIVE (0x08) -#define MPI2_PHYSDISK0_ATTRIB_HARD_DISK_DRIVE (0x04) - -#define MPI2_PHYSDISK0_ATTRIB_PROTOCOL_MASK (0x03) -#define MPI2_PHYSDISK0_ATTRIB_SAS_PROTOCOL (0x02) -#define MPI2_PHYSDISK0_ATTRIB_SATA_PROTOCOL (0x01) - -/*PhysDiskStatusFlags defines */ -#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED (0x00000040) -#define MPI2_PHYSDISK0_STATUS_FLAG_OCE_TARGET (0x00000020) -#define MPI2_PHYSDISK0_STATUS_FLAG_WRITE_CACHE_ENABLED (0x00000010) -#define MPI2_PHYSDISK0_STATUS_FLAG_OPTIMAL_PREVIOUS (0x00000000) -#define MPI2_PHYSDISK0_STATUS_FLAG_NOT_OPTIMAL_PREVIOUS (0x00000008) -#define MPI2_PHYSDISK0_STATUS_FLAG_INACTIVE_VOLUME (0x00000004) -#define MPI2_PHYSDISK0_STATUS_FLAG_QUIESCED (0x00000002) -#define MPI2_PHYSDISK0_STATUS_FLAG_OUT_OF_SYNC (0x00000001) - - -/*RAID Physical Disk Page 1 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhysDiskPaths at runtime. - */ -#ifndef MPI2_RAID_PHYS_DISK1_PATH_MAX -#define MPI2_RAID_PHYS_DISK1_PATH_MAX (1) -#endif - -typedef struct _MPI2_RAIDPHYSDISK1_PATH { - U16 DevHandle; /*0x00 */ - U16 Reserved1; /*0x02 */ - U64 WWID; /*0x04 */ - U64 OwnerWWID; /*0x0C */ - U8 OwnerIdentifier; /*0x14 */ - U8 Reserved2; /*0x15 */ - U16 Flags; /*0x16 */ -} MPI2_RAIDPHYSDISK1_PATH, *PTR_MPI2_RAIDPHYSDISK1_PATH, - Mpi2RaidPhysDisk1Path_t, - *pMpi2RaidPhysDisk1Path_t; - -/*RAID Physical Disk Page 1 Physical Disk Path Flags field defines */ -#define MPI2_RAID_PHYSDISK1_FLAG_PRIMARY (0x0004) -#define MPI2_RAID_PHYSDISK1_FLAG_BROKEN (0x0002) -#define MPI2_RAID_PHYSDISK1_FLAG_INVALID (0x0001) - -typedef struct _MPI2_CONFIG_PAGE_RD_PDISK_1 { - MPI2_CONFIG_PAGE_HEADER Header; /*0x00 */ - U8 NumPhysDiskPaths; /*0x04 */ - U8 PhysDiskNum; /*0x05 */ - U16 Reserved1; /*0x06 */ - U32 Reserved2; /*0x08 */ - MPI2_RAIDPHYSDISK1_PATH - PhysicalDiskPath[MPI2_RAID_PHYS_DISK1_PATH_MAX];/*0x0C */ -} MPI2_CONFIG_PAGE_RD_PDISK_1, - *PTR_MPI2_CONFIG_PAGE_RD_PDISK_1, - Mpi2RaidPhysDiskPage1_t, - *pMpi2RaidPhysDiskPage1_t; - -#define MPI2_RAIDPHYSDISKPAGE1_PAGEVERSION (0x02) - - -/**************************************************************************** -* values for fields used by several types of SAS Config Pages -****************************************************************************/ - -/*values for NegotiatedLinkRates fields */ -#define MPI2_SAS_NEG_LINK_RATE_MASK_LOGICAL (0xF0) -#define MPI2_SAS_NEG_LINK_RATE_SHIFT_LOGICAL (4) -#define MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL (0x0F) -/*link rates used for Negotiated Physical and Logical Link Rate */ -#define MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE (0x00) -#define MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED (0x01) -#define MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED (0x02) -#define MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE (0x03) -#define MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR (0x04) -#define MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS (0x05) -#define MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY (0x06) -#define MPI2_SAS_NEG_LINK_RATE_1_5 (0x08) -#define MPI2_SAS_NEG_LINK_RATE_3_0 (0x09) -#define MPI2_SAS_NEG_LINK_RATE_6_0 (0x0A) -#define MPI25_SAS_NEG_LINK_RATE_12_0 (0x0B) - - -/*values for AttachedPhyInfo fields */ -#define MPI2_SAS_APHYINFO_INSIDE_ZPSDS_PERSISTENT (0x00000040) -#define MPI2_SAS_APHYINFO_REQUESTED_INSIDE_ZPSDS (0x00000020) -#define MPI2_SAS_APHYINFO_BREAK_REPLY_CAPABLE (0x00000010) - -#define MPI2_SAS_APHYINFO_REASON_MASK (0x0000000F) -#define MPI2_SAS_APHYINFO_REASON_UNKNOWN (0x00000000) -#define MPI2_SAS_APHYINFO_REASON_POWER_ON (0x00000001) -#define MPI2_SAS_APHYINFO_REASON_HARD_RESET (0x00000002) -#define MPI2_SAS_APHYINFO_REASON_SMP_PHY_CONTROL (0x00000003) -#define MPI2_SAS_APHYINFO_REASON_LOSS_OF_SYNC (0x00000004) -#define MPI2_SAS_APHYINFO_REASON_MULTIPLEXING_SEQ (0x00000005) -#define MPI2_SAS_APHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00000006) -#define MPI2_SAS_APHYINFO_REASON_BREAK_TIMEOUT (0x00000007) -#define MPI2_SAS_APHYINFO_REASON_PHY_TEST_STOPPED (0x00000008) - - -/*values for PhyInfo fields */ -#define MPI2_SAS_PHYINFO_PHY_VACANT (0x80000000) - -#define MPI2_SAS_PHYINFO_PHY_POWER_CONDITION_MASK (0x18000000) -#define MPI2_SAS_PHYINFO_SHIFT_PHY_POWER_CONDITION (27) -#define MPI2_SAS_PHYINFO_PHY_POWER_ACTIVE (0x00000000) -#define MPI2_SAS_PHYINFO_PHY_POWER_PARTIAL (0x08000000) -#define MPI2_SAS_PHYINFO_PHY_POWER_SLUMBER (0x10000000) - -#define MPI2_SAS_PHYINFO_CHANGED_REQ_INSIDE_ZPSDS (0x04000000) -#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS_PERSISTENT (0x02000000) -#define MPI2_SAS_PHYINFO_REQ_INSIDE_ZPSDS (0x01000000) -#define MPI2_SAS_PHYINFO_ZONE_GROUP_PERSISTENT (0x00400000) -#define MPI2_SAS_PHYINFO_INSIDE_ZPSDS (0x00200000) -#define MPI2_SAS_PHYINFO_ZONING_ENABLED (0x00100000) - -#define MPI2_SAS_PHYINFO_REASON_MASK (0x000F0000) -#define MPI2_SAS_PHYINFO_REASON_UNKNOWN (0x00000000) -#define MPI2_SAS_PHYINFO_REASON_POWER_ON (0x00010000) -#define MPI2_SAS_PHYINFO_REASON_HARD_RESET (0x00020000) -#define MPI2_SAS_PHYINFO_REASON_SMP_PHY_CONTROL (0x00030000) -#define MPI2_SAS_PHYINFO_REASON_LOSS_OF_SYNC (0x00040000) -#define MPI2_SAS_PHYINFO_REASON_MULTIPLEXING_SEQ (0x00050000) -#define MPI2_SAS_PHYINFO_REASON_IT_NEXUS_LOSS_TIMER (0x00060000) -#define MPI2_SAS_PHYINFO_REASON_BREAK_TIMEOUT (0x00070000) -#define MPI2_SAS_PHYINFO_REASON_PHY_TEST_STOPPED (0x00080000) - -#define MPI2_SAS_PHYINFO_MULTIPLEXING_SUPPORTED (0x00008000) -#define MPI2_SAS_PHYINFO_SATA_PORT_ACTIVE (0x00004000) -#define MPI2_SAS_PHYINFO_SATA_PORT_SELECTOR_PRESENT (0x00002000) -#define MPI2_SAS_PHYINFO_VIRTUAL_PHY (0x00001000) - -#define MPI2_SAS_PHYINFO_MASK_PARTIAL_PATHWAY_TIME (0x00000F00) -#define MPI2_SAS_PHYINFO_SHIFT_PARTIAL_PATHWAY_TIME (8) - -#define MPI2_SAS_PHYINFO_MASK_ROUTING_ATTRIBUTE (0x000000F0) -#define MPI2_SAS_PHYINFO_DIRECT_ROUTING (0x00000000) -#define MPI2_SAS_PHYINFO_SUBTRACTIVE_ROUTING (0x00000010) -#define MPI2_SAS_PHYINFO_TABLE_ROUTING (0x00000020) - - -/*values for SAS ProgrammedLinkRate fields */ -#define MPI2_SAS_PRATE_MAX_RATE_MASK (0xF0) -#define MPI2_SAS_PRATE_MAX_RATE_NOT_PROGRAMMABLE (0x00) -#define MPI2_SAS_PRATE_MAX_RATE_1_5 (0x80) -#define MPI2_SAS_PRATE_MAX_RATE_3_0 (0x90) -#define MPI2_SAS_PRATE_MAX_RATE_6_0 (0xA0) -#define MPI25_SAS_PRATE_MAX_RATE_12_0 (0xB0) -#define MPI2_SAS_PRATE_MIN_RATE_MASK (0x0F) -#define MPI2_SAS_PRATE_MIN_RATE_NOT_PROGRAMMABLE (0x00) -#define MPI2_SAS_PRATE_MIN_RATE_1_5 (0x08) -#define MPI2_SAS_PRATE_MIN_RATE_3_0 (0x09) -#define MPI2_SAS_PRATE_MIN_RATE_6_0 (0x0A) -#define MPI25_SAS_PRATE_MIN_RATE_12_0 (0x0B) - - -/*values for SAS HwLinkRate fields */ -#define MPI2_SAS_HWRATE_MAX_RATE_MASK (0xF0) -#define MPI2_SAS_HWRATE_MAX_RATE_1_5 (0x80) -#define MPI2_SAS_HWRATE_MAX_RATE_3_0 (0x90) -#define MPI2_SAS_HWRATE_MAX_RATE_6_0 (0xA0) -#define MPI25_SAS_HWRATE_MAX_RATE_12_0 (0xB0) -#define MPI2_SAS_HWRATE_MIN_RATE_MASK (0x0F) -#define MPI2_SAS_HWRATE_MIN_RATE_1_5 (0x08) -#define MPI2_SAS_HWRATE_MIN_RATE_3_0 (0x09) -#define MPI2_SAS_HWRATE_MIN_RATE_6_0 (0x0A) -#define MPI25_SAS_HWRATE_MIN_RATE_12_0 (0x0B) - - - -/**************************************************************************** -* SAS IO Unit Config Pages -****************************************************************************/ - -/*SAS IO Unit Page 0 */ - -typedef struct _MPI2_SAS_IO_UNIT0_PHY_DATA { - U8 Port; /*0x00 */ - U8 PortFlags; /*0x01 */ - U8 PhyFlags; /*0x02 */ - U8 NegotiatedLinkRate; /*0x03 */ - U32 ControllerPhyDeviceInfo;/*0x04 */ - U16 AttachedDevHandle; /*0x08 */ - U16 ControllerDevHandle; /*0x0A */ - U32 DiscoveryStatus; /*0x0C */ - U32 Reserved; /*0x10 */ -} MPI2_SAS_IO_UNIT0_PHY_DATA, - *PTR_MPI2_SAS_IO_UNIT0_PHY_DATA, - Mpi2SasIOUnit0PhyData_t, - *pMpi2SasIOUnit0PhyData_t; - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_SAS_IOUNIT0_PHY_MAX -#define MPI2_SAS_IOUNIT0_PHY_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1;/*0x08 */ - U8 NumPhys; /*0x0C */ - U8 Reserved2;/*0x0D */ - U16 Reserved3;/*0x0E */ - MPI2_SAS_IO_UNIT0_PHY_DATA - PhyData[MPI2_SAS_IOUNIT0_PHY_MAX]; /*0x10 */ -} MPI2_CONFIG_PAGE_SASIOUNIT_0, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_0, - Mpi2SasIOUnitPage0_t, *pMpi2SasIOUnitPage0_t; - -#define MPI2_SASIOUNITPAGE0_PAGEVERSION (0x05) - -/*values for SAS IO Unit Page 0 PortFlags */ -#define MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS (0x08) -#define MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG (0x01) - -/*values for SAS IO Unit Page 0 PhyFlags */ -#define MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED (0x10) -#define MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED (0x08) - -/*use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ - -/*see mpi2_sas.h for values for - *SAS IO Unit Page 0 ControllerPhyDeviceInfo values */ - -/*values for SAS IO Unit Page 0 DiscoveryStatus */ -#define MPI2_SASIOUNIT0_DS_MAX_ENCLOSURES_EXCEED (0x80000000) -#define MPI2_SASIOUNIT0_DS_MAX_EXPANDERS_EXCEED (0x40000000) -#define MPI2_SASIOUNIT0_DS_MAX_DEVICES_EXCEED (0x20000000) -#define MPI2_SASIOUNIT0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) -#define MPI2_SASIOUNIT0_DS_DOWNSTREAM_INITIATOR (0x08000000) -#define MPI2_SASIOUNIT0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) -#define MPI2_SASIOUNIT0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) -#define MPI2_SASIOUNIT0_DS_MULTI_PORT_DOMAIN (0x00002000) -#define MPI2_SASIOUNIT0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) -#define MPI2_SASIOUNIT0_DS_UNSUPPORTED_DEVICE (0x00000800) -#define MPI2_SASIOUNIT0_DS_TABLE_LINK (0x00000400) -#define MPI2_SASIOUNIT0_DS_SUBTRACTIVE_LINK (0x00000200) -#define MPI2_SASIOUNIT0_DS_SMP_CRC_ERROR (0x00000100) -#define MPI2_SASIOUNIT0_DS_SMP_FUNCTION_FAILED (0x00000080) -#define MPI2_SASIOUNIT0_DS_INDEX_NOT_EXIST (0x00000040) -#define MPI2_SASIOUNIT0_DS_OUT_ROUTE_ENTRIES (0x00000020) -#define MPI2_SASIOUNIT0_DS_SMP_TIMEOUT (0x00000010) -#define MPI2_SASIOUNIT0_DS_MULTIPLE_PORTS (0x00000004) -#define MPI2_SASIOUNIT0_DS_UNADDRESSABLE_DEVICE (0x00000002) -#define MPI2_SASIOUNIT0_DS_LOOP_DETECTED (0x00000001) - - -/*SAS IO Unit Page 1 */ - -typedef struct _MPI2_SAS_IO_UNIT1_PHY_DATA { - U8 Port; /*0x00 */ - U8 PortFlags; /*0x01 */ - U8 PhyFlags; /*0x02 */ - U8 MaxMinLinkRate; /*0x03 */ - U32 ControllerPhyDeviceInfo; /*0x04 */ - U16 MaxTargetPortConnectTime; /*0x08 */ - U16 Reserved1; /*0x0A */ -} MPI2_SAS_IO_UNIT1_PHY_DATA, - *PTR_MPI2_SAS_IO_UNIT1_PHY_DATA, - Mpi2SasIOUnit1PhyData_t, - *pMpi2SasIOUnit1PhyData_t; - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_SAS_IOUNIT1_PHY_MAX -#define MPI2_SAS_IOUNIT1_PHY_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_1 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U16 - ControlFlags; /*0x08 */ - U16 - SASNarrowMaxQueueDepth; /*0x0A */ - U16 - AdditionalControlFlags; /*0x0C */ - U16 - SASWideMaxQueueDepth; /*0x0E */ - U8 - NumPhys; /*0x10 */ - U8 - SATAMaxQDepth; /*0x11 */ - U8 - ReportDeviceMissingDelay; /*0x12 */ - U8 - IODeviceMissingDelay; /*0x13 */ - MPI2_SAS_IO_UNIT1_PHY_DATA - PhyData[MPI2_SAS_IOUNIT1_PHY_MAX]; /*0x14 */ -} MPI2_CONFIG_PAGE_SASIOUNIT_1, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_1, - Mpi2SasIOUnitPage1_t, *pMpi2SasIOUnitPage1_t; - -#define MPI2_SASIOUNITPAGE1_PAGEVERSION (0x09) - -/*values for SAS IO Unit Page 1 ControlFlags */ -#define MPI2_SASIOUNIT1_CONTROL_DEVICE_SELF_TEST (0x8000) -#define MPI2_SASIOUNIT1_CONTROL_SATA_3_0_MAX (0x4000) -#define MPI2_SASIOUNIT1_CONTROL_SATA_1_5_MAX (0x2000) -#define MPI2_SASIOUNIT1_CONTROL_SATA_SW_PRESERVE (0x1000) - -#define MPI2_SASIOUNIT1_CONTROL_MASK_DEV_SUPPORT (0x0600) -#define MPI2_SASIOUNIT1_CONTROL_SHIFT_DEV_SUPPORT (9) -#define MPI2_SASIOUNIT1_CONTROL_DEV_SUPPORT_BOTH (0x0) -#define MPI2_SASIOUNIT1_CONTROL_DEV_SAS_SUPPORT (0x1) -#define MPI2_SASIOUNIT1_CONTROL_DEV_SATA_SUPPORT (0x2) - -#define MPI2_SASIOUNIT1_CONTROL_SATA_48BIT_LBA_REQUIRED (0x0080) -#define MPI2_SASIOUNIT1_CONTROL_SATA_SMART_REQUIRED (0x0040) -#define MPI2_SASIOUNIT1_CONTROL_SATA_NCQ_REQUIRED (0x0020) -#define MPI2_SASIOUNIT1_CONTROL_SATA_FUA_REQUIRED (0x0010) -#define MPI2_SASIOUNIT1_CONTROL_TABLE_SUBTRACTIVE_ILLEGAL (0x0008) -#define MPI2_SASIOUNIT1_CONTROL_SUBTRACTIVE_ILLEGAL (0x0004) -#define MPI2_SASIOUNIT1_CONTROL_FIRST_LVL_DISC_ONLY (0x0002) -#define MPI2_SASIOUNIT1_CONTROL_CLEAR_AFFILIATION (0x0001) - -/*values for SAS IO Unit Page 1 AdditionalControlFlags */ -#define MPI2_SASIOUNIT1_ACONTROL_MULTI_PORT_DOMAIN_ILLEGAL (0x0080) -#define MPI2_SASIOUNIT1_ACONTROL_SATA_ASYNCHROUNOUS_NOTIFICATION (0x0040) -#define MPI2_SASIOUNIT1_ACONTROL_INVALID_TOPOLOGY_CORRECTION (0x0020) -#define MPI2_SASIOUNIT1_ACONTROL_PORT_ENABLE_ONLY_SATA_LINK_RESET (0x0010) -#define MPI2_SASIOUNIT1_ACONTROL_OTHER_AFFILIATION_SATA_LINK_RESET (0x0008) -#define MPI2_SASIOUNIT1_ACONTROL_SELF_AFFILIATION_SATA_LINK_RESET (0x0004) -#define MPI2_SASIOUNIT1_ACONTROL_NO_AFFILIATION_SATA_LINK_RESET (0x0002) -#define MPI2_SASIOUNIT1_ACONTROL_ALLOW_TABLE_TO_TABLE (0x0001) - -/*defines for SAS IO Unit Page 1 ReportDeviceMissingDelay */ -#define MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK (0x7F) -#define MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16 (0x80) - -/*values for SAS IO Unit Page 1 PortFlags */ -#define MPI2_SASIOUNIT1_PORT_FLAGS_AUTO_PORT_CONFIG (0x01) - -/*values for SAS IO Unit Page 1 PhyFlags */ -#define MPI2_SASIOUNIT1_PHYFLAGS_ZONING_ENABLE (0x10) -#define MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE (0x08) - -/*values for SAS IO Unit Page 1 MaxMinLinkRate */ -#define MPI2_SASIOUNIT1_MAX_RATE_MASK (0xF0) -#define MPI2_SASIOUNIT1_MAX_RATE_1_5 (0x80) -#define MPI2_SASIOUNIT1_MAX_RATE_3_0 (0x90) -#define MPI2_SASIOUNIT1_MAX_RATE_6_0 (0xA0) -#define MPI25_SASIOUNIT1_MAX_RATE_12_0 (0xB0) -#define MPI2_SASIOUNIT1_MIN_RATE_MASK (0x0F) -#define MPI2_SASIOUNIT1_MIN_RATE_1_5 (0x08) -#define MPI2_SASIOUNIT1_MIN_RATE_3_0 (0x09) -#define MPI2_SASIOUNIT1_MIN_RATE_6_0 (0x0A) -#define MPI25_SASIOUNIT1_MIN_RATE_12_0 (0x0B) - -/*see mpi2_sas.h for values for - *SAS IO Unit Page 1 ControllerPhyDeviceInfo values */ - - -/*SAS IO Unit Page 4 */ - -typedef struct _MPI2_SAS_IOUNIT4_SPINUP_GROUP { - U8 MaxTargetSpinup; /*0x00 */ - U8 SpinupDelay; /*0x01 */ - U8 SpinupFlags; /*0x02 */ - U8 Reserved1; /*0x03 */ -} MPI2_SAS_IOUNIT4_SPINUP_GROUP, - *PTR_MPI2_SAS_IOUNIT4_SPINUP_GROUP, - Mpi2SasIOUnit4SpinupGroup_t, - *pMpi2SasIOUnit4SpinupGroup_t; -/*defines for SAS IO Unit Page 4 SpinupFlags */ -#define MPI2_SASIOUNIT4_SPINUP_DISABLE_FLAG (0x01) - - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_SAS_IOUNIT4_PHY_MAX -#define MPI2_SAS_IOUNIT4_PHY_MAX (4) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_4 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header;/*0x00 */ - MPI2_SAS_IOUNIT4_SPINUP_GROUP - SpinupGroupParameters[4]; /*0x08 */ - U32 - Reserved1; /*0x18 */ - U32 - Reserved2; /*0x1C */ - U32 - Reserved3; /*0x20 */ - U8 - BootDeviceWaitTime; /*0x24 */ - U8 - Reserved4; /*0x25 */ - U16 - Reserved5; /*0x26 */ - U8 - NumPhys; /*0x28 */ - U8 - PEInitialSpinupDelay; /*0x29 */ - U8 - PEReplyDelay; /*0x2A */ - U8 - Flags; /*0x2B */ - U8 - PHY[MPI2_SAS_IOUNIT4_PHY_MAX]; /*0x2C */ -} MPI2_CONFIG_PAGE_SASIOUNIT_4, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_4, - Mpi2SasIOUnitPage4_t, *pMpi2SasIOUnitPage4_t; - -#define MPI2_SASIOUNITPAGE4_PAGEVERSION (0x02) - -/*defines for Flags field */ -#define MPI2_SASIOUNIT4_FLAGS_AUTO_PORTENABLE (0x01) - -/*defines for PHY field */ -#define MPI2_SASIOUNIT4_PHY_SPINUP_GROUP_MASK (0x03) - - -/*SAS IO Unit Page 5 */ - -typedef struct _MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS { - U8 ControlFlags; /*0x00 */ - U8 PortWidthModGroup; /*0x01 */ - U16 InactivityTimerExponent; /*0x02 */ - U8 SATAPartialTimeout; /*0x04 */ - U8 Reserved2; /*0x05 */ - U8 SATASlumberTimeout; /*0x06 */ - U8 Reserved3; /*0x07 */ - U8 SASPartialTimeout; /*0x08 */ - U8 Reserved4; /*0x09 */ - U8 SASSlumberTimeout; /*0x0A */ - U8 Reserved5; /*0x0B */ -} MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS, - *PTR_MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS, - Mpi2SasIOUnit5PhyPmSettings_t, - *pMpi2SasIOUnit5PhyPmSettings_t; - -/*defines for ControlFlags field */ -#define MPI2_SASIOUNIT5_CONTROL_SAS_SLUMBER_ENABLE (0x08) -#define MPI2_SASIOUNIT5_CONTROL_SAS_PARTIAL_ENABLE (0x04) -#define MPI2_SASIOUNIT5_CONTROL_SATA_SLUMBER_ENABLE (0x02) -#define MPI2_SASIOUNIT5_CONTROL_SATA_PARTIAL_ENABLE (0x01) - -/*defines for PortWidthModeGroup field */ -#define MPI2_SASIOUNIT5_PWMG_DISABLE (0xFF) - -/*defines for InactivityTimerExponent field */ -#define MPI2_SASIOUNIT5_ITE_MASK_SAS_SLUMBER (0x7000) -#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_SLUMBER (12) -#define MPI2_SASIOUNIT5_ITE_MASK_SAS_PARTIAL (0x0700) -#define MPI2_SASIOUNIT5_ITE_SHIFT_SAS_PARTIAL (8) -#define MPI2_SASIOUNIT5_ITE_MASK_SATA_SLUMBER (0x0070) -#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_SLUMBER (4) -#define MPI2_SASIOUNIT5_ITE_MASK_SATA_PARTIAL (0x0007) -#define MPI2_SASIOUNIT5_ITE_SHIFT_SATA_PARTIAL (0) - -#define MPI2_SASIOUNIT5_ITE_TEN_SECONDS (7) -#define MPI2_SASIOUNIT5_ITE_ONE_SECOND (6) -#define MPI2_SASIOUNIT5_ITE_HUNDRED_MILLISECONDS (5) -#define MPI2_SASIOUNIT5_ITE_TEN_MILLISECONDS (4) -#define MPI2_SASIOUNIT5_ITE_ONE_MILLISECOND (3) -#define MPI2_SASIOUNIT5_ITE_HUNDRED_MICROSECONDS (2) -#define MPI2_SASIOUNIT5_ITE_TEN_MICROSECONDS (1) -#define MPI2_SASIOUNIT5_ITE_ONE_MICROSECOND (0) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhys at runtime. - */ -#ifndef MPI2_SAS_IOUNIT5_PHY_MAX -#define MPI2_SAS_IOUNIT5_PHY_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_5 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U8 NumPhys; /*0x08 */ - U8 Reserved1;/*0x09 */ - U16 Reserved2;/*0x0A */ - U32 Reserved3;/*0x0C */ - MPI2_SAS_IO_UNIT5_PHY_PM_SETTINGS - SASPhyPowerManagementSettings[MPI2_SAS_IOUNIT5_PHY_MAX];/*0x10 */ -} MPI2_CONFIG_PAGE_SASIOUNIT_5, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_5, - Mpi2SasIOUnitPage5_t, *pMpi2SasIOUnitPage5_t; - -#define MPI2_SASIOUNITPAGE5_PAGEVERSION (0x01) - - -/*SAS IO Unit Page 6 */ - -typedef struct _MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS { - U8 CurrentStatus; /*0x00 */ - U8 CurrentModulation; /*0x01 */ - U8 CurrentUtilization; /*0x02 */ - U8 Reserved1; /*0x03 */ - U32 Reserved2; /*0x04 */ -} MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS, - *PTR_MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS, - Mpi2SasIOUnit6PortWidthModGroupStatus_t, - *pMpi2SasIOUnit6PortWidthModGroupStatus_t; - -/*defines for CurrentStatus field */ -#define MPI2_SASIOUNIT6_STATUS_UNAVAILABLE (0x00) -#define MPI2_SASIOUNIT6_STATUS_UNCONFIGURED (0x01) -#define MPI2_SASIOUNIT6_STATUS_INVALID_CONFIG (0x02) -#define MPI2_SASIOUNIT6_STATUS_LINK_DOWN (0x03) -#define MPI2_SASIOUNIT6_STATUS_OBSERVATION_ONLY (0x04) -#define MPI2_SASIOUNIT6_STATUS_INACTIVE (0x05) -#define MPI2_SASIOUNIT6_STATUS_ACTIVE_IOUNIT (0x06) -#define MPI2_SASIOUNIT6_STATUS_ACTIVE_HOST (0x07) - -/*defines for CurrentModulation field */ -#define MPI2_SASIOUNIT6_MODULATION_25_PERCENT (0x00) -#define MPI2_SASIOUNIT6_MODULATION_50_PERCENT (0x01) -#define MPI2_SASIOUNIT6_MODULATION_75_PERCENT (0x02) -#define MPI2_SASIOUNIT6_MODULATION_100_PERCENT (0x03) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumGroups at runtime. - */ -#ifndef MPI2_SAS_IOUNIT6_GROUP_MAX -#define MPI2_SAS_IOUNIT6_GROUP_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_6 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x08 */ - U32 Reserved2; /*0x0C */ - U8 NumGroups; /*0x10 */ - U8 Reserved3; /*0x11 */ - U16 Reserved4; /*0x12 */ - MPI2_SAS_IO_UNIT6_PORT_WIDTH_MOD_GROUP_STATUS - PortWidthModulationGroupStatus[MPI2_SAS_IOUNIT6_GROUP_MAX]; /*0x14 */ -} MPI2_CONFIG_PAGE_SASIOUNIT_6, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_6, - Mpi2SasIOUnitPage6_t, *pMpi2SasIOUnitPage6_t; - -#define MPI2_SASIOUNITPAGE6_PAGEVERSION (0x00) - - -/*SAS IO Unit Page 7 */ - -typedef struct _MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS { - U8 Flags; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U8 Threshold75Pct; /*0x04 */ - U8 Threshold50Pct; /*0x05 */ - U8 Threshold25Pct; /*0x06 */ - U8 Reserved3; /*0x07 */ -} MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS, - *PTR_MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS, - Mpi2SasIOUnit7PortWidthModGroupSettings_t, - *pMpi2SasIOUnit7PortWidthModGroupSettings_t; - -/*defines for Flags field */ -#define MPI2_SASIOUNIT7_FLAGS_ENABLE_PORT_WIDTH_MODULATION (0x01) - - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumGroups at runtime. - */ -#ifndef MPI2_SAS_IOUNIT7_GROUP_MAX -#define MPI2_SAS_IOUNIT7_GROUP_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_7 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U8 SamplingInterval; /*0x08 */ - U8 WindowLength; /*0x09 */ - U16 Reserved1; /*0x0A */ - U32 Reserved2; /*0x0C */ - U32 Reserved3; /*0x10 */ - U8 NumGroups; /*0x14 */ - U8 Reserved4; /*0x15 */ - U16 Reserved5; /*0x16 */ - MPI2_SAS_IO_UNIT7_PORT_WIDTH_MOD_GROUP_SETTINGS - PortWidthModulationGroupSettings[MPI2_SAS_IOUNIT7_GROUP_MAX];/*0x18 */ -} MPI2_CONFIG_PAGE_SASIOUNIT_7, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_7, - Mpi2SasIOUnitPage7_t, *pMpi2SasIOUnitPage7_t; - -#define MPI2_SASIOUNITPAGE7_PAGEVERSION (0x00) - - -/*SAS IO Unit Page 8 */ - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT_8 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved1; /*0x08 */ - U32 - PowerManagementCapabilities; /*0x0C */ - U8 - TxRxSleepStatus; /*0x10 */ - U8 - Reserved2; /*0x11 */ - U16 - Reserved3; /*0x12 */ -} MPI2_CONFIG_PAGE_SASIOUNIT_8, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT_8, - Mpi2SasIOUnitPage8_t, *pMpi2SasIOUnitPage8_t; - -#define MPI2_SASIOUNITPAGE8_PAGEVERSION (0x00) - -/*defines for PowerManagementCapabilities field */ -#define MPI2_SASIOUNIT8_PM_HOST_PORT_WIDTH_MOD (0x00001000) -#define MPI2_SASIOUNIT8_PM_HOST_SAS_SLUMBER_MODE (0x00000800) -#define MPI2_SASIOUNIT8_PM_HOST_SAS_PARTIAL_MODE (0x00000400) -#define MPI2_SASIOUNIT8_PM_HOST_SATA_SLUMBER_MODE (0x00000200) -#define MPI2_SASIOUNIT8_PM_HOST_SATA_PARTIAL_MODE (0x00000100) -#define MPI2_SASIOUNIT8_PM_IOUNIT_PORT_WIDTH_MOD (0x00000010) -#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_SLUMBER_MODE (0x00000008) -#define MPI2_SASIOUNIT8_PM_IOUNIT_SAS_PARTIAL_MODE (0x00000004) -#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_SLUMBER_MODE (0x00000002) -#define MPI2_SASIOUNIT8_PM_IOUNIT_SATA_PARTIAL_MODE (0x00000001) - -/*defines for TxRxSleepStatus field */ -#define MPI25_SASIOUNIT8_TXRXSLEEP_UNSUPPORTED (0x00) -#define MPI25_SASIOUNIT8_TXRXSLEEP_DISENGAGED (0x01) -#define MPI25_SASIOUNIT8_TXRXSLEEP_ACTIVE (0x02) -#define MPI25_SASIOUNIT8_TXRXSLEEP_SHUTDOWN (0x03) - - - -/*SAS IO Unit Page 16 */ - -typedef struct _MPI2_CONFIG_PAGE_SASIOUNIT16 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U64 - TimeStamp; /*0x08 */ - U32 - Reserved1; /*0x10 */ - U32 - Reserved2; /*0x14 */ - U32 - FastPathPendedRequests; /*0x18 */ - U32 - FastPathUnPendedRequests; /*0x1C */ - U32 - FastPathHostRequestStarts; /*0x20 */ - U32 - FastPathFirmwareRequestStarts; /*0x24 */ - U32 - FastPathHostCompletions; /*0x28 */ - U32 - FastPathFirmwareCompletions; /*0x2C */ - U32 - NonFastPathRequestStarts; /*0x30 */ - U32 - NonFastPathHostCompletions; /*0x30 */ -} MPI2_CONFIG_PAGE_SASIOUNIT16, - *PTR_MPI2_CONFIG_PAGE_SASIOUNIT16, - Mpi2SasIOUnitPage16_t, *pMpi2SasIOUnitPage16_t; - -#define MPI2_SASIOUNITPAGE16_PAGEVERSION (0x00) - - -/**************************************************************************** -* SAS Expander Config Pages -****************************************************************************/ - -/*SAS Expander Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_EXPANDER_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U8 - PhysicalPort; /*0x08 */ - U8 - ReportGenLength; /*0x09 */ - U16 - EnclosureHandle; /*0x0A */ - U64 - SASAddress; /*0x0C */ - U32 - DiscoveryStatus; /*0x14 */ - U16 - DevHandle; /*0x18 */ - U16 - ParentDevHandle; /*0x1A */ - U16 - ExpanderChangeCount; /*0x1C */ - U16 - ExpanderRouteIndexes; /*0x1E */ - U8 - NumPhys; /*0x20 */ - U8 - SASLevel; /*0x21 */ - U16 - Flags; /*0x22 */ - U16 - STPBusInactivityTimeLimit; /*0x24 */ - U16 - STPMaxConnectTimeLimit; /*0x26 */ - U16 - STP_SMP_NexusLossTime; /*0x28 */ - U16 - MaxNumRoutedSasAddresses; /*0x2A */ - U64 - ActiveZoneManagerSASAddress;/*0x2C */ - U16 - ZoneLockInactivityLimit; /*0x34 */ - U16 - Reserved1; /*0x36 */ - U8 - TimeToReducedFunc; /*0x38 */ - U8 - InitialTimeToReducedFunc; /*0x39 */ - U8 - MaxReducedFuncTime; /*0x3A */ - U8 - Reserved2; /*0x3B */ -} MPI2_CONFIG_PAGE_EXPANDER_0, - *PTR_MPI2_CONFIG_PAGE_EXPANDER_0, - Mpi2ExpanderPage0_t, *pMpi2ExpanderPage0_t; - -#define MPI2_SASEXPANDER0_PAGEVERSION (0x06) - -/*values for SAS Expander Page 0 DiscoveryStatus field */ -#define MPI2_SAS_EXPANDER0_DS_MAX_ENCLOSURES_EXCEED (0x80000000) -#define MPI2_SAS_EXPANDER0_DS_MAX_EXPANDERS_EXCEED (0x40000000) -#define MPI2_SAS_EXPANDER0_DS_MAX_DEVICES_EXCEED (0x20000000) -#define MPI2_SAS_EXPANDER0_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) -#define MPI2_SAS_EXPANDER0_DS_DOWNSTREAM_INITIATOR (0x08000000) -#define MPI2_SAS_EXPANDER0_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) -#define MPI2_SAS_EXPANDER0_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) -#define MPI2_SAS_EXPANDER0_DS_MULTI_PORT_DOMAIN (0x00002000) -#define MPI2_SAS_EXPANDER0_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) -#define MPI2_SAS_EXPANDER0_DS_UNSUPPORTED_DEVICE (0x00000800) -#define MPI2_SAS_EXPANDER0_DS_TABLE_LINK (0x00000400) -#define MPI2_SAS_EXPANDER0_DS_SUBTRACTIVE_LINK (0x00000200) -#define MPI2_SAS_EXPANDER0_DS_SMP_CRC_ERROR (0x00000100) -#define MPI2_SAS_EXPANDER0_DS_SMP_FUNCTION_FAILED (0x00000080) -#define MPI2_SAS_EXPANDER0_DS_INDEX_NOT_EXIST (0x00000040) -#define MPI2_SAS_EXPANDER0_DS_OUT_ROUTE_ENTRIES (0x00000020) -#define MPI2_SAS_EXPANDER0_DS_SMP_TIMEOUT (0x00000010) -#define MPI2_SAS_EXPANDER0_DS_MULTIPLE_PORTS (0x00000004) -#define MPI2_SAS_EXPANDER0_DS_UNADDRESSABLE_DEVICE (0x00000002) -#define MPI2_SAS_EXPANDER0_DS_LOOP_DETECTED (0x00000001) - -/*values for SAS Expander Page 0 Flags field */ -#define MPI2_SAS_EXPANDER0_FLAGS_REDUCED_FUNCTIONALITY (0x2000) -#define MPI2_SAS_EXPANDER0_FLAGS_ZONE_LOCKED (0x1000) -#define MPI2_SAS_EXPANDER0_FLAGS_SUPPORTED_PHYSICAL_PRES (0x0800) -#define MPI2_SAS_EXPANDER0_FLAGS_ASSERTED_PHYSICAL_PRES (0x0400) -#define MPI2_SAS_EXPANDER0_FLAGS_ZONING_SUPPORT (0x0200) -#define MPI2_SAS_EXPANDER0_FLAGS_ENABLED_ZONING (0x0100) -#define MPI2_SAS_EXPANDER0_FLAGS_TABLE_TO_TABLE_SUPPORT (0x0080) -#define MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE (0x0010) -#define MPI2_SAS_EXPANDER0_FLAGS_OTHERS_CONFIG (0x0004) -#define MPI2_SAS_EXPANDER0_FLAGS_CONFIG_IN_PROGRESS (0x0002) -#define MPI2_SAS_EXPANDER0_FLAGS_ROUTE_TABLE_CONFIG (0x0001) - - -/*SAS Expander Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_EXPANDER_1 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U8 - PhysicalPort; /*0x08 */ - U8 - Reserved1; /*0x09 */ - U16 - Reserved2; /*0x0A */ - U8 - NumPhys; /*0x0C */ - U8 - Phy; /*0x0D */ - U16 - NumTableEntriesProgrammed; /*0x0E */ - U8 - ProgrammedLinkRate; /*0x10 */ - U8 - HwLinkRate; /*0x11 */ - U16 - AttachedDevHandle; /*0x12 */ - U32 - PhyInfo; /*0x14 */ - U32 - AttachedDeviceInfo; /*0x18 */ - U16 - ExpanderDevHandle; /*0x1C */ - U8 - ChangeCount; /*0x1E */ - U8 - NegotiatedLinkRate; /*0x1F */ - U8 - PhyIdentifier; /*0x20 */ - U8 - AttachedPhyIdentifier; /*0x21 */ - U8 - Reserved3; /*0x22 */ - U8 - DiscoveryInfo; /*0x23 */ - U32 - AttachedPhyInfo; /*0x24 */ - U8 - ZoneGroup; /*0x28 */ - U8 - SelfConfigStatus; /*0x29 */ - U16 - Reserved4; /*0x2A */ -} MPI2_CONFIG_PAGE_EXPANDER_1, - *PTR_MPI2_CONFIG_PAGE_EXPANDER_1, - Mpi2ExpanderPage1_t, *pMpi2ExpanderPage1_t; - -#define MPI2_SASEXPANDER1_PAGEVERSION (0x02) - -/*use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */ - -/*use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */ - -/*use MPI2_SAS_PHYINFO_ for the PhyInfo field */ - -/*see mpi2_sas.h for the MPI2_SAS_DEVICE_INFO_ defines - *used for the AttachedDeviceInfo field */ - -/*use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ - -/*values for SAS Expander Page 1 DiscoveryInfo field */ -#define MPI2_SAS_EXPANDER1_DISCINFO_BAD_PHY_DISABLED (0x04) -#define MPI2_SAS_EXPANDER1_DISCINFO_LINK_STATUS_CHANGE (0x02) -#define MPI2_SAS_EXPANDER1_DISCINFO_NO_ROUTING_ENTRIES (0x01) - -/*use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ - - -/**************************************************************************** -* SAS Device Config Pages -****************************************************************************/ - -/*SAS Device Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U16 - Slot; /*0x08 */ - U16 - EnclosureHandle; /*0x0A */ - U64 - SASAddress; /*0x0C */ - U16 - ParentDevHandle; /*0x14 */ - U8 - PhyNum; /*0x16 */ - U8 - AccessStatus; /*0x17 */ - U16 - DevHandle; /*0x18 */ - U8 - AttachedPhyIdentifier; /*0x1A */ - U8 - ZoneGroup; /*0x1B */ - U32 - DeviceInfo; /*0x1C */ - U16 - Flags; /*0x20 */ - U8 - PhysicalPort; /*0x22 */ - U8 - MaxPortConnections; /*0x23 */ - U64 - DeviceName; /*0x24 */ - U8 - PortGroups; /*0x2C */ - U8 - DmaGroup; /*0x2D */ - U8 - ControlGroup; /*0x2E */ - U8 - EnclosureLevel; /*0x2F */ - U32 - ConnectorName[4]; /*0x30 */ - U32 - Reserved3; /*0x34 */ -} MPI2_CONFIG_PAGE_SAS_DEV_0, - *PTR_MPI2_CONFIG_PAGE_SAS_DEV_0, - Mpi2SasDevicePage0_t, - *pMpi2SasDevicePage0_t; - -#define MPI2_SASDEVICE0_PAGEVERSION (0x09) - -/*values for SAS Device Page 0 AccessStatus field */ -#define MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS (0x00) -#define MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED (0x01) -#define MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED (0x02) -#define MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT (0x03) -#define MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION (0x04) -#define MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE (0x05) -#define MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE (0x06) -#define MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED (0x07) -/*specific values for SATA Init failures */ -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN (0x10) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT (0x11) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG (0x12) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION (0x13) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER (0x14) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN (0x15) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN (0x16) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN (0x17) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION (0x18) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE (0x19) -#define MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX (0x1F) - -/*see mpi2_sas.h for values for SAS Device Page 0 DeviceInfo values */ - -/*values for SAS Device Page 0 Flags field */ -#define MPI2_SAS_DEVICE0_FLAGS_UNAUTHORIZED_DEVICE (0x8000) -#define MPI25_SAS_DEVICE0_FLAGS_ENABLED_FAST_PATH (0x4000) -#define MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE (0x2000) -#define MPI2_SAS_DEVICE0_FLAGS_SLUMBER_PM_CAPABLE (0x1000) -#define MPI2_SAS_DEVICE0_FLAGS_PARTIAL_PM_CAPABLE (0x0800) -#define MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY (0x0400) -#define MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE (0x0200) -#define MPI2_SAS_DEVICE0_FLAGS_UNSUPPORTED_DEVICE (0x0100) -#define MPI2_SAS_DEVICE0_FLAGS_SATA_48BIT_LBA_SUPPORTED (0x0080) -#define MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED (0x0040) -#define MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED (0x0020) -#define MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED (0x0010) -#define MPI2_SAS_DEVICE0_FLAGS_PORT_SELECTOR_ATTACH (0x0008) -#define MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID (0x0002) -#define MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT (0x0001) - - -/*SAS Device Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_DEV_1 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved1; /*0x08 */ - U64 - SASAddress; /*0x0C */ - U32 - Reserved2; /*0x14 */ - U16 - DevHandle; /*0x18 */ - U16 - Reserved3; /*0x1A */ - U8 - InitialRegDeviceFIS[20];/*0x1C */ -} MPI2_CONFIG_PAGE_SAS_DEV_1, - *PTR_MPI2_CONFIG_PAGE_SAS_DEV_1, - Mpi2SasDevicePage1_t, - *pMpi2SasDevicePage1_t; - -#define MPI2_SASDEVICE1_PAGEVERSION (0x01) - - -/**************************************************************************** -* SAS PHY Config Pages -****************************************************************************/ - -/*SAS PHY Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U16 - OwnerDevHandle; /*0x08 */ - U16 - Reserved1; /*0x0A */ - U16 - AttachedDevHandle; /*0x0C */ - U8 - AttachedPhyIdentifier; /*0x0E */ - U8 - Reserved2; /*0x0F */ - U32 - AttachedPhyInfo; /*0x10 */ - U8 - ProgrammedLinkRate; /*0x14 */ - U8 - HwLinkRate; /*0x15 */ - U8 - ChangeCount; /*0x16 */ - U8 - Flags; /*0x17 */ - U32 - PhyInfo; /*0x18 */ - U8 - NegotiatedLinkRate; /*0x1C */ - U8 - Reserved3; /*0x1D */ - U16 - Reserved4; /*0x1E */ -} MPI2_CONFIG_PAGE_SAS_PHY_0, - *PTR_MPI2_CONFIG_PAGE_SAS_PHY_0, - Mpi2SasPhyPage0_t, *pMpi2SasPhyPage0_t; - -#define MPI2_SASPHY0_PAGEVERSION (0x03) - -/*use MPI2_SAS_APHYINFO_ defines for AttachedPhyInfo field */ - -/*use MPI2_SAS_PRATE_ defines for the ProgrammedLinkRate field */ - -/*use MPI2_SAS_HWRATE_ defines for the HwLinkRate field */ - -/*values for SAS PHY Page 0 Flags field */ -#define MPI2_SAS_PHY0_FLAGS_SGPIO_DIRECT_ATTACH_ENC (0x01) - -/*use MPI2_SAS_PHYINFO_ for the PhyInfo field */ - -/*use MPI2_SAS_NEG_LINK_RATE_ defines for the NegotiatedLinkRate field */ - - -/*SAS PHY Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_1 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved1; /*0x08 */ - U32 - InvalidDwordCount; /*0x0C */ - U32 - RunningDisparityErrorCount; /*0x10 */ - U32 - LossDwordSynchCount; /*0x14 */ - U32 - PhyResetProblemCount; /*0x18 */ -} MPI2_CONFIG_PAGE_SAS_PHY_1, - *PTR_MPI2_CONFIG_PAGE_SAS_PHY_1, - Mpi2SasPhyPage1_t, *pMpi2SasPhyPage1_t; - -#define MPI2_SASPHY1_PAGEVERSION (0x01) - - -/*SAS PHY Page 2 */ - -typedef struct _MPI2_SASPHY2_PHY_EVENT { - U8 PhyEventCode; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 PhyEventInfo; /*0x04 */ -} MPI2_SASPHY2_PHY_EVENT, *PTR_MPI2_SASPHY2_PHY_EVENT, - Mpi2SasPhy2PhyEvent_t, *pMpi2SasPhy2PhyEvent_t; - -/*use MPI2_SASPHY3_EVENT_CODE_ for the PhyEventCode field */ - - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhyEvents at runtime. - */ -#ifndef MPI2_SASPHY2_PHY_EVENT_MAX -#define MPI2_SASPHY2_PHY_EVENT_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_2 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved1; /*0x08 */ - U8 - NumPhyEvents; /*0x0C */ - U8 - Reserved2; /*0x0D */ - U16 - Reserved3; /*0x0E */ - MPI2_SASPHY2_PHY_EVENT - PhyEvent[MPI2_SASPHY2_PHY_EVENT_MAX]; /*0x10 */ -} MPI2_CONFIG_PAGE_SAS_PHY_2, - *PTR_MPI2_CONFIG_PAGE_SAS_PHY_2, - Mpi2SasPhyPage2_t, - *pMpi2SasPhyPage2_t; - -#define MPI2_SASPHY2_PAGEVERSION (0x00) - - -/*SAS PHY Page 3 */ - -typedef struct _MPI2_SASPHY3_PHY_EVENT_CONFIG { - U8 PhyEventCode; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U8 CounterType; /*0x04 */ - U8 ThresholdWindow; /*0x05 */ - U8 TimeUnits; /*0x06 */ - U8 Reserved3; /*0x07 */ - U32 EventThreshold; /*0x08 */ - U16 ThresholdFlags; /*0x0C */ - U16 Reserved4; /*0x0E */ -} MPI2_SASPHY3_PHY_EVENT_CONFIG, - *PTR_MPI2_SASPHY3_PHY_EVENT_CONFIG, - Mpi2SasPhy3PhyEventConfig_t, - *pMpi2SasPhy3PhyEventConfig_t; - -/*values for PhyEventCode field */ -#define MPI2_SASPHY3_EVENT_CODE_NO_EVENT (0x00) -#define MPI2_SASPHY3_EVENT_CODE_INVALID_DWORD (0x01) -#define MPI2_SASPHY3_EVENT_CODE_RUNNING_DISPARITY_ERROR (0x02) -#define MPI2_SASPHY3_EVENT_CODE_LOSS_DWORD_SYNC (0x03) -#define MPI2_SASPHY3_EVENT_CODE_PHY_RESET_PROBLEM (0x04) -#define MPI2_SASPHY3_EVENT_CODE_ELASTICITY_BUF_OVERFLOW (0x05) -#define MPI2_SASPHY3_EVENT_CODE_RX_ERROR (0x06) -#define MPI2_SASPHY3_EVENT_CODE_RX_ADDR_FRAME_ERROR (0x20) -#define MPI2_SASPHY3_EVENT_CODE_TX_AC_OPEN_REJECT (0x21) -#define MPI2_SASPHY3_EVENT_CODE_RX_AC_OPEN_REJECT (0x22) -#define MPI2_SASPHY3_EVENT_CODE_TX_RC_OPEN_REJECT (0x23) -#define MPI2_SASPHY3_EVENT_CODE_RX_RC_OPEN_REJECT (0x24) -#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_PARTIAL_WAITING_ON (0x25) -#define MPI2_SASPHY3_EVENT_CODE_RX_AIP_CONNECT_WAITING_ON (0x26) -#define MPI2_SASPHY3_EVENT_CODE_TX_BREAK (0x27) -#define MPI2_SASPHY3_EVENT_CODE_RX_BREAK (0x28) -#define MPI2_SASPHY3_EVENT_CODE_BREAK_TIMEOUT (0x29) -#define MPI2_SASPHY3_EVENT_CODE_CONNECTION (0x2A) -#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_PATHWAY_BLOCKED (0x2B) -#define MPI2_SASPHY3_EVENT_CODE_PEAKTX_ARB_WAIT_TIME (0x2C) -#define MPI2_SASPHY3_EVENT_CODE_PEAK_ARB_WAIT_TIME (0x2D) -#define MPI2_SASPHY3_EVENT_CODE_PEAK_CONNECT_TIME (0x2E) -#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_FRAMES (0x40) -#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_FRAMES (0x41) -#define MPI2_SASPHY3_EVENT_CODE_TX_SSP_ERROR_FRAMES (0x42) -#define MPI2_SASPHY3_EVENT_CODE_RX_SSP_ERROR_FRAMES (0x43) -#define MPI2_SASPHY3_EVENT_CODE_TX_CREDIT_BLOCKED (0x44) -#define MPI2_SASPHY3_EVENT_CODE_RX_CREDIT_BLOCKED (0x45) -#define MPI2_SASPHY3_EVENT_CODE_TX_SATA_FRAMES (0x50) -#define MPI2_SASPHY3_EVENT_CODE_RX_SATA_FRAMES (0x51) -#define MPI2_SASPHY3_EVENT_CODE_SATA_OVERFLOW (0x52) -#define MPI2_SASPHY3_EVENT_CODE_TX_SMP_FRAMES (0x60) -#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_FRAMES (0x61) -#define MPI2_SASPHY3_EVENT_CODE_RX_SMP_ERROR_FRAMES (0x63) -#define MPI2_SASPHY3_EVENT_CODE_HOTPLUG_TIMEOUT (0xD0) -#define MPI2_SASPHY3_EVENT_CODE_MISALIGNED_MUX_PRIMITIVE (0xD1) -#define MPI2_SASPHY3_EVENT_CODE_RX_AIP (0xD2) - -/*values for the CounterType field */ -#define MPI2_SASPHY3_COUNTER_TYPE_WRAPPING (0x00) -#define MPI2_SASPHY3_COUNTER_TYPE_SATURATING (0x01) -#define MPI2_SASPHY3_COUNTER_TYPE_PEAK_VALUE (0x02) - -/*values for the TimeUnits field */ -#define MPI2_SASPHY3_TIME_UNITS_10_MICROSECONDS (0x00) -#define MPI2_SASPHY3_TIME_UNITS_100_MICROSECONDS (0x01) -#define MPI2_SASPHY3_TIME_UNITS_1_MILLISECOND (0x02) -#define MPI2_SASPHY3_TIME_UNITS_10_MILLISECONDS (0x03) - -/*values for the ThresholdFlags field */ -#define MPI2_SASPHY3_TFLAGS_PHY_RESET (0x0002) -#define MPI2_SASPHY3_TFLAGS_EVENT_NOTIFY (0x0001) - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumPhyEvents at runtime. - */ -#ifndef MPI2_SASPHY3_PHY_EVENT_MAX -#define MPI2_SASPHY3_PHY_EVENT_MAX (1) -#endif - -typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_3 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved1; /*0x08 */ - U8 - NumPhyEvents; /*0x0C */ - U8 - Reserved2; /*0x0D */ - U16 - Reserved3; /*0x0E */ - MPI2_SASPHY3_PHY_EVENT_CONFIG - PhyEventConfig[MPI2_SASPHY3_PHY_EVENT_MAX]; /*0x10 */ -} MPI2_CONFIG_PAGE_SAS_PHY_3, - *PTR_MPI2_CONFIG_PAGE_SAS_PHY_3, - Mpi2SasPhyPage3_t, *pMpi2SasPhyPage3_t; - -#define MPI2_SASPHY3_PAGEVERSION (0x00) - - -/*SAS PHY Page 4 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_PHY_4 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U16 - Reserved1; /*0x08 */ - U8 - Reserved2; /*0x0A */ - U8 - Flags; /*0x0B */ - U8 - InitialFrame[28]; /*0x0C */ -} MPI2_CONFIG_PAGE_SAS_PHY_4, - *PTR_MPI2_CONFIG_PAGE_SAS_PHY_4, - Mpi2SasPhyPage4_t, *pMpi2SasPhyPage4_t; - -#define MPI2_SASPHY4_PAGEVERSION (0x00) - -/*values for the Flags field */ -#define MPI2_SASPHY4_FLAGS_FRAME_VALID (0x02) -#define MPI2_SASPHY4_FLAGS_SATA_FRAME (0x01) - - - - -/**************************************************************************** -* SAS Port Config Pages -****************************************************************************/ - -/*SAS Port Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_PORT_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U8 - PortNumber; /*0x08 */ - U8 - PhysicalPort; /*0x09 */ - U8 - PortWidth; /*0x0A */ - U8 - PhysicalPortWidth; /*0x0B */ - U8 - ZoneGroup; /*0x0C */ - U8 - Reserved1; /*0x0D */ - U16 - Reserved2; /*0x0E */ - U64 - SASAddress; /*0x10 */ - U32 - DeviceInfo; /*0x18 */ - U32 - Reserved3; /*0x1C */ - U32 - Reserved4; /*0x20 */ -} MPI2_CONFIG_PAGE_SAS_PORT_0, - *PTR_MPI2_CONFIG_PAGE_SAS_PORT_0, - Mpi2SasPortPage0_t, *pMpi2SasPortPage0_t; - -#define MPI2_SASPORT0_PAGEVERSION (0x00) - -/*see mpi2_sas.h for values for SAS Port Page 0 DeviceInfo values */ - - -/**************************************************************************** -* SAS Enclosure Config Pages -****************************************************************************/ - -/*SAS Enclosure Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved1; /*0x08 */ - U64 - EnclosureLogicalID; /*0x0C */ - U16 - Flags; /*0x14 */ - U16 - EnclosureHandle; /*0x16 */ - U16 - NumSlots; /*0x18 */ - U16 - StartSlot; /*0x1A */ - U8 - Reserved2; /*0x1C */ - U8 - EnclosureLevel; /*0x1D */ - U16 - SEPDevHandle; /*0x1E */ - U32 - Reserved3; /*0x20 */ - U32 - Reserved4; /*0x24 */ -} MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0, - *PTR_MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0, - Mpi2SasEnclosurePage0_t, *pMpi2SasEnclosurePage0_t; - -#define MPI2_SASENCLOSURE0_PAGEVERSION (0x04) - -/*values for SAS Enclosure Page 0 Flags field */ -#define MPI2_SAS_ENCLS0_FLAGS_ENCL_LEVEL_VALID (0x0010) -#define MPI2_SAS_ENCLS0_FLAGS_MNG_MASK (0x000F) -#define MPI2_SAS_ENCLS0_FLAGS_MNG_UNKNOWN (0x0000) -#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SES (0x0001) -#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_SGPIO (0x0002) -#define MPI2_SAS_ENCLS0_FLAGS_MNG_EXP_SGPIO (0x0003) -#define MPI2_SAS_ENCLS0_FLAGS_MNG_SES_ENCLOSURE (0x0004) -#define MPI2_SAS_ENCLS0_FLAGS_MNG_IOC_GPIO (0x0005) - - -/**************************************************************************** -* Log Config Page -****************************************************************************/ - -/*Log Page 0 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumLogEntries at runtime. - */ -#ifndef MPI2_LOG_0_NUM_LOG_ENTRIES -#define MPI2_LOG_0_NUM_LOG_ENTRIES (1) -#endif - -#define MPI2_LOG_0_LOG_DATA_LENGTH (0x1C) - -typedef struct _MPI2_LOG_0_ENTRY { - U64 TimeStamp; /*0x00 */ - U32 Reserved1; /*0x08 */ - U16 LogSequence; /*0x0C */ - U16 LogEntryQualifier; /*0x0E */ - U8 VP_ID; /*0x10 */ - U8 VF_ID; /*0x11 */ - U16 Reserved2; /*0x12 */ - U8 - LogData[MPI2_LOG_0_LOG_DATA_LENGTH];/*0x14 */ -} MPI2_LOG_0_ENTRY, *PTR_MPI2_LOG_0_ENTRY, - Mpi2Log0Entry_t, *pMpi2Log0Entry_t; - -/*values for Log Page 0 LogEntry LogEntryQualifier field */ -#define MPI2_LOG_0_ENTRY_QUAL_ENTRY_UNUSED (0x0000) -#define MPI2_LOG_0_ENTRY_QUAL_POWER_ON_RESET (0x0001) -#define MPI2_LOG_0_ENTRY_QUAL_TIMESTAMP_UPDATE (0x0002) -#define MPI2_LOG_0_ENTRY_QUAL_MIN_IMPLEMENT_SPEC (0x8000) -#define MPI2_LOG_0_ENTRY_QUAL_MAX_IMPLEMENT_SPEC (0xFFFF) - -typedef struct _MPI2_CONFIG_PAGE_LOG_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U32 Reserved1; /*0x08 */ - U32 Reserved2; /*0x0C */ - U16 NumLogEntries;/*0x10 */ - U16 Reserved3; /*0x12 */ - MPI2_LOG_0_ENTRY - LogEntry[MPI2_LOG_0_NUM_LOG_ENTRIES]; /*0x14 */ -} MPI2_CONFIG_PAGE_LOG_0, *PTR_MPI2_CONFIG_PAGE_LOG_0, - Mpi2LogPage0_t, *pMpi2LogPage0_t; - -#define MPI2_LOG_0_PAGEVERSION (0x02) - - -/**************************************************************************** -* RAID Config Page -****************************************************************************/ - -/*RAID Page 0 */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check the value returned for NumElements at runtime. - */ -#ifndef MPI2_RAIDCONFIG0_MAX_ELEMENTS -#define MPI2_RAIDCONFIG0_MAX_ELEMENTS (1) -#endif - -typedef struct _MPI2_RAIDCONFIG0_CONFIG_ELEMENT { - U16 ElementFlags; /*0x00 */ - U16 VolDevHandle; /*0x02 */ - U8 HotSparePool; /*0x04 */ - U8 PhysDiskNum; /*0x05 */ - U16 PhysDiskDevHandle; /*0x06 */ -} MPI2_RAIDCONFIG0_CONFIG_ELEMENT, - *PTR_MPI2_RAIDCONFIG0_CONFIG_ELEMENT, - Mpi2RaidConfig0ConfigElement_t, - *pMpi2RaidConfig0ConfigElement_t; - -/*values for the ElementFlags field */ -#define MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE (0x000F) -#define MPI2_RAIDCONFIG0_EFLAGS_VOLUME_ELEMENT (0x0000) -#define MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT (0x0001) -#define MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT (0x0002) -#define MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT (0x0003) - - -typedef struct _MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U8 NumHotSpares; /*0x08 */ - U8 NumPhysDisks; /*0x09 */ - U8 NumVolumes; /*0x0A */ - U8 ConfigNum; /*0x0B */ - U32 Flags; /*0x0C */ - U8 ConfigGUID[24]; /*0x10 */ - U32 Reserved1; /*0x28 */ - U8 NumElements; /*0x2C */ - U8 Reserved2; /*0x2D */ - U16 Reserved3; /*0x2E */ - MPI2_RAIDCONFIG0_CONFIG_ELEMENT - ConfigElement[MPI2_RAIDCONFIG0_MAX_ELEMENTS]; /*0x30 */ -} MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0, - *PTR_MPI2_CONFIG_PAGE_RAID_CONFIGURATION_0, - Mpi2RaidConfigurationPage0_t, - *pMpi2RaidConfigurationPage0_t; - -#define MPI2_RAIDCONFIG0_PAGEVERSION (0x00) - -/*values for RAID Configuration Page 0 Flags field */ -#define MPI2_RAIDCONFIG0_FLAG_FOREIGN_CONFIG (0x00000001) - - -/**************************************************************************** -* Driver Persistent Mapping Config Pages -****************************************************************************/ - -/*Driver Persistent Mapping Page 0 */ - -typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY { - U64 PhysicalIdentifier; /*0x00 */ - U16 MappingInformation; /*0x08 */ - U16 DeviceIndex; /*0x0A */ - U32 PhysicalBitsMapping; /*0x0C */ - U32 Reserved1; /*0x10 */ -} MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY, - *PTR_MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY, - Mpi2DriverMap0Entry_t, *pMpi2DriverMap0Entry_t; - -typedef struct _MPI2_CONFIG_PAGE_DRIVER_MAPPING_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - MPI2_CONFIG_PAGE_DRIVER_MAP0_ENTRY Entry; /*0x08 */ -} MPI2_CONFIG_PAGE_DRIVER_MAPPING_0, - *PTR_MPI2_CONFIG_PAGE_DRIVER_MAPPING_0, - Mpi2DriverMappingPage0_t, *pMpi2DriverMappingPage0_t; - -#define MPI2_DRIVERMAPPING0_PAGEVERSION (0x00) - -/*values for Driver Persistent Mapping Page 0 MappingInformation field */ -#define MPI2_DRVMAP0_MAPINFO_SLOT_MASK (0x07F0) -#define MPI2_DRVMAP0_MAPINFO_SLOT_SHIFT (4) -#define MPI2_DRVMAP0_MAPINFO_MISSING_MASK (0x000F) - - -/**************************************************************************** -* Ethernet Config Pages -****************************************************************************/ - -/*Ethernet Page 0 */ - -/*IP address (union of IPv4 and IPv6) */ -typedef union _MPI2_ETHERNET_IP_ADDR { - U32 IPv4Addr; - U32 IPv6Addr[4]; -} MPI2_ETHERNET_IP_ADDR, *PTR_MPI2_ETHERNET_IP_ADDR, - Mpi2EthernetIpAddr_t, *pMpi2EthernetIpAddr_t; - -#define MPI2_ETHERNET_HOST_NAME_LENGTH (32) - -typedef struct _MPI2_CONFIG_PAGE_ETHERNET_0 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER Header; /*0x00 */ - U8 NumInterfaces; /*0x08 */ - U8 Reserved0; /*0x09 */ - U16 Reserved1; /*0x0A */ - U32 Status; /*0x0C */ - U8 MediaState; /*0x10 */ - U8 Reserved2; /*0x11 */ - U16 Reserved3; /*0x12 */ - U8 MacAddress[6]; /*0x14 */ - U8 Reserved4; /*0x1A */ - U8 Reserved5; /*0x1B */ - MPI2_ETHERNET_IP_ADDR IpAddress; /*0x1C */ - MPI2_ETHERNET_IP_ADDR SubnetMask; /*0x2C */ - MPI2_ETHERNET_IP_ADDR GatewayIpAddress;/*0x3C */ - MPI2_ETHERNET_IP_ADDR DNS1IpAddress; /*0x4C */ - MPI2_ETHERNET_IP_ADDR DNS2IpAddress; /*0x5C */ - MPI2_ETHERNET_IP_ADDR DhcpIpAddress; /*0x6C */ - U8 - HostName[MPI2_ETHERNET_HOST_NAME_LENGTH];/*0x7C */ -} MPI2_CONFIG_PAGE_ETHERNET_0, - *PTR_MPI2_CONFIG_PAGE_ETHERNET_0, - Mpi2EthernetPage0_t, *pMpi2EthernetPage0_t; - -#define MPI2_ETHERNETPAGE0_PAGEVERSION (0x00) - -/*values for Ethernet Page 0 Status field */ -#define MPI2_ETHPG0_STATUS_IPV6_CAPABLE (0x80000000) -#define MPI2_ETHPG0_STATUS_IPV4_CAPABLE (0x40000000) -#define MPI2_ETHPG0_STATUS_CONSOLE_CONNECTED (0x20000000) -#define MPI2_ETHPG0_STATUS_DEFAULT_IF (0x00000100) -#define MPI2_ETHPG0_STATUS_FW_DWNLD_ENABLED (0x00000080) -#define MPI2_ETHPG0_STATUS_TELNET_ENABLED (0x00000040) -#define MPI2_ETHPG0_STATUS_SSH2_ENABLED (0x00000020) -#define MPI2_ETHPG0_STATUS_DHCP_CLIENT_ENABLED (0x00000010) -#define MPI2_ETHPG0_STATUS_IPV6_ENABLED (0x00000008) -#define MPI2_ETHPG0_STATUS_IPV4_ENABLED (0x00000004) -#define MPI2_ETHPG0_STATUS_IPV6_ADDRESSES (0x00000002) -#define MPI2_ETHPG0_STATUS_ETH_IF_ENABLED (0x00000001) - -/*values for Ethernet Page 0 MediaState field */ -#define MPI2_ETHPG0_MS_DUPLEX_MASK (0x80) -#define MPI2_ETHPG0_MS_HALF_DUPLEX (0x00) -#define MPI2_ETHPG0_MS_FULL_DUPLEX (0x80) - -#define MPI2_ETHPG0_MS_CONNECT_SPEED_MASK (0x07) -#define MPI2_ETHPG0_MS_NOT_CONNECTED (0x00) -#define MPI2_ETHPG0_MS_10MBIT (0x01) -#define MPI2_ETHPG0_MS_100MBIT (0x02) -#define MPI2_ETHPG0_MS_1GBIT (0x03) - - -/*Ethernet Page 1 */ - -typedef struct _MPI2_CONFIG_PAGE_ETHERNET_1 { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - Reserved0; /*0x08 */ - U32 - Flags; /*0x0C */ - U8 - MediaState; /*0x10 */ - U8 - Reserved1; /*0x11 */ - U16 - Reserved2; /*0x12 */ - U8 - MacAddress[6]; /*0x14 */ - U8 - Reserved3; /*0x1A */ - U8 - Reserved4; /*0x1B */ - MPI2_ETHERNET_IP_ADDR - StaticIpAddress; /*0x1C */ - MPI2_ETHERNET_IP_ADDR - StaticSubnetMask; /*0x2C */ - MPI2_ETHERNET_IP_ADDR - StaticGatewayIpAddress; /*0x3C */ - MPI2_ETHERNET_IP_ADDR - StaticDNS1IpAddress; /*0x4C */ - MPI2_ETHERNET_IP_ADDR - StaticDNS2IpAddress; /*0x5C */ - U32 - Reserved5; /*0x6C */ - U32 - Reserved6; /*0x70 */ - U32 - Reserved7; /*0x74 */ - U32 - Reserved8; /*0x78 */ - U8 - HostName[MPI2_ETHERNET_HOST_NAME_LENGTH];/*0x7C */ -} MPI2_CONFIG_PAGE_ETHERNET_1, - *PTR_MPI2_CONFIG_PAGE_ETHERNET_1, - Mpi2EthernetPage1_t, *pMpi2EthernetPage1_t; - -#define MPI2_ETHERNETPAGE1_PAGEVERSION (0x00) - -/*values for Ethernet Page 1 Flags field */ -#define MPI2_ETHPG1_FLAG_SET_DEFAULT_IF (0x00000100) -#define MPI2_ETHPG1_FLAG_ENABLE_FW_DOWNLOAD (0x00000080) -#define MPI2_ETHPG1_FLAG_ENABLE_TELNET (0x00000040) -#define MPI2_ETHPG1_FLAG_ENABLE_SSH2 (0x00000020) -#define MPI2_ETHPG1_FLAG_ENABLE_DHCP_CLIENT (0x00000010) -#define MPI2_ETHPG1_FLAG_ENABLE_IPV6 (0x00000008) -#define MPI2_ETHPG1_FLAG_ENABLE_IPV4 (0x00000004) -#define MPI2_ETHPG1_FLAG_USE_IPV6_ADDRESSES (0x00000002) -#define MPI2_ETHPG1_FLAG_ENABLE_ETH_IF (0x00000001) - -/*values for Ethernet Page 1 MediaState field */ -#define MPI2_ETHPG1_MS_DUPLEX_MASK (0x80) -#define MPI2_ETHPG1_MS_HALF_DUPLEX (0x00) -#define MPI2_ETHPG1_MS_FULL_DUPLEX (0x80) - -#define MPI2_ETHPG1_MS_DATA_RATE_MASK (0x07) -#define MPI2_ETHPG1_MS_DATA_RATE_AUTO (0x00) -#define MPI2_ETHPG1_MS_DATA_RATE_10MBIT (0x01) -#define MPI2_ETHPG1_MS_DATA_RATE_100MBIT (0x02) -#define MPI2_ETHPG1_MS_DATA_RATE_1GBIT (0x03) - - -/**************************************************************************** -* Extended Manufacturing Config Pages -****************************************************************************/ - -/* - *Generic structure to use for product-specific extended manufacturing pages - *(currently Extended Manufacturing Page 40 through Extended Manufacturing - *Page 60). - */ - -typedef struct _MPI2_CONFIG_PAGE_EXT_MAN_PS { - MPI2_CONFIG_EXTENDED_PAGE_HEADER - Header; /*0x00 */ - U32 - ProductSpecificInfo; /*0x08 */ -} MPI2_CONFIG_PAGE_EXT_MAN_PS, - *PTR_MPI2_CONFIG_PAGE_EXT_MAN_PS, - Mpi2ExtManufacturingPagePS_t, - *pMpi2ExtManufacturingPagePS_t; - -/*PageVersion should be provided by product-specific code */ - -#endif diff --git a/addons/mpt3sas/src/4.4.180/mpi/mpi2_init.h b/addons/mpt3sas/src/4.4.180/mpi/mpi2_init.h deleted file mode 100644 index 068c98ef..00000000 --- a/addons/mpt3sas/src/4.4.180/mpi/mpi2_init.h +++ /dev/null @@ -1,562 +0,0 @@ -/* - * Copyright (c) 2000-2014 LSI Corporation. - * - * - * Name: mpi2_init.h - * Title: MPI SCSI initiator mode messages and structures - * Creation Date: June 23, 2006 - * - * mpi2_init.h Version: 02.00.15 - * - * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 - * prefix are for use only on MPI v2.5 products, and must not be used - * with MPI v2.0 products. Unless otherwise noted, names beginning with - * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 10-31-07 02.00.01 Fixed name for pMpi2SCSITaskManagementRequest_t. - * 12-18-07 02.00.02 Modified Task Management Target Reset Method defines. - * 02-29-08 02.00.03 Added Query Task Set and Query Unit Attention. - * 03-03-08 02.00.04 Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY. - * 05-21-08 02.00.05 Fixed typo in name of Mpi2SepRequest_t. - * 10-02-08 02.00.06 Removed Untagged and No Disconnect values from SCSI IO - * Control field Task Attribute flags. - * Moved LUN field defines to mpi2.h becasue they are - * common to many structures. - * 05-06-09 02.00.07 Changed task management type of Query Unit Attention to - * Query Asynchronous Event. - * Defined two new bits in the SlotStatus field of the SCSI - * Enclosure Processor Request and Reply. - * 10-28-09 02.00.08 Added defines for decoding the ResponseInfo bytes for - * both SCSI IO Error Reply and SCSI Task Management Reply. - * Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY. - * Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define. - * 02-10-10 02.00.09 Removed unused structure that had "#if 0" around it. - * 05-12-10 02.00.10 Added optional vendor-unique region to SCSI IO Request. - * 11-10-10 02.00.11 Added MPI2_SCSIIO_NUM_SGLOFFSETS define. - * 11-18-11 02.00.12 Incorporating additions for MPI v2.5. - * 02-06-12 02.00.13 Added alternate defines for Task Priority / Command - * Priority to match SAM-4. - * Added EEDPErrorOffset to MPI2_SCSI_IO_REPLY. - * 07-10-12 02.00.14 Added MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION. - * 04-09-13 02.00.15 Added SCSIStatusQualifier field to MPI2_SCSI_IO_REPLY, - * replacing the Reserved4 field. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_INIT_H -#define MPI2_INIT_H - -/***************************************************************************** -* -* SCSI Initiator Messages -* -*****************************************************************************/ - -/**************************************************************************** -* SCSI IO messages and associated structures -****************************************************************************/ - -typedef struct _MPI2_SCSI_IO_CDB_EEDP32 { - U8 CDB[20]; /*0x00 */ - U32 PrimaryReferenceTag; /*0x14 */ - U16 PrimaryApplicationTag; /*0x18 */ - U16 PrimaryApplicationTagMask; /*0x1A */ - U32 TransferLength; /*0x1C */ -} MPI2_SCSI_IO_CDB_EEDP32, *PTR_MPI2_SCSI_IO_CDB_EEDP32, - Mpi2ScsiIoCdbEedp32_t, *pMpi2ScsiIoCdbEedp32_t; - -/*MPI v2.0 CDB field */ -typedef union _MPI2_SCSI_IO_CDB_UNION { - U8 CDB32[32]; - MPI2_SCSI_IO_CDB_EEDP32 EEDP32; - MPI2_SGE_SIMPLE_UNION SGE; -} MPI2_SCSI_IO_CDB_UNION, *PTR_MPI2_SCSI_IO_CDB_UNION, - Mpi2ScsiIoCdb_t, *pMpi2ScsiIoCdb_t; - -/*MPI v2.0 SCSI IO Request Message */ -typedef struct _MPI2_SCSI_IO_REQUEST { - U16 DevHandle; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved1; /*0x04 */ - U8 Reserved2; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U32 SenseBufferLowAddress; /*0x0C */ - U16 SGLFlags; /*0x10 */ - U8 SenseBufferLength; /*0x12 */ - U8 Reserved4; /*0x13 */ - U8 SGLOffset0; /*0x14 */ - U8 SGLOffset1; /*0x15 */ - U8 SGLOffset2; /*0x16 */ - U8 SGLOffset3; /*0x17 */ - U32 SkipCount; /*0x18 */ - U32 DataLength; /*0x1C */ - U32 BidirectionalDataLength; /*0x20 */ - U16 IoFlags; /*0x24 */ - U16 EEDPFlags; /*0x26 */ - U32 EEDPBlockSize; /*0x28 */ - U32 SecondaryReferenceTag; /*0x2C */ - U16 SecondaryApplicationTag; /*0x30 */ - U16 ApplicationTagTranslationMask; /*0x32 */ - U8 LUN[8]; /*0x34 */ - U32 Control; /*0x3C */ - MPI2_SCSI_IO_CDB_UNION CDB; /*0x40 */ - -#ifdef MPI2_SCSI_IO_VENDOR_UNIQUE_REGION /*typically this is left undefined */ - MPI2_SCSI_IO_VENDOR_UNIQUE VendorRegion; -#endif - - MPI2_SGE_IO_UNION SGL; /*0x60 */ - -} MPI2_SCSI_IO_REQUEST, *PTR_MPI2_SCSI_IO_REQUEST, - Mpi2SCSIIORequest_t, *pMpi2SCSIIORequest_t; - -/*SCSI IO MsgFlags bits */ - -/*MsgFlags for SenseBufferAddressSpace */ -#define MPI2_SCSIIO_MSGFLAGS_MASK_SENSE_ADDR (0x0C) -#define MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR (0x00) -#define MPI2_SCSIIO_MSGFLAGS_IOCDDR_SENSE_ADDR (0x04) -#define MPI2_SCSIIO_MSGFLAGS_IOCPLB_SENSE_ADDR (0x08) -#define MPI2_SCSIIO_MSGFLAGS_IOCPLBNTA_SENSE_ADDR (0x0C) - -/*SCSI IO SGLFlags bits */ - -/*base values for Data Location Address Space */ -#define MPI2_SCSIIO_SGLFLAGS_ADDR_MASK (0x0C) -#define MPI2_SCSIIO_SGLFLAGS_SYSTEM_ADDR (0x00) -#define MPI2_SCSIIO_SGLFLAGS_IOCDDR_ADDR (0x04) -#define MPI2_SCSIIO_SGLFLAGS_IOCPLB_ADDR (0x08) -#define MPI2_SCSIIO_SGLFLAGS_IOCPLBNTA_ADDR (0x0C) - -/*base values for Type */ -#define MPI2_SCSIIO_SGLFLAGS_TYPE_MASK (0x03) -#define MPI2_SCSIIO_SGLFLAGS_TYPE_MPI (0x00) -#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE32 (0x01) -#define MPI2_SCSIIO_SGLFLAGS_TYPE_IEEE64 (0x02) - -/*shift values for each sub-field */ -#define MPI2_SCSIIO_SGLFLAGS_SGL3_SHIFT (12) -#define MPI2_SCSIIO_SGLFLAGS_SGL2_SHIFT (8) -#define MPI2_SCSIIO_SGLFLAGS_SGL1_SHIFT (4) -#define MPI2_SCSIIO_SGLFLAGS_SGL0_SHIFT (0) - -/*number of SGLOffset fields */ -#define MPI2_SCSIIO_NUM_SGLOFFSETS (4) - -/*SCSI IO IoFlags bits */ - -/*Large CDB Address Space */ -#define MPI2_SCSIIO_CDB_ADDR_MASK (0x6000) -#define MPI2_SCSIIO_CDB_ADDR_SYSTEM (0x0000) -#define MPI2_SCSIIO_CDB_ADDR_IOCDDR (0x2000) -#define MPI2_SCSIIO_CDB_ADDR_IOCPLB (0x4000) -#define MPI2_SCSIIO_CDB_ADDR_IOCPLBNTA (0x6000) - -#define MPI2_SCSIIO_IOFLAGS_LARGE_CDB (0x1000) -#define MPI2_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800) -#define MPI2_SCSIIO_IOFLAGS_MULTICAST (0x0400) -#define MPI2_SCSIIO_IOFLAGS_CMD_DETERMINES_DATA_DIR (0x0200) -#define MPI2_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF) - -/*SCSI IO EEDPFlags bits */ - -#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG (0x8000) -#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_REFTAG (0x4000) -#define MPI2_SCSIIO_EEDPFLAGS_INC_PRI_APPTAG (0x2000) -#define MPI2_SCSIIO_EEDPFLAGS_INC_SEC_APPTAG (0x1000) - -#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG (0x0400) -#define MPI2_SCSIIO_EEDPFLAGS_CHECK_APPTAG (0x0200) -#define MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD (0x0100) - -#define MPI2_SCSIIO_EEDPFLAGS_PASSTHRU_REFTAG (0x0008) - -#define MPI2_SCSIIO_EEDPFLAGS_MASK_OP (0x0007) -#define MPI2_SCSIIO_EEDPFLAGS_NOOP_OP (0x0000) -#define MPI2_SCSIIO_EEDPFLAGS_CHECK_OP (0x0001) -#define MPI2_SCSIIO_EEDPFLAGS_STRIP_OP (0x0002) -#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP (0x0003) -#define MPI2_SCSIIO_EEDPFLAGS_INSERT_OP (0x0004) -#define MPI2_SCSIIO_EEDPFLAGS_REPLACE_OP (0x0006) -#define MPI2_SCSIIO_EEDPFLAGS_CHECK_REGEN_OP (0x0007) - -/*SCSI IO LUN fields: use MPI2_LUN_ from mpi2.h */ - -/*SCSI IO Control bits */ -#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_MASK (0xFC000000) -#define MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT (26) - -#define MPI2_SCSIIO_CONTROL_DATADIRECTION_MASK (0x03000000) -#define MPI2_SCSIIO_CONTROL_SHIFT_DATADIRECTION (24) -#define MPI2_SCSIIO_CONTROL_NODATATRANSFER (0x00000000) -#define MPI2_SCSIIO_CONTROL_WRITE (0x01000000) -#define MPI2_SCSIIO_CONTROL_READ (0x02000000) -#define MPI2_SCSIIO_CONTROL_BIDIRECTIONAL (0x03000000) - -#define MPI2_SCSIIO_CONTROL_TASKPRI_MASK (0x00007800) -#define MPI2_SCSIIO_CONTROL_TASKPRI_SHIFT (11) -/*alternate name for the previous field; called Command Priority in SAM-4 */ -#define MPI2_SCSIIO_CONTROL_CMDPRI_MASK (0x00007800) -#define MPI2_SCSIIO_CONTROL_CMDPRI_SHIFT (11) - -#define MPI2_SCSIIO_CONTROL_TASKATTRIBUTE_MASK (0x00000700) -#define MPI2_SCSIIO_CONTROL_SIMPLEQ (0x00000000) -#define MPI2_SCSIIO_CONTROL_HEADOFQ (0x00000100) -#define MPI2_SCSIIO_CONTROL_ORDEREDQ (0x00000200) -#define MPI2_SCSIIO_CONTROL_ACAQ (0x00000400) - -#define MPI2_SCSIIO_CONTROL_TLR_MASK (0x000000C0) -#define MPI2_SCSIIO_CONTROL_NO_TLR (0x00000000) -#define MPI2_SCSIIO_CONTROL_TLR_ON (0x00000040) -#define MPI2_SCSIIO_CONTROL_TLR_OFF (0x00000080) - -/*MPI v2.5 CDB field */ -typedef union _MPI25_SCSI_IO_CDB_UNION { - U8 CDB32[32]; - MPI2_SCSI_IO_CDB_EEDP32 EEDP32; - MPI2_IEEE_SGE_SIMPLE64 SGE; -} MPI25_SCSI_IO_CDB_UNION, *PTR_MPI25_SCSI_IO_CDB_UNION, - Mpi25ScsiIoCdb_t, *pMpi25ScsiIoCdb_t; - -/*MPI v2.5 SCSI IO Request Message */ -typedef struct _MPI25_SCSI_IO_REQUEST { - U16 DevHandle; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved1; /*0x04 */ - U8 Reserved2; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U32 SenseBufferLowAddress; /*0x0C */ - U8 DMAFlags; /*0x10 */ - U8 Reserved5; /*0x11 */ - U8 SenseBufferLength; /*0x12 */ - U8 Reserved4; /*0x13 */ - U8 SGLOffset0; /*0x14 */ - U8 SGLOffset1; /*0x15 */ - U8 SGLOffset2; /*0x16 */ - U8 SGLOffset3; /*0x17 */ - U32 SkipCount; /*0x18 */ - U32 DataLength; /*0x1C */ - U32 BidirectionalDataLength; /*0x20 */ - U16 IoFlags; /*0x24 */ - U16 EEDPFlags; /*0x26 */ - U16 EEDPBlockSize; /*0x28 */ - U16 Reserved6; /*0x2A */ - U32 SecondaryReferenceTag; /*0x2C */ - U16 SecondaryApplicationTag; /*0x30 */ - U16 ApplicationTagTranslationMask; /*0x32 */ - U8 LUN[8]; /*0x34 */ - U32 Control; /*0x3C */ - MPI25_SCSI_IO_CDB_UNION CDB; /*0x40 */ - -#ifdef MPI25_SCSI_IO_VENDOR_UNIQUE_REGION /*typically this is left undefined */ - MPI25_SCSI_IO_VENDOR_UNIQUE VendorRegion; -#endif - - MPI25_SGE_IO_UNION SGL; /*0x60 */ - -} MPI25_SCSI_IO_REQUEST, *PTR_MPI25_SCSI_IO_REQUEST, - Mpi25SCSIIORequest_t, *pMpi25SCSIIORequest_t; - -/*use MPI2_SCSIIO_MSGFLAGS_ defines for the MsgFlags field */ - -/*Defines for the DMAFlags field - * Each setting affects 4 SGLS, from SGL0 to SGL3. - * D = Data - * C = Cache DIF - * I = Interleaved - * H = Host DIF - */ -#define MPI25_SCSIIO_DMAFLAGS_OP_MASK (0x0F) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_D (0x00) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_C (0x01) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_D_I (0x02) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_C_C (0x03) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_C_I (0x04) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_D_I_I (0x05) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_C_C (0x06) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_C_I (0x07) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_C_I_I (0x08) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_I_I_I (0x09) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_D (0x0A) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_C (0x0B) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_D_I (0x0C) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_C_C (0x0D) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_C_I (0x0E) -#define MPI25_SCSIIO_DMAFLAGS_OP_D_H_I_I (0x0F) - -/*number of SGLOffset fields */ -#define MPI25_SCSIIO_NUM_SGLOFFSETS (4) - -/*defines for the IoFlags field */ -#define MPI25_SCSIIO_IOFLAGS_IO_PATH_MASK (0xC000) -#define MPI25_SCSIIO_IOFLAGS_NORMAL_PATH (0x0000) -#define MPI25_SCSIIO_IOFLAGS_FAST_PATH (0x4000) - -#define MPI25_SCSIIO_IOFLAGS_LARGE_CDB (0x1000) -#define MPI25_SCSIIO_IOFLAGS_BIDIRECTIONAL (0x0800) -#define MPI25_SCSIIO_IOFLAGS_CDBLENGTH_MASK (0x01FF) - -/*MPI v2.5 defines for the EEDPFlags bits */ -/*use MPI2_SCSIIO_EEDPFLAGS_ defines for the other EEDPFlags bits */ -#define MPI25_SCSIIO_EEDPFLAGS_ESCAPE_MODE_MASK (0x00C0) -#define MPI25_SCSIIO_EEDPFLAGS_COMPATIBLE_MODE (0x0000) -#define MPI25_SCSIIO_EEDPFLAGS_DO_NOT_DISABLE_MODE (0x0040) -#define MPI25_SCSIIO_EEDPFLAGS_APPTAG_DISABLE_MODE (0x0080) -#define MPI25_SCSIIO_EEDPFLAGS_APPTAG_REFTAG_DISABLE_MODE (0x00C0) - -#define MPI25_SCSIIO_EEDPFLAGS_HOST_GUARD_METHOD_MASK (0x0030) -#define MPI25_SCSIIO_EEDPFLAGS_T10_CRC_HOST_GUARD (0x0000) -#define MPI25_SCSIIO_EEDPFLAGS_IP_CHKSUM_HOST_GUARD (0x0010) - -/*use MPI2_LUN_ defines from mpi2.h for the LUN field */ - -/*use MPI2_SCSIIO_CONTROL_ defines for the Control field */ - -/*NOTE: The SCSI IO Reply is nearly the same for MPI 2.0 and MPI 2.5, so - * MPI2_SCSI_IO_REPLY is used for both. - */ - -/*SCSI IO Error Reply Message */ -typedef struct _MPI2_SCSI_IO_REPLY { - U16 DevHandle; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved1; /*0x04 */ - U8 Reserved2; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U8 SCSIStatus; /*0x0C */ - U8 SCSIState; /*0x0D */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 TransferCount; /*0x14 */ - U32 SenseCount; /*0x18 */ - U32 ResponseInfo; /*0x1C */ - U16 TaskTag; /*0x20 */ - U16 SCSIStatusQualifier; /* 0x22 */ - U32 BidirectionalTransferCount; /*0x24 */ - U32 EEDPErrorOffset; /*0x28 *//*MPI 2.5 only; Reserved in MPI 2.0*/ - U32 Reserved6; /*0x2C */ -} MPI2_SCSI_IO_REPLY, *PTR_MPI2_SCSI_IO_REPLY, - Mpi2SCSIIOReply_t, *pMpi2SCSIIOReply_t; - -/*SCSI IO Reply SCSIStatus values (SAM-4 status codes) */ - -#define MPI2_SCSI_STATUS_GOOD (0x00) -#define MPI2_SCSI_STATUS_CHECK_CONDITION (0x02) -#define MPI2_SCSI_STATUS_CONDITION_MET (0x04) -#define MPI2_SCSI_STATUS_BUSY (0x08) -#define MPI2_SCSI_STATUS_INTERMEDIATE (0x10) -#define MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET (0x14) -#define MPI2_SCSI_STATUS_RESERVATION_CONFLICT (0x18) -#define MPI2_SCSI_STATUS_COMMAND_TERMINATED (0x22) /*obsolete */ -#define MPI2_SCSI_STATUS_TASK_SET_FULL (0x28) -#define MPI2_SCSI_STATUS_ACA_ACTIVE (0x30) -#define MPI2_SCSI_STATUS_TASK_ABORTED (0x40) - -/*SCSI IO Reply SCSIState flags */ - -#define MPI2_SCSI_STATE_RESPONSE_INFO_VALID (0x10) -#define MPI2_SCSI_STATE_TERMINATED (0x08) -#define MPI2_SCSI_STATE_NO_SCSI_STATUS (0x04) -#define MPI2_SCSI_STATE_AUTOSENSE_FAILED (0x02) -#define MPI2_SCSI_STATE_AUTOSENSE_VALID (0x01) - -/*masks and shifts for the ResponseInfo field */ - -#define MPI2_SCSI_RI_MASK_REASONCODE (0x000000FF) -#define MPI2_SCSI_RI_SHIFT_REASONCODE (0) - -#define MPI2_SCSI_TASKTAG_UNKNOWN (0xFFFF) - -/**************************************************************************** -* SCSI Task Management messages -****************************************************************************/ - -/*SCSI Task Management Request Message */ -typedef struct _MPI2_SCSI_TASK_MANAGE_REQUEST { - U16 DevHandle; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U8 Reserved1; /*0x04 */ - U8 TaskType; /*0x05 */ - U8 Reserved2; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U8 LUN[8]; /*0x0C */ - U32 Reserved4[7]; /*0x14 */ - U16 TaskMID; /*0x30 */ - U16 Reserved5; /*0x32 */ -} MPI2_SCSI_TASK_MANAGE_REQUEST, - *PTR_MPI2_SCSI_TASK_MANAGE_REQUEST, - Mpi2SCSITaskManagementRequest_t, - *pMpi2SCSITaskManagementRequest_t; - -/*TaskType values */ - -#define MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK (0x01) -#define MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET (0x02) -#define MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET (0x03) -#define MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET (0x05) -#define MPI2_SCSITASKMGMT_TASKTYPE_CLEAR_TASK_SET (0x06) -#define MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK (0x07) -#define MPI2_SCSITASKMGMT_TASKTYPE_CLR_ACA (0x08) -#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_TASK_SET (0x09) -#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT (0x0A) - -/*obsolete TaskType name */ -#define MPI2_SCSITASKMGMT_TASKTYPE_QRY_UNIT_ATTENTION \ - (MPI2_SCSITASKMGMT_TASKTYPE_QRY_ASYNC_EVENT) - -/*MsgFlags bits */ - -#define MPI2_SCSITASKMGMT_MSGFLAGS_MASK_TARGET_RESET (0x18) -#define MPI2_SCSITASKMGMT_MSGFLAGS_LINK_RESET (0x00) -#define MPI2_SCSITASKMGMT_MSGFLAGS_NEXUS_RESET_SRST (0x08) -#define MPI2_SCSITASKMGMT_MSGFLAGS_SAS_HARD_LINK_RESET (0x10) - -#define MPI2_SCSITASKMGMT_MSGFLAGS_DO_NOT_SEND_TASK_IU (0x01) - -/*SCSI Task Management Reply Message */ -typedef struct _MPI2_SCSI_TASK_MANAGE_REPLY { - U16 DevHandle; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U8 ResponseCode; /*0x04 */ - U8 TaskType; /*0x05 */ - U8 Reserved1; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved2; /*0x0A */ - U16 Reserved3; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 TerminationCount; /*0x14 */ - U32 ResponseInfo; /*0x18 */ -} MPI2_SCSI_TASK_MANAGE_REPLY, - *PTR_MPI2_SCSI_TASK_MANAGE_REPLY, - Mpi2SCSITaskManagementReply_t, *pMpi2SCSIManagementReply_t; - -/*ResponseCode values */ - -#define MPI2_SCSITASKMGMT_RSP_TM_COMPLETE (0x00) -#define MPI2_SCSITASKMGMT_RSP_INVALID_FRAME (0x02) -#define MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED (0x04) -#define MPI2_SCSITASKMGMT_RSP_TM_FAILED (0x05) -#define MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED (0x08) -#define MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN (0x09) -#define MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG (0x0A) -#define MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC (0x80) - -/*masks and shifts for the ResponseInfo field */ - -#define MPI2_SCSITASKMGMT_RI_MASK_REASONCODE (0x000000FF) -#define MPI2_SCSITASKMGMT_RI_SHIFT_REASONCODE (0) -#define MPI2_SCSITASKMGMT_RI_MASK_ARI2 (0x0000FF00) -#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI2 (8) -#define MPI2_SCSITASKMGMT_RI_MASK_ARI1 (0x00FF0000) -#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI1 (16) -#define MPI2_SCSITASKMGMT_RI_MASK_ARI0 (0xFF000000) -#define MPI2_SCSITASKMGMT_RI_SHIFT_ARI0 (24) - -/**************************************************************************** -* SCSI Enclosure Processor messages -****************************************************************************/ - -/*SCSI Enclosure Processor Request Message */ -typedef struct _MPI2_SEP_REQUEST { - U16 DevHandle; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U8 Action; /*0x04 */ - U8 Flags; /*0x05 */ - U8 Reserved1; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved2; /*0x0A */ - U32 SlotStatus; /*0x0C */ - U32 Reserved3; /*0x10 */ - U32 Reserved4; /*0x14 */ - U32 Reserved5; /*0x18 */ - U16 Slot; /*0x1C */ - U16 EnclosureHandle; /*0x1E */ -} MPI2_SEP_REQUEST, *PTR_MPI2_SEP_REQUEST, - Mpi2SepRequest_t, *pMpi2SepRequest_t; - -/*Action defines */ -#define MPI2_SEP_REQ_ACTION_WRITE_STATUS (0x00) -#define MPI2_SEP_REQ_ACTION_READ_STATUS (0x01) - -/*Flags defines */ -#define MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS (0x00) -#define MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS (0x01) - -/*SlotStatus defines */ -#define MPI2_SEP_REQ_SLOTSTATUS_REQUEST_REMOVE (0x00040000) -#define MPI2_SEP_REQ_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) -#define MPI2_SEP_REQ_SLOTSTATUS_REBUILD_STOPPED (0x00000200) -#define MPI2_SEP_REQ_SLOTSTATUS_HOT_SPARE (0x00000100) -#define MPI2_SEP_REQ_SLOTSTATUS_UNCONFIGURED (0x00000080) -#define MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT (0x00000040) -#define MPI2_SEP_REQ_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) -#define MPI2_SEP_REQ_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) -#define MPI2_SEP_REQ_SLOTSTATUS_DEV_REBUILDING (0x00000004) -#define MPI2_SEP_REQ_SLOTSTATUS_DEV_FAULTY (0x00000002) -#define MPI2_SEP_REQ_SLOTSTATUS_NO_ERROR (0x00000001) - -/*SCSI Enclosure Processor Reply Message */ -typedef struct _MPI2_SEP_REPLY { - U16 DevHandle; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U8 Action; /*0x04 */ - U8 Flags; /*0x05 */ - U8 Reserved1; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved2; /*0x0A */ - U16 Reserved3; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 SlotStatus; /*0x14 */ - U32 Reserved4; /*0x18 */ - U16 Slot; /*0x1C */ - U16 EnclosureHandle; /*0x1E */ -} MPI2_SEP_REPLY, *PTR_MPI2_SEP_REPLY, - Mpi2SepReply_t, *pMpi2SepReply_t; - -/*SlotStatus defines */ -#define MPI2_SEP_REPLY_SLOTSTATUS_REMOVE_READY (0x00040000) -#define MPI2_SEP_REPLY_SLOTSTATUS_IDENTIFY_REQUEST (0x00020000) -#define MPI2_SEP_REPLY_SLOTSTATUS_REBUILD_STOPPED (0x00000200) -#define MPI2_SEP_REPLY_SLOTSTATUS_HOT_SPARE (0x00000100) -#define MPI2_SEP_REPLY_SLOTSTATUS_UNCONFIGURED (0x00000080) -#define MPI2_SEP_REPLY_SLOTSTATUS_PREDICTED_FAULT (0x00000040) -#define MPI2_SEP_REPLY_SLOTSTATUS_IN_CRITICAL_ARRAY (0x00000010) -#define MPI2_SEP_REPLY_SLOTSTATUS_IN_FAILED_ARRAY (0x00000008) -#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_REBUILDING (0x00000004) -#define MPI2_SEP_REPLY_SLOTSTATUS_DEV_FAULTY (0x00000002) -#define MPI2_SEP_REPLY_SLOTSTATUS_NO_ERROR (0x00000001) - -#endif diff --git a/addons/mpt3sas/src/4.4.180/mpi/mpi2_ioc.h b/addons/mpt3sas/src/4.4.180/mpi/mpi2_ioc.h deleted file mode 100644 index d7598cc4..00000000 --- a/addons/mpt3sas/src/4.4.180/mpi/mpi2_ioc.h +++ /dev/null @@ -1,1729 +0,0 @@ -/* - * Copyright (c) 2000-2014 LSI Corporation. - * - * - * Name: mpi2_ioc.h - * Title: MPI IOC, Port, Event, FW Download, and FW Upload messages - * Creation Date: October 11, 2006 - * - * mpi2_ioc.h Version: 02.00.24 - * - * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 - * prefix are for use only on MPI v2.5 products, and must not be used - * with MPI v2.0 products. Unless otherwise noted, names beginning with - * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 06-04-07 02.00.01 In IOCFacts Reply structure, renamed MaxDevices to - * MaxTargets. - * Added TotalImageSize field to FWDownload Request. - * Added reserved words to FWUpload Request. - * 06-26-07 02.00.02 Added IR Configuration Change List Event. - * 08-31-07 02.00.03 Removed SystemReplyQueueDepth field from the IOCInit - * request and replaced it with - * ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth. - * Replaced the MinReplyQueueDepth field of the IOCFacts - * reply with MaxReplyDescriptorPostQueueDepth. - * Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum - * depth for the Reply Descriptor Post Queue. - * Added SASAddress field to Initiator Device Table - * Overflow Event data. - * 10-31-07 02.00.04 Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING - * for SAS Initiator Device Status Change Event data. - * Modified Reason Code defines for SAS Topology Change - * List Event data, including adding a bit for PHY Vacant - * status, and adding a mask for the Reason Code. - * Added define for - * MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING. - * Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID. - * 12-18-07 02.00.05 Added Boot Status defines for the IOCExceptions field of - * the IOCFacts Reply. - * Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. - * Moved MPI2_VERSION_UNION to mpi2.h. - * Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks - * instead of enables, and added SASBroadcastPrimitiveMasks - * field. - * Added Log Entry Added Event and related structure. - * 02-29-08 02.00.06 Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID. - * Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET. - * Added MaxVolumes and MaxPersistentEntries fields to - * IOCFacts reply. - * Added ProtocalFlags and IOCCapabilities fields to - * MPI2_FW_IMAGE_HEADER. - * Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT. - * 03-03-08 02.00.07 Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to - * a U16 (from a U32). - * Removed extra 's' from EventMasks name. - * 06-27-08 02.00.08 Fixed an offset in a comment. - * 10-02-08 02.00.09 Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST. - * Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and - * renamed MinReplyFrameSize to ReplyFrameSize. - * Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX. - * Added two new RAIDOperation values for Integrated RAID - * Operations Status Event data. - * Added four new IR Configuration Change List Event data - * ReasonCode values. - * Added two new ReasonCode defines for SAS Device Status - * Change Event data. - * Added three new DiscoveryStatus bits for the SAS - * Discovery event data. - * Added Multiplexing Status Change bit to the PhyStatus - * field of the SAS Topology Change List event data. - * Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY. - * BootFlags are now product-specific. - * Added defines for the indivdual signature bytes - * for MPI2_INIT_IMAGE_FOOTER. - * 01-19-09 02.00.10 Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define. - * Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR - * define. - * Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE - * define. - * Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define. - * 05-06-09 02.00.11 Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define. - * Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define. - * Added two new reason codes for SAS Device Status Change - * Event. - * Added new event: SAS PHY Counter. - * 07-30-09 02.00.12 Added GPIO Interrupt event define and structure. - * Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define. - * Added new product id family for 2208. - * 10-28-09 02.00.13 Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST. - * Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY. - * Added MinDevHandle field to MPI2_IOC_FACTS_REPLY. - * Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY. - * Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define. - * Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define. - * Added Host Based Discovery Phy Event data. - * Added defines for ProductID Product field - * (MPI2_FW_HEADER_PID_). - * Modified values for SAS ProductID Family - * (MPI2_FW_HEADER_PID_FAMILY_). - * 02-10-10 02.00.14 Added SAS Quiesce Event structure and defines. - * Added PowerManagementControl Request structures and - * defines. - * 05-12-10 02.00.15 Marked Task Set Full Event as obsolete. - * Added MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY define. - * 11-10-10 02.00.16 Added MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC. - * 02-23-11 02.00.17 Added SAS NOTIFY Primitive event, and added - * SASNotifyPrimitiveMasks field to - * MPI2_EVENT_NOTIFICATION_REQUEST. - * Added Temperature Threshold Event. - * Added Host Message Event. - * Added Send Host Message request and reply. - * 05-25-11 02.00.18 For Extended Image Header, added - * MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC and - * MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC defines. - * Deprecated MPI2_EXT_IMAGE_TYPE_MAX define. - * 08-24-11 02.00.19 Added PhysicalPort field to - * MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE structure. - * Marked MPI2_PM_CONTROL_FEATURE_PCIE_LINK as obsolete. - * 11-18-11 02.00.20 Incorporating additions for MPI v2.5. - * 03-29-12 02.00.21 Added a product specific range to event values. - * 07-26-12 02.00.22 Added MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE. - * Added ElapsedSeconds field to - * MPI2_EVENT_DATA_IR_OPERATION_STATUS. - * 08-19-13 02.00.23 For IOCInit, added MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE - * and MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY. - * Added MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE. - * Added MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY. - * Added Encrypted Hash Extended Image. - * 12-05-13 02.00.24 Added MPI25_HASH_IMAGE_TYPE_BIOS. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_IOC_H -#define MPI2_IOC_H - -/***************************************************************************** -* -* IOC Messages -* -*****************************************************************************/ - -/**************************************************************************** -* IOCInit message -****************************************************************************/ - -/*IOCInit Request message */ -typedef struct _MPI2_IOC_INIT_REQUEST { - U8 WhoInit; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 MsgVersion; /*0x0C */ - U16 HeaderVersion; /*0x0E */ - U32 Reserved5; /*0x10 */ - U16 Reserved6; /*0x14 */ - U8 Reserved7; /*0x16 */ - U8 HostMSIxVectors; /*0x17 */ - U16 Reserved8; /*0x18 */ - U16 SystemRequestFrameSize; /*0x1A */ - U16 ReplyDescriptorPostQueueDepth; /*0x1C */ - U16 ReplyFreeQueueDepth; /*0x1E */ - U32 SenseBufferAddressHigh; /*0x20 */ - U32 SystemReplyAddressHigh; /*0x24 */ - U64 SystemRequestFrameBaseAddress; /*0x28 */ - U64 ReplyDescriptorPostQueueAddress; /*0x30 */ - U64 ReplyFreeQueueAddress; /*0x38 */ - U64 TimeStamp; /*0x40 */ -} MPI2_IOC_INIT_REQUEST, *PTR_MPI2_IOC_INIT_REQUEST, - Mpi2IOCInitRequest_t, *pMpi2IOCInitRequest_t; - -/*WhoInit values */ -#define MPI2_WHOINIT_NOT_INITIALIZED (0x00) -#define MPI2_WHOINIT_SYSTEM_BIOS (0x01) -#define MPI2_WHOINIT_ROM_BIOS (0x02) -#define MPI2_WHOINIT_PCI_PEER (0x03) -#define MPI2_WHOINIT_HOST_DRIVER (0x04) -#define MPI2_WHOINIT_MANUFACTURER (0x05) - -/* MsgFlags */ -#define MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE (0x01) - - -/*MsgVersion */ -#define MPI2_IOCINIT_MSGVERSION_MAJOR_MASK (0xFF00) -#define MPI2_IOCINIT_MSGVERSION_MAJOR_SHIFT (8) -#define MPI2_IOCINIT_MSGVERSION_MINOR_MASK (0x00FF) -#define MPI2_IOCINIT_MSGVERSION_MINOR_SHIFT (0) - -/*HeaderVersion */ -#define MPI2_IOCINIT_HDRVERSION_UNIT_MASK (0xFF00) -#define MPI2_IOCINIT_HDRVERSION_UNIT_SHIFT (8) -#define MPI2_IOCINIT_HDRVERSION_DEV_MASK (0x00FF) -#define MPI2_IOCINIT_HDRVERSION_DEV_SHIFT (0) - -/*minimum depth for a Reply Descriptor Post Queue */ -#define MPI2_RDPQ_DEPTH_MIN (16) - -/* Reply Descriptor Post Queue Array Entry */ -typedef struct _MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY { - U64 RDPQBaseAddress; /* 0x00 */ - U32 Reserved1; /* 0x08 */ - U32 Reserved2; /* 0x0C */ -} MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY, -*PTR_MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY, -Mpi2IOCInitRDPQArrayEntry, *pMpi2IOCInitRDPQArrayEntry; - - -/*IOCInit Reply message */ -typedef struct _MPI2_IOC_INIT_REPLY { - U8 WhoInit; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_IOC_INIT_REPLY, *PTR_MPI2_IOC_INIT_REPLY, - Mpi2IOCInitReply_t, *pMpi2IOCInitReply_t; - -/**************************************************************************** -* IOCFacts message -****************************************************************************/ - -/*IOCFacts Request message */ -typedef struct _MPI2_IOC_FACTS_REQUEST { - U16 Reserved1; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ -} MPI2_IOC_FACTS_REQUEST, *PTR_MPI2_IOC_FACTS_REQUEST, - Mpi2IOCFactsRequest_t, *pMpi2IOCFactsRequest_t; - -/*IOCFacts Reply message */ -typedef struct _MPI2_IOC_FACTS_REPLY { - U16 MsgVersion; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 HeaderVersion; /*0x04 */ - U8 IOCNumber; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U16 IOCExceptions; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U8 MaxChainDepth; /*0x14 */ - U8 WhoInit; /*0x15 */ - U8 NumberOfPorts; /*0x16 */ - U8 MaxMSIxVectors; /*0x17 */ - U16 RequestCredit; /*0x18 */ - U16 ProductID; /*0x1A */ - U32 IOCCapabilities; /*0x1C */ - MPI2_VERSION_UNION FWVersion; /*0x20 */ - U16 IOCRequestFrameSize; /*0x24 */ - U16 IOCMaxChainSegmentSize; /*0x26 */ - U16 MaxInitiators; /*0x28 */ - U16 MaxTargets; /*0x2A */ - U16 MaxSasExpanders; /*0x2C */ - U16 MaxEnclosures; /*0x2E */ - U16 ProtocolFlags; /*0x30 */ - U16 HighPriorityCredit; /*0x32 */ - U16 MaxReplyDescriptorPostQueueDepth; /*0x34 */ - U8 ReplyFrameSize; /*0x36 */ - U8 MaxVolumes; /*0x37 */ - U16 MaxDevHandle; /*0x38 */ - U16 MaxPersistentEntries; /*0x3A */ - U16 MinDevHandle; /*0x3C */ - U16 Reserved4; /*0x3E */ -} MPI2_IOC_FACTS_REPLY, *PTR_MPI2_IOC_FACTS_REPLY, - Mpi2IOCFactsReply_t, *pMpi2IOCFactsReply_t; - -/*MsgVersion */ -#define MPI2_IOCFACTS_MSGVERSION_MAJOR_MASK (0xFF00) -#define MPI2_IOCFACTS_MSGVERSION_MAJOR_SHIFT (8) -#define MPI2_IOCFACTS_MSGVERSION_MINOR_MASK (0x00FF) -#define MPI2_IOCFACTS_MSGVERSION_MINOR_SHIFT (0) - -/*HeaderVersion */ -#define MPI2_IOCFACTS_HDRVERSION_UNIT_MASK (0xFF00) -#define MPI2_IOCFACTS_HDRVERSION_UNIT_SHIFT (8) -#define MPI2_IOCFACTS_HDRVERSION_DEV_MASK (0x00FF) -#define MPI2_IOCFACTS_HDRVERSION_DEV_SHIFT (0) - -/*IOCExceptions */ -#define MPI2_IOCFACTS_EXCEPT_PARTIAL_MEMORY_FAILURE (0x0200) -#define MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX (0x0100) - -#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_MASK (0x00E0) -#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_GOOD (0x0000) -#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_BACKUP (0x0020) -#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_RESTORED (0x0040) -#define MPI2_IOCFACTS_EXCEPT_BOOTSTAT_CORRUPT_BACKUP (0x0060) - -#define MPI2_IOCFACTS_EXCEPT_METADATA_UNSUPPORTED (0x0010) -#define MPI2_IOCFACTS_EXCEPT_MANUFACT_CHECKSUM_FAIL (0x0008) -#define MPI2_IOCFACTS_EXCEPT_FW_CHECKSUM_FAIL (0x0004) -#define MPI2_IOCFACTS_EXCEPT_RAID_CONFIG_INVALID (0x0002) -#define MPI2_IOCFACTS_EXCEPT_CONFIG_CHECKSUM_FAIL (0x0001) - -/*defines for WhoInit field are after the IOCInit Request */ - -/*ProductID field uses MPI2_FW_HEADER_PID_ */ - -/*IOCCapabilities */ -#define MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE (0x00040000) -#define MPI25_IOCFACTS_CAPABILITY_FAST_PATH_CAPABLE (0x00020000) -#define MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY (0x00010000) -#define MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX (0x00008000) -#define MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR (0x00004000) -#define MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY (0x00002000) -#define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID (0x00001000) -#define MPI2_IOCFACTS_CAPABILITY_TLR (0x00000800) -#define MPI2_IOCFACTS_CAPABILITY_MULTICAST (0x00000100) -#define MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET (0x00000080) -#define MPI2_IOCFACTS_CAPABILITY_EEDP (0x00000040) -#define MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER (0x00000020) -#define MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER (0x00000010) -#define MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER (0x00000008) -#define MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING (0x00000004) - -/*ProtocolFlags */ -#define MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET (0x0001) -#define MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR (0x0002) - -/**************************************************************************** -* PortFacts message -****************************************************************************/ - -/*PortFacts Request message */ -typedef struct _MPI2_PORT_FACTS_REQUEST { - U16 Reserved1; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 PortNumber; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ -} MPI2_PORT_FACTS_REQUEST, *PTR_MPI2_PORT_FACTS_REQUEST, - Mpi2PortFactsRequest_t, *pMpi2PortFactsRequest_t; - -/*PortFacts Reply message */ -typedef struct _MPI2_PORT_FACTS_REPLY { - U16 Reserved1; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 PortNumber; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U16 Reserved4; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U8 Reserved5; /*0x14 */ - U8 PortType; /*0x15 */ - U16 Reserved6; /*0x16 */ - U16 MaxPostedCmdBuffers; /*0x18 */ - U16 Reserved7; /*0x1A */ -} MPI2_PORT_FACTS_REPLY, *PTR_MPI2_PORT_FACTS_REPLY, - Mpi2PortFactsReply_t, *pMpi2PortFactsReply_t; - -/*PortType values */ -#define MPI2_PORTFACTS_PORTTYPE_INACTIVE (0x00) -#define MPI2_PORTFACTS_PORTTYPE_FC (0x10) -#define MPI2_PORTFACTS_PORTTYPE_ISCSI (0x20) -#define MPI2_PORTFACTS_PORTTYPE_SAS_PHYSICAL (0x30) -#define MPI2_PORTFACTS_PORTTYPE_SAS_VIRTUAL (0x31) - -/**************************************************************************** -* PortEnable message -****************************************************************************/ - -/*PortEnable Request message */ -typedef struct _MPI2_PORT_ENABLE_REQUEST { - U16 Reserved1; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U8 Reserved2; /*0x04 */ - U8 PortFlags; /*0x05 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ -} MPI2_PORT_ENABLE_REQUEST, *PTR_MPI2_PORT_ENABLE_REQUEST, - Mpi2PortEnableRequest_t, *pMpi2PortEnableRequest_t; - -/*PortEnable Reply message */ -typedef struct _MPI2_PORT_ENABLE_REPLY { - U16 Reserved1; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U8 Reserved2; /*0x04 */ - U8 PortFlags; /*0x05 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_PORT_ENABLE_REPLY, *PTR_MPI2_PORT_ENABLE_REPLY, - Mpi2PortEnableReply_t, *pMpi2PortEnableReply_t; - -/**************************************************************************** -* EventNotification message -****************************************************************************/ - -/*EventNotification Request message */ -#define MPI2_EVENT_NOTIFY_EVENTMASK_WORDS (4) - -typedef struct _MPI2_EVENT_NOTIFICATION_REQUEST { - U16 Reserved1; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 Reserved5; /*0x0C */ - U32 Reserved6; /*0x10 */ - U32 EventMasks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; /*0x14 */ - U16 SASBroadcastPrimitiveMasks; /*0x24 */ - U16 SASNotifyPrimitiveMasks; /*0x26 */ - U32 Reserved8; /*0x28 */ -} MPI2_EVENT_NOTIFICATION_REQUEST, - *PTR_MPI2_EVENT_NOTIFICATION_REQUEST, - Mpi2EventNotificationRequest_t, - *pMpi2EventNotificationRequest_t; - -/*EventNotification Reply message */ -typedef struct _MPI2_EVENT_NOTIFICATION_REPLY { - U16 EventDataLength; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved1; /*0x04 */ - U8 AckRequired; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved2; /*0x0A */ - U16 Reserved3; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U16 Event; /*0x14 */ - U16 Reserved4; /*0x16 */ - U32 EventContext; /*0x18 */ - U32 EventData[1]; /*0x1C */ -} MPI2_EVENT_NOTIFICATION_REPLY, *PTR_MPI2_EVENT_NOTIFICATION_REPLY, - Mpi2EventNotificationReply_t, - *pMpi2EventNotificationReply_t; - -/*AckRequired */ -#define MPI2_EVENT_NOTIFICATION_ACK_NOT_REQUIRED (0x00) -#define MPI2_EVENT_NOTIFICATION_ACK_REQUIRED (0x01) - -/*Event */ -#define MPI2_EVENT_LOG_DATA (0x0001) -#define MPI2_EVENT_STATE_CHANGE (0x0002) -#define MPI2_EVENT_HARD_RESET_RECEIVED (0x0005) -#define MPI2_EVENT_EVENT_CHANGE (0x000A) -#define MPI2_EVENT_TASK_SET_FULL (0x000E) /*obsolete */ -#define MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE (0x000F) -#define MPI2_EVENT_IR_OPERATION_STATUS (0x0014) -#define MPI2_EVENT_SAS_DISCOVERY (0x0016) -#define MPI2_EVENT_SAS_BROADCAST_PRIMITIVE (0x0017) -#define MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE (0x0018) -#define MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW (0x0019) -#define MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST (0x001C) -#define MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE (0x001D) -#define MPI2_EVENT_IR_VOLUME (0x001E) -#define MPI2_EVENT_IR_PHYSICAL_DISK (0x001F) -#define MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST (0x0020) -#define MPI2_EVENT_LOG_ENTRY_ADDED (0x0021) -#define MPI2_EVENT_SAS_PHY_COUNTER (0x0022) -#define MPI2_EVENT_GPIO_INTERRUPT (0x0023) -#define MPI2_EVENT_HOST_BASED_DISCOVERY_PHY (0x0024) -#define MPI2_EVENT_SAS_QUIESCE (0x0025) -#define MPI2_EVENT_SAS_NOTIFY_PRIMITIVE (0x0026) -#define MPI2_EVENT_TEMP_THRESHOLD (0x0027) -#define MPI2_EVENT_HOST_MESSAGE (0x0028) -#define MPI2_EVENT_POWER_PERFORMANCE_CHANGE (0x0029) -#define MPI2_EVENT_MIN_PRODUCT_SPECIFIC (0x006E) -#define MPI2_EVENT_MAX_PRODUCT_SPECIFIC (0x007F) - -/*Log Entry Added Event data */ - -/*the following structure matches MPI2_LOG_0_ENTRY in mpi2_cnfg.h */ -#define MPI2_EVENT_DATA_LOG_DATA_LENGTH (0x1C) - -typedef struct _MPI2_EVENT_DATA_LOG_ENTRY_ADDED { - U64 TimeStamp; /*0x00 */ - U32 Reserved1; /*0x08 */ - U16 LogSequence; /*0x0C */ - U16 LogEntryQualifier; /*0x0E */ - U8 VP_ID; /*0x10 */ - U8 VF_ID; /*0x11 */ - U16 Reserved2; /*0x12 */ - U8 LogData[MPI2_EVENT_DATA_LOG_DATA_LENGTH]; /*0x14 */ -} MPI2_EVENT_DATA_LOG_ENTRY_ADDED, - *PTR_MPI2_EVENT_DATA_LOG_ENTRY_ADDED, - Mpi2EventDataLogEntryAdded_t, - *pMpi2EventDataLogEntryAdded_t; - -/*GPIO Interrupt Event data */ - -typedef struct _MPI2_EVENT_DATA_GPIO_INTERRUPT { - U8 GPIONum; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ -} MPI2_EVENT_DATA_GPIO_INTERRUPT, - *PTR_MPI2_EVENT_DATA_GPIO_INTERRUPT, - Mpi2EventDataGpioInterrupt_t, - *pMpi2EventDataGpioInterrupt_t; - -/*Temperature Threshold Event data */ - -typedef struct _MPI2_EVENT_DATA_TEMPERATURE { - U16 Status; /*0x00 */ - U8 SensorNum; /*0x02 */ - U8 Reserved1; /*0x03 */ - U16 CurrentTemperature; /*0x04 */ - U16 Reserved2; /*0x06 */ - U32 Reserved3; /*0x08 */ - U32 Reserved4; /*0x0C */ -} MPI2_EVENT_DATA_TEMPERATURE, - *PTR_MPI2_EVENT_DATA_TEMPERATURE, - Mpi2EventDataTemperature_t, *pMpi2EventDataTemperature_t; - -/*Temperature Threshold Event data Status bits */ -#define MPI2_EVENT_TEMPERATURE3_EXCEEDED (0x0008) -#define MPI2_EVENT_TEMPERATURE2_EXCEEDED (0x0004) -#define MPI2_EVENT_TEMPERATURE1_EXCEEDED (0x0002) -#define MPI2_EVENT_TEMPERATURE0_EXCEEDED (0x0001) - -/*Host Message Event data */ - -typedef struct _MPI2_EVENT_DATA_HOST_MESSAGE { - U8 SourceVF_ID; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 Reserved3; /*0x04 */ - U32 HostData[1]; /*0x08 */ -} MPI2_EVENT_DATA_HOST_MESSAGE, *PTR_MPI2_EVENT_DATA_HOST_MESSAGE, - Mpi2EventDataHostMessage_t, *pMpi2EventDataHostMessage_t; - -/*Power Performance Change Event */ - -typedef struct _MPI2_EVENT_DATA_POWER_PERF_CHANGE { - U8 CurrentPowerMode; /*0x00 */ - U8 PreviousPowerMode; /*0x01 */ - U16 Reserved1; /*0x02 */ -} MPI2_EVENT_DATA_POWER_PERF_CHANGE, - *PTR_MPI2_EVENT_DATA_POWER_PERF_CHANGE, - Mpi2EventDataPowerPerfChange_t, - *pMpi2EventDataPowerPerfChange_t; - -/*defines for CurrentPowerMode and PreviousPowerMode fields */ -#define MPI2_EVENT_PM_INIT_MASK (0xC0) -#define MPI2_EVENT_PM_INIT_UNAVAILABLE (0x00) -#define MPI2_EVENT_PM_INIT_HOST (0x40) -#define MPI2_EVENT_PM_INIT_IO_UNIT (0x80) -#define MPI2_EVENT_PM_INIT_PCIE_DPA (0xC0) - -#define MPI2_EVENT_PM_MODE_MASK (0x07) -#define MPI2_EVENT_PM_MODE_UNAVAILABLE (0x00) -#define MPI2_EVENT_PM_MODE_UNKNOWN (0x01) -#define MPI2_EVENT_PM_MODE_FULL_POWER (0x04) -#define MPI2_EVENT_PM_MODE_REDUCED_POWER (0x05) -#define MPI2_EVENT_PM_MODE_STANDBY (0x06) - -/*Hard Reset Received Event data */ - -typedef struct _MPI2_EVENT_DATA_HARD_RESET_RECEIVED { - U8 Reserved1; /*0x00 */ - U8 Port; /*0x01 */ - U16 Reserved2; /*0x02 */ -} MPI2_EVENT_DATA_HARD_RESET_RECEIVED, - *PTR_MPI2_EVENT_DATA_HARD_RESET_RECEIVED, - Mpi2EventDataHardResetReceived_t, - *pMpi2EventDataHardResetReceived_t; - -/*Task Set Full Event data */ -/* this event is obsolete */ - -typedef struct _MPI2_EVENT_DATA_TASK_SET_FULL { - U16 DevHandle; /*0x00 */ - U16 CurrentDepth; /*0x02 */ -} MPI2_EVENT_DATA_TASK_SET_FULL, *PTR_MPI2_EVENT_DATA_TASK_SET_FULL, - Mpi2EventDataTaskSetFull_t, *pMpi2EventDataTaskSetFull_t; - -/*SAS Device Status Change Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE { - U16 TaskTag; /*0x00 */ - U8 ReasonCode; /*0x02 */ - U8 PhysicalPort; /*0x03 */ - U8 ASC; /*0x04 */ - U8 ASCQ; /*0x05 */ - U16 DevHandle; /*0x06 */ - U32 Reserved2; /*0x08 */ - U64 SASAddress; /*0x0C */ - U8 LUN[8]; /*0x14 */ -} MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, - *PTR_MPI2_EVENT_DATA_SAS_DEVICE_STATUS_CHANGE, - Mpi2EventDataSasDeviceStatusChange_t, - *pMpi2EventDataSasDeviceStatusChange_t; - -/*SAS Device Status Change Event data ReasonCode values */ -#define MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA (0x05) -#define MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED (0x07) -#define MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET (0x08) -#define MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL (0x09) -#define MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL (0x0A) -#define MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL (0x0B) -#define MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL (0x0C) -#define MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION (0x0D) -#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET (0x0E) -#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL (0x0F) -#define MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE (0x10) -#define MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY (0x11) -#define MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY (0x12) - -/*Integrated RAID Operation Status Event data */ - -typedef struct _MPI2_EVENT_DATA_IR_OPERATION_STATUS { - U16 VolDevHandle; /*0x00 */ - U16 Reserved1; /*0x02 */ - U8 RAIDOperation; /*0x04 */ - U8 PercentComplete; /*0x05 */ - U16 Reserved2; /*0x06 */ - U32 ElapsedSeconds; /*0x08 */ -} MPI2_EVENT_DATA_IR_OPERATION_STATUS, - *PTR_MPI2_EVENT_DATA_IR_OPERATION_STATUS, - Mpi2EventDataIrOperationStatus_t, - *pMpi2EventDataIrOperationStatus_t; - -/*Integrated RAID Operation Status Event data RAIDOperation values */ -#define MPI2_EVENT_IR_RAIDOP_RESYNC (0x00) -#define MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION (0x01) -#define MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK (0x02) -#define MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT (0x03) -#define MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT (0x04) - -/*Integrated RAID Volume Event data */ - -typedef struct _MPI2_EVENT_DATA_IR_VOLUME { - U16 VolDevHandle; /*0x00 */ - U8 ReasonCode; /*0x02 */ - U8 Reserved1; /*0x03 */ - U32 NewValue; /*0x04 */ - U32 PreviousValue; /*0x08 */ -} MPI2_EVENT_DATA_IR_VOLUME, *PTR_MPI2_EVENT_DATA_IR_VOLUME, - Mpi2EventDataIrVolume_t, *pMpi2EventDataIrVolume_t; - -/*Integrated RAID Volume Event data ReasonCode values */ -#define MPI2_EVENT_IR_VOLUME_RC_SETTINGS_CHANGED (0x01) -#define MPI2_EVENT_IR_VOLUME_RC_STATUS_FLAGS_CHANGED (0x02) -#define MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED (0x03) - -/*Integrated RAID Physical Disk Event data */ - -typedef struct _MPI2_EVENT_DATA_IR_PHYSICAL_DISK { - U16 Reserved1; /*0x00 */ - U8 ReasonCode; /*0x02 */ - U8 PhysDiskNum; /*0x03 */ - U16 PhysDiskDevHandle; /*0x04 */ - U16 Reserved2; /*0x06 */ - U16 Slot; /*0x08 */ - U16 EnclosureHandle; /*0x0A */ - U32 NewValue; /*0x0C */ - U32 PreviousValue; /*0x10 */ -} MPI2_EVENT_DATA_IR_PHYSICAL_DISK, - *PTR_MPI2_EVENT_DATA_IR_PHYSICAL_DISK, - Mpi2EventDataIrPhysicalDisk_t, - *pMpi2EventDataIrPhysicalDisk_t; - -/*Integrated RAID Physical Disk Event data ReasonCode values */ -#define MPI2_EVENT_IR_PHYSDISK_RC_SETTINGS_CHANGED (0x01) -#define MPI2_EVENT_IR_PHYSDISK_RC_STATUS_FLAGS_CHANGED (0x02) -#define MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED (0x03) - -/*Integrated RAID Configuration Change List Event data */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check NumElements at runtime. - */ -#ifndef MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT -#define MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT (1) -#endif - -typedef struct _MPI2_EVENT_IR_CONFIG_ELEMENT { - U16 ElementFlags; /*0x00 */ - U16 VolDevHandle; /*0x02 */ - U8 ReasonCode; /*0x04 */ - U8 PhysDiskNum; /*0x05 */ - U16 PhysDiskDevHandle; /*0x06 */ -} MPI2_EVENT_IR_CONFIG_ELEMENT, *PTR_MPI2_EVENT_IR_CONFIG_ELEMENT, - Mpi2EventIrConfigElement_t, *pMpi2EventIrConfigElement_t; - -/*IR Configuration Change List Event data ElementFlags values */ -#define MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK (0x000F) -#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT (0x0000) -#define MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT (0x0001) -#define MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT (0x0002) - -/*IR Configuration Change List Event data ReasonCode values */ -#define MPI2_EVENT_IR_CHANGE_RC_ADDED (0x01) -#define MPI2_EVENT_IR_CHANGE_RC_REMOVED (0x02) -#define MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE (0x03) -#define MPI2_EVENT_IR_CHANGE_RC_HIDE (0x04) -#define MPI2_EVENT_IR_CHANGE_RC_UNHIDE (0x05) -#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED (0x06) -#define MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED (0x07) -#define MPI2_EVENT_IR_CHANGE_RC_PD_CREATED (0x08) -#define MPI2_EVENT_IR_CHANGE_RC_PD_DELETED (0x09) - -typedef struct _MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST { - U8 NumElements; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 Reserved2; /*0x02 */ - U8 ConfigNum; /*0x03 */ - U32 Flags; /*0x04 */ - MPI2_EVENT_IR_CONFIG_ELEMENT - ConfigElement[MPI2_EVENT_IR_CONFIG_ELEMENT_COUNT];/*0x08 */ -} MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST, - *PTR_MPI2_EVENT_DATA_IR_CONFIG_CHANGE_LIST, - Mpi2EventDataIrConfigChangeList_t, - *pMpi2EventDataIrConfigChangeList_t; - -/*IR Configuration Change List Event data Flags values */ -#define MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG (0x00000001) - -/*SAS Discovery Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_DISCOVERY { - U8 Flags; /*0x00 */ - U8 ReasonCode; /*0x01 */ - U8 PhysicalPort; /*0x02 */ - U8 Reserved1; /*0x03 */ - U32 DiscoveryStatus; /*0x04 */ -} MPI2_EVENT_DATA_SAS_DISCOVERY, - *PTR_MPI2_EVENT_DATA_SAS_DISCOVERY, - Mpi2EventDataSasDiscovery_t, *pMpi2EventDataSasDiscovery_t; - -/*SAS Discovery Event data Flags values */ -#define MPI2_EVENT_SAS_DISC_DEVICE_CHANGE (0x02) -#define MPI2_EVENT_SAS_DISC_IN_PROGRESS (0x01) - -/*SAS Discovery Event data ReasonCode values */ -#define MPI2_EVENT_SAS_DISC_RC_STARTED (0x01) -#define MPI2_EVENT_SAS_DISC_RC_COMPLETED (0x02) - -/*SAS Discovery Event data DiscoveryStatus values */ -#define MPI2_EVENT_SAS_DISC_DS_MAX_ENCLOSURES_EXCEED (0x80000000) -#define MPI2_EVENT_SAS_DISC_DS_MAX_EXPANDERS_EXCEED (0x40000000) -#define MPI2_EVENT_SAS_DISC_DS_MAX_DEVICES_EXCEED (0x20000000) -#define MPI2_EVENT_SAS_DISC_DS_MAX_TOPO_PHYS_EXCEED (0x10000000) -#define MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR (0x08000000) -#define MPI2_EVENT_SAS_DISC_DS_MULTI_SUBTRACTIVE_SUBTRACTIVE (0x00008000) -#define MPI2_EVENT_SAS_DISC_DS_EXP_MULTI_SUBTRACTIVE (0x00004000) -#define MPI2_EVENT_SAS_DISC_DS_MULTI_PORT_DOMAIN (0x00002000) -#define MPI2_EVENT_SAS_DISC_DS_TABLE_TO_SUBTRACTIVE_LINK (0x00001000) -#define MPI2_EVENT_SAS_DISC_DS_UNSUPPORTED_DEVICE (0x00000800) -#define MPI2_EVENT_SAS_DISC_DS_TABLE_LINK (0x00000400) -#define MPI2_EVENT_SAS_DISC_DS_SUBTRACTIVE_LINK (0x00000200) -#define MPI2_EVENT_SAS_DISC_DS_SMP_CRC_ERROR (0x00000100) -#define MPI2_EVENT_SAS_DISC_DS_SMP_FUNCTION_FAILED (0x00000080) -#define MPI2_EVENT_SAS_DISC_DS_INDEX_NOT_EXIST (0x00000040) -#define MPI2_EVENT_SAS_DISC_DS_OUT_ROUTE_ENTRIES (0x00000020) -#define MPI2_EVENT_SAS_DISC_DS_SMP_TIMEOUT (0x00000010) -#define MPI2_EVENT_SAS_DISC_DS_MULTIPLE_PORTS (0x00000004) -#define MPI2_EVENT_SAS_DISC_DS_UNADDRESSABLE_DEVICE (0x00000002) -#define MPI2_EVENT_SAS_DISC_DS_LOOP_DETECTED (0x00000001) - -/*SAS Broadcast Primitive Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE { - U8 PhyNum; /*0x00 */ - U8 Port; /*0x01 */ - U8 PortWidth; /*0x02 */ - U8 Primitive; /*0x03 */ -} MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, - *PTR_MPI2_EVENT_DATA_SAS_BROADCAST_PRIMITIVE, - Mpi2EventDataSasBroadcastPrimitive_t, - *pMpi2EventDataSasBroadcastPrimitive_t; - -/*defines for the Primitive field */ -#define MPI2_EVENT_PRIMITIVE_CHANGE (0x01) -#define MPI2_EVENT_PRIMITIVE_SES (0x02) -#define MPI2_EVENT_PRIMITIVE_EXPANDER (0x03) -#define MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT (0x04) -#define MPI2_EVENT_PRIMITIVE_RESERVED3 (0x05) -#define MPI2_EVENT_PRIMITIVE_RESERVED4 (0x06) -#define MPI2_EVENT_PRIMITIVE_CHANGE0_RESERVED (0x07) -#define MPI2_EVENT_PRIMITIVE_CHANGE1_RESERVED (0x08) - -/*SAS Notify Primitive Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE { - U8 PhyNum; /*0x00 */ - U8 Port; /*0x01 */ - U8 Reserved1; /*0x02 */ - U8 Primitive; /*0x03 */ -} MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, - *PTR_MPI2_EVENT_DATA_SAS_NOTIFY_PRIMITIVE, - Mpi2EventDataSasNotifyPrimitive_t, - *pMpi2EventDataSasNotifyPrimitive_t; - -/*defines for the Primitive field */ -#define MPI2_EVENT_NOTIFY_ENABLE_SPINUP (0x01) -#define MPI2_EVENT_NOTIFY_POWER_LOSS_EXPECTED (0x02) -#define MPI2_EVENT_NOTIFY_RESERVED1 (0x03) -#define MPI2_EVENT_NOTIFY_RESERVED2 (0x04) - -/*SAS Initiator Device Status Change Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE { - U8 ReasonCode; /*0x00 */ - U8 PhysicalPort; /*0x01 */ - U16 DevHandle; /*0x02 */ - U64 SASAddress; /*0x04 */ -} MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, - *PTR_MPI2_EVENT_DATA_SAS_INIT_DEV_STATUS_CHANGE, - Mpi2EventDataSasInitDevStatusChange_t, - *pMpi2EventDataSasInitDevStatusChange_t; - -/*SAS Initiator Device Status Change event ReasonCode values */ -#define MPI2_EVENT_SAS_INIT_RC_ADDED (0x01) -#define MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING (0x02) - -/*SAS Initiator Device Table Overflow Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW { - U16 MaxInit; /*0x00 */ - U16 CurrentInit; /*0x02 */ - U64 SASAddress; /*0x04 */ -} MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, - *PTR_MPI2_EVENT_DATA_SAS_INIT_TABLE_OVERFLOW, - Mpi2EventDataSasInitTableOverflow_t, - *pMpi2EventDataSasInitTableOverflow_t; - -/*SAS Topology Change List Event data */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check NumEntries at runtime. - */ -#ifndef MPI2_EVENT_SAS_TOPO_PHY_COUNT -#define MPI2_EVENT_SAS_TOPO_PHY_COUNT (1) -#endif - -typedef struct _MPI2_EVENT_SAS_TOPO_PHY_ENTRY { - U16 AttachedDevHandle; /*0x00 */ - U8 LinkRate; /*0x02 */ - U8 PhyStatus; /*0x03 */ -} MPI2_EVENT_SAS_TOPO_PHY_ENTRY, *PTR_MPI2_EVENT_SAS_TOPO_PHY_ENTRY, - Mpi2EventSasTopoPhyEntry_t, *pMpi2EventSasTopoPhyEntry_t; - -typedef struct _MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST { - U16 EnclosureHandle; /*0x00 */ - U16 ExpanderDevHandle; /*0x02 */ - U8 NumPhys; /*0x04 */ - U8 Reserved1; /*0x05 */ - U16 Reserved2; /*0x06 */ - U8 NumEntries; /*0x08 */ - U8 StartPhyNum; /*0x09 */ - U8 ExpStatus; /*0x0A */ - U8 PhysicalPort; /*0x0B */ - MPI2_EVENT_SAS_TOPO_PHY_ENTRY - PHY[MPI2_EVENT_SAS_TOPO_PHY_COUNT]; /*0x0C */ -} MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, - *PTR_MPI2_EVENT_DATA_SAS_TOPOLOGY_CHANGE_LIST, - Mpi2EventDataSasTopologyChangeList_t, - *pMpi2EventDataSasTopologyChangeList_t; - -/*values for the ExpStatus field */ -#define MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER (0x00) -#define MPI2_EVENT_SAS_TOPO_ES_ADDED (0x01) -#define MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING (0x02) -#define MPI2_EVENT_SAS_TOPO_ES_RESPONDING (0x03) -#define MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING (0x04) - -/*defines for the LinkRate field */ -#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_MASK (0xF0) -#define MPI2_EVENT_SAS_TOPO_LR_CURRENT_SHIFT (4) -#define MPI2_EVENT_SAS_TOPO_LR_PREV_MASK (0x0F) -#define MPI2_EVENT_SAS_TOPO_LR_PREV_SHIFT (0) - -#define MPI2_EVENT_SAS_TOPO_LR_UNKNOWN_LINK_RATE (0x00) -#define MPI2_EVENT_SAS_TOPO_LR_PHY_DISABLED (0x01) -#define MPI2_EVENT_SAS_TOPO_LR_NEGOTIATION_FAILED (0x02) -#define MPI2_EVENT_SAS_TOPO_LR_SATA_OOB_COMPLETE (0x03) -#define MPI2_EVENT_SAS_TOPO_LR_PORT_SELECTOR (0x04) -#define MPI2_EVENT_SAS_TOPO_LR_SMP_RESET_IN_PROGRESS (0x05) -#define MPI2_EVENT_SAS_TOPO_LR_UNSUPPORTED_PHY (0x06) -#define MPI2_EVENT_SAS_TOPO_LR_RATE_1_5 (0x08) -#define MPI2_EVENT_SAS_TOPO_LR_RATE_3_0 (0x09) -#define MPI2_EVENT_SAS_TOPO_LR_RATE_6_0 (0x0A) -#define MPI25_EVENT_SAS_TOPO_LR_RATE_12_0 (0x0B) - -/*values for the PhyStatus field */ -#define MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT (0x80) -#define MPI2_EVENT_SAS_TOPO_PS_MULTIPLEX_CHANGE (0x10) -/*values for the PhyStatus ReasonCode sub-field */ -#define MPI2_EVENT_SAS_TOPO_RC_MASK (0x0F) -#define MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED (0x01) -#define MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING (0x02) -#define MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED (0x03) -#define MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE (0x04) -#define MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING (0x05) - -/*SAS Enclosure Device Status Change Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE { - U16 EnclosureHandle; /*0x00 */ - U8 ReasonCode; /*0x02 */ - U8 PhysicalPort; /*0x03 */ - U64 EnclosureLogicalID; /*0x04 */ - U16 NumSlots; /*0x0C */ - U16 StartSlot; /*0x0E */ - U32 PhyBits; /*0x10 */ -} MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE, - *PTR_MPI2_EVENT_DATA_SAS_ENCL_DEV_STATUS_CHANGE, - Mpi2EventDataSasEnclDevStatusChange_t, - *pMpi2EventDataSasEnclDevStatusChange_t; - -/*SAS Enclosure Device Status Change event ReasonCode values */ -#define MPI2_EVENT_SAS_ENCL_RC_ADDED (0x01) -#define MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING (0x02) - -/*SAS PHY Counter Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_PHY_COUNTER { - U64 TimeStamp; /*0x00 */ - U32 Reserved1; /*0x08 */ - U8 PhyEventCode; /*0x0C */ - U8 PhyNum; /*0x0D */ - U16 Reserved2; /*0x0E */ - U32 PhyEventInfo; /*0x10 */ - U8 CounterType; /*0x14 */ - U8 ThresholdWindow; /*0x15 */ - U8 TimeUnits; /*0x16 */ - U8 Reserved3; /*0x17 */ - U32 EventThreshold; /*0x18 */ - U16 ThresholdFlags; /*0x1C */ - U16 Reserved4; /*0x1E */ -} MPI2_EVENT_DATA_SAS_PHY_COUNTER, - *PTR_MPI2_EVENT_DATA_SAS_PHY_COUNTER, - Mpi2EventDataSasPhyCounter_t, - *pMpi2EventDataSasPhyCounter_t; - -/*use MPI2_SASPHY3_EVENT_CODE_ values from mpi2_cnfg.h - *for the PhyEventCode field */ - -/*use MPI2_SASPHY3_COUNTER_TYPE_ values from mpi2_cnfg.h - *for the CounterType field */ - -/*use MPI2_SASPHY3_TIME_UNITS_ values from mpi2_cnfg.h - *for the TimeUnits field */ - -/*use MPI2_SASPHY3_TFLAGS_ values from mpi2_cnfg.h - *for the ThresholdFlags field */ - -/*SAS Quiesce Event data */ - -typedef struct _MPI2_EVENT_DATA_SAS_QUIESCE { - U8 ReasonCode; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 Reserved3; /*0x04 */ -} MPI2_EVENT_DATA_SAS_QUIESCE, - *PTR_MPI2_EVENT_DATA_SAS_QUIESCE, - Mpi2EventDataSasQuiesce_t, *pMpi2EventDataSasQuiesce_t; - -/*SAS Quiesce Event data ReasonCode values */ -#define MPI2_EVENT_SAS_QUIESCE_RC_STARTED (0x01) -#define MPI2_EVENT_SAS_QUIESCE_RC_COMPLETED (0x02) - -/*Host Based Discovery Phy Event data */ - -typedef struct _MPI2_EVENT_HBD_PHY_SAS { - U8 Flags; /*0x00 */ - U8 NegotiatedLinkRate; /*0x01 */ - U8 PhyNum; /*0x02 */ - U8 PhysicalPort; /*0x03 */ - U32 Reserved1; /*0x04 */ - U8 InitialFrame[28]; /*0x08 */ -} MPI2_EVENT_HBD_PHY_SAS, *PTR_MPI2_EVENT_HBD_PHY_SAS, - Mpi2EventHbdPhySas_t, *pMpi2EventHbdPhySas_t; - -/*values for the Flags field */ -#define MPI2_EVENT_HBD_SAS_FLAGS_FRAME_VALID (0x02) -#define MPI2_EVENT_HBD_SAS_FLAGS_SATA_FRAME (0x01) - -/*use MPI2_SAS_NEG_LINK_RATE_ defines from mpi2_cnfg.h - *for the NegotiatedLinkRate field */ - -typedef union _MPI2_EVENT_HBD_DESCRIPTOR { - MPI2_EVENT_HBD_PHY_SAS Sas; -} MPI2_EVENT_HBD_DESCRIPTOR, *PTR_MPI2_EVENT_HBD_DESCRIPTOR, - Mpi2EventHbdDescriptor_t, *pMpi2EventHbdDescriptor_t; - -typedef struct _MPI2_EVENT_DATA_HBD_PHY { - U8 DescriptorType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 Reserved3; /*0x04 */ - MPI2_EVENT_HBD_DESCRIPTOR Descriptor; /*0x08 */ -} MPI2_EVENT_DATA_HBD_PHY, *PTR_MPI2_EVENT_DATA_HBD_PHY, - Mpi2EventDataHbdPhy_t, - *pMpi2EventDataMpi2EventDataHbdPhy_t; - -/*values for the DescriptorType field */ -#define MPI2_EVENT_HBD_DT_SAS (0x01) - -/**************************************************************************** -* EventAck message -****************************************************************************/ - -/*EventAck Request message */ -typedef struct _MPI2_EVENT_ACK_REQUEST { - U16 Reserved1; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Event; /*0x0C */ - U16 Reserved5; /*0x0E */ - U32 EventContext; /*0x10 */ -} MPI2_EVENT_ACK_REQUEST, *PTR_MPI2_EVENT_ACK_REQUEST, - Mpi2EventAckRequest_t, *pMpi2EventAckRequest_t; - -/*EventAck Reply message */ -typedef struct _MPI2_EVENT_ACK_REPLY { - U16 Reserved1; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_EVENT_ACK_REPLY, *PTR_MPI2_EVENT_ACK_REPLY, - Mpi2EventAckReply_t, *pMpi2EventAckReply_t; - -/**************************************************************************** -* SendHostMessage message -****************************************************************************/ - -/*SendHostMessage Request message */ -typedef struct _MPI2_SEND_HOST_MESSAGE_REQUEST { - U16 HostDataLength; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved1; /*0x04 */ - U8 Reserved2; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U8 Reserved4; /*0x0C */ - U8 DestVF_ID; /*0x0D */ - U16 Reserved5; /*0x0E */ - U32 Reserved6; /*0x10 */ - U32 Reserved7; /*0x14 */ - U32 Reserved8; /*0x18 */ - U32 Reserved9; /*0x1C */ - U32 Reserved10; /*0x20 */ - U32 HostData[1]; /*0x24 */ -} MPI2_SEND_HOST_MESSAGE_REQUEST, - *PTR_MPI2_SEND_HOST_MESSAGE_REQUEST, - Mpi2SendHostMessageRequest_t, - *pMpi2SendHostMessageRequest_t; - -/*SendHostMessage Reply message */ -typedef struct _MPI2_SEND_HOST_MESSAGE_REPLY { - U16 HostDataLength; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved1; /*0x04 */ - U8 Reserved2; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U16 Reserved4; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_SEND_HOST_MESSAGE_REPLY, *PTR_MPI2_SEND_HOST_MESSAGE_REPLY, - Mpi2SendHostMessageReply_t, *pMpi2SendHostMessageReply_t; - -/**************************************************************************** -* FWDownload message -****************************************************************************/ - -/*MPI v2.0 FWDownload Request message */ -typedef struct _MPI2_FW_DOWNLOAD_REQUEST { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 TotalImageSize; /*0x0C */ - U32 Reserved5; /*0x10 */ - MPI2_MPI_SGE_UNION SGL; /*0x14 */ -} MPI2_FW_DOWNLOAD_REQUEST, *PTR_MPI2_FW_DOWNLOAD_REQUEST, - Mpi2FWDownloadRequest, *pMpi2FWDownloadRequest; - -#define MPI2_FW_DOWNLOAD_MSGFLGS_LAST_SEGMENT (0x01) - -#define MPI2_FW_DOWNLOAD_ITYPE_FW (0x01) -#define MPI2_FW_DOWNLOAD_ITYPE_BIOS (0x02) -#define MPI2_FW_DOWNLOAD_ITYPE_MANUFACTURING (0x06) -#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_1 (0x07) -#define MPI2_FW_DOWNLOAD_ITYPE_CONFIG_2 (0x08) -#define MPI2_FW_DOWNLOAD_ITYPE_MEGARAID (0x09) -#define MPI2_FW_DOWNLOAD_ITYPE_COMPLETE (0x0A) -#define MPI2_FW_DOWNLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) -#define MPI2_FW_DOWNLOAD_ITYPE_PUBLIC_KEY (0x0C) -#define MPI2_FW_DOWNLOAD_ITYPE_MIN_PRODUCT_SPECIFIC (0xF0) - -/*MPI v2.0 FWDownload TransactionContext Element */ -typedef struct _MPI2_FW_DOWNLOAD_TCSGE { - U8 Reserved1; /*0x00 */ - U8 ContextSize; /*0x01 */ - U8 DetailsLength; /*0x02 */ - U8 Flags; /*0x03 */ - U32 Reserved2; /*0x04 */ - U32 ImageOffset; /*0x08 */ - U32 ImageSize; /*0x0C */ -} MPI2_FW_DOWNLOAD_TCSGE, *PTR_MPI2_FW_DOWNLOAD_TCSGE, - Mpi2FWDownloadTCSGE_t, *pMpi2FWDownloadTCSGE_t; - -/*MPI v2.5 FWDownload Request message */ -typedef struct _MPI25_FW_DOWNLOAD_REQUEST { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 TotalImageSize; /*0x0C */ - U32 Reserved5; /*0x10 */ - U32 Reserved6; /*0x14 */ - U32 ImageOffset; /*0x18 */ - U32 ImageSize; /*0x1C */ - MPI25_SGE_IO_UNION SGL; /*0x20 */ -} MPI25_FW_DOWNLOAD_REQUEST, *PTR_MPI25_FW_DOWNLOAD_REQUEST, - Mpi25FWDownloadRequest, *pMpi25FWDownloadRequest; - -/*FWDownload Reply message */ -typedef struct _MPI2_FW_DOWNLOAD_REPLY { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_FW_DOWNLOAD_REPLY, *PTR_MPI2_FW_DOWNLOAD_REPLY, - Mpi2FWDownloadReply_t, *pMpi2FWDownloadReply_t; - -/**************************************************************************** -* FWUpload message -****************************************************************************/ - -/*MPI v2.0 FWUpload Request message */ -typedef struct _MPI2_FW_UPLOAD_REQUEST { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 Reserved5; /*0x0C */ - U32 Reserved6; /*0x10 */ - MPI2_MPI_SGE_UNION SGL; /*0x14 */ -} MPI2_FW_UPLOAD_REQUEST, *PTR_MPI2_FW_UPLOAD_REQUEST, - Mpi2FWUploadRequest_t, *pMpi2FWUploadRequest_t; - -#define MPI2_FW_UPLOAD_ITYPE_FW_CURRENT (0x00) -#define MPI2_FW_UPLOAD_ITYPE_FW_FLASH (0x01) -#define MPI2_FW_UPLOAD_ITYPE_BIOS_FLASH (0x02) -#define MPI2_FW_UPLOAD_ITYPE_FW_BACKUP (0x05) -#define MPI2_FW_UPLOAD_ITYPE_MANUFACTURING (0x06) -#define MPI2_FW_UPLOAD_ITYPE_CONFIG_1 (0x07) -#define MPI2_FW_UPLOAD_ITYPE_CONFIG_2 (0x08) -#define MPI2_FW_UPLOAD_ITYPE_MEGARAID (0x09) -#define MPI2_FW_UPLOAD_ITYPE_COMPLETE (0x0A) -#define MPI2_FW_UPLOAD_ITYPE_COMMON_BOOT_BLOCK (0x0B) - -/*MPI v2.0 FWUpload TransactionContext Element */ -typedef struct _MPI2_FW_UPLOAD_TCSGE { - U8 Reserved1; /*0x00 */ - U8 ContextSize; /*0x01 */ - U8 DetailsLength; /*0x02 */ - U8 Flags; /*0x03 */ - U32 Reserved2; /*0x04 */ - U32 ImageOffset; /*0x08 */ - U32 ImageSize; /*0x0C */ -} MPI2_FW_UPLOAD_TCSGE, *PTR_MPI2_FW_UPLOAD_TCSGE, - Mpi2FWUploadTCSGE_t, *pMpi2FWUploadTCSGE_t; - -/*MPI v2.5 FWUpload Request message */ -typedef struct _MPI25_FW_UPLOAD_REQUEST { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 Reserved5; /*0x0C */ - U32 Reserved6; /*0x10 */ - U32 Reserved7; /*0x14 */ - U32 ImageOffset; /*0x18 */ - U32 ImageSize; /*0x1C */ - MPI25_SGE_IO_UNION SGL; /*0x20 */ -} MPI25_FW_UPLOAD_REQUEST, *PTR_MPI25_FW_UPLOAD_REQUEST, - Mpi25FWUploadRequest_t, *pMpi25FWUploadRequest_t; - -/*FWUpload Reply message */ -typedef struct _MPI2_FW_UPLOAD_REPLY { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 ActualImageSize; /*0x14 */ -} MPI2_FW_UPLOAD_REPLY, *PTR_MPI2_FW_UPLOAD_REPLY, - Mpi2FWUploadReply_t, *pMPi2FWUploadReply_t; - -/*FW Image Header */ -typedef struct _MPI2_FW_IMAGE_HEADER { - U32 Signature; /*0x00 */ - U32 Signature0; /*0x04 */ - U32 Signature1; /*0x08 */ - U32 Signature2; /*0x0C */ - MPI2_VERSION_UNION MPIVersion; /*0x10 */ - MPI2_VERSION_UNION FWVersion; /*0x14 */ - MPI2_VERSION_UNION NVDATAVersion; /*0x18 */ - MPI2_VERSION_UNION PackageVersion; /*0x1C */ - U16 VendorID; /*0x20 */ - U16 ProductID; /*0x22 */ - U16 ProtocolFlags; /*0x24 */ - U16 Reserved26; /*0x26 */ - U32 IOCCapabilities; /*0x28 */ - U32 ImageSize; /*0x2C */ - U32 NextImageHeaderOffset; /*0x30 */ - U32 Checksum; /*0x34 */ - U32 Reserved38; /*0x38 */ - U32 Reserved3C; /*0x3C */ - U32 Reserved40; /*0x40 */ - U32 Reserved44; /*0x44 */ - U32 Reserved48; /*0x48 */ - U32 Reserved4C; /*0x4C */ - U32 Reserved50; /*0x50 */ - U32 Reserved54; /*0x54 */ - U32 Reserved58; /*0x58 */ - U32 Reserved5C; /*0x5C */ - U32 Reserved60; /*0x60 */ - U32 FirmwareVersionNameWhat; /*0x64 */ - U8 FirmwareVersionName[32]; /*0x68 */ - U32 VendorNameWhat; /*0x88 */ - U8 VendorName[32]; /*0x8C */ - U32 PackageNameWhat; /*0x88 */ - U8 PackageName[32]; /*0x8C */ - U32 ReservedD0; /*0xD0 */ - U32 ReservedD4; /*0xD4 */ - U32 ReservedD8; /*0xD8 */ - U32 ReservedDC; /*0xDC */ - U32 ReservedE0; /*0xE0 */ - U32 ReservedE4; /*0xE4 */ - U32 ReservedE8; /*0xE8 */ - U32 ReservedEC; /*0xEC */ - U32 ReservedF0; /*0xF0 */ - U32 ReservedF4; /*0xF4 */ - U32 ReservedF8; /*0xF8 */ - U32 ReservedFC; /*0xFC */ -} MPI2_FW_IMAGE_HEADER, *PTR_MPI2_FW_IMAGE_HEADER, - Mpi2FWImageHeader_t, *pMpi2FWImageHeader_t; - -/*Signature field */ -#define MPI2_FW_HEADER_SIGNATURE_OFFSET (0x00) -#define MPI2_FW_HEADER_SIGNATURE_MASK (0xFF000000) -#define MPI2_FW_HEADER_SIGNATURE (0xEA000000) - -/*Signature0 field */ -#define MPI2_FW_HEADER_SIGNATURE0_OFFSET (0x04) -#define MPI2_FW_HEADER_SIGNATURE0 (0x5AFAA55A) - -/*Signature1 field */ -#define MPI2_FW_HEADER_SIGNATURE1_OFFSET (0x08) -#define MPI2_FW_HEADER_SIGNATURE1 (0xA55AFAA5) - -/*Signature2 field */ -#define MPI2_FW_HEADER_SIGNATURE2_OFFSET (0x0C) -#define MPI2_FW_HEADER_SIGNATURE2 (0x5AA55AFA) - -/*defines for using the ProductID field */ -#define MPI2_FW_HEADER_PID_TYPE_MASK (0xF000) -#define MPI2_FW_HEADER_PID_TYPE_SAS (0x2000) - -#define MPI2_FW_HEADER_PID_PROD_MASK (0x0F00) -#define MPI2_FW_HEADER_PID_PROD_A (0x0000) -#define MPI2_FW_HEADER_PID_PROD_TARGET_INITIATOR_SCSI (0x0200) -#define MPI2_FW_HEADER_PID_PROD_IR_SCSI (0x0700) - -#define MPI2_FW_HEADER_PID_FAMILY_MASK (0x00FF) -/*SAS ProductID Family bits */ -#define MPI2_FW_HEADER_PID_FAMILY_2108_SAS (0x0013) -#define MPI2_FW_HEADER_PID_FAMILY_2208_SAS (0x0014) -#define MPI25_FW_HEADER_PID_FAMILY_3108_SAS (0x0021) - -/*use MPI2_IOCFACTS_PROTOCOL_ defines for ProtocolFlags field */ - -/*use MPI2_IOCFACTS_CAPABILITY_ defines for IOCCapabilities field */ - -#define MPI2_FW_HEADER_IMAGESIZE_OFFSET (0x2C) -#define MPI2_FW_HEADER_NEXTIMAGE_OFFSET (0x30) -#define MPI2_FW_HEADER_VERNMHWAT_OFFSET (0x64) - -#define MPI2_FW_HEADER_WHAT_SIGNATURE (0x29232840) - -#define MPI2_FW_HEADER_SIZE (0x100) - -/*Extended Image Header */ -typedef struct _MPI2_EXT_IMAGE_HEADER { - U8 ImageType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 Checksum; /*0x04 */ - U32 ImageSize; /*0x08 */ - U32 NextImageHeaderOffset; /*0x0C */ - U32 PackageVersion; /*0x10 */ - U32 Reserved3; /*0x14 */ - U32 Reserved4; /*0x18 */ - U32 Reserved5; /*0x1C */ - U8 IdentifyString[32]; /*0x20 */ -} MPI2_EXT_IMAGE_HEADER, *PTR_MPI2_EXT_IMAGE_HEADER, - Mpi2ExtImageHeader_t, *pMpi2ExtImageHeader_t; - -/*useful offsets */ -#define MPI2_EXT_IMAGE_IMAGETYPE_OFFSET (0x00) -#define MPI2_EXT_IMAGE_IMAGESIZE_OFFSET (0x08) -#define MPI2_EXT_IMAGE_NEXTIMAGE_OFFSET (0x0C) - -#define MPI2_EXT_IMAGE_HEADER_SIZE (0x40) - -/*defines for the ImageType field */ -#define MPI2_EXT_IMAGE_TYPE_UNSPECIFIED (0x00) -#define MPI2_EXT_IMAGE_TYPE_FW (0x01) -#define MPI2_EXT_IMAGE_TYPE_NVDATA (0x03) -#define MPI2_EXT_IMAGE_TYPE_BOOTLOADER (0x04) -#define MPI2_EXT_IMAGE_TYPE_INITIALIZATION (0x05) -#define MPI2_EXT_IMAGE_TYPE_FLASH_LAYOUT (0x06) -#define MPI2_EXT_IMAGE_TYPE_SUPPORTED_DEVICES (0x07) -#define MPI2_EXT_IMAGE_TYPE_MEGARAID (0x08) -#define MPI2_EXT_IMAGE_TYPE_ENCRYPTED_HASH (0x09) -#define MPI2_EXT_IMAGE_TYPE_MIN_PRODUCT_SPECIFIC (0x80) -#define MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC (0xFF) - -#define MPI2_EXT_IMAGE_TYPE_MAX (MPI2_EXT_IMAGE_TYPE_MAX_PRODUCT_SPECIFIC) - -/*FLASH Layout Extended Image Data */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check RegionsPerLayout at runtime. - */ -#ifndef MPI2_FLASH_NUMBER_OF_REGIONS -#define MPI2_FLASH_NUMBER_OF_REGIONS (1) -#endif - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check NumberOfLayouts at runtime. - */ -#ifndef MPI2_FLASH_NUMBER_OF_LAYOUTS -#define MPI2_FLASH_NUMBER_OF_LAYOUTS (1) -#endif - -typedef struct _MPI2_FLASH_REGION { - U8 RegionType; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 RegionOffset; /*0x04 */ - U32 RegionSize; /*0x08 */ - U32 Reserved3; /*0x0C */ -} MPI2_FLASH_REGION, *PTR_MPI2_FLASH_REGION, - Mpi2FlashRegion_t, *pMpi2FlashRegion_t; - -typedef struct _MPI2_FLASH_LAYOUT { - U32 FlashSize; /*0x00 */ - U32 Reserved1; /*0x04 */ - U32 Reserved2; /*0x08 */ - U32 Reserved3; /*0x0C */ - MPI2_FLASH_REGION Region[MPI2_FLASH_NUMBER_OF_REGIONS]; /*0x10 */ -} MPI2_FLASH_LAYOUT, *PTR_MPI2_FLASH_LAYOUT, - Mpi2FlashLayout_t, *pMpi2FlashLayout_t; - -typedef struct _MPI2_FLASH_LAYOUT_DATA { - U8 ImageRevision; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 SizeOfRegion; /*0x02 */ - U8 Reserved2; /*0x03 */ - U16 NumberOfLayouts; /*0x04 */ - U16 RegionsPerLayout; /*0x06 */ - U16 MinimumSectorAlignment; /*0x08 */ - U16 Reserved3; /*0x0A */ - U32 Reserved4; /*0x0C */ - MPI2_FLASH_LAYOUT Layout[MPI2_FLASH_NUMBER_OF_LAYOUTS]; /*0x10 */ -} MPI2_FLASH_LAYOUT_DATA, *PTR_MPI2_FLASH_LAYOUT_DATA, - Mpi2FlashLayoutData_t, *pMpi2FlashLayoutData_t; - -/*defines for the RegionType field */ -#define MPI2_FLASH_REGION_UNUSED (0x00) -#define MPI2_FLASH_REGION_FIRMWARE (0x01) -#define MPI2_FLASH_REGION_BIOS (0x02) -#define MPI2_FLASH_REGION_NVDATA (0x03) -#define MPI2_FLASH_REGION_FIRMWARE_BACKUP (0x05) -#define MPI2_FLASH_REGION_MFG_INFORMATION (0x06) -#define MPI2_FLASH_REGION_CONFIG_1 (0x07) -#define MPI2_FLASH_REGION_CONFIG_2 (0x08) -#define MPI2_FLASH_REGION_MEGARAID (0x09) -#define MPI2_FLASH_REGION_INIT (0x0A) - -/*ImageRevision */ -#define MPI2_FLASH_LAYOUT_IMAGE_REVISION (0x00) - -/*Supported Devices Extended Image Data */ - -/* - *Host code (drivers, BIOS, utilities, etc.) should leave this define set to - *one and check NumberOfDevices at runtime. - */ -#ifndef MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES -#define MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES (1) -#endif - -typedef struct _MPI2_SUPPORTED_DEVICE { - U16 DeviceID; /*0x00 */ - U16 VendorID; /*0x02 */ - U16 DeviceIDMask; /*0x04 */ - U16 Reserved1; /*0x06 */ - U8 LowPCIRev; /*0x08 */ - U8 HighPCIRev; /*0x09 */ - U16 Reserved2; /*0x0A */ - U32 Reserved3; /*0x0C */ -} MPI2_SUPPORTED_DEVICE, *PTR_MPI2_SUPPORTED_DEVICE, - Mpi2SupportedDevice_t, *pMpi2SupportedDevice_t; - -typedef struct _MPI2_SUPPORTED_DEVICES_DATA { - U8 ImageRevision; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 NumberOfDevices; /*0x02 */ - U8 Reserved2; /*0x03 */ - U32 Reserved3; /*0x04 */ - MPI2_SUPPORTED_DEVICE - SupportedDevice[MPI2_SUPPORTED_DEVICES_IMAGE_NUM_DEVICES];/*0x08 */ -} MPI2_SUPPORTED_DEVICES_DATA, *PTR_MPI2_SUPPORTED_DEVICES_DATA, - Mpi2SupportedDevicesData_t, *pMpi2SupportedDevicesData_t; - -/*ImageRevision */ -#define MPI2_SUPPORTED_DEVICES_IMAGE_REVISION (0x00) - -/*Init Extended Image Data */ - -typedef struct _MPI2_INIT_IMAGE_FOOTER { - U32 BootFlags; /*0x00 */ - U32 ImageSize; /*0x04 */ - U32 Signature0; /*0x08 */ - U32 Signature1; /*0x0C */ - U32 Signature2; /*0x10 */ - U32 ResetVector; /*0x14 */ -} MPI2_INIT_IMAGE_FOOTER, *PTR_MPI2_INIT_IMAGE_FOOTER, - Mpi2InitImageFooter_t, *pMpi2InitImageFooter_t; - -/*defines for the BootFlags field */ -#define MPI2_INIT_IMAGE_BOOTFLAGS_OFFSET (0x00) - -/*defines for the ImageSize field */ -#define MPI2_INIT_IMAGE_IMAGESIZE_OFFSET (0x04) - -/*defines for the Signature0 field */ -#define MPI2_INIT_IMAGE_SIGNATURE0_OFFSET (0x08) -#define MPI2_INIT_IMAGE_SIGNATURE0 (0x5AA55AEA) - -/*defines for the Signature1 field */ -#define MPI2_INIT_IMAGE_SIGNATURE1_OFFSET (0x0C) -#define MPI2_INIT_IMAGE_SIGNATURE1 (0xA55AEAA5) - -/*defines for the Signature2 field */ -#define MPI2_INIT_IMAGE_SIGNATURE2_OFFSET (0x10) -#define MPI2_INIT_IMAGE_SIGNATURE2 (0x5AEAA55A) - -/*Signature fields as individual bytes */ -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_0 (0xEA) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_1 (0x5A) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_2 (0xA5) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_3 (0x5A) - -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_4 (0xA5) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_5 (0xEA) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_6 (0x5A) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_7 (0xA5) - -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_8 (0x5A) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_9 (0xA5) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_A (0xEA) -#define MPI2_INIT_IMAGE_SIGNATURE_BYTE_B (0x5A) - -/*defines for the ResetVector field */ -#define MPI2_INIT_IMAGE_RESETVECTOR_OFFSET (0x14) - - -/* Encrypted Hash Extended Image Data */ - -typedef struct _MPI25_ENCRYPTED_HASH_ENTRY { - U8 HashImageType; /* 0x00 */ - U8 HashAlgorithm; /* 0x01 */ - U8 EncryptionAlgorithm; /* 0x02 */ - U8 Reserved1; /* 0x03 */ - U32 Reserved2; /* 0x04 */ - U32 EncryptedHash[1]; /* 0x08 */ /* variable length */ -} MPI25_ENCRYPTED_HASH_ENTRY, *PTR_MPI25_ENCRYPTED_HASH_ENTRY, -Mpi25EncryptedHashEntry_t, *pMpi25EncryptedHashEntry_t; - -/* values for HashImageType */ -#define MPI25_HASH_IMAGE_TYPE_UNUSED (0x00) -#define MPI25_HASH_IMAGE_TYPE_FIRMWARE (0x01) -#define MPI25_HASH_IMAGE_TYPE_BIOS (0x02) - -/* values for HashAlgorithm */ -#define MPI25_HASH_ALGORITHM_UNUSED (0x00) -#define MPI25_HASH_ALGORITHM_SHA256 (0x01) - -/* values for EncryptionAlgorithm */ -#define MPI25_ENCRYPTION_ALG_UNUSED (0x00) -#define MPI25_ENCRYPTION_ALG_RSA256 (0x01) - -typedef struct _MPI25_ENCRYPTED_HASH_DATA { - U8 ImageVersion; /* 0x00 */ - U8 NumHash; /* 0x01 */ - U16 Reserved1; /* 0x02 */ - U32 Reserved2; /* 0x04 */ - MPI25_ENCRYPTED_HASH_ENTRY EncryptedHashEntry[1]; /* 0x08 */ -} MPI25_ENCRYPTED_HASH_DATA, *PTR_MPI25_ENCRYPTED_HASH_DATA, -Mpi25EncryptedHashData_t, *pMpi25EncryptedHashData_t; - - - -/**************************************************************************** -* PowerManagementControl message -****************************************************************************/ - -/*PowerManagementControl Request message */ -typedef struct _MPI2_PWR_MGMT_CONTROL_REQUEST { - U8 Feature; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U8 Parameter1; /*0x0C */ - U8 Parameter2; /*0x0D */ - U8 Parameter3; /*0x0E */ - U8 Parameter4; /*0x0F */ - U32 Reserved5; /*0x10 */ - U32 Reserved6; /*0x14 */ -} MPI2_PWR_MGMT_CONTROL_REQUEST, *PTR_MPI2_PWR_MGMT_CONTROL_REQUEST, - Mpi2PwrMgmtControlRequest_t, *pMpi2PwrMgmtControlRequest_t; - -/*defines for the Feature field */ -#define MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND (0x01) -#define MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION (0x02) -#define MPI2_PM_CONTROL_FEATURE_PCIE_LINK (0x03) /*obsolete */ -#define MPI2_PM_CONTROL_FEATURE_IOC_SPEED (0x04) -#define MPI2_PM_CONTROL_FEATURE_GLOBAL_PWR_MGMT_MODE (0x05) -#define MPI2_PM_CONTROL_FEATURE_MIN_PRODUCT_SPECIFIC (0x80) -#define MPI2_PM_CONTROL_FEATURE_MAX_PRODUCT_SPECIFIC (0xFF) - -/*parameter usage for the MPI2_PM_CONTROL_FEATURE_DA_PHY_POWER_COND Feature */ -/*Parameter1 contains a PHY number */ -/*Parameter2 indicates power condition action using these defines */ -#define MPI2_PM_CONTROL_PARAM2_PARTIAL (0x01) -#define MPI2_PM_CONTROL_PARAM2_SLUMBER (0x02) -#define MPI2_PM_CONTROL_PARAM2_EXIT_PWR_MGMT (0x03) -/*Parameter3 and Parameter4 are reserved */ - -/*parameter usage for the MPI2_PM_CONTROL_FEATURE_PORT_WIDTH_MODULATION - * Feature */ -/*Parameter1 contains SAS port width modulation group number */ -/*Parameter2 indicates IOC action using these defines */ -#define MPI2_PM_CONTROL_PARAM2_REQUEST_OWNERSHIP (0x01) -#define MPI2_PM_CONTROL_PARAM2_CHANGE_MODULATION (0x02) -#define MPI2_PM_CONTROL_PARAM2_RELINQUISH_OWNERSHIP (0x03) -/*Parameter3 indicates desired modulation level using these defines */ -#define MPI2_PM_CONTROL_PARAM3_25_PERCENT (0x00) -#define MPI2_PM_CONTROL_PARAM3_50_PERCENT (0x01) -#define MPI2_PM_CONTROL_PARAM3_75_PERCENT (0x02) -#define MPI2_PM_CONTROL_PARAM3_100_PERCENT (0x03) -/*Parameter4 is reserved */ - -/*this next set (_PCIE_LINK) is obsolete */ -/*parameter usage for the MPI2_PM_CONTROL_FEATURE_PCIE_LINK Feature */ -/*Parameter1 indicates desired PCIe link speed using these defines */ -#define MPI2_PM_CONTROL_PARAM1_PCIE_2_5_GBPS (0x00) /*obsolete */ -#define MPI2_PM_CONTROL_PARAM1_PCIE_5_0_GBPS (0x01) /*obsolete */ -#define MPI2_PM_CONTROL_PARAM1_PCIE_8_0_GBPS (0x02) /*obsolete */ -/*Parameter2 indicates desired PCIe link width using these defines */ -#define MPI2_PM_CONTROL_PARAM2_WIDTH_X1 (0x01) /*obsolete */ -#define MPI2_PM_CONTROL_PARAM2_WIDTH_X2 (0x02) /*obsolete */ -#define MPI2_PM_CONTROL_PARAM2_WIDTH_X4 (0x04) /*obsolete */ -#define MPI2_PM_CONTROL_PARAM2_WIDTH_X8 (0x08) /*obsolete */ -/*Parameter3 and Parameter4 are reserved */ - -/*parameter usage for the MPI2_PM_CONTROL_FEATURE_IOC_SPEED Feature */ -/*Parameter1 indicates desired IOC hardware clock speed using these defines */ -#define MPI2_PM_CONTROL_PARAM1_FULL_IOC_SPEED (0x01) -#define MPI2_PM_CONTROL_PARAM1_HALF_IOC_SPEED (0x02) -#define MPI2_PM_CONTROL_PARAM1_QUARTER_IOC_SPEED (0x04) -#define MPI2_PM_CONTROL_PARAM1_EIGHTH_IOC_SPEED (0x08) -/*Parameter2, Parameter3, and Parameter4 are reserved */ - -/*parameter usage for the MPI2_PM_CONTROL_FEATURE_GLOBAL_PWR_MGMT_MODE Feature*/ -/*Parameter1 indicates host action regarding global power management mode */ -#define MPI2_PM_CONTROL_PARAM1_TAKE_CONTROL (0x01) -#define MPI2_PM_CONTROL_PARAM1_CHANGE_GLOBAL_MODE (0x02) -#define MPI2_PM_CONTROL_PARAM1_RELEASE_CONTROL (0x03) -/*Parameter2 indicates the requested global power management mode */ -#define MPI2_PM_CONTROL_PARAM2_FULL_PWR_PERF (0x01) -#define MPI2_PM_CONTROL_PARAM2_REDUCED_PWR_PERF (0x08) -#define MPI2_PM_CONTROL_PARAM2_STANDBY (0x40) -/*Parameter3 and Parameter4 are reserved */ - -/*PowerManagementControl Reply message */ -typedef struct _MPI2_PWR_MGMT_CONTROL_REPLY { - U8 Feature; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_PWR_MGMT_CONTROL_REPLY, *PTR_MPI2_PWR_MGMT_CONTROL_REPLY, - Mpi2PwrMgmtControlReply_t, *pMpi2PwrMgmtControlReply_t; - -#endif diff --git a/addons/mpt3sas/src/4.4.180/mpi/mpi2_raid.h b/addons/mpt3sas/src/4.4.180/mpi/mpi2_raid.h deleted file mode 100644 index 13d93ca0..00000000 --- a/addons/mpt3sas/src/4.4.180/mpi/mpi2_raid.h +++ /dev/null @@ -1,354 +0,0 @@ -/* - * Copyright (c) 2000-2014 LSI Corporation. - * - * - * Name: mpi2_raid.h - * Title: MPI Integrated RAID messages and structures - * Creation Date: April 26, 2007 - * - * mpi2_raid.h Version: 02.00.10 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 08-31-07 02.00.01 Modifications to RAID Action request and reply, - * including the Actions and ActionData. - * 02-29-08 02.00.02 Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD. - * 05-21-08 02.00.03 Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that - * the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT - * can be sized by the build environment. - * 07-30-09 02.00.04 Added proper define for the Use Default Settings bit of - * VolumeCreationFlags and marked the old one as obsolete. - * 05-12-10 02.00.05 Added MPI2_RAID_VOL_FLAGS_OP_MDC define. - * 08-24-10 02.00.06 Added MPI2_RAID_ACTION_COMPATIBILITY_CHECK along with - * related structures and defines. - * Added product-specific range to RAID Action values. - * 11-18-11 02.00.07 Incorporating additions for MPI v2.5. - * 02-06-12 02.00.08 Added MPI2_RAID_ACTION_PHYSDISK_HIDDEN. - * 07-26-12 02.00.09 Added ElapsedSeconds field to MPI2_RAID_VOL_INDICATOR. - * Added MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID define. - * 04-17-13 02.00.10 Added MPI25_RAID_ACTION_ADATA_ALLOW_PI. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_RAID_H -#define MPI2_RAID_H - -/***************************************************************************** -* -* Integrated RAID Messages -* -*****************************************************************************/ - -/**************************************************************************** -* RAID Action messages -****************************************************************************/ - -/* ActionDataWord defines for use with MPI2_RAID_ACTION_CREATE_VOLUME action */ -#define MPI25_RAID_ACTION_ADATA_ALLOW_PI (0x80000000) - -/*ActionDataWord defines for use with MPI2_RAID_ACTION_DELETE_VOLUME action */ -#define MPI2_RAID_ACTION_ADATA_KEEP_LBA0 (0x00000000) -#define MPI2_RAID_ACTION_ADATA_ZERO_LBA0 (0x00000001) - -/*use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for - *MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */ - -/*ActionDataWord defines for use with - *MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES action */ -#define MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD (0x00000001) - -/*ActionDataWord for MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE Action */ -typedef struct _MPI2_RAID_ACTION_RATE_DATA { - U8 RateToChange; /*0x00 */ - U8 RateOrMode; /*0x01 */ - U16 DataScrubDuration; /*0x02 */ -} MPI2_RAID_ACTION_RATE_DATA, *PTR_MPI2_RAID_ACTION_RATE_DATA, - Mpi2RaidActionRateData_t, *pMpi2RaidActionRateData_t; - -#define MPI2_RAID_ACTION_SET_RATE_RESYNC (0x00) -#define MPI2_RAID_ACTION_SET_RATE_DATA_SCRUB (0x01) -#define MPI2_RAID_ACTION_SET_RATE_POWERSAVE_MODE (0x02) - -/*ActionDataWord for MPI2_RAID_ACTION_START_RAID_FUNCTION Action */ -typedef struct _MPI2_RAID_ACTION_START_RAID_FUNCTION { - U8 RAIDFunction; /*0x00 */ - U8 Flags; /*0x01 */ - U16 Reserved1; /*0x02 */ -} MPI2_RAID_ACTION_START_RAID_FUNCTION, - *PTR_MPI2_RAID_ACTION_START_RAID_FUNCTION, - Mpi2RaidActionStartRaidFunction_t, - *pMpi2RaidActionStartRaidFunction_t; - -/*defines for the RAIDFunction field */ -#define MPI2_RAID_ACTION_START_BACKGROUND_INIT (0x00) -#define MPI2_RAID_ACTION_START_ONLINE_CAP_EXPANSION (0x01) -#define MPI2_RAID_ACTION_START_CONSISTENCY_CHECK (0x02) - -/*defines for the Flags field */ -#define MPI2_RAID_ACTION_START_NEW (0x00) -#define MPI2_RAID_ACTION_START_RESUME (0x01) - -/*ActionDataWord for MPI2_RAID_ACTION_STOP_RAID_FUNCTION Action */ -typedef struct _MPI2_RAID_ACTION_STOP_RAID_FUNCTION { - U8 RAIDFunction; /*0x00 */ - U8 Flags; /*0x01 */ - U16 Reserved1; /*0x02 */ -} MPI2_RAID_ACTION_STOP_RAID_FUNCTION, - *PTR_MPI2_RAID_ACTION_STOP_RAID_FUNCTION, - Mpi2RaidActionStopRaidFunction_t, - *pMpi2RaidActionStopRaidFunction_t; - -/*defines for the RAIDFunction field */ -#define MPI2_RAID_ACTION_STOP_BACKGROUND_INIT (0x00) -#define MPI2_RAID_ACTION_STOP_ONLINE_CAP_EXPANSION (0x01) -#define MPI2_RAID_ACTION_STOP_CONSISTENCY_CHECK (0x02) - -/*defines for the Flags field */ -#define MPI2_RAID_ACTION_STOP_ABORT (0x00) -#define MPI2_RAID_ACTION_STOP_PAUSE (0x01) - -/*ActionDataWord for MPI2_RAID_ACTION_CREATE_HOT_SPARE Action */ -typedef struct _MPI2_RAID_ACTION_HOT_SPARE { - U8 HotSparePool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 DevHandle; /*0x02 */ -} MPI2_RAID_ACTION_HOT_SPARE, *PTR_MPI2_RAID_ACTION_HOT_SPARE, - Mpi2RaidActionHotSpare_t, *pMpi2RaidActionHotSpare_t; - -/*ActionDataWord for MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE Action */ -typedef struct _MPI2_RAID_ACTION_FW_UPDATE_MODE { - U8 Flags; /*0x00 */ - U8 DeviceFirmwareUpdateModeTimeout; /*0x01 */ - U16 Reserved1; /*0x02 */ -} MPI2_RAID_ACTION_FW_UPDATE_MODE, - *PTR_MPI2_RAID_ACTION_FW_UPDATE_MODE, - Mpi2RaidActionFwUpdateMode_t, - *pMpi2RaidActionFwUpdateMode_t; - -/*ActionDataWord defines for use with - *MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE action */ -#define MPI2_RAID_ACTION_ADATA_DISABLE_FW_UPDATE (0x00) -#define MPI2_RAID_ACTION_ADATA_ENABLE_FW_UPDATE (0x01) - -typedef union _MPI2_RAID_ACTION_DATA { - U32 Word; - MPI2_RAID_ACTION_RATE_DATA Rates; - MPI2_RAID_ACTION_START_RAID_FUNCTION StartRaidFunction; - MPI2_RAID_ACTION_STOP_RAID_FUNCTION StopRaidFunction; - MPI2_RAID_ACTION_HOT_SPARE HotSpare; - MPI2_RAID_ACTION_FW_UPDATE_MODE FwUpdateMode; -} MPI2_RAID_ACTION_DATA, *PTR_MPI2_RAID_ACTION_DATA, - Mpi2RaidActionData_t, *pMpi2RaidActionData_t; - -/*RAID Action Request Message */ -typedef struct _MPI2_RAID_ACTION_REQUEST { - U8 Action; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 VolDevHandle; /*0x04 */ - U8 PhysDiskNum; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved2; /*0x0A */ - U32 Reserved3; /*0x0C */ - MPI2_RAID_ACTION_DATA ActionDataWord; /*0x10 */ - MPI2_SGE_SIMPLE_UNION ActionDataSGE; /*0x14 */ -} MPI2_RAID_ACTION_REQUEST, *PTR_MPI2_RAID_ACTION_REQUEST, - Mpi2RaidActionRequest_t, *pMpi2RaidActionRequest_t; - -/*RAID Action request Action values */ - -#define MPI2_RAID_ACTION_INDICATOR_STRUCT (0x01) -#define MPI2_RAID_ACTION_CREATE_VOLUME (0x02) -#define MPI2_RAID_ACTION_DELETE_VOLUME (0x03) -#define MPI2_RAID_ACTION_DISABLE_ALL_VOLUMES (0x04) -#define MPI2_RAID_ACTION_ENABLE_ALL_VOLUMES (0x05) -#define MPI2_RAID_ACTION_PHYSDISK_OFFLINE (0x0A) -#define MPI2_RAID_ACTION_PHYSDISK_ONLINE (0x0B) -#define MPI2_RAID_ACTION_FAIL_PHYSDISK (0x0F) -#define MPI2_RAID_ACTION_ACTIVATE_VOLUME (0x11) -#define MPI2_RAID_ACTION_DEVICE_FW_UPDATE_MODE (0x15) -#define MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE (0x17) -#define MPI2_RAID_ACTION_SET_VOLUME_NAME (0x18) -#define MPI2_RAID_ACTION_SET_RAID_FUNCTION_RATE (0x19) -#define MPI2_RAID_ACTION_ENABLE_FAILED_VOLUME (0x1C) -#define MPI2_RAID_ACTION_CREATE_HOT_SPARE (0x1D) -#define MPI2_RAID_ACTION_DELETE_HOT_SPARE (0x1E) -#define MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED (0x20) -#define MPI2_RAID_ACTION_START_RAID_FUNCTION (0x21) -#define MPI2_RAID_ACTION_STOP_RAID_FUNCTION (0x22) -#define MPI2_RAID_ACTION_COMPATIBILITY_CHECK (0x23) -#define MPI2_RAID_ACTION_PHYSDISK_HIDDEN (0x24) -#define MPI2_RAID_ACTION_MIN_PRODUCT_SPECIFIC (0x80) -#define MPI2_RAID_ACTION_MAX_PRODUCT_SPECIFIC (0xFF) - -/*RAID Volume Creation Structure */ - -/* - *The following define can be customized for the targeted product. - */ -#ifndef MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS -#define MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS (1) -#endif - -typedef struct _MPI2_RAID_VOLUME_PHYSDISK { - U8 RAIDSetNum; /*0x00 */ - U8 PhysDiskMap; /*0x01 */ - U16 PhysDiskDevHandle; /*0x02 */ -} MPI2_RAID_VOLUME_PHYSDISK, *PTR_MPI2_RAID_VOLUME_PHYSDISK, - Mpi2RaidVolumePhysDisk_t, *pMpi2RaidVolumePhysDisk_t; - -/*defines for the PhysDiskMap field */ -#define MPI2_RAIDACTION_PHYSDISK_PRIMARY (0x01) -#define MPI2_RAIDACTION_PHYSDISK_SECONDARY (0x02) - -typedef struct _MPI2_RAID_VOLUME_CREATION_STRUCT { - U8 NumPhysDisks; /*0x00 */ - U8 VolumeType; /*0x01 */ - U16 Reserved1; /*0x02 */ - U32 VolumeCreationFlags; /*0x04 */ - U32 VolumeSettings; /*0x08 */ - U8 Reserved2; /*0x0C */ - U8 ResyncRate; /*0x0D */ - U16 DataScrubDuration; /*0x0E */ - U64 VolumeMaxLBA; /*0x10 */ - U32 StripeSize; /*0x18 */ - U8 Name[16]; /*0x1C */ - MPI2_RAID_VOLUME_PHYSDISK - PhysDisk[MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS]; /*0x2C */ -} MPI2_RAID_VOLUME_CREATION_STRUCT, - *PTR_MPI2_RAID_VOLUME_CREATION_STRUCT, - Mpi2RaidVolumeCreationStruct_t, - *pMpi2RaidVolumeCreationStruct_t; - -/*use MPI2_RAID_VOL_TYPE_ defines from mpi2_cnfg.h for VolumeType */ - -/*defines for the VolumeCreationFlags field */ -#define MPI2_RAID_VOL_CREATION_DEFAULT_SETTINGS (0x80000000) -#define MPI2_RAID_VOL_CREATION_BACKGROUND_INIT (0x00000004) -#define MPI2_RAID_VOL_CREATION_LOW_LEVEL_INIT (0x00000002) -#define MPI2_RAID_VOL_CREATION_MIGRATE_DATA (0x00000001) -/*The following is an obsolete define. - *It must be shifted left 24 bits in order to set the proper bit. - */ -#define MPI2_RAID_VOL_CREATION_USE_DEFAULT_SETTINGS (0x80) - -/*RAID Online Capacity Expansion Structure */ - -typedef struct _MPI2_RAID_ONLINE_CAPACITY_EXPANSION { - U32 Flags; /*0x00 */ - U16 DevHandle0; /*0x04 */ - U16 Reserved1; /*0x06 */ - U16 DevHandle1; /*0x08 */ - U16 Reserved2; /*0x0A */ -} MPI2_RAID_ONLINE_CAPACITY_EXPANSION, - *PTR_MPI2_RAID_ONLINE_CAPACITY_EXPANSION, - Mpi2RaidOnlineCapacityExpansion_t, - *pMpi2RaidOnlineCapacityExpansion_t; - -/*RAID Compatibility Input Structure */ - -typedef struct _MPI2_RAID_COMPATIBILITY_INPUT_STRUCT { - U16 SourceDevHandle; /*0x00 */ - U16 CandidateDevHandle; /*0x02 */ - U32 Flags; /*0x04 */ - U32 Reserved1; /*0x08 */ - U32 Reserved2; /*0x0C */ -} MPI2_RAID_COMPATIBILITY_INPUT_STRUCT, - *PTR_MPI2_RAID_COMPATIBILITY_INPUT_STRUCT, - Mpi2RaidCompatibilityInputStruct_t, - *pMpi2RaidCompatibilityInputStruct_t; - -/*defines for RAID Compatibility Structure Flags field */ -#define MPI2_RAID_COMPAT_SOURCE_IS_VOLUME_FLAG (0x00000002) -#define MPI2_RAID_COMPAT_REPORT_SOURCE_INFO_FLAG (0x00000001) - -/*RAID Volume Indicator Structure */ - -typedef struct _MPI2_RAID_VOL_INDICATOR { - U64 TotalBlocks; /*0x00 */ - U64 BlocksRemaining; /*0x08 */ - U32 Flags; /*0x10 */ - U32 ElapsedSeconds; /* 0x14 */ -} MPI2_RAID_VOL_INDICATOR, *PTR_MPI2_RAID_VOL_INDICATOR, - Mpi2RaidVolIndicator_t, *pMpi2RaidVolIndicator_t; - -/*defines for RAID Volume Indicator Flags field */ -#define MPI2_RAID_VOL_FLAGS_ELAPSED_SECONDS_VALID (0x80000000) -#define MPI2_RAID_VOL_FLAGS_OP_MASK (0x0000000F) -#define MPI2_RAID_VOL_FLAGS_OP_BACKGROUND_INIT (0x00000000) -#define MPI2_RAID_VOL_FLAGS_OP_ONLINE_CAP_EXPANSION (0x00000001) -#define MPI2_RAID_VOL_FLAGS_OP_CONSISTENCY_CHECK (0x00000002) -#define MPI2_RAID_VOL_FLAGS_OP_RESYNC (0x00000003) -#define MPI2_RAID_VOL_FLAGS_OP_MDC (0x00000004) - -/*RAID Compatibility Result Structure */ - -typedef struct _MPI2_RAID_COMPATIBILITY_RESULT_STRUCT { - U8 State; /*0x00 */ - U8 Reserved1; /*0x01 */ - U16 Reserved2; /*0x02 */ - U32 GenericAttributes; /*0x04 */ - U32 OEMSpecificAttributes; /*0x08 */ - U32 Reserved3; /*0x0C */ - U32 Reserved4; /*0x10 */ -} MPI2_RAID_COMPATIBILITY_RESULT_STRUCT, - *PTR_MPI2_RAID_COMPATIBILITY_RESULT_STRUCT, - Mpi2RaidCompatibilityResultStruct_t, - *pMpi2RaidCompatibilityResultStruct_t; - -/*defines for RAID Compatibility Result Structure State field */ -#define MPI2_RAID_COMPAT_STATE_COMPATIBLE (0x00) -#define MPI2_RAID_COMPAT_STATE_NOT_COMPATIBLE (0x01) - -/*defines for RAID Compatibility Result Structure GenericAttributes field */ -#define MPI2_RAID_COMPAT_GENATTRIB_4K_SECTOR (0x00000010) - -#define MPI2_RAID_COMPAT_GENATTRIB_MEDIA_MASK (0x0000000C) -#define MPI2_RAID_COMPAT_GENATTRIB_SOLID_STATE_DRIVE (0x00000008) -#define MPI2_RAID_COMPAT_GENATTRIB_HARD_DISK_DRIVE (0x00000004) - -#define MPI2_RAID_COMPAT_GENATTRIB_PROTOCOL_MASK (0x00000003) -#define MPI2_RAID_COMPAT_GENATTRIB_SAS_PROTOCOL (0x00000002) -#define MPI2_RAID_COMPAT_GENATTRIB_SATA_PROTOCOL (0x00000001) - -/*RAID Action Reply ActionData union */ -typedef union _MPI2_RAID_ACTION_REPLY_DATA { - U32 Word[6]; - MPI2_RAID_VOL_INDICATOR RaidVolumeIndicator; - U16 VolDevHandle; - U8 VolumeState; - U8 PhysDiskNum; - MPI2_RAID_COMPATIBILITY_RESULT_STRUCT RaidCompatibilityResult; -} MPI2_RAID_ACTION_REPLY_DATA, *PTR_MPI2_RAID_ACTION_REPLY_DATA, - Mpi2RaidActionReplyData_t, *pMpi2RaidActionReplyData_t; - -/*use MPI2_RAIDVOL0_SETTING_ defines from mpi2_cnfg.h for - *MPI2_RAID_ACTION_CHANGE_VOL_WRITE_CACHE action */ - -/*RAID Action Reply Message */ -typedef struct _MPI2_RAID_ACTION_REPLY { - U8 Action; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 VolDevHandle; /*0x04 */ - U8 PhysDiskNum; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved2; /*0x0A */ - U16 Reserved3; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - MPI2_RAID_ACTION_REPLY_DATA ActionData; /*0x14 */ -} MPI2_RAID_ACTION_REPLY, *PTR_MPI2_RAID_ACTION_REPLY, - Mpi2RaidActionReply_t, *pMpi2RaidActionReply_t; - -#endif diff --git a/addons/mpt3sas/src/4.4.180/mpi/mpi2_sas.h b/addons/mpt3sas/src/4.4.180/mpi/mpi2_sas.h deleted file mode 100644 index 156e3054..00000000 --- a/addons/mpt3sas/src/4.4.180/mpi/mpi2_sas.h +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright (c) 2000-2014 LSI Corporation. - * - * - * Name: mpi2_sas.h - * Title: MPI Serial Attached SCSI structures and definitions - * Creation Date: February 9, 2007 - * - * mpi2_sas.h Version: 02.00.08 - * - * NOTE: Names (typedefs, defines, etc.) beginning with an MPI25 or Mpi25 - * prefix are for use only on MPI v2.5 products, and must not be used - * with MPI v2.0 products. Unless otherwise noted, names beginning with - * MPI2 or Mpi2 are for use with both MPI v2.0 and MPI v2.5 products. - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 06-26-07 02.00.01 Added Clear All Persistent Operation to SAS IO Unit - * Control Request. - * 10-02-08 02.00.02 Added Set IOC Parameter Operation to SAS IO Unit Control - * Request. - * 10-28-09 02.00.03 Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST - * to MPI2_SGE_IO_UNION since it supports chained SGLs. - * 05-12-10 02.00.04 Modified some comments. - * 08-11-10 02.00.05 Added NCQ operations to SAS IO Unit Control. - * 11-18-11 02.00.06 Incorporating additions for MPI v2.5. - * 07-10-12 02.00.07 Added MPI2_SATA_PT_SGE_UNION for use in the SATA - * Passthrough Request message. - * 08-19-13 02.00.08 Made MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL obsolete - * for anything newer than MPI v2.0. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_SAS_H -#define MPI2_SAS_H - -/* - *Values for SASStatus. - */ -#define MPI2_SASSTATUS_SUCCESS (0x00) -#define MPI2_SASSTATUS_UNKNOWN_ERROR (0x01) -#define MPI2_SASSTATUS_INVALID_FRAME (0x02) -#define MPI2_SASSTATUS_UTC_BAD_DEST (0x03) -#define MPI2_SASSTATUS_UTC_BREAK_RECEIVED (0x04) -#define MPI2_SASSTATUS_UTC_CONNECT_RATE_NOT_SUPPORTED (0x05) -#define MPI2_SASSTATUS_UTC_PORT_LAYER_REQUEST (0x06) -#define MPI2_SASSTATUS_UTC_PROTOCOL_NOT_SUPPORTED (0x07) -#define MPI2_SASSTATUS_UTC_STP_RESOURCES_BUSY (0x08) -#define MPI2_SASSTATUS_UTC_WRONG_DESTINATION (0x09) -#define MPI2_SASSTATUS_SHORT_INFORMATION_UNIT (0x0A) -#define MPI2_SASSTATUS_LONG_INFORMATION_UNIT (0x0B) -#define MPI2_SASSTATUS_XFER_RDY_INCORRECT_WRITE_DATA (0x0C) -#define MPI2_SASSTATUS_XFER_RDY_REQUEST_OFFSET_ERROR (0x0D) -#define MPI2_SASSTATUS_XFER_RDY_NOT_EXPECTED (0x0E) -#define MPI2_SASSTATUS_DATA_INCORRECT_DATA_LENGTH (0x0F) -#define MPI2_SASSTATUS_DATA_TOO_MUCH_READ_DATA (0x10) -#define MPI2_SASSTATUS_DATA_OFFSET_ERROR (0x11) -#define MPI2_SASSTATUS_SDSF_NAK_RECEIVED (0x12) -#define MPI2_SASSTATUS_SDSF_CONNECTION_FAILED (0x13) -#define MPI2_SASSTATUS_INITIATOR_RESPONSE_TIMEOUT (0x14) - -/* - *Values for the SAS DeviceInfo field used in SAS Device Status Change Event - *data and SAS Configuration pages. - */ -#define MPI2_SAS_DEVICE_INFO_SEP (0x00004000) -#define MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE (0x00002000) -#define MPI2_SAS_DEVICE_INFO_LSI_DEVICE (0x00001000) -#define MPI2_SAS_DEVICE_INFO_DIRECT_ATTACH (0x00000800) -#define MPI2_SAS_DEVICE_INFO_SSP_TARGET (0x00000400) -#define MPI2_SAS_DEVICE_INFO_STP_TARGET (0x00000200) -#define MPI2_SAS_DEVICE_INFO_SMP_TARGET (0x00000100) -#define MPI2_SAS_DEVICE_INFO_SATA_DEVICE (0x00000080) -#define MPI2_SAS_DEVICE_INFO_SSP_INITIATOR (0x00000040) -#define MPI2_SAS_DEVICE_INFO_STP_INITIATOR (0x00000020) -#define MPI2_SAS_DEVICE_INFO_SMP_INITIATOR (0x00000010) -#define MPI2_SAS_DEVICE_INFO_SATA_HOST (0x00000008) - -#define MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE (0x00000007) -#define MPI2_SAS_DEVICE_INFO_NO_DEVICE (0x00000000) -#define MPI2_SAS_DEVICE_INFO_END_DEVICE (0x00000001) -#define MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER (0x00000002) -#define MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER (0x00000003) - -/***************************************************************************** -* -* SAS Messages -* -*****************************************************************************/ - -/**************************************************************************** -* SMP Passthrough messages -****************************************************************************/ - -/*SMP Passthrough Request Message */ -typedef struct _MPI2_SMP_PASSTHROUGH_REQUEST { - U8 PassthroughFlags; /*0x00 */ - U8 PhysicalPort; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 RequestDataLength; /*0x04 */ - U8 SGLFlags; /*0x06*//*MPI v2.0 only. Reserved on MPI v2.5*/ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U32 Reserved2; /*0x0C */ - U64 SASAddress; /*0x10 */ - U32 Reserved3; /*0x18 */ - U32 Reserved4; /*0x1C */ - MPI2_SIMPLE_SGE_UNION SGL;/*0x20 */ -} MPI2_SMP_PASSTHROUGH_REQUEST, *PTR_MPI2_SMP_PASSTHROUGH_REQUEST, - Mpi2SmpPassthroughRequest_t, *pMpi2SmpPassthroughRequest_t; - -/*values for PassthroughFlags field */ -#define MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE (0x80) - -/*MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ - -/*SMP Passthrough Reply Message */ -typedef struct _MPI2_SMP_PASSTHROUGH_REPLY { - U8 PassthroughFlags; /*0x00 */ - U8 PhysicalPort; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 ResponseDataLength; /*0x04 */ - U8 SGLFlags; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U8 Reserved2; /*0x0C */ - U8 SASStatus; /*0x0D */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 Reserved3; /*0x14 */ - U8 ResponseData[4]; /*0x18 */ -} MPI2_SMP_PASSTHROUGH_REPLY, *PTR_MPI2_SMP_PASSTHROUGH_REPLY, - Mpi2SmpPassthroughReply_t, *pMpi2SmpPassthroughReply_t; - -/*values for PassthroughFlags field */ -#define MPI2_SMP_PT_REPLY_PT_FLAGS_IMMEDIATE (0x80) - -/*values for SASStatus field are at the top of this file */ - -/**************************************************************************** -* SATA Passthrough messages -****************************************************************************/ - -typedef union _MPI2_SATA_PT_SGE_UNION { - MPI2_SGE_SIMPLE_UNION MpiSimple; /*MPI v2.0 only */ - MPI2_SGE_CHAIN_UNION MpiChain; /*MPI v2.0 only */ - MPI2_IEEE_SGE_SIMPLE_UNION IeeeSimple; - MPI2_IEEE_SGE_CHAIN_UNION IeeeChain; /*MPI v2.0 only */ - MPI25_IEEE_SGE_CHAIN64 IeeeChain64; /*MPI v2.5 only */ -} MPI2_SATA_PT_SGE_UNION, *PTR_MPI2_SATA_PT_SGE_UNION, - Mpi2SataPTSGEUnion_t, *pMpi2SataPTSGEUnion_t; - -/*SATA Passthrough Request Message */ -typedef struct _MPI2_SATA_PASSTHROUGH_REQUEST { - U16 DevHandle; /*0x00 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 PassthroughFlags; /*0x04 */ - U8 SGLFlags; /*0x06*//*MPI v2.0 only. Reserved on MPI v2.5*/ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U32 Reserved2; /*0x0C */ - U32 Reserved3; /*0x10 */ - U32 Reserved4; /*0x14 */ - U32 DataLength; /*0x18 */ - U8 CommandFIS[20]; /*0x1C */ - MPI2_SATA_PT_SGE_UNION SGL;/*0x30*//*MPI v2.5: IEEE 64 elements only*/ -} MPI2_SATA_PASSTHROUGH_REQUEST, *PTR_MPI2_SATA_PASSTHROUGH_REQUEST, - Mpi2SataPassthroughRequest_t, - *pMpi2SataPassthroughRequest_t; - -/*values for PassthroughFlags field */ -#define MPI2_SATA_PT_REQ_PT_FLAGS_EXECUTE_DIAG (0x0100) -#define MPI2_SATA_PT_REQ_PT_FLAGS_DMA (0x0020) -#define MPI2_SATA_PT_REQ_PT_FLAGS_PIO (0x0010) -#define MPI2_SATA_PT_REQ_PT_FLAGS_UNSPECIFIED_VU (0x0004) -#define MPI2_SATA_PT_REQ_PT_FLAGS_WRITE (0x0002) -#define MPI2_SATA_PT_REQ_PT_FLAGS_READ (0x0001) - -/*MPI v2.0: use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ - -/*SATA Passthrough Reply Message */ -typedef struct _MPI2_SATA_PASSTHROUGH_REPLY { - U16 DevHandle; /*0x00 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 PassthroughFlags; /*0x04 */ - U8 SGLFlags; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved1; /*0x0A */ - U8 Reserved2; /*0x0C */ - U8 SASStatus; /*0x0D */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U8 StatusFIS[20]; /*0x14 */ - U32 StatusControlRegisters; /*0x28 */ - U32 TransferCount; /*0x2C */ -} MPI2_SATA_PASSTHROUGH_REPLY, *PTR_MPI2_SATA_PASSTHROUGH_REPLY, - Mpi2SataPassthroughReply_t, *pMpi2SataPassthroughReply_t; - -/*values for SASStatus field are at the top of this file */ - -/**************************************************************************** -* SAS IO Unit Control messages -****************************************************************************/ - -/*SAS IO Unit Control Request Message */ -typedef struct _MPI2_SAS_IOUNIT_CONTROL_REQUEST { - U8 Operation; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 DevHandle; /*0x04 */ - U8 IOCParameter; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U16 Reserved4; /*0x0C */ - U8 PhyNum; /*0x0E */ - U8 PrimFlags; /*0x0F */ - U32 Primitive; /*0x10 */ - U8 LookupMethod; /*0x14 */ - U8 Reserved5; /*0x15 */ - U16 SlotNumber; /*0x16 */ - U64 LookupAddress; /*0x18 */ - U32 IOCParameterValue; /*0x20 */ - U32 Reserved7; /*0x24 */ - U32 Reserved8; /*0x28 */ -} MPI2_SAS_IOUNIT_CONTROL_REQUEST, - *PTR_MPI2_SAS_IOUNIT_CONTROL_REQUEST, - Mpi2SasIoUnitControlRequest_t, - *pMpi2SasIoUnitControlRequest_t; - -/*values for the Operation field */ -#define MPI2_SAS_OP_CLEAR_ALL_PERSISTENT (0x02) -#define MPI2_SAS_OP_PHY_LINK_RESET (0x06) -#define MPI2_SAS_OP_PHY_HARD_RESET (0x07) -#define MPI2_SAS_OP_PHY_CLEAR_ERROR_LOG (0x08) -#define MPI2_SAS_OP_SEND_PRIMITIVE (0x0A) -#define MPI2_SAS_OP_FORCE_FULL_DISCOVERY (0x0B) -#define MPI2_SAS_OP_TRANSMIT_PORT_SELECT_SIGNAL (0x0C) /* MPI v2.0 only */ -#define MPI2_SAS_OP_REMOVE_DEVICE (0x0D) -#define MPI2_SAS_OP_LOOKUP_MAPPING (0x0E) -#define MPI2_SAS_OP_SET_IOC_PARAMETER (0x0F) -#define MPI25_SAS_OP_ENABLE_FP_DEVICE (0x10) -#define MPI25_SAS_OP_DISABLE_FP_DEVICE (0x11) -#define MPI25_SAS_OP_ENABLE_FP_ALL (0x12) -#define MPI25_SAS_OP_DISABLE_FP_ALL (0x13) -#define MPI2_SAS_OP_DEV_ENABLE_NCQ (0x14) -#define MPI2_SAS_OP_DEV_DISABLE_NCQ (0x15) -#define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN (0x80) - -/*values for the PrimFlags field */ -#define MPI2_SAS_PRIMFLAGS_SINGLE (0x08) -#define MPI2_SAS_PRIMFLAGS_TRIPLE (0x02) -#define MPI2_SAS_PRIMFLAGS_REDUNDANT (0x01) - -/*values for the LookupMethod field */ -#define MPI2_SAS_LOOKUP_METHOD_SAS_ADDRESS (0x01) -#define MPI2_SAS_LOOKUP_METHOD_SAS_ENCLOSURE_SLOT (0x02) -#define MPI2_SAS_LOOKUP_METHOD_SAS_DEVICE_NAME (0x03) - -/*SAS IO Unit Control Reply Message */ -typedef struct _MPI2_SAS_IOUNIT_CONTROL_REPLY { - U8 Operation; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 DevHandle; /*0x04 */ - U8 IOCParameter; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved3; /*0x0A */ - U16 Reserved4; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_SAS_IOUNIT_CONTROL_REPLY, - *PTR_MPI2_SAS_IOUNIT_CONTROL_REPLY, - Mpi2SasIoUnitControlReply_t, *pMpi2SasIoUnitControlReply_t; - -#endif diff --git a/addons/mpt3sas/src/4.4.180/mpi/mpi2_tool.h b/addons/mpt3sas/src/4.4.180/mpi/mpi2_tool.h deleted file mode 100644 index 1629e5bc..00000000 --- a/addons/mpt3sas/src/4.4.180/mpi/mpi2_tool.h +++ /dev/null @@ -1,482 +0,0 @@ -/* - * Copyright (c) 2000-2014 LSI Corporation. - * - * - * Name: mpi2_tool.h - * Title: MPI diagnostic tool structures and definitions - * Creation Date: March 26, 2007 - * - * mpi2_tool.h Version: 02.00.12 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * 12-18-07 02.00.01 Added Diagnostic Buffer Post and Diagnostic Release - * structures and defines. - * 02-29-08 02.00.02 Modified various names to make them 32-character unique. - * 05-06-09 02.00.03 Added ISTWI Read Write Tool and Diagnostic CLI Tool. - * 07-30-09 02.00.04 Added ExtendedType field to DiagnosticBufferPost request - * and reply messages. - * Added MPI2_DIAG_BUF_TYPE_EXTENDED. - * Incremented MPI2_DIAG_BUF_TYPE_COUNT. - * 05-12-10 02.00.05 Added Diagnostic Data Upload tool. - * 08-11-10 02.00.06 Added defines that were missing for Diagnostic Buffer - * Post Request. - * 05-25-11 02.00.07 Added Flags field and related defines to - * MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST. - * 11-18-11 02.00.08 Incorporating additions for MPI v2.5. - * 07-10-12 02.00.09 Add MPI v2.5 Toolbox Diagnostic CLI Tool Request - * message. - * 07-26-12 02.00.10 Modified MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST so that - * it uses MPI Chain SGE as well as MPI Simple SGE. - * 08-19-13 02.00.11 Added MPI2_TOOLBOX_TEXT_DISPLAY_TOOL and related info. - * 01-08-14 02.00.12 Added MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_TOOL_H -#define MPI2_TOOL_H - -/***************************************************************************** -* -* Toolbox Messages -* -*****************************************************************************/ - -/*defines for the Tools */ -#define MPI2_TOOLBOX_CLEAN_TOOL (0x00) -#define MPI2_TOOLBOX_MEMORY_MOVE_TOOL (0x01) -#define MPI2_TOOLBOX_DIAG_DATA_UPLOAD_TOOL (0x02) -#define MPI2_TOOLBOX_ISTWI_READ_WRITE_TOOL (0x03) -#define MPI2_TOOLBOX_BEACON_TOOL (0x05) -#define MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL (0x06) -#define MPI2_TOOLBOX_TEXT_DISPLAY_TOOL (0x07) - -/**************************************************************************** -* Toolbox reply -****************************************************************************/ - -typedef struct _MPI2_TOOLBOX_REPLY { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_TOOLBOX_REPLY, *PTR_MPI2_TOOLBOX_REPLY, - Mpi2ToolboxReply_t, *pMpi2ToolboxReply_t; - -/**************************************************************************** -* Toolbox Clean Tool request -****************************************************************************/ - -typedef struct _MPI2_TOOLBOX_CLEAN_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 Flags; /*0x0C */ -} MPI2_TOOLBOX_CLEAN_REQUEST, *PTR_MPI2_TOOLBOX_CLEAN_REQUEST, - Mpi2ToolboxCleanRequest_t, *pMpi2ToolboxCleanRequest_t; - -/*values for the Flags field */ -#define MPI2_TOOLBOX_CLEAN_BOOT_SERVICES (0x80000000) -#define MPI2_TOOLBOX_CLEAN_PERSIST_MANUFACT_PAGES (0x40000000) -#define MPI2_TOOLBOX_CLEAN_OTHER_PERSIST_PAGES (0x20000000) -#define MPI2_TOOLBOX_CLEAN_FW_CURRENT (0x10000000) -#define MPI2_TOOLBOX_CLEAN_FW_BACKUP (0x08000000) -#define MPI2_TOOLBOX_CLEAN_BIT26_PRODUCT_SPECIFIC (0x04000000) -#define MPI2_TOOLBOX_CLEAN_MEGARAID (0x02000000) -#define MPI2_TOOLBOX_CLEAN_INITIALIZATION (0x01000000) -#define MPI2_TOOLBOX_CLEAN_FLASH (0x00000004) -#define MPI2_TOOLBOX_CLEAN_SEEPROM (0x00000002) -#define MPI2_TOOLBOX_CLEAN_NVSRAM (0x00000001) - -/**************************************************************************** -* Toolbox Memory Move request -****************************************************************************/ - -typedef struct _MPI2_TOOLBOX_MEM_MOVE_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - MPI2_SGE_SIMPLE_UNION SGL; /*0x0C */ -} MPI2_TOOLBOX_MEM_MOVE_REQUEST, *PTR_MPI2_TOOLBOX_MEM_MOVE_REQUEST, - Mpi2ToolboxMemMoveRequest_t, *pMpi2ToolboxMemMoveRequest_t; - -/**************************************************************************** -* Toolbox Diagnostic Data Upload request -****************************************************************************/ - -typedef struct _MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U8 SGLFlags; /*0x0C */ - U8 Reserved5; /*0x0D */ - U16 Reserved6; /*0x0E */ - U32 Flags; /*0x10 */ - U32 DataLength; /*0x14 */ - MPI2_SGE_SIMPLE_UNION SGL; /*0x18 */ -} MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, - *PTR_MPI2_TOOLBOX_DIAG_DATA_UPLOAD_REQUEST, - Mpi2ToolboxDiagDataUploadRequest_t, - *pMpi2ToolboxDiagDataUploadRequest_t; - -/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ - -typedef struct _MPI2_DIAG_DATA_UPLOAD_HEADER { - U32 DiagDataLength; /*00h */ - U8 FormatCode; /*04h */ - U8 Reserved1; /*05h */ - U16 Reserved2; /*06h */ -} MPI2_DIAG_DATA_UPLOAD_HEADER, *PTR_MPI2_DIAG_DATA_UPLOAD_HEADER, - Mpi2DiagDataUploadHeader_t, *pMpi2DiagDataUploadHeader_t; - -/**************************************************************************** -* Toolbox ISTWI Read Write Tool -****************************************************************************/ - -/*Toolbox ISTWI Read Write Tool request message */ -typedef struct _MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 Reserved5; /*0x0C */ - U32 Reserved6; /*0x10 */ - U8 DevIndex; /*0x14 */ - U8 Action; /*0x15 */ - U8 SGLFlags; /*0x16 */ - U8 Flags; /*0x17 */ - U16 TxDataLength; /*0x18 */ - U16 RxDataLength; /*0x1A */ - U32 Reserved8; /*0x1C */ - U32 Reserved9; /*0x20 */ - U32 Reserved10; /*0x24 */ - U32 Reserved11; /*0x28 */ - U32 Reserved12; /*0x2C */ - MPI2_SGE_SIMPLE_UNION SGL; /*0x30 */ -} MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST, - *PTR_MPI2_TOOLBOX_ISTWI_READ_WRITE_REQUEST, - Mpi2ToolboxIstwiReadWriteRequest_t, - *pMpi2ToolboxIstwiReadWriteRequest_t; - -/*values for the Action field */ -#define MPI2_TOOL_ISTWI_ACTION_READ_DATA (0x01) -#define MPI2_TOOL_ISTWI_ACTION_WRITE_DATA (0x02) -#define MPI2_TOOL_ISTWI_ACTION_SEQUENCE (0x03) -#define MPI2_TOOL_ISTWI_ACTION_RESERVE_BUS (0x10) -#define MPI2_TOOL_ISTWI_ACTION_RELEASE_BUS (0x11) -#define MPI2_TOOL_ISTWI_ACTION_RESET (0x12) - -/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ - -/*values for the Flags field */ -#define MPI2_TOOL_ISTWI_FLAG_AUTO_RESERVE_RELEASE (0x80) -#define MPI2_TOOL_ISTWI_FLAG_PAGE_ADDR_MASK (0x07) - -/*Toolbox ISTWI Read Write Tool reply message */ -typedef struct _MPI2_TOOLBOX_ISTWI_REPLY { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U8 DevIndex; /*0x14 */ - U8 Action; /*0x15 */ - U8 IstwiStatus; /*0x16 */ - U8 Reserved6; /*0x17 */ - U16 TxDataCount; /*0x18 */ - U16 RxDataCount; /*0x1A */ -} MPI2_TOOLBOX_ISTWI_REPLY, *PTR_MPI2_TOOLBOX_ISTWI_REPLY, - Mpi2ToolboxIstwiReply_t, *pMpi2ToolboxIstwiReply_t; - -/**************************************************************************** -* Toolbox Beacon Tool request -****************************************************************************/ - -typedef struct _MPI2_TOOLBOX_BEACON_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U8 Reserved5; /*0x0C */ - U8 PhysicalPort; /*0x0D */ - U8 Reserved6; /*0x0E */ - U8 Flags; /*0x0F */ -} MPI2_TOOLBOX_BEACON_REQUEST, *PTR_MPI2_TOOLBOX_BEACON_REQUEST, - Mpi2ToolboxBeaconRequest_t, *pMpi2ToolboxBeaconRequest_t; - -/*values for the Flags field */ -#define MPI2_TOOLBOX_FLAGS_BEACONMODE_OFF (0x00) -#define MPI2_TOOLBOX_FLAGS_BEACONMODE_ON (0x01) - -/**************************************************************************** -* Toolbox Diagnostic CLI Tool -****************************************************************************/ - -#define MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH (0x5C) - -/*MPI v2.0 Toolbox Diagnostic CLI Tool request message */ -typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U8 SGLFlags; /*0x0C */ - U8 Reserved5; /*0x0D */ - U16 Reserved6; /*0x0E */ - U32 DataLength; /*0x10 */ - U8 DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH];/*0x14 */ - MPI2_MPI_SGE_IO_UNION SGL; /*0x70 */ -} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, - *PTR_MPI2_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, - Mpi2ToolboxDiagnosticCliRequest_t, - *pMpi2ToolboxDiagnosticCliRequest_t; - -/*use MPI2_SGLFLAGS_ defines from mpi2.h for the SGLFlags field */ - -/*MPI v2.5 Toolbox Diagnostic CLI Tool request message */ -typedef struct _MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U32 Reserved5; /*0x0C */ - U32 DataLength; /*0x10 */ - U8 DiagnosticCliCommand[MPI2_TOOLBOX_DIAG_CLI_CMD_LENGTH];/*0x14 */ - MPI25_SGE_IO_UNION SGL; /* 0x70 */ -} MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, - *PTR_MPI25_TOOLBOX_DIAGNOSTIC_CLI_REQUEST, - Mpi25ToolboxDiagnosticCliRequest_t, - *pMpi25ToolboxDiagnosticCliRequest_t; - -/*Toolbox Diagnostic CLI Tool reply message */ -typedef struct _MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY { - U8 Tool; /*0x00 */ - U8 Reserved1; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 ReturnedDataLength; /*0x14 */ -} MPI2_TOOLBOX_DIAGNOSTIC_CLI_REPLY, - *PTR_MPI2_TOOLBOX_DIAG_CLI_REPLY, - Mpi2ToolboxDiagnosticCliReply_t, - *pMpi2ToolboxDiagnosticCliReply_t; - - -/**************************************************************************** -* Toolbox Console Text Display Tool -****************************************************************************/ - -/* Toolbox Console Text Display Tool request message */ -typedef struct _MPI2_TOOLBOX_TEXT_DISPLAY_REQUEST { - U8 Tool; /* 0x00 */ - U8 Reserved1; /* 0x01 */ - U8 ChainOffset; /* 0x02 */ - U8 Function; /* 0x03 */ - U16 Reserved2; /* 0x04 */ - U8 Reserved3; /* 0x06 */ - U8 MsgFlags; /* 0x07 */ - U8 VP_ID; /* 0x08 */ - U8 VF_ID; /* 0x09 */ - U16 Reserved4; /* 0x0A */ - U8 Console; /* 0x0C */ - U8 Flags; /* 0x0D */ - U16 Reserved6; /* 0x0E */ - U8 TextToDisplay[4]; /* 0x10 */ -} MPI2_TOOLBOX_TEXT_DISPLAY_REQUEST, -*PTR_MPI2_TOOLBOX_TEXT_DISPLAY_REQUEST, -Mpi2ToolboxTextDisplayRequest_t, -*pMpi2ToolboxTextDisplayRequest_t; - -/* defines for the Console field */ -#define MPI2_TOOLBOX_CONSOLE_TYPE_MASK (0xF0) -#define MPI2_TOOLBOX_CONSOLE_TYPE_DEFAULT (0x00) -#define MPI2_TOOLBOX_CONSOLE_TYPE_UART (0x10) -#define MPI2_TOOLBOX_CONSOLE_TYPE_ETHERNET (0x20) - -#define MPI2_TOOLBOX_CONSOLE_NUMBER_MASK (0x0F) - -/* defines for the Flags field */ -#define MPI2_TOOLBOX_CONSOLE_FLAG_TIMESTAMP (0x01) - - - -/***************************************************************************** -* -* Diagnostic Buffer Messages -* -*****************************************************************************/ - -/**************************************************************************** -* Diagnostic Buffer Post request -****************************************************************************/ - -typedef struct _MPI2_DIAG_BUFFER_POST_REQUEST { - U8 ExtendedType; /*0x00 */ - U8 BufferType; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U64 BufferAddress; /*0x0C */ - U32 BufferLength; /*0x14 */ - U32 Reserved5; /*0x18 */ - U32 Reserved6; /*0x1C */ - U32 Flags; /*0x20 */ - U32 ProductSpecific[23]; /*0x24 */ -} MPI2_DIAG_BUFFER_POST_REQUEST, *PTR_MPI2_DIAG_BUFFER_POST_REQUEST, - Mpi2DiagBufferPostRequest_t, *pMpi2DiagBufferPostRequest_t; - -/*values for the ExtendedType field */ -#define MPI2_DIAG_EXTENDED_TYPE_UTILIZATION (0x02) - -/*values for the BufferType field */ -#define MPI2_DIAG_BUF_TYPE_TRACE (0x00) -#define MPI2_DIAG_BUF_TYPE_SNAPSHOT (0x01) -#define MPI2_DIAG_BUF_TYPE_EXTENDED (0x02) -/*count of the number of buffer types */ -#define MPI2_DIAG_BUF_TYPE_COUNT (0x03) - -/*values for the Flags field */ -#define MPI2_DIAG_BUF_FLAG_RELEASE_ON_FULL (0x00000002) -#define MPI2_DIAG_BUF_FLAG_IMMEDIATE_RELEASE (0x00000001) - -/**************************************************************************** -* Diagnostic Buffer Post reply -****************************************************************************/ - -typedef struct _MPI2_DIAG_BUFFER_POST_REPLY { - U8 ExtendedType; /*0x00 */ - U8 BufferType; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ - U32 TransferLength; /*0x14 */ -} MPI2_DIAG_BUFFER_POST_REPLY, *PTR_MPI2_DIAG_BUFFER_POST_REPLY, - Mpi2DiagBufferPostReply_t, *pMpi2DiagBufferPostReply_t; - -/**************************************************************************** -* Diagnostic Release request -****************************************************************************/ - -typedef struct _MPI2_DIAG_RELEASE_REQUEST { - U8 Reserved1; /*0x00 */ - U8 BufferType; /*0x01 */ - U8 ChainOffset; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ -} MPI2_DIAG_RELEASE_REQUEST, *PTR_MPI2_DIAG_RELEASE_REQUEST, - Mpi2DiagReleaseRequest_t, *pMpi2DiagReleaseRequest_t; - -/**************************************************************************** -* Diagnostic Buffer Post reply -****************************************************************************/ - -typedef struct _MPI2_DIAG_RELEASE_REPLY { - U8 Reserved1; /*0x00 */ - U8 BufferType; /*0x01 */ - U8 MsgLength; /*0x02 */ - U8 Function; /*0x03 */ - U16 Reserved2; /*0x04 */ - U8 Reserved3; /*0x06 */ - U8 MsgFlags; /*0x07 */ - U8 VP_ID; /*0x08 */ - U8 VF_ID; /*0x09 */ - U16 Reserved4; /*0x0A */ - U16 Reserved5; /*0x0C */ - U16 IOCStatus; /*0x0E */ - U32 IOCLogInfo; /*0x10 */ -} MPI2_DIAG_RELEASE_REPLY, *PTR_MPI2_DIAG_RELEASE_REPLY, - Mpi2DiagReleaseReply_t, *pMpi2DiagReleaseReply_t; - -#endif diff --git a/addons/mpt3sas/src/4.4.180/mpi/mpi2_type.h b/addons/mpt3sas/src/4.4.180/mpi/mpi2_type.h deleted file mode 100644 index 99ab0936..00000000 --- a/addons/mpt3sas/src/4.4.180/mpi/mpi2_type.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2000-2014 LSI Corporation. - * - * - * Name: mpi2_type.h - * Title: MPI basic type definitions - * Creation Date: August 16, 2006 - * - * mpi2_type.h Version: 02.00.00 - * - * Version History - * --------------- - * - * Date Version Description - * -------- -------- ------------------------------------------------------ - * 04-30-07 02.00.00 Corresponds to Fusion-MPT MPI Specification Rev A. - * -------------------------------------------------------------------------- - */ - -#ifndef MPI2_TYPE_H -#define MPI2_TYPE_H - -/******************************************************************************* - * Define * if it hasn't already been defined. By default - * * is defined to be a near pointer. MPI2_POINTER can be defined as - * a far pointer by defining * as "far *" before this header file is - * included. - */ - -/* the basic types may have already been included by mpi_type.h */ -#ifndef MPI_TYPE_H -/***************************************************************************** -* -* Basic Types -* -*****************************************************************************/ - -typedef u8 U8; -typedef __le16 U16; -typedef __le32 U32; -typedef __le64 U64 __attribute__ ((aligned(4))); - -/***************************************************************************** -* -* Pointer Types -* -*****************************************************************************/ - -typedef U8 *PU8; -typedef U16 *PU16; -typedef U32 *PU32; -typedef U64 *PU64; - -#endif - -#endif diff --git a/addons/mpt3sas/src/4.4.180/mpt3sas_base.c b/addons/mpt3sas/src/4.4.180/mpt3sas_base.c deleted file mode 100644 index 9b536729..00000000 --- a/addons/mpt3sas/src/4.4.180/mpt3sas_base.c +++ /dev/null @@ -1,5634 +0,0 @@ -/* - * This is the Fusion MPT base driver providing common API layer interface - * for access to MPT (Message Passing Technology) firmware. - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c - * Copyright (C) 2012-2014 LSI Corporation - * Copyright (C) 2013-2014 Avago Technologies - * (mailto: MPT-FusionLinux.pdl@avagotech.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include "mpt3sas_base.h" - -static MPT_CALLBACK mpt_callbacks[MPT_MAX_CALLBACKS]; - - -#define FAULT_POLLING_INTERVAL 1000 /* in milliseconds */ - - /* maximum controller queue depth */ -#define MAX_HBA_QUEUE_DEPTH 30000 -#define MAX_CHAIN_DEPTH 100000 -static int max_queue_depth = -1; -module_param(max_queue_depth, int, 0); -MODULE_PARM_DESC(max_queue_depth, " max controller queue depth "); - -static int max_sgl_entries = -1; -module_param(max_sgl_entries, int, 0); -MODULE_PARM_DESC(max_sgl_entries, " max sg entries "); - -static int msix_disable = -1; -module_param(msix_disable, int, 0); -MODULE_PARM_DESC(msix_disable, " disable msix routed interrupts (default=0)"); - -static int max_msix_vectors = -1; -module_param(max_msix_vectors, int, 0); -MODULE_PARM_DESC(max_msix_vectors, - " max msix vectors"); - -static int mpt3sas_fwfault_debug; -MODULE_PARM_DESC(mpt3sas_fwfault_debug, - " enable detection of firmware fault and halt firmware - (default=0)"); - -static int -_base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag); - -/** - * _scsih_set_fwfault_debug - global setting of ioc->fwfault_debug. - * - */ -static int -_scsih_set_fwfault_debug(const char *val, struct kernel_param *kp) -{ - int ret = param_set_int(val, kp); - struct MPT3SAS_ADAPTER *ioc; - - if (ret) - return ret; - - /* global ioc spinlock to protect controller list on list operations */ - pr_info("setting fwfault_debug(%d)\n", mpt3sas_fwfault_debug); - spin_lock(&gioc_lock); - list_for_each_entry(ioc, &mpt3sas_ioc_list, list) - ioc->fwfault_debug = mpt3sas_fwfault_debug; - spin_unlock(&gioc_lock); - return 0; -} -module_param_call(mpt3sas_fwfault_debug, _scsih_set_fwfault_debug, - param_get_int, &mpt3sas_fwfault_debug, 0644); - -/** - * mpt3sas_remove_dead_ioc_func - kthread context to remove dead ioc - * @arg: input argument, used to derive ioc - * - * Return 0 if controller is removed from pci subsystem. - * Return -1 for other case. - */ -static int mpt3sas_remove_dead_ioc_func(void *arg) -{ - struct MPT3SAS_ADAPTER *ioc = (struct MPT3SAS_ADAPTER *)arg; - struct pci_dev *pdev; - - if ((ioc == NULL)) - return -1; - - pdev = ioc->pdev; - if ((pdev == NULL)) - return -1; - pci_stop_and_remove_bus_device_locked(pdev); - return 0; -} - -/** - * _base_fault_reset_work - workq handling ioc fault conditions - * @work: input argument, used to derive ioc - * Context: sleep. - * - * Return nothing. - */ -static void -_base_fault_reset_work(struct work_struct *work) -{ - struct MPT3SAS_ADAPTER *ioc = - container_of(work, struct MPT3SAS_ADAPTER, fault_reset_work.work); - unsigned long flags; - u32 doorbell; - int rc; - struct task_struct *p; - - - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - if (ioc->shost_recovery || ioc->pci_error_recovery) - goto rearm_timer; - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); - - doorbell = mpt3sas_base_get_iocstate(ioc, 0); - if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_MASK) { - pr_err(MPT3SAS_FMT "SAS host is non-operational !!!!\n", - ioc->name); - - /* It may be possible that EEH recovery can resolve some of - * pci bus failure issues rather removing the dead ioc function - * by considering controller is in a non-operational state. So - * here priority is given to the EEH recovery. If it doesn't - * not resolve this issue, mpt3sas driver will consider this - * controller to non-operational state and remove the dead ioc - * function. - */ - if (ioc->non_operational_loop++ < 5) { - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, - flags); - goto rearm_timer; - } - - /* - * Call _scsih_flush_pending_cmds callback so that we flush all - * pending commands back to OS. This call is required to aovid - * deadlock at block layer. Dead IOC will fail to do diag reset, - * and this call is safe since dead ioc will never return any - * command back from HW. - */ - ioc->schedule_dead_ioc_flush_running_cmds(ioc); - /* - * Set remove_host flag early since kernel thread will - * take some time to execute. - */ - ioc->remove_host = 1; - /*Remove the Dead Host */ - p = kthread_run(mpt3sas_remove_dead_ioc_func, ioc, - "%s_dead_ioc_%d", ioc->driver_name, ioc->id); - if (IS_ERR(p)) - pr_err(MPT3SAS_FMT - "%s: Running mpt3sas_dead_ioc thread failed !!!!\n", - ioc->name, __func__); - else - pr_err(MPT3SAS_FMT - "%s: Running mpt3sas_dead_ioc thread success !!!!\n", - ioc->name, __func__); - return; /* don't rearm timer */ - } - - ioc->non_operational_loop = 0; - - if ((doorbell & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) { - rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - pr_warn(MPT3SAS_FMT "%s: hard reset: %s\n", ioc->name, - __func__, (rc == 0) ? "success" : "failed"); - doorbell = mpt3sas_base_get_iocstate(ioc, 0); - if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) - mpt3sas_base_fault_info(ioc, doorbell & - MPI2_DOORBELL_DATA_MASK); - if (rc && (doorbell & MPI2_IOC_STATE_MASK) != - MPI2_IOC_STATE_OPERATIONAL) - return; /* don't rearm timer */ - } - - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - rearm_timer: - if (ioc->fault_reset_work_q) - queue_delayed_work(ioc->fault_reset_work_q, - &ioc->fault_reset_work, - msecs_to_jiffies(FAULT_POLLING_INTERVAL)); - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); -} - -/** - * mpt3sas_base_start_watchdog - start the fault_reset_work_q - * @ioc: per adapter object - * Context: sleep. - * - * Return nothing. - */ -void -mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc) -{ - unsigned long flags; - - if (ioc->fault_reset_work_q) - return; - - /* initialize fault polling */ - - INIT_DELAYED_WORK(&ioc->fault_reset_work, _base_fault_reset_work); - snprintf(ioc->fault_reset_work_q_name, - sizeof(ioc->fault_reset_work_q_name), "poll_%s%d_status", - ioc->driver_name, ioc->id); - ioc->fault_reset_work_q = - create_singlethread_workqueue(ioc->fault_reset_work_q_name); - if (!ioc->fault_reset_work_q) { - pr_err(MPT3SAS_FMT "%s: failed (line=%d)\n", - ioc->name, __func__, __LINE__); - return; - } - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - if (ioc->fault_reset_work_q) - queue_delayed_work(ioc->fault_reset_work_q, - &ioc->fault_reset_work, - msecs_to_jiffies(FAULT_POLLING_INTERVAL)); - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); -} - -/** - * mpt3sas_base_stop_watchdog - stop the fault_reset_work_q - * @ioc: per adapter object - * Context: sleep. - * - * Return nothing. - */ -void -mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc) -{ - unsigned long flags; - struct workqueue_struct *wq; - - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - wq = ioc->fault_reset_work_q; - ioc->fault_reset_work_q = NULL; - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); - if (wq) { - if (!cancel_delayed_work_sync(&ioc->fault_reset_work)) - flush_workqueue(wq); - destroy_workqueue(wq); - } -} - -/** - * mpt3sas_base_fault_info - verbose translation of firmware FAULT code - * @ioc: per adapter object - * @fault_code: fault code - * - * Return nothing. - */ -void -mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc , u16 fault_code) -{ - pr_err(MPT3SAS_FMT "fault_state(0x%04x)!\n", - ioc->name, fault_code); -} - -/** - * mpt3sas_halt_firmware - halt's mpt controller firmware - * @ioc: per adapter object - * - * For debugging timeout related issues. Writing 0xCOFFEE00 - * to the doorbell register will halt controller firmware. With - * the purpose to stop both driver and firmware, the enduser can - * obtain a ring buffer from controller UART. - */ -void -mpt3sas_halt_firmware(struct MPT3SAS_ADAPTER *ioc) -{ - u32 doorbell; - - if (!ioc->fwfault_debug) - return; - - dump_stack(); - - doorbell = readl(&ioc->chip->Doorbell); - if ((doorbell & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) - mpt3sas_base_fault_info(ioc , doorbell); - else { - writel(0xC0FFEE00, &ioc->chip->Doorbell); - pr_err(MPT3SAS_FMT "Firmware is halted due to command timeout\n", - ioc->name); - } - - if (ioc->fwfault_debug == 2) - for (;;) - ; - else - panic("panic in %s\n", __func__); -} - -/** - * _base_sas_ioc_info - verbose translation of the ioc status - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @request_hdr: request mf - * - * Return nothing. - */ -static void -_base_sas_ioc_info(struct MPT3SAS_ADAPTER *ioc, MPI2DefaultReply_t *mpi_reply, - MPI2RequestHeader_t *request_hdr) -{ - u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & - MPI2_IOCSTATUS_MASK; - char *desc = NULL; - u16 frame_sz; - char *func_str = NULL; - - /* SCSI_IO, RAID_PASS are handled from _scsih_scsi_ioc_info */ - if (request_hdr->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || - request_hdr->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || - request_hdr->Function == MPI2_FUNCTION_EVENT_NOTIFICATION) - return; - - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) - return; - - switch (ioc_status) { - -/**************************************************************************** -* Common IOCStatus values for all replies -****************************************************************************/ - - case MPI2_IOCSTATUS_INVALID_FUNCTION: - desc = "invalid function"; - break; - case MPI2_IOCSTATUS_BUSY: - desc = "busy"; - break; - case MPI2_IOCSTATUS_INVALID_SGL: - desc = "invalid sgl"; - break; - case MPI2_IOCSTATUS_INTERNAL_ERROR: - desc = "internal error"; - break; - case MPI2_IOCSTATUS_INVALID_VPID: - desc = "invalid vpid"; - break; - case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES: - desc = "insufficient resources"; - break; - case MPI2_IOCSTATUS_INVALID_FIELD: - desc = "invalid field"; - break; - case MPI2_IOCSTATUS_INVALID_STATE: - desc = "invalid state"; - break; - case MPI2_IOCSTATUS_OP_STATE_NOT_SUPPORTED: - desc = "op state not supported"; - break; - -/**************************************************************************** -* Config IOCStatus values -****************************************************************************/ - - case MPI2_IOCSTATUS_CONFIG_INVALID_ACTION: - desc = "config invalid action"; - break; - case MPI2_IOCSTATUS_CONFIG_INVALID_TYPE: - desc = "config invalid type"; - break; - case MPI2_IOCSTATUS_CONFIG_INVALID_PAGE: - desc = "config invalid page"; - break; - case MPI2_IOCSTATUS_CONFIG_INVALID_DATA: - desc = "config invalid data"; - break; - case MPI2_IOCSTATUS_CONFIG_NO_DEFAULTS: - desc = "config no defaults"; - break; - case MPI2_IOCSTATUS_CONFIG_CANT_COMMIT: - desc = "config cant commit"; - break; - -/**************************************************************************** -* SCSI IO Reply -****************************************************************************/ - - case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: - case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: - case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: - case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: - case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: - case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: - case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: - case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: - case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: - case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: - case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: - case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: - break; - -/**************************************************************************** -* For use by SCSI Initiator and SCSI Target end-to-end data protection -****************************************************************************/ - - case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: - desc = "eedp guard error"; - break; - case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: - desc = "eedp ref tag error"; - break; - case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: - desc = "eedp app tag error"; - break; - -/**************************************************************************** -* SCSI Target values -****************************************************************************/ - - case MPI2_IOCSTATUS_TARGET_INVALID_IO_INDEX: - desc = "target invalid io index"; - break; - case MPI2_IOCSTATUS_TARGET_ABORTED: - desc = "target aborted"; - break; - case MPI2_IOCSTATUS_TARGET_NO_CONN_RETRYABLE: - desc = "target no conn retryable"; - break; - case MPI2_IOCSTATUS_TARGET_NO_CONNECTION: - desc = "target no connection"; - break; - case MPI2_IOCSTATUS_TARGET_XFER_COUNT_MISMATCH: - desc = "target xfer count mismatch"; - break; - case MPI2_IOCSTATUS_TARGET_DATA_OFFSET_ERROR: - desc = "target data offset error"; - break; - case MPI2_IOCSTATUS_TARGET_TOO_MUCH_WRITE_DATA: - desc = "target too much write data"; - break; - case MPI2_IOCSTATUS_TARGET_IU_TOO_SHORT: - desc = "target iu too short"; - break; - case MPI2_IOCSTATUS_TARGET_ACK_NAK_TIMEOUT: - desc = "target ack nak timeout"; - break; - case MPI2_IOCSTATUS_TARGET_NAK_RECEIVED: - desc = "target nak received"; - break; - -/**************************************************************************** -* Serial Attached SCSI values -****************************************************************************/ - - case MPI2_IOCSTATUS_SAS_SMP_REQUEST_FAILED: - desc = "smp request failed"; - break; - case MPI2_IOCSTATUS_SAS_SMP_DATA_OVERRUN: - desc = "smp data overrun"; - break; - -/**************************************************************************** -* Diagnostic Buffer Post / Diagnostic Release values -****************************************************************************/ - - case MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED: - desc = "diagnostic released"; - break; - default: - break; - } - - if (!desc) - return; - - switch (request_hdr->Function) { - case MPI2_FUNCTION_CONFIG: - frame_sz = sizeof(Mpi2ConfigRequest_t) + ioc->sge_size; - func_str = "config_page"; - break; - case MPI2_FUNCTION_SCSI_TASK_MGMT: - frame_sz = sizeof(Mpi2SCSITaskManagementRequest_t); - func_str = "task_mgmt"; - break; - case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: - frame_sz = sizeof(Mpi2SasIoUnitControlRequest_t); - func_str = "sas_iounit_ctl"; - break; - case MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR: - frame_sz = sizeof(Mpi2SepRequest_t); - func_str = "enclosure"; - break; - case MPI2_FUNCTION_IOC_INIT: - frame_sz = sizeof(Mpi2IOCInitRequest_t); - func_str = "ioc_init"; - break; - case MPI2_FUNCTION_PORT_ENABLE: - frame_sz = sizeof(Mpi2PortEnableRequest_t); - func_str = "port_enable"; - break; - case MPI2_FUNCTION_SMP_PASSTHROUGH: - frame_sz = sizeof(Mpi2SmpPassthroughRequest_t) + ioc->sge_size; - func_str = "smp_passthru"; - break; - default: - frame_sz = 32; - func_str = "unknown"; - break; - } - - pr_warn(MPT3SAS_FMT "ioc_status: %s(0x%04x), request(0x%p),(%s)\n", - ioc->name, desc, ioc_status, request_hdr, func_str); - - _debug_dump_mf(request_hdr, frame_sz/4); -} - -/** - * _base_display_event_data - verbose translation of firmware asyn events - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * - * Return nothing. - */ -static void -_base_display_event_data(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventNotificationReply_t *mpi_reply) -{ - char *desc = NULL; - u16 event; - - if (!(ioc->logging_level & MPT_DEBUG_EVENTS)) - return; - - event = le16_to_cpu(mpi_reply->Event); - - switch (event) { - case MPI2_EVENT_LOG_DATA: - desc = "Log Data"; - break; - case MPI2_EVENT_STATE_CHANGE: - desc = "Status Change"; - break; - case MPI2_EVENT_HARD_RESET_RECEIVED: - desc = "Hard Reset Received"; - break; - case MPI2_EVENT_EVENT_CHANGE: - desc = "Event Change"; - break; - case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: - desc = "Device Status Change"; - break; - case MPI2_EVENT_IR_OPERATION_STATUS: - if (!ioc->hide_ir_msg) - desc = "IR Operation Status"; - break; - case MPI2_EVENT_SAS_DISCOVERY: - { - Mpi2EventDataSasDiscovery_t *event_data = - (Mpi2EventDataSasDiscovery_t *)mpi_reply->EventData; - pr_info(MPT3SAS_FMT "Discovery: (%s)", ioc->name, - (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ? - "start" : "stop"); - if (event_data->DiscoveryStatus) - pr_info("discovery_status(0x%08x)", - le32_to_cpu(event_data->DiscoveryStatus)); - pr_info("\n"); - return; - } - case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: - desc = "SAS Broadcast Primitive"; - break; - case MPI2_EVENT_SAS_INIT_DEVICE_STATUS_CHANGE: - desc = "SAS Init Device Status Change"; - break; - case MPI2_EVENT_SAS_INIT_TABLE_OVERFLOW: - desc = "SAS Init Table Overflow"; - break; - case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: - desc = "SAS Topology Change List"; - break; - case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: - desc = "SAS Enclosure Device Status Change"; - break; - case MPI2_EVENT_IR_VOLUME: - if (!ioc->hide_ir_msg) - desc = "IR Volume"; - break; - case MPI2_EVENT_IR_PHYSICAL_DISK: - if (!ioc->hide_ir_msg) - desc = "IR Physical Disk"; - break; - case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: - if (!ioc->hide_ir_msg) - desc = "IR Configuration Change List"; - break; - case MPI2_EVENT_LOG_ENTRY_ADDED: - if (!ioc->hide_ir_msg) - desc = "Log Entry Added"; - break; - case MPI2_EVENT_TEMP_THRESHOLD: - desc = "Temperature Threshold"; - break; - } - - if (!desc) - return; - - pr_info(MPT3SAS_FMT "%s\n", ioc->name, desc); -} - -/** - * _base_sas_log_info - verbose translation of firmware log info - * @ioc: per adapter object - * @log_info: log info - * - * Return nothing. - */ -static void -_base_sas_log_info(struct MPT3SAS_ADAPTER *ioc , u32 log_info) -{ - union loginfo_type { - u32 loginfo; - struct { - u32 subcode:16; - u32 code:8; - u32 originator:4; - u32 bus_type:4; - } dw; - }; - union loginfo_type sas_loginfo; - char *originator_str = NULL; - - sas_loginfo.loginfo = log_info; - if (sas_loginfo.dw.bus_type != 3 /*SAS*/) - return; - - /* each nexus loss loginfo */ - if (log_info == 0x31170000) - return; - - /* eat the loginfos associated with task aborts */ - if (ioc->ignore_loginfos && (log_info == 0x30050000 || log_info == - 0x31140000 || log_info == 0x31130000)) - return; - - switch (sas_loginfo.dw.originator) { - case 0: - originator_str = "IOP"; - break; - case 1: - originator_str = "PL"; - break; - case 2: - if (!ioc->hide_ir_msg) - originator_str = "IR"; - else - originator_str = "WarpDrive"; - break; - } - - pr_warn(MPT3SAS_FMT - "log_info(0x%08x): originator(%s), code(0x%02x), sub_code(0x%04x)\n", - ioc->name, log_info, - originator_str, sas_loginfo.dw.code, - sas_loginfo.dw.subcode); -} - -/** - * _base_display_reply_info - - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Return nothing. - */ -static void -_base_display_reply_info(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - u16 ioc_status; - u32 loginfo = 0; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (unlikely(!mpi_reply)) { - pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - ioc_status = le16_to_cpu(mpi_reply->IOCStatus); - - if ((ioc_status & MPI2_IOCSTATUS_MASK) && - (ioc->logging_level & MPT_DEBUG_REPLY)) { - _base_sas_ioc_info(ioc , mpi_reply, - mpt3sas_base_get_msg_frame(ioc, smid)); - } - - if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) { - loginfo = le32_to_cpu(mpi_reply->IOCLogInfo); - _base_sas_log_info(ioc, loginfo); - } - - if (ioc_status || loginfo) { - ioc_status &= MPI2_IOCSTATUS_MASK; - mpt3sas_trigger_mpi(ioc, ioc_status, loginfo); - } -} - -/** - * mpt3sas_base_done - base internal command completion routine - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_base_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (mpi_reply && mpi_reply->Function == MPI2_FUNCTION_EVENT_ACK) - return 1; - - if (ioc->base_cmds.status == MPT3_CMD_NOT_USED) - return 1; - - ioc->base_cmds.status |= MPT3_CMD_COMPLETE; - if (mpi_reply) { - ioc->base_cmds.status |= MPT3_CMD_REPLY_VALID; - memcpy(ioc->base_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); - } - ioc->base_cmds.status &= ~MPT3_CMD_PENDING; - - complete(&ioc->base_cmds.done); - return 1; -} - -/** - * _base_async_event - main callback handler for firmware asyn events - * @ioc: per adapter object - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_base_async_event(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, u32 reply) -{ - Mpi2EventNotificationReply_t *mpi_reply; - Mpi2EventAckRequest_t *ack_request; - u16 smid; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (!mpi_reply) - return 1; - if (mpi_reply->Function != MPI2_FUNCTION_EVENT_NOTIFICATION) - return 1; - - _base_display_event_data(ioc, mpi_reply); - - if (!(mpi_reply->AckRequired & MPI2_EVENT_NOTIFICATION_ACK_REQUIRED)) - goto out; - smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - goto out; - } - - ack_request = mpt3sas_base_get_msg_frame(ioc, smid); - memset(ack_request, 0, sizeof(Mpi2EventAckRequest_t)); - ack_request->Function = MPI2_FUNCTION_EVENT_ACK; - ack_request->Event = mpi_reply->Event; - ack_request->EventContext = mpi_reply->EventContext; - ack_request->VF_ID = 0; /* TODO */ - ack_request->VP_ID = 0; - mpt3sas_base_put_smid_default(ioc, smid); - - out: - - /* scsih callback handler */ - mpt3sas_scsih_event_callback(ioc, msix_index, reply); - - /* ctl callback handler */ - mpt3sas_ctl_event_callback(ioc, msix_index, reply); - - return 1; -} - -/** - * _base_get_cb_idx - obtain the callback index - * @ioc: per adapter object - * @smid: system request message index - * - * Return callback index. - */ -static u8 -_base_get_cb_idx(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - int i; - u8 cb_idx; - - if (smid < ioc->hi_priority_smid) { - i = smid - 1; - cb_idx = ioc->scsi_lookup[i].cb_idx; - } else if (smid < ioc->internal_smid) { - i = smid - ioc->hi_priority_smid; - cb_idx = ioc->hpr_lookup[i].cb_idx; - } else if (smid <= ioc->hba_queue_depth) { - i = smid - ioc->internal_smid; - cb_idx = ioc->internal_lookup[i].cb_idx; - } else - cb_idx = 0xFF; - return cb_idx; -} - -/** - * _base_mask_interrupts - disable interrupts - * @ioc: per adapter object - * - * Disabling ResetIRQ, Reply and Doorbell Interrupts - * - * Return nothing. - */ -static void -_base_mask_interrupts(struct MPT3SAS_ADAPTER *ioc) -{ - u32 him_register; - - ioc->mask_interrupts = 1; - him_register = readl(&ioc->chip->HostInterruptMask); - him_register |= MPI2_HIM_DIM + MPI2_HIM_RIM + MPI2_HIM_RESET_IRQ_MASK; - writel(him_register, &ioc->chip->HostInterruptMask); - readl(&ioc->chip->HostInterruptMask); -} - -/** - * _base_unmask_interrupts - enable interrupts - * @ioc: per adapter object - * - * Enabling only Reply Interrupts - * - * Return nothing. - */ -static void -_base_unmask_interrupts(struct MPT3SAS_ADAPTER *ioc) -{ - u32 him_register; - - him_register = readl(&ioc->chip->HostInterruptMask); - him_register &= ~MPI2_HIM_RIM; - writel(him_register, &ioc->chip->HostInterruptMask); - ioc->mask_interrupts = 0; -} - -union reply_descriptor { - u64 word; - struct { - u32 low; - u32 high; - } u; -}; - -/** - * _base_interrupt - MPT adapter (IOC) specific interrupt handler. - * @irq: irq number (not used) - * @bus_id: bus identifier cookie == pointer to MPT_ADAPTER structure - * @r: pt_regs pointer (not used) - * - * Return IRQ_HANDLE if processed, else IRQ_NONE. - */ -static irqreturn_t -_base_interrupt(int irq, void *bus_id) -{ - struct adapter_reply_queue *reply_q = bus_id; - union reply_descriptor rd; - u32 completed_cmds; - u8 request_desript_type; - u16 smid; - u8 cb_idx; - u32 reply; - u8 msix_index = reply_q->msix_index; - struct MPT3SAS_ADAPTER *ioc = reply_q->ioc; - Mpi2ReplyDescriptorsUnion_t *rpf; - u8 rc; - - if (ioc->mask_interrupts) - return IRQ_NONE; - - if (!atomic_add_unless(&reply_q->busy, 1, 1)) - return IRQ_NONE; - - rpf = &reply_q->reply_post_free[reply_q->reply_post_host_index]; - request_desript_type = rpf->Default.ReplyFlags - & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; - if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) { - atomic_dec(&reply_q->busy); - return IRQ_NONE; - } - - completed_cmds = 0; - cb_idx = 0xFF; - do { - rd.word = le64_to_cpu(rpf->Words); - if (rd.u.low == UINT_MAX || rd.u.high == UINT_MAX) - goto out; - reply = 0; - smid = le16_to_cpu(rpf->Default.DescriptorTypeDependent1); - if (request_desript_type == - MPI25_RPY_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO_SUCCESS || - request_desript_type == - MPI2_RPY_DESCRIPT_FLAGS_SCSI_IO_SUCCESS) { - cb_idx = _base_get_cb_idx(ioc, smid); - if ((likely(cb_idx < MPT_MAX_CALLBACKS)) && - (likely(mpt_callbacks[cb_idx] != NULL))) { - rc = mpt_callbacks[cb_idx](ioc, smid, - msix_index, 0); - if (rc) - mpt3sas_base_free_smid(ioc, smid); - } - } else if (request_desript_type == - MPI2_RPY_DESCRIPT_FLAGS_ADDRESS_REPLY) { - reply = le32_to_cpu( - rpf->AddressReply.ReplyFrameAddress); - if (reply > ioc->reply_dma_max_address || - reply < ioc->reply_dma_min_address) - reply = 0; - if (smid) { - cb_idx = _base_get_cb_idx(ioc, smid); - if ((likely(cb_idx < MPT_MAX_CALLBACKS)) && - (likely(mpt_callbacks[cb_idx] != NULL))) { - rc = mpt_callbacks[cb_idx](ioc, smid, - msix_index, reply); - if (reply) - _base_display_reply_info(ioc, - smid, msix_index, reply); - if (rc) - mpt3sas_base_free_smid(ioc, - smid); - } - } else { - _base_async_event(ioc, msix_index, reply); - } - - /* reply free queue handling */ - if (reply) { - ioc->reply_free_host_index = - (ioc->reply_free_host_index == - (ioc->reply_free_queue_depth - 1)) ? - 0 : ioc->reply_free_host_index + 1; - ioc->reply_free[ioc->reply_free_host_index] = - cpu_to_le32(reply); - wmb(); - writel(ioc->reply_free_host_index, - &ioc->chip->ReplyFreeHostIndex); - } - } - - rpf->Words = cpu_to_le64(ULLONG_MAX); - reply_q->reply_post_host_index = - (reply_q->reply_post_host_index == - (ioc->reply_post_queue_depth - 1)) ? 0 : - reply_q->reply_post_host_index + 1; - request_desript_type = - reply_q->reply_post_free[reply_q->reply_post_host_index]. - Default.ReplyFlags & MPI2_RPY_DESCRIPT_FLAGS_TYPE_MASK; - completed_cmds++; - if (request_desript_type == MPI2_RPY_DESCRIPT_FLAGS_UNUSED) - goto out; - if (!reply_q->reply_post_host_index) - rpf = reply_q->reply_post_free; - else - rpf++; - } while (1); - - out: - - if (!completed_cmds) { - atomic_dec(&reply_q->busy); - return IRQ_NONE; - } - - wmb(); - if (ioc->is_warpdrive) { - writel(reply_q->reply_post_host_index, - ioc->reply_post_host_index[msix_index]); - atomic_dec(&reply_q->busy); - return IRQ_HANDLED; - } - - /* Update Reply Post Host Index. - * For those HBA's which support combined reply queue feature - * 1. Get the correct Supplemental Reply Post Host Index Register. - * i.e. (msix_index / 8)th entry from Supplemental Reply Post Host - * Index Register address bank i.e replyPostRegisterIndex[], - * 2. Then update this register with new reply host index value - * in ReplyPostIndex field and the MSIxIndex field with - * msix_index value reduced to a value between 0 and 7, - * using a modulo 8 operation. Since each Supplemental Reply Post - * Host Index Register supports 8 MSI-X vectors. - * - * For other HBA's just update the Reply Post Host Index register with - * new reply host index value in ReplyPostIndex Field and msix_index - * value in MSIxIndex field. - */ - if (ioc->msix96_vector) - writel(reply_q->reply_post_host_index | ((msix_index & 7) << - MPI2_RPHI_MSIX_INDEX_SHIFT), - ioc->replyPostRegisterIndex[msix_index/8]); - else - writel(reply_q->reply_post_host_index | (msix_index << - MPI2_RPHI_MSIX_INDEX_SHIFT), - &ioc->chip->ReplyPostHostIndex); - atomic_dec(&reply_q->busy); - return IRQ_HANDLED; -} - -/** - * _base_is_controller_msix_enabled - is controller support muli-reply queues - * @ioc: per adapter object - * - */ -static inline int -_base_is_controller_msix_enabled(struct MPT3SAS_ADAPTER *ioc) -{ - return (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable; -} - -/** - * mpt3sas_base_flush_reply_queues - flushing the MSIX reply queues - * @ioc: per adapter object - * Context: ISR conext - * - * Called when a Task Management request has completed. We want - * to flush the other reply queues so all the outstanding IO has been - * completed back to OS before we process the TM completetion. - * - * Return nothing. - */ -void -mpt3sas_base_flush_reply_queues(struct MPT3SAS_ADAPTER *ioc) -{ - struct adapter_reply_queue *reply_q; - - /* If MSIX capability is turned off - * then multi-queues are not enabled - */ - if (!_base_is_controller_msix_enabled(ioc)) - return; - - list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { - if (ioc->shost_recovery) - return; - /* TMs are on msix_index == 0 */ - if (reply_q->msix_index == 0) - continue; - _base_interrupt(reply_q->vector, (void *)reply_q); - } -} - -/** - * mpt3sas_base_release_callback_handler - clear interrupt callback handler - * @cb_idx: callback index - * - * Return nothing. - */ -void -mpt3sas_base_release_callback_handler(u8 cb_idx) -{ - mpt_callbacks[cb_idx] = NULL; -} - -/** - * mpt3sas_base_register_callback_handler - obtain index for the interrupt callback handler - * @cb_func: callback function - * - * Returns cb_func. - */ -u8 -mpt3sas_base_register_callback_handler(MPT_CALLBACK cb_func) -{ - u8 cb_idx; - - for (cb_idx = MPT_MAX_CALLBACKS-1; cb_idx; cb_idx--) - if (mpt_callbacks[cb_idx] == NULL) - break; - - mpt_callbacks[cb_idx] = cb_func; - return cb_idx; -} - -/** - * mpt3sas_base_initialize_callback_handler - initialize the interrupt callback handler - * - * Return nothing. - */ -void -mpt3sas_base_initialize_callback_handler(void) -{ - u8 cb_idx; - - for (cb_idx = 0; cb_idx < MPT_MAX_CALLBACKS; cb_idx++) - mpt3sas_base_release_callback_handler(cb_idx); -} - - -/** - * _base_build_zero_len_sge - build zero length sg entry - * @ioc: per adapter object - * @paddr: virtual address for SGE - * - * Create a zero length scatter gather entry to insure the IOCs hardware has - * something to use if the target device goes brain dead and tries - * to send data even when none is asked for. - * - * Return nothing. - */ -static void -_base_build_zero_len_sge(struct MPT3SAS_ADAPTER *ioc, void *paddr) -{ - u32 flags_length = (u32)((MPI2_SGE_FLAGS_LAST_ELEMENT | - MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST | - MPI2_SGE_FLAGS_SIMPLE_ELEMENT) << - MPI2_SGE_FLAGS_SHIFT); - ioc->base_add_sg_single(paddr, flags_length, -1); -} - -/** - * _base_add_sg_single_32 - Place a simple 32 bit SGE at address pAddr. - * @paddr: virtual address for SGE - * @flags_length: SGE flags and data transfer length - * @dma_addr: Physical address - * - * Return nothing. - */ -static void -_base_add_sg_single_32(void *paddr, u32 flags_length, dma_addr_t dma_addr) -{ - Mpi2SGESimple32_t *sgel = paddr; - - flags_length |= (MPI2_SGE_FLAGS_32_BIT_ADDRESSING | - MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT; - sgel->FlagsLength = cpu_to_le32(flags_length); - sgel->Address = cpu_to_le32(dma_addr); -} - - -/** - * _base_add_sg_single_64 - Place a simple 64 bit SGE at address pAddr. - * @paddr: virtual address for SGE - * @flags_length: SGE flags and data transfer length - * @dma_addr: Physical address - * - * Return nothing. - */ -static void -_base_add_sg_single_64(void *paddr, u32 flags_length, dma_addr_t dma_addr) -{ - Mpi2SGESimple64_t *sgel = paddr; - - flags_length |= (MPI2_SGE_FLAGS_64_BIT_ADDRESSING | - MPI2_SGE_FLAGS_SYSTEM_ADDRESS) << MPI2_SGE_FLAGS_SHIFT; - sgel->FlagsLength = cpu_to_le32(flags_length); - sgel->Address = cpu_to_le64(dma_addr); -} - -/** - * _base_get_chain_buffer_tracker - obtain chain tracker - * @ioc: per adapter object - * @smid: smid associated to an IO request - * - * Returns chain tracker(from ioc->free_chain_list) - */ -static struct chain_tracker * -_base_get_chain_buffer_tracker(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - struct chain_tracker *chain_req; - unsigned long flags; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - if (list_empty(&ioc->free_chain_list)) { - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "chain buffers not available\n", ioc->name)); - return NULL; - } - chain_req = list_entry(ioc->free_chain_list.next, - struct chain_tracker, tracker_list); - list_del_init(&chain_req->tracker_list); - list_add_tail(&chain_req->tracker_list, - &ioc->scsi_lookup[smid - 1].chain_list); - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return chain_req; -} - - -/** - * _base_build_sg - build generic sg - * @ioc: per adapter object - * @psge: virtual address for SGE - * @data_out_dma: physical address for WRITES - * @data_out_sz: data xfer size for WRITES - * @data_in_dma: physical address for READS - * @data_in_sz: data xfer size for READS - * - * Return nothing. - */ -static void -_base_build_sg(struct MPT3SAS_ADAPTER *ioc, void *psge, - dma_addr_t data_out_dma, size_t data_out_sz, dma_addr_t data_in_dma, - size_t data_in_sz) -{ - u32 sgl_flags; - - if (!data_out_sz && !data_in_sz) { - _base_build_zero_len_sge(ioc, psge); - return; - } - - if (data_out_sz && data_in_sz) { - /* WRITE sgel first */ - sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); - sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - ioc->base_add_sg_single(psge, sgl_flags | - data_out_sz, data_out_dma); - - /* incr sgel */ - psge += ioc->sge_size; - - /* READ sgel last */ - sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | - MPI2_SGE_FLAGS_END_OF_LIST); - sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - ioc->base_add_sg_single(psge, sgl_flags | - data_in_sz, data_in_dma); - } else if (data_out_sz) /* WRITE */ { - sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | - MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC); - sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - ioc->base_add_sg_single(psge, sgl_flags | - data_out_sz, data_out_dma); - } else if (data_in_sz) /* READ */ { - sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | - MPI2_SGE_FLAGS_END_OF_LIST); - sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - ioc->base_add_sg_single(psge, sgl_flags | - data_in_sz, data_in_dma); - } -} - -/* IEEE format sgls */ - -/** - * _base_add_sg_single_ieee - add sg element for IEEE format - * @paddr: virtual address for SGE - * @flags: SGE flags - * @chain_offset: number of 128 byte elements from start of segment - * @length: data transfer length - * @dma_addr: Physical address - * - * Return nothing. - */ -static void -_base_add_sg_single_ieee(void *paddr, u8 flags, u8 chain_offset, u32 length, - dma_addr_t dma_addr) -{ - Mpi25IeeeSgeChain64_t *sgel = paddr; - - sgel->Flags = flags; - sgel->NextChainOffset = chain_offset; - sgel->Length = cpu_to_le32(length); - sgel->Address = cpu_to_le64(dma_addr); -} - -/** - * _base_build_zero_len_sge_ieee - build zero length sg entry for IEEE format - * @ioc: per adapter object - * @paddr: virtual address for SGE - * - * Create a zero length scatter gather entry to insure the IOCs hardware has - * something to use if the target device goes brain dead and tries - * to send data even when none is asked for. - * - * Return nothing. - */ -static void -_base_build_zero_len_sge_ieee(struct MPT3SAS_ADAPTER *ioc, void *paddr) -{ - u8 sgl_flags = (MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR | - MPI25_IEEE_SGE_FLAGS_END_OF_LIST); - _base_add_sg_single_ieee(paddr, sgl_flags, 0, 0, -1); -} - -/** - * _base_build_sg_scmd - main sg creation routine - * @ioc: per adapter object - * @scmd: scsi command - * @smid: system request message index - * Context: none. - * - * The main routine that builds scatter gather table from a given - * scsi request sent via the .queuecommand main handler. - * - * Returns 0 success, anything else error - */ -static int -_base_build_sg_scmd(struct MPT3SAS_ADAPTER *ioc, - struct scsi_cmnd *scmd, u16 smid) -{ - Mpi2SCSIIORequest_t *mpi_request; - dma_addr_t chain_dma; - struct scatterlist *sg_scmd; - void *sg_local, *chain; - u32 chain_offset; - u32 chain_length; - u32 chain_flags; - int sges_left; - u32 sges_in_segment; - u32 sgl_flags; - u32 sgl_flags_last_element; - u32 sgl_flags_end_buffer; - struct chain_tracker *chain_req; - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - - /* init scatter gather flags */ - sgl_flags = MPI2_SGE_FLAGS_SIMPLE_ELEMENT; - if (scmd->sc_data_direction == DMA_TO_DEVICE) - sgl_flags |= MPI2_SGE_FLAGS_HOST_TO_IOC; - sgl_flags_last_element = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT) - << MPI2_SGE_FLAGS_SHIFT; - sgl_flags_end_buffer = (sgl_flags | MPI2_SGE_FLAGS_LAST_ELEMENT | - MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_END_OF_LIST) - << MPI2_SGE_FLAGS_SHIFT; - sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - - sg_scmd = scsi_sglist(scmd); - sges_left = scsi_dma_map(scmd); - if (sges_left < 0) { - sdev_printk(KERN_ERR, scmd->device, - "pci_map_sg failed: request for %d bytes!\n", - scsi_bufflen(scmd)); - return -ENOMEM; - } - - sg_local = &mpi_request->SGL; - sges_in_segment = ioc->max_sges_in_main_message; - if (sges_left <= sges_in_segment) - goto fill_in_last_segment; - - mpi_request->ChainOffset = (offsetof(Mpi2SCSIIORequest_t, SGL) + - (sges_in_segment * ioc->sge_size))/4; - - /* fill in main message segment when there is a chain following */ - while (sges_in_segment) { - if (sges_in_segment == 1) - ioc->base_add_sg_single(sg_local, - sgl_flags_last_element | sg_dma_len(sg_scmd), - sg_dma_address(sg_scmd)); - else - ioc->base_add_sg_single(sg_local, sgl_flags | - sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); - sg_scmd = sg_next(sg_scmd); - sg_local += ioc->sge_size; - sges_left--; - sges_in_segment--; - } - - /* initializing the chain flags and pointers */ - chain_flags = MPI2_SGE_FLAGS_CHAIN_ELEMENT << MPI2_SGE_FLAGS_SHIFT; - chain_req = _base_get_chain_buffer_tracker(ioc, smid); - if (!chain_req) - return -1; - chain = chain_req->chain_buffer; - chain_dma = chain_req->chain_buffer_dma; - do { - sges_in_segment = (sges_left <= - ioc->max_sges_in_chain_message) ? sges_left : - ioc->max_sges_in_chain_message; - chain_offset = (sges_left == sges_in_segment) ? - 0 : (sges_in_segment * ioc->sge_size)/4; - chain_length = sges_in_segment * ioc->sge_size; - if (chain_offset) { - chain_offset = chain_offset << - MPI2_SGE_CHAIN_OFFSET_SHIFT; - chain_length += ioc->sge_size; - } - ioc->base_add_sg_single(sg_local, chain_flags | chain_offset | - chain_length, chain_dma); - sg_local = chain; - if (!chain_offset) - goto fill_in_last_segment; - - /* fill in chain segments */ - while (sges_in_segment) { - if (sges_in_segment == 1) - ioc->base_add_sg_single(sg_local, - sgl_flags_last_element | - sg_dma_len(sg_scmd), - sg_dma_address(sg_scmd)); - else - ioc->base_add_sg_single(sg_local, sgl_flags | - sg_dma_len(sg_scmd), - sg_dma_address(sg_scmd)); - sg_scmd = sg_next(sg_scmd); - sg_local += ioc->sge_size; - sges_left--; - sges_in_segment--; - } - - chain_req = _base_get_chain_buffer_tracker(ioc, smid); - if (!chain_req) - return -1; - chain = chain_req->chain_buffer; - chain_dma = chain_req->chain_buffer_dma; - } while (1); - - - fill_in_last_segment: - - /* fill the last segment */ - while (sges_left) { - if (sges_left == 1) - ioc->base_add_sg_single(sg_local, sgl_flags_end_buffer | - sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); - else - ioc->base_add_sg_single(sg_local, sgl_flags | - sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); - sg_scmd = sg_next(sg_scmd); - sg_local += ioc->sge_size; - sges_left--; - } - - return 0; -} - -/** - * _base_build_sg_scmd_ieee - main sg creation routine for IEEE format - * @ioc: per adapter object - * @scmd: scsi command - * @smid: system request message index - * Context: none. - * - * The main routine that builds scatter gather table from a given - * scsi request sent via the .queuecommand main handler. - * - * Returns 0 success, anything else error - */ -static int -_base_build_sg_scmd_ieee(struct MPT3SAS_ADAPTER *ioc, - struct scsi_cmnd *scmd, u16 smid) -{ - Mpi2SCSIIORequest_t *mpi_request; - dma_addr_t chain_dma; - struct scatterlist *sg_scmd; - void *sg_local, *chain; - u32 chain_offset; - u32 chain_length; - int sges_left; - u32 sges_in_segment; - u8 simple_sgl_flags; - u8 simple_sgl_flags_last; - u8 chain_sgl_flags; - struct chain_tracker *chain_req; - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - - /* init scatter gather flags */ - simple_sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR; - simple_sgl_flags_last = simple_sgl_flags | - MPI25_IEEE_SGE_FLAGS_END_OF_LIST; - chain_sgl_flags = MPI2_IEEE_SGE_FLAGS_CHAIN_ELEMENT | - MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR; - - sg_scmd = scsi_sglist(scmd); - sges_left = scsi_dma_map(scmd); - if (sges_left < 0) { - sdev_printk(KERN_ERR, scmd->device, - "pci_map_sg failed: request for %d bytes!\n", - scsi_bufflen(scmd)); - return -ENOMEM; - } - - sg_local = &mpi_request->SGL; - sges_in_segment = (ioc->request_sz - - offsetof(Mpi2SCSIIORequest_t, SGL))/ioc->sge_size_ieee; - if (sges_left <= sges_in_segment) - goto fill_in_last_segment; - - mpi_request->ChainOffset = (sges_in_segment - 1 /* chain element */) + - (offsetof(Mpi2SCSIIORequest_t, SGL)/ioc->sge_size_ieee); - - /* fill in main message segment when there is a chain following */ - while (sges_in_segment > 1) { - _base_add_sg_single_ieee(sg_local, simple_sgl_flags, 0, - sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); - sg_scmd = sg_next(sg_scmd); - sg_local += ioc->sge_size_ieee; - sges_left--; - sges_in_segment--; - } - - /* initializing the pointers */ - chain_req = _base_get_chain_buffer_tracker(ioc, smid); - if (!chain_req) - return -1; - chain = chain_req->chain_buffer; - chain_dma = chain_req->chain_buffer_dma; - do { - sges_in_segment = (sges_left <= - ioc->max_sges_in_chain_message) ? sges_left : - ioc->max_sges_in_chain_message; - chain_offset = (sges_left == sges_in_segment) ? - 0 : sges_in_segment; - chain_length = sges_in_segment * ioc->sge_size_ieee; - if (chain_offset) - chain_length += ioc->sge_size_ieee; - _base_add_sg_single_ieee(sg_local, chain_sgl_flags, - chain_offset, chain_length, chain_dma); - - sg_local = chain; - if (!chain_offset) - goto fill_in_last_segment; - - /* fill in chain segments */ - while (sges_in_segment) { - _base_add_sg_single_ieee(sg_local, simple_sgl_flags, 0, - sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); - sg_scmd = sg_next(sg_scmd); - sg_local += ioc->sge_size_ieee; - sges_left--; - sges_in_segment--; - } - - chain_req = _base_get_chain_buffer_tracker(ioc, smid); - if (!chain_req) - return -1; - chain = chain_req->chain_buffer; - chain_dma = chain_req->chain_buffer_dma; - } while (1); - - - fill_in_last_segment: - - /* fill the last segment */ - while (sges_left > 0) { - if (sges_left == 1) - _base_add_sg_single_ieee(sg_local, - simple_sgl_flags_last, 0, sg_dma_len(sg_scmd), - sg_dma_address(sg_scmd)); - else - _base_add_sg_single_ieee(sg_local, simple_sgl_flags, 0, - sg_dma_len(sg_scmd), sg_dma_address(sg_scmd)); - sg_scmd = sg_next(sg_scmd); - sg_local += ioc->sge_size_ieee; - sges_left--; - } - - return 0; -} - -/** - * _base_build_sg_ieee - build generic sg for IEEE format - * @ioc: per adapter object - * @psge: virtual address for SGE - * @data_out_dma: physical address for WRITES - * @data_out_sz: data xfer size for WRITES - * @data_in_dma: physical address for READS - * @data_in_sz: data xfer size for READS - * - * Return nothing. - */ -static void -_base_build_sg_ieee(struct MPT3SAS_ADAPTER *ioc, void *psge, - dma_addr_t data_out_dma, size_t data_out_sz, dma_addr_t data_in_dma, - size_t data_in_sz) -{ - u8 sgl_flags; - - if (!data_out_sz && !data_in_sz) { - _base_build_zero_len_sge_ieee(ioc, psge); - return; - } - - if (data_out_sz && data_in_sz) { - /* WRITE sgel first */ - sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR; - _base_add_sg_single_ieee(psge, sgl_flags, 0, data_out_sz, - data_out_dma); - - /* incr sgel */ - psge += ioc->sge_size_ieee; - - /* READ sgel last */ - sgl_flags |= MPI25_IEEE_SGE_FLAGS_END_OF_LIST; - _base_add_sg_single_ieee(psge, sgl_flags, 0, data_in_sz, - data_in_dma); - } else if (data_out_sz) /* WRITE */ { - sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | - MPI25_IEEE_SGE_FLAGS_END_OF_LIST | - MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR; - _base_add_sg_single_ieee(psge, sgl_flags, 0, data_out_sz, - data_out_dma); - } else if (data_in_sz) /* READ */ { - sgl_flags = MPI2_IEEE_SGE_FLAGS_SIMPLE_ELEMENT | - MPI25_IEEE_SGE_FLAGS_END_OF_LIST | - MPI2_IEEE_SGE_FLAGS_SYSTEM_ADDR; - _base_add_sg_single_ieee(psge, sgl_flags, 0, data_in_sz, - data_in_dma); - } -} - -#define convert_to_kb(x) ((x) << (PAGE_SHIFT - 10)) - -/** - * _base_config_dma_addressing - set dma addressing - * @ioc: per adapter object - * @pdev: PCI device struct - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_config_dma_addressing(struct MPT3SAS_ADAPTER *ioc, struct pci_dev *pdev) -{ - struct sysinfo s; - u64 consistent_dma_mask; - - if (ioc->dma_mask) - consistent_dma_mask = DMA_BIT_MASK(64); - else - consistent_dma_mask = DMA_BIT_MASK(32); - - if (sizeof(dma_addr_t) > 4) { - const uint64_t required_mask = - dma_get_required_mask(&pdev->dev); - if ((required_mask > DMA_BIT_MASK(32)) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && - !pci_set_consistent_dma_mask(pdev, consistent_dma_mask)) { - ioc->base_add_sg_single = &_base_add_sg_single_64; - ioc->sge_size = sizeof(Mpi2SGESimple64_t); - ioc->dma_mask = 64; - goto out; - } - } - - if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(32)) - && !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) { - ioc->base_add_sg_single = &_base_add_sg_single_32; - ioc->sge_size = sizeof(Mpi2SGESimple32_t); - ioc->dma_mask = 32; - } else - return -ENODEV; - - out: - si_meminfo(&s); - pr_info(MPT3SAS_FMT - "%d BIT PCI BUS DMA ADDRESSING SUPPORTED, total mem (%ld kB)\n", - ioc->name, ioc->dma_mask, convert_to_kb(s.totalram)); - - return 0; -} - -static int -_base_change_consistent_dma_mask(struct MPT3SAS_ADAPTER *ioc, - struct pci_dev *pdev) -{ - if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { - if (pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32))) - return -ENODEV; - } - return 0; -} - -/** - * _base_check_enable_msix - checks MSIX capabable. - * @ioc: per adapter object - * - * Check to see if card is capable of MSIX, and set number - * of available msix vectors - */ -static int -_base_check_enable_msix(struct MPT3SAS_ADAPTER *ioc) -{ - int base; - u16 message_control; - - /* Check whether controller SAS2008 B0 controller, - * if it is SAS2008 B0 controller use IO-APIC instead of MSIX - */ - if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 && - ioc->pdev->revision == SAS2_PCI_DEVICE_B0_REVISION) { - return -EINVAL; - } - - base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX); - if (!base) { - dfailprintk(ioc, pr_info(MPT3SAS_FMT "msix not supported\n", - ioc->name)); - return -EINVAL; - } - - /* get msix vector count */ - /* NUMA_IO not supported for older controllers */ - if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2004 || - ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 || - ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_1 || - ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_2 || - ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2108_3 || - ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_1 || - ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2116_2) - ioc->msix_vector_count = 1; - else { - pci_read_config_word(ioc->pdev, base + 2, &message_control); - ioc->msix_vector_count = (message_control & 0x3FF) + 1; - } - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "msix is supported, vector_count(%d)\n", - ioc->name, ioc->msix_vector_count)); - return 0; -} - -/** - * _base_free_irq - free irq - * @ioc: per adapter object - * - * Freeing respective reply_queue from the list. - */ -static void -_base_free_irq(struct MPT3SAS_ADAPTER *ioc) -{ - struct adapter_reply_queue *reply_q, *next; - - if (list_empty(&ioc->reply_queue_list)) - return; - - list_for_each_entry_safe(reply_q, next, &ioc->reply_queue_list, list) { - list_del(&reply_q->list); - irq_set_affinity_hint(reply_q->vector, NULL); - free_cpumask_var(reply_q->affinity_hint); - synchronize_irq(reply_q->vector); - free_irq(reply_q->vector, reply_q); - kfree(reply_q); - } -} - -/** - * _base_request_irq - request irq - * @ioc: per adapter object - * @index: msix index into vector table - * @vector: irq vector - * - * Inserting respective reply_queue into the list. - */ -static int -_base_request_irq(struct MPT3SAS_ADAPTER *ioc, u8 index, u32 vector) -{ - struct adapter_reply_queue *reply_q; - int r; - - reply_q = kzalloc(sizeof(struct adapter_reply_queue), GFP_KERNEL); - if (!reply_q) { - pr_err(MPT3SAS_FMT "unable to allocate memory %d!\n", - ioc->name, (int)sizeof(struct adapter_reply_queue)); - return -ENOMEM; - } - reply_q->ioc = ioc; - reply_q->msix_index = index; - reply_q->vector = vector; - - if (!alloc_cpumask_var(&reply_q->affinity_hint, GFP_KERNEL)) - return -ENOMEM; - cpumask_clear(reply_q->affinity_hint); - - atomic_set(&reply_q->busy, 0); - if (ioc->msix_enable) - snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d-msix%d", - ioc->driver_name, ioc->id, index); - else - snprintf(reply_q->name, MPT_NAME_LENGTH, "%s%d", - ioc->driver_name, ioc->id); - r = request_irq(vector, _base_interrupt, IRQF_SHARED, reply_q->name, - reply_q); - if (r) { - pr_err(MPT3SAS_FMT "unable to allocate interrupt %d!\n", - reply_q->name, vector); - kfree(reply_q); - return -EBUSY; - } - - INIT_LIST_HEAD(&reply_q->list); - list_add_tail(&reply_q->list, &ioc->reply_queue_list); - return 0; -} - -/** - * _base_assign_reply_queues - assigning msix index for each cpu - * @ioc: per adapter object - * - * The enduser would need to set the affinity via /proc/irq/#/smp_affinity - * - * It would nice if we could call irq_set_affinity, however it is not - * an exported symbol - */ -static void -_base_assign_reply_queues(struct MPT3SAS_ADAPTER *ioc) -{ - unsigned int cpu, nr_cpus, nr_msix, index = 0; - struct adapter_reply_queue *reply_q; - - if (!_base_is_controller_msix_enabled(ioc)) - return; - - memset(ioc->cpu_msix_table, 0, ioc->cpu_msix_table_sz); - - nr_cpus = num_online_cpus(); - nr_msix = ioc->reply_queue_count = min(ioc->reply_queue_count, - ioc->facts.MaxMSIxVectors); - if (!nr_msix) - return; - - cpu = cpumask_first(cpu_online_mask); - - list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { - - unsigned int i, group = nr_cpus / nr_msix; - - if (cpu >= nr_cpus) - break; - - if (index < nr_cpus % nr_msix) - group++; - - for (i = 0 ; i < group ; i++) { - ioc->cpu_msix_table[cpu] = index; - cpumask_or(reply_q->affinity_hint, - reply_q->affinity_hint, get_cpu_mask(cpu)); - cpu = cpumask_next(cpu, cpu_online_mask); - } - - if (irq_set_affinity_hint(reply_q->vector, - reply_q->affinity_hint)) - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "error setting affinity hint for irq vector %d\n", - ioc->name, reply_q->vector)); - index++; - } -} - -/** - * _base_disable_msix - disables msix - * @ioc: per adapter object - * - */ -static void -_base_disable_msix(struct MPT3SAS_ADAPTER *ioc) -{ - if (!ioc->msix_enable) - return; - pci_disable_msix(ioc->pdev); - ioc->msix_enable = 0; -} - -/** - * _base_enable_msix - enables msix, failback to io_apic - * @ioc: per adapter object - * - */ -static int -_base_enable_msix(struct MPT3SAS_ADAPTER *ioc) -{ - struct msix_entry *entries, *a; - int r; - int i; - u8 try_msix = 0; - - if (msix_disable == -1 || msix_disable == 0) - try_msix = 1; - - if (!try_msix) - goto try_ioapic; - - if (_base_check_enable_msix(ioc) != 0) - goto try_ioapic; - - ioc->reply_queue_count = min_t(int, ioc->cpu_count, - ioc->msix_vector_count); - - printk(MPT3SAS_FMT "MSI-X vectors supported: %d, no of cores" - ": %d, max_msix_vectors: %d\n", ioc->name, ioc->msix_vector_count, - ioc->cpu_count, max_msix_vectors); - - if (!ioc->rdpq_array_enable && max_msix_vectors == -1) - max_msix_vectors = 8; - - if (max_msix_vectors > 0) { - ioc->reply_queue_count = min_t(int, max_msix_vectors, - ioc->reply_queue_count); - ioc->msix_vector_count = ioc->reply_queue_count; - } else if (max_msix_vectors == 0) - goto try_ioapic; - - entries = kcalloc(ioc->reply_queue_count, sizeof(struct msix_entry), - GFP_KERNEL); - if (!entries) { - dfailprintk(ioc, pr_info(MPT3SAS_FMT - "kcalloc failed @ at %s:%d/%s() !!!\n", - ioc->name, __FILE__, __LINE__, __func__)); - goto try_ioapic; - } - - for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) - a->entry = i; - - r = pci_enable_msix_exact(ioc->pdev, entries, ioc->reply_queue_count); - if (r) { - dfailprintk(ioc, pr_info(MPT3SAS_FMT - "pci_enable_msix_exact failed (r=%d) !!!\n", - ioc->name, r)); - kfree(entries); - goto try_ioapic; - } - - ioc->msix_enable = 1; - for (i = 0, a = entries; i < ioc->reply_queue_count; i++, a++) { - r = _base_request_irq(ioc, i, a->vector); - if (r) { - _base_free_irq(ioc); - _base_disable_msix(ioc); - kfree(entries); - goto try_ioapic; - } - } - - kfree(entries); - return 0; - -/* failback to io_apic interrupt routing */ - try_ioapic: - - ioc->reply_queue_count = 1; - r = _base_request_irq(ioc, 0, ioc->pdev->irq); - - return r; -} - -/** - * mpt3sas_base_unmap_resources - free controller resources - * @ioc: per adapter object - */ -void -mpt3sas_base_unmap_resources(struct MPT3SAS_ADAPTER *ioc) -{ - struct pci_dev *pdev = ioc->pdev; - - dexitprintk(ioc, printk(MPT3SAS_FMT "%s\n", - ioc->name, __func__)); - - _base_free_irq(ioc); - _base_disable_msix(ioc); - - if (ioc->msix96_vector) { - kfree(ioc->replyPostRegisterIndex); - ioc->replyPostRegisterIndex = NULL; - } - - if (ioc->chip_phys) { - iounmap(ioc->chip); - ioc->chip_phys = 0; - } - - if (pci_is_enabled(pdev)) { - pci_release_selected_regions(ioc->pdev, ioc->bars); - pci_disable_pcie_error_reporting(pdev); - pci_disable_device(pdev); - } -} - -/** - * mpt3sas_base_map_resources - map in controller resources (io/irq/memap) - * @ioc: per adapter object - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc) -{ - struct pci_dev *pdev = ioc->pdev; - u32 memap_sz; - u32 pio_sz; - int i, r = 0; - u64 pio_chip = 0; - u64 chip_phys = 0; - struct adapter_reply_queue *reply_q; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", - ioc->name, __func__)); - - ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM); - if (pci_enable_device_mem(pdev)) { - pr_warn(MPT3SAS_FMT "pci_enable_device_mem: failed\n", - ioc->name); - ioc->bars = 0; - return -ENODEV; - } - - - if (pci_request_selected_regions(pdev, ioc->bars, - ioc->driver_name)) { - pr_warn(MPT3SAS_FMT "pci_request_selected_regions: failed\n", - ioc->name); - ioc->bars = 0; - r = -ENODEV; - goto out_fail; - } - -/* AER (Advanced Error Reporting) hooks */ - pci_enable_pcie_error_reporting(pdev); - - pci_set_master(pdev); - - - if (_base_config_dma_addressing(ioc, pdev) != 0) { - pr_warn(MPT3SAS_FMT "no suitable DMA mask for %s\n", - ioc->name, pci_name(pdev)); - r = -ENODEV; - goto out_fail; - } - - for (i = 0, memap_sz = 0, pio_sz = 0; (i < DEVICE_COUNT_RESOURCE) && - (!memap_sz || !pio_sz); i++) { - if (pci_resource_flags(pdev, i) & IORESOURCE_IO) { - if (pio_sz) - continue; - pio_chip = (u64)pci_resource_start(pdev, i); - pio_sz = pci_resource_len(pdev, i); - } else if (pci_resource_flags(pdev, i) & IORESOURCE_MEM) { - if (memap_sz) - continue; - ioc->chip_phys = pci_resource_start(pdev, i); - chip_phys = (u64)ioc->chip_phys; - memap_sz = pci_resource_len(pdev, i); - ioc->chip = ioremap(ioc->chip_phys, memap_sz); - } - } - - if (ioc->chip == NULL) { - pr_err(MPT3SAS_FMT "unable to map adapter memory! " - " or resource not found\n", ioc->name); - r = -EINVAL; - goto out_fail; - } - - _base_mask_interrupts(ioc); - - r = _base_get_ioc_facts(ioc, CAN_SLEEP); - if (r) - goto out_fail; - - if (!ioc->rdpq_array_enable_assigned) { - ioc->rdpq_array_enable = ioc->rdpq_array_capable; - ioc->rdpq_array_enable_assigned = 1; - } - - r = _base_enable_msix(ioc); - if (r) - goto out_fail; - - /* Use the Combined reply queue feature only for SAS3 C0 & higher - * revision HBAs and also only when reply queue count is greater than 8 - */ - if (ioc->msix96_vector && ioc->reply_queue_count > 8) { - /* Determine the Supplemental Reply Post Host Index Registers - * Addresse. Supplemental Reply Post Host Index Registers - * starts at offset MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET and - * each register is at offset bytes of - * MPT3_SUP_REPLY_POST_HOST_INDEX_REG_OFFSET from previous one. - */ - ioc->replyPostRegisterIndex = kcalloc( - MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT, - sizeof(resource_size_t *), GFP_KERNEL); - if (!ioc->replyPostRegisterIndex) { - dfailprintk(ioc, printk(MPT3SAS_FMT - "allocation for reply Post Register Index failed!!!\n", - ioc->name)); - r = -ENOMEM; - goto out_fail; - } - - for (i = 0; i < MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT; i++) { - ioc->replyPostRegisterIndex[i] = (resource_size_t *) - ((u8 *)&ioc->chip->Doorbell + - MPI25_SUP_REPLY_POST_HOST_INDEX_OFFSET + - (i * MPT3_SUP_REPLY_POST_HOST_INDEX_REG_OFFSET)); - } - } else - ioc->msix96_vector = 0; - - if (ioc->is_warpdrive) { - ioc->reply_post_host_index[0] = (resource_size_t __iomem *) - &ioc->chip->ReplyPostHostIndex; - - for (i = 1; i < ioc->cpu_msix_table_sz; i++) - ioc->reply_post_host_index[i] = - (resource_size_t __iomem *) - ((u8 __iomem *)&ioc->chip->Doorbell + (0x4000 + ((i - 1) - * 4))); - } - - list_for_each_entry(reply_q, &ioc->reply_queue_list, list) - pr_info(MPT3SAS_FMT "%s: IRQ %d\n", - reply_q->name, ((ioc->msix_enable) ? "PCI-MSI-X enabled" : - "IO-APIC enabled"), reply_q->vector); - - pr_info(MPT3SAS_FMT "iomem(0x%016llx), mapped(0x%p), size(%d)\n", - ioc->name, (unsigned long long)chip_phys, ioc->chip, memap_sz); - pr_info(MPT3SAS_FMT "ioport(0x%016llx), size(%d)\n", - ioc->name, (unsigned long long)pio_chip, pio_sz); - - /* Save PCI configuration state for recovery from PCI AER/EEH errors */ - pci_save_state(pdev); - return 0; - - out_fail: - mpt3sas_base_unmap_resources(ioc); - return r; -} - -/** - * mpt3sas_base_get_msg_frame - obtain request mf pointer - * @ioc: per adapter object - * @smid: system request message index(smid zero is invalid) - * - * Returns virt pointer to message frame. - */ -void * -mpt3sas_base_get_msg_frame(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - return (void *)(ioc->request + (smid * ioc->request_sz)); -} - -/** - * mpt3sas_base_get_sense_buffer - obtain a sense buffer virt addr - * @ioc: per adapter object - * @smid: system request message index - * - * Returns virt pointer to sense buffer. - */ -void * -mpt3sas_base_get_sense_buffer(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - return (void *)(ioc->sense + ((smid - 1) * SCSI_SENSE_BUFFERSIZE)); -} - -/** - * mpt3sas_base_get_sense_buffer_dma - obtain a sense buffer dma addr - * @ioc: per adapter object - * @smid: system request message index - * - * Returns phys pointer to the low 32bit address of the sense buffer. - */ -__le32 -mpt3sas_base_get_sense_buffer_dma(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - return cpu_to_le32(ioc->sense_dma + ((smid - 1) * - SCSI_SENSE_BUFFERSIZE)); -} - -/** - * mpt3sas_base_get_reply_virt_addr - obtain reply frames virt address - * @ioc: per adapter object - * @phys_addr: lower 32 physical addr of the reply - * - * Converts 32bit lower physical addr into a virt address. - */ -void * -mpt3sas_base_get_reply_virt_addr(struct MPT3SAS_ADAPTER *ioc, u32 phys_addr) -{ - if (!phys_addr) - return NULL; - return ioc->reply + (phys_addr - (u32)ioc->reply_dma); -} - -static inline u8 -_base_get_msix_index(struct MPT3SAS_ADAPTER *ioc) -{ - return ioc->cpu_msix_table[raw_smp_processor_id()]; -} - -/** - * mpt3sas_base_get_smid - obtain a free smid from internal queue - * @ioc: per adapter object - * @cb_idx: callback index - * - * Returns smid (zero is invalid) - */ -u16 -mpt3sas_base_get_smid(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx) -{ - unsigned long flags; - struct request_tracker *request; - u16 smid; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - if (list_empty(&ioc->internal_free_list)) { - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - pr_err(MPT3SAS_FMT "%s: smid not available\n", - ioc->name, __func__); - return 0; - } - - request = list_entry(ioc->internal_free_list.next, - struct request_tracker, tracker_list); - request->cb_idx = cb_idx; - smid = request->smid; - list_del(&request->tracker_list); - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return smid; -} - -/** - * mpt3sas_base_get_smid_scsiio - obtain a free smid from scsiio queue - * @ioc: per adapter object - * @cb_idx: callback index - * @scmd: pointer to scsi command object - * - * Returns smid (zero is invalid) - */ -u16 -mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx, - struct scsi_cmnd *scmd) -{ - unsigned long flags; - struct scsiio_tracker *request; - u16 smid; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - if (list_empty(&ioc->free_list)) { - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - pr_err(MPT3SAS_FMT "%s: smid not available\n", - ioc->name, __func__); - return 0; - } - - request = list_entry(ioc->free_list.next, - struct scsiio_tracker, tracker_list); - request->scmd = scmd; - request->cb_idx = cb_idx; - smid = request->smid; - request->msix_io = _base_get_msix_index(ioc); - list_del(&request->tracker_list); - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return smid; -} - -/** - * mpt3sas_base_get_smid_hpr - obtain a free smid from hi-priority queue - * @ioc: per adapter object - * @cb_idx: callback index - * - * Returns smid (zero is invalid) - */ -u16 -mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx) -{ - unsigned long flags; - struct request_tracker *request; - u16 smid; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - if (list_empty(&ioc->hpr_free_list)) { - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return 0; - } - - request = list_entry(ioc->hpr_free_list.next, - struct request_tracker, tracker_list); - request->cb_idx = cb_idx; - smid = request->smid; - list_del(&request->tracker_list); - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return smid; -} - -/** - * mpt3sas_base_free_smid - put smid back on free_list - * @ioc: per adapter object - * @smid: system request message index - * - * Return nothing. - */ -void -mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - unsigned long flags; - int i; - struct chain_tracker *chain_req, *next; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - if (smid < ioc->hi_priority_smid) { - /* scsiio queue */ - i = smid - 1; - if (!list_empty(&ioc->scsi_lookup[i].chain_list)) { - list_for_each_entry_safe(chain_req, next, - &ioc->scsi_lookup[i].chain_list, tracker_list) { - list_del_init(&chain_req->tracker_list); - list_add(&chain_req->tracker_list, - &ioc->free_chain_list); - } - } - ioc->scsi_lookup[i].cb_idx = 0xFF; - ioc->scsi_lookup[i].scmd = NULL; - ioc->scsi_lookup[i].direct_io = 0; - list_add(&ioc->scsi_lookup[i].tracker_list, &ioc->free_list); - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - - /* - * See _wait_for_commands_to_complete() call with regards - * to this code. - */ - if (ioc->shost_recovery && ioc->pending_io_count) { - if (ioc->pending_io_count == 1) - wake_up(&ioc->reset_wq); - ioc->pending_io_count--; - } - return; - } else if (smid < ioc->internal_smid) { - /* hi-priority */ - i = smid - ioc->hi_priority_smid; - ioc->hpr_lookup[i].cb_idx = 0xFF; - list_add(&ioc->hpr_lookup[i].tracker_list, &ioc->hpr_free_list); - } else if (smid <= ioc->hba_queue_depth) { - /* internal queue */ - i = smid - ioc->internal_smid; - ioc->internal_lookup[i].cb_idx = 0xFF; - list_add(&ioc->internal_lookup[i].tracker_list, - &ioc->internal_free_list); - } - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); -} - -/** - * _base_writeq - 64 bit write to MMIO - * @ioc: per adapter object - * @b: data payload - * @addr: address in MMIO space - * @writeq_lock: spin lock - * - * Glue for handling an atomic 64 bit word to MMIO. This special handling takes - * care of 32 bit environment where its not quarenteed to send the entire word - * in one transfer. - */ -#if defined(writeq) && defined(CONFIG_64BIT) -static inline void -_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock) -{ - writeq(cpu_to_le64(b), addr); -} -#else -static inline void -_base_writeq(__u64 b, volatile void __iomem *addr, spinlock_t *writeq_lock) -{ - unsigned long flags; - __u64 data_out = cpu_to_le64(b); - - spin_lock_irqsave(writeq_lock, flags); - writel((u32)(data_out), addr); - writel((u32)(data_out >> 32), (addr + 4)); - spin_unlock_irqrestore(writeq_lock, flags); -} -#endif - -/** - * mpt3sas_base_put_smid_scsi_io - send SCSI_IO request to firmware - * @ioc: per adapter object - * @smid: system request message index - * @handle: device handle - * - * Return nothing. - */ -void -mpt3sas_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, u16 handle) -{ - Mpi2RequestDescriptorUnion_t descriptor; - u64 *request = (u64 *)&descriptor; - - - descriptor.SCSIIO.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_SCSI_IO; - descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc); - descriptor.SCSIIO.SMID = cpu_to_le16(smid); - descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); - descriptor.SCSIIO.LMID = 0; - _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, - &ioc->scsi_lookup_lock); -} - -/** - * mpt3sas_base_put_smid_fast_path - send fast path request to firmware - * @ioc: per adapter object - * @smid: system request message index - * @handle: device handle - * - * Return nothing. - */ -void -mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u16 handle) -{ - Mpi2RequestDescriptorUnion_t descriptor; - u64 *request = (u64 *)&descriptor; - - descriptor.SCSIIO.RequestFlags = - MPI25_REQ_DESCRIPT_FLAGS_FAST_PATH_SCSI_IO; - descriptor.SCSIIO.MSIxIndex = _base_get_msix_index(ioc); - descriptor.SCSIIO.SMID = cpu_to_le16(smid); - descriptor.SCSIIO.DevHandle = cpu_to_le16(handle); - descriptor.SCSIIO.LMID = 0; - _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, - &ioc->scsi_lookup_lock); -} - -/** - * mpt3sas_base_put_smid_hi_priority - send Task Managment request to firmware - * @ioc: per adapter object - * @smid: system request message index - * @msix_task: msix_task will be same as msix of IO incase of task abort else 0. - * Return nothing. - */ -void -mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u16 msix_task) -{ - Mpi2RequestDescriptorUnion_t descriptor; - u64 *request = (u64 *)&descriptor; - - descriptor.HighPriority.RequestFlags = - MPI2_REQ_DESCRIPT_FLAGS_HIGH_PRIORITY; - descriptor.HighPriority.MSIxIndex = msix_task; - descriptor.HighPriority.SMID = cpu_to_le16(smid); - descriptor.HighPriority.LMID = 0; - descriptor.HighPriority.Reserved1 = 0; - _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, - &ioc->scsi_lookup_lock); -} - -/** - * mpt3sas_base_put_smid_default - Default, primarily used for config pages - * @ioc: per adapter object - * @smid: system request message index - * - * Return nothing. - */ -void -mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - Mpi2RequestDescriptorUnion_t descriptor; - u64 *request = (u64 *)&descriptor; - - descriptor.Default.RequestFlags = MPI2_REQ_DESCRIPT_FLAGS_DEFAULT_TYPE; - descriptor.Default.MSIxIndex = _base_get_msix_index(ioc); - descriptor.Default.SMID = cpu_to_le16(smid); - descriptor.Default.LMID = 0; - descriptor.Default.DescriptorTypeDependent = 0; - _base_writeq(*request, &ioc->chip->RequestDescriptorPostLow, - &ioc->scsi_lookup_lock); -} - -/** - * _base_display_OEMs_branding - Display branding string - * @ioc: per adapter object - * - * Return nothing. - */ -static void -_base_display_OEMs_branding(struct MPT3SAS_ADAPTER *ioc) -{ - if (ioc->pdev->subsystem_vendor != PCI_VENDOR_ID_INTEL) - return; - - switch (ioc->pdev->subsystem_vendor) { - case PCI_VENDOR_ID_INTEL: - switch (ioc->pdev->device) { - case MPI2_MFGPAGE_DEVID_SAS2008: - switch (ioc->pdev->subsystem_device) { - case MPT2SAS_INTEL_RMS2LL080_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_INTEL_RMS2LL080_BRANDING); - break; - case MPT2SAS_INTEL_RMS2LL040_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_INTEL_RMS2LL040_BRANDING); - break; - case MPT2SAS_INTEL_SSD910_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_INTEL_SSD910_BRANDING); - break; - default: - pr_info(MPT3SAS_FMT - "Intel(R) Controller: Subsystem ID: 0x%X\n", - ioc->name, ioc->pdev->subsystem_device); - break; - } - case MPI2_MFGPAGE_DEVID_SAS2308_2: - switch (ioc->pdev->subsystem_device) { - case MPT2SAS_INTEL_RS25GB008_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_INTEL_RS25GB008_BRANDING); - break; - case MPT2SAS_INTEL_RMS25JB080_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_INTEL_RMS25JB080_BRANDING); - break; - case MPT2SAS_INTEL_RMS25JB040_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_INTEL_RMS25JB040_BRANDING); - break; - case MPT2SAS_INTEL_RMS25KB080_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_INTEL_RMS25KB080_BRANDING); - break; - case MPT2SAS_INTEL_RMS25KB040_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_INTEL_RMS25KB040_BRANDING); - break; - case MPT2SAS_INTEL_RMS25LB040_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_INTEL_RMS25LB040_BRANDING); - break; - case MPT2SAS_INTEL_RMS25LB080_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_INTEL_RMS25LB080_BRANDING); - break; - default: - pr_info(MPT3SAS_FMT - "Intel(R) Controller: Subsystem ID: 0x%X\n", - ioc->name, ioc->pdev->subsystem_device); - break; - } - case MPI25_MFGPAGE_DEVID_SAS3008: - switch (ioc->pdev->subsystem_device) { - case MPT3SAS_INTEL_RMS3JC080_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT3SAS_INTEL_RMS3JC080_BRANDING); - break; - - case MPT3SAS_INTEL_RS3GC008_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT3SAS_INTEL_RS3GC008_BRANDING); - break; - case MPT3SAS_INTEL_RS3FC044_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT3SAS_INTEL_RS3FC044_BRANDING); - break; - case MPT3SAS_INTEL_RS3UC080_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT3SAS_INTEL_RS3UC080_BRANDING); - break; - default: - pr_info(MPT3SAS_FMT - "Intel(R) Controller: Subsystem ID: 0x%X\n", - ioc->name, ioc->pdev->subsystem_device); - break; - } - break; - default: - pr_info(MPT3SAS_FMT - "Intel(R) Controller: Subsystem ID: 0x%X\n", - ioc->name, ioc->pdev->subsystem_device); - break; - } - break; - case PCI_VENDOR_ID_DELL: - switch (ioc->pdev->device) { - case MPI2_MFGPAGE_DEVID_SAS2008: - switch (ioc->pdev->subsystem_device) { - case MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING); - break; - case MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING); - break; - case MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING); - break; - case MPT2SAS_DELL_PERC_H200_MODULAR_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING); - break; - case MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING); - break; - case MPT2SAS_DELL_PERC_H200_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_DELL_PERC_H200_BRANDING); - break; - case MPT2SAS_DELL_6GBPS_SAS_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_DELL_6GBPS_SAS_BRANDING); - break; - default: - pr_info(MPT3SAS_FMT - "Dell 6Gbps HBA: Subsystem ID: 0x%X\n", - ioc->name, ioc->pdev->subsystem_device); - break; - } - break; - case MPI25_MFGPAGE_DEVID_SAS3008: - switch (ioc->pdev->subsystem_device) { - case MPT3SAS_DELL_12G_HBA_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT3SAS_DELL_12G_HBA_BRANDING); - break; - default: - pr_info(MPT3SAS_FMT - "Dell 12Gbps HBA: Subsystem ID: 0x%X\n", - ioc->name, ioc->pdev->subsystem_device); - break; - } - break; - default: - pr_info(MPT3SAS_FMT - "Dell HBA: Subsystem ID: 0x%X\n", ioc->name, - ioc->pdev->subsystem_device); - break; - } - break; - case PCI_VENDOR_ID_CISCO: - switch (ioc->pdev->device) { - case MPI25_MFGPAGE_DEVID_SAS3008: - switch (ioc->pdev->subsystem_device) { - case MPT3SAS_CISCO_12G_8E_HBA_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT3SAS_CISCO_12G_8E_HBA_BRANDING); - break; - case MPT3SAS_CISCO_12G_8I_HBA_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT3SAS_CISCO_12G_8I_HBA_BRANDING); - break; - case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING); - break; - default: - pr_info(MPT3SAS_FMT - "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n", - ioc->name, ioc->pdev->subsystem_device); - break; - } - break; - case MPI25_MFGPAGE_DEVID_SAS3108_1: - switch (ioc->pdev->subsystem_device) { - case MPT3SAS_CISCO_12G_AVILA_HBA_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING); - break; - case MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING - ); - break; - default: - pr_info(MPT3SAS_FMT - "Cisco 12Gbps SAS HBA: Subsystem ID: 0x%X\n", - ioc->name, ioc->pdev->subsystem_device); - break; - } - break; - default: - pr_info(MPT3SAS_FMT - "Cisco SAS HBA: Subsystem ID: 0x%X\n", - ioc->name, ioc->pdev->subsystem_device); - break; - } - break; - case MPT2SAS_HP_3PAR_SSVID: - switch (ioc->pdev->device) { - case MPI2_MFGPAGE_DEVID_SAS2004: - switch (ioc->pdev->subsystem_device) { - case MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING); - break; - default: - pr_info(MPT3SAS_FMT - "HP 6Gbps SAS HBA: Subsystem ID: 0x%X\n", - ioc->name, ioc->pdev->subsystem_device); - break; - } - case MPI2_MFGPAGE_DEVID_SAS2308_2: - switch (ioc->pdev->subsystem_device) { - case MPT2SAS_HP_2_4_INTERNAL_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_HP_2_4_INTERNAL_BRANDING); - break; - case MPT2SAS_HP_2_4_EXTERNAL_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_HP_2_4_EXTERNAL_BRANDING); - break; - case MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING); - break; - case MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID: - pr_info(MPT3SAS_FMT "%s\n", ioc->name, - MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING); - break; - default: - pr_info(MPT3SAS_FMT - "HP 6Gbps SAS HBA: Subsystem ID: 0x%X\n", - ioc->name, ioc->pdev->subsystem_device); - break; - } - default: - pr_info(MPT3SAS_FMT - "HP SAS HBA: Subsystem ID: 0x%X\n", - ioc->name, ioc->pdev->subsystem_device); - break; - } - default: - break; - } -} - -/** - * _base_display_ioc_capabilities - Disply IOC's capabilities. - * @ioc: per adapter object - * - * Return nothing. - */ -static void -_base_display_ioc_capabilities(struct MPT3SAS_ADAPTER *ioc) -{ - int i = 0; - char desc[16]; - u32 iounit_pg1_flags; - u32 bios_version; - - bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); - strncpy(desc, ioc->manu_pg0.ChipName, 16); - pr_info(MPT3SAS_FMT "%s: FWVersion(%02d.%02d.%02d.%02d), "\ - "ChipRevision(0x%02x), BiosVersion(%02d.%02d.%02d.%02d)\n", - ioc->name, desc, - (ioc->facts.FWVersion.Word & 0xFF000000) >> 24, - (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, - (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, - ioc->facts.FWVersion.Word & 0x000000FF, - ioc->pdev->revision, - (bios_version & 0xFF000000) >> 24, - (bios_version & 0x00FF0000) >> 16, - (bios_version & 0x0000FF00) >> 8, - bios_version & 0x000000FF); - - _base_display_OEMs_branding(ioc); - - pr_info(MPT3SAS_FMT "Protocol=(", ioc->name); - - if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR) { - pr_info("Initiator"); - i++; - } - - if (ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_TARGET) { - pr_info("%sTarget", i ? "," : ""); - i++; - } - - i = 0; - pr_info("), "); - pr_info("Capabilities=("); - - if (!ioc->hide_ir_msg) { - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID) { - pr_info("Raid"); - i++; - } - } - - if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR) { - pr_info("%sTLR", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_MULTICAST) { - pr_info("%sMulticast", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_BIDIRECTIONAL_TARGET) { - pr_info("%sBIDI Target", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_EEDP) { - pr_info("%sEEDP", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) { - pr_info("%sSnapshot Buffer", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) { - pr_info("%sDiag Trace Buffer", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) { - pr_info("%sDiag Extended Buffer", i ? "," : ""); - i++; - } - - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING) { - pr_info("%sTask Set Full", i ? "," : ""); - i++; - } - - iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags); - if (!(iounit_pg1_flags & MPI2_IOUNITPAGE1_NATIVE_COMMAND_Q_DISABLE)) { - pr_info("%sNCQ", i ? "," : ""); - i++; - } - - pr_info(")\n"); -} - -/** - * mpt3sas_base_update_missing_delay - change the missing delay timers - * @ioc: per adapter object - * @device_missing_delay: amount of time till device is reported missing - * @io_missing_delay: interval IO is returned when there is a missing device - * - * Return nothing. - * - * Passed on the command line, this function will modify the device missing - * delay, as well as the io missing delay. This should be called at driver - * load time. - */ -void -mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc, - u16 device_missing_delay, u8 io_missing_delay) -{ - u16 dmd, dmd_new, dmd_orignal; - u8 io_missing_delay_original; - u16 sz; - Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; - Mpi2ConfigReply_t mpi_reply; - u8 num_phys = 0; - u16 ioc_status; - - mpt3sas_config_get_number_hba_phys(ioc, &num_phys); - if (!num_phys) - return; - - sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (num_phys * - sizeof(Mpi2SasIOUnit1PhyData_t)); - sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg1) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, - sas_iounit_pg1, sz))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - - /* device missing delay */ - dmd = sas_iounit_pg1->ReportDeviceMissingDelay; - if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16) - dmd = (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16; - else - dmd = dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK; - dmd_orignal = dmd; - if (device_missing_delay > 0x7F) { - dmd = (device_missing_delay > 0x7F0) ? 0x7F0 : - device_missing_delay; - dmd = dmd / 16; - dmd |= MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16; - } else - dmd = device_missing_delay; - sas_iounit_pg1->ReportDeviceMissingDelay = dmd; - - /* io missing delay */ - io_missing_delay_original = sas_iounit_pg1->IODeviceMissingDelay; - sas_iounit_pg1->IODeviceMissingDelay = io_missing_delay; - - if (!mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, - sz)) { - if (dmd & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16) - dmd_new = (dmd & - MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16; - else - dmd_new = - dmd & MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK; - pr_info(MPT3SAS_FMT "device_missing_delay: old(%d), new(%d)\n", - ioc->name, dmd_orignal, dmd_new); - pr_info(MPT3SAS_FMT "ioc_missing_delay: old(%d), new(%d)\n", - ioc->name, io_missing_delay_original, - io_missing_delay); - ioc->device_missing_delay = dmd_new; - ioc->io_missing_delay = io_missing_delay; - } - -out: - kfree(sas_iounit_pg1); -} -/** - * _base_static_config_pages - static start of day config pages - * @ioc: per adapter object - * - * Return nothing. - */ -static void -_base_static_config_pages(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2ConfigReply_t mpi_reply; - u32 iounit_pg1_flags; - - mpt3sas_config_get_manufacturing_pg0(ioc, &mpi_reply, &ioc->manu_pg0); - if (ioc->ir_firmware) - mpt3sas_config_get_manufacturing_pg10(ioc, &mpi_reply, - &ioc->manu_pg10); - - /* - * Ensure correct T10 PI operation if vendor left EEDPTagMode - * flag unset in NVDATA. - */ - mpt3sas_config_get_manufacturing_pg11(ioc, &mpi_reply, &ioc->manu_pg11); - if (ioc->manu_pg11.EEDPTagMode == 0) { - pr_err("%s: overriding NVDATA EEDPTagMode setting\n", - ioc->name); - ioc->manu_pg11.EEDPTagMode &= ~0x3; - ioc->manu_pg11.EEDPTagMode |= 0x1; - mpt3sas_config_set_manufacturing_pg11(ioc, &mpi_reply, - &ioc->manu_pg11); - } - - mpt3sas_config_get_bios_pg2(ioc, &mpi_reply, &ioc->bios_pg2); - mpt3sas_config_get_bios_pg3(ioc, &mpi_reply, &ioc->bios_pg3); - mpt3sas_config_get_ioc_pg8(ioc, &mpi_reply, &ioc->ioc_pg8); - mpt3sas_config_get_iounit_pg0(ioc, &mpi_reply, &ioc->iounit_pg0); - mpt3sas_config_get_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1); - mpt3sas_config_get_iounit_pg8(ioc, &mpi_reply, &ioc->iounit_pg8); - _base_display_ioc_capabilities(ioc); - - /* - * Enable task_set_full handling in iounit_pg1 when the - * facts capabilities indicate that its supported. - */ - iounit_pg1_flags = le32_to_cpu(ioc->iounit_pg1.Flags); - if ((ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_TASK_SET_FULL_HANDLING)) - iounit_pg1_flags &= - ~MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING; - else - iounit_pg1_flags |= - MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING; - ioc->iounit_pg1.Flags = cpu_to_le32(iounit_pg1_flags); - mpt3sas_config_set_iounit_pg1(ioc, &mpi_reply, &ioc->iounit_pg1); - - if (ioc->iounit_pg8.NumSensors) - ioc->temp_sensors_count = ioc->iounit_pg8.NumSensors; -} - -/** - * _base_release_memory_pools - release memory - * @ioc: per adapter object - * - * Free memory allocated from _base_allocate_memory_pools. - * - * Return nothing. - */ -static void -_base_release_memory_pools(struct MPT3SAS_ADAPTER *ioc) -{ - int i = 0; - struct reply_post_struct *rps; - - dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - if (ioc->request) { - pci_free_consistent(ioc->pdev, ioc->request_dma_sz, - ioc->request, ioc->request_dma); - dexitprintk(ioc, pr_info(MPT3SAS_FMT - "request_pool(0x%p): free\n", - ioc->name, ioc->request)); - ioc->request = NULL; - } - - if (ioc->sense) { - pci_pool_free(ioc->sense_dma_pool, ioc->sense, ioc->sense_dma); - if (ioc->sense_dma_pool) - pci_pool_destroy(ioc->sense_dma_pool); - dexitprintk(ioc, pr_info(MPT3SAS_FMT - "sense_pool(0x%p): free\n", - ioc->name, ioc->sense)); - ioc->sense = NULL; - } - - if (ioc->reply) { - pci_pool_free(ioc->reply_dma_pool, ioc->reply, ioc->reply_dma); - if (ioc->reply_dma_pool) - pci_pool_destroy(ioc->reply_dma_pool); - dexitprintk(ioc, pr_info(MPT3SAS_FMT - "reply_pool(0x%p): free\n", - ioc->name, ioc->reply)); - ioc->reply = NULL; - } - - if (ioc->reply_free) { - pci_pool_free(ioc->reply_free_dma_pool, ioc->reply_free, - ioc->reply_free_dma); - if (ioc->reply_free_dma_pool) - pci_pool_destroy(ioc->reply_free_dma_pool); - dexitprintk(ioc, pr_info(MPT3SAS_FMT - "reply_free_pool(0x%p): free\n", - ioc->name, ioc->reply_free)); - ioc->reply_free = NULL; - } - - if (ioc->reply_post) { - do { - rps = &ioc->reply_post[i]; - if (rps->reply_post_free) { - pci_pool_free( - ioc->reply_post_free_dma_pool, - rps->reply_post_free, - rps->reply_post_free_dma); - dexitprintk(ioc, pr_info(MPT3SAS_FMT - "reply_post_free_pool(0x%p): free\n", - ioc->name, rps->reply_post_free)); - rps->reply_post_free = NULL; - } - } while (ioc->rdpq_array_enable && - (++i < ioc->reply_queue_count)); - - if (ioc->reply_post_free_dma_pool) - pci_pool_destroy(ioc->reply_post_free_dma_pool); - kfree(ioc->reply_post); - } - - if (ioc->config_page) { - dexitprintk(ioc, pr_info(MPT3SAS_FMT - "config_page(0x%p): free\n", ioc->name, - ioc->config_page)); - pci_free_consistent(ioc->pdev, ioc->config_page_sz, - ioc->config_page, ioc->config_page_dma); - } - - if (ioc->scsi_lookup) { - free_pages((ulong)ioc->scsi_lookup, ioc->scsi_lookup_pages); - ioc->scsi_lookup = NULL; - } - kfree(ioc->hpr_lookup); - kfree(ioc->internal_lookup); - if (ioc->chain_lookup) { - for (i = 0; i < ioc->chain_depth; i++) { - if (ioc->chain_lookup[i].chain_buffer) - pci_pool_free(ioc->chain_dma_pool, - ioc->chain_lookup[i].chain_buffer, - ioc->chain_lookup[i].chain_buffer_dma); - } - if (ioc->chain_dma_pool) - pci_pool_destroy(ioc->chain_dma_pool); - free_pages((ulong)ioc->chain_lookup, ioc->chain_pages); - ioc->chain_lookup = NULL; - } -} - -/** - * _base_allocate_memory_pools - allocate start of day memory pools - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 success, anything else error - */ -static int -_base_allocate_memory_pools(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - struct mpt3sas_facts *facts; - u16 max_sge_elements; - u16 chains_needed_per_io; - u32 sz, total_sz, reply_post_free_sz; - u32 retry_sz; - u16 max_request_credit; - unsigned short sg_tablesize; - u16 sge_size; - int i; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - - retry_sz = 0; - facts = &ioc->facts; - - /* command line tunables for max sgl entries */ - if (max_sgl_entries != -1) - sg_tablesize = max_sgl_entries; - else { - if (ioc->hba_mpi_version_belonged == MPI2_VERSION) - sg_tablesize = MPT2SAS_SG_DEPTH; - else - sg_tablesize = MPT3SAS_SG_DEPTH; - } - - if (sg_tablesize < MPT_MIN_PHYS_SEGMENTS) - sg_tablesize = MPT_MIN_PHYS_SEGMENTS; - else if (sg_tablesize > MPT_MAX_PHYS_SEGMENTS) { - sg_tablesize = min_t(unsigned short, sg_tablesize, - SCSI_MAX_SG_CHAIN_SEGMENTS); - pr_warn(MPT3SAS_FMT - "sg_tablesize(%u) is bigger than kernel" - " defined SCSI_MAX_SG_SEGMENTS(%u)\n", ioc->name, - sg_tablesize, MPT_MAX_PHYS_SEGMENTS); - } - ioc->shost->sg_tablesize = sg_tablesize; - - ioc->hi_priority_depth = facts->HighPriorityCredit; - ioc->internal_depth = ioc->hi_priority_depth + (5); - /* command line tunables for max controller queue depth */ - if (max_queue_depth != -1 && max_queue_depth != 0) { - max_request_credit = min_t(u16, max_queue_depth + - ioc->hi_priority_depth + ioc->internal_depth, - facts->RequestCredit); - if (max_request_credit > MAX_HBA_QUEUE_DEPTH) - max_request_credit = MAX_HBA_QUEUE_DEPTH; - } else - max_request_credit = min_t(u16, facts->RequestCredit, - MAX_HBA_QUEUE_DEPTH); - - ioc->hba_queue_depth = max_request_credit; - - /* request frame size */ - ioc->request_sz = facts->IOCRequestFrameSize * 4; - - /* reply frame size */ - ioc->reply_sz = facts->ReplyFrameSize * 4; - - /* calculate the max scatter element size */ - sge_size = max_t(u16, ioc->sge_size, ioc->sge_size_ieee); - - retry_allocation: - total_sz = 0; - /* calculate number of sg elements left over in the 1st frame */ - max_sge_elements = ioc->request_sz - ((sizeof(Mpi2SCSIIORequest_t) - - sizeof(Mpi2SGEIOUnion_t)) + sge_size); - ioc->max_sges_in_main_message = max_sge_elements/sge_size; - - /* now do the same for a chain buffer */ - max_sge_elements = ioc->request_sz - sge_size; - ioc->max_sges_in_chain_message = max_sge_elements/sge_size; - - /* - * MPT3SAS_SG_DEPTH = CONFIG_FUSION_MAX_SGE - */ - chains_needed_per_io = ((ioc->shost->sg_tablesize - - ioc->max_sges_in_main_message)/ioc->max_sges_in_chain_message) - + 1; - if (chains_needed_per_io > facts->MaxChainDepth) { - chains_needed_per_io = facts->MaxChainDepth; - ioc->shost->sg_tablesize = min_t(u16, - ioc->max_sges_in_main_message + (ioc->max_sges_in_chain_message - * chains_needed_per_io), ioc->shost->sg_tablesize); - } - ioc->chains_needed_per_io = chains_needed_per_io; - - /* reply free queue sizing - taking into account for 64 FW events */ - ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64; - - /* calculate reply descriptor post queue depth */ - ioc->reply_post_queue_depth = ioc->hba_queue_depth + - ioc->reply_free_queue_depth + 1 ; - /* align the reply post queue on the next 16 count boundary */ - if (ioc->reply_post_queue_depth % 16) - ioc->reply_post_queue_depth += 16 - - (ioc->reply_post_queue_depth % 16); - - - if (ioc->reply_post_queue_depth > - facts->MaxReplyDescriptorPostQueueDepth) { - ioc->reply_post_queue_depth = - facts->MaxReplyDescriptorPostQueueDepth - - (facts->MaxReplyDescriptorPostQueueDepth % 16); - ioc->hba_queue_depth = - ((ioc->reply_post_queue_depth - 64) / 2) - 1; - ioc->reply_free_queue_depth = ioc->hba_queue_depth + 64; - } - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "scatter gather: " \ - "sge_in_main_msg(%d), sge_per_chain(%d), sge_per_io(%d), " - "chains_per_io(%d)\n", ioc->name, ioc->max_sges_in_main_message, - ioc->max_sges_in_chain_message, ioc->shost->sg_tablesize, - ioc->chains_needed_per_io)); - - /* reply post queue, 16 byte align */ - reply_post_free_sz = ioc->reply_post_queue_depth * - sizeof(Mpi2DefaultReplyDescriptor_t); - - sz = reply_post_free_sz; - if (_base_is_controller_msix_enabled(ioc) && !ioc->rdpq_array_enable) - sz *= ioc->reply_queue_count; - - ioc->reply_post = kcalloc((ioc->rdpq_array_enable) ? - (ioc->reply_queue_count):1, - sizeof(struct reply_post_struct), GFP_KERNEL); - - if (!ioc->reply_post) { - pr_err(MPT3SAS_FMT "reply_post_free pool: kcalloc failed\n", - ioc->name); - goto out; - } - ioc->reply_post_free_dma_pool = pci_pool_create("reply_post_free pool", - ioc->pdev, sz, 16, 0); - if (!ioc->reply_post_free_dma_pool) { - pr_err(MPT3SAS_FMT - "reply_post_free pool: pci_pool_create failed\n", - ioc->name); - goto out; - } - i = 0; - do { - ioc->reply_post[i].reply_post_free = - pci_pool_alloc(ioc->reply_post_free_dma_pool, - GFP_KERNEL, - &ioc->reply_post[i].reply_post_free_dma); - if (!ioc->reply_post[i].reply_post_free) { - pr_err(MPT3SAS_FMT - "reply_post_free pool: pci_pool_alloc failed\n", - ioc->name); - goto out; - } - memset(ioc->reply_post[i].reply_post_free, 0, sz); - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "reply post free pool (0x%p): depth(%d)," - "element_size(%d), pool_size(%d kB)\n", ioc->name, - ioc->reply_post[i].reply_post_free, - ioc->reply_post_queue_depth, 8, sz/1024)); - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "reply_post_free_dma = (0x%llx)\n", ioc->name, - (unsigned long long) - ioc->reply_post[i].reply_post_free_dma)); - total_sz += sz; - } while (ioc->rdpq_array_enable && (++i < ioc->reply_queue_count)); - - if (ioc->dma_mask == 64) { - if (_base_change_consistent_dma_mask(ioc, ioc->pdev) != 0) { - pr_warn(MPT3SAS_FMT - "no suitable consistent DMA mask for %s\n", - ioc->name, pci_name(ioc->pdev)); - goto out; - } - } - - ioc->scsiio_depth = ioc->hba_queue_depth - - ioc->hi_priority_depth - ioc->internal_depth; - - /* set the scsi host can_queue depth - * with some internal commands that could be outstanding - */ - ioc->shost->can_queue = ioc->scsiio_depth; - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "scsi host: can_queue depth (%d)\n", - ioc->name, ioc->shost->can_queue)); - - - /* contiguous pool for request and chains, 16 byte align, one extra " - * "frame for smid=0 - */ - ioc->chain_depth = ioc->chains_needed_per_io * ioc->scsiio_depth; - sz = ((ioc->scsiio_depth + 1) * ioc->request_sz); - - /* hi-priority queue */ - sz += (ioc->hi_priority_depth * ioc->request_sz); - - /* internal queue */ - sz += (ioc->internal_depth * ioc->request_sz); - - ioc->request_dma_sz = sz; - ioc->request = pci_alloc_consistent(ioc->pdev, sz, &ioc->request_dma); - if (!ioc->request) { - pr_err(MPT3SAS_FMT "request pool: pci_alloc_consistent " \ - "failed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), " - "total(%d kB)\n", ioc->name, ioc->hba_queue_depth, - ioc->chains_needed_per_io, ioc->request_sz, sz/1024); - if (ioc->scsiio_depth < MPT3SAS_SAS_QUEUE_DEPTH) - goto out; - retry_sz += 64; - ioc->hba_queue_depth = max_request_credit - retry_sz; - goto retry_allocation; - } - - if (retry_sz) - pr_err(MPT3SAS_FMT "request pool: pci_alloc_consistent " \ - "succeed: hba_depth(%d), chains_per_io(%d), frame_sz(%d), " - "total(%d kb)\n", ioc->name, ioc->hba_queue_depth, - ioc->chains_needed_per_io, ioc->request_sz, sz/1024); - - /* hi-priority queue */ - ioc->hi_priority = ioc->request + ((ioc->scsiio_depth + 1) * - ioc->request_sz); - ioc->hi_priority_dma = ioc->request_dma + ((ioc->scsiio_depth + 1) * - ioc->request_sz); - - /* internal queue */ - ioc->internal = ioc->hi_priority + (ioc->hi_priority_depth * - ioc->request_sz); - ioc->internal_dma = ioc->hi_priority_dma + (ioc->hi_priority_depth * - ioc->request_sz); - - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "request pool(0x%p): depth(%d), frame_size(%d), pool_size(%d kB)\n", - ioc->name, ioc->request, ioc->hba_queue_depth, ioc->request_sz, - (ioc->hba_queue_depth * ioc->request_sz)/1024)); - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "request pool: dma(0x%llx)\n", - ioc->name, (unsigned long long) ioc->request_dma)); - total_sz += sz; - - sz = ioc->scsiio_depth * sizeof(struct scsiio_tracker); - ioc->scsi_lookup_pages = get_order(sz); - ioc->scsi_lookup = (struct scsiio_tracker *)__get_free_pages( - GFP_KERNEL, ioc->scsi_lookup_pages); - if (!ioc->scsi_lookup) { - pr_err(MPT3SAS_FMT "scsi_lookup: get_free_pages failed, sz(%d)\n", - ioc->name, (int)sz); - goto out; - } - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "scsiio(0x%p): depth(%d)\n", - ioc->name, ioc->request, ioc->scsiio_depth)); - - ioc->chain_depth = min_t(u32, ioc->chain_depth, MAX_CHAIN_DEPTH); - sz = ioc->chain_depth * sizeof(struct chain_tracker); - ioc->chain_pages = get_order(sz); - ioc->chain_lookup = (struct chain_tracker *)__get_free_pages( - GFP_KERNEL, ioc->chain_pages); - if (!ioc->chain_lookup) { - pr_err(MPT3SAS_FMT "chain_lookup: __get_free_pages failed\n", - ioc->name); - goto out; - } - ioc->chain_dma_pool = pci_pool_create("chain pool", ioc->pdev, - ioc->request_sz, 16, 0); - if (!ioc->chain_dma_pool) { - pr_err(MPT3SAS_FMT "chain_dma_pool: pci_pool_create failed\n", - ioc->name); - goto out; - } - for (i = 0; i < ioc->chain_depth; i++) { - ioc->chain_lookup[i].chain_buffer = pci_pool_alloc( - ioc->chain_dma_pool , GFP_KERNEL, - &ioc->chain_lookup[i].chain_buffer_dma); - if (!ioc->chain_lookup[i].chain_buffer) { - ioc->chain_depth = i; - goto chain_done; - } - total_sz += ioc->request_sz; - } - chain_done: - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "chain pool depth(%d), frame_size(%d), pool_size(%d kB)\n", - ioc->name, ioc->chain_depth, ioc->request_sz, - ((ioc->chain_depth * ioc->request_sz))/1024)); - - /* initialize hi-priority queue smid's */ - ioc->hpr_lookup = kcalloc(ioc->hi_priority_depth, - sizeof(struct request_tracker), GFP_KERNEL); - if (!ioc->hpr_lookup) { - pr_err(MPT3SAS_FMT "hpr_lookup: kcalloc failed\n", - ioc->name); - goto out; - } - ioc->hi_priority_smid = ioc->scsiio_depth + 1; - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "hi_priority(0x%p): depth(%d), start smid(%d)\n", - ioc->name, ioc->hi_priority, - ioc->hi_priority_depth, ioc->hi_priority_smid)); - - /* initialize internal queue smid's */ - ioc->internal_lookup = kcalloc(ioc->internal_depth, - sizeof(struct request_tracker), GFP_KERNEL); - if (!ioc->internal_lookup) { - pr_err(MPT3SAS_FMT "internal_lookup: kcalloc failed\n", - ioc->name); - goto out; - } - ioc->internal_smid = ioc->hi_priority_smid + ioc->hi_priority_depth; - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "internal(0x%p): depth(%d), start smid(%d)\n", - ioc->name, ioc->internal, - ioc->internal_depth, ioc->internal_smid)); - - /* sense buffers, 4 byte align */ - sz = ioc->scsiio_depth * SCSI_SENSE_BUFFERSIZE; - ioc->sense_dma_pool = pci_pool_create("sense pool", ioc->pdev, sz, 4, - 0); - if (!ioc->sense_dma_pool) { - pr_err(MPT3SAS_FMT "sense pool: pci_pool_create failed\n", - ioc->name); - goto out; - } - ioc->sense = pci_pool_alloc(ioc->sense_dma_pool , GFP_KERNEL, - &ioc->sense_dma); - if (!ioc->sense) { - pr_err(MPT3SAS_FMT "sense pool: pci_pool_alloc failed\n", - ioc->name); - goto out; - } - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "sense pool(0x%p): depth(%d), element_size(%d), pool_size" - "(%d kB)\n", ioc->name, ioc->sense, ioc->scsiio_depth, - SCSI_SENSE_BUFFERSIZE, sz/1024)); - dinitprintk(ioc, pr_info(MPT3SAS_FMT "sense_dma(0x%llx)\n", - ioc->name, (unsigned long long)ioc->sense_dma)); - total_sz += sz; - - /* reply pool, 4 byte align */ - sz = ioc->reply_free_queue_depth * ioc->reply_sz; - ioc->reply_dma_pool = pci_pool_create("reply pool", ioc->pdev, sz, 4, - 0); - if (!ioc->reply_dma_pool) { - pr_err(MPT3SAS_FMT "reply pool: pci_pool_create failed\n", - ioc->name); - goto out; - } - ioc->reply = pci_pool_alloc(ioc->reply_dma_pool , GFP_KERNEL, - &ioc->reply_dma); - if (!ioc->reply) { - pr_err(MPT3SAS_FMT "reply pool: pci_pool_alloc failed\n", - ioc->name); - goto out; - } - ioc->reply_dma_min_address = (u32)(ioc->reply_dma); - ioc->reply_dma_max_address = (u32)(ioc->reply_dma) + sz; - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "reply pool(0x%p): depth(%d), frame_size(%d), pool_size(%d kB)\n", - ioc->name, ioc->reply, - ioc->reply_free_queue_depth, ioc->reply_sz, sz/1024)); - dinitprintk(ioc, pr_info(MPT3SAS_FMT "reply_dma(0x%llx)\n", - ioc->name, (unsigned long long)ioc->reply_dma)); - total_sz += sz; - - /* reply free queue, 16 byte align */ - sz = ioc->reply_free_queue_depth * 4; - ioc->reply_free_dma_pool = pci_pool_create("reply_free pool", - ioc->pdev, sz, 16, 0); - if (!ioc->reply_free_dma_pool) { - pr_err(MPT3SAS_FMT "reply_free pool: pci_pool_create failed\n", - ioc->name); - goto out; - } - ioc->reply_free = pci_pool_alloc(ioc->reply_free_dma_pool , GFP_KERNEL, - &ioc->reply_free_dma); - if (!ioc->reply_free) { - pr_err(MPT3SAS_FMT "reply_free pool: pci_pool_alloc failed\n", - ioc->name); - goto out; - } - memset(ioc->reply_free, 0, sz); - dinitprintk(ioc, pr_info(MPT3SAS_FMT "reply_free pool(0x%p): " \ - "depth(%d), element_size(%d), pool_size(%d kB)\n", ioc->name, - ioc->reply_free, ioc->reply_free_queue_depth, 4, sz/1024)); - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "reply_free_dma (0x%llx)\n", - ioc->name, (unsigned long long)ioc->reply_free_dma)); - total_sz += sz; - - ioc->config_page_sz = 512; - ioc->config_page = pci_alloc_consistent(ioc->pdev, - ioc->config_page_sz, &ioc->config_page_dma); - if (!ioc->config_page) { - pr_err(MPT3SAS_FMT - "config page: pci_pool_alloc failed\n", - ioc->name); - goto out; - } - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "config page(0x%p): size(%d)\n", - ioc->name, ioc->config_page, ioc->config_page_sz)); - dinitprintk(ioc, pr_info(MPT3SAS_FMT "config_page_dma(0x%llx)\n", - ioc->name, (unsigned long long)ioc->config_page_dma)); - total_sz += ioc->config_page_sz; - - pr_info(MPT3SAS_FMT "Allocated physical memory: size(%d kB)\n", - ioc->name, total_sz/1024); - pr_info(MPT3SAS_FMT - "Current Controller Queue Depth(%d),Max Controller Queue Depth(%d)\n", - ioc->name, ioc->shost->can_queue, facts->RequestCredit); - pr_info(MPT3SAS_FMT "Scatter Gather Elements per IO(%d)\n", - ioc->name, ioc->shost->sg_tablesize); - return 0; - - out: - return -ENOMEM; -} - -/** - * mpt3sas_base_get_iocstate - Get the current state of a MPT adapter. - * @ioc: Pointer to MPT_ADAPTER structure - * @cooked: Request raw or cooked IOC state - * - * Returns all IOC Doorbell register bits if cooked==0, else just the - * Doorbell bits in MPI_IOC_STATE_MASK. - */ -u32 -mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked) -{ - u32 s, sc; - - s = readl(&ioc->chip->Doorbell); - sc = s & MPI2_IOC_STATE_MASK; - return cooked ? sc : s; -} - -/** - * _base_wait_on_iocstate - waiting on a particular ioc state - * @ioc_state: controller state { READY, OPERATIONAL, or RESET } - * @timeout: timeout in second - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_wait_on_iocstate(struct MPT3SAS_ADAPTER *ioc, u32 ioc_state, int timeout, - int sleep_flag) -{ - u32 count, cntdn; - u32 current_state; - - count = 0; - cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; - do { - current_state = mpt3sas_base_get_iocstate(ioc, 1); - if (current_state == ioc_state) - return 0; - if (count && current_state == MPI2_IOC_STATE_FAULT) - break; - if (sleep_flag == CAN_SLEEP) - usleep_range(1000, 1500); - else - udelay(500); - count++; - } while (--cntdn); - - return current_state; -} - -/** - * _base_wait_for_doorbell_int - waiting for controller interrupt(generated by - * a write to the doorbell) - * @ioc: per adapter object - * @timeout: timeout in second - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - * - * Notes: MPI2_HIS_IOC2SYS_DB_STATUS - set to one when IOC writes to doorbell. - */ -static int -_base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag); - -static int -_base_wait_for_doorbell_int(struct MPT3SAS_ADAPTER *ioc, int timeout, - int sleep_flag) -{ - u32 cntdn, count; - u32 int_status; - - count = 0; - cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; - do { - int_status = readl(&ioc->chip->HostInterruptStatus); - if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { - dhsprintk(ioc, pr_info(MPT3SAS_FMT - "%s: successful count(%d), timeout(%d)\n", - ioc->name, __func__, count, timeout)); - return 0; - } - if (sleep_flag == CAN_SLEEP) - usleep_range(1000, 1500); - else - udelay(500); - count++; - } while (--cntdn); - - pr_err(MPT3SAS_FMT - "%s: failed due to timeout count(%d), int_status(%x)!\n", - ioc->name, __func__, count, int_status); - return -EFAULT; -} - -/** - * _base_wait_for_doorbell_ack - waiting for controller to read the doorbell. - * @ioc: per adapter object - * @timeout: timeout in second - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - * - * Notes: MPI2_HIS_SYS2IOC_DB_STATUS - set to one when host writes to - * doorbell. - */ -static int -_base_wait_for_doorbell_ack(struct MPT3SAS_ADAPTER *ioc, int timeout, - int sleep_flag) -{ - u32 cntdn, count; - u32 int_status; - u32 doorbell; - - count = 0; - cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; - do { - int_status = readl(&ioc->chip->HostInterruptStatus); - if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) { - dhsprintk(ioc, pr_info(MPT3SAS_FMT - "%s: successful count(%d), timeout(%d)\n", - ioc->name, __func__, count, timeout)); - return 0; - } else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) { - doorbell = readl(&ioc->chip->Doorbell); - if ((doorbell & MPI2_IOC_STATE_MASK) == - MPI2_IOC_STATE_FAULT) { - mpt3sas_base_fault_info(ioc , doorbell); - return -EFAULT; - } - } else if (int_status == 0xFFFFFFFF) - goto out; - - if (sleep_flag == CAN_SLEEP) - usleep_range(1000, 1500); - else - udelay(500); - count++; - } while (--cntdn); - - out: - pr_err(MPT3SAS_FMT - "%s: failed due to timeout count(%d), int_status(%x)!\n", - ioc->name, __func__, count, int_status); - return -EFAULT; -} - -/** - * _base_wait_for_doorbell_not_used - waiting for doorbell to not be in use - * @ioc: per adapter object - * @timeout: timeout in second - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - * - */ -static int -_base_wait_for_doorbell_not_used(struct MPT3SAS_ADAPTER *ioc, int timeout, - int sleep_flag) -{ - u32 cntdn, count; - u32 doorbell_reg; - - count = 0; - cntdn = (sleep_flag == CAN_SLEEP) ? 1000*timeout : 2000*timeout; - do { - doorbell_reg = readl(&ioc->chip->Doorbell); - if (!(doorbell_reg & MPI2_DOORBELL_USED)) { - dhsprintk(ioc, pr_info(MPT3SAS_FMT - "%s: successful count(%d), timeout(%d)\n", - ioc->name, __func__, count, timeout)); - return 0; - } - if (sleep_flag == CAN_SLEEP) - usleep_range(1000, 1500); - else - udelay(500); - count++; - } while (--cntdn); - - pr_err(MPT3SAS_FMT - "%s: failed due to timeout count(%d), doorbell_reg(%x)!\n", - ioc->name, __func__, count, doorbell_reg); - return -EFAULT; -} - -/** - * _base_send_ioc_reset - send doorbell reset - * @ioc: per adapter object - * @reset_type: currently only supports: MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET - * @timeout: timeout in second - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_send_ioc_reset(struct MPT3SAS_ADAPTER *ioc, u8 reset_type, int timeout, - int sleep_flag) -{ - u32 ioc_state; - int r = 0; - - if (reset_type != MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET) { - pr_err(MPT3SAS_FMT "%s: unknown reset_type\n", - ioc->name, __func__); - return -EFAULT; - } - - if (!(ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY)) - return -EFAULT; - - pr_info(MPT3SAS_FMT "sending message unit reset !!\n", ioc->name); - - writel(reset_type << MPI2_DOORBELL_FUNCTION_SHIFT, - &ioc->chip->Doorbell); - if ((_base_wait_for_doorbell_ack(ioc, 15, sleep_flag))) { - r = -EFAULT; - goto out; - } - ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, - timeout, sleep_flag); - if (ioc_state) { - pr_err(MPT3SAS_FMT - "%s: failed going to ready state (ioc_state=0x%x)\n", - ioc->name, __func__, ioc_state); - r = -EFAULT; - goto out; - } - out: - pr_info(MPT3SAS_FMT "message unit reset: %s\n", - ioc->name, ((r == 0) ? "SUCCESS" : "FAILED")); - return r; -} - -/** - * _base_handshake_req_reply_wait - send request thru doorbell interface - * @ioc: per adapter object - * @request_bytes: request length - * @request: pointer having request payload - * @reply_bytes: reply length - * @reply: pointer to reply payload - * @timeout: timeout in second - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes, - u32 *request, int reply_bytes, u16 *reply, int timeout, int sleep_flag) -{ - MPI2DefaultReply_t *default_reply = (MPI2DefaultReply_t *)reply; - int i; - u8 failed; - u16 dummy; - __le32 *mfp; - - /* make sure doorbell is not in use */ - if ((readl(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) { - pr_err(MPT3SAS_FMT - "doorbell is in use (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - - /* clear pending doorbell interrupts from previous state changes */ - if (readl(&ioc->chip->HostInterruptStatus) & - MPI2_HIS_IOC2SYS_DB_STATUS) - writel(0, &ioc->chip->HostInterruptStatus); - - /* send message to ioc */ - writel(((MPI2_FUNCTION_HANDSHAKE<chip->Doorbell); - - if ((_base_wait_for_doorbell_int(ioc, 5, NO_SLEEP))) { - pr_err(MPT3SAS_FMT - "doorbell handshake int failed (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - writel(0, &ioc->chip->HostInterruptStatus); - - if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) { - pr_err(MPT3SAS_FMT - "doorbell handshake ack failed (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - - /* send message 32-bits at a time */ - for (i = 0, failed = 0; i < request_bytes/4 && !failed; i++) { - writel(cpu_to_le32(request[i]), &ioc->chip->Doorbell); - if ((_base_wait_for_doorbell_ack(ioc, 5, sleep_flag))) - failed = 1; - } - - if (failed) { - pr_err(MPT3SAS_FMT - "doorbell handshake sending request failed (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - - /* now wait for the reply */ - if ((_base_wait_for_doorbell_int(ioc, timeout, sleep_flag))) { - pr_err(MPT3SAS_FMT - "doorbell handshake int failed (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - - /* read the first two 16-bits, it gives the total length of the reply */ - reply[0] = le16_to_cpu(readl(&ioc->chip->Doorbell) - & MPI2_DOORBELL_DATA_MASK); - writel(0, &ioc->chip->HostInterruptStatus); - if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) { - pr_err(MPT3SAS_FMT - "doorbell handshake int failed (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - reply[1] = le16_to_cpu(readl(&ioc->chip->Doorbell) - & MPI2_DOORBELL_DATA_MASK); - writel(0, &ioc->chip->HostInterruptStatus); - - for (i = 2; i < default_reply->MsgLength * 2; i++) { - if ((_base_wait_for_doorbell_int(ioc, 5, sleep_flag))) { - pr_err(MPT3SAS_FMT - "doorbell handshake int failed (line=%d)\n", - ioc->name, __LINE__); - return -EFAULT; - } - if (i >= reply_bytes/2) /* overflow case */ - dummy = readl(&ioc->chip->Doorbell); - else - reply[i] = le16_to_cpu(readl(&ioc->chip->Doorbell) - & MPI2_DOORBELL_DATA_MASK); - writel(0, &ioc->chip->HostInterruptStatus); - } - - _base_wait_for_doorbell_int(ioc, 5, sleep_flag); - if (_base_wait_for_doorbell_not_used(ioc, 5, sleep_flag) != 0) { - dhsprintk(ioc, pr_info(MPT3SAS_FMT - "doorbell is in use (line=%d)\n", ioc->name, __LINE__)); - } - writel(0, &ioc->chip->HostInterruptStatus); - - if (ioc->logging_level & MPT_DEBUG_INIT) { - mfp = (__le32 *)reply; - pr_info("\toffset:data\n"); - for (i = 0; i < reply_bytes/4; i++) - pr_info("\t[0x%02x]:%08x\n", i*4, - le32_to_cpu(mfp[i])); - } - return 0; -} - -/** - * mpt3sas_base_sas_iounit_control - send sas iounit control to FW - * @ioc: per adapter object - * @mpi_reply: the reply payload from FW - * @mpi_request: the request payload sent to FW - * - * The SAS IO Unit Control Request message allows the host to perform low-level - * operations, such as resets on the PHYs of the IO Unit, also allows the host - * to obtain the IOC assigned device handles for a device if it has other - * identifying information about the device, in addition allows the host to - * remove IOC resources associated with the device. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc, - Mpi2SasIoUnitControlReply_t *mpi_reply, - Mpi2SasIoUnitControlRequest_t *mpi_request) -{ - u16 smid; - u32 ioc_state; - unsigned long timeleft; - bool issue_reset = false; - int rc; - void *request; - u16 wait_state_count; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - mutex_lock(&ioc->base_cmds.mutex); - - if (ioc->base_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: base_cmd in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, __func__, wait_state_count); - } - - smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - rc = 0; - ioc->base_cmds.status = MPT3_CMD_PENDING; - request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->base_cmds.smid = smid; - memcpy(request, mpi_request, sizeof(Mpi2SasIoUnitControlRequest_t)); - if (mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || - mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) - ioc->ioc_link_reset_in_progress = 1; - init_completion(&ioc->base_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, - msecs_to_jiffies(10000)); - if ((mpi_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET || - mpi_request->Operation == MPI2_SAS_OP_PHY_LINK_RESET) && - ioc->ioc_link_reset_in_progress) - ioc->ioc_link_reset_in_progress = 0; - if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SasIoUnitControlRequest_t)/4); - if (!(ioc->base_cmds.status & MPT3_CMD_RESET)) - issue_reset = true; - goto issue_host_reset; - } - if (ioc->base_cmds.status & MPT3_CMD_REPLY_VALID) - memcpy(mpi_reply, ioc->base_cmds.reply, - sizeof(Mpi2SasIoUnitControlReply_t)); - else - memset(mpi_reply, 0, sizeof(Mpi2SasIoUnitControlReply_t)); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - goto out; - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - rc = -EFAULT; - out: - mutex_unlock(&ioc->base_cmds.mutex); - return rc; -} - -/** - * mpt3sas_base_scsi_enclosure_processor - sending request to sep device - * @ioc: per adapter object - * @mpi_reply: the reply payload from FW - * @mpi_request: the request payload sent to FW - * - * The SCSI Enclosure Processor request message causes the IOC to - * communicate with SES devices to control LED status signals. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, - Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request) -{ - u16 smid; - u32 ioc_state; - unsigned long timeleft; - bool issue_reset = false; - int rc; - void *request; - u16 wait_state_count; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - mutex_lock(&ioc->base_cmds.mutex); - - if (ioc->base_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: base_cmd in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, - __func__, wait_state_count); - } - - smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - rc = 0; - ioc->base_cmds.status = MPT3_CMD_PENDING; - request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->base_cmds.smid = smid; - memcpy(request, mpi_request, sizeof(Mpi2SepReply_t)); - init_completion(&ioc->base_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, - msecs_to_jiffies(10000)); - if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SepRequest_t)/4); - if (!(ioc->base_cmds.status & MPT3_CMD_RESET)) - issue_reset = false; - goto issue_host_reset; - } - if (ioc->base_cmds.status & MPT3_CMD_REPLY_VALID) - memcpy(mpi_reply, ioc->base_cmds.reply, - sizeof(Mpi2SepReply_t)); - else - memset(mpi_reply, 0, sizeof(Mpi2SepReply_t)); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - goto out; - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - rc = -EFAULT; - out: - mutex_unlock(&ioc->base_cmds.mutex); - return rc; -} - -/** - * _base_get_port_facts - obtain port facts reply and save in ioc - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_get_port_facts(struct MPT3SAS_ADAPTER *ioc, int port, int sleep_flag) -{ - Mpi2PortFactsRequest_t mpi_request; - Mpi2PortFactsReply_t mpi_reply; - struct mpt3sas_port_facts *pfacts; - int mpi_reply_sz, mpi_request_sz, r; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - mpi_reply_sz = sizeof(Mpi2PortFactsReply_t); - mpi_request_sz = sizeof(Mpi2PortFactsRequest_t); - memset(&mpi_request, 0, mpi_request_sz); - mpi_request.Function = MPI2_FUNCTION_PORT_FACTS; - mpi_request.PortNumber = port; - r = _base_handshake_req_reply_wait(ioc, mpi_request_sz, - (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP); - - if (r != 0) { - pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", - ioc->name, __func__, r); - return r; - } - - pfacts = &ioc->pfacts[port]; - memset(pfacts, 0, sizeof(struct mpt3sas_port_facts)); - pfacts->PortNumber = mpi_reply.PortNumber; - pfacts->VP_ID = mpi_reply.VP_ID; - pfacts->VF_ID = mpi_reply.VF_ID; - pfacts->MaxPostedCmdBuffers = - le16_to_cpu(mpi_reply.MaxPostedCmdBuffers); - - return 0; -} - -/** - * _base_wait_for_iocstate - Wait until the card is in READY or OPERATIONAL - * @ioc: per adapter object - * @timeout: - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_wait_for_iocstate(struct MPT3SAS_ADAPTER *ioc, int timeout, - int sleep_flag) -{ - u32 ioc_state; - int rc; - - dinitprintk(ioc, printk(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - if (ioc->pci_error_recovery) { - dfailprintk(ioc, printk(MPT3SAS_FMT - "%s: host in pci error recovery\n", ioc->name, __func__)); - return -EFAULT; - } - - ioc_state = mpt3sas_base_get_iocstate(ioc, 0); - dhsprintk(ioc, printk(MPT3SAS_FMT "%s: ioc_state(0x%08x)\n", - ioc->name, __func__, ioc_state)); - - if (((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY) || - (ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL) - return 0; - - if (ioc_state & MPI2_DOORBELL_USED) { - dhsprintk(ioc, printk(MPT3SAS_FMT - "unexpected doorbell active!\n", ioc->name)); - goto issue_diag_reset; - } - - if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { - mpt3sas_base_fault_info(ioc, ioc_state & - MPI2_DOORBELL_DATA_MASK); - goto issue_diag_reset; - } - - ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, - timeout, sleep_flag); - if (ioc_state) { - dfailprintk(ioc, printk(MPT3SAS_FMT - "%s: failed going to ready state (ioc_state=0x%x)\n", - ioc->name, __func__, ioc_state)); - return -EFAULT; - } - - issue_diag_reset: - rc = _base_diag_reset(ioc, sleep_flag); - return rc; -} - -/** - * _base_get_ioc_facts - obtain ioc facts reply and save in ioc - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_get_ioc_facts(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - Mpi2IOCFactsRequest_t mpi_request; - Mpi2IOCFactsReply_t mpi_reply; - struct mpt3sas_facts *facts; - int mpi_reply_sz, mpi_request_sz, r; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - r = _base_wait_for_iocstate(ioc, 10, sleep_flag); - if (r) { - dfailprintk(ioc, printk(MPT3SAS_FMT - "%s: failed getting to correct state\n", - ioc->name, __func__)); - return r; - } - mpi_reply_sz = sizeof(Mpi2IOCFactsReply_t); - mpi_request_sz = sizeof(Mpi2IOCFactsRequest_t); - memset(&mpi_request, 0, mpi_request_sz); - mpi_request.Function = MPI2_FUNCTION_IOC_FACTS; - r = _base_handshake_req_reply_wait(ioc, mpi_request_sz, - (u32 *)&mpi_request, mpi_reply_sz, (u16 *)&mpi_reply, 5, CAN_SLEEP); - - if (r != 0) { - pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", - ioc->name, __func__, r); - return r; - } - - facts = &ioc->facts; - memset(facts, 0, sizeof(struct mpt3sas_facts)); - facts->MsgVersion = le16_to_cpu(mpi_reply.MsgVersion); - facts->HeaderVersion = le16_to_cpu(mpi_reply.HeaderVersion); - facts->VP_ID = mpi_reply.VP_ID; - facts->VF_ID = mpi_reply.VF_ID; - facts->IOCExceptions = le16_to_cpu(mpi_reply.IOCExceptions); - facts->MaxChainDepth = mpi_reply.MaxChainDepth; - facts->WhoInit = mpi_reply.WhoInit; - facts->NumberOfPorts = mpi_reply.NumberOfPorts; - facts->MaxMSIxVectors = mpi_reply.MaxMSIxVectors; - facts->RequestCredit = le16_to_cpu(mpi_reply.RequestCredit); - facts->MaxReplyDescriptorPostQueueDepth = - le16_to_cpu(mpi_reply.MaxReplyDescriptorPostQueueDepth); - facts->ProductID = le16_to_cpu(mpi_reply.ProductID); - facts->IOCCapabilities = le32_to_cpu(mpi_reply.IOCCapabilities); - if ((facts->IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID)) - ioc->ir_firmware = 1; - if ((facts->IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_RDPQ_ARRAY_CAPABLE)) - ioc->rdpq_array_capable = 1; - facts->FWVersion.Word = le32_to_cpu(mpi_reply.FWVersion.Word); - facts->IOCRequestFrameSize = - le16_to_cpu(mpi_reply.IOCRequestFrameSize); - facts->MaxInitiators = le16_to_cpu(mpi_reply.MaxInitiators); - facts->MaxTargets = le16_to_cpu(mpi_reply.MaxTargets); - ioc->shost->max_id = -1; - facts->MaxSasExpanders = le16_to_cpu(mpi_reply.MaxSasExpanders); - facts->MaxEnclosures = le16_to_cpu(mpi_reply.MaxEnclosures); - facts->ProtocolFlags = le16_to_cpu(mpi_reply.ProtocolFlags); - facts->HighPriorityCredit = - le16_to_cpu(mpi_reply.HighPriorityCredit); - facts->ReplyFrameSize = mpi_reply.ReplyFrameSize; - facts->MaxDevHandle = le16_to_cpu(mpi_reply.MaxDevHandle); - - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "hba queue depth(%d), max chains per io(%d)\n", - ioc->name, facts->RequestCredit, - facts->MaxChainDepth)); - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "request frame size(%d), reply frame size(%d)\n", ioc->name, - facts->IOCRequestFrameSize * 4, facts->ReplyFrameSize * 4)); - return 0; -} - -/** - * _base_send_ioc_init - send ioc_init to firmware - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_send_ioc_init(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - Mpi2IOCInitRequest_t mpi_request; - Mpi2IOCInitReply_t mpi_reply; - int i, r = 0; - struct timeval current_time; - u16 ioc_status; - u32 reply_post_free_array_sz = 0; - Mpi2IOCInitRDPQArrayEntry *reply_post_free_array = NULL; - dma_addr_t reply_post_free_array_dma; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - memset(&mpi_request, 0, sizeof(Mpi2IOCInitRequest_t)); - mpi_request.Function = MPI2_FUNCTION_IOC_INIT; - mpi_request.WhoInit = MPI2_WHOINIT_HOST_DRIVER; - mpi_request.VF_ID = 0; /* TODO */ - mpi_request.VP_ID = 0; - mpi_request.MsgVersion = cpu_to_le16(ioc->hba_mpi_version_belonged); - mpi_request.HeaderVersion = cpu_to_le16(MPI2_HEADER_VERSION); - - if (_base_is_controller_msix_enabled(ioc)) - mpi_request.HostMSIxVectors = ioc->reply_queue_count; - mpi_request.SystemRequestFrameSize = cpu_to_le16(ioc->request_sz/4); - mpi_request.ReplyDescriptorPostQueueDepth = - cpu_to_le16(ioc->reply_post_queue_depth); - mpi_request.ReplyFreeQueueDepth = - cpu_to_le16(ioc->reply_free_queue_depth); - - mpi_request.SenseBufferAddressHigh = - cpu_to_le32((u64)ioc->sense_dma >> 32); - mpi_request.SystemReplyAddressHigh = - cpu_to_le32((u64)ioc->reply_dma >> 32); - mpi_request.SystemRequestFrameBaseAddress = - cpu_to_le64((u64)ioc->request_dma); - mpi_request.ReplyFreeQueueAddress = - cpu_to_le64((u64)ioc->reply_free_dma); - - if (ioc->rdpq_array_enable) { - reply_post_free_array_sz = ioc->reply_queue_count * - sizeof(Mpi2IOCInitRDPQArrayEntry); - reply_post_free_array = pci_alloc_consistent(ioc->pdev, - reply_post_free_array_sz, &reply_post_free_array_dma); - if (!reply_post_free_array) { - pr_err(MPT3SAS_FMT - "reply_post_free_array: pci_alloc_consistent failed\n", - ioc->name); - r = -ENOMEM; - goto out; - } - memset(reply_post_free_array, 0, reply_post_free_array_sz); - for (i = 0; i < ioc->reply_queue_count; i++) - reply_post_free_array[i].RDPQBaseAddress = - cpu_to_le64( - (u64)ioc->reply_post[i].reply_post_free_dma); - mpi_request.MsgFlags = MPI2_IOCINIT_MSGFLAG_RDPQ_ARRAY_MODE; - mpi_request.ReplyDescriptorPostQueueAddress = - cpu_to_le64((u64)reply_post_free_array_dma); - } else { - mpi_request.ReplyDescriptorPostQueueAddress = - cpu_to_le64((u64)ioc->reply_post[0].reply_post_free_dma); - } - - /* This time stamp specifies number of milliseconds - * since epoch ~ midnight January 1, 1970. - */ - do_gettimeofday(¤t_time); - mpi_request.TimeStamp = cpu_to_le64((u64)current_time.tv_sec * 1000 + - (current_time.tv_usec / 1000)); - - if (ioc->logging_level & MPT_DEBUG_INIT) { - __le32 *mfp; - int i; - - mfp = (__le32 *)&mpi_request; - pr_info("\toffset:data\n"); - for (i = 0; i < sizeof(Mpi2IOCInitRequest_t)/4; i++) - pr_info("\t[0x%02x]:%08x\n", i*4, - le32_to_cpu(mfp[i])); - } - - r = _base_handshake_req_reply_wait(ioc, - sizeof(Mpi2IOCInitRequest_t), (u32 *)&mpi_request, - sizeof(Mpi2IOCInitReply_t), (u16 *)&mpi_reply, 10, - sleep_flag); - - if (r != 0) { - pr_err(MPT3SAS_FMT "%s: handshake failed (r=%d)\n", - ioc->name, __func__, r); - goto out; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS || - mpi_reply.IOCLogInfo) { - pr_err(MPT3SAS_FMT "%s: failed\n", ioc->name, __func__); - r = -EIO; - } - -out: - if (reply_post_free_array) - pci_free_consistent(ioc->pdev, reply_post_free_array_sz, - reply_post_free_array, - reply_post_free_array_dma); - return r; -} - -/** - * mpt3sas_port_enable_done - command completion routine for port enable - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_port_enable_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - u16 ioc_status; - - if (ioc->port_enable_cmds.status == MPT3_CMD_NOT_USED) - return 1; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (!mpi_reply) - return 1; - - if (mpi_reply->Function != MPI2_FUNCTION_PORT_ENABLE) - return 1; - - ioc->port_enable_cmds.status &= ~MPT3_CMD_PENDING; - ioc->port_enable_cmds.status |= MPT3_CMD_COMPLETE; - ioc->port_enable_cmds.status |= MPT3_CMD_REPLY_VALID; - memcpy(ioc->port_enable_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - ioc->port_enable_failed = 1; - - if (ioc->is_driver_loading) { - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { - mpt3sas_port_enable_complete(ioc); - return 1; - } else { - ioc->start_scan_failed = ioc_status; - ioc->start_scan = 0; - return 1; - } - } - complete(&ioc->port_enable_cmds.done); - return 1; -} - -/** - * _base_send_port_enable - send port_enable(discovery stuff) to firmware - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_send_port_enable(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - Mpi2PortEnableRequest_t *mpi_request; - Mpi2PortEnableReply_t *mpi_reply; - unsigned long timeleft; - int r = 0; - u16 smid; - u16 ioc_status; - - pr_info(MPT3SAS_FMT "sending port enable !!\n", ioc->name); - - if (ioc->port_enable_cmds.status & MPT3_CMD_PENDING) { - pr_err(MPT3SAS_FMT "%s: internal command already in use\n", - ioc->name, __func__); - return -EAGAIN; - } - - smid = mpt3sas_base_get_smid(ioc, ioc->port_enable_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - return -EAGAIN; - } - - ioc->port_enable_cmds.status = MPT3_CMD_PENDING; - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->port_enable_cmds.smid = smid; - memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); - mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; - - init_completion(&ioc->port_enable_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->port_enable_cmds.done, - 300*HZ); - if (!(ioc->port_enable_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2PortEnableRequest_t)/4); - if (ioc->port_enable_cmds.status & MPT3_CMD_RESET) - r = -EFAULT; - else - r = -ETIME; - goto out; - } - - mpi_reply = ioc->port_enable_cmds.reply; - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "%s: failed with (ioc_status=0x%08x)\n", - ioc->name, __func__, ioc_status); - r = -EFAULT; - goto out; - } - - out: - ioc->port_enable_cmds.status = MPT3_CMD_NOT_USED; - pr_info(MPT3SAS_FMT "port enable: %s\n", ioc->name, ((r == 0) ? - "SUCCESS" : "FAILED")); - return r; -} - -/** - * mpt3sas_port_enable - initiate firmware discovery (don't wait for reply) - * @ioc: per adapter object - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2PortEnableRequest_t *mpi_request; - u16 smid; - - pr_info(MPT3SAS_FMT "sending port enable !!\n", ioc->name); - - if (ioc->port_enable_cmds.status & MPT3_CMD_PENDING) { - pr_err(MPT3SAS_FMT "%s: internal command already in use\n", - ioc->name, __func__); - return -EAGAIN; - } - - smid = mpt3sas_base_get_smid(ioc, ioc->port_enable_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - return -EAGAIN; - } - - ioc->port_enable_cmds.status = MPT3_CMD_PENDING; - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->port_enable_cmds.smid = smid; - memset(mpi_request, 0, sizeof(Mpi2PortEnableRequest_t)); - mpi_request->Function = MPI2_FUNCTION_PORT_ENABLE; - - mpt3sas_base_put_smid_default(ioc, smid); - return 0; -} - -/** - * _base_determine_wait_on_discovery - desposition - * @ioc: per adapter object - * - * Decide whether to wait on discovery to complete. Used to either - * locate boot device, or report volumes ahead of physical devices. - * - * Returns 1 for wait, 0 for don't wait - */ -static int -_base_determine_wait_on_discovery(struct MPT3SAS_ADAPTER *ioc) -{ - /* We wait for discovery to complete if IR firmware is loaded. - * The sas topology events arrive before PD events, so we need time to - * turn on the bit in ioc->pd_handles to indicate PD - * Also, it maybe required to report Volumes ahead of physical - * devices when MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING is set. - */ - if (ioc->ir_firmware) - return 1; - - /* if no Bios, then we don't need to wait */ - if (!ioc->bios_pg3.BiosVersion) - return 0; - - /* Bios is present, then we drop down here. - * - * If there any entries in the Bios Page 2, then we wait - * for discovery to complete. - */ - - /* Current Boot Device */ - if ((ioc->bios_pg2.CurrentBootDeviceForm & - MPI2_BIOSPAGE2_FORM_MASK) == - MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED && - /* Request Boot Device */ - (ioc->bios_pg2.ReqBootDeviceForm & - MPI2_BIOSPAGE2_FORM_MASK) == - MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED && - /* Alternate Request Boot Device */ - (ioc->bios_pg2.ReqAltBootDeviceForm & - MPI2_BIOSPAGE2_FORM_MASK) == - MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED) - return 0; - - return 1; -} - -/** - * _base_unmask_events - turn on notification for this event - * @ioc: per adapter object - * @event: firmware event - * - * The mask is stored in ioc->event_masks. - */ -static void -_base_unmask_events(struct MPT3SAS_ADAPTER *ioc, u16 event) -{ - u32 desired_event; - - if (event >= 128) - return; - - desired_event = (1 << (event % 32)); - - if (event < 32) - ioc->event_masks[0] &= ~desired_event; - else if (event < 64) - ioc->event_masks[1] &= ~desired_event; - else if (event < 96) - ioc->event_masks[2] &= ~desired_event; - else if (event < 128) - ioc->event_masks[3] &= ~desired_event; -} - -/** - * _base_event_notification - send event notification - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_event_notification(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - Mpi2EventNotificationRequest_t *mpi_request; - unsigned long timeleft; - u16 smid; - int r = 0; - int i; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - if (ioc->base_cmds.status & MPT3_CMD_PENDING) { - pr_err(MPT3SAS_FMT "%s: internal command already in use\n", - ioc->name, __func__); - return -EAGAIN; - } - - smid = mpt3sas_base_get_smid(ioc, ioc->base_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - return -EAGAIN; - } - ioc->base_cmds.status = MPT3_CMD_PENDING; - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->base_cmds.smid = smid; - memset(mpi_request, 0, sizeof(Mpi2EventNotificationRequest_t)); - mpi_request->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) - mpi_request->EventMasks[i] = - cpu_to_le32(ioc->event_masks[i]); - init_completion(&ioc->base_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->base_cmds.done, 30*HZ); - if (!(ioc->base_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2EventNotificationRequest_t)/4); - if (ioc->base_cmds.status & MPT3_CMD_RESET) - r = -EFAULT; - else - r = -ETIME; - } else - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s: complete\n", - ioc->name, __func__)); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - return r; -} - -/** - * mpt3sas_base_validate_event_type - validating event types - * @ioc: per adapter object - * @event: firmware event - * - * This will turn on firmware event notification when application - * ask for that event. We don't mask events that are already enabled. - */ -void -mpt3sas_base_validate_event_type(struct MPT3SAS_ADAPTER *ioc, u32 *event_type) -{ - int i, j; - u32 event_mask, desired_event; - u8 send_update_to_fw; - - for (i = 0, send_update_to_fw = 0; i < - MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) { - event_mask = ~event_type[i]; - desired_event = 1; - for (j = 0; j < 32; j++) { - if (!(event_mask & desired_event) && - (ioc->event_masks[i] & desired_event)) { - ioc->event_masks[i] &= ~desired_event; - send_update_to_fw = 1; - } - desired_event = (desired_event << 1); - } - } - - if (!send_update_to_fw) - return; - - mutex_lock(&ioc->base_cmds.mutex); - _base_event_notification(ioc, CAN_SLEEP); - mutex_unlock(&ioc->base_cmds.mutex); -} - -/** - * _base_diag_reset - the "big hammer" start of day reset - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_diag_reset(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - u32 host_diagnostic; - u32 ioc_state; - u32 count; - u32 hcb_size; - - pr_info(MPT3SAS_FMT "sending diag reset !!\n", ioc->name); - - drsprintk(ioc, pr_info(MPT3SAS_FMT "clear interrupts\n", - ioc->name)); - - count = 0; - do { - /* Write magic sequence to WriteSequence register - * Loop until in diagnostic mode - */ - drsprintk(ioc, pr_info(MPT3SAS_FMT - "write magic sequence\n", ioc->name)); - writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence); - writel(MPI2_WRSEQ_1ST_KEY_VALUE, &ioc->chip->WriteSequence); - writel(MPI2_WRSEQ_2ND_KEY_VALUE, &ioc->chip->WriteSequence); - writel(MPI2_WRSEQ_3RD_KEY_VALUE, &ioc->chip->WriteSequence); - writel(MPI2_WRSEQ_4TH_KEY_VALUE, &ioc->chip->WriteSequence); - writel(MPI2_WRSEQ_5TH_KEY_VALUE, &ioc->chip->WriteSequence); - writel(MPI2_WRSEQ_6TH_KEY_VALUE, &ioc->chip->WriteSequence); - - /* wait 100 msec */ - if (sleep_flag == CAN_SLEEP) - msleep(100); - else - mdelay(100); - - if (count++ > 20) - goto out; - - host_diagnostic = readl(&ioc->chip->HostDiagnostic); - drsprintk(ioc, pr_info(MPT3SAS_FMT - "wrote magic sequence: count(%d), host_diagnostic(0x%08x)\n", - ioc->name, count, host_diagnostic)); - - } while ((host_diagnostic & MPI2_DIAG_DIAG_WRITE_ENABLE) == 0); - - hcb_size = readl(&ioc->chip->HCBSize); - - drsprintk(ioc, pr_info(MPT3SAS_FMT "diag reset: issued\n", - ioc->name)); - writel(host_diagnostic | MPI2_DIAG_RESET_ADAPTER, - &ioc->chip->HostDiagnostic); - - /*This delay allows the chip PCIe hardware time to finish reset tasks*/ - if (sleep_flag == CAN_SLEEP) - msleep(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000); - else - mdelay(MPI2_HARD_RESET_PCIE_FIRST_READ_DELAY_MICRO_SEC/1000); - - /* Approximately 300 second max wait */ - for (count = 0; count < (300000000 / - MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC); count++) { - - host_diagnostic = readl(&ioc->chip->HostDiagnostic); - - if (host_diagnostic == 0xFFFFFFFF) - goto out; - if (!(host_diagnostic & MPI2_DIAG_RESET_ADAPTER)) - break; - - /* Wait to pass the second read delay window */ - if (sleep_flag == CAN_SLEEP) - msleep(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC - / 1000); - else - mdelay(MPI2_HARD_RESET_PCIE_SECOND_READ_DELAY_MICRO_SEC - / 1000); - } - - if (host_diagnostic & MPI2_DIAG_HCB_MODE) { - - drsprintk(ioc, pr_info(MPT3SAS_FMT - "restart the adapter assuming the HCB Address points to good F/W\n", - ioc->name)); - host_diagnostic &= ~MPI2_DIAG_BOOT_DEVICE_SELECT_MASK; - host_diagnostic |= MPI2_DIAG_BOOT_DEVICE_SELECT_HCDW; - writel(host_diagnostic, &ioc->chip->HostDiagnostic); - - drsprintk(ioc, pr_info(MPT3SAS_FMT - "re-enable the HCDW\n", ioc->name)); - writel(hcb_size | MPI2_HCB_SIZE_HCB_ENABLE, - &ioc->chip->HCBSize); - } - - drsprintk(ioc, pr_info(MPT3SAS_FMT "restart the adapter\n", - ioc->name)); - writel(host_diagnostic & ~MPI2_DIAG_HOLD_IOC_RESET, - &ioc->chip->HostDiagnostic); - - drsprintk(ioc, pr_info(MPT3SAS_FMT - "disable writes to the diagnostic register\n", ioc->name)); - writel(MPI2_WRSEQ_FLUSH_KEY_VALUE, &ioc->chip->WriteSequence); - - drsprintk(ioc, pr_info(MPT3SAS_FMT - "Wait for FW to go to the READY state\n", ioc->name)); - ioc_state = _base_wait_on_iocstate(ioc, MPI2_IOC_STATE_READY, 20, - sleep_flag); - if (ioc_state) { - pr_err(MPT3SAS_FMT - "%s: failed going to ready state (ioc_state=0x%x)\n", - ioc->name, __func__, ioc_state); - goto out; - } - - pr_info(MPT3SAS_FMT "diag reset: SUCCESS\n", ioc->name); - return 0; - - out: - pr_err(MPT3SAS_FMT "diag reset: FAILED\n", ioc->name); - return -EFAULT; -} - -/** - * _base_make_ioc_ready - put controller in READY state - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * @type: FORCE_BIG_HAMMER or SOFT_RESET - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_make_ioc_ready(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, - enum reset_type type) -{ - u32 ioc_state; - int rc; - int count; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - if (ioc->pci_error_recovery) - return 0; - - ioc_state = mpt3sas_base_get_iocstate(ioc, 0); - dhsprintk(ioc, pr_info(MPT3SAS_FMT "%s: ioc_state(0x%08x)\n", - ioc->name, __func__, ioc_state)); - - /* if in RESET state, it should move to READY state shortly */ - count = 0; - if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_RESET) { - while ((ioc_state & MPI2_IOC_STATE_MASK) != - MPI2_IOC_STATE_READY) { - if (count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed going to ready state (ioc_state=0x%x)\n", - ioc->name, __func__, ioc_state); - return -EFAULT; - } - if (sleep_flag == CAN_SLEEP) - ssleep(1); - else - mdelay(1000); - ioc_state = mpt3sas_base_get_iocstate(ioc, 0); - } - } - - if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_READY) - return 0; - - if (ioc_state & MPI2_DOORBELL_USED) { - dhsprintk(ioc, pr_info(MPT3SAS_FMT - "unexpected doorbell active!\n", - ioc->name)); - goto issue_diag_reset; - } - - if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { - mpt3sas_base_fault_info(ioc, ioc_state & - MPI2_DOORBELL_DATA_MASK); - goto issue_diag_reset; - } - - if (type == FORCE_BIG_HAMMER) - goto issue_diag_reset; - - if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_OPERATIONAL) - if (!(_base_send_ioc_reset(ioc, - MPI2_FUNCTION_IOC_MESSAGE_UNIT_RESET, 15, CAN_SLEEP))) { - return 0; - } - - issue_diag_reset: - rc = _base_diag_reset(ioc, CAN_SLEEP); - return rc; -} - -/** - * _base_make_ioc_operational - put controller in OPERATIONAL state - * @ioc: per adapter object - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * Returns 0 for success, non-zero for failure. - */ -static int -_base_make_ioc_operational(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - int r, i, index; - unsigned long flags; - u32 reply_address; - u16 smid; - struct _tr_list *delayed_tr, *delayed_tr_next; - u8 hide_flag; - struct adapter_reply_queue *reply_q; - Mpi2ReplyDescriptorsUnion_t *reply_post_free_contig; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - /* clean the delayed target reset list */ - list_for_each_entry_safe(delayed_tr, delayed_tr_next, - &ioc->delayed_tr_list, list) { - list_del(&delayed_tr->list); - kfree(delayed_tr); - } - - - list_for_each_entry_safe(delayed_tr, delayed_tr_next, - &ioc->delayed_tr_volume_list, list) { - list_del(&delayed_tr->list); - kfree(delayed_tr); - } - - /* initialize the scsi lookup free list */ - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - INIT_LIST_HEAD(&ioc->free_list); - smid = 1; - for (i = 0; i < ioc->scsiio_depth; i++, smid++) { - INIT_LIST_HEAD(&ioc->scsi_lookup[i].chain_list); - ioc->scsi_lookup[i].cb_idx = 0xFF; - ioc->scsi_lookup[i].smid = smid; - ioc->scsi_lookup[i].scmd = NULL; - ioc->scsi_lookup[i].direct_io = 0; - list_add_tail(&ioc->scsi_lookup[i].tracker_list, - &ioc->free_list); - } - - /* hi-priority queue */ - INIT_LIST_HEAD(&ioc->hpr_free_list); - smid = ioc->hi_priority_smid; - for (i = 0; i < ioc->hi_priority_depth; i++, smid++) { - ioc->hpr_lookup[i].cb_idx = 0xFF; - ioc->hpr_lookup[i].smid = smid; - list_add_tail(&ioc->hpr_lookup[i].tracker_list, - &ioc->hpr_free_list); - } - - /* internal queue */ - INIT_LIST_HEAD(&ioc->internal_free_list); - smid = ioc->internal_smid; - for (i = 0; i < ioc->internal_depth; i++, smid++) { - ioc->internal_lookup[i].cb_idx = 0xFF; - ioc->internal_lookup[i].smid = smid; - list_add_tail(&ioc->internal_lookup[i].tracker_list, - &ioc->internal_free_list); - } - - /* chain pool */ - INIT_LIST_HEAD(&ioc->free_chain_list); - for (i = 0; i < ioc->chain_depth; i++) - list_add_tail(&ioc->chain_lookup[i].tracker_list, - &ioc->free_chain_list); - - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - - /* initialize Reply Free Queue */ - for (i = 0, reply_address = (u32)ioc->reply_dma ; - i < ioc->reply_free_queue_depth ; i++, reply_address += - ioc->reply_sz) - ioc->reply_free[i] = cpu_to_le32(reply_address); - - /* initialize reply queues */ - if (ioc->is_driver_loading) - _base_assign_reply_queues(ioc); - - /* initialize Reply Post Free Queue */ - index = 0; - reply_post_free_contig = ioc->reply_post[0].reply_post_free; - list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { - /* - * If RDPQ is enabled, switch to the next allocation. - * Otherwise advance within the contiguous region. - */ - if (ioc->rdpq_array_enable) { - reply_q->reply_post_free = - ioc->reply_post[index++].reply_post_free; - } else { - reply_q->reply_post_free = reply_post_free_contig; - reply_post_free_contig += ioc->reply_post_queue_depth; - } - - reply_q->reply_post_host_index = 0; - for (i = 0; i < ioc->reply_post_queue_depth; i++) - reply_q->reply_post_free[i].Words = - cpu_to_le64(ULLONG_MAX); - if (!_base_is_controller_msix_enabled(ioc)) - goto skip_init_reply_post_free_queue; - } - skip_init_reply_post_free_queue: - - r = _base_send_ioc_init(ioc, sleep_flag); - if (r) - return r; - - /* initialize reply free host index */ - ioc->reply_free_host_index = ioc->reply_free_queue_depth - 1; - writel(ioc->reply_free_host_index, &ioc->chip->ReplyFreeHostIndex); - - /* initialize reply post host index */ - list_for_each_entry(reply_q, &ioc->reply_queue_list, list) { - if (ioc->msix96_vector) - writel((reply_q->msix_index & 7)<< - MPI2_RPHI_MSIX_INDEX_SHIFT, - ioc->replyPostRegisterIndex[reply_q->msix_index/8]); - else - writel(reply_q->msix_index << - MPI2_RPHI_MSIX_INDEX_SHIFT, - &ioc->chip->ReplyPostHostIndex); - - if (!_base_is_controller_msix_enabled(ioc)) - goto skip_init_reply_post_host_index; - } - - skip_init_reply_post_host_index: - - _base_unmask_interrupts(ioc); - r = _base_event_notification(ioc, sleep_flag); - if (r) - return r; - - if (sleep_flag == CAN_SLEEP) - _base_static_config_pages(ioc); - - - if (ioc->is_driver_loading) { - - if (ioc->is_warpdrive && ioc->manu_pg10.OEMIdentifier - == 0x80) { - hide_flag = (u8) ( - le32_to_cpu(ioc->manu_pg10.OEMSpecificFlags0) & - MFG_PAGE10_HIDE_SSDS_MASK); - if (hide_flag != MFG_PAGE10_HIDE_SSDS_MASK) - ioc->mfg_pg10_hide_flag = hide_flag; - } - - ioc->wait_for_discovery_to_complete = - _base_determine_wait_on_discovery(ioc); - - return r; /* scan_start and scan_finished support */ - } - - r = _base_send_port_enable(ioc, sleep_flag); - if (r) - return r; - - return r; -} - -/** - * mpt3sas_base_free_resources - free resources controller resources - * @ioc: per adapter object - * - * Return nothing. - */ -void -mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc) -{ - dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - /* synchronizing freeing resource with pci_access_mutex lock */ - mutex_lock(&ioc->pci_access_mutex); - if (ioc->chip_phys && ioc->chip) { - _base_mask_interrupts(ioc); - ioc->shost_recovery = 1; - _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); - ioc->shost_recovery = 0; - } - - mpt3sas_base_unmap_resources(ioc); - mutex_unlock(&ioc->pci_access_mutex); - return; -} - -/** - * mpt3sas_base_attach - attach controller instance - * @ioc: per adapter object - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc) -{ - int r, i; - int cpu_id, last_cpu_id = 0; - - dinitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - /* setup cpu_msix_table */ - ioc->cpu_count = num_online_cpus(); - for_each_online_cpu(cpu_id) - last_cpu_id = cpu_id; - ioc->cpu_msix_table_sz = last_cpu_id + 1; - ioc->cpu_msix_table = kzalloc(ioc->cpu_msix_table_sz, GFP_KERNEL); - ioc->reply_queue_count = 1; - if (!ioc->cpu_msix_table) { - dfailprintk(ioc, pr_info(MPT3SAS_FMT - "allocation for cpu_msix_table failed!!!\n", - ioc->name)); - r = -ENOMEM; - goto out_free_resources; - } - - if (ioc->is_warpdrive) { - ioc->reply_post_host_index = kcalloc(ioc->cpu_msix_table_sz, - sizeof(resource_size_t *), GFP_KERNEL); - if (!ioc->reply_post_host_index) { - dfailprintk(ioc, pr_info(MPT3SAS_FMT "allocation " - "for cpu_msix_table failed!!!\n", ioc->name)); - r = -ENOMEM; - goto out_free_resources; - } - } - - ioc->rdpq_array_enable_assigned = 0; - ioc->dma_mask = 0; - r = mpt3sas_base_map_resources(ioc); - if (r) - goto out_free_resources; - - pci_set_drvdata(ioc->pdev, ioc->shost); - r = _base_get_ioc_facts(ioc, CAN_SLEEP); - if (r) - goto out_free_resources; - - switch (ioc->hba_mpi_version_belonged) { - case MPI2_VERSION: - ioc->build_sg_scmd = &_base_build_sg_scmd; - ioc->build_sg = &_base_build_sg; - ioc->build_zero_len_sge = &_base_build_zero_len_sge; - break; - case MPI25_VERSION: - /* - * In SAS3.0, - * SCSI_IO, SMP_PASSTHRU, SATA_PASSTHRU, Target Assist, and - * Target Status - all require the IEEE formated scatter gather - * elements. - */ - ioc->build_sg_scmd = &_base_build_sg_scmd_ieee; - ioc->build_sg = &_base_build_sg_ieee; - ioc->build_zero_len_sge = &_base_build_zero_len_sge_ieee; - ioc->sge_size_ieee = sizeof(Mpi2IeeeSgeSimple64_t); - break; - } - - /* - * These function pointers for other requests that don't - * the require IEEE scatter gather elements. - * - * For example Configuration Pages and SAS IOUNIT Control don't. - */ - ioc->build_sg_mpi = &_base_build_sg; - ioc->build_zero_len_sge_mpi = &_base_build_zero_len_sge; - - r = _base_make_ioc_ready(ioc, CAN_SLEEP, SOFT_RESET); - if (r) - goto out_free_resources; - - ioc->pfacts = kcalloc(ioc->facts.NumberOfPorts, - sizeof(struct mpt3sas_port_facts), GFP_KERNEL); - if (!ioc->pfacts) { - r = -ENOMEM; - goto out_free_resources; - } - - for (i = 0 ; i < ioc->facts.NumberOfPorts; i++) { - r = _base_get_port_facts(ioc, i, CAN_SLEEP); - if (r) - goto out_free_resources; - } - - r = _base_allocate_memory_pools(ioc, CAN_SLEEP); - if (r) - goto out_free_resources; - - init_waitqueue_head(&ioc->reset_wq); - - /* allocate memory pd handle bitmask list */ - ioc->pd_handles_sz = (ioc->facts.MaxDevHandle / 8); - if (ioc->facts.MaxDevHandle % 8) - ioc->pd_handles_sz++; - ioc->pd_handles = kzalloc(ioc->pd_handles_sz, - GFP_KERNEL); - if (!ioc->pd_handles) { - r = -ENOMEM; - goto out_free_resources; - } - ioc->blocking_handles = kzalloc(ioc->pd_handles_sz, - GFP_KERNEL); - if (!ioc->blocking_handles) { - r = -ENOMEM; - goto out_free_resources; - } - - ioc->fwfault_debug = mpt3sas_fwfault_debug; - - /* base internal command bits */ - mutex_init(&ioc->base_cmds.mutex); - ioc->base_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - - /* port_enable command bits */ - ioc->port_enable_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->port_enable_cmds.status = MPT3_CMD_NOT_USED; - - /* transport internal command bits */ - ioc->transport_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->transport_cmds.status = MPT3_CMD_NOT_USED; - mutex_init(&ioc->transport_cmds.mutex); - - /* scsih internal command bits */ - ioc->scsih_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; - mutex_init(&ioc->scsih_cmds.mutex); - - /* task management internal command bits */ - ioc->tm_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->tm_cmds.status = MPT3_CMD_NOT_USED; - mutex_init(&ioc->tm_cmds.mutex); - - /* config page internal command bits */ - ioc->config_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->config_cmds.status = MPT3_CMD_NOT_USED; - mutex_init(&ioc->config_cmds.mutex); - - /* ctl module internal command bits */ - ioc->ctl_cmds.reply = kzalloc(ioc->reply_sz, GFP_KERNEL); - ioc->ctl_cmds.sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_KERNEL); - ioc->ctl_cmds.status = MPT3_CMD_NOT_USED; - mutex_init(&ioc->ctl_cmds.mutex); - - if (!ioc->base_cmds.reply || !ioc->transport_cmds.reply || - !ioc->scsih_cmds.reply || !ioc->tm_cmds.reply || - !ioc->config_cmds.reply || !ioc->ctl_cmds.reply || - !ioc->ctl_cmds.sense) { - r = -ENOMEM; - goto out_free_resources; - } - - for (i = 0; i < MPI2_EVENT_NOTIFY_EVENTMASK_WORDS; i++) - ioc->event_masks[i] = -1; - - /* here we enable the events we care about */ - _base_unmask_events(ioc, MPI2_EVENT_SAS_DISCOVERY); - _base_unmask_events(ioc, MPI2_EVENT_SAS_BROADCAST_PRIMITIVE); - _base_unmask_events(ioc, MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST); - _base_unmask_events(ioc, MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE); - _base_unmask_events(ioc, MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE); - _base_unmask_events(ioc, MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST); - _base_unmask_events(ioc, MPI2_EVENT_IR_VOLUME); - _base_unmask_events(ioc, MPI2_EVENT_IR_PHYSICAL_DISK); - _base_unmask_events(ioc, MPI2_EVENT_IR_OPERATION_STATUS); - _base_unmask_events(ioc, MPI2_EVENT_LOG_ENTRY_ADDED); - _base_unmask_events(ioc, MPI2_EVENT_TEMP_THRESHOLD); - - r = _base_make_ioc_operational(ioc, CAN_SLEEP); - if (r) - goto out_free_resources; - - ioc->non_operational_loop = 0; - return 0; - - out_free_resources: - - ioc->remove_host = 1; - - mpt3sas_base_free_resources(ioc); - _base_release_memory_pools(ioc); - pci_set_drvdata(ioc->pdev, NULL); - kfree(ioc->cpu_msix_table); - if (ioc->is_warpdrive) - kfree(ioc->reply_post_host_index); - kfree(ioc->pd_handles); - kfree(ioc->blocking_handles); - kfree(ioc->tm_cmds.reply); - kfree(ioc->transport_cmds.reply); - kfree(ioc->scsih_cmds.reply); - kfree(ioc->config_cmds.reply); - kfree(ioc->base_cmds.reply); - kfree(ioc->port_enable_cmds.reply); - kfree(ioc->ctl_cmds.reply); - kfree(ioc->ctl_cmds.sense); - kfree(ioc->pfacts); - ioc->ctl_cmds.reply = NULL; - ioc->base_cmds.reply = NULL; - ioc->tm_cmds.reply = NULL; - ioc->scsih_cmds.reply = NULL; - ioc->transport_cmds.reply = NULL; - ioc->config_cmds.reply = NULL; - ioc->pfacts = NULL; - return r; -} - - -/** - * mpt3sas_base_detach - remove controller instance - * @ioc: per adapter object - * - * Return nothing. - */ -void -mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc) -{ - dexitprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - mpt3sas_base_stop_watchdog(ioc); - mpt3sas_base_free_resources(ioc); - _base_release_memory_pools(ioc); - pci_set_drvdata(ioc->pdev, NULL); - kfree(ioc->cpu_msix_table); - if (ioc->is_warpdrive) - kfree(ioc->reply_post_host_index); - kfree(ioc->pd_handles); - kfree(ioc->blocking_handles); - kfree(ioc->pfacts); - kfree(ioc->ctl_cmds.reply); - kfree(ioc->ctl_cmds.sense); - kfree(ioc->base_cmds.reply); - kfree(ioc->port_enable_cmds.reply); - kfree(ioc->tm_cmds.reply); - kfree(ioc->transport_cmds.reply); - kfree(ioc->scsih_cmds.reply); - kfree(ioc->config_cmds.reply); -} - -/** - * _base_reset_handler - reset callback handler (for base) - * @ioc: per adapter object - * @reset_phase: phase - * - * The handler for doing any required cleanup or initialization. - * - * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET, - * MPT3_IOC_DONE_RESET - * - * Return nothing. - */ -static void -_base_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase) -{ - mpt3sas_scsih_reset_handler(ioc, reset_phase); - mpt3sas_ctl_reset_handler(ioc, reset_phase); - switch (reset_phase) { - case MPT3_IOC_PRE_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__)); - break; - case MPT3_IOC_AFTER_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__)); - if (ioc->transport_cmds.status & MPT3_CMD_PENDING) { - ioc->transport_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->transport_cmds.smid); - complete(&ioc->transport_cmds.done); - } - if (ioc->base_cmds.status & MPT3_CMD_PENDING) { - ioc->base_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->base_cmds.smid); - complete(&ioc->base_cmds.done); - } - if (ioc->port_enable_cmds.status & MPT3_CMD_PENDING) { - ioc->port_enable_failed = 1; - ioc->port_enable_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->port_enable_cmds.smid); - if (ioc->is_driver_loading) { - ioc->start_scan_failed = - MPI2_IOCSTATUS_INTERNAL_ERROR; - ioc->start_scan = 0; - ioc->port_enable_cmds.status = - MPT3_CMD_NOT_USED; - } else - complete(&ioc->port_enable_cmds.done); - } - if (ioc->config_cmds.status & MPT3_CMD_PENDING) { - ioc->config_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->config_cmds.smid); - ioc->config_cmds.smid = USHRT_MAX; - complete(&ioc->config_cmds.done); - } - break; - case MPT3_IOC_DONE_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__)); - break; - } -} - -/** - * _wait_for_commands_to_complete - reset controller - * @ioc: Pointer to MPT_ADAPTER structure - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * - * This function waiting(3s) for all pending commands to complete - * prior to putting controller in reset. - */ -static void -_wait_for_commands_to_complete(struct MPT3SAS_ADAPTER *ioc, int sleep_flag) -{ - u32 ioc_state; - unsigned long flags; - u16 i; - - ioc->pending_io_count = 0; - if (sleep_flag != CAN_SLEEP) - return; - - ioc_state = mpt3sas_base_get_iocstate(ioc, 0); - if ((ioc_state & MPI2_IOC_STATE_MASK) != MPI2_IOC_STATE_OPERATIONAL) - return; - - /* pending command count */ - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - for (i = 0; i < ioc->scsiio_depth; i++) - if (ioc->scsi_lookup[i].cb_idx != 0xFF) - ioc->pending_io_count++; - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - - if (!ioc->pending_io_count) - return; - - /* wait for pending commands to complete */ - wait_event_timeout(ioc->reset_wq, ioc->pending_io_count == 0, 10 * HZ); -} - -/** - * mpt3sas_base_hard_reset_handler - reset controller - * @ioc: Pointer to MPT_ADAPTER structure - * @sleep_flag: CAN_SLEEP or NO_SLEEP - * @type: FORCE_BIG_HAMMER or SOFT_RESET - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, - enum reset_type type) -{ - int r; - unsigned long flags; - u32 ioc_state; - u8 is_fault = 0, is_trigger = 0; - - dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, - __func__)); - - if (ioc->pci_error_recovery) { - pr_err(MPT3SAS_FMT "%s: pci error recovery reset\n", - ioc->name, __func__); - r = 0; - goto out_unlocked; - } - - if (mpt3sas_fwfault_debug) - mpt3sas_halt_firmware(ioc); - - /* TODO - What we really should be doing is pulling - * out all the code associated with NO_SLEEP; its never used. - * That is legacy code from mpt fusion driver, ported over. - * I will leave this BUG_ON here for now till its been resolved. - */ - BUG_ON(sleep_flag == NO_SLEEP); - - /* wait for an active reset in progress to complete */ - if (!mutex_trylock(&ioc->reset_in_progress_mutex)) { - do { - ssleep(1); - } while (ioc->shost_recovery == 1); - dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); - return ioc->ioc_reset_in_progress_status; - } - - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - ioc->shost_recovery = 1; - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); - - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) && - (!(ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED))) { - is_trigger = 1; - ioc_state = mpt3sas_base_get_iocstate(ioc, 0); - if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) - is_fault = 1; - } - _base_reset_handler(ioc, MPT3_IOC_PRE_RESET); - _wait_for_commands_to_complete(ioc, sleep_flag); - _base_mask_interrupts(ioc); - r = _base_make_ioc_ready(ioc, sleep_flag, type); - if (r) - goto out; - _base_reset_handler(ioc, MPT3_IOC_AFTER_RESET); - - /* If this hard reset is called while port enable is active, then - * there is no reason to call make_ioc_operational - */ - if (ioc->is_driver_loading && ioc->port_enable_failed) { - ioc->remove_host = 1; - r = -EFAULT; - goto out; - } - r = _base_get_ioc_facts(ioc, CAN_SLEEP); - if (r) - goto out; - - if (ioc->rdpq_array_enable && !ioc->rdpq_array_capable) - panic("%s: Issue occurred with flashing controller firmware." - "Please reboot the system and ensure that the correct" - " firmware version is running\n", ioc->name); - - r = _base_make_ioc_operational(ioc, sleep_flag); - if (!r) - _base_reset_handler(ioc, MPT3_IOC_DONE_RESET); - - out: - dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: %s\n", - ioc->name, __func__, ((r == 0) ? "SUCCESS" : "FAILED"))); - - spin_lock_irqsave(&ioc->ioc_reset_in_progress_lock, flags); - ioc->ioc_reset_in_progress_status = r; - ioc->shost_recovery = 0; - spin_unlock_irqrestore(&ioc->ioc_reset_in_progress_lock, flags); - ioc->ioc_reset_count++; - mutex_unlock(&ioc->reset_in_progress_mutex); - - out_unlocked: - if ((r == 0) && is_trigger) { - if (is_fault) - mpt3sas_trigger_master(ioc, MASTER_TRIGGER_FW_FAULT); - else - mpt3sas_trigger_master(ioc, - MASTER_TRIGGER_ADAPTER_RESET); - } - dtmprintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); - return r; -} diff --git a/addons/mpt3sas/src/4.4.180/mpt3sas_base.h b/addons/mpt3sas/src/4.4.180/mpt3sas_base.h deleted file mode 100644 index 63f5965a..00000000 --- a/addons/mpt3sas/src/4.4.180/mpt3sas_base.h +++ /dev/null @@ -1,1437 +0,0 @@ -/* - * This is the Fusion MPT base driver providing common API layer interface - * for access to MPT (Message Passing Technology) firmware. - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h - * Copyright (C) 2012-2014 LSI Corporation - * Copyright (C) 2013-2014 Avago Technologies - * (mailto: MPT-FusionLinux.pdl@avagotech.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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 MPT3SAS_BASE_H_INCLUDED -#define MPT3SAS_BASE_H_INCLUDED - -#include "mpi/mpi2_type.h" -#include "mpi/mpi2.h" -#include "mpi/mpi2_ioc.h" -#include "mpi/mpi2_cnfg.h" -#include "mpi/mpi2_init.h" -#include "mpi/mpi2_raid.h" -#include "mpi/mpi2_tool.h" -#include "mpi/mpi2_sas.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mpt3sas_debug.h" -#include "mpt3sas_trigger_diag.h" - -/* driver versioning info */ -#define MPT3SAS_DRIVER_NAME "mpt3sas" -#define MPT3SAS_AUTHOR "Avago Technologies " -#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver" -#define MPT3SAS_DRIVER_VERSION "09.102.00.00" -#define MPT3SAS_MAJOR_VERSION 9 -#define MPT3SAS_MINOR_VERSION 102 -#define MPT3SAS_BUILD_VERSION 0 -#define MPT3SAS_RELEASE_VERSION 00 - -#define MPT2SAS_DRIVER_NAME "mpt2sas" -#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver" -#define MPT2SAS_DRIVER_VERSION "20.102.00.00" -#define MPT2SAS_MAJOR_VERSION 20 -#define MPT2SAS_MINOR_VERSION 102 -#define MPT2SAS_BUILD_VERSION 0 -#define MPT2SAS_RELEASE_VERSION 00 - -/* - * Set MPT3SAS_SG_DEPTH value based on user input. - */ -#define MPT_MAX_PHYS_SEGMENTS SCSI_MAX_SG_SEGMENTS -#define MPT_MIN_PHYS_SEGMENTS 16 - -#ifdef CONFIG_SCSI_MPT3SAS_MAX_SGE -#define MPT3SAS_SG_DEPTH CONFIG_SCSI_MPT3SAS_MAX_SGE -#else -#define MPT3SAS_SG_DEPTH MPT_MAX_PHYS_SEGMENTS -#endif - -#ifdef CONFIG_SCSI_MPT2SAS_MAX_SGE -#define MPT2SAS_SG_DEPTH CONFIG_SCSI_MPT2SAS_MAX_SGE -#else -#define MPT2SAS_SG_DEPTH MPT_MAX_PHYS_SEGMENTS -#endif - -/* - * Generic Defines - */ -#define MPT3SAS_SATA_QUEUE_DEPTH 32 -#define MPT3SAS_SAS_QUEUE_DEPTH 254 -#define MPT3SAS_RAID_QUEUE_DEPTH 128 - -#define MPT_NAME_LENGTH 32 /* generic length of strings */ -#define MPT_STRING_LENGTH 64 - -#define MPT_MAX_CALLBACKS 32 - - -#define CAN_SLEEP 1 -#define NO_SLEEP 0 - -#define INTERNAL_CMDS_COUNT 10 /* reserved cmds */ - -#define MPI3_HIM_MASK 0xFFFFFFFF /* mask every bit*/ - -#define MPT3SAS_INVALID_DEVICE_HANDLE 0xFFFF - -/* - * reset phases - */ -#define MPT3_IOC_PRE_RESET 1 /* prior to host reset */ -#define MPT3_IOC_AFTER_RESET 2 /* just after host reset */ -#define MPT3_IOC_DONE_RESET 3 /* links re-initialized */ - -/* - * logging format - */ -#define MPT3SAS_FMT "%s: " - -/* - * WarpDrive Specific Log codes - */ - -#define MPT2_WARPDRIVE_LOGENTRY (0x8002) -#define MPT2_WARPDRIVE_LC_SSDT (0x41) -#define MPT2_WARPDRIVE_LC_SSDLW (0x43) -#define MPT2_WARPDRIVE_LC_SSDLF (0x44) -#define MPT2_WARPDRIVE_LC_BRMF (0x4D) - -/* - * per target private data - */ -#define MPT_TARGET_FLAGS_RAID_COMPONENT 0x01 -#define MPT_TARGET_FLAGS_VOLUME 0x02 -#define MPT_TARGET_FLAGS_DELETED 0x04 -#define MPT_TARGET_FASTPATH_IO 0x08 - -#define SAS2_PCI_DEVICE_B0_REVISION (0x01) -#define SAS3_PCI_DEVICE_C0_REVISION (0x02) - -/* - * Intel HBA branding - */ -#define MPT2SAS_INTEL_RMS25JB080_BRANDING \ - "Intel(R) Integrated RAID Module RMS25JB080" -#define MPT2SAS_INTEL_RMS25JB040_BRANDING \ - "Intel(R) Integrated RAID Module RMS25JB040" -#define MPT2SAS_INTEL_RMS25KB080_BRANDING \ - "Intel(R) Integrated RAID Module RMS25KB080" -#define MPT2SAS_INTEL_RMS25KB040_BRANDING \ - "Intel(R) Integrated RAID Module RMS25KB040" -#define MPT2SAS_INTEL_RMS25LB040_BRANDING \ - "Intel(R) Integrated RAID Module RMS25LB040" -#define MPT2SAS_INTEL_RMS25LB080_BRANDING \ - "Intel(R) Integrated RAID Module RMS25LB080" -#define MPT2SAS_INTEL_RMS2LL080_BRANDING \ - "Intel Integrated RAID Module RMS2LL080" -#define MPT2SAS_INTEL_RMS2LL040_BRANDING \ - "Intel Integrated RAID Module RMS2LL040" -#define MPT2SAS_INTEL_RS25GB008_BRANDING \ - "Intel(R) RAID Controller RS25GB008" -#define MPT2SAS_INTEL_SSD910_BRANDING \ - "Intel(R) SSD 910 Series" - -#define MPT3SAS_INTEL_RMS3JC080_BRANDING \ - "Intel(R) Integrated RAID Module RMS3JC080" -#define MPT3SAS_INTEL_RS3GC008_BRANDING \ - "Intel(R) RAID Controller RS3GC008" -#define MPT3SAS_INTEL_RS3FC044_BRANDING \ - "Intel(R) RAID Controller RS3FC044" -#define MPT3SAS_INTEL_RS3UC080_BRANDING \ - "Intel(R) RAID Controller RS3UC080" - -/* - * Intel HBA SSDIDs - */ -#define MPT2SAS_INTEL_RMS25JB080_SSDID 0x3516 -#define MPT2SAS_INTEL_RMS25JB040_SSDID 0x3517 -#define MPT2SAS_INTEL_RMS25KB080_SSDID 0x3518 -#define MPT2SAS_INTEL_RMS25KB040_SSDID 0x3519 -#define MPT2SAS_INTEL_RMS25LB040_SSDID 0x351A -#define MPT2SAS_INTEL_RMS25LB080_SSDID 0x351B -#define MPT2SAS_INTEL_RMS2LL080_SSDID 0x350E -#define MPT2SAS_INTEL_RMS2LL040_SSDID 0x350F -#define MPT2SAS_INTEL_RS25GB008_SSDID 0x3000 -#define MPT2SAS_INTEL_SSD910_SSDID 0x3700 - -#define MPT3SAS_INTEL_RMS3JC080_SSDID 0x3521 -#define MPT3SAS_INTEL_RS3GC008_SSDID 0x3522 -#define MPT3SAS_INTEL_RS3FC044_SSDID 0x3523 -#define MPT3SAS_INTEL_RS3UC080_SSDID 0x3524 - -/* - * Dell HBA branding - */ -#define MPT2SAS_DELL_BRANDING_SIZE 32 - -#define MPT2SAS_DELL_6GBPS_SAS_HBA_BRANDING "Dell 6Gbps SAS HBA" -#define MPT2SAS_DELL_PERC_H200_ADAPTER_BRANDING "Dell PERC H200 Adapter" -#define MPT2SAS_DELL_PERC_H200_INTEGRATED_BRANDING "Dell PERC H200 Integrated" -#define MPT2SAS_DELL_PERC_H200_MODULAR_BRANDING "Dell PERC H200 Modular" -#define MPT2SAS_DELL_PERC_H200_EMBEDDED_BRANDING "Dell PERC H200 Embedded" -#define MPT2SAS_DELL_PERC_H200_BRANDING "Dell PERC H200" -#define MPT2SAS_DELL_6GBPS_SAS_BRANDING "Dell 6Gbps SAS" - -#define MPT3SAS_DELL_12G_HBA_BRANDING \ - "Dell 12Gbps HBA" - -/* - * Dell HBA SSDIDs - */ -#define MPT2SAS_DELL_6GBPS_SAS_HBA_SSDID 0x1F1C -#define MPT2SAS_DELL_PERC_H200_ADAPTER_SSDID 0x1F1D -#define MPT2SAS_DELL_PERC_H200_INTEGRATED_SSDID 0x1F1E -#define MPT2SAS_DELL_PERC_H200_MODULAR_SSDID 0x1F1F -#define MPT2SAS_DELL_PERC_H200_EMBEDDED_SSDID 0x1F20 -#define MPT2SAS_DELL_PERC_H200_SSDID 0x1F21 -#define MPT2SAS_DELL_6GBPS_SAS_SSDID 0x1F22 - -#define MPT3SAS_DELL_12G_HBA_SSDID 0x1F46 - -/* - * Cisco HBA branding - */ -#define MPT3SAS_CISCO_12G_8E_HBA_BRANDING \ - "Cisco 9300-8E 12G SAS HBA" -#define MPT3SAS_CISCO_12G_8I_HBA_BRANDING \ - "Cisco 9300-8i 12G SAS HBA" -#define MPT3SAS_CISCO_12G_AVILA_HBA_BRANDING \ - "Cisco 12G Modular SAS Pass through Controller" -#define MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_BRANDING \ - "UCS C3X60 12G SAS Pass through Controller" -/* - * Cisco HBA SSSDIDs - */ -#define MPT3SAS_CISCO_12G_8E_HBA_SSDID 0x14C -#define MPT3SAS_CISCO_12G_8I_HBA_SSDID 0x154 -#define MPT3SAS_CISCO_12G_AVILA_HBA_SSDID 0x155 -#define MPT3SAS_CISCO_12G_COLUSA_MEZZANINE_HBA_SSDID 0x156 - -/* - * status bits for ioc->diag_buffer_status - */ -#define MPT3_DIAG_BUFFER_IS_REGISTERED (0x01) -#define MPT3_DIAG_BUFFER_IS_RELEASED (0x02) -#define MPT3_DIAG_BUFFER_IS_DIAG_RESET (0x04) - -/* - * HP HBA branding - */ -#define MPT2SAS_HP_3PAR_SSVID 0x1590 - -#define MPT2SAS_HP_2_4_INTERNAL_BRANDING \ - "HP H220 Host Bus Adapter" -#define MPT2SAS_HP_2_4_EXTERNAL_BRANDING \ - "HP H221 Host Bus Adapter" -#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING \ - "HP H222 Host Bus Adapter" -#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING \ - "HP H220i Host Bus Adapter" -#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING \ - "HP H210i Host Bus Adapter" - -/* - * HO HBA SSDIDs - */ -#define MPT2SAS_HP_2_4_INTERNAL_SSDID 0x0041 -#define MPT2SAS_HP_2_4_EXTERNAL_SSDID 0x0042 -#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID 0x0043 -#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID 0x0044 -#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID 0x0046 - -/* - * Combined Reply Queue constants, - * There are twelve Supplemental Reply Post Host Index Registers - * and each register is at offset 0x10 bytes from the previous one. - */ -#define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_COUNT 12 -#define MPT3_SUP_REPLY_POST_HOST_INDEX_REG_OFFSET (0x10) - -/* OEM Identifiers */ -#define MFG10_OEM_ID_INVALID (0x00000000) -#define MFG10_OEM_ID_DELL (0x00000001) -#define MFG10_OEM_ID_FSC (0x00000002) -#define MFG10_OEM_ID_SUN (0x00000003) -#define MFG10_OEM_ID_IBM (0x00000004) - -/* GENERIC Flags 0*/ -#define MFG10_GF0_OCE_DISABLED (0x00000001) -#define MFG10_GF0_R1E_DRIVE_COUNT (0x00000002) -#define MFG10_GF0_R10_DISPLAY (0x00000004) -#define MFG10_GF0_SSD_DATA_SCRUB_DISABLE (0x00000008) -#define MFG10_GF0_SINGLE_DRIVE_R0 (0x00000010) - -#define VIRTUAL_IO_FAILED_RETRY (0x32010081) - -/* OEM Specific Flags will come from OEM specific header files */ -struct Mpi2ManufacturingPage10_t { - MPI2_CONFIG_PAGE_HEADER Header; /* 00h */ - U8 OEMIdentifier; /* 04h */ - U8 Reserved1; /* 05h */ - U16 Reserved2; /* 08h */ - U32 Reserved3; /* 0Ch */ - U32 GenericFlags0; /* 10h */ - U32 GenericFlags1; /* 14h */ - U32 Reserved4; /* 18h */ - U32 OEMSpecificFlags0; /* 1Ch */ - U32 OEMSpecificFlags1; /* 20h */ - U32 Reserved5[18]; /* 24h - 60h*/ -}; - - -/* Miscellaneous options */ -struct Mpi2ManufacturingPage11_t { - MPI2_CONFIG_PAGE_HEADER Header; /* 00h */ - __le32 Reserved1; /* 04h */ - u8 Reserved2; /* 08h */ - u8 EEDPTagMode; /* 09h */ - u8 Reserved3; /* 0Ah */ - u8 Reserved4; /* 0Bh */ - __le32 Reserved5[23]; /* 0Ch-60h*/ -}; - -/** - * struct MPT3SAS_TARGET - starget private hostdata - * @starget: starget object - * @sas_address: target sas address - * @raid_device: raid_device pointer to access volume data - * @handle: device handle - * @num_luns: number luns - * @flags: MPT_TARGET_FLAGS_XXX flags - * @deleted: target flaged for deletion - * @tm_busy: target is busy with TM request. - * @sdev: The sas_device associated with this target - */ -struct MPT3SAS_TARGET { - struct scsi_target *starget; - u64 sas_address; - struct _raid_device *raid_device; - u16 handle; - int num_luns; - u32 flags; - u8 deleted; - u8 tm_busy; - struct _sas_device *sdev; -}; - - -/* - * per device private data - */ -#define MPT_DEVICE_FLAGS_INIT 0x01 -#define MPT_DEVICE_TLR_ON 0x02 - -#define MFG_PAGE10_HIDE_SSDS_MASK (0x00000003) -#define MFG_PAGE10_HIDE_ALL_DISKS (0x00) -#define MFG_PAGE10_EXPOSE_ALL_DISKS (0x01) -#define MFG_PAGE10_HIDE_IF_VOL_PRESENT (0x02) - -/** - * struct MPT3SAS_DEVICE - sdev private hostdata - * @sas_target: starget private hostdata - * @lun: lun number - * @flags: MPT_DEVICE_XXX flags - * @configured_lun: lun is configured - * @block: device is in SDEV_BLOCK state - * @tlr_snoop_check: flag used in determining whether to disable TLR - * @eedp_enable: eedp support enable bit - * @eedp_type: 0(type_1), 1(type_2), 2(type_3) - * @eedp_block_length: block size - * @ata_command_pending: SATL passthrough outstanding for device - */ -struct MPT3SAS_DEVICE { - struct MPT3SAS_TARGET *sas_target; - unsigned int lun; - u32 flags; - u8 configured_lun; - u8 block; - u8 tlr_snoop_check; - /* - * Bug workaround for SATL handling: the mpt2/3sas firmware - * doesn't return BUSY or TASK_SET_FULL for subsequent - * commands while a SATL pass through is in operation as the - * spec requires, it simply does nothing with them until the - * pass through completes, causing them possibly to timeout if - * the passthrough is a long executing command (like format or - * secure erase). This variable allows us to do the right - * thing while a SATL command is pending. - */ - unsigned long ata_command_pending; -}; - -#define MPT3_CMD_NOT_USED 0x8000 /* free */ -#define MPT3_CMD_COMPLETE 0x0001 /* completed */ -#define MPT3_CMD_PENDING 0x0002 /* pending */ -#define MPT3_CMD_REPLY_VALID 0x0004 /* reply is valid */ -#define MPT3_CMD_RESET 0x0008 /* host reset dropped the command */ - -/** - * struct _internal_cmd - internal commands struct - * @mutex: mutex - * @done: completion - * @reply: reply message pointer - * @sense: sense data - * @status: MPT3_CMD_XXX status - * @smid: system message id - */ -struct _internal_cmd { - struct mutex mutex; - struct completion done; - void *reply; - void *sense; - u16 status; - u16 smid; -}; - - - -/** - * struct _sas_device - attached device information - * @list: sas device list - * @starget: starget object - * @sas_address: device sas address - * @device_name: retrieved from the SAS IDENTIFY frame. - * @handle: device handle - * @sas_address_parent: sas address of parent expander or sas host - * @enclosure_handle: enclosure handle - * @enclosure_logical_id: enclosure logical identifier - * @volume_handle: volume handle (valid when hidden raid member) - * @volume_wwid: volume unique identifier - * @device_info: bitfield provides detailed info about the device - * @id: target id - * @channel: target channel - * @slot: number number - * @phy: phy identifier provided in sas device page 0 - * @responding: used in _scsih_sas_device_mark_responding - * @fast_path: fast path feature enable bit - * @pfa_led_on: flag for PFA LED status - * @pend_sas_rphy_add: flag to check if device is in sas_rphy_add() - * addition routine. - */ -struct _sas_device { - struct list_head list; - struct scsi_target *starget; - u64 sas_address; - u64 device_name; - u16 handle; - u64 sas_address_parent; - u16 enclosure_handle; - u64 enclosure_logical_id; - u16 volume_handle; - u64 volume_wwid; - u32 device_info; - int id; - int channel; - u16 slot; - u8 phy; - u8 responding; - u8 fast_path; - u8 pfa_led_on; - u8 pend_sas_rphy_add; - u8 enclosure_level; - u8 connector_name[4]; - struct kref refcount; -}; - -static inline void sas_device_get(struct _sas_device *s) -{ - kref_get(&s->refcount); -} - -static inline void sas_device_free(struct kref *r) -{ - kfree(container_of(r, struct _sas_device, refcount)); -} - -static inline void sas_device_put(struct _sas_device *s) -{ - kref_put(&s->refcount, sas_device_free); -} - -/** - * struct _raid_device - raid volume link list - * @list: sas device list - * @starget: starget object - * @sdev: scsi device struct (volumes are single lun) - * @wwid: unique identifier for the volume - * @handle: device handle - * @block_size: Block size of the volume - * @id: target id - * @channel: target channel - * @volume_type: the raid level - * @device_info: bitfield provides detailed info about the hidden components - * @num_pds: number of hidden raid components - * @responding: used in _scsih_raid_device_mark_responding - * @percent_complete: resync percent complete - * @direct_io_enabled: Whether direct io to PDs are allowed or not - * @stripe_exponent: X where 2powX is the stripe sz in blocks - * @block_exponent: X where 2powX is the block sz in bytes - * @max_lba: Maximum number of LBA in the volume - * @stripe_sz: Stripe Size of the volume - * @device_info: Device info of the volume member disk - * @pd_handle: Array of handles of the physical drives for direct I/O in le16 - */ -#define MPT_MAX_WARPDRIVE_PDS 8 -struct _raid_device { - struct list_head list; - struct scsi_target *starget; - struct scsi_device *sdev; - u64 wwid; - u16 handle; - u16 block_sz; - int id; - int channel; - u8 volume_type; - u8 num_pds; - u8 responding; - u8 percent_complete; - u8 direct_io_enabled; - u8 stripe_exponent; - u8 block_exponent; - u64 max_lba; - u32 stripe_sz; - u32 device_info; - u16 pd_handle[MPT_MAX_WARPDRIVE_PDS]; -}; - -/** - * struct _boot_device - boot device info - * @is_raid: flag to indicate whether this is volume - * @device: holds pointer for either struct _sas_device or - * struct _raid_device - */ -struct _boot_device { - u8 is_raid; - void *device; -}; - -/** - * struct _sas_port - wide/narrow sas port information - * @port_list: list of ports belonging to expander - * @num_phys: number of phys belonging to this port - * @remote_identify: attached device identification - * @rphy: sas transport rphy object - * @port: sas transport wide/narrow port object - * @phy_list: _sas_phy list objects belonging to this port - */ -struct _sas_port { - struct list_head port_list; - u8 num_phys; - struct sas_identify remote_identify; - struct sas_rphy *rphy; - struct sas_port *port; - struct list_head phy_list; -}; - -/** - * struct _sas_phy - phy information - * @port_siblings: list of phys belonging to a port - * @identify: phy identification - * @remote_identify: attached device identification - * @phy: sas transport phy object - * @phy_id: unique phy id - * @handle: device handle for this phy - * @attached_handle: device handle for attached device - * @phy_belongs_to_port: port has been created for this phy - */ -struct _sas_phy { - struct list_head port_siblings; - struct sas_identify identify; - struct sas_identify remote_identify; - struct sas_phy *phy; - u8 phy_id; - u16 handle; - u16 attached_handle; - u8 phy_belongs_to_port; -}; - -/** - * struct _sas_node - sas_host/expander information - * @list: list of expanders - * @parent_dev: parent device class - * @num_phys: number phys belonging to this sas_host/expander - * @sas_address: sas address of this sas_host/expander - * @handle: handle for this sas_host/expander - * @sas_address_parent: sas address of parent expander or sas host - * @enclosure_handle: handle for this a member of an enclosure - * @device_info: bitwise defining capabilities of this sas_host/expander - * @responding: used in _scsih_expander_device_mark_responding - * @phy: a list of phys that make up this sas_host/expander - * @sas_port_list: list of ports attached to this sas_host/expander - */ -struct _sas_node { - struct list_head list; - struct device *parent_dev; - u8 num_phys; - u64 sas_address; - u16 handle; - u64 sas_address_parent; - u16 enclosure_handle; - u64 enclosure_logical_id; - u8 responding; - struct _sas_phy *phy; - struct list_head sas_port_list; -}; - -/** - * enum reset_type - reset state - * @FORCE_BIG_HAMMER: issue diagnostic reset - * @SOFT_RESET: issue message_unit_reset, if fails to to big hammer - */ -enum reset_type { - FORCE_BIG_HAMMER, - SOFT_RESET, -}; - -/** - * struct chain_tracker - firmware chain tracker - * @chain_buffer: chain buffer - * @chain_buffer_dma: physical address - * @tracker_list: list of free request (ioc->free_chain_list) - */ -struct chain_tracker { - void *chain_buffer; - dma_addr_t chain_buffer_dma; - struct list_head tracker_list; -}; - -/** - * struct scsiio_tracker - scsi mf request tracker - * @smid: system message id - * @scmd: scsi request pointer - * @cb_idx: callback index - * @direct_io: To indicate whether I/O is direct (WARPDRIVE) - * @tracker_list: list of free request (ioc->free_list) - * @msix_io: IO's msix - */ -struct scsiio_tracker { - u16 smid; - struct scsi_cmnd *scmd; - u8 cb_idx; - u8 direct_io; - struct list_head chain_list; - struct list_head tracker_list; - u16 msix_io; -}; - -/** - * struct request_tracker - firmware request tracker - * @smid: system message id - * @cb_idx: callback index - * @tracker_list: list of free request (ioc->free_list) - */ -struct request_tracker { - u16 smid; - u8 cb_idx; - struct list_head tracker_list; -}; - -/** - * struct _tr_list - target reset list - * @handle: device handle - * @state: state machine - */ -struct _tr_list { - struct list_head list; - u16 handle; - u16 state; -}; - - -/** - * struct adapter_reply_queue - the reply queue struct - * @ioc: per adapter object - * @msix_index: msix index into vector table - * @vector: irq vector - * @reply_post_host_index: head index in the pool where FW completes IO - * @reply_post_free: reply post base virt address - * @name: the name registered to request_irq() - * @busy: isr is actively processing replies on another cpu - * @list: this list -*/ -struct adapter_reply_queue { - struct MPT3SAS_ADAPTER *ioc; - u8 msix_index; - unsigned int vector; - u32 reply_post_host_index; - Mpi2ReplyDescriptorsUnion_t *reply_post_free; - char name[MPT_NAME_LENGTH]; - atomic_t busy; - cpumask_var_t affinity_hint; - struct list_head list; -}; - -typedef void (*MPT_ADD_SGE)(void *paddr, u32 flags_length, dma_addr_t dma_addr); - -/* SAS3.0 support */ -typedef int (*MPT_BUILD_SG_SCMD)(struct MPT3SAS_ADAPTER *ioc, - struct scsi_cmnd *scmd, u16 smid); -typedef void (*MPT_BUILD_SG)(struct MPT3SAS_ADAPTER *ioc, void *psge, - dma_addr_t data_out_dma, size_t data_out_sz, - dma_addr_t data_in_dma, size_t data_in_sz); -typedef void (*MPT_BUILD_ZERO_LEN_SGE)(struct MPT3SAS_ADAPTER *ioc, - void *paddr); - - - -/* IOC Facts and Port Facts converted from little endian to cpu */ -union mpi3_version_union { - MPI2_VERSION_STRUCT Struct; - u32 Word; -}; - -struct mpt3sas_facts { - u16 MsgVersion; - u16 HeaderVersion; - u8 IOCNumber; - u8 VP_ID; - u8 VF_ID; - u16 IOCExceptions; - u16 IOCStatus; - u32 IOCLogInfo; - u8 MaxChainDepth; - u8 WhoInit; - u8 NumberOfPorts; - u8 MaxMSIxVectors; - u16 RequestCredit; - u16 ProductID; - u32 IOCCapabilities; - union mpi3_version_union FWVersion; - u16 IOCRequestFrameSize; - u16 Reserved3; - u16 MaxInitiators; - u16 MaxTargets; - u16 MaxSasExpanders; - u16 MaxEnclosures; - u16 ProtocolFlags; - u16 HighPriorityCredit; - u16 MaxReplyDescriptorPostQueueDepth; - u8 ReplyFrameSize; - u8 MaxVolumes; - u16 MaxDevHandle; - u16 MaxPersistentEntries; - u16 MinDevHandle; -}; - -struct mpt3sas_port_facts { - u8 PortNumber; - u8 VP_ID; - u8 VF_ID; - u8 PortType; - u16 MaxPostedCmdBuffers; -}; - -struct reply_post_struct { - Mpi2ReplyDescriptorsUnion_t *reply_post_free; - dma_addr_t reply_post_free_dma; -}; - -/** - * enum mutex_type - task management mutex type - * @TM_MUTEX_OFF: mutex is not required becuase calling function is acquiring it - * @TM_MUTEX_ON: mutex is required - */ -enum mutex_type { - TM_MUTEX_OFF = 0, - TM_MUTEX_ON = 1, -}; - -typedef void (*MPT3SAS_FLUSH_RUNNING_CMDS)(struct MPT3SAS_ADAPTER *ioc); -/** - * struct MPT3SAS_ADAPTER - per adapter struct - * @list: ioc_list - * @shost: shost object - * @id: unique adapter id - * @cpu_count: number online cpus - * @name: generic ioc string - * @tmp_string: tmp string used for logging - * @pdev: pci pdev object - * @pio_chip: physical io register space - * @chip: memory mapped register space - * @chip_phys: physical addrss prior to mapping - * @logging_level: see mpt3sas_debug.h - * @fwfault_debug: debuging FW timeouts - * @ir_firmware: IR firmware present - * @bars: bitmask of BAR's that must be configured - * @mask_interrupts: ignore interrupt - * @dma_mask: used to set the consistent dma mask - * @fault_reset_work_q_name: fw fault work queue - * @fault_reset_work_q: "" - * @fault_reset_work: "" - * @firmware_event_name: fw event work queue - * @firmware_event_thread: "" - * @fw_event_lock: - * @fw_event_list: list of fw events - * @aen_event_read_flag: event log was read - * @broadcast_aen_busy: broadcast aen waiting to be serviced - * @shost_recovery: host reset in progress - * @ioc_reset_in_progress_lock: - * @ioc_link_reset_in_progress: phy/hard reset in progress - * @ignore_loginfos: ignore loginfos during task management - * @remove_host: flag for when driver unloads, to avoid sending dev resets - * @pci_error_recovery: flag to prevent ioc access until slot reset completes - * @wait_for_discovery_to_complete: flag set at driver load time when - * waiting on reporting devices - * @is_driver_loading: flag set at driver load time - * @port_enable_failed: flag set when port enable has failed - * @start_scan: flag set from scan_start callback, cleared from _mpt3sas_fw_work - * @start_scan_failed: means port enable failed, return's the ioc_status - * @msix_enable: flag indicating msix is enabled - * @msix_vector_count: number msix vectors - * @cpu_msix_table: table for mapping cpus to msix index - * @cpu_msix_table_sz: table size - * @schedule_dead_ioc_flush_running_cmds: callback to flush pending commands - * @scsi_io_cb_idx: shost generated commands - * @tm_cb_idx: task management commands - * @scsih_cb_idx: scsih internal commands - * @transport_cb_idx: transport internal commands - * @ctl_cb_idx: clt internal commands - * @base_cb_idx: base internal commands - * @config_cb_idx: base internal commands - * @tm_tr_cb_idx : device removal target reset handshake - * @tm_tr_volume_cb_idx : volume removal target reset - * @base_cmds: - * @transport_cmds: - * @scsih_cmds: - * @tm_cmds: - * @ctl_cmds: - * @config_cmds: - * @base_add_sg_single: handler for either 32/64 bit sgl's - * @event_type: bits indicating which events to log - * @event_context: unique id for each logged event - * @event_log: event log pointer - * @event_masks: events that are masked - * @facts: static facts data - * @pfacts: static port facts data - * @manu_pg0: static manufacturing page 0 - * @manu_pg10: static manufacturing page 10 - * @manu_pg11: static manufacturing page 11 - * @bios_pg2: static bios page 2 - * @bios_pg3: static bios page 3 - * @ioc_pg8: static ioc page 8 - * @iounit_pg0: static iounit page 0 - * @iounit_pg1: static iounit page 1 - * @iounit_pg8: static iounit page 8 - * @sas_hba: sas host object - * @sas_expander_list: expander object list - * @sas_node_lock: - * @sas_device_list: sas device object list - * @sas_device_init_list: sas device object list (used only at init time) - * @sas_device_lock: - * @io_missing_delay: time for IO completed by fw when PDR enabled - * @device_missing_delay: time for device missing by fw when PDR enabled - * @sas_id : used for setting volume target IDs - * @blocking_handles: bitmask used to identify which devices need blocking - * @pd_handles : bitmask for PD handles - * @pd_handles_sz : size of pd_handle bitmask - * @config_page_sz: config page size - * @config_page: reserve memory for config page payload - * @config_page_dma: - * @hba_queue_depth: hba request queue depth - * @sge_size: sg element size for either 32/64 bit - * @scsiio_depth: SCSI_IO queue depth - * @request_sz: per request frame size - * @request: pool of request frames - * @request_dma: - * @request_dma_sz: - * @scsi_lookup: firmware request tracker list - * @scsi_lookup_lock: - * @free_list: free list of request - * @pending_io_count: - * @reset_wq: - * @chain: pool of chains - * @chain_dma: - * @max_sges_in_main_message: number sg elements in main message - * @max_sges_in_chain_message: number sg elements per chain - * @chains_needed_per_io: max chains per io - * @chain_depth: total chains allocated - * @hi_priority_smid: - * @hi_priority: - * @hi_priority_dma: - * @hi_priority_depth: - * @hpr_lookup: - * @hpr_free_list: - * @internal_smid: - * @internal: - * @internal_dma: - * @internal_depth: - * @internal_lookup: - * @internal_free_list: - * @sense: pool of sense - * @sense_dma: - * @sense_dma_pool: - * @reply_depth: hba reply queue depth: - * @reply_sz: per reply frame size: - * @reply: pool of replys: - * @reply_dma: - * @reply_dma_pool: - * @reply_free_queue_depth: reply free depth - * @reply_free: pool for reply free queue (32 bit addr) - * @reply_free_dma: - * @reply_free_dma_pool: - * @reply_free_host_index: tail index in pool to insert free replys - * @reply_post_queue_depth: reply post queue depth - * @reply_post_struct: struct for reply_post_free physical & virt address - * @rdpq_array_capable: FW supports multiple reply queue addresses in ioc_init - * @rdpq_array_enable: rdpq_array support is enabled in the driver - * @rdpq_array_enable_assigned: this ensures that rdpq_array_enable flag - * is assigned only ones - * @reply_queue_count: number of reply queue's - * @reply_queue_list: link list contaning the reply queue info - * @msix96_vector: 96 MSI-X vector support - * @replyPostRegisterIndex: index of next position in Reply Desc Post Queue - * @delayed_tr_list: target reset link list - * @delayed_tr_volume_list: volume target reset link list - * @temp_sensors_count: flag to carry the number of temperature sensors - * @pci_access_mutex: Mutex to synchronize ioctl,sysfs show path and - * pci resource handling. PCI resource freeing will lead to free - * vital hardware/memory resource, which might be in use by cli/sysfs - * path functions resulting in Null pointer reference followed by kernel - * crash. To avoid the above race condition we use mutex syncrhonization - * which ensures the syncrhonization between cli/sysfs_show path. - */ -struct MPT3SAS_ADAPTER { - struct list_head list; - struct Scsi_Host *shost; - u8 id; - int cpu_count; - char name[MPT_NAME_LENGTH]; - char driver_name[MPT_NAME_LENGTH]; - char tmp_string[MPT_STRING_LENGTH]; - struct pci_dev *pdev; - Mpi2SystemInterfaceRegs_t __iomem *chip; - resource_size_t chip_phys; - int logging_level; - int fwfault_debug; - u8 ir_firmware; - int bars; - u8 mask_interrupts; - int dma_mask; - - /* fw fault handler */ - char fault_reset_work_q_name[20]; - struct workqueue_struct *fault_reset_work_q; - struct delayed_work fault_reset_work; - - /* fw event handler */ - char firmware_event_name[20]; - struct workqueue_struct *firmware_event_thread; - spinlock_t fw_event_lock; - struct list_head fw_event_list; - - /* misc flags */ - int aen_event_read_flag; - u8 broadcast_aen_busy; - u16 broadcast_aen_pending; - u8 shost_recovery; - - struct mutex reset_in_progress_mutex; - spinlock_t ioc_reset_in_progress_lock; - u8 ioc_link_reset_in_progress; - u8 ioc_reset_in_progress_status; - - u8 ignore_loginfos; - u8 remove_host; - u8 pci_error_recovery; - u8 wait_for_discovery_to_complete; - u8 is_driver_loading; - u8 port_enable_failed; - u8 start_scan; - u16 start_scan_failed; - - u8 msix_enable; - u16 msix_vector_count; - u8 *cpu_msix_table; - u16 cpu_msix_table_sz; - resource_size_t __iomem **reply_post_host_index; - u32 ioc_reset_count; - MPT3SAS_FLUSH_RUNNING_CMDS schedule_dead_ioc_flush_running_cmds; - u32 non_operational_loop; - - /* internal commands, callback index */ - u8 scsi_io_cb_idx; - u8 tm_cb_idx; - u8 transport_cb_idx; - u8 scsih_cb_idx; - u8 ctl_cb_idx; - u8 base_cb_idx; - u8 port_enable_cb_idx; - u8 config_cb_idx; - u8 tm_tr_cb_idx; - u8 tm_tr_volume_cb_idx; - u8 tm_sas_control_cb_idx; - struct _internal_cmd base_cmds; - struct _internal_cmd port_enable_cmds; - struct _internal_cmd transport_cmds; - struct _internal_cmd scsih_cmds; - struct _internal_cmd tm_cmds; - struct _internal_cmd ctl_cmds; - struct _internal_cmd config_cmds; - - MPT_ADD_SGE base_add_sg_single; - - /* function ptr for either IEEE or MPI sg elements */ - MPT_BUILD_SG_SCMD build_sg_scmd; - MPT_BUILD_SG build_sg; - MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge; - u16 sge_size_ieee; - u16 hba_mpi_version_belonged; - - /* function ptr for MPI sg elements only */ - MPT_BUILD_SG build_sg_mpi; - MPT_BUILD_ZERO_LEN_SGE build_zero_len_sge_mpi; - - /* event log */ - u32 event_type[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; - u32 event_context; - void *event_log; - u32 event_masks[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; - - /* static config pages */ - struct mpt3sas_facts facts; - struct mpt3sas_port_facts *pfacts; - Mpi2ManufacturingPage0_t manu_pg0; - struct Mpi2ManufacturingPage10_t manu_pg10; - struct Mpi2ManufacturingPage11_t manu_pg11; - Mpi2BiosPage2_t bios_pg2; - Mpi2BiosPage3_t bios_pg3; - Mpi2IOCPage8_t ioc_pg8; - Mpi2IOUnitPage0_t iounit_pg0; - Mpi2IOUnitPage1_t iounit_pg1; - Mpi2IOUnitPage8_t iounit_pg8; - - struct _boot_device req_boot_device; - struct _boot_device req_alt_boot_device; - struct _boot_device current_boot_device; - - /* sas hba, expander, and device list */ - struct _sas_node sas_hba; - struct list_head sas_expander_list; - spinlock_t sas_node_lock; - struct list_head sas_device_list; - struct list_head sas_device_init_list; - spinlock_t sas_device_lock; - struct list_head raid_device_list; - spinlock_t raid_device_lock; - u8 io_missing_delay; - u16 device_missing_delay; - int sas_id; - - void *blocking_handles; - void *pd_handles; - u16 pd_handles_sz; - - /* config page */ - u16 config_page_sz; - void *config_page; - dma_addr_t config_page_dma; - - /* scsiio request */ - u16 hba_queue_depth; - u16 sge_size; - u16 scsiio_depth; - u16 request_sz; - u8 *request; - dma_addr_t request_dma; - u32 request_dma_sz; - struct scsiio_tracker *scsi_lookup; - ulong scsi_lookup_pages; - spinlock_t scsi_lookup_lock; - struct list_head free_list; - int pending_io_count; - wait_queue_head_t reset_wq; - - /* chain */ - struct chain_tracker *chain_lookup; - struct list_head free_chain_list; - struct dma_pool *chain_dma_pool; - ulong chain_pages; - u16 max_sges_in_main_message; - u16 max_sges_in_chain_message; - u16 chains_needed_per_io; - u32 chain_depth; - - /* hi-priority queue */ - u16 hi_priority_smid; - u8 *hi_priority; - dma_addr_t hi_priority_dma; - u16 hi_priority_depth; - struct request_tracker *hpr_lookup; - struct list_head hpr_free_list; - - /* internal queue */ - u16 internal_smid; - u8 *internal; - dma_addr_t internal_dma; - u16 internal_depth; - struct request_tracker *internal_lookup; - struct list_head internal_free_list; - - /* sense */ - u8 *sense; - dma_addr_t sense_dma; - struct dma_pool *sense_dma_pool; - - /* reply */ - u16 reply_sz; - u8 *reply; - dma_addr_t reply_dma; - u32 reply_dma_max_address; - u32 reply_dma_min_address; - struct dma_pool *reply_dma_pool; - - /* reply free queue */ - u16 reply_free_queue_depth; - __le32 *reply_free; - dma_addr_t reply_free_dma; - struct dma_pool *reply_free_dma_pool; - u32 reply_free_host_index; - - /* reply post queue */ - u16 reply_post_queue_depth; - struct reply_post_struct *reply_post; - u8 rdpq_array_capable; - u8 rdpq_array_enable; - u8 rdpq_array_enable_assigned; - struct dma_pool *reply_post_free_dma_pool; - u8 reply_queue_count; - struct list_head reply_queue_list; - - u8 msix96_vector; - /* reply post register index */ - resource_size_t **replyPostRegisterIndex; - - struct list_head delayed_tr_list; - struct list_head delayed_tr_volume_list; - u8 temp_sensors_count; - struct mutex pci_access_mutex; - - /* diag buffer support */ - u8 *diag_buffer[MPI2_DIAG_BUF_TYPE_COUNT]; - u32 diag_buffer_sz[MPI2_DIAG_BUF_TYPE_COUNT]; - dma_addr_t diag_buffer_dma[MPI2_DIAG_BUF_TYPE_COUNT]; - u8 diag_buffer_status[MPI2_DIAG_BUF_TYPE_COUNT]; - u32 unique_id[MPI2_DIAG_BUF_TYPE_COUNT]; - u32 product_specific[MPI2_DIAG_BUF_TYPE_COUNT][23]; - u32 diagnostic_flags[MPI2_DIAG_BUF_TYPE_COUNT]; - u32 ring_buffer_offset; - u32 ring_buffer_sz; - u8 is_warpdrive; - u8 hide_ir_msg; - u8 mfg_pg10_hide_flag; - u8 hide_drives; - spinlock_t diag_trigger_lock; - u8 diag_trigger_active; - struct SL_WH_MASTER_TRIGGER_T diag_trigger_master; - struct SL_WH_EVENT_TRIGGERS_T diag_trigger_event; - struct SL_WH_SCSI_TRIGGERS_T diag_trigger_scsi; - struct SL_WH_MPI_TRIGGERS_T diag_trigger_mpi; -}; - -typedef u8 (*MPT_CALLBACK)(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply); - - -/* base shared API */ -extern struct list_head mpt3sas_ioc_list; -extern char driver_name[MPT_NAME_LENGTH]; -/* spinlock on list operations over IOCs - * Case: when multiple warpdrive cards(IOCs) are in use - * Each IOC will added to the ioc list structure on initialization. - * Watchdog threads run at regular intervals to check IOC for any - * fault conditions which will trigger the dead_ioc thread to - * deallocate pci resource, resulting deleting the IOC netry from list, - * this deletion need to protected by spinlock to enusre that - * ioc removal is syncrhonized, if not synchronized it might lead to - * list_del corruption as the ioc list is traversed in cli path. - */ -extern spinlock_t gioc_lock; - -void mpt3sas_base_start_watchdog(struct MPT3SAS_ADAPTER *ioc); -void mpt3sas_base_stop_watchdog(struct MPT3SAS_ADAPTER *ioc); - -int mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc); -void mpt3sas_base_detach(struct MPT3SAS_ADAPTER *ioc); -int mpt3sas_base_map_resources(struct MPT3SAS_ADAPTER *ioc); -void mpt3sas_base_free_resources(struct MPT3SAS_ADAPTER *ioc); -int mpt3sas_base_hard_reset_handler(struct MPT3SAS_ADAPTER *ioc, int sleep_flag, - enum reset_type type); - -void *mpt3sas_base_get_msg_frame(struct MPT3SAS_ADAPTER *ioc, u16 smid); -void *mpt3sas_base_get_sense_buffer(struct MPT3SAS_ADAPTER *ioc, u16 smid); -__le32 mpt3sas_base_get_sense_buffer_dma(struct MPT3SAS_ADAPTER *ioc, - u16 smid); -void mpt3sas_base_flush_reply_queues(struct MPT3SAS_ADAPTER *ioc); - -/* hi-priority queue */ -u16 mpt3sas_base_get_smid_hpr(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx); -u16 mpt3sas_base_get_smid_scsiio(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx, - struct scsi_cmnd *scmd); - -u16 mpt3sas_base_get_smid(struct MPT3SAS_ADAPTER *ioc, u8 cb_idx); -void mpt3sas_base_free_smid(struct MPT3SAS_ADAPTER *ioc, u16 smid); -void mpt3sas_base_put_smid_scsi_io(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u16 handle); -void mpt3sas_base_put_smid_fast_path(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u16 handle); -void mpt3sas_base_put_smid_hi_priority(struct MPT3SAS_ADAPTER *ioc, - u16 smid, u16 msix_task); -void mpt3sas_base_put_smid_default(struct MPT3SAS_ADAPTER *ioc, u16 smid); -void mpt3sas_base_initialize_callback_handler(void); -u8 mpt3sas_base_register_callback_handler(MPT_CALLBACK cb_func); -void mpt3sas_base_release_callback_handler(u8 cb_idx); - -u8 mpt3sas_base_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply); -u8 mpt3sas_port_enable_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u8 msix_index, u32 reply); -void *mpt3sas_base_get_reply_virt_addr(struct MPT3SAS_ADAPTER *ioc, - u32 phys_addr); - -u32 mpt3sas_base_get_iocstate(struct MPT3SAS_ADAPTER *ioc, int cooked); - -void mpt3sas_base_fault_info(struct MPT3SAS_ADAPTER *ioc , u16 fault_code); -int mpt3sas_base_sas_iounit_control(struct MPT3SAS_ADAPTER *ioc, - Mpi2SasIoUnitControlReply_t *mpi_reply, - Mpi2SasIoUnitControlRequest_t *mpi_request); -int mpt3sas_base_scsi_enclosure_processor(struct MPT3SAS_ADAPTER *ioc, - Mpi2SepReply_t *mpi_reply, Mpi2SepRequest_t *mpi_request); - -void mpt3sas_base_validate_event_type(struct MPT3SAS_ADAPTER *ioc, - u32 *event_type); - -void mpt3sas_halt_firmware(struct MPT3SAS_ADAPTER *ioc); - -void mpt3sas_base_update_missing_delay(struct MPT3SAS_ADAPTER *ioc, - u16 device_missing_delay, u8 io_missing_delay); - -int mpt3sas_port_enable(struct MPT3SAS_ADAPTER *ioc); - - -/* scsih shared API */ -u8 mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, - u32 reply); -void mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase); - -int mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, - uint channel, uint id, uint lun, u8 type, u16 smid_task, - ulong timeout, enum mutex_type m_type); -void mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); -void mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle); -void mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address); -void mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address); - -struct _sas_node *mpt3sas_scsih_expander_find_by_handle( - struct MPT3SAS_ADAPTER *ioc, u16 handle); -struct _sas_node *mpt3sas_scsih_expander_find_by_sas_address( - struct MPT3SAS_ADAPTER *ioc, u64 sas_address); -struct _sas_device *mpt3sas_get_sdev_by_addr( - struct MPT3SAS_ADAPTER *ioc, u64 sas_address); -struct _sas_device *__mpt3sas_get_sdev_by_addr( - struct MPT3SAS_ADAPTER *ioc, u64 sas_address); - -void mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc); -struct _raid_device * -mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle); - -/* config shared API */ -u8 mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply); -int mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, - u8 *num_phys); -int mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page); -int mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page, - u16 sz); -int mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, - struct Mpi2ManufacturingPage10_t *config_page); - -int mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, - struct Mpi2ManufacturingPage11_t *config_page); -int mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, - struct Mpi2ManufacturingPage11_t *config_page); - -int mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2BiosPage2_t *config_page); -int mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2BiosPage3_t *config_page); -int mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2IOUnitPage0_t *config_page); -int mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page, - u32 form, u32 handle); -int mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page, - u32 form, u32 handle); -int mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, - u16 sz); -int mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2IOUnitPage1_t *config_page); -int mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz); -int mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2IOUnitPage1_t *config_page); -int mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2IOUnitPage8_t *config_page); -int mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, - u16 sz); -int mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, - u16 sz); -int mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2IOCPage8_t *config_page); -int mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2ExpanderPage0_t *config_page, - u32 form, u32 handle); -int mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2ExpanderPage1_t *config_page, - u32 phy_number, u16 handle); -int mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, - u32 form, u32 handle); -int mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number); -int mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number); -int mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, - u32 handle); -int mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u8 *num_pds); -int mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, - u32 handle, u16 sz); -int mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, - u32 form, u32 form_specific); -int mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle, - u16 *volume_handle); -int mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, - u16 volume_handle, u64 *wwid); - -/* ctl shared API */ -extern struct device_attribute *mpt3sas_host_attrs[]; -extern struct device_attribute *mpt3sas_dev_attrs[]; -void mpt3sas_ctl_init(ushort hbas_to_enumerate); -void mpt3sas_ctl_exit(ushort hbas_to_enumerate); -u8 mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply); -void mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase); -u8 mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc, - u8 msix_index, u32 reply); -void mpt3sas_ctl_add_to_event_log(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventNotificationReply_t *mpi_reply); - -void mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, - u8 bits_to_regsiter); -int mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type, - u8 *issue_reset); - -/* transport shared API */ -extern struct scsi_transport_template *mpt3sas_transport_template; -u8 mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply); -struct _sas_port *mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, - u16 handle, u64 sas_address); -void mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, - u64 sas_address_parent); -int mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy - *mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev); -int mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, - struct _sas_phy *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1, - struct device *parent_dev); -void mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address, u16 handle, u8 phy_number, u8 link_rate); -extern struct sas_function_template mpt3sas_transport_functions; -extern struct scsi_transport_template *mpt3sas_transport_template; -extern int scsi_internal_device_block(struct scsi_device *sdev); -extern int scsi_internal_device_unblock(struct scsi_device *sdev, - enum scsi_device_state new_state); -/* trigger data externs */ -void mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc, - struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data); -void mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc, - struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data); -void mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc, - u32 tigger_bitmask); -void mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event, - u16 log_entry_qualifier); -void mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key, - u8 asc, u8 ascq); -void mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status, - u32 loginfo); - -/* warpdrive APIs */ -u8 mpt3sas_get_num_volumes(struct MPT3SAS_ADAPTER *ioc); -void mpt3sas_init_warpdrive_properties(struct MPT3SAS_ADAPTER *ioc, - struct _raid_device *raid_device); -u8 -mpt3sas_scsi_direct_io_get(struct MPT3SAS_ADAPTER *ioc, u16 smid); -void -mpt3sas_scsi_direct_io_set(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 direct_io); -void -mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, - struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request, - u16 smid); - -#endif /* MPT3SAS_BASE_H_INCLUDED */ diff --git a/addons/mpt3sas/src/4.4.180/mpt3sas_config.c b/addons/mpt3sas/src/4.4.180/mpt3sas_config.c deleted file mode 100644 index a6914ec9..00000000 --- a/addons/mpt3sas/src/4.4.180/mpt3sas_config.c +++ /dev/null @@ -1,1716 +0,0 @@ -/* - * This module provides common API for accessing firmware configuration pages - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.c - * Copyright (C) 2012-2014 LSI Corporation - * Copyright (C) 2013-2014 Avago Technologies - * (mailto: MPT-FusionLinux.pdl@avagotech.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mpt3sas_base.h" - -/* local definitions */ - -/* Timeout for config page request (in seconds) */ -#define MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT 15 - -/* Common sgl flags for READING a config page. */ -#define MPT3_CONFIG_COMMON_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ - MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ - | MPI2_SGE_FLAGS_END_OF_LIST) << MPI2_SGE_FLAGS_SHIFT) - -/* Common sgl flags for WRITING a config page. */ -#define MPT3_CONFIG_COMMON_WRITE_SGLFLAGS ((MPI2_SGE_FLAGS_SIMPLE_ELEMENT | \ - MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER \ - | MPI2_SGE_FLAGS_END_OF_LIST | MPI2_SGE_FLAGS_HOST_TO_IOC) \ - << MPI2_SGE_FLAGS_SHIFT) - -/** - * struct config_request - obtain dma memory via routine - * @sz: size - * @page: virt pointer - * @page_dma: phys pointer - * - */ -struct config_request { - u16 sz; - void *page; - dma_addr_t page_dma; -}; - -/** - * _config_display_some_debug - debug routine - * @ioc: per adapter object - * @smid: system request message index - * @calling_function_name: string pass from calling function - * @mpi_reply: reply message frame - * Context: none. - * - * Function for displaying debug info helpful when debugging issues - * in this module. - */ -static void -_config_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid, - char *calling_function_name, MPI2DefaultReply_t *mpi_reply) -{ - Mpi2ConfigRequest_t *mpi_request; - char *desc = NULL; - - if (!(ioc->logging_level & MPT_DEBUG_CONFIG)) - return; - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - switch (mpi_request->Header.PageType & MPI2_CONFIG_PAGETYPE_MASK) { - case MPI2_CONFIG_PAGETYPE_IO_UNIT: - desc = "io_unit"; - break; - case MPI2_CONFIG_PAGETYPE_IOC: - desc = "ioc"; - break; - case MPI2_CONFIG_PAGETYPE_BIOS: - desc = "bios"; - break; - case MPI2_CONFIG_PAGETYPE_RAID_VOLUME: - desc = "raid_volume"; - break; - case MPI2_CONFIG_PAGETYPE_MANUFACTURING: - desc = "manufaucturing"; - break; - case MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK: - desc = "physdisk"; - break; - case MPI2_CONFIG_PAGETYPE_EXTENDED: - switch (mpi_request->ExtPageType) { - case MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT: - desc = "sas_io_unit"; - break; - case MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER: - desc = "sas_expander"; - break; - case MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE: - desc = "sas_device"; - break; - case MPI2_CONFIG_EXTPAGETYPE_SAS_PHY: - desc = "sas_phy"; - break; - case MPI2_CONFIG_EXTPAGETYPE_LOG: - desc = "log"; - break; - case MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE: - desc = "enclosure"; - break; - case MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG: - desc = "raid_config"; - break; - case MPI2_CONFIG_EXTPAGETYPE_DRIVER_MAPPING: - desc = "driver_mapping"; - break; - } - break; - } - - if (!desc) - return; - - pr_info(MPT3SAS_FMT - "%s: %s(%d), action(%d), form(0x%08x), smid(%d)\n", - ioc->name, calling_function_name, desc, - mpi_request->Header.PageNumber, mpi_request->Action, - le32_to_cpu(mpi_request->PageAddress), smid); - - if (!mpi_reply) - return; - - if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) - pr_info(MPT3SAS_FMT - "\tiocstatus(0x%04x), loginfo(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo)); -} - -/** - * _config_alloc_config_dma_memory - obtain physical memory - * @ioc: per adapter object - * @mem: struct config_request - * - * A wrapper for obtaining dma-able memory for config page request. - * - * Returns 0 for success, non-zero for failure. - */ -static int -_config_alloc_config_dma_memory(struct MPT3SAS_ADAPTER *ioc, - struct config_request *mem) -{ - int r = 0; - - if (mem->sz > ioc->config_page_sz) { - mem->page = dma_alloc_coherent(&ioc->pdev->dev, mem->sz, - &mem->page_dma, GFP_KERNEL); - if (!mem->page) { - pr_err(MPT3SAS_FMT - "%s: dma_alloc_coherent failed asking for (%d) bytes!!\n", - ioc->name, __func__, mem->sz); - r = -ENOMEM; - } - } else { /* use tmp buffer if less than 512 bytes */ - mem->page = ioc->config_page; - mem->page_dma = ioc->config_page_dma; - } - return r; -} - -/** - * _config_free_config_dma_memory - wrapper to free the memory - * @ioc: per adapter object - * @mem: struct config_request - * - * A wrapper to free dma-able memory when using _config_alloc_config_dma_memory. - * - * Returns 0 for success, non-zero for failure. - */ -static void -_config_free_config_dma_memory(struct MPT3SAS_ADAPTER *ioc, - struct config_request *mem) -{ - if (mem->sz > ioc->config_page_sz) - dma_free_coherent(&ioc->pdev->dev, mem->sz, mem->page, - mem->page_dma); -} - -/** - * mpt3sas_config_done - config page completion routine - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: none. - * - * The callback handler when using _config_request. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_config_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - - if (ioc->config_cmds.status == MPT3_CMD_NOT_USED) - return 1; - if (ioc->config_cmds.smid != smid) - return 1; - ioc->config_cmds.status |= MPT3_CMD_COMPLETE; - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (mpi_reply) { - ioc->config_cmds.status |= MPT3_CMD_REPLY_VALID; - memcpy(ioc->config_cmds.reply, mpi_reply, - mpi_reply->MsgLength*4); - } - ioc->config_cmds.status &= ~MPT3_CMD_PENDING; - _config_display_some_debug(ioc, smid, "config_done", mpi_reply); - ioc->config_cmds.smid = USHRT_MAX; - complete(&ioc->config_cmds.done); - return 1; -} - -/** - * _config_request - main routine for sending config page requests - * @ioc: per adapter object - * @mpi_request: request message frame - * @mpi_reply: reply mf payload returned from firmware - * @timeout: timeout in seconds - * @config_page: contents of the config page - * @config_page_sz: size of config page - * Context: sleep - * - * A generic API for config page requests to firmware. - * - * The ioc->config_cmds.status flag should be MPT3_CMD_NOT_USED before calling - * this API. - * - * The callback index is set inside `ioc->config_cb_idx. - * - * Returns 0 for success, non-zero for failure. - */ -static int -_config_request(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigRequest_t - *mpi_request, Mpi2ConfigReply_t *mpi_reply, int timeout, - void *config_page, u16 config_page_sz) -{ - u16 smid; - u32 ioc_state; - unsigned long timeleft; - Mpi2ConfigRequest_t *config_request; - int r; - u8 retry_count, issue_host_reset = 0; - u16 wait_state_count; - struct config_request mem; - u32 ioc_status = UINT_MAX; - - mutex_lock(&ioc->config_cmds.mutex); - if (ioc->config_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: config_cmd in use\n", - ioc->name, __func__); - mutex_unlock(&ioc->config_cmds.mutex); - return -EAGAIN; - } - - retry_count = 0; - memset(&mem, 0, sizeof(struct config_request)); - - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - - if (config_page) { - mpi_request->Header.PageVersion = mpi_reply->Header.PageVersion; - mpi_request->Header.PageNumber = mpi_reply->Header.PageNumber; - mpi_request->Header.PageType = mpi_reply->Header.PageType; - mpi_request->Header.PageLength = mpi_reply->Header.PageLength; - mpi_request->ExtPageLength = mpi_reply->ExtPageLength; - mpi_request->ExtPageType = mpi_reply->ExtPageType; - if (mpi_request->Header.PageLength) - mem.sz = mpi_request->Header.PageLength * 4; - else - mem.sz = le16_to_cpu(mpi_reply->ExtPageLength) * 4; - r = _config_alloc_config_dma_memory(ioc, &mem); - if (r != 0) - goto out; - if (mpi_request->Action == - MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT || - mpi_request->Action == - MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM) { - ioc->base_add_sg_single(&mpi_request->PageBufferSGE, - MPT3_CONFIG_COMMON_WRITE_SGLFLAGS | mem.sz, - mem.page_dma); - memcpy(mem.page, config_page, min_t(u16, mem.sz, - config_page_sz)); - } else { - memset(config_page, 0, config_page_sz); - ioc->base_add_sg_single(&mpi_request->PageBufferSGE, - MPT3_CONFIG_COMMON_SGLFLAGS | mem.sz, mem.page_dma); - memset(mem.page, 0, min_t(u16, mem.sz, config_page_sz)); - } - } - - retry_config: - if (retry_count) { - if (retry_count > 2) { /* attempt only 2 retries */ - r = -EFAULT; - goto free_mem; - } - pr_info(MPT3SAS_FMT "%s: attempting retry (%d)\n", - ioc->name, __func__, retry_count); - } - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - ioc->config_cmds.status = MPT3_CMD_NOT_USED; - r = -EFAULT; - goto free_mem; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, __func__, wait_state_count); - } - if (wait_state_count) - pr_info(MPT3SAS_FMT "%s: ioc is operational\n", - ioc->name, __func__); - - smid = mpt3sas_base_get_smid(ioc, ioc->config_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - ioc->config_cmds.status = MPT3_CMD_NOT_USED; - r = -EAGAIN; - goto free_mem; - } - - r = 0; - memset(mpi_reply, 0, sizeof(Mpi2ConfigReply_t)); - ioc->config_cmds.status = MPT3_CMD_PENDING; - config_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->config_cmds.smid = smid; - memcpy(config_request, mpi_request, sizeof(Mpi2ConfigRequest_t)); - _config_display_some_debug(ioc, smid, "config_request", NULL); - init_completion(&ioc->config_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->config_cmds.done, - timeout*HZ); - if (!(ioc->config_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2ConfigRequest_t)/4); - retry_count++; - if (ioc->config_cmds.smid == smid) - mpt3sas_base_free_smid(ioc, smid); - if ((ioc->shost_recovery) || (ioc->config_cmds.status & - MPT3_CMD_RESET) || ioc->pci_error_recovery) - goto retry_config; - issue_host_reset = 1; - r = -EFAULT; - goto free_mem; - } - - if (ioc->config_cmds.status & MPT3_CMD_REPLY_VALID) { - memcpy(mpi_reply, ioc->config_cmds.reply, - sizeof(Mpi2ConfigReply_t)); - - /* Reply Frame Sanity Checks to workaround FW issues */ - if ((mpi_request->Header.PageType & 0xF) != - (mpi_reply->Header.PageType & 0xF)) { - _debug_dump_mf(mpi_request, ioc->request_sz/4); - _debug_dump_reply(mpi_reply, ioc->request_sz/4); - panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \ - " mpi_reply mismatch: Requested PageType(0x%02x)" \ - " Reply PageType(0x%02x)\n", \ - ioc->name, __func__, - (mpi_request->Header.PageType & 0xF), - (mpi_reply->Header.PageType & 0xF)); - } - - if (((mpi_request->Header.PageType & 0xF) == - MPI2_CONFIG_PAGETYPE_EXTENDED) && - mpi_request->ExtPageType != mpi_reply->ExtPageType) { - _debug_dump_mf(mpi_request, ioc->request_sz/4); - _debug_dump_reply(mpi_reply, ioc->request_sz/4); - panic(KERN_WARNING MPT3SAS_FMT "%s: Firmware BUG:" \ - " mpi_reply mismatch: Requested ExtPageType(0x%02x)" - " Reply ExtPageType(0x%02x)\n", - ioc->name, __func__, mpi_request->ExtPageType, - mpi_reply->ExtPageType); - } - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) - & MPI2_IOCSTATUS_MASK; - } - - if (retry_count) - pr_info(MPT3SAS_FMT "%s: retry (%d) completed!!\n", \ - ioc->name, __func__, retry_count); - - if ((ioc_status == MPI2_IOCSTATUS_SUCCESS) && - config_page && mpi_request->Action == - MPI2_CONFIG_ACTION_PAGE_READ_CURRENT) { - u8 *p = (u8 *)mem.page; - - /* Config Page Sanity Checks to workaround FW issues */ - if (p) { - if ((mpi_request->Header.PageType & 0xF) != - (p[3] & 0xF)) { - _debug_dump_mf(mpi_request, ioc->request_sz/4); - _debug_dump_reply(mpi_reply, ioc->request_sz/4); - _debug_dump_config(p, min_t(u16, mem.sz, - config_page_sz)/4); - panic(KERN_WARNING MPT3SAS_FMT - "%s: Firmware BUG:" \ - " config page mismatch:" - " Requested PageType(0x%02x)" - " Reply PageType(0x%02x)\n", - ioc->name, __func__, - (mpi_request->Header.PageType & 0xF), - (p[3] & 0xF)); - } - - if (((mpi_request->Header.PageType & 0xF) == - MPI2_CONFIG_PAGETYPE_EXTENDED) && - (mpi_request->ExtPageType != p[6])) { - _debug_dump_mf(mpi_request, ioc->request_sz/4); - _debug_dump_reply(mpi_reply, ioc->request_sz/4); - _debug_dump_config(p, min_t(u16, mem.sz, - config_page_sz)/4); - panic(KERN_WARNING MPT3SAS_FMT - "%s: Firmware BUG:" \ - " config page mismatch:" - " Requested ExtPageType(0x%02x)" - " Reply ExtPageType(0x%02x)\n", - ioc->name, __func__, - mpi_request->ExtPageType, p[6]); - } - } - memcpy(config_page, mem.page, min_t(u16, mem.sz, - config_page_sz)); - } - - free_mem: - if (config_page) - _config_free_config_dma_memory(ioc, &mem); - out: - ioc->config_cmds.status = MPT3_CMD_NOT_USED; - mutex_unlock(&ioc->config_cmds.mutex); - - if (issue_host_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - return r; -} - -/** - * mpt3sas_config_get_manufacturing_pg0 - obtain manufacturing page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_manufacturing_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage0_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_manufacturing_pg7 - obtain manufacturing page 7 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @sz: size of buffer passed in config_page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_manufacturing_pg7(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2ManufacturingPage7_t *config_page, - u16 sz) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; - mpi_request.Header.PageNumber = 7; - mpi_request.Header.PageVersion = MPI2_MANUFACTURING7_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sz); - out: - return r; -} - -/** - * mpt3sas_config_get_manufacturing_pg10 - obtain manufacturing page 10 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_manufacturing_pg10(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, - struct Mpi2ManufacturingPage10_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; - mpi_request.Header.PageNumber = 10; - mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_manufacturing_pg11 - obtain manufacturing page 11 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, - struct Mpi2ManufacturingPage11_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; - mpi_request.Header.PageNumber = 11; - mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_set_manufacturing_pg11 - set manufacturing page 11 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_set_manufacturing_pg11(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, - struct Mpi2ManufacturingPage11_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_MANUFACTURING; - mpi_request.Header.PageNumber = 11; - mpi_request.Header.PageVersion = MPI2_MANUFACTURING0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_bios_pg2 - obtain bios page 2 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_bios_pg2(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2BiosPage2_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; - mpi_request.Header.PageNumber = 2; - mpi_request.Header.PageVersion = MPI2_BIOSPAGE2_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_bios_pg3 - obtain bios page 3 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_bios_pg3(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2BiosPage3_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_BIOS; - mpi_request.Header.PageNumber = 3; - mpi_request.Header.PageVersion = MPI2_BIOSPAGE3_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_iounit_pg0 - obtain iounit page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage0_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_IOUNITPAGE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_iounit_pg1 - obtain iounit page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_set_iounit_pg1 - set iounit page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_set_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage1_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_IOUNITPAGE1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_iounit_pg3 - obtain iounit page 3 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @sz: size of buffer passed in config_page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_iounit_pg3(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage3_t *config_page, u16 sz) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; - mpi_request.Header.PageNumber = 3; - mpi_request.Header.PageVersion = MPI2_IOUNITPAGE3_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); - out: - return r; -} - -/** - * mpt3sas_config_get_iounit_pg8 - obtain iounit page 8 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_iounit_pg8(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2IOUnitPage8_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IO_UNIT; - mpi_request.Header.PageNumber = 8; - mpi_request.Header.PageVersion = MPI2_IOUNITPAGE8_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_ioc_pg8 - obtain ioc page 8 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_ioc_pg8(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2IOCPage8_t *config_page) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_IOC; - mpi_request.Header.PageNumber = 8; - mpi_request.Header.PageVersion = MPI2_IOCPAGE8_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_sas_device_pg0 - obtain sas device page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_HANDLE or HANDLE - * @handle: device handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_sas_device_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage0_t *config_page, - u32 form, u32 handle) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; - mpi_request.Header.PageVersion = MPI2_SASDEVICE0_PAGEVERSION; - mpi_request.Header.PageNumber = 0; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_sas_device_pg1 - obtain sas device page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_HANDLE or HANDLE - * @handle: device handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_sas_device_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasDevicePage1_t *config_page, - u32 form, u32 handle) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_DEVICE; - mpi_request.Header.PageVersion = MPI2_SASDEVICE1_PAGEVERSION; - mpi_request.Header.PageNumber = 1; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_number_hba_phys - obtain number of phys on the host - * @ioc: per adapter object - * @num_phys: pointer returned with the number of phys - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_number_hba_phys(struct MPT3SAS_ADAPTER *ioc, u8 *num_phys) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - u16 ioc_status; - Mpi2ConfigReply_t mpi_reply; - Mpi2SasIOUnitPage0_t config_page; - - *num_phys = 0; - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, &mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, &mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, - sizeof(Mpi2SasIOUnitPage0_t)); - if (!r) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) - *num_phys = config_page.NumPhys; - } - out: - return r; -} - -/** - * mpt3sas_config_get_sas_iounit_pg0 - obtain sas iounit page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @sz: size of buffer passed in config_page - * Context: sleep. - * - * Calling function should call config_get_number_hba_phys prior to - * this function, so enough memory is allocated for config_page. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_sas_iounit_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage0_t *config_page, - u16 sz) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); - out: - return r; -} - -/** - * mpt3sas_config_get_sas_iounit_pg1 - obtain sas iounit page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @sz: size of buffer passed in config_page - * Context: sleep. - * - * Calling function should call config_get_number_hba_phys prior to - * this function, so enough memory is allocated for config_page. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, - u16 sz) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); - out: - return r; -} - -/** - * mpt3sas_config_set_sas_iounit_pg1 - send sas iounit page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @sz: size of buffer passed in config_page - * Context: sleep. - * - * Calling function should call config_get_number_hba_phys prior to - * this function, so enough memory is allocated for config_page. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_set_sas_iounit_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2SasIOUnitPage1_t *config_page, - u16 sz) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_IO_UNIT; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_SASIOUNITPAGE1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_CURRENT; - _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_WRITE_NVRAM; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); - out: - return r; -} - -/** - * mpt3sas_config_get_expander_pg0 - obtain expander page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_HANDLE or HANDLE - * @handle: expander handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_expander_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2ExpanderPage0_t *config_page, u32 form, u32 handle) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_SASEXPANDER0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_expander_pg1 - obtain expander page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @phy_number: phy number - * @handle: expander handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_expander_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2ExpanderPage1_t *config_page, u32 phy_number, - u16 handle) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_EXPANDER; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_SASEXPANDER1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = - cpu_to_le32(MPI2_SAS_EXPAND_PGAD_FORM_HNDL_PHY_NUM | - (phy_number << MPI2_SAS_EXPAND_PGAD_PHYNUM_SHIFT) | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_enclosure_pg0 - obtain enclosure page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_HANDLE or HANDLE - * @handle: expander handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_enclosure_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2SasEnclosurePage0_t *config_page, u32 form, u32 handle) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_ENCLOSURE; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_SASENCLOSURE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_phy_pg0 - obtain phy page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @phy_number: phy number - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_phy_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2SasPhyPage0_t *config_page, u32 phy_number) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_SASPHY0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = - cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_phy_pg1 - obtain phy page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @phy_number: phy number - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_phy_pg1(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2SasPhyPage1_t *config_page, u32 phy_number) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_SAS_PHY; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_SASPHY1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = - cpu_to_le32(MPI2_SAS_PHY_PGAD_FORM_PHY_NUMBER | phy_number); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_raid_volume_pg1 - obtain raid volume page 1 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_HANDLE or HANDLE - * @handle: volume handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_raid_volume_pg1(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage1_t *config_page, u32 form, - u32 handle) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; - mpi_request.Header.PageNumber = 1; - mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE1_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_number_pds - obtain number of phys disk assigned to volume - * @ioc: per adapter object - * @handle: volume handle - * @num_pds: returns pds count - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_number_pds(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u8 *num_pds) -{ - Mpi2ConfigRequest_t mpi_request; - Mpi2RaidVolPage0_t config_page; - Mpi2ConfigReply_t mpi_reply; - int r; - u16 ioc_status; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - *num_pds = 0; - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, &mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = - cpu_to_le32(MPI2_RAID_VOLUME_PGAD_FORM_HANDLE | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, &mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, &config_page, - sizeof(Mpi2RaidVolPage0_t)); - if (!r) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) - *num_pds = config_page.NumPhysDisks; - } - - out: - return r; -} - -/** - * mpt3sas_config_get_raid_volume_pg0 - obtain raid volume page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_HANDLE or HANDLE - * @handle: volume handle - * @sz: size of buffer passed in config_page - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_raid_volume_pg0(struct MPT3SAS_ADAPTER *ioc, - Mpi2ConfigReply_t *mpi_reply, Mpi2RaidVolPage0_t *config_page, u32 form, - u32 handle, u16 sz) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_VOLUME; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_RAIDVOLPAGE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | handle); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, sz); - out: - return r; -} - -/** - * mpt3sas_config_get_phys_disk_pg0 - obtain phys disk page 0 - * @ioc: per adapter object - * @mpi_reply: reply mf payload returned from firmware - * @config_page: contents of the config page - * @form: GET_NEXT_PHYSDISKNUM, PHYSDISKNUM, DEVHANDLE - * @form_specific: specific to the form - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_phys_disk_pg0(struct MPT3SAS_ADAPTER *ioc, Mpi2ConfigReply_t - *mpi_reply, Mpi2RaidPhysDiskPage0_t *config_page, u32 form, - u32 form_specific) -{ - Mpi2ConfigRequest_t mpi_request; - int r; - - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_RAID_PHYSDISK; - mpi_request.Header.PageNumber = 0; - mpi_request.Header.PageVersion = MPI2_RAIDPHYSDISKPAGE0_PAGEVERSION; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.PageAddress = cpu_to_le32(form | form_specific); - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - r = _config_request(ioc, &mpi_request, mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - sizeof(*config_page)); - out: - return r; -} - -/** - * mpt3sas_config_get_volume_handle - returns volume handle for give hidden - * raid components - * @ioc: per adapter object - * @pd_handle: phys disk handle - * @volume_handle: volume handle - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_volume_handle(struct MPT3SAS_ADAPTER *ioc, u16 pd_handle, - u16 *volume_handle) -{ - Mpi2RaidConfigurationPage0_t *config_page = NULL; - Mpi2ConfigRequest_t mpi_request; - Mpi2ConfigReply_t mpi_reply; - int r, i, config_page_sz; - u16 ioc_status; - int config_num; - u16 element_type; - u16 phys_disk_dev_handle; - - *volume_handle = 0; - memset(&mpi_request, 0, sizeof(Mpi2ConfigRequest_t)); - mpi_request.Function = MPI2_FUNCTION_CONFIG; - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_HEADER; - mpi_request.Header.PageType = MPI2_CONFIG_PAGETYPE_EXTENDED; - mpi_request.ExtPageType = MPI2_CONFIG_EXTPAGETYPE_RAID_CONFIG; - mpi_request.Header.PageVersion = MPI2_RAIDCONFIG0_PAGEVERSION; - mpi_request.Header.PageNumber = 0; - ioc->build_zero_len_sge_mpi(ioc, &mpi_request.PageBufferSGE); - r = _config_request(ioc, &mpi_request, &mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, NULL, 0); - if (r) - goto out; - - mpi_request.Action = MPI2_CONFIG_ACTION_PAGE_READ_CURRENT; - config_page_sz = (le16_to_cpu(mpi_reply.ExtPageLength) * 4); - config_page = kmalloc(config_page_sz, GFP_KERNEL); - if (!config_page) { - r = -1; - goto out; - } - - config_num = 0xff; - while (1) { - mpi_request.PageAddress = cpu_to_le32(config_num + - MPI2_RAID_PGAD_FORM_GET_NEXT_CONFIGNUM); - r = _config_request(ioc, &mpi_request, &mpi_reply, - MPT3_CONFIG_PAGE_DEFAULT_TIMEOUT, config_page, - config_page_sz); - if (r) - goto out; - r = -1; - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - goto out; - for (i = 0; i < config_page->NumElements; i++) { - element_type = le16_to_cpu(config_page-> - ConfigElement[i].ElementFlags) & - MPI2_RAIDCONFIG0_EFLAGS_MASK_ELEMENT_TYPE; - if (element_type == - MPI2_RAIDCONFIG0_EFLAGS_VOL_PHYS_DISK_ELEMENT || - element_type == - MPI2_RAIDCONFIG0_EFLAGS_OCE_ELEMENT) { - phys_disk_dev_handle = - le16_to_cpu(config_page->ConfigElement[i]. - PhysDiskDevHandle); - if (phys_disk_dev_handle == pd_handle) { - *volume_handle = - le16_to_cpu(config_page-> - ConfigElement[i].VolDevHandle); - r = 0; - goto out; - } - } else if (element_type == - MPI2_RAIDCONFIG0_EFLAGS_HOT_SPARE_ELEMENT) { - *volume_handle = 0; - r = 0; - goto out; - } - } - config_num = config_page->ConfigNum; - } - out: - kfree(config_page); - return r; -} - -/** - * mpt3sas_config_get_volume_wwid - returns wwid given the volume handle - * @ioc: per adapter object - * @volume_handle: volume handle - * @wwid: volume wwid - * Context: sleep. - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_config_get_volume_wwid(struct MPT3SAS_ADAPTER *ioc, u16 volume_handle, - u64 *wwid) -{ - Mpi2ConfigReply_t mpi_reply; - Mpi2RaidVolPage1_t raid_vol_pg1; - - *wwid = 0; - if (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, - &raid_vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, - volume_handle))) { - *wwid = le64_to_cpu(raid_vol_pg1.WWID); - return 0; - } else - return -1; -} diff --git a/addons/mpt3sas/src/4.4.180/mpt3sas_ctl.c b/addons/mpt3sas/src/4.4.180/mpt3sas_ctl.c deleted file mode 100644 index 4ccde5a0..00000000 --- a/addons/mpt3sas/src/4.4.180/mpt3sas_ctl.c +++ /dev/null @@ -1,3464 +0,0 @@ -/* - * Management Module Support for MPT (Message Passing Technology) based - * controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_ctl.c - * Copyright (C) 2012-2014 LSI Corporation - * Copyright (C) 2013-2014 Avago Technologies - * (mailto: MPT-FusionLinux.pdl@avagotech.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "mpt3sas_base.h" -#include "mpt3sas_ctl.h" - - -static struct fasync_struct *async_queue; -static DECLARE_WAIT_QUEUE_HEAD(ctl_poll_wait); - - -/** - * enum block_state - blocking state - * @NON_BLOCKING: non blocking - * @BLOCKING: blocking - * - * These states are for ioctls that need to wait for a response - * from firmware, so they probably require sleep. - */ -enum block_state { - NON_BLOCKING, - BLOCKING, -}; - -/** - * _ctl_sas_device_find_by_handle - sas device search - * @ioc: per adapter object - * @handle: sas device handle (assigned by firmware) - * Context: Calling function should acquire ioc->sas_device_lock - * - * This searches for sas_device based on sas_address, then return sas_device - * object. - */ -static struct _sas_device * -_ctl_sas_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _sas_device *sas_device, *r; - - r = NULL; - list_for_each_entry(sas_device, &ioc->sas_device_list, list) { - if (sas_device->handle != handle) - continue; - r = sas_device; - goto out; - } - - out: - return r; -} - -/** - * _ctl_display_some_debug - debug routine - * @ioc: per adapter object - * @smid: system request message index - * @calling_function_name: string pass from calling function - * @mpi_reply: reply message frame - * Context: none. - * - * Function for displaying debug info helpful when debugging issues - * in this module. - */ -static void -_ctl_display_some_debug(struct MPT3SAS_ADAPTER *ioc, u16 smid, - char *calling_function_name, MPI2DefaultReply_t *mpi_reply) -{ - Mpi2ConfigRequest_t *mpi_request; - char *desc = NULL; - - if (!(ioc->logging_level & MPT_DEBUG_IOCTL)) - return; - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - switch (mpi_request->Function) { - case MPI2_FUNCTION_SCSI_IO_REQUEST: - { - Mpi2SCSIIORequest_t *scsi_request = - (Mpi2SCSIIORequest_t *)mpi_request; - - snprintf(ioc->tmp_string, MPT_STRING_LENGTH, - "scsi_io, cmd(0x%02x), cdb_len(%d)", - scsi_request->CDB.CDB32[0], - le16_to_cpu(scsi_request->IoFlags) & 0xF); - desc = ioc->tmp_string; - break; - } - case MPI2_FUNCTION_SCSI_TASK_MGMT: - desc = "task_mgmt"; - break; - case MPI2_FUNCTION_IOC_INIT: - desc = "ioc_init"; - break; - case MPI2_FUNCTION_IOC_FACTS: - desc = "ioc_facts"; - break; - case MPI2_FUNCTION_CONFIG: - { - Mpi2ConfigRequest_t *config_request = - (Mpi2ConfigRequest_t *)mpi_request; - - snprintf(ioc->tmp_string, MPT_STRING_LENGTH, - "config, type(0x%02x), ext_type(0x%02x), number(%d)", - (config_request->Header.PageType & - MPI2_CONFIG_PAGETYPE_MASK), config_request->ExtPageType, - config_request->Header.PageNumber); - desc = ioc->tmp_string; - break; - } - case MPI2_FUNCTION_PORT_FACTS: - desc = "port_facts"; - break; - case MPI2_FUNCTION_PORT_ENABLE: - desc = "port_enable"; - break; - case MPI2_FUNCTION_EVENT_NOTIFICATION: - desc = "event_notification"; - break; - case MPI2_FUNCTION_FW_DOWNLOAD: - desc = "fw_download"; - break; - case MPI2_FUNCTION_FW_UPLOAD: - desc = "fw_upload"; - break; - case MPI2_FUNCTION_RAID_ACTION: - desc = "raid_action"; - break; - case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH: - { - Mpi2SCSIIORequest_t *scsi_request = - (Mpi2SCSIIORequest_t *)mpi_request; - - snprintf(ioc->tmp_string, MPT_STRING_LENGTH, - "raid_pass, cmd(0x%02x), cdb_len(%d)", - scsi_request->CDB.CDB32[0], - le16_to_cpu(scsi_request->IoFlags) & 0xF); - desc = ioc->tmp_string; - break; - } - case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: - desc = "sas_iounit_cntl"; - break; - case MPI2_FUNCTION_SATA_PASSTHROUGH: - desc = "sata_pass"; - break; - case MPI2_FUNCTION_DIAG_BUFFER_POST: - desc = "diag_buffer_post"; - break; - case MPI2_FUNCTION_DIAG_RELEASE: - desc = "diag_release"; - break; - case MPI2_FUNCTION_SMP_PASSTHROUGH: - desc = "smp_passthrough"; - break; - } - - if (!desc) - return; - - pr_info(MPT3SAS_FMT "%s: %s, smid(%d)\n", - ioc->name, calling_function_name, desc, smid); - - if (!mpi_reply) - return; - - if (mpi_reply->IOCStatus || mpi_reply->IOCLogInfo) - pr_info(MPT3SAS_FMT - "\tiocstatus(0x%04x), loginfo(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo)); - - if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || - mpi_request->Function == - MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { - Mpi2SCSIIOReply_t *scsi_reply = - (Mpi2SCSIIOReply_t *)mpi_reply; - struct _sas_device *sas_device = NULL; - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = _ctl_sas_device_find_by_handle(ioc, - le16_to_cpu(scsi_reply->DevHandle)); - if (sas_device) { - pr_warn(MPT3SAS_FMT "\tsas_address(0x%016llx), phy(%d)\n", - ioc->name, (unsigned long long) - sas_device->sas_address, sas_device->phy); - pr_warn(MPT3SAS_FMT - "\tenclosure_logical_id(0x%016llx), slot(%d)\n", - ioc->name, (unsigned long long) - sas_device->enclosure_logical_id, sas_device->slot); - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (scsi_reply->SCSIState || scsi_reply->SCSIStatus) - pr_info(MPT3SAS_FMT - "\tscsi_state(0x%02x), scsi_status" - "(0x%02x)\n", ioc->name, - scsi_reply->SCSIState, - scsi_reply->SCSIStatus); - } -} - -/** - * mpt3sas_ctl_done - ctl module completion routine - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: none. - * - * The callback handler when using ioc->ctl_cb_idx. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_ctl_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - Mpi2SCSIIOReply_t *scsiio_reply; - const void *sense_data; - u32 sz; - - if (ioc->ctl_cmds.status == MPT3_CMD_NOT_USED) - return 1; - if (ioc->ctl_cmds.smid != smid) - return 1; - ioc->ctl_cmds.status |= MPT3_CMD_COMPLETE; - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (mpi_reply) { - memcpy(ioc->ctl_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); - ioc->ctl_cmds.status |= MPT3_CMD_REPLY_VALID; - /* get sense data */ - if (mpi_reply->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || - mpi_reply->Function == - MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { - scsiio_reply = (Mpi2SCSIIOReply_t *)mpi_reply; - if (scsiio_reply->SCSIState & - MPI2_SCSI_STATE_AUTOSENSE_VALID) { - sz = min_t(u32, SCSI_SENSE_BUFFERSIZE, - le32_to_cpu(scsiio_reply->SenseCount)); - sense_data = mpt3sas_base_get_sense_buffer(ioc, - smid); - memcpy(ioc->ctl_cmds.sense, sense_data, sz); - } - } - } - _ctl_display_some_debug(ioc, smid, "ctl_done", mpi_reply); - ioc->ctl_cmds.status &= ~MPT3_CMD_PENDING; - complete(&ioc->ctl_cmds.done); - return 1; -} - -/** - * _ctl_check_event_type - determines when an event needs logging - * @ioc: per adapter object - * @event: firmware event - * - * The bitmask in ioc->event_type[] indicates which events should be - * be saved in the driver event_log. This bitmask is set by application. - * - * Returns 1 when event should be captured, or zero means no match. - */ -static int -_ctl_check_event_type(struct MPT3SAS_ADAPTER *ioc, u16 event) -{ - u16 i; - u32 desired_event; - - if (event >= 128 || !event || !ioc->event_log) - return 0; - - desired_event = (1 << (event % 32)); - if (!desired_event) - desired_event = 1; - i = event / 32; - return desired_event & ioc->event_type[i]; -} - -/** - * mpt3sas_ctl_add_to_event_log - add event - * @ioc: per adapter object - * @mpi_reply: reply message frame - * - * Return nothing. - */ -void -mpt3sas_ctl_add_to_event_log(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventNotificationReply_t *mpi_reply) -{ - struct MPT3_IOCTL_EVENTS *event_log; - u16 event; - int i; - u32 sz, event_data_sz; - u8 send_aen = 0; - - if (!ioc->event_log) - return; - - event = le16_to_cpu(mpi_reply->Event); - - if (_ctl_check_event_type(ioc, event)) { - - /* insert entry into circular event_log */ - i = ioc->event_context % MPT3SAS_CTL_EVENT_LOG_SIZE; - event_log = ioc->event_log; - event_log[i].event = event; - event_log[i].context = ioc->event_context++; - - event_data_sz = le16_to_cpu(mpi_reply->EventDataLength)*4; - sz = min_t(u32, event_data_sz, MPT3_EVENT_DATA_SIZE); - memset(event_log[i].data, 0, MPT3_EVENT_DATA_SIZE); - memcpy(event_log[i].data, mpi_reply->EventData, sz); - send_aen = 1; - } - - /* This aen_event_read_flag flag is set until the - * application has read the event log. - * For MPI2_EVENT_LOG_ENTRY_ADDED, we always notify. - */ - if (event == MPI2_EVENT_LOG_ENTRY_ADDED || - (send_aen && !ioc->aen_event_read_flag)) { - ioc->aen_event_read_flag = 1; - wake_up_interruptible(&ctl_poll_wait); - if (async_queue) - kill_fasync(&async_queue, SIGIO, POLL_IN); - } -} - -/** - * mpt3sas_ctl_event_callback - firmware event handler (called at ISR time) - * @ioc: per adapter object - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: interrupt. - * - * This function merely adds a new work task into ioc->firmware_event_thread. - * The tasks are worked from _firmware_event_work in user context. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_ctl_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, - u32 reply) -{ - Mpi2EventNotificationReply_t *mpi_reply; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - mpt3sas_ctl_add_to_event_log(ioc, mpi_reply); - return 1; -} - -/** - * _ctl_verify_adapter - validates ioc_number passed from application - * @ioc: per adapter object - * @iocpp: The ioc pointer is returned in this. - * @mpi_version: will be MPI2_VERSION for mpt2ctl ioctl device & - * MPI25_VERSION for mpt3ctl ioctl device. - * - * Return (-1) means error, else ioc_number. - */ -static int -_ctl_verify_adapter(int ioc_number, struct MPT3SAS_ADAPTER **iocpp, - int mpi_version) -{ - struct MPT3SAS_ADAPTER *ioc; - /* global ioc lock to protect controller on list operations */ - spin_lock(&gioc_lock); - list_for_each_entry(ioc, &mpt3sas_ioc_list, list) { - if (ioc->id != ioc_number) - continue; - /* Check whether this ioctl command is from right - * ioctl device or not, if not continue the search. - */ - if (ioc->hba_mpi_version_belonged != mpi_version) - continue; - spin_unlock(&gioc_lock); - *iocpp = ioc; - return ioc_number; - } - spin_unlock(&gioc_lock); - *iocpp = NULL; - return -1; -} - -/** - * mpt3sas_ctl_reset_handler - reset callback handler (for ctl) - * @ioc: per adapter object - * @reset_phase: phase - * - * The handler for doing any required cleanup or initialization. - * - * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET, - * MPT3_IOC_DONE_RESET - */ -void -mpt3sas_ctl_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase) -{ - int i; - u8 issue_reset; - - switch (reset_phase) { - case MPT3_IOC_PRE_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__)); - for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { - if (!(ioc->diag_buffer_status[i] & - MPT3_DIAG_BUFFER_IS_REGISTERED)) - continue; - if ((ioc->diag_buffer_status[i] & - MPT3_DIAG_BUFFER_IS_RELEASED)) - continue; - mpt3sas_send_diag_release(ioc, i, &issue_reset); - } - break; - case MPT3_IOC_AFTER_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__)); - if (ioc->ctl_cmds.status & MPT3_CMD_PENDING) { - ioc->ctl_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->ctl_cmds.smid); - complete(&ioc->ctl_cmds.done); - } - break; - case MPT3_IOC_DONE_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__)); - - for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { - if (!(ioc->diag_buffer_status[i] & - MPT3_DIAG_BUFFER_IS_REGISTERED)) - continue; - if ((ioc->diag_buffer_status[i] & - MPT3_DIAG_BUFFER_IS_RELEASED)) - continue; - ioc->diag_buffer_status[i] |= - MPT3_DIAG_BUFFER_IS_DIAG_RESET; - } - break; - } -} - -/** - * _ctl_fasync - - * @fd - - * @filep - - * @mode - - * - * Called when application request fasyn callback handler. - */ -int -_ctl_fasync(int fd, struct file *filep, int mode) -{ - return fasync_helper(fd, filep, mode, &async_queue); -} - -/** - * _ctl_poll - - * @file - - * @wait - - * - */ -unsigned int -_ctl_poll(struct file *filep, poll_table *wait) -{ - struct MPT3SAS_ADAPTER *ioc; - - poll_wait(filep, &ctl_poll_wait, wait); - - /* global ioc lock to protect controller on list operations */ - spin_lock(&gioc_lock); - list_for_each_entry(ioc, &mpt3sas_ioc_list, list) { - if (ioc->aen_event_read_flag) { - spin_unlock(&gioc_lock); - return POLLIN | POLLRDNORM; - } - } - spin_unlock(&gioc_lock); - return 0; -} - -/** - * _ctl_set_task_mid - assign an active smid to tm request - * @ioc: per adapter object - * @karg - (struct mpt3_ioctl_command) - * @tm_request - pointer to mf from user space - * - * Returns 0 when an smid if found, else fail. - * during failure, the reply frame is filled. - */ -static int -_ctl_set_task_mid(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command *karg, - Mpi2SCSITaskManagementRequest_t *tm_request) -{ - u8 found = 0; - u16 i; - u16 handle; - struct scsi_cmnd *scmd; - struct MPT3SAS_DEVICE *priv_data; - unsigned long flags; - Mpi2SCSITaskManagementReply_t *tm_reply; - u32 sz; - u32 lun; - char *desc = NULL; - - if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) - desc = "abort_task"; - else if (tm_request->TaskType == MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) - desc = "query_task"; - else - return 0; - - lun = scsilun_to_int((struct scsi_lun *)tm_request->LUN); - - handle = le16_to_cpu(tm_request->DevHandle); - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - for (i = ioc->scsiio_depth; i && !found; i--) { - scmd = ioc->scsi_lookup[i - 1].scmd; - if (scmd == NULL || scmd->device == NULL || - scmd->device->hostdata == NULL) - continue; - if (lun != scmd->device->lun) - continue; - priv_data = scmd->device->hostdata; - if (priv_data->sas_target == NULL) - continue; - if (priv_data->sas_target->handle != handle) - continue; - tm_request->TaskMID = cpu_to_le16(ioc->scsi_lookup[i - 1].smid); - found = 1; - } - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - - if (!found) { - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), lun(%d), no active mid!!\n", - ioc->name, - desc, le16_to_cpu(tm_request->DevHandle), lun)); - tm_reply = ioc->ctl_cmds.reply; - tm_reply->DevHandle = tm_request->DevHandle; - tm_reply->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; - tm_reply->TaskType = tm_request->TaskType; - tm_reply->MsgLength = sizeof(Mpi2SCSITaskManagementReply_t)/4; - tm_reply->VP_ID = tm_request->VP_ID; - tm_reply->VF_ID = tm_request->VF_ID; - sz = min_t(u32, karg->max_reply_bytes, ioc->reply_sz); - if (copy_to_user(karg->reply_frame_buf_ptr, ioc->ctl_cmds.reply, - sz)) - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - return 1; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), lun(%d), task_mid(%d)\n", ioc->name, - desc, le16_to_cpu(tm_request->DevHandle), lun, - le16_to_cpu(tm_request->TaskMID))); - return 0; -} - -/** - * _ctl_do_mpt_command - main handler for MPT3COMMAND opcode - * @ioc: per adapter object - * @karg - (struct mpt3_ioctl_command) - * @mf - pointer to mf in user space - */ -static long -_ctl_do_mpt_command(struct MPT3SAS_ADAPTER *ioc, struct mpt3_ioctl_command karg, - void __user *mf) -{ - MPI2RequestHeader_t *mpi_request = NULL, *request; - MPI2DefaultReply_t *mpi_reply; - u32 ioc_state; - u16 ioc_status; - u16 smid; - unsigned long timeout, timeleft; - u8 issue_reset; - u32 sz; - void *psge; - void *data_out = NULL; - dma_addr_t data_out_dma = 0; - size_t data_out_sz = 0; - void *data_in = NULL; - dma_addr_t data_in_dma = 0; - size_t data_in_sz = 0; - long ret; - u16 wait_state_count; - - issue_reset = 0; - - if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n", - ioc->name, __func__); - ret = -EAGAIN; - goto out; - } - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - ret = -EFAULT; - goto out; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, - __func__, wait_state_count); - } - if (wait_state_count) - pr_info(MPT3SAS_FMT "%s: ioc is operational\n", - ioc->name, __func__); - - mpi_request = kzalloc(ioc->request_sz, GFP_KERNEL); - if (!mpi_request) { - pr_err(MPT3SAS_FMT - "%s: failed obtaining a memory for mpi_request\n", - ioc->name, __func__); - ret = -ENOMEM; - goto out; - } - - /* Check for overflow and wraparound */ - if (karg.data_sge_offset * 4 > ioc->request_sz || - karg.data_sge_offset > (UINT_MAX / 4)) { - ret = -EINVAL; - goto out; - } - - /* copy in request message frame from user */ - if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, __LINE__, - __func__); - ret = -EFAULT; - goto out; - } - - if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { - smid = mpt3sas_base_get_smid_hpr(ioc, ioc->ctl_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - ret = -EAGAIN; - goto out; - } - } else { - - smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->ctl_cb_idx, NULL); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - ret = -EAGAIN; - goto out; - } - } - - ret = 0; - ioc->ctl_cmds.status = MPT3_CMD_PENDING; - memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); - request = mpt3sas_base_get_msg_frame(ioc, smid); - memcpy(request, mpi_request, karg.data_sge_offset*4); - ioc->ctl_cmds.smid = smid; - data_out_sz = karg.data_out_size; - data_in_sz = karg.data_in_size; - - if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || - mpi_request->Function == MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH) { - if (!le16_to_cpu(mpi_request->FunctionDependent1) || - le16_to_cpu(mpi_request->FunctionDependent1) > - ioc->facts.MaxDevHandle) { - ret = -EINVAL; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - } - - /* obtain dma-able memory for data transfer */ - if (data_out_sz) /* WRITE */ { - data_out = pci_alloc_consistent(ioc->pdev, data_out_sz, - &data_out_dma); - if (!data_out) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - ret = -ENOMEM; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - if (copy_from_user(data_out, karg.data_out_buf_ptr, - data_out_sz)) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - ret = -EFAULT; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - } - - if (data_in_sz) /* READ */ { - data_in = pci_alloc_consistent(ioc->pdev, data_in_sz, - &data_in_dma); - if (!data_in) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - ret = -ENOMEM; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - } - - psge = (void *)request + (karg.data_sge_offset*4); - - /* send command to firmware */ - _ctl_display_some_debug(ioc, smid, "ctl_request", NULL); - - init_completion(&ioc->ctl_cmds.done); - switch (mpi_request->Function) { - case MPI2_FUNCTION_SCSI_IO_REQUEST: - case MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH: - { - Mpi2SCSIIORequest_t *scsiio_request = - (Mpi2SCSIIORequest_t *)request; - scsiio_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; - scsiio_request->SenseBufferLowAddress = - mpt3sas_base_get_sense_buffer_dma(ioc, smid); - memset(ioc->ctl_cmds.sense, 0, SCSI_SENSE_BUFFERSIZE); - ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, - data_in_dma, data_in_sz); - - if (mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST) - mpt3sas_base_put_smid_scsi_io(ioc, smid, - le16_to_cpu(mpi_request->FunctionDependent1)); - else - mpt3sas_base_put_smid_default(ioc, smid); - break; - } - case MPI2_FUNCTION_SCSI_TASK_MGMT: - { - Mpi2SCSITaskManagementRequest_t *tm_request = - (Mpi2SCSITaskManagementRequest_t *)request; - - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "TASK_MGMT: handle(0x%04x), task_type(0x%02x)\n", - ioc->name, - le16_to_cpu(tm_request->DevHandle), tm_request->TaskType)); - - if (tm_request->TaskType == - MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK || - tm_request->TaskType == - MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK) { - if (_ctl_set_task_mid(ioc, &karg, tm_request)) { - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - } - - mpt3sas_scsih_set_tm_flag(ioc, le16_to_cpu( - tm_request->DevHandle)); - ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, - data_in_dma, data_in_sz); - mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); - break; - } - case MPI2_FUNCTION_SMP_PASSTHROUGH: - { - Mpi2SmpPassthroughRequest_t *smp_request = - (Mpi2SmpPassthroughRequest_t *)mpi_request; - u8 *data; - - /* ioc determines which port to use */ - smp_request->PhysicalPort = 0xFF; - if (smp_request->PassthroughFlags & - MPI2_SMP_PT_REQ_PT_FLAGS_IMMEDIATE) - data = (u8 *)&smp_request->SGL; - else { - if (unlikely(data_out == NULL)) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - mpt3sas_base_free_smid(ioc, smid); - ret = -EINVAL; - goto out; - } - data = data_out; - } - - if (data[1] == 0x91 && (data[10] == 1 || data[10] == 2)) { - ioc->ioc_link_reset_in_progress = 1; - ioc->ignore_loginfos = 1; - } - ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, - data_in_sz); - mpt3sas_base_put_smid_default(ioc, smid); - break; - } - case MPI2_FUNCTION_SATA_PASSTHROUGH: - case MPI2_FUNCTION_FW_DOWNLOAD: - case MPI2_FUNCTION_FW_UPLOAD: - { - ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, - data_in_sz); - mpt3sas_base_put_smid_default(ioc, smid); - break; - } - case MPI2_FUNCTION_TOOLBOX: - { - Mpi2ToolboxCleanRequest_t *toolbox_request = - (Mpi2ToolboxCleanRequest_t *)mpi_request; - - if (toolbox_request->Tool == MPI2_TOOLBOX_DIAGNOSTIC_CLI_TOOL) { - ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, - data_in_dma, data_in_sz); - } else { - ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, - data_in_dma, data_in_sz); - } - mpt3sas_base_put_smid_default(ioc, smid); - break; - } - case MPI2_FUNCTION_SAS_IO_UNIT_CONTROL: - { - Mpi2SasIoUnitControlRequest_t *sasiounit_request = - (Mpi2SasIoUnitControlRequest_t *)mpi_request; - - if (sasiounit_request->Operation == MPI2_SAS_OP_PHY_HARD_RESET - || sasiounit_request->Operation == - MPI2_SAS_OP_PHY_LINK_RESET) { - ioc->ioc_link_reset_in_progress = 1; - ioc->ignore_loginfos = 1; - } - /* drop to default case for posting the request */ - } - default: - ioc->build_sg_mpi(ioc, psge, data_out_dma, data_out_sz, - data_in_dma, data_in_sz); - mpt3sas_base_put_smid_default(ioc, smid); - break; - } - - if (karg.timeout < MPT3_IOCTL_DEFAULT_TIMEOUT) - timeout = MPT3_IOCTL_DEFAULT_TIMEOUT; - else - timeout = karg.timeout; - timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, - timeout*HZ); - if (mpi_request->Function == MPI2_FUNCTION_SCSI_TASK_MGMT) { - Mpi2SCSITaskManagementRequest_t *tm_request = - (Mpi2SCSITaskManagementRequest_t *)mpi_request; - mpt3sas_scsih_clear_tm_flag(ioc, le16_to_cpu( - tm_request->DevHandle)); - mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT); - } else if ((mpi_request->Function == MPI2_FUNCTION_SMP_PASSTHROUGH || - mpi_request->Function == MPI2_FUNCTION_SAS_IO_UNIT_CONTROL) && - ioc->ioc_link_reset_in_progress) { - ioc->ioc_link_reset_in_progress = 0; - ioc->ignore_loginfos = 0; - } - if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name, - __func__); - _debug_dump_mf(mpi_request, karg.data_sge_offset); - if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - mpi_reply = ioc->ctl_cmds.reply; - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; - - if (mpi_reply->Function == MPI2_FUNCTION_SCSI_TASK_MGMT && - (ioc->logging_level & MPT_DEBUG_TM)) { - Mpi2SCSITaskManagementReply_t *tm_reply = - (Mpi2SCSITaskManagementReply_t *)mpi_reply; - - pr_info(MPT3SAS_FMT "TASK_MGMT: " \ - "IOCStatus(0x%04x), IOCLogInfo(0x%08x), " - "TerminationCount(0x%08x)\n", ioc->name, - le16_to_cpu(tm_reply->IOCStatus), - le32_to_cpu(tm_reply->IOCLogInfo), - le32_to_cpu(tm_reply->TerminationCount)); - } - - /* copy out xdata to user */ - if (data_in_sz) { - if (copy_to_user(karg.data_in_buf_ptr, data_in, - data_in_sz)) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - ret = -ENODATA; - goto out; - } - } - - /* copy out reply message frame to user */ - if (karg.max_reply_bytes) { - sz = min_t(u32, karg.max_reply_bytes, ioc->reply_sz); - if (copy_to_user(karg.reply_frame_buf_ptr, ioc->ctl_cmds.reply, - sz)) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - ret = -ENODATA; - goto out; - } - } - - /* copy out sense to user */ - if (karg.max_sense_bytes && (mpi_request->Function == - MPI2_FUNCTION_SCSI_IO_REQUEST || mpi_request->Function == - MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH)) { - sz = min_t(u32, karg.max_sense_bytes, SCSI_SENSE_BUFFERSIZE); - if (copy_to_user(karg.sense_data_ptr, ioc->ctl_cmds.sense, - sz)) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - ret = -ENODATA; - goto out; - } - } - - issue_host_reset: - if (issue_reset) { - ret = -ENODATA; - if ((mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST || - mpi_request->Function == - MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH || - mpi_request->Function == MPI2_FUNCTION_SATA_PASSTHROUGH)) { - pr_info(MPT3SAS_FMT "issue target reset: handle = (0x%04x)\n", - ioc->name, - le16_to_cpu(mpi_request->FunctionDependent1)); - mpt3sas_halt_firmware(ioc); - mpt3sas_scsih_issue_tm(ioc, - le16_to_cpu(mpi_request->FunctionDependent1), 0, 0, - 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, 30, - TM_MUTEX_ON); - } else - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - } - - out: - - /* free memory associated with sg buffers */ - if (data_in) - pci_free_consistent(ioc->pdev, data_in_sz, data_in, - data_in_dma); - - if (data_out) - pci_free_consistent(ioc->pdev, data_out_sz, data_out, - data_out_dma); - - kfree(mpi_request); - ioc->ctl_cmds.status = MPT3_CMD_NOT_USED; - return ret; -} - -/** - * _ctl_getiocinfo - main handler for MPT3IOCINFO opcode - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_getiocinfo(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_ioctl_iocinfo karg; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, - __func__)); - - memset(&karg, 0 , sizeof(karg)); - if (ioc->pfacts) - karg.port_number = ioc->pfacts[0].PortNumber; - karg.hw_rev = ioc->pdev->revision; - karg.pci_id = ioc->pdev->device; - karg.subsystem_device = ioc->pdev->subsystem_device; - karg.subsystem_vendor = ioc->pdev->subsystem_vendor; - karg.pci_information.u.bits.bus = ioc->pdev->bus->number; - karg.pci_information.u.bits.device = PCI_SLOT(ioc->pdev->devfn); - karg.pci_information.u.bits.function = PCI_FUNC(ioc->pdev->devfn); - karg.pci_information.segment_id = pci_domain_nr(ioc->pdev->bus); - karg.firmware_version = ioc->facts.FWVersion.Word; - strcpy(karg.driver_version, ioc->driver_name); - strcat(karg.driver_version, "-"); - switch (ioc->hba_mpi_version_belonged) { - case MPI2_VERSION: - if (ioc->is_warpdrive) - karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2_SSS6200; - else - karg.adapter_type = MPT2_IOCTL_INTERFACE_SAS2; - strcat(karg.driver_version, MPT2SAS_DRIVER_VERSION); - break; - case MPI25_VERSION: - karg.adapter_type = MPT3_IOCTL_INTERFACE_SAS3; - strcat(karg.driver_version, MPT3SAS_DRIVER_VERSION); - break; - } - karg.bios_version = le32_to_cpu(ioc->bios_pg3.BiosVersion); - - if (copy_to_user(arg, &karg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - return 0; -} - -/** - * _ctl_eventquery - main handler for MPT3EVENTQUERY opcode - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_eventquery(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_ioctl_eventquery karg; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, - __func__)); - - karg.event_entries = MPT3SAS_CTL_EVENT_LOG_SIZE; - memcpy(karg.event_types, ioc->event_type, - MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32)); - - if (copy_to_user(arg, &karg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - return 0; -} - -/** - * _ctl_eventenable - main handler for MPT3EVENTENABLE opcode - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_eventenable(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_ioctl_eventenable karg; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, - __func__)); - - memcpy(ioc->event_type, karg.event_types, - MPI2_EVENT_NOTIFY_EVENTMASK_WORDS * sizeof(u32)); - mpt3sas_base_validate_event_type(ioc, ioc->event_type); - - if (ioc->event_log) - return 0; - /* initialize event_log */ - ioc->event_context = 0; - ioc->aen_event_read_flag = 0; - ioc->event_log = kcalloc(MPT3SAS_CTL_EVENT_LOG_SIZE, - sizeof(struct MPT3_IOCTL_EVENTS), GFP_KERNEL); - if (!ioc->event_log) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -ENOMEM; - } - return 0; -} - -/** - * _ctl_eventreport - main handler for MPT3EVENTREPORT opcode - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_eventreport(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_ioctl_eventreport karg; - u32 number_bytes, max_events, max; - struct mpt3_ioctl_eventreport __user *uarg = arg; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, - __func__)); - - number_bytes = karg.hdr.max_data_size - - sizeof(struct mpt3_ioctl_header); - max_events = number_bytes/sizeof(struct MPT3_IOCTL_EVENTS); - max = min_t(u32, MPT3SAS_CTL_EVENT_LOG_SIZE, max_events); - - /* If fewer than 1 event is requested, there must have - * been some type of error. - */ - if (!max || !ioc->event_log) - return -ENODATA; - - number_bytes = max * sizeof(struct MPT3_IOCTL_EVENTS); - if (copy_to_user(uarg->event_data, ioc->event_log, number_bytes)) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - /* reset flag so SIGIO can restart */ - ioc->aen_event_read_flag = 0; - return 0; -} - -/** - * _ctl_do_reset - main handler for MPT3HARDRESET opcode - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_do_reset(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_ioctl_diag_reset karg; - int retval; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - if (ioc->shost_recovery || ioc->pci_error_recovery || - ioc->is_driver_loading) - return -EAGAIN; - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", ioc->name, - __func__)); - - retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - pr_info(MPT3SAS_FMT "host reset: %s\n", - ioc->name, ((!retval) ? "SUCCESS" : "FAILED")); - return 0; -} - -/** - * _ctl_btdh_search_sas_device - searching for sas device - * @ioc: per adapter object - * @btdh: btdh ioctl payload - */ -static int -_ctl_btdh_search_sas_device(struct MPT3SAS_ADAPTER *ioc, - struct mpt3_ioctl_btdh_mapping *btdh) -{ - struct _sas_device *sas_device; - unsigned long flags; - int rc = 0; - - if (list_empty(&ioc->sas_device_list)) - return rc; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - list_for_each_entry(sas_device, &ioc->sas_device_list, list) { - if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF && - btdh->handle == sas_device->handle) { - btdh->bus = sas_device->channel; - btdh->id = sas_device->id; - rc = 1; - goto out; - } else if (btdh->bus == sas_device->channel && btdh->id == - sas_device->id && btdh->handle == 0xFFFF) { - btdh->handle = sas_device->handle; - rc = 1; - goto out; - } - } - out: - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return rc; -} - -/** - * _ctl_btdh_search_raid_device - searching for raid device - * @ioc: per adapter object - * @btdh: btdh ioctl payload - */ -static int -_ctl_btdh_search_raid_device(struct MPT3SAS_ADAPTER *ioc, - struct mpt3_ioctl_btdh_mapping *btdh) -{ - struct _raid_device *raid_device; - unsigned long flags; - int rc = 0; - - if (list_empty(&ioc->raid_device_list)) - return rc; - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - list_for_each_entry(raid_device, &ioc->raid_device_list, list) { - if (btdh->bus == 0xFFFFFFFF && btdh->id == 0xFFFFFFFF && - btdh->handle == raid_device->handle) { - btdh->bus = raid_device->channel; - btdh->id = raid_device->id; - rc = 1; - goto out; - } else if (btdh->bus == raid_device->channel && btdh->id == - raid_device->id && btdh->handle == 0xFFFF) { - btdh->handle = raid_device->handle; - rc = 1; - goto out; - } - } - out: - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - return rc; -} - -/** - * _ctl_btdh_mapping - main handler for MPT3BTDHMAPPING opcode - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_btdh_mapping(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_ioctl_btdh_mapping karg; - int rc; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - rc = _ctl_btdh_search_sas_device(ioc, &karg); - if (!rc) - _ctl_btdh_search_raid_device(ioc, &karg); - - if (copy_to_user(arg, &karg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - return 0; -} - -/** - * _ctl_diag_capability - return diag buffer capability - * @ioc: per adapter object - * @buffer_type: specifies either TRACE, SNAPSHOT, or EXTENDED - * - * returns 1 when diag buffer support is enabled in firmware - */ -static u8 -_ctl_diag_capability(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type) -{ - u8 rc = 0; - - switch (buffer_type) { - case MPI2_DIAG_BUF_TYPE_TRACE: - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_DIAG_TRACE_BUFFER) - rc = 1; - break; - case MPI2_DIAG_BUF_TYPE_SNAPSHOT: - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_SNAPSHOT_BUFFER) - rc = 1; - break; - case MPI2_DIAG_BUF_TYPE_EXTENDED: - if (ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER) - rc = 1; - } - - return rc; -} - - -/** - * _ctl_diag_register_2 - wrapper for registering diag buffer support - * @ioc: per adapter object - * @diag_register: the diag_register struct passed in from user space - * - */ -static long -_ctl_diag_register_2(struct MPT3SAS_ADAPTER *ioc, - struct mpt3_diag_register *diag_register) -{ - int rc, i; - void *request_data = NULL; - dma_addr_t request_data_dma; - u32 request_data_sz = 0; - Mpi2DiagBufferPostRequest_t *mpi_request; - Mpi2DiagBufferPostReply_t *mpi_reply; - u8 buffer_type; - unsigned long timeleft; - u16 smid; - u16 ioc_status; - u32 ioc_state; - u8 issue_reset = 0; - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - buffer_type = diag_register->buffer_type; - if (!_ctl_diag_capability(ioc, buffer_type)) { - pr_err(MPT3SAS_FMT - "%s: doesn't have capability for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -EPERM; - } - - if (ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_REGISTERED) { - pr_err(MPT3SAS_FMT - "%s: already has a registered buffer for buffer_type(0x%02x)\n", - ioc->name, __func__, - buffer_type); - return -EINVAL; - } - - if (diag_register->requested_buffer_size % 4) { - pr_err(MPT3SAS_FMT - "%s: the requested_buffer_size is not 4 byte aligned\n", - ioc->name, __func__); - return -EINVAL; - } - - smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - rc = 0; - ioc->ctl_cmds.status = MPT3_CMD_PENDING; - memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->ctl_cmds.smid = smid; - - request_data = ioc->diag_buffer[buffer_type]; - request_data_sz = diag_register->requested_buffer_size; - ioc->unique_id[buffer_type] = diag_register->unique_id; - ioc->diag_buffer_status[buffer_type] = 0; - memcpy(ioc->product_specific[buffer_type], - diag_register->product_specific, MPT3_PRODUCT_SPECIFIC_DWORDS); - ioc->diagnostic_flags[buffer_type] = diag_register->diagnostic_flags; - - if (request_data) { - request_data_dma = ioc->diag_buffer_dma[buffer_type]; - if (request_data_sz != ioc->diag_buffer_sz[buffer_type]) { - pci_free_consistent(ioc->pdev, - ioc->diag_buffer_sz[buffer_type], - request_data, request_data_dma); - request_data = NULL; - } - } - - if (request_data == NULL) { - ioc->diag_buffer_sz[buffer_type] = 0; - ioc->diag_buffer_dma[buffer_type] = 0; - request_data = pci_alloc_consistent( - ioc->pdev, request_data_sz, &request_data_dma); - if (request_data == NULL) { - pr_err(MPT3SAS_FMT "%s: failed allocating memory" \ - " for diag buffers, requested size(%d)\n", - ioc->name, __func__, request_data_sz); - mpt3sas_base_free_smid(ioc, smid); - return -ENOMEM; - } - ioc->diag_buffer[buffer_type] = request_data; - ioc->diag_buffer_sz[buffer_type] = request_data_sz; - ioc->diag_buffer_dma[buffer_type] = request_data_dma; - } - - mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST; - mpi_request->BufferType = diag_register->buffer_type; - mpi_request->Flags = cpu_to_le32(diag_register->diagnostic_flags); - mpi_request->BufferAddress = cpu_to_le64(request_data_dma); - mpi_request->BufferLength = cpu_to_le32(request_data_sz); - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: diag_buffer(0x%p), dma(0x%llx), sz(%d)\n", - ioc->name, __func__, request_data, - (unsigned long long)request_data_dma, - le32_to_cpu(mpi_request->BufferLength))); - - for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++) - mpi_request->ProductSpecific[i] = - cpu_to_le32(ioc->product_specific[buffer_type][i]); - - init_completion(&ioc->ctl_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, - MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); - - if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name, - __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2DiagBufferPostRequest_t)/4); - if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - /* process the completed Reply Message Frame */ - if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) { - pr_err(MPT3SAS_FMT "%s: no reply message\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - - mpi_reply = ioc->ctl_cmds.reply; - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; - - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { - ioc->diag_buffer_status[buffer_type] |= - MPT3_DIAG_BUFFER_IS_REGISTERED; - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: success\n", - ioc->name, __func__)); - } else { - pr_info(MPT3SAS_FMT - "%s: ioc_status(0x%04x) log_info(0x%08x)\n", - ioc->name, __func__, - ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); - rc = -EFAULT; - } - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - - out: - - if (rc && request_data) - pci_free_consistent(ioc->pdev, request_data_sz, - request_data, request_data_dma); - - ioc->ctl_cmds.status = MPT3_CMD_NOT_USED; - return rc; -} - -/** - * mpt3sas_enable_diag_buffer - enabling diag_buffers support driver load time - * @ioc: per adapter object - * @bits_to_register: bitwise field where trace is bit 0, and snapshot is bit 1 - * - * This is called when command line option diag_buffer_enable is enabled - * at driver load time. - */ -void -mpt3sas_enable_diag_buffer(struct MPT3SAS_ADAPTER *ioc, u8 bits_to_register) -{ - struct mpt3_diag_register diag_register; - - memset(&diag_register, 0, sizeof(struct mpt3_diag_register)); - - if (bits_to_register & 1) { - pr_info(MPT3SAS_FMT "registering trace buffer support\n", - ioc->name); - ioc->diag_trigger_master.MasterData = - (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET); - diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE; - /* register for 2MB buffers */ - diag_register.requested_buffer_size = 2 * (1024 * 1024); - diag_register.unique_id = 0x7075900; - _ctl_diag_register_2(ioc, &diag_register); - } - - if (bits_to_register & 2) { - pr_info(MPT3SAS_FMT "registering snapshot buffer support\n", - ioc->name); - diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_SNAPSHOT; - /* register for 2MB buffers */ - diag_register.requested_buffer_size = 2 * (1024 * 1024); - diag_register.unique_id = 0x7075901; - _ctl_diag_register_2(ioc, &diag_register); - } - - if (bits_to_register & 4) { - pr_info(MPT3SAS_FMT "registering extended buffer support\n", - ioc->name); - diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_EXTENDED; - /* register for 2MB buffers */ - diag_register.requested_buffer_size = 2 * (1024 * 1024); - diag_register.unique_id = 0x7075901; - _ctl_diag_register_2(ioc, &diag_register); - } -} - -/** - * _ctl_diag_register - application register with driver - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - * - * This will allow the driver to setup any required buffers that will be - * needed by firmware to communicate with the driver. - */ -static long -_ctl_diag_register(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_diag_register karg; - long rc; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - rc = _ctl_diag_register_2(ioc, &karg); - return rc; -} - -/** - * _ctl_diag_unregister - application unregister with driver - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - * - * This will allow the driver to cleanup any memory allocated for diag - * messages and to free up any resources. - */ -static long -_ctl_diag_unregister(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_diag_unregister karg; - void *request_data; - dma_addr_t request_data_dma; - u32 request_data_sz; - u8 buffer_type; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - buffer_type = karg.unique_id & 0x000000ff; - if (!_ctl_diag_capability(ioc, buffer_type)) { - pr_err(MPT3SAS_FMT - "%s: doesn't have capability for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -EPERM; - } - - if ((ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - pr_err(MPT3SAS_FMT - "%s: buffer_type(0x%02x) is not registered\n", - ioc->name, __func__, buffer_type); - return -EINVAL; - } - if ((ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_RELEASED) == 0) { - pr_err(MPT3SAS_FMT - "%s: buffer_type(0x%02x) has not been released\n", - ioc->name, __func__, buffer_type); - return -EINVAL; - } - - if (karg.unique_id != ioc->unique_id[buffer_type]) { - pr_err(MPT3SAS_FMT - "%s: unique_id(0x%08x) is not registered\n", - ioc->name, __func__, karg.unique_id); - return -EINVAL; - } - - request_data = ioc->diag_buffer[buffer_type]; - if (!request_data) { - pr_err(MPT3SAS_FMT - "%s: doesn't have memory allocated for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -ENOMEM; - } - - request_data_sz = ioc->diag_buffer_sz[buffer_type]; - request_data_dma = ioc->diag_buffer_dma[buffer_type]; - pci_free_consistent(ioc->pdev, request_data_sz, - request_data, request_data_dma); - ioc->diag_buffer[buffer_type] = NULL; - ioc->diag_buffer_status[buffer_type] = 0; - return 0; -} - -/** - * _ctl_diag_query - query relevant info associated with diag buffers - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - * - * The application will send only buffer_type and unique_id. Driver will - * inspect unique_id first, if valid, fill in all the info. If unique_id is - * 0x00, the driver will return info specified by Buffer Type. - */ -static long -_ctl_diag_query(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_diag_query karg; - void *request_data; - int i; - u8 buffer_type; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - karg.application_flags = 0; - buffer_type = karg.buffer_type; - - if (!_ctl_diag_capability(ioc, buffer_type)) { - pr_err(MPT3SAS_FMT - "%s: doesn't have capability for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -EPERM; - } - - if ((ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - pr_err(MPT3SAS_FMT - "%s: buffer_type(0x%02x) is not registered\n", - ioc->name, __func__, buffer_type); - return -EINVAL; - } - - if (karg.unique_id & 0xffffff00) { - if (karg.unique_id != ioc->unique_id[buffer_type]) { - pr_err(MPT3SAS_FMT - "%s: unique_id(0x%08x) is not registered\n", - ioc->name, __func__, karg.unique_id); - return -EINVAL; - } - } - - request_data = ioc->diag_buffer[buffer_type]; - if (!request_data) { - pr_err(MPT3SAS_FMT - "%s: doesn't have buffer for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -ENOMEM; - } - - if (ioc->diag_buffer_status[buffer_type] & MPT3_DIAG_BUFFER_IS_RELEASED) - karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED | - MPT3_APP_FLAGS_BUFFER_VALID); - else - karg.application_flags = (MPT3_APP_FLAGS_APP_OWNED | - MPT3_APP_FLAGS_BUFFER_VALID | - MPT3_APP_FLAGS_FW_BUFFER_ACCESS); - - for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++) - karg.product_specific[i] = - ioc->product_specific[buffer_type][i]; - - karg.total_buffer_size = ioc->diag_buffer_sz[buffer_type]; - karg.driver_added_buffer_size = 0; - karg.unique_id = ioc->unique_id[buffer_type]; - karg.diagnostic_flags = ioc->diagnostic_flags[buffer_type]; - - if (copy_to_user(arg, &karg, sizeof(struct mpt3_diag_query))) { - pr_err(MPT3SAS_FMT - "%s: unable to write mpt3_diag_query data @ %p\n", - ioc->name, __func__, arg); - return -EFAULT; - } - return 0; -} - -/** - * mpt3sas_send_diag_release - Diag Release Message - * @ioc: per adapter object - * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED - * @issue_reset - specifies whether host reset is required. - * - */ -int -mpt3sas_send_diag_release(struct MPT3SAS_ADAPTER *ioc, u8 buffer_type, - u8 *issue_reset) -{ - Mpi2DiagReleaseRequest_t *mpi_request; - Mpi2DiagReleaseReply_t *mpi_reply; - u16 smid; - u16 ioc_status; - u32 ioc_state; - int rc; - unsigned long timeleft; - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - rc = 0; - *issue_reset = 0; - - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_REGISTERED) - ioc->diag_buffer_status[buffer_type] |= - MPT3_DIAG_BUFFER_IS_RELEASED; - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: skipping due to FAULT state\n", ioc->name, - __func__)); - rc = -EAGAIN; - goto out; - } - - if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - ioc->ctl_cmds.status = MPT3_CMD_PENDING; - memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->ctl_cmds.smid = smid; - - mpi_request->Function = MPI2_FUNCTION_DIAG_RELEASE; - mpi_request->BufferType = buffer_type; - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - - init_completion(&ioc->ctl_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, - MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); - - if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name, - __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2DiagReleaseRequest_t)/4); - if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET)) - *issue_reset = 1; - rc = -EFAULT; - goto out; - } - - /* process the completed Reply Message Frame */ - if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) { - pr_err(MPT3SAS_FMT "%s: no reply message\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - - mpi_reply = ioc->ctl_cmds.reply; - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; - - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { - ioc->diag_buffer_status[buffer_type] |= - MPT3_DIAG_BUFFER_IS_RELEASED; - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: success\n", - ioc->name, __func__)); - } else { - pr_info(MPT3SAS_FMT - "%s: ioc_status(0x%04x) log_info(0x%08x)\n", - ioc->name, __func__, - ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); - rc = -EFAULT; - } - - out: - ioc->ctl_cmds.status = MPT3_CMD_NOT_USED; - return rc; -} - -/** - * _ctl_diag_release - request to send Diag Release Message to firmware - * @arg - user space buffer containing ioctl content - * - * This allows ownership of the specified buffer to returned to the driver, - * allowing an application to read the buffer without fear that firmware is - * overwritting information in the buffer. - */ -static long -_ctl_diag_release(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_diag_release karg; - void *request_data; - int rc; - u8 buffer_type; - u8 issue_reset = 0; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - buffer_type = karg.unique_id & 0x000000ff; - if (!_ctl_diag_capability(ioc, buffer_type)) { - pr_err(MPT3SAS_FMT - "%s: doesn't have capability for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -EPERM; - } - - if ((ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - pr_err(MPT3SAS_FMT - "%s: buffer_type(0x%02x) is not registered\n", - ioc->name, __func__, buffer_type); - return -EINVAL; - } - - if (karg.unique_id != ioc->unique_id[buffer_type]) { - pr_err(MPT3SAS_FMT - "%s: unique_id(0x%08x) is not registered\n", - ioc->name, __func__, karg.unique_id); - return -EINVAL; - } - - if (ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_RELEASED) { - pr_err(MPT3SAS_FMT - "%s: buffer_type(0x%02x) is already released\n", - ioc->name, __func__, - buffer_type); - return 0; - } - - request_data = ioc->diag_buffer[buffer_type]; - - if (!request_data) { - pr_err(MPT3SAS_FMT - "%s: doesn't have memory allocated for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -ENOMEM; - } - - /* buffers were released by due to host reset */ - if ((ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_DIAG_RESET)) { - ioc->diag_buffer_status[buffer_type] |= - MPT3_DIAG_BUFFER_IS_RELEASED; - ioc->diag_buffer_status[buffer_type] &= - ~MPT3_DIAG_BUFFER_IS_DIAG_RESET; - pr_err(MPT3SAS_FMT - "%s: buffer_type(0x%02x) was released due to host reset\n", - ioc->name, __func__, buffer_type); - return 0; - } - - rc = mpt3sas_send_diag_release(ioc, buffer_type, &issue_reset); - - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - - return rc; -} - -/** - * _ctl_diag_read_buffer - request for copy of the diag buffer - * @ioc: per adapter object - * @arg - user space buffer containing ioctl content - */ -static long -_ctl_diag_read_buffer(struct MPT3SAS_ADAPTER *ioc, void __user *arg) -{ - struct mpt3_diag_read_buffer karg; - struct mpt3_diag_read_buffer __user *uarg = arg; - void *request_data, *diag_data; - Mpi2DiagBufferPostRequest_t *mpi_request; - Mpi2DiagBufferPostReply_t *mpi_reply; - int rc, i; - u8 buffer_type; - unsigned long timeleft, request_size, copy_size; - u16 smid; - u16 ioc_status; - u8 issue_reset = 0; - - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s\n", ioc->name, - __func__)); - - buffer_type = karg.unique_id & 0x000000ff; - if (!_ctl_diag_capability(ioc, buffer_type)) { - pr_err(MPT3SAS_FMT - "%s: doesn't have capability for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -EPERM; - } - - if (karg.unique_id != ioc->unique_id[buffer_type]) { - pr_err(MPT3SAS_FMT - "%s: unique_id(0x%08x) is not registered\n", - ioc->name, __func__, karg.unique_id); - return -EINVAL; - } - - request_data = ioc->diag_buffer[buffer_type]; - if (!request_data) { - pr_err(MPT3SAS_FMT - "%s: doesn't have buffer for buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type); - return -ENOMEM; - } - - request_size = ioc->diag_buffer_sz[buffer_type]; - - if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) { - pr_err(MPT3SAS_FMT "%s: either the starting_offset " \ - "or bytes_to_read are not 4 byte aligned\n", ioc->name, - __func__); - return -EINVAL; - } - - if (karg.starting_offset > request_size) - return -EINVAL; - - diag_data = (void *)(request_data + karg.starting_offset); - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: diag_buffer(%p), offset(%d), sz(%d)\n", - ioc->name, __func__, - diag_data, karg.starting_offset, karg.bytes_to_read)); - - /* Truncate data on requests that are too large */ - if ((diag_data + karg.bytes_to_read < diag_data) || - (diag_data + karg.bytes_to_read > request_data + request_size)) - copy_size = request_size - karg.starting_offset; - else - copy_size = karg.bytes_to_read; - - if (copy_to_user((void __user *)uarg->diagnostic_data, - diag_data, copy_size)) { - pr_err(MPT3SAS_FMT - "%s: Unable to write mpt_diag_read_buffer_t data @ %p\n", - ioc->name, __func__, diag_data); - return -EFAULT; - } - - if ((karg.flags & MPT3_FLAGS_REREGISTER) == 0) - return 0; - - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: Reregister buffer_type(0x%02x)\n", - ioc->name, __func__, buffer_type)); - if ((ioc->diag_buffer_status[buffer_type] & - MPT3_DIAG_BUFFER_IS_RELEASED) == 0) { - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "%s: buffer_type(0x%02x) is still registered\n", - ioc->name, __func__, buffer_type)); - return 0; - } - /* Get a free request frame and save the message context. - */ - - if (ioc->ctl_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: ctl_cmd in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - smid = mpt3sas_base_get_smid(ioc, ioc->ctl_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - rc = 0; - ioc->ctl_cmds.status = MPT3_CMD_PENDING; - memset(ioc->ctl_cmds.reply, 0, ioc->reply_sz); - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->ctl_cmds.smid = smid; - - mpi_request->Function = MPI2_FUNCTION_DIAG_BUFFER_POST; - mpi_request->BufferType = buffer_type; - mpi_request->BufferLength = - cpu_to_le32(ioc->diag_buffer_sz[buffer_type]); - mpi_request->BufferAddress = - cpu_to_le64(ioc->diag_buffer_dma[buffer_type]); - for (i = 0; i < MPT3_PRODUCT_SPECIFIC_DWORDS; i++) - mpi_request->ProductSpecific[i] = - cpu_to_le32(ioc->product_specific[buffer_type][i]); - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - - init_completion(&ioc->ctl_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->ctl_cmds.done, - MPT3_IOCTL_DEFAULT_TIMEOUT*HZ); - - if (!(ioc->ctl_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", ioc->name, - __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2DiagBufferPostRequest_t)/4); - if (!(ioc->ctl_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - /* process the completed Reply Message Frame */ - if ((ioc->ctl_cmds.status & MPT3_CMD_REPLY_VALID) == 0) { - pr_err(MPT3SAS_FMT "%s: no reply message\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - - mpi_reply = ioc->ctl_cmds.reply; - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & MPI2_IOCSTATUS_MASK; - - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { - ioc->diag_buffer_status[buffer_type] |= - MPT3_DIAG_BUFFER_IS_REGISTERED; - dctlprintk(ioc, pr_info(MPT3SAS_FMT "%s: success\n", - ioc->name, __func__)); - } else { - pr_info(MPT3SAS_FMT - "%s: ioc_status(0x%04x) log_info(0x%08x)\n", - ioc->name, __func__, - ioc_status, le32_to_cpu(mpi_reply->IOCLogInfo)); - rc = -EFAULT; - } - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - - out: - - ioc->ctl_cmds.status = MPT3_CMD_NOT_USED; - return rc; -} - - - -#ifdef CONFIG_COMPAT -/** - * _ctl_compat_mpt_command - convert 32bit pointers to 64bit. - * @ioc: per adapter object - * @cmd - ioctl opcode - * @arg - (struct mpt3_ioctl_command32) - * - * MPT3COMMAND32 - Handle 32bit applications running on 64bit os. - */ -static long -_ctl_compat_mpt_command(struct MPT3SAS_ADAPTER *ioc, unsigned cmd, - void __user *arg) -{ - struct mpt3_ioctl_command32 karg32; - struct mpt3_ioctl_command32 __user *uarg; - struct mpt3_ioctl_command karg; - - if (_IOC_SIZE(cmd) != sizeof(struct mpt3_ioctl_command32)) - return -EINVAL; - - uarg = (struct mpt3_ioctl_command32 __user *) arg; - - if (copy_from_user(&karg32, (char __user *)arg, sizeof(karg32))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - memset(&karg, 0, sizeof(struct mpt3_ioctl_command)); - karg.hdr.ioc_number = karg32.hdr.ioc_number; - karg.hdr.port_number = karg32.hdr.port_number; - karg.hdr.max_data_size = karg32.hdr.max_data_size; - karg.timeout = karg32.timeout; - karg.max_reply_bytes = karg32.max_reply_bytes; - karg.data_in_size = karg32.data_in_size; - karg.data_out_size = karg32.data_out_size; - karg.max_sense_bytes = karg32.max_sense_bytes; - karg.data_sge_offset = karg32.data_sge_offset; - karg.reply_frame_buf_ptr = compat_ptr(karg32.reply_frame_buf_ptr); - karg.data_in_buf_ptr = compat_ptr(karg32.data_in_buf_ptr); - karg.data_out_buf_ptr = compat_ptr(karg32.data_out_buf_ptr); - karg.sense_data_ptr = compat_ptr(karg32.sense_data_ptr); - return _ctl_do_mpt_command(ioc, karg, &uarg->mf); -} -#endif - -/** - * _ctl_ioctl_main - main ioctl entry point - * @file - (struct file) - * @cmd - ioctl opcode - * @arg - user space data buffer - * @compat - handles 32 bit applications in 64bit os - * @mpi_version: will be MPI2_VERSION for mpt2ctl ioctl device & - * MPI25_VERSION for mpt3ctl ioctl device. - */ -static long -_ctl_ioctl_main(struct file *file, unsigned int cmd, void __user *arg, - u8 compat, u16 mpi_version) -{ - struct MPT3SAS_ADAPTER *ioc; - struct mpt3_ioctl_header ioctl_header; - enum block_state state; - long ret = -EINVAL; - - /* get IOCTL header */ - if (copy_from_user(&ioctl_header, (char __user *)arg, - sizeof(struct mpt3_ioctl_header))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - return -EFAULT; - } - - if (_ctl_verify_adapter(ioctl_header.ioc_number, - &ioc, mpi_version) == -1 || !ioc) - return -ENODEV; - - /* pci_access_mutex lock acquired by ioctl path */ - mutex_lock(&ioc->pci_access_mutex); - - if (ioc->shost_recovery || ioc->pci_error_recovery || - ioc->is_driver_loading || ioc->remove_host) { - ret = -EAGAIN; - goto out_unlock_pciaccess; - } - - state = (file->f_flags & O_NONBLOCK) ? NON_BLOCKING : BLOCKING; - if (state == NON_BLOCKING) { - if (!mutex_trylock(&ioc->ctl_cmds.mutex)) { - ret = -EAGAIN; - goto out_unlock_pciaccess; - } - } else if (mutex_lock_interruptible(&ioc->ctl_cmds.mutex)) { - ret = -ERESTARTSYS; - goto out_unlock_pciaccess; - } - - - switch (cmd) { - case MPT3IOCINFO: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_iocinfo)) - ret = _ctl_getiocinfo(ioc, arg); - break; -#ifdef CONFIG_COMPAT - case MPT3COMMAND32: -#endif - case MPT3COMMAND: - { - struct mpt3_ioctl_command __user *uarg; - struct mpt3_ioctl_command karg; - -#ifdef CONFIG_COMPAT - if (compat) { - ret = _ctl_compat_mpt_command(ioc, cmd, arg); - break; - } -#endif - if (copy_from_user(&karg, arg, sizeof(karg))) { - pr_err("failure at %s:%d/%s()!\n", - __FILE__, __LINE__, __func__); - ret = -EFAULT; - break; - } - - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_command)) { - uarg = arg; - ret = _ctl_do_mpt_command(ioc, karg, &uarg->mf); - } - break; - } - case MPT3EVENTQUERY: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_eventquery)) - ret = _ctl_eventquery(ioc, arg); - break; - case MPT3EVENTENABLE: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_eventenable)) - ret = _ctl_eventenable(ioc, arg); - break; - case MPT3EVENTREPORT: - ret = _ctl_eventreport(ioc, arg); - break; - case MPT3HARDRESET: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_diag_reset)) - ret = _ctl_do_reset(ioc, arg); - break; - case MPT3BTDHMAPPING: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_ioctl_btdh_mapping)) - ret = _ctl_btdh_mapping(ioc, arg); - break; - case MPT3DIAGREGISTER: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_register)) - ret = _ctl_diag_register(ioc, arg); - break; - case MPT3DIAGUNREGISTER: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_unregister)) - ret = _ctl_diag_unregister(ioc, arg); - break; - case MPT3DIAGQUERY: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_query)) - ret = _ctl_diag_query(ioc, arg); - break; - case MPT3DIAGRELEASE: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_release)) - ret = _ctl_diag_release(ioc, arg); - break; - case MPT3DIAGREADBUFFER: - if (_IOC_SIZE(cmd) == sizeof(struct mpt3_diag_read_buffer)) - ret = _ctl_diag_read_buffer(ioc, arg); - break; - default: - dctlprintk(ioc, pr_info(MPT3SAS_FMT - "unsupported ioctl opcode(0x%08x)\n", ioc->name, cmd)); - break; - } - - mutex_unlock(&ioc->ctl_cmds.mutex); -out_unlock_pciaccess: - mutex_unlock(&ioc->pci_access_mutex); - return ret; -} - -/** - * _ctl_ioctl - mpt3ctl main ioctl entry point (unlocked) - * @file - (struct file) - * @cmd - ioctl opcode - * @arg - - */ -long -_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - long ret; - - /* pass MPI25_VERSION value, to indicate that this ioctl cmd - * came from mpt3ctl ioctl device. - */ - ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0, MPI25_VERSION); - return ret; -} - -/** - * _ctl_mpt2_ioctl - mpt2ctl main ioctl entry point (unlocked) - * @file - (struct file) - * @cmd - ioctl opcode - * @arg - - */ -long -_ctl_mpt2_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - long ret; - - /* pass MPI2_VERSION value, to indicate that this ioctl cmd - * came from mpt2ctl ioctl device. - */ - ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 0, MPI2_VERSION); - return ret; -} -#ifdef CONFIG_COMPAT -/** - *_ ctl_ioctl_compat - main ioctl entry point (compat) - * @file - - * @cmd - - * @arg - - * - * This routine handles 32 bit applications in 64bit os. - */ -long -_ctl_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) -{ - long ret; - - ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1, MPI25_VERSION); - return ret; -} - -/** - *_ ctl_mpt2_ioctl_compat - main ioctl entry point (compat) - * @file - - * @cmd - - * @arg - - * - * This routine handles 32 bit applications in 64bit os. - */ -long -_ctl_mpt2_ioctl_compat(struct file *file, unsigned cmd, unsigned long arg) -{ - long ret; - - ret = _ctl_ioctl_main(file, cmd, (void __user *)arg, 1, MPI2_VERSION); - return ret; -} -#endif - -/* scsi host attributes */ -/** - * _ctl_version_fw_show - firmware version - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_version_fw_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", - (ioc->facts.FWVersion.Word & 0xFF000000) >> 24, - (ioc->facts.FWVersion.Word & 0x00FF0000) >> 16, - (ioc->facts.FWVersion.Word & 0x0000FF00) >> 8, - ioc->facts.FWVersion.Word & 0x000000FF); -} -static DEVICE_ATTR(version_fw, S_IRUGO, _ctl_version_fw_show, NULL); - -/** - * _ctl_version_bios_show - bios version - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_version_bios_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - u32 version = le32_to_cpu(ioc->bios_pg3.BiosVersion); - - return snprintf(buf, PAGE_SIZE, "%02d.%02d.%02d.%02d\n", - (version & 0xFF000000) >> 24, - (version & 0x00FF0000) >> 16, - (version & 0x0000FF00) >> 8, - version & 0x000000FF); -} -static DEVICE_ATTR(version_bios, S_IRUGO, _ctl_version_bios_show, NULL); - -/** - * _ctl_version_mpi_show - MPI (message passing interface) version - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_version_mpi_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%03x.%02x\n", - ioc->facts.MsgVersion, ioc->facts.HeaderVersion >> 8); -} -static DEVICE_ATTR(version_mpi, S_IRUGO, _ctl_version_mpi_show, NULL); - -/** - * _ctl_version_product_show - product name - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_version_product_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, 16, "%s\n", ioc->manu_pg0.ChipName); -} -static DEVICE_ATTR(version_product, S_IRUGO, _ctl_version_product_show, NULL); - -/** - * _ctl_version_nvdata_persistent_show - ndvata persistent version - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_version_nvdata_persistent_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%08xh\n", - le32_to_cpu(ioc->iounit_pg0.NvdataVersionPersistent.Word)); -} -static DEVICE_ATTR(version_nvdata_persistent, S_IRUGO, - _ctl_version_nvdata_persistent_show, NULL); - -/** - * _ctl_version_nvdata_default_show - nvdata default version - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_version_nvdata_default_show(struct device *cdev, struct device_attribute - *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%08xh\n", - le32_to_cpu(ioc->iounit_pg0.NvdataVersionDefault.Word)); -} -static DEVICE_ATTR(version_nvdata_default, S_IRUGO, - _ctl_version_nvdata_default_show, NULL); - -/** - * _ctl_board_name_show - board name - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_board_name_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardName); -} -static DEVICE_ATTR(board_name, S_IRUGO, _ctl_board_name_show, NULL); - -/** - * _ctl_board_assembly_show - board assembly name - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_board_assembly_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardAssembly); -} -static DEVICE_ATTR(board_assembly, S_IRUGO, _ctl_board_assembly_show, NULL); - -/** - * _ctl_board_tracer_show - board tracer number - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_board_tracer_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, 16, "%s\n", ioc->manu_pg0.BoardTracerNumber); -} -static DEVICE_ATTR(board_tracer, S_IRUGO, _ctl_board_tracer_show, NULL); - -/** - * _ctl_io_delay_show - io missing delay - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is for firmware implemention for deboucing device - * removal events. - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_io_delay_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->io_missing_delay); -} -static DEVICE_ATTR(io_delay, S_IRUGO, _ctl_io_delay_show, NULL); - -/** - * _ctl_device_delay_show - device missing delay - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is for firmware implemention for deboucing device - * removal events. - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_device_delay_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->device_missing_delay); -} -static DEVICE_ATTR(device_delay, S_IRUGO, _ctl_device_delay_show, NULL); - -/** - * _ctl_fw_queue_depth_show - global credits - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is firmware queue depth limit - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_fw_queue_depth_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%02d\n", ioc->facts.RequestCredit); -} -static DEVICE_ATTR(fw_queue_depth, S_IRUGO, _ctl_fw_queue_depth_show, NULL); - -/** - * _ctl_sas_address_show - sas address - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is the controller sas address - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_host_sas_address_show(struct device *cdev, struct device_attribute *attr, - char *buf) - -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "0x%016llx\n", - (unsigned long long)ioc->sas_hba.sas_address); -} -static DEVICE_ATTR(host_sas_address, S_IRUGO, - _ctl_host_sas_address_show, NULL); - -/** - * _ctl_logging_level_show - logging level - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_logging_level_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%08xh\n", ioc->logging_level); -} -static ssize_t -_ctl_logging_level_store(struct device *cdev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - int val = 0; - - if (sscanf(buf, "%x", &val) != 1) - return -EINVAL; - - ioc->logging_level = val; - pr_info(MPT3SAS_FMT "logging_level=%08xh\n", ioc->name, - ioc->logging_level); - return strlen(buf); -} -static DEVICE_ATTR(logging_level, S_IRUGO | S_IWUSR, _ctl_logging_level_show, - _ctl_logging_level_store); - -/** - * _ctl_fwfault_debug_show - show/store fwfault_debug - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * mpt3sas_fwfault_debug is command line option - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_fwfault_debug_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%d\n", ioc->fwfault_debug); -} -static ssize_t -_ctl_fwfault_debug_store(struct device *cdev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - int val = 0; - - if (sscanf(buf, "%d", &val) != 1) - return -EINVAL; - - ioc->fwfault_debug = val; - pr_info(MPT3SAS_FMT "fwfault_debug=%d\n", ioc->name, - ioc->fwfault_debug); - return strlen(buf); -} -static DEVICE_ATTR(fwfault_debug, S_IRUGO | S_IWUSR, - _ctl_fwfault_debug_show, _ctl_fwfault_debug_store); - -/** - * _ctl_ioc_reset_count_show - ioc reset count - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is firmware queue depth limit - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_ioc_reset_count_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - return snprintf(buf, PAGE_SIZE, "%d\n", ioc->ioc_reset_count); -} -static DEVICE_ATTR(ioc_reset_count, S_IRUGO, _ctl_ioc_reset_count_show, NULL); - -/** - * _ctl_ioc_reply_queue_count_show - number of reply queues - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is number of reply queues - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_ioc_reply_queue_count_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - u8 reply_queue_count; - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - if ((ioc->facts.IOCCapabilities & - MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX) && ioc->msix_enable) - reply_queue_count = ioc->reply_queue_count; - else - reply_queue_count = 1; - - return snprintf(buf, PAGE_SIZE, "%d\n", reply_queue_count); -} -static DEVICE_ATTR(reply_queue_count, S_IRUGO, _ctl_ioc_reply_queue_count_show, - NULL); - -/** - * _ctl_BRM_status_show - Backup Rail Monitor Status - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is number of reply queues - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_BRM_status_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - Mpi2IOUnitPage3_t *io_unit_pg3 = NULL; - Mpi2ConfigReply_t mpi_reply; - u16 backup_rail_monitor_status = 0; - u16 ioc_status; - int sz; - ssize_t rc = 0; - - if (!ioc->is_warpdrive) { - pr_err(MPT3SAS_FMT "%s: BRM attribute is only for" - " warpdrive\n", ioc->name, __func__); - goto out; - } - /* pci_access_mutex lock acquired by sysfs show path */ - mutex_lock(&ioc->pci_access_mutex); - if (ioc->pci_error_recovery || ioc->remove_host) { - mutex_unlock(&ioc->pci_access_mutex); - return 0; - } - - /* allocate upto GPIOVal 36 entries */ - sz = offsetof(Mpi2IOUnitPage3_t, GPIOVal) + (sizeof(u16) * 36); - io_unit_pg3 = kzalloc(sz, GFP_KERNEL); - if (!io_unit_pg3) { - pr_err(MPT3SAS_FMT "%s: failed allocating memory " - "for iounit_pg3: (%d) bytes\n", ioc->name, __func__, sz); - goto out; - } - - if (mpt3sas_config_get_iounit_pg3(ioc, &mpi_reply, io_unit_pg3, sz) != - 0) { - pr_err(MPT3SAS_FMT - "%s: failed reading iounit_pg3\n", ioc->name, - __func__); - goto out; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "%s: iounit_pg3 failed with " - "ioc_status(0x%04x)\n", ioc->name, __func__, ioc_status); - goto out; - } - - if (io_unit_pg3->GPIOCount < 25) { - pr_err(MPT3SAS_FMT "%s: iounit_pg3->GPIOCount less than " - "25 entries, detected (%d) entries\n", ioc->name, __func__, - io_unit_pg3->GPIOCount); - goto out; - } - - /* BRM status is in bit zero of GPIOVal[24] */ - backup_rail_monitor_status = le16_to_cpu(io_unit_pg3->GPIOVal[24]); - rc = snprintf(buf, PAGE_SIZE, "%d\n", (backup_rail_monitor_status & 1)); - - out: - kfree(io_unit_pg3); - mutex_unlock(&ioc->pci_access_mutex); - return rc; -} -static DEVICE_ATTR(BRM_status, S_IRUGO, _ctl_BRM_status_show, NULL); - -struct DIAG_BUFFER_START { - __le32 Size; - __le32 DiagVersion; - u8 BufferType; - u8 Reserved[3]; - __le32 Reserved1; - __le32 Reserved2; - __le32 Reserved3; -}; - -/** - * _ctl_host_trace_buffer_size_show - host buffer size (trace only) - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_host_trace_buffer_size_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - u32 size = 0; - struct DIAG_BUFFER_START *request_data; - - if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) { - pr_err(MPT3SAS_FMT - "%s: host_trace_buffer is not registered\n", - ioc->name, __func__); - return 0; - } - - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - pr_err(MPT3SAS_FMT - "%s: host_trace_buffer is not registered\n", - ioc->name, __func__); - return 0; - } - - request_data = (struct DIAG_BUFFER_START *) - ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]; - if ((le32_to_cpu(request_data->DiagVersion) == 0x00000000 || - le32_to_cpu(request_data->DiagVersion) == 0x01000000 || - le32_to_cpu(request_data->DiagVersion) == 0x01010000) && - le32_to_cpu(request_data->Reserved3) == 0x4742444c) - size = le32_to_cpu(request_data->Size); - - ioc->ring_buffer_sz = size; - return snprintf(buf, PAGE_SIZE, "%d\n", size); -} -static DEVICE_ATTR(host_trace_buffer_size, S_IRUGO, - _ctl_host_trace_buffer_size_show, NULL); - -/** - * _ctl_host_trace_buffer_show - firmware ring buffer (trace only) - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - * - * You will only be able to read 4k bytes of ring buffer at a time. - * In order to read beyond 4k bytes, you will have to write out the - * offset to the same attribute, it will move the pointer. - */ -static ssize_t -_ctl_host_trace_buffer_show(struct device *cdev, struct device_attribute *attr, - char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - void *request_data; - u32 size; - - if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) { - pr_err(MPT3SAS_FMT - "%s: host_trace_buffer is not registered\n", - ioc->name, __func__); - return 0; - } - - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - pr_err(MPT3SAS_FMT - "%s: host_trace_buffer is not registered\n", - ioc->name, __func__); - return 0; - } - - if (ioc->ring_buffer_offset > ioc->ring_buffer_sz) - return 0; - - size = ioc->ring_buffer_sz - ioc->ring_buffer_offset; - size = (size >= PAGE_SIZE) ? (PAGE_SIZE - 1) : size; - request_data = ioc->diag_buffer[0] + ioc->ring_buffer_offset; - memcpy(buf, request_data, size); - return size; -} - -static ssize_t -_ctl_host_trace_buffer_store(struct device *cdev, struct device_attribute *attr, - const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - int val = 0; - - if (sscanf(buf, "%d", &val) != 1) - return -EINVAL; - - ioc->ring_buffer_offset = val; - return strlen(buf); -} -static DEVICE_ATTR(host_trace_buffer, S_IRUGO | S_IWUSR, - _ctl_host_trace_buffer_show, _ctl_host_trace_buffer_store); - - -/*****************************************/ - -/** - * _ctl_host_trace_buffer_enable_show - firmware ring buffer (trace only) - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - * - * This is a mechnism to post/release host_trace_buffers - */ -static ssize_t -_ctl_host_trace_buffer_enable_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - if ((!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) || - ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0)) - return snprintf(buf, PAGE_SIZE, "off\n"); - else if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED)) - return snprintf(buf, PAGE_SIZE, "release\n"); - else - return snprintf(buf, PAGE_SIZE, "post\n"); -} - -static ssize_t -_ctl_host_trace_buffer_enable_store(struct device *cdev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - char str[10] = ""; - struct mpt3_diag_register diag_register; - u8 issue_reset = 0; - - /* don't allow post/release occurr while recovery is active */ - if (ioc->shost_recovery || ioc->remove_host || - ioc->pci_error_recovery || ioc->is_driver_loading) - return -EBUSY; - - if (sscanf(buf, "%9s", str) != 1) - return -EINVAL; - - if (!strcmp(str, "post")) { - /* exit out if host buffers are already posted */ - if ((ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) && - (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) && - ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED) == 0)) - goto out; - memset(&diag_register, 0, sizeof(struct mpt3_diag_register)); - pr_info(MPT3SAS_FMT "posting host trace buffers\n", - ioc->name); - diag_register.buffer_type = MPI2_DIAG_BUF_TYPE_TRACE; - diag_register.requested_buffer_size = (1024 * 1024); - diag_register.unique_id = 0x7075900; - ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] = 0; - _ctl_diag_register_2(ioc, &diag_register); - } else if (!strcmp(str, "release")) { - /* exit out if host buffers are already released */ - if (!ioc->diag_buffer[MPI2_DIAG_BUF_TYPE_TRACE]) - goto out; - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) - goto out; - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED)) - goto out; - pr_info(MPT3SAS_FMT "releasing host trace buffer\n", - ioc->name); - mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, - &issue_reset); - } - - out: - return strlen(buf); -} -static DEVICE_ATTR(host_trace_buffer_enable, S_IRUGO | S_IWUSR, - _ctl_host_trace_buffer_enable_show, - _ctl_host_trace_buffer_enable_store); - -/*********** diagnostic trigger suppport *********************************/ - -/** - * _ctl_diag_trigger_master_show - show the diag_trigger_master attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_master_show(struct device *cdev, - struct device_attribute *attr, char *buf) - -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t rc; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - rc = sizeof(struct SL_WH_MASTER_TRIGGER_T); - memcpy(buf, &ioc->diag_trigger_master, rc); - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return rc; -} - -/** - * _ctl_diag_trigger_master_store - store the diag_trigger_master attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_master_store(struct device *cdev, - struct device_attribute *attr, const char *buf, size_t count) - -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t rc; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - rc = min(sizeof(struct SL_WH_MASTER_TRIGGER_T), count); - memset(&ioc->diag_trigger_master, 0, - sizeof(struct SL_WH_MASTER_TRIGGER_T)); - memcpy(&ioc->diag_trigger_master, buf, rc); - ioc->diag_trigger_master.MasterData |= - (MASTER_TRIGGER_FW_FAULT + MASTER_TRIGGER_ADAPTER_RESET); - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return rc; -} -static DEVICE_ATTR(diag_trigger_master, S_IRUGO | S_IWUSR, - _ctl_diag_trigger_master_show, _ctl_diag_trigger_master_store); - - -/** - * _ctl_diag_trigger_event_show - show the diag_trigger_event attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_event_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t rc; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - rc = sizeof(struct SL_WH_EVENT_TRIGGERS_T); - memcpy(buf, &ioc->diag_trigger_event, rc); - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return rc; -} - -/** - * _ctl_diag_trigger_event_store - store the diag_trigger_event attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_event_store(struct device *cdev, - struct device_attribute *attr, const char *buf, size_t count) - -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t sz; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - sz = min(sizeof(struct SL_WH_EVENT_TRIGGERS_T), count); - memset(&ioc->diag_trigger_event, 0, - sizeof(struct SL_WH_EVENT_TRIGGERS_T)); - memcpy(&ioc->diag_trigger_event, buf, sz); - if (ioc->diag_trigger_event.ValidEntries > NUM_VALID_ENTRIES) - ioc->diag_trigger_event.ValidEntries = NUM_VALID_ENTRIES; - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return sz; -} -static DEVICE_ATTR(diag_trigger_event, S_IRUGO | S_IWUSR, - _ctl_diag_trigger_event_show, _ctl_diag_trigger_event_store); - - -/** - * _ctl_diag_trigger_scsi_show - show the diag_trigger_scsi attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_scsi_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t rc; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - rc = sizeof(struct SL_WH_SCSI_TRIGGERS_T); - memcpy(buf, &ioc->diag_trigger_scsi, rc); - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return rc; -} - -/** - * _ctl_diag_trigger_scsi_store - store the diag_trigger_scsi attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_scsi_store(struct device *cdev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t sz; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - sz = min(sizeof(struct SL_WH_SCSI_TRIGGERS_T), count); - memset(&ioc->diag_trigger_scsi, 0, - sizeof(struct SL_WH_EVENT_TRIGGERS_T)); - memcpy(&ioc->diag_trigger_scsi, buf, sz); - if (ioc->diag_trigger_scsi.ValidEntries > NUM_VALID_ENTRIES) - ioc->diag_trigger_scsi.ValidEntries = NUM_VALID_ENTRIES; - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return sz; -} -static DEVICE_ATTR(diag_trigger_scsi, S_IRUGO | S_IWUSR, - _ctl_diag_trigger_scsi_show, _ctl_diag_trigger_scsi_store); - - -/** - * _ctl_diag_trigger_scsi_show - show the diag_trigger_mpi attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_mpi_show(struct device *cdev, - struct device_attribute *attr, char *buf) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t rc; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - rc = sizeof(struct SL_WH_MPI_TRIGGERS_T); - memcpy(buf, &ioc->diag_trigger_mpi, rc); - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return rc; -} - -/** - * _ctl_diag_trigger_mpi_store - store the diag_trigger_mpi attribute - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * A sysfs 'read/write' shost attribute. - */ -static ssize_t -_ctl_diag_trigger_mpi_store(struct device *cdev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct Scsi_Host *shost = class_to_shost(cdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - unsigned long flags; - ssize_t sz; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - sz = min(sizeof(struct SL_WH_MPI_TRIGGERS_T), count); - memset(&ioc->diag_trigger_mpi, 0, - sizeof(ioc->diag_trigger_mpi)); - memcpy(&ioc->diag_trigger_mpi, buf, sz); - if (ioc->diag_trigger_mpi.ValidEntries > NUM_VALID_ENTRIES) - ioc->diag_trigger_mpi.ValidEntries = NUM_VALID_ENTRIES; - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return sz; -} - -static DEVICE_ATTR(diag_trigger_mpi, S_IRUGO | S_IWUSR, - _ctl_diag_trigger_mpi_show, _ctl_diag_trigger_mpi_store); - -/*********** diagnostic trigger suppport *** END ****************************/ - - - -/*****************************************/ - -struct device_attribute *mpt3sas_host_attrs[] = { - &dev_attr_version_fw, - &dev_attr_version_bios, - &dev_attr_version_mpi, - &dev_attr_version_product, - &dev_attr_version_nvdata_persistent, - &dev_attr_version_nvdata_default, - &dev_attr_board_name, - &dev_attr_board_assembly, - &dev_attr_board_tracer, - &dev_attr_io_delay, - &dev_attr_device_delay, - &dev_attr_logging_level, - &dev_attr_fwfault_debug, - &dev_attr_fw_queue_depth, - &dev_attr_host_sas_address, - &dev_attr_ioc_reset_count, - &dev_attr_host_trace_buffer_size, - &dev_attr_host_trace_buffer, - &dev_attr_host_trace_buffer_enable, - &dev_attr_reply_queue_count, - &dev_attr_diag_trigger_master, - &dev_attr_diag_trigger_event, - &dev_attr_diag_trigger_scsi, - &dev_attr_diag_trigger_mpi, - &dev_attr_BRM_status, - NULL, -}; - -/* device attributes */ - -/** - * _ctl_device_sas_address_show - sas address - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is the sas address for the target - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_device_sas_address_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata; - - return snprintf(buf, PAGE_SIZE, "0x%016llx\n", - (unsigned long long)sas_device_priv_data->sas_target->sas_address); -} -static DEVICE_ATTR(sas_address, S_IRUGO, _ctl_device_sas_address_show, NULL); - -/** - * _ctl_device_handle_show - device handle - * @cdev - pointer to embedded class device - * @buf - the buffer returned - * - * This is the firmware assigned device handle - * - * A sysfs 'read-only' shost attribute. - */ -static ssize_t -_ctl_device_handle_show(struct device *dev, struct device_attribute *attr, - char *buf) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct MPT3SAS_DEVICE *sas_device_priv_data = sdev->hostdata; - - return snprintf(buf, PAGE_SIZE, "0x%04x\n", - sas_device_priv_data->sas_target->handle); -} -static DEVICE_ATTR(sas_device_handle, S_IRUGO, _ctl_device_handle_show, NULL); - -struct device_attribute *mpt3sas_dev_attrs[] = { - &dev_attr_sas_address, - &dev_attr_sas_device_handle, - NULL, -}; - -/* file operations table for mpt3ctl device */ -static const struct file_operations ctl_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = _ctl_ioctl, - .poll = _ctl_poll, - .fasync = _ctl_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = _ctl_ioctl_compat, -#endif -}; - -/* file operations table for mpt2ctl device */ -static const struct file_operations ctl_gen2_fops = { - .owner = THIS_MODULE, - .unlocked_ioctl = _ctl_mpt2_ioctl, - .poll = _ctl_poll, - .fasync = _ctl_fasync, -#ifdef CONFIG_COMPAT - .compat_ioctl = _ctl_mpt2_ioctl_compat, -#endif -}; - -static struct miscdevice ctl_dev = { - .minor = MPT3SAS_MINOR, - .name = MPT3SAS_DEV_NAME, - .fops = &ctl_fops, -}; - -static struct miscdevice gen2_ctl_dev = { - .minor = MPT2SAS_MINOR, - .name = MPT2SAS_DEV_NAME, - .fops = &ctl_gen2_fops, -}; - -/** - * mpt3sas_ctl_init - main entry point for ctl. - * - */ -void -mpt3sas_ctl_init(ushort hbas_to_enumerate) -{ - async_queue = NULL; - - /* Don't register mpt3ctl ioctl device if - * hbas_to_enumarate is one. - */ - if (hbas_to_enumerate != 1) - if (misc_register(&ctl_dev) < 0) - pr_err("%s can't register misc device [minor=%d]\n", - MPT3SAS_DRIVER_NAME, MPT3SAS_MINOR); - - /* Don't register mpt3ctl ioctl device if - * hbas_to_enumarate is two. - */ - if (hbas_to_enumerate != 2) - if (misc_register(&gen2_ctl_dev) < 0) - pr_err("%s can't register misc device [minor=%d]\n", - MPT2SAS_DRIVER_NAME, MPT2SAS_MINOR); - - init_waitqueue_head(&ctl_poll_wait); -} - -/** - * mpt3sas_ctl_exit - exit point for ctl - * - */ -void -mpt3sas_ctl_exit(ushort hbas_to_enumerate) -{ - struct MPT3SAS_ADAPTER *ioc; - int i; - - list_for_each_entry(ioc, &mpt3sas_ioc_list, list) { - - /* free memory associated to diag buffers */ - for (i = 0; i < MPI2_DIAG_BUF_TYPE_COUNT; i++) { - if (!ioc->diag_buffer[i]) - continue; - if (!(ioc->diag_buffer_status[i] & - MPT3_DIAG_BUFFER_IS_REGISTERED)) - continue; - if ((ioc->diag_buffer_status[i] & - MPT3_DIAG_BUFFER_IS_RELEASED)) - continue; - pci_free_consistent(ioc->pdev, ioc->diag_buffer_sz[i], - ioc->diag_buffer[i], ioc->diag_buffer_dma[i]); - ioc->diag_buffer[i] = NULL; - ioc->diag_buffer_status[i] = 0; - } - - kfree(ioc->event_log); - } - if (hbas_to_enumerate != 1) - misc_deregister(&ctl_dev); - if (hbas_to_enumerate != 2) - misc_deregister(&gen2_ctl_dev); -} diff --git a/addons/mpt3sas/src/4.4.180/mpt3sas_ctl.h b/addons/mpt3sas/src/4.4.180/mpt3sas_ctl.h deleted file mode 100644 index 89408356..00000000 --- a/addons/mpt3sas/src/4.4.180/mpt3sas_ctl.h +++ /dev/null @@ -1,423 +0,0 @@ -/* - * Management Module Support for MPT (Message Passing Technology) based - * controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_ctl.h - * Copyright (C) 2012-2014 LSI Corporation - * Copyright (C) 2013-2014 Avago Technologies - * (mailto: MPT-FusionLinux.pdl@avagotech.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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 MPT3SAS_CTL_H_INCLUDED -#define MPT3SAS_CTL_H_INCLUDED - -#ifdef __KERNEL__ -#include -#endif - -#ifndef MPT2SAS_MINOR -#define MPT2SAS_MINOR (MPT_MINOR + 1) -#endif -#ifndef MPT3SAS_MINOR -#define MPT3SAS_MINOR (MPT_MINOR + 2) -#endif -#define MPT2SAS_DEV_NAME "mpt2ctl" -#define MPT3SAS_DEV_NAME "mpt3ctl" -#define MPT3_MAGIC_NUMBER 'L' -#define MPT3_IOCTL_DEFAULT_TIMEOUT (10) /* in seconds */ - -/** - * IOCTL opcodes - */ -#define MPT3IOCINFO _IOWR(MPT3_MAGIC_NUMBER, 17, \ - struct mpt3_ioctl_iocinfo) -#define MPT3COMMAND _IOWR(MPT3_MAGIC_NUMBER, 20, \ - struct mpt3_ioctl_command) -#ifdef CONFIG_COMPAT -#define MPT3COMMAND32 _IOWR(MPT3_MAGIC_NUMBER, 20, \ - struct mpt3_ioctl_command32) -#endif -#define MPT3EVENTQUERY _IOWR(MPT3_MAGIC_NUMBER, 21, \ - struct mpt3_ioctl_eventquery) -#define MPT3EVENTENABLE _IOWR(MPT3_MAGIC_NUMBER, 22, \ - struct mpt3_ioctl_eventenable) -#define MPT3EVENTREPORT _IOWR(MPT3_MAGIC_NUMBER, 23, \ - struct mpt3_ioctl_eventreport) -#define MPT3HARDRESET _IOWR(MPT3_MAGIC_NUMBER, 24, \ - struct mpt3_ioctl_diag_reset) -#define MPT3BTDHMAPPING _IOWR(MPT3_MAGIC_NUMBER, 31, \ - struct mpt3_ioctl_btdh_mapping) - -/* diag buffer support */ -#define MPT3DIAGREGISTER _IOWR(MPT3_MAGIC_NUMBER, 26, \ - struct mpt3_diag_register) -#define MPT3DIAGRELEASE _IOWR(MPT3_MAGIC_NUMBER, 27, \ - struct mpt3_diag_release) -#define MPT3DIAGUNREGISTER _IOWR(MPT3_MAGIC_NUMBER, 28, \ - struct mpt3_diag_unregister) -#define MPT3DIAGQUERY _IOWR(MPT3_MAGIC_NUMBER, 29, \ - struct mpt3_diag_query) -#define MPT3DIAGREADBUFFER _IOWR(MPT3_MAGIC_NUMBER, 30, \ - struct mpt3_diag_read_buffer) - -/** - * struct mpt3_ioctl_header - main header structure - * @ioc_number - IOC unit number - * @port_number - IOC port number - * @max_data_size - maximum number bytes to transfer on read - */ -struct mpt3_ioctl_header { - uint32_t ioc_number; - uint32_t port_number; - uint32_t max_data_size; -}; - -/** - * struct mpt3_ioctl_diag_reset - diagnostic reset - * @hdr - generic header - */ -struct mpt3_ioctl_diag_reset { - struct mpt3_ioctl_header hdr; -}; - - -/** - * struct mpt3_ioctl_pci_info - pci device info - * @device - pci device id - * @function - pci function id - * @bus - pci bus id - * @segment_id - pci segment id - */ -struct mpt3_ioctl_pci_info { - union { - struct { - uint32_t device:5; - uint32_t function:3; - uint32_t bus:24; - } bits; - uint32_t word; - } u; - uint32_t segment_id; -}; - - -#define MPT2_IOCTL_INTERFACE_SCSI (0x00) -#define MPT2_IOCTL_INTERFACE_FC (0x01) -#define MPT2_IOCTL_INTERFACE_FC_IP (0x02) -#define MPT2_IOCTL_INTERFACE_SAS (0x03) -#define MPT2_IOCTL_INTERFACE_SAS2 (0x04) -#define MPT2_IOCTL_INTERFACE_SAS2_SSS6200 (0x05) -#define MPT3_IOCTL_INTERFACE_SAS3 (0x06) -#define MPT2_IOCTL_VERSION_LENGTH (32) - -/** - * struct mpt3_ioctl_iocinfo - generic controller info - * @hdr - generic header - * @adapter_type - type of adapter (spi, fc, sas) - * @port_number - port number - * @pci_id - PCI Id - * @hw_rev - hardware revision - * @sub_system_device - PCI subsystem Device ID - * @sub_system_vendor - PCI subsystem Vendor ID - * @rsvd0 - reserved - * @firmware_version - firmware version - * @bios_version - BIOS version - * @driver_version - driver version - 32 ASCII characters - * @rsvd1 - reserved - * @scsi_id - scsi id of adapter 0 - * @rsvd2 - reserved - * @pci_information - pci info (2nd revision) - */ -struct mpt3_ioctl_iocinfo { - struct mpt3_ioctl_header hdr; - uint32_t adapter_type; - uint32_t port_number; - uint32_t pci_id; - uint32_t hw_rev; - uint32_t subsystem_device; - uint32_t subsystem_vendor; - uint32_t rsvd0; - uint32_t firmware_version; - uint32_t bios_version; - uint8_t driver_version[MPT2_IOCTL_VERSION_LENGTH]; - uint8_t rsvd1; - uint8_t scsi_id; - uint16_t rsvd2; - struct mpt3_ioctl_pci_info pci_information; -}; - - -/* number of event log entries */ -#define MPT3SAS_CTL_EVENT_LOG_SIZE (50) - -/** - * struct mpt3_ioctl_eventquery - query event count and type - * @hdr - generic header - * @event_entries - number of events returned by get_event_report - * @rsvd - reserved - * @event_types - type of events currently being captured - */ -struct mpt3_ioctl_eventquery { - struct mpt3_ioctl_header hdr; - uint16_t event_entries; - uint16_t rsvd; - uint32_t event_types[MPI2_EVENT_NOTIFY_EVENTMASK_WORDS]; -}; - -/** - * struct mpt3_ioctl_eventenable - enable/disable event capturing - * @hdr - generic header - * @event_types - toggle off/on type of events to be captured - */ -struct mpt3_ioctl_eventenable { - struct mpt3_ioctl_header hdr; - uint32_t event_types[4]; -}; - -#define MPT3_EVENT_DATA_SIZE (192) -/** - * struct MPT3_IOCTL_EVENTS - - * @event - the event that was reported - * @context - unique value for each event assigned by driver - * @data - event data returned in fw reply message - */ -struct MPT3_IOCTL_EVENTS { - uint32_t event; - uint32_t context; - uint8_t data[MPT3_EVENT_DATA_SIZE]; -}; - -/** - * struct mpt3_ioctl_eventreport - returing event log - * @hdr - generic header - * @event_data - (see struct MPT3_IOCTL_EVENTS) - */ -struct mpt3_ioctl_eventreport { - struct mpt3_ioctl_header hdr; - struct MPT3_IOCTL_EVENTS event_data[1]; -}; - -/** - * struct mpt3_ioctl_command - generic mpt firmware passthru ioctl - * @hdr - generic header - * @timeout - command timeout in seconds. (if zero then use driver default - * value). - * @reply_frame_buf_ptr - reply location - * @data_in_buf_ptr - destination for read - * @data_out_buf_ptr - data source for write - * @sense_data_ptr - sense data location - * @max_reply_bytes - maximum number of reply bytes to be sent to app. - * @data_in_size - number bytes for data transfer in (read) - * @data_out_size - number bytes for data transfer out (write) - * @max_sense_bytes - maximum number of bytes for auto sense buffers - * @data_sge_offset - offset in words from the start of the request message to - * the first SGL - * @mf[1]; - */ -struct mpt3_ioctl_command { - struct mpt3_ioctl_header hdr; - uint32_t timeout; - void __user *reply_frame_buf_ptr; - void __user *data_in_buf_ptr; - void __user *data_out_buf_ptr; - void __user *sense_data_ptr; - uint32_t max_reply_bytes; - uint32_t data_in_size; - uint32_t data_out_size; - uint32_t max_sense_bytes; - uint32_t data_sge_offset; - uint8_t mf[1]; -}; - -#ifdef CONFIG_COMPAT -struct mpt3_ioctl_command32 { - struct mpt3_ioctl_header hdr; - uint32_t timeout; - uint32_t reply_frame_buf_ptr; - uint32_t data_in_buf_ptr; - uint32_t data_out_buf_ptr; - uint32_t sense_data_ptr; - uint32_t max_reply_bytes; - uint32_t data_in_size; - uint32_t data_out_size; - uint32_t max_sense_bytes; - uint32_t data_sge_offset; - uint8_t mf[1]; -}; -#endif - -/** - * struct mpt3_ioctl_btdh_mapping - mapping info - * @hdr - generic header - * @id - target device identification number - * @bus - SCSI bus number that the target device exists on - * @handle - device handle for the target device - * @rsvd - reserved - * - * To obtain a bus/id the application sets - * handle to valid handle, and bus/id to 0xFFFF. - * - * To obtain the device handle the application sets - * bus/id valid value, and the handle to 0xFFFF. - */ -struct mpt3_ioctl_btdh_mapping { - struct mpt3_ioctl_header hdr; - uint32_t id; - uint32_t bus; - uint16_t handle; - uint16_t rsvd; -}; - - - -/* application flags for mpt3_diag_register, mpt3_diag_query */ -#define MPT3_APP_FLAGS_APP_OWNED (0x0001) -#define MPT3_APP_FLAGS_BUFFER_VALID (0x0002) -#define MPT3_APP_FLAGS_FW_BUFFER_ACCESS (0x0004) - -/* flags for mpt3_diag_read_buffer */ -#define MPT3_FLAGS_REREGISTER (0x0001) - -#define MPT3_PRODUCT_SPECIFIC_DWORDS 23 - -/** - * struct mpt3_diag_register - application register with driver - * @hdr - generic header - * @reserved - - * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED - * @application_flags - misc flags - * @diagnostic_flags - specifies flags affecting command processing - * @product_specific - product specific information - * @requested_buffer_size - buffers size in bytes - * @unique_id - tag specified by application that is used to signal ownership - * of the buffer. - * - * This will allow the driver to setup any required buffers that will be - * needed by firmware to communicate with the driver. - */ -struct mpt3_diag_register { - struct mpt3_ioctl_header hdr; - uint8_t reserved; - uint8_t buffer_type; - uint16_t application_flags; - uint32_t diagnostic_flags; - uint32_t product_specific[MPT3_PRODUCT_SPECIFIC_DWORDS]; - uint32_t requested_buffer_size; - uint32_t unique_id; -}; - -/** - * struct mpt3_diag_unregister - application unregister with driver - * @hdr - generic header - * @unique_id - tag uniquely identifies the buffer to be unregistered - * - * This will allow the driver to cleanup any memory allocated for diag - * messages and to free up any resources. - */ -struct mpt3_diag_unregister { - struct mpt3_ioctl_header hdr; - uint32_t unique_id; -}; - -/** - * struct mpt3_diag_query - query relevant info associated with diag buffers - * @hdr - generic header - * @reserved - - * @buffer_type - specifies either TRACE, SNAPSHOT, or EXTENDED - * @application_flags - misc flags - * @diagnostic_flags - specifies flags affecting command processing - * @product_specific - product specific information - * @total_buffer_size - diag buffer size in bytes - * @driver_added_buffer_size - size of extra space appended to end of buffer - * @unique_id - unique id associated with this buffer. - * - * The application will send only buffer_type and unique_id. Driver will - * inspect unique_id first, if valid, fill in all the info. If unique_id is - * 0x00, the driver will return info specified by Buffer Type. - */ -struct mpt3_diag_query { - struct mpt3_ioctl_header hdr; - uint8_t reserved; - uint8_t buffer_type; - uint16_t application_flags; - uint32_t diagnostic_flags; - uint32_t product_specific[MPT3_PRODUCT_SPECIFIC_DWORDS]; - uint32_t total_buffer_size; - uint32_t driver_added_buffer_size; - uint32_t unique_id; -}; - -/** - * struct mpt3_diag_release - request to send Diag Release Message to firmware - * @hdr - generic header - * @unique_id - tag uniquely identifies the buffer to be released - * - * This allows ownership of the specified buffer to returned to the driver, - * allowing an application to read the buffer without fear that firmware is - * overwritting information in the buffer. - */ -struct mpt3_diag_release { - struct mpt3_ioctl_header hdr; - uint32_t unique_id; -}; - -/** - * struct mpt3_diag_read_buffer - request for copy of the diag buffer - * @hdr - generic header - * @status - - * @reserved - - * @flags - misc flags - * @starting_offset - starting offset within drivers buffer where to start - * reading data at into the specified application buffer - * @bytes_to_read - number of bytes to copy from the drivers buffer into the - * application buffer starting at starting_offset. - * @unique_id - unique id associated with this buffer. - * @diagnostic_data - data payload - */ -struct mpt3_diag_read_buffer { - struct mpt3_ioctl_header hdr; - uint8_t status; - uint8_t reserved; - uint16_t flags; - uint32_t starting_offset; - uint32_t bytes_to_read; - uint32_t unique_id; - uint32_t diagnostic_data[1]; -}; - -#endif /* MPT3SAS_CTL_H_INCLUDED */ diff --git a/addons/mpt3sas/src/4.4.180/mpt3sas_debug.h b/addons/mpt3sas/src/4.4.180/mpt3sas_debug.h deleted file mode 100644 index cceeb2c1..00000000 --- a/addons/mpt3sas/src/4.4.180/mpt3sas_debug.h +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Logging Support for MPT (Message Passing Technology) based controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_debug.c - * Copyright (C) 2012-2014 LSI Corporation - * Copyright (C) 2013-2014 Avago Technologies - * (mailto: MPT-FusionLinux.pdl@avagotech.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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 MPT3SAS_DEBUG_H_INCLUDED -#define MPT3SAS_DEBUG_H_INCLUDED - -#define MPT_DEBUG 0x00000001 -#define MPT_DEBUG_MSG_FRAME 0x00000002 -#define MPT_DEBUG_SG 0x00000004 -#define MPT_DEBUG_EVENTS 0x00000008 -#define MPT_DEBUG_EVENT_WORK_TASK 0x00000010 -#define MPT_DEBUG_INIT 0x00000020 -#define MPT_DEBUG_EXIT 0x00000040 -#define MPT_DEBUG_FAIL 0x00000080 -#define MPT_DEBUG_TM 0x00000100 -#define MPT_DEBUG_REPLY 0x00000200 -#define MPT_DEBUG_HANDSHAKE 0x00000400 -#define MPT_DEBUG_CONFIG 0x00000800 -#define MPT_DEBUG_DL 0x00001000 -#define MPT_DEBUG_RESET 0x00002000 -#define MPT_DEBUG_SCSI 0x00004000 -#define MPT_DEBUG_IOCTL 0x00008000 -#define MPT_DEBUG_SAS 0x00020000 -#define MPT_DEBUG_TRANSPORT 0x00040000 -#define MPT_DEBUG_TASK_SET_FULL 0x00080000 - -#define MPT_DEBUG_TRIGGER_DIAG 0x00200000 - - -#define MPT_CHECK_LOGGING(IOC, CMD, BITS) \ -{ \ - if (IOC->logging_level & BITS) \ - CMD; \ -} - -/* - * debug macros - */ - -#define dprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG) - -#define dsgprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SG) - -#define devtprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENTS) - -#define dewtprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EVENT_WORK_TASK) - -#define dinitprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_INIT) - -#define dexitprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_EXIT) - -#define dfailprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_FAIL) - -#define dtmprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TM) - -#define dreplyprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_REPLY) - -#define dhsprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_HANDSHAKE) - -#define dcprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_CONFIG) - -#define ddlprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_DL) - -#define drsprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_RESET) - -#define dsprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SCSI) - -#define dctlprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_IOCTL) - -#define dsasprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS) - -#define dsastransport(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_SAS_WIDE) - -#define dmfprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_MSG_FRAME) - -#define dtsfprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TASK_SET_FULL) - -#define dtransportprintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRANSPORT) - -#define dTriggerDiagPrintk(IOC, CMD) \ - MPT_CHECK_LOGGING(IOC, CMD, MPT_DEBUG_TRIGGER_DIAG) - - - -/* inline functions for dumping debug data*/ - -/** - * _debug_dump_mf - print message frame contents - * @mpi_request: pointer to message frame - * @sz: number of dwords - */ -static inline void -_debug_dump_mf(void *mpi_request, int sz) -{ - int i; - __le32 *mfp = (__le32 *)mpi_request; - - pr_info("mf:\n\t"); - for (i = 0; i < sz; i++) { - if (i && ((i % 8) == 0)) - pr_info("\n\t"); - pr_info("%08x ", le32_to_cpu(mfp[i])); - } - pr_info("\n"); -} -/** - * _debug_dump_reply - print message frame contents - * @mpi_request: pointer to message frame - * @sz: number of dwords - */ -static inline void -_debug_dump_reply(void *mpi_request, int sz) -{ - int i; - __le32 *mfp = (__le32 *)mpi_request; - - pr_info("reply:\n\t"); - for (i = 0; i < sz; i++) { - if (i && ((i % 8) == 0)) - pr_info("\n\t"); - pr_info("%08x ", le32_to_cpu(mfp[i])); - } - pr_info("\n"); -} -/** - * _debug_dump_config - print config page contents - * @mpi_request: pointer to message frame - * @sz: number of dwords - */ -static inline void -_debug_dump_config(void *mpi_request, int sz) -{ - int i; - __le32 *mfp = (__le32 *)mpi_request; - - pr_info("config:\n\t"); - for (i = 0; i < sz; i++) { - if (i && ((i % 8) == 0)) - pr_info("\n\t"); - pr_info("%08x ", le32_to_cpu(mfp[i])); - } - pr_info("\n"); -} - -#endif /* MPT3SAS_DEBUG_H_INCLUDED */ diff --git a/addons/mpt3sas/src/4.4.180/mpt3sas_scsih.c b/addons/mpt3sas/src/4.4.180/mpt3sas_scsih.c deleted file mode 100644 index 7d67a68b..00000000 --- a/addons/mpt3sas/src/4.4.180/mpt3sas_scsih.c +++ /dev/null @@ -1,9107 +0,0 @@ -/* - * Scsi Host Layer for MPT (Message Passing Technology) based controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_scsih.c - * Copyright (C) 2012-2014 LSI Corporation - * Copyright (C) 2013-2014 Avago Technologies - * (mailto: MPT-FusionLinux.pdl@avagotech.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "mpt3sas_base.h" - -#define RAID_CHANNEL 1 -/* forward proto's */ -static void _scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_expander); -static void _firmware_event_work(struct work_struct *work); - -static void _scsih_remove_device(struct MPT3SAS_ADAPTER *ioc, - struct _sas_device *sas_device); -static int _scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u8 retry_count, u8 is_pd); - -static u8 _scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid); - -/* global parameters */ -LIST_HEAD(mpt3sas_ioc_list); -/* global ioc lock for list operations */ -DEFINE_SPINLOCK(gioc_lock); - -MODULE_AUTHOR(MPT3SAS_AUTHOR); -MODULE_DESCRIPTION(MPT3SAS_DESCRIPTION); -MODULE_LICENSE("GPL"); -MODULE_VERSION(MPT3SAS_DRIVER_VERSION); -MODULE_ALIAS("mpt2sas"); - -/* local parameters */ -static u8 scsi_io_cb_idx = -1; -static u8 tm_cb_idx = -1; -static u8 ctl_cb_idx = -1; -static u8 base_cb_idx = -1; -static u8 port_enable_cb_idx = -1; -static u8 transport_cb_idx = -1; -static u8 scsih_cb_idx = -1; -static u8 config_cb_idx = -1; -static int mpt2_ids; -static int mpt3_ids; - -static u8 tm_tr_cb_idx = -1 ; -static u8 tm_tr_volume_cb_idx = -1 ; -static u8 tm_sas_control_cb_idx = -1; - -/* command line options */ -static u32 logging_level; -MODULE_PARM_DESC(logging_level, - " bits for enabling additional logging info (default=0)"); - - -static ushort max_sectors = 0xFFFF; -module_param(max_sectors, ushort, 0); -MODULE_PARM_DESC(max_sectors, "max sectors, range 64 to 32767 default=32767"); - - -static int missing_delay[2] = {-1, -1}; -module_param_array(missing_delay, int, NULL, 0); -MODULE_PARM_DESC(missing_delay, " device missing delay , io missing delay"); - -/* scsi-mid layer global parmeter is max_report_luns, which is 511 */ -#define MPT3SAS_MAX_LUN (16895) -static u64 max_lun = MPT3SAS_MAX_LUN; -module_param(max_lun, ullong, 0); -MODULE_PARM_DESC(max_lun, " max lun, default=16895 "); - -static ushort hbas_to_enumerate; -module_param(hbas_to_enumerate, ushort, 0); -MODULE_PARM_DESC(hbas_to_enumerate, - " 0 - enumerates both SAS 2.0 & SAS 3.0 generation HBAs\n \ - 1 - enumerates only SAS 2.0 generation HBAs\n \ - 2 - enumerates only SAS 3.0 generation HBAs (default=0)"); - -/* diag_buffer_enable is bitwise - * bit 0 set = TRACE - * bit 1 set = SNAPSHOT - * bit 2 set = EXTENDED - * - * Either bit can be set, or both - */ -static int diag_buffer_enable = -1; -module_param(diag_buffer_enable, int, 0); -MODULE_PARM_DESC(diag_buffer_enable, - " post diag buffers (TRACE=1/SNAPSHOT=2/EXTENDED=4/default=0)"); -static int disable_discovery = -1; -module_param(disable_discovery, int, 0); -MODULE_PARM_DESC(disable_discovery, " disable discovery "); - - -/* permit overriding the host protection capabilities mask (EEDP/T10 PI) */ -static int prot_mask = -1; -module_param(prot_mask, int, 0); -MODULE_PARM_DESC(prot_mask, " host protection capabilities mask, def=7 "); - - -/* raid transport support */ -struct raid_template *mpt3sas_raid_template; -struct raid_template *mpt2sas_raid_template; - - -/** - * struct sense_info - common structure for obtaining sense keys - * @skey: sense key - * @asc: additional sense code - * @ascq: additional sense code qualifier - */ -struct sense_info { - u8 skey; - u8 asc; - u8 ascq; -}; - -#define MPT3SAS_PROCESS_TRIGGER_DIAG (0xFFFB) -#define MPT3SAS_TURN_ON_PFA_LED (0xFFFC) -#define MPT3SAS_PORT_ENABLE_COMPLETE (0xFFFD) -#define MPT3SAS_ABRT_TASK_SET (0xFFFE) -#define MPT3SAS_REMOVE_UNRESPONDING_DEVICES (0xFFFF) -/** - * struct fw_event_work - firmware event struct - * @list: link list framework - * @work: work object (ioc->fault_reset_work_q) - * @cancel_pending_work: flag set during reset handling - * @ioc: per adapter object - * @device_handle: device handle - * @VF_ID: virtual function id - * @VP_ID: virtual port id - * @ignore: flag meaning this event has been marked to ignore - * @event: firmware event MPI2_EVENT_XXX defined in mpt2_ioc.h - * @event_data: reply event data payload follows - * - * This object stored on ioc->fw_event_list. - */ -struct fw_event_work { - struct list_head list; - struct work_struct work; - u8 cancel_pending_work; - struct delayed_work delayed_work; - - struct MPT3SAS_ADAPTER *ioc; - u16 device_handle; - u8 VF_ID; - u8 VP_ID; - u8 ignore; - u16 event; - struct kref refcount; - char event_data[0] __aligned(4); -}; - -static void fw_event_work_free(struct kref *r) -{ - kfree(container_of(r, struct fw_event_work, refcount)); -} - -static void fw_event_work_get(struct fw_event_work *fw_work) -{ - kref_get(&fw_work->refcount); -} - -static void fw_event_work_put(struct fw_event_work *fw_work) -{ - kref_put(&fw_work->refcount, fw_event_work_free); -} - -static struct fw_event_work *alloc_fw_event_work(int len) -{ - struct fw_event_work *fw_event; - - fw_event = kzalloc(sizeof(*fw_event) + len, GFP_ATOMIC); - if (!fw_event) - return NULL; - - kref_init(&fw_event->refcount); - return fw_event; -} - -/** - * struct _scsi_io_transfer - scsi io transfer - * @handle: sas device handle (assigned by firmware) - * @is_raid: flag set for hidden raid components - * @dir: DMA_TO_DEVICE, DMA_FROM_DEVICE, - * @data_length: data transfer length - * @data_dma: dma pointer to data - * @sense: sense data - * @lun: lun number - * @cdb_length: cdb length - * @cdb: cdb contents - * @timeout: timeout for this command - * @VF_ID: virtual function id - * @VP_ID: virtual port id - * @valid_reply: flag set for reply message - * @sense_length: sense length - * @ioc_status: ioc status - * @scsi_state: scsi state - * @scsi_status: scsi staus - * @log_info: log information - * @transfer_length: data length transfer when there is a reply message - * - * Used for sending internal scsi commands to devices within this module. - * Refer to _scsi_send_scsi_io(). - */ -struct _scsi_io_transfer { - u16 handle; - u8 is_raid; - enum dma_data_direction dir; - u32 data_length; - dma_addr_t data_dma; - u8 sense[SCSI_SENSE_BUFFERSIZE]; - u32 lun; - u8 cdb_length; - u8 cdb[32]; - u8 timeout; - u8 VF_ID; - u8 VP_ID; - u8 valid_reply; - /* the following bits are only valid when 'valid_reply = 1' */ - u32 sense_length; - u16 ioc_status; - u8 scsi_state; - u8 scsi_status; - u32 log_info; - u32 transfer_length; -}; - -/** - * _scsih_set_debug_level - global setting of ioc->logging_level. - * - * Note: The logging levels are defined in mpt3sas_debug.h. - */ -static int -_scsih_set_debug_level(const char *val, struct kernel_param *kp) -{ - int ret = param_set_int(val, kp); - struct MPT3SAS_ADAPTER *ioc; - - if (ret) - return ret; - - pr_info("setting logging_level(0x%08x)\n", logging_level); - spin_lock(&gioc_lock); - list_for_each_entry(ioc, &mpt3sas_ioc_list, list) - ioc->logging_level = logging_level; - spin_unlock(&gioc_lock); - return 0; -} -module_param_call(logging_level, _scsih_set_debug_level, param_get_int, - &logging_level, 0644); - -/** - * _scsih_srch_boot_sas_address - search based on sas_address - * @sas_address: sas address - * @boot_device: boot device object from bios page 2 - * - * Returns 1 when there's a match, 0 means no match. - */ -static inline int -_scsih_srch_boot_sas_address(u64 sas_address, - Mpi2BootDeviceSasWwid_t *boot_device) -{ - return (sas_address == le64_to_cpu(boot_device->SASAddress)) ? 1 : 0; -} - -/** - * _scsih_srch_boot_device_name - search based on device name - * @device_name: device name specified in INDENTIFY fram - * @boot_device: boot device object from bios page 2 - * - * Returns 1 when there's a match, 0 means no match. - */ -static inline int -_scsih_srch_boot_device_name(u64 device_name, - Mpi2BootDeviceDeviceName_t *boot_device) -{ - return (device_name == le64_to_cpu(boot_device->DeviceName)) ? 1 : 0; -} - -/** - * _scsih_srch_boot_encl_slot - search based on enclosure_logical_id/slot - * @enclosure_logical_id: enclosure logical id - * @slot_number: slot number - * @boot_device: boot device object from bios page 2 - * - * Returns 1 when there's a match, 0 means no match. - */ -static inline int -_scsih_srch_boot_encl_slot(u64 enclosure_logical_id, u16 slot_number, - Mpi2BootDeviceEnclosureSlot_t *boot_device) -{ - return (enclosure_logical_id == le64_to_cpu(boot_device-> - EnclosureLogicalID) && slot_number == le16_to_cpu(boot_device-> - SlotNumber)) ? 1 : 0; -} - -/** - * _scsih_is_boot_device - search for matching boot device. - * @sas_address: sas address - * @device_name: device name specified in INDENTIFY fram - * @enclosure_logical_id: enclosure logical id - * @slot_number: slot number - * @form: specifies boot device form - * @boot_device: boot device object from bios page 2 - * - * Returns 1 when there's a match, 0 means no match. - */ -static int -_scsih_is_boot_device(u64 sas_address, u64 device_name, - u64 enclosure_logical_id, u16 slot, u8 form, - Mpi2BiosPage2BootDevice_t *boot_device) -{ - int rc = 0; - - switch (form) { - case MPI2_BIOSPAGE2_FORM_SAS_WWID: - if (!sas_address) - break; - rc = _scsih_srch_boot_sas_address( - sas_address, &boot_device->SasWwid); - break; - case MPI2_BIOSPAGE2_FORM_ENCLOSURE_SLOT: - if (!enclosure_logical_id) - break; - rc = _scsih_srch_boot_encl_slot( - enclosure_logical_id, - slot, &boot_device->EnclosureSlot); - break; - case MPI2_BIOSPAGE2_FORM_DEVICE_NAME: - if (!device_name) - break; - rc = _scsih_srch_boot_device_name( - device_name, &boot_device->DeviceName); - break; - case MPI2_BIOSPAGE2_FORM_NO_DEVICE_SPECIFIED: - break; - } - - return rc; -} - -/** - * _scsih_get_sas_address - set the sas_address for given device handle - * @handle: device handle - * @sas_address: sas address - * - * Returns 0 success, non-zero when failure - */ -static int -_scsih_get_sas_address(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u64 *sas_address) -{ - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2ConfigReply_t mpi_reply; - u32 ioc_status; - - *sas_address = 0; - - if (handle <= ioc->sas_hba.num_phys) { - *sas_address = ioc->sas_hba.sas_address; - return 0; - } - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__); - return -ENXIO; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_SUCCESS) { - *sas_address = le64_to_cpu(sas_device_pg0.SASAddress); - return 0; - } - - /* we hit this becuase the given parent handle doesn't exist */ - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) - return -ENXIO; - - /* else error case */ - pr_err(MPT3SAS_FMT - "handle(0x%04x), ioc_status(0x%04x), failure at %s:%d/%s()!\n", - ioc->name, handle, ioc_status, - __FILE__, __LINE__, __func__); - return -EIO; -} - -/** - * _scsih_determine_boot_device - determine boot device. - * @ioc: per adapter object - * @device: either sas_device or raid_device object - * @is_raid: [flag] 1 = raid object, 0 = sas object - * - * Determines whether this device should be first reported device to - * to scsi-ml or sas transport, this purpose is for persistent boot device. - * There are primary, alternate, and current entries in bios page 2. The order - * priority is primary, alternate, then current. This routine saves - * the corresponding device object and is_raid flag in the ioc object. - * The saved data to be used later in _scsih_probe_boot_devices(). - */ -static void -_scsih_determine_boot_device(struct MPT3SAS_ADAPTER *ioc, - void *device, u8 is_raid) -{ - struct _sas_device *sas_device; - struct _raid_device *raid_device; - u64 sas_address; - u64 device_name; - u64 enclosure_logical_id; - u16 slot; - - /* only process this function when driver loads */ - if (!ioc->is_driver_loading) - return; - - /* no Bios, return immediately */ - if (!ioc->bios_pg3.BiosVersion) - return; - - if (!is_raid) { - sas_device = device; - sas_address = sas_device->sas_address; - device_name = sas_device->device_name; - enclosure_logical_id = sas_device->enclosure_logical_id; - slot = sas_device->slot; - } else { - raid_device = device; - sas_address = raid_device->wwid; - device_name = 0; - enclosure_logical_id = 0; - slot = 0; - } - - if (!ioc->req_boot_device.device) { - if (_scsih_is_boot_device(sas_address, device_name, - enclosure_logical_id, slot, - (ioc->bios_pg2.ReqBootDeviceForm & - MPI2_BIOSPAGE2_FORM_MASK), - &ioc->bios_pg2.RequestedBootDevice)) { - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "%s: req_boot_device(0x%016llx)\n", - ioc->name, __func__, - (unsigned long long)sas_address)); - ioc->req_boot_device.device = device; - ioc->req_boot_device.is_raid = is_raid; - } - } - - if (!ioc->req_alt_boot_device.device) { - if (_scsih_is_boot_device(sas_address, device_name, - enclosure_logical_id, slot, - (ioc->bios_pg2.ReqAltBootDeviceForm & - MPI2_BIOSPAGE2_FORM_MASK), - &ioc->bios_pg2.RequestedAltBootDevice)) { - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "%s: req_alt_boot_device(0x%016llx)\n", - ioc->name, __func__, - (unsigned long long)sas_address)); - ioc->req_alt_boot_device.device = device; - ioc->req_alt_boot_device.is_raid = is_raid; - } - } - - if (!ioc->current_boot_device.device) { - if (_scsih_is_boot_device(sas_address, device_name, - enclosure_logical_id, slot, - (ioc->bios_pg2.CurrentBootDeviceForm & - MPI2_BIOSPAGE2_FORM_MASK), - &ioc->bios_pg2.CurrentBootDevice)) { - dinitprintk(ioc, pr_info(MPT3SAS_FMT - "%s: current_boot_device(0x%016llx)\n", - ioc->name, __func__, - (unsigned long long)sas_address)); - ioc->current_boot_device.device = device; - ioc->current_boot_device.is_raid = is_raid; - } - } -} - -static struct _sas_device * -__mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc, - struct MPT3SAS_TARGET *tgt_priv) -{ - struct _sas_device *ret; - - assert_spin_locked(&ioc->sas_device_lock); - - ret = tgt_priv->sdev; - if (ret) - sas_device_get(ret); - - return ret; -} - -static struct _sas_device * -mpt3sas_get_sdev_from_target(struct MPT3SAS_ADAPTER *ioc, - struct MPT3SAS_TARGET *tgt_priv) -{ - struct _sas_device *ret; - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - ret = __mpt3sas_get_sdev_from_target(ioc, tgt_priv); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - return ret; -} - - -struct _sas_device * -__mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) -{ - struct _sas_device *sas_device; - - assert_spin_locked(&ioc->sas_device_lock); - - list_for_each_entry(sas_device, &ioc->sas_device_list, list) - if (sas_device->sas_address == sas_address) - goto found_device; - - list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) - if (sas_device->sas_address == sas_address) - goto found_device; - - return NULL; - -found_device: - sas_device_get(sas_device); - return sas_device; -} - -/** - * mpt3sas_get_sdev_by_addr - sas device search - * @ioc: per adapter object - * @sas_address: sas address - * Context: Calling function should acquire ioc->sas_device_lock - * - * This searches for sas_device based on sas_address, then return sas_device - * object. - */ -struct _sas_device * -mpt3sas_get_sdev_by_addr(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) -{ - struct _sas_device *sas_device; - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, - sas_address); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - return sas_device; -} - -static struct _sas_device * -__mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _sas_device *sas_device; - - assert_spin_locked(&ioc->sas_device_lock); - - list_for_each_entry(sas_device, &ioc->sas_device_list, list) - if (sas_device->handle == handle) - goto found_device; - - list_for_each_entry(sas_device, &ioc->sas_device_init_list, list) - if (sas_device->handle == handle) - goto found_device; - - return NULL; - -found_device: - sas_device_get(sas_device); - return sas_device; -} - -/** - * mpt3sas_get_sdev_by_handle - sas device search - * @ioc: per adapter object - * @handle: sas device handle (assigned by firmware) - * Context: Calling function should acquire ioc->sas_device_lock - * - * This searches for sas_device based on sas_address, then return sas_device - * object. - */ -static struct _sas_device * -mpt3sas_get_sdev_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _sas_device *sas_device; - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - return sas_device; -} - -/** - * _scsih_sas_device_remove - remove sas_device from list. - * @ioc: per adapter object - * @sas_device: the sas_device object - * Context: This function will acquire ioc->sas_device_lock. - * - * If sas_device is on the list, remove it and decrement its reference count. - */ -static void -_scsih_sas_device_remove(struct MPT3SAS_ADAPTER *ioc, - struct _sas_device *sas_device) -{ - unsigned long flags; - - if (!sas_device) - return; - pr_info(MPT3SAS_FMT - "removing handle(0x%04x), sas_addr(0x%016llx)\n", - ioc->name, sas_device->handle, - (unsigned long long) sas_device->sas_address); - - if (sas_device->enclosure_handle != 0) - pr_info(MPT3SAS_FMT - "removing enclosure logical id(0x%016llx), slot(%d)\n", - ioc->name, (unsigned long long) - sas_device->enclosure_logical_id, sas_device->slot); - - if (sas_device->connector_name[0] != '\0') - pr_info(MPT3SAS_FMT - "removing enclosure level(0x%04x), connector name( %s)\n", - ioc->name, sas_device->enclosure_level, - sas_device->connector_name); - - /* - * The lock serializes access to the list, but we still need to verify - * that nobody removed the entry while we were waiting on the lock. - */ - spin_lock_irqsave(&ioc->sas_device_lock, flags); - if (!list_empty(&sas_device->list)) { - list_del_init(&sas_device->list); - sas_device_put(sas_device); - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); -} - -/** - * _scsih_device_remove_by_handle - removing device object by handle - * @ioc: per adapter object - * @handle: device handle - * - * Return nothing. - */ -static void -_scsih_device_remove_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _sas_device *sas_device; - unsigned long flags; - - if (ioc->shost_recovery) - return; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); - if (sas_device) { - list_del_init(&sas_device->list); - sas_device_put(sas_device); - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (sas_device) { - _scsih_remove_device(ioc, sas_device); - sas_device_put(sas_device); - } -} - -/** - * mpt3sas_device_remove_by_sas_address - removing device object by sas address - * @ioc: per adapter object - * @sas_address: device sas_address - * - * Return nothing. - */ -void -mpt3sas_device_remove_by_sas_address(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) -{ - struct _sas_device *sas_device; - unsigned long flags; - - if (ioc->shost_recovery) - return; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, sas_address); - if (sas_device) { - list_del_init(&sas_device->list); - sas_device_put(sas_device); - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (sas_device) { - _scsih_remove_device(ioc, sas_device); - sas_device_put(sas_device); - } -} - -/** - * _scsih_sas_device_add - insert sas_device to the list. - * @ioc: per adapter object - * @sas_device: the sas_device object - * Context: This function will acquire ioc->sas_device_lock. - * - * Adding new object to the ioc->sas_device_list. - */ -static void -_scsih_sas_device_add(struct MPT3SAS_ADAPTER *ioc, - struct _sas_device *sas_device) -{ - unsigned long flags; - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), sas_addr(0x%016llx)\n", - ioc->name, __func__, sas_device->handle, - (unsigned long long)sas_device->sas_address)); - - if (sas_device->enclosure_handle != 0) - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: enclosure logical id(0x%016llx), slot( %d)\n", - ioc->name, __func__, (unsigned long long) - sas_device->enclosure_logical_id, sas_device->slot)); - - if (sas_device->connector_name[0] != '\0') - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: enclosure level(0x%04x), connector name( %s)\n", - ioc->name, __func__, - sas_device->enclosure_level, sas_device->connector_name)); - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device_get(sas_device); - list_add_tail(&sas_device->list, &ioc->sas_device_list); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - if (!mpt3sas_transport_port_add(ioc, sas_device->handle, - sas_device->sas_address_parent)) { - _scsih_sas_device_remove(ioc, sas_device); - } else if (!sas_device->starget) { - /* - * When asyn scanning is enabled, its not possible to remove - * devices while scanning is turned on due to an oops in - * scsi_sysfs_add_sdev()->add_device()->sysfs_addrm_start() - */ - if (!ioc->is_driver_loading) { - mpt3sas_transport_port_remove(ioc, - sas_device->sas_address, - sas_device->sas_address_parent); - _scsih_sas_device_remove(ioc, sas_device); - } - } -} - -/** - * _scsih_sas_device_init_add - insert sas_device to the list. - * @ioc: per adapter object - * @sas_device: the sas_device object - * Context: This function will acquire ioc->sas_device_lock. - * - * Adding new object at driver load time to the ioc->sas_device_init_list. - */ -static void -_scsih_sas_device_init_add(struct MPT3SAS_ADAPTER *ioc, - struct _sas_device *sas_device) -{ - unsigned long flags; - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), sas_addr(0x%016llx)\n", ioc->name, - __func__, sas_device->handle, - (unsigned long long)sas_device->sas_address)); - - if (sas_device->enclosure_handle != 0) - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: enclosure logical id(0x%016llx), slot( %d)\n", - ioc->name, __func__, (unsigned long long) - sas_device->enclosure_logical_id, sas_device->slot)); - - if (sas_device->connector_name[0] != '\0') - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: enclosure level(0x%04x), connector name( %s)\n", - ioc->name, __func__, sas_device->enclosure_level, - sas_device->connector_name)); - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device_get(sas_device); - list_add_tail(&sas_device->list, &ioc->sas_device_init_list); - _scsih_determine_boot_device(ioc, sas_device, 0); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); -} - -/** - * _scsih_raid_device_find_by_id - raid device search - * @ioc: per adapter object - * @id: sas device target id - * @channel: sas device channel - * Context: Calling function should acquire ioc->raid_device_lock - * - * This searches for raid_device based on target id, then return raid_device - * object. - */ -static struct _raid_device * -_scsih_raid_device_find_by_id(struct MPT3SAS_ADAPTER *ioc, int id, int channel) -{ - struct _raid_device *raid_device, *r; - - r = NULL; - list_for_each_entry(raid_device, &ioc->raid_device_list, list) { - if (raid_device->id == id && raid_device->channel == channel) { - r = raid_device; - goto out; - } - } - - out: - return r; -} - -/** - * mpt3sas_raid_device_find_by_handle - raid device search - * @ioc: per adapter object - * @handle: sas device handle (assigned by firmware) - * Context: Calling function should acquire ioc->raid_device_lock - * - * This searches for raid_device based on handle, then return raid_device - * object. - */ -struct _raid_device * -mpt3sas_raid_device_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _raid_device *raid_device, *r; - - r = NULL; - list_for_each_entry(raid_device, &ioc->raid_device_list, list) { - if (raid_device->handle != handle) - continue; - r = raid_device; - goto out; - } - - out: - return r; -} - -/** - * _scsih_raid_device_find_by_wwid - raid device search - * @ioc: per adapter object - * @handle: sas device handle (assigned by firmware) - * Context: Calling function should acquire ioc->raid_device_lock - * - * This searches for raid_device based on wwid, then return raid_device - * object. - */ -static struct _raid_device * -_scsih_raid_device_find_by_wwid(struct MPT3SAS_ADAPTER *ioc, u64 wwid) -{ - struct _raid_device *raid_device, *r; - - r = NULL; - list_for_each_entry(raid_device, &ioc->raid_device_list, list) { - if (raid_device->wwid != wwid) - continue; - r = raid_device; - goto out; - } - - out: - return r; -} - -/** - * _scsih_raid_device_add - add raid_device object - * @ioc: per adapter object - * @raid_device: raid_device object - * - * This is added to the raid_device_list link list. - */ -static void -_scsih_raid_device_add(struct MPT3SAS_ADAPTER *ioc, - struct _raid_device *raid_device) -{ - unsigned long flags; - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), wwid(0x%016llx)\n", ioc->name, __func__, - raid_device->handle, (unsigned long long)raid_device->wwid)); - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - list_add_tail(&raid_device->list, &ioc->raid_device_list); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); -} - -/** - * _scsih_raid_device_remove - delete raid_device object - * @ioc: per adapter object - * @raid_device: raid_device object - * - */ -static void -_scsih_raid_device_remove(struct MPT3SAS_ADAPTER *ioc, - struct _raid_device *raid_device) -{ - unsigned long flags; - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - list_del(&raid_device->list); - kfree(raid_device); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); -} - -/** - * mpt3sas_scsih_expander_find_by_handle - expander device search - * @ioc: per adapter object - * @handle: expander handle (assigned by firmware) - * Context: Calling function should acquire ioc->sas_device_lock - * - * This searches for expander device based on handle, then returns the - * sas_node object. - */ -struct _sas_node * -mpt3sas_scsih_expander_find_by_handle(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _sas_node *sas_expander, *r; - - r = NULL; - list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { - if (sas_expander->handle != handle) - continue; - r = sas_expander; - goto out; - } - out: - return r; -} - -/** - * mpt3sas_scsih_expander_find_by_sas_address - expander device search - * @ioc: per adapter object - * @sas_address: sas address - * Context: Calling function should acquire ioc->sas_node_lock. - * - * This searches for expander device based on sas_address, then returns the - * sas_node object. - */ -struct _sas_node * -mpt3sas_scsih_expander_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) -{ - struct _sas_node *sas_expander, *r; - - r = NULL; - list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { - if (sas_expander->sas_address != sas_address) - continue; - r = sas_expander; - goto out; - } - out: - return r; -} - -/** - * _scsih_expander_node_add - insert expander device to the list. - * @ioc: per adapter object - * @sas_expander: the sas_device object - * Context: This function will acquire ioc->sas_node_lock. - * - * Adding new object to the ioc->sas_expander_list. - * - * Return nothing. - */ -static void -_scsih_expander_node_add(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_expander) -{ - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - list_add_tail(&sas_expander->list, &ioc->sas_expander_list); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); -} - -/** - * _scsih_is_end_device - determines if device is an end device - * @device_info: bitfield providing information about the device. - * Context: none - * - * Returns 1 if end device. - */ -static int -_scsih_is_end_device(u32 device_info) -{ - if (device_info & MPI2_SAS_DEVICE_INFO_END_DEVICE && - ((device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) | - (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) | - (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE))) - return 1; - else - return 0; -} - -/** - * _scsih_scsi_lookup_get - returns scmd entry - * @ioc: per adapter object - * @smid: system request message index - * - * Returns the smid stored scmd pointer. - */ -static struct scsi_cmnd * -_scsih_scsi_lookup_get(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - return ioc->scsi_lookup[smid - 1].scmd; -} - -/** - * _scsih_scsi_lookup_get_clear - returns scmd entry - * @ioc: per adapter object - * @smid: system request message index - * - * Returns the smid stored scmd pointer. - * Then will derefrence the stored scmd pointer. - */ -static inline struct scsi_cmnd * -_scsih_scsi_lookup_get_clear(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - unsigned long flags; - struct scsi_cmnd *scmd; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - scmd = ioc->scsi_lookup[smid - 1].scmd; - ioc->scsi_lookup[smid - 1].scmd = NULL; - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - - return scmd; -} - -/** - * _scsih_scsi_lookup_find_by_scmd - scmd lookup - * @ioc: per adapter object - * @smid: system request message index - * @scmd: pointer to scsi command object - * Context: This function will acquire ioc->scsi_lookup_lock. - * - * This will search for a scmd pointer in the scsi_lookup array, - * returning the revelent smid. A returned value of zero means invalid. - */ -static u16 -_scsih_scsi_lookup_find_by_scmd(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd - *scmd) -{ - u16 smid; - unsigned long flags; - int i; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - smid = 0; - for (i = 0; i < ioc->scsiio_depth; i++) { - if (ioc->scsi_lookup[i].scmd == scmd) { - smid = ioc->scsi_lookup[i].smid; - goto out; - } - } - out: - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return smid; -} - -/** - * _scsih_scsi_lookup_find_by_target - search for matching channel:id - * @ioc: per adapter object - * @id: target id - * @channel: channel - * Context: This function will acquire ioc->scsi_lookup_lock. - * - * This will search for a matching channel:id in the scsi_lookup array, - * returning 1 if found. - */ -static u8 -_scsih_scsi_lookup_find_by_target(struct MPT3SAS_ADAPTER *ioc, int id, - int channel) -{ - u8 found; - unsigned long flags; - int i; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - found = 0; - for (i = 0 ; i < ioc->scsiio_depth; i++) { - if (ioc->scsi_lookup[i].scmd && - (ioc->scsi_lookup[i].scmd->device->id == id && - ioc->scsi_lookup[i].scmd->device->channel == channel)) { - found = 1; - goto out; - } - } - out: - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return found; -} - -/** - * _scsih_scsi_lookup_find_by_lun - search for matching channel:id:lun - * @ioc: per adapter object - * @id: target id - * @lun: lun number - * @channel: channel - * Context: This function will acquire ioc->scsi_lookup_lock. - * - * This will search for a matching channel:id:lun in the scsi_lookup array, - * returning 1 if found. - */ -static u8 -_scsih_scsi_lookup_find_by_lun(struct MPT3SAS_ADAPTER *ioc, int id, - unsigned int lun, int channel) -{ - u8 found; - unsigned long flags; - int i; - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - found = 0; - for (i = 0 ; i < ioc->scsiio_depth; i++) { - if (ioc->scsi_lookup[i].scmd && - (ioc->scsi_lookup[i].scmd->device->id == id && - ioc->scsi_lookup[i].scmd->device->channel == channel && - ioc->scsi_lookup[i].scmd->device->lun == lun)) { - found = 1; - goto out; - } - } - out: - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - return found; -} - -/** - * scsih_change_queue_depth - setting device queue depth - * @sdev: scsi device struct - * @qdepth: requested queue depth - * - * Returns queue depth. - */ -int -scsih_change_queue_depth(struct scsi_device *sdev, int qdepth) -{ - struct Scsi_Host *shost = sdev->host; - int max_depth; - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct MPT3SAS_TARGET *sas_target_priv_data; - struct _sas_device *sas_device; - unsigned long flags; - - max_depth = shost->can_queue; - - /* limit max device queue for SATA to 32 */ - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - goto not_sata; - sas_target_priv_data = sas_device_priv_data->sas_target; - if (!sas_target_priv_data) - goto not_sata; - if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) - goto not_sata; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data); - if (sas_device) { - if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) - max_depth = MPT3SAS_SATA_QUEUE_DEPTH; - - sas_device_put(sas_device); - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - not_sata: - - if (!sdev->tagged_supported) - max_depth = 1; - if (qdepth > max_depth) - qdepth = max_depth; - return scsi_change_queue_depth(sdev, qdepth); -} - -/** - * scsih_target_alloc - target add routine - * @starget: scsi target struct - * - * Returns 0 if ok. Any other return is assumed to be an error and - * the device is ignored. - */ -int -scsih_target_alloc(struct scsi_target *starget) -{ - struct Scsi_Host *shost = dev_to_shost(&starget->dev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - struct MPT3SAS_TARGET *sas_target_priv_data; - struct _sas_device *sas_device; - struct _raid_device *raid_device; - unsigned long flags; - struct sas_rphy *rphy; - - sas_target_priv_data = kzalloc(sizeof(*sas_target_priv_data), - GFP_KERNEL); - if (!sas_target_priv_data) - return -ENOMEM; - - starget->hostdata = sas_target_priv_data; - sas_target_priv_data->starget = starget; - sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE; - - /* RAID volumes */ - if (starget->channel == RAID_CHANNEL) { - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_id(ioc, starget->id, - starget->channel); - if (raid_device) { - sas_target_priv_data->handle = raid_device->handle; - sas_target_priv_data->sas_address = raid_device->wwid; - sas_target_priv_data->flags |= MPT_TARGET_FLAGS_VOLUME; - if (ioc->is_warpdrive) - sas_target_priv_data->raid_device = raid_device; - raid_device->starget = starget; - } - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - return 0; - } - - /* sas/sata devices */ - spin_lock_irqsave(&ioc->sas_device_lock, flags); - rphy = dev_to_rphy(starget->dev.parent); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, - rphy->identify.sas_address); - - if (sas_device) { - sas_target_priv_data->handle = sas_device->handle; - sas_target_priv_data->sas_address = sas_device->sas_address; - sas_target_priv_data->sdev = sas_device; - sas_device->starget = starget; - sas_device->id = starget->id; - sas_device->channel = starget->channel; - if (test_bit(sas_device->handle, ioc->pd_handles)) - sas_target_priv_data->flags |= - MPT_TARGET_FLAGS_RAID_COMPONENT; - if (sas_device->fast_path) - sas_target_priv_data->flags |= MPT_TARGET_FASTPATH_IO; - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - return 0; -} - -/** - * scsih_target_destroy - target destroy routine - * @starget: scsi target struct - * - * Returns nothing. - */ -void -scsih_target_destroy(struct scsi_target *starget) -{ - struct Scsi_Host *shost = dev_to_shost(&starget->dev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - struct MPT3SAS_TARGET *sas_target_priv_data; - struct _sas_device *sas_device; - struct _raid_device *raid_device; - unsigned long flags; - struct sas_rphy *rphy; - - sas_target_priv_data = starget->hostdata; - if (!sas_target_priv_data) - return; - - if (starget->channel == RAID_CHANNEL) { - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_id(ioc, starget->id, - starget->channel); - if (raid_device) { - raid_device->starget = NULL; - raid_device->sdev = NULL; - } - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - goto out; - } - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - rphy = dev_to_rphy(starget->dev.parent); - sas_device = __mpt3sas_get_sdev_from_target(ioc, sas_target_priv_data); - if (sas_device && (sas_device->starget == starget) && - (sas_device->id == starget->id) && - (sas_device->channel == starget->channel)) - sas_device->starget = NULL; - - if (sas_device) { - /* - * Corresponding get() is in _scsih_target_alloc() - */ - sas_target_priv_data->sdev = NULL; - sas_device_put(sas_device); - - sas_device_put(sas_device); - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - out: - kfree(sas_target_priv_data); - starget->hostdata = NULL; -} - -/** - * scsih_slave_alloc - device add routine - * @sdev: scsi device struct - * - * Returns 0 if ok. Any other return is assumed to be an error and - * the device is ignored. - */ -int -scsih_slave_alloc(struct scsi_device *sdev) -{ - struct Scsi_Host *shost; - struct MPT3SAS_ADAPTER *ioc; - struct MPT3SAS_TARGET *sas_target_priv_data; - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_target *starget; - struct _raid_device *raid_device; - struct _sas_device *sas_device; - unsigned long flags; - - sas_device_priv_data = kzalloc(sizeof(*sas_device_priv_data), - GFP_KERNEL); - if (!sas_device_priv_data) - return -ENOMEM; - - sas_device_priv_data->lun = sdev->lun; - sas_device_priv_data->flags = MPT_DEVICE_FLAGS_INIT; - - starget = scsi_target(sdev); - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->num_luns++; - sas_device_priv_data->sas_target = sas_target_priv_data; - sdev->hostdata = sas_device_priv_data; - if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT)) - sdev->no_uld_attach = 1; - - shost = dev_to_shost(&starget->dev); - ioc = shost_priv(shost); - if (starget->channel == RAID_CHANNEL) { - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_id(ioc, - starget->id, starget->channel); - if (raid_device) - raid_device->sdev = sdev; /* raid is single lun */ - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - } - - if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, - sas_target_priv_data->sas_address); - if (sas_device && (sas_device->starget == NULL)) { - sdev_printk(KERN_INFO, sdev, - "%s : sas_device->starget set to starget @ %d\n", - __func__, __LINE__); - sas_device->starget = starget; - } - - if (sas_device) - sas_device_put(sas_device); - - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - } - - return 0; -} - -/** - * scsih_slave_destroy - device destroy routine - * @sdev: scsi device struct - * - * Returns nothing. - */ -void -scsih_slave_destroy(struct scsi_device *sdev) -{ - struct MPT3SAS_TARGET *sas_target_priv_data; - struct scsi_target *starget; - struct Scsi_Host *shost; - struct MPT3SAS_ADAPTER *ioc; - struct _sas_device *sas_device; - unsigned long flags; - - if (!sdev->hostdata) - return; - - starget = scsi_target(sdev); - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->num_luns--; - - shost = dev_to_shost(&starget->dev); - ioc = shost_priv(shost); - - if (!(sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME)) { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_from_target(ioc, - sas_target_priv_data); - if (sas_device && !sas_target_priv_data->num_luns) - sas_device->starget = NULL; - - if (sas_device) - sas_device_put(sas_device); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - } - - kfree(sdev->hostdata); - sdev->hostdata = NULL; -} - -/** - * _scsih_display_sata_capabilities - sata capabilities - * @ioc: per adapter object - * @handle: device handle - * @sdev: scsi device struct - */ -static void -_scsih_display_sata_capabilities(struct MPT3SAS_ADAPTER *ioc, - u16 handle, struct scsi_device *sdev) -{ - Mpi2ConfigReply_t mpi_reply; - Mpi2SasDevicePage0_t sas_device_pg0; - u32 ioc_status; - u16 flags; - u32 device_info; - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - flags = le16_to_cpu(sas_device_pg0.Flags); - device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); - - sdev_printk(KERN_INFO, sdev, - "atapi(%s), ncq(%s), asyn_notify(%s), smart(%s), fua(%s), " - "sw_preserve(%s)\n", - (device_info & MPI2_SAS_DEVICE_INFO_ATAPI_DEVICE) ? "y" : "n", - (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_NCQ_SUPPORTED) ? "y" : "n", - (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_ASYNCHRONOUS_NOTIFY) ? "y" : - "n", - (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SMART_SUPPORTED) ? "y" : "n", - (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_FUA_SUPPORTED) ? "y" : "n", - (flags & MPI2_SAS_DEVICE0_FLAGS_SATA_SW_PRESERVE) ? "y" : "n"); -} - -/* - * raid transport support - - * Enabled for SLES11 and newer, in older kernels the driver will panic when - * unloading the driver followed by a load - I beleive that the subroutine - * raid_class_release() is not cleaning up properly. - */ - -/** - * scsih_is_raid - return boolean indicating device is raid volume - * @dev the device struct object - */ -int -scsih_is_raid(struct device *dev) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host); - - if (ioc->is_warpdrive) - return 0; - return (sdev->channel == RAID_CHANNEL) ? 1 : 0; -} - -/** - * scsih_get_resync - get raid volume resync percent complete - * @dev the device struct object - */ -void -scsih_get_resync(struct device *dev) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host); - static struct _raid_device *raid_device; - unsigned long flags; - Mpi2RaidVolPage0_t vol_pg0; - Mpi2ConfigReply_t mpi_reply; - u32 volume_status_flags; - u8 percent_complete; - u16 handle; - - percent_complete = 0; - handle = 0; - if (ioc->is_warpdrive) - goto out; - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id, - sdev->channel); - if (raid_device) { - handle = raid_device->handle; - percent_complete = raid_device->percent_complete; - } - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - - if (!handle) - goto out; - - if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0, - MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, - sizeof(Mpi2RaidVolPage0_t))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - percent_complete = 0; - goto out; - } - - volume_status_flags = le32_to_cpu(vol_pg0.VolumeStatusFlags); - if (!(volume_status_flags & - MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS)) - percent_complete = 0; - - out: - if (ioc->hba_mpi_version_belonged == MPI2_VERSION) - raid_set_resync(mpt2sas_raid_template, dev, percent_complete); - if (ioc->hba_mpi_version_belonged == MPI25_VERSION) - raid_set_resync(mpt3sas_raid_template, dev, percent_complete); -} - -/** - * scsih_get_state - get raid volume level - * @dev the device struct object - */ -void -scsih_get_state(struct device *dev) -{ - struct scsi_device *sdev = to_scsi_device(dev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(sdev->host); - static struct _raid_device *raid_device; - unsigned long flags; - Mpi2RaidVolPage0_t vol_pg0; - Mpi2ConfigReply_t mpi_reply; - u32 volstate; - enum raid_state state = RAID_STATE_UNKNOWN; - u16 handle = 0; - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_id(ioc, sdev->id, - sdev->channel); - if (raid_device) - handle = raid_device->handle; - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - - if (!raid_device) - goto out; - - if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, &vol_pg0, - MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, - sizeof(Mpi2RaidVolPage0_t))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - - volstate = le32_to_cpu(vol_pg0.VolumeStatusFlags); - if (volstate & MPI2_RAIDVOL0_STATUS_FLAG_RESYNC_IN_PROGRESS) { - state = RAID_STATE_RESYNCING; - goto out; - } - - switch (vol_pg0.VolumeState) { - case MPI2_RAID_VOL_STATE_OPTIMAL: - case MPI2_RAID_VOL_STATE_ONLINE: - state = RAID_STATE_ACTIVE; - break; - case MPI2_RAID_VOL_STATE_DEGRADED: - state = RAID_STATE_DEGRADED; - break; - case MPI2_RAID_VOL_STATE_FAILED: - case MPI2_RAID_VOL_STATE_MISSING: - state = RAID_STATE_OFFLINE; - break; - } - out: - if (ioc->hba_mpi_version_belonged == MPI2_VERSION) - raid_set_state(mpt2sas_raid_template, dev, state); - if (ioc->hba_mpi_version_belonged == MPI25_VERSION) - raid_set_state(mpt3sas_raid_template, dev, state); -} - -/** - * _scsih_set_level - set raid level - * @sdev: scsi device struct - * @volume_type: volume type - */ -static void -_scsih_set_level(struct MPT3SAS_ADAPTER *ioc, - struct scsi_device *sdev, u8 volume_type) -{ - enum raid_level level = RAID_LEVEL_UNKNOWN; - - switch (volume_type) { - case MPI2_RAID_VOL_TYPE_RAID0: - level = RAID_LEVEL_0; - break; - case MPI2_RAID_VOL_TYPE_RAID10: - level = RAID_LEVEL_10; - break; - case MPI2_RAID_VOL_TYPE_RAID1E: - level = RAID_LEVEL_1E; - break; - case MPI2_RAID_VOL_TYPE_RAID1: - level = RAID_LEVEL_1; - break; - } - - if (ioc->hba_mpi_version_belonged == MPI2_VERSION) - raid_set_level(mpt2sas_raid_template, - &sdev->sdev_gendev, level); - if (ioc->hba_mpi_version_belonged == MPI25_VERSION) - raid_set_level(mpt3sas_raid_template, - &sdev->sdev_gendev, level); -} - - -/** - * _scsih_get_volume_capabilities - volume capabilities - * @ioc: per adapter object - * @sas_device: the raid_device object - * - * Returns 0 for success, else 1 - */ -static int -_scsih_get_volume_capabilities(struct MPT3SAS_ADAPTER *ioc, - struct _raid_device *raid_device) -{ - Mpi2RaidVolPage0_t *vol_pg0; - Mpi2RaidPhysDiskPage0_t pd_pg0; - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2ConfigReply_t mpi_reply; - u16 sz; - u8 num_pds; - - if ((mpt3sas_config_get_number_pds(ioc, raid_device->handle, - &num_pds)) || !num_pds) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, - __func__)); - return 1; - } - - raid_device->num_pds = num_pds; - sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds * - sizeof(Mpi2RaidVol0PhysDisk_t)); - vol_pg0 = kzalloc(sz, GFP_KERNEL); - if (!vol_pg0) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, - __func__)); - return 1; - } - - if ((mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0, - MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, - __func__)); - kfree(vol_pg0); - return 1; - } - - raid_device->volume_type = vol_pg0->VolumeType; - - /* figure out what the underlying devices are by - * obtaining the device_info bits for the 1st device - */ - if (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply, - &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM, - vol_pg0->PhysDisk[0].PhysDiskNum))) { - if (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, - &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, - le16_to_cpu(pd_pg0.DevHandle)))) { - raid_device->device_info = - le32_to_cpu(sas_device_pg0.DeviceInfo); - } - } - - kfree(vol_pg0); - return 0; -} - -/** - * _scsih_enable_tlr - setting TLR flags - * @ioc: per adapter object - * @sdev: scsi device struct - * - * Enabling Transaction Layer Retries for tape devices when - * vpd page 0x90 is present - * - */ -static void -_scsih_enable_tlr(struct MPT3SAS_ADAPTER *ioc, struct scsi_device *sdev) -{ - - /* only for TAPE */ - if (sdev->type != TYPE_TAPE) - return; - - if (!(ioc->facts.IOCCapabilities & MPI2_IOCFACTS_CAPABILITY_TLR)) - return; - - sas_enable_tlr(sdev); - sdev_printk(KERN_INFO, sdev, "TLR %s\n", - sas_is_tlr_enabled(sdev) ? "Enabled" : "Disabled"); - return; - -} - -/** - * scsih_slave_configure - device configure routine. - * @sdev: scsi device struct - * - * Returns 0 if ok. Any other return is assumed to be an error and - * the device is ignored. - */ -int -scsih_slave_configure(struct scsi_device *sdev) -{ - struct Scsi_Host *shost = sdev->host; - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct MPT3SAS_TARGET *sas_target_priv_data; - struct _sas_device *sas_device; - struct _raid_device *raid_device; - unsigned long flags; - int qdepth; - u8 ssp_target = 0; - char *ds = ""; - char *r_level = ""; - u16 handle, volume_handle = 0; - u64 volume_wwid = 0; - - qdepth = 1; - sas_device_priv_data = sdev->hostdata; - sas_device_priv_data->configured_lun = 1; - sas_device_priv_data->flags &= ~MPT_DEVICE_FLAGS_INIT; - sas_target_priv_data = sas_device_priv_data->sas_target; - handle = sas_target_priv_data->handle; - - /* raid volume handling */ - if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME) { - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - if (!raid_device) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, __FILE__, - __LINE__, __func__)); - return 1; - } - - if (_scsih_get_volume_capabilities(ioc, raid_device)) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, __FILE__, - __LINE__, __func__)); - return 1; - } - - /* - * WARPDRIVE: Initialize the required data for Direct IO - */ - mpt3sas_init_warpdrive_properties(ioc, raid_device); - - /* RAID Queue Depth Support - * IS volume = underlying qdepth of drive type, either - * MPT3SAS_SAS_QUEUE_DEPTH or MPT3SAS_SATA_QUEUE_DEPTH - * IM/IME/R10 = 128 (MPT3SAS_RAID_QUEUE_DEPTH) - */ - if (raid_device->device_info & - MPI2_SAS_DEVICE_INFO_SSP_TARGET) { - qdepth = MPT3SAS_SAS_QUEUE_DEPTH; - ds = "SSP"; - } else { - qdepth = MPT3SAS_SATA_QUEUE_DEPTH; - if (raid_device->device_info & - MPI2_SAS_DEVICE_INFO_SATA_DEVICE) - ds = "SATA"; - else - ds = "STP"; - } - - switch (raid_device->volume_type) { - case MPI2_RAID_VOL_TYPE_RAID0: - r_level = "RAID0"; - break; - case MPI2_RAID_VOL_TYPE_RAID1E: - qdepth = MPT3SAS_RAID_QUEUE_DEPTH; - if (ioc->manu_pg10.OEMIdentifier && - (le32_to_cpu(ioc->manu_pg10.GenericFlags0) & - MFG10_GF0_R10_DISPLAY) && - !(raid_device->num_pds % 2)) - r_level = "RAID10"; - else - r_level = "RAID1E"; - break; - case MPI2_RAID_VOL_TYPE_RAID1: - qdepth = MPT3SAS_RAID_QUEUE_DEPTH; - r_level = "RAID1"; - break; - case MPI2_RAID_VOL_TYPE_RAID10: - qdepth = MPT3SAS_RAID_QUEUE_DEPTH; - r_level = "RAID10"; - break; - case MPI2_RAID_VOL_TYPE_UNKNOWN: - default: - qdepth = MPT3SAS_RAID_QUEUE_DEPTH; - r_level = "RAIDX"; - break; - } - - if (!ioc->hide_ir_msg) - sdev_printk(KERN_INFO, sdev, - "%s: handle(0x%04x), wwid(0x%016llx)," - " pd_count(%d), type(%s)\n", - r_level, raid_device->handle, - (unsigned long long)raid_device->wwid, - raid_device->num_pds, ds); - - scsih_change_queue_depth(sdev, qdepth); - - /* raid transport support */ - if (!ioc->is_warpdrive) - _scsih_set_level(ioc, sdev, raid_device->volume_type); - return 0; - } - - /* non-raid handling */ - if (sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) { - if (mpt3sas_config_get_volume_handle(ioc, handle, - &volume_handle)) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__)); - return 1; - } - if (volume_handle && mpt3sas_config_get_volume_wwid(ioc, - volume_handle, &volume_wwid)) { - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__)); - return 1; - } - } - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, - sas_device_priv_data->sas_target->sas_address); - if (!sas_device) { - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - dfailprintk(ioc, pr_warn(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, __FILE__, __LINE__, - __func__)); - return 1; - } - - sas_device->volume_handle = volume_handle; - sas_device->volume_wwid = volume_wwid; - if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) { - qdepth = MPT3SAS_SAS_QUEUE_DEPTH; - ssp_target = 1; - ds = "SSP"; - } else { - qdepth = MPT3SAS_SATA_QUEUE_DEPTH; - if (sas_device->device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) - ds = "STP"; - else if (sas_device->device_info & - MPI2_SAS_DEVICE_INFO_SATA_DEVICE) - ds = "SATA"; - } - - sdev_printk(KERN_INFO, sdev, "%s: handle(0x%04x), " \ - "sas_addr(0x%016llx), phy(%d), device_name(0x%016llx)\n", - ds, handle, (unsigned long long)sas_device->sas_address, - sas_device->phy, (unsigned long long)sas_device->device_name); - if (sas_device->enclosure_handle != 0) - sdev_printk(KERN_INFO, sdev, - "%s: enclosure_logical_id(0x%016llx), slot(%d)\n", - ds, (unsigned long long) - sas_device->enclosure_logical_id, sas_device->slot); - if (sas_device->connector_name[0] != '\0') - sdev_printk(KERN_INFO, sdev, - "%s: enclosure level(0x%04x), connector name( %s)\n", - ds, sas_device->enclosure_level, - sas_device->connector_name); - - sas_device_put(sas_device); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - if (!ssp_target) - _scsih_display_sata_capabilities(ioc, handle, sdev); - - - scsih_change_queue_depth(sdev, qdepth); - - if (ssp_target) { - sas_read_port_mode_page(sdev); - _scsih_enable_tlr(ioc, sdev); - } - - return 0; -} - -/** - * scsih_bios_param - fetch head, sector, cylinder info for a disk - * @sdev: scsi device struct - * @bdev: pointer to block device context - * @capacity: device size (in 512 byte sectors) - * @params: three element array to place output: - * params[0] number of heads (max 255) - * params[1] number of sectors (max 63) - * params[2] number of cylinders - * - * Return nothing. - */ -int -scsih_bios_param(struct scsi_device *sdev, struct block_device *bdev, - sector_t capacity, int params[]) -{ - int heads; - int sectors; - sector_t cylinders; - ulong dummy; - - heads = 64; - sectors = 32; - - dummy = heads * sectors; - cylinders = capacity; - sector_div(cylinders, dummy); - - /* - * Handle extended translation size for logical drives - * > 1Gb - */ - if ((ulong)capacity >= 0x200000) { - heads = 255; - sectors = 63; - dummy = heads * sectors; - cylinders = capacity; - sector_div(cylinders, dummy); - } - - /* return result */ - params[0] = heads; - params[1] = sectors; - params[2] = cylinders; - - return 0; -} - -/** - * _scsih_response_code - translation of device response code - * @ioc: per adapter object - * @response_code: response code returned by the device - * - * Return nothing. - */ -static void -_scsih_response_code(struct MPT3SAS_ADAPTER *ioc, u8 response_code) -{ - char *desc; - - switch (response_code) { - case MPI2_SCSITASKMGMT_RSP_TM_COMPLETE: - desc = "task management request completed"; - break; - case MPI2_SCSITASKMGMT_RSP_INVALID_FRAME: - desc = "invalid frame"; - break; - case MPI2_SCSITASKMGMT_RSP_TM_NOT_SUPPORTED: - desc = "task management request not supported"; - break; - case MPI2_SCSITASKMGMT_RSP_TM_FAILED: - desc = "task management request failed"; - break; - case MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED: - desc = "task management request succeeded"; - break; - case MPI2_SCSITASKMGMT_RSP_TM_INVALID_LUN: - desc = "invalid lun"; - break; - case 0xA: - desc = "overlapped tag attempted"; - break; - case MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC: - desc = "task queued, however not sent to target"; - break; - default: - desc = "unknown"; - break; - } - pr_warn(MPT3SAS_FMT "response_code(0x%01x): %s\n", - ioc->name, response_code, desc); -} - -/** - * _scsih_tm_done - tm completion routine - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: none. - * - * The callback handler when using scsih_issue_tm. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_tm_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - - if (ioc->tm_cmds.status == MPT3_CMD_NOT_USED) - return 1; - if (ioc->tm_cmds.smid != smid) - return 1; - mpt3sas_base_flush_reply_queues(ioc); - ioc->tm_cmds.status |= MPT3_CMD_COMPLETE; - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (mpi_reply) { - memcpy(ioc->tm_cmds.reply, mpi_reply, mpi_reply->MsgLength*4); - ioc->tm_cmds.status |= MPT3_CMD_REPLY_VALID; - } - ioc->tm_cmds.status &= ~MPT3_CMD_PENDING; - complete(&ioc->tm_cmds.done); - return 1; -} - -/** - * mpt3sas_scsih_set_tm_flag - set per target tm_busy - * @ioc: per adapter object - * @handle: device handle - * - * During taskmangement request, we need to freeze the device queue. - */ -void -mpt3sas_scsih_set_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - u8 skip = 0; - - shost_for_each_device(sdev, ioc->shost) { - if (skip) - continue; - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - continue; - if (sas_device_priv_data->sas_target->handle == handle) { - sas_device_priv_data->sas_target->tm_busy = 1; - skip = 1; - ioc->ignore_loginfos = 1; - } - } -} - -/** - * mpt3sas_scsih_clear_tm_flag - clear per target tm_busy - * @ioc: per adapter object - * @handle: device handle - * - * During taskmangement request, we need to freeze the device queue. - */ -void -mpt3sas_scsih_clear_tm_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - u8 skip = 0; - - shost_for_each_device(sdev, ioc->shost) { - if (skip) - continue; - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - continue; - if (sas_device_priv_data->sas_target->handle == handle) { - sas_device_priv_data->sas_target->tm_busy = 0; - skip = 1; - ioc->ignore_loginfos = 0; - } - } -} - -/** - * mpt3sas_scsih_issue_tm - main routine for sending tm requests - * @ioc: per adapter struct - * @device_handle: device handle - * @channel: the channel assigned by the OS - * @id: the id assigned by the OS - * @lun: lun number - * @type: MPI2_SCSITASKMGMT_TASKTYPE__XXX (defined in mpi2_init.h) - * @smid_task: smid assigned to the task - * @timeout: timeout in seconds - * @m_type: TM_MUTEX_ON or TM_MUTEX_OFF - * Context: user - * - * A generic API for sending task management requests to firmware. - * - * The callback index is set inside `ioc->tm_cb_idx`. - * - * Return SUCCESS or FAILED. - */ -int -mpt3sas_scsih_issue_tm(struct MPT3SAS_ADAPTER *ioc, u16 handle, uint channel, - uint id, uint lun, u8 type, u16 smid_task, ulong timeout, - enum mutex_type m_type) -{ - Mpi2SCSITaskManagementRequest_t *mpi_request; - Mpi2SCSITaskManagementReply_t *mpi_reply; - u16 smid = 0; - u32 ioc_state; - unsigned long timeleft; - struct scsiio_tracker *scsi_lookup = NULL; - int rc; - u16 msix_task = 0; - - if (m_type == TM_MUTEX_ON) - mutex_lock(&ioc->tm_cmds.mutex); - if (ioc->tm_cmds.status != MPT3_CMD_NOT_USED) { - pr_info(MPT3SAS_FMT "%s: tm_cmd busy!!!\n", - __func__, ioc->name); - rc = FAILED; - goto err_out; - } - - if (ioc->shost_recovery || ioc->remove_host || - ioc->pci_error_recovery) { - pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", - __func__, ioc->name); - rc = FAILED; - goto err_out; - } - - ioc_state = mpt3sas_base_get_iocstate(ioc, 0); - if (ioc_state & MPI2_DOORBELL_USED) { - dhsprintk(ioc, pr_info(MPT3SAS_FMT - "unexpected doorbell active!\n", ioc->name)); - rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - rc = (!rc) ? SUCCESS : FAILED; - goto err_out; - } - - if ((ioc_state & MPI2_IOC_STATE_MASK) == MPI2_IOC_STATE_FAULT) { - mpt3sas_base_fault_info(ioc, ioc_state & - MPI2_DOORBELL_DATA_MASK); - rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - rc = (!rc) ? SUCCESS : FAILED; - goto err_out; - } - - smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = FAILED; - goto err_out; - } - - if (type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) - scsi_lookup = &ioc->scsi_lookup[smid_task - 1]; - - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "sending tm: handle(0x%04x), task_type(0x%02x), smid(%d)\n", - ioc->name, handle, type, smid_task)); - ioc->tm_cmds.status = MPT3_CMD_PENDING; - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->tm_cmds.smid = smid; - memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); - memset(ioc->tm_cmds.reply, 0, sizeof(Mpi2SCSITaskManagementReply_t)); - mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; - mpi_request->DevHandle = cpu_to_le16(handle); - mpi_request->TaskType = type; - mpi_request->TaskMID = cpu_to_le16(smid_task); - int_to_scsilun(lun, (struct scsi_lun *)mpi_request->LUN); - mpt3sas_scsih_set_tm_flag(ioc, handle); - init_completion(&ioc->tm_cmds.done); - if ((type == MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK) && - (scsi_lookup->msix_io < ioc->reply_queue_count)) - msix_task = scsi_lookup->msix_io; - else - msix_task = 0; - mpt3sas_base_put_smid_hi_priority(ioc, smid, msix_task); - timeleft = wait_for_completion_timeout(&ioc->tm_cmds.done, timeout*HZ); - if (!(ioc->tm_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SCSITaskManagementRequest_t)/4); - if (!(ioc->tm_cmds.status & MPT3_CMD_RESET)) { - rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - rc = (!rc) ? SUCCESS : FAILED; - ioc->tm_cmds.status = MPT3_CMD_NOT_USED; - mpt3sas_scsih_clear_tm_flag(ioc, handle); - goto err_out; - } - } - - if (ioc->tm_cmds.status & MPT3_CMD_REPLY_VALID) { - mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT); - mpi_reply = ioc->tm_cmds.reply; - dtmprintk(ioc, pr_info(MPT3SAS_FMT "complete tm: " \ - "ioc_status(0x%04x), loginfo(0x%08x), term_count(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo), - le32_to_cpu(mpi_reply->TerminationCount))); - if (ioc->logging_level & MPT_DEBUG_TM) { - _scsih_response_code(ioc, mpi_reply->ResponseCode); - if (mpi_reply->IOCStatus) - _debug_dump_mf(mpi_request, - sizeof(Mpi2SCSITaskManagementRequest_t)/4); - } - } - - switch (type) { - case MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK: - rc = SUCCESS; - if (scsi_lookup->scmd == NULL) - break; - rc = FAILED; - break; - - case MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET: - if (_scsih_scsi_lookup_find_by_target(ioc, id, channel)) - rc = FAILED; - else - rc = SUCCESS; - break; - case MPI2_SCSITASKMGMT_TASKTYPE_ABRT_TASK_SET: - case MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET: - if (_scsih_scsi_lookup_find_by_lun(ioc, id, lun, channel)) - rc = FAILED; - else - rc = SUCCESS; - break; - case MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK: - rc = SUCCESS; - break; - default: - rc = FAILED; - break; - } - - mpt3sas_scsih_clear_tm_flag(ioc, handle); - ioc->tm_cmds.status = MPT3_CMD_NOT_USED; - if (m_type == TM_MUTEX_ON) - mutex_unlock(&ioc->tm_cmds.mutex); - - return rc; - - err_out: - if (m_type == TM_MUTEX_ON) - mutex_unlock(&ioc->tm_cmds.mutex); - return rc; -} - -/** - * _scsih_tm_display_info - displays info about the device - * @ioc: per adapter struct - * @scmd: pointer to scsi command object - * - * Called by task management callback handlers. - */ -static void -_scsih_tm_display_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd) -{ - struct scsi_target *starget = scmd->device->sdev_target; - struct MPT3SAS_TARGET *priv_target = starget->hostdata; - struct _sas_device *sas_device = NULL; - unsigned long flags; - char *device_str = NULL; - - if (!priv_target) - return; - if (ioc->hide_ir_msg) - device_str = "WarpDrive"; - else - device_str = "volume"; - - scsi_print_command(scmd); - if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) { - starget_printk(KERN_INFO, starget, - "%s handle(0x%04x), %s wwid(0x%016llx)\n", - device_str, priv_target->handle, - device_str, (unsigned long long)priv_target->sas_address); - } else { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_from_target(ioc, priv_target); - if (sas_device) { - if (priv_target->flags & - MPT_TARGET_FLAGS_RAID_COMPONENT) { - starget_printk(KERN_INFO, starget, - "volume handle(0x%04x), " - "volume wwid(0x%016llx)\n", - sas_device->volume_handle, - (unsigned long long)sas_device->volume_wwid); - } - starget_printk(KERN_INFO, starget, - "handle(0x%04x), sas_address(0x%016llx), phy(%d)\n", - sas_device->handle, - (unsigned long long)sas_device->sas_address, - sas_device->phy); - if (sas_device->enclosure_handle != 0) - starget_printk(KERN_INFO, starget, - "enclosure_logical_id(0x%016llx), slot(%d)\n", - (unsigned long long) - sas_device->enclosure_logical_id, - sas_device->slot); - if (sas_device->connector_name) - starget_printk(KERN_INFO, starget, - "enclosure level(0x%04x),connector name(%s)\n", - sas_device->enclosure_level, - sas_device->connector_name); - - sas_device_put(sas_device); - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - } -} - -/** - * scsih_abort - eh threads main abort routine - * @scmd: pointer to scsi command object - * - * Returns SUCCESS if command aborted else FAILED - */ -int -scsih_abort(struct scsi_cmnd *scmd) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); - struct MPT3SAS_DEVICE *sas_device_priv_data; - u16 smid; - u16 handle; - int r; - - sdev_printk(KERN_INFO, scmd->device, - "attempting task abort! scmd(%p)\n", scmd); - _scsih_tm_display_info(ioc, scmd); - - sas_device_priv_data = scmd->device->hostdata; - if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { - sdev_printk(KERN_INFO, scmd->device, - "device been deleted! scmd(%p)\n", scmd); - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - r = SUCCESS; - goto out; - } - - /* search for the command */ - smid = _scsih_scsi_lookup_find_by_scmd(ioc, scmd); - if (!smid) { - scmd->result = DID_RESET << 16; - r = SUCCESS; - goto out; - } - - /* for hidden raid components and volumes this is not supported */ - if (sas_device_priv_data->sas_target->flags & - MPT_TARGET_FLAGS_RAID_COMPONENT || - sas_device_priv_data->sas_target->flags & MPT_TARGET_FLAGS_VOLUME) { - scmd->result = DID_RESET << 16; - r = FAILED; - goto out; - } - - mpt3sas_halt_firmware(ioc); - - handle = sas_device_priv_data->sas_target->handle; - r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel, - scmd->device->id, scmd->device->lun, - MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, TM_MUTEX_ON); - - out: - sdev_printk(KERN_INFO, scmd->device, "task abort: %s scmd(%p)\n", - ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); - return r; -} - -/** - * scsih_dev_reset - eh threads main device reset routine - * @scmd: pointer to scsi command object - * - * Returns SUCCESS if command aborted else FAILED - */ -int -scsih_dev_reset(struct scsi_cmnd *scmd) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct _sas_device *sas_device = NULL; - u16 handle; - int r; - - struct scsi_target *starget = scmd->device->sdev_target; - struct MPT3SAS_TARGET *target_priv_data = starget->hostdata; - - sdev_printk(KERN_INFO, scmd->device, - "attempting device reset! scmd(%p)\n", scmd); - _scsih_tm_display_info(ioc, scmd); - - sas_device_priv_data = scmd->device->hostdata; - if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { - sdev_printk(KERN_INFO, scmd->device, - "device been deleted! scmd(%p)\n", scmd); - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - r = SUCCESS; - goto out; - } - - /* for hidden raid components obtain the volume_handle */ - handle = 0; - if (sas_device_priv_data->sas_target->flags & - MPT_TARGET_FLAGS_RAID_COMPONENT) { - sas_device = mpt3sas_get_sdev_from_target(ioc, - target_priv_data); - if (sas_device) - handle = sas_device->volume_handle; - } else - handle = sas_device_priv_data->sas_target->handle; - - if (!handle) { - scmd->result = DID_RESET << 16; - r = FAILED; - goto out; - } - - r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel, - scmd->device->id, scmd->device->lun, - MPI2_SCSITASKMGMT_TASKTYPE_LOGICAL_UNIT_RESET, 0, 30, TM_MUTEX_ON); - - out: - sdev_printk(KERN_INFO, scmd->device, "device reset: %s scmd(%p)\n", - ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); - - if (sas_device) - sas_device_put(sas_device); - - return r; -} - -/** - * scsih_target_reset - eh threads main target reset routine - * @scmd: pointer to scsi command object - * - * Returns SUCCESS if command aborted else FAILED - */ -int -scsih_target_reset(struct scsi_cmnd *scmd) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct _sas_device *sas_device = NULL; - u16 handle; - int r; - struct scsi_target *starget = scmd->device->sdev_target; - struct MPT3SAS_TARGET *target_priv_data = starget->hostdata; - - starget_printk(KERN_INFO, starget, "attempting target reset! scmd(%p)\n", - scmd); - _scsih_tm_display_info(ioc, scmd); - - sas_device_priv_data = scmd->device->hostdata; - if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { - starget_printk(KERN_INFO, starget, "target been deleted! scmd(%p)\n", - scmd); - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - r = SUCCESS; - goto out; - } - - /* for hidden raid components obtain the volume_handle */ - handle = 0; - if (sas_device_priv_data->sas_target->flags & - MPT_TARGET_FLAGS_RAID_COMPONENT) { - sas_device = mpt3sas_get_sdev_from_target(ioc, - target_priv_data); - if (sas_device) - handle = sas_device->volume_handle; - } else - handle = sas_device_priv_data->sas_target->handle; - - if (!handle) { - scmd->result = DID_RESET << 16; - r = FAILED; - goto out; - } - - r = mpt3sas_scsih_issue_tm(ioc, handle, scmd->device->channel, - scmd->device->id, 0, MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET, 0, - 30, TM_MUTEX_ON); - - out: - starget_printk(KERN_INFO, starget, "target reset: %s scmd(%p)\n", - ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); - - if (sas_device) - sas_device_put(sas_device); - - return r; -} - - -/** - * scsih_host_reset - eh threads main host reset routine - * @scmd: pointer to scsi command object - * - * Returns SUCCESS if command aborted else FAILED - */ -int -scsih_host_reset(struct scsi_cmnd *scmd) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(scmd->device->host); - int r, retval; - - pr_info(MPT3SAS_FMT "attempting host reset! scmd(%p)\n", - ioc->name, scmd); - scsi_print_command(scmd); - - if (ioc->is_driver_loading) { - pr_info(MPT3SAS_FMT "Blocking the host reset\n", - ioc->name); - r = FAILED; - goto out; - } - - retval = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - r = (retval < 0) ? FAILED : SUCCESS; -out: - pr_info(MPT3SAS_FMT "host reset: %s scmd(%p)\n", - ioc->name, ((r == SUCCESS) ? "SUCCESS" : "FAILED"), scmd); - - return r; -} - -/** - * _scsih_fw_event_add - insert and queue up fw_event - * @ioc: per adapter object - * @fw_event: object describing the event - * Context: This function will acquire ioc->fw_event_lock. - * - * This adds the firmware event object into link list, then queues it up to - * be processed from user context. - * - * Return nothing. - */ -static void -_scsih_fw_event_add(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) -{ - unsigned long flags; - - if (ioc->firmware_event_thread == NULL) - return; - - spin_lock_irqsave(&ioc->fw_event_lock, flags); - fw_event_work_get(fw_event); - INIT_LIST_HEAD(&fw_event->list); - list_add_tail(&fw_event->list, &ioc->fw_event_list); - INIT_WORK(&fw_event->work, _firmware_event_work); - fw_event_work_get(fw_event); - queue_work(ioc->firmware_event_thread, &fw_event->work); - spin_unlock_irqrestore(&ioc->fw_event_lock, flags); -} - -/** - * _scsih_fw_event_del_from_list - delete fw_event from the list - * @ioc: per adapter object - * @fw_event: object describing the event - * Context: This function will acquire ioc->fw_event_lock. - * - * If the fw_event is on the fw_event_list, remove it and do a put. - * - * Return nothing. - */ -static void -_scsih_fw_event_del_from_list(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work - *fw_event) -{ - unsigned long flags; - - spin_lock_irqsave(&ioc->fw_event_lock, flags); - if (!list_empty(&fw_event->list)) { - list_del_init(&fw_event->list); - fw_event_work_put(fw_event); - } - spin_unlock_irqrestore(&ioc->fw_event_lock, flags); -} - - - /** - * mpt3sas_send_trigger_data_event - send event for processing trigger data - * @ioc: per adapter object - * @event_data: trigger event data - * - * Return nothing. - */ -void -mpt3sas_send_trigger_data_event(struct MPT3SAS_ADAPTER *ioc, - struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data) -{ - struct fw_event_work *fw_event; - u16 sz; - - if (ioc->is_driver_loading) - return; - sz = sizeof(*event_data); - fw_event = alloc_fw_event_work(sz); - if (!fw_event) - return; - fw_event->event = MPT3SAS_PROCESS_TRIGGER_DIAG; - fw_event->ioc = ioc; - memcpy(fw_event->event_data, event_data, sizeof(*event_data)); - _scsih_fw_event_add(ioc, fw_event); - fw_event_work_put(fw_event); -} - -/** - * _scsih_error_recovery_delete_devices - remove devices not responding - * @ioc: per adapter object - * - * Return nothing. - */ -static void -_scsih_error_recovery_delete_devices(struct MPT3SAS_ADAPTER *ioc) -{ - struct fw_event_work *fw_event; - - if (ioc->is_driver_loading) - return; - fw_event = alloc_fw_event_work(0); - if (!fw_event) - return; - fw_event->event = MPT3SAS_REMOVE_UNRESPONDING_DEVICES; - fw_event->ioc = ioc; - _scsih_fw_event_add(ioc, fw_event); - fw_event_work_put(fw_event); -} - -/** - * mpt3sas_port_enable_complete - port enable completed (fake event) - * @ioc: per adapter object - * - * Return nothing. - */ -void -mpt3sas_port_enable_complete(struct MPT3SAS_ADAPTER *ioc) -{ - struct fw_event_work *fw_event; - - fw_event = alloc_fw_event_work(0); - if (!fw_event) - return; - fw_event->event = MPT3SAS_PORT_ENABLE_COMPLETE; - fw_event->ioc = ioc; - _scsih_fw_event_add(ioc, fw_event); - fw_event_work_put(fw_event); -} - -static struct fw_event_work *dequeue_next_fw_event(struct MPT3SAS_ADAPTER *ioc) -{ - unsigned long flags; - struct fw_event_work *fw_event = NULL; - - spin_lock_irqsave(&ioc->fw_event_lock, flags); - if (!list_empty(&ioc->fw_event_list)) { - fw_event = list_first_entry(&ioc->fw_event_list, - struct fw_event_work, list); - list_del_init(&fw_event->list); - } - spin_unlock_irqrestore(&ioc->fw_event_lock, flags); - - return fw_event; -} - -/** - * _scsih_fw_event_cleanup_queue - cleanup event queue - * @ioc: per adapter object - * - * Walk the firmware event queue, either killing timers, or waiting - * for outstanding events to complete - * - * Return nothing. - */ -static void -_scsih_fw_event_cleanup_queue(struct MPT3SAS_ADAPTER *ioc) -{ - struct fw_event_work *fw_event; - - if (list_empty(&ioc->fw_event_list) || - !ioc->firmware_event_thread || in_interrupt()) - return; - - while ((fw_event = dequeue_next_fw_event(ioc))) { - /* - * Wait on the fw_event to complete. If this returns 1, then - * the event was never executed, and we need a put for the - * reference the delayed_work had on the fw_event. - * - * If it did execute, we wait for it to finish, and the put will - * happen from _firmware_event_work() - */ - if (cancel_delayed_work_sync(&fw_event->delayed_work)) - fw_event_work_put(fw_event); - - fw_event_work_put(fw_event); - } -} - -/** - * _scsih_internal_device_block - block the sdev device - * @sdev: per device object - * @sas_device_priv_data : per device driver private data - * - * make sure device is blocked without error, if not - * print an error - */ -static void -_scsih_internal_device_block(struct scsi_device *sdev, - struct MPT3SAS_DEVICE *sas_device_priv_data) -{ - int r = 0; - - sdev_printk(KERN_INFO, sdev, "device_block, handle(0x%04x)\n", - sas_device_priv_data->sas_target->handle); - sas_device_priv_data->block = 1; - - r = scsi_internal_device_block(sdev); - if (r == -EINVAL) - sdev_printk(KERN_WARNING, sdev, - "device_block failed with return(%d) for handle(0x%04x)\n", - sas_device_priv_data->sas_target->handle, r); -} - -/** - * _scsih_internal_device_unblock - unblock the sdev device - * @sdev: per device object - * @sas_device_priv_data : per device driver private data - * make sure device is unblocked without error, if not retry - * by blocking and then unblocking - */ - -static void -_scsih_internal_device_unblock(struct scsi_device *sdev, - struct MPT3SAS_DEVICE *sas_device_priv_data) -{ - int r = 0; - - sdev_printk(KERN_WARNING, sdev, "device_unblock and setting to running, " - "handle(0x%04x)\n", sas_device_priv_data->sas_target->handle); - sas_device_priv_data->block = 0; - r = scsi_internal_device_unblock(sdev, SDEV_RUNNING); - if (r == -EINVAL) { - /* The device has been set to SDEV_RUNNING by SD layer during - * device addition but the request queue is still stopped by - * our earlier block call. We need to perform a block again - * to get the device to SDEV_BLOCK and then to SDEV_RUNNING */ - - sdev_printk(KERN_WARNING, sdev, - "device_unblock failed with return(%d) for handle(0x%04x) " - "performing a block followed by an unblock\n", - sas_device_priv_data->sas_target->handle, r); - sas_device_priv_data->block = 1; - r = scsi_internal_device_block(sdev); - if (r) - sdev_printk(KERN_WARNING, sdev, "retried device_block " - "failed with return(%d) for handle(0x%04x)\n", - sas_device_priv_data->sas_target->handle, r); - - sas_device_priv_data->block = 0; - r = scsi_internal_device_unblock(sdev, SDEV_RUNNING); - if (r) - sdev_printk(KERN_WARNING, sdev, "retried device_unblock" - " failed with return(%d) for handle(0x%04x)\n", - sas_device_priv_data->sas_target->handle, r); - } -} - -/** - * _scsih_ublock_io_all_device - unblock every device - * @ioc: per adapter object - * - * change the device state from block to running - */ -static void -_scsih_ublock_io_all_device(struct MPT3SAS_ADAPTER *ioc) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - - shost_for_each_device(sdev, ioc->shost) { - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - continue; - if (!sas_device_priv_data->block) - continue; - - dewtprintk(ioc, sdev_printk(KERN_INFO, sdev, - "device_running, handle(0x%04x)\n", - sas_device_priv_data->sas_target->handle)); - _scsih_internal_device_unblock(sdev, sas_device_priv_data); - } -} - - -/** - * _scsih_ublock_io_device - prepare device to be deleted - * @ioc: per adapter object - * @sas_addr: sas address - * - * unblock then put device in offline state - */ -static void -_scsih_ublock_io_device(struct MPT3SAS_ADAPTER *ioc, u64 sas_address) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - - shost_for_each_device(sdev, ioc->shost) { - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - continue; - if (sas_device_priv_data->sas_target->sas_address - != sas_address) - continue; - if (sas_device_priv_data->block) - _scsih_internal_device_unblock(sdev, - sas_device_priv_data); - } -} - -/** - * _scsih_block_io_all_device - set the device state to SDEV_BLOCK - * @ioc: per adapter object - * @handle: device handle - * - * During device pull we need to appropiately set the sdev state. - */ -static void -_scsih_block_io_all_device(struct MPT3SAS_ADAPTER *ioc) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - - shost_for_each_device(sdev, ioc->shost) { - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - continue; - if (sas_device_priv_data->block) - continue; - _scsih_internal_device_block(sdev, sas_device_priv_data); - } -} - -/** - * _scsih_block_io_device - set the device state to SDEV_BLOCK - * @ioc: per adapter object - * @handle: device handle - * - * During device pull we need to appropiately set the sdev state. - */ -static void -_scsih_block_io_device(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - struct _sas_device *sas_device; - - sas_device = mpt3sas_get_sdev_by_handle(ioc, handle); - if (!sas_device) - return; - - shost_for_each_device(sdev, ioc->shost) { - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data) - continue; - if (sas_device_priv_data->sas_target->handle != handle) - continue; - if (sas_device_priv_data->block) - continue; - if (sas_device->pend_sas_rphy_add) - continue; - _scsih_internal_device_block(sdev, sas_device_priv_data); - } - - sas_device_put(sas_device); -} - -/** - * _scsih_block_io_to_children_attached_to_ex - * @ioc: per adapter object - * @sas_expander: the sas_device object - * - * This routine set sdev state to SDEV_BLOCK for all devices - * attached to this expander. This function called when expander is - * pulled. - */ -static void -_scsih_block_io_to_children_attached_to_ex(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_expander) -{ - struct _sas_port *mpt3sas_port; - struct _sas_device *sas_device; - struct _sas_node *expander_sibling; - unsigned long flags; - - if (!sas_expander) - return; - - list_for_each_entry(mpt3sas_port, - &sas_expander->sas_port_list, port_list) { - if (mpt3sas_port->remote_identify.device_type == - SAS_END_DEVICE) { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, - mpt3sas_port->remote_identify.sas_address); - if (sas_device) { - set_bit(sas_device->handle, - ioc->blocking_handles); - sas_device_put(sas_device); - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - } - } - - list_for_each_entry(mpt3sas_port, - &sas_expander->sas_port_list, port_list) { - - if (mpt3sas_port->remote_identify.device_type == - SAS_EDGE_EXPANDER_DEVICE || - mpt3sas_port->remote_identify.device_type == - SAS_FANOUT_EXPANDER_DEVICE) { - expander_sibling = - mpt3sas_scsih_expander_find_by_sas_address( - ioc, mpt3sas_port->remote_identify.sas_address); - _scsih_block_io_to_children_attached_to_ex(ioc, - expander_sibling); - } - } -} - -/** - * _scsih_block_io_to_children_attached_directly - * @ioc: per adapter object - * @event_data: topology change event data - * - * This routine set sdev state to SDEV_BLOCK for all devices - * direct attached during device pull. - */ -static void -_scsih_block_io_to_children_attached_directly(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataSasTopologyChangeList_t *event_data) -{ - int i; - u16 handle; - u16 reason_code; - - for (i = 0; i < event_data->NumEntries; i++) { - handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); - if (!handle) - continue; - reason_code = event_data->PHY[i].PhyStatus & - MPI2_EVENT_SAS_TOPO_RC_MASK; - if (reason_code == MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING) - _scsih_block_io_device(ioc, handle); - } -} - -/** - * _scsih_tm_tr_send - send task management request - * @ioc: per adapter object - * @handle: device handle - * Context: interrupt time. - * - * This code is to initiate the device removal handshake protocol - * with controller firmware. This function will issue target reset - * using high priority request queue. It will send a sas iounit - * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion. - * - * This is designed to send muliple task management request at the same - * time to the fifo. If the fifo is full, we will append the request, - * and process it in a future completion. - */ -static void -_scsih_tm_tr_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - Mpi2SCSITaskManagementRequest_t *mpi_request; - u16 smid; - struct _sas_device *sas_device = NULL; - struct MPT3SAS_TARGET *sas_target_priv_data = NULL; - u64 sas_address = 0; - unsigned long flags; - struct _tr_list *delayed_tr; - u32 ioc_state; - - if (ioc->remove_host) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host has been removed: handle(0x%04x)\n", - __func__, ioc->name, handle)); - return; - } else if (ioc->pci_error_recovery) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host in pci error recovery: handle(0x%04x)\n", - __func__, ioc->name, - handle)); - return; - } - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host is not operational: handle(0x%04x)\n", - __func__, ioc->name, - handle)); - return; - } - - /* if PD, then return */ - if (test_bit(handle, ioc->pd_handles)) - return; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); - if (sas_device && sas_device->starget && - sas_device->starget->hostdata) { - sas_target_priv_data = sas_device->starget->hostdata; - sas_target_priv_data->deleted = 1; - sas_address = sas_device->sas_address; - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - if (sas_target_priv_data) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "setting delete flag: handle(0x%04x), sas_addr(0x%016llx)\n", - ioc->name, handle, - (unsigned long long)sas_address)); - if (sas_device->enclosure_handle != 0) - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "setting delete flag:enclosure logical id(0x%016llx)," - " slot(%d)\n", ioc->name, (unsigned long long) - sas_device->enclosure_logical_id, - sas_device->slot)); - if (sas_device->connector_name) - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "setting delete flag: enclosure level(0x%04x)," - " connector name( %s)\n", ioc->name, - sas_device->enclosure_level, - sas_device->connector_name)); - _scsih_ublock_io_device(ioc, sas_address); - sas_target_priv_data->handle = MPT3SAS_INVALID_DEVICE_HANDLE; - } - - smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_cb_idx); - if (!smid) { - delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); - if (!delayed_tr) - goto out; - INIT_LIST_HEAD(&delayed_tr->list); - delayed_tr->handle = handle; - list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "DELAYED:tr:handle(0x%04x), (open)\n", - ioc->name, handle)); - goto out; - } - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n", - ioc->name, handle, smid, - ioc->tm_tr_cb_idx)); - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; - mpi_request->DevHandle = cpu_to_le16(handle); - mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; - mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); - mpt3sas_trigger_master(ioc, MASTER_TRIGGER_DEVICE_REMOVAL); - -out: - if (sas_device) - sas_device_put(sas_device); -} - -/** - * _scsih_tm_tr_complete - - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: interrupt time. - * - * This is the target reset completion routine. - * This code is part of the code to initiate the device removal - * handshake protocol with controller firmware. - * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE) - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_tm_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - u16 handle; - Mpi2SCSITaskManagementRequest_t *mpi_request_tm; - Mpi2SCSITaskManagementReply_t *mpi_reply = - mpt3sas_base_get_reply_virt_addr(ioc, reply); - Mpi2SasIoUnitControlRequest_t *mpi_request; - u16 smid_sas_ctrl; - u32 ioc_state; - - if (ioc->remove_host) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host has been removed\n", __func__, ioc->name)); - return 1; - } else if (ioc->pci_error_recovery) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host in pci error recovery\n", __func__, - ioc->name)); - return 1; - } - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - if (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host is not operational\n", __func__, ioc->name)); - return 1; - } - if (unlikely(!mpi_reply)) { - pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return 1; - } - mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid); - handle = le16_to_cpu(mpi_request_tm->DevHandle); - if (handle != le16_to_cpu(mpi_reply->DevHandle)) { - dewtprintk(ioc, pr_err(MPT3SAS_FMT - "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n", - ioc->name, handle, - le16_to_cpu(mpi_reply->DevHandle), smid)); - return 0; - } - - mpt3sas_trigger_master(ioc, MASTER_TRIGGER_TASK_MANAGMENT); - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), " - "loginfo(0x%08x), completed(%d)\n", ioc->name, - handle, smid, le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo), - le32_to_cpu(mpi_reply->TerminationCount))); - - smid_sas_ctrl = mpt3sas_base_get_smid(ioc, ioc->tm_sas_control_cb_idx); - if (!smid_sas_ctrl) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - return 1; - } - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "sc_send:handle(0x%04x), (open), smid(%d), cb(%d)\n", - ioc->name, handle, smid_sas_ctrl, - ioc->tm_sas_control_cb_idx)); - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid_sas_ctrl); - memset(mpi_request, 0, sizeof(Mpi2SasIoUnitControlRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; - mpi_request->Operation = MPI2_SAS_OP_REMOVE_DEVICE; - mpi_request->DevHandle = mpi_request_tm->DevHandle; - mpt3sas_base_put_smid_default(ioc, smid_sas_ctrl); - - return _scsih_check_for_pending_tm(ioc, smid); -} - - -/** - * _scsih_sas_control_complete - completion routine - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: interrupt time. - * - * This is the sas iounit control completion routine. - * This code is part of the code to initiate the device removal - * handshake protocol with controller firmware. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_sas_control_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u8 msix_index, u32 reply) -{ - Mpi2SasIoUnitControlReply_t *mpi_reply = - mpt3sas_base_get_reply_virt_addr(ioc, reply); - - if (likely(mpi_reply)) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "sc_complete:handle(0x%04x), (open) " - "smid(%d), ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply->DevHandle), smid, - le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo))); - } else { - pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - } - return 1; -} - -/** - * _scsih_tm_tr_volume_send - send target reset request for volumes - * @ioc: per adapter object - * @handle: device handle - * Context: interrupt time. - * - * This is designed to send muliple task management request at the same - * time to the fifo. If the fifo is full, we will append the request, - * and process it in a future completion. - */ -static void -_scsih_tm_tr_volume_send(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - Mpi2SCSITaskManagementRequest_t *mpi_request; - u16 smid; - struct _tr_list *delayed_tr; - - if (ioc->shost_recovery || ioc->remove_host || - ioc->pci_error_recovery) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host reset in progress!\n", - __func__, ioc->name)); - return; - } - - smid = mpt3sas_base_get_smid_hpr(ioc, ioc->tm_tr_volume_cb_idx); - if (!smid) { - delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); - if (!delayed_tr) - return; - INIT_LIST_HEAD(&delayed_tr->list); - delayed_tr->handle = handle; - list_add_tail(&delayed_tr->list, &ioc->delayed_tr_volume_list); - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "DELAYED:tr:handle(0x%04x), (open)\n", - ioc->name, handle)); - return; - } - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "tr_send:handle(0x%04x), (open), smid(%d), cb(%d)\n", - ioc->name, handle, smid, - ioc->tm_tr_volume_cb_idx)); - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - memset(mpi_request, 0, sizeof(Mpi2SCSITaskManagementRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SCSI_TASK_MGMT; - mpi_request->DevHandle = cpu_to_le16(handle); - mpi_request->TaskType = MPI2_SCSITASKMGMT_TASKTYPE_TARGET_RESET; - mpt3sas_base_put_smid_hi_priority(ioc, smid, 0); -} - -/** - * _scsih_tm_volume_tr_complete - target reset completion - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: interrupt time. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_tm_volume_tr_complete(struct MPT3SAS_ADAPTER *ioc, u16 smid, - u8 msix_index, u32 reply) -{ - u16 handle; - Mpi2SCSITaskManagementRequest_t *mpi_request_tm; - Mpi2SCSITaskManagementReply_t *mpi_reply = - mpt3sas_base_get_reply_virt_addr(ioc, reply); - - if (ioc->shost_recovery || ioc->remove_host || - ioc->pci_error_recovery) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: host reset in progress!\n", - __func__, ioc->name)); - return 1; - } - if (unlikely(!mpi_reply)) { - pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return 1; - } - - mpi_request_tm = mpt3sas_base_get_msg_frame(ioc, smid); - handle = le16_to_cpu(mpi_request_tm->DevHandle); - if (handle != le16_to_cpu(mpi_reply->DevHandle)) { - dewtprintk(ioc, pr_err(MPT3SAS_FMT - "spurious interrupt: handle(0x%04x:0x%04x), smid(%d)!!!\n", - ioc->name, handle, - le16_to_cpu(mpi_reply->DevHandle), smid)); - return 0; - } - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "tr_complete:handle(0x%04x), (open) smid(%d), ioc_status(0x%04x), " - "loginfo(0x%08x), completed(%d)\n", ioc->name, - handle, smid, le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo), - le32_to_cpu(mpi_reply->TerminationCount))); - - return _scsih_check_for_pending_tm(ioc, smid); -} - - -/** - * _scsih_check_for_pending_tm - check for pending task management - * @ioc: per adapter object - * @smid: system request message index - * - * This will check delayed target reset list, and feed the - * next reqeust. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_check_for_pending_tm(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - struct _tr_list *delayed_tr; - - if (!list_empty(&ioc->delayed_tr_volume_list)) { - delayed_tr = list_entry(ioc->delayed_tr_volume_list.next, - struct _tr_list, list); - mpt3sas_base_free_smid(ioc, smid); - _scsih_tm_tr_volume_send(ioc, delayed_tr->handle); - list_del(&delayed_tr->list); - kfree(delayed_tr); - return 0; - } - - if (!list_empty(&ioc->delayed_tr_list)) { - delayed_tr = list_entry(ioc->delayed_tr_list.next, - struct _tr_list, list); - mpt3sas_base_free_smid(ioc, smid); - _scsih_tm_tr_send(ioc, delayed_tr->handle); - list_del(&delayed_tr->list); - kfree(delayed_tr); - return 0; - } - - return 1; -} - -/** - * _scsih_check_topo_delete_events - sanity check on topo events - * @ioc: per adapter object - * @event_data: the event data payload - * - * This routine added to better handle cable breaker. - * - * This handles the case where driver receives multiple expander - * add and delete events in a single shot. When there is a delete event - * the routine will void any pending add events waiting in the event queue. - * - * Return nothing. - */ -static void -_scsih_check_topo_delete_events(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataSasTopologyChangeList_t *event_data) -{ - struct fw_event_work *fw_event; - Mpi2EventDataSasTopologyChangeList_t *local_event_data; - u16 expander_handle; - struct _sas_node *sas_expander; - unsigned long flags; - int i, reason_code; - u16 handle; - - for (i = 0 ; i < event_data->NumEntries; i++) { - handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); - if (!handle) - continue; - reason_code = event_data->PHY[i].PhyStatus & - MPI2_EVENT_SAS_TOPO_RC_MASK; - if (reason_code == MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING) - _scsih_tm_tr_send(ioc, handle); - } - - expander_handle = le16_to_cpu(event_data->ExpanderDevHandle); - if (expander_handle < ioc->sas_hba.num_phys) { - _scsih_block_io_to_children_attached_directly(ioc, event_data); - return; - } - if (event_data->ExpStatus == - MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING) { - /* put expander attached devices into blocking state */ - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc, - expander_handle); - _scsih_block_io_to_children_attached_to_ex(ioc, sas_expander); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - do { - handle = find_first_bit(ioc->blocking_handles, - ioc->facts.MaxDevHandle); - if (handle < ioc->facts.MaxDevHandle) - _scsih_block_io_device(ioc, handle); - } while (test_and_clear_bit(handle, ioc->blocking_handles)); - } else if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_RESPONDING) - _scsih_block_io_to_children_attached_directly(ioc, event_data); - - if (event_data->ExpStatus != MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING) - return; - - /* mark ignore flag for pending events */ - spin_lock_irqsave(&ioc->fw_event_lock, flags); - list_for_each_entry(fw_event, &ioc->fw_event_list, list) { - if (fw_event->event != MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST || - fw_event->ignore) - continue; - local_event_data = (Mpi2EventDataSasTopologyChangeList_t *) - fw_event->event_data; - if (local_event_data->ExpStatus == - MPI2_EVENT_SAS_TOPO_ES_ADDED || - local_event_data->ExpStatus == - MPI2_EVENT_SAS_TOPO_ES_RESPONDING) { - if (le16_to_cpu(local_event_data->ExpanderDevHandle) == - expander_handle) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "setting ignoring flag\n", ioc->name)); - fw_event->ignore = 1; - } - } - } - spin_unlock_irqrestore(&ioc->fw_event_lock, flags); -} - -/** - * _scsih_set_volume_delete_flag - setting volume delete flag - * @ioc: per adapter object - * @handle: device handle - * - * This returns nothing. - */ -static void -_scsih_set_volume_delete_flag(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _raid_device *raid_device; - struct MPT3SAS_TARGET *sas_target_priv_data; - unsigned long flags; - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle); - if (raid_device && raid_device->starget && - raid_device->starget->hostdata) { - sas_target_priv_data = - raid_device->starget->hostdata; - sas_target_priv_data->deleted = 1; - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "setting delete flag: handle(0x%04x), " - "wwid(0x%016llx)\n", ioc->name, handle, - (unsigned long long) raid_device->wwid)); - } - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); -} - -/** - * _scsih_set_volume_handle_for_tr - set handle for target reset to volume - * @handle: input handle - * @a: handle for volume a - * @b: handle for volume b - * - * IR firmware only supports two raid volumes. The purpose of this - * routine is to set the volume handle in either a or b. When the given - * input handle is non-zero, or when a and b have not been set before. - */ -static void -_scsih_set_volume_handle_for_tr(u16 handle, u16 *a, u16 *b) -{ - if (!handle || handle == *a || handle == *b) - return; - if (!*a) - *a = handle; - else if (!*b) - *b = handle; -} - -/** - * _scsih_check_ir_config_unhide_events - check for UNHIDE events - * @ioc: per adapter object - * @event_data: the event data payload - * Context: interrupt time. - * - * This routine will send target reset to volume, followed by target - * resets to the PDs. This is called when a PD has been removed, or - * volume has been deleted or removed. When the target reset is sent - * to volume, the PD target resets need to be queued to start upon - * completion of the volume target reset. - * - * Return nothing. - */ -static void -_scsih_check_ir_config_unhide_events(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataIrConfigChangeList_t *event_data) -{ - Mpi2EventIrConfigElement_t *element; - int i; - u16 handle, volume_handle, a, b; - struct _tr_list *delayed_tr; - - a = 0; - b = 0; - - if (ioc->is_warpdrive) - return; - - /* Volume Resets for Deleted or Removed */ - element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; - for (i = 0; i < event_data->NumElements; i++, element++) { - if (le32_to_cpu(event_data->Flags) & - MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) - continue; - if (element->ReasonCode == - MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED || - element->ReasonCode == - MPI2_EVENT_IR_CHANGE_RC_REMOVED) { - volume_handle = le16_to_cpu(element->VolDevHandle); - _scsih_set_volume_delete_flag(ioc, volume_handle); - _scsih_set_volume_handle_for_tr(volume_handle, &a, &b); - } - } - - /* Volume Resets for UNHIDE events */ - element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; - for (i = 0; i < event_data->NumElements; i++, element++) { - if (le32_to_cpu(event_data->Flags) & - MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) - continue; - if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_UNHIDE) { - volume_handle = le16_to_cpu(element->VolDevHandle); - _scsih_set_volume_handle_for_tr(volume_handle, &a, &b); - } - } - - if (a) - _scsih_tm_tr_volume_send(ioc, a); - if (b) - _scsih_tm_tr_volume_send(ioc, b); - - /* PD target resets */ - element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; - for (i = 0; i < event_data->NumElements; i++, element++) { - if (element->ReasonCode != MPI2_EVENT_IR_CHANGE_RC_UNHIDE) - continue; - handle = le16_to_cpu(element->PhysDiskDevHandle); - volume_handle = le16_to_cpu(element->VolDevHandle); - clear_bit(handle, ioc->pd_handles); - if (!volume_handle) - _scsih_tm_tr_send(ioc, handle); - else if (volume_handle == a || volume_handle == b) { - delayed_tr = kzalloc(sizeof(*delayed_tr), GFP_ATOMIC); - BUG_ON(!delayed_tr); - INIT_LIST_HEAD(&delayed_tr->list); - delayed_tr->handle = handle; - list_add_tail(&delayed_tr->list, &ioc->delayed_tr_list); - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "DELAYED:tr:handle(0x%04x), (open)\n", ioc->name, - handle)); - } else - _scsih_tm_tr_send(ioc, handle); - } -} - - -/** - * _scsih_check_volume_delete_events - set delete flag for volumes - * @ioc: per adapter object - * @event_data: the event data payload - * Context: interrupt time. - * - * This will handle the case when the cable connected to entire volume is - * pulled. We will take care of setting the deleted flag so normal IO will - * not be sent. - * - * Return nothing. - */ -static void -_scsih_check_volume_delete_events(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataIrVolume_t *event_data) -{ - u32 state; - - if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) - return; - state = le32_to_cpu(event_data->NewValue); - if (state == MPI2_RAID_VOL_STATE_MISSING || state == - MPI2_RAID_VOL_STATE_FAILED) - _scsih_set_volume_delete_flag(ioc, - le16_to_cpu(event_data->VolDevHandle)); -} - -/** - * _scsih_temp_threshold_events - display temperature threshold exceeded events - * @ioc: per adapter object - * @event_data: the temp threshold event data - * Context: interrupt time. - * - * Return nothing. - */ -static void -_scsih_temp_threshold_events(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataTemperature_t *event_data) -{ - if (ioc->temp_sensors_count >= event_data->SensorNum) { - pr_err(MPT3SAS_FMT "Temperature Threshold flags %s%s%s%s" - " exceeded for Sensor: %d !!!\n", ioc->name, - ((le16_to_cpu(event_data->Status) & 0x1) == 1) ? "0 " : " ", - ((le16_to_cpu(event_data->Status) & 0x2) == 2) ? "1 " : " ", - ((le16_to_cpu(event_data->Status) & 0x4) == 4) ? "2 " : " ", - ((le16_to_cpu(event_data->Status) & 0x8) == 8) ? "3 " : " ", - event_data->SensorNum); - pr_err(MPT3SAS_FMT "Current Temp In Celsius: %d\n", - ioc->name, event_data->CurrentTemperature); - } -} - -static int _scsih_set_satl_pending(struct scsi_cmnd *scmd, bool pending) -{ - struct MPT3SAS_DEVICE *priv = scmd->device->hostdata; - - if (scmd->cmnd[0] != ATA_12 && scmd->cmnd[0] != ATA_16) - return 0; - - if (pending) - return test_and_set_bit(0, &priv->ata_command_pending); - - clear_bit(0, &priv->ata_command_pending); - return 0; -} - -/** - * _scsih_flush_running_cmds - completing outstanding commands. - * @ioc: per adapter object - * - * The flushing out of all pending scmd commands following host reset, - * where all IO is dropped to the floor. - * - * Return nothing. - */ -static void -_scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc) -{ - struct scsi_cmnd *scmd; - u16 smid; - u16 count = 0; - - for (smid = 1; smid <= ioc->scsiio_depth; smid++) { - scmd = _scsih_scsi_lookup_get_clear(ioc, smid); - if (!scmd) - continue; - count++; - _scsih_set_satl_pending(scmd, false); - mpt3sas_base_free_smid(ioc, smid); - scsi_dma_unmap(scmd); - if (ioc->pci_error_recovery) - scmd->result = DID_NO_CONNECT << 16; - else - scmd->result = DID_RESET << 16; - scmd->scsi_done(scmd); - } - dtmprintk(ioc, pr_info(MPT3SAS_FMT "completing %d cmds\n", - ioc->name, count)); -} - -/** - * _scsih_setup_eedp - setup MPI request for EEDP transfer - * @ioc: per adapter object - * @scmd: pointer to scsi command object - * @mpi_request: pointer to the SCSI_IO reqest message frame - * - * Supporting protection 1 and 3. - * - * Returns nothing - */ -static void -_scsih_setup_eedp(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, - Mpi2SCSIIORequest_t *mpi_request) -{ - u16 eedp_flags; - unsigned char prot_op = scsi_get_prot_op(scmd); - unsigned char prot_type = scsi_get_prot_type(scmd); - Mpi25SCSIIORequest_t *mpi_request_3v = - (Mpi25SCSIIORequest_t *)mpi_request; - - if (prot_type == SCSI_PROT_DIF_TYPE0 || prot_op == SCSI_PROT_NORMAL) - return; - - if (prot_op == SCSI_PROT_READ_STRIP) - eedp_flags = MPI2_SCSIIO_EEDPFLAGS_CHECK_REMOVE_OP; - else if (prot_op == SCSI_PROT_WRITE_INSERT) - eedp_flags = MPI2_SCSIIO_EEDPFLAGS_INSERT_OP; - else - return; - - switch (prot_type) { - case SCSI_PROT_DIF_TYPE1: - case SCSI_PROT_DIF_TYPE2: - - /* - * enable ref/guard checking - * auto increment ref tag - */ - eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_INC_PRI_REFTAG | - MPI2_SCSIIO_EEDPFLAGS_CHECK_REFTAG | - MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; - mpi_request->CDB.EEDP32.PrimaryReferenceTag = - cpu_to_be32(scsi_get_lba(scmd)); - break; - - case SCSI_PROT_DIF_TYPE3: - - /* - * enable guard checking - */ - eedp_flags |= MPI2_SCSIIO_EEDPFLAGS_CHECK_GUARD; - - break; - } - - mpi_request_3v->EEDPBlockSize = - cpu_to_le16(scmd->device->sector_size); - mpi_request->EEDPFlags = cpu_to_le16(eedp_flags); -} - -/** - * _scsih_eedp_error_handling - return sense code for EEDP errors - * @scmd: pointer to scsi command object - * @ioc_status: ioc status - * - * Returns nothing - */ -static void -_scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status) -{ - u8 ascq; - - switch (ioc_status) { - case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: - ascq = 0x01; - break; - case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: - ascq = 0x02; - break; - case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: - ascq = 0x03; - break; - default: - ascq = 0x00; - break; - } - scsi_build_sense_buffer(0, scmd->sense_buffer, ILLEGAL_REQUEST, 0x10, - ascq); - scmd->result = DRIVER_SENSE << 24 | (DID_ABORT << 16) | - SAM_STAT_CHECK_CONDITION; -} - -/** - * scsih_qcmd - main scsi request entry point - * @scmd: pointer to scsi command object - * @done: function pointer to be invoked on completion - * - * The callback index is set inside `ioc->scsi_io_cb_idx`. - * - * Returns 0 on success. If there's a failure, return either: - * SCSI_MLQUEUE_DEVICE_BUSY if the device queue is full, or - * SCSI_MLQUEUE_HOST_BUSY if the entire host queue is full - */ -int -scsih_qcmd(struct Scsi_Host *shost, struct scsi_cmnd *scmd) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct MPT3SAS_TARGET *sas_target_priv_data; - struct _raid_device *raid_device; - Mpi2SCSIIORequest_t *mpi_request; - u32 mpi_control; - u16 smid; - u16 handle; - - if (ioc->logging_level & MPT_DEBUG_SCSI) - scsi_print_command(scmd); - - sas_device_priv_data = scmd->device->hostdata; - if (!sas_device_priv_data || !sas_device_priv_data->sas_target) { - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - return 0; - } - - if (ioc->pci_error_recovery || ioc->remove_host) { - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - return 0; - } - - sas_target_priv_data = sas_device_priv_data->sas_target; - - /* invalid device handle */ - handle = sas_target_priv_data->handle; - if (handle == MPT3SAS_INVALID_DEVICE_HANDLE) { - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - return 0; - } - - - /* host recovery or link resets sent via IOCTLs */ - if (ioc->shost_recovery || ioc->ioc_link_reset_in_progress) - return SCSI_MLQUEUE_HOST_BUSY; - - /* device has been deleted */ - else if (sas_target_priv_data->deleted) { - scmd->result = DID_NO_CONNECT << 16; - scmd->scsi_done(scmd); - return 0; - /* device busy with task managment */ - } else if (sas_target_priv_data->tm_busy || - sas_device_priv_data->block) - return SCSI_MLQUEUE_DEVICE_BUSY; - - /* - * Bug work around for firmware SATL handling. The loop - * is based on atomic operations and ensures consistency - * since we're lockless at this point - */ - do { - if (test_bit(0, &sas_device_priv_data->ata_command_pending)) { - scmd->result = SAM_STAT_BUSY; - scmd->scsi_done(scmd); - return 0; - } - } while (_scsih_set_satl_pending(scmd, true)); - - if (scmd->sc_data_direction == DMA_FROM_DEVICE) - mpi_control = MPI2_SCSIIO_CONTROL_READ; - else if (scmd->sc_data_direction == DMA_TO_DEVICE) - mpi_control = MPI2_SCSIIO_CONTROL_WRITE; - else - mpi_control = MPI2_SCSIIO_CONTROL_NODATATRANSFER; - - /* set tags */ - mpi_control |= MPI2_SCSIIO_CONTROL_SIMPLEQ; - - /* Make sure Device is not raid volume. - * We do not expose raid functionality to upper layer for warpdrive. - */ - if (!ioc->is_warpdrive && !scsih_is_raid(&scmd->device->sdev_gendev) - && sas_is_tlr_enabled(scmd->device) && scmd->cmd_len != 32) - mpi_control |= MPI2_SCSIIO_CONTROL_TLR_ON; - - smid = mpt3sas_base_get_smid_scsiio(ioc, ioc->scsi_io_cb_idx, scmd); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - _scsih_set_satl_pending(scmd, false); - goto out; - } - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - memset(mpi_request, 0, sizeof(Mpi2SCSIIORequest_t)); - _scsih_setup_eedp(ioc, scmd, mpi_request); - - if (scmd->cmd_len == 32) - mpi_control |= 4 << MPI2_SCSIIO_CONTROL_ADDCDBLEN_SHIFT; - mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; - if (sas_device_priv_data->sas_target->flags & - MPT_TARGET_FLAGS_RAID_COMPONENT) - mpi_request->Function = MPI2_FUNCTION_RAID_SCSI_IO_PASSTHROUGH; - else - mpi_request->Function = MPI2_FUNCTION_SCSI_IO_REQUEST; - mpi_request->DevHandle = cpu_to_le16(handle); - mpi_request->DataLength = cpu_to_le32(scsi_bufflen(scmd)); - mpi_request->Control = cpu_to_le32(mpi_control); - mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len); - mpi_request->MsgFlags = MPI2_SCSIIO_MSGFLAGS_SYSTEM_SENSE_ADDR; - mpi_request->SenseBufferLength = SCSI_SENSE_BUFFERSIZE; - mpi_request->SenseBufferLowAddress = - mpt3sas_base_get_sense_buffer_dma(ioc, smid); - mpi_request->SGLOffset0 = offsetof(Mpi2SCSIIORequest_t, SGL) / 4; - int_to_scsilun(sas_device_priv_data->lun, (struct scsi_lun *) - mpi_request->LUN); - memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len); - - if (mpi_request->DataLength) { - if (ioc->build_sg_scmd(ioc, scmd, smid)) { - mpt3sas_base_free_smid(ioc, smid); - _scsih_set_satl_pending(scmd, false); - goto out; - } - } else - ioc->build_zero_len_sge(ioc, &mpi_request->SGL); - - raid_device = sas_target_priv_data->raid_device; - if (raid_device && raid_device->direct_io_enabled) - mpt3sas_setup_direct_io(ioc, scmd, raid_device, mpi_request, - smid); - - if (likely(mpi_request->Function == MPI2_FUNCTION_SCSI_IO_REQUEST)) { - if (sas_target_priv_data->flags & MPT_TARGET_FASTPATH_IO) { - mpi_request->IoFlags = cpu_to_le16(scmd->cmd_len | - MPI25_SCSIIO_IOFLAGS_FAST_PATH); - mpt3sas_base_put_smid_fast_path(ioc, smid, handle); - } else - mpt3sas_base_put_smid_scsi_io(ioc, smid, - le16_to_cpu(mpi_request->DevHandle)); - } else - mpt3sas_base_put_smid_default(ioc, smid); - return 0; - - out: - return SCSI_MLQUEUE_HOST_BUSY; -} - -/** - * _scsih_normalize_sense - normalize descriptor and fixed format sense data - * @sense_buffer: sense data returned by target - * @data: normalized skey/asc/ascq - * - * Return nothing. - */ -static void -_scsih_normalize_sense(char *sense_buffer, struct sense_info *data) -{ - if ((sense_buffer[0] & 0x7F) >= 0x72) { - /* descriptor format */ - data->skey = sense_buffer[1] & 0x0F; - data->asc = sense_buffer[2]; - data->ascq = sense_buffer[3]; - } else { - /* fixed format */ - data->skey = sense_buffer[2] & 0x0F; - data->asc = sense_buffer[12]; - data->ascq = sense_buffer[13]; - } -} - -/** - * _scsih_scsi_ioc_info - translated non-succesfull SCSI_IO request - * @ioc: per adapter object - * @scmd: pointer to scsi command object - * @mpi_reply: reply mf payload returned from firmware - * - * scsi_status - SCSI Status code returned from target device - * scsi_state - state info associated with SCSI_IO determined by ioc - * ioc_status - ioc supplied status info - * - * Return nothing. - */ -static void -_scsih_scsi_ioc_info(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, - Mpi2SCSIIOReply_t *mpi_reply, u16 smid) -{ - u32 response_info; - u8 *response_bytes; - u16 ioc_status = le16_to_cpu(mpi_reply->IOCStatus) & - MPI2_IOCSTATUS_MASK; - u8 scsi_state = mpi_reply->SCSIState; - u8 scsi_status = mpi_reply->SCSIStatus; - char *desc_ioc_state = NULL; - char *desc_scsi_status = NULL; - char *desc_scsi_state = ioc->tmp_string; - u32 log_info = le32_to_cpu(mpi_reply->IOCLogInfo); - struct _sas_device *sas_device = NULL; - struct scsi_target *starget = scmd->device->sdev_target; - struct MPT3SAS_TARGET *priv_target = starget->hostdata; - char *device_str = NULL; - - if (!priv_target) - return; - if (ioc->hide_ir_msg) - device_str = "WarpDrive"; - else - device_str = "volume"; - - if (log_info == 0x31170000) - return; - - switch (ioc_status) { - case MPI2_IOCSTATUS_SUCCESS: - desc_ioc_state = "success"; - break; - case MPI2_IOCSTATUS_INVALID_FUNCTION: - desc_ioc_state = "invalid function"; - break; - case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: - desc_ioc_state = "scsi recovered error"; - break; - case MPI2_IOCSTATUS_SCSI_INVALID_DEVHANDLE: - desc_ioc_state = "scsi invalid dev handle"; - break; - case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: - desc_ioc_state = "scsi device not there"; - break; - case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: - desc_ioc_state = "scsi data overrun"; - break; - case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: - desc_ioc_state = "scsi data underrun"; - break; - case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: - desc_ioc_state = "scsi io data error"; - break; - case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: - desc_ioc_state = "scsi protocol error"; - break; - case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: - desc_ioc_state = "scsi task terminated"; - break; - case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: - desc_ioc_state = "scsi residual mismatch"; - break; - case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: - desc_ioc_state = "scsi task mgmt failed"; - break; - case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: - desc_ioc_state = "scsi ioc terminated"; - break; - case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: - desc_ioc_state = "scsi ext terminated"; - break; - case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: - desc_ioc_state = "eedp guard error"; - break; - case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: - desc_ioc_state = "eedp ref tag error"; - break; - case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: - desc_ioc_state = "eedp app tag error"; - break; - default: - desc_ioc_state = "unknown"; - break; - } - - switch (scsi_status) { - case MPI2_SCSI_STATUS_GOOD: - desc_scsi_status = "good"; - break; - case MPI2_SCSI_STATUS_CHECK_CONDITION: - desc_scsi_status = "check condition"; - break; - case MPI2_SCSI_STATUS_CONDITION_MET: - desc_scsi_status = "condition met"; - break; - case MPI2_SCSI_STATUS_BUSY: - desc_scsi_status = "busy"; - break; - case MPI2_SCSI_STATUS_INTERMEDIATE: - desc_scsi_status = "intermediate"; - break; - case MPI2_SCSI_STATUS_INTERMEDIATE_CONDMET: - desc_scsi_status = "intermediate condmet"; - break; - case MPI2_SCSI_STATUS_RESERVATION_CONFLICT: - desc_scsi_status = "reservation conflict"; - break; - case MPI2_SCSI_STATUS_COMMAND_TERMINATED: - desc_scsi_status = "command terminated"; - break; - case MPI2_SCSI_STATUS_TASK_SET_FULL: - desc_scsi_status = "task set full"; - break; - case MPI2_SCSI_STATUS_ACA_ACTIVE: - desc_scsi_status = "aca active"; - break; - case MPI2_SCSI_STATUS_TASK_ABORTED: - desc_scsi_status = "task aborted"; - break; - default: - desc_scsi_status = "unknown"; - break; - } - - desc_scsi_state[0] = '\0'; - if (!scsi_state) - desc_scsi_state = " "; - if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) - strcat(desc_scsi_state, "response info "); - if (scsi_state & MPI2_SCSI_STATE_TERMINATED) - strcat(desc_scsi_state, "state terminated "); - if (scsi_state & MPI2_SCSI_STATE_NO_SCSI_STATUS) - strcat(desc_scsi_state, "no status "); - if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_FAILED) - strcat(desc_scsi_state, "autosense failed "); - if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) - strcat(desc_scsi_state, "autosense valid "); - - scsi_print_command(scmd); - - if (priv_target->flags & MPT_TARGET_FLAGS_VOLUME) { - pr_warn(MPT3SAS_FMT "\t%s wwid(0x%016llx)\n", ioc->name, - device_str, (unsigned long long)priv_target->sas_address); - } else { - sas_device = mpt3sas_get_sdev_from_target(ioc, priv_target); - if (sas_device) { - pr_warn(MPT3SAS_FMT - "\tsas_address(0x%016llx), phy(%d)\n", - ioc->name, (unsigned long long) - sas_device->sas_address, sas_device->phy); - if (sas_device->enclosure_handle != 0) - pr_warn(MPT3SAS_FMT - "\tenclosure_logical_id(0x%016llx)," - "slot(%d)\n", ioc->name, - (unsigned long long) - sas_device->enclosure_logical_id, - sas_device->slot); - if (sas_device->connector_name[0]) - pr_warn(MPT3SAS_FMT - "\tenclosure level(0x%04x)," - " connector name( %s)\n", ioc->name, - sas_device->enclosure_level, - sas_device->connector_name); - - sas_device_put(sas_device); - } - } - - pr_warn(MPT3SAS_FMT - "\thandle(0x%04x), ioc_status(%s)(0x%04x), smid(%d)\n", - ioc->name, le16_to_cpu(mpi_reply->DevHandle), - desc_ioc_state, ioc_status, smid); - pr_warn(MPT3SAS_FMT - "\trequest_len(%d), underflow(%d), resid(%d)\n", - ioc->name, scsi_bufflen(scmd), scmd->underflow, - scsi_get_resid(scmd)); - pr_warn(MPT3SAS_FMT - "\ttag(%d), transfer_count(%d), sc->result(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply->TaskTag), - le32_to_cpu(mpi_reply->TransferCount), scmd->result); - pr_warn(MPT3SAS_FMT - "\tscsi_status(%s)(0x%02x), scsi_state(%s)(0x%02x)\n", - ioc->name, desc_scsi_status, - scsi_status, desc_scsi_state, scsi_state); - - if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { - struct sense_info data; - _scsih_normalize_sense(scmd->sense_buffer, &data); - pr_warn(MPT3SAS_FMT - "\t[sense_key,asc,ascq]: [0x%02x,0x%02x,0x%02x], count(%d)\n", - ioc->name, data.skey, - data.asc, data.ascq, le32_to_cpu(mpi_reply->SenseCount)); - } - - if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) { - response_info = le32_to_cpu(mpi_reply->ResponseInfo); - response_bytes = (u8 *)&response_info; - _scsih_response_code(ioc, response_bytes[0]); - } -} - -/** - * _scsih_turn_on_pfa_led - illuminate PFA LED - * @ioc: per adapter object - * @handle: device handle - * Context: process - * - * Return nothing. - */ -static void -_scsih_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - Mpi2SepReply_t mpi_reply; - Mpi2SepRequest_t mpi_request; - struct _sas_device *sas_device; - - sas_device = mpt3sas_get_sdev_by_handle(ioc, handle); - if (!sas_device) - return; - - memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t)); - mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; - mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS; - mpi_request.SlotStatus = - cpu_to_le32(MPI2_SEP_REQ_SLOTSTATUS_PREDICTED_FAULT); - mpi_request.DevHandle = cpu_to_le16(handle); - mpi_request.Flags = MPI2_SEP_REQ_FLAGS_DEVHANDLE_ADDRESS; - if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply, - &mpi_request)) != 0) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__); - goto out; - } - sas_device->pfa_led_on = 1; - - if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply.IOCStatus), - le32_to_cpu(mpi_reply.IOCLogInfo))); - goto out; - } -out: - sas_device_put(sas_device); -} - -/** - * _scsih_turn_off_pfa_led - turn off Fault LED - * @ioc: per adapter object - * @sas_device: sas device whose PFA LED has to turned off - * Context: process - * - * Return nothing. - */ -static void -_scsih_turn_off_pfa_led(struct MPT3SAS_ADAPTER *ioc, - struct _sas_device *sas_device) -{ - Mpi2SepReply_t mpi_reply; - Mpi2SepRequest_t mpi_request; - - memset(&mpi_request, 0, sizeof(Mpi2SepRequest_t)); - mpi_request.Function = MPI2_FUNCTION_SCSI_ENCLOSURE_PROCESSOR; - mpi_request.Action = MPI2_SEP_REQ_ACTION_WRITE_STATUS; - mpi_request.SlotStatus = 0; - mpi_request.Slot = cpu_to_le16(sas_device->slot); - mpi_request.DevHandle = 0; - mpi_request.EnclosureHandle = cpu_to_le16(sas_device->enclosure_handle); - mpi_request.Flags = MPI2_SEP_REQ_FLAGS_ENCLOSURE_SLOT_ADDRESS; - if ((mpt3sas_base_scsi_enclosure_processor(ioc, &mpi_reply, - &mpi_request)) != 0) { - printk(MPT3SAS_FMT "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__); - return; - } - - if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) { - dewtprintk(ioc, printk(MPT3SAS_FMT - "enclosure_processor: ioc_status (0x%04x), loginfo(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply.IOCStatus), - le32_to_cpu(mpi_reply.IOCLogInfo))); - return; - } -} - -/** - * _scsih_send_event_to_turn_on_pfa_led - fire delayed event - * @ioc: per adapter object - * @handle: device handle - * Context: interrupt. - * - * Return nothing. - */ -static void -_scsih_send_event_to_turn_on_pfa_led(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct fw_event_work *fw_event; - - fw_event = alloc_fw_event_work(0); - if (!fw_event) - return; - fw_event->event = MPT3SAS_TURN_ON_PFA_LED; - fw_event->device_handle = handle; - fw_event->ioc = ioc; - _scsih_fw_event_add(ioc, fw_event); - fw_event_work_put(fw_event); -} - -/** - * _scsih_smart_predicted_fault - process smart errors - * @ioc: per adapter object - * @handle: device handle - * Context: interrupt. - * - * Return nothing. - */ -static void -_scsih_smart_predicted_fault(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct scsi_target *starget; - struct MPT3SAS_TARGET *sas_target_priv_data; - Mpi2EventNotificationReply_t *event_reply; - Mpi2EventDataSasDeviceStatusChange_t *event_data; - struct _sas_device *sas_device; - ssize_t sz; - unsigned long flags; - - /* only handle non-raid devices */ - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); - if (!sas_device) - goto out_unlock; - - starget = sas_device->starget; - sas_target_priv_data = starget->hostdata; - - if ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_RAID_COMPONENT) || - ((sas_target_priv_data->flags & MPT_TARGET_FLAGS_VOLUME))) - goto out_unlock; - - if (sas_device->enclosure_handle != 0) - starget_printk(KERN_INFO, starget, "predicted fault, " - "enclosure logical id(0x%016llx), slot(%d)\n", - (unsigned long long)sas_device->enclosure_logical_id, - sas_device->slot); - if (sas_device->connector_name[0] != '\0') - starget_printk(KERN_WARNING, starget, "predicted fault, " - "enclosure level(0x%04x), connector name( %s)\n", - sas_device->enclosure_level, - sas_device->connector_name); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) - _scsih_send_event_to_turn_on_pfa_led(ioc, handle); - - /* insert into event log */ - sz = offsetof(Mpi2EventNotificationReply_t, EventData) + - sizeof(Mpi2EventDataSasDeviceStatusChange_t); - event_reply = kzalloc(sz, GFP_KERNEL); - if (!event_reply) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - - event_reply->Function = MPI2_FUNCTION_EVENT_NOTIFICATION; - event_reply->Event = - cpu_to_le16(MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE); - event_reply->MsgLength = sz/4; - event_reply->EventDataLength = - cpu_to_le16(sizeof(Mpi2EventDataSasDeviceStatusChange_t)/4); - event_data = (Mpi2EventDataSasDeviceStatusChange_t *) - event_reply->EventData; - event_data->ReasonCode = MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA; - event_data->ASC = 0x5D; - event_data->DevHandle = cpu_to_le16(handle); - event_data->SASAddress = cpu_to_le64(sas_target_priv_data->sas_address); - mpt3sas_ctl_add_to_event_log(ioc, event_reply); - kfree(event_reply); -out: - if (sas_device) - sas_device_put(sas_device); - return; - -out_unlock: - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - goto out; -} - -/** - * _scsih_io_done - scsi request callback - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Callback handler when using _scsih_qcmd. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_io_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) -{ - Mpi2SCSIIORequest_t *mpi_request; - Mpi2SCSIIOReply_t *mpi_reply; - struct scsi_cmnd *scmd; - u16 ioc_status; - u32 xfer_cnt; - u8 scsi_state; - u8 scsi_status; - u32 log_info; - struct MPT3SAS_DEVICE *sas_device_priv_data; - u32 response_code = 0; - unsigned long flags; - unsigned int sector_sz; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - scmd = _scsih_scsi_lookup_get_clear(ioc, smid); - if (scmd == NULL) - return 1; - - _scsih_set_satl_pending(scmd, false); - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - - if (mpi_reply == NULL) { - scmd->result = DID_OK << 16; - goto out; - } - - sas_device_priv_data = scmd->device->hostdata; - if (!sas_device_priv_data || !sas_device_priv_data->sas_target || - sas_device_priv_data->sas_target->deleted) { - scmd->result = DID_NO_CONNECT << 16; - goto out; - } - ioc_status = le16_to_cpu(mpi_reply->IOCStatus); - - /* - * WARPDRIVE: If direct_io is set then it is directIO, - * the failed direct I/O should be redirected to volume - */ - if (mpt3sas_scsi_direct_io_get(ioc, smid) && - ((ioc_status & MPI2_IOCSTATUS_MASK) - != MPI2_IOCSTATUS_SCSI_TASK_TERMINATED)) { - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - ioc->scsi_lookup[smid - 1].scmd = scmd; - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - mpt3sas_scsi_direct_io_set(ioc, smid, 0); - memcpy(mpi_request->CDB.CDB32, scmd->cmnd, scmd->cmd_len); - mpi_request->DevHandle = - cpu_to_le16(sas_device_priv_data->sas_target->handle); - mpt3sas_base_put_smid_scsi_io(ioc, smid, - sas_device_priv_data->sas_target->handle); - return 0; - } - /* turning off TLR */ - scsi_state = mpi_reply->SCSIState; - if (scsi_state & MPI2_SCSI_STATE_RESPONSE_INFO_VALID) - response_code = - le32_to_cpu(mpi_reply->ResponseInfo) & 0xFF; - if (!sas_device_priv_data->tlr_snoop_check) { - sas_device_priv_data->tlr_snoop_check++; - if (!ioc->is_warpdrive && - !scsih_is_raid(&scmd->device->sdev_gendev) && - sas_is_tlr_enabled(scmd->device) && - response_code == MPI2_SCSITASKMGMT_RSP_INVALID_FRAME) { - sas_disable_tlr(scmd->device); - sdev_printk(KERN_INFO, scmd->device, "TLR disabled\n"); - } - } - - xfer_cnt = le32_to_cpu(mpi_reply->TransferCount); - - /* In case of bogus fw or device, we could end up having - * unaligned partial completion. We can force alignment here, - * then scsi-ml does not need to handle this misbehavior. - */ - sector_sz = scmd->device->sector_size; - if (unlikely(scmd->request->cmd_type == REQ_TYPE_FS && sector_sz && - xfer_cnt % sector_sz)) { - sdev_printk(KERN_INFO, scmd->device, - "unaligned partial completion avoided (xfer_cnt=%u, sector_sz=%u)\n", - xfer_cnt, sector_sz); - xfer_cnt = round_down(xfer_cnt, sector_sz); - } - - scsi_set_resid(scmd, scsi_bufflen(scmd) - xfer_cnt); - if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) - log_info = le32_to_cpu(mpi_reply->IOCLogInfo); - else - log_info = 0; - ioc_status &= MPI2_IOCSTATUS_MASK; - scsi_status = mpi_reply->SCSIStatus; - - if (ioc_status == MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN && xfer_cnt == 0 && - (scsi_status == MPI2_SCSI_STATUS_BUSY || - scsi_status == MPI2_SCSI_STATUS_RESERVATION_CONFLICT || - scsi_status == MPI2_SCSI_STATUS_TASK_SET_FULL)) { - ioc_status = MPI2_IOCSTATUS_SUCCESS; - } - - if (scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID) { - struct sense_info data; - const void *sense_data = mpt3sas_base_get_sense_buffer(ioc, - smid); - u32 sz = min_t(u32, SCSI_SENSE_BUFFERSIZE, - le32_to_cpu(mpi_reply->SenseCount)); - memcpy(scmd->sense_buffer, sense_data, sz); - _scsih_normalize_sense(scmd->sense_buffer, &data); - /* failure prediction threshold exceeded */ - if (data.asc == 0x5D) - _scsih_smart_predicted_fault(ioc, - le16_to_cpu(mpi_reply->DevHandle)); - mpt3sas_trigger_scsi(ioc, data.skey, data.asc, data.ascq); - - if ((ioc->logging_level & MPT_DEBUG_REPLY) && - ((scmd->sense_buffer[2] == UNIT_ATTENTION) || - (scmd->sense_buffer[2] == MEDIUM_ERROR) || - (scmd->sense_buffer[2] == HARDWARE_ERROR))) - _scsih_scsi_ioc_info(ioc, scmd, mpi_reply, smid); - } - switch (ioc_status) { - case MPI2_IOCSTATUS_BUSY: - case MPI2_IOCSTATUS_INSUFFICIENT_RESOURCES: - scmd->result = SAM_STAT_BUSY; - break; - - case MPI2_IOCSTATUS_SCSI_DEVICE_NOT_THERE: - scmd->result = DID_NO_CONNECT << 16; - break; - - case MPI2_IOCSTATUS_SCSI_IOC_TERMINATED: - if (sas_device_priv_data->block) { - scmd->result = DID_TRANSPORT_DISRUPTED << 16; - goto out; - } - if (log_info == 0x31110630) { - if (scmd->retries > 2) { - scmd->result = DID_NO_CONNECT << 16; - scsi_device_set_state(scmd->device, - SDEV_OFFLINE); - } else { - scmd->result = DID_SOFT_ERROR << 16; - scmd->device->expecting_cc_ua = 1; - } - break; - } else if (log_info == VIRTUAL_IO_FAILED_RETRY) { - scmd->result = DID_RESET << 16; - break; - } else if ((scmd->device->channel == RAID_CHANNEL) && - (scsi_state == (MPI2_SCSI_STATE_TERMINATED | - MPI2_SCSI_STATE_NO_SCSI_STATUS))) { - scmd->result = DID_RESET << 16; - break; - } - scmd->result = DID_SOFT_ERROR << 16; - break; - case MPI2_IOCSTATUS_SCSI_TASK_TERMINATED: - case MPI2_IOCSTATUS_SCSI_EXT_TERMINATED: - scmd->result = DID_RESET << 16; - break; - - case MPI2_IOCSTATUS_SCSI_RESIDUAL_MISMATCH: - if ((xfer_cnt == 0) || (scmd->underflow > xfer_cnt)) - scmd->result = DID_SOFT_ERROR << 16; - else - scmd->result = (DID_OK << 16) | scsi_status; - break; - - case MPI2_IOCSTATUS_SCSI_DATA_UNDERRUN: - scmd->result = (DID_OK << 16) | scsi_status; - - if ((scsi_state & MPI2_SCSI_STATE_AUTOSENSE_VALID)) - break; - - if (xfer_cnt < scmd->underflow) { - if (scsi_status == SAM_STAT_BUSY) - scmd->result = SAM_STAT_BUSY; - else - scmd->result = DID_SOFT_ERROR << 16; - } else if (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED | - MPI2_SCSI_STATE_NO_SCSI_STATUS)) - scmd->result = DID_SOFT_ERROR << 16; - else if (scsi_state & MPI2_SCSI_STATE_TERMINATED) - scmd->result = DID_RESET << 16; - else if (!xfer_cnt && scmd->cmnd[0] == REPORT_LUNS) { - mpi_reply->SCSIState = MPI2_SCSI_STATE_AUTOSENSE_VALID; - mpi_reply->SCSIStatus = SAM_STAT_CHECK_CONDITION; - scmd->result = (DRIVER_SENSE << 24) | - SAM_STAT_CHECK_CONDITION; - scmd->sense_buffer[0] = 0x70; - scmd->sense_buffer[2] = ILLEGAL_REQUEST; - scmd->sense_buffer[12] = 0x20; - scmd->sense_buffer[13] = 0; - } - break; - - case MPI2_IOCSTATUS_SCSI_DATA_OVERRUN: - scsi_set_resid(scmd, 0); - case MPI2_IOCSTATUS_SCSI_RECOVERED_ERROR: - case MPI2_IOCSTATUS_SUCCESS: - scmd->result = (DID_OK << 16) | scsi_status; - if (response_code == - MPI2_SCSITASKMGMT_RSP_INVALID_FRAME || - (scsi_state & (MPI2_SCSI_STATE_AUTOSENSE_FAILED | - MPI2_SCSI_STATE_NO_SCSI_STATUS))) - scmd->result = DID_SOFT_ERROR << 16; - else if (scsi_state & MPI2_SCSI_STATE_TERMINATED) - scmd->result = DID_RESET << 16; - break; - - case MPI2_IOCSTATUS_EEDP_GUARD_ERROR: - case MPI2_IOCSTATUS_EEDP_REF_TAG_ERROR: - case MPI2_IOCSTATUS_EEDP_APP_TAG_ERROR: - _scsih_eedp_error_handling(scmd, ioc_status); - break; - - case MPI2_IOCSTATUS_SCSI_PROTOCOL_ERROR: - case MPI2_IOCSTATUS_INVALID_FUNCTION: - case MPI2_IOCSTATUS_INVALID_SGL: - case MPI2_IOCSTATUS_INTERNAL_ERROR: - case MPI2_IOCSTATUS_INVALID_FIELD: - case MPI2_IOCSTATUS_INVALID_STATE: - case MPI2_IOCSTATUS_SCSI_IO_DATA_ERROR: - case MPI2_IOCSTATUS_SCSI_TASK_MGMT_FAILED: - default: - scmd->result = DID_SOFT_ERROR << 16; - break; - - } - - if (scmd->result && (ioc->logging_level & MPT_DEBUG_REPLY)) - _scsih_scsi_ioc_info(ioc , scmd, mpi_reply, smid); - - out: - - scsi_dma_unmap(scmd); - - scmd->scsi_done(scmd); - return 1; -} - -/** - * _scsih_sas_host_refresh - refreshing sas host object contents - * @ioc: per adapter object - * Context: user - * - * During port enable, fw will send topology events for every device. Its - * possible that the handles may change from the previous setting, so this - * code keeping handles updating if changed. - * - * Return nothing. - */ -static void -_scsih_sas_host_refresh(struct MPT3SAS_ADAPTER *ioc) -{ - u16 sz; - u16 ioc_status; - int i; - Mpi2ConfigReply_t mpi_reply; - Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; - u16 attached_handle; - u8 link_rate; - - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "updating handles for sas_host(0x%016llx)\n", - ioc->name, (unsigned long long)ioc->sas_hba.sas_address)); - - sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys - * sizeof(Mpi2SasIOUnit0PhyData_t)); - sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg0) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, - sas_iounit_pg0, sz)) != 0) - goto out; - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - goto out; - for (i = 0; i < ioc->sas_hba.num_phys ; i++) { - link_rate = sas_iounit_pg0->PhyData[i].NegotiatedLinkRate >> 4; - if (i == 0) - ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> - PhyData[0].ControllerDevHandle); - ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; - attached_handle = le16_to_cpu(sas_iounit_pg0->PhyData[i]. - AttachedDevHandle); - if (attached_handle && link_rate < MPI2_SAS_NEG_LINK_RATE_1_5) - link_rate = MPI2_SAS_NEG_LINK_RATE_1_5; - mpt3sas_transport_update_links(ioc, ioc->sas_hba.sas_address, - attached_handle, i, link_rate); - } - out: - kfree(sas_iounit_pg0); -} - -/** - * _scsih_sas_host_add - create sas host object - * @ioc: per adapter object - * - * Creating host side data object, stored in ioc->sas_hba - * - * Return nothing. - */ -static void -_scsih_sas_host_add(struct MPT3SAS_ADAPTER *ioc) -{ - int i; - Mpi2ConfigReply_t mpi_reply; - Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; - Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; - Mpi2SasPhyPage0_t phy_pg0; - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2SasEnclosurePage0_t enclosure_pg0; - u16 ioc_status; - u16 sz; - u8 device_missing_delay; - - mpt3sas_config_get_number_hba_phys(ioc, &ioc->sas_hba.num_phys); - if (!ioc->sas_hba.num_phys) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - /* sas_iounit page 0 */ - sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys * - sizeof(Mpi2SasIOUnit0PhyData_t)); - sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg0) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, - sas_iounit_pg0, sz))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - - /* sas_iounit page 1 */ - sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * - sizeof(Mpi2SasIOUnit1PhyData_t)); - sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg1) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, - sas_iounit_pg1, sz))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - - ioc->io_missing_delay = - sas_iounit_pg1->IODeviceMissingDelay; - device_missing_delay = - sas_iounit_pg1->ReportDeviceMissingDelay; - if (device_missing_delay & MPI2_SASIOUNIT1_REPORT_MISSING_UNIT_16) - ioc->device_missing_delay = (device_missing_delay & - MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK) * 16; - else - ioc->device_missing_delay = device_missing_delay & - MPI2_SASIOUNIT1_REPORT_MISSING_TIMEOUT_MASK; - - ioc->sas_hba.parent_dev = &ioc->shost->shost_gendev; - ioc->sas_hba.phy = kcalloc(ioc->sas_hba.num_phys, - sizeof(struct _sas_phy), GFP_KERNEL); - if (!ioc->sas_hba.phy) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - for (i = 0; i < ioc->sas_hba.num_phys ; i++) { - if ((mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0, - i))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - - if (i == 0) - ioc->sas_hba.handle = le16_to_cpu(sas_iounit_pg0-> - PhyData[0].ControllerDevHandle); - ioc->sas_hba.phy[i].handle = ioc->sas_hba.handle; - ioc->sas_hba.phy[i].phy_id = i; - mpt3sas_transport_add_host_phy(ioc, &ioc->sas_hba.phy[i], - phy_pg0, ioc->sas_hba.parent_dev); - } - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, ioc->sas_hba.handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out; - } - ioc->sas_hba.enclosure_handle = - le16_to_cpu(sas_device_pg0.EnclosureHandle); - ioc->sas_hba.sas_address = le64_to_cpu(sas_device_pg0.SASAddress); - pr_info(MPT3SAS_FMT - "host_add: handle(0x%04x), sas_addr(0x%016llx), phys(%d)\n", - ioc->name, ioc->sas_hba.handle, - (unsigned long long) ioc->sas_hba.sas_address, - ioc->sas_hba.num_phys) ; - - if (ioc->sas_hba.enclosure_handle) { - if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply, - &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - ioc->sas_hba.enclosure_handle))) - ioc->sas_hba.enclosure_logical_id = - le64_to_cpu(enclosure_pg0.EnclosureLogicalID); - } - - out: - kfree(sas_iounit_pg1); - kfree(sas_iounit_pg0); -} - -/** - * _scsih_expander_add - creating expander object - * @ioc: per adapter object - * @handle: expander handle - * - * Creating expander object, stored in ioc->sas_expander_list. - * - * Return 0 for success, else error. - */ -static int -_scsih_expander_add(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _sas_node *sas_expander; - Mpi2ConfigReply_t mpi_reply; - Mpi2ExpanderPage0_t expander_pg0; - Mpi2ExpanderPage1_t expander_pg1; - Mpi2SasEnclosurePage0_t enclosure_pg0; - u32 ioc_status; - u16 parent_handle; - u64 sas_address, sas_address_parent = 0; - int i; - unsigned long flags; - struct _sas_port *mpt3sas_port = NULL; - - int rc = 0; - - if (!handle) - return -1; - - if (ioc->shost_recovery || ioc->pci_error_recovery) - return -1; - - if ((mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, - MPI2_SAS_EXPAND_PGAD_FORM_HNDL, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - - /* handle out of order topology events */ - parent_handle = le16_to_cpu(expander_pg0.ParentDevHandle); - if (_scsih_get_sas_address(ioc, parent_handle, &sas_address_parent) - != 0) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - if (sas_address_parent != ioc->sas_hba.sas_address) { - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address_parent); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - if (!sas_expander) { - rc = _scsih_expander_add(ioc, parent_handle); - if (rc != 0) - return rc; - } - } - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_address = le64_to_cpu(expander_pg0.SASAddress); - sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - if (sas_expander) - return 0; - - sas_expander = kzalloc(sizeof(struct _sas_node), - GFP_KERNEL); - if (!sas_expander) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - - sas_expander->handle = handle; - sas_expander->num_phys = expander_pg0.NumPhys; - sas_expander->sas_address_parent = sas_address_parent; - sas_expander->sas_address = sas_address; - - pr_info(MPT3SAS_FMT "expander_add: handle(0x%04x)," \ - " parent(0x%04x), sas_addr(0x%016llx), phys(%d)\n", ioc->name, - handle, parent_handle, (unsigned long long) - sas_expander->sas_address, sas_expander->num_phys); - - if (!sas_expander->num_phys) - goto out_fail; - sas_expander->phy = kcalloc(sas_expander->num_phys, - sizeof(struct _sas_phy), GFP_KERNEL); - if (!sas_expander->phy) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -1; - goto out_fail; - } - - INIT_LIST_HEAD(&sas_expander->sas_port_list); - mpt3sas_port = mpt3sas_transport_port_add(ioc, handle, - sas_address_parent); - if (!mpt3sas_port) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -1; - goto out_fail; - } - sas_expander->parent_dev = &mpt3sas_port->rphy->dev; - - for (i = 0 ; i < sas_expander->num_phys ; i++) { - if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply, - &expander_pg1, i, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -1; - goto out_fail; - } - sas_expander->phy[i].handle = handle; - sas_expander->phy[i].phy_id = i; - - if ((mpt3sas_transport_add_expander_phy(ioc, - &sas_expander->phy[i], expander_pg1, - sas_expander->parent_dev))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -1; - goto out_fail; - } - } - - if (sas_expander->enclosure_handle) { - if (!(mpt3sas_config_get_enclosure_pg0(ioc, &mpi_reply, - &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - sas_expander->enclosure_handle))) - sas_expander->enclosure_logical_id = - le64_to_cpu(enclosure_pg0.EnclosureLogicalID); - } - - _scsih_expander_node_add(ioc, sas_expander); - return 0; - - out_fail: - - if (mpt3sas_port) - mpt3sas_transport_port_remove(ioc, sas_expander->sas_address, - sas_address_parent); - kfree(sas_expander); - return rc; -} - -/** - * mpt3sas_expander_remove - removing expander object - * @ioc: per adapter object - * @sas_address: expander sas_address - * - * Return nothing. - */ -void -mpt3sas_expander_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address) -{ - struct _sas_node *sas_expander; - unsigned long flags; - - if (ioc->shost_recovery) - return; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_expander = mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address); - if (sas_expander) - list_del(&sas_expander->list); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - if (sas_expander) - _scsih_expander_node_remove(ioc, sas_expander); -} - -/** - * _scsih_done - internal SCSI_IO callback handler. - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Callback handler when sending internal generated SCSI_IO. - * The callback index passed is `ioc->scsih_cb_idx` - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -static u8 -_scsih_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (ioc->scsih_cmds.status == MPT3_CMD_NOT_USED) - return 1; - if (ioc->scsih_cmds.smid != smid) - return 1; - ioc->scsih_cmds.status |= MPT3_CMD_COMPLETE; - if (mpi_reply) { - memcpy(ioc->scsih_cmds.reply, mpi_reply, - mpi_reply->MsgLength*4); - ioc->scsih_cmds.status |= MPT3_CMD_REPLY_VALID; - } - ioc->scsih_cmds.status &= ~MPT3_CMD_PENDING; - complete(&ioc->scsih_cmds.done); - return 1; -} - - - - -#define MPT3_MAX_LUNS (255) - - -/** - * _scsih_check_access_status - check access flags - * @ioc: per adapter object - * @sas_address: sas address - * @handle: sas device handle - * @access_flags: errors returned during discovery of the device - * - * Return 0 for success, else failure - */ -static u8 -_scsih_check_access_status(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, - u16 handle, u8 access_status) -{ - u8 rc = 1; - char *desc = NULL; - - switch (access_status) { - case MPI2_SAS_DEVICE0_ASTATUS_NO_ERRORS: - case MPI2_SAS_DEVICE0_ASTATUS_SATA_NEEDS_INITIALIZATION: - rc = 0; - break; - case MPI2_SAS_DEVICE0_ASTATUS_SATA_CAPABILITY_FAILED: - desc = "sata capability failed"; - break; - case MPI2_SAS_DEVICE0_ASTATUS_SATA_AFFILIATION_CONFLICT: - desc = "sata affiliation conflict"; - break; - case MPI2_SAS_DEVICE0_ASTATUS_ROUTE_NOT_ADDRESSABLE: - desc = "route not addressable"; - break; - case MPI2_SAS_DEVICE0_ASTATUS_SMP_ERROR_NOT_ADDRESSABLE: - desc = "smp error not addressable"; - break; - case MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED: - desc = "device blocked"; - break; - case MPI2_SAS_DEVICE0_ASTATUS_SATA_INIT_FAILED: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_UNKNOWN: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_AFFILIATION_CONFLICT: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_DIAG: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_IDENTIFICATION: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_CHECK_POWER: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_PIO_SN: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_MDMA_SN: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_UDMA_SN: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_ZONING_VIOLATION: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_NOT_ADDRESSABLE: - case MPI2_SAS_DEVICE0_ASTATUS_SIF_MAX: - desc = "sata initialization failed"; - break; - default: - desc = "unknown"; - break; - } - - if (!rc) - return 0; - - pr_err(MPT3SAS_FMT - "discovery errors(%s): sas_address(0x%016llx), handle(0x%04x)\n", - ioc->name, desc, (unsigned long long)sas_address, handle); - return rc; -} - -/** - * _scsih_check_device - checking device responsiveness - * @ioc: per adapter object - * @parent_sas_address: sas address of parent expander or sas host - * @handle: attached device handle - * @phy_numberv: phy number - * @link_rate: new link rate - * - * Returns nothing. - */ -static void -_scsih_check_device(struct MPT3SAS_ADAPTER *ioc, - u64 parent_sas_address, u16 handle, u8 phy_number, u8 link_rate) -{ - Mpi2ConfigReply_t mpi_reply; - Mpi2SasDevicePage0_t sas_device_pg0; - struct _sas_device *sas_device; - u32 ioc_status; - unsigned long flags; - u64 sas_address; - struct scsi_target *starget; - struct MPT3SAS_TARGET *sas_target_priv_data; - u32 device_info; - - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) - return; - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - return; - - /* wide port handling ~ we need only handle device once for the phy that - * is matched in sas device page zero - */ - if (phy_number != sas_device_pg0.PhyNum) - return; - - /* check if this is end device */ - device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); - if (!(_scsih_is_end_device(device_info))) - return; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_address = le64_to_cpu(sas_device_pg0.SASAddress); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, - sas_address); - - if (!sas_device) - goto out_unlock; - - if (unlikely(sas_device->handle != handle)) { - starget = sas_device->starget; - sas_target_priv_data = starget->hostdata; - starget_printk(KERN_INFO, starget, - "handle changed from(0x%04x) to (0x%04x)!!!\n", - sas_device->handle, handle); - sas_target_priv_data->handle = handle; - sas_device->handle = handle; - if (sas_device_pg0.Flags & - MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { - sas_device->enclosure_level = - le16_to_cpu(sas_device_pg0.EnclosureLevel); - memcpy(&sas_device->connector_name[0], - &sas_device_pg0.ConnectorName[0], 4); - } else { - sas_device->enclosure_level = 0; - sas_device->connector_name[0] = '\0'; - } - } - - /* check if device is present */ - if (!(le16_to_cpu(sas_device_pg0.Flags) & - MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) { - pr_err(MPT3SAS_FMT - "device is not present handle(0x%04x), flags!!!\n", - ioc->name, handle); - goto out_unlock; - } - - /* check if there were any issues with discovery */ - if (_scsih_check_access_status(ioc, sas_address, handle, - sas_device_pg0.AccessStatus)) - goto out_unlock; - - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - _scsih_ublock_io_device(ioc, sas_address); - - if (sas_device) - sas_device_put(sas_device); - return; - -out_unlock: - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (sas_device) - sas_device_put(sas_device); -} - -/** - * _scsih_add_device - creating sas device object - * @ioc: per adapter object - * @handle: sas device handle - * @phy_num: phy number end device attached to - * @is_pd: is this hidden raid component - * - * Creating end device object, stored in ioc->sas_device_list. - * - * Returns 0 for success, non-zero for failure. - */ -static int -_scsih_add_device(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phy_num, - u8 is_pd) -{ - Mpi2ConfigReply_t mpi_reply; - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2SasEnclosurePage0_t enclosure_pg0; - struct _sas_device *sas_device; - u32 ioc_status; - u64 sas_address; - u32 device_info; - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - - /* check if this is end device */ - device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); - if (!(_scsih_is_end_device(device_info))) - return -1; - sas_address = le64_to_cpu(sas_device_pg0.SASAddress); - - /* check if device is present */ - if (!(le16_to_cpu(sas_device_pg0.Flags) & - MPI2_SAS_DEVICE0_FLAGS_DEVICE_PRESENT)) { - pr_err(MPT3SAS_FMT "device is not present handle(0x04%x)!!!\n", - ioc->name, handle); - return -1; - } - - /* check if there were any issues with discovery */ - if (_scsih_check_access_status(ioc, sas_address, handle, - sas_device_pg0.AccessStatus)) - return -1; - - sas_device = mpt3sas_get_sdev_by_addr(ioc, - sas_address); - if (sas_device) { - sas_device_put(sas_device); - return -1; - } - - sas_device = kzalloc(sizeof(struct _sas_device), - GFP_KERNEL); - if (!sas_device) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return 0; - } - - kref_init(&sas_device->refcount); - sas_device->handle = handle; - if (_scsih_get_sas_address(ioc, - le16_to_cpu(sas_device_pg0.ParentDevHandle), - &sas_device->sas_address_parent) != 0) - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - sas_device->enclosure_handle = - le16_to_cpu(sas_device_pg0.EnclosureHandle); - if (sas_device->enclosure_handle != 0) - sas_device->slot = - le16_to_cpu(sas_device_pg0.Slot); - sas_device->device_info = device_info; - sas_device->sas_address = sas_address; - sas_device->phy = sas_device_pg0.PhyNum; - sas_device->fast_path = (le16_to_cpu(sas_device_pg0.Flags) & - MPI25_SAS_DEVICE0_FLAGS_FAST_PATH_CAPABLE) ? 1 : 0; - - if (sas_device_pg0.Flags & MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { - sas_device->enclosure_level = - le16_to_cpu(sas_device_pg0.EnclosureLevel); - memcpy(&sas_device->connector_name[0], - &sas_device_pg0.ConnectorName[0], 4); - } else { - sas_device->enclosure_level = 0; - sas_device->connector_name[0] = '\0'; - } - /* get enclosure_logical_id */ - if (sas_device->enclosure_handle && !(mpt3sas_config_get_enclosure_pg0( - ioc, &mpi_reply, &enclosure_pg0, MPI2_SAS_ENCLOS_PGAD_FORM_HANDLE, - sas_device->enclosure_handle))) - sas_device->enclosure_logical_id = - le64_to_cpu(enclosure_pg0.EnclosureLogicalID); - - /* get device name */ - sas_device->device_name = le64_to_cpu(sas_device_pg0.DeviceName); - - if (ioc->wait_for_discovery_to_complete) - _scsih_sas_device_init_add(ioc, sas_device); - else - _scsih_sas_device_add(ioc, sas_device); - - sas_device_put(sas_device); - return 0; -} - -/** - * _scsih_remove_device - removing sas device object - * @ioc: per adapter object - * @sas_device_delete: the sas_device object - * - * Return nothing. - */ -static void -_scsih_remove_device(struct MPT3SAS_ADAPTER *ioc, - struct _sas_device *sas_device) -{ - struct MPT3SAS_TARGET *sas_target_priv_data; - - if ((ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) && - (sas_device->pfa_led_on)) { - _scsih_turn_off_pfa_led(ioc, sas_device); - sas_device->pfa_led_on = 0; - } - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: enter: handle(0x%04x), sas_addr(0x%016llx)\n", - ioc->name, __func__, - sas_device->handle, (unsigned long long) - sas_device->sas_address)); - if (sas_device->enclosure_handle != 0) - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: enter: enclosure logical id(0x%016llx), slot(%d)\n", - ioc->name, __func__, - (unsigned long long)sas_device->enclosure_logical_id, - sas_device->slot)); - if (sas_device->connector_name[0] != '\0') - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: enter: enclosure level(0x%04x), connector name( %s)\n", - ioc->name, __func__, - sas_device->enclosure_level, - sas_device->connector_name)); - - if (sas_device->starget && sas_device->starget->hostdata) { - sas_target_priv_data = sas_device->starget->hostdata; - sas_target_priv_data->deleted = 1; - _scsih_ublock_io_device(ioc, sas_device->sas_address); - sas_target_priv_data->handle = - MPT3SAS_INVALID_DEVICE_HANDLE; - } - - if (!ioc->hide_drives) - mpt3sas_transport_port_remove(ioc, - sas_device->sas_address, - sas_device->sas_address_parent); - - pr_info(MPT3SAS_FMT - "removing handle(0x%04x), sas_addr(0x%016llx)\n", - ioc->name, sas_device->handle, - (unsigned long long) sas_device->sas_address); - if (sas_device->enclosure_handle != 0) - pr_info(MPT3SAS_FMT - "removing : enclosure logical id(0x%016llx), slot(%d)\n", - ioc->name, - (unsigned long long)sas_device->enclosure_logical_id, - sas_device->slot); - if (sas_device->connector_name[0] != '\0') - pr_info(MPT3SAS_FMT - "removing enclosure level(0x%04x), connector name( %s)\n", - ioc->name, sas_device->enclosure_level, - sas_device->connector_name); - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: exit: handle(0x%04x), sas_addr(0x%016llx)\n", - ioc->name, __func__, - sas_device->handle, (unsigned long long) - sas_device->sas_address)); - if (sas_device->enclosure_handle != 0) - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: exit: enclosure logical id(0x%016llx), slot(%d)\n", - ioc->name, __func__, - (unsigned long long)sas_device->enclosure_logical_id, - sas_device->slot)); - if (sas_device->connector_name[0] != '\0') - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: exit: enclosure level(0x%04x), connector name(%s)\n", - ioc->name, __func__, sas_device->enclosure_level, - sas_device->connector_name)); -} - -/** - * _scsih_sas_topology_change_event_debug - debug for topology event - * @ioc: per adapter object - * @event_data: event data payload - * Context: user. - */ -static void -_scsih_sas_topology_change_event_debug(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataSasTopologyChangeList_t *event_data) -{ - int i; - u16 handle; - u16 reason_code; - u8 phy_number; - char *status_str = NULL; - u8 link_rate, prev_link_rate; - - switch (event_data->ExpStatus) { - case MPI2_EVENT_SAS_TOPO_ES_ADDED: - status_str = "add"; - break; - case MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING: - status_str = "remove"; - break; - case MPI2_EVENT_SAS_TOPO_ES_RESPONDING: - case 0: - status_str = "responding"; - break; - case MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING: - status_str = "remove delay"; - break; - default: - status_str = "unknown status"; - break; - } - pr_info(MPT3SAS_FMT "sas topology change: (%s)\n", - ioc->name, status_str); - pr_info("\thandle(0x%04x), enclosure_handle(0x%04x) " \ - "start_phy(%02d), count(%d)\n", - le16_to_cpu(event_data->ExpanderDevHandle), - le16_to_cpu(event_data->EnclosureHandle), - event_data->StartPhyNum, event_data->NumEntries); - for (i = 0; i < event_data->NumEntries; i++) { - handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); - if (!handle) - continue; - phy_number = event_data->StartPhyNum + i; - reason_code = event_data->PHY[i].PhyStatus & - MPI2_EVENT_SAS_TOPO_RC_MASK; - switch (reason_code) { - case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: - status_str = "target add"; - break; - case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: - status_str = "target remove"; - break; - case MPI2_EVENT_SAS_TOPO_RC_DELAY_NOT_RESPONDING: - status_str = "delay target remove"; - break; - case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: - status_str = "link rate change"; - break; - case MPI2_EVENT_SAS_TOPO_RC_NO_CHANGE: - status_str = "target responding"; - break; - default: - status_str = "unknown"; - break; - } - link_rate = event_data->PHY[i].LinkRate >> 4; - prev_link_rate = event_data->PHY[i].LinkRate & 0xF; - pr_info("\tphy(%02d), attached_handle(0x%04x): %s:" \ - " link rate: new(0x%02x), old(0x%02x)\n", phy_number, - handle, status_str, link_rate, prev_link_rate); - - } -} - -/** - * _scsih_sas_topology_change_event - handle topology changes - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - */ -static int -_scsih_sas_topology_change_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - int i; - u16 parent_handle, handle; - u16 reason_code; - u8 phy_number, max_phys; - struct _sas_node *sas_expander; - u64 sas_address; - unsigned long flags; - u8 link_rate, prev_link_rate; - Mpi2EventDataSasTopologyChangeList_t *event_data = - (Mpi2EventDataSasTopologyChangeList_t *) - fw_event->event_data; - - if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) - _scsih_sas_topology_change_event_debug(ioc, event_data); - - if (ioc->shost_recovery || ioc->remove_host || ioc->pci_error_recovery) - return 0; - - if (!ioc->sas_hba.num_phys) - _scsih_sas_host_add(ioc); - else - _scsih_sas_host_refresh(ioc); - - if (fw_event->ignore) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "ignoring expander event\n", ioc->name)); - return 0; - } - - parent_handle = le16_to_cpu(event_data->ExpanderDevHandle); - - /* handle expander add */ - if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_ADDED) - if (_scsih_expander_add(ioc, parent_handle) != 0) - return 0; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_expander = mpt3sas_scsih_expander_find_by_handle(ioc, - parent_handle); - if (sas_expander) { - sas_address = sas_expander->sas_address; - max_phys = sas_expander->num_phys; - } else if (parent_handle < ioc->sas_hba.num_phys) { - sas_address = ioc->sas_hba.sas_address; - max_phys = ioc->sas_hba.num_phys; - } else { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return 0; - } - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - /* handle siblings events */ - for (i = 0; i < event_data->NumEntries; i++) { - if (fw_event->ignore) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "ignoring expander event\n", ioc->name)); - return 0; - } - if (ioc->remove_host || ioc->pci_error_recovery) - return 0; - phy_number = event_data->StartPhyNum + i; - if (phy_number >= max_phys) - continue; - reason_code = event_data->PHY[i].PhyStatus & - MPI2_EVENT_SAS_TOPO_RC_MASK; - if ((event_data->PHY[i].PhyStatus & - MPI2_EVENT_SAS_TOPO_PHYSTATUS_VACANT) && (reason_code != - MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING)) - continue; - handle = le16_to_cpu(event_data->PHY[i].AttachedDevHandle); - if (!handle) - continue; - link_rate = event_data->PHY[i].LinkRate >> 4; - prev_link_rate = event_data->PHY[i].LinkRate & 0xF; - switch (reason_code) { - case MPI2_EVENT_SAS_TOPO_RC_PHY_CHANGED: - - if (ioc->shost_recovery) - break; - - if (link_rate == prev_link_rate) - break; - - mpt3sas_transport_update_links(ioc, sas_address, - handle, phy_number, link_rate); - - if (link_rate < MPI2_SAS_NEG_LINK_RATE_1_5) - break; - - _scsih_check_device(ioc, sas_address, handle, - phy_number, link_rate); - - - case MPI2_EVENT_SAS_TOPO_RC_TARG_ADDED: - - if (ioc->shost_recovery) - break; - - mpt3sas_transport_update_links(ioc, sas_address, - handle, phy_number, link_rate); - - _scsih_add_device(ioc, handle, phy_number, 0); - - break; - case MPI2_EVENT_SAS_TOPO_RC_TARG_NOT_RESPONDING: - - _scsih_device_remove_by_handle(ioc, handle); - break; - } - } - - /* handle expander removal */ - if (event_data->ExpStatus == MPI2_EVENT_SAS_TOPO_ES_NOT_RESPONDING && - sas_expander) - mpt3sas_expander_remove(ioc, sas_address); - - return 0; -} - -/** - * _scsih_sas_device_status_change_event_debug - debug for device event - * @event_data: event data payload - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_device_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataSasDeviceStatusChange_t *event_data) -{ - char *reason_str = NULL; - - switch (event_data->ReasonCode) { - case MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA: - reason_str = "smart data"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_UNSUPPORTED: - reason_str = "unsupported device discovered"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET: - reason_str = "internal device reset"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_TASK_ABORT_INTERNAL: - reason_str = "internal task abort"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_ABORT_TASK_SET_INTERNAL: - reason_str = "internal task abort set"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_CLEAR_TASK_SET_INTERNAL: - reason_str = "internal clear task set"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_QUERY_TASK_INTERNAL: - reason_str = "internal query task"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE: - reason_str = "sata init failure"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET: - reason_str = "internal device reset complete"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_TASK_ABORT_INTERNAL: - reason_str = "internal task abort complete"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_ASYNC_NOTIFICATION: - reason_str = "internal async notification"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_EXPANDER_REDUCED_FUNCTIONALITY: - reason_str = "expander reduced functionality"; - break; - case MPI2_EVENT_SAS_DEV_STAT_RC_CMP_EXPANDER_REDUCED_FUNCTIONALITY: - reason_str = "expander reduced functionality complete"; - break; - default: - reason_str = "unknown reason"; - break; - } - pr_info(MPT3SAS_FMT "device status change: (%s)\n" - "\thandle(0x%04x), sas address(0x%016llx), tag(%d)", - ioc->name, reason_str, le16_to_cpu(event_data->DevHandle), - (unsigned long long)le64_to_cpu(event_data->SASAddress), - le16_to_cpu(event_data->TaskTag)); - if (event_data->ReasonCode == MPI2_EVENT_SAS_DEV_STAT_RC_SMART_DATA) - pr_info(MPT3SAS_FMT ", ASC(0x%x), ASCQ(0x%x)\n", ioc->name, - event_data->ASC, event_data->ASCQ); - pr_info("\n"); -} - -/** - * _scsih_sas_device_status_change_event - handle device status change - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_device_status_change_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - struct MPT3SAS_TARGET *target_priv_data; - struct _sas_device *sas_device; - u64 sas_address; - unsigned long flags; - Mpi2EventDataSasDeviceStatusChange_t *event_data = - (Mpi2EventDataSasDeviceStatusChange_t *) - fw_event->event_data; - - if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) - _scsih_sas_device_status_change_event_debug(ioc, - event_data); - - /* In MPI Revision K (0xC), the internal device reset complete was - * implemented, so avoid setting tm_busy flag for older firmware. - */ - if ((ioc->facts.HeaderVersion >> 8) < 0xC) - return; - - if (event_data->ReasonCode != - MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET && - event_data->ReasonCode != - MPI2_EVENT_SAS_DEV_STAT_RC_CMP_INTERNAL_DEV_RESET) - return; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_address = le64_to_cpu(event_data->SASAddress); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, - sas_address); - - if (!sas_device || !sas_device->starget) - goto out; - - target_priv_data = sas_device->starget->hostdata; - if (!target_priv_data) - goto out; - - if (event_data->ReasonCode == - MPI2_EVENT_SAS_DEV_STAT_RC_INTERNAL_DEVICE_RESET) - target_priv_data->tm_busy = 1; - else - target_priv_data->tm_busy = 0; - -out: - if (sas_device) - sas_device_put(sas_device); - - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - -} - -/** - * _scsih_sas_enclosure_dev_status_change_event_debug - debug for enclosure - * event - * @ioc: per adapter object - * @event_data: event data payload - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_enclosure_dev_status_change_event_debug(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataSasEnclDevStatusChange_t *event_data) -{ - char *reason_str = NULL; - - switch (event_data->ReasonCode) { - case MPI2_EVENT_SAS_ENCL_RC_ADDED: - reason_str = "enclosure add"; - break; - case MPI2_EVENT_SAS_ENCL_RC_NOT_RESPONDING: - reason_str = "enclosure remove"; - break; - default: - reason_str = "unknown reason"; - break; - } - - pr_info(MPT3SAS_FMT "enclosure status change: (%s)\n" - "\thandle(0x%04x), enclosure logical id(0x%016llx)" - " number slots(%d)\n", ioc->name, reason_str, - le16_to_cpu(event_data->EnclosureHandle), - (unsigned long long)le64_to_cpu(event_data->EnclosureLogicalID), - le16_to_cpu(event_data->StartSlot)); -} - -/** - * _scsih_sas_enclosure_dev_status_change_event - handle enclosure events - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_enclosure_dev_status_change_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) - _scsih_sas_enclosure_dev_status_change_event_debug(ioc, - (Mpi2EventDataSasEnclDevStatusChange_t *) - fw_event->event_data); -} - -/** - * _scsih_sas_broadcast_primitive_event - handle broadcast events - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_broadcast_primitive_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - struct scsi_cmnd *scmd; - struct scsi_device *sdev; - u16 smid, handle; - u32 lun; - struct MPT3SAS_DEVICE *sas_device_priv_data; - u32 termination_count; - u32 query_count; - Mpi2SCSITaskManagementReply_t *mpi_reply; - Mpi2EventDataSasBroadcastPrimitive_t *event_data = - (Mpi2EventDataSasBroadcastPrimitive_t *) - fw_event->event_data; - u16 ioc_status; - unsigned long flags; - int r; - u8 max_retries = 0; - u8 task_abort_retries; - - mutex_lock(&ioc->tm_cmds.mutex); - pr_info(MPT3SAS_FMT - "%s: enter: phy number(%d), width(%d)\n", - ioc->name, __func__, event_data->PhyNum, - event_data->PortWidth); - - _scsih_block_io_all_device(ioc); - - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - mpi_reply = ioc->tm_cmds.reply; - broadcast_aen_retry: - - /* sanity checks for retrying this loop */ - if (max_retries++ == 5) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: giving up\n", - ioc->name, __func__)); - goto out; - } else if (max_retries > 1) - dewtprintk(ioc, pr_info(MPT3SAS_FMT "%s: %d retry\n", - ioc->name, __func__, max_retries - 1)); - - termination_count = 0; - query_count = 0; - for (smid = 1; smid <= ioc->scsiio_depth; smid++) { - if (ioc->shost_recovery) - goto out; - scmd = _scsih_scsi_lookup_get(ioc, smid); - if (!scmd) - continue; - sdev = scmd->device; - sas_device_priv_data = sdev->hostdata; - if (!sas_device_priv_data || !sas_device_priv_data->sas_target) - continue; - /* skip hidden raid components */ - if (sas_device_priv_data->sas_target->flags & - MPT_TARGET_FLAGS_RAID_COMPONENT) - continue; - /* skip volumes */ - if (sas_device_priv_data->sas_target->flags & - MPT_TARGET_FLAGS_VOLUME) - continue; - - handle = sas_device_priv_data->sas_target->handle; - lun = sas_device_priv_data->lun; - query_count++; - - if (ioc->shost_recovery) - goto out; - - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - r = mpt3sas_scsih_issue_tm(ioc, handle, 0, 0, lun, - MPI2_SCSITASKMGMT_TASKTYPE_QUERY_TASK, smid, 30, - TM_MUTEX_OFF); - if (r == FAILED) { - sdev_printk(KERN_WARNING, sdev, - "mpt3sas_scsih_issue_tm: FAILED when sending " - "QUERY_TASK: scmd(%p)\n", scmd); - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - goto broadcast_aen_retry; - } - ioc_status = le16_to_cpu(mpi_reply->IOCStatus) - & MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - sdev_printk(KERN_WARNING, sdev, - "query task: FAILED with IOCSTATUS(0x%04x), scmd(%p)\n", - ioc_status, scmd); - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - goto broadcast_aen_retry; - } - - /* see if IO is still owned by IOC and target */ - if (mpi_reply->ResponseCode == - MPI2_SCSITASKMGMT_RSP_TM_SUCCEEDED || - mpi_reply->ResponseCode == - MPI2_SCSITASKMGMT_RSP_IO_QUEUED_ON_IOC) { - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - continue; - } - task_abort_retries = 0; - tm_retry: - if (task_abort_retries++ == 60) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: ABORT_TASK: giving up\n", ioc->name, - __func__)); - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - goto broadcast_aen_retry; - } - - if (ioc->shost_recovery) - goto out_no_lock; - - r = mpt3sas_scsih_issue_tm(ioc, handle, sdev->channel, sdev->id, - sdev->lun, MPI2_SCSITASKMGMT_TASKTYPE_ABORT_TASK, smid, 30, - TM_MUTEX_OFF); - if (r == FAILED) { - sdev_printk(KERN_WARNING, sdev, - "mpt3sas_scsih_issue_tm: ABORT_TASK: FAILED : " - "scmd(%p)\n", scmd); - goto tm_retry; - } - - if (task_abort_retries > 1) - sdev_printk(KERN_WARNING, sdev, - "mpt3sas_scsih_issue_tm: ABORT_TASK: RETRIES (%d):" - " scmd(%p)\n", - task_abort_retries - 1, scmd); - - termination_count += le32_to_cpu(mpi_reply->TerminationCount); - spin_lock_irqsave(&ioc->scsi_lookup_lock, flags); - } - - if (ioc->broadcast_aen_pending) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: loop back due to pending AEN\n", - ioc->name, __func__)); - ioc->broadcast_aen_pending = 0; - goto broadcast_aen_retry; - } - - out: - spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags); - out_no_lock: - - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s - exit, query_count = %d termination_count = %d\n", - ioc->name, __func__, query_count, termination_count)); - - ioc->broadcast_aen_busy = 0; - if (!ioc->shost_recovery) - _scsih_ublock_io_all_device(ioc); - mutex_unlock(&ioc->tm_cmds.mutex); -} - -/** - * _scsih_sas_discovery_event - handle discovery events - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_discovery_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - Mpi2EventDataSasDiscovery_t *event_data = - (Mpi2EventDataSasDiscovery_t *) fw_event->event_data; - - if (ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) { - pr_info(MPT3SAS_FMT "discovery event: (%s)", ioc->name, - (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED) ? - "start" : "stop"); - if (event_data->DiscoveryStatus) - pr_info("discovery_status(0x%08x)", - le32_to_cpu(event_data->DiscoveryStatus)); - pr_info("\n"); - } - - if (event_data->ReasonCode == MPI2_EVENT_SAS_DISC_RC_STARTED && - !ioc->sas_hba.num_phys) { - if (disable_discovery > 0 && ioc->shost_recovery) { - /* Wait for the reset to complete */ - while (ioc->shost_recovery) - ssleep(1); - } - _scsih_sas_host_add(ioc); - } -} - -/** - * _scsih_ir_fastpath - turn on fastpath for IR physdisk - * @ioc: per adapter object - * @handle: device handle for physical disk - * @phys_disk_num: physical disk number - * - * Return 0 for success, else failure. - */ -static int -_scsih_ir_fastpath(struct MPT3SAS_ADAPTER *ioc, u16 handle, u8 phys_disk_num) -{ - Mpi2RaidActionRequest_t *mpi_request; - Mpi2RaidActionReply_t *mpi_reply; - u16 smid; - u8 issue_reset = 0; - int rc = 0; - u16 ioc_status; - u32 log_info; - - if (ioc->hba_mpi_version_belonged == MPI2_VERSION) - return rc; - - mutex_lock(&ioc->scsih_cmds.mutex); - - if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - ioc->scsih_cmds.status = MPT3_CMD_PENDING; - - smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; - rc = -EAGAIN; - goto out; - } - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->scsih_cmds.smid = smid; - memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t)); - - mpi_request->Function = MPI2_FUNCTION_RAID_ACTION; - mpi_request->Action = MPI2_RAID_ACTION_PHYSDISK_HIDDEN; - mpi_request->PhysDiskNum = phys_disk_num; - - dewtprintk(ioc, pr_info(MPT3SAS_FMT "IR RAID_ACTION: turning fast "\ - "path on for handle(0x%04x), phys_disk_num (0x%02x)\n", ioc->name, - handle, phys_disk_num)); - - init_completion(&ioc->scsih_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); - - if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - if (!(ioc->scsih_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - rc = -EFAULT; - goto out; - } - - if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) { - - mpi_reply = ioc->scsih_cmds.reply; - ioc_status = le16_to_cpu(mpi_reply->IOCStatus); - if (ioc_status & MPI2_IOCSTATUS_FLAG_LOG_INFO_AVAILABLE) - log_info = le32_to_cpu(mpi_reply->IOCLogInfo); - else - log_info = 0; - ioc_status &= MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "IR RAID_ACTION: failed: ioc_status(0x%04x), " - "loginfo(0x%08x)!!!\n", ioc->name, ioc_status, - log_info)); - rc = -EFAULT; - } else - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "IR RAID_ACTION: completed successfully\n", - ioc->name)); - } - - out: - ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; - mutex_unlock(&ioc->scsih_cmds.mutex); - - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - return rc; -} - -/** - * _scsih_reprobe_lun - reprobing lun - * @sdev: scsi device struct - * @no_uld_attach: sdev->no_uld_attach flag setting - * - **/ -static void -_scsih_reprobe_lun(struct scsi_device *sdev, void *no_uld_attach) -{ - int rc; - sdev->no_uld_attach = no_uld_attach ? 1 : 0; - sdev_printk(KERN_INFO, sdev, "%s raid component\n", - sdev->no_uld_attach ? "hidding" : "exposing"); - rc = scsi_device_reprobe(sdev); -} - -/** - * _scsih_sas_volume_add - add new volume - * @ioc: per adapter object - * @element: IR config element data - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_volume_add(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventIrConfigElement_t *element) -{ - struct _raid_device *raid_device; - unsigned long flags; - u64 wwid; - u16 handle = le16_to_cpu(element->VolDevHandle); - int rc; - - mpt3sas_config_get_volume_wwid(ioc, handle, &wwid); - if (!wwid) { - pr_err(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__); - return; - } - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_wwid(ioc, wwid); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - - if (raid_device) - return; - - raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL); - if (!raid_device) { - pr_err(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__); - return; - } - - raid_device->id = ioc->sas_id++; - raid_device->channel = RAID_CHANNEL; - raid_device->handle = handle; - raid_device->wwid = wwid; - _scsih_raid_device_add(ioc, raid_device); - if (!ioc->wait_for_discovery_to_complete) { - rc = scsi_add_device(ioc->shost, RAID_CHANNEL, - raid_device->id, 0); - if (rc) - _scsih_raid_device_remove(ioc, raid_device); - } else { - spin_lock_irqsave(&ioc->raid_device_lock, flags); - _scsih_determine_boot_device(ioc, raid_device, 1); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - } -} - -/** - * _scsih_sas_volume_delete - delete volume - * @ioc: per adapter object - * @handle: volume device handle - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_volume_delete(struct MPT3SAS_ADAPTER *ioc, u16 handle) -{ - struct _raid_device *raid_device; - unsigned long flags; - struct MPT3SAS_TARGET *sas_target_priv_data; - struct scsi_target *starget = NULL; - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle); - if (raid_device) { - if (raid_device->starget) { - starget = raid_device->starget; - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->deleted = 1; - } - pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n", - ioc->name, raid_device->handle, - (unsigned long long) raid_device->wwid); - list_del(&raid_device->list); - kfree(raid_device); - } - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - if (starget) - scsi_remove_target(&starget->dev); -} - -/** - * _scsih_sas_pd_expose - expose pd component to /dev/sdX - * @ioc: per adapter object - * @element: IR config element data - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_pd_expose(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventIrConfigElement_t *element) -{ - struct _sas_device *sas_device; - struct scsi_target *starget = NULL; - struct MPT3SAS_TARGET *sas_target_priv_data; - unsigned long flags; - u16 handle = le16_to_cpu(element->PhysDiskDevHandle); - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); - if (sas_device) { - sas_device->volume_handle = 0; - sas_device->volume_wwid = 0; - clear_bit(handle, ioc->pd_handles); - if (sas_device->starget && sas_device->starget->hostdata) { - starget = sas_device->starget; - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->flags &= - ~MPT_TARGET_FLAGS_RAID_COMPONENT; - } - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (!sas_device) - return; - - /* exposing raid component */ - if (starget) - starget_for_each_device(starget, NULL, _scsih_reprobe_lun); - - sas_device_put(sas_device); -} - -/** - * _scsih_sas_pd_hide - hide pd component from /dev/sdX - * @ioc: per adapter object - * @element: IR config element data - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_pd_hide(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventIrConfigElement_t *element) -{ - struct _sas_device *sas_device; - struct scsi_target *starget = NULL; - struct MPT3SAS_TARGET *sas_target_priv_data; - unsigned long flags; - u16 handle = le16_to_cpu(element->PhysDiskDevHandle); - u16 volume_handle = 0; - u64 volume_wwid = 0; - - mpt3sas_config_get_volume_handle(ioc, handle, &volume_handle); - if (volume_handle) - mpt3sas_config_get_volume_wwid(ioc, volume_handle, - &volume_wwid); - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_handle(ioc, handle); - if (sas_device) { - set_bit(handle, ioc->pd_handles); - if (sas_device->starget && sas_device->starget->hostdata) { - starget = sas_device->starget; - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->flags |= - MPT_TARGET_FLAGS_RAID_COMPONENT; - sas_device->volume_handle = volume_handle; - sas_device->volume_wwid = volume_wwid; - } - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - if (!sas_device) - return; - - /* hiding raid component */ - _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum); - - if (starget) - starget_for_each_device(starget, (void *)1, _scsih_reprobe_lun); - - sas_device_put(sas_device); -} - -/** - * _scsih_sas_pd_delete - delete pd component - * @ioc: per adapter object - * @element: IR config element data - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_pd_delete(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventIrConfigElement_t *element) -{ - u16 handle = le16_to_cpu(element->PhysDiskDevHandle); - - _scsih_device_remove_by_handle(ioc, handle); -} - -/** - * _scsih_sas_pd_add - remove pd component - * @ioc: per adapter object - * @element: IR config element data - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_pd_add(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventIrConfigElement_t *element) -{ - struct _sas_device *sas_device; - u16 handle = le16_to_cpu(element->PhysDiskDevHandle); - Mpi2ConfigReply_t mpi_reply; - Mpi2SasDevicePage0_t sas_device_pg0; - u32 ioc_status; - u64 sas_address; - u16 parent_handle; - - set_bit(handle, ioc->pd_handles); - - sas_device = mpt3sas_get_sdev_by_handle(ioc, handle); - if (sas_device) { - _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum); - sas_device_put(sas_device); - return; - } - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); - if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) - mpt3sas_transport_update_links(ioc, sas_address, handle, - sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); - - _scsih_ir_fastpath(ioc, handle, element->PhysDiskNum); - _scsih_add_device(ioc, handle, 0, 1); -} - -/** - * _scsih_sas_ir_config_change_event_debug - debug for IR Config Change events - * @ioc: per adapter object - * @event_data: event data payload - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_ir_config_change_event_debug(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataIrConfigChangeList_t *event_data) -{ - Mpi2EventIrConfigElement_t *element; - u8 element_type; - int i; - char *reason_str = NULL, *element_str = NULL; - - element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; - - pr_info(MPT3SAS_FMT "raid config change: (%s), elements(%d)\n", - ioc->name, (le32_to_cpu(event_data->Flags) & - MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? - "foreign" : "native", event_data->NumElements); - for (i = 0; i < event_data->NumElements; i++, element++) { - switch (element->ReasonCode) { - case MPI2_EVENT_IR_CHANGE_RC_ADDED: - reason_str = "add"; - break; - case MPI2_EVENT_IR_CHANGE_RC_REMOVED: - reason_str = "remove"; - break; - case MPI2_EVENT_IR_CHANGE_RC_NO_CHANGE: - reason_str = "no change"; - break; - case MPI2_EVENT_IR_CHANGE_RC_HIDE: - reason_str = "hide"; - break; - case MPI2_EVENT_IR_CHANGE_RC_UNHIDE: - reason_str = "unhide"; - break; - case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: - reason_str = "volume_created"; - break; - case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: - reason_str = "volume_deleted"; - break; - case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: - reason_str = "pd_created"; - break; - case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: - reason_str = "pd_deleted"; - break; - default: - reason_str = "unknown reason"; - break; - } - element_type = le16_to_cpu(element->ElementFlags) & - MPI2_EVENT_IR_CHANGE_EFLAGS_ELEMENT_TYPE_MASK; - switch (element_type) { - case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLUME_ELEMENT: - element_str = "volume"; - break; - case MPI2_EVENT_IR_CHANGE_EFLAGS_VOLPHYSDISK_ELEMENT: - element_str = "phys disk"; - break; - case MPI2_EVENT_IR_CHANGE_EFLAGS_HOTSPARE_ELEMENT: - element_str = "hot spare"; - break; - default: - element_str = "unknown element"; - break; - } - pr_info("\t(%s:%s), vol handle(0x%04x), " \ - "pd handle(0x%04x), pd num(0x%02x)\n", element_str, - reason_str, le16_to_cpu(element->VolDevHandle), - le16_to_cpu(element->PhysDiskDevHandle), - element->PhysDiskNum); - } -} - -/** - * _scsih_sas_ir_config_change_event - handle ir configuration change events - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_ir_config_change_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - Mpi2EventIrConfigElement_t *element; - int i; - u8 foreign_config; - Mpi2EventDataIrConfigChangeList_t *event_data = - (Mpi2EventDataIrConfigChangeList_t *) - fw_event->event_data; - - if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) && - (!ioc->hide_ir_msg)) - _scsih_sas_ir_config_change_event_debug(ioc, event_data); - - foreign_config = (le32_to_cpu(event_data->Flags) & - MPI2_EVENT_IR_CHANGE_FLAGS_FOREIGN_CONFIG) ? 1 : 0; - - element = (Mpi2EventIrConfigElement_t *)&event_data->ConfigElement[0]; - if (ioc->shost_recovery && - ioc->hba_mpi_version_belonged != MPI2_VERSION) { - for (i = 0; i < event_data->NumElements; i++, element++) { - if (element->ReasonCode == MPI2_EVENT_IR_CHANGE_RC_HIDE) - _scsih_ir_fastpath(ioc, - le16_to_cpu(element->PhysDiskDevHandle), - element->PhysDiskNum); - } - return; - } - - for (i = 0; i < event_data->NumElements; i++, element++) { - - switch (element->ReasonCode) { - case MPI2_EVENT_IR_CHANGE_RC_VOLUME_CREATED: - case MPI2_EVENT_IR_CHANGE_RC_ADDED: - if (!foreign_config) - _scsih_sas_volume_add(ioc, element); - break; - case MPI2_EVENT_IR_CHANGE_RC_VOLUME_DELETED: - case MPI2_EVENT_IR_CHANGE_RC_REMOVED: - if (!foreign_config) - _scsih_sas_volume_delete(ioc, - le16_to_cpu(element->VolDevHandle)); - break; - case MPI2_EVENT_IR_CHANGE_RC_PD_CREATED: - if (!ioc->is_warpdrive) - _scsih_sas_pd_hide(ioc, element); - break; - case MPI2_EVENT_IR_CHANGE_RC_PD_DELETED: - if (!ioc->is_warpdrive) - _scsih_sas_pd_expose(ioc, element); - break; - case MPI2_EVENT_IR_CHANGE_RC_HIDE: - if (!ioc->is_warpdrive) - _scsih_sas_pd_add(ioc, element); - break; - case MPI2_EVENT_IR_CHANGE_RC_UNHIDE: - if (!ioc->is_warpdrive) - _scsih_sas_pd_delete(ioc, element); - break; - } - } -} - -/** - * _scsih_sas_ir_volume_event - IR volume event - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_ir_volume_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - u64 wwid; - unsigned long flags; - struct _raid_device *raid_device; - u16 handle; - u32 state; - int rc; - Mpi2EventDataIrVolume_t *event_data = - (Mpi2EventDataIrVolume_t *) fw_event->event_data; - - if (ioc->shost_recovery) - return; - - if (event_data->ReasonCode != MPI2_EVENT_IR_VOLUME_RC_STATE_CHANGED) - return; - - handle = le16_to_cpu(event_data->VolDevHandle); - state = le32_to_cpu(event_data->NewValue); - if (!ioc->hide_ir_msg) - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n", - ioc->name, __func__, handle, - le32_to_cpu(event_data->PreviousValue), state)); - switch (state) { - case MPI2_RAID_VOL_STATE_MISSING: - case MPI2_RAID_VOL_STATE_FAILED: - _scsih_sas_volume_delete(ioc, handle); - break; - - case MPI2_RAID_VOL_STATE_ONLINE: - case MPI2_RAID_VOL_STATE_DEGRADED: - case MPI2_RAID_VOL_STATE_OPTIMAL: - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - - if (raid_device) - break; - - mpt3sas_config_get_volume_wwid(ioc, handle, &wwid); - if (!wwid) { - pr_err(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__); - break; - } - - raid_device = kzalloc(sizeof(struct _raid_device), GFP_KERNEL); - if (!raid_device) { - pr_err(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", ioc->name, - __FILE__, __LINE__, __func__); - break; - } - - raid_device->id = ioc->sas_id++; - raid_device->channel = RAID_CHANNEL; - raid_device->handle = handle; - raid_device->wwid = wwid; - _scsih_raid_device_add(ioc, raid_device); - rc = scsi_add_device(ioc->shost, RAID_CHANNEL, - raid_device->id, 0); - if (rc) - _scsih_raid_device_remove(ioc, raid_device); - break; - - case MPI2_RAID_VOL_STATE_INITIALIZING: - default: - break; - } -} - -/** - * _scsih_sas_ir_physical_disk_event - PD event - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_ir_physical_disk_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - u16 handle, parent_handle; - u32 state; - struct _sas_device *sas_device; - Mpi2ConfigReply_t mpi_reply; - Mpi2SasDevicePage0_t sas_device_pg0; - u32 ioc_status; - Mpi2EventDataIrPhysicalDisk_t *event_data = - (Mpi2EventDataIrPhysicalDisk_t *) fw_event->event_data; - u64 sas_address; - - if (ioc->shost_recovery) - return; - - if (event_data->ReasonCode != MPI2_EVENT_IR_PHYSDISK_RC_STATE_CHANGED) - return; - - handle = le16_to_cpu(event_data->PhysDiskDevHandle); - state = le32_to_cpu(event_data->NewValue); - - if (!ioc->hide_ir_msg) - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "%s: handle(0x%04x), old(0x%08x), new(0x%08x)\n", - ioc->name, __func__, handle, - le32_to_cpu(event_data->PreviousValue), state)); - - switch (state) { - case MPI2_RAID_PD_STATE_ONLINE: - case MPI2_RAID_PD_STATE_DEGRADED: - case MPI2_RAID_PD_STATE_REBUILDING: - case MPI2_RAID_PD_STATE_OPTIMAL: - case MPI2_RAID_PD_STATE_HOT_SPARE: - - if (!ioc->is_warpdrive) - set_bit(handle, ioc->pd_handles); - - sas_device = mpt3sas_get_sdev_by_handle(ioc, handle); - if (sas_device) { - sas_device_put(sas_device); - return; - } - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, - &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, - handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); - if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) - mpt3sas_transport_update_links(ioc, sas_address, handle, - sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); - - _scsih_add_device(ioc, handle, 0, 1); - - break; - - case MPI2_RAID_PD_STATE_OFFLINE: - case MPI2_RAID_PD_STATE_NOT_CONFIGURED: - case MPI2_RAID_PD_STATE_NOT_COMPATIBLE: - default: - break; - } -} - -/** - * _scsih_sas_ir_operation_status_event_debug - debug for IR op event - * @ioc: per adapter object - * @event_data: event data payload - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_ir_operation_status_event_debug(struct MPT3SAS_ADAPTER *ioc, - Mpi2EventDataIrOperationStatus_t *event_data) -{ - char *reason_str = NULL; - - switch (event_data->RAIDOperation) { - case MPI2_EVENT_IR_RAIDOP_RESYNC: - reason_str = "resync"; - break; - case MPI2_EVENT_IR_RAIDOP_ONLINE_CAP_EXPANSION: - reason_str = "online capacity expansion"; - break; - case MPI2_EVENT_IR_RAIDOP_CONSISTENCY_CHECK: - reason_str = "consistency check"; - break; - case MPI2_EVENT_IR_RAIDOP_BACKGROUND_INIT: - reason_str = "background init"; - break; - case MPI2_EVENT_IR_RAIDOP_MAKE_DATA_CONSISTENT: - reason_str = "make data consistent"; - break; - } - - if (!reason_str) - return; - - pr_info(MPT3SAS_FMT "raid operational status: (%s)" \ - "\thandle(0x%04x), percent complete(%d)\n", - ioc->name, reason_str, - le16_to_cpu(event_data->VolDevHandle), - event_data->PercentComplete); -} - -/** - * _scsih_sas_ir_operation_status_event - handle RAID operation events - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_scsih_sas_ir_operation_status_event(struct MPT3SAS_ADAPTER *ioc, - struct fw_event_work *fw_event) -{ - Mpi2EventDataIrOperationStatus_t *event_data = - (Mpi2EventDataIrOperationStatus_t *) - fw_event->event_data; - static struct _raid_device *raid_device; - unsigned long flags; - u16 handle; - - if ((ioc->logging_level & MPT_DEBUG_EVENT_WORK_TASK) && - (!ioc->hide_ir_msg)) - _scsih_sas_ir_operation_status_event_debug(ioc, - event_data); - - /* code added for raid transport support */ - if (event_data->RAIDOperation == MPI2_EVENT_IR_RAIDOP_RESYNC) { - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - handle = le16_to_cpu(event_data->VolDevHandle); - raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle); - if (raid_device) - raid_device->percent_complete = - event_data->PercentComplete; - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - } -} - -/** - * _scsih_prep_device_scan - initialize parameters prior to device scan - * @ioc: per adapter object - * - * Set the deleted flag prior to device scan. If the device is found during - * the scan, then we clear the deleted flag. - */ -static void -_scsih_prep_device_scan(struct MPT3SAS_ADAPTER *ioc) -{ - struct MPT3SAS_DEVICE *sas_device_priv_data; - struct scsi_device *sdev; - - shost_for_each_device(sdev, ioc->shost) { - sas_device_priv_data = sdev->hostdata; - if (sas_device_priv_data && sas_device_priv_data->sas_target) - sas_device_priv_data->sas_target->deleted = 1; - } -} - -/** - * _scsih_mark_responding_sas_device - mark a sas_devices as responding - * @ioc: per adapter object - * @sas_device_pg0: SAS Device page 0 - * - * After host reset, find out whether devices are still responding. - * Used in _scsih_remove_unresponsive_sas_devices. - * - * Return nothing. - */ -static void -_scsih_mark_responding_sas_device(struct MPT3SAS_ADAPTER *ioc, -Mpi2SasDevicePage0_t *sas_device_pg0) -{ - struct MPT3SAS_TARGET *sas_target_priv_data = NULL; - struct scsi_target *starget; - struct _sas_device *sas_device; - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - list_for_each_entry(sas_device, &ioc->sas_device_list, list) { - if ((sas_device->sas_address == sas_device_pg0->SASAddress) && - (sas_device->slot == sas_device_pg0->Slot)) { - sas_device->responding = 1; - starget = sas_device->starget; - if (starget && starget->hostdata) { - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->tm_busy = 0; - sas_target_priv_data->deleted = 0; - } else - sas_target_priv_data = NULL; - if (starget) { - starget_printk(KERN_INFO, starget, - "handle(0x%04x), sas_addr(0x%016llx)\n", - sas_device_pg0->DevHandle, - (unsigned long long) - sas_device->sas_address); - - if (sas_device->enclosure_handle != 0) - starget_printk(KERN_INFO, starget, - "enclosure logical id(0x%016llx)," - " slot(%d)\n", - (unsigned long long) - sas_device->enclosure_logical_id, - sas_device->slot); - } - if (sas_device_pg0->Flags & - MPI2_SAS_DEVICE0_FLAGS_ENCL_LEVEL_VALID) { - sas_device->enclosure_level = - le16_to_cpu(sas_device_pg0->EnclosureLevel); - memcpy(&sas_device->connector_name[0], - &sas_device_pg0->ConnectorName[0], 4); - } else { - sas_device->enclosure_level = 0; - sas_device->connector_name[0] = '\0'; - } - - if (sas_device->handle == sas_device_pg0->DevHandle) - goto out; - pr_info("\thandle changed from(0x%04x)!!!\n", - sas_device->handle); - sas_device->handle = sas_device_pg0->DevHandle; - if (sas_target_priv_data) - sas_target_priv_data->handle = - sas_device_pg0->DevHandle; - goto out; - } - } - out: - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); -} - -/** - * _scsih_search_responding_sas_devices - - * @ioc: per adapter object - * - * After host reset, find out whether devices are still responding. - * If not remove. - * - * Return nothing. - */ -static void -_scsih_search_responding_sas_devices(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2ConfigReply_t mpi_reply; - u16 ioc_status; - u16 handle; - u32 device_info; - - pr_info(MPT3SAS_FMT "search for end-devices: start\n", ioc->name); - - if (list_empty(&ioc->sas_device_list)) - goto out; - - handle = 0xFFFF; - while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, - &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, - handle))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - break; - handle = sas_device_pg0.DevHandle = - le16_to_cpu(sas_device_pg0.DevHandle); - device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); - if (!(_scsih_is_end_device(device_info))) - continue; - sas_device_pg0.SASAddress = - le64_to_cpu(sas_device_pg0.SASAddress); - sas_device_pg0.Slot = le16_to_cpu(sas_device_pg0.Slot); - _scsih_mark_responding_sas_device(ioc, &sas_device_pg0); - } - - out: - pr_info(MPT3SAS_FMT "search for end-devices: complete\n", - ioc->name); -} - -/** - * _scsih_mark_responding_raid_device - mark a raid_device as responding - * @ioc: per adapter object - * @wwid: world wide identifier for raid volume - * @handle: device handle - * - * After host reset, find out whether devices are still responding. - * Used in _scsih_remove_unresponsive_raid_devices. - * - * Return nothing. - */ -static void -_scsih_mark_responding_raid_device(struct MPT3SAS_ADAPTER *ioc, u64 wwid, - u16 handle) -{ - struct MPT3SAS_TARGET *sas_target_priv_data = NULL; - struct scsi_target *starget; - struct _raid_device *raid_device; - unsigned long flags; - - spin_lock_irqsave(&ioc->raid_device_lock, flags); - list_for_each_entry(raid_device, &ioc->raid_device_list, list) { - if (raid_device->wwid == wwid && raid_device->starget) { - starget = raid_device->starget; - if (starget && starget->hostdata) { - sas_target_priv_data = starget->hostdata; - sas_target_priv_data->deleted = 0; - } else - sas_target_priv_data = NULL; - raid_device->responding = 1; - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - starget_printk(KERN_INFO, raid_device->starget, - "handle(0x%04x), wwid(0x%016llx)\n", handle, - (unsigned long long)raid_device->wwid); - - /* - * WARPDRIVE: The handles of the PDs might have changed - * across the host reset so re-initialize the - * required data for Direct IO - */ - mpt3sas_init_warpdrive_properties(ioc, raid_device); - spin_lock_irqsave(&ioc->raid_device_lock, flags); - if (raid_device->handle == handle) { - spin_unlock_irqrestore(&ioc->raid_device_lock, - flags); - return; - } - pr_info("\thandle changed from(0x%04x)!!!\n", - raid_device->handle); - raid_device->handle = handle; - if (sas_target_priv_data) - sas_target_priv_data->handle = handle; - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - return; - } - } - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); -} - -/** - * _scsih_search_responding_raid_devices - - * @ioc: per adapter object - * - * After host reset, find out whether devices are still responding. - * If not remove. - * - * Return nothing. - */ -static void -_scsih_search_responding_raid_devices(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2RaidVolPage1_t volume_pg1; - Mpi2RaidVolPage0_t volume_pg0; - Mpi2RaidPhysDiskPage0_t pd_pg0; - Mpi2ConfigReply_t mpi_reply; - u16 ioc_status; - u16 handle; - u8 phys_disk_num; - - if (!ioc->ir_firmware) - return; - - pr_info(MPT3SAS_FMT "search for raid volumes: start\n", - ioc->name); - - if (list_empty(&ioc->raid_device_list)) - goto out; - - handle = 0xFFFF; - while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, - &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - break; - handle = le16_to_cpu(volume_pg1.DevHandle); - - if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, - &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, - sizeof(Mpi2RaidVolPage0_t))) - continue; - - if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL || - volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE || - volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) - _scsih_mark_responding_raid_device(ioc, - le64_to_cpu(volume_pg1.WWID), handle); - } - - /* refresh the pd_handles */ - if (!ioc->is_warpdrive) { - phys_disk_num = 0xFF; - memset(ioc->pd_handles, 0, ioc->pd_handles_sz); - while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply, - &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM, - phys_disk_num))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - break; - phys_disk_num = pd_pg0.PhysDiskNum; - handle = le16_to_cpu(pd_pg0.DevHandle); - set_bit(handle, ioc->pd_handles); - } - } - out: - pr_info(MPT3SAS_FMT "search for responding raid volumes: complete\n", - ioc->name); -} - -/** - * _scsih_mark_responding_expander - mark a expander as responding - * @ioc: per adapter object - * @sas_address: sas address - * @handle: - * - * After host reset, find out whether devices are still responding. - * Used in _scsih_remove_unresponsive_expanders. - * - * Return nothing. - */ -static void -_scsih_mark_responding_expander(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, - u16 handle) -{ - struct _sas_node *sas_expander; - unsigned long flags; - int i; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - list_for_each_entry(sas_expander, &ioc->sas_expander_list, list) { - if (sas_expander->sas_address != sas_address) - continue; - sas_expander->responding = 1; - if (sas_expander->handle == handle) - goto out; - pr_info("\texpander(0x%016llx): handle changed" \ - " from(0x%04x) to (0x%04x)!!!\n", - (unsigned long long)sas_expander->sas_address, - sas_expander->handle, handle); - sas_expander->handle = handle; - for (i = 0 ; i < sas_expander->num_phys ; i++) - sas_expander->phy[i].handle = handle; - goto out; - } - out: - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); -} - -/** - * _scsih_search_responding_expanders - - * @ioc: per adapter object - * - * After host reset, find out whether devices are still responding. - * If not remove. - * - * Return nothing. - */ -static void -_scsih_search_responding_expanders(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2ExpanderPage0_t expander_pg0; - Mpi2ConfigReply_t mpi_reply; - u16 ioc_status; - u64 sas_address; - u16 handle; - - pr_info(MPT3SAS_FMT "search for expanders: start\n", ioc->name); - - if (list_empty(&ioc->sas_expander_list)) - goto out; - - handle = 0xFFFF; - while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, - MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) { - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) - break; - - handle = le16_to_cpu(expander_pg0.DevHandle); - sas_address = le64_to_cpu(expander_pg0.SASAddress); - pr_info("\texpander present: handle(0x%04x), sas_addr(0x%016llx)\n", - handle, - (unsigned long long)sas_address); - _scsih_mark_responding_expander(ioc, sas_address, handle); - } - - out: - pr_info(MPT3SAS_FMT "search for expanders: complete\n", ioc->name); -} - -/** - * _scsih_remove_unresponding_sas_devices - removing unresponding devices - * @ioc: per adapter object - * - * Return nothing. - */ -static void -_scsih_remove_unresponding_sas_devices(struct MPT3SAS_ADAPTER *ioc) -{ - struct _sas_device *sas_device, *sas_device_next; - struct _sas_node *sas_expander, *sas_expander_next; - struct _raid_device *raid_device, *raid_device_next; - struct list_head tmp_list; - unsigned long flags; - LIST_HEAD(head); - - pr_info(MPT3SAS_FMT "removing unresponding devices: start\n", - ioc->name); - - /* removing unresponding end devices */ - pr_info(MPT3SAS_FMT "removing unresponding devices: end-devices\n", - ioc->name); - /* - * Iterate, pulling off devices marked as non-responding. We become the - * owner for the reference the list had on any object we prune. - */ - spin_lock_irqsave(&ioc->sas_device_lock, flags); - list_for_each_entry_safe(sas_device, sas_device_next, - &ioc->sas_device_list, list) { - if (!sas_device->responding) - list_move_tail(&sas_device->list, &head); - else - sas_device->responding = 0; - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - /* - * Now, uninitialize and remove the unresponding devices we pruned. - */ - list_for_each_entry_safe(sas_device, sas_device_next, &head, list) { - _scsih_remove_device(ioc, sas_device); - list_del_init(&sas_device->list); - sas_device_put(sas_device); - } - - /* removing unresponding volumes */ - if (ioc->ir_firmware) { - pr_info(MPT3SAS_FMT "removing unresponding devices: volumes\n", - ioc->name); - list_for_each_entry_safe(raid_device, raid_device_next, - &ioc->raid_device_list, list) { - if (!raid_device->responding) - _scsih_sas_volume_delete(ioc, - raid_device->handle); - else - raid_device->responding = 0; - } - } - - /* removing unresponding expanders */ - pr_info(MPT3SAS_FMT "removing unresponding devices: expanders\n", - ioc->name); - spin_lock_irqsave(&ioc->sas_node_lock, flags); - INIT_LIST_HEAD(&tmp_list); - list_for_each_entry_safe(sas_expander, sas_expander_next, - &ioc->sas_expander_list, list) { - if (!sas_expander->responding) - list_move_tail(&sas_expander->list, &tmp_list); - else - sas_expander->responding = 0; - } - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - list_for_each_entry_safe(sas_expander, sas_expander_next, &tmp_list, - list) { - list_del(&sas_expander->list); - _scsih_expander_node_remove(ioc, sas_expander); - } - - pr_info(MPT3SAS_FMT "removing unresponding devices: complete\n", - ioc->name); - - /* unblock devices */ - _scsih_ublock_io_all_device(ioc); -} - -static void -_scsih_refresh_expander_links(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_expander, u16 handle) -{ - Mpi2ExpanderPage1_t expander_pg1; - Mpi2ConfigReply_t mpi_reply; - int i; - - for (i = 0 ; i < sas_expander->num_phys ; i++) { - if ((mpt3sas_config_get_expander_pg1(ioc, &mpi_reply, - &expander_pg1, i, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return; - } - - mpt3sas_transport_update_links(ioc, sas_expander->sas_address, - le16_to_cpu(expander_pg1.AttachedDevHandle), i, - expander_pg1.NegotiatedLinkRate >> 4); - } -} - -/** - * _scsih_scan_for_devices_after_reset - scan for devices after host reset - * @ioc: per adapter object - * - * Return nothing. - */ -static void -_scsih_scan_for_devices_after_reset(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2ExpanderPage0_t expander_pg0; - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2RaidVolPage1_t volume_pg1; - Mpi2RaidVolPage0_t volume_pg0; - Mpi2RaidPhysDiskPage0_t pd_pg0; - Mpi2EventIrConfigElement_t element; - Mpi2ConfigReply_t mpi_reply; - u8 phys_disk_num; - u16 ioc_status; - u16 handle, parent_handle; - u64 sas_address; - struct _sas_device *sas_device; - struct _sas_node *expander_device; - static struct _raid_device *raid_device; - u8 retry_count; - unsigned long flags; - - pr_info(MPT3SAS_FMT "scan devices: start\n", ioc->name); - - _scsih_sas_host_refresh(ioc); - - pr_info(MPT3SAS_FMT "\tscan devices: expanders start\n", ioc->name); - - /* expanders */ - handle = 0xFFFF; - while (!(mpt3sas_config_get_expander_pg0(ioc, &mpi_reply, &expander_pg0, - MPI2_SAS_EXPAND_PGAD_FORM_GET_NEXT_HNDL, handle))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_info(MPT3SAS_FMT "\tbreak from expander scan: " \ - "ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, ioc_status, - le32_to_cpu(mpi_reply.IOCLogInfo)); - break; - } - handle = le16_to_cpu(expander_pg0.DevHandle); - spin_lock_irqsave(&ioc->sas_node_lock, flags); - expander_device = mpt3sas_scsih_expander_find_by_sas_address( - ioc, le64_to_cpu(expander_pg0.SASAddress)); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - if (expander_device) - _scsih_refresh_expander_links(ioc, expander_device, - handle); - else { - pr_info(MPT3SAS_FMT "\tBEFORE adding expander: " \ - "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name, - handle, (unsigned long long) - le64_to_cpu(expander_pg0.SASAddress)); - _scsih_expander_add(ioc, handle); - pr_info(MPT3SAS_FMT "\tAFTER adding expander: " \ - "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name, - handle, (unsigned long long) - le64_to_cpu(expander_pg0.SASAddress)); - } - } - - pr_info(MPT3SAS_FMT "\tscan devices: expanders complete\n", - ioc->name); - - if (!ioc->ir_firmware) - goto skip_to_sas; - - pr_info(MPT3SAS_FMT "\tscan devices: phys disk start\n", ioc->name); - - /* phys disk */ - phys_disk_num = 0xFF; - while (!(mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply, - &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_GET_NEXT_PHYSDISKNUM, - phys_disk_num))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_info(MPT3SAS_FMT "\tbreak from phys disk scan: "\ - "ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, ioc_status, - le32_to_cpu(mpi_reply.IOCLogInfo)); - break; - } - phys_disk_num = pd_pg0.PhysDiskNum; - handle = le16_to_cpu(pd_pg0.DevHandle); - sas_device = mpt3sas_get_sdev_by_handle(ioc, handle); - if (sas_device) { - sas_device_put(sas_device); - continue; - } - if (mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, - &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, - handle) != 0) - continue; - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_info(MPT3SAS_FMT "\tbreak from phys disk scan " \ - "ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, ioc_status, - le32_to_cpu(mpi_reply.IOCLogInfo)); - break; - } - parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); - if (!_scsih_get_sas_address(ioc, parent_handle, - &sas_address)) { - pr_info(MPT3SAS_FMT "\tBEFORE adding phys disk: " \ - " handle (0x%04x), sas_addr(0x%016llx)\n", - ioc->name, handle, (unsigned long long) - le64_to_cpu(sas_device_pg0.SASAddress)); - mpt3sas_transport_update_links(ioc, sas_address, - handle, sas_device_pg0.PhyNum, - MPI2_SAS_NEG_LINK_RATE_1_5); - set_bit(handle, ioc->pd_handles); - retry_count = 0; - /* This will retry adding the end device. - * _scsih_add_device() will decide on retries and - * return "1" when it should be retried - */ - while (_scsih_add_device(ioc, handle, retry_count++, - 1)) { - ssleep(1); - } - pr_info(MPT3SAS_FMT "\tAFTER adding phys disk: " \ - " handle (0x%04x), sas_addr(0x%016llx)\n", - ioc->name, handle, (unsigned long long) - le64_to_cpu(sas_device_pg0.SASAddress)); - } - } - - pr_info(MPT3SAS_FMT "\tscan devices: phys disk complete\n", - ioc->name); - - pr_info(MPT3SAS_FMT "\tscan devices: volumes start\n", ioc->name); - - /* volumes */ - handle = 0xFFFF; - while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, - &volume_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \ - "ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, ioc_status, - le32_to_cpu(mpi_reply.IOCLogInfo)); - break; - } - handle = le16_to_cpu(volume_pg1.DevHandle); - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = _scsih_raid_device_find_by_wwid(ioc, - le64_to_cpu(volume_pg1.WWID)); - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - if (raid_device) - continue; - if (mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, - &volume_pg0, MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, handle, - sizeof(Mpi2RaidVolPage0_t))) - continue; - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_info(MPT3SAS_FMT "\tbreak from volume scan: " \ - "ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, ioc_status, - le32_to_cpu(mpi_reply.IOCLogInfo)); - break; - } - if (volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_OPTIMAL || - volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_ONLINE || - volume_pg0.VolumeState == MPI2_RAID_VOL_STATE_DEGRADED) { - memset(&element, 0, sizeof(Mpi2EventIrConfigElement_t)); - element.ReasonCode = MPI2_EVENT_IR_CHANGE_RC_ADDED; - element.VolDevHandle = volume_pg1.DevHandle; - pr_info(MPT3SAS_FMT - "\tBEFORE adding volume: handle (0x%04x)\n", - ioc->name, volume_pg1.DevHandle); - _scsih_sas_volume_add(ioc, &element); - pr_info(MPT3SAS_FMT - "\tAFTER adding volume: handle (0x%04x)\n", - ioc->name, volume_pg1.DevHandle); - } - } - - pr_info(MPT3SAS_FMT "\tscan devices: volumes complete\n", - ioc->name); - - skip_to_sas: - - pr_info(MPT3SAS_FMT "\tscan devices: end devices start\n", - ioc->name); - - /* sas devices */ - handle = 0xFFFF; - while (!(mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, - &sas_device_pg0, MPI2_SAS_DEVICE_PGAD_FORM_GET_NEXT_HANDLE, - handle))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_info(MPT3SAS_FMT "\tbreak from end device scan:"\ - " ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, ioc_status, - le32_to_cpu(mpi_reply.IOCLogInfo)); - break; - } - handle = le16_to_cpu(sas_device_pg0.DevHandle); - if (!(_scsih_is_end_device( - le32_to_cpu(sas_device_pg0.DeviceInfo)))) - continue; - sas_device = mpt3sas_get_sdev_by_addr(ioc, - le64_to_cpu(sas_device_pg0.SASAddress)); - if (sas_device) { - sas_device_put(sas_device); - continue; - } - parent_handle = le16_to_cpu(sas_device_pg0.ParentDevHandle); - if (!_scsih_get_sas_address(ioc, parent_handle, &sas_address)) { - pr_info(MPT3SAS_FMT "\tBEFORE adding end device: " \ - "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name, - handle, (unsigned long long) - le64_to_cpu(sas_device_pg0.SASAddress)); - mpt3sas_transport_update_links(ioc, sas_address, handle, - sas_device_pg0.PhyNum, MPI2_SAS_NEG_LINK_RATE_1_5); - retry_count = 0; - /* This will retry adding the end device. - * _scsih_add_device() will decide on retries and - * return "1" when it should be retried - */ - while (_scsih_add_device(ioc, handle, retry_count++, - 0)) { - ssleep(1); - } - pr_info(MPT3SAS_FMT "\tAFTER adding end device: " \ - "handle (0x%04x), sas_addr(0x%016llx)\n", ioc->name, - handle, (unsigned long long) - le64_to_cpu(sas_device_pg0.SASAddress)); - } - } - pr_info(MPT3SAS_FMT "\tscan devices: end devices complete\n", - ioc->name); - - pr_info(MPT3SAS_FMT "scan devices: complete\n", ioc->name); -} -/** - * mpt3sas_scsih_reset_handler - reset callback handler (for scsih) - * @ioc: per adapter object - * @reset_phase: phase - * - * The handler for doing any required cleanup or initialization. - * - * The reset phase can be MPT3_IOC_PRE_RESET, MPT3_IOC_AFTER_RESET, - * MPT3_IOC_DONE_RESET - * - * Return nothing. - */ -void -mpt3sas_scsih_reset_handler(struct MPT3SAS_ADAPTER *ioc, int reset_phase) -{ - switch (reset_phase) { - case MPT3_IOC_PRE_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_PRE_RESET\n", ioc->name, __func__)); - break; - case MPT3_IOC_AFTER_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_AFTER_RESET\n", ioc->name, __func__)); - if (ioc->scsih_cmds.status & MPT3_CMD_PENDING) { - ioc->scsih_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->scsih_cmds.smid); - complete(&ioc->scsih_cmds.done); - } - if (ioc->tm_cmds.status & MPT3_CMD_PENDING) { - ioc->tm_cmds.status |= MPT3_CMD_RESET; - mpt3sas_base_free_smid(ioc, ioc->tm_cmds.smid); - complete(&ioc->tm_cmds.done); - } - - _scsih_fw_event_cleanup_queue(ioc); - _scsih_flush_running_cmds(ioc); - break; - case MPT3_IOC_DONE_RESET: - dtmprintk(ioc, pr_info(MPT3SAS_FMT - "%s: MPT3_IOC_DONE_RESET\n", ioc->name, __func__)); - if ((!ioc->is_driver_loading) && !(disable_discovery > 0 && - !ioc->sas_hba.num_phys)) { - _scsih_prep_device_scan(ioc); - _scsih_search_responding_sas_devices(ioc); - _scsih_search_responding_raid_devices(ioc); - _scsih_search_responding_expanders(ioc); - _scsih_error_recovery_delete_devices(ioc); - } - break; - } -} - -/** - * _mpt3sas_fw_work - delayed task for processing firmware events - * @ioc: per adapter object - * @fw_event: The fw_event_work object - * Context: user. - * - * Return nothing. - */ -static void -_mpt3sas_fw_work(struct MPT3SAS_ADAPTER *ioc, struct fw_event_work *fw_event) -{ - _scsih_fw_event_del_from_list(ioc, fw_event); - - /* the queue is being flushed so ignore this event */ - if (ioc->remove_host || ioc->pci_error_recovery) { - fw_event_work_put(fw_event); - return; - } - - switch (fw_event->event) { - case MPT3SAS_PROCESS_TRIGGER_DIAG: - mpt3sas_process_trigger_data(ioc, - (struct SL_WH_TRIGGERS_EVENT_DATA_T *) - fw_event->event_data); - break; - case MPT3SAS_REMOVE_UNRESPONDING_DEVICES: - while (scsi_host_in_recovery(ioc->shost) || - ioc->shost_recovery) { - /* - * If we're unloading, bail. Otherwise, this can become - * an infinite loop. - */ - if (ioc->remove_host) - goto out; - ssleep(1); - } - _scsih_remove_unresponding_sas_devices(ioc); - _scsih_scan_for_devices_after_reset(ioc); - break; - case MPT3SAS_PORT_ENABLE_COMPLETE: - ioc->start_scan = 0; - if (missing_delay[0] != -1 && missing_delay[1] != -1) - mpt3sas_base_update_missing_delay(ioc, missing_delay[0], - missing_delay[1]); - dewtprintk(ioc, pr_info(MPT3SAS_FMT - "port enable: complete from worker thread\n", - ioc->name)); - break; - case MPT3SAS_TURN_ON_PFA_LED: - _scsih_turn_on_pfa_led(ioc, fw_event->device_handle); - break; - case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: - _scsih_sas_topology_change_event(ioc, fw_event); - break; - case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: - _scsih_sas_device_status_change_event(ioc, fw_event); - break; - case MPI2_EVENT_SAS_DISCOVERY: - _scsih_sas_discovery_event(ioc, fw_event); - break; - case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: - _scsih_sas_broadcast_primitive_event(ioc, fw_event); - break; - case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: - _scsih_sas_enclosure_dev_status_change_event(ioc, - fw_event); - break; - case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: - _scsih_sas_ir_config_change_event(ioc, fw_event); - break; - case MPI2_EVENT_IR_VOLUME: - _scsih_sas_ir_volume_event(ioc, fw_event); - break; - case MPI2_EVENT_IR_PHYSICAL_DISK: - _scsih_sas_ir_physical_disk_event(ioc, fw_event); - break; - case MPI2_EVENT_IR_OPERATION_STATUS: - _scsih_sas_ir_operation_status_event(ioc, fw_event); - break; - } -out: - fw_event_work_put(fw_event); -} - -/** - * _firmware_event_work - * @ioc: per adapter object - * @work: The fw_event_work object - * Context: user. - * - * wrappers for the work thread handling firmware events - * - * Return nothing. - */ - -static void -_firmware_event_work(struct work_struct *work) -{ - struct fw_event_work *fw_event = container_of(work, - struct fw_event_work, work); - - _mpt3sas_fw_work(fw_event->ioc, fw_event); -} - -/** - * mpt3sas_scsih_event_callback - firmware event handler (called at ISR time) - * @ioc: per adapter object - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * Context: interrupt. - * - * This function merely adds a new work task into ioc->firmware_event_thread. - * The tasks are worked from _firmware_event_work in user context. - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_scsih_event_callback(struct MPT3SAS_ADAPTER *ioc, u8 msix_index, - u32 reply) -{ - struct fw_event_work *fw_event; - Mpi2EventNotificationReply_t *mpi_reply; - u16 event; - u16 sz; - - /* events turned off due to host reset or driver unloading */ - if (ioc->remove_host || ioc->pci_error_recovery) - return 1; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - - if (unlikely(!mpi_reply)) { - pr_err(MPT3SAS_FMT "mpi_reply not valid at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return 1; - } - - event = le16_to_cpu(mpi_reply->Event); - - if (event != MPI2_EVENT_LOG_ENTRY_ADDED) - mpt3sas_trigger_event(ioc, event, 0); - - switch (event) { - /* handle these */ - case MPI2_EVENT_SAS_BROADCAST_PRIMITIVE: - { - Mpi2EventDataSasBroadcastPrimitive_t *baen_data = - (Mpi2EventDataSasBroadcastPrimitive_t *) - mpi_reply->EventData; - - if (baen_data->Primitive != - MPI2_EVENT_PRIMITIVE_ASYNCHRONOUS_EVENT) - return 1; - - if (ioc->broadcast_aen_busy) { - ioc->broadcast_aen_pending++; - return 1; - } else - ioc->broadcast_aen_busy = 1; - break; - } - - case MPI2_EVENT_SAS_TOPOLOGY_CHANGE_LIST: - _scsih_check_topo_delete_events(ioc, - (Mpi2EventDataSasTopologyChangeList_t *) - mpi_reply->EventData); - break; - case MPI2_EVENT_IR_CONFIGURATION_CHANGE_LIST: - _scsih_check_ir_config_unhide_events(ioc, - (Mpi2EventDataIrConfigChangeList_t *) - mpi_reply->EventData); - break; - case MPI2_EVENT_IR_VOLUME: - _scsih_check_volume_delete_events(ioc, - (Mpi2EventDataIrVolume_t *) - mpi_reply->EventData); - break; - case MPI2_EVENT_LOG_ENTRY_ADDED: - { - Mpi2EventDataLogEntryAdded_t *log_entry; - u32 *log_code; - - if (!ioc->is_warpdrive) - break; - - log_entry = (Mpi2EventDataLogEntryAdded_t *) - mpi_reply->EventData; - log_code = (u32 *)log_entry->LogData; - - if (le16_to_cpu(log_entry->LogEntryQualifier) - != MPT2_WARPDRIVE_LOGENTRY) - break; - - switch (le32_to_cpu(*log_code)) { - case MPT2_WARPDRIVE_LC_SSDT: - pr_warn(MPT3SAS_FMT "WarpDrive Warning: " - "IO Throttling has occurred in the WarpDrive " - "subsystem. Check WarpDrive documentation for " - "additional details.\n", ioc->name); - break; - case MPT2_WARPDRIVE_LC_SSDLW: - pr_warn(MPT3SAS_FMT "WarpDrive Warning: " - "Program/Erase Cycles for the WarpDrive subsystem " - "in degraded range. Check WarpDrive documentation " - "for additional details.\n", ioc->name); - break; - case MPT2_WARPDRIVE_LC_SSDLF: - pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: " - "There are no Program/Erase Cycles for the " - "WarpDrive subsystem. The storage device will be " - "in read-only mode. Check WarpDrive documentation " - "for additional details.\n", ioc->name); - break; - case MPT2_WARPDRIVE_LC_BRMF: - pr_err(MPT3SAS_FMT "WarpDrive Fatal Error: " - "The Backup Rail Monitor has failed on the " - "WarpDrive subsystem. Check WarpDrive " - "documentation for additional details.\n", - ioc->name); - break; - } - - break; - } - case MPI2_EVENT_SAS_DEVICE_STATUS_CHANGE: - case MPI2_EVENT_IR_OPERATION_STATUS: - case MPI2_EVENT_SAS_DISCOVERY: - case MPI2_EVENT_SAS_ENCL_DEVICE_STATUS_CHANGE: - case MPI2_EVENT_IR_PHYSICAL_DISK: - break; - - case MPI2_EVENT_TEMP_THRESHOLD: - _scsih_temp_threshold_events(ioc, - (Mpi2EventDataTemperature_t *) - mpi_reply->EventData); - break; - - default: /* ignore the rest */ - return 1; - } - - sz = le16_to_cpu(mpi_reply->EventDataLength) * 4; - fw_event = alloc_fw_event_work(sz); - if (!fw_event) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return 1; - } - - memcpy(fw_event->event_data, mpi_reply->EventData, sz); - fw_event->ioc = ioc; - fw_event->VF_ID = mpi_reply->VF_ID; - fw_event->VP_ID = mpi_reply->VP_ID; - fw_event->event = event; - _scsih_fw_event_add(ioc, fw_event); - fw_event_work_put(fw_event); - return 1; -} - -/** - * _scsih_expander_node_remove - removing expander device from list. - * @ioc: per adapter object - * @sas_expander: the sas_device object - * Context: Calling function should acquire ioc->sas_node_lock. - * - * Removing object and freeing associated memory from the - * ioc->sas_expander_list. - * - * Return nothing. - */ -static void -_scsih_expander_node_remove(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_expander) -{ - struct _sas_port *mpt3sas_port, *next; - - /* remove sibling ports attached to this expander */ - list_for_each_entry_safe(mpt3sas_port, next, - &sas_expander->sas_port_list, port_list) { - if (ioc->shost_recovery) - return; - if (mpt3sas_port->remote_identify.device_type == - SAS_END_DEVICE) - mpt3sas_device_remove_by_sas_address(ioc, - mpt3sas_port->remote_identify.sas_address); - else if (mpt3sas_port->remote_identify.device_type == - SAS_EDGE_EXPANDER_DEVICE || - mpt3sas_port->remote_identify.device_type == - SAS_FANOUT_EXPANDER_DEVICE) - mpt3sas_expander_remove(ioc, - mpt3sas_port->remote_identify.sas_address); - } - - mpt3sas_transport_port_remove(ioc, sas_expander->sas_address, - sas_expander->sas_address_parent); - - pr_info(MPT3SAS_FMT - "expander_remove: handle(0x%04x), sas_addr(0x%016llx)\n", - ioc->name, - sas_expander->handle, (unsigned long long) - sas_expander->sas_address); - - kfree(sas_expander->phy); - kfree(sas_expander); -} - -/** - * _scsih_ir_shutdown - IR shutdown notification - * @ioc: per adapter object - * - * Sending RAID Action to alert the Integrated RAID subsystem of the IOC that - * the host system is shutting down. - * - * Return nothing. - */ -static void -_scsih_ir_shutdown(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2RaidActionRequest_t *mpi_request; - Mpi2RaidActionReply_t *mpi_reply; - u16 smid; - - /* is IR firmware build loaded ? */ - if (!ioc->ir_firmware) - return; - - /* are there any volumes ? */ - if (list_empty(&ioc->raid_device_list)) - return; - - mutex_lock(&ioc->scsih_cmds.mutex); - - if (ioc->scsih_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: scsih_cmd in use\n", - ioc->name, __func__); - goto out; - } - ioc->scsih_cmds.status = MPT3_CMD_PENDING; - - smid = mpt3sas_base_get_smid(ioc, ioc->scsih_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; - goto out; - } - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->scsih_cmds.smid = smid; - memset(mpi_request, 0, sizeof(Mpi2RaidActionRequest_t)); - - mpi_request->Function = MPI2_FUNCTION_RAID_ACTION; - mpi_request->Action = MPI2_RAID_ACTION_SYSTEM_SHUTDOWN_INITIATED; - - if (!ioc->hide_ir_msg) - pr_info(MPT3SAS_FMT "IR shutdown (sending)\n", ioc->name); - init_completion(&ioc->scsih_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - wait_for_completion_timeout(&ioc->scsih_cmds.done, 10*HZ); - - if (!(ioc->scsih_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - goto out; - } - - if (ioc->scsih_cmds.status & MPT3_CMD_REPLY_VALID) { - mpi_reply = ioc->scsih_cmds.reply; - if (!ioc->hide_ir_msg) - pr_info(MPT3SAS_FMT "IR shutdown " - "(complete): ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, le16_to_cpu(mpi_reply->IOCStatus), - le32_to_cpu(mpi_reply->IOCLogInfo)); - } - - out: - ioc->scsih_cmds.status = MPT3_CMD_NOT_USED; - mutex_unlock(&ioc->scsih_cmds.mutex); -} - -/** - * scsih_remove - detach and remove add host - * @pdev: PCI device struct - * - * Routine called when unloading the driver. - * Return nothing. - */ -void scsih_remove(struct pci_dev *pdev) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - struct _sas_port *mpt3sas_port, *next_port; - struct _raid_device *raid_device, *next; - struct MPT3SAS_TARGET *sas_target_priv_data; - struct workqueue_struct *wq; - unsigned long flags; - - ioc->remove_host = 1; - _scsih_fw_event_cleanup_queue(ioc); - - spin_lock_irqsave(&ioc->fw_event_lock, flags); - wq = ioc->firmware_event_thread; - ioc->firmware_event_thread = NULL; - spin_unlock_irqrestore(&ioc->fw_event_lock, flags); - if (wq) - destroy_workqueue(wq); - - /* release all the volumes */ - _scsih_ir_shutdown(ioc); - list_for_each_entry_safe(raid_device, next, &ioc->raid_device_list, - list) { - if (raid_device->starget) { - sas_target_priv_data = - raid_device->starget->hostdata; - sas_target_priv_data->deleted = 1; - scsi_remove_target(&raid_device->starget->dev); - } - pr_info(MPT3SAS_FMT "removing handle(0x%04x), wwid(0x%016llx)\n", - ioc->name, raid_device->handle, - (unsigned long long) raid_device->wwid); - _scsih_raid_device_remove(ioc, raid_device); - } - - /* free ports attached to the sas_host */ - list_for_each_entry_safe(mpt3sas_port, next_port, - &ioc->sas_hba.sas_port_list, port_list) { - if (mpt3sas_port->remote_identify.device_type == - SAS_END_DEVICE) - mpt3sas_device_remove_by_sas_address(ioc, - mpt3sas_port->remote_identify.sas_address); - else if (mpt3sas_port->remote_identify.device_type == - SAS_EDGE_EXPANDER_DEVICE || - mpt3sas_port->remote_identify.device_type == - SAS_FANOUT_EXPANDER_DEVICE) - mpt3sas_expander_remove(ioc, - mpt3sas_port->remote_identify.sas_address); - } - - /* free phys attached to the sas_host */ - if (ioc->sas_hba.num_phys) { - kfree(ioc->sas_hba.phy); - ioc->sas_hba.phy = NULL; - ioc->sas_hba.num_phys = 0; - } - - sas_remove_host(shost); - scsi_remove_host(shost); - mpt3sas_base_detach(ioc); - spin_lock(&gioc_lock); - list_del(&ioc->list); - spin_unlock(&gioc_lock); - scsi_host_put(shost); -} - -/** - * scsih_shutdown - routine call during system shutdown - * @pdev: PCI device struct - * - * Return nothing. - */ -void -scsih_shutdown(struct pci_dev *pdev) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - struct workqueue_struct *wq; - unsigned long flags; - - ioc->remove_host = 1; - _scsih_fw_event_cleanup_queue(ioc); - - spin_lock_irqsave(&ioc->fw_event_lock, flags); - wq = ioc->firmware_event_thread; - ioc->firmware_event_thread = NULL; - spin_unlock_irqrestore(&ioc->fw_event_lock, flags); - if (wq) - destroy_workqueue(wq); - - _scsih_ir_shutdown(ioc); - mpt3sas_base_detach(ioc); -} - - -/** - * _scsih_probe_boot_devices - reports 1st device - * @ioc: per adapter object - * - * If specified in bios page 2, this routine reports the 1st - * device scsi-ml or sas transport for persistent boot device - * purposes. Please refer to function _scsih_determine_boot_device() - */ -static void -_scsih_probe_boot_devices(struct MPT3SAS_ADAPTER *ioc) -{ - u8 is_raid; - void *device; - struct _sas_device *sas_device; - struct _raid_device *raid_device; - u16 handle; - u64 sas_address_parent; - u64 sas_address; - unsigned long flags; - int rc; - - /* no Bios, return immediately */ - if (!ioc->bios_pg3.BiosVersion) - return; - - device = NULL; - is_raid = 0; - if (ioc->req_boot_device.device) { - device = ioc->req_boot_device.device; - is_raid = ioc->req_boot_device.is_raid; - } else if (ioc->req_alt_boot_device.device) { - device = ioc->req_alt_boot_device.device; - is_raid = ioc->req_alt_boot_device.is_raid; - } else if (ioc->current_boot_device.device) { - device = ioc->current_boot_device.device; - is_raid = ioc->current_boot_device.is_raid; - } - - if (!device) - return; - - if (is_raid) { - raid_device = device; - rc = scsi_add_device(ioc->shost, RAID_CHANNEL, - raid_device->id, 0); - if (rc) - _scsih_raid_device_remove(ioc, raid_device); - } else { - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = device; - handle = sas_device->handle; - sas_address_parent = sas_device->sas_address_parent; - sas_address = sas_device->sas_address; - list_move_tail(&sas_device->list, &ioc->sas_device_list); - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - if (ioc->hide_drives) - return; - if (!mpt3sas_transport_port_add(ioc, handle, - sas_address_parent)) { - _scsih_sas_device_remove(ioc, sas_device); - } else if (!sas_device->starget) { - if (!ioc->is_driver_loading) { - mpt3sas_transport_port_remove(ioc, - sas_address, - sas_address_parent); - _scsih_sas_device_remove(ioc, sas_device); - } - } - } -} - -/** - * _scsih_probe_raid - reporting raid volumes to scsi-ml - * @ioc: per adapter object - * - * Called during initial loading of the driver. - */ -static void -_scsih_probe_raid(struct MPT3SAS_ADAPTER *ioc) -{ - struct _raid_device *raid_device, *raid_next; - int rc; - - list_for_each_entry_safe(raid_device, raid_next, - &ioc->raid_device_list, list) { - if (raid_device->starget) - continue; - rc = scsi_add_device(ioc->shost, RAID_CHANNEL, - raid_device->id, 0); - if (rc) - _scsih_raid_device_remove(ioc, raid_device); - } -} - -static struct _sas_device *get_next_sas_device(struct MPT3SAS_ADAPTER *ioc) -{ - struct _sas_device *sas_device = NULL; - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - if (!list_empty(&ioc->sas_device_init_list)) { - sas_device = list_first_entry(&ioc->sas_device_init_list, - struct _sas_device, list); - sas_device_get(sas_device); - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - - return sas_device; -} - -static void sas_device_make_active(struct MPT3SAS_ADAPTER *ioc, - struct _sas_device *sas_device) -{ - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - - /* - * Since we dropped the lock during the call to port_add(), we need to - * be careful here that somebody else didn't move or delete this item - * while we were busy with other things. - * - * If it was on the list, we need a put() for the reference the list - * had. Either way, we need a get() for the destination list. - */ - if (!list_empty(&sas_device->list)) { - list_del_init(&sas_device->list); - sas_device_put(sas_device); - } - - sas_device_get(sas_device); - list_add_tail(&sas_device->list, &ioc->sas_device_list); - - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); -} - -/** - * _scsih_probe_sas - reporting sas devices to sas transport - * @ioc: per adapter object - * - * Called during initial loading of the driver. - */ -static void -_scsih_probe_sas(struct MPT3SAS_ADAPTER *ioc) -{ - struct _sas_device *sas_device; - - if (ioc->hide_drives) - return; - - while ((sas_device = get_next_sas_device(ioc))) { - if (!mpt3sas_transport_port_add(ioc, sas_device->handle, - sas_device->sas_address_parent)) { - _scsih_sas_device_remove(ioc, sas_device); - sas_device_put(sas_device); - continue; - } else if (!sas_device->starget) { - /* - * When asyn scanning is enabled, its not possible to - * remove devices while scanning is turned on due to an - * oops in scsi_sysfs_add_sdev()->add_device()-> - * sysfs_addrm_start() - */ - if (!ioc->is_driver_loading) { - mpt3sas_transport_port_remove(ioc, - sas_device->sas_address, - sas_device->sas_address_parent); - _scsih_sas_device_remove(ioc, sas_device); - sas_device_put(sas_device); - continue; - } - } - sas_device_make_active(ioc, sas_device); - sas_device_put(sas_device); - } -} - -/** - * _scsih_probe_devices - probing for devices - * @ioc: per adapter object - * - * Called during initial loading of the driver. - */ -static void -_scsih_probe_devices(struct MPT3SAS_ADAPTER *ioc) -{ - u16 volume_mapping_flags; - - if (!(ioc->facts.ProtocolFlags & MPI2_IOCFACTS_PROTOCOL_SCSI_INITIATOR)) - return; /* return when IOC doesn't support initiator mode */ - - _scsih_probe_boot_devices(ioc); - - if (ioc->ir_firmware) { - volume_mapping_flags = - le16_to_cpu(ioc->ioc_pg8.IRVolumeMappingFlags) & - MPI2_IOCPAGE8_IRFLAGS_MASK_VOLUME_MAPPING_MODE; - if (volume_mapping_flags == - MPI2_IOCPAGE8_IRFLAGS_LOW_VOLUME_MAPPING) { - _scsih_probe_raid(ioc); - _scsih_probe_sas(ioc); - } else { - _scsih_probe_sas(ioc); - _scsih_probe_raid(ioc); - } - } else - _scsih_probe_sas(ioc); -} - -/** - * scsih_scan_start - scsi lld callback for .scan_start - * @shost: SCSI host pointer - * - * The shost has the ability to discover targets on its own instead - * of scanning the entire bus. In our implemention, we will kick off - * firmware discovery. - */ -void -scsih_scan_start(struct Scsi_Host *shost) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - int rc; - if (diag_buffer_enable != -1 && diag_buffer_enable != 0) - mpt3sas_enable_diag_buffer(ioc, diag_buffer_enable); - - if (disable_discovery > 0) - return; - - ioc->start_scan = 1; - rc = mpt3sas_port_enable(ioc); - - if (rc != 0) - pr_info(MPT3SAS_FMT "port enable: FAILED\n", ioc->name); -} - -/** - * scsih_scan_finished - scsi lld callback for .scan_finished - * @shost: SCSI host pointer - * @time: elapsed time of the scan in jiffies - * - * This function will be called periodicallyn until it returns 1 with the - * scsi_host and the elapsed time of the scan in jiffies. In our implemention, - * we wait for firmware discovery to complete, then return 1. - */ -int -scsih_scan_finished(struct Scsi_Host *shost, unsigned long time) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - if (disable_discovery > 0) { - ioc->is_driver_loading = 0; - ioc->wait_for_discovery_to_complete = 0; - return 1; - } - - if (time >= (300 * HZ)) { - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - pr_info(MPT3SAS_FMT - "port enable: FAILED with timeout (timeout=300s)\n", - ioc->name); - ioc->is_driver_loading = 0; - return 1; - } - - if (ioc->start_scan) - return 0; - - if (ioc->start_scan_failed) { - pr_info(MPT3SAS_FMT - "port enable: FAILED with (ioc_status=0x%08x)\n", - ioc->name, ioc->start_scan_failed); - ioc->is_driver_loading = 0; - ioc->wait_for_discovery_to_complete = 0; - ioc->remove_host = 1; - return 1; - } - - pr_info(MPT3SAS_FMT "port enable: SUCCESS\n", ioc->name); - ioc->base_cmds.status = MPT3_CMD_NOT_USED; - - if (ioc->wait_for_discovery_to_complete) { - ioc->wait_for_discovery_to_complete = 0; - _scsih_probe_devices(ioc); - } - mpt3sas_base_start_watchdog(ioc); - ioc->is_driver_loading = 0; - return 1; -} - -/* shost template for SAS 2.0 HBA devices */ -static struct scsi_host_template mpt2sas_driver_template = { - .module = THIS_MODULE, - .name = "Fusion MPT SAS Host", - .proc_name = MPT2SAS_DRIVER_NAME, - .queuecommand = scsih_qcmd, - .target_alloc = scsih_target_alloc, - .slave_alloc = scsih_slave_alloc, - .slave_configure = scsih_slave_configure, - .target_destroy = scsih_target_destroy, - .slave_destroy = scsih_slave_destroy, - .scan_finished = scsih_scan_finished, - .scan_start = scsih_scan_start, - .change_queue_depth = scsih_change_queue_depth, - .eh_abort_handler = scsih_abort, - .eh_device_reset_handler = scsih_dev_reset, - .eh_target_reset_handler = scsih_target_reset, - .eh_host_reset_handler = scsih_host_reset, - .bios_param = scsih_bios_param, - .can_queue = 1, - .this_id = -1, - .sg_tablesize = MPT2SAS_SG_DEPTH, - .max_sectors = 32767, - .cmd_per_lun = 7, - .use_clustering = ENABLE_CLUSTERING, - .shost_attrs = mpt3sas_host_attrs, - .sdev_attrs = mpt3sas_dev_attrs, - .track_queue_depth = 1, -}; - -/* raid transport support for SAS 2.0 HBA devices */ -static struct raid_function_template mpt2sas_raid_functions = { - .cookie = &mpt2sas_driver_template, - .is_raid = scsih_is_raid, - .get_resync = scsih_get_resync, - .get_state = scsih_get_state, -}; - -/* shost template for SAS 3.0 HBA devices */ -static struct scsi_host_template mpt3sas_driver_template = { - .module = THIS_MODULE, - .name = "Fusion MPT SAS Host", - .proc_name = MPT3SAS_DRIVER_NAME, - .queuecommand = scsih_qcmd, - .target_alloc = scsih_target_alloc, - .slave_alloc = scsih_slave_alloc, - .slave_configure = scsih_slave_configure, - .target_destroy = scsih_target_destroy, - .slave_destroy = scsih_slave_destroy, - .scan_finished = scsih_scan_finished, - .scan_start = scsih_scan_start, - .change_queue_depth = scsih_change_queue_depth, - .eh_abort_handler = scsih_abort, - .eh_device_reset_handler = scsih_dev_reset, - .eh_target_reset_handler = scsih_target_reset, - .eh_host_reset_handler = scsih_host_reset, - .bios_param = scsih_bios_param, - .can_queue = 1, - .this_id = -1, - .sg_tablesize = MPT3SAS_SG_DEPTH, - .max_sectors = 32767, - .cmd_per_lun = 7, - .use_clustering = ENABLE_CLUSTERING, - .shost_attrs = mpt3sas_host_attrs, - .sdev_attrs = mpt3sas_dev_attrs, - .track_queue_depth = 1, -}; - -/* raid transport support for SAS 3.0 HBA devices */ -static struct raid_function_template mpt3sas_raid_functions = { - .cookie = &mpt3sas_driver_template, - .is_raid = scsih_is_raid, - .get_resync = scsih_get_resync, - .get_state = scsih_get_state, -}; - -/** - * _scsih_determine_hba_mpi_version - determine in which MPI version class - * this device belongs to. - * @pdev: PCI device struct - * - * return MPI2_VERSION for SAS 2.0 HBA devices, - * MPI25_VERSION for SAS 3.0 HBA devices. - */ -u16 -_scsih_determine_hba_mpi_version(struct pci_dev *pdev) -{ - - switch (pdev->device) { - case MPI2_MFGPAGE_DEVID_SSS6200: - case MPI2_MFGPAGE_DEVID_SAS2004: - case MPI2_MFGPAGE_DEVID_SAS2008: - case MPI2_MFGPAGE_DEVID_SAS2108_1: - case MPI2_MFGPAGE_DEVID_SAS2108_2: - case MPI2_MFGPAGE_DEVID_SAS2108_3: - case MPI2_MFGPAGE_DEVID_SAS2116_1: - case MPI2_MFGPAGE_DEVID_SAS2116_2: - case MPI2_MFGPAGE_DEVID_SAS2208_1: - case MPI2_MFGPAGE_DEVID_SAS2208_2: - case MPI2_MFGPAGE_DEVID_SAS2208_3: - case MPI2_MFGPAGE_DEVID_SAS2208_4: - case MPI2_MFGPAGE_DEVID_SAS2208_5: - case MPI2_MFGPAGE_DEVID_SAS2208_6: - case MPI2_MFGPAGE_DEVID_SAS2308_1: - case MPI2_MFGPAGE_DEVID_SAS2308_2: - case MPI2_MFGPAGE_DEVID_SAS2308_3: - return MPI2_VERSION; - case MPI25_MFGPAGE_DEVID_SAS3004: - case MPI25_MFGPAGE_DEVID_SAS3008: - case MPI25_MFGPAGE_DEVID_SAS3108_1: - case MPI25_MFGPAGE_DEVID_SAS3108_2: - case MPI25_MFGPAGE_DEVID_SAS3108_5: - case MPI25_MFGPAGE_DEVID_SAS3108_6: - return MPI25_VERSION; - } - return 0; -} - -/** - * _scsih_probe - attach and add scsi host - * @pdev: PCI device struct - * @id: pci device id - * - * Returns 0 success, anything else error. - */ -int -_scsih_probe(struct pci_dev *pdev, const struct pci_device_id *id) -{ - struct MPT3SAS_ADAPTER *ioc; - struct Scsi_Host *shost = NULL; - int rv; - u16 hba_mpi_version; - - /* Determine in which MPI version class this pci device belongs */ - hba_mpi_version = _scsih_determine_hba_mpi_version(pdev); - if (hba_mpi_version == 0) - return -ENODEV; - - /* Enumerate only SAS 2.0 HBA's if hbas_to_enumerate is one, - * for other generation HBA's return with -ENODEV - */ - if ((hbas_to_enumerate == 1) && (hba_mpi_version != MPI2_VERSION)) - return -ENODEV; - - /* Enumerate only SAS 3.0 HBA's if hbas_to_enumerate is two, - * for other generation HBA's return with -ENODEV - */ - if ((hbas_to_enumerate == 2) && (hba_mpi_version != MPI25_VERSION)) - return -ENODEV; - - switch (hba_mpi_version) { - case MPI2_VERSION: - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | - PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_CLKPM); - /* Use mpt2sas driver host template for SAS 2.0 HBA's */ - shost = scsi_host_alloc(&mpt2sas_driver_template, - sizeof(struct MPT3SAS_ADAPTER)); - if (!shost) - return -ENODEV; - ioc = shost_priv(shost); - memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER)); - ioc->hba_mpi_version_belonged = hba_mpi_version; - ioc->id = mpt2_ids++; - sprintf(ioc->driver_name, "%s", MPT2SAS_DRIVER_NAME); - if (pdev->device == MPI2_MFGPAGE_DEVID_SSS6200) { - ioc->is_warpdrive = 1; - ioc->hide_ir_msg = 1; - } else - ioc->mfg_pg10_hide_flag = MFG_PAGE10_EXPOSE_ALL_DISKS; - break; - case MPI25_VERSION: - /* Use mpt3sas driver host template for SAS 3.0 HBA's */ - shost = scsi_host_alloc(&mpt3sas_driver_template, - sizeof(struct MPT3SAS_ADAPTER)); - if (!shost) - return -ENODEV; - ioc = shost_priv(shost); - memset(ioc, 0, sizeof(struct MPT3SAS_ADAPTER)); - ioc->hba_mpi_version_belonged = hba_mpi_version; - ioc->id = mpt3_ids++; - sprintf(ioc->driver_name, "%s", MPT3SAS_DRIVER_NAME); - if (pdev->revision >= SAS3_PCI_DEVICE_C0_REVISION) - ioc->msix96_vector = 1; - break; - default: - return -ENODEV; - } - - INIT_LIST_HEAD(&ioc->list); - spin_lock(&gioc_lock); - list_add_tail(&ioc->list, &mpt3sas_ioc_list); - spin_unlock(&gioc_lock); - ioc->shost = shost; - ioc->pdev = pdev; - ioc->scsi_io_cb_idx = scsi_io_cb_idx; - ioc->tm_cb_idx = tm_cb_idx; - ioc->ctl_cb_idx = ctl_cb_idx; - ioc->base_cb_idx = base_cb_idx; - ioc->port_enable_cb_idx = port_enable_cb_idx; - ioc->transport_cb_idx = transport_cb_idx; - ioc->scsih_cb_idx = scsih_cb_idx; - ioc->config_cb_idx = config_cb_idx; - ioc->tm_tr_cb_idx = tm_tr_cb_idx; - ioc->tm_tr_volume_cb_idx = tm_tr_volume_cb_idx; - ioc->tm_sas_control_cb_idx = tm_sas_control_cb_idx; - ioc->logging_level = logging_level; - ioc->schedule_dead_ioc_flush_running_cmds = &_scsih_flush_running_cmds; - /* misc semaphores and spin locks */ - mutex_init(&ioc->reset_in_progress_mutex); - /* initializing pci_access_mutex lock */ - mutex_init(&ioc->pci_access_mutex); - spin_lock_init(&ioc->ioc_reset_in_progress_lock); - spin_lock_init(&ioc->scsi_lookup_lock); - spin_lock_init(&ioc->sas_device_lock); - spin_lock_init(&ioc->sas_node_lock); - spin_lock_init(&ioc->fw_event_lock); - spin_lock_init(&ioc->raid_device_lock); - spin_lock_init(&ioc->diag_trigger_lock); - - INIT_LIST_HEAD(&ioc->sas_device_list); - INIT_LIST_HEAD(&ioc->sas_device_init_list); - INIT_LIST_HEAD(&ioc->sas_expander_list); - INIT_LIST_HEAD(&ioc->fw_event_list); - INIT_LIST_HEAD(&ioc->raid_device_list); - INIT_LIST_HEAD(&ioc->sas_hba.sas_port_list); - INIT_LIST_HEAD(&ioc->delayed_tr_list); - INIT_LIST_HEAD(&ioc->delayed_tr_volume_list); - INIT_LIST_HEAD(&ioc->reply_queue_list); - - sprintf(ioc->name, "%s_cm%d", ioc->driver_name, ioc->id); - - /* init shost parameters */ - shost->max_cmd_len = 32; - shost->max_lun = max_lun; - shost->transportt = mpt3sas_transport_template; - shost->unique_id = ioc->id; - - if (max_sectors != 0xFFFF) { - if (max_sectors < 64) { - shost->max_sectors = 64; - pr_warn(MPT3SAS_FMT "Invalid value %d passed " \ - "for max_sectors, range is 64 to 32767. Assigning " - "value of 64.\n", ioc->name, max_sectors); - } else if (max_sectors > 32767) { - shost->max_sectors = 32767; - pr_warn(MPT3SAS_FMT "Invalid value %d passed " \ - "for max_sectors, range is 64 to 32767. Assigning " - "default value of 32767.\n", ioc->name, - max_sectors); - } else { - shost->max_sectors = max_sectors & 0xFFFE; - pr_info(MPT3SAS_FMT - "The max_sectors value is set to %d\n", - ioc->name, shost->max_sectors); - } - } - - /* register EEDP capabilities with SCSI layer */ - if (prot_mask > 0) - scsi_host_set_prot(shost, prot_mask); - else - scsi_host_set_prot(shost, SHOST_DIF_TYPE1_PROTECTION - | SHOST_DIF_TYPE2_PROTECTION - | SHOST_DIF_TYPE3_PROTECTION); - - scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC); - - /* event thread */ - snprintf(ioc->firmware_event_name, sizeof(ioc->firmware_event_name), - "fw_event_%s%d", ioc->driver_name, ioc->id); - ioc->firmware_event_thread = alloc_ordered_workqueue( - ioc->firmware_event_name, 0); - if (!ioc->firmware_event_thread) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rv = -ENODEV; - goto out_thread_fail; - } - - ioc->is_driver_loading = 1; - if ((mpt3sas_base_attach(ioc))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rv = -ENODEV; - goto out_attach_fail; - } - - if (ioc->is_warpdrive) { - if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) - ioc->hide_drives = 0; - else if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_HIDE_ALL_DISKS) - ioc->hide_drives = 1; - else { - if (mpt3sas_get_num_volumes(ioc)) - ioc->hide_drives = 1; - else - ioc->hide_drives = 0; - } - } else - ioc->hide_drives = 0; - - rv = scsi_add_host(shost, &pdev->dev); - if (rv) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out_add_shost_fail; - } - - scsi_scan_host(shost); - return 0; -out_add_shost_fail: - mpt3sas_base_detach(ioc); - out_attach_fail: - destroy_workqueue(ioc->firmware_event_thread); - out_thread_fail: - spin_lock(&gioc_lock); - list_del(&ioc->list); - spin_unlock(&gioc_lock); - scsi_host_put(shost); - return rv; -} - -#ifdef CONFIG_PM -/** - * scsih_suspend - power management suspend main entry point - * @pdev: PCI device struct - * @state: PM state change to (usually PCI_D3) - * - * Returns 0 success, anything else error. - */ -int -scsih_suspend(struct pci_dev *pdev, pm_message_t state) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - pci_power_t device_state; - - mpt3sas_base_stop_watchdog(ioc); - flush_scheduled_work(); - scsi_block_requests(shost); - device_state = pci_choose_state(pdev, state); - pr_info(MPT3SAS_FMT - "pdev=0x%p, slot=%s, entering operating state [D%d]\n", - ioc->name, pdev, pci_name(pdev), device_state); - - pci_save_state(pdev); - mpt3sas_base_free_resources(ioc); - pci_set_power_state(pdev, device_state); - return 0; -} - -/** - * scsih_resume - power management resume main entry point - * @pdev: PCI device struct - * - * Returns 0 success, anything else error. - */ -int -scsih_resume(struct pci_dev *pdev) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - pci_power_t device_state = pdev->current_state; - int r; - - pr_info(MPT3SAS_FMT - "pdev=0x%p, slot=%s, previous operating state [D%d]\n", - ioc->name, pdev, pci_name(pdev), device_state); - - pci_set_power_state(pdev, PCI_D0); - pci_enable_wake(pdev, PCI_D0, 0); - pci_restore_state(pdev); - ioc->pdev = pdev; - r = mpt3sas_base_map_resources(ioc); - if (r) - return r; - - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, SOFT_RESET); - scsi_unblock_requests(shost); - mpt3sas_base_start_watchdog(ioc); - return 0; -} -#endif /* CONFIG_PM */ - -/** - * scsih_pci_error_detected - Called when a PCI error is detected. - * @pdev: PCI device struct - * @state: PCI channel state - * - * Description: Called when a PCI error is detected. - * - * Return value: - * PCI_ERS_RESULT_NEED_RESET or PCI_ERS_RESULT_DISCONNECT - */ -pci_ers_result_t -scsih_pci_error_detected(struct pci_dev *pdev, pci_channel_state_t state) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - pr_info(MPT3SAS_FMT "PCI error: detected callback, state(%d)!!\n", - ioc->name, state); - - switch (state) { - case pci_channel_io_normal: - return PCI_ERS_RESULT_CAN_RECOVER; - case pci_channel_io_frozen: - /* Fatal error, prepare for slot reset */ - ioc->pci_error_recovery = 1; - scsi_block_requests(ioc->shost); - mpt3sas_base_stop_watchdog(ioc); - mpt3sas_base_free_resources(ioc); - return PCI_ERS_RESULT_NEED_RESET; - case pci_channel_io_perm_failure: - /* Permanent error, prepare for device removal */ - ioc->pci_error_recovery = 1; - mpt3sas_base_stop_watchdog(ioc); - _scsih_flush_running_cmds(ioc); - return PCI_ERS_RESULT_DISCONNECT; - } - return PCI_ERS_RESULT_NEED_RESET; -} - -/** - * scsih_pci_slot_reset - Called when PCI slot has been reset. - * @pdev: PCI device struct - * - * Description: This routine is called by the pci error recovery - * code after the PCI slot has been reset, just before we - * should resume normal operations. - */ -pci_ers_result_t -scsih_pci_slot_reset(struct pci_dev *pdev) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - int rc; - - pr_info(MPT3SAS_FMT "PCI error: slot reset callback!!\n", - ioc->name); - - ioc->pci_error_recovery = 0; - ioc->pdev = pdev; - pci_restore_state(pdev); - rc = mpt3sas_base_map_resources(ioc); - if (rc) - return PCI_ERS_RESULT_DISCONNECT; - - rc = mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - - pr_warn(MPT3SAS_FMT "hard reset: %s\n", ioc->name, - (rc == 0) ? "success" : "failed"); - - if (!rc) - return PCI_ERS_RESULT_RECOVERED; - else - return PCI_ERS_RESULT_DISCONNECT; -} - -/** - * scsih_pci_resume() - resume normal ops after PCI reset - * @pdev: pointer to PCI device - * - * Called when the error recovery driver tells us that its - * OK to resume normal operation. Use completion to allow - * halted scsi ops to resume. - */ -void -scsih_pci_resume(struct pci_dev *pdev) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - pr_info(MPT3SAS_FMT "PCI error: resume callback!!\n", ioc->name); - - pci_cleanup_aer_uncorrect_error_status(pdev); - mpt3sas_base_start_watchdog(ioc); - scsi_unblock_requests(ioc->shost); -} - -/** - * scsih_pci_mmio_enabled - Enable MMIO and dump debug registers - * @pdev: pointer to PCI device - */ -pci_ers_result_t -scsih_pci_mmio_enabled(struct pci_dev *pdev) -{ - struct Scsi_Host *shost = pci_get_drvdata(pdev); - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - - pr_info(MPT3SAS_FMT "PCI error: mmio enabled callback!!\n", - ioc->name); - - /* TODO - dump whatever for debugging purposes */ - - /* Request a slot reset. */ - return PCI_ERS_RESULT_NEED_RESET; -} - -/* - * The pci device ids are defined in mpi/mpi2_cnfg.h. - */ -static const struct pci_device_id mpt3sas_pci_table[] = { - /* Spitfire ~ 2004 */ - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2004, - PCI_ANY_ID, PCI_ANY_ID }, - /* Falcon ~ 2008 */ - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2008, - PCI_ANY_ID, PCI_ANY_ID }, - /* Liberator ~ 2108 */ - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_1, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_2, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2108_3, - PCI_ANY_ID, PCI_ANY_ID }, - /* Meteor ~ 2116 */ - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_1, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2116_2, - PCI_ANY_ID, PCI_ANY_ID }, - /* Thunderbolt ~ 2208 */ - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_1, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_2, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_3, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_4, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_5, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2208_6, - PCI_ANY_ID, PCI_ANY_ID }, - /* Mustang ~ 2308 */ - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_1, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_2, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SAS2308_3, - PCI_ANY_ID, PCI_ANY_ID }, - /* SSS6200 */ - { MPI2_MFGPAGE_VENDORID_LSI, MPI2_MFGPAGE_DEVID_SSS6200, - PCI_ANY_ID, PCI_ANY_ID }, - /* Fury ~ 3004 and 3008 */ - { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3004, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3008, - PCI_ANY_ID, PCI_ANY_ID }, - /* Invader ~ 3108 */ - { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_1, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_2, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_5, - PCI_ANY_ID, PCI_ANY_ID }, - { MPI2_MFGPAGE_VENDORID_LSI, MPI25_MFGPAGE_DEVID_SAS3108_6, - PCI_ANY_ID, PCI_ANY_ID }, - {0} /* Terminating entry */ -}; -MODULE_DEVICE_TABLE(pci, mpt3sas_pci_table); - -static struct pci_error_handlers _mpt3sas_err_handler = { - .error_detected = scsih_pci_error_detected, - .mmio_enabled = scsih_pci_mmio_enabled, - .slot_reset = scsih_pci_slot_reset, - .resume = scsih_pci_resume, -}; - -static struct pci_driver mpt3sas_driver = { - .name = MPT3SAS_DRIVER_NAME, - .id_table = mpt3sas_pci_table, - .probe = _scsih_probe, - .remove = scsih_remove, - .shutdown = scsih_shutdown, - .err_handler = &_mpt3sas_err_handler, -#ifdef CONFIG_PM - .suspend = scsih_suspend, - .resume = scsih_resume, -#endif -}; - -/** - * scsih_init - main entry point for this driver. - * - * Returns 0 success, anything else error. - */ -int -scsih_init(void) -{ - mpt2_ids = 0; - mpt3_ids = 0; - - mpt3sas_base_initialize_callback_handler(); - - /* queuecommand callback hander */ - scsi_io_cb_idx = mpt3sas_base_register_callback_handler(_scsih_io_done); - - /* task managment callback handler */ - tm_cb_idx = mpt3sas_base_register_callback_handler(_scsih_tm_done); - - /* base internal commands callback handler */ - base_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_base_done); - port_enable_cb_idx = mpt3sas_base_register_callback_handler( - mpt3sas_port_enable_done); - - /* transport internal commands callback handler */ - transport_cb_idx = mpt3sas_base_register_callback_handler( - mpt3sas_transport_done); - - /* scsih internal commands callback handler */ - scsih_cb_idx = mpt3sas_base_register_callback_handler(_scsih_done); - - /* configuration page API internal commands callback handler */ - config_cb_idx = mpt3sas_base_register_callback_handler( - mpt3sas_config_done); - - /* ctl module callback handler */ - ctl_cb_idx = mpt3sas_base_register_callback_handler(mpt3sas_ctl_done); - - tm_tr_cb_idx = mpt3sas_base_register_callback_handler( - _scsih_tm_tr_complete); - - tm_tr_volume_cb_idx = mpt3sas_base_register_callback_handler( - _scsih_tm_volume_tr_complete); - - tm_sas_control_cb_idx = mpt3sas_base_register_callback_handler( - _scsih_sas_control_complete); - - return 0; -} - -/** - * scsih_exit - exit point for this driver (when it is a module). - * - * Returns 0 success, anything else error. - */ -void -scsih_exit(void) -{ - - mpt3sas_base_release_callback_handler(scsi_io_cb_idx); - mpt3sas_base_release_callback_handler(tm_cb_idx); - mpt3sas_base_release_callback_handler(base_cb_idx); - mpt3sas_base_release_callback_handler(port_enable_cb_idx); - mpt3sas_base_release_callback_handler(transport_cb_idx); - mpt3sas_base_release_callback_handler(scsih_cb_idx); - mpt3sas_base_release_callback_handler(config_cb_idx); - mpt3sas_base_release_callback_handler(ctl_cb_idx); - - mpt3sas_base_release_callback_handler(tm_tr_cb_idx); - mpt3sas_base_release_callback_handler(tm_tr_volume_cb_idx); - mpt3sas_base_release_callback_handler(tm_sas_control_cb_idx); - -/* raid transport support */ - if (hbas_to_enumerate != 1) - raid_class_release(mpt3sas_raid_template); - if (hbas_to_enumerate != 2) - raid_class_release(mpt2sas_raid_template); - sas_release_transport(mpt3sas_transport_template); -} - -/** - * _mpt3sas_init - main entry point for this driver. - * - * Returns 0 success, anything else error. - */ -static int __init -_mpt3sas_init(void) -{ - int error; - - pr_info("%s version %s loaded\n", MPT3SAS_DRIVER_NAME, - MPT3SAS_DRIVER_VERSION); - - mpt3sas_transport_template = - sas_attach_transport(&mpt3sas_transport_functions); - if (!mpt3sas_transport_template) - return -ENODEV; - - /* No need attach mpt3sas raid functions template - * if hbas_to_enumarate value is one. - */ - if (hbas_to_enumerate != 1) { - mpt3sas_raid_template = - raid_class_attach(&mpt3sas_raid_functions); - if (!mpt3sas_raid_template) { - sas_release_transport(mpt3sas_transport_template); - return -ENODEV; - } - } - - /* No need to attach mpt2sas raid functions template - * if hbas_to_enumarate value is two - */ - if (hbas_to_enumerate != 2) { - mpt2sas_raid_template = - raid_class_attach(&mpt2sas_raid_functions); - if (!mpt2sas_raid_template) { - sas_release_transport(mpt3sas_transport_template); - return -ENODEV; - } - } - - error = scsih_init(); - if (error) { - scsih_exit(); - return error; - } - - mpt3sas_ctl_init(hbas_to_enumerate); - - error = pci_register_driver(&mpt3sas_driver); - if (error) - scsih_exit(); - - return error; -} - -/** - * _mpt3sas_exit - exit point for this driver (when it is a module). - * - */ -static void __exit -_mpt3sas_exit(void) -{ - pr_info("mpt3sas version %s unloading\n", - MPT3SAS_DRIVER_VERSION); - - pci_unregister_driver(&mpt3sas_driver); - - mpt3sas_ctl_exit(hbas_to_enumerate); - - scsih_exit(); -} - -module_init(_mpt3sas_init); -module_exit(_mpt3sas_exit); diff --git a/addons/mpt3sas/src/4.4.180/mpt3sas_transport.c b/addons/mpt3sas/src/4.4.180/mpt3sas_transport.c deleted file mode 100644 index ca36d7ea..00000000 --- a/addons/mpt3sas/src/4.4.180/mpt3sas_transport.c +++ /dev/null @@ -1,2154 +0,0 @@ -/* - * SAS Transport Layer for MPT (Message Passing Technology) based controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_transport.c - * Copyright (C) 2012-2014 LSI Corporation - * Copyright (C) 2013-2014 Avago Technologies - * (mailto: MPT-FusionLinux.pdl@avagotech.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include - -#include "mpt3sas_base.h" - -/** - * _transport_sas_node_find_by_sas_address - sas node search - * @ioc: per adapter object - * @sas_address: sas address of expander or sas host - * Context: Calling function should acquire ioc->sas_node_lock. - * - * Search for either hba phys or expander device based on handle, then returns - * the sas_node object. - */ -static struct _sas_node * -_transport_sas_node_find_by_sas_address(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address) -{ - if (ioc->sas_hba.sas_address == sas_address) - return &ioc->sas_hba; - else - return mpt3sas_scsih_expander_find_by_sas_address(ioc, - sas_address); -} - -/** - * _transport_convert_phy_link_rate - - * @link_rate: link rate returned from mpt firmware - * - * Convert link_rate from mpi fusion into sas_transport form. - */ -static enum sas_linkrate -_transport_convert_phy_link_rate(u8 link_rate) -{ - enum sas_linkrate rc; - - switch (link_rate) { - case MPI2_SAS_NEG_LINK_RATE_1_5: - rc = SAS_LINK_RATE_1_5_GBPS; - break; - case MPI2_SAS_NEG_LINK_RATE_3_0: - rc = SAS_LINK_RATE_3_0_GBPS; - break; - case MPI2_SAS_NEG_LINK_RATE_6_0: - rc = SAS_LINK_RATE_6_0_GBPS; - break; - case MPI25_SAS_NEG_LINK_RATE_12_0: - rc = SAS_LINK_RATE_12_0_GBPS; - break; - case MPI2_SAS_NEG_LINK_RATE_PHY_DISABLED: - rc = SAS_PHY_DISABLED; - break; - case MPI2_SAS_NEG_LINK_RATE_NEGOTIATION_FAILED: - rc = SAS_LINK_RATE_FAILED; - break; - case MPI2_SAS_NEG_LINK_RATE_PORT_SELECTOR: - rc = SAS_SATA_PORT_SELECTOR; - break; - case MPI2_SAS_NEG_LINK_RATE_SMP_RESET_IN_PROGRESS: - rc = SAS_PHY_RESET_IN_PROGRESS; - break; - - default: - case MPI2_SAS_NEG_LINK_RATE_SATA_OOB_COMPLETE: - case MPI2_SAS_NEG_LINK_RATE_UNKNOWN_LINK_RATE: - rc = SAS_LINK_RATE_UNKNOWN; - break; - } - return rc; -} - -/** - * _transport_set_identify - set identify for phys and end devices - * @ioc: per adapter object - * @handle: device handle - * @identify: sas identify info - * - * Populates sas identify info. - * - * Returns 0 for success, non-zero for failure. - */ -static int -_transport_set_identify(struct MPT3SAS_ADAPTER *ioc, u16 handle, - struct sas_identify *identify) -{ - Mpi2SasDevicePage0_t sas_device_pg0; - Mpi2ConfigReply_t mpi_reply; - u32 device_info; - u32 ioc_status; - - if (ioc->shost_recovery || ioc->pci_error_recovery) { - pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", - __func__, ioc->name); - return -EFAULT; - } - - if ((mpt3sas_config_get_sas_device_pg0(ioc, &mpi_reply, &sas_device_pg0, - MPI2_SAS_DEVICE_PGAD_FORM_HANDLE, handle))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -ENXIO; - } - - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT - "handle(0x%04x), ioc_status(0x%04x)\nfailure at %s:%d/%s()!\n", - ioc->name, handle, ioc_status, - __FILE__, __LINE__, __func__); - return -EIO; - } - - memset(identify, 0, sizeof(struct sas_identify)); - device_info = le32_to_cpu(sas_device_pg0.DeviceInfo); - - /* sas_address */ - identify->sas_address = le64_to_cpu(sas_device_pg0.SASAddress); - - /* phy number of the parent device this device is linked to */ - identify->phy_identifier = sas_device_pg0.PhyNum; - - /* device_type */ - switch (device_info & MPI2_SAS_DEVICE_INFO_MASK_DEVICE_TYPE) { - case MPI2_SAS_DEVICE_INFO_NO_DEVICE: - identify->device_type = SAS_PHY_UNUSED; - break; - case MPI2_SAS_DEVICE_INFO_END_DEVICE: - identify->device_type = SAS_END_DEVICE; - break; - case MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER: - identify->device_type = SAS_EDGE_EXPANDER_DEVICE; - break; - case MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER: - identify->device_type = SAS_FANOUT_EXPANDER_DEVICE; - break; - } - - /* initiator_port_protocols */ - if (device_info & MPI2_SAS_DEVICE_INFO_SSP_INITIATOR) - identify->initiator_port_protocols |= SAS_PROTOCOL_SSP; - if (device_info & MPI2_SAS_DEVICE_INFO_STP_INITIATOR) - identify->initiator_port_protocols |= SAS_PROTOCOL_STP; - if (device_info & MPI2_SAS_DEVICE_INFO_SMP_INITIATOR) - identify->initiator_port_protocols |= SAS_PROTOCOL_SMP; - if (device_info & MPI2_SAS_DEVICE_INFO_SATA_HOST) - identify->initiator_port_protocols |= SAS_PROTOCOL_SATA; - - /* target_port_protocols */ - if (device_info & MPI2_SAS_DEVICE_INFO_SSP_TARGET) - identify->target_port_protocols |= SAS_PROTOCOL_SSP; - if (device_info & MPI2_SAS_DEVICE_INFO_STP_TARGET) - identify->target_port_protocols |= SAS_PROTOCOL_STP; - if (device_info & MPI2_SAS_DEVICE_INFO_SMP_TARGET) - identify->target_port_protocols |= SAS_PROTOCOL_SMP; - if (device_info & MPI2_SAS_DEVICE_INFO_SATA_DEVICE) - identify->target_port_protocols |= SAS_PROTOCOL_SATA; - - return 0; -} - -/** - * mpt3sas_transport_done - internal transport layer callback handler. - * @ioc: per adapter object - * @smid: system request message index - * @msix_index: MSIX table index supplied by the OS - * @reply: reply message frame(lower 32bit addr) - * - * Callback handler when sending internal generated transport cmds. - * The callback index passed is `ioc->transport_cb_idx` - * - * Return 1 meaning mf should be freed from _base_interrupt - * 0 means the mf is freed from this function. - */ -u8 -mpt3sas_transport_done(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 msix_index, - u32 reply) -{ - MPI2DefaultReply_t *mpi_reply; - - mpi_reply = mpt3sas_base_get_reply_virt_addr(ioc, reply); - if (ioc->transport_cmds.status == MPT3_CMD_NOT_USED) - return 1; - if (ioc->transport_cmds.smid != smid) - return 1; - ioc->transport_cmds.status |= MPT3_CMD_COMPLETE; - if (mpi_reply) { - memcpy(ioc->transport_cmds.reply, mpi_reply, - mpi_reply->MsgLength*4); - ioc->transport_cmds.status |= MPT3_CMD_REPLY_VALID; - } - ioc->transport_cmds.status &= ~MPT3_CMD_PENDING; - complete(&ioc->transport_cmds.done); - return 1; -} - -/* report manufacture request structure */ -struct rep_manu_request { - u8 smp_frame_type; - u8 function; - u8 reserved; - u8 request_length; -}; - -/* report manufacture reply structure */ -struct rep_manu_reply { - u8 smp_frame_type; /* 0x41 */ - u8 function; /* 0x01 */ - u8 function_result; - u8 response_length; - u16 expander_change_count; - u8 reserved0[2]; - u8 sas_format; - u8 reserved2[3]; - u8 vendor_id[SAS_EXPANDER_VENDOR_ID_LEN]; - u8 product_id[SAS_EXPANDER_PRODUCT_ID_LEN]; - u8 product_rev[SAS_EXPANDER_PRODUCT_REV_LEN]; - u8 component_vendor_id[SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN]; - u16 component_id; - u8 component_revision_id; - u8 reserved3; - u8 vendor_specific[8]; -}; - -/** - * transport_expander_report_manufacture - obtain SMP report_manufacture - * @ioc: per adapter object - * @sas_address: expander sas address - * @edev: the sas_expander_device object - * - * Fills in the sas_expander_device object when SMP port is created. - * - * Returns 0 for success, non-zero for failure. - */ -static int -_transport_expander_report_manufacture(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address, struct sas_expander_device *edev) -{ - Mpi2SmpPassthroughRequest_t *mpi_request; - Mpi2SmpPassthroughReply_t *mpi_reply; - struct rep_manu_reply *manufacture_reply; - struct rep_manu_request *manufacture_request; - int rc; - u16 smid; - u32 ioc_state; - unsigned long timeleft; - void *psge; - u8 issue_reset = 0; - void *data_out = NULL; - dma_addr_t data_out_dma; - dma_addr_t data_in_dma; - size_t data_in_sz; - size_t data_out_sz; - u16 wait_state_count; - - if (ioc->shost_recovery || ioc->pci_error_recovery) { - pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", - __func__, ioc->name); - return -EFAULT; - } - - mutex_lock(&ioc->transport_cmds.mutex); - - if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - ioc->transport_cmds.status = MPT3_CMD_PENDING; - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, __func__, wait_state_count); - } - if (wait_state_count) - pr_info(MPT3SAS_FMT "%s: ioc is operational\n", - ioc->name, __func__); - - smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - rc = 0; - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->transport_cmds.smid = smid; - - data_out_sz = sizeof(struct rep_manu_request); - data_in_sz = sizeof(struct rep_manu_reply); - data_out = pci_alloc_consistent(ioc->pdev, data_out_sz + data_in_sz, - &data_out_dma); - - if (!data_out) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - rc = -ENOMEM; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - - data_in_dma = data_out_dma + sizeof(struct rep_manu_request); - - manufacture_request = data_out; - manufacture_request->smp_frame_type = 0x40; - manufacture_request->function = 1; - manufacture_request->reserved = 0; - manufacture_request->request_length = 0; - - memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; - mpi_request->PhysicalPort = 0xFF; - mpi_request->SASAddress = cpu_to_le64(sas_address); - mpi_request->RequestDataLength = cpu_to_le16(data_out_sz); - psge = &mpi_request->SGL; - - ioc->build_sg(ioc, psge, data_out_dma, data_out_sz, data_in_dma, - data_in_sz); - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "report_manufacture - send to sas_addr(0x%016llx)\n", - ioc->name, (unsigned long long)sas_address)); - init_completion(&ioc->transport_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, - 10*HZ); - - if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SmpPassthroughRequest_t)/4); - if (!(ioc->transport_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "report_manufacture - complete\n", ioc->name)); - - if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) { - u8 *tmp; - - mpi_reply = ioc->transport_cmds.reply; - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "report_manufacture - reply data transfer size(%d)\n", - ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength))); - - if (le16_to_cpu(mpi_reply->ResponseDataLength) != - sizeof(struct rep_manu_reply)) - goto out; - - manufacture_reply = data_out + sizeof(struct rep_manu_request); - strncpy(edev->vendor_id, manufacture_reply->vendor_id, - SAS_EXPANDER_VENDOR_ID_LEN); - strncpy(edev->product_id, manufacture_reply->product_id, - SAS_EXPANDER_PRODUCT_ID_LEN); - strncpy(edev->product_rev, manufacture_reply->product_rev, - SAS_EXPANDER_PRODUCT_REV_LEN); - edev->level = manufacture_reply->sas_format & 1; - if (edev->level) { - strncpy(edev->component_vendor_id, - manufacture_reply->component_vendor_id, - SAS_EXPANDER_COMPONENT_VENDOR_ID_LEN); - tmp = (u8 *)&manufacture_reply->component_id; - edev->component_id = tmp[0] << 8 | tmp[1]; - edev->component_revision_id = - manufacture_reply->component_revision_id; - } - } else - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "report_manufacture - no reply\n", ioc->name)); - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - out: - ioc->transport_cmds.status = MPT3_CMD_NOT_USED; - if (data_out) - pci_free_consistent(ioc->pdev, data_out_sz + data_in_sz, - data_out, data_out_dma); - - mutex_unlock(&ioc->transport_cmds.mutex); - return rc; -} - - -/** - * _transport_delete_port - helper function to removing a port - * @ioc: per adapter object - * @mpt3sas_port: mpt3sas per port object - * - * Returns nothing. - */ -static void -_transport_delete_port(struct MPT3SAS_ADAPTER *ioc, - struct _sas_port *mpt3sas_port) -{ - u64 sas_address = mpt3sas_port->remote_identify.sas_address; - enum sas_device_type device_type = - mpt3sas_port->remote_identify.device_type; - - dev_printk(KERN_INFO, &mpt3sas_port->port->dev, - "remove: sas_addr(0x%016llx)\n", - (unsigned long long) sas_address); - - ioc->logging_level |= MPT_DEBUG_TRANSPORT; - if (device_type == SAS_END_DEVICE) - mpt3sas_device_remove_by_sas_address(ioc, sas_address); - else if (device_type == SAS_EDGE_EXPANDER_DEVICE || - device_type == SAS_FANOUT_EXPANDER_DEVICE) - mpt3sas_expander_remove(ioc, sas_address); - ioc->logging_level &= ~MPT_DEBUG_TRANSPORT; -} - -/** - * _transport_delete_phy - helper function to removing single phy from port - * @ioc: per adapter object - * @mpt3sas_port: mpt3sas per port object - * @mpt3sas_phy: mpt3sas per phy object - * - * Returns nothing. - */ -static void -_transport_delete_phy(struct MPT3SAS_ADAPTER *ioc, - struct _sas_port *mpt3sas_port, struct _sas_phy *mpt3sas_phy) -{ - u64 sas_address = mpt3sas_port->remote_identify.sas_address; - - dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev, - "remove: sas_addr(0x%016llx), phy(%d)\n", - (unsigned long long) sas_address, mpt3sas_phy->phy_id); - - list_del(&mpt3sas_phy->port_siblings); - mpt3sas_port->num_phys--; - sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy); - mpt3sas_phy->phy_belongs_to_port = 0; -} - -/** - * _transport_add_phy - helper function to adding single phy to port - * @ioc: per adapter object - * @mpt3sas_port: mpt3sas per port object - * @mpt3sas_phy: mpt3sas per phy object - * - * Returns nothing. - */ -static void -_transport_add_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_port *mpt3sas_port, - struct _sas_phy *mpt3sas_phy) -{ - u64 sas_address = mpt3sas_port->remote_identify.sas_address; - - dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev, - "add: sas_addr(0x%016llx), phy(%d)\n", (unsigned long long) - sas_address, mpt3sas_phy->phy_id); - - list_add_tail(&mpt3sas_phy->port_siblings, &mpt3sas_port->phy_list); - mpt3sas_port->num_phys++; - sas_port_add_phy(mpt3sas_port->port, mpt3sas_phy->phy); - mpt3sas_phy->phy_belongs_to_port = 1; -} - -/** - * _transport_add_phy_to_an_existing_port - adding new phy to existing port - * @ioc: per adapter object - * @sas_node: sas node object (either expander or sas host) - * @mpt3sas_phy: mpt3sas per phy object - * @sas_address: sas address of device/expander were phy needs to be added to - * - * Returns nothing. - */ -static void -_transport_add_phy_to_an_existing_port(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy, - u64 sas_address) -{ - struct _sas_port *mpt3sas_port; - struct _sas_phy *phy_srch; - - if (mpt3sas_phy->phy_belongs_to_port == 1) - return; - - list_for_each_entry(mpt3sas_port, &sas_node->sas_port_list, - port_list) { - if (mpt3sas_port->remote_identify.sas_address != - sas_address) - continue; - list_for_each_entry(phy_srch, &mpt3sas_port->phy_list, - port_siblings) { - if (phy_srch == mpt3sas_phy) - return; - } - _transport_add_phy(ioc, mpt3sas_port, mpt3sas_phy); - return; - } - -} - -/** - * _transport_del_phy_from_an_existing_port - delete phy from existing port - * @ioc: per adapter object - * @sas_node: sas node object (either expander or sas host) - * @mpt3sas_phy: mpt3sas per phy object - * - * Returns nothing. - */ -static void -_transport_del_phy_from_an_existing_port(struct MPT3SAS_ADAPTER *ioc, - struct _sas_node *sas_node, struct _sas_phy *mpt3sas_phy) -{ - struct _sas_port *mpt3sas_port, *next; - struct _sas_phy *phy_srch; - - if (mpt3sas_phy->phy_belongs_to_port == 0) - return; - - list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list, - port_list) { - list_for_each_entry(phy_srch, &mpt3sas_port->phy_list, - port_siblings) { - if (phy_srch != mpt3sas_phy) - continue; - - if (mpt3sas_port->num_phys == 1) - _transport_delete_port(ioc, mpt3sas_port); - else - _transport_delete_phy(ioc, mpt3sas_port, - mpt3sas_phy); - return; - } - } -} - -/** - * _transport_sanity_check - sanity check when adding a new port - * @ioc: per adapter object - * @sas_node: sas node object (either expander or sas host) - * @sas_address: sas address of device being added - * - * See the explanation above from _transport_delete_duplicate_port - */ -static void -_transport_sanity_check(struct MPT3SAS_ADAPTER *ioc, struct _sas_node *sas_node, - u64 sas_address) -{ - int i; - - for (i = 0; i < sas_node->num_phys; i++) { - if (sas_node->phy[i].remote_identify.sas_address != sas_address) - continue; - if (sas_node->phy[i].phy_belongs_to_port == 1) - _transport_del_phy_from_an_existing_port(ioc, sas_node, - &sas_node->phy[i]); - } -} - -/** - * mpt3sas_transport_port_add - insert port to the list - * @ioc: per adapter object - * @handle: handle of attached device - * @sas_address: sas address of parent expander or sas host - * Context: This function will acquire ioc->sas_node_lock. - * - * Adding new port object to the sas_node->sas_port_list. - * - * Returns mpt3sas_port. - */ -struct _sas_port * -mpt3sas_transport_port_add(struct MPT3SAS_ADAPTER *ioc, u16 handle, - u64 sas_address) -{ - struct _sas_phy *mpt3sas_phy, *next; - struct _sas_port *mpt3sas_port; - unsigned long flags; - struct _sas_node *sas_node; - struct sas_rphy *rphy; - struct _sas_device *sas_device = NULL; - int i; - struct sas_port *port; - - mpt3sas_port = kzalloc(sizeof(struct _sas_port), - GFP_KERNEL); - if (!mpt3sas_port) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return NULL; - } - - INIT_LIST_HEAD(&mpt3sas_port->port_list); - INIT_LIST_HEAD(&mpt3sas_port->phy_list); - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - if (!sas_node) { - pr_err(MPT3SAS_FMT - "%s: Could not find parent sas_address(0x%016llx)!\n", - ioc->name, __func__, (unsigned long long)sas_address); - goto out_fail; - } - - if ((_transport_set_identify(ioc, handle, - &mpt3sas_port->remote_identify))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out_fail; - } - - if (mpt3sas_port->remote_identify.device_type == SAS_PHY_UNUSED) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out_fail; - } - - _transport_sanity_check(ioc, sas_node, - mpt3sas_port->remote_identify.sas_address); - - for (i = 0; i < sas_node->num_phys; i++) { - if (sas_node->phy[i].remote_identify.sas_address != - mpt3sas_port->remote_identify.sas_address) - continue; - list_add_tail(&sas_node->phy[i].port_siblings, - &mpt3sas_port->phy_list); - mpt3sas_port->num_phys++; - } - - if (!mpt3sas_port->num_phys) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out_fail; - } - - port = sas_port_alloc_num(sas_node->parent_dev); - if ((sas_port_add(port))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - goto out_fail; - } - - list_for_each_entry(mpt3sas_phy, &mpt3sas_port->phy_list, - port_siblings) { - if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) - dev_printk(KERN_INFO, &port->dev, - "add: handle(0x%04x), sas_addr(0x%016llx), phy(%d)\n", - handle, (unsigned long long) - mpt3sas_port->remote_identify.sas_address, - mpt3sas_phy->phy_id); - sas_port_add_phy(port, mpt3sas_phy->phy); - mpt3sas_phy->phy_belongs_to_port = 1; - } - - mpt3sas_port->port = port; - if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) - rphy = sas_end_device_alloc(port); - else - rphy = sas_expander_alloc(port, - mpt3sas_port->remote_identify.device_type); - - rphy->identify = mpt3sas_port->remote_identify; - - if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { - sas_device = mpt3sas_get_sdev_by_addr(ioc, - mpt3sas_port->remote_identify.sas_address); - if (!sas_device) { - dfailprintk(ioc, printk(MPT3SAS_FMT - "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__)); - goto out_fail; - } - sas_device->pend_sas_rphy_add = 1; - } - - if ((sas_rphy_add(rphy))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - } - - if (mpt3sas_port->remote_identify.device_type == SAS_END_DEVICE) { - sas_device->pend_sas_rphy_add = 0; - sas_device_put(sas_device); - } - - if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) - dev_printk(KERN_INFO, &rphy->dev, - "add: handle(0x%04x), sas_addr(0x%016llx)\n", - handle, (unsigned long long) - mpt3sas_port->remote_identify.sas_address); - mpt3sas_port->rphy = rphy; - spin_lock_irqsave(&ioc->sas_node_lock, flags); - list_add_tail(&mpt3sas_port->port_list, &sas_node->sas_port_list); - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - /* fill in report manufacture */ - if (mpt3sas_port->remote_identify.device_type == - MPI2_SAS_DEVICE_INFO_EDGE_EXPANDER || - mpt3sas_port->remote_identify.device_type == - MPI2_SAS_DEVICE_INFO_FANOUT_EXPANDER) - _transport_expander_report_manufacture(ioc, - mpt3sas_port->remote_identify.sas_address, - rphy_to_expander_device(rphy)); - return mpt3sas_port; - - out_fail: - list_for_each_entry_safe(mpt3sas_phy, next, &mpt3sas_port->phy_list, - port_siblings) - list_del(&mpt3sas_phy->port_siblings); - kfree(mpt3sas_port); - return NULL; -} - -/** - * mpt3sas_transport_port_remove - remove port from the list - * @ioc: per adapter object - * @sas_address: sas address of attached device - * @sas_address_parent: sas address of parent expander or sas host - * Context: This function will acquire ioc->sas_node_lock. - * - * Removing object and freeing associated memory from the - * ioc->sas_port_list. - * - * Return nothing. - */ -void -mpt3sas_transport_port_remove(struct MPT3SAS_ADAPTER *ioc, u64 sas_address, - u64 sas_address_parent) -{ - int i; - unsigned long flags; - struct _sas_port *mpt3sas_port, *next; - struct _sas_node *sas_node; - u8 found = 0; - struct _sas_phy *mpt3sas_phy, *next_phy; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_node = _transport_sas_node_find_by_sas_address(ioc, - sas_address_parent); - if (!sas_node) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return; - } - list_for_each_entry_safe(mpt3sas_port, next, &sas_node->sas_port_list, - port_list) { - if (mpt3sas_port->remote_identify.sas_address != sas_address) - continue; - found = 1; - list_del(&mpt3sas_port->port_list); - goto out; - } - out: - if (!found) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return; - } - - for (i = 0; i < sas_node->num_phys; i++) { - if (sas_node->phy[i].remote_identify.sas_address == sas_address) - memset(&sas_node->phy[i].remote_identify, 0 , - sizeof(struct sas_identify)); - } - - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - list_for_each_entry_safe(mpt3sas_phy, next_phy, - &mpt3sas_port->phy_list, port_siblings) { - if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) - dev_printk(KERN_INFO, &mpt3sas_port->port->dev, - "remove: sas_addr(0x%016llx), phy(%d)\n", - (unsigned long long) - mpt3sas_port->remote_identify.sas_address, - mpt3sas_phy->phy_id); - mpt3sas_phy->phy_belongs_to_port = 0; - sas_port_delete_phy(mpt3sas_port->port, mpt3sas_phy->phy); - list_del(&mpt3sas_phy->port_siblings); - } - sas_port_delete(mpt3sas_port->port); - kfree(mpt3sas_port); -} - -/** - * mpt3sas_transport_add_host_phy - report sas_host phy to transport - * @ioc: per adapter object - * @mpt3sas_phy: mpt3sas per phy object - * @phy_pg0: sas phy page 0 - * @parent_dev: parent device class object - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_transport_add_host_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy - *mpt3sas_phy, Mpi2SasPhyPage0_t phy_pg0, struct device *parent_dev) -{ - struct sas_phy *phy; - int phy_index = mpt3sas_phy->phy_id; - - - INIT_LIST_HEAD(&mpt3sas_phy->port_siblings); - phy = sas_phy_alloc(parent_dev, phy_index); - if (!phy) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - if ((_transport_set_identify(ioc, mpt3sas_phy->handle, - &mpt3sas_phy->identify))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - sas_phy_free(phy); - return -1; - } - phy->identify = mpt3sas_phy->identify; - mpt3sas_phy->attached_handle = le16_to_cpu(phy_pg0.AttachedDevHandle); - if (mpt3sas_phy->attached_handle) - _transport_set_identify(ioc, mpt3sas_phy->attached_handle, - &mpt3sas_phy->remote_identify); - phy->identify.phy_identifier = mpt3sas_phy->phy_id; - phy->negotiated_linkrate = _transport_convert_phy_link_rate( - phy_pg0.NegotiatedLinkRate & MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL); - phy->minimum_linkrate_hw = _transport_convert_phy_link_rate( - phy_pg0.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK); - phy->maximum_linkrate_hw = _transport_convert_phy_link_rate( - phy_pg0.HwLinkRate >> 4); - phy->minimum_linkrate = _transport_convert_phy_link_rate( - phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); - phy->maximum_linkrate = _transport_convert_phy_link_rate( - phy_pg0.ProgrammedLinkRate >> 4); - - if ((sas_phy_add(phy))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - sas_phy_free(phy); - return -1; - } - if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) - dev_printk(KERN_INFO, &phy->dev, - "add: handle(0x%04x), sas_addr(0x%016llx)\n" - "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n", - mpt3sas_phy->handle, (unsigned long long) - mpt3sas_phy->identify.sas_address, - mpt3sas_phy->attached_handle, - (unsigned long long) - mpt3sas_phy->remote_identify.sas_address); - mpt3sas_phy->phy = phy; - return 0; -} - - -/** - * mpt3sas_transport_add_expander_phy - report expander phy to transport - * @ioc: per adapter object - * @mpt3sas_phy: mpt3sas per phy object - * @expander_pg1: expander page 1 - * @parent_dev: parent device class object - * - * Returns 0 for success, non-zero for failure. - */ -int -mpt3sas_transport_add_expander_phy(struct MPT3SAS_ADAPTER *ioc, struct _sas_phy - *mpt3sas_phy, Mpi2ExpanderPage1_t expander_pg1, - struct device *parent_dev) -{ - struct sas_phy *phy; - int phy_index = mpt3sas_phy->phy_id; - - INIT_LIST_HEAD(&mpt3sas_phy->port_siblings); - phy = sas_phy_alloc(parent_dev, phy_index); - if (!phy) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -1; - } - if ((_transport_set_identify(ioc, mpt3sas_phy->handle, - &mpt3sas_phy->identify))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - sas_phy_free(phy); - return -1; - } - phy->identify = mpt3sas_phy->identify; - mpt3sas_phy->attached_handle = - le16_to_cpu(expander_pg1.AttachedDevHandle); - if (mpt3sas_phy->attached_handle) - _transport_set_identify(ioc, mpt3sas_phy->attached_handle, - &mpt3sas_phy->remote_identify); - phy->identify.phy_identifier = mpt3sas_phy->phy_id; - phy->negotiated_linkrate = _transport_convert_phy_link_rate( - expander_pg1.NegotiatedLinkRate & - MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL); - phy->minimum_linkrate_hw = _transport_convert_phy_link_rate( - expander_pg1.HwLinkRate & MPI2_SAS_HWRATE_MIN_RATE_MASK); - phy->maximum_linkrate_hw = _transport_convert_phy_link_rate( - expander_pg1.HwLinkRate >> 4); - phy->minimum_linkrate = _transport_convert_phy_link_rate( - expander_pg1.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); - phy->maximum_linkrate = _transport_convert_phy_link_rate( - expander_pg1.ProgrammedLinkRate >> 4); - - if ((sas_phy_add(phy))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - sas_phy_free(phy); - return -1; - } - if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) - dev_printk(KERN_INFO, &phy->dev, - "add: handle(0x%04x), sas_addr(0x%016llx)\n" - "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n", - mpt3sas_phy->handle, (unsigned long long) - mpt3sas_phy->identify.sas_address, - mpt3sas_phy->attached_handle, - (unsigned long long) - mpt3sas_phy->remote_identify.sas_address); - mpt3sas_phy->phy = phy; - return 0; -} - -/** - * mpt3sas_transport_update_links - refreshing phy link changes - * @ioc: per adapter object - * @sas_address: sas address of parent expander or sas host - * @handle: attached device handle - * @phy_numberv: phy number - * @link_rate: new link rate - * - * Returns nothing. - */ -void -mpt3sas_transport_update_links(struct MPT3SAS_ADAPTER *ioc, - u64 sas_address, u16 handle, u8 phy_number, u8 link_rate) -{ - unsigned long flags; - struct _sas_node *sas_node; - struct _sas_phy *mpt3sas_phy; - - if (ioc->shost_recovery || ioc->pci_error_recovery) - return; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - sas_node = _transport_sas_node_find_by_sas_address(ioc, sas_address); - if (!sas_node) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return; - } - - mpt3sas_phy = &sas_node->phy[phy_number]; - mpt3sas_phy->attached_handle = handle; - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - if (handle && (link_rate >= MPI2_SAS_NEG_LINK_RATE_1_5)) { - _transport_set_identify(ioc, handle, - &mpt3sas_phy->remote_identify); - _transport_add_phy_to_an_existing_port(ioc, sas_node, - mpt3sas_phy, mpt3sas_phy->remote_identify.sas_address); - } else - memset(&mpt3sas_phy->remote_identify, 0 , sizeof(struct - sas_identify)); - - if (mpt3sas_phy->phy) - mpt3sas_phy->phy->negotiated_linkrate = - _transport_convert_phy_link_rate(link_rate); - - if ((ioc->logging_level & MPT_DEBUG_TRANSPORT)) - dev_printk(KERN_INFO, &mpt3sas_phy->phy->dev, - "refresh: parent sas_addr(0x%016llx),\n" - "\tlink_rate(0x%02x), phy(%d)\n" - "\tattached_handle(0x%04x), sas_addr(0x%016llx)\n", - (unsigned long long)sas_address, - link_rate, phy_number, handle, (unsigned long long) - mpt3sas_phy->remote_identify.sas_address); -} - -static inline void * -phy_to_ioc(struct sas_phy *phy) -{ - struct Scsi_Host *shost = dev_to_shost(phy->dev.parent); - return shost_priv(shost); -} - -static inline void * -rphy_to_ioc(struct sas_rphy *rphy) -{ - struct Scsi_Host *shost = dev_to_shost(rphy->dev.parent->parent); - return shost_priv(shost); -} - -/* report phy error log structure */ -struct phy_error_log_request { - u8 smp_frame_type; /* 0x40 */ - u8 function; /* 0x11 */ - u8 allocated_response_length; - u8 request_length; /* 02 */ - u8 reserved_1[5]; - u8 phy_identifier; - u8 reserved_2[2]; -}; - -/* report phy error log reply structure */ -struct phy_error_log_reply { - u8 smp_frame_type; /* 0x41 */ - u8 function; /* 0x11 */ - u8 function_result; - u8 response_length; - __be16 expander_change_count; - u8 reserved_1[3]; - u8 phy_identifier; - u8 reserved_2[2]; - __be32 invalid_dword; - __be32 running_disparity_error; - __be32 loss_of_dword_sync; - __be32 phy_reset_problem; -}; - -/** - * _transport_get_expander_phy_error_log - return expander counters - * @ioc: per adapter object - * @phy: The sas phy object - * - * Returns 0 for success, non-zero for failure. - * - */ -static int -_transport_get_expander_phy_error_log(struct MPT3SAS_ADAPTER *ioc, - struct sas_phy *phy) -{ - Mpi2SmpPassthroughRequest_t *mpi_request; - Mpi2SmpPassthroughReply_t *mpi_reply; - struct phy_error_log_request *phy_error_log_request; - struct phy_error_log_reply *phy_error_log_reply; - int rc; - u16 smid; - u32 ioc_state; - unsigned long timeleft; - void *psge; - u8 issue_reset = 0; - void *data_out = NULL; - dma_addr_t data_out_dma; - u32 sz; - u16 wait_state_count; - - if (ioc->shost_recovery || ioc->pci_error_recovery) { - pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", - __func__, ioc->name); - return -EFAULT; - } - - mutex_lock(&ioc->transport_cmds.mutex); - - if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - ioc->transport_cmds.status = MPT3_CMD_PENDING; - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, __func__, wait_state_count); - } - if (wait_state_count) - pr_info(MPT3SAS_FMT "%s: ioc is operational\n", - ioc->name, __func__); - - smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->transport_cmds.smid = smid; - - sz = sizeof(struct phy_error_log_request) + - sizeof(struct phy_error_log_reply); - data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma); - if (!data_out) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - rc = -ENOMEM; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - - rc = -EINVAL; - memset(data_out, 0, sz); - phy_error_log_request = data_out; - phy_error_log_request->smp_frame_type = 0x40; - phy_error_log_request->function = 0x11; - phy_error_log_request->request_length = 2; - phy_error_log_request->allocated_response_length = 0; - phy_error_log_request->phy_identifier = phy->number; - - memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; - mpi_request->PhysicalPort = 0xFF; - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address); - mpi_request->RequestDataLength = - cpu_to_le16(sizeof(struct phy_error_log_request)); - psge = &mpi_request->SGL; - - ioc->build_sg(ioc, psge, data_out_dma, - sizeof(struct phy_error_log_request), - data_out_dma + sizeof(struct phy_error_log_request), - sizeof(struct phy_error_log_reply)); - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_error_log - send to sas_addr(0x%016llx), phy(%d)\n", - ioc->name, (unsigned long long)phy->identify.sas_address, - phy->number)); - init_completion(&ioc->transport_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, - 10*HZ); - - if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SmpPassthroughRequest_t)/4); - if (!(ioc->transport_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_error_log - complete\n", ioc->name)); - - if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) { - - mpi_reply = ioc->transport_cmds.reply; - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_error_log - reply data transfer size(%d)\n", - ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength))); - - if (le16_to_cpu(mpi_reply->ResponseDataLength) != - sizeof(struct phy_error_log_reply)) - goto out; - - phy_error_log_reply = data_out + - sizeof(struct phy_error_log_request); - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_error_log - function_result(%d)\n", - ioc->name, phy_error_log_reply->function_result)); - - phy->invalid_dword_count = - be32_to_cpu(phy_error_log_reply->invalid_dword); - phy->running_disparity_error_count = - be32_to_cpu(phy_error_log_reply->running_disparity_error); - phy->loss_of_dword_sync_count = - be32_to_cpu(phy_error_log_reply->loss_of_dword_sync); - phy->phy_reset_problem_count = - be32_to_cpu(phy_error_log_reply->phy_reset_problem); - rc = 0; - } else - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_error_log - no reply\n", ioc->name)); - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - out: - ioc->transport_cmds.status = MPT3_CMD_NOT_USED; - if (data_out) - pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma); - - mutex_unlock(&ioc->transport_cmds.mutex); - return rc; -} - -/** - * _transport_get_linkerrors - return phy counters for both hba and expanders - * @phy: The sas phy object - * - * Returns 0 for success, non-zero for failure. - * - */ -static int -_transport_get_linkerrors(struct sas_phy *phy) -{ - struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy); - unsigned long flags; - Mpi2ConfigReply_t mpi_reply; - Mpi2SasPhyPage1_t phy_pg1; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - if (_transport_sas_node_find_by_sas_address(ioc, - phy->identify.sas_address) == NULL) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return -EINVAL; - } - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - if (phy->identify.sas_address != ioc->sas_hba.sas_address) - return _transport_get_expander_phy_error_log(ioc, phy); - - /* get hba phy error logs */ - if ((mpt3sas_config_get_phy_pg1(ioc, &mpi_reply, &phy_pg1, - phy->number))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -ENXIO; - } - - if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) - pr_info(MPT3SAS_FMT - "phy(%d), ioc_status (0x%04x), loginfo(0x%08x)\n", - ioc->name, phy->number, - le16_to_cpu(mpi_reply.IOCStatus), - le32_to_cpu(mpi_reply.IOCLogInfo)); - - phy->invalid_dword_count = le32_to_cpu(phy_pg1.InvalidDwordCount); - phy->running_disparity_error_count = - le32_to_cpu(phy_pg1.RunningDisparityErrorCount); - phy->loss_of_dword_sync_count = - le32_to_cpu(phy_pg1.LossDwordSynchCount); - phy->phy_reset_problem_count = - le32_to_cpu(phy_pg1.PhyResetProblemCount); - return 0; -} - -/** - * _transport_get_enclosure_identifier - - * @phy: The sas phy object - * - * Obtain the enclosure logical id for an expander. - * Returns 0 for success, non-zero for failure. - */ -static int -_transport_get_enclosure_identifier(struct sas_rphy *rphy, u64 *identifier) -{ - struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy); - struct _sas_device *sas_device; - unsigned long flags; - int rc; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, - rphy->identify.sas_address); - if (sas_device) { - *identifier = sas_device->enclosure_logical_id; - rc = 0; - sas_device_put(sas_device); - } else { - *identifier = 0; - rc = -ENXIO; - } - - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return rc; -} - -/** - * _transport_get_bay_identifier - - * @phy: The sas phy object - * - * Returns the slot id for a device that resides inside an enclosure. - */ -static int -_transport_get_bay_identifier(struct sas_rphy *rphy) -{ - struct MPT3SAS_ADAPTER *ioc = rphy_to_ioc(rphy); - struct _sas_device *sas_device; - unsigned long flags; - int rc; - - spin_lock_irqsave(&ioc->sas_device_lock, flags); - sas_device = __mpt3sas_get_sdev_by_addr(ioc, - rphy->identify.sas_address); - if (sas_device) { - rc = sas_device->slot; - sas_device_put(sas_device); - } else { - rc = -ENXIO; - } - spin_unlock_irqrestore(&ioc->sas_device_lock, flags); - return rc; -} - -/* phy control request structure */ -struct phy_control_request { - u8 smp_frame_type; /* 0x40 */ - u8 function; /* 0x91 */ - u8 allocated_response_length; - u8 request_length; /* 0x09 */ - u16 expander_change_count; - u8 reserved_1[3]; - u8 phy_identifier; - u8 phy_operation; - u8 reserved_2[13]; - u64 attached_device_name; - u8 programmed_min_physical_link_rate; - u8 programmed_max_physical_link_rate; - u8 reserved_3[6]; -}; - -/* phy control reply structure */ -struct phy_control_reply { - u8 smp_frame_type; /* 0x41 */ - u8 function; /* 0x11 */ - u8 function_result; - u8 response_length; -}; - -#define SMP_PHY_CONTROL_LINK_RESET (0x01) -#define SMP_PHY_CONTROL_HARD_RESET (0x02) -#define SMP_PHY_CONTROL_DISABLE (0x03) - -/** - * _transport_expander_phy_control - expander phy control - * @ioc: per adapter object - * @phy: The sas phy object - * - * Returns 0 for success, non-zero for failure. - * - */ -static int -_transport_expander_phy_control(struct MPT3SAS_ADAPTER *ioc, - struct sas_phy *phy, u8 phy_operation) -{ - Mpi2SmpPassthroughRequest_t *mpi_request; - Mpi2SmpPassthroughReply_t *mpi_reply; - struct phy_control_request *phy_control_request; - struct phy_control_reply *phy_control_reply; - int rc; - u16 smid; - u32 ioc_state; - unsigned long timeleft; - void *psge; - u32 sgl_flags; - u8 issue_reset = 0; - void *data_out = NULL; - dma_addr_t data_out_dma; - u32 sz; - u16 wait_state_count; - - if (ioc->shost_recovery || ioc->pci_error_recovery) { - pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", - __func__, ioc->name); - return -EFAULT; - } - - mutex_lock(&ioc->transport_cmds.mutex); - - if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - ioc->transport_cmds.status = MPT3_CMD_PENDING; - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EFAULT; - goto out; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, __func__, wait_state_count); - } - if (wait_state_count) - pr_info(MPT3SAS_FMT "%s: ioc is operational\n", - ioc->name, __func__); - - smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto out; - } - - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->transport_cmds.smid = smid; - - sz = sizeof(struct phy_control_request) + - sizeof(struct phy_control_reply); - data_out = pci_alloc_consistent(ioc->pdev, sz, &data_out_dma); - if (!data_out) { - pr_err("failure at %s:%d/%s()!\n", __FILE__, - __LINE__, __func__); - rc = -ENOMEM; - mpt3sas_base_free_smid(ioc, smid); - goto out; - } - - rc = -EINVAL; - memset(data_out, 0, sz); - phy_control_request = data_out; - phy_control_request->smp_frame_type = 0x40; - phy_control_request->function = 0x91; - phy_control_request->request_length = 9; - phy_control_request->allocated_response_length = 0; - phy_control_request->phy_identifier = phy->number; - phy_control_request->phy_operation = phy_operation; - phy_control_request->programmed_min_physical_link_rate = - phy->minimum_linkrate << 4; - phy_control_request->programmed_max_physical_link_rate = - phy->maximum_linkrate << 4; - - memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; - mpi_request->PhysicalPort = 0xFF; - mpi_request->VF_ID = 0; /* TODO */ - mpi_request->VP_ID = 0; - mpi_request->SASAddress = cpu_to_le64(phy->identify.sas_address); - mpi_request->RequestDataLength = - cpu_to_le16(sizeof(struct phy_error_log_request)); - psge = &mpi_request->SGL; - - /* WRITE sgel first */ - sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); - sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - ioc->base_add_sg_single(psge, sgl_flags | - sizeof(struct phy_control_request), data_out_dma); - - /* incr sgel */ - psge += ioc->sge_size; - - /* READ sgel last */ - sgl_flags = (MPI2_SGE_FLAGS_SIMPLE_ELEMENT | - MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | - MPI2_SGE_FLAGS_END_OF_LIST); - sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; - ioc->base_add_sg_single(psge, sgl_flags | - sizeof(struct phy_control_reply), data_out_dma + - sizeof(struct phy_control_request)); - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_control - send to sas_addr(0x%016llx), phy(%d), opcode(%d)\n", - ioc->name, (unsigned long long)phy->identify.sas_address, - phy->number, phy_operation)); - init_completion(&ioc->transport_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, - 10*HZ); - - if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s: timeout\n", - ioc->name, __func__); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SmpPassthroughRequest_t)/4); - if (!(ioc->transport_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_control - complete\n", ioc->name)); - - if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) { - - mpi_reply = ioc->transport_cmds.reply; - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_control - reply data transfer size(%d)\n", - ioc->name, le16_to_cpu(mpi_reply->ResponseDataLength))); - - if (le16_to_cpu(mpi_reply->ResponseDataLength) != - sizeof(struct phy_control_reply)) - goto out; - - phy_control_reply = data_out + - sizeof(struct phy_control_request); - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_control - function_result(%d)\n", - ioc->name, phy_control_reply->function_result)); - - rc = 0; - } else - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "phy_control - no reply\n", ioc->name)); - - issue_host_reset: - if (issue_reset) - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - out: - ioc->transport_cmds.status = MPT3_CMD_NOT_USED; - if (data_out) - pci_free_consistent(ioc->pdev, sz, data_out, data_out_dma); - - mutex_unlock(&ioc->transport_cmds.mutex); - return rc; -} - -/** - * _transport_phy_reset - - * @phy: The sas phy object - * @hard_reset: - * - * Returns 0 for success, non-zero for failure. - */ -static int -_transport_phy_reset(struct sas_phy *phy, int hard_reset) -{ - struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy); - Mpi2SasIoUnitControlReply_t mpi_reply; - Mpi2SasIoUnitControlRequest_t mpi_request; - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - if (_transport_sas_node_find_by_sas_address(ioc, - phy->identify.sas_address) == NULL) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return -EINVAL; - } - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - /* handle expander phys */ - if (phy->identify.sas_address != ioc->sas_hba.sas_address) - return _transport_expander_phy_control(ioc, phy, - (hard_reset == 1) ? SMP_PHY_CONTROL_HARD_RESET : - SMP_PHY_CONTROL_LINK_RESET); - - /* handle hba phys */ - memset(&mpi_request, 0, sizeof(Mpi2SasIoUnitControlReply_t)); - mpi_request.Function = MPI2_FUNCTION_SAS_IO_UNIT_CONTROL; - mpi_request.Operation = hard_reset ? - MPI2_SAS_OP_PHY_HARD_RESET : MPI2_SAS_OP_PHY_LINK_RESET; - mpi_request.PhyNum = phy->number; - - if ((mpt3sas_base_sas_iounit_control(ioc, &mpi_reply, &mpi_request))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - return -ENXIO; - } - - if (mpi_reply.IOCStatus || mpi_reply.IOCLogInfo) - pr_info(MPT3SAS_FMT - "phy(%d), ioc_status(0x%04x), loginfo(0x%08x)\n", - ioc->name, phy->number, le16_to_cpu(mpi_reply.IOCStatus), - le32_to_cpu(mpi_reply.IOCLogInfo)); - - return 0; -} - -/** - * _transport_phy_enable - enable/disable phys - * @phy: The sas phy object - * @enable: enable phy when true - * - * Only support sas_host direct attached phys. - * Returns 0 for success, non-zero for failure. - */ -static int -_transport_phy_enable(struct sas_phy *phy, int enable) -{ - struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy); - Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; - Mpi2SasIOUnitPage0_t *sas_iounit_pg0 = NULL; - Mpi2ConfigReply_t mpi_reply; - u16 ioc_status; - u16 sz; - int rc = 0; - unsigned long flags; - int i, discovery_active; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - if (_transport_sas_node_find_by_sas_address(ioc, - phy->identify.sas_address) == NULL) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return -EINVAL; - } - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - /* handle expander phys */ - if (phy->identify.sas_address != ioc->sas_hba.sas_address) - return _transport_expander_phy_control(ioc, phy, - (enable == 1) ? SMP_PHY_CONTROL_LINK_RESET : - SMP_PHY_CONTROL_DISABLE); - - /* handle hba phys */ - - /* read sas_iounit page 0 */ - sz = offsetof(Mpi2SasIOUnitPage0_t, PhyData) + (ioc->sas_hba.num_phys * - sizeof(Mpi2SasIOUnit0PhyData_t)); - sas_iounit_pg0 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg0) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENOMEM; - goto out; - } - if ((mpt3sas_config_get_sas_iounit_pg0(ioc, &mpi_reply, - sas_iounit_pg0, sz))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENXIO; - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -EIO; - goto out; - } - - /* unable to enable/disable phys when when discovery is active */ - for (i = 0, discovery_active = 0; i < ioc->sas_hba.num_phys ; i++) { - if (sas_iounit_pg0->PhyData[i].PortFlags & - MPI2_SASIOUNIT0_PORTFLAGS_DISCOVERY_IN_PROGRESS) { - pr_err(MPT3SAS_FMT "discovery is active on " \ - "port = %d, phy = %d: unable to enable/disable " - "phys, try again later!\n", ioc->name, - sas_iounit_pg0->PhyData[i].Port, i); - discovery_active = 1; - } - } - - if (discovery_active) { - rc = -EAGAIN; - goto out; - } - - /* read sas_iounit page 1 */ - sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * - sizeof(Mpi2SasIOUnit1PhyData_t)); - sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg1) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENOMEM; - goto out; - } - if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, - sas_iounit_pg1, sz))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENXIO; - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -EIO; - goto out; - } - - /* copy Port/PortFlags/PhyFlags from page 0 */ - for (i = 0; i < ioc->sas_hba.num_phys ; i++) { - sas_iounit_pg1->PhyData[i].Port = - sas_iounit_pg0->PhyData[i].Port; - sas_iounit_pg1->PhyData[i].PortFlags = - (sas_iounit_pg0->PhyData[i].PortFlags & - MPI2_SASIOUNIT0_PORTFLAGS_AUTO_PORT_CONFIG); - sas_iounit_pg1->PhyData[i].PhyFlags = - (sas_iounit_pg0->PhyData[i].PhyFlags & - (MPI2_SASIOUNIT0_PHYFLAGS_ZONING_ENABLED + - MPI2_SASIOUNIT0_PHYFLAGS_PHY_DISABLED)); - } - - if (enable) - sas_iounit_pg1->PhyData[phy->number].PhyFlags - &= ~MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; - else - sas_iounit_pg1->PhyData[phy->number].PhyFlags - |= MPI2_SASIOUNIT1_PHYFLAGS_PHY_DISABLE; - - mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, sz); - - /* link reset */ - if (enable) - _transport_phy_reset(phy, 0); - - out: - kfree(sas_iounit_pg1); - kfree(sas_iounit_pg0); - return rc; -} - -/** - * _transport_phy_speed - set phy min/max link rates - * @phy: The sas phy object - * @rates: rates defined in sas_phy_linkrates - * - * Only support sas_host direct attached phys. - * Returns 0 for success, non-zero for failure. - */ -static int -_transport_phy_speed(struct sas_phy *phy, struct sas_phy_linkrates *rates) -{ - struct MPT3SAS_ADAPTER *ioc = phy_to_ioc(phy); - Mpi2SasIOUnitPage1_t *sas_iounit_pg1 = NULL; - Mpi2SasPhyPage0_t phy_pg0; - Mpi2ConfigReply_t mpi_reply; - u16 ioc_status; - u16 sz; - int i; - int rc = 0; - unsigned long flags; - - spin_lock_irqsave(&ioc->sas_node_lock, flags); - if (_transport_sas_node_find_by_sas_address(ioc, - phy->identify.sas_address) == NULL) { - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - return -EINVAL; - } - spin_unlock_irqrestore(&ioc->sas_node_lock, flags); - - if (!rates->minimum_linkrate) - rates->minimum_linkrate = phy->minimum_linkrate; - else if (rates->minimum_linkrate < phy->minimum_linkrate_hw) - rates->minimum_linkrate = phy->minimum_linkrate_hw; - - if (!rates->maximum_linkrate) - rates->maximum_linkrate = phy->maximum_linkrate; - else if (rates->maximum_linkrate > phy->maximum_linkrate_hw) - rates->maximum_linkrate = phy->maximum_linkrate_hw; - - /* handle expander phys */ - if (phy->identify.sas_address != ioc->sas_hba.sas_address) { - phy->minimum_linkrate = rates->minimum_linkrate; - phy->maximum_linkrate = rates->maximum_linkrate; - return _transport_expander_phy_control(ioc, phy, - SMP_PHY_CONTROL_LINK_RESET); - } - - /* handle hba phys */ - - /* sas_iounit page 1 */ - sz = offsetof(Mpi2SasIOUnitPage1_t, PhyData) + (ioc->sas_hba.num_phys * - sizeof(Mpi2SasIOUnit1PhyData_t)); - sas_iounit_pg1 = kzalloc(sz, GFP_KERNEL); - if (!sas_iounit_pg1) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENOMEM; - goto out; - } - if ((mpt3sas_config_get_sas_iounit_pg1(ioc, &mpi_reply, - sas_iounit_pg1, sz))) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENXIO; - goto out; - } - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status != MPI2_IOCSTATUS_SUCCESS) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -EIO; - goto out; - } - - for (i = 0; i < ioc->sas_hba.num_phys; i++) { - if (phy->number != i) { - sas_iounit_pg1->PhyData[i].MaxMinLinkRate = - (ioc->sas_hba.phy[i].phy->minimum_linkrate + - (ioc->sas_hba.phy[i].phy->maximum_linkrate << 4)); - } else { - sas_iounit_pg1->PhyData[i].MaxMinLinkRate = - (rates->minimum_linkrate + - (rates->maximum_linkrate << 4)); - } - } - - if (mpt3sas_config_set_sas_iounit_pg1(ioc, &mpi_reply, sas_iounit_pg1, - sz)) { - pr_err(MPT3SAS_FMT "failure at %s:%d/%s()!\n", - ioc->name, __FILE__, __LINE__, __func__); - rc = -ENXIO; - goto out; - } - - /* link reset */ - _transport_phy_reset(phy, 0); - - /* read phy page 0, then update the rates in the sas transport phy */ - if (!mpt3sas_config_get_phy_pg0(ioc, &mpi_reply, &phy_pg0, - phy->number)) { - phy->minimum_linkrate = _transport_convert_phy_link_rate( - phy_pg0.ProgrammedLinkRate & MPI2_SAS_PRATE_MIN_RATE_MASK); - phy->maximum_linkrate = _transport_convert_phy_link_rate( - phy_pg0.ProgrammedLinkRate >> 4); - phy->negotiated_linkrate = _transport_convert_phy_link_rate( - phy_pg0.NegotiatedLinkRate & - MPI2_SAS_NEG_LINK_RATE_MASK_PHYSICAL); - } - - out: - kfree(sas_iounit_pg1); - return rc; -} - -/** - * _transport_smp_handler - transport portal for smp passthru - * @shost: shost object - * @rphy: sas transport rphy object - * @req: - * - * This used primarily for smp_utils. - * Example: - * smp_rep_general /sys/class/bsg/expander-5:0 - */ -static int -_transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, - struct request *req) -{ - struct MPT3SAS_ADAPTER *ioc = shost_priv(shost); - Mpi2SmpPassthroughRequest_t *mpi_request; - Mpi2SmpPassthroughReply_t *mpi_reply; - int rc; - u16 smid; - u32 ioc_state; - unsigned long timeleft; - void *psge; - u8 issue_reset = 0; - dma_addr_t dma_addr_in = 0; - dma_addr_t dma_addr_out = 0; - dma_addr_t pci_dma_in = 0; - dma_addr_t pci_dma_out = 0; - void *pci_addr_in = NULL; - void *pci_addr_out = NULL; - u16 wait_state_count; - struct request *rsp = req->next_rq; - struct bio_vec bvec; - struct bvec_iter iter; - - if (!rsp) { - pr_err(MPT3SAS_FMT "%s: the smp response space is missing\n", - ioc->name, __func__); - return -EINVAL; - } - - if (ioc->shost_recovery || ioc->pci_error_recovery) { - pr_info(MPT3SAS_FMT "%s: host reset in progress!\n", - __func__, ioc->name); - return -EFAULT; - } - - rc = mutex_lock_interruptible(&ioc->transport_cmds.mutex); - if (rc) - return rc; - - if (ioc->transport_cmds.status != MPT3_CMD_NOT_USED) { - pr_err(MPT3SAS_FMT "%s: transport_cmds in use\n", ioc->name, - __func__); - rc = -EAGAIN; - goto out; - } - ioc->transport_cmds.status = MPT3_CMD_PENDING; - - /* Check if the request is split across multiple segments */ - if (bio_multiple_segments(req->bio)) { - u32 offset = 0; - - /* Allocate memory and copy the request */ - pci_addr_out = pci_alloc_consistent(ioc->pdev, - blk_rq_bytes(req), &pci_dma_out); - if (!pci_addr_out) { - pr_info(MPT3SAS_FMT "%s(): PCI Addr out = NULL\n", - ioc->name, __func__); - rc = -ENOMEM; - goto out; - } - - bio_for_each_segment(bvec, req->bio, iter) { - memcpy(pci_addr_out + offset, - page_address(bvec.bv_page) + bvec.bv_offset, - bvec.bv_len); - offset += bvec.bv_len; - } - } else { - dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio), - blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(ioc->pdev, dma_addr_out)) { - pr_info(MPT3SAS_FMT "%s(): DMA Addr out = NULL\n", - ioc->name, __func__); - rc = -ENOMEM; - goto free_pci; - } - } - - /* Check if the response needs to be populated across - * multiple segments */ - if (bio_multiple_segments(rsp->bio)) { - pci_addr_in = pci_alloc_consistent(ioc->pdev, blk_rq_bytes(rsp), - &pci_dma_in); - if (!pci_addr_in) { - pr_info(MPT3SAS_FMT "%s(): PCI Addr in = NULL\n", - ioc->name, __func__); - rc = -ENOMEM; - goto unmap; - } - } else { - dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio), - blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(ioc->pdev, dma_addr_in)) { - pr_info(MPT3SAS_FMT "%s(): DMA Addr in = NULL\n", - ioc->name, __func__); - rc = -ENOMEM; - goto unmap; - } - } - - wait_state_count = 0; - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - while (ioc_state != MPI2_IOC_STATE_OPERATIONAL) { - if (wait_state_count++ == 10) { - pr_err(MPT3SAS_FMT - "%s: failed due to ioc not operational\n", - ioc->name, __func__); - rc = -EFAULT; - goto unmap; - } - ssleep(1); - ioc_state = mpt3sas_base_get_iocstate(ioc, 1); - pr_info(MPT3SAS_FMT - "%s: waiting for operational state(count=%d)\n", - ioc->name, __func__, wait_state_count); - } - if (wait_state_count) - pr_info(MPT3SAS_FMT "%s: ioc is operational\n", - ioc->name, __func__); - - smid = mpt3sas_base_get_smid(ioc, ioc->transport_cb_idx); - if (!smid) { - pr_err(MPT3SAS_FMT "%s: failed obtaining a smid\n", - ioc->name, __func__); - rc = -EAGAIN; - goto unmap; - } - - rc = 0; - mpi_request = mpt3sas_base_get_msg_frame(ioc, smid); - ioc->transport_cmds.smid = smid; - - memset(mpi_request, 0, sizeof(Mpi2SmpPassthroughRequest_t)); - mpi_request->Function = MPI2_FUNCTION_SMP_PASSTHROUGH; - mpi_request->PhysicalPort = 0xFF; - mpi_request->SASAddress = (rphy) ? - cpu_to_le64(rphy->identify.sas_address) : - cpu_to_le64(ioc->sas_hba.sas_address); - mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4); - psge = &mpi_request->SGL; - - if (bio_multiple_segments(req->bio)) - ioc->build_sg(ioc, psge, pci_dma_out, (blk_rq_bytes(req) - 4), - pci_dma_in, (blk_rq_bytes(rsp) + 4)); - else - ioc->build_sg(ioc, psge, dma_addr_out, (blk_rq_bytes(req) - 4), - dma_addr_in, (blk_rq_bytes(rsp) + 4)); - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "%s - sending smp request\n", ioc->name, __func__)); - - init_completion(&ioc->transport_cmds.done); - mpt3sas_base_put_smid_default(ioc, smid); - timeleft = wait_for_completion_timeout(&ioc->transport_cmds.done, - 10*HZ); - - if (!(ioc->transport_cmds.status & MPT3_CMD_COMPLETE)) { - pr_err(MPT3SAS_FMT "%s : timeout\n", - __func__, ioc->name); - _debug_dump_mf(mpi_request, - sizeof(Mpi2SmpPassthroughRequest_t)/4); - if (!(ioc->transport_cmds.status & MPT3_CMD_RESET)) - issue_reset = 1; - goto issue_host_reset; - } - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "%s - complete\n", ioc->name, __func__)); - - if (ioc->transport_cmds.status & MPT3_CMD_REPLY_VALID) { - - mpi_reply = ioc->transport_cmds.reply; - - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "%s - reply data transfer size(%d)\n", - ioc->name, __func__, - le16_to_cpu(mpi_reply->ResponseDataLength))); - - memcpy(req->sense, mpi_reply, sizeof(*mpi_reply)); - req->sense_len = sizeof(*mpi_reply); - req->resid_len = 0; - rsp->resid_len -= - le16_to_cpu(mpi_reply->ResponseDataLength); - - /* check if the resp needs to be copied from the allocated - * pci mem */ - if (bio_multiple_segments(rsp->bio)) { - u32 offset = 0; - u32 bytes_to_copy = - le16_to_cpu(mpi_reply->ResponseDataLength); - bio_for_each_segment(bvec, rsp->bio, iter) { - if (bytes_to_copy <= bvec.bv_len) { - memcpy(page_address(bvec.bv_page) + - bvec.bv_offset, pci_addr_in + - offset, bytes_to_copy); - break; - } else { - memcpy(page_address(bvec.bv_page) + - bvec.bv_offset, pci_addr_in + - offset, bvec.bv_len); - bytes_to_copy -= bvec.bv_len; - } - offset += bvec.bv_len; - } - } - } else { - dtransportprintk(ioc, pr_info(MPT3SAS_FMT - "%s - no reply\n", ioc->name, __func__)); - rc = -ENXIO; - } - - issue_host_reset: - if (issue_reset) { - mpt3sas_base_hard_reset_handler(ioc, CAN_SLEEP, - FORCE_BIG_HAMMER); - rc = -ETIMEDOUT; - } - - unmap: - if (dma_addr_out) - pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req), - PCI_DMA_BIDIRECTIONAL); - if (dma_addr_in) - pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp), - PCI_DMA_BIDIRECTIONAL); - - free_pci: - if (pci_addr_out) - pci_free_consistent(ioc->pdev, blk_rq_bytes(req), pci_addr_out, - pci_dma_out); - - if (pci_addr_in) - pci_free_consistent(ioc->pdev, blk_rq_bytes(rsp), pci_addr_in, - pci_dma_in); - - out: - ioc->transport_cmds.status = MPT3_CMD_NOT_USED; - mutex_unlock(&ioc->transport_cmds.mutex); - return rc; -} - -struct sas_function_template mpt3sas_transport_functions = { - .get_linkerrors = _transport_get_linkerrors, - .get_enclosure_identifier = _transport_get_enclosure_identifier, - .get_bay_identifier = _transport_get_bay_identifier, - .phy_reset = _transport_phy_reset, - .phy_enable = _transport_phy_enable, - .set_phy_speed = _transport_phy_speed, - .smp_handler = _transport_smp_handler, -}; - -struct scsi_transport_template *mpt3sas_transport_template; diff --git a/addons/mpt3sas/src/4.4.180/mpt3sas_trigger_diag.c b/addons/mpt3sas/src/4.4.180/mpt3sas_trigger_diag.c deleted file mode 100644 index b60fd7a3..00000000 --- a/addons/mpt3sas/src/4.4.180/mpt3sas_trigger_diag.c +++ /dev/null @@ -1,434 +0,0 @@ -/* - * This module provides common API to set Diagnostic trigger for MPT - * (Message Passing Technology) based controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_trigger_diag.c - * Copyright (C) 2012-2014 LSI Corporation - * Copyright (C) 2013-2014 Avago Technologies - * (mailto: MPT-FusionLinux.pdl@avagotech.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include "mpt3sas_base.h" - -/** - * _mpt3sas_raise_sigio - notifiy app - * @ioc: per adapter object - * @event_data: - */ -static void -_mpt3sas_raise_sigio(struct MPT3SAS_ADAPTER *ioc, - struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data) -{ - Mpi2EventNotificationReply_t *mpi_reply; - u16 sz, event_data_sz; - unsigned long flags; - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", - ioc->name, __func__)); - - sz = offsetof(Mpi2EventNotificationReply_t, EventData) + - sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4; - mpi_reply = kzalloc(sz, GFP_KERNEL); - if (!mpi_reply) - goto out; - mpi_reply->Event = cpu_to_le16(MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED); - event_data_sz = (sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T) + 4) / 4; - mpi_reply->EventDataLength = cpu_to_le16(event_data_sz); - memcpy(&mpi_reply->EventData, event_data, - sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: add to driver event log\n", - ioc->name, __func__)); - mpt3sas_ctl_add_to_event_log(ioc, mpi_reply); - kfree(mpi_reply); - out: - - /* clearing the diag_trigger_active flag */ - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: clearing diag_trigger_active flag\n", - ioc->name, __func__)); - ioc->diag_trigger_active = 0; - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); -} - -/** - * mpt3sas_process_trigger_data - process the event data for the trigger - * @ioc: per adapter object - * @event_data: - */ -void -mpt3sas_process_trigger_data(struct MPT3SAS_ADAPTER *ioc, - struct SL_WH_TRIGGERS_EVENT_DATA_T *event_data) -{ - u8 issue_reset = 0; - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: enter\n", - ioc->name, __func__)); - - /* release the diag buffer trace */ - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED) == 0) { - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: release trace diag buffer\n", ioc->name, __func__)); - mpt3sas_send_diag_release(ioc, MPI2_DIAG_BUF_TYPE_TRACE, - &issue_reset); - } - - _mpt3sas_raise_sigio(ioc, event_data); - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); -} - -/** - * mpt3sas_trigger_master - Master trigger handler - * @ioc: per adapter object - * @trigger_bitmask: - * - */ -void -mpt3sas_trigger_master(struct MPT3SAS_ADAPTER *ioc, u32 trigger_bitmask) -{ - struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; - unsigned long flags; - u8 found_match = 0; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - - if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT || - trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET) - goto by_pass_checks; - - /* check to see if trace buffers are currently registered */ - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - /* check to see if trace buffers are currently released */ - if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - by_pass_checks: - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: enter - trigger_bitmask = 0x%08x\n", - ioc->name, __func__, trigger_bitmask)); - - /* don't send trigger if an trigger is currently active */ - if (ioc->diag_trigger_active) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - goto out; - } - - /* check for the trigger condition */ - if (ioc->diag_trigger_master.MasterData & trigger_bitmask) { - found_match = 1; - ioc->diag_trigger_active = 1; - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: setting diag_trigger_active flag\n", - ioc->name, __func__)); - } - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - - if (!found_match) - goto out; - - memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); - event_data.trigger_type = MPT3SAS_TRIGGER_MASTER; - event_data.u.master.MasterData = trigger_bitmask; - - if (trigger_bitmask & MASTER_TRIGGER_FW_FAULT || - trigger_bitmask & MASTER_TRIGGER_ADAPTER_RESET) - _mpt3sas_raise_sigio(ioc, &event_data); - else - mpt3sas_send_trigger_data_event(ioc, &event_data); - - out: - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); -} - -/** - * mpt3sas_trigger_event - Event trigger handler - * @ioc: per adapter object - * @event: - * @log_entry_qualifier: - * - */ -void -mpt3sas_trigger_event(struct MPT3SAS_ADAPTER *ioc, u16 event, - u16 log_entry_qualifier) -{ - struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; - struct SL_WH_EVENT_TRIGGER_T *event_trigger; - int i; - unsigned long flags; - u8 found_match; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - - /* check to see if trace buffers are currently registered */ - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - /* check to see if trace buffers are currently released */ - if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: enter - event = 0x%04x, log_entry_qualifier = 0x%04x\n", - ioc->name, __func__, event, log_entry_qualifier)); - - /* don't send trigger if an trigger is currently active */ - if (ioc->diag_trigger_active) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - goto out; - } - - /* check for the trigger condition */ - event_trigger = ioc->diag_trigger_event.EventTriggerEntry; - for (i = 0 , found_match = 0; i < ioc->diag_trigger_event.ValidEntries - && !found_match; i++, event_trigger++) { - if (event_trigger->EventValue != event) - continue; - if (event == MPI2_EVENT_LOG_ENTRY_ADDED) { - if (event_trigger->LogEntryQualifier == - log_entry_qualifier) - found_match = 1; - continue; - } - found_match = 1; - ioc->diag_trigger_active = 1; - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: setting diag_trigger_active flag\n", - ioc->name, __func__)); - } - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - - if (!found_match) - goto out; - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: setting diag_trigger_active flag\n", - ioc->name, __func__)); - memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); - event_data.trigger_type = MPT3SAS_TRIGGER_EVENT; - event_data.u.event.EventValue = event; - event_data.u.event.LogEntryQualifier = log_entry_qualifier; - mpt3sas_send_trigger_data_event(ioc, &event_data); - out: - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); -} - -/** - * mpt3sas_trigger_scsi - SCSI trigger handler - * @ioc: per adapter object - * @sense_key: - * @asc: - * @ascq: - * - */ -void -mpt3sas_trigger_scsi(struct MPT3SAS_ADAPTER *ioc, u8 sense_key, u8 asc, - u8 ascq) -{ - struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; - struct SL_WH_SCSI_TRIGGER_T *scsi_trigger; - int i; - unsigned long flags; - u8 found_match; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - - /* check to see if trace buffers are currently registered */ - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - /* check to see if trace buffers are currently released */ - if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: enter - sense_key = 0x%02x, asc = 0x%02x, ascq = 0x%02x\n", - ioc->name, __func__, sense_key, asc, ascq)); - - /* don't send trigger if an trigger is currently active */ - if (ioc->diag_trigger_active) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - goto out; - } - - /* check for the trigger condition */ - scsi_trigger = ioc->diag_trigger_scsi.SCSITriggerEntry; - for (i = 0 , found_match = 0; i < ioc->diag_trigger_scsi.ValidEntries - && !found_match; i++, scsi_trigger++) { - if (scsi_trigger->SenseKey != sense_key) - continue; - if (!(scsi_trigger->ASC == 0xFF || scsi_trigger->ASC == asc)) - continue; - if (!(scsi_trigger->ASCQ == 0xFF || scsi_trigger->ASCQ == ascq)) - continue; - found_match = 1; - ioc->diag_trigger_active = 1; - } - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - - if (!found_match) - goto out; - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: setting diag_trigger_active flag\n", - ioc->name, __func__)); - memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); - event_data.trigger_type = MPT3SAS_TRIGGER_SCSI; - event_data.u.scsi.SenseKey = sense_key; - event_data.u.scsi.ASC = asc; - event_data.u.scsi.ASCQ = ascq; - mpt3sas_send_trigger_data_event(ioc, &event_data); - out: - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); -} - -/** - * mpt3sas_trigger_mpi - MPI trigger handler - * @ioc: per adapter object - * @ioc_status: - * @loginfo: - * - */ -void -mpt3sas_trigger_mpi(struct MPT3SAS_ADAPTER *ioc, u16 ioc_status, u32 loginfo) -{ - struct SL_WH_TRIGGERS_EVENT_DATA_T event_data; - struct SL_WH_MPI_TRIGGER_T *mpi_trigger; - int i; - unsigned long flags; - u8 found_match; - - spin_lock_irqsave(&ioc->diag_trigger_lock, flags); - - /* check to see if trace buffers are currently registered */ - if ((ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_REGISTERED) == 0) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - /* check to see if trace buffers are currently released */ - if (ioc->diag_buffer_status[MPI2_DIAG_BUF_TYPE_TRACE] & - MPT3_DIAG_BUFFER_IS_RELEASED) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - return; - } - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: enter - ioc_status = 0x%04x, loginfo = 0x%08x\n", - ioc->name, __func__, ioc_status, loginfo)); - - /* don't send trigger if an trigger is currently active */ - if (ioc->diag_trigger_active) { - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - goto out; - } - - /* check for the trigger condition */ - mpi_trigger = ioc->diag_trigger_mpi.MPITriggerEntry; - for (i = 0 , found_match = 0; i < ioc->diag_trigger_mpi.ValidEntries - && !found_match; i++, mpi_trigger++) { - if (mpi_trigger->IOCStatus != ioc_status) - continue; - if (!(mpi_trigger->IocLogInfo == 0xFFFFFFFF || - mpi_trigger->IocLogInfo == loginfo)) - continue; - found_match = 1; - ioc->diag_trigger_active = 1; - } - spin_unlock_irqrestore(&ioc->diag_trigger_lock, flags); - - if (!found_match) - goto out; - - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT - "%s: setting diag_trigger_active flag\n", - ioc->name, __func__)); - memset(&event_data, 0, sizeof(struct SL_WH_TRIGGERS_EVENT_DATA_T)); - event_data.trigger_type = MPT3SAS_TRIGGER_MPI; - event_data.u.mpi.IOCStatus = ioc_status; - event_data.u.mpi.IocLogInfo = loginfo; - mpt3sas_send_trigger_data_event(ioc, &event_data); - out: - dTriggerDiagPrintk(ioc, pr_info(MPT3SAS_FMT "%s: exit\n", ioc->name, - __func__)); -} diff --git a/addons/mpt3sas/src/4.4.180/mpt3sas_trigger_diag.h b/addons/mpt3sas/src/4.4.180/mpt3sas_trigger_diag.h deleted file mode 100644 index 6586a463..00000000 --- a/addons/mpt3sas/src/4.4.180/mpt3sas_trigger_diag.h +++ /dev/null @@ -1,194 +0,0 @@ -/* - * This is the Fusion MPT base driver providing common API layer interface - * to set Diagnostic triggers for MPT (Message Passing Technology) based - * controllers - * - * This code is based on drivers/scsi/mpt3sas/mpt3sas_base.h - * Copyright (C) 2012-2014 LSI Corporation - * Copyright (C) 2013-2014 Avago Technologies - * (mailto: MPT-FusionLinux.pdl@avagotech.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * 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. - */ - /* Diagnostic Trigger Configuration Data Structures */ - -#ifndef MPT3SAS_TRIGGER_DIAG_H_INCLUDED -#define MPT3SAS_TRIGGER_DIAG_H_INCLUDED - -/* limitation on number of entries */ -#define NUM_VALID_ENTRIES (20) - -/* trigger types */ -#define MPT3SAS_TRIGGER_MASTER (1) -#define MPT3SAS_TRIGGER_EVENT (2) -#define MPT3SAS_TRIGGER_SCSI (3) -#define MPT3SAS_TRIGGER_MPI (4) - -/* trigger names */ -#define MASTER_TRIGGER_FILE_NAME "diag_trigger_master" -#define EVENT_TRIGGERS_FILE_NAME "diag_trigger_event" -#define SCSI_TRIGGERS_FILE_NAME "diag_trigger_scsi" -#define MPI_TRIGGER_FILE_NAME "diag_trigger_mpi" - -/* master trigger bitmask */ -#define MASTER_TRIGGER_FW_FAULT (0x00000001) -#define MASTER_TRIGGER_ADAPTER_RESET (0x00000002) -#define MASTER_TRIGGER_TASK_MANAGMENT (0x00000004) -#define MASTER_TRIGGER_DEVICE_REMOVAL (0x00000008) - -/* fake firmware event for tigger */ -#define MPI3_EVENT_DIAGNOSTIC_TRIGGER_FIRED (0x6E) - -/** - * MasterTrigger is a single U32 passed to/from sysfs. - * - * Bit Flags (enables) include: - * 1. FW Faults - * 2. Adapter Reset issued by driver - * 3. TMs - * 4. Device Remove Event sent by FW - */ - -struct SL_WH_MASTER_TRIGGER_T { - uint32_t MasterData; -}; - -/** - * struct SL_WH_EVENT_TRIGGER_T - Definition of an event trigger element - * @EventValue: Event Code to trigger on - * @LogEntryQualifier: Type of FW event that logged (Log Entry Added Event only) - * - * Defines an event that should induce a DIAG_TRIGGER driver event if observed. - */ -struct SL_WH_EVENT_TRIGGER_T { - uint16_t EventValue; - uint16_t LogEntryQualifier; -}; - -/** - * struct SL_WH_EVENT_TRIGGERS_T - Structure passed to/from sysfs containing a - * list of Event Triggers to be monitored for. - * @ValidEntries: Number of _SL_WH_EVENT_TRIGGER_T structures contained in this - * structure. - * @EventTriggerEntry: List of Event trigger elements. - * - * This binary structure is transferred via sysfs to get/set Event Triggers - * in the Linux Driver. - */ - -struct SL_WH_EVENT_TRIGGERS_T { - uint32_t ValidEntries; - struct SL_WH_EVENT_TRIGGER_T EventTriggerEntry[NUM_VALID_ENTRIES]; -}; - -/** - * struct SL_WH_SCSI_TRIGGER_T - Definition of a SCSI trigger element - * @ASCQ: Additional Sense Code Qualifier. Can be specific or 0xFF for - * wildcard. - * @ASC: Additional Sense Code. Can be specific or 0xFF for wildcard - * @SenseKey: SCSI Sense Key - * - * Defines a sense key (single or many variants) that should induce a - * DIAG_TRIGGER driver event if observed. - */ -struct SL_WH_SCSI_TRIGGER_T { - U8 ASCQ; - U8 ASC; - U8 SenseKey; - U8 Reserved; -}; - -/** - * struct SL_WH_SCSI_TRIGGERS_T - Structure passed to/from sysfs containing a - * list of SCSI sense codes that should trigger a DIAG_SERVICE event when - * observed. - * @ValidEntries: Number of _SL_WH_SCSI_TRIGGER_T structures contained in this - * structure. - * @SCSITriggerEntry: List of SCSI Sense Code trigger elements. - * - * This binary structure is transferred via sysfs to get/set SCSI Sense Code - * Triggers in the Linux Driver. - */ -struct SL_WH_SCSI_TRIGGERS_T { - uint32_t ValidEntries; - struct SL_WH_SCSI_TRIGGER_T SCSITriggerEntry[NUM_VALID_ENTRIES]; -}; - -/** - * struct SL_WH_MPI_TRIGGER_T - Definition of an MPI trigger element - * @IOCStatus: MPI IOCStatus - * @IocLogInfo: MPI IocLogInfo. Can be specific or 0xFFFFFFFF for wildcard - * - * Defines a MPI IOCStatus/IocLogInfo pair that should induce a DIAG_TRIGGER - * driver event if observed. - */ -struct SL_WH_MPI_TRIGGER_T { - uint16_t IOCStatus; - uint16_t Reserved; - uint32_t IocLogInfo; -}; - -/** - * struct SL_WH_MPI_TRIGGERS_T - Structure passed to/from sysfs containing a - * list of MPI IOCStatus/IocLogInfo pairs that should trigger a DIAG_SERVICE - * event when observed. - * @ValidEntries: Number of _SL_WH_MPI_TRIGGER_T structures contained in this - * structure. - * @MPITriggerEntry: List of MPI IOCStatus/IocLogInfo trigger elements. - * - * This binary structure is transferred via sysfs to get/set MPI Error Triggers - * in the Linux Driver. - */ -struct SL_WH_MPI_TRIGGERS_T { - uint32_t ValidEntries; - struct SL_WH_MPI_TRIGGER_T MPITriggerEntry[NUM_VALID_ENTRIES]; -}; - -/** - * struct SL_WH_TRIGGERS_EVENT_DATA_T - event data for trigger - * @trigger_type: trigger type (see MPT3SAS_TRIGGER_XXXX) - * @u: trigger condition that caused trigger to be sent - */ -struct SL_WH_TRIGGERS_EVENT_DATA_T { - uint32_t trigger_type; - union { - struct SL_WH_MASTER_TRIGGER_T master; - struct SL_WH_EVENT_TRIGGER_T event; - struct SL_WH_SCSI_TRIGGER_T scsi; - struct SL_WH_MPI_TRIGGER_T mpi; - } u; -}; -#endif /* MPT3SAS_TRIGGER_DIAG_H_INCLUDED */ diff --git a/addons/mpt3sas/src/4.4.180/mpt3sas_warpdrive.c b/addons/mpt3sas/src/4.4.180/mpt3sas_warpdrive.c deleted file mode 100644 index 540bd500..00000000 --- a/addons/mpt3sas/src/4.4.180/mpt3sas_warpdrive.c +++ /dev/null @@ -1,344 +0,0 @@ -/* - * Scsi Host Layer for MPT (Message Passing Technology) based controllers - * - * Copyright (C) 2012-2014 LSI Corporation - * Copyright (C) 2013-2015 Avago Technologies - * (mailto: MPT-FusionLinux.pdl@avagotech.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * NO WARRANTY - * THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR - * CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT - * LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, - * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is - * solely responsible for determining the appropriateness of using and - * distributing the Program and assumes all risks associated with its - * exercise of rights under this Agreement, including but not limited to - * the risks and costs of program errors, damage to or loss of data, - * programs or equipment, and unavailability or interruption of operations. - - * DISCLAIMER OF LIABILITY - * NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR - * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE - * USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED - * HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES - - * You should have received a copy of the GNU General Public License - * along with this program. - */ -#include -#include -#include -#include -#include - -#include "mpt3sas_base.h" - -/** - * _warpdrive_disable_ddio - Disable direct I/O for all the volumes - * @ioc: per adapter object - */ -static void -_warpdrive_disable_ddio(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2RaidVolPage1_t vol_pg1; - Mpi2ConfigReply_t mpi_reply; - struct _raid_device *raid_device; - u16 handle; - u16 ioc_status; - unsigned long flags; - - handle = 0xFFFF; - while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, - &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) - break; - handle = le16_to_cpu(vol_pg1.DevHandle); - spin_lock_irqsave(&ioc->raid_device_lock, flags); - raid_device = mpt3sas_raid_device_find_by_handle(ioc, handle); - if (raid_device) - raid_device->direct_io_enabled = 0; - spin_unlock_irqrestore(&ioc->raid_device_lock, flags); - } - return; -} - - -/** - * mpt3sas_get_num_volumes - Get number of volumes in the ioc - * @ioc: per adapter object - */ -u8 -mpt3sas_get_num_volumes(struct MPT3SAS_ADAPTER *ioc) -{ - Mpi2RaidVolPage1_t vol_pg1; - Mpi2ConfigReply_t mpi_reply; - u16 handle; - u8 vol_cnt = 0; - u16 ioc_status; - - handle = 0xFFFF; - while (!(mpt3sas_config_get_raid_volume_pg1(ioc, &mpi_reply, - &vol_pg1, MPI2_RAID_VOLUME_PGAD_FORM_GET_NEXT_HANDLE, handle))) { - ioc_status = le16_to_cpu(mpi_reply.IOCStatus) & - MPI2_IOCSTATUS_MASK; - if (ioc_status == MPI2_IOCSTATUS_CONFIG_INVALID_PAGE) - break; - vol_cnt++; - handle = le16_to_cpu(vol_pg1.DevHandle); - } - return vol_cnt; -} - - -/** - * mpt3sas_init_warpdrive_properties - Set properties for warpdrive direct I/O. - * @ioc: per adapter object - * @raid_device: the raid_device object - */ -void -mpt3sas_init_warpdrive_properties(struct MPT3SAS_ADAPTER *ioc, - struct _raid_device *raid_device) -{ - Mpi2RaidVolPage0_t *vol_pg0; - Mpi2RaidPhysDiskPage0_t pd_pg0; - Mpi2ConfigReply_t mpi_reply; - u16 sz; - u8 num_pds, count; - unsigned long stripe_sz, block_sz; - u8 stripe_exp, block_exp; - u64 dev_max_lba; - - if (!ioc->is_warpdrive) - return; - - if (ioc->mfg_pg10_hide_flag == MFG_PAGE10_EXPOSE_ALL_DISKS) { - pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " - "globally as drives are exposed\n", ioc->name); - return; - } - if (mpt3sas_get_num_volumes(ioc) > 1) { - _warpdrive_disable_ddio(ioc); - pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " - "globally as number of drives > 1\n", ioc->name); - return; - } - if ((mpt3sas_config_get_number_pds(ioc, raid_device->handle, - &num_pds)) || !num_pds) { - pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " - "Failure in computing number of drives\n", ioc->name); - return; - } - - sz = offsetof(Mpi2RaidVolPage0_t, PhysDisk) + (num_pds * - sizeof(Mpi2RaidVol0PhysDisk_t)); - vol_pg0 = kzalloc(sz, GFP_KERNEL); - if (!vol_pg0) { - pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " - "Memory allocation failure for RVPG0\n", ioc->name); - return; - } - - if ((mpt3sas_config_get_raid_volume_pg0(ioc, &mpi_reply, vol_pg0, - MPI2_RAID_VOLUME_PGAD_FORM_HANDLE, raid_device->handle, sz))) { - pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " - "Failure in retrieving RVPG0\n", ioc->name); - kfree(vol_pg0); - return; - } - - /* - * WARPDRIVE:If number of physical disks in a volume exceeds the max pds - * assumed for WARPDRIVE, disable direct I/O - */ - if (num_pds > MPT_MAX_WARPDRIVE_PDS) { - pr_warn(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " - "for the drive with handle(0x%04x): num_mem=%d, " - "max_mem_allowed=%d\n", ioc->name, raid_device->handle, - num_pds, MPT_MAX_WARPDRIVE_PDS); - kfree(vol_pg0); - return; - } - for (count = 0; count < num_pds; count++) { - if (mpt3sas_config_get_phys_disk_pg0(ioc, &mpi_reply, - &pd_pg0, MPI2_PHYSDISK_PGAD_FORM_PHYSDISKNUM, - vol_pg0->PhysDisk[count].PhysDiskNum) || - pd_pg0.DevHandle == MPT3SAS_INVALID_DEVICE_HANDLE) { - pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is " - "disabled for the drive with handle(0x%04x) member" - "handle retrieval failed for member number=%d\n", - ioc->name, raid_device->handle, - vol_pg0->PhysDisk[count].PhysDiskNum); - goto out_error; - } - /* Disable direct I/O if member drive lba exceeds 4 bytes */ - dev_max_lba = le64_to_cpu(pd_pg0.DeviceMaxLBA); - if (dev_max_lba >> 32) { - pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is " - "disabled for the drive with handle(0x%04x) member" - " handle (0x%04x) unsupported max lba 0x%016llx\n", - ioc->name, raid_device->handle, - le16_to_cpu(pd_pg0.DevHandle), - (unsigned long long)dev_max_lba); - goto out_error; - } - - raid_device->pd_handle[count] = le16_to_cpu(pd_pg0.DevHandle); - } - - /* - * Assumption for WD: Direct I/O is not supported if the volume is - * not RAID0 - */ - if (raid_device->volume_type != MPI2_RAID_VOL_TYPE_RAID0) { - pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " - "for the drive with handle(0x%04x): type=%d, " - "s_sz=%uK, blk_size=%u\n", ioc->name, - raid_device->handle, raid_device->volume_type, - (le32_to_cpu(vol_pg0->StripeSize) * - le16_to_cpu(vol_pg0->BlockSize)) / 1024, - le16_to_cpu(vol_pg0->BlockSize)); - goto out_error; - } - - stripe_sz = le32_to_cpu(vol_pg0->StripeSize); - stripe_exp = find_first_bit(&stripe_sz, 32); - if (stripe_exp == 32) { - pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " - "for the drive with handle(0x%04x) invalid stripe sz %uK\n", - ioc->name, raid_device->handle, - (le32_to_cpu(vol_pg0->StripeSize) * - le16_to_cpu(vol_pg0->BlockSize)) / 1024); - goto out_error; - } - raid_device->stripe_exponent = stripe_exp; - block_sz = le16_to_cpu(vol_pg0->BlockSize); - block_exp = find_first_bit(&block_sz, 16); - if (block_exp == 16) { - pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is disabled " - "for the drive with handle(0x%04x) invalid block sz %u\n", - ioc->name, raid_device->handle, - le16_to_cpu(vol_pg0->BlockSize)); - goto out_error; - } - raid_device->block_exponent = block_exp; - raid_device->direct_io_enabled = 1; - - pr_info(MPT3SAS_FMT "WarpDrive : Direct IO is Enabled for the drive" - " with handle(0x%04x)\n", ioc->name, raid_device->handle); - /* - * WARPDRIVE: Though the following fields are not used for direct IO, - * stored for future purpose: - */ - raid_device->max_lba = le64_to_cpu(vol_pg0->MaxLBA); - raid_device->stripe_sz = le32_to_cpu(vol_pg0->StripeSize); - raid_device->block_sz = le16_to_cpu(vol_pg0->BlockSize); - - - kfree(vol_pg0); - return; - -out_error: - raid_device->direct_io_enabled = 0; - for (count = 0; count < num_pds; count++) - raid_device->pd_handle[count] = 0; - kfree(vol_pg0); - return; -} - -/** - * mpt3sas_scsi_direct_io_get - returns direct io flag - * @ioc: per adapter object - * @smid: system request message index - * - * Returns the smid stored scmd pointer. - */ -inline u8 -mpt3sas_scsi_direct_io_get(struct MPT3SAS_ADAPTER *ioc, u16 smid) -{ - return ioc->scsi_lookup[smid - 1].direct_io; -} - -/** - * mpt3sas_scsi_direct_io_set - sets direct io flag - * @ioc: per adapter object - * @smid: system request message index - * @direct_io: Zero or non-zero value to set in the direct_io flag - * - * Returns Nothing. - */ -inline void -mpt3sas_scsi_direct_io_set(struct MPT3SAS_ADAPTER *ioc, u16 smid, u8 direct_io) -{ - ioc->scsi_lookup[smid - 1].direct_io = direct_io; -} - -/** - * mpt3sas_setup_direct_io - setup MPI request for WARPDRIVE Direct I/O - * @ioc: per adapter object - * @scmd: pointer to scsi command object - * @raid_device: pointer to raid device data structure - * @mpi_request: pointer to the SCSI_IO reqest message frame - * @smid: system request message index - * - * Returns nothing - */ -void -mpt3sas_setup_direct_io(struct MPT3SAS_ADAPTER *ioc, struct scsi_cmnd *scmd, - struct _raid_device *raid_device, Mpi2SCSIIORequest_t *mpi_request, - u16 smid) -{ - sector_t v_lba, p_lba, stripe_off, column, io_size; - u32 stripe_sz, stripe_exp; - u8 num_pds, cmd = scmd->cmnd[0]; - - if (cmd != READ_10 && cmd != WRITE_10 && - cmd != READ_16 && cmd != WRITE_16) - return; - - if (cmd == READ_10 || cmd == WRITE_10) - v_lba = get_unaligned_be32(&mpi_request->CDB.CDB32[2]); - else - v_lba = get_unaligned_be64(&mpi_request->CDB.CDB32[2]); - - io_size = scsi_bufflen(scmd) >> raid_device->block_exponent; - - if (v_lba + io_size - 1 > raid_device->max_lba) - return; - - stripe_sz = raid_device->stripe_sz; - stripe_exp = raid_device->stripe_exponent; - stripe_off = v_lba & (stripe_sz - 1); - - /* Return unless IO falls within a stripe */ - if (stripe_off + io_size > stripe_sz) - return; - - num_pds = raid_device->num_pds; - p_lba = v_lba >> stripe_exp; - column = sector_div(p_lba, num_pds); - p_lba = (p_lba << stripe_exp) + stripe_off; - mpi_request->DevHandle = cpu_to_le16(raid_device->pd_handle[column]); - - if (cmd == READ_10 || cmd == WRITE_10) - put_unaligned_be32(lower_32_bits(p_lba), - &mpi_request->CDB.CDB32[2]); - else - put_unaligned_be64(p_lba, &mpi_request->CDB.CDB32[2]); - - mpt3sas_scsi_direct_io_set(ioc, smid, 1); -} diff --git a/addons/qjs-dtb/all/addons/dts.js b/addons/qjs-dtb/all/addons/dts.js deleted file mode 100644 index 4d0fca87..00000000 --- a/addons/qjs-dtb/all/addons/dts.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see bundle.js.LICENSE.txt */ -(()=>{var t={654:()=>{}},e={};function n(s){var i=e[s];if(void 0!==i)return i.exports;var r=e[s]={exports:{}};return t[s](r,r.exports,n),r.exports}(()=>{"use strict";String.prototype.seed=String.prototype.seed||Math.round(Math.random()*Math.pow(2,32)),String.prototype.hashCode=function(){const t=this.toString();let e,n;const s=3&t.length,i=t.length-s;let r=String.prototype.seed;const o=3432918353,a=461845907;let l=0;for(;l>>16)*o&65535)<<16)&4294967295,n=n<<15|n>>>17,n=(65535&n)*a+(((n>>>16)*a&65535)<<16)&4294967295,r^=n,r=r<<13|r>>>19,e=5*(65535&r)+((5*(r>>>16)&65535)<<16)&4294967295,r=27492+(65535&e)+((58964+(e>>>16)&65535)<<16);switch(n=0,s){case 3:n^=(255&t.charCodeAt(l+2))<<16;case 2:n^=(255&t.charCodeAt(l+1))<<8;case 1:n^=255&t.charCodeAt(l),n=(65535&n)*o+(((n>>>16)*o&65535)<<16)&4294967295,n=n<<15|n>>>17,n=(65535&n)*a+(((n>>>16)*a&65535)<<16)&4294967295,r^=n}return r^=t.length,r^=r>>>16,r=2246822507*(65535&r)+((2246822507*(r>>>16)&65535)<<16)&4294967295,r^=r>>>13,r=3266489909*(65535&r)+((3266489909*(r>>>16)&65535)<<16)&4294967295,r^=r>>>16,r>>>0},String.prototype.codePointAt||function(){var t=function(){let t;try{const e={},n=Object.defineProperty;t=n(e,e,e)&&n}catch(t){}return t}();const e=function(t){if(null==this)throw TypeError();const e=String(this),n=e.length;let s=t?Number(t):0;if(s!=s&&(s=0),s<0||s>=n)return;const i=e.charCodeAt(s);let r;return i>=55296&&i<=56319&&n>s+1&&(r=e.charCodeAt(s+1),r>=56320&&r<=57343)?1024*(i-55296)+r-56320+65536:i};t?t(String.prototype,"codePointAt",{value:e,configurable:!0,writable:!0}):String.prototype.codePointAt=e}(),String.fromCodePoint||function(){const t=function(){let t;try{const e={},n=Object.defineProperty;t=n(e,e,e)&&n}catch(t){}return t}(),e=String.fromCharCode,n=Math.floor,s=function(t){const s=16384,i=[];let r,o,a=-1;const l=arguments.length;if(!l)return"";let h="";for(;++a1114111||n(t)!==t)throw RangeError("Invalid code point: "+t);t<=65535?i.push(t):(t-=65536,r=55296+(t>>10),o=t%1024+56320,i.push(r,o)),(a+1===l||i.length>s)&&(h+=e.apply(null,i),i.length=0)}return h};t?t(String,"fromCodePoint",{value:s,configurable:!0,writable:!0}):String.fromCodePoint=s}();class t{constructor(){this.source=null,this.type=null,this.channel=null,this.start=null,this.stop=null,this.tokenIndex=null,this.line=null,this.column=null,this._text=null}getTokenSource(){return this.source[0]}getInputStream(){return this.source[1]}get text(){return this._text}set text(t){this._text=t}}function e(t,e){if(!Array.isArray(t)||!Array.isArray(e))return!1;if(t===e)return!0;if(t.length!==e.length)return!1;for(let n=0;n>>17,t*=461845907,this.count=this.count+1;let n=this.hash^t;n=n<<13|n>>>19,n=5*n+3864292196,this.hash=n}}}finish(){let t=this.hash^4*this.count;return t^=t>>>16,t*=2246822507,t^=t>>>13,t*=3266489909,t^=t>>>16,t}static hashStuff(){const t=new s;return t.update.apply(t,arguments),t.finish()}}function i(t){return t?t.hashCode():-1}function r(t,e){return t?t.equals(e):t===e}function o(t){return null===t?"null":t}function a(t){return Array.isArray(t)?"["+t.map(o).join(", ")+"]":"null"}const l="h-";class h{constructor(t,e){this.data={},this.hashFunction=t||i,this.equalsFunction=e||r}add(t){const e=l+this.hashFunction(t);if(e in this.data){const n=this.data[e];for(let e=0;et.startsWith(l))).flatMap((t=>this.data[t]),this)}toString(){return a(this.values())}get length(){return Object.keys(this.data).filter((t=>t.startsWith(l))).map((t=>this.data[t].length),this).reduce(((t,e)=>t+e),0)}}class c{hashCode(){const t=new s;return this.updateHashCode(t),t.finish()}evaluate(t,e){}evalPrecedence(t,e){return this}static andContext(t,e){if(null===t||t===c.NONE)return e;if(null===e||e===c.NONE)return t;const n=new u(t,e);return 1===n.opnds.length?n.opnds[0]:n}static orContext(t,e){if(null===t)return e;if(null===e)return t;if(t===c.NONE||e===c.NONE)return c.NONE;const n=new d(t,e);return 1===n.opnds.length?n.opnds[0]:n}}class u extends c{constructor(t,e){super();const n=new h;t instanceof u?t.opnds.map((function(t){n.add(t)})):n.add(t),e instanceof u?e.opnds.map((function(t){n.add(t)})):n.add(e);const s=p(n);if(s.length>0){let t=null;s.map((function(e){(null===t||e.precedencet.toString()));return(t.length>3?t.slice(3):t).join("&&")}}class d extends c{constructor(t,e){super();const n=new h;t instanceof d?t.opnds.map((function(t){n.add(t)})):n.add(t),e instanceof d?e.opnds.map((function(t){n.add(t)})):n.add(e);const s=p(n);if(s.length>0){const t=s.sort((function(t,e){return t.compareTo(e)})),e=t[t.length-1];n.add(e)}this.opnds=Array.from(n.values())}equals(t){return this===t||t instanceof d&&e(this.opnds,t.opnds)}updateHashCode(t){t.update(this.opnds,"OR")}evaluate(t,e){for(let n=0;nt.toString()));return(t.length>3?t.slice(3):t).join("||")}}function p(t){const e=[];return t.values().map((function(t){t instanceof c.PrecedencePredicate&&e.push(t)})),e}function g(t,e){if(null===t){const t={state:null,alt:null,context:null,semanticContext:null};return e&&(t.reachesIntoOuterContext=0),t}{const n={};return n.state=t.state||null,n.alt=void 0===t.alt?null:t.alt,n.context=t.context||null,n.semanticContext=t.semanticContext||null,e&&(n.reachesIntoOuterContext=t.reachesIntoOuterContext||0,n.precedenceFilterSuppressed=t.precedenceFilterSuppressed||!1),n}}class f{constructor(t,e){this.checkContext(t,e),t=g(t),e=g(e,!0),this.state=null!==t.state?t.state:e.state,this.alt=null!==t.alt?t.alt:e.alt,this.context=null!==t.context?t.context:e.context,this.semanticContext=null!==t.semanticContext?t.semanticContext:null!==e.semanticContext?e.semanticContext:c.NONE,this.reachesIntoOuterContext=e.reachesIntoOuterContext,this.precedenceFilterSuppressed=e.precedenceFilterSuppressed}checkContext(t,e){null!==t.context&&void 0!==t.context||null!==e&&null!==e.context&&void 0!==e.context||(this.context=null)}hashCode(){const t=new s;return this.updateHashCode(t),t.finish()}updateHashCode(t){t.update(this.state.stateNumber,this.alt,this.context,this.semanticContext)}equals(t){return this===t||t instanceof f&&this.state.stateNumber===t.state.stateNumber&&this.alt===t.alt&&(null===this.context?null===t.context:this.context.equals(t.context))&&this.semanticContext.equals(t.semanticContext)&&this.precedenceFilterSuppressed===t.precedenceFilterSuppressed}hashCodeForConfigSet(){const t=new s;return t.update(this.state.stateNumber,this.alt,this.semanticContext),t.finish()}equalsForConfigSet(t){return this===t||t instanceof f&&this.state.stateNumber===t.state.stateNumber&&this.alt===t.alt&&this.semanticContext.equals(t.semanticContext)}toString(){return"("+this.state+","+this.alt+(null!==this.context?",["+this.context.toString()+"]":"")+(this.semanticContext!==c.NONE?","+this.semanticContext.toString():"")+(this.reachesIntoOuterContext>0?",up="+this.reachesIntoOuterContext:"")+")"}}class x{constructor(t,e){this.start=t,this.stop=e}clone(){return new x(this.start,this.stop)}contains(t){return t>=this.start&&tthis.addInterval(t)),this),this}reduce(t){if(t=n.stop?(this.intervals.splice(t+1,1),this.reduce(t)):e.stop>=n.start&&(this.intervals[t]=new x(e.start,n.stop),this.intervals.splice(t+1,1))}}complement(t,e){const n=new T;return n.addInterval(new x(t,e+1)),null!==this.intervals&&this.intervals.forEach((t=>n.removeRange(t))),n}contains(t){if(null===this.intervals)return!1;for(let e=0;en.start&&t.stop=n.stop?(this.intervals.splice(e,1),e-=1):t.start"):e.push("'"+String.fromCharCode(s.start)+"'"):e.push("'"+String.fromCharCode(s.start)+"'..'"+String.fromCharCode(s.stop-1)+"'")}return e.length>1?"{"+e.join(", ")+"}":e[0]}toIndexString(){const e=[];for(let n=0;n"):e.push(s.start.toString()):e.push(s.start.toString()+".."+(s.stop-1).toString())}return e.length>1?"{"+e.join(", ")+"}":e[0]}toTokenString(t,e){const n=[];for(let s=0;s1?"{"+n.join(", ")+"}":n[0]}elementName(e,n,s){return s===t.EOF?"":s===t.EPSILON?"":e[s]||n[s]}get length(){return this.intervals.map((t=>t.length)).reduce(((t,e)=>t+e))}}class S{constructor(){this.atn=null,this.stateNumber=S.INVALID_STATE_NUMBER,this.stateType=null,this.ruleIndex=0,this.epsilonOnlyTransitions=!1,this.transitions=[],this.nextTokenWithinRule=null}toString(){return this.stateNumber}equals(t){return t instanceof S&&this.stateNumber===t.stateNumber}isNonGreedyExitState(){return!1}addTransition(t,e){void 0===e&&(e=-1),0===this.transitions.length?this.epsilonOnlyTransitions=t.isEpsilon:this.epsilonOnlyTransitions!==t.isEpsilon&&(this.epsilonOnlyTransitions=!1),-1===e?this.transitions.push(t):this.transitions.splice(e,1,t)}}S.INVALID_TYPE=0,S.BASIC=1,S.RULE_START=2,S.BLOCK_START=3,S.PLUS_BLOCK_START=4,S.STAR_BLOCK_START=5,S.TOKEN_START=6,S.RULE_STOP=7,S.BLOCK_END=8,S.STAR_LOOP_BACK=9,S.STAR_LOOP_ENTRY=10,S.PLUS_LOOP_BACK=11,S.LOOP_END=12,S.serializationNames=["INVALID","BASIC","RULE_START","BLOCK_START","PLUS_BLOCK_START","STAR_BLOCK_START","TOKEN_START","RULE_STOP","BLOCK_END","STAR_LOOP_BACK","STAR_LOOP_ENTRY","PLUS_LOOP_BACK","LOOP_END"],S.INVALID_STATE_NUMBER=-1;class E extends S{constructor(){return super(),this.stateType=S.RULE_STOP,this}}class m{constructor(t){if(null==t)throw"target cannot be null.";this.target=t,this.isEpsilon=!1,this.label=null}}m.EPSILON=1,m.RANGE=2,m.RULE=3,m.PREDICATE=4,m.ATOM=5,m.ACTION=6,m.SET=7,m.NOT_SET=8,m.WILDCARD=9,m.PRECEDENCE=10,m.serializationNames=["INVALID","EPSILON","RANGE","RULE","PREDICATE","ATOM","ACTION","SET","NOT_SET","WILDCARD","PRECEDENCE"],m.serializationTypes={EpsilonTransition:m.EPSILON,RangeTransition:m.RANGE,RuleTransition:m.RULE,PredicateTransition:m.PREDICATE,AtomTransition:m.ATOM,ActionTransition:m.ACTION,SetTransition:m.SET,NotSetTransition:m.NOT_SET,WildcardTransition:m.WILDCARD,PrecedencePredicateTransition:m.PRECEDENCE};class _ extends m{constructor(t,e,n,s){super(t),this.ruleIndex=e,this.precedence=n,this.followState=s,this.serializationType=m.RULE,this.isEpsilon=!0}matches(t,e,n){return!1}}class C extends m{constructor(e,n){super(e),this.serializationType=m.SET,null!=n?this.label=n:(this.label=new T,this.label.addOne(t.INVALID_TYPE))}matches(t,e,n){return this.label.contains(t)}toString(){return this.label.toString()}}class A extends C{constructor(t,e){super(t,e),this.serializationType=m.NOT_SET}matches(t,e,n){return t>=e&&t<=n&&!super.matches(t,e,n)}toString(){return"~"+super.toString()}}class N extends m{constructor(t){super(t),this.serializationType=m.WILDCARD}matches(t,e,n){return t>=e&&t<=n}toString(){return"."}}class y extends m{constructor(t){super(t)}}class I extends class extends class{}{}{}class k extends I{getRuleContext(){throw new Error("missing interface implementation")}}class O extends I{}class R extends O{}const L={toStringTree:function(t,e,n){e=e||null,null!==(n=n||null)&&(e=n.ruleNames);let s=L.getNodeText(t,e);s=function(t,e){return t=t.replace(/\t/g,"\\t").replace(/\n/g,"\\n").replace(/\r/g,"\\r")}(s);const i=t.getChildCount();if(0===i)return s;let r="("+s+" ";i>0&&(s=L.toStringTree(t.getChild(0),e),r=r.concat(s));for(let n=1;n=0&&e0&&(t+=", "),this.returnStates[e]!==P.EMPTY_RETURN_STATE?(t+=this.returnStates[e],null!==this.parents[e]?t=t+" "+this.parents[e]:t+="null"):t+="$";return t+"]"}}get length(){return this.returnStates.length}}class D extends P{constructor(t,e){let n=0;const i=new s;null!==t?i.update(t,e):i.update(1),n=i.finish(),super(n),this.parentCtx=t,this.returnState=e}getParent(t){return this.parentCtx}getReturnState(t){return this.returnState}equals(t){return this===t||t instanceof D&&this.hashCode()===t.hashCode()&&this.returnState===t.returnState&&(null==this.parentCtx?null==t.parentCtx:this.parentCtx.equals(t.parentCtx))}toString(){const t=null===this.parentCtx?"":this.parentCtx.toString();return 0===t.length?this.returnState===P.EMPTY_RETURN_STATE?"$":""+this.returnState:this.returnState+" "+t}get length(){return 1}static create(t,e){return e===P.EMPTY_RETURN_STATE&&null===t?P.EMPTY:new D(t,e)}}class F extends D{constructor(){super(null,P.EMPTY_RETURN_STATE)}isEmpty(){return!0}getParent(t){return null}getReturnState(t){return this.returnState}equals(t){return this===t}toString(){return"$"}}P.EMPTY=new F;const M="h-";class U{constructor(t,e){this.data={},this.hashFunction=t||i,this.equalsFunction=e||r}set(t,e){const n=M+this.hashFunction(t);if(n in this.data){const s=this.data[n];for(let n=0;nt.startsWith(M))).flatMap((t=>this.data[t]),this)}getKeys(){return this.entries().map((t=>t.key))}getValues(){return this.entries().map((t=>t.value))}toString(){return"["+this.entries().map((t=>"{"+t.key+":"+t.value+"}")).join(", ")+"]"}get length(){return Object.keys(this.data).filter((t=>t.startsWith(M))).map((t=>this.data[t].length),this).reduce(((t,e)=>t+e),0)}}function B(t,e){if(null==e&&(e=w.EMPTY),null===e.parentCtx||e===w.EMPTY)return P.EMPTY;const n=B(t,e.parentCtx),s=t.states[e.invokingState].transitions[0];return D.create(n,s.followState.stateNumber)}function V(t,e,n){if(t.isEmpty())return t;let s=n.get(t)||null;if(null!==s)return s;if(s=e.get(t),null!==s)return n.set(t,s),s;let i=!1,r=[];for(let s=0;se.returnState&&(i[0]=e.returnState,i[1]=t.returnState);const r=new b([n,n],i);return null!==s&&s.set(t,e,r),r}const i=[t.returnState,e.returnState];let r=[t.parentCtx,e.parentCtx];t.returnState>e.returnState&&(i[0]=e.returnState,i[1]=t.returnState,r=[e.parentCtx,t.parentCtx]);const o=new b(r,i);return null!==s&&s.set(t,e,o),o}}(t,e,n,s);if(n){if(t instanceof F)return t;if(e instanceof F)return e}return t instanceof D&&(t=new b([t.getParent()],[t.returnState])),e instanceof D&&(e=new b([e.getParent()],[e.returnState])),function(t,e,n,s){if(null!==s){let n=s.get(t,e);if(null!==n)return n;if(n=s.get(e,t),null!==n)return n}let i=0,r=0,o=0,a=[],l=[];for(;ithis.add(t)),this)}remove(t){delete this.data[t]}has(t){return!0===this.data[t]}values(){return Object.keys(this.data)}minValue(){return Math.min.apply(null,this.values())}hashCode(){return s.hashStuff(this.values())}equals(t){return t instanceof K&&e(this.data,t.data)}toString(){return"{"+this.values().join(", ")+"}"}get length(){return this.values().length}}class q{constructor(t){this.atn=t}getDecisionLookahead(t){if(null===t)return null;const e=t.transitions.length,n=[];for(let s=0;s=this.states.length)throw"Invalid state number.";const s=this.states[e];let i=this.nextTokens(s);if(!i.contains(t.EPSILON))return i;const r=new T;for(r.addSet(i),r.removeOne(t.EPSILON);null!==n&&n.invokingState>=0&&i.contains(t.EPSILON);){const e=this.states[n.invokingState].transitions[0];i=this.nextTokens(e.followState),r.addSet(i),r.removeOne(t.EPSILON),n=n.parentCtx}return i.contains(t.EPSILON)&&r.addOne(t.EOF),r}}Y.INVALID_ALT_NUMBER=0;class z extends S{constructor(){super(),this.stateType=S.BASIC}}class G extends S{constructor(){return super(),this.decision=-1,this.nonGreedy=!1,this}}class W extends G{constructor(){return super(),this.endState=null,this}}class j extends S{constructor(){return super(),this.stateType=S.BLOCK_END,this.startState=null,this}}class Q extends S{constructor(){return super(),this.stateType=S.LOOP_END,this.loopBackState=null,this}}class $ extends S{constructor(){return super(),this.stateType=S.RULE_START,this.stopState=null,this.isPrecedenceRule=!1,this}}class X extends G{constructor(){return super(),this.stateType=S.TOKEN_START,this}}class J extends G{constructor(){return super(),this.stateType=S.PLUS_LOOP_BACK,this}}class Z extends S{constructor(){return super(),this.stateType=S.STAR_LOOP_BACK,this}}class tt extends G{constructor(){return super(),this.stateType=S.STAR_LOOP_ENTRY,this.loopBackState=null,this.isPrecedenceDecision=null,this}}class et extends W{constructor(){return super(),this.stateType=S.PLUS_BLOCK_START,this.loopBackState=null,this}}class nt extends W{constructor(){return super(),this.stateType=S.STAR_BLOCK_START,this}}class st extends W{constructor(){return super(),this.stateType=S.BLOCK_START,this}}class it extends m{constructor(t,e){super(t),this.label_=e,this.label=this.makeLabel(),this.serializationType=m.ATOM}makeLabel(){const t=new T;return t.addOne(this.label_),t}matches(t,e,n){return this.label_===t}toString(){return this.label_}}class rt extends m{constructor(t,e,n){super(t),this.serializationType=m.RANGE,this.start=e,this.stop=n,this.label=this.makeLabel()}makeLabel(){const t=new T;return t.addRange(this.start,this.stop),t}matches(t,e,n){return t>=this.start&&t<=this.stop}toString(){return"'"+String.fromCharCode(this.start)+"'..'"+String.fromCharCode(this.stop)+"'"}}class ot extends m{constructor(t,e,n,s){super(t),this.serializationType=m.ACTION,this.ruleIndex=e,this.actionIndex=void 0===n?-1:n,this.isCtxDependent=void 0!==s&&s,this.isEpsilon=!0}matches(t,e,n){return!1}toString(){return"action_"+this.ruleIndex+":"+this.actionIndex}}class at extends m{constructor(t,e){super(t),this.serializationType=m.EPSILON,this.isEpsilon=!0,this.outermostPrecedenceReturn=e}matches(t,e,n){return!1}toString(){return"epsilon"}}class lt extends c{constructor(t,e,n){super(),this.ruleIndex=void 0===t?-1:t,this.predIndex=void 0===e?-1:e,this.isCtxDependent=void 0!==n&&n}evaluate(t,e){const n=this.isCtxDependent?e:null;return t.sempred(n,this.ruleIndex,this.predIndex)}updateHashCode(t){t.update(this.ruleIndex,this.predIndex,this.isCtxDependent)}equals(t){return this===t||t instanceof lt&&this.ruleIndex===t.ruleIndex&&this.predIndex===t.predIndex&&this.isCtxDependent===t.isCtxDependent}toString(){return"{"+this.ruleIndex+":"+this.predIndex+"}?"}}c.NONE=new lt;class ht extends y{constructor(t,e,n,s){super(t),this.serializationType=m.PREDICATE,this.ruleIndex=e,this.predIndex=n,this.isCtxDependent=s,this.isEpsilon=!0}matches(t,e,n){return!1}getPredicate(){return new lt(this.ruleIndex,this.predIndex,this.isCtxDependent)}toString(){return"pred_"+this.ruleIndex+":"+this.predIndex}}class ct extends c{constructor(t){super(),this.precedence=void 0===t?0:t}evaluate(t,e){return t.precpred(e,this.precedence)}evalPrecedence(t,e){return t.precpred(e,this.precedence)?c.NONE:null}compareTo(t){return this.precedence-t.precedence}updateHashCode(t){t.update(this.precedence)}equals(t){return this===t||t instanceof ct&&this.precedence===t.precedence}toString(){return"{"+this.precedence+">=prec}?"}}c.PrecedencePredicate=ct;class ut extends y{constructor(t,e){super(t),this.serializationType=m.PRECEDENCE,this.precedence=e,this.isEpsilon=!0}matches(t,e,n){return!1}getPredicate(){return new ct(this.precedence)}toString(){return this.precedence+" >= _p"}}class dt{constructor(t){void 0===t&&(t=null),this.readOnly=!1,this.verifyATN=null===t||t.verifyATN,this.generateRuleBypassTransitions=null!==t&&t.generateRuleBypassTransitions}}dt.defaultOptions=new dt,dt.defaultOptions.readOnly=!0;class pt{constructor(t){this.actionType=t,this.isPositionDependent=!1}hashCode(){const t=new s;return this.updateHashCode(t),t.finish()}updateHashCode(t){t.update(this.actionType)}equals(t){return this===t}}class gt extends pt{constructor(){super(6)}execute(t){t.skip()}toString(){return"skip"}}gt.INSTANCE=new gt;class ft extends pt{constructor(t){super(0),this.channel=t}execute(t){t._channel=this.channel}updateHashCode(t){t.update(this.actionType,this.channel)}equals(t){return this===t||t instanceof ft&&this.channel===t.channel}toString(){return"channel("+this.channel+")"}}class xt extends pt{constructor(t,e){super(1),this.ruleIndex=t,this.actionIndex=e,this.isPositionDependent=!0}execute(t){t.action(null,this.ruleIndex,this.actionIndex)}updateHashCode(t){t.update(this.actionType,this.ruleIndex,this.actionIndex)}equals(t){return this===t||t instanceof xt&&this.ruleIndex===t.ruleIndex&&this.actionIndex===t.actionIndex}}class Tt extends pt{constructor(){super(3)}execute(t){t.more()}toString(){return"more"}}Tt.INSTANCE=new Tt;class St extends pt{constructor(t){super(7),this.type=t}execute(t){t.type=this.type}updateHashCode(t){t.update(this.actionType,this.type)}equals(t){return this===t||t instanceof St&&this.type===t.type}toString(){return"type("+this.type+")"}}class Et extends pt{constructor(t){super(5),this.mode=t}execute(t){t.pushMode(this.mode)}updateHashCode(t){t.update(this.actionType,this.mode)}equals(t){return this===t||t instanceof Et&&this.mode===t.mode}toString(){return"pushMode("+this.mode+")"}}class mt extends pt{constructor(){super(4)}execute(t){t.popMode()}toString(){return"popMode"}}mt.INSTANCE=new mt;class _t extends pt{constructor(t){super(2),this.mode=t}execute(t){t.mode(this.mode)}updateHashCode(t){t.update(this.actionType,this.mode)}equals(t){return this===t||t instanceof _t&&this.mode===t.mode}toString(){return"mode("+this.mode+")"}}function Ct(t,e){const n=[];return n[t-1]=e,n.map((function(t){return e}))}class At{constructor(t){null==t&&(t=dt.defaultOptions),this.deserializationOptions=t,this.stateFactories=null,this.actionFactories=null}deserialize(t){const e=this.reset(t);this.checkVersion(e),e&&this.skipUUID();const n=this.readATN();this.readStates(n,e),this.readRules(n,e),this.readModes(n);const s=[];return this.readSets(n,s,this.readInt.bind(this)),e&&this.readSets(n,s,this.readInt32.bind(this)),this.readEdges(n,s),this.readDecisions(n),this.readLexerActions(n,e),this.markPrecedenceDecisions(n),this.verifyATN(n),this.deserializationOptions.generateRuleBypassTransitions&&1===n.grammarType&&(this.generateRuleBypassTransitions(n),this.verifyATN(n)),n}reset(t){if(3===(t.charCodeAt?t.charCodeAt(0):t[0])){const e=function(t){const e=t.charCodeAt(0);return e>1?e-2:e+65534},n=t.split("").map(e);return n[0]=t.charCodeAt(0),this.data=n,this.pos=0,!0}return this.data=t,this.pos=0,!1}skipUUID(){let t=0;for(;t++<8;)this.readInt()}checkVersion(t){const e=this.readInt();if(!t&&4!==e)throw"Could not deserialize ATN with version "+e+" (expected 4)."}readATN(){const t=this.readInt(),e=this.readInt();return new Y(t,e)}readStates(t,e){let n,s,i;const r=[],o=[],a=this.readInt();for(let n=0;n0;)i.addTransition(l.transitions[h-1]),l.transitions=l.transitions.slice(-1);t.ruleToStartState[e].addTransition(new at(i)),r.addTransition(new at(a));const c=new z;t.addState(c),c.addTransition(new it(r,t.ruleToTokenType[e])),i.addTransition(new at(c))}stateIsEndStateFor(t,e){if(t.ruleIndex!==e)return null;if(!(t instanceof tt))return null;const n=t.transitions[t.transitions.length-1].target;return n instanceof Q&&n.epsilonOnlyTransitions&&n.transitions[0].target instanceof E?t:null}markPrecedenceDecisions(t){for(let e=0;e=0):this.checkCondition(n.transitions.length<=1||n instanceof E)}}checkCondition(t,e){if(!t)throw null==e&&(e="IllegalState"),e}readInt(){return this.data[this.pos++]}readInt32(){return this.readInt()|this.readInt()<<16}edgeFactory(e,n,s,i,r,o,a,l){const h=e.states[i];switch(n){case m.EPSILON:return new at(h);case m.RANGE:return new rt(h,0!==a?t.EOF:r,o);case m.RULE:return new _(e.states[r],o,a,h);case m.PREDICATE:return new ht(h,r,o,0!==a);case m.PRECEDENCE:return new ut(h,r);case m.ATOM:return new it(h,0!==a?t.EOF:r);case m.ACTION:return new ot(h,r,o,0!==a);case m.SET:return new C(h,l[r]);case m.NOT_SET:return new A(h,l[r]);case m.WILDCARD:return new N(h);default:throw"The specified transition type: "+n+" is not valid."}}stateFactory(t,e){if(null===this.stateFactories){const t=[];t[S.INVALID_TYPE]=null,t[S.BASIC]=()=>new z,t[S.RULE_START]=()=>new $,t[S.BLOCK_START]=()=>new st,t[S.PLUS_BLOCK_START]=()=>new et,t[S.STAR_BLOCK_START]=()=>new nt,t[S.TOKEN_START]=()=>new X,t[S.RULE_STOP]=()=>new E,t[S.BLOCK_END]=()=>new j,t[S.STAR_LOOP_BACK]=()=>new Z,t[S.STAR_LOOP_ENTRY]=()=>new tt,t[S.PLUS_LOOP_BACK]=()=>new J,t[S.LOOP_END]=()=>new Q,this.stateFactories=t}if(t>this.stateFactories.length||null===this.stateFactories[t])throw"The specified state type "+t+" is not valid.";{const n=this.stateFactories[t]();if(null!==n)return n.ruleIndex=e,n}}lexerActionFactory(t,e,n){if(null===this.actionFactories){const t=[];t[0]=(t,e)=>new ft(t),t[1]=(t,e)=>new xt(t,e),t[2]=(t,e)=>new _t(t),t[3]=(t,e)=>Tt.INSTANCE,t[4]=(t,e)=>mt.INSTANCE,t[5]=(t,e)=>new Et(t),t[6]=(t,e)=>gt.INSTANCE,t[7]=(t,e)=>new St(t),this.actionFactories=t}if(t>this.actionFactories.length||null===this.actionFactories[t])throw"The specified lexer action type "+t+" is not valid.";return this.actionFactories[t](e,n)}}class Nt{syntaxError(t,e,n,s,i,r){}reportAmbiguity(t,e,n,s,i,r,o){}reportAttemptingFullContext(t,e,n,s,i,r){}reportContextSensitivity(t,e,n,s,i,r){}}class yt extends Nt{constructor(){super()}syntaxError(t,e,n,s,i,r){console.error("line "+n+":"+s+" "+i)}}yt.INSTANCE=new yt;class It extends Nt{constructor(t){if(super(),null===t)throw"delegates";return this.delegates=t,this}syntaxError(t,e,n,s,i,r){this.delegates.map((o=>o.syntaxError(t,e,n,s,i,r)))}reportAmbiguity(t,e,n,s,i,r,o){this.delegates.map((a=>a.reportAmbiguity(t,e,n,s,i,r,o)))}reportAttemptingFullContext(t,e,n,s,i,r){this.delegates.map((o=>o.reportAttemptingFullContext(t,e,n,s,i,r)))}reportContextSensitivity(t,e,n,s,i,r){this.delegates.map((o=>o.reportContextSensitivity(t,e,n,s,i,r)))}}class kt{constructor(){this._listeners=[yt.INSTANCE],this._interp=null,this._stateNumber=-1}checkVersion(t){"4.10.1"!==t&&console.log("ANTLR runtime and generated code versions disagree: 4.10.1!="+t)}addErrorListener(t){this._listeners.push(t)}removeErrorListeners(){this._listeners=[]}getLiteralNames(){return Object.getPrototypeOf(this).constructor.literalNames||[]}getSymbolicNames(){return Object.getPrototypeOf(this).constructor.symbolicNames||[]}getTokenNames(){if(!this.tokenNames){const t=this.getLiteralNames(),e=this.getSymbolicNames(),n=t.length>e.length?t.length:e.length;this.tokenNames=[];for(let s=0;s";let n=e.text;return null===n&&(n=e.type===t.EOF?"":"<"+e.type+">"),n=n.replace("\n","\\n").replace("\r","\\r").replace("\t","\\t"),"'"+n+"'"}getErrorListenerDispatch(){return new It(this._listeners)}sempred(t,e,n){return!0}precpred(t,e){return!0}get state(){return this._stateNumber}set state(t){this._stateNumber=t}}kt.tokenTypeMapCache={},kt.ruleIndexMapCache={};class Ot extends t{constructor(e,n,s,i,r){super(),this.source=void 0!==e?e:Ot.EMPTY_SOURCE,this.type=void 0!==n?n:null,this.channel=void 0!==s?s:t.DEFAULT_CHANNEL,this.start=void 0!==i?i:-1,this.stop=void 0!==r?r:-1,this.tokenIndex=-1,null!==this.source[0]?(this.line=e[0].line,this.column=e[0].column):this.column=-1}clone(){const t=new Ot(this.source,this.type,this.channel,this.start,this.stop);return t.tokenIndex=this.tokenIndex,t.line=this.line,t.column=this.column,t.text=this.text,t}toString(){let t=this.text;return t=null!==t?t.replace(/\n/g,"\\n").replace(/\r/g,"\\r").replace(/\t/g,"\\t"):"","[@"+this.tokenIndex+","+this.start+":"+this.stop+"='"+t+"',<"+this.type+">"+(this.channel>0?",channel="+this.channel:"")+","+this.line+":"+this.column+"]"}get text(){if(null!==this._text)return this._text;const t=this.getInputStream();if(null===t)return null;const e=t.size;return this.start"}set text(t){this._text=t}}Ot.EMPTY_SOURCE=[null,null];class Rt extends class{}{constructor(t){super(),this.copyText=void 0!==t&&t}create(t,e,n,s,i,r,o,a){const l=new Ot(t,e,s,i,r);return l.line=o,l.column=a,null!==n?l.text=n:this.copyText&&null!==t[1]&&(l.text=t[1].getText(i,r)),l}createThin(t,e){const n=new Ot(null,t);return n.text=e,n}}Rt.DEFAULT=new Rt;class Lt extends Error{constructor(t){super(t.message),Error.captureStackTrace&&Error.captureStackTrace(this,Lt),this.message=t.message,this.recognizer=t.recognizer,this.input=t.input,this.ctx=t.ctx,this.offendingToken=null,this.offendingState=-1,null!==this.recognizer&&(this.offendingState=this.recognizer.state)}getExpectedTokens(){return null!==this.recognizer?this.recognizer.atn.getExpectedTokens(this.offendingState,this.ctx):null}toString(){return this.message}}class vt extends Lt{constructor(t,e,n,s){super({message:"",recognizer:t,input:e,ctx:null}),this.startIndex=n,this.deadEndConfigs=s}toString(){let t="";return this.startIndex>=0&&this.startIndex":"\n"===e?"\\n":"\t"===e?"\\t":"\r"===e?"\\r":e}getCharErrorDisplay(t){return"'"+this.getErrorDisplayForChar(t)+"'"}recover(e){this._input.LA(1)!==t.EOF&&(e instanceof vt?this._interp.consume(this._input):this._input.consume())}get inputStream(){return this._input}set inputStream(t){this._input=null,this._tokenFactorySourcePair=[this,this._input],this.reset(),this._input=t,this._tokenFactorySourcePair=[this,this._input]}get sourceName(){return this._input.sourceName}get type(){return this._type}set type(t){this._type=t}get line(){return this._interp.line}set line(t){this._interp.line=t}get column(){return this._interp.column}set column(t){this._interp.column=t}get text(){return null!==this._text?this._text:this._interp.getText(this._input)}set text(t){this._text=t}}function Pt(t){return t.hashCodeForConfigSet()}function bt(t,e){return t===e||null!==t&&null!==e&&t.equalsForConfigSet(e)}wt.DEFAULT_MODE=0,wt.MORE=-2,wt.SKIP=-3,wt.DEFAULT_TOKEN_CHANNEL=t.DEFAULT_CHANNEL,wt.HIDDEN=t.HIDDEN_CHANNEL,wt.MIN_CHAR_VALUE=0,wt.MAX_CHAR_VALUE=1114111;class Dt{constructor(t){this.configLookup=new h(Pt,bt),this.fullCtx=void 0===t||t,this.readOnly=!1,this.configs=[],this.uniqueAlt=0,this.conflictingAlts=null,this.hasSemanticContext=!1,this.dipsIntoOuterContext=!1,this.cachedHashCode=-1}add(t,e){if(void 0===e&&(e=null),this.readOnly)throw"This set is readonly";t.semanticContext!==c.NONE&&(this.hasSemanticContext=!0),t.reachesIntoOuterContext>0&&(this.dipsIntoOuterContext=!0);const n=this.configLookup.add(t);if(n===t)return this.cachedHashCode=-1,this.configs.push(t),!0;const s=!this.fullCtx,i=H(n.context,t.context,s,e);return n.reachesIntoOuterContext=Math.max(n.reachesIntoOuterContext,t.reachesIntoOuterContext),t.precedenceFilterSuppressed&&(n.precedenceFilterSuppressed=!0),n.context=i,!0}getStates(){const t=new h;for(let e=0;eYt.MAX_DFA_EDGE)return null;let n=t.edges[e-Yt.MIN_DFA_EDGE];return void 0===n&&(n=null),Yt.debug&&null!==n&&console.log("reuse state "+t.stateNumber+" edge to "+n.stateNumber),n}computeTargetState(t,e,n){const s=new Ut;return this.getReachableConfigSet(t,e.configs,s,n),0===s.items.length?(s.hasSemanticContext||this.addDFAEdge(e,n,Mt.ERROR),Mt.ERROR):this.addDFAEdge(e,n,null,s)}failOrAccept(e,n,s,i){if(null!==this.prevAccept.dfaState){const t=e.dfaState.lexerActionExecutor;return this.accept(n,t,this.startIndex,e.index,e.line,e.column),e.dfaState.prediction}if(i===t.EOF&&n.index===this.startIndex)return t.EOF;throw new vt(this.recog,n,this.startIndex,s)}getReachableConfigSet(e,n,s,i){let r=Y.INVALID_ALT_NUMBER;for(let o=0;oYt.MAX_DFA_EDGE||(Yt.debug&&console.log("EDGE "+t+" -> "+n+" upon "+e),null===t.edges&&(t.edges=[]),t.edges[e-Yt.MIN_DFA_EDGE]=n),n}addDFAState(t){const e=new Ft(null,t);let n=null;for(let e=0;et.startsWith("k-"))).map((t=>this.data[t]),this)}}const Wt={SLL:0,LL:1,LL_EXACT_AMBIG_DETECTION:2,hasSLLConflictTerminatingPrediction:function(t,e){if(Wt.allConfigsInRuleStopStates(e))return!0;if(t===Wt.SLL&&e.hasSemanticContext){const t=new Dt;for(let n=0;n1)return!0;return!1},allSubsetsEqual:function(t){let e=null;for(let n=0;n0&&(r=this.getAltThatFinishedDecisionEntryRule(i),r!==Y.INVALID_ALT_NUMBER)?r:Y.INVALID_ALT_NUMBER}getAltThatFinishedDecisionEntryRule(t){const e=[];for(let n=0;n0||s.state instanceof E&&s.context.hasEmptyPath())&&e.indexOf(s.alt)<0&&e.push(s.alt)}return 0===e.length?Y.INVALID_ALT_NUMBER:Math.min.apply(null,e)}splitAccordingToSemanticValidity(t,e){const n=new Dt(t.fullCtx),s=new Dt(t.fullCtx);for(let i=0;i50))throw"problem";if(t.state instanceof E){if(!t.context.isEmpty()){for(let a=0;a=0&&(s+=1)}this.closureCheckingStopState(u,e,n,c,i,s,o)}}}canDropLoopEntryEdgeInLeftRecursiveRule(t){const e=t.state;if(e.stateType!==S.STAR_LOOP_ENTRY)return!1;if(e.stateType!==S.STAR_LOOP_ENTRY||!e.isPrecedenceDecision||t.context.isEmpty()||t.context.hasEmptyPath())return!1;const n=t.context.length;for(let s=0;s=0?this.parser.ruleNames[t]:""}getEpsilonTarget(e,n,s,i,r,o){switch(n.serializationType){case m.RULE:return this.ruleTransition(e,n);case m.PRECEDENCE:return this.precedenceTransition(e,n,s,i,r);case m.PREDICATE:return this.predTransition(e,n,s,i,r);case m.ACTION:return this.actionTransition(e,n);case m.EPSILON:return new f({state:n.target},e);case m.ATOM:case m.RANGE:case m.SET:return o&&n.matches(t.EOF,0,1)?new f({state:n.target},e):null;default:return null}}actionTransition(t,e){if(this.debug){const t=-1===e.actionIndex?65535:e.actionIndex;console.log("ACTION edge "+e.ruleIndex+":"+t)}return new f({state:e.target},t)}precedenceTransition(t,e,n,s,i){this.debug&&(console.log("PRED (collectPredicates="+n+") "+e.precedence+">=_p, ctx dependent=true"),null!==this.parser&&console.log("context surrounding pred is "+a(this.parser.getRuleInvocationStack())));let r=null;if(n&&s)if(i){const n=this._input.index;this._input.seek(this._startIndex);const s=e.getPredicate().evaluate(this.parser,this._outerContext);this._input.seek(n),s&&(r=new f({state:e.target},t))}else{const n=c.andContext(t.semanticContext,e.getPredicate());r=new f({state:e.target,semanticContext:n},t)}else r=new f({state:e.target},t);return this.debug&&console.log("config from pred transition="+r),r}predTransition(t,e,n,s,i){this.debug&&(console.log("PRED (collectPredicates="+n+") "+e.ruleIndex+":"+e.predIndex+", ctx dependent="+e.isCtxDependent),null!==this.parser&&console.log("context surrounding pred is "+a(this.parser.getRuleInvocationStack())));let r=null;if(n&&(e.isCtxDependent&&s||!e.isCtxDependent))if(i){const n=this._input.index;this._input.seek(this._startIndex);const s=e.getPredicate().evaluate(this.parser,this._outerContext);this._input.seek(n),s&&(r=new f({state:e.target},t))}else{const n=c.andContext(t.semanticContext,e.getPredicate());r=new f({state:e.target,semanticContext:n},t)}else r=new f({state:e.target},t);return this.debug&&console.log("config from pred transition="+r),r}ruleTransition(t,e){this.debug&&console.log("CALL rule "+this.getRuleName(e.target.ruleIndex)+", ctx="+t.context);const n=e.followState,s=D.create(t.context,n.stateNumber);return new f({state:e.target,context:s},t)}getConflictingAlts(t){const e=jt.getConflictingAltSubsets(t);return jt.getAlts(e)}getConflictingAltsOrUniqueAlt(t){let e=null;return t.uniqueAlt!==Y.INVALID_ALT_NUMBER?(e=new K,e.add(t.uniqueAlt)):e=t.conflictingAlts,e}getTokenName(e){if(e===t.EOF)return"EOF";if(null!==this.parser&&null!==this.parser.literalNames){if(!(e>=this.parser.literalNames.length&&e>=this.parser.symbolicNames.length))return(this.parser.literalNames[e]||this.parser.symbolicNames[e])+"<"+e+">";console.log(e+" ttype out of range: "+this.parser.literalNames),console.log(""+this.parser.getInputStream().getTokens())}return""+e}getLookaheadName(t){return this.getTokenName(t.LA(1))}dumpDeadEndConfigs(t){console.log("dead end configs: ");const e=t.getDeadEndConfigs();for(let t=0;t0){const t=n.state.transitions[0];t instanceof it?s="Atom "+this.getTokenName(t.label):t instanceof C&&(s=(t instanceof A?"~":"")+"Set "+t.set)}console.error(n.toString(this.parser,!0)+":"+s)}}noViableAlt(t,e,n,s){return new Qt(this.parser,t,t.get(s),t.LT(1),n,e)}getUniqueAlt(t){let e=Y.INVALID_ALT_NUMBER;for(let n=0;n "+s+" upon "+this.getTokenName(n)),null===s)return null;if(s=this.addDFAState(t,s),null===e||n<-1||n>this.atn.maxTokenType)return s;if(null===e.edges&&(e.edges=[]),e.edges[n+1]=s,this.debug){const e=null===this.parser?null:this.parser.literalNames,n=null===this.parser?null:this.parser.symbolicNames;console.log("DFA=\n"+t.toString(e,n))}return s}addDFAState(t,e){if(e===Mt.ERROR)return e;const n=t.states.get(e);return null!==n?n:(e.stateNumber=t.states.length,e.configs.readOnly||(e.configs.optimizeConfigs(this),e.configs.setReadonly(!0)),t.states.add(e),this.debug&&console.log("adding new DFA state: "+e),e)}reportAttemptingFullContext(t,e,n,s,i){if(this.debug||this.retry_debug){const e=new x(s,i+1);console.log("reportAttemptingFullContext decision="+t.decision+":"+n+", input="+this.parser.getTokenStream().getText(e))}null!==this.parser&&this.parser.getErrorListenerDispatch().reportAttemptingFullContext(this.parser,t,s,i,e,n)}reportContextSensitivity(t,e,n,s,i){if(this.debug||this.retry_debug){const e=new x(s,i+1);console.log("reportContextSensitivity decision="+t.decision+":"+n+", input="+this.parser.getTokenStream().getText(e))}null!==this.parser&&this.parser.getErrorListenerDispatch().reportContextSensitivity(this.parser,t,s,i,e,n)}reportAmbiguity(t,e,n,s,i,r,o){if(this.debug||this.retry_debug){const t=new x(n,s+1);console.log("reportAmbiguity "+r+":"+o+", input="+this.parser.getTokenStream().getText(t))}null!==this.parser&&this.parser.getErrorListenerDispatch().reportAmbiguity(this.parser,t,n,s,i,r,o)}},PredictionMode:jt};class Jt{constructor(t,e,n){this.dfa=t,this.literalNames=e||[],this.symbolicNames=n||[]}toString(){if(null===this.dfa.s0)return null;let t="";const e=this.dfa.sortedStates();for(let n=0;n"),t=t.concat(this.getStateString(e)),t=t.concat("\n"))}}}return 0===t.length?null:t}getEdgeLabel(t){return 0===t?"EOF":null!==this.literalNames||null!==this.symbolicNames?this.literalNames[t-1]||this.symbolicNames[t-1]:String.fromCharCode(t-1)}getStateString(t){const e=(t.isAcceptState?":":"")+"s"+t.stateNumber+(t.requiresFullContext?"^":"");return t.isAcceptState?null!==t.predicates?e+"=>"+a(t.predicates):e+"=>"+t.prediction.toString():e}}class Zt extends Jt{constructor(t){super(t,null)}getEdgeLabel(t){return"'"+String.fromCharCode(t)+"'"}}const te={DFA:class{constructor(t,e){if(void 0===e&&(e=0),this.atnStartState=t,this.decision=e,this._states=new h,this.s0=null,this.precedenceDfa=!1,t instanceof tt&&t.isPrecedenceDecision){this.precedenceDfa=!0;const t=new Ft(null,new Dt);t.edges=[],t.isAcceptState=!1,t.requiresFullContext=!1,this.s0=t}}getPrecedenceStartState(t){if(!this.precedenceDfa)throw"Only precedence DFAs may contain a precedence start state.";return t<0||t>=this.s0.edges.length?null:this.s0.edges[t]||null}setPrecedenceStartState(t,e){if(!this.precedenceDfa)throw"Only precedence DFAs may contain a precedence start state.";t<0||(this.s0.edges[t]=e)}setPrecedenceDfa(t){if(this.precedenceDfa!==t){if(this._states=new h,t){const t=new Ft(null,new Dt);t.edges=[],t.isAcceptState=!1,t.requiresFullContext=!1,this.s0=t}else this.s0=null;this.precedenceDfa=t}}sortedStates(){return this._states.values().sort((function(t,e){return t.stateNumber-e.stateNumber}))}toString(t,e){return t=t||null,e=e||null,null===this.s0?"":new Jt(this,t,e).toString()}toLexerString(){return null===this.s0?"":new Zt(this).toString()}get states(){return this._states}},DFASerializer:Jt,LexerDFASerializer:Zt,PredPrediction:zt};class ee{visitTerminal(t){}visitErrorNode(t){}enterEveryRule(t){}exitEveryRule(t){}}class ne{walk(t,e){if(e instanceof R||void 0!==e.isErrorNode&&e.isErrorNode())t.visitErrorNode(e);else if(e instanceof O)t.visitTerminal(e);else{this.enterRule(t,e);for(let n=0;n=0&&t.consume(),this.lastErrorIndex=t._input.index,null===this.lastErrorStates&&(this.lastErrorStates=[]),this.lastErrorStates.push(t.state);const n=this.getErrorRecoverySet(t);this.consumeUntil(t,n)}sync(e){if(this.inErrorRecoveryMode(e))return;const n=e._interp.atn.states[e.state],s=e.getTokenStream().LA(1),i=e.atn.nextTokens(n);if(i.contains(s))return this.nextTokensContext=null,void(this.nextTokenState=S.INVALID_STATE_NUMBER);if(i.contains(t.EPSILON))null===this.nextTokensContext&&(this.nextTokensContext=e._ctx,this.nextTokensState=e._stateNumber);else switch(n.stateType){case S.BLOCK_START:case S.STAR_BLOCK_START:case S.PLUS_BLOCK_START:case S.STAR_LOOP_ENTRY:if(null!==this.singleTokenDeletion(e))return;throw new ie(e);case S.PLUS_LOOP_BACK:case S.STAR_LOOP_BACK:{this.reportUnwantedToken(e);const t=new T;t.addSet(e.getExpectedTokens());const n=t.addSet(this.getErrorRecoverySet(e));this.consumeUntil(e,n)}}}reportNoViableAlternative(e,n){const s=e.getTokenStream();let i;i=null!==s?n.startToken.type===t.EOF?"":s.getText(new x(n.startToken.tokenIndex,n.offendingToken.tokenIndex)):"";const r="no viable alternative at input "+this.escapeWSAndQuote(i);e.notifyErrorListeners(r,n.offendingToken,n)}reportInputMismatch(t,e){const n="mismatched input "+this.getTokenErrorDisplay(e.offendingToken)+" expecting "+e.getExpectedTokens().toString(t.literalNames,t.symbolicNames);t.notifyErrorListeners(n,e.offendingToken,e)}reportFailedPredicate(t,e){const n="rule "+t.ruleNames[t._ctx.ruleIndex]+" "+e.message;t.notifyErrorListeners(n,e.offendingToken,e)}reportUnwantedToken(t){if(this.inErrorRecoveryMode(t))return;this.beginErrorCondition(t);const e=t.getCurrentToken(),n="extraneous input "+this.getTokenErrorDisplay(e)+" expecting "+this.getExpectedTokens(t).toString(t.literalNames,t.symbolicNames);t.notifyErrorListeners(n,e,null)}reportMissingToken(t){if(this.inErrorRecoveryMode(t))return;this.beginErrorCondition(t);const e=t.getCurrentToken(),n="missing "+this.getExpectedTokens(t).toString(t.literalNames,t.symbolicNames)+" at "+this.getTokenErrorDisplay(e);t.notifyErrorListeners(n,e,null)}recoverInline(t){const e=this.singleTokenDeletion(t);if(null!==e)return t.consume(),e;if(this.singleTokenInsertion(t))return this.getMissingSymbol(t);throw new ie(t)}singleTokenInsertion(t){const e=t.getTokenStream().LA(1),n=t._interp.atn,s=n.states[t.state].transitions[0].target;return!!n.nextTokens(s,t._ctx).contains(e)&&(this.reportMissingToken(t),!0)}singleTokenDeletion(t){const e=t.getTokenStream().LA(2);if(this.getExpectedTokens(t).contains(e)){this.reportUnwantedToken(t),t.consume();const e=t.getCurrentToken();return this.reportMatch(t),e}return null}getMissingSymbol(e){const n=e.getCurrentToken(),s=this.getExpectedTokens(e).first();let i;i=s===t.EOF?"":"";let r=n;const o=e.getTokenStream().LT(-1);return r.type===t.EOF&&null!==o&&(r=o),e.getTokenFactory().create(r.source,s,i,t.DEFAULT_CHANNEL,-1,-1,r.line,r.column)}getExpectedTokens(t){return t.getExpectedTokens()}getTokenErrorDisplay(e){if(null===e)return"";let n=e.text;return null===n&&(n=e.type===t.EOF?"":"<"+e.type+">"),this.escapeWSAndQuote(n)}escapeWSAndQuote(t){return"'"+(t=(t=(t=t.replace(/\n/g,"\\n")).replace(/\r/g,"\\r")).replace(/\t/g,"\\t"))+"'"}getErrorRecoverySet(e){const n=e._interp.atn;let s=e._ctx;const i=new T;for(;null!==s&&s.invokingState>=0;){const t=n.states[s.invokingState].transitions[0],e=n.nextTokens(t.followState);i.addSet(e),s=s.parentCtx}return i.removeOne(t.EPSILON),i}consumeUntil(e,n){let s=e.getTokenStream().LA(1);for(;s!==t.EOF&&!n.contains(s);)e.consume(),s=e.getTokenStream().LA(1)}}const he={RecognitionException:Lt,NoViableAltException:Qt,LexerNoViableAltException:vt,InputMismatchException:ie,FailedPredicateException:re,DiagnosticErrorListener:class extends Nt{constructor(t){super(),t=t||!0,this.exactOnly=t}reportAmbiguity(t,e,n,s,i,r,o){if(this.exactOnly&&!i)return;const a="reportAmbiguity d="+this.getDecisionDescription(t,e)+": ambigAlts="+this.getConflictingAlts(r,o)+", input='"+t.getTokenStream().getText(new x(n,s))+"'";t.notifyErrorListeners(a)}reportAttemptingFullContext(t,e,n,s,i,r){const o="reportAttemptingFullContext d="+this.getDecisionDescription(t,e)+", input='"+t.getTokenStream().getText(new x(n,s))+"'";t.notifyErrorListeners(o)}reportContextSensitivity(t,e,n,s,i,r){const o="reportContextSensitivity d="+this.getDecisionDescription(t,e)+", input='"+t.getTokenStream().getText(new x(n,s))+"'";t.notifyErrorListeners(o)}getDecisionDescription(t,e){const n=e.decision,s=e.atnStartState.ruleIndex,i=t.ruleNames;if(s<0||s>=i.length)return""+n;const r=i[s]||null;return null===r||0===r.length?""+n:`${n} (${r})`}getConflictingAlts(t,e){if(null!==t)return t;const n=new K;for(let t=0;t=this._size)throw"cannot consume EOF";this._index+=1}LA(e){if(0===e)return 0;e<0&&(e+=1);const n=this._index+e-1;return n<0||n>=this._size?t.EOF:this.data[n]}LT(t){return this.LA(t)}mark(){return-1}release(t){}seek(t){t<=this._index?this._index=t:this._index=Math.min(t,this._size)}getText(t,e){if(e>=this._size&&(e=this._size-1),t>=this._size)return"";if(this.decodeToUnicodeCodePoints){let n="";for(let s=t;s<=e;s++)n+=String.fromCodePoint(this.data[s]);return n}return this.strdata.slice(t,e+1)}toString(){return this.strdata}get index(){return this._index}get size(){return this._size}}var ue=n(654);const de={fromString:function(t){return new ce(t,!0)},fromBlob:function(t,e,n,s){const i=new window.FileReader;i.onload=function(t){const e=new ce(t.target.result,!0);n(e)},i.onerror=s,i.readAsText(t,e)},fromBuffer:function(t,e){return new ce(t.toString(e),!0)},fromPath:function(t,e,n){ue.readFile(t,e,(function(t,e){let s=null;null!==e&&(s=new ce(e,!0)),n(t,s)}))},fromPathSync:function(t,e){const n=ue.readFileSync(t,e);return new ce(n,!0)}};class pe extends ee{constructor(t){super(),this.parser=t}enterEveryRule(t){console.log("enter "+this.parser.ruleNames[t.ruleIndex]+", LT(1)="+this.parser._input.LT(1).text)}visitTerminal(t){console.log("consume "+t.symbol+" rule "+this.parser.ruleNames[this.parser._ctx.ruleIndex])}exitEveryRule(t){console.log("exit "+this.parser.ruleNames[t.ruleIndex]+", LT(1)="+this.parser._input.LT(1).text)}}class ge extends kt{constructor(t){super(),this._input=null,this._errHandler=new le,this._precedenceStack=[],this._precedenceStack.push(0),this._ctx=null,this.buildParseTrees=!0,this._tracer=null,this._parseListeners=null,this._syntaxErrors=0,this.setInputStream(t)}reset(){null!==this._input&&this._input.seek(0),this._errHandler.reset(this),this._ctx=null,this._syntaxErrors=0,this.setTrace(!1),this._precedenceStack=[],this._precedenceStack.push(0),null!==this._interp&&this._interp.reset()}match(t){let e=this.getCurrentToken();return e.type===t?(this._errHandler.reportMatch(this),this.consume()):(e=this._errHandler.recoverInline(this),this.buildParseTrees&&-1===e.tokenIndex&&this._ctx.addErrorNode(e)),e}matchWildcard(){let t=this.getCurrentToken();return t.type>0?(this._errHandler.reportMatch(this),this.consume()):(t=this._errHandler.recoverInline(this),this._buildParseTrees&&-1===t.tokenIndex&&this._ctx.addErrorNode(t)),t}getParseListeners(){return this._parseListeners||[]}addParseListener(t){if(null===t)throw"listener";null===this._parseListeners&&(this._parseListeners=[]),this._parseListeners.push(t)}removeParseListener(t){if(null!==this._parseListeners){const e=this._parseListeners.indexOf(t);e>=0&&this._parseListeners.splice(e,1),0===this._parseListeners.length&&(this._parseListeners=null)}}removeParseListeners(){this._parseListeners=null}triggerEnterRuleEvent(){if(null!==this._parseListeners){const t=this._ctx;this._parseListeners.forEach((function(e){e.enterEveryRule(t),t.enterRule(e)}))}}triggerExitRuleEvent(){if(null!==this._parseListeners){const t=this._ctx;this._parseListeners.slice(0).reverse().forEach((function(e){t.exitRule(e),e.exitEveryRule(t)}))}}getTokenFactory(){return this._input.tokenSource._factory}setTokenFactory(t){this._input.tokenSource._factory=t}getATNWithBypassAlts(){const t=this.getSerializedATN();if(null===t)throw"The current parser does not support an ATN with bypass alternatives.";let e=this.bypassAltsAtnCache[t];if(null===e){const n=new dt;n.generateRuleBypassTransitions=!0,e=new At(n).deserialize(t),this.bypassAltsAtnCache[t]=e}return e}getInputStream(){return this.getTokenStream()}setInputStream(t){this.setTokenStream(t)}getTokenStream(){return this._input}setTokenStream(t){this._input=null,this.reset(),this._input=t}getCurrentToken(){return this._input.LT(1)}notifyErrorListeners(t,e,n){n=n||null,null===(e=e||null)&&(e=this.getCurrentToken()),this._syntaxErrors+=1;const s=e.line,i=e.column;this.getErrorListenerDispatch().syntaxError(this,e,s,i,t,n)}consume(){const e=this.getCurrentToken();e.type!==t.EOF&&this.getInputStream().consume();const n=null!==this._parseListeners&&this._parseListeners.length>0;if(this.buildParseTrees||n){let t;t=this._errHandler.inErrorRecoveryMode(this)?this._ctx.addErrorNode(e):this._ctx.addTokenNode(e),t.invokingState=this.state,n&&this._parseListeners.forEach((function(e){t instanceof R||void 0!==t.isErrorNode&&t.isErrorNode()?e.visitErrorNode(t):t instanceof O&&e.visitTerminal(t)}))}return e}addContextToParseTree(){null!==this._ctx.parentCtx&&this._ctx.parentCtx.addChild(this._ctx)}enterRule(t,e,n){this.state=e,this._ctx=t,this._ctx.start=this._input.LT(1),this.buildParseTrees&&this.addContextToParseTree(),this.triggerEnterRuleEvent()}exitRule(){this._ctx.stop=this._input.LT(-1),this.triggerExitRuleEvent(),this.state=this._ctx.invokingState,this._ctx=this._ctx.parentCtx}enterOuterAlt(t,e){t.setAltNumber(e),this.buildParseTrees&&this._ctx!==t&&null!==this._ctx.parentCtx&&(this._ctx.parentCtx.removeLastChild(),this._ctx.parentCtx.addChild(t)),this._ctx=t}getPrecedence(){return 0===this._precedenceStack.length?-1:this._precedenceStack[this._precedenceStack.length-1]}enterRecursionRule(t,e,n,s){this.state=e,this._precedenceStack.push(s),this._ctx=t,this._ctx.start=this._input.LT(1),this.triggerEnterRuleEvent()}pushNewRecursionContext(t,e,n){const s=this._ctx;s.parentCtx=t,s.invokingState=e,s.stop=this._input.LT(-1),this._ctx=t,this._ctx.start=s.start,this.buildParseTrees&&this._ctx.addChild(s),this.triggerEnterRuleEvent()}unrollRecursionContexts(t){this._precedenceStack.pop(),this._ctx.stop=this._input.LT(-1);const e=this._ctx,n=this.getParseListeners();if(null!==n&&n.length>0)for(;this._ctx!==t;)this.triggerExitRuleEvent(),this._ctx=this._ctx.parentCtx;else this._ctx=t;e.parentCtx=t,this.buildParseTrees&&null!==t&&t.addChild(e)}getInvokingContext(t){let e=this._ctx;for(;null!==e;){if(e.ruleIndex===t)return e;e=e.parentCtx}return null}precpred(t,e){return e>=this._precedenceStack[this._precedenceStack.length-1]}inContext(t){return!1}isExpectedToken(e){const n=this._interp.atn;let s=this._ctx;const i=n.states[this.state];let r=n.nextTokens(i);if(r.contains(e))return!0;if(!r.contains(t.EPSILON))return!1;for(;null!==s&&s.invokingState>=0&&r.contains(t.EPSILON);){const t=n.states[s.invokingState].transitions[0];if(r=n.nextTokens(t.followState),r.contains(e))return!0;s=s.parentCtx}return!(!r.contains(t.EPSILON)||e!==t.EOF)}getExpectedTokens(){return this._interp.atn.getExpectedTokens(this.state,this._ctx)}getExpectedTokensWithinCurrentRule(){const t=this._interp.atn,e=t.states[this.state];return t.nextTokens(e)}getRuleIndex(t){const e=this.getRuleIndexMap()[t];return null!==e?e:-1}getRuleInvocationStack(t){null===(t=t||null)&&(t=this._ctx);const e=[];for(;null!==t;){const n=t.ruleIndex;n<0?e.push("n/a"):e.push(this.ruleNames[n]),t=t.parentCtx}return e}getDFAStrings(){return this._interp.decisionToDFA.toString()}dumpDFA(){let t=!1;for(let e=0;e0&&(t&&console.log(),this.printer.println("Decision "+n.decision+":"),this.printer.print(n.toString(this.literalNames,this.symbolicNames)),t=!0)}}getSourceName(){return this._input.sourceName}setTrace(t){t?(null!==this._tracer&&this.removeParseListener(this._tracer),this._tracer=new pe(this),this.addParseListener(this._tracer)):(this.removeParseListener(this._tracer),this._tracer=null)}}ge.bypassAltsAtnCache={};class fe extends O{constructor(t){super(),this.parentCtx=null,this.symbol=t}getChild(t){return null}getSymbol(){return this.symbol}getParent(){return this.parentCtx}getPayload(){return this.symbol}getSourceInterval(){if(null===this.symbol)return x.INVALID_INTERVAL;const t=this.symbol.tokenIndex;return new x(t,t)}getChildCount(){return 0}accept(t){return t.visitTerminal(this)}getText(){return this.symbol.text}toString(){return this.symbol.type===t.EOF?"":this.symbol.text}}class xe extends fe{constructor(t){super(t)}isErrorNode(){return!0}accept(t){return t.visitErrorNode(this)}}class Te extends w{constructor(t,e){super(t=t||null,e=e||null),this.ruleIndex=-1,this.children=null,this.start=null,this.stop=null,this.exception=null}copyFrom(t){this.parentCtx=t.parentCtx,this.invokingState=t.invokingState,this.children=null,this.start=t.start,this.stop=t.stop,t.children&&(this.children=[],t.children.map((function(t){t instanceof xe&&(this.children.push(t),t.parentCtx=this)}),this))}enterRule(t){}exitRule(t){}addChild(t){return null===this.children&&(this.children=[]),this.children.push(t),t}removeLastChild(){null!==this.children&&this.children.pop()}addTokenNode(t){const e=new fe(t);return this.addChild(e),e.parentCtx=this,e}addErrorNode(t){const e=new xe(t);return this.addChild(e),e.parentCtx=this,e}getChild(t,e){if(e=e||null,null===this.children||t<0||t>=this.children.length)return null;if(null===e)return this.children[t];for(let n=0;n=this.children.length)return null;for(let n=0;n=0&&(this.fetchedEOF?this.index0)||this.fetch(e)>=e}fetch(e){if(this.fetchedEOF)return 0;for(let n=0;n=this.tokens.length&&(n=this.tokens.length-1);for(let r=e;r=this.tokens.length?this.tokens[this.tokens.length-1]:this.tokens[e]}adjustSeekIndex(t){return t}lazyInit(){-1===this.index&&this.setup()}setup(){this.sync(0),this.index=this.adjustSeekIndex(0)}setTokenSource(t){this.tokenSource=t,this.tokens=[],this.index=-1,this.fetchedEOF=!1}nextTokenOnChannel(e,n){if(this.sync(e),e>=this.tokens.length)return-1;let s=this.tokens[e];for(;s.channel!==this.channel;){if(s.type===t.EOF)return-1;e+=1,this.sync(e),s=this.tokens[e]}return e}previousTokenOnChannel(t,e){for(;t>=0&&this.tokens[t].channel!==e;)t-=1;return t}getHiddenTokensToRight(t,e){if(void 0===e&&(e=-1),this.lazyInit(),t<0||t>=this.tokens.length)throw t+" not in 0.."+this.tokens.length-1;const n=this.nextTokenOnChannel(t+1,wt.DEFAULT_TOKEN_CHANNEL),s=t+1,i=-1===n?this.tokens.length-1:n;return this.filterForChannel(s,i,e)}getHiddenTokensToLeft(t,e){if(void 0===e&&(e=-1),this.lazyInit(),t<0||t>=this.tokens.length)throw t+" not in 0.."+this.tokens.length-1;const n=this.previousTokenOnChannel(t-1,wt.DEFAULT_TOKEN_CHANNEL);if(n===t-1)return null;const s=n+1,i=t-1;return this.filterForChannel(s,i,e)}filterForChannel(t,e,n){const s=[];for(let i=t;i=this.tokens.length&&(s=this.tokens.length-1);let i="";for(let e=n;enew me.dfa.DFA(t,e)));class Ae extends me.Lexer{static grammarFileName="DTS.g4";static channelNames=["DEFAULT_TOKEN_CHANNEL","HIDDEN"];static modeNames=["DEFAULT_MODE"];static literalNames=[null,"'{'","'}'","','",null,null,null,null,null,null,"'='","';'","'/'"];static symbolicNames=[null,null,null,null,"STRING","NUMBER2","ARR","KEY","NUMBER","WS","EQ","SEMICOLON","ROOT","VERSION"];static ruleNames=["T__0","T__1","T__2","STRING","NUMBER2","ARR","KEY","ESC","UNICODE","HEX","SAFECODEPOINT","NUMBER","INT","EXP","WS","EQ","SEMICOLON","ROOT","VERSION"];constructor(t){super(t),this._interp=new me.atn.LexerATNSimulator(this,_e,Ce,new me.PredictionContextCache)}get atn(){return _e}}Ae.EOF=me.Token.EOF,Ae.T__0=1,Ae.T__1=2,Ae.T__2=3,Ae.STRING=4,Ae.NUMBER2=5,Ae.ARR=6,Ae.KEY=7,Ae.NUMBER=8,Ae.WS=9,Ae.EQ=10,Ae.SEMICOLON=11,Ae.ROOT=12,Ae.VERSION=13;class Ne extends me.tree.ParseTreeListener{enterDts(t){}exitDts(t){}enterDic(t){}exitDic(t){}enterPair(t){}exitPair(t){}enterArray(t){}exitArray(t){}enterValue(t){}exitValue(t){}visitTerminal(t){}}class ye extends me.tree.ParseTreeVisitor{visitDts(t){return this.visitChildren(t)}visitDic(t){return this.visitChildren(t)}visitPair(t){return this.visitChildren(t)}visitArray(t){return this.visitChildren(t)}visitValue(t){return this.visitChildren(t)}}const Ie=(new me.atn.ATNDeserializer).deserialize([4,1,13,49,2,0,7,0,2,1,7,1,2,2,7,2,2,3,7,3,2,4,7,4,1,0,1,0,1,0,1,0,1,1,1,1,5,1,17,8,1,10,1,12,1,20,9,1,1,1,1,1,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,1,2,3,2,38,8,2,1,3,1,3,1,3,4,3,43,8,3,11,3,12,3,44,1,4,1,4,1,4,0,0,5,0,2,4,6,8,0,1,2,0,4,6,8,8,47,0,10,1,0,0,0,2,14,1,0,0,0,4,37,1,0,0,0,6,39,1,0,0,0,8,46,1,0,0,0,10,11,5,13,0,0,11,12,3,4,2,0,12,13,5,0,0,1,13,1,1,0,0,0,14,18,5,1,0,0,15,17,3,4,2,0,16,15,1,0,0,0,17,20,1,0,0,0,18,16,1,0,0,0,18,19,1,0,0,0,19,21,1,0,0,0,20,18,1,0,0,0,21,22,5,2,0,0,22,3,1,0,0,0,23,24,5,7,0,0,24,25,5,10,0,0,25,26,3,8,4,0,26,27,5,11,0,0,27,38,1,0,0,0,28,29,5,7,0,0,29,30,5,10,0,0,30,31,3,6,3,0,31,32,5,11,0,0,32,38,1,0,0,0,33,34,5,7,0,0,34,35,3,2,1,0,35,36,5,11,0,0,36,38,1,0,0,0,37,23,1,0,0,0,37,28,1,0,0,0,37,33,1,0,0,0,38,5,1,0,0,0,39,42,3,8,4,0,40,41,5,3,0,0,41,43,3,8,4,0,42,40,1,0,0,0,43,44,1,0,0,0,44,42,1,0,0,0,44,45,1,0,0,0,45,7,1,0,0,0,46,47,7,0,0,0,47,9,1,0,0,0,3,18,37,44]),ke=Ie.decisionToState.map(((t,e)=>new me.dfa.DFA(t,e))),Oe=new me.PredictionContextCache;class Re extends me.Parser{static grammarFileName="DTS.g4";static literalNames=[null,"'{'","'}'","','",null,null,null,null,null,null,"'='","';'","'/'"];static symbolicNames=[null,null,null,null,"STRING","NUMBER2","ARR","KEY","NUMBER","WS","EQ","SEMICOLON","ROOT","VERSION"];static ruleNames=["dts","dic","pair","array","value"];constructor(t){super(t),this._interp=new me.atn.ParserATNSimulator(this,Ie,ke,Oe),this.ruleNames=Re.ruleNames,this.literalNames=Re.literalNames,this.symbolicNames=Re.symbolicNames}get atn(){return Ie}dts(){let t=new Le(this,this._ctx,this.state);this.enterRule(t,0,Re.RULE_dts);try{this.enterOuterAlt(t,1),this.state=10,this.match(Re.VERSION),this.state=11,this.pair(),this.state=12,this.match(Re.EOF)}catch(e){if(!(e instanceof me.error.RecognitionException))throw e;t.exception=e,this._errHandler.reportError(this,e),this._errHandler.recover(this,e)}finally{this.exitRule()}return t}dic(){let t=new ve(this,this._ctx,this.state);this.enterRule(t,2,Re.RULE_dic);var e=0;try{for(this.enterOuterAlt(t,1),this.state=14,this.match(Re.T__0),this.state=18,this._errHandler.sync(this),e=this._input.LA(1);e===Re.KEY;)this.state=15,this.pair(),this.state=20,this._errHandler.sync(this),e=this._input.LA(1);this.state=21,this.match(Re.T__1)}catch(e){if(!(e instanceof me.error.RecognitionException))throw e;t.exception=e,this._errHandler.reportError(this,e),this._errHandler.recover(this,e)}finally{this.exitRule()}return t}pair(){let t=new we(this,this._ctx,this.state);this.enterRule(t,4,Re.RULE_pair);try{switch(this.state=37,this._errHandler.sync(this),this._interp.adaptivePredict(this._input,1,this._ctx)){case 1:this.enterOuterAlt(t,1),this.state=23,this.match(Re.KEY),this.state=24,this.match(Re.EQ),this.state=25,this.value(),this.state=26,this.match(Re.SEMICOLON);break;case 2:this.enterOuterAlt(t,2),this.state=28,this.match(Re.KEY),this.state=29,this.match(Re.EQ),this.state=30,this.array(),this.state=31,this.match(Re.SEMICOLON);break;case 3:this.enterOuterAlt(t,3),this.state=33,this.match(Re.KEY),this.state=34,this.dic(),this.state=35,this.match(Re.SEMICOLON)}}catch(e){if(!(e instanceof me.error.RecognitionException))throw e;t.exception=e,this._errHandler.reportError(this,e),this._errHandler.recover(this,e)}finally{this.exitRule()}return t}array(){let t=new Pe(this,this._ctx,this.state);this.enterRule(t,6,Re.RULE_array);var e=0;try{this.enterOuterAlt(t,1),this.state=39,this.value(),this.state=42,this._errHandler.sync(this),e=this._input.LA(1);do{this.state=40,this.match(Re.T__2),this.state=41,this.value(),this.state=44,this._errHandler.sync(this),e=this._input.LA(1)}while(e===Re.T__2)}catch(e){if(!(e instanceof me.error.RecognitionException))throw e;t.exception=e,this._errHandler.reportError(this,e),this._errHandler.recover(this,e)}finally{this.exitRule()}return t}value(){let t=new be(this,this._ctx,this.state);this.enterRule(t,8,Re.RULE_value);var e=0;try{this.enterOuterAlt(t,1),this.state=46,0!=(-32&(e=this._input.LA(1)))||0==(1<e||t<0||e<0||e>=this.tokens.tokens.length)throw new RangeError(`replace: range invalid: ${t}..${e}(size=${this.tokens.tokens.length})`);let i=this.getProgram(s),r=new Be(this.tokens,t,e,i.length,n);i.push(r)}delete(t,e,n=De.DEFAULT_PROGRAM_NAME){void 0===e&&(e=t),this.replace(t,e,"",n)}getProgram(t){let e=this.programs.get(t);return null==e&&(e=this.initializeProgram(t)),e}initializeProgram(t){const e=[];return this.programs.set(t,e),e}getText(t,e=De.DEFAULT_PROGRAM_NAME){let n;n=t instanceof me.Interval?t:new me.Interval(0,this.tokens.tokens.length-1),"string"==typeof t&&(e=t);const s=this.programs.get(e);let i=n.start,r=n.stop;if(r>this.tokens.tokens.length-1&&(r=this.tokens.tokens.length-1),i<0&&(i=0),null==s||0===s.length)return this.tokens.getText(n);let o=[],a=this.reduceToSingleOperationPerIndex(s),l=i;for(;l<=r&&l=this.tokens.tokens.length-1&&o.push(t.text.toString());return o.join("")}reduceToSingleOperationPerIndex(t){for(let e=0;es.index&&e.index<=s.lastIndex&&(t[e.instructionIndex]=void 0);let r=this.getKindOfOps(t,Be,e);for(let e of r){if(e.index>=s.index&&e.lastIndex<=s.lastIndex){t[e.instructionIndex]=void 0;continue}let n=e.lastIndexs.lastIndex;if(null!=e.text||null!=s.text||n){if(!n)throw new Error(`replace op boundaries of ${s} overlap with previous ${e}`)}else t[e.instructionIndex]=void 0,s.index=Math.min(e.index,s.index),s.lastIndex=Math.max(e.lastIndex,s.lastIndex)}}for(let e=0;e=n.index&&s.index<=n.lastIndex)throw new Error(`insert op ${s} within boundaries of previous ${n}`)}else n.text=this.catOpText(s.text,n.text),t[e]=void 0}let e=new Map;for(let n of t)if(null!=n){if(null!=e.get(n.index))throw new Error("should only be one op per index");e.set(n.index,n)}return e}catOpText(t,e){let n="",s="";return null!=t&&(n=t.toString()),null!=e&&(s=e.toString()),n+s}getKindOfOps(t,e,n){let s=[];for(let i=0;i'}}class Me extends Fe{constructor(t,e,n,s){super(t,e,n,s)}execute(t){return t.push(this.text.toString()),this.tokens.get(this.index).type!==me.Token.EOF&&t.push(String(this.tokens.get(this.index).text)),this.index+1}}class Ue extends Me{constructor(t,e,n,s){super(t,e+1,n,s)}}class Be extends Fe{constructor(t,e,n,s,i){super(t,e,s,i),this.lastIndex=n}execute(t){return null!=this.text&&t.push(this.text.toString()),this.lastIndex+1}toString(){return null==this.text?"":"'}}String.format||(String.format=function(t){let e=Array.prototype.slice.call(arguments,1);return t.replace(/{(\d+)}/g,(function(t,n){return void 0!==e[n]?e[n]:t}))});const Ve=scriptArgs;(Ve.length<2||Ve.length>3)&&(std.out.printf("Usage: qjs dts.js [output path]\n"),std.exit(1));let He=Ve[1],Ke=Ve.length>2?Ve[2]:He+".out";const qe=std.loadFile(He),Ye=new Ae(new me.InputStream(qe)),ze=new me.CommonTokenStream(Ye),Ge=new Re(ze);Ge.buildParseTrees=!0;const We=Ge.dts(),je=new me.tree.ParseTreeWalker,Qe=new class extends Ne{static tokens;static rewriter;constructor(t){super(),this.tokens=t,this.rewriter=new De(t)}enterDts(t){}exitDts(t){}enterDic(t){}exitDic(t){}enterPair(t){}exitPair(t){}enterArray(t){}exitArray(t){}enterValue(t){}exitValue(t){}tabCnt=0;lastKey="";map=new Map;visitTerminal(t){t.getSymbol().type===Re.T__0&&this.tabCnt++,t.getSymbol().type===Re.T__1&&this.tabCnt--,t.getSymbol().type!==Re.KEY&&t.getSymbol().type!==Re.T__1||this.rewriter.insertBefore(t.getSymbol(),"\t".repeat(Math.max(0,this.tabCnt))),t.getSymbol().type!==Re.SEMICOLON&&t.getSymbol().type!==Re.T__0&&t.getSymbol().type!==Re.VERSION||this.rewriter.insertAfter(t.getSymbol(),"\n"),t.getSymbol().type!==Re.KEY&&t.getSymbol().type!==Re.EQ||this.rewriter.insertAfter(t.getSymbol()," "),t.getSymbol().type===Re.KEY&&("/"===t.getText()?this.lastKey="/":this.lastKey+="/"+t.getText(),this.map.set(this.lastKey.replace("//","/"),t.getSymbol().tokenIndex)),t.getSymbol().type===Re.SEMICOLON&&(this.lastKey=this.lastKey.substring(0,this.lastKey.lastIndexOf("/"))),super.visitTerminal(t)}put(t,e){let n=this.map.get(t);if(console.log("modify path "+t),null==n)console.log("[err] path not found");else{if(this.tokens.get(n+1).type===Re.EQ){let t=this.tokens.get(n+2);return console.log("[ok] value "+e),this.rewriter.replaceSingle(t,e),1}console.log("[err] path not correct")}return 0}}(ze);je.walk(Qe,We);const $e="/sys/block/";let Xe=os.readdir($e);if(0===Xe[1]){let t="/sys/block/sata",e=/\/sys\/block\/nvme(\d{1,2})n(\d{1,2})/i;for(let n in Xe[0]){let s=$e+Xe[0][n];try{if(std.out.printf("start processing path:%s\n",s),s.toString().startsWith(t)){let e=Number.parseInt(s.toString().substring(t.length)),n=Je(s+"/device/syno_block_info");"ahci"===n.get("driver")?(Qe.put(String.format("/internal_slot@{0}/ahci/pcie_root",e),String.format('"{0}"',n.get("pciepath"))),Qe.put(String.format("/internal_slot@{0}/ahci/ata_port",e),String.format("<0x{0}>",Number.parseInt(n.get("ata_port_no")).toString(16).padStart(2,"0")))):std.out.printf("not ahci\n")}else if(s.toString().startsWith("/sys/block/nvme")){let t;if(t=e.exec(s.toString())){let e=Number.parseInt(t[1]),n=Je(s+"/device/syno_block_info");Qe.put(String.format("/nvme_slot@{0}/pcie_root",e+1),String.format('"{0}"',n.get("pciepath")))}else std.out.printf("nvme not found\n")}else std.out.printf("unsupported\n")}catch(t){std.out.printf("update path: %s to dts error: %s\n",s,t.message),std.exit(1)}}const n=std.open(Ke,"w");n.puts(Qe.rewriter.getText()),n.close()}else std.out.printf("update dts error:%d\n",Xe[1]),std.exit(1);function Je(t){const e=std.open(t,"r");let n=new Map;for(;;){let t=e.getline();if(null===t)break;let s=t.indexOf("=");if(s>0){let e=t.substring(0,s),i=t.substring(s+1);n.set(e,i),std.out.printf("%s = %s\n",e,i)}}return e.close(),n}})()})(); \ No newline at end of file diff --git a/addons/qjs-dtb/all/usr/sbin/dtc b/addons/qjs-dtb/all/usr/sbin/dtc deleted file mode 100755 index d3da15be20af35dc06c02f88df7275c0b616c5a9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 150200 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

W+b6Xg~?O8j?e)<-OCOeXz{xYOXFRu>n&H*L3 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 HC+huQ28`;Q diff --git a/addons/qjs-dtb/all/usr/sbin/qjs b/addons/qjs-dtb/all/usr/sbin/qjs deleted file mode 100755 index 84a05e4c2cadc4cd55fc9562fd26deb478e82da2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 937504 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

=bsa$12C=_(7Au^iF%sXblHm2;uTY1S6@QO6!k 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

3k`!x^AA6)4hdW*{_dQM>LwJM%4Bg{gY- z+zYuF5|62t-osRe<@g-#Rnc2gUVd6-@YGUa^q8^`t)QMKo!_~swh@n?b} zB0u+86Nz8giGkP>b*(LfbEYaB*v;~{a-baD1aHu`^x2iCWJdq2YmSte_3oq<(dx3C z)rCNAz(npiICl+8Ty7E!atykITXK`U2jZM4#$dR`hRwiENhdaNm+;n(t4ypvEp`3| zPLn-Y5pTM(wz6YEG`!<$)1wN*8|B??EyhfC3=Qghcu`%6J@Qo5`6-{Ws%1kZO_mM( z#LrJY!`uZnKI8Y^?>5dc;%fId!a{;0!=nCPL@OodGi=e~%p42A9c0aZnG8krY4xQZ zRq{L~eV7_jRi$!=BOAQZh{yZQ2asnm4@4l$)pW<7Iy-@hnMtBB)pP3HhprT9i z76Dg5ea9ph|B^)mchDF!KX&U9A&JFGaSg;mH6I7i&iq$k16)@_dT$?pq^unD6{yPN zK}~c$+77C^mt@;yR#3f#=xm@WaQ=(tKAx_Lvy|yWO*~c0k?rY~1E0^)yHEfr+k)lv zeO(hD^!$YK@zf>AeakBr|6S;le6TWXS{HQxj&{Pd4r9R2@CF%luk}Y*h0OBLjz6G{ zRU@xT->XZHOhs-Isga!%a@q<@SP_mdvRn#*%%IDd3@1=nzX@A4bj%#NFGj z&&>v@FyjpgBjgor1Sb6{G_WqIz>2`&!!##1fvhk?CU;V8i+Z~g zX(i4V`Trgk^u%}!)9vsbj%y#oOS-WoeW>|Cq*$Ye@ddf9Ej^1-VS6lBjJRcC|BDr2 zy?%zfhA$bia@~ljzh7uejjzNU982woWi{688Pj7HII;e*FmvVV1q1~^7MFOisuj@C z{;JlQ_A3lbZrmQ$znAQv)1MvwcK91E>f1ihG6X+_&xd$?4naTn+Ks|#@!g>3K~`C76Yxa2WN(v>%oH;jHz ztW0NN)L?{LKnBANp-T3aA>&a!AUNLUfb#;fhUtphtUNpm^`Wb6axt~TT>&NXbzAB+ zTLwigsK^r+d!N~0{#wkMIkiK+S2y?b!S@cu^F{aeGt{QbKzl2@jM^ab6Muz!(sxSi zq4Fo3NJ#0kCZ!%BZpVb?NXXt1re`uu?bYt-R}7>+LiE^&a8HqDE3FK{)5WpD8o>L| zq=N2@Pz3Ta+Cu!AF+B3!sQB}UvcYTG2d@bu$22CkZ0W(sLcM*zIf)ru@7~M;o8*cb zt4>;8;v`k2t?krGRrDrQuZ(l9Gl%ncCZAWT`J6e$t3A161cGl&4#ouaD7f`R+PPg# z{^-*q%BDn|wYXFPAN_)5neQa?!1ssHi(jaSTxG8d*3|H#yntVDQzja|!9 z#e#**^MTU^40)g>9#L6@d9+<|qm2eTf(t+PC+WjDTvDTF`P9cm0gy9S-Y6{|*YF*K zv)cz}15|Gu>D}S^8@T860?`=`q)Mgu!{Y`Bu}s@TyUtt^UmG2 zsT?kWbF{o(unm^^O=j2#bST;S=g*j434(*}iJ4;Hy4@rB{-~f^A@!C7p6f)}KfN^K zI$C}bEHsD|il;udueZU7Z?lfAiCN%Z@G~72AI+r+Kr@1A=T zqVm$if>SjEPwKt z_4xcR@Khqc^XyMx4OWfh!zzwAO+GJ@XQft{?Hca^&TXFXln{u{Kksv5_656*J|T{MVk&>9@_N~bbpt>$@fNi9{|ic zEx~CojD3c!8uldSPRf3hfV zdd2#nTlNqicjv*XSktqer?OMSta~7W4V&Gk-WCuOKL+O0OJUC0_H(IR33d=aVvN>; z@Bv@-C3|a}N3M?C88*M{J$vwVctM|DRP=z);pXtaiytt3iq&JQ!*Yuj@Cd#XuiLn5 zn9K)*uQhK1cd%;>Zi!irmi?5Ud$(9B)oNiFiHQ{fg}=NNvF#fRXz<_)F-Mh2l@G zsrO_3?^nc#dL3i`w&}^%)Ze6A39uamd8HEm8@uB`^oX*O#2!CmsEP2eAx zr;pgeE5)A?3#i?A0K9jj`}IDC@BhXA6*Amtn{2n1n@R=@kZq|C({E!$zt!$==qI9I z>;q;hh>#}YA9?z%7Pr$S64YA)O$YTz%U$1`Qpx@1X+5k9oB9)%7@o=fW{I|1i{e_W zRcyr?1-C%|h0(uit~gj5;18%^u_ZvF%!CV@J%Tt8-l4{Q15pzAH%6oN?SsJ&VH?Pw zmqMPvC0%Dp*lQo`Xppo*tcB$J?_qyA&{jFw=tlg=)I&QoRB|4&_r$|amHzlLVOeR+ zXDFIq<_70g_vao38BYAi2^;9@+|MVsk57!AH7&V4Ok9@Serm_9HUym~@P}87`&qEP zF@8VI*Nde^s@FV?@k zV$zwdsTI&5fi!Tlc_DX!1Qx}Z5M^~bW805Jq1-aS@2mNx@+&?OVGWPzp)g& z@<^_uP*x&#$6yMyY*pcnLz=&#Cg>iGSk!r~@6}A~4m=I-xYj$wjc!SesqN1m63fI0 z-*zP^gs?<_o{HXP+V~>J)ntENx_}|L6*uf0yzruy^q5*qqjK3Bji(6O_m~P+gO?cc zOElCr?E@?fRXACuR1jnT(!%?!ex~>%BEQcCGC!ZFaryA`-MpB*@uw za`@8_$rrtKc^Vj-L3@&KR&jl)r%uis)0P?C+`st{tGfkBFS)9MuoYj7XBH}m(K+EX z5UYO!C$Ok}0`=Ljwa%SJN4a$LrC|U)Hl+ozFzCJ(+zO{{F9P(^+bAQ~$<+3i)SHZN ze-$fV(KhXg55@EQP=AaWRQVpsOVW@6&pSFr2j}|^=6iQRaqsTFj%EmRITS05%MjdM zlDp0KDkiKHH-xwAtl#(u=6Wu4bW^BQ6>5Gm=an-{D|@OKP13#|fwH z&}6SOI56KH=T6FuK49su>16+VBkKFF=s!MI&!XI#TIYsSZ)Tt2)R#TP=B}Ggq4W#y zi_i?xK}IxO^59(hCu(ai=;Oe2z3Jw@yzskc6(0%}F>%?;tqJ(~y!V4oi;nkV&p_a< zY7uX0L6)@w=)^b50J-!lMSx`nCtWKj5YPrg#^{LR2+vbREwR5eQvh(rGHslocpjX& zp2B|o)(~wlk8weBPwD{^n1whnHM+H0m>or>qZVrLMYH96Al^(VJhF-_Qp7)(&MNKb zU0>BQZ~gLop~||fzS}-ornww6j3rkL)9f7?-o6qi)SB!=7#VE63vVZ_+<#mH7?ta& z*tTb~`xpdG9>SjP#qeFWg@_~@rjCIU-Ukk5z0t8U-Qm%#JsZiUf3+17;kAYoanZv* zxO|j&MwVFUC5}5esrTalUg}-=yr@pgEQ0RXXKYhl|pH>Gz|pZKZ8_;NV(fwvoj&-`x0g&zEh;X znUsS#d+i(_m#eNQ(A4F~hjR3j_iy+S!MQ9Tm#2K0o9z?|Hh0btx>Gs$iS5DbzS3?v z2+JlGH8JYZwa`Zee-2+KY2@ipcckb55G&?lgSl2G+rdrI@blp(AEQnQBD?jwGyY{e z2`n1o2O3l;yXuQYVQW9hvR}FF{FVZXf*9qUM@Y0uyAWIEQtuA#&0SnDoB$J&4FGm`gWgnP4C zm*gE0oD&IWRoN#E9nl{i!jxhjBwk+PjpH~{Dd?3q4{USyVQ4UO^Al+38UC6yS+9BAT)(o?%vR@EY7UY+U2J`dAjBL{qU zqoSbaQOaRlY0$@frSDm#iQi|5bbyhN-A${y(gG2*r8^O8)p4^wKDP=nC5`>@ESfcZ zH&idQFC)JX?cmrdDa-1DYZE^s^OfyIX((rMW41O~n2$P5BE~{lZNHE?ojVXxAL|^K z+<{$O_pc^*44b`YG+BMNznk1Kim(DqZLX(H8ka(M{VThMN8f3Z-BH$Go(Arwh7zso zJ6L2H=&{RsY{JpHZnQ6xN8HXAL;f0n9dTaRmHe2w?{xDFzVTc9giH2#>L)W#*!`)W zoEgvDCUZlyi-8o|YN&aSVHHXn1Y)%ehMBdlP|}&s@P50&CF_Co(JM#WOdbrhc(g zUB5ESj33TcVHkv4DD+U+zljd*8b-c;D_u^Gid(_9vao!OeaTcLr?l1gMg1&a)<)}u zk{cOkE1~|M@zm2+$B;t0d9QqVyneklb+%@#~ZeAu(9?_@wVoY~swuH4-P%<4f8( z6c9$H>F7o(x^fLmDD`JAqk#DRtOn)c+Y}u3@~Y9`2G3uS#j5A+(m~Xf6}5+T&P;7t z*-~5HVQPB+_R)6Q7DGvJZ`VvLsa$C~EVZS7du7R|;fqI5K9<^&d^M0#r>KY=0I?D+ z3o1qj_byc7F!kz!(G~9D4X{9F*yES+GjAVffhikUVo)i}9~$90zIU_QDF8Rv(5M3u z&2j_@6UPPhME?)!1t_I^+8-S&HbZ6Cj3rn`27 zep4@CbY#y;k8nBT$Qa+Ht0LW0G(-ti?upJQcoRydI+UY_^l26IUI5Z_n;z@jyQ>q+ z*tBJHPQmGaWL0weVTr2Vd5oMDO|fb;v+%df)x#7?sOinl&t$G<3t^StJ^wh|6Vvd) zM3X97kAnMJ##iAGkXz57i{6D+<&>=MMK5yVh74G&S)O>vuj?|Y%=x)?8x#nu1NzMc zwOXI*cb%I^F&xT`M}lC?+jDk;8`I(N=V+DKbDFXFx@9nSD9+W+G`UoZ9jb>Fbf-Kwr5QPEKb@&|x5}JDvv^BQES7 zCC!`1eW&pFR&Z`BGU~aLYRE#is(mN=uaoMc50e!8bKj>fRNl$04g7hS{Cgg4*(UdQ zOqLKe9rU^SXaW0Do=k|szx@g?M1700Ox5(f?ab>(>doqjLz0U4`$vRGt&wC)cQI07 zG5?4_snzaNG%9u*76PSe&S)$uL&#LcN_|g@+=#ILvCI2)ata^;sLB1=qs4nXe?!-6 z)0sH(8+?eTcV-&R%F%ZHv6yYM-zd_L(7EPJr~)Wb-g}W}}_h+fpQC(ZRhqi z2M#j)jq*SFA0Ns;iGX1q`~__4g#8Wyv%-JdV(aNu<6HL^#z!Q!+}d5dU#dHvkGM2> z?a19b2zY!_BSza1$?c;$aJ@UF5h14``}KcS6wQZhDLKsFupqZaQFRngPW&9Esr|LL z+H^95V`~pmXfj4u7G!r5lq!vAFO&^XzoHhl(-(YwElZ*?=pzYiG94le|9a!IpWWH< z%PXddRX>oAP`&MSy(8^HBuv@nm-+WPOyLv!K7%6-KU>4gA1*upQzMYXc_V(@!-}!k zpFJ_W{2}{Z{#aN~XQ*ZeA)BdiwKfB{Z8qk#^AoB)tbdM531EkgvO0eGGAZBj`o55G zcqj!qCbn58Y@xZQ5TnWak8nvL%(F?@$l0naa}0v^F8CIHA4JwhRAxQlu!X4*E5rJ2 zTAA4Yvoe>zTZM%QWyFN@HVj{F_3ue@keXp(qff~kzdJ2bA6u(-ZjmF4aW<5!zExyb zee6N64j&l)cKsSE zKU47}#Dh7CbCLb*I2#}{6_5CjtHW|2v_&;MZ4hL58t~}PQ1`x8Vhdnz`^$0E0GPQf z+%XS*_MyB#tjCjZiwb7OP=a;0e+Q-B4(BcZBj$&;`*TZl3BRa&OL|+D+ULv}i^uP} zt;;z>eG9-{-?r^FQ)!A;?(HAFaQ#-J|1K=wQ#EUau9Hr5_1FhNX#>`a7w5v7}TzUR5I?FW2KGb^6=UpuZP1>hBHB z`rB$XC|ke1RzdQUhpgYUVe|d)z&AXio~q6g`Yt%j-S{0CmP)vW{!_$cyL7hws6`i7VkkYLF;%CnwI0DvCfFns9cn7 zM7S=ze6100{Te8+4J?{?d7nPCmG{L_%=6SNl{obzgD~xVC^hpje)+?mnpd~gv(qYF zUu66yMItSFRG9i_+|w#rvM6@@iSbOuXGn$?P3Z<%Un;`RSjRoHJJ43ul#Qy14(p-gsIfv)Oeni?htmE&o%%l-bkIy{|Wo4KO)8OcF+;13r z;4lhx{>k()?oXAO?fN%NEBlcGb+J*fO8E!AQ6vv>Z2#=4fnVhGv)0TF<=uU4(^drw zzTtadnqY_8QagzYTT?r!AeUcWM#N*wI~2`5I0`xlAKm1BhyPcpJ-`O)KJ^RJp`)$k zNcZoeJ%3rG+@ZI*ey(;zp}g7mdSrGT>f)l9DU{h6Ec-qUP zOTx0;Ss&}VzLvXD9%7hRo?nIQ3+1>FBcE|k&QFqY?o)PdkieNmf$%#2jq2RrerBMp zE3ujv=DWx*b+12?lM>&d#K7MfHjWcE{4oa2Px2Rk!8|+-m|+CWkfZUHI!8FhZMrW4 zE5ZXhQqcW2wE$RY^Bgy(URfao*2d`fc>Q{?Vm%PO)BxUNTv>A-ymdkMBW!uFwL27^ z=`UA!V8@zXyWw)oG_#?Q6|LP{g9VGI7I>e}T`=rYm8aGvH>^*(SaSO(W*wS2c@1$I zW*x9}H!`K3f8ZXJEqC)&n+Yxl)Z#2Bqtx@Qsn^_PczVT(8@m2BJdvyH62?(>awL}G zY{e99%BYk(`=r6HYk`NnvOcr#%=fc#)4M!vscEvFl3V7<*>Ef*UU*TmMVD15(KY>e0NH%039n zc6)o?az&9%J>S3U)$n!`uf}#$UX4AV*Tc1 z_|b%_>?eSc%{)jnM)JLG%U-&NRq{Zu=I-$e{oM7)b-oy!H~yixe||sWVXs<$StGKE zM>EC^?z{mY z@ zk-bmL)F>@eiAK3!;3cLrS=?vxxJYV3#bGKM<6L0oYm|=ZCaAV)E5EuLI$_?mysajl zn;nqd>@EUy#DiNNEch#MOKzXrnmKLwT*XVQ#Kr2E)boZBh7TGoE+;F?-O}?7G0f{- zL90d++Komdd=!B{>Q6}(OtY`Dw^uIKcaOb-%Z*6)f=zf|Hg&}-@lZL?fv{2$nQiONG!i{9r zEZg1}#)mxaMZ3A6VCfRs44g7f8e=R>iH9l z$Zz}@SU#{I`O+veh+DtlKG}Qt>|iX#+!=Qm*S2zp6|oJ4gbuY=h;jUeREYZ+%M zfkk#W45hf1$wKNwW#8y zd(wbgO#(etyYx0@NVKHP_lVJ}9vtdbt3z9`{>isZ0wtpXKns+GZ3ZZqPIg(&e>=q= zsyO$;Au)YtXq6OvmD`F(2SfT14t?WnR)?u%9T~#Zw-iNS$%e0a`0Q!zYv_Mcax{9& zBLH+#1tXuS9;a@d!;cS`W9@bMIvA0qrxz*R{Ux3Q=110eq_1(2ukm)PvBJny7?Q8i z($kBS?k>;QIAnS@n1FTb0;{X1OLf_q(f@jS4%GD2-}e#Iv%zBqgHb(9k7{*q7-kSA zr~uprzH7zV3NvN>{c4z>Q=3qPOUr{M=nBu_0J z%b(sZqo2)g$)PM6P$V&r927ZqMk{{eT~%z8Su?|l>4u3M zCG=jz?zl6|vF6_jY`9diE3#jDPtzp=fEevjzccR`v${T>c)%RT^!=63*)qx$$K z?igG}e!$&ar=M_Dvx&%I3aKO2&Nf3kaiyCZnGh=FIn`bhbW8q|L8ZnfP4}O>LpWB6 zB7v*KJHh-=(htA}dj=b*IdG%0l4xhyF(@-g9aJIFs$l`pk1yOn0&YB}h zwV@3(*bNMRy;1kwWztZdGJLc5bM*e({ChNOF}`N6Wq8`DxAx?DBd(KU3U_Z14AYC9 zepYqqP5%i|`GHRXZY)+(ZUFk`8N;-nT5Uj(cS^f^3{OXxZ$@p%{yF~*vBq65O+o_Bz+##6%_+v9 zDtFI8Zn@Hz2J3*nyv~>GPH;S@kNf!kTiNFDYn4Bj@;5UHjD4uLZ`jFfF1=P`Cjwpw zp?41e8Z>NUNv_I$sn!=acD4jYBYi@ON@|FKCz`}%@dc#A!4f|P& zyMU<|`$@aI6}pfaE%o5!^X$OuI~38`;K9T}c$gigM#JKK`pH9K@ z8Bzbtn!@L^sgv=MXuD6GpgyKHzx5L=l(URK9H?o}sd?;lGvc()xN@lw=6=LE@zLoUKNS#1q*?DJf=P@h>_-1r}ZNau^P{rl&57lAb6 zA_p$}I5@6GUw>1|Pjmbbsfu$;^Ip51fojj{(>cfdQ@_m2&0C@GxnavOJ%?{LsmMKc z{pL(ifZ$VZHVA1xf>4hc1rmP+={PgJfu%-gy0S~U44|;3O=uAAQ?o{*NxWWC1}Q4> z31K_4wGVr5>)jo!c1(D;jvdDC7k2(te`3TtW2Qmf8hfxQ_x|xPfW?+25*+?_3}C7l zz;t!h7{K(10o+r22kp2`SgN^`F--d=a%^B9b#-c<4Fn6nDP4&>wu0_;{)zcbH|CFT z|AdbgF`P)`a3ICRWhUpDG<1!Jr)$B;#$ieWO34(p7fsPz2CZZL z34Hb9wKJE@rKy~V4}<2&HU1ty(?G!R$4aJ8@ynC%jSPDJ9jY_zDh#6$zuXoMzNIg& zt;t>mEfnc5l26=iKZIO$7FF>$d{8IivbZjNR$!VT`E5ija_%B!_&^d(UjO&!iv>Uz zQ|eZw4k_|yrMu7cLQyxKaIL}v>|(up<$`Noa8@tV9^-j z6o^{^p0ZyeuSKTutRc@2vI8(=rXzO0HUFG{^OJKO@}-{vkX}=;^ZSf(0#lmfZ#n*$ zi%*3NLzISB8OX$G_+GsYA>c?u;F^v-bdfoZ$?QLwoJM`D2kf+Nc9-FqX}pb7>0F+& zkQ{COFIVKm6GFQvzKgCuFm45gpG`57y{^AVc>IJ=ps@sx3lc}LaDowU*hM2J)AV_KCUiOFdBBHvBAd|S3G6t-8J*%a z`KvkQYqJ*tcDy__30vxK0i~9NG%YINP8%%kedMmORE8&IbPTv?{q7K+`fe`$&JU$S4==jM$dFw|S~0!p4BDQ#8^KbO$~q4xYxc*=74cJ@M`myj zgY=ayLmi-drQHDN+eRJ3O-zY1b3NdK>0JK`_C5|M>h#&89%oR{k?8<%LcQJ?y5VqLYUXM$!SP!&`zGEceV?7L(#ODfArSuB={^tNumrD8XuS! z+4sEswDoqT_Be3J%Ts1H5YpJ z^Iv0=#LNP&`5jTvhvN_A_OrH5I@9F#rzkXeVw(H9rdRse_k>cz{dsvdV-yo~{}9-r zsKJ-k`X{34{Zb$n_l#o#hVjPbj(R2GazAt*ljIFeMne<=LNj677DqugvR>sU1GX3m z9u0XH{$SzFVl8kk+!CVH=AzUyjPYo?BBz3AAFxDTj-@%nlp%rNkdeF^ST_U}g_*#kDg5EoKKaXiQeVa&nMeFr{k53np zyA+=y^}vFl*^+2DYPd$Bo$pB z6)@o@tEXiCK-D@!)%MC_@oK2zsTm?R=L?bos@2VVL0s;xs*S2 zrYNO`6n2r%!9hQYC)t(`g8RM#-tF2m@$dX?2)dJo>oE7sG55yP6S!LAm@Q$lv%0J~ zxOHW7aPL-K#P%gJ6)J9d7LS_cgeBLJ_#NoaVFN8S20ao$*i&bZW2zQ4O(MO+_cT@2 zmf;;ck+fLS5WGys%B8WkSXy;#)p!|9@lu4o<`ijewh9&TukD=8-AG1M4@@4tTP|+J z1$>P{Hl6iEl@El$RKsV_qi)DZbb^e1N)2D?Oa{{zR+&>8_|hoUYu8+8QxhtJwgze+AN?Rb$Qo*bl}&{9`qVz{PqdTCSeR8HU*4nNMDHeGppaU|Ckq79kQ!a53qNvN~Kx4T2{6S|iVq zMWnx_Z6K4ca>A9=%v-oEkBRmXgM#iJ>Vg=?aPcF{Z@U+SY|+w$KAPnnxZtS;3v z8IPQNRqg4Knb3~x1q)9nTi$BHHGw^Ai8U82lp*m$bDuA?$$(QTBowN=pVZbK6a%Em zO+oh#R-=zHfSjaCJ~CFw5PnDZ%9;3y1Q{U|8v7UfYlx}!LCb29z5-}Hj2oW2Wty~< zwXzPxrkqEpeis1$eb=UoB%40`mTVy$RZuJy0Q=%YjNhCo8c z8~@Chvdj4+{sc;Syv$b%3g)r0&sXcV-d|kZdFN)ktvD;M#us#tgloZQ;bi;eOq{}x z$wG~GqyOv(1_XapP`esaQ?<1xBg5fq{icr!)Tlt+tiy{Pys+0QI=O{3do(jt9s%R) zu!?+4W4Z!W+h=|iV~V?z%-LsXwv=CE54lk(2Uv>oyV-hwjna{QMAq^b-GAuoV*6U) zx2CpK6Cv+W76#2+dyWX|j>mk_A0x5dQzH7*Bao63pn`r5` z3_g06FODk|h2REg_yZ};i#mxb~CLhql8>XZFP@0I!Y2$=Kq^@)#y z&t*#aiKQ5MmBj1r%ylt$gf_=GJLlwyj^(>p`0Tt=DaLFqr8z&O&I_QfVE!LytJK7J z^AGvtCllFllY1gfmlXTZe=}_8(>Lwc+a&%`Z`bDDe#+ZG$`Zb#$J--)D`#Jk{n@-% zWPConH@BbmgUd!D!sO%gmdG((P%ej^kp~EF)WHhc*-(~vaO^|6{=n=g*iGE%@0w18 zK^~he@xry7`_t6$c6?&7F@QWP@$rj;Ji>XztH)!anxSFY`)LlvHgUGNWtA~XtUGe0 zac6V;ra)>ssjY5RMGN9O3g#y%GS7T0nJw?(oO7`7yQCuNS^Ql&9U(&HFG$YaGFrfA z=?BXuwx!FB&8_v($+Al~~p{&|Iuny)W8L(LkDWBWlb& zg!T~atW;AjXS?*2_P-H3!_+;sYXqs({k29Bet)IgUh-Qk^8Ro)o+2@mZPr_Ax2r@X zY1+PpswkqZ>(L^#;fj63Kb4A|H}H`qsrsE+h{kbvx16Qh^V=*3TN!Tnu+%C`t!h%;I(BXhkqC=0*-I~Jxk{@r_jnn|?zbPTA)aJ{?nxg}VjLwP zbk%F(3G5H<8g!43y5>b+NPWgAVe)jigw`(M^3-1mm)R!_7W^6f9NULeG&^=T)y@P; zP`%vt>GfT;T?~y*e4ig_J1t=1?RqX>ErZWgbw092ct!cp@KpI82 zC6doLoJyBp{5gwY`W~ipX0F6{N?y!KUrUqVK3bciCsV!=kY3@@M}MzI7g*C#ZFM zd6uYLCOTQ)wHx*2uStX|k!MYUI!E8<7vy8c3PC*TPSp3CK9t`O7@Bs6D82hb>28$1 zFUr^Fw$0=Hr}=l42m2m%>-AkXY!R~&NIR*p6^!-NJV4$_(4o%_8Bk@WMnXp0LS8&FtbX**2z4q+; zG*IYS49NZGPsRPtJ2zNRtwKe$%+f{q=F{xE(B@Hhm6|w#51InMgX<-hd<)r2sW?ADLlfId6AeL*<(r2}1d_jj z={79p#jm99-A>y5Q8ZT(GXcsNo!7T85#maI){aN=7iT$!yoqbXrfm^|sfle9aZFP- z&96N}WG3cRXGGI@==+JQ&;-ioq}w>QEfwy%7&~?uLE}j=erU;UpT7$u2(04)<}yEY zPe1{KBb4*R)HX3j^}%CXYMFL9SlM6q6v6qbKTwTGn~&({+uWVJo8vuURJXZr@s?d~ z$l_y<+tMaGOI&qf`%dWC7+0WD_rk#h+ z-{;6G{L|Vys4X(o9}^ksVeYg(9nmO;LI=jy$X0Jwdv+PF*D{Uts)PpiiY2gwb{Cn+ z6#Cq#C-Sq#>#5S5!lYsxuZq{-ERqU(j)Suh-y`UeVZ1fFR+a@i5IfBc-G8|6N z!t^X}aiST-(--hn=9~k>mP}4x$0ZR)zi}$pG_V*WLb+ewk)zy4ZQ|LBSR&*y;IDUC zjw1`D{y<`4I?b@+JsD-J&WRM-$YO&OFz^4;;Mz{~?wU*uSYl=~9Uhh(dO+R* zX|9E_H#dq+ZWK~9$fY21s^i};1_CHw{25Hs zz2jt`{)F6U!fo91x@FR?T`Fn8aO9F)AoYx707>#C(TH-&! ztXP}z332bAh1>Y#o<5n-&Z@1MGdWJ==Qvxist4OEJ_3jVW!z1>tK6yry$QmSt1tP& zeN;8CKV>bc!e3G0g~*XsomCQ~#=&wlowNR3F15lGTXtfpirTqj#4C(u*1AWol>w}1 zy($_0?5iOOpWEIom%VOCaA!4@jo&M*JY-a<{ph~D1uq#}CJQ`7)z=gypwQT>EE zTbnqPgT{CW=hBm_Fr}>I(wz6g)Hzf$etX9&Rz5u{yH4LMMOH=3U zx->O@SJZxR@2KG3{TA%MK)r9F{hqay-ak>3D{twPC;lVHr<&edaL(X@@q-;3qj+XZ zo5z2NAmw8Rv&#-Ael$|{8ksD@-L`ucO6V%CCegOiyw@6$MuM) zHqVDDL9oj5#Z_%5b7wGrph^}9SfgPAwNa0X1~-1Hl9({H4=&CXs$AS2QfMlF@`VN< zFX|h%c#V=alqCJmlByPOm_SllNz%70sbcXWmAa!iDchm7R+b2B2OiH3DFHm^zib*L z$ZA`;|J2*Ibz$lzufJuyZlg$m8GMEqc7v=9nm7~~Er$A!)4v+(9Bocw{^hnP^`mN} zWRdnTbA}7%|JIt}HQ86L^|B$k{WBDqt|Bvon+bslqFpH?;HI$u^{8ARx1Har3l$LqOO2!E2nuxVKs zOjx60%>*6P@Met_Bpi;rS%eD$a4`Q2N}-!ghZreZ zt*puSJ{$B5ih}~Pc2!v!FCv#oOeEyea3kS4jJ`cEWKU6E!Gl_81>l#5CW_bQmmV-6Hp#lL@m{{j$(l4A{ZR3|V7Be9VvG)g^4Lbx0W zI+==Cm;#EtAj;}blML8Ah3q%ZZqM#*^WFstm7ShB^0;{F?b9>Iz-L(<%~rh45H+}Y zfH_AtM5K@&MfsX|CUHU8;F@?790s5NVE$@l8Fx(WHTRy9Ise$GIvplaWugq+`qUBd zV5O%Cs;LVW>JnPo9hmQV!cy^s#Su^NkjTC%y+C}XYN?pX;xf-MqSVK8sl%3v3oYJI zlBz=%HXnw^&wD(UkTr&xBtno1b95Kt085Px8V;||O&7-*Oh?CLWH8Ns&MIuq;S`vc z3Z0)U@G8P7!!?^Gk5$2qzb{6dDx+seMMO=j{J9bzBnWt1i^#j8cGemCJ~iI7eb#5# z!Wh_Zk-+Cs>iNMZ3DMY=dT!SKrwY`$=>pRXuyddAmzlqTC~ao4r0%T(j$D{Dc|m_Rg)~w@^E@s6U3+ zKx+(82NjKD*5Gh+h-m(~AbAr*!)a(@YD-({je!Zp_J;okzvoW=Xxs*yLG5ckZ%96? z_x}rCcmA7j`kMk|Rak!{-OYh;ADi`Tqr`p#p-z1J8^+!gj?7!3)w@U%H_Z1d_L6AD z?pGZ(*?$>84SmD~;2P~9mL=jYR1qlG)a>_ED=S46uqn%C3=ioH)6K4qwtIvazO*eN zDs!-E)+#JQ%ywY*us4xbRzA)4CNj*Pn|o8&vZwM^kZ0nV3FVyK=5|$!1ly7cn-??K z!C2ROC(OQ>2o4XOG+6t{FO6fCnf%$b<%S8|6Ca=UD96$cP2H10V98v6+_2!@{x()* z&X~^}Oud<0*_GUN;_QR^H;hcaaN=&OB_wV*si`7!2l;31=lyN1rK0$$@zk)A_>|@i zIIu9UkD5}Iy^iih<>9Vn*((a~vhZZ5|-JUD=@#N|)3r6Yf6lxjG z@$%&At_1`yML@A?{fF{_pO(t!%5b`sSiNDvsDXc|-ofFs8hf_R(Jcs>(}(rDgOjU2 zP~H8mI;wXK&&8cOOe^q<4n$LZuy&(_3lL?WykyLRx* z8gzedsh28=UGC&M{mKtb*9Y#%oZ8^85A^X3?LM-XsbvBo6SrJ*430WIYde})vzk>c zHEPjo+7bpQZ?XH85HvokCOG$aV3-;nrmi4v&IS<*9cyMMi}4N)yte9O8HaPP&*kTr z_PA2S4m+jig6>b^ueX0V?wYFE1pWQ2EMn!`;^nWpdk#XGD!-!A-w0cL-f6uHX@NaR z1jg$s2OcsE8~9g*@Bdx>!^auBdexmXr1BzrDBRmQ=4@#F|IF2op(MJmW+x*4WCp3& zvbRJgmYck-AM;ZmqmLsPujV(=9MpH)=37wj?cPECEoRnMz*$+J6mV8n^q~GO+Xx8i z?=d5PP=CKS?q|AdyGXYH9z>mG_q(@?n#EfXeEl{CRuXX+7)DXx*;A``5?*2MtXbi- zbsWqD-XY?Rn>I*7l)rIR|NpKHY$h^i}XB3F0)u5kDb)_j$7`)jT)sDx<> z9xeIn^P~@A+o{2!QM>e0X_58@o+^TO?5~C|D{}T+?}s26=WUq`-0^fD(+J%r2KweH z7a&{P9Ui&-WU97JjphZ~r>3>hZo8Ok(jo*$_Y?d>%2_;9`!QAjHns!X=_Z8YYn8qO z?j1~M%=sbV@C%qW#Nn;`D1ac^ftc;Tv(j3oK3DSIa@E8&Mx`8JMVP(GgOA5tEDm8(A&t6W=ZW?dMxtZCzT zGPKvNcFVy3v0KkudpeXM+uhFgg6Q>Ri}v%NtJHjf4V;74U7=_d8{IoIN0g=3 zja_SmTr@xK)WmQ`vwYww&yS04TlDk}V8`MZPZV{U@;)Ts66ZHht+f3PHGGMVfbykU z(fGGAk8CozVZK+0Rf*5r4#h?{2&{7*8*j6;*-fEiwrjB2wezS6$n_I%0^~8~a zYj6gu%FW0~-=g`|h>a5OZk5|hqc=2nm(rS<0ySK*z@qszH|)0bKD7W-*4Iiku*3aH zdk74ItGsY{GqY?2?e&=1-7P*Dz$cE6HUW_gSGp@TR@-iNZ+=OTmZ8tR%HtI4z}UW_ z@l~Ztxd$x+YB&pvWhlZwhAVVn$W_=3I&a|02n`(1Y!T;QZjkY{)-Fd6 z)_@g>amb&zoUC$(>|L0M96p>%%Rr?nKN+R#uab(8U^&ci^dL-W;ATJn?z*p(;DaKR zwMR4KJ9vO~(58k98yKMlY~g-R5jJCIil9JG=4gDn&y8LpyjAH9^?K~qc^B7K?Smkl zjMwgi#eBqlo3PlCqnhVGMb9;48uRD5x>2R}(_FAp`zb0P@q;L}j_2=0&ka1^8a+4i z{Eg_jndc18RLoP_KUE+054db{bps1SwL6%uJ|ZdXRu|*Djd;~w+?Ud4XoT-8Ag?C+CN)A|AFA(fT=x1u)wfaed^`3o z?q5yyjm1Hn548h`+&aVyQ=r;f&o1_ITpLZsu9eU3i>;M*iSUj_ugU zBDOQm`qMF6cKx|A(4+ER&||6o2<>qAg&Xcy#38SWSj^fh4DqUSh-bb`Wy$O6h9{Qj zEIa(IP7P^=bx&SvSiYB3#erWG@zbcXo~W`SRQ2__XTId|Gv&wsA$VSAH76F&bSQQ3$hU&=3mbB=q3+OF{Y(iqq6 zc$-2M<~gw0{TlbLv3(PJUN-)b*drS8nN*yY5)1O{(DejYl%V@Y5K~swHi9$e<{PV_ zKVVns+?BM?AvA9K>BAw=bI}$cRmsW4iK#bdjFKxGeClb<<jX~RZQic_QXjFTj#c;>bIQ+NjQY<+iA3m#6zg5F$@2?VIBbKP# zG4=96 z^J4pjX%Mz@{_#INKk)dH=cl?W92b7FP}XIXNwwH$g-^7vJCumynBH^q%ZHb_15U;h z8g8n^H1X*$U8U`i1271|NKWD3Ug0WD1e#nkTLG{t>2;C{6{FkEv&3@uZ{fxXjl@!q zs+IJyHL899ax6^Vp}o=&G^vko_C)*zq`;Qc9HiQrTuD~PMhq4EDJr6bJpT<-tqlXu z7U)<0uqCmHtb7Sui^OElzYBDE^;F!DIf4^ON9jGk@)F%0eUd>VfqcMPw><0_Oq`!? z9u3AG=Bh^Lmx;q7^)^~9Allq|@tb_6j%VD$%UL|0D49P-m+u|$>)r58j2pT~(Y{>!Adn_u9SD52QeJFniEdIaF{}due9)Ld8=a)y|~#Q%0G$v3lhlC{1b}vTYo0e|BvjC;`Ky4)yu3kM6ipekG*)q z;blROPVe?S)Ol@7=JLTdBKNlSzrvME&kcO0Ko6|&Y(~GSo9)1(RU9a+a@zteh^AM4 ze;Pt{(?H_5NI=o_N(~YTmUS2jGSeN48E=ivk2iS4E{I*o@SEWmeD@TeBgc~U1!M7O zca9WZ$<8a$2Z*=W#{5O`nTq|Xclr@FV(dZYYY-cXr|-BMmhW1dg=vw0ex$5fS0Rmf z`m^!$6_xG}*BCY)M3+9&&Akfhe1HoO!IUQ2@b~x3PO)6Q*ML-m)RpQPGw< zy+I?hd)P}40F>;%b4K$=zdEJN{pr&z8|2T;O62JeKMdwS4gM7enzXo6=3T;$*=9Fq z3eHXUk_Y@2f5AAiBb3QwrSa{3*F7%?KH{2B@Vw?gq6r{gw%5@fU6;f$<$~;sr|RUg zK6&Qn`D;|)&f@y2sn5NAyszxE0%P491YoThZTvNHn42kxTNB>alKs&$@~(iZ75IZo zkK8#p@UH^?e?8mN;@qB9a(#I$MXVtb%snz}458;lt`eos?w=Q3+hIJ8+ zb>MbJ(qQLYBIg0LIa|8LIgl;h`~V#^M6N?Qe3J_+^eR7`2cZ1Hc+(?6x9)k5c@?c# zo{XhqRZXjc`1V-xt2M(CV>2^P#FZztd?Epb+P1{{cN`MyA2@*cz}(bY&5dzb_FL-z z)%N(t_-^;VbGPbDezjp(;^>?}P zY(4C`nwbmJR{@?^xI`K>x5*ngaEN^)4VEj%?c_+_0Pt`qys8Qmh@~es13L~iJqq0V zcOBCIhM-pdrU8w+DIVV#_S|nUODvg~!Q#tKmHZu?WAUBH#I$8v8*Fnk-n1p?M(-|b zOMlD`z^Be2_wH@0#+wA%Hm20vaB=2b z*!7%G3H-URAXxYv`ly=mGC#i7!iIS-bDdshg`t`!ftDB-_hnr)9S;jVXS zUASs|jjH6gj=3_G9KGRerb=-vhlPHMNVZvPNuOQS%4w|blz=PgDxkMpUL^NVx$H%A6* z@vBr+SU>2(?K6g#Wmo(4kfjbQ*?RXfce8NqokACvv`4z;)vfU9w|qE#-_%nqpBm^U z9Liw;7#?q6b8CCh{VzU1rCwHh9L+lt+j<`EI4mbGr$vtB{jJZ73Bo9z9f9`}FNRzq z=Q|jF^5HPG@4;#c4&sjW-BC1zQhH_Upf2c{LuJO%$6Z2riNBL8xq2}B6k?lPeOGVi zuE?qLMv2+ca_!amTekAoyDyx{9Q;tyo{SDHOspA#f^z7TFi>3(1`a6^29ADw=y_&0(2hL7#ZQs_Pwl-O zsf=<&EN%}QTq(+{DYdyrp}i9^)xqShF~OwhyX+tIJQ93<&S5s1gz_Y>O;;Dz`*$}* zFH7_Nk^X@FLTcT#7jkBAFJKp}GhzCdCS^asxieO#9`90dCJgKv;+zb#>o9%-kXhQ@ zUjV)&@t=rFwR)weRKcf4hfS{IknB->9YPPnSLg3z9@k#g@kU#61$xTM6{lpbtf?fl zSq)W8sx;8&!4NE*Mn!n&>Qwe{Ow`)+>X2e=j70W7JFRI-$PoT>K_&JKx--x*df-vy zohh_GkXSM9%3eo9qi)0>L*{ock1t}i`rDo5f` z1Lmq`YZ04Dv=!Iv9sE``H^9Hk6a+XuiOKhvoSF`5v_d&X-X-ubWkB=xlLJTkXk>c% z_UX{+L3C0tDZMO;I76{MCMzN<-vsc$@WX`J#6i7{x7rnjXHX+pS(lp%h5cMqWb_*o zHx4l4Vj+yY$tr`MztVXfsTl(gJ~6oQXl5BT4{3R3Rpz8!AX;)eUYx%m7liD~pJFFc zefjQ}l>*Bo_HEU~^qi_VSoewSD8srg(nxGZ{s7-}%Sg+(sZ|}Xdl8C-Qmio_3XGs4 zITS+;8&%HgN{8oE_uh@~SUfee#+|YAgTa9rL*%i@Hj^C=@J#p_7(!qHoejD z34d#GVf``ry6KI?-Yw%Ut?GDFZq;r&Ymk~FY!L?%75~S*^1%o2Kf~_qFPRFPHbCHB z`vlWg6rZX0JuhTn4=Ue-r0d9Bf=|L175vt-hELqdKu^J`F&<}-#0+QR9%rhu&r^Xh zO>yhai8*flQVt)^nnd&&7zegh;R9NEo^R~q7IM-8Mtnd76|kW}*ihuZ0-Dx@>4~=U zU<>1KE>V$=M@WFrO>8t_LmmF6Pq>E!kb9zS$JtW*&gzXgw%`ca6Y0 z&hmGxA%Vn+Fg*-BO1S#?BCsy@mW&9jIJ^MX;6@9qSH6m)E(94dsifm{ckNaN7y&lX z{(l3iM7e0axQKYydCjW+3l`+ z_k+Qn*E`P5clgBrQ-?upZ1uADS^w4)`UfPnEj3~+B1tY&u|0-`7il0`c#F40_Hk!i zWW;k&fq49u$dL8ZdnQEFhOuiJ@ld834XrHR)`PG&yImY8hq!*rJVHZEv`E4&(2R*7 zz6jUdn)uH=FuwSI0)`zz%*i|Mdv8lAz{&phfje{X`KwGtbZ7IwSCnPBim2#3=n(tz z30yoPR4=tJvzh_b2i=c6g#J7Ga>1KG5ULPjzjuKF;bDNl>A7gb^PTrVguXc(6DYAk zm$_%&^8Fup#pq|!nM=#AI~fW$mk4*zkBvyM^e0*^6wuPLMWTNjUVCGTa%fihpZ>eb$t$8T z0C(%_+C4h#Ne5&02 z)8~o^-^))CK9u$|T(unPK}sVYDLu+w!%M0D=H+|E^GC`*vp4vbu&7)N*$K+<=q?zZGb}kMH7IMpglJfv#-`7pqDBn`?%tzwyc62*vqFanrsz zvnF!((F}NDrUUym_Xj;O0u)@qrh0JBUR1Ue9_Z5LZW}|QJJ~B4 z#Sr<;4G^PtRoT8&ZZ~sL$^=3iZ&Ll(Qjko8pfDF3l&iHW2iEDG*LtmI-{R~gdT znHq3ly_2GBbYySGpW?j@UbiXG{;3(Y%t`5v%guF+p32XZqPm~kuDjR-60zV!0cncY z6D5@5P3ic(zDt;2_u@;!Z&1MBf6!5Fn6DcJL4sq~u>-?dJFGdoC#Hb(y6CSR>}B;h zUtM__C=1=!TZgsfdyPMuwAp2+Yc6sqf8Y}uuJg_bh$5hSNq;rofff1nUG2EXRb;a( zE6Z(B2>H9260om$^9Jt?{3FQCh^6)ne1B2${ox4&Zu}xstJx)A@^KK}oimCa!BXB{ zZu|A-e**_+Bh$F)^fx~s)ZgojyR#b43+Ak?EsfK@x~6{o5;Vai*7J;?qmL645~^X0 z#??Rn0==d3{B(d7Mfm!?*H}L)g-czODYN~$)FaR%B6EZ_2+Vnzd9*w499#DHD=hm3 zWmfiiFY*T?* z-YKT~z-=Y+Z+d{P;k%Ts?1W4D%*uK)S)H${OVM{t{R`+aR_$g z@*KVey@&*T<;nMFryfhZm3;r|#OvJ;bzB~KbUq5^7*JOcq*1e*{9st;$1x)#$(R%w;*{Y!uu#&tneWH!z90{;QvNVZR&rdjX$K|M%zZeE{(i z_)h}X6D!@uvvWA<;oAn%l2Dj{l|F;bkm7y!{(FSD&p|C+ipkV*Dg6|)y-w?c@D>n1 zU?AQ#EV$XU5CLgEObKX~p#5H00DMex0I_dGuTyin)&^l0LUsSTdW z3-ATJe=EjM)@SBEkN;@$7N0_MWSThSMYy8su& zRyT$mI&EO4w9fP6=~Fq>h*c9IaZGIS2|x@4B%WuS7z3%%97kh4aCv5msLXYmKtdiJA2 zhHY-wMnnFInIlJb{M*1awjQ6)DYmFga4-AR50<<8{sGZ8y`K1D(98bE_D`plcRZEL z(|bNGx?9OHu$uA~m}R4TFlKnAJutR<1gav$F2?65|E=WD*LV({bbC`{?h7~Y9K$OS zm2Rgd1-`fhI4eR;7w^5VG?D)&PC5j z{I?(T&72X%6%KpYCe%2%;LF-QaHuF-PLuVU!g=rS3OGhJa=~y#$VP|>x(CQ6m>v!R za--%yTgMKLef=*I8^9^m`NBQoh}&GffKD*qc6ZU=xcLLaWOb|NaV&Z5{EC~vcQ4aq zdxx%1c9{?r%Mh*Fo_X~H$>+4;x@f>xJW>_VM2-94VeL2RsxQU+E!n<0pASZ=<_0?a z^DMD#d@AK%Igq+PQBkx8Wb4VclD*2{-d6gs`IqYxd*{|OMFt>-z%SQ#ynB32(EUl~ z$p$!9sM@WQL#6c-@TElm(vTcO^4F^V#k%O?9P2#606uEL1#rs;?LP7v(9?~11S9y4 z-8)vTY-M@ux}j{(j=T6N-@W5!{0uAW_+bm`S7R&jvwQkf8%MzFh7DBb`>Tn7r3ii- z7$UApOXX%7=?|OT9xoe-bo{dga-6OW!k#(Qqnlf?j}Zz3;7cWIx0^k6<)o`7l(tvM zv{~D;lLb2VfJh;G>W9WJcy*mvlh}rmq}?a?8?b{OR};fneSVe_N3A9yxqVtN|54tu zKc~JtzZYUTh=-QIdb|71cKwY*vMsi8#wczfYD@iV$(Kb{uTLSu-i~1xUX-|6oko;m zU)j*--FRxiExZ5>lBAP*jF5W-HMWA=xWuHDXm#~$JsUZG30^!xy~(1NFmUqi&1-d zwnUiKh5+X#;HwqN5KrH&y`xS^g$R7!Zd(yse6xnz%T}I9Yd#r^4Uk&Rv?%`YGy#-{vY;ZV#zNxmv`K6vC@-=J-6iWvKv)ezkPSENta()#~MdlUG$sxt0BX+s;N za065bSS3i%lr<651d3!Jfe9o~q@`uA7NH_afk_*drm2~fj6+IY5KvUyQBhElQkIx> zFDkZWUt5a6y-ha@lv1Jje}B)pcjiutzVG|__w#9H=H9bD=Q+=L_LH4m?jQCUqu?Sl zIw%pVI{0dC=Mj$}6;-)^<;jM9NzPf%>?3#wUh>cpczTk9t|j{^gmN!EhpHwC_nyQz z;nLz)ZC|A>Z0?y>+&p%j@g|ET4&B+W{HO^D90uYo{^y6FrKv!OLTiwQX^Y>z_Z|e* zyLyD_S|@&?LvN zW&Iiz8suj0L$)vKsk`To*CrXlwuBs;;Vb-tZUHu>a3p(yPJVT>VVjqhsF|1A*Rl`% z2S}uEn7Ay}9CBBILsF@C59krPNrno!s@wjc?IZm2FMx16l*=<%W|!=sm!jT3fW8z% zCBg_c|2tRhu&~+?zMge1kS}BQxH%ikA&i|nKk&M;AS3fjWd7MGqVu-@`eh<{YgqzD zTaL1%L4z|5#KXVQtWnt1P^tF>OW9GJ7~5br6(ITa7l+fjR%oU2N-XR{1^e(` zkip(XwEEXOuo3yE0ABpx;h%+zZ^1A3zUjKOZM#2}MH&?!5aOb-y+=CZ5Awd3zE8_6 zB8W~c@z9~ROzfsD{@ibwC?g*sdD|`a_qZ3OusQwwl2SlB3~|8OAK+~9l|w#s1sd+Q z)NpU!d~5JI?Ij0R`I{eW57+uXe>udCZ}Fg4Y?P4w>wu7<8BJNO7X!A4Z~7(fn0E4@ z)0~iO0d3Mx;n;fXzpqWO#oxSH==7%lE1F?RV;x8Ild9p6w^ak(ivfHAf1*LGc!{C) zOh?q%;=eD&pgTeS@X#>~zNu%{FdDf$fkE8Agmm&YcIgoRxDHOOZonXWBJGC6?eX8z z&ym)Tt?vuHE6l_vm-{a;Uc7wdFB|#aFq@)qHWj=Lj;3Zzf1=rTxcAiGwaM!5Z>@I# zuP|)r8KH%-y~OLh!%l9(h&5-UZA6?$#q?=${CP__KR0>vP6H7_?T2t>ila>ar6^Kt z^2pB5Ql6kkuZ|*Q54;J`oO^9th>B?Ivz@Z&_Fqc#&I_eH@&aCv(O)A*g zU))spcW>^4l;TAz)Z_8yv5!Y1X(na^KV;&a`*ofv+Xk)_*LV*WH}^CV3DbW_HwkbC z_MYFQ{0rUnc%%0#55vBlJF7FRQe!)J9+s-?x%TNfZ+t)pse?LqR-{IE?)O1jrMVWexDY3mr&*}oEf%% zv+2rvs0U(x#kAPPnmjo%CDjSdKqb=j8*UFeo#hrm2Cy6yS5m&Lh0^NKX0A4R~qpIrF&Y z6H6+u-9OM>Gvd_s6WNAef~-Lm=nAsG_f4$Rtl2%{(iov9cE7EjD&k0cwN7wA$ag{N`X;UG-Gcz$G8tjw$ZCUlHTgAre8%_fD!=)2S*_dPZyqqKvD~nb6|>q^cdkpIt315ED~_I zZ-|snWEQ;20PS^s3(70smx^T1_bTmT$ewyKaxL=aK8xlKJYcp6L27-vR`;sJvLgPI zp`Bf5sX`r<7o^uc#)RXLHHV?x*lk%c&c#POezy@1obE<^g&hCF)ii&J@iqq5^dYuX zk$>H8ooNXp5cVEU83*1Ma**6#1sswwVFLiJ(erdcPYj6Tb{kTu3l8aeN-~avmBV9T zIqu|d^L z3F_TyCW;deUj=B?a&Uq`?BFpWf(J;ollT7<9y`9^mS~CPN}_7A=R@G}Z1dP>r1C2B ztDX@&_-62Ep4umXXs*LriZ#b!29X~#ha9R!>j+kT>k*zeMEez}24`yAZVy5l%#2~% z&sNm`ZGA`=4rh1@5t!C%YARVLX~y5MK($jwM0haHfA1KW2CYX>%rD$?1ZEC8jPZP~r||DBBHi~I|D17kw$ zqT~1MJuhlj`t`Y2IrS;_sKL};G5J#Wja0X8hUG&x!xOq1);mS&7#t-t|Iw`>rCd^o zbU5R4a$}1>_^4xtcC(+g%4b0yI~QI&`09K+g|Vv?4dUqw`5AbqP@iLbxIFz`{8US} z9D#lFbT&bGx2q5q5LhvJ9LSS`8w)r!5s)7;Lv#6od@UUCH|P?`ToBPmE@ z@L7JdQo0o#*x)jOy83dd98B#W-E{Hkw^(wkGoNwU&1E2lKjq}GsrdS#@6D_bdt~}v zL9uhku%>KPQ+6^2AeX73y{-i}Yqad#hR?TK1P@&y5vGrXb5Yt*3uxC1TOz1^h^@9{p1bV&+;#nTL<$%`mLJDYHvz z|0kO=k7EjIW=nN$Op-sBbC__PzkBJefS%vzc;B#ZvrC72Y55B%*?5P2x=Y3FeyWR< zEby|*T8B>DJJFnZ9&MvGJp)D!b|uR^Nlv+yRW7yl-RL11Wd)Y4w@uV}nn;Ed-3{sc zbDtV$DVYZ@1!>ny{{cMgY57QIL+5+@&KzT>5b-^~*=x-3BCqRZhO>PMzPcKpb2iQk zLcbOhh}#Bez=0iSD(9ouXwJMo@asrEF^Z|Q!2ny=ff4?p>*{sAj>!|~>E88cvfEGy zCN4-^=%q)~IIFJ2!SFOt+0@tQ-7yu${SOgiRHiw57S~XY zB01~z5e;C=&h2ScE4 zl6OrN!FqcJ?Al@Pkd9brh0`Cr3rCyX_vi7BR@A(UXaU96YczkM`bGOX9O z$jQdev+({`lmf5#)pRhV%=}1i1}(a-G<)iJcwJ>?=I*}(ws!Tk*P}d0W}qEGS%#O{ zbBq?f(VQLGoZTxCqH`isI(vCj_Id!d%>UaV5Su^c=}*tsh;?}sCFmXsZ}h zIMCNhm!CQTnZgbVqe}+=i5MRnWOsZ$G2z^r7ja2J-G!5pywXp+=Q+w>dsWAchqA-J zX{&V|Ow5_)AaW&yeJj>IKj8FXH=ch<>RQFY9o>}S4m}o+PM=Hmd}Zr}iHq|2i!SfH zf%E%rt}3k__yL?;ND>Af59R;f>Bdg_l`nx;RK|-<)pPUf9d^5&L&tBFD^KW@D)V=OcqT_le@84>IeL%9UV1UV zYSuJJyxrm-fDXef5R18!(CGpUzULa1vdf!APoTY`Z^GPqWy>5-T_JCk=r7b6ywy8L zgUJ_D#tNsP&R}&_GnYI0f50WgX+S4m(3~AzX(`YTuw9?Xx_z9;pjrAAy=b$0>6>g- z_SaO#H;_V?!LEGSc#*H94rh;yzh{5vTG6>~-_9MRtNj@BveGL0#8SoQNv}F^Qpk^K zhlzfF%9PN#18_E>HnYn8i$5+oKX#r){LP#tf@_STMEV@N?+l&O8vju02IiR@+i&V+ zvH&mzV%L&cr%|-cM(=eeOC#!z)o4K;L6>n#H#s0PDx$Od}2hFbaa*2rtNT2Uxh zqO^UF^MnjB>g6-&iqF3!IECV|@qhr+hkISpNYNYLZsdLNH{nQhbK81<(iryK&9>in z$G0aE4^7pgXj3U-xm!OB)8>nBm&ATx9@FrksS7bp>TmzvUx%0`e^X?8trk{IV^}yT zgle@q=Ih-tk3k6Xh+H2bnLFO&Xw_KmPa={*u)|<+!TCBlT8hH!addLXDG{>($TZu= z&H0EOV68u=NXsBQ#ldKUG>tIPqk?SAumER645rPlzCloBARGK9BD(Qn{A_Av1DRFp zHTQb8_oc;J!Pkp1UZh5BZ``A}^`71;TRSPDruv3iVgAT@(Rm~A`9n>lC(!tSr zqa+9N=d!hRz5DH;J_8P#_0Gu`5kCKF2tI#bExX?Qn`tyCxAu^4NZN-&d0XP4FBv#w z1p>xz_^TyPY5C--B$S1~EtbFBg$~J*W$xs*O-&7a$?MDg7l~qU)NyL));xAlzQM=g zTuuXAo43SY{)j$RB(>C~ z-h-#@!A%7y1jlLc`COrH{IU7XdDx8~h(x8(??0;93@qurJ2%fd#L`6OrGfiRp30b3 zUu+6a33pO=;Eti^L1ZH^d!FQ+&i975WGfUDrQoQRY_fu*3Q3}>oka75LQf-LeR^%` z7@!`BSW8~F!R;o0sC?#iM4ncz+2AruL`J{+?^@0TMt4b&sjFmjn@K(*#WQo*t|s*m zXVeP`Bxx?N#Ei2=TCFO-{w)h~sF0$nG%;uAI@W9US!|^v!YpehTH;NrlzZVOOmKPn zz%SzT?!ydsvG-81hRidzm+qg3CXh`va993)1S<>pNTBlr9LR>#kPRKQh)+BD@H07k z{XhOI4w6uw_p^Uao)3=vPk$-xT4V;s zKg!?QW8)u1cuP)U5VPkQrjraLnuFw9H;2}*cD^^P#U$0)XK8CagF6hU6CP%`z^BNy zv9T2UE5pB%P4j}wET*zMIb_0_oPWvelQrPju_t*{!t=mAj{ZczO1~BdR-ArnJ-`7Y zCtURTF(&1ROV(L)V~uM+hxV@B)+cp%)YU-+T@BH9L?G~ATN$m>ICKT^rK)2;M@v=D zQjPiWr3&fm|HFFK-x99ZZ}aPw%r2N_XWZ@6`3Rlu*8T8|qToB^{JMNT)cEyiO`*z~ z_B3NoGp!xT%x!HDhfK>Y&6&nKnlml)LzZ=U<1g4cI07`v7E$DVb339e@_a`!Yc;gC z*_K<3gVimIpAN!97h5kLFTF%l%rxGg?BRcABGF(ijAi0{cZfGu_+1<2d6Ss)!8%&>Zj}`c%)E*LBycclsN3nyy?_?8 zf6-iY{bR}iI`N){%nrDaMI}+yd5S7F<30CDZuwv^xP;#^{*U?o0+}w1?RjP2Vof$J z1EVlNh~SXGe{J&z;t&n+?mE&$W`s9S^1q-Sl9CwkBYs5mYjdWt+po#69U8lX<7k|h z?mT2K7QpG=oy0hnP$KeA2|+OL>l%^~!_EGi-Ovn%7hGfo3SA}iE+p72oBfNCGR^OfCpw=d{_uKpIe7*Pge?VLsuh|ww4|ja5p{TdsF{{nl z4i#+9c3Z)NF$PLt8qS?p$;_#3$;@{zFWC18Eqc zSpQM1MrZ&>0mv9off+lYdpwJ58246|>Ju~F6vl5~rb(RDlj+eDvLfn<(?7b0=}O54 z(Q}!@^iO5PSlV;)q2JGU|A`+6bzGt)B~2H3mi@xzFL#tQbI|g{Xr31>Pn5Zja`$2G z#?DH9-jCD{%oY5&a(H>^UzE`0kjrqV9H3R_HZFv^HWXt_!%N=?VA;12yl?Xjn%a`t zh|*dKWEzW#J3koA1n66NB~{%#M&J3~NaCCA3--@(e3AN9BbQnCZa#I_{t_mWj4be$xau&at*>%78ZbfDJeNfV8Qh3Q9`%j&wF%QrlD_MIp$XFgQ=v z7)4epgy@RgW>(GSO!+BhZC>m5RfuTd6wZtqkV)}6+@7$zD4VhLYr&hc2R3DAvMs-e zBI<^U!7r9JEkC`K7gDs8LOT&{ox4mUf@q&W2u#(Fb`&`lA20ytv=H9BTf#B|Z?24R zE>>o8Sf)E(rlYV-rIitG(2?B?xejNqOLzV>Wlyi}Xsaml(zT#@Gv-3H zC6{5VKM5K*WIRwo!v({NaG?z=PI+Be!F{EfjnoQVb@6dt(5U`OymUXK;@cix7m3JG zA4>@Tjau;PGxYK$Vyob1{cLxsd+nq%;my^86J z5};nmL-GW6Zf|pl{u-R!`QAsomK6laUM$~3c8^w61VYPfH^D~ji^_9GCKjrRD`|vW zt7yH}3XhNX&-%1szU%^B-{Fu*PMuI$*?YR9+y4BT4{3ZdQ;EUfR&C}-IEmh8=+ZB+ zidX3O6Zzkh^!o?-->2*M<+p_$ z(cD@i74~RuDYyX@c9(Jsu{^`LSQ`mY`|e~a52blm>97TGhWn4&2YcF)YcJi-XauP$ zR6HSzlZEKhSl3j&VpmqN5#Nwz06aCqt1q@?gP#I&aeaOt-)R`|6=>W5N-1U+-aWa~KZj?*XXrA{ugJ$ql+R!MAF?5fC_1r55H+o%P;ER8~wcNTy*+T0Lfn|$Eb$}AN+|QPU=dz3(Pon|ERFt|S zA*cNvvxo}lZU^xK#{yUoHTD(q>e*L5IY8nZL25_5K~W7WJ{A7zkApI73h)1}|$ zM68EDVUe{#ejOJ2E5E^B#3F$sxGglbyy7MA?dR5Q(U7b70 zN_35_LUHTT#~2&#^@6~r*WK{Uw~4jf%>oO@Z@A$vwvvg=rWD5%h;s8b@Y;xY0Y3Ua z3|m~!YlTSFT2L}GgHiI2;kY&?D7Ls>dI3cRwu@8Oz~L00w;E&>?{mwNnxiemdaw|= zC3(|7zA8L@yDt%RwFs?TPB!T86^`e02lTcC*NzfF{cG#6_3qw_frZL_mmMrzI7C3# zReVmK4DF3(uYC8^7nV^sfif9M#u$ViGY+p+Dpag()5Hc8 z<8yVH%xrMD&_<K;_LWfkesn3Y9F87|ZM8k|!0dj|$A3h`cO?th> z`0Ln-w%H#(j1#8c^10{Yv$^I1UPpFl5{1S5lgs_32Xo8=zH~bsXfSlD3wWY9Rjo-s z0L-4b75YT*ui1Mt=Wg}pU8!xR^p)S{3tOeQePp7uy?ii59IEmnRK*mIiii*o+bi6wB$s|eP{?z>I}{W~nq(|lI1#~EkZ%P2 zQCFW`SzYRNe~Q+fCD3?fHya9@b=L1501N(uvh8Vat|Iy@P&JV~AylvJ=iR!7r!hFF zk5WHT1Te&n1b^mrsIPJB+jHI4rFV#r}FHE}yTH*+{|xSExy8Sv_!v7`?rKmR#hicRlZ=Ip zj_bqSAF*y6dq)dX^liG+-=<-TvdI!BUUamLEb_XqK}_ZH%!|AS+sf)Y23xVN?ipp- zB~^#RS8ho!?zpMU<1NxcQQhjyGqVRMeSK;Y{(2I8i~9#g=iz7NZz#JyRhz7PT>0nZ zUi?sFyHrYxdM7S9Q-k#n_(X`Sn0YkU@fztAFZ~K#h&%6Nib5S;GD(-Ox;f)gRELIM zO6iQg(tM5|;@fy}t^Ao#nIw@ZX@&gz;RKC(!6vGMic2oV-fy74&K+|!uVe1?J#08| zrYcsd5haoTO2Tc4dCcYaL)BpUpU`a$BP8_!6UQ{4&z0#k^Sb9z1;xM}3=Y!YMdq~1LIpt9AbLyhUQR{#}VBVVY}zE)3h@I;@|=#&Nu zLGk7t!E?KH9@0RpYjz~FDRWANk>0$Q7-2%y3RMliZ_FVj-|@Dy!WWCN!s8bd+6a6I#0 zF_LJVVODT`Tempw$m~(Qimk+|3Y*aT&>A@FpK(B5hE`tTytWH1TC#5Wti5!n_dQl; z2ct;ITRuGjn$G%8)`Ku6Pv8SYO6yv+23?GZDhTk>4ID8afJ0Z_e?ML z@A-s{Kz5k!Ur~!n!my^gWnTIlws4{Tjj`XY)}mZo+DhF#0Q4#UPwyGi+ePFa{XJ?W zNj&-;mQfm%$qD0nS~BkrOpftO;mCk+esC>4GZ8Zxpudle?2=0%WU(>9cHvOIw79wM zUhBo1hwO*v;=8!CxFANU0~Wm^Sy~8}d8a+Y(o7GRW#=ag zmW5o}wj55;9!~ler+~3JAN+Bx1|vgt)cqTvo8RHNy{(-c)NsViht(Pr{M}^H4$7Jq z^-cX;(8iTRBD(K`Q>J+yAgG?M7Zq~_(fECMvz3)Hg1do|*L&&p)C-Aj�t|*Q@+6 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

vMCj88d&(Y<>NqN9<&`(p@G}znvq52TDW#=XJMd zF)kf1*4|-Q`=X>)RJ|niSLx;A&zz07rQ%l8?W3%A+}n9O?Z3=&q|81;kKkQnb>hN- zS0_}_)Qzi_B)-maMPpWmeFjTvU$S8FWR^KTRtpx!dupobRm~M8#748ymB_R1-Fik# zj*>alhO9QV^2HJcYh2Rk{yvK)b5Y(HVnUNT#%QIw&u#Iw2zkS^tElYv`VvS)In6$*S5`dZQ~6n*0$-H z2+1a^S1vHW)a!0TjKP=asce6e?R!i&NueG!;<$zasI@|AlbASbQ zy)>e>v!h%8{m`ndvZ%b=h5d+rgsi)dpQukTR3Tg-3(LmJyXp{C!-`Gq(ibKb!fmX* zDSNT5&l#m1{4*p`2=)G6T3*#ows)ulN94$Aa`}-xXRx%)9#X=jb29YC(kSOd+ZVA! z%ZsfPK6~`Nq-ODMS7vtM_?g!ijL1E!FuB6q&|g>7G~TF1>j8C5XoyPEd$Mk%z zHI)@iV|5mVjKKx=)hh^}T1+u2i85qjfm7BGh}Eu~c?z^9Z2aE%J9(8{o)Td?$EGdO z;qR+Ay~Kq{$rdU#zgQ7Zq_cA)sg#F*EP`iuv@dF#AYV9Z-^=3*PP*t&6RsBfC|Ugu zxv1w#Bn~eJz1x=(8=Q{ML?by5{kBI#ZP96XXj*6XfA?+upX- zd*6ItZGNX=LB}<3QvP0X@zid7VOgmvd2Ar1Ihmrra!H{x-tQzg)mBoQJl~PWb)29v zsI8sFT5Gg7X)rCN%p6R=)uS4T#NLHA^&-49WnHc`M{ZvJts`dZwM=$QSZ~q?(s!gI zLp8iIxO?5gJIi~G)z$ZUdg>7$|@GCF61 zGB!1sj-l?Be-dqNKp$qbGS}@>gja_PR27 zA)I&F>HqZN%$$RG+(~bQs;p73+;?~HGqNU=9MSZZF8wH%_v%pA0r0 zTcDXyCse1w!vrO$qeBVeku1-8OVl$3k+oN3{cJGL5(@H)^^D^+0gL5a{Vjoh3D#BG zYozovz072HaPZWkO`F=*v`h7+)RWW?C8>7}PP4NFUu>q62lW=q&yCp*R<-C>RkkE1 zqiyN?QG)oY(;!v!c`A`~UzPX=_INgRDb3p3_Q}J(wnz39b!;r@T*N7_^5kGIyD}I? z$QN=FKE7$TmD#kFx?d=5;~s*1AnN~S@KD}r&7PB0kXJC=%|FGt!*vs><(13yksem2 zGWOZ$6W5tTYGfUI0G*|sX%oHT`|~oDU&)T&4^EYM8;zBDUQx1G&e2DGDl*kbU@vBT zlBW1q8MesolaelmB3K}+orjG)YwVIim&{W)A$7(GbI`?M$K=Iwx;FB)2ssTh%rCUYpEkQY;@z_pwTn z%`Rl)8CgFw^JaecWO?#6Qau;#YHxd_MyA;9%J74kyOp%l$8pH5E&5qUn;JoMv_H9L ztX?+H5D%RtjDv*q%I#d0Dzv1EG5^dcQC{b#nwFTm12?C&Z(5_|k7cZ*VpyfVPJ;P{ z>w?63BB~`-e_-|xqJN9ej#O%VB|yeocpV~vMJ`)?sHvZ}q){^79(a3wAlp{*^84)w>v{G^BH2fhisV%%QZ=ph^dkb3^p`ohm_JZDNgBP$U*%J zQQUxf>onOcHL7GiQX_q6rwnG$d9bRWxFR7w@07_tVNVtZ6<7%o5j?PTME`CIKUwrp9+c#S2TJ;5_osY1Sd;p>fAAUh8RKV+ zFCZ626rM4Hf$NylXA~3`4lfunreJ<P17h*ENXzvq+n9j;>p@DT+ z)}_Y_ao;9Nwz?#>T1HE1JUlbo+RYAWqLPaH7EVK?B(V{o<~5>iNoDr!kS?W9k#BK4 z@dNpQC=Y<2+%t|+FB=E)zx4uD29KR37n#2nwXx_y)+q2r96U$`*e=(}W#14nRQE?N zrK#;FpYTYTN+BAYqcotF=#k}0JY=UX-+Y8DHKOPKRO-YfT1zT6e`v@E$DBEZOc1gs z@|7Km`x#?q6c(O5draZ*iFspKC&)5P?v&DhZ%URb{a?f6Y?kHOx|IHhId9mqK3%@w zoywlJB%9MZ@qFb!$_Cot&4UtoA>aFG8PqHk))WFD6*nR>3sk_=f= zpd!lCGbVH3jLA$iRbiDe=hIm6!W;VwrEBAN#y)DPS^=UA%_5N{5A2yLDc6^Na2($< zsH0@hu$FYm^0t;VN)Ag6Y0;C}fyXW;<-Vyj$}AKQ^j4{qf{y!BX#PSi=@f#_Ar~2i zz@0sjZeEH(QaKnypLzZ8T$ja>o>!PP=B(`OF(XR(oJn5RS*~3ECl8PG5%#%BpJGx2 zC;As-e^vMHH)ZpPQN4z#W^1DiqnNA>?vOn*Z7dUPW#IIgj6CieD*H$#W#x@GIqE%+HE7j8F(DYRH4)sA-zJ=dOnJ=?%tBMPt2I*Z*u1#_5XjmRw+ zpItCpnCBJ_&np}*CGJCG+1Hi4VC$GH%j4$wKs|gqI#izz{*7fL88d&4JzKKrm6BtM zk@BNfCBM+ikE&C<{;xNi-Jbmwo6Y_!+Z^>O#ohW8;<%Pc%8StyWp%VIqA{ZRWD!vs zqNeQRU1sVrp)<)|2~){ty(hBuw|V7pqScbToiE}jvcBKbt?c=S6Z-m_quAQbvmKH3 zjNyxM3^pHS@27QqaX6uS4!ZNLL-PT>Bw@ECVMDfqJ(T7SV;SOG3RC;FUTo}7+BK{e zjnuA37JT@^lv+d`Ez76jM7`^z*0D#}oCk#4+L_{8qwh$&)0~~buFc#$_iQ$8s}6#; zfq3ID_^WA~3_|r6{5!Mt{Tn#oQ3eTr$kAL;|A+Jv>ANvd+z5RX2)^6ovzv1IRe;-Fp zA4d!yhx+>vTPPWt;p2$-Am6X3#yeg150m{|wY*ISr{>O&V7Y%dpQ*AHTdHef*v3`DV<} zY4X?9>11-NpH4|H{i`_cALfuaekvLK#lI>3loN?hBw=lm_~mvMTPgb`!>b8&q-yI}VX&jPVly#mM=5iFc$B)TlcTe`r zF}VRT({1*C^+5I)sIv3=FufkE?C-;7`e-wJ+-~?7X5^%JFuv$hbUVML1?n>V-ti@V zsP&F*rZ#wWBn?}VdwiW zYOuN12s+dV`sxPDszf;Pz1oOmT|b`*U#kctKGzvOAJ$8N)uX3lhwM91zSR>C^{adD zNUKGaEcL>al;Ypz*zEI@KBPikum3j$t%(bI>Ucqq8fEhIFVpCSRZ6F|EI&$Wo<+TIJt6y-hO6wLg z&S&hr&LvHV{&Yo6J*dIFqrlf<-&Wrlc#B-N{3U>#FZ=sesk*yvyg}pIvuKiXuU+Ez zTjp_MceRBR$Ez(h^DNbJvADWn$>Lhe&6SHSa@?$?iX$-_sx3Ej5V%E-Os$(|;TT*? zO)dZD?9VX_uErF1dB zZ)vEmt*W=wEKrvmmP-gO^iz#-=YZ42^D5_7TS$XtVddPLD(6>QI2in9&fveb&F2IDMje)#G*^0!()8XKefmsHQh(EL!**NH{-gz3lb%I|qK^Ota3Io4dt z39;&jB%0IC#ZAeuaKN;MW6v$vzCzAJZ>X!Nuq>&?zUWtF!MkWUr>@RlU0I82i#c=F z!jZ?M*HXW1!JIn3GLBeyN$pLwbxUh4=5f3jn!Kn+Ex}@oSG2vv;-z5lFXe)N@mrz) zlKi>ELjE+A68kL{PQw-5IOUd$n%ad+8YI(EY8K}!a}YD9VOux?p1l46N9Ia$DFK%H zg?@~!GFa>&$-{qxG7t75rOB5y^;0F|>*YvS%vgOhhuIn~6cNjfm1e0m;#}5Og=Hds z=F(d8ZZQWwFRoe0S+ExDa9Q;-G_0zkOxIRZ)Ng6fO-=^aEm=%an#Zx`^_Kbmx;bRx zlG>WNbyd`w%B4~*#u~|&nlqMT<~h;1Ldvwodt=>#>Iyvru%8@ByQG0b)Ya+HIOs)> zlWY6AtCFw#;uP`P8p(n=iz{oZF0q^$Hy4VNzN6rHZR^u#f*^;pR$mfAnfY-&oXYpGh~e%xhR-Qv>PQko8NwOm;}f9fp@ zEh@&zOXQGg%j_FDpSvpA){3Je*DMO+MDHfv5{HkVeTALZZUt0 zxfWW)<-0WI@>?j^{Px6cgG1s%shPOc^CNMs+tJhCIc|On^^tPOzp7LkyizZ-@w|yU zOA(H{7D=fc_{tDq>Eq=}y#^?^xB`8{$DJ)xY5(++c4cMl{A%N8wK{Elu5megS#3k* zE&8o8+I0QbRachkKgh=F#dLA{m05%JB09FAZr0+O1vS!GSPZ8cv+x<$94<{SnS4=1 z?`>RjptoQ8IODRux^i*Cv)-~Ax6FR2ta85TyQY4MYJz9ej#gHw9>(xYGg@l&@TTW_ zj)Ip4-0;C^>T~NBN|?A)rDQ~+c&Iu!RvLb(N>Y5j_Fuv7sbA{%h6{`P++Tiyab4Bd zy^p7_bCGrFm-_laeFe=c=YRYCb#uSO=k^Qqao2K#vo6%H&GFat*%i|`%KgeE43ii# z9QXG>f$7SPpP-`>@)$Z+KYqf_`m!9`R}4`&YGc=48?z@sl4kS@reQsfN0w zTk0qGO9r}c=uN3K0sDS$|{vj{XC?(d|}H4i?an$>^Z(pCMO5 z(?rN1pzmKr1wQ0%S>4q#jOu&WLd&l1me$i9R4=ZXtA-;S8!CUxSB@?6ct%~g#52Y- z>f8&K@Vh?4l0j#ndJ~W8Wvg-GQ2S~NcgI)p&jn)(s+7k%dQTet((9&LW)xjM)q;qE zde5i{>c0&7+y!-umw8lypl7Kv9hTJdThc3is0_gB5xp=m4DxvDZ>(HM-I=qDaVR~d zXP(g~)yJdoqrn7!RR$qVUm|4g1u_n`Oc^kQc%H|AOh4^jA~jF7r;DzwL{)tpQqMS! z1TR}qx1|0Oe0e;T4W!pHaa5JXGrE?s@Xgg{Tf8z+;Pzm7r4=_ZzG9q1v6q2p;+`rPy8Bt9 z>d!J|nIl^4cFVGfh?Y@LO+CZE2C=0+MAU~c6FqY(tCAe&)-0a8#9z5M;pCZnV#AGAKC|jcU`4u%XI%}wAJnhNL!;WLa4{fq%4o%oiXX`!(@K@!jLzf$|61u2Bm0XM7^>jE!zyZR=<%=B*@%>A5A3gNy zq5J$Yd3w41YJaL;oj6@_{ml9%UcW5fL~SyJVp()f6yClCn^s2dCY5yjGwzkTA!SYq zq|Akuc~nWPn@7cXdc$OR2lML=& zq~AAb%KLxC{^>L0G2Q!GEpa6;tPS)hJ9Xr5VXHpQc;-o+ztNqK`}aY^rNHpN-0&}7 z(UQOZ?yGd?j{Noa-=sSqr;q7w+>YZR<5zzBi;XWi*q<*dYOy^@KaDV&+?oXV+{mB!!KXn54&x;kCX4HY_HI)VGk zCvgAc3EZ0v_aTP-0z>{QCvbn&aG&MX$L-sVd5UbYlfVA%uPayDhXZ=~^z7F8hT(2` zR&W1?JfhQd?#~7H`IOU(HvP_0DP&_Z^1&ts{-S3<_}5BY_fdHj8dNnn?5g{WDdqE=^E>+7vEf6<*BJ+bjMN= zgKo3ex~gp2xf49~tP54M;>@xeE5K^)*24m@haOZPLJV+YF@rLeZ|dird&%4-i!16E zdPZFAnQ@iRCo_i9`m4+})6p^*s9=%vY-RzBoohWsGM9}n1DHLjy6Ks3E*d4rC}VOD z>07`ko9QltRnnwlC%I-y7=kWlWsuPqw<|reAZ04Aj8ZqZfl)O}l1vTa39e@>U#-U0 zGRs&hHmX&j<~Dd1$Qql4#WX*Q?<|=04{Lg@ozDo8cv)DJzxs18kwwR98JEl4Y4)`< zrc{(noiX*wqOzG+R?IFdDw|qS^xdM;veFqP6<1CzyXwjroNQiRTqP03$4QurJfkBVKcZ~XBx|`SkztPgq z9{tn*RrWFOFW;!!dD4cyY&5P%8nis$w>?rTL2B{4Vjk-p7UuuDQ@rX>+3K0ASEx01 zJyVnZ9oWCDUn`;NDbeWK3p}G#Jy=-5gPOCYEEiZtjTw7RwPn=Ub9hqa@p|SgnWrX4 zmJ#tKgwlFez~)z1(Hf1elGXpSc|rj2y}04rOJv$&1W`Yk+({BfFFZT`fXXA!c|2w# zWMRd!UJ9wyKx*$osyHk0v|rRqgpOwFHm9QD?DIWduV+SCS;gfuiz|FHOD?FmyyzMu z%?mu2T>NDoOK0dF&31$ZXnC%}OuLRz{ydMqFrUdOaGJY5At`?(DSkEUC{dM*xE;|S^9NJ`aR#e`bh88yV01?7{C^PtmW>yR2rxZLfZqZ9PrD{_#_PzIDy9Z7*0y=+|FdRr)~g z7k{d-j?}Lo9QxZ2vL9S_vh^(e`YiX2zgd}A-eMi2Uw`wNm$HBGV(E?6vHJD%*H$k1 z?C?a7)mT${p=I?QKRSENHtTr({{1(WE~qNoyU;p8zaISZ#F3}HKk6*&Mf&ySo6lKr zw9&iMTBu*ona9JDiiLGcE0)xVOKn3##k_e96_g!WJh5Defe+v=dkh;91r`!Csjf7!%- z;w_K8`tZ0RkKTRi(bU`iaqi7ejM($|)oJJ5(q;SYtV@14d*zC=p8C-D&o7464ta6d zCByzOZ2X!3v!u?Ql{4(L_dfgkZ+`NRZP_!cU-ka2v@&biuyd}Q>Dl(J{_^$mwNp;+ z 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 MwJ4JJfG$A)58M@=d;kCd diff --git a/addons/qjs-dtb/install.sh b/addons/qjs-dtb/install.sh deleted file mode 100644 index 5605f5f2..00000000 --- a/addons/qjs-dtb/install.sh +++ /dev/null @@ -1,27 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Jumkey's qjs-dtb arpl version - ramdisk time" - # fix executable flag - chmod +x /usr/sbin/dtc - chmod +x /usr/sbin/qjs - - # copy file - if [ ! -f model_${PLATFORM_ID%%_*}.dtb ]; then - # Dynamic generation - dtc -I dtb -O dts -o output.dts /etc.defaults/model.dtb - qjs --std /addons/dts.js output.dts output.dts.out - if [ $? -ne 0 ]; then - echo "auto generated dts file is broken" - else - dtc -I dts -O dtb -o model_r2.dtb output.dts.out - cp -vf model_r2.dtb /etc.defaults/model.dtb - cp -vf model_r2.dtb /var/run/model.dtb - fi - else - cp -vf model_${PLATFORM_ID%%_*}.dtb /etc.defaults/model.dtb - cp -vf model_${PLATFORM_ID%%_*}.dtb /var/run/model.dtb - fi -else - echo "Jumkey's qjs-dtb arpl version - sys time" - # copy file - cp -vf /etc.defaults/model.dtb /tmpRoot/etc.defaults/model.dtb -fi diff --git a/addons/qjs-dtb/manifest.yml b/addons/qjs-dtb/manifest.yml deleted file mode 100644 index 7fc1726b..00000000 --- a/addons/qjs-dtb/manifest.yml +++ /dev/null @@ -1,16 +0,0 @@ -version: 1 -name: qjs-dtb -system: true -description: "Jumkey's script to change model.dtb dynamically" -all: - install-script: "install.sh" - copy: "all" -available-for: - bromolow-3.10.108: - apollolake-4.4.180: - broadwell-4.4.180: - broadwellnk-4.4.180: - denverton-4.4.180: - geminilake-4.4.180: - v1000-4.4.180: - purley-4.4.180: diff --git a/addons/r8125/install.sh b/addons/r8125/install.sh deleted file mode 100644 index 98bfddff..00000000 --- a/addons/r8125/install.sh +++ /dev/null @@ -1,4 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Installing module for RealTek RTL8125 2.5Gigabit PCI-e Ethernet adapter" - ${INSMOD} "/modules/r8125.ko" ${PARAMS} -fi diff --git a/addons/r8125/manifest.yml b/addons/r8125/manifest.yml deleted file mode 100644 index 9a7074c3..00000000 --- a/addons/r8125/manifest.yml +++ /dev/null @@ -1,25 +0,0 @@ -version: 1 -name: r8125 -description: "Driver for RealTek RTL8125 2.5Gigabit PCI-e Ethernet adapter" -available-for: - apollolake-4.4.180: - install-script: &script "install.sh" - modules: true - broadwell-4.4.180: - install-script: *script - modules: true - broadwellnk-4.4.180: - install-script: *script - modules: true - denverton-4.4.180: - install-script: *script - modules: true - geminilake-4.4.180: - install-script: *script - modules: true - v1000-4.4.180: - install-script: *script - modules: true - purley-4.4.180: - install-script: *script - modules: true diff --git a/addons/r8125/src/4.4.180/Makefile b/addons/r8125/src/4.4.180/Makefile deleted file mode 100755 index d8c99bff..00000000 --- a/addons/r8125/src/4.4.180/Makefile +++ /dev/null @@ -1,88 +0,0 @@ -CONFIG_SOC_LAN = n -ENABLE_REALWOW_SUPPORT = n -ENABLE_DASH_SUPPORT = n -ENABLE_DASH_PRINTER_SUPPORT = n -CONFIG_DOWN_SPEED_100 = n -CONFIG_ASPM = y -ENABLE_S5WOL = y -ENABLE_S5_KEEP_CURR_MAC = n -ENABLE_EEE = y -ENABLE_S0_MAGIC_PACKET = n -ENABLE_TX_NO_CLOSE = y -ENABLE_MULTIPLE_TX_QUEUE = n -ENABLE_PTP_SUPPORT = n -ENABLE_PTP_MASTER_MODE = n -ENABLE_RSS_SUPPORT = n -ENABLE_LIB_SUPPORT = n -ENABLE_USE_FIRMWARE_FILE = n -DISABLE_PM_SUPPORT = n -DISABLE_MULTI_MSIX_VECTOR = n - -obj-m := r8125.o -r8125-objs := r8125_n.o rtl_eeprom.o rtltool.o -ifeq ($(CONFIG_SOC_LAN), y) - EXTRA_CFLAGS += -DCONFIG_SOC_LAN -endif -ifeq ($(ENABLE_REALWOW_SUPPORT), y) - r8125-objs += r8125_realwow.o - EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT -endif -ifeq ($(ENABLE_DASH_SUPPORT), y) - r8125-objs += r8125_dash.o - EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -endif -ifeq ($(ENABLE_DASH_PRINTER_SUPPORT), y) - r8125-objs += r8125_dash.o - EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT -endif -EXTRA_CFLAGS += -DCONFIG_R8125_NAPI -EXTRA_CFLAGS += -DCONFIG_R8125_VLAN -ifeq ($(CONFIG_DOWN_SPEED_100), y) - EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100 -endif -ifeq ($(CONFIG_ASPM), y) - EXTRA_CFLAGS += -DCONFIG_ASPM -endif -ifeq ($(ENABLE_S5WOL), y) - EXTRA_CFLAGS += -DENABLE_S5WOL -endif -ifeq ($(ENABLE_S5_KEEP_CURR_MAC), y) - EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC -endif -ifeq ($(ENABLE_EEE), y) - EXTRA_CFLAGS += -DENABLE_EEE -endif -ifeq ($(ENABLE_S0_MAGIC_PACKET), y) - EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET -endif -ifeq ($(ENABLE_TX_NO_CLOSE), y) - EXTRA_CFLAGS += -DENABLE_TX_NO_CLOSE -endif -ifeq ($(ENABLE_MULTIPLE_TX_QUEUE), y) - EXTRA_CFLAGS += -DENABLE_MULTIPLE_TX_QUEUE -endif -ifeq ($(ENABLE_PTP_SUPPORT), y) - r8125-objs += r8125_ptp.o - EXTRA_CFLAGS += -DENABLE_PTP_SUPPORT -endif -ifeq ($(ENABLE_PTP_MASTER_MODE), y) - EXTRA_CFLAGS += -DENABLE_PTP_MASTER_MODE -endif -ifeq ($(ENABLE_RSS_SUPPORT), y) - r8125-objs += r8125_rss.o - EXTRA_CFLAGS += -DENABLE_RSS_SUPPORT -endif -ifeq ($(ENABLE_LIB_SUPPORT), y) - r8125-objs += r8125_lib.o - EXTRA_CFLAGS += -DENABLE_LIB_SUPPORT -endif -ifeq ($(ENABLE_USE_FIRMWARE_FILE), y) - r8125-objs += r8125_firmware.o - EXTRA_CFLAGS += -DENABLE_USE_FIRMWARE_FILE -endif -ifeq ($(DISABLE_PM_SUPPORT), y) - EXTRA_CFLAGS += -DDISABLE_PM_SUPPORT -endif -ifeq ($(DISABLE_MULTI_MSIX_VECTOR), y) - EXTRA_CFLAGS += -DDISABLE_MULTI_MSIX_VECTOR -endif diff --git a/addons/r8125/src/4.4.180/r8125.h b/addons/r8125/src/4.4.180/r8125.h deleted file mode 100755 index d48ab769..00000000 --- a/addons/r8125/src/4.4.180/r8125.h +++ /dev/null @@ -1,2536 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef __R8125_H -#define __R8125_H - -//#include -#include -#include -#include -#include "r8125_dash.h" -#include "r8125_realwow.h" -#include "r8125_ptp.h" -#include "r8125_rss.h" -#ifdef ENABLE_LIB_SUPPORT -#include "r8125_lib.h" -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) -typedef int netdev_tx_t; -#endif - -/* -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0)&& !defined(ENABLE_LIB_SUPPORT) -#define RTL_USE_NEW_INTR_API -#endif -*/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -#define skb_transport_offset(skb) (skb->h.raw - skb->data) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) -#define device_set_wakeup_enable(dev, val) do {} while (0) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,14,0) -static inline void ether_addr_copy(u8 *dst, const u8 *src) -{ - u16 *a = (u16 *)dst; - const u16 *b = (const u16 *)src; - - a[0] = b[0]; - a[1] = b[1]; - a[2] = b[2]; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) -#define IS_ERR_OR_NULL(ptr) (!ptr) -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) -#define reinit_completion(x) ((x)->done = 0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) -#define pm_runtime_mark_last_busy(x) -#define pm_runtime_put_autosuspend(x) pm_runtime_put(x) -#define pm_runtime_put_sync_autosuspend(x) pm_runtime_put_sync(x) - -static inline bool pm_runtime_suspended(struct device *dev) -{ - return dev->power.runtime_status == RPM_SUSPENDED - && !dev->power.disable_depth; -} - -static inline bool pm_runtime_active(struct device *dev) -{ - return dev->power.runtime_status == RPM_ACTIVE - || dev->power.disable_depth; -} -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) -#define queue_delayed_work(long_wq, work, delay) schedule_delayed_work(work, delay) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) -#define netif_printk(priv, type, level, netdev, fmt, args...) \ - do { \ - if (netif_msg_##type(priv)) \ - printk(level "%s: " fmt,(netdev)->name , ##args); \ - } while (0) - -#define netif_emerg(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_EMERG, netdev, fmt, ##args) -#define netif_alert(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_ALERT, netdev, fmt, ##args) -#define netif_crit(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_CRIT, netdev, fmt, ##args) -#define netif_err(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_ERR, netdev, fmt, ##args) -#define netif_warn(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_WARNING, netdev, fmt, ##args) -#define netif_notice(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_NOTICE, netdev, fmt, ##args) -#define netif_info(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_INFO, (netdev), fmt, ##args) -#endif -#endif -#endif -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) -#define setup_timer(_timer, _function, _data) \ -do { \ - (_timer)->function = _function; \ - (_timer)->data = _data; \ - init_timer(_timer); \ -} while (0) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) -#if defined(skb_vlan_tag_present) && !defined(vlan_tx_tag_present) -#define vlan_tx_tag_present skb_vlan_tag_present -#endif -#if defined(skb_vlan_tag_get) && !defined(vlan_tx_tag_get) -#define vlan_tx_tag_get skb_vlan_tag_get -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) - -#define RTL_ALLOC_SKB_INTR(napi, length) dev_alloc_skb(length) -#ifdef CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) -#undef RTL_ALLOC_SKB_INTR -#define RTL_ALLOC_SKB_INTR(napi, length) napi_alloc_skb(napi, length) -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) -#define eth_random_addr(addr) random_ether_addr(addr) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,6,0) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) -#define netdev_features_t u32 -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) -#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK -#else -#ifndef NETIF_F_ALL_CSUM -#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) -#define ENABLE_R8125_PROCFS -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -#define NETIF_F_HW_VLAN_RX NETIF_F_HW_VLAN_CTAG_RX -#define NETIF_F_HW_VLAN_TX NETIF_F_HW_VLAN_CTAG_TX -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) -#define __devinit -#define __devexit -#define __devexit_p(func) func -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -#define CHECKSUM_PARTIAL CHECKSUM_HW -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define irqreturn_t void -#define IRQ_HANDLED 1 -#define IRQ_NONE 0 -#define IRQ_RETVAL(x) -#endif - -#ifndef NETIF_F_RXALL -#define NETIF_F_RXALL 0 -#endif - -#ifndef NETIF_F_RXFCS -#define NETIF_F_RXFCS 0 -#endif - -#ifndef HAVE_FREE_NETDEV -#define free_netdev(x) kfree(x) -#endif - -#ifndef SET_NETDEV_DEV -#define SET_NETDEV_DEV(net, pdev) -#endif - -#ifndef SET_MODULE_OWNER -#define SET_MODULE_OWNER(dev) -#endif - -#ifndef SA_SHIRQ -#define SA_SHIRQ IRQF_SHARED -#endif - -#ifndef NETIF_F_GSO -#define gso_size tso_size -#define gso_segs tso_segs -#endif - -#ifndef PCI_VENDOR_ID_DLINK -#define PCI_VENDOR_ID_DLINK 0x1186 -#endif - -#ifndef dma_mapping_error -#define dma_mapping_error(a,b) 0 -#endif - -#ifndef netif_err -#define netif_err(a,b,c,d) -#endif - -#ifndef AUTONEG_DISABLE -#define AUTONEG_DISABLE 0x00 -#endif - -#ifndef AUTONEG_ENABLE -#define AUTONEG_ENABLE 0x01 -#endif - -#ifndef BMCR_SPEED1000 -#define BMCR_SPEED1000 0x0040 -#endif - -#ifndef BMCR_SPEED100 -#define BMCR_SPEED100 0x2000 -#endif - -#ifndef BMCR_SPEED10 -#define BMCR_SPEED10 0x0000 -#endif - -#ifndef SPEED_UNKNOWN -#define SPEED_UNKNOWN -1 -#endif - -#ifndef DUPLEX_UNKNOWN -#define DUPLEX_UNKNOWN 0xff -#endif - -#ifndef SUPPORTED_Pause -#define SUPPORTED_Pause (1 << 13) -#endif - -#ifndef SUPPORTED_Asym_Pause -#define SUPPORTED_Asym_Pause (1 << 14) -#endif - -#ifndef MDIO_EEE_100TX -#define MDIO_EEE_100TX 0x0002 -#endif - -#ifndef MDIO_EEE_1000T -#define MDIO_EEE_1000T 0x0004 -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -#ifdef CONFIG_NET_POLL_CONTROLLER -#define RTL_NET_POLL_CONTROLLER dev->poll_controller=rtl8125_netpoll -#else -#define RTL_NET_POLL_CONTROLLER -#endif - -#ifdef CONFIG_R8125_VLAN -#define RTL_SET_VLAN dev->vlan_rx_register=rtl8125_vlan_rx_register -#else -#define RTL_SET_VLAN -#endif - -#define RTL_NET_DEVICE_OPS(ops) dev->open=rtl8125_open; \ - dev->hard_start_xmit=rtl8125_start_xmit; \ - dev->get_stats=rtl8125_get_stats; \ - dev->stop=rtl8125_close; \ - dev->tx_timeout=rtl8125_tx_timeout; \ - dev->set_multicast_list=rtl8125_set_rx_mode; \ - dev->change_mtu=rtl8125_change_mtu; \ - dev->set_mac_address=rtl8125_set_mac_address; \ - dev->do_ioctl=rtl8125_do_ioctl; \ - RTL_NET_POLL_CONTROLLER; \ - RTL_SET_VLAN; -#else -#define RTL_NET_DEVICE_OPS(ops) dev->netdev_ops=&ops -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef false -#define false 0 -#endif - -#ifndef true -#define true 1 -#endif - -//Hardware will continue interrupt 10 times after interrupt finished. -#define RTK_KEEP_INTERRUPT_COUNT (10) - -//the low 32 bit address of receive buffer must be 8-byte alignment. -#ifndef NET_IP_ALIGN -#define NET_IP_ALIGN 2 -#endif -#define RTK_RX_ALIGN 8 - -#ifdef CONFIG_R8125_NAPI -#define NAPI_SUFFIX "-NAPI" -#else -#define NAPI_SUFFIX "" -#endif -#if defined(ENABLE_DASH_PRINTER_SUPPORT) -#define DASH_SUFFIX "-PRINTER" -#elif defined(ENABLE_DASH_SUPPORT) -#define DASH_SUFFIX "-DASH" -#else -#define DASH_SUFFIX "" -#endif - -#if defined(ENABLE_REALWOW_SUPPORT) -#define REALWOW_SUFFIX "-REALWOW" -#else -#define REALWOW_SUFFIX "" -#endif - -#if defined(ENABLE_PTP_SUPPORT) -#define PTP_SUFFIX "-PTP" -#else -#define PTP_SUFFIX "" -#endif - -#if defined(ENABLE_RSS_SUPPORT) -#define RSS_SUFFIX "-RSS" -#else -#define RSS_SUFFIX "" -#endif - -#define RTL8125_VERSION "9.009.01" NAPI_SUFFIX DASH_SUFFIX REALWOW_SUFFIX PTP_SUFFIX RSS_SUFFIX -#define MODULENAME "r8125" -#define PFX MODULENAME ": " - -#define GPL_CLAIM "\ -r8125 Copyright (C) 2022 Realtek NIC software team \n \ -This program comes with ABSOLUTELY NO WARRANTY; for details, please see . \n \ -This is free software, and you are welcome to redistribute it under certain conditions; see . \n" - -#ifdef RTL8125_DEBUG -#define assert(expr) \ - if(!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8125_DEBUG */ - -#define R8125_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#ifdef CONFIG_R8125_NAPI -#define rtl8125_rx_hwaccel_skb vlan_hwaccel_receive_skb -#define rtl8125_rx_quota(count, quota) min(count, quota) -#else -#define rtl8125_rx_hwaccel_skb vlan_hwaccel_rx -#define rtl8125_rx_quota(count, quota) count -#endif - -/* MAC address length */ -#ifndef MAC_ADDR_LEN -#define MAC_ADDR_LEN 6 -#endif - -#ifndef MAC_PROTOCOL_LEN -#define MAC_PROTOCOL_LEN 2 -#endif - -#ifndef ETH_FCS_LEN -#define ETH_FCS_LEN 4 -#endif - -#ifndef NETIF_F_TSO6 -#define NETIF_F_TSO6 0 -#endif - -#define Reserved2_data 7 -#define RX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */ -#define TX_DMA_BURST_unlimited 7 -#define TX_DMA_BURST_1024 6 -#define TX_DMA_BURST_512 5 -#define TX_DMA_BURST_256 4 -#define TX_DMA_BURST_128 3 -#define TX_DMA_BURST_64 2 -#define TX_DMA_BURST_32 1 -#define TX_DMA_BURST_16 0 -#define Reserved1_data 0x3F -#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ -#define Jumbo_Frame_1k ETH_DATA_LEN -#define Jumbo_Frame_2k (2*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_3k (3*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_4k (4*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_5k (5*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_6k (6*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_7k (7*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_8k (8*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_9k (9*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ -#define RxEarly_off_V1 (0x07 << 11) -#define RxEarly_off_V2 (1 << 11) -#define Rx_Single_fetch_V2 (1 << 14) - -#define R8125_REGS_SIZE (256) -#define R8125_MAC_REGS_SIZE (256) -#define R8125_PHY_REGS_SIZE (16*2) -#define R8125_EPHY_REGS_SIZE (31*2) -#define R8125_ERI_REGS_SIZE (0x100) -#define R8125_REGS_DUMP_SIZE (0x400) -#define R8125_PCI_REGS_SIZE (0x100) -#define R8125_NAPI_WEIGHT 64 - -#define R8125_MAX_MSIX_VEC_8125B 32 -#define R8125_MIN_MSIX_VEC_8125B 17 -#define R8125_MAX_MSIX_VEC 32 -#define R8125_MAX_RX_QUEUES_VEC_V3 (16) - -#define RTL8125_TX_TIMEOUT (6 * HZ) -#define RTL8125_LINK_TIMEOUT (1 * HZ) -#define RTL8125_ESD_TIMEOUT (2 * HZ) - -#define MAX_NUM_TX_DESC 1024 /* Maximum number of Tx descriptor registers */ -#define MAX_NUM_RX_DESC 1024 /* Maximum number of Rx descriptor registers */ - -#define MIN_NUM_TX_DESC 256 /* Minimum number of Tx descriptor registers */ -#define MIN_NUM_RX_DESC 256 /* Minimum number of Rx descriptor registers */ - -#define NUM_TX_DESC MAX_NUM_TX_DESC /* Number of Tx descriptor registers */ -#define NUM_RX_DESC MAX_NUM_RX_DESC /* Number of Rx descriptor registers */ - -#define RX_BUF_SIZE 0x05F3 /* 0x05F3 = 1522bye + 1 */ - -#define R8125_MAX_TX_QUEUES (2) -#define R8125_MAX_RX_QUEUES (4) -#define R8125_MAX_QUEUES R8125_MAX_RX_QUEUES - -#define OCP_STD_PHY_BASE 0xa400 - -#ifdef ENABLE_LIB_SUPPORT -#define R8125_MULTI_RX_Q(tp) 0 -#else -#define R8125_MULTI_RX_Q(tp) (tp->num_rx_rings > 1) -#endif - -#define NODE_ADDRESS_SIZE 6 - -#define SHORT_PACKET_PADDING_BUF_SIZE 256 - -#define RTK_MAGIC_DEBUG_VALUE 0x0badbeef - -/* write/read MMIO register */ -#define RTL_W8(tp, reg, val8) writeb((val8), tp->mmio_addr + (reg)) -#define RTL_W16(tp, reg, val16) writew((val16), tp->mmio_addr + (reg)) -#define RTL_W32(tp, reg, val32) writel((val32), tp->mmio_addr + (reg)) -#define RTL_R8(tp, reg) readb(tp->mmio_addr + (reg)) -#define RTL_R16(tp, reg) readw(tp->mmio_addr + (reg)) -#define RTL_R32(tp, reg) ((unsigned long) readl(tp->mmio_addr + (reg))) - -#ifndef DMA_64BIT_MASK -#define DMA_64BIT_MASK 0xffffffffffffffffULL -#endif - -#ifndef DMA_32BIT_MASK -#define DMA_32BIT_MASK 0x00000000ffffffffULL -#endif - -#ifndef NETDEV_TX_OK -#define NETDEV_TX_OK 0 /* driver took care of packet */ -#endif - -#ifndef NETDEV_TX_BUSY -#define NETDEV_TX_BUSY 1 /* driver tx path was busy*/ -#endif - -#ifndef NETDEV_TX_LOCKED -#define NETDEV_TX_LOCKED -1t /* driver tx lock was already taken */ -#endif - -#ifndef ADVERTISED_Pause -#define ADVERTISED_Pause (1 << 13) -#endif - -#ifndef ADVERTISED_Asym_Pause -#define ADVERTISED_Asym_Pause (1 << 14) -#endif - -#ifndef ADVERTISE_PAUSE_CAP -#define ADVERTISE_PAUSE_CAP 0x400 -#endif - -#ifndef ADVERTISE_PAUSE_ASYM -#define ADVERTISE_PAUSE_ASYM 0x800 -#endif - -#ifndef MII_CTRL1000 -#define MII_CTRL1000 0x09 -#endif - -#ifndef ADVERTISE_1000FULL -#define ADVERTISE_1000FULL 0x200 -#endif - -#ifndef ADVERTISE_1000HALF -#define ADVERTISE_1000HALF 0x100 -#endif - -#ifndef ADVERTISED_2500baseX_Full -#define ADVERTISED_2500baseX_Full 0x8000 -#endif - -#define RTK_ADVERTISE_2500FULL 0x80 -#define RTK_LPA_ADVERTISE_2500FULL 0x20 -#define RTK_LPA_ADVERTISE_5000FULL 0x40 -#define RTK_LPA_ADVERTISE_10000FULL 0x800 - -#define RTK_EEE_ADVERTISE_2500FULL 0x01 -#define RTK_LPA_EEE_ADVERTISE_2500FULL 0x01 - -/* Tx NO CLOSE */ -#define MAX_TX_NO_CLOSE_DESC_PTR_V2 0x10000 -#define TX_NO_CLOSE_SW_PTR_MASK_V2 0x1FFFF - -#ifndef ETH_MIN_MTU -#define ETH_MIN_MTU 68 -#endif - -#define D0_SPEED_UP_SPEED_DISABLE 0 -#define D0_SPEED_UP_SPEED_1000 1 -#define D0_SPEED_UP_SPEED_2500 2 - -#define RTL8125_MAC_MCU_PAGE_SIZE 256 //256 words - -#ifndef WRITE_ONCE -#define WRITE_ONCE(var, val) (*((volatile typeof(val) *)(&(var))) = (val)) -#endif -#ifndef READ_ONCE -#define READ_ONCE(var) (*((volatile typeof(var) *)(&(var)))) -#endif - -/*****************************************************************************/ - -//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) -#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ - (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ - ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) -/* copied from linux kernel 2.6.20 include/linux/netdev.h */ -#define NETDEV_ALIGN 32 -#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1) - -static inline void *netdev_priv(struct net_device *dev) -{ - return (char *)dev + ((sizeof(struct net_device) - + NETDEV_ALIGN_CONST) - & ~NETDEV_ALIGN_CONST); -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -#define RTLDEV tp -#else -#define RTLDEV dev -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -/*****************************************************************************/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) -typedef struct net_device *napi_ptr; -typedef int *napi_budget; - -#define napi dev -#define RTL_NAPI_CONFIG(ndev, priv, function, weig) ndev->poll=function; \ - ndev->weight=weig; -#define RTL_NAPI_QUOTA(budget, ndev) min(*budget, ndev->quota) -#define RTL_GET_PRIV(stuct_ptr, priv_struct) netdev_priv(stuct_ptr) -#define RTL_GET_NETDEV(priv_ptr) -#define RTL_RX_QUOTA(budget) *budget -#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) *budget -= work_done; \ - ndev->quota -= work_done; -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev) -#define RTL_NAPI_RETURN_VALUE work_done >= work_to_do -#define RTL_NAPI_ENABLE(dev, napi) netif_poll_enable(dev) -#define RTL_NAPI_DISABLE(dev, napi) netif_poll_disable(dev) -#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) -#else -typedef struct napi_struct *napi_ptr; -typedef int napi_budget; - -#define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) -#define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) -#define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) -#define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; -#define RTL_RX_QUOTA(budget) budget -#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev, napi) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev, napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev, napi) -#endif -#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,29) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(napi) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(napi) -#endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete_done(napi, work_done) -#else -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete(napi) -#endif -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) napi_schedule_prep(napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __napi_schedule(napi) -#endif -#define RTL_NAPI_RETURN_VALUE work_done -#define RTL_NAPI_ENABLE(dev, napi) napi_enable(napi) -#define RTL_NAPI_DISABLE(dev, napi) napi_disable(napi) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) -#define RTL_NAPI_DEL(priv) -#else -#define RTL_NAPI_DEL(priv) netif_napi_del(&priv->napi) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) - -/*****************************************************************************/ -#ifdef CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) napi_consume_skb(skb, budget) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_consume_skb_any(skb); -#else -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_kfree_skb_any(skb); -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,0) -#else //CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_consume_skb_any(skb); -#else -#define RTL_NAPI_CONSUME_SKB_ANY(skb, budget) dev_kfree_skb_any(skb); -#endif -#endif //CONFIG_R8125_NAPI - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -#ifdef __CHECKER__ -#define __iomem __attribute__((noderef, address_space(2))) -extern void __chk_io_ptr(void __iomem *); -#define __bitwise __attribute__((bitwise)) -#else -#define __iomem -#define __chk_io_ptr(x) (void)0 -#define __bitwise -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) -#ifdef __CHECKER__ -#define __force __attribute__((force)) -#else -#define __force -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) - -#ifndef module_param -#define module_param(v,t,p) MODULE_PARM(v, "i"); -#endif - -#ifndef PCI_DEVICE -#define PCI_DEVICE(vend,dev) \ - .vendor = (vend), .device = (dev), \ - .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID -#endif - -/*****************************************************************************/ -/* 2.5.28 => 2.4.23 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) - -static inline void _kc_synchronize_irq(void) -{ - synchronize_irq(); -} -#undef synchronize_irq -#define synchronize_irq(X) _kc_synchronize_irq() - -#include -#define work_struct tq_struct -#undef INIT_WORK -#define INIT_WORK(a,b,c) INIT_TQUEUE(a,(void (*)(void *))b,c) -#undef container_of -#define container_of list_entry -#define schedule_work schedule_task -#define flush_scheduled_work flush_scheduled_tasks -#endif /* 2.5.28 => 2.4.17 */ - -/*****************************************************************************/ -/* 2.6.4 => 2.6.0 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) -#define MODULE_VERSION(_version) MODULE_INFO(version, _version) -#endif /* 2.6.4 => 2.6.0 */ -/*****************************************************************************/ -/* 2.6.0 => 2.5.28 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) -#define MODULE_INFO(version, _version) -#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT -#define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 -#endif - -#define pci_set_consistent_dma_mask(dev,mask) 1 - -#undef dev_put -#define dev_put(dev) __dev_put(dev) - -#ifndef skb_fill_page_desc -#define skb_fill_page_desc _kc_skb_fill_page_desc -extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); -#endif - -#ifndef pci_dma_mapping_error -#define pci_dma_mapping_error _kc_pci_dma_mapping_error -static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr) -{ - return dma_addr == 0; -} -#endif - -#undef ALIGN -#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) - -#endif /* 2.6.0 => 2.5.28 */ - -/*****************************************************************************/ -/* 2.4.22 => 2.4.17 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) -#define pci_name(x) ((x)->slot_name) -#endif /* 2.4.22 => 2.4.17 */ - -/*****************************************************************************/ -/* 2.6.5 => 2.6.0 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) -#define pci_dma_sync_single_for_cpu pci_dma_sync_single -#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu -#endif /* 2.6.5 => 2.6.0 */ - -/*****************************************************************************/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -/* - * initialize a work-struct's func and data pointers: - */ -#define PREPARE_WORK(_work, _func, _data) \ - do { \ - (_work)->func = _func; \ - (_work)->data = _data; \ - } while (0) - -#endif -/*****************************************************************************/ -/* 2.6.4 => 2.6.0 */ -#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) && \ - LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22)) || \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4))) -#define ETHTOOL_OPS_COMPAT -#endif /* 2.6.4 => 2.6.0 */ - -/*****************************************************************************/ -/* Installations with ethtool version without eeprom, adapter id, or statistics - * support */ - -#ifndef ETH_GSTRING_LEN -#define ETH_GSTRING_LEN 32 -#endif - -#ifndef ETHTOOL_GSTATS -#define ETHTOOL_GSTATS 0x1d -#undef ethtool_drvinfo -#define ethtool_drvinfo k_ethtool_drvinfo -struct k_ethtool_drvinfo { - u32 cmd; - char driver[32]; - char version[32]; - char fw_version[32]; - char bus_info[32]; - char reserved1[32]; - char reserved2[16]; - u32 n_stats; - u32 testinfo_len; - u32 eedump_len; - u32 regdump_len; -}; - -struct ethtool_stats { - u32 cmd; - u32 n_stats; - u64 data[0]; -}; -#endif /* ETHTOOL_GSTATS */ - -#ifndef ETHTOOL_PHYS_ID -#define ETHTOOL_PHYS_ID 0x1c -#endif /* ETHTOOL_PHYS_ID */ - -#ifndef ETHTOOL_GSTRINGS -#define ETHTOOL_GSTRINGS 0x1b -enum ethtool_stringset { - ETH_SS_TEST = 0, - ETH_SS_STATS, -}; -struct ethtool_gstrings { - u32 cmd; /* ETHTOOL_GSTRINGS */ - u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ - u32 len; /* number of strings in the string set */ - u8 data[0]; -}; -#endif /* ETHTOOL_GSTRINGS */ - -#ifndef ETHTOOL_TEST -#define ETHTOOL_TEST 0x1a -enum ethtool_test_flags { - ETH_TEST_FL_OFFLINE = (1 << 0), - ETH_TEST_FL_FAILED = (1 << 1), -}; -struct ethtool_test { - u32 cmd; - u32 flags; - u32 reserved; - u32 len; - u64 data[0]; -}; -#endif /* ETHTOOL_TEST */ - -#ifndef ETHTOOL_GEEPROM -#define ETHTOOL_GEEPROM 0xb -#undef ETHTOOL_GREGS -struct ethtool_eeprom { - u32 cmd; - u32 magic; - u32 offset; - u32 len; - u8 data[0]; -}; - -struct ethtool_value { - u32 cmd; - u32 data; -}; -#endif /* ETHTOOL_GEEPROM */ - -#ifndef ETHTOOL_GLINK -#define ETHTOOL_GLINK 0xa -#endif /* ETHTOOL_GLINK */ - -#ifndef ETHTOOL_GREGS -#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ -#define ethtool_regs _kc_ethtool_regs -/* for passing big chunks of data */ -struct _kc_ethtool_regs { - u32 cmd; - u32 version; /* driver-specific, indicates different chips/revs */ - u32 len; /* bytes */ - u8 data[0]; -}; -#endif /* ETHTOOL_GREGS */ - -#ifndef ETHTOOL_GMSGLVL -#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ -#endif -#ifndef ETHTOOL_SMSGLVL -#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ -#endif -#ifndef ETHTOOL_NWAY_RST -#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ -#endif -#ifndef ETHTOOL_GLINK -#define ETHTOOL_GLINK 0x0000000a /* Get link status */ -#endif -#ifndef ETHTOOL_GEEPROM -#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ -#endif -#ifndef ETHTOOL_SEEPROM -#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ -#endif -#ifndef ETHTOOL_GCOALESCE -#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ -/* for configuring coalescing parameters of chip */ -#define ethtool_coalesce _kc_ethtool_coalesce -struct _kc_ethtool_coalesce { - u32 cmd; /* ETHTOOL_{G,S}COALESCE */ - - /* How many usecs to delay an RX interrupt after - * a packet arrives. If 0, only rx_max_coalesced_frames - * is used. - */ - u32 rx_coalesce_usecs; - - /* How many packets to delay an RX interrupt after - * a packet arrives. If 0, only rx_coalesce_usecs is - * used. It is illegal to set both usecs and max frames - * to zero as this would cause RX interrupts to never be - * generated. - */ - u32 rx_max_coalesced_frames; - - /* Same as above two parameters, except that these values - * apply while an IRQ is being serviced by the host. Not - * all cards support this feature and the values are ignored - * in that case. - */ - u32 rx_coalesce_usecs_irq; - u32 rx_max_coalesced_frames_irq; - - /* How many usecs to delay a TX interrupt after - * a packet is sent. If 0, only tx_max_coalesced_frames - * is used. - */ - u32 tx_coalesce_usecs; - - /* How many packets to delay a TX interrupt after - * a packet is sent. If 0, only tx_coalesce_usecs is - * used. It is illegal to set both usecs and max frames - * to zero as this would cause TX interrupts to never be - * generated. - */ - u32 tx_max_coalesced_frames; - - /* Same as above two parameters, except that these values - * apply while an IRQ is being serviced by the host. Not - * all cards support this feature and the values are ignored - * in that case. - */ - u32 tx_coalesce_usecs_irq; - u32 tx_max_coalesced_frames_irq; - - /* How many usecs to delay in-memory statistics - * block updates. Some drivers do not have an in-memory - * statistic block, and in such cases this value is ignored. - * This value must not be zero. - */ - u32 stats_block_coalesce_usecs; - - /* Adaptive RX/TX coalescing is an algorithm implemented by - * some drivers to improve latency under low packet rates and - * improve throughput under high packet rates. Some drivers - * only implement one of RX or TX adaptive coalescing. Anything - * not implemented by the driver causes these values to be - * silently ignored. - */ - u32 use_adaptive_rx_coalesce; - u32 use_adaptive_tx_coalesce; - - /* When the packet rate (measured in packets per second) - * is below pkt_rate_low, the {rx,tx}_*_low parameters are - * used. - */ - u32 pkt_rate_low; - u32 rx_coalesce_usecs_low; - u32 rx_max_coalesced_frames_low; - u32 tx_coalesce_usecs_low; - u32 tx_max_coalesced_frames_low; - - /* When the packet rate is below pkt_rate_high but above - * pkt_rate_low (both measured in packets per second) the - * normal {rx,tx}_* coalescing parameters are used. - */ - - /* When the packet rate is (measured in packets per second) - * is above pkt_rate_high, the {rx,tx}_*_high parameters are - * used. - */ - u32 pkt_rate_high; - u32 rx_coalesce_usecs_high; - u32 rx_max_coalesced_frames_high; - u32 tx_coalesce_usecs_high; - u32 tx_max_coalesced_frames_high; - - /* How often to do adaptive coalescing packet rate sampling, - * measured in seconds. Must not be zero. - */ - u32 rate_sample_interval; -}; -#endif /* ETHTOOL_GCOALESCE */ - -#ifndef ETHTOOL_SCOALESCE -#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ -#endif -#ifndef ETHTOOL_GRINGPARAM -#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ -/* for configuring RX/TX ring parameters */ -#define ethtool_ringparam _kc_ethtool_ringparam -struct _kc_ethtool_ringparam { - u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ - - /* Read only attributes. These indicate the maximum number - * of pending RX/TX ring entries the driver will allow the - * user to set. - */ - u32 rx_max_pending; - u32 rx_mini_max_pending; - u32 rx_jumbo_max_pending; - u32 tx_max_pending; - - /* Values changeable by the user. The valid values are - * in the range 1 to the "*_max_pending" counterpart above. - */ - u32 rx_pending; - u32 rx_mini_pending; - u32 rx_jumbo_pending; - u32 tx_pending; -}; -#endif /* ETHTOOL_GRINGPARAM */ - -#ifndef ETHTOOL_SRINGPARAM -#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ -#endif -#ifndef ETHTOOL_GPAUSEPARAM -#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ -/* for configuring link flow control parameters */ -#define ethtool_pauseparam _kc_ethtool_pauseparam -struct _kc_ethtool_pauseparam { - u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ - - /* If the link is being auto-negotiated (via ethtool_cmd.autoneg - * being true) the user may set 'autonet' here non-zero to have the - * pause parameters be auto-negotiated too. In such a case, the - * {rx,tx}_pause values below determine what capabilities are - * advertised. - * - * If 'autoneg' is zero or the link is not being auto-negotiated, - * then {rx,tx}_pause force the driver to use/not-use pause - * flow control. - */ - u32 autoneg; - u32 rx_pause; - u32 tx_pause; -}; -#endif /* ETHTOOL_GPAUSEPARAM */ - -#ifndef ETHTOOL_SPAUSEPARAM -#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ -#endif -#ifndef ETHTOOL_GRXCSUM -#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_SRXCSUM -#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_GTXCSUM -#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_STXCSUM -#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_GSG -#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable -* (ethtool_value) */ -#endif -#ifndef ETHTOOL_SSG -#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable -* (ethtool_value). */ -#endif -#ifndef ETHTOOL_TEST -#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ -#endif -#ifndef ETHTOOL_GSTRINGS -#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ -#endif -#ifndef ETHTOOL_PHYS_ID -#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ -#endif -#ifndef ETHTOOL_GSTATS -#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ -#endif -#ifndef ETHTOOL_GTSO -#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_STSO -#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ -#endif - -#ifndef ETHTOOL_BUSINFO_LEN -#define ETHTOOL_BUSINFO_LEN 32 -#endif - -/*****************************************************************************/ - -enum RTL8125_registers { - MAC0 = 0x00, /* Ethernet hardware address. */ - MAC4 = 0x04, - MAR0 = 0x08, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - CustomLED = 0x18, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - INT_CFG0_8125 = 0x34, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - TCTR = 0x48, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - TDFNR = 0x57, - TimeInt0 = 0x58, - TimeInt1 = 0x5C, - PHYAR = 0x60, - CSIDR = 0x64, - CSIAR = 0x68, - PHYstatus = 0x6C, - MACDBG = 0x6D, - GPIO = 0x6E, - PMCH = 0x6F, - ERIDR = 0x70, - ERIAR = 0x74, - INT_CFG1_8125 = 0x7A, - EPHY_RXER_NUM = 0x7C, - EPHYAR = 0x80, - TimeInt2 = 0x8C, - OCPDR = 0xB0, - MACOCP = 0xB0, - OCPAR = 0xB4, - SecMAC0 = 0xB4, - SecMAC4 = 0xB8, - PHYOCP = 0xB8, - DBG_reg = 0xD1, - TwiCmdReg = 0xD2, - MCUCmd_reg = 0xD3, - RxMaxSize = 0xDA, - EFUSEAR = 0xDC, - CPlusCmd = 0xE0, - IntrMitigate = 0xE2, - RxDescAddrLow = 0xE4, - RxDescAddrHigh = 0xE8, - MTPS = 0xEC, - FuncEvent = 0xF0, - PPSW = 0xF2, - FuncEventMask = 0xF4, - TimeInt3 = 0xF4, - FuncPresetState = 0xF8, - CMAC_IBCR0 = 0xF8, - CMAC_IBCR2 = 0xF9, - CMAC_IBIMR0 = 0xFA, - CMAC_IBISR0 = 0xFB, - FuncForceEvent = 0xFC, - //8125 - IMR0_8125 = 0x38, - ISR0_8125 = 0x3C, - TPPOLL_8125 = 0x90, - IMR1_8125 = 0x800, - ISR1_8125 = 0x802, - IMR2_8125 = 0x804, - ISR2_8125 = 0x806, - IMR3_8125 = 0x808, - ISR3_8125 = 0x80A, - BACKUP_ADDR0_8125 = 0x19E0, - BACKUP_ADDR1_8125 = 0X19E4, - TCTR0_8125 = 0x0048, - TCTR1_8125 = 0x004C, - TCTR2_8125 = 0x0088, - TCTR3_8125 = 0x001C, - TIMER_INT0_8125 = 0x0058, - TIMER_INT1_8125 = 0x005C, - TIMER_INT2_8125 = 0x008C, - TIMER_INT3_8125 = 0x00F4, - INT_MITI_V2_0_RX = 0x0A00, - INT_MITI_V2_0_TX = 0x0A02, - INT_MITI_V2_1_RX = 0x0A08, - INT_MITI_V2_1_TX = 0x0A0A, - IMR_V2_CLEAR_REG_8125 = 0x0D00, - ISR_V2_8125 = 0x0D04, - IMR_V2_SET_REG_8125 = 0x0D0C, - TDU_STA_8125 = 0x0D08, - RDU_STA_8125 = 0x0D0A, - TX_NEW_CTRL = 0x203E, - TNPDS_Q1_LOW_8125 = 0x2100, - PLA_TXQ0_IDLE_CREDIT = 0x2500, - PLA_TXQ1_IDLE_CREDIT = 0x2504, - SW_TAIL_PTR0_8125 = 0x2800, - HW_CLO_PTR0_8125 = 0x2802, - RDSAR_Q1_LOW_8125 = 0x4000, - RSS_CTRL_8125 = 0x4500, - Q_NUM_CTRL_8125 = 0x4800, - RSS_KEY_8125 = 0x4600, - RSS_INDIRECTION_TBL_8125_V2 = 0x4700, - EEE_TXIDLE_TIMER_8125 = 0x6048, - PTP_CTRL_8125 = 0x6800, - PTP_STATUS_8125 = 0x6802, - PTP_ISR_8125 = 0x6804, - PTP_IMR_8125 = 0x6805, - PTP_TIME_CORRECT_CMD_8125 = 0x6806, - PTP_SOFT_CONFIG_Time_NS_8125 = 0x6808, - PTP_SOFT_CONFIG_Time_S_8125 = 0x680C, - PTP_LOCAL_Time_SUB_NS_8125 = 0x6814, - PTP_LOCAL_Time_NS_8125 = 0x6818, - PTP_LOCAL_Time_S_8125 = 0x681C, - PTP_Time_SHIFTER_S_8125 = 0x6856, - PPS_RISE_TIME_NS_8125 = 0x68A0, - PPS_RISE_TIME_S_8125 = 0x68A4, -}; - -enum RTL8125_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxDescUnavail = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - RxDU1 = 0x0002, - RxOK1 = 0x0001, - - /* RxStatusDesc */ - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - RxRWT_V3 = (1 << 18), - RxRES_V3 = (1 << 20), - RxRUNT_V3 = (1 << 19), - RxCRC_V3 = (1 << 17), - - /* ChipCmdBits */ - StopReq = 0x80, - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, - Cfg9346_EEDO = (1 << 0), - Cfg9346_EEDI = (1 << 1), - Cfg9346_EESK = (1 << 2), - Cfg9346_EECS = (1 << 3), - Cfg9346_EEM0 = (1 << 6), - Cfg9346_EEM1 = (1 << 7), - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* Transmit Priority Polling*/ - HPQ = 0x80, - NPQ = 0x40, - FSWInt = 0x01, - - /* RxConfigBits */ - Reserved2_shift = 13, - RxCfgDMAShift = 8, - EnableRxDescV3 = (1 << 24), - EnableOuterVlan = (1 << 23), - EnableInnerVlan = (1 << 22), - RxCfg_128_int_en = (1 << 15), - RxCfg_fet_multi_en = (1 << 14), - RxCfg_half_refetch = (1 << 13), - RxCfg_pause_slot_en = (1 << 11), - RxCfg_9356SEL = (1 << 6), - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - TxMACLoopBack = (1 << 17), /* MAC loopback */ - - /* Config1 register */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register */ - PMSTS_En = (1 << 5), - - /* Config3 register */ - Isolate_en = (1 << 12), /* Isolate enable */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* This bit is reserved in RTL8125B.*/ - /* Wake up when the cable connection is re-established */ - ECRCEN = (1 << 3), /* This bit is reserved in RTL8125B*/ - Jumbo_En0 = (1 << 2), /* This bit is reserved in RTL8125B*/ - RDY_TO_L23 = (1 << 1), /* This bit is reserved in RTL8125B*/ - Beacon_en = (1 << 0), /* This bit is reserved in RTL8125B*/ - - /* Config4 register */ - Jumbo_En1 = (1 << 1), /* This bit is reserved in RTL8125B*/ - - /* Config5 register */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - - /* CPlusCmd */ - EnableBist = (1 << 15), - Macdbgo_oe = (1 << 14), - Normal_mode = (1 << 13), - Force_halfdup = (1 << 12), - Force_rxflow_en = (1 << 11), - Force_txflow_en = (1 << 10), - Cxpl_dbg_sel = (1 << 9),//This bit is reserved in RTL8125B - ASF = (1 << 8),//This bit is reserved in RTL8125C - PktCntrDisable = (1 << 7), - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - Macdbgo_sel = 0x001C, - INTT_0 = 0x0000, - INTT_1 = 0x0001, - INTT_2 = 0x0002, - INTT_3 = 0x0003, - - /* rtl8125_PHYstatus */ - PowerSaveStatus = 0x80, - _2500bpsF = 0x400, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* DBG_reg */ - Fix_Nak_1 = (1 << 4), - Fix_Nak_2 = (1 << 3), - DBGPIN_E2 = (1 << 0), - - /* ResetCounterCommand */ - CounterReset = 0x1, - /* DumpCounterCommand */ - CounterDump = 0x8, - - /* PHY access */ - PHYAR_Flag = 0x80000000, - PHYAR_Write = 0x80000000, - PHYAR_Read = 0x00000000, - PHYAR_Reg_Mask = 0x1f, - PHYAR_Reg_shift = 16, - PHYAR_Data_Mask = 0xffff, - - /* EPHY access */ - EPHYAR_Flag = 0x80000000, - EPHYAR_Write = 0x80000000, - EPHYAR_Read = 0x00000000, - EPHYAR_Reg_Mask = 0x3f, - EPHYAR_Reg_Mask_v2 = 0x7f, - EPHYAR_Reg_shift = 16, - EPHYAR_Data_Mask = 0xffff, - - /* CSI access */ - CSIAR_Flag = 0x80000000, - CSIAR_Write = 0x80000000, - CSIAR_Read = 0x00000000, - CSIAR_ByteEn = 0x0f, - CSIAR_ByteEn_shift = 12, - CSIAR_Addr_Mask = 0x0fff, - - /* ERI access */ - ERIAR_Flag = 0x80000000, - ERIAR_Write = 0x80000000, - ERIAR_Read = 0x00000000, - ERIAR_Addr_Align = 4, /* ERI access register address must be 4 byte alignment */ - ERIAR_ExGMAC = 0, - ERIAR_MSIX = 1, - ERIAR_ASF = 2, - ERIAR_OOB = 2, - ERIAR_Type_shift = 16, - ERIAR_ByteEn = 0x0f, - ERIAR_ByteEn_shift = 12, - - /* OCP GPHY access */ - OCPDR_Write = 0x80000000, - OCPDR_Read = 0x00000000, - OCPDR_Reg_Mask = 0xFF, - OCPDR_Data_Mask = 0xFFFF, - OCPDR_GPHY_Reg_shift = 16, - OCPAR_Flag = 0x80000000, - OCPAR_GPHY_Write = 0x8000F060, - OCPAR_GPHY_Read = 0x0000F060, - OCPR_Write = 0x80000000, - OCPR_Read = 0x00000000, - OCPR_Addr_Reg_shift = 16, - OCPR_Flag = 0x80000000, - OCP_STD_PHY_BASE_PAGE = 0x0A40, - - /* MCU Command */ - Now_is_oob = (1 << 7), - Txfifo_empty = (1 << 5), - Rxfifo_empty = (1 << 4), - - /* E-FUSE access */ - EFUSE_WRITE = 0x80000000, - EFUSE_WRITE_OK = 0x00000000, - EFUSE_READ = 0x00000000, - EFUSE_READ_OK = 0x80000000, - EFUSE_WRITE_V3 = 0x40000000, - EFUSE_WRITE_OK_V3 = 0x00000000, - EFUSE_READ_V3 = 0x80000000, - EFUSE_READ_OK_V3 = 0x00000000, - EFUSE_Reg_Mask = 0x03FF, - EFUSE_Reg_Shift = 8, - EFUSE_Check_Cnt = 300, - EFUSE_READ_FAIL = 0xFF, - EFUSE_Data_Mask = 0x000000FF, - - /* GPIO */ - GPIO_en = (1 << 0), - - /* PTP */ - PTP_ISR_TOK = (1 << 1), - PTP_ISR_TER = (1 << 2), - PTP_EXEC_CMD = (1 << 7), - PTP_ADJUST_TIME_NS_NEGATIVE = (1 << 30), - PTP_ADJUST_TIME_S_NEGATIVE = (1ULL << 48), - - /* New Interrupt Bits */ - INT_CFG0_ENABLE_8125 = (1 << 0), - INT_CFG0_TIMEOUT0_BYPASS_8125 = (1 << 1), - INT_CFG0_MITIGATION_BYPASS_8125 = (1 << 2), - ISRIMR_V2_ROK_Q0 = (1 << 0), - ISRIMR_TOK_Q0 = (1 << 16), - ISRIMR_TOK_Q1 = (1 << 18), - ISRIMR_V2_LINKCHG = (1 << 21), - - /* Magic Number */ - RTL8125_MAGIC_NUMBER = 0x0badbadbadbadbadull, -}; - -enum _DescStatusBit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - DescOwn_V3 = (DescOwn), /* Descriptor is owned by NIC */ - RingEnd_V3 = (RingEnd), /* End of descriptor ring */ - FirstFrag_V3 = (1 << 25), /* First segment of a packet */ - LastFrag_V3 = (1 << 24), /* Final segment of a packet */ - - /* Tx private */ - /*------ offset 0 of tx descriptor ------*/ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - GiantSendv4 = (1 << 26), /* TCP Giant Send Offload V4 (GSOv4) */ - GiantSendv6 = (1 << 25), /* TCP Giant Send Offload V6 (GSOv6) */ - LargeSend_DP = (1 << 16), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0x7FFU, /* MSS value 11 bits */ - TxIPCS = (1 << 18), /* Calculate IP checksum */ - TxUDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TxTCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /*@@@@@@ offset 4 of tx descriptor => bits for RTL8125 only begin @@@@@@*/ - TxUDPCS_C = (1 << 31), /* Calculate UDP/IP checksum */ - TxTCPCS_C = (1 << 30), /* Calculate TCP/IP checksum */ - TxIPCS_C = (1 << 29), /* Calculate IP checksum */ - TxIPV6F_C = (1 << 28), /* Indicate it is an IPv6 packet */ - /*@@@@@@ offset 4 of tx descriptor => bits for RTL8125 only end @@@@@@*/ - - - /* Rx private */ - /*------ offset 0 of rx descriptor ------*/ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - RxIPF = (1 << 16), /* IP checksum failed */ - RxUDPF = (1 << 15), /* UDP/IP checksum failed */ - RxTCPF = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ - - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ - RxUDPT = (1 << 18), - RxTCPT = (1 << 17), - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only end @@@@@@*/ - - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ - RxV6F = (1 << 31), - RxV4F = (1 << 30), - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/ - - - PID1_v3 = (1 << 29), /* Protocol ID bit 1/2 */ - PID0_v3 = (1 << 28), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP_v3 (PID1_v3) -#define RxProtoTCP_v3 (PID0_v3) -#define RxProtoIP_v3 (PID1_v3 | PID0_v3) -#define RxProtoMask_v3 RxProtoIP_v3 - - RxIPF_v3 = (1 << 26), /* IP checksum failed */ - RxUDPF_v3 = (1 << 25), /* UDP/IP checksum failed */ - RxTCPF_v3 = (1 << 24), /* TCP/IP checksum failed */ - RxSCTPF_v3 = (1 << 23), /* TCP/IP checksum failed */ - RxVlanTag_v3 = (RxVlanTag), /* VLAN tag available */ - - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ - RxUDPT_v3 = (1 << 29), - RxTCPT_v3 = (1 << 28), - RxSCTP_v3 = (1 << 27), - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8125 only end @@@@@@*/ - - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only begin @@@@@@*/ - RxV6F_v3 = (RxV6F), - RxV4F_v3 = (RxV4F), - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8125 only end @@@@@@*/ -}; - -enum features { -// RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_MSIX = (1 << 2), -}; - -enum wol_capability { - WOL_DISABLED = 0, - WOL_ENABLED = 1 -}; - -enum bits { - BIT_0 = (1 << 0), - BIT_1 = (1 << 1), - BIT_2 = (1 << 2), - BIT_3 = (1 << 3), - BIT_4 = (1 << 4), - BIT_5 = (1 << 5), - BIT_6 = (1 << 6), - BIT_7 = (1 << 7), - BIT_8 = (1 << 8), - BIT_9 = (1 << 9), - BIT_10 = (1 << 10), - BIT_11 = (1 << 11), - BIT_12 = (1 << 12), - BIT_13 = (1 << 13), - BIT_14 = (1 << 14), - BIT_15 = (1 << 15), - BIT_16 = (1 << 16), - BIT_17 = (1 << 17), - BIT_18 = (1 << 18), - BIT_19 = (1 << 19), - BIT_20 = (1 << 20), - BIT_21 = (1 << 21), - BIT_22 = (1 << 22), - BIT_23 = (1 << 23), - BIT_24 = (1 << 24), - BIT_25 = (1 << 25), - BIT_26 = (1 << 26), - BIT_27 = (1 << 27), - BIT_28 = (1 << 28), - BIT_29 = (1 << 29), - BIT_30 = (1 << 30), - BIT_31 = (1 << 31) -}; - -enum effuse { - EFUSE_NOT_SUPPORT = 0, - EFUSE_SUPPORT_V1, - EFUSE_SUPPORT_V2, - EFUSE_SUPPORT_V3, - EFUSE_SUPPORT_V4, -}; -#define RsvdMask 0x3fffc000 -#define RsvdMaskV3 0x3fff8000 - -struct TxDesc { - u32 opts1; - u32 opts2; - u64 addr; - u32 reserved0; - u32 reserved1; - u32 reserved2; - u32 reserved3; -}; - -struct RxDesc { - u32 opts1; - u32 opts2; - u64 addr; -}; - -struct RxDescV3 { - union { - struct { - u32 rsv1; - u32 rsv2; - } RxDescDDWord1; - }; - - union { - struct { - u32 RSSResult; - u16 HeaderBufferLen; - u16 HeaderInfo; - } RxDescNormalDDWord2; - - struct { - u32 rsv5; - u32 rsv6; - } RxDescDDWord2; - }; - - union { - u64 addr; - - struct { - u32 TimeStampLow; - u32 TimeStampHigh; - } RxDescTimeStamp; - - struct { - u32 rsv8; - u32 rsv9; - } RxDescDDWord3; - }; - - union { - struct { - u32 opts2; - u32 opts1; - } RxDescNormalDDWord4; - - struct { - u16 TimeStampHHigh; - u16 rsv11; - u32 opts1; - } RxDescPTPDDWord4; - }; -}; - -enum rxdesc_type { - RXDESC_TYPE_NORMAL=0, - RXDESC_TYPE_NEXT, - RXDESC_TYPE_PTP, - RXDESC_TYPE_MAX -}; - -//Rx Desc Type -enum rx_desc_ring_type { - RX_DESC_RING_TYPE_UNKNOWN=0, - RX_DESC_RING_TYPE_1, - RX_DESC_RING_TYPE_2, - RX_DESC_RING_TYPE_3, - RX_DESC_RING_TYPE_MAX -}; - -enum rx_desc_len { - RX_DESC_LEN_TYPE_1 = (sizeof(struct RxDesc)), - RX_DESC_LEN_TYPE_3 = (sizeof(struct RxDescV3)) -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -struct pci_resource { - u8 cmd; - u8 cls; - u16 io_base_h; - u16 io_base_l; - u16 mem_base_h; - u16 mem_base_l; - u8 ilr; - u16 resv_0x1c_h; - u16 resv_0x1c_l; - u16 resv_0x20_h; - u16 resv_0x20_l; - u16 resv_0x24_h; - u16 resv_0x24_l; - u16 resv_0x2c_h; - u16 resv_0x2c_l; - u32 pci_sn_l; - u32 pci_sn_h; -}; - -enum r8125_flag { - R8125_FLAG_DOWN = 0, - R8125_FLAG_TASK_RESET_PENDING, - R8125_FLAG_TASK_ESD_CHECK_PENDING, - R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, - R8125_FLAG_MAX -}; - -struct rtl8125_tx_ring { - void* priv; - u32 index; - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_tx; - u32 num_tx_desc; /* Number of Tx descriptor registers */ - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - dma_addr_t TxPhyAddr; - struct ring_info tx_skb[MAX_NUM_TX_DESC]; /* Tx data buffers */ - - u32 NextHwDesCloPtr; - u32 BeginHwDesCloPtr; - - u16 hw_clo_ptr_reg; - u16 sw_tail_ptr_reg; - - u16 tdsar_reg; /* Transmit Descriptor Start Address */ -}; - -struct rtl8125_rx_ring { - void* priv; - u32 index; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 num_rx_desc; /* Number of Rx descriptor registers */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - u64 RxDescPhyAddr[MAX_NUM_RX_DESC]; /* Rx desc physical address*/ - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[MAX_NUM_RX_DESC]; /* Rx data buffers */ - - u16 rdsar_reg; /* Receive Descriptor Start Address */ -}; - -struct r8125_napi { -#ifdef CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) - struct napi_struct napi; -#endif -#endif - void* priv; - int index; -}; - -struct r8125_irq { - irq_handler_t handler; - unsigned int vector; - u8 requested; - char name[IFNAMSIZ + 10]; -}; - -#pragma pack(1) -struct rtl8125_regs { - //00 - u8 mac_id[6]; - u16 reg_06; - u8 mar[8]; - //10 - u64 dtccr; - u16 ledsel0; - u16 legreg; - u32 tctr3; - //20 - u32 txq0_dsc_st_addr_0; - u32 txq0_dsc_st_addr_2; - u64 reg_28; - //30 - u16 rit; - u16 ritc; - u16 reg_34; - u8 reg_36; - u8 command; - u32 imr0; - u32 isr0; - //40 - u32 tcr; - u32 rcr; - u32 tctr0; - u32 tctr1; - //50 - u8 cr93c46; - u8 config0; - u8 config1; - u8 config2; - u8 config3; - u8 config4; - u8 config5; - u8 tdfnr; - u32 timer_int0; - u32 timer_int1; - //60 - u32 gphy_mdcmdio; - u32 csidr; - u32 csiar; - u16 phy_status; - u8 config6; - u8 pmch; - //70 - u32 eridr; - u32 eriar; - u16 config7; - u16 reg_7a; - u32 ephy_rxerr_cnt; - //80 - u32 ephy_mdcmdio; - u16 ledsel2; - u16 ledsel1; - u32 tctr2; - u32 timer_int2; - //90 - u8 tppoll0; - u8 reg_91; - u16 reg_92; - u16 led_feature; - u16 ledsel3; - u16 eee_led_config; - u16 reg_9a; - u32 reg_9c; - //a0 - u32 reg_a0; - u32 reg_a4; - u32 reg_a8; - u32 reg_ac; - //b0 - u32 patch_dbg; - u32 reg_b4; - u32 gphy_ocp; - u32 reg_bc; - //c0 - u32 reg_c0; - u32 reg_c4; - u32 reg_c8; - u16 otp_cmd; - u16 otp_pg_config; - //d0 - u16 phy_pwr; - u8 twsi_ctrl; - u8 oob_ctrl; - u16 mac_dbgo; - u16 mac_dbg; - u16 reg_d8; - u16 rms; - u32 efuse_data; - //e0 - u16 cplus_cmd; - u16 reg_e2; - u32 rxq0_dsc_st_addr_0; - u32 rxq0_dsc_st_addr_2; - u16 reg_ec; - u16 tx10midle_cnt; - //f0 - u16 misc0; - u16 misc1; - u32 timer_int3; - u32 cmac_ib; - u16 reg_fc; - u16 sw_rst; -}; -#pragma pack() - -struct rtl8125_regs_save { - union { - u8 mac_io[R8125_MAC_REGS_SIZE]; - - struct rtl8125_regs mac_reg; - }; - u16 pcie_phy[R8125_EPHY_REGS_SIZE/2]; - u16 eth_phy[R8125_PHY_REGS_SIZE/2]; - u32 eri_reg[R8125_ERI_REGS_SIZE/4]; - u32 pci_reg[R8125_PCI_REGS_SIZE/4]; - u16 sw_tail_ptr_reg[R8125_MAX_TX_QUEUES]; - u16 hw_clo_ptr_reg[R8125_MAX_TX_QUEUES]; - - //ktime_t begin_ktime; - //ktime_t end_ktime; - //u64 duration_ns; - - u16 sw0_tail_ptr; - u16 next_hwq0_clo_ptr; - u16 sw1_tail_ptr; - u16 next_hwq1_clo_ptr; - - u16 int_miti_rxq0; - u16 int_miti_txq0; - u16 int_miti_rxq1; - u16 int_miti_txq1; - u8 int_config; - u32 imr_new; - u32 isr_new; - - u8 tdu_status; - u16 rdu_status; - - u16 tc_mode; - - u32 txq1_dsc_st_addr_0; - u32 txq1_dsc_st_addr_2; - - u32 pla_tx_q0_idle_credit; - u32 pla_tx_q1_idle_credit; - - u32 rxq1_dsc_st_addr_0; - u32 rxq1_dsc_st_addr_2; - - u32 rss_ctrl; - u8 rss_key[RTL8125_RSS_KEY_SIZE]; - u8 rss_i_table[RTL8125_MAX_INDIRECTION_TABLE_ENTRIES]; - u16 rss_queue_num_sel_r; -}; - -struct rtl8125_counters { - /* legacy */ - u64 tx_packets; - u64 rx_packets; - u64 tx_errors; - u32 rx_errors; - u16 rx_missed; - u16 align_errors; - u32 tx_one_collision; - u32 tx_multi_collision; - u64 rx_unicast; - u64 rx_broadcast; - u32 rx_multicast; - u16 tx_aborted; - u16 tx_underrun; - - /* extended */ - u64 tx_octets; - u64 rx_octets; - u64 rx_multicast64; - u64 tx_unicast64; - u64 tx_broadcast64; - u64 tx_multicast64; - u32 tx_pause_on; - u32 tx_pause_off; - u32 tx_pause_all; - u32 tx_deferred; - u32 tx_late_collision; - u32 tx_all_collision; - u32 tx_aborted32; - u32 align_errors32; - u32 rx_frame_too_long; - u32 rx_runt; - u32 rx_pause_on; - u32 rx_pause_off; - u32 rx_pause_all; - u32 rx_unknown_opcode; - u32 rx_mac_error; - u32 tx_underrun32; - u32 rx_mac_missed; - u32 rx_tcam_dropped; - u32 tdu; - u32 rdu; -}; - -/* Flow Control Settings */ -enum rtl8125_fc_mode { - rtl8125_fc_none = 0, - rtl8125_fc_rx_pause, - rtl8125_fc_tx_pause, - rtl8125_fc_full, - rtl8125_fc_default -}; - -struct rtl8125_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; - struct r8125_napi r8125napi[R8125_MAX_MSIX_VEC]; - struct r8125_irq irq_tbl[R8125_MAX_MSIX_VEC]; - unsigned int irq_nvecs; - unsigned int max_irq_nvecs; - unsigned int min_irq_nvecs; - //struct msix_entry msix_entries[R8125_MAX_MSIX_VEC]; - struct net_device_stats stats; /* statistics of net device */ -#ifdef ENABLE_PTP_SUPPORT - spinlock_t lock; /* spin lock flag */ -#endif - u32 msg_enable; - u32 tx_tcp_csum_cmd; - u32 tx_udp_csum_cmd; - u32 tx_ip_csum_cmd; - u32 tx_ipv6_csum_cmd; - int max_jumbo_frame_size; - int chipset; - u32 mcfg; - //u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - //u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - //u32 dirty_rx; - //u32 dirty_tx; - //struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - //struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - //dma_addr_t TxPhyAddr; - //dma_addr_t RxPhyAddr; - //struct sk_buff *Rx_skbuff[MAX_NUM_RX_DESC]; /* Rx data buffers */ - //struct ring_info tx_skb[MAX_NUM_TX_DESC]; /* Tx data buffers */ - unsigned rx_buf_sz; - u16 HwSuppNumTxQueues; - u16 HwSuppNumRxQueues; - unsigned int num_tx_rings; - unsigned int num_rx_rings; - struct rtl8125_tx_ring tx_ring[R8125_MAX_TX_QUEUES]; - struct rtl8125_rx_ring rx_ring[R8125_MAX_RX_QUEUES]; -#ifdef ENABLE_LIB_SUPPORT - struct atomic_notifier_head lib_nh; - struct rtl8125_ring lib_tx_ring[R8125_MAX_TX_QUEUES]; - struct rtl8125_ring lib_rx_ring[R8125_MAX_RX_QUEUES]; -#endif - //struct timer_list esd_timer; - //struct timer_list link_timer; - struct pci_resource pci_cfg_space; - unsigned int esd_flag; - unsigned int pci_cfg_is_read; - unsigned int rtl8125_rx_config; - u16 cp_cmd; - u32 intr_mask; - u32 timer_intr_mask; - u16 isr_reg[R8125_MAX_QUEUES]; - u16 imr_reg[R8125_MAX_QUEUES]; - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; - int phy_2500_ctrl_reg; - u8 org_mac_addr[NODE_ADDRESS_SIZE]; - struct rtl8125_counters *tally_vaddr; - dma_addr_t tally_paddr; - -#ifdef CONFIG_R8125_VLAN - struct vlan_group *vlgrp; -#endif - u8 wol_enabled; - u32 wol_opts; - u8 efuse_ver; - u8 eeprom_type; - u8 autoneg; - u8 duplex; - u32 speed; - u32 advertising; - enum rtl8125_fc_mode fcpause; - u16 eeprom_len; - u16 cur_page; - u32 bios_setting; - - int (*set_speed)(struct net_device *, u8 autoneg, u32 speed, u8 duplex, u32 adv); -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - void (*get_settings)(struct net_device *, struct ethtool_cmd *); -#else - void (*get_settings)(struct net_device *, struct ethtool_link_ksettings *); -#endif - void (*phy_reset_enable)(struct net_device *); - unsigned int (*phy_reset_pending)(struct net_device *); - unsigned int (*link_ok)(struct net_device *); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct work_struct reset_task; - struct work_struct esd_task; - struct work_struct linkchg_task; -#else - struct delayed_work reset_task; - struct delayed_work esd_task; - struct delayed_work linkchg_task; -#endif - DECLARE_BITMAP(task_flags, R8125_FLAG_MAX); - unsigned features; - - u8 org_pci_offset_99; - u8 org_pci_offset_180; - u8 issue_offset_99_event; - - u8 org_pci_offset_80; - u8 org_pci_offset_81; - u8 use_timer_interrrupt; - - u32 keep_intr_cnt; - - u8 HwIcVerUnknown; - u8 NotWrRamCodeToMicroP; - u8 NotWrMcuPatchCode; - u8 HwHasWrRamCodeToMicroP; - - u16 sw_ram_code_ver; - u16 hw_ram_code_ver; - - u8 RequireRduNonStopPatch; - - u8 rtk_enable_diag; - - u8 ShortPacketSwChecksum; - - u8 UseSwPaddingShortPkt; - - void *ShortPacketEmptyBuffer; - dma_addr_t ShortPacketEmptyBufferPhy; - - u8 RequireAdcBiasPatch; - u16 AdcBiasPatchIoffset; - - u8 RequireAdjustUpsTxLinkPulseTiming; - u16 SwrCnt1msIni; - - u8 HwSuppNowIsOobVer; - - u8 RequiredSecLanDonglePatch; - - u8 RequirePhyMdiSwapPatch; - - u8 RequireLSOPatch; - - u32 HwFiberModeVer; - u32 HwFiberStat; - u8 HwSwitchMdiToFiber; - - u16 NicCustLedValue; - - u8 HwSuppMagicPktVer; - - u8 HwSuppLinkChgWakeUpVer; - - u8 HwSuppCheckPhyDisableModeVer; - - u8 random_mac; - - u16 phy_reg_aner; - u16 phy_reg_anlpar; - u16 phy_reg_gbsr; - u16 phy_reg_status_2500; - - u32 HwPcieSNOffset; - - u8 HwSuppTxNoCloseVer; - u8 EnableTxNoClose; - - u8 HwSuppIsrVer; - u8 HwCurrIsrVer; - - u8 HwSuppIntMitiVer; - - u8 HwSuppExtendTallyCounterVer; - - u8 check_keep_link_speed; - u8 resume_not_chg_speed; - - u8 HwSuppD0SpeedUpVer; - u8 D0SpeedUpSpeed; - - u8 ring_lib_enabled; - - const char *fw_name; - struct rtl8125_fw *rtl_fw; - u32 ocp_base; - - //Dash+++++++++++++++++ - u8 HwSuppDashVer; - u8 DASH; - u8 dash_printer_enabled; - u8 HwPkgDet; - void __iomem *mapped_cmac_ioaddr; /* mapped cmac memory map physical address */ - void __iomem *cmac_ioaddr; /* cmac memory map physical address */ - -#ifdef ENABLE_DASH_SUPPORT - u16 AfterRecvFromFwBufLen; - u8 AfterRecvFromFwBuf[RECV_FROM_FW_BUF_SIZE]; - u16 AfterSendToFwBufLen; - u8 AfterSendToFwBuf[SEND_TO_FW_BUF_SIZE]; - u16 SendToFwBufferLen; - u32 SizeOfSendToFwBuffer; - u32 SizeOfSendToFwBufferMemAlloc; - u32 NumOfSendToFwBuffer; - - u8 OobReq; - u8 OobAck; - u32 OobReqComplete; - u32 OobAckComplete; - - u8 RcvFwReqSysOkEvt; - u8 RcvFwDashOkEvt; - u8 SendFwHostOkEvt; - - u8 DashFwDisableRx; - - void *UnalignedSendToFwBufferVa; - void *SendToFwBuffer; - u64 SendToFwBufferPhy; - u8 SendingToFw; - dma_addr_t UnalignedSendToFwBufferPa; - PTX_DASH_SEND_FW_DESC TxDashSendFwDesc; - u64 TxDashSendFwDescPhy; - u8 *UnalignedTxDashSendFwDescVa; - u32 SizeOfTxDashSendFwDescMemAlloc; - u32 SizeOfTxDashSendFwDesc; - u32 NumTxDashSendFwDesc; - u32 CurrNumTxDashSendFwDesc; - u32 LastSendNumTxDashSendFwDesc; - dma_addr_t UnalignedTxDashSendFwDescPa; - - u32 NumRecvFromFwBuffer; - u32 SizeOfRecvFromFwBuffer; - u32 SizeOfRecvFromFwBufferMemAlloc; - void *RecvFromFwBuffer; - u64 RecvFromFwBufferPhy; - - void *UnalignedRecvFromFwBufferVa; - dma_addr_t UnalignedRecvFromFwBufferPa; - PRX_DASH_FROM_FW_DESC RxDashRecvFwDesc; - u64 RxDashRecvFwDescPhy; - u8 *UnalignedRxDashRecvFwDescVa; - u32 SizeOfRxDashRecvFwDescMemAlloc; - u32 SizeOfRxDashRecvFwDesc; - u32 NumRxDashRecvFwDesc; - u32 CurrNumRxDashRecvFwDesc; - dma_addr_t UnalignedRxDashRecvFwDescPa; - u8 DashReqRegValue; - u16 HostReqValue; - - u32 CmacResetIsrCounter; - u8 CmacResetIntr; - u8 CmacResetting; - u8 CmacOobIssueCmacReset; - u32 CmacResetbyFwCnt; - -#if defined(ENABLE_DASH_PRINTER_SUPPORT) - struct completion fw_ack; - struct completion fw_req; - struct completion fw_host_ok; -#endif - //Dash----------------- -#endif //ENABLE_DASH_SUPPORT - - //Realwow++++++++++++++ - u8 HwSuppKCPOffloadVer; - - u8 EnableDhcpTimeoutWake; - u8 EnableTeredoOffload; - u8 EnableKCPOffload; -#ifdef ENABLE_REALWOW_SUPPORT - u32 DhcpTimeout; - MP_KCP_INFO MpKCPInfo; - //Realwow-------------- -#endif //ENABLE_REALWOW_SUPPORT - - struct ethtool_eee eee; - -#ifdef ENABLE_R8125_PROCFS - //Procfs support - struct proc_dir_entry *proc_dir; -#endif - u8 InitRxDescType; - u16 RxDescLength; //V1 16 Byte V2 32 Bytes - - u8 HwSuppPtpVer; - u8 EnablePtp; - u8 ptp_master_mode; - s64 ptp_adjust; -#ifdef ENABLE_PTP_SUPPORT - u32 tx_hwtstamp_timeouts; - u32 tx_hwtstamp_skipped; - struct work_struct ptp_tx_work; - struct sk_buff *ptp_tx_skb; - struct hwtstamp_config hwtstamp_config; - unsigned long ptp_tx_start; - struct ptp_clock_info ptp_clock_info; - struct ptp_clock *ptp_clock; -#endif - - u8 HwSuppRssVer; - u8 EnableRss; - u16 HwSuppIndirTblEntries; -#ifdef ENABLE_RSS_SUPPORT - u32 rss_flags; - /* Receive Side Scaling settings */ - u8 rss_key[RTL8125_RSS_KEY_SIZE]; - u8 rss_indir_tbl[RTL8125_MAX_INDIRECTION_TABLE_ENTRIES]; - u32 rss_options; -#endif - - u8 HwSuppMacMcuVer; - u16 MacMcuPageSize; -}; - -#ifdef ENABLE_LIB_SUPPORT -static inline unsigned int -rtl8125_num_lib_tx_rings(struct rtl8125_private *tp) -{ - int count, i; - - for (count = 0, i = tp->num_tx_rings; i < tp->HwSuppNumTxQueues; i++) - if(tp->lib_tx_ring[i].enabled) - count++; - - return count; -} - -static inline unsigned int -rtl8125_num_lib_rx_rings(struct rtl8125_private *tp) -{ - int count, i; - - for (count = 0, i = tp->num_rx_rings; i < tp->HwSuppNumRxQueues; i++) - if(tp->lib_rx_ring[i].enabled) - count++; - - return count; -} - -#else -static inline unsigned int -rtl8125_num_lib_tx_rings(struct rtl8125_private *tp) -{ - return 0; -} - -static inline unsigned int -rtl8125_num_lib_rx_rings(struct rtl8125_private *tp) -{ - return 0; -} -#endif - -static inline unsigned int -rtl8125_tot_tx_rings(struct rtl8125_private *tp) -{ - return tp->num_tx_rings + rtl8125_num_lib_tx_rings(tp); -} - -static inline unsigned int -rtl8125_tot_rx_rings(struct rtl8125_private *tp) -{ - return tp->num_rx_rings + rtl8125_num_lib_rx_rings(tp); -} - -enum eetype { - EEPROM_TYPE_NONE=0, - EEPROM_TYPE_93C46, - EEPROM_TYPE_93C56, - EEPROM_TWSI -}; - -enum mcfg { - CFG_METHOD_2=2, - CFG_METHOD_3, - CFG_METHOD_4, - CFG_METHOD_5, - CFG_METHOD_6, - CFG_METHOD_7, - CFG_METHOD_DEFAULT, - CFG_METHOD_MAX -}; - -#define LSO_32K 32000 -#define LSO_64K 64000 - -#define NIC_MIN_PHYS_BUF_COUNT (2) -#define NIC_MAX_PHYS_BUF_COUNT_LSO_64K (24) -#define NIC_MAX_PHYS_BUF_COUNT_LSO2 (16*4) - -#define GTTCPHO_SHIFT 18 -#define GTTCPHO_MAX 0x70U -#define GTPKTSIZE_MAX 0x3ffffU -#define TCPHO_SHIFT 18 -#define TCPHO_MAX 0x3ffU -#define LSOPKTSIZE_MAX 0xffffU -#define MSS_MAX 0x07ffu /* MSS value */ - -#define OOB_CMD_RESET 0x00 -#define OOB_CMD_DRIVER_START 0x05 -#define OOB_CMD_DRIVER_STOP 0x06 -#define OOB_CMD_SET_IPMAC 0x41 - -#define WAKEUP_MAGIC_PACKET_NOT_SUPPORT (0) -#define WAKEUP_MAGIC_PACKET_V1 (1) -#define WAKEUP_MAGIC_PACKET_V2 (2) -#define WAKEUP_MAGIC_PACKET_V3 (3) - -//Ram Code Version -#define NIC_RAMCODE_VERSION_CFG_METHOD_2 (0x0b11) -#define NIC_RAMCODE_VERSION_CFG_METHOD_3 (0x0b33) -#define NIC_RAMCODE_VERSION_CFG_METHOD_4 (0x0b17) -#define NIC_RAMCODE_VERSION_CFG_METHOD_5 (0x0b74) - -//hwoptimize -#define HW_PATCH_SOC_LAN (BIT_0) -#define HW_PATCH_SAMSUNG_LAN_DONGLE (BIT_2) - -static const u16 other_q_intr_mask = (RxOK1 | RxDU1); - -void rtl8125_mdio_write(struct rtl8125_private *tp, u16 RegAddr, u16 value); -void rtl8125_mdio_prot_write(struct rtl8125_private *tp, u32 RegAddr, u32 value); -void rtl8125_mdio_prot_direct_write_phy_ocp(struct rtl8125_private *tp, u32 RegAddr, u32 value); -u32 rtl8125_mdio_read(struct rtl8125_private *tp, u16 RegAddr); -u32 rtl8125_mdio_prot_read(struct rtl8125_private *tp, u32 RegAddr); -u32 rtl8125_mdio_prot_direct_read_phy_ocp(struct rtl8125_private *tp, u32 RegAddr); -void rtl8125_ephy_write(struct rtl8125_private *tp, int RegAddr, int value); -void rtl8125_mac_ocp_write(struct rtl8125_private *tp, u16 reg_addr, u16 value); -u32 rtl8125_mac_ocp_read(struct rtl8125_private *tp, u16 reg_addr); -void rtl8125_clear_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask); -void rtl8125_set_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask); -void rtl8125_ocp_write(struct rtl8125_private *tp, u16 addr, u8 len, u32 data); -void rtl8125_oob_notify(struct rtl8125_private *tp, u8 cmd); -void rtl8125_init_ring_indexes(struct rtl8125_private *tp); -int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type); -void rtl8125_oob_mutex_lock(struct rtl8125_private *tp); -u32 rtl8125_ocp_read(struct rtl8125_private *tp, u16 addr, u8 len); -u32 rtl8125_ocp_read_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 base_address); -u32 rtl8125_ocp_write_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 value, u32 base_address); -u32 rtl8125_eri_read(struct rtl8125_private *tp, int addr, int len, int type); -u32 rtl8125_eri_read_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, int type, u32 base_address); -int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type); -int rtl8125_eri_write_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, u32 value, int type, u32 base_address); -u16 rtl8125_ephy_read(struct rtl8125_private *tp, int RegAddr); -void rtl8125_wait_txrx_fifo_empty(struct net_device *dev); -void rtl8125_enable_now_is_oob(struct rtl8125_private *tp); -void rtl8125_disable_now_is_oob(struct rtl8125_private *tp); -void rtl8125_oob_mutex_unlock(struct rtl8125_private *tp); -void rtl8125_dash2_disable_tx(struct rtl8125_private *tp); -void rtl8125_dash2_enable_tx(struct rtl8125_private *tp); -void rtl8125_dash2_disable_rx(struct rtl8125_private *tp); -void rtl8125_dash2_enable_rx(struct rtl8125_private *tp); -void rtl8125_hw_disable_mac_mcu_bps(struct net_device *dev); -void rtl8125_mark_to_asic(struct rtl8125_private *tp, struct RxDesc *desc, u32 rx_buf_sz); - -static inline void -rtl8125_make_unusable_by_asic(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) { - ((struct RxDescV3 *)desc)->addr = RTL8125_MAGIC_NUMBER; - ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts1 &= ~cpu_to_le32(DescOwn | RsvdMaskV3); - } else { - desc->addr = RTL8125_MAGIC_NUMBER; - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); - } -} - -static inline struct RxDesc* -rtl8125_get_rxdesc(struct rtl8125_private *tp, struct RxDesc *RxDescBase, u32 const cur_rx) -{ - return (struct RxDesc*)((u8*)RxDescBase + (cur_rx * tp->RxDescLength)); -} - -static inline void -rtl8125_disable_hw_interrupt_v2(struct rtl8125_private *tp, - u32 message_id) -{ - RTL_W32(tp, IMR_V2_CLEAR_REG_8125, BIT(message_id)); -} - -static inline void -rtl8125_enable_hw_interrupt_v2(struct rtl8125_private *tp, u32 message_id) -{ - RTL_W32(tp, IMR_V2_SET_REG_8125, BIT(message_id)); -} - -int rtl8125_open(struct net_device *dev); -int rtl8125_close(struct net_device *dev); -void rtl8125_hw_config(struct net_device *dev); -void rtl8125_hw_set_timer_int_8125(struct rtl8125_private *tp, u32 message_id, u8 timer_intmiti_val); -void rtl8125_set_rx_q_num(struct rtl8125_private *tp, unsigned int num_rx_queues); -void rtl8125_set_tx_q_num(struct rtl8125_private *tp, unsigned int num_tx_queues); -void rtl8125_hw_start(struct net_device *dev); -void rtl8125_hw_reset(struct net_device *dev); -void rtl8125_tx_clear(struct rtl8125_private *tp); -void rtl8125_rx_clear(struct rtl8125_private *tp); -int rtl8125_init_ring(struct net_device *dev); -void rtl8125_hw_set_rx_packet_filter(struct net_device *dev); -void rtl8125_enable_hw_linkchg_interrupt(struct rtl8125_private *tp); -int rtl8125_dump_tally_counter(struct rtl8125_private *tp, dma_addr_t paddr); - -#ifndef ENABLE_LIB_SUPPORT -static inline void rtl8125_lib_reset_prepare(struct rtl8125_private *tp) { } -static inline void rtl8125_lib_reset_complete(struct rtl8125_private *tp) { } -#endif - -#define HW_SUPPORT_CHECK_PHY_DISABLE_MODE(_M) ((_M)->HwSuppCheckPhyDisableModeVer > 0 ) -#define HW_HAS_WRITE_PHY_MCU_RAM_CODE(_M) (((_M)->HwHasWrRamCodeToMicroP == TRUE) ? 1 : 0) -#define HW_SUPPORT_D0_SPEED_UP(_M) ((_M)->HwSuppD0SpeedUpVer > 0) -#define HW_SUPPORT_MAC_MCU(_M) ((_M)->HwSuppMacMcuVer > 0) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) -#define netdev_mc_count(dev) ((dev)->mc_count) -#define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0) -#define netdev_for_each_mc_addr(mclist, dev) \ - for (mclist = dev->mc_list; mclist; mclist = mclist->next) -#endif - -#endif /* __R8125_H */ diff --git a/addons/r8125/src/4.4.180/r8125_dash.h b/addons/r8125/src/4.4.180/r8125_dash.h deleted file mode 100755 index 6819370d..00000000 --- a/addons/r8125/src/4.4.180/r8125_dash.h +++ /dev/null @@ -1,261 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_R8125_DASH_H -#define _LINUX_R8125_DASH_H - -#include - -#define SIOCDEVPRIVATE_RTLDASH SIOCDEVPRIVATE+2 - -enum rtl_dash_cmd { - RTL_DASH_ARP_NS_OFFLOAD = 0, - RTL_DASH_SET_OOB_IPMAC, - RTL_DASH_NOTIFY_OOB, - - RTL_DASH_SEND_BUFFER_DATA_TO_DASH_FW, - RTL_DASH_CHECK_SEND_BUFFER_TO_DASH_FW_COMPLETE, - RTL_DASH_GET_RCV_FROM_FW_BUFFER_DATA, - RTL_DASH_OOB_REQ, - RTL_DASH_OOB_ACK, - RTL_DASH_DETACH_OOB_REQ, - RTL_DASH_DETACH_OOB_ACK, - - RTL_FW_SET_IPV4 = 0x10, - RTL_FW_GET_IPV4, - RTL_FW_SET_IPV6, - RTL_FW_GET_IPV6, - RTL_FW_SET_EXT_SNMP, - RTL_FW_GET_EXT_SNMP, - RTL_FW_SET_WAKEUP_PATTERN, - RTL_FW_GET_WAKEUP_PATTERN, - RTL_FW_DEL_WAKEUP_PATTERN, - - RTLT_DASH_COMMAND_INVALID, -}; - -struct rtl_dash_ip_mac { - struct sockaddr ifru_addr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; -}; - -struct rtl_dash_ioctl_struct { - __u32 cmd; - __u32 offset; - __u32 len; - union { - __u32 data; - void *data_buffer; - }; -}; - -struct settings_ipv4 { - __u32 IPv4addr; - __u32 IPv4mask; - __u32 IPv4Gateway; -}; - -struct settings_ipv6 { - __u32 reserved; - __u32 prefixLen; - __u16 IPv6addr[8]; - __u16 IPv6Gateway[8]; -}; - -struct settings_ext_snmp { - __u16 index; - __u16 oid_get_len; - __u8 oid_for_get[24]; - __u8 reserved0[26]; - __u16 value_len; - __u8 value[256]; - __u8 supported; - __u8 reserved1[27]; -}; - -struct wakeup_pattern { - __u8 index; - __u8 valid; - __u8 start; - __u8 length; - __u8 name[36]; - __u8 mask[16]; - __u8 pattern[128]; - __u32 reserved[2]; -}; - -typedef struct _RX_DASH_FROM_FW_DESC { - u16 length; - u8 statusLowByte; - u8 statusHighByte; - u32 resv; - u64 BufferAddress; -} -RX_DASH_FROM_FW_DESC, *PRX_DASH_FROM_FW_DESC; - -typedef struct _TX_DASH_SEND_FW_DESC { - u16 length; - u8 statusLowByte; - u8 statusHighByte; - u32 resv; - u64 BufferAddress; -} -TX_DASH_SEND_FW_DESC, *PTX_DASH_SEND_FW_DESC; - -typedef struct _OSOOBHdr { - u32 len; - u8 type; - u8 flag; - u8 hostReqV; - u8 res; -} -OSOOBHdr, *POSOOBHdr; - -typedef struct _RX_DASH_BUFFER_TYPE_2 { - OSOOBHdr oobhdr; - u8 RxDataBuffer[0]; -} -RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2; - -#define ALIGN_8 (0x7) -#define ALIGN_16 (0xf) -#define ALIGN_32 (0x1f) -#define ALIGN_64 (0x3f) -#define ALIGN_256 (0xff) -#define ALIGN_4096 (0xfff) - -#define OCP_REG_CONFIG0 (0x10) -#define OCP_REG_CONFIG0_REV_F (0xB8) -#define OCP_REG_DASH_POLL (0x30) -#define OCP_REG_HOST_REQ (0x34) -#define OCP_REG_DASH_REQ (0x35) -#define OCP_REG_CR (0x36) -#define OCP_REG_DMEMSTA (0x38) -#define OCP_REG_GPHYAR (0x60) - - -#define OCP_REG_CONFIG0_DASHEN BIT_15 -#define OCP_REG_CONFIG0_OOBRESET BIT_14 -#define OCP_REG_CONFIG0_APRDY BIT_13 -#define OCP_REG_CONFIG0_FIRMWARERDY BIT_12 -#define OCP_REG_CONFIG0_DRIVERRDY BIT_11 -#define OCP_REG_CONFIG0_OOB_WDT BIT_9 -#define OCP_REG_CONFIG0_DRV_WAIT_OOB BIT_8 -#define OCP_REG_CONFIG0_TLSEN BIT_7 - -#define HW_DASH_SUPPORT_DASH(_M) ((_M)->HwSuppDashVer > 0 ) -#define HW_DASH_SUPPORT_TYPE_1(_M) ((_M)->HwSuppDashVer == 1 ) -#define HW_DASH_SUPPORT_TYPE_2(_M) ((_M)->HwSuppDashVer == 2 ) -#define HW_DASH_SUPPORT_TYPE_3(_M) ((_M)->HwSuppDashVer == 3 ) - -#define RECV_FROM_FW_BUF_SIZE (1520) -#define SEND_TO_FW_BUF_SIZE (1520) - -#define RX_DASH_FROM_FW_OWN BIT_15 -#define TX_DASH_SEND_FW_OWN BIT_15 -#define TX_DASH_SEND_FW_OWN_HIGHBYTE BIT_7 - -#define TXS_CC3_0 (BIT_0|BIT_1|BIT_2|BIT_3) -#define TXS_EXC BIT_4 -#define TXS_LNKF BIT_5 -#define TXS_OWC BIT_6 -#define TXS_TES BIT_7 -#define TXS_UNF BIT_9 -#define TXS_LGSEN BIT_11 -#define TXS_LS BIT_12 -#define TXS_FS BIT_13 -#define TXS_EOR BIT_14 -#define TXS_OWN BIT_15 - -#define TPPool_HRDY 0x20 - -#define HostReqReg (0xC0) -#define SystemMasterDescStartAddrLow (0xF0) -#define SystemMasterDescStartAddrHigh (0xF4) -#define SystemSlaveDescStartAddrLow (0xF8) -#define SystemSlaveDescStartAddrHigh (0xFC) - -//DASH Request Type -#define WSMANREG 0x01 -#define OSPUSHDATA 0x02 - -#define RXS_OWN BIT_15 -#define RXS_EOR BIT_14 -#define RXS_FS BIT_13 -#define RXS_LS BIT_12 - -#define ISRIMR_DP_DASH_OK BIT_15 -#define ISRIMR_DP_HOST_OK BIT_13 -#define ISRIMR_DP_REQSYS_OK BIT_11 - -#define ISRIMR_DASH_INTR_EN BIT_12 -#define ISRIMR_DASH_INTR_CMAC_RESET BIT_15 - -#define ISRIMR_DASH_TYPE2_ROK BIT_0 -#define ISRIMR_DASH_TYPE2_RDU BIT_1 -#define ISRIMR_DASH_TYPE2_TOK BIT_2 -#define ISRIMR_DASH_TYPE2_TDU BIT_3 -#define ISRIMR_DASH_TYPE2_TX_FIFO_FULL BIT_4 -#define ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE BIT_5 -#define ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE BIT_6 - -#define CMAC_OOB_STOP 0x25 -#define CMAC_OOB_INIT 0x26 -#define CMAC_OOB_RESET 0x2a - -#define NO_BASE_ADDRESS 0x00000000 -#define RTL8168FP_OOBMAC_BASE 0xBAF70000 -#define RTL8168FP_CMAC_IOBASE 0xBAF20000 -#define RTL8168FP_KVM_BASE 0xBAF80400 -#define CMAC_SYNC_REG 0x20 -#define CMAC_RXDESC_OFFSET 0x90 //RX: 0x90 - 0x98 -#define CMAC_TXDESC_OFFSET 0x98 //TX: 0x98 - 0x9F - -/* cmac write/read MMIO register */ -#define RTL_CMAC_W8(tp, reg, val8) writeb ((val8), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_W16(tp, reg, val16) writew ((val16), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_W32(tp, reg, val32) writel ((val32), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R8(tp, reg) readb (tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R16(tp, reg) readw (tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R32(tp, reg) ((unsigned long) readl (tp->cmac_ioaddr + (reg))) - -int rtl8125_dash_ioctl(struct net_device *dev, struct ifreq *ifr); -void HandleDashInterrupt(struct net_device *dev); -int AllocateDashShareMemory(struct net_device *dev); -void FreeAllocatedDashShareMemory(struct net_device *dev); -void DashHwInit(struct net_device *dev); - - -#endif /* _LINUX_R8125_DASH_H */ diff --git a/addons/r8125/src/4.4.180/r8125_firmware.c b/addons/r8125/src/4.4.180/r8125_firmware.c deleted file mode 100755 index 61b92d11..00000000 --- a/addons/r8125/src/4.4.180/r8125_firmware.c +++ /dev/null @@ -1,264 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include - -#include "r8125_firmware.h" - -enum rtl_fw_opcode { - PHY_READ = 0x0, - PHY_DATA_OR = 0x1, - PHY_DATA_AND = 0x2, - PHY_BJMPN = 0x3, - PHY_MDIO_CHG = 0x4, - PHY_CLEAR_READCOUNT = 0x7, - PHY_WRITE = 0x8, - PHY_READCOUNT_EQ_SKIP = 0x9, - PHY_COMP_EQ_SKIPN = 0xa, - PHY_COMP_NEQ_SKIPN = 0xb, - PHY_WRITE_PREVIOUS = 0xc, - PHY_SKIPN = 0xd, - PHY_DELAY_MS = 0xe, -}; - -struct fw_info { - u32 magic; - char version[RTL8125_VER_SIZE]; - __le32 fw_start; - __le32 fw_len; - u8 chksum; -} __packed; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) -#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) -#endif -#define FW_OPCODE_SIZE sizeof_field(struct rtl8125_fw_phy_action, code[0]) - -static bool rtl8125_fw_format_ok(struct rtl8125_fw *rtl_fw) -{ - const struct firmware *fw = rtl_fw->fw; - struct fw_info *fw_info = (struct fw_info *)fw->data; - struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; - - if (fw->size < FW_OPCODE_SIZE) - return false; - - if (!fw_info->magic) { - size_t i, size, start; - u8 checksum = 0; - - if (fw->size < sizeof(*fw_info)) - return false; - - for (i = 0; i < fw->size; i++) - checksum += fw->data[i]; - if (checksum != 0) - return false; - - start = le32_to_cpu(fw_info->fw_start); - if (start > fw->size) - return false; - - size = le32_to_cpu(fw_info->fw_len); - if (size > (fw->size - start) / FW_OPCODE_SIZE) - return false; - - strscpy(rtl_fw->version, fw_info->version, RTL8125_VER_SIZE); - - pa->code = (__le32 *)(fw->data + start); - pa->size = size; - } else { - if (fw->size % FW_OPCODE_SIZE) - return false; - - strscpy(rtl_fw->version, rtl_fw->fw_name, RTL8125_VER_SIZE); - - pa->code = (__le32 *)fw->data; - pa->size = fw->size / FW_OPCODE_SIZE; - } - - return true; -} - -static bool rtl8125_fw_data_ok(struct rtl8125_fw *rtl_fw) -{ - struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; - size_t index; - - for (index = 0; index < pa->size; index++) { - u32 action = le32_to_cpu(pa->code[index]); - u32 val = action & 0x0000ffff; - u32 regno = (action & 0x0fff0000) >> 16; - - switch (action >> 28) { - case PHY_READ: - case PHY_DATA_OR: - case PHY_DATA_AND: - case PHY_CLEAR_READCOUNT: - case PHY_WRITE: - case PHY_WRITE_PREVIOUS: - case PHY_DELAY_MS: - break; - - case PHY_MDIO_CHG: - if (val > 1) - goto out; - break; - - case PHY_BJMPN: - if (regno > index) - goto out; - break; - case PHY_READCOUNT_EQ_SKIP: - if (index + 2 >= pa->size) - goto out; - break; - case PHY_COMP_EQ_SKIPN: - case PHY_COMP_NEQ_SKIPN: - case PHY_SKIPN: - if (index + 1 + regno >= pa->size) - goto out; - break; - - default: - dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action); - return false; - } - } - - return true; -out: - dev_err(rtl_fw->dev, "Out of range of firmware\n"); - return false; -} - -void rtl8125_fw_write_firmware(struct rtl8125_private *tp, struct rtl8125_fw *rtl_fw) -{ - struct rtl8125_fw_phy_action *pa = &rtl_fw->phy_action; - rtl8125_fw_write_t fw_write = rtl_fw->phy_write; - rtl8125_fw_read_t fw_read = rtl_fw->phy_read; - int predata = 0, count = 0; - size_t index; - - for (index = 0; index < pa->size; index++) { - u32 action = le32_to_cpu(pa->code[index]); - u32 data = action & 0x0000ffff; - u32 regno = (action & 0x0fff0000) >> 16; - enum rtl_fw_opcode opcode = action >> 28; - - if (!action) - break; - - switch (opcode) { - case PHY_READ: - predata = fw_read(tp, regno); - count++; - break; - case PHY_DATA_OR: - predata |= data; - break; - case PHY_DATA_AND: - predata &= data; - break; - case PHY_BJMPN: - index -= (regno + 1); - break; - case PHY_MDIO_CHG: - if (data) { - fw_write = rtl_fw->mac_mcu_write; - fw_read = rtl_fw->mac_mcu_read; - } else { - fw_write = rtl_fw->phy_write; - fw_read = rtl_fw->phy_read; - } - - break; - case PHY_CLEAR_READCOUNT: - count = 0; - break; - case PHY_WRITE: - fw_write(tp, regno, data); - break; - case PHY_READCOUNT_EQ_SKIP: - if (count == data) - index++; - break; - case PHY_COMP_EQ_SKIPN: - if (predata == data) - index += regno; - break; - case PHY_COMP_NEQ_SKIPN: - if (predata != data) - index += regno; - break; - case PHY_WRITE_PREVIOUS: - fw_write(tp, regno, predata); - break; - case PHY_SKIPN: - index += regno; - break; - case PHY_DELAY_MS: - mdelay(data); - break; - } - } -} - -void rtl8125_fw_release_firmware(struct rtl8125_fw *rtl_fw) -{ - release_firmware(rtl_fw->fw); -} - -int rtl8125_fw_request_firmware(struct rtl8125_fw *rtl_fw) -{ - int rc; - - rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev); - if (rc < 0) - goto out; - - if (!rtl8125_fw_format_ok(rtl_fw) || !rtl8125_fw_data_ok(rtl_fw)) { - release_firmware(rtl_fw->fw); - rc = -EINVAL; - goto out; - } - - return 0; -out: - dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n", - rtl_fw->fw_name, rc); - return rc; -} diff --git a/addons/r8125/src/4.4.180/r8125_firmware.h b/addons/r8125/src/4.4.180/r8125_firmware.h deleted file mode 100755 index df97bf9b..00000000 --- a/addons/r8125/src/4.4.180/r8125_firmware.h +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_rtl8125_FIRMWARE_H -#define _LINUX_rtl8125_FIRMWARE_H - -#include -#include - -struct rtl8125_private; -typedef void (*rtl8125_fw_write_t)(struct rtl8125_private *tp, u16 reg, u16 val); -typedef u32 (*rtl8125_fw_read_t)(struct rtl8125_private *tp, u16 reg); - -#define RTL8125_VER_SIZE 32 - -struct rtl8125_fw { - rtl8125_fw_write_t phy_write; - rtl8125_fw_read_t phy_read; - rtl8125_fw_write_t mac_mcu_write; - rtl8125_fw_read_t mac_mcu_read; - const struct firmware *fw; - const char *fw_name; - struct device *dev; - - char version[RTL8125_VER_SIZE]; - - struct rtl8125_fw_phy_action { - __le32 *code; - size_t size; - } phy_action; -}; - -int rtl8125_fw_request_firmware(struct rtl8125_fw *rtl_fw); -void rtl8125_fw_release_firmware(struct rtl8125_fw *rtl_fw); -void rtl8125_fw_write_firmware(struct rtl8125_private *tp, struct rtl8125_fw *rtl_fw); - -#endif /* _LINUX_rtl8125_FIRMWARE_H */ diff --git a/addons/r8125/src/4.4.180/r8125_n.c b/addons/r8125/src/4.4.180/r8125_n.c deleted file mode 100755 index 0bc5eec3..00000000 --- a/addons/r8125/src/4.4.180/r8125_n.c +++ /dev/null @@ -1,15803 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -/* - * This driver is modified from r8169.c in Linux kernel 2.6.18 - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) -#include -#include -#endif -#include -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0) -#include -#endif -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) -#include -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define dev_printk(A,B,fmt,args...) printk(A fmt,##args) -#else -#include -#include -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) -#include -#endif - -#include -#include - -#include "r8125.h" -#include "rtl_eeprom.h" -#include "rtltool.h" -#include "r8125_firmware.h" - -#ifdef ENABLE_R8125_PROCFS -#include -#include -#endif - -#define FIRMWARE_8125A_3 "rtl_nic/rtl8125a-3.fw" -#define FIRMWARE_8125B_2 "rtl_nic/rtl8125b-2.fw" - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -static const struct { - const char *name; - const char *fw_name; -} rtl_chip_fw_infos[] = { - /* PCI-E devices. */ - [CFG_METHOD_2] = {"RTL8125A" }, - [CFG_METHOD_3] = {"RTL8125A", FIRMWARE_8125A_3}, - [CFG_METHOD_4] = {"RTL8125B", }, - [CFG_METHOD_5] = {"RTL8125B", FIRMWARE_8125B_2}, - [CFG_METHOD_6] = {"RTL8168KB", FIRMWARE_8125A_3}, - [CFG_METHOD_7] = {"RTL8168KB", FIRMWARE_8125B_2}, - [CFG_METHOD_DEFAULT] = {"Unknown", }, -}; - -#define _R(NAME,MAC,RCR,MASK,JumFrameSz) \ - { .name = NAME, .mcfg = MAC, .RCR_Cfg = RCR, .RxConfigMask = MASK, .jumbo_frame_sz = JumFrameSz } - -static const struct { - const char *name; - u8 mcfg; - u32 RCR_Cfg; - u32 RxConfigMask; /* Clears the bits supported by this chip */ - u32 jumbo_frame_sz; -} rtl_chip_info[] = { - _R("RTL8125A", - CFG_METHOD_2, - BIT_30 | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8125A", - CFG_METHOD_3, - BIT_30 | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8125B", - CFG_METHOD_4, - BIT_30 | RxCfg_pause_slot_en | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8125B", - CFG_METHOD_5, - BIT_30 | RxCfg_pause_slot_en | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168KB", - CFG_METHOD_6, - BIT_30 | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168KB", - CFG_METHOD_7, - BIT_30 | RxCfg_pause_slot_en | EnableInnerVlan | EnableOuterVlan | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("Unknown", - CFG_METHOD_DEFAULT, - (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_1k) -}; -#undef _R - - -#ifndef PCI_VENDOR_ID_DLINK -#define PCI_VENDOR_ID_DLINK 0x1186 -#endif - -static struct pci_device_id rtl8125_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8125), }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8162), }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x3000), }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8125_pci_tbl); - -static int rx_copybreak = 0; -static int use_dac = 1; -static int timer_count = 0x2600; -static int timer_count_v2 = (0x2600 / 0x100); - -static struct { - u32 msg_enable; -} debug = { -1 }; - -static unsigned int speed_mode = SPEED_2500; -static unsigned int duplex_mode = DUPLEX_FULL; -static unsigned int autoneg_mode = AUTONEG_ENABLE; -static unsigned int advertising_mode = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_2500baseX_Full; -#ifdef CONFIG_ASPM -static int aspm = 1; -#else -static int aspm = 0; -#endif -#ifdef ENABLE_S5WOL -static int s5wol = 1; -#else -static int s5wol = 0; -#endif -#ifdef ENABLE_S5_KEEP_CURR_MAC -static int s5_keep_curr_mac = 1; -#else -static int s5_keep_curr_mac = 0; -#endif -#ifdef ENABLE_EEE -static int eee_enable = 1; -#else -static int eee_enable = 0; -#endif -#ifdef CONFIG_SOC_LAN -static ulong hwoptimize = HW_PATCH_SOC_LAN; -#else -static ulong hwoptimize = 0; -#endif -#ifdef ENABLE_S0_MAGIC_PACKET -static int s0_magic_packet = 1; -#else -static int s0_magic_packet = 0; -#endif -#ifdef ENABLE_TX_NO_CLOSE -static int tx_no_close_enable = 1; -#else -static int tx_no_close_enable = 0; -#endif -#ifdef ENABLE_PTP_MASTER_MODE -static int enable_ptp_master_mode = 1; -#else -static int enable_ptp_master_mode = 0; -#endif -#ifdef DISABLE_PM_SUPPORT -static int disable_pm_support = 1; -#else -static int disable_pm_support = 0; -#endif - -MODULE_AUTHOR("Realtek and the Linux r8125 crew "); -MODULE_DESCRIPTION("Realtek RTL8125 2.5Gigabit Ethernet driver"); - -module_param(speed_mode, uint, 0); -MODULE_PARM_DESC(speed_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(duplex_mode, uint, 0); -MODULE_PARM_DESC(duplex_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(autoneg_mode, uint, 0); -MODULE_PARM_DESC(autoneg_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(advertising_mode, uint, 0); -MODULE_PARM_DESC(advertising_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(aspm, int, 0); -MODULE_PARM_DESC(aspm, "Enable ASPM."); - -module_param(s5wol, int, 0); -MODULE_PARM_DESC(s5wol, "Enable Shutdown Wake On Lan."); - -module_param(s5_keep_curr_mac, int, 0); -MODULE_PARM_DESC(s5_keep_curr_mac, "Enable Shutdown Keep Current MAC Address."); - -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); - -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); - -module_param(timer_count, int, 0); -MODULE_PARM_DESC(timer_count, "Timer Interrupt Interval."); - -module_param(eee_enable, int, 0); -MODULE_PARM_DESC(eee_enable, "Enable Energy Efficient Ethernet."); - -module_param(hwoptimize, ulong, 0); -MODULE_PARM_DESC(hwoptimize, "Enable HW optimization function."); - -module_param(s0_magic_packet, int, 0); -MODULE_PARM_DESC(s0_magic_packet, "Enable S0 Magic Packet."); - -module_param(tx_no_close_enable, int, 0); -MODULE_PARM_DESC(tx_no_close_enable, "Enable TX No Close."); - -module_param(enable_ptp_master_mode, int, 0); -MODULE_PARM_DESC(enable_ptp_master_mode, "Enable PTP Master Mode."); - -module_param(disable_pm_support, int, 0); -MODULE_PARM_DESC(disable_pm_support, "Disable PM support."); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -#endif//LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - -MODULE_LICENSE("GPL"); -#ifdef ENABLE_USE_FIRMWARE_FILE -MODULE_FIRMWARE(FIRMWARE_8125A_3); -MODULE_FIRMWARE(FIRMWARE_8125B_2); -#endif - -MODULE_VERSION(RTL8125_VERSION); - -/* -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -static void rtl8125_esd_timer(unsigned long __opaque); -#else -static void rtl8125_esd_timer(struct timer_list *t); -#endif -*/ -/* -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -static void rtl8125_link_timer(unsigned long __opaque); -#else -static void rtl8125_link_timer(struct timer_list *t); -#endif -*/ - -static netdev_tx_t rtl8125_start_xmit(struct sk_buff *skb, struct net_device *dev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -#else -static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance, struct pt_regs *regs); -#else -static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance); -#endif -static void rtl8125_set_rx_mode(struct net_device *dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static void rtl8125_tx_timeout(struct net_device *dev, unsigned int txqueue); -#else -static void rtl8125_tx_timeout(struct net_device *dev); -#endif -static struct net_device_stats *rtl8125_get_stats(struct net_device *dev); -static int rtl8125_rx_interrupt(struct net_device *, struct rtl8125_private *, struct rtl8125_rx_ring *, napi_budget); -static int rtl8125_tx_interrupt(struct rtl8125_tx_ring *ring, int budget); -static int rtl8125_tx_interrupt_with_vector(struct rtl8125_private *tp, const int message_id, int budget); -static void rtl8125_wait_for_quiescence(struct net_device *dev); -static int rtl8125_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8125_down(struct net_device *dev); - -static int rtl8125_set_mac_address(struct net_device *dev, void *p); -static void rtl8125_rar_set(struct rtl8125_private *tp, const u8 *addr); -static void rtl8125_desc_addr_fill(struct rtl8125_private *); -static void rtl8125_tx_desc_init(struct rtl8125_private *tp); -static void rtl8125_rx_desc_init(struct rtl8125_private *tp); - -static u32 mdio_direct_read_phy_ocp(struct rtl8125_private *tp, u16 RegAddr); -static u16 rtl8125_get_hw_phy_mcu_code_ver(struct rtl8125_private *tp); -static void rtl8125_phy_power_up(struct net_device *dev); -static void rtl8125_phy_power_down(struct net_device *dev); -static int rtl8125_set_speed(struct net_device *dev, u8 autoneg, u32 speed, u8 duplex, u32 adv); -static bool rtl8125_set_phy_mcu_patch_request(struct rtl8125_private *tp); -static bool rtl8125_clear_phy_mcu_patch_request(struct rtl8125_private *tp); - -#ifdef CONFIG_R8125_NAPI -static int rtl8125_poll(napi_ptr napi, napi_budget budget); -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8125_reset_task(void *_data); -static void rtl8125_esd_task(void *_data); -static void rtl8125_linkchg_task(void *_data); -#else -static void rtl8125_reset_task(struct work_struct *work); -static void rtl8125_esd_task(struct work_struct *work); -static void rtl8125_linkchg_task(struct work_struct *work); -#endif -static void rtl8125_schedule_reset_work(struct rtl8125_private *tp); -static void rtl8125_schedule_esd_work(struct rtl8125_private *tp); -static void rtl8125_schedule_linkchg_work(struct rtl8125_private *tp); -static void rtl8125_init_all_schedule_work(struct rtl8125_private *tp); -static void rtl8125_cancel_all_schedule_work(struct rtl8125_private *tp); - -static inline struct device *tp_to_dev(struct rtl8125_private *tp) -{ - return &tp->pci_dev->dev; -} - -#if ((LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) && \ - LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,00))) -void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, - u32 legacy_u32) -{ - bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS); - dst[0] = legacy_u32; -} - -bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, - const unsigned long *src) -{ - bool retval = true; - - /* TODO: following test will soon always be true */ - if (__ETHTOOL_LINK_MODE_MASK_NBITS > 32) { - __ETHTOOL_DECLARE_LINK_MODE_MASK(ext); - - bitmap_zero(ext, __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_fill(ext, 32); - bitmap_complement(ext, ext, __ETHTOOL_LINK_MODE_MASK_NBITS); - if (bitmap_intersects(ext, src, - __ETHTOOL_LINK_MODE_MASK_NBITS)) { - /* src mask goes beyond bit 31 */ - retval = false; - } - } - *legacy_u32 = src[0]; - return retval; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - -#ifndef LPA_1000FULL -#define LPA_1000FULL 0x0800 -#endif - -#ifndef LPA_1000HALF -#define LPA_1000HALF 0x0400 -#endif - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) -static inline void eth_hw_addr_random(struct net_device *dev) -{ - random_ether_addr(dev->dev_addr); -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#undef ethtool_ops -#define ethtool_ops _kc_ethtool_ops - -struct _kc_ethtool_ops { - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - int (*set_settings)(struct net_device *, struct ethtool_cmd *); - void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); - int (*get_regs_len)(struct net_device *); - void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); - void (*get_wol)(struct net_device *, struct ethtool_wolinfo *); - int (*set_wol)(struct net_device *, struct ethtool_wolinfo *); - u32 (*get_msglevel)(struct net_device *); - void (*set_msglevel)(struct net_device *, u32); - int (*nway_reset)(struct net_device *); - u32 (*get_link)(struct net_device *); - int (*get_eeprom_len)(struct net_device *); - int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); - int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); - int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *); - int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *); - void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *); - int (*set_ringparam)(struct net_device *, struct ethtool_ringparam *); - void (*get_pauseparam)(struct net_device *, - struct ethtool_pauseparam*); - int (*set_pauseparam)(struct net_device *, - struct ethtool_pauseparam*); - u32 (*get_rx_csum)(struct net_device *); - int (*set_rx_csum)(struct net_device *, u32); - u32 (*get_tx_csum)(struct net_device *); - int (*set_tx_csum)(struct net_device *, u32); - u32 (*get_sg)(struct net_device *); - int (*set_sg)(struct net_device *, u32); - u32 (*get_tso)(struct net_device *); - int (*set_tso)(struct net_device *, u32); - int (*self_test_count)(struct net_device *); - void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); - void (*get_strings)(struct net_device *, u32 stringset, u8 *); - int (*phys_id)(struct net_device *, u32); - int (*get_stats_count)(struct net_device *); - void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, - u64 *); -} *ethtool_ops = NULL; - -#undef SET_ETHTOOL_OPS -#define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops)) - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) -#ifndef SET_ETHTOOL_OPS -#define SET_ETHTOOL_OPS(netdev,ops) \ - ( (netdev)->ethtool_ops = (ops) ) -#endif //SET_ETHTOOL_OPS -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) - -//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) -#ifndef netif_msg_init -#define netif_msg_init _kc_netif_msg_init -/* copied from linux kernel 2.6.20 include/linux/netdevice.h */ -static inline u32 netif_msg_init(int debug_value, int default_msg_enable_bits) -{ - /* use default */ - if (debug_value < 0 || debug_value >= (sizeof(u32) * 8)) - return default_msg_enable_bits; - if (debug_value == 0) /* no output */ - return 0; - /* set low N bits */ - return (1 << debug_value) - 1; -} - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) -static inline void eth_copy_and_sum (struct sk_buff *dest, - const unsigned char *src, - int len, int base) -{ - memcpy (dest->data, src, len); -} -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) -/* copied from linux kernel 2.6.20 /include/linux/time.h */ -/* Parameters used to convert the timespec values: */ -#define MSEC_PER_SEC 1000L - -/* copied from linux kernel 2.6.20 /include/linux/jiffies.h */ -/* - * Change timeval to jiffies, trying to avoid the - * most obvious overflows.. - * - * And some not so obvious. - * - * Note that we don't want to return MAX_LONG, because - * for various timeout reasons we often end up having - * to wait "jiffies+1" in order to guarantee that we wait - * at _least_ "jiffies" - so "jiffies+1" had better still - * be positive. - */ -#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1) - -/* - * Convert jiffies to milliseconds and back. - * - * Avoid unnecessary multiplications/divisions in the - * two most common HZ cases: - */ -static inline unsigned int _kc_jiffies_to_msecs(const unsigned long j) -{ -#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) - return (MSEC_PER_SEC / HZ) * j; -#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) - return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); -#else - return (j * MSEC_PER_SEC) / HZ; -#endif -} - -static inline unsigned long _kc_msecs_to_jiffies(const unsigned int m) -{ - if (m > _kc_jiffies_to_msecs(MAX_JIFFY_OFFSET)) - return MAX_JIFFY_OFFSET; -#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) - return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); -#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) - return m * (HZ / MSEC_PER_SEC); -#else - return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC; -#endif -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) - -/* copied from linux kernel 2.6.12.6 /include/linux/pm.h */ -typedef int __bitwise pci_power_t; - -/* copied from linux kernel 2.6.12.6 /include/linux/pci.h */ -typedef u32 __bitwise pm_message_t; - -#define PCI_D0 ((pci_power_t __force) 0) -#define PCI_D1 ((pci_power_t __force) 1) -#define PCI_D2 ((pci_power_t __force) 2) -#define PCI_D3hot ((pci_power_t __force) 3) -#define PCI_D3cold ((pci_power_t __force) 4) -#define PCI_POWER_ERROR ((pci_power_t __force) -1) - -/* copied from linux kernel 2.6.12.6 /drivers/pci/pci.c */ -/** - * pci_choose_state - Choose the power state of a PCI device - * @dev: PCI device to be suspended - * @state: target sleep state for the whole system. This is the value - * that is passed to suspend() function. - * - * Returns PCI power state suitable for given device and given system - * message. - */ - -pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) -{ - if (!pci_find_capability(dev, PCI_CAP_ID_PM)) - return PCI_D0; - - switch (state) { - case 0: - return PCI_D0; - case 3: - return PCI_D3hot; - default: - printk("They asked me for state %d\n", state); -// BUG(); - } - return PCI_D0; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -/** - * msleep_interruptible - sleep waiting for waitqueue interruptions - * @msecs: Time in milliseconds to sleep for - */ -#define msleep_interruptible _kc_msleep_interruptible -unsigned long _kc_msleep_interruptible(unsigned int msecs) -{ - unsigned long timeout = _kc_msecs_to_jiffies(msecs); - - while (timeout && !signal_pending(current)) { - set_current_state(TASK_INTERRUPTIBLE); - timeout = schedule_timeout(timeout); - } - return _kc_jiffies_to_msecs(timeout); -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) -/* copied from linux kernel 2.6.20 include/linux/sched.h */ -#ifndef __sched -#define __sched __attribute__((__section__(".sched.text"))) -#endif - -/* copied from linux kernel 2.6.20 kernel/timer.c */ -signed long __sched schedule_timeout_uninterruptible(signed long timeout) -{ - __set_current_state(TASK_UNINTERRUPTIBLE); - return schedule_timeout(timeout); -} - -/* copied from linux kernel 2.6.20 include/linux/mii.h */ -#undef if_mii -#define if_mii _kc_if_mii -static inline struct mii_ioctl_data *if_mii(struct ifreq *rq) -{ - return (struct mii_ioctl_data *) &rq->ifr_ifru; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) - -static u32 rtl8125_read_thermal_sensor(struct rtl8125_private *tp) -{ - u16 ts_digout; - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - ts_digout = mdio_direct_read_phy_ocp(tp, 0xBD84); - ts_digout &= 0x3ff; - break; - default: - ts_digout = 0xffff; - break; - } - - return ts_digout; -} - -int rtl8125_dump_tally_counter(struct rtl8125_private *tp, dma_addr_t paddr) -{ - u32 cmd; - u32 WaitCnt; - int retval = -1; - - RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(tp, CounterAddrLow, cmd); - RTL_W32(tp, CounterAddrLow, cmd | CounterDump); - - WaitCnt = 0; - while (RTL_R32(tp, CounterAddrLow) & CounterDump) { - udelay(10); - - WaitCnt++; - if (WaitCnt > 20) - break; - } - - if (WaitCnt <= 20) - retval = 0; - - return retval; -} - -#ifdef ENABLE_R8125_PROCFS -/**************************************************************************** -* -----------------------------PROCFS STUFF------------------------- -***************************************************************************** -*/ - -static struct proc_dir_entry *rtl8125_proc; -static int proc_init_num = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -static int proc_get_driver_variable(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct rtl8125_private *tp = netdev_priv(dev); - - seq_puts(m, "\nDump Driver Variable\n"); - - rtnl_lock(); - - seq_puts(m, "Variable\tValue\n----------\t-----\n"); - seq_printf(m, "MODULENAME\t%s\n", MODULENAME); - seq_printf(m, "driver version\t%s\n", RTL8125_VERSION); - seq_printf(m, "mcfg\t%d\n", tp->mcfg); - seq_printf(m, "chipset\t%d\n", tp->chipset); - seq_printf(m, "chipset_name\t%s\n", rtl_chip_info[tp->chipset].name); - seq_printf(m, "mtu\t%d\n", dev->mtu); - seq_printf(m, "NUM_RX_DESC\t0x%x\n", tp->rx_ring[0].num_rx_desc); - seq_printf(m, "cur_rx0\t0x%x\n", tp->rx_ring[0].cur_rx); - seq_printf(m, "dirty_rx0\t0x%x\n", tp->rx_ring[0].dirty_rx); - seq_printf(m, "cur_rx1\t0x%x\n", tp->rx_ring[1].cur_rx); - seq_printf(m, "dirty_rx1\t0x%x\n", tp->rx_ring[1].dirty_rx); - seq_printf(m, "cur_rx2\t0x%x\n", tp->rx_ring[2].cur_rx); - seq_printf(m, "dirty_rx2\t0x%x\n", tp->rx_ring[2].dirty_rx); - seq_printf(m, "cur_rx3\t0x%x\n", tp->rx_ring[3].cur_rx); - seq_printf(m, "dirty_rx3\t0x%x\n", tp->rx_ring[3].dirty_rx); - seq_printf(m, "NUM_TX_DESC\t0x%x\n", tp->tx_ring[0].num_tx_desc); - seq_printf(m, "cur_tx0\t0x%x\n", tp->tx_ring[0].cur_tx); - seq_printf(m, "dirty_tx0\t0x%x\n", tp->tx_ring[0].dirty_tx); - seq_printf(m, "cur_tx1\t0x%x\n", tp->tx_ring[1].cur_tx); - seq_printf(m, "dirty_tx1\t0x%x\n", tp->tx_ring[1].dirty_tx); - seq_printf(m, "rx_buf_sz\t0x%x\n", tp->rx_buf_sz); - seq_printf(m, "esd_flag\t0x%x\n", tp->esd_flag); - seq_printf(m, "pci_cfg_is_read\t0x%x\n", tp->pci_cfg_is_read); - seq_printf(m, "rtl8125_rx_config\t0x%x\n", tp->rtl8125_rx_config); - seq_printf(m, "cp_cmd\t0x%x\n", tp->cp_cmd); - seq_printf(m, "intr_mask\t0x%x\n", tp->intr_mask); - seq_printf(m, "timer_intr_mask\t0x%x\n", tp->timer_intr_mask); - seq_printf(m, "wol_enabled\t0x%x\n", tp->wol_enabled); - seq_printf(m, "wol_opts\t0x%x\n", tp->wol_opts); - seq_printf(m, "efuse_ver\t0x%x\n", tp->efuse_ver); - seq_printf(m, "eeprom_type\t0x%x\n", tp->eeprom_type); - seq_printf(m, "autoneg\t0x%x\n", tp->autoneg); - seq_printf(m, "duplex\t0x%x\n", tp->duplex); - seq_printf(m, "speed\t%d\n", tp->speed); - seq_printf(m, "advertising\t0x%x\n", tp->advertising); - seq_printf(m, "eeprom_len\t0x%x\n", tp->eeprom_len); - seq_printf(m, "cur_page\t0x%x\n", tp->cur_page); - seq_printf(m, "bios_setting\t0x%x\n", tp->bios_setting); - seq_printf(m, "features\t0x%x\n", tp->features); - seq_printf(m, "org_pci_offset_99\t0x%x\n", tp->org_pci_offset_99); - seq_printf(m, "org_pci_offset_180\t0x%x\n", tp->org_pci_offset_180); - seq_printf(m, "issue_offset_99_event\t0x%x\n", tp->issue_offset_99_event); - seq_printf(m, "org_pci_offset_80\t0x%x\n", tp->org_pci_offset_80); - seq_printf(m, "org_pci_offset_81\t0x%x\n", tp->org_pci_offset_81); - seq_printf(m, "use_timer_interrrupt\t0x%x\n", tp->use_timer_interrrupt); - seq_printf(m, "HwIcVerUnknown\t0x%x\n", tp->HwIcVerUnknown); - seq_printf(m, "NotWrRamCodeToMicroP\t0x%x\n", tp->NotWrRamCodeToMicroP); - seq_printf(m, "NotWrMcuPatchCode\t0x%x\n", tp->NotWrMcuPatchCode); - seq_printf(m, "HwHasWrRamCodeToMicroP\t0x%x\n", tp->HwHasWrRamCodeToMicroP); - seq_printf(m, "sw_ram_code_ver\t0x%x\n", tp->sw_ram_code_ver); - seq_printf(m, "hw_ram_code_ver\t0x%x\n", tp->hw_ram_code_ver); - seq_printf(m, "rtk_enable_diag\t0x%x\n", tp->rtk_enable_diag); - seq_printf(m, "ShortPacketSwChecksum\t0x%x\n", tp->ShortPacketSwChecksum); - seq_printf(m, "UseSwPaddingShortPkt\t0x%x\n", tp->UseSwPaddingShortPkt); - seq_printf(m, "RequireRduNonStopPatch\t0x%x\n", tp->RequireRduNonStopPatch); - seq_printf(m, "RequireAdcBiasPatch\t0x%x\n", tp->RequireAdcBiasPatch); - seq_printf(m, "AdcBiasPatchIoffset\t0x%x\n", tp->AdcBiasPatchIoffset); - seq_printf(m, "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n", tp->RequireAdjustUpsTxLinkPulseTiming); - seq_printf(m, "SwrCnt1msIni\t0x%x\n", tp->SwrCnt1msIni); - seq_printf(m, "HwSuppNowIsOobVer\t0x%x\n", tp->HwSuppNowIsOobVer); - seq_printf(m, "HwFiberModeVer\t0x%x\n", tp->HwFiberModeVer); - seq_printf(m, "HwFiberStat\t0x%x\n", tp->HwFiberStat); - seq_printf(m, "HwSwitchMdiToFiber\t0x%x\n", tp->HwSwitchMdiToFiber); - seq_printf(m, "NicCustLedValue\t0x%x\n", tp->NicCustLedValue); - seq_printf(m, "RequiredSecLanDonglePatch\t0x%x\n", tp->RequiredSecLanDonglePatch); - seq_printf(m, "HwSuppDashVer\t0x%x\n", tp->HwSuppDashVer); - seq_printf(m, "DASH\t0x%x\n", tp->DASH); - seq_printf(m, "dash_printer_enabled\t0x%x\n", tp->dash_printer_enabled); - seq_printf(m, "HwSuppKCPOffloadVer\t0x%x\n", tp->HwSuppKCPOffloadVer); - seq_printf(m, "speed_mode\t0x%x\n", speed_mode); - seq_printf(m, "duplex_mode\t0x%x\n", duplex_mode); - seq_printf(m, "autoneg_mode\t0x%x\n", autoneg_mode); - seq_printf(m, "advertising_mode\t0x%x\n", advertising_mode); - seq_printf(m, "aspm\t0x%x\n", aspm); - seq_printf(m, "s5wol\t0x%x\n", s5wol); - seq_printf(m, "s5_keep_curr_mac\t0x%x\n", s5_keep_curr_mac); - seq_printf(m, "eee_enable\t0x%x\n", tp->eee.eee_enabled); - seq_printf(m, "hwoptimize\t0x%lx\n", hwoptimize); - seq_printf(m, "proc_init_num\t0x%x\n", proc_init_num); - seq_printf(m, "s0_magic_packet\t0x%x\n", s0_magic_packet); - seq_printf(m, "HwSuppMagicPktVer\t0x%x\n", tp->HwSuppMagicPktVer); - seq_printf(m, "HwSuppLinkChgWakeUpVer\t0x%x\n", tp->HwSuppLinkChgWakeUpVer); - seq_printf(m, "HwSuppD0SpeedUpVer\t0x%x\n", tp->HwSuppD0SpeedUpVer); - seq_printf(m, "D0SpeedUpSpeed\t0x%x\n", tp->D0SpeedUpSpeed); - seq_printf(m, "HwSuppCheckPhyDisableModeVer\t0x%x\n", tp->HwSuppCheckPhyDisableModeVer); - seq_printf(m, "HwPkgDet\t0x%x\n", tp->HwPkgDet); - seq_printf(m, "HwSuppTxNoCloseVer\t0x%x\n", tp->HwSuppTxNoCloseVer); - seq_printf(m, "EnableTxNoClose\t0x%x\n", tp->EnableTxNoClose); - seq_printf(m, "NextHwDesCloPtr0\t0x%x\n", tp->tx_ring[0].NextHwDesCloPtr); - seq_printf(m, "BeginHwDesCloPtr0\t0x%x\n", tp->tx_ring[0].BeginHwDesCloPtr); - seq_printf(m, "NextHwDesCloPtr1\t0x%x\n", tp->tx_ring[1].NextHwDesCloPtr); - seq_printf(m, "BeginHwDesCloPtr1\t0x%x\n", tp->tx_ring[1].BeginHwDesCloPtr); - seq_printf(m, "InitRxDescType\t0x%x\n", tp->InitRxDescType); - seq_printf(m, "RxDescLength\t0x%x\n", tp->RxDescLength); - seq_printf(m, "num_rx_rings\t0x%x\n", tp->num_rx_rings); - seq_printf(m, "num_tx_rings\t0x%x\n", tp->num_tx_rings); - seq_printf(m, "tot_rx_rings\t0x%x\n", rtl8125_tot_rx_rings(tp)); - seq_printf(m, "tot_tx_rings\t0x%x\n", rtl8125_tot_tx_rings(tp)); - seq_printf(m, "EnableRss\t0x%x\n", tp->EnableRss); - seq_printf(m, "EnablePtp\t0x%x\n", tp->EnablePtp); - seq_printf(m, "ptp_master_mode\t0x%x\n", tp->ptp_master_mode); - seq_printf(m, "min_irq_nvecs\t0x%x\n", tp->min_irq_nvecs); - seq_printf(m, "irq_nvecs\t0x%x\n", tp->irq_nvecs); - seq_printf(m, "ring_lib_enabled\t0x%x\n", tp->ring_lib_enabled); - seq_printf(m, "HwSuppIsrVer\t0x%x\n", tp->HwSuppIsrVer); - seq_printf(m, "HwCurrIsrVer\t0x%x\n", tp->HwCurrIsrVer); -#ifdef ENABLE_PTP_SUPPORT - seq_printf(m, "tx_hwtstamp_timeouts\t0x%x\n", tp->tx_hwtstamp_timeouts); - seq_printf(m, "tx_hwtstamp_skipped\t0x%x\n", tp->tx_hwtstamp_skipped); -#endif - seq_printf(m, "random_mac\t0x%x\n", tp->random_mac); - seq_printf(m, "org_mac_addr\t%pM\n", tp->org_mac_addr); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - seq_printf(m, "perm_addr\t%pM\n", dev->perm_addr); -#endif - seq_printf(m, "dev_addr\t%pM\n", dev->dev_addr); - - rtnl_unlock(); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_tally_counter(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct rtl8125_private *tp = netdev_priv(dev); - struct rtl8125_counters *counters; - dma_addr_t paddr; - - seq_puts(m, "\nDump Tally Counter\n"); - - rtnl_lock(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) { - seq_puts(m, "\nDump Tally Counter Fail\n"); - goto out_unlock; - } - - rtl8125_dump_tally_counter(tp, paddr); - - seq_puts(m, "Statistics\tValue\n----------\t-----\n"); - seq_printf(m, "tx_packets\t%lld\n", le64_to_cpu(counters->tx_packets)); - seq_printf(m, "rx_packets\t%lld\n", le64_to_cpu(counters->rx_packets)); - seq_printf(m, "tx_errors\t%lld\n", le64_to_cpu(counters->tx_errors)); - seq_printf(m, "rx_errors\t%d\n", le32_to_cpu(counters->rx_errors)); - seq_printf(m, "rx_missed\t%d\n", le16_to_cpu(counters->rx_missed)); - seq_printf(m, "align_errors\t%d\n", le16_to_cpu(counters->align_errors)); - seq_printf(m, "tx_one_collision\t%d\n", le32_to_cpu(counters->tx_one_collision)); - seq_printf(m, "tx_multi_collision\t%d\n", le32_to_cpu(counters->tx_multi_collision)); - seq_printf(m, "rx_unicast\t%lld\n", le64_to_cpu(counters->rx_unicast)); - seq_printf(m, "rx_broadcast\t%lld\n", le64_to_cpu(counters->rx_broadcast)); - seq_printf(m, "rx_multicast\t%d\n", le32_to_cpu(counters->rx_multicast)); - seq_printf(m, "tx_aborted\t%d\n", le16_to_cpu(counters->tx_aborted)); - seq_printf(m, "tx_underrun\t%d\n", le16_to_cpu(counters->tx_underrun)); - - seq_printf(m, "tx_octets\t%lld\n", le64_to_cpu(counters->tx_octets)); - seq_printf(m, "rx_octets\t%lld\n", le64_to_cpu(counters->rx_octets)); - seq_printf(m, "rx_multicast64\t%lld\n", le64_to_cpu(counters->rx_multicast64)); - seq_printf(m, "tx_unicast64\t%lld\n", le64_to_cpu(counters->tx_unicast64)); - seq_printf(m, "tx_broadcast64\t%lld\n", le64_to_cpu(counters->tx_broadcast64)); - seq_printf(m, "tx_multicast64\t%lld\n", le64_to_cpu(counters->tx_multicast64)); - seq_printf(m, "tx_pause_on\t%d\n", le32_to_cpu(counters->tx_pause_on)); - seq_printf(m, "tx_pause_off\t%d\n", le32_to_cpu(counters->tx_pause_off)); - seq_printf(m, "tx_pause_all\t%d\n", le32_to_cpu(counters->tx_pause_all)); - seq_printf(m, "tx_deferred\t%d\n", le32_to_cpu(counters->tx_deferred)); - seq_printf(m, "tx_late_collision\t%d\n", le32_to_cpu(counters->tx_late_collision)); - seq_printf(m, "tx_all_collision\t%d\n", le32_to_cpu(counters->tx_all_collision)); - seq_printf(m, "tx_aborted32\t%d\n", le32_to_cpu(counters->tx_aborted32)); - seq_printf(m, "align_errors32\t%d\n", le32_to_cpu(counters->align_errors32)); - seq_printf(m, "rx_frame_too_long\t%d\n", le32_to_cpu(counters->rx_frame_too_long)); - seq_printf(m, "rx_runt\t%d\n", le32_to_cpu(counters->rx_runt)); - seq_printf(m, "rx_pause_on\t%d\n", le32_to_cpu(counters->rx_pause_on)); - seq_printf(m, "rx_pause_off\t%d\n", le32_to_cpu(counters->rx_pause_off)); - seq_printf(m, "rx_pause_all\t%d\n", le32_to_cpu(counters->rx_pause_all)); - seq_printf(m, "rx_unknown_opcode\t%d\n", le32_to_cpu(counters->rx_unknown_opcode)); - seq_printf(m, "rx_mac_error\t%d\n", le32_to_cpu(counters->rx_mac_error)); - seq_printf(m, "tx_underrun32\t%d\n", le32_to_cpu(counters->tx_underrun32)); - seq_printf(m, "rx_mac_missed\t%d\n", le32_to_cpu(counters->rx_mac_missed)); - seq_printf(m, "rx_tcam_dropped\t%d\n", le32_to_cpu(counters->rx_tcam_dropped)); - seq_printf(m, "tdu\t%d\n", le32_to_cpu(counters->tdu)); - seq_printf(m, "rdu\t%d\n", le32_to_cpu(counters->rdu)); - - seq_putc(m, '\n'); - -out_unlock: - rtnl_unlock(); - - return 0; -} - -static int proc_get_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_MAC_REGS_SIZE; - u8 byte_rd; - struct rtl8125_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - seq_puts(m, "\nDump MAC Registers\n"); - seq_puts(m, "Offset\tValue\n------\t-----\n"); - - rtnl_lock(); - - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 16 && n < max; i++, n++) { - byte_rd = readb(ioaddr + n); - seq_printf(m, "%02x ", byte_rd); - } - } - - rtnl_unlock(); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_pcie_phy(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_EPHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8125_private *tp = netdev_priv(dev); - - seq_puts(m, "\nDump PCIE PHY\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - rtnl_lock(); - - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8125_ephy_read(tp, n); - seq_printf(m, "%04x ", word_rd); - } - } - - rtnl_unlock(); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_eth_phy(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_PHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8125_private *tp = netdev_priv(dev); - - seq_puts(m, "\nDump Ethernet PHY\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - rtnl_lock(); - - seq_puts(m, "\n####################page 0##################\n "); - rtl8125_mdio_write(tp, 0x1f, 0x0000); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8125_mdio_read(tp, n); - seq_printf(m, "%04x ", word_rd); - } - } - - rtnl_unlock(); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_extended_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_ERI_REGS_SIZE; - u32 dword_rd; - struct rtl8125_private *tp = netdev_priv(dev); - - seq_puts(m, "\nDump Extended Registers\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - rtnl_lock(); - - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - dword_rd = rtl8125_eri_read(tp, n, 4, ERIAR_ExGMAC); - seq_printf(m, "%08x ", dword_rd); - } - } - - rtnl_unlock(); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_pci_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8125_PCI_REGS_SIZE; - u32 dword_rd; - struct rtl8125_private *tp = netdev_priv(dev); - - seq_puts(m, "\nDump PCI Registers\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - rtnl_lock(); - - for (n = 0; n < max;) { - seq_printf(m, "\n0x%03x:\t", n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "%08x ", dword_rd); - } - } - - n = 0x110; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); - n = 0x70c; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); - - rtnl_unlock(); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_temperature(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct rtl8125_private *tp = netdev_priv(dev); - u16 ts_digout, tj, fah; - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - seq_puts(m, "\nChip Temperature\n"); - break; - default: - seq_puts(m, "\nThis Chip Does Not Support Dump Temperature\n"); - break; - } - - rtnl_lock(); - ts_digout = rtl8125_read_thermal_sensor(tp); - rtnl_unlock(); - - tj = ts_digout / 2; - if (ts_digout <= 512) { - tj = ts_digout / 2; - seq_printf(m, "Cel:%d\n", tj); - fah = tj * (9/5) + 32; - seq_printf(m, "Fah:%d\n", fah); - } else { - tj = (512 - ((ts_digout / 2) - 512)) / 2; - seq_printf(m, "Cel:-%d\n", tj); - fah = tj * (9/5) + 32; - seq_printf(m, "Fah:-%d\n", fah); - } - - seq_putc(m, '\n'); - return 0; -} -#else - -static int proc_get_driver_variable(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct rtl8125_private *tp = netdev_priv(dev); - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Driver Driver\n"); - - rtnl_lock(); - - len += snprintf(page + len, count - len, - "Variable\tValue\n----------\t-----\n"); - - len += snprintf(page + len, count - len, - "MODULENAME\t%s\n" - "driver version\t%s\n" - "mcfg\t%d\n" - "chipset\t%d\n" - "chipset_name\t%s\n" - "mtu\t%d\n" - "NUM_RX_DESC\t0x%x\n" - "cur_rx0\t0x%x\n" - "dirty_rx0\t0x%x\n" - "cur_rx1\t0x%x\n" - "dirty_rx1\t0x%x\n" - "cur_rx2\t0x%x\n" - "dirty_rx2\t0x%x\n" - "cur_rx3\t0x%x\n" - "dirty_rx3\t0x%x\n" - "NUM_TX_DESC\t0x%x\n" - "cur_tx0\t0x%x\n" - "dirty_tx0\t0x%x\n" - "cur_tx1\t0x%x\n" - "dirty_tx1\t0x%x\n" - "rx_buf_sz\t0x%x\n" - "esd_flag\t0x%x\n" - "pci_cfg_is_read\t0x%x\n" - "rtl8125_rx_config\t0x%x\n" - "cp_cmd\t0x%x\n" - "intr_mask\t0x%x\n" - "timer_intr_mask\t0x%x\n" - "wol_enabled\t0x%x\n" - "wol_opts\t0x%x\n" - "efuse_ver\t0x%x\n" - "eeprom_type\t0x%x\n" - "autoneg\t0x%x\n" - "duplex\t0x%x\n" - "speed\t%d\n" - "advertising\t0x%x\n" - "eeprom_len\t0x%x\n" - "cur_page\t0x%x\n" - "bios_setting\t0x%x\n" - "features\t0x%x\n" - "org_pci_offset_99\t0x%x\n" - "org_pci_offset_180\t0x%x\n" - "issue_offset_99_event\t0x%x\n" - "org_pci_offset_80\t0x%x\n" - "org_pci_offset_81\t0x%x\n" - "use_timer_interrrupt\t0x%x\n" - "HwIcVerUnknown\t0x%x\n" - "NotWrRamCodeToMicroP\t0x%x\n" - "NotWrMcuPatchCode\t0x%x\n" - "HwHasWrRamCodeToMicroP\t0x%x\n" - "sw_ram_code_ver\t0x%x\n" - "hw_ram_code_ver\t0x%x\n" - "rtk_enable_diag\t0x%x\n" - "ShortPacketSwChecksum\t0x%x\n" - "UseSwPaddingShortPkt\t0x%x\n" - "RequireRduNonStopPatch\t0x%x\n" - "RequireAdcBiasPatch\t0x%x\n" - "AdcBiasPatchIoffset\t0x%x\n" - "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n" - "SwrCnt1msIni\t0x%x\n" - "HwSuppNowIsOobVer\t0x%x\n" - "HwFiberModeVer\t0x%x\n" - "HwFiberStat\t0x%x\n" - "HwSwitchMdiToFiber\t0x%x\n" - "NicCustLedValue\t0x%x\n" - "RequiredSecLanDonglePatch\t0x%x\n" - "HwSuppDashVer\t0x%x\n" - "DASH\t0x%x\n" - "dash_printer_enabled\t0x%x\n" - "HwSuppKCPOffloadVer\t0x%x\n" - "speed_mode\t0x%x\n" - "duplex_mode\t0x%x\n" - "autoneg_mode\t0x%x\n" - "advertising_mode\t0x%x\n" - "aspm\t0x%x\n" - "s5wol\t0x%x\n" - "s5_keep_curr_mac\t0x%x\n" - "eee_enable\t0x%x\n" - "hwoptimize\t0x%lx\n" - "proc_init_num\t0x%x\n" - "s0_magic_packet\t0x%x\n" - "HwSuppMagicPktVer\t0x%x\n" - "HwSuppLinkChgWakeUpVer\t0x%x\n" - "HwSuppD0SpeedUpVer\t0x%x\n" - "D0SpeedUpSpeed\t0x%x\n" - "HwSuppCheckPhyDisableModeVer\t0x%x\n" - "HwPkgDet\t0x%x\n" - "HwSuppTxNoCloseVer\t0x%x\n" - "EnableTxNoClose\t0x%x\n" - "NextHwDesCloPtr0\t0x%x\n" - "BeginHwDesCloPtr0\t0x%x\n" - "NextHwDesCloPtr1\t0x%x\n" - "BeginHwDesCloPtr1\t0x%x\n" - "InitRxDescType\t0x%x\n" - "RxDescLength\t0x%x\n" - "num_rx_rings\t0x%x\n" - "num_tx_rings\t0x%x\n" - "tot_rx_rings\t0x%x\n" - "tot_tx_rings\t0x%x\n" - "EnableRss\t0x%x\n" - "EnablePtp\t0x%x\n" - "ptp_master_mode\t0x%x\n" - "min_irq_nvecs\t0x%x\n" - "irq_nvecs\t0x%x\n" - "ring_lib_enabled\t0x%x\n" - "HwSuppIsrVer\t0x%x\n" - "HwCurrIsrVer\t0x%x\n" -#ifdef ENABLE_PTP_SUPPORT - "tx_hwtstamp_timeouts\t0x%x\n" - "tx_hwtstamp_skipped\t0x%x\n" -#endif - "random_mac\t0x%x\n" - "org_mac_addr\t%pM\n" -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - "perm_addr\t%pM\n" -#endif - "dev_addr\t%pM\n", - MODULENAME, - RTL8125_VERSION, - tp->mcfg, - tp->chipset, - rtl_chip_info[tp->chipset].name, - dev->mtu, - tp->rx_ring[0].num_rx_desc, - tp->rx_ring[0].cur_rx, - tp->rx_ring[0].dirty_rx, - tp->rx_ring[1].cur_rx, - tp->rx_ring[1].dirty_rx, - tp->rx_ring[2].cur_rx, - tp->rx_ring[2].dirty_rx, - tp->rx_ring[3].cur_rx, - tp->rx_ring[3].dirty_rx, - tp->tx_ring[0].num_tx_desc, - tp->tx_ring[0].cur_tx, - tp->tx_ring[0].dirty_tx, - tp->tx_ring[1].cur_tx, - tp->tx_ring[1].dirty_tx, - tp->rx_buf_sz, - tp->esd_flag, - tp->pci_cfg_is_read, - tp->rtl8125_rx_config, - tp->cp_cmd, - tp->intr_mask, - tp->timer_intr_mask, - tp->wol_enabled, - tp->wol_opts, - tp->efuse_ver, - tp->eeprom_type, - tp->autoneg, - tp->duplex, - tp->speed, - tp->advertising, - tp->eeprom_len, - tp->cur_page, - tp->bios_setting, - tp->features, - tp->org_pci_offset_99, - tp->org_pci_offset_180, - tp->issue_offset_99_event, - tp->org_pci_offset_80, - tp->org_pci_offset_81, - tp->use_timer_interrrupt, - tp->HwIcVerUnknown, - tp->NotWrRamCodeToMicroP, - tp->NotWrMcuPatchCode, - tp->HwHasWrRamCodeToMicroP, - tp->sw_ram_code_ver, - tp->hw_ram_code_ver, - tp->rtk_enable_diag, - tp->ShortPacketSwChecksum, - tp->UseSwPaddingShortPkt, - tp->RequireRduNonStopPatch, - tp->RequireAdcBiasPatch, - tp->AdcBiasPatchIoffset, - tp->RequireAdjustUpsTxLinkPulseTiming, - tp->SwrCnt1msIni, - tp->HwSuppNowIsOobVer, - tp->HwFiberModeVer, - tp->HwFiberStat, - tp->HwSwitchMdiToFiber, - tp->NicCustLedValue, - tp->RequiredSecLanDonglePatch, - tp->HwSuppDashVer, - tp->DASH, - tp->dash_printer_enabled, - tp->HwSuppKCPOffloadVer, - speed_mode, - duplex_mode, - autoneg_mode, - advertising_mode, - aspm, - s5wol, - s5_keep_curr_mac, - tp->eee.eee_enabled, - hwoptimize, - proc_init_num, - s0_magic_packet, - tp->HwSuppMagicPktVer, - tp->HwSuppLinkChgWakeUpVer, - tp->HwSuppD0SpeedUpVer, - tp->D0SpeedUpSpeed, - tp->HwSuppCheckPhyDisableModeVer, - tp->HwPkgDet, - tp->HwSuppTxNoCloseVer, - tp->EnableTxNoClose, - tp->tx_ring[0].NextHwDesCloPtr, - tp->tx_ring[0].BeginHwDesCloPtr, - tp->tx_ring[1].NextHwDesCloPtr, - tp->tx_ring[1].BeginHwDesCloPtr, - tp->InitRxDescType, - tp->RxDescLength, - tp->num_rx_rings, - tp->num_tx_rings, - tp->tot_rx_rings, - tp->tot_tx_rings, - tp->EnableRss, - tp->EnablePtp, - tp->ptp_master_mode, - tp->min_irq_nvecs, - tp->irq_nvecs, - tp->ring_lib_enabled, - tp->HwSuppIsrVer, - tp->HwCurrIsrVer, -#ifdef ENABLE_PTP_SUPPORT - tp->tx_hwtstamp_timeouts, - tp->tx_hwtstamp_skipped, -#endif - tp->random_mac, - tp->org_mac_addr, -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - dev->perm_addr, -#endif - dev->dev_addr - ); - - rtnl_unlock(); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_tally_counter(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct rtl8125_private *tp = netdev_priv(dev); - struct rtl8125_counters *counters; - dma_addr_t paddr; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Tally Counter\n"); - - rtnl_lock(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) { - len += snprintf(page + len, count - len, - "\nDump Tally Counter Fail\n"); - goto out_unlock; - } - - rtl8125_dump_tally_counter(tp, paddr); - - len += snprintf(page + len, count - len, - "Statistics\tValue\n----------\t-----\n"); - - len += snprintf(page + len, count - len, - "tx_packets\t%lld\n" - "rx_packets\t%lld\n" - "tx_errors\t%lld\n" - "rx_errors\t%d\n" - "rx_missed\t%d\n" - "align_errors\t%d\n" - "tx_one_collision\t%d\n" - "tx_multi_collision\t%d\n" - "rx_unicast\t%lld\n" - "rx_broadcast\t%lld\n" - "rx_multicast\t%d\n" - "tx_aborted\t%d\n" - "tx_underrun\t%d\n", - - "tx_octets\t%lld\n", - "rx_octets\t%lld\n", - "rx_multicast64\t%lld\n", - "tx_unicast64\t%lld\n", - "tx_broadcast64\t%lld\n", - "tx_multicast64\t%lld\n", - "tx_pause_on\t%d\n", - "tx_pause_off\t%d\n", - "tx_pause_all\t%d\n", - "tx_deferred\t%d\n", - "tx_late_collision\t%d\n", - "tx_all_collision\t%d\n", - "tx_aborted32\t%d\n", - "align_errors32\t%d\n", - "rx_frame_too_long\t%d\n", - "rx_runt\t%d\n", - "rx_pause_on\t%d\n", - "rx_pause_off\t%d\n", - "rx_pause_all\t%d\n", - "rx_unknown_opcode\t%d\n", - "rx_mac_error\t%d\n", - "tx_underrun32\t%d\n", - "rx_mac_missed\t%d\n", - "rx_tcam_dropped\t%d\n", - "tdu\t%d\n", - "rdu\t%d\n", - le64_to_cpu(counters->tx_packets), - le64_to_cpu(counters->rx_packets), - le64_to_cpu(counters->tx_errors), - le32_to_cpu(counters->rx_errors), - le16_to_cpu(counters->rx_missed), - le16_to_cpu(counters->align_errors), - le32_to_cpu(counters->tx_one_collision), - le32_to_cpu(counters->tx_multi_collision), - le64_to_cpu(counters->rx_unicast), - le64_to_cpu(counters->rx_broadcast), - le32_to_cpu(counters->rx_multicast), - le16_to_cpu(counters->tx_aborted), - le16_to_cpu(counters->tx_underrun), - - le64_to_cpu(counters->tx_octets), - le64_to_cpu(counters->rx_octets), - le64_to_cpu(counters->rx_multicast64), - le64_to_cpu(counters->tx_unicast64), - le64_to_cpu(counters->tx_broadcast64), - le64_to_cpu(counters->tx_multicast64), - le32_to_cpu(counters->tx_pause_on), - le32_to_cpu(counters->tx_pause_off), - le32_to_cpu(counters->tx_pause_all), - le32_to_cpu(counters->tx_deferred), - le32_to_cpu(counters->tx_late_collision), - le32_to_cpu(counters->tx_all_collision), - le32_to_cpu(counters->tx_aborted32), - le32_to_cpu(counters->align_errors32), - le32_to_cpu(counters->rx_frame_too_long), - le32_to_cpu(counters->rx_runt), - le32_to_cpu(counters->rx_pause_on), - le32_to_cpu(counters->rx_pause_off), - le32_to_cpu(counters->rx_pause_all), - le32_to_cpu(counters->rx_unknown_opcode), - le32_to_cpu(counters->rx_mac_error), - le32_to_cpu(counters->tx_underrun32), - le32_to_cpu(counters->rx_mac_missed), - le32_to_cpu(counters->rx_tcam_dropped), - le32_to_cpu(counters->tdu), - le32_to_cpu(counters->rdu), - ); - - len += snprintf(page + len, count - len, "\n"); -out_unlock: - rtnl_unlock(); - - *eof = 1; - return len; -} - -static int proc_get_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_MAC_REGS_SIZE; - u8 byte_rd; - struct rtl8125_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump MAC Registers\n" - "Offset\tValue\n------\t-----\n"); - - rtnl_lock(); - - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 16 && n < max; i++, n++) { - byte_rd = readb(ioaddr + n); - len += snprintf(page + len, count - len, - "%02x ", - byte_rd); - } - } - - rtnl_unlock(); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_pcie_phy(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_EPHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8125_private *tp = netdev_priv(dev); - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump PCIE PHY\n" - "Offset\tValue\n------\t-----\n"); - - rtnl_lock(); - - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8125_ephy_read(tp, n); - len += snprintf(page + len, count - len, - "%04x ", - word_rd); - } - } - - rtnl_unlock(); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_eth_phy(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_PHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8125_private *tp = netdev_priv(dev); - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Ethernet PHY\n" - "Offset\tValue\n------\t-----\n"); - - rtnl_lock(); - - len += snprintf(page + len, count - len, - "\n####################page 0##################\n"); - rtl8125_mdio_write(tp, 0x1f, 0x0000); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8125_mdio_read(tp, n); - len += snprintf(page + len, count - len, - "%04x ", - word_rd); - } - } - - rtnl_unlock(); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_extended_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_ERI_REGS_SIZE; - u32 dword_rd; - struct rtl8125_private *tp = netdev_priv(dev); - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Extended Registers\n" - "Offset\tValue\n------\t-----\n"); - - rtnl_lock(); - - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - dword_rd = rtl8125_eri_read(tp, n, 4, ERIAR_ExGMAC); - len += snprintf(page + len, count - len, - "%08x ", - dword_rd); - } - } - - rtnl_unlock(); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_pci_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8125_PCI_REGS_SIZE; - u32 dword_rd; - struct rtl8125_private *tp = netdev_priv(dev); - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump PCI Registers\n" - "Offset\tValue\n------\t-----\n"); - - rtnl_lock(); - - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%03x:\t", - n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "%08x ", - dword_rd); - } - } - - n = 0x110; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "\n0x%03x:\t%08x ", - n, - dword_rd); - n = 0x70c; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "\n0x%03x:\t%08x ", - n, - dword_rd); - - rtnl_unlock(); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_temperature(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct rtl8125_private *tp = netdev_priv(dev); - u16 ts_digout, tj, fah; - int len = 0; - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - len += snprintf(page + len, count - len, - "\nChip Temperature\n"); - break; - default: - len += snprintf(page + len, count - len, - "\nThis Chip Does Not Support Dump Temperature\n"); - break; - } - - rtnl_lock(); - ts_digout = rtl8125_read_thermal_sensor(tp); - rtnl_unlock(); - - tj = ts_digout / 2; - if (ts_digout <= 512) { - tj = ts_digout / 2; - len += snprintf(page + len, count - len, - "Cel:%d\n", - tj); - fah = tj * (9/5) + 32; - len += snprintf(page + len, count - len, - "Fah:%d\n", - fah); - - } else { - tj = (512 - ((ts_digout / 2) - 512)) / 2; - len += snprintf(page + len, count - len, - "Cel:-%d\n", - tj); - fah = tj * (9/5) + 32; - len += snprintf(page + len, count - len, - "Fah:-%d\n", - fah); - } - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} -#endif -static void rtl8125_proc_module_init(void) -{ - //create /proc/net/r8125 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) - rtl8125_proc = proc_mkdir(MODULENAME, init_net.proc_net); -#else - rtl8125_proc = proc_mkdir(MODULENAME, proc_net); -#endif - if (!rtl8125_proc) - dprintk("cannot create %s proc entry \n", MODULENAME); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -/* - * seq_file wrappers for procfile show routines. - */ -static int rtl8125_proc_open(struct inode *inode, struct file *file) -{ - struct net_device *dev = proc_get_parent_data(inode); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) - int (*show)(struct seq_file *, void *) = pde_data(inode); -#else - int (*show)(struct seq_file *, void *) = PDE_DATA(inode); -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) - - return single_open(file, show, dev); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static const struct proc_ops rtl8125_proc_fops = { - .proc_open = rtl8125_proc_open, - .proc_read = seq_read, - .proc_lseek = seq_lseek, - .proc_release = single_release, -}; -#else -static const struct file_operations rtl8125_proc_fops = { - .open = rtl8125_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - -#endif - -/* - * Table of proc files we need to create. - */ -struct rtl8125_proc_file { - char name[12]; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - int (*show)(struct seq_file *, void *); -#else - int (*show)(char *, char **, off_t, int, int *, void *); -#endif -}; - -static const struct rtl8125_proc_file rtl8125_proc_files[] = { - { "driver_var", &proc_get_driver_variable }, - { "tally", &proc_get_tally_counter }, - { "registers", &proc_get_registers }, - { "pcie_phy", &proc_get_pcie_phy }, - { "eth_phy", &proc_get_eth_phy }, - { "ext_regs", &proc_get_extended_registers }, - { "pci_regs", &proc_get_pci_registers }, - { "temp", &proc_get_temperature }, - { "", NULL } -}; - -static void rtl8125_proc_init(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - const struct rtl8125_proc_file *f; - struct proc_dir_entry *dir; - - if (rtl8125_proc && !tp->proc_dir) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - dir = proc_mkdir_data(dev->name, 0, rtl8125_proc, dev); - if (!dir) { - printk("Unable to initialize /proc/net/%s/%s\n", - MODULENAME, dev->name); - return; - } - - tp->proc_dir = dir; - proc_init_num++; - - for (f = rtl8125_proc_files; f->name[0]; f++) { - if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir, - &rtl8125_proc_fops, f->show)) { - printk("Unable to initialize " - "/proc/net/%s/%s/%s\n", - MODULENAME, dev->name, f->name); - return; - } - } -#else - dir = proc_mkdir(dev->name, rtl8125_proc); - if (!dir) { - printk("Unable to initialize /proc/net/%s/%s\n", - MODULENAME, dev->name); - return; - } - - tp->proc_dir = dir; - proc_init_num++; - - for (f = rtl8125_proc_files; f->name[0]; f++) { - if (!create_proc_read_entry(f->name, S_IFREG | S_IRUGO, - dir, f->show, dev)) { - printk("Unable to initialize " - "/proc/net/%s/%s/%s\n", - MODULENAME, dev->name, f->name); - return; - } - } -#endif - } -} - -static void rtl8125_proc_remove(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->proc_dir) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - remove_proc_subtree(dev->name, rtl8125_proc); - proc_init_num--; - -#else - const struct rtl8125_proc_file *f; - struct rtl8125_private *tp = netdev_priv(dev); - - for (f = rtl8125_proc_files; f->name[0]; f++) - remove_proc_entry(f->name, tp->proc_dir); - - remove_proc_entry(dev->name, rtl8125_proc); - proc_init_num--; -#endif - tp->proc_dir = NULL; - } -} - -#endif //ENABLE_R8125_PROCFS - -static inline u16 map_phy_ocp_addr(u16 PageNum, u8 RegNum) -{ - u16 OcpPageNum = 0; - u8 OcpRegNum = 0; - u16 OcpPhyAddress = 0; - - if ( PageNum == 0 ) { - OcpPageNum = OCP_STD_PHY_BASE_PAGE + ( RegNum / 8 ); - OcpRegNum = 0x10 + ( RegNum % 8 ); - } else { - OcpPageNum = PageNum; - OcpRegNum = RegNum; - } - - OcpPageNum <<= 4; - - if ( OcpRegNum < 16 ) { - OcpPhyAddress = 0; - } else { - OcpRegNum -= 16; - OcpRegNum <<= 1; - - OcpPhyAddress = OcpPageNum + OcpRegNum; - } - - - return OcpPhyAddress; -} - -static void mdio_real_direct_write_phy_ocp(struct rtl8125_private *tp, - u16 RegAddr, - u16 value) -{ - u32 data32; - int i; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(RegAddr % 2); -#endif - data32 = RegAddr/2; - data32 <<= OCPR_Addr_Reg_shift; - data32 |= OCPR_Write | value; - - RTL_W32(tp, PHYOCP, data32); - for (i = 0; i < 100; i++) { - udelay(1); - - if (!(RTL_R32(tp, PHYOCP) & OCPR_Flag)) - break; - } -} - -static void mdio_direct_write_phy_ocp(struct rtl8125_private *tp, - u16 RegAddr, - u16 value) -{ - if (tp->rtk_enable_diag) return; - - mdio_real_direct_write_phy_ocp(tp, RegAddr, value); -} - -/* -static void rtl8125_mdio_write_phy_ocp(struct rtl8125_private *tp, - u16 PageNum, - u32 RegAddr, - u32 value) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - mdio_direct_write_phy_ocp(tp, ocp_addr, value); -} -*/ - -static void rtl8125_mdio_real_write_phy_ocp(struct rtl8125_private *tp, - u16 PageNum, - u32 RegAddr, - u32 value) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - mdio_real_direct_write_phy_ocp(tp, ocp_addr, value); -} - -static void mdio_real_write(struct rtl8125_private *tp, - u16 RegAddr, - u16 value) -{ - if (RegAddr == 0x1F) { - tp->cur_page = value; - return; - } - rtl8125_mdio_real_write_phy_ocp(tp, tp->cur_page, RegAddr, value); -} - -void rtl8125_mdio_write(struct rtl8125_private *tp, - u16 RegAddr, - u16 value) -{ - if (tp->rtk_enable_diag) return; - - mdio_real_write(tp, RegAddr, value); -} - -void rtl8125_mdio_prot_write(struct rtl8125_private *tp, - u32 RegAddr, - u32 value) -{ - mdio_real_write(tp, RegAddr, value); -} - -void rtl8125_mdio_prot_direct_write_phy_ocp(struct rtl8125_private *tp, - u32 RegAddr, - u32 value) -{ - mdio_real_direct_write_phy_ocp(tp, RegAddr, value); -} - -static u32 mdio_real_direct_read_phy_ocp(struct rtl8125_private *tp, - u16 RegAddr) -{ - u32 data32; - int i, value = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(RegAddr % 2); -#endif - data32 = RegAddr/2; - data32 <<= OCPR_Addr_Reg_shift; - - RTL_W32(tp, PHYOCP, data32); - for (i = 0; i < 100; i++) { - udelay(1); - - if (RTL_R32(tp, PHYOCP) & OCPR_Flag) - break; - } - value = RTL_R32(tp, PHYOCP) & OCPDR_Data_Mask; - - return value; -} - -static u32 mdio_direct_read_phy_ocp(struct rtl8125_private *tp, - u16 RegAddr) -{ - if (tp->rtk_enable_diag) return 0xffffffff; - - return mdio_real_direct_read_phy_ocp(tp, RegAddr); -} - -/* -static u32 rtl8125_mdio_read_phy_ocp(struct rtl8125_private *tp, - u16 PageNum, - u32 RegAddr) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - return mdio_direct_read_phy_ocp(tp, ocp_addr); -} -*/ - -static u32 rtl8125_mdio_real_read_phy_ocp(struct rtl8125_private *tp, - u16 PageNum, - u32 RegAddr) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - return mdio_real_direct_read_phy_ocp(tp, ocp_addr); -} - -static u32 mdio_real_read(struct rtl8125_private *tp, - u16 RegAddr) -{ - return rtl8125_mdio_real_read_phy_ocp(tp, tp->cur_page, RegAddr); -} - -u32 rtl8125_mdio_read(struct rtl8125_private *tp, - u16 RegAddr) -{ - if (tp->rtk_enable_diag) return 0xffffffff; - - return mdio_real_read(tp, RegAddr); -} - -u32 rtl8125_mdio_prot_read(struct rtl8125_private *tp, - u32 RegAddr) -{ - return mdio_real_read(tp, RegAddr); -} - -u32 rtl8125_mdio_prot_direct_read_phy_ocp(struct rtl8125_private *tp, - u32 RegAddr) -{ - return mdio_real_direct_read_phy_ocp(tp, RegAddr); -} - -static void ClearAndSetEthPhyBit(struct rtl8125_private *tp, u8 addr, u16 clearmask, u16 setmask) -{ - u16 PhyRegValue; - - PhyRegValue = rtl8125_mdio_read(tp, addr); - PhyRegValue &= ~clearmask; - PhyRegValue |= setmask; - rtl8125_mdio_write(tp, addr, PhyRegValue); -} - -void rtl8125_clear_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask) -{ - ClearAndSetEthPhyBit(tp, - addr, - mask, - 0 - ); -} - -void rtl8125_set_eth_phy_bit(struct rtl8125_private *tp, u8 addr, u16 mask) -{ - ClearAndSetEthPhyBit(tp, - addr, - 0, - mask - ); -} - -static void ClearAndSetEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 clearmask, u16 setmask) -{ - u16 PhyRegValue; - - PhyRegValue = mdio_direct_read_phy_ocp(tp, addr); - PhyRegValue &= ~clearmask; - PhyRegValue |= setmask; - mdio_direct_write_phy_ocp(tp, addr, PhyRegValue); -} - -void ClearEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 mask) -{ - ClearAndSetEthPhyOcpBit(tp, - addr, - mask, - 0 - ); -} - -void SetEthPhyOcpBit(struct rtl8125_private *tp, u16 addr, u16 mask) -{ - ClearAndSetEthPhyOcpBit(tp, - addr, - 0, - mask - ); -} - -void rtl8125_mac_ocp_write(struct rtl8125_private *tp, u16 reg_addr, u16 value) -{ - u32 data32; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(reg_addr % 2); -#endif - - data32 = reg_addr/2; - data32 <<= OCPR_Addr_Reg_shift; - data32 += value; - data32 |= OCPR_Write; - - RTL_W32(tp, MACOCP, data32); -} - -u32 rtl8125_mac_ocp_read(struct rtl8125_private *tp, u16 reg_addr) -{ - u32 data32; - u16 data16 = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(reg_addr % 2); -#endif - - data32 = reg_addr/2; - data32 <<= OCPR_Addr_Reg_shift; - - RTL_W32(tp, MACOCP, data32); - data16 = (u16)RTL_R32(tp, MACOCP); - - return data16; -} - -#ifdef ENABLE_USE_FIRMWARE_FILE -static void mac_mcu_write(struct rtl8125_private *tp, u16 reg, u16 value) -{ - if (reg == 0x1f) { - tp->ocp_base = value << 4; - return; - } - - rtl8125_mac_ocp_write(tp, tp->ocp_base + reg, value); -} - -static u32 mac_mcu_read(struct rtl8125_private *tp, u16 reg) -{ - return rtl8125_mac_ocp_read(tp, tp->ocp_base + reg); -} -#endif - -static void -ClearAndSetMcuAccessRegBit( - struct rtl8125_private *tp, - u16 addr, - u16 clearmask, - u16 setmask -) -{ - u16 PhyRegValue; - - PhyRegValue = rtl8125_mac_ocp_read(tp, addr); - PhyRegValue &= ~clearmask; - PhyRegValue |= setmask; - rtl8125_mac_ocp_write(tp, addr, PhyRegValue); -} - -static void -ClearMcuAccessRegBit( - struct rtl8125_private *tp, - u16 addr, - u16 mask -) -{ - ClearAndSetMcuAccessRegBit(tp, - addr, - mask, - 0 - ); -} - -static void -SetMcuAccessRegBit( - struct rtl8125_private *tp, - u16 addr, - u16 mask -) -{ - ClearAndSetMcuAccessRegBit(tp, - addr, - 0, - mask - ); -} - -u32 rtl8125_ocp_read_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, const u32 base_address) -{ - return rtl8125_eri_read_with_oob_base_address(tp, addr, len, ERIAR_OOB, base_address); -} - -u32 rtl8125_ocp_read(struct rtl8125_private *tp, u16 addr, u8 len) -{ - u32 value = 0; - - if (HW_DASH_SUPPORT_TYPE_2(tp)) - value = rtl8125_ocp_read_with_oob_base_address(tp, addr, len, NO_BASE_ADDRESS); - else if (HW_DASH_SUPPORT_TYPE_3(tp)) - value = rtl8125_ocp_read_with_oob_base_address(tp, addr, len, RTL8168FP_OOBMAC_BASE); - - return value; -} - -u32 rtl8125_ocp_write_with_oob_base_address(struct rtl8125_private *tp, u16 addr, u8 len, u32 value, const u32 base_address) -{ - return rtl8125_eri_write_with_oob_base_address(tp, addr, len, value, ERIAR_OOB, base_address); -} - -void rtl8125_ocp_write(struct rtl8125_private *tp, u16 addr, u8 len, u32 value) -{ - if (HW_DASH_SUPPORT_TYPE_2(tp)) - rtl8125_ocp_write_with_oob_base_address(tp, addr, len, value, NO_BASE_ADDRESS); - else if (HW_DASH_SUPPORT_TYPE_3(tp)) - rtl8125_ocp_write_with_oob_base_address(tp, addr, len, value, RTL8168FP_OOBMAC_BASE); -} - -void rtl8125_oob_mutex_lock(struct rtl8125_private *tp) -{ - u8 reg_16, reg_a0; - u32 wait_cnt_0, wait_Cnt_1; - u16 ocp_reg_mutex_ib; - u16 ocp_reg_mutex_oob; - u16 ocp_reg_mutex_prio; - - if (!tp->DASH) return; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - default: - ocp_reg_mutex_oob = 0x110; - ocp_reg_mutex_ib = 0x114; - ocp_reg_mutex_prio = 0x11C; - break; - } - - rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); - reg_16 = rtl8125_ocp_read(tp, ocp_reg_mutex_oob, 1); - wait_cnt_0 = 0; - while(reg_16) { - reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); - if (reg_a0) { - rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); - reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); - wait_Cnt_1 = 0; - while(reg_a0) { - reg_a0 = rtl8125_ocp_read(tp, ocp_reg_mutex_prio, 1); - - wait_Cnt_1++; - - if (wait_Cnt_1 > 2000) - break; - }; - rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); - - } - reg_16 = rtl8125_ocp_read(tp, ocp_reg_mutex_oob, 1); - - wait_cnt_0++; - - if (wait_cnt_0 > 2000) - break; - }; -} - -void rtl8125_oob_mutex_unlock(struct rtl8125_private *tp) -{ - u16 ocp_reg_mutex_ib; - u16 ocp_reg_mutex_oob; - u16 ocp_reg_mutex_prio; - - if (!tp->DASH) return; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - default: - ocp_reg_mutex_oob = 0x110; - ocp_reg_mutex_ib = 0x114; - ocp_reg_mutex_prio = 0x11C; - break; - } - - rtl8125_ocp_write(tp, ocp_reg_mutex_prio, 1, BIT_0); - rtl8125_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); -} - -void rtl8125_oob_notify(struct rtl8125_private *tp, u8 cmd) -{ - rtl8125_eri_write(tp, 0xE8, 1, cmd, ERIAR_ExGMAC); - - rtl8125_ocp_write(tp, 0x30, 1, 0x01); -} - -static int rtl8125_check_dash(struct rtl8125_private *tp) -{ - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - if (rtl8125_ocp_read(tp, 0x128, 1) & BIT_0) - return 1; - } - - return 0; -} - -void rtl8125_dash2_disable_tx(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - u16 WaitCnt; - u8 TmpUchar; - - //Disable oob Tx - RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) & ~( BIT_0 )); - WaitCnt = 0; - - //wait oob tx disable - do { - TmpUchar = RTL_CMAC_R8(tp, CMAC_IBISR0); - - if ( TmpUchar & ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE ) { - break; - } - - udelay( 50 ); - WaitCnt++; - } while(WaitCnt < 2000); - - //Clear ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE - RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0) | ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE); - } -} - -void rtl8125_dash2_enable_tx(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) | BIT_0); - } -} - -void rtl8125_dash2_disable_rx(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) & ~( BIT_0 )); - } -} - -void rtl8125_dash2_enable_rx(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) | BIT_0); - } -} - -static void rtl8125_dash2_disable_txrx(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - rtl8125_dash2_disable_tx( tp ); - rtl8125_dash2_disable_rx( tp ); - } -} - -static void rtl8125_driver_start(struct rtl8125_private *tp) -{ - if (!tp->DASH) - return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - int timeout; - u32 tmp_value; - - rtl8125_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_START); - tmp_value = rtl8125_ocp_read(tp, 0x30, 1); - tmp_value |= BIT_0; - rtl8125_ocp_write(tp, 0x30, 1, tmp_value); - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if (rtl8125_ocp_read(tp, 0x124, 1) & BIT_0) - break; - } - } -} - -static void rtl8125_driver_stop(struct rtl8125_private *tp) -{ - if (!tp->DASH) - return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - struct net_device *dev = tp->dev; - int timeout; - u32 tmp_value; - - rtl8125_dash2_disable_txrx(dev); - - rtl8125_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_STOP); - tmp_value = rtl8125_ocp_read(tp, 0x30, 1); - tmp_value |= BIT_0; - rtl8125_ocp_write(tp, 0x30, 1, tmp_value); - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if (!(rtl8125_ocp_read(tp, 0x124, 1) & BIT_0)) - break; - } - } -} - -void rtl8125_ephy_write(struct rtl8125_private *tp, int RegAddr, int value) -{ - int i; - - RTL_W32(tp, EPHYAR, - EPHYAR_Write | - (RegAddr & EPHYAR_Reg_Mask_v2) << EPHYAR_Reg_shift | - (value & EPHYAR_Data_Mask)); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed EPHY write */ - if (!(RTL_R32(tp, EPHYAR) & EPHYAR_Flag)) - break; - } - - udelay(20); -} - -u16 rtl8125_ephy_read(struct rtl8125_private *tp, int RegAddr) -{ - int i; - u16 value = 0xffff; - - RTL_W32(tp, EPHYAR, - EPHYAR_Read | (RegAddr & EPHYAR_Reg_Mask_v2) << EPHYAR_Reg_shift); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed EPHY read */ - if (RTL_R32(tp, EPHYAR) & EPHYAR_Flag) { - value = (u16) (RTL_R32(tp, EPHYAR) & EPHYAR_Data_Mask); - break; - } - } - - udelay(20); - - return value; -} - -static void ClearAndSetPCIePhyBit(struct rtl8125_private *tp, u8 addr, u16 clearmask, u16 setmask) -{ - u16 EphyValue; - - EphyValue = rtl8125_ephy_read(tp, addr); - EphyValue &= ~clearmask; - EphyValue |= setmask; - rtl8125_ephy_write(tp, addr, EphyValue); -} - -static void ClearPCIePhyBit(struct rtl8125_private *tp, u8 addr, u16 mask) -{ - ClearAndSetPCIePhyBit( tp, - addr, - mask, - 0 - ); -} - -static void SetPCIePhyBit( struct rtl8125_private *tp, u8 addr, u16 mask) -{ - ClearAndSetPCIePhyBit( tp, - addr, - 0, - mask - ); -} - -static u32 -rtl8125_csi_other_fun_read(struct rtl8125_private *tp, - u8 multi_fun_sel_bit, - u32 addr) -{ - u32 cmd; - int i; - u32 value = 0; - - cmd = CSIAR_Read | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); - - if (tp->mcfg == CFG_METHOD_DEFAULT) - multi_fun_sel_bit = 0; - - if (multi_fun_sel_bit > 7) - return 0xffffffff; - - cmd |= multi_fun_sel_bit << 16; - - RTL_W32(tp, CSIAR, cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed CSI read */ - if (RTL_R32(tp, CSIAR) & CSIAR_Flag) { - value = (u32)RTL_R32(tp, CSIDR); - break; - } - } - - udelay(20); - - return value; -} - -static void -rtl8125_csi_other_fun_write(struct rtl8125_private *tp, - u8 multi_fun_sel_bit, - u32 addr, - u32 value) -{ - u32 cmd; - int i; - - RTL_W32(tp, CSIDR, value); - cmd = CSIAR_Write | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); - if (tp->mcfg == CFG_METHOD_DEFAULT) - multi_fun_sel_bit = 0; - - if ( multi_fun_sel_bit > 7 ) - return; - - cmd |= multi_fun_sel_bit << 16; - - RTL_W32(tp, CSIAR, cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed CSI write */ - if (!(RTL_R32(tp, CSIAR) & CSIAR_Flag)) - break; - } - - udelay(20); -} - -static u32 -rtl8125_csi_read(struct rtl8125_private *tp, - u32 addr) -{ - u8 multi_fun_sel_bit; - - multi_fun_sel_bit = 0; - - return rtl8125_csi_other_fun_read(tp, multi_fun_sel_bit, addr); -} - -static void -rtl8125_csi_write(struct rtl8125_private *tp, - u32 addr, - u32 value) -{ - u8 multi_fun_sel_bit; - - multi_fun_sel_bit = 0; - - rtl8125_csi_other_fun_write(tp, multi_fun_sel_bit, addr, value); -} - -static u8 -rtl8125_csi_fun0_read_byte(struct rtl8125_private *tp, - u32 addr) -{ - u8 RetVal = 0; - - if (tp->mcfg == CFG_METHOD_DEFAULT) { - struct pci_dev *pdev = tp->pci_dev; - - pci_read_config_byte(pdev, addr, &RetVal); - } else { - u32 TmpUlong; - u16 RegAlignAddr; - u8 ShiftByte; - - RegAlignAddr = addr & ~(0x3); - ShiftByte = addr & (0x3); - TmpUlong = rtl8125_csi_other_fun_read(tp, 0, addr); - TmpUlong >>= (8*ShiftByte); - RetVal = (u8)TmpUlong; - } - - udelay(20); - - return RetVal; -} - -static void -rtl8125_csi_fun0_write_byte(struct rtl8125_private *tp, - u32 addr, - u8 value) -{ - if (tp->mcfg == CFG_METHOD_DEFAULT) { - struct pci_dev *pdev = tp->pci_dev; - - pci_write_config_byte(pdev, addr, value); - } else { - u32 TmpUlong; - u16 RegAlignAddr; - u8 ShiftByte; - - RegAlignAddr = addr & ~(0x3); - ShiftByte = addr & (0x3); - TmpUlong = rtl8125_csi_other_fun_read(tp, 0, RegAlignAddr); - TmpUlong &= ~(0xFF << (8*ShiftByte)); - TmpUlong |= (value << (8*ShiftByte)); - rtl8125_csi_other_fun_write( tp, 0, RegAlignAddr, TmpUlong ); - } - - udelay(20); -} - -u32 rtl8125_eri_read_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, int type, const u32 base_address) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, value2 = 0, mask; - u32 eri_cmd; - const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % ERIAR_Addr_Align; - addr = addr & ~0x3; - - eri_cmd = ERIAR_Read | - transformed_base_address | - type << ERIAR_Type_shift | - ERIAR_ByteEn << ERIAR_ByteEn_shift | - (addr & 0x0FFF); - if (addr & 0xF000) { - u32 tmp; - - tmp = addr & 0xF000; - tmp >>= 12; - eri_cmd |= (tmp << 20) & 0x00F00000; - } - - RTL_W32(tp, ERIAR, eri_cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed ERI read */ - if (RTL_R32(tp, ERIAR) & ERIAR_Flag) - break; - } - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = RTL_R32(tp, ERIDR) & mask; - value2 |= (value1 >> val_shift * 8) << shift * 8; - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return value2; -} - -u32 rtl8125_eri_read(struct rtl8125_private *tp, int addr, int len, int type) -{ - return rtl8125_eri_read_with_oob_base_address(tp, addr, len, type, 0); -} - -int rtl8125_eri_write_with_oob_base_address(struct rtl8125_private *tp, int addr, int len, u32 value, int type, const u32 base_address) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, mask; - u32 eri_cmd; - const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % ERIAR_Addr_Align; - addr = addr & ~0x3; - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = rtl8125_eri_read_with_oob_base_address(tp, addr, 4, type, base_address) & ~mask; - value1 |= ((value << val_shift * 8) >> shift * 8); - - RTL_W32(tp, ERIDR, value1); - - eri_cmd = ERIAR_Write | - transformed_base_address | - type << ERIAR_Type_shift | - ERIAR_ByteEn << ERIAR_ByteEn_shift | - (addr & 0x0FFF); - if (addr & 0xF000) { - u32 tmp; - - tmp = addr & 0xF000; - tmp >>= 12; - eri_cmd |= (tmp << 20) & 0x00F00000; - } - - RTL_W32(tp, ERIAR, eri_cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8125 has completed ERI write */ - if (!(RTL_R32(tp, ERIAR) & ERIAR_Flag)) - break; - } - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return 0; -} - -int rtl8125_eri_write(struct rtl8125_private *tp, int addr, int len, u32 value, int type) -{ - return rtl8125_eri_write_with_oob_base_address(tp, addr, len, value, type, NO_BASE_ADDRESS); -} - -static void -rtl8125_enable_rxdvgate(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_3); - mdelay(2); - break; - } -} - -static void -rtl8125_disable_rxdvgate(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_3); - mdelay(2); - break; - } -} - -static u8 -rtl8125_is_gpio_low(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u8 gpio_low = FALSE; - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 3: - if (!(rtl8125_mac_ocp_read(tp, 0xDC04) & BIT_13)) - gpio_low = TRUE; - break; - } - - if (gpio_low) - dprintk("gpio is low.\n"); - - return gpio_low; -} - -static u8 -rtl8125_is_phy_disable_mode_enabled(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u8 phy_disable_mode_enabled = FALSE; - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 3: - if (RTL_R8(tp, 0xF2) & BIT_5) - phy_disable_mode_enabled = TRUE; - break; - } - - if (phy_disable_mode_enabled) - dprintk("phy disable mode enabled.\n"); - - return phy_disable_mode_enabled; -} - -static u8 -rtl8125_is_in_phy_disable_mode(struct net_device *dev) -{ - u8 in_phy_disable_mode = FALSE; - - if (rtl8125_is_phy_disable_mode_enabled(dev) && rtl8125_is_gpio_low(dev)) - in_phy_disable_mode = TRUE; - - if (in_phy_disable_mode) - dprintk("Hardware is in phy disable mode.\n"); - - return in_phy_disable_mode; -} - -static bool -rtl8125_stop_all_request(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_6: - for (i = 0; i < 20; i++) { - udelay(10); - if (!(RTL_R8(tp, ChipCmd) & StopReq)) break; - } - - if (i == 20) - return 0; - break; - } - - return 1; -} - -void -rtl8125_wait_txrx_fifo_empty(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - rtl8125_stop_all_request(dev); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - for (i = 0; i < 3000; i++) { - udelay(50); - if ((RTL_R8(tp, MCUCmd_reg) & (Txfifo_empty | Rxfifo_empty)) == (Txfifo_empty | Rxfifo_empty)) - break; - } - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - for (i = 0; i < 3000; i++) { - udelay(50); - if ((RTL_R16(tp, IntrMitigate) & (BIT_0 | BIT_1 | BIT_8)) == (BIT_0 | BIT_1 | BIT_8)) - break; - } - break; - } -} - -#ifdef ENABLE_DASH_SUPPORT - -static inline void -rtl8125_enable_dash2_interrupt(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBIMR0, ( ISRIMR_DASH_TYPE2_ROK | ISRIMR_DASH_TYPE2_TOK | ISRIMR_DASH_TYPE2_TDU | ISRIMR_DASH_TYPE2_RDU | ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE )); - } -} - -static inline void -rtl8125_disable_dash2_interrupt(struct rtl8125_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBIMR0, 0); - } -} -#endif - -void -rtl8125_enable_hw_linkchg_interrupt(struct rtl8125_private *tp) -{ - switch (tp->HwCurrIsrVer) { - case 2: - RTL_W32(tp, IMR_V2_SET_REG_8125, ISRIMR_V2_LINKCHG); - break; - case 1: - RTL_W32(tp, tp->imr_reg[0], LinkChg | RTL_R32(tp, tp->imr_reg[0])); - break; - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8125_enable_dash2_interrupt(tp); -#endif -} - -static inline void -rtl8125_enable_hw_interrupt(struct rtl8125_private *tp) -{ - switch (tp->HwCurrIsrVer) { - case 2: - RTL_W32(tp, IMR_V2_SET_REG_8125, tp->intr_mask); - break; - case 1: - RTL_W32(tp, tp->imr_reg[0], tp->intr_mask); - - if (R8125_MULTI_RX_Q(tp)) { - int i; - for (i=1; inum_rx_rings; i++) - RTL_W16(tp, tp->imr_reg[i], other_q_intr_mask); - } - break; - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8125_enable_dash2_interrupt(tp); -#endif -} - -static inline void rtl8125_clear_hw_isr_v2(struct rtl8125_private *tp, - u32 message_id) -{ - RTL_W32(tp, ISR_V2_8125, BIT(message_id)); -} - -static inline void -rtl8125_disable_hw_interrupt(struct rtl8125_private *tp) -{ - if (tp->HwCurrIsrVer == 2) { - RTL_W32(tp, IMR_V2_CLEAR_REG_8125, 0xFFFFFFFF); - } else { - RTL_W32(tp, tp->imr_reg[0], 0x0000); - - if (R8125_MULTI_RX_Q(tp)) { - int i; - for (i=1; inum_rx_rings; i++) - RTL_W16(tp, tp->imr_reg[i], 0); - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8125_disable_dash2_interrupt(tp); -#endif - } -} - -static inline void -rtl8125_switch_to_hw_interrupt(struct rtl8125_private *tp) -{ - RTL_W32(tp, TIMER_INT0_8125, 0x0000); - - rtl8125_enable_hw_interrupt(tp); -} - -static inline void -rtl8125_switch_to_timer_interrupt(struct rtl8125_private *tp) -{ - if (tp->use_timer_interrrupt) { - RTL_W32(tp, TIMER_INT0_8125, timer_count); - RTL_W32(tp, TCTR0_8125, timer_count); - RTL_W32(tp, tp->imr_reg[0], tp->timer_intr_mask); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8125_enable_dash2_interrupt(tp); -#endif - } else { - rtl8125_switch_to_hw_interrupt(tp); - } -} - -static void -rtl8125_irq_mask_and_ack(struct rtl8125_private *tp) -{ - rtl8125_disable_hw_interrupt(tp); - - if (tp->HwCurrIsrVer == 2) { - RTL_W32(tp, ISR_V2_8125, 0xFFFFFFFF); - } else { -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - if (tp->dash_printer_enabled) { - RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0]) & - ~(ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); - } else { - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0)); - } - } - } else { - RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0])); - } -#else - RTL_W32(tp, tp->isr_reg[0], RTL_R32(tp, tp->isr_reg[0])); -#endif - if (R8125_MULTI_RX_Q(tp)) { - int i; - for (i=1; inum_rx_rings; i++) - RTL_W16(tp, tp->isr_reg[i], RTL_R16(tp, tp->isr_reg[i])); - } - } -} - -static void -rtl8125_nic_reset(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); - - rtl8125_enable_rxdvgate(dev); - - rtl8125_stop_all_request(dev); - - rtl8125_wait_txrx_fifo_empty(dev); - - mdelay(2); - - /* Soft reset the chip. */ - RTL_W8(tp, ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 100; i > 0; i--) { - udelay(100); - if ((RTL_R8(tp, ChipCmd) & CmdReset) == 0) - break; - } -} - -static void -rtl8125_hw_set_interrupt_type(struct rtl8125_private *tp, u8 isr_ver) -{ - u8 tmp; - - switch (tp->HwSuppIsrVer) { - case 2: - tmp = RTL_R8(tp, INT_CFG0_8125); - tmp &= ~(INT_CFG0_ENABLE_8125); - if (isr_ver == 2) - tmp |= INT_CFG0_ENABLE_8125; - RTL_W8(tp, INT_CFG0_8125, tmp); - break; - } -} - -static void -rtl8125_hw_clear_timer_int(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - RTL_W32(tp, TIMER_INT0_8125, 0x0000); - RTL_W32(tp, TIMER_INT1_8125, 0x0000); - RTL_W32(tp, TIMER_INT2_8125, 0x0000); - RTL_W32(tp, TIMER_INT3_8125, 0x0000); - break; - } -} - -static void -rtl8125_hw_clear_int_miti(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - switch (tp->HwSuppIntMitiVer) { - case 3: - //IntMITI_0-IntMITI_31 - for (i=0xA00; i<0xB00; i+=4) - RTL_W32(tp, i, 0x0000); - break; - case 4: - //IntMITI_0-IntMITI_15 - for (i = 0xA00; i < 0xA80; i += 4) - RTL_W32(tp, i, 0x0000); - - RTL_W8(tp, INT_CFG0_8125, RTL_R8(tp, INT_CFG0_8125) & - ~(INT_CFG0_TIMEOUT0_BYPASS_8125 | INT_CFG0_MITIGATION_BYPASS_8125)); - - RTL_W16(tp, INT_CFG1_8125, 0x0000); - break; - } -} - -void -rtl8125_hw_set_timer_int_8125(struct rtl8125_private *tp, - u32 message_id, - u8 timer_intmiti_val) -{ - switch (tp->HwSuppIntMitiVer) { - case 4: -#ifdef ENABLE_LIB_SUPPORT - if (message_id < R8125_MAX_RX_QUEUES_VEC_V3) - timer_intmiti_val = 0; -#else - if (tp->EnableRss && (message_id < R8125_MAX_RX_QUEUES_VEC_V3)) - timer_intmiti_val = 0; -#endif //ENABLE_LIB_SUPPORT - if (message_id < R8125_MAX_RX_QUEUES_VEC_V3) //ROK - RTL_W8(tp,INT_MITI_V2_0_RX + 8 * message_id, timer_intmiti_val); - else if (message_id == 16) //TOK - RTL_W8(tp,INT_MITI_V2_0_TX, timer_intmiti_val); - else if (message_id == 18) //TOK - RTL_W8(tp,INT_MITI_V2_1_TX, timer_intmiti_val); - break; - } -} - -void -rtl8125_hw_reset(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_lib_reset_prepare(tp); - - /* Disable interrupts */ - rtl8125_irq_mask_and_ack(tp); - - rtl8125_hw_clear_timer_int(dev); - - rtl8125_nic_reset(dev); -} - -static unsigned int -rtl8125_xmii_reset_pending(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned int retval; - - rtl8125_mdio_write(tp, 0x1f, 0x0000); - retval = rtl8125_mdio_read(tp, MII_BMCR) & BMCR_RESET; - - return retval; -} - -static unsigned int -rtl8125_xmii_link_ok(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned int retval; - - retval = (RTL_R16(tp, PHYstatus) & LinkStatus) ? 1 : 0; - - return retval; -} - -static int -rtl8125_wait_phy_reset_complete(struct rtl8125_private *tp) -{ - int i, val; - - for (i = 0; i < 2500; i++) { - val = rtl8125_mdio_read(tp, MII_BMCR) & BMCR_RESET; - if (!val) - return 0; - - mdelay(1); - } - - return -1; -} - -static void -rtl8125_xmii_reset_enable(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (rtl8125_is_in_phy_disable_mode(dev)) { - return; - } - - rtl8125_mdio_write(tp, 0x1f, 0x0000); - rtl8125_mdio_write(tp, MII_ADVERTISE, rtl8125_mdio_read(tp, MII_ADVERTISE) & - ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL)); - rtl8125_mdio_write(tp, MII_CTRL1000, rtl8125_mdio_read(tp, MII_CTRL1000) & - ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL)); - mdio_direct_write_phy_ocp(tp, 0xA5D4, mdio_direct_read_phy_ocp(tp, 0xA5D4) & ~(RTK_ADVERTISE_2500FULL)); - rtl8125_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); - - if (rtl8125_wait_phy_reset_complete(tp) == 0) return; - - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -void -rtl8125_init_ring_indexes(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->HwSuppNumTxQueues; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - ring->dirty_tx = ring->cur_tx = 0; - ring->NextHwDesCloPtr = 0; - ring->BeginHwDesCloPtr = 0; - ring->index = i; - ring->priv = tp; - } - - for (i = 0; i < tp->HwSuppNumRxQueues; i++) { - struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; - ring->dirty_rx = ring->cur_rx = 0; - ring->index = i; - ring->priv = tp; - } - -#ifdef ENABLE_LIB_SUPPORT - for (i = 0; i < tp->HwSuppNumTxQueues; i++) { - struct rtl8125_ring *ring = &tp->lib_tx_ring[i]; - ring->direction = RTL8125_CH_DIR_TX; - ring->queue_num = i; - ring->private = tp; - } - - for (i = 0; i < tp->HwSuppNumRxQueues; i++) { - struct rtl8125_ring *ring = &tp->lib_rx_ring[i]; - ring->direction = RTL8125_CH_DIR_RX; - ring->queue_num = i; - ring->private = tp; - } -#endif -} - -static void -rtl8125_issue_offset_99_event(struct rtl8125_private *tp) -{ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_mac_ocp_write(tp, 0xE09A, rtl8125_mac_ocp_read(tp, 0xE09A) | BIT_0); - break; - } -} - -#ifdef ENABLE_DASH_SUPPORT -static void -NICChkTypeEnableDashInterrupt(struct rtl8125_private *tp) -{ - if (tp->DASH) { - // - // even disconnected, enable 3 dash interrupt mask bits for in-band/out-band communication - // - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - rtl8125_enable_dash2_interrupt(tp); - RTL_W16(tp, IntrMask, (ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); - } - } -} -#endif - -static int rtl8125_enable_eee_plus(struct rtl8125_private *tp) -{ - int ret; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_mac_ocp_write(tp, 0xE080, rtl8125_mac_ocp_read(tp, 0xE080)|BIT_1); - break; - - default: -// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEEPlus\n"); - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -static int rtl8125_disable_eee_plus(struct rtl8125_private *tp) -{ - int ret; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_mac_ocp_write(tp, 0xE080, rtl8125_mac_ocp_read(tp, 0xE080)&~BIT_1); - break; - - default: -// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEEPlus\n"); - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -static void -rtl8125_link_on_patch(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_hw_config(dev); - - if ((tp->mcfg == CFG_METHOD_2) && - netif_running(dev)) { - if (RTL_R16(tp, PHYstatus)&FullDup) - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | (BIT_24 | BIT_25)) & ~BIT_19); - else - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | BIT_25) & ~(BIT_19 | BIT_24)); - } - - if ((tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_6 || - tp->mcfg == CFG_METHOD_7) && - (RTL_R8(tp, PHYstatus) & _10bps)) - rtl8125_enable_eee_plus(tp); - - rtl8125_hw_start(dev); - - netif_carrier_on(dev); - - netif_tx_wake_all_queues(dev); - - tp->phy_reg_aner = rtl8125_mdio_read(tp, MII_EXPANSION); - tp->phy_reg_anlpar = rtl8125_mdio_read(tp, MII_LPA); - tp->phy_reg_gbsr = rtl8125_mdio_read(tp, MII_STAT1000); - tp->phy_reg_status_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D6); -} - -static void -rtl8125_link_down_patch(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->phy_reg_aner = 0; - tp->phy_reg_anlpar = 0; - tp->phy_reg_gbsr = 0; - tp->phy_reg_status_2500 = 0; - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_6 || - tp->mcfg == CFG_METHOD_7) - rtl8125_disable_eee_plus(tp); - - netif_tx_stop_all_queues(dev); - - netif_carrier_off(dev); - - rtl8125_hw_reset(dev); - - rtl8125_tx_clear(tp); - - rtl8125_rx_clear(tp); - - rtl8125_init_ring(dev); - - rtl8125_enable_hw_linkchg_interrupt(tp); - - //rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - NICChkTypeEnableDashInterrupt(tp); - } -#endif -} - -static void -_rtl8125_check_link_status(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->link_ok(dev)) { - rtl8125_link_on_patch(dev); - - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - - rtl8125_link_down_patch(dev); - } -} - -static void -rtl8125_check_link_status(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - _rtl8125_check_link_status(dev); - - tp->resume_not_chg_speed = 0; -} - -static void -rtl8125_link_option_giga(u8 *aut, - u32 *spd, - u8 *dup, - u32 *adv) -{ - if ((*spd != SPEED_1000) && - (*spd != SPEED_100) && - (*spd != SPEED_10)) - *spd = SPEED_1000; - - if ((*dup != DUPLEX_FULL) && (*dup != DUPLEX_HALF)) - *dup = DUPLEX_FULL; - - if ((*aut != AUTONEG_ENABLE) && (*aut != AUTONEG_DISABLE)) - *aut = AUTONEG_ENABLE; - - *adv &= (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full); - if (*adv == 0) - *adv = (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full); -} - -static void -rtl8125_link_option(u8 *aut, - u32 *spd, - u8 *dup, - u32 *adv) -{ - if ((*spd != SPEED_2500) && (*spd != SPEED_1000) && - (*spd != SPEED_100) && (*spd != SPEED_10)) - *spd = SPEED_2500; - - if ((*dup != DUPLEX_FULL) && (*dup != DUPLEX_HALF)) - *dup = DUPLEX_FULL; - - if ((*aut != AUTONEG_ENABLE) && (*aut != AUTONEG_DISABLE)) - *aut = AUTONEG_ENABLE; - - *adv &= (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_2500baseX_Full); - if (*adv == 0) - *adv = (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full | - ADVERTISED_2500baseX_Full); -} - -/* -static void -rtl8125_enable_ocp_phy_power_saving(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 val; - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_6 || - tp->mcfg == CFG_METHOD_7) { - val = mdio_direct_read_phy_ocp(tp, 0xC416); - if (val != 0x0050) { - rtl8125_set_phy_mcu_patch_request(tp); - mdio_direct_write_phy_ocp(tp, 0xC416, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xC416, 0x0050); - rtl8125_clear_phy_mcu_patch_request(tp); - } - } -} -*/ - -static void -rtl8125_disable_ocp_phy_power_saving(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 val; - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_6 || - tp->mcfg == CFG_METHOD_7) { - val = mdio_direct_read_phy_ocp(tp, 0xC416); - if (val != 0x0500) { - rtl8125_set_phy_mcu_patch_request(tp); - mdio_direct_write_phy_ocp(tp, 0xC416, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xC416, 0x0500); - rtl8125_clear_phy_mcu_patch_request(tp); - } - } -} - -static void -rtl8125_wait_ll_share_fifo_ready(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - for (i = 0; i < 10; i++) { - udelay(100); - if (RTL_R16(tp, 0xD2) & BIT_9) - break; - } -} - -static void -rtl8125_disable_pci_offset_99(struct rtl8125_private *tp) -{ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_mac_ocp_write(tp, 0xE032, rtl8125_mac_ocp_read(tp, 0xE032) & ~(BIT_0 | BIT_1)); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_csi_fun0_write_byte(tp, 0x99, 0x00); - break; - } -} - -static void -rtl8125_enable_pci_offset_99(struct rtl8125_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_csi_fun0_write_byte(tp, 0x99, tp->org_pci_offset_99); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE032); - csi_tmp &= ~(BIT_0 | BIT_1); - if (tp->org_pci_offset_99 & (BIT_5 | BIT_6)) - csi_tmp |= BIT_1; - if (tp->org_pci_offset_99 & BIT_2) - csi_tmp |= BIT_0; - rtl8125_mac_ocp_write(tp, 0xE032, csi_tmp); - break; - } -} - -static void -rtl8125_init_pci_offset_99(struct rtl8125_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_mac_ocp_write(tp, 0xCDD0, 0x9003); - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE034); - csi_tmp |= (BIT_15 | BIT_14); - rtl8125_mac_ocp_write(tp, 0xE034, csi_tmp); - rtl8125_mac_ocp_write(tp, 0xCDD2, 0x889C); - rtl8125_mac_ocp_write(tp, 0xCDD8, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDD4, 0x8C30); - rtl8125_mac_ocp_write(tp, 0xCDDA, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDD6, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDDC, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDE8, 0x883E); - rtl8125_mac_ocp_write(tp, 0xCDEA, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDEC, 0x889C); - rtl8125_mac_ocp_write(tp, 0xCDEE, 0x9003); - rtl8125_mac_ocp_write(tp, 0xCDF0, 0x8C09); - rtl8125_mac_ocp_write(tp, 0xCDF2, 0x9003); - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE032); - csi_tmp |= (BIT_14); - rtl8125_mac_ocp_write(tp, 0xE032, csi_tmp); - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE0A2); - csi_tmp |= (BIT_0); - rtl8125_mac_ocp_write(tp, 0xE0A2, csi_tmp); - break; - } - - rtl8125_enable_pci_offset_99(tp); -} - -static void -rtl8125_disable_pci_offset_180(struct rtl8125_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE092); - csi_tmp &= 0xFF00; - rtl8125_mac_ocp_write(tp, 0xE092, csi_tmp); - break; - } -} - -static void -rtl8125_enable_pci_offset_180(struct rtl8125_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE094); - csi_tmp &= 0x00FF; - rtl8125_mac_ocp_write(tp, 0xE094, csi_tmp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xE092); - csi_tmp &= 0xFF00; - csi_tmp |= BIT_2; - rtl8125_mac_ocp_write(tp, 0xE092, csi_tmp); - break; - } -} - -static void -rtl8125_init_pci_offset_180(struct rtl8125_private *tp) -{ - if (tp->org_pci_offset_180 & (BIT_0|BIT_1)) - rtl8125_enable_pci_offset_180(tp); - else - rtl8125_disable_pci_offset_180(tp); -} - -static void -rtl8125_set_pci_99_180_exit_driver_para(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - if (tp->org_pci_offset_99 & BIT_2) - rtl8125_issue_offset_99_event(tp); - rtl8125_disable_pci_offset_99(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_disable_pci_offset_180(tp); - break; - } -} - -static void -rtl8125_enable_cfg9346_write(struct rtl8125_private *tp) -{ - RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) | Cfg9346_Unlock); -} - -static void -rtl8125_disable_cfg9346_write(struct rtl8125_private *tp) -{ - RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) & ~Cfg9346_Unlock); -} - -static void -rtl8125_enable_exit_l1_mask(struct rtl8125_private *tp) -{ - //(1)ERI(0xD4)(OCP 0xC0AC).bit[7:12]=6'b111111, L1 Mask - SetMcuAccessRegBit(tp, 0xC0AC, (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12)); -} - -static void -rtl8125_disable_exit_l1_mask(struct rtl8125_private *tp) -{ - //(1)ERI(0xD4)(OCP 0xC0AC).bit[7:12]=6'b000000, L1 Mask - ClearMcuAccessRegBit(tp, 0xC0AC, (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12)); -} - -static void -rtl8125_enable_extend_tally_couter(struct rtl8125_private *tp) -{ - switch (tp->HwSuppExtendTallyCounterVer) { - case 1: - SetMcuAccessRegBit(tp, 0xEA84, (BIT_1 | BIT_0)); - break; - } -} - -static void -rtl8125_disable_extend_tally_couter(struct rtl8125_private *tp) -{ - switch (tp->HwSuppExtendTallyCounterVer) { - case 1: - ClearMcuAccessRegBit(tp, 0xEA84, (BIT_1 | BIT_0)); - break; - } -} - -static void -rtl8125_hw_d3_para(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - RTL_W16(tp, RxMaxSize, RX_BUF_SIZE); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - rtl8125_enable_cfg9346_write(tp); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - rtl8125_disable_cfg9346_write(tp); - break; - } - - rtl8125_disable_exit_l1_mask(tp); - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8125_set_realwow_d3_para(dev); -#endif - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_mac_ocp_write(tp, 0xEA18, 0x0064); - break; - } - - rtl8125_set_pci_99_180_exit_driver_para(dev); - - /*disable ocp phy power saving*/ - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_6 || - tp->mcfg == CFG_METHOD_7) - rtl8125_disable_ocp_phy_power_saving(dev); - - rtl8125_disable_rxdvgate(dev); - - rtl8125_disable_extend_tally_couter(tp); -} - -static void -rtl8125_enable_magic_packet(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V3: - rtl8125_mac_ocp_write(tp, 0xC0B6, rtl8125_mac_ocp_read(tp, 0xC0B6) | BIT_0); - break; - } -} -static void -rtl8125_disable_magic_packet(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V3: - rtl8125_mac_ocp_write(tp, 0xC0B6, rtl8125_mac_ocp_read(tp, 0xC0B6) & ~BIT_0); - break; - } -} - -static void -rtl8125_enable_linkchg_wakeup(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppLinkChgWakeUpVer) { - case 3: - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | LinkUp); - ClearAndSetMcuAccessRegBit(tp, 0xE0C6, (BIT_5 | BIT_3 | BIT_2), (BIT_4 | BIT_1 | BIT_0)); - break; - } -} - -static void -rtl8125_disable_linkchg_wakeup(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppLinkChgWakeUpVer) { - case 3: - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~LinkUp); - ClearMcuAccessRegBit(tp, 0xE0C6, (BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0)); - break; - } -} - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - -static u32 -rtl8125_get_hw_wol(struct rtl8125_private *tp) -{ - u8 options; - u32 csi_tmp; - u32 wol_opts = 0; - - if (disable_pm_support) - goto out; - - options = RTL_R8(tp, Config1); - if (!(options & PMEnable)) - goto out; - - options = RTL_R8(tp, Config3); - if (options & LinkUp) - wol_opts |= WAKE_PHY; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V3: - csi_tmp = rtl8125_mac_ocp_read(tp, 0xC0B6); - if (csi_tmp & BIT_0) - wol_opts |= WAKE_MAGIC; - break; - } - - options = RTL_R8(tp, Config5); - if (options & UWF) - wol_opts |= WAKE_UCAST; - if (options & BWF) - wol_opts |= WAKE_BCAST; - if (options & MWF) - wol_opts |= WAKE_MCAST; - -out: - return wol_opts; -} - -static void -rtl8125_enable_d0_speedup(struct rtl8125_private *tp) -{ - if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; - if (tp->D0SpeedUpSpeed == D0_SPEED_UP_SPEED_DISABLE) return; - - if (tp->HwSuppD0SpeedUpVer == 1) { - u16 mac_ocp_data; - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_3); - - //speed up speed - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE10A); - mac_ocp_data &= ~(BIT_10 | BIT_9 | BIT_8 | BIT_7); - if (tp->D0SpeedUpSpeed == D0_SPEED_UP_SPEED_2500) { - mac_ocp_data |= BIT_7; - } - rtl8125_mac_ocp_write(tp, 0xE10A, mac_ocp_data); - - //speed up flowcontrol - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE860); - mac_ocp_data |= (BIT_15 | BIT_14); - rtl8125_mac_ocp_write(tp, 0xE860, mac_ocp_data); - } -} - -static void -rtl8125_disable_d0_speedup(struct rtl8125_private *tp) -{ - if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; - - if (tp->HwSuppD0SpeedUpVer == 1) - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) & ~BIT_7); -} - -static void -rtl8125_set_hw_wol(struct net_device *dev, u32 wolopts) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i,tmp; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_PHY, Config3, LinkUp }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake }, - { WAKE_MAGIC, Config3, MagicPacket }, - }; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V3: - default: - tmp = ARRAY_SIZE(cfg) - 1; - - if (wolopts & WAKE_MAGIC) - rtl8125_enable_magic_packet(dev); - else - rtl8125_disable_magic_packet(dev); - break; - } - - rtl8125_enable_cfg9346_write(tp); - - for (i = 0; i < tmp; i++) { - u8 options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(tp, cfg[i].reg, options); - } - - switch (tp->HwSuppLinkChgWakeUpVer) { - case 3: - if (wolopts & WAKE_PHY) - rtl8125_enable_linkchg_wakeup(dev); - else - rtl8125_disable_linkchg_wakeup(dev); - break; - } - - rtl8125_disable_cfg9346_write(tp); -} - -static void -rtl8125_phy_restart_nway(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (rtl8125_is_in_phy_disable_mode(dev)) return; - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_ANRESTART); -} - -static void -rtl8125_phy_setup_force_mode(struct net_device *dev, u32 speed, u8 duplex) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 bmcr_true_force = 0; - - if (rtl8125_is_in_phy_disable_mode(dev)) return; - - if ((speed == SPEED_10) && (duplex == DUPLEX_HALF)) { - bmcr_true_force = BMCR_SPEED10; - } else if ((speed == SPEED_10) && (duplex == DUPLEX_FULL)) { - bmcr_true_force = BMCR_SPEED10 | BMCR_FULLDPLX; - } else if ((speed == SPEED_100) && (duplex == DUPLEX_HALF)) { - bmcr_true_force = BMCR_SPEED100; - } else if ((speed == SPEED_100) && (duplex == DUPLEX_FULL)) { - bmcr_true_force = BMCR_SPEED100 | BMCR_FULLDPLX; - } else { - netif_err(tp, drv, dev, "Failed to set phy force mode!\n"); - return; - } - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, MII_BMCR, bmcr_true_force); -} - -static void -rtl8125_set_pci_pme(struct rtl8125_private *tp, int set) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 pmc; - - if (!pdev->pm_cap) - return; - - pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmc); - pmc |= PCI_PM_CTRL_PME_STATUS; - if (set) - pmc |= PCI_PM_CTRL_PME_ENABLE; - else - pmc &= ~PCI_PM_CTRL_PME_ENABLE; - pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, pmc); -} - -static void -rtl8125_set_wol_link_speed(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int auto_nego; - int giga_ctrl; - int ctrl_2500; - u32 adv; - u16 anlpar; - u16 gbsr; - u16 status_2500; - u16 aner; - - if (tp->autoneg != AUTONEG_ENABLE) - goto exit; - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - - auto_nego = rtl8125_mdio_read(tp, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL - | ADVERTISE_100HALF | ADVERTISE_100FULL); - - giga_ctrl = rtl8125_mdio_read(tp, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - - ctrl_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D4); - ctrl_2500 &= ~(RTK_ADVERTISE_2500FULL); - - aner = anlpar = gbsr = status_2500 = 0; - if (tp->link_ok(dev)) { - aner = rtl8125_mdio_read(tp, MII_EXPANSION); - anlpar = rtl8125_mdio_read(tp, MII_LPA); - gbsr = rtl8125_mdio_read(tp, MII_STAT1000); - status_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D6); - } else { - if (netif_running(dev)) { - aner = tp->phy_reg_aner; - anlpar = tp->phy_reg_anlpar; - gbsr = tp->phy_reg_gbsr; - status_2500 = tp->phy_reg_status_2500; - } - } - - if ((aner | anlpar | gbsr | status_2500) == 0) { - int auto_nego_tmp = 0; - adv = tp->advertising; - if ((adv & ADVERTISED_10baseT_Half) && (anlpar & LPA_10HALF)) - auto_nego_tmp |= ADVERTISE_10HALF; - if ((adv & ADVERTISED_10baseT_Full) && (anlpar & LPA_10FULL)) - auto_nego_tmp |= ADVERTISE_10FULL; - if ((adv & ADVERTISED_100baseT_Half) && (anlpar & LPA_100HALF)) - auto_nego_tmp |= ADVERTISE_100HALF; - if ((adv & ADVERTISED_100baseT_Full) && (anlpar & LPA_100FULL)) - auto_nego_tmp |= ADVERTISE_100FULL; - - if (auto_nego_tmp == 0) goto exit; - - auto_nego |= auto_nego_tmp; - goto skip_check_lpa; - } - if (!(aner & EXPANSION_NWAY)) goto exit; - - adv = tp->advertising; - if ((adv & ADVERTISED_10baseT_Half) && (anlpar & LPA_10HALF)) - auto_nego |= ADVERTISE_10HALF; - else if ((adv & ADVERTISED_10baseT_Full) && (anlpar & LPA_10FULL)) - auto_nego |= ADVERTISE_10FULL; - else if ((adv & ADVERTISED_100baseT_Half) && (anlpar & LPA_100HALF)) - auto_nego |= ADVERTISE_100HALF; - else if ((adv & ADVERTISED_100baseT_Full) && (anlpar & LPA_100FULL)) - auto_nego |= ADVERTISE_100FULL; - else if (adv & ADVERTISED_1000baseT_Half && (gbsr & LPA_1000HALF)) - giga_ctrl |= ADVERTISE_1000HALF; - else if (adv & ADVERTISED_1000baseT_Full && (gbsr & LPA_1000FULL)) - giga_ctrl |= ADVERTISE_1000FULL; - else if (adv & ADVERTISED_2500baseX_Full && (status_2500 & RTK_LPA_ADVERTISE_2500FULL)) - ctrl_2500 |= RTK_ADVERTISE_2500FULL; - else - goto exit; - -skip_check_lpa: - if (tp->DASH) - auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); - -#ifdef CONFIG_DOWN_SPEED_100 - auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); -#endif - - rtl8125_mdio_write(tp, MII_ADVERTISE, auto_nego); - rtl8125_mdio_write(tp, MII_CTRL1000, giga_ctrl); - mdio_direct_write_phy_ocp(tp, 0xA5D4, ctrl_2500); - - rtl8125_phy_restart_nway(dev); - -exit: - return; -} - -static bool -rtl8125_keep_wol_link_speed(struct net_device *dev, u8 from_suspend) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if ((from_suspend && !tp->link_ok(dev)) || - (!from_suspend && tp->resume_not_chg_speed)) - return 1; - - return 0; -} -static void -rtl8125_powerdown_pll(struct net_device *dev, u8 from_suspend) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->check_keep_link_speed = 0; - if (tp->wol_enabled == WOL_ENABLED || tp->DASH || tp->EnableKCPOffload) { - rtl8125_set_hw_wol(dev, tp->wol_opts); - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_6 || - tp->mcfg == CFG_METHOD_7) { - rtl8125_enable_cfg9346_write(tp); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) | PMSTS_En); - rtl8125_disable_cfg9346_write(tp); - } - - /* Enable the PME and clear the status */ - rtl8125_set_pci_pme(tp, 1); - - if (rtl8125_keep_wol_link_speed(dev, from_suspend)) { - if (tp->wol_opts & WAKE_PHY) - tp->check_keep_link_speed = 1; - } else { - if (HW_SUPPORT_D0_SPEED_UP(tp)) { - rtl8125_enable_d0_speedup(tp); - tp->check_keep_link_speed = 1; - } - - rtl8125_set_wol_link_speed(dev); - } - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); - - return; - } - - if (tp->DASH) - return; - - rtl8125_phy_power_down(dev); - - if (!tp->HwIcVerUnknown) { - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~BIT_7); - break; - } - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_6); - break; - } -} - -static void rtl8125_powerup_pll(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | BIT_7 | BIT_6); - break; - } - - if (tp->resume_not_chg_speed) return; - - rtl8125_phy_power_up(dev); -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static void -rtl8125_get_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u8 options; - - wol->wolopts = 0; - - if (tp->mcfg == CFG_METHOD_DEFAULT || disable_pm_support) { - wol->supported = 0; - return; - } else { - wol->supported = WAKE_ANY; - } - - options = RTL_R8(tp, Config1); - if (!(options & PMEnable)) - return; - - wol->wolopts = tp->wol_opts; -} - -static int -rtl8125_set_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_DEFAULT || disable_pm_support) - return -EOPNOTSUPP; - - tp->wol_opts = wol->wolopts; - - tp->wol_enabled = (tp->wol_opts) ? WOL_ENABLED : WOL_DISABLED; - - device_set_wakeup_enable(tp_to_dev(tp), wol->wolopts); - - return 0; -} - -static void -rtl8125_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct rtl8125_fw *rtl_fw = tp->rtl_fw; - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8125_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = R8125_REGS_DUMP_SIZE; - info->eedump_len = tp->eeprom_len; - BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version)); - if (rtl_fw) - strlcpy(info->fw_version, rtl_fw->version, - sizeof(info->fw_version)); -} - -static int -rtl8125_get_regs_len(struct net_device *dev) -{ - return R8125_REGS_DUMP_SIZE; -} -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -static void -rtl8125_set_d0_speedup_speed(struct rtl8125_private *tp) -{ - if (FALSE == HW_SUPPORT_D0_SPEED_UP(tp)) return; - - tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_DISABLE; - if (tp->autoneg == AUTONEG_ENABLE) { - if (tp->speed == SPEED_2500) - tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_2500; - else if(tp->speed == SPEED_1000) - tp->D0SpeedUpSpeed = D0_SPEED_UP_SPEED_1000; - } -} - -static int -rtl8125_set_speed_xmii(struct net_device *dev, - u8 autoneg, - u32 speed, - u8 duplex, - u32 adv) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int auto_nego = 0; - int giga_ctrl = 0; - int ctrl_2500 = 0; - int rc = -EINVAL; - - //Disable Giga Lite - ClearEthPhyOcpBit(tp, 0xA428, BIT_9); - ClearEthPhyOcpBit(tp, 0xA5EA, BIT_0); - - if (speed != SPEED_2500 && - (speed != SPEED_1000) && - (speed != SPEED_100) && - (speed != SPEED_10)) { - speed = SPEED_2500; - duplex = DUPLEX_FULL; - } - - giga_ctrl = rtl8125_mdio_read(tp, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - ctrl_2500 = mdio_direct_read_phy_ocp(tp, 0xA5D4); - ctrl_2500 &= ~(RTK_ADVERTISE_2500FULL); - - if (autoneg == AUTONEG_ENABLE) { - /*n-way force*/ - auto_nego = rtl8125_mdio_read(tp, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL | - ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - - if (adv & ADVERTISED_10baseT_Half) - auto_nego |= ADVERTISE_10HALF; - if (adv & ADVERTISED_10baseT_Full) - auto_nego |= ADVERTISE_10FULL; - if (adv & ADVERTISED_100baseT_Half) - auto_nego |= ADVERTISE_100HALF; - if (adv & ADVERTISED_100baseT_Full) - auto_nego |= ADVERTISE_100FULL; - if (adv & ADVERTISED_1000baseT_Half) - giga_ctrl |= ADVERTISE_1000HALF; - if (adv & ADVERTISED_1000baseT_Full) - giga_ctrl |= ADVERTISE_1000FULL; - if (adv & ADVERTISED_2500baseX_Full) - ctrl_2500 |= RTK_ADVERTISE_2500FULL; - - //flow control - if (dev->mtu <= ETH_DATA_LEN && tp->fcpause == rtl8125_fc_full) - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - tp->phy_auto_nego_reg = auto_nego; - tp->phy_1000_ctrl_reg = giga_ctrl; - - tp->phy_2500_ctrl_reg = ctrl_2500; - - rtl8125_mdio_write(tp, 0x1f, 0x0000); - rtl8125_mdio_write(tp, MII_ADVERTISE, auto_nego); - rtl8125_mdio_write(tp, MII_CTRL1000, giga_ctrl); - mdio_direct_write_phy_ocp(tp, 0xA5D4, ctrl_2500); - rtl8125_phy_restart_nway(dev); - mdelay(20); - } else { - /*true force*/ - if (speed == SPEED_10 || speed == SPEED_100) - rtl8125_phy_setup_force_mode(dev, speed, duplex); - else - goto out; - } - - tp->autoneg = autoneg; - tp->speed = speed; - tp->duplex = duplex; - tp->advertising = adv; - - rtl8125_set_d0_speedup_speed(tp); - - rc = 0; -out: - return rc; -} - -static int -rtl8125_set_speed(struct net_device *dev, - u8 autoneg, - u32 speed, - u8 duplex, - u32 adv) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret; - - if (tp->resume_not_chg_speed) return 0; - - ret = tp->set_speed(dev, autoneg, speed, duplex, adv); - - return ret; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int -rtl8125_set_settings(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - const struct ethtool_link_ksettings *cmd -#endif - ) -{ - int ret; - u8 autoneg; - u32 speed; - u8 duplex; - u32 supported, advertising; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - autoneg = cmd->autoneg; - speed = cmd->speed; - duplex = cmd->duplex; - supported = cmd->supported; - advertising = cmd->advertising; -#else - const struct ethtool_link_settings *base = &cmd->base; - autoneg = base->autoneg; - speed = base->speed; - duplex = base->duplex; - ethtool_convert_link_mode_to_legacy_u32(&supported, - cmd->link_modes.supported); - ethtool_convert_link_mode_to_legacy_u32(&advertising, - cmd->link_modes.advertising); - if (test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - cmd->link_modes.supported)) - supported |= ADVERTISED_2500baseX_Full; - if (test_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - cmd->link_modes.advertising)) - advertising |= ADVERTISED_2500baseX_Full; -#endif - if (advertising & ~supported) - return -EINVAL; - - ret = rtl8125_set_speed(dev, autoneg, speed, duplex, advertising); - - return ret; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -static u32 -rtl8125_get_tx_csum(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 ret; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - ret = ((dev->features & NETIF_F_IP_CSUM) != 0); -#else - ret = ((dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) != 0); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - - return ret; -} - -static u32 -rtl8125_get_rx_csum(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 ret; - - ret = tp->cp_cmd & RxChkSum; - - return ret; -} - -static int -rtl8125_set_tx_csum(struct net_device *dev, - u32 data) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - if (data) - dev->features |= NETIF_F_IP_CSUM; - else - dev->features &= ~NETIF_F_IP_CSUM; -#else - if (data) - dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - else - dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - - return 0; -} - -static int -rtl8125_set_rx_csum(struct net_device *dev, - u32 data) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(tp, CPlusCmd, tp->cp_cmd); - - return 0; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -static u32 -rtl8125_rx_desc_opts1(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - return ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts1; - else - return desc->opts1; -} - -static u32 -rtl8125_rx_desc_opts2(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - return ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts2; - else - return desc->opts2; -} - -#ifdef CONFIG_R8125_VLAN - -static void -rtl8125_clear_rx_desc_opts2(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - ((struct RxDescV3 *)desc)->RxDescNormalDDWord4.opts2 = 0; - else - desc->opts2 = 0; -} - -static inline u32 -rtl8125_tx_vlan_tag(struct rtl8125_private *tp, - struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - return (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) - return (vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -#else - return (skb_vlan_tag_present(skb)) ? - TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00; -#endif - - return 0; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - -static void -rtl8125_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->vlgrp = grp; - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_6 || - tp->mcfg == CFG_METHOD_7) { - if (tp->vlgrp) { - tp->rtl8125_rx_config |= (EnableInnerVlan | EnableOuterVlan); - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | (EnableInnerVlan | EnableOuterVlan)) - } else { - tp->rtl8125_rx_config &= ~(EnableInnerVlan | EnableOuterVlan); - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(EnableInnerVlan | EnableOuterVlan)) - } - } -} - -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -static void -rtl8125_vlan_rx_kill_vid(struct net_device *dev, - unsigned short vid) -{ - struct rtl8125_private *tp = netdev_priv(dev); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) - if (tp->vlgrp) - tp->vlgrp->vlan_devices[vid] = NULL; -#else - vlan_group_set_device(tp->vlgrp, vid, NULL); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - -static int -rtl8125_rx_vlan_skb(struct rtl8125_private *tp, - struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(rtl8125_rx_desc_opts2(tp, desc)); - int ret = -1; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - if (tp->vlgrp && (opts2 & RxVlanTag)) { - rtl8125_rx_hwaccel_skb(skb, tp->vlgrp, - swab16(opts2 & 0xffff)); - ret = 0; - } -#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) - if (opts2 & RxVlanTag) - __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); -#else - if (opts2 & RxVlanTag) - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff)); -#endif - - rtl8125_clear_rx_desc_opts2(tp, desc); - return ret; -} - -#else /* !CONFIG_R8125_VLAN */ - -static inline u32 -rtl8125_tx_vlan_tag(struct rtl8125_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int -rtl8125_rx_vlan_skb(struct rtl8125_private *tp, - struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) - -static netdev_features_t rtl8125_fix_features(struct net_device *dev, - netdev_features_t features) -{ - if (dev->mtu > MSS_MAX) - features &= ~NETIF_F_ALL_TSO; - if (dev->mtu > ETH_DATA_LEN) { - features &= ~NETIF_F_ALL_TSO; - features &= ~NETIF_F_ALL_CSUM; - } -#ifndef CONFIG_R8125_VLAN - features &= ~NETIF_F_ALL_CSUM; -#endif - - return features; -} - -static int rtl8125_hw_set_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 rx_config; - - rx_config = RTL_R32(tp, RxConfig); - if (features & NETIF_F_RXALL) { - tp->rtl8125_rx_config |= (AcceptErr | AcceptRunt); - rx_config |= (AcceptErr | AcceptRunt); - } else { - tp->rtl8125_rx_config &= ~(AcceptErr | AcceptRunt); - rx_config &= ~(AcceptErr | AcceptRunt); - } - - if (features & NETIF_F_HW_VLAN_RX) { - tp->rtl8125_rx_config |= (EnableInnerVlan | EnableOuterVlan); - rx_config |= (EnableInnerVlan | EnableOuterVlan); - } else { - tp->rtl8125_rx_config &= ~(EnableInnerVlan | EnableOuterVlan); - rx_config &= ~(EnableInnerVlan | EnableOuterVlan); - } - - RTL_W32(tp, RxConfig, rx_config); - - if (features & NETIF_F_RXCSUM) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(tp, CPlusCmd, tp->cp_cmd); - RTL_R16(tp, CPlusCmd); - - return 0; -} - -static int rtl8125_set_features(struct net_device *dev, - netdev_features_t features) -{ - features &= NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX; - - rtl8125_hw_set_features(dev, features); - - return 0; -} - -#endif - -static void rtl8125_gset_xmii(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - struct ethtool_link_ksettings *cmd -#endif - ) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 aner = tp->phy_reg_aner; - u16 anlpar = tp->phy_reg_anlpar; - u16 gbsr = tp->phy_reg_gbsr; - u16 status_2500 = tp->phy_reg_status_2500; - u32 lpa_adv = 0; - u16 status; - u8 autoneg, duplex; - u32 speed = 0; - u16 bmcr; - u32 supported, advertising; - u8 report_lpa = 0; - - supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_2500baseX_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP | - SUPPORTED_Pause | - SUPPORTED_Asym_Pause; - - if (tp->mcfg == CFG_METHOD_6 || tp->mcfg == CFG_METHOD_7) - supported &= ~SUPPORTED_2500baseX_Full; - - advertising = ADVERTISED_TP; - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - bmcr = rtl8125_mdio_read(tp, MII_BMCR); - - if (bmcr & BMCR_ANENABLE) { - advertising |= ADVERTISED_Autoneg; - autoneg = AUTONEG_ENABLE; - - if (tp->phy_auto_nego_reg & ADVERTISE_10HALF) - advertising |= ADVERTISED_10baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_10FULL) - advertising |= ADVERTISED_10baseT_Full; - if (tp->phy_auto_nego_reg & ADVERTISE_100HALF) - advertising |= ADVERTISED_100baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_100FULL) - advertising |= ADVERTISED_100baseT_Full; - if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL) - advertising |= ADVERTISED_1000baseT_Full; - if (tp->phy_2500_ctrl_reg & RTK_ADVERTISE_2500FULL) - advertising |= ADVERTISED_2500baseX_Full; - } else { - autoneg = AUTONEG_DISABLE; - } - - status = RTL_R16(tp, PHYstatus); - if (netif_running(dev) && (status & LinkStatus)) - report_lpa = 1; - - if (report_lpa) { - /*link on*/ - if (status & _2500bpsF) - speed = SPEED_2500; - else if (status & _1000bpsF) - speed = SPEED_1000; - else if (status & _100bps) - speed = SPEED_100; - else if (status & _10bps) - speed = SPEED_10; - - if (status & TxFlowCtrl) - advertising |= ADVERTISED_Asym_Pause; - - if (status & RxFlowCtrl) - advertising |= ADVERTISED_Pause; - - duplex = ((status & (_1000bpsF | _2500bpsF)) || (status & FullDup)) ? - DUPLEX_FULL : DUPLEX_HALF; - - /*link partner*/ - if (aner & EXPANSION_NWAY) - lpa_adv |= ADVERTISED_Autoneg; - if (anlpar & LPA_10HALF) - lpa_adv |= ADVERTISED_10baseT_Half; - if (anlpar & LPA_10FULL) - lpa_adv |= ADVERTISED_10baseT_Full; - if (anlpar & LPA_100HALF) - lpa_adv |= ADVERTISED_100baseT_Half; - if (anlpar & LPA_100FULL) - lpa_adv |= ADVERTISED_100baseT_Full; - if (anlpar & LPA_PAUSE_CAP) - lpa_adv |= ADVERTISED_Pause; - if (anlpar & LPA_PAUSE_ASYM) - lpa_adv |= ADVERTISED_Asym_Pause; - if (gbsr & LPA_1000HALF) - lpa_adv |= ADVERTISED_1000baseT_Half; - if (gbsr & LPA_1000FULL) - lpa_adv |= ADVERTISED_1000baseT_Full; - if (status_2500 & RTK_LPA_ADVERTISE_2500FULL) - lpa_adv |= ADVERTISED_2500baseX_Full; - } else { - /*link down*/ - speed = SPEED_UNKNOWN; - duplex = DUPLEX_UNKNOWN; - lpa_adv = 0; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - cmd->supported = supported; - cmd->advertising = advertising; - cmd->autoneg = autoneg; - cmd->speed = speed; - cmd->duplex = duplex; - cmd->port = PORT_TP; - cmd->lp_advertising = lpa_adv; -#else - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, - supported); - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, - advertising); - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, - lpa_adv); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,0,0) - if (supported & SUPPORTED_2500baseX_Full) { - linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, - cmd->link_modes.supported, 0); - linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - cmd->link_modes.supported, 1); - } - if (advertising & ADVERTISED_2500baseX_Full) { - linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, - cmd->link_modes.advertising, 0); - linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - cmd->link_modes.advertising, 1); - } - if (report_lpa) { - if (lpa_adv & ADVERTISED_2500baseX_Full) { - linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, - cmd->link_modes.lp_advertising, 0); - linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, - cmd->link_modes.lp_advertising, 1); - } - if (status_2500 & RTK_LPA_ADVERTISE_5000FULL) - linkmode_mod_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, - cmd->link_modes.lp_advertising, 1); - if (status_2500 & RTK_LPA_ADVERTISE_10000FULL) - linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, - cmd->link_modes.lp_advertising, 1); - } -#endif - cmd->base.autoneg = autoneg; - cmd->base.speed = speed; - cmd->base.duplex = duplex; - cmd->base.port = PORT_TP; -#endif -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int -rtl8125_get_settings(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - struct ethtool_link_ksettings *cmd -#endif - ) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->get_settings(dev, cmd); - - return 0; -} - -static void rtl8125_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8125_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - u8 *data = p; - - if (regs->len < R8125_REGS_DUMP_SIZE) - return /* -EINVAL */; - - memset(p, 0, regs->len); - - for (i = 0; i < R8125_MAC_REGS_SIZE; i++) - *data++ = readb(ioaddr + i); - data = (u8*)p + 256; - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - for (i = 0; i < R8125_PHY_REGS_SIZE/2; i++) { - *(u16*)data = rtl8125_mdio_read(tp, i); - data += 2; - } - data = (u8*)p + 256 * 2; - - for (i = 0; i < R8125_EPHY_REGS_SIZE/2; i++) { - *(u16*)data = rtl8125_ephy_read(tp, i); - data += 2; - } - data = (u8*)p + 256 * 3; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - default: - for (i = 0; i < R8125_ERI_REGS_SIZE; i+=4) { - *(u32*)data = rtl8125_eri_read(tp, i , 4, ERIAR_ExGMAC); - data += 4; - } - break; - } -} - -static void rtl8125_get_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *pause) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - pause->autoneg = (tp->autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE); - if (tp->fcpause == rtl8125_fc_rx_pause) - pause->rx_pause = 1; - else if (tp->fcpause == rtl8125_fc_tx_pause) - pause->tx_pause = 1; - else if (tp->fcpause == rtl8125_fc_full) { - pause->rx_pause = 1; - pause->tx_pause = 1; - } -} - -static int rtl8125_set_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *pause) -{ - struct rtl8125_private *tp = netdev_priv(dev); - enum rtl8125_fc_mode newfc; - - if (pause->tx_pause || pause->rx_pause) - newfc = rtl8125_fc_full; - else - newfc = rtl8125_fc_none; - - if (tp->fcpause != newfc) { - tp->fcpause = newfc; - - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - } - - return 0; - -} - -static u32 -rtl8125_get_msglevel(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void -rtl8125_set_msglevel(struct net_device *dev, - u32 value) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8125_gstrings[][ETH_GSTRING_LEN] = { - /* legacy */ - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", - - /* extended */ - "tx_octets", - "rx_octets", - "rx_multicast64", - "tx_unicast64", - "tx_broadcast64", - "tx_multicast64", - "tx_pause_on", - "tx_pause_off", - "tx_pause_all", - "tx_deferred", - "tx_late_collision", - "tx_all_collision", - "tx_aborted32", - "align_errors32", - "rx_frame_too_long", - "rx_runt", - "rx_pause_on", - "rx_pause_off", - "rx_pause_all", - "rx_unknown_opcode", - "rx_mac_error", - "tx_underrun32", - "rx_mac_missed", - "rx_tcam_dropped", - "tdu", - "rdu", -}; -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int rtl8125_get_stats_count(struct net_device *dev) -{ - return ARRAY_SIZE(rtl8125_gstrings); -} -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -#else -static int rtl8125_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8125_gstrings); - default: - return -EOPNOTSUPP; - } -} -#endif - -static void -rtl8125_set_ring_size(struct rtl8125_private *tp, u32 rx, u32 tx) -{ - int i; - - for (i = 0; i < tp->num_rx_rings; i++) - tp->rx_ring[i].num_rx_desc = rx; - - for (i = 0; i < tp->num_tx_rings; i++) - tp->tx_ring[i].num_tx_desc = tx; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) -static void rtl8125_get_ringparam(struct net_device *dev, - struct ethtool_ringparam *ring, - struct kernel_ethtool_ringparam *kernel_ring, - struct netlink_ext_ack *extack) -#else -static void rtl8125_get_ringparam(struct net_device *dev, - struct ethtool_ringparam *ring) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - ring->rx_max_pending = MAX_NUM_TX_DESC; - ring->tx_max_pending = MAX_NUM_RX_DESC;; - ring->rx_pending = tp->rx_ring[0].num_rx_desc; - ring->tx_pending = tp->tx_ring[0].num_tx_desc; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) -static int rtl8125_set_ringparam(struct net_device *dev, - struct ethtool_ringparam *ring, - struct kernel_ethtool_ringparam *kernel_ring, - struct netlink_ext_ack *extack) -#else -static int rtl8125_set_ringparam(struct net_device *dev, - struct ethtool_ringparam *ring) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 new_rx_count, new_tx_count; - int rc = 0; - - if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending)) - return -EINVAL; - - new_tx_count = clamp_t(u32, ring->tx_pending, - MIN_NUM_TX_DESC, MAX_NUM_TX_DESC); - - new_rx_count = clamp_t(u32, ring->rx_pending, - MIN_NUM_RX_DESC, MAX_NUM_RX_DESC); - - if ((new_rx_count == tp->rx_ring[0].num_rx_desc) && - (new_tx_count == tp->tx_ring[0].num_tx_desc)) { - /* nothing to do */ - return 0; - } - - if (netif_running(dev)) { - rtl8125_wait_for_quiescence(dev); - rtl8125_close(dev); - } - - rtl8125_set_ring_size(tp, new_rx_count, new_tx_count); - - if (netif_running(dev)) - rc = rtl8125_open(dev); - - return rc; -} -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static void -rtl8125_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, - u64 *data) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct rtl8125_counters *counters; - dma_addr_t paddr; - - ASSERT_RTNL(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) - return; - - rtl8125_dump_tally_counter(tp, paddr); - - data[0] = le64_to_cpu(counters->tx_packets); - data[1] = le64_to_cpu(counters->rx_packets); - data[2] = le64_to_cpu(counters->tx_errors); - data[3] = le32_to_cpu(counters->rx_errors); - data[4] = le16_to_cpu(counters->rx_missed); - data[5] = le16_to_cpu(counters->align_errors); - data[6] = le32_to_cpu(counters->tx_one_collision); - data[7] = le32_to_cpu(counters->tx_multi_collision); - data[8] = le64_to_cpu(counters->rx_unicast); - data[9] = le64_to_cpu(counters->rx_broadcast); - data[10] = le32_to_cpu(counters->rx_multicast); - data[11] = le16_to_cpu(counters->tx_aborted); - data[12] = le16_to_cpu(counters->tx_underrun); - - data[13] = le64_to_cpu(counters->tx_octets); - data[14] = le64_to_cpu(counters->rx_octets); - data[15] = le64_to_cpu(counters->rx_multicast64); - data[16] = le64_to_cpu(counters->tx_unicast64); - data[17] = le64_to_cpu(counters->tx_broadcast64); - data[18] = le64_to_cpu(counters->tx_multicast64); - data[19] = le32_to_cpu(counters->tx_pause_on); - data[20] = le32_to_cpu(counters->tx_pause_off); - data[21] = le32_to_cpu(counters->tx_pause_all); - data[22] = le32_to_cpu(counters->tx_deferred); - data[23] = le32_to_cpu(counters->tx_late_collision); - data[24] = le32_to_cpu(counters->tx_all_collision); - data[25] = le32_to_cpu(counters->tx_aborted32); - data[26] = le32_to_cpu(counters->align_errors32); - data[27] = le32_to_cpu(counters->rx_frame_too_long); - data[28] = le32_to_cpu(counters->rx_runt); - data[29] = le32_to_cpu(counters->rx_pause_on); - data[30] = le32_to_cpu(counters->rx_pause_off); - data[31] = le32_to_cpu(counters->rx_pause_all); - data[32] = le32_to_cpu(counters->rx_unknown_opcode); - data[33] = le32_to_cpu(counters->rx_mac_error); - data[34] = le32_to_cpu(counters->tx_underrun32); - data[35] = le32_to_cpu(counters->rx_mac_missed); - data[36] = le32_to_cpu(counters->rx_tcam_dropped); - data[37] = le32_to_cpu(counters->tdu); - data[38] = le32_to_cpu(counters->rdu); -} - -static void -rtl8125_get_strings(struct net_device *dev, - u32 stringset, - u8 *data) -{ - switch (stringset) { - case ETH_SS_STATS: - memcpy(data, rtl8125_gstrings, sizeof(rtl8125_gstrings)); - break; - } -} -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -static int rtl_get_eeprom_len(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - return tp->eeprom_len; -} - -static int rtl_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *buf) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i,j,ret; - int start_w, end_w; - int VPD_addr, VPD_data; - u32 *eeprom_buff; - u16 tmp; - - if (tp->eeprom_type == EEPROM_TYPE_NONE) { - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Detect none EEPROM\n"); - return -EOPNOTSUPP; - } else if (eeprom->len == 0 || (eeprom->offset+eeprom->len) > tp->eeprom_len) { - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Invalid parameter\n"); - return -EINVAL; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - default: - VPD_addr = 0xD2; - VPD_data = 0xD4; - break; - } - - start_w = eeprom->offset >> 2; - end_w = (eeprom->offset + eeprom->len - 1) >> 2; - - eeprom_buff = kmalloc(sizeof(u32)*(end_w - start_w + 1), GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - rtl8125_enable_cfg9346_write(tp); - ret = -EFAULT; - for (i=start_w; i<=end_w; i++) { - pci_write_config_word(tp->pci_dev, VPD_addr, (u16)i*4); - ret = -EFAULT; - for (j = 0; j < 10; j++) { - udelay(400); - pci_read_config_word(tp->pci_dev, VPD_addr, &tmp); - if (tmp&0x8000) { - ret = 0; - break; - } - } - - if (ret) - break; - - pci_read_config_dword(tp->pci_dev, VPD_data, &eeprom_buff[i-start_w]); - } - rtl8125_disable_cfg9346_write(tp); - - if (!ret) - memcpy(buf, (u8 *)eeprom_buff + (eeprom->offset & 3), eeprom->len); - - kfree(eeprom_buff); - - return ret; -} - -#undef ethtool_op_get_link -#define ethtool_op_get_link _kc_ethtool_op_get_link -static u32 _kc_ethtool_op_get_link(struct net_device *dev) -{ - return netif_carrier_ok(dev) ? 1 : 0; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#undef ethtool_op_get_sg -#define ethtool_op_get_sg _kc_ethtool_op_get_sg -static u32 _kc_ethtool_op_get_sg(struct net_device *dev) -{ -#ifdef NETIF_F_SG - return (dev->features & NETIF_F_SG) != 0; -#else - return 0; -#endif -} - -#undef ethtool_op_set_sg -#define ethtool_op_set_sg _kc_ethtool_op_set_sg -static int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - -#ifdef NETIF_F_SG - if (data) - dev->features |= NETIF_F_SG; - else - dev->features &= ~NETIF_F_SG; -#endif - - return 0; -} -#endif - -static int rtl8125_enable_eee(struct rtl8125_private *tp) -{ - struct ethtool_eee *eee = &tp->eee; - u16 eee_adv_t = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); - int ret; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_6: - RTL_W16(tp, EEE_TXIDLE_TIMER_8125, eee->tx_lpi_timer); - - SetMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); - SetMcuAccessRegBit(tp, 0xEB62, (BIT_2|BIT_1)); - - SetEthPhyOcpBit(tp, 0xA432, BIT_4); - ClearAndSetEthPhyOcpBit(tp, - 0xA5D0, - MDIO_EEE_100TX | MDIO_EEE_1000T, - eee_adv_t); - ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); - - ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); - ClearEthPhyOcpBit(tp, 0xA428, BIT_7); - ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - RTL_W16(tp, EEE_TXIDLE_TIMER_8125, eee->tx_lpi_timer); - - SetMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); - - ClearAndSetEthPhyOcpBit(tp, - 0xA5D0, - MDIO_EEE_100TX | MDIO_EEE_1000T, - eee_adv_t); - if (eee->advertised & SUPPORTED_2500baseX_Full) - SetEthPhyOcpBit(tp, 0xA6D4, BIT_0); - else - ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); - - ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); - ClearEthPhyOcpBit(tp, 0xA428, BIT_7); - ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); - break; - default: -// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEE\n"); - ret = -EOPNOTSUPP; - break; - } - - /*Advanced EEE*/ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_set_phy_mcu_patch_request(tp); - ClearMcuAccessRegBit(tp, 0xE052, BIT_0); - ClearEthPhyOcpBit(tp, 0xA442, BIT_12 | BIT_13); - ClearEthPhyOcpBit(tp, 0xA430, BIT_15); - rtl8125_clear_phy_mcu_patch_request(tp); - break; - } - - return ret; -} - -static int rtl8125_disable_eee(struct rtl8125_private *tp) -{ - int ret; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_6: - ClearMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); - ClearMcuAccessRegBit(tp, 0xEB62, (BIT_2|BIT_1)); - - ClearEthPhyOcpBit(tp, 0xA432, BIT_4); - ClearEthPhyOcpBit(tp, 0xA5D0, (BIT_2 | BIT_1)); - ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); - - ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); - ClearEthPhyOcpBit(tp, 0xA428, BIT_7); - ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - ClearMcuAccessRegBit(tp, 0xE040, (BIT_1|BIT_0)); - - ClearEthPhyOcpBit(tp, 0xA5D0, (BIT_2 | BIT_1)); - ClearEthPhyOcpBit(tp, 0xA6D4, BIT_0); - - ClearEthPhyOcpBit(tp, 0xA6D8, BIT_4); - ClearEthPhyOcpBit(tp, 0xA428, BIT_7); - ClearEthPhyOcpBit(tp, 0xA4A2, BIT_9); - break; - default: -// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEE\n"); - ret = -EOPNOTSUPP; - break; - } - - /*Advanced EEE*/ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_set_phy_mcu_patch_request(tp); - ClearMcuAccessRegBit(tp, 0xE052, BIT_0); - ClearEthPhyOcpBit(tp, 0xA442, BIT_12 | BIT_13); - ClearEthPhyOcpBit(tp, 0xA430, BIT_15); - rtl8125_clear_phy_mcu_patch_request(tp); - break; - } - - return ret; -} - -static int rtl_nway_reset(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret, bmcr; - - if (unlikely(tp->rtk_enable_diag)) - return -EBUSY; - - /* if autoneg is off, it's an error */ - rtl8125_mdio_write(tp, 0x1F, 0x0000); - bmcr = rtl8125_mdio_read(tp, MII_BMCR); - - if (bmcr & BMCR_ANENABLE) { - bmcr |= BMCR_ANRESTART; - rtl8125_mdio_write(tp, MII_BMCR, bmcr); - ret = 0; - } else { - ret = -EINVAL; - } - - return ret; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) -static u32 -rtl8125_tx_lpi_timer_to_us(struct rtl8125_private *tp , u32 tx_lpi_timer) -{ - u32 to_us; - u16 status; - - //2.5G : tx_lpi_timer * 3.2ns - //Giga: tx_lpi_timer * 8ns - //100M : tx_lpi_timer * 80ns - to_us = tx_lpi_timer * 80; - status = RTL_R16(tp, PHYstatus); - if (status & LinkStatus) { - /*link on*/ - if (status & _2500bpsF) - to_us = (tx_lpi_timer * 32) / 10; - else if (status & _1000bpsF) - to_us = tx_lpi_timer * 8; - } - - //ns to us - to_us /= 1000; - - return to_us; -} - -static int -rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *edata) -{ - struct rtl8125_private *tp = netdev_priv(net); - struct ethtool_eee *eee = &tp->eee; - u32 lp, adv, tx_lpi_timer, supported = 0; - u16 val; - - if (unlikely(tp->rtk_enable_diag)) - return -EBUSY; - - /* Get Supported EEE */ - //val = mdio_direct_read_phy_ocp(tp, 0xA5C4); - //supported = mmd_eee_cap_to_ethtool_sup_t(val); - supported = eee->supported; - - /* Get advertisement EEE */ - val = mdio_direct_read_phy_ocp(tp, 0xA5D0); - adv = mmd_eee_adv_to_ethtool_adv_t(val); - val = mdio_direct_read_phy_ocp(tp, 0xA6D4); - if (val & RTK_EEE_ADVERTISE_2500FULL) - adv |= ADVERTISED_2500baseX_Full; - - /* Get LP advertisement EEE */ - val = mdio_direct_read_phy_ocp(tp, 0xA5D2); - lp = mmd_eee_adv_to_ethtool_adv_t(val); - val = mdio_direct_read_phy_ocp(tp, 0xA6D0); - if (val & RTK_LPA_EEE_ADVERTISE_2500FULL) - lp |= ADVERTISED_2500baseX_Full; - - /* Get EEE Tx LPI timer*/ - tx_lpi_timer = RTL_R16(tp, EEE_TXIDLE_TIMER_8125); - - val = rtl8125_mac_ocp_read(tp, 0xE040); - val &= BIT_1 | BIT_0; - - edata->eee_enabled = !!val; - edata->eee_active = !!(supported & adv & lp); - edata->supported = supported; - edata->advertised = adv; - edata->lp_advertised = lp; - edata->tx_lpi_enabled = edata->eee_enabled; - edata->tx_lpi_timer = rtl8125_tx_lpi_timer_to_us(tp, tx_lpi_timer); - - return 0; -} - -static int -rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *edata) -{ - struct rtl8125_private *tp = netdev_priv(net); - struct ethtool_eee *eee = &tp->eee; - u32 advertising; - int rc = 0; - - if (!HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp) || - tp->DASH) - return -EOPNOTSUPP; - - if (unlikely(tp->rtk_enable_diag)) { - dev_printk(KERN_WARNING, tp_to_dev(tp), "Diag Enabled\n"); - rc = -EBUSY; - goto out; - } - - if (tp->autoneg != AUTONEG_ENABLE) { - dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE requires autoneg\n"); - rc = -EINVAL; - goto out; - } - - if (edata->tx_lpi_enabled) { - if (edata->tx_lpi_timer > tp->max_jumbo_frame_size || - edata->tx_lpi_timer < ETH_MIN_MTU) { - dev_printk(KERN_WARNING, tp_to_dev(tp), "Valid LPI timer range is %d to %d. \n", - ETH_MIN_MTU, tp->max_jumbo_frame_size); - rc = -EINVAL; - goto out; - } - } - - advertising = tp->advertising; - if (!edata->advertised) { - edata->advertised = advertising & eee->supported; - } else if (edata->advertised & ~advertising) { - dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE advertised %x must be a subset of autoneg advertised speeds %x\n", - edata->advertised, advertising); - rc = -EINVAL; - goto out; - } - - if (edata->advertised & ~eee->supported) { - dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE advertised %x must be a subset of support %x\n", - edata->advertised, eee->supported); - rc = -EINVAL; - goto out; - } - - //tp->eee.eee_enabled = edata->eee_enabled; - //tp->eee_adv_t = ethtool_adv_to_mmd_eee_adv_t(edata->advertised); - - dev_printk(KERN_WARNING, tp_to_dev(tp), "EEE tx_lpi_timer %x must be a subset of support %x\n", - edata->tx_lpi_timer, eee->tx_lpi_timer); - - eee->advertised = edata->advertised; - eee->tx_lpi_enabled = edata->tx_lpi_enabled; - eee->tx_lpi_timer = edata->tx_lpi_timer; - eee->eee_enabled = edata->eee_enabled; - - if (eee->eee_enabled) - rtl8125_enable_eee(tp); - else - rtl8125_disable_eee(tp); - - rtl_nway_reset(net); - - return rc; - -out: - - return rc; -} -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static const struct ethtool_ops rtl8125_ethtool_ops = { - .get_drvinfo = rtl8125_get_drvinfo, - .get_regs_len = rtl8125_get_regs_len, - .get_link = ethtool_op_get_link, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - .get_ringparam = rtl8125_get_ringparam, - .set_ringparam = rtl8125_set_ringparam, -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - .get_settings = rtl8125_get_settings, - .set_settings = rtl8125_set_settings, -#else - .get_link_ksettings = rtl8125_get_settings, - .set_link_ksettings = rtl8125_set_settings, -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - .get_pauseparam = rtl8125_get_pauseparam, - .set_pauseparam = rtl8125_set_pauseparam, -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) - .get_msglevel = rtl8125_get_msglevel, - .set_msglevel = rtl8125_set_msglevel, -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - .get_rx_csum = rtl8125_get_rx_csum, - .set_rx_csum = rtl8125_set_rx_csum, - .get_tx_csum = rtl8125_get_tx_csum, - .set_tx_csum = rtl8125_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, -#ifdef NETIF_F_TSO - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, -#endif //NETIF_F_TSO -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - .get_regs = rtl8125_get_regs, - .get_wol = rtl8125_get_wol, - .set_wol = rtl8125_set_wol, - .get_strings = rtl8125_get_strings, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) - .get_stats_count = rtl8125_get_stats_count, -#else - .get_sset_count = rtl8125_get_sset_count, -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) - .get_ethtool_stats = rtl8125_get_ethtool_stats, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) -#ifdef ETHTOOL_GPERMADDR - .get_perm_addr = ethtool_op_get_perm_addr, -#endif //ETHTOOL_GPERMADDR -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) - .get_eeprom = rtl_get_eeprom, - .get_eeprom_len = rtl_get_eeprom_len, -#ifdef ENABLE_RSS_SUPPORT - .get_rxnfc = rtl8125_get_rxnfc, - .set_rxnfc = rtl8125_set_rxnfc, - .get_rxfh_indir_size = rtl8125_rss_indir_size, - .get_rxfh_key_size = rtl8125_get_rxfh_key_size, - .get_rxfh = rtl8125_get_rxfh, - .set_rxfh = rtl8125_set_rxfh, -#endif //ENABLE_RSS_SUPPORT -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) -#ifdef ENABLE_PTP_SUPPORT - .get_ts_info = rtl8125_get_ts_info, -#else - .get_ts_info = ethtool_op_get_ts_info, -#endif //ENABLE_PTP_SUPPORT -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) - .get_eee = rtl_ethtool_get_eee, - .set_eee = rtl_ethtool_set_eee, -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ - .nway_reset = rtl_nway_reset, - -}; -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -#if 0 - -static int rtl8125_enable_green_feature(struct rtl8125_private *tp) -{ - u16 gphy_val; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8011); - SetEthPhyOcpBit(tp, 0xA438, BIT_15); - rtl8125_mdio_write(tp, 0x00, 0x9200); - break; - default: - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support Green Feature\n"); - break; - } - - return 0; -} - -static int rtl8125_disable_green_feature(struct rtl8125_private *tp) -{ - u16 gphy_val; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8011); - ClearEthPhyOcpBit(tp, 0xA438, BIT_15); - rtl8125_mdio_write(tp, 0x00, 0x9200); - break; - default: - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support Green Feature\n"); - break; - } - - return 0; -} - -#endif - -static void rtl8125_get_mac_version(struct rtl8125_private *tp) -{ - u32 reg,val32; - u32 ICVerID; - struct pci_dev *pdev = tp->pci_dev; - - val32 = RTL_R32(tp, TxConfig); - reg = val32 & 0x7c800000; - ICVerID = val32 & 0x00700000; - - switch (reg) { - case 0x60800000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_2; - } else if (ICVerID == 0x100000) { - tp->mcfg = CFG_METHOD_3; - } else { - tp->mcfg = CFG_METHOD_3; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V4; - break; - case 0x64000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_4; - } else if (ICVerID == 0x100000) { - tp->mcfg = CFG_METHOD_5; - } else { - tp->mcfg = CFG_METHOD_5; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V4; - break; - default: - printk("unknown chip version (%x)\n",reg); - tp->mcfg = CFG_METHOD_DEFAULT; - tp->HwIcVerUnknown = TRUE; - tp->efuse_ver = EFUSE_NOT_SUPPORT; - break; - } - - if (pdev->subsystem_vendor == 0x8162) { - if (tp->mcfg == CFG_METHOD_3) - tp->mcfg = CFG_METHOD_6; - else if (tp->mcfg == CFG_METHOD_5) - tp->mcfg = CFG_METHOD_7; - } -} - -static void -rtl8125_print_mac_version(struct rtl8125_private *tp) -{ - int i; - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { - if (tp->mcfg == rtl_chip_info[i].mcfg) { - dprintk("Realtek PCIe 2.5GbE Family Controller mcfg = %04d\n", - rtl_chip_info[i].mcfg); - return; - } - } - - dprintk("mac_version == Unknown\n"); -} - -static void -rtl8125_tally_counter_addr_fill(struct rtl8125_private *tp) -{ - if (!tp->tally_paddr) - return; - - RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); - RTL_W32(tp, CounterAddrLow, (u64)tp->tally_paddr & (DMA_BIT_MASK(32))); -} - -static void -rtl8125_tally_counter_clear(struct rtl8125_private *tp) -{ - if (!tp->tally_paddr) - return; - - RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); - RTL_W32(tp, CounterAddrLow, ((u64)tp->tally_paddr & (DMA_BIT_MASK(32))) | CounterReset); -} - -static void -rtl8125_clear_phy_ups_reg(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - ClearEthPhyOcpBit(tp, 0xA466, BIT_0); - break; - }; - ClearEthPhyOcpBit(tp, 0xA468, BIT_3 | BIT_1); -} - -static int -rtl8125_is_ups_resume(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_6 || - tp->mcfg == CFG_METHOD_7) - return (rtl8125_mac_ocp_read(tp, 0xD42C) & BIT_8); - - return 0; -} - -static void -rtl8125_clear_ups_resume_bit(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_6 || - tp->mcfg == CFG_METHOD_7) - rtl8125_mac_ocp_write(tp, 0xD408, rtl8125_mac_ocp_read(tp, 0xD408) & ~(BIT_8)); -} - -static void -rtl8125_wait_phy_ups_resume(struct net_device *dev, u16 PhyState) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 TmpPhyState; - int i=0; - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_6 || - tp->mcfg == CFG_METHOD_7) { - do { - TmpPhyState = mdio_direct_read_phy_ocp(tp, 0xA420); - TmpPhyState &= 0x7; - mdelay(1); - i++; - } while ((i < 100) && (TmpPhyState != PhyState)); - } - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(i == 100); -#endif -} - -void -rtl8125_enable_now_is_oob(struct rtl8125_private *tp) -{ - if ( tp->HwSuppNowIsOobVer == 1 ) { - RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) | Now_is_oob); - } -} - -void -rtl8125_disable_now_is_oob(struct rtl8125_private *tp) -{ - if ( tp->HwSuppNowIsOobVer == 1 ) { - RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) & ~Now_is_oob); - } -} - -static void -rtl8125_exit_oob(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 data16; - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(AcceptErr | AcceptRunt | AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys)); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_6: - rtl8125_dash2_disable_txrx(dev); - break; - } - - if (tp->DASH) { - rtl8125_driver_stop(tp); - rtl8125_driver_start(tp); -#ifdef ENABLE_DASH_SUPPORT - DashHwInit(dev); -#endif - } - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8125_realwow_hw_init(dev); -#else - //Disable realwow function - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_mac_ocp_write(tp, 0xC0BC, 0x00FF); - break; - } -#endif //ENABLE_REALWOW_SUPPORT - - rtl8125_nic_reset(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_disable_now_is_oob(tp); - - data16 = rtl8125_mac_ocp_read(tp, 0xE8DE) & ~BIT_14; - rtl8125_mac_ocp_write(tp, 0xE8DE, data16); - rtl8125_wait_ll_share_fifo_ready(dev); - - rtl8125_mac_ocp_write(tp, 0xC0AA, 0x07D0); - rtl8125_mac_ocp_write(tp, 0xC0A6, 0x01B5); - rtl8125_mac_ocp_write(tp, 0xC01E, 0x5555); - - rtl8125_wait_ll_share_fifo_ready(dev); - break; - } - - //wait ups resume (phy state 2) - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - if (rtl8125_is_ups_resume(dev)) { - rtl8125_wait_phy_ups_resume(dev, 2); - rtl8125_clear_ups_resume_bit(dev); - rtl8125_clear_phy_ups_reg(dev); - } - break; - }; -} - -void -rtl8125_hw_disable_mac_mcu_bps(struct net_device *dev) -{ - u16 regAddr; - - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_enable_cfg9346_write(tp); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - rtl8125_disable_cfg9346_write(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_mac_ocp_write(tp, 0xFC48, 0x0000); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - for (regAddr = 0xFC28; regAddr < 0xFC48; regAddr += 2) { - rtl8125_mac_ocp_write(tp, regAddr, 0x0000); - } - - mdelay(3); - - rtl8125_mac_ocp_write(tp, 0xFC26, 0x0000); - break; - } -} - -#ifndef ENABLE_USE_FIRMWARE_FILE -static void -rtl8125_switch_mac_mcu_ram_code_page(struct rtl8125_private *tp, u16 page) -{ - u16 tmpUshort; - - page &= (BIT_1 | BIT_0); - tmpUshort = rtl8125_mac_ocp_read(tp, 0xE446); - tmpUshort &= ~(BIT_1 | BIT_0); - tmpUshort |= page; - rtl8125_mac_ocp_write(tp, 0xE446, tmpUshort); -} - -static void -_rtl8125_write_mac_mcu_ram_code(struct rtl8125_private *tp, const u16 *entry, u16 entry_cnt) -{ - u16 i; - - for (i = 0; i < entry_cnt; i++) { - rtl8125_mac_ocp_write(tp, 0xF800 + i * 2, entry[i]); - } -} - -static void -_rtl8125_write_mac_mcu_ram_code_with_page(struct rtl8125_private *tp, const u16 *entry, u16 entry_cnt, u16 page_size) -{ - u16 i; - u16 offset; - - if (page_size == 0) return; - - for (i = 0; i < entry_cnt; i++) { - offset = i % page_size; - if (offset == 0) { - u16 page = (i / page_size); - rtl8125_switch_mac_mcu_ram_code_page(tp, page); - } - rtl8125_mac_ocp_write(tp, 0xF800 + offset * 2, entry[i]); - } -} - -static void -rtl8125_write_mac_mcu_ram_code(struct rtl8125_private *tp, const u16 *entry, u16 entry_cnt) -{ - if (FALSE == HW_SUPPORT_MAC_MCU(tp)) return; - if (entry == NULL || entry_cnt == 0) return; - - if (tp->MacMcuPageSize > 0) - _rtl8125_write_mac_mcu_ram_code_with_page(tp, entry, entry_cnt, tp->MacMcuPageSize); - else - _rtl8125_write_mac_mcu_ram_code(tp, entry, entry_cnt); -} - -static void -rtl8125_set_mac_mcu_8125a_1(struct net_device *dev) -{ - rtl8125_hw_disable_mac_mcu_bps(dev); -} - -static void -rtl8125_set_mac_mcu_8125a_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - static const u16 mcu_patch_code_8125a_2[] = { - 0xE010, 0xE012, 0xE022, 0xE024, 0xE029, 0xE02B, 0xE094, 0xE09D, 0xE09F, - 0xE0AA, 0xE0B5, 0xE0C6, 0xE0CC, 0xE0D1, 0xE0D6, 0xE0D8, 0xC602, 0xBE00, - 0x0000, 0xC60F, 0x73C4, 0x49B3, 0xF106, 0x73C2, 0xC608, 0xB406, 0xC609, - 0xFF80, 0xC605, 0xB406, 0xC605, 0xFF80, 0x0544, 0x0568, 0xE906, 0xCDE8, - 0xC602, 0xBE00, 0x0000, 0x48C1, 0x48C2, 0x9C46, 0xC402, 0xBC00, 0x0A12, - 0xC602, 0xBE00, 0x0EBA, 0x1501, 0xF02A, 0x1500, 0xF15D, 0xC661, 0x75C8, - 0x49D5, 0xF00A, 0x49D6, 0xF008, 0x49D7, 0xF006, 0x49D8, 0xF004, 0x75D2, - 0x49D9, 0xF150, 0xC553, 0x77A0, 0x75C8, 0x4855, 0x4856, 0x4857, 0x4858, - 0x48DA, 0x48DB, 0x49FE, 0xF002, 0x485A, 0x49FF, 0xF002, 0x485B, 0x9DC8, - 0x75D2, 0x4859, 0x9DD2, 0xC643, 0x75C0, 0x49D4, 0xF033, 0x49D0, 0xF137, - 0xE030, 0xC63A, 0x75C8, 0x49D5, 0xF00E, 0x49D6, 0xF00C, 0x49D7, 0xF00A, - 0x49D8, 0xF008, 0x75D2, 0x49D9, 0xF005, 0xC62E, 0x75C0, 0x49D7, 0xF125, - 0xC528, 0x77A0, 0xC627, 0x75C8, 0x4855, 0x4856, 0x4857, 0x4858, 0x48DA, - 0x48DB, 0x49FE, 0xF002, 0x485A, 0x49FF, 0xF002, 0x485B, 0x9DC8, 0x75D2, - 0x4859, 0x9DD2, 0xC616, 0x75C0, 0x4857, 0x9DC0, 0xC613, 0x75C0, 0x49DA, - 0xF003, 0x49D0, 0xF107, 0xC60B, 0xC50E, 0x48D9, 0x9DC0, 0x4859, 0x9DC0, - 0xC608, 0xC702, 0xBF00, 0x3AE0, 0xE860, 0xB400, 0xB5D4, 0xE908, 0xE86C, - 0x1200, 0xC409, 0x6780, 0x48F1, 0x8F80, 0xC404, 0xC602, 0xBE00, 0x10AA, - 0xC010, 0xEA7C, 0xC602, 0xBE00, 0x0000, 0x740A, 0x4846, 0x4847, 0x9C0A, - 0xC607, 0x74C0, 0x48C6, 0x9CC0, 0xC602, 0xBE00, 0x13FE, 0xE054, 0x72CA, - 0x4826, 0x4827, 0x9ACA, 0xC607, 0x72C0, 0x48A6, 0x9AC0, 0xC602, 0xBE00, - 0x07DC, 0xE054, 0xC60F, 0x74C4, 0x49CC, 0xF109, 0xC60C, 0x74CA, 0x48C7, - 0x9CCA, 0xC609, 0x74C0, 0x4846, 0x9CC0, 0xC602, 0xBE00, 0x2480, 0xE092, - 0xE0C0, 0xE054, 0x7420, 0x48C0, 0x9C20, 0x7444, 0xC602, 0xBE00, 0x12F8, - 0x1BFF, 0x46EB, 0x1BFF, 0xC102, 0xB900, 0x0D5A, 0x1BFF, 0x46EB, 0x1BFF, - 0xC102, 0xB900, 0x0E2A, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, - 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x6486, - 0x0B15, 0x090E, 0x1139 - }; - - rtl8125_hw_disable_mac_mcu_bps(dev); - - rtl8125_write_mac_mcu_ram_code(tp, mcu_patch_code_8125a_2, ARRAY_SIZE(mcu_patch_code_8125a_2)); - - rtl8125_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0540); - rtl8125_mac_ocp_write(tp, 0xFC2E, 0x0A06); - rtl8125_mac_ocp_write(tp, 0xFC30, 0x0EB8); - rtl8125_mac_ocp_write(tp, 0xFC32, 0x3A5C); - rtl8125_mac_ocp_write(tp, 0xFC34, 0x10A8); - rtl8125_mac_ocp_write(tp, 0xFC40, 0x0D54); - rtl8125_mac_ocp_write(tp, 0xFC42, 0x0E24); - - rtl8125_mac_ocp_write(tp, 0xFC48, 0x307A); -} - -static void -rtl8125_set_mac_mcu_8125b_1(struct net_device *dev) -{ - rtl8125_hw_disable_mac_mcu_bps(dev); -} - -static void -rtl8125_set_mac_mcu_8125b_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - static const u16 mcu_patch_code_8125b_2[] = { - 0xE010, 0xE01B, 0xE026, 0xE037, 0xE03D, 0xE057, 0xE05B, 0xE060, 0xE062, - 0xE064, 0xE066, 0xE068, 0xE06A, 0xE06C, 0xE06E, 0xE070, 0x740A, 0x4846, - 0x4847, 0x9C0A, 0xC607, 0x74C0, 0x48C6, 0x9CC0, 0xC602, 0xBE00, 0x13F0, - 0xE054, 0x72CA, 0x4826, 0x4827, 0x9ACA, 0xC607, 0x72C0, 0x48A6, 0x9AC0, - 0xC602, 0xBE00, 0x081C, 0xE054, 0xC60F, 0x74C4, 0x49CC, 0xF109, 0xC60C, - 0x74CA, 0x48C7, 0x9CCA, 0xC609, 0x74C0, 0x4846, 0x9CC0, 0xC602, 0xBE00, - 0x2494, 0xE092, 0xE0C0, 0xE054, 0x7420, 0x48C0, 0x9C20, 0x7444, 0xC602, - 0xBE00, 0x12DC, 0x733A, 0x21B5, 0x25BC, 0x1304, 0xF111, 0x1B12, 0x1D2A, - 0x3168, 0x3ADA, 0x31AB, 0x1A00, 0x9AC0, 0x1300, 0xF1FB, 0x7620, 0x236E, - 0x276F, 0x1A3C, 0x22A1, 0x41B5, 0x9EE2, 0x76E4, 0x486F, 0x9EE4, 0xC602, - 0xBE00, 0x4A26, 0x733A, 0x49BB, 0xC602, 0xBE00, 0x47A2, 0x48C1, 0x48C2, - 0x9C46, 0xC402, 0xBC00, 0x0A52, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, - 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, - 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, - 0x0000, 0xC602, 0xBE00, 0x0000 - }; - - rtl8125_hw_disable_mac_mcu_bps(dev); - - rtl8125_write_mac_mcu_ram_code(tp, mcu_patch_code_8125b_2, ARRAY_SIZE(mcu_patch_code_8125b_2)); - - rtl8125_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8125_mac_ocp_write(tp, 0xFC28, 0x13E6); - rtl8125_mac_ocp_write(tp, 0xFC2A, 0x0812); - rtl8125_mac_ocp_write(tp, 0xFC2C, 0x248C); - rtl8125_mac_ocp_write(tp, 0xFC2E, 0x12DA); - rtl8125_mac_ocp_write(tp, 0xFC30, 0x4A20); - rtl8125_mac_ocp_write(tp, 0xFC32, 0x47A0); - //rtl8125_mac_ocp_write(tp, 0xFC34, 0x0A46); - - rtl8125_mac_ocp_write(tp, 0xFC48, 0x003F); -} - -static void -rtl8125_hw_mac_mcu_config(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->NotWrMcuPatchCode == TRUE) return; - - switch (tp->mcfg) { - case CFG_METHOD_2: - rtl8125_set_mac_mcu_8125a_1(dev); - break; - case CFG_METHOD_3: - case CFG_METHOD_6: - rtl8125_set_mac_mcu_8125a_2(dev); - break; - case CFG_METHOD_4: - rtl8125_set_mac_mcu_8125b_1(dev); - break; - case CFG_METHOD_5: - case CFG_METHOD_7: - rtl8125_set_mac_mcu_8125b_2(dev); - break; - } -} -#endif - -#ifdef ENABLE_USE_FIRMWARE_FILE -static void rtl8125_release_firmware(struct rtl8125_private *tp) -{ - if (tp->rtl_fw) { - rtl8125_fw_release_firmware(tp->rtl_fw); - kfree(tp->rtl_fw); - tp->rtl_fw = NULL; - } -} - -void rtl8125_apply_firmware(struct rtl8125_private *tp) -{ - /* TODO: release firmware if rtl_fw_write_firmware signals failure. */ - if (tp->rtl_fw) { - rtl8125_fw_write_firmware(tp, tp->rtl_fw); - /* At least one firmware doesn't reset tp->ocp_base. */ - tp->ocp_base = OCP_STD_PHY_BASE; - - /* PHY soft reset may still be in progress */ - //phy_read_poll_timeout(tp->phydev, MII_BMCR, val, - // !(val & BMCR_RESET), - // 50000, 600000, true); - rtl8125_wait_phy_reset_complete(tp); - - tp->hw_ram_code_ver = rtl8125_get_hw_phy_mcu_code_ver(tp); - tp->sw_ram_code_ver = tp->hw_ram_code_ver; - tp->HwHasWrRamCodeToMicroP = TRUE; - } -} -#endif - -static void -rtl8125_hw_init(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_enable_cfg9346_write(tp); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - rtl8125_disable_cfg9346_write(tp); - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - break; - } - - //Disable UPS - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_mac_ocp_write(tp, 0xD40A, rtl8125_mac_ocp_read( tp, 0xD40A) & ~(BIT_4)); - break; - } - -#ifndef ENABLE_USE_FIRMWARE_FILE - if (!tp->rtl_fw) - rtl8125_hw_mac_mcu_config(dev); -#endif - - /*disable ocp phy power saving*/ - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_6 || - tp->mcfg == CFG_METHOD_7) - rtl8125_disable_ocp_phy_power_saving(dev); - - //Set PCIE uncorrectable error status mask pcie 0x108 - csi_tmp = rtl8125_csi_read(tp, 0x108); - csi_tmp |= BIT_20; - rtl8125_csi_write(tp, 0x108, csi_tmp); - - rtl8125_enable_cfg9346_write(tp); - rtl8125_disable_linkchg_wakeup(dev); - rtl8125_disable_cfg9346_write(tp); - rtl8125_disable_magic_packet(dev); - rtl8125_disable_d0_speedup(tp); - rtl8125_set_pci_pme(tp, 0); - if (s0_magic_packet == 1) - rtl8125_enable_magic_packet(dev); - -#ifdef ENABLE_USE_FIRMWARE_FILE - if (tp->rtl_fw && - !tp->resume_not_chg_speed && - !(HW_DASH_SUPPORT_TYPE_3(tp) && - tp->HwPkgDet == 0x06)) - rtl8125_apply_firmware(tp); -#endif -} - -static void -rtl8125_hw_ephy_config(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - rtl8125_ephy_write(tp, 0x01, 0xA812); - rtl8125_ephy_write(tp, 0x09, 0x520C); - rtl8125_ephy_write(tp, 0x04, 0xD000); - rtl8125_ephy_write(tp, 0x0D, 0xF702); - rtl8125_ephy_write(tp, 0x0A, 0x8653); - rtl8125_ephy_write(tp, 0x06, 0x001E); - rtl8125_ephy_write(tp, 0x08, 0x3595); - rtl8125_ephy_write(tp, 0x20, 0x9455); - rtl8125_ephy_write(tp, 0x21, 0x99FF); - rtl8125_ephy_write(tp, 0x02, 0x6046); - rtl8125_ephy_write(tp, 0x29, 0xFE00); - rtl8125_ephy_write(tp, 0x23, 0xAB62); - - rtl8125_ephy_write(tp, 0x41, 0xA80C); - rtl8125_ephy_write(tp, 0x49, 0x520C); - rtl8125_ephy_write(tp, 0x44, 0xD000); - rtl8125_ephy_write(tp, 0x4D, 0xF702); - rtl8125_ephy_write(tp, 0x4A, 0x8653); - rtl8125_ephy_write(tp, 0x46, 0x001E); - rtl8125_ephy_write(tp, 0x48, 0x3595); - rtl8125_ephy_write(tp, 0x60, 0x9455); - rtl8125_ephy_write(tp, 0x61, 0x99FF); - rtl8125_ephy_write(tp, 0x42, 0x6046); - rtl8125_ephy_write(tp, 0x69, 0xFE00); - rtl8125_ephy_write(tp, 0x63, 0xAB62); - break; - case CFG_METHOD_3: - case CFG_METHOD_6: - rtl8125_ephy_write(tp, 0x04, 0xD000); - rtl8125_ephy_write(tp, 0x0A, 0x8653); - rtl8125_ephy_write(tp, 0x23, 0xAB66); - rtl8125_ephy_write(tp, 0x20, 0x9455); - rtl8125_ephy_write(tp, 0x21, 0x99FF); - rtl8125_ephy_write(tp, 0x29, 0xFE04); - - rtl8125_ephy_write(tp, 0x44, 0xD000); - rtl8125_ephy_write(tp, 0x4A, 0x8653); - rtl8125_ephy_write(tp, 0x63, 0xAB66); - rtl8125_ephy_write(tp, 0x60, 0x9455); - rtl8125_ephy_write(tp, 0x61, 0x99FF); - rtl8125_ephy_write(tp, 0x69, 0xFE04); - - ClearAndSetPCIePhyBit(tp, - 0x2A, - (BIT_14 | BIT_13 | BIT_12), - (BIT_13 | BIT_12) - ); - ClearPCIePhyBit(tp, 0x19, BIT_6); - SetPCIePhyBit(tp, 0x1B, (BIT_11 | BIT_10 | BIT_9)); - ClearPCIePhyBit(tp, 0x1B, (BIT_14 | BIT_13 | BIT_12)); - rtl8125_ephy_write(tp, 0x02, 0x6042); - rtl8125_ephy_write(tp, 0x06, 0x0014); - - ClearAndSetPCIePhyBit(tp, - 0x6A, - (BIT_14 | BIT_13 | BIT_12), - (BIT_13 | BIT_12) - ); - ClearPCIePhyBit(tp, 0x59, BIT_6); - SetPCIePhyBit(tp, 0x5B, (BIT_11 | BIT_10 | BIT_9)); - ClearPCIePhyBit(tp, 0x5B, (BIT_14 | BIT_13 | BIT_12)); - rtl8125_ephy_write(tp, 0x42, 0x6042); - rtl8125_ephy_write(tp, 0x46, 0x0014); - break; - case CFG_METHOD_4: - rtl8125_ephy_write(tp, 0x06, 0x001F); - rtl8125_ephy_write(tp, 0x0A, 0xB66B); - rtl8125_ephy_write(tp, 0x01, 0xA852); - rtl8125_ephy_write(tp, 0x24, 0x0008); - rtl8125_ephy_write(tp, 0x2F, 0x6052); - rtl8125_ephy_write(tp, 0x0D, 0xF716); - rtl8125_ephy_write(tp, 0x20, 0xD477); - rtl8125_ephy_write(tp, 0x21, 0x4477); - rtl8125_ephy_write(tp, 0x22, 0x0013); - rtl8125_ephy_write(tp, 0x23, 0xBB66); - rtl8125_ephy_write(tp, 0x0B, 0xA909); - rtl8125_ephy_write(tp, 0x29, 0xFF04); - rtl8125_ephy_write(tp, 0x1B, 0x1EA0); - - rtl8125_ephy_write(tp, 0x46, 0x001F); - rtl8125_ephy_write(tp, 0x4A, 0xB66B); - rtl8125_ephy_write(tp, 0x41, 0xA84A); - rtl8125_ephy_write(tp, 0x64, 0x000C); - rtl8125_ephy_write(tp, 0x6F, 0x604A); - rtl8125_ephy_write(tp, 0x4D, 0xF716); - rtl8125_ephy_write(tp, 0x60, 0xD477); - rtl8125_ephy_write(tp, 0x61, 0x4477); - rtl8125_ephy_write(tp, 0x62, 0x0013); - rtl8125_ephy_write(tp, 0x63, 0xBB66); - rtl8125_ephy_write(tp, 0x4B, 0xA909); - rtl8125_ephy_write(tp, 0x69, 0xFF04); - rtl8125_ephy_write(tp, 0x5B, 0x1EA0); - break; - case CFG_METHOD_5: - case CFG_METHOD_7: - rtl8125_ephy_write(tp, 0x0B, 0xA908); - rtl8125_ephy_write(tp, 0x1E, 0x20EB); - rtl8125_ephy_write(tp, 0x22, 0x0023); - rtl8125_ephy_write(tp, 0x02, 0x60C2); - rtl8125_ephy_write(tp, 0x29, 0xFF00); - - rtl8125_ephy_write(tp, 0x4B, 0xA908); - rtl8125_ephy_write(tp, 0x5E, 0x28EB); - rtl8125_ephy_write(tp, 0x62, 0x0023); - rtl8125_ephy_write(tp, 0x42, 0x60C2); - rtl8125_ephy_write(tp, 0x69, 0xFF00); - break; - } -} - -static u16 -rtl8125_get_hw_phy_mcu_code_ver(struct rtl8125_private *tp) -{ - u16 hw_ram_code_ver = ~0; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x801E); - hw_ram_code_ver = mdio_direct_read_phy_ocp(tp, 0xA438); - break; - } - - return hw_ram_code_ver; -} - -static int -rtl8125_check_hw_phy_mcu_code_ver(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ram_code_ver_match = 0; - - tp->hw_ram_code_ver = rtl8125_get_hw_phy_mcu_code_ver(tp); - - if (tp->hw_ram_code_ver == tp->sw_ram_code_ver) { - ram_code_ver_match = 1; - tp->HwHasWrRamCodeToMicroP = TRUE; - } - - return ram_code_ver_match; -} - -bool -rtl8125_set_phy_mcu_patch_request(struct rtl8125_private *tp) -{ - u16 gphy_val; - u16 WaitCount; - bool bSuccess = TRUE; - - SetEthPhyOcpBit(tp, 0xB820, BIT_4); - - WaitCount = 0; - do { - gphy_val = mdio_direct_read_phy_ocp(tp, 0xB800); - udelay(100); - WaitCount++; - } while (!(gphy_val & BIT_6) && (WaitCount < 1000)); - - if (!(gphy_val & BIT_6) && (WaitCount == 1000)) bSuccess = FALSE; - - if (!bSuccess) - dprintk("rtl8125_set_phy_mcu_patch_request fail.\n"); - - return bSuccess; -} - -bool -rtl8125_clear_phy_mcu_patch_request(struct rtl8125_private *tp) -{ - u16 gphy_val; - u16 WaitCount; - bool bSuccess = TRUE; - - ClearEthPhyOcpBit(tp, 0xB820, BIT_4); - - WaitCount = 0; - do { - gphy_val = mdio_direct_read_phy_ocp(tp, 0xB800); - udelay(100); - WaitCount++; - } while ((gphy_val & BIT_6) && (WaitCount < 1000)); - - if ((gphy_val & BIT_6) && (WaitCount == 1000)) bSuccess = FALSE; - - if (!bSuccess) - dprintk("rtl8125_clear_phy_mcu_patch_request fail.\n"); - - return bSuccess; -} - -#ifndef ENABLE_USE_FIRMWARE_FILE -static void -rtl8125_write_hw_phy_mcu_code_ver(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x801E); - mdio_direct_write_phy_ocp(tp, 0xA438, tp->sw_ram_code_ver); - tp->hw_ram_code_ver = tp->sw_ram_code_ver; - break; - } -} - -static void -rtl8125_acquire_phy_mcu_patch_key_lock(struct rtl8125_private *tp) -{ - u16 PatchKey; - - switch (tp->mcfg) { - case CFG_METHOD_2: - PatchKey = 0x8600; - break; - case CFG_METHOD_3: - case CFG_METHOD_6: - PatchKey = 0x8601; - break; - case CFG_METHOD_4: - PatchKey = 0x3700; - break; - case CFG_METHOD_5: - case CFG_METHOD_7: - PatchKey = 0x3701; - break; - default: - return; - } - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8024); - mdio_direct_write_phy_ocp(tp, 0xA438, PatchKey); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xB82E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0001); -} - -static void -rtl8125_release_phy_mcu_patch_key_lock(struct rtl8125_private *tp) -{ - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - mdio_direct_write_phy_ocp(tp, 0xA436, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - ClearEthPhyOcpBit(tp, 0xB82E, BIT_0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - break; - default: - break; - } -} - -static void -rtl8125_set_phy_mcu_ram_code(struct net_device *dev, const u16 *ramcode, u16 codesize) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 i; - u16 addr; - u16 val; - - if (ramcode == NULL || codesize % 2) { - goto out; - } - - for (i = 0; i < codesize; i += 2) { - addr = ramcode[i]; - val = ramcode[i + 1]; - if (addr == 0xFFFF && val == 0xFFFF) { - break; - } - mdio_direct_write_phy_ocp(tp, addr, val); - } - -out: - return; -} - -static void -rtl8125_enable_phy_disable_mode(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 3: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_5); - break; - } - - dprintk("enable phy disable mode.\n"); -} - -static void -rtl8125_disable_phy_disable_mode(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 3: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_5); - break; - } - - mdelay(1); - - dprintk("disable phy disable mode.\n"); -} - -static void -rtl8125_set_hw_phy_before_init_phy_mcu(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u16 PhyRegValue; - - switch (tp->mcfg) { - case CFG_METHOD_4: - mdio_direct_write_phy_ocp(tp, 0xBF86, 0x9000); - - SetEthPhyOcpBit(tp, 0xC402, BIT_10); - ClearEthPhyOcpBit(tp, 0xC402, BIT_10); - - PhyRegValue = mdio_direct_read_phy_ocp(tp, 0xBF86); - PhyRegValue &= (BIT_1 | BIT_0); - if (PhyRegValue != 0) - dprintk("PHY watch dog not clear, value = 0x%x \n", PhyRegValue); - - mdio_direct_write_phy_ocp(tp, 0xBD86, 0x1010); - mdio_direct_write_phy_ocp(tp, 0xBD88, 0x1010); - - ClearAndSetEthPhyOcpBit(tp, - 0xBD4E, - BIT_11 | BIT_10, - BIT_11); - ClearAndSetEthPhyOcpBit(tp, - 0xBF46, - BIT_11 | BIT_10 | BIT_9 | BIT_8, - BIT_10 | BIT_9 | BIT_8); - break; - } -} - -static void -rtl8125_real_set_phy_mcu_8125a_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_acquire_phy_mcu_patch_key_lock(tp); - - - SetEthPhyOcpBit(tp, 0xB820, BIT_7); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8013); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8021); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x802f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x803d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8042); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa088); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a50); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1a3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x401a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd707); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f8b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a6c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8080); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd019); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1a2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x401a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd707); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f8b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a84); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8970); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c07); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0901); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcf09); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd705); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xceff); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf0a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1213); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8401); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8580); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1253); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd064); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd181); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4018); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd706); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2c59); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x804d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc60f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc605); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x10fd); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA026); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA022); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x10f4); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA020); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1252); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA006); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1206); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA004); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a78); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a60); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a4f); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3f00); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0010); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8066); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x807c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8089); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x808e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80b2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80c2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62db); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x655c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0505); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x653c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0502); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0506); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x050a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0505); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0506); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x050c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x050a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x050c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0508); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0304); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd73e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x614a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0502); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0508); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0321); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0346); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8208); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x609d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x001a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x001a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x607d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ab); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x017b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x017b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60fd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa50f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaa0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0231); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0503); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a05); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0231); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0221); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08A); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ce); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA088); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0169); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA086); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00a6); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA084); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x000d); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA082); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0308); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA080); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x029f); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA090); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x007f); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0020); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8017); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8029); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8054); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x805a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8064); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9430); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9480); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb408); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd120); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd057); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb80); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9906); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0567); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb94); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8406); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8dff); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0773); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb91); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd139); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07dc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa110); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa2a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4045); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa180); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07ec); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07dc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fa7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0481); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x94bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x870c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa00a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa280); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8220); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x078e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb92); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd150); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6121); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x61a2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6223); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d10); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d20); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d30); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf005); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d40); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4046); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07f7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0742); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3ad4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0537); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8301); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa70c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9402); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x890c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x064b); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0642); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0686); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10A); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0788); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA108); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x047b); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA106); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x065c); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA104); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0769); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA102); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0565); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x06f9); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA110); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ff); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8530); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3caf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8593); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9caf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x85a5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5afb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe083); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfb0c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x020d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x021b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x10bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86d7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbe0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x83fc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1b10); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xda02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xdd02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5afb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe083); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfd0c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x020d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x021b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x10bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86dd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbe0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x83fe); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1b10); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf2f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2cac); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0286); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x65af); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x212b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x022c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86b6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf21); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cd1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8710); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x870d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8716); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x871f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x871c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8728); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8725); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8707); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbad); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x281c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1302); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2202); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2b02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae1a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd101); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1302); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2202); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2b02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd101); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3402); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3102); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3d02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3a02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4302); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4c02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4902); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2e02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4602); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf87); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4f02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ab7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf35); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7ff8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfaef); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x69bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86fb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86fe); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86e9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86ec); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfbbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x025a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7bf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86ef); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cbf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x86f8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0262); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7cef); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x96fe); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfc04); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf8fa); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xef69); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xef02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf202); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf502); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbf86); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf802); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6273); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xef96); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfefc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0420); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb540); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x53b5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4086); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb540); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb9b5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40c8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb03a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbac8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb13a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xba77); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd26); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffbd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2677); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd28); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffbd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd26); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8bd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2640); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbd28); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc8bd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x28bb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa430); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x98b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1eba); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb01e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xdcb0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e98); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbab0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9edc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x98b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1eba); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb11e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xdcb1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e98); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbab1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9edc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x11b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e22); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb01e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x33b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e11); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x22b0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9e33); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb09e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x11b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e22); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb11e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x33b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1e11); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x22b1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9e33); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb19e); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb85e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2f71); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb860); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x20d9); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb862); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2109); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb864); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x34e7); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb878); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x000f); - - - ClearEthPhyOcpBit(tp, 0xB820, BIT_7); - - - rtl8125_release_phy_mcu_patch_key_lock(tp); -} - -static void -rtl8125_set_phy_mcu_8125a_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_set_phy_mcu_patch_request(tp); - - rtl8125_real_set_phy_mcu_8125a_1(dev); - - rtl8125_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8125_real_set_phy_mcu_8125a_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_acquire_phy_mcu_patch_key_lock(tp); - - - SetEthPhyOcpBit(tp, 0xB820, BIT_7); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x808b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x808f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8093); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8097); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x809d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80a1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80aa); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x607b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x42da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x615b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14a4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x14bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f2e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf034); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac11); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa410); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4779); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf034); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac22); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa420); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4559); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf023); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac44); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa440); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4339); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd719); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4118); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac88); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa480); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xce00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4119); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xac0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1444); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf001); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1456); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd718); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fac); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc48f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x141b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd504); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x121a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd0b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1bb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0898); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd0b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1bb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a0e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd064); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd18a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0b7e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x401c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd501); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa804); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8804); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x053b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd500); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa301); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0648); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc520); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa201); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x252d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1646); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd708); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4006); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1646); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0308); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA026); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0307); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1645); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA022); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0647); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA020); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x053a); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA006); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0b7c); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA004); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0a0c); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0896); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x11a1); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xff00); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0010); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8015); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x801a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xad02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x02d7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00ed); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0509); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xc100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x008f); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA08A); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA088); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA086); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA084); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA082); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x008d); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA080); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00eb); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA090); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0103); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA016); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0020); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA012); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8014); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8018); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8024); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8051); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8055); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8072); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x80dc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfffd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfffd); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8301); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa70c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x9402); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x890c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8840); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa380); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb91); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd139); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd140); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa110); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa2a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4085); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa180); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8280); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07f0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5f74); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x82a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0c0f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd158); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd04d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03d4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x94bc); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x870c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8380); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd10d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fb4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa190); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa00a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa280); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa404); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa220); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd130); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07c4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5fb4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xbb80); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1c4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd074); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa301); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x604b); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa90c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0556); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xcb92); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4063); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd116); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd119); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd040); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x60a0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6241); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x63e2); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6583); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf054); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d10); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d50); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf02a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d20); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf021); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d60); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf01c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d30); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf013); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d70); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf00e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x611e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x40da); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d40); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf005); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d80); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x405d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa720); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd700); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x5ff4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa008); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd704); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x4046); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07fb); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd703); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f6f); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f4e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f2d); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7f0c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x800a); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0cf0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0d00); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07e8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8010); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa740); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0743); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7fb5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd701); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3ad4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0556); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8610); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x066e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd1f5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xd049); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x1800); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ec); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10E); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x01ea); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x06a9); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA10A); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x078a); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA108); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03d2); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA106); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x067f); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA104); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0665); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA102); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA100); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xA110); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00fc); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8530); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb87e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x3caf); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8545); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf85); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x45af); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8545); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xee82); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf900); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0103); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xaf03); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb7f8); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0a6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00e1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa601); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xef01); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x58f0); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa080); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x37a1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8402); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae16); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa185); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x02ae); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x11a1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8702); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae0c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xa188); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x02ae); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x07a1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8902); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae02); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xae1c); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6901); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe4b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe0b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6901); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xe4b4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x62e5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xb463); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xfc04); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb85e); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03b3); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb860); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb862); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb864); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xffff); - mdio_direct_write_phy_ocp(tp, 0xA436, 0xb878); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0001); - - - ClearEthPhyOcpBit(tp, 0xB820, BIT_7); - - - rtl8125_release_phy_mcu_patch_key_lock(tp); -} - -static void -rtl8125_set_phy_mcu_8125a_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_set_phy_mcu_patch_request(tp); - - rtl8125_real_set_phy_mcu_8125a_2(dev); - - rtl8125_clear_phy_mcu_patch_request(tp); -} - -static const u16 phy_mcu_ram_code_8125b_1[] = { - 0xa436, 0x8024, 0xa438, 0x3700, 0xa436, 0xB82E, 0xa438, 0x0001, - 0xb820, 0x0090, 0xa436, 0xA016, 0xa438, 0x0000, 0xa436, 0xA012, - 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, - 0xa438, 0x1800, 0xa438, 0x8025, 0xa438, 0x1800, 0xa438, 0x803a, - 0xa438, 0x1800, 0xa438, 0x8044, 0xa438, 0x1800, 0xa438, 0x8083, - 0xa438, 0x1800, 0xa438, 0x808d, 0xa438, 0x1800, 0xa438, 0x808d, - 0xa438, 0x1800, 0xa438, 0x808d, 0xa438, 0xd712, 0xa438, 0x4077, - 0xa438, 0xd71e, 0xa438, 0x4159, 0xa438, 0xd71e, 0xa438, 0x6099, - 0xa438, 0x7f44, 0xa438, 0x1800, 0xa438, 0x1a14, 0xa438, 0x9040, - 0xa438, 0x9201, 0xa438, 0x1800, 0xa438, 0x1b1a, 0xa438, 0xd71e, - 0xa438, 0x2425, 0xa438, 0x1a14, 0xa438, 0xd71f, 0xa438, 0x3ce5, - 0xa438, 0x1afb, 0xa438, 0x1800, 0xa438, 0x1b00, 0xa438, 0xd712, - 0xa438, 0x4077, 0xa438, 0xd71e, 0xa438, 0x4159, 0xa438, 0xd71e, - 0xa438, 0x60b9, 0xa438, 0x2421, 0xa438, 0x1c17, 0xa438, 0x1800, - 0xa438, 0x1a14, 0xa438, 0x9040, 0xa438, 0x1800, 0xa438, 0x1c2c, - 0xa438, 0xd71e, 0xa438, 0x2425, 0xa438, 0x1a14, 0xa438, 0xd71f, - 0xa438, 0x3ce5, 0xa438, 0x1c0f, 0xa438, 0x1800, 0xa438, 0x1c13, - 0xa438, 0xd702, 0xa438, 0xd501, 0xa438, 0x6072, 0xa438, 0x8401, - 0xa438, 0xf002, 0xa438, 0xa401, 0xa438, 0x1000, 0xa438, 0x146e, - 0xa438, 0x1800, 0xa438, 0x0b77, 0xa438, 0xd703, 0xa438, 0x665d, - 0xa438, 0x653e, 0xa438, 0x641f, 0xa438, 0xd700, 0xa438, 0x62c4, - 0xa438, 0x6185, 0xa438, 0x6066, 0xa438, 0x1800, 0xa438, 0x165a, - 0xa438, 0xc101, 0xa438, 0xcb00, 0xa438, 0x1000, 0xa438, 0x1945, - 0xa438, 0xd700, 0xa438, 0x7fa6, 0xa438, 0x1800, 0xa438, 0x807d, - 0xa438, 0xc102, 0xa438, 0xcb00, 0xa438, 0x1000, 0xa438, 0x1945, - 0xa438, 0xd700, 0xa438, 0x2569, 0xa438, 0x8058, 0xa438, 0x1800, - 0xa438, 0x807d, 0xa438, 0xc104, 0xa438, 0xcb00, 0xa438, 0x1000, - 0xa438, 0x1945, 0xa438, 0xd700, 0xa438, 0x7fa4, 0xa438, 0x1800, - 0xa438, 0x807d, 0xa438, 0xc120, 0xa438, 0xcb00, 0xa438, 0x1000, - 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbf, 0xa438, 0x1800, - 0xa438, 0x807d, 0xa438, 0xc140, 0xa438, 0xcb00, 0xa438, 0x1000, - 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbe, 0xa438, 0x1800, - 0xa438, 0x807d, 0xa438, 0xc180, 0xa438, 0xcb00, 0xa438, 0x1000, - 0xa438, 0x1945, 0xa438, 0xd703, 0xa438, 0x7fbd, 0xa438, 0xc100, - 0xa438, 0xcb00, 0xa438, 0xd708, 0xa438, 0x6018, 0xa438, 0x1800, - 0xa438, 0x165a, 0xa438, 0x1000, 0xa438, 0x14f6, 0xa438, 0xd014, - 0xa438, 0xd1e3, 0xa438, 0x1000, 0xa438, 0x1356, 0xa438, 0xd705, - 0xa438, 0x5fbe, 0xa438, 0x1800, 0xa438, 0x1559, 0xa436, 0xA026, - 0xa438, 0xffff, 0xa436, 0xA024, 0xa438, 0xffff, 0xa436, 0xA022, - 0xa438, 0xffff, 0xa436, 0xA020, 0xa438, 0x1557, 0xa436, 0xA006, - 0xa438, 0x1677, 0xa436, 0xA004, 0xa438, 0x0b75, 0xa436, 0xA002, - 0xa438, 0x1c17, 0xa436, 0xA000, 0xa438, 0x1b04, 0xa436, 0xA008, - 0xa438, 0x1f00, 0xa436, 0xA016, 0xa438, 0x0020, 0xa436, 0xA012, - 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, - 0xa438, 0x1800, 0xa438, 0x817f, 0xa438, 0x1800, 0xa438, 0x82ab, - 0xa438, 0x1800, 0xa438, 0x83f8, 0xa438, 0x1800, 0xa438, 0x8444, - 0xa438, 0x1800, 0xa438, 0x8454, 0xa438, 0x1800, 0xa438, 0x8459, - 0xa438, 0x1800, 0xa438, 0x8465, 0xa438, 0xcb11, 0xa438, 0xa50c, - 0xa438, 0x8310, 0xa438, 0xd701, 0xa438, 0x4076, 0xa438, 0x0c03, - 0xa438, 0x0903, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d00, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0x1000, 0xa438, 0x0a4d, - 0xa438, 0xcb12, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5f84, 0xa438, 0xd102, 0xa438, 0xd040, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd701, - 0xa438, 0x60f3, 0xa438, 0xd413, 0xa438, 0x1000, 0xa438, 0x0a37, - 0xa438, 0xd410, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb13, - 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8108, - 0xa438, 0xa00a, 0xa438, 0xa910, 0xa438, 0xa780, 0xa438, 0xd14a, - 0xa438, 0xd048, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, - 0xa438, 0x6255, 0xa438, 0xd700, 0xa438, 0x5f74, 0xa438, 0x6326, - 0xa438, 0xd702, 0xa438, 0x5f07, 0xa438, 0x800a, 0xa438, 0xa004, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, - 0xa438, 0x0902, 0xa438, 0xffe2, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x5fab, 0xa438, 0xba08, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8b, 0xa438, 0x9a08, - 0xa438, 0x800a, 0xa438, 0xd702, 0xa438, 0x6535, 0xa438, 0xd40d, - 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb14, 0xa438, 0xa004, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0xa00a, - 0xa438, 0xa780, 0xa438, 0xd14a, 0xa438, 0xd048, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x6206, - 0xa438, 0xd702, 0xa438, 0x5f47, 0xa438, 0x800a, 0xa438, 0xa004, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, - 0xa438, 0x0902, 0xa438, 0x1800, 0xa438, 0x8064, 0xa438, 0x800a, - 0xa438, 0xd40e, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0xd701, 0xa438, 0x6073, 0xa438, 0xd701, - 0xa438, 0x4216, 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0a42, - 0xa438, 0x8004, 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0a42, - 0xa438, 0x8001, 0xa438, 0xd120, 0xa438, 0xd040, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0x8504, - 0xa438, 0xcb21, 0xa438, 0xa301, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5f9f, 0xa438, 0x8301, 0xa438, 0xd704, - 0xa438, 0x40e0, 0xa438, 0xd196, 0xa438, 0xd04d, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb22, - 0xa438, 0x1000, 0xa438, 0x0a6d, 0xa438, 0x0c03, 0xa438, 0x1502, - 0xa438, 0xa640, 0xa438, 0x9503, 0xa438, 0x8910, 0xa438, 0x8720, - 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d01, - 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0x1000, - 0xa438, 0x0a7d, 0xa438, 0x0c1f, 0xa438, 0x0f14, 0xa438, 0xcb23, - 0xa438, 0x8fc0, 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xaf40, - 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0x0cc0, 0xa438, 0x0f80, - 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xafc0, 0xa438, 0x1000, - 0xa438, 0x0a25, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, - 0xa438, 0x5dee, 0xa438, 0xcb24, 0xa438, 0x8f1f, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x7f6e, 0xa438, 0xa111, - 0xa438, 0xa215, 0xa438, 0xa401, 0xa438, 0x8404, 0xa438, 0xa720, - 0xa438, 0xcb25, 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, - 0xa438, 0x9503, 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, - 0xa438, 0x0b86, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0xcb26, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x5f82, 0xa438, 0x8111, 0xa438, 0x8205, - 0xa438, 0x8404, 0xa438, 0xcb27, 0xa438, 0xd404, 0xa438, 0x1000, - 0xa438, 0x0a37, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa710, 0xa438, 0xa104, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8104, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0xa120, - 0xa438, 0xaa0f, 0xa438, 0x8110, 0xa438, 0xa284, 0xa438, 0xa404, - 0xa438, 0xa00a, 0xa438, 0xd193, 0xa438, 0xd046, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb28, - 0xa438, 0xa110, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fa8, 0xa438, 0x8110, 0xa438, 0x8284, 0xa438, 0xa404, - 0xa438, 0x800a, 0xa438, 0x8710, 0xa438, 0xb804, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f82, 0xa438, 0x9804, - 0xa438, 0xcb29, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5f85, 0xa438, 0xa710, 0xa438, 0xb820, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f65, 0xa438, 0x9820, - 0xa438, 0xcb2a, 0xa438, 0xa190, 0xa438, 0xa284, 0xa438, 0xa404, - 0xa438, 0xa00a, 0xa438, 0xd13d, 0xa438, 0xd04a, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8149, - 0xa438, 0xa220, 0xa438, 0xd1a0, 0xa438, 0xd040, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8151, - 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xcb2f, 0xa438, 0xa302, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd708, 0xa438, 0x5f63, - 0xa438, 0xd411, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8302, - 0xa438, 0xd409, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5fa3, 0xa438, 0x8190, 0xa438, 0x82a4, 0xa438, 0x8404, - 0xa438, 0x800a, 0xa438, 0xb808, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7fa3, 0xa438, 0x9808, 0xa438, 0x1800, - 0xa438, 0x0433, 0xa438, 0xcb15, 0xa438, 0xa508, 0xa438, 0xd700, - 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0xf003, - 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0x1000, 0xa438, 0x0a7d, - 0xa438, 0x1000, 0xa438, 0x0a4d, 0xa438, 0xa301, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5f9f, 0xa438, 0x8301, - 0xa438, 0xd704, 0xa438, 0x40e0, 0xa438, 0xd115, 0xa438, 0xd04f, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, - 0xa438, 0xd413, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xcb16, - 0xa438, 0x1000, 0xa438, 0x0a6d, 0xa438, 0x0c03, 0xa438, 0x1502, - 0xa438, 0xa640, 0xa438, 0x9503, 0xa438, 0x8720, 0xa438, 0xd17a, - 0xa438, 0xd04c, 0xa438, 0x0c1f, 0xa438, 0x0f14, 0xa438, 0xcb17, - 0xa438, 0x8fc0, 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xaf40, - 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0x0cc0, 0xa438, 0x0f80, - 0xa438, 0x1000, 0xa438, 0x0a25, 0xa438, 0xafc0, 0xa438, 0x1000, - 0xa438, 0x0a25, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd701, - 0xa438, 0x61ce, 0xa438, 0xd700, 0xa438, 0x5db4, 0xa438, 0xcb18, - 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, 0xa438, 0x9503, - 0xa438, 0xa720, 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xffd6, 0xa438, 0x8f1f, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x7f8e, 0xa438, 0xa131, - 0xa438, 0xaa0f, 0xa438, 0xa2d5, 0xa438, 0xa407, 0xa438, 0xa720, - 0xa438, 0x8310, 0xa438, 0xa308, 0xa438, 0x8308, 0xa438, 0xcb19, - 0xa438, 0x0c03, 0xa438, 0x1502, 0xa438, 0x8640, 0xa438, 0x9503, - 0xa438, 0x1000, 0xa438, 0x0b43, 0xa438, 0x1000, 0xa438, 0x0b86, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xb920, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, - 0xa438, 0xcb1a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5f82, 0xa438, 0x8111, 0xa438, 0x82c5, 0xa438, 0xa404, - 0xa438, 0x8402, 0xa438, 0xb804, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7f82, 0xa438, 0x9804, 0xa438, 0xcb1b, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f85, - 0xa438, 0xa710, 0xa438, 0xb820, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7f65, 0xa438, 0x9820, 0xa438, 0xcb1c, - 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, 0xa438, 0x1000, - 0xa438, 0x0a7d, 0xa438, 0xa110, 0xa438, 0xa284, 0xa438, 0xa404, - 0xa438, 0x8402, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fa8, 0xa438, 0xcb1d, 0xa438, 0xa180, 0xa438, 0xa402, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa8, - 0xa438, 0xa220, 0xa438, 0xd1f5, 0xa438, 0xd049, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x8221, - 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xb920, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fa3, - 0xa438, 0xa504, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d00, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa00a, 0xa438, 0x8190, - 0xa438, 0x82a4, 0xa438, 0x8402, 0xa438, 0xa404, 0xa438, 0xb808, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7fa3, - 0xa438, 0x9808, 0xa438, 0xcb2b, 0xa438, 0xcb2c, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f84, 0xa438, 0xd14a, - 0xa438, 0xd048, 0xa438, 0xa780, 0xa438, 0xcb2d, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5f94, 0xa438, 0x6208, - 0xa438, 0xd702, 0xa438, 0x5f27, 0xa438, 0x800a, 0xa438, 0xa004, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, 0xa438, 0xa001, - 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, 0xa438, 0x0c03, - 0xa438, 0x0902, 0xa438, 0xa00a, 0xa438, 0xffe9, 0xa438, 0xcb2e, - 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, 0xa438, 0x1000, - 0xa438, 0x0a7d, 0xa438, 0xa190, 0xa438, 0xa284, 0xa438, 0xa406, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa8, - 0xa438, 0xa220, 0xa438, 0xd1a0, 0xa438, 0xd040, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x3444, 0xa438, 0x827d, - 0xa438, 0xd702, 0xa438, 0x5f51, 0xa438, 0xcb2f, 0xa438, 0xa302, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd708, 0xa438, 0x5f63, - 0xa438, 0xd411, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8302, - 0xa438, 0xd409, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5fa3, 0xa438, 0x8190, 0xa438, 0x82a4, 0xa438, 0x8406, - 0xa438, 0x800a, 0xa438, 0xb808, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7fa3, 0xa438, 0x9808, 0xa438, 0x1800, - 0xa438, 0x0433, 0xa438, 0xcb30, 0xa438, 0x8380, 0xa438, 0xcb31, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5f86, - 0xa438, 0x9308, 0xa438, 0xb204, 0xa438, 0xb301, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd701, 0xa438, 0x5fa2, 0xa438, 0xb302, - 0xa438, 0x9204, 0xa438, 0xcb32, 0xa438, 0xd408, 0xa438, 0x1000, - 0xa438, 0x0a37, 0xa438, 0xd141, 0xa438, 0xd043, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd704, - 0xa438, 0x4ccc, 0xa438, 0xd700, 0xa438, 0x4c81, 0xa438, 0xd702, - 0xa438, 0x609e, 0xa438, 0xd1e5, 0xa438, 0xd04d, 0xa438, 0xf003, - 0xa438, 0xd1e5, 0xa438, 0xd04d, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xd700, 0xa438, 0x6083, - 0xa438, 0x0c1f, 0xa438, 0x0d01, 0xa438, 0xf003, 0xa438, 0x0c1f, - 0xa438, 0x0d01, 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0x8710, - 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8108, - 0xa438, 0xa203, 0xa438, 0x8120, 0xa438, 0x8a0f, 0xa438, 0xa111, - 0xa438, 0x8204, 0xa438, 0xa140, 0xa438, 0x1000, 0xa438, 0x0a42, - 0xa438, 0x8140, 0xa438, 0xd17a, 0xa438, 0xd04b, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xa204, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa7, - 0xa438, 0xb920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x5fac, 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x7f8c, 0xa438, 0xd404, 0xa438, 0x1000, - 0xa438, 0x0a37, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xa710, 0xa438, 0x8101, - 0xa438, 0x8201, 0xa438, 0xa104, 0xa438, 0x1000, 0xa438, 0x0a42, - 0xa438, 0x8104, 0xa438, 0xa120, 0xa438, 0xaa0f, 0xa438, 0x8110, - 0xa438, 0xa284, 0xa438, 0xa404, 0xa438, 0xa00a, 0xa438, 0xd193, - 0xa438, 0xd047, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0xa110, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fa8, 0xa438, 0xa180, 0xa438, 0xd13d, - 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0xf024, 0xa438, 0xa710, 0xa438, 0xa00a, - 0xa438, 0x8190, 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa404, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fa7, - 0xa438, 0x8710, 0xa438, 0xb920, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x5fac, 0xa438, 0x9920, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f8c, 0xa438, 0x800a, - 0xa438, 0x8190, 0xa438, 0x8284, 0xa438, 0x8406, 0xa438, 0xd700, - 0xa438, 0x4121, 0xa438, 0xd701, 0xa438, 0x60f3, 0xa438, 0xd1e5, - 0xa438, 0xd04d, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0x8710, 0xa438, 0xa00a, 0xa438, 0x8190, - 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa404, 0xa438, 0xb920, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x5fac, - 0xa438, 0x9920, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, - 0xa438, 0x7f8c, 0xa438, 0xcb33, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd71f, 0xa438, 0x5f85, 0xa438, 0xa710, 0xa438, 0xb820, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd71f, 0xa438, 0x7f65, - 0xa438, 0x9820, 0xa438, 0xcb34, 0xa438, 0xa00a, 0xa438, 0xa190, - 0xa438, 0xa284, 0xa438, 0xa404, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fa9, 0xa438, 0xd701, 0xa438, 0x6853, - 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, 0xa438, 0x0d00, - 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d00, 0xa438, 0x1000, - 0xa438, 0x0a7d, 0xa438, 0x8190, 0xa438, 0x8284, 0xa438, 0xcb35, - 0xa438, 0xd407, 0xa438, 0x1000, 0xa438, 0x0a37, 0xa438, 0x8110, - 0xa438, 0x8204, 0xa438, 0xa280, 0xa438, 0xa00a, 0xa438, 0xd704, - 0xa438, 0x4215, 0xa438, 0xa304, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fb8, 0xa438, 0xd1c3, 0xa438, 0xd043, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, - 0xa438, 0x8304, 0xa438, 0xd700, 0xa438, 0x4109, 0xa438, 0xf01e, - 0xa438, 0xcb36, 0xa438, 0xd412, 0xa438, 0x1000, 0xa438, 0x0a37, - 0xa438, 0xd700, 0xa438, 0x6309, 0xa438, 0xd702, 0xa438, 0x42c7, - 0xa438, 0x800a, 0xa438, 0x8180, 0xa438, 0x8280, 0xa438, 0x8404, - 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8004, - 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0a42, 0xa438, 0x8001, - 0xa438, 0x0c03, 0xa438, 0x0902, 0xa438, 0xa00a, 0xa438, 0xd14a, - 0xa438, 0xd048, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0xd700, 0xa438, 0x6083, 0xa438, 0x0c1f, - 0xa438, 0x0d02, 0xa438, 0xf003, 0xa438, 0x0c1f, 0xa438, 0x0d02, - 0xa438, 0x1000, 0xa438, 0x0a7d, 0xa438, 0xcc55, 0xa438, 0xcb37, - 0xa438, 0xa00a, 0xa438, 0xa190, 0xa438, 0xa2a4, 0xa438, 0xa404, - 0xa438, 0xd700, 0xa438, 0x6041, 0xa438, 0xa402, 0xa438, 0xd13d, - 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, - 0xa438, 0x5fa9, 0xa438, 0xd702, 0xa438, 0x5f71, 0xa438, 0xcb38, - 0xa438, 0x8224, 0xa438, 0xa288, 0xa438, 0x8180, 0xa438, 0xa110, - 0xa438, 0xa404, 0xa438, 0x800a, 0xa438, 0xd700, 0xa438, 0x6041, - 0xa438, 0x8402, 0xa438, 0xd415, 0xa438, 0x1000, 0xa438, 0x0a37, - 0xa438, 0xd13d, 0xa438, 0xd04a, 0xa438, 0x1000, 0xa438, 0x0a5e, - 0xa438, 0xd700, 0xa438, 0x5fb4, 0xa438, 0xcb39, 0xa438, 0xa00a, - 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0xd700, - 0xa438, 0x6041, 0xa438, 0xa402, 0xa438, 0xd17a, 0xa438, 0xd047, - 0xa438, 0x1000, 0xa438, 0x0a5e, 0xa438, 0xd700, 0xa438, 0x5fb4, - 0xa438, 0x1800, 0xa438, 0x0560, 0xa438, 0xa111, 0xa438, 0x0000, - 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0xd3f5, - 0xa438, 0xd219, 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, - 0xa438, 0x5fa5, 0xa438, 0xa215, 0xa438, 0xd30e, 0xa438, 0xd21a, - 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, 0xa438, 0x63e9, - 0xa438, 0xd708, 0xa438, 0x5f65, 0xa438, 0xd708, 0xa438, 0x7f36, - 0xa438, 0xa004, 0xa438, 0x1000, 0xa438, 0x0c35, 0xa438, 0x8004, - 0xa438, 0xa001, 0xa438, 0x1000, 0xa438, 0x0c35, 0xa438, 0x8001, - 0xa438, 0xd708, 0xa438, 0x4098, 0xa438, 0xd102, 0xa438, 0x9401, - 0xa438, 0xf003, 0xa438, 0xd103, 0xa438, 0xb401, 0xa438, 0x1000, - 0xa438, 0x0c27, 0xa438, 0xa108, 0xa438, 0x1000, 0xa438, 0x0c35, - 0xa438, 0x8108, 0xa438, 0x8110, 0xa438, 0x8294, 0xa438, 0xa202, - 0xa438, 0x1800, 0xa438, 0x0bdb, 0xa438, 0xd39c, 0xa438, 0xd210, - 0xa438, 0x1000, 0xa438, 0x0c31, 0xa438, 0xd708, 0xa438, 0x5fa5, - 0xa438, 0xd39c, 0xa438, 0xd210, 0xa438, 0x1000, 0xa438, 0x0c31, - 0xa438, 0xd708, 0xa438, 0x5fa5, 0xa438, 0x1000, 0xa438, 0x0c31, - 0xa438, 0xd708, 0xa438, 0x29b5, 0xa438, 0x840e, 0xa438, 0xd708, - 0xa438, 0x5f4a, 0xa438, 0x0c1f, 0xa438, 0x1014, 0xa438, 0x1000, - 0xa438, 0x0c31, 0xa438, 0xd709, 0xa438, 0x7fa4, 0xa438, 0x901f, - 0xa438, 0x1800, 0xa438, 0x0c23, 0xa438, 0xcb43, 0xa438, 0xa508, - 0xa438, 0xd701, 0xa438, 0x3699, 0xa438, 0x844a, 0xa438, 0xa504, - 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0xa00a, - 0xa438, 0xd700, 0xa438, 0x2109, 0xa438, 0x05ea, 0xa438, 0xa402, - 0xa438, 0x1800, 0xa438, 0x05ea, 0xa438, 0xcb90, 0xa438, 0x0cf0, - 0xa438, 0x0ca0, 0xa438, 0x1800, 0xa438, 0x06db, 0xa438, 0xd1ff, - 0xa438, 0xd052, 0xa438, 0xa508, 0xa438, 0x8718, 0xa438, 0xa00a, - 0xa438, 0xa190, 0xa438, 0xa2a0, 0xa438, 0xa404, 0xa438, 0x0cf0, - 0xa438, 0x0c50, 0xa438, 0x1800, 0xa438, 0x09ef, 0xa438, 0x1000, - 0xa438, 0x0a5e, 0xa438, 0xd704, 0xa438, 0x2e70, 0xa438, 0x06da, - 0xa438, 0xd700, 0xa438, 0x5f55, 0xa438, 0xa90c, 0xa438, 0x1800, - 0xa438, 0x0645, 0xa436, 0xA10E, 0xa438, 0x0644, 0xa436, 0xA10C, - 0xa438, 0x09e9, 0xa436, 0xA10A, 0xa438, 0x06da, 0xa436, 0xA108, - 0xa438, 0x05e1, 0xa436, 0xA106, 0xa438, 0x0be4, 0xa436, 0xA104, - 0xa438, 0x0435, 0xa436, 0xA102, 0xa438, 0x0141, 0xa436, 0xA100, - 0xa438, 0x026d, 0xa436, 0xA110, 0xa438, 0x00ff, 0xa436, 0xb87c, - 0xa438, 0x85fe, 0xa436, 0xb87e, 0xa438, 0xaf86, 0xa438, 0x16af, - 0xa438, 0x8699, 0xa438, 0xaf86, 0xa438, 0xe5af, 0xa438, 0x86f9, - 0xa438, 0xaf87, 0xa438, 0x7aaf, 0xa438, 0x883a, 0xa438, 0xaf88, - 0xa438, 0x58af, 0xa438, 0x8b6c, 0xa438, 0xd48b, 0xa438, 0x7c02, - 0xa438, 0x8644, 0xa438, 0x2c00, 0xa438, 0x503c, 0xa438, 0xffd6, - 0xa438, 0xac27, 0xa438, 0x18e1, 0xa438, 0x82fe, 0xa438, 0xad28, - 0xa438, 0x0cd4, 0xa438, 0x8b84, 0xa438, 0x0286, 0xa438, 0x442c, - 0xa438, 0x003c, 0xa438, 0xac27, 0xa438, 0x06ee, 0xa438, 0x8299, - 0xa438, 0x01ae, 0xa438, 0x04ee, 0xa438, 0x8299, 0xa438, 0x00af, - 0xa438, 0x23dc, 0xa438, 0xf9fa, 0xa438, 0xcefa, 0xa438, 0xfbef, - 0xa438, 0x79fb, 0xa438, 0xc4bf, 0xa438, 0x8b76, 0xa438, 0x026c, - 0xa438, 0x6dac, 0xa438, 0x2804, 0xa438, 0xd203, 0xa438, 0xae02, - 0xa438, 0xd201, 0xa438, 0xbdd8, 0xa438, 0x19d9, 0xa438, 0xef94, - 0xa438, 0x026c, 0xa438, 0x6d78, 0xa438, 0x03ef, 0xa438, 0x648a, - 0xa438, 0x0002, 0xa438, 0xbdd8, 0xa438, 0x19d9, 0xa438, 0xef94, - 0xa438, 0x026c, 0xa438, 0x6d78, 0xa438, 0x03ef, 0xa438, 0x7402, - 0xa438, 0x72cd, 0xa438, 0xac50, 0xa438, 0x02ef, 0xa438, 0x643a, - 0xa438, 0x019f, 0xa438, 0xe4ef, 0xa438, 0x4678, 0xa438, 0x03ac, - 0xa438, 0x2002, 0xa438, 0xae02, 0xa438, 0xd0ff, 0xa438, 0xffef, - 0xa438, 0x97ff, 0xa438, 0xfec6, 0xa438, 0xfefd, 0xa438, 0x041f, - 0xa438, 0x771f, 0xa438, 0x221c, 0xa438, 0x450d, 0xa438, 0x481f, - 0xa438, 0x00ac, 0xa438, 0x7f04, 0xa438, 0x1a94, 0xa438, 0xae08, - 0xa438, 0x1a94, 0xa438, 0xac7f, 0xa438, 0x03d7, 0xa438, 0x0100, - 0xa438, 0xef46, 0xa438, 0x0d48, 0xa438, 0x1f00, 0xa438, 0x1c45, - 0xa438, 0xef69, 0xa438, 0xef57, 0xa438, 0xef74, 0xa438, 0x0272, - 0xa438, 0xe8a7, 0xa438, 0xffff, 0xa438, 0x0d1a, 0xa438, 0x941b, - 0xa438, 0x979e, 0xa438, 0x072d, 0xa438, 0x0100, 0xa438, 0x1a64, - 0xa438, 0xef76, 0xa438, 0xef97, 0xa438, 0x0d98, 0xa438, 0xd400, - 0xa438, 0xff1d, 0xa438, 0x941a, 0xa438, 0x89cf, 0xa438, 0x1a75, - 0xa438, 0xaf74, 0xa438, 0xf9bf, 0xa438, 0x8b79, 0xa438, 0x026c, - 0xa438, 0x6da1, 0xa438, 0x0005, 0xa438, 0xe180, 0xa438, 0xa0ae, - 0xa438, 0x03e1, 0xa438, 0x80a1, 0xa438, 0xaf26, 0xa438, 0x9aac, - 0xa438, 0x284d, 0xa438, 0xe08f, 0xa438, 0xffef, 0xa438, 0x10c0, - 0xa438, 0xe08f, 0xa438, 0xfe10, 0xa438, 0x1b08, 0xa438, 0xa000, - 0xa438, 0x04c8, 0xa438, 0xaf40, 0xa438, 0x67c8, 0xa438, 0xbf8b, - 0xa438, 0x8c02, 0xa438, 0x6c4e, 0xa438, 0xc4bf, 0xa438, 0x8b8f, - 0xa438, 0x026c, 0xa438, 0x6def, 0xa438, 0x74e0, 0xa438, 0x830c, - 0xa438, 0xad20, 0xa438, 0x0302, 0xa438, 0x74ac, 0xa438, 0xccef, - 0xa438, 0x971b, 0xa438, 0x76ad, 0xa438, 0x5f02, 0xa438, 0xae13, - 0xa438, 0xef69, 0xa438, 0xef30, 0xa438, 0x1b32, 0xa438, 0xc4ef, - 0xa438, 0x46e4, 0xa438, 0x8ffb, 0xa438, 0xe58f, 0xa438, 0xfce7, - 0xa438, 0x8ffd, 0xa438, 0xcc10, 0xa438, 0x11ae, 0xa438, 0xb8d1, - 0xa438, 0x00a1, 0xa438, 0x1f03, 0xa438, 0xaf40, 0xa438, 0x4fbf, - 0xa438, 0x8b8c, 0xa438, 0x026c, 0xa438, 0x4ec4, 0xa438, 0xbf8b, - 0xa438, 0x8f02, 0xa438, 0x6c6d, 0xa438, 0xef74, 0xa438, 0xe083, - 0xa438, 0x0cad, 0xa438, 0x2003, 0xa438, 0x0274, 0xa438, 0xaccc, - 0xa438, 0xef97, 0xa438, 0x1b76, 0xa438, 0xad5f, 0xa438, 0x02ae, - 0xa438, 0x04ef, 0xa438, 0x69ef, 0xa438, 0x3111, 0xa438, 0xaed1, - 0xa438, 0x0287, 0xa438, 0x80af, 0xa438, 0x2293, 0xa438, 0xf8f9, - 0xa438, 0xfafb, 0xa438, 0xef59, 0xa438, 0xe080, 0xa438, 0x13ad, - 0xa438, 0x252f, 0xa438, 0xbf88, 0xa438, 0x2802, 0xa438, 0x6c6d, - 0xa438, 0xef64, 0xa438, 0x1f44, 0xa438, 0xe18f, 0xa438, 0xb91b, - 0xa438, 0x64ad, 0xa438, 0x4f1d, 0xa438, 0xd688, 0xa438, 0x2bd7, - 0xa438, 0x882e, 0xa438, 0x0274, 0xa438, 0x73ad, 0xa438, 0x5008, - 0xa438, 0xbf88, 0xa438, 0x3102, 0xa438, 0x737c, 0xa438, 0xae03, - 0xa438, 0x0287, 0xa438, 0xd0bf, 0xa438, 0x882b, 0xa438, 0x0273, - 0xa438, 0x73e0, 0xa438, 0x824c, 0xa438, 0xf621, 0xa438, 0xe482, - 0xa438, 0x4cbf, 0xa438, 0x8834, 0xa438, 0x0273, 0xa438, 0x7cef, - 0xa438, 0x95ff, 0xa438, 0xfefd, 0xa438, 0xfc04, 0xa438, 0xf8f9, - 0xa438, 0xfafb, 0xa438, 0xef79, 0xa438, 0xbf88, 0xa438, 0x1f02, - 0xa438, 0x737c, 0xa438, 0x1f22, 0xa438, 0xac32, 0xa438, 0x31ef, - 0xa438, 0x12bf, 0xa438, 0x8822, 0xa438, 0x026c, 0xa438, 0x4ed6, - 0xa438, 0x8fba, 0xa438, 0x1f33, 0xa438, 0xac3c, 0xa438, 0x1eef, - 0xa438, 0x13bf, 0xa438, 0x8837, 0xa438, 0x026c, 0xa438, 0x4eef, - 0xa438, 0x96d8, 0xa438, 0x19d9, 0xa438, 0xbf88, 0xa438, 0x2502, - 0xa438, 0x6c4e, 0xa438, 0xbf88, 0xa438, 0x2502, 0xa438, 0x6c4e, - 0xa438, 0x1616, 0xa438, 0x13ae, 0xa438, 0xdf12, 0xa438, 0xaecc, - 0xa438, 0xbf88, 0xa438, 0x1f02, 0xa438, 0x7373, 0xa438, 0xef97, - 0xa438, 0xfffe, 0xa438, 0xfdfc, 0xa438, 0x0466, 0xa438, 0xac88, - 0xa438, 0x54ac, 0xa438, 0x88f0, 0xa438, 0xac8a, 0xa438, 0x92ac, - 0xa438, 0xbadd, 0xa438, 0xac6c, 0xa438, 0xeeac, 0xa438, 0x6cff, - 0xa438, 0xad02, 0xa438, 0x99ac, 0xa438, 0x0030, 0xa438, 0xac88, - 0xa438, 0xd4c3, 0xa438, 0x5000, 0xa438, 0x0000, 0xa438, 0x0000, - 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x0000, - 0xa438, 0x0000, 0xa438, 0x0000, 0xa438, 0x00b4, 0xa438, 0xecee, - 0xa438, 0x8298, 0xa438, 0x00af, 0xa438, 0x1412, 0xa438, 0xf8bf, - 0xa438, 0x8b5d, 0xa438, 0x026c, 0xa438, 0x6d58, 0xa438, 0x03e1, - 0xa438, 0x8fb8, 0xa438, 0x2901, 0xa438, 0xe58f, 0xa438, 0xb8a0, - 0xa438, 0x0049, 0xa438, 0xef47, 0xa438, 0xe483, 0xa438, 0x02e5, - 0xa438, 0x8303, 0xa438, 0xbfc2, 0xa438, 0x5f1a, 0xa438, 0x95f7, - 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00d8, 0xa438, 0xf605, - 0xa438, 0x1f11, 0xa438, 0xef60, 0xa438, 0xbf8b, 0xa438, 0x3002, - 0xa438, 0x6c4e, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c6d, - 0xa438, 0xf728, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, - 0xa438, 0xf628, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, - 0xa438, 0x0c64, 0xa438, 0xef46, 0xa438, 0xbf8b, 0xa438, 0x6002, - 0xa438, 0x6c4e, 0xa438, 0x0289, 0xa438, 0x9902, 0xa438, 0x3920, - 0xa438, 0xaf89, 0xa438, 0x96a0, 0xa438, 0x0149, 0xa438, 0xef47, - 0xa438, 0xe483, 0xa438, 0x04e5, 0xa438, 0x8305, 0xa438, 0xbfc2, - 0xa438, 0x5f1a, 0xa438, 0x95f7, 0xa438, 0x05ee, 0xa438, 0xffd2, - 0xa438, 0x00d8, 0xa438, 0xf605, 0xa438, 0x1f11, 0xa438, 0xef60, - 0xa438, 0xbf8b, 0xa438, 0x3002, 0xa438, 0x6c4e, 0xa438, 0xbf8b, - 0xa438, 0x3302, 0xa438, 0x6c6d, 0xa438, 0xf729, 0xa438, 0xbf8b, - 0xa438, 0x3302, 0xa438, 0x6c4e, 0xa438, 0xf629, 0xa438, 0xbf8b, - 0xa438, 0x3302, 0xa438, 0x6c4e, 0xa438, 0x0c64, 0xa438, 0xef46, - 0xa438, 0xbf8b, 0xa438, 0x6302, 0xa438, 0x6c4e, 0xa438, 0x0289, - 0xa438, 0x9902, 0xa438, 0x3920, 0xa438, 0xaf89, 0xa438, 0x96a0, - 0xa438, 0x0249, 0xa438, 0xef47, 0xa438, 0xe483, 0xa438, 0x06e5, - 0xa438, 0x8307, 0xa438, 0xbfc2, 0xa438, 0x5f1a, 0xa438, 0x95f7, - 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00d8, 0xa438, 0xf605, - 0xa438, 0x1f11, 0xa438, 0xef60, 0xa438, 0xbf8b, 0xa438, 0x3002, - 0xa438, 0x6c4e, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c6d, - 0xa438, 0xf72a, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, - 0xa438, 0xf62a, 0xa438, 0xbf8b, 0xa438, 0x3302, 0xa438, 0x6c4e, - 0xa438, 0x0c64, 0xa438, 0xef46, 0xa438, 0xbf8b, 0xa438, 0x6602, - 0xa438, 0x6c4e, 0xa438, 0x0289, 0xa438, 0x9902, 0xa438, 0x3920, - 0xa438, 0xaf89, 0xa438, 0x96ef, 0xa438, 0x47e4, 0xa438, 0x8308, - 0xa438, 0xe583, 0xa438, 0x09bf, 0xa438, 0xc25f, 0xa438, 0x1a95, - 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xd8f6, - 0xa438, 0x051f, 0xa438, 0x11ef, 0xa438, 0x60bf, 0xa438, 0x8b30, - 0xa438, 0x026c, 0xa438, 0x4ebf, 0xa438, 0x8b33, 0xa438, 0x026c, - 0xa438, 0x6df7, 0xa438, 0x2bbf, 0xa438, 0x8b33, 0xa438, 0x026c, - 0xa438, 0x4ef6, 0xa438, 0x2bbf, 0xa438, 0x8b33, 0xa438, 0x026c, - 0xa438, 0x4e0c, 0xa438, 0x64ef, 0xa438, 0x46bf, 0xa438, 0x8b69, - 0xa438, 0x026c, 0xa438, 0x4e02, 0xa438, 0x8999, 0xa438, 0x0239, - 0xa438, 0x20af, 0xa438, 0x8996, 0xa438, 0xaf39, 0xa438, 0x1ef8, - 0xa438, 0xf9fa, 0xa438, 0xe08f, 0xa438, 0xb838, 0xa438, 0x02ad, - 0xa438, 0x2702, 0xa438, 0xae03, 0xa438, 0xaf8b, 0xa438, 0x201f, - 0xa438, 0x66ef, 0xa438, 0x65bf, 0xa438, 0xc21f, 0xa438, 0x1a96, - 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xdaf6, - 0xa438, 0x05bf, 0xa438, 0xc22f, 0xa438, 0x1a96, 0xa438, 0xf705, - 0xa438, 0xeeff, 0xa438, 0xd200, 0xa438, 0xdbf6, 0xa438, 0x05ef, - 0xa438, 0x021f, 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b3c, - 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x021b, 0xa438, 0x031f, - 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b36, 0xa438, 0x026c, - 0xa438, 0x4eef, 0xa438, 0x021a, 0xa438, 0x031f, 0xa438, 0x110d, - 0xa438, 0x42bf, 0xa438, 0x8b39, 0xa438, 0x026c, 0xa438, 0x4ebf, - 0xa438, 0xc23f, 0xa438, 0x1a96, 0xa438, 0xf705, 0xa438, 0xeeff, - 0xa438, 0xd200, 0xa438, 0xdaf6, 0xa438, 0x05bf, 0xa438, 0xc24f, - 0xa438, 0x1a96, 0xa438, 0xf705, 0xa438, 0xeeff, 0xa438, 0xd200, - 0xa438, 0xdbf6, 0xa438, 0x05ef, 0xa438, 0x021f, 0xa438, 0x110d, - 0xa438, 0x42bf, 0xa438, 0x8b45, 0xa438, 0x026c, 0xa438, 0x4eef, - 0xa438, 0x021b, 0xa438, 0x031f, 0xa438, 0x110d, 0xa438, 0x42bf, - 0xa438, 0x8b3f, 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x021a, - 0xa438, 0x031f, 0xa438, 0x110d, 0xa438, 0x42bf, 0xa438, 0x8b42, - 0xa438, 0x026c, 0xa438, 0x4eef, 0xa438, 0x56d0, 0xa438, 0x201f, - 0xa438, 0x11bf, 0xa438, 0x8b4e, 0xa438, 0x026c, 0xa438, 0x4ebf, - 0xa438, 0x8b48, 0xa438, 0x026c, 0xa438, 0x4ebf, 0xa438, 0x8b4b, - 0xa438, 0x026c, 0xa438, 0x4ee1, 0xa438, 0x8578, 0xa438, 0xef03, - 0xa438, 0x480a, 0xa438, 0x2805, 0xa438, 0xef20, 0xa438, 0x1b01, - 0xa438, 0xad27, 0xa438, 0x3f1f, 0xa438, 0x44e0, 0xa438, 0x8560, - 0xa438, 0xe185, 0xa438, 0x61bf, 0xa438, 0x8b51, 0xa438, 0x026c, - 0xa438, 0x4ee0, 0xa438, 0x8566, 0xa438, 0xe185, 0xa438, 0x67bf, - 0xa438, 0x8b54, 0xa438, 0x026c, 0xa438, 0x4ee0, 0xa438, 0x856c, - 0xa438, 0xe185, 0xa438, 0x6dbf, 0xa438, 0x8b57, 0xa438, 0x026c, - 0xa438, 0x4ee0, 0xa438, 0x8572, 0xa438, 0xe185, 0xa438, 0x73bf, - 0xa438, 0x8b5a, 0xa438, 0x026c, 0xa438, 0x4ee1, 0xa438, 0x8fb8, - 0xa438, 0x5900, 0xa438, 0xf728, 0xa438, 0xe58f, 0xa438, 0xb8af, - 0xa438, 0x8b2c, 0xa438, 0xe185, 0xa438, 0x791b, 0xa438, 0x21ad, - 0xa438, 0x373e, 0xa438, 0x1f44, 0xa438, 0xe085, 0xa438, 0x62e1, - 0xa438, 0x8563, 0xa438, 0xbf8b, 0xa438, 0x5102, 0xa438, 0x6c4e, - 0xa438, 0xe085, 0xa438, 0x68e1, 0xa438, 0x8569, 0xa438, 0xbf8b, - 0xa438, 0x5402, 0xa438, 0x6c4e, 0xa438, 0xe085, 0xa438, 0x6ee1, - 0xa438, 0x856f, 0xa438, 0xbf8b, 0xa438, 0x5702, 0xa438, 0x6c4e, - 0xa438, 0xe085, 0xa438, 0x74e1, 0xa438, 0x8575, 0xa438, 0xbf8b, - 0xa438, 0x5a02, 0xa438, 0x6c4e, 0xa438, 0xe18f, 0xa438, 0xb859, - 0xa438, 0x00f7, 0xa438, 0x28e5, 0xa438, 0x8fb8, 0xa438, 0xae4a, - 0xa438, 0x1f44, 0xa438, 0xe085, 0xa438, 0x64e1, 0xa438, 0x8565, - 0xa438, 0xbf8b, 0xa438, 0x5102, 0xa438, 0x6c4e, 0xa438, 0xe085, - 0xa438, 0x6ae1, 0xa438, 0x856b, 0xa438, 0xbf8b, 0xa438, 0x5402, - 0xa438, 0x6c4e, 0xa438, 0xe085, 0xa438, 0x70e1, 0xa438, 0x8571, - 0xa438, 0xbf8b, 0xa438, 0x5702, 0xa438, 0x6c4e, 0xa438, 0xe085, - 0xa438, 0x76e1, 0xa438, 0x8577, 0xa438, 0xbf8b, 0xa438, 0x5a02, - 0xa438, 0x6c4e, 0xa438, 0xe18f, 0xa438, 0xb859, 0xa438, 0x00f7, - 0xa438, 0x28e5, 0xa438, 0x8fb8, 0xa438, 0xae0c, 0xa438, 0xe18f, - 0xa438, 0xb839, 0xa438, 0x04ac, 0xa438, 0x2f04, 0xa438, 0xee8f, - 0xa438, 0xb800, 0xa438, 0xfefd, 0xa438, 0xfc04, 0xa438, 0xf0ac, - 0xa438, 0x8efc, 0xa438, 0xac8c, 0xa438, 0xf0ac, 0xa438, 0xfaf0, - 0xa438, 0xacf8, 0xa438, 0xf0ac, 0xa438, 0xf6f0, 0xa438, 0xad00, - 0xa438, 0xf0ac, 0xa438, 0xfef0, 0xa438, 0xacfc, 0xa438, 0xf0ac, - 0xa438, 0xf4f0, 0xa438, 0xacf2, 0xa438, 0xf0ac, 0xa438, 0xf0f0, - 0xa438, 0xacb0, 0xa438, 0xf0ac, 0xa438, 0xaef0, 0xa438, 0xacac, - 0xa438, 0xf0ac, 0xa438, 0xaaf0, 0xa438, 0xacee, 0xa438, 0xf0b0, - 0xa438, 0x24f0, 0xa438, 0xb0a4, 0xa438, 0xf0b1, 0xa438, 0x24f0, - 0xa438, 0xb1a4, 0xa438, 0xee8f, 0xa438, 0xb800, 0xa438, 0xd400, - 0xa438, 0x00af, 0xa438, 0x3976, 0xa438, 0x66ac, 0xa438, 0xeabb, - 0xa438, 0xa430, 0xa438, 0x6e50, 0xa438, 0x6e53, 0xa438, 0x6e56, - 0xa438, 0x6e59, 0xa438, 0x6e5c, 0xa438, 0x6e5f, 0xa438, 0x6e62, - 0xa438, 0x6e65, 0xa438, 0xd9ac, 0xa438, 0x70f0, 0xa438, 0xac6a, - 0xa436, 0xb85e, 0xa438, 0x23b7, 0xa436, 0xb860, 0xa438, 0x74db, - 0xa436, 0xb862, 0xa438, 0x268c, 0xa436, 0xb864, 0xa438, 0x3FE5, - 0xa436, 0xb886, 0xa438, 0x2250, 0xa436, 0xb888, 0xa438, 0x140e, - 0xa436, 0xb88a, 0xa438, 0x3696, 0xa436, 0xb88c, 0xa438, 0x3973, - 0xa436, 0xb838, 0xa438, 0x00ff, 0xb820, 0x0010, 0xa436, 0x8464, - 0xa438, 0xaf84, 0xa438, 0x7caf, 0xa438, 0x8485, 0xa438, 0xaf85, - 0xa438, 0x13af, 0xa438, 0x851e, 0xa438, 0xaf85, 0xa438, 0xb9af, - 0xa438, 0x8684, 0xa438, 0xaf87, 0xa438, 0x01af, 0xa438, 0x8701, - 0xa438, 0xac38, 0xa438, 0x03af, 0xa438, 0x38bb, 0xa438, 0xaf38, - 0xa438, 0xc302, 0xa438, 0x4618, 0xa438, 0xbf85, 0xa438, 0x0a02, - 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0x1002, 0xa438, 0x54c0, - 0xa438, 0xd400, 0xa438, 0x0fbf, 0xa438, 0x8507, 0xa438, 0x024f, - 0xa438, 0x48bf, 0xa438, 0x8504, 0xa438, 0x024f, 0xa438, 0x6759, - 0xa438, 0xf0a1, 0xa438, 0x3008, 0xa438, 0xbf85, 0xa438, 0x0d02, - 0xa438, 0x54c0, 0xa438, 0xae06, 0xa438, 0xbf85, 0xa438, 0x0d02, - 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0x0402, 0xa438, 0x4f67, - 0xa438, 0xa183, 0xa438, 0x02ae, 0xa438, 0x15a1, 0xa438, 0x8502, - 0xa438, 0xae10, 0xa438, 0x59f0, 0xa438, 0xa180, 0xa438, 0x16bf, - 0xa438, 0x8501, 0xa438, 0x024f, 0xa438, 0x67a1, 0xa438, 0x381b, - 0xa438, 0xae0b, 0xa438, 0xe18f, 0xa438, 0xffbf, 0xa438, 0x84fe, - 0xa438, 0x024f, 0xa438, 0x48ae, 0xa438, 0x17bf, 0xa438, 0x84fe, - 0xa438, 0x0254, 0xa438, 0xb7bf, 0xa438, 0x84fb, 0xa438, 0x0254, - 0xa438, 0xb7ae, 0xa438, 0x09a1, 0xa438, 0x5006, 0xa438, 0xbf84, - 0xa438, 0xfb02, 0xa438, 0x54c0, 0xa438, 0xaf04, 0xa438, 0x4700, - 0xa438, 0xad34, 0xa438, 0xfdad, 0xa438, 0x0670, 0xa438, 0xae14, - 0xa438, 0xf0a6, 0xa438, 0x00b8, 0xa438, 0xbd32, 0xa438, 0x30bd, - 0xa438, 0x30aa, 0xa438, 0xbd2c, 0xa438, 0xccbd, 0xa438, 0x2ca1, - 0xa438, 0x0705, 0xa438, 0xec80, 0xa438, 0xaf40, 0xa438, 0xf7af, - 0xa438, 0x40f5, 0xa438, 0xd101, 0xa438, 0xbf85, 0xa438, 0xa402, - 0xa438, 0x4f48, 0xa438, 0xbf85, 0xa438, 0xa702, 0xa438, 0x54c0, - 0xa438, 0xd10f, 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, - 0xa438, 0x024d, 0xa438, 0x6abf, 0xa438, 0x85ad, 0xa438, 0x024f, - 0xa438, 0x67bf, 0xa438, 0x8ff7, 0xa438, 0xddbf, 0xa438, 0x85b0, - 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff8, 0xa438, 0xddbf, - 0xa438, 0x85b3, 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff9, - 0xa438, 0xddbf, 0xa438, 0x85b6, 0xa438, 0x024f, 0xa438, 0x67bf, - 0xa438, 0x8ffa, 0xa438, 0xddd1, 0xa438, 0x00bf, 0xa438, 0x85aa, - 0xa438, 0x024f, 0xa438, 0x4802, 0xa438, 0x4d6a, 0xa438, 0xbf85, - 0xa438, 0xad02, 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfbdd, - 0xa438, 0xbf85, 0xa438, 0xb002, 0xa438, 0x4f67, 0xa438, 0xbf8f, - 0xa438, 0xfcdd, 0xa438, 0xbf85, 0xa438, 0xb302, 0xa438, 0x4f67, - 0xa438, 0xbf8f, 0xa438, 0xfddd, 0xa438, 0xbf85, 0xa438, 0xb602, - 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfedd, 0xa438, 0xbf85, - 0xa438, 0xa702, 0xa438, 0x54b7, 0xa438, 0xbf85, 0xa438, 0xa102, - 0xa438, 0x54b7, 0xa438, 0xaf3c, 0xa438, 0x2066, 0xa438, 0xb800, - 0xa438, 0xb8bd, 0xa438, 0x30ee, 0xa438, 0xbd2c, 0xa438, 0xb8bd, - 0xa438, 0x7040, 0xa438, 0xbd86, 0xa438, 0xc8bd, 0xa438, 0x8640, - 0xa438, 0xbd88, 0xa438, 0xc8bd, 0xa438, 0x8802, 0xa438, 0x1929, - 0xa438, 0xa202, 0xa438, 0x02ae, 0xa438, 0x03a2, 0xa438, 0x032e, - 0xa438, 0xd10f, 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, - 0xa438, 0xe18f, 0xa438, 0xf7bf, 0xa438, 0x85ad, 0xa438, 0x024f, - 0xa438, 0x48e1, 0xa438, 0x8ff8, 0xa438, 0xbf85, 0xa438, 0xb002, - 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf9bf, 0xa438, 0x85b3, - 0xa438, 0x024f, 0xa438, 0x48e1, 0xa438, 0x8ffa, 0xa438, 0xbf85, - 0xa438, 0xb602, 0xa438, 0x4f48, 0xa438, 0xae2c, 0xa438, 0xd100, - 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, 0xa438, 0xe18f, - 0xa438, 0xfbbf, 0xa438, 0x85ad, 0xa438, 0x024f, 0xa438, 0x48e1, - 0xa438, 0x8ffc, 0xa438, 0xbf85, 0xa438, 0xb002, 0xa438, 0x4f48, - 0xa438, 0xe18f, 0xa438, 0xfdbf, 0xa438, 0x85b3, 0xa438, 0x024f, - 0xa438, 0x48e1, 0xa438, 0x8ffe, 0xa438, 0xbf85, 0xa438, 0xb602, - 0xa438, 0x4f48, 0xa438, 0xbf86, 0xa438, 0x7e02, 0xa438, 0x4f67, - 0xa438, 0xa100, 0xa438, 0x02ae, 0xa438, 0x25a1, 0xa438, 0x041d, - 0xa438, 0xe18f, 0xa438, 0xf1bf, 0xa438, 0x8675, 0xa438, 0x024f, - 0xa438, 0x48e1, 0xa438, 0x8ff2, 0xa438, 0xbf86, 0xa438, 0x7802, - 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf3bf, 0xa438, 0x867b, - 0xa438, 0x024f, 0xa438, 0x48ae, 0xa438, 0x29a1, 0xa438, 0x070b, - 0xa438, 0xae24, 0xa438, 0xbf86, 0xa438, 0x8102, 0xa438, 0x4f67, - 0xa438, 0xad28, 0xa438, 0x1be1, 0xa438, 0x8ff4, 0xa438, 0xbf86, - 0xa438, 0x7502, 0xa438, 0x4f48, 0xa438, 0xe18f, 0xa438, 0xf5bf, - 0xa438, 0x8678, 0xa438, 0x024f, 0xa438, 0x48e1, 0xa438, 0x8ff6, - 0xa438, 0xbf86, 0xa438, 0x7b02, 0xa438, 0x4f48, 0xa438, 0xaf09, - 0xa438, 0x8420, 0xa438, 0xbc32, 0xa438, 0x20bc, 0xa438, 0x3e76, - 0xa438, 0xbc08, 0xa438, 0xfda6, 0xa438, 0x1a00, 0xa438, 0xb64e, - 0xa438, 0xd101, 0xa438, 0xbf85, 0xa438, 0xa402, 0xa438, 0x4f48, - 0xa438, 0xbf85, 0xa438, 0xa702, 0xa438, 0x54c0, 0xa438, 0xd10f, - 0xa438, 0xbf85, 0xa438, 0xaa02, 0xa438, 0x4f48, 0xa438, 0x024d, - 0xa438, 0x6abf, 0xa438, 0x85ad, 0xa438, 0x024f, 0xa438, 0x67bf, - 0xa438, 0x8ff7, 0xa438, 0xddbf, 0xa438, 0x85b0, 0xa438, 0x024f, - 0xa438, 0x67bf, 0xa438, 0x8ff8, 0xa438, 0xddbf, 0xa438, 0x85b3, - 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ff9, 0xa438, 0xddbf, - 0xa438, 0x85b6, 0xa438, 0x024f, 0xa438, 0x67bf, 0xa438, 0x8ffa, - 0xa438, 0xddd1, 0xa438, 0x00bf, 0xa438, 0x85aa, 0xa438, 0x024f, - 0xa438, 0x4802, 0xa438, 0x4d6a, 0xa438, 0xbf85, 0xa438, 0xad02, - 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfbdd, 0xa438, 0xbf85, - 0xa438, 0xb002, 0xa438, 0x4f67, 0xa438, 0xbf8f, 0xa438, 0xfcdd, - 0xa438, 0xbf85, 0xa438, 0xb302, 0xa438, 0x4f67, 0xa438, 0xbf8f, - 0xa438, 0xfddd, 0xa438, 0xbf85, 0xa438, 0xb602, 0xa438, 0x4f67, - 0xa438, 0xbf8f, 0xa438, 0xfedd, 0xa438, 0xbf85, 0xa438, 0xa702, - 0xa438, 0x54b7, 0xa438, 0xaf00, 0xa438, 0x8800, 0xa436, 0xb818, - 0xa438, 0x38b8, 0xa436, 0xb81a, 0xa438, 0x0444, 0xa436, 0xb81c, - 0xa438, 0x40ee, 0xa436, 0xb81e, 0xa438, 0x3C1A, 0xa436, 0xb850, - 0xa438, 0x0981, 0xa436, 0xb852, 0xa438, 0x0085, 0xa436, 0xb878, - 0xa438, 0xffff, 0xa436, 0xb884, 0xa438, 0xffff, 0xa436, 0xb832, - 0xa438, 0x003f, 0xa436, 0x0000, 0xa438, 0x0000, 0xa436, 0xB82E, - 0xa438, 0x0000, 0xa436, 0x8024, 0xa438, 0x0000, 0xb820, 0x0000, - 0xa436, 0x801E, 0xa438, 0x0021, 0xFFFF, 0xFFFF -}; - -static const u16 phy_mcu_ram_code_8125b_2[] = { - 0xa436, 0x8024, 0xa438, 0x3701, 0xa436, 0xB82E, 0xa438, 0x0001, - 0xb820, 0x0090, 0xa436, 0xA016, 0xa438, 0x0000, 0xa436, 0xA012, - 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, - 0xa438, 0x1800, 0xa438, 0x801a, 0xa438, 0x1800, 0xa438, 0x803f, - 0xa438, 0x1800, 0xa438, 0x8045, 0xa438, 0x1800, 0xa438, 0x8067, - 0xa438, 0x1800, 0xa438, 0x806d, 0xa438, 0x1800, 0xa438, 0x8071, - 0xa438, 0x1800, 0xa438, 0x80b1, 0xa438, 0xd093, 0xa438, 0xd1c4, - 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd704, 0xa438, 0x5fbc, - 0xa438, 0xd504, 0xa438, 0xc9f1, 0xa438, 0x1800, 0xa438, 0x0fc9, - 0xa438, 0xbb50, 0xa438, 0xd505, 0xa438, 0xa202, 0xa438, 0xd504, - 0xa438, 0x8c0f, 0xa438, 0xd500, 0xa438, 0x1000, 0xa438, 0x1519, - 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd75e, 0xa438, 0x5fae, - 0xa438, 0x9b50, 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd75e, - 0xa438, 0x7fae, 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd707, - 0xa438, 0x40a7, 0xa438, 0xd719, 0xa438, 0x4071, 0xa438, 0x1800, - 0xa438, 0x1557, 0xa438, 0xd719, 0xa438, 0x2f70, 0xa438, 0x803b, - 0xa438, 0x2f73, 0xa438, 0x156a, 0xa438, 0x5e70, 0xa438, 0x1800, - 0xa438, 0x155d, 0xa438, 0xd505, 0xa438, 0xa202, 0xa438, 0xd500, - 0xa438, 0xffed, 0xa438, 0xd709, 0xa438, 0x4054, 0xa438, 0xa788, - 0xa438, 0xd70b, 0xa438, 0x1800, 0xa438, 0x172a, 0xa438, 0xc0c1, - 0xa438, 0xc0c0, 0xa438, 0xd05a, 0xa438, 0xd1ba, 0xa438, 0xd701, - 0xa438, 0x2529, 0xa438, 0x022a, 0xa438, 0xd0a7, 0xa438, 0xd1b9, - 0xa438, 0xa208, 0xa438, 0x1000, 0xa438, 0x080e, 0xa438, 0xd701, - 0xa438, 0x408b, 0xa438, 0x1000, 0xa438, 0x0a65, 0xa438, 0xf003, - 0xa438, 0x1000, 0xa438, 0x0a6b, 0xa438, 0xd701, 0xa438, 0x1000, - 0xa438, 0x0920, 0xa438, 0x1000, 0xa438, 0x0915, 0xa438, 0x1000, - 0xa438, 0x0909, 0xa438, 0x228f, 0xa438, 0x804e, 0xa438, 0x9801, - 0xa438, 0xd71e, 0xa438, 0x5d61, 0xa438, 0xd701, 0xa438, 0x1800, - 0xa438, 0x022a, 0xa438, 0x2005, 0xa438, 0x091a, 0xa438, 0x3bd9, - 0xa438, 0x0919, 0xa438, 0x1800, 0xa438, 0x0916, 0xa438, 0xd090, - 0xa438, 0xd1c9, 0xa438, 0x1800, 0xa438, 0x1064, 0xa438, 0xd096, - 0xa438, 0xd1a9, 0xa438, 0xd503, 0xa438, 0xa104, 0xa438, 0x0c07, - 0xa438, 0x0902, 0xa438, 0xd500, 0xa438, 0xbc10, 0xa438, 0xd501, - 0xa438, 0xce01, 0xa438, 0xa201, 0xa438, 0x8201, 0xa438, 0xce00, - 0xa438, 0xd500, 0xa438, 0xc484, 0xa438, 0xd503, 0xa438, 0xcc02, - 0xa438, 0xcd0d, 0xa438, 0xaf01, 0xa438, 0xd500, 0xa438, 0xd703, - 0xa438, 0x4371, 0xa438, 0xbd08, 0xa438, 0x1000, 0xa438, 0x135c, - 0xa438, 0xd75e, 0xa438, 0x5fb3, 0xa438, 0xd503, 0xa438, 0xd0f5, - 0xa438, 0xd1c6, 0xa438, 0x0cf0, 0xa438, 0x0e50, 0xa438, 0xd704, - 0xa438, 0x401c, 0xa438, 0xd0f5, 0xa438, 0xd1c6, 0xa438, 0x0cf0, - 0xa438, 0x0ea0, 0xa438, 0x401c, 0xa438, 0xd07b, 0xa438, 0xd1c5, - 0xa438, 0x8ef0, 0xa438, 0x401c, 0xa438, 0x9d08, 0xa438, 0x1000, - 0xa438, 0x135c, 0xa438, 0xd75e, 0xa438, 0x7fb3, 0xa438, 0x1000, - 0xa438, 0x135c, 0xa438, 0xd75e, 0xa438, 0x5fad, 0xa438, 0x1000, - 0xa438, 0x14c5, 0xa438, 0xd703, 0xa438, 0x3181, 0xa438, 0x80af, - 0xa438, 0x60ad, 0xa438, 0x1000, 0xa438, 0x135c, 0xa438, 0xd703, - 0xa438, 0x5fba, 0xa438, 0x1800, 0xa438, 0x0cc7, 0xa438, 0xa802, - 0xa438, 0xa301, 0xa438, 0xa801, 0xa438, 0xc004, 0xa438, 0xd710, - 0xa438, 0x4000, 0xa438, 0x1800, 0xa438, 0x1e79, 0xa436, 0xA026, - 0xa438, 0x1e78, 0xa436, 0xA024, 0xa438, 0x0c93, 0xa436, 0xA022, - 0xa438, 0x1062, 0xa436, 0xA020, 0xa438, 0x0915, 0xa436, 0xA006, - 0xa438, 0x020a, 0xa436, 0xA004, 0xa438, 0x1726, 0xa436, 0xA002, - 0xa438, 0x1542, 0xa436, 0xA000, 0xa438, 0x0fc7, 0xa436, 0xA008, - 0xa438, 0xff00, 0xa436, 0xA016, 0xa438, 0x0010, 0xa436, 0xA012, - 0xa438, 0x0000, 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, - 0xa438, 0x1800, 0xa438, 0x801d, 0xa438, 0x1800, 0xa438, 0x802c, - 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0x1800, 0xa438, 0x802c, - 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0x1800, 0xa438, 0x802c, - 0xa438, 0x1800, 0xa438, 0x802c, 0xa438, 0xd700, 0xa438, 0x6090, - 0xa438, 0x60d1, 0xa438, 0xc95c, 0xa438, 0xf007, 0xa438, 0x60b1, - 0xa438, 0xc95a, 0xa438, 0xf004, 0xa438, 0xc956, 0xa438, 0xf002, - 0xa438, 0xc94e, 0xa438, 0x1800, 0xa438, 0x00cd, 0xa438, 0xd700, - 0xa438, 0x6090, 0xa438, 0x60d1, 0xa438, 0xc95c, 0xa438, 0xf007, - 0xa438, 0x60b1, 0xa438, 0xc95a, 0xa438, 0xf004, 0xa438, 0xc956, - 0xa438, 0xf002, 0xa438, 0xc94e, 0xa438, 0x1000, 0xa438, 0x022a, - 0xa438, 0x1800, 0xa438, 0x0132, 0xa436, 0xA08E, 0xa438, 0xffff, - 0xa436, 0xA08C, 0xa438, 0xffff, 0xa436, 0xA08A, 0xa438, 0xffff, - 0xa436, 0xA088, 0xa438, 0xffff, 0xa436, 0xA086, 0xa438, 0xffff, - 0xa436, 0xA084, 0xa438, 0xffff, 0xa436, 0xA082, 0xa438, 0x012f, - 0xa436, 0xA080, 0xa438, 0x00cc, 0xa436, 0xA090, 0xa438, 0x0103, - 0xa436, 0xA016, 0xa438, 0x0020, 0xa436, 0xA012, 0xa438, 0x0000, - 0xa436, 0xA014, 0xa438, 0x1800, 0xa438, 0x8010, 0xa438, 0x1800, - 0xa438, 0x8020, 0xa438, 0x1800, 0xa438, 0x802a, 0xa438, 0x1800, - 0xa438, 0x8035, 0xa438, 0x1800, 0xa438, 0x803c, 0xa438, 0x1800, - 0xa438, 0x803c, 0xa438, 0x1800, 0xa438, 0x803c, 0xa438, 0x1800, - 0xa438, 0x803c, 0xa438, 0xd107, 0xa438, 0xd042, 0xa438, 0xa404, - 0xa438, 0x1000, 0xa438, 0x09df, 0xa438, 0xd700, 0xa438, 0x5fb4, - 0xa438, 0x8280, 0xa438, 0xd700, 0xa438, 0x6065, 0xa438, 0xd125, - 0xa438, 0xf002, 0xa438, 0xd12b, 0xa438, 0xd040, 0xa438, 0x1800, - 0xa438, 0x077f, 0xa438, 0x0cf0, 0xa438, 0x0c50, 0xa438, 0xd104, - 0xa438, 0xd040, 0xa438, 0x1000, 0xa438, 0x0aa8, 0xa438, 0xd700, - 0xa438, 0x5fb4, 0xa438, 0x1800, 0xa438, 0x0a2e, 0xa438, 0xcb9b, - 0xa438, 0xd110, 0xa438, 0xd040, 0xa438, 0x1000, 0xa438, 0x0b7b, - 0xa438, 0x1000, 0xa438, 0x09df, 0xa438, 0xd700, 0xa438, 0x5fb4, - 0xa438, 0x1800, 0xa438, 0x081b, 0xa438, 0x1000, 0xa438, 0x09df, - 0xa438, 0xd704, 0xa438, 0x7fb8, 0xa438, 0xa718, 0xa438, 0x1800, - 0xa438, 0x074e, 0xa436, 0xA10E, 0xa438, 0xffff, 0xa436, 0xA10C, - 0xa438, 0xffff, 0xa436, 0xA10A, 0xa438, 0xffff, 0xa436, 0xA108, - 0xa438, 0xffff, 0xa436, 0xA106, 0xa438, 0x074d, 0xa436, 0xA104, - 0xa438, 0x0818, 0xa436, 0xA102, 0xa438, 0x0a2c, 0xa436, 0xA100, - 0xa438, 0x077e, 0xa436, 0xA110, 0xa438, 0x000f, 0xa436, 0xb87c, - 0xa438, 0x8625, 0xa436, 0xb87e, 0xa438, 0xaf86, 0xa438, 0x3daf, - 0xa438, 0x8689, 0xa438, 0xaf88, 0xa438, 0x69af, 0xa438, 0x8887, - 0xa438, 0xaf88, 0xa438, 0x9caf, 0xa438, 0x889c, 0xa438, 0xaf88, - 0xa438, 0x9caf, 0xa438, 0x889c, 0xa438, 0xbf86, 0xa438, 0x49d7, - 0xa438, 0x0040, 0xa438, 0x0277, 0xa438, 0x7daf, 0xa438, 0x2727, - 0xa438, 0x0000, 0xa438, 0x7205, 0xa438, 0x0000, 0xa438, 0x7208, - 0xa438, 0x0000, 0xa438, 0x71f3, 0xa438, 0x0000, 0xa438, 0x71f6, - 0xa438, 0x0000, 0xa438, 0x7229, 0xa438, 0x0000, 0xa438, 0x722c, - 0xa438, 0x0000, 0xa438, 0x7217, 0xa438, 0x0000, 0xa438, 0x721a, - 0xa438, 0x0000, 0xa438, 0x721d, 0xa438, 0x0000, 0xa438, 0x7211, - 0xa438, 0x0000, 0xa438, 0x7220, 0xa438, 0x0000, 0xa438, 0x7214, - 0xa438, 0x0000, 0xa438, 0x722f, 0xa438, 0x0000, 0xa438, 0x7223, - 0xa438, 0x0000, 0xa438, 0x7232, 0xa438, 0x0000, 0xa438, 0x7226, - 0xa438, 0xf8f9, 0xa438, 0xfae0, 0xa438, 0x85b3, 0xa438, 0x3802, - 0xa438, 0xad27, 0xa438, 0x02ae, 0xa438, 0x03af, 0xa438, 0x8830, - 0xa438, 0x1f66, 0xa438, 0xef65, 0xa438, 0xbfc2, 0xa438, 0x1f1a, - 0xa438, 0x96f7, 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00da, - 0xa438, 0xf605, 0xa438, 0xbfc2, 0xa438, 0x2f1a, 0xa438, 0x96f7, - 0xa438, 0x05ee, 0xa438, 0xffd2, 0xa438, 0x00db, 0xa438, 0xf605, - 0xa438, 0xef02, 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, - 0xa438, 0x4202, 0xa438, 0x6e7d, 0xa438, 0xef02, 0xa438, 0x1b03, - 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4502, - 0xa438, 0x6e7d, 0xa438, 0xef02, 0xa438, 0x1a03, 0xa438, 0x1f11, - 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4802, 0xa438, 0x6e7d, - 0xa438, 0xbfc2, 0xa438, 0x3f1a, 0xa438, 0x96f7, 0xa438, 0x05ee, - 0xa438, 0xffd2, 0xa438, 0x00da, 0xa438, 0xf605, 0xa438, 0xbfc2, - 0xa438, 0x4f1a, 0xa438, 0x96f7, 0xa438, 0x05ee, 0xa438, 0xffd2, - 0xa438, 0x00db, 0xa438, 0xf605, 0xa438, 0xef02, 0xa438, 0x1f11, - 0xa438, 0x0d42, 0xa438, 0xbf88, 0xa438, 0x4b02, 0xa438, 0x6e7d, - 0xa438, 0xef02, 0xa438, 0x1b03, 0xa438, 0x1f11, 0xa438, 0x0d42, - 0xa438, 0xbf88, 0xa438, 0x4e02, 0xa438, 0x6e7d, 0xa438, 0xef02, - 0xa438, 0x1a03, 0xa438, 0x1f11, 0xa438, 0x0d42, 0xa438, 0xbf88, - 0xa438, 0x5102, 0xa438, 0x6e7d, 0xa438, 0xef56, 0xa438, 0xd020, - 0xa438, 0x1f11, 0xa438, 0xbf88, 0xa438, 0x5402, 0xa438, 0x6e7d, - 0xa438, 0xbf88, 0xa438, 0x5702, 0xa438, 0x6e7d, 0xa438, 0xbf88, - 0xa438, 0x5a02, 0xa438, 0x6e7d, 0xa438, 0xe185, 0xa438, 0xa0ef, - 0xa438, 0x0348, 0xa438, 0x0a28, 0xa438, 0x05ef, 0xa438, 0x201b, - 0xa438, 0x01ad, 0xa438, 0x2735, 0xa438, 0x1f44, 0xa438, 0xe085, - 0xa438, 0x88e1, 0xa438, 0x8589, 0xa438, 0xbf88, 0xa438, 0x5d02, - 0xa438, 0x6e7d, 0xa438, 0xe085, 0xa438, 0x8ee1, 0xa438, 0x858f, - 0xa438, 0xbf88, 0xa438, 0x6002, 0xa438, 0x6e7d, 0xa438, 0xe085, - 0xa438, 0x94e1, 0xa438, 0x8595, 0xa438, 0xbf88, 0xa438, 0x6302, - 0xa438, 0x6e7d, 0xa438, 0xe085, 0xa438, 0x9ae1, 0xa438, 0x859b, - 0xa438, 0xbf88, 0xa438, 0x6602, 0xa438, 0x6e7d, 0xa438, 0xaf88, - 0xa438, 0x3cbf, 0xa438, 0x883f, 0xa438, 0x026e, 0xa438, 0x9cad, - 0xa438, 0x2835, 0xa438, 0x1f44, 0xa438, 0xe08f, 0xa438, 0xf8e1, - 0xa438, 0x8ff9, 0xa438, 0xbf88, 0xa438, 0x5d02, 0xa438, 0x6e7d, - 0xa438, 0xe08f, 0xa438, 0xfae1, 0xa438, 0x8ffb, 0xa438, 0xbf88, - 0xa438, 0x6002, 0xa438, 0x6e7d, 0xa438, 0xe08f, 0xa438, 0xfce1, - 0xa438, 0x8ffd, 0xa438, 0xbf88, 0xa438, 0x6302, 0xa438, 0x6e7d, - 0xa438, 0xe08f, 0xa438, 0xfee1, 0xa438, 0x8fff, 0xa438, 0xbf88, - 0xa438, 0x6602, 0xa438, 0x6e7d, 0xa438, 0xaf88, 0xa438, 0x3ce1, - 0xa438, 0x85a1, 0xa438, 0x1b21, 0xa438, 0xad37, 0xa438, 0x341f, - 0xa438, 0x44e0, 0xa438, 0x858a, 0xa438, 0xe185, 0xa438, 0x8bbf, - 0xa438, 0x885d, 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x8590, - 0xa438, 0xe185, 0xa438, 0x91bf, 0xa438, 0x8860, 0xa438, 0x026e, - 0xa438, 0x7de0, 0xa438, 0x8596, 0xa438, 0xe185, 0xa438, 0x97bf, - 0xa438, 0x8863, 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x859c, - 0xa438, 0xe185, 0xa438, 0x9dbf, 0xa438, 0x8866, 0xa438, 0x026e, - 0xa438, 0x7dae, 0xa438, 0x401f, 0xa438, 0x44e0, 0xa438, 0x858c, - 0xa438, 0xe185, 0xa438, 0x8dbf, 0xa438, 0x885d, 0xa438, 0x026e, - 0xa438, 0x7de0, 0xa438, 0x8592, 0xa438, 0xe185, 0xa438, 0x93bf, - 0xa438, 0x8860, 0xa438, 0x026e, 0xa438, 0x7de0, 0xa438, 0x8598, - 0xa438, 0xe185, 0xa438, 0x99bf, 0xa438, 0x8863, 0xa438, 0x026e, - 0xa438, 0x7de0, 0xa438, 0x859e, 0xa438, 0xe185, 0xa438, 0x9fbf, - 0xa438, 0x8866, 0xa438, 0x026e, 0xa438, 0x7dae, 0xa438, 0x0ce1, - 0xa438, 0x85b3, 0xa438, 0x3904, 0xa438, 0xac2f, 0xa438, 0x04ee, - 0xa438, 0x85b3, 0xa438, 0x00af, 0xa438, 0x39d9, 0xa438, 0x22ac, - 0xa438, 0xeaf0, 0xa438, 0xacf6, 0xa438, 0xf0ac, 0xa438, 0xfaf0, - 0xa438, 0xacf8, 0xa438, 0xf0ac, 0xa438, 0xfcf0, 0xa438, 0xad00, - 0xa438, 0xf0ac, 0xa438, 0xfef0, 0xa438, 0xacf0, 0xa438, 0xf0ac, - 0xa438, 0xf4f0, 0xa438, 0xacf2, 0xa438, 0xf0ac, 0xa438, 0xb0f0, - 0xa438, 0xacae, 0xa438, 0xf0ac, 0xa438, 0xacf0, 0xa438, 0xacaa, - 0xa438, 0xa100, 0xa438, 0x0ce1, 0xa438, 0x8ff7, 0xa438, 0xbf88, - 0xa438, 0x8402, 0xa438, 0x6e7d, 0xa438, 0xaf26, 0xa438, 0xe9e1, - 0xa438, 0x8ff6, 0xa438, 0xbf88, 0xa438, 0x8402, 0xa438, 0x6e7d, - 0xa438, 0xaf26, 0xa438, 0xf520, 0xa438, 0xac86, 0xa438, 0xbf88, - 0xa438, 0x3f02, 0xa438, 0x6e9c, 0xa438, 0xad28, 0xa438, 0x03af, - 0xa438, 0x3324, 0xa438, 0xad38, 0xa438, 0x03af, 0xa438, 0x32e6, - 0xa438, 0xaf32, 0xa438, 0xfb00, 0xa436, 0xb87c, 0xa438, 0x8ff6, - 0xa436, 0xb87e, 0xa438, 0x0705, 0xa436, 0xb87c, 0xa438, 0x8ff8, - 0xa436, 0xb87e, 0xa438, 0x19cc, 0xa436, 0xb87c, 0xa438, 0x8ffa, - 0xa436, 0xb87e, 0xa438, 0x28e3, 0xa436, 0xb87c, 0xa438, 0x8ffc, - 0xa436, 0xb87e, 0xa438, 0x1047, 0xa436, 0xb87c, 0xa438, 0x8ffe, - 0xa436, 0xb87e, 0xa438, 0x0a45, 0xa436, 0xb85e, 0xa438, 0x271E, - 0xa436, 0xb860, 0xa438, 0x3846, 0xa436, 0xb862, 0xa438, 0x26E6, - 0xa436, 0xb864, 0xa438, 0x32E3, 0xa436, 0xb886, 0xa438, 0xffff, - 0xa436, 0xb888, 0xa438, 0xffff, 0xa436, 0xb88a, 0xa438, 0xffff, - 0xa436, 0xb88c, 0xa438, 0xffff, 0xa436, 0xb838, 0xa438, 0x000f, - 0xb820, 0x0010, 0xa436, 0x846e, 0xa438, 0xaf84, 0xa438, 0x86af, - 0xa438, 0x8690, 0xa438, 0xaf86, 0xa438, 0xa4af, 0xa438, 0x86a4, - 0xa438, 0xaf86, 0xa438, 0xa4af, 0xa438, 0x86a4, 0xa438, 0xaf86, - 0xa438, 0xa4af, 0xa438, 0x86a4, 0xa438, 0xee82, 0xa438, 0x5f00, - 0xa438, 0x0284, 0xa438, 0x90af, 0xa438, 0x0441, 0xa438, 0xf8e0, - 0xa438, 0x8ff3, 0xa438, 0xa000, 0xa438, 0x0502, 0xa438, 0x84a4, - 0xa438, 0xae06, 0xa438, 0xa001, 0xa438, 0x0302, 0xa438, 0x84c8, - 0xa438, 0xfc04, 0xa438, 0xf8f9, 0xa438, 0xef59, 0xa438, 0xe080, - 0xa438, 0x15ad, 0xa438, 0x2702, 0xa438, 0xae03, 0xa438, 0xaf84, - 0xa438, 0xc3bf, 0xa438, 0x53ca, 0xa438, 0x0252, 0xa438, 0xc8ad, - 0xa438, 0x2807, 0xa438, 0x0285, 0xa438, 0x2cee, 0xa438, 0x8ff3, - 0xa438, 0x01ef, 0xa438, 0x95fd, 0xa438, 0xfc04, 0xa438, 0xf8f9, - 0xa438, 0xfaef, 0xa438, 0x69bf, 0xa438, 0x53ca, 0xa438, 0x0252, - 0xa438, 0xc8ac, 0xa438, 0x2822, 0xa438, 0xd480, 0xa438, 0x00bf, - 0xa438, 0x8684, 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x8687, - 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x868a, 0xa438, 0x0252, - 0xa438, 0xa9bf, 0xa438, 0x868d, 0xa438, 0x0252, 0xa438, 0xa9ee, - 0xa438, 0x8ff3, 0xa438, 0x00af, 0xa438, 0x8526, 0xa438, 0xe08f, - 0xa438, 0xf4e1, 0xa438, 0x8ff5, 0xa438, 0xe28f, 0xa438, 0xf6e3, - 0xa438, 0x8ff7, 0xa438, 0x1b45, 0xa438, 0xac27, 0xa438, 0x0eee, - 0xa438, 0x8ff4, 0xa438, 0x00ee, 0xa438, 0x8ff5, 0xa438, 0x0002, - 0xa438, 0x852c, 0xa438, 0xaf85, 0xa438, 0x26e0, 0xa438, 0x8ff4, - 0xa438, 0xe18f, 0xa438, 0xf52c, 0xa438, 0x0001, 0xa438, 0xe48f, - 0xa438, 0xf4e5, 0xa438, 0x8ff5, 0xa438, 0xef96, 0xa438, 0xfefd, - 0xa438, 0xfc04, 0xa438, 0xf8f9, 0xa438, 0xef59, 0xa438, 0xbf53, - 0xa438, 0x2202, 0xa438, 0x52c8, 0xa438, 0xa18b, 0xa438, 0x02ae, - 0xa438, 0x03af, 0xa438, 0x85da, 0xa438, 0xbf57, 0xa438, 0x7202, - 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xf8e5, 0xa438, 0x8ff9, - 0xa438, 0xbf57, 0xa438, 0x7502, 0xa438, 0x52c8, 0xa438, 0xe48f, - 0xa438, 0xfae5, 0xa438, 0x8ffb, 0xa438, 0xbf57, 0xa438, 0x7802, - 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfce5, 0xa438, 0x8ffd, - 0xa438, 0xbf57, 0xa438, 0x7b02, 0xa438, 0x52c8, 0xa438, 0xe48f, - 0xa438, 0xfee5, 0xa438, 0x8fff, 0xa438, 0xbf57, 0xa438, 0x6c02, - 0xa438, 0x52c8, 0xa438, 0xa102, 0xa438, 0x13ee, 0xa438, 0x8ffc, - 0xa438, 0x80ee, 0xa438, 0x8ffd, 0xa438, 0x00ee, 0xa438, 0x8ffe, - 0xa438, 0x80ee, 0xa438, 0x8fff, 0xa438, 0x00af, 0xa438, 0x8599, - 0xa438, 0xa101, 0xa438, 0x0cbf, 0xa438, 0x534c, 0xa438, 0x0252, - 0xa438, 0xc8a1, 0xa438, 0x0303, 0xa438, 0xaf85, 0xa438, 0x77bf, - 0xa438, 0x5322, 0xa438, 0x0252, 0xa438, 0xc8a1, 0xa438, 0x8b02, - 0xa438, 0xae03, 0xa438, 0xaf86, 0xa438, 0x64e0, 0xa438, 0x8ff8, - 0xa438, 0xe18f, 0xa438, 0xf9bf, 0xa438, 0x8684, 0xa438, 0x0252, - 0xa438, 0xa9e0, 0xa438, 0x8ffa, 0xa438, 0xe18f, 0xa438, 0xfbbf, - 0xa438, 0x8687, 0xa438, 0x0252, 0xa438, 0xa9e0, 0xa438, 0x8ffc, - 0xa438, 0xe18f, 0xa438, 0xfdbf, 0xa438, 0x868a, 0xa438, 0x0252, - 0xa438, 0xa9e0, 0xa438, 0x8ffe, 0xa438, 0xe18f, 0xa438, 0xffbf, - 0xa438, 0x868d, 0xa438, 0x0252, 0xa438, 0xa9af, 0xa438, 0x867f, - 0xa438, 0xbf53, 0xa438, 0x2202, 0xa438, 0x52c8, 0xa438, 0xa144, - 0xa438, 0x3cbf, 0xa438, 0x547b, 0xa438, 0x0252, 0xa438, 0xc8e4, - 0xa438, 0x8ff8, 0xa438, 0xe58f, 0xa438, 0xf9bf, 0xa438, 0x547e, - 0xa438, 0x0252, 0xa438, 0xc8e4, 0xa438, 0x8ffa, 0xa438, 0xe58f, - 0xa438, 0xfbbf, 0xa438, 0x5481, 0xa438, 0x0252, 0xa438, 0xc8e4, - 0xa438, 0x8ffc, 0xa438, 0xe58f, 0xa438, 0xfdbf, 0xa438, 0x5484, - 0xa438, 0x0252, 0xa438, 0xc8e4, 0xa438, 0x8ffe, 0xa438, 0xe58f, - 0xa438, 0xffbf, 0xa438, 0x5322, 0xa438, 0x0252, 0xa438, 0xc8a1, - 0xa438, 0x4448, 0xa438, 0xaf85, 0xa438, 0xa7bf, 0xa438, 0x5322, - 0xa438, 0x0252, 0xa438, 0xc8a1, 0xa438, 0x313c, 0xa438, 0xbf54, - 0xa438, 0x7b02, 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xf8e5, - 0xa438, 0x8ff9, 0xa438, 0xbf54, 0xa438, 0x7e02, 0xa438, 0x52c8, - 0xa438, 0xe48f, 0xa438, 0xfae5, 0xa438, 0x8ffb, 0xa438, 0xbf54, - 0xa438, 0x8102, 0xa438, 0x52c8, 0xa438, 0xe48f, 0xa438, 0xfce5, - 0xa438, 0x8ffd, 0xa438, 0xbf54, 0xa438, 0x8402, 0xa438, 0x52c8, - 0xa438, 0xe48f, 0xa438, 0xfee5, 0xa438, 0x8fff, 0xa438, 0xbf53, - 0xa438, 0x2202, 0xa438, 0x52c8, 0xa438, 0xa131, 0xa438, 0x03af, - 0xa438, 0x85a7, 0xa438, 0xd480, 0xa438, 0x00bf, 0xa438, 0x8684, - 0xa438, 0x0252, 0xa438, 0xa9bf, 0xa438, 0x8687, 0xa438, 0x0252, - 0xa438, 0xa9bf, 0xa438, 0x868a, 0xa438, 0x0252, 0xa438, 0xa9bf, - 0xa438, 0x868d, 0xa438, 0x0252, 0xa438, 0xa9ef, 0xa438, 0x95fd, - 0xa438, 0xfc04, 0xa438, 0xf0d1, 0xa438, 0x2af0, 0xa438, 0xd12c, - 0xa438, 0xf0d1, 0xa438, 0x44f0, 0xa438, 0xd146, 0xa438, 0xbf86, - 0xa438, 0xa102, 0xa438, 0x52c8, 0xa438, 0xbf86, 0xa438, 0xa102, - 0xa438, 0x52c8, 0xa438, 0xd101, 0xa438, 0xaf06, 0xa438, 0xa570, - 0xa438, 0xce42, 0xa436, 0xb818, 0xa438, 0x043d, 0xa436, 0xb81a, - 0xa438, 0x06a3, 0xa436, 0xb81c, 0xa438, 0xffff, 0xa436, 0xb81e, - 0xa438, 0xffff, 0xa436, 0xb850, 0xa438, 0xffff, 0xa436, 0xb852, - 0xa438, 0xffff, 0xa436, 0xb878, 0xa438, 0xffff, 0xa436, 0xb884, - 0xa438, 0xffff, 0xa436, 0xb832, 0xa438, 0x0003, 0xa436, 0x0000, - 0xa438, 0x0000, 0xa436, 0xB82E, 0xa438, 0x0000, 0xa436, 0x8024, - 0xa438, 0x0000, 0xa436, 0x801E, 0xa438, 0x0021, 0xb820, 0x0000, - 0xFFFF, 0xFFFF -}; - -static void -rtl8125_real_set_phy_mcu_8125b_1(struct net_device *dev) -{ - rtl8125_set_phy_mcu_ram_code(dev, - phy_mcu_ram_code_8125b_1, - ARRAY_SIZE(phy_mcu_ram_code_8125b_1) - ); -} - -static void -rtl8125_set_phy_mcu_8125b_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_set_phy_mcu_patch_request(tp); - - rtl8125_real_set_phy_mcu_8125b_1(dev); - - rtl8125_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8125_real_set_phy_mcu_8125b_2(struct net_device *dev) -{ - rtl8125_set_phy_mcu_ram_code(dev, - phy_mcu_ram_code_8125b_2, - ARRAY_SIZE(phy_mcu_ram_code_8125b_2) - ); -} - -static void -rtl8125_set_phy_mcu_8125b_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_set_phy_mcu_patch_request(tp); - - rtl8125_real_set_phy_mcu_8125b_2(dev); - - rtl8125_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8125_init_hw_phy_mcu(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u8 require_disable_phy_disable_mode = FALSE; - - if (tp->NotWrRamCodeToMicroP == TRUE) return; - if (rtl8125_check_hw_phy_mcu_code_ver(dev)) return; - - if (HW_SUPPORT_CHECK_PHY_DISABLE_MODE(tp) && rtl8125_is_in_phy_disable_mode(dev)) - require_disable_phy_disable_mode = TRUE; - - if (require_disable_phy_disable_mode) - rtl8125_disable_phy_disable_mode(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - rtl8125_set_phy_mcu_8125a_1(dev); - break; - case CFG_METHOD_3: - case CFG_METHOD_6: - rtl8125_set_phy_mcu_8125a_2(dev); - break; - case CFG_METHOD_4: - rtl8125_set_phy_mcu_8125b_1(dev); - break; - case CFG_METHOD_5: - case CFG_METHOD_7: - rtl8125_set_phy_mcu_8125b_2(dev); - break; - } - - if (require_disable_phy_disable_mode) - rtl8125_enable_phy_disable_mode(dev); - - rtl8125_write_hw_phy_mcu_code_ver(dev); - - rtl8125_mdio_write(tp,0x1F, 0x0000); - - tp->HwHasWrRamCodeToMicroP = TRUE; -} -#endif - -static void -rtl8125_enable_phy_aldps(struct rtl8125_private *tp) -{ - //enable aldps - //GPHY OCP 0xA430 bit[2] = 0x1 (en_aldps) - SetEthPhyOcpBit(tp, 0xA430, BIT_2); -} - -static void -rtl8125_hw_phy_config_8125a_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - ClearAndSetEthPhyOcpBit(tp, - 0xAD40, - 0x03FF, - 0x84 - ); - - SetEthPhyOcpBit(tp, 0xAD4E, BIT_4); - ClearAndSetEthPhyOcpBit(tp, - 0xAD16, - 0x03FF, - 0x0006 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD32, - 0x003F, - 0x0006 - ); - ClearEthPhyOcpBit(tp, 0xAC08, BIT_12); - ClearEthPhyOcpBit(tp, 0xAC08, BIT_8); - ClearAndSetEthPhyOcpBit(tp, - 0xAC8A, - BIT_15|BIT_14|BIT_13|BIT_12, - BIT_14|BIT_13|BIT_12 - ); - SetEthPhyOcpBit(tp, 0xAD18, BIT_10); - SetEthPhyOcpBit(tp, 0xAD1A, 0x3FF); - SetEthPhyOcpBit(tp, 0xAD1C, 0x3FF); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EA); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xC400 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EB); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0x0700, - 0x0300 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80F8); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x1C00 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80F1); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x3000 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80FE); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xA500 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8102); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x5000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8105); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x3300 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8100); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x7000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8104); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xF000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8106); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x6500 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DC); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xED00 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DF); - SetEthPhyOcpBit(tp, 0xA438, BIT_8); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80E1); - ClearEthPhyOcpBit(tp, 0xA438, BIT_8); - - ClearAndSetEthPhyOcpBit(tp, - 0xBF06, - 0x003F, - 0x38 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x819F); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xD0B6); - - mdio_direct_write_phy_ocp(tp, 0xBC34, 0x5555); - ClearAndSetEthPhyOcpBit(tp, - 0xBF0A, - BIT_11|BIT_10|BIT_9, - BIT_11|BIT_9 - ); - - ClearEthPhyOcpBit(tp, 0xA5C0, BIT_10); - - SetEthPhyOcpBit(tp, 0xA442, BIT_11); - - //enable aldps - //GPHY OCP 0xA430 bit[2] = 0x1 (en_aldps) - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8125_enable_phy_aldps(tp); - } - } -} - -static void -rtl8125_hw_phy_config_8125a_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - SetEthPhyOcpBit(tp, 0xAD4E, BIT_4); - ClearAndSetEthPhyOcpBit(tp, - 0xAD16, - 0x03FF, - 0x03FF - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD32, - 0x003F, - 0x0006 - ); - ClearEthPhyOcpBit(tp, 0xAC08, BIT_12); - ClearEthPhyOcpBit(tp, 0xAC08, BIT_8); - ClearAndSetEthPhyOcpBit(tp, - 0xACC0, - BIT_1|BIT_0, - BIT_1 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD40, - BIT_7|BIT_6|BIT_5, - BIT_6 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD40, - BIT_2|BIT_1|BIT_0, - BIT_2 - ); - ClearEthPhyOcpBit(tp, 0xAC14, BIT_7); - ClearEthPhyOcpBit(tp, 0xAC80, BIT_9|BIT_8); - ClearAndSetEthPhyOcpBit(tp, - 0xAC5E, - BIT_2|BIT_1|BIT_0, - BIT_1 - ); - mdio_direct_write_phy_ocp(tp, 0xAD4C, 0x00A8); - mdio_direct_write_phy_ocp(tp, 0xAC5C, 0x01FF); - ClearAndSetEthPhyOcpBit(tp, - 0xAC8A, - BIT_7|BIT_6|BIT_5|BIT_4, - BIT_5|BIT_4 - ); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8157); - ClearAndSetEthPhyOcpBit(tp, - 0xB87E, - 0xFF00, - 0x0500 - ); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8159); - ClearAndSetEthPhyOcpBit(tp, - 0xB87E, - 0xFF00, - 0x0700 - ); - - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80A2); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0153); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x809C); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0153); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x81B3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0043); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00A7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00D6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00EC); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00F6); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FB); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FD); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00FF); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x00BB); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0058); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0029); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0013); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0009); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0004); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0002); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0000); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8257); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x020F); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80EA); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x7843); - - - rtl8125_set_phy_mcu_patch_request(tp); - - ClearEthPhyOcpBit(tp, 0xB896, BIT_0); - ClearEthPhyOcpBit(tp, 0xB892, 0xFF00); - - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC091); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E12); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC092); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1214); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC094); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1516); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC096); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x171B); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC098); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1B1C); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09A); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1F1F); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09C); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2021); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC09E); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2224); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A0); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A2); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC0A4); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x2424); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC018); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0AF2); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01A); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0D4A); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01C); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0F26); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC01E); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x118D); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC020); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x14F3); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC022); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x175A); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC024); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x19C0); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC026); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1C26); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC089); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6050); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08A); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x5F6E); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08C); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E6E); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC08E); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E6E); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC090); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x6E12); - - SetEthPhyOcpBit(tp, 0xB896, BIT_0); - - rtl8125_clear_phy_mcu_patch_request(tp); - - - SetEthPhyOcpBit(tp, 0xD068, BIT_13); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x81A2); - SetEthPhyOcpBit(tp, 0xA438, BIT_8); - ClearAndSetEthPhyOcpBit(tp, - 0xB54C, - 0xFF00, - 0xDB00); - - - ClearEthPhyOcpBit(tp, 0xA454, BIT_0); - - - SetEthPhyOcpBit(tp, 0xA5D4, BIT_5); - ClearEthPhyOcpBit(tp, 0xAD4E, BIT_4); - ClearEthPhyOcpBit(tp, 0xA86A, BIT_0); - - - SetEthPhyOcpBit(tp, 0xA442, BIT_11); - - - if (tp->RequirePhyMdiSwapPatch) { - u16 adccal_offset_p0; - u16 adccal_offset_p1; - u16 adccal_offset_p2; - u16 adccal_offset_p3; - u16 rg_lpf_cap_xg_p0; - u16 rg_lpf_cap_xg_p1; - u16 rg_lpf_cap_xg_p2; - u16 rg_lpf_cap_xg_p3; - u16 rg_lpf_cap_p0; - u16 rg_lpf_cap_p1; - u16 rg_lpf_cap_p2; - u16 rg_lpf_cap_p3; - - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0007, - 0x0001 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0000 - ); - adccal_offset_p0 = mdio_direct_read_phy_ocp(tp, 0xD06A); - adccal_offset_p0 &= 0x07FF; - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0008 - ); - adccal_offset_p1 = mdio_direct_read_phy_ocp(tp, 0xD06A); - adccal_offset_p1 &= 0x07FF; - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0010 - ); - adccal_offset_p2 = mdio_direct_read_phy_ocp(tp, 0xD06A); - adccal_offset_p2 &= 0x07FF; - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0018 - ); - adccal_offset_p3 = mdio_direct_read_phy_ocp(tp, 0xD06A); - adccal_offset_p3 &= 0x07FF; - - - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0000 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD06A, - 0x07FF, - adccal_offset_p3 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0008 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD06A, - 0x07FF, - adccal_offset_p2 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0010 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD06A, - 0x07FF, - adccal_offset_p1 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD068, - 0x0018, - 0x0018 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xD06A, - 0x07FF, - adccal_offset_p0 - ); - - - rg_lpf_cap_xg_p0 = mdio_direct_read_phy_ocp(tp, 0xBD5A); - rg_lpf_cap_xg_p0 &= 0x001F; - rg_lpf_cap_xg_p1 = mdio_direct_read_phy_ocp(tp, 0xBD5A); - rg_lpf_cap_xg_p1 &= 0x1F00; - rg_lpf_cap_xg_p2 = mdio_direct_read_phy_ocp(tp, 0xBD5C); - rg_lpf_cap_xg_p2 &= 0x001F; - rg_lpf_cap_xg_p3 = mdio_direct_read_phy_ocp(tp, 0xBD5C); - rg_lpf_cap_xg_p3 &= 0x1F00; - rg_lpf_cap_p0 = mdio_direct_read_phy_ocp(tp, 0xBC18); - rg_lpf_cap_p0 &= 0x001F; - rg_lpf_cap_p1 = mdio_direct_read_phy_ocp(tp, 0xBC18); - rg_lpf_cap_p1 &= 0x1F00; - rg_lpf_cap_p2 = mdio_direct_read_phy_ocp(tp, 0xBC1A); - rg_lpf_cap_p2 &= 0x001F; - rg_lpf_cap_p3 = mdio_direct_read_phy_ocp(tp, 0xBC1A); - rg_lpf_cap_p3 &= 0x1F00; - - - ClearAndSetEthPhyOcpBit(tp, - 0xBD5A, - 0x001F, - rg_lpf_cap_xg_p3 >> 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBD5A, - 0x1F00, - rg_lpf_cap_xg_p2 << 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBD5C, - 0x001F, - rg_lpf_cap_xg_p1 >> 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBD5C, - 0x1F00, - rg_lpf_cap_xg_p0 << 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBC18, - 0x001F, - rg_lpf_cap_p3 >> 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBC18, - 0x1F00, - rg_lpf_cap_p2 << 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBC1A, - 0x001F, - rg_lpf_cap_p1 >> 8 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xBC1A, - 0x1F00, - rg_lpf_cap_p0 << 8 - ); - } - - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8125_enable_phy_aldps(tp); - } - } -} - -static void -rtl8125_hw_phy_config_8125b_1(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - SetEthPhyOcpBit(tp, 0xA442, BIT_11); - - - SetEthPhyOcpBit(tp, 0xBC08, (BIT_3 | BIT_2)); - - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FFF); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x0400 - ); - } - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8560); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8562); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8564); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x19CC); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8566); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8568); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x856A); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x147D); - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FFE); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0907); - } - ClearAndSetEthPhyOcpBit(tp, - 0xACDA, - 0xFF00, - 0xFF00 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xACDE, - 0xF000, - 0xF000 - ); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80D6); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F2); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F4); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x6077); - mdio_direct_write_phy_ocp(tp, 0xB506, 0x01E7); - mdio_direct_write_phy_ocp(tp, 0xAC8C, 0x0FFC); - mdio_direct_write_phy_ocp(tp, 0xAC46, 0xB7B4); - mdio_direct_write_phy_ocp(tp, 0xAC50, 0x0FBC); - mdio_direct_write_phy_ocp(tp, 0xAC3C, 0x9240); - mdio_direct_write_phy_ocp(tp, 0xAC4E, 0x0DB4); - mdio_direct_write_phy_ocp(tp, 0xACC6, 0x0707); - mdio_direct_write_phy_ocp(tp, 0xACC8, 0xA0D3); - mdio_direct_write_phy_ocp(tp, 0xAD08, 0x0007); - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8013); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0700); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FB9); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x2801); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBA); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0100); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBC); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x1900); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FBE); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xE100); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC0); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0800); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC2); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xE500); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC4); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0F00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC6); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF100); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FC8); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0400); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCa); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF300); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCc); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFD00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FCe); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFF00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD0); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFB00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD2); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0100); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD4); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF400); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD6); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFF00); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8FD8); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xF600); - - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x813D); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x390E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x814F); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x790E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80B0); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0F31); - SetEthPhyOcpBit(tp, 0xBF4C, BIT_1); - SetEthPhyOcpBit(tp, 0xBCCA, (BIT_9 | BIT_8)); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8141); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x320E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8153); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x720E); - ClearEthPhyOcpBit(tp, 0xA432, BIT_6); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8529); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x050E); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x816C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xC4A0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8170); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xC4A0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8174); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x04A0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8178); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x04A0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x817C); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0719); - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FF4); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0400); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8FF1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0404); - } - mdio_direct_write_phy_ocp(tp, 0xBF4A, 0x001B); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8033); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8037); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x803B); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0xFC32); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x803F); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8043); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8047); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x7C13); - - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8145); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x370E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8157); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x770E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8169); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x0D0A); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x817B); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x1D0A); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8217); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x5000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x821A); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x5000 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DA); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0403); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DC); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x1000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x0384); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2007); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80BA); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x6C00 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80B5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xF009); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80BD); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x9F00 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80C7); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xf083); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DD); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x03f0); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80DF); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x1000 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80CB); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x2007); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80CE); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x6C00 - ); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80C9); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x8009); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80D1); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0x8000 - ); - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A3); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x200A); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A5); - mdio_direct_write_phy_ocp(tp, 0xA438, 0xF0AD); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x809F); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x6073); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A1); - mdio_direct_write_phy_ocp(tp, 0xA438, 0x000B); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x80A9); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - 0xFF00, - 0xC000 - ); - - rtl8125_set_phy_mcu_patch_request(tp); - - ClearEthPhyOcpBit(tp, 0xB896, BIT_0); - ClearEthPhyOcpBit(tp, 0xB892, 0xFF00); - - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC23E); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0000); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC240); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0103); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC242); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0507); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC244); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x090B); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC246); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x0C0E); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC248); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1012); - mdio_direct_write_phy_ocp(tp, 0xB88E, 0xC24A); - mdio_direct_write_phy_ocp(tp, 0xB890, 0x1416); - - SetEthPhyOcpBit(tp, 0xB896, BIT_0); - - rtl8125_clear_phy_mcu_patch_request(tp); - - - SetEthPhyOcpBit(tp, 0xA86A, BIT_0); - SetEthPhyOcpBit(tp, 0xA6F0, BIT_0); - - - mdio_direct_write_phy_ocp(tp, 0xBFA0, 0xD70D); - mdio_direct_write_phy_ocp(tp, 0xBFA2, 0x4100); - mdio_direct_write_phy_ocp(tp, 0xBFA4, 0xE868); - mdio_direct_write_phy_ocp(tp, 0xBFA6, 0xDC59); - mdio_direct_write_phy_ocp(tp, 0xB54C, 0x3C18); - ClearEthPhyOcpBit(tp, 0xBFA4, BIT_5); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x817D); - SetEthPhyOcpBit(tp, 0xA438, BIT_12); - - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8125_enable_phy_aldps(tp); - } - } -} - -static void -rtl8125_hw_phy_config_8125b_2(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - SetEthPhyOcpBit(tp, 0xA442, BIT_11); - - - ClearAndSetEthPhyOcpBit(tp, - 0xAC46, - 0x00F0, - 0x0090 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xAD30, - 0x0003, - 0x0001 - ); - - - RTL_W16(tp, EEE_TXIDLE_TIMER_8125, tp->eee.tx_lpi_timer); - - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x80F5); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x760E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8107); - mdio_direct_write_phy_ocp(tp, 0xB87E, 0x360E); - mdio_direct_write_phy_ocp(tp, 0xB87C, 0x8551); - ClearAndSetEthPhyOcpBit(tp, - 0xB87E, - BIT_15 | BIT_14 | BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_9 | BIT_8, - BIT_11 - ); - - ClearAndSetEthPhyOcpBit(tp, - 0xbf00, - 0xE000, - 0xA000 - ); - ClearAndSetEthPhyOcpBit(tp, - 0xbf46, - 0x0F00, - 0x0300 - ); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8044); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x804A); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8050); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8056); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x805C); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8062); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8068); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x806E); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x8074); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - mdio_direct_write_phy_ocp(tp, 0xa436, 0x807A); - mdio_direct_write_phy_ocp(tp, 0xa438, 0x2417); - - - SetEthPhyOcpBit(tp, 0xA4CA, BIT_6); - - - ClearAndSetEthPhyOcpBit(tp, - 0xBF84, - BIT_15 | BIT_14 | BIT_13, - BIT_15 | BIT_13 - ); - - - mdio_direct_write_phy_ocp(tp, 0xA436, 0x8170); - ClearAndSetEthPhyOcpBit(tp, - 0xA438, - BIT_13 | BIT_10 | BIT_9 | BIT_8, - BIT_15 | BIT_14 | BIT_12 | BIT_11 - ); - - /* - mdio_direct_write_phy_ocp(tp, 0xBFA0, 0xD70D); - mdio_direct_write_phy_ocp(tp, 0xBFA2, 0x4100); - mdio_direct_write_phy_ocp(tp, 0xBFA4, 0xE868); - mdio_direct_write_phy_ocp(tp, 0xBFA6, 0xDC59); - mdio_direct_write_phy_ocp(tp, 0xB54C, 0x3C18); - ClearEthPhyOcpBit(tp, 0xBFA4, BIT_5); - mdio_direct_write_phy_ocp(tp, 0xA436, 0x817D); - SetEthPhyOcpBit(tp, 0xA438, BIT_12); - */ - - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8125_enable_phy_aldps(tp); - } - } -} - -static void -rtl8125_hw_phy_config(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (tp->resume_not_chg_speed) return; - - tp->phy_reset_enable(dev); - - if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x06) return; - -#ifndef ENABLE_USE_FIRMWARE_FILE - if (!tp->rtl_fw) { - rtl8125_set_hw_phy_before_init_phy_mcu(dev); - - rtl8125_init_hw_phy_mcu(dev); - } -#endif - - switch (tp->mcfg) { - case CFG_METHOD_2: - rtl8125_hw_phy_config_8125a_1(dev); - break; - case CFG_METHOD_3: - case CFG_METHOD_6: - rtl8125_hw_phy_config_8125a_2(dev); - break; - case CFG_METHOD_4: - rtl8125_hw_phy_config_8125b_1(dev); - break; - case CFG_METHOD_5: - case CFG_METHOD_7: - rtl8125_hw_phy_config_8125b_2(dev); - break; - } - - //legacy force mode(Chap 22) - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - default: - rtl8125_mdio_write(tp, 0x1F, 0x0A5B); - rtl8125_clear_eth_phy_bit(tp, 0x12, BIT_15); - rtl8125_mdio_write(tp, 0x1F, 0x0000); - break; - } - - /*ocp phy power saving*/ - /* - if (aspm) { - if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_6) - rtl8125_enable_ocp_phy_power_saving(dev); - } - */ - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - if (tp->eee.eee_enabled) - rtl8125_enable_eee(tp); - else - rtl8125_disable_eee(tp); - } -} - -static void -rtl8125_up(struct net_device *dev) -{ - rtl8125_hw_init(dev); - rtl8125_hw_reset(dev); - rtl8125_powerup_pll(dev); - rtl8125_hw_ephy_config(dev); - rtl8125_hw_phy_config(dev); - rtl8125_hw_config(dev); -} - -/* -static inline void rtl8125_delete_esd_timer(struct net_device *dev, struct timer_list *timer) -{ - del_timer_sync(timer); -} - -static inline void rtl8125_request_esd_timer(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->esd_timer; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - setup_timer(timer, rtl8125_esd_timer, (unsigned long)dev); -#else - timer_setup(timer, rtl8125_esd_timer, 0); -#endif - mod_timer(timer, jiffies + RTL8125_ESD_TIMEOUT); -} -*/ - -/* -static inline void rtl8125_delete_link_timer(struct net_device *dev, struct timer_list *timer) -{ - del_timer_sync(timer); -} - -static inline void rtl8125_request_link_timer(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->link_timer; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - setup_timer(timer, rtl8125_link_timer, (unsigned long)dev); -#else - timer_setup(timer, rtl8125_link_timer, 0); -#endif - mod_timer(timer, jiffies + RTL8125_LINK_TIMEOUT); -} -*/ - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void -rtl8125_netpoll(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - for (i = 0; i < tp->irq_nvecs; i++) { - struct r8125_irq *irq = &tp->irq_tbl[i]; - struct r8125_napi *r8125napi = &tp->r8125napi[i]; - - disable_irq(irq->vector); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,12,0) - irq->handler(irq->vector, r8125napi); -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) - irq->handler(irq->vector, r8125napi, NULL); -#else - irq->handler(irq->vector, r8125napi); -#endif - - enable_irq(irq->vector); - } -} -#endif //CONFIG_NET_POLL_CONTROLLER - -static void -rtl8125_get_bios_setting(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - tp->bios_setting = RTL_R32(tp, TimeInt2); - break; - } -} - -static void -rtl8125_set_bios_setting(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - RTL_W32(tp, TimeInt2, tp->bios_setting); - break; - } -} - -static void -rtl8125_setup_mqs_reg(struct rtl8125_private *tp) -{ - int i; - - //tx - tp->tx_ring[0].tdsar_reg = TxDescStartAddrLow; - for (i = 1; i < R8125_MAX_TX_QUEUES; i++) { - tp->tx_ring[i].tdsar_reg = (u16)(TNPDS_Q1_LOW_8125 + (i - 1) * 8); - } - - for (i = 0; i < R8125_MAX_TX_QUEUES; i++) { - tp->tx_ring[i].hw_clo_ptr_reg = (u16)(HW_CLO_PTR0_8125 + i * 4); - tp->tx_ring[i].sw_tail_ptr_reg = (u16)(SW_TAIL_PTR0_8125 + i * 4); - } - - //rx - tp->rx_ring[0].rdsar_reg = RxDescAddrLow; - for (i = 1; i < R8125_MAX_RX_QUEUES; i++) { - tp->rx_ring[i].rdsar_reg = (u16)(RDSAR_Q1_LOW_8125 + (i - 1) * 8); - } - - tp->isr_reg[0] = ISR0_8125; - for (i = 1; i < R8125_MAX_QUEUES; i++) { - tp->isr_reg[i] = (u16)(ISR1_8125 + (i - 1) * 4); - } - - tp->imr_reg[0] = IMR0_8125; - for (i = 1; i < R8125_MAX_QUEUES; i++) { - tp->imr_reg[i] = (u16)(IMR1_8125 + (i - 1) * 4); - } -} - -static void -rtl8125_init_software_variable(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8125_get_bios_setting(dev); - -#ifdef ENABLE_LIB_SUPPORT - tp->ring_lib_enabled = 1; -#endif - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - //tp->HwSuppDashVer = 3; - break; - default: - tp->HwSuppDashVer = 0; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - tp->HwPkgDet = rtl8125_mac_ocp_read(tp, 0xDC00); - tp->HwPkgDet = (tp->HwPkgDet >> 3) & 0x07; - break; - } - - if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x06) - eee_enable = 0; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - tp->HwSuppNowIsOobVer = 1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - tp->HwPcieSNOffset = 0x16C; - break; - } - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8125_get_realwow_hw_version(dev); -#endif //ENABLE_REALWOW_SUPPORT - - if (HW_DASH_SUPPORT_DASH(tp) && rtl8125_check_dash(tp)) - tp->DASH = 1; - else - tp->DASH = 0; - - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_3(tp)) { - u64 CmacMemPhysAddress; - void __iomem *cmac_ioaddr = NULL; - - //map CMAC IO space - CmacMemPhysAddress = rtl8125_csi_other_fun_read(tp, 0, 0x18); - if (!(CmacMemPhysAddress & BIT_0)) { - if (CmacMemPhysAddress & BIT_2) - CmacMemPhysAddress |= (u64)rtl8125_csi_other_fun_read(tp, 0, 0x1C) << 32; - - CmacMemPhysAddress &= 0xFFFFFFF0; - /* ioremap MMIO region */ - cmac_ioaddr = ioremap(CmacMemPhysAddress, R8125_REGS_SIZE); - } - - if (cmac_ioaddr == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap CMAC MMIO, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - } - - if (cmac_ioaddr == NULL) { - tp->DASH = 0; - } else { - tp->mapped_cmac_ioaddr = cmac_ioaddr; - } - } - - eee_enable = 0; - } - - if (HW_DASH_SUPPORT_TYPE_3(tp)) - tp->cmac_ioaddr = tp->mapped_cmac_ioaddr; - - if (aspm) { - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - tp->org_pci_offset_99 = rtl8125_csi_fun0_read_byte(tp, 0x99); - tp->org_pci_offset_99 &= ~(BIT_5|BIT_6); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_6: - tp->org_pci_offset_180 = rtl8125_csi_fun0_read_byte(tp, 0x264); - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - tp->org_pci_offset_180 = rtl8125_csi_fun0_read_byte(tp, 0x214); - break; - } - } - - pci_read_config_byte(pdev, 0x80, &tp->org_pci_offset_80); - pci_read_config_byte(pdev, 0x81, &tp->org_pci_offset_81); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - default: - tp->use_timer_interrrupt = TRUE; - break; - } - - if (timer_count == 0 || tp->mcfg == CFG_METHOD_DEFAULT) - tp->use_timer_interrrupt = FALSE; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_V3; - break; - default: - tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_NOT_SUPPORT; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - tp->HwSuppLinkChgWakeUpVer = 3; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - tp->HwSuppD0SpeedUpVer = 1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - tp->HwSuppCheckPhyDisableModeVer = 3; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - tp->HwSuppTxNoCloseVer = 3; - break; - } - - if (tp->HwSuppTxNoCloseVer > 0 && tx_no_close_enable == 1) - tp->EnableTxNoClose = TRUE; - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_6: - tp->RequireLSOPatch = TRUE; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_2; - break; - case CFG_METHOD_3: - case CFG_METHOD_6: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_3; - break; - case CFG_METHOD_4: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_4; - break; - case CFG_METHOD_5: - case CFG_METHOD_7: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_5; - break; - } - - if (tp->HwIcVerUnknown) { - tp->NotWrRamCodeToMicroP = TRUE; - tp->NotWrMcuPatchCode = TRUE; - } - - switch (tp->mcfg) { - case CFG_METHOD_3: - case CFG_METHOD_6: - if ((rtl8125_mac_ocp_read(tp, 0xD442) & BIT_5) && - (mdio_direct_read_phy_ocp(tp, 0xD068) & BIT_1)) - tp->RequirePhyMdiSwapPatch = TRUE; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - tp->HwSuppMacMcuVer = 2; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - tp->MacMcuPageSize = RTL8125_MAC_MCU_PAGE_SIZE; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - tp->HwSuppNumTxQueues = 2; - tp->HwSuppNumRxQueues = 4; - break; - default: - tp->HwSuppNumTxQueues = 1; - tp->HwSuppNumRxQueues = 1; - break; - } - - tp->num_tx_rings = 1; -#ifdef ENABLE_MULTIPLE_TX_QUEUE -#ifndef ENABLE_LIB_SUPPORT - tp->num_tx_rings = tp->HwSuppNumTxQueues; -#endif -#endif - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - tp->HwSuppRssVer = 5; - tp->HwSuppIndirTblEntries = 128; - break; - } - - tp->num_rx_rings = 1; -#ifdef ENABLE_RSS_SUPPORT -#ifdef ENABLE_LIB_SUPPORT - if (tp->HwSuppRssVer > 0) - tp->EnableRss = 1; -#else - if (tp->HwSuppRssVer > 0) { - u8 rss_queue_num = netif_get_num_default_rss_queues(); - tp->num_rx_rings = (tp->HwSuppNumRxQueues > rss_queue_num)? - rss_queue_num : tp->HwSuppNumRxQueues; - - if (!(tp->num_rx_rings >= 2 && tp->irq_nvecs >= tp->num_rx_rings)) - tp->num_rx_rings = 1; - - if (tp->num_rx_rings >= 2) - tp->EnableRss = 1; - } -#endif -#endif - - rtl8125_setup_mqs_reg(tp); - - rtl8125_set_ring_size(tp, NUM_RX_DESC, NUM_TX_DESC); - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - tp->HwSuppPtpVer = 1; - break; - } -#ifdef ENABLE_PTP_SUPPORT - if (tp->HwSuppPtpVer > 0) - tp->EnablePtp = 1; -#endif - - //init interrupt - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - tp->HwSuppIsrVer = 2; - break; - default: - tp->HwSuppIsrVer = 1; - break; - } - - tp->HwCurrIsrVer = tp->HwSuppIsrVer; - if (tp->HwSuppIsrVer == 2) { - if (!(tp->features & RTL_FEATURE_MSIX) || - tp->irq_nvecs < R8125_MIN_MSIX_VEC_8125B) - tp->HwCurrIsrVer = 1; - } - - if (tp->HwCurrIsrVer < 2 || tp->irq_nvecs < 19) - tp->num_tx_rings = 1; - - if (tp->HwCurrIsrVer == 2) { - int i; - - tp->intr_mask = ISRIMR_V2_LINKCHG | ISRIMR_TOK_Q0; - if (tp->num_tx_rings > 1) - tp->intr_mask |= ISRIMR_TOK_Q1; - - for (i = 0; i < tp->num_rx_rings; i++) - tp->intr_mask |= ISRIMR_V2_ROK_Q0 << i; - } else { - tp->intr_mask = LinkChg | RxDescUnavail | TxOK | RxOK | SWInt; - tp->timer_intr_mask = LinkChg | PCSTimeout; - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_3(tp)) { - tp->timer_intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); - tp->intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); - } - } -#endif - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_6: - tp->HwSuppIntMitiVer = 3; - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - tp->HwSuppIntMitiVer = 4; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - tp->HwSuppExtendTallyCounterVer = 1; - break; - } - - timer_count_v2 = (timer_count / 0x100); - -#ifndef ENABLE_LIB_SUPPORT - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - if (tp->HwSuppIsrVer == 2) { - tp->RequireRduNonStopPatch = 1; - tp->EnableRss = 0; - } - break; - } -#endif - - tp->InitRxDescType = RX_DESC_RING_TYPE_1; - if (tp->EnableRss || tp->EnablePtp) - tp->InitRxDescType = RX_DESC_RING_TYPE_3; - - tp->RxDescLength = RX_DESC_LEN_TYPE_1; - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - tp->RxDescLength = RX_DESC_LEN_TYPE_3; - - tp->rtl8125_rx_config = rtl_chip_info[tp->chipset].RCR_Cfg; - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - tp->rtl8125_rx_config |= EnableRxDescV3; - - tp->NicCustLedValue = RTL_R16(tp, CustomLED); - - tp->wol_opts = rtl8125_get_hw_wol(tp); - tp->wol_enabled = (tp->wol_opts) ? WOL_ENABLED : WOL_DISABLED; - - if (tp->mcfg == CFG_METHOD_6 || tp->mcfg == CFG_METHOD_7) - rtl8125_link_option_giga((u8*)&autoneg_mode, (u32*)&speed_mode, (u8*)&duplex_mode, (u32*)&advertising_mode); - else - rtl8125_link_option((u8*)&autoneg_mode, (u32*)&speed_mode, (u8*)&duplex_mode, (u32*)&advertising_mode); - - tp->autoneg = autoneg_mode; - tp->speed = speed_mode; - tp->duplex = duplex_mode; - tp->advertising = advertising_mode; - tp->fcpause = rtl8125_fc_full; - - tp->max_jumbo_frame_size = rtl_chip_info[tp->chipset].jumbo_frame_sz; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - /* MTU range: 60 - hw-specific max */ - dev->min_mtu = ETH_MIN_MTU; - dev->max_mtu = tp->max_jumbo_frame_size; -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - - if (tp->mcfg != CFG_METHOD_DEFAULT) { - struct ethtool_eee *eee = &tp->eee; - - eee->eee_enabled = eee_enable; - eee->supported = SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full; - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - eee->supported |= SUPPORTED_2500baseX_Full; - break; - } - eee->advertised = mmd_eee_adv_to_ethtool_adv_t(MDIO_EEE_1000T | MDIO_EEE_100TX); - eee->tx_lpi_timer = dev->mtu + ETH_HLEN + 0x20; - } - - tp->ptp_master_mode = enable_ptp_master_mode; - -#ifdef ENABLE_RSS_SUPPORT - if (tp->EnableRss) - rtl8125_init_rss(tp); -#endif -} - -static void -rtl8125_release_board(struct pci_dev *pdev, - struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8125_set_bios_setting(dev); - rtl8125_rar_set(tp, tp->org_mac_addr); - tp->wol_enabled = WOL_DISABLED; - - if (!tp->DASH) - rtl8125_phy_power_down(dev); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - FreeAllocatedDashShareMemory(dev); -#endif - - if (tp->mapped_cmac_ioaddr != NULL) - iounmap(tp->mapped_cmac_ioaddr); - - iounmap(ioaddr); - pci_release_regions(pdev); - pci_clear_mwi(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static void -rtl8125_hw_address_set(struct net_device *dev, u8 mac_addr[MAC_ADDR_LEN]) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) - eth_hw_addr_set(dev, mac_addr); -#else - memcpy(dev->dev_addr, mac_addr, MAC_ADDR_LEN); -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(5,17,0) -} - -static int -rtl8125_get_mac_address(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - u8 mac_addr[MAC_ADDR_LEN]; - - for (i = 0; i < MAC_ADDR_LEN; i++) - mac_addr[i] = RTL_R8(tp, MAC0 + i); - - if(tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_6 || - tp->mcfg == CFG_METHOD_7) { - *(u32*)&mac_addr[0] = RTL_R32(tp, BACKUP_ADDR0_8125); - *(u16*)&mac_addr[4] = RTL_R16(tp, BACKUP_ADDR1_8125); - } - - if (!is_valid_ether_addr(mac_addr)) { - netif_err(tp, probe, dev, "Invalid ether addr %pM\n", - mac_addr); - eth_random_addr(mac_addr); - dev->addr_assign_type = NET_ADDR_RANDOM; - netif_info(tp, probe, dev, "Random ether addr %pM\n", - mac_addr); - tp->random_mac = 1; - } - - rtl8125_hw_address_set(dev, mac_addr); - rtl8125_rar_set(tp, mac_addr); - - /* keep the original MAC address */ - memcpy(tp->org_mac_addr, dev->dev_addr, MAC_ADDR_LEN); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); -#endif - return 0; -} - -/** - * rtl8125_set_mac_address - Change the Ethernet Address of the NIC - * @dev: network interface device structure - * @p: pointer to an address structure - * - * Return 0 on success, negative on failure - **/ -static int -rtl8125_set_mac_address(struct net_device *dev, - void *p) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - rtl8125_hw_address_set(dev, addr->sa_data); - - rtl8125_rar_set(tp, dev->dev_addr); - - return 0; -} - -/****************************************************************************** - * rtl8125_rar_set - Puts an ethernet address into a receive address register. - * - * tp - The private data structure for driver - * addr - Address to put into receive address register - *****************************************************************************/ -void -rtl8125_rar_set(struct rtl8125_private *tp, - const u8 *addr) -{ - uint32_t rar_low = 0; - uint32_t rar_high = 0; - - rar_low = ((uint32_t) addr[0] | - ((uint32_t) addr[1] << 8) | - ((uint32_t) addr[2] << 16) | - ((uint32_t) addr[3] << 24)); - - rar_high = ((uint32_t) addr[4] | - ((uint32_t) addr[5] << 8)); - - rtl8125_enable_cfg9346_write(tp); - RTL_W32(tp, MAC0, rar_low); - RTL_W32(tp, MAC4, rar_high); - - rtl8125_disable_cfg9346_write(tp); -} - -#ifdef ETHTOOL_OPS_COMPAT -static int ethtool_get_settings(struct net_device *dev, void *useraddr) -{ - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - int err; - - if (!ethtool_ops->get_settings) - return -EOPNOTSUPP; - - err = ethtool_ops->get_settings(dev, &cmd); - if (err < 0) - return err; - - if (copy_to_user(useraddr, &cmd, sizeof(cmd))) - return -EFAULT; - return 0; -} - -static int ethtool_set_settings(struct net_device *dev, void *useraddr) -{ - struct ethtool_cmd cmd; - - if (!ethtool_ops->set_settings) - return -EOPNOTSUPP; - - if (copy_from_user(&cmd, useraddr, sizeof(cmd))) - return -EFAULT; - - return ethtool_ops->set_settings(dev, &cmd); -} - -static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr) -{ - struct ethtool_drvinfo info; - struct ethtool_ops *ops = ethtool_ops; - - if (!ops->get_drvinfo) - return -EOPNOTSUPP; - - memset(&info, 0, sizeof(info)); - info.cmd = ETHTOOL_GDRVINFO; - ops->get_drvinfo(dev, &info); - - if (ops->self_test_count) - info.testinfo_len = ops->self_test_count(dev); - if (ops->get_stats_count) - info.n_stats = ops->get_stats_count(dev); - if (ops->get_regs_len) - info.regdump_len = ops->get_regs_len(dev); - if (ops->get_eeprom_len) - info.eedump_len = ops->get_eeprom_len(dev); - - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int ethtool_get_regs(struct net_device *dev, char *useraddr) -{ - struct ethtool_regs regs; - struct ethtool_ops *ops = ethtool_ops; - void *regbuf; - int reglen, ret; - - if (!ops->get_regs || !ops->get_regs_len) - return -EOPNOTSUPP; - - if (copy_from_user(®s, useraddr, sizeof(regs))) - return -EFAULT; - - reglen = ops->get_regs_len(dev); - if (regs.len > reglen) - regs.len = reglen; - - regbuf = kmalloc(reglen, GFP_USER); - if (!regbuf) - return -ENOMEM; - - ops->get_regs(dev, ®s, regbuf); - - ret = -EFAULT; - if (copy_to_user(useraddr, ®s, sizeof(regs))) - goto out; - useraddr += offsetof(struct ethtool_regs, data); - if (copy_to_user(useraddr, regbuf, reglen)) - goto out; - ret = 0; - -out: - kfree(regbuf); - return ret; -} - -static int ethtool_get_wol(struct net_device *dev, char *useraddr) -{ - struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; - - if (!ethtool_ops->get_wol) - return -EOPNOTSUPP; - - ethtool_ops->get_wol(dev, &wol); - - if (copy_to_user(useraddr, &wol, sizeof(wol))) - return -EFAULT; - return 0; -} - -static int ethtool_set_wol(struct net_device *dev, char *useraddr) -{ - struct ethtool_wolinfo wol; - - if (!ethtool_ops->set_wol) - return -EOPNOTSUPP; - - if (copy_from_user(&wol, useraddr, sizeof(wol))) - return -EFAULT; - - return ethtool_ops->set_wol(dev, &wol); -} - -static int ethtool_get_msglevel(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GMSGLVL }; - - if (!ethtool_ops->get_msglevel) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_msglevel(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_msglevel(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_msglevel) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - ethtool_ops->set_msglevel(dev, edata.data); - return 0; -} - -static int ethtool_nway_reset(struct net_device *dev) -{ - if (!ethtool_ops->nway_reset) - return -EOPNOTSUPP; - - return ethtool_ops->nway_reset(dev); -} - -static int ethtool_get_link(struct net_device *dev, void *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - - if (!ethtool_ops->get_link) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_link(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_get_eeprom(struct net_device *dev, void *useraddr) -{ - struct ethtool_eeprom eeprom; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->get_eeprom || !ops->get_eeprom_len) - return -EOPNOTSUPP; - - if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; - - /* Check for wrap and zero */ - if (eeprom.offset + eeprom.len <= eeprom.offset) - return -EINVAL; - - /* Check for exceeding total eeprom len */ - if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) - return -EINVAL; - - data = kmalloc(eeprom.len, GFP_USER); - if (!data) - return -ENOMEM; - - ret = -EFAULT; - if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) - goto out; - - ret = ops->get_eeprom(dev, &eeprom, data); - if (ret) - goto out; - - ret = -EFAULT; - if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) - goto out; - if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_set_eeprom(struct net_device *dev, void *useraddr) -{ - struct ethtool_eeprom eeprom; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->set_eeprom || !ops->get_eeprom_len) - return -EOPNOTSUPP; - - if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; - - /* Check for wrap and zero */ - if (eeprom.offset + eeprom.len <= eeprom.offset) - return -EINVAL; - - /* Check for exceeding total eeprom len */ - if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) - return -EINVAL; - - data = kmalloc(eeprom.len, GFP_USER); - if (!data) - return -ENOMEM; - - ret = -EFAULT; - if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) - goto out; - - ret = ops->set_eeprom(dev, &eeprom, data); - if (ret) - goto out; - - if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) - ret = -EFAULT; - -out: - kfree(data); - return ret; -} - -static int ethtool_get_coalesce(struct net_device *dev, void *useraddr) -{ - struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; - - if (!ethtool_ops->get_coalesce) - return -EOPNOTSUPP; - - ethtool_ops->get_coalesce(dev, &coalesce); - - if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) - return -EFAULT; - return 0; -} - -static int ethtool_set_coalesce(struct net_device *dev, void *useraddr) -{ - struct ethtool_coalesce coalesce; - - if (!ethtool_ops->get_coalesce) - return -EOPNOTSUPP; - - if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) - return -EFAULT; - - return ethtool_ops->set_coalesce(dev, &coalesce); -} - -static int ethtool_get_ringparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; - - if (!ethtool_ops->get_ringparam) - return -EOPNOTSUPP; - - ethtool_ops->get_ringparam(dev, &ringparam); - - if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) - return -EFAULT; - return 0; -} - -static int ethtool_set_ringparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_ringparam ringparam; - - if (!ethtool_ops->get_ringparam) - return -EOPNOTSUPP; - - if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) - return -EFAULT; - - return ethtool_ops->set_ringparam(dev, &ringparam); -} - -static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; - - if (!ethtool_ops->get_pauseparam) - return -EOPNOTSUPP; - - ethtool_ops->get_pauseparam(dev, &pauseparam); - - if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) - return -EFAULT; - return 0; -} - -static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_pauseparam pauseparam; - - if (!ethtool_ops->get_pauseparam) - return -EOPNOTSUPP; - - if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) - return -EFAULT; - - return ethtool_ops->set_pauseparam(dev, &pauseparam); -} - -static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GRXCSUM }; - - if (!ethtool_ops->get_rx_csum) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_rx_csum(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_rx_csum) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - ethtool_ops->set_rx_csum(dev, edata.data); - return 0; -} - -static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GTXCSUM }; - - if (!ethtool_ops->get_tx_csum) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_tx_csum(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_tx_csum) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_tx_csum(dev, edata.data); -} - -static int ethtool_get_sg(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GSG }; - - if (!ethtool_ops->get_sg) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_sg(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_sg(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_sg) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_sg(dev, edata.data); -} - -static int ethtool_get_tso(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GTSO }; - - if (!ethtool_ops->get_tso) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_tso(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_tso(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_tso) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_tso(dev, edata.data); -} - -static int ethtool_self_test(struct net_device *dev, char *useraddr) -{ - struct ethtool_test test; - struct ethtool_ops *ops = ethtool_ops; - u64 *data; - int ret; - - if (!ops->self_test || !ops->self_test_count) - return -EOPNOTSUPP; - - if (copy_from_user(&test, useraddr, sizeof(test))) - return -EFAULT; - - test.len = ops->self_test_count(dev); - data = kmalloc(test.len * sizeof(u64), GFP_USER); - if (!data) - return -ENOMEM; - - ops->self_test(dev, &test, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &test, sizeof(test))) - goto out; - useraddr += sizeof(test); - if (copy_to_user(useraddr, data, test.len * sizeof(u64))) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_get_strings(struct net_device *dev, void *useraddr) -{ - struct ethtool_gstrings gstrings; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->get_strings) - return -EOPNOTSUPP; - - if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) - return -EFAULT; - - switch (gstrings.string_set) { - case ETH_SS_TEST: - if (!ops->self_test_count) - return -EOPNOTSUPP; - gstrings.len = ops->self_test_count(dev); - break; - case ETH_SS_STATS: - if (!ops->get_stats_count) - return -EOPNOTSUPP; - gstrings.len = ops->get_stats_count(dev); - break; - default: - return -EINVAL; - } - - data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); - if (!data) - return -ENOMEM; - - ops->get_strings(dev, gstrings.string_set, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) - goto out; - useraddr += sizeof(gstrings); - if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_phys_id(struct net_device *dev, void *useraddr) -{ - struct ethtool_value id; - - if (!ethtool_ops->phys_id) - return -EOPNOTSUPP; - - if (copy_from_user(&id, useraddr, sizeof(id))) - return -EFAULT; - - return ethtool_ops->phys_id(dev, id.data); -} - -static int ethtool_get_stats(struct net_device *dev, void *useraddr) -{ - struct ethtool_stats stats; - struct ethtool_ops *ops = ethtool_ops; - u64 *data; - int ret; - - if (!ops->get_ethtool_stats || !ops->get_stats_count) - return -EOPNOTSUPP; - - if (copy_from_user(&stats, useraddr, sizeof(stats))) - return -EFAULT; - - stats.n_stats = ops->get_stats_count(dev); - data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER); - if (!data) - return -ENOMEM; - - ops->get_ethtool_stats(dev, &stats, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &stats, sizeof(stats))) - goto out; - useraddr += sizeof(stats); - if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_ioctl(struct ifreq *ifr) -{ - struct net_device *dev = __dev_get_by_name(ifr->ifr_name); - void *useraddr = (void *) ifr->ifr_data; - u32 ethcmd; - - /* - * XXX: This can be pushed down into the ethtool_* handlers that - * need it. Keep existing behaviour for the moment. - */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (!dev || !netif_device_present(dev)) - return -ENODEV; - - if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GSET: - return ethtool_get_settings(dev, useraddr); - case ETHTOOL_SSET: - return ethtool_set_settings(dev, useraddr); - case ETHTOOL_GDRVINFO: - return ethtool_get_drvinfo(dev, useraddr); - case ETHTOOL_GREGS: - return ethtool_get_regs(dev, useraddr); - case ETHTOOL_GWOL: - return ethtool_get_wol(dev, useraddr); - case ETHTOOL_SWOL: - return ethtool_set_wol(dev, useraddr); - case ETHTOOL_GMSGLVL: - return ethtool_get_msglevel(dev, useraddr); - case ETHTOOL_SMSGLVL: - return ethtool_set_msglevel(dev, useraddr); - case ETHTOOL_NWAY_RST: - return ethtool_nway_reset(dev); - case ETHTOOL_GLINK: - return ethtool_get_link(dev, useraddr); - case ETHTOOL_GEEPROM: - return ethtool_get_eeprom(dev, useraddr); - case ETHTOOL_SEEPROM: - return ethtool_set_eeprom(dev, useraddr); - case ETHTOOL_GCOALESCE: - return ethtool_get_coalesce(dev, useraddr); - case ETHTOOL_SCOALESCE: - return ethtool_set_coalesce(dev, useraddr); - case ETHTOOL_GRINGPARAM: - return ethtool_get_ringparam(dev, useraddr); - case ETHTOOL_SRINGPARAM: - return ethtool_set_ringparam(dev, useraddr); - case ETHTOOL_GPAUSEPARAM: - return ethtool_get_pauseparam(dev, useraddr); - case ETHTOOL_SPAUSEPARAM: - return ethtool_set_pauseparam(dev, useraddr); - case ETHTOOL_GRXCSUM: - return ethtool_get_rx_csum(dev, useraddr); - case ETHTOOL_SRXCSUM: - return ethtool_set_rx_csum(dev, useraddr); - case ETHTOOL_GTXCSUM: - return ethtool_get_tx_csum(dev, useraddr); - case ETHTOOL_STXCSUM: - return ethtool_set_tx_csum(dev, useraddr); - case ETHTOOL_GSG: - return ethtool_get_sg(dev, useraddr); - case ETHTOOL_SSG: - return ethtool_set_sg(dev, useraddr); - case ETHTOOL_GTSO: - return ethtool_get_tso(dev, useraddr); - case ETHTOOL_STSO: - return ethtool_set_tso(dev, useraddr); - case ETHTOOL_TEST: - return ethtool_self_test(dev, useraddr); - case ETHTOOL_GSTRINGS: - return ethtool_get_strings(dev, useraddr); - case ETHTOOL_PHYS_ID: - return ethtool_phys_id(dev, useraddr); - case ETHTOOL_GSTATS: - return ethtool_get_stats(dev, useraddr); - default: - return -EOPNOTSUPP; - } - - return -EOPNOTSUPP; -} -#endif //ETHTOOL_OPS_COMPAT - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) -static int rtl8125_siocdevprivate(struct net_device *dev, struct ifreq *ifr, - void __user *data, int cmd) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret = 0; - - switch (cmd) { -#ifdef ENABLE_DASH_SUPPORT - case SIOCDEVPRIVATE_RTLDASH: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - - ret = rtl8125_dash_ioctl(dev, ifr); - break; -#endif - -#ifdef ENABLE_REALWOW_SUPPORT - case SIOCDEVPRIVATE_RTLREALWOW: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - - ret = rtl8125_realwow_ioctl(dev, ifr); - break; -#endif - - case SIOCRTLTOOL: - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - - ret = rtl8125_tool_ioctl(tp, ifr); - break; - - default: - ret = -EOPNOTSUPP; - } - - return ret; -} -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(5,15,0) - -static int -rtl8125_do_ioctl(struct net_device *dev, - struct ifreq *ifr, - int cmd) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - int ret = 0; - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - break; - - case SIOCGMIIREG: - rtl8125_mdio_write(tp, 0x1F, 0x0000); - data->val_out = rtl8125_mdio_read(tp, data->reg_num); - break; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, data->reg_num, data->val_in); - break; - -#ifdef ETHTOOL_OPS_COMPAT - case SIOCETHTOOL: - ret = ethtool_ioctl(ifr); - break; -#endif - -#ifdef ENABLE_PTP_SUPPORT - case SIOCSHWTSTAMP: - case SIOCGHWTSTAMP: - if (tp->EnablePtp) - ret = rtl8125_ptp_ioctl(dev, ifr, cmd); - else - ret = -EOPNOTSUPP; - break; -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,15,0) -#ifdef ENABLE_DASH_SUPPORT - case SIOCDEVPRIVATE_RTLDASH: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - - ret = rtl8125_dash_ioctl(dev, ifr); - break; -#endif - -#ifdef ENABLE_REALWOW_SUPPORT - case SIOCDEVPRIVATE_RTLREALWOW: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - - ret = rtl8125_realwow_ioctl(dev, ifr); - break; -#endif - - case SIOCRTLTOOL: - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - - ret = rtl8125_tool_ioctl(tp, ifr); - break; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(5,15,0) - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -static void -rtl8125_phy_power_up(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (rtl8125_is_in_phy_disable_mode(dev)) { - return; - } - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE); - - //wait ups resume (phy state 3) - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_wait_phy_ups_resume(dev, 3); - break; - }; -} - -static void -rtl8125_phy_power_down(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - rtl8125_mdio_write(tp, 0x1F, 0x0000); - rtl8125_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); -} - -static int __devinit -rtl8125_init_board(struct pci_dev *pdev, - struct net_device **dev_out, - void __iomem **ioaddr_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8125_private *tp; - int rc = -ENOMEM, i, pm_cap; - - assert(ioaddr_out != NULL); - - /* dev zeroed in alloc_etherdev */ - dev = alloc_etherdev_mq(sizeof (*tp), R8125_MAX_QUEUES); - if (dev == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out; - } - - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8125_MSG_DEFAULT); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - if (!aspm) - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | - PCIE_LINK_STATE_CLKPM); -#endif - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_free_dev; - } - - if (pci_set_mwi(pdev) < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_drv(&debug)) - dev_info(&pdev->dev, "Mem-Wr-Inval unavailable.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - } - - /* save power state before pci_enable_device overwrites it */ - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap) { - u16 pwr_command; - - pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); - } else { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, "PowerManagement capability not found.\n"); - } -#else - printk("PowerManagement capability not found.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - - } - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -ENODEV; - goto err_out_mwi; - } - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, 2) < R8125_REGS_SIZE) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -ENODEV; - goto err_out_mwi; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_mwi; - } - - if ((sizeof(dma_addr_t) > 4) && - use_dac && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && - !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "DMA configuration failed.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_free_res; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); - if (ioaddr == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -EIO; - goto err_out_free_res; - } - - tp->mmio_addr = ioaddr; - - /* Identify chip attached to board */ - rtl8125_get_mac_version(tp); - - rtl8125_print_mac_version(tp); - - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { - if (tp->mcfg == rtl_chip_info[i].mcfg) - break; - } - - if (i < 0) { - /* Unknown chip: assume array element #0, original RTL-8125 */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_printk(KERN_DEBUG, &pdev->dev, "unknown chip version, assuming %s\n", rtl_chip_info[0].name); -#else - printk("Realtek unknown chip version, assuming %s\n", rtl_chip_info[0].name); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - i++; - } - - tp->chipset = i; - - *ioaddr_out = ioaddr; - *dev_out = dev; -out: - return rc; - -err_out_free_res: - pci_release_regions(pdev); -err_out_mwi: - pci_clear_mwi(pdev); - pci_disable_device(pdev); -err_out_free_dev: - free_netdev(dev); -err_out: - *ioaddr_out = NULL; - *dev_out = NULL; - goto out; -} - -static void -rtl8125_esd_checker(struct rtl8125_private *tp) -{ - struct net_device *dev = tp->dev; - struct pci_dev *pdev = tp->pci_dev; - u8 cmd; - u16 io_base_l; - u16 mem_base_l; - u16 mem_base_h; - u8 ilr; - u16 resv_0x1c_h; - u16 resv_0x1c_l; - u16 resv_0x20_l; - u16 resv_0x20_h; - u16 resv_0x24_l; - u16 resv_0x24_h; - u16 resv_0x2c_h; - u16 resv_0x2c_l; - u32 pci_sn_l; - u32 pci_sn_h; - - if (unlikely(tp->rtk_enable_diag)) - goto exit; - - tp->esd_flag = 0; - - pci_read_config_byte(pdev, PCI_COMMAND, &cmd); - if (cmd != tp->pci_cfg_space.cmd) { - printk(KERN_ERR "%s: cmd = 0x%02x, should be 0x%02x \n.", dev->name, cmd, tp->pci_cfg_space.cmd); - pci_write_config_byte(pdev, PCI_COMMAND, tp->pci_cfg_space.cmd); - tp->esd_flag |= BIT_0; - - pci_read_config_byte(pdev, PCI_COMMAND, &cmd); - if (cmd == 0xff) { - printk(KERN_ERR "%s: pci link is down \n.", dev->name); - goto exit; - } - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &io_base_l); - if (io_base_l != tp->pci_cfg_space.io_base_l) { - printk(KERN_ERR "%s: io_base_l = 0x%04x, should be 0x%04x \n.", dev->name, io_base_l, tp->pci_cfg_space.io_base_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_0, tp->pci_cfg_space.io_base_l); - tp->esd_flag |= BIT_1; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &mem_base_l); - if (mem_base_l != tp->pci_cfg_space.mem_base_l) { - printk(KERN_ERR "%s: mem_base_l = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_l, tp->pci_cfg_space.mem_base_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_2, tp->pci_cfg_space.mem_base_l); - tp->esd_flag |= BIT_2; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &mem_base_h); - if (mem_base_h!= tp->pci_cfg_space.mem_base_h) { - printk(KERN_ERR "%s: mem_base_h = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_h, tp->pci_cfg_space.mem_base_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, tp->pci_cfg_space.mem_base_h); - tp->esd_flag |= BIT_3; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &resv_0x1c_l); - if (resv_0x1c_l != tp->pci_cfg_space.resv_0x1c_l) { - printk(KERN_ERR "%s: resv_0x1c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_l, tp->pci_cfg_space.resv_0x1c_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_3, tp->pci_cfg_space.resv_0x1c_l); - tp->esd_flag |= BIT_4; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &resv_0x1c_h); - if (resv_0x1c_h != tp->pci_cfg_space.resv_0x1c_h) { - printk(KERN_ERR "%s: resv_0x1c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_h, tp->pci_cfg_space.resv_0x1c_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, tp->pci_cfg_space.resv_0x1c_h); - tp->esd_flag |= BIT_5; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &resv_0x20_l); - if (resv_0x20_l != tp->pci_cfg_space.resv_0x20_l) { - printk(KERN_ERR "%s: resv_0x20_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_l, tp->pci_cfg_space.resv_0x20_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_4, tp->pci_cfg_space.resv_0x20_l); - tp->esd_flag |= BIT_6; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &resv_0x20_h); - if (resv_0x20_h != tp->pci_cfg_space.resv_0x20_h) { - printk(KERN_ERR "%s: resv_0x20_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_h, tp->pci_cfg_space.resv_0x20_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, tp->pci_cfg_space.resv_0x20_h); - tp->esd_flag |= BIT_7; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &resv_0x24_l); - if (resv_0x24_l != tp->pci_cfg_space.resv_0x24_l) { - printk(KERN_ERR "%s: resv_0x24_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_l, tp->pci_cfg_space.resv_0x24_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_5, tp->pci_cfg_space.resv_0x24_l); - tp->esd_flag |= BIT_8; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &resv_0x24_h); - if (resv_0x24_h != tp->pci_cfg_space.resv_0x24_h) { - printk(KERN_ERR "%s: resv_0x24_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_h, tp->pci_cfg_space.resv_0x24_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, tp->pci_cfg_space.resv_0x24_h); - tp->esd_flag |= BIT_9; - } - - pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ilr); - if (ilr != tp->pci_cfg_space.ilr) { - printk(KERN_ERR "%s: ilr = 0x%02x, should be 0x%02x \n.", dev->name, ilr, tp->pci_cfg_space.ilr); - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, tp->pci_cfg_space.ilr); - tp->esd_flag |= BIT_10; - } - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &resv_0x2c_l); - if (resv_0x2c_l != tp->pci_cfg_space.resv_0x2c_l) { - printk(KERN_ERR "%s: resv_0x2c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_l, tp->pci_cfg_space.resv_0x2c_l); - pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, tp->pci_cfg_space.resv_0x2c_l); - tp->esd_flag |= BIT_11; - } - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &resv_0x2c_h); - if (resv_0x2c_h != tp->pci_cfg_space.resv_0x2c_h) { - printk(KERN_ERR "%s: resv_0x2c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_h, tp->pci_cfg_space.resv_0x2c_h); - pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, tp->pci_cfg_space.resv_0x2c_h); - tp->esd_flag |= BIT_12; - } - - if (tp->HwPcieSNOffset > 0) { - pci_sn_l = rtl8125_csi_read(tp, tp->HwPcieSNOffset); - if (pci_sn_l != tp->pci_cfg_space.pci_sn_l) { - printk(KERN_ERR "%s: pci_sn_l = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_l, tp->pci_cfg_space.pci_sn_l); - rtl8125_csi_write(tp, tp->HwPcieSNOffset, tp->pci_cfg_space.pci_sn_l); - tp->esd_flag |= BIT_13; - } - - pci_sn_h = rtl8125_csi_read(tp, tp->HwPcieSNOffset + 4); - if (pci_sn_h != tp->pci_cfg_space.pci_sn_h) { - printk(KERN_ERR "%s: pci_sn_h = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_h, tp->pci_cfg_space.pci_sn_h); - rtl8125_csi_write(tp, tp->HwPcieSNOffset + 4, tp->pci_cfg_space.pci_sn_h); - tp->esd_flag |= BIT_14; - } - } - - if (tp->esd_flag != 0) { - printk(KERN_ERR "%s: esd_flag = 0x%04x\n.\n", dev->name, tp->esd_flag); - netif_tx_stop_all_queues(dev); - netif_carrier_off(dev); - rtl8125_hw_reset(dev); - rtl8125_tx_clear(tp); - rtl8125_rx_clear(tp); - rtl8125_init_ring(dev); - rtl8125_up(dev); - rtl8125_enable_hw_linkchg_interrupt(tp); - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - tp->esd_flag = 0; - } -exit: - return; -} -/* -static void -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -rtl8125_esd_timer(unsigned long __opaque) -#else -rtl8125_esd_timer(struct timer_list *t) -#endif -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8125_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->esd_timer; -#else - struct rtl8125_private *tp = from_timer(tp, t, esd_timer); - //struct net_device *dev = tp->dev; - struct timer_list *timer = t; -#endif - rtl8125_esd_checker(tp); - - mod_timer(timer, jiffies + timeout); -} -*/ - -/* -static void -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -rtl8125_link_timer(unsigned long __opaque) -#else -rtl8125_link_timer(struct timer_list *t) -#endif -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8125_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->link_timer; -#else - struct rtl8125_private *tp = from_timer(tp, t, link_timer); - struct net_device *dev = tp->dev; - struct timer_list *timer = t; -#endif - rtl8125_check_link_status(dev); - - mod_timer(timer, jiffies + RTL8125_LINK_TIMEOUT); -} -*/ - -int -rtl8125_enable_msix(struct rtl8125_private *tp) -{ - int i, nvecs = 0; - struct msix_entry msix_ent[R8125_MAX_MSIX_VEC]; - //struct net_device *dev = tp->dev; - //const int len = sizeof(tp->irq_tbl[0].name); - - for (i = 0; i < R8125_MAX_MSIX_VEC; i++) { - msix_ent[i].entry = i; - msix_ent[i].vector = 0; - } - - nvecs = pci_enable_msix_range(tp->pci_dev, msix_ent, - tp->min_irq_nvecs, tp->max_irq_nvecs); - if (nvecs < 0) - goto out; - - for (i = 0; i < nvecs; i++) { - struct r8125_irq *irq = &tp->irq_tbl[i]; - irq->vector = msix_ent[i].vector; - //snprintf(irq->name, len, "%s-%d", dev->name, i); - //irq->handler = rtl8125_interrupt_msix; - } - -out: - return nvecs; -} - -void rtl8125_dump_msix_tbl(struct rtl8125_private *tp) -{ - void __iomem *ioaddr; - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(tp->pci_dev, 4), pci_resource_len(tp->pci_dev, 4)); - if (ioaddr) { - int i = 0; - for (i=0; iirq_nvecs; i++) { - printk("entry 0x%d %08X %08X %08X %08X \n", - i, - readl(ioaddr + 16 * i), - readl(ioaddr + 16 * i + 4), - readl(ioaddr + 16 * i + 8), - readl(ioaddr + 16 * i + 12)); - } - iounmap(ioaddr); - } -} - -/* Cfg9346_Unlock assumed. */ -static int rtl8125_try_msi(struct rtl8125_private *tp) -{ - struct pci_dev *pdev = tp->pci_dev; - unsigned msi = 0; - int nvecs = 1; - - tp->max_irq_nvecs = 1; - tp->min_irq_nvecs = 1; -#ifndef DISABLE_MULTI_MSIX_VECTOR - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_7: - tp->max_irq_nvecs = R8125_MAX_MSIX_VEC_8125B; - tp->min_irq_nvecs = R8125_MIN_MSIX_VEC_8125B; - break; - } -#endif - -#if defined(RTL_USE_NEW_INTR_API) - if ((nvecs = pci_alloc_irq_vectors(pdev, tp->min_irq_nvecs, tp->max_irq_nvecs, PCI_IRQ_MSIX)) > 0) - msi |= RTL_FEATURE_MSIX; - else if ((nvecs = pci_alloc_irq_vectors(pdev, 1, 1, PCI_IRQ_ALL_TYPES)) > 0 && - pci_dev_msi_enabled(pdev)) - msi |= RTL_FEATURE_MSI; -#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - if ((nvecs = rtl8125_enable_msix(tp)) > 0) - msi |= RTL_FEATURE_MSIX; - else if (!pci_enable_msi(pdev)) - msi |= RTL_FEATURE_MSI; -#endif - if (!(msi & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX))) - dev_info(&pdev->dev, "no MSI/MSI-X. Back to INTx.\n"); - - if (!(msi & RTL_FEATURE_MSIX) || nvecs < 1) - nvecs = 1; - - tp->irq_nvecs = nvecs; - - tp->features |= msi; - - return nvecs; -} - -static void rtl8125_disable_msi(struct pci_dev *pdev, struct rtl8125_private *tp) -{ -#if defined(RTL_USE_NEW_INTR_API) - if (tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX)) - pci_free_irq_vectors(pdev); -#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - if (tp->features & (RTL_FEATURE_MSIX)) - pci_disable_msix(pdev); - else if (tp->features & (RTL_FEATURE_MSI)) - pci_disable_msi(pdev); -#endif - tp->features &= ~(RTL_FEATURE_MSI | RTL_FEATURE_MSIX); -} - -static int rtl8125_get_irq(struct pci_dev *pdev) -{ -#if defined(RTL_USE_NEW_INTR_API) - return pci_irq_vector(pdev, 0); -#else - return pdev->irq; -#endif -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) -static const struct net_device_ops rtl8125_netdev_ops = { - .ndo_open = rtl8125_open, - .ndo_stop = rtl8125_close, - .ndo_get_stats = rtl8125_get_stats, - .ndo_start_xmit = rtl8125_start_xmit, - .ndo_tx_timeout = rtl8125_tx_timeout, - .ndo_change_mtu = rtl8125_change_mtu, - .ndo_set_mac_address = rtl8125_set_mac_address, -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,15,0) - .ndo_do_ioctl = rtl8125_do_ioctl, -#else - .ndo_siocdevprivate = rtl8125_siocdevprivate, - .ndo_eth_ioctl = rtl8125_do_ioctl, -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(5,15,0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) - .ndo_set_multicast_list = rtl8125_set_rx_mode, -#else - .ndo_set_rx_mode = rtl8125_set_rx_mode, -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) -#ifdef CONFIG_R8125_VLAN - .ndo_vlan_rx_register = rtl8125_vlan_rx_register, -#endif -#else - .ndo_fix_features = rtl8125_fix_features, - .ndo_set_features = rtl8125_set_features, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8125_netpoll, -#endif -}; -#endif - - -#ifdef CONFIG_R8125_NAPI - -static int rtl8125_poll(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done = 0; - int i; - - for (i = 0; i < tp->num_tx_rings; i++) - rtl8125_tx_interrupt(&tp->tx_ring[i], budget); - - for (i = 0; i < tp->num_rx_rings; i++) - work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], budget); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - HandleDashInterrupt(tp->dev); -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8125_switch_to_timer_interrupt(tp); - } - - return RTL_NAPI_RETURN_VALUE; -} - -#if 0 -static int rtl8125_poll_msix_ring(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done = 0; - const int message_id = r8125napi->index; - - rtl8125_tx_interrupt_with_vector(tp, message_id, budget); - - work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH && message_id == 0) - HandleDashInterrupt(tp->dev); -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8125_enable_hw_interrupt_v2(tp, message_id); - } - - return RTL_NAPI_RETURN_VALUE; -} -#endif - -static int rtl8125_poll_msix_tx(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done = 0; - const int message_id = r8125napi->index; - - //suppress unused variable - (void)(dev); - - rtl8125_tx_interrupt_with_vector(tp, message_id, budget); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8125_enable_hw_interrupt_v2(tp, message_id); - } - - return RTL_NAPI_RETURN_VALUE; -} - -static int rtl8125_poll_msix_other(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - const int message_id = r8125napi->index; - - //suppress unused variable - (void)(dev); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - RTL_NETIF_RX_COMPLETE(dev, napi, work_to_do); -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_to_do); -#endif - - rtl8125_enable_hw_interrupt_v2(tp, message_id); - - return 1; -} - -static int rtl8125_poll_msix_rx(napi_ptr napi, napi_budget budget) -{ - struct r8125_napi *r8125napi = RTL_GET_PRIV(napi, struct r8125_napi); - struct rtl8125_private *tp = r8125napi->priv; - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done = 0; - const int message_id = r8125napi->index; - - work_done += rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8125_enable_hw_interrupt_v2(tp, message_id); - } - - return RTL_NAPI_RETURN_VALUE; -} - -static void rtl8125_enable_napi(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - int i; - - for (i = 0; i < tp->irq_nvecs; i++) - RTL_NAPI_ENABLE(tp->dev, &tp->r8125napi[i].napi); -#endif -} - -static void rtl8125_disable_napi(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - int i; - - for (i = 0; i < tp->irq_nvecs; i++) - RTL_NAPI_DISABLE(tp->dev, &tp->r8125napi[i].napi); -#endif -} - -static void rtl8125_del_napi(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - int i; - - for (i = 0; i < tp->irq_nvecs; i++) - RTL_NAPI_DEL((&tp->r8125napi[i])); -#endif -} -#endif //CONFIG_R8125_NAPI - -static void rtl8125_init_napi(struct rtl8125_private *tp) -{ - int i; - - for (i=0; iirq_nvecs; i++) { - struct r8125_napi *r8125napi = &tp->r8125napi[i]; -#ifdef CONFIG_R8125_NAPI - int (*poll)(struct napi_struct *, int); - - if (tp->features & RTL_FEATURE_MSIX && - tp->HwCurrIsrVer == 2) { - if (i < R8125_MAX_RX_QUEUES_VEC_V3) - poll = rtl8125_poll_msix_rx; - else if (i == 16 || i == 18) - poll = rtl8125_poll_msix_tx; - else - poll = rtl8125_poll_msix_other; - } else { - poll = rtl8125_poll; - } - - RTL_NAPI_CONFIG(tp->dev, r8125napi, poll, R8125_NAPI_WEIGHT); -#endif - - r8125napi->priv = tp; - r8125napi->index = i; - } -} - -static int -rtl8125_set_real_num_queue(struct rtl8125_private *tp) -{ - int retval = 0; - - retval = netif_set_real_num_tx_queues(tp->dev, tp->num_tx_rings); - if (retval < 0) - goto exit; - - retval = netif_set_real_num_rx_queues(tp->dev, tp->num_rx_rings); - if (retval < 0) - goto exit; - -exit: - return retval; -} - -static int __devinit -rtl8125_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8125_private *tp; - void __iomem *ioaddr = NULL; - static int board_idx = -1; - - int rc; - - assert(pdev != NULL); - assert(ent != NULL); - - board_idx++; - - if (netif_msg_drv(&debug)) - printk(KERN_INFO "%s 2.5Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8125_VERSION); - - rc = rtl8125_init_board(pdev, &dev, &ioaddr); - if (rc) - goto out; - - tp = netdev_priv(dev); - assert(ioaddr != NULL); - - tp->set_speed = rtl8125_set_speed_xmii; - tp->get_settings = rtl8125_gset_xmii; - tp->phy_reset_enable = rtl8125_xmii_reset_enable; - tp->phy_reset_pending = rtl8125_xmii_reset_pending; - tp->link_ok = rtl8125_xmii_link_ok; - - rc = rtl8125_try_msi(tp); - if (rc < 0) { - dev_err(&pdev->dev, "Can't allocate interrupt\n"); - goto err_out_1; - } -#ifdef ENABLE_PTP_SUPPORT - spin_lock_init(&tp->lock); -#endif - rtl8125_init_software_variable(dev); - - RTL_NET_DEVICE_OPS(rtl8125_netdev_ops); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - SET_ETHTOOL_OPS(dev, &rtl8125_ethtool_ops); -#endif - - dev->watchdog_timeo = RTL8125_TX_TIMEOUT; - dev->irq = rtl8125_get_irq(pdev); - dev->base_addr = (unsigned long) ioaddr; - - rtl8125_init_napi(tp); - -#ifdef CONFIG_R8125_VLAN - if (tp->mcfg != CFG_METHOD_DEFAULT) { - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - dev->vlan_rx_kill_vid = rtl8125_vlan_rx_kill_vid; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - } -#endif - - /* There has been a number of reports that using SG/TSO results in - * tx timeouts. However for a lot of people SG/TSO works fine. - * Therefore disable both features by default, but allow users to - * enable them. Use at own risk! - */ - tp->cp_cmd |= RTL_R16(tp, CPlusCmd); - if (tp->mcfg != CFG_METHOD_DEFAULT) { - dev->features |= NETIF_F_IP_CSUM; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - tp->cp_cmd |= RxChkSum; -#else - dev->features |= NETIF_F_RXCSUM; - dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | - NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | - NETIF_F_HIGHDMA; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) - dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) - dev->hw_features |= NETIF_F_RXALL; - dev->hw_features |= NETIF_F_RXFCS; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; - dev->features |= NETIF_F_IPV6_CSUM; - netif_set_gso_max_size(dev, LSO_64K); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - dev->gso_max_segs = NIC_MAX_PHYS_BUF_COUNT_LSO2; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) - dev->gso_min_segs = NIC_MIN_PHYS_BUF_COUNT; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - -#ifdef ENABLE_RSS_SUPPORT - if (tp->EnableRss) { - dev->hw_features |= NETIF_F_RXHASH; - dev->features |= NETIF_F_RXHASH; - } -#endif - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - AllocateDashShareMemory(dev); -#endif - -#ifdef ENABLE_LIB_SUPPORT - ATOMIC_INIT_NOTIFIER_HEAD(&tp->lib_nh); -#endif - rtl8125_init_all_schedule_work(tp); - - rc = rtl8125_set_real_num_queue(tp); - if (rc < 0) - goto err_out; - - rtl8125_exit_oob(dev); - - rtl8125_powerup_pll(dev); - - rtl8125_hw_init(dev); - - rtl8125_hw_reset(dev); - - /* Get production from EEPROM */ - rtl8125_eeprom_type(tp); - - if (tp->eeprom_type == EEPROM_TYPE_93C46 || tp->eeprom_type == EEPROM_TYPE_93C56) - rtl8125_set_eeprom_sel_low(tp); - - rtl8125_get_mac_address(dev); - - tp->fw_name = rtl_chip_fw_infos[tp->mcfg].fw_name; - - tp->tally_vaddr = dma_alloc_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), - &tp->tally_paddr, GFP_KERNEL); - if (!tp->tally_vaddr) { - rc = -ENOMEM; - goto err_out; - } - - rtl8125_tally_counter_clear(tp); - - pci_set_drvdata(pdev, dev); - - rc = register_netdev(dev); - if (rc) - goto err_out; - - printk(KERN_INFO "%s: This product is covered by one or more of the following patents: US6,570,884, US6,115,776, and US6,327,625.\n", MODULENAME); - - rtl8125_disable_rxdvgate(dev); - - device_set_wakeup_enable(&pdev->dev, tp->wol_enabled); - - netif_carrier_off(dev); - - printk("%s", GPL_CLAIM); - -out: - return rc; - -err_out: - if (tp->tally_vaddr != NULL) { - dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, - tp->tally_paddr); - - tp->tally_vaddr = NULL; - } -#ifdef CONFIG_R8125_NAPI - rtl8125_del_napi(tp); -#endif - rtl8125_disable_msi(pdev, tp); - -err_out_1: - rtl8125_release_board(pdev, dev); - - goto out; -} - -static void __devexit -rtl8125_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8125_private *tp = netdev_priv(dev); - - assert(dev != NULL); - assert(tp != NULL); - - set_bit(R8125_FLAG_DOWN, tp->task_flags); - - rtl8125_cancel_all_schedule_work(tp); - -#ifdef CONFIG_R8125_NAPI - rtl8125_del_napi(tp); -#endif - if (tp->DASH) - rtl8125_driver_stop(tp); - - unregister_netdev(dev); - rtl8125_disable_msi(pdev, tp); -#ifdef ENABLE_R8125_PROCFS - rtl8125_proc_remove(dev); -#endif - if (tp->tally_vaddr != NULL) { - dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, tp->tally_paddr); - tp->tally_vaddr = NULL; - } - - rtl8125_release_board(pdev, dev); - -#ifdef ENABLE_USE_FIRMWARE_FILE - rtl8125_release_firmware(tp); -#endif - - pci_set_drvdata(pdev, NULL); -} - -static void -rtl8125_set_rxbufsize(struct rtl8125_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > ETH_DATA_LEN) ? mtu + ETH_HLEN + 8 + 1 : RX_BUF_SIZE; -} - -static void rtl8125_free_irq(struct rtl8125_private *tp) -{ - int i; - - for (i=0; iirq_nvecs; i++) { - struct r8125_irq *irq = &tp->irq_tbl[i]; - struct r8125_napi *r8125napi = &tp->r8125napi[i]; - - if (irq->requested) { - irq->requested = 0; -#if defined(RTL_USE_NEW_INTR_API) - pci_free_irq(tp->pci_dev, i, r8125napi); -#else - free_irq(irq->vector, r8125napi); -#endif - } - } -} - -static int rtl8125_alloc_irq(struct rtl8125_private *tp) -{ - struct net_device *dev = tp->dev; - int rc = 0; - struct r8125_irq *irq; - struct r8125_napi *r8125napi; - int i = 0; - const int len = sizeof(tp->irq_tbl[0].name); - -#if defined(RTL_USE_NEW_INTR_API) - for (i=0; iirq_nvecs; i++) { - irq = &tp->irq_tbl[i]; - if (tp->features & RTL_FEATURE_MSIX && - tp->HwCurrIsrVer == 2) - irq->handler = rtl8125_interrupt_msix; - else - irq->handler = rtl8125_interrupt; - - r8125napi = &tp->r8125napi[i]; - snprintf(irq->name, len, "%s-%d", dev->name, i); - rc = pci_request_irq(tp->pci_dev, i, irq->handler, NULL, r8125napi, - irq->name); - if (rc) - break; - - irq->vector = pci_irq_vector(tp->pci_dev, i); - irq->requested = 1; - } -#else - unsigned long irq_flags = 0; -#ifdef ENABLE_LIB_SUPPORT - irq_flags |= IRQF_NO_SUSPEND; -#endif - if (tp->features & RTL_FEATURE_MSIX && - tp->HwCurrIsrVer == 2) { - for (i=0; iirq_nvecs; i++) { - irq = &tp->irq_tbl[i]; - irq->handler = rtl8125_interrupt_msix; - r8125napi = &tp->r8125napi[i]; - snprintf(irq->name, len, "%s-%d", dev->name, i); - rc = request_irq(irq->vector, irq->handler, irq_flags, irq->name, r8125napi); - - if (rc) - break; - - irq->requested = 1; - } - } else { - irq = &tp->irq_tbl[0]; - irq->handler = rtl8125_interrupt; - r8125napi = &tp->r8125napi[0]; - snprintf(irq->name, len, "%s-0", dev->name); - if (!(tp->features & RTL_FEATURE_MSIX)) - irq->vector = dev->irq; - irq_flags |= (tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX)) ? 0 : SA_SHIRQ; - rc = request_irq(irq->vector, irq->handler, irq_flags, irq->name, r8125napi); - - if (rc == 0) - irq->requested = 1; - } -#endif - if (rc) - rtl8125_free_irq(tp); - - return rc; -} - -static int rtl8125_alloc_tx_desc(struct rtl8125_private *tp) -{ - struct rtl8125_tx_ring *ring; - struct pci_dev *pdev = tp->pci_dev; - int i; - - for (i = 0; i < tp->num_tx_rings; i++) { - ring = &tp->tx_ring[i]; - ring->TxDescArray = dma_alloc_coherent(&pdev->dev, - (ring->num_tx_desc * sizeof(struct TxDesc)), - &ring->TxPhyAddr, - GFP_KERNEL); - - if (!ring->TxDescArray) - return -1; - } - - return 0; -} - -static int rtl8125_alloc_rx_desc(struct rtl8125_private *tp) -{ - struct rtl8125_rx_ring *ring; - struct pci_dev *pdev = tp->pci_dev; - int i; - - for (i = 0; i < tp->num_rx_rings; i++) { - ring = &tp->rx_ring[i]; - ring->RxDescArray = dma_alloc_coherent(&pdev->dev, - (ring->num_rx_desc * tp->RxDescLength), - &ring->RxPhyAddr, - GFP_KERNEL); - - if (!ring->RxDescArray) - return -1; - } - - return 0; -} - -static int rtl8125_alloc_patch_mem(struct rtl8125_private *tp) -{ - struct pci_dev *pdev = tp->pci_dev; - - if (tp->RequireRduNonStopPatch) { - tp->ShortPacketEmptyBuffer = dma_alloc_coherent(&pdev->dev, - SHORT_PACKET_PADDING_BUF_SIZE, - &tp->ShortPacketEmptyBufferPhy, - GFP_KERNEL); - if (!tp->ShortPacketEmptyBuffer) - return -1; - - memset(tp->ShortPacketEmptyBuffer, 0x0, SHORT_PACKET_PADDING_BUF_SIZE); - } - - return 0; -} - -static void rtl8125_free_tx_desc(struct rtl8125_private *tp) -{ - struct rtl8125_tx_ring *ring; - struct pci_dev *pdev = tp->pci_dev; - int i; - - for (i = 0; i < tp->num_tx_rings; i++) { - ring = &tp->tx_ring[i]; - if (ring->TxDescArray) { - dma_free_coherent(&pdev->dev, - (ring->num_tx_desc * sizeof(struct TxDesc)), - ring->TxDescArray, - ring->TxPhyAddr); - ring->TxDescArray = NULL; - } - } -} - -static void rtl8125_free_rx_desc(struct rtl8125_private *tp) -{ - struct rtl8125_rx_ring *ring; - struct pci_dev *pdev = tp->pci_dev; - int i; - - for (i = 0; i < tp->num_rx_rings; i++) { - ring = &tp->rx_ring[i]; - if (ring->RxDescArray) { - dma_free_coherent(&pdev->dev, - (ring->num_rx_desc * tp->RxDescLength), - ring->RxDescArray, - ring->RxPhyAddr); - ring->RxDescArray = NULL; - } - } -} - -static void rtl8125_free_patch_mem(struct rtl8125_private *tp) -{ - struct pci_dev *pdev = tp->pci_dev; - - if (tp->ShortPacketEmptyBuffer) { - dma_free_coherent(&pdev->dev, - SHORT_PACKET_PADDING_BUF_SIZE, - tp->ShortPacketEmptyBuffer, - tp->ShortPacketEmptyBufferPhy); - tp->ShortPacketEmptyBuffer = NULL; - } -} - -static void rtl8125_free_alloc_resources(struct rtl8125_private *tp) -{ - rtl8125_free_rx_desc(tp); - - rtl8125_free_tx_desc(tp); - - rtl8125_free_patch_mem(tp); -} - -#ifdef ENABLE_USE_FIRMWARE_FILE -static void rtl8125_request_firmware(struct rtl8125_private *tp) -{ - struct rtl8125_fw *rtl_fw; - - /* firmware loaded already or no firmware available */ - if (tp->rtl_fw || !tp->fw_name) - return; - - rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL); - if (!rtl_fw) - return; - - rtl_fw->phy_write = rtl8125_mdio_write; - rtl_fw->phy_read = rtl8125_mdio_read; - rtl_fw->mac_mcu_write = mac_mcu_write; - rtl_fw->mac_mcu_read = mac_mcu_read; - rtl_fw->fw_name = tp->fw_name; - rtl_fw->dev = tp_to_dev(tp); - - if (rtl8125_fw_request_firmware(rtl_fw)) - kfree(rtl_fw); - else - tp->rtl_fw = rtl_fw; -} -#endif - -int rtl8125_open(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int retval; - - retval = -ENOMEM; - -#ifdef ENABLE_R8125_PROCFS - rtl8125_proc_init(dev); -#endif - rtl8125_set_rxbufsize(tp, dev); - /* - * Rx and Tx descriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - if (rtl8125_alloc_tx_desc(tp) < 0 || rtl8125_alloc_rx_desc(tp) < 0) - goto err_free_all_allocated_mem; - - retval = rtl8125_init_ring(dev); - if (retval < 0) - goto err_free_all_allocated_mem; - - retval = rtl8125_alloc_patch_mem(tp); - if (retval < 0) - goto err_free_all_allocated_mem; - - retval = rtl8125_alloc_irq(tp); - if (retval < 0) - goto err_free_all_allocated_mem; - - if (netif_msg_probe(tp)) { - printk(KERN_INFO "%s: 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], dev->irq); - } - -#ifdef ENABLE_USE_FIRMWARE_FILE - rtl8125_request_firmware(tp); -#endif - pci_set_master(tp->pci_dev); - -#ifdef CONFIG_R8125_NAPI - rtl8125_enable_napi(tp); -#endif - - rtl8125_exit_oob(dev); - - rtl8125_up(dev); - -#ifdef ENABLE_PTP_SUPPORT - if (tp->EnablePtp) - rtl8125_ptp_init(tp); -#endif - clear_bit(R8125_FLAG_DOWN, tp->task_flags); - - if (tp->resume_not_chg_speed) - rtl8125_check_link_status(dev); - else - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - - if (tp->esd_flag == 0) { - //rtl8125_request_esd_timer(dev); - - rtl8125_schedule_esd_work(tp); - } - - //rtl8125_request_link_timer(dev); - - rtl8125_enable_hw_linkchg_interrupt(tp); - -out: - - return retval; - -err_free_all_allocated_mem: - rtl8125_free_alloc_resources(tp); - - goto out; -} - -static void -set_offset70F(struct rtl8125_private *tp, u8 setting) -{ - u32 csi_tmp; - u32 temp = (u32)setting; - temp = temp << 24; - /*set PCI configuration space offset 0x70F to setting*/ - /*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/ - - csi_tmp = rtl8125_csi_read(tp, 0x70c) & 0x00ffffff; - rtl8125_csi_write(tp, 0x70c, csi_tmp | temp); -} - -static void -set_offset79(struct rtl8125_private *tp, u8 setting) -{ - //Set PCI configuration space offset 0x79 to setting - - struct pci_dev *pdev = tp->pci_dev; - u8 device_control; - - if (hwoptimize & HW_PATCH_SOC_LAN) return; - - pci_read_config_byte(pdev, 0x79, &device_control); - device_control &= ~0x70; - device_control |= setting; - pci_write_config_byte(pdev, 0x79, device_control); -} - -void -rtl8125_hw_set_rx_packet_filter(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } -#else - struct netdev_hw_addr *ha; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } -#endif - } - - if (dev->features & NETIF_F_RXALL) - rx_mode |= (AcceptErr | AcceptRunt); - - tmp = mc_filter[0]; - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(tmp); - - tmp = tp->rtl8125_rx_config | rx_mode | (RTL_R32(tp, RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - RTL_W32(tp, RxConfig, tmp); - RTL_W32(tp, MAR0 + 0, mc_filter[0]); - RTL_W32(tp, MAR0 + 4, mc_filter[1]); -} - -static void -rtl8125_set_rx_mode(struct net_device *dev) -{ - rtl8125_hw_set_rx_packet_filter(dev); -} - -void -rtl8125_set_rx_q_num(struct rtl8125_private *tp, - unsigned int num_rx_queues) -{ - u16 q_ctrl; - u16 rx_q_num; - - rx_q_num = (u16)ilog2(num_rx_queues); - rx_q_num &= (BIT_0 | BIT_1 | BIT_2); - rx_q_num <<= 2; - q_ctrl = RTL_R16(tp, Q_NUM_CTRL_8125); - q_ctrl &= ~(BIT_2 | BIT_3 | BIT_4); - q_ctrl |= rx_q_num; - RTL_W16(tp, Q_NUM_CTRL_8125, q_ctrl); -} - -void -rtl8125_set_tx_q_num(struct rtl8125_private *tp, - unsigned int num_tx_queues) -{ - u16 mac_ocp_data; - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE63E); - mac_ocp_data &= ~(BIT_11 | BIT_10); - mac_ocp_data |= ((ilog2(num_tx_queues) & 0x03) << 10); - rtl8125_mac_ocp_write(tp, 0xE63E, mac_ocp_data); -} - -void -rtl8125_hw_config(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - u16 mac_ocp_data; - int i; - - RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); - - rtl8125_hw_reset(dev); - - rtl8125_enable_cfg9346_write(tp); - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - break; - } - - //clear io_rdy_l23 - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~BIT_1); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - //IntMITI_0-IntMITI_31 - for (i=0xA00; i<0xB00; i+=4) - RTL_W32(tp, i, 0x00000000); - break; - } - - //keep magic packet only - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B6); - mac_ocp_data &= BIT_0; - rtl8125_mac_ocp_write(tp, 0xC0B6, mac_ocp_data); - break; - } - - rtl8125_tally_counter_addr_fill(tp); - - rtl8125_enable_extend_tally_couter(tp); - - rtl8125_desc_addr_fill(tp); - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(tp, TxConfig, (TX_DMA_BURST_unlimited << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - if (tp->EnableTxNoClose) - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | BIT_6)); - - if (tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_4 || - tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_6 || - tp->mcfg == CFG_METHOD_7) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - RTL_W16(tp, 0x382, 0x221B); - -#ifdef ENABLE_RSS_SUPPORT - rtl8125_config_rss(tp); -#else - RTL_W32(tp, RSS_CTRL_8125, 0x00); -#endif - rtl8125_set_rx_q_num(tp, rtl8125_tot_rx_rings(tp)); - - RTL_W8(tp, Config1, RTL_R8(tp, Config1) & ~0x10); - - rtl8125_mac_ocp_write(tp, 0xC140, 0xFFFF); - rtl8125_mac_ocp_write(tp, 0xC142, 0xFFFF); - - //new tx desc format - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB58); - mac_ocp_data |= (BIT_0); - rtl8125_mac_ocp_write(tp, 0xEB58, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE614); - mac_ocp_data &= ~( BIT_10 | BIT_9 | BIT_8); - if (tp->mcfg == CFG_METHOD_4 || tp->mcfg == CFG_METHOD_5 || - tp->mcfg == CFG_METHOD_7) - mac_ocp_data |= ((2 & 0x07) << 8); - else - mac_ocp_data |= ((3 & 0x07) << 8); - rtl8125_mac_ocp_write(tp, 0xE614, mac_ocp_data); - - rtl8125_set_tx_q_num(tp, rtl8125_tot_tx_rings(tp)); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE63E); - mac_ocp_data &= ~(BIT_5 | BIT_4); - if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_6) - mac_ocp_data |= ((0x02 & 0x03) << 4); - rtl8125_mac_ocp_write(tp, 0xE63E, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B4); - mac_ocp_data &= ~BIT_0; - rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); - mac_ocp_data |= BIT_0; - rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xC0B4); - mac_ocp_data |= (BIT_3|BIT_2); - rtl8125_mac_ocp_write(tp, 0xC0B4, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB6A); - mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= (BIT_5 | BIT_4 | BIT_1 | BIT_0); - rtl8125_mac_ocp_write(tp, 0xEB6A, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEB50); - mac_ocp_data &= ~(BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5); - mac_ocp_data |= (BIT_6); - rtl8125_mac_ocp_write(tp, 0xEB50, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE056); - mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4); - //mac_ocp_data |= (BIT_4 | BIT_5); - rtl8125_mac_ocp_write(tp, 0xE056, mac_ocp_data); - - RTL_W8(tp, TDFNR, 0x10); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_7); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xE040); - mac_ocp_data &= ~(BIT_12); - rtl8125_mac_ocp_write(tp, 0xE040, mac_ocp_data); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEA1C); - mac_ocp_data &= ~(BIT_1 | BIT_0); - mac_ocp_data |= (BIT_0); - rtl8125_mac_ocp_write(tp, 0xEA1C, mac_ocp_data); - - rtl8125_mac_ocp_write(tp, 0xE0C0, 0x4000); - - SetMcuAccessRegBit(tp, 0xE052, (BIT_6 | BIT_5)); - ClearMcuAccessRegBit(tp, 0xE052, BIT_3 | BIT_7); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xD430); - mac_ocp_data &= ~(BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= 0x45F; - rtl8125_mac_ocp_write(tp, 0xD430, mac_ocp_data); - - //rtl8125_mac_ocp_write(tp, 0xE0C0, 0x4F87); - if (!tp->DASH) - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6 | BIT_7); - else - RTL_W8(tp, 0xD0, (RTL_R8(tp, 0xD0) & ~BIT_6) | BIT_7); - - if (tp->mcfg == CFG_METHOD_2 || tp->mcfg == CFG_METHOD_3 || - tp->mcfg == CFG_METHOD_6) - RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) | BIT_0); - - rtl8125_disable_eee_plus(tp); - - mac_ocp_data = rtl8125_mac_ocp_read(tp, 0xEA1C); - mac_ocp_data &= ~(BIT_2); - rtl8125_mac_ocp_write(tp, 0xEA1C, mac_ocp_data); - - SetMcuAccessRegBit(tp, 0xEB54, BIT_0); - udelay(1); - ClearMcuAccessRegBit(tp, 0xEB54, BIT_0); - RTL_W16(tp, 0x1880, RTL_R16(tp, 0x1880) & ~(BIT_4 | BIT_5)); - } - - /* csum offload command for RTL8125 */ - tp->tx_tcp_csum_cmd = TxTCPCS_C; - tp->tx_udp_csum_cmd = TxUDPCS_C; - tp->tx_ip_csum_cmd = TxIPCS_C; - tp->tx_ipv6_csum_cmd = TxIPV6F_C; - - /* config interrupt type for RTL8125B */ - if (tp->HwSuppIsrVer == 2) - rtl8125_hw_set_interrupt_type(tp, tp->HwCurrIsrVer); - - //other hw parameters - rtl8125_hw_clear_timer_int(dev); - - rtl8125_hw_clear_int_miti(dev); - - if (tp->RequireRduNonStopPatch && - tp->ShortPacketEmptyBuffer) { - RTL_W32(tp, RSS_INDIRECTION_TBL_8125_V2, ((u64)tp->ShortPacketEmptyBufferPhy & DMA_BIT_MASK(32))); - RTL_W32(tp, RSS_INDIRECTION_TBL_8125_V2 + 4, ((u64)tp->ShortPacketEmptyBufferPhy >> 32)); - } - - if (tp->use_timer_interrrupt && - (tp->HwCurrIsrVer == 2) && - (tp->HwSuppIntMitiVer == 4) && - (tp->features & RTL_FEATURE_MSIX)) { - int i; - for (i = 0; i < tp->irq_nvecs; i++) - rtl8125_hw_set_timer_int_8125(tp, i, timer_count_v2); - } - - rtl8125_enable_exit_l1_mask(tp); - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - rtl8125_mac_ocp_write(tp, 0xE098, 0xC302); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - if (aspm) { - rtl8125_init_pci_offset_99(tp); - } - break; - } - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - if (aspm) { - rtl8125_init_pci_offset_180(tp); - } - break; - } - - tp->cp_cmd &= ~(EnableBist | Macdbgo_oe | Force_halfdup | - Force_rxflow_en | Force_txflow_en | Cxpl_dbg_sel | - ASF | Macdbgo_sel); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - RTL_W16(tp, CPlusCmd, tp->cp_cmd); -#else - rtl8125_hw_set_features(dev, dev->features); -#endif - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: { - int timeout; - for (timeout = 0; timeout < 10; timeout++) { - if ((rtl8125_mac_ocp_read(tp, 0xE00E) & BIT_13)==0) - break; - mdelay(1); - } - } - break; - } - - RTL_W16(tp, RxMaxSize, tp->rx_buf_sz); - - rtl8125_disable_rxdvgate(dev); - - if (!tp->pci_cfg_is_read) { - pci_read_config_byte(pdev, PCI_COMMAND, &tp->pci_cfg_space.cmd); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &tp->pci_cfg_space.io_base_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0 + 2, &tp->pci_cfg_space.io_base_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &tp->pci_cfg_space.mem_base_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &tp->pci_cfg_space.mem_base_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &tp->pci_cfg_space.resv_0x1c_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &tp->pci_cfg_space.resv_0x1c_h); - pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tp->pci_cfg_space.ilr); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &tp->pci_cfg_space.resv_0x20_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &tp->pci_cfg_space.resv_0x20_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &tp->pci_cfg_space.resv_0x24_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &tp->pci_cfg_space.resv_0x24_h); - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->pci_cfg_space.resv_0x2c_l); - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &tp->pci_cfg_space.resv_0x2c_h); - if (tp->HwPcieSNOffset > 0) { - tp->pci_cfg_space.pci_sn_l = rtl8125_csi_read(tp, tp->HwPcieSNOffset); - tp->pci_cfg_space.pci_sn_h = rtl8125_csi_read(tp, tp->HwPcieSNOffset + 4); - } - - tp->pci_cfg_is_read = 1; - } - - /* Set Rx packet filter */ - rtl8125_hw_set_rx_packet_filter(dev); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH && !tp->dash_printer_enabled) - NICChkTypeEnableDashInterrupt(tp); -#endif - - switch (tp->mcfg) { - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - if (aspm) { - RTL_W8(tp, Config5, RTL_R8(tp, Config5) | BIT_0); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) | BIT_7); - } else { - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~BIT_7); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_0); - } - break; - } - - rtl8125_disable_cfg9346_write(tp); - - udelay(10); -} - -void -rtl8125_hw_start(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb); - - rtl8125_enable_hw_interrupt(tp); - - rtl8125_lib_reset_complete(tp); -} - -static int -rtl8125_change_mtu(struct net_device *dev, - int new_mtu) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret = 0; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) - if (new_mtu < ETH_MIN_MTU) - return -EINVAL; - else if (new_mtu > tp->max_jumbo_frame_size) - new_mtu = tp->max_jumbo_frame_size; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) - - dev->mtu = new_mtu; - - if (!netif_running(dev)) - goto out; - - rtl8125_down(dev); - - rtl8125_set_rxbufsize(tp, dev); - - ret = rtl8125_init_ring(dev); - - if (ret < 0) - goto err_out; - -#ifdef CONFIG_R8125_NAPI - rtl8125_enable_napi(tp); -#endif//CONFIG_R8125_NAPI - - //netif_tx_stop_all_queues(dev); - //netif_carrier_off(dev); - rtl8125_hw_config(dev); - rtl8125_enable_hw_linkchg_interrupt(tp); - - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - - //mod_timer(&tp->esd_timer, jiffies + RTL8125_ESD_TIMEOUT); - //mod_timer(&tp->link_timer, jiffies + RTL8125_LINK_TIMEOUT); -out: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) - netdev_update_features(dev); -#endif - -err_out: - return ret; -} - -static void -rtl8125_free_rx_skb(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct sk_buff **sk_buff, - struct RxDesc *desc, - const u32 cur_rx) -{ - struct pci_dev *pdev = tp->pci_dev; - - dma_unmap_single(&pdev->dev, ring->RxDescPhyAddr[cur_rx], tp->rx_buf_sz, - DMA_FROM_DEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8125_make_unusable_by_asic(tp, desc); -} - -static inline void -rtl8125_mark_to_asic_v3(struct RxDescV3 *descv3, - u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(descv3->RxDescNormalDDWord4.opts1) & RingEnd; - - WRITE_ONCE(descv3->RxDescNormalDDWord4.opts1, cpu_to_le32(DescOwn | eor | rx_buf_sz)); -} - -void -rtl8125_mark_to_asic(struct rtl8125_private *tp, - struct RxDesc *desc, - u32 rx_buf_sz) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - rtl8125_mark_to_asic_v3((struct RxDescV3 *)desc, rx_buf_sz); - else { - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - WRITE_ONCE(desc->opts1, cpu_to_le32(DescOwn | eor | rx_buf_sz)); - } -} - -static inline void -rtl8125_map_to_asic(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct RxDesc *desc, - dma_addr_t mapping, - u32 rx_buf_sz, - const u32 cur_rx) -{ - ring->RxDescPhyAddr[cur_rx] = mapping; - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - ((struct RxDescV3 *)desc)->addr = cpu_to_le64(mapping); - else - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8125_mark_to_asic(tp, desc, rx_buf_sz); -} - -static int -rtl8125_alloc_rx_skb(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct sk_buff **sk_buff, - struct RxDesc *desc, - int rx_buf_sz, - const u32 cur_rx, - u8 in_intr) -{ - struct sk_buff *skb; - dma_addr_t mapping; - int ret = 0; - - if (in_intr) - skb = RTL_ALLOC_SKB_INTR(&tp->r8125napi[ring->index].napi, rx_buf_sz + RTK_RX_ALIGN); - else - skb = dev_alloc_skb(rx_buf_sz + RTK_RX_ALIGN); - - if (unlikely(!skb)) - goto err_out; - - skb_reserve(skb, RTK_RX_ALIGN); - - mapping = dma_map_single(tp_to_dev(tp), skb->data, rx_buf_sz, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); - goto err_out; - } - - *sk_buff = skb; - rtl8125_map_to_asic(tp, ring, desc, mapping, rx_buf_sz, cur_rx); -out: - return ret; - -err_out: - if (skb) - dev_kfree_skb(skb); - ret = -ENOMEM; - rtl8125_make_unusable_by_asic(tp, desc); - goto out; -} - -static void -_rtl8125_rx_clear(struct rtl8125_private *tp, struct rtl8125_rx_ring *ring) -{ - int i; - - for (i = 0; i < ring->num_rx_desc; i++) { - if (ring->Rx_skbuff[i]) { - rtl8125_free_rx_skb(tp, - ring, - ring->Rx_skbuff + i, - rtl8125_get_rxdesc(tp, ring->RxDescArray, i), - i); - ring->Rx_skbuff[i] = NULL; - } - } -} - -void -rtl8125_rx_clear(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_rx_rings; i++) - _rtl8125_rx_clear(tp, &tp->rx_ring[i]); -} - -static u32 -rtl8125_rx_fill(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct net_device *dev, - u32 start, - u32 end, - u8 in_intr) -{ - u32 cur; - - for (cur = start; end - cur > 0; cur++) { - int ret, i = cur % ring->num_rx_desc; - - if (ring->Rx_skbuff[i]) - continue; - - ret = rtl8125_alloc_rx_skb(tp, - ring, - ring->Rx_skbuff + i, - rtl8125_get_rxdesc(tp, ring->RxDescArray, i), - tp->rx_buf_sz, - i, - in_intr - ); - if (ret < 0) - break; - } - return cur - start; -} - -static inline void -rtl8125_mark_as_last_descriptor_8125(struct RxDescV3 *descv3) -{ - descv3->RxDescNormalDDWord4.opts1 |= cpu_to_le32(RingEnd); -} - -static inline void -rtl8125_mark_as_last_descriptor(struct rtl8125_private *tp, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - rtl8125_mark_as_last_descriptor_8125((struct RxDescV3 *)desc); - else - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void -rtl8125_desc_addr_fill(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_tx_rings; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - RTL_W32(tp, ring->tdsar_reg, ((u64)ring->TxPhyAddr & DMA_BIT_MASK(32))); - RTL_W32(tp, ring->tdsar_reg + 4, ((u64)ring->TxPhyAddr >> 32)); - } - - for (i = 0; i < tp->num_rx_rings; i++) { - struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; - RTL_W32(tp, ring->rdsar_reg, ((u64)ring->RxPhyAddr & DMA_BIT_MASK(32))); - RTL_W32(tp, ring->rdsar_reg + 4, ((u64)ring->RxPhyAddr >> 32)); - } -} - -static void -rtl8125_tx_desc_init(struct rtl8125_private *tp) -{ - int i = 0; - - for (i = 0; i < tp->num_tx_rings; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - memset(ring->TxDescArray, 0x0, (ring->num_tx_desc * sizeof(struct TxDesc))); - - ring->TxDescArray[ring->num_tx_desc - 1].opts1 = cpu_to_le32(RingEnd); - } -} - -static void -rtl8125_rx_desc_init(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_rx_rings; i++) { - struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; - memset(ring->RxDescArray, 0x0, - (ring->num_rx_desc * tp->RxDescLength)); - } -} - -int -rtl8125_init_ring(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - - rtl8125_init_ring_indexes(tp); - - rtl8125_tx_desc_init(tp); - rtl8125_rx_desc_init(tp); - - for (i = 0; i < tp->num_tx_rings; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - memset(ring->tx_skb, 0x0, sizeof(ring->tx_skb)); - } - - for (i = 0; i < tp->num_rx_rings; i++) { - struct rtl8125_rx_ring *ring = &tp->rx_ring[i]; - - memset(ring->Rx_skbuff, 0x0, sizeof(ring->Rx_skbuff)); - if (rtl8125_rx_fill(tp, ring, dev, 0, ring->num_rx_desc, 0) != ring->num_rx_desc) - goto err_out; - - rtl8125_mark_as_last_descriptor(tp, rtl8125_get_rxdesc(tp, ring->RxDescArray, ring->num_rx_desc - 1)); - } - - return 0; - -err_out: - rtl8125_rx_clear(tp); - return -ENOMEM; -} - -static void -rtl8125_unmap_tx_skb(struct pci_dev *pdev, - struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE); - - desc->opts1 = cpu_to_le32(RTK_MAGIC_DEBUG_VALUE); - desc->opts2 = 0x00; - desc->addr = RTL8125_MAGIC_NUMBER; - tx_skb->len = 0; -} - -static void -rtl8125_tx_clear_range(struct rtl8125_private *tp, - struct rtl8125_tx_ring *ring, - u32 start, - unsigned int n) -{ - unsigned int i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - struct net_device *dev = tp->dev; -#endif - - for (i = 0; i < n; i++) { - unsigned int entry = (start + i) % ring->num_tx_desc; - struct ring_info *tx_skb = ring->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8125_unmap_tx_skb(tp->pci_dev, tx_skb, - ring->TxDescArray + entry); - if (skb) { - RTLDEV->stats.tx_dropped++; - dev_kfree_skb_any(skb); - tx_skb->skb = NULL; - } - } - } -} - -void -rtl8125_tx_clear(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_tx_rings; i++) { - struct rtl8125_tx_ring *ring = &tp->tx_ring[i]; - rtl8125_tx_clear_range(tp, ring, ring->dirty_tx, ring->num_tx_desc); - ring->cur_tx = ring->dirty_tx = 0; - } -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8125_schedule_reset_work(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - set_bit(R8125_FLAG_TASK_RESET_PENDING, tp->task_flags); - schedule_delayed_work(&tp->reset_task, 4); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -} - -static void rtl8125_schedule_esd_work(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - set_bit(R8125_FLAG_TASK_ESD_CHECK_PENDING, tp->task_flags); - schedule_delayed_work(&tp->esd_task, RTL8125_ESD_TIMEOUT); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -} - -static void rtl8125_schedule_linkchg_work(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - set_bit(R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, tp->task_flags); - schedule_delayed_work(&tp->linkchg_task, 4); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -} - -#define rtl8125_cancel_schedule_reset_work(a) -#define rtl8125_cancel_schedule_esd_work(a) -#define rtl8125_cancel_schedule_linkchg_work(a) - -#else -static void rtl8125_schedule_reset_work(struct rtl8125_private *tp) -{ - set_bit(R8125_FLAG_TASK_RESET_PENDING, tp->task_flags); - schedule_delayed_work(&tp->reset_task, 4); -} - -static void rtl8125_cancel_schedule_reset_work(struct rtl8125_private *tp) -{ - struct work_struct *work = &tp->reset_task.work; - - if (!work->func) return; - - cancel_delayed_work_sync(&tp->reset_task); -} - -static void rtl8125_schedule_esd_work(struct rtl8125_private *tp) -{ - set_bit(R8125_FLAG_TASK_ESD_CHECK_PENDING, tp->task_flags); - schedule_delayed_work(&tp->esd_task, RTL8125_ESD_TIMEOUT); -} - -static void rtl8125_cancel_schedule_esd_work(struct rtl8125_private *tp) -{ - struct work_struct *work = &tp->esd_task.work; - - if (!work->func) return; - - cancel_delayed_work_sync(&tp->esd_task); -} - -static void rtl8125_schedule_linkchg_work(struct rtl8125_private *tp) -{ - set_bit(R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, tp->task_flags); - schedule_delayed_work(&tp->linkchg_task, RTL8125_ESD_TIMEOUT); -} - -static void rtl8125_cancel_schedule_linkchg_work(struct rtl8125_private *tp) -{ - struct work_struct *work = &tp->linkchg_task.work; - - if (!work->func) return; - - cancel_delayed_work_sync(&tp->linkchg_task); -} -#endif - -static void rtl8125_init_all_schedule_work(struct rtl8125_private *tp) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_WORK(&tp->reset_task, rtl8125_reset_task, dev); - INIT_WORK(&tp->esd_task, rtl8125_esd_task, dev); - INIT_WORK(&tp->linkchg_task, rtl8125_linkchg_task, dev); -#else - INIT_DELAYED_WORK(&tp->reset_task, rtl8125_reset_task); - INIT_DELAYED_WORK(&tp->esd_task, rtl8125_esd_task); - INIT_DELAYED_WORK(&tp->linkchg_task, rtl8125_linkchg_task); -#endif -} - -static void rtl8125_cancel_all_schedule_work(struct rtl8125_private *tp) -{ - rtl8125_cancel_schedule_reset_work(tp); - rtl8125_cancel_schedule_esd_work(tp); - rtl8125_cancel_schedule_linkchg_work(tp); -} - -static void -rtl8125_wait_for_irq_complete(struct rtl8125_private *tp) -{ - if (tp->features & RTL_FEATURE_MSIX) { - int i; - for (i = 0; i < tp->irq_nvecs; i++) - synchronize_irq(tp->irq_tbl[i].vector); - } else { - synchronize_irq(tp->dev->irq); - } -} - -static void -_rtl8125_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - /* Wait for any pending NAPI task to complete */ -#ifdef CONFIG_R8125_NAPI - rtl8125_disable_napi(tp); -#endif//CONFIG_R8125_NAPI - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,67) - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_net(); -#endif - - rtl8125_irq_mask_and_ack(tp); - - rtl8125_wait_for_irq_complete(tp); -} - -static void -rtl8125_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - //suppress unused variable - (void)(tp); - - _rtl8125_wait_for_quiescence(dev); - -#ifdef CONFIG_R8125_NAPI - rtl8125_enable_napi(tp); -#endif//CONFIG_R8125_NAPI -} - -static int rtl8125_rx_nostuck(struct rtl8125_private *tp) -{ - int i, ret = 1; - for (i = 0; i < tp->num_rx_rings; i++) - ret &= (tp->rx_ring[i].dirty_rx == tp->rx_ring[i].cur_rx); - return ret; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8125_reset_task(void *_data) -{ - struct net_device *dev = _data; - struct rtl8125_private *tp = netdev_priv(dev); -#else -static void rtl8125_reset_task(struct work_struct *work) -{ - struct rtl8125_private *tp = - container_of(work, struct rtl8125_private, reset_task.work); - struct net_device *dev = tp->dev; -#endif - u32 budget = ~(u32)0; - int i; - - rtnl_lock(); - - if (!netif_running(dev) || - test_bit(R8125_FLAG_DOWN, tp->task_flags) || - !test_and_clear_bit(R8125_FLAG_TASK_RESET_PENDING, tp->task_flags)) - goto out_unlock; - - rtl8125_wait_for_quiescence(dev); - - for (i = 0; i < tp->num_rx_rings; i++) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], &budget); -#else - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[i], budget); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - } - - netif_tx_stop_all_queues(dev); - netif_carrier_off(dev); - rtl8125_hw_reset(dev); - - rtl8125_tx_clear(tp); - - if (rtl8125_rx_nostuck(tp)) { - rtl8125_rx_clear(tp); - rtl8125_init_ring(dev); -#ifdef ENABLE_PTP_SUPPORT - rtl8125_ptp_reset(tp); -#endif - if (tp->resume_not_chg_speed) { - _rtl8125_check_link_status(dev); - - tp->resume_not_chg_speed = 0; - } else { - rtl8125_enable_hw_linkchg_interrupt(tp); - - rtl8125_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - } - } else { - if (unlikely(net_ratelimit())) { - struct rtl8125_private *tp = netdev_priv(dev); - - if (netif_msg_intr(tp)) { - printk(PFX KERN_EMERG - "%s: Rx buffers shortage\n", dev->name); - } - } - rtl8125_schedule_reset_work(tp); - } - -out_unlock: - rtnl_unlock(); -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8125_esd_task(void *_data) -{ - struct net_device *dev = _data; - struct rtl8125_private *tp = netdev_priv(dev); -#else -static void rtl8125_esd_task(struct work_struct *work) -{ - struct rtl8125_private *tp = - container_of(work, struct rtl8125_private, esd_task.work); - struct net_device *dev = tp->dev; -#endif - rtnl_lock(); - - if (!netif_running(dev) || - test_bit(R8125_FLAG_DOWN, tp->task_flags) || - !test_and_clear_bit(R8125_FLAG_TASK_ESD_CHECK_PENDING, tp->task_flags)) - goto out_unlock; - - rtl8125_esd_checker(tp); - - rtl8125_schedule_esd_work(tp); - -out_unlock: - rtnl_unlock(); -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8125_linkchg_task(void *_data) -{ - struct net_device *dev = _data; - //struct rtl8125_private *tp = netdev_priv(dev); -#else -static void rtl8125_linkchg_task(struct work_struct *work) -{ - struct rtl8125_private *tp = - container_of(work, struct rtl8125_private, linkchg_task.work); - struct net_device *dev = tp->dev; -#endif - rtnl_lock(); - - if (!netif_running(dev) || - test_bit(R8125_FLAG_DOWN, tp->task_flags) || - !test_and_clear_bit(R8125_FLAG_TASK_LINKCHG_CHECK_PENDING, tp->task_flags)) - goto out_unlock; - - rtl8125_check_link_status(dev); - -out_unlock: - rtnl_unlock(); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static void -rtl8125_tx_timeout(struct net_device *dev, unsigned int txqueue) -#else -static void -rtl8125_tx_timeout(struct net_device *dev) -#endif -{ - struct rtl8125_private *tp = netdev_priv(dev); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8125_schedule_reset_work(tp); -} - -static u32 -rtl8125_get_txd_opts1(struct rtl8125_tx_ring *ring, - u32 opts1, - u32 len, - unsigned int entry) -{ - u32 status = opts1 | len; - - if (entry == ring->num_tx_desc - 1) - status |= RingEnd; - - return status; -} - -static int -rtl8125_xmit_frags(struct rtl8125_private *tp, - struct rtl8125_tx_ring *ring, - struct sk_buff *skb, - const u32 *opts) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc *txd = NULL; - const unsigned char nr_frags = info->nr_frags; - unsigned long PktLenCnt = 0; - bool LsoPatchEnabled = FALSE; - - entry = ring->cur_tx; - for (cur_frag = 0; cur_frag < nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % ring->num_tx_desc; - - txd = ring->TxDescArray + entry; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; -#else - len = skb_frag_size(frag); - addr = skb_frag_address(frag); -#endif - if (tp->RequireLSOPatch && - (cur_frag == nr_frags - 1) && - (opts[0] & (GiantSendv4|GiantSendv6)) && - PktLenCnt < ETH_FRAME_LEN && - len > 1) { - len -= 1; - mapping = dma_map_single(tp_to_dev(tp), addr, len, DMA_TO_DEVICE); - - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, tp->dev, - "Failed to map TX fragments DMA!\n"); - goto err_out; - } - - /* anti gcc 2.95.3 bugware (sic) */ - status = rtl8125_get_txd_opts1(ring, opts[0], len, entry); - - txd->addr = cpu_to_le64(mapping); - - ring->tx_skb[entry].len = len; - - txd->opts2 = cpu_to_le32(opts[1]); - wmb(); - txd->opts1 = cpu_to_le32(status); - - //second txd - addr += len; - len = 1; - entry = (entry + 1) % ring->num_tx_desc; - txd = ring->TxDescArray + entry; - cur_frag += 1; - - LsoPatchEnabled = TRUE; - } - - mapping = dma_map_single(tp_to_dev(tp), addr, len, DMA_TO_DEVICE); - - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, tp->dev, - "Failed to map TX fragments DMA!\n"); - goto err_out; - } - - /* anti gcc 2.95.3 bugware (sic) */ - status = rtl8125_get_txd_opts1(ring, opts[0], len, entry); - if (cur_frag == (nr_frags - 1) || LsoPatchEnabled == TRUE) { - //ring->tx_skb[entry].skb = skb; - status |= LastFrag; - } - - txd->addr = cpu_to_le64(mapping); - - ring->tx_skb[entry].len = len; - - txd->opts2 = cpu_to_le32(opts[1]); - wmb(); - txd->opts1 = cpu_to_le32(status); - - PktLenCnt += len; - } - - return cur_frag; - -err_out: - rtl8125_tx_clear_range(tp, ring, ring->cur_tx + 1, cur_frag); - return -EIO; -} - -static inline -__be16 get_protocol(struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) - return vlan_get_protocol(skb); -#else - __be16 protocol; - - if (skb->protocol == htons(ETH_P_8021Q)) - protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; - else - protocol = skb->protocol; - - return protocol; -#endif -} - -static inline -u8 rtl8125_get_l4_protocol(struct sk_buff *skb) -{ - int no = skb_network_offset(skb); - struct ipv6hdr *i6h, _i6h; - struct iphdr *ih, _ih; - u8 ip_protocol = IPPROTO_RAW; - - switch (get_protocol(skb)) { - case __constant_htons(ETH_P_IP): - ih = skb_header_pointer(skb, no, sizeof(_ih), &_ih); - if (ih) - ip_protocol = ih->protocol; - break; - case __constant_htons(ETH_P_IPV6): - i6h = skb_header_pointer(skb, no, sizeof(_i6h), &_i6h); - if (i6h) - ip_protocol = i6h->nexthdr; - break; - } - - return ip_protocol; -} - -static bool rtl8125_skb_pad_with_len(struct sk_buff *skb, unsigned int len) -{ - if (skb_padto(skb, len)) - return false; - skb_put(skb, len - skb->len); - return true; -} - -static bool rtl8125_skb_pad(struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) - return rtl8125_skb_pad_with_len(skb, ETH_ZLEN); -#else - return !eth_skb_pad(skb); -#endif -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) -/* msdn_giant_send_check() - * According to the document of microsoft, the TCP Pseudo Header excludes the - * packet length for IPv6 TCP large packets. - */ -static int msdn_giant_send_check(struct sk_buff *skb) -{ - const struct ipv6hdr *ipv6h; - struct tcphdr *th; - int ret; - - ret = skb_cow_head(skb, 0); - if (ret) - return ret; - - ipv6h = ipv6_hdr(skb); - th = tcp_hdr(skb); - - th->check = 0; - th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0); - - return ret; -} -#endif - -#define MIN_PATCH_LEN (47) -static u32 -rtl8125_get_patch_pad_len(struct sk_buff *skb) -{ - u32 pad_len = 0; - int trans_data_len; - u32 hdr_len; - u32 pkt_len = skb->len; - u8 ip_protocol; - bool has_trans = skb_transport_header_was_set(skb); - - if (!(has_trans && (pkt_len < 175))) //128 + MIN_PATCH_LEN - goto no_padding; - - ip_protocol = rtl8125_get_l4_protocol(skb); - if (!(ip_protocol == IPPROTO_TCP || ip_protocol == IPPROTO_UDP)) - goto no_padding; - - trans_data_len = pkt_len - - (skb->transport_header - - skb_headroom(skb)); - if (ip_protocol == IPPROTO_UDP) { - if (trans_data_len > 3 && trans_data_len < MIN_PATCH_LEN) { - u16 dest_port = 0; - - skb_copy_bits(skb, skb->transport_header - skb_headroom(skb) + 2, &dest_port, 2); - dest_port = ntohs(dest_port); - - if (dest_port == 0x13f || - dest_port == 0x140) { - pad_len = MIN_PATCH_LEN - trans_data_len; - goto out; - } - } - } - - hdr_len = 0; - if (ip_protocol == IPPROTO_TCP) - hdr_len = 20; - else if (ip_protocol == IPPROTO_UDP) - hdr_len = 8; - if (trans_data_len < hdr_len) - pad_len = hdr_len - trans_data_len; - -out: - if ((pkt_len + pad_len) < ETH_ZLEN) - pad_len = ETH_ZLEN - pkt_len; - - return pad_len; - -no_padding: - - return 0; -} - -static bool -rtl8125_tso_csum(struct sk_buff *skb, - struct net_device *dev, - u32 *opts) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned long large_send = 0; - u32 csum_cmd = 0; - u8 sw_calc_csum = false; - u8 check_patch_required = true; - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) - u32 mss = skb_shinfo(skb)->tso_size; -#else - u32 mss = skb_shinfo(skb)->gso_size; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) - - /* TCP Segmentation Offload (or TCP Large Send) */ - if (mss) { - u32 transport_offset = (u32)skb_transport_offset(skb); - assert((transport_offset%2) == 0); - switch (get_protocol(skb)) { - case __constant_htons(ETH_P_IP): - if (transport_offset <= GTTCPHO_MAX) { - opts[0] |= GiantSendv4; - opts[0] |= transport_offset << GTTCPHO_SHIFT; - opts[1] |= min(mss, MSS_MAX) << 18; - large_send = 1; - } - break; - case __constant_htons(ETH_P_IPV6): -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) - if (msdn_giant_send_check(skb)) - return false; -#endif - if (transport_offset <= GTTCPHO_MAX) { - opts[0] |= GiantSendv6; - opts[0] |= transport_offset << GTTCPHO_SHIFT; - opts[1] |= min(mss, MSS_MAX) << 18; - large_send = 1; - } - break; - default: - if (unlikely(net_ratelimit())) - dprintk("tso proto=%x!\n", skb->protocol); - break; - } - - if (large_send == 0) - return false; - - return true; - } - } -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - - if (skb->ip_summed == CHECKSUM_PARTIAL) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - const struct iphdr *ip = skb->nh.iph; - - if (dev->features & NETIF_F_IP_CSUM) { - if (ip->protocol == IPPROTO_TCP) - csum_cmd = tp->tx_ip_csum_cmd | tp->tx_tcp_csum_cmd; - else if (ip->protocol == IPPROTO_UDP) - csum_cmd = tp->tx_ip_csum_cmd | tp->tx_udp_csum_cmd; - else if (ip->protocol == IPPROTO_IP) - csum_cmd = tp->tx_ip_csum_cmd; - } -#else - u8 ip_protocol = IPPROTO_RAW; - - switch (get_protocol(skb)) { - case __constant_htons(ETH_P_IP): - if (dev->features & NETIF_F_IP_CSUM) { - ip_protocol = ip_hdr(skb)->protocol; - csum_cmd = tp->tx_ip_csum_cmd; - } - break; - case __constant_htons(ETH_P_IPV6): - if (dev->features & NETIF_F_IPV6_CSUM) { - u32 transport_offset = (u32)skb_transport_offset(skb); - if (transport_offset > 0 && transport_offset <= TCPHO_MAX) { - ip_protocol = ipv6_hdr(skb)->nexthdr; - csum_cmd = tp->tx_ipv6_csum_cmd; - csum_cmd |= transport_offset << TCPHO_SHIFT; - } - } - break; - default: - if (unlikely(net_ratelimit())) - dprintk("checksum_partial proto=%x!\n", skb->protocol); - break; - } - - if (ip_protocol == IPPROTO_TCP) - csum_cmd |= tp->tx_tcp_csum_cmd; - else if (ip_protocol == IPPROTO_UDP) - csum_cmd |= tp->tx_udp_csum_cmd; -#endif - if (csum_cmd == 0) { - sw_calc_csum = true; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - WARN_ON(1); /* we need a WARN() */ -#endif - } - - if (ip_protocol == IPPROTO_TCP) - check_patch_required = false; - } - - if (check_patch_required) { - u32 pad_len = rtl8125_get_patch_pad_len(skb); - - if (pad_len > 0) { - if (!rtl8125_skb_pad_with_len(skb, skb->len + pad_len)) - return false; - - if (csum_cmd != 0) - sw_calc_csum = true; - } - } - - if (skb->len < ETH_ZLEN) { - if (tp->UseSwPaddingShortPkt || - (tp->ShortPacketSwChecksum && csum_cmd != 0)) { - if (!rtl8125_skb_pad(skb)) - return false; - - if (csum_cmd != 0) - sw_calc_csum = true; - } - } - - if (sw_calc_csum) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7) - skb_checksum_help(&skb, 0); -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) - skb_checksum_help(skb, 0); -#else - skb_checksum_help(skb); -#endif - } else - opts[1] |= csum_cmd; - - return true; -} - -static bool rtl8125_tx_slots_avail(struct rtl8125_private *tp, - struct rtl8125_tx_ring *ring) -{ - unsigned int slots_avail = READ_ONCE(ring->dirty_tx) + ring->num_tx_desc - - READ_ONCE(ring->cur_tx); - - /* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */ - return slots_avail > MAX_SKB_FRAGS; -} - -static netdev_tx_t -rtl8125_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - unsigned int entry; - struct TxDesc *txd; - dma_addr_t mapping; - u32 len; - u32 opts[2]; - netdev_tx_t ret = NETDEV_TX_OK; - int frags; - u8 EnableTxNoClose = tp->EnableTxNoClose; - const u16 queue_mapping = skb_get_queue_mapping(skb); - struct rtl8125_tx_ring *ring; - bool stop_queue; - - assert(queue_mapping < tp->num_tx_rings); - - ring = &tp->tx_ring[queue_mapping]; - - if (unlikely(!rtl8125_tx_slots_avail(tp, ring))) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring[%d] full when queue awake!\n", - dev->name, - queue_mapping); - } - goto err_stop; - } - - entry = ring->cur_tx % ring->num_tx_desc; - txd = ring->TxDescArray + entry; - - if (!EnableTxNoClose) { - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Desc is own by hardware!\n", - dev->name); - } - goto err_stop; - } - } - - opts[0] = DescOwn; - opts[1] = rtl8125_tx_vlan_tag(tp, skb); - - if (unlikely(!rtl8125_tso_csum(skb, dev, opts))) - goto err_dma_0; - - frags = rtl8125_xmit_frags(tp, ring, skb, opts); - if (unlikely(frags < 0)) - goto err_dma_0; - if (frags) { - len = skb_headlen(skb); - opts[0] |= FirstFrag; - } else { - len = skb->len; - - //ring->tx_skb[entry].skb = skb; - - opts[0] |= FirstFrag | LastFrag; - } - - opts[0] = rtl8125_get_txd_opts1(ring, opts[0], len, entry); - mapping = dma_map_single(tp_to_dev(tp), skb->data, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, dev, "Failed to map TX DMA!\n"); - goto err_dma_1; - } - ring->tx_skb[entry].len = len; -#ifdef ENABLE_PTP_SUPPORT - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) { - if (tp->hwtstamp_config.tx_type == HWTSTAMP_TX_ON && - !tp->ptp_tx_skb) { - skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; - - tp->ptp_tx_skb = skb_get(skb); - tp->ptp_tx_start = jiffies; - schedule_work(&tp->ptp_tx_work); - } else { - tp->tx_hwtstamp_skipped++; - } - } -#endif - ring->tx_skb[entry].skb = skb; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(opts[1]); - wmb(); - txd->opts1 = cpu_to_le32(opts[0]); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) - dev->trans_start = jiffies; -#else - skb_tx_timestamp(skb); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) - - /* rtl_tx needs to see descriptor changes before updated tp->cur_tx */ - smp_wmb(); - - WRITE_ONCE(ring->cur_tx, ring->cur_tx + frags + 1); - - stop_queue = !rtl8125_tx_slots_avail(tp, ring); - if (unlikely(stop_queue)) { - /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must - * not miss a ring update when it notices a stopped queue. - */ - smp_wmb(); - netif_stop_subqueue(dev, queue_mapping); - } - - if (EnableTxNoClose) - RTL_W16(tp, ring->sw_tail_ptr_reg, ring->cur_tx % MAX_TX_NO_CLOSE_DESC_PTR_V2); - else - RTL_W16(tp, TPPOLL_8125, BIT(ring->index)); /* set polling bit */ - - if (unlikely(stop_queue)) { - /* Sync with rtl_tx: - * - publish queue status and cur_tx ring index (write barrier) - * - refresh dirty_tx ring index (read barrier). - * May the current thread have a pessimistic view of the ring - * status and forget to wake up queue, a racing rtl_tx thread - * can't. - */ - smp_mb(); - if (rtl8125_tx_slots_avail(tp, ring)) - netif_start_subqueue(dev, queue_mapping); - } -out: - return ret; -err_dma_1: - ring->tx_skb[entry].skb = NULL; - rtl8125_tx_clear_range(tp, ring, ring->cur_tx + 1, frags); -err_dma_0: - RTLDEV->stats.tx_dropped++; - dev_kfree_skb_any(skb); - ret = NETDEV_TX_OK; - goto out; -err_stop: - netif_stop_subqueue(dev, queue_mapping); - ret = NETDEV_TX_BUSY; - RTLDEV->stats.tx_dropped++; - goto out; -} - -static inline u32 -rtl8125_fast_mod(const u32 input, const u32 ceil) -{ - return input >= ceil ? input % ceil : input; -} - -static int -rtl8125_tx_interrupt(struct rtl8125_tx_ring *ring, int budget) -{ - struct rtl8125_private *tp = ring->priv; - struct net_device *dev = tp->dev; - unsigned int dirty_tx, tx_left; - unsigned int count = 0; - u8 EnableTxNoClose = tp->EnableTxNoClose; - - dirty_tx = ring->dirty_tx; - smp_rmb(); - tx_left = READ_ONCE(ring->cur_tx) - dirty_tx; - if (EnableTxNoClose) { - unsigned int tx_desc_closed; - u32 NextHwDesCloPtr = RTL_R16(tp, ring->hw_clo_ptr_reg); - ring->NextHwDesCloPtr = NextHwDesCloPtr; - smp_rmb(); - tx_desc_closed = rtl8125_fast_mod(NextHwDesCloPtr - ring->BeginHwDesCloPtr, MAX_TX_NO_CLOSE_DESC_PTR_V2); - if(tx_left > tx_desc_closed) tx_left = tx_desc_closed; - ring->BeginHwDesCloPtr = NextHwDesCloPtr; - } - - while (tx_left > 0) { - unsigned int entry = dirty_tx % ring->num_tx_desc; - struct ring_info *tx_skb = ring->tx_skb + entry; - - if (!EnableTxNoClose && - (le32_to_cpu(ring->TxDescArray[entry].opts1) & DescOwn)) - break; - - RTLDEV->stats.tx_bytes += tx_skb->len; - RTLDEV->stats.tx_packets++; - - rtl8125_unmap_tx_skb(tp->pci_dev, - tx_skb, - ring->TxDescArray + entry); - - if (tx_skb->skb != NULL) { - RTL_NAPI_CONSUME_SKB_ANY(tx_skb->skb, budget); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (ring->dirty_tx != dirty_tx) { - count = dirty_tx - ring->dirty_tx; - WRITE_ONCE(ring->dirty_tx, dirty_tx); - smp_wmb(); - if (__netif_subqueue_stopped(dev, ring->index) && - (rtl8125_tx_slots_avail(tp, ring))) { - netif_start_subqueue(dev, ring->index); - } - smp_rmb(); - if (!EnableTxNoClose && (ring->cur_tx != dirty_tx)) { - RTL_W16(tp, TPPOLL_8125, BIT(ring->index)); - } - } - - return count; -} - -static int -rtl8125_tx_interrupt_with_vector(struct rtl8125_private *tp, - const int message_id, - int budget) -{ - int count = 0; - - if (message_id == 16) - count += rtl8125_tx_interrupt(&tp->tx_ring[0], budget); -#ifdef ENABLE_MULTIPLE_TX_QUEUE - else if (message_id == 18) - count += rtl8125_tx_interrupt(&tp->tx_ring[1], budget); -#endif - - return count; -} - -static inline int -rtl8125_fragmented_frame(struct rtl8125_private *tp, u32 status) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - return (status & (FirstFrag_V3 | LastFrag_V3)) != (FirstFrag_V3 | LastFrag_V3); - else - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline int -rtl8125_rx_desc_type(u32 status) -{ - return ((status >> 26) & 0x0F); -} - -static inline void -rtl8125_rx_v3_csum(struct rtl8125_private *tp, - struct sk_buff *skb, - struct RxDescV3 *descv3) -{ - //u32 opts1 = le32_to_cpu(descv3->RxDescNormalDDWord4.opts1); - u32 opts2 = le32_to_cpu(descv3->RxDescNormalDDWord4.opts2); - - /* rx csum offload for RTL8125 */ - if (((opts2 & RxV4F_v3) && !(opts2 & RxIPF_v3)) || (opts2 & RxV6F_v3)) { - if (((opts2 & RxTCPT_v3) && !(opts2 & RxTCPF_v3)) || - ((opts2 & RxUDPT_v3) && !(opts2 & RxUDPF_v3))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - } else - skb->ip_summed = CHECKSUM_NONE; -} - -static inline void -rtl8125_rx_csum(struct rtl8125_private *tp, - struct sk_buff *skb, - struct RxDesc *desc) -{ - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) - rtl8125_rx_v3_csum(tp, skb, (struct RxDescV3 *)desc); - else { - u32 opts1 = le32_to_cpu(rtl8125_rx_desc_opts1(tp, desc)); - u32 opts2 = le32_to_cpu(rtl8125_rx_desc_opts2(tp, desc)); - - /* rx csum offload for RTL8125 */ - if (((opts2 & RxV4F) && !(opts1 & RxIPF)) || (opts2 & RxV6F)) { - if (((opts1 & RxTCPT) && !(opts1 & RxTCPF)) || - ((opts1 & RxUDPT) && !(opts1 & RxUDPF))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - } else - skb->ip_summed = CHECKSUM_NONE; - } -} - -static inline int -rtl8125_try_rx_copy(struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - struct sk_buff **sk_buff, - int pkt_size, - struct RxDesc *desc, - int rx_buf_sz) -{ - int ret = -1; - - if (pkt_size < rx_copybreak) { - struct sk_buff *skb; - - skb = RTL_ALLOC_SKB_INTR(&tp->r8125napi[ring->index].napi, pkt_size + RTK_RX_ALIGN); - if (skb) { - u8 *data; - - data = sk_buff[0]->data; - skb_reserve(skb, RTK_RX_ALIGN); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) - prefetch(data - RTK_RX_ALIGN); -#endif - eth_copy_and_sum(skb, data, pkt_size, 0); - *sk_buff = skb; - rtl8125_mark_to_asic(tp, desc, rx_buf_sz); - ret = 0; - } - } - return ret; -} - -static inline void -rtl8125_rx_skb(struct rtl8125_private *tp, - struct sk_buff *skb, - u32 ring_index) -{ -#ifdef CONFIG_R8125_NAPI -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - netif_receive_skb(skb); -#else - napi_gro_receive(&tp->r8125napi[ring_index].napi, skb); -#endif -#else - netif_rx(skb); -#endif -} - -static int -rtl8125_check_rx_desc_error(struct net_device *dev, - struct rtl8125_private *tp, - u32 status) -{ - int ret = 0; - - if (tp->InitRxDescType == RX_DESC_RING_TYPE_3) { - if (unlikely(status & RxRES_V3)) { - if (status & (RxRWT_V3 | RxRUNT_V3)) - RTLDEV->stats.rx_length_errors++; - if (status & RxCRC_V3) - RTLDEV->stats.rx_crc_errors++; - - ret = -1; - } - } else { - if (unlikely(status & RxRES)) { - if (status & (RxRWT | RxRUNT)) - RTLDEV->stats.rx_length_errors++; - if (status & RxCRC) - RTLDEV->stats.rx_crc_errors++; - - ret = -1; - } - } - - return ret; -} - -static int -rtl8125_rx_interrupt(struct net_device *dev, - struct rtl8125_private *tp, - struct rtl8125_rx_ring *ring, - napi_budget budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count = 0; - unsigned int entry; - struct RxDesc *desc; - u32 status; - u32 rx_quota; - u64 rx_buf_phy_addr; - u32 ring_index = ring->index; - - assert(dev != NULL); - assert(tp != NULL); - - if (ring->RxDescArray == NULL) - goto rx_out; - - rx_quota = RTL_RX_QUOTA(budget); - cur_rx = ring->cur_rx; - entry = cur_rx % ring->num_rx_desc; - desc = rtl8125_get_rxdesc(tp, ring->RxDescArray, entry); - rx_left = ring->num_rx_desc + ring->dirty_rx - cur_rx; - rx_left = rtl8125_rx_quota(rx_left, (u32)rx_quota); - - for (; rx_left > 0; rx_left--) { - rmb(); - status = le32_to_cpu(rtl8125_rx_desc_opts1(tp, desc)); - if (status & DescOwn) - break; - - if (unlikely(rtl8125_check_rx_desc_error(dev, tp, status) < 0)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - - RTLDEV->stats.rx_errors++; - - if (dev->features & NETIF_F_RXALL) - goto process_pkt; - - rtl8125_mark_to_asic(tp, desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb; - int pkt_size; - -process_pkt: - if (likely(!(dev->features & NETIF_F_RXFCS))) - pkt_size = (status & 0x00003fff) - 4; - else - pkt_size = status & 0x00003fff; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8125_fragmented_frame(tp, status))) { - RTLDEV->stats.rx_dropped++; - RTLDEV->stats.rx_length_errors++; - rtl8125_mark_to_asic(tp, desc, tp->rx_buf_sz); - continue; - } - - skb = ring->Rx_skbuff[entry]; - - if (!skb) - break; - -#ifdef ENABLE_PTP_SUPPORT - if (tp->EnablePtp) { - u8 desc_type; - - desc_type = rtl8125_rx_desc_type(status); - if (desc_type == RXDESC_TYPE_NEXT && rx_left > 0) { - u32 status_next; - struct RxDescV3 *desc_next; - unsigned int entry_next; - struct sk_buff *skb_next; - - entry_next = (cur_rx + 1) % ring->num_rx_desc; - desc_next = (struct RxDescV3 *)rtl8125_get_rxdesc(tp, ring->RxDescArray, entry_next); - rmb(); - status_next = le32_to_cpu(desc_next->RxDescNormalDDWord4.opts1); - if (unlikely(status_next & DescOwn)) { - udelay(1); - rmb(); - status_next = le32_to_cpu(desc_next->RxDescNormalDDWord4.opts1); - if (unlikely(status_next & DescOwn)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_ERR - "%s: Rx Next Desc ERROR. status = %08x\n", - dev->name, status_next); - } - break; - } - } - - cur_rx++; - rx_left--; - desc_type = rtl8125_rx_desc_type(status_next); - if (desc_type == RXDESC_TYPE_PTP) - rtl8125_rx_ptp_pktstamp(tp, skb, desc_next); - else - WARN_ON(1); - - rx_buf_phy_addr = ring->RxDescPhyAddr[entry_next]; - dma_unmap_single(tp_to_dev(tp), rx_buf_phy_addr, - tp->rx_buf_sz, DMA_FROM_DEVICE); - skb_next = ring->Rx_skbuff[entry_next]; - dev_kfree_skb_any(skb_next); - ring->Rx_skbuff[entry_next] = NULL; - } else - WARN_ON(desc_type != RXDESC_TYPE_NORMAL); - } -#endif - rx_buf_phy_addr = ring->RxDescPhyAddr[entry]; - dma_sync_single_for_cpu(tp_to_dev(tp), - rx_buf_phy_addr, tp->rx_buf_sz, - DMA_FROM_DEVICE); - - if (rtl8125_try_rx_copy(tp, ring, &skb, pkt_size, - desc, tp->rx_buf_sz)) { - ring->Rx_skbuff[entry] = NULL; - dma_unmap_single(tp_to_dev(tp), rx_buf_phy_addr, - tp->rx_buf_sz, DMA_FROM_DEVICE); - } else { - dma_sync_single_for_device(tp_to_dev(tp), rx_buf_phy_addr, - tp->rx_buf_sz, DMA_FROM_DEVICE); - } - -#ifdef ENABLE_RSS_SUPPORT - rtl8125_rx_hash(tp, (struct RxDescV3 *)desc, skb); -#endif - - if (tp->cp_cmd & RxChkSum) - rtl8125_rx_csum(tp, skb, desc); - - skb->dev = dev; - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (skb->pkt_type == PACKET_MULTICAST) - RTLDEV->stats.multicast++; - - if (rtl8125_rx_vlan_skb(tp, desc, skb) < 0) - rtl8125_rx_skb(tp, skb, ring_index); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) - dev->last_rx = jiffies; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) - RTLDEV->stats.rx_bytes += pkt_size; - RTLDEV->stats.rx_packets++; - } - - cur_rx++; - entry = cur_rx % ring->num_rx_desc; - desc = rtl8125_get_rxdesc(tp, ring->RxDescArray, entry); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) - prefetch(desc); -#endif - } - - count = cur_rx - ring->cur_rx; - ring->cur_rx = cur_rx; - - delta = rtl8125_rx_fill(tp, ring, dev, ring->dirty_rx, ring->cur_rx, 1); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - ring->dirty_rx += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((ring->dirty_rx + ring->num_rx_desc == ring->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - -rx_out: - return count; -} - -static bool -rtl8125_linkchg_interrupt(struct rtl8125_private *tp, u32 status) -{ - if (tp->HwCurrIsrVer == 2) - return status & ISRIMR_V2_LINKCHG; - - return status & LinkChg; -} - -/* - *The interrupt handler does all of the Rx thread work and cleans up after - *the Tx thread. - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -#else -static irqreturn_t rtl8125_interrupt(int irq, void *dev_instance) -#endif -{ - struct r8125_napi *r8125napi = dev_instance; - struct rtl8125_private *tp = r8125napi->priv; - struct net_device *dev = tp->dev; - u32 status; - int handled = 0; - - do { - status = RTL_R32(tp, tp->isr_reg[0]); - - if (!(tp->features & (RTL_FEATURE_MSI | RTL_FEATURE_MSIX))) { - /* hotplug/major error/no more work/shared irq */ - if (!status) - break; - - if (status == 0xFFFFFFFF) - break; - - if (!(status & (tp->intr_mask | tp->timer_intr_mask))) - break; - } - - handled = 1; - -#if defined(RTL_USE_NEW_INTR_API) - if (!tp->irq_tbl[0].requested) - break; -#endif - rtl8125_disable_hw_interrupt(tp); - - RTL_W32(tp, tp->isr_reg[0], status&~RxFIFOOver); - - if (rtl8125_linkchg_interrupt(tp, status)) - rtl8125_schedule_linkchg_work(tp); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_3(tp)) { - u8 DashIntType2Status; - - if (status & ISRIMR_DASH_INTR_CMAC_RESET) - tp->CmacResetIntr = TRUE; - - DashIntType2Status = RTL_CMAC_R8(tp, CMAC_IBISR0); - if (DashIntType2Status & ISRIMR_DASH_TYPE2_ROK) { - tp->RcvFwDashOkEvt = TRUE; - } - if (DashIntType2Status & ISRIMR_DASH_TYPE2_TOK) { - tp->SendFwHostOkEvt = TRUE; - } - if (DashIntType2Status & ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE) { - tp->DashFwDisableRx = TRUE; - } - - RTL_CMAC_W8(tp, CMAC_IBISR0, DashIntType2Status); - } - } -#endif - -#ifdef CONFIG_R8125_NAPI - if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { - if (status & tp->intr_mask) - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - - if (likely(RTL_NETIF_RX_SCHEDULE_PREP(dev, &tp->r8125napi[0].napi))) - __RTL_NETIF_RX_SCHEDULE(dev, &tp->r8125napi[0].napi); - else if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } else { - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - rtl8125_switch_to_hw_interrupt(tp); - } -#else - if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { - u32 budget = ~(u32)0; - int i; - - if (status & tp->intr_mask) - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - - for (i = 0; i < tp->num_tx_rings; i++) - rtl8125_tx_interrupt(&tp->tx_ring[i], ~(u32)0); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[0], &budget); -#else - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[0], budget); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - struct net_device *dev = tp->dev; - - HandleDashInterrupt(dev); - } -#endif - - rtl8125_switch_to_timer_interrupt(tp); - } else { - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - rtl8125_switch_to_hw_interrupt(tp); - } -#endif - } while (false); - - return IRQ_RETVAL(handled); -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance, struct pt_regs *regs) -#else -static irqreturn_t rtl8125_interrupt_msix(int irq, void *dev_instance) -#endif -{ - struct r8125_napi *r8125napi = dev_instance; - struct rtl8125_private *tp = r8125napi->priv; - struct net_device *dev = tp->dev; - int message_id = r8125napi->index; -#ifndef CONFIG_R8125_NAPI - u32 budget = ~(u32)0; -#endif - - do { -#if defined(RTL_USE_NEW_INTR_API) - if (!tp->irq_tbl[message_id].requested) - break; -#endif - rtl8125_disable_hw_interrupt_v2(tp, message_id); - - rtl8125_clear_hw_isr_v2(tp, message_id); - - //link change - if (message_id == 21) { - rtl8125_schedule_linkchg_work(tp); - break; - } - -#ifdef CONFIG_R8125_NAPI - if (likely(RTL_NETIF_RX_SCHEDULE_PREP(dev, &r8125napi->napi))) - __RTL_NETIF_RX_SCHEDULE(dev, &r8125napi->napi); - else if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: interrupt message id %d in poll_msix\n", - dev->name, message_id); -#else - rtl8125_tx_interrupt_with_vector(tp, message_id, ~(u32)0); - - if (message_id < tp->num_rx_rings) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], &budget); -#else - rtl8125_rx_interrupt(dev, tp, &tp->rx_ring[message_id], budget); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - } - - rtl8125_enable_hw_interrupt_v2(tp, message_id); -#endif - - } while (false); - - return IRQ_HANDLED; -} - -static void rtl8125_down(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - //rtl8125_delete_esd_timer(dev, &tp->esd_timer); - - //rtl8125_delete_link_timer(dev, &tp->link_timer); - - netif_tx_disable(dev); - - _rtl8125_wait_for_quiescence(dev); - - netif_carrier_off(dev); - - rtl8125_hw_reset(dev); - - rtl8125_tx_clear(tp); - - rtl8125_rx_clear(tp); -} - -static int rtl8125_resource_freed(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < tp->num_tx_rings; i++) - if (tp->tx_ring[i].TxDescArray) return 0; - - for (i = 0; i < tp->num_rx_rings; i++) - if (tp->rx_ring[i].RxDescArray) return 0; - - return 1; -} - -int rtl8125_close(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - if (!rtl8125_resource_freed(tp)) { - set_bit(R8125_FLAG_DOWN, tp->task_flags); - - rtl8125_down(dev); - - pci_clear_master(tp->pci_dev); - -#ifdef ENABLE_PTP_SUPPORT - rtl8125_ptp_stop(tp); -#endif - rtl8125_hw_d3_para(dev); - - rtl8125_powerdown_pll(dev, 0); - - rtl8125_free_irq(tp); - - rtl8125_free_alloc_resources(tp); - } else { - rtl8125_hw_d3_para(dev); - - rtl8125_powerdown_pll(dev, 0); - } - - return 0; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) -static void rtl8125_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8125_private *tp = netdev_priv(dev); - - rtnl_lock(); - - if (tp->DASH) - rtl8125_driver_stop(tp); - - rtl8125_set_bios_setting(dev); - if (s5_keep_curr_mac == 0 && tp->random_mac == 0) - rtl8125_rar_set(tp, tp->org_mac_addr); - - if (s5wol == 0) - tp->wol_enabled = WOL_DISABLED; - - rtl8125_close(dev); - rtl8125_disable_msi(pdev, tp); - - rtnl_unlock(); - - if (system_state == SYSTEM_POWER_OFF) { - pci_clear_master(tp->pci_dev); - pci_wake_from_d3(pdev, tp->wol_enabled); - pci_set_power_state(pdev, PCI_D3hot); - } -} -#endif - -/** - * rtl8125_get_stats - Get rtl8125 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8125 - */ -static struct -net_device_stats *rtl8125_get_stats(struct net_device *dev) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - struct rtl8125_private *tp = netdev_priv(dev); -#endif - return &RTLDEV->stats; -} - -#ifdef CONFIG_PM - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) -static int -rtl8125_suspend(struct pci_dev *pdev, u32 state) -#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) -static int -rtl8125_suspend(struct device *device) -#else -static int -rtl8125_suspend(struct pci_dev *pdev, pm_message_t state) -#endif -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); -#else - struct net_device *dev = pci_get_drvdata(pdev); -#endif - struct rtl8125_private *tp = netdev_priv(dev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - u32 pci_pm_state = pci_choose_state(pdev, state); -#endif - if (!netif_running(dev)) - goto out; - - //rtl8125_cancel_all_schedule_work(tp); - - //rtl8125_delete_esd_timer(dev, &tp->esd_timer); - - //rtl8125_delete_link_timer(dev, &tp->link_timer); - - rtnl_lock(); - - set_bit(R8125_FLAG_DOWN, tp->task_flags); - - netif_tx_disable(dev); - - netif_carrier_off(dev); - - netif_device_detach(dev); - -#ifdef ENABLE_PTP_SUPPORT - rtl8125_ptp_suspend(tp); -#endif - rtl8125_hw_reset(dev); - - pci_clear_master(pdev); - - rtl8125_hw_d3_para(dev); - - rtl8125_powerdown_pll(dev, 1); - - if (tp->DASH) - rtl8125_driver_stop(tp); - - rtnl_unlock(); -out: - - pci_disable_device(pdev); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - pci_save_state(pdev, &pci_pm_state); -#else - pci_save_state(pdev); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled); -#endif - - pci_prepare_to_sleep(pdev); - - return 0; -} - -static int -rtl8125_hw_d3_not_power_off(struct net_device *dev) -{ - return rtl8125_check_hw_phy_mcu_code_ver(dev); -} - -static int rtl8125_wait_phy_nway_complete_sleep(struct rtl8125_private *tp) -{ - int i, val; - - for (i = 0; i < 30; i++) { - val = rtl8125_mdio_read(tp, MII_BMSR) & BMSR_ANEGCOMPLETE; - if (val) - return 0; - - msleep(100); - } - - return -1; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -static int -rtl8125_resume(struct pci_dev *pdev) -#else -static int -rtl8125_resume(struct device *device) -#endif -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); -#else - struct net_device *dev = pci_get_drvdata(pdev); -#endif - struct rtl8125_private *tp = netdev_priv(dev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - u32 pci_pm_state = PCI_D0; -#endif - u32 err; - - rtnl_lock(); - - err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "Cannot enable PCI device from suspend\n"); - goto out_unlock; - } -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - pci_restore_state(pdev, &pci_pm_state); -#else - pci_restore_state(pdev); -#endif - pci_enable_wake(pdev, PCI_D0, 0); - - /* restore last modified mac address */ - rtl8125_rar_set(tp, dev->dev_addr); - - tp->resume_not_chg_speed = 0; - if (tp->check_keep_link_speed && - //tp->link_ok(dev) && - rtl8125_hw_d3_not_power_off(dev) && - rtl8125_wait_phy_nway_complete_sleep(tp) == 0) - tp->resume_not_chg_speed = 1; - - if (!netif_running(dev)) - goto out_unlock; - - pci_set_master(pdev); - - rtl8125_exit_oob(dev); - - rtl8125_up(dev); - - clear_bit(R8125_FLAG_DOWN, tp->task_flags); - - rtl8125_schedule_reset_work(tp); - - rtl8125_schedule_esd_work(tp); - - //mod_timer(&tp->esd_timer, jiffies + RTL8125_ESD_TIMEOUT); - //mod_timer(&tp->link_timer, jiffies + RTL8125_LINK_TIMEOUT); -out_unlock: - netif_device_attach(dev); - - rtnl_unlock(); - - return err; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) - -static struct dev_pm_ops rtl8125_pm_ops = { - .suspend = rtl8125_suspend, - .resume = rtl8125_resume, - .freeze = rtl8125_suspend, - .thaw = rtl8125_resume, - .poweroff = rtl8125_suspend, - .restore = rtl8125_resume, -}; - -#define RTL8125_PM_OPS (&rtl8125_pm_ops) - -#endif - -#else /* !CONFIG_PM */ - -#define RTL8125_PM_OPS NULL - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8125_pci_driver = { - .name = MODULENAME, - .id_table = rtl8125_pci_tbl, - .probe = rtl8125_init_one, - .remove = __devexit_p(rtl8125_remove_one), -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) - .shutdown = rtl8125_shutdown, -#endif -#ifdef CONFIG_PM -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - .suspend = rtl8125_suspend, - .resume = rtl8125_resume, -#else - .driver.pm = RTL8125_PM_OPS, -#endif -#endif -}; - -static int __init -rtl8125_init_module(void) -{ - int ret = 0; -#ifdef ENABLE_R8125_PROCFS - rtl8125_proc_module_init(); -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - - ret = pci_register_driver(&rtl8125_pci_driver); -#else - ret = pci_module_init(&rtl8125_pci_driver); -#endif - - return ret; -} - -static void __exit -rtl8125_cleanup_module(void) -{ - pci_unregister_driver(&rtl8125_pci_driver); - -#ifdef ENABLE_R8125_PROCFS - if (rtl8125_proc) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - remove_proc_subtree(MODULENAME, init_net.proc_net); -#else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) - remove_proc_entry(MODULENAME, init_net.proc_net); -#else - remove_proc_entry(MODULENAME, proc_net); -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - rtl8125_proc = NULL; - } -#endif -} - -module_init(rtl8125_init_module); -module_exit(rtl8125_cleanup_module); diff --git a/addons/r8125/src/4.4.180/r8125_ptp.c b/addons/r8125/src/4.4.180/r8125_ptp.c deleted file mode 100755 index 6010a180..00000000 --- a/addons/r8125/src/4.4.180/r8125_ptp.c +++ /dev/null @@ -1,594 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "r8125.h" -#include "r8125_ptp.h" - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static inline struct timespec timespec64_to_timespec(const struct timespec64 ts64) -{ - return *(const struct timespec *)&ts64; -} - -static inline struct timespec64 timespec_to_timespec64(const struct timespec ts) -{ - return *(const struct timespec64 *)&ts; -} -#endif - -static int _rtl8125_phc_gettime(struct rtl8125_private *tp, struct timespec64 *ts64) -{ - //get local time - RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_LATCHED_LOCAL_TIME | PTP_EXEC_CMD)); - - /* nanoseconds */ - //0x6808[29:0] - ts64->tv_nsec = (RTL_R32(tp, PTP_SOFT_CONFIG_Time_NS_8125) & 0x3fffffff) + - tp->ptp_adjust; - - /* seconds */ - //0x680C[47:0] - ts64->tv_sec = RTL_R16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4); - ts64->tv_sec <<= 32; - ts64->tv_sec |= RTL_R32(tp, PTP_SOFT_CONFIG_Time_S_8125); - - return 0; -} - -static int _rtl8125_phc_settime(struct rtl8125_private *tp, const struct timespec64 *ts64) -{ - /* nanoseconds */ - //0x6808[29:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, (ts64->tv_nsec & 0x3fffffff)); - - /* seconds */ - //0x680C[47:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, ts64->tv_sec); - RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (ts64->tv_sec >> 32)); - - //set local time - RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); - - return 0; -} - -#if 0 -static int _rtl8125_phc_adjtime(struct rtl8125_private *tp, s64 delta) -{ - struct timespec64 now, then = ns_to_timespec64(delta); - u32 nsec; - u64 sec; - - _rtl8125_phc_gettime(tp, &now); - now = timespec64_add(now, then); - - nsec = now.tv_nsec & 0x3fffffff; - sec = now.tv_sec & 0x0000ffffffffffff; - - /* nanoseconds */ - //0x6808[29:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, nsec); - - /* seconds */ - //0x680C[47:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_S_8125, sec); - RTL_W16(tp, PTP_SOFT_CONFIG_Time_S_8125 + 4, (sec >> 32)); - - //adjust local time - //RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_DRIFT_LOCAL_TIME | PTP_EXEC_CMD)); - RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); - - return 0; -} -#endif - -static int rtl8125_phc_adjtime(struct ptp_clock_info *ptp, s64 delta) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - unsigned long flags; - //int ret = 0; - - //netif_info(tp, drv, tp->dev, "phc adjust time\n"); - - spin_lock_irqsave(&tp->lock, flags); - //ret = _rtl8125_phc_adjtime(tp, delta); - tp->ptp_adjust += delta; - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -/* -1ppm means every 125MHz plus 125Hz. It also means every 8ns minus 8ns*10^(-6) - -1ns=2^30 sub_ns - -8ns*10^(-6) = 8 * 2^30 sub_ns * 10^(-6) = 2^33 sub_ns * 10^(-6) = 8590 = 0x218E sub_ns - -1ppb means every 125MHz plus 0.125Hz. It also means every 8ns minus 8ns*10^(-9) - -1ns=2^30 sub_ns - -8ns*10^(-9) = 8 * 2^30 sub_ns * 10^(-9) = 2^33 sub_ns * 10^(-9) = 8.59 sub_ns = 9 sub_ns -*/ -static int _rtl8125_phc_adjfreq(struct ptp_clock_info *ptp, s32 ppb) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - bool negative = false; - u32 sub_ns; - - if (ppb < 0) { - negative = true; - ppb = -ppb; - } - - sub_ns = ppb * 9; - if (negative) { - sub_ns = -sub_ns; - sub_ns &= 0x3fffffff; - sub_ns |= PTP_ADJUST_TIME_NS_NEGATIVE; - } else - sub_ns &= 0x3fffffff; - - /* nanoseconds */ - //0x6808[29:0] - RTL_W32(tp, PTP_SOFT_CONFIG_Time_NS_8125, sub_ns); - - //adjust local time - RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_DRIFT_LOCAL_TIME | PTP_EXEC_CMD)); - //RTL_W16(tp, PTP_TIME_CORRECT_CMD_8125, (PTP_CMD_SET_LOCAL_TIME | PTP_EXEC_CMD)); - - return 0; -} - -static int rtl8125_phc_adjfreq(struct ptp_clock_info *ptp, s32 delta) -{ - //struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - - //netif_info(tp, drv, tp->dev, "phc adjust freq\n"); - - if (delta > ptp->max_adj || delta < -ptp->max_adj) - return -EINVAL; - - _rtl8125_phc_adjfreq(ptp, delta); - - return 0; -} - -static int rtl8125_phc_gettime(struct ptp_clock_info *ptp, struct timespec64 *ts64) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - unsigned long flags; - int ret; - - //netif_info(tp, drv, tp->dev, "phc get ts\n"); - - spin_lock_irqsave(&tp->lock, flags); - ret = _rtl8125_phc_gettime(tp, ts64); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static int rtl8125_phc_settime(struct ptp_clock_info *ptp, - const struct timespec64 *ts64) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - unsigned long flags; - int ret; - - //netif_info(tp, drv, tp->dev, "phc set ts\n"); - - spin_lock_irqsave(&tp->lock, flags); - ret = _rtl8125_phc_settime(tp, ts64); - tp->ptp_adjust = 0; - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static int rtl8125_phc_enable(struct ptp_clock_info *ptp, - struct ptp_clock_request *rq, int on) -{ - struct rtl8125_private *tp = container_of(ptp, struct rtl8125_private, ptp_clock_info); - unsigned long flags; - u16 ptp_ctrl; - - //netif_info(tp, drv, tp->dev, "phc enable type %x on %d\n", rq->type, on); - - switch (rq->type) { - case PTP_CLK_REQ_PPS: - spin_lock_irqsave(&tp->lock, flags); - ptp_ctrl = RTL_R16(tp, PTP_CTRL_8125); - ptp_ctrl &= ~BIT_15; - if (on) - ptp_ctrl |= BIT_14; - else - ptp_ctrl &= ~BIT_14; - RTL_W16(tp, PTP_CTRL_8125, ptp_ctrl); - spin_unlock_irqrestore(&tp->lock, flags); - return 0; - default: - return -EOPNOTSUPP; - } -} - -int rtl8125_get_ts_info(struct net_device *netdev, - struct ethtool_ts_info *info) -{ - struct rtl8125_private *tp = netdev_priv(netdev); - - /* we always support timestamping disabled */ - info->rx_filters = BIT(HWTSTAMP_FILTER_NONE); - - if (tp->HwSuppPtpVer == 0) - return ethtool_op_get_ts_info(netdev, info); - - info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE | - SOF_TIMESTAMPING_RX_SOFTWARE | - SOF_TIMESTAMPING_SOFTWARE | - SOF_TIMESTAMPING_TX_HARDWARE | - SOF_TIMESTAMPING_RX_HARDWARE | - SOF_TIMESTAMPING_RAW_HARDWARE; - - if (tp->ptp_clock) - info->phc_index = ptp_clock_index(tp->ptp_clock); - else - info->phc_index = -1; - - info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON); - - info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) | - BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) | - BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) | - BIT(HWTSTAMP_FILTER_PTP_V2_SYNC) | - BIT(HWTSTAMP_FILTER_PTP_V2_L4_SYNC) | - BIT(HWTSTAMP_FILTER_PTP_V2_DELAY_REQ) | - BIT(HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ); - - return 0; -} - -static const struct ptp_clock_info rtl_ptp_clock_info = { - .owner = THIS_MODULE, - .n_alarm = 0, - .n_ext_ts = 0, - .n_per_out = 0, - .n_pins = 0, - .pps = 1, - .adjfreq = rtl8125_phc_adjfreq, - .adjtime = rtl8125_phc_adjtime, - .gettime64 = rtl8125_phc_gettime, - .settime64 = rtl8125_phc_settime, - .enable = rtl8125_phc_enable, -}; - -static int rtl8125_get_tx_ptp_pkt_tstamp(struct rtl8125_private *tp, struct timespec64 *ts64) -{ - return _rtl8125_phc_gettime(tp, ts64); -} - -static void rtl8125_ptp_tx_hwtstamp(struct rtl8125_private *tp) -{ - struct sk_buff *skb = tp->ptp_tx_skb; - struct skb_shared_hwtstamps shhwtstamps = {0}; - struct timespec64 ts64; - - RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); - - rtl8125_get_tx_ptp_pkt_tstamp(tp, &ts64); - - /* Upper 32 bits contain s, lower 32 bits contain ns. */ - shhwtstamps.hwtstamp = ktime_set(ts64.tv_sec, - ts64.tv_nsec); - - /* Clear the lock early before calling skb_tstamp_tx so that - * applications are not woken up before the lock bit is clear. We use - * a copy of the skb pointer to ensure other threads can't change it - * while we're notifying the stack. - */ - tp->ptp_tx_skb = NULL; - - /* Notify the stack and free the skb after we've unlocked */ - skb_tstamp_tx(skb, &shhwtstamps); - dev_kfree_skb_any(skb); -} - -#define RTL8125_PTP_TX_TIMEOUT (HZ * 15) -static void rtl8125_ptp_tx_work(struct work_struct *work) -{ - struct rtl8125_private *tp = container_of(work, struct rtl8125_private, - ptp_tx_work); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - if (!tp->ptp_tx_skb) - goto Exit; - - if (time_is_before_jiffies(tp->ptp_tx_start + - RTL8125_PTP_TX_TIMEOUT)) { - dev_kfree_skb_any(tp->ptp_tx_skb); - tp->ptp_tx_skb = NULL; - tp->tx_hwtstamp_timeouts++; - /* Clear the tx valid bit in TSYNCTXCTL register to enable - * interrupt - */ - RTL_W8(tp, PTP_ISR_8125, PTP_ISR_TOK | PTP_ISR_TER); - goto Exit; - } - - if (RTL_R8(tp, PTP_ISR_8125) & (PTP_ISR_TOK)) - rtl8125_ptp_tx_hwtstamp(tp); - else - /* reschedule to check later */ - schedule_work(&tp->ptp_tx_work); - -Exit: - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8125_hwtstamp_enable(struct rtl8125_private *tp, bool enable) -{ - RTL_W16(tp, PTP_CTRL_8125, 0); - if (enable) { - u16 ptp_ctrl; - struct timespec64 ts64; - - //clear ptp isr - RTL_W8(tp, PTP_ISR_8125, 0xff); - //ptp source 0:gphy 1:mac - rtl8125_mac_ocp_write(tp, 0xDC00, rtl8125_mac_ocp_read(tp, 0xDC00) | BIT_6); - //enable ptp - ptp_ctrl = (BIT_0 | BIT_3 | BIT_4 | BIT_6 | BIT_10 | BIT_12 | BIT_13); - if (tp->ptp_master_mode) { - ptp_ctrl &= ~BIT_13; - ptp_ctrl |= BIT_1; - } - RTL_W16(tp, PTP_CTRL_8125, ptp_ctrl); - - //set system time - /* - if (ktime_to_timespec64_cond(ktime_get_real(), &ts64)) - _rtl8125_phc_settime(tp, timespec64_to_timespec(ts64)); - */ - ktime_get_real_ts64(&ts64); - ts64.tv_nsec += tp->ptp_adjust; - _rtl8125_phc_settime(tp, &ts64); - tp->ptp_adjust = 0; - } - - return 0; -} - -static long rtl8125_ptp_create_clock(struct rtl8125_private *tp) -{ - struct net_device *netdev = tp->dev; - long err; - - if (!IS_ERR_OR_NULL(tp->ptp_clock)) - return 0; - - if (tp->HwSuppPtpVer == 0) { - tp->ptp_clock = NULL; - return -EOPNOTSUPP; - } - - tp->ptp_clock_info = rtl_ptp_clock_info; - snprintf(tp->ptp_clock_info.name, sizeof(tp->ptp_clock_info.name), - "%pm", tp->dev->dev_addr); - tp->ptp_clock_info.max_adj = 119304647; - tp->ptp_clock = ptp_clock_register(&tp->ptp_clock_info, &tp->pci_dev->dev); - if (IS_ERR(tp->ptp_clock)) { - err = PTR_ERR(tp->ptp_clock); - tp->ptp_clock = NULL; - netif_err(tp, drv, tp->dev, "ptp_clock_register failed\n"); - return err; - } else - netif_info(tp, drv, tp->dev, "registered PHC device on %s\n", netdev->name); - - return 0; -} - -void rtl8125_ptp_reset(struct rtl8125_private *tp) -{ - if (!tp->ptp_clock) - return; - - netif_info(tp, drv, tp->dev, "reset PHC clock\n"); - - rtl8125_hwtstamp_enable(tp, false); -} - -void rtl8125_ptp_init(struct rtl8125_private *tp) -{ - /* obtain a PTP device, or re-use an existing device */ - if (rtl8125_ptp_create_clock(tp)) - return; - - /* we have a clock so we can initialize work now */ - INIT_WORK(&tp->ptp_tx_work, rtl8125_ptp_tx_work); - - tp->ptp_adjust = 0; - - /* reset the PTP related hardware bits */ - rtl8125_ptp_reset(tp); - - return; -} - -void rtl8125_ptp_suspend(struct rtl8125_private *tp) -{ - if (!tp->ptp_clock) - return; - - netif_info(tp, drv, tp->dev, "suspend PHC clock\n"); - - rtl8125_hwtstamp_enable(tp, false); - - /* ensure that we cancel any pending PTP Tx work item in progress */ - cancel_work_sync(&tp->ptp_tx_work); -} - -void rtl8125_ptp_stop(struct rtl8125_private *tp) -{ - struct net_device *netdev = tp->dev; - - netif_info(tp, drv, tp->dev, "stop PHC clock\n"); - - /* first, suspend PTP activity */ - rtl8125_ptp_suspend(tp); - - /* disable the PTP clock device */ - if (tp->ptp_clock) { - ptp_clock_unregister(tp->ptp_clock); - tp->ptp_clock = NULL; - netif_info(tp, drv, tp->dev, "removed PHC on %s\n", - netdev->name); - } -} - -static int rtl8125_set_tstamp(struct net_device *netdev, struct ifreq *ifr) -{ - struct rtl8125_private *tp = netdev_priv(netdev); - struct hwtstamp_config config; - bool hwtstamp = 0; - - //netif_info(tp, drv, tp->dev, "ptp set ts\n"); - - if (copy_from_user(&config, ifr->ifr_data, sizeof(config))) - return -EFAULT; - - if (config.flags) - return -EINVAL; - - switch (config.tx_type) { - case HWTSTAMP_TX_ON: - hwtstamp = 1; - case HWTSTAMP_TX_OFF: - break; - case HWTSTAMP_TX_ONESTEP_SYNC: - default: - return -ERANGE; - } - - switch (config.rx_filter) { - case HWTSTAMP_FILTER_PTP_V2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: - case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: - case HWTSTAMP_FILTER_PTP_V2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: - case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: - case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: - case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ: - config.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; - hwtstamp = 1; - case HWTSTAMP_FILTER_NONE: - break; - default: - return -ERANGE; - } - - if (tp->hwtstamp_config.tx_type != config.tx_type || - tp->hwtstamp_config.rx_filter != config.rx_filter) { - tp->hwtstamp_config = config; - rtl8125_hwtstamp_enable(tp, hwtstamp); - } - - return copy_to_user(ifr->ifr_data, &config, - sizeof(config)) ? -EFAULT : 0; -} - -static int rtl8125_get_tstamp(struct net_device *netdev, struct ifreq *ifr) -{ - struct rtl8125_private *tp = netdev_priv(netdev); - - //netif_info(tp, drv, tp->dev, "ptp get ts\n"); - - return copy_to_user(ifr->ifr_data, &tp->hwtstamp_config, - sizeof(tp->hwtstamp_config)) ? -EFAULT : 0; -} - -int rtl8125_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd) -{ - struct rtl8125_private *tp = netdev_priv(netdev); - int ret; - unsigned long flags; - - //netif_info(tp, drv, tp->dev, "ptp ioctl\n"); - - ret = 0; - switch (cmd) { -#ifdef ENABLE_PTP_SUPPORT - case SIOCSHWTSTAMP: - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8125_set_tstamp(netdev, ifr); - spin_unlock_irqrestore(&tp->lock, flags); - break; - case SIOCGHWTSTAMP: - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8125_get_tstamp(netdev, ifr); - spin_unlock_irqrestore(&tp->lock, flags); - break; -#endif - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -void rtl8125_rx_ptp_pktstamp(struct rtl8125_private *tp, struct sk_buff *skb, - struct RxDescV3 *descv3) -{ - time64_t tv_sec; - long tv_nsec; - - tv_sec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampHigh) + - ((u64)le32_to_cpu(descv3->RxDescPTPDDWord4.TimeStampHHigh) << 32); - tv_nsec = le32_to_cpu(descv3->RxDescTimeStamp.TimeStampLow) + tp->ptp_adjust; - - skb_hwtstamps(skb)->hwtstamp = ktime_set(tv_sec, tv_nsec); -} diff --git a/addons/r8125/src/4.4.180/r8125_ptp.h b/addons/r8125/src/4.4.180/r8125_ptp.h deleted file mode 100755 index 7a1fe83b..00000000 --- a/addons/r8125/src/4.4.180/r8125_ptp.h +++ /dev/null @@ -1,81 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_rtl8125_PTP_H -#define _LINUX_rtl8125_PTP_H - -#include -#include -#include -#include -#include - -struct rtl8125_ptp_info { - s64 time_sec; - u32 time_ns; - u16 ts_info; -}; - -#ifndef _STRUCT_TIMESPEC -#define _STRUCT_TIMESPEC -struct timespec { - __kernel_old_time_t tv_sec; /* seconds */ - long tv_nsec; /* nanoseconds */ -}; -#endif - -enum PTP_CMD_TYPE { - PTP_CMD_SET_LOCAL_TIME = 0, - PTP_CMD_DRIFT_LOCAL_TIME, - PTP_CMD_LATCHED_LOCAL_TIME, -}; - - -struct rtl8125_private; -struct RxDescV3; - -int rtl8125_get_ts_info(struct net_device *netdev, - struct ethtool_ts_info *info); - -void rtl8125_ptp_reset(struct rtl8125_private *tp); -void rtl8125_ptp_init(struct rtl8125_private *tp); -void rtl8125_ptp_suspend(struct rtl8125_private *tp); -void rtl8125_ptp_stop(struct rtl8125_private *tp); - -int rtl8125_ptp_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd); - -void rtl8125_rx_ptp_pktstamp(struct rtl8125_private *tp, struct sk_buff *skb, - struct RxDescV3 *descv3); - -#endif /* _LINUX_rtl8125_PTP_H */ diff --git a/addons/r8125/src/4.4.180/r8125_realwow.h b/addons/r8125/src/4.4.180/r8125_realwow.h deleted file mode 100755 index e5e9b46d..00000000 --- a/addons/r8125/src/4.4.180/r8125_realwow.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_R8125_REALWOW_H -#define _LINUX_R8125_REALWOW_H - -#define SIOCDEVPRIVATE_RTLREALWOW SIOCDEVPRIVATE+3 - -#define MAX_RealWoW_KCP_SIZE (100) -#define MAX_RealWoW_Payload (64) - -#define KA_TX_PACKET_SIZE (100) -#define KA_WAKEUP_PATTERN_SIZE (120) - -//HwSuppKeepAliveOffloadVer -#define HW_SUPPORT_KCP_OFFLOAD(_M) ((_M)->HwSuppKCPOffloadVer > 0) - -enum rtl_realwow_cmd { - - RTL_REALWOW_SET_KCP_DISABLE=0, - RTL_REALWOW_SET_KCP_INFO, - RTL_REALWOW_SET_KCP_CONTENT, - - RTL_REALWOW_SET_KCP_ACKPKTINFO, - RTL_REALWOW_SET_KCP_WPINFO, - RTL_REALWOW_SET_KCPDHCP_TIMEOUT, - - RTLT_REALWOW_COMMAND_INVALID -}; - -struct rtl_realwow_ioctl_struct { - __u32 cmd; - __u32 offset; - __u32 len; - union { - __u32 data; - void *data_buffer; - }; -}; - -typedef struct _MP_KCPInfo { - u8 DIPv4[4]; - u8 MacID[6]; - u16 UdpPort[2]; - u8 PKTLEN[2]; - - u16 ackLostCnt; - u8 KCP_WakePattern[MAX_RealWoW_Payload]; - u8 KCP_AckPacket[MAX_RealWoW_Payload]; - u32 KCP_interval; - u8 KCP_WakePattern_Len; - u8 KCP_AckPacket_Len; - u8 KCP_TxPacket[2][KA_TX_PACKET_SIZE]; -} MP_KCP_INFO, *PMP_KCP_INFO; - -typedef struct _KCPInfo { - u32 nId; // = id - u8 DIPv4[4]; - u8 MacID[6]; - u16 UdpPort; - u16 PKTLEN; -} KCPInfo, *PKCPInfo; - -typedef struct _KCPContent { - u32 id; // = id - u32 mSec; // = msec - u32 size; // =size - u8 bPacket[MAX_RealWoW_KCP_SIZE]; // put packet here -} KCPContent, *PKCPContent; - -typedef struct _RealWoWAckPktInfo { - u16 ackLostCnt; - u16 patterntSize; - u8 pattern[MAX_RealWoW_Payload]; -} RealWoWAckPktInfo,*PRealWoWAckPktInfo; - -typedef struct _RealWoWWPInfo { - u16 patterntSize; - u8 pattern[MAX_RealWoW_Payload]; -} RealWoWWPInfo,*PRealWoWWPInfo; - -int rtl8125_realwow_ioctl(struct net_device *dev, struct ifreq *ifr); -void rtl8125_realwow_hw_init(struct net_device *dev); -void rtl8125_get_realwow_hw_version(struct net_device *dev); -void rtl8125_set_realwow_d3_para(struct net_device *dev); - -#endif /* _LINUX_R8125_REALWOW_H */ diff --git a/addons/r8125/src/4.4.180/r8125_rss.c b/addons/r8125/src/4.4.180/r8125_rss.c deleted file mode 100755 index 1f55c447..00000000 --- a/addons/r8125/src/4.4.180/r8125_rss.c +++ /dev/null @@ -1,481 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include "r8125.h" - -enum rtl8125_rss_register_content { - /* RSS */ - RSS_CTRL_TCP_IPV4_SUPP = (1 << 0), - RSS_CTRL_IPV4_SUPP = (1 << 1), - RSS_CTRL_TCP_IPV6_SUPP = (1 << 2), - RSS_CTRL_IPV6_SUPP = (1 << 3), - RSS_HALF_SUPP = (1 << 7), - RSS_CTRL_UDP_IPV4_SUPP = (1 << 11), - RSS_CTRL_UDP_IPV6_SUPP = (1 << 12), - RSS_QUAD_CPU_EN = (1 << 16), - RSS_HQ_Q_SUP_R = (1 << 31), -}; - -static int rtl8125_get_rss_hash_opts(struct rtl8125_private *tp, - struct ethtool_rxnfc *cmd) -{ - cmd->data = 0; - - /* Report default options for RSS */ - switch (cmd->flow_type) { - case TCP_V4_FLOW: - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fallthrough */ - case UDP_V4_FLOW: - if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fallthrough */ - case IPV4_FLOW: - cmd->data |= RXH_IP_SRC | RXH_IP_DST; - break; - case TCP_V6_FLOW: - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fallthrough */ - case UDP_V6_FLOW: - if (tp->rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) - cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3; - /* fallthrough */ - case IPV6_FLOW: - cmd->data |= RXH_IP_SRC | RXH_IP_DST; - break; - default: - return -EINVAL; - } - - return 0; -} - -int rtl8125_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, - u32 *rule_locs) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret = -EOPNOTSUPP; - - netif_info(tp, drv, tp->dev, "rss get rxnfc\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return ret; - - switch (cmd->cmd) { - case ETHTOOL_GRXRINGS: - cmd->data = rtl8125_tot_rx_rings(tp); - ret = 0; - break; - case ETHTOOL_GRXFH: - ret = rtl8125_get_rss_hash_opts(tp, cmd); - break; - default: - break; - } - - return ret; -} - -u32 rtl8125_rss_indir_tbl_entries(struct rtl8125_private *tp) -{ - return tp->HwSuppIndirTblEntries; -} - -#define RSS_MASK_BITS_OFFSET (8) -#define RSS_CPU_NUM_OFFSET (16) -#define RTL8125_UDP_RSS_FLAGS (RTL_8125_RSS_FLAG_HASH_UDP_IPV4 | \ - RTL_8125_RSS_FLAG_HASH_UDP_IPV6) -static int _rtl8125_set_rss_hash_opt(struct rtl8125_private *tp) -{ - u32 rss_flags = tp->rss_flags; - u32 hash_mask_len; - u32 rss_ctrl; - - rss_ctrl = ilog2(rtl8125_tot_rx_rings(tp)); - rss_ctrl &= (BIT_0 | BIT_1 | BIT_2); - rss_ctrl <<= RSS_CPU_NUM_OFFSET; - - /* Perform hash on these packet types */ - rss_ctrl |= RSS_CTRL_TCP_IPV4_SUPP - | RSS_CTRL_IPV4_SUPP - | RSS_CTRL_IPV6_SUPP - | RSS_CTRL_TCP_IPV6_SUPP; - - if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) - rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP; - - if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) - rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP; - - hash_mask_len = ilog2(rtl8125_rss_indir_tbl_entries(tp)); - hash_mask_len &= (BIT_0 | BIT_1 | BIT_2); - rss_ctrl |= hash_mask_len << RSS_MASK_BITS_OFFSET; - - RTL_W32(tp, RSS_CTRL_8125, rss_ctrl); - - return 0; -} - -static int rtl8125_set_rss_hash_opt(struct rtl8125_private *tp, - struct ethtool_rxnfc *nfc) -{ - u32 rss_flags = tp->rss_flags; - - netif_info(tp, drv, tp->dev, "rss set hash\n"); - - /* - * RSS does not support anything other than hashing - * to queues on src and dst IPs and ports - */ - if (nfc->data & ~(RXH_IP_SRC | RXH_IP_DST | - RXH_L4_B_0_1 | RXH_L4_B_2_3)) - return -EINVAL; - - switch (nfc->flow_type) { - case TCP_V4_FLOW: - case TCP_V6_FLOW: - if (!(nfc->data & RXH_IP_SRC) || - !(nfc->data & RXH_IP_DST) || - !(nfc->data & RXH_L4_B_0_1) || - !(nfc->data & RXH_L4_B_2_3)) - return -EINVAL; - break; - case UDP_V4_FLOW: - if (!(nfc->data & RXH_IP_SRC) || - !(nfc->data & RXH_IP_DST)) - return -EINVAL; - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV4; - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): - rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV4; - break; - default: - return -EINVAL; - } - break; - case UDP_V6_FLOW: - if (!(nfc->data & RXH_IP_SRC) || - !(nfc->data & RXH_IP_DST)) - return -EINVAL; - switch (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) { - case 0: - rss_flags &= ~RTL_8125_RSS_FLAG_HASH_UDP_IPV6; - break; - case (RXH_L4_B_0_1 | RXH_L4_B_2_3): - rss_flags |= RTL_8125_RSS_FLAG_HASH_UDP_IPV6; - break; - default: - return -EINVAL; - } - break; - case SCTP_V4_FLOW: - case AH_ESP_V4_FLOW: - case AH_V4_FLOW: - case ESP_V4_FLOW: - case SCTP_V6_FLOW: - case AH_ESP_V6_FLOW: - case AH_V6_FLOW: - case ESP_V6_FLOW: - case IP_USER_FLOW: - case ETHER_FLOW: - /* RSS is not supported for these protocols */ - if (nfc->data) { - netif_err(tp, drv, tp->dev, "Command parameters not supported\n"); - return -EINVAL; - } - return 0; - break; - default: - return -EINVAL; - } - - /* if we changed something we need to update flags */ - if (rss_flags != tp->rss_flags) { - u32 rss_ctrl = RTL_R32(tp, RSS_CTRL_8125); - - if ((rss_flags & RTL8125_UDP_RSS_FLAGS) && - !(tp->rss_flags & RTL8125_UDP_RSS_FLAGS)) - netdev_warn(tp->dev, - "enabling UDP RSS: fragmented packets may " - "arrive out of order to the stack above\n"); - - tp->rss_flags = rss_flags; - - /* Perform hash on these packet types */ - rss_ctrl |= RSS_CTRL_TCP_IPV4_SUPP - | RSS_CTRL_IPV4_SUPP - | RSS_CTRL_IPV6_SUPP - | RSS_CTRL_TCP_IPV6_SUPP; - - rss_ctrl &= ~(RSS_CTRL_UDP_IPV4_SUPP | - RSS_CTRL_UDP_IPV6_SUPP); - - if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV4) - rss_ctrl |= RSS_CTRL_UDP_IPV4_SUPP; - - if (rss_flags & RTL_8125_RSS_FLAG_HASH_UDP_IPV6) - rss_ctrl |= RSS_CTRL_UDP_IPV6_SUPP; - - RTL_W32(tp, RSS_CTRL_8125, rss_ctrl); - } - - return 0; -} - -int rtl8125_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int ret = -EOPNOTSUPP; - - netif_info(tp, drv, tp->dev, "rss set rxnfc\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return ret; - - switch (cmd->cmd) { - case ETHTOOL_SRXFH: - ret = rtl8125_set_rss_hash_opt(tp, cmd); - break; - default: - break; - } - - return ret; -} - -static u32 _rtl8125_get_rxfh_key_size(struct rtl8125_private *tp) -{ - return sizeof(tp->rss_key); -} - -u32 rtl8125_get_rxfh_key_size(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - netif_info(tp, drv, tp->dev, "rss get key size\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return 0; - - return _rtl8125_get_rxfh_key_size(tp); -} - -u32 rtl8125_rss_indir_size(struct net_device *dev) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - netif_info(tp, drv, tp->dev, "rss get indir tbl size\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return 0; - - return rtl8125_rss_indir_tbl_entries(tp); -} - -static void rtl8125_get_reta(struct rtl8125_private *tp, u32 *indir) -{ - int i, reta_size = rtl8125_rss_indir_tbl_entries(tp); - - for (i = 0; i < reta_size; i++) - indir[i] = tp->rss_indir_tbl[i]; -} - -int rtl8125_get_rxfh(struct net_device *dev, u32 *indir, u8 *key, - u8 *hfunc) -{ - struct rtl8125_private *tp = netdev_priv(dev); - - netif_info(tp, drv, tp->dev, "rss get rxfh\n"); - - if (!(dev->features & NETIF_F_RXHASH)) - return -EOPNOTSUPP; - - if (hfunc) - *hfunc = ETH_RSS_HASH_TOP; - - if (indir) - rtl8125_get_reta(tp, indir); - - if (key) - memcpy(key, tp->rss_key, rtl8125_get_rxfh_key_size(dev)); - - return 0; -} - -static u32 rtl8125_rss_key_reg(struct rtl8125_private *tp) -{ - return RSS_KEY_8125; -} - -static u32 rtl8125_rss_indir_tbl_reg(struct rtl8125_private *tp) -{ - return RSS_INDIRECTION_TBL_8125_V2; -} - -static void rtl8125_store_reta(struct rtl8125_private *tp) -{ - u16 indir_tbl_reg = rtl8125_rss_indir_tbl_reg(tp); - u32 i, reta_entries = rtl8125_rss_indir_tbl_entries(tp); - u32 reta = 0; - u8 *indir_tbl = tp->rss_indir_tbl; - - /* Write redirection table to HW */ - for (i = 0; i < reta_entries; i++) { - reta |= indir_tbl[i] << (i & 0x3) * 8; - if ((i & 3) == 3) { - RTL_W32(tp, indir_tbl_reg, reta); - - indir_tbl_reg += 4; - reta = 0; - } - } -} - -static void rtl8125_store_rss_key(struct rtl8125_private *tp) -{ - const u16 rss_key_reg = rtl8125_rss_key_reg(tp); - u32 i, rss_key_size = _rtl8125_get_rxfh_key_size(tp); - u32 *rss_key = (u32*)tp->rss_key; - - /* Write redirection table to HW */ - for (i = 0; i < rss_key_size; i+=4) - RTL_W32(tp, rss_key_reg + i, *rss_key++); -} - -int rtl8125_set_rxfh(struct net_device *dev, const u32 *indir, - const u8 *key, const u8 hfunc) -{ - struct rtl8125_private *tp = netdev_priv(dev); - int i; - u32 reta_entries = rtl8125_rss_indir_tbl_entries(tp); - - netif_info(tp, drv, tp->dev, "rss set rxfh\n"); - - /* We require at least one supported parameter to be changed and no - * change in any of the unsupported parameters - */ - if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) - return -EOPNOTSUPP; - - /* Fill out the redirection table */ - if (indir) { - int max_queues = tp->num_rx_rings; - - /* Verify user input. */ - for (i = 0; i < reta_entries; i++) - if (indir[i] >= max_queues) - return -EINVAL; - - for (i = 0; i < reta_entries; i++) - tp->rss_indir_tbl[i] = indir[i]; - } - - /* Fill out the rss hash key */ - if (key) - memcpy(tp->rss_key, key, rtl8125_get_rxfh_key_size(dev)); - - rtl8125_store_reta(tp); - - rtl8125_store_rss_key(tp); - - return 0; -} - -static u32 rtl8125_get_rx_desc_hash(struct rtl8125_private *tp, - struct RxDescV3 *descv3) -{ - return le32_to_cpu(descv3->RxDescNormalDDWord2.RSSResult); -} - -#define RXS_8125B_RSS_UDP BIT(9) -#define RXS_8125_RSS_IPV4 BIT(10) -#define RXS_8125_RSS_IPV6 BIT(12) -#define RXS_8125_RSS_TCP BIT(13) -#define RTL8125_RXS_RSS_L3_TYPE_MASK (RXS_8125_RSS_IPV4 | RXS_8125_RSS_IPV6) -#define RTL8125_RXS_RSS_L4_TYPE_MASK (RXS_8125_RSS_TCP | RXS_8125B_RSS_UDP) -void rtl8125_rx_hash(struct rtl8125_private *tp, - struct RxDescV3 *descv3, - struct sk_buff *skb) -{ - u16 rss_header_info; - - if (!(tp->dev->features & NETIF_F_RXHASH)) - return; - - rss_header_info = le16_to_cpu(descv3->RxDescNormalDDWord2.HeaderInfo); - - if (!(rss_header_info & RTL8125_RXS_RSS_L3_TYPE_MASK)) - return; - - skb_set_hash(skb, rtl8125_get_rx_desc_hash(tp, descv3), - (RTL8125_RXS_RSS_L4_TYPE_MASK & rss_header_info) ? - PKT_HASH_TYPE_L4 : PKT_HASH_TYPE_L3); -} - -void rtl8125_disable_rss(struct rtl8125_private *tp) -{ - RTL_W32(tp, RSS_CTRL_8125, 0x00); -} - -void _rtl8125_config_rss(struct rtl8125_private *tp) -{ - _rtl8125_set_rss_hash_opt(tp); - - rtl8125_store_reta(tp); - - rtl8125_store_rss_key(tp); -} - -void rtl8125_config_rss(struct rtl8125_private *tp) -{ - if (!tp->EnableRss) { - rtl8125_disable_rss(tp); - return; - } - - _rtl8125_config_rss(tp); -} - -void rtl8125_init_rss(struct rtl8125_private *tp) -{ - int i; - - for (i = 0; i < rtl8125_rss_indir_tbl_entries(tp); i++) - tp->rss_indir_tbl[i] = ethtool_rxfh_indir_default(i, tp->num_rx_rings); - - netdev_rss_key_fill(tp->rss_key, RTL8125_RSS_KEY_SIZE); -} diff --git a/addons/r8125/src/4.4.180/r8125_rss.h b/addons/r8125/src/4.4.180/r8125_rss.h deleted file mode 100755 index 88641395..00000000 --- a/addons/r8125/src/4.4.180/r8125_rss.h +++ /dev/null @@ -1,69 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_rtl8125_RSS_H -#define _LINUX_rtl8125_RSS_H - -#include -#include - -#define RTL8125_RSS_KEY_SIZE 40 /* size of RSS Hash Key in bytes */ -#define RTL8125_MAX_INDIRECTION_TABLE_ENTRIES 128 - -enum rtl8125_rss_flag { - RTL_8125_RSS_FLAG_HASH_UDP_IPV4 = (1 << 0), - RTL_8125_RSS_FLAG_HASH_UDP_IPV6 = (1 << 1), -}; - -struct rtl8125_private; - -int rtl8125_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd, - u32 *rule_locs); -int rtl8125_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd); -u32 rtl8125_get_rxfh_key_size(struct net_device *netdev); -u32 rtl8125_rss_indir_size(struct net_device *netdev); -int rtl8125_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, - u8 *hfunc); -int rtl8125_set_rxfh(struct net_device *netdev, const u32 *indir, - const u8 *key, const u8 hfunc); -void rtl8125_rx_hash(struct rtl8125_private *tp, - struct RxDescV3 *descv3, - struct sk_buff *skb); -void _rtl8125_config_rss(struct rtl8125_private *tp); -void rtl8125_config_rss(struct rtl8125_private *tp); -void rtl8125_init_rss(struct rtl8125_private *tp); -u32 rtl8125_rss_indir_tbl_entries(struct rtl8125_private *tp); -void rtl8125_disable_rss(struct rtl8125_private *tp); - -#endif /* _LINUX_rtl8125_RSS_H */ diff --git a/addons/r8125/src/4.4.180/rtl_eeprom.c b/addons/r8125/src/4.4.180/rtl_eeprom.c deleted file mode 100755 index 03660dda..00000000 --- a/addons/r8125/src/4.4.180/rtl_eeprom.c +++ /dev/null @@ -1,289 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include - -#include "r8125.h" -#include "rtl_eeprom.h" - -//------------------------------------------------------------------- -//rtl8125_eeprom_type(): -// tell the eeprom type -//return value: -// 0: the eeprom type is 93C46 -// 1: the eeprom type is 93C56 or 93C66 -//------------------------------------------------------------------- -void rtl8125_eeprom_type(struct rtl8125_private *tp) -{ - u16 magic = 0; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - goto out_no_eeprom; - - if(RTL_R8(tp, 0xD2)&0x04) { - //not support - //tp->eeprom_type = EEPROM_TWSI; - //tp->eeprom_len = 256; - goto out_no_eeprom; - } else if(RTL_R32(tp, RxConfig) & RxCfg_9356SEL) { - tp->eeprom_type = EEPROM_TYPE_93C56; - tp->eeprom_len = 256; - } else { - tp->eeprom_type = EEPROM_TYPE_93C46; - tp->eeprom_len = 128; - } - - magic = rtl8125_eeprom_read_sc(tp, 0); - -out_no_eeprom: - if ((magic != 0x8129) && (magic != 0x8128)) { - tp->eeprom_type = EEPROM_TYPE_NONE; - tp->eeprom_len = 0; - } -} - -void rtl8125_eeprom_cleanup(struct rtl8125_private *tp) -{ - u8 x; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EECS); - - RTL_W8(tp, Cfg9346, x); - - rtl8125_raise_clock(tp, &x); - rtl8125_lower_clock(tp, &x); -} - -int rtl8125_eeprom_cmd_done(struct rtl8125_private *tp) -{ - u8 x; - int i; - - rtl8125_stand_by(tp); - - for (i = 0; i < 50000; i++) { - x = RTL_R8(tp, Cfg9346); - - if (x & Cfg9346_EEDO) { - udelay(RTL_CLOCK_RATE * 2 * 3); - return 0; - } - udelay(1); - } - - return -1; -} - -//------------------------------------------------------------------- -//rtl8125_eeprom_read_sc(): -// read one word from eeprom -//------------------------------------------------------------------- -u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg) -{ - int addr_sz = 6; - u8 x; - u16 data; - - if(tp->eeprom_type == EEPROM_TYPE_NONE) { - return -1; - } - - if (tp->eeprom_type==EEPROM_TYPE_93C46) - addr_sz = 6; - else if (tp->eeprom_type==EEPROM_TYPE_93C56) - addr_sz = 8; - - x = Cfg9346_EEM1 | Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_READ_OPCODE, 3); - rtl8125_shift_out_bits(tp, reg, addr_sz); - - data = rtl8125_shift_in_bits(tp); - - rtl8125_eeprom_cleanup(tp); - - RTL_W8(tp, Cfg9346, 0); - - return data; -} - -//------------------------------------------------------------------- -//rtl8125_eeprom_write_sc(): -// write one word to a specific address in the eeprom -//------------------------------------------------------------------- -void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data) -{ - u8 x; - int addr_sz = 6; - int w_dummy_addr = 4; - - if(tp->eeprom_type == EEPROM_TYPE_NONE) { - return ; - } - - if (tp->eeprom_type==EEPROM_TYPE_93C46) { - addr_sz = 6; - w_dummy_addr = 4; - } else if (tp->eeprom_type==EEPROM_TYPE_93C56) { - addr_sz = 8; - w_dummy_addr = 6; - } - - x = Cfg9346_EEM1 | Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_EWEN_OPCODE, 5); - rtl8125_shift_out_bits(tp, reg, w_dummy_addr); - rtl8125_stand_by(tp); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3); - rtl8125_shift_out_bits(tp, reg, addr_sz); - if (rtl8125_eeprom_cmd_done(tp) < 0) { - return; - } - rtl8125_stand_by(tp); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3); - rtl8125_shift_out_bits(tp, reg, addr_sz); - rtl8125_shift_out_bits(tp, data, 16); - if (rtl8125_eeprom_cmd_done(tp) < 0) { - return; - } - rtl8125_stand_by(tp); - - rtl8125_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5); - rtl8125_shift_out_bits(tp, reg, w_dummy_addr); - - rtl8125_eeprom_cleanup(tp); - RTL_W8(tp, Cfg9346, 0); -} - -void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x) -{ - *x = *x | Cfg9346_EESK; - RTL_W8(tp, Cfg9346, *x); - udelay(RTL_CLOCK_RATE); -} - -void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x) -{ - - *x = *x & ~Cfg9346_EESK; - RTL_W8(tp, Cfg9346, *x); - udelay(RTL_CLOCK_RATE); -} - -void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count) -{ - u8 x; - int mask; - - mask = 0x01 << (count - 1); - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); - - do { - if (data & mask) - x |= Cfg9346_EEDI; - else - x &= ~Cfg9346_EEDI; - - RTL_W8(tp, Cfg9346, x); - udelay(RTL_CLOCK_RATE); - rtl8125_raise_clock(tp, &x); - rtl8125_lower_clock(tp, &x); - mask = mask >> 1; - } while(mask); - - x &= ~Cfg9346_EEDI; - RTL_W8(tp, Cfg9346, x); -} - -u16 rtl8125_shift_in_bits(struct rtl8125_private *tp) -{ - u8 x; - u16 d, i; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); - - d = 0; - - for (i = 0; i < 16; i++) { - d = d << 1; - rtl8125_raise_clock(tp, &x); - - x = RTL_R8(tp, Cfg9346); - x &= ~Cfg9346_EEDI; - - if (x & Cfg9346_EEDO) - d |= 1; - - rtl8125_lower_clock(tp, &x); - } - - return d; -} - -void rtl8125_stand_by(struct rtl8125_private *tp) -{ - u8 x; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EECS | Cfg9346_EESK); - RTL_W8(tp, Cfg9346, x); - udelay(RTL_CLOCK_RATE); - - x |= Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); -} - -void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp) -{ - RTL_W8(tp, Cfg9346, Cfg9346_EEM1); - RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK); - - udelay(20); - - RTL_W8(tp, Cfg9346, Cfg9346_EEM1); -} diff --git a/addons/r8125/src/4.4.180/rtl_eeprom.h b/addons/r8125/src/4.4.180/rtl_eeprom.h deleted file mode 100755 index 8faed17c..00000000 --- a/addons/r8125/src/4.4.180/rtl_eeprom.h +++ /dev/null @@ -1,53 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -//EEPROM opcodes -#define RTL_EEPROM_READ_OPCODE 06 -#define RTL_EEPROM_WRITE_OPCODE 05 -#define RTL_EEPROM_ERASE_OPCODE 07 -#define RTL_EEPROM_EWEN_OPCODE 19 -#define RTL_EEPROM_EWDS_OPCODE 16 - -#define RTL_CLOCK_RATE 3 - -void rtl8125_eeprom_type(struct rtl8125_private *tp); -void rtl8125_eeprom_cleanup(struct rtl8125_private *tp); -u16 rtl8125_eeprom_read_sc(struct rtl8125_private *tp, u16 reg); -void rtl8125_eeprom_write_sc(struct rtl8125_private *tp, u16 reg, u16 data); -void rtl8125_shift_out_bits(struct rtl8125_private *tp, int data, int count); -u16 rtl8125_shift_in_bits(struct rtl8125_private *tp); -void rtl8125_raise_clock(struct rtl8125_private *tp, u8 *x); -void rtl8125_lower_clock(struct rtl8125_private *tp, u8 *x); -void rtl8125_stand_by(struct rtl8125_private *tp); -void rtl8125_set_eeprom_sel_low(struct rtl8125_private *tp); diff --git a/addons/r8125/src/4.4.180/rtltool.c b/addons/r8125/src/4.4.180/rtltool.c deleted file mode 100755 index f40df6fe..00000000 --- a/addons/r8125/src/4.4.180/rtltool.c +++ /dev/null @@ -1,260 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "r8125.h" -#include "rtl_eeprom.h" -#include "rtltool.h" - -int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr) -{ - struct rtltool_cmd my_cmd; - int ret; - - if (copy_from_user(&my_cmd, ifr->ifr_data, sizeof(my_cmd))) - return -EFAULT; - - ret = 0; - switch (my_cmd.cmd) { - case RTLTOOL_READ_MAC: - if (my_cmd.len==1) - my_cmd.data = readb(tp->mmio_addr+my_cmd.offset); - else if (my_cmd.len==2) - my_cmd.data = readw(tp->mmio_addr+(my_cmd.offset&~1)); - else if (my_cmd.len==4) - my_cmd.data = readl(tp->mmio_addr+(my_cmd.offset&~3)); - else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTLTOOL_WRITE_MAC: - if (my_cmd.len==1) - writeb(my_cmd.data, tp->mmio_addr+my_cmd.offset); - else if (my_cmd.len==2) - writew(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~1)); - else if (my_cmd.len==4) - writel(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~3)); - else { - ret = -EOPNOTSUPP; - break; - } - - break; - - case RTLTOOL_READ_PHY: - my_cmd.data = rtl8125_mdio_prot_read(tp, my_cmd.offset); - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_PHY: - rtl8125_mdio_prot_write(tp, my_cmd.offset, my_cmd.data); - break; - - case RTLTOOL_READ_EPHY: - my_cmd.data = rtl8125_ephy_read(tp, my_cmd.offset); - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_EPHY: - rtl8125_ephy_write(tp, my_cmd.offset, my_cmd.data); - break; - - case RTLTOOL_READ_ERI: - my_cmd.data = 0; - if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { - my_cmd.data = rtl8125_eri_read(tp, my_cmd.offset, my_cmd.len, ERIAR_ExGMAC); - } else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_ERI: - if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { - rtl8125_eri_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC); - } else { - ret = -EOPNOTSUPP; - break; - } - break; - - case RTLTOOL_READ_PCI: - my_cmd.data = 0; - if (my_cmd.len==1) - pci_read_config_byte(tp->pci_dev, my_cmd.offset, - (u8 *)&my_cmd.data); - else if (my_cmd.len==2) - pci_read_config_word(tp->pci_dev, my_cmd.offset, - (u16 *)&my_cmd.data); - else if (my_cmd.len==4) - pci_read_config_dword(tp->pci_dev, my_cmd.offset, - &my_cmd.data); - else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTLTOOL_WRITE_PCI: - if (my_cmd.len==1) - pci_write_config_byte(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else if (my_cmd.len==2) - pci_write_config_word(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else if (my_cmd.len==4) - pci_write_config_dword(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else { - ret = -EOPNOTSUPP; - break; - } - - break; - - case RTLTOOL_READ_EEPROM: - my_cmd.data = rtl8125_eeprom_read_sc(tp, my_cmd.offset); - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_EEPROM: - rtl8125_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data); - break; - - case RTL_READ_OOB_MAC: - rtl8125_oob_mutex_lock(tp); - my_cmd.data = rtl8125_ocp_read(tp, my_cmd.offset, 4); - rtl8125_oob_mutex_unlock(tp); - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTL_WRITE_OOB_MAC: - if (my_cmd.len == 0 || my_cmd.len > 4) - return -EOPNOTSUPP; - - rtl8125_oob_mutex_lock(tp); - rtl8125_ocp_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data); - rtl8125_oob_mutex_unlock(tp); - break; - - case RTL_ENABLE_PCI_DIAG: - tp->rtk_enable_diag = 1; - - dprintk("enable rtk diag\n"); - break; - - case RTL_DISABLE_PCI_DIAG: - tp->rtk_enable_diag = 0; - - dprintk("disable rtk diag\n"); - break; - - case RTL_READ_MAC_OCP: - if (my_cmd.offset % 2) - return -EOPNOTSUPP; - - my_cmd.data = rtl8125_mac_ocp_read(tp, my_cmd.offset); - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTL_WRITE_MAC_OCP: - if ((my_cmd.offset % 2) || (my_cmd.len != 2)) - return -EOPNOTSUPP; - - rtl8125_mac_ocp_write(tp, my_cmd.offset, (u16)my_cmd.data); - break; - - case RTL_DIRECT_READ_PHY_OCP: - my_cmd.data = rtl8125_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset); - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTL_DIRECT_WRITE_PHY_OCP: - rtl8125_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} diff --git a/addons/r8125/src/4.4.180/rtltool.h b/addons/r8125/src/4.4.180/rtltool.h deleted file mode 100755 index a54f8e6a..00000000 --- a/addons/r8125/src/4.4.180/rtltool.h +++ /dev/null @@ -1,86 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8125 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2022 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_RTLTOOL_H -#define _LINUX_RTLTOOL_H - -#define SIOCRTLTOOL SIOCDEVPRIVATE+1 - -enum rtl_cmd { - RTLTOOL_READ_MAC=0, - RTLTOOL_WRITE_MAC, - RTLTOOL_READ_PHY, - RTLTOOL_WRITE_PHY, - RTLTOOL_READ_EPHY, - RTLTOOL_WRITE_EPHY, - RTLTOOL_READ_ERI, - RTLTOOL_WRITE_ERI, - RTLTOOL_READ_PCI, - RTLTOOL_WRITE_PCI, - RTLTOOL_READ_EEPROM, - RTLTOOL_WRITE_EEPROM, - - RTL_READ_OOB_MAC, - RTL_WRITE_OOB_MAC, - - RTL_ENABLE_PCI_DIAG, - RTL_DISABLE_PCI_DIAG, - - RTL_READ_MAC_OCP, - RTL_WRITE_MAC_OCP, - - RTL_DIRECT_READ_PHY_OCP, - RTL_DIRECT_WRITE_PHY_OCP, - - RTLTOOL_INVALID -}; - -struct rtltool_cmd { - __u32 cmd; - __u32 offset; - __u32 len; - __u32 data; -}; - -enum mode_access { - MODE_NONE=0, - MODE_READ, - MODE_WRITE -}; - -#ifdef __KERNEL__ -int rtl8125_tool_ioctl(struct rtl8125_private *tp, struct ifreq *ifr); -#endif - -#endif /* _LINUX_RTLTOOL_H */ diff --git a/addons/r8168/install.sh b/addons/r8168/install.sh deleted file mode 100644 index 8794d078..00000000 --- a/addons/r8168/install.sh +++ /dev/null @@ -1,4 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Installing module for Realtek R8168/8111 Ethernet adapter" - ${INSMOD} "/modules/r8168.ko" ${PARAMS} -fi diff --git a/addons/r8168/manifest.yml b/addons/r8168/manifest.yml deleted file mode 100644 index 53e5d9bf..00000000 --- a/addons/r8168/manifest.yml +++ /dev/null @@ -1,30 +0,0 @@ -version: 1 -name: r8168 -description: "Driver for Realtek R8168/8111 Ethernet adapters" -conflits: - - r8169 -available-for: - bromolow-3.10.108: - install-script: &script "install.sh" - modules: true - apollolake-4.4.180: - install-script: *script - modules: true - broadwell-4.4.180: - install-script: *script - modules: true - broadwellnk-4.4.180: - install-script: *script - modules: true - denverton-4.4.180: - install-script: *script - modules: true - geminilake-4.4.180: - install-script: *script - modules: true - v1000-4.4.180: - install-script: *script - modules: true - purley-4.4.180: - install-script: *script - modules: true diff --git a/addons/r8168/src/3.10.108/Makefile b/addons/r8168/src/3.10.108/Makefile deleted file mode 100644 index 74c19689..00000000 --- a/addons/r8168/src/3.10.108/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -CONFIG_SOC_LAN = n -ENABLE_FIBER_SUPPORT = n -ENABLE_REALWOW_SUPPORT = n -ENABLE_DASH_SUPPORT = n -ENABLE_DASH_PRINTER_SUPPORT = n -CONFIG_DOWN_SPEED_100 = n -CONFIG_ASPM = y -ENABLE_S5WOL = y -ENABLE_S5_KEEP_CURR_MAC = n -ENABLE_EEE = y -ENABLE_S0_MAGIC_PACKET = n -CONFIG_DYNAMIC_ASPM = y -ENABLE_USE_FIRMWARE_FILE = n - -obj-m := r8168.o -r8168-objs := r8168_n.o r8168_asf.o rtl_eeprom.o rtltool.o -ifeq ($(CONFIG_SOC_LAN), y) - EXTRA_CFLAGS += -DCONFIG_SOC_LAN -endif -ifeq ($(ENABLE_FIBER_SUPPORT), y) - r8168-objs += r8168_fiber.o - EXTRA_CFLAGS += -DENABLE_FIBER_SUPPORT -endif -ifeq ($(ENABLE_REALWOW_SUPPORT), y) - r8168-objs += r8168_realwow.o - EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT -endif -ifeq ($(ENABLE_DASH_SUPPORT), y) - r8168-objs += r8168_dash.o - EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -endif -ifeq ($(ENABLE_DASH_PRINTER_SUPPORT), y) - r8168-objs += r8168_dash.o - EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT -endif -EXTRA_CFLAGS += -DCONFIG_R8168_NAPI -EXTRA_CFLAGS += -DCONFIG_R8168_VLAN -ifeq ($(CONFIG_DOWN_SPEED_100), y) - EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100 -endif -ifeq ($(CONFIG_ASPM), y) - EXTRA_CFLAGS += -DCONFIG_ASPM -endif -ifeq ($(ENABLE_S5WOL), y) - EXTRA_CFLAGS += -DENABLE_S5WOL -endif -ifeq ($(ENABLE_S5_KEEP_CURR_MAC), y) - EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC -endif -ifeq ($(ENABLE_EEE), y) - EXTRA_CFLAGS += -DENABLE_EEE -endif -ifeq ($(ENABLE_S0_MAGIC_PACKET), y) - EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET -endif -ifeq ($(CONFIG_DYNAMIC_ASPM), y) - EXTRA_CFLAGS += -DCONFIG_DYNAMIC_ASPM -endif -ifeq ($(ENABLE_USE_FIRMWARE_FILE), y) - r8168-objs += r8168_firmware.o - EXTRA_CFLAGS += -DENABLE_USE_FIRMWARE_FILE -endif diff --git a/addons/r8168/src/3.10.108/r8168.h b/addons/r8168/src/3.10.108/r8168.h deleted file mode 100644 index 4bd1047a..00000000 --- a/addons/r8168/src/3.10.108/r8168.h +++ /dev/null @@ -1,1842 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include "r8168_dash.h" -#include "r8168_realwow.h" -#include "r8168_fiber.h" - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) -typedef int netdev_tx_t; -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -#define skb_transport_offset(skb) (skb->h.raw - skb->data) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) -#define device_set_wakeup_enable(dev, val) do {} while (0) -#endif - -#if 0 -static inline void ether_addr_copy(u8 *dst, const u8 *src) -{ - u16 *a = (u16 *)dst; - const u16 *b = (const u16 *)src; - - a[0] = b[0]; - a[1] = b[1]; - a[2] = b[2]; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) -#define IS_ERR_OR_NULL(ptr) (!ptr) -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) -#define reinit_completion(x) ((x)->done = 0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) -#define pm_runtime_mark_last_busy(x) -#define pm_runtime_put_autosuspend(x) pm_runtime_put(x) -#define pm_runtime_put_sync_autosuspend(x) pm_runtime_put_sync(x) - -static inline bool pm_runtime_suspended(struct device *dev) -{ - return dev->power.runtime_status == RPM_SUSPENDED - && !dev->power.disable_depth; -} - -static inline bool pm_runtime_active(struct device *dev) -{ - return dev->power.runtime_status == RPM_ACTIVE - || dev->power.disable_depth; -} -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) -#define queue_delayed_work(long_wq, work, delay) schedule_delayed_work(work, delay) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) -#define netif_printk(priv, type, level, netdev, fmt, args...) \ - do { \ - if (netif_msg_##type(priv)) \ - printk(level "%s: " fmt,(netdev)->name , ##args); \ - } while (0) - -#define netif_emerg(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_EMERG, netdev, fmt, ##args) -#define netif_alert(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_ALERT, netdev, fmt, ##args) -#define netif_crit(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_CRIT, netdev, fmt, ##args) -#define netif_err(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_ERR, netdev, fmt, ##args) -#define netif_warn(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_WARNING, netdev, fmt, ##args) -#define netif_notice(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_NOTICE, netdev, fmt, ##args) -#define netif_info(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_INFO, (netdev), fmt, ##args) -#endif -#endif -#endif -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) -#define setup_timer(_timer, _function, _data) \ -do { \ - (_timer)->function = _function; \ - (_timer)->data = _data; \ - init_timer(_timer); \ -} while (0) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) -#if defined(skb_vlan_tag_present) && !defined(vlan_tx_tag_present) -#define vlan_tx_tag_present skb_vlan_tag_present -#endif -#if defined(skb_vlan_tag_get) && !defined(vlan_tx_tag_get) -#define vlan_tx_tag_get skb_vlan_tag_get -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) - -#define RTL_ALLOC_SKB_INTR(tp, length) dev_alloc_skb(length) -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) -#undef RTL_ALLOC_SKB_INTR -#define RTL_ALLOC_SKB_INTR(tp, length) napi_alloc_skb(&tp->napi, length) -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) -#define netdev_features_t u32 -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) -#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK -#else -#ifndef NETIF_F_ALL_CSUM -#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) -#define ENABLE_R8168_PROCFS -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -#define NETIF_F_HW_VLAN_RX NETIF_F_HW_VLAN_CTAG_RX -#define NETIF_F_HW_VLAN_TX NETIF_F_HW_VLAN_CTAG_TX -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) -#define __devinit -#define __devexit -#define __devexit_p(func) func -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -#define CHECKSUM_PARTIAL CHECKSUM_HW -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define irqreturn_t void -#define IRQ_HANDLED 1 -#define IRQ_NONE 0 -#define IRQ_RETVAL(x) -#endif - -#ifndef NETIF_F_RXALL -#define NETIF_F_RXALL 0 -#endif - -#ifndef NETIF_F_RXFCS -#define NETIF_F_RXFCS 0 -#endif - -#ifndef HAVE_FREE_NETDEV -#define free_netdev(x) kfree(x) -#endif - -#ifndef SET_NETDEV_DEV -#define SET_NETDEV_DEV(net, pdev) -#endif - -#ifndef SET_MODULE_OWNER -#define SET_MODULE_OWNER(dev) -#endif - -#ifndef SA_SHIRQ -#define SA_SHIRQ IRQF_SHARED -#endif - -#ifndef NETIF_F_GSO -#define gso_size tso_size -#define gso_segs tso_segs -#endif - -#ifndef PCI_VENDOR_ID_DLINK -#define PCI_VENDOR_ID_DLINK 0x1186 -#endif - -#ifndef dma_mapping_error -#define dma_mapping_error(a,b) 0 -#endif - -#ifndef netif_err -#define netif_err(a,b,c,d) -#endif - -#ifndef AUTONEG_DISABLE -#define AUTONEG_DISABLE 0x00 -#endif - -#ifndef AUTONEG_ENABLE -#define AUTONEG_ENABLE 0x01 -#endif - -#ifndef BMCR_SPEED1000 -#define BMCR_SPEED1000 0x0040 -#endif - -#ifndef BMCR_SPEED100 -#define BMCR_SPEED100 0x2000 -#endif - -#ifndef BMCR_SPEED10 -#define BMCR_SPEED10 0x0000 -#endif - -#ifndef SPEED_UNKNOWN -#define SPEED_UNKNOWN -1 -#endif - -#ifndef DUPLEX_UNKNOWN -#define DUPLEX_UNKNOWN 0xff -#endif - -#ifndef SUPPORTED_Pause -#define SUPPORTED_Pause (1 << 13) -#endif - -#ifndef SUPPORTED_Asym_Pause -#define SUPPORTED_Asym_Pause (1 << 14) -#endif - -#ifndef MDIO_EEE_100TX -#define MDIO_EEE_100TX 0x0002 -#endif - -#ifndef MDIO_EEE_1000T -#define MDIO_EEE_1000T 0x0004 -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -#ifdef CONFIG_NET_POLL_CONTROLLER -#define RTL_NET_POLL_CONTROLLER dev->poll_controller=rtl8168_netpoll -#else -#define RTL_NET_POLL_CONTROLLER -#endif - -#ifdef CONFIG_R8168_VLAN -#define RTL_SET_VLAN dev->vlan_rx_register=rtl8168_vlan_rx_register -#else -#define RTL_SET_VLAN -#endif - -#define RTL_NET_DEVICE_OPS(ops) dev->open=rtl8168_open; \ - dev->hard_start_xmit=rtl8168_start_xmit; \ - dev->get_stats=rtl8168_get_stats; \ - dev->stop=rtl8168_close; \ - dev->tx_timeout=rtl8168_tx_timeout; \ - dev->set_multicast_list=rtl8168_set_rx_mode; \ - dev->change_mtu=rtl8168_change_mtu; \ - dev->set_mac_address=rtl8168_set_mac_address; \ - dev->do_ioctl=rtl8168_do_ioctl; \ - RTL_NET_POLL_CONTROLLER; \ - RTL_SET_VLAN; -#else -#define RTL_NET_DEVICE_OPS(ops) dev->netdev_ops=&ops -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef false -#define false 0 -#endif - -#ifndef true -#define true 1 -#endif - -//Hardware will continue interrupt 10 times after interrupt finished. -#define RTK_KEEP_INTERRUPT_COUNT (10) - -//Due to the hardware design of RTL8111B, the low 32 bit address of receive -//buffer must be 8-byte alignment. -#ifndef NET_IP_ALIGN -#define NET_IP_ALIGN 2 -#endif -#define RTK_RX_ALIGN 8 - -#ifdef CONFIG_R8168_NAPI -#define NAPI_SUFFIX "-NAPI" -#else -#define NAPI_SUFFIX "" -#endif -#ifdef ENABLE_FIBER_SUPPORT -#define FIBER_SUFFIX "-FIBER" -#else -#define FIBER_SUFFIX "" -#endif -#ifdef ENABLE_REALWOW_SUPPORT -#define REALWOW_SUFFIX "-REALWOW" -#else -#define REALWOW_SUFFIX "" -#endif -#if defined(ENABLE_DASH_PRINTER_SUPPORT) -#define DASH_SUFFIX "-PRINTER" -#elif defined(ENABLE_DASH_SUPPORT) -#define DASH_SUFFIX "-DASH" -#else -#define DASH_SUFFIX "" -#endif - -#define RTL8168_VERSION "8.049.02" NAPI_SUFFIX FIBER_SUFFIX REALWOW_SUFFIX DASH_SUFFIX -#define MODULENAME "r8168" -#define PFX MODULENAME ": " - -#define GPL_CLAIM "\ -r8168 Copyright (C) 2021 Realtek NIC software team \n \ -This program comes with ABSOLUTELY NO WARRANTY; for details, please see . \n \ -This is free software, and you are welcome to redistribute it under certain conditions; see . \n" - -#ifdef RTL8168_DEBUG -#define assert(expr) \ - if(!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8168_DEBUG */ - -#define R8168_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#ifdef CONFIG_R8168_NAPI -#define rtl8168_rx_hwaccel_skb vlan_hwaccel_receive_skb -#define rtl8168_rx_quota(count, quota) min(count, quota) -#else -#define rtl8168_rx_hwaccel_skb vlan_hwaccel_rx -#define rtl8168_rx_quota(count, quota) count -#endif - -/* MAC address length */ -#ifndef MAC_ADDR_LEN -#define MAC_ADDR_LEN 6 -#endif - -#ifndef MAC_PROTOCOL_LEN -#define MAC_PROTOCOL_LEN 2 -#endif - -#ifndef ETH_FCS_LEN -#define ETH_FCS_LEN 4 -#endif - -#ifndef NETIF_F_TSO6 -#define NETIF_F_TSO6 0 -#endif - -#define Reserved2_data 7 -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST_unlimited 7 -#define TX_DMA_BURST_1024 6 -#define TX_DMA_BURST_512 5 -#define TX_DMA_BURST_256 4 -#define TX_DMA_BURST_128 3 -#define TX_DMA_BURST_64 2 -#define TX_DMA_BURST_32 1 -#define TX_DMA_BURST_16 0 -#define Reserved1_data 0x3F -#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ -#define Jumbo_Frame_1k ETH_DATA_LEN -#define Jumbo_Frame_2k (2*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_3k (3*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_4k (4*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_5k (5*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_6k (6*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_7k (7*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_8k (8*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_9k (9*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ -#define RxEarly_off_V1 (0x07 << 11) -#define RxEarly_off_V2 (1 << 11) -#define Rx_Single_fetch_V2 (1 << 14) - -#define R8168_REGS_SIZE (256) -#define R8168_MAC_REGS_SIZE (256) -#define R8168_PHY_REGS_SIZE (16*2) -#define R8168_EPHY_REGS_SIZE (31*2) -#define R8168_ERI_REGS_SIZE (0x100) -#define R8168_REGS_DUMP_SIZE (0x400) -#define R8168_PCI_REGS_SIZE (0x100) -#define R8168_NAPI_WEIGHT 64 - -#define RTL8168_TX_TIMEOUT (6 * HZ) -#define RTL8168_LINK_TIMEOUT (1 * HZ) -#define RTL8168_ESD_TIMEOUT (2 * HZ) - -#define NUM_TX_DESC 1024 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 1024 /* Number of Rx descriptor registers */ - -#define RX_BUF_SIZE 0x05F3 /* 0x05F3 = 1522bye + 1 */ -#define R8168_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8168_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define OCP_STD_PHY_BASE 0xa400 - -#define NODE_ADDRESS_SIZE 6 - -#define SHORT_PACKET_PADDING_BUF_SIZE 256 - -#define RTK_MAGIC_DEBUG_VALUE 0x0badbeef - -/* write/read MMIO register */ -#define RTL_W8(tp, reg, val8) writeb((val8), tp->mmio_addr + (reg)) -#define RTL_W16(tp, reg, val16) writew((val16), tp->mmio_addr + (reg)) -#define RTL_W32(tp, reg, val32) writel((val32), tp->mmio_addr + (reg)) -#define RTL_R8(tp, reg) readb(tp->mmio_addr + (reg)) -#define RTL_R16(tp, reg) readw(tp->mmio_addr + (reg)) -#define RTL_R32(tp, reg) ((unsigned long) readl(tp->mmio_addr + (reg))) - -#ifndef DMA_64BIT_MASK -#define DMA_64BIT_MASK 0xffffffffffffffffULL -#endif - -#ifndef DMA_32BIT_MASK -#define DMA_32BIT_MASK 0x00000000ffffffffULL -#endif - -#ifndef NETDEV_TX_OK -#define NETDEV_TX_OK 0 /* driver took care of packet */ -#endif - -#ifndef NETDEV_TX_BUSY -#define NETDEV_TX_BUSY 1 /* driver tx path was busy*/ -#endif - -#ifndef NETDEV_TX_LOCKED -#define NETDEV_TX_LOCKED -1 /* driver tx lock was already taken */ -#endif - -#ifndef ADVERTISED_Pause -#define ADVERTISED_Pause (1 << 13) -#endif - -#ifndef ADVERTISED_Asym_Pause -#define ADVERTISED_Asym_Pause (1 << 14) -#endif - -#ifndef ADVERTISE_PAUSE_CAP -#define ADVERTISE_PAUSE_CAP 0x400 -#endif - -#ifndef ADVERTISE_PAUSE_ASYM -#define ADVERTISE_PAUSE_ASYM 0x800 -#endif - -#ifndef MII_CTRL1000 -#define MII_CTRL1000 0x09 -#endif - -#ifndef ADVERTISE_1000FULL -#define ADVERTISE_1000FULL 0x200 -#endif - -#ifndef ADVERTISE_1000HALF -#define ADVERTISE_1000HALF 0x100 -#endif - -#ifndef ETH_MIN_MTU -#define ETH_MIN_MTU 68 -#endif - -/*****************************************************************************/ - -//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) -#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ - (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ - ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) -/* copied from linux kernel 2.6.20 include/linux/netdev.h */ -#define NETDEV_ALIGN 32 -#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1) - -static inline void *netdev_priv(struct net_device *dev) -{ - return (char *)dev + ((sizeof(struct net_device) - + NETDEV_ALIGN_CONST) - & ~NETDEV_ALIGN_CONST); -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -#define RTLDEV tp -#else -#define RTLDEV dev -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -/*****************************************************************************/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) -typedef struct net_device *napi_ptr; -typedef int *napi_budget; - -#define napi dev -#define RTL_NAPI_CONFIG(ndev, priv, function, weig) ndev->poll=function; \ - ndev->weight=weig; -#define RTL_NAPI_QUOTA(budget, ndev) min(*budget, ndev->quota) -#define RTL_GET_PRIV(stuct_ptr, priv_struct) netdev_priv(stuct_ptr) -#define RTL_GET_NETDEV(priv_ptr) -#define RTL_RX_QUOTA(budget) *budget -#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) *budget -= work_done; \ - ndev->quota -= work_done; -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev) -#define RTL_NAPI_RETURN_VALUE work_done >= work_to_do -#define RTL_NAPI_ENABLE(dev, napi) netif_poll_enable(dev) -#define RTL_NAPI_DISABLE(dev, napi) netif_poll_disable(dev) -#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) -#else -typedef struct napi_struct *napi_ptr; -typedef int napi_budget; - -#define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) -#define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) -#define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) -#define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; -#define RTL_RX_QUOTA(budget) budget -#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev, napi) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev, napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev, napi) -#endif -#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,29) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(napi) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(napi) -#endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete_done(napi, work_done) -#else -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete(napi) -#endif -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) napi_schedule_prep(napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __napi_schedule(napi) -#endif -#define RTL_NAPI_RETURN_VALUE work_done -#define RTL_NAPI_ENABLE(dev, napi) napi_enable(napi) -#define RTL_NAPI_DISABLE(dev, napi) napi_disable(napi) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) -#define RTL_NAPI_DEL(priv) -#else -#define RTL_NAPI_DEL(priv) netif_napi_del(&priv->napi) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -#ifdef __CHECKER__ -#define __iomem __attribute__((noderef, address_space(2))) -extern void __chk_io_ptr(void __iomem *); -#define __bitwise __attribute__((bitwise)) -#else -#define __iomem -#define __chk_io_ptr(x) (void)0 -#define __bitwise -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) -#ifdef __CHECKER__ -#define __force __attribute__((force)) -#else -#define __force -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) - -#ifndef module_param -#define module_param(v,t,p) MODULE_PARM(v, "i"); -#endif - -#ifndef PCI_DEVICE -#define PCI_DEVICE(vend,dev) \ - .vendor = (vend), .device = (dev), \ - .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID -#endif - -/*****************************************************************************/ -/* 2.5.28 => 2.4.23 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) - -static inline void _kc_synchronize_irq(void) -{ - synchronize_irq(); -} -#undef synchronize_irq -#define synchronize_irq(X) _kc_synchronize_irq() - -#include -#define work_struct tq_struct -#undef INIT_WORK -#define INIT_WORK(a,b,c) INIT_TQUEUE(a,(void (*)(void *))b,c) -#undef container_of -#define container_of list_entry -#define schedule_work schedule_task -#define flush_scheduled_work flush_scheduled_tasks -#endif /* 2.5.28 => 2.4.17 */ - -/*****************************************************************************/ -/* 2.6.4 => 2.6.0 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) -#define MODULE_VERSION(_version) MODULE_INFO(version, _version) -#endif /* 2.6.4 => 2.6.0 */ -/*****************************************************************************/ -/* 2.6.0 => 2.5.28 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) -#define MODULE_INFO(version, _version) -#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT -#define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 -#endif - -#define pci_set_consistent_dma_mask(dev,mask) 1 - -#undef dev_put -#define dev_put(dev) __dev_put(dev) - -#ifndef skb_fill_page_desc -#define skb_fill_page_desc _kc_skb_fill_page_desc -extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); -#endif - -#ifndef pci_dma_mapping_error -#define pci_dma_mapping_error _kc_pci_dma_mapping_error -static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr) -{ - return dma_addr == 0; -} -#endif - -#undef ALIGN -#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) - -#endif /* 2.6.0 => 2.5.28 */ - -/*****************************************************************************/ -/* 2.4.22 => 2.4.17 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) -#define pci_name(x) ((x)->slot_name) -#endif /* 2.4.22 => 2.4.17 */ - -/*****************************************************************************/ -/* 2.6.5 => 2.6.0 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) -#define pci_dma_sync_single_for_cpu pci_dma_sync_single -#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu -#endif /* 2.6.5 => 2.6.0 */ - -/*****************************************************************************/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -/* - * initialize a work-struct's func and data pointers: - */ -#define PREPARE_WORK(_work, _func, _data) \ - do { \ - (_work)->func = _func; \ - (_work)->data = _data; \ - } while (0) - -#endif -/*****************************************************************************/ -/* 2.6.4 => 2.6.0 */ -#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) && \ - LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22)) || \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4))) -#define ETHTOOL_OPS_COMPAT -#endif /* 2.6.4 => 2.6.0 */ - -/*****************************************************************************/ -/* Installations with ethtool version without eeprom, adapter id, or statistics - * support */ - -#ifndef ETH_GSTRING_LEN -#define ETH_GSTRING_LEN 32 -#endif - -#ifndef ETHTOOL_GSTATS -#define ETHTOOL_GSTATS 0x1d -#undef ethtool_drvinfo -#define ethtool_drvinfo k_ethtool_drvinfo -struct k_ethtool_drvinfo { - u32 cmd; - char driver[32]; - char version[32]; - char fw_version[32]; - char bus_info[32]; - char reserved1[32]; - char reserved2[16]; - u32 n_stats; - u32 testinfo_len; - u32 eedump_len; - u32 regdump_len; -}; - -struct ethtool_stats { - u32 cmd; - u32 n_stats; - u64 data[0]; -}; -#endif /* ETHTOOL_GSTATS */ - -#ifndef ETHTOOL_PHYS_ID -#define ETHTOOL_PHYS_ID 0x1c -#endif /* ETHTOOL_PHYS_ID */ - -#ifndef ETHTOOL_GSTRINGS -#define ETHTOOL_GSTRINGS 0x1b -enum ethtool_stringset { - ETH_SS_TEST = 0, - ETH_SS_STATS, -}; -struct ethtool_gstrings { - u32 cmd; /* ETHTOOL_GSTRINGS */ - u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ - u32 len; /* number of strings in the string set */ - u8 data[0]; -}; -#endif /* ETHTOOL_GSTRINGS */ - -#ifndef ETHTOOL_TEST -#define ETHTOOL_TEST 0x1a -enum ethtool_test_flags { - ETH_TEST_FL_OFFLINE = (1 << 0), - ETH_TEST_FL_FAILED = (1 << 1), -}; -struct ethtool_test { - u32 cmd; - u32 flags; - u32 reserved; - u32 len; - u64 data[0]; -}; -#endif /* ETHTOOL_TEST */ - -#ifndef ETHTOOL_GEEPROM -#define ETHTOOL_GEEPROM 0xb -#undef ETHTOOL_GREGS -struct ethtool_eeprom { - u32 cmd; - u32 magic; - u32 offset; - u32 len; - u8 data[0]; -}; - -struct ethtool_value { - u32 cmd; - u32 data; -}; -#endif /* ETHTOOL_GEEPROM */ - -#ifndef ETHTOOL_GLINK -#define ETHTOOL_GLINK 0xa -#endif /* ETHTOOL_GLINK */ - -#ifndef ETHTOOL_GREGS -#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ -#define ethtool_regs _kc_ethtool_regs -/* for passing big chunks of data */ -struct _kc_ethtool_regs { - u32 cmd; - u32 version; /* driver-specific, indicates different chips/revs */ - u32 len; /* bytes */ - u8 data[0]; -}; -#endif /* ETHTOOL_GREGS */ - -#ifndef ETHTOOL_GMSGLVL -#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ -#endif -#ifndef ETHTOOL_SMSGLVL -#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ -#endif -#ifndef ETHTOOL_NWAY_RST -#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ -#endif -#ifndef ETHTOOL_GLINK -#define ETHTOOL_GLINK 0x0000000a /* Get link status */ -#endif -#ifndef ETHTOOL_GEEPROM -#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ -#endif -#ifndef ETHTOOL_SEEPROM -#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ -#endif -#ifndef ETHTOOL_GCOALESCE -#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ -/* for configuring coalescing parameters of chip */ -#define ethtool_coalesce _kc_ethtool_coalesce -struct _kc_ethtool_coalesce { - u32 cmd; /* ETHTOOL_{G,S}COALESCE */ - - /* How many usecs to delay an RX interrupt after - * a packet arrives. If 0, only rx_max_coalesced_frames - * is used. - */ - u32 rx_coalesce_usecs; - - /* How many packets to delay an RX interrupt after - * a packet arrives. If 0, only rx_coalesce_usecs is - * used. It is illegal to set both usecs and max frames - * to zero as this would cause RX interrupts to never be - * generated. - */ - u32 rx_max_coalesced_frames; - - /* Same as above two parameters, except that these values - * apply while an IRQ is being serviced by the host. Not - * all cards support this feature and the values are ignored - * in that case. - */ - u32 rx_coalesce_usecs_irq; - u32 rx_max_coalesced_frames_irq; - - /* How many usecs to delay a TX interrupt after - * a packet is sent. If 0, only tx_max_coalesced_frames - * is used. - */ - u32 tx_coalesce_usecs; - - /* How many packets to delay a TX interrupt after - * a packet is sent. If 0, only tx_coalesce_usecs is - * used. It is illegal to set both usecs and max frames - * to zero as this would cause TX interrupts to never be - * generated. - */ - u32 tx_max_coalesced_frames; - - /* Same as above two parameters, except that these values - * apply while an IRQ is being serviced by the host. Not - * all cards support this feature and the values are ignored - * in that case. - */ - u32 tx_coalesce_usecs_irq; - u32 tx_max_coalesced_frames_irq; - - /* How many usecs to delay in-memory statistics - * block updates. Some drivers do not have an in-memory - * statistic block, and in such cases this value is ignored. - * This value must not be zero. - */ - u32 stats_block_coalesce_usecs; - - /* Adaptive RX/TX coalescing is an algorithm implemented by - * some drivers to improve latency under low packet rates and - * improve throughput under high packet rates. Some drivers - * only implement one of RX or TX adaptive coalescing. Anything - * not implemented by the driver causes these values to be - * silently ignored. - */ - u32 use_adaptive_rx_coalesce; - u32 use_adaptive_tx_coalesce; - - /* When the packet rate (measured in packets per second) - * is below pkt_rate_low, the {rx,tx}_*_low parameters are - * used. - */ - u32 pkt_rate_low; - u32 rx_coalesce_usecs_low; - u32 rx_max_coalesced_frames_low; - u32 tx_coalesce_usecs_low; - u32 tx_max_coalesced_frames_low; - - /* When the packet rate is below pkt_rate_high but above - * pkt_rate_low (both measured in packets per second) the - * normal {rx,tx}_* coalescing parameters are used. - */ - - /* When the packet rate is (measured in packets per second) - * is above pkt_rate_high, the {rx,tx}_*_high parameters are - * used. - */ - u32 pkt_rate_high; - u32 rx_coalesce_usecs_high; - u32 rx_max_coalesced_frames_high; - u32 tx_coalesce_usecs_high; - u32 tx_max_coalesced_frames_high; - - /* How often to do adaptive coalescing packet rate sampling, - * measured in seconds. Must not be zero. - */ - u32 rate_sample_interval; -}; -#endif /* ETHTOOL_GCOALESCE */ - -#ifndef ETHTOOL_SCOALESCE -#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ -#endif -#ifndef ETHTOOL_GRINGPARAM -#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ -/* for configuring RX/TX ring parameters */ -#define ethtool_ringparam _kc_ethtool_ringparam -struct _kc_ethtool_ringparam { - u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ - - /* Read only attributes. These indicate the maximum number - * of pending RX/TX ring entries the driver will allow the - * user to set. - */ - u32 rx_max_pending; - u32 rx_mini_max_pending; - u32 rx_jumbo_max_pending; - u32 tx_max_pending; - - /* Values changeable by the user. The valid values are - * in the range 1 to the "*_max_pending" counterpart above. - */ - u32 rx_pending; - u32 rx_mini_pending; - u32 rx_jumbo_pending; - u32 tx_pending; -}; -#endif /* ETHTOOL_GRINGPARAM */ - -#ifndef ETHTOOL_SRINGPARAM -#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ -#endif -#ifndef ETHTOOL_GPAUSEPARAM -#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ -/* for configuring link flow control parameters */ -#define ethtool_pauseparam _kc_ethtool_pauseparam -struct _kc_ethtool_pauseparam { - u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ - - /* If the link is being auto-negotiated (via ethtool_cmd.autoneg - * being true) the user may set 'autonet' here non-zero to have the - * pause parameters be auto-negotiated too. In such a case, the - * {rx,tx}_pause values below determine what capabilities are - * advertised. - * - * If 'autoneg' is zero or the link is not being auto-negotiated, - * then {rx,tx}_pause force the driver to use/not-use pause - * flow control. - */ - u32 autoneg; - u32 rx_pause; - u32 tx_pause; -}; -#endif /* ETHTOOL_GPAUSEPARAM */ - -#ifndef ETHTOOL_SPAUSEPARAM -#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ -#endif -#ifndef ETHTOOL_GRXCSUM -#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_SRXCSUM -#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_GTXCSUM -#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_STXCSUM -#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_GSG -#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable -* (ethtool_value) */ -#endif -#ifndef ETHTOOL_SSG -#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable -* (ethtool_value). */ -#endif -#ifndef ETHTOOL_TEST -#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ -#endif -#ifndef ETHTOOL_GSTRINGS -#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ -#endif -#ifndef ETHTOOL_PHYS_ID -#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ -#endif -#ifndef ETHTOOL_GSTATS -#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ -#endif -#ifndef ETHTOOL_GTSO -#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_STSO -#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ -#endif - -#ifndef ETHTOOL_BUSINFO_LEN -#define ETHTOOL_BUSINFO_LEN 32 -#endif - -/*****************************************************************************/ - -enum RTL8168_DSM_STATE { - DSM_MAC_INIT = 1, - DSM_NIC_GOTO_D3 = 2, - DSM_IF_DOWN = 3, - DSM_NIC_RESUME_D3 = 4, - DSM_IF_UP = 5, -}; - -enum RTL8168_registers { - MAC0 = 0x00, /* Ethernet hardware address. */ - MAC4 = 0x04, - MAR0 = 0x08, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - CustomLED = 0x18, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - TCTR = 0x48, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - TDFNR = 0x57, - TimeInt0 = 0x58, - TimeInt1 = 0x5C, - PHYAR = 0x60, - CSIDR = 0x64, - CSIAR = 0x68, - PHYstatus = 0x6C, - MACDBG = 0x6D, - GPIO = 0x6E, - PMCH = 0x6F, - ERIDR = 0x70, - ERIAR = 0x74, - EPHY_RXER_NUM = 0x7C, - EPHYAR = 0x80, - TimeInt2 = 0x8C, - OCPDR = 0xB0, - MACOCP = 0xB0, - OCPAR = 0xB4, - SecMAC0 = 0xB4, - SecMAC4 = 0xB8, - PHYOCP = 0xB8, - DBG_reg = 0xD1, - TwiCmdReg = 0xD2, - MCUCmd_reg = 0xD3, - RxMaxSize = 0xDA, - EFUSEAR = 0xDC, - CPlusCmd = 0xE0, - IntrMitigate = 0xE2, - RxDescAddrLow = 0xE4, - RxDescAddrHigh = 0xE8, - MTPS = 0xEC, - FuncEvent = 0xF0, - PPSW = 0xF2, - FuncEventMask = 0xF4, - TimeInt3 = 0xF4, - FuncPresetState = 0xF8, - CMAC_IBCR0 = 0xF8, - CMAC_IBCR2 = 0xF9, - CMAC_IBIMR0 = 0xFA, - CMAC_IBISR0 = 0xFB, - FuncForceEvent = 0xFC, -}; - -enum RTL8168_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxDescUnavail = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - StopReq = 0x80, - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, - Cfg9346_EEDO = (1 << 0), - Cfg9346_EEDI = (1 << 1), - Cfg9346_EESK = (1 << 2), - Cfg9346_EECS = (1 << 3), - Cfg9346_EEM0 = (1 << 6), - Cfg9346_EEM1 = (1 << 7), - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* Transmit Priority Polling*/ - HPQ = 0x80, - NPQ = 0x40, - FSWInt = 0x01, - - /* RxConfigBits */ - Reserved2_shift = 13, - RxCfgDMAShift = 8, - RxCfg_128_int_en = (1 << 15), - RxCfg_fet_multi_en = (1 << 14), - RxCfg_half_refetch = (1 << 13), - RxCfg_9356SEL = (1 << 6), - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - TxMACLoopBack = (1 << 17), /* MAC loopback */ - - /* Config1 register */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register */ - ClkReqEn = (1 << 7), /* Clock Request Enable */ - PMSTS_En = (1 << 5), - - /* Config3 register */ - Isolate_en = (1 << 12), /* Isolate enable */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* This bit is reserved in RTL8168B.*/ - /* Wake up when the cable connection is re-established */ - ECRCEN = (1 << 3), /* This bit is reserved in RTL8168B*/ - Jumbo_En0 = (1 << 2), /* This bit is reserved in RTL8168B*/ - RDY_TO_L23 = (1 << 1), /* This bit is reserved in RTL8168B*/ - Beacon_en = (1 << 0), /* This bit is reserved in RTL8168B*/ - - /* Config4 register */ - Jumbo_En1 = (1 << 1), /* This bit is reserved in RTL8168B*/ - - /* Config5 register */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - ASPM_en = (1 << 0), /* ASPM enable */ - - /* CPlusCmd */ - EnableBist = (1 << 15), - Macdbgo_oe = (1 << 14), - Normal_mode = (1 << 13), - Force_halfdup = (1 << 12), - Force_rxflow_en = (1 << 11), - Force_txflow_en = (1 << 10), - Cxpl_dbg_sel = (1 << 9),//This bit is reserved in RTL8168B - ASF = (1 << 8),//This bit is reserved in RTL8168C - PktCntrDisable = (1 << 7), - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - Macdbgo_sel = 0x001C, - INTT_0 = 0x0000, - INTT_1 = 0x0001, - INTT_2 = 0x0002, - INTT_3 = 0x0003, - - /* rtl8168_PHYstatus */ - PowerSaveStatus = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* DBG_reg */ - Fix_Nak_1 = (1 << 4), - Fix_Nak_2 = (1 << 3), - DBGPIN_E2 = (1 << 0), - - /* ResetCounterCommand */ - CounterReset = 0x1, - /* DumpCounterCommand */ - CounterDump = 0x8, - - /* PHY access */ - PHYAR_Flag = 0x80000000, - PHYAR_Write = 0x80000000, - PHYAR_Read = 0x00000000, - PHYAR_Reg_Mask = 0x1f, - PHYAR_Reg_shift = 16, - PHYAR_Data_Mask = 0xffff, - - /* EPHY access */ - EPHYAR_Flag = 0x80000000, - EPHYAR_Write = 0x80000000, - EPHYAR_Read = 0x00000000, - EPHYAR_Reg_Mask = 0x3f, - EPHYAR_Reg_shift = 16, - EPHYAR_Data_Mask = 0xffff, - - /* CSI access */ - CSIAR_Flag = 0x80000000, - CSIAR_Write = 0x80000000, - CSIAR_Read = 0x00000000, - CSIAR_ByteEn = 0x0f, - CSIAR_ByteEn_shift = 12, - CSIAR_Addr_Mask = 0x0fff, - - /* ERI access */ - ERIAR_Flag = 0x80000000, - ERIAR_Write = 0x80000000, - ERIAR_Read = 0x00000000, - ERIAR_Addr_Align = 4, /* ERI access register address must be 4 byte alignment */ - ERIAR_ExGMAC = 0, - ERIAR_MSIX = 1, - ERIAR_ASF = 2, - ERIAR_OOB = 2, - ERIAR_Type_shift = 16, - ERIAR_ByteEn = 0x0f, - ERIAR_ByteEn_shift = 12, - - /* OCP GPHY access */ - OCPDR_Write = 0x80000000, - OCPDR_Read = 0x00000000, - OCPDR_Reg_Mask = 0xFF, - OCPDR_Data_Mask = 0xFFFF, - OCPDR_GPHY_Reg_shift = 16, - OCPAR_Flag = 0x80000000, - OCPAR_GPHY_Write = 0x8000F060, - OCPAR_GPHY_Read = 0x0000F060, - OCPR_Write = 0x80000000, - OCPR_Read = 0x00000000, - OCPR_Addr_Reg_shift = 16, - OCPR_Flag = 0x80000000, - OCP_STD_PHY_BASE_PAGE = 0x0A40, - - /* MCU Command */ - Now_is_oob = (1 << 7), - Txfifo_empty = (1 << 5), - Rxfifo_empty = (1 << 4), - - /* E-FUSE access */ - EFUSE_WRITE = 0x80000000, - EFUSE_WRITE_OK = 0x00000000, - EFUSE_READ = 0x00000000, - EFUSE_READ_OK = 0x80000000, - EFUSE_WRITE_V3 = 0x40000000, - EFUSE_WRITE_OK_V3 = 0x00000000, - EFUSE_READ_V3 = 0x80000000, - EFUSE_READ_OK_V3 = 0x00000000, - EFUSE_Reg_Mask = 0x03FF, - EFUSE_Reg_Shift = 8, - EFUSE_Check_Cnt = 300, - EFUSE_READ_FAIL = 0xFF, - EFUSE_Data_Mask = 0x000000FF, - - /* GPIO */ - GPIO_en = (1 << 0), - -}; - -enum _DescStatusBit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - /*------ offset 0 of tx descriptor ------*/ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - GiantSendv4 = (1 << 26), /* TCP Giant Send Offload V4 (GSOv4) */ - GiantSendv6 = (1 << 25), /* TCP Giant Send Offload V6 (GSOv6) */ - LargeSend_DP = (1 << 16), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0x7FFU, /* MSS value 11 bits */ - TxIPCS = (1 << 18), /* Calculate IP checksum */ - TxUDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TxTCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /*@@@@@@ offset 4 of tx descriptor => bits for RTL8168C/CP only begin @@@@@@*/ - TxUDPCS_C = (1 << 31), /* Calculate UDP/IP checksum */ - TxTCPCS_C = (1 << 30), /* Calculate TCP/IP checksum */ - TxIPCS_C = (1 << 29), /* Calculate IP checksum */ - TxIPV6F_C = (1 << 28), /* Indicate it is an IPv6 packet */ - /*@@@@@@ offset 4 of tx descriptor => bits for RTL8168C/CP only end @@@@@@*/ - - - /* Rx private */ - /*------ offset 0 of rx descriptor ------*/ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - RxIPF = (1 << 16), /* IP checksum failed */ - RxUDPF = (1 << 15), /* UDP/IP checksum failed */ - RxTCPF = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ - - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8168C/CP only begin @@@@@@*/ - RxUDPT = (1 << 18), - RxTCPT = (1 << 17), - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8168C/CP only end @@@@@@*/ - - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8168C/CP only begin @@@@@@*/ - RxV6F = (1 << 31), - RxV4F = (1 << 30), - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8168C/CP only end @@@@@@*/ -}; - -enum features { -// RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), -}; - -enum wol_capability { - WOL_DISABLED = 0, - WOL_ENABLED = 1 -}; - -enum bits { - BIT_0 = (1 << 0), - BIT_1 = (1 << 1), - BIT_2 = (1 << 2), - BIT_3 = (1 << 3), - BIT_4 = (1 << 4), - BIT_5 = (1 << 5), - BIT_6 = (1 << 6), - BIT_7 = (1 << 7), - BIT_8 = (1 << 8), - BIT_9 = (1 << 9), - BIT_10 = (1 << 10), - BIT_11 = (1 << 11), - BIT_12 = (1 << 12), - BIT_13 = (1 << 13), - BIT_14 = (1 << 14), - BIT_15 = (1 << 15), - BIT_16 = (1 << 16), - BIT_17 = (1 << 17), - BIT_18 = (1 << 18), - BIT_19 = (1 << 19), - BIT_20 = (1 << 20), - BIT_21 = (1 << 21), - BIT_22 = (1 << 22), - BIT_23 = (1 << 23), - BIT_24 = (1 << 24), - BIT_25 = (1 << 25), - BIT_26 = (1 << 26), - BIT_27 = (1 << 27), - BIT_28 = (1 << 28), - BIT_29 = (1 << 29), - BIT_30 = (1 << 30), - BIT_31 = (1 << 31) -}; - -enum effuse { - EFUSE_NOT_SUPPORT = 0, - EFUSE_SUPPORT_V1, - EFUSE_SUPPORT_V2, - EFUSE_SUPPORT_V3, -}; -#define RsvdMask 0x3fffc000 - -struct TxDesc { - u32 opts1; - u32 opts2; - u64 addr; -}; - -struct RxDesc { - u32 opts1; - u32 opts2; - u64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -struct pci_resource { - u8 cmd; - u8 cls; - u16 io_base_h; - u16 io_base_l; - u16 mem_base_h; - u16 mem_base_l; - u8 ilr; - u16 resv_0x1c_h; - u16 resv_0x1c_l; - u16 resv_0x20_h; - u16 resv_0x20_l; - u16 resv_0x24_h; - u16 resv_0x24_l; - u16 resv_0x2c_h; - u16 resv_0x2c_l; - u32 pci_sn_l; - u32 pci_sn_h; -}; - -struct rtl8168_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) - struct napi_struct napi; -#endif -#endif - struct net_device_stats stats; /* statistics of net device */ - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - u32 tx_tcp_csum_cmd; - u32 tx_udp_csum_cmd; - u32 tx_ip_csum_cmd; - u32 tx_ipv6_csum_cmd; - int max_jumbo_frame_size; - int chipset; - u32 mcfg; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned rx_buf_sz; - struct timer_list esd_timer; - struct timer_list link_timer; - struct pci_resource pci_cfg_space; - unsigned int esd_flag; - unsigned int pci_cfg_is_read; - unsigned int rtl8168_rx_config; - u16 cp_cmd; - u16 intr_mask; - u16 timer_intr_mask; - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; - u8 org_mac_addr[NODE_ADDRESS_SIZE]; - struct rtl8168_counters *tally_vaddr; - dma_addr_t tally_paddr; - -#ifdef CONFIG_R8168_VLAN - struct vlan_group *vlgrp; -#endif - u8 wol_enabled; - u32 wol_opts; - u8 efuse_ver; - u8 eeprom_type; - u8 autoneg; - u8 duplex; - u32 speed; - u32 advertising; - u16 eeprom_len; - u16 cur_page; - u32 bios_setting; - - int (*set_speed)(struct net_device *, u8 autoneg, u32 speed, u8 duplex, u32 adv); -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - void (*get_settings)(struct net_device *, struct ethtool_cmd *); -#else - void (*get_settings)(struct net_device *, struct ethtool_link_ksettings *); -#endif - void (*phy_reset_enable)(struct net_device *); - unsigned int (*phy_reset_pending)(struct net_device *); - unsigned int (*link_ok)(struct net_device *); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct work_struct task; -#else - struct delayed_work task; -#endif - unsigned features; - - u8 org_pci_offset_99; - u8 org_pci_offset_180; - u8 issue_offset_99_event; - - u8 org_pci_offset_80; - u8 org_pci_offset_81; - u8 use_timer_interrrupt; - - u32 keep_intr_cnt; - - u8 HwIcVerUnknown; - u8 NotWrRamCodeToMicroP; - u8 NotWrMcuPatchCode; - u8 HwHasWrRamCodeToMicroP; - - u16 sw_ram_code_ver; - u16 hw_ram_code_ver; - - u8 rtk_enable_diag; - - u8 ShortPacketSwChecksum; - - u8 UseSwPaddingShortPkt; - - u8 RequireAdcBiasPatch; - u16 AdcBiasPatchIoffset; - - u8 RequireAdjustUpsTxLinkPulseTiming; - u16 SwrCnt1msIni; - - u8 HwSuppNowIsOobVer; - - u8 RequiredSecLanDonglePatch; - - u32 HwFiberModeVer; - u32 HwFiberStat; - u8 HwSwitchMdiToFiber; - - u8 HwSuppSerDesPhyVer; - - u8 HwSuppPhyOcpVer; - - u8 HwSuppAspmClkIntrLock; - - u16 NicCustLedValue; - - u8 HwSuppUpsVer; - - u8 HwSuppMagicPktVer; - - u8 HwSuppCheckPhyDisableModeVer; - - u8 random_mac; - - u16 phy_reg_aner; - u16 phy_reg_anlpar; - u16 phy_reg_gbsr; - - u32 HwPcieSNOffset; - - u8 HwSuppEsdVer; - u8 TestPhyOcpReg; - u16 BackupPhyFuseDout_15_0; - u16 BackupPhyFuseDout_47_32; - u16 BackupPhyFuseDout_63_48; - - const char *fw_name; - struct rtl8168_fw *rtl_fw; - u32 ocp_base; - - //Dash+++++++++++++++++ - u8 HwSuppDashVer; - u8 DASH; - u8 dash_printer_enabled; - u8 HwPkgDet; - void __iomem *mapped_cmac_ioaddr; /* mapped cmac memory map physical address */ - void __iomem *cmac_ioaddr; /* cmac memory map physical address */ - -#ifdef ENABLE_DASH_SUPPORT - u16 AfterRecvFromFwBufLen; - u8 AfterRecvFromFwBuf[RECV_FROM_FW_BUF_SIZE]; - u16 AfterSendToFwBufLen; - u8 AfterSendToFwBuf[SEND_TO_FW_BUF_SIZE]; - u16 SendToFwBufferLen; - u32 SizeOfSendToFwBuffer ; - u32 SizeOfSendToFwBufferMemAlloc ; - u32 NumOfSendToFwBuffer ; - - u8 OobReq; - u8 OobAck; - u32 OobReqComplete; - u32 OobAckComplete; - - u8 RcvFwReqSysOkEvt; - u8 RcvFwDashOkEvt; - u8 SendFwHostOkEvt; - - u8 DashFwDisableRx; - - void *SendToFwBuffer ; - dma_addr_t SendToFwBufferPhy ; - u8 SendingToFw; - PTX_DASH_SEND_FW_DESC TxDashSendFwDesc; - dma_addr_t TxDashSendFwDescPhy; - u32 SizeOfTxDashSendFwDescMemAlloc; - u32 SizeOfTxDashSendFwDesc ; - u32 NumTxDashSendFwDesc ; - u32 CurrNumTxDashSendFwDesc ; - u32 LastSendNumTxDashSendFwDesc ; - - u32 NumRecvFromFwBuffer ; - u32 SizeOfRecvFromFwBuffer ; - u32 SizeOfRecvFromFwBufferMemAlloc ; - void *RecvFromFwBuffer ; - dma_addr_t RecvFromFwBufferPhy ; - - PRX_DASH_FROM_FW_DESC RxDashRecvFwDesc; - dma_addr_t RxDashRecvFwDescPhy; - u32 SizeOfRxDashRecvFwDescMemAlloc; - u32 SizeOfRxDashRecvFwDesc ; - u32 NumRxDashRecvFwDesc ; - u32 CurrNumRxDashRecvFwDesc ; - u8 DashReqRegValue; - u16 HostReqValue; - - u32 CmacResetIsrCounter; - u8 CmacResetIntr ; - u8 CmacResetting ; - u8 CmacOobIssueCmacReset ; - u32 CmacResetbyFwCnt; - -#if defined(ENABLE_DASH_PRINTER_SUPPORT) - struct completion fw_ack; - struct completion fw_req; - struct completion fw_host_ok; -#endif - //Dash----------------- -#endif //ENABLE_DASH_SUPPORT - - //Realwow++++++++++++++ - u8 HwSuppKCPOffloadVer; - - u8 EnableDhcpTimeoutWake; - u8 EnableTeredoOffload; - u8 EnableKCPOffload; -#ifdef ENABLE_REALWOW_SUPPORT - u32 DhcpTimeout; - MP_KCP_INFO MpKCPInfo; - //Realwow-------------- -#endif //ENABLE_REALWOW_SUPPORT - - u32 eee_adv_t; - u8 eee_enabled; - - u32 dynamic_aspm_packet_count; - -#ifdef ENABLE_R8168_PROCFS - //Procfs support - struct proc_dir_entry *proc_dir; -#endif -}; - -enum eetype { - EEPROM_TYPE_NONE=0, - EEPROM_TYPE_93C46, - EEPROM_TYPE_93C56, - EEPROM_TWSI -}; - -enum mcfg { - CFG_METHOD_1=0, - CFG_METHOD_2, - CFG_METHOD_3, - CFG_METHOD_4, - CFG_METHOD_5, - CFG_METHOD_6, - CFG_METHOD_7, - CFG_METHOD_8, - CFG_METHOD_9 , - CFG_METHOD_10, - CFG_METHOD_11, - CFG_METHOD_12, - CFG_METHOD_13, - CFG_METHOD_14, - CFG_METHOD_15, - CFG_METHOD_16, - CFG_METHOD_17, - CFG_METHOD_18, - CFG_METHOD_19, - CFG_METHOD_20, - CFG_METHOD_21, - CFG_METHOD_22, - CFG_METHOD_23, - CFG_METHOD_24, - CFG_METHOD_25, - CFG_METHOD_26, - CFG_METHOD_27, - CFG_METHOD_28, - CFG_METHOD_29, - CFG_METHOD_30, - CFG_METHOD_31, - CFG_METHOD_32, - CFG_METHOD_33, - CFG_METHOD_MAX, - CFG_METHOD_DEFAULT = 0xFF -}; - -#define LSO_32K 32000 -#define LSO_64K 64000 - -#define NIC_MIN_PHYS_BUF_COUNT (2) -#define NIC_MAX_PHYS_BUF_COUNT_LSO_64K (24) -#define NIC_MAX_PHYS_BUF_COUNT_LSO2 (16*4) - -#define GTTCPHO_SHIFT 18 -#define GTTCPHO_MAX 0x7fU -#define GTPKTSIZE_MAX 0x3ffffU -#define TCPHO_SHIFT 18 -#define TCPHO_MAX 0x3ffU -#define LSOPKTSIZE_MAX 0xffffU -#define MSS_MAX 0x07ffu /* MSS value */ - -#define OOB_CMD_RESET 0x00 -#define OOB_CMD_DRIVER_START 0x05 -#define OOB_CMD_DRIVER_STOP 0x06 -#define OOB_CMD_SET_IPMAC 0x41 - -#define WAKEUP_MAGIC_PACKET_NOT_SUPPORT (0) -#define WAKEUP_MAGIC_PACKET_V1 (1) -#define WAKEUP_MAGIC_PACKET_V2 (2) - -//Ram Code Version -#define NIC_RAMCODE_VERSION_CFG_METHOD_14 (0x0057) -#define NIC_RAMCODE_VERSION_CFG_METHOD_16 (0x0055) -#define NIC_RAMCODE_VERSION_CFG_METHOD_18 (0x0052) -#define NIC_RAMCODE_VERSION_CFG_METHOD_20 (0x0044) -#define NIC_RAMCODE_VERSION_CFG_METHOD_21 (0x0042) -#define NIC_RAMCODE_VERSION_CFG_METHOD_24 (0x0001) -#define NIC_RAMCODE_VERSION_CFG_METHOD_23 (0x0015) -#define NIC_RAMCODE_VERSION_CFG_METHOD_26 (0x0012) -#define NIC_RAMCODE_VERSION_CFG_METHOD_28 (0x0019) -#define NIC_RAMCODE_VERSION_CFG_METHOD_29 (0x0055) -#define NIC_RAMCODE_VERSION_CFG_METHOD_31 (0x0003) - -//hwoptimize -#define HW_PATCH_SOC_LAN (BIT_0) -#define HW_PATCH_SAMSUNG_LAN_DONGLE (BIT_2) - -#define HW_PHY_STATUS_INI 1 -#define HW_PHY_STATUS_EXT_INI 2 -#define HW_PHY_STATUS_LAN_ON 3 - -void rtl8168_mdio_write(struct rtl8168_private *tp, u16 RegAddr, u16 value); -void rtl8168_mdio_prot_write(struct rtl8168_private *tp, u32 RegAddr, u32 value); -void rtl8168_mdio_prot_direct_write_phy_ocp(struct rtl8168_private *tp, u32 RegAddr, u32 value); -u32 rtl8168_mdio_read(struct rtl8168_private *tp, u16 RegAddr); -u32 rtl8168_mdio_prot_read(struct rtl8168_private *tp, u32 RegAddr); -u32 rtl8168_mdio_prot_direct_read_phy_ocp(struct rtl8168_private *tp, u32 RegAddr); -void rtl8168_ephy_write(struct rtl8168_private *tp, int RegAddr, int value); -void rtl8168_mac_ocp_write(struct rtl8168_private *tp, u16 reg_addr, u16 value); -u16 rtl8168_mac_ocp_read(struct rtl8168_private *tp, u16 reg_addr); -void rtl8168_clear_eth_phy_bit(struct rtl8168_private *tp, u8 addr, u16 mask); -void rtl8168_set_eth_phy_bit(struct rtl8168_private *tp, u8 addr, u16 mask); -void rtl8168_ocp_write(struct rtl8168_private *tp, u16 addr, u8 len, u32 data); -void rtl8168_oob_notify(struct rtl8168_private *tp, u8 cmd); -void rtl8168_init_ring_indexes(struct rtl8168_private *tp); -int rtl8168_eri_write(struct rtl8168_private *tp, int addr, int len, u32 value, int type); -void rtl8168_oob_mutex_lock(struct rtl8168_private *tp); -u32 rtl8168_ocp_read(struct rtl8168_private *tp, u16 addr, u8 len); -u32 rtl8168_ocp_read_with_oob_base_address(struct rtl8168_private *tp, u16 addr, u8 len, u32 base_address); -u32 rtl8168_ocp_write_with_oob_base_address(struct rtl8168_private *tp, u16 addr, u8 len, u32 value, u32 base_address); -u32 rtl8168_eri_read(struct rtl8168_private *tp, int addr, int len, int type); -u32 rtl8168_eri_read_with_oob_base_address(struct rtl8168_private *tp, int addr, int len, int type, u32 base_address); -int rtl8168_eri_write_with_oob_base_address(struct rtl8168_private *tp, int addr, int len, u32 value, int type, u32 base_address); -u16 rtl8168_ephy_read(struct rtl8168_private *tp, int RegAddr); -void rtl8168_wait_txrx_fifo_empty(struct net_device *dev); -void rtl8168_wait_ll_share_fifo_ready(struct net_device *dev); -void rtl8168_enable_now_is_oob(struct rtl8168_private *tp); -void rtl8168_disable_now_is_oob(struct rtl8168_private *tp); -void rtl8168_oob_mutex_unlock(struct rtl8168_private *tp); -void rtl8168_dash2_disable_tx(struct rtl8168_private *tp); -void rtl8168_dash2_enable_tx(struct rtl8168_private *tp); -void rtl8168_dash2_disable_rx(struct rtl8168_private *tp); -void rtl8168_dash2_enable_rx(struct rtl8168_private *tp); -void rtl8168_hw_disable_mac_mcu_bps(struct net_device *dev); - -#define HW_SUPPORT_CHECK_PHY_DISABLE_MODE(_M) ((_M)->HwSuppCheckPhyDisableModeVer > 0 ) -#define HW_SUPP_SERDES_PHY(_M) ((_M)->HwSuppSerDesPhyVer > 0) -#define HW_HAS_WRITE_PHY_MCU_RAM_CODE(_M) (((_M)->HwHasWrRamCodeToMicroP == TRUE) ? 1 : 0) -#define HW_SUPPORT_UPS_MODE(_M) ((_M)->HwSuppUpsVer > 0) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) -#define netdev_mc_count(dev) ((dev)->mc_count) -#define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0) -#define netdev_for_each_mc_addr(mclist, dev) \ - for (mclist = dev->mc_list; mclist; mclist = mclist->next) -#endif diff --git a/addons/r8168/src/3.10.108/r8168.mod.c b/addons/r8168/src/3.10.108/r8168.mod.c deleted file mode 100644 index 28be82f9..00000000 --- a/addons/r8168/src/3.10.108/r8168.mod.c +++ /dev/null @@ -1,31 +0,0 @@ -#include -#include -#include - -MODULE_INFO(vermagic, VERMAGIC_STRING); - -struct module __this_module -__attribute__((section(".gnu.linkonce.this_module"))) = { - .name = KBUILD_MODNAME, - .init = init_module, -#ifdef CONFIG_MODULE_UNLOAD - .exit = cleanup_module, -#endif - .arch = MODULE_ARCH_INIT, -}; - -static const char __module_depends[] -__used -__attribute__((section(".modinfo"))) = -"depends="; - -MODULE_ALIAS("pci:v000010ECd00008168sv*sd*bc*sc*i*"); -MODULE_ALIAS("pci:v000010ECd00008161sv*sd*bc*sc*i*"); -MODULE_ALIAS("pci:v000010ECd00002502sv*sd*bc*sc*i*"); -MODULE_ALIAS("pci:v000010ECd00002600sv*sd*bc*sc*i*"); -MODULE_ALIAS("pci:v00001186d00004300sv00001186sd00004B10bc*sc*i*"); - -MODULE_INFO(srcversion, "7584797F71DC2D0613CBA69"); -#ifdef RETPOLINE - MODULE_INFO(retpoline, "Y"); -#endif diff --git a/addons/r8168/src/3.10.108/r8168_asf.c b/addons/r8168/src/3.10.108/r8168_asf.c deleted file mode 100644 index 77524f04..00000000 --- a/addons/r8168/src/3.10.108/r8168_asf.c +++ /dev/null @@ -1,422 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "r8168.h" -#include "r8168_asf.h" -#include "rtl_eeprom.h" - -int rtl8168_asf_ioctl(struct net_device *dev, - struct ifreq *ifr) -{ - struct rtl8168_private *tp = netdev_priv(dev); - void *user_data = ifr->ifr_data; - struct asf_ioctl_struct asf_usrdata; - unsigned long flags; - - if (tp->mcfg != CFG_METHOD_7 && tp->mcfg != CFG_METHOD_8) - return -EOPNOTSUPP; - - if (copy_from_user(&asf_usrdata, user_data, sizeof(struct asf_ioctl_struct))) - return -EFAULT; - - spin_lock_irqsave(&tp->lock, flags); - - switch (asf_usrdata.offset) { - case HBPeriod: - rtl8168_asf_hbperiod(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case WD8Timer: - break; - case WD16Rst: - rtl8168_asf_wd16rst(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case WD8Rst: - rtl8168_asf_time_period(tp, asf_usrdata.arg, WD8Rst, asf_usrdata.u.data); - break; - case LSnsrPollCycle: - rtl8168_asf_time_period(tp, asf_usrdata.arg, LSnsrPollCycle, asf_usrdata.u.data); - break; - case ASFSnsrPollPrd: - rtl8168_asf_time_period(tp, asf_usrdata.arg, ASFSnsrPollPrd, asf_usrdata.u.data); - break; - case AlertReSendItvl: - rtl8168_asf_time_period(tp, asf_usrdata.arg, AlertReSendItvl, asf_usrdata.u.data); - break; - case SMBAddr: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, SMBAddr, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case ASFConfigR0: - rtl8168_asf_config_regs(tp, asf_usrdata.arg, ASFConfigR0, asf_usrdata.u.data); - break; - case ASFConfigR1: - rtl8168_asf_config_regs(tp, asf_usrdata.arg, ASFConfigR1, asf_usrdata.u.data); - break; - case ConsoleMA: - rtl8168_asf_console_mac(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case ConsoleIP: - rtl8168_asf_ip_address(tp, asf_usrdata.arg, ConsoleIP, asf_usrdata.u.data); - break; - case IPAddr: - rtl8168_asf_ip_address(tp, asf_usrdata.arg, IPAddr, asf_usrdata.u.data); - break; - case UUID: - rtl8168_asf_rw_uuid(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case IANA: - rtl8168_asf_rw_iana(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case SysID: - rtl8168_asf_rw_systemid(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case Community: - rtl8168_asf_community_string(tp, asf_usrdata.arg, asf_usrdata.u.string); - break; - case StringLength: - rtl8168_asf_community_string_len(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case FmCapMsk: - rtl8168_asf_capability_masks(tp, asf_usrdata.arg, FmCapMsk, asf_usrdata.u.data); - break; - case SpCMDMsk: - rtl8168_asf_capability_masks(tp, asf_usrdata.arg, SpCMDMsk, asf_usrdata.u.data); - break; - case SysCapMsk: - rtl8168_asf_capability_masks(tp, asf_usrdata.arg, SysCapMsk, asf_usrdata.u.data); - break; - case RmtRstAddr: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtRstAddr, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtRstCmd: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtRstCmd, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtRstData: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtRstData, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPwrOffAddr: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOffAddr, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPwrOffCmd: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOffCmd, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPwrOffData: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOffData, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPwrOnAddr: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOnAddr, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPwrOnCmd: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOnCmd, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPwrOnData: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOnData, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPCRAddr: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPCRAddr, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPCRCmd: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPCRCmd, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPCRData: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPCRData, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case ASFSnsr0Addr: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, ASFSnsr0Addr, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case LSnsrAddr0: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, LSnsrAddr0, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case KO: - /* Get/Set Key Operation */ - rtl8168_asf_key_access(tp, asf_usrdata.arg, KO, asf_usrdata.u.data); - break; - case KA: - /* Get/Set Key Administrator */ - rtl8168_asf_key_access(tp, asf_usrdata.arg, KA, asf_usrdata.u.data); - break; - case KG: - /* Get/Set Key Generation */ - rtl8168_asf_key_access(tp, asf_usrdata.arg, KG, asf_usrdata.u.data); - break; - case KR: - /* Get/Set Key Random */ - rtl8168_asf_key_access(tp, asf_usrdata.arg, KR, asf_usrdata.u.data); - break; - default: - spin_unlock_irqrestore(&tp->lock, flags); - return -EOPNOTSUPP; - } - - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(user_data, &asf_usrdata, sizeof(struct asf_ioctl_struct))) - return -EFAULT; - - return 0; -} - -void rtl8168_asf_hbperiod(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - if (arg == ASF_GET) - data[ASFHBPERIOD] = rtl8168_eri_read(tp, HBPeriod, RW_TWO_BYTES, ERIAR_ASF); - else if (arg == ASF_SET) { - rtl8168_eri_write(tp, HBPeriod, RW_TWO_BYTES, data[ASFHBPERIOD], ERIAR_ASF); - rtl8168_eri_write(tp, 0x1EC, RW_ONE_BYTE, 0x07, ERIAR_ASF); - } -} - -void rtl8168_asf_wd16rst(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - data[ASFWD16RST] = rtl8168_eri_read(tp, WD16Rst, RW_TWO_BYTES, ERIAR_ASF); -} - -void rtl8168_asf_console_mac(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - int i; - - if (arg == ASF_GET) { - for (i = 0; i < 6; i++) - data[i] = rtl8168_eri_read(tp, ConsoleMA + i, RW_ONE_BYTE, ERIAR_ASF); - } else if (arg == ASF_SET) { - for (i = 0; i < 6; i++) - rtl8168_eri_write(tp, ConsoleMA + i, RW_ONE_BYTE, data[i], ERIAR_ASF); - - /* write the new console MAC address to EEPROM */ - rtl8168_eeprom_write_sc(tp, 70, (data[1] << 8) | data[0]); - rtl8168_eeprom_write_sc(tp, 71, (data[3] << 8) | data[2]); - rtl8168_eeprom_write_sc(tp, 72, (data[5] << 8) | data[4]); - } -} - -void rtl8168_asf_ip_address(struct rtl8168_private *tp, int arg, int offset, unsigned int *data) -{ - int i; - int eeprom_off = 0; - - if (arg == ASF_GET) { - for (i = 0; i < 4; i++) - data[i] = rtl8168_eri_read(tp, offset + i, RW_ONE_BYTE, ERIAR_ASF); - } else if (arg == ASF_SET) { - for (i = 0; i < 4; i++) - rtl8168_eri_write(tp, offset + i, RW_ONE_BYTE, data[i], ERIAR_ASF); - - if (offset == ConsoleIP) - eeprom_off = 73; - else if (offset == IPAddr) - eeprom_off = 75; - - /* write the new IP address to EEPROM */ - rtl8168_eeprom_write_sc(tp, eeprom_off, (data[1] << 8) | data[0]); - rtl8168_eeprom_write_sc(tp, eeprom_off + 1, (data[3] << 8) | data[2]); - - } -} - -void rtl8168_asf_config_regs(struct rtl8168_private *tp, int arg, int offset, unsigned int *data) -{ - unsigned int value; - - if (arg == ASF_GET) { - data[ASFCAPABILITY] = (rtl8168_eri_read(tp, offset, RW_ONE_BYTE, ERIAR_ASF) & data[ASFCONFIG]) ? FUNCTION_ENABLE : FUNCTION_DISABLE; - } else if (arg == ASF_SET) { - value = rtl8168_eri_read(tp, offset, RW_ONE_BYTE, ERIAR_ASF); - - if (data[ASFCAPABILITY] == FUNCTION_ENABLE) - value |= data[ASFCONFIG]; - else if (data[ASFCAPABILITY] == FUNCTION_DISABLE) - value &= ~data[ASFCONFIG]; - - rtl8168_eri_write(tp, offset, RW_ONE_BYTE, value, ERIAR_ASF); - } -} - -void rtl8168_asf_capability_masks(struct rtl8168_private *tp, int arg, int offset, unsigned int *data) -{ - unsigned int len, bit_mask; - - bit_mask = DISABLE_MASK; - - if (offset == FmCapMsk) { - /* System firmware capabilities */ - len = RW_FOUR_BYTES; - if (data[ASFCAPMASK] == FUNCTION_ENABLE) - bit_mask = FMW_CAP_MASK; - } else if (offset == SpCMDMsk) { - /* Special commands */ - len = RW_TWO_BYTES; - if (data[ASFCAPMASK] == FUNCTION_ENABLE) - bit_mask = SPC_CMD_MASK; - } else { - /* System capability (offset == SysCapMsk)*/ - len = RW_ONE_BYTE; - if (data[ASFCAPMASK] == FUNCTION_ENABLE) - bit_mask = SYS_CAP_MASK; - } - - if (arg == ASF_GET) - data[ASFCAPMASK] = rtl8168_eri_read(tp, offset, len, ERIAR_ASF) ? FUNCTION_ENABLE : FUNCTION_DISABLE; - else /* arg == ASF_SET */ - rtl8168_eri_write(tp, offset, len, bit_mask, ERIAR_ASF); -} - -void rtl8168_asf_community_string(struct rtl8168_private *tp, int arg, char *string) -{ - int i; - - if (arg == ASF_GET) { - for (i = 0; i < COMMU_STR_MAX_LEN; i++) - string[i] = rtl8168_eri_read(tp, Community + i, RW_ONE_BYTE, ERIAR_ASF); - } else { /* arg == ASF_SET */ - for (i = 0; i < COMMU_STR_MAX_LEN; i++) - rtl8168_eri_write(tp, Community + i, RW_ONE_BYTE, string[i], ERIAR_ASF); - } -} - -void rtl8168_asf_community_string_len(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - if (arg == ASF_GET) - data[ASFCOMMULEN] = rtl8168_eri_read(tp, StringLength, RW_ONE_BYTE, ERIAR_ASF); - else /* arg == ASF_SET */ - rtl8168_eri_write(tp, StringLength, RW_ONE_BYTE, data[ASFCOMMULEN], ERIAR_ASF); -} - -void rtl8168_asf_time_period(struct rtl8168_private *tp, int arg, int offset, unsigned int *data) -{ - int pos = 0; - - if (offset == WD8Rst) - pos = ASFWD8RESET; - else if (offset == LSnsrPollCycle) - pos = ASFLSNRPOLLCYC; - else if (offset == ASFSnsrPollPrd) - pos = ASFSNRPOLLCYC; - else if (offset == AlertReSendItvl) - pos = ASFALERTRESND; - - if (arg == ASF_GET) - data[pos] = rtl8168_eri_read(tp, offset, RW_ONE_BYTE, ERIAR_ASF); - else /* arg == ASF_SET */ - rtl8168_eri_write(tp, offset, RW_ONE_BYTE, data[pos], ERIAR_ASF); - -} - -void rtl8168_asf_key_access(struct rtl8168_private *tp, int arg, int offset, unsigned int *data) -{ - int i, j; - int key_off = 0; - - if (arg == ASF_GET) { - for (i = 0; i < KEY_LEN; i++) - data[i] = rtl8168_eri_read(tp, offset + KEY_LEN - (i + 1), RW_ONE_BYTE, ERIAR_ASF); - } else { - if (offset == KO) - key_off = 162; - else if (offset == KA) - key_off = 172; - else if (offset == KG) - key_off = 182; - else if (offset == KR) - key_off = 192; - - /* arg == ASF_SET */ - for (i = 0; i < KEY_LEN; i++) - rtl8168_eri_write(tp, offset + KEY_LEN - (i + 1), RW_ONE_BYTE, data[i], ERIAR_ASF); - - /* write the new key to EEPROM */ - for (i = 0, j = 19; i < 10; i++, j = j - 2) - rtl8168_eeprom_write_sc(tp, key_off + i, (data[j - 1] << 8) | data[j]); - } -} - -void rtl8168_asf_rw_hexadecimal(struct rtl8168_private *tp, int arg, int offset, int len, unsigned int *data) -{ - if (arg == ASF_GET) - data[ASFRWHEXNUM] = rtl8168_eri_read(tp, offset, len, ERIAR_ASF); - else /* arg == ASF_SET */ - rtl8168_eri_write(tp, offset, len, data[ASFRWHEXNUM], ERIAR_ASF); -} - -void rtl8168_asf_rw_systemid(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - int i; - - if (arg == ASF_GET) - for (i = 0; i < SYSID_LEN ; i++) - data[i] = rtl8168_eri_read(tp, SysID + i, RW_ONE_BYTE, ERIAR_ASF); - else /* arg == ASF_SET */ - for (i = 0; i < SYSID_LEN ; i++) - rtl8168_eri_write(tp, SysID + i, RW_ONE_BYTE, data[i], ERIAR_ASF); -} - -void rtl8168_asf_rw_iana(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - int i; - - if (arg == ASF_GET) - for (i = 0; i < RW_FOUR_BYTES; i++) - data[i] = rtl8168_eri_read(tp, IANA + i, RW_ONE_BYTE, ERIAR_ASF); - else /* arg == ASF_SET */ - for (i = 0; i < RW_FOUR_BYTES; i++) - rtl8168_eri_write(tp, IANA + i, RW_ONE_BYTE, data[i], ERIAR_ASF); -} - -void rtl8168_asf_rw_uuid(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - int i, j; - - if (arg == ASF_GET) - for (i = UUID_LEN - 1, j = 0; i >= 0 ; i--, j++) - data[j] = rtl8168_eri_read(tp, UUID + i, RW_ONE_BYTE, ERIAR_ASF); - else /* arg == ASF_SET */ - for (i = UUID_LEN - 1, j = 0; i >= 0 ; i--, j++) - rtl8168_eri_write(tp, UUID + i, RW_ONE_BYTE, data[j], ERIAR_ASF); -} diff --git a/addons/r8168/src/3.10.108/r8168_asf.h b/addons/r8168/src/3.10.108/r8168_asf.h deleted file mode 100644 index c4b412a6..00000000 --- a/addons/r8168/src/3.10.108/r8168_asf.h +++ /dev/null @@ -1,295 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#define SIOCDEVPRIVATE_RTLASF SIOCDEVPRIVATE - -#define FUNCTION_ENABLE 1 -#define FUNCTION_DISABLE 0 - -#define ASFCONFIG 0 -#define ASFCAPABILITY 1 -#define ASFCOMMULEN 0 -#define ASFHBPERIOD 0 -#define ASFWD16RST 0 -#define ASFCAPMASK 0 -#define ASFALERTRESND 0 -#define ASFLSNRPOLLCYC 0 -#define ASFSNRPOLLCYC 0 -#define ASFWD8RESET 0 -#define ASFRWHEXNUM 0 - -#define FMW_CAP_MASK 0x0000F867 -#define SPC_CMD_MASK 0x1F00 -#define SYS_CAP_MASK 0xFF -#define DISABLE_MASK 0x00 - -#define MAX_DATA_LEN 200 -#define MAX_STR_LEN 200 - -#define COMMU_STR_MAX_LEN 23 - -#define KEY_LEN 20 -#define UUID_LEN 16 -#define SYSID_LEN 2 - -#define RW_ONE_BYTE 1 -#define RW_TWO_BYTES 2 -#define RW_FOUR_BYTES 4 - -enum asf_registers { - HBPeriod = 0x0000, - WD8Rst = 0x0002, - WD8Timer = 0x0003, - WD16Rst = 0x0004, - LSnsrPollCycle = 0x0006, - ASFSnsrPollPrd = 0x0007, - AlertReSendCnt = 0x0008, - AlertReSendItvl = 0x0009, - SMBAddr = 0x000A, - SMBCap = 0x000B, - ASFConfigR0 = 0x000C, - ASFConfigR1 = 0x000D, - WD16Timer = 0x000E, - ConsoleMA = 0x0010, - ConsoleIP = 0x0016, - IPAddr = 0x001A, - - UUID = 0x0020, - IANA = 0x0030, - SysID = 0x0034, - Community = 0x0036, - StringLength = 0x004D, - LC = 0x004E, - EntityInst = 0x004F, - FmCapMsk = 0x0050, - SpCMDMsk = 0x0054, - SysCapMsk = 0x0056, - WDSysSt = 0x0057, - RxMsgType = 0x0058, - RxSpCMD = 0x0059, - RxSpCMDPa = 0x005A, - RxBtOpMsk = 0x005C, - RmtRstAddr = 0x005E, - RmtRstCmd = 0x005F, - RmtRstData = 0x0060, - RmtPwrOffAddr = 0x0061, - RmtPwrOffCmd = 0x0062, - RmtPwrOffData = 0x0063, - RmtPwrOnAddr = 0x0064, - RmtPwrOnCmd = 0x0065, - RmtPwrOnData = 0x0066, - RmtPCRAddr = 0x0067, - RmtPCRCmd = 0x0068, - RmtPCRData = 0x0069, - RMCP_IANA = 0x006A, - RMCP_OEM = 0x006E, - ASFSnsr0Addr = 0x0070, - - ASFSnsrEvSt = 0x0073, - ASFSnsrEvAlert = 0x0081, - - LSnsrNo = 0x00AD, - AssrtEvntMsk = 0x00AE, - DeAssrtEvntMsk = 0x00AF, - - LSnsrAddr0 = 0x00B0, - LAlertCMD0 = 0x00B1, - LAlertDataMsk0 = 0x00B2, - LAlertCmp0 = 0x00B3, - LAlertESnsrT0 = 0x00B4, - LAlertET0 = 0x00B5, - LAlertEOffset0 = 0x00B6, - LAlertES0 = 0x00B7, - LAlertSN0 = 0x00B8, - LAlertEntity0 = 0x00B9, - LAlertEI0 = 0x00BA, - LSnsrState0 = 0x00BB, - - LSnsrAddr1 = 0x00BD, - LAlertCMD1 = 0x00BE, - LAlertDataMsk1 = 0x00BF, - LAlertCmp1 = 0x00C0, - LAlertESnsrT1 = 0x00C1, - LAlertET1 = 0x00C2, - LAlertEOffset1 = 0x00C3, - LAlertES1 = 0x00C4, - LAlertSN1 = 0x00C5, - LAlertEntity1 = 0x00C6, - LAlertEI1 = 0x00C7, - LSnsrState1 = 0x00C8, - - LSnsrAddr2 = 0x00CA, - LAlertCMD2 = 0x00CB, - LAlertDataMsk2 = 0x00CC, - LAlertCmp2 = 0x00CD, - LAlertESnsrT2 = 0x00CE, - LAlertET2 = 0x00CF, - LAlertEOffset2 = 0x00D0, - LAlertES2 = 0x00D1, - LAlertSN2 = 0x00D2, - LAlertEntity2 = 0x00D3, - LAlertEI2 = 0x00D4, - LSnsrState2 = 0x00D5, - - LSnsrAddr3 = 0x00D7, - LAlertCMD3 = 0x00D8, - LAlertDataMsk3 = 0x00D9, - LAlertCmp3 = 0x00DA, - LAlertESnsrT3 = 0x00DB, - LAlertET3 = 0x00DC, - LAlertEOffset3 = 0x00DD, - LAlertES3 = 0x00DE, - LAlertSN3 = 0x00DF, - LAlertEntity3 = 0x00E0, - LAlertEI3 = 0x00E1, - LSnsrState3 = 0x00E2, - - LSnsrAddr4 = 0x00E4, - LAlertCMD4 = 0x00E5, - LAlertDataMsk4 = 0x00E6, - LAlertCmp4 = 0x00E7, - LAlertESnsrT4 = 0x00E8, - LAlertET4 = 0x00E9, - LAlertEOffset4 = 0x00EA, - LAlertES4 = 0x00EB, - LAlertSN4 = 0x00EC, - LAlertEntity4 = 0x00ED, - LAlertEI4 = 0x00EE, - LSnsrState4 = 0x00EF, - - LSnsrAddr5 = 0x00F1, - LAlertCMD5 = 0x00F2, - LAlertDataMsk5 = 0x00F3, - LAlertCmp5 = 0x00F4, - LAlertESnsrT5 = 0x00F5, - LAlertET5 = 0x00F6, - LAlertEOffset5 = 0x00F7, - LAlertES5 = 0x00F8, - LAlertSN5 = 0x00F9, - LAlertEntity5 = 0x00FA, - LAlertEI5 = 0x00FB, - LSnsrState5 = 0x00FC, - - LSnsrAddr6 = 0x00FE, - LAlertCMD6 = 0x00FF, - LAlertDataMsk6 = 0x0100, - LAlertCmp6 = 0x0101, - LAlertESnsrT6 = 0x0102, - LAlertET6 = 0x0103, - LAlertEOffset6 = 0x0104, - LAlertES6 = 0x0105, - LAlertSN6 = 0x0106, - LAlertEntity6 = 0x0107, - LAlertEI6 = 0x0108, - LSnsrState6 = 0x0109, - - LSnsrAddr7 = 0x010B, - LAlertCMD7 = 0x010C, - LAlertDataMsk7 = 0x010D, - LAlertCmp7 = 0x010E, - LAlertESnsrT7 = 0x010F, - LAlertET7 = 0x0110, - LAlertEOffset7 = 0x0111, - LAlertES7 = 0x0112, - LAlertSN7 = 0x0113, - LAlertEntity7 = 0x0114, - LAlertEI7 = 0x0115, - LSnsrState7 = 0x0116, - LAssert = 0x0117, - LDAssert = 0x0118, - IPServiceType = 0x0119, - IPIdfr = 0x011A, - FlagFOffset = 0x011C, - TTL = 0x011E, - HbtEI = 0x011F, - MgtConSID1 = 0x0120, - MgtConSID2 = 0x0124, - MgdCltSID = 0x0128, - StCd = 0x012C, - MgtConUR = 0x012D, - MgtConUNL = 0x012E, - - AuthPd = 0x0130, - IntyPd = 0x0138, - MgtConRN = 0x0140, - MgdCtlRN = 0x0150, - MgtConUN = 0x0160, - Rakp2IntCk = 0x0170, - KO = 0x017C, - KA = 0x0190, - KG = 0x01A4, - KR = 0x01B8, - CP = 0x01CC, - CQ = 0x01D0, - KC = 0x01D4, - ConsoleSid = 0x01E8, - - SIK1 = 0x01FC, - SIK2 = 0x0210, - Udpsrc_port = 0x0224, - Udpdes_port = 0x0226, - Asf_debug_mux = 0x0228 -}; - -enum asf_cmdln_opt { - ASF_GET, - ASF_SET, - ASF_HELP -}; - -struct asf_ioctl_struct { - unsigned int arg; - unsigned int offset; - union { - unsigned int data[MAX_DATA_LEN]; - char string[MAX_STR_LEN]; - } u; -}; - -int rtl8168_asf_ioctl(struct net_device *dev, struct ifreq *ifr); -void rtl8168_asf_hbperiod(struct rtl8168_private *tp, int arg, unsigned int *data); -void rtl8168_asf_wd16rst(struct rtl8168_private *tp, int arg, unsigned int *data); -void rtl8168_asf_console_mac(struct rtl8168_private *, int arg, unsigned int *data); -void rtl8168_asf_ip_address(struct rtl8168_private *, int arg, int offset, unsigned int *data); -void rtl8168_asf_config_regs(struct rtl8168_private *tp, int arg, int offset, unsigned int *data); -void rtl8168_asf_capability_masks(struct rtl8168_private *tp, int arg, int offset, unsigned int *data); -void rtl8168_asf_community_string(struct rtl8168_private *tp, int arg, char *string); -void rtl8168_asf_community_string_len(struct rtl8168_private *tp, int arg, unsigned int *data); -void rtl8168_asf_alert_resend_interval(struct rtl8168_private *tp, int arg, unsigned int *data); -void rtl8168_asf_time_period(struct rtl8168_private *tp, int arg, int offset, unsigned int *data); -void rtl8168_asf_key_access(struct rtl8168_private *, int arg, int offset, unsigned int *data); -void rtl8168_asf_rw_hexadecimal(struct rtl8168_private *tp, int arg, int offset, int len, unsigned int *data); -void rtl8168_asf_rw_iana(struct rtl8168_private *tp, int arg, unsigned int *data); -void rtl8168_asf_rw_uuid(struct rtl8168_private *tp, int arg, unsigned int *data); -void rtl8168_asf_rw_systemid(struct rtl8168_private *tp, int arg, unsigned int *data); diff --git a/addons/r8168/src/3.10.108/r8168_dash.h b/addons/r8168/src/3.10.108/r8168_dash.h deleted file mode 100644 index b4d358f1..00000000 --- a/addons/r8168/src/3.10.108/r8168_dash.h +++ /dev/null @@ -1,256 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_R8168_DASH_H -#define _LINUX_R8168_DASH_H - -#define SIOCDEVPRIVATE_RTLDASH SIOCDEVPRIVATE+2 - -enum rtl_dash_cmd { - RTL_DASH_ARP_NS_OFFLOAD = 0, - RTL_DASH_SET_OOB_IPMAC, - RTL_DASH_NOTIFY_OOB, - - RTL_DASH_SEND_BUFFER_DATA_TO_DASH_FW, - RTL_DASH_CHECK_SEND_BUFFER_TO_DASH_FW_COMPLETE, - RTL_DASH_GET_RCV_FROM_FW_BUFFER_DATA, - RTL_DASH_OOB_REQ, - RTL_DASH_OOB_ACK, - RTL_DASH_DETACH_OOB_REQ, - RTL_DASH_DETACH_OOB_ACK, - - RTL_FW_SET_IPV4 = 0x10, - RTL_FW_GET_IPV4, - RTL_FW_SET_IPV6, - RTL_FW_GET_IPV6, - RTL_FW_SET_EXT_SNMP, - RTL_FW_GET_EXT_SNMP, - RTL_FW_SET_WAKEUP_PATTERN, - RTL_FW_GET_WAKEUP_PATTERN, - RTL_FW_DEL_WAKEUP_PATTERN, - - RTLT_DASH_COMMAND_INVALID, -}; - -struct rtl_dash_ip_mac { - struct sockaddr ifru_addr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; -}; - -struct rtl_dash_ioctl_struct { - __u32 cmd; - __u32 offset; - __u32 len; - union { - __u32 data; - void *data_buffer; - }; -}; - -struct settings_ipv4 { - __u32 IPv4addr; - __u32 IPv4mask; - __u32 IPv4Gateway; -}; - -struct settings_ipv6 { - __u32 reserved; - __u32 prefixLen; - __u16 IPv6addr[8]; - __u16 IPv6Gateway[8]; -}; - -struct settings_ext_snmp { - __u16 index; - __u16 oid_get_len; - __u8 oid_for_get[24]; - __u8 reserved0[26]; - __u16 value_len; - __u8 value[256]; - __u8 supported; - __u8 reserved1[27]; -}; - -struct wakeup_pattern { - __u8 index; - __u8 valid; - __u8 start; - __u8 length; - __u8 name[36]; - __u8 mask[16]; - __u8 pattern[128]; - __u32 reserved[2]; -}; - -typedef struct _RX_DASH_FROM_FW_DESC { - __le16 length; - __le16 status; - __le32 resv; - __le64 BufferAddress; -} -RX_DASH_FROM_FW_DESC, *PRX_DASH_FROM_FW_DESC; - -typedef struct _TX_DASH_SEND_FW_DESC { - __le16 length; - __le16 status; - __le32 resv; - __le64 BufferAddress; -} -TX_DASH_SEND_FW_DESC, *PTX_DASH_SEND_FW_DESC; - -typedef struct _OSOOBHdr { - __le32 len; - u8 type; - u8 flag; - u8 hostReqV; - u8 res; -} -OSOOBHdr, *POSOOBHdr; - -typedef struct _RX_DASH_BUFFER_TYPE_2 { - OSOOBHdr oobhdr; - u8 RxDataBuffer[0]; -} -RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2; - -#define ALIGN_8 (0x7) -#define ALIGN_16 (0xf) -#define ALIGN_32 (0x1f) -#define ALIGN_64 (0x3f) -#define ALIGN_256 (0xff) -#define ALIGN_4096 (0xfff) - -#define OCP_REG_CONFIG0 (0x10) -#define OCP_REG_CONFIG0_REV_F (0xB8) -#define OCP_REG_DASH_POLL (0x30) -#define OCP_REG_HOST_REQ (0x34) -#define OCP_REG_DASH_REQ (0x35) -#define OCP_REG_CR (0x36) -#define OCP_REG_DMEMSTA (0x38) -#define OCP_REG_GPHYAR (0x60) - - -#define OCP_REG_CONFIG0_DASHEN BIT_15 -#define OCP_REG_CONFIG0_OOBRESET BIT_14 -#define OCP_REG_CONFIG0_APRDY BIT_13 -#define OCP_REG_CONFIG0_FIRMWARERDY BIT_12 -#define OCP_REG_CONFIG0_DRIVERRDY BIT_11 -#define OCP_REG_CONFIG0_OOB_WDT BIT_9 -#define OCP_REG_CONFIG0_DRV_WAIT_OOB BIT_8 -#define OCP_REG_CONFIG0_TLSEN BIT_7 - -#define HW_DASH_SUPPORT_DASH(_M) ((_M)->HwSuppDashVer > 0) -#define HW_DASH_SUPPORT_TYPE_1(_M) ((_M)->HwSuppDashVer == 1) -#define HW_DASH_SUPPORT_TYPE_2(_M) ((_M)->HwSuppDashVer == 2) -#define HW_DASH_SUPPORT_TYPE_3(_M) ((_M)->HwSuppDashVer == 3) - -#define RECV_FROM_FW_BUF_SIZE (2048) -#define SEND_TO_FW_BUF_SIZE (2048) - -#define RX_DASH_FROM_FW_OWN BIT_15 -#define TX_DASH_SEND_FW_OWN BIT_15 - -#define TXS_CC3_0 (BIT_0|BIT_1|BIT_2|BIT_3) -#define TXS_EXC BIT_4 -#define TXS_LNKF BIT_5 -#define TXS_OWC BIT_6 -#define TXS_TES BIT_7 -#define TXS_UNF BIT_9 -#define TXS_LGSEN BIT_11 -#define TXS_LS BIT_12 -#define TXS_FS BIT_13 -#define TXS_EOR BIT_14 -#define TXS_OWN BIT_15 - -#define TPPool_HRDY 0x20 - -#define HostReqReg (0xC0) -#define SystemMasterDescStartAddrLow (0xF0) -#define SystemMasterDescStartAddrHigh (0xF4) -#define SystemSlaveDescStartAddrLow (0xF8) -#define SystemSlaveDescStartAddrHigh (0xFC) - -//DASH Request Type -#define WSMANREG 0x01 -#define OSPUSHDATA 0x02 - -#define RXS_OWN BIT_15 -#define RXS_EOR BIT_14 -#define RXS_FS BIT_13 -#define RXS_LS BIT_12 - -#define ISRIMR_DP_DASH_OK BIT_15 -#define ISRIMR_DP_HOST_OK BIT_13 -#define ISRIMR_DP_REQSYS_OK BIT_11 - -#define ISRIMR_DASH_INTR_EN BIT_12 -#define ISRIMR_DASH_INTR_CMAC_RESET BIT_15 - -#define ISRIMR_DASH_TYPE2_ROK BIT_0 -#define ISRIMR_DASH_TYPE2_RDU BIT_1 -#define ISRIMR_DASH_TYPE2_TOK BIT_2 -#define ISRIMR_DASH_TYPE2_TDU BIT_3 -#define ISRIMR_DASH_TYPE2_TX_FIFO_FULL BIT_4 -#define ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE BIT_5 -#define ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE BIT_6 - -#define CMAC_OOB_STOP 0x25 -#define CMAC_OOB_INIT 0x26 -#define CMAC_OOB_RESET 0x2a - -#define NO_BASE_ADDRESS 0x00000000 -#define RTL8168FP_OOBMAC_BASE 0xBAF70000 -#define RTL8168FP_CMAC_IOBASE 0xBAF20000 -#define RTL8168FP_KVM_BASE 0xBAF80400 -#define CMAC_SYNC_REG 0x20 -#define CMAC_RXDESC_OFFSET 0x90 //RX: 0x90 - 0x98 -#define CMAC_TXDESC_OFFSET 0x98 //TX: 0x98 - 0x9F - -/* cmac write/read MMIO register */ -#define RTL_CMAC_W8(tp, reg, val8) writeb ((val8), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_W16(tp, reg, val16) writew ((val16), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_W32(tp, reg, val32) writel ((val32), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R8(tp, reg) readb (tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R16(tp, reg) readw (tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R32(tp, reg) ((unsigned long) readl (tp->cmac_ioaddr + (reg))) - -int rtl8168_dash_ioctl(struct net_device *dev, struct ifreq *ifr); -void HandleDashInterrupt(struct net_device *dev); -int AllocateDashShareMemory(struct net_device *dev); -void FreeAllocatedDashShareMemory(struct net_device *dev); -void DashHwInit(struct net_device *dev); - - -#endif /* _LINUX_R8168_DASH_H */ diff --git a/addons/r8168/src/3.10.108/r8168_fiber.h b/addons/r8168/src/3.10.108/r8168_fiber.h deleted file mode 100644 index 2e303fe2..00000000 --- a/addons/r8168/src/3.10.108/r8168_fiber.h +++ /dev/null @@ -1,67 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_R8168_FIBER_H -#define _LINUX_R8168_FIBER_H - -enum { - FIBER_MODE_NIC_ONLY = 0, - FIBER_MODE_RTL8168H_RTL8211FS, - FIBER_MODE_RTL8168H_MDI_SWITCH_RTL8211FS, - FIBER_MODE_MAX -}; - -enum { - FIBER_STAT_NOT_CHECKED = 0, - FIBER_STAT_CONNECT, - FIBER_STAT_DISCONNECT, - FIBER_STAT_MAX -}; - -#define HW_FIBER_MODE_ENABLED(_M) ((_M)->HwFiberModeVer > 0) - - - -void rtl8168_hw_init_fiber_nic(struct net_device *dev); -void rtl8168_hw_fiber_nic_d3_para(struct net_device *dev); -void rtl8168_hw_fiber_phy_config(struct net_device *dev); -void rtl8168_hw_switch_mdi_to_fiber(struct net_device *dev); -void rtl8168_hw_switch_mdi_to_nic(struct net_device *dev); -unsigned int rtl8168_hw_fiber_link_ok(struct net_device *dev); -void rtl8168_check_fiber_link_status(struct net_device *dev); -void rtl8168_check_hw_fiber_mode_support(struct net_device *dev); -void rtl8168_set_fiber_mode_software_variable(struct net_device *dev); - - -#endif /* _LINUX_R8168_FIBER_H */ diff --git a/addons/r8168/src/3.10.108/r8168_firmware.c b/addons/r8168/src/3.10.108/r8168_firmware.c deleted file mode 100644 index 3fe95db9..00000000 --- a/addons/r8168/src/3.10.108/r8168_firmware.c +++ /dev/null @@ -1,264 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include - -#include "r8168_firmware.h" - -enum rtl_fw_opcode { - PHY_READ = 0x0, - PHY_DATA_OR = 0x1, - PHY_DATA_AND = 0x2, - PHY_BJMPN = 0x3, - PHY_MDIO_CHG = 0x4, - PHY_CLEAR_READCOUNT = 0x7, - PHY_WRITE = 0x8, - PHY_READCOUNT_EQ_SKIP = 0x9, - PHY_COMP_EQ_SKIPN = 0xa, - PHY_COMP_NEQ_SKIPN = 0xb, - PHY_WRITE_PREVIOUS = 0xc, - PHY_SKIPN = 0xd, - PHY_DELAY_MS = 0xe, -}; - -struct fw_info { - u32 magic; - char version[RTL8168_VER_SIZE]; - __le32 fw_start; - __le32 fw_len; - u8 chksum; -} __packed; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) -#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) -#endif -#define FW_OPCODE_SIZE sizeof_field(struct rtl8168_fw_phy_action, code[0]) - -static bool rtl8168_fw_format_ok(struct rtl8168_fw *rtl_fw) -{ - const struct firmware *fw = rtl_fw->fw; - struct fw_info *fw_info = (struct fw_info *)fw->data; - struct rtl8168_fw_phy_action *pa = &rtl_fw->phy_action; - - if (fw->size < FW_OPCODE_SIZE) - return false; - - if (!fw_info->magic) { - size_t i, size, start; - u8 checksum = 0; - - if (fw->size < sizeof(*fw_info)) - return false; - - for (i = 0; i < fw->size; i++) - checksum += fw->data[i]; - if (checksum != 0) - return false; - - start = le32_to_cpu(fw_info->fw_start); - if (start > fw->size) - return false; - - size = le32_to_cpu(fw_info->fw_len); - if (size > (fw->size - start) / FW_OPCODE_SIZE) - return false; - - strscpy(rtl_fw->version, fw_info->version, RTL8168_VER_SIZE); - - pa->code = (__le32 *)(fw->data + start); - pa->size = size; - } else { - if (fw->size % FW_OPCODE_SIZE) - return false; - - strscpy(rtl_fw->version, rtl_fw->fw_name, RTL8168_VER_SIZE); - - pa->code = (__le32 *)fw->data; - pa->size = fw->size / FW_OPCODE_SIZE; - } - - return true; -} - -static bool rtl8168_fw_data_ok(struct rtl8168_fw *rtl_fw) -{ - struct rtl8168_fw_phy_action *pa = &rtl_fw->phy_action; - size_t index; - - for (index = 0; index < pa->size; index++) { - u32 action = le32_to_cpu(pa->code[index]); - u32 val = action & 0x0000ffff; - u32 regno = (action & 0x0fff0000) >> 16; - - switch (action >> 28) { - case PHY_READ: - case PHY_DATA_OR: - case PHY_DATA_AND: - case PHY_CLEAR_READCOUNT: - case PHY_WRITE: - case PHY_WRITE_PREVIOUS: - case PHY_DELAY_MS: - break; - - case PHY_MDIO_CHG: - if (val > 1) - goto out; - break; - - case PHY_BJMPN: - if (regno > index) - goto out; - break; - case PHY_READCOUNT_EQ_SKIP: - if (index + 2 >= pa->size) - goto out; - break; - case PHY_COMP_EQ_SKIPN: - case PHY_COMP_NEQ_SKIPN: - case PHY_SKIPN: - if (index + 1 + regno >= pa->size) - goto out; - break; - - default: - dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action); - return false; - } - } - - return true; -out: - dev_err(rtl_fw->dev, "Out of range of firmware\n"); - return false; -} - -void rtl8168_fw_write_firmware(struct rtl8168_private *tp, struct rtl8168_fw *rtl_fw) -{ - struct rtl8168_fw_phy_action *pa = &rtl_fw->phy_action; - rtl8168_fw_write_t fw_write = rtl_fw->phy_write; - rtl8168_fw_read_t fw_read = rtl_fw->phy_read; - int predata = 0, count = 0; - size_t index; - - for (index = 0; index < pa->size; index++) { - u32 action = le32_to_cpu(pa->code[index]); - u32 data = action & 0x0000ffff; - u32 regno = (action & 0x0fff0000) >> 16; - enum rtl_fw_opcode opcode = action >> 28; - - if (!action) - break; - - switch (opcode) { - case PHY_READ: - predata = fw_read(tp, regno); - count++; - break; - case PHY_DATA_OR: - predata |= data; - break; - case PHY_DATA_AND: - predata &= data; - break; - case PHY_BJMPN: - index -= (regno + 1); - break; - case PHY_MDIO_CHG: - if (data) { - fw_write = rtl_fw->mac_mcu_write; - fw_read = rtl_fw->mac_mcu_read; - } else { - fw_write = rtl_fw->phy_write; - fw_read = rtl_fw->phy_read; - } - - break; - case PHY_CLEAR_READCOUNT: - count = 0; - break; - case PHY_WRITE: - fw_write(tp, regno, data); - break; - case PHY_READCOUNT_EQ_SKIP: - if (count == data) - index++; - break; - case PHY_COMP_EQ_SKIPN: - if (predata == data) - index += regno; - break; - case PHY_COMP_NEQ_SKIPN: - if (predata != data) - index += regno; - break; - case PHY_WRITE_PREVIOUS: - fw_write(tp, regno, predata); - break; - case PHY_SKIPN: - index += regno; - break; - case PHY_DELAY_MS: - mdelay(data); - break; - } - } -} - -void rtl8168_fw_release_firmware(struct rtl8168_fw *rtl_fw) -{ - release_firmware(rtl_fw->fw); -} - -int rtl8168_fw_request_firmware(struct rtl8168_fw *rtl_fw) -{ - int rc; - - rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev); - if (rc < 0) - goto out; - - if (!rtl8168_fw_format_ok(rtl_fw) || !rtl8168_fw_data_ok(rtl_fw)) { - release_firmware(rtl_fw->fw); - rc = -EINVAL; - goto out; - } - - return 0; -out: - dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n", - rtl_fw->fw_name, rc); - return rc; -} diff --git a/addons/r8168/src/3.10.108/r8168_firmware.h b/addons/r8168/src/3.10.108/r8168_firmware.h deleted file mode 100644 index 563280ff..00000000 --- a/addons/r8168/src/3.10.108/r8168_firmware.h +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_RTL8168_FIRMWARE_H -#define _LINUX_RTL8168_FIRMWARE_H - -#include -#include - -struct rtl8168_private; -typedef void (*rtl8168_fw_write_t)(struct rtl8168_private *tp, u16 reg, u16 val); -typedef u32 (*rtl8168_fw_read_t)(struct rtl8168_private *tp, u16 reg); - -#define RTL8168_VER_SIZE 32 - -struct rtl8168_fw { - rtl8168_fw_write_t phy_write; - rtl8168_fw_read_t phy_read; - rtl8168_fw_write_t mac_mcu_write; - rtl8168_fw_read_t mac_mcu_read; - const struct firmware *fw; - const char *fw_name; - struct device *dev; - - char version[RTL8168_VER_SIZE]; - - struct rtl8168_fw_phy_action { - __le32 *code; - size_t size; - } phy_action; -}; - -int rtl8168_fw_request_firmware(struct rtl8168_fw *rtl_fw); -void rtl8168_fw_release_firmware(struct rtl8168_fw *rtl_fw); -void rtl8168_fw_write_firmware(struct rtl8168_private *tp, struct rtl8168_fw *rtl_fw); - -#endif /* _LINUX_RTL8168_FIRMWARE_H */ diff --git a/addons/r8168/src/3.10.108/r8168_n.c b/addons/r8168/src/3.10.108/r8168_n.c deleted file mode 100644 index a44352f3..00000000 --- a/addons/r8168/src/3.10.108/r8168_n.c +++ /dev/null @@ -1,28743 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -/* - * This driver is modified from r8169.c in Linux kernel 2.6.18 - */ - -/* In Linux 5.4 asm_inline was introduced, but it's not supported by clang. - * Redefine it to just asm to enable successful compilation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) -#include -#include -#endif -#include -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0) -#include -#endif -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) -#include -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define dev_printk(A,B,fmt,args...) printk(A fmt,##args) -#else -#include -#include -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) -#include -#endif - -#include -#include - -#include "r8168.h" -#include "r8168_asf.h" -#include "rtl_eeprom.h" -#include "rtltool.h" -#include "r8168_firmware.h" - -#ifdef ENABLE_R8168_PROCFS -#include -#include -#endif - -#define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw" -#define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw" -#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw" -#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw" -#define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw" -#define FIRMWARE_8168E_4 "rtl_nic/rtl8168e-4.fw" -#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw" -#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw" -#define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw" -#define FIRMWARE_8411_2 "rtl_nic/rtl8411-2.fw" -#define FIRMWARE_8168G_2 "rtl_nic/rtl8168g-2.fw" -#define FIRMWARE_8168G_3 "rtl_nic/rtl8168g-3.fw" -#define FIRMWARE_8168EP_1 "rtl_nic/rtl8168ep-1.fw" -#define FIRMWARE_8168EP_2 "rtl_nic/rtl8168ep-2.fw" -#define FIRMWARE_8168EP_3 "rtl_nic/rtl8168ep-3.fw" -#define FIRMWARE_8168H_1 "rtl_nic/rtl8168h-1.fw" -#define FIRMWARE_8168H_2 "rtl_nic/rtl8168h-2.fw" -#define FIRMWARE_8168FP_3 "rtl_nic/rtl8168fp-3.fw" -#define FIRMWARE_8168FP_4 "rtl_nic/rtl8168fp-4.fw" - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -static const struct { - const char *name; - const char *fw_name; -} rtl_chip_fw_infos[] = { - /* PCI-E devices. */ - [CFG_METHOD_1] = {"RTL8168B/8111", }, - [CFG_METHOD_2] = {"RTL8168B/8111", }, - [CFG_METHOD_3] = {"RTL8168B/8111", }, - [CFG_METHOD_4] = {"RTL8168C/8111C", }, - [CFG_METHOD_5] = {"RTL8168C/8111C", }, - [CFG_METHOD_6] = {"RTL8168C/8111C", }, - [CFG_METHOD_7] = {"RTL8168CP/8111CP", }, - [CFG_METHOD_8] = {"RTL8168CP/8111CP", }, - [CFG_METHOD_9] = {"RTL8168D/8111D", FIRMWARE_8168D_1}, - [CFG_METHOD_10] = {"RTL8168D/8111D", FIRMWARE_8168D_2}, - [CFG_METHOD_11] = {"RTL8168DP/8111DP", }, - [CFG_METHOD_12] = {"RTL8168DP/8111DP", }, - [CFG_METHOD_13] = {"RTL8168DP/8111DP", }, - [CFG_METHOD_14] = {"RTL8168E/8111E", FIRMWARE_8168E_1}, - [CFG_METHOD_15] = {"RTL8168E/8111E", FIRMWARE_8168E_2}, - [CFG_METHOD_16] = {"RTL8168E-VL/8111E-VL", FIRMWARE_8168E_3}, - [CFG_METHOD_17] = {"RTL8168E-VL/8111E-VL", FIRMWARE_8168E_4}, - [CFG_METHOD_18] = {"RTL8168F/8111F", FIRMWARE_8168F_1}, - [CFG_METHOD_19] = {"RTL8168F/8111F", FIRMWARE_8168F_2}, - [CFG_METHOD_20] = {"RTL8411", FIRMWARE_8411_1}, - [CFG_METHOD_21] = {"RTL8168G/8111G", FIRMWARE_8168G_2}, - [CFG_METHOD_22] = {"RTL8168G/8111G", }, - [CFG_METHOD_23] = {"RTL8168EP/8111EP", FIRMWARE_8168EP_1}, - [CFG_METHOD_24] = {"RTL8168GU/8111GU", }, - [CFG_METHOD_25] = {"RTL8168GU/8111GU", FIRMWARE_8168G_3}, - [CFG_METHOD_26] = {"8411B", FIRMWARE_8411_2}, - [CFG_METHOD_27] = {"RTL8168EP/8111EP", FIRMWARE_8168EP_2}, - [CFG_METHOD_28] = {"RTL8168EP/8111EP", FIRMWARE_8168EP_3}, - [CFG_METHOD_29] = {"RTL8168H/8111H", FIRMWARE_8168H_1}, - [CFG_METHOD_30] = {"RTL8168H/8111H", FIRMWARE_8168H_2}, - [CFG_METHOD_31] = {"RTL8168FP/8111FP", }, - [CFG_METHOD_32] = {"RTL8168FP/8111FP", FIRMWARE_8168FP_3}, - [CFG_METHOD_33] = {"RTL8168FP/8111FP", FIRMWARE_8168FP_4}, - [CFG_METHOD_DEFAULT] = {"Unknown", }, -}; - -#define _R(NAME,MAC,RCR,MASK, JumFrameSz) \ - { .name = NAME, .mcfg = MAC, .RCR_Cfg = RCR, .RxConfigMask = MASK, .jumbo_frame_sz = JumFrameSz } - -static const struct { - const char *name; - u8 mcfg; - u32 RCR_Cfg; - u32 RxConfigMask; /* Clears the bits supported by this chip */ - u32 jumbo_frame_sz; -} rtl_chip_info[] = { - _R("RTL8168B/8111B", - CFG_METHOD_1, - (Reserved2_data << Reserved2_shift) | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_4k), - - _R("RTL8168B/8111B", - CFG_METHOD_2, - (Reserved2_data << Reserved2_shift) | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_4k), - - _R("RTL8168B/8111B", - CFG_METHOD_3, - (Reserved2_data << Reserved2_shift) | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_4k), - - _R("RTL8168C/8111C", - CFG_METHOD_4, - RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_6k), - - _R("RTL8168C/8111C", - CFG_METHOD_5, - RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_6k), - - _R("RTL8168C/8111C", - CFG_METHOD_6, - RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_6k), - - _R("RTL8168CP/8111CP", - CFG_METHOD_7, - RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_6k), - - _R("RTL8168CP/8111CP", - CFG_METHOD_8, - RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_6k), - - _R("RTL8168D/8111D", - CFG_METHOD_9, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168D/8111D", - CFG_METHOD_10, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168DP/8111DP", - CFG_METHOD_11, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168DP/8111DP", - CFG_METHOD_12, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168DP/8111DP", - CFG_METHOD_13, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168E/8111E", - CFG_METHOD_14, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168E/8111E", - CFG_METHOD_15, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168E-VL/8111E-VL", - CFG_METHOD_16, - RxCfg_128_int_en | RxEarly_off_V1 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e0080, - Jumbo_Frame_9k), - - _R("RTL8168E-VL/8111E-VL", - CFG_METHOD_17, - RxCfg_128_int_en | RxEarly_off_V1 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168F/8111F", - CFG_METHOD_18, - RxCfg_128_int_en | RxEarly_off_V1 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168F/8111F", - CFG_METHOD_19, - RxCfg_128_int_en | RxEarly_off_V1 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8411", - CFG_METHOD_20, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168G/8111G", - CFG_METHOD_21, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168G/8111G", - CFG_METHOD_22, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168EP/8111EP", - CFG_METHOD_23, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168GU/8111GU", - CFG_METHOD_24, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168GU/8111GU", - CFG_METHOD_25, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("8411B", - CFG_METHOD_26, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168EP/8111EP", - CFG_METHOD_27, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168EP/8111EP", - CFG_METHOD_28, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168H/8111H", - CFG_METHOD_29, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168H/8111H", - CFG_METHOD_30, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168FP/8111FP", - CFG_METHOD_31, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168FP/8111FP", - CFG_METHOD_32, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168FP/8111FP", - CFG_METHOD_33, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("Unknown", - CFG_METHOD_DEFAULT, - (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_1k) -}; -#undef _R - -#ifndef PCI_VENDOR_ID_DLINK -#define PCI_VENDOR_ID_DLINK 0x1186 -#endif - -static struct pci_device_id rtl8168_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8161), }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x2502), }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x2600), }, - { PCI_VENDOR_ID_DLINK, 0x4300, 0x1186, 0x4b10,}, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8168_pci_tbl); - -static int rx_copybreak = 0; -static int use_dac = 1; -static int timer_count = 0x2600; -static int dynamic_aspm_packet_threshold = 10; - -static struct { - u32 msg_enable; -} debug = { -1 }; - -static unsigned int speed_mode = SPEED_1000; -static unsigned int duplex_mode = DUPLEX_FULL; -static unsigned int autoneg_mode = AUTONEG_ENABLE; -static unsigned int advertising_mode = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full; -#ifdef CONFIG_ASPM -static int aspm = 1; -#else -static int aspm = 0; -#endif -#ifdef CONFIG_DYNAMIC_ASPM -static int dynamic_aspm = 1; -#else -static int dynamic_aspm = 0; -#endif -#ifdef ENABLE_S5WOL -static int s5wol = 1; -#else -static int s5wol = 0; -#endif -#ifdef ENABLE_S5_KEEP_CURR_MAC -static int s5_keep_curr_mac = 1; -#else -static int s5_keep_curr_mac = 0; -#endif -#ifdef ENABLE_EEE -static int eee_enable = 1; -#else -static int eee_enable = 0; -#endif -#ifdef CONFIG_SOC_LAN -static ulong hwoptimize = HW_PATCH_SOC_LAN; -#else -static ulong hwoptimize = 0; -#endif -#ifdef ENABLE_S0_MAGIC_PACKET -static int s0_magic_packet = 1; -#else -static int s0_magic_packet = 0; -#endif - -MODULE_AUTHOR("Realtek and the Linux r8168 crew "); -MODULE_DESCRIPTION("RealTek RTL-8168 Gigabit Ethernet driver"); - -module_param(speed_mode, uint, 0); -MODULE_PARM_DESC(speed_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(duplex_mode, uint, 0); -MODULE_PARM_DESC(duplex_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(autoneg_mode, uint, 0); -MODULE_PARM_DESC(autoneg_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(advertising_mode, uint, 0); -MODULE_PARM_DESC(advertising_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(aspm, int, 0); -MODULE_PARM_DESC(aspm, "Enable ASPM."); - -module_param(dynamic_aspm, int, 0); -MODULE_PARM_DESC(aspm, "Enable Software Dynamic ASPM."); - -module_param(s5wol, int, 0); -MODULE_PARM_DESC(s5wol, "Enable Shutdown Wake On Lan."); - -module_param(s5_keep_curr_mac, int, 0); -MODULE_PARM_DESC(s5_keep_curr_mac, "Enable Shutdown Keep Current MAC Address."); - -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); - -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); - -module_param(timer_count, int, 0); -MODULE_PARM_DESC(timer_count, "Timer Interrupt Interval."); - -module_param(eee_enable, int, 0); -MODULE_PARM_DESC(eee_enable, "Enable Energy Efficient Ethernet."); - -module_param(hwoptimize, ulong, 0); -MODULE_PARM_DESC(hwoptimize, "Enable HW optimization function."); - -module_param(s0_magic_packet, int, 0); -MODULE_PARM_DESC(s0_magic_packet, "Enable S0 Magic Packet."); - -module_param(dynamic_aspm_packet_threshold, int, 0); -MODULE_PARM_DESC(dynamic_aspm_packet_threshold, "Dynamic ASPM packet threshold."); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -#endif//LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - -MODULE_LICENSE("GPL"); -#ifdef ENABLE_USE_FIRMWARE_FILE -MODULE_FIRMWARE(FIRMWARE_8168D_1); -MODULE_FIRMWARE(FIRMWARE_8168D_2); -MODULE_FIRMWARE(FIRMWARE_8168E_1); -MODULE_FIRMWARE(FIRMWARE_8168E_2); -MODULE_FIRMWARE(FIRMWARE_8168E_3); -MODULE_FIRMWARE(FIRMWARE_8168E_4); -MODULE_FIRMWARE(FIRMWARE_8168F_1); -MODULE_FIRMWARE(FIRMWARE_8168F_2); -MODULE_FIRMWARE(FIRMWARE_8411_1); -MODULE_FIRMWARE(FIRMWARE_8411_2); -MODULE_FIRMWARE(FIRMWARE_8168G_2); -MODULE_FIRMWARE(FIRMWARE_8168G_3); -MODULE_FIRMWARE(FIRMWARE_8168EP_1); -MODULE_FIRMWARE(FIRMWARE_8168EP_2); -MODULE_FIRMWARE(FIRMWARE_8168EP_3); -MODULE_FIRMWARE(FIRMWARE_8168H_1); -MODULE_FIRMWARE(FIRMWARE_8168H_2); -MODULE_FIRMWARE(FIRMWARE_8168FP_3); -MODULE_FIRMWARE(FIRMWARE_8168FP_4); -#endif - -MODULE_VERSION(RTL8168_VERSION); - -static void rtl8168_sleep_rx_enable(struct net_device *dev); -static void rtl8168_dsm(struct net_device *dev, int dev_state); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -static void rtl8168_esd_timer(unsigned long __opaque); -#else -static void rtl8168_esd_timer(struct timer_list *t); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -static void rtl8168_link_timer(unsigned long __opaque); -#else -static void rtl8168_link_timer(struct timer_list *t); -#endif -static void rtl8168_tx_clear(struct rtl8168_private *tp); -static void rtl8168_rx_clear(struct rtl8168_private *tp); - -static int rtl8168_open(struct net_device *dev); -static netdev_tx_t rtl8168_start_xmit(struct sk_buff *skb, struct net_device *dev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8168_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -#else -static irqreturn_t rtl8168_interrupt(int irq, void *dev_instance); -#endif -static void rtl8168_rx_desc_offset0_init(struct rtl8168_private *, int); -static int rtl8168_init_ring(struct net_device *dev); -static void rtl8168_hw_config(struct net_device *dev); -static void rtl8168_hw_start(struct net_device *dev); -static int rtl8168_close(struct net_device *dev); -static void rtl8168_set_rx_mode(struct net_device *dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static void rtl8168_tx_timeout(struct net_device *dev, unsigned int txqueue); -#else -static void rtl8168_tx_timeout(struct net_device *dev); -#endif -static struct net_device_stats *rtl8168_get_stats(struct net_device *dev); -static int rtl8168_rx_interrupt(struct net_device *, struct rtl8168_private *, napi_budget); -static int rtl8168_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8168_down(struct net_device *dev); - -static int rtl8168_set_mac_address(struct net_device *dev, void *p); -void rtl8168_rar_set(struct rtl8168_private *tp, uint8_t *addr); -static void rtl8168_desc_addr_fill(struct rtl8168_private *); -static void rtl8168_tx_desc_init(struct rtl8168_private *tp); -static void rtl8168_rx_desc_init(struct rtl8168_private *tp); - -static u16 rtl8168_get_hw_phy_mcu_code_ver(struct rtl8168_private *tp); - -static void rtl8168_hw_reset(struct net_device *dev); - -static void rtl8168_phy_power_up(struct net_device *dev); -static void rtl8168_phy_power_down(struct net_device *dev); -static int rtl8168_set_speed(struct net_device *dev, u8 autoneg, u32 speed, u8 duplex, u32 adv); - -static int rtl8168_set_phy_mcu_patch_request(struct rtl8168_private *tp); -static int rtl8168_clear_phy_mcu_patch_request(struct rtl8168_private *tp); - -#ifdef CONFIG_R8168_NAPI -static int rtl8168_poll(napi_ptr napi, napi_budget budget); -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8168_reset_task(void *_data); -#else -static void rtl8168_reset_task(struct work_struct *work); -#endif - -static inline struct device *tp_to_dev(struct rtl8168_private *tp) -{ - return &tp->pci_dev->dev; -} - -#if ((LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) && \ - LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,00))) -void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, - u32 legacy_u32) -{ - bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS); - dst[0] = legacy_u32; -} - -bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, - const unsigned long *src) -{ - bool retval = true; - - /* TODO: following test will soon always be true */ - if (__ETHTOOL_LINK_MODE_MASK_NBITS > 32) { - __ETHTOOL_DECLARE_LINK_MODE_MASK(ext); - - bitmap_zero(ext, __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_fill(ext, 32); - bitmap_complement(ext, ext, __ETHTOOL_LINK_MODE_MASK_NBITS); - if (bitmap_intersects(ext, src, - __ETHTOOL_LINK_MODE_MASK_NBITS)) { - /* src mask goes beyond bit 31 */ - retval = false; - } - } - *legacy_u32 = src[0]; - return retval; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - -#ifndef LPA_1000FULL -#define LPA_1000FULL 0x0800 -#endif - -#ifndef LPA_1000HALF -#define LPA_1000HALF 0x0400 -#endif - -static inline u32 mii_adv_to_ethtool_adv_t(u32 adv) -{ - u32 result = 0; - - if (adv & ADVERTISE_10HALF) - result |= ADVERTISED_10baseT_Half; - if (adv & ADVERTISE_10FULL) - result |= ADVERTISED_10baseT_Full; - if (adv & ADVERTISE_100HALF) - result |= ADVERTISED_100baseT_Half; - if (adv & ADVERTISE_100FULL) - result |= ADVERTISED_100baseT_Full; - if (adv & ADVERTISE_PAUSE_CAP) - result |= ADVERTISED_Pause; - if (adv & ADVERTISE_PAUSE_ASYM) - result |= ADVERTISED_Asym_Pause; - - return result; -} - -static inline u32 mii_lpa_to_ethtool_lpa_t(u32 lpa) -{ - u32 result = 0; - - if (lpa & LPA_LPACK) - result |= ADVERTISED_Autoneg; - - return result | mii_adv_to_ethtool_adv_t(lpa); -} - -static inline u32 mii_stat1000_to_ethtool_lpa_t(u32 lpa) -{ - u32 result = 0; - - if (lpa & LPA_1000HALF) - result |= ADVERTISED_1000baseT_Half; - if (lpa & LPA_1000FULL) - result |= ADVERTISED_1000baseT_Full; - - return result; -} - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) -static inline void eth_hw_addr_random(struct net_device *dev) -{ - random_ether_addr(dev->dev_addr); -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#undef ethtool_ops -#define ethtool_ops _kc_ethtool_ops - -struct _kc_ethtool_ops { - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - int (*set_settings)(struct net_device *, struct ethtool_cmd *); - void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); - int (*get_regs_len)(struct net_device *); - void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); - void (*get_wol)(struct net_device *, struct ethtool_wolinfo *); - int (*set_wol)(struct net_device *, struct ethtool_wolinfo *); - u32 (*get_msglevel)(struct net_device *); - void (*set_msglevel)(struct net_device *, u32); - int (*nway_reset)(struct net_device *); - u32 (*get_link)(struct net_device *); - int (*get_eeprom_len)(struct net_device *); - int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); - int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); - int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *); - int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *); - void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *); - int (*set_ringparam)(struct net_device *, struct ethtool_ringparam *); - void (*get_pauseparam)(struct net_device *, - struct ethtool_pauseparam*); - int (*set_pauseparam)(struct net_device *, - struct ethtool_pauseparam*); - u32 (*get_rx_csum)(struct net_device *); - int (*set_rx_csum)(struct net_device *, u32); - u32 (*get_tx_csum)(struct net_device *); - int (*set_tx_csum)(struct net_device *, u32); - u32 (*get_sg)(struct net_device *); - int (*set_sg)(struct net_device *, u32); - u32 (*get_tso)(struct net_device *); - int (*set_tso)(struct net_device *, u32); - int (*self_test_count)(struct net_device *); - void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); - void (*get_strings)(struct net_device *, u32 stringset, u8 *); - int (*phys_id)(struct net_device *, u32); - int (*get_stats_count)(struct net_device *); - void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, - u64 *); -} *ethtool_ops = NULL; - -#undef SET_ETHTOOL_OPS -#define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops)) - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) -#ifndef SET_ETHTOOL_OPS -#define SET_ETHTOOL_OPS(netdev,ops) \ - ( (netdev)->ethtool_ops = (ops) ) -#endif //SET_ETHTOOL_OPS -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) - -//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) -#ifndef netif_msg_init -#define netif_msg_init _kc_netif_msg_init -/* copied from linux kernel 2.6.20 include/linux/netdevice.h */ -static inline u32 netif_msg_init(int debug_value, int default_msg_enable_bits) -{ - /* use default */ - if (debug_value < 0 || debug_value >= (sizeof(u32) * 8)) - return default_msg_enable_bits; - if (debug_value == 0) /* no output */ - return 0; - /* set low N bits */ - return (1 << debug_value) - 1; -} - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) -static inline void eth_copy_and_sum (struct sk_buff *dest, - const unsigned char *src, - int len, int base) -{ - memcpy (dest->data, src, len); -} -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) -/* copied from linux kernel 2.6.20 /include/linux/time.h */ -/* Parameters used to convert the timespec values: */ -#define MSEC_PER_SEC 1000L - -/* copied from linux kernel 2.6.20 /include/linux/jiffies.h */ -/* - * Change timeval to jiffies, trying to avoid the - * most obvious overflows.. - * - * And some not so obvious. - * - * Note that we don't want to return MAX_LONG, because - * for various timeout reasons we often end up having - * to wait "jiffies+1" in order to guarantee that we wait - * at _least_ "jiffies" - so "jiffies+1" had better still - * be positive. - */ -#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1) - -/* - * Convert jiffies to milliseconds and back. - * - * Avoid unnecessary multiplications/divisions in the - * two most common HZ cases: - */ -static inline unsigned int _kc_jiffies_to_msecs(const unsigned long j) -{ -#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) - return (MSEC_PER_SEC / HZ) * j; -#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) - return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); -#else - return (j * MSEC_PER_SEC) / HZ; -#endif -} - -static inline unsigned long _kc_msecs_to_jiffies(const unsigned int m) -{ - if (m > _kc_jiffies_to_msecs(MAX_JIFFY_OFFSET)) - return MAX_JIFFY_OFFSET; -#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) - return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); -#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) - return m * (HZ / MSEC_PER_SEC); -#else - return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC; -#endif -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) - -/* copied from linux kernel 2.6.12.6 /include/linux/pm.h */ -typedef int __bitwise pci_power_t; - -/* copied from linux kernel 2.6.12.6 /include/linux/pci.h */ -typedef u32 __bitwise pm_message_t; - -#define PCI_D0 ((pci_power_t __force) 0) -#define PCI_D1 ((pci_power_t __force) 1) -#define PCI_D2 ((pci_power_t __force) 2) -#define PCI_D3hot ((pci_power_t __force) 3) -#define PCI_D3cold ((pci_power_t __force) 4) -#define PCI_POWER_ERROR ((pci_power_t __force) -1) - -/* copied from linux kernel 2.6.12.6 /drivers/pci/pci.c */ -/** - * pci_choose_state - Choose the power state of a PCI device - * @dev: PCI device to be suspended - * @state: target sleep state for the whole system. This is the value - * that is passed to suspend() function. - * - * Returns PCI power state suitable for given device and given system - * message. - */ - -pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) -{ - if (!pci_find_capability(dev, PCI_CAP_ID_PM)) - return PCI_D0; - - switch (state) { - case 0: - return PCI_D0; - case 3: - return PCI_D3hot; - default: - printk("They asked me for state %d\n", state); -// BUG(); - } - return PCI_D0; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -/** - * msleep_interruptible - sleep waiting for waitqueue interruptions - * @msecs: Time in milliseconds to sleep for - */ -#define msleep_interruptible _kc_msleep_interruptible -unsigned long _kc_msleep_interruptible(unsigned int msecs) -{ - unsigned long timeout = _kc_msecs_to_jiffies(msecs); - - while (timeout && !signal_pending(current)) { - set_current_state(TASK_INTERRUPTIBLE); - timeout = schedule_timeout(timeout); - } - return _kc_jiffies_to_msecs(timeout); -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) -/* copied from linux kernel 2.6.20 include/linux/sched.h */ -#ifndef __sched -#define __sched __attribute__((__section__(".sched.text"))) -#endif - -/* copied from linux kernel 2.6.20 kernel/timer.c */ -signed long __sched schedule_timeout_uninterruptible(signed long timeout) -{ - __set_current_state(TASK_UNINTERRUPTIBLE); - return schedule_timeout(timeout); -} - -/* copied from linux kernel 2.6.20 include/linux/mii.h */ -#undef if_mii -#define if_mii _kc_if_mii -static inline struct mii_ioctl_data *if_mii(struct ifreq *rq) -{ - return (struct mii_ioctl_data *) &rq->ifr_ifru; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) - -struct rtl8168_counters { - u64 tx_packets; - u64 rx_packets; - u64 tx_errors; - u32 rx_errors; - u16 rx_missed; - u16 align_errors; - u32 tx_one_collision; - u32 tx_multi_collision; - u64 rx_unicast; - u64 rx_broadcast; - u32 rx_multicast; - u16 tx_aborted; - u16 tx_underrun; -}; - -#ifdef ENABLE_R8168_PROCFS -/**************************************************************************** -* -----------------------------PROCFS STUFF------------------------- -***************************************************************************** -*/ - -static struct proc_dir_entry *rtl8168_proc; -static int proc_init_num = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -static int proc_get_driver_variable(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - seq_puts(m, "\nDump Driver Variable\n"); - - spin_lock_irqsave(&tp->lock, flags); - seq_puts(m, "Variable\tValue\n----------\t-----\n"); - seq_printf(m, "MODULENAME\t%s\n", MODULENAME); - seq_printf(m, "driver version\t%s\n", RTL8168_VERSION); - seq_printf(m, "chipset\t%d\n", tp->chipset); - seq_printf(m, "chipset_name\t%s\n", rtl_chip_info[tp->chipset].name); - seq_printf(m, "mtu\t%d\n", dev->mtu); - seq_printf(m, "NUM_RX_DESC\t0x%x\n", NUM_RX_DESC); - seq_printf(m, "cur_rx\t0x%x\n", tp->cur_rx); - seq_printf(m, "dirty_rx\t0x%x\n", tp->dirty_rx); - seq_printf(m, "NUM_TX_DESC\t0x%x\n", NUM_TX_DESC); - seq_printf(m, "cur_tx\t0x%x\n", tp->cur_tx); - seq_printf(m, "dirty_tx\t0x%x\n", tp->dirty_tx); - seq_printf(m, "rx_buf_sz\t0x%x\n", tp->rx_buf_sz); - seq_printf(m, "esd_flag\t0x%x\n", tp->esd_flag); - seq_printf(m, "pci_cfg_is_read\t0x%x\n", tp->pci_cfg_is_read); - seq_printf(m, "rtl8168_rx_config\t0x%x\n", tp->rtl8168_rx_config); - seq_printf(m, "cp_cmd\t0x%x\n", tp->cp_cmd); - seq_printf(m, "intr_mask\t0x%x\n", tp->intr_mask); - seq_printf(m, "timer_intr_mask\t0x%x\n", tp->timer_intr_mask); - seq_printf(m, "wol_enabled\t0x%x\n", tp->wol_enabled); - seq_printf(m, "wol_opts\t0x%x\n", tp->wol_opts); - seq_printf(m, "efuse_ver\t0x%x\n", tp->efuse_ver); - seq_printf(m, "eeprom_type\t0x%x\n", tp->eeprom_type); - seq_printf(m, "autoneg\t0x%x\n", tp->autoneg); - seq_printf(m, "duplex\t0x%x\n", tp->duplex); - seq_printf(m, "speed\t%d\n", tp->speed); - seq_printf(m, "advertising\t0x%x\n", tp->advertising); - seq_printf(m, "eeprom_len\t0x%x\n", tp->eeprom_len); - seq_printf(m, "cur_page\t0x%x\n", tp->cur_page); - seq_printf(m, "bios_setting\t0x%x\n", tp->bios_setting); - seq_printf(m, "features\t0x%x\n", tp->features); - seq_printf(m, "org_pci_offset_99\t0x%x\n", tp->org_pci_offset_99); - seq_printf(m, "org_pci_offset_180\t0x%x\n", tp->org_pci_offset_180); - seq_printf(m, "issue_offset_99_event\t0x%x\n", tp->issue_offset_99_event); - seq_printf(m, "org_pci_offset_80\t0x%x\n", tp->org_pci_offset_80); - seq_printf(m, "org_pci_offset_81\t0x%x\n", tp->org_pci_offset_81); - seq_printf(m, "use_timer_interrrupt\t0x%x\n", tp->use_timer_interrrupt); - seq_printf(m, "HwIcVerUnknown\t0x%x\n", tp->HwIcVerUnknown); - seq_printf(m, "NotWrRamCodeToMicroP\t0x%x\n", tp->NotWrRamCodeToMicroP); - seq_printf(m, "NotWrMcuPatchCode\t0x%x\n", tp->NotWrMcuPatchCode); - seq_printf(m, "HwHasWrRamCodeToMicroP\t0x%x\n", tp->HwHasWrRamCodeToMicroP); - seq_printf(m, "sw_ram_code_ver\t0x%x\n", tp->sw_ram_code_ver); - seq_printf(m, "hw_ram_code_ver\t0x%x\n", tp->hw_ram_code_ver); - seq_printf(m, "rtk_enable_diag\t0x%x\n", tp->rtk_enable_diag); - seq_printf(m, "ShortPacketSwChecksum\t0x%x\n", tp->ShortPacketSwChecksum); - seq_printf(m, "UseSwPaddingShortPkt\t0x%x\n", tp->UseSwPaddingShortPkt); - seq_printf(m, "RequireAdcBiasPatch\t0x%x\n", tp->RequireAdcBiasPatch); - seq_printf(m, "AdcBiasPatchIoffset\t0x%x\n", tp->AdcBiasPatchIoffset); - seq_printf(m, "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n", tp->RequireAdjustUpsTxLinkPulseTiming); - seq_printf(m, "SwrCnt1msIni\t0x%x\n", tp->SwrCnt1msIni); - seq_printf(m, "HwSuppNowIsOobVer\t0x%x\n", tp->HwSuppNowIsOobVer); - seq_printf(m, "HwFiberModeVer\t0x%x\n", tp->HwFiberModeVer); - seq_printf(m, "HwFiberStat\t0x%x\n", tp->HwFiberStat); - seq_printf(m, "HwSwitchMdiToFiber\t0x%x\n", tp->HwSwitchMdiToFiber); - seq_printf(m, "HwSuppSerDesPhyVer\t0x%x\n", tp->HwSuppSerDesPhyVer); - seq_printf(m, "NicCustLedValue\t0x%x\n", tp->NicCustLedValue); - seq_printf(m, "RequiredSecLanDonglePatch\t0x%x\n", tp->RequiredSecLanDonglePatch); - seq_printf(m, "HwSuppDashVer\t0x%x\n", tp->HwSuppDashVer); - seq_printf(m, "DASH\t0x%x\n", tp->DASH); - seq_printf(m, "dash_printer_enabled\t0x%x\n", tp->dash_printer_enabled); - seq_printf(m, "HwSuppKCPOffloadVer\t0x%x\n", tp->HwSuppKCPOffloadVer); - seq_printf(m, "speed_mode\t0x%x\n", speed_mode); - seq_printf(m, "duplex_mode\t0x%x\n", duplex_mode); - seq_printf(m, "autoneg_mode\t0x%x\n", autoneg_mode); - seq_printf(m, "advertising_mode\t0x%x\n", advertising_mode); - seq_printf(m, "aspm\t0x%x\n", aspm); - seq_printf(m, "s5wol\t0x%x\n", s5wol); - seq_printf(m, "s5_keep_curr_mac\t0x%x\n", s5_keep_curr_mac); - seq_printf(m, "eee_enable\t0x%x\n", tp->eee_enabled); - seq_printf(m, "hwoptimize\t0x%lx\n", hwoptimize); - seq_printf(m, "proc_init_num\t0x%x\n", proc_init_num); - seq_printf(m, "s0_magic_packet\t0x%x\n", s0_magic_packet); - seq_printf(m, "HwSuppMagicPktVer\t0x%x\n", tp->HwSuppMagicPktVer); - seq_printf(m, "HwSuppUpsVer\t0x%x\n", tp->HwSuppUpsVer); - seq_printf(m, "HwSuppEsdVer\t0x%x\n", tp->HwSuppEsdVer); - seq_printf(m, "HwSuppCheckPhyDisableModeVer\t0x%x\n", tp->HwSuppCheckPhyDisableModeVer); - seq_printf(m, "HwPkgDet\t0x%x\n", tp->HwPkgDet); - seq_printf(m, "random_mac\t0x%x\n", tp->random_mac); - seq_printf(m, "org_mac_addr\t%pM\n", tp->org_mac_addr); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - seq_printf(m, "perm_addr\t%pM\n", dev->perm_addr); -#endif - seq_printf(m, "dev_addr\t%pM\n", dev->dev_addr); - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_tally_counter(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct rtl8168_private *tp = netdev_priv(dev); - struct rtl8168_counters *counters; - dma_addr_t paddr; - u32 cmd; - u32 WaitCnt; - unsigned long flags; - - seq_puts(m, "\nDump Tally Counter\n"); - - //ASSERT_RTNL(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) { - seq_puts(m, "\nDump Tally Counter Fail\n"); - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(tp, CounterAddrLow, cmd); - RTL_W32(tp, CounterAddrLow, cmd | CounterDump); - - WaitCnt = 0; - while (RTL_R32(tp, CounterAddrLow) & CounterDump) { - udelay(10); - - WaitCnt++; - if (WaitCnt > 20) - break; - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_puts(m, "Statistics\tValue\n----------\t-----\n"); - seq_printf(m, "tx_packets\t%lld\n", le64_to_cpu(counters->tx_packets)); - seq_printf(m, "rx_packets\t%lld\n", le64_to_cpu(counters->rx_packets)); - seq_printf(m, "tx_errors\t%lld\n", le64_to_cpu(counters->tx_errors)); - seq_printf(m, "rx_errors\t%d\n", le32_to_cpu(counters->rx_errors)); - seq_printf(m, "rx_missed\t%d\n", le16_to_cpu(counters->rx_missed)); - seq_printf(m, "align_errors\t%d\n", le16_to_cpu(counters->align_errors)); - seq_printf(m, "tx_one_collision\t%d\n", le32_to_cpu(counters->tx_one_collision)); - seq_printf(m, "tx_multi_collision\t%d\n", le32_to_cpu(counters->tx_multi_collision)); - seq_printf(m, "rx_unicast\t%lld\n", le64_to_cpu(counters->rx_unicast)); - seq_printf(m, "rx_broadcast\t%lld\n", le64_to_cpu(counters->rx_broadcast)); - seq_printf(m, "rx_multicast\t%d\n", le32_to_cpu(counters->rx_multicast)); - seq_printf(m, "tx_aborted\t%d\n", le16_to_cpu(counters->tx_aborted)); - seq_printf(m, "tx_underrun\t%d\n", le16_to_cpu(counters->tx_underrun)); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8168_MAC_REGS_SIZE; - u8 byte_rd; - struct rtl8168_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - seq_puts(m, "\nDump MAC Registers\n"); - seq_puts(m, "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 16 && n < max; i++, n++) { - byte_rd = readb(ioaddr + n); - seq_printf(m, "%02x ", byte_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_pcie_phy(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8168_EPHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - seq_puts(m, "\nDump PCIE PHY\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8168_ephy_read(tp, n); - seq_printf(m, "%04x ", word_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_eth_phy(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8168_PHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - seq_puts(m, "\nDump Ethernet PHY\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - spin_lock_irqsave(&tp->lock, flags); - seq_puts(m, "\n####################page 0##################\n "); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8168_mdio_read(tp, n); - seq_printf(m, "%04x ", word_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_extended_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8168_ERI_REGS_SIZE; - u32 dword_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - /* RTL8168B does not support Extend GMAC */ - seq_puts(m, "\nNot Support Dump Extended Registers\n"); - return 0; - } - - seq_puts(m, "\nDump Extended Registers\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - dword_rd = rtl8168_eri_read(tp, n, 4, ERIAR_ExGMAC); - seq_printf(m, "%08x ", dword_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_pci_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8168_PCI_REGS_SIZE; - u32 dword_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - seq_puts(m, "\nDump PCI Registers\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%03x:\t", n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "%08x ", dword_rd); - } - } - - n = 0x110; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); - n = 0x70c; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); - - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} -#else - -static int proc_get_driver_variable(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Driver Driver\n"); - - spin_lock_irqsave(&tp->lock, flags); - len += snprintf(page + len, count - len, - "Variable\tValue\n----------\t-----\n"); - - len += snprintf(page + len, count - len, - "MODULENAME\t%s\n" - "driver version\t%s\n" - "chipset\t%d\n" - "chipset_name\t%s\n" - "mtu\t%d\n" - "NUM_RX_DESC\t0x%x\n" - "cur_rx\t0x%x\n" - "dirty_rx\t0x%x\n" - "NUM_TX_DESC\t0x%x\n" - "cur_tx\t0x%x\n" - "dirty_tx\t0x%x\n" - "rx_buf_sz\t0x%x\n" - "esd_flag\t0x%x\n" - "pci_cfg_is_read\t0x%x\n" - "rtl8168_rx_config\t0x%x\n" - "cp_cmd\t0x%x\n" - "intr_mask\t0x%x\n" - "timer_intr_mask\t0x%x\n" - "wol_enabled\t0x%x\n" - "wol_opts\t0x%x\n" - "efuse_ver\t0x%x\n" - "eeprom_type\t0x%x\n" - "autoneg\t0x%x\n" - "duplex\t0x%x\n" - "speed\t%d\n" - "advertising\t0x%x\n" - "eeprom_len\t0x%x\n" - "cur_page\t0x%x\n" - "bios_setting\t0x%x\n" - "features\t0x%x\n" - "org_pci_offset_99\t0x%x\n" - "org_pci_offset_180\t0x%x\n" - "issue_offset_99_event\t0x%x\n" - "org_pci_offset_80\t0x%x\n" - "org_pci_offset_81\t0x%x\n" - "use_timer_interrrupt\t0x%x\n" - "HwIcVerUnknown\t0x%x\n" - "NotWrRamCodeToMicroP\t0x%x\n" - "NotWrMcuPatchCode\t0x%x\n" - "HwHasWrRamCodeToMicroP\t0x%x\n" - "sw_ram_code_ver\t0x%x\n" - "hw_ram_code_ver\t0x%x\n" - "rtk_enable_diag\t0x%x\n" - "ShortPacketSwChecksum\t0x%x\n" - "UseSwPaddingShortPkt\t0x%x\n" - "RequireAdcBiasPatch\t0x%x\n" - "AdcBiasPatchIoffset\t0x%x\n" - "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n" - "SwrCnt1msIni\t0x%x\n" - "HwSuppNowIsOobVer\t0x%x\n" - "HwFiberModeVer\t0x%x\n" - "HwFiberStat\t0x%x\n" - "HwSwitchMdiToFiber\t0x%x\n" - "HwSuppSerDesPhyVer\t0x%x\n" - "NicCustLedValue\t0x%x\n" - "RequiredSecLanDonglePatch\t0x%x\n" - "HwSuppDashVer\t0x%x\n" - "DASH\t0x%x\n" - "dash_printer_enabled\t0x%x\n" - "HwSuppKCPOffloadVer\t0x%x\n" - "speed_mode\t0x%x\n" - "duplex_mode\t0x%x\n" - "autoneg_mode\t0x%x\n" - "advertising_mode\t0x%x\n" - "aspm\t0x%x\n" - "s5wol\t0x%x\n" - "s5_keep_curr_mac\t0x%x\n" - "eee_enable\t0x%x\n" - "hwoptimize\t0x%lx\n" - "proc_init_num\t0x%x\n" - "s0_magic_packet\t0x%x\n" - "HwSuppMagicPktVer\t0x%x\n" - "HwSuppUpsVer\t0x%x\n" - "HwSuppEsdVer\t0x%x\n" - "HwSuppCheckPhyDisableModeVer\t0x%x\n" - "HwPkgDet\t0x%x\n" - "random_mac\t0x%x\n" - "org_mac_addr\t%pM\n" -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - "perm_addr\t%pM\n" -#endif - "dev_addr\t%pM\n", - MODULENAME, - RTL8168_VERSION, - tp->chipset, - rtl_chip_info[tp->chipset].name, - dev->mtu, - NUM_RX_DESC, - tp->cur_rx, - tp->dirty_rx, - NUM_TX_DESC, - tp->cur_tx, - tp->dirty_tx, - tp->rx_buf_sz, - tp->esd_flag, - tp->pci_cfg_is_read, - tp->rtl8168_rx_config, - tp->cp_cmd, - tp->intr_mask, - tp->timer_intr_mask, - tp->wol_enabled, - tp->wol_opts, - tp->efuse_ver, - tp->eeprom_type, - tp->autoneg, - tp->duplex, - tp->speed, - tp->advertising, - tp->eeprom_len, - tp->cur_page, - tp->bios_setting, - tp->features, - tp->org_pci_offset_99, - tp->org_pci_offset_180, - tp->issue_offset_99_event, - tp->org_pci_offset_80, - tp->org_pci_offset_81, - tp->use_timer_interrrupt, - tp->HwIcVerUnknown, - tp->NotWrRamCodeToMicroP, - tp->NotWrMcuPatchCode, - tp->HwHasWrRamCodeToMicroP, - tp->sw_ram_code_ver, - tp->hw_ram_code_ver, - tp->rtk_enable_diag, - tp->ShortPacketSwChecksum, - tp->UseSwPaddingShortPkt, - tp->RequireAdcBiasPatch, - tp->AdcBiasPatchIoffset, - tp->RequireAdjustUpsTxLinkPulseTiming, - tp->SwrCnt1msIni, - tp->HwSuppNowIsOobVer, - tp->HwFiberModeVer, - tp->HwFiberStat, - tp->HwSwitchMdiToFiber, - tp->HwSuppSerDesPhyVer, - tp->NicCustLedValue, - tp->RequiredSecLanDonglePatch, - tp->HwSuppDashVer, - tp->DASH, - tp->dash_printer_enabled, - tp->HwSuppKCPOffloadVer, - speed_mode, - duplex_mode, - autoneg_mode, - advertising_mode, - aspm, - s5wol, - s5_keep_curr_mac, - tp->eee_enabled, - hwoptimize, - proc_init_num, - s0_magic_packet, - tp->HwSuppMagicPktVer, - tp->HwSuppUpsVer, - tp->HwSuppEsdVer, - tp->HwSuppCheckPhyDisableModeVer, - tp->HwPkgDet, - tp->random_mac, - tp->org_mac_addr, -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - dev->perm_addr, -#endif - dev->dev_addr - ); - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_tally_counter(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct rtl8168_private *tp = netdev_priv(dev); - struct rtl8168_counters *counters; - dma_addr_t paddr; - u32 cmd; - u32 WaitCnt; - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Tally Counter\n"); - - //ASSERT_RTNL(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) { - len += snprintf(page + len, count - len, - "\nDump Tally Counter Fail\n"); - goto out; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(tp, CounterAddrLow, cmd); - RTL_W32(tp, CounterAddrLow, cmd | CounterDump); - - WaitCnt = 0; - while (RTL_R32(tp, CounterAddrLow) & CounterDump) { - udelay(10); - - WaitCnt++; - if (WaitCnt > 20) - break; - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, - "Statistics\tValue\n----------\t-----\n"); - - len += snprintf(page + len, count - len, - "tx_packets\t%lld\n" - "rx_packets\t%lld\n" - "tx_errors\t%lld\n" - "rx_errors\t%d\n" - "rx_missed\t%d\n" - "align_errors\t%d\n" - "tx_one_collision\t%d\n" - "tx_multi_collision\t%d\n" - "rx_unicast\t%lld\n" - "rx_broadcast\t%lld\n" - "rx_multicast\t%d\n" - "tx_aborted\t%d\n" - "tx_underrun\t%d\n", - le64_to_cpu(counters->tx_packets), - le64_to_cpu(counters->rx_packets), - le64_to_cpu(counters->tx_errors), - le32_to_cpu(counters->rx_errors), - le16_to_cpu(counters->rx_missed), - le16_to_cpu(counters->align_errors), - le32_to_cpu(counters->tx_one_collision), - le32_to_cpu(counters->tx_multi_collision), - le64_to_cpu(counters->rx_unicast), - le64_to_cpu(counters->rx_broadcast), - le32_to_cpu(counters->rx_multicast), - le16_to_cpu(counters->tx_aborted), - le16_to_cpu(counters->tx_underrun) - ); - - len += snprintf(page + len, count - len, "\n"); -out: - *eof = 1; - return len; -} - -static int proc_get_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8168_MAC_REGS_SIZE; - u8 byte_rd; - struct rtl8168_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump MAC Registers\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 16 && n < max; i++, n++) { - byte_rd = readb(ioaddr + n); - len += snprintf(page + len, count - len, - "%02x ", - byte_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_pcie_phy(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8168_EPHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump PCIE PHY\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8168_ephy_read(tp, n); - len += snprintf(page + len, count - len, - "%04x ", - word_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_eth_phy(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8168_PHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Ethernet PHY\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - len += snprintf(page + len, count - len, - "\n####################page 0##################\n"); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8168_mdio_read(tp, n); - len += snprintf(page + len, count - len, - "%04x ", - word_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_extended_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8168_ERI_REGS_SIZE; - u32 dword_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - /* RTL8168B does not support Extend GMAC */ - len += snprintf(page + len, count - len, - "\nNot Support Dump Extended Registers\n"); - - goto out; - } - - len += snprintf(page + len, count - len, - "\nDump Extended Registers\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - dword_rd = rtl8168_eri_read(tp, n, 4, ERIAR_ExGMAC); - len += snprintf(page + len, count - len, - "%08x ", - dword_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); -out: - *eof = 1; - return len; -} - -static int proc_get_pci_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8168_PCI_REGS_SIZE; - u32 dword_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump PCI Registers\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%03x:\t", - n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "%08x ", - dword_rd); - } - } - - n = 0x110; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "\n0x%03x:\t%08x ", - n, - dword_rd); - n = 0x70c; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "\n0x%03x:\t%08x ", - n, - dword_rd); - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} -#endif -static void rtl8168_proc_module_init(void) -{ - //create /proc/net/r8168 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) - rtl8168_proc = proc_mkdir(MODULENAME, init_net.proc_net); -#else - rtl8168_proc = proc_mkdir(MODULENAME, proc_net); -#endif - if (!rtl8168_proc) - dprintk("cannot create %s proc entry \n", MODULENAME); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -/* - * seq_file wrappers for procfile show routines. - */ -static int rtl8168_proc_open(struct inode *inode, struct file *file) -{ - struct net_device *dev = proc_get_parent_data(inode); - int (*show)(struct seq_file *, void *) = PDE_DATA(inode); - - return single_open(file, show, dev); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static const struct proc_ops rtl8168_proc_fops = { - .proc_open = rtl8168_proc_open, - .proc_read = seq_read, - .proc_lseek = seq_lseek, - .proc_release = single_release, -}; -#else -static const struct file_operations rtl8168_proc_fops = { - .open = rtl8168_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - -#endif - -/* - * Table of proc files we need to create. - */ -struct rtl8168_proc_file { - char name[12]; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - int (*show)(struct seq_file *, void *); -#else - int (*show)(char *, char **, off_t, int, int *, void *); -#endif -}; - -static const struct rtl8168_proc_file rtl8168_proc_files[] = { - { "driver_var", &proc_get_driver_variable }, - { "tally", &proc_get_tally_counter }, - { "registers", &proc_get_registers }, - { "pcie_phy", &proc_get_pcie_phy }, - { "eth_phy", &proc_get_eth_phy }, - { "ext_regs", &proc_get_extended_registers }, - { "pci_regs", &proc_get_pci_registers }, - { "" } -}; - -static void rtl8168_proc_init(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - const struct rtl8168_proc_file *f; - struct proc_dir_entry *dir; - - if (rtl8168_proc && !tp->proc_dir) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - dir = proc_mkdir_data(dev->name, 0, rtl8168_proc, dev); - if (!dir) { - printk("Unable to initialize /proc/net/%s/%s\n", - MODULENAME, dev->name); - return; - } - - tp->proc_dir = dir; - proc_init_num++; - - for (f = rtl8168_proc_files; f->name[0]; f++) { - if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir, - &rtl8168_proc_fops, f->show)) { - printk("Unable to initialize " - "/proc/net/%s/%s/%s\n", - MODULENAME, dev->name, f->name); - return; - } - } -#else - dir = proc_mkdir(dev->name, rtl8168_proc); - if (!dir) { - printk("Unable to initialize /proc/net/%s/%s\n", - MODULENAME, dev->name); - return; - } - - tp->proc_dir = dir; - proc_init_num++; - - for (f = rtl8168_proc_files; f->name[0]; f++) { - if (!create_proc_read_entry(f->name, S_IFREG | S_IRUGO, - dir, f->show, dev)) { - printk("Unable to initialize " - "/proc/net/%s/%s/%s\n", - MODULENAME, dev->name, f->name); - return; - } - } -#endif - } -} - -static void rtl8168_proc_remove(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (tp->proc_dir) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - remove_proc_subtree(dev->name, rtl8168_proc); - proc_init_num--; - -#else - const struct rtl8168_proc_file *f; - struct rtl8168_private *tp = netdev_priv(dev); - - for (f = rtl8168_proc_files; f->name[0]; f++) - remove_proc_entry(f->name, tp->proc_dir); - - remove_proc_entry(dev->name, rtl8168_proc); - proc_init_num--; -#endif - tp->proc_dir = NULL; - } -} - -#endif //ENABLE_R8168_PROCFS - -static inline u16 map_phy_ocp_addr(u16 PageNum, u8 RegNum) -{ - u16 OcpPageNum = 0; - u8 OcpRegNum = 0; - u16 OcpPhyAddress = 0; - - if ( PageNum == 0 ) { - OcpPageNum = OCP_STD_PHY_BASE_PAGE + ( RegNum / 8 ); - OcpRegNum = 0x10 + ( RegNum % 8 ); - } else { - OcpPageNum = PageNum; - OcpRegNum = RegNum; - } - - OcpPageNum <<= 4; - - if ( OcpRegNum < 16 ) { - OcpPhyAddress = 0; - } else { - OcpRegNum -= 16; - OcpRegNum <<= 1; - - OcpPhyAddress = OcpPageNum + OcpRegNum; - } - - - return OcpPhyAddress; -} - -static void mdio_real_direct_write_phy_ocp(struct rtl8168_private *tp, - u32 RegAddr, - u32 value) -{ - u32 data32; - int i; - - if (tp->HwSuppPhyOcpVer == 0) goto out; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(RegAddr % 2); -#endif - data32 = RegAddr/2; - data32 <<= OCPR_Addr_Reg_shift; - data32 |= OCPR_Write | value; - - RTL_W32(tp, PHYOCP, data32); - for (i = 0; i < 100; i++) { - udelay(1); - - if (!(RTL_R32(tp, PHYOCP) & OCPR_Flag)) - break; - } -out: - return; -} - -static void mdio_direct_write_phy_ocp(struct rtl8168_private *tp, - u16 RegAddr, - u16 value) -{ - if (tp->rtk_enable_diag) return; - - mdio_real_direct_write_phy_ocp(tp, RegAddr, value); -} - -static void rtl8168_mdio_write_phy_ocp(struct rtl8168_private *tp, - u16 PageNum, - u32 RegAddr, - u32 value) -{ - u16 ocp_addr; - - if (tp->rtk_enable_diag) return; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - mdio_direct_write_phy_ocp(tp, ocp_addr, value); -} - -static void rtl8168_mdio_real_write_phy_ocp(struct rtl8168_private *tp, - u16 PageNum, - u32 RegAddr, - u32 value) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - mdio_real_direct_write_phy_ocp(tp, ocp_addr, value); -} - -static void mdio_real_write(struct rtl8168_private *tp, - u32 RegAddr, - u32 value) -{ - int i; - - if (RegAddr == 0x1F) { - tp->cur_page = value; - } - - if (tp->mcfg == CFG_METHOD_11) { - RTL_W32(tp, OCPDR, OCPDR_Write | - (RegAddr & OCPDR_Reg_Mask) << OCPDR_GPHY_Reg_shift | - (value & OCPDR_Data_Mask)); - RTL_W32(tp, OCPAR, OCPAR_GPHY_Write); - RTL_W32(tp, EPHY_RXER_NUM, 0); - - for (i = 0; i < 100; i++) { - mdelay(1); - if (!(RTL_R32(tp, OCPAR) & OCPAR_Flag)) - break; - } - } else { - if (tp->HwSuppPhyOcpVer > 0) { - if (RegAddr == 0x1F) { - return; - } - rtl8168_mdio_real_write_phy_ocp(tp, tp->cur_page, RegAddr, value); - } else { - if (tp->mcfg == CFG_METHOD_12 || tp->mcfg == CFG_METHOD_13) - RTL_W32(tp, 0xD0, RTL_R32(tp, 0xD0) & ~0x00020000); - - RTL_W32(tp, PHYAR, PHYAR_Write | - (RegAddr & PHYAR_Reg_Mask) << PHYAR_Reg_shift | - (value & PHYAR_Data_Mask)); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed writing to the specified MII register */ - if (!(RTL_R32(tp, PHYAR) & PHYAR_Flag)) { - udelay(20); - break; - } - } - - if (tp->mcfg == CFG_METHOD_12 || tp->mcfg == CFG_METHOD_13) - RTL_W32(tp, 0xD0, RTL_R32(tp, 0xD0) | 0x00020000); - } - } -} - -void rtl8168_mdio_write(struct rtl8168_private *tp, - u16 RegAddr, - u16 value) -{ - if (tp->rtk_enable_diag) return; - - mdio_real_write(tp, RegAddr, value); -} - -void rtl8168_mdio_prot_write(struct rtl8168_private *tp, - u32 RegAddr, - u32 value) -{ - mdio_real_write(tp, RegAddr, value); -} - -void rtl8168_mdio_prot_direct_write_phy_ocp(struct rtl8168_private *tp, - u32 RegAddr, - u32 value) -{ - mdio_real_direct_write_phy_ocp(tp, RegAddr, value); -} - -static u32 mdio_real_direct_read_phy_ocp(struct rtl8168_private *tp, - u32 RegAddr) -{ - u32 data32; - int i, value = 0; - - if (tp->HwSuppPhyOcpVer == 0) goto out; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(RegAddr % 2); -#endif - data32 = RegAddr/2; - data32 <<= OCPR_Addr_Reg_shift; - - RTL_W32(tp, PHYOCP, data32); - for (i = 0; i < 100; i++) { - udelay(1); - - if (RTL_R32(tp, PHYOCP) & OCPR_Flag) - break; - } - value = RTL_R32(tp, PHYOCP) & OCPDR_Data_Mask; - -out: - return value; -} - -static u32 mdio_direct_read_phy_ocp(struct rtl8168_private *tp, - u16 RegAddr) -{ - if (tp->rtk_enable_diag) return 0xffffffff; - - return mdio_real_direct_read_phy_ocp(tp, RegAddr); -} - -static u32 rtl8168_mdio_read_phy_ocp(struct rtl8168_private *tp, - u16 PageNum, - u32 RegAddr) -{ - u16 ocp_addr; - - if (tp->rtk_enable_diag) return 0xffffffff; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - return mdio_direct_read_phy_ocp(tp, ocp_addr); -} - -static u32 rtl8168_mdio_real_read_phy_ocp(struct rtl8168_private *tp, - u16 PageNum, - u32 RegAddr) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - return mdio_real_direct_read_phy_ocp(tp, ocp_addr); -} - -u32 mdio_real_read(struct rtl8168_private *tp, - u32 RegAddr) -{ - int i, value = 0; - - if (tp->mcfg==CFG_METHOD_11) { - RTL_W32(tp, OCPDR, OCPDR_Read | - (RegAddr & OCPDR_Reg_Mask) << OCPDR_GPHY_Reg_shift); - RTL_W32(tp, OCPAR, OCPAR_GPHY_Write); - RTL_W32(tp, EPHY_RXER_NUM, 0); - - for (i = 0; i < 100; i++) { - mdelay(1); - if (!(RTL_R32(tp, OCPAR) & OCPAR_Flag)) - break; - } - - mdelay(1); - RTL_W32(tp, OCPAR, OCPAR_GPHY_Read); - RTL_W32(tp, EPHY_RXER_NUM, 0); - - for (i = 0; i < 100; i++) { - mdelay(1); - if (RTL_R32(tp, OCPAR) & OCPAR_Flag) - break; - } - - value = RTL_R32(tp, OCPDR) & OCPDR_Data_Mask; - } else { - if (tp->HwSuppPhyOcpVer > 0) { - value = rtl8168_mdio_real_read_phy_ocp(tp, tp->cur_page, RegAddr); - } else { - if (tp->mcfg == CFG_METHOD_12 || tp->mcfg == CFG_METHOD_13) - RTL_W32(tp, 0xD0, RTL_R32(tp, 0xD0) & ~0x00020000); - - RTL_W32(tp, PHYAR, - PHYAR_Read | (RegAddr & PHYAR_Reg_Mask) << PHYAR_Reg_shift); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed retrieving data from the specified MII register */ - if (RTL_R32(tp, PHYAR) & PHYAR_Flag) { - value = RTL_R32(tp, PHYAR) & PHYAR_Data_Mask; - udelay(20); - break; - } - } - - if (tp->mcfg == CFG_METHOD_12 || tp->mcfg == CFG_METHOD_13) - RTL_W32(tp, 0xD0, RTL_R32(tp, 0xD0) | 0x00020000); - } - } - - return value; -} - -u32 rtl8168_mdio_read(struct rtl8168_private *tp, - u16 RegAddr) -{ - if (tp->rtk_enable_diag) return 0xffffffff; - - return mdio_real_read(tp, RegAddr); -} - -u32 rtl8168_mdio_prot_read(struct rtl8168_private *tp, - u32 RegAddr) -{ - return mdio_real_read(tp, RegAddr); -} - -u32 rtl8168_mdio_prot_direct_read_phy_ocp(struct rtl8168_private *tp, - u32 RegAddr) -{ - return mdio_real_direct_read_phy_ocp(tp, RegAddr); -} - -static void ClearAndSetEthPhyBit(struct rtl8168_private *tp, u8 addr, u16 clearmask, u16 setmask) -{ - u16 PhyRegValue; - - - PhyRegValue = rtl8168_mdio_read(tp, addr); - PhyRegValue &= ~clearmask; - PhyRegValue |= setmask; - rtl8168_mdio_write(tp, addr, PhyRegValue); -} - -void rtl8168_clear_eth_phy_bit(struct rtl8168_private *tp, u8 addr, u16 mask) -{ - ClearAndSetEthPhyBit(tp, - addr, - mask, - 0 - ); -} - -void rtl8168_set_eth_phy_bit(struct rtl8168_private *tp, u8 addr, u16 mask) -{ - ClearAndSetEthPhyBit(tp, - addr, - 0, - mask - ); -} - -void rtl8168_mac_ocp_write(struct rtl8168_private *tp, u16 reg_addr, u16 value) -{ - u32 data32; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(reg_addr % 2); -#endif - - data32 = reg_addr/2; - data32 <<= OCPR_Addr_Reg_shift; - data32 += value; - data32 |= OCPR_Write; - - RTL_W32(tp, MACOCP, data32); -} - -u16 rtl8168_mac_ocp_read(struct rtl8168_private *tp, u16 reg_addr) -{ - u32 data32; - u16 data16 = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(reg_addr % 2); -#endif - - data32 = reg_addr/2; - data32 <<= OCPR_Addr_Reg_shift; - - RTL_W32(tp, MACOCP, data32); - data16 = (u16)RTL_R32(tp, MACOCP); - - return data16; -} - -#ifdef ENABLE_USE_FIRMWARE_FILE -static void mac_mcu_write(struct rtl8168_private *tp, u16 reg, u16 value) -{ - if (reg == 0x1f) { - tp->ocp_base = value << 4; - return; - } - - rtl8168_mac_ocp_write(tp, tp->ocp_base + reg, value); -} - -static u32 mac_mcu_read(struct rtl8168_private *tp, u16 reg) -{ - return rtl8168_mac_ocp_read(tp, tp->ocp_base + reg); -} -#endif - -static void -rtl8168_clear_and_set_mcu_ocp_bit( - struct rtl8168_private *tp, - u16 addr, - u16 clearmask, - u16 setmask -) -{ - u16 RegValue; - - RegValue = rtl8168_mac_ocp_read(tp, addr); - RegValue &= ~clearmask; - RegValue |= setmask; - rtl8168_mac_ocp_write(tp, addr, RegValue); -} - -/* -static void -rtl8168_clear_mcu_ocp_bit( - struct rtl8168_private *tp, - u16 addr, - u16 mask -) -{ - rtl8168_clear_and_set_mcu_ocp_bit(tp, - addr, - mask, - 0 - ); -} -*/ - -static void -rtl8168_set_mcu_ocp_bit( - struct rtl8168_private *tp, - u16 addr, - u16 mask -) -{ - rtl8168_clear_and_set_mcu_ocp_bit(tp, - addr, - 0, - mask - ); -} - -static u32 real_ocp_read(struct rtl8168_private *tp, u16 addr, u8 len) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, value2 = 0, mask; - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % 4; - addr = addr & ~0x3; - - RTL_W32(tp, OCPAR, (0x0F<<12) | (addr&0xFFF)); - - for (i = 0; i < 20; i++) { - udelay(100); - if (RTL_R32(tp, OCPAR) & OCPAR_Flag) - break; - } - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = RTL_R32(tp, OCPDR) & mask; - value2 |= (value1 >> val_shift * 8) << shift * 8; - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return value2; -} - -u32 rtl8168_ocp_read_with_oob_base_address(struct rtl8168_private *tp, u16 addr, u8 len, const u32 base_address) -{ - return rtl8168_eri_read_with_oob_base_address(tp, addr, len, ERIAR_OOB, base_address); -} - -u32 rtl8168_ocp_read(struct rtl8168_private *tp, u16 addr, u8 len) -{ - u32 value = 0; - - if (HW_DASH_SUPPORT_TYPE_2(tp)) - value = rtl8168_ocp_read_with_oob_base_address(tp, addr, len, NO_BASE_ADDRESS); - else if (HW_DASH_SUPPORT_TYPE_3(tp)) - value = rtl8168_ocp_read_with_oob_base_address(tp, addr, len, RTL8168FP_OOBMAC_BASE); - else - value = real_ocp_read(tp, addr, len); - - return value; -} - -static int real_ocp_write(struct rtl8168_private *tp, u16 addr, u8 len, u32 value) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, mask; - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % 4; - addr = addr & ~0x3; - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = rtl8168_ocp_read(tp, addr, 4) & ~mask; - value1 |= ((value << val_shift * 8) >> shift * 8); - - RTL_W32(tp, OCPDR, value1); - RTL_W32(tp, OCPAR, OCPAR_Flag | (0x0F<<12) | (addr&0xFFF)); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed ERI write */ - if (!(RTL_R32(tp, OCPAR) & OCPAR_Flag)) - break; - } - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return 0; -} - -u32 rtl8168_ocp_write_with_oob_base_address(struct rtl8168_private *tp, u16 addr, u8 len, u32 value, const u32 base_address) -{ - return rtl8168_eri_write_with_oob_base_address(tp, addr, len, value, ERIAR_OOB, base_address); -} - -void rtl8168_ocp_write(struct rtl8168_private *tp, u16 addr, u8 len, u32 value) -{ - if (HW_DASH_SUPPORT_TYPE_2(tp)) - rtl8168_ocp_write_with_oob_base_address(tp, addr, len, value, NO_BASE_ADDRESS); - else if (HW_DASH_SUPPORT_TYPE_3(tp)) - rtl8168_ocp_write_with_oob_base_address(tp, addr, len, value, RTL8168FP_OOBMAC_BASE); - else - real_ocp_write(tp, addr, len, value); -} - -void rtl8168_oob_mutex_lock(struct rtl8168_private *tp) -{ - u8 reg_16, reg_a0; - u32 wait_cnt_0, wait_Cnt_1; - u16 ocp_reg_mutex_ib; - u16 ocp_reg_mutex_oob; - u16 ocp_reg_mutex_prio; - - if (!tp->DASH) return; - - switch (tp->mcfg) { - case CFG_METHOD_11: - case CFG_METHOD_12: - ocp_reg_mutex_oob = 0x16; - ocp_reg_mutex_ib = 0x17; - ocp_reg_mutex_prio = 0x9C; - break; - case CFG_METHOD_13: - ocp_reg_mutex_oob = 0x06; - ocp_reg_mutex_ib = 0x07; - ocp_reg_mutex_prio = 0x9C; - break; - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - default: - ocp_reg_mutex_oob = 0x110; - ocp_reg_mutex_ib = 0x114; - ocp_reg_mutex_prio = 0x11C; - break; - } - - rtl8168_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); - reg_16 = rtl8168_ocp_read(tp, ocp_reg_mutex_oob, 1); - wait_cnt_0 = 0; - while(reg_16) { - reg_a0 = rtl8168_ocp_read(tp, ocp_reg_mutex_prio, 1); - if (reg_a0) { - rtl8168_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); - reg_a0 = rtl8168_ocp_read(tp, ocp_reg_mutex_prio, 1); - wait_Cnt_1 = 0; - while(reg_a0) { - reg_a0 = rtl8168_ocp_read(tp, ocp_reg_mutex_prio, 1); - - wait_Cnt_1++; - - if (wait_Cnt_1 > 2000) - break; - }; - rtl8168_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); - - } - reg_16 = rtl8168_ocp_read(tp, ocp_reg_mutex_oob, 1); - - wait_cnt_0++; - - if (wait_cnt_0 > 2000) - break; - }; -} - -void rtl8168_oob_mutex_unlock(struct rtl8168_private *tp) -{ - u16 ocp_reg_mutex_ib; - u16 ocp_reg_mutex_oob; - u16 ocp_reg_mutex_prio; - - if (!tp->DASH) return; - - switch (tp->mcfg) { - case CFG_METHOD_11: - case CFG_METHOD_12: - ocp_reg_mutex_oob = 0x16; - ocp_reg_mutex_ib = 0x17; - ocp_reg_mutex_prio = 0x9C; - break; - case CFG_METHOD_13: - ocp_reg_mutex_oob = 0x06; - ocp_reg_mutex_ib = 0x07; - ocp_reg_mutex_prio = 0x9C; - break; - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - default: - ocp_reg_mutex_oob = 0x110; - ocp_reg_mutex_ib = 0x114; - ocp_reg_mutex_prio = 0x11C; - break; - } - - rtl8168_ocp_write(tp, ocp_reg_mutex_prio, 1, BIT_0); - rtl8168_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); -} - -void rtl8168_oob_notify(struct rtl8168_private *tp, u8 cmd) -{ - rtl8168_eri_write(tp, 0xE8, 1, cmd, ERIAR_ExGMAC); - - rtl8168_ocp_write(tp, 0x30, 1, 0x01); -} - -static int rtl8168_check_dash(struct rtl8168_private *tp) -{ - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - if (rtl8168_ocp_read(tp, 0x128, 1) & BIT_0) - return 1; - else - return 0; - } else { - u32 reg; - - if (tp->mcfg == CFG_METHOD_13) - reg = 0xb8; - else - reg = 0x10; - - if (rtl8168_ocp_read(tp, reg, 2) & 0x00008000) - return 1; - else - return 0; - } -} - -void rtl8168_dash2_disable_tx(struct rtl8168_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - u16 WaitCnt; - u8 TmpUchar; - - //Disable oob Tx - RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) & ~( BIT_0 )); - WaitCnt = 0; - - //wait oob tx disable - do { - TmpUchar = RTL_CMAC_R8(tp, CMAC_IBISR0); - - if ( TmpUchar & ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE ) { - break; - } - - udelay( 50 ); - WaitCnt++; - } while(WaitCnt < 2000); - - //Clear ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE - RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0) | ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE); - } -} - -void rtl8168_dash2_enable_tx(struct rtl8168_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) | BIT_0); - } -} - -void rtl8168_dash2_disable_rx(struct rtl8168_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) & ~( BIT_0 )); - } -} - -void rtl8168_dash2_enable_rx(struct rtl8168_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) | BIT_0); - } -} - -static void rtl8168_dash2_disable_txrx(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - rtl8168_dash2_disable_tx( tp ); - rtl8168_dash2_disable_rx( tp ); - } -} - -void rtl8168_ephy_write(struct rtl8168_private *tp, int RegAddr, int value) -{ - int i; - - RTL_W32(tp, EPHYAR, - EPHYAR_Write | - (RegAddr & EPHYAR_Reg_Mask) << EPHYAR_Reg_shift | - (value & EPHYAR_Data_Mask)); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed EPHY write */ - if (!(RTL_R32(tp, EPHYAR) & EPHYAR_Flag)) - break; - } - - udelay(20); -} - -u16 rtl8168_ephy_read(struct rtl8168_private *tp, int RegAddr) -{ - int i; - u16 value = 0xffff; - - RTL_W32(tp, EPHYAR, - EPHYAR_Read | (RegAddr & EPHYAR_Reg_Mask) << EPHYAR_Reg_shift); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed EPHY read */ - if (RTL_R32(tp, EPHYAR) & EPHYAR_Flag) { - value = (u16) (RTL_R32(tp, EPHYAR) & EPHYAR_Data_Mask); - break; - } - } - - udelay(20); - - return value; -} - -static void ClearAndSetPCIePhyBit(struct rtl8168_private *tp, u8 addr, u16 clearmask, u16 setmask) -{ - u16 EphyValue; - - EphyValue = rtl8168_ephy_read(tp, addr); - EphyValue &= ~clearmask; - EphyValue |= setmask; - rtl8168_ephy_write(tp, addr, EphyValue); -} - -static void ClearPCIePhyBit(struct rtl8168_private *tp, u8 addr, u16 mask) -{ - ClearAndSetPCIePhyBit( tp, - addr, - mask, - 0 - ); -} - -static void SetPCIePhyBit( struct rtl8168_private *tp, u8 addr, u16 mask) -{ - ClearAndSetPCIePhyBit( tp, - addr, - 0, - mask - ); -} - -static u32 -rtl8168_csi_other_fun_read(struct rtl8168_private *tp, - u8 multi_fun_sel_bit, - u32 addr) -{ - u32 cmd; - int i; - u32 value = 0; - - cmd = CSIAR_Read | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); - - if (tp->mcfg != CFG_METHOD_20 && tp->mcfg != CFG_METHOD_23 && - tp->mcfg != CFG_METHOD_26 && tp->mcfg != CFG_METHOD_27 && - tp->mcfg != CFG_METHOD_28 && tp->mcfg != CFG_METHOD_31 && - tp->mcfg != CFG_METHOD_32 && tp->mcfg != CFG_METHOD_33) { - multi_fun_sel_bit = 0; - } - - if ( multi_fun_sel_bit > 7 ) { - return 0xffffffff; - } - - cmd |= multi_fun_sel_bit << 16; - - RTL_W32(tp, CSIAR, cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed CSI read */ - if (RTL_R32(tp, CSIAR) & CSIAR_Flag) { - value = (u32)RTL_R32(tp, CSIDR); - break; - } - } - - udelay(20); - - return value; -} - -static void -rtl8168_csi_other_fun_write(struct rtl8168_private *tp, - u8 multi_fun_sel_bit, - u32 addr, - u32 value) -{ - u32 cmd; - int i; - - RTL_W32(tp, CSIDR, value); - cmd = CSIAR_Write | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); - if (tp->mcfg != CFG_METHOD_20 && tp->mcfg != CFG_METHOD_23 && - tp->mcfg != CFG_METHOD_26 && tp->mcfg != CFG_METHOD_27 && - tp->mcfg != CFG_METHOD_28 && tp->mcfg != CFG_METHOD_31 && - tp->mcfg != CFG_METHOD_32 && tp->mcfg != CFG_METHOD_33) { - multi_fun_sel_bit = 0; - } - - if ( multi_fun_sel_bit > 7 ) { - return; - } - - cmd |= multi_fun_sel_bit << 16; - - RTL_W32(tp, CSIAR, cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed CSI write */ - if (!(RTL_R32(tp, CSIAR) & CSIAR_Flag)) - break; - } - - udelay(20); -} - -static u32 -rtl8168_csi_read(struct rtl8168_private *tp, - u32 addr) -{ - u8 multi_fun_sel_bit; - - if (tp->mcfg == CFG_METHOD_20) - multi_fun_sel_bit = 2; - else if (tp->mcfg == CFG_METHOD_26 || tp->mcfg == CFG_METHOD_31 || - tp->mcfg == CFG_METHOD_32 || tp->mcfg == CFG_METHOD_33) - multi_fun_sel_bit = 1; - else - multi_fun_sel_bit = 0; - - return rtl8168_csi_other_fun_read(tp, multi_fun_sel_bit, addr); -} - -static void -rtl8168_csi_write(struct rtl8168_private *tp, - u32 addr, - u32 value) -{ - u8 multi_fun_sel_bit; - - if (tp->mcfg == CFG_METHOD_20) - multi_fun_sel_bit = 2; - else if (tp->mcfg == CFG_METHOD_26 || tp->mcfg == CFG_METHOD_31 || - tp->mcfg == CFG_METHOD_32 || tp->mcfg == CFG_METHOD_33) - multi_fun_sel_bit = 1; - else - multi_fun_sel_bit = 0; - - rtl8168_csi_other_fun_write(tp, multi_fun_sel_bit, addr, value); -} - -static u8 -rtl8168_csi_fun0_read_byte(struct rtl8168_private *tp, - u32 addr) -{ - u8 RetVal = 0; - - if (tp->mcfg == CFG_METHOD_20 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - u32 TmpUlong; - u16 RegAlignAddr; - u8 ShiftByte; - - RegAlignAddr = addr & ~(0x3); - ShiftByte = addr & (0x3); - TmpUlong = rtl8168_csi_other_fun_read(tp, 0, addr); - TmpUlong >>= (8*ShiftByte); - RetVal = (u8)TmpUlong; - } else { - struct pci_dev *pdev = tp->pci_dev; - - pci_read_config_byte(pdev, addr, &RetVal); - } - - udelay(20); - - return RetVal; -} - -static void -rtl8168_csi_fun0_write_byte(struct rtl8168_private *tp, - u32 addr, - u8 value) -{ - if (tp->mcfg == CFG_METHOD_20 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - u32 TmpUlong; - u16 RegAlignAddr; - u8 ShiftByte; - - RegAlignAddr = addr & ~(0x3); - ShiftByte = addr & (0x3); - TmpUlong = rtl8168_csi_other_fun_read(tp, 0, RegAlignAddr); - TmpUlong &= ~(0xFF << (8*ShiftByte)); - TmpUlong |= (value << (8*ShiftByte)); - rtl8168_csi_other_fun_write( tp, 0, RegAlignAddr, TmpUlong ); - } else { - struct pci_dev *pdev = tp->pci_dev; - - pci_write_config_byte(pdev, addr, value); - } - - udelay(20); -} - -static void -rtl8168_clear_and_set_other_fun_pci_bit(struct rtl8168_private *tp, - u8 multi_fun_sel_bit, - u32 addr, - u32 clearmask, - u32 setmask) -{ - u32 TmpUlong; - - TmpUlong = rtl8168_csi_other_fun_read(tp, multi_fun_sel_bit, addr); - TmpUlong &= ~clearmask; - TmpUlong |= setmask; - rtl8168_csi_other_fun_write(tp, multi_fun_sel_bit, addr, TmpUlong); -} - -static void -rtl8168_other_fun_dev_pci_setting(struct rtl8168_private *tp, - u32 addr, - u32 clearmask, - u32 setmask, - u8 multi_fun_sel_bit) -{ - u32 TmpUlong; - u8 i; - u8 FunBit; - - for (i = 0; i < 8; i++) { - FunBit = (1 << i); - if (FunBit & multi_fun_sel_bit) { - u8 set_other_fun = TRUE; - - switch(tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - //0: UMAC, 1: TCR1, 2: TCR2, 3: KCS, 4: EHCI(Control by EHCI Driver) - if (i < 5) { - TmpUlong = rtl8168_csi_other_fun_read(tp, i, 0x00); - if (TmpUlong == 0xFFFFFFFF) - set_other_fun = TRUE; - else - set_other_fun = FALSE; - } - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - //0: BMC, 1: NIC, 2: TCR, 3: VGA/PCIE_TO_USB, 4: EHCI, 5: WIFI, 6: WIFI, 7: KCS - if (i == 5 || i == 6) { - if (tp->DASH) { - TmpUlong = rtl8168_ocp_read(tp, 0x184, 4); - if (TmpUlong & BIT_26) - set_other_fun = FALSE; - else - set_other_fun = TRUE; - } - } else { //function 0/1/2/3/4/7 - TmpUlong = rtl8168_csi_other_fun_read(tp, i, 0x00); - if (TmpUlong == 0xFFFFFFFF) - set_other_fun = TRUE; - else - set_other_fun = FALSE; - } - break; - default: - return; - } - - if (set_other_fun) - rtl8168_clear_and_set_other_fun_pci_bit(tp, i, addr, clearmask, setmask); - } - } -} - -static void -rtl8168_set_dash_other_fun_dev_state_change(struct rtl8168_private *tp, - u8 dev_state, - u8 multi_fun_sel_bit) -{ - u32 clearmask; - u32 setmask; - - if (dev_state == 0) { - // - // goto D0 - // - clearmask = (BIT_0 | BIT_1); - setmask = 0; - - rtl8168_other_fun_dev_pci_setting(tp, 0x44, clearmask, setmask, multi_fun_sel_bit); - } else { - // - // goto D3 - // - clearmask = 0; - setmask = (BIT_0 | BIT_1); - - rtl8168_other_fun_dev_pci_setting(tp, 0x44, clearmask, setmask, multi_fun_sel_bit); - } -} - -static void -rtl8168_set_dash_other_fun_dev_aspm_clkreq(struct rtl8168_private *tp, - u8 aspm_val, - u8 clkreq_en, - u8 multi_fun_sel_bit) -{ - u32 clearmask; - u32 setmask; - - aspm_val &= (BIT_0 | BIT_1); - clearmask = (BIT_0 | BIT_1 | BIT_8); - setmask = aspm_val; - if (clkreq_en) - setmask |= BIT_8; - - rtl8168_other_fun_dev_pci_setting(tp, 0x80, clearmask, setmask, multi_fun_sel_bit); -} - -/* -static void -rtl8168_set_dash_other_fun_dev_pci_cmd_register(struct rtl8168_private *tp, - u8 pci_cmd_reg, - u8 multi_fun_sel_bit) -{ - u32 clearmask; - u32 setmask; - - pci_cmd_reg &= (BIT_0 | BIT_1 | BIT_2); - - clearmask = (BIT_0 | BIT_1 | BIT_2); - setmask = pci_cmd_reg; - - rtl8168_other_fun_dev_pci_setting(tp, 0x04, clearmask, setmask, multi_fun_sel_bit); -} -*/ - -u32 rtl8168_eri_read_with_oob_base_address(struct rtl8168_private *tp, int addr, int len, int type, const u32 base_address) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, value2 = 0, mask; - u32 eri_cmd; - const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % ERIAR_Addr_Align; - addr = addr & ~0x3; - - eri_cmd = ERIAR_Read | - transformed_base_address | - type << ERIAR_Type_shift | - ERIAR_ByteEn << ERIAR_ByteEn_shift | - (addr & 0x0FFF); - if (addr & 0xF000) { - u32 tmp; - - tmp = addr & 0xF000; - tmp >>= 12; - eri_cmd |= (tmp << 20) & 0x00F00000; - } - - RTL_W32(tp, ERIAR, eri_cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed ERI read */ - if (RTL_R32(tp, ERIAR) & ERIAR_Flag) - break; - } - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = RTL_R32(tp, ERIDR) & mask; - value2 |= (value1 >> val_shift * 8) << shift * 8; - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return value2; -} - -u32 rtl8168_eri_read(struct rtl8168_private *tp, int addr, int len, int type) -{ - return rtl8168_eri_read_with_oob_base_address(tp, addr, len, type, 0); -} - -int rtl8168_eri_write_with_oob_base_address(struct rtl8168_private *tp, int addr, int len, u32 value, int type, const u32 base_address) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, mask; - u32 eri_cmd; - const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % ERIAR_Addr_Align; - addr = addr & ~0x3; - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = rtl8168_eri_read_with_oob_base_address(tp, addr, 4, type, base_address) & ~mask; - value1 |= ((value << val_shift * 8) >> shift * 8); - - RTL_W32(tp, ERIDR, value1); - - eri_cmd = ERIAR_Write | - transformed_base_address | - type << ERIAR_Type_shift | - ERIAR_ByteEn << ERIAR_ByteEn_shift | - (addr & 0x0FFF); - if (addr & 0xF000) { - u32 tmp; - - tmp = addr & 0xF000; - tmp >>= 12; - eri_cmd |= (tmp << 20) & 0x00F00000; - } - - RTL_W32(tp, ERIAR, eri_cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed ERI write */ - if (!(RTL_R32(tp, ERIAR) & ERIAR_Flag)) - break; - } - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return 0; -} - -int rtl8168_eri_write(struct rtl8168_private *tp, int addr, int len, u32 value, int type) -{ - return rtl8168_eri_write_with_oob_base_address(tp, addr, len, value, type, NO_BASE_ADDRESS); -} - -static void -rtl8168_enable_rxdvgate(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_3); - mdelay(2); - break; - } -} - -static void -rtl8168_disable_rxdvgate(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_3); - mdelay(2); - break; - } -} - -static u8 -rtl8168_is_gpio_low(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 gpio_low = FALSE; - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 1: - case 2: - if (!(rtl8168_mac_ocp_read(tp, 0xDC04) & BIT_9)) - gpio_low = TRUE; - break; - case 3: - if (!(rtl8168_mac_ocp_read(tp, 0xDC04) & BIT_13)) - gpio_low = TRUE; - break; - } - - if (gpio_low) - dprintk("gpio is low.\n"); - - return gpio_low; -} - -static u8 -rtl8168_is_phy_disable_mode_enabled(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 phy_disable_mode_enabled = FALSE; - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 1: - if (rtl8168_mac_ocp_read(tp, 0xDC20) & BIT_1) - phy_disable_mode_enabled = TRUE; - break; - case 2: - case 3: - if (RTL_R8(tp, 0xF2) & BIT_5) - phy_disable_mode_enabled = TRUE; - break; - } - - if (phy_disable_mode_enabled) - dprintk("phy disable mode enabled.\n"); - - return phy_disable_mode_enabled; -} - -static u8 -rtl8168_is_in_phy_disable_mode(struct net_device *dev) -{ - u8 in_phy_disable_mode = FALSE; - - if (rtl8168_is_phy_disable_mode_enabled(dev) && rtl8168_is_gpio_low(dev)) - in_phy_disable_mode = TRUE; - - if (in_phy_disable_mode) - dprintk("Hardware is in phy disable mode.\n"); - - return in_phy_disable_mode; -} - -void -rtl8168_wait_txrx_fifo_empty(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int i; - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - for (i = 0; i < 10; i++) { - udelay(100); - if (RTL_R32(tp, TxConfig) & BIT_11) - break; - } - - for (i = 0; i < 10; i++) { - udelay(100); - if ((RTL_R8(tp, MCUCmd_reg) & (Txfifo_empty | Rxfifo_empty)) == (Txfifo_empty | Rxfifo_empty)) - break; - } - - mdelay(1); - break; - } -} - -static void rtl8168_driver_start(struct rtl8168_private *tp) -{ - //change other device state to D0. - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - rtl8168_set_dash_other_fun_dev_aspm_clkreq(tp, 3, 1, 0x1E); - rtl8168_set_dash_other_fun_dev_state_change(tp, 3, 0x1E); - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_set_dash_other_fun_dev_aspm_clkreq(tp, 3, 1, 0xFC); - rtl8168_set_dash_other_fun_dev_state_change(tp, 3, 0xFC); - break; - } - - if (!tp->DASH) - return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - int timeout; - u32 tmp_value; - - rtl8168_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_START); - tmp_value = rtl8168_ocp_read(tp, 0x30, 1); - tmp_value |= BIT_0; - rtl8168_ocp_write(tp, 0x30, 1, tmp_value); - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if (rtl8168_ocp_read(tp, 0x124, 1) & BIT_0) - break; - } - } else { - int timeout; - u32 reg; - - if (tp->mcfg == CFG_METHOD_13) { - RTL_W8(tp, TwiCmdReg, RTL_R8(tp, TwiCmdReg) | ( BIT_7 )); - } - - rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START); - - if (tp->mcfg == CFG_METHOD_13) - reg = 0xB8; - else - reg = 0x10; - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if (rtl8168_ocp_read(tp, reg, 2) & BIT_11) - break; - } - } -} - -static void rtl8168_driver_stop(struct rtl8168_private *tp) -{ - if (!tp->DASH) - goto update_device_state; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - struct net_device *dev = tp->dev; - int timeout; - u32 tmp_value; - - rtl8168_dash2_disable_txrx(dev); - - rtl8168_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_STOP); - tmp_value = rtl8168_ocp_read(tp, 0x30, 1); - tmp_value |= BIT_0; - rtl8168_ocp_write(tp, 0x30, 1, tmp_value); - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if (!(rtl8168_ocp_read(tp, 0x124, 1) & BIT_0)) - break; - } - } else { - int timeout; - u32 reg; - - rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP); - - if (tp->mcfg == CFG_METHOD_13) - reg = 0xB8; - else - reg = 0x10; - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if ((rtl8168_ocp_read(tp, reg, 2) & BIT_11) == 0) - break; - } - - if (tp->mcfg == CFG_METHOD_13) { - RTL_W8(tp, TwiCmdReg, RTL_R8(tp, TwiCmdReg) & ~( BIT_7 )); - } - } - -update_device_state: - //change other device state to D3. - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - rtl8168_set_dash_other_fun_dev_state_change(tp, 3, 0x0E); - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_set_dash_other_fun_dev_state_change(tp, 3, 0xFD); - break; - } -} - -#ifdef ENABLE_DASH_SUPPORT - -inline void -rtl8168_enable_dash2_interrupt(struct rtl8168_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBIMR0, ( ISRIMR_DASH_TYPE2_ROK | ISRIMR_DASH_TYPE2_TOK | ISRIMR_DASH_TYPE2_TDU | ISRIMR_DASH_TYPE2_RDU | ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE )); - } -} - -static inline void -rtl8168_disable_dash2_interrupt(struct rtl8168_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBIMR0, 0); - } -} -#endif - -static inline void -rtl8168_enable_hw_interrupt(struct rtl8168_private *tp) -{ - RTL_W16(tp, IntrMask, tp->intr_mask); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8168_enable_dash2_interrupt(tp); -#endif -} - -static inline void -rtl8168_disable_hw_interrupt(struct rtl8168_private *tp) -{ - RTL_W16(tp, IntrMask, 0x0000); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8168_disable_dash2_interrupt(tp); -#endif -} - - -static inline void -rtl8168_switch_to_hw_interrupt(struct rtl8168_private *tp) -{ - RTL_W32(tp, TimeInt0, 0x0000); - - rtl8168_enable_hw_interrupt(tp); -} - -static inline void -rtl8168_switch_to_timer_interrupt(struct rtl8168_private *tp) -{ - if (tp->use_timer_interrrupt) { - RTL_W32(tp, TimeInt0, timer_count); - RTL_W32(tp, TCTR, timer_count); - RTL_W16(tp, IntrMask, tp->timer_intr_mask); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8168_enable_dash2_interrupt(tp); -#endif - } else { - rtl8168_switch_to_hw_interrupt(tp); - } -} - -static void -rtl8168_irq_mask_and_ack(struct rtl8168_private *tp) -{ - rtl8168_disable_hw_interrupt(tp); -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - if (tp->dash_printer_enabled) { - RTL_W16(tp, IntrStatus, RTL_R16(tp, IntrStatus) & - ~(ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); - } else { - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0)); - } - } - } else { - RTL_W16(tp, IntrStatus, RTL_R16(tp, IntrStatus)); - } -#else - RTL_W16(tp, IntrStatus, RTL_R16(tp, IntrStatus)); -#endif -} - -static void -rtl8168_nic_reset(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int i; - - RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); - - rtl8168_enable_rxdvgate(dev); - - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - mdelay(10); - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - case CFG_METHOD_8: - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_14: - case CFG_METHOD_15: - RTL_W8(tp, ChipCmd, StopReq | CmdRxEnb | CmdTxEnb); - udelay(100); - break; - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - for (i = 0; i < 2000; i++) { - if (!(RTL_R8(tp, TxPoll) & NPQ)) break; - udelay(100); - } - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - mdelay(2); - break; - default: - mdelay(10); - break; - } - - rtl8168_wait_txrx_fifo_empty(dev); - - /* Soft reset the chip. */ - RTL_W8(tp, ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 100; i > 0; i--) { - udelay(100); - if ((RTL_R8(tp, ChipCmd) & CmdReset) == 0) - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_11: - rtl8168_oob_mutex_lock(tp); - rtl8168_ocp_write(tp, 0x10, 2, rtl8168_ocp_read(tp, 0x010, 2)&~0x00004000); - rtl8168_oob_mutex_unlock(tp); - - rtl8168_oob_notify(tp, OOB_CMD_RESET); - - for (i = 0; i < 10; i++) { - mdelay(10); - if (rtl8168_ocp_read(tp, 0x010, 2)&0x00004000) - break; - } - - for (i = 0; i < 5; i++) { - if ( rtl8168_ocp_read(tp, 0x034, 1) == 0) - break; - } - break; - } -} - -static void -rtl8168_hw_clear_timer_int(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - RTL_W32(tp, TimeInt0, 0x0000); - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - case CFG_METHOD_8: - RTL_W32(tp, TimeInt1, 0x0000); - break; - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W32(tp, TimeInt1, 0x0000); - RTL_W32(tp, TimeInt2, 0x0000); - RTL_W32(tp, TimeInt3, 0x0000); - break; - } -} - -static void -rtl8168_hw_reset(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - /* Disable interrupts */ - rtl8168_irq_mask_and_ack(tp); - - rtl8168_hw_clear_timer_int(dev); - - rtl8168_nic_reset(dev); -} - -static void rtl8168_mac_loopback_test(struct rtl8168_private *tp) -{ - struct pci_dev *pdev = tp->pci_dev; - struct net_device *dev = tp->dev; - struct sk_buff *skb, *rx_skb; - dma_addr_t mapping; - struct TxDesc *txd; - struct RxDesc *rxd; - void *tmpAddr; - u32 len, rx_len, rx_cmd = 0; - u16 type; - u8 pattern; - int i; - - if (tp->DASH) - return; - - pattern = 0x5A; - len = 60; - type = htons(ETH_P_IP); - txd = tp->TxDescArray; - rxd = tp->RxDescArray; - rx_skb = tp->Rx_skbuff[0]; - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) & ~0x00060000) | 0x00020000); - - do { - skb = dev_alloc_skb(len + RTK_RX_ALIGN); - if (unlikely(!skb)) - dev_printk(KERN_NOTICE, tp_to_dev(tp), "-ENOMEM;\n"); - } while (unlikely(skb == NULL)); - skb_reserve(skb, RTK_RX_ALIGN); - - memcpy(skb_put(skb, dev->addr_len), dev->dev_addr, dev->addr_len); - memcpy(skb_put(skb, dev->addr_len), dev->dev_addr, dev->addr_len); - memcpy(skb_put(skb, sizeof(type)), &type, sizeof(type)); - tmpAddr = skb_put(skb, len - 14); - - mapping = dma_map_single(tp_to_dev(tp), skb->data, len, DMA_TO_DEVICE); - dma_sync_single_for_cpu(tp_to_dev(tp), le64_to_cpu(mapping), - len, DMA_TO_DEVICE); - txd->addr = cpu_to_le64(mapping); - txd->opts2 = 0; - while (1) { - memset(tmpAddr, pattern++, len - 14); - pci_dma_sync_single_for_device(tp->pci_dev, - le64_to_cpu(mapping), - len, DMA_TO_DEVICE); - txd->opts1 = cpu_to_le32(DescOwn | FirstFrag | LastFrag | len); - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | AcceptMyPhys); - - smp_wmb(); - RTL_W8(tp, TxPoll, NPQ); /* set polling bit */ - - for (i = 0; i < 50; i++) { - udelay(200); - rx_cmd = le32_to_cpu(rxd->opts1); - if ((rx_cmd & DescOwn) == 0) - break; - } - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(AcceptErr | AcceptRunt | AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys)); - - rx_len = rx_cmd & 0x3FFF; - rx_len -= 4; - rxd->opts1 = cpu_to_le32(DescOwn | tp->rx_buf_sz); - - dma_sync_single_for_cpu(tp_to_dev(tp), le64_to_cpu(mapping), len, DMA_TO_DEVICE); - - if (rx_len == len) { - dma_sync_single_for_cpu(tp_to_dev(tp), le64_to_cpu(rxd->addr), tp->rx_buf_sz, DMA_FROM_DEVICE); - i = memcmp(skb->data, rx_skb->data, rx_len); - pci_dma_sync_single_for_device(tp->pci_dev, le64_to_cpu(rxd->addr), tp->rx_buf_sz, DMA_FROM_DEVICE); - if (i == 0) { -// dev_printk(KERN_INFO, tp_to_dev(tp), "loopback test finished\n",rx_len,len); - break; - } - } - - rtl8168_hw_reset(dev); - rtl8168_disable_rxdvgate(dev); - RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb); - } - tp->dirty_tx++; - tp->dirty_rx++; - tp->cur_tx++; - tp->cur_rx++; - dma_unmap_single(&pdev->dev, le64_to_cpu(mapping), - len, DMA_TO_DEVICE); - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) & ~0x00060000); - dev_kfree_skb_any(skb); - RTL_W16(tp, IntrStatus, 0xFFBF); -} - -static unsigned int -rtl8168_xmii_reset_pending(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int retval; - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - retval = rtl8168_mdio_read(tp, MII_BMCR) & BMCR_RESET; - - return retval; -} - -static unsigned int -rtl8168_xmii_link_ok(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int retval; - - retval = (RTL_R8(tp, PHYstatus) & LinkStatus) ? 1 : 0; - - return retval; -} - -static int -rtl8168_wait_phy_reset_complete(struct rtl8168_private *tp) -{ - int i, val; - - for (i = 0; i < 2500; i++) { - val = rtl8168_mdio_read(tp, MII_BMCR) & BMCR_RESET; - if (!val) - return 0; - - mdelay(1); - } - - return -1; -} - -static void -rtl8168_xmii_reset_enable(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (rtl8168_is_in_phy_disable_mode(dev)) - return; - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, MII_ADVERTISE, rtl8168_mdio_read(tp, MII_ADVERTISE) & - ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL)); - rtl8168_mdio_write(tp, MII_CTRL1000, rtl8168_mdio_read(tp, MII_CTRL1000) & - ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL)); - rtl8168_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); - - if (rtl8168_wait_phy_reset_complete(tp) == 0) return; - - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void -rtl8168dp_10mbps_gphy_para(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 status = RTL_R8(tp, PHYstatus); - - if ((status & LinkStatus) && (status & _10bps)) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x10, 0x04EE); - } else { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x10, 0x01EE); - } -} - -void rtl8168_init_ring_indexes(struct rtl8168_private *tp) -{ - tp->dirty_tx = 0; - tp->dirty_rx = 0; - tp->cur_tx = 0; - tp->cur_rx = 0; -} - -static void -rtl8168_issue_offset_99_event(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_27: - case CFG_METHOD_28: - if (tp->mcfg == CFG_METHOD_24 || tp->mcfg == CFG_METHOD_25 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28) { - rtl8168_eri_write(tp, 0x3FC, 4, 0x00000000, ERIAR_ExGMAC); - } else { - rtl8168_eri_write(tp, 0x3FC, 4, 0x083C083C, ERIAR_ExGMAC); - } - csi_tmp = rtl8168_eri_read(tp, 0x3F8, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0x3F8, 1, csi_tmp, ERIAR_ExGMAC); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x1EA, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0x1EA, 1, csi_tmp, ERIAR_ExGMAC); - break; - } -} - -static void -rtl8168_enable_cfg9346_write(struct rtl8168_private *tp) -{ - RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) | Cfg9346_Unlock); -} - -static void -rtl8168_disable_cfg9346_write(struct rtl8168_private *tp) -{ - RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) & ~Cfg9346_Unlock); -} - -static void -rtl8168_enable_exit_l1_mask(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp |= (BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12); - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - break; - case CFG_METHOD_20: - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp |= (BIT_10 | BIT_11); - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - break; - case CFG_METHOD_21 ... CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp |= (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12); - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - break; - } -} - -static void -rtl8168_disable_exit_l1_mask(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12); - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - break; - case CFG_METHOD_20: - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_10 | BIT_11); - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - break; - case CFG_METHOD_21 ... CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12); - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - break; - } -} - -static void -rtl8168_hw_aspm_clkreq_enable(struct rtl8168_private *tp, bool enable) -{ - if (!tp->HwSuppAspmClkIntrLock) return; - - if (enable && aspm) { - RTL_W8(tp, Config5, RTL_R8(tp, Config5) | ASPM_en); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) | ClkReqEn); - } else { - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en); - } - - udelay(10); -} - -#ifdef ENABLE_DASH_SUPPORT -static void -NICChkTypeEnableDashInterrupt(struct rtl8168_private *tp) -{ - if (tp->DASH) { - // - // even disconnected, enable 3 dash interrupt mask bits for in-band/out-band communication - // - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - rtl8168_enable_dash2_interrupt(tp); - RTL_W16(tp, IntrMask, (ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); - } else { - RTL_W16(tp, IntrMask, (ISRIMR_DP_DASH_OK | ISRIMR_DP_HOST_OK | ISRIMR_DP_REQSYS_OK)); - } - } -} -#endif - -static void -rtl8168_check_link_status(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int link_status_on; - -#ifdef ENABLE_FIBER_SUPPORT - rtl8168_check_fiber_link_status(dev); -#endif //ENABLE_FIBER_SUPPORT - - link_status_on = tp->link_ok(dev); - - if (tp->mcfg == CFG_METHOD_11) - rtl8168dp_10mbps_gphy_para(dev); - - if (netif_carrier_ok(dev) != link_status_on) { - if (link_status_on) { - rtl8168_hw_config(dev); - - if (tp->mcfg == CFG_METHOD_18 || tp->mcfg == CFG_METHOD_19 || tp->mcfg == CFG_METHOD_20) { - if (RTL_R8(tp, PHYstatus) & _1000bpsF) { - rtl8168_eri_write(tp, 0x1bc, 4, 0x00000011, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x0000001f, ERIAR_ExGMAC); - } else if (RTL_R8(tp, PHYstatus) & _100bps) { - rtl8168_eri_write(tp, 0x1bc, 4, 0x0000001f, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x0000001f, ERIAR_ExGMAC); - } else { - rtl8168_eri_write(tp, 0x1bc, 4, 0x0000001f, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x0000002d, ERIAR_ExGMAC); - } - } else if ((tp->mcfg == CFG_METHOD_16 || tp->mcfg == CFG_METHOD_17) && netif_running(dev)) { - if (tp->mcfg == CFG_METHOD_16 && (RTL_R8(tp, PHYstatus) & _10bps)) { - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | AcceptAllPhys); - } else if (tp->mcfg == CFG_METHOD_17) { - if (RTL_R8(tp, PHYstatus) & _1000bpsF) { - rtl8168_eri_write(tp, 0x1bc, 4, 0x00000011, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x00000005, ERIAR_ExGMAC); - } else if (RTL_R8(tp, PHYstatus) & _100bps) { - rtl8168_eri_write(tp, 0x1bc, 4, 0x0000001f, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x00000005, ERIAR_ExGMAC); - } else { - rtl8168_eri_write(tp, 0x1bc, 4, 0x0000001f, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x0000003f, ERIAR_ExGMAC); - } - } - } else if ((tp->mcfg == CFG_METHOD_14 || tp->mcfg == CFG_METHOD_15) && tp->eee_enabled == 1) { - /*Full -Duplex mode*/ - if (RTL_R8(tp, PHYstatus)&FullDup) { - rtl8168_mdio_write(tp, 0x1F, 0x0006); - rtl8168_mdio_write(tp, 0x00, 0x5a30); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - if (RTL_R8(tp, PHYstatus) & (_10bps | _100bps)) - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) & ~BIT_19) | BIT_25); - - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0006); - rtl8168_mdio_write(tp, 0x00, 0x5a00); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - if (RTL_R8(tp, PHYstatus) & (_10bps | _100bps)) - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) & ~BIT_19) | (InterFrameGap << TxInterFrameGapShift)); - } - } else if ((tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_23 || tp->mcfg == CFG_METHOD_24 || - tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) && netif_running(dev)) { - if (RTL_R8(tp, PHYstatus)&FullDup) - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | (BIT_24 | BIT_25)) & ~BIT_19); - else - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | BIT_25) & ~(BIT_19 | BIT_24)); - } - - if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - /*half mode*/ - if (!(RTL_R8(tp, PHYstatus)&FullDup)) { - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, MII_ADVERTISE, rtl8168_mdio_read(tp, MII_ADVERTISE)&~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM)); - } - } - - if ((tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) && (RTL_R8(tp, PHYstatus) & _10bps)) { - u32 csi_tmp; - - csi_tmp = rtl8168_eri_read(tp, 0x1D0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_1; - rtl8168_eri_write(tp, 0x1D0, 1, csi_tmp, ERIAR_ExGMAC); - } - - rtl8168_hw_start(dev); - - netif_carrier_on(dev); - - netif_wake_queue(dev); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - tp->phy_reg_aner = rtl8168_mdio_read(tp, MII_EXPANSION); - tp->phy_reg_anlpar = rtl8168_mdio_read(tp, MII_LPA); - tp->phy_reg_gbsr = rtl8168_mdio_read(tp, MII_STAT1000); - - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - - tp->phy_reg_aner = 0; - tp->phy_reg_anlpar = 0; - tp->phy_reg_gbsr = 0; - - netif_stop_queue(dev); - - netif_carrier_off(dev); - - rtl8168_hw_reset(dev); - - rtl8168_tx_clear(tp); - - rtl8168_rx_clear(tp); - - rtl8168_init_ring(dev); - - if (dynamic_aspm) { - rtl8168_enable_cfg9346_write(tp); - rtl8168_hw_aspm_clkreq_enable(tp, true); - rtl8168_disable_cfg9346_write(tp); - } - - rtl8168_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_27: - case CFG_METHOD_28: - if (tp->org_pci_offset_99 & BIT_2) - tp->issue_offset_99_event = TRUE; - break; - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - NICChkTypeEnableDashInterrupt(tp); - } -#endif - } - } - - if (!link_status_on) { - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_27: - case CFG_METHOD_28: - if (tp->issue_offset_99_event) { - if (!(RTL_R8(tp, PHYstatus) & PowerSaveStatus)) { - tp->issue_offset_99_event = FALSE; - rtl8168_issue_offset_99_event(tp); - } - } - break; - } - } else { - if (dynamic_aspm) { - bool enable_hw_aspm_clkreq = true; - if (tp->dynamic_aspm_packet_count > dynamic_aspm_packet_threshold) - enable_hw_aspm_clkreq = false; - - rtl8168_enable_cfg9346_write(tp); - rtl8168_hw_aspm_clkreq_enable(tp, enable_hw_aspm_clkreq); - rtl8168_disable_cfg9346_write(tp); - } - tp->dynamic_aspm_packet_count = 0; - } -} - -static void -rtl8168_link_option(u8 *aut, - u32 *spd, - u8 *dup, - u32 *adv) -{ - if ((*spd != SPEED_1000) && (*spd != SPEED_100) && (*spd != SPEED_10)) - *spd = SPEED_1000; - - if ((*dup != DUPLEX_FULL) && (*dup != DUPLEX_HALF)) - *dup = DUPLEX_FULL; - - if ((*aut != AUTONEG_ENABLE) && (*aut != AUTONEG_DISABLE)) - *aut = AUTONEG_ENABLE; - - *adv &= (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full); - if (*adv == 0) - *adv = (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full); -} - -static void -rtl8168_enable_ocp_phy_power_saving(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 val; - - if (tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - val = rtl8168_mdio_read_phy_ocp(tp, 0x0C41, 0x13); - if (val != 0x0050) { - rtl8168_set_phy_mcu_patch_request(tp); - rtl8168_mdio_write_phy_ocp(tp, 0x0C41, 0x13, 0x0000); - rtl8168_mdio_write_phy_ocp(tp, 0x0C41, 0x13, 0x0050); - rtl8168_clear_phy_mcu_patch_request(tp); - } - } -} - -static void -rtl8168_disable_ocp_phy_power_saving(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 val; - - if (tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - val = rtl8168_mdio_read_phy_ocp(tp, 0x0C41, 0x13); - if (val != 0x0500) { - rtl8168_set_phy_mcu_patch_request(tp); - rtl8168_mdio_write_phy_ocp(tp, 0x0C41, 0x13, 0x0000); - rtl8168_mdio_write_phy_ocp(tp, 0x0C41, 0x13, 0x0500); - rtl8168_clear_phy_mcu_patch_request(tp); - } - } -} - -void -rtl8168_wait_ll_share_fifo_ready(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int i; - - for (i = 0; i < 10; i++) { - udelay(100); - if (RTL_R16(tp, 0xD2) & BIT_9) - break; - } -} - -static void -rtl8168_disable_pci_offset_99(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x3F2, 2, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_0 | BIT_1); - rtl8168_eri_write(tp, 0x3F2, 2, csi_tmp, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_csi_fun0_write_byte(tp, 0x99, 0x00); - break; - } -} - -static void -rtl8168_enable_pci_offset_99(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_csi_fun0_write_byte(tp, 0x99, tp->org_pci_offset_99); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x3F2, 2, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_0 | BIT_1); - if (tp->org_pci_offset_99 & (BIT_5 | BIT_6)) - csi_tmp |= BIT_1; - if (tp->org_pci_offset_99 & BIT_2) - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0x3F2, 2, csi_tmp, ERIAR_ExGMAC); - break; - } -} - -static void -rtl8168_init_pci_offset_99(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_26: - if (tp->org_pci_offset_99 & BIT_2) { - csi_tmp = rtl8168_eri_read(tp, 0x5C2, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_1; - rtl8168_eri_write(tp, 0x5C2, 1, csi_tmp, ERIAR_ExGMAC); - } - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x3F2, 2, ERIAR_ExGMAC); - csi_tmp &= ~( BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12 | BIT_13 | BIT_14 | BIT_15 ); - csi_tmp |= ( BIT_9 | BIT_10 | BIT_13 | BIT_14 | BIT_15 ); - rtl8168_eri_write(tp, 0x3F2, 2, csi_tmp, ERIAR_ExGMAC); - csi_tmp = rtl8168_eri_read(tp, 0x3F5, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_6 | BIT_7; - rtl8168_eri_write(tp, 0x3F5, 1, csi_tmp, ERIAR_ExGMAC); - rtl8168_mac_ocp_write(tp, 0xE02C, 0x1880); - rtl8168_mac_ocp_write(tp, 0xE02E, 0x4880); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_26: - rtl8168_eri_write(tp, 0x5C0, 1, 0xFA, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_26: - if (tp->org_pci_offset_99 & BIT_2) { - csi_tmp = rtl8168_eri_read(tp, 0x5C8, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0x5C8, 1, csi_tmp, ERIAR_ExGMAC); - } - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - if (tp->org_pci_offset_99 & BIT_2) - rtl8168_mac_ocp_write(tp, 0xE0A2, rtl8168_mac_ocp_read(tp, 0xE0A2) | BIT_0); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_23: - rtl8168_eri_write(tp, 0x2E8, 2, 0x883C, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2EA, 2, 0x8C12, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2EC, 2, 0x9003, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2E2, 2, 0x883C, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2E4, 2, 0x8C12, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2E6, 2, 0x9003, ERIAR_ExGMAC); - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_eri_write(tp, 0x2E8, 2, 0x9003, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2EA, 2, 0x9003, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2EC, 2, 0x9003, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2E2, 2, 0x883C, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2E4, 2, 0x8C12, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2E6, 2, 0x9003, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - csi_tmp = rtl8168_eri_read(tp, 0x3FA, 2, ERIAR_ExGMAC); - csi_tmp |= BIT_14; - rtl8168_eri_write(tp, 0x3FA, 2, csi_tmp, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - if (tp->org_pci_offset_99 & BIT_2) - RTL_W8(tp, 0xB6, RTL_R8(tp, 0xB6) | BIT_0); - break; - } - - rtl8168_enable_pci_offset_99(tp); -} - -static void -rtl8168_disable_pci_offset_180(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x1E2, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_2; - rtl8168_eri_write(tp, 0x1E2, 1, csi_tmp, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_26: - rtl8168_eri_write(tp, 0x1E9, 1, 0x0A, ERIAR_ExGMAC); - break; - } -} - -static void -rtl8168_enable_pci_offset_180(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_25: - case CFG_METHOD_28: - csi_tmp = rtl8168_eri_read(tp, 0x1E8, 4, ERIAR_ExGMAC); - csi_tmp &= ~(0x0000FF00); - csi_tmp |= (0x00006400); - rtl8168_eri_write(tp, 0x1E8, 4, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x1E4, 4, ERIAR_ExGMAC); - csi_tmp &= ~(0x0000FF00); - rtl8168_eri_write(tp, 0x1E4, 4, csi_tmp, ERIAR_ExGMAC); - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x1E8, 4, ERIAR_ExGMAC); - csi_tmp &= ~(0x0000FFF0); - csi_tmp |= (0x00000640); - rtl8168_eri_write(tp, 0x1E8, 4, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x1E4, 4, ERIAR_ExGMAC); - csi_tmp &= ~(0x0000FF00); - rtl8168_eri_write(tp, 0x1E4, 4, csi_tmp, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - csi_tmp = rtl8168_eri_read(tp, 0x1E2, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_2; - rtl8168_eri_write(tp, 0x1E2, 1, csi_tmp, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_26: - rtl8168_eri_write(tp, 0x1E9, 1, 0x64, ERIAR_ExGMAC); - break; - } - - rtl8168_mac_ocp_write(tp, 0xE094, 0x0000); -} - -static void -rtl8168_init_pci_offset_180(struct rtl8168_private *tp) -{ - if (tp->org_pci_offset_180 & (BIT_0|BIT_1)) - rtl8168_enable_pci_offset_180(tp); - else - rtl8168_disable_pci_offset_180(tp); -} - -static void -rtl8168_set_pci_99_180_exit_driver_para(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_issue_offset_99_event(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_disable_pci_offset_99(tp); - break; - } - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_disable_pci_offset_180(tp); - break; - } -} - -static void -rtl8168_hw_d3_para(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - RTL_W16(tp, RxMaxSize, RX_BUF_SIZE); - - if (tp->HwSuppAspmClkIntrLock) { - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - rtl8168_enable_cfg9346_write(tp); - rtl8168_hw_aspm_clkreq_enable(tp, false); - rtl8168_disable_cfg9346_write(tp); - } - - rtl8168_disable_exit_l1_mask(tp); - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8168_set_realwow_d3_para(dev); -#endif - - if (tp->mcfg == CFG_METHOD_18 || tp->mcfg == CFG_METHOD_19 || tp->mcfg == CFG_METHOD_20) { - rtl8168_eri_write(tp, 0x1bc, 4, 0x0000001f, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x0000002d, ERIAR_ExGMAC); - } else if (tp->mcfg == CFG_METHOD_16) { - rtl8168_eri_write(tp, 0x1bc, 4, 0x0000001f, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x0000003f, ERIAR_ExGMAC); - } - - if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_23 || tp->mcfg == CFG_METHOD_24 || - tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - rtl8168_eri_write(tp, 0x2F8, 2, 0x0064, ERIAR_ExGMAC); - } - - if (tp->bios_setting & BIT_28) { - if (tp->mcfg == CFG_METHOD_18 || tp->mcfg == CFG_METHOD_19 || - tp->mcfg == CFG_METHOD_20) { - u32 gphy_val; - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x04, 0x0061); - rtl8168_mdio_write(tp, 0x09, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val &= ~BIT_7; - rtl8168_mdio_write(tp, 0x06, gphy_val); - mdelay(1); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - gphy_val = rtl8168_mdio_read(tp, 0x16); - gphy_val &= ~BIT_10; - rtl8168_mdio_write(tp, 0x16, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - } - - rtl8168_set_pci_99_180_exit_driver_para(dev); - - /*disable ocp phy power saving*/ - if (tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) - if (!tp->dash_printer_enabled) - rtl8168_disable_ocp_phy_power_saving(dev); - - rtl8168_disable_rxdvgate(dev); -} - -static void -rtl8168_enable_magic_packet(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 csi_tmp; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V1: - rtl8168_enable_cfg9346_write(tp); - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | MagicPacket); - rtl8168_disable_cfg9346_write(tp); - break; - case WAKEUP_MAGIC_PACKET_V2: - csi_tmp = rtl8168_eri_read(tp, 0xDE, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDE, 1, csi_tmp, ERIAR_ExGMAC); - break; - } -} -static void -rtl8168_disable_magic_packet(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 csi_tmp; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V1: - rtl8168_enable_cfg9346_write(tp); - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~MagicPacket); - rtl8168_disable_cfg9346_write(tp); - break; - case WAKEUP_MAGIC_PACKET_V2: - csi_tmp = rtl8168_eri_read(tp, 0xDE, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDE, 1, csi_tmp, ERIAR_ExGMAC); - break; - } -} - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - -static void -rtl8168_get_hw_wol(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 options; - u32 csi_tmp; - unsigned long flags; - - - spin_lock_irqsave(&tp->lock, flags); - - tp->wol_opts = 0; - options = RTL_R8(tp, Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(tp, Config3); - if (options & LinkUp) - tp->wol_opts |= WAKE_PHY; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V2: - csi_tmp = rtl8168_eri_read(tp, 0xDE, 1, ERIAR_ExGMAC); - if (csi_tmp & BIT_0) - tp->wol_opts |= WAKE_MAGIC; - break; - default: - if (options & MagicPacket) - tp->wol_opts |= WAKE_MAGIC; - break; - } - - options = RTL_R8(tp, Config5); - if (options & UWF) - tp->wol_opts |= WAKE_UCAST; - if (options & BWF) - tp->wol_opts |= WAKE_BCAST; - if (options & MWF) - tp->wol_opts |= WAKE_MCAST; - -out_unlock: - tp->wol_enabled = (tp->wol_opts || tp->dash_printer_enabled) ? WOL_ENABLED : WOL_DISABLED; - - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void -rtl8168_set_hw_wol(struct net_device *dev, u32 wolopts) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int i,tmp; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_PHY, Config3, LinkUp }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake }, - { WAKE_MAGIC, Config3, MagicPacket }, - }; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V2: - tmp = ARRAY_SIZE(cfg) - 1; - - if (wolopts & WAKE_MAGIC) - rtl8168_enable_magic_packet(dev); - else - rtl8168_disable_magic_packet(dev); - break; - default: - tmp = ARRAY_SIZE(cfg); - break; - } - - rtl8168_enable_cfg9346_write(tp); - - for (i = 0; i < tmp; i++) { - u8 options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(tp, cfg[i].reg, options); - } - - if (tp->dash_printer_enabled) - RTL_W8(tp, Config5, RTL_R8(tp, Config5) | LanWake); - - rtl8168_disable_cfg9346_write(tp); -} - -static void -rtl8168_phy_restart_nway(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (rtl8168_is_in_phy_disable_mode(dev)) return; - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART); -} - -static void -rtl8168_phy_setup_force_mode(struct net_device *dev, u32 speed, u8 duplex) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 bmcr_true_force = 0; - - if (rtl8168_is_in_phy_disable_mode(dev)) return; - - if ((speed == SPEED_10) && (duplex == DUPLEX_HALF)) { - bmcr_true_force = BMCR_SPEED10; - } else if ((speed == SPEED_10) && (duplex == DUPLEX_FULL)) { - bmcr_true_force = BMCR_SPEED10 | BMCR_FULLDPLX; - } else if ((speed == SPEED_100) && (duplex == DUPLEX_HALF)) { - bmcr_true_force = BMCR_SPEED100; - } else if ((speed == SPEED_100) && (duplex == DUPLEX_FULL)) { - bmcr_true_force = BMCR_SPEED100 | BMCR_FULLDPLX; - } else { - netif_err(tp, drv, dev, "Failed to set phy force mode!\n"); - return; - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, MII_BMCR, bmcr_true_force); -} - -static void -rtl8168_set_pci_pme(struct rtl8168_private *tp, int set) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 pmc; - - if (!pdev->pm_cap) - return; - - pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmc); - pmc |= PCI_PM_CTRL_PME_STATUS; - if (set) - pmc |= PCI_PM_CTRL_PME_ENABLE; - else - pmc &= ~PCI_PM_CTRL_PME_ENABLE; - pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, pmc); -} - -static void -rtl8168_set_wol_link_speed(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int auto_nego; - int giga_ctrl; - u32 adv; - u16 anlpar; - u16 gbsr; - u16 aner; - - if (tp->autoneg != AUTONEG_ENABLE) - goto exit; - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - auto_nego = rtl8168_mdio_read(tp, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL - | ADVERTISE_100HALF | ADVERTISE_100FULL); - - giga_ctrl = rtl8168_mdio_read(tp, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - - aner = anlpar = gbsr = 0; - if (tp->link_ok(dev)) { - aner = rtl8168_mdio_read(tp, MII_EXPANSION); - anlpar = rtl8168_mdio_read(tp, MII_LPA); - gbsr = rtl8168_mdio_read(tp, MII_STAT1000); - } else { - if (netif_running(dev)) { - aner = tp->phy_reg_aner; - anlpar = tp->phy_reg_anlpar; - gbsr = tp->phy_reg_gbsr; - } - } - - if ((aner | anlpar | gbsr) == 0) { - int auto_nego_tmp = 0; - adv = tp->advertising; - if ((adv & ADVERTISED_10baseT_Half) && (anlpar & LPA_10HALF)) - auto_nego_tmp |= ADVERTISE_10HALF; - if ((adv & ADVERTISED_10baseT_Full) && (anlpar & LPA_10FULL)) - auto_nego_tmp |= ADVERTISE_10FULL; - if ((adv & ADVERTISED_100baseT_Half) && (anlpar & LPA_100HALF)) - auto_nego_tmp |= ADVERTISE_100HALF; - if ((adv & ADVERTISED_100baseT_Full) && (anlpar & LPA_100FULL)) - auto_nego_tmp |= ADVERTISE_100FULL; - - if (auto_nego_tmp == 0) goto exit; - - auto_nego |= auto_nego_tmp; - goto skip_check_lpa; - } - if (!(aner & EXPANSION_NWAY)) goto exit; - - adv = tp->advertising; - if ((adv & ADVERTISED_10baseT_Half) && (anlpar & LPA_10HALF)) - auto_nego |= ADVERTISE_10HALF; - else if ((adv & ADVERTISED_10baseT_Full) && (anlpar & LPA_10FULL)) - auto_nego |= ADVERTISE_10FULL; - else if ((adv & ADVERTISED_100baseT_Half) && (anlpar & LPA_100HALF)) - auto_nego |= ADVERTISE_100HALF; - else if ((adv & ADVERTISED_100baseT_Full) && (anlpar & LPA_100FULL)) - auto_nego |= ADVERTISE_100FULL; - else if (adv & ADVERTISED_1000baseT_Half && (gbsr & LPA_1000HALF)) - giga_ctrl |= ADVERTISE_1000HALF; - else if (adv & ADVERTISED_1000baseT_Full && (gbsr & LPA_1000FULL)) - giga_ctrl |= ADVERTISE_1000FULL; - else - goto exit; - -skip_check_lpa: - if (tp->DASH) - auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); - - if (((tp->mcfg == CFG_METHOD_7) || (tp->mcfg == CFG_METHOD_8)) && (RTL_R16(tp, CPlusCmd) & ASF)) - auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); - -#ifdef CONFIG_DOWN_SPEED_100 - auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); -#endif - - rtl8168_mdio_write(tp, MII_ADVERTISE, auto_nego); - rtl8168_mdio_write(tp, MII_CTRL1000, giga_ctrl); - - rtl8168_phy_restart_nway(dev); - -exit: - return; -} - -static void -rtl8168_powerdown_pll(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - -#ifdef ENABLE_FIBER_SUPPORT - if (HW_FIBER_MODE_ENABLED(tp)) - return; -#endif //ENABLE_FIBER_SUPPORT - - if (tp->wol_enabled == WOL_ENABLED || tp->DASH || tp->EnableKCPOffload) { - rtl8168_set_hw_wol(dev, tp->wol_opts); - - if (tp->mcfg == CFG_METHOD_16 || tp->mcfg == CFG_METHOD_17 || - tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_24 || tp->mcfg == CFG_METHOD_25 || - tp->mcfg == CFG_METHOD_26 || tp->mcfg == CFG_METHOD_23 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - rtl8168_enable_cfg9346_write(tp); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) | PMSTS_En); - rtl8168_disable_cfg9346_write(tp); - } - - /* Enable the PME and clear the status */ - rtl8168_set_pci_pme(tp, 1); - - if (HW_SUPP_SERDES_PHY(tp)) - return; - - rtl8168_set_wol_link_speed(dev); - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); - - return; - } - - if (tp->DASH) - return; - - if (((tp->mcfg == CFG_METHOD_7) || (tp->mcfg == CFG_METHOD_8)) && (RTL_R16(tp, CPlusCmd) & ASF)) - return; - - rtl8168_phy_power_down(dev); - - if (!tp->HwIcVerUnknown) { - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - //case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~BIT_7); - break; - } - } - - switch (tp->mcfg) { - case CFG_METHOD_14 ... CFG_METHOD_15: - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) & ~BIT_6); - break; - case CFG_METHOD_16 ... CFG_METHOD_33: - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) & ~BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_6); - break; - } -} - -static void rtl8168_powerup_pll(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | BIT_7 | BIT_6); - break; - } - - rtl8168_phy_power_up(dev); -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static void -rtl8168_get_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 options; - unsigned long flags; - - wol->wolopts = 0; - - if (tp->mcfg == CFG_METHOD_DEFAULT) { - wol->supported = 0; - return; - } else { - wol->supported = WAKE_ANY; - } - - spin_lock_irqsave(&tp->lock, flags); - - options = RTL_R8(tp, Config1); - if (!(options & PMEnable)) - goto out_unlock; - - wol->wolopts = tp->wol_opts; - -out_unlock: - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int -rtl8168_set_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - - tp->wol_opts = wol->wolopts; - - tp->wol_enabled = (tp->wol_opts || tp->dash_printer_enabled) ? WOL_ENABLED : WOL_DISABLED; - - spin_unlock_irqrestore(&tp->lock, flags); - - device_set_wakeup_enable(tp_to_dev(tp), tp->wol_enabled); - - return 0; -} - -static void -rtl8168_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct rtl8168_fw *rtl_fw = tp->rtl_fw; - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8168_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = R8168_REGS_DUMP_SIZE; - info->eedump_len = tp->eeprom_len; - BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version)); - if (rtl_fw) - strlcpy(info->fw_version, rtl_fw->version, - sizeof(info->fw_version)); -} - -static int -rtl8168_get_regs_len(struct net_device *dev) -{ - return R8168_REGS_DUMP_SIZE; -} -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -static int -rtl8168_set_speed_xmii(struct net_device *dev, - u8 autoneg, - u32 speed, - u8 duplex, - u32 adv) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int auto_nego = 0; - int giga_ctrl = 0; - int rc = -EINVAL; - - if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - //Disable Giga Lite - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - rtl8168_clear_eth_phy_bit(tp, 0x14, BIT_9); - if (tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) - rtl8168_clear_eth_phy_bit(tp, 0x14, BIT_7); - rtl8168_mdio_write(tp, 0x1F, 0x0A40); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - if ((speed != SPEED_1000) && - (speed != SPEED_100) && - (speed != SPEED_10)) { - speed = SPEED_1000; - duplex = DUPLEX_FULL; - } - - giga_ctrl = rtl8168_mdio_read(tp, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - - if (autoneg == AUTONEG_ENABLE) { - /*n-way force*/ - auto_nego = rtl8168_mdio_read(tp, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL | - ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - - if (adv & ADVERTISED_10baseT_Half) - auto_nego |= ADVERTISE_10HALF; - if (adv & ADVERTISED_10baseT_Full) - auto_nego |= ADVERTISE_10FULL; - if (adv & ADVERTISED_100baseT_Half) - auto_nego |= ADVERTISE_100HALF; - if (adv & ADVERTISED_100baseT_Full) - auto_nego |= ADVERTISE_100FULL; - if (adv & ADVERTISED_1000baseT_Half) - giga_ctrl |= ADVERTISE_1000HALF; - if (adv & ADVERTISED_1000baseT_Full) - giga_ctrl |= ADVERTISE_1000FULL; - - //flow control - if (dev->mtu <= ETH_DATA_LEN) - auto_nego |= ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM; - - tp->phy_auto_nego_reg = auto_nego; - tp->phy_1000_ctrl_reg = giga_ctrl; - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, MII_ADVERTISE, auto_nego); - rtl8168_mdio_write(tp, MII_CTRL1000, giga_ctrl); - rtl8168_phy_restart_nway(dev); - mdelay(20); - } else { - /*true force*/ - if (speed == SPEED_10 || speed == SPEED_100) - rtl8168_phy_setup_force_mode(dev, speed, duplex); - else - goto out; - } - - tp->autoneg = autoneg; - tp->speed = speed; - tp->duplex = duplex; - tp->advertising = adv; - - if (tp->mcfg == CFG_METHOD_11) - rtl8168dp_10mbps_gphy_para(dev); - - rc = 0; -out: - return rc; -} - -static int -rtl8168_set_speed(struct net_device *dev, - u8 autoneg, - u32 speed, - u8 duplex, - u32 adv) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex, adv); - - return ret; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int -rtl8168_set_settings(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - const struct ethtool_link_ksettings *cmd -#endif - ) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int ret; - unsigned long flags; - u8 autoneg; - u32 speed; - u8 duplex; - u32 supported, advertising; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - autoneg = cmd->autoneg; - speed = cmd->speed; - duplex = cmd->duplex; - supported = cmd->supported; - advertising = cmd->advertising; -#else - const struct ethtool_link_settings *base = &cmd->base; - autoneg = base->autoneg; - speed = base->speed; - duplex = base->duplex; - ethtool_convert_link_mode_to_legacy_u32(&supported, - cmd->link_modes.supported); - ethtool_convert_link_mode_to_legacy_u32(&advertising, - cmd->link_modes.advertising); -#endif - if (advertising & ~supported) - return -EINVAL; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8168_set_speed(dev, autoneg, speed, duplex, advertising); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -static u32 -rtl8168_get_tx_csum(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 ret; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - ret = ((dev->features & NETIF_F_IP_CSUM) != 0); -#else - ret = ((dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) != 0); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 -rtl8168_get_rx_csum(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 ret; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - ret = tp->cp_cmd & RxChkSum; - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static int -rtl8168_set_tx_csum(struct net_device *dev, - u32 data) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - if (data) - dev->features |= NETIF_F_IP_CSUM; - else - dev->features &= ~NETIF_F_IP_CSUM; -#else - if (data) - if ((tp->mcfg == CFG_METHOD_1) || (tp->mcfg == CFG_METHOD_2) || (tp->mcfg == CFG_METHOD_3)) - dev->features |= NETIF_F_IP_CSUM; - else - dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - else - dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -static int -rtl8168_set_rx_csum(struct net_device *dev, - u32 data) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(tp, CPlusCmd, tp->cp_cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -#ifdef CONFIG_R8168_VLAN - -static inline u32 -rtl8168_tx_vlan_tag(struct rtl8168_private *tp, - struct sk_buff *skb) -{ - u32 tag; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - tag = (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) - tag = (vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -#else - tag = (skb_vlan_tag_present(skb)) ? - TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00; -#endif - - return tag; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - -static void -rtl8168_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - if (tp->vlgrp) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(tp, CPlusCmd, tp->cp_cmd); - RTL_R16(tp, CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -static void -rtl8168_vlan_rx_kill_vid(struct net_device *dev, - unsigned short vid) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) - if (tp->vlgrp) - tp->vlgrp->vlan_devices[vid] = NULL; -#else - vlan_group_set_device(tp->vlgrp, vid, NULL); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) - spin_unlock_irqrestore(&tp->lock, flags); -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - -static int -rtl8168_rx_vlan_skb(struct rtl8168_private *tp, - struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - int ret = -1; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - if (tp->vlgrp && (opts2 & RxVlanTag)) { - rtl8168_rx_hwaccel_skb(skb, tp->vlgrp, - swab16(opts2 & 0xffff)); - ret = 0; - } -#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) - if (opts2 & RxVlanTag) - __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); -#else - if (opts2 & RxVlanTag) - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff)); -#endif - - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8168_VLAN */ - -static inline u32 -rtl8168_tx_vlan_tag(struct rtl8168_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int -rtl8168_rx_vlan_skb(struct rtl8168_private *tp, - struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) - -static netdev_features_t rtl8168_fix_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (dev->mtu > MSS_MAX) - features &= ~NETIF_F_ALL_TSO; - if (dev->mtu > ETH_DATA_LEN) { - features &= ~NETIF_F_ALL_TSO; - features &= ~NETIF_F_ALL_CSUM; - } - spin_unlock_irqrestore(&tp->lock, flags); - - return features; -} - -static int rtl8168_hw_set_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 rx_config; - - rx_config = RTL_R32(tp, RxConfig); - if (features & NETIF_F_RXALL) - rx_config |= (AcceptErr | AcceptRunt); - else - rx_config &= ~(AcceptErr | AcceptRunt); - - RTL_W32(tp, RxConfig, rx_config); - - if (features & NETIF_F_RXCSUM) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - if (dev->features & NETIF_F_HW_VLAN_RX) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - - RTL_W16(tp, CPlusCmd, tp->cp_cmd); - RTL_R16(tp, CPlusCmd); - - return 0; -} - -static int rtl8168_set_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - features &= NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX; - - spin_lock_irqsave(&tp->lock, flags); - if (features ^ dev->features) - rtl8168_hw_set_features(dev, features); - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#endif - -static void rtl8168_gset_xmii(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - struct ethtool_link_ksettings *cmd -#endif - ) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 status; - u8 autoneg, duplex; - u32 speed = 0; - u16 bmcr, bmsr, anlpar, ctrl1000 = 0, stat1000 = 0; - u32 supported, advertising, lp_advertising; - unsigned long flags; - - supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP | - SUPPORTED_Pause | - SUPPORTED_Asym_Pause; - - advertising = ADVERTISED_TP; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - bmcr = rtl8168_mdio_read(tp, MII_BMCR); - bmsr = rtl8168_mdio_read(tp, MII_BMSR); - anlpar = rtl8168_mdio_read(tp, MII_LPA); - ctrl1000 = rtl8168_mdio_read(tp, MII_CTRL1000); - stat1000 = rtl8168_mdio_read(tp, MII_STAT1000); - spin_unlock_irqrestore(&tp->lock, flags); - - if (bmcr & BMCR_ANENABLE) { - advertising |= ADVERTISED_Autoneg; - autoneg = AUTONEG_ENABLE; - - if (bmsr & BMSR_ANEGCOMPLETE) { - lp_advertising = mii_lpa_to_ethtool_lpa_t(anlpar); - lp_advertising |= - mii_stat1000_to_ethtool_lpa_t(stat1000); - } else { - lp_advertising = 0; - } - - if (tp->phy_auto_nego_reg & ADVERTISE_10HALF) - advertising |= ADVERTISED_10baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_10FULL) - advertising |= ADVERTISED_10baseT_Full; - if (tp->phy_auto_nego_reg & ADVERTISE_100HALF) - advertising |= ADVERTISED_100baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_100FULL) - advertising |= ADVERTISED_100baseT_Full; - if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL) - advertising |= ADVERTISED_1000baseT_Full; - } else { - autoneg = AUTONEG_DISABLE; - lp_advertising = 0; - } - - status = RTL_R8(tp, PHYstatus); - - if (status & LinkStatus) { - /*link on*/ - if (status & _1000bpsF) - speed = SPEED_1000; - else if (status & _100bps) - speed = SPEED_100; - else if (status & _10bps) - speed = SPEED_10; - - if (status & TxFlowCtrl) - advertising |= ADVERTISED_Asym_Pause; - - if (status & RxFlowCtrl) - advertising |= ADVERTISED_Pause; - - duplex = ((status & _1000bpsF) || (status & FullDup)) ? - DUPLEX_FULL : DUPLEX_HALF; - } else { - /*link down*/ - speed = SPEED_UNKNOWN; - duplex = DUPLEX_UNKNOWN; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - cmd->supported = supported; - cmd->advertising = advertising; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30) - cmd->lp_advertising = lp_advertising; -#endif - cmd->autoneg = autoneg; - cmd->speed = speed; - cmd->duplex = duplex; - cmd->port = PORT_TP; -#else - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, - supported); - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, - advertising); - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, - lp_advertising); - cmd->base.autoneg = autoneg; - cmd->base.speed = speed; - cmd->base.duplex = duplex; - cmd->base.port = PORT_TP; -#endif -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int -rtl8168_get_settings(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - struct ethtool_link_ksettings *cmd -#endif - ) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - tp->get_settings(dev, cmd); - - return 0; -} - -static void rtl8168_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8168_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - u8 *data = p; - unsigned long flags; - - if (regs->len < R8168_REGS_DUMP_SIZE) - return /* -EINVAL */; - - memset(p, 0, regs->len); - - spin_lock_irqsave(&tp->lock, flags); - for (i = 0; i < R8168_MAC_REGS_SIZE; i++) - *data++ = readb(ioaddr + i); - data = (u8*)p + 256; - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - for (i = 0; i < R8168_PHY_REGS_SIZE/2; i++) { - *(u16*)data = rtl8168_mdio_read(tp, i); - data += 2; - } - data = (u8*)p + 256 * 2; - - for (i = 0; i < R8168_EPHY_REGS_SIZE/2; i++) { - *(u16*)data = rtl8168_ephy_read(tp, i); - data += 2; - } - data = (u8*)p + 256 * 3; - - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - /* RTL8168B does not support Extend GMAC */ - break; - default: - for (i = 0; i < R8168_ERI_REGS_SIZE; i+=4) { - *(u32*)data = rtl8168_eri_read(tp, i , 4, ERIAR_ExGMAC); - data += 4; - } - break; - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 -rtl8168_get_msglevel(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void -rtl8168_set_msglevel(struct net_device *dev, - u32 value) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8168_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; -#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int rtl8168_get_stats_count(struct net_device *dev) -{ - return ARRAY_SIZE(rtl8168_gstrings); -} -#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -#else -static int rtl8168_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8168_gstrings); - default: - return -EOPNOTSUPP; - } -} -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static void -rtl8168_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, - u64 *data) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct rtl8168_counters *counters; - dma_addr_t paddr; - u32 cmd; - u32 WaitCnt; - unsigned long flags; - - ASSERT_RTNL(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) - return; - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(tp, CounterAddrLow, cmd); - RTL_W32(tp, CounterAddrLow, cmd | CounterDump); - - WaitCnt = 0; - while (RTL_R32(tp, CounterAddrLow) & CounterDump) { - udelay(10); - - WaitCnt++; - if (WaitCnt > 20) - break; - } - spin_unlock_irqrestore(&tp->lock, flags); - - data[0] = le64_to_cpu(counters->tx_packets); - data[1] = le64_to_cpu(counters->rx_packets); - data[2] = le64_to_cpu(counters->tx_errors); - data[3] = le32_to_cpu(counters->rx_errors); - data[4] = le16_to_cpu(counters->rx_missed); - data[5] = le16_to_cpu(counters->align_errors); - data[6] = le32_to_cpu(counters->tx_one_collision); - data[7] = le32_to_cpu(counters->tx_multi_collision); - data[8] = le64_to_cpu(counters->rx_unicast); - data[9] = le64_to_cpu(counters->rx_broadcast); - data[10] = le32_to_cpu(counters->rx_multicast); - data[11] = le16_to_cpu(counters->tx_aborted); - data[12] = le16_to_cpu(counters->tx_underrun); -} - -static void -rtl8168_get_strings(struct net_device *dev, - u32 stringset, - u8 *data) -{ - switch (stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8168_gstrings, sizeof(rtl8168_gstrings)); - break; - } -} -#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -static int rtl_get_eeprom_len(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - return tp->eeprom_len; -} - -static int rtl_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *buf) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int i,j,ret; - int start_w, end_w; - int VPD_addr, VPD_data; - u32 *eeprom_buff; - u16 tmp; - - if (tp->eeprom_type == EEPROM_TYPE_NONE) { - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Detect none EEPROM\n"); - return -EOPNOTSUPP; - } else if (eeprom->len == 0 || (eeprom->offset+eeprom->len) > tp->eeprom_len) { - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Invalid parameter\n"); - return -EINVAL; - } - - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - VPD_addr = 0xCE; - VPD_data = 0xD0; - break; - - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - return -EOPNOTSUPP; - default: - VPD_addr = 0xD2; - VPD_data = 0xD4; - break; - } - - start_w = eeprom->offset >> 2; - end_w = (eeprom->offset + eeprom->len - 1) >> 2; - - eeprom_buff = kmalloc(sizeof(u32)*(end_w - start_w + 1), GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - rtl8168_enable_cfg9346_write(tp); - ret = -EFAULT; - for (i=start_w; i<=end_w; i++) { - pci_write_config_word(tp->pci_dev, VPD_addr, (u16)i*4); - ret = -EFAULT; - for (j = 0; j < 10; j++) { - udelay(400); - pci_read_config_word(tp->pci_dev, VPD_addr, &tmp); - if (tmp&0x8000) { - ret = 0; - break; - } - } - - if (ret) - break; - - pci_read_config_dword(tp->pci_dev, VPD_data, &eeprom_buff[i-start_w]); - } - rtl8168_disable_cfg9346_write(tp); - - if (!ret) - memcpy(buf, (u8 *)eeprom_buff + (eeprom->offset & 3), eeprom->len); - - kfree(eeprom_buff); - - return ret; -} - -#undef ethtool_op_get_link -#define ethtool_op_get_link _kc_ethtool_op_get_link -static u32 _kc_ethtool_op_get_link(struct net_device *dev) -{ - return netif_carrier_ok(dev) ? 1 : 0; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#undef ethtool_op_get_sg -#define ethtool_op_get_sg _kc_ethtool_op_get_sg -static u32 _kc_ethtool_op_get_sg(struct net_device *dev) -{ -#ifdef NETIF_F_SG - return (dev->features & NETIF_F_SG) != 0; -#else - return 0; -#endif -} - -#undef ethtool_op_set_sg -#define ethtool_op_set_sg _kc_ethtool_op_set_sg -static int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - -#ifdef NETIF_F_SG - if (data) - dev->features |= NETIF_F_SG; - else - dev->features &= ~NETIF_F_SG; -#endif - - return 0; -} -#endif - -static int rtl8168_enable_EEE(struct rtl8168_private *tp) -{ - int ret; - u16 data; - u32 csi_tmp; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0020); - data = rtl8168_mdio_read(tp, 0x15) | 0x0100; - rtl8168_mdio_write(tp, 0x15, data); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - data = rtl8168_mdio_read(tp, 0x06) | 0x2000; - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0006); - rtl8168_mdio_write(tp, 0x00, 0x5A30); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0007); - rtl8168_mdio_write(tp, 0x0E, 0x003C); - rtl8168_mdio_write(tp, 0x0D, 0x4007); - rtl8168_mdio_write(tp, 0x0E, 0x0006); - rtl8168_mdio_write(tp, 0x0D, 0x0000); - if ((RTL_R8(tp, Config4)&0x40) && (RTL_R8(tp, 0x6D) & BIT_7)) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8AC8); - rtl8168_mdio_write(tp, 0x06, RTL_R16(tp, tp->NicCustLedValue)); - rtl8168_mdio_write(tp, 0x05, 0x8B82); - data = rtl8168_mdio_read(tp, 0x06) | 0x0010; - rtl8168_mdio_write(tp, 0x05, 0x8B82); - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - break; - - case CFG_METHOD_16: - case CFG_METHOD_17: - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC) | 0x0003; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - rtl8168_mdio_write(tp,0x1F , 0x0004); - rtl8168_mdio_write(tp,0x1F , 0x0007); - rtl8168_mdio_write(tp,0x1E , 0x0020); - data = rtl8168_mdio_read(tp, 0x15)|0x0100; - rtl8168_mdio_write(tp,0x15 , data); - rtl8168_mdio_write(tp,0x1F , 0x0002); - rtl8168_mdio_write(tp,0x1F , 0x0005); - rtl8168_mdio_write(tp,0x05 , 0x8B85); - data = rtl8168_mdio_read(tp, 0x06)|0x2000; - rtl8168_mdio_write(tp,0x06 , data); - rtl8168_mdio_write(tp,0x1F , 0x0000); - rtl8168_mdio_write(tp,0x0D , 0x0007); - rtl8168_mdio_write(tp,0x0E , 0x003C); - rtl8168_mdio_write(tp,0x0D , 0x4007); - rtl8168_mdio_write(tp,0x0E , 0x0006); - rtl8168_mdio_write(tp,0x0D , 0x0000); - break; - - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp |= BIT_1 | BIT_0; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0020); - data = rtl8168_mdio_read(tp, 0x15); - data |= BIT_8; - rtl8168_mdio_write(tp, 0x15, data); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - data = rtl8168_mdio_read(tp, 0x06); - data |= BIT_13; - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0007); - rtl8168_mdio_write(tp, 0x0E, 0x003C); - rtl8168_mdio_write(tp, 0x0D, 0x4007); - rtl8168_mdio_write(tp, 0x0E, 0x0006); - rtl8168_mdio_write(tp, 0x0D, 0x0000); - break; - - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp |= BIT_1 | BIT_0; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x11); - rtl8168_mdio_write(tp, 0x11, data | BIT_4); - rtl8168_mdio_write(tp, 0x1F, 0x0A5D); - rtl8168_mdio_write(tp, 0x10, tp->eee_adv_t); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - - default: -// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEE\n"); - ret = -EOPNOTSUPP; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mdio_write(tp, 0x1F, 0x0A4A); - rtl8168_set_eth_phy_bit(tp, 0x11, BIT_9); - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_7); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - } - - /*Advanced EEE*/ - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_oob_mutex_lock(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_set_phy_mcu_patch_request(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_25: - rtl8168_eri_write(tp, 0x1EA, 1, 0xFA, ERIAR_ExGMAC); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x10); - if (data & BIT_10) { - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - data = rtl8168_mdio_read(tp, 0x16); - data &= ~(BIT_1); - rtl8168_mdio_write(tp, 0x16, data); - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - data = rtl8168_mdio_read(tp, 0x16); - data |= BIT_1; - rtl8168_mdio_write(tp, 0x16, data); - } - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_26: - data = rtl8168_mac_ocp_read(tp, 0xE052); - data |= BIT_0; - rtl8168_mac_ocp_write(tp, 0xE052, data); - data = rtl8168_mac_ocp_read(tp, 0xE056); - data &= 0xFF0F; - data |= (BIT_4 | BIT_5 | BIT_6); - rtl8168_mac_ocp_write(tp, 0xE056, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x10); - if (data & BIT_10) { - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - data = rtl8168_mdio_read(tp, 0x16); - data &= ~(BIT_1); - rtl8168_mdio_write(tp, 0x16, data); - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - data = rtl8168_mdio_read(tp, 0x16); - data |= BIT_1; - rtl8168_mdio_write(tp, 0x16, data); - } - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_27: - case CFG_METHOD_28: - data = rtl8168_mac_ocp_read(tp, 0xE052); - data &= ~BIT_0; - rtl8168_mac_ocp_write(tp, 0xE052, data); - data = rtl8168_mac_ocp_read(tp, 0xE056); - data &= 0xFF0F; - data |= (BIT_4 | BIT_5 | BIT_6); - rtl8168_mac_ocp_write(tp, 0xE056, data); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - data = rtl8168_mac_ocp_read(tp, 0xE052); - data &= ~(BIT_0); - rtl8168_mac_ocp_write(tp, 0xE052, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x10) | BIT_15; - rtl8168_mdio_write(tp, 0x10, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - data = rtl8168_mdio_read(tp, 0x11) | BIT_13 | BIT_14; - data &= ~(BIT_12); - rtl8168_mdio_write(tp, 0x11, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - /* - data = rtl8168_mac_ocp_read(tp, 0xE052); - data |= BIT_0; - rtl8168_mac_ocp_write(tp, 0xE052, data); - */ - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x10) | BIT_15; - rtl8168_mdio_write(tp, 0x10, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - data = rtl8168_mdio_read(tp, 0x11) | BIT_13 | BIT_14; - data &= ~(BIT_12); - rtl8168_mdio_write(tp, 0x11, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_clear_phy_mcu_patch_request(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_oob_mutex_unlock(tp); - break; - } - - return ret; -} - -static int rtl8168_disable_EEE(struct rtl8168_private *tp) -{ - int ret; - u16 data; - u32 csi_tmp; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - data = rtl8168_mdio_read(tp, 0x06) & ~0x2000; - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0020); - data = rtl8168_mdio_read(tp, 0x15) & ~0x0100; - rtl8168_mdio_write(tp, 0x15, data); - rtl8168_mdio_write(tp, 0x1F, 0x0006); - rtl8168_mdio_write(tp, 0x00, 0x5A00); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0007); - rtl8168_mdio_write(tp, 0x0E, 0x003C); - rtl8168_mdio_write(tp, 0x0D, 0x4007); - rtl8168_mdio_write(tp, 0x0E, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - if (RTL_R8(tp, Config4) & 0x40) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B82); - data = rtl8168_mdio_read(tp, 0x06) & ~0x0010; - rtl8168_mdio_write(tp, 0x05, 0x8B82); - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - break; - - case CFG_METHOD_16: - case CFG_METHOD_17: - csi_tmp = rtl8168_eri_read(tp, 0x1B0,4, ERIAR_ExGMAC)& ~0x0003; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - data = rtl8168_mdio_read(tp, 0x06) & ~0x2000; - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0004); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0020); - data = rtl8168_mdio_read(tp, 0x15) & ~0x0100; - rtl8168_mdio_write(tp,0x15 , data); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0007); - rtl8168_mdio_write(tp, 0x0E, 0x003C); - rtl8168_mdio_write(tp, 0x0D, 0x4007); - rtl8168_mdio_write(tp, 0x0E, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_1 | BIT_0); - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - data = rtl8168_mdio_read(tp, 0x06); - data &= ~BIT_13; - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0020); - data = rtl8168_mdio_read(tp, 0x15); - data &= ~BIT_8; - rtl8168_mdio_write(tp, 0x15, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0007); - rtl8168_mdio_write(tp, 0x0E, 0x003C); - rtl8168_mdio_write(tp, 0x0D, 0x4007); - rtl8168_mdio_write(tp, 0x0E, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_1 | BIT_0); - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x11); - rtl8168_mdio_write(tp, 0x11, data & ~BIT_4); - rtl8168_mdio_write(tp, 0x1F, 0x0A5D); - rtl8168_mdio_write(tp, 0x10, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - - default: -// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEE\n"); - ret = -EOPNOTSUPP; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - rtl8168_clear_eth_phy_bit(tp, 0x14, BIT_7); - rtl8168_mdio_write(tp, 0x1F, 0x0A4A); - rtl8168_clear_eth_phy_bit(tp, 0x11, BIT_9); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - } - - /*Advanced EEE*/ - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_oob_mutex_lock(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_set_phy_mcu_patch_request(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_25: - rtl8168_eri_write(tp, 0x1EA, 1, 0x00, ERIAR_ExGMAC); - - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - data = rtl8168_mdio_read(tp, 0x16); - data &= ~(BIT_1); - rtl8168_mdio_write(tp, 0x16, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_26: - data = rtl8168_mac_ocp_read(tp, 0xE052); - data &= ~(BIT_0); - rtl8168_mac_ocp_write(tp, 0xE052, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - data = rtl8168_mdio_read(tp, 0x16); - data &= ~(BIT_1); - rtl8168_mdio_write(tp, 0x16, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_27: - case CFG_METHOD_28: - data = rtl8168_mac_ocp_read(tp, 0xE052); - data &= ~(BIT_0); - rtl8168_mac_ocp_write(tp, 0xE052, data); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - data = rtl8168_mac_ocp_read(tp, 0xE052); - data &= ~(BIT_0); - rtl8168_mac_ocp_write(tp, 0xE052, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x10) & ~(BIT_15); - rtl8168_mdio_write(tp, 0x10, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - data = rtl8168_mdio_read(tp, 0x11) & ~(BIT_12 | BIT_13 | BIT_14); - rtl8168_mdio_write(tp, 0x11, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_clear_phy_mcu_patch_request(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_oob_mutex_unlock(tp); - break; - } - - return ret; -} - -static int rtl_nway_reset(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - int ret, bmcr; - - spin_lock_irqsave(&tp->lock, flags); - - if (unlikely(tp->rtk_enable_diag)) { - spin_unlock_irqrestore(&tp->lock, flags); - return -EBUSY; - } - - /* if autoneg is off, it's an error */ - rtl8168_mdio_write(tp, 0x1F, 0x0000); - bmcr = rtl8168_mdio_read(tp, MII_BMCR); - - if (bmcr & BMCR_ANENABLE) { - bmcr |= BMCR_ANRESTART; - rtl8168_mdio_write(tp, MII_BMCR, bmcr); - ret = 0; - } else { - ret = -EINVAL; - } - - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) -static int -rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *eee) -{ - struct rtl8168_private *tp = netdev_priv(net); - u32 lp, adv, supported = 0; - unsigned long flags; - u16 val; - - switch (tp->mcfg) { - case CFG_METHOD_21 ... CFG_METHOD_33: - break; - default: - return -EOPNOTSUPP; - } - - spin_lock_irqsave(&tp->lock, flags); - - if (unlikely(tp->rtk_enable_diag)) { - spin_unlock_irqrestore(&tp->lock, flags); - return -EBUSY; - } - - rtl8168_mdio_write(tp, 0x1F, 0x0A5C); - val = rtl8168_mdio_read(tp, 0x12); - supported = mmd_eee_cap_to_ethtool_sup_t(val); - - rtl8168_mdio_write(tp, 0x1F, 0x0A5D); - val = rtl8168_mdio_read(tp, 0x10); - adv = mmd_eee_adv_to_ethtool_adv_t(val); - - val = rtl8168_mdio_read(tp, 0x11); - lp = mmd_eee_adv_to_ethtool_adv_t(val); - - val = rtl8168_eri_read(tp, 0x1B0, 2, ERIAR_ExGMAC); - val &= BIT_1 | BIT_0; - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - spin_unlock_irqrestore(&tp->lock, flags); - - eee->eee_enabled = !!val; - eee->eee_active = !!(supported & adv & lp); - eee->supported = supported; - eee->advertised = adv; - eee->lp_advertised = lp; - - return 0; -} - -static int -rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *eee) -{ - struct rtl8168_private *tp = netdev_priv(net); - unsigned long flags; - - switch (tp->mcfg) { - case CFG_METHOD_21 ... CFG_METHOD_33: - break; - default: - return -EOPNOTSUPP; - } - - if (HW_SUPP_SERDES_PHY(tp) || - !HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp) || - tp->DASH) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - - if (unlikely(tp->rtk_enable_diag)) { - spin_unlock_irqrestore(&tp->lock, flags); - return -EBUSY; - } - - tp->eee_enabled = eee->eee_enabled; - tp->eee_adv_t = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); - - if (tp->eee_enabled) - rtl8168_enable_EEE(tp); - else - rtl8168_disable_EEE(tp); - - spin_unlock_irqrestore(&tp->lock, flags); - - rtl_nway_reset(net); - - return 0; -} -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static const struct ethtool_ops rtl8168_ethtool_ops = { - .get_drvinfo = rtl8168_get_drvinfo, - .get_regs_len = rtl8168_get_regs_len, - .get_link = ethtool_op_get_link, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - .get_settings = rtl8168_get_settings, - .set_settings = rtl8168_set_settings, -#else - .get_link_ksettings = rtl8168_get_settings, - .set_link_ksettings = rtl8168_set_settings, -#endif - .get_msglevel = rtl8168_get_msglevel, - .set_msglevel = rtl8168_set_msglevel, -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - .get_rx_csum = rtl8168_get_rx_csum, - .set_rx_csum = rtl8168_set_rx_csum, - .get_tx_csum = rtl8168_get_tx_csum, - .set_tx_csum = rtl8168_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, -#ifdef NETIF_F_TSO - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, -#endif -#endif - .get_regs = rtl8168_get_regs, - .get_wol = rtl8168_get_wol, - .set_wol = rtl8168_set_wol, - .get_strings = rtl8168_get_strings, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) - .get_stats_count = rtl8168_get_stats_count, -#else - .get_sset_count = rtl8168_get_sset_count, -#endif - .get_ethtool_stats = rtl8168_get_ethtool_stats, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) -#ifdef ETHTOOL_GPERMADDR - .get_perm_addr = ethtool_op_get_perm_addr, -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) - .get_eeprom = rtl_get_eeprom, - .get_eeprom_len = rtl_get_eeprom_len, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) - .get_ts_info = ethtool_op_get_ts_info, -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) - .get_eee = rtl_ethtool_get_eee, - .set_eee = rtl_ethtool_set_eee, -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ - .nway_reset = rtl_nway_reset, -}; -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -#if 0 - -static int rtl8168_enable_green_feature(struct rtl8168_private *tp) -{ - u16 gphy_val; - unsigned long flags; - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - rtl8168_mdio_write(tp, 0x1F, 0x0003); - gphy_val = rtl8168_mdio_read(tp, 0x10) | 0x0400; - rtl8168_mdio_write(tp, 0x10, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x19) | 0x0001; - rtl8168_mdio_write(tp, 0x19, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - gphy_val = rtl8168_mdio_read(tp, 0x01) & ~0x0100; - rtl8168_mdio_write(tp, 0x01, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - mdelay(20); - break; - - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - rtl8168_mdio_write(tp, 0x1f, 0x0003); - gphy_val = rtl8168_mdio_read(tp, 0x10); - gphy_val |= BIT_10; - rtl8168_mdio_write(tp, 0x10, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x19); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x19, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - gphy_val = rtl8168_mdio_read(tp, 0x01); - gphy_val |= BIT_8; - rtl8168_mdio_write(tp, 0x01, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - break; - case CFG_METHOD_21: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_set_eth_phy_bit( tp, 0x14, BIT_14 ); - rtl8168_mdio_write(tp, 0x1F, 0x0A40); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8045); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0x804d); - rtl8168_mdio_write(tp, 0x14, 0x1222); - rtl8168_mdio_write(tp, 0x13, 0x805d); - rtl8168_mdio_write(tp, 0x14, 0x0022); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_set_eth_phy_bit( tp, 0x14, BIT_15 ); - rtl8168_mdio_write(tp, 0x1F, 0x0A40); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - break; - default: - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support Green Feature\n"); - break; - } - - return 0; -} - -static int rtl8168_disable_green_feature(struct rtl8168_private *tp) -{ - u16 gphy_val; - unsigned long flags; - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - rtl8168_mdio_write(tp, 0x1F, 0x0005); - gphy_val = rtl8168_mdio_read(tp, 0x01) | 0x0100; - rtl8168_mdio_write(tp, 0x01, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - gphy_val = rtl8168_mdio_read(tp, 0x10) & ~0x0400; - rtl8168_mdio_write(tp, 0x10, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x19) & ~0x0001; - rtl8168_mdio_write(tp, 0x19, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x06) & ~0x7000; - gphy_val |= 0x3000; - rtl8168_mdio_write(tp, 0x06, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x0D) & 0x0700; - gphy_val |= 0x0500; - rtl8168_mdio_write(tp, 0x0D, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - rtl8168_mdio_write(tp, 0x1f, 0x0003); - gphy_val = rtl8168_mdio_read(tp, 0x19); - gphy_val &= ~BIT_0; - rtl8168_mdio_write(tp, 0x19, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x10); - gphy_val &= ~BIT_10; - rtl8168_mdio_write(tp, 0x10, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - break; - case CFG_METHOD_21: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_clear_eth_phy_bit( tp, 0x14, BIT_14 ); - rtl8168_mdio_write(tp, 0x1F, 0x0A40); - rtl8168_mdio_write(tp, 0x00, 0x9200); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8045); - rtl8168_mdio_write(tp, 0x14, 0x2444); - rtl8168_mdio_write(tp, 0x13, 0x804d); - rtl8168_mdio_write(tp, 0x14, 0x2444); - rtl8168_mdio_write(tp, 0x13, 0x805d); - rtl8168_mdio_write(tp, 0x14, 0x2444); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_set_eth_phy_bit( tp, 0x14, BIT_15 ); - rtl8168_mdio_write(tp, 0x1F, 0x0A40); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - break; - default: - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support Green Feature\n"); - break; - } - - return 0; -} - -#endif - -static void rtl8168_get_mac_version(struct rtl8168_private *tp) -{ - u32 reg,val32; - u32 ICVerID; - - val32 = RTL_R32(tp, TxConfig); - reg = val32 & 0x7c800000; - ICVerID = val32 & 0x00700000; - - switch (reg) { - case 0x30000000: - tp->mcfg = CFG_METHOD_1; - tp->efuse_ver = EFUSE_NOT_SUPPORT; - break; - case 0x38000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_2; - } else if (ICVerID == 0x00500000) { - tp->mcfg = CFG_METHOD_3; - } else { - tp->mcfg = CFG_METHOD_3; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_NOT_SUPPORT; - break; - case 0x3C000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_4; - } else if (ICVerID == 0x00200000) { - tp->mcfg = CFG_METHOD_5; - } else if (ICVerID == 0x00400000) { - tp->mcfg = CFG_METHOD_6; - } else { - tp->mcfg = CFG_METHOD_6; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_NOT_SUPPORT; - break; - case 0x3C800000: - if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_7; - } else if (ICVerID == 0x00300000) { - tp->mcfg = CFG_METHOD_8; - } else { - tp->mcfg = CFG_METHOD_8; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_NOT_SUPPORT; - break; - case 0x28000000: - if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_9; - } else if (ICVerID == 0x00300000) { - tp->mcfg = CFG_METHOD_10; - } else { - tp->mcfg = CFG_METHOD_10; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V1; - break; - case 0x28800000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_11; - } else if (ICVerID == 0x00200000) { - tp->mcfg = CFG_METHOD_12; - RTL_W32(tp, 0xD0, RTL_R32(tp, 0xD0) | 0x00020000); - } else if (ICVerID == 0x00300000) { - tp->mcfg = CFG_METHOD_13; - } else { - tp->mcfg = CFG_METHOD_13; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V1; - break; - case 0x2C000000: - if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_14; - } else if (ICVerID == 0x00200000) { - tp->mcfg = CFG_METHOD_15; - } else { - tp->mcfg = CFG_METHOD_15; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V2; - break; - case 0x2C800000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_16; - } else if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_17; - } else { - tp->mcfg = CFG_METHOD_17; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x48000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_18; - } else if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_19; - } else { - tp->mcfg = CFG_METHOD_19; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x48800000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_20; - } else { - tp->mcfg = CFG_METHOD_20; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x4C000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_21; - } else if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_22; - } else { - tp->mcfg = CFG_METHOD_22; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x50000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_23; - } else if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_27; - } else if (ICVerID == 0x00200000) { - tp->mcfg = CFG_METHOD_28; - } else { - tp->mcfg = CFG_METHOD_28; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x50800000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_24; - } else if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_25; - } else { - tp->mcfg = CFG_METHOD_25; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x5C800000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_26; - } else { - tp->mcfg = CFG_METHOD_26; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x54000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_29; - } else if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_30; - } else { - tp->mcfg = CFG_METHOD_30; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x54800000: - if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_31; - } else if (ICVerID == 0x00200000) { - tp->mcfg = CFG_METHOD_32; - } else if (ICVerID == 0x00300000) { - tp->mcfg = CFG_METHOD_33; - } else { - tp->mcfg = CFG_METHOD_33; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - default: - printk("unknown chip version (%x)\n",reg); - tp->mcfg = CFG_METHOD_DEFAULT; - tp->HwIcVerUnknown = TRUE; - tp->efuse_ver = EFUSE_NOT_SUPPORT; - break; - } -} - -static void -rtl8168_print_mac_version(struct rtl8168_private *tp) -{ - int i; - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { - if (tp->mcfg == rtl_chip_info[i].mcfg) { - dprintk("Realtek PCIe GbE Family Controller mcfg = %04d\n", - rtl_chip_info[i].mcfg); - return; - } - } - - dprintk("mac_version == Unknown\n"); -} - -static u8 rtl8168_calc_efuse_dummy_bit(u16 reg) -{ - int s,a,b; - u8 dummyBitPos = 0; - - - s=reg% 32; - a=s % 16; - b=s/16; - - if (s/16) { - dummyBitPos = (u8)(16-a); - } else { - dummyBitPos = (u8)a; - } - - return dummyBitPos; -} - -static u32 rtl8168_decode_efuse_cmd(struct rtl8168_private *tp, u32 DwCmd) -{ - u16 reg = (u16)((DwCmd & 0x00FE0000) >> 17); - u32 DummyPos = rtl8168_calc_efuse_dummy_bit(reg); - u32 DeCodeDwCmd = DwCmd; - u32 Dw17BitData; - - - if (tp->efuse_ver < 3) { - DeCodeDwCmd = (DwCmd>>(DummyPos+1))< 0) { - DeCodeDwCmd |= ((DwCmd<<(32-DummyPos))>>(32-DummyPos)); - } - } else { - reg = (u16)((DwCmd & 0x007F0000) >> 16); - DummyPos = rtl8168_calc_efuse_dummy_bit(reg); - Dw17BitData = ((DwCmd & BIT_23) >> 23); - Dw17BitData <<= 16; - Dw17BitData |= (DwCmd & 0x0000FFFF); - DeCodeDwCmd = (Dw17BitData>>(DummyPos+1))< 0) { - DeCodeDwCmd |= ((Dw17BitData<<(32-DummyPos))>>(32-DummyPos)); - } - } - - return DeCodeDwCmd; -} - -static u8 rtl8168_efuse_read(struct rtl8168_private *tp, u16 reg) -{ - u8 efuse_data = 0; - u32 temp; - int cnt; - - if (tp->efuse_ver == EFUSE_NOT_SUPPORT) - return EFUSE_READ_FAIL; - - if (tp->efuse_ver == EFUSE_SUPPORT_V1) { - temp = EFUSE_READ | ((reg & EFUSE_Reg_Mask) << EFUSE_Reg_Shift); - RTL_W32(tp, EFUSEAR, temp); - - cnt = 0; - do { - udelay(100); - temp = RTL_R32(tp, EFUSEAR); - cnt++; - } while (!(temp & EFUSE_READ_OK) && (cnt < EFUSE_Check_Cnt)); - - if (cnt == EFUSE_Check_Cnt) - efuse_data = EFUSE_READ_FAIL; - else - efuse_data = (u8)(RTL_R32(tp, EFUSEAR) & EFUSE_Data_Mask); - } else if (tp->efuse_ver == EFUSE_SUPPORT_V2) { - temp = (reg/2) & 0x03ff; - temp <<= 17; - temp |= EFUSE_READ; - RTL_W32(tp, EFUSEAR, temp); - - cnt = 0; - do { - udelay(100); - temp = RTL_R32(tp, EFUSEAR); - cnt++; - } while (!(temp & EFUSE_READ_OK) && (cnt < EFUSE_Check_Cnt)); - - if (cnt == EFUSE_Check_Cnt) { - efuse_data = EFUSE_READ_FAIL; - } else { - temp = RTL_R32(tp, EFUSEAR); - temp = rtl8168_decode_efuse_cmd(tp, temp); - - if (reg%2) { - temp >>= 8; - efuse_data = (u8)temp; - } else { - efuse_data = (u8)temp; - } - } - } else if (tp->efuse_ver == EFUSE_SUPPORT_V3) { - temp = (reg/2) & 0x03ff; - temp <<= 16; - temp |= EFUSE_READ_V3; - RTL_W32(tp, EFUSEAR, temp); - - cnt = 0; - do { - udelay(100); - temp = RTL_R32(tp, EFUSEAR); - cnt++; - } while ((temp & BIT_31) && (cnt < EFUSE_Check_Cnt)); - - if (cnt == EFUSE_Check_Cnt) { - efuse_data = EFUSE_READ_FAIL; - } else { - temp = RTL_R32(tp, EFUSEAR); - temp = rtl8168_decode_efuse_cmd(tp, temp); - - if (reg%2) { - temp >>= 8; - efuse_data = (u8)temp; - } else { - efuse_data = (u8)temp; - } - } - } - - udelay(20); - - return efuse_data; -} - -static void -rtl8168_tally_counter_addr_fill(struct rtl8168_private *tp) -{ - if (!tp->tally_paddr) - return; - - RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); - RTL_W32(tp, CounterAddrLow, (u64)tp->tally_paddr & (DMA_BIT_MASK(32))); -} - -static void -rtl8168_tally_counter_clear(struct rtl8168_private *tp) -{ - if (tp->mcfg == CFG_METHOD_1 || tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 ) - return; - - if (!tp->tally_paddr) - return; - - RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); - RTL_W32(tp, CounterAddrLow, ((u64)tp->tally_paddr & (DMA_BIT_MASK(32))) | CounterReset); -} - -static -u16 -rtl8168_get_phy_state(struct rtl8168_private *tp) -{ - u16 PhyState = 0xFF; - - if (HW_SUPPORT_UPS_MODE(tp) == FALSE) goto exit; - - switch (tp->HwSuppUpsVer) { - case 1: - PhyState = rtl8168_mdio_read_phy_ocp(tp, 0x0A42, 0x10); - PhyState &= 0x7; //bit[2:0] - break; - } - -exit: - return PhyState; -} - -static -bool -rtl8168_wait_phy_state_ready(struct rtl8168_private *tp, - u16 PhyState, - u32 MicroSecondTimeout - ) -{ - u16 TmpPhyState; - u32 WaitCount; - u32 i = 0; - bool PhyStateReady = TRUE; - - if (HW_SUPPORT_UPS_MODE(tp) == FALSE) goto exit; - - WaitCount = MicroSecondTimeout / 1000; - if (WaitCount == 0) WaitCount = 100; - - do { - TmpPhyState = rtl8168_get_phy_state(tp); - mdelay(1); - i++; - } while ((i < WaitCount) && (TmpPhyState != PhyState)); - - PhyStateReady = (i == WaitCount && TmpPhyState != PhyState) ? FALSE : TRUE; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(i == WaitCount); -#endif - -exit: - return PhyStateReady; -} - -static -bool -rtl8168_test_phy_ocp(struct rtl8168_private *tp) -{ - bool RestorePhyOcpReg = FALSE; - - if (tp->TestPhyOcpReg == FALSE) goto exit; - - if (tp->HwSuppEsdVer == 2) { - u16 PhyRegValue; - u8 ResetPhyType = 0; - - if (HW_PHY_STATUS_INI == rtl8168_get_phy_state(tp)) { - ResetPhyType = 1; - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0C40); - PhyRegValue = rtl8168_mdio_read(tp, 0x12); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - if ((PhyRegValue & 0x03) != 0x00) { - ResetPhyType = 2; - } - } - - if (ResetPhyType > 0) { - u32 WaitCnt; - struct net_device *dev = tp->dev; - - printk(KERN_ERR "%s: test_phy_ocp ResetPhyType = 0x%02x\n.\n", dev->name, ResetPhyType); - - rtl8168_mdio_write(tp, 0x1F, 0x0C41); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - mdelay(24); //24ms - - rtl8168_mdio_write(tp, 0x1F, 0x0C40); - PhyRegValue = rtl8168_mdio_read(tp, 0x12); - if ((PhyRegValue & 0x03) != 0x00) { - WaitCnt = 0; - while ((PhyRegValue & 0x03) != 0x00 && WaitCnt < 5) { - rtl8168_mdio_write(tp, 0x1F, 0x0C40); - rtl8168_set_eth_phy_bit(tp, 0x11, (BIT_15 | BIT_14)); - rtl8168_clear_eth_phy_bit(tp, 0x11, (BIT_15 | BIT_14)); - mdelay(100); - rtl8168_mdio_write(tp, 0x1F, 0x0C40); - PhyRegValue = rtl8168_mdio_read(tp, 0x12); - WaitCnt++; - } - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A46); - rtl8168_mdio_write(tp, 0x10, tp->BackupPhyFuseDout_15_0); - rtl8168_mdio_write(tp, 0x12, tp->BackupPhyFuseDout_47_32); - rtl8168_mdio_write(tp, 0x13, tp->BackupPhyFuseDout_63_48); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_wait_phy_state_ready(tp, HW_PHY_STATUS_INI, 5000000); - rtl8168_mdio_write(tp, 0x1F, 0x0A46); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_wait_phy_state_ready(tp, HW_PHY_STATUS_LAN_ON, 500000); - - tp->HwHasWrRamCodeToMicroP = FALSE; - - RestorePhyOcpReg = TRUE; - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - -exit: - return RestorePhyOcpReg; -} - -static int -rtl8168_is_ups_resume(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - return (rtl8168_mac_ocp_read(tp, 0xD408) & BIT_0); -} - -static void -rtl8168_clear_ups_resume_bit(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - rtl8168_mac_ocp_write(tp, 0xD408, rtl8168_mac_ocp_read(tp, 0xD408) & ~(BIT_0)); -} - -static void -rtl8168_wait_phy_ups_resume(struct net_device *dev, u16 PhyState) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 TmpPhyState; - int i = 0; - - do { - TmpPhyState = rtl8168_mdio_read_phy_ocp(tp, 0x0A42, 0x10); - TmpPhyState &= 0x7; - mdelay(1); - i++; - } while ((i < 100) && (TmpPhyState != PhyState)); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(i == 100); -#endif -} - -void -rtl8168_enable_now_is_oob(struct rtl8168_private *tp) -{ - if ( tp->HwSuppNowIsOobVer == 1 ) { - RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) | Now_is_oob); - } -} - -void -rtl8168_disable_now_is_oob(struct rtl8168_private *tp) -{ - if ( tp->HwSuppNowIsOobVer == 1 ) { - RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) & ~Now_is_oob); - } -} - -static void -rtl8168_switch_to_sgmii_mode( - struct rtl8168_private *tp -) -{ - if (FALSE == HW_SUPP_SERDES_PHY(tp)) return; - - switch (tp->HwSuppSerDesPhyVer) { - case 1: - rtl8168_mac_ocp_write(tp, 0xEB00, 0x2); - rtl8168_set_mcu_ocp_bit(tp, 0xEB16, BIT_1); - break; - } -} - -static void -rtl8168_exit_oob(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 data16; - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(AcceptErr | AcceptRunt | AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys)); - - if (HW_SUPP_SERDES_PHY(tp)) { - if (tp->HwSuppSerDesPhyVer == 1) { - rtl8168_switch_to_sgmii_mode(tp); - } - } - - if (HW_DASH_SUPPORT_DASH(tp)) { - rtl8168_driver_start(tp); - rtl8168_dash2_disable_txrx(dev); -#ifdef ENABLE_DASH_SUPPORT - DashHwInit(dev); -#endif - } - - //Disable realwow function - switch (tp->mcfg) { - case CFG_METHOD_18: - case CFG_METHOD_19: - RTL_W32(tp, MACOCP, 0xE5A90000); - RTL_W32(tp, MACOCP, 0xF2100010); - break; - case CFG_METHOD_20: - RTL_W32(tp, MACOCP, 0xE5A90000); - RTL_W32(tp, MACOCP, 0xE4640000); - RTL_W32(tp, MACOCP, 0xF2100010); - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - RTL_W32(tp, MACOCP, 0x605E0000); - RTL_W32(tp, MACOCP, (0xE05E << 16) | (RTL_R32(tp, MACOCP) & 0xFFFE)); - RTL_W32(tp, MACOCP, 0xE9720000); - RTL_W32(tp, MACOCP, 0xF2140010); - break; - case CFG_METHOD_26: - RTL_W32(tp, MACOCP, 0xE05E00FF); - RTL_W32(tp, MACOCP, 0xE9720000); - rtl8168_mac_ocp_write(tp, 0xE428, 0x0010); - break; - } - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8168_realwow_hw_init(dev); -#else - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - rtl8168_eri_write(tp, 0x174, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_mac_ocp_write(tp, 0xE428, 0x0010); - break; - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_eri_write(tp, 0x174, 2, 0x00FF, ERIAR_ExGMAC); - rtl8168_mac_ocp_write(tp, 0xE428, 0x0010); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: { - u32 csi_tmp; - csi_tmp = rtl8168_eri_read(tp, 0x174, 2, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_8); - csi_tmp |= (BIT_15); - rtl8168_eri_write(tp, 0x174, 2, csi_tmp, ERIAR_ExGMAC); - rtl8168_mac_ocp_write(tp, 0xE428, 0x0010); - } - break; - } -#endif //ENABLE_REALWOW_SUPPORT - - rtl8168_nic_reset(dev); - - switch (tp->mcfg) { - case CFG_METHOD_20: - rtl8168_wait_ll_share_fifo_ready(dev); - - data16 = rtl8168_mac_ocp_read(tp, 0xD4DE) | BIT_15; - rtl8168_mac_ocp_write(tp, 0xD4DE, data16); - - rtl8168_wait_ll_share_fifo_ready(dev); - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_disable_now_is_oob(tp); - - data16 = rtl8168_mac_ocp_read(tp, 0xE8DE) & ~BIT_14; - rtl8168_mac_ocp_write(tp, 0xE8DE, data16); - rtl8168_wait_ll_share_fifo_ready(dev); - - data16 = rtl8168_mac_ocp_read(tp, 0xE8DE) | BIT_15; - rtl8168_mac_ocp_write(tp, 0xE8DE, data16); - - rtl8168_wait_ll_share_fifo_ready(dev); - break; - } - - //wait ups resume (phy state 2) - if (HW_SUPPORT_UPS_MODE(tp)) - if (rtl8168_is_ups_resume(dev)) { - rtl8168_wait_phy_ups_resume(dev, HW_PHY_STATUS_EXT_INI); - rtl8168_clear_ups_resume_bit(dev); - } - -#ifdef ENABLE_FIBER_SUPPORT - if (HW_FIBER_MODE_ENABLED(tp)) - rtl8168_hw_init_fiber_nic(dev); -#endif //ENABLE_FIBER_SUPPORT -} - -void -rtl8168_hw_disable_mac_mcu_bps(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (tp->HwSuppAspmClkIntrLock) { - rtl8168_enable_cfg9346_write(tp); - rtl8168_hw_aspm_clkreq_enable(tp, false); - rtl8168_disable_cfg9346_write(tp); - } - - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mac_ocp_write(tp, 0xFC38, 0x0000); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mac_ocp_write(tp, 0xFC28, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC2E, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC30, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC32, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC34, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC36, 0x0000); - mdelay(3); - rtl8168_mac_ocp_write(tp, 0xFC26, 0x0000); - break; - } -} - -#ifndef ENABLE_USE_FIRMWARE_FILE -static void -rtl8168_set_mac_mcu_8168g_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - rtl8168_mac_ocp_write(tp, 0xE43C, 0x0000); - rtl8168_mac_ocp_write(tp, 0xE43E, 0x0000); - - rtl8168_mac_ocp_write(tp, 0xE434, 0x0004); - rtl8168_mac_ocp_write(tp, 0xE43C, 0x0004); - - rtl8168_hw_disable_mac_mcu_bps(dev); - - rtl8168_mac_ocp_write( tp, 0xF800, 0xE008 ); - rtl8168_mac_ocp_write( tp, 0xF802, 0xE01B ); - rtl8168_mac_ocp_write( tp, 0xF804, 0xE022 ); - rtl8168_mac_ocp_write( tp, 0xF806, 0xE094 ); - rtl8168_mac_ocp_write( tp, 0xF808, 0xE097 ); - rtl8168_mac_ocp_write( tp, 0xF80A, 0xE09A ); - rtl8168_mac_ocp_write( tp, 0xF80C, 0xE0B3 ); - rtl8168_mac_ocp_write( tp, 0xF80E, 0xE0BA ); - rtl8168_mac_ocp_write( tp, 0xF810, 0x49D2 ); - rtl8168_mac_ocp_write( tp, 0xF812, 0xF10D ); - rtl8168_mac_ocp_write( tp, 0xF814, 0x766C ); - rtl8168_mac_ocp_write( tp, 0xF816, 0x49E2 ); - rtl8168_mac_ocp_write( tp, 0xF818, 0xF00A ); - rtl8168_mac_ocp_write( tp, 0xF81A, 0x1EC0 ); - rtl8168_mac_ocp_write( tp, 0xF81C, 0x8EE1 ); - rtl8168_mac_ocp_write( tp, 0xF81E, 0xC60A ); - rtl8168_mac_ocp_write( tp, 0xF820, 0x77C0 ); - rtl8168_mac_ocp_write( tp, 0xF822, 0x4870 ); - rtl8168_mac_ocp_write( tp, 0xF824, 0x9FC0 ); - rtl8168_mac_ocp_write( tp, 0xF826, 0x1EA0 ); - rtl8168_mac_ocp_write( tp, 0xF828, 0xC707 ); - rtl8168_mac_ocp_write( tp, 0xF82A, 0x8EE1 ); - rtl8168_mac_ocp_write( tp, 0xF82C, 0x9D6C ); - rtl8168_mac_ocp_write( tp, 0xF82E, 0xC603 ); - rtl8168_mac_ocp_write( tp, 0xF830, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF832, 0xB416 ); - rtl8168_mac_ocp_write( tp, 0xF834, 0x0076 ); - rtl8168_mac_ocp_write( tp, 0xF836, 0xE86C ); - rtl8168_mac_ocp_write( tp, 0xF838, 0xC406 ); - rtl8168_mac_ocp_write( tp, 0xF83A, 0x7580 ); - rtl8168_mac_ocp_write( tp, 0xF83C, 0x4852 ); - rtl8168_mac_ocp_write( tp, 0xF83E, 0x8D80 ); - rtl8168_mac_ocp_write( tp, 0xF840, 0xC403 ); - rtl8168_mac_ocp_write( tp, 0xF842, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF844, 0xD3E0 ); - rtl8168_mac_ocp_write( tp, 0xF846, 0x02C8 ); - rtl8168_mac_ocp_write( tp, 0xF848, 0x8918 ); - rtl8168_mac_ocp_write( tp, 0xF84A, 0xE815 ); - rtl8168_mac_ocp_write( tp, 0xF84C, 0x1100 ); - rtl8168_mac_ocp_write( tp, 0xF84E, 0xF011 ); - rtl8168_mac_ocp_write( tp, 0xF850, 0xE812 ); - rtl8168_mac_ocp_write( tp, 0xF852, 0x4990 ); - rtl8168_mac_ocp_write( tp, 0xF854, 0xF002 ); - rtl8168_mac_ocp_write( tp, 0xF856, 0xE817 ); - rtl8168_mac_ocp_write( tp, 0xF858, 0xE80E ); - rtl8168_mac_ocp_write( tp, 0xF85A, 0x4992 ); - rtl8168_mac_ocp_write( tp, 0xF85C, 0xF002 ); - rtl8168_mac_ocp_write( tp, 0xF85E, 0xE80E ); - rtl8168_mac_ocp_write( tp, 0xF860, 0xE80A ); - rtl8168_mac_ocp_write( tp, 0xF862, 0x4993 ); - rtl8168_mac_ocp_write( tp, 0xF864, 0xF002 ); - rtl8168_mac_ocp_write( tp, 0xF866, 0xE818 ); - rtl8168_mac_ocp_write( tp, 0xF868, 0xE806 ); - rtl8168_mac_ocp_write( tp, 0xF86A, 0x4991 ); - rtl8168_mac_ocp_write( tp, 0xF86C, 0xF002 ); - rtl8168_mac_ocp_write( tp, 0xF86E, 0xE838 ); - rtl8168_mac_ocp_write( tp, 0xF870, 0xC25E ); - rtl8168_mac_ocp_write( tp, 0xF872, 0xBA00 ); - rtl8168_mac_ocp_write( tp, 0xF874, 0xC056 ); - rtl8168_mac_ocp_write( tp, 0xF876, 0x7100 ); - rtl8168_mac_ocp_write( tp, 0xF878, 0xFF80 ); - rtl8168_mac_ocp_write( tp, 0xF87A, 0x7100 ); - rtl8168_mac_ocp_write( tp, 0xF87C, 0x4892 ); - rtl8168_mac_ocp_write( tp, 0xF87E, 0x4813 ); - rtl8168_mac_ocp_write( tp, 0xF880, 0x8900 ); - rtl8168_mac_ocp_write( tp, 0xF882, 0xE00A ); - rtl8168_mac_ocp_write( tp, 0xF884, 0x7100 ); - rtl8168_mac_ocp_write( tp, 0xF886, 0x4890 ); - rtl8168_mac_ocp_write( tp, 0xF888, 0x4813 ); - rtl8168_mac_ocp_write( tp, 0xF88A, 0x8900 ); - rtl8168_mac_ocp_write( tp, 0xF88C, 0xC74B ); - rtl8168_mac_ocp_write( tp, 0xF88E, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF890, 0x48C2 ); - rtl8168_mac_ocp_write( tp, 0xF892, 0x4841 ); - rtl8168_mac_ocp_write( tp, 0xF894, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF896, 0xC746 ); - rtl8168_mac_ocp_write( tp, 0xF898, 0x74FC ); - rtl8168_mac_ocp_write( tp, 0xF89A, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF89C, 0xF120 ); - rtl8168_mac_ocp_write( tp, 0xF89E, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF8A0, 0xF11E ); - rtl8168_mac_ocp_write( tp, 0xF8A2, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF8A4, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF8A6, 0xF01B ); - rtl8168_mac_ocp_write( tp, 0xF8A8, 0x49C6 ); - rtl8168_mac_ocp_write( tp, 0xF8AA, 0xF119 ); - rtl8168_mac_ocp_write( tp, 0xF8AC, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF8AE, 0x49C4 ); - rtl8168_mac_ocp_write( tp, 0xF8B0, 0xF013 ); - rtl8168_mac_ocp_write( tp, 0xF8B2, 0xC536 ); - rtl8168_mac_ocp_write( tp, 0xF8B4, 0x74B0 ); - rtl8168_mac_ocp_write( tp, 0xF8B6, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF8B8, 0xF1FD ); - rtl8168_mac_ocp_write( tp, 0xF8BA, 0xC537 ); - rtl8168_mac_ocp_write( tp, 0xF8BC, 0xC434 ); - rtl8168_mac_ocp_write( tp, 0xF8BE, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF8C0, 0xC435 ); - rtl8168_mac_ocp_write( tp, 0xF8C2, 0x1C13 ); - rtl8168_mac_ocp_write( tp, 0xF8C4, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xF8C6, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xF8C8, 0xC52B ); - rtl8168_mac_ocp_write( tp, 0xF8CA, 0x74B0 ); - rtl8168_mac_ocp_write( tp, 0xF8CC, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF8CE, 0xF1FD ); - rtl8168_mac_ocp_write( tp, 0xF8D0, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF8D2, 0x48C4 ); - rtl8168_mac_ocp_write( tp, 0xF8D4, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF8D6, 0x7100 ); - rtl8168_mac_ocp_write( tp, 0xF8D8, 0x4893 ); - rtl8168_mac_ocp_write( tp, 0xF8DA, 0x8900 ); - rtl8168_mac_ocp_write( tp, 0xF8DC, 0xFF80 ); - rtl8168_mac_ocp_write( tp, 0xF8DE, 0xC520 ); - rtl8168_mac_ocp_write( tp, 0xF8E0, 0x74B0 ); - rtl8168_mac_ocp_write( tp, 0xF8E2, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF8E4, 0xF11C ); - rtl8168_mac_ocp_write( tp, 0xF8E6, 0xC71E ); - rtl8168_mac_ocp_write( tp, 0xF8E8, 0x74FC ); - rtl8168_mac_ocp_write( tp, 0xF8EA, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF8EC, 0xF118 ); - rtl8168_mac_ocp_write( tp, 0xF8EE, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF8F0, 0xF116 ); - rtl8168_mac_ocp_write( tp, 0xF8F2, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF8F4, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF8F6, 0xF013 ); - rtl8168_mac_ocp_write( tp, 0xF8F8, 0x48C3 ); - rtl8168_mac_ocp_write( tp, 0xF8FA, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF8FC, 0xC516 ); - rtl8168_mac_ocp_write( tp, 0xF8FE, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xF900, 0x49CE ); - rtl8168_mac_ocp_write( tp, 0xF902, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xF904, 0xC411 ); - rtl8168_mac_ocp_write( tp, 0xF906, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF908, 0xC411 ); - rtl8168_mac_ocp_write( tp, 0xF90A, 0x1C13 ); - rtl8168_mac_ocp_write( tp, 0xF90C, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xF90E, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xF910, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xF912, 0x49CF ); - rtl8168_mac_ocp_write( tp, 0xF914, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xF916, 0x7100 ); - rtl8168_mac_ocp_write( tp, 0xF918, 0x4891 ); - rtl8168_mac_ocp_write( tp, 0xF91A, 0x8900 ); - rtl8168_mac_ocp_write( tp, 0xF91C, 0xFF80 ); - rtl8168_mac_ocp_write( tp, 0xF91E, 0xE400 ); - rtl8168_mac_ocp_write( tp, 0xF920, 0xD3E0 ); - rtl8168_mac_ocp_write( tp, 0xF922, 0xE000 ); - rtl8168_mac_ocp_write( tp, 0xF924, 0x0481 ); - rtl8168_mac_ocp_write( tp, 0xF926, 0x0C81 ); - rtl8168_mac_ocp_write( tp, 0xF928, 0xDE20 ); - rtl8168_mac_ocp_write( tp, 0xF92A, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xF92C, 0x0992 ); - rtl8168_mac_ocp_write( tp, 0xF92E, 0x1B76 ); - rtl8168_mac_ocp_write( tp, 0xF930, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF932, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF934, 0x059C ); - rtl8168_mac_ocp_write( tp, 0xF936, 0x1B76 ); - rtl8168_mac_ocp_write( tp, 0xF938, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF93A, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF93C, 0x065A ); - rtl8168_mac_ocp_write( tp, 0xF93E, 0xB400 ); - rtl8168_mac_ocp_write( tp, 0xF940, 0x18DE ); - rtl8168_mac_ocp_write( tp, 0xF942, 0x2008 ); - rtl8168_mac_ocp_write( tp, 0xF944, 0x4001 ); - rtl8168_mac_ocp_write( tp, 0xF946, 0xF10F ); - rtl8168_mac_ocp_write( tp, 0xF948, 0x7342 ); - rtl8168_mac_ocp_write( tp, 0xF94A, 0x1880 ); - rtl8168_mac_ocp_write( tp, 0xF94C, 0x2008 ); - rtl8168_mac_ocp_write( tp, 0xF94E, 0x0009 ); - rtl8168_mac_ocp_write( tp, 0xF950, 0x4018 ); - rtl8168_mac_ocp_write( tp, 0xF952, 0xF109 ); - rtl8168_mac_ocp_write( tp, 0xF954, 0x7340 ); - rtl8168_mac_ocp_write( tp, 0xF956, 0x25BC ); - rtl8168_mac_ocp_write( tp, 0xF958, 0x130F ); - rtl8168_mac_ocp_write( tp, 0xF95A, 0xF105 ); - rtl8168_mac_ocp_write( tp, 0xF95C, 0xC00A ); - rtl8168_mac_ocp_write( tp, 0xF95E, 0x7300 ); - rtl8168_mac_ocp_write( tp, 0xF960, 0x4831 ); - rtl8168_mac_ocp_write( tp, 0xF962, 0x9B00 ); - rtl8168_mac_ocp_write( tp, 0xF964, 0xB000 ); - rtl8168_mac_ocp_write( tp, 0xF966, 0x7340 ); - rtl8168_mac_ocp_write( tp, 0xF968, 0x8320 ); - rtl8168_mac_ocp_write( tp, 0xF96A, 0xC302 ); - rtl8168_mac_ocp_write( tp, 0xF96C, 0xBB00 ); - rtl8168_mac_ocp_write( tp, 0xF96E, 0x0C12 ); - rtl8168_mac_ocp_write( tp, 0xF970, 0xE860 ); - rtl8168_mac_ocp_write( tp, 0xF972, 0xC406 ); - rtl8168_mac_ocp_write( tp, 0xF974, 0x7580 ); - rtl8168_mac_ocp_write( tp, 0xF976, 0x4851 ); - rtl8168_mac_ocp_write( tp, 0xF978, 0x8D80 ); - rtl8168_mac_ocp_write( tp, 0xF97A, 0xC403 ); - rtl8168_mac_ocp_write( tp, 0xF97C, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF97E, 0xD3E0 ); - rtl8168_mac_ocp_write( tp, 0xF980, 0x02C8 ); - rtl8168_mac_ocp_write( tp, 0xF982, 0xC406 ); - rtl8168_mac_ocp_write( tp, 0xF984, 0x7580 ); - rtl8168_mac_ocp_write( tp, 0xF986, 0x4850 ); - rtl8168_mac_ocp_write( tp, 0xF988, 0x8D80 ); - rtl8168_mac_ocp_write( tp, 0xF98A, 0xC403 ); - rtl8168_mac_ocp_write( tp, 0xF98C, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF98E, 0xD3E0 ); - rtl8168_mac_ocp_write( tp, 0xF990, 0x0298 ); - - rtl8168_mac_ocp_write( tp, 0xDE30, 0x0080 ); - - rtl8168_mac_ocp_write( tp, 0xFC26, 0x8000 ); - - rtl8168_mac_ocp_write( tp, 0xFC28, 0x0075 ); - rtl8168_mac_ocp_write( tp, 0xFC2A, 0x02B1 ); - rtl8168_mac_ocp_write( tp, 0xFC2C, 0x0991 ); - rtl8168_mac_ocp_write( tp, 0xFC2E, 0x059B ); - rtl8168_mac_ocp_write( tp, 0xFC30, 0x0659 ); - rtl8168_mac_ocp_write( tp, 0xFC32, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFC34, 0x02C7 ); - rtl8168_mac_ocp_write( tp, 0xFC36, 0x0279 ); -} - -static void -rtl8168_set_mac_mcu_8168gu_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - rtl8168_hw_disable_mac_mcu_bps(dev); - - rtl8168_mac_ocp_write( tp, 0xF800, 0xE008 ); - rtl8168_mac_ocp_write( tp, 0xF802, 0xE011 ); - rtl8168_mac_ocp_write( tp, 0xF804, 0xE015 ); - rtl8168_mac_ocp_write( tp, 0xF806, 0xE018 ); - rtl8168_mac_ocp_write( tp, 0xF808, 0xE01B ); - rtl8168_mac_ocp_write( tp, 0xF80A, 0xE027 ); - rtl8168_mac_ocp_write( tp, 0xF80C, 0xE043 ); - rtl8168_mac_ocp_write( tp, 0xF80E, 0xE065 ); - rtl8168_mac_ocp_write( tp, 0xF810, 0x49E2 ); - rtl8168_mac_ocp_write( tp, 0xF812, 0xF005 ); - rtl8168_mac_ocp_write( tp, 0xF814, 0x49EA ); - rtl8168_mac_ocp_write( tp, 0xF816, 0xF003 ); - rtl8168_mac_ocp_write( tp, 0xF818, 0xC404 ); - rtl8168_mac_ocp_write( tp, 0xF81A, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF81C, 0xC403 ); - rtl8168_mac_ocp_write( tp, 0xF81E, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF820, 0x0496 ); - rtl8168_mac_ocp_write( tp, 0xF822, 0x051A ); - rtl8168_mac_ocp_write( tp, 0xF824, 0x1D01 ); - rtl8168_mac_ocp_write( tp, 0xF826, 0x8DE8 ); - rtl8168_mac_ocp_write( tp, 0xF828, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF82A, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF82C, 0x0206 ); - rtl8168_mac_ocp_write( tp, 0xF82E, 0x1B76 ); - rtl8168_mac_ocp_write( tp, 0xF830, 0xC202 ); - rtl8168_mac_ocp_write( tp, 0xF832, 0xBA00 ); - rtl8168_mac_ocp_write( tp, 0xF834, 0x058A ); - rtl8168_mac_ocp_write( tp, 0xF836, 0x1B76 ); - rtl8168_mac_ocp_write( tp, 0xF838, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF83A, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF83C, 0x0648 ); - rtl8168_mac_ocp_write( tp, 0xF83E, 0x74E6 ); - rtl8168_mac_ocp_write( tp, 0xF840, 0x1B78 ); - rtl8168_mac_ocp_write( tp, 0xF842, 0x46DC ); - rtl8168_mac_ocp_write( tp, 0xF844, 0x1300 ); - rtl8168_mac_ocp_write( tp, 0xF846, 0xF005 ); - rtl8168_mac_ocp_write( tp, 0xF848, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF84A, 0x48C3 ); - rtl8168_mac_ocp_write( tp, 0xF84C, 0x48C4 ); - rtl8168_mac_ocp_write( tp, 0xF84E, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF850, 0x64E7 ); - rtl8168_mac_ocp_write( tp, 0xF852, 0xC302 ); - rtl8168_mac_ocp_write( tp, 0xF854, 0xBB00 ); - rtl8168_mac_ocp_write( tp, 0xF856, 0x068E ); - rtl8168_mac_ocp_write( tp, 0xF858, 0x74E4 ); - rtl8168_mac_ocp_write( tp, 0xF85A, 0x49C5 ); - rtl8168_mac_ocp_write( tp, 0xF85C, 0xF106 ); - rtl8168_mac_ocp_write( tp, 0xF85E, 0x49C6 ); - rtl8168_mac_ocp_write( tp, 0xF860, 0xF107 ); - rtl8168_mac_ocp_write( tp, 0xF862, 0x48C8 ); - rtl8168_mac_ocp_write( tp, 0xF864, 0x48C9 ); - rtl8168_mac_ocp_write( tp, 0xF866, 0xE011 ); - rtl8168_mac_ocp_write( tp, 0xF868, 0x48C9 ); - rtl8168_mac_ocp_write( tp, 0xF86A, 0x4848 ); - rtl8168_mac_ocp_write( tp, 0xF86C, 0xE00E ); - rtl8168_mac_ocp_write( tp, 0xF86E, 0x4848 ); - rtl8168_mac_ocp_write( tp, 0xF870, 0x49C7 ); - rtl8168_mac_ocp_write( tp, 0xF872, 0xF00A ); - rtl8168_mac_ocp_write( tp, 0xF874, 0x48C9 ); - rtl8168_mac_ocp_write( tp, 0xF876, 0xC60D ); - rtl8168_mac_ocp_write( tp, 0xF878, 0x1D1F ); - rtl8168_mac_ocp_write( tp, 0xF87A, 0x8DC2 ); - rtl8168_mac_ocp_write( tp, 0xF87C, 0x1D00 ); - rtl8168_mac_ocp_write( tp, 0xF87E, 0x8DC3 ); - rtl8168_mac_ocp_write( tp, 0xF880, 0x1D11 ); - rtl8168_mac_ocp_write( tp, 0xF882, 0x8DC0 ); - rtl8168_mac_ocp_write( tp, 0xF884, 0xE002 ); - rtl8168_mac_ocp_write( tp, 0xF886, 0x4849 ); - rtl8168_mac_ocp_write( tp, 0xF888, 0x94E5 ); - rtl8168_mac_ocp_write( tp, 0xF88A, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF88C, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF88E, 0x0238 ); - rtl8168_mac_ocp_write( tp, 0xF890, 0xE434 ); - rtl8168_mac_ocp_write( tp, 0xF892, 0x49D9 ); - rtl8168_mac_ocp_write( tp, 0xF894, 0xF01B ); - rtl8168_mac_ocp_write( tp, 0xF896, 0xC31E ); - rtl8168_mac_ocp_write( tp, 0xF898, 0x7464 ); - rtl8168_mac_ocp_write( tp, 0xF89A, 0x49C4 ); - rtl8168_mac_ocp_write( tp, 0xF89C, 0xF114 ); - rtl8168_mac_ocp_write( tp, 0xF89E, 0xC31B ); - rtl8168_mac_ocp_write( tp, 0xF8A0, 0x6460 ); - rtl8168_mac_ocp_write( tp, 0xF8A2, 0x14FA ); - rtl8168_mac_ocp_write( tp, 0xF8A4, 0xFA02 ); - rtl8168_mac_ocp_write( tp, 0xF8A6, 0xE00F ); - rtl8168_mac_ocp_write( tp, 0xF8A8, 0xC317 ); - rtl8168_mac_ocp_write( tp, 0xF8AA, 0x7460 ); - rtl8168_mac_ocp_write( tp, 0xF8AC, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF8AE, 0xF10B ); - rtl8168_mac_ocp_write( tp, 0xF8B0, 0xC311 ); - rtl8168_mac_ocp_write( tp, 0xF8B2, 0x7462 ); - rtl8168_mac_ocp_write( tp, 0xF8B4, 0x48C1 ); - rtl8168_mac_ocp_write( tp, 0xF8B6, 0x9C62 ); - rtl8168_mac_ocp_write( tp, 0xF8B8, 0x4841 ); - rtl8168_mac_ocp_write( tp, 0xF8BA, 0x9C62 ); - rtl8168_mac_ocp_write( tp, 0xF8BC, 0xC30A ); - rtl8168_mac_ocp_write( tp, 0xF8BE, 0x1C04 ); - rtl8168_mac_ocp_write( tp, 0xF8C0, 0x8C60 ); - rtl8168_mac_ocp_write( tp, 0xF8C2, 0xE004 ); - rtl8168_mac_ocp_write( tp, 0xF8C4, 0x1C15 ); - rtl8168_mac_ocp_write( tp, 0xF8C6, 0xC305 ); - rtl8168_mac_ocp_write( tp, 0xF8C8, 0x8C60 ); - rtl8168_mac_ocp_write( tp, 0xF8CA, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF8CC, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF8CE, 0x0374 ); - rtl8168_mac_ocp_write( tp, 0xF8D0, 0xE434 ); - rtl8168_mac_ocp_write( tp, 0xF8D2, 0xE030 ); - rtl8168_mac_ocp_write( tp, 0xF8D4, 0xE61C ); - rtl8168_mac_ocp_write( tp, 0xF8D6, 0xE906 ); - rtl8168_mac_ocp_write( tp, 0xF8D8, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF8DA, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF8DC, 0x0000 ); - - rtl8168_mac_ocp_write( tp, 0xFC26, 0x8000 ); - - rtl8168_mac_ocp_write( tp, 0xFC28, 0x0493 ); - rtl8168_mac_ocp_write( tp, 0xFC2A, 0x0205 ); - rtl8168_mac_ocp_write( tp, 0xFC2C, 0x0589 ); - rtl8168_mac_ocp_write( tp, 0xFC2E, 0x0647 ); - rtl8168_mac_ocp_write( tp, 0xFC30, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFC32, 0x0215 ); - rtl8168_mac_ocp_write( tp, 0xFC34, 0x0285 ); -} - -static void -rtl8168_set_mac_mcu_8168gu_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - rtl8168_hw_disable_mac_mcu_bps(dev); - - rtl8168_mac_ocp_write( tp, 0xF800, 0xE008 ); - rtl8168_mac_ocp_write( tp, 0xF802, 0xE00A ); - rtl8168_mac_ocp_write( tp, 0xF804, 0xE00D ); - rtl8168_mac_ocp_write( tp, 0xF806, 0xE02F ); - rtl8168_mac_ocp_write( tp, 0xF808, 0xE031 ); - rtl8168_mac_ocp_write( tp, 0xF80A, 0xE038 ); - rtl8168_mac_ocp_write( tp, 0xF80C, 0xE03A ); - rtl8168_mac_ocp_write( tp, 0xF80E, 0xE051 ); - rtl8168_mac_ocp_write( tp, 0xF810, 0xC202 ); - rtl8168_mac_ocp_write( tp, 0xF812, 0xBA00 ); - rtl8168_mac_ocp_write( tp, 0xF814, 0x0DFC ); - rtl8168_mac_ocp_write( tp, 0xF816, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xF818, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF81A, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF81C, 0x0A30 ); - rtl8168_mac_ocp_write( tp, 0xF81E, 0x49D9 ); - rtl8168_mac_ocp_write( tp, 0xF820, 0xF019 ); - rtl8168_mac_ocp_write( tp, 0xF822, 0xC520 ); - rtl8168_mac_ocp_write( tp, 0xF824, 0x64A5 ); - rtl8168_mac_ocp_write( tp, 0xF826, 0x1400 ); - rtl8168_mac_ocp_write( tp, 0xF828, 0xF007 ); - rtl8168_mac_ocp_write( tp, 0xF82A, 0x0C01 ); - rtl8168_mac_ocp_write( tp, 0xF82C, 0x8CA5 ); - rtl8168_mac_ocp_write( tp, 0xF82E, 0x1C15 ); - rtl8168_mac_ocp_write( tp, 0xF830, 0xC515 ); - rtl8168_mac_ocp_write( tp, 0xF832, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF834, 0xE00F ); - rtl8168_mac_ocp_write( tp, 0xF836, 0xC513 ); - rtl8168_mac_ocp_write( tp, 0xF838, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF83A, 0x48C8 ); - rtl8168_mac_ocp_write( tp, 0xF83C, 0x48CA ); - rtl8168_mac_ocp_write( tp, 0xF83E, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF840, 0xC510 ); - rtl8168_mac_ocp_write( tp, 0xF842, 0x1B00 ); - rtl8168_mac_ocp_write( tp, 0xF844, 0x9BA0 ); - rtl8168_mac_ocp_write( tp, 0xF846, 0x1B1C ); - rtl8168_mac_ocp_write( tp, 0xF848, 0x483F ); - rtl8168_mac_ocp_write( tp, 0xF84A, 0x9BA2 ); - rtl8168_mac_ocp_write( tp, 0xF84C, 0x1B04 ); - rtl8168_mac_ocp_write( tp, 0xF84E, 0xC506 ); - rtl8168_mac_ocp_write( tp, 0xF850, 0x9BA0 ); - rtl8168_mac_ocp_write( tp, 0xF852, 0xC603 ); - rtl8168_mac_ocp_write( tp, 0xF854, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF856, 0x0298 ); - rtl8168_mac_ocp_write( tp, 0xF858, 0x03DE ); - rtl8168_mac_ocp_write( tp, 0xF85A, 0xE434 ); - rtl8168_mac_ocp_write( tp, 0xF85C, 0xE096 ); - rtl8168_mac_ocp_write( tp, 0xF85E, 0xE860 ); - rtl8168_mac_ocp_write( tp, 0xF860, 0xDE20 ); - rtl8168_mac_ocp_write( tp, 0xF862, 0xD3C0 ); - rtl8168_mac_ocp_write( tp, 0xF864, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF866, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF868, 0x0A64 ); - rtl8168_mac_ocp_write( tp, 0xF86A, 0xC707 ); - rtl8168_mac_ocp_write( tp, 0xF86C, 0x1D00 ); - rtl8168_mac_ocp_write( tp, 0xF86E, 0x8DE2 ); - rtl8168_mac_ocp_write( tp, 0xF870, 0x48C1 ); - rtl8168_mac_ocp_write( tp, 0xF872, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF874, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF876, 0x00AA ); - rtl8168_mac_ocp_write( tp, 0xF878, 0xE0C0 ); - rtl8168_mac_ocp_write( tp, 0xF87A, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF87C, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF87E, 0x0132 ); - rtl8168_mac_ocp_write( tp, 0xF880, 0xC50C ); - rtl8168_mac_ocp_write( tp, 0xF882, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xF884, 0x49CE ); - rtl8168_mac_ocp_write( tp, 0xF886, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xF888, 0x1C00 ); - rtl8168_mac_ocp_write( tp, 0xF88A, 0x9EA0 ); - rtl8168_mac_ocp_write( tp, 0xF88C, 0x1C1C ); - rtl8168_mac_ocp_write( tp, 0xF88E, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xF890, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xF892, 0xC402 ); - rtl8168_mac_ocp_write( tp, 0xF894, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF896, 0x0AFA ); - rtl8168_mac_ocp_write( tp, 0xF898, 0xDE20 ); - rtl8168_mac_ocp_write( tp, 0xF89A, 0xE000 ); - rtl8168_mac_ocp_write( tp, 0xF89C, 0xE092 ); - rtl8168_mac_ocp_write( tp, 0xF89E, 0xE430 ); - rtl8168_mac_ocp_write( tp, 0xF8A0, 0xDE20 ); - rtl8168_mac_ocp_write( tp, 0xF8A2, 0xE0C0 ); - rtl8168_mac_ocp_write( tp, 0xF8A4, 0xE860 ); - rtl8168_mac_ocp_write( tp, 0xF8A6, 0xE84C ); - rtl8168_mac_ocp_write( tp, 0xF8A8, 0xB400 ); - rtl8168_mac_ocp_write( tp, 0xF8AA, 0xB430 ); - rtl8168_mac_ocp_write( tp, 0xF8AC, 0xE410 ); - rtl8168_mac_ocp_write( tp, 0xF8AE, 0xC0AE ); - rtl8168_mac_ocp_write( tp, 0xF8B0, 0xB407 ); - rtl8168_mac_ocp_write( tp, 0xF8B2, 0xB406 ); - rtl8168_mac_ocp_write( tp, 0xF8B4, 0xB405 ); - rtl8168_mac_ocp_write( tp, 0xF8B6, 0xB404 ); - rtl8168_mac_ocp_write( tp, 0xF8B8, 0xB403 ); - rtl8168_mac_ocp_write( tp, 0xF8BA, 0xB402 ); - rtl8168_mac_ocp_write( tp, 0xF8BC, 0xB401 ); - rtl8168_mac_ocp_write( tp, 0xF8BE, 0xC7EE ); - rtl8168_mac_ocp_write( tp, 0xF8C0, 0x76F4 ); - rtl8168_mac_ocp_write( tp, 0xF8C2, 0xC2ED ); - rtl8168_mac_ocp_write( tp, 0xF8C4, 0xC3ED ); - rtl8168_mac_ocp_write( tp, 0xF8C6, 0xC1EF ); - rtl8168_mac_ocp_write( tp, 0xF8C8, 0xC5F3 ); - rtl8168_mac_ocp_write( tp, 0xF8CA, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF8CC, 0x49CD ); - rtl8168_mac_ocp_write( tp, 0xF8CE, 0xF001 ); - rtl8168_mac_ocp_write( tp, 0xF8D0, 0xC5EE ); - rtl8168_mac_ocp_write( tp, 0xF8D2, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF8D4, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF8D6, 0xF105 ); - rtl8168_mac_ocp_write( tp, 0xF8D8, 0xC5E4 ); - rtl8168_mac_ocp_write( tp, 0xF8DA, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xF8DC, 0x49CE ); - rtl8168_mac_ocp_write( tp, 0xF8DE, 0xF00B ); - rtl8168_mac_ocp_write( tp, 0xF8E0, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xF8E2, 0x484B ); - rtl8168_mac_ocp_write( tp, 0xF8E4, 0x9C44 ); - rtl8168_mac_ocp_write( tp, 0xF8E6, 0x1C10 ); - rtl8168_mac_ocp_write( tp, 0xF8E8, 0x9C62 ); - rtl8168_mac_ocp_write( tp, 0xF8EA, 0x1C11 ); - rtl8168_mac_ocp_write( tp, 0xF8EC, 0x8C60 ); - rtl8168_mac_ocp_write( tp, 0xF8EE, 0x1C00 ); - rtl8168_mac_ocp_write( tp, 0xF8F0, 0x9CF6 ); - rtl8168_mac_ocp_write( tp, 0xF8F2, 0xE0EC ); - rtl8168_mac_ocp_write( tp, 0xF8F4, 0x49E7 ); - rtl8168_mac_ocp_write( tp, 0xF8F6, 0xF016 ); - rtl8168_mac_ocp_write( tp, 0xF8F8, 0x1D80 ); - rtl8168_mac_ocp_write( tp, 0xF8FA, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xF8FC, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF8FE, 0x4843 ); - rtl8168_mac_ocp_write( tp, 0xF900, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF902, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF904, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF906, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xF908, 0x48C8 ); - rtl8168_mac_ocp_write( tp, 0xF90A, 0x48C9 ); - rtl8168_mac_ocp_write( tp, 0xF90C, 0x48CA ); - rtl8168_mac_ocp_write( tp, 0xF90E, 0x9C44 ); - rtl8168_mac_ocp_write( tp, 0xF910, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF912, 0x4844 ); - rtl8168_mac_ocp_write( tp, 0xF914, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF916, 0x1E01 ); - rtl8168_mac_ocp_write( tp, 0xF918, 0xE8DB ); - rtl8168_mac_ocp_write( tp, 0xF91A, 0x7420 ); - rtl8168_mac_ocp_write( tp, 0xF91C, 0x48C1 ); - rtl8168_mac_ocp_write( tp, 0xF91E, 0x9C20 ); - rtl8168_mac_ocp_write( tp, 0xF920, 0xE0D5 ); - rtl8168_mac_ocp_write( tp, 0xF922, 0x49E6 ); - rtl8168_mac_ocp_write( tp, 0xF924, 0xF02A ); - rtl8168_mac_ocp_write( tp, 0xF926, 0x1D40 ); - rtl8168_mac_ocp_write( tp, 0xF928, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xF92A, 0x74FC ); - rtl8168_mac_ocp_write( tp, 0xF92C, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF92E, 0xF124 ); - rtl8168_mac_ocp_write( tp, 0xF930, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF932, 0xF122 ); - rtl8168_mac_ocp_write( tp, 0xF934, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF936, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF938, 0xF01F ); - rtl8168_mac_ocp_write( tp, 0xF93A, 0xE8D3 ); - rtl8168_mac_ocp_write( tp, 0xF93C, 0x48C4 ); - rtl8168_mac_ocp_write( tp, 0xF93E, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF940, 0x1E00 ); - rtl8168_mac_ocp_write( tp, 0xF942, 0xE8C6 ); - rtl8168_mac_ocp_write( tp, 0xF944, 0xC5B1 ); - rtl8168_mac_ocp_write( tp, 0xF946, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF948, 0x49C3 ); - rtl8168_mac_ocp_write( tp, 0xF94A, 0xF016 ); - rtl8168_mac_ocp_write( tp, 0xF94C, 0xC5AF ); - rtl8168_mac_ocp_write( tp, 0xF94E, 0x74A4 ); - rtl8168_mac_ocp_write( tp, 0xF950, 0x49C2 ); - rtl8168_mac_ocp_write( tp, 0xF952, 0xF005 ); - rtl8168_mac_ocp_write( tp, 0xF954, 0xC5AA ); - rtl8168_mac_ocp_write( tp, 0xF956, 0x74B2 ); - rtl8168_mac_ocp_write( tp, 0xF958, 0x49C9 ); - rtl8168_mac_ocp_write( tp, 0xF95A, 0xF10E ); - rtl8168_mac_ocp_write( tp, 0xF95C, 0xC5A6 ); - rtl8168_mac_ocp_write( tp, 0xF95E, 0x74A8 ); - rtl8168_mac_ocp_write( tp, 0xF960, 0x4845 ); - rtl8168_mac_ocp_write( tp, 0xF962, 0x4846 ); - rtl8168_mac_ocp_write( tp, 0xF964, 0x4847 ); - rtl8168_mac_ocp_write( tp, 0xF966, 0x4848 ); - rtl8168_mac_ocp_write( tp, 0xF968, 0x9CA8 ); - rtl8168_mac_ocp_write( tp, 0xF96A, 0x74B2 ); - rtl8168_mac_ocp_write( tp, 0xF96C, 0x4849 ); - rtl8168_mac_ocp_write( tp, 0xF96E, 0x9CB2 ); - rtl8168_mac_ocp_write( tp, 0xF970, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF972, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xF974, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF976, 0xE0AA ); - rtl8168_mac_ocp_write( tp, 0xF978, 0x49E4 ); - rtl8168_mac_ocp_write( tp, 0xF97A, 0xF018 ); - rtl8168_mac_ocp_write( tp, 0xF97C, 0x1D10 ); - rtl8168_mac_ocp_write( tp, 0xF97E, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xF980, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF982, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF984, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF986, 0x4843 ); - rtl8168_mac_ocp_write( tp, 0xF988, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF98A, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF98C, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF98E, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF990, 0x4844 ); - rtl8168_mac_ocp_write( tp, 0xF992, 0x4842 ); - rtl8168_mac_ocp_write( tp, 0xF994, 0x4841 ); - rtl8168_mac_ocp_write( tp, 0xF996, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF998, 0x1E01 ); - rtl8168_mac_ocp_write( tp, 0xF99A, 0xE89A ); - rtl8168_mac_ocp_write( tp, 0xF99C, 0x7420 ); - rtl8168_mac_ocp_write( tp, 0xF99E, 0x4841 ); - rtl8168_mac_ocp_write( tp, 0xF9A0, 0x9C20 ); - rtl8168_mac_ocp_write( tp, 0xF9A2, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xF9A4, 0x4848 ); - rtl8168_mac_ocp_write( tp, 0xF9A6, 0x9C44 ); - rtl8168_mac_ocp_write( tp, 0xF9A8, 0xE091 ); - rtl8168_mac_ocp_write( tp, 0xF9AA, 0x49E5 ); - rtl8168_mac_ocp_write( tp, 0xF9AC, 0xF03E ); - rtl8168_mac_ocp_write( tp, 0xF9AE, 0x1D20 ); - rtl8168_mac_ocp_write( tp, 0xF9B0, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xF9B2, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF9B4, 0x48C2 ); - rtl8168_mac_ocp_write( tp, 0xF9B6, 0x4841 ); - rtl8168_mac_ocp_write( tp, 0xF9B8, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF9BA, 0x1E01 ); - rtl8168_mac_ocp_write( tp, 0xF9BC, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xF9BE, 0x49CA ); - rtl8168_mac_ocp_write( tp, 0xF9C0, 0xF103 ); - rtl8168_mac_ocp_write( tp, 0xF9C2, 0x49C2 ); - rtl8168_mac_ocp_write( tp, 0xF9C4, 0xF00C ); - rtl8168_mac_ocp_write( tp, 0xF9C6, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF9C8, 0xF004 ); - rtl8168_mac_ocp_write( tp, 0xF9CA, 0x6447 ); - rtl8168_mac_ocp_write( tp, 0xF9CC, 0x2244 ); - rtl8168_mac_ocp_write( tp, 0xF9CE, 0xE002 ); - rtl8168_mac_ocp_write( tp, 0xF9D0, 0x1C01 ); - rtl8168_mac_ocp_write( tp, 0xF9D2, 0x9C62 ); - rtl8168_mac_ocp_write( tp, 0xF9D4, 0x1C11 ); - rtl8168_mac_ocp_write( tp, 0xF9D6, 0x8C60 ); - rtl8168_mac_ocp_write( tp, 0xF9D8, 0x1C00 ); - rtl8168_mac_ocp_write( tp, 0xF9DA, 0x9CF6 ); - rtl8168_mac_ocp_write( tp, 0xF9DC, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xF9DE, 0x49C8 ); - rtl8168_mac_ocp_write( tp, 0xF9E0, 0xF01D ); - rtl8168_mac_ocp_write( tp, 0xF9E2, 0x74FC ); - rtl8168_mac_ocp_write( tp, 0xF9E4, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF9E6, 0xF11A ); - rtl8168_mac_ocp_write( tp, 0xF9E8, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF9EA, 0xF118 ); - rtl8168_mac_ocp_write( tp, 0xF9EC, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF9EE, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF9F0, 0xF015 ); - rtl8168_mac_ocp_write( tp, 0xF9F2, 0x49C6 ); - rtl8168_mac_ocp_write( tp, 0xF9F4, 0xF113 ); - rtl8168_mac_ocp_write( tp, 0xF9F6, 0xE875 ); - rtl8168_mac_ocp_write( tp, 0xF9F8, 0x48C4 ); - rtl8168_mac_ocp_write( tp, 0xF9FA, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF9FC, 0x7420 ); - rtl8168_mac_ocp_write( tp, 0xF9FE, 0x48C1 ); - rtl8168_mac_ocp_write( tp, 0xFA00, 0x9C20 ); - rtl8168_mac_ocp_write( tp, 0xFA02, 0xC50A ); - rtl8168_mac_ocp_write( tp, 0xFA04, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFA06, 0x8CA5 ); - rtl8168_mac_ocp_write( tp, 0xFA08, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xFA0A, 0xC505 ); - rtl8168_mac_ocp_write( tp, 0xFA0C, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xFA0E, 0x1C11 ); - rtl8168_mac_ocp_write( tp, 0xFA10, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xFA12, 0xE00A ); - rtl8168_mac_ocp_write( tp, 0xFA14, 0xE434 ); - rtl8168_mac_ocp_write( tp, 0xFA16, 0xD3C0 ); - rtl8168_mac_ocp_write( tp, 0xFA18, 0xDC00 ); - rtl8168_mac_ocp_write( tp, 0xFA1A, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xFA1C, 0x49CA ); - rtl8168_mac_ocp_write( tp, 0xFA1E, 0xF004 ); - rtl8168_mac_ocp_write( tp, 0xFA20, 0x48CA ); - rtl8168_mac_ocp_write( tp, 0xFA22, 0x9C44 ); - rtl8168_mac_ocp_write( tp, 0xFA24, 0xE855 ); - rtl8168_mac_ocp_write( tp, 0xFA26, 0xE052 ); - rtl8168_mac_ocp_write( tp, 0xFA28, 0x49E8 ); - rtl8168_mac_ocp_write( tp, 0xFA2A, 0xF024 ); - rtl8168_mac_ocp_write( tp, 0xFA2C, 0x1D01 ); - rtl8168_mac_ocp_write( tp, 0xFA2E, 0x8DF5 ); - rtl8168_mac_ocp_write( tp, 0xFA30, 0x7440 ); - rtl8168_mac_ocp_write( tp, 0xFA32, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xFA34, 0xF11E ); - rtl8168_mac_ocp_write( tp, 0xFA36, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xFA38, 0x49C8 ); - rtl8168_mac_ocp_write( tp, 0xFA3A, 0xF01B ); - rtl8168_mac_ocp_write( tp, 0xFA3C, 0x49CA ); - rtl8168_mac_ocp_write( tp, 0xFA3E, 0xF119 ); - rtl8168_mac_ocp_write( tp, 0xFA40, 0xC5EC ); - rtl8168_mac_ocp_write( tp, 0xFA42, 0x76A4 ); - rtl8168_mac_ocp_write( tp, 0xFA44, 0x49E3 ); - rtl8168_mac_ocp_write( tp, 0xFA46, 0xF015 ); - rtl8168_mac_ocp_write( tp, 0xFA48, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xFA4A, 0xF103 ); - rtl8168_mac_ocp_write( tp, 0xFA4C, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xFA4E, 0xF011 ); - rtl8168_mac_ocp_write( tp, 0xFA50, 0x4849 ); - rtl8168_mac_ocp_write( tp, 0xFA52, 0x9C44 ); - rtl8168_mac_ocp_write( tp, 0xFA54, 0x1C00 ); - rtl8168_mac_ocp_write( tp, 0xFA56, 0x9CF6 ); - rtl8168_mac_ocp_write( tp, 0xFA58, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xFA5A, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xFA5C, 0xF004 ); - rtl8168_mac_ocp_write( tp, 0xFA5E, 0x6446 ); - rtl8168_mac_ocp_write( tp, 0xFA60, 0x1E07 ); - rtl8168_mac_ocp_write( tp, 0xFA62, 0xE003 ); - rtl8168_mac_ocp_write( tp, 0xFA64, 0x1C01 ); - rtl8168_mac_ocp_write( tp, 0xFA66, 0x1E03 ); - rtl8168_mac_ocp_write( tp, 0xFA68, 0x9C62 ); - rtl8168_mac_ocp_write( tp, 0xFA6A, 0x1C11 ); - rtl8168_mac_ocp_write( tp, 0xFA6C, 0x8C60 ); - rtl8168_mac_ocp_write( tp, 0xFA6E, 0xE830 ); - rtl8168_mac_ocp_write( tp, 0xFA70, 0xE02D ); - rtl8168_mac_ocp_write( tp, 0xFA72, 0x49E9 ); - rtl8168_mac_ocp_write( tp, 0xFA74, 0xF004 ); - rtl8168_mac_ocp_write( tp, 0xFA76, 0x1D02 ); - rtl8168_mac_ocp_write( tp, 0xFA78, 0x8DF5 ); - rtl8168_mac_ocp_write( tp, 0xFA7A, 0xE79C ); - rtl8168_mac_ocp_write( tp, 0xFA7C, 0x49E3 ); - rtl8168_mac_ocp_write( tp, 0xFA7E, 0xF006 ); - rtl8168_mac_ocp_write( tp, 0xFA80, 0x1D08 ); - rtl8168_mac_ocp_write( tp, 0xFA82, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xFA84, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xFA86, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xFA88, 0xE73A ); - rtl8168_mac_ocp_write( tp, 0xFA8A, 0x49E1 ); - rtl8168_mac_ocp_write( tp, 0xFA8C, 0xF007 ); - rtl8168_mac_ocp_write( tp, 0xFA8E, 0x1D02 ); - rtl8168_mac_ocp_write( tp, 0xFA90, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xFA92, 0x1E01 ); - rtl8168_mac_ocp_write( tp, 0xFA94, 0xE7A7 ); - rtl8168_mac_ocp_write( tp, 0xFA96, 0xDE20 ); - rtl8168_mac_ocp_write( tp, 0xFA98, 0xE410 ); - rtl8168_mac_ocp_write( tp, 0xFA9A, 0x49E0 ); - rtl8168_mac_ocp_write( tp, 0xFA9C, 0xF017 ); - rtl8168_mac_ocp_write( tp, 0xFA9E, 0x1D01 ); - rtl8168_mac_ocp_write( tp, 0xFAA0, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xFAA2, 0xC5FA ); - rtl8168_mac_ocp_write( tp, 0xFAA4, 0x1C00 ); - rtl8168_mac_ocp_write( tp, 0xFAA6, 0x8CA0 ); - rtl8168_mac_ocp_write( tp, 0xFAA8, 0x1C1B ); - rtl8168_mac_ocp_write( tp, 0xFAAA, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xFAAC, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFAAE, 0x49CF ); - rtl8168_mac_ocp_write( tp, 0xFAB0, 0xF0FE ); - rtl8168_mac_ocp_write( tp, 0xFAB2, 0xC5F3 ); - rtl8168_mac_ocp_write( tp, 0xFAB4, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xFAB6, 0x4849 ); - rtl8168_mac_ocp_write( tp, 0xFAB8, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xFABA, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xFABC, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xFABE, 0xF006 ); - rtl8168_mac_ocp_write( tp, 0xFAC0, 0x48C3 ); - rtl8168_mac_ocp_write( tp, 0xFAC2, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xFAC4, 0xE820 ); - rtl8168_mac_ocp_write( tp, 0xFAC6, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xFAC8, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xFACA, 0xC432 ); - rtl8168_mac_ocp_write( tp, 0xFACC, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xFACE, 0xC5E4 ); - rtl8168_mac_ocp_write( tp, 0xFAD0, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFAD2, 0x49CE ); - rtl8168_mac_ocp_write( tp, 0xFAD4, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xFAD6, 0x9EA0 ); - rtl8168_mac_ocp_write( tp, 0xFAD8, 0x1C1C ); - rtl8168_mac_ocp_write( tp, 0xFADA, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xFADC, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xFADE, 0xFF80 ); - rtl8168_mac_ocp_write( tp, 0xFAE0, 0xB404 ); - rtl8168_mac_ocp_write( tp, 0xFAE2, 0xB405 ); - rtl8168_mac_ocp_write( tp, 0xFAE4, 0xC5D9 ); - rtl8168_mac_ocp_write( tp, 0xFAE6, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFAE8, 0x49CE ); - rtl8168_mac_ocp_write( tp, 0xFAEA, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xFAEC, 0xC41F ); - rtl8168_mac_ocp_write( tp, 0xFAEE, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xFAF0, 0xC41C ); - rtl8168_mac_ocp_write( tp, 0xFAF2, 0x1C13 ); - rtl8168_mac_ocp_write( tp, 0xFAF4, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xFAF6, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xFAF8, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFAFA, 0x49CF ); - rtl8168_mac_ocp_write( tp, 0xFAFC, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xFAFE, 0xB005 ); - rtl8168_mac_ocp_write( tp, 0xFB00, 0xB004 ); - rtl8168_mac_ocp_write( tp, 0xFB02, 0xFF80 ); - rtl8168_mac_ocp_write( tp, 0xFB04, 0xB404 ); - rtl8168_mac_ocp_write( tp, 0xFB06, 0xB405 ); - rtl8168_mac_ocp_write( tp, 0xFB08, 0xC5C7 ); - rtl8168_mac_ocp_write( tp, 0xFB0A, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFB0C, 0x49CE ); - rtl8168_mac_ocp_write( tp, 0xFB0E, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xFB10, 0xC40E ); - rtl8168_mac_ocp_write( tp, 0xFB12, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xFB14, 0xC40A ); - rtl8168_mac_ocp_write( tp, 0xFB16, 0x1C13 ); - rtl8168_mac_ocp_write( tp, 0xFB18, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xFB1A, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xFB1C, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFB1E, 0x49CF ); - rtl8168_mac_ocp_write( tp, 0xFB20, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xFB22, 0xB005 ); - rtl8168_mac_ocp_write( tp, 0xFB24, 0xB004 ); - rtl8168_mac_ocp_write( tp, 0xFB26, 0xFF80 ); - rtl8168_mac_ocp_write( tp, 0xFB28, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFB2A, 0x0481 ); - rtl8168_mac_ocp_write( tp, 0xFB2C, 0x0C81 ); - rtl8168_mac_ocp_write( tp, 0xFB2E, 0x0AE0 ); - - - rtl8168_mac_ocp_write( tp, 0xFC26, 0x8000 ); - - rtl8168_mac_ocp_write( tp, 0xFC28, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFC2A, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFC2C, 0x0297 ); - rtl8168_mac_ocp_write( tp, 0xFC2E, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFC30, 0x00A9 ); - rtl8168_mac_ocp_write( tp, 0xFC32, 0x012D ); - rtl8168_mac_ocp_write( tp, 0xFC34, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFC36, 0x08DF ); -} - -static void -rtl8168_set_mac_mcu_8411b_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - rtl8168_hw_disable_mac_mcu_bps(dev); - - rtl8168_mac_ocp_write( tp, 0xF800, 0xE008 ); - rtl8168_mac_ocp_write( tp, 0xF802, 0xE00A ); - rtl8168_mac_ocp_write( tp, 0xF804, 0xE00C ); - rtl8168_mac_ocp_write( tp, 0xF806, 0xE00E ); - rtl8168_mac_ocp_write( tp, 0xF808, 0xE027 ); - rtl8168_mac_ocp_write( tp, 0xF80A, 0xE04F ); - rtl8168_mac_ocp_write( tp, 0xF80C, 0xE05E ); - rtl8168_mac_ocp_write( tp, 0xF80E, 0xE065 ); - rtl8168_mac_ocp_write( tp, 0xF810, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF812, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF814, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xF816, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF818, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF81A, 0x074C ); - rtl8168_mac_ocp_write( tp, 0xF81C, 0xC302 ); - rtl8168_mac_ocp_write( tp, 0xF81E, 0xBB00 ); - rtl8168_mac_ocp_write( tp, 0xF820, 0x080A ); - rtl8168_mac_ocp_write( tp, 0xF822, 0x6420 ); - rtl8168_mac_ocp_write( tp, 0xF824, 0x48C2 ); - rtl8168_mac_ocp_write( tp, 0xF826, 0x8C20 ); - rtl8168_mac_ocp_write( tp, 0xF828, 0xC516 ); - rtl8168_mac_ocp_write( tp, 0xF82A, 0x64A4 ); - rtl8168_mac_ocp_write( tp, 0xF82C, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF82E, 0xF009 ); - rtl8168_mac_ocp_write( tp, 0xF830, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xF832, 0x8CA5 ); - rtl8168_mac_ocp_write( tp, 0xF834, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF836, 0xC50E ); - rtl8168_mac_ocp_write( tp, 0xF838, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xF83A, 0x1C11 ); - rtl8168_mac_ocp_write( tp, 0xF83C, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF83E, 0xE006 ); - rtl8168_mac_ocp_write( tp, 0xF840, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF842, 0x48C4 ); - rtl8168_mac_ocp_write( tp, 0xF844, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF846, 0xC404 ); - rtl8168_mac_ocp_write( tp, 0xF848, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF84A, 0xC403 ); - rtl8168_mac_ocp_write( tp, 0xF84C, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF84E, 0x0BF2 ); - rtl8168_mac_ocp_write( tp, 0xF850, 0x0C0A ); - rtl8168_mac_ocp_write( tp, 0xF852, 0xE434 ); - rtl8168_mac_ocp_write( tp, 0xF854, 0xD3C0 ); - rtl8168_mac_ocp_write( tp, 0xF856, 0x49D9 ); - rtl8168_mac_ocp_write( tp, 0xF858, 0xF01F ); - rtl8168_mac_ocp_write( tp, 0xF85A, 0xC526 ); - rtl8168_mac_ocp_write( tp, 0xF85C, 0x64A5 ); - rtl8168_mac_ocp_write( tp, 0xF85E, 0x1400 ); - rtl8168_mac_ocp_write( tp, 0xF860, 0xF007 ); - rtl8168_mac_ocp_write( tp, 0xF862, 0x0C01 ); - rtl8168_mac_ocp_write( tp, 0xF864, 0x8CA5 ); - rtl8168_mac_ocp_write( tp, 0xF866, 0x1C15 ); - rtl8168_mac_ocp_write( tp, 0xF868, 0xC51B ); - rtl8168_mac_ocp_write( tp, 0xF86A, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF86C, 0xE013 ); - rtl8168_mac_ocp_write( tp, 0xF86E, 0xC519 ); - rtl8168_mac_ocp_write( tp, 0xF870, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF872, 0x48C4 ); - rtl8168_mac_ocp_write( tp, 0xF874, 0x8CA0 ); - rtl8168_mac_ocp_write( tp, 0xF876, 0xC516 ); - rtl8168_mac_ocp_write( tp, 0xF878, 0x74A4 ); - rtl8168_mac_ocp_write( tp, 0xF87A, 0x48C8 ); - rtl8168_mac_ocp_write( tp, 0xF87C, 0x48CA ); - rtl8168_mac_ocp_write( tp, 0xF87E, 0x9CA4 ); - rtl8168_mac_ocp_write( tp, 0xF880, 0xC512 ); - rtl8168_mac_ocp_write( tp, 0xF882, 0x1B00 ); - rtl8168_mac_ocp_write( tp, 0xF884, 0x9BA0 ); - rtl8168_mac_ocp_write( tp, 0xF886, 0x1B1C ); - rtl8168_mac_ocp_write( tp, 0xF888, 0x483F ); - rtl8168_mac_ocp_write( tp, 0xF88A, 0x9BA2 ); - rtl8168_mac_ocp_write( tp, 0xF88C, 0x1B04 ); - rtl8168_mac_ocp_write( tp, 0xF88E, 0xC508 ); - rtl8168_mac_ocp_write( tp, 0xF890, 0x9BA0 ); - rtl8168_mac_ocp_write( tp, 0xF892, 0xC505 ); - rtl8168_mac_ocp_write( tp, 0xF894, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF896, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF898, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF89A, 0x0300 ); - rtl8168_mac_ocp_write( tp, 0xF89C, 0x051E ); - rtl8168_mac_ocp_write( tp, 0xF89E, 0xE434 ); - rtl8168_mac_ocp_write( tp, 0xF8A0, 0xE018 ); - rtl8168_mac_ocp_write( tp, 0xF8A2, 0xE092 ); - rtl8168_mac_ocp_write( tp, 0xF8A4, 0xDE20 ); - rtl8168_mac_ocp_write( tp, 0xF8A6, 0xD3C0 ); - rtl8168_mac_ocp_write( tp, 0xF8A8, 0xC50F ); - rtl8168_mac_ocp_write( tp, 0xF8AA, 0x76A4 ); - rtl8168_mac_ocp_write( tp, 0xF8AC, 0x49E3 ); - rtl8168_mac_ocp_write( tp, 0xF8AE, 0xF007 ); - rtl8168_mac_ocp_write( tp, 0xF8B0, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF8B2, 0xF103 ); - rtl8168_mac_ocp_write( tp, 0xF8B4, 0xC607 ); - rtl8168_mac_ocp_write( tp, 0xF8B6, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF8B8, 0xC606 ); - rtl8168_mac_ocp_write( tp, 0xF8BA, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF8BC, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF8BE, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF8C0, 0x0C4C ); - rtl8168_mac_ocp_write( tp, 0xF8C2, 0x0C28 ); - rtl8168_mac_ocp_write( tp, 0xF8C4, 0x0C2C ); - rtl8168_mac_ocp_write( tp, 0xF8C6, 0xDC00 ); - rtl8168_mac_ocp_write( tp, 0xF8C8, 0xC707 ); - rtl8168_mac_ocp_write( tp, 0xF8CA, 0x1D00 ); - rtl8168_mac_ocp_write( tp, 0xF8CC, 0x8DE2 ); - rtl8168_mac_ocp_write( tp, 0xF8CE, 0x48C1 ); - rtl8168_mac_ocp_write( tp, 0xF8D0, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF8D2, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF8D4, 0x00AA ); - rtl8168_mac_ocp_write( tp, 0xF8D6, 0xE0C0 ); - rtl8168_mac_ocp_write( tp, 0xF8D8, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF8DA, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF8DC, 0x0132 ); - - rtl8168_mac_ocp_write( tp, 0xFC26, 0x8000 ); - - rtl8168_mac_ocp_write( tp, 0xFC2A, 0x0743 ); - rtl8168_mac_ocp_write( tp, 0xFC2C, 0x0801 ); - rtl8168_mac_ocp_write( tp, 0xFC2E, 0x0BE9 ); - rtl8168_mac_ocp_write( tp, 0xFC30, 0x02FD ); - rtl8168_mac_ocp_write( tp, 0xFC32, 0x0C25 ); - rtl8168_mac_ocp_write( tp, 0xFC34, 0x00A9 ); - rtl8168_mac_ocp_write( tp, 0xFC36, 0x012D ); -} - -static void -rtl8168_set_mac_mcu_8168ep_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8168ep_1[] = { - 0xE008, 0xE0D3, 0xE0D6, 0xE0D9, 0xE0DB, 0xE0DD, 0xE0DF, 0xE0E1, 0xC251, - 0x7340, 0x49B1, 0xF010, 0x1D02, 0x8D40, 0xC202, 0xBA00, 0x2C3A, 0xC0F0, - 0xE8DE, 0x2000, 0x8000, 0xC0B6, 0x268C, 0x752C, 0x49D4, 0xF112, 0xE025, - 0xC2F6, 0x7146, 0xC2F5, 0x7340, 0x49BE, 0xF103, 0xC7F2, 0xE002, 0xC7F1, - 0x304F, 0x6226, 0x49A1, 0xF1F0, 0x7222, 0x49A0, 0xF1ED, 0x2525, 0x1F28, - 0x3097, 0x3091, 0x9A36, 0x752C, 0x21DC, 0x25BC, 0xC6E2, 0x77C0, 0x1304, - 0xF014, 0x1303, 0xF014, 0x1302, 0xF014, 0x1301, 0xF014, 0x49D4, 0xF103, - 0xC3D7, 0xBB00, 0xC618, 0x67C6, 0x752E, 0x22D7, 0x26DD, 0x1505, 0xF013, - 0xC60A, 0xBE00, 0xC309, 0xBB00, 0xC308, 0xBB00, 0xC307, 0xBB00, 0xC306, - 0xBB00, 0x25C8, 0x25A6, 0x25AC, 0x25B2, 0x25B8, 0xCD08, 0x0000, 0xC0BC, - 0xC2FF, 0x7340, 0x49B0, 0xF04E, 0x1F46, 0x308F, 0xC3F7, 0x1C04, 0xE84D, - 0x1401, 0xF147, 0x7226, 0x49A7, 0xF044, 0x7222, 0x2525, 0x1F30, 0x3097, - 0x3091, 0x7340, 0xC4EA, 0x401C, 0xF006, 0xC6E8, 0x75C0, 0x49D7, 0xF105, - 0xE036, 0x1D08, 0x8DC1, 0x0208, 0x6640, 0x2764, 0x1606, 0xF12F, 0x6346, - 0x133B, 0xF12C, 0x9B34, 0x1B18, 0x3093, 0xC32A, 0x1C10, 0xE82A, 0x1401, - 0xF124, 0x1A36, 0x308A, 0x7322, 0x25B5, 0x0B0E, 0x1C00, 0xE82C, 0xC71F, - 0x4027, 0xF11A, 0xE838, 0x1F42, 0x308F, 0x1B08, 0xE824, 0x7236, 0x7746, - 0x1700, 0xF00D, 0xC313, 0x401F, 0xF103, 0x1F00, 0x9F46, 0x7744, 0x449F, - 0x445F, 0xE817, 0xC70A, 0x4027, 0xF105, 0xC302, 0xBB00, 0x2E08, 0x2DC2, - 0xC7FF, 0xBF00, 0xCDB8, 0xFFFF, 0x0C02, 0xA554, 0xA5DC, 0x402F, 0xF105, - 0x1400, 0xF1FA, 0x1C01, 0xE002, 0x1C00, 0xFF80, 0x49B0, 0xF004, 0x0B01, - 0xA1D3, 0xE003, 0x0B02, 0xA5D3, 0x3127, 0x3720, 0x0B02, 0xA5D3, 0x3127, - 0x3720, 0x1300, 0xF1FB, 0xFF80, 0x7322, 0x25B5, 0x1E28, 0x30DE, 0x30D9, - 0x7264, 0x1E11, 0x2368, 0x3116, 0xFF80, 0x1B7E, 0xC602, 0xBE00, 0x06A6, - 0x1B7E, 0xC602, 0xBE00, 0x0764, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, - 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, - 0x0000 - }; - - rtl8168_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168ep_1); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168ep_1[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x2549); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x06A5); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x0763); -} - -static void -rtl8168_set_mac_mcu_8168ep_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8168ep_2[] = { - 0xE008, 0xE017, 0xE052, 0xE056, 0xE058, 0xE05A, 0xE05C, 0xE05E, 0xC50F, - 0x76A4, 0x49E3, 0xF007, 0x49C0, 0xF103, 0xC607, 0xBE00, 0xC606, 0xBE00, - 0xC602, 0xBE00, 0x0BDA, 0x0BB6, 0x0BBA, 0xDC00, 0xB400, 0xB401, 0xB402, - 0xB403, 0xB404, 0xC02E, 0x7206, 0x49AE, 0xF1FE, 0xC12B, 0x9904, 0xC12A, - 0x9906, 0x7206, 0x49AE, 0xF1FE, 0x7200, 0x49A0, 0xF117, 0xC123, 0xC223, - 0xC323, 0xE808, 0xC322, 0xE806, 0xC321, 0xE804, 0xC320, 0xE802, 0xE00C, - 0x740E, 0x49CE, 0xF1FE, 0x9908, 0x990A, 0x9A0C, 0x9B0E, 0x740E, 0x49CE, - 0xF1FE, 0xFF80, 0xB004, 0xB003, 0xB002, 0xB001, 0xB000, 0xC604, 0xC002, - 0xB800, 0x1FC8, 0xE000, 0xE8E0, 0xF128, 0x0002, 0xFFFF, 0xF000, 0x8001, - 0x8002, 0x8003, 0x8004, 0x48C1, 0x48C2, 0xC502, 0xBD00, 0x0490, 0xC602, - 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, - 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, - }; - - rtl8168_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168ep_2); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168ep_2[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x0BB3); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x1FC7); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x0485); -} - -static void -rtl8168_set_mac_mcu_8168h_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8168h_1[] = { - 0xE008, 0xE00F, 0xE011, 0xE047, 0xE049, 0xE073, 0xE075, 0xE079, 0xC707, - 0x1D00, 0x8DE2, 0x48C1, 0xC502, 0xBD00, 0x00E4, 0xE0C0, 0xC502, 0xBD00, - 0x0216, 0xC634, 0x75C0, 0x49D3, 0xF027, 0xC631, 0x75C0, 0x49D3, 0xF123, - 0xC627, 0x75C0, 0xB405, 0xC525, 0x9DC0, 0xC621, 0x75C8, 0x49D5, 0xF00A, - 0x49D6, 0xF008, 0x49D7, 0xF006, 0x49D8, 0xF004, 0x75D2, 0x49D9, 0xF111, - 0xC517, 0x9DC8, 0xC516, 0x9DD2, 0xC618, 0x75C0, 0x49D4, 0xF003, 0x49D0, - 0xF104, 0xC60A, 0xC50E, 0x9DC0, 0xB005, 0xC607, 0x9DC0, 0xB007, 0xC602, - 0xBE00, 0x1A06, 0xB400, 0xE86C, 0xA000, 0x01E1, 0x0200, 0x9200, 0xE84C, - 0xE004, 0xE908, 0xC502, 0xBD00, 0x0B58, 0xB407, 0xB404, 0x2195, 0x25BD, - 0x9BE0, 0x1C1C, 0x484F, 0x9CE2, 0x72E2, 0x49AE, 0xF1FE, 0x0B00, 0xF116, - 0xC71C, 0xC419, 0x9CE0, 0x1C13, 0x484F, 0x9CE2, 0x74E2, 0x49CE, 0xF1FE, - 0xC412, 0x9CE0, 0x1C13, 0x484F, 0x9CE2, 0x74E2, 0x49CE, 0xF1FE, 0xC70C, - 0x74F8, 0x48C3, 0x8CF8, 0xB004, 0xB007, 0xC502, 0xBD00, 0x0F24, 0x0481, - 0x0C81, 0xDE24, 0xE000, 0xC602, 0xBE00, 0x0CA4, 0x48C1, 0x48C2, 0xC502, - 0xBD00, 0x0578, 0xC602, 0xBE00, 0x0000 - }; - - rtl8168_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168h_1); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168h_1[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x00E2); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x0210); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x1A04); - rtl8168_mac_ocp_write(tp, 0xFC2E, 0x0B26); - rtl8168_mac_ocp_write(tp, 0xFC30, 0x0F02); - rtl8168_mac_ocp_write(tp, 0xFC32, 0x0CA0); - rtl8168_mac_ocp_write(tp, 0xFC34, 0x056C); - - rtl8168_mac_ocp_write(tp, 0xFC38, 0x007F); -} - -static void -rtl8168_set_mac_mcu_8168fp_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 i; - u16 breakPointEnabled = 0; - - rtl8168_hw_disable_mac_mcu_bps(dev); - - if(tp->HwPkgDet == 0x00 || tp->HwPkgDet == 0x0F) { - static const u16 mcu_patch_code_8168fp_1_1[] = { - 0xE00A, 0xE0C1, 0xE104, 0xE108, 0xE10D, 0xE112, 0xE11C, 0xE121, 0xE000, - 0xE0C8, 0xB400, 0xC1FE, 0x49E2, 0xF04C, 0x49EA, 0xF04A, 0x74E6, 0xC246, - 0x7542, 0x73EC, 0x1800, 0x49C0, 0xF10D, 0x49C1, 0xF10B, 0x49C2, 0xF109, - 0x49B0, 0xF107, 0x49B1, 0xF105, 0x7220, 0x49A2, 0xF102, 0xE002, 0x4800, - 0x49D0, 0xF10A, 0x49D1, 0xF108, 0x49D2, 0xF106, 0x49D3, 0xF104, 0x49DF, - 0xF102, 0xE00C, 0x4801, 0x72E4, 0x49AD, 0xF108, 0xC225, 0x6741, 0x48F0, - 0x8F41, 0x4870, 0x8F41, 0xC7CF, 0x49B5, 0xF01F, 0x49B2, 0xF00B, 0x4980, - 0xF003, 0x484E, 0x94E7, 0x4981, 0xF004, 0x485E, 0xC212, 0x9543, 0xE071, - 0x49B6, 0xF003, 0x49B3, 0xF10F, 0x4980, 0xF003, 0x484E, 0x94E7, 0x4981, - 0xF004, 0x485E, 0xC204, 0x9543, 0xE005, 0xE000, 0xE0FC, 0xE0FA, 0xE065, - 0x49B7, 0xF007, 0x4980, 0xF005, 0x1A38, 0x46D4, 0x1200, 0xF109, 0x4981, - 0xF055, 0x49C3, 0xF105, 0x1A30, 0x46D5, 0x1200, 0xF04F, 0x7220, 0x49A2, - 0xF130, 0x49C1, 0xF12E, 0x49B0, 0xF12C, 0xC2E6, 0x7240, 0x49A8, 0xF003, - 0x49D0, 0xF126, 0x49A9, 0xF003, 0x49D1, 0xF122, 0x49AA, 0xF003, 0x49D2, - 0xF11E, 0x49AB, 0xF003, 0x49DF, 0xF11A, 0x49AC, 0xF003, 0x49D3, 0xF116, - 0x4980, 0xF003, 0x49C7, 0xF105, 0x4981, 0xF02C, 0x49D7, 0xF02A, 0x49C0, - 0xF00C, 0xC721, 0x62F4, 0x49A0, 0xF008, 0x49A4, 0xF106, 0x4824, 0x8AF4, - 0xC71A, 0x1A40, 0x9AE0, 0x49B6, 0xF017, 0x200E, 0xC7B8, 0x72E0, 0x4710, - 0x92E1, 0xC70E, 0x77E0, 0x49F0, 0xF112, 0xC70B, 0x77E0, 0x27FE, 0x1AFA, - 0x4317, 0xC705, 0x9AE2, 0x1A11, 0x8AE0, 0xE008, 0xE41C, 0xC0AE, 0xD23A, - 0xC7A2, 0x74E6, 0x484F, 0x94E7, 0xC79E, 0x8CE6, 0x8BEC, 0xC29C, 0x8D42, - 0x7220, 0xB000, 0xC502, 0xBD00, 0x0932, 0xB400, 0xC240, 0xC340, 0x7060, - 0x498F, 0xF014, 0x488F, 0x9061, 0x744C, 0x49C3, 0xF004, 0x7562, 0x485E, - 0x9563, 0x7446, 0x49C3, 0xF106, 0x7562, 0x1C30, 0x46E5, 0x1200, 0xF004, - 0x7446, 0x484F, 0x9447, 0xC32A, 0x7466, 0x49C0, 0xF00F, 0x48C0, 0x9C66, - 0x7446, 0x4840, 0x4841, 0x4842, 0x9C46, 0x744C, 0x4840, 0x9C4C, 0x744A, - 0x484A, 0x9C4A, 0xE013, 0x498E, 0xF011, 0x488E, 0x9061, 0x744C, 0x49C3, - 0xF004, 0x7446, 0x484E, 0x9447, 0x7446, 0x1D38, 0x46EC, 0x1500, 0xF004, - 0x7446, 0x484F, 0x9447, 0xB000, 0xC502, 0xBD00, 0x074C, 0xE000, 0xE0FC, - 0xE0C0, 0x4830, 0x4837, 0xC502, 0xBD00, 0x0978, 0x63E2, 0x4830, 0x4837, - 0xC502, 0xBD00, 0x09FE, 0x73E2, 0x4830, 0x8BE2, 0xC302, 0xBB00, 0x0A12, - 0x73E2, 0x48B0, 0x48B3, 0x48B4, 0x48B5, 0x48B6, 0x48B7, 0x8BE2, 0xC302, - 0xBB00, 0x0A5A, 0x73E2, 0x4830, 0x8BE2, 0xC302, 0xBB00, 0x0A6C, 0x73E2, - 0x4830, 0x4837, 0xC502, 0xBD00, 0x0A86 - }; - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168fp_1_1); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168fp_1_1[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x0890); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x0712); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x0974); - rtl8168_mac_ocp_write(tp, 0xFC2E, 0x09FC); - rtl8168_mac_ocp_write(tp, 0xFC30, 0x0A0E); - rtl8168_mac_ocp_write(tp, 0xFC32, 0x0A56); - rtl8168_mac_ocp_write(tp, 0xFC34, 0x0A68); - rtl8168_mac_ocp_write(tp, 0xFC36, 0x0A84); - - } else if (tp->HwPkgDet == 0x6) { - static const u16 mcu_patch_code_8168fp_1_2[] = { - 0xE008, 0xE00A, 0xE031, 0xE033, 0xE035, 0xE144, 0xE166, 0xE168, 0xC502, - 0xBD00, 0x0000, 0xC725, 0x75E0, 0x48D0, 0x9DE0, 0xC722, 0x75E0, 0x1C78, - 0x416C, 0x1530, 0xF111, 0xC71D, 0x75F6, 0x49D1, 0xF00D, 0x75E0, 0x1C1F, - 0x416C, 0x1502, 0xF108, 0x75FA, 0x49D3, 0xF005, 0x75EC, 0x9DE4, 0x4853, - 0x9DFA, 0xC70B, 0x75E0, 0x4852, 0x4850, 0x9DE0, 0xC602, 0xBE00, 0x04B8, - 0xE420, 0xE000, 0xE0FC, 0xE43C, 0xDC00, 0xEB00, 0xC202, 0xBA00, 0x0000, - 0xC002, 0xB800, 0x0000, 0xB401, 0xB402, 0xB403, 0xB404, 0xB405, 0xB406, - 0xC44D, 0xC54D, 0x1867, 0xE8A2, 0x2318, 0x276E, 0x1601, 0xF106, 0x1A07, - 0xE861, 0xE86B, 0xE873, 0xE037, 0x231E, 0x276E, 0x1602, 0xF10B, 0x1A07, - 0xE858, 0xE862, 0xC247, 0xC344, 0xE8E3, 0xC73B, 0x66E0, 0xE8B5, 0xE029, - 0x231A, 0x276C, 0xC733, 0x9EE0, 0x1866, 0xE885, 0x251C, 0x120F, 0xF011, - 0x1209, 0xF011, 0x2014, 0x240E, 0x1000, 0xF007, 0x120C, 0xF00D, 0x1203, - 0xF00D, 0x1200, 0xF00D, 0x120C, 0xF00D, 0x1203, 0xF00D, 0x1A03, 0xE00C, - 0x1A07, 0xE00A, 0x1A00, 0xE008, 0x1A01, 0xE006, 0x1A02, 0xE004, 0x1A04, - 0xE002, 0x1A05, 0xE829, 0xE833, 0xB006, 0xB005, 0xB004, 0xB003, 0xB002, - 0xB001, 0x60C4, 0xC702, 0xBF00, 0x2786, 0xDD00, 0xD030, 0xE0C4, 0xE0F8, - 0xDC42, 0xD3F0, 0x0000, 0x0004, 0x0007, 0x0014, 0x0090, 0x1000, 0x0F00, - 0x1004, 0x1008, 0x3000, 0x3004, 0x3008, 0x4000, 0x7777, 0x8000, 0x8001, - 0x8008, 0x8003, 0x8004, 0xC000, 0xC004, 0xF004, 0xFFFF, 0xB406, 0xB407, - 0xC6E5, 0x77C0, 0x27F3, 0x23F3, 0x47FA, 0x9FC0, 0xB007, 0xB006, 0xFF80, - 0xB405, 0xB407, 0xC7D8, 0x75E0, 0x48D0, 0x9DE0, 0xB007, 0xB005, 0xFF80, - 0xB401, 0xC0EA, 0xC2DC, 0xC3D8, 0xE865, 0xC0D3, 0xC1E0, 0xC2E3, 0xE861, - 0xE817, 0xC0CD, 0xC2CF, 0xE85D, 0xC0C9, 0xC1D6, 0xC2DB, 0xE859, 0xE80F, - 0xC1C7, 0xC2CE, 0xE855, 0xC0C0, 0xC1D1, 0xC2D3, 0xE851, 0xE807, 0xC0BE, - 0xC2C2, 0xE84D, 0xE803, 0xB001, 0xFF80, 0xB402, 0xC2C6, 0xE859, 0x499F, - 0xF1FE, 0xB002, 0xFF80, 0xB402, 0xB403, 0xB407, 0xE821, 0x8882, 0x1980, - 0x8983, 0xE81D, 0x7180, 0x218B, 0x25BB, 0x1310, 0xF014, 0x1310, 0xFB03, - 0x1F20, 0x38FB, 0x3288, 0x434B, 0x2491, 0x430B, 0x1F0F, 0x38FB, 0x4313, - 0x2121, 0x4353, 0x2521, 0x418A, 0x6282, 0x2527, 0x212F, 0x418A, 0xB007, - 0xB003, 0xB002, 0xFF80, 0x6183, 0x2496, 0x1100, 0xF1FD, 0xFF80, 0x4800, - 0x4801, 0xC213, 0xC313, 0xE815, 0x4860, 0x8EE0, 0xC210, 0xC310, 0xE822, - 0x481E, 0xC20C, 0xC30C, 0xE80C, 0xC206, 0x7358, 0x483A, 0x9B58, 0xFF80, - 0xE8E0, 0xE000, 0x1008, 0x0F00, 0x800C, 0x0F00, 0xB407, 0xB406, 0xB403, - 0xC7F7, 0x98E0, 0x99E2, 0x9AE4, 0x21B2, 0x4831, 0x483F, 0x9BE6, 0x66E7, - 0x49E6, 0xF1FE, 0xB003, 0xB006, 0xB007, 0xFF80, 0xB407, 0xB406, 0xB403, - 0xC7E5, 0x9AE4, 0x21B2, 0x4831, 0x9BE6, 0x66E7, 0x49E6, 0xF1FE, 0x70E0, - 0x71E2, 0xB003, 0xB006, 0xB007, 0xFF80, 0x4882, 0xB406, 0xB405, 0xC71E, - 0x76E0, 0x1D78, 0x4175, 0x1630, 0xF10C, 0xC715, 0x76E0, 0x4861, 0x9EE0, - 0xC713, 0x1EFF, 0x9EE2, 0x75E0, 0x4850, 0x9DE0, 0xE005, 0xC70B, 0x76E0, - 0x4865, 0x9EE0, 0xB005, 0xB006, 0xC708, 0xC102, 0xB900, 0x279E, 0xEB16, - 0xEB00, 0xE43C, 0xDC00, 0xD3EC, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, - 0x0000 - }; - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168fp_1_2); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168fp_1_2[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x04b4); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC2E, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC30, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC32, 0x279C); - rtl8168_mac_ocp_write(tp, 0xFC34, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC36, 0x0000); - } - - if (tp->HwPkgDet == 0x00) - breakPointEnabled = 0x00FC; - else if (tp->HwPkgDet == 0x0F) - breakPointEnabled = 0x00FF; - else if (tp->HwPkgDet == 0x06) - breakPointEnabled = 0x0022; - - rtl8168_mac_ocp_write(tp, 0xFC38, breakPointEnabled); -} - -static void -rtl8168_set_mac_mcu_8168fp_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8168fp_2[] = { - 0xE008, 0xE00A, 0xE00F, 0xE014, 0xE05F, 0xE063, 0xE065, 0xE067, 0xC602, - 0xBE00, 0x2AB2, 0x1BC0, 0x46EB, 0x1BFE, 0xC102, 0xB900, 0x0B1A, 0x1BC0, - 0x46EB, 0x1B7E, 0xC102, 0xB900, 0x0BEA, 0xB400, 0xB401, 0xB402, 0xB403, - 0xB404, 0xB405, 0xC03A, 0x7206, 0x49AE, 0xF1FE, 0xC137, 0x9904, 0xC136, - 0x9906, 0x7206, 0x49AE, 0xF1FE, 0x7200, 0x49A0, 0xF10B, 0xC52F, 0xC12E, - 0xC232, 0xC332, 0xE812, 0xC331, 0xE810, 0xC330, 0xE80E, 0xE018, 0xC126, - 0xC229, 0xC525, 0xC328, 0xE808, 0xC523, 0xC326, 0xE805, 0xC521, 0xC324, - 0xE802, 0xE00C, 0x740E, 0x49CE, 0xF1FE, 0x9908, 0x9D0A, 0x9A0C, 0x9B0E, - 0x740E, 0x49CE, 0xF1FE, 0xFF80, 0xB005, 0xB004, 0xB003, 0xB002, 0xB001, - 0xB000, 0xC604, 0xC002, 0xB800, 0x2A5E, 0xE000, 0xE8E0, 0xF128, 0x3DC2, - 0xFFFF, 0x10EC, 0x816A, 0x816D, 0x816C, 0xF000, 0x8002, 0x8004, 0x8007, - 0x48C1, 0x48C2, 0xC502, 0xBD00, 0x07BC, 0xC602, 0xBE00, 0x0000, 0xC602, - 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000 - }; - - rtl8168_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168fp_2); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168fp_2[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x2AAC); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x0B14); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x0BE4); - rtl8168_mac_ocp_write(tp, 0xFC2E, 0x2A5C); - rtl8168_mac_ocp_write(tp, 0xFC30, 0x07B0); - - if (tp->HwSuppSerDesPhyVer == 1) - rtl8168_mac_ocp_write(tp, 0xFC38, 0x001F); - else - rtl8168_mac_ocp_write(tp, 0xFC38, 0x001E); - -} - -static void -rtl8168_set_mac_mcu_8168fp_3(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8168fp_3[] = { - 0xE008, 0xE053, 0xE057, 0xE059, 0xE05B, 0xE05D, 0xE05F, 0xE061, 0xB400, - 0xB401, 0xB402, 0xB403, 0xB404, 0xB405, 0xC03A, 0x7206, 0x49AE, 0xF1FE, - 0xC137, 0x9904, 0xC136, 0x9906, 0x7206, 0x49AE, 0xF1FE, 0x7200, 0x49A0, - 0xF10B, 0xC52F, 0xC12E, 0xC232, 0xC332, 0xE812, 0xC331, 0xE810, 0xC330, - 0xE80E, 0xE018, 0xC126, 0xC229, 0xC525, 0xC328, 0xE808, 0xC523, 0xC326, - 0xE805, 0xC521, 0xC324, 0xE802, 0xE00C, 0x740E, 0x49CE, 0xF1FE, 0x9908, - 0x9D0A, 0x9A0C, 0x9B0E, 0x740E, 0x49CE, 0xF1FE, 0xFF80, 0xB005, 0xB004, - 0xB003, 0xB002, 0xB001, 0xB000, 0xC604, 0xC002, 0xB800, 0x2B16, 0xE000, - 0xE8E0, 0xF128, 0x3DC2, 0xFFFF, 0x10EC, 0x816A, 0x816D, 0x816C, 0xF000, - 0x8002, 0x8004, 0x8007, 0x48C1, 0x48C2, 0xC502, 0xBD00, 0x07BC, 0xC602, - 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, - 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000 - }; - - rtl8168_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168fp_3); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168fp_3[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x2B14); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x07B0); - - rtl8168_mac_ocp_write(tp, 0xFC38, 0x0003); -} - -static void -rtl8168_hw_mac_mcu_config(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (tp->NotWrMcuPatchCode == TRUE) return; - - switch (tp->mcfg) { - case CFG_METHOD_21: - rtl8168_set_mac_mcu_8168g_1(dev); - break; - case CFG_METHOD_24: - rtl8168_set_mac_mcu_8168gu_1(dev); - break; - case CFG_METHOD_25: - rtl8168_set_mac_mcu_8168gu_2(dev); - break; - case CFG_METHOD_26: - rtl8168_set_mac_mcu_8411b_1(dev); - break; - case CFG_METHOD_27: - rtl8168_set_mac_mcu_8168ep_1(dev); - break; - case CFG_METHOD_28: - rtl8168_set_mac_mcu_8168ep_2(dev); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - rtl8168_set_mac_mcu_8168h_1(dev); - break; - case CFG_METHOD_31: - rtl8168_set_mac_mcu_8168fp_1(dev); - break; - case CFG_METHOD_32: - rtl8168_set_mac_mcu_8168fp_2(dev); - break; - case CFG_METHOD_33: - rtl8168_set_mac_mcu_8168fp_3(dev); - break; - } -} -#endif - -#ifdef ENABLE_USE_FIRMWARE_FILE -static void rtl8168_release_firmware(struct rtl8168_private *tp) -{ - if (tp->rtl_fw) { - rtl8168_fw_release_firmware(tp->rtl_fw); - kfree(tp->rtl_fw); - tp->rtl_fw = NULL; - } -} - -void rtl8168_apply_firmware(struct rtl8168_private *tp) -{ - /* TODO: release firmware if rtl_fw_write_firmware signals failure. */ - if (tp->rtl_fw) { - rtl8168_fw_write_firmware(tp, tp->rtl_fw); - /* At least one firmware doesn't reset tp->ocp_base. */ - tp->ocp_base = OCP_STD_PHY_BASE; - - /* PHY soft reset may still be in progress */ - //phy_read_poll_timeout(tp->phydev, MII_BMCR, val, - // !(val & BMCR_RESET), - // 50000, 600000, true); - rtl8168_wait_phy_reset_complete(tp); - - tp->hw_ram_code_ver = rtl8168_get_hw_phy_mcu_code_ver(tp); - tp->sw_ram_code_ver = tp->hw_ram_code_ver; - tp->HwHasWrRamCodeToMicroP = TRUE; - } -} -#endif - -static void -rtl8168_hw_init(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 csi_tmp; - - if (tp->HwSuppAspmClkIntrLock) { - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - rtl8168_enable_cfg9346_write(tp); - rtl8168_hw_aspm_clkreq_enable(tp, false); - rtl8168_disable_cfg9346_write(tp); - } - - //Disable UPS - if (HW_SUPPORT_UPS_MODE(tp)) - rtl8168_mac_ocp_write(tp, 0xD400, rtl8168_mac_ocp_read( tp, 0xD400) & ~(BIT_0)); - - //Disable DMA Aggregation - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mac_ocp_write(tp, 0xE63E, rtl8168_mac_ocp_read( tp, 0xE63E) & ~(BIT_3 | BIT_2 | BIT_1)); - rtl8168_mac_ocp_write(tp, 0xE63E, rtl8168_mac_ocp_read( tp, 0xE63E) | (BIT_0)); - rtl8168_mac_ocp_write(tp, 0xE63E, rtl8168_mac_ocp_read( tp, 0xE63E) & ~(BIT_0)); - rtl8168_mac_ocp_write(tp, 0xC094, 0x0); - rtl8168_mac_ocp_write(tp, 0xC09E, 0x0); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - RTL_W8(tp, DBG_reg, RTL_R8(tp, DBG_reg) | BIT_1 | BIT_7); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - RTL_W8(tp, 0xF2, (RTL_R8(tp, 0xF2) & ~(BIT_2 | BIT_1 | BIT_0))); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - if (aspm) { - RTL_W8(tp, 0x6E, RTL_R8(tp, 0x6E) | BIT_6); - rtl8168_eri_write(tp, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); - } - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_29: - case CFG_METHOD_30: - if (aspm) { - if ((rtl8168_mac_ocp_read(tp, 0xDC00) & BIT_3) || (RTL_R8(tp, Config0) & 0x07)) { - RTL_W8(tp, 0x6E, RTL_R8(tp, 0x6E) | BIT_6); - rtl8168_eri_write(tp, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); - } - } - break; - } - - if (tp->mcfg == CFG_METHOD_10 || tp->mcfg == CFG_METHOD_14 || tp->mcfg == CFG_METHOD_15) - RTL_W8(tp, 0xF3, RTL_R8(tp, 0xF3) | BIT_2); - -#ifndef ENABLE_USE_FIRMWARE_FILE - if (!tp->rtl_fw) - rtl8168_hw_mac_mcu_config(dev); -#endif - - /*disable ocp phy power saving*/ - if (tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) - if (!tp->dash_printer_enabled) - rtl8168_disable_ocp_phy_power_saving(dev); - - //Set PCIE uncorrectable error status mask pcie 0x108 - csi_tmp = rtl8168_csi_read(tp, 0x108); - csi_tmp |= BIT_20; - rtl8168_csi_write(tp, 0x108, csi_tmp); - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - csi_tmp = rtl8168_eri_read(tp, 0x1AB, 1, ERIAR_ExGMAC); - csi_tmp |= ( BIT_2 | BIT_3 | BIT_4 | BIT_5 | BIT_6 | BIT_7 ); - rtl8168_eri_write(tp, 0x1AB, 1, csi_tmp, ERIAR_ExGMAC); - break; - } - - rtl8168_set_pci_pme(tp, 0); - - if (s0_magic_packet == 1) - rtl8168_enable_magic_packet(dev); - -#ifdef ENABLE_USE_FIRMWARE_FILE - if (tp->rtl_fw && - !(HW_DASH_SUPPORT_TYPE_3(tp) && - tp->HwPkgDet == 0x06)) - rtl8168_apply_firmware(tp); -#endif -} - -static void -rtl8168_hw_ephy_config(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 ephy_data; - - switch (tp->mcfg) { - case CFG_METHOD_4: - /*Set EPHY registers begin*/ - /*Set EPHY register offset 0x02 bit 11 to 0 and bit 12 to 1*/ - ephy_data = rtl8168_ephy_read(tp, 0x02); - ephy_data &= ~BIT_11; - ephy_data |= BIT_12; - rtl8168_ephy_write(tp, 0x02, ephy_data); - - /*Set EPHY register offset 0x03 bit 1 to 1*/ - ephy_data = rtl8168_ephy_read(tp, 0x03); - ephy_data |= (1 << 1); - rtl8168_ephy_write(tp, 0x03, ephy_data); - - /*Set EPHY register offset 0x06 bit 7 to 0*/ - ephy_data = rtl8168_ephy_read(tp, 0x06); - ephy_data &= ~(1 << 7); - rtl8168_ephy_write(tp, 0x06, ephy_data); - /*Set EPHY registers end*/ - - break; - case CFG_METHOD_5: - /* set EPHY registers */ - SetPCIePhyBit(tp, 0x01, BIT_0); - - ClearAndSetPCIePhyBit(tp, - 0x03, - BIT_10, - BIT_5 - ); - - break; - case CFG_METHOD_9: - /* set EPHY registers */ - rtl8168_ephy_write(tp, 0x01, 0x7C7F); - rtl8168_ephy_write(tp, 0x02, 0x011F); - if (tp->eeprom_type != EEPROM_TYPE_NONE) { - ClearAndSetPCIePhyBit(tp, - 0x03, - 0xFFB0, - 0x05B0 - ); - } else { - ClearAndSetPCIePhyBit(tp, - 0x03, - 0xFFF0, - 0x05F0 - ); - } - rtl8168_ephy_write(tp, 0x06, 0xB271); - rtl8168_ephy_write(tp, 0x07, 0xCE00); - - break; - case CFG_METHOD_10: - /* set EPHY registers */ - rtl8168_ephy_write(tp, 0x01, 0x6C7F); - rtl8168_ephy_write(tp, 0x02, 0x011F); - ClearAndSetPCIePhyBit(tp, - 0x03, - 0xFFF0, - 0x01B0 - ); - rtl8168_ephy_write(tp, 0x1A, 0x0546); - rtl8168_ephy_write(tp, 0x1C, 0x80C4); - rtl8168_ephy_write(tp, 0x1D, 0x78E5); - rtl8168_ephy_write(tp, 0x0A, 0x8100); - - break; - case CFG_METHOD_12: - case CFG_METHOD_13: - ephy_data = rtl8168_ephy_read(tp, 0x0B); - rtl8168_ephy_write(tp, 0x0B, ephy_data|0x48); - ephy_data = rtl8168_ephy_read(tp, 0x19); - ephy_data &= ~0x20; - rtl8168_ephy_write(tp, 0x19, ephy_data|0x50); - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~0x100; - rtl8168_ephy_write(tp, 0x0C, ephy_data|0x20); - ephy_data = rtl8168_ephy_read(tp, 0x10); - ephy_data &= ~0x04; - rtl8168_ephy_write(tp, 0x10, ephy_data); - - break; - case CFG_METHOD_14: - case CFG_METHOD_15: - /* set EPHY registers */ - ephy_data = rtl8168_ephy_read(tp, 0x00) & ~0x0200; - ephy_data |= 0x0100; - rtl8168_ephy_write(tp, 0x00, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data |= 0x0004; - rtl8168_ephy_write(tp, 0x00, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x06) & ~0x0002; - ephy_data |= 0x0001; - rtl8168_ephy_write(tp, 0x06, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x06); - ephy_data |= 0x0030; - rtl8168_ephy_write(tp, 0x06, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x07); - ephy_data |= 0x2000; - rtl8168_ephy_write(tp, 0x07, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data |= 0x0020; - rtl8168_ephy_write(tp, 0x00, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x03) & ~0x5800; - ephy_data |= 0x2000; - rtl8168_ephy_write(tp, 0x03, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x03); - ephy_data |= 0x0001; - rtl8168_ephy_write(tp, 0x03, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x01) & ~0x0800; - ephy_data |= 0x1000; - rtl8168_ephy_write(tp, 0x01, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x07); - ephy_data |= 0x4000; - rtl8168_ephy_write(tp, 0x07, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x1E); - ephy_data |= 0x2000; - rtl8168_ephy_write(tp, 0x1E, ephy_data); - - rtl8168_ephy_write(tp, 0x19, 0xFE6C); - - ephy_data = rtl8168_ephy_read(tp, 0x0A); - ephy_data |= 0x0040; - rtl8168_ephy_write(tp, 0x0A, ephy_data); - - break; - case CFG_METHOD_16: - case CFG_METHOD_17: - if (tp->mcfg == CFG_METHOD_16) { - rtl8168_ephy_write(tp, 0x06, 0xF020); - rtl8168_ephy_write(tp, 0x07, 0x01FF); - rtl8168_ephy_write(tp, 0x00, 0x5027); - rtl8168_ephy_write(tp, 0x01, 0x0003); - rtl8168_ephy_write(tp, 0x02, 0x2D16); - rtl8168_ephy_write(tp, 0x03, 0x6D49); - rtl8168_ephy_write(tp, 0x08, 0x0006); - rtl8168_ephy_write(tp, 0x0A, 0x00C8); - } - - ephy_data = rtl8168_ephy_read(tp, 0x09); - ephy_data |= BIT_7; - rtl8168_ephy_write(tp, 0x09, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x19); - ephy_data |= (BIT_2 | BIT_5 | BIT_9); - rtl8168_ephy_write(tp, 0x19, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data |= BIT_3; - rtl8168_ephy_write(tp, 0x00, ephy_data); - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~(BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4); - ephy_data |= BIT_9; - rtl8168_ephy_write(tp, 0x0C, ephy_data); - - break; - case CFG_METHOD_18: - case CFG_METHOD_19: - if (tp->mcfg == CFG_METHOD_18) { - ephy_data = rtl8168_ephy_read(tp, 0x06); - ephy_data |= BIT_5; - ephy_data &= ~(BIT_7 | BIT_6); - rtl8168_ephy_write(tp, 0x06, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x08); - ephy_data |= BIT_1; - ephy_data &= ~BIT_0; - rtl8168_ephy_write(tp, 0x08, ephy_data); - } - - ephy_data = rtl8168_ephy_read(tp, 0x09); - ephy_data |= BIT_7; - rtl8168_ephy_write(tp, 0x09, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x19); - ephy_data |= (BIT_2 | BIT_5 | BIT_9); - rtl8168_ephy_write(tp, 0x19, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data |= BIT_3; - rtl8168_ephy_write(tp, 0x00, ephy_data); - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~(BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4); - ephy_data |= BIT_9; - rtl8168_ephy_write(tp, 0x0C, ephy_data); - - break; - case CFG_METHOD_20: - ephy_data = rtl8168_ephy_read(tp, 0x06); - ephy_data |= BIT_5; - ephy_data &= ~(BIT_7 | BIT_6); - rtl8168_ephy_write(tp, 0x06, ephy_data); - - rtl8168_ephy_write(tp, 0x0f, 0x5200); - - ephy_data = rtl8168_ephy_read(tp, 0x19); - ephy_data |= (BIT_2 | BIT_5 | BIT_9); - rtl8168_ephy_write(tp, 0x19, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data |= BIT_3; - rtl8168_ephy_write(tp, 0x00, ephy_data); - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~(BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4); - ephy_data |= BIT_9; - rtl8168_ephy_write(tp, 0x0C, ephy_data); - - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data &= ~(BIT_3); - rtl8168_ephy_write(tp, 0x00, ephy_data); - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~(BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4); - ephy_data |= (BIT_5 | BIT_11); - rtl8168_ephy_write(tp, 0x0C, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x1E); - ephy_data |= (BIT_0); - rtl8168_ephy_write(tp, 0x1E, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x19); - ephy_data &= ~(BIT_15); - rtl8168_ephy_write(tp, 0x19, ephy_data); - - break; - case CFG_METHOD_25: - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data &= ~BIT_3; - rtl8168_ephy_write(tp, 0x00, ephy_data); - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~(BIT_13 | BIT_12 | BIT_11 | BIT_10| BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4); - ephy_data |= (BIT_5 | BIT_11); - rtl8168_ephy_write(tp, 0x0C, ephy_data); - - rtl8168_ephy_write(tp, 0x19, 0x7C00); - rtl8168_ephy_write(tp, 0x1E, 0x20EB); - rtl8168_ephy_write(tp, 0x0D, 0x1666); - rtl8168_ephy_write(tp, 0x00, 0x10A3); - rtl8168_ephy_write(tp, 0x06, 0xF050); - - SetPCIePhyBit(tp, 0x04, BIT_4); - ClearPCIePhyBit(tp, 0x1D, BIT_14); - - break; - case CFG_METHOD_26: - ClearPCIePhyBit(tp, 0x00, BIT_3); - ClearAndSetPCIePhyBit( tp, - 0x0C, - (BIT_13 | BIT_12 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_4), - (BIT_5 | BIT_11) - ); - SetPCIePhyBit(tp, 0x1E, BIT_0); - ClearPCIePhyBit(tp, 0x19, BIT_15); - - ClearPCIePhyBit(tp, 0x19, (BIT_5 | BIT_0)); - - SetPCIePhyBit(tp, 0x1E, BIT_13); - ClearPCIePhyBit(tp, 0x0D, BIT_8); - SetPCIePhyBit(tp, 0x0D, BIT_9); - SetPCIePhyBit(tp, 0x00, BIT_7); - - SetPCIePhyBit(tp, 0x06, BIT_4); - - SetPCIePhyBit(tp, 0x04, BIT_4); - SetPCIePhyBit(tp, 0x1D, BIT_14); - - break; - case CFG_METHOD_23: - rtl8168_ephy_write(tp, 0x00, 0x10AB); - rtl8168_ephy_write(tp, 0x06, 0xf030); - rtl8168_ephy_write(tp, 0x08, 0x2006); - rtl8168_ephy_write(tp, 0x0D, 0x1666); - - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~(BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4); - rtl8168_ephy_write(tp, 0x0C, ephy_data); - - break; - case CFG_METHOD_27: - rtl8168_ephy_write(tp, 0x00, 0x10A3); - rtl8168_ephy_write(tp, 0x19, 0xFC00); - rtl8168_ephy_write(tp, 0x1E, 0x20EA); - - break; - case CFG_METHOD_28: - rtl8168_ephy_write(tp, 0x00, 0x10AB); - rtl8168_ephy_write(tp, 0x19, 0xFC00); - rtl8168_ephy_write(tp, 0x1E, 0x20EB); - rtl8168_ephy_write(tp, 0x0D, 0x1666); - ClearPCIePhyBit(tp, 0x0B, BIT_0); - SetPCIePhyBit(tp, 0x1D, BIT_14); - ClearAndSetPCIePhyBit(tp, - 0x0C, - BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_8 | BIT_7 | BIT_6 | BIT_5, - BIT_9 | BIT_4 - ); - - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - ClearPCIePhyBit(tp, 0x1E, BIT_11); - - SetPCIePhyBit(tp, 0x1E, BIT_0); - SetPCIePhyBit(tp, 0x1D, BIT_11); - - rtl8168_ephy_write(tp, 0x05, 0x2089); - rtl8168_ephy_write(tp, 0x06, 0x5881); - - rtl8168_ephy_write(tp, 0x04, 0x854A); - rtl8168_ephy_write(tp, 0x01, 0x068B); - - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - ClearAndSetPCIePhyBit(tp, - 0x19, - BIT_6, - (BIT_12| BIT_8) - ); - ClearAndSetPCIePhyBit(tp, - 0x59, - BIT_6, - (BIT_12| BIT_8) - ); - - ClearPCIePhyBit(tp, 0x0C, BIT_4); - ClearPCIePhyBit(tp, 0x4C, BIT_4); - ClearPCIePhyBit(tp, 0x0B, BIT_0); - - break; - } -} - -static int -rtl8168_set_phy_mcu_patch_request(struct rtl8168_private *tp) -{ - u16 PhyRegValue; - u32 WaitCnt; - int retval = TRUE; - - switch (tp->mcfg) { - case CFG_METHOD_21 ... CFG_METHOD_33: - rtl8168_mdio_write(tp,0x1f, 0x0B82); - rtl8168_set_eth_phy_bit(tp, 0x10, BIT_4); - - rtl8168_mdio_write(tp,0x1f, 0x0B80); - WaitCnt = 0; - do { - PhyRegValue = rtl8168_mdio_read(tp, 0x10); - udelay(100); - WaitCnt++; - } while (!(PhyRegValue & BIT_6) && (WaitCnt < 1000)); - - if (!(PhyRegValue & BIT_6) && (WaitCnt == 1000)) retval = FALSE; - - rtl8168_mdio_write(tp,0x1f, 0x0000); - break; - } - - return retval; -} - -static int -rtl8168_clear_phy_mcu_patch_request(struct rtl8168_private *tp) -{ - u16 PhyRegValue; - u32 WaitCnt; - int retval = TRUE; - - switch (tp->mcfg) { - case CFG_METHOD_21 ... CFG_METHOD_33: - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - rtl8168_clear_eth_phy_bit(tp, 0x10, BIT_4); - - rtl8168_mdio_write(tp,0x1f, 0x0B80); - WaitCnt = 0; - do { - PhyRegValue = rtl8168_mdio_read(tp, 0x10); - udelay(100); - WaitCnt++; - } while ((PhyRegValue & BIT_6) && (WaitCnt < 1000)); - - if ((PhyRegValue & BIT_6) && (WaitCnt == 1000)) retval = FALSE; - - rtl8168_mdio_write(tp,0x1f, 0x0000); - break; - } - - return retval; -} - -static u16 -rtl8168_get_hw_phy_mcu_code_ver(struct rtl8168_private *tp) -{ - u16 hw_ram_code_ver = ~0; - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B60); - hw_ram_code_ver = rtl8168_mdio_read(tp, 0x06); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B30); - hw_ram_code_ver = rtl8168_mdio_read(tp, 0x06); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x801E); - hw_ram_code_ver = rtl8168_mdio_read(tp, 0x14); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - default: - tp->hw_ram_code_ver = ~0; - break; - } - - return hw_ram_code_ver; -} - -#ifndef ENABLE_USE_FIRMWARE_FILE -static void -rtl8168_enable_phy_disable_mode(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 1: - rtl8168_mac_ocp_write(tp, 0xDC20, rtl8168_mac_ocp_read(tp, 0xDC20) | BIT_1); - break; - case 2: - case 3: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_5); - break; - } - - dprintk("enable phy disable mode.\n"); -} - -static void -rtl8168_disable_phy_disable_mode(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 1: - rtl8168_mac_ocp_write(tp, 0xDC20, rtl8168_mac_ocp_read(tp, 0xDC20) & ~BIT_1); - break; - case 2: - case 3: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_5); - break; - } - - mdelay(1); - - dprintk("disable phy disable mode.\n"); -} - -static int -rtl8168_check_hw_phy_mcu_code_ver(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int ram_code_ver_match = 0; - - tp->hw_ram_code_ver = rtl8168_get_hw_phy_mcu_code_ver(tp); - - if ( tp->hw_ram_code_ver == tp->sw_ram_code_ver) { - ram_code_ver_match = 1; - tp->HwHasWrRamCodeToMicroP = TRUE; - } - - return ram_code_ver_match; -} - -static void -rtl8168_write_hw_phy_mcu_code_ver(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B60); - rtl8168_mdio_write(tp, 0x06, tp->sw_ram_code_ver); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - tp->hw_ram_code_ver = tp->sw_ram_code_ver; - break; - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B30); - rtl8168_mdio_write(tp, 0x06, tp->sw_ram_code_ver); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - tp->hw_ram_code_ver = tp->sw_ram_code_ver; - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x801E); - rtl8168_mdio_write(tp, 0x14, tp->sw_ram_code_ver); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - tp->hw_ram_code_ver = tp->sw_ram_code_ver; - break; - } -} -static int -rtl8168_phy_ram_code_check(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 PhyRegValue; - int retval = TRUE; - - switch(tp->mcfg) { - case CFG_METHOD_21: - rtl8168_mdio_write(tp, 0x1f, 0x0A40); - PhyRegValue = rtl8168_mdio_read(tp, 0x10); - PhyRegValue &= ~(BIT_11); - rtl8168_mdio_write(tp, 0x10, PhyRegValue); - - - rtl8168_mdio_write(tp, 0x1f, 0x0A00); - PhyRegValue = rtl8168_mdio_read(tp, 0x10); - PhyRegValue &= ~(BIT_12 | BIT_13 | BIT_14 | BIT_15); - rtl8168_mdio_write(tp, 0x10, PhyRegValue); - - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8010); - PhyRegValue = rtl8168_mdio_read(tp, 0x14); - PhyRegValue &= ~(BIT_11); - rtl8168_mdio_write(tp, 0x14, PhyRegValue); - - retval = rtl8168_set_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp, 0x1f, 0x0A40); - rtl8168_mdio_write(tp, 0x10, 0x0140); - - rtl8168_mdio_write(tp, 0x1f, 0x0A4A); - PhyRegValue = rtl8168_mdio_read(tp, 0x13); - PhyRegValue &= ~(BIT_6); - PhyRegValue |= (BIT_7); - rtl8168_mdio_write(tp, 0x13, PhyRegValue); - - rtl8168_mdio_write(tp, 0x1f, 0x0A44); - PhyRegValue = rtl8168_mdio_read(tp, 0x14); - PhyRegValue |= (BIT_2); - rtl8168_mdio_write(tp, 0x14, PhyRegValue); - - rtl8168_mdio_write(tp, 0x1f, 0x0A50); - PhyRegValue = rtl8168_mdio_read(tp, 0x11); - PhyRegValue |= (BIT_11|BIT_12); - rtl8168_mdio_write(tp, 0x11, PhyRegValue); - - retval = rtl8168_clear_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp, 0x1f, 0x0A40); - rtl8168_mdio_write(tp, 0x10, 0x1040); - - rtl8168_mdio_write(tp, 0x1f, 0x0A4A); - PhyRegValue = rtl8168_mdio_read(tp, 0x13); - PhyRegValue &= ~(BIT_6|BIT_7); - rtl8168_mdio_write(tp, 0x13, PhyRegValue); - - rtl8168_mdio_write(tp, 0x1f, 0x0A44); - PhyRegValue = rtl8168_mdio_read(tp, 0x14); - PhyRegValue &= ~(BIT_2); - rtl8168_mdio_write(tp, 0x14, PhyRegValue); - - rtl8168_mdio_write(tp, 0x1f, 0x0A50); - PhyRegValue = rtl8168_mdio_read(tp, 0x11); - PhyRegValue &= ~(BIT_11|BIT_12); - rtl8168_mdio_write(tp, 0x11, PhyRegValue); - - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8010); - PhyRegValue = rtl8168_mdio_read(tp, 0x14); - PhyRegValue |= (BIT_11); - rtl8168_mdio_write(tp, 0x14, PhyRegValue); - - retval = rtl8168_set_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp, 0x1f, 0x0A20); - PhyRegValue = rtl8168_mdio_read(tp, 0x13); - if (PhyRegValue & BIT_11) { - if (PhyRegValue & BIT_10) { - retval = FALSE; - } - } - - retval = rtl8168_clear_phy_mcu_patch_request(tp); - - mdelay(2); - break; - default: - break; - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - return retval; -} - -static void -rtl8168_set_phy_ram_code_check_fail_flag(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 TmpUshort; - - switch(tp->mcfg) { - case CFG_METHOD_21: - TmpUshort = rtl8168_mac_ocp_read(tp, 0xD3C0); - TmpUshort |= BIT_0; - rtl8168_mac_ocp_write(tp, 0xD3C0, TmpUshort); - break; - } -} - -static void -rtl8168_set_phy_mcu_8168e_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val,i; - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x1800); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x17, 0x0117); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - rtl8168_mdio_write(tp, 0x1B, 0x5000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x4104); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1E); - gphy_val &= 0x03FF; - if (gphy_val == 0x000C) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x07); - if ((gphy_val & BIT_5) == 0) - break; - } - gphy_val = rtl8168_mdio_read(tp, 0x07); - if (gphy_val & BIT_5) { - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x00a1); - rtl8168_mdio_write(tp, 0x17, 0x1000); - rtl8168_mdio_write(tp, 0x17, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2000); - rtl8168_mdio_write(tp, 0x1e, 0x002f); - rtl8168_mdio_write(tp, 0x18, 0x9bfb); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x07, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x08); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x08, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x000e); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x0010); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x0018); - rtl8168_mdio_write(tp, 0x19, 0x4801); - rtl8168_mdio_write(tp, 0x15, 0x0019); - rtl8168_mdio_write(tp, 0x19, 0x6801); - rtl8168_mdio_write(tp, 0x15, 0x001a); - rtl8168_mdio_write(tp, 0x19, 0x66a1); - rtl8168_mdio_write(tp, 0x15, 0x001f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0020); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0021); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0022); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0023); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0024); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0025); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0026); - rtl8168_mdio_write(tp, 0x19, 0x40ea); - rtl8168_mdio_write(tp, 0x15, 0x0027); - rtl8168_mdio_write(tp, 0x19, 0x4503); - rtl8168_mdio_write(tp, 0x15, 0x0028); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0029); - rtl8168_mdio_write(tp, 0x19, 0xa631); - rtl8168_mdio_write(tp, 0x15, 0x002a); - rtl8168_mdio_write(tp, 0x19, 0x9717); - rtl8168_mdio_write(tp, 0x15, 0x002b); - rtl8168_mdio_write(tp, 0x19, 0x302c); - rtl8168_mdio_write(tp, 0x15, 0x002c); - rtl8168_mdio_write(tp, 0x19, 0x4802); - rtl8168_mdio_write(tp, 0x15, 0x002d); - rtl8168_mdio_write(tp, 0x19, 0x58da); - rtl8168_mdio_write(tp, 0x15, 0x002e); - rtl8168_mdio_write(tp, 0x19, 0x400d); - rtl8168_mdio_write(tp, 0x15, 0x002f); - rtl8168_mdio_write(tp, 0x19, 0x4488); - rtl8168_mdio_write(tp, 0x15, 0x0030); - rtl8168_mdio_write(tp, 0x19, 0x9e00); - rtl8168_mdio_write(tp, 0x15, 0x0031); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0032); - rtl8168_mdio_write(tp, 0x19, 0x6481); - rtl8168_mdio_write(tp, 0x15, 0x0033); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0034); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0035); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0036); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0037); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0038); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0039); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x003a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x003b); - rtl8168_mdio_write(tp, 0x19, 0x63e8); - rtl8168_mdio_write(tp, 0x15, 0x003c); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x003d); - rtl8168_mdio_write(tp, 0x19, 0x59d4); - rtl8168_mdio_write(tp, 0x15, 0x003e); - rtl8168_mdio_write(tp, 0x19, 0x63f8); - rtl8168_mdio_write(tp, 0x15, 0x0040); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0041); - rtl8168_mdio_write(tp, 0x19, 0x30de); - rtl8168_mdio_write(tp, 0x15, 0x0044); - rtl8168_mdio_write(tp, 0x19, 0x480f); - rtl8168_mdio_write(tp, 0x15, 0x0045); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x0046); - rtl8168_mdio_write(tp, 0x19, 0x6680); - rtl8168_mdio_write(tp, 0x15, 0x0047); - rtl8168_mdio_write(tp, 0x19, 0x7c10); - rtl8168_mdio_write(tp, 0x15, 0x0048); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0049); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004f); - rtl8168_mdio_write(tp, 0x19, 0x40ea); - rtl8168_mdio_write(tp, 0x15, 0x0050); - rtl8168_mdio_write(tp, 0x19, 0x4503); - rtl8168_mdio_write(tp, 0x15, 0x0051); - rtl8168_mdio_write(tp, 0x19, 0x58ca); - rtl8168_mdio_write(tp, 0x15, 0x0052); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0053); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x0054); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x0055); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0056); - rtl8168_mdio_write(tp, 0x19, 0x3000); - rtl8168_mdio_write(tp, 0x15, 0x006E); - rtl8168_mdio_write(tp, 0x19, 0x9afa); - rtl8168_mdio_write(tp, 0x15, 0x00a1); - rtl8168_mdio_write(tp, 0x19, 0x3044); - rtl8168_mdio_write(tp, 0x15, 0x00ab); - rtl8168_mdio_write(tp, 0x19, 0x5820); - rtl8168_mdio_write(tp, 0x15, 0x00ac); - rtl8168_mdio_write(tp, 0x19, 0x5e04); - rtl8168_mdio_write(tp, 0x15, 0x00ad); - rtl8168_mdio_write(tp, 0x19, 0xb60c); - rtl8168_mdio_write(tp, 0x15, 0x00af); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x00b2); - rtl8168_mdio_write(tp, 0x19, 0x30b9); - rtl8168_mdio_write(tp, 0x15, 0x00b9); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x00ba); - rtl8168_mdio_write(tp, 0x19, 0x480b); - rtl8168_mdio_write(tp, 0x15, 0x00bb); - rtl8168_mdio_write(tp, 0x19, 0x5e00); - rtl8168_mdio_write(tp, 0x15, 0x00bc); - rtl8168_mdio_write(tp, 0x19, 0x405f); - rtl8168_mdio_write(tp, 0x15, 0x00bd); - rtl8168_mdio_write(tp, 0x19, 0x4448); - rtl8168_mdio_write(tp, 0x15, 0x00be); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x00bf); - rtl8168_mdio_write(tp, 0x19, 0x4468); - rtl8168_mdio_write(tp, 0x15, 0x00c0); - rtl8168_mdio_write(tp, 0x19, 0x9c02); - rtl8168_mdio_write(tp, 0x15, 0x00c1); - rtl8168_mdio_write(tp, 0x19, 0x58a0); - rtl8168_mdio_write(tp, 0x15, 0x00c2); - rtl8168_mdio_write(tp, 0x19, 0xb605); - rtl8168_mdio_write(tp, 0x15, 0x00c3); - rtl8168_mdio_write(tp, 0x19, 0xc0d3); - rtl8168_mdio_write(tp, 0x15, 0x00c4); - rtl8168_mdio_write(tp, 0x19, 0x00e6); - rtl8168_mdio_write(tp, 0x15, 0x00c5); - rtl8168_mdio_write(tp, 0x19, 0xdaec); - rtl8168_mdio_write(tp, 0x15, 0x00c6); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00c7); - rtl8168_mdio_write(tp, 0x19, 0x9df9); - rtl8168_mdio_write(tp, 0x15, 0x00c8); - rtl8168_mdio_write(tp, 0x19, 0x307a); - rtl8168_mdio_write(tp, 0x15, 0x0112); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0113); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0114); - rtl8168_mdio_write(tp, 0x19, 0x63f0); - rtl8168_mdio_write(tp, 0x15, 0x0115); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0116); - rtl8168_mdio_write(tp, 0x19, 0x4418); - rtl8168_mdio_write(tp, 0x15, 0x0117); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x15, 0x0118); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0119); - rtl8168_mdio_write(tp, 0x19, 0x64e1); - rtl8168_mdio_write(tp, 0x15, 0x011a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0150); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0151); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0152); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0153); - rtl8168_mdio_write(tp, 0x19, 0x4540); - rtl8168_mdio_write(tp, 0x15, 0x0154); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0155); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x15, 0x0156); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0157); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0158); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0159); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x015a); - rtl8168_mdio_write(tp, 0x19, 0x30fe); - rtl8168_mdio_write(tp, 0x15, 0x021e); - rtl8168_mdio_write(tp, 0x19, 0x5410); - rtl8168_mdio_write(tp, 0x15, 0x0225); - rtl8168_mdio_write(tp, 0x19, 0x5400); - rtl8168_mdio_write(tp, 0x15, 0x023D); - rtl8168_mdio_write(tp, 0x19, 0x4050); - rtl8168_mdio_write(tp, 0x15, 0x0295); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x02bd); - rtl8168_mdio_write(tp, 0x19, 0xa523); - rtl8168_mdio_write(tp, 0x15, 0x02be); - rtl8168_mdio_write(tp, 0x19, 0x32ca); - rtl8168_mdio_write(tp, 0x15, 0x02ca); - rtl8168_mdio_write(tp, 0x19, 0x48b3); - rtl8168_mdio_write(tp, 0x15, 0x02cb); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x02cc); - rtl8168_mdio_write(tp, 0x19, 0x4823); - rtl8168_mdio_write(tp, 0x15, 0x02cd); - rtl8168_mdio_write(tp, 0x19, 0x4510); - rtl8168_mdio_write(tp, 0x15, 0x02ce); - rtl8168_mdio_write(tp, 0x19, 0xb63a); - rtl8168_mdio_write(tp, 0x15, 0x02cf); - rtl8168_mdio_write(tp, 0x19, 0x7dc8); - rtl8168_mdio_write(tp, 0x15, 0x02d6); - rtl8168_mdio_write(tp, 0x19, 0x9bf8); - rtl8168_mdio_write(tp, 0x15, 0x02d8); - rtl8168_mdio_write(tp, 0x19, 0x85f6); - rtl8168_mdio_write(tp, 0x15, 0x02d9); - rtl8168_mdio_write(tp, 0x19, 0x32e0); - rtl8168_mdio_write(tp, 0x15, 0x02e0); - rtl8168_mdio_write(tp, 0x19, 0x4834); - rtl8168_mdio_write(tp, 0x15, 0x02e1); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x02e2); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x02e3); - rtl8168_mdio_write(tp, 0x19, 0x4824); - rtl8168_mdio_write(tp, 0x15, 0x02e4); - rtl8168_mdio_write(tp, 0x19, 0x4520); - rtl8168_mdio_write(tp, 0x15, 0x02e5); - rtl8168_mdio_write(tp, 0x19, 0x4008); - rtl8168_mdio_write(tp, 0x15, 0x02e6); - rtl8168_mdio_write(tp, 0x19, 0x4560); - rtl8168_mdio_write(tp, 0x15, 0x02e7); - rtl8168_mdio_write(tp, 0x19, 0x9d04); - rtl8168_mdio_write(tp, 0x15, 0x02e8); - rtl8168_mdio_write(tp, 0x19, 0x48c4); - rtl8168_mdio_write(tp, 0x15, 0x02e9); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02ea); - rtl8168_mdio_write(tp, 0x19, 0x4844); - rtl8168_mdio_write(tp, 0x15, 0x02eb); - rtl8168_mdio_write(tp, 0x19, 0x7dc8); - rtl8168_mdio_write(tp, 0x15, 0x02f0); - rtl8168_mdio_write(tp, 0x19, 0x9cf7); - rtl8168_mdio_write(tp, 0x15, 0x02f1); - rtl8168_mdio_write(tp, 0x19, 0xdf94); - rtl8168_mdio_write(tp, 0x15, 0x02f2); - rtl8168_mdio_write(tp, 0x19, 0x0002); - rtl8168_mdio_write(tp, 0x15, 0x02f3); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x02f4); - rtl8168_mdio_write(tp, 0x19, 0xb614); - rtl8168_mdio_write(tp, 0x15, 0x02f5); - rtl8168_mdio_write(tp, 0x19, 0xc42b); - rtl8168_mdio_write(tp, 0x15, 0x02f6); - rtl8168_mdio_write(tp, 0x19, 0x00d4); - rtl8168_mdio_write(tp, 0x15, 0x02f7); - rtl8168_mdio_write(tp, 0x19, 0xc455); - rtl8168_mdio_write(tp, 0x15, 0x02f8); - rtl8168_mdio_write(tp, 0x19, 0x0093); - rtl8168_mdio_write(tp, 0x15, 0x02f9); - rtl8168_mdio_write(tp, 0x19, 0x92ee); - rtl8168_mdio_write(tp, 0x15, 0x02fa); - rtl8168_mdio_write(tp, 0x19, 0xefed); - rtl8168_mdio_write(tp, 0x15, 0x02fb); - rtl8168_mdio_write(tp, 0x19, 0x3312); - rtl8168_mdio_write(tp, 0x15, 0x0312); - rtl8168_mdio_write(tp, 0x19, 0x49b5); - rtl8168_mdio_write(tp, 0x15, 0x0313); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x0314); - rtl8168_mdio_write(tp, 0x19, 0x4d00); - rtl8168_mdio_write(tp, 0x15, 0x0315); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x031e); - rtl8168_mdio_write(tp, 0x19, 0x404f); - rtl8168_mdio_write(tp, 0x15, 0x031f); - rtl8168_mdio_write(tp, 0x19, 0x44c8); - rtl8168_mdio_write(tp, 0x15, 0x0320); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0321); - rtl8168_mdio_write(tp, 0x19, 0x00e7); - rtl8168_mdio_write(tp, 0x15, 0x0322); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0323); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x0324); - rtl8168_mdio_write(tp, 0x19, 0x4d48); - rtl8168_mdio_write(tp, 0x15, 0x0325); - rtl8168_mdio_write(tp, 0x19, 0x3327); - rtl8168_mdio_write(tp, 0x15, 0x0326); - rtl8168_mdio_write(tp, 0x19, 0x4d40); - rtl8168_mdio_write(tp, 0x15, 0x0327); - rtl8168_mdio_write(tp, 0x19, 0xc8d7); - rtl8168_mdio_write(tp, 0x15, 0x0328); - rtl8168_mdio_write(tp, 0x19, 0x0003); - rtl8168_mdio_write(tp, 0x15, 0x0329); - rtl8168_mdio_write(tp, 0x19, 0x7c20); - rtl8168_mdio_write(tp, 0x15, 0x032a); - rtl8168_mdio_write(tp, 0x19, 0x4c20); - rtl8168_mdio_write(tp, 0x15, 0x032b); - rtl8168_mdio_write(tp, 0x19, 0xc8ed); - rtl8168_mdio_write(tp, 0x15, 0x032c); - rtl8168_mdio_write(tp, 0x19, 0x00f4); - rtl8168_mdio_write(tp, 0x15, 0x032d); - rtl8168_mdio_write(tp, 0x19, 0x82b3); - rtl8168_mdio_write(tp, 0x15, 0x032e); - rtl8168_mdio_write(tp, 0x19, 0xd11d); - rtl8168_mdio_write(tp, 0x15, 0x032f); - rtl8168_mdio_write(tp, 0x19, 0x00b1); - rtl8168_mdio_write(tp, 0x15, 0x0330); - rtl8168_mdio_write(tp, 0x19, 0xde18); - rtl8168_mdio_write(tp, 0x15, 0x0331); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x0332); - rtl8168_mdio_write(tp, 0x19, 0x91ee); - rtl8168_mdio_write(tp, 0x15, 0x0333); - rtl8168_mdio_write(tp, 0x19, 0x3339); - rtl8168_mdio_write(tp, 0x15, 0x033a); - rtl8168_mdio_write(tp, 0x19, 0x4064); - rtl8168_mdio_write(tp, 0x15, 0x0340); - rtl8168_mdio_write(tp, 0x19, 0x9e06); - rtl8168_mdio_write(tp, 0x15, 0x0341); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0342); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x0343); - rtl8168_mdio_write(tp, 0x19, 0x4d48); - rtl8168_mdio_write(tp, 0x15, 0x0344); - rtl8168_mdio_write(tp, 0x19, 0x3346); - rtl8168_mdio_write(tp, 0x15, 0x0345); - rtl8168_mdio_write(tp, 0x19, 0x4d40); - rtl8168_mdio_write(tp, 0x15, 0x0346); - rtl8168_mdio_write(tp, 0x19, 0xd11d); - rtl8168_mdio_write(tp, 0x15, 0x0347); - rtl8168_mdio_write(tp, 0x19, 0x0099); - rtl8168_mdio_write(tp, 0x15, 0x0348); - rtl8168_mdio_write(tp, 0x19, 0xbb17); - rtl8168_mdio_write(tp, 0x15, 0x0349); - rtl8168_mdio_write(tp, 0x19, 0x8102); - rtl8168_mdio_write(tp, 0x15, 0x034a); - rtl8168_mdio_write(tp, 0x19, 0x334d); - rtl8168_mdio_write(tp, 0x15, 0x034b); - rtl8168_mdio_write(tp, 0x19, 0xa22c); - rtl8168_mdio_write(tp, 0x15, 0x034c); - rtl8168_mdio_write(tp, 0x19, 0x3397); - rtl8168_mdio_write(tp, 0x15, 0x034d); - rtl8168_mdio_write(tp, 0x19, 0x91f2); - rtl8168_mdio_write(tp, 0x15, 0x034e); - rtl8168_mdio_write(tp, 0x19, 0xc218); - rtl8168_mdio_write(tp, 0x15, 0x034f); - rtl8168_mdio_write(tp, 0x19, 0x00f0); - rtl8168_mdio_write(tp, 0x15, 0x0350); - rtl8168_mdio_write(tp, 0x19, 0x3397); - rtl8168_mdio_write(tp, 0x15, 0x0351); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0364); - rtl8168_mdio_write(tp, 0x19, 0xbc05); - rtl8168_mdio_write(tp, 0x15, 0x0367); - rtl8168_mdio_write(tp, 0x19, 0xa1fc); - rtl8168_mdio_write(tp, 0x15, 0x0368); - rtl8168_mdio_write(tp, 0x19, 0x3377); - rtl8168_mdio_write(tp, 0x15, 0x0369); - rtl8168_mdio_write(tp, 0x19, 0x328b); - rtl8168_mdio_write(tp, 0x15, 0x036a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0377); - rtl8168_mdio_write(tp, 0x19, 0x4b97); - rtl8168_mdio_write(tp, 0x15, 0x0378); - rtl8168_mdio_write(tp, 0x19, 0x6818); - rtl8168_mdio_write(tp, 0x15, 0x0379); - rtl8168_mdio_write(tp, 0x19, 0x4b07); - rtl8168_mdio_write(tp, 0x15, 0x037a); - rtl8168_mdio_write(tp, 0x19, 0x40ac); - rtl8168_mdio_write(tp, 0x15, 0x037b); - rtl8168_mdio_write(tp, 0x19, 0x4445); - rtl8168_mdio_write(tp, 0x15, 0x037c); - rtl8168_mdio_write(tp, 0x19, 0x404e); - rtl8168_mdio_write(tp, 0x15, 0x037d); - rtl8168_mdio_write(tp, 0x19, 0x4461); - rtl8168_mdio_write(tp, 0x15, 0x037e); - rtl8168_mdio_write(tp, 0x19, 0x9c09); - rtl8168_mdio_write(tp, 0x15, 0x037f); - rtl8168_mdio_write(tp, 0x19, 0x63da); - rtl8168_mdio_write(tp, 0x15, 0x0380); - rtl8168_mdio_write(tp, 0x19, 0x5440); - rtl8168_mdio_write(tp, 0x15, 0x0381); - rtl8168_mdio_write(tp, 0x19, 0x4b98); - rtl8168_mdio_write(tp, 0x15, 0x0382); - rtl8168_mdio_write(tp, 0x19, 0x7c60); - rtl8168_mdio_write(tp, 0x15, 0x0383); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x0384); - rtl8168_mdio_write(tp, 0x19, 0x4b08); - rtl8168_mdio_write(tp, 0x15, 0x0385); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x0386); - rtl8168_mdio_write(tp, 0x19, 0x338d); - rtl8168_mdio_write(tp, 0x15, 0x0387); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0388); - rtl8168_mdio_write(tp, 0x19, 0x0080); - rtl8168_mdio_write(tp, 0x15, 0x0389); - rtl8168_mdio_write(tp, 0x19, 0x820c); - rtl8168_mdio_write(tp, 0x15, 0x038a); - rtl8168_mdio_write(tp, 0x19, 0xa10b); - rtl8168_mdio_write(tp, 0x15, 0x038b); - rtl8168_mdio_write(tp, 0x19, 0x9df3); - rtl8168_mdio_write(tp, 0x15, 0x038c); - rtl8168_mdio_write(tp, 0x19, 0x3395); - rtl8168_mdio_write(tp, 0x15, 0x038d); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x038e); - rtl8168_mdio_write(tp, 0x19, 0x00f9); - rtl8168_mdio_write(tp, 0x15, 0x038f); - rtl8168_mdio_write(tp, 0x19, 0xc017); - rtl8168_mdio_write(tp, 0x15, 0x0390); - rtl8168_mdio_write(tp, 0x19, 0x0005); - rtl8168_mdio_write(tp, 0x15, 0x0391); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x0392); - rtl8168_mdio_write(tp, 0x19, 0xa103); - rtl8168_mdio_write(tp, 0x15, 0x0393); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x0394); - rtl8168_mdio_write(tp, 0x19, 0x9df9); - rtl8168_mdio_write(tp, 0x15, 0x0395); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x0396); - rtl8168_mdio_write(tp, 0x19, 0x3397); - rtl8168_mdio_write(tp, 0x15, 0x0399); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x03a4); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x03a5); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x03a6); - rtl8168_mdio_write(tp, 0x19, 0x4d08); - rtl8168_mdio_write(tp, 0x15, 0x03a7); - rtl8168_mdio_write(tp, 0x19, 0x33a9); - rtl8168_mdio_write(tp, 0x15, 0x03a8); - rtl8168_mdio_write(tp, 0x19, 0x4d00); - rtl8168_mdio_write(tp, 0x15, 0x03a9); - rtl8168_mdio_write(tp, 0x19, 0x9bfa); - rtl8168_mdio_write(tp, 0x15, 0x03aa); - rtl8168_mdio_write(tp, 0x19, 0x33b6); - rtl8168_mdio_write(tp, 0x15, 0x03bb); - rtl8168_mdio_write(tp, 0x19, 0x4056); - rtl8168_mdio_write(tp, 0x15, 0x03bc); - rtl8168_mdio_write(tp, 0x19, 0x44e9); - rtl8168_mdio_write(tp, 0x15, 0x03bd); - rtl8168_mdio_write(tp, 0x19, 0x405e); - rtl8168_mdio_write(tp, 0x15, 0x03be); - rtl8168_mdio_write(tp, 0x19, 0x44f8); - rtl8168_mdio_write(tp, 0x15, 0x03bf); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x03c0); - rtl8168_mdio_write(tp, 0x19, 0x0037); - rtl8168_mdio_write(tp, 0x15, 0x03c1); - rtl8168_mdio_write(tp, 0x19, 0xbd37); - rtl8168_mdio_write(tp, 0x15, 0x03c2); - rtl8168_mdio_write(tp, 0x19, 0x9cfd); - rtl8168_mdio_write(tp, 0x15, 0x03c3); - rtl8168_mdio_write(tp, 0x19, 0xc639); - rtl8168_mdio_write(tp, 0x15, 0x03c4); - rtl8168_mdio_write(tp, 0x19, 0x0011); - rtl8168_mdio_write(tp, 0x15, 0x03c5); - rtl8168_mdio_write(tp, 0x19, 0x9b03); - rtl8168_mdio_write(tp, 0x15, 0x03c6); - rtl8168_mdio_write(tp, 0x19, 0x7c01); - rtl8168_mdio_write(tp, 0x15, 0x03c7); - rtl8168_mdio_write(tp, 0x19, 0x4c01); - rtl8168_mdio_write(tp, 0x15, 0x03c8); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x03c9); - rtl8168_mdio_write(tp, 0x19, 0x7c20); - rtl8168_mdio_write(tp, 0x15, 0x03ca); - rtl8168_mdio_write(tp, 0x19, 0x4c20); - rtl8168_mdio_write(tp, 0x15, 0x03cb); - rtl8168_mdio_write(tp, 0x19, 0x9af4); - rtl8168_mdio_write(tp, 0x15, 0x03cc); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03cd); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03ce); - rtl8168_mdio_write(tp, 0x19, 0x4470); - rtl8168_mdio_write(tp, 0x15, 0x03cf); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03d0); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03d1); - rtl8168_mdio_write(tp, 0x19, 0x33bf); - rtl8168_mdio_write(tp, 0x15, 0x03d6); - rtl8168_mdio_write(tp, 0x19, 0x4047); - rtl8168_mdio_write(tp, 0x15, 0x03d7); - rtl8168_mdio_write(tp, 0x19, 0x4469); - rtl8168_mdio_write(tp, 0x15, 0x03d8); - rtl8168_mdio_write(tp, 0x19, 0x492b); - rtl8168_mdio_write(tp, 0x15, 0x03d9); - rtl8168_mdio_write(tp, 0x19, 0x4479); - rtl8168_mdio_write(tp, 0x15, 0x03da); - rtl8168_mdio_write(tp, 0x19, 0x7c09); - rtl8168_mdio_write(tp, 0x15, 0x03db); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x03dc); - rtl8168_mdio_write(tp, 0x19, 0x4d48); - rtl8168_mdio_write(tp, 0x15, 0x03dd); - rtl8168_mdio_write(tp, 0x19, 0x33df); - rtl8168_mdio_write(tp, 0x15, 0x03de); - rtl8168_mdio_write(tp, 0x19, 0x4d40); - rtl8168_mdio_write(tp, 0x15, 0x03df); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x03e0); - rtl8168_mdio_write(tp, 0x19, 0x0017); - rtl8168_mdio_write(tp, 0x15, 0x03e1); - rtl8168_mdio_write(tp, 0x19, 0xbd17); - rtl8168_mdio_write(tp, 0x15, 0x03e2); - rtl8168_mdio_write(tp, 0x19, 0x9b03); - rtl8168_mdio_write(tp, 0x15, 0x03e3); - rtl8168_mdio_write(tp, 0x19, 0x7c20); - rtl8168_mdio_write(tp, 0x15, 0x03e4); - rtl8168_mdio_write(tp, 0x19, 0x4c20); - rtl8168_mdio_write(tp, 0x15, 0x03e5); - rtl8168_mdio_write(tp, 0x19, 0x88f5); - rtl8168_mdio_write(tp, 0x15, 0x03e6); - rtl8168_mdio_write(tp, 0x19, 0xc428); - rtl8168_mdio_write(tp, 0x15, 0x03e7); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x03e8); - rtl8168_mdio_write(tp, 0x19, 0x9af2); - rtl8168_mdio_write(tp, 0x15, 0x03e9); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03ea); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03eb); - rtl8168_mdio_write(tp, 0x19, 0x4470); - rtl8168_mdio_write(tp, 0x15, 0x03ec); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03ed); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03ee); - rtl8168_mdio_write(tp, 0x19, 0x33da); - rtl8168_mdio_write(tp, 0x15, 0x03ef); - rtl8168_mdio_write(tp, 0x19, 0x3312); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2179); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0040); - rtl8168_mdio_write(tp, 0x18, 0x0645); - rtl8168_mdio_write(tp, 0x19, 0xe200); - rtl8168_mdio_write(tp, 0x18, 0x0655); - rtl8168_mdio_write(tp, 0x19, 0x9000); - rtl8168_mdio_write(tp, 0x18, 0x0d05); - rtl8168_mdio_write(tp, 0x19, 0xbe00); - rtl8168_mdio_write(tp, 0x18, 0x0d15); - rtl8168_mdio_write(tp, 0x19, 0xd300); - rtl8168_mdio_write(tp, 0x18, 0x0d25); - rtl8168_mdio_write(tp, 0x19, 0xfe00); - rtl8168_mdio_write(tp, 0x18, 0x0d35); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x0d45); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x0d55); - rtl8168_mdio_write(tp, 0x19, 0x1000); - rtl8168_mdio_write(tp, 0x18, 0x0d65); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x0d75); - rtl8168_mdio_write(tp, 0x19, 0x8200); - rtl8168_mdio_write(tp, 0x18, 0x0d85); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x0d95); - rtl8168_mdio_write(tp, 0x19, 0x7000); - rtl8168_mdio_write(tp, 0x18, 0x0da5); - rtl8168_mdio_write(tp, 0x19, 0x0f00); - rtl8168_mdio_write(tp, 0x18, 0x0db5); - rtl8168_mdio_write(tp, 0x19, 0x0100); - rtl8168_mdio_write(tp, 0x18, 0x0dc5); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x18, 0x0dd5); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x0de5); - rtl8168_mdio_write(tp, 0x19, 0xe000); - rtl8168_mdio_write(tp, 0x18, 0x0df5); - rtl8168_mdio_write(tp, 0x19, 0xef00); - rtl8168_mdio_write(tp, 0x18, 0x16d5); - rtl8168_mdio_write(tp, 0x19, 0xe200); - rtl8168_mdio_write(tp, 0x18, 0x16e5); - rtl8168_mdio_write(tp, 0x19, 0xab00); - rtl8168_mdio_write(tp, 0x18, 0x2904); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x2914); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x2924); - rtl8168_mdio_write(tp, 0x19, 0x0100); - rtl8168_mdio_write(tp, 0x18, 0x2934); - rtl8168_mdio_write(tp, 0x19, 0x2000); - rtl8168_mdio_write(tp, 0x18, 0x2944); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2954); - rtl8168_mdio_write(tp, 0x19, 0x4600); - rtl8168_mdio_write(tp, 0x18, 0x2964); - rtl8168_mdio_write(tp, 0x19, 0xfc00); - rtl8168_mdio_write(tp, 0x18, 0x2974); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2984); - rtl8168_mdio_write(tp, 0x19, 0x5000); - rtl8168_mdio_write(tp, 0x18, 0x2994); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x18, 0x29a4); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x29b4); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x29c4); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x29d4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x29e4); - rtl8168_mdio_write(tp, 0x19, 0x2000); - rtl8168_mdio_write(tp, 0x18, 0x29f4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2a04); - rtl8168_mdio_write(tp, 0x19, 0xe600); - rtl8168_mdio_write(tp, 0x18, 0x2a14); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x2a24); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2a34); - rtl8168_mdio_write(tp, 0x19, 0x5000); - rtl8168_mdio_write(tp, 0x18, 0x2a44); - rtl8168_mdio_write(tp, 0x19, 0x8500); - rtl8168_mdio_write(tp, 0x18, 0x2a54); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x2a64); - rtl8168_mdio_write(tp, 0x19, 0xac00); - rtl8168_mdio_write(tp, 0x18, 0x2a74); - rtl8168_mdio_write(tp, 0x19, 0x0800); - rtl8168_mdio_write(tp, 0x18, 0x2a84); - rtl8168_mdio_write(tp, 0x19, 0xfc00); - rtl8168_mdio_write(tp, 0x18, 0x2a94); - rtl8168_mdio_write(tp, 0x19, 0xe000); - rtl8168_mdio_write(tp, 0x18, 0x2aa4); - rtl8168_mdio_write(tp, 0x19, 0x7400); - rtl8168_mdio_write(tp, 0x18, 0x2ab4); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x2ac4); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x2ad4); - rtl8168_mdio_write(tp, 0x19, 0x0100); - rtl8168_mdio_write(tp, 0x18, 0x2ae4); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x2af4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2b04); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x18, 0x2b14); - rtl8168_mdio_write(tp, 0x19, 0xfc00); - rtl8168_mdio_write(tp, 0x18, 0x2b24); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2b34); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x2b44); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x18, 0x2b54); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x2b64); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x2b74); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x2b84); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2b94); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x2ba4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2bb4); - rtl8168_mdio_write(tp, 0x19, 0xfc00); - rtl8168_mdio_write(tp, 0x18, 0x2bc4); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x2bd4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2be4); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x2bf4); - rtl8168_mdio_write(tp, 0x19, 0x8900); - rtl8168_mdio_write(tp, 0x18, 0x2c04); - rtl8168_mdio_write(tp, 0x19, 0x8300); - rtl8168_mdio_write(tp, 0x18, 0x2c14); - rtl8168_mdio_write(tp, 0x19, 0xe000); - rtl8168_mdio_write(tp, 0x18, 0x2c24); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2c34); - rtl8168_mdio_write(tp, 0x19, 0xac00); - rtl8168_mdio_write(tp, 0x18, 0x2c44); - rtl8168_mdio_write(tp, 0x19, 0x0800); - rtl8168_mdio_write(tp, 0x18, 0x2c54); - rtl8168_mdio_write(tp, 0x19, 0xfa00); - rtl8168_mdio_write(tp, 0x18, 0x2c64); - rtl8168_mdio_write(tp, 0x19, 0xe100); - rtl8168_mdio_write(tp, 0x18, 0x2c74); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x0001); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2100); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8b88); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0xd480); - rtl8168_mdio_write(tp, 0x06, 0xc1e4); - rtl8168_mdio_write(tp, 0x06, 0x8b9a); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x9bee); - rtl8168_mdio_write(tp, 0x06, 0x8b83); - rtl8168_mdio_write(tp, 0x06, 0x41bf); - rtl8168_mdio_write(tp, 0x06, 0x8b88); - rtl8168_mdio_write(tp, 0x06, 0xec00); - rtl8168_mdio_write(tp, 0x06, 0x19a9); - rtl8168_mdio_write(tp, 0x06, 0x8b90); - rtl8168_mdio_write(tp, 0x06, 0xf9ee); - rtl8168_mdio_write(tp, 0x06, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x41f7); - rtl8168_mdio_write(tp, 0x06, 0x2ff6); - rtl8168_mdio_write(tp, 0x06, 0x28e4); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xe5e1); - rtl8168_mdio_write(tp, 0x06, 0x41f7); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x020c); - rtl8168_mdio_write(tp, 0x06, 0x0202); - rtl8168_mdio_write(tp, 0x06, 0x1d02); - rtl8168_mdio_write(tp, 0x06, 0x0230); - rtl8168_mdio_write(tp, 0x06, 0x0202); - rtl8168_mdio_write(tp, 0x06, 0x4002); - rtl8168_mdio_write(tp, 0x06, 0x028b); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x6c02); - rtl8168_mdio_write(tp, 0x06, 0x8085); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaec3); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x10ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x1310); - rtl8168_mdio_write(tp, 0x06, 0x021f); - rtl8168_mdio_write(tp, 0x06, 0x9d02); - rtl8168_mdio_write(tp, 0x06, 0x1f0c); - rtl8168_mdio_write(tp, 0x06, 0x0227); - rtl8168_mdio_write(tp, 0x06, 0x49fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x200b); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x830e); - rtl8168_mdio_write(tp, 0x06, 0x021b); - rtl8168_mdio_write(tp, 0x06, 0x67ad); - rtl8168_mdio_write(tp, 0x06, 0x2211); - rtl8168_mdio_write(tp, 0x06, 0xf622); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x2ba5); - rtl8168_mdio_write(tp, 0x06, 0x022a); - rtl8168_mdio_write(tp, 0x06, 0x2402); - rtl8168_mdio_write(tp, 0x06, 0x80c6); - rtl8168_mdio_write(tp, 0x06, 0x022a); - rtl8168_mdio_write(tp, 0x06, 0xf0ad); - rtl8168_mdio_write(tp, 0x06, 0x2511); - rtl8168_mdio_write(tp, 0x06, 0xf625); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x8226); - rtl8168_mdio_write(tp, 0x06, 0x0204); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x19cc); - rtl8168_mdio_write(tp, 0x06, 0x022b); - rtl8168_mdio_write(tp, 0x06, 0x5bfc); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x0105); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b83); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x44e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x23ad); - rtl8168_mdio_write(tp, 0x06, 0x223b); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xbea0); - rtl8168_mdio_write(tp, 0x06, 0x0005); - rtl8168_mdio_write(tp, 0x06, 0x0228); - rtl8168_mdio_write(tp, 0x06, 0xdeae); - rtl8168_mdio_write(tp, 0x06, 0x42a0); - rtl8168_mdio_write(tp, 0x06, 0x0105); - rtl8168_mdio_write(tp, 0x06, 0x0228); - rtl8168_mdio_write(tp, 0x06, 0xf1ae); - rtl8168_mdio_write(tp, 0x06, 0x3aa0); - rtl8168_mdio_write(tp, 0x06, 0x0205); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x25ae); - rtl8168_mdio_write(tp, 0x06, 0x32a0); - rtl8168_mdio_write(tp, 0x06, 0x0305); - rtl8168_mdio_write(tp, 0x06, 0x0229); - rtl8168_mdio_write(tp, 0x06, 0x9aae); - rtl8168_mdio_write(tp, 0x06, 0x2aa0); - rtl8168_mdio_write(tp, 0x06, 0x0405); - rtl8168_mdio_write(tp, 0x06, 0x0229); - rtl8168_mdio_write(tp, 0x06, 0xaeae); - rtl8168_mdio_write(tp, 0x06, 0x22a0); - rtl8168_mdio_write(tp, 0x06, 0x0505); - rtl8168_mdio_write(tp, 0x06, 0x0229); - rtl8168_mdio_write(tp, 0x06, 0xd7ae); - rtl8168_mdio_write(tp, 0x06, 0x1aa0); - rtl8168_mdio_write(tp, 0x06, 0x0605); - rtl8168_mdio_write(tp, 0x06, 0x0229); - rtl8168_mdio_write(tp, 0x06, 0xfeae); - rtl8168_mdio_write(tp, 0x06, 0x12ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac0); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac1); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x00fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0x022a); - rtl8168_mdio_write(tp, 0x06, 0x67e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x230d); - rtl8168_mdio_write(tp, 0x06, 0x0658); - rtl8168_mdio_write(tp, 0x06, 0x03a0); - rtl8168_mdio_write(tp, 0x06, 0x0202); - rtl8168_mdio_write(tp, 0x06, 0xae2d); - rtl8168_mdio_write(tp, 0x06, 0xa001); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x2da0); - rtl8168_mdio_write(tp, 0x06, 0x004d); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe201); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x44e0); - rtl8168_mdio_write(tp, 0x06, 0x8ac2); - rtl8168_mdio_write(tp, 0x06, 0xe48a); - rtl8168_mdio_write(tp, 0x06, 0xc4e0); - rtl8168_mdio_write(tp, 0x06, 0x8ac3); - rtl8168_mdio_write(tp, 0x06, 0xe48a); - rtl8168_mdio_write(tp, 0x06, 0xc5ee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x03e0); - rtl8168_mdio_write(tp, 0x06, 0x8b83); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x3aee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x05ae); - rtl8168_mdio_write(tp, 0x06, 0x34e0); - rtl8168_mdio_write(tp, 0x06, 0x8ace); - rtl8168_mdio_write(tp, 0x06, 0xae03); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xcfe1); - rtl8168_mdio_write(tp, 0x06, 0x8ac2); - rtl8168_mdio_write(tp, 0x06, 0x4905); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xc4e1); - rtl8168_mdio_write(tp, 0x06, 0x8ac3); - rtl8168_mdio_write(tp, 0x06, 0x4905); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xc5ee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x2ab6); - rtl8168_mdio_write(tp, 0x06, 0xac20); - rtl8168_mdio_write(tp, 0x06, 0x1202); - rtl8168_mdio_write(tp, 0x06, 0x819b); - rtl8168_mdio_write(tp, 0x06, 0xac20); - rtl8168_mdio_write(tp, 0x06, 0x0cee); - rtl8168_mdio_write(tp, 0x06, 0x8ac1); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x02fc); - rtl8168_mdio_write(tp, 0x06, 0x04d0); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x590f); - rtl8168_mdio_write(tp, 0x06, 0x3902); - rtl8168_mdio_write(tp, 0x06, 0xaa04); - rtl8168_mdio_write(tp, 0x06, 0xd001); - rtl8168_mdio_write(tp, 0x06, 0xae02); - rtl8168_mdio_write(tp, 0x06, 0xd000); - rtl8168_mdio_write(tp, 0x06, 0x04f9); - rtl8168_mdio_write(tp, 0x06, 0xfae2); - rtl8168_mdio_write(tp, 0x06, 0xe2d2); - rtl8168_mdio_write(tp, 0x06, 0xe3e2); - rtl8168_mdio_write(tp, 0x06, 0xd3f9); - rtl8168_mdio_write(tp, 0x06, 0x5af7); - rtl8168_mdio_write(tp, 0x06, 0xe6e2); - rtl8168_mdio_write(tp, 0x06, 0xd2e7); - rtl8168_mdio_write(tp, 0x06, 0xe2d3); - rtl8168_mdio_write(tp, 0x06, 0xe2e0); - rtl8168_mdio_write(tp, 0x06, 0x2ce3); - rtl8168_mdio_write(tp, 0x06, 0xe02d); - rtl8168_mdio_write(tp, 0x06, 0xf95b); - rtl8168_mdio_write(tp, 0x06, 0xe01e); - rtl8168_mdio_write(tp, 0x06, 0x30e6); - rtl8168_mdio_write(tp, 0x06, 0xe02c); - rtl8168_mdio_write(tp, 0x06, 0xe7e0); - rtl8168_mdio_write(tp, 0x06, 0x2de2); - rtl8168_mdio_write(tp, 0x06, 0xe2cc); - rtl8168_mdio_write(tp, 0x06, 0xe3e2); - rtl8168_mdio_write(tp, 0x06, 0xcdf9); - rtl8168_mdio_write(tp, 0x06, 0x5a0f); - rtl8168_mdio_write(tp, 0x06, 0x6a50); - rtl8168_mdio_write(tp, 0x06, 0xe6e2); - rtl8168_mdio_write(tp, 0x06, 0xcce7); - rtl8168_mdio_write(tp, 0x06, 0xe2cd); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x3ce1); - rtl8168_mdio_write(tp, 0x06, 0xe03d); - rtl8168_mdio_write(tp, 0x06, 0xef64); - rtl8168_mdio_write(tp, 0x06, 0xfde0); - rtl8168_mdio_write(tp, 0x06, 0xe2cc); - rtl8168_mdio_write(tp, 0x06, 0xe1e2); - rtl8168_mdio_write(tp, 0x06, 0xcd58); - rtl8168_mdio_write(tp, 0x06, 0x0f5a); - rtl8168_mdio_write(tp, 0x06, 0xf01e); - rtl8168_mdio_write(tp, 0x06, 0x02e4); - rtl8168_mdio_write(tp, 0x06, 0xe2cc); - rtl8168_mdio_write(tp, 0x06, 0xe5e2); - rtl8168_mdio_write(tp, 0x06, 0xcdfd); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x2ce1); - rtl8168_mdio_write(tp, 0x06, 0xe02d); - rtl8168_mdio_write(tp, 0x06, 0x59e0); - rtl8168_mdio_write(tp, 0x06, 0x5b1f); - rtl8168_mdio_write(tp, 0x06, 0x1e13); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x2ce5); - rtl8168_mdio_write(tp, 0x06, 0xe02d); - rtl8168_mdio_write(tp, 0x06, 0xfde0); - rtl8168_mdio_write(tp, 0x06, 0xe2d2); - rtl8168_mdio_write(tp, 0x06, 0xe1e2); - rtl8168_mdio_write(tp, 0x06, 0xd358); - rtl8168_mdio_write(tp, 0x06, 0xf75a); - rtl8168_mdio_write(tp, 0x06, 0x081e); - rtl8168_mdio_write(tp, 0x06, 0x02e4); - rtl8168_mdio_write(tp, 0x06, 0xe2d2); - rtl8168_mdio_write(tp, 0x06, 0xe5e2); - rtl8168_mdio_write(tp, 0x06, 0xd3ef); - rtl8168_mdio_write(tp, 0x06, 0x46fe); - rtl8168_mdio_write(tp, 0x06, 0xfd04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xc4e1); - rtl8168_mdio_write(tp, 0x06, 0x8b6e); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e58); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x6ead); - rtl8168_mdio_write(tp, 0x06, 0x2222); - rtl8168_mdio_write(tp, 0x06, 0xac27); - rtl8168_mdio_write(tp, 0x06, 0x55ac); - rtl8168_mdio_write(tp, 0x06, 0x2602); - rtl8168_mdio_write(tp, 0x06, 0xae1a); - rtl8168_mdio_write(tp, 0x06, 0xd106); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xba02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd107); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xbd02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd107); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xc002); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xae30); - rtl8168_mdio_write(tp, 0x06, 0xd103); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xc302); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xc602); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xca02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd10f); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xba02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xbd02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xc002); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xc302); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd011); - rtl8168_mdio_write(tp, 0x06, 0x022b); - rtl8168_mdio_write(tp, 0x06, 0xfb59); - rtl8168_mdio_write(tp, 0x06, 0x03ef); - rtl8168_mdio_write(tp, 0x06, 0x01d1); - rtl8168_mdio_write(tp, 0x06, 0x00a0); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xc602); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd111); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x020c); - rtl8168_mdio_write(tp, 0x06, 0x11ad); - rtl8168_mdio_write(tp, 0x06, 0x2102); - rtl8168_mdio_write(tp, 0x06, 0x0c12); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xca02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xaec8); - rtl8168_mdio_write(tp, 0x06, 0x70e4); - rtl8168_mdio_write(tp, 0x06, 0x2602); - rtl8168_mdio_write(tp, 0x06, 0x82d1); - rtl8168_mdio_write(tp, 0x06, 0x05f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0xe2fe); - rtl8168_mdio_write(tp, 0x06, 0xe1e2); - rtl8168_mdio_write(tp, 0x06, 0xffad); - rtl8168_mdio_write(tp, 0x06, 0x2d1a); - rtl8168_mdio_write(tp, 0x06, 0xe0e1); - rtl8168_mdio_write(tp, 0x06, 0x4ee1); - rtl8168_mdio_write(tp, 0x06, 0xe14f); - rtl8168_mdio_write(tp, 0x06, 0xac2d); - rtl8168_mdio_write(tp, 0x06, 0x22f6); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x033b); - rtl8168_mdio_write(tp, 0x06, 0xf703); - rtl8168_mdio_write(tp, 0x06, 0xf706); - rtl8168_mdio_write(tp, 0x06, 0xbf84); - rtl8168_mdio_write(tp, 0x06, 0x4402); - rtl8168_mdio_write(tp, 0x06, 0x2d21); - rtl8168_mdio_write(tp, 0x06, 0xae11); - rtl8168_mdio_write(tp, 0x06, 0xe0e1); - rtl8168_mdio_write(tp, 0x06, 0x4ee1); - rtl8168_mdio_write(tp, 0x06, 0xe14f); - rtl8168_mdio_write(tp, 0x06, 0xad2d); - rtl8168_mdio_write(tp, 0x06, 0x08bf); - rtl8168_mdio_write(tp, 0x06, 0x844f); - rtl8168_mdio_write(tp, 0x06, 0x022d); - rtl8168_mdio_write(tp, 0x06, 0x21f6); - rtl8168_mdio_write(tp, 0x06, 0x06ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0x4502); - rtl8168_mdio_write(tp, 0x06, 0x83a2); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe001); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x1fd1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x843b); - rtl8168_mdio_write(tp, 0x06, 0x022d); - rtl8168_mdio_write(tp, 0x06, 0xc1e0); - rtl8168_mdio_write(tp, 0x06, 0xe020); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x21ad); - rtl8168_mdio_write(tp, 0x06, 0x200e); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf84); - rtl8168_mdio_write(tp, 0x06, 0x3b02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0x9602); - rtl8168_mdio_write(tp, 0x06, 0x2d21); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x204c); - rtl8168_mdio_write(tp, 0x06, 0xd200); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x0058); - rtl8168_mdio_write(tp, 0x06, 0x010c); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0x5810); - rtl8168_mdio_write(tp, 0x06, 0x1e20); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x3658); - rtl8168_mdio_write(tp, 0x06, 0x031e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xe01e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0x8b64); - rtl8168_mdio_write(tp, 0x06, 0x1f02); - rtl8168_mdio_write(tp, 0x06, 0x9e22); - rtl8168_mdio_write(tp, 0x06, 0xe68b); - rtl8168_mdio_write(tp, 0x06, 0x64ad); - rtl8168_mdio_write(tp, 0x06, 0x3214); - rtl8168_mdio_write(tp, 0x06, 0xad34); - rtl8168_mdio_write(tp, 0x06, 0x11ef); - rtl8168_mdio_write(tp, 0x06, 0x0258); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x07ad); - rtl8168_mdio_write(tp, 0x06, 0x3508); - rtl8168_mdio_write(tp, 0x06, 0x5ac0); - rtl8168_mdio_write(tp, 0x06, 0x9f04); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xae02); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf84); - rtl8168_mdio_write(tp, 0x06, 0x3e02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfbe0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x22e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x23e2); - rtl8168_mdio_write(tp, 0x06, 0xe036); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0x375a); - rtl8168_mdio_write(tp, 0x06, 0xc40d); - rtl8168_mdio_write(tp, 0x06, 0x0158); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x20e3); - rtl8168_mdio_write(tp, 0x06, 0x8ae7); - rtl8168_mdio_write(tp, 0x06, 0xac31); - rtl8168_mdio_write(tp, 0x06, 0x60ac); - rtl8168_mdio_write(tp, 0x06, 0x3a08); - rtl8168_mdio_write(tp, 0x06, 0xac3e); - rtl8168_mdio_write(tp, 0x06, 0x26ae); - rtl8168_mdio_write(tp, 0x06, 0x67af); - rtl8168_mdio_write(tp, 0x06, 0x8437); - rtl8168_mdio_write(tp, 0x06, 0xad37); - rtl8168_mdio_write(tp, 0x06, 0x61e0); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xe91b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x51d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8441); - rtl8168_mdio_write(tp, 0x06, 0x022d); - rtl8168_mdio_write(tp, 0x06, 0xc1ee); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x43ad); - rtl8168_mdio_write(tp, 0x06, 0x3627); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xeee1); - rtl8168_mdio_write(tp, 0x06, 0x8aef); - rtl8168_mdio_write(tp, 0x06, 0xef74); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xeae1); - rtl8168_mdio_write(tp, 0x06, 0x8aeb); - rtl8168_mdio_write(tp, 0x06, 0x1b74); - rtl8168_mdio_write(tp, 0x06, 0x9e2e); - rtl8168_mdio_write(tp, 0x06, 0x14e4); - rtl8168_mdio_write(tp, 0x06, 0x8aea); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xebef); - rtl8168_mdio_write(tp, 0x06, 0x74e0); - rtl8168_mdio_write(tp, 0x06, 0x8aee); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xef1b); - rtl8168_mdio_write(tp, 0x06, 0x479e); - rtl8168_mdio_write(tp, 0x06, 0x0fae); - rtl8168_mdio_write(tp, 0x06, 0x19ee); - rtl8168_mdio_write(tp, 0x06, 0x8aea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8aeb); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x0fac); - rtl8168_mdio_write(tp, 0x06, 0x390c); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf84); - rtl8168_mdio_write(tp, 0x06, 0x4102); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe800); - rtl8168_mdio_write(tp, 0x06, 0xe68a); - rtl8168_mdio_write(tp, 0x06, 0xe7ff); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x0400); - rtl8168_mdio_write(tp, 0x06, 0xe234); - rtl8168_mdio_write(tp, 0x06, 0xcce2); - rtl8168_mdio_write(tp, 0x06, 0x0088); - rtl8168_mdio_write(tp, 0x06, 0xe200); - rtl8168_mdio_write(tp, 0x06, 0xa725); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x1de5); - rtl8168_mdio_write(tp, 0x06, 0x0a2c); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x6de5); - rtl8168_mdio_write(tp, 0x06, 0x0a1d); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x1ce5); - rtl8168_mdio_write(tp, 0x06, 0x0a2d); - rtl8168_mdio_write(tp, 0x06, 0xa755); - rtl8168_mdio_write(tp, 0x05, 0x8b64); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8b94); - rtl8168_mdio_write(tp, 0x06, 0x82cd); - rtl8168_mdio_write(tp, 0x05, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0x2000); - rtl8168_mdio_write(tp, 0x05, 0x8aee); - rtl8168_mdio_write(tp, 0x06, 0x03b8); - rtl8168_mdio_write(tp, 0x05, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x01); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x01, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~(BIT_2); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0028); - rtl8168_mdio_write(tp, 0x15, 0x0010); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0041); - rtl8168_mdio_write(tp, 0x15, 0x0802); - rtl8168_mdio_write(tp, 0x16, 0x2185); - rtl8168_mdio_write(tp, 0x1f, 0x0000); -} - -static void -rtl8168_set_phy_mcu_8168e_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val,i; - - if (rtl8168_efuse_read(tp, 0x22) == 0x0c) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x1800); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x17, 0x0117); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - rtl8168_mdio_write(tp, 0x1B, 0x5000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x4104); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1E); - gphy_val &= 0x03FF; - if (gphy_val==0x000C) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x07); - if ((gphy_val & BIT_5) == 0) - break; - } - gphy_val = rtl8168_mdio_read(tp, 0x07); - if (gphy_val & BIT_5) { - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x00a1); - rtl8168_mdio_write(tp, 0x17, 0x1000); - rtl8168_mdio_write(tp, 0x17, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2000); - rtl8168_mdio_write(tp, 0x1e, 0x002f); - rtl8168_mdio_write(tp, 0x18, 0x9bfb); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x07, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x08); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x08, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x000e); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x0010); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x0018); - rtl8168_mdio_write(tp, 0x19, 0x4801); - rtl8168_mdio_write(tp, 0x15, 0x0019); - rtl8168_mdio_write(tp, 0x19, 0x6801); - rtl8168_mdio_write(tp, 0x15, 0x001a); - rtl8168_mdio_write(tp, 0x19, 0x66a1); - rtl8168_mdio_write(tp, 0x15, 0x001f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0020); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0021); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0022); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0023); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0024); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0025); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0026); - rtl8168_mdio_write(tp, 0x19, 0x40ea); - rtl8168_mdio_write(tp, 0x15, 0x0027); - rtl8168_mdio_write(tp, 0x19, 0x4503); - rtl8168_mdio_write(tp, 0x15, 0x0028); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0029); - rtl8168_mdio_write(tp, 0x19, 0xa631); - rtl8168_mdio_write(tp, 0x15, 0x002a); - rtl8168_mdio_write(tp, 0x19, 0x9717); - rtl8168_mdio_write(tp, 0x15, 0x002b); - rtl8168_mdio_write(tp, 0x19, 0x302c); - rtl8168_mdio_write(tp, 0x15, 0x002c); - rtl8168_mdio_write(tp, 0x19, 0x4802); - rtl8168_mdio_write(tp, 0x15, 0x002d); - rtl8168_mdio_write(tp, 0x19, 0x58da); - rtl8168_mdio_write(tp, 0x15, 0x002e); - rtl8168_mdio_write(tp, 0x19, 0x400d); - rtl8168_mdio_write(tp, 0x15, 0x002f); - rtl8168_mdio_write(tp, 0x19, 0x4488); - rtl8168_mdio_write(tp, 0x15, 0x0030); - rtl8168_mdio_write(tp, 0x19, 0x9e00); - rtl8168_mdio_write(tp, 0x15, 0x0031); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0032); - rtl8168_mdio_write(tp, 0x19, 0x6481); - rtl8168_mdio_write(tp, 0x15, 0x0033); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0034); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0035); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0036); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0037); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0038); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0039); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x003a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x003b); - rtl8168_mdio_write(tp, 0x19, 0x63e8); - rtl8168_mdio_write(tp, 0x15, 0x003c); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x003d); - rtl8168_mdio_write(tp, 0x19, 0x59d4); - rtl8168_mdio_write(tp, 0x15, 0x003e); - rtl8168_mdio_write(tp, 0x19, 0x63f8); - rtl8168_mdio_write(tp, 0x15, 0x0040); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0041); - rtl8168_mdio_write(tp, 0x19, 0x30de); - rtl8168_mdio_write(tp, 0x15, 0x0044); - rtl8168_mdio_write(tp, 0x19, 0x480f); - rtl8168_mdio_write(tp, 0x15, 0x0045); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x0046); - rtl8168_mdio_write(tp, 0x19, 0x6680); - rtl8168_mdio_write(tp, 0x15, 0x0047); - rtl8168_mdio_write(tp, 0x19, 0x7c10); - rtl8168_mdio_write(tp, 0x15, 0x0048); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0049); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004f); - rtl8168_mdio_write(tp, 0x19, 0x40ea); - rtl8168_mdio_write(tp, 0x15, 0x0050); - rtl8168_mdio_write(tp, 0x19, 0x4503); - rtl8168_mdio_write(tp, 0x15, 0x0051); - rtl8168_mdio_write(tp, 0x19, 0x58ca); - rtl8168_mdio_write(tp, 0x15, 0x0052); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0053); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x0054); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x0055); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0056); - rtl8168_mdio_write(tp, 0x19, 0x3000); - rtl8168_mdio_write(tp, 0x15, 0x00a1); - rtl8168_mdio_write(tp, 0x19, 0x3044); - rtl8168_mdio_write(tp, 0x15, 0x00ab); - rtl8168_mdio_write(tp, 0x19, 0x5820); - rtl8168_mdio_write(tp, 0x15, 0x00ac); - rtl8168_mdio_write(tp, 0x19, 0x5e04); - rtl8168_mdio_write(tp, 0x15, 0x00ad); - rtl8168_mdio_write(tp, 0x19, 0xb60c); - rtl8168_mdio_write(tp, 0x15, 0x00af); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x00b2); - rtl8168_mdio_write(tp, 0x19, 0x30b9); - rtl8168_mdio_write(tp, 0x15, 0x00b9); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x00ba); - rtl8168_mdio_write(tp, 0x19, 0x480b); - rtl8168_mdio_write(tp, 0x15, 0x00bb); - rtl8168_mdio_write(tp, 0x19, 0x5e00); - rtl8168_mdio_write(tp, 0x15, 0x00bc); - rtl8168_mdio_write(tp, 0x19, 0x405f); - rtl8168_mdio_write(tp, 0x15, 0x00bd); - rtl8168_mdio_write(tp, 0x19, 0x4448); - rtl8168_mdio_write(tp, 0x15, 0x00be); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x00bf); - rtl8168_mdio_write(tp, 0x19, 0x4468); - rtl8168_mdio_write(tp, 0x15, 0x00c0); - rtl8168_mdio_write(tp, 0x19, 0x9c02); - rtl8168_mdio_write(tp, 0x15, 0x00c1); - rtl8168_mdio_write(tp, 0x19, 0x58a0); - rtl8168_mdio_write(tp, 0x15, 0x00c2); - rtl8168_mdio_write(tp, 0x19, 0xb605); - rtl8168_mdio_write(tp, 0x15, 0x00c3); - rtl8168_mdio_write(tp, 0x19, 0xc0d3); - rtl8168_mdio_write(tp, 0x15, 0x00c4); - rtl8168_mdio_write(tp, 0x19, 0x00e6); - rtl8168_mdio_write(tp, 0x15, 0x00c5); - rtl8168_mdio_write(tp, 0x19, 0xdaec); - rtl8168_mdio_write(tp, 0x15, 0x00c6); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00c7); - rtl8168_mdio_write(tp, 0x19, 0x9df9); - rtl8168_mdio_write(tp, 0x15, 0x0112); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0113); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0114); - rtl8168_mdio_write(tp, 0x19, 0x63f0); - rtl8168_mdio_write(tp, 0x15, 0x0115); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0116); - rtl8168_mdio_write(tp, 0x19, 0x4418); - rtl8168_mdio_write(tp, 0x15, 0x0117); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x15, 0x0118); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0119); - rtl8168_mdio_write(tp, 0x19, 0x64e1); - rtl8168_mdio_write(tp, 0x15, 0x011a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0150); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0151); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0152); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0153); - rtl8168_mdio_write(tp, 0x19, 0x4540); - rtl8168_mdio_write(tp, 0x15, 0x0154); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0155); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x15, 0x0156); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0157); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0158); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0159); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x015a); - rtl8168_mdio_write(tp, 0x19, 0x30fe); - rtl8168_mdio_write(tp, 0x15, 0x029c); - rtl8168_mdio_write(tp, 0x19, 0x0070); - rtl8168_mdio_write(tp, 0x15, 0x02b2); - rtl8168_mdio_write(tp, 0x19, 0x005a); - rtl8168_mdio_write(tp, 0x15, 0x02bd); - rtl8168_mdio_write(tp, 0x19, 0xa522); - rtl8168_mdio_write(tp, 0x15, 0x02ce); - rtl8168_mdio_write(tp, 0x19, 0xb63e); - rtl8168_mdio_write(tp, 0x15, 0x02d9); - rtl8168_mdio_write(tp, 0x19, 0x32df); - rtl8168_mdio_write(tp, 0x15, 0x02df); - rtl8168_mdio_write(tp, 0x19, 0x4500); - rtl8168_mdio_write(tp, 0x15, 0x02e7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02f4); - rtl8168_mdio_write(tp, 0x19, 0xb618); - rtl8168_mdio_write(tp, 0x15, 0x02fb); - rtl8168_mdio_write(tp, 0x19, 0xb900); - rtl8168_mdio_write(tp, 0x15, 0x02fc); - rtl8168_mdio_write(tp, 0x19, 0x49b5); - rtl8168_mdio_write(tp, 0x15, 0x02fd); - rtl8168_mdio_write(tp, 0x19, 0x6812); - rtl8168_mdio_write(tp, 0x15, 0x02fe); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x02ff); - rtl8168_mdio_write(tp, 0x19, 0x9900); - rtl8168_mdio_write(tp, 0x15, 0x0300); - rtl8168_mdio_write(tp, 0x19, 0x64a0); - rtl8168_mdio_write(tp, 0x15, 0x0301); - rtl8168_mdio_write(tp, 0x19, 0x3316); - rtl8168_mdio_write(tp, 0x15, 0x0308); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030c); - rtl8168_mdio_write(tp, 0x19, 0x3000); - rtl8168_mdio_write(tp, 0x15, 0x0312); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0313); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0314); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0315); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0316); - rtl8168_mdio_write(tp, 0x19, 0x49b5); - rtl8168_mdio_write(tp, 0x15, 0x0317); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x0318); - rtl8168_mdio_write(tp, 0x19, 0x4d00); - rtl8168_mdio_write(tp, 0x15, 0x0319); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x031a); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x031b); - rtl8168_mdio_write(tp, 0x19, 0x4925); - rtl8168_mdio_write(tp, 0x15, 0x031c); - rtl8168_mdio_write(tp, 0x19, 0x403b); - rtl8168_mdio_write(tp, 0x15, 0x031d); - rtl8168_mdio_write(tp, 0x19, 0xa602); - rtl8168_mdio_write(tp, 0x15, 0x031e); - rtl8168_mdio_write(tp, 0x19, 0x402f); - rtl8168_mdio_write(tp, 0x15, 0x031f); - rtl8168_mdio_write(tp, 0x19, 0x4484); - rtl8168_mdio_write(tp, 0x15, 0x0320); - rtl8168_mdio_write(tp, 0x19, 0x40c8); - rtl8168_mdio_write(tp, 0x15, 0x0321); - rtl8168_mdio_write(tp, 0x19, 0x44c4); - rtl8168_mdio_write(tp, 0x15, 0x0322); - rtl8168_mdio_write(tp, 0x19, 0x404f); - rtl8168_mdio_write(tp, 0x15, 0x0323); - rtl8168_mdio_write(tp, 0x19, 0x44c8); - rtl8168_mdio_write(tp, 0x15, 0x0324); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0325); - rtl8168_mdio_write(tp, 0x19, 0x00e7); - rtl8168_mdio_write(tp, 0x15, 0x0326); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0327); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x0328); - rtl8168_mdio_write(tp, 0x19, 0x4d48); - rtl8168_mdio_write(tp, 0x15, 0x0329); - rtl8168_mdio_write(tp, 0x19, 0x332b); - rtl8168_mdio_write(tp, 0x15, 0x032a); - rtl8168_mdio_write(tp, 0x19, 0x4d40); - rtl8168_mdio_write(tp, 0x15, 0x032c); - rtl8168_mdio_write(tp, 0x19, 0x00f8); - rtl8168_mdio_write(tp, 0x15, 0x032d); - rtl8168_mdio_write(tp, 0x19, 0x82b2); - rtl8168_mdio_write(tp, 0x15, 0x032f); - rtl8168_mdio_write(tp, 0x19, 0x00b0); - rtl8168_mdio_write(tp, 0x15, 0x0332); - rtl8168_mdio_write(tp, 0x19, 0x91f2); - rtl8168_mdio_write(tp, 0x15, 0x033f); - rtl8168_mdio_write(tp, 0x19, 0xb6cd); - rtl8168_mdio_write(tp, 0x15, 0x0340); - rtl8168_mdio_write(tp, 0x19, 0x9e01); - rtl8168_mdio_write(tp, 0x15, 0x0341); - rtl8168_mdio_write(tp, 0x19, 0xd11d); - rtl8168_mdio_write(tp, 0x15, 0x0342); - rtl8168_mdio_write(tp, 0x19, 0x009d); - rtl8168_mdio_write(tp, 0x15, 0x0343); - rtl8168_mdio_write(tp, 0x19, 0xbb1c); - rtl8168_mdio_write(tp, 0x15, 0x0344); - rtl8168_mdio_write(tp, 0x19, 0x8102); - rtl8168_mdio_write(tp, 0x15, 0x0345); - rtl8168_mdio_write(tp, 0x19, 0x3348); - rtl8168_mdio_write(tp, 0x15, 0x0346); - rtl8168_mdio_write(tp, 0x19, 0xa231); - rtl8168_mdio_write(tp, 0x15, 0x0347); - rtl8168_mdio_write(tp, 0x19, 0x335b); - rtl8168_mdio_write(tp, 0x15, 0x0348); - rtl8168_mdio_write(tp, 0x19, 0x91f7); - rtl8168_mdio_write(tp, 0x15, 0x0349); - rtl8168_mdio_write(tp, 0x19, 0xc218); - rtl8168_mdio_write(tp, 0x15, 0x034a); - rtl8168_mdio_write(tp, 0x19, 0x00f5); - rtl8168_mdio_write(tp, 0x15, 0x034b); - rtl8168_mdio_write(tp, 0x19, 0x335b); - rtl8168_mdio_write(tp, 0x15, 0x034c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x034d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x034e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x034f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0350); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x035b); - rtl8168_mdio_write(tp, 0x19, 0xa23c); - rtl8168_mdio_write(tp, 0x15, 0x035c); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x035d); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x035e); - rtl8168_mdio_write(tp, 0x19, 0x3397); - rtl8168_mdio_write(tp, 0x15, 0x0363); - rtl8168_mdio_write(tp, 0x19, 0xb6a9); - rtl8168_mdio_write(tp, 0x15, 0x0366); - rtl8168_mdio_write(tp, 0x19, 0x00f5); - rtl8168_mdio_write(tp, 0x15, 0x0382); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0388); - rtl8168_mdio_write(tp, 0x19, 0x0084); - rtl8168_mdio_write(tp, 0x15, 0x0389); - rtl8168_mdio_write(tp, 0x19, 0xdd17); - rtl8168_mdio_write(tp, 0x15, 0x038a); - rtl8168_mdio_write(tp, 0x19, 0x000b); - rtl8168_mdio_write(tp, 0x15, 0x038b); - rtl8168_mdio_write(tp, 0x19, 0xa10a); - rtl8168_mdio_write(tp, 0x15, 0x038c); - rtl8168_mdio_write(tp, 0x19, 0x337e); - rtl8168_mdio_write(tp, 0x15, 0x038d); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x038e); - rtl8168_mdio_write(tp, 0x19, 0xa107); - rtl8168_mdio_write(tp, 0x15, 0x038f); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x0390); - rtl8168_mdio_write(tp, 0x19, 0xc017); - rtl8168_mdio_write(tp, 0x15, 0x0391); - rtl8168_mdio_write(tp, 0x19, 0x0004); - rtl8168_mdio_write(tp, 0x15, 0x0392); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0393); - rtl8168_mdio_write(tp, 0x19, 0x00f4); - rtl8168_mdio_write(tp, 0x15, 0x0397); - rtl8168_mdio_write(tp, 0x19, 0x4098); - rtl8168_mdio_write(tp, 0x15, 0x0398); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x0399); - rtl8168_mdio_write(tp, 0x19, 0x55bf); - rtl8168_mdio_write(tp, 0x15, 0x039a); - rtl8168_mdio_write(tp, 0x19, 0x4bb9); - rtl8168_mdio_write(tp, 0x15, 0x039b); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x039c); - rtl8168_mdio_write(tp, 0x19, 0x4b29); - rtl8168_mdio_write(tp, 0x15, 0x039d); - rtl8168_mdio_write(tp, 0x19, 0x4041); - rtl8168_mdio_write(tp, 0x15, 0x039e); - rtl8168_mdio_write(tp, 0x19, 0x442a); - rtl8168_mdio_write(tp, 0x15, 0x039f); - rtl8168_mdio_write(tp, 0x19, 0x4029); - rtl8168_mdio_write(tp, 0x15, 0x03aa); - rtl8168_mdio_write(tp, 0x19, 0x33b8); - rtl8168_mdio_write(tp, 0x15, 0x03b6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b8); - rtl8168_mdio_write(tp, 0x19, 0x543f); - rtl8168_mdio_write(tp, 0x15, 0x03b9); - rtl8168_mdio_write(tp, 0x19, 0x499a); - rtl8168_mdio_write(tp, 0x15, 0x03ba); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x03bb); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03bc); - rtl8168_mdio_write(tp, 0x19, 0x490a); - rtl8168_mdio_write(tp, 0x15, 0x03bd); - rtl8168_mdio_write(tp, 0x19, 0x405e); - rtl8168_mdio_write(tp, 0x15, 0x03c2); - rtl8168_mdio_write(tp, 0x19, 0x9a03); - rtl8168_mdio_write(tp, 0x15, 0x03c4); - rtl8168_mdio_write(tp, 0x19, 0x0015); - rtl8168_mdio_write(tp, 0x15, 0x03c5); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x03c8); - rtl8168_mdio_write(tp, 0x19, 0x9cf7); - rtl8168_mdio_write(tp, 0x15, 0x03c9); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03ca); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03cb); - rtl8168_mdio_write(tp, 0x19, 0x4458); - rtl8168_mdio_write(tp, 0x15, 0x03cd); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03ce); - rtl8168_mdio_write(tp, 0x19, 0x33bf); - rtl8168_mdio_write(tp, 0x15, 0x03cf); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d0); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d1); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d9); - rtl8168_mdio_write(tp, 0x19, 0x49bb); - rtl8168_mdio_write(tp, 0x15, 0x03da); - rtl8168_mdio_write(tp, 0x19, 0x4478); - rtl8168_mdio_write(tp, 0x15, 0x03db); - rtl8168_mdio_write(tp, 0x19, 0x492b); - rtl8168_mdio_write(tp, 0x15, 0x03dc); - rtl8168_mdio_write(tp, 0x19, 0x7c01); - rtl8168_mdio_write(tp, 0x15, 0x03dd); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x03de); - rtl8168_mdio_write(tp, 0x19, 0xbd1a); - rtl8168_mdio_write(tp, 0x15, 0x03df); - rtl8168_mdio_write(tp, 0x19, 0xc428); - rtl8168_mdio_write(tp, 0x15, 0x03e0); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x03e1); - rtl8168_mdio_write(tp, 0x19, 0x9cfd); - rtl8168_mdio_write(tp, 0x15, 0x03e2); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03e3); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03e4); - rtl8168_mdio_write(tp, 0x19, 0x4458); - rtl8168_mdio_write(tp, 0x15, 0x03e5); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03e6); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03e7); - rtl8168_mdio_write(tp, 0x19, 0x33de); - rtl8168_mdio_write(tp, 0x15, 0x03e8); - rtl8168_mdio_write(tp, 0x19, 0xc218); - rtl8168_mdio_write(tp, 0x15, 0x03e9); - rtl8168_mdio_write(tp, 0x19, 0x0002); - rtl8168_mdio_write(tp, 0x15, 0x03ea); - rtl8168_mdio_write(tp, 0x19, 0x32df); - rtl8168_mdio_write(tp, 0x15, 0x03eb); - rtl8168_mdio_write(tp, 0x19, 0x3316); - rtl8168_mdio_write(tp, 0x15, 0x03ec); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ed); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ee); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ef); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03f7); - rtl8168_mdio_write(tp, 0x19, 0x330c); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x0200); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x9002); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x0202); - rtl8168_mdio_write(tp, 0x06, 0x3402); - rtl8168_mdio_write(tp, 0x06, 0x027f); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0xa602); - rtl8168_mdio_write(tp, 0x06, 0x80bf); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe600); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xee03); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xefb8); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe902); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8285); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8520); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8701); - rtl8168_mdio_write(tp, 0x06, 0xd481); - rtl8168_mdio_write(tp, 0x06, 0x35e4); - rtl8168_mdio_write(tp, 0x06, 0x8b94); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x95bf); - rtl8168_mdio_write(tp, 0x06, 0x8b88); - rtl8168_mdio_write(tp, 0x06, 0xec00); - rtl8168_mdio_write(tp, 0x06, 0x19a9); - rtl8168_mdio_write(tp, 0x06, 0x8b90); - rtl8168_mdio_write(tp, 0x06, 0xf9ee); - rtl8168_mdio_write(tp, 0x06, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x41f7); - rtl8168_mdio_write(tp, 0x06, 0x2ff6); - rtl8168_mdio_write(tp, 0x06, 0x28e4); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xe5e1); - rtl8168_mdio_write(tp, 0x06, 0x4104); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x0dee); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x82f4); - rtl8168_mdio_write(tp, 0x06, 0x021f); - rtl8168_mdio_write(tp, 0x06, 0x4102); - rtl8168_mdio_write(tp, 0x06, 0x2812); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x10ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x139d); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xd602); - rtl8168_mdio_write(tp, 0x06, 0x1f99); - rtl8168_mdio_write(tp, 0x06, 0x0227); - rtl8168_mdio_write(tp, 0x06, 0xeafc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2014); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x8104); - rtl8168_mdio_write(tp, 0x06, 0x021b); - rtl8168_mdio_write(tp, 0x06, 0xf402); - rtl8168_mdio_write(tp, 0x06, 0x2c9c); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x7902); - rtl8168_mdio_write(tp, 0x06, 0x8443); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x11f6); - rtl8168_mdio_write(tp, 0x06, 0x22e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x022c); - rtl8168_mdio_write(tp, 0x06, 0x4602); - rtl8168_mdio_write(tp, 0x06, 0x2ac5); - rtl8168_mdio_write(tp, 0x06, 0x0229); - rtl8168_mdio_write(tp, 0x06, 0x2002); - rtl8168_mdio_write(tp, 0x06, 0x2b91); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x11f6); - rtl8168_mdio_write(tp, 0x06, 0x25e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0xe202); - rtl8168_mdio_write(tp, 0x06, 0x043a); - rtl8168_mdio_write(tp, 0x06, 0x021a); - rtl8168_mdio_write(tp, 0x06, 0x5902); - rtl8168_mdio_write(tp, 0x06, 0x2bfc); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe001); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x1fd1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8638); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50e0); - rtl8168_mdio_write(tp, 0x06, 0xe020); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x21ad); - rtl8168_mdio_write(tp, 0x06, 0x200e); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xbf3d); - rtl8168_mdio_write(tp, 0x06, 0x3902); - rtl8168_mdio_write(tp, 0x06, 0x2eb0); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x0402); - rtl8168_mdio_write(tp, 0x06, 0x8591); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x3c05); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xfee1); - rtl8168_mdio_write(tp, 0x06, 0xe2ff); - rtl8168_mdio_write(tp, 0x06, 0xad2d); - rtl8168_mdio_write(tp, 0x06, 0x1ae0); - rtl8168_mdio_write(tp, 0x06, 0xe14e); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x4fac); - rtl8168_mdio_write(tp, 0x06, 0x2d22); - rtl8168_mdio_write(tp, 0x06, 0xf603); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x36f7); - rtl8168_mdio_write(tp, 0x06, 0x03f7); - rtl8168_mdio_write(tp, 0x06, 0x06bf); - rtl8168_mdio_write(tp, 0x06, 0x8622); - rtl8168_mdio_write(tp, 0x06, 0x022e); - rtl8168_mdio_write(tp, 0x06, 0xb0ae); - rtl8168_mdio_write(tp, 0x06, 0x11e0); - rtl8168_mdio_write(tp, 0x06, 0xe14e); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x4fad); - rtl8168_mdio_write(tp, 0x06, 0x2d08); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x2d02); - rtl8168_mdio_write(tp, 0x06, 0x2eb0); - rtl8168_mdio_write(tp, 0x06, 0xf606); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x204c); - rtl8168_mdio_write(tp, 0x06, 0xd200); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x0058); - rtl8168_mdio_write(tp, 0x06, 0x010c); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0x5810); - rtl8168_mdio_write(tp, 0x06, 0x1e20); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x3658); - rtl8168_mdio_write(tp, 0x06, 0x031e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xe01e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0x8ae6); - rtl8168_mdio_write(tp, 0x06, 0x1f02); - rtl8168_mdio_write(tp, 0x06, 0x9e22); - rtl8168_mdio_write(tp, 0x06, 0xe68a); - rtl8168_mdio_write(tp, 0x06, 0xe6ad); - rtl8168_mdio_write(tp, 0x06, 0x3214); - rtl8168_mdio_write(tp, 0x06, 0xad34); - rtl8168_mdio_write(tp, 0x06, 0x11ef); - rtl8168_mdio_write(tp, 0x06, 0x0258); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x07ad); - rtl8168_mdio_write(tp, 0x06, 0x3508); - rtl8168_mdio_write(tp, 0x06, 0x5ac0); - rtl8168_mdio_write(tp, 0x06, 0x9f04); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xae02); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x3e02); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfae0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac26); - rtl8168_mdio_write(tp, 0x06, 0x0ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xac24); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x6bee); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xe0eb); - rtl8168_mdio_write(tp, 0x06, 0x00e2); - rtl8168_mdio_write(tp, 0x06, 0xe07c); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0x7da5); - rtl8168_mdio_write(tp, 0x06, 0x1111); - rtl8168_mdio_write(tp, 0x06, 0x15d2); - rtl8168_mdio_write(tp, 0x06, 0x60d6); - rtl8168_mdio_write(tp, 0x06, 0x6666); - rtl8168_mdio_write(tp, 0x06, 0x0207); - rtl8168_mdio_write(tp, 0x06, 0xf9d2); - rtl8168_mdio_write(tp, 0x06, 0xa0d6); - rtl8168_mdio_write(tp, 0x06, 0xaaaa); - rtl8168_mdio_write(tp, 0x06, 0x0207); - rtl8168_mdio_write(tp, 0x06, 0xf902); - rtl8168_mdio_write(tp, 0x06, 0x825c); - rtl8168_mdio_write(tp, 0x06, 0xae44); - rtl8168_mdio_write(tp, 0x06, 0xa566); - rtl8168_mdio_write(tp, 0x06, 0x6602); - rtl8168_mdio_write(tp, 0x06, 0xae38); - rtl8168_mdio_write(tp, 0x06, 0xa5aa); - rtl8168_mdio_write(tp, 0x06, 0xaa02); - rtl8168_mdio_write(tp, 0x06, 0xae32); - rtl8168_mdio_write(tp, 0x06, 0xeee0); - rtl8168_mdio_write(tp, 0x06, 0xea04); - rtl8168_mdio_write(tp, 0x06, 0xeee0); - rtl8168_mdio_write(tp, 0x06, 0xeb06); - rtl8168_mdio_write(tp, 0x06, 0xe2e0); - rtl8168_mdio_write(tp, 0x06, 0x7ce3); - rtl8168_mdio_write(tp, 0x06, 0xe07d); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x38e1); - rtl8168_mdio_write(tp, 0x06, 0xe039); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x21ad); - rtl8168_mdio_write(tp, 0x06, 0x3f13); - rtl8168_mdio_write(tp, 0x06, 0xe0e4); - rtl8168_mdio_write(tp, 0x06, 0x14e1); - rtl8168_mdio_write(tp, 0x06, 0xe415); - rtl8168_mdio_write(tp, 0x06, 0x6880); - rtl8168_mdio_write(tp, 0x06, 0xe4e4); - rtl8168_mdio_write(tp, 0x06, 0x14e5); - rtl8168_mdio_write(tp, 0x06, 0xe415); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x5cae); - rtl8168_mdio_write(tp, 0x06, 0x0bac); - rtl8168_mdio_write(tp, 0x06, 0x3e02); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x8602); - rtl8168_mdio_write(tp, 0x06, 0x82b0); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2605); - rtl8168_mdio_write(tp, 0x06, 0x0221); - rtl8168_mdio_write(tp, 0x06, 0xf3f7); - rtl8168_mdio_write(tp, 0x06, 0x28e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xad21); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x22f8); - rtl8168_mdio_write(tp, 0x06, 0xf729); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2405); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xebf7); - rtl8168_mdio_write(tp, 0x06, 0x2ae5); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x2134); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2109); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x2eac); - rtl8168_mdio_write(tp, 0x06, 0x2003); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0x52e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x09e0); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x8337); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2608); - rtl8168_mdio_write(tp, 0x06, 0xe085); - rtl8168_mdio_write(tp, 0x06, 0xd2ad); - rtl8168_mdio_write(tp, 0x06, 0x2502); - rtl8168_mdio_write(tp, 0x06, 0xf628); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x210a); - rtl8168_mdio_write(tp, 0x06, 0xe086); - rtl8168_mdio_write(tp, 0x06, 0x0af6); - rtl8168_mdio_write(tp, 0x06, 0x27a0); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0xf629); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2408); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xedad); - rtl8168_mdio_write(tp, 0x06, 0x2002); - rtl8168_mdio_write(tp, 0x06, 0xf62a); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x2ea1); - rtl8168_mdio_write(tp, 0x06, 0x0003); - rtl8168_mdio_write(tp, 0x06, 0x0221); - rtl8168_mdio_write(tp, 0x06, 0x11fc); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x8aed); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8aec); - rtl8168_mdio_write(tp, 0x06, 0x0004); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x3ae0); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xeb58); - rtl8168_mdio_write(tp, 0x06, 0xf8d1); - rtl8168_mdio_write(tp, 0x06, 0x01e4); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0xebe0); - rtl8168_mdio_write(tp, 0x06, 0xe07c); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x7d5c); - rtl8168_mdio_write(tp, 0x06, 0x00ff); - rtl8168_mdio_write(tp, 0x06, 0x3c00); - rtl8168_mdio_write(tp, 0x06, 0x1eab); - rtl8168_mdio_write(tp, 0x06, 0x1ce0); - rtl8168_mdio_write(tp, 0x06, 0xe04c); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x4d58); - rtl8168_mdio_write(tp, 0x06, 0xc1e4); - rtl8168_mdio_write(tp, 0x06, 0xe04c); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0x4de0); - rtl8168_mdio_write(tp, 0x06, 0xe0ee); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0x3ce4); - rtl8168_mdio_write(tp, 0x06, 0xe0ee); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0xeffc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2412); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0xeee1); - rtl8168_mdio_write(tp, 0x06, 0xe0ef); - rtl8168_mdio_write(tp, 0x06, 0x59c3); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0xeee5); - rtl8168_mdio_write(tp, 0x06, 0xe0ef); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xed01); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac25); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x8363); - rtl8168_mdio_write(tp, 0x06, 0xae03); - rtl8168_mdio_write(tp, 0x06, 0x0225); - rtl8168_mdio_write(tp, 0x06, 0x16fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfae0); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0xa000); - rtl8168_mdio_write(tp, 0x06, 0x19e0); - rtl8168_mdio_write(tp, 0x06, 0x860b); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x331b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x04aa); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x06ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0xe602); - rtl8168_mdio_write(tp, 0x06, 0x241e); - rtl8168_mdio_write(tp, 0x06, 0xae14); - rtl8168_mdio_write(tp, 0x06, 0xa001); - rtl8168_mdio_write(tp, 0x06, 0x1402); - rtl8168_mdio_write(tp, 0x06, 0x2426); - rtl8168_mdio_write(tp, 0x06, 0xbf26); - rtl8168_mdio_write(tp, 0x06, 0x6d02); - rtl8168_mdio_write(tp, 0x06, 0x2eb0); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0b00); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0a02); - rtl8168_mdio_write(tp, 0x06, 0xaf84); - rtl8168_mdio_write(tp, 0x06, 0x3ca0); - rtl8168_mdio_write(tp, 0x06, 0x0252); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0400); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0500); - rtl8168_mdio_write(tp, 0x06, 0xe086); - rtl8168_mdio_write(tp, 0x06, 0x0be1); - rtl8168_mdio_write(tp, 0x06, 0x8b32); - rtl8168_mdio_write(tp, 0x06, 0x1b10); - rtl8168_mdio_write(tp, 0x06, 0x9e04); - rtl8168_mdio_write(tp, 0x06, 0xaa02); - rtl8168_mdio_write(tp, 0x06, 0xaecb); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0b00); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x3ae2); - rtl8168_mdio_write(tp, 0x06, 0x8604); - rtl8168_mdio_write(tp, 0x06, 0xe386); - rtl8168_mdio_write(tp, 0x06, 0x05ef); - rtl8168_mdio_write(tp, 0x06, 0x65e2); - rtl8168_mdio_write(tp, 0x06, 0x8606); - rtl8168_mdio_write(tp, 0x06, 0xe386); - rtl8168_mdio_write(tp, 0x06, 0x071b); - rtl8168_mdio_write(tp, 0x06, 0x56aa); - rtl8168_mdio_write(tp, 0x06, 0x0eef); - rtl8168_mdio_write(tp, 0x06, 0x56e6); - rtl8168_mdio_write(tp, 0x06, 0x8606); - rtl8168_mdio_write(tp, 0x06, 0xe786); - rtl8168_mdio_write(tp, 0x06, 0x07e2); - rtl8168_mdio_write(tp, 0x06, 0x8609); - rtl8168_mdio_write(tp, 0x06, 0xe686); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8609); - rtl8168_mdio_write(tp, 0x06, 0xa000); - rtl8168_mdio_write(tp, 0x06, 0x07ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x03af); - rtl8168_mdio_write(tp, 0x06, 0x8369); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x2426); - rtl8168_mdio_write(tp, 0x06, 0xae48); - rtl8168_mdio_write(tp, 0x06, 0xa003); - rtl8168_mdio_write(tp, 0x06, 0x21e0); - rtl8168_mdio_write(tp, 0x06, 0x8608); - rtl8168_mdio_write(tp, 0x06, 0xe186); - rtl8168_mdio_write(tp, 0x06, 0x091b); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x0caa); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x249d); - rtl8168_mdio_write(tp, 0x06, 0xaee7); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x8eae); - rtl8168_mdio_write(tp, 0x06, 0xe2ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x860b); - rtl8168_mdio_write(tp, 0x06, 0x00af); - rtl8168_mdio_write(tp, 0x06, 0x8369); - rtl8168_mdio_write(tp, 0x06, 0xa004); - rtl8168_mdio_write(tp, 0x06, 0x15e0); - rtl8168_mdio_write(tp, 0x06, 0x860b); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x341b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x05aa); - rtl8168_mdio_write(tp, 0x06, 0x03af); - rtl8168_mdio_write(tp, 0x06, 0x8383); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0a05); - rtl8168_mdio_write(tp, 0x06, 0xae0c); - rtl8168_mdio_write(tp, 0x06, 0xa005); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x0702); - rtl8168_mdio_write(tp, 0x06, 0x2309); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0a00); - rtl8168_mdio_write(tp, 0x06, 0xfeef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfbe0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x22e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x23e2); - rtl8168_mdio_write(tp, 0x06, 0xe036); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0x375a); - rtl8168_mdio_write(tp, 0x06, 0xc40d); - rtl8168_mdio_write(tp, 0x06, 0x0158); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x20e3); - rtl8168_mdio_write(tp, 0x06, 0x8ae7); - rtl8168_mdio_write(tp, 0x06, 0xac31); - rtl8168_mdio_write(tp, 0x06, 0x60ac); - rtl8168_mdio_write(tp, 0x06, 0x3a08); - rtl8168_mdio_write(tp, 0x06, 0xac3e); - rtl8168_mdio_write(tp, 0x06, 0x26ae); - rtl8168_mdio_write(tp, 0x06, 0x67af); - rtl8168_mdio_write(tp, 0x06, 0x84db); - rtl8168_mdio_write(tp, 0x06, 0xad37); - rtl8168_mdio_write(tp, 0x06, 0x61e0); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xe91b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x51d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x863b); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50ee); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x43ad); - rtl8168_mdio_write(tp, 0x06, 0x3627); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xeee1); - rtl8168_mdio_write(tp, 0x06, 0x8aef); - rtl8168_mdio_write(tp, 0x06, 0xef74); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xeae1); - rtl8168_mdio_write(tp, 0x06, 0x8aeb); - rtl8168_mdio_write(tp, 0x06, 0x1b74); - rtl8168_mdio_write(tp, 0x06, 0x9e2e); - rtl8168_mdio_write(tp, 0x06, 0x14e4); - rtl8168_mdio_write(tp, 0x06, 0x8aea); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xebef); - rtl8168_mdio_write(tp, 0x06, 0x74e0); - rtl8168_mdio_write(tp, 0x06, 0x8aee); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xef1b); - rtl8168_mdio_write(tp, 0x06, 0x479e); - rtl8168_mdio_write(tp, 0x06, 0x0fae); - rtl8168_mdio_write(tp, 0x06, 0x19ee); - rtl8168_mdio_write(tp, 0x06, 0x8aea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8aeb); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x0fac); - rtl8168_mdio_write(tp, 0x06, 0x390c); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x3b02); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe800); - rtl8168_mdio_write(tp, 0x06, 0xe68a); - rtl8168_mdio_write(tp, 0x06, 0xe7ff); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xc4e1); - rtl8168_mdio_write(tp, 0x06, 0x8b6e); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e24); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x6ead); - rtl8168_mdio_write(tp, 0x06, 0x2218); - rtl8168_mdio_write(tp, 0x06, 0xac27); - rtl8168_mdio_write(tp, 0x06, 0x0dac); - rtl8168_mdio_write(tp, 0x06, 0x2605); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x8fae); - rtl8168_mdio_write(tp, 0x06, 0x1302); - rtl8168_mdio_write(tp, 0x06, 0x03c8); - rtl8168_mdio_write(tp, 0x06, 0xae0e); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0xe102); - rtl8168_mdio_write(tp, 0x06, 0x8520); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x8f02); - rtl8168_mdio_write(tp, 0x06, 0x8566); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x82ad); - rtl8168_mdio_write(tp, 0x06, 0x2737); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4402); - rtl8168_mdio_write(tp, 0x06, 0x2f23); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x2ed1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8647); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50bf); - rtl8168_mdio_write(tp, 0x06, 0x8641); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x23e5); - rtl8168_mdio_write(tp, 0x06, 0x8af0); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x22e1); - rtl8168_mdio_write(tp, 0x06, 0xe023); - rtl8168_mdio_write(tp, 0x06, 0xac2e); - rtl8168_mdio_write(tp, 0x06, 0x04d1); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0x02d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8641); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50d1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8644); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4702); - rtl8168_mdio_write(tp, 0x06, 0x2f23); - rtl8168_mdio_write(tp, 0x06, 0xad28); - rtl8168_mdio_write(tp, 0x06, 0x19d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8644); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50e1); - rtl8168_mdio_write(tp, 0x06, 0x8af0); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4102); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4702); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xfee1); - rtl8168_mdio_write(tp, 0x06, 0xe2ff); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x63e0); - rtl8168_mdio_write(tp, 0x06, 0xe038); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x39ad); - rtl8168_mdio_write(tp, 0x06, 0x2f10); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xf726); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xae0e); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e1); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xf728); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e5); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xf72b); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xd07d); - rtl8168_mdio_write(tp, 0x06, 0xb0fe); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xf62b); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xf626); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e1); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xf628); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e5); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xae20); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0xa725); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x1de5); - rtl8168_mdio_write(tp, 0x06, 0x0a2c); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x6de5); - rtl8168_mdio_write(tp, 0x06, 0x0a1d); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x1ce5); - rtl8168_mdio_write(tp, 0x06, 0x0a2d); - rtl8168_mdio_write(tp, 0x06, 0xa755); - rtl8168_mdio_write(tp, 0x06, 0x00e2); - rtl8168_mdio_write(tp, 0x06, 0x3488); - rtl8168_mdio_write(tp, 0x06, 0xe200); - rtl8168_mdio_write(tp, 0x06, 0xcce2); - rtl8168_mdio_write(tp, 0x06, 0x0055); - rtl8168_mdio_write(tp, 0x06, 0xe020); - rtl8168_mdio_write(tp, 0x06, 0x55e2); - rtl8168_mdio_write(tp, 0x06, 0xd600); - rtl8168_mdio_write(tp, 0x06, 0xe24a); - gphy_val = rtl8168_mdio_read(tp, 0x01); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x01, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2179); - rtl8168_mdio_write(tp, 0x1f, 0x0001); - rtl8168_mdio_write(tp, 0x10, 0xf274); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0042); - rtl8168_mdio_write(tp, 0x15, 0x0f00); - rtl8168_mdio_write(tp, 0x15, 0x0f00); - rtl8168_mdio_write(tp, 0x16, 0x7408); - rtl8168_mdio_write(tp, 0x15, 0x0e00); - rtl8168_mdio_write(tp, 0x15, 0x0f00); - rtl8168_mdio_write(tp, 0x15, 0x0f01); - rtl8168_mdio_write(tp, 0x16, 0x4000); - rtl8168_mdio_write(tp, 0x15, 0x0e01); - rtl8168_mdio_write(tp, 0x15, 0x0f01); - rtl8168_mdio_write(tp, 0x15, 0x0f02); - rtl8168_mdio_write(tp, 0x16, 0x9400); - rtl8168_mdio_write(tp, 0x15, 0x0e02); - rtl8168_mdio_write(tp, 0x15, 0x0f02); - rtl8168_mdio_write(tp, 0x15, 0x0f03); - rtl8168_mdio_write(tp, 0x16, 0x7408); - rtl8168_mdio_write(tp, 0x15, 0x0e03); - rtl8168_mdio_write(tp, 0x15, 0x0f03); - rtl8168_mdio_write(tp, 0x15, 0x0f04); - rtl8168_mdio_write(tp, 0x16, 0x4008); - rtl8168_mdio_write(tp, 0x15, 0x0e04); - rtl8168_mdio_write(tp, 0x15, 0x0f04); - rtl8168_mdio_write(tp, 0x15, 0x0f05); - rtl8168_mdio_write(tp, 0x16, 0x9400); - rtl8168_mdio_write(tp, 0x15, 0x0e05); - rtl8168_mdio_write(tp, 0x15, 0x0f05); - rtl8168_mdio_write(tp, 0x15, 0x0f06); - rtl8168_mdio_write(tp, 0x16, 0x0803); - rtl8168_mdio_write(tp, 0x15, 0x0e06); - rtl8168_mdio_write(tp, 0x15, 0x0f06); - rtl8168_mdio_write(tp, 0x15, 0x0d00); - rtl8168_mdio_write(tp, 0x15, 0x0100); - rtl8168_mdio_write(tp, 0x1f, 0x0001); - rtl8168_mdio_write(tp, 0x10, 0xf074); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2149); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~(BIT_2); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val |= BIT_14; - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1e, 0x0020); - gphy_val = rtl8168_mdio_read(tp, 0x1b); - gphy_val |= BIT_7; - rtl8168_mdio_write(tp, 0x1b, gphy_val); - rtl8168_mdio_write(tp, 0x1e, 0x0041); - rtl8168_mdio_write(tp, 0x15, 0x0e02); - rtl8168_mdio_write(tp, 0x1e, 0x0028); - gphy_val = rtl8168_mdio_read(tp, 0x19); - gphy_val |= BIT_15; - rtl8168_mdio_write(tp, 0x19, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } else { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x1800); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x17, 0x0117); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - rtl8168_mdio_write(tp, 0x1B, 0x5000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x4104); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1E); - gphy_val &= 0x03FF; - if (gphy_val==0x000C) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x07); - if ((gphy_val & BIT_5) == 0) - break; - } - gphy_val = rtl8168_mdio_read(tp, 0x07); - if (gphy_val & BIT_5) { - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x00a1); - rtl8168_mdio_write(tp, 0x17, 0x1000); - rtl8168_mdio_write(tp, 0x17, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2000); - rtl8168_mdio_write(tp, 0x1e, 0x002f); - rtl8168_mdio_write(tp, 0x18, 0x9bfb); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x07, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x08); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x08, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x000e); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x0010); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x0018); - rtl8168_mdio_write(tp, 0x19, 0x4801); - rtl8168_mdio_write(tp, 0x15, 0x0019); - rtl8168_mdio_write(tp, 0x19, 0x6801); - rtl8168_mdio_write(tp, 0x15, 0x001a); - rtl8168_mdio_write(tp, 0x19, 0x66a1); - rtl8168_mdio_write(tp, 0x15, 0x001f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0020); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0021); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0022); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0023); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0024); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0025); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0026); - rtl8168_mdio_write(tp, 0x19, 0x40ea); - rtl8168_mdio_write(tp, 0x15, 0x0027); - rtl8168_mdio_write(tp, 0x19, 0x4503); - rtl8168_mdio_write(tp, 0x15, 0x0028); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0029); - rtl8168_mdio_write(tp, 0x19, 0xa631); - rtl8168_mdio_write(tp, 0x15, 0x002a); - rtl8168_mdio_write(tp, 0x19, 0x9717); - rtl8168_mdio_write(tp, 0x15, 0x002b); - rtl8168_mdio_write(tp, 0x19, 0x302c); - rtl8168_mdio_write(tp, 0x15, 0x002c); - rtl8168_mdio_write(tp, 0x19, 0x4802); - rtl8168_mdio_write(tp, 0x15, 0x002d); - rtl8168_mdio_write(tp, 0x19, 0x58da); - rtl8168_mdio_write(tp, 0x15, 0x002e); - rtl8168_mdio_write(tp, 0x19, 0x400d); - rtl8168_mdio_write(tp, 0x15, 0x002f); - rtl8168_mdio_write(tp, 0x19, 0x4488); - rtl8168_mdio_write(tp, 0x15, 0x0030); - rtl8168_mdio_write(tp, 0x19, 0x9e00); - rtl8168_mdio_write(tp, 0x15, 0x0031); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0032); - rtl8168_mdio_write(tp, 0x19, 0x6481); - rtl8168_mdio_write(tp, 0x15, 0x0033); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0034); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0035); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0036); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0037); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0038); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0039); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x003a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x003b); - rtl8168_mdio_write(tp, 0x19, 0x63e8); - rtl8168_mdio_write(tp, 0x15, 0x003c); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x003d); - rtl8168_mdio_write(tp, 0x19, 0x59d4); - rtl8168_mdio_write(tp, 0x15, 0x003e); - rtl8168_mdio_write(tp, 0x19, 0x63f8); - rtl8168_mdio_write(tp, 0x15, 0x0040); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0041); - rtl8168_mdio_write(tp, 0x19, 0x30de); - rtl8168_mdio_write(tp, 0x15, 0x0044); - rtl8168_mdio_write(tp, 0x19, 0x480f); - rtl8168_mdio_write(tp, 0x15, 0x0045); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x0046); - rtl8168_mdio_write(tp, 0x19, 0x6680); - rtl8168_mdio_write(tp, 0x15, 0x0047); - rtl8168_mdio_write(tp, 0x19, 0x7c10); - rtl8168_mdio_write(tp, 0x15, 0x0048); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0049); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004f); - rtl8168_mdio_write(tp, 0x19, 0x40ea); - rtl8168_mdio_write(tp, 0x15, 0x0050); - rtl8168_mdio_write(tp, 0x19, 0x4503); - rtl8168_mdio_write(tp, 0x15, 0x0051); - rtl8168_mdio_write(tp, 0x19, 0x58ca); - rtl8168_mdio_write(tp, 0x15, 0x0052); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0053); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x0054); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x0055); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0056); - rtl8168_mdio_write(tp, 0x19, 0x3000); - rtl8168_mdio_write(tp, 0x15, 0x00a1); - rtl8168_mdio_write(tp, 0x19, 0x3044); - rtl8168_mdio_write(tp, 0x15, 0x00ab); - rtl8168_mdio_write(tp, 0x19, 0x5820); - rtl8168_mdio_write(tp, 0x15, 0x00ac); - rtl8168_mdio_write(tp, 0x19, 0x5e04); - rtl8168_mdio_write(tp, 0x15, 0x00ad); - rtl8168_mdio_write(tp, 0x19, 0xb60c); - rtl8168_mdio_write(tp, 0x15, 0x00af); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x00b2); - rtl8168_mdio_write(tp, 0x19, 0x30b9); - rtl8168_mdio_write(tp, 0x15, 0x00b9); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x00ba); - rtl8168_mdio_write(tp, 0x19, 0x480b); - rtl8168_mdio_write(tp, 0x15, 0x00bb); - rtl8168_mdio_write(tp, 0x19, 0x5e00); - rtl8168_mdio_write(tp, 0x15, 0x00bc); - rtl8168_mdio_write(tp, 0x19, 0x405f); - rtl8168_mdio_write(tp, 0x15, 0x00bd); - rtl8168_mdio_write(tp, 0x19, 0x4448); - rtl8168_mdio_write(tp, 0x15, 0x00be); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x00bf); - rtl8168_mdio_write(tp, 0x19, 0x4468); - rtl8168_mdio_write(tp, 0x15, 0x00c0); - rtl8168_mdio_write(tp, 0x19, 0x9c02); - rtl8168_mdio_write(tp, 0x15, 0x00c1); - rtl8168_mdio_write(tp, 0x19, 0x58a0); - rtl8168_mdio_write(tp, 0x15, 0x00c2); - rtl8168_mdio_write(tp, 0x19, 0xb605); - rtl8168_mdio_write(tp, 0x15, 0x00c3); - rtl8168_mdio_write(tp, 0x19, 0xc0d3); - rtl8168_mdio_write(tp, 0x15, 0x00c4); - rtl8168_mdio_write(tp, 0x19, 0x00e6); - rtl8168_mdio_write(tp, 0x15, 0x00c5); - rtl8168_mdio_write(tp, 0x19, 0xdaec); - rtl8168_mdio_write(tp, 0x15, 0x00c6); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00c7); - rtl8168_mdio_write(tp, 0x19, 0x9df9); - rtl8168_mdio_write(tp, 0x15, 0x0112); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0113); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0114); - rtl8168_mdio_write(tp, 0x19, 0x63f0); - rtl8168_mdio_write(tp, 0x15, 0x0115); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0116); - rtl8168_mdio_write(tp, 0x19, 0x4418); - rtl8168_mdio_write(tp, 0x15, 0x0117); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x15, 0x0118); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0119); - rtl8168_mdio_write(tp, 0x19, 0x64e1); - rtl8168_mdio_write(tp, 0x15, 0x011a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0150); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0151); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0152); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0153); - rtl8168_mdio_write(tp, 0x19, 0x4540); - rtl8168_mdio_write(tp, 0x15, 0x0154); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0155); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x15, 0x0156); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0157); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0158); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0159); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x015a); - rtl8168_mdio_write(tp, 0x19, 0x30fe); - rtl8168_mdio_write(tp, 0x15, 0x029c); - rtl8168_mdio_write(tp, 0x19, 0x0070); - rtl8168_mdio_write(tp, 0x15, 0x02b2); - rtl8168_mdio_write(tp, 0x19, 0x005a); - rtl8168_mdio_write(tp, 0x15, 0x02bd); - rtl8168_mdio_write(tp, 0x19, 0xa522); - rtl8168_mdio_write(tp, 0x15, 0x02ce); - rtl8168_mdio_write(tp, 0x19, 0xb63e); - rtl8168_mdio_write(tp, 0x15, 0x02d9); - rtl8168_mdio_write(tp, 0x19, 0x32df); - rtl8168_mdio_write(tp, 0x15, 0x02df); - rtl8168_mdio_write(tp, 0x19, 0x4500); - rtl8168_mdio_write(tp, 0x15, 0x02f4); - rtl8168_mdio_write(tp, 0x19, 0xb618); - rtl8168_mdio_write(tp, 0x15, 0x02fb); - rtl8168_mdio_write(tp, 0x19, 0xb900); - rtl8168_mdio_write(tp, 0x15, 0x02fc); - rtl8168_mdio_write(tp, 0x19, 0x49b5); - rtl8168_mdio_write(tp, 0x15, 0x02fd); - rtl8168_mdio_write(tp, 0x19, 0x6812); - rtl8168_mdio_write(tp, 0x15, 0x02fe); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x02ff); - rtl8168_mdio_write(tp, 0x19, 0x9900); - rtl8168_mdio_write(tp, 0x15, 0x0300); - rtl8168_mdio_write(tp, 0x19, 0x64a0); - rtl8168_mdio_write(tp, 0x15, 0x0301); - rtl8168_mdio_write(tp, 0x19, 0x3316); - rtl8168_mdio_write(tp, 0x15, 0x0308); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030c); - rtl8168_mdio_write(tp, 0x19, 0x3000); - rtl8168_mdio_write(tp, 0x15, 0x0312); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0313); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0314); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0315); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0316); - rtl8168_mdio_write(tp, 0x19, 0x49b5); - rtl8168_mdio_write(tp, 0x15, 0x0317); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x0318); - rtl8168_mdio_write(tp, 0x19, 0x4d00); - rtl8168_mdio_write(tp, 0x15, 0x0319); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x031a); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x031b); - rtl8168_mdio_write(tp, 0x19, 0x4925); - rtl8168_mdio_write(tp, 0x15, 0x031c); - rtl8168_mdio_write(tp, 0x19, 0x403b); - rtl8168_mdio_write(tp, 0x15, 0x031d); - rtl8168_mdio_write(tp, 0x19, 0xa602); - rtl8168_mdio_write(tp, 0x15, 0x031e); - rtl8168_mdio_write(tp, 0x19, 0x402f); - rtl8168_mdio_write(tp, 0x15, 0x031f); - rtl8168_mdio_write(tp, 0x19, 0x4484); - rtl8168_mdio_write(tp, 0x15, 0x0320); - rtl8168_mdio_write(tp, 0x19, 0x40c8); - rtl8168_mdio_write(tp, 0x15, 0x0321); - rtl8168_mdio_write(tp, 0x19, 0x44c4); - rtl8168_mdio_write(tp, 0x15, 0x0322); - rtl8168_mdio_write(tp, 0x19, 0x404f); - rtl8168_mdio_write(tp, 0x15, 0x0323); - rtl8168_mdio_write(tp, 0x19, 0x44c8); - rtl8168_mdio_write(tp, 0x15, 0x0324); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0325); - rtl8168_mdio_write(tp, 0x19, 0x00e7); - rtl8168_mdio_write(tp, 0x15, 0x0326); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0327); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x0328); - rtl8168_mdio_write(tp, 0x19, 0x4d48); - rtl8168_mdio_write(tp, 0x15, 0x0329); - rtl8168_mdio_write(tp, 0x19, 0x332b); - rtl8168_mdio_write(tp, 0x15, 0x032a); - rtl8168_mdio_write(tp, 0x19, 0x4d40); - rtl8168_mdio_write(tp, 0x15, 0x032c); - rtl8168_mdio_write(tp, 0x19, 0x00f8); - rtl8168_mdio_write(tp, 0x15, 0x032d); - rtl8168_mdio_write(tp, 0x19, 0x82b2); - rtl8168_mdio_write(tp, 0x15, 0x032f); - rtl8168_mdio_write(tp, 0x19, 0x00b0); - rtl8168_mdio_write(tp, 0x15, 0x0332); - rtl8168_mdio_write(tp, 0x19, 0x91f2); - rtl8168_mdio_write(tp, 0x15, 0x033f); - rtl8168_mdio_write(tp, 0x19, 0xb6cd); - rtl8168_mdio_write(tp, 0x15, 0x0340); - rtl8168_mdio_write(tp, 0x19, 0x9e01); - rtl8168_mdio_write(tp, 0x15, 0x0341); - rtl8168_mdio_write(tp, 0x19, 0xd11d); - rtl8168_mdio_write(tp, 0x15, 0x0342); - rtl8168_mdio_write(tp, 0x19, 0x009d); - rtl8168_mdio_write(tp, 0x15, 0x0343); - rtl8168_mdio_write(tp, 0x19, 0xbb1c); - rtl8168_mdio_write(tp, 0x15, 0x0344); - rtl8168_mdio_write(tp, 0x19, 0x8102); - rtl8168_mdio_write(tp, 0x15, 0x0345); - rtl8168_mdio_write(tp, 0x19, 0x3348); - rtl8168_mdio_write(tp, 0x15, 0x0346); - rtl8168_mdio_write(tp, 0x19, 0xa231); - rtl8168_mdio_write(tp, 0x15, 0x0347); - rtl8168_mdio_write(tp, 0x19, 0x335b); - rtl8168_mdio_write(tp, 0x15, 0x0348); - rtl8168_mdio_write(tp, 0x19, 0x91f7); - rtl8168_mdio_write(tp, 0x15, 0x0349); - rtl8168_mdio_write(tp, 0x19, 0xc218); - rtl8168_mdio_write(tp, 0x15, 0x034a); - rtl8168_mdio_write(tp, 0x19, 0x00f5); - rtl8168_mdio_write(tp, 0x15, 0x034b); - rtl8168_mdio_write(tp, 0x19, 0x335b); - rtl8168_mdio_write(tp, 0x15, 0x034c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x034d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x034e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x034f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0350); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x035b); - rtl8168_mdio_write(tp, 0x19, 0xa23c); - rtl8168_mdio_write(tp, 0x15, 0x035c); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x035d); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x035e); - rtl8168_mdio_write(tp, 0x19, 0x3397); - rtl8168_mdio_write(tp, 0x15, 0x0363); - rtl8168_mdio_write(tp, 0x19, 0xb6a9); - rtl8168_mdio_write(tp, 0x15, 0x0366); - rtl8168_mdio_write(tp, 0x19, 0x00f5); - rtl8168_mdio_write(tp, 0x15, 0x0382); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0388); - rtl8168_mdio_write(tp, 0x19, 0x0084); - rtl8168_mdio_write(tp, 0x15, 0x0389); - rtl8168_mdio_write(tp, 0x19, 0xdd17); - rtl8168_mdio_write(tp, 0x15, 0x038a); - rtl8168_mdio_write(tp, 0x19, 0x000b); - rtl8168_mdio_write(tp, 0x15, 0x038b); - rtl8168_mdio_write(tp, 0x19, 0xa10a); - rtl8168_mdio_write(tp, 0x15, 0x038c); - rtl8168_mdio_write(tp, 0x19, 0x337e); - rtl8168_mdio_write(tp, 0x15, 0x038d); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x038e); - rtl8168_mdio_write(tp, 0x19, 0xa107); - rtl8168_mdio_write(tp, 0x15, 0x038f); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x0390); - rtl8168_mdio_write(tp, 0x19, 0xc017); - rtl8168_mdio_write(tp, 0x15, 0x0391); - rtl8168_mdio_write(tp, 0x19, 0x0004); - rtl8168_mdio_write(tp, 0x15, 0x0392); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0393); - rtl8168_mdio_write(tp, 0x19, 0x00f4); - rtl8168_mdio_write(tp, 0x15, 0x0397); - rtl8168_mdio_write(tp, 0x19, 0x4098); - rtl8168_mdio_write(tp, 0x15, 0x0398); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x0399); - rtl8168_mdio_write(tp, 0x19, 0x55bf); - rtl8168_mdio_write(tp, 0x15, 0x039a); - rtl8168_mdio_write(tp, 0x19, 0x4bb9); - rtl8168_mdio_write(tp, 0x15, 0x039b); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x039c); - rtl8168_mdio_write(tp, 0x19, 0x4b29); - rtl8168_mdio_write(tp, 0x15, 0x039d); - rtl8168_mdio_write(tp, 0x19, 0x4041); - rtl8168_mdio_write(tp, 0x15, 0x039e); - rtl8168_mdio_write(tp, 0x19, 0x442a); - rtl8168_mdio_write(tp, 0x15, 0x039f); - rtl8168_mdio_write(tp, 0x19, 0x4029); - rtl8168_mdio_write(tp, 0x15, 0x03aa); - rtl8168_mdio_write(tp, 0x19, 0x33b8); - rtl8168_mdio_write(tp, 0x15, 0x03b6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b8); - rtl8168_mdio_write(tp, 0x19, 0x543f); - rtl8168_mdio_write(tp, 0x15, 0x03b9); - rtl8168_mdio_write(tp, 0x19, 0x499a); - rtl8168_mdio_write(tp, 0x15, 0x03ba); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x03bb); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03bc); - rtl8168_mdio_write(tp, 0x19, 0x490a); - rtl8168_mdio_write(tp, 0x15, 0x03bd); - rtl8168_mdio_write(tp, 0x19, 0x405e); - rtl8168_mdio_write(tp, 0x15, 0x03c2); - rtl8168_mdio_write(tp, 0x19, 0x9a03); - rtl8168_mdio_write(tp, 0x15, 0x03c4); - rtl8168_mdio_write(tp, 0x19, 0x0015); - rtl8168_mdio_write(tp, 0x15, 0x03c5); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x03c8); - rtl8168_mdio_write(tp, 0x19, 0x9cf7); - rtl8168_mdio_write(tp, 0x15, 0x03c9); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03ca); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03cb); - rtl8168_mdio_write(tp, 0x19, 0x4458); - rtl8168_mdio_write(tp, 0x15, 0x03cd); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03ce); - rtl8168_mdio_write(tp, 0x19, 0x33bf); - rtl8168_mdio_write(tp, 0x15, 0x03cf); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d0); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d1); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d9); - rtl8168_mdio_write(tp, 0x19, 0x49bb); - rtl8168_mdio_write(tp, 0x15, 0x03da); - rtl8168_mdio_write(tp, 0x19, 0x4478); - rtl8168_mdio_write(tp, 0x15, 0x03db); - rtl8168_mdio_write(tp, 0x19, 0x492b); - rtl8168_mdio_write(tp, 0x15, 0x03dc); - rtl8168_mdio_write(tp, 0x19, 0x7c01); - rtl8168_mdio_write(tp, 0x15, 0x03dd); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x03de); - rtl8168_mdio_write(tp, 0x19, 0xbd1a); - rtl8168_mdio_write(tp, 0x15, 0x03df); - rtl8168_mdio_write(tp, 0x19, 0xc428); - rtl8168_mdio_write(tp, 0x15, 0x03e0); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x03e1); - rtl8168_mdio_write(tp, 0x19, 0x9cfd); - rtl8168_mdio_write(tp, 0x15, 0x03e2); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03e3); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03e4); - rtl8168_mdio_write(tp, 0x19, 0x4458); - rtl8168_mdio_write(tp, 0x15, 0x03e5); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03e6); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03e7); - rtl8168_mdio_write(tp, 0x19, 0x33de); - rtl8168_mdio_write(tp, 0x15, 0x03e8); - rtl8168_mdio_write(tp, 0x19, 0xc218); - rtl8168_mdio_write(tp, 0x15, 0x03e9); - rtl8168_mdio_write(tp, 0x19, 0x0002); - rtl8168_mdio_write(tp, 0x15, 0x03ea); - rtl8168_mdio_write(tp, 0x19, 0x32df); - rtl8168_mdio_write(tp, 0x15, 0x03eb); - rtl8168_mdio_write(tp, 0x19, 0x3316); - rtl8168_mdio_write(tp, 0x15, 0x03ec); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ed); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ee); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ef); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03f7); - rtl8168_mdio_write(tp, 0x19, 0x330c); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x0200); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x9002); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x0202); - rtl8168_mdio_write(tp, 0x06, 0x3402); - rtl8168_mdio_write(tp, 0x06, 0x027f); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0xa602); - rtl8168_mdio_write(tp, 0x06, 0x80bf); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe600); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xee03); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xefb8); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe902); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8285); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8520); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8701); - rtl8168_mdio_write(tp, 0x06, 0xd481); - rtl8168_mdio_write(tp, 0x06, 0x35e4); - rtl8168_mdio_write(tp, 0x06, 0x8b94); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x95bf); - rtl8168_mdio_write(tp, 0x06, 0x8b88); - rtl8168_mdio_write(tp, 0x06, 0xec00); - rtl8168_mdio_write(tp, 0x06, 0x19a9); - rtl8168_mdio_write(tp, 0x06, 0x8b90); - rtl8168_mdio_write(tp, 0x06, 0xf9ee); - rtl8168_mdio_write(tp, 0x06, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x41f7); - rtl8168_mdio_write(tp, 0x06, 0x2ff6); - rtl8168_mdio_write(tp, 0x06, 0x28e4); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xe5e1); - rtl8168_mdio_write(tp, 0x06, 0x4104); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x0dee); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x82f4); - rtl8168_mdio_write(tp, 0x06, 0x021f); - rtl8168_mdio_write(tp, 0x06, 0x4102); - rtl8168_mdio_write(tp, 0x06, 0x2812); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x10ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x139d); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xd602); - rtl8168_mdio_write(tp, 0x06, 0x1f99); - rtl8168_mdio_write(tp, 0x06, 0x0227); - rtl8168_mdio_write(tp, 0x06, 0xeafc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2014); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x8104); - rtl8168_mdio_write(tp, 0x06, 0x021b); - rtl8168_mdio_write(tp, 0x06, 0xf402); - rtl8168_mdio_write(tp, 0x06, 0x2c9c); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x7902); - rtl8168_mdio_write(tp, 0x06, 0x8443); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x11f6); - rtl8168_mdio_write(tp, 0x06, 0x22e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x022c); - rtl8168_mdio_write(tp, 0x06, 0x4602); - rtl8168_mdio_write(tp, 0x06, 0x2ac5); - rtl8168_mdio_write(tp, 0x06, 0x0229); - rtl8168_mdio_write(tp, 0x06, 0x2002); - rtl8168_mdio_write(tp, 0x06, 0x2b91); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x11f6); - rtl8168_mdio_write(tp, 0x06, 0x25e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0xe202); - rtl8168_mdio_write(tp, 0x06, 0x043a); - rtl8168_mdio_write(tp, 0x06, 0x021a); - rtl8168_mdio_write(tp, 0x06, 0x5902); - rtl8168_mdio_write(tp, 0x06, 0x2bfc); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe001); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x1fd1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8638); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50e0); - rtl8168_mdio_write(tp, 0x06, 0xe020); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x21ad); - rtl8168_mdio_write(tp, 0x06, 0x200e); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xbf3d); - rtl8168_mdio_write(tp, 0x06, 0x3902); - rtl8168_mdio_write(tp, 0x06, 0x2eb0); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x0402); - rtl8168_mdio_write(tp, 0x06, 0x8591); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x3c05); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xfee1); - rtl8168_mdio_write(tp, 0x06, 0xe2ff); - rtl8168_mdio_write(tp, 0x06, 0xad2d); - rtl8168_mdio_write(tp, 0x06, 0x1ae0); - rtl8168_mdio_write(tp, 0x06, 0xe14e); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x4fac); - rtl8168_mdio_write(tp, 0x06, 0x2d22); - rtl8168_mdio_write(tp, 0x06, 0xf603); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x36f7); - rtl8168_mdio_write(tp, 0x06, 0x03f7); - rtl8168_mdio_write(tp, 0x06, 0x06bf); - rtl8168_mdio_write(tp, 0x06, 0x8622); - rtl8168_mdio_write(tp, 0x06, 0x022e); - rtl8168_mdio_write(tp, 0x06, 0xb0ae); - rtl8168_mdio_write(tp, 0x06, 0x11e0); - rtl8168_mdio_write(tp, 0x06, 0xe14e); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x4fad); - rtl8168_mdio_write(tp, 0x06, 0x2d08); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x2d02); - rtl8168_mdio_write(tp, 0x06, 0x2eb0); - rtl8168_mdio_write(tp, 0x06, 0xf606); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x204c); - rtl8168_mdio_write(tp, 0x06, 0xd200); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x0058); - rtl8168_mdio_write(tp, 0x06, 0x010c); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0x5810); - rtl8168_mdio_write(tp, 0x06, 0x1e20); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x3658); - rtl8168_mdio_write(tp, 0x06, 0x031e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xe01e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0x8ae6); - rtl8168_mdio_write(tp, 0x06, 0x1f02); - rtl8168_mdio_write(tp, 0x06, 0x9e22); - rtl8168_mdio_write(tp, 0x06, 0xe68a); - rtl8168_mdio_write(tp, 0x06, 0xe6ad); - rtl8168_mdio_write(tp, 0x06, 0x3214); - rtl8168_mdio_write(tp, 0x06, 0xad34); - rtl8168_mdio_write(tp, 0x06, 0x11ef); - rtl8168_mdio_write(tp, 0x06, 0x0258); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x07ad); - rtl8168_mdio_write(tp, 0x06, 0x3508); - rtl8168_mdio_write(tp, 0x06, 0x5ac0); - rtl8168_mdio_write(tp, 0x06, 0x9f04); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xae02); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x3e02); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfae0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac26); - rtl8168_mdio_write(tp, 0x06, 0x0ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xac24); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x6bee); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xe0eb); - rtl8168_mdio_write(tp, 0x06, 0x00e2); - rtl8168_mdio_write(tp, 0x06, 0xe07c); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0x7da5); - rtl8168_mdio_write(tp, 0x06, 0x1111); - rtl8168_mdio_write(tp, 0x06, 0x15d2); - rtl8168_mdio_write(tp, 0x06, 0x60d6); - rtl8168_mdio_write(tp, 0x06, 0x6666); - rtl8168_mdio_write(tp, 0x06, 0x0207); - rtl8168_mdio_write(tp, 0x06, 0xf9d2); - rtl8168_mdio_write(tp, 0x06, 0xa0d6); - rtl8168_mdio_write(tp, 0x06, 0xaaaa); - rtl8168_mdio_write(tp, 0x06, 0x0207); - rtl8168_mdio_write(tp, 0x06, 0xf902); - rtl8168_mdio_write(tp, 0x06, 0x825c); - rtl8168_mdio_write(tp, 0x06, 0xae44); - rtl8168_mdio_write(tp, 0x06, 0xa566); - rtl8168_mdio_write(tp, 0x06, 0x6602); - rtl8168_mdio_write(tp, 0x06, 0xae38); - rtl8168_mdio_write(tp, 0x06, 0xa5aa); - rtl8168_mdio_write(tp, 0x06, 0xaa02); - rtl8168_mdio_write(tp, 0x06, 0xae32); - rtl8168_mdio_write(tp, 0x06, 0xeee0); - rtl8168_mdio_write(tp, 0x06, 0xea04); - rtl8168_mdio_write(tp, 0x06, 0xeee0); - rtl8168_mdio_write(tp, 0x06, 0xeb06); - rtl8168_mdio_write(tp, 0x06, 0xe2e0); - rtl8168_mdio_write(tp, 0x06, 0x7ce3); - rtl8168_mdio_write(tp, 0x06, 0xe07d); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x38e1); - rtl8168_mdio_write(tp, 0x06, 0xe039); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x21ad); - rtl8168_mdio_write(tp, 0x06, 0x3f13); - rtl8168_mdio_write(tp, 0x06, 0xe0e4); - rtl8168_mdio_write(tp, 0x06, 0x14e1); - rtl8168_mdio_write(tp, 0x06, 0xe415); - rtl8168_mdio_write(tp, 0x06, 0x6880); - rtl8168_mdio_write(tp, 0x06, 0xe4e4); - rtl8168_mdio_write(tp, 0x06, 0x14e5); - rtl8168_mdio_write(tp, 0x06, 0xe415); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x5cae); - rtl8168_mdio_write(tp, 0x06, 0x0bac); - rtl8168_mdio_write(tp, 0x06, 0x3e02); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x8602); - rtl8168_mdio_write(tp, 0x06, 0x82b0); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2605); - rtl8168_mdio_write(tp, 0x06, 0x0221); - rtl8168_mdio_write(tp, 0x06, 0xf3f7); - rtl8168_mdio_write(tp, 0x06, 0x28e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xad21); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x22f8); - rtl8168_mdio_write(tp, 0x06, 0xf729); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2405); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xebf7); - rtl8168_mdio_write(tp, 0x06, 0x2ae5); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x2134); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2109); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x2eac); - rtl8168_mdio_write(tp, 0x06, 0x2003); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0x52e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x09e0); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x8337); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2608); - rtl8168_mdio_write(tp, 0x06, 0xe085); - rtl8168_mdio_write(tp, 0x06, 0xd2ad); - rtl8168_mdio_write(tp, 0x06, 0x2502); - rtl8168_mdio_write(tp, 0x06, 0xf628); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x210a); - rtl8168_mdio_write(tp, 0x06, 0xe086); - rtl8168_mdio_write(tp, 0x06, 0x0af6); - rtl8168_mdio_write(tp, 0x06, 0x27a0); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0xf629); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2408); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xedad); - rtl8168_mdio_write(tp, 0x06, 0x2002); - rtl8168_mdio_write(tp, 0x06, 0xf62a); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x2ea1); - rtl8168_mdio_write(tp, 0x06, 0x0003); - rtl8168_mdio_write(tp, 0x06, 0x0221); - rtl8168_mdio_write(tp, 0x06, 0x11fc); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x8aed); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8aec); - rtl8168_mdio_write(tp, 0x06, 0x0004); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x3ae0); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xeb58); - rtl8168_mdio_write(tp, 0x06, 0xf8d1); - rtl8168_mdio_write(tp, 0x06, 0x01e4); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0xebe0); - rtl8168_mdio_write(tp, 0x06, 0xe07c); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x7d5c); - rtl8168_mdio_write(tp, 0x06, 0x00ff); - rtl8168_mdio_write(tp, 0x06, 0x3c00); - rtl8168_mdio_write(tp, 0x06, 0x1eab); - rtl8168_mdio_write(tp, 0x06, 0x1ce0); - rtl8168_mdio_write(tp, 0x06, 0xe04c); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x4d58); - rtl8168_mdio_write(tp, 0x06, 0xc1e4); - rtl8168_mdio_write(tp, 0x06, 0xe04c); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0x4de0); - rtl8168_mdio_write(tp, 0x06, 0xe0ee); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0x3ce4); - rtl8168_mdio_write(tp, 0x06, 0xe0ee); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0xeffc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2412); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0xeee1); - rtl8168_mdio_write(tp, 0x06, 0xe0ef); - rtl8168_mdio_write(tp, 0x06, 0x59c3); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0xeee5); - rtl8168_mdio_write(tp, 0x06, 0xe0ef); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xed01); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac25); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x8363); - rtl8168_mdio_write(tp, 0x06, 0xae03); - rtl8168_mdio_write(tp, 0x06, 0x0225); - rtl8168_mdio_write(tp, 0x06, 0x16fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfae0); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0xa000); - rtl8168_mdio_write(tp, 0x06, 0x19e0); - rtl8168_mdio_write(tp, 0x06, 0x860b); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x331b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x04aa); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x06ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0xe602); - rtl8168_mdio_write(tp, 0x06, 0x241e); - rtl8168_mdio_write(tp, 0x06, 0xae14); - rtl8168_mdio_write(tp, 0x06, 0xa001); - rtl8168_mdio_write(tp, 0x06, 0x1402); - rtl8168_mdio_write(tp, 0x06, 0x2426); - rtl8168_mdio_write(tp, 0x06, 0xbf26); - rtl8168_mdio_write(tp, 0x06, 0x6d02); - rtl8168_mdio_write(tp, 0x06, 0x2eb0); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0b00); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0a02); - rtl8168_mdio_write(tp, 0x06, 0xaf84); - rtl8168_mdio_write(tp, 0x06, 0x3ca0); - rtl8168_mdio_write(tp, 0x06, 0x0252); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0400); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0500); - rtl8168_mdio_write(tp, 0x06, 0xe086); - rtl8168_mdio_write(tp, 0x06, 0x0be1); - rtl8168_mdio_write(tp, 0x06, 0x8b32); - rtl8168_mdio_write(tp, 0x06, 0x1b10); - rtl8168_mdio_write(tp, 0x06, 0x9e04); - rtl8168_mdio_write(tp, 0x06, 0xaa02); - rtl8168_mdio_write(tp, 0x06, 0xaecb); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0b00); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x3ae2); - rtl8168_mdio_write(tp, 0x06, 0x8604); - rtl8168_mdio_write(tp, 0x06, 0xe386); - rtl8168_mdio_write(tp, 0x06, 0x05ef); - rtl8168_mdio_write(tp, 0x06, 0x65e2); - rtl8168_mdio_write(tp, 0x06, 0x8606); - rtl8168_mdio_write(tp, 0x06, 0xe386); - rtl8168_mdio_write(tp, 0x06, 0x071b); - rtl8168_mdio_write(tp, 0x06, 0x56aa); - rtl8168_mdio_write(tp, 0x06, 0x0eef); - rtl8168_mdio_write(tp, 0x06, 0x56e6); - rtl8168_mdio_write(tp, 0x06, 0x8606); - rtl8168_mdio_write(tp, 0x06, 0xe786); - rtl8168_mdio_write(tp, 0x06, 0x07e2); - rtl8168_mdio_write(tp, 0x06, 0x8609); - rtl8168_mdio_write(tp, 0x06, 0xe686); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8609); - rtl8168_mdio_write(tp, 0x06, 0xa000); - rtl8168_mdio_write(tp, 0x06, 0x07ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x03af); - rtl8168_mdio_write(tp, 0x06, 0x8369); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x2426); - rtl8168_mdio_write(tp, 0x06, 0xae48); - rtl8168_mdio_write(tp, 0x06, 0xa003); - rtl8168_mdio_write(tp, 0x06, 0x21e0); - rtl8168_mdio_write(tp, 0x06, 0x8608); - rtl8168_mdio_write(tp, 0x06, 0xe186); - rtl8168_mdio_write(tp, 0x06, 0x091b); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x0caa); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x249d); - rtl8168_mdio_write(tp, 0x06, 0xaee7); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x8eae); - rtl8168_mdio_write(tp, 0x06, 0xe2ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x860b); - rtl8168_mdio_write(tp, 0x06, 0x00af); - rtl8168_mdio_write(tp, 0x06, 0x8369); - rtl8168_mdio_write(tp, 0x06, 0xa004); - rtl8168_mdio_write(tp, 0x06, 0x15e0); - rtl8168_mdio_write(tp, 0x06, 0x860b); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x341b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x05aa); - rtl8168_mdio_write(tp, 0x06, 0x03af); - rtl8168_mdio_write(tp, 0x06, 0x8383); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0a05); - rtl8168_mdio_write(tp, 0x06, 0xae0c); - rtl8168_mdio_write(tp, 0x06, 0xa005); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x0702); - rtl8168_mdio_write(tp, 0x06, 0x2309); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0a00); - rtl8168_mdio_write(tp, 0x06, 0xfeef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfbe0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x22e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x23e2); - rtl8168_mdio_write(tp, 0x06, 0xe036); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0x375a); - rtl8168_mdio_write(tp, 0x06, 0xc40d); - rtl8168_mdio_write(tp, 0x06, 0x0158); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x20e3); - rtl8168_mdio_write(tp, 0x06, 0x8ae7); - rtl8168_mdio_write(tp, 0x06, 0xac31); - rtl8168_mdio_write(tp, 0x06, 0x60ac); - rtl8168_mdio_write(tp, 0x06, 0x3a08); - rtl8168_mdio_write(tp, 0x06, 0xac3e); - rtl8168_mdio_write(tp, 0x06, 0x26ae); - rtl8168_mdio_write(tp, 0x06, 0x67af); - rtl8168_mdio_write(tp, 0x06, 0x84db); - rtl8168_mdio_write(tp, 0x06, 0xad37); - rtl8168_mdio_write(tp, 0x06, 0x61e0); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xe91b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x51d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x863b); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50ee); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x43ad); - rtl8168_mdio_write(tp, 0x06, 0x3627); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xeee1); - rtl8168_mdio_write(tp, 0x06, 0x8aef); - rtl8168_mdio_write(tp, 0x06, 0xef74); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xeae1); - rtl8168_mdio_write(tp, 0x06, 0x8aeb); - rtl8168_mdio_write(tp, 0x06, 0x1b74); - rtl8168_mdio_write(tp, 0x06, 0x9e2e); - rtl8168_mdio_write(tp, 0x06, 0x14e4); - rtl8168_mdio_write(tp, 0x06, 0x8aea); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xebef); - rtl8168_mdio_write(tp, 0x06, 0x74e0); - rtl8168_mdio_write(tp, 0x06, 0x8aee); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xef1b); - rtl8168_mdio_write(tp, 0x06, 0x479e); - rtl8168_mdio_write(tp, 0x06, 0x0fae); - rtl8168_mdio_write(tp, 0x06, 0x19ee); - rtl8168_mdio_write(tp, 0x06, 0x8aea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8aeb); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x0fac); - rtl8168_mdio_write(tp, 0x06, 0x390c); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x3b02); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe800); - rtl8168_mdio_write(tp, 0x06, 0xe68a); - rtl8168_mdio_write(tp, 0x06, 0xe7ff); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xc4e1); - rtl8168_mdio_write(tp, 0x06, 0x8b6e); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e24); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x6ead); - rtl8168_mdio_write(tp, 0x06, 0x2218); - rtl8168_mdio_write(tp, 0x06, 0xac27); - rtl8168_mdio_write(tp, 0x06, 0x0dac); - rtl8168_mdio_write(tp, 0x06, 0x2605); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x8fae); - rtl8168_mdio_write(tp, 0x06, 0x1302); - rtl8168_mdio_write(tp, 0x06, 0x03c8); - rtl8168_mdio_write(tp, 0x06, 0xae0e); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0xe102); - rtl8168_mdio_write(tp, 0x06, 0x8520); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x8f02); - rtl8168_mdio_write(tp, 0x06, 0x8566); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x82ad); - rtl8168_mdio_write(tp, 0x06, 0x2737); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4402); - rtl8168_mdio_write(tp, 0x06, 0x2f23); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x2ed1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8647); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50bf); - rtl8168_mdio_write(tp, 0x06, 0x8641); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x23e5); - rtl8168_mdio_write(tp, 0x06, 0x8af0); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x22e1); - rtl8168_mdio_write(tp, 0x06, 0xe023); - rtl8168_mdio_write(tp, 0x06, 0xac2e); - rtl8168_mdio_write(tp, 0x06, 0x04d1); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0x02d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8641); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50d1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8644); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4702); - rtl8168_mdio_write(tp, 0x06, 0x2f23); - rtl8168_mdio_write(tp, 0x06, 0xad28); - rtl8168_mdio_write(tp, 0x06, 0x19d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8644); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50e1); - rtl8168_mdio_write(tp, 0x06, 0x8af0); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4102); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4702); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xfee1); - rtl8168_mdio_write(tp, 0x06, 0xe2ff); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x63e0); - rtl8168_mdio_write(tp, 0x06, 0xe038); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x39ad); - rtl8168_mdio_write(tp, 0x06, 0x2f10); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xf726); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xae0e); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e1); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xf728); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e5); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xf72b); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xd07d); - rtl8168_mdio_write(tp, 0x06, 0xb0fe); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xf62b); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xf626); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e1); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xf628); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e5); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xae20); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0xa725); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x1de5); - rtl8168_mdio_write(tp, 0x06, 0x0a2c); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x6de5); - rtl8168_mdio_write(tp, 0x06, 0x0a1d); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x1ce5); - rtl8168_mdio_write(tp, 0x06, 0x0a2d); - rtl8168_mdio_write(tp, 0x06, 0xa755); - rtl8168_mdio_write(tp, 0x06, 0x00e2); - rtl8168_mdio_write(tp, 0x06, 0x3488); - rtl8168_mdio_write(tp, 0x06, 0xe200); - rtl8168_mdio_write(tp, 0x06, 0xcce2); - rtl8168_mdio_write(tp, 0x06, 0x0055); - rtl8168_mdio_write(tp, 0x06, 0xe020); - rtl8168_mdio_write(tp, 0x06, 0x55e2); - rtl8168_mdio_write(tp, 0x06, 0xd600); - rtl8168_mdio_write(tp, 0x06, 0xe24a); - gphy_val = rtl8168_mdio_read(tp, 0x01); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x01, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~(BIT_2); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } -} - -static void -rtl8168_set_phy_mcu_8168evl_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val,i; - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x1800); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val &= ~(BIT_12); - rtl8168_mdio_write(tp, 0x15, gphy_val); - mdelay(20); - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - if ((gphy_val & BIT_11) == 0x0000) { - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x17, gphy_val); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x17); - if (gphy_val & BIT_11) - break; - } - } - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - rtl8168_mdio_write(tp, 0x1B, 0x5000); - rtl8168_mdio_write(tp, 0x1E, 0x002d); - rtl8168_mdio_write(tp, 0x19, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1E); - if ((gphy_val & 0x03FF) == 0x0014) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x07); - if ((gphy_val & BIT_5) == 0) - break; - } - gphy_val = rtl8168_mdio_read(tp, 0x07); - if (gphy_val & BIT_5) { - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x00a1); - rtl8168_mdio_write(tp, 0x17, 0x1000); - rtl8168_mdio_write(tp, 0x17, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2000); - rtl8168_mdio_write(tp, 0x1e, 0x002f); - rtl8168_mdio_write(tp, 0x18, 0x9bfb); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x07, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x0000); - rtl8168_mdio_write(tp, 0x19, 0x407d); - rtl8168_mdio_write(tp, 0x15, 0x0001); - rtl8168_mdio_write(tp, 0x19, 0x440f); - rtl8168_mdio_write(tp, 0x15, 0x0002); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0003); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x0004); - rtl8168_mdio_write(tp, 0x19, 0xc4d5); - rtl8168_mdio_write(tp, 0x15, 0x0005); - rtl8168_mdio_write(tp, 0x19, 0x00ff); - rtl8168_mdio_write(tp, 0x15, 0x0006); - rtl8168_mdio_write(tp, 0x19, 0x74f0); - rtl8168_mdio_write(tp, 0x15, 0x0007); - rtl8168_mdio_write(tp, 0x19, 0x4880); - rtl8168_mdio_write(tp, 0x15, 0x0008); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x0009); - rtl8168_mdio_write(tp, 0x19, 0x4800); - rtl8168_mdio_write(tp, 0x15, 0x000a); - rtl8168_mdio_write(tp, 0x19, 0x5000); - rtl8168_mdio_write(tp, 0x15, 0x000b); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x000c); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x000d); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x15, 0x000e); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x000f); - rtl8168_mdio_write(tp, 0x19, 0x7010); - rtl8168_mdio_write(tp, 0x15, 0x0010); - rtl8168_mdio_write(tp, 0x19, 0x6804); - rtl8168_mdio_write(tp, 0x15, 0x0011); - rtl8168_mdio_write(tp, 0x19, 0x64a0); - rtl8168_mdio_write(tp, 0x15, 0x0012); - rtl8168_mdio_write(tp, 0x19, 0x63da); - rtl8168_mdio_write(tp, 0x15, 0x0013); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x0014); - rtl8168_mdio_write(tp, 0x19, 0x6f05); - rtl8168_mdio_write(tp, 0x15, 0x0015); - rtl8168_mdio_write(tp, 0x19, 0x5420); - rtl8168_mdio_write(tp, 0x15, 0x0016); - rtl8168_mdio_write(tp, 0x19, 0x58ce); - rtl8168_mdio_write(tp, 0x15, 0x0017); - rtl8168_mdio_write(tp, 0x19, 0x5cf3); - rtl8168_mdio_write(tp, 0x15, 0x0018); - rtl8168_mdio_write(tp, 0x19, 0xb600); - rtl8168_mdio_write(tp, 0x15, 0x0019); - rtl8168_mdio_write(tp, 0x19, 0xc659); - rtl8168_mdio_write(tp, 0x15, 0x001a); - rtl8168_mdio_write(tp, 0x19, 0x0018); - rtl8168_mdio_write(tp, 0x15, 0x001b); - rtl8168_mdio_write(tp, 0x19, 0xc403); - rtl8168_mdio_write(tp, 0x15, 0x001c); - rtl8168_mdio_write(tp, 0x19, 0x0016); - rtl8168_mdio_write(tp, 0x15, 0x001d); - rtl8168_mdio_write(tp, 0x19, 0xaa05); - rtl8168_mdio_write(tp, 0x15, 0x001e); - rtl8168_mdio_write(tp, 0x19, 0xc503); - rtl8168_mdio_write(tp, 0x15, 0x001f); - rtl8168_mdio_write(tp, 0x19, 0x0003); - rtl8168_mdio_write(tp, 0x15, 0x0020); - rtl8168_mdio_write(tp, 0x19, 0x89f8); - rtl8168_mdio_write(tp, 0x15, 0x0021); - rtl8168_mdio_write(tp, 0x19, 0x32ae); - rtl8168_mdio_write(tp, 0x15, 0x0022); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0023); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x0024); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0025); - rtl8168_mdio_write(tp, 0x19, 0x6801); - rtl8168_mdio_write(tp, 0x15, 0x0026); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x0027); - rtl8168_mdio_write(tp, 0x19, 0xa300); - rtl8168_mdio_write(tp, 0x15, 0x0028); - rtl8168_mdio_write(tp, 0x19, 0x64a0); - rtl8168_mdio_write(tp, 0x15, 0x0029); - rtl8168_mdio_write(tp, 0x19, 0x76f0); - rtl8168_mdio_write(tp, 0x15, 0x002a); - rtl8168_mdio_write(tp, 0x19, 0x7670); - rtl8168_mdio_write(tp, 0x15, 0x002b); - rtl8168_mdio_write(tp, 0x19, 0x7630); - rtl8168_mdio_write(tp, 0x15, 0x002c); - rtl8168_mdio_write(tp, 0x19, 0x31a6); - rtl8168_mdio_write(tp, 0x15, 0x002d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x002e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x002f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0030); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0031); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0032); - rtl8168_mdio_write(tp, 0x19, 0x4801); - rtl8168_mdio_write(tp, 0x15, 0x0033); - rtl8168_mdio_write(tp, 0x19, 0x6803); - rtl8168_mdio_write(tp, 0x15, 0x0034); - rtl8168_mdio_write(tp, 0x19, 0x66a1); - rtl8168_mdio_write(tp, 0x15, 0x0035); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0036); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x0037); - rtl8168_mdio_write(tp, 0x19, 0xa300); - rtl8168_mdio_write(tp, 0x15, 0x0038); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0039); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x003a); - rtl8168_mdio_write(tp, 0x19, 0x74f8); - rtl8168_mdio_write(tp, 0x15, 0x003b); - rtl8168_mdio_write(tp, 0x19, 0x63d0); - rtl8168_mdio_write(tp, 0x15, 0x003c); - rtl8168_mdio_write(tp, 0x19, 0x7ff0); - rtl8168_mdio_write(tp, 0x15, 0x003d); - rtl8168_mdio_write(tp, 0x19, 0x77f0); - rtl8168_mdio_write(tp, 0x15, 0x003e); - rtl8168_mdio_write(tp, 0x19, 0x7ff0); - rtl8168_mdio_write(tp, 0x15, 0x003f); - rtl8168_mdio_write(tp, 0x19, 0x7750); - rtl8168_mdio_write(tp, 0x15, 0x0040); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x0041); - rtl8168_mdio_write(tp, 0x19, 0x7cf0); - rtl8168_mdio_write(tp, 0x15, 0x0042); - rtl8168_mdio_write(tp, 0x19, 0x7708); - rtl8168_mdio_write(tp, 0x15, 0x0043); - rtl8168_mdio_write(tp, 0x19, 0xa654); - rtl8168_mdio_write(tp, 0x15, 0x0044); - rtl8168_mdio_write(tp, 0x19, 0x304a); - rtl8168_mdio_write(tp, 0x15, 0x0045); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0046); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0047); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0048); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0049); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004a); - rtl8168_mdio_write(tp, 0x19, 0x4802); - rtl8168_mdio_write(tp, 0x15, 0x004b); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x004c); - rtl8168_mdio_write(tp, 0x19, 0x4440); - rtl8168_mdio_write(tp, 0x15, 0x004d); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x004e); - rtl8168_mdio_write(tp, 0x19, 0x6481); - rtl8168_mdio_write(tp, 0x15, 0x004f); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x15, 0x0050); - rtl8168_mdio_write(tp, 0x19, 0x63e8); - rtl8168_mdio_write(tp, 0x15, 0x0051); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x0052); - rtl8168_mdio_write(tp, 0x19, 0x5900); - rtl8168_mdio_write(tp, 0x15, 0x0053); - rtl8168_mdio_write(tp, 0x19, 0x63f8); - rtl8168_mdio_write(tp, 0x15, 0x0054); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0055); - rtl8168_mdio_write(tp, 0x19, 0x3116); - rtl8168_mdio_write(tp, 0x15, 0x0056); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0057); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0058); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0059); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x005a); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x005b); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x005c); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x005d); - rtl8168_mdio_write(tp, 0x19, 0x6000); - rtl8168_mdio_write(tp, 0x15, 0x005e); - rtl8168_mdio_write(tp, 0x19, 0x59ce); - rtl8168_mdio_write(tp, 0x15, 0x005f); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x0060); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x0061); - rtl8168_mdio_write(tp, 0x19, 0x72b0); - rtl8168_mdio_write(tp, 0x15, 0x0062); - rtl8168_mdio_write(tp, 0x19, 0x400e); - rtl8168_mdio_write(tp, 0x15, 0x0063); - rtl8168_mdio_write(tp, 0x19, 0x4440); - rtl8168_mdio_write(tp, 0x15, 0x0064); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x15, 0x0065); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x15, 0x0066); - rtl8168_mdio_write(tp, 0x19, 0x70b0); - rtl8168_mdio_write(tp, 0x15, 0x0067); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0068); - rtl8168_mdio_write(tp, 0x19, 0x6008); - rtl8168_mdio_write(tp, 0x15, 0x0069); - rtl8168_mdio_write(tp, 0x19, 0x7cf0); - rtl8168_mdio_write(tp, 0x15, 0x006a); - rtl8168_mdio_write(tp, 0x19, 0x7750); - rtl8168_mdio_write(tp, 0x15, 0x006b); - rtl8168_mdio_write(tp, 0x19, 0x4007); - rtl8168_mdio_write(tp, 0x15, 0x006c); - rtl8168_mdio_write(tp, 0x19, 0x4500); - rtl8168_mdio_write(tp, 0x15, 0x006d); - rtl8168_mdio_write(tp, 0x19, 0x4023); - rtl8168_mdio_write(tp, 0x15, 0x006e); - rtl8168_mdio_write(tp, 0x19, 0x4580); - rtl8168_mdio_write(tp, 0x15, 0x006f); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0070); - rtl8168_mdio_write(tp, 0x19, 0xcd78); - rtl8168_mdio_write(tp, 0x15, 0x0071); - rtl8168_mdio_write(tp, 0x19, 0x0003); - rtl8168_mdio_write(tp, 0x15, 0x0072); - rtl8168_mdio_write(tp, 0x19, 0xbe02); - rtl8168_mdio_write(tp, 0x15, 0x0073); - rtl8168_mdio_write(tp, 0x19, 0x3070); - rtl8168_mdio_write(tp, 0x15, 0x0074); - rtl8168_mdio_write(tp, 0x19, 0x7cf0); - rtl8168_mdio_write(tp, 0x15, 0x0075); - rtl8168_mdio_write(tp, 0x19, 0x77f0); - rtl8168_mdio_write(tp, 0x15, 0x0076); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x0077); - rtl8168_mdio_write(tp, 0x19, 0x4007); - rtl8168_mdio_write(tp, 0x15, 0x0078); - rtl8168_mdio_write(tp, 0x19, 0x4500); - rtl8168_mdio_write(tp, 0x15, 0x0079); - rtl8168_mdio_write(tp, 0x19, 0x4023); - rtl8168_mdio_write(tp, 0x15, 0x007a); - rtl8168_mdio_write(tp, 0x19, 0x4580); - rtl8168_mdio_write(tp, 0x15, 0x007b); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x007c); - rtl8168_mdio_write(tp, 0x19, 0xce80); - rtl8168_mdio_write(tp, 0x15, 0x007d); - rtl8168_mdio_write(tp, 0x19, 0x0004); - rtl8168_mdio_write(tp, 0x15, 0x007e); - rtl8168_mdio_write(tp, 0x19, 0xce80); - rtl8168_mdio_write(tp, 0x15, 0x007f); - rtl8168_mdio_write(tp, 0x19, 0x0002); - rtl8168_mdio_write(tp, 0x15, 0x0080); - rtl8168_mdio_write(tp, 0x19, 0x307c); - rtl8168_mdio_write(tp, 0x15, 0x0081); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x0082); - rtl8168_mdio_write(tp, 0x19, 0x480f); - rtl8168_mdio_write(tp, 0x15, 0x0083); - rtl8168_mdio_write(tp, 0x19, 0x6802); - rtl8168_mdio_write(tp, 0x15, 0x0084); - rtl8168_mdio_write(tp, 0x19, 0x6680); - rtl8168_mdio_write(tp, 0x15, 0x0085); - rtl8168_mdio_write(tp, 0x19, 0x7c10); - rtl8168_mdio_write(tp, 0x15, 0x0086); - rtl8168_mdio_write(tp, 0x19, 0x6010); - rtl8168_mdio_write(tp, 0x15, 0x0087); - rtl8168_mdio_write(tp, 0x19, 0x400a); - rtl8168_mdio_write(tp, 0x15, 0x0088); - rtl8168_mdio_write(tp, 0x19, 0x4580); - rtl8168_mdio_write(tp, 0x15, 0x0089); - rtl8168_mdio_write(tp, 0x19, 0x9e00); - rtl8168_mdio_write(tp, 0x15, 0x008a); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x008b); - rtl8168_mdio_write(tp, 0x19, 0x5800); - rtl8168_mdio_write(tp, 0x15, 0x008c); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x008d); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x008e); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x008f); - rtl8168_mdio_write(tp, 0x19, 0x8300); - rtl8168_mdio_write(tp, 0x15, 0x0090); - rtl8168_mdio_write(tp, 0x19, 0x7ff0); - rtl8168_mdio_write(tp, 0x15, 0x0091); - rtl8168_mdio_write(tp, 0x19, 0x74f0); - rtl8168_mdio_write(tp, 0x15, 0x0092); - rtl8168_mdio_write(tp, 0x19, 0x3006); - rtl8168_mdio_write(tp, 0x15, 0x0093); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0094); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0095); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0096); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0097); - rtl8168_mdio_write(tp, 0x19, 0x4803); - rtl8168_mdio_write(tp, 0x15, 0x0098); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0099); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x009a); - rtl8168_mdio_write(tp, 0x19, 0xa203); - rtl8168_mdio_write(tp, 0x15, 0x009b); - rtl8168_mdio_write(tp, 0x19, 0x64b1); - rtl8168_mdio_write(tp, 0x15, 0x009c); - rtl8168_mdio_write(tp, 0x19, 0x309e); - rtl8168_mdio_write(tp, 0x15, 0x009d); - rtl8168_mdio_write(tp, 0x19, 0x64b3); - rtl8168_mdio_write(tp, 0x15, 0x009e); - rtl8168_mdio_write(tp, 0x19, 0x4030); - rtl8168_mdio_write(tp, 0x15, 0x009f); - rtl8168_mdio_write(tp, 0x19, 0x440e); - rtl8168_mdio_write(tp, 0x15, 0x00a0); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x00a1); - rtl8168_mdio_write(tp, 0x19, 0x4419); - rtl8168_mdio_write(tp, 0x15, 0x00a2); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x00a3); - rtl8168_mdio_write(tp, 0x19, 0xc520); - rtl8168_mdio_write(tp, 0x15, 0x00a4); - rtl8168_mdio_write(tp, 0x19, 0x000b); - rtl8168_mdio_write(tp, 0x15, 0x00a5); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x00a6); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x00a7); - rtl8168_mdio_write(tp, 0x19, 0x58a4); - rtl8168_mdio_write(tp, 0x15, 0x00a8); - rtl8168_mdio_write(tp, 0x19, 0x63da); - rtl8168_mdio_write(tp, 0x15, 0x00a9); - rtl8168_mdio_write(tp, 0x19, 0x5cb0); - rtl8168_mdio_write(tp, 0x15, 0x00aa); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x00ab); - rtl8168_mdio_write(tp, 0x19, 0x72b0); - rtl8168_mdio_write(tp, 0x15, 0x00ac); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x15, 0x00ad); - rtl8168_mdio_write(tp, 0x19, 0x70b0); - rtl8168_mdio_write(tp, 0x15, 0x00ae); - rtl8168_mdio_write(tp, 0x19, 0x30b8); - rtl8168_mdio_write(tp, 0x15, 0x00AF); - rtl8168_mdio_write(tp, 0x19, 0x4060); - rtl8168_mdio_write(tp, 0x15, 0x00B0); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x00B1); - rtl8168_mdio_write(tp, 0x19, 0x7e00); - rtl8168_mdio_write(tp, 0x15, 0x00B2); - rtl8168_mdio_write(tp, 0x19, 0x72B0); - rtl8168_mdio_write(tp, 0x15, 0x00B3); - rtl8168_mdio_write(tp, 0x19, 0x7F00); - rtl8168_mdio_write(tp, 0x15, 0x00B4); - rtl8168_mdio_write(tp, 0x19, 0x73B0); - rtl8168_mdio_write(tp, 0x15, 0x00b5); - rtl8168_mdio_write(tp, 0x19, 0x58a0); - rtl8168_mdio_write(tp, 0x15, 0x00b6); - rtl8168_mdio_write(tp, 0x19, 0x63d2); - rtl8168_mdio_write(tp, 0x15, 0x00b7); - rtl8168_mdio_write(tp, 0x19, 0x5c00); - rtl8168_mdio_write(tp, 0x15, 0x00b8); - rtl8168_mdio_write(tp, 0x19, 0x5780); - rtl8168_mdio_write(tp, 0x15, 0x00b9); - rtl8168_mdio_write(tp, 0x19, 0xb60d); - rtl8168_mdio_write(tp, 0x15, 0x00ba); - rtl8168_mdio_write(tp, 0x19, 0x9bff); - rtl8168_mdio_write(tp, 0x15, 0x00bb); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x00bc); - rtl8168_mdio_write(tp, 0x19, 0x6001); - rtl8168_mdio_write(tp, 0x15, 0x00bd); - rtl8168_mdio_write(tp, 0x19, 0xc020); - rtl8168_mdio_write(tp, 0x15, 0x00be); - rtl8168_mdio_write(tp, 0x19, 0x002b); - rtl8168_mdio_write(tp, 0x15, 0x00bf); - rtl8168_mdio_write(tp, 0x19, 0xc137); - rtl8168_mdio_write(tp, 0x15, 0x00c0); - rtl8168_mdio_write(tp, 0x19, 0x0006); - rtl8168_mdio_write(tp, 0x15, 0x00c1); - rtl8168_mdio_write(tp, 0x19, 0x9af8); - rtl8168_mdio_write(tp, 0x15, 0x00c2); - rtl8168_mdio_write(tp, 0x19, 0x30c6); - rtl8168_mdio_write(tp, 0x15, 0x00c3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00c4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00c5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00c6); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x00c7); - rtl8168_mdio_write(tp, 0x19, 0x70b0); - rtl8168_mdio_write(tp, 0x15, 0x00c8); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x00c9); - rtl8168_mdio_write(tp, 0x19, 0x4804); - rtl8168_mdio_write(tp, 0x15, 0x00ca); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x00cb); - rtl8168_mdio_write(tp, 0x19, 0x5c80); - rtl8168_mdio_write(tp, 0x15, 0x00cc); - rtl8168_mdio_write(tp, 0x19, 0x4010); - rtl8168_mdio_write(tp, 0x15, 0x00cd); - rtl8168_mdio_write(tp, 0x19, 0x4415); - rtl8168_mdio_write(tp, 0x15, 0x00ce); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x15, 0x00cf); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x15, 0x00d0); - rtl8168_mdio_write(tp, 0x19, 0x70b0); - rtl8168_mdio_write(tp, 0x15, 0x00d1); - rtl8168_mdio_write(tp, 0x19, 0x3177); - rtl8168_mdio_write(tp, 0x15, 0x00d2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00d3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00d4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00d5); - rtl8168_mdio_write(tp, 0x19, 0x4808); - rtl8168_mdio_write(tp, 0x15, 0x00d6); - rtl8168_mdio_write(tp, 0x19, 0x4007); - rtl8168_mdio_write(tp, 0x15, 0x00d7); - rtl8168_mdio_write(tp, 0x19, 0x4420); - rtl8168_mdio_write(tp, 0x15, 0x00d8); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x00d9); - rtl8168_mdio_write(tp, 0x19, 0xb608); - rtl8168_mdio_write(tp, 0x15, 0x00da); - rtl8168_mdio_write(tp, 0x19, 0xbcbd); - rtl8168_mdio_write(tp, 0x15, 0x00db); - rtl8168_mdio_write(tp, 0x19, 0xc60b); - rtl8168_mdio_write(tp, 0x15, 0x00dc); - rtl8168_mdio_write(tp, 0x19, 0x00fd); - rtl8168_mdio_write(tp, 0x15, 0x00dd); - rtl8168_mdio_write(tp, 0x19, 0x30e1); - rtl8168_mdio_write(tp, 0x15, 0x00de); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00df); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00e0); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00e1); - rtl8168_mdio_write(tp, 0x19, 0x4809); - rtl8168_mdio_write(tp, 0x15, 0x00e2); - rtl8168_mdio_write(tp, 0x19, 0x7e40); - rtl8168_mdio_write(tp, 0x15, 0x00e3); - rtl8168_mdio_write(tp, 0x19, 0x5a40); - rtl8168_mdio_write(tp, 0x15, 0x00e4); - rtl8168_mdio_write(tp, 0x19, 0x305a); - rtl8168_mdio_write(tp, 0x15, 0x00e5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00e6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00e7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00e8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00e9); - rtl8168_mdio_write(tp, 0x19, 0x480a); - rtl8168_mdio_write(tp, 0x15, 0x00ea); - rtl8168_mdio_write(tp, 0x19, 0x5820); - rtl8168_mdio_write(tp, 0x15, 0x00eb); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x00ec); - rtl8168_mdio_write(tp, 0x19, 0xb60a); - rtl8168_mdio_write(tp, 0x15, 0x00ed); - rtl8168_mdio_write(tp, 0x19, 0xda07); - rtl8168_mdio_write(tp, 0x15, 0x00ee); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x00ef); - rtl8168_mdio_write(tp, 0x19, 0xc60b); - rtl8168_mdio_write(tp, 0x15, 0x00f0); - rtl8168_mdio_write(tp, 0x19, 0x00fc); - rtl8168_mdio_write(tp, 0x15, 0x00f1); - rtl8168_mdio_write(tp, 0x19, 0x30f6); - rtl8168_mdio_write(tp, 0x15, 0x00f2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00f3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00f4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00f5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00f6); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x00f7); - rtl8168_mdio_write(tp, 0x19, 0x480b); - rtl8168_mdio_write(tp, 0x15, 0x00f8); - rtl8168_mdio_write(tp, 0x19, 0x6f03); - rtl8168_mdio_write(tp, 0x15, 0x00f9); - rtl8168_mdio_write(tp, 0x19, 0x405f); - rtl8168_mdio_write(tp, 0x15, 0x00fa); - rtl8168_mdio_write(tp, 0x19, 0x4448); - rtl8168_mdio_write(tp, 0x15, 0x00fb); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x00fc); - rtl8168_mdio_write(tp, 0x19, 0x4468); - rtl8168_mdio_write(tp, 0x15, 0x00fd); - rtl8168_mdio_write(tp, 0x19, 0x9c03); - rtl8168_mdio_write(tp, 0x15, 0x00fe); - rtl8168_mdio_write(tp, 0x19, 0x6f07); - rtl8168_mdio_write(tp, 0x15, 0x00ff); - rtl8168_mdio_write(tp, 0x19, 0x58a0); - rtl8168_mdio_write(tp, 0x15, 0x0100); - rtl8168_mdio_write(tp, 0x19, 0xd6d1); - rtl8168_mdio_write(tp, 0x15, 0x0101); - rtl8168_mdio_write(tp, 0x19, 0x0004); - rtl8168_mdio_write(tp, 0x15, 0x0102); - rtl8168_mdio_write(tp, 0x19, 0xc137); - rtl8168_mdio_write(tp, 0x15, 0x0103); - rtl8168_mdio_write(tp, 0x19, 0x0002); - rtl8168_mdio_write(tp, 0x15, 0x0104); - rtl8168_mdio_write(tp, 0x19, 0xa0e5); - rtl8168_mdio_write(tp, 0x15, 0x0105); - rtl8168_mdio_write(tp, 0x19, 0x9df8); - rtl8168_mdio_write(tp, 0x15, 0x0106); - rtl8168_mdio_write(tp, 0x19, 0x30c6); - rtl8168_mdio_write(tp, 0x15, 0x0107); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0108); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0109); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x010a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x010b); - rtl8168_mdio_write(tp, 0x19, 0x4808); - rtl8168_mdio_write(tp, 0x15, 0x010c); - rtl8168_mdio_write(tp, 0x19, 0xc32d); - rtl8168_mdio_write(tp, 0x15, 0x010d); - rtl8168_mdio_write(tp, 0x19, 0x0003); - rtl8168_mdio_write(tp, 0x15, 0x010e); - rtl8168_mdio_write(tp, 0x19, 0xc8b3); - rtl8168_mdio_write(tp, 0x15, 0x010f); - rtl8168_mdio_write(tp, 0x19, 0x00fc); - rtl8168_mdio_write(tp, 0x15, 0x0110); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x0111); - rtl8168_mdio_write(tp, 0x19, 0x3116); - rtl8168_mdio_write(tp, 0x15, 0x0112); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0113); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0114); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0115); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0116); - rtl8168_mdio_write(tp, 0x19, 0x4803); - rtl8168_mdio_write(tp, 0x15, 0x0117); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0118); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x0119); - rtl8168_mdio_write(tp, 0x19, 0x7c04); - rtl8168_mdio_write(tp, 0x15, 0x011a); - rtl8168_mdio_write(tp, 0x19, 0x6000); - rtl8168_mdio_write(tp, 0x15, 0x011b); - rtl8168_mdio_write(tp, 0x19, 0x5cf7); - rtl8168_mdio_write(tp, 0x15, 0x011c); - rtl8168_mdio_write(tp, 0x19, 0x7c2a); - rtl8168_mdio_write(tp, 0x15, 0x011d); - rtl8168_mdio_write(tp, 0x19, 0x5800); - rtl8168_mdio_write(tp, 0x15, 0x011e); - rtl8168_mdio_write(tp, 0x19, 0x5400); - rtl8168_mdio_write(tp, 0x15, 0x011f); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0120); - rtl8168_mdio_write(tp, 0x19, 0x74f0); - rtl8168_mdio_write(tp, 0x15, 0x0121); - rtl8168_mdio_write(tp, 0x19, 0x4019); - rtl8168_mdio_write(tp, 0x15, 0x0122); - rtl8168_mdio_write(tp, 0x19, 0x440d); - rtl8168_mdio_write(tp, 0x15, 0x0123); - rtl8168_mdio_write(tp, 0x19, 0xb6c1); - rtl8168_mdio_write(tp, 0x15, 0x0124); - rtl8168_mdio_write(tp, 0x19, 0xc05b); - rtl8168_mdio_write(tp, 0x15, 0x0125); - rtl8168_mdio_write(tp, 0x19, 0x00bf); - rtl8168_mdio_write(tp, 0x15, 0x0126); - rtl8168_mdio_write(tp, 0x19, 0xc025); - rtl8168_mdio_write(tp, 0x15, 0x0127); - rtl8168_mdio_write(tp, 0x19, 0x00bd); - rtl8168_mdio_write(tp, 0x15, 0x0128); - rtl8168_mdio_write(tp, 0x19, 0xc603); - rtl8168_mdio_write(tp, 0x15, 0x0129); - rtl8168_mdio_write(tp, 0x19, 0x00bb); - rtl8168_mdio_write(tp, 0x15, 0x012a); - rtl8168_mdio_write(tp, 0x19, 0x8805); - rtl8168_mdio_write(tp, 0x15, 0x012b); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x012c); - rtl8168_mdio_write(tp, 0x19, 0x4001); - rtl8168_mdio_write(tp, 0x15, 0x012d); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x012e); - rtl8168_mdio_write(tp, 0x19, 0xa3dd); - rtl8168_mdio_write(tp, 0x15, 0x012f); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0130); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x0131); - rtl8168_mdio_write(tp, 0x19, 0x8407); - rtl8168_mdio_write(tp, 0x15, 0x0132); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0133); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x0134); - rtl8168_mdio_write(tp, 0x19, 0xd9b8); - rtl8168_mdio_write(tp, 0x15, 0x0135); - rtl8168_mdio_write(tp, 0x19, 0x0003); - rtl8168_mdio_write(tp, 0x15, 0x0136); - rtl8168_mdio_write(tp, 0x19, 0xc240); - rtl8168_mdio_write(tp, 0x15, 0x0137); - rtl8168_mdio_write(tp, 0x19, 0x0015); - rtl8168_mdio_write(tp, 0x15, 0x0138); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0139); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x013a); - rtl8168_mdio_write(tp, 0x19, 0x9ae9); - rtl8168_mdio_write(tp, 0x15, 0x013b); - rtl8168_mdio_write(tp, 0x19, 0x3140); - rtl8168_mdio_write(tp, 0x15, 0x013c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x013d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x013e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x013f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0140); - rtl8168_mdio_write(tp, 0x19, 0x4807); - rtl8168_mdio_write(tp, 0x15, 0x0141); - rtl8168_mdio_write(tp, 0x19, 0x4004); - rtl8168_mdio_write(tp, 0x15, 0x0142); - rtl8168_mdio_write(tp, 0x19, 0x4410); - rtl8168_mdio_write(tp, 0x15, 0x0143); - rtl8168_mdio_write(tp, 0x19, 0x7c0c); - rtl8168_mdio_write(tp, 0x15, 0x0144); - rtl8168_mdio_write(tp, 0x19, 0x600c); - rtl8168_mdio_write(tp, 0x15, 0x0145); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x15, 0x0146); - rtl8168_mdio_write(tp, 0x19, 0xa68f); - rtl8168_mdio_write(tp, 0x15, 0x0147); - rtl8168_mdio_write(tp, 0x19, 0x3116); - rtl8168_mdio_write(tp, 0x15, 0x0148); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0149); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x014a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x014b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x014c); - rtl8168_mdio_write(tp, 0x19, 0x4804); - rtl8168_mdio_write(tp, 0x15, 0x014d); - rtl8168_mdio_write(tp, 0x19, 0x54c0); - rtl8168_mdio_write(tp, 0x15, 0x014e); - rtl8168_mdio_write(tp, 0x19, 0xb703); - rtl8168_mdio_write(tp, 0x15, 0x014f); - rtl8168_mdio_write(tp, 0x19, 0x5cff); - rtl8168_mdio_write(tp, 0x15, 0x0150); - rtl8168_mdio_write(tp, 0x19, 0x315f); - rtl8168_mdio_write(tp, 0x15, 0x0151); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0152); - rtl8168_mdio_write(tp, 0x19, 0x74f8); - rtl8168_mdio_write(tp, 0x15, 0x0153); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0154); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0155); - rtl8168_mdio_write(tp, 0x19, 0x6000); - rtl8168_mdio_write(tp, 0x15, 0x0156); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0157); - rtl8168_mdio_write(tp, 0x19, 0x4418); - rtl8168_mdio_write(tp, 0x15, 0x0158); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x15, 0x0159); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x015a); - rtl8168_mdio_write(tp, 0x19, 0x64e1); - rtl8168_mdio_write(tp, 0x15, 0x015b); - rtl8168_mdio_write(tp, 0x19, 0x7c20); - rtl8168_mdio_write(tp, 0x15, 0x015c); - rtl8168_mdio_write(tp, 0x19, 0x5820); - rtl8168_mdio_write(tp, 0x15, 0x015d); - rtl8168_mdio_write(tp, 0x19, 0x5ccf); - rtl8168_mdio_write(tp, 0x15, 0x015e); - rtl8168_mdio_write(tp, 0x19, 0x7050); - rtl8168_mdio_write(tp, 0x15, 0x015f); - rtl8168_mdio_write(tp, 0x19, 0xd9b8); - rtl8168_mdio_write(tp, 0x15, 0x0160); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x0161); - rtl8168_mdio_write(tp, 0x19, 0xdab1); - rtl8168_mdio_write(tp, 0x15, 0x0162); - rtl8168_mdio_write(tp, 0x19, 0x0015); - rtl8168_mdio_write(tp, 0x15, 0x0163); - rtl8168_mdio_write(tp, 0x19, 0xc244); - rtl8168_mdio_write(tp, 0x15, 0x0164); - rtl8168_mdio_write(tp, 0x19, 0x0013); - rtl8168_mdio_write(tp, 0x15, 0x0165); - rtl8168_mdio_write(tp, 0x19, 0xc021); - rtl8168_mdio_write(tp, 0x15, 0x0166); - rtl8168_mdio_write(tp, 0x19, 0x00f9); - rtl8168_mdio_write(tp, 0x15, 0x0167); - rtl8168_mdio_write(tp, 0x19, 0x3177); - rtl8168_mdio_write(tp, 0x15, 0x0168); - rtl8168_mdio_write(tp, 0x19, 0x5cf7); - rtl8168_mdio_write(tp, 0x15, 0x0169); - rtl8168_mdio_write(tp, 0x19, 0x4010); - rtl8168_mdio_write(tp, 0x15, 0x016a); - rtl8168_mdio_write(tp, 0x19, 0x4428); - rtl8168_mdio_write(tp, 0x15, 0x016b); - rtl8168_mdio_write(tp, 0x19, 0x9c00); - rtl8168_mdio_write(tp, 0x15, 0x016c); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x016d); - rtl8168_mdio_write(tp, 0x19, 0x6008); - rtl8168_mdio_write(tp, 0x15, 0x016e); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x016f); - rtl8168_mdio_write(tp, 0x19, 0x74f0); - rtl8168_mdio_write(tp, 0x15, 0x0170); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0171); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0172); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0173); - rtl8168_mdio_write(tp, 0x19, 0x3116); - rtl8168_mdio_write(tp, 0x15, 0x0174); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0175); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0176); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0177); - rtl8168_mdio_write(tp, 0x19, 0x4805); - rtl8168_mdio_write(tp, 0x15, 0x0178); - rtl8168_mdio_write(tp, 0x19, 0xa103); - rtl8168_mdio_write(tp, 0x15, 0x0179); - rtl8168_mdio_write(tp, 0x19, 0x7c02); - rtl8168_mdio_write(tp, 0x15, 0x017a); - rtl8168_mdio_write(tp, 0x19, 0x6002); - rtl8168_mdio_write(tp, 0x15, 0x017b); - rtl8168_mdio_write(tp, 0x19, 0x7e00); - rtl8168_mdio_write(tp, 0x15, 0x017c); - rtl8168_mdio_write(tp, 0x19, 0x5400); - rtl8168_mdio_write(tp, 0x15, 0x017d); - rtl8168_mdio_write(tp, 0x19, 0x7c6b); - rtl8168_mdio_write(tp, 0x15, 0x017e); - rtl8168_mdio_write(tp, 0x19, 0x5c63); - rtl8168_mdio_write(tp, 0x15, 0x017f); - rtl8168_mdio_write(tp, 0x19, 0x407d); - rtl8168_mdio_write(tp, 0x15, 0x0180); - rtl8168_mdio_write(tp, 0x19, 0xa602); - rtl8168_mdio_write(tp, 0x15, 0x0181); - rtl8168_mdio_write(tp, 0x19, 0x4001); - rtl8168_mdio_write(tp, 0x15, 0x0182); - rtl8168_mdio_write(tp, 0x19, 0x4420); - rtl8168_mdio_write(tp, 0x15, 0x0183); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x0184); - rtl8168_mdio_write(tp, 0x19, 0x44a1); - rtl8168_mdio_write(tp, 0x15, 0x0185); - rtl8168_mdio_write(tp, 0x19, 0xd6e0); - rtl8168_mdio_write(tp, 0x15, 0x0186); - rtl8168_mdio_write(tp, 0x19, 0x0009); - rtl8168_mdio_write(tp, 0x15, 0x0187); - rtl8168_mdio_write(tp, 0x19, 0x9efe); - rtl8168_mdio_write(tp, 0x15, 0x0188); - rtl8168_mdio_write(tp, 0x19, 0x7c02); - rtl8168_mdio_write(tp, 0x15, 0x0189); - rtl8168_mdio_write(tp, 0x19, 0x6000); - rtl8168_mdio_write(tp, 0x15, 0x018a); - rtl8168_mdio_write(tp, 0x19, 0x9c00); - rtl8168_mdio_write(tp, 0x15, 0x018b); - rtl8168_mdio_write(tp, 0x19, 0x318f); - rtl8168_mdio_write(tp, 0x15, 0x018c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x018d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x018e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x018f); - rtl8168_mdio_write(tp, 0x19, 0x4806); - rtl8168_mdio_write(tp, 0x15, 0x0190); - rtl8168_mdio_write(tp, 0x19, 0x7c10); - rtl8168_mdio_write(tp, 0x15, 0x0191); - rtl8168_mdio_write(tp, 0x19, 0x5c10); - rtl8168_mdio_write(tp, 0x15, 0x0192); - rtl8168_mdio_write(tp, 0x19, 0x40fa); - rtl8168_mdio_write(tp, 0x15, 0x0193); - rtl8168_mdio_write(tp, 0x19, 0xa602); - rtl8168_mdio_write(tp, 0x15, 0x0194); - rtl8168_mdio_write(tp, 0x19, 0x4010); - rtl8168_mdio_write(tp, 0x15, 0x0195); - rtl8168_mdio_write(tp, 0x19, 0x4440); - rtl8168_mdio_write(tp, 0x15, 0x0196); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x15, 0x0197); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0198); - rtl8168_mdio_write(tp, 0x19, 0x6400); - rtl8168_mdio_write(tp, 0x15, 0x0199); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x019a); - rtl8168_mdio_write(tp, 0x19, 0x4540); - rtl8168_mdio_write(tp, 0x15, 0x019b); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x019c); - rtl8168_mdio_write(tp, 0x19, 0x6008); - rtl8168_mdio_write(tp, 0x15, 0x019d); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x019e); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x019f); - rtl8168_mdio_write(tp, 0x19, 0x6400); - rtl8168_mdio_write(tp, 0x15, 0x01a0); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x01a1); - rtl8168_mdio_write(tp, 0x19, 0x6480); - rtl8168_mdio_write(tp, 0x15, 0x01a2); - rtl8168_mdio_write(tp, 0x19, 0x3140); - rtl8168_mdio_write(tp, 0x15, 0x01a3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01a4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01a5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01a6); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x01a7); - rtl8168_mdio_write(tp, 0x19, 0x7c0b); - rtl8168_mdio_write(tp, 0x15, 0x01a8); - rtl8168_mdio_write(tp, 0x19, 0x6c01); - rtl8168_mdio_write(tp, 0x15, 0x01a9); - rtl8168_mdio_write(tp, 0x19, 0x64a8); - rtl8168_mdio_write(tp, 0x15, 0x01aa); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x01ab); - rtl8168_mdio_write(tp, 0x19, 0x5cf0); - rtl8168_mdio_write(tp, 0x15, 0x01ac); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x01ad); - rtl8168_mdio_write(tp, 0x19, 0xb628); - rtl8168_mdio_write(tp, 0x15, 0x01ae); - rtl8168_mdio_write(tp, 0x19, 0xc053); - rtl8168_mdio_write(tp, 0x15, 0x01af); - rtl8168_mdio_write(tp, 0x19, 0x0026); - rtl8168_mdio_write(tp, 0x15, 0x01b0); - rtl8168_mdio_write(tp, 0x19, 0xc02d); - rtl8168_mdio_write(tp, 0x15, 0x01b1); - rtl8168_mdio_write(tp, 0x19, 0x0024); - rtl8168_mdio_write(tp, 0x15, 0x01b2); - rtl8168_mdio_write(tp, 0x19, 0xc603); - rtl8168_mdio_write(tp, 0x15, 0x01b3); - rtl8168_mdio_write(tp, 0x19, 0x0022); - rtl8168_mdio_write(tp, 0x15, 0x01b4); - rtl8168_mdio_write(tp, 0x19, 0x8cf9); - rtl8168_mdio_write(tp, 0x15, 0x01b5); - rtl8168_mdio_write(tp, 0x19, 0x31ba); - rtl8168_mdio_write(tp, 0x15, 0x01b6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01b7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01b8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01b9); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01ba); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x01bb); - rtl8168_mdio_write(tp, 0x19, 0x5420); - rtl8168_mdio_write(tp, 0x15, 0x01bc); - rtl8168_mdio_write(tp, 0x19, 0x4811); - rtl8168_mdio_write(tp, 0x15, 0x01bd); - rtl8168_mdio_write(tp, 0x19, 0x5000); - rtl8168_mdio_write(tp, 0x15, 0x01be); - rtl8168_mdio_write(tp, 0x19, 0x4801); - rtl8168_mdio_write(tp, 0x15, 0x01bf); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x01c0); - rtl8168_mdio_write(tp, 0x19, 0x31f5); - rtl8168_mdio_write(tp, 0x15, 0x01c1); - rtl8168_mdio_write(tp, 0x19, 0xb614); - rtl8168_mdio_write(tp, 0x15, 0x01c2); - rtl8168_mdio_write(tp, 0x19, 0x8ce4); - rtl8168_mdio_write(tp, 0x15, 0x01c3); - rtl8168_mdio_write(tp, 0x19, 0xb30c); - rtl8168_mdio_write(tp, 0x15, 0x01c4); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x01c5); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x01c6); - rtl8168_mdio_write(tp, 0x19, 0x8206); - rtl8168_mdio_write(tp, 0x15, 0x01c7); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x01c8); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x01c9); - rtl8168_mdio_write(tp, 0x19, 0x7c04); - rtl8168_mdio_write(tp, 0x15, 0x01ca); - rtl8168_mdio_write(tp, 0x19, 0x7404); - rtl8168_mdio_write(tp, 0x15, 0x01cb); - rtl8168_mdio_write(tp, 0x19, 0x31c0); - rtl8168_mdio_write(tp, 0x15, 0x01cc); - rtl8168_mdio_write(tp, 0x19, 0x7c04); - rtl8168_mdio_write(tp, 0x15, 0x01cd); - rtl8168_mdio_write(tp, 0x19, 0x7400); - rtl8168_mdio_write(tp, 0x15, 0x01ce); - rtl8168_mdio_write(tp, 0x19, 0x31c0); - rtl8168_mdio_write(tp, 0x15, 0x01cf); - rtl8168_mdio_write(tp, 0x19, 0x8df1); - rtl8168_mdio_write(tp, 0x15, 0x01d0); - rtl8168_mdio_write(tp, 0x19, 0x3248); - rtl8168_mdio_write(tp, 0x15, 0x01d1); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01d2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01d3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01d4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01d5); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x01d6); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x01d7); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x01d8); - rtl8168_mdio_write(tp, 0x19, 0x7670); - rtl8168_mdio_write(tp, 0x15, 0x01d9); - rtl8168_mdio_write(tp, 0x19, 0x4023); - rtl8168_mdio_write(tp, 0x15, 0x01da); - rtl8168_mdio_write(tp, 0x19, 0x4500); - rtl8168_mdio_write(tp, 0x15, 0x01db); - rtl8168_mdio_write(tp, 0x19, 0x4069); - rtl8168_mdio_write(tp, 0x15, 0x01dc); - rtl8168_mdio_write(tp, 0x19, 0x4580); - rtl8168_mdio_write(tp, 0x15, 0x01dd); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x01de); - rtl8168_mdio_write(tp, 0x19, 0xcff5); - rtl8168_mdio_write(tp, 0x15, 0x01df); - rtl8168_mdio_write(tp, 0x19, 0x00ff); - rtl8168_mdio_write(tp, 0x15, 0x01e0); - rtl8168_mdio_write(tp, 0x19, 0x76f0); - rtl8168_mdio_write(tp, 0x15, 0x01e1); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x01e2); - rtl8168_mdio_write(tp, 0x19, 0x4023); - rtl8168_mdio_write(tp, 0x15, 0x01e3); - rtl8168_mdio_write(tp, 0x19, 0x4500); - rtl8168_mdio_write(tp, 0x15, 0x01e4); - rtl8168_mdio_write(tp, 0x19, 0x4069); - rtl8168_mdio_write(tp, 0x15, 0x01e5); - rtl8168_mdio_write(tp, 0x19, 0x4580); - rtl8168_mdio_write(tp, 0x15, 0x01e6); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x01e7); - rtl8168_mdio_write(tp, 0x19, 0xd0f5); - rtl8168_mdio_write(tp, 0x15, 0x01e8); - rtl8168_mdio_write(tp, 0x19, 0x00ff); - rtl8168_mdio_write(tp, 0x15, 0x01e9); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x01ea); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x01eb); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x01ec); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x01ed); - rtl8168_mdio_write(tp, 0x19, 0x8300); - rtl8168_mdio_write(tp, 0x15, 0x01ee); - rtl8168_mdio_write(tp, 0x19, 0x74f0); - rtl8168_mdio_write(tp, 0x15, 0x01ef); - rtl8168_mdio_write(tp, 0x19, 0x3006); - rtl8168_mdio_write(tp, 0x15, 0x01f0); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01f1); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01f2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01f3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01f4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01f5); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x01f6); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x01f7); - rtl8168_mdio_write(tp, 0x19, 0x409d); - rtl8168_mdio_write(tp, 0x15, 0x01f8); - rtl8168_mdio_write(tp, 0x19, 0x7c87); - rtl8168_mdio_write(tp, 0x15, 0x01f9); - rtl8168_mdio_write(tp, 0x19, 0xae14); - rtl8168_mdio_write(tp, 0x15, 0x01fa); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x01fb); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x01fc); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x01fd); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x01fe); - rtl8168_mdio_write(tp, 0x19, 0x980e); - rtl8168_mdio_write(tp, 0x15, 0x01ff); - rtl8168_mdio_write(tp, 0x19, 0x930c); - rtl8168_mdio_write(tp, 0x15, 0x0200); - rtl8168_mdio_write(tp, 0x19, 0x9206); - rtl8168_mdio_write(tp, 0x15, 0x0201); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0202); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0203); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0204); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0205); - rtl8168_mdio_write(tp, 0x19, 0x320c); - rtl8168_mdio_write(tp, 0x15, 0x0206); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x15, 0x0207); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0208); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x0209); - rtl8168_mdio_write(tp, 0x19, 0x5500); - rtl8168_mdio_write(tp, 0x15, 0x020a); - rtl8168_mdio_write(tp, 0x19, 0x320c); - rtl8168_mdio_write(tp, 0x15, 0x020b); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x020c); - rtl8168_mdio_write(tp, 0x19, 0x3220); - rtl8168_mdio_write(tp, 0x15, 0x020d); - rtl8168_mdio_write(tp, 0x19, 0x4480); - rtl8168_mdio_write(tp, 0x15, 0x020e); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x020f); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0210); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x0211); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0212); - rtl8168_mdio_write(tp, 0x19, 0x980e); - rtl8168_mdio_write(tp, 0x15, 0x0213); - rtl8168_mdio_write(tp, 0x19, 0x930c); - rtl8168_mdio_write(tp, 0x15, 0x0214); - rtl8168_mdio_write(tp, 0x19, 0x9206); - rtl8168_mdio_write(tp, 0x15, 0x0215); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x15, 0x0216); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0217); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0218); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0219); - rtl8168_mdio_write(tp, 0x19, 0x3220); - rtl8168_mdio_write(tp, 0x15, 0x021a); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x021b); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x021c); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x021d); - rtl8168_mdio_write(tp, 0x19, 0x5540); - rtl8168_mdio_write(tp, 0x15, 0x021e); - rtl8168_mdio_write(tp, 0x19, 0x3220); - rtl8168_mdio_write(tp, 0x15, 0x021f); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x15, 0x0220); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0221); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0222); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0223); - rtl8168_mdio_write(tp, 0x19, 0x3231); - rtl8168_mdio_write(tp, 0x15, 0x0224); - rtl8168_mdio_write(tp, 0x19, 0xab06); - rtl8168_mdio_write(tp, 0x15, 0x0225); - rtl8168_mdio_write(tp, 0x19, 0xbf08); - rtl8168_mdio_write(tp, 0x15, 0x0226); - rtl8168_mdio_write(tp, 0x19, 0x4076); - rtl8168_mdio_write(tp, 0x15, 0x0227); - rtl8168_mdio_write(tp, 0x19, 0x7d07); - rtl8168_mdio_write(tp, 0x15, 0x0228); - rtl8168_mdio_write(tp, 0x19, 0x4502); - rtl8168_mdio_write(tp, 0x15, 0x0229); - rtl8168_mdio_write(tp, 0x19, 0x3231); - rtl8168_mdio_write(tp, 0x15, 0x022a); - rtl8168_mdio_write(tp, 0x19, 0x7d80); - rtl8168_mdio_write(tp, 0x15, 0x022b); - rtl8168_mdio_write(tp, 0x19, 0x5180); - rtl8168_mdio_write(tp, 0x15, 0x022c); - rtl8168_mdio_write(tp, 0x19, 0x322f); - rtl8168_mdio_write(tp, 0x15, 0x022d); - rtl8168_mdio_write(tp, 0x19, 0x7d80); - rtl8168_mdio_write(tp, 0x15, 0x022e); - rtl8168_mdio_write(tp, 0x19, 0x5000); - rtl8168_mdio_write(tp, 0x15, 0x022f); - rtl8168_mdio_write(tp, 0x19, 0x7d07); - rtl8168_mdio_write(tp, 0x15, 0x0230); - rtl8168_mdio_write(tp, 0x19, 0x4402); - rtl8168_mdio_write(tp, 0x15, 0x0231); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0232); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x0233); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0234); - rtl8168_mdio_write(tp, 0x19, 0xb309); - rtl8168_mdio_write(tp, 0x15, 0x0235); - rtl8168_mdio_write(tp, 0x19, 0xb204); - rtl8168_mdio_write(tp, 0x15, 0x0236); - rtl8168_mdio_write(tp, 0x19, 0xb105); - rtl8168_mdio_write(tp, 0x15, 0x0237); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0238); - rtl8168_mdio_write(tp, 0x19, 0x31c1); - rtl8168_mdio_write(tp, 0x15, 0x0239); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x023a); - rtl8168_mdio_write(tp, 0x19, 0x3261); - rtl8168_mdio_write(tp, 0x15, 0x023b); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x023c); - rtl8168_mdio_write(tp, 0x19, 0x3250); - rtl8168_mdio_write(tp, 0x15, 0x023d); - rtl8168_mdio_write(tp, 0x19, 0xb203); - rtl8168_mdio_write(tp, 0x15, 0x023e); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x023f); - rtl8168_mdio_write(tp, 0x19, 0x327a); - rtl8168_mdio_write(tp, 0x15, 0x0240); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0241); - rtl8168_mdio_write(tp, 0x19, 0x3293); - rtl8168_mdio_write(tp, 0x15, 0x0242); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0243); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0244); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0245); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0246); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0247); - rtl8168_mdio_write(tp, 0x19, 0x32a3); - rtl8168_mdio_write(tp, 0x15, 0x0248); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0249); - rtl8168_mdio_write(tp, 0x19, 0x403d); - rtl8168_mdio_write(tp, 0x15, 0x024a); - rtl8168_mdio_write(tp, 0x19, 0x440c); - rtl8168_mdio_write(tp, 0x15, 0x024b); - rtl8168_mdio_write(tp, 0x19, 0x4812); - rtl8168_mdio_write(tp, 0x15, 0x024c); - rtl8168_mdio_write(tp, 0x19, 0x5001); - rtl8168_mdio_write(tp, 0x15, 0x024d); - rtl8168_mdio_write(tp, 0x19, 0x4802); - rtl8168_mdio_write(tp, 0x15, 0x024e); - rtl8168_mdio_write(tp, 0x19, 0x6880); - rtl8168_mdio_write(tp, 0x15, 0x024f); - rtl8168_mdio_write(tp, 0x19, 0x31f5); - rtl8168_mdio_write(tp, 0x15, 0x0250); - rtl8168_mdio_write(tp, 0x19, 0xb685); - rtl8168_mdio_write(tp, 0x15, 0x0251); - rtl8168_mdio_write(tp, 0x19, 0x801c); - rtl8168_mdio_write(tp, 0x15, 0x0252); - rtl8168_mdio_write(tp, 0x19, 0xbaf5); - rtl8168_mdio_write(tp, 0x15, 0x0253); - rtl8168_mdio_write(tp, 0x19, 0xc07c); - rtl8168_mdio_write(tp, 0x15, 0x0254); - rtl8168_mdio_write(tp, 0x19, 0x00fb); - rtl8168_mdio_write(tp, 0x15, 0x0255); - rtl8168_mdio_write(tp, 0x19, 0x325a); - rtl8168_mdio_write(tp, 0x15, 0x0256); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0257); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0258); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0259); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x025a); - rtl8168_mdio_write(tp, 0x19, 0x481a); - rtl8168_mdio_write(tp, 0x15, 0x025b); - rtl8168_mdio_write(tp, 0x19, 0x5001); - rtl8168_mdio_write(tp, 0x15, 0x025c); - rtl8168_mdio_write(tp, 0x19, 0x401b); - rtl8168_mdio_write(tp, 0x15, 0x025d); - rtl8168_mdio_write(tp, 0x19, 0x480a); - rtl8168_mdio_write(tp, 0x15, 0x025e); - rtl8168_mdio_write(tp, 0x19, 0x4418); - rtl8168_mdio_write(tp, 0x15, 0x025f); - rtl8168_mdio_write(tp, 0x19, 0x6900); - rtl8168_mdio_write(tp, 0x15, 0x0260); - rtl8168_mdio_write(tp, 0x19, 0x31f5); - rtl8168_mdio_write(tp, 0x15, 0x0261); - rtl8168_mdio_write(tp, 0x19, 0xb64b); - rtl8168_mdio_write(tp, 0x15, 0x0262); - rtl8168_mdio_write(tp, 0x19, 0xdb00); - rtl8168_mdio_write(tp, 0x15, 0x0263); - rtl8168_mdio_write(tp, 0x19, 0x0048); - rtl8168_mdio_write(tp, 0x15, 0x0264); - rtl8168_mdio_write(tp, 0x19, 0xdb7d); - rtl8168_mdio_write(tp, 0x15, 0x0265); - rtl8168_mdio_write(tp, 0x19, 0x0002); - rtl8168_mdio_write(tp, 0x15, 0x0266); - rtl8168_mdio_write(tp, 0x19, 0xa0fa); - rtl8168_mdio_write(tp, 0x15, 0x0267); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x0268); - rtl8168_mdio_write(tp, 0x19, 0x3248); - rtl8168_mdio_write(tp, 0x15, 0x0269); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x026a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x026b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x026c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x026d); - rtl8168_mdio_write(tp, 0x19, 0xb806); - rtl8168_mdio_write(tp, 0x15, 0x026e); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x026f); - rtl8168_mdio_write(tp, 0x19, 0x5500); - rtl8168_mdio_write(tp, 0x15, 0x0270); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0271); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0272); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0273); - rtl8168_mdio_write(tp, 0x19, 0x4814); - rtl8168_mdio_write(tp, 0x15, 0x0274); - rtl8168_mdio_write(tp, 0x19, 0x500b); - rtl8168_mdio_write(tp, 0x15, 0x0275); - rtl8168_mdio_write(tp, 0x19, 0x4804); - rtl8168_mdio_write(tp, 0x15, 0x0276); - rtl8168_mdio_write(tp, 0x19, 0x40c4); - rtl8168_mdio_write(tp, 0x15, 0x0277); - rtl8168_mdio_write(tp, 0x19, 0x4425); - rtl8168_mdio_write(tp, 0x15, 0x0278); - rtl8168_mdio_write(tp, 0x19, 0x6a00); - rtl8168_mdio_write(tp, 0x15, 0x0279); - rtl8168_mdio_write(tp, 0x19, 0x31f5); - rtl8168_mdio_write(tp, 0x15, 0x027a); - rtl8168_mdio_write(tp, 0x19, 0xb632); - rtl8168_mdio_write(tp, 0x15, 0x027b); - rtl8168_mdio_write(tp, 0x19, 0xdc03); - rtl8168_mdio_write(tp, 0x15, 0x027c); - rtl8168_mdio_write(tp, 0x19, 0x0027); - rtl8168_mdio_write(tp, 0x15, 0x027d); - rtl8168_mdio_write(tp, 0x19, 0x80fc); - rtl8168_mdio_write(tp, 0x15, 0x027e); - rtl8168_mdio_write(tp, 0x19, 0x3283); - rtl8168_mdio_write(tp, 0x15, 0x027f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0280); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0281); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0282); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0283); - rtl8168_mdio_write(tp, 0x19, 0xb806); - rtl8168_mdio_write(tp, 0x15, 0x0284); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0285); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0286); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0287); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x15, 0x0288); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0289); - rtl8168_mdio_write(tp, 0x19, 0x4818); - rtl8168_mdio_write(tp, 0x15, 0x028a); - rtl8168_mdio_write(tp, 0x19, 0x5051); - rtl8168_mdio_write(tp, 0x15, 0x028b); - rtl8168_mdio_write(tp, 0x19, 0x4808); - rtl8168_mdio_write(tp, 0x15, 0x028c); - rtl8168_mdio_write(tp, 0x19, 0x4050); - rtl8168_mdio_write(tp, 0x15, 0x028d); - rtl8168_mdio_write(tp, 0x19, 0x4462); - rtl8168_mdio_write(tp, 0x15, 0x028e); - rtl8168_mdio_write(tp, 0x19, 0x40c4); - rtl8168_mdio_write(tp, 0x15, 0x028f); - rtl8168_mdio_write(tp, 0x19, 0x4473); - rtl8168_mdio_write(tp, 0x15, 0x0290); - rtl8168_mdio_write(tp, 0x19, 0x5041); - rtl8168_mdio_write(tp, 0x15, 0x0291); - rtl8168_mdio_write(tp, 0x19, 0x6b00); - rtl8168_mdio_write(tp, 0x15, 0x0292); - rtl8168_mdio_write(tp, 0x19, 0x31f5); - rtl8168_mdio_write(tp, 0x15, 0x0293); - rtl8168_mdio_write(tp, 0x19, 0xb619); - rtl8168_mdio_write(tp, 0x15, 0x0294); - rtl8168_mdio_write(tp, 0x19, 0x80d9); - rtl8168_mdio_write(tp, 0x15, 0x0295); - rtl8168_mdio_write(tp, 0x19, 0xbd06); - rtl8168_mdio_write(tp, 0x15, 0x0296); - rtl8168_mdio_write(tp, 0x19, 0xbb0d); - rtl8168_mdio_write(tp, 0x15, 0x0297); - rtl8168_mdio_write(tp, 0x19, 0xaf14); - rtl8168_mdio_write(tp, 0x15, 0x0298); - rtl8168_mdio_write(tp, 0x19, 0x8efa); - rtl8168_mdio_write(tp, 0x15, 0x0299); - rtl8168_mdio_write(tp, 0x19, 0x5049); - rtl8168_mdio_write(tp, 0x15, 0x029a); - rtl8168_mdio_write(tp, 0x19, 0x3248); - rtl8168_mdio_write(tp, 0x15, 0x029b); - rtl8168_mdio_write(tp, 0x19, 0x4c10); - rtl8168_mdio_write(tp, 0x15, 0x029c); - rtl8168_mdio_write(tp, 0x19, 0x44b0); - rtl8168_mdio_write(tp, 0x15, 0x029d); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x029e); - rtl8168_mdio_write(tp, 0x19, 0x3292); - rtl8168_mdio_write(tp, 0x15, 0x029f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02a0); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02a1); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02a2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02a3); - rtl8168_mdio_write(tp, 0x19, 0x481f); - rtl8168_mdio_write(tp, 0x15, 0x02a4); - rtl8168_mdio_write(tp, 0x19, 0x5005); - rtl8168_mdio_write(tp, 0x15, 0x02a5); - rtl8168_mdio_write(tp, 0x19, 0x480f); - rtl8168_mdio_write(tp, 0x15, 0x02a6); - rtl8168_mdio_write(tp, 0x19, 0xac00); - rtl8168_mdio_write(tp, 0x15, 0x02a7); - rtl8168_mdio_write(tp, 0x19, 0x31a6); - rtl8168_mdio_write(tp, 0x15, 0x02a8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02a9); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02aa); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02ab); - rtl8168_mdio_write(tp, 0x19, 0x31ba); - rtl8168_mdio_write(tp, 0x15, 0x02ac); - rtl8168_mdio_write(tp, 0x19, 0x31d5); - rtl8168_mdio_write(tp, 0x15, 0x02ad); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02ae); - rtl8168_mdio_write(tp, 0x19, 0x5cf0); - rtl8168_mdio_write(tp, 0x15, 0x02af); - rtl8168_mdio_write(tp, 0x19, 0x588c); - rtl8168_mdio_write(tp, 0x15, 0x02b0); - rtl8168_mdio_write(tp, 0x19, 0x542f); - rtl8168_mdio_write(tp, 0x15, 0x02b1); - rtl8168_mdio_write(tp, 0x19, 0x7ffb); - rtl8168_mdio_write(tp, 0x15, 0x02b2); - rtl8168_mdio_write(tp, 0x19, 0x6ff8); - rtl8168_mdio_write(tp, 0x15, 0x02b3); - rtl8168_mdio_write(tp, 0x19, 0x64a4); - rtl8168_mdio_write(tp, 0x15, 0x02b4); - rtl8168_mdio_write(tp, 0x19, 0x64a0); - rtl8168_mdio_write(tp, 0x15, 0x02b5); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x02b6); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x02b7); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x02b8); - rtl8168_mdio_write(tp, 0x19, 0x4480); - rtl8168_mdio_write(tp, 0x15, 0x02b9); - rtl8168_mdio_write(tp, 0x19, 0x9e00); - rtl8168_mdio_write(tp, 0x15, 0x02ba); - rtl8168_mdio_write(tp, 0x19, 0x4891); - rtl8168_mdio_write(tp, 0x15, 0x02bb); - rtl8168_mdio_write(tp, 0x19, 0x4cc0); - rtl8168_mdio_write(tp, 0x15, 0x02bc); - rtl8168_mdio_write(tp, 0x19, 0x4801); - rtl8168_mdio_write(tp, 0x15, 0x02bd); - rtl8168_mdio_write(tp, 0x19, 0xa609); - rtl8168_mdio_write(tp, 0x15, 0x02be); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x02bf); - rtl8168_mdio_write(tp, 0x19, 0x004e); - rtl8168_mdio_write(tp, 0x15, 0x02c0); - rtl8168_mdio_write(tp, 0x19, 0x87fe); - rtl8168_mdio_write(tp, 0x15, 0x02c1); - rtl8168_mdio_write(tp, 0x19, 0x32c6); - rtl8168_mdio_write(tp, 0x15, 0x02c2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02c3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02c4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02c5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02c6); - rtl8168_mdio_write(tp, 0x19, 0x48b2); - rtl8168_mdio_write(tp, 0x15, 0x02c7); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x02c8); - rtl8168_mdio_write(tp, 0x19, 0x4822); - rtl8168_mdio_write(tp, 0x15, 0x02c9); - rtl8168_mdio_write(tp, 0x19, 0x4488); - rtl8168_mdio_write(tp, 0x15, 0x02ca); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x02cb); - rtl8168_mdio_write(tp, 0x19, 0x0042); - rtl8168_mdio_write(tp, 0x15, 0x02cc); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x02cd); - rtl8168_mdio_write(tp, 0x19, 0x4cc8); - rtl8168_mdio_write(tp, 0x15, 0x02ce); - rtl8168_mdio_write(tp, 0x19, 0x32d0); - rtl8168_mdio_write(tp, 0x15, 0x02cf); - rtl8168_mdio_write(tp, 0x19, 0x4cc0); - rtl8168_mdio_write(tp, 0x15, 0x02d0); - rtl8168_mdio_write(tp, 0x19, 0xc4d4); - rtl8168_mdio_write(tp, 0x15, 0x02d1); - rtl8168_mdio_write(tp, 0x19, 0x00f9); - rtl8168_mdio_write(tp, 0x15, 0x02d2); - rtl8168_mdio_write(tp, 0x19, 0xa51a); - rtl8168_mdio_write(tp, 0x15, 0x02d3); - rtl8168_mdio_write(tp, 0x19, 0x32d9); - rtl8168_mdio_write(tp, 0x15, 0x02d4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02d5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02d6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02d7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02d8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02d9); - rtl8168_mdio_write(tp, 0x19, 0x48b3); - rtl8168_mdio_write(tp, 0x15, 0x02da); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x02db); - rtl8168_mdio_write(tp, 0x19, 0x4823); - rtl8168_mdio_write(tp, 0x15, 0x02dc); - rtl8168_mdio_write(tp, 0x19, 0x4410); - rtl8168_mdio_write(tp, 0x15, 0x02dd); - rtl8168_mdio_write(tp, 0x19, 0xb630); - rtl8168_mdio_write(tp, 0x15, 0x02de); - rtl8168_mdio_write(tp, 0x19, 0x7dc8); - rtl8168_mdio_write(tp, 0x15, 0x02df); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x02e0); - rtl8168_mdio_write(tp, 0x19, 0x4c48); - rtl8168_mdio_write(tp, 0x15, 0x02e1); - rtl8168_mdio_write(tp, 0x19, 0x32e3); - rtl8168_mdio_write(tp, 0x15, 0x02e2); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x02e3); - rtl8168_mdio_write(tp, 0x19, 0x9bfa); - rtl8168_mdio_write(tp, 0x15, 0x02e4); - rtl8168_mdio_write(tp, 0x19, 0x84ca); - rtl8168_mdio_write(tp, 0x15, 0x02e5); - rtl8168_mdio_write(tp, 0x19, 0x85f8); - rtl8168_mdio_write(tp, 0x15, 0x02e6); - rtl8168_mdio_write(tp, 0x19, 0x32ec); - rtl8168_mdio_write(tp, 0x15, 0x02e7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02e8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02e9); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02ea); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02eb); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02ec); - rtl8168_mdio_write(tp, 0x19, 0x48d4); - rtl8168_mdio_write(tp, 0x15, 0x02ed); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x02ee); - rtl8168_mdio_write(tp, 0x19, 0x4844); - rtl8168_mdio_write(tp, 0x15, 0x02ef); - rtl8168_mdio_write(tp, 0x19, 0x4420); - rtl8168_mdio_write(tp, 0x15, 0x02f0); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x02f1); - rtl8168_mdio_write(tp, 0x19, 0x7dc0); - rtl8168_mdio_write(tp, 0x15, 0x02f2); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x02f3); - rtl8168_mdio_write(tp, 0x19, 0x7c0b); - rtl8168_mdio_write(tp, 0x15, 0x02f4); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x02f5); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x02f6); - rtl8168_mdio_write(tp, 0x19, 0x9cfd); - rtl8168_mdio_write(tp, 0x15, 0x02f7); - rtl8168_mdio_write(tp, 0x19, 0xb616); - rtl8168_mdio_write(tp, 0x15, 0x02f8); - rtl8168_mdio_write(tp, 0x19, 0xc42b); - rtl8168_mdio_write(tp, 0x15, 0x02f9); - rtl8168_mdio_write(tp, 0x19, 0x00e0); - rtl8168_mdio_write(tp, 0x15, 0x02fa); - rtl8168_mdio_write(tp, 0x19, 0xc455); - rtl8168_mdio_write(tp, 0x15, 0x02fb); - rtl8168_mdio_write(tp, 0x19, 0x00b3); - rtl8168_mdio_write(tp, 0x15, 0x02fc); - rtl8168_mdio_write(tp, 0x19, 0xb20a); - rtl8168_mdio_write(tp, 0x15, 0x02fd); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x02fe); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x02ff); - rtl8168_mdio_write(tp, 0x19, 0x8204); - rtl8168_mdio_write(tp, 0x15, 0x0300); - rtl8168_mdio_write(tp, 0x19, 0x7c04); - rtl8168_mdio_write(tp, 0x15, 0x0301); - rtl8168_mdio_write(tp, 0x19, 0x7404); - rtl8168_mdio_write(tp, 0x15, 0x0302); - rtl8168_mdio_write(tp, 0x19, 0x32f3); - rtl8168_mdio_write(tp, 0x15, 0x0303); - rtl8168_mdio_write(tp, 0x19, 0x7c04); - rtl8168_mdio_write(tp, 0x15, 0x0304); - rtl8168_mdio_write(tp, 0x19, 0x7400); - rtl8168_mdio_write(tp, 0x15, 0x0305); - rtl8168_mdio_write(tp, 0x19, 0x32f3); - rtl8168_mdio_write(tp, 0x15, 0x0306); - rtl8168_mdio_write(tp, 0x19, 0xefed); - rtl8168_mdio_write(tp, 0x15, 0x0307); - rtl8168_mdio_write(tp, 0x19, 0x3342); - rtl8168_mdio_write(tp, 0x15, 0x0308); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0309); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030d); - rtl8168_mdio_write(tp, 0x19, 0x3006); - rtl8168_mdio_write(tp, 0x15, 0x030e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0310); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0311); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0312); - rtl8168_mdio_write(tp, 0x19, 0xa207); - rtl8168_mdio_write(tp, 0x15, 0x0313); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x0314); - rtl8168_mdio_write(tp, 0x19, 0x3322); - rtl8168_mdio_write(tp, 0x15, 0x0315); - rtl8168_mdio_write(tp, 0x19, 0x4041); - rtl8168_mdio_write(tp, 0x15, 0x0316); - rtl8168_mdio_write(tp, 0x19, 0x7d07); - rtl8168_mdio_write(tp, 0x15, 0x0317); - rtl8168_mdio_write(tp, 0x19, 0x4502); - rtl8168_mdio_write(tp, 0x15, 0x0318); - rtl8168_mdio_write(tp, 0x19, 0x3322); - rtl8168_mdio_write(tp, 0x15, 0x0319); - rtl8168_mdio_write(tp, 0x19, 0x4c08); - rtl8168_mdio_write(tp, 0x15, 0x031a); - rtl8168_mdio_write(tp, 0x19, 0x3322); - rtl8168_mdio_write(tp, 0x15, 0x031b); - rtl8168_mdio_write(tp, 0x19, 0x7d80); - rtl8168_mdio_write(tp, 0x15, 0x031c); - rtl8168_mdio_write(tp, 0x19, 0x5180); - rtl8168_mdio_write(tp, 0x15, 0x031d); - rtl8168_mdio_write(tp, 0x19, 0x3320); - rtl8168_mdio_write(tp, 0x15, 0x031e); - rtl8168_mdio_write(tp, 0x19, 0x7d80); - rtl8168_mdio_write(tp, 0x15, 0x031f); - rtl8168_mdio_write(tp, 0x19, 0x5000); - rtl8168_mdio_write(tp, 0x15, 0x0320); - rtl8168_mdio_write(tp, 0x19, 0x7d07); - rtl8168_mdio_write(tp, 0x15, 0x0321); - rtl8168_mdio_write(tp, 0x19, 0x4402); - rtl8168_mdio_write(tp, 0x15, 0x0322); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0323); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x0324); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0325); - rtl8168_mdio_write(tp, 0x19, 0xb30c); - rtl8168_mdio_write(tp, 0x15, 0x0326); - rtl8168_mdio_write(tp, 0x19, 0xb206); - rtl8168_mdio_write(tp, 0x15, 0x0327); - rtl8168_mdio_write(tp, 0x19, 0xb103); - rtl8168_mdio_write(tp, 0x15, 0x0328); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0329); - rtl8168_mdio_write(tp, 0x19, 0x32f6); - rtl8168_mdio_write(tp, 0x15, 0x032a); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x032b); - rtl8168_mdio_write(tp, 0x19, 0x3352); - rtl8168_mdio_write(tp, 0x15, 0x032c); - rtl8168_mdio_write(tp, 0x19, 0xb103); - rtl8168_mdio_write(tp, 0x15, 0x032d); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x032e); - rtl8168_mdio_write(tp, 0x19, 0x336a); - rtl8168_mdio_write(tp, 0x15, 0x032f); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0330); - rtl8168_mdio_write(tp, 0x19, 0x3382); - rtl8168_mdio_write(tp, 0x15, 0x0331); - rtl8168_mdio_write(tp, 0x19, 0xb206); - rtl8168_mdio_write(tp, 0x15, 0x0332); - rtl8168_mdio_write(tp, 0x19, 0xb103); - rtl8168_mdio_write(tp, 0x15, 0x0333); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0334); - rtl8168_mdio_write(tp, 0x19, 0x3395); - rtl8168_mdio_write(tp, 0x15, 0x0335); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0336); - rtl8168_mdio_write(tp, 0x19, 0x33c6); - rtl8168_mdio_write(tp, 0x15, 0x0337); - rtl8168_mdio_write(tp, 0x19, 0xb103); - rtl8168_mdio_write(tp, 0x15, 0x0338); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0339); - rtl8168_mdio_write(tp, 0x19, 0x33d7); - rtl8168_mdio_write(tp, 0x15, 0x033a); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x033b); - rtl8168_mdio_write(tp, 0x19, 0x33f2); - rtl8168_mdio_write(tp, 0x15, 0x033c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x033d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x033e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x033f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0340); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0341); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0342); - rtl8168_mdio_write(tp, 0x19, 0x49b5); - rtl8168_mdio_write(tp, 0x15, 0x0343); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x0344); - rtl8168_mdio_write(tp, 0x19, 0x4d00); - rtl8168_mdio_write(tp, 0x15, 0x0345); - rtl8168_mdio_write(tp, 0x19, 0x6880); - rtl8168_mdio_write(tp, 0x15, 0x0346); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0347); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x0348); - rtl8168_mdio_write(tp, 0x19, 0x4925); - rtl8168_mdio_write(tp, 0x15, 0x0349); - rtl8168_mdio_write(tp, 0x19, 0x403b); - rtl8168_mdio_write(tp, 0x15, 0x034a); - rtl8168_mdio_write(tp, 0x19, 0xa602); - rtl8168_mdio_write(tp, 0x15, 0x034b); - rtl8168_mdio_write(tp, 0x19, 0x402f); - rtl8168_mdio_write(tp, 0x15, 0x034c); - rtl8168_mdio_write(tp, 0x19, 0x4484); - rtl8168_mdio_write(tp, 0x15, 0x034d); - rtl8168_mdio_write(tp, 0x19, 0x40c8); - rtl8168_mdio_write(tp, 0x15, 0x034e); - rtl8168_mdio_write(tp, 0x19, 0x44c4); - rtl8168_mdio_write(tp, 0x15, 0x034f); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0350); - rtl8168_mdio_write(tp, 0x19, 0x00bd); - rtl8168_mdio_write(tp, 0x15, 0x0351); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x0352); - rtl8168_mdio_write(tp, 0x19, 0xc8ed); - rtl8168_mdio_write(tp, 0x15, 0x0353); - rtl8168_mdio_write(tp, 0x19, 0x00fc); - rtl8168_mdio_write(tp, 0x15, 0x0354); - rtl8168_mdio_write(tp, 0x19, 0x8221); - rtl8168_mdio_write(tp, 0x15, 0x0355); - rtl8168_mdio_write(tp, 0x19, 0xd11d); - rtl8168_mdio_write(tp, 0x15, 0x0356); - rtl8168_mdio_write(tp, 0x19, 0x001f); - rtl8168_mdio_write(tp, 0x15, 0x0357); - rtl8168_mdio_write(tp, 0x19, 0xde18); - rtl8168_mdio_write(tp, 0x15, 0x0358); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x0359); - rtl8168_mdio_write(tp, 0x19, 0x91f6); - rtl8168_mdio_write(tp, 0x15, 0x035a); - rtl8168_mdio_write(tp, 0x19, 0x3360); - rtl8168_mdio_write(tp, 0x15, 0x035b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x035c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x035d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x035e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x035f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0360); - rtl8168_mdio_write(tp, 0x19, 0x4bb6); - rtl8168_mdio_write(tp, 0x15, 0x0361); - rtl8168_mdio_write(tp, 0x19, 0x4064); - rtl8168_mdio_write(tp, 0x15, 0x0362); - rtl8168_mdio_write(tp, 0x19, 0x4b26); - rtl8168_mdio_write(tp, 0x15, 0x0363); - rtl8168_mdio_write(tp, 0x19, 0x4410); - rtl8168_mdio_write(tp, 0x15, 0x0364); - rtl8168_mdio_write(tp, 0x19, 0x4006); - rtl8168_mdio_write(tp, 0x15, 0x0365); - rtl8168_mdio_write(tp, 0x19, 0x4490); - rtl8168_mdio_write(tp, 0x15, 0x0366); - rtl8168_mdio_write(tp, 0x19, 0x6900); - rtl8168_mdio_write(tp, 0x15, 0x0367); - rtl8168_mdio_write(tp, 0x19, 0xb6a6); - rtl8168_mdio_write(tp, 0x15, 0x0368); - rtl8168_mdio_write(tp, 0x19, 0x9e02); - rtl8168_mdio_write(tp, 0x15, 0x0369); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x036a); - rtl8168_mdio_write(tp, 0x19, 0xd11d); - rtl8168_mdio_write(tp, 0x15, 0x036b); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x036c); - rtl8168_mdio_write(tp, 0x19, 0xbb0f); - rtl8168_mdio_write(tp, 0x15, 0x036d); - rtl8168_mdio_write(tp, 0x19, 0x8102); - rtl8168_mdio_write(tp, 0x15, 0x036e); - rtl8168_mdio_write(tp, 0x19, 0x3371); - rtl8168_mdio_write(tp, 0x15, 0x036f); - rtl8168_mdio_write(tp, 0x19, 0xa21e); - rtl8168_mdio_write(tp, 0x15, 0x0370); - rtl8168_mdio_write(tp, 0x19, 0x33b6); - rtl8168_mdio_write(tp, 0x15, 0x0371); - rtl8168_mdio_write(tp, 0x19, 0x91f6); - rtl8168_mdio_write(tp, 0x15, 0x0372); - rtl8168_mdio_write(tp, 0x19, 0xc218); - rtl8168_mdio_write(tp, 0x15, 0x0373); - rtl8168_mdio_write(tp, 0x19, 0x00f4); - rtl8168_mdio_write(tp, 0x15, 0x0374); - rtl8168_mdio_write(tp, 0x19, 0x33b6); - rtl8168_mdio_write(tp, 0x15, 0x0375); - rtl8168_mdio_write(tp, 0x19, 0x32ec); - rtl8168_mdio_write(tp, 0x15, 0x0376); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0377); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0378); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0379); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x037a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x037b); - rtl8168_mdio_write(tp, 0x19, 0x4b97); - rtl8168_mdio_write(tp, 0x15, 0x037c); - rtl8168_mdio_write(tp, 0x19, 0x402b); - rtl8168_mdio_write(tp, 0x15, 0x037d); - rtl8168_mdio_write(tp, 0x19, 0x4b07); - rtl8168_mdio_write(tp, 0x15, 0x037e); - rtl8168_mdio_write(tp, 0x19, 0x4422); - rtl8168_mdio_write(tp, 0x15, 0x037f); - rtl8168_mdio_write(tp, 0x19, 0x6980); - rtl8168_mdio_write(tp, 0x15, 0x0380); - rtl8168_mdio_write(tp, 0x19, 0xb608); - rtl8168_mdio_write(tp, 0x15, 0x0381); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x0382); - rtl8168_mdio_write(tp, 0x19, 0xbc05); - rtl8168_mdio_write(tp, 0x15, 0x0383); - rtl8168_mdio_write(tp, 0x19, 0xc21c); - rtl8168_mdio_write(tp, 0x15, 0x0384); - rtl8168_mdio_write(tp, 0x19, 0x0032); - rtl8168_mdio_write(tp, 0x15, 0x0385); - rtl8168_mdio_write(tp, 0x19, 0xa1fb); - rtl8168_mdio_write(tp, 0x15, 0x0386); - rtl8168_mdio_write(tp, 0x19, 0x338d); - rtl8168_mdio_write(tp, 0x15, 0x0387); - rtl8168_mdio_write(tp, 0x19, 0x32ae); - rtl8168_mdio_write(tp, 0x15, 0x0388); - rtl8168_mdio_write(tp, 0x19, 0x330d); - rtl8168_mdio_write(tp, 0x15, 0x0389); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x038a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x038b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x038c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x038d); - rtl8168_mdio_write(tp, 0x19, 0x4b97); - rtl8168_mdio_write(tp, 0x15, 0x038e); - rtl8168_mdio_write(tp, 0x19, 0x6a08); - rtl8168_mdio_write(tp, 0x15, 0x038f); - rtl8168_mdio_write(tp, 0x19, 0x4b07); - rtl8168_mdio_write(tp, 0x15, 0x0390); - rtl8168_mdio_write(tp, 0x19, 0x40ac); - rtl8168_mdio_write(tp, 0x15, 0x0391); - rtl8168_mdio_write(tp, 0x19, 0x4445); - rtl8168_mdio_write(tp, 0x15, 0x0392); - rtl8168_mdio_write(tp, 0x19, 0x404e); - rtl8168_mdio_write(tp, 0x15, 0x0393); - rtl8168_mdio_write(tp, 0x19, 0x4461); - rtl8168_mdio_write(tp, 0x15, 0x0394); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x0395); - rtl8168_mdio_write(tp, 0x19, 0x9c0a); - rtl8168_mdio_write(tp, 0x15, 0x0396); - rtl8168_mdio_write(tp, 0x19, 0x63da); - rtl8168_mdio_write(tp, 0x15, 0x0397); - rtl8168_mdio_write(tp, 0x19, 0x6f0c); - rtl8168_mdio_write(tp, 0x15, 0x0398); - rtl8168_mdio_write(tp, 0x19, 0x5440); - rtl8168_mdio_write(tp, 0x15, 0x0399); - rtl8168_mdio_write(tp, 0x19, 0x4b98); - rtl8168_mdio_write(tp, 0x15, 0x039a); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x039b); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x039c); - rtl8168_mdio_write(tp, 0x19, 0x4b08); - rtl8168_mdio_write(tp, 0x15, 0x039d); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x039e); - rtl8168_mdio_write(tp, 0x19, 0x33a5); - rtl8168_mdio_write(tp, 0x15, 0x039f); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x03a0); - rtl8168_mdio_write(tp, 0x19, 0x00e8); - rtl8168_mdio_write(tp, 0x15, 0x03a1); - rtl8168_mdio_write(tp, 0x19, 0x820e); - rtl8168_mdio_write(tp, 0x15, 0x03a2); - rtl8168_mdio_write(tp, 0x19, 0xa10d); - rtl8168_mdio_write(tp, 0x15, 0x03a3); - rtl8168_mdio_write(tp, 0x19, 0x9df1); - rtl8168_mdio_write(tp, 0x15, 0x03a4); - rtl8168_mdio_write(tp, 0x19, 0x33af); - rtl8168_mdio_write(tp, 0x15, 0x03a5); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x03a6); - rtl8168_mdio_write(tp, 0x19, 0x00f9); - rtl8168_mdio_write(tp, 0x15, 0x03a7); - rtl8168_mdio_write(tp, 0x19, 0xc017); - rtl8168_mdio_write(tp, 0x15, 0x03a8); - rtl8168_mdio_write(tp, 0x19, 0x0007); - rtl8168_mdio_write(tp, 0x15, 0x03a9); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x03aa); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x03ab); - rtl8168_mdio_write(tp, 0x19, 0xa104); - rtl8168_mdio_write(tp, 0x15, 0x03ac); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x03ad); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x03ae); - rtl8168_mdio_write(tp, 0x19, 0x9df7); - rtl8168_mdio_write(tp, 0x15, 0x03af); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x03b0); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x03b1); - rtl8168_mdio_write(tp, 0x19, 0x33b6); - rtl8168_mdio_write(tp, 0x15, 0x03b2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b6); - rtl8168_mdio_write(tp, 0x19, 0x55af); - rtl8168_mdio_write(tp, 0x15, 0x03b7); - rtl8168_mdio_write(tp, 0x19, 0x7ff0); - rtl8168_mdio_write(tp, 0x15, 0x03b8); - rtl8168_mdio_write(tp, 0x19, 0x6ff0); - rtl8168_mdio_write(tp, 0x15, 0x03b9); - rtl8168_mdio_write(tp, 0x19, 0x4bb9); - rtl8168_mdio_write(tp, 0x15, 0x03ba); - rtl8168_mdio_write(tp, 0x19, 0x6a80); - rtl8168_mdio_write(tp, 0x15, 0x03bb); - rtl8168_mdio_write(tp, 0x19, 0x4b29); - rtl8168_mdio_write(tp, 0x15, 0x03bc); - rtl8168_mdio_write(tp, 0x19, 0x4041); - rtl8168_mdio_write(tp, 0x15, 0x03bd); - rtl8168_mdio_write(tp, 0x19, 0x440a); - rtl8168_mdio_write(tp, 0x15, 0x03be); - rtl8168_mdio_write(tp, 0x19, 0x4029); - rtl8168_mdio_write(tp, 0x15, 0x03bf); - rtl8168_mdio_write(tp, 0x19, 0x4418); - rtl8168_mdio_write(tp, 0x15, 0x03c0); - rtl8168_mdio_write(tp, 0x19, 0x4090); - rtl8168_mdio_write(tp, 0x15, 0x03c1); - rtl8168_mdio_write(tp, 0x19, 0x4438); - rtl8168_mdio_write(tp, 0x15, 0x03c2); - rtl8168_mdio_write(tp, 0x19, 0x40c4); - rtl8168_mdio_write(tp, 0x15, 0x03c3); - rtl8168_mdio_write(tp, 0x19, 0x447b); - rtl8168_mdio_write(tp, 0x15, 0x03c4); - rtl8168_mdio_write(tp, 0x19, 0xb6c4); - rtl8168_mdio_write(tp, 0x15, 0x03c5); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x03c6); - rtl8168_mdio_write(tp, 0x19, 0x9bfe); - rtl8168_mdio_write(tp, 0x15, 0x03c7); - rtl8168_mdio_write(tp, 0x19, 0x33cc); - rtl8168_mdio_write(tp, 0x15, 0x03c8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03c9); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ca); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03cb); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03cc); - rtl8168_mdio_write(tp, 0x19, 0x542f); - rtl8168_mdio_write(tp, 0x15, 0x03cd); - rtl8168_mdio_write(tp, 0x19, 0x499a); - rtl8168_mdio_write(tp, 0x15, 0x03ce); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x03cf); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03d0); - rtl8168_mdio_write(tp, 0x19, 0x490a); - rtl8168_mdio_write(tp, 0x15, 0x03d1); - rtl8168_mdio_write(tp, 0x19, 0x405e); - rtl8168_mdio_write(tp, 0x15, 0x03d2); - rtl8168_mdio_write(tp, 0x19, 0x44f8); - rtl8168_mdio_write(tp, 0x15, 0x03d3); - rtl8168_mdio_write(tp, 0x19, 0x6b00); - rtl8168_mdio_write(tp, 0x15, 0x03d4); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x03d5); - rtl8168_mdio_write(tp, 0x19, 0x0028); - rtl8168_mdio_write(tp, 0x15, 0x03d6); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x03d7); - rtl8168_mdio_write(tp, 0x19, 0xbd27); - rtl8168_mdio_write(tp, 0x15, 0x03d8); - rtl8168_mdio_write(tp, 0x19, 0x9cfc); - rtl8168_mdio_write(tp, 0x15, 0x03d9); - rtl8168_mdio_write(tp, 0x19, 0xc639); - rtl8168_mdio_write(tp, 0x15, 0x03da); - rtl8168_mdio_write(tp, 0x19, 0x000f); - rtl8168_mdio_write(tp, 0x15, 0x03db); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x03dc); - rtl8168_mdio_write(tp, 0x19, 0x7c01); - rtl8168_mdio_write(tp, 0x15, 0x03dd); - rtl8168_mdio_write(tp, 0x19, 0x4c01); - rtl8168_mdio_write(tp, 0x15, 0x03de); - rtl8168_mdio_write(tp, 0x19, 0x9af6); - rtl8168_mdio_write(tp, 0x15, 0x03df); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03e0); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03e1); - rtl8168_mdio_write(tp, 0x19, 0x4470); - rtl8168_mdio_write(tp, 0x15, 0x03e2); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03e3); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03e4); - rtl8168_mdio_write(tp, 0x19, 0x33d4); - rtl8168_mdio_write(tp, 0x15, 0x03e5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03e6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03e7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03e8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03e9); - rtl8168_mdio_write(tp, 0x19, 0x49bb); - rtl8168_mdio_write(tp, 0x15, 0x03ea); - rtl8168_mdio_write(tp, 0x19, 0x4478); - rtl8168_mdio_write(tp, 0x15, 0x03eb); - rtl8168_mdio_write(tp, 0x19, 0x492b); - rtl8168_mdio_write(tp, 0x15, 0x03ec); - rtl8168_mdio_write(tp, 0x19, 0x6b80); - rtl8168_mdio_write(tp, 0x15, 0x03ed); - rtl8168_mdio_write(tp, 0x19, 0x7c01); - rtl8168_mdio_write(tp, 0x15, 0x03ee); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x03ef); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x03f0); - rtl8168_mdio_write(tp, 0x19, 0x000d); - rtl8168_mdio_write(tp, 0x15, 0x03f1); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x03f2); - rtl8168_mdio_write(tp, 0x19, 0xbd0c); - rtl8168_mdio_write(tp, 0x15, 0x03f3); - rtl8168_mdio_write(tp, 0x19, 0xc428); - rtl8168_mdio_write(tp, 0x15, 0x03f4); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x03f5); - rtl8168_mdio_write(tp, 0x19, 0x9afa); - rtl8168_mdio_write(tp, 0x15, 0x03f6); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03f7); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03f8); - rtl8168_mdio_write(tp, 0x19, 0x4470); - rtl8168_mdio_write(tp, 0x15, 0x03f9); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03fa); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03fb); - rtl8168_mdio_write(tp, 0x19, 0x33ef); - rtl8168_mdio_write(tp, 0x15, 0x03fc); - rtl8168_mdio_write(tp, 0x19, 0x3342); - rtl8168_mdio_write(tp, 0x15, 0x03fd); - rtl8168_mdio_write(tp, 0x19, 0x330d); - rtl8168_mdio_write(tp, 0x15, 0x03fe); - rtl8168_mdio_write(tp, 0x19, 0x32ae); - rtl8168_mdio_write(tp, 0x15, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x0112); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x1f02); - rtl8168_mdio_write(tp, 0x06, 0x012c); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x3c02); - rtl8168_mdio_write(tp, 0x06, 0x0156); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x6d02); - rtl8168_mdio_write(tp, 0x06, 0x809d); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xc702); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd105); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xcd02); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xca02); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd105); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xd002); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd481); - rtl8168_mdio_write(tp, 0x06, 0xc9e4); - rtl8168_mdio_write(tp, 0x06, 0x8b90); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x91d4); - rtl8168_mdio_write(tp, 0x06, 0x81b8); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x92e5); - rtl8168_mdio_write(tp, 0x06, 0x8b93); - rtl8168_mdio_write(tp, 0x06, 0xbf8b); - rtl8168_mdio_write(tp, 0x06, 0x88ec); - rtl8168_mdio_write(tp, 0x06, 0x0019); - rtl8168_mdio_write(tp, 0x06, 0xa98b); - rtl8168_mdio_write(tp, 0x06, 0x90f9); - rtl8168_mdio_write(tp, 0x06, 0xeeff); - rtl8168_mdio_write(tp, 0x06, 0xf600); - rtl8168_mdio_write(tp, 0x06, 0xeeff); - rtl8168_mdio_write(tp, 0x06, 0xf7fc); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xc102); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xc402); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x201a); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x824b); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x1902); - rtl8168_mdio_write(tp, 0x06, 0x2c9d); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x9602); - rtl8168_mdio_write(tp, 0x06, 0x0473); - rtl8168_mdio_write(tp, 0x06, 0x022e); - rtl8168_mdio_write(tp, 0x06, 0x3902); - rtl8168_mdio_write(tp, 0x06, 0x044d); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x210b); - rtl8168_mdio_write(tp, 0x06, 0xf621); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x0416); - rtl8168_mdio_write(tp, 0x06, 0x021b); - rtl8168_mdio_write(tp, 0x06, 0xa4e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x22e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2305); - rtl8168_mdio_write(tp, 0x06, 0xf623); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x24e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2505); - rtl8168_mdio_write(tp, 0x06, 0xf625); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x26e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xdae0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x27e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x5cfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad21); - rtl8168_mdio_write(tp, 0x06, 0x57e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xc059); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b3c); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e44); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x3cad); - rtl8168_mdio_write(tp, 0x06, 0x211d); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x84f7); - rtl8168_mdio_write(tp, 0x06, 0x29e5); - rtl8168_mdio_write(tp, 0x06, 0x8b84); - rtl8168_mdio_write(tp, 0x06, 0xac27); - rtl8168_mdio_write(tp, 0x06, 0x0dac); - rtl8168_mdio_write(tp, 0x06, 0x2605); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x7fae); - rtl8168_mdio_write(tp, 0x06, 0x2b02); - rtl8168_mdio_write(tp, 0x06, 0x2c23); - rtl8168_mdio_write(tp, 0x06, 0xae26); - rtl8168_mdio_write(tp, 0x06, 0x022c); - rtl8168_mdio_write(tp, 0x06, 0x41ae); - rtl8168_mdio_write(tp, 0x06, 0x21e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x18e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0x58fc); - rtl8168_mdio_write(tp, 0x06, 0xe4ff); - rtl8168_mdio_write(tp, 0x06, 0xf7d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x2eee); - rtl8168_mdio_write(tp, 0x06, 0x0232); - rtl8168_mdio_write(tp, 0x06, 0x0ad1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x82e8); - rtl8168_mdio_write(tp, 0x06, 0x0232); - rtl8168_mdio_write(tp, 0x06, 0x0a02); - rtl8168_mdio_write(tp, 0x06, 0x2bdf); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x04d0); - rtl8168_mdio_write(tp, 0x06, 0x0202); - rtl8168_mdio_write(tp, 0x06, 0x1e97); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2228); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xd302); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd10c); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xd602); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd104); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xd902); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xe802); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xe0ff); - rtl8168_mdio_write(tp, 0x06, 0xf768); - rtl8168_mdio_write(tp, 0x06, 0x03e4); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xd004); - rtl8168_mdio_write(tp, 0x06, 0x0228); - rtl8168_mdio_write(tp, 0x06, 0x7a04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0xe234); - rtl8168_mdio_write(tp, 0x06, 0xe1e2); - rtl8168_mdio_write(tp, 0x06, 0x35f6); - rtl8168_mdio_write(tp, 0x06, 0x2be4); - rtl8168_mdio_write(tp, 0x06, 0xe234); - rtl8168_mdio_write(tp, 0x06, 0xe5e2); - rtl8168_mdio_write(tp, 0x06, 0x35fc); - rtl8168_mdio_write(tp, 0x06, 0x05f8); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xf72b); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xfc05); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69ac); - rtl8168_mdio_write(tp, 0x06, 0x1b4c); - rtl8168_mdio_write(tp, 0x06, 0xbf2e); - rtl8168_mdio_write(tp, 0x06, 0x3002); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0xef01); - rtl8168_mdio_write(tp, 0x06, 0xe28a); - rtl8168_mdio_write(tp, 0x06, 0x76e4); - rtl8168_mdio_write(tp, 0x06, 0x8a76); - rtl8168_mdio_write(tp, 0x06, 0x1f12); - rtl8168_mdio_write(tp, 0x06, 0x9e3a); - rtl8168_mdio_write(tp, 0x06, 0xef12); - rtl8168_mdio_write(tp, 0x06, 0x5907); - rtl8168_mdio_write(tp, 0x06, 0x9f12); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf721); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40d0); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x287a); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x34fc); - rtl8168_mdio_write(tp, 0x06, 0xa000); - rtl8168_mdio_write(tp, 0x06, 0x1002); - rtl8168_mdio_write(tp, 0x06, 0x2dc3); - rtl8168_mdio_write(tp, 0x06, 0x022e); - rtl8168_mdio_write(tp, 0x06, 0x21e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf621); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40ae); - rtl8168_mdio_write(tp, 0x06, 0x0fbf); - rtl8168_mdio_write(tp, 0x06, 0x3fa5); - rtl8168_mdio_write(tp, 0x06, 0x0231); - rtl8168_mdio_write(tp, 0x06, 0x6cbf); - rtl8168_mdio_write(tp, 0x06, 0x3fa2); - rtl8168_mdio_write(tp, 0x06, 0x0231); - rtl8168_mdio_write(tp, 0x06, 0x6c02); - rtl8168_mdio_write(tp, 0x06, 0x2dc3); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0xe2f4); - rtl8168_mdio_write(tp, 0x06, 0xe1e2); - rtl8168_mdio_write(tp, 0x06, 0xf5e4); - rtl8168_mdio_write(tp, 0x06, 0x8a78); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0x79ee); - rtl8168_mdio_write(tp, 0x06, 0xe2f4); - rtl8168_mdio_write(tp, 0x06, 0xd8ee); - rtl8168_mdio_write(tp, 0x06, 0xe2f5); - rtl8168_mdio_write(tp, 0x06, 0x20fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2065); - rtl8168_mdio_write(tp, 0x06, 0xd200); - rtl8168_mdio_write(tp, 0x06, 0xbf2e); - rtl8168_mdio_write(tp, 0x06, 0xe802); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0x1e21); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xdf02); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0x0c11); - rtl8168_mdio_write(tp, 0x06, 0x1e21); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xe202); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0x0c12); - rtl8168_mdio_write(tp, 0x06, 0x1e21); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xe502); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0x0c13); - rtl8168_mdio_write(tp, 0x06, 0x1e21); - rtl8168_mdio_write(tp, 0x06, 0xbf1f); - rtl8168_mdio_write(tp, 0x06, 0x5302); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0x0c14); - rtl8168_mdio_write(tp, 0x06, 0x1e21); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xeb02); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0x0c16); - rtl8168_mdio_write(tp, 0x06, 0x1e21); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0xe01f); - rtl8168_mdio_write(tp, 0x06, 0x029e); - rtl8168_mdio_write(tp, 0x06, 0x22e6); - rtl8168_mdio_write(tp, 0x06, 0x83e0); - rtl8168_mdio_write(tp, 0x06, 0xad31); - rtl8168_mdio_write(tp, 0x06, 0x14ad); - rtl8168_mdio_write(tp, 0x06, 0x3011); - rtl8168_mdio_write(tp, 0x06, 0xef02); - rtl8168_mdio_write(tp, 0x06, 0x580c); - rtl8168_mdio_write(tp, 0x06, 0x9e07); - rtl8168_mdio_write(tp, 0x06, 0xad36); - rtl8168_mdio_write(tp, 0x06, 0x085a); - rtl8168_mdio_write(tp, 0x06, 0x309f); - rtl8168_mdio_write(tp, 0x06, 0x04d1); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0x02d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x82dc); - rtl8168_mdio_write(tp, 0x06, 0x0232); - rtl8168_mdio_write(tp, 0x06, 0x0aef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x0400); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0x77e1); - rtl8168_mdio_write(tp, 0x06, 0x4010); - rtl8168_mdio_write(tp, 0x06, 0xe150); - rtl8168_mdio_write(tp, 0x06, 0x32e1); - rtl8168_mdio_write(tp, 0x06, 0x5030); - rtl8168_mdio_write(tp, 0x06, 0xe144); - rtl8168_mdio_write(tp, 0x06, 0x74e1); - rtl8168_mdio_write(tp, 0x06, 0x44bb); - rtl8168_mdio_write(tp, 0x06, 0xe2d2); - rtl8168_mdio_write(tp, 0x06, 0x40e0); - rtl8168_mdio_write(tp, 0x06, 0x2cfc); - rtl8168_mdio_write(tp, 0x06, 0xe2cc); - rtl8168_mdio_write(tp, 0x06, 0xcce2); - rtl8168_mdio_write(tp, 0x06, 0x00cc); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0x99e0); - rtl8168_mdio_write(tp, 0x06, 0x3688); - rtl8168_mdio_write(tp, 0x06, 0xe036); - rtl8168_mdio_write(tp, 0x06, 0x99e1); - rtl8168_mdio_write(tp, 0x06, 0x40dd); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x05, 0xe142); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x05, 0xe140); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - gphy_val |= BIT_2; - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); -} - -static void -rtl8168_set_phy_mcu_8168evl_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - unsigned int gphy_val,i; - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x1800); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val &= ~(BIT_12); - rtl8168_mdio_write(tp, 0x15, gphy_val); - rtl8168_mdio_write(tp, 0x00, 0x4800); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x002f); - for (i = 0; i < 1000; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1c); - if ((gphy_val & 0x0080) == 0x0080) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x1800); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x17); - if (!(gphy_val & 0x0001)) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x00AF); - rtl8168_mdio_write(tp, 0x19, 0x4060); - rtl8168_mdio_write(tp, 0x15, 0x00B0); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x00B1); - rtl8168_mdio_write(tp, 0x19, 0x7e00); - rtl8168_mdio_write(tp, 0x15, 0x00B2); - rtl8168_mdio_write(tp, 0x19, 0x72B0); - rtl8168_mdio_write(tp, 0x15, 0x00B3); - rtl8168_mdio_write(tp, 0x19, 0x7F00); - rtl8168_mdio_write(tp, 0x15, 0x00B4); - rtl8168_mdio_write(tp, 0x19, 0x73B0); - rtl8168_mdio_write(tp, 0x15, 0x0101); - rtl8168_mdio_write(tp, 0x19, 0x0005); - rtl8168_mdio_write(tp, 0x15, 0x0103); - rtl8168_mdio_write(tp, 0x19, 0x0003); - rtl8168_mdio_write(tp, 0x15, 0x0105); - rtl8168_mdio_write(tp, 0x19, 0x30FD); - rtl8168_mdio_write(tp, 0x15, 0x0106); - rtl8168_mdio_write(tp, 0x19, 0x9DF7); - rtl8168_mdio_write(tp, 0x15, 0x0107); - rtl8168_mdio_write(tp, 0x19, 0x30C6); - rtl8168_mdio_write(tp, 0x15, 0x0098); - rtl8168_mdio_write(tp, 0x19, 0x7c0b); - rtl8168_mdio_write(tp, 0x15, 0x0099); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00eb); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00f8); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00fe); - rtl8168_mdio_write(tp, 0x19, 0x6f0f); - rtl8168_mdio_write(tp, 0x15, 0x00db); - rtl8168_mdio_write(tp, 0x19, 0x6f09); - rtl8168_mdio_write(tp, 0x15, 0x00dc); - rtl8168_mdio_write(tp, 0x19, 0xaefd); - rtl8168_mdio_write(tp, 0x15, 0x00dd); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00de); - rtl8168_mdio_write(tp, 0x19, 0xc60b); - rtl8168_mdio_write(tp, 0x15, 0x00df); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00e0); - rtl8168_mdio_write(tp, 0x19, 0x30e1); - rtl8168_mdio_write(tp, 0x15, 0x020c); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x020e); - rtl8168_mdio_write(tp, 0x19, 0x9813); - rtl8168_mdio_write(tp, 0x15, 0x020f); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0210); - rtl8168_mdio_write(tp, 0x19, 0x930f); - rtl8168_mdio_write(tp, 0x15, 0x0211); - rtl8168_mdio_write(tp, 0x19, 0x9206); - rtl8168_mdio_write(tp, 0x15, 0x0212); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0213); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0214); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0215); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0216); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0217); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0218); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0219); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x021a); - rtl8168_mdio_write(tp, 0x19, 0x5540); - rtl8168_mdio_write(tp, 0x15, 0x021b); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x021c); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x021d); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x021e); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x021f); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0220); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0221); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x0222); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0223); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x0224); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0225); - rtl8168_mdio_write(tp, 0x19, 0x3231); - rtl8168_mdio_write(tp, 0x15, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2160); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0040); - rtl8168_mdio_write(tp, 0x18, 0x0004); - if (pdev->subsystem_vendor == 0x144d && - pdev->subsystem_device == 0xc0a6) { - rtl8168_mdio_write(tp, 0x18, 0x0724); - rtl8168_mdio_write(tp, 0x19, 0xfe00); - rtl8168_mdio_write(tp, 0x18, 0x0734); - rtl8168_mdio_write(tp, 0x19, 0xfd00); - rtl8168_mdio_write(tp, 0x18, 0x1824); - rtl8168_mdio_write(tp, 0x19, 0xfc00); - rtl8168_mdio_write(tp, 0x18, 0x1834); - rtl8168_mdio_write(tp, 0x19, 0xfd00); - } - rtl8168_mdio_write(tp, 0x18, 0x09d4); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x09e4); - rtl8168_mdio_write(tp, 0x19, 0x0800); - rtl8168_mdio_write(tp, 0x18, 0x09f4); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x0a04); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x0a14); - rtl8168_mdio_write(tp, 0x19, 0x0c00); - rtl8168_mdio_write(tp, 0x18, 0x0a24); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x0a74); - rtl8168_mdio_write(tp, 0x19, 0xf600); - rtl8168_mdio_write(tp, 0x18, 0x1a24); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x18, 0x1a64); - rtl8168_mdio_write(tp, 0x19, 0x0500); - rtl8168_mdio_write(tp, 0x18, 0x1a74); - rtl8168_mdio_write(tp, 0x19, 0x9500); - rtl8168_mdio_write(tp, 0x18, 0x1a84); - rtl8168_mdio_write(tp, 0x19, 0x8000); - rtl8168_mdio_write(tp, 0x18, 0x1a94); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x18, 0x1aa4); - rtl8168_mdio_write(tp, 0x19, 0x9600); - rtl8168_mdio_write(tp, 0x18, 0x1ac4); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x1ad4); - rtl8168_mdio_write(tp, 0x19, 0x0800); - rtl8168_mdio_write(tp, 0x18, 0x1af4); - rtl8168_mdio_write(tp, 0x19, 0xc400); - rtl8168_mdio_write(tp, 0x18, 0x1b04); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x1b14); - rtl8168_mdio_write(tp, 0x19, 0x0800); - rtl8168_mdio_write(tp, 0x18, 0x1b24); - rtl8168_mdio_write(tp, 0x19, 0xfd00); - rtl8168_mdio_write(tp, 0x18, 0x1b34); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x1b44); - rtl8168_mdio_write(tp, 0x19, 0x0400); - rtl8168_mdio_write(tp, 0x18, 0x1b94); - rtl8168_mdio_write(tp, 0x19, 0xf100); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2100); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0040); - rtl8168_mdio_write(tp, 0x18, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x0115); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x2202); - rtl8168_mdio_write(tp, 0x06, 0x80a0); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x3f02); - rtl8168_mdio_write(tp, 0x06, 0x0159); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0xbd02); - rtl8168_mdio_write(tp, 0x06, 0x80da); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xd481); - rtl8168_mdio_write(tp, 0x06, 0xd2e4); - rtl8168_mdio_write(tp, 0x06, 0x8b92); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x93d1); - rtl8168_mdio_write(tp, 0x06, 0x03bf); - rtl8168_mdio_write(tp, 0x06, 0x859e); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23d1); - rtl8168_mdio_write(tp, 0x06, 0x02bf); - rtl8168_mdio_write(tp, 0x06, 0x85a1); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23ee); - rtl8168_mdio_write(tp, 0x06, 0x8608); - rtl8168_mdio_write(tp, 0x06, 0x03ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x60ee); - rtl8168_mdio_write(tp, 0x06, 0x8610); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8611); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x07ee); - rtl8168_mdio_write(tp, 0x06, 0x8abf); - rtl8168_mdio_write(tp, 0x06, 0x73ee); - rtl8168_mdio_write(tp, 0x06, 0x8a95); - rtl8168_mdio_write(tp, 0x06, 0x02bf); - rtl8168_mdio_write(tp, 0x06, 0x8b88); - rtl8168_mdio_write(tp, 0x06, 0xec00); - rtl8168_mdio_write(tp, 0x06, 0x19a9); - rtl8168_mdio_write(tp, 0x06, 0x8b90); - rtl8168_mdio_write(tp, 0x06, 0xf9ee); - rtl8168_mdio_write(tp, 0x06, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xfed1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8595); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23d1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8598); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x2304); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8a); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x14ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8a); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x1f9a); - rtl8168_mdio_write(tp, 0x06, 0xe0e4); - rtl8168_mdio_write(tp, 0x06, 0x26e1); - rtl8168_mdio_write(tp, 0x06, 0xe427); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x2623); - rtl8168_mdio_write(tp, 0x06, 0xe5e4); - rtl8168_mdio_write(tp, 0x06, 0x27fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8dad); - rtl8168_mdio_write(tp, 0x06, 0x2014); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8d00); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0x5a78); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x0902); - rtl8168_mdio_write(tp, 0x06, 0x05db); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x7b02); - rtl8168_mdio_write(tp, 0x06, 0x3231); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x1df6); - rtl8168_mdio_write(tp, 0x06, 0x20e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x5c02); - rtl8168_mdio_write(tp, 0x06, 0x2bcb); - rtl8168_mdio_write(tp, 0x06, 0x022d); - rtl8168_mdio_write(tp, 0x06, 0x2902); - rtl8168_mdio_write(tp, 0x06, 0x03b4); - rtl8168_mdio_write(tp, 0x06, 0x0285); - rtl8168_mdio_write(tp, 0x06, 0x6402); - rtl8168_mdio_write(tp, 0x06, 0x2eca); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0xcd02); - rtl8168_mdio_write(tp, 0x06, 0x046f); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x210b); - rtl8168_mdio_write(tp, 0x06, 0xf621); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x8520); - rtl8168_mdio_write(tp, 0x06, 0x021b); - rtl8168_mdio_write(tp, 0x06, 0xe8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x22e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2308); - rtl8168_mdio_write(tp, 0x06, 0xf623); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x311c); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2405); - rtl8168_mdio_write(tp, 0x06, 0xf624); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x25e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2608); - rtl8168_mdio_write(tp, 0x06, 0xf626); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x2df5); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2705); - rtl8168_mdio_write(tp, 0x06, 0xf627); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x037a); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x65d2); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x2fe9); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf61e); - rtl8168_mdio_write(tp, 0x06, 0x21bf); - rtl8168_mdio_write(tp, 0x06, 0x2ff5); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf60c); - rtl8168_mdio_write(tp, 0x06, 0x111e); - rtl8168_mdio_write(tp, 0x06, 0x21bf); - rtl8168_mdio_write(tp, 0x06, 0x2ff8); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf60c); - rtl8168_mdio_write(tp, 0x06, 0x121e); - rtl8168_mdio_write(tp, 0x06, 0x21bf); - rtl8168_mdio_write(tp, 0x06, 0x2ffb); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf60c); - rtl8168_mdio_write(tp, 0x06, 0x131e); - rtl8168_mdio_write(tp, 0x06, 0x21bf); - rtl8168_mdio_write(tp, 0x06, 0x1f97); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf60c); - rtl8168_mdio_write(tp, 0x06, 0x141e); - rtl8168_mdio_write(tp, 0x06, 0x21bf); - rtl8168_mdio_write(tp, 0x06, 0x859b); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf60c); - rtl8168_mdio_write(tp, 0x06, 0x161e); - rtl8168_mdio_write(tp, 0x06, 0x21e0); - rtl8168_mdio_write(tp, 0x06, 0x8a8c); - rtl8168_mdio_write(tp, 0x06, 0x1f02); - rtl8168_mdio_write(tp, 0x06, 0x9e22); - rtl8168_mdio_write(tp, 0x06, 0xe68a); - rtl8168_mdio_write(tp, 0x06, 0x8cad); - rtl8168_mdio_write(tp, 0x06, 0x3114); - rtl8168_mdio_write(tp, 0x06, 0xad30); - rtl8168_mdio_write(tp, 0x06, 0x11ef); - rtl8168_mdio_write(tp, 0x06, 0x0258); - rtl8168_mdio_write(tp, 0x06, 0x0c9e); - rtl8168_mdio_write(tp, 0x06, 0x07ad); - rtl8168_mdio_write(tp, 0x06, 0x3608); - rtl8168_mdio_write(tp, 0x06, 0x5a30); - rtl8168_mdio_write(tp, 0x06, 0x9f04); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xae02); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf2f); - rtl8168_mdio_write(tp, 0x06, 0xf202); - rtl8168_mdio_write(tp, 0x06, 0x3723); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xface); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69fa); - rtl8168_mdio_write(tp, 0x06, 0xd401); - rtl8168_mdio_write(tp, 0x06, 0x55b4); - rtl8168_mdio_write(tp, 0x06, 0xfebf); - rtl8168_mdio_write(tp, 0x06, 0x85a7); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf6ac); - rtl8168_mdio_write(tp, 0x06, 0x280b); - rtl8168_mdio_write(tp, 0x06, 0xbf85); - rtl8168_mdio_write(tp, 0x06, 0xa402); - rtl8168_mdio_write(tp, 0x06, 0x36f6); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x49ae); - rtl8168_mdio_write(tp, 0x06, 0x64bf); - rtl8168_mdio_write(tp, 0x06, 0x85a4); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf6ac); - rtl8168_mdio_write(tp, 0x06, 0x285b); - rtl8168_mdio_write(tp, 0x06, 0xd000); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x60ac); - rtl8168_mdio_write(tp, 0x06, 0x2105); - rtl8168_mdio_write(tp, 0x06, 0xac22); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x4ebf); - rtl8168_mdio_write(tp, 0x06, 0xe0c4); - rtl8168_mdio_write(tp, 0x06, 0xbe86); - rtl8168_mdio_write(tp, 0x06, 0x14d2); - rtl8168_mdio_write(tp, 0x06, 0x04d8); - rtl8168_mdio_write(tp, 0x06, 0x19d9); - rtl8168_mdio_write(tp, 0x06, 0x1907); - rtl8168_mdio_write(tp, 0x06, 0xdc19); - rtl8168_mdio_write(tp, 0x06, 0xdd19); - rtl8168_mdio_write(tp, 0x06, 0x0789); - rtl8168_mdio_write(tp, 0x06, 0x89ef); - rtl8168_mdio_write(tp, 0x06, 0x645e); - rtl8168_mdio_write(tp, 0x06, 0x07ff); - rtl8168_mdio_write(tp, 0x06, 0x0d65); - rtl8168_mdio_write(tp, 0x06, 0x5cf8); - rtl8168_mdio_write(tp, 0x06, 0x001e); - rtl8168_mdio_write(tp, 0x06, 0x46dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0x19b2); - rtl8168_mdio_write(tp, 0x06, 0xe2d4); - rtl8168_mdio_write(tp, 0x06, 0x0001); - rtl8168_mdio_write(tp, 0x06, 0xbf85); - rtl8168_mdio_write(tp, 0x06, 0xa402); - rtl8168_mdio_write(tp, 0x06, 0x3723); - rtl8168_mdio_write(tp, 0x06, 0xae1d); - rtl8168_mdio_write(tp, 0x06, 0xbee0); - rtl8168_mdio_write(tp, 0x06, 0xc4bf); - rtl8168_mdio_write(tp, 0x06, 0x8614); - rtl8168_mdio_write(tp, 0x06, 0xd204); - rtl8168_mdio_write(tp, 0x06, 0xd819); - rtl8168_mdio_write(tp, 0x06, 0xd919); - rtl8168_mdio_write(tp, 0x06, 0x07dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0x1907); - rtl8168_mdio_write(tp, 0x06, 0xb2f4); - rtl8168_mdio_write(tp, 0x06, 0xd400); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x85a4); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23fe); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfec6); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc05); - rtl8168_mdio_write(tp, 0x06, 0xf9e2); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0xeb5a); - rtl8168_mdio_write(tp, 0x06, 0x070c); - rtl8168_mdio_write(tp, 0x06, 0x031e); - rtl8168_mdio_write(tp, 0x06, 0x20e6); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe7e0); - rtl8168_mdio_write(tp, 0x06, 0xebe0); - rtl8168_mdio_write(tp, 0x06, 0xe0fc); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xfdfd); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac26); - rtl8168_mdio_write(tp, 0x06, 0x1ae0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x14e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xac20); - rtl8168_mdio_write(tp, 0x06, 0x0ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xac23); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xac24); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0x1ab5); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x1c04); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x1d04); - rtl8168_mdio_write(tp, 0x06, 0xe2e0); - rtl8168_mdio_write(tp, 0x06, 0x7ce3); - rtl8168_mdio_write(tp, 0x06, 0xe07d); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x38e1); - rtl8168_mdio_write(tp, 0x06, 0xe039); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x1bad); - rtl8168_mdio_write(tp, 0x06, 0x390d); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf21); - rtl8168_mdio_write(tp, 0x06, 0xd502); - rtl8168_mdio_write(tp, 0x06, 0x3723); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xd8ae); - rtl8168_mdio_write(tp, 0x06, 0x0bac); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0x1802); - rtl8168_mdio_write(tp, 0x06, 0x8360); - rtl8168_mdio_write(tp, 0x06, 0x021a); - rtl8168_mdio_write(tp, 0x06, 0xc6fd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2605); - rtl8168_mdio_write(tp, 0x06, 0x0222); - rtl8168_mdio_write(tp, 0x06, 0xa4f7); - rtl8168_mdio_write(tp, 0x06, 0x28e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xad21); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x23a9); - rtl8168_mdio_write(tp, 0x06, 0xf729); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2005); - rtl8168_mdio_write(tp, 0x06, 0x0214); - rtl8168_mdio_write(tp, 0x06, 0xabf7); - rtl8168_mdio_write(tp, 0x06, 0x2ae0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad23); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x12e7); - rtl8168_mdio_write(tp, 0x06, 0xf72b); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2405); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0xbcf7); - rtl8168_mdio_write(tp, 0x06, 0x2ce5); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x21e5); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2109); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xf4ac); - rtl8168_mdio_write(tp, 0x06, 0x2003); - rtl8168_mdio_write(tp, 0x06, 0x0223); - rtl8168_mdio_write(tp, 0x06, 0x98e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x09e0); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x13fb); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2309); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xf4ac); - rtl8168_mdio_write(tp, 0x06, 0x2203); - rtl8168_mdio_write(tp, 0x06, 0x0212); - rtl8168_mdio_write(tp, 0x06, 0xfae0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x09e0); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xac23); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x83c1); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2608); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0xd2ad); - rtl8168_mdio_write(tp, 0x06, 0x2502); - rtl8168_mdio_write(tp, 0x06, 0xf628); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x210a); - rtl8168_mdio_write(tp, 0x06, 0xe084); - rtl8168_mdio_write(tp, 0x06, 0x0af6); - rtl8168_mdio_write(tp, 0x06, 0x27a0); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0xf629); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2008); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xe8ad); - rtl8168_mdio_write(tp, 0x06, 0x2102); - rtl8168_mdio_write(tp, 0x06, 0xf62a); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2308); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x20a0); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0xf62b); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2408); - rtl8168_mdio_write(tp, 0x06, 0xe086); - rtl8168_mdio_write(tp, 0x06, 0x02a0); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0xf62c); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xf4a1); - rtl8168_mdio_write(tp, 0x06, 0x0008); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf21); - rtl8168_mdio_write(tp, 0x06, 0xd502); - rtl8168_mdio_write(tp, 0x06, 0x3723); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0200); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x241e); - rtl8168_mdio_write(tp, 0x06, 0xe086); - rtl8168_mdio_write(tp, 0x06, 0x02a0); - rtl8168_mdio_write(tp, 0x06, 0x0005); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0xe8ae); - rtl8168_mdio_write(tp, 0x06, 0xf5a0); - rtl8168_mdio_write(tp, 0x06, 0x0105); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0xf8ae); - rtl8168_mdio_write(tp, 0x06, 0x0ba0); - rtl8168_mdio_write(tp, 0x06, 0x0205); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0x14ae); - rtl8168_mdio_write(tp, 0x06, 0x03a0); - rtl8168_mdio_write(tp, 0x06, 0x0300); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0x2bee); - rtl8168_mdio_write(tp, 0x06, 0x8602); - rtl8168_mdio_write(tp, 0x06, 0x01ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8ee); - rtl8168_mdio_write(tp, 0x06, 0x8609); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x8461); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xae10); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8608); - rtl8168_mdio_write(tp, 0x06, 0xe186); - rtl8168_mdio_write(tp, 0x06, 0x091f); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x0611); - rtl8168_mdio_write(tp, 0x06, 0xe586); - rtl8168_mdio_write(tp, 0x06, 0x09ae); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x8602); - rtl8168_mdio_write(tp, 0x06, 0x01fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfbbf); - rtl8168_mdio_write(tp, 0x06, 0x8604); - rtl8168_mdio_write(tp, 0x06, 0xef79); - rtl8168_mdio_write(tp, 0x06, 0xd200); - rtl8168_mdio_write(tp, 0x06, 0xd400); - rtl8168_mdio_write(tp, 0x06, 0x221e); - rtl8168_mdio_write(tp, 0x06, 0x02bf); - rtl8168_mdio_write(tp, 0x06, 0x2fec); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23bf); - rtl8168_mdio_write(tp, 0x06, 0x13f2); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf60d); - rtl8168_mdio_write(tp, 0x06, 0x4559); - rtl8168_mdio_write(tp, 0x06, 0x1fef); - rtl8168_mdio_write(tp, 0x06, 0x97dd); - rtl8168_mdio_write(tp, 0x06, 0xd308); - rtl8168_mdio_write(tp, 0x06, 0x1a93); - rtl8168_mdio_write(tp, 0x06, 0xdd12); - rtl8168_mdio_write(tp, 0x06, 0x17a2); - rtl8168_mdio_write(tp, 0x06, 0x04de); - rtl8168_mdio_write(tp, 0x06, 0xffef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfbee); - rtl8168_mdio_write(tp, 0x06, 0x8602); - rtl8168_mdio_write(tp, 0x06, 0x03d5); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x04ef); - rtl8168_mdio_write(tp, 0x06, 0x79ef); - rtl8168_mdio_write(tp, 0x06, 0x45bf); - rtl8168_mdio_write(tp, 0x06, 0x2fec); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23bf); - rtl8168_mdio_write(tp, 0x06, 0x13f2); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf6ad); - rtl8168_mdio_write(tp, 0x06, 0x2702); - rtl8168_mdio_write(tp, 0x06, 0x78ff); - rtl8168_mdio_write(tp, 0x06, 0xe186); - rtl8168_mdio_write(tp, 0x06, 0x0a1b); - rtl8168_mdio_write(tp, 0x06, 0x01aa); - rtl8168_mdio_write(tp, 0x06, 0x2eef); - rtl8168_mdio_write(tp, 0x06, 0x97d9); - rtl8168_mdio_write(tp, 0x06, 0x7900); - rtl8168_mdio_write(tp, 0x06, 0x9e2b); - rtl8168_mdio_write(tp, 0x06, 0x81dd); - rtl8168_mdio_write(tp, 0x06, 0xbf85); - rtl8168_mdio_write(tp, 0x06, 0xad02); - rtl8168_mdio_write(tp, 0x06, 0x3723); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xef02); - rtl8168_mdio_write(tp, 0x06, 0x100c); - rtl8168_mdio_write(tp, 0x06, 0x11b0); - rtl8168_mdio_write(tp, 0x06, 0xfc0d); - rtl8168_mdio_write(tp, 0x06, 0x11bf); - rtl8168_mdio_write(tp, 0x06, 0x85aa); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x85aa); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23ee); - rtl8168_mdio_write(tp, 0x06, 0x8602); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x0413); - rtl8168_mdio_write(tp, 0x06, 0xa38b); - rtl8168_mdio_write(tp, 0x06, 0xb4d3); - rtl8168_mdio_write(tp, 0x06, 0x8012); - rtl8168_mdio_write(tp, 0x06, 0x17a2); - rtl8168_mdio_write(tp, 0x06, 0x04ad); - rtl8168_mdio_write(tp, 0x06, 0xffef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x48e0); - rtl8168_mdio_write(tp, 0x06, 0x8a96); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0x977c); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x9e35); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x9600); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x9700); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xbee1); - rtl8168_mdio_write(tp, 0x06, 0x8abf); - rtl8168_mdio_write(tp, 0x06, 0xe286); - rtl8168_mdio_write(tp, 0x06, 0x10e3); - rtl8168_mdio_write(tp, 0x06, 0x8611); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0x1aad); - rtl8168_mdio_write(tp, 0x06, 0x2012); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x9603); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x97b7); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x1000); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x1100); - rtl8168_mdio_write(tp, 0x06, 0xae11); - rtl8168_mdio_write(tp, 0x06, 0x15e6); - rtl8168_mdio_write(tp, 0x06, 0x8610); - rtl8168_mdio_write(tp, 0x06, 0xe786); - rtl8168_mdio_write(tp, 0x06, 0x11ae); - rtl8168_mdio_write(tp, 0x06, 0x08ee); - rtl8168_mdio_write(tp, 0x06, 0x8610); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8611); - rtl8168_mdio_write(tp, 0x06, 0x00fd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe001); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x32e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf720); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40bf); - rtl8168_mdio_write(tp, 0x06, 0x31f5); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf6ad); - rtl8168_mdio_write(tp, 0x06, 0x2821); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x20e1); - rtl8168_mdio_write(tp, 0x06, 0xe021); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x18e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40ee); - rtl8168_mdio_write(tp, 0x06, 0x8b3b); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0x8a8a); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0x8be4); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0x01ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x80ad); - rtl8168_mdio_write(tp, 0x06, 0x2722); - rtl8168_mdio_write(tp, 0x06, 0xbf44); - rtl8168_mdio_write(tp, 0x06, 0xfc02); - rtl8168_mdio_write(tp, 0x06, 0x36f6); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x441f); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x15e5); - rtl8168_mdio_write(tp, 0x06, 0x8b44); - rtl8168_mdio_write(tp, 0x06, 0xad29); - rtl8168_mdio_write(tp, 0x06, 0x07ac); - rtl8168_mdio_write(tp, 0x06, 0x2804); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xae02); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf85); - rtl8168_mdio_write(tp, 0x06, 0xb002); - rtl8168_mdio_write(tp, 0x06, 0x3723); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x0400); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0x77e1); - rtl8168_mdio_write(tp, 0x06, 0x40dd); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0x32e1); - rtl8168_mdio_write(tp, 0x06, 0x5074); - rtl8168_mdio_write(tp, 0x06, 0xe144); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0xdaff); - rtl8168_mdio_write(tp, 0x06, 0xe0c0); - rtl8168_mdio_write(tp, 0x06, 0x52e0); - rtl8168_mdio_write(tp, 0x06, 0xeed9); - rtl8168_mdio_write(tp, 0x06, 0xe04c); - rtl8168_mdio_write(tp, 0x06, 0xbbe0); - rtl8168_mdio_write(tp, 0x06, 0x2a00); - rtl8168_mdio_write(tp, 0x05, 0xe142); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x05, 0xe140); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0042); - rtl8168_mdio_write(tp, 0x18, 0x2300); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - if (tp->RequiredSecLanDonglePatch) { - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~BIT_2; - rtl8168_mdio_write(tp, 0x17, gphy_val); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); -} - -static void -rtl8168_set_phy_mcu_8168f_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val,i; - - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x1800); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val &= ~(BIT_12); - rtl8168_mdio_write(tp,0x15, gphy_val); - rtl8168_mdio_write(tp,0x00, 0x4800); - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x002f); - for (i = 0; i < 1000; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1c); - if (gphy_val & 0x0080) - break; - } - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x1800); - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x0023); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x18); - if (!(gphy_val & 0x0001)) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x0194); - rtl8168_mdio_write(tp, 0x19, 0x407D); - rtl8168_mdio_write(tp, 0x15, 0x0098); - rtl8168_mdio_write(tp, 0x19, 0x7c0b); - rtl8168_mdio_write(tp, 0x15, 0x0099); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00eb); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00f8); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00fe); - rtl8168_mdio_write(tp, 0x19, 0x6f0f); - rtl8168_mdio_write(tp, 0x15, 0x00db); - rtl8168_mdio_write(tp, 0x19, 0x6f09); - rtl8168_mdio_write(tp, 0x15, 0x00dc); - rtl8168_mdio_write(tp, 0x19, 0xaefd); - rtl8168_mdio_write(tp, 0x15, 0x00dd); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00de); - rtl8168_mdio_write(tp, 0x19, 0xc60b); - rtl8168_mdio_write(tp, 0x15, 0x00df); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00e0); - rtl8168_mdio_write(tp, 0x19, 0x30e1); - rtl8168_mdio_write(tp, 0x15, 0x020c); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x020e); - rtl8168_mdio_write(tp, 0x19, 0x9813); - rtl8168_mdio_write(tp, 0x15, 0x020f); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0210); - rtl8168_mdio_write(tp, 0x19, 0x930f); - rtl8168_mdio_write(tp, 0x15, 0x0211); - rtl8168_mdio_write(tp, 0x19, 0x9206); - rtl8168_mdio_write(tp, 0x15, 0x0212); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0213); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0214); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0215); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0216); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0217); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0218); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0219); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x021a); - rtl8168_mdio_write(tp, 0x19, 0x5540); - rtl8168_mdio_write(tp, 0x15, 0x021b); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x021c); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x021d); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x021e); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x021f); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0220); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0221); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x0222); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0223); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x0224); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0225); - rtl8168_mdio_write(tp, 0x19, 0x3231); - rtl8168_mdio_write(tp, 0x15, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x0118); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x2502); - rtl8168_mdio_write(tp, 0x06, 0x8090); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x4202); - rtl8168_mdio_write(tp, 0x06, 0x015c); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0xad02); - rtl8168_mdio_write(tp, 0x06, 0x80ca); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xd484); - rtl8168_mdio_write(tp, 0x06, 0x3ce4); - rtl8168_mdio_write(tp, 0x06, 0x8b92); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x93ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac8); - rtl8168_mdio_write(tp, 0x06, 0x03ee); - rtl8168_mdio_write(tp, 0x06, 0x8aca); - rtl8168_mdio_write(tp, 0x06, 0x60ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac0); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac1); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x07ee); - rtl8168_mdio_write(tp, 0x06, 0x8abf); - rtl8168_mdio_write(tp, 0x06, 0x73ee); - rtl8168_mdio_write(tp, 0x06, 0x8a95); - rtl8168_mdio_write(tp, 0x06, 0x02bf); - rtl8168_mdio_write(tp, 0x06, 0x8b88); - rtl8168_mdio_write(tp, 0x06, 0xec00); - rtl8168_mdio_write(tp, 0x06, 0x19a9); - rtl8168_mdio_write(tp, 0x06, 0x8b90); - rtl8168_mdio_write(tp, 0x06, 0xf9ee); - rtl8168_mdio_write(tp, 0x06, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xfed1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x85a4); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7dd1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x85a7); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7d04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8a); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x14ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8a); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x204b); - rtl8168_mdio_write(tp, 0x06, 0xe0e4); - rtl8168_mdio_write(tp, 0x06, 0x26e1); - rtl8168_mdio_write(tp, 0x06, 0xe427); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x2623); - rtl8168_mdio_write(tp, 0x06, 0xe5e4); - rtl8168_mdio_write(tp, 0x06, 0x27fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8dad); - rtl8168_mdio_write(tp, 0x06, 0x2014); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8d00); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0x5a78); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x0902); - rtl8168_mdio_write(tp, 0x06, 0x05e8); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x4f02); - rtl8168_mdio_write(tp, 0x06, 0x326c); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x1df6); - rtl8168_mdio_write(tp, 0x06, 0x20e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x0902); - rtl8168_mdio_write(tp, 0x06, 0x2ab0); - rtl8168_mdio_write(tp, 0x06, 0x0285); - rtl8168_mdio_write(tp, 0x06, 0x1602); - rtl8168_mdio_write(tp, 0x06, 0x03ba); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0xe502); - rtl8168_mdio_write(tp, 0x06, 0x2df1); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0x8302); - rtl8168_mdio_write(tp, 0x06, 0x0475); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x210b); - rtl8168_mdio_write(tp, 0x06, 0xf621); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x83f8); - rtl8168_mdio_write(tp, 0x06, 0x021c); - rtl8168_mdio_write(tp, 0x06, 0x99e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x22e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0235); - rtl8168_mdio_write(tp, 0x06, 0x63e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad23); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x23e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0231); - rtl8168_mdio_write(tp, 0x06, 0x57e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x24e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2505); - rtl8168_mdio_write(tp, 0x06, 0xf625); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x26e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x022d); - rtl8168_mdio_write(tp, 0x06, 0x1ce0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x27e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x80fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac26); - rtl8168_mdio_write(tp, 0x06, 0x1ae0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x14e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xac20); - rtl8168_mdio_write(tp, 0x06, 0x0ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xac23); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xac24); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0x1ac2); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x1c04); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x1d04); - rtl8168_mdio_write(tp, 0x06, 0xe2e0); - rtl8168_mdio_write(tp, 0x06, 0x7ce3); - rtl8168_mdio_write(tp, 0x06, 0xe07d); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x38e1); - rtl8168_mdio_write(tp, 0x06, 0xe039); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x1bad); - rtl8168_mdio_write(tp, 0x06, 0x390d); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf22); - rtl8168_mdio_write(tp, 0x06, 0x7a02); - rtl8168_mdio_write(tp, 0x06, 0x387d); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xacae); - rtl8168_mdio_write(tp, 0x06, 0x0bac); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xe902); - rtl8168_mdio_write(tp, 0x06, 0x822e); - rtl8168_mdio_write(tp, 0x06, 0x021a); - rtl8168_mdio_write(tp, 0x06, 0xd3fd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2602); - rtl8168_mdio_write(tp, 0x06, 0xf728); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2105); - rtl8168_mdio_write(tp, 0x06, 0x0222); - rtl8168_mdio_write(tp, 0x06, 0x8ef7); - rtl8168_mdio_write(tp, 0x06, 0x29e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x14b8); - rtl8168_mdio_write(tp, 0x06, 0xf72a); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2305); - rtl8168_mdio_write(tp, 0x06, 0x0212); - rtl8168_mdio_write(tp, 0x06, 0xf4f7); - rtl8168_mdio_write(tp, 0x06, 0x2be0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x8284); - rtl8168_mdio_write(tp, 0x06, 0xf72c); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xf4fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2600); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2109); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xf4ac); - rtl8168_mdio_write(tp, 0x06, 0x2003); - rtl8168_mdio_write(tp, 0x06, 0x0222); - rtl8168_mdio_write(tp, 0x06, 0x7de0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x09e0); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x1408); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2309); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xf4ac); - rtl8168_mdio_write(tp, 0x06, 0x2203); - rtl8168_mdio_write(tp, 0x06, 0x0213); - rtl8168_mdio_write(tp, 0x06, 0x07e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x09e0); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xac23); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x8289); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2602); - rtl8168_mdio_write(tp, 0x06, 0xf628); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x210a); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0xecf6); - rtl8168_mdio_write(tp, 0x06, 0x27a0); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0xf629); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2008); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xe8ad); - rtl8168_mdio_write(tp, 0x06, 0x2102); - rtl8168_mdio_write(tp, 0x06, 0xf62a); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2308); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x20a0); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0xf62b); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2408); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xc2a0); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0xf62c); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xf4a1); - rtl8168_mdio_write(tp, 0x06, 0x0008); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf22); - rtl8168_mdio_write(tp, 0x06, 0x7a02); - rtl8168_mdio_write(tp, 0x06, 0x387d); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xc200); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x241e); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xc2a0); - rtl8168_mdio_write(tp, 0x06, 0x0005); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xb0ae); - rtl8168_mdio_write(tp, 0x06, 0xf5a0); - rtl8168_mdio_write(tp, 0x06, 0x0105); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xc0ae); - rtl8168_mdio_write(tp, 0x06, 0x0ba0); - rtl8168_mdio_write(tp, 0x06, 0x0205); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xcaae); - rtl8168_mdio_write(tp, 0x06, 0x03a0); - rtl8168_mdio_write(tp, 0x06, 0x0300); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xe1ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac2); - rtl8168_mdio_write(tp, 0x06, 0x01ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac9); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x8317); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8ac8); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xc91f); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x0611); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xc9ae); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac2); - rtl8168_mdio_write(tp, 0x06, 0x01fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfbbf); - rtl8168_mdio_write(tp, 0x06, 0x8ac4); - rtl8168_mdio_write(tp, 0x06, 0xef79); - rtl8168_mdio_write(tp, 0x06, 0xd200); - rtl8168_mdio_write(tp, 0x06, 0xd400); - rtl8168_mdio_write(tp, 0x06, 0x221e); - rtl8168_mdio_write(tp, 0x06, 0x02bf); - rtl8168_mdio_write(tp, 0x06, 0x3024); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7dbf); - rtl8168_mdio_write(tp, 0x06, 0x13ff); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x500d); - rtl8168_mdio_write(tp, 0x06, 0x4559); - rtl8168_mdio_write(tp, 0x06, 0x1fef); - rtl8168_mdio_write(tp, 0x06, 0x97dd); - rtl8168_mdio_write(tp, 0x06, 0xd308); - rtl8168_mdio_write(tp, 0x06, 0x1a93); - rtl8168_mdio_write(tp, 0x06, 0xdd12); - rtl8168_mdio_write(tp, 0x06, 0x17a2); - rtl8168_mdio_write(tp, 0x06, 0x04de); - rtl8168_mdio_write(tp, 0x06, 0xffef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfbee); - rtl8168_mdio_write(tp, 0x06, 0x8ac2); - rtl8168_mdio_write(tp, 0x06, 0x03d5); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x06, 0xbf8a); - rtl8168_mdio_write(tp, 0x06, 0xc4ef); - rtl8168_mdio_write(tp, 0x06, 0x79ef); - rtl8168_mdio_write(tp, 0x06, 0x45bf); - rtl8168_mdio_write(tp, 0x06, 0x3024); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7dbf); - rtl8168_mdio_write(tp, 0x06, 0x13ff); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x50ad); - rtl8168_mdio_write(tp, 0x06, 0x2702); - rtl8168_mdio_write(tp, 0x06, 0x78ff); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xca1b); - rtl8168_mdio_write(tp, 0x06, 0x01aa); - rtl8168_mdio_write(tp, 0x06, 0x2eef); - rtl8168_mdio_write(tp, 0x06, 0x97d9); - rtl8168_mdio_write(tp, 0x06, 0x7900); - rtl8168_mdio_write(tp, 0x06, 0x9e2b); - rtl8168_mdio_write(tp, 0x06, 0x81dd); - rtl8168_mdio_write(tp, 0x06, 0xbf85); - rtl8168_mdio_write(tp, 0x06, 0xad02); - rtl8168_mdio_write(tp, 0x06, 0x387d); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xef02); - rtl8168_mdio_write(tp, 0x06, 0x100c); - rtl8168_mdio_write(tp, 0x06, 0x11b0); - rtl8168_mdio_write(tp, 0x06, 0xfc0d); - rtl8168_mdio_write(tp, 0x06, 0x11bf); - rtl8168_mdio_write(tp, 0x06, 0x85aa); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7dd1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x85aa); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7dee); - rtl8168_mdio_write(tp, 0x06, 0x8ac2); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x0413); - rtl8168_mdio_write(tp, 0x06, 0xa38b); - rtl8168_mdio_write(tp, 0x06, 0xb4d3); - rtl8168_mdio_write(tp, 0x06, 0x8012); - rtl8168_mdio_write(tp, 0x06, 0x17a2); - rtl8168_mdio_write(tp, 0x06, 0x04ad); - rtl8168_mdio_write(tp, 0x06, 0xffef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x48e0); - rtl8168_mdio_write(tp, 0x06, 0x8a96); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0x977c); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x9e35); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x9600); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x9700); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xbee1); - rtl8168_mdio_write(tp, 0x06, 0x8abf); - rtl8168_mdio_write(tp, 0x06, 0xe28a); - rtl8168_mdio_write(tp, 0x06, 0xc0e3); - rtl8168_mdio_write(tp, 0x06, 0x8ac1); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x74ad); - rtl8168_mdio_write(tp, 0x06, 0x2012); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x9603); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x97b7); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xc000); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xc100); - rtl8168_mdio_write(tp, 0x06, 0xae11); - rtl8168_mdio_write(tp, 0x06, 0x15e6); - rtl8168_mdio_write(tp, 0x06, 0x8ac0); - rtl8168_mdio_write(tp, 0x06, 0xe78a); - rtl8168_mdio_write(tp, 0x06, 0xc1ae); - rtl8168_mdio_write(tp, 0x06, 0x08ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac0); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac1); - rtl8168_mdio_write(tp, 0x06, 0x00fd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xae20); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe001); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x32e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf720); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40bf); - rtl8168_mdio_write(tp, 0x06, 0x3230); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x50ad); - rtl8168_mdio_write(tp, 0x06, 0x2821); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x20e1); - rtl8168_mdio_write(tp, 0x06, 0xe021); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x18e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40ee); - rtl8168_mdio_write(tp, 0x06, 0x8b3b); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0x8a8a); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0x8be4); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0x01ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xface); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69fa); - rtl8168_mdio_write(tp, 0x06, 0xd401); - rtl8168_mdio_write(tp, 0x06, 0x55b4); - rtl8168_mdio_write(tp, 0x06, 0xfebf); - rtl8168_mdio_write(tp, 0x06, 0x1c1e); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x50ac); - rtl8168_mdio_write(tp, 0x06, 0x280b); - rtl8168_mdio_write(tp, 0x06, 0xbf1c); - rtl8168_mdio_write(tp, 0x06, 0x1b02); - rtl8168_mdio_write(tp, 0x06, 0x3850); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x49ae); - rtl8168_mdio_write(tp, 0x06, 0x64bf); - rtl8168_mdio_write(tp, 0x06, 0x1c1b); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x50ac); - rtl8168_mdio_write(tp, 0x06, 0x285b); - rtl8168_mdio_write(tp, 0x06, 0xd000); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0xcaac); - rtl8168_mdio_write(tp, 0x06, 0x2105); - rtl8168_mdio_write(tp, 0x06, 0xac22); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x4ebf); - rtl8168_mdio_write(tp, 0x06, 0xe0c4); - rtl8168_mdio_write(tp, 0x06, 0xbe85); - rtl8168_mdio_write(tp, 0x06, 0xf6d2); - rtl8168_mdio_write(tp, 0x06, 0x04d8); - rtl8168_mdio_write(tp, 0x06, 0x19d9); - rtl8168_mdio_write(tp, 0x06, 0x1907); - rtl8168_mdio_write(tp, 0x06, 0xdc19); - rtl8168_mdio_write(tp, 0x06, 0xdd19); - rtl8168_mdio_write(tp, 0x06, 0x0789); - rtl8168_mdio_write(tp, 0x06, 0x89ef); - rtl8168_mdio_write(tp, 0x06, 0x645e); - rtl8168_mdio_write(tp, 0x06, 0x07ff); - rtl8168_mdio_write(tp, 0x06, 0x0d65); - rtl8168_mdio_write(tp, 0x06, 0x5cf8); - rtl8168_mdio_write(tp, 0x06, 0x001e); - rtl8168_mdio_write(tp, 0x06, 0x46dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0x19b2); - rtl8168_mdio_write(tp, 0x06, 0xe2d4); - rtl8168_mdio_write(tp, 0x06, 0x0001); - rtl8168_mdio_write(tp, 0x06, 0xbf1c); - rtl8168_mdio_write(tp, 0x06, 0x1b02); - rtl8168_mdio_write(tp, 0x06, 0x387d); - rtl8168_mdio_write(tp, 0x06, 0xae1d); - rtl8168_mdio_write(tp, 0x06, 0xbee0); - rtl8168_mdio_write(tp, 0x06, 0xc4bf); - rtl8168_mdio_write(tp, 0x06, 0x85f6); - rtl8168_mdio_write(tp, 0x06, 0xd204); - rtl8168_mdio_write(tp, 0x06, 0xd819); - rtl8168_mdio_write(tp, 0x06, 0xd919); - rtl8168_mdio_write(tp, 0x06, 0x07dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0x1907); - rtl8168_mdio_write(tp, 0x06, 0xb2f4); - rtl8168_mdio_write(tp, 0x06, 0xd400); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x1c1b); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7dfe); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfec6); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc05); - rtl8168_mdio_write(tp, 0x06, 0xf9e2); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0xeb5a); - rtl8168_mdio_write(tp, 0x06, 0x070c); - rtl8168_mdio_write(tp, 0x06, 0x031e); - rtl8168_mdio_write(tp, 0x06, 0x20e6); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe7e0); - rtl8168_mdio_write(tp, 0x06, 0xebe0); - rtl8168_mdio_write(tp, 0x06, 0xe0fc); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xfdfd); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0x8b80); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x22bf); - rtl8168_mdio_write(tp, 0x06, 0x4616); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x50e0); - rtl8168_mdio_write(tp, 0x06, 0x8b44); - rtl8168_mdio_write(tp, 0x06, 0x1f01); - rtl8168_mdio_write(tp, 0x06, 0x9e15); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x44ad); - rtl8168_mdio_write(tp, 0x06, 0x2907); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x04d1); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0x02d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x85b0); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7def); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x30e0); - rtl8168_mdio_write(tp, 0x06, 0xe036); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x37e1); - rtl8168_mdio_write(tp, 0x06, 0x8b3f); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e23); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x3fac); - rtl8168_mdio_write(tp, 0x06, 0x200b); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x0dac); - rtl8168_mdio_write(tp, 0x06, 0x250f); - rtl8168_mdio_write(tp, 0x06, 0xac27); - rtl8168_mdio_write(tp, 0x06, 0x11ae); - rtl8168_mdio_write(tp, 0x06, 0x1202); - rtl8168_mdio_write(tp, 0x06, 0x2c47); - rtl8168_mdio_write(tp, 0x06, 0xae0d); - rtl8168_mdio_write(tp, 0x06, 0x0285); - rtl8168_mdio_write(tp, 0x06, 0x4fae); - rtl8168_mdio_write(tp, 0x06, 0x0802); - rtl8168_mdio_write(tp, 0x06, 0x2c69); - rtl8168_mdio_write(tp, 0x06, 0xae03); - rtl8168_mdio_write(tp, 0x06, 0x022c); - rtl8168_mdio_write(tp, 0x06, 0x7cfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x6902); - rtl8168_mdio_write(tp, 0x06, 0x856c); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x14e1); - rtl8168_mdio_write(tp, 0x06, 0xe015); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x08d1); - rtl8168_mdio_write(tp, 0x06, 0x1ebf); - rtl8168_mdio_write(tp, 0x06, 0x2cd9); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7def); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x2fd0); - rtl8168_mdio_write(tp, 0x06, 0x0b02); - rtl8168_mdio_write(tp, 0x06, 0x3682); - rtl8168_mdio_write(tp, 0x06, 0x5882); - rtl8168_mdio_write(tp, 0x06, 0x7882); - rtl8168_mdio_write(tp, 0x06, 0x9f24); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x32e1); - rtl8168_mdio_write(tp, 0x06, 0x8b33); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e1a); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x8b32); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x28e1); - rtl8168_mdio_write(tp, 0x06, 0xe029); - rtl8168_mdio_write(tp, 0x06, 0xf72c); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x28e5); - rtl8168_mdio_write(tp, 0x06, 0xe029); - rtl8168_mdio_write(tp, 0x06, 0xf62c); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x28e5); - rtl8168_mdio_write(tp, 0x06, 0xe029); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0x4077); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0x52e0); - rtl8168_mdio_write(tp, 0x06, 0xeed9); - rtl8168_mdio_write(tp, 0x06, 0xe04c); - rtl8168_mdio_write(tp, 0x06, 0xbbe0); - rtl8168_mdio_write(tp, 0x06, 0x2a00); - rtl8168_mdio_write(tp, 0x05, 0xe142); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp,0x06, gphy_val); - rtl8168_mdio_write(tp, 0x05, 0xe140); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp,0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp,0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val |= BIT_1; - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~BIT_2; - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x09, 0xA20F); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0003); - rtl8168_mdio_write(tp, 0x01, 0x328A); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); -} - -static void -rtl8168_set_phy_mcu_8168f_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val,i; - - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x1800); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val &= ~(BIT_12); - rtl8168_mdio_write(tp,0x15, gphy_val); - rtl8168_mdio_write(tp,0x00, 0x4800); - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x002f); - for (i = 0; i < 1000; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1c); - if (gphy_val & 0x0080) - break; - } - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x1800); - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x0023); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x18); - if (!(gphy_val & 0x0001)) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x0098); - rtl8168_mdio_write(tp, 0x19, 0x7c0b); - rtl8168_mdio_write(tp, 0x15, 0x0099); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00eb); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00f8); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00fe); - rtl8168_mdio_write(tp, 0x19, 0x6f0f); - rtl8168_mdio_write(tp, 0x15, 0x00db); - rtl8168_mdio_write(tp, 0x19, 0x6f09); - rtl8168_mdio_write(tp, 0x15, 0x00dc); - rtl8168_mdio_write(tp, 0x19, 0xaefd); - rtl8168_mdio_write(tp, 0x15, 0x00dd); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00de); - rtl8168_mdio_write(tp, 0x19, 0xc60b); - rtl8168_mdio_write(tp, 0x15, 0x00df); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00e0); - rtl8168_mdio_write(tp, 0x19, 0x30e1); - rtl8168_mdio_write(tp, 0x15, 0x020c); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x020e); - rtl8168_mdio_write(tp, 0x19, 0x9813); - rtl8168_mdio_write(tp, 0x15, 0x020f); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0210); - rtl8168_mdio_write(tp, 0x19, 0x930f); - rtl8168_mdio_write(tp, 0x15, 0x0211); - rtl8168_mdio_write(tp, 0x19, 0x9206); - rtl8168_mdio_write(tp, 0x15, 0x0212); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0213); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0214); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0215); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0216); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0217); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0218); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0219); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x021a); - rtl8168_mdio_write(tp, 0x19, 0x5540); - rtl8168_mdio_write(tp, 0x15, 0x021b); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x021c); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x021d); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x021e); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x021f); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0220); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0221); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x0222); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0223); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x0224); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0225); - rtl8168_mdio_write(tp, 0x19, 0x3231); - rtl8168_mdio_write(tp, 0x15, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x011b); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x2802); - rtl8168_mdio_write(tp, 0x06, 0x0135); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x4502); - rtl8168_mdio_write(tp, 0x06, 0x015f); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x6b02); - rtl8168_mdio_write(tp, 0x06, 0x80e5); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xbf8b); - rtl8168_mdio_write(tp, 0x06, 0x88ec); - rtl8168_mdio_write(tp, 0x06, 0x0019); - rtl8168_mdio_write(tp, 0x06, 0xa98b); - rtl8168_mdio_write(tp, 0x06, 0x90f9); - rtl8168_mdio_write(tp, 0x06, 0xeeff); - rtl8168_mdio_write(tp, 0x06, 0xf600); - rtl8168_mdio_write(tp, 0x06, 0xeeff); - rtl8168_mdio_write(tp, 0x06, 0xf7fe); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf81); - rtl8168_mdio_write(tp, 0x06, 0x9802); - rtl8168_mdio_write(tp, 0x06, 0x39f3); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf81); - rtl8168_mdio_write(tp, 0x06, 0x9b02); - rtl8168_mdio_write(tp, 0x06, 0x39f3); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8dad); - rtl8168_mdio_write(tp, 0x06, 0x2014); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8d00); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0x5a78); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x0902); - rtl8168_mdio_write(tp, 0x06, 0x05fc); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x8802); - rtl8168_mdio_write(tp, 0x06, 0x32dd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ac); - rtl8168_mdio_write(tp, 0x06, 0x261a); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ac); - rtl8168_mdio_write(tp, 0x06, 0x2114); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ac); - rtl8168_mdio_write(tp, 0x06, 0x200e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ac); - rtl8168_mdio_write(tp, 0x06, 0x2308); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ac); - rtl8168_mdio_write(tp, 0x06, 0x2402); - rtl8168_mdio_write(tp, 0x06, 0xae38); - rtl8168_mdio_write(tp, 0x06, 0x021a); - rtl8168_mdio_write(tp, 0x06, 0xd6ee); - rtl8168_mdio_write(tp, 0x06, 0xe41c); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0xe41d); - rtl8168_mdio_write(tp, 0x06, 0x04e2); - rtl8168_mdio_write(tp, 0x06, 0xe07c); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0x7de0); - rtl8168_mdio_write(tp, 0x06, 0xe038); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x39ad); - rtl8168_mdio_write(tp, 0x06, 0x2e1b); - rtl8168_mdio_write(tp, 0x06, 0xad39); - rtl8168_mdio_write(tp, 0x06, 0x0dd1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x22c8); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xf302); - rtl8168_mdio_write(tp, 0x06, 0x21f0); - rtl8168_mdio_write(tp, 0x06, 0xae0b); - rtl8168_mdio_write(tp, 0x06, 0xac38); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x0602); - rtl8168_mdio_write(tp, 0x06, 0x222d); - rtl8168_mdio_write(tp, 0x06, 0x0222); - rtl8168_mdio_write(tp, 0x06, 0x7202); - rtl8168_mdio_write(tp, 0x06, 0x1ae7); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x201a); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x2afe); - rtl8168_mdio_write(tp, 0x06, 0x022c); - rtl8168_mdio_write(tp, 0x06, 0x5c02); - rtl8168_mdio_write(tp, 0x06, 0x03c5); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x6702); - rtl8168_mdio_write(tp, 0x06, 0x2e4f); - rtl8168_mdio_write(tp, 0x06, 0x0204); - rtl8168_mdio_write(tp, 0x06, 0x8902); - rtl8168_mdio_write(tp, 0x06, 0x2f7a); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x210b); - rtl8168_mdio_write(tp, 0x06, 0xf621); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x0445); - rtl8168_mdio_write(tp, 0x06, 0x021c); - rtl8168_mdio_write(tp, 0x06, 0xb8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x22e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0235); - rtl8168_mdio_write(tp, 0x06, 0xd4e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad23); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x23e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0231); - rtl8168_mdio_write(tp, 0x06, 0xc8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x24e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2505); - rtl8168_mdio_write(tp, 0x06, 0xf625); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x26e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x022d); - rtl8168_mdio_write(tp, 0x06, 0x6ae0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x27e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x8bfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0x8b80); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x22bf); - rtl8168_mdio_write(tp, 0x06, 0x479a); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xc6e0); - rtl8168_mdio_write(tp, 0x06, 0x8b44); - rtl8168_mdio_write(tp, 0x06, 0x1f01); - rtl8168_mdio_write(tp, 0x06, 0x9e15); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x44ad); - rtl8168_mdio_write(tp, 0x06, 0x2907); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x04d1); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0x02d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x819e); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xf3ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0x4077); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xbbe0); - rtl8168_mdio_write(tp, 0x06, 0x2a00); - rtl8168_mdio_write(tp, 0x05, 0xe142); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x05, 0xe140); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp,0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val |= BIT_1; - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~BIT_2; - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); -} - -static void -rtl8168_set_phy_mcu_8411_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val,i; - - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x1800); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val &= ~(BIT_12); - rtl8168_mdio_write(tp,0x15, gphy_val); - rtl8168_mdio_write(tp,0x00, 0x4800); - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x002f); - for (i = 0; i < 1000; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1c); - if (gphy_val & 0x0080) - break; - } - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x1800); - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x0023); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x18); - if (!(gphy_val & 0x0001)) - break; - } - rtl8168_mdio_write(tp,0x1f, 0x0005); - rtl8168_mdio_write(tp,0x05, 0xfff6); - rtl8168_mdio_write(tp,0x06, 0x0080); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x0098); - rtl8168_mdio_write(tp, 0x19, 0x7c0b); - rtl8168_mdio_write(tp, 0x15, 0x0099); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00eb); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00f8); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00fe); - rtl8168_mdio_write(tp, 0x19, 0x6f0f); - rtl8168_mdio_write(tp, 0x15, 0x00db); - rtl8168_mdio_write(tp, 0x19, 0x6f09); - rtl8168_mdio_write(tp, 0x15, 0x00dc); - rtl8168_mdio_write(tp, 0x19, 0xaefd); - rtl8168_mdio_write(tp, 0x15, 0x00dd); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00de); - rtl8168_mdio_write(tp, 0x19, 0xc60b); - rtl8168_mdio_write(tp, 0x15, 0x00df); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00e0); - rtl8168_mdio_write(tp, 0x19, 0x30e1); - rtl8168_mdio_write(tp, 0x15, 0x020c); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x020e); - rtl8168_mdio_write(tp, 0x19, 0x9813); - rtl8168_mdio_write(tp, 0x15, 0x020f); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0210); - rtl8168_mdio_write(tp, 0x19, 0x930f); - rtl8168_mdio_write(tp, 0x15, 0x0211); - rtl8168_mdio_write(tp, 0x19, 0x9206); - rtl8168_mdio_write(tp, 0x15, 0x0212); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0213); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0214); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0215); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0216); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0217); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0218); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0219); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x021a); - rtl8168_mdio_write(tp, 0x19, 0x5540); - rtl8168_mdio_write(tp, 0x15, 0x021b); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x021c); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x021d); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x021e); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x021f); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0220); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0221); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x0222); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0223); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x0224); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0225); - rtl8168_mdio_write(tp, 0x19, 0x3231); - rtl8168_mdio_write(tp, 0x15, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x011e); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x2b02); - rtl8168_mdio_write(tp, 0x06, 0x8077); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x4802); - rtl8168_mdio_write(tp, 0x06, 0x0162); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x9402); - rtl8168_mdio_write(tp, 0x06, 0x810e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xd481); - rtl8168_mdio_write(tp, 0x06, 0xd4e4); - rtl8168_mdio_write(tp, 0x06, 0x8b92); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x9302); - rtl8168_mdio_write(tp, 0x06, 0x2e5a); - rtl8168_mdio_write(tp, 0x06, 0xbf8b); - rtl8168_mdio_write(tp, 0x06, 0x88ec); - rtl8168_mdio_write(tp, 0x06, 0x0019); - rtl8168_mdio_write(tp, 0x06, 0xa98b); - rtl8168_mdio_write(tp, 0x06, 0x90f9); - rtl8168_mdio_write(tp, 0x06, 0xeeff); - rtl8168_mdio_write(tp, 0x06, 0xf600); - rtl8168_mdio_write(tp, 0x06, 0xeeff); - rtl8168_mdio_write(tp, 0x06, 0xf7fc); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf83); - rtl8168_mdio_write(tp, 0x06, 0x3c02); - rtl8168_mdio_write(tp, 0x06, 0x3a21); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf83); - rtl8168_mdio_write(tp, 0x06, 0x3f02); - rtl8168_mdio_write(tp, 0x06, 0x3a21); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8aad); - rtl8168_mdio_write(tp, 0x06, 0x2014); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8a00); - rtl8168_mdio_write(tp, 0x06, 0x0220); - rtl8168_mdio_write(tp, 0x06, 0x8be0); - rtl8168_mdio_write(tp, 0x06, 0xe426); - rtl8168_mdio_write(tp, 0x06, 0xe1e4); - rtl8168_mdio_write(tp, 0x06, 0x27ee); - rtl8168_mdio_write(tp, 0x06, 0xe426); - rtl8168_mdio_write(tp, 0x06, 0x23e5); - rtl8168_mdio_write(tp, 0x06, 0xe427); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x14ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0x8a5a); - rtl8168_mdio_write(tp, 0x06, 0x7803); - rtl8168_mdio_write(tp, 0x06, 0x9e09); - rtl8168_mdio_write(tp, 0x06, 0x0206); - rtl8168_mdio_write(tp, 0x06, 0x2802); - rtl8168_mdio_write(tp, 0x06, 0x80b1); - rtl8168_mdio_write(tp, 0x06, 0x0232); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac26); - rtl8168_mdio_write(tp, 0x06, 0x1ae0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x14e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xac20); - rtl8168_mdio_write(tp, 0x06, 0x0ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xac23); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xac24); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0x1b02); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x1c04); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x1d04); - rtl8168_mdio_write(tp, 0x06, 0xe2e0); - rtl8168_mdio_write(tp, 0x06, 0x7ce3); - rtl8168_mdio_write(tp, 0x06, 0xe07d); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x38e1); - rtl8168_mdio_write(tp, 0x06, 0xe039); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x1bad); - rtl8168_mdio_write(tp, 0x06, 0x390d); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf22); - rtl8168_mdio_write(tp, 0x06, 0xe802); - rtl8168_mdio_write(tp, 0x06, 0x3a21); - rtl8168_mdio_write(tp, 0x06, 0x0222); - rtl8168_mdio_write(tp, 0x06, 0x10ae); - rtl8168_mdio_write(tp, 0x06, 0x0bac); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0222); - rtl8168_mdio_write(tp, 0x06, 0x4d02); - rtl8168_mdio_write(tp, 0x06, 0x2292); - rtl8168_mdio_write(tp, 0x06, 0x021b); - rtl8168_mdio_write(tp, 0x06, 0x13fd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x1af6); - rtl8168_mdio_write(tp, 0x06, 0x20e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x022b); - rtl8168_mdio_write(tp, 0x06, 0x1e02); - rtl8168_mdio_write(tp, 0x06, 0x82ae); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0xc002); - rtl8168_mdio_write(tp, 0x06, 0x827d); - rtl8168_mdio_write(tp, 0x06, 0x022e); - rtl8168_mdio_write(tp, 0x06, 0x6f02); - rtl8168_mdio_write(tp, 0x06, 0x047b); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x9ae0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad21); - rtl8168_mdio_write(tp, 0x06, 0x0bf6); - rtl8168_mdio_write(tp, 0x06, 0x21e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x9002); - rtl8168_mdio_write(tp, 0x06, 0x1cd9); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2208); - rtl8168_mdio_write(tp, 0x06, 0xf622); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x35f4); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2308); - rtl8168_mdio_write(tp, 0x06, 0xf623); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x31e8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2405); - rtl8168_mdio_write(tp, 0x06, 0xf624); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x25e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2608); - rtl8168_mdio_write(tp, 0x06, 0xf626); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x2d8a); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2705); - rtl8168_mdio_write(tp, 0x06, 0xf627); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x0386); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe001); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x32e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf720); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40bf); - rtl8168_mdio_write(tp, 0x06, 0x32c1); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xf4ad); - rtl8168_mdio_write(tp, 0x06, 0x2821); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x20e1); - rtl8168_mdio_write(tp, 0x06, 0xe021); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x18e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40ee); - rtl8168_mdio_write(tp, 0x06, 0x8b3b); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0x8a8a); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0x8be4); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0x01ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xface); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69fa); - rtl8168_mdio_write(tp, 0x06, 0xd401); - rtl8168_mdio_write(tp, 0x06, 0x55b4); - rtl8168_mdio_write(tp, 0x06, 0xfebf); - rtl8168_mdio_write(tp, 0x06, 0x1c5e); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xf4ac); - rtl8168_mdio_write(tp, 0x06, 0x280b); - rtl8168_mdio_write(tp, 0x06, 0xbf1c); - rtl8168_mdio_write(tp, 0x06, 0x5b02); - rtl8168_mdio_write(tp, 0x06, 0x39f4); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x49ae); - rtl8168_mdio_write(tp, 0x06, 0x64bf); - rtl8168_mdio_write(tp, 0x06, 0x1c5b); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xf4ac); - rtl8168_mdio_write(tp, 0x06, 0x285b); - rtl8168_mdio_write(tp, 0x06, 0xd000); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x62ac); - rtl8168_mdio_write(tp, 0x06, 0x2105); - rtl8168_mdio_write(tp, 0x06, 0xac22); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x4ebf); - rtl8168_mdio_write(tp, 0x06, 0xe0c4); - rtl8168_mdio_write(tp, 0x06, 0xbe85); - rtl8168_mdio_write(tp, 0x06, 0xecd2); - rtl8168_mdio_write(tp, 0x06, 0x04d8); - rtl8168_mdio_write(tp, 0x06, 0x19d9); - rtl8168_mdio_write(tp, 0x06, 0x1907); - rtl8168_mdio_write(tp, 0x06, 0xdc19); - rtl8168_mdio_write(tp, 0x06, 0xdd19); - rtl8168_mdio_write(tp, 0x06, 0x0789); - rtl8168_mdio_write(tp, 0x06, 0x89ef); - rtl8168_mdio_write(tp, 0x06, 0x645e); - rtl8168_mdio_write(tp, 0x06, 0x07ff); - rtl8168_mdio_write(tp, 0x06, 0x0d65); - rtl8168_mdio_write(tp, 0x06, 0x5cf8); - rtl8168_mdio_write(tp, 0x06, 0x001e); - rtl8168_mdio_write(tp, 0x06, 0x46dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0x19b2); - rtl8168_mdio_write(tp, 0x06, 0xe2d4); - rtl8168_mdio_write(tp, 0x06, 0x0001); - rtl8168_mdio_write(tp, 0x06, 0xbf1c); - rtl8168_mdio_write(tp, 0x06, 0x5b02); - rtl8168_mdio_write(tp, 0x06, 0x3a21); - rtl8168_mdio_write(tp, 0x06, 0xae1d); - rtl8168_mdio_write(tp, 0x06, 0xbee0); - rtl8168_mdio_write(tp, 0x06, 0xc4bf); - rtl8168_mdio_write(tp, 0x06, 0x85ec); - rtl8168_mdio_write(tp, 0x06, 0xd204); - rtl8168_mdio_write(tp, 0x06, 0xd819); - rtl8168_mdio_write(tp, 0x06, 0xd919); - rtl8168_mdio_write(tp, 0x06, 0x07dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0x1907); - rtl8168_mdio_write(tp, 0x06, 0xb2f4); - rtl8168_mdio_write(tp, 0x06, 0xd400); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x1c5b); - rtl8168_mdio_write(tp, 0x06, 0x023a); - rtl8168_mdio_write(tp, 0x06, 0x21fe); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfec6); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc05); - rtl8168_mdio_write(tp, 0x06, 0xf9e2); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0xeb5a); - rtl8168_mdio_write(tp, 0x06, 0x070c); - rtl8168_mdio_write(tp, 0x06, 0x031e); - rtl8168_mdio_write(tp, 0x06, 0x20e6); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe7e0); - rtl8168_mdio_write(tp, 0x06, 0xebe0); - rtl8168_mdio_write(tp, 0x06, 0xe0fc); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xfdfd); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0x8b80); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x22bf); - rtl8168_mdio_write(tp, 0x06, 0x47ba); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xf4e0); - rtl8168_mdio_write(tp, 0x06, 0x8b44); - rtl8168_mdio_write(tp, 0x06, 0x1f01); - rtl8168_mdio_write(tp, 0x06, 0x9e15); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x44ad); - rtl8168_mdio_write(tp, 0x06, 0x2907); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x04d1); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0x02d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8342); - rtl8168_mdio_write(tp, 0x06, 0x023a); - rtl8168_mdio_write(tp, 0x06, 0x21ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x30e0); - rtl8168_mdio_write(tp, 0x06, 0xe036); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x37e1); - rtl8168_mdio_write(tp, 0x06, 0x8b3f); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e23); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x3fac); - rtl8168_mdio_write(tp, 0x06, 0x200b); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x0dac); - rtl8168_mdio_write(tp, 0x06, 0x250f); - rtl8168_mdio_write(tp, 0x06, 0xac27); - rtl8168_mdio_write(tp, 0x06, 0x11ae); - rtl8168_mdio_write(tp, 0x06, 0x1202); - rtl8168_mdio_write(tp, 0x06, 0x2cb5); - rtl8168_mdio_write(tp, 0x06, 0xae0d); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xe7ae); - rtl8168_mdio_write(tp, 0x06, 0x0802); - rtl8168_mdio_write(tp, 0x06, 0x2cd7); - rtl8168_mdio_write(tp, 0x06, 0xae03); - rtl8168_mdio_write(tp, 0x06, 0x022c); - rtl8168_mdio_write(tp, 0x06, 0xeafc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x6902); - rtl8168_mdio_write(tp, 0x06, 0x8304); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x14e1); - rtl8168_mdio_write(tp, 0x06, 0xe015); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x08d1); - rtl8168_mdio_write(tp, 0x06, 0x1ebf); - rtl8168_mdio_write(tp, 0x06, 0x2d47); - rtl8168_mdio_write(tp, 0x06, 0x023a); - rtl8168_mdio_write(tp, 0x06, 0x21ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x2fd0); - rtl8168_mdio_write(tp, 0x06, 0x0b02); - rtl8168_mdio_write(tp, 0x06, 0x3826); - rtl8168_mdio_write(tp, 0x06, 0x5882); - rtl8168_mdio_write(tp, 0x06, 0x7882); - rtl8168_mdio_write(tp, 0x06, 0x9f24); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x32e1); - rtl8168_mdio_write(tp, 0x06, 0x8b33); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e1a); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x8b32); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x28e1); - rtl8168_mdio_write(tp, 0x06, 0xe029); - rtl8168_mdio_write(tp, 0x06, 0xf72c); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x28e5); - rtl8168_mdio_write(tp, 0x06, 0xe029); - rtl8168_mdio_write(tp, 0x06, 0xf62c); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x28e5); - rtl8168_mdio_write(tp, 0x06, 0xe029); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0x4077); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xbbe0); - rtl8168_mdio_write(tp, 0x06, 0x2a00); - rtl8168_mdio_write(tp, 0x05, 0xe142); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp,0x06, gphy_val); - rtl8168_mdio_write(tp, 0x05, 0xe140); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp,0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp,0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val |= BIT_1; - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~BIT_2; - rtl8168_mdio_write(tp,0x17, gphy_val); - rtl8168_mdio_write(tp,0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x09, 0xA20F); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0003); - rtl8168_mdio_write(tp, 0x01, 0x328A); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x9200); -} - -static void -rtl8168_set_phy_mcu_8168g_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val; - - rtl8168_set_phy_mcu_patch_request(tp); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8146); - rtl8168_mdio_write(tp, 0x14, 0x2300); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0210); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0290); - rtl8168_mdio_write(tp, 0x13, 0xA012); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xA014); - rtl8168_mdio_write(tp, 0x14, 0x2c04); - rtl8168_mdio_write(tp, 0x14, 0x2c0c); - rtl8168_mdio_write(tp, 0x14, 0x2c6c); - rtl8168_mdio_write(tp, 0x14, 0x2d0d); - rtl8168_mdio_write(tp, 0x14, 0x31ce); - rtl8168_mdio_write(tp, 0x14, 0x506d); - rtl8168_mdio_write(tp, 0x14, 0xd708); - rtl8168_mdio_write(tp, 0x14, 0x3108); - rtl8168_mdio_write(tp, 0x14, 0x106d); - rtl8168_mdio_write(tp, 0x14, 0x1560); - rtl8168_mdio_write(tp, 0x14, 0x15a9); - rtl8168_mdio_write(tp, 0x14, 0x206e); - rtl8168_mdio_write(tp, 0x14, 0x175b); - rtl8168_mdio_write(tp, 0x14, 0x6062); - rtl8168_mdio_write(tp, 0x14, 0xd700); - rtl8168_mdio_write(tp, 0x14, 0x5fae); - rtl8168_mdio_write(tp, 0x14, 0xd708); - rtl8168_mdio_write(tp, 0x14, 0x3107); - rtl8168_mdio_write(tp, 0x14, 0x4c1e); - rtl8168_mdio_write(tp, 0x14, 0x4169); - rtl8168_mdio_write(tp, 0x14, 0x316a); - rtl8168_mdio_write(tp, 0x14, 0x0c19); - rtl8168_mdio_write(tp, 0x14, 0x31aa); - rtl8168_mdio_write(tp, 0x14, 0x0c19); - rtl8168_mdio_write(tp, 0x14, 0x2c1b); - rtl8168_mdio_write(tp, 0x14, 0x5e62); - rtl8168_mdio_write(tp, 0x14, 0x26b5); - rtl8168_mdio_write(tp, 0x14, 0x31ab); - rtl8168_mdio_write(tp, 0x14, 0x5c1e); - rtl8168_mdio_write(tp, 0x14, 0x2c0c); - rtl8168_mdio_write(tp, 0x14, 0xc040); - rtl8168_mdio_write(tp, 0x14, 0x8808); - rtl8168_mdio_write(tp, 0x14, 0xc520); - rtl8168_mdio_write(tp, 0x14, 0xc421); - rtl8168_mdio_write(tp, 0x14, 0xd05a); - rtl8168_mdio_write(tp, 0x14, 0xd19a); - rtl8168_mdio_write(tp, 0x14, 0xd709); - rtl8168_mdio_write(tp, 0x14, 0x608f); - rtl8168_mdio_write(tp, 0x14, 0xd06b); - rtl8168_mdio_write(tp, 0x14, 0xd18a); - rtl8168_mdio_write(tp, 0x14, 0x2c2c); - rtl8168_mdio_write(tp, 0x14, 0xd0be); - rtl8168_mdio_write(tp, 0x14, 0xd188); - rtl8168_mdio_write(tp, 0x14, 0x2c2c); - rtl8168_mdio_write(tp, 0x14, 0xd708); - rtl8168_mdio_write(tp, 0x14, 0x4072); - rtl8168_mdio_write(tp, 0x14, 0xc104); - rtl8168_mdio_write(tp, 0x14, 0x2c3e); - rtl8168_mdio_write(tp, 0x14, 0x4076); - rtl8168_mdio_write(tp, 0x14, 0xc110); - rtl8168_mdio_write(tp, 0x14, 0x2c3e); - rtl8168_mdio_write(tp, 0x14, 0x4071); - rtl8168_mdio_write(tp, 0x14, 0xc102); - rtl8168_mdio_write(tp, 0x14, 0x2c3e); - rtl8168_mdio_write(tp, 0x14, 0x4070); - rtl8168_mdio_write(tp, 0x14, 0xc101); - rtl8168_mdio_write(tp, 0x14, 0x2c3e); - rtl8168_mdio_write(tp, 0x14, 0x175b); - rtl8168_mdio_write(tp, 0x14, 0xd709); - rtl8168_mdio_write(tp, 0x14, 0x3390); - rtl8168_mdio_write(tp, 0x14, 0x5c39); - rtl8168_mdio_write(tp, 0x14, 0x2c4e); - rtl8168_mdio_write(tp, 0x14, 0x175b); - rtl8168_mdio_write(tp, 0x14, 0xd708); - rtl8168_mdio_write(tp, 0x14, 0x6193); - rtl8168_mdio_write(tp, 0x14, 0xd709); - rtl8168_mdio_write(tp, 0x14, 0x5f9d); - rtl8168_mdio_write(tp, 0x14, 0x408b); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x6042); - rtl8168_mdio_write(tp, 0x14, 0xb401); - rtl8168_mdio_write(tp, 0x14, 0x175b); - rtl8168_mdio_write(tp, 0x14, 0xd708); - rtl8168_mdio_write(tp, 0x14, 0x6073); - rtl8168_mdio_write(tp, 0x14, 0x5fbc); - rtl8168_mdio_write(tp, 0x14, 0x2c4d); - rtl8168_mdio_write(tp, 0x14, 0x26ed); - rtl8168_mdio_write(tp, 0x14, 0xb280); - rtl8168_mdio_write(tp, 0x14, 0xa841); - rtl8168_mdio_write(tp, 0x14, 0x9420); - rtl8168_mdio_write(tp, 0x14, 0x8710); - rtl8168_mdio_write(tp, 0x14, 0xd709); - rtl8168_mdio_write(tp, 0x14, 0x42ec); - rtl8168_mdio_write(tp, 0x14, 0x606d); - rtl8168_mdio_write(tp, 0x14, 0xd207); - rtl8168_mdio_write(tp, 0x14, 0x2c57); - rtl8168_mdio_write(tp, 0x14, 0xd203); - rtl8168_mdio_write(tp, 0x14, 0x33ff); - rtl8168_mdio_write(tp, 0x14, 0x563b); - rtl8168_mdio_write(tp, 0x14, 0x3275); - rtl8168_mdio_write(tp, 0x14, 0x7c5e); - rtl8168_mdio_write(tp, 0x14, 0xb240); - rtl8168_mdio_write(tp, 0x14, 0xb402); - rtl8168_mdio_write(tp, 0x14, 0x263b); - rtl8168_mdio_write(tp, 0x14, 0x6096); - rtl8168_mdio_write(tp, 0x14, 0xb240); - rtl8168_mdio_write(tp, 0x14, 0xb406); - rtl8168_mdio_write(tp, 0x14, 0x263b); - rtl8168_mdio_write(tp, 0x14, 0x31d7); - rtl8168_mdio_write(tp, 0x14, 0x7c67); - rtl8168_mdio_write(tp, 0x14, 0xb240); - rtl8168_mdio_write(tp, 0x14, 0xb40e); - rtl8168_mdio_write(tp, 0x14, 0x263b); - rtl8168_mdio_write(tp, 0x14, 0xb410); - rtl8168_mdio_write(tp, 0x14, 0x8802); - rtl8168_mdio_write(tp, 0x14, 0xb240); - rtl8168_mdio_write(tp, 0x14, 0x940e); - rtl8168_mdio_write(tp, 0x14, 0x263b); - rtl8168_mdio_write(tp, 0x14, 0xba04); - rtl8168_mdio_write(tp, 0x14, 0x1cd6); - rtl8168_mdio_write(tp, 0x14, 0xa902); - rtl8168_mdio_write(tp, 0x14, 0xd711); - rtl8168_mdio_write(tp, 0x14, 0x4045); - rtl8168_mdio_write(tp, 0x14, 0xa980); - rtl8168_mdio_write(tp, 0x14, 0x3003); - rtl8168_mdio_write(tp, 0x14, 0x59b1); - rtl8168_mdio_write(tp, 0x14, 0xa540); - rtl8168_mdio_write(tp, 0x14, 0xa601); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4043); - rtl8168_mdio_write(tp, 0x14, 0xa910); - rtl8168_mdio_write(tp, 0x14, 0xd711); - rtl8168_mdio_write(tp, 0x14, 0x60a0); - rtl8168_mdio_write(tp, 0x14, 0xca33); - rtl8168_mdio_write(tp, 0x14, 0xcb33); - rtl8168_mdio_write(tp, 0x14, 0xa941); - rtl8168_mdio_write(tp, 0x14, 0x2c82); - rtl8168_mdio_write(tp, 0x14, 0xcaff); - rtl8168_mdio_write(tp, 0x14, 0xcbff); - rtl8168_mdio_write(tp, 0x14, 0xa921); - rtl8168_mdio_write(tp, 0x14, 0xce02); - rtl8168_mdio_write(tp, 0x14, 0xe070); - rtl8168_mdio_write(tp, 0x14, 0x0f10); - rtl8168_mdio_write(tp, 0x14, 0xaf01); - rtl8168_mdio_write(tp, 0x14, 0x8f01); - rtl8168_mdio_write(tp, 0x14, 0x1766); - rtl8168_mdio_write(tp, 0x14, 0x8e02); - rtl8168_mdio_write(tp, 0x14, 0x1787); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x609c); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fa4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0x1ce9); - rtl8168_mdio_write(tp, 0x14, 0xce04); - rtl8168_mdio_write(tp, 0x14, 0xe070); - rtl8168_mdio_write(tp, 0x14, 0x0f20); - rtl8168_mdio_write(tp, 0x14, 0xaf01); - rtl8168_mdio_write(tp, 0x14, 0x8f01); - rtl8168_mdio_write(tp, 0x14, 0x1766); - rtl8168_mdio_write(tp, 0x14, 0x8e04); - rtl8168_mdio_write(tp, 0x14, 0x6044); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0xa520); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4043); - rtl8168_mdio_write(tp, 0x14, 0x2cc1); - rtl8168_mdio_write(tp, 0x14, 0xe00f); - rtl8168_mdio_write(tp, 0x14, 0x0501); - rtl8168_mdio_write(tp, 0x14, 0x1cef); - rtl8168_mdio_write(tp, 0x14, 0xb801); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x4060); - rtl8168_mdio_write(tp, 0x14, 0x7fc4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0x1cf5); - rtl8168_mdio_write(tp, 0x14, 0xe00f); - rtl8168_mdio_write(tp, 0x14, 0x0502); - rtl8168_mdio_write(tp, 0x14, 0x1cef); - rtl8168_mdio_write(tp, 0x14, 0xb802); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x4061); - rtl8168_mdio_write(tp, 0x14, 0x7fc4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0x1cf5); - rtl8168_mdio_write(tp, 0x14, 0xe00f); - rtl8168_mdio_write(tp, 0x14, 0x0504); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6099); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fa4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0xc17f); - rtl8168_mdio_write(tp, 0x14, 0xc200); - rtl8168_mdio_write(tp, 0x14, 0xc43f); - rtl8168_mdio_write(tp, 0x14, 0xcc03); - rtl8168_mdio_write(tp, 0x14, 0xa701); - rtl8168_mdio_write(tp, 0x14, 0xa510); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4018); - rtl8168_mdio_write(tp, 0x14, 0x9910); - rtl8168_mdio_write(tp, 0x14, 0x8510); - rtl8168_mdio_write(tp, 0x14, 0x2860); - rtl8168_mdio_write(tp, 0x14, 0xe00f); - rtl8168_mdio_write(tp, 0x14, 0x0504); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6099); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fa4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0xa608); - rtl8168_mdio_write(tp, 0x14, 0xc17d); - rtl8168_mdio_write(tp, 0x14, 0xc200); - rtl8168_mdio_write(tp, 0x14, 0xc43f); - rtl8168_mdio_write(tp, 0x14, 0xcc03); - rtl8168_mdio_write(tp, 0x14, 0xa701); - rtl8168_mdio_write(tp, 0x14, 0xa510); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4018); - rtl8168_mdio_write(tp, 0x14, 0x9910); - rtl8168_mdio_write(tp, 0x14, 0x8510); - rtl8168_mdio_write(tp, 0x14, 0x2926); - rtl8168_mdio_write(tp, 0x14, 0x1792); - rtl8168_mdio_write(tp, 0x14, 0x27db); - rtl8168_mdio_write(tp, 0x14, 0xc000); - rtl8168_mdio_write(tp, 0x14, 0xc100); - rtl8168_mdio_write(tp, 0x14, 0xc200); - rtl8168_mdio_write(tp, 0x14, 0xc300); - rtl8168_mdio_write(tp, 0x14, 0xc400); - rtl8168_mdio_write(tp, 0x14, 0xc500); - rtl8168_mdio_write(tp, 0x14, 0xc600); - rtl8168_mdio_write(tp, 0x14, 0xc7c1); - rtl8168_mdio_write(tp, 0x14, 0xc800); - rtl8168_mdio_write(tp, 0x14, 0xcc00); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xca0f); - rtl8168_mdio_write(tp, 0x14, 0xcbff); - rtl8168_mdio_write(tp, 0x14, 0xa901); - rtl8168_mdio_write(tp, 0x14, 0x8902); - rtl8168_mdio_write(tp, 0x14, 0xc900); - rtl8168_mdio_write(tp, 0x14, 0xca00); - rtl8168_mdio_write(tp, 0x14, 0xcb00); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xb804); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x6044); - rtl8168_mdio_write(tp, 0x14, 0x9804); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6099); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fa4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xa510); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6098); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fa4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0x8510); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xd711); - rtl8168_mdio_write(tp, 0x14, 0x3003); - rtl8168_mdio_write(tp, 0x14, 0x1d01); - rtl8168_mdio_write(tp, 0x14, 0x2d0b); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x60be); - rtl8168_mdio_write(tp, 0x14, 0xe060); - rtl8168_mdio_write(tp, 0x14, 0x0920); - rtl8168_mdio_write(tp, 0x14, 0x1cd6); - rtl8168_mdio_write(tp, 0x14, 0x2c89); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x3063); - rtl8168_mdio_write(tp, 0x14, 0x1948); - rtl8168_mdio_write(tp, 0x14, 0x288a); - rtl8168_mdio_write(tp, 0x14, 0x1cd6); - rtl8168_mdio_write(tp, 0x14, 0x29bd); - rtl8168_mdio_write(tp, 0x14, 0xa802); - rtl8168_mdio_write(tp, 0x14, 0xa303); - rtl8168_mdio_write(tp, 0x14, 0x843f); - rtl8168_mdio_write(tp, 0x14, 0x81ff); - rtl8168_mdio_write(tp, 0x14, 0x8208); - rtl8168_mdio_write(tp, 0x14, 0xa201); - rtl8168_mdio_write(tp, 0x14, 0xc001); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x30a0); - rtl8168_mdio_write(tp, 0x14, 0x0d1c); - rtl8168_mdio_write(tp, 0x14, 0x30a0); - rtl8168_mdio_write(tp, 0x14, 0x3d13); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7f4c); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0xe003); - rtl8168_mdio_write(tp, 0x14, 0x0202); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6090); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fac); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0xa20c); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6091); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fac); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0x820e); - rtl8168_mdio_write(tp, 0x14, 0xa3e0); - rtl8168_mdio_write(tp, 0x14, 0xa520); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x609d); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fac); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0x8520); - rtl8168_mdio_write(tp, 0x14, 0x6703); - rtl8168_mdio_write(tp, 0x14, 0x2d34); - rtl8168_mdio_write(tp, 0x14, 0xa13e); - rtl8168_mdio_write(tp, 0x14, 0xc001); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0x6046); - rtl8168_mdio_write(tp, 0x14, 0x2d0d); - rtl8168_mdio_write(tp, 0x14, 0xa43f); - rtl8168_mdio_write(tp, 0x14, 0xa101); - rtl8168_mdio_write(tp, 0x14, 0xc020); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x3121); - rtl8168_mdio_write(tp, 0x14, 0x0d45); - rtl8168_mdio_write(tp, 0x14, 0x30c0); - rtl8168_mdio_write(tp, 0x14, 0x3d0d); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7f4c); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0xa540); - rtl8168_mdio_write(tp, 0x14, 0xc001); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4001); - rtl8168_mdio_write(tp, 0x14, 0xe00f); - rtl8168_mdio_write(tp, 0x14, 0x0501); - rtl8168_mdio_write(tp, 0x14, 0x1dac); - rtl8168_mdio_write(tp, 0x14, 0xc1c4); - rtl8168_mdio_write(tp, 0x14, 0xa268); - rtl8168_mdio_write(tp, 0x14, 0xa303); - rtl8168_mdio_write(tp, 0x14, 0x8420); - rtl8168_mdio_write(tp, 0x14, 0xe00f); - rtl8168_mdio_write(tp, 0x14, 0x0502); - rtl8168_mdio_write(tp, 0x14, 0x1dac); - rtl8168_mdio_write(tp, 0x14, 0xc002); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0x8208); - rtl8168_mdio_write(tp, 0x14, 0x8410); - rtl8168_mdio_write(tp, 0x14, 0xa121); - rtl8168_mdio_write(tp, 0x14, 0xc002); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0x8120); - rtl8168_mdio_write(tp, 0x14, 0x8180); - rtl8168_mdio_write(tp, 0x14, 0x1d97); - rtl8168_mdio_write(tp, 0x14, 0xa180); - rtl8168_mdio_write(tp, 0x14, 0xa13a); - rtl8168_mdio_write(tp, 0x14, 0x8240); - rtl8168_mdio_write(tp, 0x14, 0xa430); - rtl8168_mdio_write(tp, 0x14, 0xc010); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x30e1); - rtl8168_mdio_write(tp, 0x14, 0x0abc); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7f8c); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0xa480); - rtl8168_mdio_write(tp, 0x14, 0xa230); - rtl8168_mdio_write(tp, 0x14, 0xa303); - rtl8168_mdio_write(tp, 0x14, 0xc001); - rtl8168_mdio_write(tp, 0x14, 0xd70c); - rtl8168_mdio_write(tp, 0x14, 0x4124); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6120); - rtl8168_mdio_write(tp, 0x14, 0xd711); - rtl8168_mdio_write(tp, 0x14, 0x3128); - rtl8168_mdio_write(tp, 0x14, 0x3d76); - rtl8168_mdio_write(tp, 0x14, 0x2d70); - rtl8168_mdio_write(tp, 0x14, 0xa801); - rtl8168_mdio_write(tp, 0x14, 0x2d6c); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0xe018); - rtl8168_mdio_write(tp, 0x14, 0x0208); - rtl8168_mdio_write(tp, 0x14, 0xa1f8); - rtl8168_mdio_write(tp, 0x14, 0x8480); - rtl8168_mdio_write(tp, 0x14, 0xc004); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0x6046); - rtl8168_mdio_write(tp, 0x14, 0x2d0d); - rtl8168_mdio_write(tp, 0x14, 0xa43f); - rtl8168_mdio_write(tp, 0x14, 0xa105); - rtl8168_mdio_write(tp, 0x14, 0x8228); - rtl8168_mdio_write(tp, 0x14, 0xc004); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0x81bc); - rtl8168_mdio_write(tp, 0x14, 0xa220); - rtl8168_mdio_write(tp, 0x14, 0x1d97); - rtl8168_mdio_write(tp, 0x14, 0x8220); - rtl8168_mdio_write(tp, 0x14, 0xa1bc); - rtl8168_mdio_write(tp, 0x14, 0xc040); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x30e1); - rtl8168_mdio_write(tp, 0x14, 0x0abc); - rtl8168_mdio_write(tp, 0x14, 0x30e1); - rtl8168_mdio_write(tp, 0x14, 0x3d0d); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7f4c); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0xa802); - rtl8168_mdio_write(tp, 0x14, 0xd70c); - rtl8168_mdio_write(tp, 0x14, 0x4244); - rtl8168_mdio_write(tp, 0x14, 0xa301); - rtl8168_mdio_write(tp, 0x14, 0xc004); - rtl8168_mdio_write(tp, 0x14, 0xd711); - rtl8168_mdio_write(tp, 0x14, 0x3128); - rtl8168_mdio_write(tp, 0x14, 0x3da5); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x5f80); - rtl8168_mdio_write(tp, 0x14, 0xd711); - rtl8168_mdio_write(tp, 0x14, 0x3109); - rtl8168_mdio_write(tp, 0x14, 0x3da7); - rtl8168_mdio_write(tp, 0x14, 0x2dab); - rtl8168_mdio_write(tp, 0x14, 0xa801); - rtl8168_mdio_write(tp, 0x14, 0x2d9a); - rtl8168_mdio_write(tp, 0x14, 0xa802); - rtl8168_mdio_write(tp, 0x14, 0xc004); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xa510); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x609a); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fac); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0x8510); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x13, 0xA01A); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xA006); - rtl8168_mdio_write(tp, 0x14, 0x0ad6); - rtl8168_mdio_write(tp, 0x13, 0xA004); - rtl8168_mdio_write(tp, 0x14, 0x07f5); - rtl8168_mdio_write(tp, 0x13, 0xA002); - rtl8168_mdio_write(tp, 0x14, 0x06a9); - rtl8168_mdio_write(tp, 0x13, 0xA000); - rtl8168_mdio_write(tp, 0x14, 0xf069); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0210); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x83a0); - rtl8168_mdio_write(tp, 0x14, 0xaf83); - rtl8168_mdio_write(tp, 0x14, 0xacaf); - rtl8168_mdio_write(tp, 0x14, 0x83b8); - rtl8168_mdio_write(tp, 0x14, 0xaf83); - rtl8168_mdio_write(tp, 0x14, 0xcdaf); - rtl8168_mdio_write(tp, 0x14, 0x83d3); - rtl8168_mdio_write(tp, 0x14, 0x0204); - rtl8168_mdio_write(tp, 0x14, 0x9a02); - rtl8168_mdio_write(tp, 0x14, 0x09a9); - rtl8168_mdio_write(tp, 0x14, 0x0284); - rtl8168_mdio_write(tp, 0x14, 0x61af); - rtl8168_mdio_write(tp, 0x14, 0x02fc); - rtl8168_mdio_write(tp, 0x14, 0xad20); - rtl8168_mdio_write(tp, 0x14, 0x0302); - rtl8168_mdio_write(tp, 0x14, 0x867c); - rtl8168_mdio_write(tp, 0x14, 0xad21); - rtl8168_mdio_write(tp, 0x14, 0x0302); - rtl8168_mdio_write(tp, 0x14, 0x85c9); - rtl8168_mdio_write(tp, 0x14, 0xad22); - rtl8168_mdio_write(tp, 0x14, 0x0302); - rtl8168_mdio_write(tp, 0x14, 0x1bc0); - rtl8168_mdio_write(tp, 0x14, 0xaf17); - rtl8168_mdio_write(tp, 0x14, 0xe302); - rtl8168_mdio_write(tp, 0x14, 0x8703); - rtl8168_mdio_write(tp, 0x14, 0xaf18); - rtl8168_mdio_write(tp, 0x14, 0x6201); - rtl8168_mdio_write(tp, 0x14, 0x06e0); - rtl8168_mdio_write(tp, 0x14, 0x8148); - rtl8168_mdio_write(tp, 0x14, 0xaf3c); - rtl8168_mdio_write(tp, 0x14, 0x69f8); - rtl8168_mdio_write(tp, 0x14, 0xf9fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0x10f7); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0x131f); - rtl8168_mdio_write(tp, 0x14, 0xd104); - rtl8168_mdio_write(tp, 0x14, 0xbf87); - rtl8168_mdio_write(tp, 0x14, 0xf302); - rtl8168_mdio_write(tp, 0x14, 0x4259); - rtl8168_mdio_write(tp, 0x14, 0x0287); - rtl8168_mdio_write(tp, 0x14, 0x88bf); - rtl8168_mdio_write(tp, 0x14, 0x87cf); - rtl8168_mdio_write(tp, 0x14, 0xd7b8); - rtl8168_mdio_write(tp, 0x14, 0x22d0); - rtl8168_mdio_write(tp, 0x14, 0x0c02); - rtl8168_mdio_write(tp, 0x14, 0x4252); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xcda0); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xce8b); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xd1f5); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xd2a9); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xd30a); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xf010); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xf38f); - rtl8168_mdio_write(tp, 0x14, 0xee81); - rtl8168_mdio_write(tp, 0x14, 0x011e); - rtl8168_mdio_write(tp, 0x14, 0xee81); - rtl8168_mdio_write(tp, 0x14, 0x0b4a); - rtl8168_mdio_write(tp, 0x14, 0xee81); - rtl8168_mdio_write(tp, 0x14, 0x0c7c); - rtl8168_mdio_write(tp, 0x14, 0xee81); - rtl8168_mdio_write(tp, 0x14, 0x127f); - rtl8168_mdio_write(tp, 0x14, 0xd100); - rtl8168_mdio_write(tp, 0x14, 0x0210); - rtl8168_mdio_write(tp, 0x14, 0xb5ee); - rtl8168_mdio_write(tp, 0x14, 0x8088); - rtl8168_mdio_write(tp, 0x14, 0xa4ee); - rtl8168_mdio_write(tp, 0x14, 0x8089); - rtl8168_mdio_write(tp, 0x14, 0x44ee); - rtl8168_mdio_write(tp, 0x14, 0x809a); - rtl8168_mdio_write(tp, 0x14, 0xa4ee); - rtl8168_mdio_write(tp, 0x14, 0x809b); - rtl8168_mdio_write(tp, 0x14, 0x44ee); - rtl8168_mdio_write(tp, 0x14, 0x809c); - rtl8168_mdio_write(tp, 0x14, 0xa7ee); - rtl8168_mdio_write(tp, 0x14, 0x80a5); - rtl8168_mdio_write(tp, 0x14, 0xa7d2); - rtl8168_mdio_write(tp, 0x14, 0x0002); - rtl8168_mdio_write(tp, 0x14, 0x0e66); - rtl8168_mdio_write(tp, 0x14, 0x0285); - rtl8168_mdio_write(tp, 0x14, 0xc0ee); - rtl8168_mdio_write(tp, 0x14, 0x87fc); - rtl8168_mdio_write(tp, 0x14, 0x00e0); - rtl8168_mdio_write(tp, 0x14, 0x8245); - rtl8168_mdio_write(tp, 0x14, 0xf622); - rtl8168_mdio_write(tp, 0x14, 0xe482); - rtl8168_mdio_write(tp, 0x14, 0x45ef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfdfc); - rtl8168_mdio_write(tp, 0x14, 0x0402); - rtl8168_mdio_write(tp, 0x14, 0x847a); - rtl8168_mdio_write(tp, 0x14, 0x0284); - rtl8168_mdio_write(tp, 0x14, 0xb302); - rtl8168_mdio_write(tp, 0x14, 0x0cab); - rtl8168_mdio_write(tp, 0x14, 0x020c); - rtl8168_mdio_write(tp, 0x14, 0xc402); - rtl8168_mdio_write(tp, 0x14, 0x0cef); - rtl8168_mdio_write(tp, 0x14, 0x020d); - rtl8168_mdio_write(tp, 0x14, 0x0802); - rtl8168_mdio_write(tp, 0x14, 0x0d33); - rtl8168_mdio_write(tp, 0x14, 0x020c); - rtl8168_mdio_write(tp, 0x14, 0x3d04); - rtl8168_mdio_write(tp, 0x14, 0xf8fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xe182); - rtl8168_mdio_write(tp, 0x14, 0x2fac); - rtl8168_mdio_write(tp, 0x14, 0x291a); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x24ac); - rtl8168_mdio_write(tp, 0x14, 0x2102); - rtl8168_mdio_write(tp, 0x14, 0xae22); - rtl8168_mdio_write(tp, 0x14, 0x0210); - rtl8168_mdio_write(tp, 0x14, 0x57f6); - rtl8168_mdio_write(tp, 0x14, 0x21e4); - rtl8168_mdio_write(tp, 0x14, 0x8224); - rtl8168_mdio_write(tp, 0x14, 0xd101); - rtl8168_mdio_write(tp, 0x14, 0xbf44); - rtl8168_mdio_write(tp, 0x14, 0xd202); - rtl8168_mdio_write(tp, 0x14, 0x4259); - rtl8168_mdio_write(tp, 0x14, 0xae10); - rtl8168_mdio_write(tp, 0x14, 0x0212); - rtl8168_mdio_write(tp, 0x14, 0x4cf6); - rtl8168_mdio_write(tp, 0x14, 0x29e5); - rtl8168_mdio_write(tp, 0x14, 0x822f); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x24f6); - rtl8168_mdio_write(tp, 0x14, 0x21e4); - rtl8168_mdio_write(tp, 0x14, 0x8224); - rtl8168_mdio_write(tp, 0x14, 0xef96); - rtl8168_mdio_write(tp, 0x14, 0xfefc); - rtl8168_mdio_write(tp, 0x14, 0x04f8); - rtl8168_mdio_write(tp, 0x14, 0xe182); - rtl8168_mdio_write(tp, 0x14, 0x2fac); - rtl8168_mdio_write(tp, 0x14, 0x2a18); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x24ac); - rtl8168_mdio_write(tp, 0x14, 0x2202); - rtl8168_mdio_write(tp, 0x14, 0xae26); - rtl8168_mdio_write(tp, 0x14, 0x0284); - rtl8168_mdio_write(tp, 0x14, 0xf802); - rtl8168_mdio_write(tp, 0x14, 0x8565); - rtl8168_mdio_write(tp, 0x14, 0xd101); - rtl8168_mdio_write(tp, 0x14, 0xbf44); - rtl8168_mdio_write(tp, 0x14, 0xd502); - rtl8168_mdio_write(tp, 0x14, 0x4259); - rtl8168_mdio_write(tp, 0x14, 0xae0e); - rtl8168_mdio_write(tp, 0x14, 0x0284); - rtl8168_mdio_write(tp, 0x14, 0xea02); - rtl8168_mdio_write(tp, 0x14, 0x85a9); - rtl8168_mdio_write(tp, 0x14, 0xe182); - rtl8168_mdio_write(tp, 0x14, 0x2ff6); - rtl8168_mdio_write(tp, 0x14, 0x2ae5); - rtl8168_mdio_write(tp, 0x14, 0x822f); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x24f6); - rtl8168_mdio_write(tp, 0x14, 0x22e4); - rtl8168_mdio_write(tp, 0x14, 0x8224); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xf9e2); - rtl8168_mdio_write(tp, 0x14, 0x8011); - rtl8168_mdio_write(tp, 0x14, 0xad31); - rtl8168_mdio_write(tp, 0x14, 0x05d2); - rtl8168_mdio_write(tp, 0x14, 0x0002); - rtl8168_mdio_write(tp, 0x14, 0x0e66); - rtl8168_mdio_write(tp, 0x14, 0xfd04); - rtl8168_mdio_write(tp, 0x14, 0xf8f9); - rtl8168_mdio_write(tp, 0x14, 0xfaef); - rtl8168_mdio_write(tp, 0x14, 0x69e0); - rtl8168_mdio_write(tp, 0x14, 0x8011); - rtl8168_mdio_write(tp, 0x14, 0xad21); - rtl8168_mdio_write(tp, 0x14, 0x5cbf); - rtl8168_mdio_write(tp, 0x14, 0x43be); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97ac); - rtl8168_mdio_write(tp, 0x14, 0x281b); - rtl8168_mdio_write(tp, 0x14, 0xbf43); - rtl8168_mdio_write(tp, 0x14, 0xc102); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0xac28); - rtl8168_mdio_write(tp, 0x14, 0x12bf); - rtl8168_mdio_write(tp, 0x14, 0x43c7); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97ac); - rtl8168_mdio_write(tp, 0x14, 0x2804); - rtl8168_mdio_write(tp, 0x14, 0xd300); - rtl8168_mdio_write(tp, 0x14, 0xae07); - rtl8168_mdio_write(tp, 0x14, 0xd306); - rtl8168_mdio_write(tp, 0x14, 0xaf85); - rtl8168_mdio_write(tp, 0x14, 0x56d3); - rtl8168_mdio_write(tp, 0x14, 0x03e0); - rtl8168_mdio_write(tp, 0x14, 0x8011); - rtl8168_mdio_write(tp, 0x14, 0xad26); - rtl8168_mdio_write(tp, 0x14, 0x25bf); - rtl8168_mdio_write(tp, 0x14, 0x4559); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97e2); - rtl8168_mdio_write(tp, 0x14, 0x8073); - rtl8168_mdio_write(tp, 0x14, 0x0d21); - rtl8168_mdio_write(tp, 0x14, 0xf637); - rtl8168_mdio_write(tp, 0x14, 0x0d11); - rtl8168_mdio_write(tp, 0x14, 0xf62f); - rtl8168_mdio_write(tp, 0x14, 0x1b21); - rtl8168_mdio_write(tp, 0x14, 0xaa02); - rtl8168_mdio_write(tp, 0x14, 0xae10); - rtl8168_mdio_write(tp, 0x14, 0xe280); - rtl8168_mdio_write(tp, 0x14, 0x740d); - rtl8168_mdio_write(tp, 0x14, 0x21f6); - rtl8168_mdio_write(tp, 0x14, 0x371b); - rtl8168_mdio_write(tp, 0x14, 0x21aa); - rtl8168_mdio_write(tp, 0x14, 0x0313); - rtl8168_mdio_write(tp, 0x14, 0xae02); - rtl8168_mdio_write(tp, 0x14, 0x2b02); - rtl8168_mdio_write(tp, 0x14, 0x020e); - rtl8168_mdio_write(tp, 0x14, 0x5102); - rtl8168_mdio_write(tp, 0x14, 0x0e66); - rtl8168_mdio_write(tp, 0x14, 0x020f); - rtl8168_mdio_write(tp, 0x14, 0xa3ef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfdfc); - rtl8168_mdio_write(tp, 0x14, 0x04f8); - rtl8168_mdio_write(tp, 0x14, 0xf9fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xe080); - rtl8168_mdio_write(tp, 0x14, 0x12ad); - rtl8168_mdio_write(tp, 0x14, 0x2733); - rtl8168_mdio_write(tp, 0x14, 0xbf43); - rtl8168_mdio_write(tp, 0x14, 0xbe02); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0xac28); - rtl8168_mdio_write(tp, 0x14, 0x09bf); - rtl8168_mdio_write(tp, 0x14, 0x43c1); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97ad); - rtl8168_mdio_write(tp, 0x14, 0x2821); - rtl8168_mdio_write(tp, 0x14, 0xbf45); - rtl8168_mdio_write(tp, 0x14, 0x5902); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0xe387); - rtl8168_mdio_write(tp, 0x14, 0xffd2); - rtl8168_mdio_write(tp, 0x14, 0x001b); - rtl8168_mdio_write(tp, 0x14, 0x45ac); - rtl8168_mdio_write(tp, 0x14, 0x2711); - rtl8168_mdio_write(tp, 0x14, 0xe187); - rtl8168_mdio_write(tp, 0x14, 0xfebf); - rtl8168_mdio_write(tp, 0x14, 0x87e4); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x590d); - rtl8168_mdio_write(tp, 0x14, 0x11bf); - rtl8168_mdio_write(tp, 0x14, 0x87e7); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59ef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfdfc); - rtl8168_mdio_write(tp, 0x14, 0x04f8); - rtl8168_mdio_write(tp, 0x14, 0xfaef); - rtl8168_mdio_write(tp, 0x14, 0x69d1); - rtl8168_mdio_write(tp, 0x14, 0x00bf); - rtl8168_mdio_write(tp, 0x14, 0x87e4); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59bf); - rtl8168_mdio_write(tp, 0x14, 0x87e7); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59ef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xee87); - rtl8168_mdio_write(tp, 0x14, 0xff46); - rtl8168_mdio_write(tp, 0x14, 0xee87); - rtl8168_mdio_write(tp, 0x14, 0xfe01); - rtl8168_mdio_write(tp, 0x14, 0x04f8); - rtl8168_mdio_write(tp, 0x14, 0xfaef); - rtl8168_mdio_write(tp, 0x14, 0x69e0); - rtl8168_mdio_write(tp, 0x14, 0x8241); - rtl8168_mdio_write(tp, 0x14, 0xa000); - rtl8168_mdio_write(tp, 0x14, 0x0502); - rtl8168_mdio_write(tp, 0x14, 0x85eb); - rtl8168_mdio_write(tp, 0x14, 0xae0e); - rtl8168_mdio_write(tp, 0x14, 0xa001); - rtl8168_mdio_write(tp, 0x14, 0x0502); - rtl8168_mdio_write(tp, 0x14, 0x1a5a); - rtl8168_mdio_write(tp, 0x14, 0xae06); - rtl8168_mdio_write(tp, 0x14, 0xa002); - rtl8168_mdio_write(tp, 0x14, 0x0302); - rtl8168_mdio_write(tp, 0x14, 0x1ae6); - rtl8168_mdio_write(tp, 0x14, 0xef96); - rtl8168_mdio_write(tp, 0x14, 0xfefc); - rtl8168_mdio_write(tp, 0x14, 0x04f8); - rtl8168_mdio_write(tp, 0x14, 0xf9fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x29f6); - rtl8168_mdio_write(tp, 0x14, 0x21e4); - rtl8168_mdio_write(tp, 0x14, 0x8229); - rtl8168_mdio_write(tp, 0x14, 0xe080); - rtl8168_mdio_write(tp, 0x14, 0x10ac); - rtl8168_mdio_write(tp, 0x14, 0x2202); - rtl8168_mdio_write(tp, 0x14, 0xae76); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x27f7); - rtl8168_mdio_write(tp, 0x14, 0x21e4); - rtl8168_mdio_write(tp, 0x14, 0x8227); - rtl8168_mdio_write(tp, 0x14, 0xbf43); - rtl8168_mdio_write(tp, 0x14, 0x1302); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0xef21); - rtl8168_mdio_write(tp, 0x14, 0xbf43); - rtl8168_mdio_write(tp, 0x14, 0x1602); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0x0c11); - rtl8168_mdio_write(tp, 0x14, 0x1e21); - rtl8168_mdio_write(tp, 0x14, 0xbf43); - rtl8168_mdio_write(tp, 0x14, 0x1902); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0x0c12); - rtl8168_mdio_write(tp, 0x14, 0x1e21); - rtl8168_mdio_write(tp, 0x14, 0xe682); - rtl8168_mdio_write(tp, 0x14, 0x43a2); - rtl8168_mdio_write(tp, 0x14, 0x000a); - rtl8168_mdio_write(tp, 0x14, 0xe182); - rtl8168_mdio_write(tp, 0x14, 0x27f6); - rtl8168_mdio_write(tp, 0x14, 0x29e5); - rtl8168_mdio_write(tp, 0x14, 0x8227); - rtl8168_mdio_write(tp, 0x14, 0xae42); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x44f7); - rtl8168_mdio_write(tp, 0x14, 0x21e4); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x0246); - rtl8168_mdio_write(tp, 0x14, 0xaebf); - rtl8168_mdio_write(tp, 0x14, 0x4325); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97ef); - rtl8168_mdio_write(tp, 0x14, 0x21bf); - rtl8168_mdio_write(tp, 0x14, 0x431c); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x970c); - rtl8168_mdio_write(tp, 0x14, 0x121e); - rtl8168_mdio_write(tp, 0x14, 0x21bf); - rtl8168_mdio_write(tp, 0x14, 0x431f); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x970c); - rtl8168_mdio_write(tp, 0x14, 0x131e); - rtl8168_mdio_write(tp, 0x14, 0x21bf); - rtl8168_mdio_write(tp, 0x14, 0x4328); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x970c); - rtl8168_mdio_write(tp, 0x14, 0x141e); - rtl8168_mdio_write(tp, 0x14, 0x21bf); - rtl8168_mdio_write(tp, 0x14, 0x44b1); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x970c); - rtl8168_mdio_write(tp, 0x14, 0x161e); - rtl8168_mdio_write(tp, 0x14, 0x21e6); - rtl8168_mdio_write(tp, 0x14, 0x8242); - rtl8168_mdio_write(tp, 0x14, 0xee82); - rtl8168_mdio_write(tp, 0x14, 0x4101); - rtl8168_mdio_write(tp, 0x14, 0xef96); - rtl8168_mdio_write(tp, 0x14, 0xfefd); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xf8fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x46a0); - rtl8168_mdio_write(tp, 0x14, 0x0005); - rtl8168_mdio_write(tp, 0x14, 0x0286); - rtl8168_mdio_write(tp, 0x14, 0x96ae); - rtl8168_mdio_write(tp, 0x14, 0x06a0); - rtl8168_mdio_write(tp, 0x14, 0x0103); - rtl8168_mdio_write(tp, 0x14, 0x0219); - rtl8168_mdio_write(tp, 0x14, 0x19ef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xf8fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x29f6); - rtl8168_mdio_write(tp, 0x14, 0x20e4); - rtl8168_mdio_write(tp, 0x14, 0x8229); - rtl8168_mdio_write(tp, 0x14, 0xe080); - rtl8168_mdio_write(tp, 0x14, 0x10ac); - rtl8168_mdio_write(tp, 0x14, 0x2102); - rtl8168_mdio_write(tp, 0x14, 0xae54); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x27f7); - rtl8168_mdio_write(tp, 0x14, 0x20e4); - rtl8168_mdio_write(tp, 0x14, 0x8227); - rtl8168_mdio_write(tp, 0x14, 0xbf42); - rtl8168_mdio_write(tp, 0x14, 0xe602); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0xac28); - rtl8168_mdio_write(tp, 0x14, 0x22bf); - rtl8168_mdio_write(tp, 0x14, 0x430d); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97e5); - rtl8168_mdio_write(tp, 0x14, 0x8247); - rtl8168_mdio_write(tp, 0x14, 0xac28); - rtl8168_mdio_write(tp, 0x14, 0x20d1); - rtl8168_mdio_write(tp, 0x14, 0x03bf); - rtl8168_mdio_write(tp, 0x14, 0x4307); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59ee); - rtl8168_mdio_write(tp, 0x14, 0x8246); - rtl8168_mdio_write(tp, 0x14, 0x00e1); - rtl8168_mdio_write(tp, 0x14, 0x8227); - rtl8168_mdio_write(tp, 0x14, 0xf628); - rtl8168_mdio_write(tp, 0x14, 0xe582); - rtl8168_mdio_write(tp, 0x14, 0x27ae); - rtl8168_mdio_write(tp, 0x14, 0x21d1); - rtl8168_mdio_write(tp, 0x14, 0x04bf); - rtl8168_mdio_write(tp, 0x14, 0x4307); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59ae); - rtl8168_mdio_write(tp, 0x14, 0x08d1); - rtl8168_mdio_write(tp, 0x14, 0x05bf); - rtl8168_mdio_write(tp, 0x14, 0x4307); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59e0); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0xf720); - rtl8168_mdio_write(tp, 0x14, 0xe482); - rtl8168_mdio_write(tp, 0x14, 0x4402); - rtl8168_mdio_write(tp, 0x14, 0x46ae); - rtl8168_mdio_write(tp, 0x14, 0xee82); - rtl8168_mdio_write(tp, 0x14, 0x4601); - rtl8168_mdio_write(tp, 0x14, 0xef96); - rtl8168_mdio_write(tp, 0x14, 0xfefc); - rtl8168_mdio_write(tp, 0x14, 0x04f8); - rtl8168_mdio_write(tp, 0x14, 0xfaef); - rtl8168_mdio_write(tp, 0x14, 0x69e0); - rtl8168_mdio_write(tp, 0x14, 0x8013); - rtl8168_mdio_write(tp, 0x14, 0xad24); - rtl8168_mdio_write(tp, 0x14, 0x1cbf); - rtl8168_mdio_write(tp, 0x14, 0x87f0); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97ad); - rtl8168_mdio_write(tp, 0x14, 0x2813); - rtl8168_mdio_write(tp, 0x14, 0xe087); - rtl8168_mdio_write(tp, 0x14, 0xfca0); - rtl8168_mdio_write(tp, 0x14, 0x0005); - rtl8168_mdio_write(tp, 0x14, 0x0287); - rtl8168_mdio_write(tp, 0x14, 0x36ae); - rtl8168_mdio_write(tp, 0x14, 0x10a0); - rtl8168_mdio_write(tp, 0x14, 0x0105); - rtl8168_mdio_write(tp, 0x14, 0x0287); - rtl8168_mdio_write(tp, 0x14, 0x48ae); - rtl8168_mdio_write(tp, 0x14, 0x08e0); - rtl8168_mdio_write(tp, 0x14, 0x8230); - rtl8168_mdio_write(tp, 0x14, 0xf626); - rtl8168_mdio_write(tp, 0x14, 0xe482); - rtl8168_mdio_write(tp, 0x14, 0x30ef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xf8e0); - rtl8168_mdio_write(tp, 0x14, 0x8245); - rtl8168_mdio_write(tp, 0x14, 0xf722); - rtl8168_mdio_write(tp, 0x14, 0xe482); - rtl8168_mdio_write(tp, 0x14, 0x4502); - rtl8168_mdio_write(tp, 0x14, 0x46ae); - rtl8168_mdio_write(tp, 0x14, 0xee87); - rtl8168_mdio_write(tp, 0x14, 0xfc01); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xf8fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xfb02); - rtl8168_mdio_write(tp, 0x14, 0x46d3); - rtl8168_mdio_write(tp, 0x14, 0xad50); - rtl8168_mdio_write(tp, 0x14, 0x2fbf); - rtl8168_mdio_write(tp, 0x14, 0x87ed); - rtl8168_mdio_write(tp, 0x14, 0xd101); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59bf); - rtl8168_mdio_write(tp, 0x14, 0x87ed); - rtl8168_mdio_write(tp, 0x14, 0xd100); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59e0); - rtl8168_mdio_write(tp, 0x14, 0x8245); - rtl8168_mdio_write(tp, 0x14, 0xf622); - rtl8168_mdio_write(tp, 0x14, 0xe482); - rtl8168_mdio_write(tp, 0x14, 0x4502); - rtl8168_mdio_write(tp, 0x14, 0x46ae); - rtl8168_mdio_write(tp, 0x14, 0xd100); - rtl8168_mdio_write(tp, 0x14, 0xbf87); - rtl8168_mdio_write(tp, 0x14, 0xf002); - rtl8168_mdio_write(tp, 0x14, 0x4259); - rtl8168_mdio_write(tp, 0x14, 0xee87); - rtl8168_mdio_write(tp, 0x14, 0xfc00); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x30f6); - rtl8168_mdio_write(tp, 0x14, 0x26e4); - rtl8168_mdio_write(tp, 0x14, 0x8230); - rtl8168_mdio_write(tp, 0x14, 0xffef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xf8f9); - rtl8168_mdio_write(tp, 0x14, 0xface); - rtl8168_mdio_write(tp, 0x14, 0xfaef); - rtl8168_mdio_write(tp, 0x14, 0x69fb); - rtl8168_mdio_write(tp, 0x14, 0xbf87); - rtl8168_mdio_write(tp, 0x14, 0xb3d7); - rtl8168_mdio_write(tp, 0x14, 0x001c); - rtl8168_mdio_write(tp, 0x14, 0xd819); - rtl8168_mdio_write(tp, 0x14, 0xd919); - rtl8168_mdio_write(tp, 0x14, 0xda19); - rtl8168_mdio_write(tp, 0x14, 0xdb19); - rtl8168_mdio_write(tp, 0x14, 0x07ef); - rtl8168_mdio_write(tp, 0x14, 0x9502); - rtl8168_mdio_write(tp, 0x14, 0x4259); - rtl8168_mdio_write(tp, 0x14, 0x073f); - rtl8168_mdio_write(tp, 0x14, 0x0004); - rtl8168_mdio_write(tp, 0x14, 0x9fec); - rtl8168_mdio_write(tp, 0x14, 0xffef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xc6fe); - rtl8168_mdio_write(tp, 0x14, 0xfdfc); - rtl8168_mdio_write(tp, 0x14, 0x0400); - rtl8168_mdio_write(tp, 0x14, 0x0145); - rtl8168_mdio_write(tp, 0x14, 0x7d00); - rtl8168_mdio_write(tp, 0x14, 0x0345); - rtl8168_mdio_write(tp, 0x14, 0x5c00); - rtl8168_mdio_write(tp, 0x14, 0x0143); - rtl8168_mdio_write(tp, 0x14, 0x4f00); - rtl8168_mdio_write(tp, 0x14, 0x0387); - rtl8168_mdio_write(tp, 0x14, 0xdb00); - rtl8168_mdio_write(tp, 0x14, 0x0987); - rtl8168_mdio_write(tp, 0x14, 0xde00); - rtl8168_mdio_write(tp, 0x14, 0x0987); - rtl8168_mdio_write(tp, 0x14, 0xe100); - rtl8168_mdio_write(tp, 0x14, 0x0087); - rtl8168_mdio_write(tp, 0x14, 0xeaa4); - rtl8168_mdio_write(tp, 0x14, 0x00b8); - rtl8168_mdio_write(tp, 0x14, 0x20c4); - rtl8168_mdio_write(tp, 0x14, 0x1600); - rtl8168_mdio_write(tp, 0x14, 0x000f); - rtl8168_mdio_write(tp, 0x14, 0xf800); - rtl8168_mdio_write(tp, 0x14, 0x7098); - rtl8168_mdio_write(tp, 0x14, 0xa58a); - rtl8168_mdio_write(tp, 0x14, 0xb6a8); - rtl8168_mdio_write(tp, 0x14, 0x3e50); - rtl8168_mdio_write(tp, 0x14, 0xa83e); - rtl8168_mdio_write(tp, 0x14, 0x33bc); - rtl8168_mdio_write(tp, 0x14, 0xc622); - rtl8168_mdio_write(tp, 0x14, 0xbcc6); - rtl8168_mdio_write(tp, 0x14, 0xaaa4); - rtl8168_mdio_write(tp, 0x14, 0x42ff); - rtl8168_mdio_write(tp, 0x14, 0xc408); - rtl8168_mdio_write(tp, 0x14, 0x00c4); - rtl8168_mdio_write(tp, 0x14, 0x16a8); - rtl8168_mdio_write(tp, 0x14, 0xbcc0); - rtl8168_mdio_write(tp, 0x13, 0xb818); - rtl8168_mdio_write(tp, 0x14, 0x02f3); - rtl8168_mdio_write(tp, 0x13, 0xb81a); - rtl8168_mdio_write(tp, 0x14, 0x17d1); - rtl8168_mdio_write(tp, 0x13, 0xb81c); - rtl8168_mdio_write(tp, 0x14, 0x185a); - rtl8168_mdio_write(tp, 0x13, 0xb81e); - rtl8168_mdio_write(tp, 0x14, 0x3c66); - rtl8168_mdio_write(tp, 0x13, 0xb820); - rtl8168_mdio_write(tp, 0x14, 0x021f); - rtl8168_mdio_write(tp, 0x13, 0xc416); - rtl8168_mdio_write(tp, 0x14, 0x0500); - rtl8168_mdio_write(tp, 0x13, 0xb82e); - rtl8168_mdio_write(tp, 0x14, 0xfffc); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - gphy_val = rtl8168_mdio_read(tp, 0x10); - gphy_val &= ~(BIT_9); - rtl8168_mdio_write(tp, 0x10, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8146); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8168_set_phy_mcu_8168gu_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val; - - rtl8168_set_phy_mcu_patch_request(tp); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8146); - rtl8168_mdio_write(tp, 0x14, 0x0300); - rtl8168_mdio_write(tp, 0x13, 0xB82E); - rtl8168_mdio_write(tp, 0x14, 0x0001); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0xb820); - rtl8168_mdio_write(tp, 0x14, 0x0290); - rtl8168_mdio_write(tp, 0x13, 0xa012); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xa014); - rtl8168_mdio_write(tp, 0x14, 0x2c04); - rtl8168_mdio_write(tp, 0x14, 0x2c07); - rtl8168_mdio_write(tp, 0x14, 0x2c07); - rtl8168_mdio_write(tp, 0x14, 0x2c07); - rtl8168_mdio_write(tp, 0x14, 0xa304); - rtl8168_mdio_write(tp, 0x14, 0xa301); - rtl8168_mdio_write(tp, 0x14, 0x207e); - rtl8168_mdio_write(tp, 0x13, 0xa01a); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xa006); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xa004); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xa002); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xa000); - rtl8168_mdio_write(tp, 0x14, 0x107c); - rtl8168_mdio_write(tp, 0x13, 0xb820); - rtl8168_mdio_write(tp, 0x14, 0x0210); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8146); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8168_set_phy_mcu_8411b_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val; - - rtl8168_set_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp,0x1f, 0x0A43); - rtl8168_mdio_write(tp,0x13, 0x8146); - rtl8168_mdio_write(tp,0x14, 0x0100); - rtl8168_mdio_write(tp,0x13, 0xB82E); - rtl8168_mdio_write(tp,0x14, 0x0001); - - - rtl8168_mdio_write(tp,0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0xb820); - rtl8168_mdio_write(tp, 0x14, 0x0290); - rtl8168_mdio_write(tp, 0x13, 0xa012); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xa014); - rtl8168_mdio_write(tp, 0x14, 0x2c04); - rtl8168_mdio_write(tp, 0x14, 0x2c07); - rtl8168_mdio_write(tp, 0x14, 0x2c07); - rtl8168_mdio_write(tp, 0x14, 0x2c07); - rtl8168_mdio_write(tp, 0x14, 0xa304); - rtl8168_mdio_write(tp, 0x14, 0xa301); - rtl8168_mdio_write(tp, 0x14, 0x207e); - rtl8168_mdio_write(tp, 0x13, 0xa01a); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xa006); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xa004); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xa002); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xa000); - rtl8168_mdio_write(tp, 0x14, 0x107c); - rtl8168_mdio_write(tp, 0x13, 0xb820); - rtl8168_mdio_write(tp, 0x14, 0x0210); - - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8146); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8168_set_phy_mcu_8168ep_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val; - - rtl8168_set_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp,0x1f, 0x0A43); - rtl8168_mdio_write(tp,0x13, 0x8146); - rtl8168_mdio_write(tp,0x14, 0x8700); - rtl8168_mdio_write(tp,0x13, 0xB82E); - rtl8168_mdio_write(tp,0x14, 0x0001); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - - rtl8168_mdio_write(tp, 0x13, 0x83DD); - rtl8168_mdio_write(tp, 0x14, 0xAF83); - rtl8168_mdio_write(tp, 0x14, 0xE9AF); - rtl8168_mdio_write(tp, 0x14, 0x83EE); - rtl8168_mdio_write(tp, 0x14, 0xAF83); - rtl8168_mdio_write(tp, 0x14, 0xF1A1); - rtl8168_mdio_write(tp, 0x14, 0x83F4); - rtl8168_mdio_write(tp, 0x14, 0xD149); - rtl8168_mdio_write(tp, 0x14, 0xAF06); - rtl8168_mdio_write(tp, 0x14, 0x47AF); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0xAF00); - rtl8168_mdio_write(tp, 0x14, 0x00AF); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_mdio_write(tp, 0x13, 0xB818); - rtl8168_mdio_write(tp, 0x14, 0x0645); - - rtl8168_mdio_write(tp, 0x13, 0xB81A); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_mdio_write(tp, 0x13, 0xB81C); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_mdio_write(tp, 0x13, 0xB81E); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_mdio_write(tp, 0x13, 0xB832); - rtl8168_mdio_write(tp, 0x14, 0x0001); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8146); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8168_set_phy_mcu_8168h_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val; - - rtl8168_set_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8028); - rtl8168_mdio_write(tp, 0x14, 0x6200); - rtl8168_mdio_write(tp, 0x13, 0xB82E); - rtl8168_mdio_write(tp, 0x14, 0x0001); - - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0290); - rtl8168_mdio_write(tp, 0x13, 0xA012); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xA014); - rtl8168_mdio_write(tp, 0x14, 0x2c04); - rtl8168_mdio_write(tp, 0x14, 0x2c10); - rtl8168_mdio_write(tp, 0x14, 0x2c10); - rtl8168_mdio_write(tp, 0x14, 0x2c10); - rtl8168_mdio_write(tp, 0x14, 0xa210); - rtl8168_mdio_write(tp, 0x14, 0xa101); - rtl8168_mdio_write(tp, 0x14, 0xce10); - rtl8168_mdio_write(tp, 0x14, 0xe070); - rtl8168_mdio_write(tp, 0x14, 0x0f40); - rtl8168_mdio_write(tp, 0x14, 0xaf01); - rtl8168_mdio_write(tp, 0x14, 0x8f01); - rtl8168_mdio_write(tp, 0x14, 0x183e); - rtl8168_mdio_write(tp, 0x14, 0x8e10); - rtl8168_mdio_write(tp, 0x14, 0x8101); - rtl8168_mdio_write(tp, 0x14, 0x8210); - rtl8168_mdio_write(tp, 0x14, 0x28da); - rtl8168_mdio_write(tp, 0x13, 0xA01A); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xA006); - rtl8168_mdio_write(tp, 0x14, 0x0017); - rtl8168_mdio_write(tp, 0x13, 0xA004); - rtl8168_mdio_write(tp, 0x14, 0x0015); - rtl8168_mdio_write(tp, 0x13, 0xA002); - rtl8168_mdio_write(tp, 0x14, 0x0013); - rtl8168_mdio_write(tp, 0x13, 0xA000); - rtl8168_mdio_write(tp, 0x14, 0x18d1); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0210); - - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8028); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8168_set_phy_mcu_8168h_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val; - - rtl8168_set_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8028); - rtl8168_mdio_write(tp, 0x14, 0x6201); - rtl8168_mdio_write(tp, 0x13, 0xB82E); - rtl8168_mdio_write(tp, 0x14, 0x0001); - - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0290); - rtl8168_mdio_write(tp, 0x13, 0xA012); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xA014); - rtl8168_mdio_write(tp, 0x14, 0x2c04); - rtl8168_mdio_write(tp, 0x14, 0x2c09); - rtl8168_mdio_write(tp, 0x14, 0x2c09); - rtl8168_mdio_write(tp, 0x14, 0x2c09); - rtl8168_mdio_write(tp, 0x14, 0xad01); - rtl8168_mdio_write(tp, 0x14, 0xad01); - rtl8168_mdio_write(tp, 0x14, 0xad01); - rtl8168_mdio_write(tp, 0x14, 0xad01); - rtl8168_mdio_write(tp, 0x14, 0x236c); - rtl8168_mdio_write(tp, 0x13, 0xA01A); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xA006); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xA004); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xA002); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xA000); - rtl8168_mdio_write(tp, 0x14, 0x136b); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0210); - - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8323); - rtl8168_mdio_write(tp, 0x14, 0xaf83); - rtl8168_mdio_write(tp, 0x14, 0x2faf); - rtl8168_mdio_write(tp, 0x14, 0x853d); - rtl8168_mdio_write(tp, 0x14, 0xaf85); - rtl8168_mdio_write(tp, 0x14, 0x3daf); - rtl8168_mdio_write(tp, 0x14, 0x853d); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x45ad); - rtl8168_mdio_write(tp, 0x14, 0x2052); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7ae3); - rtl8168_mdio_write(tp, 0x14, 0x85fe); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f6); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7a1b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fa); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7be3); - rtl8168_mdio_write(tp, 0x14, 0x85fe); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f7); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7b1b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fb); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7ce3); - rtl8168_mdio_write(tp, 0x14, 0x85fe); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f8); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7c1b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fc); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7de3); - rtl8168_mdio_write(tp, 0x14, 0x85fe); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f9); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7d1b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fd); - rtl8168_mdio_write(tp, 0x14, 0xae50); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7ee3); - rtl8168_mdio_write(tp, 0x14, 0x85ff); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f6); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7e1b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fa); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7fe3); - rtl8168_mdio_write(tp, 0x14, 0x85ff); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f7); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7f1b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fb); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x80e3); - rtl8168_mdio_write(tp, 0x14, 0x85ff); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f8); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x801b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fc); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x81e3); - rtl8168_mdio_write(tp, 0x14, 0x85ff); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f9); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x811b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fd); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf6ad); - rtl8168_mdio_write(tp, 0x14, 0x2404); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xf610); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf7ad); - rtl8168_mdio_write(tp, 0x14, 0x2404); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xf710); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf8ad); - rtl8168_mdio_write(tp, 0x14, 0x2404); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xf810); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf9ad); - rtl8168_mdio_write(tp, 0x14, 0x2404); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xf910); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfaad); - rtl8168_mdio_write(tp, 0x14, 0x2704); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xfa00); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfbad); - rtl8168_mdio_write(tp, 0x14, 0x2704); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xfb00); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfcad); - rtl8168_mdio_write(tp, 0x14, 0x2704); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xfc00); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfdad); - rtl8168_mdio_write(tp, 0x14, 0x2704); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xfd00); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x44ad); - rtl8168_mdio_write(tp, 0x14, 0x203f); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf6e4); - rtl8168_mdio_write(tp, 0x14, 0x8288); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfae4); - rtl8168_mdio_write(tp, 0x14, 0x8289); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x440d); - rtl8168_mdio_write(tp, 0x14, 0x0458); - rtl8168_mdio_write(tp, 0x14, 0x01bf); - rtl8168_mdio_write(tp, 0x14, 0x8264); - rtl8168_mdio_write(tp, 0x14, 0x0215); - rtl8168_mdio_write(tp, 0x14, 0x38bf); - rtl8168_mdio_write(tp, 0x14, 0x824e); - rtl8168_mdio_write(tp, 0x14, 0x0213); - rtl8168_mdio_write(tp, 0x14, 0x06a0); - rtl8168_mdio_write(tp, 0x14, 0x010f); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x44f6); - rtl8168_mdio_write(tp, 0x14, 0x20e4); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x580f); - rtl8168_mdio_write(tp, 0x14, 0xe582); - rtl8168_mdio_write(tp, 0x14, 0x5aae); - rtl8168_mdio_write(tp, 0x14, 0x0ebf); - rtl8168_mdio_write(tp, 0x14, 0x825e); - rtl8168_mdio_write(tp, 0x14, 0xe382); - rtl8168_mdio_write(tp, 0x14, 0x44f7); - rtl8168_mdio_write(tp, 0x14, 0x3ce7); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x0212); - rtl8168_mdio_write(tp, 0x14, 0xf0ad); - rtl8168_mdio_write(tp, 0x14, 0x213f); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf7e4); - rtl8168_mdio_write(tp, 0x14, 0x8288); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfbe4); - rtl8168_mdio_write(tp, 0x14, 0x8289); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x440d); - rtl8168_mdio_write(tp, 0x14, 0x0558); - rtl8168_mdio_write(tp, 0x14, 0x01bf); - rtl8168_mdio_write(tp, 0x14, 0x826b); - rtl8168_mdio_write(tp, 0x14, 0x0215); - rtl8168_mdio_write(tp, 0x14, 0x38bf); - rtl8168_mdio_write(tp, 0x14, 0x824f); - rtl8168_mdio_write(tp, 0x14, 0x0213); - rtl8168_mdio_write(tp, 0x14, 0x06a0); - rtl8168_mdio_write(tp, 0x14, 0x010f); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x44f6); - rtl8168_mdio_write(tp, 0x14, 0x21e4); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x580f); - rtl8168_mdio_write(tp, 0x14, 0xe582); - rtl8168_mdio_write(tp, 0x14, 0x5bae); - rtl8168_mdio_write(tp, 0x14, 0x0ebf); - rtl8168_mdio_write(tp, 0x14, 0x8265); - rtl8168_mdio_write(tp, 0x14, 0xe382); - rtl8168_mdio_write(tp, 0x14, 0x44f7); - rtl8168_mdio_write(tp, 0x14, 0x3de7); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x0212); - rtl8168_mdio_write(tp, 0x14, 0xf0ad); - rtl8168_mdio_write(tp, 0x14, 0x223f); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf8e4); - rtl8168_mdio_write(tp, 0x14, 0x8288); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfce4); - rtl8168_mdio_write(tp, 0x14, 0x8289); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x440d); - rtl8168_mdio_write(tp, 0x14, 0x0658); - rtl8168_mdio_write(tp, 0x14, 0x01bf); - rtl8168_mdio_write(tp, 0x14, 0x8272); - rtl8168_mdio_write(tp, 0x14, 0x0215); - rtl8168_mdio_write(tp, 0x14, 0x38bf); - rtl8168_mdio_write(tp, 0x14, 0x8250); - rtl8168_mdio_write(tp, 0x14, 0x0213); - rtl8168_mdio_write(tp, 0x14, 0x06a0); - rtl8168_mdio_write(tp, 0x14, 0x010f); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x44f6); - rtl8168_mdio_write(tp, 0x14, 0x22e4); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x580f); - rtl8168_mdio_write(tp, 0x14, 0xe582); - rtl8168_mdio_write(tp, 0x14, 0x5cae); - rtl8168_mdio_write(tp, 0x14, 0x0ebf); - rtl8168_mdio_write(tp, 0x14, 0x826c); - rtl8168_mdio_write(tp, 0x14, 0xe382); - rtl8168_mdio_write(tp, 0x14, 0x44f7); - rtl8168_mdio_write(tp, 0x14, 0x3ee7); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x0212); - rtl8168_mdio_write(tp, 0x14, 0xf0ad); - rtl8168_mdio_write(tp, 0x14, 0x233f); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf9e4); - rtl8168_mdio_write(tp, 0x14, 0x8288); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfde4); - rtl8168_mdio_write(tp, 0x14, 0x8289); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x440d); - rtl8168_mdio_write(tp, 0x14, 0x0758); - rtl8168_mdio_write(tp, 0x14, 0x01bf); - rtl8168_mdio_write(tp, 0x14, 0x8279); - rtl8168_mdio_write(tp, 0x14, 0x0215); - rtl8168_mdio_write(tp, 0x14, 0x38bf); - rtl8168_mdio_write(tp, 0x14, 0x8251); - rtl8168_mdio_write(tp, 0x14, 0x0213); - rtl8168_mdio_write(tp, 0x14, 0x06a0); - rtl8168_mdio_write(tp, 0x14, 0x010f); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x44f6); - rtl8168_mdio_write(tp, 0x14, 0x23e4); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x580f); - rtl8168_mdio_write(tp, 0x14, 0xe582); - rtl8168_mdio_write(tp, 0x14, 0x5dae); - rtl8168_mdio_write(tp, 0x14, 0x0ebf); - rtl8168_mdio_write(tp, 0x14, 0x8273); - rtl8168_mdio_write(tp, 0x14, 0xe382); - rtl8168_mdio_write(tp, 0x14, 0x44f7); - rtl8168_mdio_write(tp, 0x14, 0x3fe7); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x0212); - rtl8168_mdio_write(tp, 0x14, 0xf0ee); - rtl8168_mdio_write(tp, 0x14, 0x8288); - rtl8168_mdio_write(tp, 0x14, 0x10ee); - rtl8168_mdio_write(tp, 0x14, 0x8289); - rtl8168_mdio_write(tp, 0x14, 0x00af); - rtl8168_mdio_write(tp, 0x14, 0x14aa); - rtl8168_mdio_write(tp, 0x13, 0xb818); - rtl8168_mdio_write(tp, 0x14, 0x13cf); - rtl8168_mdio_write(tp, 0x13, 0xb81a); - rtl8168_mdio_write(tp, 0x14, 0xfffd); - rtl8168_mdio_write(tp, 0x13, 0xb81c); - rtl8168_mdio_write(tp, 0x14, 0xfffd); - rtl8168_mdio_write(tp, 0x13, 0xb81e); - rtl8168_mdio_write(tp, 0x14, 0xfffd); - rtl8168_mdio_write(tp, 0x13, 0xb832); - rtl8168_mdio_write(tp, 0x14, 0x0001); - - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8028); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_clear_phy_mcu_patch_request(tp); - - if (tp->RequiredSecLanDonglePatch) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - gphy_val = rtl8168_mdio_read(tp, 0x11); - gphy_val &= ~BIT_6; - rtl8168_mdio_write(tp, 0x11, gphy_val); - } -} - -static void -rtl8168_init_hw_phy_mcu(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 require_disable_phy_disable_mode = FALSE; - - if (tp->NotWrRamCodeToMicroP == TRUE) return; - if (rtl8168_check_hw_phy_mcu_code_ver(dev)) return; - - if (FALSE == rtl8168_phy_ram_code_check(dev)) { - rtl8168_set_phy_ram_code_check_fail_flag(dev); - return; - } - - if (HW_SUPPORT_CHECK_PHY_DISABLE_MODE(tp) && rtl8168_is_in_phy_disable_mode(dev)) - require_disable_phy_disable_mode = TRUE; - - if (require_disable_phy_disable_mode) - rtl8168_disable_phy_disable_mode(dev); - - switch (tp->mcfg) { - case CFG_METHOD_14: - rtl8168_set_phy_mcu_8168e_1(dev); - break; - case CFG_METHOD_15: - rtl8168_set_phy_mcu_8168e_2(dev); - break; - case CFG_METHOD_16: - rtl8168_set_phy_mcu_8168evl_1(dev); - break; - case CFG_METHOD_17: - rtl8168_set_phy_mcu_8168evl_2(dev); - break; - case CFG_METHOD_18: - rtl8168_set_phy_mcu_8168f_1(dev); - break; - case CFG_METHOD_19: - rtl8168_set_phy_mcu_8168f_2(dev); - break; - case CFG_METHOD_20: - rtl8168_set_phy_mcu_8411_1(dev); - break; - case CFG_METHOD_21: - rtl8168_set_phy_mcu_8168g_1(dev); - break; - case CFG_METHOD_25: - rtl8168_set_phy_mcu_8168gu_2(dev); - break; - case CFG_METHOD_26: - rtl8168_set_phy_mcu_8411b_1(dev); - break; - case CFG_METHOD_28: - rtl8168_set_phy_mcu_8168ep_2(dev); - break; - case CFG_METHOD_29: - rtl8168_set_phy_mcu_8168h_1(dev); - break; - case CFG_METHOD_30: - rtl8168_set_phy_mcu_8168h_2(dev); - break; - } - - if (require_disable_phy_disable_mode) - rtl8168_enable_phy_disable_mode(dev); - - rtl8168_write_hw_phy_mcu_code_ver(dev); - - rtl8168_mdio_write(tp,0x1F, 0x0000); - - tp->HwHasWrRamCodeToMicroP = TRUE; -} -#endif - -static void -rtl8168_hw_phy_config(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - u16 gphy_val; - unsigned int i; - - tp->phy_reset_enable(dev); - - if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x06) return; - -#ifndef ENABLE_USE_FIRMWARE_FILE - if (!tp->rtl_fw) { - rtl8168_init_hw_phy_mcu(dev); - } -#endif - - if (tp->mcfg == CFG_METHOD_1) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0B, 0x94B0); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x12, 0x6096); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x0D, 0xF8A0); - } else if (tp->mcfg == CFG_METHOD_2) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0B, 0x94B0); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x12, 0x6096); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_3) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0B, 0x94B0); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x12, 0x6096); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_4) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x12, 0x2300); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x16, 0x000A); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x12, 0xC096); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x00, 0x88DE); - rtl8168_mdio_write(tp, 0x01, 0x82B1); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x08, 0x9E30); - rtl8168_mdio_write(tp, 0x09, 0x01F0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0A, 0x5500); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x03, 0x7002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0C, 0x00C8); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | (1 << 5)); - rtl8168_mdio_write(tp, 0x0D, rtl8168_mdio_read(tp, 0x0D) & ~(1 << 5)); - } else if (tp->mcfg == CFG_METHOD_5) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x12, 0x2300); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x16, 0x0F0A); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x00, 0x88DE); - rtl8168_mdio_write(tp, 0x01, 0x82B1); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0C, 0x7EB8); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x0761); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x03, 0x802F); - rtl8168_mdio_write(tp, 0x02, 0x4F02); - rtl8168_mdio_write(tp, 0x01, 0x0409); - rtl8168_mdio_write(tp, 0x00, 0xF099); - rtl8168_mdio_write(tp, 0x04, 0x9800); - rtl8168_mdio_write(tp, 0x04, 0x9000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x16, rtl8168_mdio_read(tp, 0x16) | (1 << 0)); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | (1 << 5)); - rtl8168_mdio_write(tp, 0x0D, rtl8168_mdio_read(tp, 0x0D) & ~(1 << 5)); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x1D, 0x3D98); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_6) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x12, 0x2300); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x16, 0x0F0A); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x00, 0x88DE); - rtl8168_mdio_write(tp, 0x01, 0x82B1); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0C, 0x7EB8); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x5461); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x5461); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x16, rtl8168_mdio_read(tp, 0x16) | (1 << 0)); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | (1 << 5)); - rtl8168_mdio_write(tp, 0x0D, rtl8168_mdio_read(tp, 0x0D) & ~(1 << 5)); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x1D, 0x3D98); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_7) { - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | (1 << 5)); - rtl8168_mdio_write(tp, 0x0D, rtl8168_mdio_read(tp, 0x0D) & ~(1 << 5)); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x1D, 0x3D98); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x14, 0xCAA3); - rtl8168_mdio_write(tp, 0x1C, 0x000A); - rtl8168_mdio_write(tp, 0x18, 0x65D0); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x17, 0xB580); - rtl8168_mdio_write(tp, 0x18, 0xFF54); - rtl8168_mdio_write(tp, 0x19, 0x3954); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0D, 0x310C); - rtl8168_mdio_write(tp, 0x0E, 0x310C); - rtl8168_mdio_write(tp, 0x0F, 0x311C); - rtl8168_mdio_write(tp, 0x06, 0x0761); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x18, 0xFF55); - rtl8168_mdio_write(tp, 0x19, 0x3955); - rtl8168_mdio_write(tp, 0x18, 0xFF54); - rtl8168_mdio_write(tp, 0x19, 0x3954); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_8) { - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | (1 << 5)); - rtl8168_mdio_write(tp, 0x0D, rtl8168_mdio_read(tp, 0x0D) & ~(1 << 5)); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x14, 0xCAA3); - rtl8168_mdio_write(tp, 0x1C, 0x000A); - rtl8168_mdio_write(tp, 0x18, 0x65D0); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x17, 0xB580); - rtl8168_mdio_write(tp, 0x18, 0xFF54); - rtl8168_mdio_write(tp, 0x19, 0x3954); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0D, 0x310C); - rtl8168_mdio_write(tp, 0x0E, 0x310C); - rtl8168_mdio_write(tp, 0x0F, 0x311C); - rtl8168_mdio_write(tp, 0x06, 0x0761); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x18, 0xFF55); - rtl8168_mdio_write(tp, 0x19, 0x3955); - rtl8168_mdio_write(tp, 0x18, 0xFF54); - rtl8168_mdio_write(tp, 0x19, 0x3954); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x16, rtl8168_mdio_read(tp, 0x16) | (1 << 0)); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_9) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x06, 0x4064); - rtl8168_mdio_write(tp, 0x07, 0x2863); - rtl8168_mdio_write(tp, 0x08, 0x059C); - rtl8168_mdio_write(tp, 0x09, 0x26B4); - rtl8168_mdio_write(tp, 0x0A, 0x6A19); - rtl8168_mdio_write(tp, 0x0B, 0xDCC8); - rtl8168_mdio_write(tp, 0x10, 0xF06D); - rtl8168_mdio_write(tp, 0x14, 0x7F68); - rtl8168_mdio_write(tp, 0x18, 0x7FD9); - rtl8168_mdio_write(tp, 0x1C, 0xF0FF); - rtl8168_mdio_write(tp, 0x1D, 0x3D9C); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x12, 0xF49F); - rtl8168_mdio_write(tp, 0x13, 0x070B); - rtl8168_mdio_write(tp, 0x1A, 0x05AD); - rtl8168_mdio_write(tp, 0x14, 0x94C0); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0B) & 0xFF00; - gphy_val |= 0x10; - rtl8168_mdio_write(tp, 0x0B, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x0C) & 0x00FF; - gphy_val |= 0xA200; - rtl8168_mdio_write(tp, 0x0C, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x5561); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8332); - rtl8168_mdio_write(tp, 0x06, 0x5561); - - if (rtl8168_efuse_read(tp, 0x01) == 0xb1) { - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x05, 0x669A); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8330); - rtl8168_mdio_write(tp, 0x06, 0x669A); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0D); - if ((gphy_val & 0x00FF) != 0x006C) { - gphy_val &= 0xFF00; - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0065); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0066); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0067); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0068); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0069); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x006A); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x006B); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x006C); - } - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x05, 0x6662); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8330); - rtl8168_mdio_write(tp, 0x06, 0x6662); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0D); - gphy_val |= BIT_9; - gphy_val |= BIT_8; - rtl8168_mdio_write(tp, 0x0D, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x0F); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x0F, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x02); - gphy_val &= ~BIT_10; - gphy_val &= ~BIT_9; - gphy_val |= BIT_8; - rtl8168_mdio_write(tp, 0x02, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x03); - gphy_val &= ~BIT_15; - gphy_val &= ~BIT_14; - gphy_val &= ~BIT_13; - rtl8168_mdio_write(tp, 0x03, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x001B); - if (rtl8168_mdio_read(tp, 0x06) == 0xBF00) { - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x59ee); - rtl8168_mdio_write(tp, 0x06, 0xf8ea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xf8eb); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xf87c); - rtl8168_mdio_write(tp, 0x06, 0xe1f8); - rtl8168_mdio_write(tp, 0x06, 0x7d59); - rtl8168_mdio_write(tp, 0x06, 0x0fef); - rtl8168_mdio_write(tp, 0x06, 0x0139); - rtl8168_mdio_write(tp, 0x06, 0x029e); - rtl8168_mdio_write(tp, 0x06, 0x06ef); - rtl8168_mdio_write(tp, 0x06, 0x1039); - rtl8168_mdio_write(tp, 0x06, 0x089f); - rtl8168_mdio_write(tp, 0x06, 0x2aee); - rtl8168_mdio_write(tp, 0x06, 0xf8ea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xf8eb); - rtl8168_mdio_write(tp, 0x06, 0x01e0); - rtl8168_mdio_write(tp, 0x06, 0xf87c); - rtl8168_mdio_write(tp, 0x06, 0xe1f8); - rtl8168_mdio_write(tp, 0x06, 0x7d58); - rtl8168_mdio_write(tp, 0x06, 0x409e); - rtl8168_mdio_write(tp, 0x06, 0x0f39); - rtl8168_mdio_write(tp, 0x06, 0x46aa); - rtl8168_mdio_write(tp, 0x06, 0x0bbf); - rtl8168_mdio_write(tp, 0x06, 0x8290); - rtl8168_mdio_write(tp, 0x06, 0xd682); - rtl8168_mdio_write(tp, 0x06, 0x9802); - rtl8168_mdio_write(tp, 0x06, 0x014f); - rtl8168_mdio_write(tp, 0x06, 0xae09); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0x98d6); - rtl8168_mdio_write(tp, 0x06, 0x82a0); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x4fef); - rtl8168_mdio_write(tp, 0x06, 0x95fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x05f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xeef8); - rtl8168_mdio_write(tp, 0x06, 0xea00); - rtl8168_mdio_write(tp, 0x06, 0xeef8); - rtl8168_mdio_write(tp, 0x06, 0xeb00); - rtl8168_mdio_write(tp, 0x06, 0xe2f8); - rtl8168_mdio_write(tp, 0x06, 0x7ce3); - rtl8168_mdio_write(tp, 0x06, 0xf87d); - rtl8168_mdio_write(tp, 0x06, 0xa511); - rtl8168_mdio_write(tp, 0x06, 0x1112); - rtl8168_mdio_write(tp, 0x06, 0xd240); - rtl8168_mdio_write(tp, 0x06, 0xd644); - rtl8168_mdio_write(tp, 0x06, 0x4402); - rtl8168_mdio_write(tp, 0x06, 0x8217); - rtl8168_mdio_write(tp, 0x06, 0xd2a0); - rtl8168_mdio_write(tp, 0x06, 0xd6aa); - rtl8168_mdio_write(tp, 0x06, 0xaa02); - rtl8168_mdio_write(tp, 0x06, 0x8217); - rtl8168_mdio_write(tp, 0x06, 0xae0f); - rtl8168_mdio_write(tp, 0x06, 0xa544); - rtl8168_mdio_write(tp, 0x06, 0x4402); - rtl8168_mdio_write(tp, 0x06, 0xae4d); - rtl8168_mdio_write(tp, 0x06, 0xa5aa); - rtl8168_mdio_write(tp, 0x06, 0xaa02); - rtl8168_mdio_write(tp, 0x06, 0xae47); - rtl8168_mdio_write(tp, 0x06, 0xaf82); - rtl8168_mdio_write(tp, 0x06, 0x13ee); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0x0fee); - rtl8168_mdio_write(tp, 0x06, 0x834c); - rtl8168_mdio_write(tp, 0x06, 0x0fee); - rtl8168_mdio_write(tp, 0x06, 0x834f); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8351); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x834a); - rtl8168_mdio_write(tp, 0x06, 0xffee); - rtl8168_mdio_write(tp, 0x06, 0x834b); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0x8330); - rtl8168_mdio_write(tp, 0x06, 0xe183); - rtl8168_mdio_write(tp, 0x06, 0x3158); - rtl8168_mdio_write(tp, 0x06, 0xfee4); - rtl8168_mdio_write(tp, 0x06, 0xf88a); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x8be0); - rtl8168_mdio_write(tp, 0x06, 0x8332); - rtl8168_mdio_write(tp, 0x06, 0xe183); - rtl8168_mdio_write(tp, 0x06, 0x3359); - rtl8168_mdio_write(tp, 0x06, 0x0fe2); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0x0c24); - rtl8168_mdio_write(tp, 0x06, 0x5af0); - rtl8168_mdio_write(tp, 0x06, 0x1e12); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x8ce5); - rtl8168_mdio_write(tp, 0x06, 0xf88d); - rtl8168_mdio_write(tp, 0x06, 0xaf82); - rtl8168_mdio_write(tp, 0x06, 0x13e0); - rtl8168_mdio_write(tp, 0x06, 0x834f); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x834f); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x009f); - rtl8168_mdio_write(tp, 0x06, 0x0ae0); - rtl8168_mdio_write(tp, 0x06, 0x834f); - rtl8168_mdio_write(tp, 0x06, 0xa010); - rtl8168_mdio_write(tp, 0x06, 0xa5ee); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x01e0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7805); - rtl8168_mdio_write(tp, 0x06, 0x9e9a); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x049e); - rtl8168_mdio_write(tp, 0x06, 0x10e0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7803); - rtl8168_mdio_write(tp, 0x06, 0x9e0f); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x05ae); - rtl8168_mdio_write(tp, 0x06, 0x0caf); - rtl8168_mdio_write(tp, 0x06, 0x81f8); - rtl8168_mdio_write(tp, 0x06, 0xaf81); - rtl8168_mdio_write(tp, 0x06, 0xa3af); - rtl8168_mdio_write(tp, 0x06, 0x81dc); - rtl8168_mdio_write(tp, 0x06, 0xaf82); - rtl8168_mdio_write(tp, 0x06, 0x13ee); - rtl8168_mdio_write(tp, 0x06, 0x8348); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8349); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0x8351); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x8351); - rtl8168_mdio_write(tp, 0x06, 0x5801); - rtl8168_mdio_write(tp, 0x06, 0x9fea); - rtl8168_mdio_write(tp, 0x06, 0xd000); - rtl8168_mdio_write(tp, 0x06, 0xd180); - rtl8168_mdio_write(tp, 0x06, 0x1f66); - rtl8168_mdio_write(tp, 0x06, 0xe2f8); - rtl8168_mdio_write(tp, 0x06, 0xeae3); - rtl8168_mdio_write(tp, 0x06, 0xf8eb); - rtl8168_mdio_write(tp, 0x06, 0x5af8); - rtl8168_mdio_write(tp, 0x06, 0x1e20); - rtl8168_mdio_write(tp, 0x06, 0xe6f8); - rtl8168_mdio_write(tp, 0x06, 0xeae5); - rtl8168_mdio_write(tp, 0x06, 0xf8eb); - rtl8168_mdio_write(tp, 0x06, 0xd302); - rtl8168_mdio_write(tp, 0x06, 0xb3fe); - rtl8168_mdio_write(tp, 0x06, 0xe2f8); - rtl8168_mdio_write(tp, 0x06, 0x7cef); - rtl8168_mdio_write(tp, 0x06, 0x325b); - rtl8168_mdio_write(tp, 0x06, 0x80e3); - rtl8168_mdio_write(tp, 0x06, 0xf87d); - rtl8168_mdio_write(tp, 0x06, 0x9e03); - rtl8168_mdio_write(tp, 0x06, 0x7dff); - rtl8168_mdio_write(tp, 0x06, 0xff0d); - rtl8168_mdio_write(tp, 0x06, 0x581c); - rtl8168_mdio_write(tp, 0x06, 0x551a); - rtl8168_mdio_write(tp, 0x06, 0x6511); - rtl8168_mdio_write(tp, 0x06, 0xa190); - rtl8168_mdio_write(tp, 0x06, 0xd3e2); - rtl8168_mdio_write(tp, 0x06, 0x8348); - rtl8168_mdio_write(tp, 0x06, 0xe383); - rtl8168_mdio_write(tp, 0x06, 0x491b); - rtl8168_mdio_write(tp, 0x06, 0x56ab); - rtl8168_mdio_write(tp, 0x06, 0x08ef); - rtl8168_mdio_write(tp, 0x06, 0x56e6); - rtl8168_mdio_write(tp, 0x06, 0x8348); - rtl8168_mdio_write(tp, 0x06, 0xe783); - rtl8168_mdio_write(tp, 0x06, 0x4910); - rtl8168_mdio_write(tp, 0x06, 0xd180); - rtl8168_mdio_write(tp, 0x06, 0x1f66); - rtl8168_mdio_write(tp, 0x06, 0xa004); - rtl8168_mdio_write(tp, 0x06, 0xb9e2); - rtl8168_mdio_write(tp, 0x06, 0x8348); - rtl8168_mdio_write(tp, 0x06, 0xe383); - rtl8168_mdio_write(tp, 0x06, 0x49ef); - rtl8168_mdio_write(tp, 0x06, 0x65e2); - rtl8168_mdio_write(tp, 0x06, 0x834a); - rtl8168_mdio_write(tp, 0x06, 0xe383); - rtl8168_mdio_write(tp, 0x06, 0x4b1b); - rtl8168_mdio_write(tp, 0x06, 0x56aa); - rtl8168_mdio_write(tp, 0x06, 0x0eef); - rtl8168_mdio_write(tp, 0x06, 0x56e6); - rtl8168_mdio_write(tp, 0x06, 0x834a); - rtl8168_mdio_write(tp, 0x06, 0xe783); - rtl8168_mdio_write(tp, 0x06, 0x4be2); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0xe683); - rtl8168_mdio_write(tp, 0x06, 0x4ce0); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0xa000); - rtl8168_mdio_write(tp, 0x06, 0x0caf); - rtl8168_mdio_write(tp, 0x06, 0x81dc); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4d10); - rtl8168_mdio_write(tp, 0x06, 0xe483); - rtl8168_mdio_write(tp, 0x06, 0x4dae); - rtl8168_mdio_write(tp, 0x06, 0x0480); - rtl8168_mdio_write(tp, 0x06, 0xe483); - rtl8168_mdio_write(tp, 0x06, 0x4de0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7803); - rtl8168_mdio_write(tp, 0x06, 0x9e0b); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x049e); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x02e0); - rtl8168_mdio_write(tp, 0x06, 0x8332); - rtl8168_mdio_write(tp, 0x06, 0xe183); - rtl8168_mdio_write(tp, 0x06, 0x3359); - rtl8168_mdio_write(tp, 0x06, 0x0fe2); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0x0c24); - rtl8168_mdio_write(tp, 0x06, 0x5af0); - rtl8168_mdio_write(tp, 0x06, 0x1e12); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x8ce5); - rtl8168_mdio_write(tp, 0x06, 0xf88d); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x30e1); - rtl8168_mdio_write(tp, 0x06, 0x8331); - rtl8168_mdio_write(tp, 0x06, 0x6801); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x8ae5); - rtl8168_mdio_write(tp, 0x06, 0xf88b); - rtl8168_mdio_write(tp, 0x06, 0xae37); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4e03); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4ce1); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0x1b01); - rtl8168_mdio_write(tp, 0x06, 0x9e04); - rtl8168_mdio_write(tp, 0x06, 0xaaa1); - rtl8168_mdio_write(tp, 0x06, 0xaea8); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4e04); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4f00); - rtl8168_mdio_write(tp, 0x06, 0xaeab); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4f78); - rtl8168_mdio_write(tp, 0x06, 0x039f); - rtl8168_mdio_write(tp, 0x06, 0x14ee); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x05d2); - rtl8168_mdio_write(tp, 0x06, 0x40d6); - rtl8168_mdio_write(tp, 0x06, 0x5554); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x17d2); - rtl8168_mdio_write(tp, 0x06, 0xa0d6); - rtl8168_mdio_write(tp, 0x06, 0xba00); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x17fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x05f8); - rtl8168_mdio_write(tp, 0x06, 0xe0f8); - rtl8168_mdio_write(tp, 0x06, 0x60e1); - rtl8168_mdio_write(tp, 0x06, 0xf861); - rtl8168_mdio_write(tp, 0x06, 0x6802); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x60e5); - rtl8168_mdio_write(tp, 0x06, 0xf861); - rtl8168_mdio_write(tp, 0x06, 0xe0f8); - rtl8168_mdio_write(tp, 0x06, 0x48e1); - rtl8168_mdio_write(tp, 0x06, 0xf849); - rtl8168_mdio_write(tp, 0x06, 0x580f); - rtl8168_mdio_write(tp, 0x06, 0x1e02); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x48e5); - rtl8168_mdio_write(tp, 0x06, 0xf849); - rtl8168_mdio_write(tp, 0x06, 0xd000); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x5bbf); - rtl8168_mdio_write(tp, 0x06, 0x8350); - rtl8168_mdio_write(tp, 0x06, 0xef46); - rtl8168_mdio_write(tp, 0x06, 0xdc19); - rtl8168_mdio_write(tp, 0x06, 0xddd0); - rtl8168_mdio_write(tp, 0x06, 0x0102); - rtl8168_mdio_write(tp, 0x06, 0x825b); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x77e0); - rtl8168_mdio_write(tp, 0x06, 0xf860); - rtl8168_mdio_write(tp, 0x06, 0xe1f8); - rtl8168_mdio_write(tp, 0x06, 0x6158); - rtl8168_mdio_write(tp, 0x06, 0xfde4); - rtl8168_mdio_write(tp, 0x06, 0xf860); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x61fc); - rtl8168_mdio_write(tp, 0x06, 0x04f9); - rtl8168_mdio_write(tp, 0x06, 0xfafb); - rtl8168_mdio_write(tp, 0x06, 0xc6bf); - rtl8168_mdio_write(tp, 0x06, 0xf840); - rtl8168_mdio_write(tp, 0x06, 0xbe83); - rtl8168_mdio_write(tp, 0x06, 0x50a0); - rtl8168_mdio_write(tp, 0x06, 0x0101); - rtl8168_mdio_write(tp, 0x06, 0x071b); - rtl8168_mdio_write(tp, 0x06, 0x89cf); - rtl8168_mdio_write(tp, 0x06, 0xd208); - rtl8168_mdio_write(tp, 0x06, 0xebdb); - rtl8168_mdio_write(tp, 0x06, 0x19b2); - rtl8168_mdio_write(tp, 0x06, 0xfbff); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe0f8); - rtl8168_mdio_write(tp, 0x06, 0x48e1); - rtl8168_mdio_write(tp, 0x06, 0xf849); - rtl8168_mdio_write(tp, 0x06, 0x6808); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x48e5); - rtl8168_mdio_write(tp, 0x06, 0xf849); - rtl8168_mdio_write(tp, 0x06, 0x58f7); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x48e5); - rtl8168_mdio_write(tp, 0x06, 0xf849); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0x4d20); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x4e22); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x4ddf); - rtl8168_mdio_write(tp, 0x06, 0xff01); - rtl8168_mdio_write(tp, 0x06, 0x4edd); - rtl8168_mdio_write(tp, 0x06, 0xff01); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xfbef); - rtl8168_mdio_write(tp, 0x06, 0x79bf); - rtl8168_mdio_write(tp, 0x06, 0xf822); - rtl8168_mdio_write(tp, 0x06, 0xd819); - rtl8168_mdio_write(tp, 0x06, 0xd958); - rtl8168_mdio_write(tp, 0x06, 0x849f); - rtl8168_mdio_write(tp, 0x06, 0x09bf); - rtl8168_mdio_write(tp, 0x06, 0x82be); - rtl8168_mdio_write(tp, 0x06, 0xd682); - rtl8168_mdio_write(tp, 0x06, 0xc602); - rtl8168_mdio_write(tp, 0x06, 0x014f); - rtl8168_mdio_write(tp, 0x06, 0xef97); - rtl8168_mdio_write(tp, 0x06, 0xfffe); - rtl8168_mdio_write(tp, 0x06, 0xfc05); - rtl8168_mdio_write(tp, 0x06, 0x17ff); - rtl8168_mdio_write(tp, 0x06, 0xfe01); - rtl8168_mdio_write(tp, 0x06, 0x1700); - rtl8168_mdio_write(tp, 0x06, 0x0102); - rtl8168_mdio_write(tp, 0x05, 0x83d8); - rtl8168_mdio_write(tp, 0x06, 0x8051); - rtl8168_mdio_write(tp, 0x05, 0x83d6); - rtl8168_mdio_write(tp, 0x06, 0x82a0); - rtl8168_mdio_write(tp, 0x05, 0x83d4); - rtl8168_mdio_write(tp, 0x06, 0x8000); - rtl8168_mdio_write(tp, 0x02, 0x2010); - rtl8168_mdio_write(tp, 0x03, 0xdc00); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x0b, 0x0600); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00fc); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0xF880); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_10) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x06, 0x4064); - rtl8168_mdio_write(tp, 0x07, 0x2863); - rtl8168_mdio_write(tp, 0x08, 0x059C); - rtl8168_mdio_write(tp, 0x09, 0x26B4); - rtl8168_mdio_write(tp, 0x0A, 0x6A19); - rtl8168_mdio_write(tp, 0x0B, 0xDCC8); - rtl8168_mdio_write(tp, 0x10, 0xF06D); - rtl8168_mdio_write(tp, 0x14, 0x7F68); - rtl8168_mdio_write(tp, 0x18, 0x7FD9); - rtl8168_mdio_write(tp, 0x1C, 0xF0FF); - rtl8168_mdio_write(tp, 0x1D, 0x3D9C); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x12, 0xF49F); - rtl8168_mdio_write(tp, 0x13, 0x070B); - rtl8168_mdio_write(tp, 0x1A, 0x05AD); - rtl8168_mdio_write(tp, 0x14, 0x94C0); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x5561); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8332); - rtl8168_mdio_write(tp, 0x06, 0x5561); - - if (rtl8168_efuse_read(tp, 0x01) == 0xb1) { - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x05, 0x669A); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8330); - rtl8168_mdio_write(tp, 0x06, 0x669A); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0D); - if ((gphy_val & 0x00FF) != 0x006C) { - gphy_val &= 0xFF00; - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0065); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0066); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0067); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0068); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0069); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x006A); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x006B); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x006C); - } - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x05, 0x2642); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8330); - rtl8168_mdio_write(tp, 0x06, 0x2642); - } - - if (rtl8168_efuse_read(tp, 0x30) == 0x98) { - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) & ~BIT_1); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x01, rtl8168_mdio_read(tp, 0x01) | BIT_9); - } else if (rtl8168_efuse_read(tp, 0x30) == 0x90) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x01, rtl8168_mdio_read(tp, 0x01) & ~BIT_9); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x5101); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x02); - gphy_val &= ~BIT_10; - gphy_val &= ~BIT_9; - gphy_val |= BIT_8; - rtl8168_mdio_write(tp, 0x02, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x03); - gphy_val &= ~BIT_15; - gphy_val &= ~BIT_14; - gphy_val &= ~BIT_13; - rtl8168_mdio_write(tp, 0x03, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0F); - gphy_val |= BIT_4; - gphy_val |= BIT_2; - gphy_val |= BIT_1; - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x0F, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x001B); - if (rtl8168_mdio_read(tp, 0x06) == 0xB300) { - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaee); - rtl8168_mdio_write(tp, 0x06, 0xf8ea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xf8eb); - rtl8168_mdio_write(tp, 0x06, 0x00e2); - rtl8168_mdio_write(tp, 0x06, 0xf87c); - rtl8168_mdio_write(tp, 0x06, 0xe3f8); - rtl8168_mdio_write(tp, 0x06, 0x7da5); - rtl8168_mdio_write(tp, 0x06, 0x1111); - rtl8168_mdio_write(tp, 0x06, 0x12d2); - rtl8168_mdio_write(tp, 0x06, 0x40d6); - rtl8168_mdio_write(tp, 0x06, 0x4444); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xc6d2); - rtl8168_mdio_write(tp, 0x06, 0xa0d6); - rtl8168_mdio_write(tp, 0x06, 0xaaaa); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xc6ae); - rtl8168_mdio_write(tp, 0x06, 0x0fa5); - rtl8168_mdio_write(tp, 0x06, 0x4444); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x4da5); - rtl8168_mdio_write(tp, 0x06, 0xaaaa); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x47af); - rtl8168_mdio_write(tp, 0x06, 0x81c2); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4e00); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4d0f); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4c0f); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4f00); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x5100); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4aff); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4bff); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x30e1); - rtl8168_mdio_write(tp, 0x06, 0x8331); - rtl8168_mdio_write(tp, 0x06, 0x58fe); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x8ae5); - rtl8168_mdio_write(tp, 0x06, 0xf88b); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x32e1); - rtl8168_mdio_write(tp, 0x06, 0x8333); - rtl8168_mdio_write(tp, 0x06, 0x590f); - rtl8168_mdio_write(tp, 0x06, 0xe283); - rtl8168_mdio_write(tp, 0x06, 0x4d0c); - rtl8168_mdio_write(tp, 0x06, 0x245a); - rtl8168_mdio_write(tp, 0x06, 0xf01e); - rtl8168_mdio_write(tp, 0x06, 0x12e4); - rtl8168_mdio_write(tp, 0x06, 0xf88c); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x8daf); - rtl8168_mdio_write(tp, 0x06, 0x81c2); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4f10); - rtl8168_mdio_write(tp, 0x06, 0xe483); - rtl8168_mdio_write(tp, 0x06, 0x4fe0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7800); - rtl8168_mdio_write(tp, 0x06, 0x9f0a); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4fa0); - rtl8168_mdio_write(tp, 0x06, 0x10a5); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4e01); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x059e); - rtl8168_mdio_write(tp, 0x06, 0x9ae0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7804); - rtl8168_mdio_write(tp, 0x06, 0x9e10); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x0fe0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7801); - rtl8168_mdio_write(tp, 0x06, 0x9e05); - rtl8168_mdio_write(tp, 0x06, 0xae0c); - rtl8168_mdio_write(tp, 0x06, 0xaf81); - rtl8168_mdio_write(tp, 0x06, 0xa7af); - rtl8168_mdio_write(tp, 0x06, 0x8152); - rtl8168_mdio_write(tp, 0x06, 0xaf81); - rtl8168_mdio_write(tp, 0x06, 0x8baf); - rtl8168_mdio_write(tp, 0x06, 0x81c2); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4800); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4900); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x5110); - rtl8168_mdio_write(tp, 0x06, 0xe483); - rtl8168_mdio_write(tp, 0x06, 0x5158); - rtl8168_mdio_write(tp, 0x06, 0x019f); - rtl8168_mdio_write(tp, 0x06, 0xead0); - rtl8168_mdio_write(tp, 0x06, 0x00d1); - rtl8168_mdio_write(tp, 0x06, 0x801f); - rtl8168_mdio_write(tp, 0x06, 0x66e2); - rtl8168_mdio_write(tp, 0x06, 0xf8ea); - rtl8168_mdio_write(tp, 0x06, 0xe3f8); - rtl8168_mdio_write(tp, 0x06, 0xeb5a); - rtl8168_mdio_write(tp, 0x06, 0xf81e); - rtl8168_mdio_write(tp, 0x06, 0x20e6); - rtl8168_mdio_write(tp, 0x06, 0xf8ea); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0xebd3); - rtl8168_mdio_write(tp, 0x06, 0x02b3); - rtl8168_mdio_write(tp, 0x06, 0xfee2); - rtl8168_mdio_write(tp, 0x06, 0xf87c); - rtl8168_mdio_write(tp, 0x06, 0xef32); - rtl8168_mdio_write(tp, 0x06, 0x5b80); - rtl8168_mdio_write(tp, 0x06, 0xe3f8); - rtl8168_mdio_write(tp, 0x06, 0x7d9e); - rtl8168_mdio_write(tp, 0x06, 0x037d); - rtl8168_mdio_write(tp, 0x06, 0xffff); - rtl8168_mdio_write(tp, 0x06, 0x0d58); - rtl8168_mdio_write(tp, 0x06, 0x1c55); - rtl8168_mdio_write(tp, 0x06, 0x1a65); - rtl8168_mdio_write(tp, 0x06, 0x11a1); - rtl8168_mdio_write(tp, 0x06, 0x90d3); - rtl8168_mdio_write(tp, 0x06, 0xe283); - rtl8168_mdio_write(tp, 0x06, 0x48e3); - rtl8168_mdio_write(tp, 0x06, 0x8349); - rtl8168_mdio_write(tp, 0x06, 0x1b56); - rtl8168_mdio_write(tp, 0x06, 0xab08); - rtl8168_mdio_write(tp, 0x06, 0xef56); - rtl8168_mdio_write(tp, 0x06, 0xe683); - rtl8168_mdio_write(tp, 0x06, 0x48e7); - rtl8168_mdio_write(tp, 0x06, 0x8349); - rtl8168_mdio_write(tp, 0x06, 0x10d1); - rtl8168_mdio_write(tp, 0x06, 0x801f); - rtl8168_mdio_write(tp, 0x06, 0x66a0); - rtl8168_mdio_write(tp, 0x06, 0x04b9); - rtl8168_mdio_write(tp, 0x06, 0xe283); - rtl8168_mdio_write(tp, 0x06, 0x48e3); - rtl8168_mdio_write(tp, 0x06, 0x8349); - rtl8168_mdio_write(tp, 0x06, 0xef65); - rtl8168_mdio_write(tp, 0x06, 0xe283); - rtl8168_mdio_write(tp, 0x06, 0x4ae3); - rtl8168_mdio_write(tp, 0x06, 0x834b); - rtl8168_mdio_write(tp, 0x06, 0x1b56); - rtl8168_mdio_write(tp, 0x06, 0xaa0e); - rtl8168_mdio_write(tp, 0x06, 0xef56); - rtl8168_mdio_write(tp, 0x06, 0xe683); - rtl8168_mdio_write(tp, 0x06, 0x4ae7); - rtl8168_mdio_write(tp, 0x06, 0x834b); - rtl8168_mdio_write(tp, 0x06, 0xe283); - rtl8168_mdio_write(tp, 0x06, 0x4de6); - rtl8168_mdio_write(tp, 0x06, 0x834c); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4da0); - rtl8168_mdio_write(tp, 0x06, 0x000c); - rtl8168_mdio_write(tp, 0x06, 0xaf81); - rtl8168_mdio_write(tp, 0x06, 0x8be0); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0xae04); - rtl8168_mdio_write(tp, 0x06, 0x80e4); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x0be0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7804); - rtl8168_mdio_write(tp, 0x06, 0x9e04); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4e02); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x32e1); - rtl8168_mdio_write(tp, 0x06, 0x8333); - rtl8168_mdio_write(tp, 0x06, 0x590f); - rtl8168_mdio_write(tp, 0x06, 0xe283); - rtl8168_mdio_write(tp, 0x06, 0x4d0c); - rtl8168_mdio_write(tp, 0x06, 0x245a); - rtl8168_mdio_write(tp, 0x06, 0xf01e); - rtl8168_mdio_write(tp, 0x06, 0x12e4); - rtl8168_mdio_write(tp, 0x06, 0xf88c); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x8de0); - rtl8168_mdio_write(tp, 0x06, 0x8330); - rtl8168_mdio_write(tp, 0x06, 0xe183); - rtl8168_mdio_write(tp, 0x06, 0x3168); - rtl8168_mdio_write(tp, 0x06, 0x01e4); - rtl8168_mdio_write(tp, 0x06, 0xf88a); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x8bae); - rtl8168_mdio_write(tp, 0x06, 0x37ee); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x03e0); - rtl8168_mdio_write(tp, 0x06, 0x834c); - rtl8168_mdio_write(tp, 0x06, 0xe183); - rtl8168_mdio_write(tp, 0x06, 0x4d1b); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x04aa); - rtl8168_mdio_write(tp, 0x06, 0xa1ae); - rtl8168_mdio_write(tp, 0x06, 0xa8ee); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x834f); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0xabe0); - rtl8168_mdio_write(tp, 0x06, 0x834f); - rtl8168_mdio_write(tp, 0x06, 0x7803); - rtl8168_mdio_write(tp, 0x06, 0x9f14); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4e05); - rtl8168_mdio_write(tp, 0x06, 0xd240); - rtl8168_mdio_write(tp, 0x06, 0xd655); - rtl8168_mdio_write(tp, 0x06, 0x5402); - rtl8168_mdio_write(tp, 0x06, 0x81c6); - rtl8168_mdio_write(tp, 0x06, 0xd2a0); - rtl8168_mdio_write(tp, 0x06, 0xd6ba); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x81c6); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc05); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0xf860); - rtl8168_mdio_write(tp, 0x06, 0xe1f8); - rtl8168_mdio_write(tp, 0x06, 0x6168); - rtl8168_mdio_write(tp, 0x06, 0x02e4); - rtl8168_mdio_write(tp, 0x06, 0xf860); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x61e0); - rtl8168_mdio_write(tp, 0x06, 0xf848); - rtl8168_mdio_write(tp, 0x06, 0xe1f8); - rtl8168_mdio_write(tp, 0x06, 0x4958); - rtl8168_mdio_write(tp, 0x06, 0x0f1e); - rtl8168_mdio_write(tp, 0x06, 0x02e4); - rtl8168_mdio_write(tp, 0x06, 0xf848); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x49d0); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x820a); - rtl8168_mdio_write(tp, 0x06, 0xbf83); - rtl8168_mdio_write(tp, 0x06, 0x50ef); - rtl8168_mdio_write(tp, 0x06, 0x46dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0xd001); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x0a02); - rtl8168_mdio_write(tp, 0x06, 0x8226); - rtl8168_mdio_write(tp, 0x06, 0xe0f8); - rtl8168_mdio_write(tp, 0x06, 0x60e1); - rtl8168_mdio_write(tp, 0x06, 0xf861); - rtl8168_mdio_write(tp, 0x06, 0x58fd); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x60e5); - rtl8168_mdio_write(tp, 0x06, 0xf861); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xfbc6); - rtl8168_mdio_write(tp, 0x06, 0xbff8); - rtl8168_mdio_write(tp, 0x06, 0x40be); - rtl8168_mdio_write(tp, 0x06, 0x8350); - rtl8168_mdio_write(tp, 0x06, 0xa001); - rtl8168_mdio_write(tp, 0x06, 0x0107); - rtl8168_mdio_write(tp, 0x06, 0x1b89); - rtl8168_mdio_write(tp, 0x06, 0xcfd2); - rtl8168_mdio_write(tp, 0x06, 0x08eb); - rtl8168_mdio_write(tp, 0x06, 0xdb19); - rtl8168_mdio_write(tp, 0x06, 0xb2fb); - rtl8168_mdio_write(tp, 0x06, 0xfffe); - rtl8168_mdio_write(tp, 0x06, 0xfd04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0xf848); - rtl8168_mdio_write(tp, 0x06, 0xe1f8); - rtl8168_mdio_write(tp, 0x06, 0x4968); - rtl8168_mdio_write(tp, 0x06, 0x08e4); - rtl8168_mdio_write(tp, 0x06, 0xf848); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x4958); - rtl8168_mdio_write(tp, 0x06, 0xf7e4); - rtl8168_mdio_write(tp, 0x06, 0xf848); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x49fc); - rtl8168_mdio_write(tp, 0x06, 0x044d); - rtl8168_mdio_write(tp, 0x06, 0x2000); - rtl8168_mdio_write(tp, 0x06, 0x024e); - rtl8168_mdio_write(tp, 0x06, 0x2200); - rtl8168_mdio_write(tp, 0x06, 0x024d); - rtl8168_mdio_write(tp, 0x06, 0xdfff); - rtl8168_mdio_write(tp, 0x06, 0x014e); - rtl8168_mdio_write(tp, 0x06, 0xddff); - rtl8168_mdio_write(tp, 0x06, 0x01f8); - rtl8168_mdio_write(tp, 0x06, 0xfafb); - rtl8168_mdio_write(tp, 0x06, 0xef79); - rtl8168_mdio_write(tp, 0x06, 0xbff8); - rtl8168_mdio_write(tp, 0x06, 0x22d8); - rtl8168_mdio_write(tp, 0x06, 0x19d9); - rtl8168_mdio_write(tp, 0x06, 0x5884); - rtl8168_mdio_write(tp, 0x06, 0x9f09); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0x6dd6); - rtl8168_mdio_write(tp, 0x06, 0x8275); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x4fef); - rtl8168_mdio_write(tp, 0x06, 0x97ff); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x0517); - rtl8168_mdio_write(tp, 0x06, 0xfffe); - rtl8168_mdio_write(tp, 0x06, 0x0117); - rtl8168_mdio_write(tp, 0x06, 0x0001); - rtl8168_mdio_write(tp, 0x06, 0x0200); - rtl8168_mdio_write(tp, 0x05, 0x83d8); - rtl8168_mdio_write(tp, 0x06, 0x8000); - rtl8168_mdio_write(tp, 0x05, 0x83d6); - rtl8168_mdio_write(tp, 0x06, 0x824f); - rtl8168_mdio_write(tp, 0x02, 0x2010); - rtl8168_mdio_write(tp, 0x03, 0xdc00); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x0b, 0x0600); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00fc); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0xF880); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_11) { - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x10, 0x0008); - rtl8168_mdio_write(tp, 0x0D, 0x006C); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0B, 0xA4D8); - rtl8168_mdio_write(tp, 0x09, 0x281C); - rtl8168_mdio_write(tp, 0x07, 0x2883); - rtl8168_mdio_write(tp, 0x0A, 0x6B35); - rtl8168_mdio_write(tp, 0x1D, 0x3DA4); - rtl8168_mdio_write(tp, 0x1C, 0xEFFD); - rtl8168_mdio_write(tp, 0x14, 0x7F52); - rtl8168_mdio_write(tp, 0x18, 0x7FC6); - rtl8168_mdio_write(tp, 0x08, 0x0601); - rtl8168_mdio_write(tp, 0x06, 0x4063); - rtl8168_mdio_write(tp, 0x10, 0xF074); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x13, 0x0789); - rtl8168_mdio_write(tp, 0x12, 0xF4BD); - rtl8168_mdio_write(tp, 0x1A, 0x04FD); - rtl8168_mdio_write(tp, 0x14, 0x84B0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x01, 0x0340); - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x04, 0x4000); - rtl8168_mdio_write(tp, 0x03, 0x1D21); - rtl8168_mdio_write(tp, 0x02, 0x0C32); - rtl8168_mdio_write(tp, 0x01, 0x0200); - rtl8168_mdio_write(tp, 0x00, 0x5554); - rtl8168_mdio_write(tp, 0x04, 0x4800); - rtl8168_mdio_write(tp, 0x04, 0x4000); - rtl8168_mdio_write(tp, 0x04, 0xF000); - rtl8168_mdio_write(tp, 0x03, 0xDF01); - rtl8168_mdio_write(tp, 0x02, 0xDF20); - rtl8168_mdio_write(tp, 0x01, 0x101A); - rtl8168_mdio_write(tp, 0x00, 0xA0FF); - rtl8168_mdio_write(tp, 0x04, 0xF800); - rtl8168_mdio_write(tp, 0x04, 0xF000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - gphy_val = rtl8168_mdio_read(tp, 0x0D); - gphy_val |= BIT_5; - rtl8168_mdio_write(tp, 0x0D, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0C); - gphy_val |= BIT_10; - rtl8168_mdio_write(tp, 0x0C, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_12) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x0D); - gphy_val |= BIT_5; - rtl8168_mdio_write(tp, 0x0D, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0C); - gphy_val |= BIT_10; - rtl8168_mdio_write(tp, 0x0C, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - rtl8168_mdio_write(tp, 0x15, 0x035D); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x01, 0x0300); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_13) { - rtl8168_mdio_write(tp, 0x1F, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x0D); - gphy_val |= BIT_5; - rtl8168_mdio_write(tp, 0x0D, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0C); - gphy_val |= BIT_10; - rtl8168_mdio_write(tp, 0x0C, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_14 || tp->mcfg == CFG_METHOD_15) { - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17) | BIT_1; - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~(BIT_2); - else - gphy_val |= (BIT_2); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b80); - rtl8168_mdio_write(tp, 0x06, 0xc896); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0B, 0x6C20); - rtl8168_mdio_write(tp, 0x07, 0x2872); - rtl8168_mdio_write(tp, 0x1C, 0xEFFF); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x14, 0x6420); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x08) & 0x00FF; - rtl8168_mdio_write(tp, 0x08, gphy_val | 0x8000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - rtl8168_mdio_write(tp, 0x18, gphy_val | 0x0010); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x14); - rtl8168_mdio_write(tp, 0x14, gphy_val | 0x8000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x00, 0x080B); - rtl8168_mdio_write(tp, 0x0B, 0x09D7); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x1006); - } - } - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x19, 0x7F46); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8AD2); - rtl8168_mdio_write(tp, 0x06, 0x6810); - rtl8168_mdio_write(tp, 0x05, 0x8AD4); - rtl8168_mdio_write(tp, 0x06, 0x8002); - rtl8168_mdio_write(tp, 0x05, 0x8ADE); - rtl8168_mdio_write(tp, 0x06, 0x8025); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002F); - rtl8168_mdio_write(tp, 0x15, 0x1919); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - rtl8168_mdio_write(tp, 0x18, gphy_val | 0x0040); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - rtl8168_mdio_write(tp, 0x06, gphy_val | 0x0001); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x00AC); - rtl8168_mdio_write(tp, 0x18, 0x0006); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_16) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_2 | BIT_1; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x18, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x14); - gphy_val |= BIT_15; - rtl8168_mdio_write(tp, 0x14, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x1006); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0B, 0x6C14); - rtl8168_mdio_write(tp, 0x14, 0x7F3D); - rtl8168_mdio_write(tp, 0x1C, 0xFAFE); - rtl8168_mdio_write(tp, 0x08, 0x07C5); - rtl8168_mdio_write(tp, 0x10, 0xF090); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x14, 0x641A); - rtl8168_mdio_write(tp, 0x1A, 0x0606); - rtl8168_mdio_write(tp, 0x12, 0xF480); - rtl8168_mdio_write(tp, 0x13, 0x0747); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0004); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0078); - rtl8168_mdio_write(tp, 0x15, 0xA408); - rtl8168_mdio_write(tp, 0x17, 0x5100); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x0D, 0x0207); - rtl8168_mdio_write(tp, 0x02, 0x5FD0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0004); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x00A1); - gphy_val = rtl8168_mdio_read(tp, 0x1A); - gphy_val &= ~BIT_2; - rtl8168_mdio_write(tp, 0x1A, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0004); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x16); - gphy_val |= BIT_5; - rtl8168_mdio_write(tp, 0x16, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0004); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x00AC); - rtl8168_mdio_write(tp, 0x18, 0x0006); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x09, 0xA20F); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B5B); - rtl8168_mdio_write(tp, 0x06, 0x9222); - rtl8168_mdio_write(tp, 0x05, 0x8B6D); - rtl8168_mdio_write(tp, 0x06, 0x8000); - rtl8168_mdio_write(tp, 0x05, 0x8B76); - rtl8168_mdio_write(tp, 0x06, 0x8000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (pdev->subsystem_vendor == 0x1043 && - pdev->subsystem_device == 0x13F7) { - - static const u16 evl_phy_value[] = { - 0x8B56, 0x8B5F, 0x8B68, 0x8B71, - 0x8B7A, 0x8A7B, 0x8A7E, 0x8A81, - 0x8A84, 0x8A87 - }; - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - for (i = 0; i < ARRAY_SIZE(evl_phy_value); i++) { - rtl8168_mdio_write(tp, 0x05, evl_phy_value[i]); - gphy_val = (0xAA << 8) | (rtl8168_mdio_read(tp, 0x06) & 0xFF); - rtl8168_mdio_write(tp, 0x06, gphy_val); - } - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0078); - rtl8168_mdio_write(tp, 0x17, 0x51AA); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B54); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8B5D); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8A7C); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A7F); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A82); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A88); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - gphy_val = rtl8168_mdio_read(tp, 0x06) | BIT_14 | BIT_15; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } else if (tp->mcfg == CFG_METHOD_17) { - if (pdev->subsystem_vendor == 0x144d && - pdev->subsystem_device == 0xc0a6) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0e, 0x6b7f); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_2 | BIT_1; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val &= ~BIT_4; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x18, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x14); - gphy_val |= BIT_15; - rtl8168_mdio_write(tp, 0x14, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0004); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x00AC); - rtl8168_mdio_write(tp, 0x18, 0x0006); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x09, 0xA20F); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - gphy_val = rtl8168_mdio_read(tp, 0x06) | BIT_14 | BIT_15; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B5B); - rtl8168_mdio_write(tp, 0x06, 0x9222); - rtl8168_mdio_write(tp, 0x05, 0x8B6D); - rtl8168_mdio_write(tp, 0x06, 0x8000); - rtl8168_mdio_write(tp, 0x05, 0x8B76); - rtl8168_mdio_write(tp, 0x06, 0x8000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (pdev->subsystem_vendor == 0x1043 && - pdev->subsystem_device == 0x13F7) { - - static const u16 evl_phy_value[] = { - 0x8B56, 0x8B5F, 0x8B68, 0x8B71, - 0x8B7A, 0x8A7B, 0x8A7E, 0x8A81, - 0x8A84, 0x8A87 - }; - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - for (i = 0; i < ARRAY_SIZE(evl_phy_value); i++) { - rtl8168_mdio_write(tp, 0x05, evl_phy_value[i]); - gphy_val = (0xAA << 8) | (rtl8168_mdio_read(tp, 0x06) & 0xFF); - rtl8168_mdio_write(tp, 0x06, gphy_val); - } - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0078); - rtl8168_mdio_write(tp, 0x17, 0x51AA); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B54); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8B5D); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8A7C); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A7F); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A82); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A88); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val |= BIT_12; - rtl8168_mdio_write(tp, 0x15, gphy_val); - } - } - } else if (tp->mcfg == CFG_METHOD_18) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_2 | BIT_1; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x18, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x14); - gphy_val |= BIT_15; - rtl8168_mdio_write(tp, 0x14, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_14; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x09, 0xA20F); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B55); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8B5E); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8B67); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8B70); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0078); - rtl8168_mdio_write(tp, 0x17, 0x0000); - rtl8168_mdio_write(tp, 0x19, 0x00FB); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B79); - rtl8168_mdio_write(tp, 0x06, 0xAA00); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0003); - rtl8168_mdio_write(tp, 0x01, 0x328A); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B54); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8B5D); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8A7C); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A7F); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A82); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A88); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_15); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val |= BIT_12; - rtl8168_mdio_write(tp, 0x15, gphy_val); - } - } - } else if (tp->mcfg == CFG_METHOD_19) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_2 | BIT_1; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x18, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x14); - gphy_val |= BIT_15; - rtl8168_mdio_write(tp, 0x14, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B54); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8B5D); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8A7C); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A7F); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A82); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A88); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_15); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val |= BIT_12; - rtl8168_mdio_write(tp, 0x15, gphy_val); - } - } - } else if (tp->mcfg == CFG_METHOD_20) { - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_2 | BIT_1; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x18, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x14); - gphy_val |= BIT_15; - rtl8168_mdio_write(tp, 0x14, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_14; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x09, 0xA20F); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B55); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8B5E); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8B67); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8B70); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0078); - rtl8168_mdio_write(tp, 0x17, 0x0000); - rtl8168_mdio_write(tp, 0x19, 0x00FB); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B79); - rtl8168_mdio_write(tp, 0x06, 0xAA00); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B54); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8B5D); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8A7C); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A7F); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A82); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A88); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_15); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val |= BIT_12; - rtl8168_mdio_write(tp, 0x15, gphy_val); - } - } - } else if (tp->mcfg == CFG_METHOD_21) { - rtl8168_mdio_write(tp, 0x1F, 0x0A46); - gphy_val = rtl8168_mdio_read(tp, 0x10); - rtl8168_mdio_write(tp, 0x1F, 0x0BCC); - if (gphy_val & BIT_8) - rtl8168_clear_eth_phy_bit(tp, 0x12, BIT_15); - else - rtl8168_set_eth_phy_bit(tp, 0x12, BIT_15); - rtl8168_mdio_write(tp, 0x1F, 0x0A46); - gphy_val = rtl8168_mdio_read(tp, 0x13); - rtl8168_mdio_write(tp, 0x1F, 0x0C41); - if (gphy_val & BIT_8) - rtl8168_set_eth_phy_bit(tp, 0x15, BIT_1); - else - rtl8168_clear_eth_phy_bit(tp, 0x15, BIT_1); - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_2 | BIT_3); - - rtl8168_mdio_write(tp, 0x1F, 0x0BCC); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_7); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_6); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8084); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~(BIT_14 | BIT_13)); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_12); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_1); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_0); - - rtl8168_mdio_write(tp, 0x1F, 0x0A4B); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_2); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8012); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | BIT_15); - - rtl8168_mdio_write(tp, 0x1F, 0x0C42); - gphy_val = rtl8168_mdio_read(tp, 0x11); - gphy_val |= BIT_14; - gphy_val &= ~BIT_13; - rtl8168_mdio_write(tp, 0x11, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x809A); - rtl8168_mdio_write(tp, 0x14, 0x8022); - rtl8168_mdio_write(tp, 0x13, 0x80A0); - gphy_val = rtl8168_mdio_read(tp, 0x14) & 0x00FF; - gphy_val |= 0x1000; - rtl8168_mdio_write(tp, 0x14, gphy_val); - rtl8168_mdio_write(tp, 0x13, 0x8088); - rtl8168_mdio_write(tp, 0x14, 0x9222); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_2); - } - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_22) { - //do nothing - } else if (tp->mcfg == CFG_METHOD_23) { - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | (BIT_3 | BIT_2)); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0BCC); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_7); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_6); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8084); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~(BIT_14 | BIT_13)); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_12); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_1); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_0); - - rtl8168_mdio_write(tp, 0x1F, 0x0A4B); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_2); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8012); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | BIT_15); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0C42); - ClearAndSetEthPhyBit(tp, - 0x11, - BIT_13, - BIT_14 - ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_2); - } - } - } else if (tp->mcfg == CFG_METHOD_24) { - rtl8168_mdio_write(tp, 0x1F, 0x0BCC); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_7); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_6); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8084); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~(BIT_14 | BIT_13)); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_12); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_1); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_0); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8012); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | BIT_15); - - rtl8168_mdio_write(tp, 0x1F, 0x0C42); - gphy_val = rtl8168_mdio_read(tp, 0x11); - gphy_val |= BIT_14; - gphy_val &= ~BIT_13; - rtl8168_mdio_write(tp, 0x11, gphy_val); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_2); - } - } - } else if (tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26) { - rtl8168_mdio_write(tp, 0x1F, 0x0BCC); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_7); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_6); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8084); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~(BIT_14 | BIT_13)); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_12); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_1); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_0); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8012); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | BIT_15); - - rtl8168_mdio_write(tp, 0x1F, 0x0BCE); - rtl8168_mdio_write(tp, 0x12, 0x8860); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x80F3); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x8B00); - rtl8168_mdio_write(tp, 0x13, 0x80F0); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x3A00); - rtl8168_mdio_write(tp, 0x13, 0x80EF); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x0500); - rtl8168_mdio_write(tp, 0x13, 0x80F6); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x6E00); - rtl8168_mdio_write(tp, 0x13, 0x80EC); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x6800); - rtl8168_mdio_write(tp, 0x13, 0x80ED); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x7C00); - rtl8168_mdio_write(tp, 0x13, 0x80F2); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xF400); - rtl8168_mdio_write(tp, 0x13, 0x80F4); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x8500); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8110); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xA800); - rtl8168_mdio_write(tp, 0x13, 0x810F); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x1D00); - rtl8168_mdio_write(tp, 0x13, 0x8111); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xF500); - rtl8168_mdio_write(tp, 0x13, 0x8113); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x6100); - rtl8168_mdio_write(tp, 0x13, 0x8115); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x9200); - rtl8168_mdio_write(tp, 0x13, 0x810E); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x0400); - rtl8168_mdio_write(tp, 0x13, 0x810C); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x7C00); - rtl8168_mdio_write(tp, 0x13, 0x810B); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x5A00); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x80D1); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xFF00); - rtl8168_mdio_write(tp, 0x13, 0x80CD); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x9E00); - rtl8168_mdio_write(tp, 0x13, 0x80D3); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x0E00); - rtl8168_mdio_write(tp, 0x13, 0x80D5); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xCA00); - rtl8168_mdio_write(tp, 0x13, 0x80D7); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x8400); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_2); - } - } - } else if (tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28) { - rtl8168_mdio_write(tp, 0x1F, 0x0BCC); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_7); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_6); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8084); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~(BIT_14 | BIT_13)); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_12); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_1); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_0); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8012); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | BIT_15); - - rtl8168_mdio_write(tp, 0x1F, 0x0C42); - rtl8168_mdio_write(tp, 0x11, (rtl8168_mdio_read(tp, 0x11) & ~BIT_13) | BIT_14); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x80F3); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x8B00); - rtl8168_mdio_write(tp, 0x13, 0x80F0); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x3A00); - rtl8168_mdio_write(tp, 0x13, 0x80EF); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x0500); - rtl8168_mdio_write(tp, 0x13, 0x80F6); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x6E00); - rtl8168_mdio_write(tp, 0x13, 0x80EC); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x6800); - rtl8168_mdio_write(tp, 0x13, 0x80ED); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x7C00); - rtl8168_mdio_write(tp, 0x13, 0x80F2); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xF400); - rtl8168_mdio_write(tp, 0x13, 0x80F4); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x8500); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8110); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xA800); - rtl8168_mdio_write(tp, 0x13, 0x810F); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x1D00); - rtl8168_mdio_write(tp, 0x13, 0x8111); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xF500); - rtl8168_mdio_write(tp, 0x13, 0x8113); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x6100); - rtl8168_mdio_write(tp, 0x13, 0x8115); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x9200); - rtl8168_mdio_write(tp, 0x13, 0x810E); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x0400); - rtl8168_mdio_write(tp, 0x13, 0x810C); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x7C00); - rtl8168_mdio_write(tp, 0x13, 0x810B); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x5A00); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x80D1); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xFF00); - rtl8168_mdio_write(tp, 0x13, 0x80CD); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x9E00); - rtl8168_mdio_write(tp, 0x13, 0x80D3); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x0E00); - rtl8168_mdio_write(tp, 0x13, 0x80D5); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xCA00); - rtl8168_mdio_write(tp, 0x13, 0x80D7); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x8400); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_2); - } - } - } else if (tp->mcfg == CFG_METHOD_29) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x809b); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xF800 , - 0x8000 - ); - rtl8168_mdio_write(tp, 0x13, 0x80A2); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x8000 - ); - rtl8168_mdio_write(tp, 0x13, 0x80A4); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x8500 - ); - rtl8168_mdio_write(tp, 0x13, 0x809C); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0xbd00 - ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x80AD); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xF800 , - 0x7000 - ); - rtl8168_mdio_write(tp, 0x13, 0x80B4); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x5000 - ); - rtl8168_mdio_write(tp, 0x13, 0x80AC); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x4000 - ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x808E); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x1200 - ); - rtl8168_mdio_write(tp, 0x13, 0x8090); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0xE500 - ); - rtl8168_mdio_write(tp, 0x13, 0x8092); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x9F00 - ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - u16 dout_tapbin; - - dout_tapbin = 0x0000; - rtl8168_mdio_write( tp, 0x1F, 0x0A46 ); - gphy_val = rtl8168_mdio_read( tp, 0x13 ); - gphy_val &= (BIT_1|BIT_0); - gphy_val <<= 2; - dout_tapbin |= gphy_val; - - gphy_val = rtl8168_mdio_read( tp, 0x12 ); - gphy_val &= (BIT_15|BIT_14); - gphy_val >>= 14; - dout_tapbin |= gphy_val; - - dout_tapbin = ~( dout_tapbin^BIT_3 ); - dout_tapbin <<= 12; - dout_tapbin &= 0xF000; - - rtl8168_mdio_write( tp, 0x1F, 0x0A43 ); - - rtl8168_mdio_write( tp, 0x13, 0x827A ); - ClearAndSetEthPhyBit( tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_12, - dout_tapbin - ); - - - rtl8168_mdio_write( tp, 0x13, 0x827B ); - ClearAndSetEthPhyBit( tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_12, - dout_tapbin - ); - - - rtl8168_mdio_write( tp, 0x13, 0x827C ); - ClearAndSetEthPhyBit( tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_12, - dout_tapbin - ); - - - rtl8168_mdio_write( tp, 0x13, 0x827D ); - ClearAndSetEthPhyBit( tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_12, - dout_tapbin - ); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_11); - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - rtl8168_set_eth_phy_bit(tp, 0x16, BIT_1); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_set_eth_phy_bit( tp, 0x11, BIT_11 ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - - rtl8168_mdio_write(tp, 0x1F, 0x0BCA); - ClearAndSetEthPhyBit( tp, - 0x17, - (BIT_13 | BIT_12) , - BIT_14 - ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x803F); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x13, 0x8047); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x13, 0x804F); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x13, 0x8057); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x13, 0x805F); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x13, 0x8067 ); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x13, 0x806F ); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_set_eth_phy_bit( tp, 0x10, BIT_2 ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - } - } else if (tp->mcfg == CFG_METHOD_30) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x808A); - ClearAndSetEthPhyBit( tp, - 0x14, - BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0, - 0x0A ); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_11); - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - rtl8168_set_eth_phy_bit(tp, 0x16, BIT_1); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_set_eth_phy_bit( tp, 0x11, BIT_11 ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (tp->RequireAdcBiasPatch) { - rtl8168_mdio_write(tp, 0x1F, 0x0BCF); - rtl8168_mdio_write(tp, 0x16, tp->AdcBiasPatchIoffset); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - { - u16 rlen; - - rtl8168_mdio_write(tp, 0x1F, 0x0BCD); - gphy_val = rtl8168_mdio_read( tp, 0x16 ); - gphy_val &= 0x000F; - - if ( gphy_val > 3 ) { - rlen = gphy_val - 3; - } else { - rlen = 0; - } - - gphy_val = rlen | (rlen<<4) | (rlen<<8) | (rlen<<12); - - rtl8168_mdio_write(tp, 0x1F, 0x0BCD); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x85FE); - ClearAndSetEthPhyBit( - tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_12|BIT_11|BIT_10|BIT_8, - BIT_9); - rtl8168_mdio_write(tp, 0x13, 0x85FF); - ClearAndSetEthPhyBit( - tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_12, - BIT_11|BIT_10|BIT_9|BIT_8); - rtl8168_mdio_write(tp, 0x13, 0x814B); - ClearAndSetEthPhyBit( - tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_11|BIT_10|BIT_9|BIT_8, - BIT_12); - } - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_set_eth_phy_bit( tp, 0x10, BIT_2 ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - } - } else if (tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x808E); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x4800 - ); - rtl8168_mdio_write(tp, 0x13, 0x8090); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0xCC00 - ); - rtl8168_mdio_write(tp, 0x13, 0x8092); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0xB000 - ); - rtl8168_mdio_write(tp, 0x13, 0x8088); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x6000 - ); - rtl8168_mdio_write(tp, 0x13, 0x808B); - ClearAndSetEthPhyBit( tp, - 0x14, - 0x3F00 , - 0x0B00 - ); - rtl8168_mdio_write(tp, 0x13, 0x808D); - ClearAndSetEthPhyBit( tp, - 0x14, - 0x1F00 , - 0x0600 - ); - rtl8168_mdio_write(tp, 0x13, 0x808C); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0xB000 - ); - - rtl8168_mdio_write(tp, 0x13, 0x80A0); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x2800 - ); - rtl8168_mdio_write(tp, 0x13, 0x80A2); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x5000 - ); - rtl8168_mdio_write(tp, 0x13, 0x809B); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xF800 , - 0xB000 - ); - rtl8168_mdio_write(tp, 0x13, 0x809A); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x4B00 - ); - rtl8168_mdio_write(tp, 0x13, 0x809D); - ClearAndSetEthPhyBit( tp, - 0x14, - 0x3F00 , - 0x0800 - ); - rtl8168_mdio_write(tp, 0x13, 0x80A1); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x7000 - ); - rtl8168_mdio_write(tp, 0x13, 0x809F); - ClearAndSetEthPhyBit( tp, - 0x14, - 0x1F00 , - 0x0300 - ); - rtl8168_mdio_write(tp, 0x13, 0x809E); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x8800 - ); - - rtl8168_mdio_write(tp, 0x13, 0x80B2); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x2200 - ); - rtl8168_mdio_write(tp, 0x13, 0x80AD); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xF800 , - 0x9800 - ); - rtl8168_mdio_write(tp, 0x13, 0x80AF); - ClearAndSetEthPhyBit( tp, - 0x14, - 0x3F00 , - 0x0800 - ); - rtl8168_mdio_write(tp, 0x13, 0x80B3); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x6F00 - ); - rtl8168_mdio_write(tp, 0x13, 0x80B1); - ClearAndSetEthPhyBit( tp, - 0x14, - 0x1F00 , - 0x0300 - ); - rtl8168_mdio_write(tp, 0x13, 0x80B0); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x9300 - ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_11); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_set_eth_phy_bit(tp, 0x11, BIT_11); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8016); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_10); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (aspm) { - if (!HW_SUPP_SERDES_PHY(tp) && - HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_set_eth_phy_bit( tp, 0x10, BIT_2 ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - } - } - -#ifdef ENABLE_FIBER_SUPPORT - if (HW_FIBER_MODE_ENABLED(tp)) - rtl8168_hw_fiber_phy_config(dev); -#endif //ENABLE_FIBER_SUPPORT - - //EthPhyPPSW - if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_24 || tp->mcfg == CFG_METHOD_25 || - tp->mcfg == CFG_METHOD_26) { - //disable EthPhyPPSW - rtl8168_mdio_write(tp, 0x1F, 0x0BCD); - rtl8168_mdio_write(tp, 0x14, 0x5065); - rtl8168_mdio_write(tp, 0x14, 0xD065); - rtl8168_mdio_write(tp, 0x1F, 0x0BC8); - rtl8168_mdio_write(tp, 0x11, 0x5655); - rtl8168_mdio_write(tp, 0x1F, 0x0BCD); - rtl8168_mdio_write(tp, 0x14, 0x1065); - rtl8168_mdio_write(tp, 0x14, 0x9065); - rtl8168_mdio_write(tp, 0x14, 0x1065); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - //enable EthPhyPPSW - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_set_eth_phy_bit( tp, 0x11, BIT_7 ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - /*ocp phy power saving*/ - if (tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - if (aspm) - rtl8168_enable_ocp_phy_power_saving(dev); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - if (tp->eee_enabled) - rtl8168_enable_EEE(tp); - else - rtl8168_disable_EEE(tp); - } -} - -static inline void rtl8168_delete_esd_timer(struct net_device *dev, struct timer_list *timer) -{ - del_timer_sync(timer); -} - -static inline void rtl8168_request_esd_timer(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->esd_timer; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - setup_timer(timer, rtl8168_esd_timer, (unsigned long)dev); -#else - timer_setup(timer, rtl8168_esd_timer, 0); -#endif - mod_timer(timer, jiffies + RTL8168_ESD_TIMEOUT); -} - -static inline void rtl8168_delete_link_timer(struct net_device *dev, struct timer_list *timer) -{ - del_timer_sync(timer); -} - -static inline void rtl8168_request_link_timer(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->link_timer; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - setup_timer(timer, rtl8168_link_timer, (unsigned long)dev); -#else - timer_setup(timer, rtl8168_link_timer, 0); -#endif - mod_timer(timer, jiffies + RTL8168_LINK_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void -rtl8168_netpoll(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) - rtl8168_interrupt(pdev->irq, dev, NULL); -#else - rtl8168_interrupt(pdev->irq, dev); -#endif - enable_irq(pdev->irq); -} -#endif - -static void -rtl8168_get_bios_setting(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->bios_setting = RTL_R32(tp, 0x8c); - break; - } -} - -static void -rtl8168_set_bios_setting(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W32(tp, 0x8C, tp->bios_setting); - break; - } -} - -static void -rtl8168_init_software_variable(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8168_get_bios_setting(dev); - - switch (tp->mcfg) { - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - tp->HwSuppDashVer = 1; - break; - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - tp->HwSuppDashVer = 2; - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppDashVer = 3; - break; - default: - tp->HwSuppDashVer = 0; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwPkgDet = rtl8168_mac_ocp_read(tp, 0xDC00); - tp->HwPkgDet = (tp->HwPkgDet >> 3) & 0x0F; - break; - } - - if (HW_SUPP_SERDES_PHY(tp)) - eee_enable = 0; - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppNowIsOobVer = 1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppPhyOcpVer = 1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppUpsVer = 1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwPcieSNOffset = 0x16C; - break; - case CFG_METHOD_DEFAULT: - tp->HwPcieSNOffset = 0; - break; - default: - tp->HwPcieSNOffset = 0x164; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppAspmClkIntrLock = 1; - break; - } - - if (!aspm || !tp->HwSuppAspmClkIntrLock) - dynamic_aspm = 0; - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8168_get_realwow_hw_version(dev); -#endif //ENABLE_REALWOW_SUPPORT - - if (HW_DASH_SUPPORT_DASH(tp) && rtl8168_check_dash(tp)) - tp->DASH = 1; - else - tp->DASH = 0; - - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_3(tp)) { - u64 CmacMemPhysAddress; - void __iomem *cmac_ioaddr = NULL; - struct pci_dev *pdev_cmac; - - pdev_cmac = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 0)); - - //map CMAC IO space - CmacMemPhysAddress = pci_resource_start(pdev_cmac, 2); - - /* ioremap MMIO region */ - cmac_ioaddr = ioremap(CmacMemPhysAddress, R8168_REGS_SIZE); - - if (cmac_ioaddr == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap CMAC MMIO, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - tp->DASH = 0; - } else { - tp->mapped_cmac_ioaddr = cmac_ioaddr; - } - } - - eee_enable = 0; - } - -#ifdef ENABLE_DASH_SUPPORT -#ifdef ENABLE_DASH_PRINTER_SUPPORT - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x0F) - tp->dash_printer_enabled = 1; - else if (HW_DASH_SUPPORT_TYPE_2(tp)) - tp->dash_printer_enabled = 1; - } -#endif //ENABLE_DASH_PRINTER_SUPPORT -#endif //ENABLE_DASH_SUPPORT - - if (HW_DASH_SUPPORT_TYPE_2(tp)) - tp->cmac_ioaddr = tp->mmio_addr; - else if (HW_DASH_SUPPORT_TYPE_3(tp)) - tp->cmac_ioaddr = tp->mapped_cmac_ioaddr; - - switch (tp->mcfg) { - case CFG_METHOD_1: - tp->intr_mask = RxDescUnavail | RxFIFOOver | TxDescUnavail | TxOK | RxOK | SWInt; - tp->timer_intr_mask = PCSTimeout | RxFIFOOver; - break; - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - tp->intr_mask = RxDescUnavail | TxDescUnavail | TxOK | RxOK | SWInt; - tp->timer_intr_mask = PCSTimeout; - break; - default: - tp->intr_mask = RxDescUnavail | TxOK | RxOK | SWInt; - tp->timer_intr_mask = PCSTimeout; - break; - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - tp->timer_intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); - tp->intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); - } else { - tp->timer_intr_mask |= ( ISRIMR_DP_DASH_OK | ISRIMR_DP_HOST_OK | ISRIMR_DP_REQSYS_OK ); - tp->intr_mask |= ( ISRIMR_DP_DASH_OK | ISRIMR_DP_HOST_OK | ISRIMR_DP_REQSYS_OK ); - } - } -#endif - if (aspm) { - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->org_pci_offset_99 = rtl8168_csi_fun0_read_byte(tp, 0x99); - tp->org_pci_offset_99 &= ~(BIT_5|BIT_6); - break; - } - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - tp->org_pci_offset_180 = rtl8168_csi_fun0_read_byte(tp, 0x180); - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->org_pci_offset_180 = rtl8168_csi_fun0_read_byte(tp, 0x214); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_27: - case CFG_METHOD_28: - if (tp->org_pci_offset_99 & BIT_2) - tp->issue_offset_99_event = TRUE; - break; - } - } - - pci_read_config_byte(pdev, 0x80, &tp->org_pci_offset_80); - pci_read_config_byte(pdev, 0x81, &tp->org_pci_offset_81); - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - if ((tp->features & RTL_FEATURE_MSI) && (tp->org_pci_offset_80 & BIT_1)) - tp->use_timer_interrrupt = FALSE; - else - tp->use_timer_interrrupt = TRUE; - break; - default: - tp->use_timer_interrrupt = TRUE; - break; - } - - if (timer_count == 0 || tp->mcfg == CFG_METHOD_DEFAULT) - tp->use_timer_interrrupt = FALSE; - - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - tp->ShortPacketSwChecksum = TRUE; - break; - case CFG_METHOD_16: - case CFG_METHOD_17: - tp->ShortPacketSwChecksum = TRUE; - tp->UseSwPaddingShortPkt = TRUE; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_30: { - u16 ioffset_p3, ioffset_p2, ioffset_p1, ioffset_p0; - u16 TmpUshort; - - rtl8168_mac_ocp_write( tp, 0xDD02, 0x807D); - TmpUshort = rtl8168_mac_ocp_read( tp, 0xDD02 ); - ioffset_p3 = ( (TmpUshort & BIT_7) >>7 ); - ioffset_p3 <<= 3; - TmpUshort = rtl8168_mac_ocp_read( tp, 0xDD00 ); - - ioffset_p3 |= ((TmpUshort & (BIT_15 | BIT_14 | BIT_13))>>13); - - ioffset_p2 = ((TmpUshort & (BIT_12|BIT_11|BIT_10|BIT_9))>>9); - ioffset_p1 = ((TmpUshort & (BIT_8|BIT_7|BIT_6|BIT_5))>>5); - - ioffset_p0 = ( (TmpUshort & BIT_4) >>4 ); - ioffset_p0 <<= 3; - ioffset_p0 |= (TmpUshort & (BIT_2| BIT_1 | BIT_0)); - - if ((ioffset_p3 == 0x0F) && (ioffset_p2 == 0x0F) && (ioffset_p1 == 0x0F) && (ioffset_p0 == 0x0F)) { - tp->RequireAdcBiasPatch = FALSE; - } else { - tp->RequireAdcBiasPatch = TRUE; - tp->AdcBiasPatchIoffset = (ioffset_p3<<12)|(ioffset_p2<<8)|(ioffset_p1<<4)|(ioffset_p0); - } - } - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: { - u16 rg_saw_cnt; - - rtl8168_mdio_write(tp, 0x1F, 0x0C42); - rg_saw_cnt = rtl8168_mdio_read(tp, 0x13); - rg_saw_cnt &= ~(BIT_15|BIT_14); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if ( rg_saw_cnt > 0) { - tp->SwrCnt1msIni = 16000000/rg_saw_cnt; - tp->SwrCnt1msIni &= 0x0FFF; - - tp->RequireAdjustUpsTxLinkPulseTiming = TRUE; - } - } - break; - } - -#ifdef ENABLE_FIBER_SUPPORT - rtl8168_check_hw_fiber_mode_support(dev); -#endif //ENABLE_FIBER_SUPPORT - - switch(tp->mcfg) { - case CFG_METHOD_32: - case CFG_METHOD_33: - if (tp->HwPkgDet == 0x06) { - u8 tmpUchar = rtl8168_eri_read(tp, 0xE6, 1, ERIAR_ExGMAC); - if (tmpUchar == 0x02) - tp->HwSuppSerDesPhyVer = 1; - else if (tmpUchar == 0x00) - tp->HwSuppSerDesPhyVer = 2; - } - break; - } - - if (pdev->subsystem_vendor == 0x144d) { - if (pdev->subsystem_device == 0xc098 || - pdev->subsystem_device == 0xc0b1 || - pdev->subsystem_device == 0xc0b8) - hwoptimize |= HW_PATCH_SAMSUNG_LAN_DONGLE; - } - - if (hwoptimize & HW_PATCH_SAMSUNG_LAN_DONGLE) { - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_30: - tp->RequiredSecLanDonglePatch = TRUE; - break; - } - } - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_V2; - break; - case CFG_METHOD_DEFAULT: - tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_NOT_SUPPORT; - break; - default: - tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_V1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - tp->HwSuppEsdVer = 2; - break; - default: - tp->HwSuppEsdVer = 1; - break; - } - - if (tp->HwSuppEsdVer == 2) { - rtl8168_mdio_write(tp, 0x1F, 0x0A46); - tp->BackupPhyFuseDout_15_0 = rtl8168_mdio_read(tp, 0x10); - tp->BackupPhyFuseDout_47_32 = rtl8168_mdio_read(tp, 0x12); - tp->BackupPhyFuseDout_63_48 = rtl8168_mdio_read(tp, 0x13); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - tp->TestPhyOcpReg = TRUE; - } - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - tp->HwSuppCheckPhyDisableModeVer = 1; - break; - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - tp->HwSuppCheckPhyDisableModeVer = 2; - break; - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppCheckPhyDisableModeVer = 3; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_14; - break; - case CFG_METHOD_16: - case CFG_METHOD_17: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_16; - break; - case CFG_METHOD_18: - case CFG_METHOD_19: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_18; - break; - case CFG_METHOD_20: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_20; - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_21; - break; - case CFG_METHOD_23: - case CFG_METHOD_27: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_23; - break; - case CFG_METHOD_24: - case CFG_METHOD_25: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_24; - break; - case CFG_METHOD_26: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_26; - break; - case CFG_METHOD_28: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_28; - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_29; - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_31; - break; - } - - if (tp->HwIcVerUnknown) { - tp->NotWrRamCodeToMicroP = TRUE; - tp->NotWrMcuPatchCode = TRUE; - } - - tp->NicCustLedValue = RTL_R16(tp, CustomLED); - - rtl8168_get_hw_wol(dev); - - rtl8168_link_option((u8*)&autoneg_mode, (u32*)&speed_mode, (u8*)&duplex_mode, (u32*)&advertising_mode); - - tp->autoneg = autoneg_mode; - tp->speed = speed_mode; - tp->duplex = duplex_mode; - tp->advertising = advertising_mode; - - tp->max_jumbo_frame_size = rtl_chip_info[tp->chipset].jumbo_frame_sz; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - /* MTU range: 60 - hw-specific max */ - dev->min_mtu = ETH_MIN_MTU; - dev->max_mtu = tp->max_jumbo_frame_size; -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - tp->eee_enabled = eee_enable; - tp->eee_adv_t = MDIO_EEE_1000T | MDIO_EEE_100TX; - -#ifdef ENABLE_FIBER_SUPPORT - if (HW_FIBER_MODE_ENABLED(tp)) - rtl8168_set_fiber_mode_software_variable(dev); -#endif //ENABLE_FIBER_SUPPORT -} - -static void -rtl8168_release_board(struct pci_dev *pdev, - struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8168_set_bios_setting(dev); - rtl8168_rar_set(tp, tp->org_mac_addr); - tp->wol_enabled = WOL_DISABLED; - - if (!tp->DASH) - rtl8168_phy_power_down(dev); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - FreeAllocatedDashShareMemory(dev); -#endif - - if (tp->mapped_cmac_ioaddr != NULL) - iounmap(tp->mapped_cmac_ioaddr); - - iounmap(ioaddr); - pci_release_regions(pdev); - pci_clear_mwi(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static int -rtl8168_get_mac_address(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int i; - u8 mac_addr[MAC_ADDR_LEN]; - - for (i = 0; i < MAC_ADDR_LEN; i++) - mac_addr[i] = RTL_R8(tp, MAC0 + i); - - if (tp->mcfg == CFG_METHOD_18 || - tp->mcfg == CFG_METHOD_19 || - tp->mcfg == CFG_METHOD_20 || - tp->mcfg == CFG_METHOD_21 || - tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_23 || - tp->mcfg == CFG_METHOD_24 || - tp->mcfg == CFG_METHOD_25 || - tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || - tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || - tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || - tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - *(u32*)&mac_addr[0] = rtl8168_eri_read(tp, 0xE0, 4, ERIAR_ExGMAC); - *(u16*)&mac_addr[4] = rtl8168_eri_read(tp, 0xE4, 2, ERIAR_ExGMAC); - } else { - if (tp->eeprom_type != EEPROM_TYPE_NONE) { - u16 *pUshort = (u16*)mac_addr; - /* Get MAC address from EEPROM */ - if (tp->mcfg == CFG_METHOD_16 || - tp->mcfg == CFG_METHOD_17 || - tp->mcfg == CFG_METHOD_18 || - tp->mcfg == CFG_METHOD_19 || - tp->mcfg == CFG_METHOD_20 || - tp->mcfg == CFG_METHOD_21 || - tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_23 || - tp->mcfg == CFG_METHOD_24 || - tp->mcfg == CFG_METHOD_25 || - tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || - tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || - tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || - tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - *pUshort++ = rtl8168_eeprom_read_sc(tp, 1); - *pUshort++ = rtl8168_eeprom_read_sc(tp, 2); - *pUshort = rtl8168_eeprom_read_sc(tp, 3); - } else { - *pUshort++ = rtl8168_eeprom_read_sc(tp, 7); - *pUshort++ = rtl8168_eeprom_read_sc(tp, 8); - *pUshort = rtl8168_eeprom_read_sc(tp, 9); - } - } - } - - if (!is_valid_ether_addr(mac_addr)) { - netif_err(tp, probe, dev, "Invalid ether addr %pM\n", - mac_addr); - eth_hw_addr_random(dev); - ether_addr_copy(mac_addr, dev->dev_addr); - netif_info(tp, probe, dev, "Random ether addr %pM\n", - mac_addr); - tp->random_mac = 1; - } - - rtl8168_rar_set(tp, mac_addr); - - for (i = 0; i < MAC_ADDR_LEN; i++) { - dev->dev_addr[i] = RTL_R8(tp, MAC0 + i); - tp->org_mac_addr[i] = dev->dev_addr[i]; /* keep the original MAC address */ - } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); -#endif -// memcpy(dev->dev_addr, dev->dev_addr, dev->addr_len); - - return 0; -} - -/** - * rtl8168_set_mac_address - Change the Ethernet Address of the NIC - * @dev: network interface device structure - * @p: pointer to an address structure - * - * Return 0 on success, negative on failure - **/ -static int -rtl8168_set_mac_address(struct net_device *dev, - void *p) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - unsigned long flags; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - spin_lock_irqsave(&tp->lock, flags); - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl8168_rar_set(tp, dev->dev_addr); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -/****************************************************************************** - * rtl8168_rar_set - Puts an ethernet address into a receive address register. - * - * tp - The private data structure for driver - * addr - Address to put into receive address register - *****************************************************************************/ -void -rtl8168_rar_set(struct rtl8168_private *tp, - uint8_t *addr) -{ - uint32_t rar_low = 0; - uint32_t rar_high = 0; - - rar_low = ((uint32_t) addr[0] | - ((uint32_t) addr[1] << 8) | - ((uint32_t) addr[2] << 16) | - ((uint32_t) addr[3] << 24)); - - rar_high = ((uint32_t) addr[4] | - ((uint32_t) addr[5] << 8)); - - rtl8168_enable_cfg9346_write(tp); - RTL_W32(tp, MAC0, rar_low); - RTL_W32(tp, MAC4, rar_high); - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - RTL_W32(tp, SecMAC0, rar_low); - RTL_W16(tp, SecMAC4, (uint16_t)rar_high); - break; - } - - if (tp->mcfg == CFG_METHOD_17) { - rtl8168_eri_write(tp, 0xf0, 4, rar_low << 16, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xf4, 4, rar_low >> 16 | rar_high << 16, ERIAR_ExGMAC); - } - - rtl8168_disable_cfg9346_write(tp); -} - -#ifdef ETHTOOL_OPS_COMPAT -static int ethtool_get_settings(struct net_device *dev, void *useraddr) -{ - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - int err; - - if (!ethtool_ops->get_settings) - return -EOPNOTSUPP; - - err = ethtool_ops->get_settings(dev, &cmd); - if (err < 0) - return err; - - if (copy_to_user(useraddr, &cmd, sizeof(cmd))) - return -EFAULT; - return 0; -} - -static int ethtool_set_settings(struct net_device *dev, void *useraddr) -{ - struct ethtool_cmd cmd; - - if (!ethtool_ops->set_settings) - return -EOPNOTSUPP; - - if (copy_from_user(&cmd, useraddr, sizeof(cmd))) - return -EFAULT; - - return ethtool_ops->set_settings(dev, &cmd); -} - -static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr) -{ - struct ethtool_drvinfo info; - struct ethtool_ops *ops = ethtool_ops; - - if (!ops->get_drvinfo) - return -EOPNOTSUPP; - - memset(&info, 0, sizeof(info)); - info.cmd = ETHTOOL_GDRVINFO; - ops->get_drvinfo(dev, &info); - - if (ops->self_test_count) - info.testinfo_len = ops->self_test_count(dev); - if (ops->get_stats_count) - info.n_stats = ops->get_stats_count(dev); - if (ops->get_regs_len) - info.regdump_len = ops->get_regs_len(dev); - if (ops->get_eeprom_len) - info.eedump_len = ops->get_eeprom_len(dev); - - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int ethtool_get_regs(struct net_device *dev, char *useraddr) -{ - struct ethtool_regs regs; - struct ethtool_ops *ops = ethtool_ops; - void *regbuf; - int reglen, ret; - - if (!ops->get_regs || !ops->get_regs_len) - return -EOPNOTSUPP; - - if (copy_from_user(®s, useraddr, sizeof(regs))) - return -EFAULT; - - reglen = ops->get_regs_len(dev); - if (regs.len > reglen) - regs.len = reglen; - - regbuf = kmalloc(reglen, GFP_USER); - if (!regbuf) - return -ENOMEM; - - ops->get_regs(dev, ®s, regbuf); - - ret = -EFAULT; - if (copy_to_user(useraddr, ®s, sizeof(regs))) - goto out; - useraddr += offsetof(struct ethtool_regs, data); - if (copy_to_user(useraddr, regbuf, reglen)) - goto out; - ret = 0; - -out: - kfree(regbuf); - return ret; -} - -static int ethtool_get_wol(struct net_device *dev, char *useraddr) -{ - struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; - - if (!ethtool_ops->get_wol) - return -EOPNOTSUPP; - - ethtool_ops->get_wol(dev, &wol); - - if (copy_to_user(useraddr, &wol, sizeof(wol))) - return -EFAULT; - return 0; -} - -static int ethtool_set_wol(struct net_device *dev, char *useraddr) -{ - struct ethtool_wolinfo wol; - - if (!ethtool_ops->set_wol) - return -EOPNOTSUPP; - - if (copy_from_user(&wol, useraddr, sizeof(wol))) - return -EFAULT; - - return ethtool_ops->set_wol(dev, &wol); -} - -static int ethtool_get_msglevel(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GMSGLVL }; - - if (!ethtool_ops->get_msglevel) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_msglevel(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_msglevel(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_msglevel) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - ethtool_ops->set_msglevel(dev, edata.data); - return 0; -} - -static int ethtool_nway_reset(struct net_device *dev) -{ - if (!ethtool_ops->nway_reset) - return -EOPNOTSUPP; - - return ethtool_ops->nway_reset(dev); -} - -static int ethtool_get_link(struct net_device *dev, void *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - - if (!ethtool_ops->get_link) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_link(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_get_eeprom(struct net_device *dev, void *useraddr) -{ - struct ethtool_eeprom eeprom; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->get_eeprom || !ops->get_eeprom_len) - return -EOPNOTSUPP; - - if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; - - /* Check for wrap and zero */ - if (eeprom.offset + eeprom.len <= eeprom.offset) - return -EINVAL; - - /* Check for exceeding total eeprom len */ - if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) - return -EINVAL; - - data = kmalloc(eeprom.len, GFP_USER); - if (!data) - return -ENOMEM; - - ret = -EFAULT; - if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) - goto out; - - ret = ops->get_eeprom(dev, &eeprom, data); - if (ret) - goto out; - - ret = -EFAULT; - if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) - goto out; - if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_set_eeprom(struct net_device *dev, void *useraddr) -{ - struct ethtool_eeprom eeprom; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->set_eeprom || !ops->get_eeprom_len) - return -EOPNOTSUPP; - - if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; - - /* Check for wrap and zero */ - if (eeprom.offset + eeprom.len <= eeprom.offset) - return -EINVAL; - - /* Check for exceeding total eeprom len */ - if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) - return -EINVAL; - - data = kmalloc(eeprom.len, GFP_USER); - if (!data) - return -ENOMEM; - - ret = -EFAULT; - if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) - goto out; - - ret = ops->set_eeprom(dev, &eeprom, data); - if (ret) - goto out; - - if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) - ret = -EFAULT; - -out: - kfree(data); - return ret; -} - -static int ethtool_get_coalesce(struct net_device *dev, void *useraddr) -{ - struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; - - if (!ethtool_ops->get_coalesce) - return -EOPNOTSUPP; - - ethtool_ops->get_coalesce(dev, &coalesce); - - if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) - return -EFAULT; - return 0; -} - -static int ethtool_set_coalesce(struct net_device *dev, void *useraddr) -{ - struct ethtool_coalesce coalesce; - - if (!ethtool_ops->get_coalesce) - return -EOPNOTSUPP; - - if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) - return -EFAULT; - - return ethtool_ops->set_coalesce(dev, &coalesce); -} - -static int ethtool_get_ringparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; - - if (!ethtool_ops->get_ringparam) - return -EOPNOTSUPP; - - ethtool_ops->get_ringparam(dev, &ringparam); - - if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) - return -EFAULT; - return 0; -} - -static int ethtool_set_ringparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_ringparam ringparam; - - if (!ethtool_ops->get_ringparam) - return -EOPNOTSUPP; - - if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) - return -EFAULT; - - return ethtool_ops->set_ringparam(dev, &ringparam); -} - -static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; - - if (!ethtool_ops->get_pauseparam) - return -EOPNOTSUPP; - - ethtool_ops->get_pauseparam(dev, &pauseparam); - - if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) - return -EFAULT; - return 0; -} - -static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_pauseparam pauseparam; - - if (!ethtool_ops->get_pauseparam) - return -EOPNOTSUPP; - - if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) - return -EFAULT; - - return ethtool_ops->set_pauseparam(dev, &pauseparam); -} - -static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GRXCSUM }; - - if (!ethtool_ops->get_rx_csum) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_rx_csum(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_rx_csum) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - ethtool_ops->set_rx_csum(dev, edata.data); - return 0; -} - -static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GTXCSUM }; - - if (!ethtool_ops->get_tx_csum) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_tx_csum(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_tx_csum) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_tx_csum(dev, edata.data); -} - -static int ethtool_get_sg(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GSG }; - - if (!ethtool_ops->get_sg) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_sg(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_sg(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_sg) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_sg(dev, edata.data); -} - -static int ethtool_get_tso(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GTSO }; - - if (!ethtool_ops->get_tso) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_tso(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_tso(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_tso) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_tso(dev, edata.data); -} - -static int ethtool_self_test(struct net_device *dev, char *useraddr) -{ - struct ethtool_test test; - struct ethtool_ops *ops = ethtool_ops; - u64 *data; - int ret; - - if (!ops->self_test || !ops->self_test_count) - return -EOPNOTSUPP; - - if (copy_from_user(&test, useraddr, sizeof(test))) - return -EFAULT; - - test.len = ops->self_test_count(dev); - data = kmalloc(test.len * sizeof(u64), GFP_USER); - if (!data) - return -ENOMEM; - - ops->self_test(dev, &test, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &test, sizeof(test))) - goto out; - useraddr += sizeof(test); - if (copy_to_user(useraddr, data, test.len * sizeof(u64))) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_get_strings(struct net_device *dev, void *useraddr) -{ - struct ethtool_gstrings gstrings; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->get_strings) - return -EOPNOTSUPP; - - if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) - return -EFAULT; - - switch (gstrings.string_set) { - case ETH_SS_TEST: - if (!ops->self_test_count) - return -EOPNOTSUPP; - gstrings.len = ops->self_test_count(dev); - break; - case ETH_SS_STATS: - if (!ops->get_stats_count) - return -EOPNOTSUPP; - gstrings.len = ops->get_stats_count(dev); - break; - default: - return -EINVAL; - } - - data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); - if (!data) - return -ENOMEM; - - ops->get_strings(dev, gstrings.string_set, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) - goto out; - useraddr += sizeof(gstrings); - if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_phys_id(struct net_device *dev, void *useraddr) -{ - struct ethtool_value id; - - if (!ethtool_ops->phys_id) - return -EOPNOTSUPP; - - if (copy_from_user(&id, useraddr, sizeof(id))) - return -EFAULT; - - return ethtool_ops->phys_id(dev, id.data); -} - -static int ethtool_get_stats(struct net_device *dev, void *useraddr) -{ - struct ethtool_stats stats; - struct ethtool_ops *ops = ethtool_ops; - u64 *data; - int ret; - - if (!ops->get_ethtool_stats || !ops->get_stats_count) - return -EOPNOTSUPP; - - if (copy_from_user(&stats, useraddr, sizeof(stats))) - return -EFAULT; - - stats.n_stats = ops->get_stats_count(dev); - data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER); - if (!data) - return -ENOMEM; - - ops->get_ethtool_stats(dev, &stats, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &stats, sizeof(stats))) - goto out; - useraddr += sizeof(stats); - if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_ioctl(struct ifreq *ifr) -{ - struct net_device *dev = __dev_get_by_name(ifr->ifr_name); - void *useraddr = (void *) ifr->ifr_data; - u32 ethcmd; - - /* - * XXX: This can be pushed down into the ethtool_* handlers that - * need it. Keep existing behaviour for the moment. - */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (!dev || !netif_device_present(dev)) - return -ENODEV; - - if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GSET: - return ethtool_get_settings(dev, useraddr); - case ETHTOOL_SSET: - return ethtool_set_settings(dev, useraddr); - case ETHTOOL_GDRVINFO: - return ethtool_get_drvinfo(dev, useraddr); - case ETHTOOL_GREGS: - return ethtool_get_regs(dev, useraddr); - case ETHTOOL_GWOL: - return ethtool_get_wol(dev, useraddr); - case ETHTOOL_SWOL: - return ethtool_set_wol(dev, useraddr); - case ETHTOOL_GMSGLVL: - return ethtool_get_msglevel(dev, useraddr); - case ETHTOOL_SMSGLVL: - return ethtool_set_msglevel(dev, useraddr); - case ETHTOOL_NWAY_RST: - return ethtool_nway_reset(dev); - case ETHTOOL_GLINK: - return ethtool_get_link(dev, useraddr); - case ETHTOOL_GEEPROM: - return ethtool_get_eeprom(dev, useraddr); - case ETHTOOL_SEEPROM: - return ethtool_set_eeprom(dev, useraddr); - case ETHTOOL_GCOALESCE: - return ethtool_get_coalesce(dev, useraddr); - case ETHTOOL_SCOALESCE: - return ethtool_set_coalesce(dev, useraddr); - case ETHTOOL_GRINGPARAM: - return ethtool_get_ringparam(dev, useraddr); - case ETHTOOL_SRINGPARAM: - return ethtool_set_ringparam(dev, useraddr); - case ETHTOOL_GPAUSEPARAM: - return ethtool_get_pauseparam(dev, useraddr); - case ETHTOOL_SPAUSEPARAM: - return ethtool_set_pauseparam(dev, useraddr); - case ETHTOOL_GRXCSUM: - return ethtool_get_rx_csum(dev, useraddr); - case ETHTOOL_SRXCSUM: - return ethtool_set_rx_csum(dev, useraddr); - case ETHTOOL_GTXCSUM: - return ethtool_get_tx_csum(dev, useraddr); - case ETHTOOL_STXCSUM: - return ethtool_set_tx_csum(dev, useraddr); - case ETHTOOL_GSG: - return ethtool_get_sg(dev, useraddr); - case ETHTOOL_SSG: - return ethtool_set_sg(dev, useraddr); - case ETHTOOL_GTSO: - return ethtool_get_tso(dev, useraddr); - case ETHTOOL_STSO: - return ethtool_set_tso(dev, useraddr); - case ETHTOOL_TEST: - return ethtool_self_test(dev, useraddr); - case ETHTOOL_GSTRINGS: - return ethtool_get_strings(dev, useraddr); - case ETHTOOL_PHYS_ID: - return ethtool_phys_id(dev, useraddr); - case ETHTOOL_GSTATS: - return ethtool_get_stats(dev, useraddr); - default: - return -EOPNOTSUPP; - } - - return -EOPNOTSUPP; -} -#endif //ETHTOOL_OPS_COMPAT - -static int -rtl8168_do_ioctl(struct net_device *dev, - struct ifreq *ifr, - int cmd) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - int ret; - unsigned long flags; - - ret = 0; - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - break; - - case SIOCGMIIREG: - spin_lock_irqsave(&tp->lock, flags); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - data->val_out = rtl8168_mdio_read(tp, data->reg_num); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - spin_lock_irqsave(&tp->lock, flags); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, data->reg_num, data->val_in); - spin_unlock_irqrestore(&tp->lock, flags); - break; - -#ifdef ETHTOOL_OPS_COMPAT - case SIOCETHTOOL: - ret = ethtool_ioctl(ifr); - break; -#endif - case SIOCDEVPRIVATE_RTLASF: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - - ret = rtl8168_asf_ioctl(dev, ifr); - break; - -#ifdef ENABLE_DASH_SUPPORT - case SIOCDEVPRIVATE_RTLDASH: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - - ret = rtl8168_dash_ioctl(dev, ifr); - break; -#endif - -#ifdef ENABLE_REALWOW_SUPPORT - case SIOCDEVPRIVATE_RTLREALWOW: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - - ret = rtl8168_realwow_ioctl(dev, ifr); - break; -#endif - - case SIOCRTLTOOL: - ret = rtl8168_tool_ioctl(tp, ifr); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -static void -rtl8168_phy_power_up(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (rtl8168_is_in_phy_disable_mode(dev)) - return; - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - case CFG_METHOD_8: - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - rtl8168_mdio_write(tp, 0x0E, 0x0000); - break; - } - rtl8168_mdio_write(tp, MII_BMCR, BMCR_ANENABLE); - - //wait mdc/mdio ready - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - mdelay(10); - break; - } - - //wait ups resume (phy state 3) - if (HW_SUPPORT_UPS_MODE(tp)) - rtl8168_wait_phy_ups_resume(dev, HW_PHY_STATUS_LAN_ON); -} - -static void -rtl8168_phy_power_down(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - csi_tmp = rtl8168_eri_read(tp, 0x1AB, 1, ERIAR_ExGMAC); - csi_tmp &= ~( BIT_2 | BIT_3 | BIT_4 | BIT_5 | BIT_6 | BIT_7 ); - rtl8168_eri_write(tp, 0x1AB, 1, csi_tmp, ERIAR_ExGMAC); - break; - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - case CFG_METHOD_8: - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - rtl8168_mdio_write(tp, 0x0E, 0x0200); - rtl8168_mdio_write(tp, MII_BMCR, BMCR_PDOWN); - break; - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_29: - case CFG_METHOD_30: - rtl8168_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - rtl8168_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); - break; - case CFG_METHOD_23: - case CFG_METHOD_24: - rtl8168_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); - break; - default: - rtl8168_mdio_write(tp, MII_BMCR, BMCR_PDOWN); - break; - } -} - -static int __devinit -rtl8168_init_board(struct pci_dev *pdev, - struct net_device **dev_out, - void __iomem **ioaddr_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8168_private *tp; - int rc = -ENOMEM, i, pm_cap; - - assert(ioaddr_out != NULL); - - /* dev zeroed in alloc_etherdev */ - dev = alloc_etherdev(sizeof (*tp)); - if (dev == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out; - } - - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - tp = netdev_priv(dev); - tp->dev = dev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8168_MSG_DEFAULT); - - if (!aspm || tp->mcfg == CFG_METHOD_9) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | - PCIE_LINK_STATE_CLKPM); -#endif - } - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_free_dev; - } - - if (pci_set_mwi(pdev) < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_drv(&debug)) - dev_info(&pdev->dev, "Mem-Wr-Inval unavailable.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - } - - /* save power state before pci_enable_device overwrites it */ - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap) { - u16 pwr_command; - - pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); - } else { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, "PowerManagement capability not found.\n"); - } -#else - printk("PowerManagement capability not found.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - - } - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -ENODEV; - goto err_out_mwi; - } - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, 2) < R8168_REGS_SIZE) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -ENODEV; - goto err_out_mwi; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_mwi; - } - - if ((sizeof(dma_addr_t) > 4) && - use_dac && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && - !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "DMA configuration failed.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_free_res; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, 2), R8168_REGS_SIZE); - if (ioaddr == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -EIO; - goto err_out_free_res; - } - - tp->mmio_addr = ioaddr; - - /* Identify chip attached to board */ - rtl8168_get_mac_version(tp); - - rtl8168_print_mac_version(tp); - - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { - if (tp->mcfg == rtl_chip_info[i].mcfg) - break; - } - - if (i < 0) { - /* Unknown chip: assume array element #0, original RTL-8168 */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_printk(KERN_DEBUG, &pdev->dev, "unknown chip version, assuming %s\n", rtl_chip_info[0].name); -#else - printk("Realtek unknown chip version, assuming %s\n", rtl_chip_info[0].name); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - i++; - } - - tp->chipset = i; - - *ioaddr_out = ioaddr; - *dev_out = dev; -out: - return rc; - -err_out_free_res: - pci_release_regions(pdev); -err_out_mwi: - pci_clear_mwi(pdev); - pci_disable_device(pdev); -err_out_free_dev: - free_netdev(dev); -err_out: - *ioaddr_out = NULL; - *dev_out = NULL; - goto out; -} - -static void -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -rtl8168_esd_timer(unsigned long __opaque) -#else -rtl8168_esd_timer(struct timer_list *t) -#endif -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8168_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->esd_timer; -#else - struct rtl8168_private *tp = from_timer(tp, t, esd_timer); - struct net_device *dev = tp->dev; - struct timer_list *timer = t; -#endif - struct pci_dev *pdev = tp->pci_dev; - unsigned long timeout = RTL8168_ESD_TIMEOUT; - unsigned long flags; - u8 cmd; - u16 io_base_l; - u16 mem_base_l; - u16 mem_base_h; - u8 ilr; - u16 resv_0x1c_h; - u16 resv_0x1c_l; - u16 resv_0x20_l; - u16 resv_0x20_h; - u16 resv_0x24_l; - u16 resv_0x24_h; - u16 resv_0x2c_h; - u16 resv_0x2c_l; - u32 pci_sn_l; - u32 pci_sn_h; - - spin_lock_irqsave(&tp->lock, flags); - - tp->esd_flag = 0; - - pci_read_config_byte(pdev, PCI_COMMAND, &cmd); - if (cmd != tp->pci_cfg_space.cmd) { - printk(KERN_ERR "%s: cmd = 0x%02x, should be 0x%02x \n.", dev->name, cmd, tp->pci_cfg_space.cmd); - pci_write_config_byte(pdev, PCI_COMMAND, tp->pci_cfg_space.cmd); - tp->esd_flag |= BIT_0; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &io_base_l); - if (io_base_l != tp->pci_cfg_space.io_base_l) { - printk(KERN_ERR "%s: io_base_l = 0x%04x, should be 0x%04x \n.", dev->name, io_base_l, tp->pci_cfg_space.io_base_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_0, tp->pci_cfg_space.io_base_l); - tp->esd_flag |= BIT_1; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &mem_base_l); - if (mem_base_l != tp->pci_cfg_space.mem_base_l) { - printk(KERN_ERR "%s: mem_base_l = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_l, tp->pci_cfg_space.mem_base_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_2, tp->pci_cfg_space.mem_base_l); - tp->esd_flag |= BIT_2; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &mem_base_h); - if (mem_base_h!= tp->pci_cfg_space.mem_base_h) { - printk(KERN_ERR "%s: mem_base_h = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_h, tp->pci_cfg_space.mem_base_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, tp->pci_cfg_space.mem_base_h); - tp->esd_flag |= BIT_3; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &resv_0x1c_l); - if (resv_0x1c_l != tp->pci_cfg_space.resv_0x1c_l) { - printk(KERN_ERR "%s: resv_0x1c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_l, tp->pci_cfg_space.resv_0x1c_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_3, tp->pci_cfg_space.resv_0x1c_l); - tp->esd_flag |= BIT_4; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &resv_0x1c_h); - if (resv_0x1c_h != tp->pci_cfg_space.resv_0x1c_h) { - printk(KERN_ERR "%s: resv_0x1c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_h, tp->pci_cfg_space.resv_0x1c_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, tp->pci_cfg_space.resv_0x1c_h); - tp->esd_flag |= BIT_5; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &resv_0x20_l); - if (resv_0x20_l != tp->pci_cfg_space.resv_0x20_l) { - printk(KERN_ERR "%s: resv_0x20_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_l, tp->pci_cfg_space.resv_0x20_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_4, tp->pci_cfg_space.resv_0x20_l); - tp->esd_flag |= BIT_6; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &resv_0x20_h); - if (resv_0x20_h != tp->pci_cfg_space.resv_0x20_h) { - printk(KERN_ERR "%s: resv_0x20_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_h, tp->pci_cfg_space.resv_0x20_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, tp->pci_cfg_space.resv_0x20_h); - tp->esd_flag |= BIT_7; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &resv_0x24_l); - if (resv_0x24_l != tp->pci_cfg_space.resv_0x24_l) { - printk(KERN_ERR "%s: resv_0x24_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_l, tp->pci_cfg_space.resv_0x24_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_5, tp->pci_cfg_space.resv_0x24_l); - tp->esd_flag |= BIT_8; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &resv_0x24_h); - if (resv_0x24_h != tp->pci_cfg_space.resv_0x24_h) { - printk(KERN_ERR "%s: resv_0x24_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_h, tp->pci_cfg_space.resv_0x24_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, tp->pci_cfg_space.resv_0x24_h); - tp->esd_flag |= BIT_9; - } - - pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ilr); - if (ilr != tp->pci_cfg_space.ilr) { - printk(KERN_ERR "%s: ilr = 0x%02x, should be 0x%02x \n.", dev->name, ilr, tp->pci_cfg_space.ilr); - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, tp->pci_cfg_space.ilr); - tp->esd_flag |= BIT_10; - } - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &resv_0x2c_l); - if (resv_0x2c_l != tp->pci_cfg_space.resv_0x2c_l) { - printk(KERN_ERR "%s: resv_0x2c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_l, tp->pci_cfg_space.resv_0x2c_l); - pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, tp->pci_cfg_space.resv_0x2c_l); - tp->esd_flag |= BIT_11; - } - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &resv_0x2c_h); - if (resv_0x2c_h != tp->pci_cfg_space.resv_0x2c_h) { - printk(KERN_ERR "%s: resv_0x2c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_h, tp->pci_cfg_space.resv_0x2c_h); - pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, tp->pci_cfg_space.resv_0x2c_h); - tp->esd_flag |= BIT_12; - } - - if (tp->HwPcieSNOffset > 0) { - pci_sn_l = rtl8168_csi_read(tp, tp->HwPcieSNOffset); - if (pci_sn_l != tp->pci_cfg_space.pci_sn_l) { - printk(KERN_ERR "%s: pci_sn_l = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_l, tp->pci_cfg_space.pci_sn_l); - rtl8168_csi_write(tp, tp->HwPcieSNOffset, tp->pci_cfg_space.pci_sn_l); - tp->esd_flag |= BIT_13; - } - - pci_sn_h = rtl8168_csi_read(tp, tp->HwPcieSNOffset + 4); - if (pci_sn_h != tp->pci_cfg_space.pci_sn_h) { - printk(KERN_ERR "%s: pci_sn_h = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_h, tp->pci_cfg_space.pci_sn_h); - rtl8168_csi_write(tp, tp->HwPcieSNOffset + 4, tp->pci_cfg_space.pci_sn_h); - tp->esd_flag |= BIT_14; - } - } - - if (tp->TestPhyOcpReg && rtl8168_test_phy_ocp(tp)) - tp->esd_flag |= BIT_15; - - if (tp->esd_flag != 0) { - printk(KERN_ERR "%s: esd_flag = 0x%04x\n.\n", dev->name, tp->esd_flag); - netif_stop_queue(dev); - netif_carrier_off(dev); - rtl8168_hw_reset(dev); - rtl8168_tx_clear(tp); - rtl8168_rx_clear(tp); - rtl8168_init_ring(dev); - rtl8168_hw_init(dev); - rtl8168_powerup_pll(dev); - rtl8168_hw_ephy_config(dev); - rtl8168_hw_phy_config(dev); - rtl8168_hw_config(dev); - rtl8168_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - tp->esd_flag = 0; - } - spin_unlock_irqrestore(&tp->lock, flags); - - mod_timer(timer, jiffies + timeout); -} - -static void -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -rtl8168_link_timer(unsigned long __opaque) -#else -rtl8168_link_timer(struct timer_list *t) -#endif -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8168_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->link_timer; -#else - struct rtl8168_private *tp = from_timer(tp, t, link_timer); - struct net_device *dev = tp->dev; - struct timer_list *timer = t; -#endif - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_check_link_status(dev); - spin_unlock_irqrestore(&tp->lock, flags); - - mod_timer(timer, jiffies + RTL8168_LINK_TIMEOUT); -} - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl8168_try_msi(struct pci_dev *pdev, struct rtl8168_private *tp) -{ - unsigned msi = 0; - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - case CFG_METHOD_8: - dev_info(&pdev->dev, "Default use INTx.\n"); - break; - default: - if (pci_enable_msi(pdev)) - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - else - msi |= RTL_FEATURE_MSI; - break; - } -#endif - - return msi; -} - -static void rtl8168_disable_msi(struct pci_dev *pdev, struct rtl8168_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - pci_disable_msi(pdev); -#endif - tp->features &= ~RTL_FEATURE_MSI; - } -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) -static const struct net_device_ops rtl8168_netdev_ops = { - .ndo_open = rtl8168_open, - .ndo_stop = rtl8168_close, - .ndo_get_stats = rtl8168_get_stats, - .ndo_start_xmit = rtl8168_start_xmit, - .ndo_tx_timeout = rtl8168_tx_timeout, - .ndo_change_mtu = rtl8168_change_mtu, - .ndo_set_mac_address = rtl8168_set_mac_address, - .ndo_do_ioctl = rtl8168_do_ioctl, -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) - .ndo_set_multicast_list = rtl8168_set_rx_mode, -#else - .ndo_set_rx_mode = rtl8168_set_rx_mode, -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) -#ifdef CONFIG_R8168_VLAN - .ndo_vlan_rx_register = rtl8168_vlan_rx_register, -#endif -#else - .ndo_fix_features = rtl8168_fix_features, - .ndo_set_features = rtl8168_set_features, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8168_netpoll, -#endif -}; -#endif - -static int __devinit -rtl8168_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8168_private *tp; - void __iomem *ioaddr = NULL; - static int board_idx = -1; - - int rc; - - assert(pdev != NULL); - assert(ent != NULL); - - board_idx++; - - if (netif_msg_drv(&debug)) - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8168_VERSION); - - rc = rtl8168_init_board(pdev, &dev, &ioaddr); - if (rc) - goto out; - - tp = netdev_priv(dev); - assert(ioaddr != NULL); - - tp->set_speed = rtl8168_set_speed_xmii; - tp->get_settings = rtl8168_gset_xmii; - tp->phy_reset_enable = rtl8168_xmii_reset_enable; - tp->phy_reset_pending = rtl8168_xmii_reset_pending; - tp->link_ok = rtl8168_xmii_link_ok; - - tp->features |= rtl8168_try_msi(pdev, tp); - - RTL_NET_DEVICE_OPS(rtl8168_netdev_ops); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - SET_ETHTOOL_OPS(dev, &rtl8168_ethtool_ops); -#endif - - dev->watchdog_timeo = RTL8168_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - -#ifdef CONFIG_R8168_NAPI - RTL_NAPI_CONFIG(dev, tp, rtl8168_poll, R8168_NAPI_WEIGHT); -#endif - -#ifdef CONFIG_R8168_VLAN - if (tp->mcfg != CFG_METHOD_DEFAULT) { - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - dev->vlan_rx_kill_vid = rtl8168_vlan_rx_kill_vid; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - } -#endif - - /* There has been a number of reports that using SG/TSO results in - * tx timeouts. However for a lot of people SG/TSO works fine. - * Therefore disable both features by default, but allow users to - * enable them. Use at own risk! - */ - tp->cp_cmd |= RTL_R16(tp, CPlusCmd); - if (tp->mcfg != CFG_METHOD_DEFAULT) { - dev->features |= NETIF_F_IP_CSUM; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - tp->cp_cmd |= RxChkSum; -#else - dev->features |= NETIF_F_RXCSUM; - dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | - NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | - NETIF_F_HIGHDMA; - if ((tp->mcfg != CFG_METHOD_16) && (tp->mcfg != CFG_METHOD_17)) { - //dev->features |= NETIF_F_TSO; - dev->hw_features |= NETIF_F_TSO; - dev->vlan_features |= NETIF_F_TSO; - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) - dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) - dev->hw_features |= NETIF_F_RXALL; - dev->hw_features |= NETIF_F_RXFCS; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - if ((tp->mcfg == CFG_METHOD_1) || (tp->mcfg == CFG_METHOD_2) || (tp->mcfg == CFG_METHOD_3)) { - dev->hw_features &= ~NETIF_F_IPV6_CSUM; - netif_set_gso_max_size(dev, LSO_32K); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - dev->gso_max_segs = NIC_MAX_PHYS_BUF_COUNT_LSO_64K; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) - dev->gso_min_segs = NIC_MIN_PHYS_BUF_COUNT; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - } else { - dev->hw_features |= NETIF_F_IPV6_CSUM; - dev->features |= NETIF_F_IPV6_CSUM; - if ((tp->mcfg != CFG_METHOD_16) && (tp->mcfg != CFG_METHOD_17)) { - dev->hw_features |= NETIF_F_TSO6; - //dev->features |= NETIF_F_TSO6; - } - netif_set_gso_max_size(dev, LSO_64K); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - dev->gso_max_segs = NIC_MAX_PHYS_BUF_COUNT_LSO2; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) - dev->gso_min_segs = NIC_MIN_PHYS_BUF_COUNT; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - } -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - } - - tp->pci_dev = pdev; - - spin_lock_init(&tp->lock); - - rtl8168_init_software_variable(dev); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - AllocateDashShareMemory(dev); -#endif - - rtl8168_exit_oob(dev); - - rtl8168_hw_init(dev); - - rtl8168_hw_reset(dev); - - /* Get production from EEPROM */ - if (((tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_29 || - tp->mcfg == CFG_METHOD_30) && (rtl8168_mac_ocp_read(tp, 0xDC00) & BIT_3)) || - ((tp->mcfg == CFG_METHOD_26) && (rtl8168_mac_ocp_read(tp, 0xDC00) & BIT_4))) - tp->eeprom_type = EEPROM_TYPE_NONE; - else - rtl8168_eeprom_type(tp); - - if (tp->eeprom_type == EEPROM_TYPE_93C46 || tp->eeprom_type == EEPROM_TYPE_93C56) - rtl8168_set_eeprom_sel_low(tp); - - rtl8168_get_mac_address(dev); - - tp->fw_name = rtl_chip_fw_infos[tp->mcfg].fw_name; - -#if defined(ENABLE_DASH_PRINTER_SUPPORT) - init_completion(&tp->fw_host_ok); - init_completion(&tp->fw_ack); - init_completion(&tp->fw_req); -#endif - - tp->tally_vaddr = dma_alloc_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), - &tp->tally_paddr, GFP_KERNEL); - if (!tp->tally_vaddr) { - rc = -ENOMEM; - goto err_out; - } - - rtl8168_tally_counter_clear(tp); - - pci_set_drvdata(pdev, dev); - - rc = register_netdev(dev); - if (rc) - goto err_out; - - printk(KERN_INFO "%s: This product is covered by one or more of the following patents: US6,570,884, US6,115,776, and US6,327,625.\n", MODULENAME); - - rtl8168_disable_rxdvgate(dev); - - device_set_wakeup_enable(&pdev->dev, tp->wol_enabled); - - netif_carrier_off(dev); - - printk("%s", GPL_CLAIM); - -out: - return rc; - -err_out: - if (tp->tally_vaddr != NULL) { - dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, - tp->tally_paddr); - - tp->tally_vaddr = NULL; - } -#ifdef CONFIG_R8168_NAPI - RTL_NAPI_DEL(tp); -#endif - rtl8168_disable_msi(pdev, tp); - rtl8168_release_board(pdev, dev); - - goto out; -} - -static void __devexit -rtl8168_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8168_private *tp = netdev_priv(dev); - - assert(dev != NULL); - assert(tp != NULL); - -#ifdef CONFIG_R8168_NAPI - RTL_NAPI_DEL(tp); -#endif - if (HW_DASH_SUPPORT_DASH(tp)) - rtl8168_driver_stop(tp); - - unregister_netdev(dev); - rtl8168_disable_msi(pdev, tp); -#ifdef ENABLE_R8168_PROCFS - rtl8168_proc_remove(dev); -#endif - if (tp->tally_vaddr != NULL) { - dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, tp->tally_paddr); - tp->tally_vaddr = NULL; - } - - rtl8168_release_board(pdev, dev); - -#ifdef ENABLE_USE_FIRMWARE_FILE - rtl8168_release_firmware(tp); -#endif - - pci_set_drvdata(pdev, NULL); -} - -static void -rtl8168_set_rxbufsize(struct rtl8168_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > ETH_DATA_LEN) ? mtu + ETH_HLEN + 8 + 1 : RX_BUF_SIZE; -} - -#ifdef ENABLE_USE_FIRMWARE_FILE -static void rtl8168_request_firmware(struct rtl8168_private *tp) -{ - struct rtl8168_fw *rtl_fw; - - /* firmware loaded already or no firmware available */ - if (tp->rtl_fw || !tp->fw_name) - return; - - rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL); - if (!rtl_fw) - return; - - rtl_fw->phy_write = rtl8168_mdio_write; - rtl_fw->phy_read = rtl8168_mdio_read; - rtl_fw->mac_mcu_write = mac_mcu_write; - rtl_fw->mac_mcu_read = mac_mcu_read; - rtl_fw->fw_name = tp->fw_name; - rtl_fw->dev = tp_to_dev(tp); - - if (rtl8168_fw_request_firmware(rtl_fw)) - kfree(rtl_fw); - else - tp->rtl_fw = rtl_fw; -} -#endif - -static int rtl8168_open(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - unsigned long flags; - int retval; - - retval = -ENOMEM; - -#ifdef ENABLE_R8168_PROCFS - rtl8168_proc_init(dev); -#endif - rtl8168_set_rxbufsize(tp, dev); - /* - * Rx and Tx descriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8168_TX_RING_BYTES, - &tp->TxPhyAddr, GFP_KERNEL); - if (!tp->TxDescArray) - goto err_free_all_allocated_mem; - - tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8168_RX_RING_BYTES, - &tp->RxPhyAddr, GFP_KERNEL); - if (!tp->RxDescArray) - goto err_free_all_allocated_mem; - - retval = rtl8168_init_ring(dev); - if (retval < 0) - goto err_free_all_allocated_mem; - - retval = request_irq(dev->irq, rtl8168_interrupt, (tp->features & RTL_FEATURE_MSI) ? 0 : SA_SHIRQ, dev->name, dev); - if (retval<0) - goto err_free_all_allocated_mem; - - if (netif_msg_probe(tp)) { - printk(KERN_INFO "%s: 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], dev->irq); - } - -#ifdef ENABLE_USE_FIRMWARE_FILE - rtl8168_request_firmware(tp); -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_WORK(&tp->task, rtl8168_reset_task, dev); -#else - INIT_DELAYED_WORK(&tp->task, rtl8168_reset_task); -#endif - - pci_set_master(pdev); - -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - RTL_NAPI_ENABLE(dev, &tp->napi); -#endif -#endif - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_exit_oob(dev); - - rtl8168_hw_init(dev); - - rtl8168_hw_reset(dev); - - rtl8168_powerup_pll(dev); - - rtl8168_hw_ephy_config(dev); - - rtl8168_hw_phy_config(dev); - - rtl8168_hw_config(dev); - - rtl8168_dsm(dev, DSM_IF_UP); - - rtl8168_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - - spin_unlock_irqrestore(&tp->lock, flags); - - if (tp->esd_flag == 0) - rtl8168_request_esd_timer(dev); - - rtl8168_request_link_timer(dev); - -out: - - return retval; - -err_free_all_allocated_mem: - if (tp->RxDescArray != NULL) { - dma_free_coherent(&pdev->dev, R8168_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - tp->RxDescArray = NULL; - } - - if (tp->TxDescArray != NULL) { - dma_free_coherent(&pdev->dev, R8168_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - } - - goto out; -} - -static void -rtl8168_dsm(struct net_device *dev, int dev_state) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (dev_state) { - case DSM_MAC_INIT: - if ((tp->mcfg == CFG_METHOD_5) || (tp->mcfg == CFG_METHOD_6)) { - if (RTL_R8(tp, MACDBG) & 0x80) - RTL_W8(tp, GPIO, RTL_R8(tp, GPIO) | GPIO_en); - else - RTL_W8(tp, GPIO, RTL_R8(tp, GPIO) & ~GPIO_en); - } - - break; - case DSM_NIC_GOTO_D3: - case DSM_IF_DOWN: - if ((tp->mcfg == CFG_METHOD_5) || (tp->mcfg == CFG_METHOD_6)) { - if (RTL_R8(tp, MACDBG) & 0x80) - RTL_W8(tp, GPIO, RTL_R8(tp, GPIO) & ~GPIO_en); - } - break; - - case DSM_NIC_RESUME_D3: - case DSM_IF_UP: - if ((tp->mcfg == CFG_METHOD_5) || (tp->mcfg == CFG_METHOD_6)) { - if (RTL_R8(tp, MACDBG) & 0x80) - RTL_W8(tp, GPIO, RTL_R8(tp, GPIO) | GPIO_en); - } - - break; - } - -} - -static void -set_offset70F(struct rtl8168_private *tp, u8 setting) -{ - u32 csi_tmp; - u32 temp = (u32)setting; - temp = temp << 24; - /*set PCI configuration space offset 0x70F to setting*/ - /*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/ - - csi_tmp = rtl8168_csi_read(tp, 0x70c) & 0x00ffffff; - rtl8168_csi_write(tp, 0x70c, csi_tmp | temp); -} - -static void -set_offset79(struct rtl8168_private *tp, u8 setting) -{ - //Set PCI configuration space offset 0x79 to setting - - struct pci_dev *pdev = tp->pci_dev; - u8 device_control; - - if (hwoptimize & HW_PATCH_SOC_LAN) return; - - pci_read_config_byte(pdev, 0x79, &device_control); - device_control &= ~0x70; - device_control |= setting; - pci_write_config_byte(pdev, 0x79, device_control); -} - -static void -set_offset711(struct rtl8168_private *tp, u8 setting) -{ - u32 csi_tmp; - u32 temp = (u32)setting; - temp &= 0x0f; - temp = temp << 12; - /*set PCI configuration space offset 0x711 to setting*/ - - csi_tmp = rtl8168_csi_read(tp, 0x710) & 0xffff0fff; - rtl8168_csi_write(tp, 0x710, csi_tmp | temp); -} - -static void -rtl8168_hw_set_rx_packet_filter(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } -#else - struct netdev_hw_addr *ha; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } -#endif - } - - if (dev->features & NETIF_F_RXALL) - rx_mode |= (AcceptErr | AcceptRunt); - - tmp = mc_filter[0]; - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(tmp); - - tp->rtl8168_rx_config = rtl_chip_info[tp->chipset].RCR_Cfg; - tmp = tp->rtl8168_rx_config | rx_mode | (RTL_R32(tp, RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - RTL_W32(tp, RxConfig, tmp); - RTL_W32(tp, MAR0 + 0, mc_filter[0]); - RTL_W32(tp, MAR0 + 4, mc_filter[1]); -} - -static void -rtl8168_set_rx_mode(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_hw_set_rx_packet_filter(dev); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void -rtl8168_hw_config(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - u8 device_control; - u16 mac_ocp_data; - u32 csi_tmp; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - if (dev->mtu > ETH_DATA_LEN) { - dev->features &= ~(NETIF_F_IP_CSUM); - } else { - dev->features |= NETIF_F_IP_CSUM; - } -#endif - - RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); - - rtl8168_hw_reset(dev); - - rtl8168_enable_cfg9346_write(tp); - if (tp->HwSuppAspmClkIntrLock) { - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - rtl8168_hw_aspm_clkreq_enable(tp, false); - } - - //clear io_rdy_l23 - switch (tp->mcfg) { - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~BIT_1); - break; - } - - //keep magic packet only - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0xDE, 1, ERIAR_ExGMAC); - csi_tmp &= BIT_0; - rtl8168_eri_write(tp, 0xDE, 1, csi_tmp, ERIAR_ExGMAC); - break; - } - - RTL_W8(tp, MTPS, Reserved1_data); - - tp->cp_cmd |= INTT_1; - if (tp->use_timer_interrrupt) - tp->cp_cmd |= PktCntrDisable; - else - tp->cp_cmd &= ~PktCntrDisable; - - RTL_W16(tp, IntrMitigate, 0x5f51); - - rtl8168_tally_counter_addr_fill(tp); - - rtl8168_desc_addr_fill(tp); - - /* Set DMA burst size and Interframe Gap Time */ - if (tp->mcfg == CFG_METHOD_1) - RTL_W32(tp, TxConfig, (TX_DMA_BURST_512 << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - else - RTL_W32(tp, TxConfig, (TX_DMA_BURST_unlimited << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - if (tp->mcfg == CFG_METHOD_4) { - set_offset70F(tp, 0x27); - - RTL_W8(tp, DBG_reg, (0x0E << 4) | Fix_Nak_1 | Fix_Nak_2); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - //disable clock request. - pci_write_config_byte(pdev, 0x81, 0x00); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - set_offset79(tp, 0x50); - } - - //rx checksum offload enable -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - tp->cp_cmd |= RxChkSum; -#else - dev->features |= NETIF_F_RXCSUM; -#endif - - tp->cp_cmd &= ~(EnableBist | Macdbgo_oe | Force_halfdup | - Force_rxflow_en | Force_txflow_en | Cxpl_dbg_sel | - ASF | PktCntrDisable | Macdbgo_sel); - } else if (tp->mcfg == CFG_METHOD_5) { - - set_offset70F(tp, 0x27); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - //disable clock request. - pci_write_config_byte(pdev, 0x81, 0x00); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - set_offset79(tp, 0x50); - } - - //rx checksum offload enable -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - tp->cp_cmd |= RxChkSum; -#else - dev->features |= NETIF_F_RXCSUM; -#endif - } else if (tp->mcfg == CFG_METHOD_6) { - set_offset70F(tp, 0x27); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - //disable clock request. - pci_write_config_byte(pdev, 0x81, 0x00); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - set_offset79(tp, 0x50); - } - - //rx checksum offload enable -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - tp->cp_cmd |= RxChkSum; -#else - dev->features |= NETIF_F_RXCSUM; -#endif - } else if (tp->mcfg == CFG_METHOD_7) { - set_offset70F(tp, 0x27); - - rtl8168_eri_write(tp, 0x1EC, 1, 0x07, ERIAR_ASF); - - //disable clock request. - pci_write_config_byte(pdev, 0x81, 0x00); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - - set_offset79(tp, 0x50); - } - } else if (tp->mcfg == CFG_METHOD_8) { - - set_offset70F(tp, 0x27); - - rtl8168_eri_write(tp, 0x1EC, 1, 0x07, ERIAR_ASF); - - //disable clock request. - pci_write_config_byte(pdev, 0x81, 0x00); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - RTL_W8(tp, 0xD1, 0x20); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - set_offset79(tp, 0x50); - } - } else if (tp->mcfg == CFG_METHOD_9) { - set_offset70F(tp, 0x27); - - /* disable clock request. */ - pci_write_config_byte(pdev, 0x81, 0x00); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~BIT_4); - RTL_W8(tp, DBG_reg, RTL_R8(tp, DBG_reg) | BIT_7 | BIT_1); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - set_offset79(tp, 0x50); - } - - RTL_W8(tp, TDFNR, 0x8); - - } else if (tp->mcfg == CFG_METHOD_10) { - set_offset70F(tp, 0x27); - - RTL_W8(tp, DBG_reg, RTL_R8(tp, DBG_reg) | BIT_7 | BIT_1); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - set_offset79(tp, 0x50); - } - - RTL_W8(tp, TDFNR, 0x8); - - RTL_W8(tp, Config1, RTL_R8(tp, Config1) | 0x10); - - /* disable clock request. */ - pci_write_config_byte(pdev, 0x81, 0x00); - } else if (tp->mcfg == CFG_METHOD_11 || tp->mcfg == CFG_METHOD_13) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - else - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - - pci_write_config_byte(pdev, 0x81, 0x00); - - RTL_W8(tp, Config1, RTL_R8(tp, Config1) | 0x10); - - } else if (tp->mcfg == CFG_METHOD_12) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - else - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - - pci_write_config_byte(pdev, 0x81, 0x01); - - RTL_W8(tp, Config1, RTL_R8(tp, Config1) | 0x10); - - } else if (tp->mcfg == CFG_METHOD_14 || tp->mcfg == CFG_METHOD_15) { - - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, MTPS, 0x24); - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | 0x01); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~0x01); - } - - RTL_W8(tp, 0xF3, RTL_R8(tp, 0xF3) | BIT_5); - RTL_W8(tp, 0xF3, RTL_R8(tp, 0xF3) & ~BIT_5); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_7 | BIT_6); - - RTL_W8(tp, 0xD1, RTL_R8(tp, 0xD1) | BIT_2 | BIT_3); - - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_6 | BIT_5 | BIT_4 | BIT_2 | BIT_1); - - RTL_W8(tp, TDFNR, 0x8); - - /* - if (aspm) - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_7); - */ - - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_3); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - RTL_W8(tp, Config1, RTL_R8(tp, Config1) & ~0x10); - } else if (tp->mcfg == CFG_METHOD_16 || tp->mcfg == CFG_METHOD_17) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - rtl8168_eri_write(tp, 0xC0, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xB8, 4, 0x00000000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xC8, 4, 0x00100002, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xE8, 4, 0x00100006, ERIAR_ExGMAC); - csi_tmp = rtl8168_eri_read(tp, 0x1D0, 4, ERIAR_ExGMAC); - csi_tmp |= BIT_1; - rtl8168_eri_write(tp, 0x1D0, 1, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0xDC, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | BIT_7); - RTL_W8(tp, 0xD3, RTL_R8(tp, 0xD3) & ~BIT_7); - RTL_W8(tp, 0x1B, RTL_R8(tp, 0x1B) & ~0x07); - - if (tp->mcfg == CFG_METHOD_16) { - RTL_W32(tp, 0xB0, 0xEE480010); - RTL_W8(tp, 0x1A, RTL_R8(tp, 0x1A) & ~(BIT_2|BIT_3)); - rtl8168_eri_write(tp, 0x1DC, 1, 0x64, ERIAR_ExGMAC); - } else { - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp |= BIT_4; - rtl8168_eri_write(tp, 0x1B0, 1, csi_tmp, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xCC, 4, 0x00000050, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xD0, 4, 0x07ff0060, ERIAR_ExGMAC); - } - - RTL_W8(tp, TDFNR, 0x8); - - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~PMSTS_En); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_6); - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, MTPS, 0x27); - - /* disable clock request. */ - pci_write_config_byte(pdev, 0x81, 0x00); - - } else if (tp->mcfg == CFG_METHOD_18 || tp->mcfg == CFG_METHOD_19) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - rtl8168_eri_write(tp, 0xC8, 4, 0x00100002, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xE8, 4, 0x00100006, ERIAR_ExGMAC); - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | BIT_7); - RTL_W8(tp, 0xD3, RTL_R8(tp, 0xD3) & ~BIT_7); - csi_tmp = rtl8168_eri_read(tp, 0xDC, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - - /* - if (aspm) - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_7); - */ - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, MTPS, 0x27); - - RTL_W8(tp, TDFNR, 0x8); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_6); - - rtl8168_eri_write(tp, 0xC0, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xB8, 4, 0x00000000, ERIAR_ExGMAC); - RTL_W8(tp, 0x1B,RTL_R8(tp, 0x1B) & ~0x07); - - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_4; - rtl8168_eri_write(tp, 0x1B0, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp = rtl8168_eri_read(tp, 0x1d0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_4 | BIT_1; - rtl8168_eri_write(tp, 0x1d0, 1, csi_tmp, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xCC, 4, 0x00000050, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xd0, 4, 0x00000060, ERIAR_ExGMAC); - } else if (tp->mcfg == CFG_METHOD_20) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - rtl8168_eri_write(tp, 0xC8, 4, 0x00100002, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xE8, 4, 0x00100006, ERIAR_ExGMAC); - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | BIT_7); - RTL_W8(tp, 0xD3, RTL_R8(tp, 0xD3) & ~BIT_7); - csi_tmp = rtl8168_eri_read(tp, 0xDC, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - - /* - if (aspm) - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_7); - */ - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, MTPS, 0x27); - - RTL_W8(tp, TDFNR, 0x8); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_6); - rtl8168_eri_write(tp, 0xC0, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xB8, 4, 0x00000000, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_4; - rtl8168_eri_write(tp, 0x1B0, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp = rtl8168_eri_read(tp, 0x1d0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_4 | BIT_1; - rtl8168_eri_write(tp, 0x1d0, 1, csi_tmp, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xCC, 4, 0x00000050, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xd0, 4, 0x00000060, ERIAR_ExGMAC); - } else if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_24 || tp->mcfg == CFG_METHOD_25 || - tp->mcfg == CFG_METHOD_26 || tp->mcfg == CFG_METHOD_29 || - tp->mcfg == CFG_METHOD_30) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22) - set_offset711(tp, 0x04); - - rtl8168_eri_write(tp, 0xC8, 4, 0x00080002, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xCC, 1, 0x38, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xD0, 1, 0x48, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xE8, 4, 0x00100006, ERIAR_ExGMAC); - - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | BIT_7); - - csi_tmp = rtl8168_eri_read(tp, 0xDC, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - - if (tp->mcfg == CFG_METHOD_26) { - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD3C0); - mac_ocp_data &= ~(BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= 0x0FFF; - rtl8168_mac_ocp_write(tp, 0xD3C0, mac_ocp_data); - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD3C2); - mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - rtl8168_mac_ocp_write(tp, 0xD3C2, mac_ocp_data); - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD3C4); - mac_ocp_data |= BIT_0; - rtl8168_mac_ocp_write(tp, 0xD3C4, mac_ocp_data); - } else if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30) { - - if (tp->RequireAdjustUpsTxLinkPulseTiming) { - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD412); - mac_ocp_data &= ~(0x0FFF); - mac_ocp_data |= tp->SwrCnt1msIni; - rtl8168_mac_ocp_write(tp, 0xD412, mac_ocp_data); - } - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xE056); - mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4); - //mac_ocp_data |= (BIT_6 | BIT_5 | BIT_4); - rtl8168_mac_ocp_write(tp, 0xE056, mac_ocp_data); - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xE052); - mac_ocp_data &= ~(BIT_15 | BIT_14 | BIT_13 | BIT_3); - mac_ocp_data |= BIT_15; - //mac_ocp_data |= BIT_3; - rtl8168_mac_ocp_write(tp, 0xE052, mac_ocp_data); - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD420); - mac_ocp_data &= ~(BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= 0x45F; - rtl8168_mac_ocp_write(tp, 0xD420, mac_ocp_data); - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xE0D6); - mac_ocp_data &= ~(BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= 0x17F; - rtl8168_mac_ocp_write(tp, 0xE0D6, mac_ocp_data); - } - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - RTL_W8(tp, 0x1B, RTL_R8(tp, 0x1B) & ~0x07); - - RTL_W8(tp, TDFNR, 0x4); - - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~PMSTS_En); - - /* - if (aspm) - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_7); - */ - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, MTPS, 0x27); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_6); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_7); - - rtl8168_eri_write(tp, 0xC0, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xB8, 4, 0x00000000, ERIAR_ExGMAC); - - if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30) { - rtl8168_mac_ocp_write(tp, 0xE054, 0x0000); - - rtl8168_eri_write(tp, 0x5F0, 2, 0x4000, ERIAR_ExGMAC); - } else { - rtl8168_eri_write(tp, 0x5F0, 2, 0x4F87, ERIAR_ExGMAC); - } - - if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30) { - csi_tmp = rtl8168_eri_read(tp, 0xDC, 4, ERIAR_ExGMAC); - csi_tmp |= (BIT_2 | BIT_3 | BIT_4); - rtl8168_eri_write(tp, 0xDC, 4, csi_tmp, ERIAR_ExGMAC); - } - - if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_24 || tp->mcfg == CFG_METHOD_25) { - rtl8168_mac_ocp_write(tp, 0xC140, 0xFFFF); - } else if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30) { - rtl8168_mac_ocp_write(tp, 0xC140, 0xFFFF); - rtl8168_mac_ocp_write(tp, 0xC142, 0xFFFF); - } - - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp &= ~BIT_12; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - - if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30) { - csi_tmp = rtl8168_eri_read(tp, 0x2FC, 1, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_2); - rtl8168_eri_write(tp, 0x2FC, 1, csi_tmp, ERIAR_ExGMAC); - } else { - csi_tmp = rtl8168_eri_read(tp, 0x2FC, 1, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_0 | BIT_1 | BIT_2); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0x2FC, 1, csi_tmp, ERIAR_ExGMAC); - } - - csi_tmp = rtl8168_eri_read(tp, 0x1D0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_1; - rtl8168_eri_write(tp, 0x1D0, 1, csi_tmp, ERIAR_ExGMAC); - } else if (tp->mcfg == CFG_METHOD_23 || tp->mcfg == CFG_METHOD_27 || - tp->mcfg == CFG_METHOD_28) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - rtl8168_eri_write(tp, 0xC8, 4, 0x00080002, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xCC, 1, 0x2F, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xD0, 1, 0x5F, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xE8, 4, 0x00100006, ERIAR_ExGMAC); - - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | BIT_7); - - csi_tmp = rtl8168_eri_read(tp, 0xDC, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_6); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_7); - - rtl8168_eri_write(tp, 0xC0, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xB8, 4, 0x00000000, ERIAR_ExGMAC); - RTL_W8(tp, 0x1B, RTL_R8(tp, 0x1B) & ~0x07); - - RTL_W8(tp, TDFNR, 0x4); - - /* - if (aspm) - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_7); - */ - - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp &= ~BIT_12; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x2FC, 1, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_0 | BIT_1 | BIT_2); - csi_tmp |= (BIT_0 | BIT_1); - rtl8168_eri_write(tp, 0x2FC, 1, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x1D0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_1; - rtl8168_eri_write(tp, 0x1D0, 1, csi_tmp, ERIAR_ExGMAC); - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, MTPS, 0x27); - - if (tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28) { - rtl8168_oob_mutex_lock(tp); - rtl8168_eri_write(tp, 0x5F0, 2, 0x4F87, ERIAR_ExGMAC); - rtl8168_oob_mutex_unlock(tp); - } - - rtl8168_mac_ocp_write(tp, 0xC140, 0xFFFF); - rtl8168_mac_ocp_write(tp, 0xC142, 0xFFFF); - - if (tp->mcfg == CFG_METHOD_28) { - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD3E2); - mac_ocp_data &= 0xF000; - mac_ocp_data |= 0xAFD; - rtl8168_mac_ocp_write(tp, 0xD3E2, mac_ocp_data); - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD3E4); - mac_ocp_data &= 0xFF00; - rtl8168_mac_ocp_write(tp, 0xD3E4, mac_ocp_data); - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xE860); - mac_ocp_data |= BIT_7; - rtl8168_mac_ocp_write(tp, 0xE860, mac_ocp_data); - } - } else if (tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - rtl8168_eri_write(tp, 0xC8, 4, 0x00080002, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xCC, 1, 0x2F, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xD0, 1, 0x5F, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xE8, 4, 0x00100006, ERIAR_ExGMAC); - - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | BIT_7); - - csi_tmp = rtl8168_eri_read(tp, 0xDC, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - - if (tp->RequireAdjustUpsTxLinkPulseTiming) { - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD412); - mac_ocp_data &= ~(0x0FFF); - mac_ocp_data |= tp->SwrCnt1msIni; - rtl8168_mac_ocp_write(tp, 0xD412, mac_ocp_data); - } - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xE056); - mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4); - rtl8168_mac_ocp_write(tp, 0xE056, mac_ocp_data); - if (FALSE == HW_SUPP_SERDES_PHY(tp)) - rtl8168_mac_ocp_write(tp, 0xEA80, 0x0003); - else - rtl8168_mac_ocp_write(tp, 0xEA80, 0x0000); - - rtl8168_oob_mutex_lock(tp); - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xE052); - mac_ocp_data &= ~(BIT_3 | BIT_0); - rtl8168_mac_ocp_write(tp, 0xE052, mac_ocp_data); - rtl8168_oob_mutex_unlock(tp); - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD420); - mac_ocp_data &= ~(BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= 0x45F; - rtl8168_mac_ocp_write(tp, 0xD420, mac_ocp_data); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - RTL_W8(tp, 0x1B, RTL_R8(tp, 0x1B) & ~0x07); - - RTL_W8(tp, TDFNR, 0x4); - - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~PMSTS_En); - - /* - if (aspm) - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_7); - */ - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, MTPS, 0x27); - - if (FALSE == HW_SUPP_SERDES_PHY(tp)) { - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_6); - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_7); - } else { - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) & ~BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_6); - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) & ~BIT_7); - } - - rtl8168_eri_write(tp, 0xC0, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xB8, 4, 0x00000000, ERIAR_ExGMAC); - - rtl8168_oob_mutex_lock(tp); - rtl8168_eri_write(tp, 0x5F0, 2, 0x4000, ERIAR_ExGMAC); - rtl8168_oob_mutex_unlock(tp); - - if (tp->mcfg == CFG_METHOD_32 || tp->mcfg == CFG_METHOD_33) { - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp |= BIT_4; - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - } - - rtl8168_mac_ocp_write(tp, 0xC140, 0xFFFF); - rtl8168_mac_ocp_write(tp, 0xC142, 0xFFFF); - - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp &= ~BIT_12; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x2FC, 1, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_0 | BIT_1); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0x2FC, 1, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x1D0, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_1; - rtl8168_eri_write(tp, 0x1D0, 1, csi_tmp, ERIAR_ExGMAC); - } else if (tp->mcfg == CFG_METHOD_1) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - if (dev->mtu > ETH_DATA_LEN) { - pci_read_config_byte(pdev, 0x69, &device_control); - device_control &= ~0x70; - device_control |= 0x28; - pci_write_config_byte(pdev, 0x69, device_control); - } else { - pci_read_config_byte(pdev, 0x69, &device_control); - device_control &= ~0x70; - device_control |= 0x58; - pci_write_config_byte(pdev, 0x69, device_control); - } - } else if (tp->mcfg == CFG_METHOD_2) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - if (dev->mtu > ETH_DATA_LEN) { - pci_read_config_byte(pdev, 0x69, &device_control); - device_control &= ~0x70; - device_control |= 0x28; - pci_write_config_byte(pdev, 0x69, device_control); - - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | (1 << 0)); - } else { - pci_read_config_byte(pdev, 0x69, &device_control); - device_control &= ~0x70; - device_control |= 0x58; - pci_write_config_byte(pdev, 0x69, device_control); - - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~(1 << 0)); - } - } else if (tp->mcfg == CFG_METHOD_3) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - if (dev->mtu > ETH_DATA_LEN) { - pci_read_config_byte(pdev, 0x69, &device_control); - device_control &= ~0x70; - device_control |= 0x28; - pci_write_config_byte(pdev, 0x69, device_control); - - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | (1 << 0)); - } else { - pci_read_config_byte(pdev, 0x69, &device_control); - device_control &= ~0x70; - device_control |= 0x58; - pci_write_config_byte(pdev, 0x69, device_control); - - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~(1 << 0)); - } - } - - if ((tp->mcfg == CFG_METHOD_1) || (tp->mcfg == CFG_METHOD_2) || (tp->mcfg == CFG_METHOD_3)) { - /* csum offload command for RTL8168B/8111B */ - tp->tx_tcp_csum_cmd = TxTCPCS; - tp->tx_udp_csum_cmd = TxUDPCS; - tp->tx_ip_csum_cmd = TxIPCS; - tp->tx_ipv6_csum_cmd = 0; - } else { - /* csum offload command for RTL8168C/8111C and RTL8168CP/8111CP */ - tp->tx_tcp_csum_cmd = TxTCPCS_C; - tp->tx_udp_csum_cmd = TxUDPCS_C; - tp->tx_ip_csum_cmd = TxIPCS_C; - tp->tx_ipv6_csum_cmd = TxIPV6F_C; - } - - - //other hw parameters - if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_23 || tp->mcfg == CFG_METHOD_24 || - tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28) - rtl8168_eri_write(tp, 0x2F8, 2, 0x1D8F, ERIAR_ExGMAC); - - if (tp->bios_setting & BIT_28) { - if (tp->mcfg == CFG_METHOD_18 || tp->mcfg == CFG_METHOD_19 || - tp->mcfg == CFG_METHOD_20) { - u32 gphy_val; - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - gphy_val = rtl8168_mdio_read(tp, 0x16); - gphy_val |= BIT_10; - rtl8168_mdio_write(tp, 0x16, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_7; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - } - - rtl8168_hw_clear_timer_int(dev); - - rtl8168_enable_exit_l1_mask(tp); - - switch (tp->mcfg) { - case CFG_METHOD_25: - rtl8168_mac_ocp_write(tp, 0xD3C0, 0x0B00); - rtl8168_mac_ocp_write(tp, 0xD3C2, 0x0000); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - rtl8168_mac_ocp_write(tp, 0xE098, 0x0AA2); - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mac_ocp_write(tp, 0xE098, 0xC302); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - if (aspm) { - rtl8168_init_pci_offset_99(tp); - } - break; - } - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - if (aspm) { - rtl8168_init_pci_offset_180(tp); - } - break; - } - - tp->cp_cmd &= ~(EnableBist | Macdbgo_oe | Force_halfdup | - Force_rxflow_en | Force_txflow_en | Cxpl_dbg_sel | - ASF | Macdbgo_sel); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - RTL_W16(tp, CPlusCmd, tp->cp_cmd); -#else - rtl8168_hw_set_features(dev, dev->features); -#endif - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: { - int timeout; - for (timeout = 0; timeout < 10; timeout++) { - if ((rtl8168_eri_read(tp, 0x1AE, 2, ERIAR_ExGMAC) & BIT_13)==0) - break; - mdelay(1); - } - } - break; - } - - RTL_W16(tp, RxMaxSize, tp->rx_buf_sz); - - rtl8168_disable_rxdvgate(dev); - - if (tp->mcfg == CFG_METHOD_11 || tp->mcfg == CFG_METHOD_12) - rtl8168_mac_loopback_test(tp); - - if (!tp->pci_cfg_is_read) { - pci_read_config_byte(pdev, PCI_COMMAND, &tp->pci_cfg_space.cmd); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &tp->pci_cfg_space.io_base_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0 + 2, &tp->pci_cfg_space.io_base_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &tp->pci_cfg_space.mem_base_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &tp->pci_cfg_space.mem_base_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &tp->pci_cfg_space.resv_0x1c_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &tp->pci_cfg_space.resv_0x1c_h); - pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tp->pci_cfg_space.ilr); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &tp->pci_cfg_space.resv_0x20_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &tp->pci_cfg_space.resv_0x20_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &tp->pci_cfg_space.resv_0x24_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &tp->pci_cfg_space.resv_0x24_h); - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->pci_cfg_space.resv_0x2c_l); - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &tp->pci_cfg_space.resv_0x2c_h); - if (tp->HwPcieSNOffset > 0) { - tp->pci_cfg_space.pci_sn_l = rtl8168_csi_read(tp, tp->HwPcieSNOffset); - tp->pci_cfg_space.pci_sn_h = rtl8168_csi_read(tp, tp->HwPcieSNOffset + 4); - } - - tp->pci_cfg_is_read = 1; - } - - rtl8168_dsm(dev, DSM_MAC_INIT); - - /* Set Rx packet filter */ - rtl8168_hw_set_rx_packet_filter(dev); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH && !tp->dash_printer_enabled) - NICChkTypeEnableDashInterrupt(tp); -#endif - - if (tp->HwSuppAspmClkIntrLock) - rtl8168_hw_aspm_clkreq_enable(tp, true); - - rtl8168_disable_cfg9346_write(tp); - - udelay(10); -} - -static void -rtl8168_hw_start(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb); - - rtl8168_enable_hw_interrupt(tp); -} - -static int -rtl8168_change_mtu(struct net_device *dev, - int new_mtu) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int ret = 0; - unsigned long flags; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) - if (new_mtu < ETH_MIN_MTU) - return -EINVAL; - else if (new_mtu > tp->max_jumbo_frame_size) - new_mtu = tp->max_jumbo_frame_size; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) - - spin_lock_irqsave(&tp->lock, flags); - dev->mtu = new_mtu; - spin_unlock_irqrestore(&tp->lock, flags); - - if (!netif_running(dev)) - goto out; - - rtl8168_down(dev); - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_set_rxbufsize(tp, dev); - - ret = rtl8168_init_ring(dev); - - if (ret < 0) { - spin_unlock_irqrestore(&tp->lock, flags); - goto err_out; - } - -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - RTL_NAPI_ENABLE(dev, &tp->napi); -#endif -#endif//CONFIG_R8168_NAPI - - netif_stop_queue(dev); - netif_carrier_off(dev); - rtl8168_hw_config(dev); - spin_unlock_irqrestore(&tp->lock, flags); - - rtl8168_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - - mod_timer(&tp->esd_timer, jiffies + RTL8168_ESD_TIMEOUT); - mod_timer(&tp->link_timer, jiffies + RTL8168_LINK_TIMEOUT); -out: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) - netdev_update_features(dev); -#endif - -err_out: - return ret; -} - -static inline void -rtl8168_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = 0x0badbadbadbadbadull; - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void -rtl8168_free_rx_skb(struct rtl8168_private *tp, - struct sk_buff **sk_buff, - struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - DMA_FROM_DEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8168_make_unusable_by_asic(desc); -} - -static inline void -rtl8168_mark_to_asic(struct RxDesc *desc, - u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void -rtl8168_map_to_asic(struct RxDesc *desc, - dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8168_mark_to_asic(desc, rx_buf_sz); -} - -static int -rtl8168_alloc_rx_skb(struct rtl8168_private *tp, - struct sk_buff **sk_buff, - struct RxDesc *desc, - int rx_buf_sz, - u8 in_intr) -{ - struct sk_buff *skb; - dma_addr_t mapping; - int ret = 0; - - if (in_intr) - skb = RTL_ALLOC_SKB_INTR(tp, rx_buf_sz + RTK_RX_ALIGN); - else - skb = dev_alloc_skb(rx_buf_sz + RTK_RX_ALIGN); - - if (unlikely(!skb)) - goto err_out; - - skb_reserve(skb, RTK_RX_ALIGN); - - mapping = dma_map_single(tp_to_dev(tp), skb->data, rx_buf_sz, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); - goto err_out; - } - - *sk_buff = skb; - rtl8168_map_to_asic(desc, mapping, rx_buf_sz); -out: - return ret; - -err_out: - if (skb) - dev_kfree_skb(skb); - ret = -ENOMEM; - rtl8168_make_unusable_by_asic(desc); - goto out; -} - -static void -rtl8168_rx_clear(struct rtl8168_private *tp) -{ - int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) - rtl8168_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } -} - -static u32 -rtl8168_rx_fill(struct rtl8168_private *tp, - struct net_device *dev, - u32 start, - u32 end, - u8 in_intr) -{ - u32 cur; - - for (cur = start; end - cur > 0; cur++) { - int ret, i = cur % NUM_RX_DESC; - - if (tp->Rx_skbuff[i]) - continue; - - ret = rtl8168_alloc_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i, - tp->rx_buf_sz, - in_intr); - if (ret < 0) - break; - } - return cur - start; -} - -static inline void -rtl8168_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void -rtl8168_desc_addr_fill(struct rtl8168_private *tp) -{ - if (!tp->TxPhyAddr || !tp->RxPhyAddr) - return; - - RTL_W32(tp, TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_BIT_MASK(32))); - RTL_W32(tp, TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32)); - RTL_W32(tp, RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_BIT_MASK(32))); - RTL_W32(tp, RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32)); -} - -static void -rtl8168_tx_desc_init(struct rtl8168_private *tp) -{ - int i = 0; - - memset(tp->TxDescArray, 0x0, NUM_TX_DESC * sizeof(struct TxDesc)); - - for (i = 0; i < NUM_TX_DESC; i++) { - if (i == (NUM_TX_DESC - 1)) - tp->TxDescArray[i].opts1 = cpu_to_le32(RingEnd); - } -} - -static void -rtl8168_rx_desc_offset0_init(struct rtl8168_private *tp, int own) -{ - int i = 0; - int ownbit = 0; - - if (tp->RxDescArray == NULL) return; - - if (own) - ownbit = DescOwn; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (i == (NUM_RX_DESC - 1)) - tp->RxDescArray[i].opts1 = cpu_to_le32((ownbit | RingEnd) | (unsigned long)tp->rx_buf_sz); - else - tp->RxDescArray[i].opts1 = cpu_to_le32(ownbit | (unsigned long)tp->rx_buf_sz); - } -} - -static void -rtl8168_rx_desc_init(struct rtl8168_private *tp) -{ - memset(tp->RxDescArray, 0x0, NUM_RX_DESC * sizeof(struct RxDesc)); -} - -static int -rtl8168_init_ring(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - rtl8168_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - rtl8168_tx_desc_init(tp); - rtl8168_rx_desc_init(tp); - - if (rtl8168_rx_fill(tp, dev, 0, NUM_RX_DESC, 0) != NUM_RX_DESC) - goto err_out; - - rtl8168_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8168_rx_clear(tp); - return -ENOMEM; -} - -static void -rtl8168_unmap_tx_skb(struct pci_dev *pdev, - struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE); - - desc->opts1 = cpu_to_le32(RTK_MAGIC_DEBUG_VALUE); - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8168_tx_clear_range(struct rtl8168_private *tp, u32 start, - unsigned int n) -{ - unsigned int i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - struct net_device *dev = tp->dev; -#endif - - for (i = 0; i < n; i++) { - unsigned int entry = (start + i) % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8168_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - RTLDEV->stats.tx_dropped++; - dev_kfree_skb_any(skb); - tx_skb->skb = NULL; - } - } - } -} - -static void -rtl8168_tx_clear(struct rtl8168_private *tp) -{ - rtl8168_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC); - tp->cur_tx = tp->dirty_tx = 0; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8168_schedule_work(struct net_device *dev, void (*task)(void *)) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - struct rtl8168_private *tp = netdev_priv(dev); - - INIT_WORK(&tp->task, task, dev); - schedule_delayed_work(&tp->task, 4); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -} - -#define rtl8168_cancel_schedule_work(a) - -#else -static void rtl8168_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - INIT_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8168_cancel_schedule_work(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct work_struct *work = &tp->task.work; - - if (!work->func) return; - - cancel_delayed_work_sync(&tp->task); -} -#endif - -static void -rtl8168_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - RTL_NAPI_DISABLE(dev, &tp->napi); -#endif -#endif//CONFIG_R8168_NAPI - - rtl8168_irq_mask_and_ack(tp); - -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - RTL_NAPI_ENABLE(dev, &tp->napi); -#endif -#endif//CONFIG_R8168_NAPI -} - -#if 0 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8168_reinit_task(void *_data) -#else -static void rtl8168_reinit_task(struct work_struct *work) -#endif -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct net_device *dev = _data; -#else - struct rtl8168_private *tp = - container_of(work, struct rtl8168_private, task.work); - struct net_device *dev = tp->dev; -#endif - int ret; - - if (netif_running(dev)) { - rtl8168_wait_for_quiescence(dev); - rtl8168_close(dev); - } - - ret = rtl8168_open(dev); - if (unlikely(ret < 0)) { - if (unlikely(net_ratelimit())) { - struct rtl8168_private *tp = netdev_priv(dev); - - if (netif_msg_drv(tp)) { - printk(PFX KERN_ERR - "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - } - rtl8168_schedule_work(dev, rtl8168_reinit_task); - } -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8168_reset_task(void *_data) -{ - struct net_device *dev = _data; - struct rtl8168_private *tp = netdev_priv(dev); -#else -static void rtl8168_reset_task(struct work_struct *work) -{ - struct rtl8168_private *tp = - container_of(work, struct rtl8168_private, task.work); - struct net_device *dev = tp->dev; -#endif - u32 budget = ~(u32)0; - unsigned long flags; - - if (!netif_running(dev)) - return; - - rtl8168_wait_for_quiescence(dev); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8168_rx_interrupt(dev, tp, &budget); -#else - rtl8168_rx_interrupt(dev, tp, budget); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8168_rx_clear(tp); - rtl8168_init_ring(dev); - rtl8168_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - spin_unlock_irqrestore(&tp->lock, flags); - } else { - spin_unlock_irqrestore(&tp->lock, flags); - if (unlikely(net_ratelimit())) { - struct rtl8168_private *tp = netdev_priv(dev); - - if (netif_msg_intr(tp)) { - printk(PFX KERN_EMERG - "%s: Rx buffers shortage\n", dev->name); - } - } - rtl8168_schedule_work(dev, rtl8168_reset_task); - } -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static void -rtl8168_tx_timeout(struct net_device *dev, unsigned int txqueue) -#else -static void -rtl8168_tx_timeout(struct net_device *dev) -#endif -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - netif_stop_queue(dev); - netif_carrier_off(dev); - rtl8168_hw_reset(dev); - spin_unlock_irqrestore(&tp->lock, flags); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8168_schedule_work(dev, rtl8168_reset_task); -} - -static u32 -rtl8168_get_txd_opts1(u32 opts1, u32 len, unsigned int entry) -{ - u32 status = opts1 | len; - - if (entry == NUM_TX_DESC - 1) - status |= RingEnd; - - return status; -} - -static int -rtl8168_xmit_frags(struct rtl8168_private *tp, - struct sk_buff *skb, - const u32 *opts) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc *txd = NULL; - const unsigned char nr_frags = info->nr_frags; - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; -#else - len = skb_frag_size(frag); - addr = skb_frag_address(frag); -#endif - mapping = dma_map_single(tp_to_dev(tp), addr, len, DMA_TO_DEVICE); - - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, tp->dev, - "Failed to map TX fragments DMA!\n"); - goto err_out; - } - - /* anti gcc 2.95.3 bugware (sic) */ - status = rtl8168_get_txd_opts1(opts[0], len, entry); - if (cur_frag == (nr_frags - 1)) { - tp->tx_skb[entry].skb = skb; - status |= LastFrag; - } - - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - - txd->opts2 = cpu_to_le32(opts[1]); - wmb(); - txd->opts1 = cpu_to_le32(status); - } - - return cur_frag; - -err_out: - rtl8168_tx_clear_range(tp, tp->cur_tx + 1, cur_frag); - return -EIO; -} - -static inline -__be16 get_protocol(struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) - return vlan_get_protocol(skb); -#else - __be16 protocol; - - if (skb->protocol == htons(ETH_P_8021Q)) - protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; - else - protocol = skb->protocol; - - return protocol; -#endif -} - -static bool rtl8168_skb_pad(struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) - if (skb_padto(skb, ETH_ZLEN)) - return false; - skb_put(skb, ETH_ZLEN - skb->len); - return true; -#else - return !eth_skb_pad(skb); -#endif -} - -static inline bool -rtl8168_tx_csum(struct sk_buff *skb, - struct net_device *dev, - u32 *opts) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 csum_cmd = 0; - u8 sw_calc_csum = FALSE; - - if (skb->ip_summed == CHECKSUM_PARTIAL) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - const struct iphdr *ip = skb->nh.iph; - - if (dev->features & NETIF_F_IP_CSUM) { - if (ip->protocol == IPPROTO_TCP) - csum_cmd = tp->tx_ip_csum_cmd | tp->tx_tcp_csum_cmd; - else if (ip->protocol == IPPROTO_UDP) - csum_cmd = tp->tx_ip_csum_cmd | tp->tx_udp_csum_cmd; - else if (ip->protocol == IPPROTO_IP) - csum_cmd = tp->tx_ip_csum_cmd; - } -#else - u8 ip_protocol = IPPROTO_RAW; - - switch (get_protocol(skb)) { - case __constant_htons(ETH_P_IP): - if (dev->features & NETIF_F_IP_CSUM) { - ip_protocol = ip_hdr(skb)->protocol; - csum_cmd = tp->tx_ip_csum_cmd; - } - break; - case __constant_htons(ETH_P_IPV6): - if (dev->features & NETIF_F_IPV6_CSUM) { - u32 transport_offset = (u32)skb_transport_offset(skb); - if (transport_offset > 0 && transport_offset <= TCPHO_MAX) { - ip_protocol = ipv6_hdr(skb)->nexthdr; - csum_cmd = tp->tx_ipv6_csum_cmd; - csum_cmd |= transport_offset << TCPHO_SHIFT; - } - } - break; - default: - if (unlikely(net_ratelimit())) - dprintk("checksum_partial proto=%x!\n", skb->protocol); - break; - } - - if (ip_protocol == IPPROTO_TCP) - csum_cmd |= tp->tx_tcp_csum_cmd; - else if (ip_protocol == IPPROTO_UDP) - csum_cmd |= tp->tx_udp_csum_cmd; -#endif - if (csum_cmd == 0) { - sw_calc_csum = TRUE; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - WARN_ON(1); /* we need a WARN() */ -#endif - } - } - - if (csum_cmd != 0) { - if (tp->ShortPacketSwChecksum && skb->len < ETH_ZLEN) { - sw_calc_csum = TRUE; - if (!rtl8168_skb_pad(skb)) - return false; - } else { - if ((tp->mcfg == CFG_METHOD_1) || (tp->mcfg == CFG_METHOD_2) || (tp->mcfg == CFG_METHOD_3)) - opts[0] |= csum_cmd; - else - opts[1] |= csum_cmd; - } - } - - if (tp->UseSwPaddingShortPkt && skb->len < ETH_ZLEN) - if (!rtl8168_skb_pad(skb)) - return false; - - if (sw_calc_csum) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7) - skb_checksum_help(&skb, 0); -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) - skb_checksum_help(skb, 0); -#else - skb_checksum_help(skb); -#endif - } - - return true; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) -/* r8169_csum_workaround() - * The hw limits the value the transport offset. When the offset is out of the - * range, calculate the checksum by sw. - */ -static void r8168_csum_workaround(struct rtl8168_private *tp, - struct sk_buff *skb) -{ - if (skb_shinfo(skb)->gso_size) { - netdev_features_t features = tp->dev->features; - struct sk_buff *segs, *nskb; - - features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6); - segs = skb_gso_segment(skb, features); - if (IS_ERR(segs) || !segs) - goto drop; - - do { - nskb = segs; - segs = segs->next; - nskb->next = NULL; - rtl8168_start_xmit(nskb, tp->dev); - } while (segs); - - dev_consume_skb_any(skb); - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - if (skb_checksum_help(skb) < 0) - goto drop; - - rtl8168_start_xmit(skb, tp->dev); - } else { - struct net_device_stats *stats; - -drop: - stats = &tp->dev->stats; - stats->tx_dropped++; - dev_kfree_skb_any(skb); - } -} - -/* msdn_giant_send_check() - * According to the document of microsoft, the TCP Pseudo Header excludes the - * packet length for IPv6 TCP large packets. - */ -static int msdn_giant_send_check(struct sk_buff *skb) -{ - const struct ipv6hdr *ipv6h; - struct tcphdr *th; - int ret; - - ret = skb_cow_head(skb, 0); - if (ret) - return ret; - - ipv6h = ipv6_hdr(skb); - th = tcp_hdr(skb); - - th->check = 0; - th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0); - - return ret; -} -#endif - -static bool rtl8168_tx_slots_avail(struct rtl8168_private *tp, - unsigned int nr_frags) -{ - unsigned int slots_avail = tp->dirty_tx + NUM_TX_DESC - tp->cur_tx; - - /* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */ - return slots_avail > nr_frags; -} - -static netdev_tx_t -rtl8168_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int entry; - struct TxDesc *txd; - dma_addr_t mapping; - u32 len; - u32 opts[2]; - netdev_tx_t ret = NETDEV_TX_OK; - unsigned long flags, large_send; - int frags; - - spin_lock_irqsave(&tp->lock, flags); - - if (unlikely(!rtl8168_tx_slots_avail(tp, skb_shinfo(skb)->nr_frags))) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - entry = tp->cur_tx % NUM_TX_DESC; - txd = tp->TxDescArray + entry; - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Desc is own by hardware!\n", - dev->name); - } - goto err_stop; - } - - opts[0] = DescOwn; - opts[1] = rtl8168_tx_vlan_tag(tp, skb); - - large_send = 0; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) - u32 mss = skb_shinfo(skb)->tso_size; -#else - u32 mss = skb_shinfo(skb)->gso_size; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) - - /* TCP Segmentation Offload (or TCP Large Send) */ - if (mss) { - if ((tp->mcfg == CFG_METHOD_1) || - (tp->mcfg == CFG_METHOD_2) || - (tp->mcfg == CFG_METHOD_3)) { - opts[0] |= LargeSend | (min(mss, MSS_MAX) << 16); - large_send = 1; - } else { - u32 transport_offset = (u32)skb_transport_offset(skb); - switch (get_protocol(skb)) { - case __constant_htons(ETH_P_IP): - if (transport_offset <= GTTCPHO_MAX) { - opts[0] |= GiantSendv4; - opts[0] |= transport_offset << GTTCPHO_SHIFT; - opts[1] |= min(mss, MSS_MAX) << 18; - large_send = 1; - } - break; - case __constant_htons(ETH_P_IPV6): -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) - if (msdn_giant_send_check(skb)) { - spin_unlock_irqrestore(&tp->lock, flags); - r8168_csum_workaround(tp, skb); - goto out; - } -#endif - if (transport_offset <= GTTCPHO_MAX) { - opts[0] |= GiantSendv6; - opts[0] |= transport_offset << GTTCPHO_SHIFT; - opts[1] |= min(mss, MSS_MAX) << 18; - large_send = 1; - } - break; - default: - if (unlikely(net_ratelimit())) - dprintk("tso proto=%x!\n", skb->protocol); - break; - } - } - - if (large_send == 0) - goto err_dma_0; - } - } -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - - if (large_send == 0) { - if (unlikely(!rtl8168_tx_csum(skb, dev, opts))) - goto err_dma_0; - } - - frags = rtl8168_xmit_frags(tp, skb, opts); - if (unlikely(frags < 0)) - goto err_dma_0; - if (frags) { - len = skb_headlen(skb); - opts[0] |= FirstFrag; - } else { - len = skb->len; - - tp->tx_skb[entry].skb = skb; - - opts[0] |= FirstFrag | LastFrag; - } - - opts[0] = rtl8168_get_txd_opts1(opts[0], len, entry); - mapping = dma_map_single(tp_to_dev(tp), skb->data, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, dev, "Failed to map TX DMA!\n"); - goto err_dma_1; - } - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(opts[1]); - wmb(); - txd->opts1 = cpu_to_le32(opts[0]); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) - dev->trans_start = jiffies; -#else - skb_tx_timestamp(skb); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) - - tp->cur_tx += frags + 1; - - wmb(); - - RTL_W8(tp, TxPoll, NPQ); /* set polling bit */ - - if (!rtl8168_tx_slots_avail(tp, MAX_SKB_FRAGS)) { - netif_stop_queue(dev); - smp_rmb(); - if (rtl8168_tx_slots_avail(tp, MAX_SKB_FRAGS)) - netif_wake_queue(dev); - } - - spin_unlock_irqrestore(&tp->lock, flags); -out: - return ret; -err_dma_1: - tp->tx_skb[entry].skb = NULL; - rtl8168_tx_clear_range(tp, tp->cur_tx + 1, frags); -err_dma_0: - RTLDEV->stats.tx_dropped++; - spin_unlock_irqrestore(&tp->lock, flags); - dev_kfree_skb_any(skb); - ret = NETDEV_TX_OK; - goto out; -err_stop: - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; - RTLDEV->stats.tx_dropped++; - - spin_unlock_irqrestore(&tp->lock, flags); - goto out; -} - -static void -rtl8168_tx_interrupt(struct net_device *dev, - struct rtl8168_private *tp) -{ - unsigned int dirty_tx, tx_left; - - assert(dev != NULL); - assert(tp != NULL); - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - tp->dynamic_aspm_packet_count += tx_left; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - RTLDEV->stats.tx_bytes += len; - RTLDEV->stats.tx_packets++; - - rtl8168_unmap_tx_skb(tp->pci_dev, - tx_skb, - tp->TxDescArray + entry); - - if (tx_skb->skb!=NULL) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) - dev_consume_skb_any(tx_skb->skb); -#else - dev_kfree_skb_any(tx_skb->skb); -#endif - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - tp->dynamic_aspm_packet_count -= tx_left; - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (netif_queue_stopped(dev) && - (rtl8168_tx_slots_avail(tp, MAX_SKB_FRAGS))) { - netif_wake_queue(dev); - } - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(tp, TxPoll, NPQ); - } -} - -static inline int -rtl8168_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void -rtl8168_rx_csum(struct rtl8168_private *tp, - struct sk_buff *skb, - struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 opts2 = le32_to_cpu(desc->opts2); - - if ((tp->mcfg == CFG_METHOD_1) || - (tp->mcfg == CFG_METHOD_2) || - (tp->mcfg == CFG_METHOD_3)) { - u32 status = opts1 & RxProtoMask; - - /* rx csum offload for RTL8168B/8111B */ - if (((status == RxProtoTCP) && !(opts1 & (RxTCPF | RxIPF))) || - ((status == RxProtoUDP) && !(opts1 & (RxUDPF | RxIPF)))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - } else { - /* rx csum offload for RTL8168C/8111C and RTL8168CP/8111CP */ - if (((opts2 & RxV4F) && !(opts1 & RxIPF)) || (opts2 & RxV6F)) { - if (((opts1 & RxTCPT) && !(opts1 & RxTCPF)) || - ((opts1 & RxUDPT) && !(opts1 & RxUDPF))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - } else - skb->ip_summed = CHECKSUM_NONE; - } -} - -static inline int -rtl8168_try_rx_copy(struct rtl8168_private *tp, - struct sk_buff **sk_buff, - int pkt_size, - struct RxDesc *desc, - int rx_buf_sz) -{ - int ret = -1; - - if (pkt_size < rx_copybreak) { - struct sk_buff *skb; - - skb = RTL_ALLOC_SKB_INTR(tp, pkt_size + RTK_RX_ALIGN); - if (skb) { - u8 *data; - - data = sk_buff[0]->data; - skb_reserve(skb, RTK_RX_ALIGN); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) - prefetch(data - RTK_RX_ALIGN); -#endif - eth_copy_and_sum(skb, data, pkt_size, 0); - *sk_buff = skb; - rtl8168_mark_to_asic(desc, rx_buf_sz); - ret = 0; - } - } - return ret; -} - -static inline void -rtl8168_rx_skb(struct rtl8168_private *tp, - struct sk_buff *skb) -{ -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - netif_receive_skb(skb); -#else - napi_gro_receive(&tp->napi, skb); -#endif -#else - netif_rx(skb); -#endif -} - -static int -rtl8168_rx_interrupt(struct net_device *dev, - struct rtl8168_private *tp, - napi_budget budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count = 0; - unsigned int entry; - struct RxDesc *desc; - u32 status; - u32 rx_quota; - - assert(dev != NULL); - assert(tp != NULL); - - if (tp->RxDescArray == NULL) - goto rx_out; - - rx_quota = RTL_RX_QUOTA(budget); - cur_rx = tp->cur_rx; - entry = cur_rx % NUM_RX_DESC; - desc = tp->RxDescArray + entry; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = rtl8168_rx_quota(rx_left, (u32)rx_quota); - - for (; rx_left > 0; rx_left--) { - rmb(); - status = le32_to_cpu(desc->opts1); - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - - RTLDEV->stats.rx_errors++; - - if (status & (RxRWT | RxRUNT)) - RTLDEV->stats.rx_length_errors++; - if (status & RxCRC) - RTLDEV->stats.rx_crc_errors++; - if (dev->features & NETIF_F_RXALL) - goto process_pkt; - - rtl8168_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb; - int pkt_size; - -process_pkt: - if (likely(!(dev->features & NETIF_F_RXFCS))) - pkt_size = (status & 0x00003fff) - 4; - else - pkt_size = status & 0x00003fff; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8168_fragmented_frame(status))) { - RTLDEV->stats.rx_dropped++; - RTLDEV->stats.rx_length_errors++; - rtl8168_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - skb = tp->Rx_skbuff[entry]; - - dma_sync_single_for_cpu(tp_to_dev(tp), - le64_to_cpu(desc->addr), tp->rx_buf_sz, - DMA_FROM_DEVICE); - - if (rtl8168_try_rx_copy(tp, &skb, pkt_size, - desc, tp->rx_buf_sz)) { - tp->Rx_skbuff[entry] = NULL; - dma_unmap_single(tp_to_dev(tp), le64_to_cpu(desc->addr), - tp->rx_buf_sz, DMA_FROM_DEVICE); - } else { - dma_sync_single_for_device(tp_to_dev(tp), le64_to_cpu(desc->addr), - tp->rx_buf_sz, DMA_FROM_DEVICE); - } - - if (tp->cp_cmd & RxChkSum) - rtl8168_rx_csum(tp, skb, desc); - - skb->dev = dev; - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (skb->pkt_type == PACKET_MULTICAST) - RTLDEV->stats.multicast++; - - if (rtl8168_rx_vlan_skb(tp, desc, skb) < 0) - rtl8168_rx_skb(tp, skb); -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) - dev->last_rx = jiffies; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) - RTLDEV->stats.rx_bytes += pkt_size; - RTLDEV->stats.rx_packets++; - } - - cur_rx++; - entry = cur_rx % NUM_RX_DESC; - desc = tp->RxDescArray + entry; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) - prefetch(desc); -#endif - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - delta = rtl8168_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx, 1); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - tp->dynamic_aspm_packet_count += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - -rx_out: - return count; -} - -/* - *The interrupt handler does all of the Rx thread work and cleans up after - *the Tx thread. - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8168_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -#else -static irqreturn_t rtl8168_interrupt(int irq, void *dev_instance) -#endif -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8168_private *tp = netdev_priv(dev); - int status; - int handled = 0; - - do { - status = RTL_R16(tp, IntrStatus); - - if (!(tp->features & RTL_FEATURE_MSI)) { - /* hotplug/major error/no more work/shared irq */ - if ((status == 0xFFFF) || !status) - break; - - if (!(status & (tp->intr_mask | tp->timer_intr_mask))) - break; - } - - handled = 1; - - rtl8168_disable_hw_interrupt(tp); - - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - /* RX_OVERFLOW RE-START mechanism now HW handles it automatically*/ - RTL_W16(tp, IntrStatus, status&~RxFIFOOver); - break; - default: - RTL_W16(tp, IntrStatus, status); - break; - } - - //Work around for rx fifo overflow - if (unlikely(status & RxFIFOOver)) { - if (tp->mcfg == CFG_METHOD_1) { - netif_stop_queue(dev); - udelay(300); - rtl8168_hw_reset(dev); - rtl8168_tx_clear(tp); - rtl8168_rx_clear(tp); - rtl8168_init_ring(dev); - rtl8168_hw_config(dev); - rtl8168_hw_start(dev); - netif_wake_queue(dev); - } - } - -#ifdef ENABLE_DASH_SUPPORT - if ( tp->DASH ) { - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - u8 DashIntType2Status; - - if (status & ISRIMR_DASH_INTR_CMAC_RESET) - tp->CmacResetIntr = TRUE; - - DashIntType2Status = RTL_CMAC_R8(tp, CMAC_IBISR0); - if (DashIntType2Status & ISRIMR_DASH_TYPE2_ROK) { - tp->RcvFwDashOkEvt = TRUE; - } - if (DashIntType2Status & ISRIMR_DASH_TYPE2_TOK) { - tp->SendFwHostOkEvt = TRUE; - } - if (DashIntType2Status & ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE) { - tp->DashFwDisableRx = TRUE; - } - - RTL_CMAC_W8(tp, CMAC_IBISR0, DashIntType2Status); - } else { - if (status & ISRIMR_DP_REQSYS_OK) { - tp->RcvFwReqSysOkEvt = TRUE; - } - if (status & ISRIMR_DP_DASH_OK) { - tp->RcvFwDashOkEvt = TRUE; - } - if (status & ISRIMR_DP_HOST_OK) { - tp->SendFwHostOkEvt = TRUE; - } - } - } -#endif - -#ifdef CONFIG_R8168_NAPI - if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { - if (status & tp->intr_mask) - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - - if (likely(RTL_NETIF_RX_SCHEDULE_PREP(dev, &tp->napi))) - __RTL_NETIF_RX_SCHEDULE(dev, &tp->napi); - else if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } else { - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - rtl8168_switch_to_hw_interrupt(tp); - } -#else - if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { - u32 budget = ~(u32)0; - - if (status & tp->intr_mask) - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8168_rx_interrupt(dev, tp, &budget); -#else - rtl8168_rx_interrupt(dev, tp, budget); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8168_tx_interrupt(dev, tp); - -#ifdef ENABLE_DASH_SUPPORT - if ( tp->DASH ) { - struct net_device *dev = tp->dev; - - HandleDashInterrupt(dev); - } -#endif - - rtl8168_switch_to_timer_interrupt(tp); - } else { - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - rtl8168_switch_to_hw_interrupt(tp); - } -#endif - - } while (false); - - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_R8168_NAPI -static int rtl8168_poll(napi_ptr napi, napi_budget budget) -{ - struct rtl8168_private *tp = RTL_GET_PRIV(napi, struct rtl8168_private); - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done; - unsigned long flags; - - work_done = rtl8168_rx_interrupt(dev, tp, budget); - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_tx_interrupt(dev, tp); - spin_unlock_irqrestore(&tp->lock, flags); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#ifdef ENABLE_DASH_SUPPORT - if ( tp->DASH ) { - struct net_device *dev = tp->dev; - - spin_lock_irqsave(&tp->lock, flags); - HandleDashInterrupt(dev); - spin_unlock_irqrestore(&tp->lock, flags); - } -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8168_switch_to_timer_interrupt(tp); - } - - return RTL_NAPI_RETURN_VALUE; -} -#endif//CONFIG_R8168_NAPI - -static void rtl8168_sleep_rx_enable(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (tp->wol_enabled != WOL_ENABLED) return; - - if ((tp->mcfg == CFG_METHOD_1) || (tp->mcfg == CFG_METHOD_2)) { - RTL_W8(tp, ChipCmd, CmdReset); - rtl8168_rx_desc_offset0_init(tp, 0); - RTL_W8(tp, ChipCmd, CmdRxEnb); - } else if (tp->mcfg == CFG_METHOD_14 || tp->mcfg == CFG_METHOD_15) { - rtl8168_ephy_write(tp, 0x19, 0xFF64); - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); - } -} - -static void rtl8168_down(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - rtl8168_delete_esd_timer(dev, &tp->esd_timer); - - rtl8168_delete_link_timer(dev, &tp->link_timer); - -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - RTL_NAPI_DISABLE(dev, &tp->napi); -#endif -#endif//CONFIG_R8168_NAPI - - netif_stop_queue(dev); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_rcu(); /* FIXME: should this be synchronize_irq()? */ -#endif - - spin_lock_irqsave(&tp->lock, flags); - - netif_carrier_off(dev); - - rtl8168_dsm(dev, DSM_IF_DOWN); - - rtl8168_hw_reset(dev); - - spin_unlock_irqrestore(&tp->lock, flags); - - synchronize_irq(dev->irq); - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_tx_clear(tp); - - rtl8168_rx_clear(tp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8168_close(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - unsigned long flags; - - if (tp->TxDescArray!=NULL && tp->RxDescArray!=NULL) { - rtl8168_cancel_schedule_work(dev); - - rtl8168_down(dev); - - pci_clear_master(tp->pci_dev); - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_hw_d3_para(dev); - - rtl8168_powerdown_pll(dev); - - rtl8168_sleep_rx_enable(dev); - - spin_unlock_irqrestore(&tp->lock, flags); - - free_irq(dev->irq, dev); - - dma_free_coherent(&pdev->dev, R8168_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - dma_free_coherent(&pdev->dev, R8168_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - } else { - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_hw_d3_para(dev); - - rtl8168_powerdown_pll(dev); - - spin_unlock_irqrestore(&tp->lock, flags); - } - - return 0; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) -static void rtl8168_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8168_private *tp = netdev_priv(dev); - - if (HW_DASH_SUPPORT_DASH(tp)) - rtl8168_driver_stop(tp); - - rtl8168_set_bios_setting(dev); - if (s5_keep_curr_mac == 0 && tp->random_mac == 0) - rtl8168_rar_set(tp, tp->org_mac_addr); - -#ifdef ENABLE_FIBER_SUPPORT - rtl8168_hw_fiber_nic_d3_para(dev); -#endif //ENABLE_FIBER_SUPPORT - - if (s5wol == 0) - tp->wol_enabled = WOL_DISABLED; - - rtl8168_close(dev); - rtl8168_disable_msi(pdev, tp); - - if (system_state == SYSTEM_POWER_OFF) { - pci_clear_master(tp->pci_dev); - rtl8168_sleep_rx_enable(dev); - pci_wake_from_d3(pdev, tp->wol_enabled); - pci_set_power_state(pdev, PCI_D3hot); - } -} -#endif - -/** - * rtl8168_get_stats - Get rtl8168 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8168 - */ -static struct -net_device_stats *rtl8168_get_stats(struct net_device *dev) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - struct rtl8168_private *tp = netdev_priv(dev); -#endif - if (netif_running(dev)) { -// spin_lock_irqsave(&tp->lock, flags); -// spin_unlock_irqrestore(&tp->lock, flags); - } - - return &RTLDEV->stats; -} - -#ifdef CONFIG_PM - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) -static int -rtl8168_suspend(struct pci_dev *pdev, u32 state) -#else -static int -rtl8168_suspend(struct pci_dev *pdev, pm_message_t state) -#endif -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8168_private *tp = netdev_priv(dev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - u32 pci_pm_state = pci_choose_state(pdev, state); -#endif - unsigned long flags; - - if (!netif_running(dev)) - goto out; - - rtl8168_cancel_schedule_work(dev); - - rtl8168_delete_esd_timer(dev, &tp->esd_timer); - - rtl8168_delete_link_timer(dev, &tp->link_timer); - - netif_stop_queue(dev); - - netif_carrier_off(dev); - - netif_device_detach(dev); - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_dsm(dev, DSM_NIC_GOTO_D3); - - rtl8168_hw_reset(dev); - - pci_clear_master(pdev); - - rtl8168_hw_d3_para(dev); - -#ifdef ENABLE_FIBER_SUPPORT - rtl8168_hw_fiber_nic_d3_para(dev); -#endif //ENABLE_FIBER_SUPPORT - - rtl8168_powerdown_pll(dev); - - rtl8168_sleep_rx_enable(dev); - - spin_unlock_irqrestore(&tp->lock, flags); - -out: - if (HW_DASH_SUPPORT_DASH(tp)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8168_driver_stop(tp); - spin_unlock_irqrestore(&tp->lock, flags); - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - pci_save_state(pdev, &pci_pm_state); -#else - pci_save_state(pdev); -#endif - pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled); -// pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int -rtl8168_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - u32 pci_pm_state = PCI_D0; -#endif - - pci_set_power_state(pdev, PCI_D0); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - pci_restore_state(pdev, &pci_pm_state); -#else - pci_restore_state(pdev); -#endif - pci_enable_wake(pdev, PCI_D0, 0); - - spin_lock_irqsave(&tp->lock, flags); - - /* restore last modified mac address */ - rtl8168_rar_set(tp, dev->dev_addr); - - spin_unlock_irqrestore(&tp->lock, flags); - - if (!netif_running(dev)) { - if (HW_DASH_SUPPORT_DASH(tp)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8168_driver_start(tp); - spin_unlock_irqrestore(&tp->lock, flags); - } - goto out; - } - - pci_set_master(pdev); - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_exit_oob(dev); - - rtl8168_dsm(dev, DSM_NIC_RESUME_D3); - - rtl8168_hw_init(dev); - - rtl8168_powerup_pll(dev); - - rtl8168_hw_ephy_config(dev); - - rtl8168_hw_phy_config(dev); - - rtl8168_hw_config(dev); - - spin_unlock_irqrestore(&tp->lock, flags); - - rtl8168_schedule_work(dev, rtl8168_reset_task); - - netif_device_attach(dev); - - mod_timer(&tp->esd_timer, jiffies + RTL8168_ESD_TIMEOUT); - mod_timer(&tp->link_timer, jiffies + RTL8168_LINK_TIMEOUT); -out: - return 0; -} - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8168_pci_driver = { - .name = MODULENAME, - .id_table = rtl8168_pci_tbl, - .probe = rtl8168_init_one, - .remove = __devexit_p(rtl8168_remove_one), -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) - .shutdown = rtl8168_shutdown, -#endif -#ifdef CONFIG_PM - .suspend = rtl8168_suspend, - .resume = rtl8168_resume, -#endif -}; - -static int __init -rtl8168_init_module(void) -{ -#ifdef ENABLE_R8168_PROCFS - rtl8168_proc_module_init(); -#endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - return pci_register_driver(&rtl8168_pci_driver); -#else - return pci_module_init(&rtl8168_pci_driver); -#endif -} - -static void __exit -rtl8168_cleanup_module(void) -{ - pci_unregister_driver(&rtl8168_pci_driver); -#ifdef ENABLE_R8168_PROCFS - if (rtl8168_proc) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - remove_proc_subtree(MODULENAME, init_net.proc_net); -#else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) - remove_proc_entry(MODULENAME, init_net.proc_net); -#else - remove_proc_entry(MODULENAME, proc_net); -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - rtl8168_proc = NULL; - } -#endif -} - -module_init(rtl8168_init_module); -module_exit(rtl8168_cleanup_module); diff --git a/addons/r8168/src/3.10.108/r8168_realwow.h b/addons/r8168/src/3.10.108/r8168_realwow.h deleted file mode 100644 index 28e2579e..00000000 --- a/addons/r8168/src/3.10.108/r8168_realwow.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_R8168_REALWOW_H -#define _LINUX_R8168_REALWOW_H - -#define SIOCDEVPRIVATE_RTLREALWOW SIOCDEVPRIVATE+3 - -#define MAX_RealWoW_KCP_SIZE (100) -#define MAX_RealWoW_Payload (64) - -#define KA_TX_PACKET_SIZE (100) -#define KA_WAKEUP_PATTERN_SIZE (120) - -//HwSuppKeepAliveOffloadVer -#define HW_SUPPORT_KCP_OFFLOAD(_M) ((_M)->HwSuppKCPOffloadVer > 0) - -enum rtl_realwow_cmd { - - RTL_REALWOW_SET_KCP_DISABLE=0, - RTL_REALWOW_SET_KCP_INFO, - RTL_REALWOW_SET_KCP_CONTENT, - - RTL_REALWOW_SET_KCP_ACKPKTINFO, - RTL_REALWOW_SET_KCP_WPINFO, - RTL_REALWOW_SET_KCPDHCP_TIMEOUT, - - RTLT_REALWOW_COMMAND_INVALID -}; - -struct rtl_realwow_ioctl_struct { - __u32 cmd; - __u32 offset; - __u32 len; - union { - __u32 data; - void *data_buffer; - }; -}; - -typedef struct _MP_KCPInfo { - u8 DIPv4[4]; - u8 MacID[6]; - u16 UdpPort[2]; - u8 PKTLEN[2]; - - u16 ackLostCnt; - u8 KCP_WakePattern[MAX_RealWoW_Payload]; - u8 KCP_AckPacket[MAX_RealWoW_Payload]; - u32 KCP_interval; - u8 KCP_WakePattern_Len; - u8 KCP_AckPacket_Len; - u8 KCP_TxPacket[2][KA_TX_PACKET_SIZE]; -} MP_KCP_INFO, *PMP_KCP_INFO; - -typedef struct _KCPInfo { - u32 nId; // = id - u8 DIPv4[4]; - u8 MacID[6]; - u16 UdpPort; - u16 PKTLEN; -} KCPInfo, *PKCPInfo; - -typedef struct _KCPContent { - u32 id; // = id - u32 mSec; // = msec - u32 size; // =size - u8 bPacket[MAX_RealWoW_KCP_SIZE]; // put packet here -} KCPContent, *PKCPContent; - -typedef struct _RealWoWAckPktInfo { - u16 ackLostCnt; - u16 patterntSize; - u8 pattern[MAX_RealWoW_Payload]; -} RealWoWAckPktInfo,*PRealWoWAckPktInfo; - -typedef struct _RealWoWWPInfo { - u16 patterntSize; - u8 pattern[MAX_RealWoW_Payload]; -} RealWoWWPInfo,*PRealWoWWPInfo; - -int rtl8168_realwow_ioctl(struct net_device *dev, struct ifreq *ifr); -void rtl8168_realwow_hw_init(struct net_device *dev); -void rtl8168_get_realwow_hw_version(struct net_device *dev); -void rtl8168_set_realwow_d3_para(struct net_device *dev); - -#endif /* _LINUX_R8168_REALWOW_H */ diff --git a/addons/r8168/src/3.10.108/rtl_eeprom.c b/addons/r8168/src/3.10.108/rtl_eeprom.c deleted file mode 100644 index 51bd3a12..00000000 --- a/addons/r8168/src/3.10.108/rtl_eeprom.c +++ /dev/null @@ -1,289 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include - -#include "r8168.h" -#include "rtl_eeprom.h" - -//------------------------------------------------------------------- -//rtl8168_eeprom_type(): -// tell the eeprom type -//return value: -// 0: the eeprom type is 93C46 -// 1: the eeprom type is 93C56 or 93C66 -//------------------------------------------------------------------- -void rtl8168_eeprom_type(struct rtl8168_private *tp) -{ - u16 magic = 0; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - goto out_no_eeprom; - - if(RTL_R8(tp, 0xD2)&0x04) { - //not support - //tp->eeprom_type = EEPROM_TWSI; - //tp->eeprom_len = 256; - goto out_no_eeprom; - } else if(RTL_R32(tp, RxConfig) & RxCfg_9356SEL) { - tp->eeprom_type = EEPROM_TYPE_93C56; - tp->eeprom_len = 256; - } else { - tp->eeprom_type = EEPROM_TYPE_93C46; - tp->eeprom_len = 128; - } - - magic = rtl8168_eeprom_read_sc(tp, 0); - -out_no_eeprom: - if ((magic != 0x8129) && (magic != 0x8128)) { - tp->eeprom_type = EEPROM_TYPE_NONE; - tp->eeprom_len = 0; - } -} - -void rtl8168_eeprom_cleanup(struct rtl8168_private *tp) -{ - u8 x; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EECS); - - RTL_W8(tp, Cfg9346, x); - - rtl8168_raise_clock(tp, &x); - rtl8168_lower_clock(tp, &x); -} - -int rtl8168_eeprom_cmd_done(struct rtl8168_private *tp) -{ - u8 x; - int i; - - rtl8168_stand_by(tp); - - for (i = 0; i < 50000; i++) { - x = RTL_R8(tp, Cfg9346); - - if (x & Cfg9346_EEDO) { - udelay(RTL_CLOCK_RATE * 2 * 3); - return 0; - } - udelay(1); - } - - return -1; -} - -//------------------------------------------------------------------- -//rtl8168_eeprom_read_sc(): -// read one word from eeprom -//------------------------------------------------------------------- -u16 rtl8168_eeprom_read_sc(struct rtl8168_private *tp, u16 reg) -{ - int addr_sz = 6; - u8 x; - u16 data; - - if(tp->eeprom_type == EEPROM_TYPE_NONE) { - return -1; - } - - if (tp->eeprom_type==EEPROM_TYPE_93C46) - addr_sz = 6; - else if (tp->eeprom_type==EEPROM_TYPE_93C56) - addr_sz = 8; - - x = Cfg9346_EEM1 | Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); - - rtl8168_shift_out_bits(tp, RTL_EEPROM_READ_OPCODE, 3); - rtl8168_shift_out_bits(tp, reg, addr_sz); - - data = rtl8168_shift_in_bits(tp); - - rtl8168_eeprom_cleanup(tp); - - RTL_W8(tp, Cfg9346, 0); - - return data; -} - -//------------------------------------------------------------------- -//rtl8168_eeprom_write_sc(): -// write one word to a specific address in the eeprom -//------------------------------------------------------------------- -void rtl8168_eeprom_write_sc(struct rtl8168_private *tp, u16 reg, u16 data) -{ - u8 x; - int addr_sz = 6; - int w_dummy_addr = 4; - - if(tp->eeprom_type == EEPROM_TYPE_NONE) { - return ; - } - - if (tp->eeprom_type==EEPROM_TYPE_93C46) { - addr_sz = 6; - w_dummy_addr = 4; - } else if (tp->eeprom_type==EEPROM_TYPE_93C56) { - addr_sz = 8; - w_dummy_addr = 6; - } - - x = Cfg9346_EEM1 | Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); - - rtl8168_shift_out_bits(tp, RTL_EEPROM_EWEN_OPCODE, 5); - rtl8168_shift_out_bits(tp, reg, w_dummy_addr); - rtl8168_stand_by(tp); - - rtl8168_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3); - rtl8168_shift_out_bits(tp, reg, addr_sz); - if (rtl8168_eeprom_cmd_done(tp) < 0) { - return; - } - rtl8168_stand_by(tp); - - rtl8168_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3); - rtl8168_shift_out_bits(tp, reg, addr_sz); - rtl8168_shift_out_bits(tp, data, 16); - if (rtl8168_eeprom_cmd_done(tp) < 0) { - return; - } - rtl8168_stand_by(tp); - - rtl8168_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5); - rtl8168_shift_out_bits(tp, reg, w_dummy_addr); - - rtl8168_eeprom_cleanup(tp); - RTL_W8(tp, Cfg9346, 0); -} - -void rtl8168_raise_clock(struct rtl8168_private *tp, u8 *x) -{ - *x = *x | Cfg9346_EESK; - RTL_W8(tp, Cfg9346, *x); - udelay(RTL_CLOCK_RATE); -} - -void rtl8168_lower_clock(struct rtl8168_private *tp, u8 *x) -{ - - *x = *x & ~Cfg9346_EESK; - RTL_W8(tp, Cfg9346, *x); - udelay(RTL_CLOCK_RATE); -} - -void rtl8168_shift_out_bits(struct rtl8168_private *tp, int data, int count) -{ - u8 x; - int mask; - - mask = 0x01 << (count - 1); - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); - - do { - if (data & mask) - x |= Cfg9346_EEDI; - else - x &= ~Cfg9346_EEDI; - - RTL_W8(tp, Cfg9346, x); - udelay(RTL_CLOCK_RATE); - rtl8168_raise_clock(tp, &x); - rtl8168_lower_clock(tp, &x); - mask = mask >> 1; - } while(mask); - - x &= ~Cfg9346_EEDI; - RTL_W8(tp, Cfg9346, x); -} - -u16 rtl8168_shift_in_bits(struct rtl8168_private *tp) -{ - u8 x; - u16 d, i; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); - - d = 0; - - for (i = 0; i < 16; i++) { - d = d << 1; - rtl8168_raise_clock(tp, &x); - - x = RTL_R8(tp, Cfg9346); - x &= ~Cfg9346_EEDI; - - if (x & Cfg9346_EEDO) - d |= 1; - - rtl8168_lower_clock(tp, &x); - } - - return d; -} - -void rtl8168_stand_by(struct rtl8168_private *tp) -{ - u8 x; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EECS | Cfg9346_EESK); - RTL_W8(tp, Cfg9346, x); - udelay(RTL_CLOCK_RATE); - - x |= Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); -} - -void rtl8168_set_eeprom_sel_low(struct rtl8168_private *tp) -{ - RTL_W8(tp, Cfg9346, Cfg9346_EEM1); - RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK); - - udelay(20); - - RTL_W8(tp, Cfg9346, Cfg9346_EEM1); -} diff --git a/addons/r8168/src/3.10.108/rtl_eeprom.h b/addons/r8168/src/3.10.108/rtl_eeprom.h deleted file mode 100644 index 861defd0..00000000 --- a/addons/r8168/src/3.10.108/rtl_eeprom.h +++ /dev/null @@ -1,56 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -//EEPROM opcodes -#define RTL_EEPROM_READ_OPCODE 06 -#define RTL_EEPROM_WRITE_OPCODE 05 -#define RTL_EEPROM_ERASE_OPCODE 07 -#define RTL_EEPROM_EWEN_OPCODE 19 -#define RTL_EEPROM_EWDS_OPCODE 16 - -#define RTL_CLOCK_RATE 3 - -void rtl8168_eeprom_type(struct rtl8168_private *tp); -void rtl8168_eeprom_cleanup(struct rtl8168_private *tp); -u16 rtl8168_eeprom_read_sc(struct rtl8168_private *tp, u16 reg); -void rtl8168_eeprom_write_sc(struct rtl8168_private *tp, u16 reg, u16 data); -void rtl8168_shift_out_bits(struct rtl8168_private *tp, int data, int count); -u16 rtl8168_shift_in_bits(struct rtl8168_private *tp); -void rtl8168_raise_clock(struct rtl8168_private *tp, u8 *x); -void rtl8168_lower_clock(struct rtl8168_private *tp, u8 *x); -void rtl8168_stand_by(struct rtl8168_private *tp); -void rtl8168_set_eeprom_sel_low(struct rtl8168_private *tp); - - - diff --git a/addons/r8168/src/3.10.108/rtltool.c b/addons/r8168/src/3.10.108/rtltool.c deleted file mode 100644 index 2a1be083..00000000 --- a/addons/r8168/src/3.10.108/rtltool.c +++ /dev/null @@ -1,359 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "r8168.h" -#include "rtl_eeprom.h" -#include "rtltool.h" - -int rtl8168_tool_ioctl(struct rtl8168_private *tp, struct ifreq *ifr) -{ - struct rtltool_cmd my_cmd; - unsigned long flags; - int ret; - - if (copy_from_user(&my_cmd, ifr->ifr_data, sizeof(my_cmd))) - return -EFAULT; - - ret = 0; - switch (my_cmd.cmd) { - case RTLTOOL_READ_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1) - my_cmd.data = readb(tp->mmio_addr+my_cmd.offset); - else if (my_cmd.len==2) - my_cmd.data = readw(tp->mmio_addr+(my_cmd.offset&~1)); - else if (my_cmd.len==4) - my_cmd.data = readl(tp->mmio_addr+(my_cmd.offset&~3)); - else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTLTOOL_WRITE_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1) - writeb(my_cmd.data, tp->mmio_addr+my_cmd.offset); - else if (my_cmd.len==2) - writew(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~1)); - else if (my_cmd.len==4) - writel(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~3)); - else { - ret = -EOPNOTSUPP; - break; - } - - break; - - case RTLTOOL_READ_PHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8168_mdio_prot_read(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_PHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_mdio_prot_write(tp, my_cmd.offset, my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTLTOOL_READ_EPHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8168_ephy_read(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_EPHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_ephy_write(tp, my_cmd.offset, my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTLTOOL_READ_ERI: - my_cmd.data = 0; - if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8168_eri_read(tp, my_cmd.offset, my_cmd.len, ERIAR_ExGMAC); - spin_unlock_irqrestore(&tp->lock, flags); - } else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_ERI: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { - spin_lock_irqsave(&tp->lock, flags); - rtl8168_eri_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC); - spin_unlock_irqrestore(&tp->lock, flags); - } else { - ret = -EOPNOTSUPP; - break; - } - break; - - case RTLTOOL_READ_PCI: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - my_cmd.data = 0; - if (my_cmd.len==1) - pci_read_config_byte(tp->pci_dev, my_cmd.offset, - (u8 *)&my_cmd.data); - else if (my_cmd.len==2) - pci_read_config_word(tp->pci_dev, my_cmd.offset, - (u16 *)&my_cmd.data); - else if (my_cmd.len==4) - pci_read_config_dword(tp->pci_dev, my_cmd.offset, - &my_cmd.data); - else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTLTOOL_WRITE_PCI: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1) - pci_write_config_byte(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else if (my_cmd.len==2) - pci_write_config_word(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else if (my_cmd.len==4) - pci_write_config_dword(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else { - ret = -EOPNOTSUPP; - break; - } - - break; - - case RTLTOOL_READ_EEPROM: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8168_eeprom_read_sc(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_EEPROM: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTL_READ_OOB_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_oob_mutex_lock(tp); - my_cmd.data = rtl8168_ocp_read(tp, my_cmd.offset, 4); - rtl8168_oob_mutex_unlock(tp); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTL_WRITE_OOB_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len == 0 || my_cmd.len > 4) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_oob_mutex_lock(tp); - rtl8168_ocp_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data); - rtl8168_oob_mutex_unlock(tp); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTL_ENABLE_PCI_DIAG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - tp->rtk_enable_diag = 1; - spin_unlock_irqrestore(&tp->lock, flags); - - dprintk("enable rtk diag\n"); - break; - - case RTL_DISABLE_PCI_DIAG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - tp->rtk_enable_diag = 0; - spin_unlock_irqrestore(&tp->lock, flags); - - dprintk("disable rtk diag\n"); - break; - - case RTL_READ_MAC_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.offset % 2) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8168_mac_ocp_read(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTL_WRITE_MAC_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if ((my_cmd.offset % 2) || (my_cmd.len != 2)) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_mac_ocp_write(tp, my_cmd.offset, (u16)my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTL_DIRECT_READ_PHY_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8168_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTL_DIRECT_WRITE_PHY_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} diff --git a/addons/r8168/src/3.10.108/rtltool.h b/addons/r8168/src/3.10.108/rtltool.h deleted file mode 100644 index d8731dff..00000000 --- a/addons/r8168/src/3.10.108/rtltool.h +++ /dev/null @@ -1,86 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_RTLTOOL_H -#define _LINUX_RTLTOOL_H - -#define SIOCRTLTOOL SIOCDEVPRIVATE+1 - -enum rtl_cmd { - RTLTOOL_READ_MAC=0, - RTLTOOL_WRITE_MAC, - RTLTOOL_READ_PHY, - RTLTOOL_WRITE_PHY, - RTLTOOL_READ_EPHY, - RTLTOOL_WRITE_EPHY, - RTLTOOL_READ_ERI, - RTLTOOL_WRITE_ERI, - RTLTOOL_READ_PCI, - RTLTOOL_WRITE_PCI, - RTLTOOL_READ_EEPROM, - RTLTOOL_WRITE_EEPROM, - - RTL_READ_OOB_MAC, - RTL_WRITE_OOB_MAC, - - RTL_ENABLE_PCI_DIAG, - RTL_DISABLE_PCI_DIAG, - - RTL_READ_MAC_OCP, - RTL_WRITE_MAC_OCP, - - RTL_DIRECT_READ_PHY_OCP, - RTL_DIRECT_WRITE_PHY_OCP, - - RTLTOOL_INVALID -}; - -struct rtltool_cmd { - __u32 cmd; - __u32 offset; - __u32 len; - __u32 data; -}; - -enum mode_access { - MODE_NONE=0, - MODE_READ, - MODE_WRITE -}; - -#ifdef __KERNEL__ -int rtl8168_tool_ioctl(struct rtl8168_private *tp, struct ifreq *ifr); -#endif - -#endif /* _LINUX_RTLTOOL_H */ diff --git a/addons/r8168/src/4.4.180/Makefile b/addons/r8168/src/4.4.180/Makefile deleted file mode 100644 index 74c19689..00000000 --- a/addons/r8168/src/4.4.180/Makefile +++ /dev/null @@ -1,62 +0,0 @@ -CONFIG_SOC_LAN = n -ENABLE_FIBER_SUPPORT = n -ENABLE_REALWOW_SUPPORT = n -ENABLE_DASH_SUPPORT = n -ENABLE_DASH_PRINTER_SUPPORT = n -CONFIG_DOWN_SPEED_100 = n -CONFIG_ASPM = y -ENABLE_S5WOL = y -ENABLE_S5_KEEP_CURR_MAC = n -ENABLE_EEE = y -ENABLE_S0_MAGIC_PACKET = n -CONFIG_DYNAMIC_ASPM = y -ENABLE_USE_FIRMWARE_FILE = n - -obj-m := r8168.o -r8168-objs := r8168_n.o r8168_asf.o rtl_eeprom.o rtltool.o -ifeq ($(CONFIG_SOC_LAN), y) - EXTRA_CFLAGS += -DCONFIG_SOC_LAN -endif -ifeq ($(ENABLE_FIBER_SUPPORT), y) - r8168-objs += r8168_fiber.o - EXTRA_CFLAGS += -DENABLE_FIBER_SUPPORT -endif -ifeq ($(ENABLE_REALWOW_SUPPORT), y) - r8168-objs += r8168_realwow.o - EXTRA_CFLAGS += -DENABLE_REALWOW_SUPPORT -endif -ifeq ($(ENABLE_DASH_SUPPORT), y) - r8168-objs += r8168_dash.o - EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -endif -ifeq ($(ENABLE_DASH_PRINTER_SUPPORT), y) - r8168-objs += r8168_dash.o - EXTRA_CFLAGS += -DENABLE_DASH_SUPPORT -DENABLE_DASH_PRINTER_SUPPORT -endif -EXTRA_CFLAGS += -DCONFIG_R8168_NAPI -EXTRA_CFLAGS += -DCONFIG_R8168_VLAN -ifeq ($(CONFIG_DOWN_SPEED_100), y) - EXTRA_CFLAGS += -DCONFIG_DOWN_SPEED_100 -endif -ifeq ($(CONFIG_ASPM), y) - EXTRA_CFLAGS += -DCONFIG_ASPM -endif -ifeq ($(ENABLE_S5WOL), y) - EXTRA_CFLAGS += -DENABLE_S5WOL -endif -ifeq ($(ENABLE_S5_KEEP_CURR_MAC), y) - EXTRA_CFLAGS += -DENABLE_S5_KEEP_CURR_MAC -endif -ifeq ($(ENABLE_EEE), y) - EXTRA_CFLAGS += -DENABLE_EEE -endif -ifeq ($(ENABLE_S0_MAGIC_PACKET), y) - EXTRA_CFLAGS += -DENABLE_S0_MAGIC_PACKET -endif -ifeq ($(CONFIG_DYNAMIC_ASPM), y) - EXTRA_CFLAGS += -DCONFIG_DYNAMIC_ASPM -endif -ifeq ($(ENABLE_USE_FIRMWARE_FILE), y) - r8168-objs += r8168_firmware.o - EXTRA_CFLAGS += -DENABLE_USE_FIRMWARE_FILE -endif diff --git a/addons/r8168/src/4.4.180/r8168.h b/addons/r8168/src/4.4.180/r8168.h deleted file mode 100644 index 4bd1047a..00000000 --- a/addons/r8168/src/4.4.180/r8168.h +++ /dev/null @@ -1,1842 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include "r8168_dash.h" -#include "r8168_realwow.h" -#include "r8168_fiber.h" - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,32) -typedef int netdev_tx_t; -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -#define skb_transport_offset(skb) (skb->h.raw - skb->data) -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,26) -#define device_set_wakeup_enable(dev, val) do {} while (0) -#endif - -#if 0 -static inline void ether_addr_copy(u8 *dst, const u8 *src) -{ - u16 *a = (u16 *)dst; - const u16 *b = (const u16 *)src; - - a[0] = b[0]; - a[1] = b[1]; - a[2] = b[2]; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,15,0) -#define IS_ERR_OR_NULL(ptr) (!ptr) -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,13,0) -#define reinit_completion(x) ((x)->done = 0) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,39) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) -#define pm_runtime_mark_last_busy(x) -#define pm_runtime_put_autosuspend(x) pm_runtime_put(x) -#define pm_runtime_put_sync_autosuspend(x) pm_runtime_put_sync(x) - -static inline bool pm_runtime_suspended(struct device *dev) -{ - return dev->power.runtime_status == RPM_SUSPENDED - && !dev->power.disable_depth; -} - -static inline bool pm_runtime_active(struct device *dev) -{ - return dev->power.runtime_status == RPM_ACTIVE - || dev->power.disable_depth; -} -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,36) -#define queue_delayed_work(long_wq, work, delay) schedule_delayed_work(work, delay) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) -#define netif_printk(priv, type, level, netdev, fmt, args...) \ - do { \ - if (netif_msg_##type(priv)) \ - printk(level "%s: " fmt,(netdev)->name , ##args); \ - } while (0) - -#define netif_emerg(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_EMERG, netdev, fmt, ##args) -#define netif_alert(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_ALERT, netdev, fmt, ##args) -#define netif_crit(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_CRIT, netdev, fmt, ##args) -#define netif_err(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_ERR, netdev, fmt, ##args) -#define netif_warn(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_WARNING, netdev, fmt, ##args) -#define netif_notice(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_NOTICE, netdev, fmt, ##args) -#define netif_info(priv, type, netdev, fmt, args...) \ - netif_printk(priv, type, KERN_INFO, (netdev), fmt, ##args) -#endif -#endif -#endif -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) -#define setup_timer(_timer, _function, _data) \ -do { \ - (_timer)->function = _function; \ - (_timer)->data = _data; \ - init_timer(_timer); \ -} while (0) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) -#if defined(skb_vlan_tag_present) && !defined(vlan_tx_tag_present) -#define vlan_tx_tag_present skb_vlan_tag_present -#endif -#if defined(skb_vlan_tag_get) && !defined(vlan_tx_tag_get) -#define vlan_tx_tag_get skb_vlan_tag_get -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) - -#define RTL_ALLOC_SKB_INTR(tp, length) dev_alloc_skb(length) -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) -#undef RTL_ALLOC_SKB_INTR -#define RTL_ALLOC_SKB_INTR(tp, length) napi_alloc_skb(&tp->napi, length) -#endif -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) -#define netdev_features_t u32 -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,5,0) -#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK -#else -#ifndef NETIF_F_ALL_CSUM -#define NETIF_F_ALL_CSUM NETIF_F_CSUM_MASK -#endif -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) -#define ENABLE_R8168_PROCFS -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -#define NETIF_F_HW_VLAN_RX NETIF_F_HW_VLAN_CTAG_RX -#define NETIF_F_HW_VLAN_TX NETIF_F_HW_VLAN_CTAG_TX -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,8,0) -#define __devinit -#define __devexit -#define __devexit_p(func) func -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -#define CHECKSUM_PARTIAL CHECKSUM_HW -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define irqreturn_t void -#define IRQ_HANDLED 1 -#define IRQ_NONE 0 -#define IRQ_RETVAL(x) -#endif - -#ifndef NETIF_F_RXALL -#define NETIF_F_RXALL 0 -#endif - -#ifndef NETIF_F_RXFCS -#define NETIF_F_RXFCS 0 -#endif - -#ifndef HAVE_FREE_NETDEV -#define free_netdev(x) kfree(x) -#endif - -#ifndef SET_NETDEV_DEV -#define SET_NETDEV_DEV(net, pdev) -#endif - -#ifndef SET_MODULE_OWNER -#define SET_MODULE_OWNER(dev) -#endif - -#ifndef SA_SHIRQ -#define SA_SHIRQ IRQF_SHARED -#endif - -#ifndef NETIF_F_GSO -#define gso_size tso_size -#define gso_segs tso_segs -#endif - -#ifndef PCI_VENDOR_ID_DLINK -#define PCI_VENDOR_ID_DLINK 0x1186 -#endif - -#ifndef dma_mapping_error -#define dma_mapping_error(a,b) 0 -#endif - -#ifndef netif_err -#define netif_err(a,b,c,d) -#endif - -#ifndef AUTONEG_DISABLE -#define AUTONEG_DISABLE 0x00 -#endif - -#ifndef AUTONEG_ENABLE -#define AUTONEG_ENABLE 0x01 -#endif - -#ifndef BMCR_SPEED1000 -#define BMCR_SPEED1000 0x0040 -#endif - -#ifndef BMCR_SPEED100 -#define BMCR_SPEED100 0x2000 -#endif - -#ifndef BMCR_SPEED10 -#define BMCR_SPEED10 0x0000 -#endif - -#ifndef SPEED_UNKNOWN -#define SPEED_UNKNOWN -1 -#endif - -#ifndef DUPLEX_UNKNOWN -#define DUPLEX_UNKNOWN 0xff -#endif - -#ifndef SUPPORTED_Pause -#define SUPPORTED_Pause (1 << 13) -#endif - -#ifndef SUPPORTED_Asym_Pause -#define SUPPORTED_Asym_Pause (1 << 14) -#endif - -#ifndef MDIO_EEE_100TX -#define MDIO_EEE_100TX 0x0002 -#endif - -#ifndef MDIO_EEE_1000T -#define MDIO_EEE_1000T 0x0004 -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -#ifdef CONFIG_NET_POLL_CONTROLLER -#define RTL_NET_POLL_CONTROLLER dev->poll_controller=rtl8168_netpoll -#else -#define RTL_NET_POLL_CONTROLLER -#endif - -#ifdef CONFIG_R8168_VLAN -#define RTL_SET_VLAN dev->vlan_rx_register=rtl8168_vlan_rx_register -#else -#define RTL_SET_VLAN -#endif - -#define RTL_NET_DEVICE_OPS(ops) dev->open=rtl8168_open; \ - dev->hard_start_xmit=rtl8168_start_xmit; \ - dev->get_stats=rtl8168_get_stats; \ - dev->stop=rtl8168_close; \ - dev->tx_timeout=rtl8168_tx_timeout; \ - dev->set_multicast_list=rtl8168_set_rx_mode; \ - dev->change_mtu=rtl8168_change_mtu; \ - dev->set_mac_address=rtl8168_set_mac_address; \ - dev->do_ioctl=rtl8168_do_ioctl; \ - RTL_NET_POLL_CONTROLLER; \ - RTL_SET_VLAN; -#else -#define RTL_NET_DEVICE_OPS(ops) dev->netdev_ops=&ops -#endif - -#ifndef FALSE -#define FALSE 0 -#endif - -#ifndef TRUE -#define TRUE 1 -#endif - -#ifndef false -#define false 0 -#endif - -#ifndef true -#define true 1 -#endif - -//Hardware will continue interrupt 10 times after interrupt finished. -#define RTK_KEEP_INTERRUPT_COUNT (10) - -//Due to the hardware design of RTL8111B, the low 32 bit address of receive -//buffer must be 8-byte alignment. -#ifndef NET_IP_ALIGN -#define NET_IP_ALIGN 2 -#endif -#define RTK_RX_ALIGN 8 - -#ifdef CONFIG_R8168_NAPI -#define NAPI_SUFFIX "-NAPI" -#else -#define NAPI_SUFFIX "" -#endif -#ifdef ENABLE_FIBER_SUPPORT -#define FIBER_SUFFIX "-FIBER" -#else -#define FIBER_SUFFIX "" -#endif -#ifdef ENABLE_REALWOW_SUPPORT -#define REALWOW_SUFFIX "-REALWOW" -#else -#define REALWOW_SUFFIX "" -#endif -#if defined(ENABLE_DASH_PRINTER_SUPPORT) -#define DASH_SUFFIX "-PRINTER" -#elif defined(ENABLE_DASH_SUPPORT) -#define DASH_SUFFIX "-DASH" -#else -#define DASH_SUFFIX "" -#endif - -#define RTL8168_VERSION "8.049.02" NAPI_SUFFIX FIBER_SUFFIX REALWOW_SUFFIX DASH_SUFFIX -#define MODULENAME "r8168" -#define PFX MODULENAME ": " - -#define GPL_CLAIM "\ -r8168 Copyright (C) 2021 Realtek NIC software team \n \ -This program comes with ABSOLUTELY NO WARRANTY; for details, please see . \n \ -This is free software, and you are welcome to redistribute it under certain conditions; see . \n" - -#ifdef RTL8168_DEBUG -#define assert(expr) \ - if(!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__FUNCTION__,__LINE__); \ - } -#define dprintk(fmt, args...) do { printk(PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8168_DEBUG */ - -#define R8168_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#ifdef CONFIG_R8168_NAPI -#define rtl8168_rx_hwaccel_skb vlan_hwaccel_receive_skb -#define rtl8168_rx_quota(count, quota) min(count, quota) -#else -#define rtl8168_rx_hwaccel_skb vlan_hwaccel_rx -#define rtl8168_rx_quota(count, quota) count -#endif - -/* MAC address length */ -#ifndef MAC_ADDR_LEN -#define MAC_ADDR_LEN 6 -#endif - -#ifndef MAC_PROTOCOL_LEN -#define MAC_PROTOCOL_LEN 2 -#endif - -#ifndef ETH_FCS_LEN -#define ETH_FCS_LEN 4 -#endif - -#ifndef NETIF_F_TSO6 -#define NETIF_F_TSO6 0 -#endif - -#define Reserved2_data 7 -#define RX_DMA_BURST 7 /* Maximum PCI burst, '6' is 1024 */ -#define TX_DMA_BURST_unlimited 7 -#define TX_DMA_BURST_1024 6 -#define TX_DMA_BURST_512 5 -#define TX_DMA_BURST_256 4 -#define TX_DMA_BURST_128 3 -#define TX_DMA_BURST_64 2 -#define TX_DMA_BURST_32 1 -#define TX_DMA_BURST_16 0 -#define Reserved1_data 0x3F -#define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ -#define Jumbo_Frame_1k ETH_DATA_LEN -#define Jumbo_Frame_2k (2*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_3k (3*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_4k (4*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_5k (5*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_6k (6*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_7k (7*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_8k (8*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define Jumbo_Frame_9k (9*1024 - ETH_HLEN - VLAN_HLEN - ETH_FCS_LEN) -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ -#define RxEarly_off_V1 (0x07 << 11) -#define RxEarly_off_V2 (1 << 11) -#define Rx_Single_fetch_V2 (1 << 14) - -#define R8168_REGS_SIZE (256) -#define R8168_MAC_REGS_SIZE (256) -#define R8168_PHY_REGS_SIZE (16*2) -#define R8168_EPHY_REGS_SIZE (31*2) -#define R8168_ERI_REGS_SIZE (0x100) -#define R8168_REGS_DUMP_SIZE (0x400) -#define R8168_PCI_REGS_SIZE (0x100) -#define R8168_NAPI_WEIGHT 64 - -#define RTL8168_TX_TIMEOUT (6 * HZ) -#define RTL8168_LINK_TIMEOUT (1 * HZ) -#define RTL8168_ESD_TIMEOUT (2 * HZ) - -#define NUM_TX_DESC 1024 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 1024 /* Number of Rx descriptor registers */ - -#define RX_BUF_SIZE 0x05F3 /* 0x05F3 = 1522bye + 1 */ -#define R8168_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8168_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define OCP_STD_PHY_BASE 0xa400 - -#define NODE_ADDRESS_SIZE 6 - -#define SHORT_PACKET_PADDING_BUF_SIZE 256 - -#define RTK_MAGIC_DEBUG_VALUE 0x0badbeef - -/* write/read MMIO register */ -#define RTL_W8(tp, reg, val8) writeb((val8), tp->mmio_addr + (reg)) -#define RTL_W16(tp, reg, val16) writew((val16), tp->mmio_addr + (reg)) -#define RTL_W32(tp, reg, val32) writel((val32), tp->mmio_addr + (reg)) -#define RTL_R8(tp, reg) readb(tp->mmio_addr + (reg)) -#define RTL_R16(tp, reg) readw(tp->mmio_addr + (reg)) -#define RTL_R32(tp, reg) ((unsigned long) readl(tp->mmio_addr + (reg))) - -#ifndef DMA_64BIT_MASK -#define DMA_64BIT_MASK 0xffffffffffffffffULL -#endif - -#ifndef DMA_32BIT_MASK -#define DMA_32BIT_MASK 0x00000000ffffffffULL -#endif - -#ifndef NETDEV_TX_OK -#define NETDEV_TX_OK 0 /* driver took care of packet */ -#endif - -#ifndef NETDEV_TX_BUSY -#define NETDEV_TX_BUSY 1 /* driver tx path was busy*/ -#endif - -#ifndef NETDEV_TX_LOCKED -#define NETDEV_TX_LOCKED -1 /* driver tx lock was already taken */ -#endif - -#ifndef ADVERTISED_Pause -#define ADVERTISED_Pause (1 << 13) -#endif - -#ifndef ADVERTISED_Asym_Pause -#define ADVERTISED_Asym_Pause (1 << 14) -#endif - -#ifndef ADVERTISE_PAUSE_CAP -#define ADVERTISE_PAUSE_CAP 0x400 -#endif - -#ifndef ADVERTISE_PAUSE_ASYM -#define ADVERTISE_PAUSE_ASYM 0x800 -#endif - -#ifndef MII_CTRL1000 -#define MII_CTRL1000 0x09 -#endif - -#ifndef ADVERTISE_1000FULL -#define ADVERTISE_1000FULL 0x200 -#endif - -#ifndef ADVERTISE_1000HALF -#define ADVERTISE_1000HALF 0x100 -#endif - -#ifndef ETH_MIN_MTU -#define ETH_MIN_MTU 68 -#endif - -/*****************************************************************************/ - -//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) -#if (( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,27) ) || \ - (( LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) ) && \ - ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) ))) -/* copied from linux kernel 2.6.20 include/linux/netdev.h */ -#define NETDEV_ALIGN 32 -#define NETDEV_ALIGN_CONST (NETDEV_ALIGN - 1) - -static inline void *netdev_priv(struct net_device *dev) -{ - return (char *)dev + ((sizeof(struct net_device) - + NETDEV_ALIGN_CONST) - & ~NETDEV_ALIGN_CONST); -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,3) - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -#define RTLDEV tp -#else -#define RTLDEV dev -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -/*****************************************************************************/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) -typedef struct net_device *napi_ptr; -typedef int *napi_budget; - -#define napi dev -#define RTL_NAPI_CONFIG(ndev, priv, function, weig) ndev->poll=function; \ - ndev->weight=weig; -#define RTL_NAPI_QUOTA(budget, ndev) min(*budget, ndev->quota) -#define RTL_GET_PRIV(stuct_ptr, priv_struct) netdev_priv(stuct_ptr) -#define RTL_GET_NETDEV(priv_ptr) -#define RTL_RX_QUOTA(budget) *budget -#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) *budget -= work_done; \ - ndev->quota -= work_done; -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev) -#define RTL_NAPI_RETURN_VALUE work_done >= work_to_do -#define RTL_NAPI_ENABLE(dev, napi) netif_poll_enable(dev) -#define RTL_NAPI_DISABLE(dev, napi) netif_poll_disable(dev) -#define DMA_BIT_MASK(n) (((n) == 64) ? ~0ULL : ((1ULL<<(n))-1)) -#else -typedef struct napi_struct *napi_ptr; -typedef int napi_budget; - -#define RTL_NAPI_CONFIG(ndev, priv, function, weight) netif_napi_add(ndev, &priv->napi, function, weight) -#define RTL_NAPI_QUOTA(budget, ndev) min(budget, budget) -#define RTL_GET_PRIV(stuct_ptr, priv_struct) container_of(stuct_ptr, priv_struct, stuct_ptr) -#define RTL_GET_NETDEV(priv_ptr) struct net_device *dev = priv_ptr->dev; -#define RTL_RX_QUOTA(budget) budget -#define RTL_NAPI_QUOTA_UPDATE(ndev, work_done, budget) -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(dev, napi) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(dev, napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(dev, napi) -#endif -#if LINUX_VERSION_CODE == KERNEL_VERSION(2,6,29) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) netif_rx_complete(napi) -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) netif_rx_schedule_prep(napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __netif_rx_schedule(napi) -#endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,29) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,19,0) -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete_done(napi, work_done) -#else -#define RTL_NETIF_RX_COMPLETE(dev, napi, work_done) napi_complete(napi) -#endif -#define RTL_NETIF_RX_SCHEDULE_PREP(dev, napi) napi_schedule_prep(napi) -#define __RTL_NETIF_RX_SCHEDULE(dev, napi) __napi_schedule(napi) -#endif -#define RTL_NAPI_RETURN_VALUE work_done -#define RTL_NAPI_ENABLE(dev, napi) napi_enable(napi) -#define RTL_NAPI_DISABLE(dev, napi) napi_disable(napi) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) -#define RTL_NAPI_DEL(priv) -#else -#define RTL_NAPI_DEL(priv) netif_napi_del(&priv->napi) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,27) - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -#ifdef __CHECKER__ -#define __iomem __attribute__((noderef, address_space(2))) -extern void __chk_io_ptr(void __iomem *); -#define __bitwise __attribute__((bitwise)) -#else -#define __iomem -#define __chk_io_ptr(x) (void)0 -#define __bitwise -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) - -/*****************************************************************************/ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) -#ifdef __CHECKER__ -#define __force __attribute__((force)) -#else -#define __force -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) - -#ifndef module_param -#define module_param(v,t,p) MODULE_PARM(v, "i"); -#endif - -#ifndef PCI_DEVICE -#define PCI_DEVICE(vend,dev) \ - .vendor = (vend), .device = (dev), \ - .subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID -#endif - -/*****************************************************************************/ -/* 2.5.28 => 2.4.23 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,5,28) ) - -static inline void _kc_synchronize_irq(void) -{ - synchronize_irq(); -} -#undef synchronize_irq -#define synchronize_irq(X) _kc_synchronize_irq() - -#include -#define work_struct tq_struct -#undef INIT_WORK -#define INIT_WORK(a,b,c) INIT_TQUEUE(a,(void (*)(void *))b,c) -#undef container_of -#define container_of list_entry -#define schedule_work schedule_task -#define flush_scheduled_work flush_scheduled_tasks -#endif /* 2.5.28 => 2.4.17 */ - -/*****************************************************************************/ -/* 2.6.4 => 2.6.0 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4) ) -#define MODULE_VERSION(_version) MODULE_INFO(version, _version) -#endif /* 2.6.4 => 2.6.0 */ -/*****************************************************************************/ -/* 2.6.0 => 2.5.28 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) ) -#define MODULE_INFO(version, _version) -#ifndef CONFIG_E1000_DISABLE_PACKET_SPLIT -#define CONFIG_E1000_DISABLE_PACKET_SPLIT 1 -#endif - -#define pci_set_consistent_dma_mask(dev,mask) 1 - -#undef dev_put -#define dev_put(dev) __dev_put(dev) - -#ifndef skb_fill_page_desc -#define skb_fill_page_desc _kc_skb_fill_page_desc -extern void _kc_skb_fill_page_desc(struct sk_buff *skb, int i, struct page *page, int off, int size); -#endif - -#ifndef pci_dma_mapping_error -#define pci_dma_mapping_error _kc_pci_dma_mapping_error -static inline int _kc_pci_dma_mapping_error(dma_addr_t dma_addr) -{ - return dma_addr == 0; -} -#endif - -#undef ALIGN -#define ALIGN(x,a) (((x)+(a)-1)&~((a)-1)) - -#endif /* 2.6.0 => 2.5.28 */ - -/*****************************************************************************/ -/* 2.4.22 => 2.4.17 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,4,22) ) -#define pci_name(x) ((x)->slot_name) -#endif /* 2.4.22 => 2.4.17 */ - -/*****************************************************************************/ -/* 2.6.5 => 2.6.0 */ -#if ( LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) ) -#define pci_dma_sync_single_for_cpu pci_dma_sync_single -#define pci_dma_sync_single_for_device pci_dma_sync_single_for_cpu -#endif /* 2.6.5 => 2.6.0 */ - -/*****************************************************************************/ - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -/* - * initialize a work-struct's func and data pointers: - */ -#define PREPARE_WORK(_work, _func, _data) \ - do { \ - (_work)->func = _func; \ - (_work)->data = _data; \ - } while (0) - -#endif -/*****************************************************************************/ -/* 2.6.4 => 2.6.0 */ -#if ((LINUX_VERSION_CODE < KERNEL_VERSION(2,4,25) && \ - LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22)) || \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0) && \ - LINUX_VERSION_CODE < KERNEL_VERSION(2,6,4))) -#define ETHTOOL_OPS_COMPAT -#endif /* 2.6.4 => 2.6.0 */ - -/*****************************************************************************/ -/* Installations with ethtool version without eeprom, adapter id, or statistics - * support */ - -#ifndef ETH_GSTRING_LEN -#define ETH_GSTRING_LEN 32 -#endif - -#ifndef ETHTOOL_GSTATS -#define ETHTOOL_GSTATS 0x1d -#undef ethtool_drvinfo -#define ethtool_drvinfo k_ethtool_drvinfo -struct k_ethtool_drvinfo { - u32 cmd; - char driver[32]; - char version[32]; - char fw_version[32]; - char bus_info[32]; - char reserved1[32]; - char reserved2[16]; - u32 n_stats; - u32 testinfo_len; - u32 eedump_len; - u32 regdump_len; -}; - -struct ethtool_stats { - u32 cmd; - u32 n_stats; - u64 data[0]; -}; -#endif /* ETHTOOL_GSTATS */ - -#ifndef ETHTOOL_PHYS_ID -#define ETHTOOL_PHYS_ID 0x1c -#endif /* ETHTOOL_PHYS_ID */ - -#ifndef ETHTOOL_GSTRINGS -#define ETHTOOL_GSTRINGS 0x1b -enum ethtool_stringset { - ETH_SS_TEST = 0, - ETH_SS_STATS, -}; -struct ethtool_gstrings { - u32 cmd; /* ETHTOOL_GSTRINGS */ - u32 string_set; /* string set id e.c. ETH_SS_TEST, etc*/ - u32 len; /* number of strings in the string set */ - u8 data[0]; -}; -#endif /* ETHTOOL_GSTRINGS */ - -#ifndef ETHTOOL_TEST -#define ETHTOOL_TEST 0x1a -enum ethtool_test_flags { - ETH_TEST_FL_OFFLINE = (1 << 0), - ETH_TEST_FL_FAILED = (1 << 1), -}; -struct ethtool_test { - u32 cmd; - u32 flags; - u32 reserved; - u32 len; - u64 data[0]; -}; -#endif /* ETHTOOL_TEST */ - -#ifndef ETHTOOL_GEEPROM -#define ETHTOOL_GEEPROM 0xb -#undef ETHTOOL_GREGS -struct ethtool_eeprom { - u32 cmd; - u32 magic; - u32 offset; - u32 len; - u8 data[0]; -}; - -struct ethtool_value { - u32 cmd; - u32 data; -}; -#endif /* ETHTOOL_GEEPROM */ - -#ifndef ETHTOOL_GLINK -#define ETHTOOL_GLINK 0xa -#endif /* ETHTOOL_GLINK */ - -#ifndef ETHTOOL_GREGS -#define ETHTOOL_GREGS 0x00000004 /* Get NIC registers */ -#define ethtool_regs _kc_ethtool_regs -/* for passing big chunks of data */ -struct _kc_ethtool_regs { - u32 cmd; - u32 version; /* driver-specific, indicates different chips/revs */ - u32 len; /* bytes */ - u8 data[0]; -}; -#endif /* ETHTOOL_GREGS */ - -#ifndef ETHTOOL_GMSGLVL -#define ETHTOOL_GMSGLVL 0x00000007 /* Get driver message level */ -#endif -#ifndef ETHTOOL_SMSGLVL -#define ETHTOOL_SMSGLVL 0x00000008 /* Set driver msg level, priv. */ -#endif -#ifndef ETHTOOL_NWAY_RST -#define ETHTOOL_NWAY_RST 0x00000009 /* Restart autonegotiation, priv */ -#endif -#ifndef ETHTOOL_GLINK -#define ETHTOOL_GLINK 0x0000000a /* Get link status */ -#endif -#ifndef ETHTOOL_GEEPROM -#define ETHTOOL_GEEPROM 0x0000000b /* Get EEPROM data */ -#endif -#ifndef ETHTOOL_SEEPROM -#define ETHTOOL_SEEPROM 0x0000000c /* Set EEPROM data */ -#endif -#ifndef ETHTOOL_GCOALESCE -#define ETHTOOL_GCOALESCE 0x0000000e /* Get coalesce config */ -/* for configuring coalescing parameters of chip */ -#define ethtool_coalesce _kc_ethtool_coalesce -struct _kc_ethtool_coalesce { - u32 cmd; /* ETHTOOL_{G,S}COALESCE */ - - /* How many usecs to delay an RX interrupt after - * a packet arrives. If 0, only rx_max_coalesced_frames - * is used. - */ - u32 rx_coalesce_usecs; - - /* How many packets to delay an RX interrupt after - * a packet arrives. If 0, only rx_coalesce_usecs is - * used. It is illegal to set both usecs and max frames - * to zero as this would cause RX interrupts to never be - * generated. - */ - u32 rx_max_coalesced_frames; - - /* Same as above two parameters, except that these values - * apply while an IRQ is being serviced by the host. Not - * all cards support this feature and the values are ignored - * in that case. - */ - u32 rx_coalesce_usecs_irq; - u32 rx_max_coalesced_frames_irq; - - /* How many usecs to delay a TX interrupt after - * a packet is sent. If 0, only tx_max_coalesced_frames - * is used. - */ - u32 tx_coalesce_usecs; - - /* How many packets to delay a TX interrupt after - * a packet is sent. If 0, only tx_coalesce_usecs is - * used. It is illegal to set both usecs and max frames - * to zero as this would cause TX interrupts to never be - * generated. - */ - u32 tx_max_coalesced_frames; - - /* Same as above two parameters, except that these values - * apply while an IRQ is being serviced by the host. Not - * all cards support this feature and the values are ignored - * in that case. - */ - u32 tx_coalesce_usecs_irq; - u32 tx_max_coalesced_frames_irq; - - /* How many usecs to delay in-memory statistics - * block updates. Some drivers do not have an in-memory - * statistic block, and in such cases this value is ignored. - * This value must not be zero. - */ - u32 stats_block_coalesce_usecs; - - /* Adaptive RX/TX coalescing is an algorithm implemented by - * some drivers to improve latency under low packet rates and - * improve throughput under high packet rates. Some drivers - * only implement one of RX or TX adaptive coalescing. Anything - * not implemented by the driver causes these values to be - * silently ignored. - */ - u32 use_adaptive_rx_coalesce; - u32 use_adaptive_tx_coalesce; - - /* When the packet rate (measured in packets per second) - * is below pkt_rate_low, the {rx,tx}_*_low parameters are - * used. - */ - u32 pkt_rate_low; - u32 rx_coalesce_usecs_low; - u32 rx_max_coalesced_frames_low; - u32 tx_coalesce_usecs_low; - u32 tx_max_coalesced_frames_low; - - /* When the packet rate is below pkt_rate_high but above - * pkt_rate_low (both measured in packets per second) the - * normal {rx,tx}_* coalescing parameters are used. - */ - - /* When the packet rate is (measured in packets per second) - * is above pkt_rate_high, the {rx,tx}_*_high parameters are - * used. - */ - u32 pkt_rate_high; - u32 rx_coalesce_usecs_high; - u32 rx_max_coalesced_frames_high; - u32 tx_coalesce_usecs_high; - u32 tx_max_coalesced_frames_high; - - /* How often to do adaptive coalescing packet rate sampling, - * measured in seconds. Must not be zero. - */ - u32 rate_sample_interval; -}; -#endif /* ETHTOOL_GCOALESCE */ - -#ifndef ETHTOOL_SCOALESCE -#define ETHTOOL_SCOALESCE 0x0000000f /* Set coalesce config. */ -#endif -#ifndef ETHTOOL_GRINGPARAM -#define ETHTOOL_GRINGPARAM 0x00000010 /* Get ring parameters */ -/* for configuring RX/TX ring parameters */ -#define ethtool_ringparam _kc_ethtool_ringparam -struct _kc_ethtool_ringparam { - u32 cmd; /* ETHTOOL_{G,S}RINGPARAM */ - - /* Read only attributes. These indicate the maximum number - * of pending RX/TX ring entries the driver will allow the - * user to set. - */ - u32 rx_max_pending; - u32 rx_mini_max_pending; - u32 rx_jumbo_max_pending; - u32 tx_max_pending; - - /* Values changeable by the user. The valid values are - * in the range 1 to the "*_max_pending" counterpart above. - */ - u32 rx_pending; - u32 rx_mini_pending; - u32 rx_jumbo_pending; - u32 tx_pending; -}; -#endif /* ETHTOOL_GRINGPARAM */ - -#ifndef ETHTOOL_SRINGPARAM -#define ETHTOOL_SRINGPARAM 0x00000011 /* Set ring parameters, priv. */ -#endif -#ifndef ETHTOOL_GPAUSEPARAM -#define ETHTOOL_GPAUSEPARAM 0x00000012 /* Get pause parameters */ -/* for configuring link flow control parameters */ -#define ethtool_pauseparam _kc_ethtool_pauseparam -struct _kc_ethtool_pauseparam { - u32 cmd; /* ETHTOOL_{G,S}PAUSEPARAM */ - - /* If the link is being auto-negotiated (via ethtool_cmd.autoneg - * being true) the user may set 'autonet' here non-zero to have the - * pause parameters be auto-negotiated too. In such a case, the - * {rx,tx}_pause values below determine what capabilities are - * advertised. - * - * If 'autoneg' is zero or the link is not being auto-negotiated, - * then {rx,tx}_pause force the driver to use/not-use pause - * flow control. - */ - u32 autoneg; - u32 rx_pause; - u32 tx_pause; -}; -#endif /* ETHTOOL_GPAUSEPARAM */ - -#ifndef ETHTOOL_SPAUSEPARAM -#define ETHTOOL_SPAUSEPARAM 0x00000013 /* Set pause parameters. */ -#endif -#ifndef ETHTOOL_GRXCSUM -#define ETHTOOL_GRXCSUM 0x00000014 /* Get RX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_SRXCSUM -#define ETHTOOL_SRXCSUM 0x00000015 /* Set RX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_GTXCSUM -#define ETHTOOL_GTXCSUM 0x00000016 /* Get TX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_STXCSUM -#define ETHTOOL_STXCSUM 0x00000017 /* Set TX hw csum enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_GSG -#define ETHTOOL_GSG 0x00000018 /* Get scatter-gather enable -* (ethtool_value) */ -#endif -#ifndef ETHTOOL_SSG -#define ETHTOOL_SSG 0x00000019 /* Set scatter-gather enable -* (ethtool_value). */ -#endif -#ifndef ETHTOOL_TEST -#define ETHTOOL_TEST 0x0000001a /* execute NIC self-test, priv. */ -#endif -#ifndef ETHTOOL_GSTRINGS -#define ETHTOOL_GSTRINGS 0x0000001b /* get specified string set */ -#endif -#ifndef ETHTOOL_PHYS_ID -#define ETHTOOL_PHYS_ID 0x0000001c /* identify the NIC */ -#endif -#ifndef ETHTOOL_GSTATS -#define ETHTOOL_GSTATS 0x0000001d /* get NIC-specific statistics */ -#endif -#ifndef ETHTOOL_GTSO -#define ETHTOOL_GTSO 0x0000001e /* Get TSO enable (ethtool_value) */ -#endif -#ifndef ETHTOOL_STSO -#define ETHTOOL_STSO 0x0000001f /* Set TSO enable (ethtool_value) */ -#endif - -#ifndef ETHTOOL_BUSINFO_LEN -#define ETHTOOL_BUSINFO_LEN 32 -#endif - -/*****************************************************************************/ - -enum RTL8168_DSM_STATE { - DSM_MAC_INIT = 1, - DSM_NIC_GOTO_D3 = 2, - DSM_IF_DOWN = 3, - DSM_NIC_RESUME_D3 = 4, - DSM_IF_UP = 5, -}; - -enum RTL8168_registers { - MAC0 = 0x00, /* Ethernet hardware address. */ - MAC4 = 0x04, - MAR0 = 0x08, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - CustomLED = 0x18, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3C, - IntrStatus = 0x3E, - TxConfig = 0x40, - RxConfig = 0x44, - TCTR = 0x48, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - TDFNR = 0x57, - TimeInt0 = 0x58, - TimeInt1 = 0x5C, - PHYAR = 0x60, - CSIDR = 0x64, - CSIAR = 0x68, - PHYstatus = 0x6C, - MACDBG = 0x6D, - GPIO = 0x6E, - PMCH = 0x6F, - ERIDR = 0x70, - ERIAR = 0x74, - EPHY_RXER_NUM = 0x7C, - EPHYAR = 0x80, - TimeInt2 = 0x8C, - OCPDR = 0xB0, - MACOCP = 0xB0, - OCPAR = 0xB4, - SecMAC0 = 0xB4, - SecMAC4 = 0xB8, - PHYOCP = 0xB8, - DBG_reg = 0xD1, - TwiCmdReg = 0xD2, - MCUCmd_reg = 0xD3, - RxMaxSize = 0xDA, - EFUSEAR = 0xDC, - CPlusCmd = 0xE0, - IntrMitigate = 0xE2, - RxDescAddrLow = 0xE4, - RxDescAddrHigh = 0xE8, - MTPS = 0xEC, - FuncEvent = 0xF0, - PPSW = 0xF2, - FuncEventMask = 0xF4, - TimeInt3 = 0xF4, - FuncPresetState = 0xF8, - CMAC_IBCR0 = 0xF8, - CMAC_IBCR2 = 0xF9, - CMAC_IBIMR0 = 0xFA, - CMAC_IBISR0 = 0xFB, - FuncForceEvent = 0xFC, -}; - -enum RTL8168_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxDescUnavail = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - StopReq = 0x80, - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xC0, - Cfg9346_EEDO = (1 << 0), - Cfg9346_EEDI = (1 << 1), - Cfg9346_EESK = (1 << 2), - Cfg9346_EECS = (1 << 3), - Cfg9346_EEM0 = (1 << 6), - Cfg9346_EEM1 = (1 << 7), - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, - - /* Transmit Priority Polling*/ - HPQ = 0x80, - NPQ = 0x40, - FSWInt = 0x01, - - /* RxConfigBits */ - Reserved2_shift = 13, - RxCfgDMAShift = 8, - RxCfg_128_int_en = (1 << 15), - RxCfg_fet_multi_en = (1 << 14), - RxCfg_half_refetch = (1 << 13), - RxCfg_9356SEL = (1 << 6), - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - TxMACLoopBack = (1 << 17), /* MAC loopback */ - - /* Config1 register */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register */ - ClkReqEn = (1 << 7), /* Clock Request Enable */ - PMSTS_En = (1 << 5), - - /* Config3 register */ - Isolate_en = (1 << 12), /* Isolate enable */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* This bit is reserved in RTL8168B.*/ - /* Wake up when the cable connection is re-established */ - ECRCEN = (1 << 3), /* This bit is reserved in RTL8168B*/ - Jumbo_En0 = (1 << 2), /* This bit is reserved in RTL8168B*/ - RDY_TO_L23 = (1 << 1), /* This bit is reserved in RTL8168B*/ - Beacon_en = (1 << 0), /* This bit is reserved in RTL8168B*/ - - /* Config4 register */ - Jumbo_En1 = (1 << 1), /* This bit is reserved in RTL8168B*/ - - /* Config5 register */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - ASPM_en = (1 << 0), /* ASPM enable */ - - /* CPlusCmd */ - EnableBist = (1 << 15), - Macdbgo_oe = (1 << 14), - Normal_mode = (1 << 13), - Force_halfdup = (1 << 12), - Force_rxflow_en = (1 << 11), - Force_txflow_en = (1 << 10), - Cxpl_dbg_sel = (1 << 9),//This bit is reserved in RTL8168B - ASF = (1 << 8),//This bit is reserved in RTL8168C - PktCntrDisable = (1 << 7), - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - Macdbgo_sel = 0x001C, - INTT_0 = 0x0000, - INTT_1 = 0x0001, - INTT_2 = 0x0002, - INTT_3 = 0x0003, - - /* rtl8168_PHYstatus */ - PowerSaveStatus = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* DBG_reg */ - Fix_Nak_1 = (1 << 4), - Fix_Nak_2 = (1 << 3), - DBGPIN_E2 = (1 << 0), - - /* ResetCounterCommand */ - CounterReset = 0x1, - /* DumpCounterCommand */ - CounterDump = 0x8, - - /* PHY access */ - PHYAR_Flag = 0x80000000, - PHYAR_Write = 0x80000000, - PHYAR_Read = 0x00000000, - PHYAR_Reg_Mask = 0x1f, - PHYAR_Reg_shift = 16, - PHYAR_Data_Mask = 0xffff, - - /* EPHY access */ - EPHYAR_Flag = 0x80000000, - EPHYAR_Write = 0x80000000, - EPHYAR_Read = 0x00000000, - EPHYAR_Reg_Mask = 0x3f, - EPHYAR_Reg_shift = 16, - EPHYAR_Data_Mask = 0xffff, - - /* CSI access */ - CSIAR_Flag = 0x80000000, - CSIAR_Write = 0x80000000, - CSIAR_Read = 0x00000000, - CSIAR_ByteEn = 0x0f, - CSIAR_ByteEn_shift = 12, - CSIAR_Addr_Mask = 0x0fff, - - /* ERI access */ - ERIAR_Flag = 0x80000000, - ERIAR_Write = 0x80000000, - ERIAR_Read = 0x00000000, - ERIAR_Addr_Align = 4, /* ERI access register address must be 4 byte alignment */ - ERIAR_ExGMAC = 0, - ERIAR_MSIX = 1, - ERIAR_ASF = 2, - ERIAR_OOB = 2, - ERIAR_Type_shift = 16, - ERIAR_ByteEn = 0x0f, - ERIAR_ByteEn_shift = 12, - - /* OCP GPHY access */ - OCPDR_Write = 0x80000000, - OCPDR_Read = 0x00000000, - OCPDR_Reg_Mask = 0xFF, - OCPDR_Data_Mask = 0xFFFF, - OCPDR_GPHY_Reg_shift = 16, - OCPAR_Flag = 0x80000000, - OCPAR_GPHY_Write = 0x8000F060, - OCPAR_GPHY_Read = 0x0000F060, - OCPR_Write = 0x80000000, - OCPR_Read = 0x00000000, - OCPR_Addr_Reg_shift = 16, - OCPR_Flag = 0x80000000, - OCP_STD_PHY_BASE_PAGE = 0x0A40, - - /* MCU Command */ - Now_is_oob = (1 << 7), - Txfifo_empty = (1 << 5), - Rxfifo_empty = (1 << 4), - - /* E-FUSE access */ - EFUSE_WRITE = 0x80000000, - EFUSE_WRITE_OK = 0x00000000, - EFUSE_READ = 0x00000000, - EFUSE_READ_OK = 0x80000000, - EFUSE_WRITE_V3 = 0x40000000, - EFUSE_WRITE_OK_V3 = 0x00000000, - EFUSE_READ_V3 = 0x80000000, - EFUSE_READ_OK_V3 = 0x00000000, - EFUSE_Reg_Mask = 0x03FF, - EFUSE_Reg_Shift = 8, - EFUSE_Check_Cnt = 300, - EFUSE_READ_FAIL = 0xFF, - EFUSE_Data_Mask = 0x000000FF, - - /* GPIO */ - GPIO_en = (1 << 0), - -}; - -enum _DescStatusBit { - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ - - /* Tx private */ - /*------ offset 0 of tx descriptor ------*/ - LargeSend = (1 << 27), /* TCP Large Send Offload (TSO) */ - GiantSendv4 = (1 << 26), /* TCP Giant Send Offload V4 (GSOv4) */ - GiantSendv6 = (1 << 25), /* TCP Giant Send Offload V6 (GSOv6) */ - LargeSend_DP = (1 << 16), /* TCP Large Send Offload (TSO) */ - MSSShift = 16, /* MSS value position */ - MSSMask = 0x7FFU, /* MSS value 11 bits */ - TxIPCS = (1 << 18), /* Calculate IP checksum */ - TxUDPCS = (1 << 17), /* Calculate UDP/IP checksum */ - TxTCPCS = (1 << 16), /* Calculate TCP/IP checksum */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ - - /*@@@@@@ offset 4 of tx descriptor => bits for RTL8168C/CP only begin @@@@@@*/ - TxUDPCS_C = (1 << 31), /* Calculate UDP/IP checksum */ - TxTCPCS_C = (1 << 30), /* Calculate TCP/IP checksum */ - TxIPCS_C = (1 << 29), /* Calculate IP checksum */ - TxIPV6F_C = (1 << 28), /* Indicate it is an IPv6 packet */ - /*@@@@@@ offset 4 of tx descriptor => bits for RTL8168C/CP only end @@@@@@*/ - - - /* Rx private */ - /*------ offset 0 of rx descriptor ------*/ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - RxIPF = (1 << 16), /* IP checksum failed */ - RxUDPF = (1 << 15), /* UDP/IP checksum failed */ - RxTCPF = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ - - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8168C/CP only begin @@@@@@*/ - RxUDPT = (1 << 18), - RxTCPT = (1 << 17), - /*@@@@@@ offset 0 of rx descriptor => bits for RTL8168C/CP only end @@@@@@*/ - - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8168C/CP only begin @@@@@@*/ - RxV6F = (1 << 31), - RxV4F = (1 << 30), - /*@@@@@@ offset 4 of rx descriptor => bits for RTL8168C/CP only end @@@@@@*/ -}; - -enum features { -// RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), -}; - -enum wol_capability { - WOL_DISABLED = 0, - WOL_ENABLED = 1 -}; - -enum bits { - BIT_0 = (1 << 0), - BIT_1 = (1 << 1), - BIT_2 = (1 << 2), - BIT_3 = (1 << 3), - BIT_4 = (1 << 4), - BIT_5 = (1 << 5), - BIT_6 = (1 << 6), - BIT_7 = (1 << 7), - BIT_8 = (1 << 8), - BIT_9 = (1 << 9), - BIT_10 = (1 << 10), - BIT_11 = (1 << 11), - BIT_12 = (1 << 12), - BIT_13 = (1 << 13), - BIT_14 = (1 << 14), - BIT_15 = (1 << 15), - BIT_16 = (1 << 16), - BIT_17 = (1 << 17), - BIT_18 = (1 << 18), - BIT_19 = (1 << 19), - BIT_20 = (1 << 20), - BIT_21 = (1 << 21), - BIT_22 = (1 << 22), - BIT_23 = (1 << 23), - BIT_24 = (1 << 24), - BIT_25 = (1 << 25), - BIT_26 = (1 << 26), - BIT_27 = (1 << 27), - BIT_28 = (1 << 28), - BIT_29 = (1 << 29), - BIT_30 = (1 << 30), - BIT_31 = (1 << 31) -}; - -enum effuse { - EFUSE_NOT_SUPPORT = 0, - EFUSE_SUPPORT_V1, - EFUSE_SUPPORT_V2, - EFUSE_SUPPORT_V3, -}; -#define RsvdMask 0x3fffc000 - -struct TxDesc { - u32 opts1; - u32 opts2; - u64 addr; -}; - -struct RxDesc { - u32 opts1; - u32 opts2; - u64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -struct pci_resource { - u8 cmd; - u8 cls; - u16 io_base_h; - u16 io_base_l; - u16 mem_base_h; - u16 mem_base_l; - u8 ilr; - u16 resv_0x1c_h; - u16 resv_0x1c_l; - u16 resv_0x20_h; - u16 resv_0x20_l; - u16 resv_0x24_h; - u16 resv_0x24_l; - u16 resv_0x2c_h; - u16 resv_0x2c_l; - u32 pci_sn_l; - u32 pci_sn_h; -}; - -struct rtl8168_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; /* Index of PCI device */ - struct net_device *dev; -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) - struct napi_struct napi; -#endif -#endif - struct net_device_stats stats; /* statistics of net device */ - spinlock_t lock; /* spin lock flag */ - u32 msg_enable; - u32 tx_tcp_csum_cmd; - u32 tx_udp_csum_cmd; - u32 tx_ip_csum_cmd; - u32 tx_ipv6_csum_cmd; - int max_jumbo_frame_size; - int chipset; - u32 mcfg; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_rx; - u32 dirty_tx; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - struct sk_buff *Rx_skbuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - unsigned rx_buf_sz; - struct timer_list esd_timer; - struct timer_list link_timer; - struct pci_resource pci_cfg_space; - unsigned int esd_flag; - unsigned int pci_cfg_is_read; - unsigned int rtl8168_rx_config; - u16 cp_cmd; - u16 intr_mask; - u16 timer_intr_mask; - int phy_auto_nego_reg; - int phy_1000_ctrl_reg; - u8 org_mac_addr[NODE_ADDRESS_SIZE]; - struct rtl8168_counters *tally_vaddr; - dma_addr_t tally_paddr; - -#ifdef CONFIG_R8168_VLAN - struct vlan_group *vlgrp; -#endif - u8 wol_enabled; - u32 wol_opts; - u8 efuse_ver; - u8 eeprom_type; - u8 autoneg; - u8 duplex; - u32 speed; - u32 advertising; - u16 eeprom_len; - u16 cur_page; - u32 bios_setting; - - int (*set_speed)(struct net_device *, u8 autoneg, u32 speed, u8 duplex, u32 adv); -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - void (*get_settings)(struct net_device *, struct ethtool_cmd *); -#else - void (*get_settings)(struct net_device *, struct ethtool_link_ksettings *); -#endif - void (*phy_reset_enable)(struct net_device *); - unsigned int (*phy_reset_pending)(struct net_device *); - unsigned int (*link_ok)(struct net_device *); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct work_struct task; -#else - struct delayed_work task; -#endif - unsigned features; - - u8 org_pci_offset_99; - u8 org_pci_offset_180; - u8 issue_offset_99_event; - - u8 org_pci_offset_80; - u8 org_pci_offset_81; - u8 use_timer_interrrupt; - - u32 keep_intr_cnt; - - u8 HwIcVerUnknown; - u8 NotWrRamCodeToMicroP; - u8 NotWrMcuPatchCode; - u8 HwHasWrRamCodeToMicroP; - - u16 sw_ram_code_ver; - u16 hw_ram_code_ver; - - u8 rtk_enable_diag; - - u8 ShortPacketSwChecksum; - - u8 UseSwPaddingShortPkt; - - u8 RequireAdcBiasPatch; - u16 AdcBiasPatchIoffset; - - u8 RequireAdjustUpsTxLinkPulseTiming; - u16 SwrCnt1msIni; - - u8 HwSuppNowIsOobVer; - - u8 RequiredSecLanDonglePatch; - - u32 HwFiberModeVer; - u32 HwFiberStat; - u8 HwSwitchMdiToFiber; - - u8 HwSuppSerDesPhyVer; - - u8 HwSuppPhyOcpVer; - - u8 HwSuppAspmClkIntrLock; - - u16 NicCustLedValue; - - u8 HwSuppUpsVer; - - u8 HwSuppMagicPktVer; - - u8 HwSuppCheckPhyDisableModeVer; - - u8 random_mac; - - u16 phy_reg_aner; - u16 phy_reg_anlpar; - u16 phy_reg_gbsr; - - u32 HwPcieSNOffset; - - u8 HwSuppEsdVer; - u8 TestPhyOcpReg; - u16 BackupPhyFuseDout_15_0; - u16 BackupPhyFuseDout_47_32; - u16 BackupPhyFuseDout_63_48; - - const char *fw_name; - struct rtl8168_fw *rtl_fw; - u32 ocp_base; - - //Dash+++++++++++++++++ - u8 HwSuppDashVer; - u8 DASH; - u8 dash_printer_enabled; - u8 HwPkgDet; - void __iomem *mapped_cmac_ioaddr; /* mapped cmac memory map physical address */ - void __iomem *cmac_ioaddr; /* cmac memory map physical address */ - -#ifdef ENABLE_DASH_SUPPORT - u16 AfterRecvFromFwBufLen; - u8 AfterRecvFromFwBuf[RECV_FROM_FW_BUF_SIZE]; - u16 AfterSendToFwBufLen; - u8 AfterSendToFwBuf[SEND_TO_FW_BUF_SIZE]; - u16 SendToFwBufferLen; - u32 SizeOfSendToFwBuffer ; - u32 SizeOfSendToFwBufferMemAlloc ; - u32 NumOfSendToFwBuffer ; - - u8 OobReq; - u8 OobAck; - u32 OobReqComplete; - u32 OobAckComplete; - - u8 RcvFwReqSysOkEvt; - u8 RcvFwDashOkEvt; - u8 SendFwHostOkEvt; - - u8 DashFwDisableRx; - - void *SendToFwBuffer ; - dma_addr_t SendToFwBufferPhy ; - u8 SendingToFw; - PTX_DASH_SEND_FW_DESC TxDashSendFwDesc; - dma_addr_t TxDashSendFwDescPhy; - u32 SizeOfTxDashSendFwDescMemAlloc; - u32 SizeOfTxDashSendFwDesc ; - u32 NumTxDashSendFwDesc ; - u32 CurrNumTxDashSendFwDesc ; - u32 LastSendNumTxDashSendFwDesc ; - - u32 NumRecvFromFwBuffer ; - u32 SizeOfRecvFromFwBuffer ; - u32 SizeOfRecvFromFwBufferMemAlloc ; - void *RecvFromFwBuffer ; - dma_addr_t RecvFromFwBufferPhy ; - - PRX_DASH_FROM_FW_DESC RxDashRecvFwDesc; - dma_addr_t RxDashRecvFwDescPhy; - u32 SizeOfRxDashRecvFwDescMemAlloc; - u32 SizeOfRxDashRecvFwDesc ; - u32 NumRxDashRecvFwDesc ; - u32 CurrNumRxDashRecvFwDesc ; - u8 DashReqRegValue; - u16 HostReqValue; - - u32 CmacResetIsrCounter; - u8 CmacResetIntr ; - u8 CmacResetting ; - u8 CmacOobIssueCmacReset ; - u32 CmacResetbyFwCnt; - -#if defined(ENABLE_DASH_PRINTER_SUPPORT) - struct completion fw_ack; - struct completion fw_req; - struct completion fw_host_ok; -#endif - //Dash----------------- -#endif //ENABLE_DASH_SUPPORT - - //Realwow++++++++++++++ - u8 HwSuppKCPOffloadVer; - - u8 EnableDhcpTimeoutWake; - u8 EnableTeredoOffload; - u8 EnableKCPOffload; -#ifdef ENABLE_REALWOW_SUPPORT - u32 DhcpTimeout; - MP_KCP_INFO MpKCPInfo; - //Realwow-------------- -#endif //ENABLE_REALWOW_SUPPORT - - u32 eee_adv_t; - u8 eee_enabled; - - u32 dynamic_aspm_packet_count; - -#ifdef ENABLE_R8168_PROCFS - //Procfs support - struct proc_dir_entry *proc_dir; -#endif -}; - -enum eetype { - EEPROM_TYPE_NONE=0, - EEPROM_TYPE_93C46, - EEPROM_TYPE_93C56, - EEPROM_TWSI -}; - -enum mcfg { - CFG_METHOD_1=0, - CFG_METHOD_2, - CFG_METHOD_3, - CFG_METHOD_4, - CFG_METHOD_5, - CFG_METHOD_6, - CFG_METHOD_7, - CFG_METHOD_8, - CFG_METHOD_9 , - CFG_METHOD_10, - CFG_METHOD_11, - CFG_METHOD_12, - CFG_METHOD_13, - CFG_METHOD_14, - CFG_METHOD_15, - CFG_METHOD_16, - CFG_METHOD_17, - CFG_METHOD_18, - CFG_METHOD_19, - CFG_METHOD_20, - CFG_METHOD_21, - CFG_METHOD_22, - CFG_METHOD_23, - CFG_METHOD_24, - CFG_METHOD_25, - CFG_METHOD_26, - CFG_METHOD_27, - CFG_METHOD_28, - CFG_METHOD_29, - CFG_METHOD_30, - CFG_METHOD_31, - CFG_METHOD_32, - CFG_METHOD_33, - CFG_METHOD_MAX, - CFG_METHOD_DEFAULT = 0xFF -}; - -#define LSO_32K 32000 -#define LSO_64K 64000 - -#define NIC_MIN_PHYS_BUF_COUNT (2) -#define NIC_MAX_PHYS_BUF_COUNT_LSO_64K (24) -#define NIC_MAX_PHYS_BUF_COUNT_LSO2 (16*4) - -#define GTTCPHO_SHIFT 18 -#define GTTCPHO_MAX 0x7fU -#define GTPKTSIZE_MAX 0x3ffffU -#define TCPHO_SHIFT 18 -#define TCPHO_MAX 0x3ffU -#define LSOPKTSIZE_MAX 0xffffU -#define MSS_MAX 0x07ffu /* MSS value */ - -#define OOB_CMD_RESET 0x00 -#define OOB_CMD_DRIVER_START 0x05 -#define OOB_CMD_DRIVER_STOP 0x06 -#define OOB_CMD_SET_IPMAC 0x41 - -#define WAKEUP_MAGIC_PACKET_NOT_SUPPORT (0) -#define WAKEUP_MAGIC_PACKET_V1 (1) -#define WAKEUP_MAGIC_PACKET_V2 (2) - -//Ram Code Version -#define NIC_RAMCODE_VERSION_CFG_METHOD_14 (0x0057) -#define NIC_RAMCODE_VERSION_CFG_METHOD_16 (0x0055) -#define NIC_RAMCODE_VERSION_CFG_METHOD_18 (0x0052) -#define NIC_RAMCODE_VERSION_CFG_METHOD_20 (0x0044) -#define NIC_RAMCODE_VERSION_CFG_METHOD_21 (0x0042) -#define NIC_RAMCODE_VERSION_CFG_METHOD_24 (0x0001) -#define NIC_RAMCODE_VERSION_CFG_METHOD_23 (0x0015) -#define NIC_RAMCODE_VERSION_CFG_METHOD_26 (0x0012) -#define NIC_RAMCODE_VERSION_CFG_METHOD_28 (0x0019) -#define NIC_RAMCODE_VERSION_CFG_METHOD_29 (0x0055) -#define NIC_RAMCODE_VERSION_CFG_METHOD_31 (0x0003) - -//hwoptimize -#define HW_PATCH_SOC_LAN (BIT_0) -#define HW_PATCH_SAMSUNG_LAN_DONGLE (BIT_2) - -#define HW_PHY_STATUS_INI 1 -#define HW_PHY_STATUS_EXT_INI 2 -#define HW_PHY_STATUS_LAN_ON 3 - -void rtl8168_mdio_write(struct rtl8168_private *tp, u16 RegAddr, u16 value); -void rtl8168_mdio_prot_write(struct rtl8168_private *tp, u32 RegAddr, u32 value); -void rtl8168_mdio_prot_direct_write_phy_ocp(struct rtl8168_private *tp, u32 RegAddr, u32 value); -u32 rtl8168_mdio_read(struct rtl8168_private *tp, u16 RegAddr); -u32 rtl8168_mdio_prot_read(struct rtl8168_private *tp, u32 RegAddr); -u32 rtl8168_mdio_prot_direct_read_phy_ocp(struct rtl8168_private *tp, u32 RegAddr); -void rtl8168_ephy_write(struct rtl8168_private *tp, int RegAddr, int value); -void rtl8168_mac_ocp_write(struct rtl8168_private *tp, u16 reg_addr, u16 value); -u16 rtl8168_mac_ocp_read(struct rtl8168_private *tp, u16 reg_addr); -void rtl8168_clear_eth_phy_bit(struct rtl8168_private *tp, u8 addr, u16 mask); -void rtl8168_set_eth_phy_bit(struct rtl8168_private *tp, u8 addr, u16 mask); -void rtl8168_ocp_write(struct rtl8168_private *tp, u16 addr, u8 len, u32 data); -void rtl8168_oob_notify(struct rtl8168_private *tp, u8 cmd); -void rtl8168_init_ring_indexes(struct rtl8168_private *tp); -int rtl8168_eri_write(struct rtl8168_private *tp, int addr, int len, u32 value, int type); -void rtl8168_oob_mutex_lock(struct rtl8168_private *tp); -u32 rtl8168_ocp_read(struct rtl8168_private *tp, u16 addr, u8 len); -u32 rtl8168_ocp_read_with_oob_base_address(struct rtl8168_private *tp, u16 addr, u8 len, u32 base_address); -u32 rtl8168_ocp_write_with_oob_base_address(struct rtl8168_private *tp, u16 addr, u8 len, u32 value, u32 base_address); -u32 rtl8168_eri_read(struct rtl8168_private *tp, int addr, int len, int type); -u32 rtl8168_eri_read_with_oob_base_address(struct rtl8168_private *tp, int addr, int len, int type, u32 base_address); -int rtl8168_eri_write_with_oob_base_address(struct rtl8168_private *tp, int addr, int len, u32 value, int type, u32 base_address); -u16 rtl8168_ephy_read(struct rtl8168_private *tp, int RegAddr); -void rtl8168_wait_txrx_fifo_empty(struct net_device *dev); -void rtl8168_wait_ll_share_fifo_ready(struct net_device *dev); -void rtl8168_enable_now_is_oob(struct rtl8168_private *tp); -void rtl8168_disable_now_is_oob(struct rtl8168_private *tp); -void rtl8168_oob_mutex_unlock(struct rtl8168_private *tp); -void rtl8168_dash2_disable_tx(struct rtl8168_private *tp); -void rtl8168_dash2_enable_tx(struct rtl8168_private *tp); -void rtl8168_dash2_disable_rx(struct rtl8168_private *tp); -void rtl8168_dash2_enable_rx(struct rtl8168_private *tp); -void rtl8168_hw_disable_mac_mcu_bps(struct net_device *dev); - -#define HW_SUPPORT_CHECK_PHY_DISABLE_MODE(_M) ((_M)->HwSuppCheckPhyDisableModeVer > 0 ) -#define HW_SUPP_SERDES_PHY(_M) ((_M)->HwSuppSerDesPhyVer > 0) -#define HW_HAS_WRITE_PHY_MCU_RAM_CODE(_M) (((_M)->HwHasWrRamCodeToMicroP == TRUE) ? 1 : 0) -#define HW_SUPPORT_UPS_MODE(_M) ((_M)->HwSuppUpsVer > 0) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,34) -#define netdev_mc_count(dev) ((dev)->mc_count) -#define netdev_mc_empty(dev) (netdev_mc_count(dev) == 0) -#define netdev_for_each_mc_addr(mclist, dev) \ - for (mclist = dev->mc_list; mclist; mclist = mclist->next) -#endif diff --git a/addons/r8168/src/4.4.180/r8168_asf.c b/addons/r8168/src/4.4.180/r8168_asf.c deleted file mode 100644 index 77524f04..00000000 --- a/addons/r8168/src/4.4.180/r8168_asf.c +++ /dev/null @@ -1,422 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "r8168.h" -#include "r8168_asf.h" -#include "rtl_eeprom.h" - -int rtl8168_asf_ioctl(struct net_device *dev, - struct ifreq *ifr) -{ - struct rtl8168_private *tp = netdev_priv(dev); - void *user_data = ifr->ifr_data; - struct asf_ioctl_struct asf_usrdata; - unsigned long flags; - - if (tp->mcfg != CFG_METHOD_7 && tp->mcfg != CFG_METHOD_8) - return -EOPNOTSUPP; - - if (copy_from_user(&asf_usrdata, user_data, sizeof(struct asf_ioctl_struct))) - return -EFAULT; - - spin_lock_irqsave(&tp->lock, flags); - - switch (asf_usrdata.offset) { - case HBPeriod: - rtl8168_asf_hbperiod(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case WD8Timer: - break; - case WD16Rst: - rtl8168_asf_wd16rst(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case WD8Rst: - rtl8168_asf_time_period(tp, asf_usrdata.arg, WD8Rst, asf_usrdata.u.data); - break; - case LSnsrPollCycle: - rtl8168_asf_time_period(tp, asf_usrdata.arg, LSnsrPollCycle, asf_usrdata.u.data); - break; - case ASFSnsrPollPrd: - rtl8168_asf_time_period(tp, asf_usrdata.arg, ASFSnsrPollPrd, asf_usrdata.u.data); - break; - case AlertReSendItvl: - rtl8168_asf_time_period(tp, asf_usrdata.arg, AlertReSendItvl, asf_usrdata.u.data); - break; - case SMBAddr: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, SMBAddr, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case ASFConfigR0: - rtl8168_asf_config_regs(tp, asf_usrdata.arg, ASFConfigR0, asf_usrdata.u.data); - break; - case ASFConfigR1: - rtl8168_asf_config_regs(tp, asf_usrdata.arg, ASFConfigR1, asf_usrdata.u.data); - break; - case ConsoleMA: - rtl8168_asf_console_mac(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case ConsoleIP: - rtl8168_asf_ip_address(tp, asf_usrdata.arg, ConsoleIP, asf_usrdata.u.data); - break; - case IPAddr: - rtl8168_asf_ip_address(tp, asf_usrdata.arg, IPAddr, asf_usrdata.u.data); - break; - case UUID: - rtl8168_asf_rw_uuid(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case IANA: - rtl8168_asf_rw_iana(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case SysID: - rtl8168_asf_rw_systemid(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case Community: - rtl8168_asf_community_string(tp, asf_usrdata.arg, asf_usrdata.u.string); - break; - case StringLength: - rtl8168_asf_community_string_len(tp, asf_usrdata.arg, asf_usrdata.u.data); - break; - case FmCapMsk: - rtl8168_asf_capability_masks(tp, asf_usrdata.arg, FmCapMsk, asf_usrdata.u.data); - break; - case SpCMDMsk: - rtl8168_asf_capability_masks(tp, asf_usrdata.arg, SpCMDMsk, asf_usrdata.u.data); - break; - case SysCapMsk: - rtl8168_asf_capability_masks(tp, asf_usrdata.arg, SysCapMsk, asf_usrdata.u.data); - break; - case RmtRstAddr: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtRstAddr, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtRstCmd: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtRstCmd, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtRstData: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtRstData, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPwrOffAddr: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOffAddr, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPwrOffCmd: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOffCmd, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPwrOffData: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOffData, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPwrOnAddr: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOnAddr, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPwrOnCmd: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOnCmd, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPwrOnData: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPwrOnData, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPCRAddr: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPCRAddr, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPCRCmd: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPCRCmd, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case RmtPCRData: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, RmtPCRData, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case ASFSnsr0Addr: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, ASFSnsr0Addr, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case LSnsrAddr0: - rtl8168_asf_rw_hexadecimal(tp, asf_usrdata.arg, LSnsrAddr0, RW_ONE_BYTE, asf_usrdata.u.data); - break; - case KO: - /* Get/Set Key Operation */ - rtl8168_asf_key_access(tp, asf_usrdata.arg, KO, asf_usrdata.u.data); - break; - case KA: - /* Get/Set Key Administrator */ - rtl8168_asf_key_access(tp, asf_usrdata.arg, KA, asf_usrdata.u.data); - break; - case KG: - /* Get/Set Key Generation */ - rtl8168_asf_key_access(tp, asf_usrdata.arg, KG, asf_usrdata.u.data); - break; - case KR: - /* Get/Set Key Random */ - rtl8168_asf_key_access(tp, asf_usrdata.arg, KR, asf_usrdata.u.data); - break; - default: - spin_unlock_irqrestore(&tp->lock, flags); - return -EOPNOTSUPP; - } - - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(user_data, &asf_usrdata, sizeof(struct asf_ioctl_struct))) - return -EFAULT; - - return 0; -} - -void rtl8168_asf_hbperiod(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - if (arg == ASF_GET) - data[ASFHBPERIOD] = rtl8168_eri_read(tp, HBPeriod, RW_TWO_BYTES, ERIAR_ASF); - else if (arg == ASF_SET) { - rtl8168_eri_write(tp, HBPeriod, RW_TWO_BYTES, data[ASFHBPERIOD], ERIAR_ASF); - rtl8168_eri_write(tp, 0x1EC, RW_ONE_BYTE, 0x07, ERIAR_ASF); - } -} - -void rtl8168_asf_wd16rst(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - data[ASFWD16RST] = rtl8168_eri_read(tp, WD16Rst, RW_TWO_BYTES, ERIAR_ASF); -} - -void rtl8168_asf_console_mac(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - int i; - - if (arg == ASF_GET) { - for (i = 0; i < 6; i++) - data[i] = rtl8168_eri_read(tp, ConsoleMA + i, RW_ONE_BYTE, ERIAR_ASF); - } else if (arg == ASF_SET) { - for (i = 0; i < 6; i++) - rtl8168_eri_write(tp, ConsoleMA + i, RW_ONE_BYTE, data[i], ERIAR_ASF); - - /* write the new console MAC address to EEPROM */ - rtl8168_eeprom_write_sc(tp, 70, (data[1] << 8) | data[0]); - rtl8168_eeprom_write_sc(tp, 71, (data[3] << 8) | data[2]); - rtl8168_eeprom_write_sc(tp, 72, (data[5] << 8) | data[4]); - } -} - -void rtl8168_asf_ip_address(struct rtl8168_private *tp, int arg, int offset, unsigned int *data) -{ - int i; - int eeprom_off = 0; - - if (arg == ASF_GET) { - for (i = 0; i < 4; i++) - data[i] = rtl8168_eri_read(tp, offset + i, RW_ONE_BYTE, ERIAR_ASF); - } else if (arg == ASF_SET) { - for (i = 0; i < 4; i++) - rtl8168_eri_write(tp, offset + i, RW_ONE_BYTE, data[i], ERIAR_ASF); - - if (offset == ConsoleIP) - eeprom_off = 73; - else if (offset == IPAddr) - eeprom_off = 75; - - /* write the new IP address to EEPROM */ - rtl8168_eeprom_write_sc(tp, eeprom_off, (data[1] << 8) | data[0]); - rtl8168_eeprom_write_sc(tp, eeprom_off + 1, (data[3] << 8) | data[2]); - - } -} - -void rtl8168_asf_config_regs(struct rtl8168_private *tp, int arg, int offset, unsigned int *data) -{ - unsigned int value; - - if (arg == ASF_GET) { - data[ASFCAPABILITY] = (rtl8168_eri_read(tp, offset, RW_ONE_BYTE, ERIAR_ASF) & data[ASFCONFIG]) ? FUNCTION_ENABLE : FUNCTION_DISABLE; - } else if (arg == ASF_SET) { - value = rtl8168_eri_read(tp, offset, RW_ONE_BYTE, ERIAR_ASF); - - if (data[ASFCAPABILITY] == FUNCTION_ENABLE) - value |= data[ASFCONFIG]; - else if (data[ASFCAPABILITY] == FUNCTION_DISABLE) - value &= ~data[ASFCONFIG]; - - rtl8168_eri_write(tp, offset, RW_ONE_BYTE, value, ERIAR_ASF); - } -} - -void rtl8168_asf_capability_masks(struct rtl8168_private *tp, int arg, int offset, unsigned int *data) -{ - unsigned int len, bit_mask; - - bit_mask = DISABLE_MASK; - - if (offset == FmCapMsk) { - /* System firmware capabilities */ - len = RW_FOUR_BYTES; - if (data[ASFCAPMASK] == FUNCTION_ENABLE) - bit_mask = FMW_CAP_MASK; - } else if (offset == SpCMDMsk) { - /* Special commands */ - len = RW_TWO_BYTES; - if (data[ASFCAPMASK] == FUNCTION_ENABLE) - bit_mask = SPC_CMD_MASK; - } else { - /* System capability (offset == SysCapMsk)*/ - len = RW_ONE_BYTE; - if (data[ASFCAPMASK] == FUNCTION_ENABLE) - bit_mask = SYS_CAP_MASK; - } - - if (arg == ASF_GET) - data[ASFCAPMASK] = rtl8168_eri_read(tp, offset, len, ERIAR_ASF) ? FUNCTION_ENABLE : FUNCTION_DISABLE; - else /* arg == ASF_SET */ - rtl8168_eri_write(tp, offset, len, bit_mask, ERIAR_ASF); -} - -void rtl8168_asf_community_string(struct rtl8168_private *tp, int arg, char *string) -{ - int i; - - if (arg == ASF_GET) { - for (i = 0; i < COMMU_STR_MAX_LEN; i++) - string[i] = rtl8168_eri_read(tp, Community + i, RW_ONE_BYTE, ERIAR_ASF); - } else { /* arg == ASF_SET */ - for (i = 0; i < COMMU_STR_MAX_LEN; i++) - rtl8168_eri_write(tp, Community + i, RW_ONE_BYTE, string[i], ERIAR_ASF); - } -} - -void rtl8168_asf_community_string_len(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - if (arg == ASF_GET) - data[ASFCOMMULEN] = rtl8168_eri_read(tp, StringLength, RW_ONE_BYTE, ERIAR_ASF); - else /* arg == ASF_SET */ - rtl8168_eri_write(tp, StringLength, RW_ONE_BYTE, data[ASFCOMMULEN], ERIAR_ASF); -} - -void rtl8168_asf_time_period(struct rtl8168_private *tp, int arg, int offset, unsigned int *data) -{ - int pos = 0; - - if (offset == WD8Rst) - pos = ASFWD8RESET; - else if (offset == LSnsrPollCycle) - pos = ASFLSNRPOLLCYC; - else if (offset == ASFSnsrPollPrd) - pos = ASFSNRPOLLCYC; - else if (offset == AlertReSendItvl) - pos = ASFALERTRESND; - - if (arg == ASF_GET) - data[pos] = rtl8168_eri_read(tp, offset, RW_ONE_BYTE, ERIAR_ASF); - else /* arg == ASF_SET */ - rtl8168_eri_write(tp, offset, RW_ONE_BYTE, data[pos], ERIAR_ASF); - -} - -void rtl8168_asf_key_access(struct rtl8168_private *tp, int arg, int offset, unsigned int *data) -{ - int i, j; - int key_off = 0; - - if (arg == ASF_GET) { - for (i = 0; i < KEY_LEN; i++) - data[i] = rtl8168_eri_read(tp, offset + KEY_LEN - (i + 1), RW_ONE_BYTE, ERIAR_ASF); - } else { - if (offset == KO) - key_off = 162; - else if (offset == KA) - key_off = 172; - else if (offset == KG) - key_off = 182; - else if (offset == KR) - key_off = 192; - - /* arg == ASF_SET */ - for (i = 0; i < KEY_LEN; i++) - rtl8168_eri_write(tp, offset + KEY_LEN - (i + 1), RW_ONE_BYTE, data[i], ERIAR_ASF); - - /* write the new key to EEPROM */ - for (i = 0, j = 19; i < 10; i++, j = j - 2) - rtl8168_eeprom_write_sc(tp, key_off + i, (data[j - 1] << 8) | data[j]); - } -} - -void rtl8168_asf_rw_hexadecimal(struct rtl8168_private *tp, int arg, int offset, int len, unsigned int *data) -{ - if (arg == ASF_GET) - data[ASFRWHEXNUM] = rtl8168_eri_read(tp, offset, len, ERIAR_ASF); - else /* arg == ASF_SET */ - rtl8168_eri_write(tp, offset, len, data[ASFRWHEXNUM], ERIAR_ASF); -} - -void rtl8168_asf_rw_systemid(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - int i; - - if (arg == ASF_GET) - for (i = 0; i < SYSID_LEN ; i++) - data[i] = rtl8168_eri_read(tp, SysID + i, RW_ONE_BYTE, ERIAR_ASF); - else /* arg == ASF_SET */ - for (i = 0; i < SYSID_LEN ; i++) - rtl8168_eri_write(tp, SysID + i, RW_ONE_BYTE, data[i], ERIAR_ASF); -} - -void rtl8168_asf_rw_iana(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - int i; - - if (arg == ASF_GET) - for (i = 0; i < RW_FOUR_BYTES; i++) - data[i] = rtl8168_eri_read(tp, IANA + i, RW_ONE_BYTE, ERIAR_ASF); - else /* arg == ASF_SET */ - for (i = 0; i < RW_FOUR_BYTES; i++) - rtl8168_eri_write(tp, IANA + i, RW_ONE_BYTE, data[i], ERIAR_ASF); -} - -void rtl8168_asf_rw_uuid(struct rtl8168_private *tp, int arg, unsigned int *data) -{ - int i, j; - - if (arg == ASF_GET) - for (i = UUID_LEN - 1, j = 0; i >= 0 ; i--, j++) - data[j] = rtl8168_eri_read(tp, UUID + i, RW_ONE_BYTE, ERIAR_ASF); - else /* arg == ASF_SET */ - for (i = UUID_LEN - 1, j = 0; i >= 0 ; i--, j++) - rtl8168_eri_write(tp, UUID + i, RW_ONE_BYTE, data[j], ERIAR_ASF); -} diff --git a/addons/r8168/src/4.4.180/r8168_asf.h b/addons/r8168/src/4.4.180/r8168_asf.h deleted file mode 100644 index c4b412a6..00000000 --- a/addons/r8168/src/4.4.180/r8168_asf.h +++ /dev/null @@ -1,295 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#define SIOCDEVPRIVATE_RTLASF SIOCDEVPRIVATE - -#define FUNCTION_ENABLE 1 -#define FUNCTION_DISABLE 0 - -#define ASFCONFIG 0 -#define ASFCAPABILITY 1 -#define ASFCOMMULEN 0 -#define ASFHBPERIOD 0 -#define ASFWD16RST 0 -#define ASFCAPMASK 0 -#define ASFALERTRESND 0 -#define ASFLSNRPOLLCYC 0 -#define ASFSNRPOLLCYC 0 -#define ASFWD8RESET 0 -#define ASFRWHEXNUM 0 - -#define FMW_CAP_MASK 0x0000F867 -#define SPC_CMD_MASK 0x1F00 -#define SYS_CAP_MASK 0xFF -#define DISABLE_MASK 0x00 - -#define MAX_DATA_LEN 200 -#define MAX_STR_LEN 200 - -#define COMMU_STR_MAX_LEN 23 - -#define KEY_LEN 20 -#define UUID_LEN 16 -#define SYSID_LEN 2 - -#define RW_ONE_BYTE 1 -#define RW_TWO_BYTES 2 -#define RW_FOUR_BYTES 4 - -enum asf_registers { - HBPeriod = 0x0000, - WD8Rst = 0x0002, - WD8Timer = 0x0003, - WD16Rst = 0x0004, - LSnsrPollCycle = 0x0006, - ASFSnsrPollPrd = 0x0007, - AlertReSendCnt = 0x0008, - AlertReSendItvl = 0x0009, - SMBAddr = 0x000A, - SMBCap = 0x000B, - ASFConfigR0 = 0x000C, - ASFConfigR1 = 0x000D, - WD16Timer = 0x000E, - ConsoleMA = 0x0010, - ConsoleIP = 0x0016, - IPAddr = 0x001A, - - UUID = 0x0020, - IANA = 0x0030, - SysID = 0x0034, - Community = 0x0036, - StringLength = 0x004D, - LC = 0x004E, - EntityInst = 0x004F, - FmCapMsk = 0x0050, - SpCMDMsk = 0x0054, - SysCapMsk = 0x0056, - WDSysSt = 0x0057, - RxMsgType = 0x0058, - RxSpCMD = 0x0059, - RxSpCMDPa = 0x005A, - RxBtOpMsk = 0x005C, - RmtRstAddr = 0x005E, - RmtRstCmd = 0x005F, - RmtRstData = 0x0060, - RmtPwrOffAddr = 0x0061, - RmtPwrOffCmd = 0x0062, - RmtPwrOffData = 0x0063, - RmtPwrOnAddr = 0x0064, - RmtPwrOnCmd = 0x0065, - RmtPwrOnData = 0x0066, - RmtPCRAddr = 0x0067, - RmtPCRCmd = 0x0068, - RmtPCRData = 0x0069, - RMCP_IANA = 0x006A, - RMCP_OEM = 0x006E, - ASFSnsr0Addr = 0x0070, - - ASFSnsrEvSt = 0x0073, - ASFSnsrEvAlert = 0x0081, - - LSnsrNo = 0x00AD, - AssrtEvntMsk = 0x00AE, - DeAssrtEvntMsk = 0x00AF, - - LSnsrAddr0 = 0x00B0, - LAlertCMD0 = 0x00B1, - LAlertDataMsk0 = 0x00B2, - LAlertCmp0 = 0x00B3, - LAlertESnsrT0 = 0x00B4, - LAlertET0 = 0x00B5, - LAlertEOffset0 = 0x00B6, - LAlertES0 = 0x00B7, - LAlertSN0 = 0x00B8, - LAlertEntity0 = 0x00B9, - LAlertEI0 = 0x00BA, - LSnsrState0 = 0x00BB, - - LSnsrAddr1 = 0x00BD, - LAlertCMD1 = 0x00BE, - LAlertDataMsk1 = 0x00BF, - LAlertCmp1 = 0x00C0, - LAlertESnsrT1 = 0x00C1, - LAlertET1 = 0x00C2, - LAlertEOffset1 = 0x00C3, - LAlertES1 = 0x00C4, - LAlertSN1 = 0x00C5, - LAlertEntity1 = 0x00C6, - LAlertEI1 = 0x00C7, - LSnsrState1 = 0x00C8, - - LSnsrAddr2 = 0x00CA, - LAlertCMD2 = 0x00CB, - LAlertDataMsk2 = 0x00CC, - LAlertCmp2 = 0x00CD, - LAlertESnsrT2 = 0x00CE, - LAlertET2 = 0x00CF, - LAlertEOffset2 = 0x00D0, - LAlertES2 = 0x00D1, - LAlertSN2 = 0x00D2, - LAlertEntity2 = 0x00D3, - LAlertEI2 = 0x00D4, - LSnsrState2 = 0x00D5, - - LSnsrAddr3 = 0x00D7, - LAlertCMD3 = 0x00D8, - LAlertDataMsk3 = 0x00D9, - LAlertCmp3 = 0x00DA, - LAlertESnsrT3 = 0x00DB, - LAlertET3 = 0x00DC, - LAlertEOffset3 = 0x00DD, - LAlertES3 = 0x00DE, - LAlertSN3 = 0x00DF, - LAlertEntity3 = 0x00E0, - LAlertEI3 = 0x00E1, - LSnsrState3 = 0x00E2, - - LSnsrAddr4 = 0x00E4, - LAlertCMD4 = 0x00E5, - LAlertDataMsk4 = 0x00E6, - LAlertCmp4 = 0x00E7, - LAlertESnsrT4 = 0x00E8, - LAlertET4 = 0x00E9, - LAlertEOffset4 = 0x00EA, - LAlertES4 = 0x00EB, - LAlertSN4 = 0x00EC, - LAlertEntity4 = 0x00ED, - LAlertEI4 = 0x00EE, - LSnsrState4 = 0x00EF, - - LSnsrAddr5 = 0x00F1, - LAlertCMD5 = 0x00F2, - LAlertDataMsk5 = 0x00F3, - LAlertCmp5 = 0x00F4, - LAlertESnsrT5 = 0x00F5, - LAlertET5 = 0x00F6, - LAlertEOffset5 = 0x00F7, - LAlertES5 = 0x00F8, - LAlertSN5 = 0x00F9, - LAlertEntity5 = 0x00FA, - LAlertEI5 = 0x00FB, - LSnsrState5 = 0x00FC, - - LSnsrAddr6 = 0x00FE, - LAlertCMD6 = 0x00FF, - LAlertDataMsk6 = 0x0100, - LAlertCmp6 = 0x0101, - LAlertESnsrT6 = 0x0102, - LAlertET6 = 0x0103, - LAlertEOffset6 = 0x0104, - LAlertES6 = 0x0105, - LAlertSN6 = 0x0106, - LAlertEntity6 = 0x0107, - LAlertEI6 = 0x0108, - LSnsrState6 = 0x0109, - - LSnsrAddr7 = 0x010B, - LAlertCMD7 = 0x010C, - LAlertDataMsk7 = 0x010D, - LAlertCmp7 = 0x010E, - LAlertESnsrT7 = 0x010F, - LAlertET7 = 0x0110, - LAlertEOffset7 = 0x0111, - LAlertES7 = 0x0112, - LAlertSN7 = 0x0113, - LAlertEntity7 = 0x0114, - LAlertEI7 = 0x0115, - LSnsrState7 = 0x0116, - LAssert = 0x0117, - LDAssert = 0x0118, - IPServiceType = 0x0119, - IPIdfr = 0x011A, - FlagFOffset = 0x011C, - TTL = 0x011E, - HbtEI = 0x011F, - MgtConSID1 = 0x0120, - MgtConSID2 = 0x0124, - MgdCltSID = 0x0128, - StCd = 0x012C, - MgtConUR = 0x012D, - MgtConUNL = 0x012E, - - AuthPd = 0x0130, - IntyPd = 0x0138, - MgtConRN = 0x0140, - MgdCtlRN = 0x0150, - MgtConUN = 0x0160, - Rakp2IntCk = 0x0170, - KO = 0x017C, - KA = 0x0190, - KG = 0x01A4, - KR = 0x01B8, - CP = 0x01CC, - CQ = 0x01D0, - KC = 0x01D4, - ConsoleSid = 0x01E8, - - SIK1 = 0x01FC, - SIK2 = 0x0210, - Udpsrc_port = 0x0224, - Udpdes_port = 0x0226, - Asf_debug_mux = 0x0228 -}; - -enum asf_cmdln_opt { - ASF_GET, - ASF_SET, - ASF_HELP -}; - -struct asf_ioctl_struct { - unsigned int arg; - unsigned int offset; - union { - unsigned int data[MAX_DATA_LEN]; - char string[MAX_STR_LEN]; - } u; -}; - -int rtl8168_asf_ioctl(struct net_device *dev, struct ifreq *ifr); -void rtl8168_asf_hbperiod(struct rtl8168_private *tp, int arg, unsigned int *data); -void rtl8168_asf_wd16rst(struct rtl8168_private *tp, int arg, unsigned int *data); -void rtl8168_asf_console_mac(struct rtl8168_private *, int arg, unsigned int *data); -void rtl8168_asf_ip_address(struct rtl8168_private *, int arg, int offset, unsigned int *data); -void rtl8168_asf_config_regs(struct rtl8168_private *tp, int arg, int offset, unsigned int *data); -void rtl8168_asf_capability_masks(struct rtl8168_private *tp, int arg, int offset, unsigned int *data); -void rtl8168_asf_community_string(struct rtl8168_private *tp, int arg, char *string); -void rtl8168_asf_community_string_len(struct rtl8168_private *tp, int arg, unsigned int *data); -void rtl8168_asf_alert_resend_interval(struct rtl8168_private *tp, int arg, unsigned int *data); -void rtl8168_asf_time_period(struct rtl8168_private *tp, int arg, int offset, unsigned int *data); -void rtl8168_asf_key_access(struct rtl8168_private *, int arg, int offset, unsigned int *data); -void rtl8168_asf_rw_hexadecimal(struct rtl8168_private *tp, int arg, int offset, int len, unsigned int *data); -void rtl8168_asf_rw_iana(struct rtl8168_private *tp, int arg, unsigned int *data); -void rtl8168_asf_rw_uuid(struct rtl8168_private *tp, int arg, unsigned int *data); -void rtl8168_asf_rw_systemid(struct rtl8168_private *tp, int arg, unsigned int *data); diff --git a/addons/r8168/src/4.4.180/r8168_dash.h b/addons/r8168/src/4.4.180/r8168_dash.h deleted file mode 100644 index b4d358f1..00000000 --- a/addons/r8168/src/4.4.180/r8168_dash.h +++ /dev/null @@ -1,256 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_R8168_DASH_H -#define _LINUX_R8168_DASH_H - -#define SIOCDEVPRIVATE_RTLDASH SIOCDEVPRIVATE+2 - -enum rtl_dash_cmd { - RTL_DASH_ARP_NS_OFFLOAD = 0, - RTL_DASH_SET_OOB_IPMAC, - RTL_DASH_NOTIFY_OOB, - - RTL_DASH_SEND_BUFFER_DATA_TO_DASH_FW, - RTL_DASH_CHECK_SEND_BUFFER_TO_DASH_FW_COMPLETE, - RTL_DASH_GET_RCV_FROM_FW_BUFFER_DATA, - RTL_DASH_OOB_REQ, - RTL_DASH_OOB_ACK, - RTL_DASH_DETACH_OOB_REQ, - RTL_DASH_DETACH_OOB_ACK, - - RTL_FW_SET_IPV4 = 0x10, - RTL_FW_GET_IPV4, - RTL_FW_SET_IPV6, - RTL_FW_GET_IPV6, - RTL_FW_SET_EXT_SNMP, - RTL_FW_GET_EXT_SNMP, - RTL_FW_SET_WAKEUP_PATTERN, - RTL_FW_GET_WAKEUP_PATTERN, - RTL_FW_DEL_WAKEUP_PATTERN, - - RTLT_DASH_COMMAND_INVALID, -}; - -struct rtl_dash_ip_mac { - struct sockaddr ifru_addr; - struct sockaddr ifru_netmask; - struct sockaddr ifru_hwaddr; -}; - -struct rtl_dash_ioctl_struct { - __u32 cmd; - __u32 offset; - __u32 len; - union { - __u32 data; - void *data_buffer; - }; -}; - -struct settings_ipv4 { - __u32 IPv4addr; - __u32 IPv4mask; - __u32 IPv4Gateway; -}; - -struct settings_ipv6 { - __u32 reserved; - __u32 prefixLen; - __u16 IPv6addr[8]; - __u16 IPv6Gateway[8]; -}; - -struct settings_ext_snmp { - __u16 index; - __u16 oid_get_len; - __u8 oid_for_get[24]; - __u8 reserved0[26]; - __u16 value_len; - __u8 value[256]; - __u8 supported; - __u8 reserved1[27]; -}; - -struct wakeup_pattern { - __u8 index; - __u8 valid; - __u8 start; - __u8 length; - __u8 name[36]; - __u8 mask[16]; - __u8 pattern[128]; - __u32 reserved[2]; -}; - -typedef struct _RX_DASH_FROM_FW_DESC { - __le16 length; - __le16 status; - __le32 resv; - __le64 BufferAddress; -} -RX_DASH_FROM_FW_DESC, *PRX_DASH_FROM_FW_DESC; - -typedef struct _TX_DASH_SEND_FW_DESC { - __le16 length; - __le16 status; - __le32 resv; - __le64 BufferAddress; -} -TX_DASH_SEND_FW_DESC, *PTX_DASH_SEND_FW_DESC; - -typedef struct _OSOOBHdr { - __le32 len; - u8 type; - u8 flag; - u8 hostReqV; - u8 res; -} -OSOOBHdr, *POSOOBHdr; - -typedef struct _RX_DASH_BUFFER_TYPE_2 { - OSOOBHdr oobhdr; - u8 RxDataBuffer[0]; -} -RX_DASH_BUFFER_TYPE_2, *PRX_DASH_BUFFER_TYPE_2; - -#define ALIGN_8 (0x7) -#define ALIGN_16 (0xf) -#define ALIGN_32 (0x1f) -#define ALIGN_64 (0x3f) -#define ALIGN_256 (0xff) -#define ALIGN_4096 (0xfff) - -#define OCP_REG_CONFIG0 (0x10) -#define OCP_REG_CONFIG0_REV_F (0xB8) -#define OCP_REG_DASH_POLL (0x30) -#define OCP_REG_HOST_REQ (0x34) -#define OCP_REG_DASH_REQ (0x35) -#define OCP_REG_CR (0x36) -#define OCP_REG_DMEMSTA (0x38) -#define OCP_REG_GPHYAR (0x60) - - -#define OCP_REG_CONFIG0_DASHEN BIT_15 -#define OCP_REG_CONFIG0_OOBRESET BIT_14 -#define OCP_REG_CONFIG0_APRDY BIT_13 -#define OCP_REG_CONFIG0_FIRMWARERDY BIT_12 -#define OCP_REG_CONFIG0_DRIVERRDY BIT_11 -#define OCP_REG_CONFIG0_OOB_WDT BIT_9 -#define OCP_REG_CONFIG0_DRV_WAIT_OOB BIT_8 -#define OCP_REG_CONFIG0_TLSEN BIT_7 - -#define HW_DASH_SUPPORT_DASH(_M) ((_M)->HwSuppDashVer > 0) -#define HW_DASH_SUPPORT_TYPE_1(_M) ((_M)->HwSuppDashVer == 1) -#define HW_DASH_SUPPORT_TYPE_2(_M) ((_M)->HwSuppDashVer == 2) -#define HW_DASH_SUPPORT_TYPE_3(_M) ((_M)->HwSuppDashVer == 3) - -#define RECV_FROM_FW_BUF_SIZE (2048) -#define SEND_TO_FW_BUF_SIZE (2048) - -#define RX_DASH_FROM_FW_OWN BIT_15 -#define TX_DASH_SEND_FW_OWN BIT_15 - -#define TXS_CC3_0 (BIT_0|BIT_1|BIT_2|BIT_3) -#define TXS_EXC BIT_4 -#define TXS_LNKF BIT_5 -#define TXS_OWC BIT_6 -#define TXS_TES BIT_7 -#define TXS_UNF BIT_9 -#define TXS_LGSEN BIT_11 -#define TXS_LS BIT_12 -#define TXS_FS BIT_13 -#define TXS_EOR BIT_14 -#define TXS_OWN BIT_15 - -#define TPPool_HRDY 0x20 - -#define HostReqReg (0xC0) -#define SystemMasterDescStartAddrLow (0xF0) -#define SystemMasterDescStartAddrHigh (0xF4) -#define SystemSlaveDescStartAddrLow (0xF8) -#define SystemSlaveDescStartAddrHigh (0xFC) - -//DASH Request Type -#define WSMANREG 0x01 -#define OSPUSHDATA 0x02 - -#define RXS_OWN BIT_15 -#define RXS_EOR BIT_14 -#define RXS_FS BIT_13 -#define RXS_LS BIT_12 - -#define ISRIMR_DP_DASH_OK BIT_15 -#define ISRIMR_DP_HOST_OK BIT_13 -#define ISRIMR_DP_REQSYS_OK BIT_11 - -#define ISRIMR_DASH_INTR_EN BIT_12 -#define ISRIMR_DASH_INTR_CMAC_RESET BIT_15 - -#define ISRIMR_DASH_TYPE2_ROK BIT_0 -#define ISRIMR_DASH_TYPE2_RDU BIT_1 -#define ISRIMR_DASH_TYPE2_TOK BIT_2 -#define ISRIMR_DASH_TYPE2_TDU BIT_3 -#define ISRIMR_DASH_TYPE2_TX_FIFO_FULL BIT_4 -#define ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE BIT_5 -#define ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE BIT_6 - -#define CMAC_OOB_STOP 0x25 -#define CMAC_OOB_INIT 0x26 -#define CMAC_OOB_RESET 0x2a - -#define NO_BASE_ADDRESS 0x00000000 -#define RTL8168FP_OOBMAC_BASE 0xBAF70000 -#define RTL8168FP_CMAC_IOBASE 0xBAF20000 -#define RTL8168FP_KVM_BASE 0xBAF80400 -#define CMAC_SYNC_REG 0x20 -#define CMAC_RXDESC_OFFSET 0x90 //RX: 0x90 - 0x98 -#define CMAC_TXDESC_OFFSET 0x98 //TX: 0x98 - 0x9F - -/* cmac write/read MMIO register */ -#define RTL_CMAC_W8(tp, reg, val8) writeb ((val8), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_W16(tp, reg, val16) writew ((val16), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_W32(tp, reg, val32) writel ((val32), tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R8(tp, reg) readb (tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R16(tp, reg) readw (tp->cmac_ioaddr + (reg)) -#define RTL_CMAC_R32(tp, reg) ((unsigned long) readl (tp->cmac_ioaddr + (reg))) - -int rtl8168_dash_ioctl(struct net_device *dev, struct ifreq *ifr); -void HandleDashInterrupt(struct net_device *dev); -int AllocateDashShareMemory(struct net_device *dev); -void FreeAllocatedDashShareMemory(struct net_device *dev); -void DashHwInit(struct net_device *dev); - - -#endif /* _LINUX_R8168_DASH_H */ diff --git a/addons/r8168/src/4.4.180/r8168_fiber.h b/addons/r8168/src/4.4.180/r8168_fiber.h deleted file mode 100644 index 2e303fe2..00000000 --- a/addons/r8168/src/4.4.180/r8168_fiber.h +++ /dev/null @@ -1,67 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_R8168_FIBER_H -#define _LINUX_R8168_FIBER_H - -enum { - FIBER_MODE_NIC_ONLY = 0, - FIBER_MODE_RTL8168H_RTL8211FS, - FIBER_MODE_RTL8168H_MDI_SWITCH_RTL8211FS, - FIBER_MODE_MAX -}; - -enum { - FIBER_STAT_NOT_CHECKED = 0, - FIBER_STAT_CONNECT, - FIBER_STAT_DISCONNECT, - FIBER_STAT_MAX -}; - -#define HW_FIBER_MODE_ENABLED(_M) ((_M)->HwFiberModeVer > 0) - - - -void rtl8168_hw_init_fiber_nic(struct net_device *dev); -void rtl8168_hw_fiber_nic_d3_para(struct net_device *dev); -void rtl8168_hw_fiber_phy_config(struct net_device *dev); -void rtl8168_hw_switch_mdi_to_fiber(struct net_device *dev); -void rtl8168_hw_switch_mdi_to_nic(struct net_device *dev); -unsigned int rtl8168_hw_fiber_link_ok(struct net_device *dev); -void rtl8168_check_fiber_link_status(struct net_device *dev); -void rtl8168_check_hw_fiber_mode_support(struct net_device *dev); -void rtl8168_set_fiber_mode_software_variable(struct net_device *dev); - - -#endif /* _LINUX_R8168_FIBER_H */ diff --git a/addons/r8168/src/4.4.180/r8168_firmware.c b/addons/r8168/src/4.4.180/r8168_firmware.c deleted file mode 100644 index 3fe95db9..00000000 --- a/addons/r8168/src/4.4.180/r8168_firmware.c +++ /dev/null @@ -1,264 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include - -#include "r8168_firmware.h" - -enum rtl_fw_opcode { - PHY_READ = 0x0, - PHY_DATA_OR = 0x1, - PHY_DATA_AND = 0x2, - PHY_BJMPN = 0x3, - PHY_MDIO_CHG = 0x4, - PHY_CLEAR_READCOUNT = 0x7, - PHY_WRITE = 0x8, - PHY_READCOUNT_EQ_SKIP = 0x9, - PHY_COMP_EQ_SKIPN = 0xa, - PHY_COMP_NEQ_SKIPN = 0xb, - PHY_WRITE_PREVIOUS = 0xc, - PHY_SKIPN = 0xd, - PHY_DELAY_MS = 0xe, -}; - -struct fw_info { - u32 magic; - char version[RTL8168_VER_SIZE]; - __le32 fw_start; - __le32 fw_len; - u8 chksum; -} __packed; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,16,0) -#define sizeof_field(TYPE, MEMBER) sizeof((((TYPE *)0)->MEMBER)) -#endif -#define FW_OPCODE_SIZE sizeof_field(struct rtl8168_fw_phy_action, code[0]) - -static bool rtl8168_fw_format_ok(struct rtl8168_fw *rtl_fw) -{ - const struct firmware *fw = rtl_fw->fw; - struct fw_info *fw_info = (struct fw_info *)fw->data; - struct rtl8168_fw_phy_action *pa = &rtl_fw->phy_action; - - if (fw->size < FW_OPCODE_SIZE) - return false; - - if (!fw_info->magic) { - size_t i, size, start; - u8 checksum = 0; - - if (fw->size < sizeof(*fw_info)) - return false; - - for (i = 0; i < fw->size; i++) - checksum += fw->data[i]; - if (checksum != 0) - return false; - - start = le32_to_cpu(fw_info->fw_start); - if (start > fw->size) - return false; - - size = le32_to_cpu(fw_info->fw_len); - if (size > (fw->size - start) / FW_OPCODE_SIZE) - return false; - - strscpy(rtl_fw->version, fw_info->version, RTL8168_VER_SIZE); - - pa->code = (__le32 *)(fw->data + start); - pa->size = size; - } else { - if (fw->size % FW_OPCODE_SIZE) - return false; - - strscpy(rtl_fw->version, rtl_fw->fw_name, RTL8168_VER_SIZE); - - pa->code = (__le32 *)fw->data; - pa->size = fw->size / FW_OPCODE_SIZE; - } - - return true; -} - -static bool rtl8168_fw_data_ok(struct rtl8168_fw *rtl_fw) -{ - struct rtl8168_fw_phy_action *pa = &rtl_fw->phy_action; - size_t index; - - for (index = 0; index < pa->size; index++) { - u32 action = le32_to_cpu(pa->code[index]); - u32 val = action & 0x0000ffff; - u32 regno = (action & 0x0fff0000) >> 16; - - switch (action >> 28) { - case PHY_READ: - case PHY_DATA_OR: - case PHY_DATA_AND: - case PHY_CLEAR_READCOUNT: - case PHY_WRITE: - case PHY_WRITE_PREVIOUS: - case PHY_DELAY_MS: - break; - - case PHY_MDIO_CHG: - if (val > 1) - goto out; - break; - - case PHY_BJMPN: - if (regno > index) - goto out; - break; - case PHY_READCOUNT_EQ_SKIP: - if (index + 2 >= pa->size) - goto out; - break; - case PHY_COMP_EQ_SKIPN: - case PHY_COMP_NEQ_SKIPN: - case PHY_SKIPN: - if (index + 1 + regno >= pa->size) - goto out; - break; - - default: - dev_err(rtl_fw->dev, "Invalid action 0x%08x\n", action); - return false; - } - } - - return true; -out: - dev_err(rtl_fw->dev, "Out of range of firmware\n"); - return false; -} - -void rtl8168_fw_write_firmware(struct rtl8168_private *tp, struct rtl8168_fw *rtl_fw) -{ - struct rtl8168_fw_phy_action *pa = &rtl_fw->phy_action; - rtl8168_fw_write_t fw_write = rtl_fw->phy_write; - rtl8168_fw_read_t fw_read = rtl_fw->phy_read; - int predata = 0, count = 0; - size_t index; - - for (index = 0; index < pa->size; index++) { - u32 action = le32_to_cpu(pa->code[index]); - u32 data = action & 0x0000ffff; - u32 regno = (action & 0x0fff0000) >> 16; - enum rtl_fw_opcode opcode = action >> 28; - - if (!action) - break; - - switch (opcode) { - case PHY_READ: - predata = fw_read(tp, regno); - count++; - break; - case PHY_DATA_OR: - predata |= data; - break; - case PHY_DATA_AND: - predata &= data; - break; - case PHY_BJMPN: - index -= (regno + 1); - break; - case PHY_MDIO_CHG: - if (data) { - fw_write = rtl_fw->mac_mcu_write; - fw_read = rtl_fw->mac_mcu_read; - } else { - fw_write = rtl_fw->phy_write; - fw_read = rtl_fw->phy_read; - } - - break; - case PHY_CLEAR_READCOUNT: - count = 0; - break; - case PHY_WRITE: - fw_write(tp, regno, data); - break; - case PHY_READCOUNT_EQ_SKIP: - if (count == data) - index++; - break; - case PHY_COMP_EQ_SKIPN: - if (predata == data) - index += regno; - break; - case PHY_COMP_NEQ_SKIPN: - if (predata != data) - index += regno; - break; - case PHY_WRITE_PREVIOUS: - fw_write(tp, regno, predata); - break; - case PHY_SKIPN: - index += regno; - break; - case PHY_DELAY_MS: - mdelay(data); - break; - } - } -} - -void rtl8168_fw_release_firmware(struct rtl8168_fw *rtl_fw) -{ - release_firmware(rtl_fw->fw); -} - -int rtl8168_fw_request_firmware(struct rtl8168_fw *rtl_fw) -{ - int rc; - - rc = request_firmware(&rtl_fw->fw, rtl_fw->fw_name, rtl_fw->dev); - if (rc < 0) - goto out; - - if (!rtl8168_fw_format_ok(rtl_fw) || !rtl8168_fw_data_ok(rtl_fw)) { - release_firmware(rtl_fw->fw); - rc = -EINVAL; - goto out; - } - - return 0; -out: - dev_err(rtl_fw->dev, "Unable to load firmware %s (%d)\n", - rtl_fw->fw_name, rc); - return rc; -} diff --git a/addons/r8168/src/4.4.180/r8168_firmware.h b/addons/r8168/src/4.4.180/r8168_firmware.h deleted file mode 100644 index 563280ff..00000000 --- a/addons/r8168/src/4.4.180/r8168_firmware.h +++ /dev/null @@ -1,68 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek 2.5Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_RTL8168_FIRMWARE_H -#define _LINUX_RTL8168_FIRMWARE_H - -#include -#include - -struct rtl8168_private; -typedef void (*rtl8168_fw_write_t)(struct rtl8168_private *tp, u16 reg, u16 val); -typedef u32 (*rtl8168_fw_read_t)(struct rtl8168_private *tp, u16 reg); - -#define RTL8168_VER_SIZE 32 - -struct rtl8168_fw { - rtl8168_fw_write_t phy_write; - rtl8168_fw_read_t phy_read; - rtl8168_fw_write_t mac_mcu_write; - rtl8168_fw_read_t mac_mcu_read; - const struct firmware *fw; - const char *fw_name; - struct device *dev; - - char version[RTL8168_VER_SIZE]; - - struct rtl8168_fw_phy_action { - __le32 *code; - size_t size; - } phy_action; -}; - -int rtl8168_fw_request_firmware(struct rtl8168_fw *rtl_fw); -void rtl8168_fw_release_firmware(struct rtl8168_fw *rtl_fw); -void rtl8168_fw_write_firmware(struct rtl8168_private *tp, struct rtl8168_fw *rtl_fw); - -#endif /* _LINUX_RTL8168_FIRMWARE_H */ diff --git a/addons/r8168/src/4.4.180/r8168_n.c b/addons/r8168/src/4.4.180/r8168_n.c deleted file mode 100644 index a44352f3..00000000 --- a/addons/r8168/src/4.4.180/r8168_n.c +++ /dev/null @@ -1,28743 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -/* - * This driver is modified from r8169.c in Linux kernel 2.6.18 - */ - -/* In Linux 5.4 asm_inline was introduced, but it's not supported by clang. - * Redefine it to just asm to enable successful compilation. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) -#include -#include -#endif -#include -#include -#include -#include - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) -#if LINUX_VERSION_CODE < KERNEL_VERSION(5,4,0) -#include -#endif -#endif -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) -#include -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#define dev_printk(A,B,fmt,args...) printk(A fmt,##args) -#else -#include -#include -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,31) -#include -#endif - -#include -#include - -#include "r8168.h" -#include "r8168_asf.h" -#include "rtl_eeprom.h" -#include "rtltool.h" -#include "r8168_firmware.h" - -#ifdef ENABLE_R8168_PROCFS -#include -#include -#endif - -#define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw" -#define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw" -#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw" -#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw" -#define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw" -#define FIRMWARE_8168E_4 "rtl_nic/rtl8168e-4.fw" -#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw" -#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw" -#define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw" -#define FIRMWARE_8411_2 "rtl_nic/rtl8411-2.fw" -#define FIRMWARE_8168G_2 "rtl_nic/rtl8168g-2.fw" -#define FIRMWARE_8168G_3 "rtl_nic/rtl8168g-3.fw" -#define FIRMWARE_8168EP_1 "rtl_nic/rtl8168ep-1.fw" -#define FIRMWARE_8168EP_2 "rtl_nic/rtl8168ep-2.fw" -#define FIRMWARE_8168EP_3 "rtl_nic/rtl8168ep-3.fw" -#define FIRMWARE_8168H_1 "rtl_nic/rtl8168h-1.fw" -#define FIRMWARE_8168H_2 "rtl_nic/rtl8168h-2.fw" -#define FIRMWARE_8168FP_3 "rtl_nic/rtl8168fp-3.fw" -#define FIRMWARE_8168FP_4 "rtl_nic/rtl8168fp-4.fw" - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -static const struct { - const char *name; - const char *fw_name; -} rtl_chip_fw_infos[] = { - /* PCI-E devices. */ - [CFG_METHOD_1] = {"RTL8168B/8111", }, - [CFG_METHOD_2] = {"RTL8168B/8111", }, - [CFG_METHOD_3] = {"RTL8168B/8111", }, - [CFG_METHOD_4] = {"RTL8168C/8111C", }, - [CFG_METHOD_5] = {"RTL8168C/8111C", }, - [CFG_METHOD_6] = {"RTL8168C/8111C", }, - [CFG_METHOD_7] = {"RTL8168CP/8111CP", }, - [CFG_METHOD_8] = {"RTL8168CP/8111CP", }, - [CFG_METHOD_9] = {"RTL8168D/8111D", FIRMWARE_8168D_1}, - [CFG_METHOD_10] = {"RTL8168D/8111D", FIRMWARE_8168D_2}, - [CFG_METHOD_11] = {"RTL8168DP/8111DP", }, - [CFG_METHOD_12] = {"RTL8168DP/8111DP", }, - [CFG_METHOD_13] = {"RTL8168DP/8111DP", }, - [CFG_METHOD_14] = {"RTL8168E/8111E", FIRMWARE_8168E_1}, - [CFG_METHOD_15] = {"RTL8168E/8111E", FIRMWARE_8168E_2}, - [CFG_METHOD_16] = {"RTL8168E-VL/8111E-VL", FIRMWARE_8168E_3}, - [CFG_METHOD_17] = {"RTL8168E-VL/8111E-VL", FIRMWARE_8168E_4}, - [CFG_METHOD_18] = {"RTL8168F/8111F", FIRMWARE_8168F_1}, - [CFG_METHOD_19] = {"RTL8168F/8111F", FIRMWARE_8168F_2}, - [CFG_METHOD_20] = {"RTL8411", FIRMWARE_8411_1}, - [CFG_METHOD_21] = {"RTL8168G/8111G", FIRMWARE_8168G_2}, - [CFG_METHOD_22] = {"RTL8168G/8111G", }, - [CFG_METHOD_23] = {"RTL8168EP/8111EP", FIRMWARE_8168EP_1}, - [CFG_METHOD_24] = {"RTL8168GU/8111GU", }, - [CFG_METHOD_25] = {"RTL8168GU/8111GU", FIRMWARE_8168G_3}, - [CFG_METHOD_26] = {"8411B", FIRMWARE_8411_2}, - [CFG_METHOD_27] = {"RTL8168EP/8111EP", FIRMWARE_8168EP_2}, - [CFG_METHOD_28] = {"RTL8168EP/8111EP", FIRMWARE_8168EP_3}, - [CFG_METHOD_29] = {"RTL8168H/8111H", FIRMWARE_8168H_1}, - [CFG_METHOD_30] = {"RTL8168H/8111H", FIRMWARE_8168H_2}, - [CFG_METHOD_31] = {"RTL8168FP/8111FP", }, - [CFG_METHOD_32] = {"RTL8168FP/8111FP", FIRMWARE_8168FP_3}, - [CFG_METHOD_33] = {"RTL8168FP/8111FP", FIRMWARE_8168FP_4}, - [CFG_METHOD_DEFAULT] = {"Unknown", }, -}; - -#define _R(NAME,MAC,RCR,MASK, JumFrameSz) \ - { .name = NAME, .mcfg = MAC, .RCR_Cfg = RCR, .RxConfigMask = MASK, .jumbo_frame_sz = JumFrameSz } - -static const struct { - const char *name; - u8 mcfg; - u32 RCR_Cfg; - u32 RxConfigMask; /* Clears the bits supported by this chip */ - u32 jumbo_frame_sz; -} rtl_chip_info[] = { - _R("RTL8168B/8111B", - CFG_METHOD_1, - (Reserved2_data << Reserved2_shift) | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_4k), - - _R("RTL8168B/8111B", - CFG_METHOD_2, - (Reserved2_data << Reserved2_shift) | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_4k), - - _R("RTL8168B/8111B", - CFG_METHOD_3, - (Reserved2_data << Reserved2_shift) | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_4k), - - _R("RTL8168C/8111C", - CFG_METHOD_4, - RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_6k), - - _R("RTL8168C/8111C", - CFG_METHOD_5, - RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_6k), - - _R("RTL8168C/8111C", - CFG_METHOD_6, - RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_6k), - - _R("RTL8168CP/8111CP", - CFG_METHOD_7, - RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_6k), - - _R("RTL8168CP/8111CP", - CFG_METHOD_8, - RxCfg_128_int_en | RxCfg_fet_multi_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_6k), - - _R("RTL8168D/8111D", - CFG_METHOD_9, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168D/8111D", - CFG_METHOD_10, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168DP/8111DP", - CFG_METHOD_11, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168DP/8111DP", - CFG_METHOD_12, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168DP/8111DP", - CFG_METHOD_13, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168E/8111E", - CFG_METHOD_14, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168E/8111E", - CFG_METHOD_15, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168E-VL/8111E-VL", - CFG_METHOD_16, - RxCfg_128_int_en | RxEarly_off_V1 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e0080, - Jumbo_Frame_9k), - - _R("RTL8168E-VL/8111E-VL", - CFG_METHOD_17, - RxCfg_128_int_en | RxEarly_off_V1 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168F/8111F", - CFG_METHOD_18, - RxCfg_128_int_en | RxEarly_off_V1 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168F/8111F", - CFG_METHOD_19, - RxCfg_128_int_en | RxEarly_off_V1 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8411", - CFG_METHOD_20, - RxCfg_128_int_en | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e1880, - Jumbo_Frame_9k), - - _R("RTL8168G/8111G", - CFG_METHOD_21, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168G/8111G", - CFG_METHOD_22, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168EP/8111EP", - CFG_METHOD_23, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168GU/8111GU", - CFG_METHOD_24, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168GU/8111GU", - CFG_METHOD_25, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("8411B", - CFG_METHOD_26, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168EP/8111EP", - CFG_METHOD_27, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168EP/8111EP", - CFG_METHOD_28, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168H/8111H", - CFG_METHOD_29, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168H/8111H", - CFG_METHOD_30, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168FP/8111FP", - CFG_METHOD_31, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168FP/8111FP", - CFG_METHOD_32, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("RTL8168FP/8111FP", - CFG_METHOD_33, - RxCfg_128_int_en | RxEarly_off_V2 | Rx_Single_fetch_V2 | (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_9k), - - _R("Unknown", - CFG_METHOD_DEFAULT, - (RX_DMA_BURST << RxCfgDMAShift), - 0xff7e5880, - Jumbo_Frame_1k) -}; -#undef _R - -#ifndef PCI_VENDOR_ID_DLINK -#define PCI_VENDOR_ID_DLINK 0x1186 -#endif - -static struct pci_device_id rtl8168_pci_tbl[] = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8161), }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x2502), }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x2600), }, - { PCI_VENDOR_ID_DLINK, 0x4300, 0x1186, 0x4b10,}, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8168_pci_tbl); - -static int rx_copybreak = 0; -static int use_dac = 1; -static int timer_count = 0x2600; -static int dynamic_aspm_packet_threshold = 10; - -static struct { - u32 msg_enable; -} debug = { -1 }; - -static unsigned int speed_mode = SPEED_1000; -static unsigned int duplex_mode = DUPLEX_FULL; -static unsigned int autoneg_mode = AUTONEG_ENABLE; -static unsigned int advertising_mode = ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full; -#ifdef CONFIG_ASPM -static int aspm = 1; -#else -static int aspm = 0; -#endif -#ifdef CONFIG_DYNAMIC_ASPM -static int dynamic_aspm = 1; -#else -static int dynamic_aspm = 0; -#endif -#ifdef ENABLE_S5WOL -static int s5wol = 1; -#else -static int s5wol = 0; -#endif -#ifdef ENABLE_S5_KEEP_CURR_MAC -static int s5_keep_curr_mac = 1; -#else -static int s5_keep_curr_mac = 0; -#endif -#ifdef ENABLE_EEE -static int eee_enable = 1; -#else -static int eee_enable = 0; -#endif -#ifdef CONFIG_SOC_LAN -static ulong hwoptimize = HW_PATCH_SOC_LAN; -#else -static ulong hwoptimize = 0; -#endif -#ifdef ENABLE_S0_MAGIC_PACKET -static int s0_magic_packet = 1; -#else -static int s0_magic_packet = 0; -#endif - -MODULE_AUTHOR("Realtek and the Linux r8168 crew "); -MODULE_DESCRIPTION("RealTek RTL-8168 Gigabit Ethernet driver"); - -module_param(speed_mode, uint, 0); -MODULE_PARM_DESC(speed_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(duplex_mode, uint, 0); -MODULE_PARM_DESC(duplex_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(autoneg_mode, uint, 0); -MODULE_PARM_DESC(autoneg_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(advertising_mode, uint, 0); -MODULE_PARM_DESC(advertising_mode, "force phy operation. Deprecated by ethtool (8)."); - -module_param(aspm, int, 0); -MODULE_PARM_DESC(aspm, "Enable ASPM."); - -module_param(dynamic_aspm, int, 0); -MODULE_PARM_DESC(aspm, "Enable Software Dynamic ASPM."); - -module_param(s5wol, int, 0); -MODULE_PARM_DESC(s5wol, "Enable Shutdown Wake On Lan."); - -module_param(s5_keep_curr_mac, int, 0); -MODULE_PARM_DESC(s5_keep_curr_mac, "Enable Shutdown Keep Current MAC Address."); - -module_param(rx_copybreak, int, 0); -MODULE_PARM_DESC(rx_copybreak, "Copy breakpoint for copy-only-tiny-frames"); - -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); - -module_param(timer_count, int, 0); -MODULE_PARM_DESC(timer_count, "Timer Interrupt Interval."); - -module_param(eee_enable, int, 0); -MODULE_PARM_DESC(eee_enable, "Enable Energy Efficient Ethernet."); - -module_param(hwoptimize, ulong, 0); -MODULE_PARM_DESC(hwoptimize, "Enable HW optimization function."); - -module_param(s0_magic_packet, int, 0); -MODULE_PARM_DESC(s0_magic_packet, "Enable S0 Magic Packet."); - -module_param(dynamic_aspm_packet_threshold, int, 0); -MODULE_PARM_DESC(dynamic_aspm_packet_threshold, "Dynamic ASPM packet threshold."); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -#endif//LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - -MODULE_LICENSE("GPL"); -#ifdef ENABLE_USE_FIRMWARE_FILE -MODULE_FIRMWARE(FIRMWARE_8168D_1); -MODULE_FIRMWARE(FIRMWARE_8168D_2); -MODULE_FIRMWARE(FIRMWARE_8168E_1); -MODULE_FIRMWARE(FIRMWARE_8168E_2); -MODULE_FIRMWARE(FIRMWARE_8168E_3); -MODULE_FIRMWARE(FIRMWARE_8168E_4); -MODULE_FIRMWARE(FIRMWARE_8168F_1); -MODULE_FIRMWARE(FIRMWARE_8168F_2); -MODULE_FIRMWARE(FIRMWARE_8411_1); -MODULE_FIRMWARE(FIRMWARE_8411_2); -MODULE_FIRMWARE(FIRMWARE_8168G_2); -MODULE_FIRMWARE(FIRMWARE_8168G_3); -MODULE_FIRMWARE(FIRMWARE_8168EP_1); -MODULE_FIRMWARE(FIRMWARE_8168EP_2); -MODULE_FIRMWARE(FIRMWARE_8168EP_3); -MODULE_FIRMWARE(FIRMWARE_8168H_1); -MODULE_FIRMWARE(FIRMWARE_8168H_2); -MODULE_FIRMWARE(FIRMWARE_8168FP_3); -MODULE_FIRMWARE(FIRMWARE_8168FP_4); -#endif - -MODULE_VERSION(RTL8168_VERSION); - -static void rtl8168_sleep_rx_enable(struct net_device *dev); -static void rtl8168_dsm(struct net_device *dev, int dev_state); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -static void rtl8168_esd_timer(unsigned long __opaque); -#else -static void rtl8168_esd_timer(struct timer_list *t); -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -static void rtl8168_link_timer(unsigned long __opaque); -#else -static void rtl8168_link_timer(struct timer_list *t); -#endif -static void rtl8168_tx_clear(struct rtl8168_private *tp); -static void rtl8168_rx_clear(struct rtl8168_private *tp); - -static int rtl8168_open(struct net_device *dev); -static netdev_tx_t rtl8168_start_xmit(struct sk_buff *skb, struct net_device *dev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8168_interrupt(int irq, void *dev_instance, struct pt_regs *regs); -#else -static irqreturn_t rtl8168_interrupt(int irq, void *dev_instance); -#endif -static void rtl8168_rx_desc_offset0_init(struct rtl8168_private *, int); -static int rtl8168_init_ring(struct net_device *dev); -static void rtl8168_hw_config(struct net_device *dev); -static void rtl8168_hw_start(struct net_device *dev); -static int rtl8168_close(struct net_device *dev); -static void rtl8168_set_rx_mode(struct net_device *dev); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static void rtl8168_tx_timeout(struct net_device *dev, unsigned int txqueue); -#else -static void rtl8168_tx_timeout(struct net_device *dev); -#endif -static struct net_device_stats *rtl8168_get_stats(struct net_device *dev); -static int rtl8168_rx_interrupt(struct net_device *, struct rtl8168_private *, napi_budget); -static int rtl8168_change_mtu(struct net_device *dev, int new_mtu); -static void rtl8168_down(struct net_device *dev); - -static int rtl8168_set_mac_address(struct net_device *dev, void *p); -void rtl8168_rar_set(struct rtl8168_private *tp, uint8_t *addr); -static void rtl8168_desc_addr_fill(struct rtl8168_private *); -static void rtl8168_tx_desc_init(struct rtl8168_private *tp); -static void rtl8168_rx_desc_init(struct rtl8168_private *tp); - -static u16 rtl8168_get_hw_phy_mcu_code_ver(struct rtl8168_private *tp); - -static void rtl8168_hw_reset(struct net_device *dev); - -static void rtl8168_phy_power_up(struct net_device *dev); -static void rtl8168_phy_power_down(struct net_device *dev); -static int rtl8168_set_speed(struct net_device *dev, u8 autoneg, u32 speed, u8 duplex, u32 adv); - -static int rtl8168_set_phy_mcu_patch_request(struct rtl8168_private *tp); -static int rtl8168_clear_phy_mcu_patch_request(struct rtl8168_private *tp); - -#ifdef CONFIG_R8168_NAPI -static int rtl8168_poll(napi_ptr napi, napi_budget budget); -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8168_reset_task(void *_data); -#else -static void rtl8168_reset_task(struct work_struct *work); -#endif - -static inline struct device *tp_to_dev(struct rtl8168_private *tp) -{ - return &tp->pci_dev->dev; -} - -#if ((LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) && \ - LINUX_VERSION_CODE >= KERNEL_VERSION(4,6,00))) -void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, - u32 legacy_u32) -{ - bitmap_zero(dst, __ETHTOOL_LINK_MODE_MASK_NBITS); - dst[0] = legacy_u32; -} - -bool ethtool_convert_link_mode_to_legacy_u32(u32 *legacy_u32, - const unsigned long *src) -{ - bool retval = true; - - /* TODO: following test will soon always be true */ - if (__ETHTOOL_LINK_MODE_MASK_NBITS > 32) { - __ETHTOOL_DECLARE_LINK_MODE_MASK(ext); - - bitmap_zero(ext, __ETHTOOL_LINK_MODE_MASK_NBITS); - bitmap_fill(ext, 32); - bitmap_complement(ext, ext, __ETHTOOL_LINK_MODE_MASK_NBITS); - if (bitmap_intersects(ext, src, - __ETHTOOL_LINK_MODE_MASK_NBITS)) { - /* src mask goes beyond bit 31 */ - retval = false; - } - } - *legacy_u32 = src[0]; - return retval; -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - -#ifndef LPA_1000FULL -#define LPA_1000FULL 0x0800 -#endif - -#ifndef LPA_1000HALF -#define LPA_1000HALF 0x0400 -#endif - -static inline u32 mii_adv_to_ethtool_adv_t(u32 adv) -{ - u32 result = 0; - - if (adv & ADVERTISE_10HALF) - result |= ADVERTISED_10baseT_Half; - if (adv & ADVERTISE_10FULL) - result |= ADVERTISED_10baseT_Full; - if (adv & ADVERTISE_100HALF) - result |= ADVERTISED_100baseT_Half; - if (adv & ADVERTISE_100FULL) - result |= ADVERTISED_100baseT_Full; - if (adv & ADVERTISE_PAUSE_CAP) - result |= ADVERTISED_Pause; - if (adv & ADVERTISE_PAUSE_ASYM) - result |= ADVERTISED_Asym_Pause; - - return result; -} - -static inline u32 mii_lpa_to_ethtool_lpa_t(u32 lpa) -{ - u32 result = 0; - - if (lpa & LPA_LPACK) - result |= ADVERTISED_Autoneg; - - return result | mii_adv_to_ethtool_adv_t(lpa); -} - -static inline u32 mii_stat1000_to_ethtool_lpa_t(u32 lpa) -{ - u32 result = 0; - - if (lpa & LPA_1000HALF) - result |= ADVERTISED_1000baseT_Half; - if (lpa & LPA_1000FULL) - result |= ADVERTISED_1000baseT_Full; - - return result; -} - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,4,0) -static inline void eth_hw_addr_random(struct net_device *dev) -{ - random_ether_addr(dev->dev_addr); -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) -#undef ethtool_ops -#define ethtool_ops _kc_ethtool_ops - -struct _kc_ethtool_ops { - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - int (*set_settings)(struct net_device *, struct ethtool_cmd *); - void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *); - int (*get_regs_len)(struct net_device *); - void (*get_regs)(struct net_device *, struct ethtool_regs *, void *); - void (*get_wol)(struct net_device *, struct ethtool_wolinfo *); - int (*set_wol)(struct net_device *, struct ethtool_wolinfo *); - u32 (*get_msglevel)(struct net_device *); - void (*set_msglevel)(struct net_device *, u32); - int (*nway_reset)(struct net_device *); - u32 (*get_link)(struct net_device *); - int (*get_eeprom_len)(struct net_device *); - int (*get_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); - int (*set_eeprom)(struct net_device *, struct ethtool_eeprom *, u8 *); - int (*get_coalesce)(struct net_device *, struct ethtool_coalesce *); - int (*set_coalesce)(struct net_device *, struct ethtool_coalesce *); - void (*get_ringparam)(struct net_device *, struct ethtool_ringparam *); - int (*set_ringparam)(struct net_device *, struct ethtool_ringparam *); - void (*get_pauseparam)(struct net_device *, - struct ethtool_pauseparam*); - int (*set_pauseparam)(struct net_device *, - struct ethtool_pauseparam*); - u32 (*get_rx_csum)(struct net_device *); - int (*set_rx_csum)(struct net_device *, u32); - u32 (*get_tx_csum)(struct net_device *); - int (*set_tx_csum)(struct net_device *, u32); - u32 (*get_sg)(struct net_device *); - int (*set_sg)(struct net_device *, u32); - u32 (*get_tso)(struct net_device *); - int (*set_tso)(struct net_device *, u32); - int (*self_test_count)(struct net_device *); - void (*self_test)(struct net_device *, struct ethtool_test *, u64 *); - void (*get_strings)(struct net_device *, u32 stringset, u8 *); - int (*phys_id)(struct net_device *, u32); - int (*get_stats_count)(struct net_device *); - void (*get_ethtool_stats)(struct net_device *, struct ethtool_stats *, - u64 *); -} *ethtool_ops = NULL; - -#undef SET_ETHTOOL_OPS -#define SET_ETHTOOL_OPS(netdev, ops) (ethtool_ops = (ops)) - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) -#ifndef SET_ETHTOOL_OPS -#define SET_ETHTOOL_OPS(netdev,ops) \ - ( (netdev)->ethtool_ops = (ops) ) -#endif //SET_ETHTOOL_OPS -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,16,0) - -//#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) -#ifndef netif_msg_init -#define netif_msg_init _kc_netif_msg_init -/* copied from linux kernel 2.6.20 include/linux/netdevice.h */ -static inline u32 netif_msg_init(int debug_value, int default_msg_enable_bits) -{ - /* use default */ - if (debug_value < 0 || debug_value >= (sizeof(u32) * 8)) - return default_msg_enable_bits; - if (debug_value == 0) /* no output */ - return 0; - /* set low N bits */ - return (1 << debug_value) - 1; -} - -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,5) - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) -static inline void eth_copy_and_sum (struct sk_buff *dest, - const unsigned char *src, - int len, int base) -{ - memcpy (dest->data, src, len); -} -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) -/* copied from linux kernel 2.6.20 /include/linux/time.h */ -/* Parameters used to convert the timespec values: */ -#define MSEC_PER_SEC 1000L - -/* copied from linux kernel 2.6.20 /include/linux/jiffies.h */ -/* - * Change timeval to jiffies, trying to avoid the - * most obvious overflows.. - * - * And some not so obvious. - * - * Note that we don't want to return MAX_LONG, because - * for various timeout reasons we often end up having - * to wait "jiffies+1" in order to guarantee that we wait - * at _least_ "jiffies" - so "jiffies+1" had better still - * be positive. - */ -#define MAX_JIFFY_OFFSET ((~0UL >> 1)-1) - -/* - * Convert jiffies to milliseconds and back. - * - * Avoid unnecessary multiplications/divisions in the - * two most common HZ cases: - */ -static inline unsigned int _kc_jiffies_to_msecs(const unsigned long j) -{ -#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) - return (MSEC_PER_SEC / HZ) * j; -#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) - return (j + (HZ / MSEC_PER_SEC) - 1)/(HZ / MSEC_PER_SEC); -#else - return (j * MSEC_PER_SEC) / HZ; -#endif -} - -static inline unsigned long _kc_msecs_to_jiffies(const unsigned int m) -{ - if (m > _kc_jiffies_to_msecs(MAX_JIFFY_OFFSET)) - return MAX_JIFFY_OFFSET; -#if HZ <= MSEC_PER_SEC && !(MSEC_PER_SEC % HZ) - return (m + (MSEC_PER_SEC / HZ) - 1) / (MSEC_PER_SEC / HZ); -#elif HZ > MSEC_PER_SEC && !(HZ % MSEC_PER_SEC) - return m * (HZ / MSEC_PER_SEC); -#else - return (m * HZ + MSEC_PER_SEC - 1) / MSEC_PER_SEC; -#endif -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) - - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) - -/* copied from linux kernel 2.6.12.6 /include/linux/pm.h */ -typedef int __bitwise pci_power_t; - -/* copied from linux kernel 2.6.12.6 /include/linux/pci.h */ -typedef u32 __bitwise pm_message_t; - -#define PCI_D0 ((pci_power_t __force) 0) -#define PCI_D1 ((pci_power_t __force) 1) -#define PCI_D2 ((pci_power_t __force) 2) -#define PCI_D3hot ((pci_power_t __force) 3) -#define PCI_D3cold ((pci_power_t __force) 4) -#define PCI_POWER_ERROR ((pci_power_t __force) -1) - -/* copied from linux kernel 2.6.12.6 /drivers/pci/pci.c */ -/** - * pci_choose_state - Choose the power state of a PCI device - * @dev: PCI device to be suspended - * @state: target sleep state for the whole system. This is the value - * that is passed to suspend() function. - * - * Returns PCI power state suitable for given device and given system - * message. - */ - -pci_power_t pci_choose_state(struct pci_dev *dev, pm_message_t state) -{ - if (!pci_find_capability(dev, PCI_CAP_ID_PM)) - return PCI_D0; - - switch (state) { - case 0: - return PCI_D0; - case 3: - return PCI_D3hot; - default: - printk("They asked me for state %d\n", state); -// BUG(); - } - return PCI_D0; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) -/** - * msleep_interruptible - sleep waiting for waitqueue interruptions - * @msecs: Time in milliseconds to sleep for - */ -#define msleep_interruptible _kc_msleep_interruptible -unsigned long _kc_msleep_interruptible(unsigned int msecs) -{ - unsigned long timeout = _kc_msecs_to_jiffies(msecs); - - while (timeout && !signal_pending(current)) { - set_current_state(TASK_INTERRUPTIBLE); - timeout = schedule_timeout(timeout); - } - return _kc_jiffies_to_msecs(timeout); -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,9) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) -/* copied from linux kernel 2.6.20 include/linux/sched.h */ -#ifndef __sched -#define __sched __attribute__((__section__(".sched.text"))) -#endif - -/* copied from linux kernel 2.6.20 kernel/timer.c */ -signed long __sched schedule_timeout_uninterruptible(signed long timeout) -{ - __set_current_state(TASK_UNINTERRUPTIBLE); - return schedule_timeout(timeout); -} - -/* copied from linux kernel 2.6.20 include/linux/mii.h */ -#undef if_mii -#define if_mii _kc_if_mii -static inline struct mii_ioctl_data *if_mii(struct ifreq *rq) -{ - return (struct mii_ioctl_data *) &rq->ifr_ifru; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,7) - -struct rtl8168_counters { - u64 tx_packets; - u64 rx_packets; - u64 tx_errors; - u32 rx_errors; - u16 rx_missed; - u16 align_errors; - u32 tx_one_collision; - u32 tx_multi_collision; - u64 rx_unicast; - u64 rx_broadcast; - u32 rx_multicast; - u16 tx_aborted; - u16 tx_underrun; -}; - -#ifdef ENABLE_R8168_PROCFS -/**************************************************************************** -* -----------------------------PROCFS STUFF------------------------- -***************************************************************************** -*/ - -static struct proc_dir_entry *rtl8168_proc; -static int proc_init_num = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -static int proc_get_driver_variable(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - seq_puts(m, "\nDump Driver Variable\n"); - - spin_lock_irqsave(&tp->lock, flags); - seq_puts(m, "Variable\tValue\n----------\t-----\n"); - seq_printf(m, "MODULENAME\t%s\n", MODULENAME); - seq_printf(m, "driver version\t%s\n", RTL8168_VERSION); - seq_printf(m, "chipset\t%d\n", tp->chipset); - seq_printf(m, "chipset_name\t%s\n", rtl_chip_info[tp->chipset].name); - seq_printf(m, "mtu\t%d\n", dev->mtu); - seq_printf(m, "NUM_RX_DESC\t0x%x\n", NUM_RX_DESC); - seq_printf(m, "cur_rx\t0x%x\n", tp->cur_rx); - seq_printf(m, "dirty_rx\t0x%x\n", tp->dirty_rx); - seq_printf(m, "NUM_TX_DESC\t0x%x\n", NUM_TX_DESC); - seq_printf(m, "cur_tx\t0x%x\n", tp->cur_tx); - seq_printf(m, "dirty_tx\t0x%x\n", tp->dirty_tx); - seq_printf(m, "rx_buf_sz\t0x%x\n", tp->rx_buf_sz); - seq_printf(m, "esd_flag\t0x%x\n", tp->esd_flag); - seq_printf(m, "pci_cfg_is_read\t0x%x\n", tp->pci_cfg_is_read); - seq_printf(m, "rtl8168_rx_config\t0x%x\n", tp->rtl8168_rx_config); - seq_printf(m, "cp_cmd\t0x%x\n", tp->cp_cmd); - seq_printf(m, "intr_mask\t0x%x\n", tp->intr_mask); - seq_printf(m, "timer_intr_mask\t0x%x\n", tp->timer_intr_mask); - seq_printf(m, "wol_enabled\t0x%x\n", tp->wol_enabled); - seq_printf(m, "wol_opts\t0x%x\n", tp->wol_opts); - seq_printf(m, "efuse_ver\t0x%x\n", tp->efuse_ver); - seq_printf(m, "eeprom_type\t0x%x\n", tp->eeprom_type); - seq_printf(m, "autoneg\t0x%x\n", tp->autoneg); - seq_printf(m, "duplex\t0x%x\n", tp->duplex); - seq_printf(m, "speed\t%d\n", tp->speed); - seq_printf(m, "advertising\t0x%x\n", tp->advertising); - seq_printf(m, "eeprom_len\t0x%x\n", tp->eeprom_len); - seq_printf(m, "cur_page\t0x%x\n", tp->cur_page); - seq_printf(m, "bios_setting\t0x%x\n", tp->bios_setting); - seq_printf(m, "features\t0x%x\n", tp->features); - seq_printf(m, "org_pci_offset_99\t0x%x\n", tp->org_pci_offset_99); - seq_printf(m, "org_pci_offset_180\t0x%x\n", tp->org_pci_offset_180); - seq_printf(m, "issue_offset_99_event\t0x%x\n", tp->issue_offset_99_event); - seq_printf(m, "org_pci_offset_80\t0x%x\n", tp->org_pci_offset_80); - seq_printf(m, "org_pci_offset_81\t0x%x\n", tp->org_pci_offset_81); - seq_printf(m, "use_timer_interrrupt\t0x%x\n", tp->use_timer_interrrupt); - seq_printf(m, "HwIcVerUnknown\t0x%x\n", tp->HwIcVerUnknown); - seq_printf(m, "NotWrRamCodeToMicroP\t0x%x\n", tp->NotWrRamCodeToMicroP); - seq_printf(m, "NotWrMcuPatchCode\t0x%x\n", tp->NotWrMcuPatchCode); - seq_printf(m, "HwHasWrRamCodeToMicroP\t0x%x\n", tp->HwHasWrRamCodeToMicroP); - seq_printf(m, "sw_ram_code_ver\t0x%x\n", tp->sw_ram_code_ver); - seq_printf(m, "hw_ram_code_ver\t0x%x\n", tp->hw_ram_code_ver); - seq_printf(m, "rtk_enable_diag\t0x%x\n", tp->rtk_enable_diag); - seq_printf(m, "ShortPacketSwChecksum\t0x%x\n", tp->ShortPacketSwChecksum); - seq_printf(m, "UseSwPaddingShortPkt\t0x%x\n", tp->UseSwPaddingShortPkt); - seq_printf(m, "RequireAdcBiasPatch\t0x%x\n", tp->RequireAdcBiasPatch); - seq_printf(m, "AdcBiasPatchIoffset\t0x%x\n", tp->AdcBiasPatchIoffset); - seq_printf(m, "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n", tp->RequireAdjustUpsTxLinkPulseTiming); - seq_printf(m, "SwrCnt1msIni\t0x%x\n", tp->SwrCnt1msIni); - seq_printf(m, "HwSuppNowIsOobVer\t0x%x\n", tp->HwSuppNowIsOobVer); - seq_printf(m, "HwFiberModeVer\t0x%x\n", tp->HwFiberModeVer); - seq_printf(m, "HwFiberStat\t0x%x\n", tp->HwFiberStat); - seq_printf(m, "HwSwitchMdiToFiber\t0x%x\n", tp->HwSwitchMdiToFiber); - seq_printf(m, "HwSuppSerDesPhyVer\t0x%x\n", tp->HwSuppSerDesPhyVer); - seq_printf(m, "NicCustLedValue\t0x%x\n", tp->NicCustLedValue); - seq_printf(m, "RequiredSecLanDonglePatch\t0x%x\n", tp->RequiredSecLanDonglePatch); - seq_printf(m, "HwSuppDashVer\t0x%x\n", tp->HwSuppDashVer); - seq_printf(m, "DASH\t0x%x\n", tp->DASH); - seq_printf(m, "dash_printer_enabled\t0x%x\n", tp->dash_printer_enabled); - seq_printf(m, "HwSuppKCPOffloadVer\t0x%x\n", tp->HwSuppKCPOffloadVer); - seq_printf(m, "speed_mode\t0x%x\n", speed_mode); - seq_printf(m, "duplex_mode\t0x%x\n", duplex_mode); - seq_printf(m, "autoneg_mode\t0x%x\n", autoneg_mode); - seq_printf(m, "advertising_mode\t0x%x\n", advertising_mode); - seq_printf(m, "aspm\t0x%x\n", aspm); - seq_printf(m, "s5wol\t0x%x\n", s5wol); - seq_printf(m, "s5_keep_curr_mac\t0x%x\n", s5_keep_curr_mac); - seq_printf(m, "eee_enable\t0x%x\n", tp->eee_enabled); - seq_printf(m, "hwoptimize\t0x%lx\n", hwoptimize); - seq_printf(m, "proc_init_num\t0x%x\n", proc_init_num); - seq_printf(m, "s0_magic_packet\t0x%x\n", s0_magic_packet); - seq_printf(m, "HwSuppMagicPktVer\t0x%x\n", tp->HwSuppMagicPktVer); - seq_printf(m, "HwSuppUpsVer\t0x%x\n", tp->HwSuppUpsVer); - seq_printf(m, "HwSuppEsdVer\t0x%x\n", tp->HwSuppEsdVer); - seq_printf(m, "HwSuppCheckPhyDisableModeVer\t0x%x\n", tp->HwSuppCheckPhyDisableModeVer); - seq_printf(m, "HwPkgDet\t0x%x\n", tp->HwPkgDet); - seq_printf(m, "random_mac\t0x%x\n", tp->random_mac); - seq_printf(m, "org_mac_addr\t%pM\n", tp->org_mac_addr); -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - seq_printf(m, "perm_addr\t%pM\n", dev->perm_addr); -#endif - seq_printf(m, "dev_addr\t%pM\n", dev->dev_addr); - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_tally_counter(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - struct rtl8168_private *tp = netdev_priv(dev); - struct rtl8168_counters *counters; - dma_addr_t paddr; - u32 cmd; - u32 WaitCnt; - unsigned long flags; - - seq_puts(m, "\nDump Tally Counter\n"); - - //ASSERT_RTNL(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) { - seq_puts(m, "\nDump Tally Counter Fail\n"); - return 0; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(tp, CounterAddrLow, cmd); - RTL_W32(tp, CounterAddrLow, cmd | CounterDump); - - WaitCnt = 0; - while (RTL_R32(tp, CounterAddrLow) & CounterDump) { - udelay(10); - - WaitCnt++; - if (WaitCnt > 20) - break; - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_puts(m, "Statistics\tValue\n----------\t-----\n"); - seq_printf(m, "tx_packets\t%lld\n", le64_to_cpu(counters->tx_packets)); - seq_printf(m, "rx_packets\t%lld\n", le64_to_cpu(counters->rx_packets)); - seq_printf(m, "tx_errors\t%lld\n", le64_to_cpu(counters->tx_errors)); - seq_printf(m, "rx_errors\t%d\n", le32_to_cpu(counters->rx_errors)); - seq_printf(m, "rx_missed\t%d\n", le16_to_cpu(counters->rx_missed)); - seq_printf(m, "align_errors\t%d\n", le16_to_cpu(counters->align_errors)); - seq_printf(m, "tx_one_collision\t%d\n", le32_to_cpu(counters->tx_one_collision)); - seq_printf(m, "tx_multi_collision\t%d\n", le32_to_cpu(counters->tx_multi_collision)); - seq_printf(m, "rx_unicast\t%lld\n", le64_to_cpu(counters->rx_unicast)); - seq_printf(m, "rx_broadcast\t%lld\n", le64_to_cpu(counters->rx_broadcast)); - seq_printf(m, "rx_multicast\t%d\n", le32_to_cpu(counters->rx_multicast)); - seq_printf(m, "tx_aborted\t%d\n", le16_to_cpu(counters->tx_aborted)); - seq_printf(m, "tx_underrun\t%d\n", le16_to_cpu(counters->tx_underrun)); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8168_MAC_REGS_SIZE; - u8 byte_rd; - struct rtl8168_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - - seq_puts(m, "\nDump MAC Registers\n"); - seq_puts(m, "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 16 && n < max; i++, n++) { - byte_rd = readb(ioaddr + n); - seq_printf(m, "%02x ", byte_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_pcie_phy(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8168_EPHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - seq_puts(m, "\nDump PCIE PHY\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8168_ephy_read(tp, n); - seq_printf(m, "%04x ", word_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_eth_phy(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8168_PHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - seq_puts(m, "\nDump Ethernet PHY\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - spin_lock_irqsave(&tp->lock, flags); - seq_puts(m, "\n####################page 0##################\n "); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8168_mdio_read(tp, n); - seq_printf(m, "%04x ", word_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_extended_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8168_ERI_REGS_SIZE; - u32 dword_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - /* RTL8168B does not support Extend GMAC */ - seq_puts(m, "\nNot Support Dump Extended Registers\n"); - return 0; - } - - seq_puts(m, "\nDump Extended Registers\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%02x:\t", n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - dword_rd = rtl8168_eri_read(tp, n, 4, ERIAR_ExGMAC); - seq_printf(m, "%08x ", dword_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} - -static int proc_get_pci_registers(struct seq_file *m, void *v) -{ - struct net_device *dev = m->private; - int i, n, max = R8168_PCI_REGS_SIZE; - u32 dword_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - seq_puts(m, "\nDump PCI Registers\n"); - seq_puts(m, "\nOffset\tValue\n------\t-----\n "); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - seq_printf(m, "\n0x%03x:\t", n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "%08x ", dword_rd); - } - } - - n = 0x110; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); - n = 0x70c; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - seq_printf(m, "\n0x%03x:\t%08x ", n, dword_rd); - - spin_unlock_irqrestore(&tp->lock, flags); - - seq_putc(m, '\n'); - return 0; -} -#else - -static int proc_get_driver_variable(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Driver Driver\n"); - - spin_lock_irqsave(&tp->lock, flags); - len += snprintf(page + len, count - len, - "Variable\tValue\n----------\t-----\n"); - - len += snprintf(page + len, count - len, - "MODULENAME\t%s\n" - "driver version\t%s\n" - "chipset\t%d\n" - "chipset_name\t%s\n" - "mtu\t%d\n" - "NUM_RX_DESC\t0x%x\n" - "cur_rx\t0x%x\n" - "dirty_rx\t0x%x\n" - "NUM_TX_DESC\t0x%x\n" - "cur_tx\t0x%x\n" - "dirty_tx\t0x%x\n" - "rx_buf_sz\t0x%x\n" - "esd_flag\t0x%x\n" - "pci_cfg_is_read\t0x%x\n" - "rtl8168_rx_config\t0x%x\n" - "cp_cmd\t0x%x\n" - "intr_mask\t0x%x\n" - "timer_intr_mask\t0x%x\n" - "wol_enabled\t0x%x\n" - "wol_opts\t0x%x\n" - "efuse_ver\t0x%x\n" - "eeprom_type\t0x%x\n" - "autoneg\t0x%x\n" - "duplex\t0x%x\n" - "speed\t%d\n" - "advertising\t0x%x\n" - "eeprom_len\t0x%x\n" - "cur_page\t0x%x\n" - "bios_setting\t0x%x\n" - "features\t0x%x\n" - "org_pci_offset_99\t0x%x\n" - "org_pci_offset_180\t0x%x\n" - "issue_offset_99_event\t0x%x\n" - "org_pci_offset_80\t0x%x\n" - "org_pci_offset_81\t0x%x\n" - "use_timer_interrrupt\t0x%x\n" - "HwIcVerUnknown\t0x%x\n" - "NotWrRamCodeToMicroP\t0x%x\n" - "NotWrMcuPatchCode\t0x%x\n" - "HwHasWrRamCodeToMicroP\t0x%x\n" - "sw_ram_code_ver\t0x%x\n" - "hw_ram_code_ver\t0x%x\n" - "rtk_enable_diag\t0x%x\n" - "ShortPacketSwChecksum\t0x%x\n" - "UseSwPaddingShortPkt\t0x%x\n" - "RequireAdcBiasPatch\t0x%x\n" - "AdcBiasPatchIoffset\t0x%x\n" - "RequireAdjustUpsTxLinkPulseTiming\t0x%x\n" - "SwrCnt1msIni\t0x%x\n" - "HwSuppNowIsOobVer\t0x%x\n" - "HwFiberModeVer\t0x%x\n" - "HwFiberStat\t0x%x\n" - "HwSwitchMdiToFiber\t0x%x\n" - "HwSuppSerDesPhyVer\t0x%x\n" - "NicCustLedValue\t0x%x\n" - "RequiredSecLanDonglePatch\t0x%x\n" - "HwSuppDashVer\t0x%x\n" - "DASH\t0x%x\n" - "dash_printer_enabled\t0x%x\n" - "HwSuppKCPOffloadVer\t0x%x\n" - "speed_mode\t0x%x\n" - "duplex_mode\t0x%x\n" - "autoneg_mode\t0x%x\n" - "advertising_mode\t0x%x\n" - "aspm\t0x%x\n" - "s5wol\t0x%x\n" - "s5_keep_curr_mac\t0x%x\n" - "eee_enable\t0x%x\n" - "hwoptimize\t0x%lx\n" - "proc_init_num\t0x%x\n" - "s0_magic_packet\t0x%x\n" - "HwSuppMagicPktVer\t0x%x\n" - "HwSuppUpsVer\t0x%x\n" - "HwSuppEsdVer\t0x%x\n" - "HwSuppCheckPhyDisableModeVer\t0x%x\n" - "HwPkgDet\t0x%x\n" - "random_mac\t0x%x\n" - "org_mac_addr\t%pM\n" -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - "perm_addr\t%pM\n" -#endif - "dev_addr\t%pM\n", - MODULENAME, - RTL8168_VERSION, - tp->chipset, - rtl_chip_info[tp->chipset].name, - dev->mtu, - NUM_RX_DESC, - tp->cur_rx, - tp->dirty_rx, - NUM_TX_DESC, - tp->cur_tx, - tp->dirty_tx, - tp->rx_buf_sz, - tp->esd_flag, - tp->pci_cfg_is_read, - tp->rtl8168_rx_config, - tp->cp_cmd, - tp->intr_mask, - tp->timer_intr_mask, - tp->wol_enabled, - tp->wol_opts, - tp->efuse_ver, - tp->eeprom_type, - tp->autoneg, - tp->duplex, - tp->speed, - tp->advertising, - tp->eeprom_len, - tp->cur_page, - tp->bios_setting, - tp->features, - tp->org_pci_offset_99, - tp->org_pci_offset_180, - tp->issue_offset_99_event, - tp->org_pci_offset_80, - tp->org_pci_offset_81, - tp->use_timer_interrrupt, - tp->HwIcVerUnknown, - tp->NotWrRamCodeToMicroP, - tp->NotWrMcuPatchCode, - tp->HwHasWrRamCodeToMicroP, - tp->sw_ram_code_ver, - tp->hw_ram_code_ver, - tp->rtk_enable_diag, - tp->ShortPacketSwChecksum, - tp->UseSwPaddingShortPkt, - tp->RequireAdcBiasPatch, - tp->AdcBiasPatchIoffset, - tp->RequireAdjustUpsTxLinkPulseTiming, - tp->SwrCnt1msIni, - tp->HwSuppNowIsOobVer, - tp->HwFiberModeVer, - tp->HwFiberStat, - tp->HwSwitchMdiToFiber, - tp->HwSuppSerDesPhyVer, - tp->NicCustLedValue, - tp->RequiredSecLanDonglePatch, - tp->HwSuppDashVer, - tp->DASH, - tp->dash_printer_enabled, - tp->HwSuppKCPOffloadVer, - speed_mode, - duplex_mode, - autoneg_mode, - advertising_mode, - aspm, - s5wol, - s5_keep_curr_mac, - tp->eee_enabled, - hwoptimize, - proc_init_num, - s0_magic_packet, - tp->HwSuppMagicPktVer, - tp->HwSuppUpsVer, - tp->HwSuppEsdVer, - tp->HwSuppCheckPhyDisableModeVer, - tp->HwPkgDet, - tp->random_mac, - tp->org_mac_addr, -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - dev->perm_addr, -#endif - dev->dev_addr - ); - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_tally_counter(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - struct rtl8168_private *tp = netdev_priv(dev); - struct rtl8168_counters *counters; - dma_addr_t paddr; - u32 cmd; - u32 WaitCnt; - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Tally Counter\n"); - - //ASSERT_RTNL(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) { - len += snprintf(page + len, count - len, - "\nDump Tally Counter Fail\n"); - goto out; - } - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(tp, CounterAddrLow, cmd); - RTL_W32(tp, CounterAddrLow, cmd | CounterDump); - - WaitCnt = 0; - while (RTL_R32(tp, CounterAddrLow) & CounterDump) { - udelay(10); - - WaitCnt++; - if (WaitCnt > 20) - break; - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, - "Statistics\tValue\n----------\t-----\n"); - - len += snprintf(page + len, count - len, - "tx_packets\t%lld\n" - "rx_packets\t%lld\n" - "tx_errors\t%lld\n" - "rx_errors\t%d\n" - "rx_missed\t%d\n" - "align_errors\t%d\n" - "tx_one_collision\t%d\n" - "tx_multi_collision\t%d\n" - "rx_unicast\t%lld\n" - "rx_broadcast\t%lld\n" - "rx_multicast\t%d\n" - "tx_aborted\t%d\n" - "tx_underrun\t%d\n", - le64_to_cpu(counters->tx_packets), - le64_to_cpu(counters->rx_packets), - le64_to_cpu(counters->tx_errors), - le32_to_cpu(counters->rx_errors), - le16_to_cpu(counters->rx_missed), - le16_to_cpu(counters->align_errors), - le32_to_cpu(counters->tx_one_collision), - le32_to_cpu(counters->tx_multi_collision), - le64_to_cpu(counters->rx_unicast), - le64_to_cpu(counters->rx_broadcast), - le32_to_cpu(counters->rx_multicast), - le16_to_cpu(counters->tx_aborted), - le16_to_cpu(counters->tx_underrun) - ); - - len += snprintf(page + len, count - len, "\n"); -out: - *eof = 1; - return len; -} - -static int proc_get_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8168_MAC_REGS_SIZE; - u8 byte_rd; - struct rtl8168_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump MAC Registers\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 16 && n < max; i++, n++) { - byte_rd = readb(ioaddr + n); - len += snprintf(page + len, count - len, - "%02x ", - byte_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_pcie_phy(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8168_EPHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump PCIE PHY\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8168_ephy_read(tp, n); - len += snprintf(page + len, count - len, - "%04x ", - word_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_eth_phy(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8168_PHY_REGS_SIZE/2; - u16 word_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump Ethernet PHY\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - len += snprintf(page + len, count - len, - "\n####################page 0##################\n"); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 8 && n < max; i++, n++) { - word_rd = rtl8168_mdio_read(tp, n); - len += snprintf(page + len, count - len, - "%04x ", - word_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} - -static int proc_get_extended_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8168_ERI_REGS_SIZE; - u32 dword_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - /* RTL8168B does not support Extend GMAC */ - len += snprintf(page + len, count - len, - "\nNot Support Dump Extended Registers\n"); - - goto out; - } - - len += snprintf(page + len, count - len, - "\nDump Extended Registers\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%02x:\t", - n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - dword_rd = rtl8168_eri_read(tp, n, 4, ERIAR_ExGMAC); - len += snprintf(page + len, count - len, - "%08x ", - dword_rd); - } - } - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); -out: - *eof = 1; - return len; -} - -static int proc_get_pci_registers(char *page, char **start, - off_t offset, int count, - int *eof, void *data) -{ - struct net_device *dev = data; - int i, n, max = R8168_PCI_REGS_SIZE; - u32 dword_rd; - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - int len = 0; - - len += snprintf(page + len, count - len, - "\nDump PCI Registers\n" - "Offset\tValue\n------\t-----\n"); - - spin_lock_irqsave(&tp->lock, flags); - for (n = 0; n < max;) { - len += snprintf(page + len, count - len, - "\n0x%03x:\t", - n); - - for (i = 0; i < 4 && n < max; i++, n+=4) { - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "%08x ", - dword_rd); - } - } - - n = 0x110; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "\n0x%03x:\t%08x ", - n, - dword_rd); - n = 0x70c; - pci_read_config_dword(tp->pci_dev, n, &dword_rd); - len += snprintf(page + len, count - len, - "\n0x%03x:\t%08x ", - n, - dword_rd); - spin_unlock_irqrestore(&tp->lock, flags); - - len += snprintf(page + len, count - len, "\n"); - - *eof = 1; - return len; -} -#endif -static void rtl8168_proc_module_init(void) -{ - //create /proc/net/r8168 -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) - rtl8168_proc = proc_mkdir(MODULENAME, init_net.proc_net); -#else - rtl8168_proc = proc_mkdir(MODULENAME, proc_net); -#endif - if (!rtl8168_proc) - dprintk("cannot create %s proc entry \n", MODULENAME); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) -/* - * seq_file wrappers for procfile show routines. - */ -static int rtl8168_proc_open(struct inode *inode, struct file *file) -{ - struct net_device *dev = proc_get_parent_data(inode); - int (*show)(struct seq_file *, void *) = PDE_DATA(inode); - - return single_open(file, show, dev); -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static const struct proc_ops rtl8168_proc_fops = { - .proc_open = rtl8168_proc_open, - .proc_read = seq_read, - .proc_lseek = seq_lseek, - .proc_release = single_release, -}; -#else -static const struct file_operations rtl8168_proc_fops = { - .open = rtl8168_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; -#endif - -#endif - -/* - * Table of proc files we need to create. - */ -struct rtl8168_proc_file { - char name[12]; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - int (*show)(struct seq_file *, void *); -#else - int (*show)(char *, char **, off_t, int, int *, void *); -#endif -}; - -static const struct rtl8168_proc_file rtl8168_proc_files[] = { - { "driver_var", &proc_get_driver_variable }, - { "tally", &proc_get_tally_counter }, - { "registers", &proc_get_registers }, - { "pcie_phy", &proc_get_pcie_phy }, - { "eth_phy", &proc_get_eth_phy }, - { "ext_regs", &proc_get_extended_registers }, - { "pci_regs", &proc_get_pci_registers }, - { "" } -}; - -static void rtl8168_proc_init(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - const struct rtl8168_proc_file *f; - struct proc_dir_entry *dir; - - if (rtl8168_proc && !tp->proc_dir) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - dir = proc_mkdir_data(dev->name, 0, rtl8168_proc, dev); - if (!dir) { - printk("Unable to initialize /proc/net/%s/%s\n", - MODULENAME, dev->name); - return; - } - - tp->proc_dir = dir; - proc_init_num++; - - for (f = rtl8168_proc_files; f->name[0]; f++) { - if (!proc_create_data(f->name, S_IFREG | S_IRUGO, dir, - &rtl8168_proc_fops, f->show)) { - printk("Unable to initialize " - "/proc/net/%s/%s/%s\n", - MODULENAME, dev->name, f->name); - return; - } - } -#else - dir = proc_mkdir(dev->name, rtl8168_proc); - if (!dir) { - printk("Unable to initialize /proc/net/%s/%s\n", - MODULENAME, dev->name); - return; - } - - tp->proc_dir = dir; - proc_init_num++; - - for (f = rtl8168_proc_files; f->name[0]; f++) { - if (!create_proc_read_entry(f->name, S_IFREG | S_IRUGO, - dir, f->show, dev)) { - printk("Unable to initialize " - "/proc/net/%s/%s/%s\n", - MODULENAME, dev->name, f->name); - return; - } - } -#endif - } -} - -static void rtl8168_proc_remove(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (tp->proc_dir) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - remove_proc_subtree(dev->name, rtl8168_proc); - proc_init_num--; - -#else - const struct rtl8168_proc_file *f; - struct rtl8168_private *tp = netdev_priv(dev); - - for (f = rtl8168_proc_files; f->name[0]; f++) - remove_proc_entry(f->name, tp->proc_dir); - - remove_proc_entry(dev->name, rtl8168_proc); - proc_init_num--; -#endif - tp->proc_dir = NULL; - } -} - -#endif //ENABLE_R8168_PROCFS - -static inline u16 map_phy_ocp_addr(u16 PageNum, u8 RegNum) -{ - u16 OcpPageNum = 0; - u8 OcpRegNum = 0; - u16 OcpPhyAddress = 0; - - if ( PageNum == 0 ) { - OcpPageNum = OCP_STD_PHY_BASE_PAGE + ( RegNum / 8 ); - OcpRegNum = 0x10 + ( RegNum % 8 ); - } else { - OcpPageNum = PageNum; - OcpRegNum = RegNum; - } - - OcpPageNum <<= 4; - - if ( OcpRegNum < 16 ) { - OcpPhyAddress = 0; - } else { - OcpRegNum -= 16; - OcpRegNum <<= 1; - - OcpPhyAddress = OcpPageNum + OcpRegNum; - } - - - return OcpPhyAddress; -} - -static void mdio_real_direct_write_phy_ocp(struct rtl8168_private *tp, - u32 RegAddr, - u32 value) -{ - u32 data32; - int i; - - if (tp->HwSuppPhyOcpVer == 0) goto out; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(RegAddr % 2); -#endif - data32 = RegAddr/2; - data32 <<= OCPR_Addr_Reg_shift; - data32 |= OCPR_Write | value; - - RTL_W32(tp, PHYOCP, data32); - for (i = 0; i < 100; i++) { - udelay(1); - - if (!(RTL_R32(tp, PHYOCP) & OCPR_Flag)) - break; - } -out: - return; -} - -static void mdio_direct_write_phy_ocp(struct rtl8168_private *tp, - u16 RegAddr, - u16 value) -{ - if (tp->rtk_enable_diag) return; - - mdio_real_direct_write_phy_ocp(tp, RegAddr, value); -} - -static void rtl8168_mdio_write_phy_ocp(struct rtl8168_private *tp, - u16 PageNum, - u32 RegAddr, - u32 value) -{ - u16 ocp_addr; - - if (tp->rtk_enable_diag) return; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - mdio_direct_write_phy_ocp(tp, ocp_addr, value); -} - -static void rtl8168_mdio_real_write_phy_ocp(struct rtl8168_private *tp, - u16 PageNum, - u32 RegAddr, - u32 value) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - mdio_real_direct_write_phy_ocp(tp, ocp_addr, value); -} - -static void mdio_real_write(struct rtl8168_private *tp, - u32 RegAddr, - u32 value) -{ - int i; - - if (RegAddr == 0x1F) { - tp->cur_page = value; - } - - if (tp->mcfg == CFG_METHOD_11) { - RTL_W32(tp, OCPDR, OCPDR_Write | - (RegAddr & OCPDR_Reg_Mask) << OCPDR_GPHY_Reg_shift | - (value & OCPDR_Data_Mask)); - RTL_W32(tp, OCPAR, OCPAR_GPHY_Write); - RTL_W32(tp, EPHY_RXER_NUM, 0); - - for (i = 0; i < 100; i++) { - mdelay(1); - if (!(RTL_R32(tp, OCPAR) & OCPAR_Flag)) - break; - } - } else { - if (tp->HwSuppPhyOcpVer > 0) { - if (RegAddr == 0x1F) { - return; - } - rtl8168_mdio_real_write_phy_ocp(tp, tp->cur_page, RegAddr, value); - } else { - if (tp->mcfg == CFG_METHOD_12 || tp->mcfg == CFG_METHOD_13) - RTL_W32(tp, 0xD0, RTL_R32(tp, 0xD0) & ~0x00020000); - - RTL_W32(tp, PHYAR, PHYAR_Write | - (RegAddr & PHYAR_Reg_Mask) << PHYAR_Reg_shift | - (value & PHYAR_Data_Mask)); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed writing to the specified MII register */ - if (!(RTL_R32(tp, PHYAR) & PHYAR_Flag)) { - udelay(20); - break; - } - } - - if (tp->mcfg == CFG_METHOD_12 || tp->mcfg == CFG_METHOD_13) - RTL_W32(tp, 0xD0, RTL_R32(tp, 0xD0) | 0x00020000); - } - } -} - -void rtl8168_mdio_write(struct rtl8168_private *tp, - u16 RegAddr, - u16 value) -{ - if (tp->rtk_enable_diag) return; - - mdio_real_write(tp, RegAddr, value); -} - -void rtl8168_mdio_prot_write(struct rtl8168_private *tp, - u32 RegAddr, - u32 value) -{ - mdio_real_write(tp, RegAddr, value); -} - -void rtl8168_mdio_prot_direct_write_phy_ocp(struct rtl8168_private *tp, - u32 RegAddr, - u32 value) -{ - mdio_real_direct_write_phy_ocp(tp, RegAddr, value); -} - -static u32 mdio_real_direct_read_phy_ocp(struct rtl8168_private *tp, - u32 RegAddr) -{ - u32 data32; - int i, value = 0; - - if (tp->HwSuppPhyOcpVer == 0) goto out; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(RegAddr % 2); -#endif - data32 = RegAddr/2; - data32 <<= OCPR_Addr_Reg_shift; - - RTL_W32(tp, PHYOCP, data32); - for (i = 0; i < 100; i++) { - udelay(1); - - if (RTL_R32(tp, PHYOCP) & OCPR_Flag) - break; - } - value = RTL_R32(tp, PHYOCP) & OCPDR_Data_Mask; - -out: - return value; -} - -static u32 mdio_direct_read_phy_ocp(struct rtl8168_private *tp, - u16 RegAddr) -{ - if (tp->rtk_enable_diag) return 0xffffffff; - - return mdio_real_direct_read_phy_ocp(tp, RegAddr); -} - -static u32 rtl8168_mdio_read_phy_ocp(struct rtl8168_private *tp, - u16 PageNum, - u32 RegAddr) -{ - u16 ocp_addr; - - if (tp->rtk_enable_diag) return 0xffffffff; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - return mdio_direct_read_phy_ocp(tp, ocp_addr); -} - -static u32 rtl8168_mdio_real_read_phy_ocp(struct rtl8168_private *tp, - u16 PageNum, - u32 RegAddr) -{ - u16 ocp_addr; - - ocp_addr = map_phy_ocp_addr(PageNum, RegAddr); - - return mdio_real_direct_read_phy_ocp(tp, ocp_addr); -} - -u32 mdio_real_read(struct rtl8168_private *tp, - u32 RegAddr) -{ - int i, value = 0; - - if (tp->mcfg==CFG_METHOD_11) { - RTL_W32(tp, OCPDR, OCPDR_Read | - (RegAddr & OCPDR_Reg_Mask) << OCPDR_GPHY_Reg_shift); - RTL_W32(tp, OCPAR, OCPAR_GPHY_Write); - RTL_W32(tp, EPHY_RXER_NUM, 0); - - for (i = 0; i < 100; i++) { - mdelay(1); - if (!(RTL_R32(tp, OCPAR) & OCPAR_Flag)) - break; - } - - mdelay(1); - RTL_W32(tp, OCPAR, OCPAR_GPHY_Read); - RTL_W32(tp, EPHY_RXER_NUM, 0); - - for (i = 0; i < 100; i++) { - mdelay(1); - if (RTL_R32(tp, OCPAR) & OCPAR_Flag) - break; - } - - value = RTL_R32(tp, OCPDR) & OCPDR_Data_Mask; - } else { - if (tp->HwSuppPhyOcpVer > 0) { - value = rtl8168_mdio_real_read_phy_ocp(tp, tp->cur_page, RegAddr); - } else { - if (tp->mcfg == CFG_METHOD_12 || tp->mcfg == CFG_METHOD_13) - RTL_W32(tp, 0xD0, RTL_R32(tp, 0xD0) & ~0x00020000); - - RTL_W32(tp, PHYAR, - PHYAR_Read | (RegAddr & PHYAR_Reg_Mask) << PHYAR_Reg_shift); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed retrieving data from the specified MII register */ - if (RTL_R32(tp, PHYAR) & PHYAR_Flag) { - value = RTL_R32(tp, PHYAR) & PHYAR_Data_Mask; - udelay(20); - break; - } - } - - if (tp->mcfg == CFG_METHOD_12 || tp->mcfg == CFG_METHOD_13) - RTL_W32(tp, 0xD0, RTL_R32(tp, 0xD0) | 0x00020000); - } - } - - return value; -} - -u32 rtl8168_mdio_read(struct rtl8168_private *tp, - u16 RegAddr) -{ - if (tp->rtk_enable_diag) return 0xffffffff; - - return mdio_real_read(tp, RegAddr); -} - -u32 rtl8168_mdio_prot_read(struct rtl8168_private *tp, - u32 RegAddr) -{ - return mdio_real_read(tp, RegAddr); -} - -u32 rtl8168_mdio_prot_direct_read_phy_ocp(struct rtl8168_private *tp, - u32 RegAddr) -{ - return mdio_real_direct_read_phy_ocp(tp, RegAddr); -} - -static void ClearAndSetEthPhyBit(struct rtl8168_private *tp, u8 addr, u16 clearmask, u16 setmask) -{ - u16 PhyRegValue; - - - PhyRegValue = rtl8168_mdio_read(tp, addr); - PhyRegValue &= ~clearmask; - PhyRegValue |= setmask; - rtl8168_mdio_write(tp, addr, PhyRegValue); -} - -void rtl8168_clear_eth_phy_bit(struct rtl8168_private *tp, u8 addr, u16 mask) -{ - ClearAndSetEthPhyBit(tp, - addr, - mask, - 0 - ); -} - -void rtl8168_set_eth_phy_bit(struct rtl8168_private *tp, u8 addr, u16 mask) -{ - ClearAndSetEthPhyBit(tp, - addr, - 0, - mask - ); -} - -void rtl8168_mac_ocp_write(struct rtl8168_private *tp, u16 reg_addr, u16 value) -{ - u32 data32; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(reg_addr % 2); -#endif - - data32 = reg_addr/2; - data32 <<= OCPR_Addr_Reg_shift; - data32 += value; - data32 |= OCPR_Write; - - RTL_W32(tp, MACOCP, data32); -} - -u16 rtl8168_mac_ocp_read(struct rtl8168_private *tp, u16 reg_addr) -{ - u32 data32; - u16 data16 = 0; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(reg_addr % 2); -#endif - - data32 = reg_addr/2; - data32 <<= OCPR_Addr_Reg_shift; - - RTL_W32(tp, MACOCP, data32); - data16 = (u16)RTL_R32(tp, MACOCP); - - return data16; -} - -#ifdef ENABLE_USE_FIRMWARE_FILE -static void mac_mcu_write(struct rtl8168_private *tp, u16 reg, u16 value) -{ - if (reg == 0x1f) { - tp->ocp_base = value << 4; - return; - } - - rtl8168_mac_ocp_write(tp, tp->ocp_base + reg, value); -} - -static u32 mac_mcu_read(struct rtl8168_private *tp, u16 reg) -{ - return rtl8168_mac_ocp_read(tp, tp->ocp_base + reg); -} -#endif - -static void -rtl8168_clear_and_set_mcu_ocp_bit( - struct rtl8168_private *tp, - u16 addr, - u16 clearmask, - u16 setmask -) -{ - u16 RegValue; - - RegValue = rtl8168_mac_ocp_read(tp, addr); - RegValue &= ~clearmask; - RegValue |= setmask; - rtl8168_mac_ocp_write(tp, addr, RegValue); -} - -/* -static void -rtl8168_clear_mcu_ocp_bit( - struct rtl8168_private *tp, - u16 addr, - u16 mask -) -{ - rtl8168_clear_and_set_mcu_ocp_bit(tp, - addr, - mask, - 0 - ); -} -*/ - -static void -rtl8168_set_mcu_ocp_bit( - struct rtl8168_private *tp, - u16 addr, - u16 mask -) -{ - rtl8168_clear_and_set_mcu_ocp_bit(tp, - addr, - 0, - mask - ); -} - -static u32 real_ocp_read(struct rtl8168_private *tp, u16 addr, u8 len) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, value2 = 0, mask; - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % 4; - addr = addr & ~0x3; - - RTL_W32(tp, OCPAR, (0x0F<<12) | (addr&0xFFF)); - - for (i = 0; i < 20; i++) { - udelay(100); - if (RTL_R32(tp, OCPAR) & OCPAR_Flag) - break; - } - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = RTL_R32(tp, OCPDR) & mask; - value2 |= (value1 >> val_shift * 8) << shift * 8; - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return value2; -} - -u32 rtl8168_ocp_read_with_oob_base_address(struct rtl8168_private *tp, u16 addr, u8 len, const u32 base_address) -{ - return rtl8168_eri_read_with_oob_base_address(tp, addr, len, ERIAR_OOB, base_address); -} - -u32 rtl8168_ocp_read(struct rtl8168_private *tp, u16 addr, u8 len) -{ - u32 value = 0; - - if (HW_DASH_SUPPORT_TYPE_2(tp)) - value = rtl8168_ocp_read_with_oob_base_address(tp, addr, len, NO_BASE_ADDRESS); - else if (HW_DASH_SUPPORT_TYPE_3(tp)) - value = rtl8168_ocp_read_with_oob_base_address(tp, addr, len, RTL8168FP_OOBMAC_BASE); - else - value = real_ocp_read(tp, addr, len); - - return value; -} - -static int real_ocp_write(struct rtl8168_private *tp, u16 addr, u8 len, u32 value) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, mask; - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % 4; - addr = addr & ~0x3; - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = rtl8168_ocp_read(tp, addr, 4) & ~mask; - value1 |= ((value << val_shift * 8) >> shift * 8); - - RTL_W32(tp, OCPDR, value1); - RTL_W32(tp, OCPAR, OCPAR_Flag | (0x0F<<12) | (addr&0xFFF)); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed ERI write */ - if (!(RTL_R32(tp, OCPAR) & OCPAR_Flag)) - break; - } - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return 0; -} - -u32 rtl8168_ocp_write_with_oob_base_address(struct rtl8168_private *tp, u16 addr, u8 len, u32 value, const u32 base_address) -{ - return rtl8168_eri_write_with_oob_base_address(tp, addr, len, value, ERIAR_OOB, base_address); -} - -void rtl8168_ocp_write(struct rtl8168_private *tp, u16 addr, u8 len, u32 value) -{ - if (HW_DASH_SUPPORT_TYPE_2(tp)) - rtl8168_ocp_write_with_oob_base_address(tp, addr, len, value, NO_BASE_ADDRESS); - else if (HW_DASH_SUPPORT_TYPE_3(tp)) - rtl8168_ocp_write_with_oob_base_address(tp, addr, len, value, RTL8168FP_OOBMAC_BASE); - else - real_ocp_write(tp, addr, len, value); -} - -void rtl8168_oob_mutex_lock(struct rtl8168_private *tp) -{ - u8 reg_16, reg_a0; - u32 wait_cnt_0, wait_Cnt_1; - u16 ocp_reg_mutex_ib; - u16 ocp_reg_mutex_oob; - u16 ocp_reg_mutex_prio; - - if (!tp->DASH) return; - - switch (tp->mcfg) { - case CFG_METHOD_11: - case CFG_METHOD_12: - ocp_reg_mutex_oob = 0x16; - ocp_reg_mutex_ib = 0x17; - ocp_reg_mutex_prio = 0x9C; - break; - case CFG_METHOD_13: - ocp_reg_mutex_oob = 0x06; - ocp_reg_mutex_ib = 0x07; - ocp_reg_mutex_prio = 0x9C; - break; - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - default: - ocp_reg_mutex_oob = 0x110; - ocp_reg_mutex_ib = 0x114; - ocp_reg_mutex_prio = 0x11C; - break; - } - - rtl8168_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); - reg_16 = rtl8168_ocp_read(tp, ocp_reg_mutex_oob, 1); - wait_cnt_0 = 0; - while(reg_16) { - reg_a0 = rtl8168_ocp_read(tp, ocp_reg_mutex_prio, 1); - if (reg_a0) { - rtl8168_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); - reg_a0 = rtl8168_ocp_read(tp, ocp_reg_mutex_prio, 1); - wait_Cnt_1 = 0; - while(reg_a0) { - reg_a0 = rtl8168_ocp_read(tp, ocp_reg_mutex_prio, 1); - - wait_Cnt_1++; - - if (wait_Cnt_1 > 2000) - break; - }; - rtl8168_ocp_write(tp, ocp_reg_mutex_ib, 1, BIT_0); - - } - reg_16 = rtl8168_ocp_read(tp, ocp_reg_mutex_oob, 1); - - wait_cnt_0++; - - if (wait_cnt_0 > 2000) - break; - }; -} - -void rtl8168_oob_mutex_unlock(struct rtl8168_private *tp) -{ - u16 ocp_reg_mutex_ib; - u16 ocp_reg_mutex_oob; - u16 ocp_reg_mutex_prio; - - if (!tp->DASH) return; - - switch (tp->mcfg) { - case CFG_METHOD_11: - case CFG_METHOD_12: - ocp_reg_mutex_oob = 0x16; - ocp_reg_mutex_ib = 0x17; - ocp_reg_mutex_prio = 0x9C; - break; - case CFG_METHOD_13: - ocp_reg_mutex_oob = 0x06; - ocp_reg_mutex_ib = 0x07; - ocp_reg_mutex_prio = 0x9C; - break; - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - default: - ocp_reg_mutex_oob = 0x110; - ocp_reg_mutex_ib = 0x114; - ocp_reg_mutex_prio = 0x11C; - break; - } - - rtl8168_ocp_write(tp, ocp_reg_mutex_prio, 1, BIT_0); - rtl8168_ocp_write(tp, ocp_reg_mutex_ib, 1, 0x00); -} - -void rtl8168_oob_notify(struct rtl8168_private *tp, u8 cmd) -{ - rtl8168_eri_write(tp, 0xE8, 1, cmd, ERIAR_ExGMAC); - - rtl8168_ocp_write(tp, 0x30, 1, 0x01); -} - -static int rtl8168_check_dash(struct rtl8168_private *tp) -{ - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - if (rtl8168_ocp_read(tp, 0x128, 1) & BIT_0) - return 1; - else - return 0; - } else { - u32 reg; - - if (tp->mcfg == CFG_METHOD_13) - reg = 0xb8; - else - reg = 0x10; - - if (rtl8168_ocp_read(tp, reg, 2) & 0x00008000) - return 1; - else - return 0; - } -} - -void rtl8168_dash2_disable_tx(struct rtl8168_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - u16 WaitCnt; - u8 TmpUchar; - - //Disable oob Tx - RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) & ~( BIT_0 )); - WaitCnt = 0; - - //wait oob tx disable - do { - TmpUchar = RTL_CMAC_R8(tp, CMAC_IBISR0); - - if ( TmpUchar & ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE ) { - break; - } - - udelay( 50 ); - WaitCnt++; - } while(WaitCnt < 2000); - - //Clear ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE - RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0) | ISRIMR_DASH_TYPE2_TX_DISABLE_IDLE); - } -} - -void rtl8168_dash2_enable_tx(struct rtl8168_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR2, RTL_CMAC_R8(tp, CMAC_IBCR2) | BIT_0); - } -} - -void rtl8168_dash2_disable_rx(struct rtl8168_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) & ~( BIT_0 )); - } -} - -void rtl8168_dash2_enable_rx(struct rtl8168_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBCR0, RTL_CMAC_R8(tp, CMAC_IBCR0) | BIT_0); - } -} - -static void rtl8168_dash2_disable_txrx(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - rtl8168_dash2_disable_tx( tp ); - rtl8168_dash2_disable_rx( tp ); - } -} - -void rtl8168_ephy_write(struct rtl8168_private *tp, int RegAddr, int value) -{ - int i; - - RTL_W32(tp, EPHYAR, - EPHYAR_Write | - (RegAddr & EPHYAR_Reg_Mask) << EPHYAR_Reg_shift | - (value & EPHYAR_Data_Mask)); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed EPHY write */ - if (!(RTL_R32(tp, EPHYAR) & EPHYAR_Flag)) - break; - } - - udelay(20); -} - -u16 rtl8168_ephy_read(struct rtl8168_private *tp, int RegAddr) -{ - int i; - u16 value = 0xffff; - - RTL_W32(tp, EPHYAR, - EPHYAR_Read | (RegAddr & EPHYAR_Reg_Mask) << EPHYAR_Reg_shift); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed EPHY read */ - if (RTL_R32(tp, EPHYAR) & EPHYAR_Flag) { - value = (u16) (RTL_R32(tp, EPHYAR) & EPHYAR_Data_Mask); - break; - } - } - - udelay(20); - - return value; -} - -static void ClearAndSetPCIePhyBit(struct rtl8168_private *tp, u8 addr, u16 clearmask, u16 setmask) -{ - u16 EphyValue; - - EphyValue = rtl8168_ephy_read(tp, addr); - EphyValue &= ~clearmask; - EphyValue |= setmask; - rtl8168_ephy_write(tp, addr, EphyValue); -} - -static void ClearPCIePhyBit(struct rtl8168_private *tp, u8 addr, u16 mask) -{ - ClearAndSetPCIePhyBit( tp, - addr, - mask, - 0 - ); -} - -static void SetPCIePhyBit( struct rtl8168_private *tp, u8 addr, u16 mask) -{ - ClearAndSetPCIePhyBit( tp, - addr, - 0, - mask - ); -} - -static u32 -rtl8168_csi_other_fun_read(struct rtl8168_private *tp, - u8 multi_fun_sel_bit, - u32 addr) -{ - u32 cmd; - int i; - u32 value = 0; - - cmd = CSIAR_Read | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); - - if (tp->mcfg != CFG_METHOD_20 && tp->mcfg != CFG_METHOD_23 && - tp->mcfg != CFG_METHOD_26 && tp->mcfg != CFG_METHOD_27 && - tp->mcfg != CFG_METHOD_28 && tp->mcfg != CFG_METHOD_31 && - tp->mcfg != CFG_METHOD_32 && tp->mcfg != CFG_METHOD_33) { - multi_fun_sel_bit = 0; - } - - if ( multi_fun_sel_bit > 7 ) { - return 0xffffffff; - } - - cmd |= multi_fun_sel_bit << 16; - - RTL_W32(tp, CSIAR, cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed CSI read */ - if (RTL_R32(tp, CSIAR) & CSIAR_Flag) { - value = (u32)RTL_R32(tp, CSIDR); - break; - } - } - - udelay(20); - - return value; -} - -static void -rtl8168_csi_other_fun_write(struct rtl8168_private *tp, - u8 multi_fun_sel_bit, - u32 addr, - u32 value) -{ - u32 cmd; - int i; - - RTL_W32(tp, CSIDR, value); - cmd = CSIAR_Write | CSIAR_ByteEn << CSIAR_ByteEn_shift | (addr & CSIAR_Addr_Mask); - if (tp->mcfg != CFG_METHOD_20 && tp->mcfg != CFG_METHOD_23 && - tp->mcfg != CFG_METHOD_26 && tp->mcfg != CFG_METHOD_27 && - tp->mcfg != CFG_METHOD_28 && tp->mcfg != CFG_METHOD_31 && - tp->mcfg != CFG_METHOD_32 && tp->mcfg != CFG_METHOD_33) { - multi_fun_sel_bit = 0; - } - - if ( multi_fun_sel_bit > 7 ) { - return; - } - - cmd |= multi_fun_sel_bit << 16; - - RTL_W32(tp, CSIAR, cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed CSI write */ - if (!(RTL_R32(tp, CSIAR) & CSIAR_Flag)) - break; - } - - udelay(20); -} - -static u32 -rtl8168_csi_read(struct rtl8168_private *tp, - u32 addr) -{ - u8 multi_fun_sel_bit; - - if (tp->mcfg == CFG_METHOD_20) - multi_fun_sel_bit = 2; - else if (tp->mcfg == CFG_METHOD_26 || tp->mcfg == CFG_METHOD_31 || - tp->mcfg == CFG_METHOD_32 || tp->mcfg == CFG_METHOD_33) - multi_fun_sel_bit = 1; - else - multi_fun_sel_bit = 0; - - return rtl8168_csi_other_fun_read(tp, multi_fun_sel_bit, addr); -} - -static void -rtl8168_csi_write(struct rtl8168_private *tp, - u32 addr, - u32 value) -{ - u8 multi_fun_sel_bit; - - if (tp->mcfg == CFG_METHOD_20) - multi_fun_sel_bit = 2; - else if (tp->mcfg == CFG_METHOD_26 || tp->mcfg == CFG_METHOD_31 || - tp->mcfg == CFG_METHOD_32 || tp->mcfg == CFG_METHOD_33) - multi_fun_sel_bit = 1; - else - multi_fun_sel_bit = 0; - - rtl8168_csi_other_fun_write(tp, multi_fun_sel_bit, addr, value); -} - -static u8 -rtl8168_csi_fun0_read_byte(struct rtl8168_private *tp, - u32 addr) -{ - u8 RetVal = 0; - - if (tp->mcfg == CFG_METHOD_20 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - u32 TmpUlong; - u16 RegAlignAddr; - u8 ShiftByte; - - RegAlignAddr = addr & ~(0x3); - ShiftByte = addr & (0x3); - TmpUlong = rtl8168_csi_other_fun_read(tp, 0, addr); - TmpUlong >>= (8*ShiftByte); - RetVal = (u8)TmpUlong; - } else { - struct pci_dev *pdev = tp->pci_dev; - - pci_read_config_byte(pdev, addr, &RetVal); - } - - udelay(20); - - return RetVal; -} - -static void -rtl8168_csi_fun0_write_byte(struct rtl8168_private *tp, - u32 addr, - u8 value) -{ - if (tp->mcfg == CFG_METHOD_20 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - u32 TmpUlong; - u16 RegAlignAddr; - u8 ShiftByte; - - RegAlignAddr = addr & ~(0x3); - ShiftByte = addr & (0x3); - TmpUlong = rtl8168_csi_other_fun_read(tp, 0, RegAlignAddr); - TmpUlong &= ~(0xFF << (8*ShiftByte)); - TmpUlong |= (value << (8*ShiftByte)); - rtl8168_csi_other_fun_write( tp, 0, RegAlignAddr, TmpUlong ); - } else { - struct pci_dev *pdev = tp->pci_dev; - - pci_write_config_byte(pdev, addr, value); - } - - udelay(20); -} - -static void -rtl8168_clear_and_set_other_fun_pci_bit(struct rtl8168_private *tp, - u8 multi_fun_sel_bit, - u32 addr, - u32 clearmask, - u32 setmask) -{ - u32 TmpUlong; - - TmpUlong = rtl8168_csi_other_fun_read(tp, multi_fun_sel_bit, addr); - TmpUlong &= ~clearmask; - TmpUlong |= setmask; - rtl8168_csi_other_fun_write(tp, multi_fun_sel_bit, addr, TmpUlong); -} - -static void -rtl8168_other_fun_dev_pci_setting(struct rtl8168_private *tp, - u32 addr, - u32 clearmask, - u32 setmask, - u8 multi_fun_sel_bit) -{ - u32 TmpUlong; - u8 i; - u8 FunBit; - - for (i = 0; i < 8; i++) { - FunBit = (1 << i); - if (FunBit & multi_fun_sel_bit) { - u8 set_other_fun = TRUE; - - switch(tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - //0: UMAC, 1: TCR1, 2: TCR2, 3: KCS, 4: EHCI(Control by EHCI Driver) - if (i < 5) { - TmpUlong = rtl8168_csi_other_fun_read(tp, i, 0x00); - if (TmpUlong == 0xFFFFFFFF) - set_other_fun = TRUE; - else - set_other_fun = FALSE; - } - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - //0: BMC, 1: NIC, 2: TCR, 3: VGA/PCIE_TO_USB, 4: EHCI, 5: WIFI, 6: WIFI, 7: KCS - if (i == 5 || i == 6) { - if (tp->DASH) { - TmpUlong = rtl8168_ocp_read(tp, 0x184, 4); - if (TmpUlong & BIT_26) - set_other_fun = FALSE; - else - set_other_fun = TRUE; - } - } else { //function 0/1/2/3/4/7 - TmpUlong = rtl8168_csi_other_fun_read(tp, i, 0x00); - if (TmpUlong == 0xFFFFFFFF) - set_other_fun = TRUE; - else - set_other_fun = FALSE; - } - break; - default: - return; - } - - if (set_other_fun) - rtl8168_clear_and_set_other_fun_pci_bit(tp, i, addr, clearmask, setmask); - } - } -} - -static void -rtl8168_set_dash_other_fun_dev_state_change(struct rtl8168_private *tp, - u8 dev_state, - u8 multi_fun_sel_bit) -{ - u32 clearmask; - u32 setmask; - - if (dev_state == 0) { - // - // goto D0 - // - clearmask = (BIT_0 | BIT_1); - setmask = 0; - - rtl8168_other_fun_dev_pci_setting(tp, 0x44, clearmask, setmask, multi_fun_sel_bit); - } else { - // - // goto D3 - // - clearmask = 0; - setmask = (BIT_0 | BIT_1); - - rtl8168_other_fun_dev_pci_setting(tp, 0x44, clearmask, setmask, multi_fun_sel_bit); - } -} - -static void -rtl8168_set_dash_other_fun_dev_aspm_clkreq(struct rtl8168_private *tp, - u8 aspm_val, - u8 clkreq_en, - u8 multi_fun_sel_bit) -{ - u32 clearmask; - u32 setmask; - - aspm_val &= (BIT_0 | BIT_1); - clearmask = (BIT_0 | BIT_1 | BIT_8); - setmask = aspm_val; - if (clkreq_en) - setmask |= BIT_8; - - rtl8168_other_fun_dev_pci_setting(tp, 0x80, clearmask, setmask, multi_fun_sel_bit); -} - -/* -static void -rtl8168_set_dash_other_fun_dev_pci_cmd_register(struct rtl8168_private *tp, - u8 pci_cmd_reg, - u8 multi_fun_sel_bit) -{ - u32 clearmask; - u32 setmask; - - pci_cmd_reg &= (BIT_0 | BIT_1 | BIT_2); - - clearmask = (BIT_0 | BIT_1 | BIT_2); - setmask = pci_cmd_reg; - - rtl8168_other_fun_dev_pci_setting(tp, 0x04, clearmask, setmask, multi_fun_sel_bit); -} -*/ - -u32 rtl8168_eri_read_with_oob_base_address(struct rtl8168_private *tp, int addr, int len, int type, const u32 base_address) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, value2 = 0, mask; - u32 eri_cmd; - const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % ERIAR_Addr_Align; - addr = addr & ~0x3; - - eri_cmd = ERIAR_Read | - transformed_base_address | - type << ERIAR_Type_shift | - ERIAR_ByteEn << ERIAR_ByteEn_shift | - (addr & 0x0FFF); - if (addr & 0xF000) { - u32 tmp; - - tmp = addr & 0xF000; - tmp >>= 12; - eri_cmd |= (tmp << 20) & 0x00F00000; - } - - RTL_W32(tp, ERIAR, eri_cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed ERI read */ - if (RTL_R32(tp, ERIAR) & ERIAR_Flag) - break; - } - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = RTL_R32(tp, ERIDR) & mask; - value2 |= (value1 >> val_shift * 8) << shift * 8; - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return value2; -} - -u32 rtl8168_eri_read(struct rtl8168_private *tp, int addr, int len, int type) -{ - return rtl8168_eri_read_with_oob_base_address(tp, addr, len, type, 0); -} - -int rtl8168_eri_write_with_oob_base_address(struct rtl8168_private *tp, int addr, int len, u32 value, int type, const u32 base_address) -{ - int i, val_shift, shift = 0; - u32 value1 = 0, mask; - u32 eri_cmd; - const u32 transformed_base_address = ((base_address & 0x00FFF000) << 6) | (base_address & 0x000FFF); - - if (len > 4 || len <= 0) - return -1; - - while (len > 0) { - val_shift = addr % ERIAR_Addr_Align; - addr = addr & ~0x3; - - if (len == 1) mask = (0xFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 2) mask = (0xFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else if (len == 3) mask = (0xFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - else mask = (0xFFFFFFFF << (val_shift * 8)) & 0xFFFFFFFF; - - value1 = rtl8168_eri_read_with_oob_base_address(tp, addr, 4, type, base_address) & ~mask; - value1 |= ((value << val_shift * 8) >> shift * 8); - - RTL_W32(tp, ERIDR, value1); - - eri_cmd = ERIAR_Write | - transformed_base_address | - type << ERIAR_Type_shift | - ERIAR_ByteEn << ERIAR_ByteEn_shift | - (addr & 0x0FFF); - if (addr & 0xF000) { - u32 tmp; - - tmp = addr & 0xF000; - tmp >>= 12; - eri_cmd |= (tmp << 20) & 0x00F00000; - } - - RTL_W32(tp, ERIAR, eri_cmd); - - for (i = 0; i < 10; i++) { - udelay(100); - - /* Check if the RTL8168 has completed ERI write */ - if (!(RTL_R32(tp, ERIAR) & ERIAR_Flag)) - break; - } - - if (len <= 4 - val_shift) { - len = 0; - } else { - len -= (4 - val_shift); - shift = 4 - val_shift; - addr += 4; - } - } - - udelay(20); - - return 0; -} - -int rtl8168_eri_write(struct rtl8168_private *tp, int addr, int len, u32 value, int type) -{ - return rtl8168_eri_write_with_oob_base_address(tp, addr, len, value, type, NO_BASE_ADDRESS); -} - -static void -rtl8168_enable_rxdvgate(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_3); - mdelay(2); - break; - } -} - -static void -rtl8168_disable_rxdvgate(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_3); - mdelay(2); - break; - } -} - -static u8 -rtl8168_is_gpio_low(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 gpio_low = FALSE; - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 1: - case 2: - if (!(rtl8168_mac_ocp_read(tp, 0xDC04) & BIT_9)) - gpio_low = TRUE; - break; - case 3: - if (!(rtl8168_mac_ocp_read(tp, 0xDC04) & BIT_13)) - gpio_low = TRUE; - break; - } - - if (gpio_low) - dprintk("gpio is low.\n"); - - return gpio_low; -} - -static u8 -rtl8168_is_phy_disable_mode_enabled(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 phy_disable_mode_enabled = FALSE; - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 1: - if (rtl8168_mac_ocp_read(tp, 0xDC20) & BIT_1) - phy_disable_mode_enabled = TRUE; - break; - case 2: - case 3: - if (RTL_R8(tp, 0xF2) & BIT_5) - phy_disable_mode_enabled = TRUE; - break; - } - - if (phy_disable_mode_enabled) - dprintk("phy disable mode enabled.\n"); - - return phy_disable_mode_enabled; -} - -static u8 -rtl8168_is_in_phy_disable_mode(struct net_device *dev) -{ - u8 in_phy_disable_mode = FALSE; - - if (rtl8168_is_phy_disable_mode_enabled(dev) && rtl8168_is_gpio_low(dev)) - in_phy_disable_mode = TRUE; - - if (in_phy_disable_mode) - dprintk("Hardware is in phy disable mode.\n"); - - return in_phy_disable_mode; -} - -void -rtl8168_wait_txrx_fifo_empty(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int i; - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - for (i = 0; i < 10; i++) { - udelay(100); - if (RTL_R32(tp, TxConfig) & BIT_11) - break; - } - - for (i = 0; i < 10; i++) { - udelay(100); - if ((RTL_R8(tp, MCUCmd_reg) & (Txfifo_empty | Rxfifo_empty)) == (Txfifo_empty | Rxfifo_empty)) - break; - } - - mdelay(1); - break; - } -} - -static void rtl8168_driver_start(struct rtl8168_private *tp) -{ - //change other device state to D0. - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - rtl8168_set_dash_other_fun_dev_aspm_clkreq(tp, 3, 1, 0x1E); - rtl8168_set_dash_other_fun_dev_state_change(tp, 3, 0x1E); - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_set_dash_other_fun_dev_aspm_clkreq(tp, 3, 1, 0xFC); - rtl8168_set_dash_other_fun_dev_state_change(tp, 3, 0xFC); - break; - } - - if (!tp->DASH) - return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - int timeout; - u32 tmp_value; - - rtl8168_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_START); - tmp_value = rtl8168_ocp_read(tp, 0x30, 1); - tmp_value |= BIT_0; - rtl8168_ocp_write(tp, 0x30, 1, tmp_value); - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if (rtl8168_ocp_read(tp, 0x124, 1) & BIT_0) - break; - } - } else { - int timeout; - u32 reg; - - if (tp->mcfg == CFG_METHOD_13) { - RTL_W8(tp, TwiCmdReg, RTL_R8(tp, TwiCmdReg) | ( BIT_7 )); - } - - rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START); - - if (tp->mcfg == CFG_METHOD_13) - reg = 0xB8; - else - reg = 0x10; - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if (rtl8168_ocp_read(tp, reg, 2) & BIT_11) - break; - } - } -} - -static void rtl8168_driver_stop(struct rtl8168_private *tp) -{ - if (!tp->DASH) - goto update_device_state; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - struct net_device *dev = tp->dev; - int timeout; - u32 tmp_value; - - rtl8168_dash2_disable_txrx(dev); - - rtl8168_ocp_write(tp, 0x180, 1, OOB_CMD_DRIVER_STOP); - tmp_value = rtl8168_ocp_read(tp, 0x30, 1); - tmp_value |= BIT_0; - rtl8168_ocp_write(tp, 0x30, 1, tmp_value); - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if (!(rtl8168_ocp_read(tp, 0x124, 1) & BIT_0)) - break; - } - } else { - int timeout; - u32 reg; - - rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP); - - if (tp->mcfg == CFG_METHOD_13) - reg = 0xB8; - else - reg = 0x10; - - for (timeout = 0; timeout < 10; timeout++) { - mdelay(10); - if ((rtl8168_ocp_read(tp, reg, 2) & BIT_11) == 0) - break; - } - - if (tp->mcfg == CFG_METHOD_13) { - RTL_W8(tp, TwiCmdReg, RTL_R8(tp, TwiCmdReg) & ~( BIT_7 )); - } - } - -update_device_state: - //change other device state to D3. - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - rtl8168_set_dash_other_fun_dev_state_change(tp, 3, 0x0E); - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_set_dash_other_fun_dev_state_change(tp, 3, 0xFD); - break; - } -} - -#ifdef ENABLE_DASH_SUPPORT - -inline void -rtl8168_enable_dash2_interrupt(struct rtl8168_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBIMR0, ( ISRIMR_DASH_TYPE2_ROK | ISRIMR_DASH_TYPE2_TOK | ISRIMR_DASH_TYPE2_TDU | ISRIMR_DASH_TYPE2_RDU | ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE )); - } -} - -static inline void -rtl8168_disable_dash2_interrupt(struct rtl8168_private *tp) -{ - if (!tp->DASH) return; - - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBIMR0, 0); - } -} -#endif - -static inline void -rtl8168_enable_hw_interrupt(struct rtl8168_private *tp) -{ - RTL_W16(tp, IntrMask, tp->intr_mask); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8168_enable_dash2_interrupt(tp); -#endif -} - -static inline void -rtl8168_disable_hw_interrupt(struct rtl8168_private *tp) -{ - RTL_W16(tp, IntrMask, 0x0000); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8168_disable_dash2_interrupt(tp); -#endif -} - - -static inline void -rtl8168_switch_to_hw_interrupt(struct rtl8168_private *tp) -{ - RTL_W32(tp, TimeInt0, 0x0000); - - rtl8168_enable_hw_interrupt(tp); -} - -static inline void -rtl8168_switch_to_timer_interrupt(struct rtl8168_private *tp) -{ - if (tp->use_timer_interrrupt) { - RTL_W32(tp, TimeInt0, timer_count); - RTL_W32(tp, TCTR, timer_count); - RTL_W16(tp, IntrMask, tp->timer_intr_mask); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - rtl8168_enable_dash2_interrupt(tp); -#endif - } else { - rtl8168_switch_to_hw_interrupt(tp); - } -} - -static void -rtl8168_irq_mask_and_ack(struct rtl8168_private *tp) -{ - rtl8168_disable_hw_interrupt(tp); -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - if (tp->dash_printer_enabled) { - RTL_W16(tp, IntrStatus, RTL_R16(tp, IntrStatus) & - ~(ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); - } else { - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - RTL_CMAC_W8(tp, CMAC_IBISR0, RTL_CMAC_R8(tp, CMAC_IBISR0)); - } - } - } else { - RTL_W16(tp, IntrStatus, RTL_R16(tp, IntrStatus)); - } -#else - RTL_W16(tp, IntrStatus, RTL_R16(tp, IntrStatus)); -#endif -} - -static void -rtl8168_nic_reset(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int i; - - RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); - - rtl8168_enable_rxdvgate(dev); - - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - mdelay(10); - break; - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - case CFG_METHOD_8: - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_14: - case CFG_METHOD_15: - RTL_W8(tp, ChipCmd, StopReq | CmdRxEnb | CmdTxEnb); - udelay(100); - break; - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - for (i = 0; i < 2000; i++) { - if (!(RTL_R8(tp, TxPoll) & NPQ)) break; - udelay(100); - } - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - mdelay(2); - break; - default: - mdelay(10); - break; - } - - rtl8168_wait_txrx_fifo_empty(dev); - - /* Soft reset the chip. */ - RTL_W8(tp, ChipCmd, CmdReset); - - /* Check that the chip has finished the reset. */ - for (i = 100; i > 0; i--) { - udelay(100); - if ((RTL_R8(tp, ChipCmd) & CmdReset) == 0) - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_11: - rtl8168_oob_mutex_lock(tp); - rtl8168_ocp_write(tp, 0x10, 2, rtl8168_ocp_read(tp, 0x010, 2)&~0x00004000); - rtl8168_oob_mutex_unlock(tp); - - rtl8168_oob_notify(tp, OOB_CMD_RESET); - - for (i = 0; i < 10; i++) { - mdelay(10); - if (rtl8168_ocp_read(tp, 0x010, 2)&0x00004000) - break; - } - - for (i = 0; i < 5; i++) { - if ( rtl8168_ocp_read(tp, 0x034, 1) == 0) - break; - } - break; - } -} - -static void -rtl8168_hw_clear_timer_int(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - RTL_W32(tp, TimeInt0, 0x0000); - - switch (tp->mcfg) { - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - case CFG_METHOD_8: - RTL_W32(tp, TimeInt1, 0x0000); - break; - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W32(tp, TimeInt1, 0x0000); - RTL_W32(tp, TimeInt2, 0x0000); - RTL_W32(tp, TimeInt3, 0x0000); - break; - } -} - -static void -rtl8168_hw_reset(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - /* Disable interrupts */ - rtl8168_irq_mask_and_ack(tp); - - rtl8168_hw_clear_timer_int(dev); - - rtl8168_nic_reset(dev); -} - -static void rtl8168_mac_loopback_test(struct rtl8168_private *tp) -{ - struct pci_dev *pdev = tp->pci_dev; - struct net_device *dev = tp->dev; - struct sk_buff *skb, *rx_skb; - dma_addr_t mapping; - struct TxDesc *txd; - struct RxDesc *rxd; - void *tmpAddr; - u32 len, rx_len, rx_cmd = 0; - u16 type; - u8 pattern; - int i; - - if (tp->DASH) - return; - - pattern = 0x5A; - len = 60; - type = htons(ETH_P_IP); - txd = tp->TxDescArray; - rxd = tp->RxDescArray; - rx_skb = tp->Rx_skbuff[0]; - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) & ~0x00060000) | 0x00020000); - - do { - skb = dev_alloc_skb(len + RTK_RX_ALIGN); - if (unlikely(!skb)) - dev_printk(KERN_NOTICE, tp_to_dev(tp), "-ENOMEM;\n"); - } while (unlikely(skb == NULL)); - skb_reserve(skb, RTK_RX_ALIGN); - - memcpy(skb_put(skb, dev->addr_len), dev->dev_addr, dev->addr_len); - memcpy(skb_put(skb, dev->addr_len), dev->dev_addr, dev->addr_len); - memcpy(skb_put(skb, sizeof(type)), &type, sizeof(type)); - tmpAddr = skb_put(skb, len - 14); - - mapping = dma_map_single(tp_to_dev(tp), skb->data, len, DMA_TO_DEVICE); - dma_sync_single_for_cpu(tp_to_dev(tp), le64_to_cpu(mapping), - len, DMA_TO_DEVICE); - txd->addr = cpu_to_le64(mapping); - txd->opts2 = 0; - while (1) { - memset(tmpAddr, pattern++, len - 14); - pci_dma_sync_single_for_device(tp->pci_dev, - le64_to_cpu(mapping), - len, DMA_TO_DEVICE); - txd->opts1 = cpu_to_le32(DescOwn | FirstFrag | LastFrag | len); - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | AcceptMyPhys); - - smp_wmb(); - RTL_W8(tp, TxPoll, NPQ); /* set polling bit */ - - for (i = 0; i < 50; i++) { - udelay(200); - rx_cmd = le32_to_cpu(rxd->opts1); - if ((rx_cmd & DescOwn) == 0) - break; - } - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(AcceptErr | AcceptRunt | AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys)); - - rx_len = rx_cmd & 0x3FFF; - rx_len -= 4; - rxd->opts1 = cpu_to_le32(DescOwn | tp->rx_buf_sz); - - dma_sync_single_for_cpu(tp_to_dev(tp), le64_to_cpu(mapping), len, DMA_TO_DEVICE); - - if (rx_len == len) { - dma_sync_single_for_cpu(tp_to_dev(tp), le64_to_cpu(rxd->addr), tp->rx_buf_sz, DMA_FROM_DEVICE); - i = memcmp(skb->data, rx_skb->data, rx_len); - pci_dma_sync_single_for_device(tp->pci_dev, le64_to_cpu(rxd->addr), tp->rx_buf_sz, DMA_FROM_DEVICE); - if (i == 0) { -// dev_printk(KERN_INFO, tp_to_dev(tp), "loopback test finished\n",rx_len,len); - break; - } - } - - rtl8168_hw_reset(dev); - rtl8168_disable_rxdvgate(dev); - RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb); - } - tp->dirty_tx++; - tp->dirty_rx++; - tp->cur_tx++; - tp->cur_rx++; - dma_unmap_single(&pdev->dev, le64_to_cpu(mapping), - len, DMA_TO_DEVICE); - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) & ~0x00060000); - dev_kfree_skb_any(skb); - RTL_W16(tp, IntrStatus, 0xFFBF); -} - -static unsigned int -rtl8168_xmii_reset_pending(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int retval; - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - retval = rtl8168_mdio_read(tp, MII_BMCR) & BMCR_RESET; - - return retval; -} - -static unsigned int -rtl8168_xmii_link_ok(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int retval; - - retval = (RTL_R8(tp, PHYstatus) & LinkStatus) ? 1 : 0; - - return retval; -} - -static int -rtl8168_wait_phy_reset_complete(struct rtl8168_private *tp) -{ - int i, val; - - for (i = 0; i < 2500; i++) { - val = rtl8168_mdio_read(tp, MII_BMCR) & BMCR_RESET; - if (!val) - return 0; - - mdelay(1); - } - - return -1; -} - -static void -rtl8168_xmii_reset_enable(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (rtl8168_is_in_phy_disable_mode(dev)) - return; - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, MII_ADVERTISE, rtl8168_mdio_read(tp, MII_ADVERTISE) & - ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL)); - rtl8168_mdio_write(tp, MII_CTRL1000, rtl8168_mdio_read(tp, MII_CTRL1000) & - ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL)); - rtl8168_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE); - - if (rtl8168_wait_phy_reset_complete(tp) == 0) return; - - if (netif_msg_link(tp)) - printk(KERN_ERR "%s: PHY reset failed.\n", dev->name); -} - -static void -rtl8168dp_10mbps_gphy_para(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 status = RTL_R8(tp, PHYstatus); - - if ((status & LinkStatus) && (status & _10bps)) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x10, 0x04EE); - } else { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x10, 0x01EE); - } -} - -void rtl8168_init_ring_indexes(struct rtl8168_private *tp) -{ - tp->dirty_tx = 0; - tp->dirty_rx = 0; - tp->cur_tx = 0; - tp->cur_rx = 0; -} - -static void -rtl8168_issue_offset_99_event(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_27: - case CFG_METHOD_28: - if (tp->mcfg == CFG_METHOD_24 || tp->mcfg == CFG_METHOD_25 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28) { - rtl8168_eri_write(tp, 0x3FC, 4, 0x00000000, ERIAR_ExGMAC); - } else { - rtl8168_eri_write(tp, 0x3FC, 4, 0x083C083C, ERIAR_ExGMAC); - } - csi_tmp = rtl8168_eri_read(tp, 0x3F8, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0x3F8, 1, csi_tmp, ERIAR_ExGMAC); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x1EA, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0x1EA, 1, csi_tmp, ERIAR_ExGMAC); - break; - } -} - -static void -rtl8168_enable_cfg9346_write(struct rtl8168_private *tp) -{ - RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) | Cfg9346_Unlock); -} - -static void -rtl8168_disable_cfg9346_write(struct rtl8168_private *tp) -{ - RTL_W8(tp, Cfg9346, RTL_R8(tp, Cfg9346) & ~Cfg9346_Unlock); -} - -static void -rtl8168_enable_exit_l1_mask(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp |= (BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12); - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - break; - case CFG_METHOD_20: - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp |= (BIT_10 | BIT_11); - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - break; - case CFG_METHOD_21 ... CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp |= (BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12); - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - break; - } -} - -static void -rtl8168_disable_exit_l1_mask(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12); - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - break; - case CFG_METHOD_20: - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_10 | BIT_11); - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - break; - case CFG_METHOD_21 ... CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_7 | BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12); - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - break; - } -} - -static void -rtl8168_hw_aspm_clkreq_enable(struct rtl8168_private *tp, bool enable) -{ - if (!tp->HwSuppAspmClkIntrLock) return; - - if (enable && aspm) { - RTL_W8(tp, Config5, RTL_R8(tp, Config5) | ASPM_en); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) | ClkReqEn); - } else { - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~ClkReqEn); - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~ASPM_en); - } - - udelay(10); -} - -#ifdef ENABLE_DASH_SUPPORT -static void -NICChkTypeEnableDashInterrupt(struct rtl8168_private *tp) -{ - if (tp->DASH) { - // - // even disconnected, enable 3 dash interrupt mask bits for in-band/out-band communication - // - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - rtl8168_enable_dash2_interrupt(tp); - RTL_W16(tp, IntrMask, (ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET)); - } else { - RTL_W16(tp, IntrMask, (ISRIMR_DP_DASH_OK | ISRIMR_DP_HOST_OK | ISRIMR_DP_REQSYS_OK)); - } - } -} -#endif - -static void -rtl8168_check_link_status(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int link_status_on; - -#ifdef ENABLE_FIBER_SUPPORT - rtl8168_check_fiber_link_status(dev); -#endif //ENABLE_FIBER_SUPPORT - - link_status_on = tp->link_ok(dev); - - if (tp->mcfg == CFG_METHOD_11) - rtl8168dp_10mbps_gphy_para(dev); - - if (netif_carrier_ok(dev) != link_status_on) { - if (link_status_on) { - rtl8168_hw_config(dev); - - if (tp->mcfg == CFG_METHOD_18 || tp->mcfg == CFG_METHOD_19 || tp->mcfg == CFG_METHOD_20) { - if (RTL_R8(tp, PHYstatus) & _1000bpsF) { - rtl8168_eri_write(tp, 0x1bc, 4, 0x00000011, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x0000001f, ERIAR_ExGMAC); - } else if (RTL_R8(tp, PHYstatus) & _100bps) { - rtl8168_eri_write(tp, 0x1bc, 4, 0x0000001f, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x0000001f, ERIAR_ExGMAC); - } else { - rtl8168_eri_write(tp, 0x1bc, 4, 0x0000001f, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x0000002d, ERIAR_ExGMAC); - } - } else if ((tp->mcfg == CFG_METHOD_16 || tp->mcfg == CFG_METHOD_17) && netif_running(dev)) { - if (tp->mcfg == CFG_METHOD_16 && (RTL_R8(tp, PHYstatus) & _10bps)) { - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | AcceptAllPhys); - } else if (tp->mcfg == CFG_METHOD_17) { - if (RTL_R8(tp, PHYstatus) & _1000bpsF) { - rtl8168_eri_write(tp, 0x1bc, 4, 0x00000011, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x00000005, ERIAR_ExGMAC); - } else if (RTL_R8(tp, PHYstatus) & _100bps) { - rtl8168_eri_write(tp, 0x1bc, 4, 0x0000001f, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x00000005, ERIAR_ExGMAC); - } else { - rtl8168_eri_write(tp, 0x1bc, 4, 0x0000001f, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x0000003f, ERIAR_ExGMAC); - } - } - } else if ((tp->mcfg == CFG_METHOD_14 || tp->mcfg == CFG_METHOD_15) && tp->eee_enabled == 1) { - /*Full -Duplex mode*/ - if (RTL_R8(tp, PHYstatus)&FullDup) { - rtl8168_mdio_write(tp, 0x1F, 0x0006); - rtl8168_mdio_write(tp, 0x00, 0x5a30); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - if (RTL_R8(tp, PHYstatus) & (_10bps | _100bps)) - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) & ~BIT_19) | BIT_25); - - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0006); - rtl8168_mdio_write(tp, 0x00, 0x5a00); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - if (RTL_R8(tp, PHYstatus) & (_10bps | _100bps)) - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) & ~BIT_19) | (InterFrameGap << TxInterFrameGapShift)); - } - } else if ((tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_23 || tp->mcfg == CFG_METHOD_24 || - tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) && netif_running(dev)) { - if (RTL_R8(tp, PHYstatus)&FullDup) - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | (BIT_24 | BIT_25)) & ~BIT_19); - else - RTL_W32(tp, TxConfig, (RTL_R32(tp, TxConfig) | BIT_25) & ~(BIT_19 | BIT_24)); - } - - if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - /*half mode*/ - if (!(RTL_R8(tp, PHYstatus)&FullDup)) { - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, MII_ADVERTISE, rtl8168_mdio_read(tp, MII_ADVERTISE)&~(ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM)); - } - } - - if ((tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) && (RTL_R8(tp, PHYstatus) & _10bps)) { - u32 csi_tmp; - - csi_tmp = rtl8168_eri_read(tp, 0x1D0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_1; - rtl8168_eri_write(tp, 0x1D0, 1, csi_tmp, ERIAR_ExGMAC); - } - - rtl8168_hw_start(dev); - - netif_carrier_on(dev); - - netif_wake_queue(dev); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - tp->phy_reg_aner = rtl8168_mdio_read(tp, MII_EXPANSION); - tp->phy_reg_anlpar = rtl8168_mdio_read(tp, MII_LPA); - tp->phy_reg_gbsr = rtl8168_mdio_read(tp, MII_STAT1000); - - if (netif_msg_ifup(tp)) - printk(KERN_INFO PFX "%s: link up\n", dev->name); - } else { - if (netif_msg_ifdown(tp)) - printk(KERN_INFO PFX "%s: link down\n", dev->name); - - tp->phy_reg_aner = 0; - tp->phy_reg_anlpar = 0; - tp->phy_reg_gbsr = 0; - - netif_stop_queue(dev); - - netif_carrier_off(dev); - - rtl8168_hw_reset(dev); - - rtl8168_tx_clear(tp); - - rtl8168_rx_clear(tp); - - rtl8168_init_ring(dev); - - if (dynamic_aspm) { - rtl8168_enable_cfg9346_write(tp); - rtl8168_hw_aspm_clkreq_enable(tp, true); - rtl8168_disable_cfg9346_write(tp); - } - - rtl8168_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_27: - case CFG_METHOD_28: - if (tp->org_pci_offset_99 & BIT_2) - tp->issue_offset_99_event = TRUE; - break; - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - NICChkTypeEnableDashInterrupt(tp); - } -#endif - } - } - - if (!link_status_on) { - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_27: - case CFG_METHOD_28: - if (tp->issue_offset_99_event) { - if (!(RTL_R8(tp, PHYstatus) & PowerSaveStatus)) { - tp->issue_offset_99_event = FALSE; - rtl8168_issue_offset_99_event(tp); - } - } - break; - } - } else { - if (dynamic_aspm) { - bool enable_hw_aspm_clkreq = true; - if (tp->dynamic_aspm_packet_count > dynamic_aspm_packet_threshold) - enable_hw_aspm_clkreq = false; - - rtl8168_enable_cfg9346_write(tp); - rtl8168_hw_aspm_clkreq_enable(tp, enable_hw_aspm_clkreq); - rtl8168_disable_cfg9346_write(tp); - } - tp->dynamic_aspm_packet_count = 0; - } -} - -static void -rtl8168_link_option(u8 *aut, - u32 *spd, - u8 *dup, - u32 *adv) -{ - if ((*spd != SPEED_1000) && (*spd != SPEED_100) && (*spd != SPEED_10)) - *spd = SPEED_1000; - - if ((*dup != DUPLEX_FULL) && (*dup != DUPLEX_HALF)) - *dup = DUPLEX_FULL; - - if ((*aut != AUTONEG_ENABLE) && (*aut != AUTONEG_DISABLE)) - *aut = AUTONEG_ENABLE; - - *adv &= (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full); - if (*adv == 0) - *adv = (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full); -} - -static void -rtl8168_enable_ocp_phy_power_saving(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 val; - - if (tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - val = rtl8168_mdio_read_phy_ocp(tp, 0x0C41, 0x13); - if (val != 0x0050) { - rtl8168_set_phy_mcu_patch_request(tp); - rtl8168_mdio_write_phy_ocp(tp, 0x0C41, 0x13, 0x0000); - rtl8168_mdio_write_phy_ocp(tp, 0x0C41, 0x13, 0x0050); - rtl8168_clear_phy_mcu_patch_request(tp); - } - } -} - -static void -rtl8168_disable_ocp_phy_power_saving(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 val; - - if (tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - val = rtl8168_mdio_read_phy_ocp(tp, 0x0C41, 0x13); - if (val != 0x0500) { - rtl8168_set_phy_mcu_patch_request(tp); - rtl8168_mdio_write_phy_ocp(tp, 0x0C41, 0x13, 0x0000); - rtl8168_mdio_write_phy_ocp(tp, 0x0C41, 0x13, 0x0500); - rtl8168_clear_phy_mcu_patch_request(tp); - } - } -} - -void -rtl8168_wait_ll_share_fifo_ready(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int i; - - for (i = 0; i < 10; i++) { - udelay(100); - if (RTL_R16(tp, 0xD2) & BIT_9) - break; - } -} - -static void -rtl8168_disable_pci_offset_99(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x3F2, 2, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_0 | BIT_1); - rtl8168_eri_write(tp, 0x3F2, 2, csi_tmp, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_csi_fun0_write_byte(tp, 0x99, 0x00); - break; - } -} - -static void -rtl8168_enable_pci_offset_99(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_csi_fun0_write_byte(tp, 0x99, tp->org_pci_offset_99); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x3F2, 2, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_0 | BIT_1); - if (tp->org_pci_offset_99 & (BIT_5 | BIT_6)) - csi_tmp |= BIT_1; - if (tp->org_pci_offset_99 & BIT_2) - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0x3F2, 2, csi_tmp, ERIAR_ExGMAC); - break; - } -} - -static void -rtl8168_init_pci_offset_99(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_26: - if (tp->org_pci_offset_99 & BIT_2) { - csi_tmp = rtl8168_eri_read(tp, 0x5C2, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_1; - rtl8168_eri_write(tp, 0x5C2, 1, csi_tmp, ERIAR_ExGMAC); - } - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x3F2, 2, ERIAR_ExGMAC); - csi_tmp &= ~( BIT_8 | BIT_9 | BIT_10 | BIT_11 | BIT_12 | BIT_13 | BIT_14 | BIT_15 ); - csi_tmp |= ( BIT_9 | BIT_10 | BIT_13 | BIT_14 | BIT_15 ); - rtl8168_eri_write(tp, 0x3F2, 2, csi_tmp, ERIAR_ExGMAC); - csi_tmp = rtl8168_eri_read(tp, 0x3F5, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_6 | BIT_7; - rtl8168_eri_write(tp, 0x3F5, 1, csi_tmp, ERIAR_ExGMAC); - rtl8168_mac_ocp_write(tp, 0xE02C, 0x1880); - rtl8168_mac_ocp_write(tp, 0xE02E, 0x4880); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_26: - rtl8168_eri_write(tp, 0x5C0, 1, 0xFA, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_26: - if (tp->org_pci_offset_99 & BIT_2) { - csi_tmp = rtl8168_eri_read(tp, 0x5C8, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0x5C8, 1, csi_tmp, ERIAR_ExGMAC); - } - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - if (tp->org_pci_offset_99 & BIT_2) - rtl8168_mac_ocp_write(tp, 0xE0A2, rtl8168_mac_ocp_read(tp, 0xE0A2) | BIT_0); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_23: - rtl8168_eri_write(tp, 0x2E8, 2, 0x883C, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2EA, 2, 0x8C12, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2EC, 2, 0x9003, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2E2, 2, 0x883C, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2E4, 2, 0x8C12, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2E6, 2, 0x9003, ERIAR_ExGMAC); - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_eri_write(tp, 0x2E8, 2, 0x9003, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2EA, 2, 0x9003, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2EC, 2, 0x9003, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2E2, 2, 0x883C, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2E4, 2, 0x8C12, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x2E6, 2, 0x9003, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - csi_tmp = rtl8168_eri_read(tp, 0x3FA, 2, ERIAR_ExGMAC); - csi_tmp |= BIT_14; - rtl8168_eri_write(tp, 0x3FA, 2, csi_tmp, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - if (tp->org_pci_offset_99 & BIT_2) - RTL_W8(tp, 0xB6, RTL_R8(tp, 0xB6) | BIT_0); - break; - } - - rtl8168_enable_pci_offset_99(tp); -} - -static void -rtl8168_disable_pci_offset_180(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x1E2, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_2; - rtl8168_eri_write(tp, 0x1E2, 1, csi_tmp, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_26: - rtl8168_eri_write(tp, 0x1E9, 1, 0x0A, ERIAR_ExGMAC); - break; - } -} - -static void -rtl8168_enable_pci_offset_180(struct rtl8168_private *tp) -{ - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_25: - case CFG_METHOD_28: - csi_tmp = rtl8168_eri_read(tp, 0x1E8, 4, ERIAR_ExGMAC); - csi_tmp &= ~(0x0000FF00); - csi_tmp |= (0x00006400); - rtl8168_eri_write(tp, 0x1E8, 4, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x1E4, 4, ERIAR_ExGMAC); - csi_tmp &= ~(0x0000FF00); - rtl8168_eri_write(tp, 0x1E4, 4, csi_tmp, ERIAR_ExGMAC); - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x1E8, 4, ERIAR_ExGMAC); - csi_tmp &= ~(0x0000FFF0); - csi_tmp |= (0x00000640); - rtl8168_eri_write(tp, 0x1E8, 4, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x1E4, 4, ERIAR_ExGMAC); - csi_tmp &= ~(0x0000FF00); - rtl8168_eri_write(tp, 0x1E4, 4, csi_tmp, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - csi_tmp = rtl8168_eri_read(tp, 0x1E2, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_2; - rtl8168_eri_write(tp, 0x1E2, 1, csi_tmp, ERIAR_ExGMAC); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_26: - rtl8168_eri_write(tp, 0x1E9, 1, 0x64, ERIAR_ExGMAC); - break; - } - - rtl8168_mac_ocp_write(tp, 0xE094, 0x0000); -} - -static void -rtl8168_init_pci_offset_180(struct rtl8168_private *tp) -{ - if (tp->org_pci_offset_180 & (BIT_0|BIT_1)) - rtl8168_enable_pci_offset_180(tp); - else - rtl8168_disable_pci_offset_180(tp); -} - -static void -rtl8168_set_pci_99_180_exit_driver_para(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_issue_offset_99_event(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_disable_pci_offset_99(tp); - break; - } - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_disable_pci_offset_180(tp); - break; - } -} - -static void -rtl8168_hw_d3_para(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - RTL_W16(tp, RxMaxSize, RX_BUF_SIZE); - - if (tp->HwSuppAspmClkIntrLock) { - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - rtl8168_enable_cfg9346_write(tp); - rtl8168_hw_aspm_clkreq_enable(tp, false); - rtl8168_disable_cfg9346_write(tp); - } - - rtl8168_disable_exit_l1_mask(tp); - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8168_set_realwow_d3_para(dev); -#endif - - if (tp->mcfg == CFG_METHOD_18 || tp->mcfg == CFG_METHOD_19 || tp->mcfg == CFG_METHOD_20) { - rtl8168_eri_write(tp, 0x1bc, 4, 0x0000001f, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x0000002d, ERIAR_ExGMAC); - } else if (tp->mcfg == CFG_METHOD_16) { - rtl8168_eri_write(tp, 0x1bc, 4, 0x0000001f, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0x1dc, 4, 0x0000003f, ERIAR_ExGMAC); - } - - if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_23 || tp->mcfg == CFG_METHOD_24 || - tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - rtl8168_eri_write(tp, 0x2F8, 2, 0x0064, ERIAR_ExGMAC); - } - - if (tp->bios_setting & BIT_28) { - if (tp->mcfg == CFG_METHOD_18 || tp->mcfg == CFG_METHOD_19 || - tp->mcfg == CFG_METHOD_20) { - u32 gphy_val; - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x04, 0x0061); - rtl8168_mdio_write(tp, 0x09, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val &= ~BIT_7; - rtl8168_mdio_write(tp, 0x06, gphy_val); - mdelay(1); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - gphy_val = rtl8168_mdio_read(tp, 0x16); - gphy_val &= ~BIT_10; - rtl8168_mdio_write(tp, 0x16, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - } - - rtl8168_set_pci_99_180_exit_driver_para(dev); - - /*disable ocp phy power saving*/ - if (tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) - if (!tp->dash_printer_enabled) - rtl8168_disable_ocp_phy_power_saving(dev); - - rtl8168_disable_rxdvgate(dev); -} - -static void -rtl8168_enable_magic_packet(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 csi_tmp; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V1: - rtl8168_enable_cfg9346_write(tp); - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | MagicPacket); - rtl8168_disable_cfg9346_write(tp); - break; - case WAKEUP_MAGIC_PACKET_V2: - csi_tmp = rtl8168_eri_read(tp, 0xDE, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDE, 1, csi_tmp, ERIAR_ExGMAC); - break; - } -} -static void -rtl8168_disable_magic_packet(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 csi_tmp; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V1: - rtl8168_enable_cfg9346_write(tp); - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~MagicPacket); - rtl8168_disable_cfg9346_write(tp); - break; - case WAKEUP_MAGIC_PACKET_V2: - csi_tmp = rtl8168_eri_read(tp, 0xDE, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDE, 1, csi_tmp, ERIAR_ExGMAC); - break; - } -} - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - -static void -rtl8168_get_hw_wol(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 options; - u32 csi_tmp; - unsigned long flags; - - - spin_lock_irqsave(&tp->lock, flags); - - tp->wol_opts = 0; - options = RTL_R8(tp, Config1); - if (!(options & PMEnable)) - goto out_unlock; - - options = RTL_R8(tp, Config3); - if (options & LinkUp) - tp->wol_opts |= WAKE_PHY; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V2: - csi_tmp = rtl8168_eri_read(tp, 0xDE, 1, ERIAR_ExGMAC); - if (csi_tmp & BIT_0) - tp->wol_opts |= WAKE_MAGIC; - break; - default: - if (options & MagicPacket) - tp->wol_opts |= WAKE_MAGIC; - break; - } - - options = RTL_R8(tp, Config5); - if (options & UWF) - tp->wol_opts |= WAKE_UCAST; - if (options & BWF) - tp->wol_opts |= WAKE_BCAST; - if (options & MWF) - tp->wol_opts |= WAKE_MCAST; - -out_unlock: - tp->wol_enabled = (tp->wol_opts || tp->dash_printer_enabled) ? WOL_ENABLED : WOL_DISABLED; - - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void -rtl8168_set_hw_wol(struct net_device *dev, u32 wolopts) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int i,tmp; - static struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_PHY, Config3, LinkUp }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake }, - { WAKE_MAGIC, Config3, MagicPacket }, - }; - - switch (tp->HwSuppMagicPktVer) { - case WAKEUP_MAGIC_PACKET_V2: - tmp = ARRAY_SIZE(cfg) - 1; - - if (wolopts & WAKE_MAGIC) - rtl8168_enable_magic_packet(dev); - else - rtl8168_disable_magic_packet(dev); - break; - default: - tmp = ARRAY_SIZE(cfg); - break; - } - - rtl8168_enable_cfg9346_write(tp); - - for (i = 0; i < tmp; i++) { - u8 options = RTL_R8(tp, cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(tp, cfg[i].reg, options); - } - - if (tp->dash_printer_enabled) - RTL_W8(tp, Config5, RTL_R8(tp, Config5) | LanWake); - - rtl8168_disable_cfg9346_write(tp); -} - -static void -rtl8168_phy_restart_nway(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (rtl8168_is_in_phy_disable_mode(dev)) return; - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, MII_BMCR, BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART); -} - -static void -rtl8168_phy_setup_force_mode(struct net_device *dev, u32 speed, u8 duplex) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 bmcr_true_force = 0; - - if (rtl8168_is_in_phy_disable_mode(dev)) return; - - if ((speed == SPEED_10) && (duplex == DUPLEX_HALF)) { - bmcr_true_force = BMCR_SPEED10; - } else if ((speed == SPEED_10) && (duplex == DUPLEX_FULL)) { - bmcr_true_force = BMCR_SPEED10 | BMCR_FULLDPLX; - } else if ((speed == SPEED_100) && (duplex == DUPLEX_HALF)) { - bmcr_true_force = BMCR_SPEED100; - } else if ((speed == SPEED_100) && (duplex == DUPLEX_FULL)) { - bmcr_true_force = BMCR_SPEED100 | BMCR_FULLDPLX; - } else { - netif_err(tp, drv, dev, "Failed to set phy force mode!\n"); - return; - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, MII_BMCR, bmcr_true_force); -} - -static void -rtl8168_set_pci_pme(struct rtl8168_private *tp, int set) -{ - struct pci_dev *pdev = tp->pci_dev; - u16 pmc; - - if (!pdev->pm_cap) - return; - - pci_read_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, &pmc); - pmc |= PCI_PM_CTRL_PME_STATUS; - if (set) - pmc |= PCI_PM_CTRL_PME_ENABLE; - else - pmc &= ~PCI_PM_CTRL_PME_ENABLE; - pci_write_config_word(pdev, pdev->pm_cap + PCI_PM_CTRL, pmc); -} - -static void -rtl8168_set_wol_link_speed(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int auto_nego; - int giga_ctrl; - u32 adv; - u16 anlpar; - u16 gbsr; - u16 aner; - - if (tp->autoneg != AUTONEG_ENABLE) - goto exit; - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - auto_nego = rtl8168_mdio_read(tp, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL - | ADVERTISE_100HALF | ADVERTISE_100FULL); - - giga_ctrl = rtl8168_mdio_read(tp, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - - aner = anlpar = gbsr = 0; - if (tp->link_ok(dev)) { - aner = rtl8168_mdio_read(tp, MII_EXPANSION); - anlpar = rtl8168_mdio_read(tp, MII_LPA); - gbsr = rtl8168_mdio_read(tp, MII_STAT1000); - } else { - if (netif_running(dev)) { - aner = tp->phy_reg_aner; - anlpar = tp->phy_reg_anlpar; - gbsr = tp->phy_reg_gbsr; - } - } - - if ((aner | anlpar | gbsr) == 0) { - int auto_nego_tmp = 0; - adv = tp->advertising; - if ((adv & ADVERTISED_10baseT_Half) && (anlpar & LPA_10HALF)) - auto_nego_tmp |= ADVERTISE_10HALF; - if ((adv & ADVERTISED_10baseT_Full) && (anlpar & LPA_10FULL)) - auto_nego_tmp |= ADVERTISE_10FULL; - if ((adv & ADVERTISED_100baseT_Half) && (anlpar & LPA_100HALF)) - auto_nego_tmp |= ADVERTISE_100HALF; - if ((adv & ADVERTISED_100baseT_Full) && (anlpar & LPA_100FULL)) - auto_nego_tmp |= ADVERTISE_100FULL; - - if (auto_nego_tmp == 0) goto exit; - - auto_nego |= auto_nego_tmp; - goto skip_check_lpa; - } - if (!(aner & EXPANSION_NWAY)) goto exit; - - adv = tp->advertising; - if ((adv & ADVERTISED_10baseT_Half) && (anlpar & LPA_10HALF)) - auto_nego |= ADVERTISE_10HALF; - else if ((adv & ADVERTISED_10baseT_Full) && (anlpar & LPA_10FULL)) - auto_nego |= ADVERTISE_10FULL; - else if ((adv & ADVERTISED_100baseT_Half) && (anlpar & LPA_100HALF)) - auto_nego |= ADVERTISE_100HALF; - else if ((adv & ADVERTISED_100baseT_Full) && (anlpar & LPA_100FULL)) - auto_nego |= ADVERTISE_100FULL; - else if (adv & ADVERTISED_1000baseT_Half && (gbsr & LPA_1000HALF)) - giga_ctrl |= ADVERTISE_1000HALF; - else if (adv & ADVERTISED_1000baseT_Full && (gbsr & LPA_1000FULL)) - giga_ctrl |= ADVERTISE_1000FULL; - else - goto exit; - -skip_check_lpa: - if (tp->DASH) - auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); - - if (((tp->mcfg == CFG_METHOD_7) || (tp->mcfg == CFG_METHOD_8)) && (RTL_R16(tp, CPlusCmd) & ASF)) - auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); - -#ifdef CONFIG_DOWN_SPEED_100 - auto_nego |= (ADVERTISE_100FULL | ADVERTISE_100HALF | ADVERTISE_10HALF | ADVERTISE_10FULL); -#endif - - rtl8168_mdio_write(tp, MII_ADVERTISE, auto_nego); - rtl8168_mdio_write(tp, MII_CTRL1000, giga_ctrl); - - rtl8168_phy_restart_nway(dev); - -exit: - return; -} - -static void -rtl8168_powerdown_pll(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - -#ifdef ENABLE_FIBER_SUPPORT - if (HW_FIBER_MODE_ENABLED(tp)) - return; -#endif //ENABLE_FIBER_SUPPORT - - if (tp->wol_enabled == WOL_ENABLED || tp->DASH || tp->EnableKCPOffload) { - rtl8168_set_hw_wol(dev, tp->wol_opts); - - if (tp->mcfg == CFG_METHOD_16 || tp->mcfg == CFG_METHOD_17 || - tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_24 || tp->mcfg == CFG_METHOD_25 || - tp->mcfg == CFG_METHOD_26 || tp->mcfg == CFG_METHOD_23 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - rtl8168_enable_cfg9346_write(tp); - RTL_W8(tp, Config2, RTL_R8(tp, Config2) | PMSTS_En); - rtl8168_disable_cfg9346_write(tp); - } - - /* Enable the PME and clear the status */ - rtl8168_set_pci_pme(tp, 1); - - if (HW_SUPP_SERDES_PHY(tp)) - return; - - rtl8168_set_wol_link_speed(dev); - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); - - return; - } - - if (tp->DASH) - return; - - if (((tp->mcfg == CFG_METHOD_7) || (tp->mcfg == CFG_METHOD_8)) && (RTL_R16(tp, CPlusCmd) & ASF)) - return; - - rtl8168_phy_power_down(dev); - - if (!tp->HwIcVerUnknown) { - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - //case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) & ~BIT_7); - break; - } - } - - switch (tp->mcfg) { - case CFG_METHOD_14 ... CFG_METHOD_15: - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) & ~BIT_6); - break; - case CFG_METHOD_16 ... CFG_METHOD_33: - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) & ~BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_6); - break; - } -} - -static void rtl8168_powerup_pll(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W8(tp, PMCH, RTL_R8(tp, PMCH) | BIT_7 | BIT_6); - break; - } - - rtl8168_phy_power_up(dev); -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static void -rtl8168_get_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 options; - unsigned long flags; - - wol->wolopts = 0; - - if (tp->mcfg == CFG_METHOD_DEFAULT) { - wol->supported = 0; - return; - } else { - wol->supported = WAKE_ANY; - } - - spin_lock_irqsave(&tp->lock, flags); - - options = RTL_R8(tp, Config1); - if (!(options & PMEnable)) - goto out_unlock; - - wol->wolopts = tp->wol_opts; - -out_unlock: - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int -rtl8168_set_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - - tp->wol_opts = wol->wolopts; - - tp->wol_enabled = (tp->wol_opts || tp->dash_printer_enabled) ? WOL_ENABLED : WOL_DISABLED; - - spin_unlock_irqrestore(&tp->lock, flags); - - device_set_wakeup_enable(tp_to_dev(tp), tp->wol_enabled); - - return 0; -} - -static void -rtl8168_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct rtl8168_fw *rtl_fw = tp->rtl_fw; - - strcpy(info->driver, MODULENAME); - strcpy(info->version, RTL8168_VERSION); - strcpy(info->bus_info, pci_name(tp->pci_dev)); - info->regdump_len = R8168_REGS_DUMP_SIZE; - info->eedump_len = tp->eeprom_len; - BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version)); - if (rtl_fw) - strlcpy(info->fw_version, rtl_fw->version, - sizeof(info->fw_version)); -} - -static int -rtl8168_get_regs_len(struct net_device *dev) -{ - return R8168_REGS_DUMP_SIZE; -} -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -static int -rtl8168_set_speed_xmii(struct net_device *dev, - u8 autoneg, - u32 speed, - u8 duplex, - u32 adv) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int auto_nego = 0; - int giga_ctrl = 0; - int rc = -EINVAL; - - if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - //Disable Giga Lite - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - rtl8168_clear_eth_phy_bit(tp, 0x14, BIT_9); - if (tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) - rtl8168_clear_eth_phy_bit(tp, 0x14, BIT_7); - rtl8168_mdio_write(tp, 0x1F, 0x0A40); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - if ((speed != SPEED_1000) && - (speed != SPEED_100) && - (speed != SPEED_10)) { - speed = SPEED_1000; - duplex = DUPLEX_FULL; - } - - giga_ctrl = rtl8168_mdio_read(tp, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - - if (autoneg == AUTONEG_ENABLE) { - /*n-way force*/ - auto_nego = rtl8168_mdio_read(tp, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL | - ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM); - - if (adv & ADVERTISED_10baseT_Half) - auto_nego |= ADVERTISE_10HALF; - if (adv & ADVERTISED_10baseT_Full) - auto_nego |= ADVERTISE_10FULL; - if (adv & ADVERTISED_100baseT_Half) - auto_nego |= ADVERTISE_100HALF; - if (adv & ADVERTISED_100baseT_Full) - auto_nego |= ADVERTISE_100FULL; - if (adv & ADVERTISED_1000baseT_Half) - giga_ctrl |= ADVERTISE_1000HALF; - if (adv & ADVERTISED_1000baseT_Full) - giga_ctrl |= ADVERTISE_1000FULL; - - //flow control - if (dev->mtu <= ETH_DATA_LEN) - auto_nego |= ADVERTISE_PAUSE_CAP|ADVERTISE_PAUSE_ASYM; - - tp->phy_auto_nego_reg = auto_nego; - tp->phy_1000_ctrl_reg = giga_ctrl; - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, MII_ADVERTISE, auto_nego); - rtl8168_mdio_write(tp, MII_CTRL1000, giga_ctrl); - rtl8168_phy_restart_nway(dev); - mdelay(20); - } else { - /*true force*/ - if (speed == SPEED_10 || speed == SPEED_100) - rtl8168_phy_setup_force_mode(dev, speed, duplex); - else - goto out; - } - - tp->autoneg = autoneg; - tp->speed = speed; - tp->duplex = duplex; - tp->advertising = adv; - - if (tp->mcfg == CFG_METHOD_11) - rtl8168dp_10mbps_gphy_para(dev); - - rc = 0; -out: - return rc; -} - -static int -rtl8168_set_speed(struct net_device *dev, - u8 autoneg, - u32 speed, - u8 duplex, - u32 adv) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex, adv); - - return ret; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int -rtl8168_set_settings(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - const struct ethtool_link_ksettings *cmd -#endif - ) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int ret; - unsigned long flags; - u8 autoneg; - u32 speed; - u8 duplex; - u32 supported, advertising; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - autoneg = cmd->autoneg; - speed = cmd->speed; - duplex = cmd->duplex; - supported = cmd->supported; - advertising = cmd->advertising; -#else - const struct ethtool_link_settings *base = &cmd->base; - autoneg = base->autoneg; - speed = base->speed; - duplex = base->duplex; - ethtool_convert_link_mode_to_legacy_u32(&supported, - cmd->link_modes.supported); - ethtool_convert_link_mode_to_legacy_u32(&advertising, - cmd->link_modes.advertising); -#endif - if (advertising & ~supported) - return -EINVAL; - - spin_lock_irqsave(&tp->lock, flags); - ret = rtl8168_set_speed(dev, autoneg, speed, duplex, advertising); - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -static u32 -rtl8168_get_tx_csum(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 ret; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - ret = ((dev->features & NETIF_F_IP_CSUM) != 0); -#else - ret = ((dev->features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) != 0); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static u32 -rtl8168_get_rx_csum(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 ret; - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - ret = tp->cp_cmd & RxChkSum; - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -static int -rtl8168_set_tx_csum(struct net_device *dev, - u32 data) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - if (data) - dev->features |= NETIF_F_IP_CSUM; - else - dev->features &= ~NETIF_F_IP_CSUM; -#else - if (data) - if ((tp->mcfg == CFG_METHOD_1) || (tp->mcfg == CFG_METHOD_2) || (tp->mcfg == CFG_METHOD_3)) - dev->features |= NETIF_F_IP_CSUM; - else - dev->features |= (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); - else - dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -static int -rtl8168_set_rx_csum(struct net_device *dev, - u32 data) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - - if (data) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - RTL_W16(tp, CPlusCmd, tp->cp_cmd); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -#ifdef CONFIG_R8168_VLAN - -static inline u32 -rtl8168_tx_vlan_tag(struct rtl8168_private *tp, - struct sk_buff *skb) -{ - u32 tag; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - tag = (tp->vlgrp && vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -#elif LINUX_VERSION_CODE < KERNEL_VERSION(4,0,0) - tag = (vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -#else - tag = (skb_vlan_tag_present(skb)) ? - TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00; -#endif - - return tag; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - -static void -rtl8168_vlan_rx_register(struct net_device *dev, - struct vlan_group *grp) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - tp->vlgrp = grp; - if (tp->vlgrp) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - RTL_W16(tp, CPlusCmd, tp->cp_cmd); - RTL_R16(tp, CPlusCmd); - spin_unlock_irqrestore(&tp->lock, flags); -} - -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) -static void -rtl8168_vlan_rx_kill_vid(struct net_device *dev, - unsigned short vid) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) - if (tp->vlgrp) - tp->vlgrp->vlan_devices[vid] = NULL; -#else - vlan_group_set_device(tp->vlgrp, vid, NULL); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,21) - spin_unlock_irqrestore(&tp->lock, flags); -} -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - -static int -rtl8168_rx_vlan_skb(struct rtl8168_private *tp, - struct RxDesc *desc, - struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - int ret = -1; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - if (tp->vlgrp && (opts2 & RxVlanTag)) { - rtl8168_rx_hwaccel_skb(skb, tp->vlgrp, - swab16(opts2 & 0xffff)); - ret = 0; - } -#elif LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0) - if (opts2 & RxVlanTag) - __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); -#else - if (opts2 & RxVlanTag) - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff)); -#endif - - desc->opts2 = 0; - return ret; -} - -#else /* !CONFIG_R8168_VLAN */ - -static inline u32 -rtl8168_tx_vlan_tag(struct rtl8168_private *tp, - struct sk_buff *skb) -{ - return 0; -} - -static int -rtl8168_rx_vlan_skb(struct rtl8168_private *tp, - struct RxDesc *desc, - struct sk_buff *skb) -{ - return -1; -} - -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) - -static netdev_features_t rtl8168_fix_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - if (dev->mtu > MSS_MAX) - features &= ~NETIF_F_ALL_TSO; - if (dev->mtu > ETH_DATA_LEN) { - features &= ~NETIF_F_ALL_TSO; - features &= ~NETIF_F_ALL_CSUM; - } - spin_unlock_irqrestore(&tp->lock, flags); - - return features; -} - -static int rtl8168_hw_set_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 rx_config; - - rx_config = RTL_R32(tp, RxConfig); - if (features & NETIF_F_RXALL) - rx_config |= (AcceptErr | AcceptRunt); - else - rx_config &= ~(AcceptErr | AcceptRunt); - - RTL_W32(tp, RxConfig, rx_config); - - if (features & NETIF_F_RXCSUM) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - if (dev->features & NETIF_F_HW_VLAN_RX) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - - RTL_W16(tp, CPlusCmd, tp->cp_cmd); - RTL_R16(tp, CPlusCmd); - - return 0; -} - -static int rtl8168_set_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - features &= NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_RX; - - spin_lock_irqsave(&tp->lock, flags); - if (features ^ dev->features) - rtl8168_hw_set_features(dev, features); - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -#endif - -static void rtl8168_gset_xmii(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - struct ethtool_link_ksettings *cmd -#endif - ) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 status; - u8 autoneg, duplex; - u32 speed = 0; - u16 bmcr, bmsr, anlpar, ctrl1000 = 0, stat1000 = 0; - u32 supported, advertising, lp_advertising; - unsigned long flags; - - supported = SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP | - SUPPORTED_Pause | - SUPPORTED_Asym_Pause; - - advertising = ADVERTISED_TP; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - bmcr = rtl8168_mdio_read(tp, MII_BMCR); - bmsr = rtl8168_mdio_read(tp, MII_BMSR); - anlpar = rtl8168_mdio_read(tp, MII_LPA); - ctrl1000 = rtl8168_mdio_read(tp, MII_CTRL1000); - stat1000 = rtl8168_mdio_read(tp, MII_STAT1000); - spin_unlock_irqrestore(&tp->lock, flags); - - if (bmcr & BMCR_ANENABLE) { - advertising |= ADVERTISED_Autoneg; - autoneg = AUTONEG_ENABLE; - - if (bmsr & BMSR_ANEGCOMPLETE) { - lp_advertising = mii_lpa_to_ethtool_lpa_t(anlpar); - lp_advertising |= - mii_stat1000_to_ethtool_lpa_t(stat1000); - } else { - lp_advertising = 0; - } - - if (tp->phy_auto_nego_reg & ADVERTISE_10HALF) - advertising |= ADVERTISED_10baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_10FULL) - advertising |= ADVERTISED_10baseT_Full; - if (tp->phy_auto_nego_reg & ADVERTISE_100HALF) - advertising |= ADVERTISED_100baseT_Half; - if (tp->phy_auto_nego_reg & ADVERTISE_100FULL) - advertising |= ADVERTISED_100baseT_Full; - if (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL) - advertising |= ADVERTISED_1000baseT_Full; - } else { - autoneg = AUTONEG_DISABLE; - lp_advertising = 0; - } - - status = RTL_R8(tp, PHYstatus); - - if (status & LinkStatus) { - /*link on*/ - if (status & _1000bpsF) - speed = SPEED_1000; - else if (status & _100bps) - speed = SPEED_100; - else if (status & _10bps) - speed = SPEED_10; - - if (status & TxFlowCtrl) - advertising |= ADVERTISED_Asym_Pause; - - if (status & RxFlowCtrl) - advertising |= ADVERTISED_Pause; - - duplex = ((status & _1000bpsF) || (status & FullDup)) ? - DUPLEX_FULL : DUPLEX_HALF; - } else { - /*link down*/ - speed = SPEED_UNKNOWN; - duplex = DUPLEX_UNKNOWN; - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - cmd->supported = supported; - cmd->advertising = advertising; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,30) - cmd->lp_advertising = lp_advertising; -#endif - cmd->autoneg = autoneg; - cmd->speed = speed; - cmd->duplex = duplex; - cmd->port = PORT_TP; -#else - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, - supported); - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, - advertising); - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.lp_advertising, - lp_advertising); - cmd->base.autoneg = autoneg; - cmd->base.speed = speed; - cmd->base.duplex = duplex; - cmd->base.port = PORT_TP; -#endif -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int -rtl8168_get_settings(struct net_device *dev, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - struct ethtool_cmd *cmd -#else - struct ethtool_link_ksettings *cmd -#endif - ) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - tp->get_settings(dev, cmd); - - return 0; -} - -static void rtl8168_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8168_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - u8 *data = p; - unsigned long flags; - - if (regs->len < R8168_REGS_DUMP_SIZE) - return /* -EINVAL */; - - memset(p, 0, regs->len); - - spin_lock_irqsave(&tp->lock, flags); - for (i = 0; i < R8168_MAC_REGS_SIZE; i++) - *data++ = readb(ioaddr + i); - data = (u8*)p + 256; - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - for (i = 0; i < R8168_PHY_REGS_SIZE/2; i++) { - *(u16*)data = rtl8168_mdio_read(tp, i); - data += 2; - } - data = (u8*)p + 256 * 2; - - for (i = 0; i < R8168_EPHY_REGS_SIZE/2; i++) { - *(u16*)data = rtl8168_ephy_read(tp, i); - data += 2; - } - data = (u8*)p + 256 * 3; - - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - /* RTL8168B does not support Extend GMAC */ - break; - default: - for (i = 0; i < R8168_ERI_REGS_SIZE; i+=4) { - *(u32*)data = rtl8168_eri_read(tp, i , 4, ERIAR_ExGMAC); - data += 4; - } - break; - } - spin_unlock_irqrestore(&tp->lock, flags); -} - -static u32 -rtl8168_get_msglevel(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void -rtl8168_set_msglevel(struct net_device *dev, - u32 value) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8168_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; -#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static int rtl8168_get_stats_count(struct net_device *dev) -{ - return ARRAY_SIZE(rtl8168_gstrings); -} -#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -#else -static int rtl8168_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8168_gstrings); - default: - return -EOPNOTSUPP; - } -} -#endif - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static void -rtl8168_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, - u64 *data) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct rtl8168_counters *counters; - dma_addr_t paddr; - u32 cmd; - u32 WaitCnt; - unsigned long flags; - - ASSERT_RTNL(); - - counters = tp->tally_vaddr; - paddr = tp->tally_paddr; - if (!counters) - return; - - spin_lock_irqsave(&tp->lock, flags); - RTL_W32(tp, CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(tp, CounterAddrLow, cmd); - RTL_W32(tp, CounterAddrLow, cmd | CounterDump); - - WaitCnt = 0; - while (RTL_R32(tp, CounterAddrLow) & CounterDump) { - udelay(10); - - WaitCnt++; - if (WaitCnt > 20) - break; - } - spin_unlock_irqrestore(&tp->lock, flags); - - data[0] = le64_to_cpu(counters->tx_packets); - data[1] = le64_to_cpu(counters->rx_packets); - data[2] = le64_to_cpu(counters->tx_errors); - data[3] = le32_to_cpu(counters->rx_errors); - data[4] = le16_to_cpu(counters->rx_missed); - data[5] = le16_to_cpu(counters->align_errors); - data[6] = le32_to_cpu(counters->tx_one_collision); - data[7] = le32_to_cpu(counters->tx_multi_collision); - data[8] = le64_to_cpu(counters->rx_unicast); - data[9] = le64_to_cpu(counters->rx_broadcast); - data[10] = le32_to_cpu(counters->rx_multicast); - data[11] = le16_to_cpu(counters->tx_aborted); - data[12] = le16_to_cpu(counters->tx_underrun); -} - -static void -rtl8168_get_strings(struct net_device *dev, - u32 stringset, - u8 *data) -{ - switch (stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8168_gstrings, sizeof(rtl8168_gstrings)); - break; - } -} -#endif //#LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -static int rtl_get_eeprom_len(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - return tp->eeprom_len; -} - -static int rtl_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, u8 *buf) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int i,j,ret; - int start_w, end_w; - int VPD_addr, VPD_data; - u32 *eeprom_buff; - u16 tmp; - - if (tp->eeprom_type == EEPROM_TYPE_NONE) { - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Detect none EEPROM\n"); - return -EOPNOTSUPP; - } else if (eeprom->len == 0 || (eeprom->offset+eeprom->len) > tp->eeprom_len) { - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Invalid parameter\n"); - return -EINVAL; - } - - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - VPD_addr = 0xCE; - VPD_data = 0xD0; - break; - - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - return -EOPNOTSUPP; - default: - VPD_addr = 0xD2; - VPD_data = 0xD4; - break; - } - - start_w = eeprom->offset >> 2; - end_w = (eeprom->offset + eeprom->len - 1) >> 2; - - eeprom_buff = kmalloc(sizeof(u32)*(end_w - start_w + 1), GFP_KERNEL); - if (!eeprom_buff) - return -ENOMEM; - - rtl8168_enable_cfg9346_write(tp); - ret = -EFAULT; - for (i=start_w; i<=end_w; i++) { - pci_write_config_word(tp->pci_dev, VPD_addr, (u16)i*4); - ret = -EFAULT; - for (j = 0; j < 10; j++) { - udelay(400); - pci_read_config_word(tp->pci_dev, VPD_addr, &tmp); - if (tmp&0x8000) { - ret = 0; - break; - } - } - - if (ret) - break; - - pci_read_config_dword(tp->pci_dev, VPD_data, &eeprom_buff[i-start_w]); - } - rtl8168_disable_cfg9346_write(tp); - - if (!ret) - memcpy(buf, (u8 *)eeprom_buff + (eeprom->offset & 3), eeprom->len); - - kfree(eeprom_buff); - - return ret; -} - -#undef ethtool_op_get_link -#define ethtool_op_get_link _kc_ethtool_op_get_link -static u32 _kc_ethtool_op_get_link(struct net_device *dev) -{ - return netif_carrier_ok(dev) ? 1 : 0; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) -#undef ethtool_op_get_sg -#define ethtool_op_get_sg _kc_ethtool_op_get_sg -static u32 _kc_ethtool_op_get_sg(struct net_device *dev) -{ -#ifdef NETIF_F_SG - return (dev->features & NETIF_F_SG) != 0; -#else - return 0; -#endif -} - -#undef ethtool_op_set_sg -#define ethtool_op_set_sg _kc_ethtool_op_set_sg -static int _kc_ethtool_op_set_sg(struct net_device *dev, u32 data) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (tp->mcfg == CFG_METHOD_DEFAULT) - return -EOPNOTSUPP; - -#ifdef NETIF_F_SG - if (data) - dev->features |= NETIF_F_SG; - else - dev->features &= ~NETIF_F_SG; -#endif - - return 0; -} -#endif - -static int rtl8168_enable_EEE(struct rtl8168_private *tp) -{ - int ret; - u16 data; - u32 csi_tmp; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0020); - data = rtl8168_mdio_read(tp, 0x15) | 0x0100; - rtl8168_mdio_write(tp, 0x15, data); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - data = rtl8168_mdio_read(tp, 0x06) | 0x2000; - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0006); - rtl8168_mdio_write(tp, 0x00, 0x5A30); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0007); - rtl8168_mdio_write(tp, 0x0E, 0x003C); - rtl8168_mdio_write(tp, 0x0D, 0x4007); - rtl8168_mdio_write(tp, 0x0E, 0x0006); - rtl8168_mdio_write(tp, 0x0D, 0x0000); - if ((RTL_R8(tp, Config4)&0x40) && (RTL_R8(tp, 0x6D) & BIT_7)) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8AC8); - rtl8168_mdio_write(tp, 0x06, RTL_R16(tp, tp->NicCustLedValue)); - rtl8168_mdio_write(tp, 0x05, 0x8B82); - data = rtl8168_mdio_read(tp, 0x06) | 0x0010; - rtl8168_mdio_write(tp, 0x05, 0x8B82); - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - break; - - case CFG_METHOD_16: - case CFG_METHOD_17: - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC) | 0x0003; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - rtl8168_mdio_write(tp,0x1F , 0x0004); - rtl8168_mdio_write(tp,0x1F , 0x0007); - rtl8168_mdio_write(tp,0x1E , 0x0020); - data = rtl8168_mdio_read(tp, 0x15)|0x0100; - rtl8168_mdio_write(tp,0x15 , data); - rtl8168_mdio_write(tp,0x1F , 0x0002); - rtl8168_mdio_write(tp,0x1F , 0x0005); - rtl8168_mdio_write(tp,0x05 , 0x8B85); - data = rtl8168_mdio_read(tp, 0x06)|0x2000; - rtl8168_mdio_write(tp,0x06 , data); - rtl8168_mdio_write(tp,0x1F , 0x0000); - rtl8168_mdio_write(tp,0x0D , 0x0007); - rtl8168_mdio_write(tp,0x0E , 0x003C); - rtl8168_mdio_write(tp,0x0D , 0x4007); - rtl8168_mdio_write(tp,0x0E , 0x0006); - rtl8168_mdio_write(tp,0x0D , 0x0000); - break; - - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp |= BIT_1 | BIT_0; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0020); - data = rtl8168_mdio_read(tp, 0x15); - data |= BIT_8; - rtl8168_mdio_write(tp, 0x15, data); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - data = rtl8168_mdio_read(tp, 0x06); - data |= BIT_13; - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0007); - rtl8168_mdio_write(tp, 0x0E, 0x003C); - rtl8168_mdio_write(tp, 0x0D, 0x4007); - rtl8168_mdio_write(tp, 0x0E, 0x0006); - rtl8168_mdio_write(tp, 0x0D, 0x0000); - break; - - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp |= BIT_1 | BIT_0; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x11); - rtl8168_mdio_write(tp, 0x11, data | BIT_4); - rtl8168_mdio_write(tp, 0x1F, 0x0A5D); - rtl8168_mdio_write(tp, 0x10, tp->eee_adv_t); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - - default: -// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEE\n"); - ret = -EOPNOTSUPP; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mdio_write(tp, 0x1F, 0x0A4A); - rtl8168_set_eth_phy_bit(tp, 0x11, BIT_9); - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_7); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - } - - /*Advanced EEE*/ - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_oob_mutex_lock(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_set_phy_mcu_patch_request(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_25: - rtl8168_eri_write(tp, 0x1EA, 1, 0xFA, ERIAR_ExGMAC); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x10); - if (data & BIT_10) { - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - data = rtl8168_mdio_read(tp, 0x16); - data &= ~(BIT_1); - rtl8168_mdio_write(tp, 0x16, data); - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - data = rtl8168_mdio_read(tp, 0x16); - data |= BIT_1; - rtl8168_mdio_write(tp, 0x16, data); - } - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_26: - data = rtl8168_mac_ocp_read(tp, 0xE052); - data |= BIT_0; - rtl8168_mac_ocp_write(tp, 0xE052, data); - data = rtl8168_mac_ocp_read(tp, 0xE056); - data &= 0xFF0F; - data |= (BIT_4 | BIT_5 | BIT_6); - rtl8168_mac_ocp_write(tp, 0xE056, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x10); - if (data & BIT_10) { - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - data = rtl8168_mdio_read(tp, 0x16); - data &= ~(BIT_1); - rtl8168_mdio_write(tp, 0x16, data); - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - data = rtl8168_mdio_read(tp, 0x16); - data |= BIT_1; - rtl8168_mdio_write(tp, 0x16, data); - } - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_27: - case CFG_METHOD_28: - data = rtl8168_mac_ocp_read(tp, 0xE052); - data &= ~BIT_0; - rtl8168_mac_ocp_write(tp, 0xE052, data); - data = rtl8168_mac_ocp_read(tp, 0xE056); - data &= 0xFF0F; - data |= (BIT_4 | BIT_5 | BIT_6); - rtl8168_mac_ocp_write(tp, 0xE056, data); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - data = rtl8168_mac_ocp_read(tp, 0xE052); - data &= ~(BIT_0); - rtl8168_mac_ocp_write(tp, 0xE052, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x10) | BIT_15; - rtl8168_mdio_write(tp, 0x10, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - data = rtl8168_mdio_read(tp, 0x11) | BIT_13 | BIT_14; - data &= ~(BIT_12); - rtl8168_mdio_write(tp, 0x11, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - /* - data = rtl8168_mac_ocp_read(tp, 0xE052); - data |= BIT_0; - rtl8168_mac_ocp_write(tp, 0xE052, data); - */ - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x10) | BIT_15; - rtl8168_mdio_write(tp, 0x10, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - data = rtl8168_mdio_read(tp, 0x11) | BIT_13 | BIT_14; - data &= ~(BIT_12); - rtl8168_mdio_write(tp, 0x11, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_clear_phy_mcu_patch_request(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_oob_mutex_unlock(tp); - break; - } - - return ret; -} - -static int rtl8168_disable_EEE(struct rtl8168_private *tp) -{ - int ret; - u16 data; - u32 csi_tmp; - - ret = 0; - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - data = rtl8168_mdio_read(tp, 0x06) & ~0x2000; - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0020); - data = rtl8168_mdio_read(tp, 0x15) & ~0x0100; - rtl8168_mdio_write(tp, 0x15, data); - rtl8168_mdio_write(tp, 0x1F, 0x0006); - rtl8168_mdio_write(tp, 0x00, 0x5A00); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0007); - rtl8168_mdio_write(tp, 0x0E, 0x003C); - rtl8168_mdio_write(tp, 0x0D, 0x4007); - rtl8168_mdio_write(tp, 0x0E, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - if (RTL_R8(tp, Config4) & 0x40) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B82); - data = rtl8168_mdio_read(tp, 0x06) & ~0x0010; - rtl8168_mdio_write(tp, 0x05, 0x8B82); - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - break; - - case CFG_METHOD_16: - case CFG_METHOD_17: - csi_tmp = rtl8168_eri_read(tp, 0x1B0,4, ERIAR_ExGMAC)& ~0x0003; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - data = rtl8168_mdio_read(tp, 0x06) & ~0x2000; - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0004); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0020); - data = rtl8168_mdio_read(tp, 0x15) & ~0x0100; - rtl8168_mdio_write(tp,0x15 , data); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0007); - rtl8168_mdio_write(tp, 0x0E, 0x003C); - rtl8168_mdio_write(tp, 0x0D, 0x4007); - rtl8168_mdio_write(tp, 0x0E, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_1 | BIT_0); - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - data = rtl8168_mdio_read(tp, 0x06); - data &= ~BIT_13; - rtl8168_mdio_write(tp, 0x06, data); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0020); - data = rtl8168_mdio_read(tp, 0x15); - data &= ~BIT_8; - rtl8168_mdio_write(tp, 0x15, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0007); - rtl8168_mdio_write(tp, 0x0E, 0x003C); - rtl8168_mdio_write(tp, 0x0D, 0x4007); - rtl8168_mdio_write(tp, 0x0E, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_1 | BIT_0); - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x11); - rtl8168_mdio_write(tp, 0x11, data & ~BIT_4); - rtl8168_mdio_write(tp, 0x1F, 0x0A5D); - rtl8168_mdio_write(tp, 0x10, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - - default: -// dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support EEE\n"); - ret = -EOPNOTSUPP; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - rtl8168_clear_eth_phy_bit(tp, 0x14, BIT_7); - rtl8168_mdio_write(tp, 0x1F, 0x0A4A); - rtl8168_clear_eth_phy_bit(tp, 0x11, BIT_9); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - } - - /*Advanced EEE*/ - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_oob_mutex_lock(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_set_phy_mcu_patch_request(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_25: - rtl8168_eri_write(tp, 0x1EA, 1, 0x00, ERIAR_ExGMAC); - - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - data = rtl8168_mdio_read(tp, 0x16); - data &= ~(BIT_1); - rtl8168_mdio_write(tp, 0x16, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_26: - data = rtl8168_mac_ocp_read(tp, 0xE052); - data &= ~(BIT_0); - rtl8168_mac_ocp_write(tp, 0xE052, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - data = rtl8168_mdio_read(tp, 0x16); - data &= ~(BIT_1); - rtl8168_mdio_write(tp, 0x16, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_27: - case CFG_METHOD_28: - data = rtl8168_mac_ocp_read(tp, 0xE052); - data &= ~(BIT_0); - rtl8168_mac_ocp_write(tp, 0xE052, data); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - data = rtl8168_mac_ocp_read(tp, 0xE052); - data &= ~(BIT_0); - rtl8168_mac_ocp_write(tp, 0xE052, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - data = rtl8168_mdio_read(tp, 0x10) & ~(BIT_15); - rtl8168_mdio_write(tp, 0x10, data); - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - data = rtl8168_mdio_read(tp, 0x11) & ~(BIT_12 | BIT_13 | BIT_14); - rtl8168_mdio_write(tp, 0x11, data); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_clear_phy_mcu_patch_request(tp); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_oob_mutex_unlock(tp); - break; - } - - return ret; -} - -static int rtl_nway_reset(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - int ret, bmcr; - - spin_lock_irqsave(&tp->lock, flags); - - if (unlikely(tp->rtk_enable_diag)) { - spin_unlock_irqrestore(&tp->lock, flags); - return -EBUSY; - } - - /* if autoneg is off, it's an error */ - rtl8168_mdio_write(tp, 0x1F, 0x0000); - bmcr = rtl8168_mdio_read(tp, MII_BMCR); - - if (bmcr & BMCR_ANENABLE) { - bmcr |= BMCR_ANRESTART; - rtl8168_mdio_write(tp, MII_BMCR, bmcr); - ret = 0; - } else { - ret = -EINVAL; - } - - spin_unlock_irqrestore(&tp->lock, flags); - - return ret; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) -static int -rtl_ethtool_get_eee(struct net_device *net, struct ethtool_eee *eee) -{ - struct rtl8168_private *tp = netdev_priv(net); - u32 lp, adv, supported = 0; - unsigned long flags; - u16 val; - - switch (tp->mcfg) { - case CFG_METHOD_21 ... CFG_METHOD_33: - break; - default: - return -EOPNOTSUPP; - } - - spin_lock_irqsave(&tp->lock, flags); - - if (unlikely(tp->rtk_enable_diag)) { - spin_unlock_irqrestore(&tp->lock, flags); - return -EBUSY; - } - - rtl8168_mdio_write(tp, 0x1F, 0x0A5C); - val = rtl8168_mdio_read(tp, 0x12); - supported = mmd_eee_cap_to_ethtool_sup_t(val); - - rtl8168_mdio_write(tp, 0x1F, 0x0A5D); - val = rtl8168_mdio_read(tp, 0x10); - adv = mmd_eee_adv_to_ethtool_adv_t(val); - - val = rtl8168_mdio_read(tp, 0x11); - lp = mmd_eee_adv_to_ethtool_adv_t(val); - - val = rtl8168_eri_read(tp, 0x1B0, 2, ERIAR_ExGMAC); - val &= BIT_1 | BIT_0; - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - spin_unlock_irqrestore(&tp->lock, flags); - - eee->eee_enabled = !!val; - eee->eee_active = !!(supported & adv & lp); - eee->supported = supported; - eee->advertised = adv; - eee->lp_advertised = lp; - - return 0; -} - -static int -rtl_ethtool_set_eee(struct net_device *net, struct ethtool_eee *eee) -{ - struct rtl8168_private *tp = netdev_priv(net); - unsigned long flags; - - switch (tp->mcfg) { - case CFG_METHOD_21 ... CFG_METHOD_33: - break; - default: - return -EOPNOTSUPP; - } - - if (HW_SUPP_SERDES_PHY(tp) || - !HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp) || - tp->DASH) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - - if (unlikely(tp->rtk_enable_diag)) { - spin_unlock_irqrestore(&tp->lock, flags); - return -EBUSY; - } - - tp->eee_enabled = eee->eee_enabled; - tp->eee_adv_t = ethtool_adv_to_mmd_eee_adv_t(eee->advertised); - - if (tp->eee_enabled) - rtl8168_enable_EEE(tp); - else - rtl8168_disable_EEE(tp); - - spin_unlock_irqrestore(&tp->lock, flags); - - rtl_nway_reset(net); - - return 0; -} -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) -static const struct ethtool_ops rtl8168_ethtool_ops = { - .get_drvinfo = rtl8168_get_drvinfo, - .get_regs_len = rtl8168_get_regs_len, - .get_link = ethtool_op_get_link, -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,6,0) - .get_settings = rtl8168_get_settings, - .set_settings = rtl8168_set_settings, -#else - .get_link_ksettings = rtl8168_get_settings, - .set_link_ksettings = rtl8168_set_settings, -#endif - .get_msglevel = rtl8168_get_msglevel, - .set_msglevel = rtl8168_set_msglevel, -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,3,0) - .get_rx_csum = rtl8168_get_rx_csum, - .set_rx_csum = rtl8168_set_rx_csum, - .get_tx_csum = rtl8168_get_tx_csum, - .set_tx_csum = rtl8168_set_tx_csum, - .get_sg = ethtool_op_get_sg, - .set_sg = ethtool_op_set_sg, -#ifdef NETIF_F_TSO - .get_tso = ethtool_op_get_tso, - .set_tso = ethtool_op_set_tso, -#endif -#endif - .get_regs = rtl8168_get_regs, - .get_wol = rtl8168_get_wol, - .set_wol = rtl8168_set_wol, - .get_strings = rtl8168_get_strings, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,33) - .get_stats_count = rtl8168_get_stats_count, -#else - .get_sset_count = rtl8168_get_sset_count, -#endif - .get_ethtool_stats = rtl8168_get_ethtool_stats, -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) -#ifdef ETHTOOL_GPERMADDR - .get_perm_addr = ethtool_op_get_perm_addr, -#endif -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,23) - .get_eeprom = rtl_get_eeprom, - .get_eeprom_len = rtl_get_eeprom_len, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) - .get_ts_info = ethtool_op_get_ts_info, -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,5,0) -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) - .get_eee = rtl_ethtool_get_eee, - .set_eee = rtl_ethtool_set_eee, -#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3,6,0) */ - .nway_reset = rtl_nway_reset, -}; -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - -#if 0 - -static int rtl8168_enable_green_feature(struct rtl8168_private *tp) -{ - u16 gphy_val; - unsigned long flags; - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - rtl8168_mdio_write(tp, 0x1F, 0x0003); - gphy_val = rtl8168_mdio_read(tp, 0x10) | 0x0400; - rtl8168_mdio_write(tp, 0x10, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x19) | 0x0001; - rtl8168_mdio_write(tp, 0x19, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - gphy_val = rtl8168_mdio_read(tp, 0x01) & ~0x0100; - rtl8168_mdio_write(tp, 0x01, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - mdelay(20); - break; - - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - rtl8168_mdio_write(tp, 0x1f, 0x0003); - gphy_val = rtl8168_mdio_read(tp, 0x10); - gphy_val |= BIT_10; - rtl8168_mdio_write(tp, 0x10, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x19); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x19, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - gphy_val = rtl8168_mdio_read(tp, 0x01); - gphy_val |= BIT_8; - rtl8168_mdio_write(tp, 0x01, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - break; - case CFG_METHOD_21: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_set_eth_phy_bit( tp, 0x14, BIT_14 ); - rtl8168_mdio_write(tp, 0x1F, 0x0A40); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8045); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0x804d); - rtl8168_mdio_write(tp, 0x14, 0x1222); - rtl8168_mdio_write(tp, 0x13, 0x805d); - rtl8168_mdio_write(tp, 0x14, 0x0022); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_set_eth_phy_bit( tp, 0x14, BIT_15 ); - rtl8168_mdio_write(tp, 0x1F, 0x0A40); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - break; - default: - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support Green Feature\n"); - break; - } - - return 0; -} - -static int rtl8168_disable_green_feature(struct rtl8168_private *tp) -{ - u16 gphy_val; - unsigned long flags; - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - rtl8168_mdio_write(tp, 0x1F, 0x0005); - gphy_val = rtl8168_mdio_read(tp, 0x01) | 0x0100; - rtl8168_mdio_write(tp, 0x01, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - gphy_val = rtl8168_mdio_read(tp, 0x10) & ~0x0400; - rtl8168_mdio_write(tp, 0x10, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x19) & ~0x0001; - rtl8168_mdio_write(tp, 0x19, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x06) & ~0x7000; - gphy_val |= 0x3000; - rtl8168_mdio_write(tp, 0x06, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x0D) & 0x0700; - gphy_val |= 0x0500; - rtl8168_mdio_write(tp, 0x0D, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - rtl8168_mdio_write(tp, 0x1f, 0x0003); - gphy_val = rtl8168_mdio_read(tp, 0x19); - gphy_val &= ~BIT_0; - rtl8168_mdio_write(tp, 0x19, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x10); - gphy_val &= ~BIT_10; - rtl8168_mdio_write(tp, 0x10, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - break; - case CFG_METHOD_21: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_clear_eth_phy_bit( tp, 0x14, BIT_14 ); - rtl8168_mdio_write(tp, 0x1F, 0x0A40); - rtl8168_mdio_write(tp, 0x00, 0x9200); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8045); - rtl8168_mdio_write(tp, 0x14, 0x2444); - rtl8168_mdio_write(tp, 0x13, 0x804d); - rtl8168_mdio_write(tp, 0x14, 0x2444); - rtl8168_mdio_write(tp, 0x13, 0x805d); - rtl8168_mdio_write(tp, 0x14, 0x2444); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_set_eth_phy_bit( tp, 0x14, BIT_15 ); - rtl8168_mdio_write(tp, 0x1F, 0x0A40); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - break; - default: - dev_printk(KERN_DEBUG, tp_to_dev(tp), "Not Support Green Feature\n"); - break; - } - - return 0; -} - -#endif - -static void rtl8168_get_mac_version(struct rtl8168_private *tp) -{ - u32 reg,val32; - u32 ICVerID; - - val32 = RTL_R32(tp, TxConfig); - reg = val32 & 0x7c800000; - ICVerID = val32 & 0x00700000; - - switch (reg) { - case 0x30000000: - tp->mcfg = CFG_METHOD_1; - tp->efuse_ver = EFUSE_NOT_SUPPORT; - break; - case 0x38000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_2; - } else if (ICVerID == 0x00500000) { - tp->mcfg = CFG_METHOD_3; - } else { - tp->mcfg = CFG_METHOD_3; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_NOT_SUPPORT; - break; - case 0x3C000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_4; - } else if (ICVerID == 0x00200000) { - tp->mcfg = CFG_METHOD_5; - } else if (ICVerID == 0x00400000) { - tp->mcfg = CFG_METHOD_6; - } else { - tp->mcfg = CFG_METHOD_6; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_NOT_SUPPORT; - break; - case 0x3C800000: - if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_7; - } else if (ICVerID == 0x00300000) { - tp->mcfg = CFG_METHOD_8; - } else { - tp->mcfg = CFG_METHOD_8; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_NOT_SUPPORT; - break; - case 0x28000000: - if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_9; - } else if (ICVerID == 0x00300000) { - tp->mcfg = CFG_METHOD_10; - } else { - tp->mcfg = CFG_METHOD_10; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V1; - break; - case 0x28800000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_11; - } else if (ICVerID == 0x00200000) { - tp->mcfg = CFG_METHOD_12; - RTL_W32(tp, 0xD0, RTL_R32(tp, 0xD0) | 0x00020000); - } else if (ICVerID == 0x00300000) { - tp->mcfg = CFG_METHOD_13; - } else { - tp->mcfg = CFG_METHOD_13; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V1; - break; - case 0x2C000000: - if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_14; - } else if (ICVerID == 0x00200000) { - tp->mcfg = CFG_METHOD_15; - } else { - tp->mcfg = CFG_METHOD_15; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V2; - break; - case 0x2C800000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_16; - } else if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_17; - } else { - tp->mcfg = CFG_METHOD_17; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x48000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_18; - } else if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_19; - } else { - tp->mcfg = CFG_METHOD_19; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x48800000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_20; - } else { - tp->mcfg = CFG_METHOD_20; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x4C000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_21; - } else if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_22; - } else { - tp->mcfg = CFG_METHOD_22; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x50000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_23; - } else if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_27; - } else if (ICVerID == 0x00200000) { - tp->mcfg = CFG_METHOD_28; - } else { - tp->mcfg = CFG_METHOD_28; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x50800000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_24; - } else if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_25; - } else { - tp->mcfg = CFG_METHOD_25; - tp->HwIcVerUnknown = TRUE; - } - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x5C800000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_26; - } else { - tp->mcfg = CFG_METHOD_26; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x54000000: - if (ICVerID == 0x00000000) { - tp->mcfg = CFG_METHOD_29; - } else if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_30; - } else { - tp->mcfg = CFG_METHOD_30; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - case 0x54800000: - if (ICVerID == 0x00100000) { - tp->mcfg = CFG_METHOD_31; - } else if (ICVerID == 0x00200000) { - tp->mcfg = CFG_METHOD_32; - } else if (ICVerID == 0x00300000) { - tp->mcfg = CFG_METHOD_33; - } else { - tp->mcfg = CFG_METHOD_33; - tp->HwIcVerUnknown = TRUE; - } - - tp->efuse_ver = EFUSE_SUPPORT_V3; - break; - default: - printk("unknown chip version (%x)\n",reg); - tp->mcfg = CFG_METHOD_DEFAULT; - tp->HwIcVerUnknown = TRUE; - tp->efuse_ver = EFUSE_NOT_SUPPORT; - break; - } -} - -static void -rtl8168_print_mac_version(struct rtl8168_private *tp) -{ - int i; - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { - if (tp->mcfg == rtl_chip_info[i].mcfg) { - dprintk("Realtek PCIe GbE Family Controller mcfg = %04d\n", - rtl_chip_info[i].mcfg); - return; - } - } - - dprintk("mac_version == Unknown\n"); -} - -static u8 rtl8168_calc_efuse_dummy_bit(u16 reg) -{ - int s,a,b; - u8 dummyBitPos = 0; - - - s=reg% 32; - a=s % 16; - b=s/16; - - if (s/16) { - dummyBitPos = (u8)(16-a); - } else { - dummyBitPos = (u8)a; - } - - return dummyBitPos; -} - -static u32 rtl8168_decode_efuse_cmd(struct rtl8168_private *tp, u32 DwCmd) -{ - u16 reg = (u16)((DwCmd & 0x00FE0000) >> 17); - u32 DummyPos = rtl8168_calc_efuse_dummy_bit(reg); - u32 DeCodeDwCmd = DwCmd; - u32 Dw17BitData; - - - if (tp->efuse_ver < 3) { - DeCodeDwCmd = (DwCmd>>(DummyPos+1))< 0) { - DeCodeDwCmd |= ((DwCmd<<(32-DummyPos))>>(32-DummyPos)); - } - } else { - reg = (u16)((DwCmd & 0x007F0000) >> 16); - DummyPos = rtl8168_calc_efuse_dummy_bit(reg); - Dw17BitData = ((DwCmd & BIT_23) >> 23); - Dw17BitData <<= 16; - Dw17BitData |= (DwCmd & 0x0000FFFF); - DeCodeDwCmd = (Dw17BitData>>(DummyPos+1))< 0) { - DeCodeDwCmd |= ((Dw17BitData<<(32-DummyPos))>>(32-DummyPos)); - } - } - - return DeCodeDwCmd; -} - -static u8 rtl8168_efuse_read(struct rtl8168_private *tp, u16 reg) -{ - u8 efuse_data = 0; - u32 temp; - int cnt; - - if (tp->efuse_ver == EFUSE_NOT_SUPPORT) - return EFUSE_READ_FAIL; - - if (tp->efuse_ver == EFUSE_SUPPORT_V1) { - temp = EFUSE_READ | ((reg & EFUSE_Reg_Mask) << EFUSE_Reg_Shift); - RTL_W32(tp, EFUSEAR, temp); - - cnt = 0; - do { - udelay(100); - temp = RTL_R32(tp, EFUSEAR); - cnt++; - } while (!(temp & EFUSE_READ_OK) && (cnt < EFUSE_Check_Cnt)); - - if (cnt == EFUSE_Check_Cnt) - efuse_data = EFUSE_READ_FAIL; - else - efuse_data = (u8)(RTL_R32(tp, EFUSEAR) & EFUSE_Data_Mask); - } else if (tp->efuse_ver == EFUSE_SUPPORT_V2) { - temp = (reg/2) & 0x03ff; - temp <<= 17; - temp |= EFUSE_READ; - RTL_W32(tp, EFUSEAR, temp); - - cnt = 0; - do { - udelay(100); - temp = RTL_R32(tp, EFUSEAR); - cnt++; - } while (!(temp & EFUSE_READ_OK) && (cnt < EFUSE_Check_Cnt)); - - if (cnt == EFUSE_Check_Cnt) { - efuse_data = EFUSE_READ_FAIL; - } else { - temp = RTL_R32(tp, EFUSEAR); - temp = rtl8168_decode_efuse_cmd(tp, temp); - - if (reg%2) { - temp >>= 8; - efuse_data = (u8)temp; - } else { - efuse_data = (u8)temp; - } - } - } else if (tp->efuse_ver == EFUSE_SUPPORT_V3) { - temp = (reg/2) & 0x03ff; - temp <<= 16; - temp |= EFUSE_READ_V3; - RTL_W32(tp, EFUSEAR, temp); - - cnt = 0; - do { - udelay(100); - temp = RTL_R32(tp, EFUSEAR); - cnt++; - } while ((temp & BIT_31) && (cnt < EFUSE_Check_Cnt)); - - if (cnt == EFUSE_Check_Cnt) { - efuse_data = EFUSE_READ_FAIL; - } else { - temp = RTL_R32(tp, EFUSEAR); - temp = rtl8168_decode_efuse_cmd(tp, temp); - - if (reg%2) { - temp >>= 8; - efuse_data = (u8)temp; - } else { - efuse_data = (u8)temp; - } - } - } - - udelay(20); - - return efuse_data; -} - -static void -rtl8168_tally_counter_addr_fill(struct rtl8168_private *tp) -{ - if (!tp->tally_paddr) - return; - - RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); - RTL_W32(tp, CounterAddrLow, (u64)tp->tally_paddr & (DMA_BIT_MASK(32))); -} - -static void -rtl8168_tally_counter_clear(struct rtl8168_private *tp) -{ - if (tp->mcfg == CFG_METHOD_1 || tp->mcfg == CFG_METHOD_2 || - tp->mcfg == CFG_METHOD_3 ) - return; - - if (!tp->tally_paddr) - return; - - RTL_W32(tp, CounterAddrHigh, (u64)tp->tally_paddr >> 32); - RTL_W32(tp, CounterAddrLow, ((u64)tp->tally_paddr & (DMA_BIT_MASK(32))) | CounterReset); -} - -static -u16 -rtl8168_get_phy_state(struct rtl8168_private *tp) -{ - u16 PhyState = 0xFF; - - if (HW_SUPPORT_UPS_MODE(tp) == FALSE) goto exit; - - switch (tp->HwSuppUpsVer) { - case 1: - PhyState = rtl8168_mdio_read_phy_ocp(tp, 0x0A42, 0x10); - PhyState &= 0x7; //bit[2:0] - break; - } - -exit: - return PhyState; -} - -static -bool -rtl8168_wait_phy_state_ready(struct rtl8168_private *tp, - u16 PhyState, - u32 MicroSecondTimeout - ) -{ - u16 TmpPhyState; - u32 WaitCount; - u32 i = 0; - bool PhyStateReady = TRUE; - - if (HW_SUPPORT_UPS_MODE(tp) == FALSE) goto exit; - - WaitCount = MicroSecondTimeout / 1000; - if (WaitCount == 0) WaitCount = 100; - - do { - TmpPhyState = rtl8168_get_phy_state(tp); - mdelay(1); - i++; - } while ((i < WaitCount) && (TmpPhyState != PhyState)); - - PhyStateReady = (i == WaitCount && TmpPhyState != PhyState) ? FALSE : TRUE; - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(i == WaitCount); -#endif - -exit: - return PhyStateReady; -} - -static -bool -rtl8168_test_phy_ocp(struct rtl8168_private *tp) -{ - bool RestorePhyOcpReg = FALSE; - - if (tp->TestPhyOcpReg == FALSE) goto exit; - - if (tp->HwSuppEsdVer == 2) { - u16 PhyRegValue; - u8 ResetPhyType = 0; - - if (HW_PHY_STATUS_INI == rtl8168_get_phy_state(tp)) { - ResetPhyType = 1; - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0C40); - PhyRegValue = rtl8168_mdio_read(tp, 0x12); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - if ((PhyRegValue & 0x03) != 0x00) { - ResetPhyType = 2; - } - } - - if (ResetPhyType > 0) { - u32 WaitCnt; - struct net_device *dev = tp->dev; - - printk(KERN_ERR "%s: test_phy_ocp ResetPhyType = 0x%02x\n.\n", dev->name, ResetPhyType); - - rtl8168_mdio_write(tp, 0x1F, 0x0C41); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - mdelay(24); //24ms - - rtl8168_mdio_write(tp, 0x1F, 0x0C40); - PhyRegValue = rtl8168_mdio_read(tp, 0x12); - if ((PhyRegValue & 0x03) != 0x00) { - WaitCnt = 0; - while ((PhyRegValue & 0x03) != 0x00 && WaitCnt < 5) { - rtl8168_mdio_write(tp, 0x1F, 0x0C40); - rtl8168_set_eth_phy_bit(tp, 0x11, (BIT_15 | BIT_14)); - rtl8168_clear_eth_phy_bit(tp, 0x11, (BIT_15 | BIT_14)); - mdelay(100); - rtl8168_mdio_write(tp, 0x1F, 0x0C40); - PhyRegValue = rtl8168_mdio_read(tp, 0x12); - WaitCnt++; - } - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A46); - rtl8168_mdio_write(tp, 0x10, tp->BackupPhyFuseDout_15_0); - rtl8168_mdio_write(tp, 0x12, tp->BackupPhyFuseDout_47_32); - rtl8168_mdio_write(tp, 0x13, tp->BackupPhyFuseDout_63_48); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_wait_phy_state_ready(tp, HW_PHY_STATUS_INI, 5000000); - rtl8168_mdio_write(tp, 0x1F, 0x0A46); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_wait_phy_state_ready(tp, HW_PHY_STATUS_LAN_ON, 500000); - - tp->HwHasWrRamCodeToMicroP = FALSE; - - RestorePhyOcpReg = TRUE; - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - -exit: - return RestorePhyOcpReg; -} - -static int -rtl8168_is_ups_resume(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - return (rtl8168_mac_ocp_read(tp, 0xD408) & BIT_0); -} - -static void -rtl8168_clear_ups_resume_bit(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - rtl8168_mac_ocp_write(tp, 0xD408, rtl8168_mac_ocp_read(tp, 0xD408) & ~(BIT_0)); -} - -static void -rtl8168_wait_phy_ups_resume(struct net_device *dev, u16 PhyState) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 TmpPhyState; - int i = 0; - - do { - TmpPhyState = rtl8168_mdio_read_phy_ocp(tp, 0x0A42, 0x10); - TmpPhyState &= 0x7; - mdelay(1); - i++; - } while ((i < 100) && (TmpPhyState != PhyState)); - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,18) - WARN_ON_ONCE(i == 100); -#endif -} - -void -rtl8168_enable_now_is_oob(struct rtl8168_private *tp) -{ - if ( tp->HwSuppNowIsOobVer == 1 ) { - RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) | Now_is_oob); - } -} - -void -rtl8168_disable_now_is_oob(struct rtl8168_private *tp) -{ - if ( tp->HwSuppNowIsOobVer == 1 ) { - RTL_W8(tp, MCUCmd_reg, RTL_R8(tp, MCUCmd_reg) & ~Now_is_oob); - } -} - -static void -rtl8168_switch_to_sgmii_mode( - struct rtl8168_private *tp -) -{ - if (FALSE == HW_SUPP_SERDES_PHY(tp)) return; - - switch (tp->HwSuppSerDesPhyVer) { - case 1: - rtl8168_mac_ocp_write(tp, 0xEB00, 0x2); - rtl8168_set_mcu_ocp_bit(tp, 0xEB16, BIT_1); - break; - } -} - -static void -rtl8168_exit_oob(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 data16; - - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) & ~(AcceptErr | AcceptRunt | AcceptBroadcast | AcceptMulticast | AcceptMyPhys | AcceptAllPhys)); - - if (HW_SUPP_SERDES_PHY(tp)) { - if (tp->HwSuppSerDesPhyVer == 1) { - rtl8168_switch_to_sgmii_mode(tp); - } - } - - if (HW_DASH_SUPPORT_DASH(tp)) { - rtl8168_driver_start(tp); - rtl8168_dash2_disable_txrx(dev); -#ifdef ENABLE_DASH_SUPPORT - DashHwInit(dev); -#endif - } - - //Disable realwow function - switch (tp->mcfg) { - case CFG_METHOD_18: - case CFG_METHOD_19: - RTL_W32(tp, MACOCP, 0xE5A90000); - RTL_W32(tp, MACOCP, 0xF2100010); - break; - case CFG_METHOD_20: - RTL_W32(tp, MACOCP, 0xE5A90000); - RTL_W32(tp, MACOCP, 0xE4640000); - RTL_W32(tp, MACOCP, 0xF2100010); - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - RTL_W32(tp, MACOCP, 0x605E0000); - RTL_W32(tp, MACOCP, (0xE05E << 16) | (RTL_R32(tp, MACOCP) & 0xFFFE)); - RTL_W32(tp, MACOCP, 0xE9720000); - RTL_W32(tp, MACOCP, 0xF2140010); - break; - case CFG_METHOD_26: - RTL_W32(tp, MACOCP, 0xE05E00FF); - RTL_W32(tp, MACOCP, 0xE9720000); - rtl8168_mac_ocp_write(tp, 0xE428, 0x0010); - break; - } - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8168_realwow_hw_init(dev); -#else - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - rtl8168_eri_write(tp, 0x174, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_mac_ocp_write(tp, 0xE428, 0x0010); - break; - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_eri_write(tp, 0x174, 2, 0x00FF, ERIAR_ExGMAC); - rtl8168_mac_ocp_write(tp, 0xE428, 0x0010); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: { - u32 csi_tmp; - csi_tmp = rtl8168_eri_read(tp, 0x174, 2, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_8); - csi_tmp |= (BIT_15); - rtl8168_eri_write(tp, 0x174, 2, csi_tmp, ERIAR_ExGMAC); - rtl8168_mac_ocp_write(tp, 0xE428, 0x0010); - } - break; - } -#endif //ENABLE_REALWOW_SUPPORT - - rtl8168_nic_reset(dev); - - switch (tp->mcfg) { - case CFG_METHOD_20: - rtl8168_wait_ll_share_fifo_ready(dev); - - data16 = rtl8168_mac_ocp_read(tp, 0xD4DE) | BIT_15; - rtl8168_mac_ocp_write(tp, 0xD4DE, data16); - - rtl8168_wait_ll_share_fifo_ready(dev); - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_disable_now_is_oob(tp); - - data16 = rtl8168_mac_ocp_read(tp, 0xE8DE) & ~BIT_14; - rtl8168_mac_ocp_write(tp, 0xE8DE, data16); - rtl8168_wait_ll_share_fifo_ready(dev); - - data16 = rtl8168_mac_ocp_read(tp, 0xE8DE) | BIT_15; - rtl8168_mac_ocp_write(tp, 0xE8DE, data16); - - rtl8168_wait_ll_share_fifo_ready(dev); - break; - } - - //wait ups resume (phy state 2) - if (HW_SUPPORT_UPS_MODE(tp)) - if (rtl8168_is_ups_resume(dev)) { - rtl8168_wait_phy_ups_resume(dev, HW_PHY_STATUS_EXT_INI); - rtl8168_clear_ups_resume_bit(dev); - } - -#ifdef ENABLE_FIBER_SUPPORT - if (HW_FIBER_MODE_ENABLED(tp)) - rtl8168_hw_init_fiber_nic(dev); -#endif //ENABLE_FIBER_SUPPORT -} - -void -rtl8168_hw_disable_mac_mcu_bps(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (tp->HwSuppAspmClkIntrLock) { - rtl8168_enable_cfg9346_write(tp); - rtl8168_hw_aspm_clkreq_enable(tp, false); - rtl8168_disable_cfg9346_write(tp); - } - - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mac_ocp_write(tp, 0xFC38, 0x0000); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mac_ocp_write(tp, 0xFC28, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC2E, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC30, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC32, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC34, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC36, 0x0000); - mdelay(3); - rtl8168_mac_ocp_write(tp, 0xFC26, 0x0000); - break; - } -} - -#ifndef ENABLE_USE_FIRMWARE_FILE -static void -rtl8168_set_mac_mcu_8168g_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - rtl8168_mac_ocp_write(tp, 0xE43C, 0x0000); - rtl8168_mac_ocp_write(tp, 0xE43E, 0x0000); - - rtl8168_mac_ocp_write(tp, 0xE434, 0x0004); - rtl8168_mac_ocp_write(tp, 0xE43C, 0x0004); - - rtl8168_hw_disable_mac_mcu_bps(dev); - - rtl8168_mac_ocp_write( tp, 0xF800, 0xE008 ); - rtl8168_mac_ocp_write( tp, 0xF802, 0xE01B ); - rtl8168_mac_ocp_write( tp, 0xF804, 0xE022 ); - rtl8168_mac_ocp_write( tp, 0xF806, 0xE094 ); - rtl8168_mac_ocp_write( tp, 0xF808, 0xE097 ); - rtl8168_mac_ocp_write( tp, 0xF80A, 0xE09A ); - rtl8168_mac_ocp_write( tp, 0xF80C, 0xE0B3 ); - rtl8168_mac_ocp_write( tp, 0xF80E, 0xE0BA ); - rtl8168_mac_ocp_write( tp, 0xF810, 0x49D2 ); - rtl8168_mac_ocp_write( tp, 0xF812, 0xF10D ); - rtl8168_mac_ocp_write( tp, 0xF814, 0x766C ); - rtl8168_mac_ocp_write( tp, 0xF816, 0x49E2 ); - rtl8168_mac_ocp_write( tp, 0xF818, 0xF00A ); - rtl8168_mac_ocp_write( tp, 0xF81A, 0x1EC0 ); - rtl8168_mac_ocp_write( tp, 0xF81C, 0x8EE1 ); - rtl8168_mac_ocp_write( tp, 0xF81E, 0xC60A ); - rtl8168_mac_ocp_write( tp, 0xF820, 0x77C0 ); - rtl8168_mac_ocp_write( tp, 0xF822, 0x4870 ); - rtl8168_mac_ocp_write( tp, 0xF824, 0x9FC0 ); - rtl8168_mac_ocp_write( tp, 0xF826, 0x1EA0 ); - rtl8168_mac_ocp_write( tp, 0xF828, 0xC707 ); - rtl8168_mac_ocp_write( tp, 0xF82A, 0x8EE1 ); - rtl8168_mac_ocp_write( tp, 0xF82C, 0x9D6C ); - rtl8168_mac_ocp_write( tp, 0xF82E, 0xC603 ); - rtl8168_mac_ocp_write( tp, 0xF830, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF832, 0xB416 ); - rtl8168_mac_ocp_write( tp, 0xF834, 0x0076 ); - rtl8168_mac_ocp_write( tp, 0xF836, 0xE86C ); - rtl8168_mac_ocp_write( tp, 0xF838, 0xC406 ); - rtl8168_mac_ocp_write( tp, 0xF83A, 0x7580 ); - rtl8168_mac_ocp_write( tp, 0xF83C, 0x4852 ); - rtl8168_mac_ocp_write( tp, 0xF83E, 0x8D80 ); - rtl8168_mac_ocp_write( tp, 0xF840, 0xC403 ); - rtl8168_mac_ocp_write( tp, 0xF842, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF844, 0xD3E0 ); - rtl8168_mac_ocp_write( tp, 0xF846, 0x02C8 ); - rtl8168_mac_ocp_write( tp, 0xF848, 0x8918 ); - rtl8168_mac_ocp_write( tp, 0xF84A, 0xE815 ); - rtl8168_mac_ocp_write( tp, 0xF84C, 0x1100 ); - rtl8168_mac_ocp_write( tp, 0xF84E, 0xF011 ); - rtl8168_mac_ocp_write( tp, 0xF850, 0xE812 ); - rtl8168_mac_ocp_write( tp, 0xF852, 0x4990 ); - rtl8168_mac_ocp_write( tp, 0xF854, 0xF002 ); - rtl8168_mac_ocp_write( tp, 0xF856, 0xE817 ); - rtl8168_mac_ocp_write( tp, 0xF858, 0xE80E ); - rtl8168_mac_ocp_write( tp, 0xF85A, 0x4992 ); - rtl8168_mac_ocp_write( tp, 0xF85C, 0xF002 ); - rtl8168_mac_ocp_write( tp, 0xF85E, 0xE80E ); - rtl8168_mac_ocp_write( tp, 0xF860, 0xE80A ); - rtl8168_mac_ocp_write( tp, 0xF862, 0x4993 ); - rtl8168_mac_ocp_write( tp, 0xF864, 0xF002 ); - rtl8168_mac_ocp_write( tp, 0xF866, 0xE818 ); - rtl8168_mac_ocp_write( tp, 0xF868, 0xE806 ); - rtl8168_mac_ocp_write( tp, 0xF86A, 0x4991 ); - rtl8168_mac_ocp_write( tp, 0xF86C, 0xF002 ); - rtl8168_mac_ocp_write( tp, 0xF86E, 0xE838 ); - rtl8168_mac_ocp_write( tp, 0xF870, 0xC25E ); - rtl8168_mac_ocp_write( tp, 0xF872, 0xBA00 ); - rtl8168_mac_ocp_write( tp, 0xF874, 0xC056 ); - rtl8168_mac_ocp_write( tp, 0xF876, 0x7100 ); - rtl8168_mac_ocp_write( tp, 0xF878, 0xFF80 ); - rtl8168_mac_ocp_write( tp, 0xF87A, 0x7100 ); - rtl8168_mac_ocp_write( tp, 0xF87C, 0x4892 ); - rtl8168_mac_ocp_write( tp, 0xF87E, 0x4813 ); - rtl8168_mac_ocp_write( tp, 0xF880, 0x8900 ); - rtl8168_mac_ocp_write( tp, 0xF882, 0xE00A ); - rtl8168_mac_ocp_write( tp, 0xF884, 0x7100 ); - rtl8168_mac_ocp_write( tp, 0xF886, 0x4890 ); - rtl8168_mac_ocp_write( tp, 0xF888, 0x4813 ); - rtl8168_mac_ocp_write( tp, 0xF88A, 0x8900 ); - rtl8168_mac_ocp_write( tp, 0xF88C, 0xC74B ); - rtl8168_mac_ocp_write( tp, 0xF88E, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF890, 0x48C2 ); - rtl8168_mac_ocp_write( tp, 0xF892, 0x4841 ); - rtl8168_mac_ocp_write( tp, 0xF894, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF896, 0xC746 ); - rtl8168_mac_ocp_write( tp, 0xF898, 0x74FC ); - rtl8168_mac_ocp_write( tp, 0xF89A, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF89C, 0xF120 ); - rtl8168_mac_ocp_write( tp, 0xF89E, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF8A0, 0xF11E ); - rtl8168_mac_ocp_write( tp, 0xF8A2, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF8A4, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF8A6, 0xF01B ); - rtl8168_mac_ocp_write( tp, 0xF8A8, 0x49C6 ); - rtl8168_mac_ocp_write( tp, 0xF8AA, 0xF119 ); - rtl8168_mac_ocp_write( tp, 0xF8AC, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF8AE, 0x49C4 ); - rtl8168_mac_ocp_write( tp, 0xF8B0, 0xF013 ); - rtl8168_mac_ocp_write( tp, 0xF8B2, 0xC536 ); - rtl8168_mac_ocp_write( tp, 0xF8B4, 0x74B0 ); - rtl8168_mac_ocp_write( tp, 0xF8B6, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF8B8, 0xF1FD ); - rtl8168_mac_ocp_write( tp, 0xF8BA, 0xC537 ); - rtl8168_mac_ocp_write( tp, 0xF8BC, 0xC434 ); - rtl8168_mac_ocp_write( tp, 0xF8BE, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF8C0, 0xC435 ); - rtl8168_mac_ocp_write( tp, 0xF8C2, 0x1C13 ); - rtl8168_mac_ocp_write( tp, 0xF8C4, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xF8C6, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xF8C8, 0xC52B ); - rtl8168_mac_ocp_write( tp, 0xF8CA, 0x74B0 ); - rtl8168_mac_ocp_write( tp, 0xF8CC, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF8CE, 0xF1FD ); - rtl8168_mac_ocp_write( tp, 0xF8D0, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF8D2, 0x48C4 ); - rtl8168_mac_ocp_write( tp, 0xF8D4, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF8D6, 0x7100 ); - rtl8168_mac_ocp_write( tp, 0xF8D8, 0x4893 ); - rtl8168_mac_ocp_write( tp, 0xF8DA, 0x8900 ); - rtl8168_mac_ocp_write( tp, 0xF8DC, 0xFF80 ); - rtl8168_mac_ocp_write( tp, 0xF8DE, 0xC520 ); - rtl8168_mac_ocp_write( tp, 0xF8E0, 0x74B0 ); - rtl8168_mac_ocp_write( tp, 0xF8E2, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF8E4, 0xF11C ); - rtl8168_mac_ocp_write( tp, 0xF8E6, 0xC71E ); - rtl8168_mac_ocp_write( tp, 0xF8E8, 0x74FC ); - rtl8168_mac_ocp_write( tp, 0xF8EA, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF8EC, 0xF118 ); - rtl8168_mac_ocp_write( tp, 0xF8EE, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF8F0, 0xF116 ); - rtl8168_mac_ocp_write( tp, 0xF8F2, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF8F4, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF8F6, 0xF013 ); - rtl8168_mac_ocp_write( tp, 0xF8F8, 0x48C3 ); - rtl8168_mac_ocp_write( tp, 0xF8FA, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF8FC, 0xC516 ); - rtl8168_mac_ocp_write( tp, 0xF8FE, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xF900, 0x49CE ); - rtl8168_mac_ocp_write( tp, 0xF902, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xF904, 0xC411 ); - rtl8168_mac_ocp_write( tp, 0xF906, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF908, 0xC411 ); - rtl8168_mac_ocp_write( tp, 0xF90A, 0x1C13 ); - rtl8168_mac_ocp_write( tp, 0xF90C, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xF90E, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xF910, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xF912, 0x49CF ); - rtl8168_mac_ocp_write( tp, 0xF914, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xF916, 0x7100 ); - rtl8168_mac_ocp_write( tp, 0xF918, 0x4891 ); - rtl8168_mac_ocp_write( tp, 0xF91A, 0x8900 ); - rtl8168_mac_ocp_write( tp, 0xF91C, 0xFF80 ); - rtl8168_mac_ocp_write( tp, 0xF91E, 0xE400 ); - rtl8168_mac_ocp_write( tp, 0xF920, 0xD3E0 ); - rtl8168_mac_ocp_write( tp, 0xF922, 0xE000 ); - rtl8168_mac_ocp_write( tp, 0xF924, 0x0481 ); - rtl8168_mac_ocp_write( tp, 0xF926, 0x0C81 ); - rtl8168_mac_ocp_write( tp, 0xF928, 0xDE20 ); - rtl8168_mac_ocp_write( tp, 0xF92A, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xF92C, 0x0992 ); - rtl8168_mac_ocp_write( tp, 0xF92E, 0x1B76 ); - rtl8168_mac_ocp_write( tp, 0xF930, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF932, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF934, 0x059C ); - rtl8168_mac_ocp_write( tp, 0xF936, 0x1B76 ); - rtl8168_mac_ocp_write( tp, 0xF938, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF93A, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF93C, 0x065A ); - rtl8168_mac_ocp_write( tp, 0xF93E, 0xB400 ); - rtl8168_mac_ocp_write( tp, 0xF940, 0x18DE ); - rtl8168_mac_ocp_write( tp, 0xF942, 0x2008 ); - rtl8168_mac_ocp_write( tp, 0xF944, 0x4001 ); - rtl8168_mac_ocp_write( tp, 0xF946, 0xF10F ); - rtl8168_mac_ocp_write( tp, 0xF948, 0x7342 ); - rtl8168_mac_ocp_write( tp, 0xF94A, 0x1880 ); - rtl8168_mac_ocp_write( tp, 0xF94C, 0x2008 ); - rtl8168_mac_ocp_write( tp, 0xF94E, 0x0009 ); - rtl8168_mac_ocp_write( tp, 0xF950, 0x4018 ); - rtl8168_mac_ocp_write( tp, 0xF952, 0xF109 ); - rtl8168_mac_ocp_write( tp, 0xF954, 0x7340 ); - rtl8168_mac_ocp_write( tp, 0xF956, 0x25BC ); - rtl8168_mac_ocp_write( tp, 0xF958, 0x130F ); - rtl8168_mac_ocp_write( tp, 0xF95A, 0xF105 ); - rtl8168_mac_ocp_write( tp, 0xF95C, 0xC00A ); - rtl8168_mac_ocp_write( tp, 0xF95E, 0x7300 ); - rtl8168_mac_ocp_write( tp, 0xF960, 0x4831 ); - rtl8168_mac_ocp_write( tp, 0xF962, 0x9B00 ); - rtl8168_mac_ocp_write( tp, 0xF964, 0xB000 ); - rtl8168_mac_ocp_write( tp, 0xF966, 0x7340 ); - rtl8168_mac_ocp_write( tp, 0xF968, 0x8320 ); - rtl8168_mac_ocp_write( tp, 0xF96A, 0xC302 ); - rtl8168_mac_ocp_write( tp, 0xF96C, 0xBB00 ); - rtl8168_mac_ocp_write( tp, 0xF96E, 0x0C12 ); - rtl8168_mac_ocp_write( tp, 0xF970, 0xE860 ); - rtl8168_mac_ocp_write( tp, 0xF972, 0xC406 ); - rtl8168_mac_ocp_write( tp, 0xF974, 0x7580 ); - rtl8168_mac_ocp_write( tp, 0xF976, 0x4851 ); - rtl8168_mac_ocp_write( tp, 0xF978, 0x8D80 ); - rtl8168_mac_ocp_write( tp, 0xF97A, 0xC403 ); - rtl8168_mac_ocp_write( tp, 0xF97C, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF97E, 0xD3E0 ); - rtl8168_mac_ocp_write( tp, 0xF980, 0x02C8 ); - rtl8168_mac_ocp_write( tp, 0xF982, 0xC406 ); - rtl8168_mac_ocp_write( tp, 0xF984, 0x7580 ); - rtl8168_mac_ocp_write( tp, 0xF986, 0x4850 ); - rtl8168_mac_ocp_write( tp, 0xF988, 0x8D80 ); - rtl8168_mac_ocp_write( tp, 0xF98A, 0xC403 ); - rtl8168_mac_ocp_write( tp, 0xF98C, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF98E, 0xD3E0 ); - rtl8168_mac_ocp_write( tp, 0xF990, 0x0298 ); - - rtl8168_mac_ocp_write( tp, 0xDE30, 0x0080 ); - - rtl8168_mac_ocp_write( tp, 0xFC26, 0x8000 ); - - rtl8168_mac_ocp_write( tp, 0xFC28, 0x0075 ); - rtl8168_mac_ocp_write( tp, 0xFC2A, 0x02B1 ); - rtl8168_mac_ocp_write( tp, 0xFC2C, 0x0991 ); - rtl8168_mac_ocp_write( tp, 0xFC2E, 0x059B ); - rtl8168_mac_ocp_write( tp, 0xFC30, 0x0659 ); - rtl8168_mac_ocp_write( tp, 0xFC32, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFC34, 0x02C7 ); - rtl8168_mac_ocp_write( tp, 0xFC36, 0x0279 ); -} - -static void -rtl8168_set_mac_mcu_8168gu_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - rtl8168_hw_disable_mac_mcu_bps(dev); - - rtl8168_mac_ocp_write( tp, 0xF800, 0xE008 ); - rtl8168_mac_ocp_write( tp, 0xF802, 0xE011 ); - rtl8168_mac_ocp_write( tp, 0xF804, 0xE015 ); - rtl8168_mac_ocp_write( tp, 0xF806, 0xE018 ); - rtl8168_mac_ocp_write( tp, 0xF808, 0xE01B ); - rtl8168_mac_ocp_write( tp, 0xF80A, 0xE027 ); - rtl8168_mac_ocp_write( tp, 0xF80C, 0xE043 ); - rtl8168_mac_ocp_write( tp, 0xF80E, 0xE065 ); - rtl8168_mac_ocp_write( tp, 0xF810, 0x49E2 ); - rtl8168_mac_ocp_write( tp, 0xF812, 0xF005 ); - rtl8168_mac_ocp_write( tp, 0xF814, 0x49EA ); - rtl8168_mac_ocp_write( tp, 0xF816, 0xF003 ); - rtl8168_mac_ocp_write( tp, 0xF818, 0xC404 ); - rtl8168_mac_ocp_write( tp, 0xF81A, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF81C, 0xC403 ); - rtl8168_mac_ocp_write( tp, 0xF81E, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF820, 0x0496 ); - rtl8168_mac_ocp_write( tp, 0xF822, 0x051A ); - rtl8168_mac_ocp_write( tp, 0xF824, 0x1D01 ); - rtl8168_mac_ocp_write( tp, 0xF826, 0x8DE8 ); - rtl8168_mac_ocp_write( tp, 0xF828, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF82A, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF82C, 0x0206 ); - rtl8168_mac_ocp_write( tp, 0xF82E, 0x1B76 ); - rtl8168_mac_ocp_write( tp, 0xF830, 0xC202 ); - rtl8168_mac_ocp_write( tp, 0xF832, 0xBA00 ); - rtl8168_mac_ocp_write( tp, 0xF834, 0x058A ); - rtl8168_mac_ocp_write( tp, 0xF836, 0x1B76 ); - rtl8168_mac_ocp_write( tp, 0xF838, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF83A, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF83C, 0x0648 ); - rtl8168_mac_ocp_write( tp, 0xF83E, 0x74E6 ); - rtl8168_mac_ocp_write( tp, 0xF840, 0x1B78 ); - rtl8168_mac_ocp_write( tp, 0xF842, 0x46DC ); - rtl8168_mac_ocp_write( tp, 0xF844, 0x1300 ); - rtl8168_mac_ocp_write( tp, 0xF846, 0xF005 ); - rtl8168_mac_ocp_write( tp, 0xF848, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF84A, 0x48C3 ); - rtl8168_mac_ocp_write( tp, 0xF84C, 0x48C4 ); - rtl8168_mac_ocp_write( tp, 0xF84E, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF850, 0x64E7 ); - rtl8168_mac_ocp_write( tp, 0xF852, 0xC302 ); - rtl8168_mac_ocp_write( tp, 0xF854, 0xBB00 ); - rtl8168_mac_ocp_write( tp, 0xF856, 0x068E ); - rtl8168_mac_ocp_write( tp, 0xF858, 0x74E4 ); - rtl8168_mac_ocp_write( tp, 0xF85A, 0x49C5 ); - rtl8168_mac_ocp_write( tp, 0xF85C, 0xF106 ); - rtl8168_mac_ocp_write( tp, 0xF85E, 0x49C6 ); - rtl8168_mac_ocp_write( tp, 0xF860, 0xF107 ); - rtl8168_mac_ocp_write( tp, 0xF862, 0x48C8 ); - rtl8168_mac_ocp_write( tp, 0xF864, 0x48C9 ); - rtl8168_mac_ocp_write( tp, 0xF866, 0xE011 ); - rtl8168_mac_ocp_write( tp, 0xF868, 0x48C9 ); - rtl8168_mac_ocp_write( tp, 0xF86A, 0x4848 ); - rtl8168_mac_ocp_write( tp, 0xF86C, 0xE00E ); - rtl8168_mac_ocp_write( tp, 0xF86E, 0x4848 ); - rtl8168_mac_ocp_write( tp, 0xF870, 0x49C7 ); - rtl8168_mac_ocp_write( tp, 0xF872, 0xF00A ); - rtl8168_mac_ocp_write( tp, 0xF874, 0x48C9 ); - rtl8168_mac_ocp_write( tp, 0xF876, 0xC60D ); - rtl8168_mac_ocp_write( tp, 0xF878, 0x1D1F ); - rtl8168_mac_ocp_write( tp, 0xF87A, 0x8DC2 ); - rtl8168_mac_ocp_write( tp, 0xF87C, 0x1D00 ); - rtl8168_mac_ocp_write( tp, 0xF87E, 0x8DC3 ); - rtl8168_mac_ocp_write( tp, 0xF880, 0x1D11 ); - rtl8168_mac_ocp_write( tp, 0xF882, 0x8DC0 ); - rtl8168_mac_ocp_write( tp, 0xF884, 0xE002 ); - rtl8168_mac_ocp_write( tp, 0xF886, 0x4849 ); - rtl8168_mac_ocp_write( tp, 0xF888, 0x94E5 ); - rtl8168_mac_ocp_write( tp, 0xF88A, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF88C, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF88E, 0x0238 ); - rtl8168_mac_ocp_write( tp, 0xF890, 0xE434 ); - rtl8168_mac_ocp_write( tp, 0xF892, 0x49D9 ); - rtl8168_mac_ocp_write( tp, 0xF894, 0xF01B ); - rtl8168_mac_ocp_write( tp, 0xF896, 0xC31E ); - rtl8168_mac_ocp_write( tp, 0xF898, 0x7464 ); - rtl8168_mac_ocp_write( tp, 0xF89A, 0x49C4 ); - rtl8168_mac_ocp_write( tp, 0xF89C, 0xF114 ); - rtl8168_mac_ocp_write( tp, 0xF89E, 0xC31B ); - rtl8168_mac_ocp_write( tp, 0xF8A0, 0x6460 ); - rtl8168_mac_ocp_write( tp, 0xF8A2, 0x14FA ); - rtl8168_mac_ocp_write( tp, 0xF8A4, 0xFA02 ); - rtl8168_mac_ocp_write( tp, 0xF8A6, 0xE00F ); - rtl8168_mac_ocp_write( tp, 0xF8A8, 0xC317 ); - rtl8168_mac_ocp_write( tp, 0xF8AA, 0x7460 ); - rtl8168_mac_ocp_write( tp, 0xF8AC, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF8AE, 0xF10B ); - rtl8168_mac_ocp_write( tp, 0xF8B0, 0xC311 ); - rtl8168_mac_ocp_write( tp, 0xF8B2, 0x7462 ); - rtl8168_mac_ocp_write( tp, 0xF8B4, 0x48C1 ); - rtl8168_mac_ocp_write( tp, 0xF8B6, 0x9C62 ); - rtl8168_mac_ocp_write( tp, 0xF8B8, 0x4841 ); - rtl8168_mac_ocp_write( tp, 0xF8BA, 0x9C62 ); - rtl8168_mac_ocp_write( tp, 0xF8BC, 0xC30A ); - rtl8168_mac_ocp_write( tp, 0xF8BE, 0x1C04 ); - rtl8168_mac_ocp_write( tp, 0xF8C0, 0x8C60 ); - rtl8168_mac_ocp_write( tp, 0xF8C2, 0xE004 ); - rtl8168_mac_ocp_write( tp, 0xF8C4, 0x1C15 ); - rtl8168_mac_ocp_write( tp, 0xF8C6, 0xC305 ); - rtl8168_mac_ocp_write( tp, 0xF8C8, 0x8C60 ); - rtl8168_mac_ocp_write( tp, 0xF8CA, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF8CC, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF8CE, 0x0374 ); - rtl8168_mac_ocp_write( tp, 0xF8D0, 0xE434 ); - rtl8168_mac_ocp_write( tp, 0xF8D2, 0xE030 ); - rtl8168_mac_ocp_write( tp, 0xF8D4, 0xE61C ); - rtl8168_mac_ocp_write( tp, 0xF8D6, 0xE906 ); - rtl8168_mac_ocp_write( tp, 0xF8D8, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF8DA, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF8DC, 0x0000 ); - - rtl8168_mac_ocp_write( tp, 0xFC26, 0x8000 ); - - rtl8168_mac_ocp_write( tp, 0xFC28, 0x0493 ); - rtl8168_mac_ocp_write( tp, 0xFC2A, 0x0205 ); - rtl8168_mac_ocp_write( tp, 0xFC2C, 0x0589 ); - rtl8168_mac_ocp_write( tp, 0xFC2E, 0x0647 ); - rtl8168_mac_ocp_write( tp, 0xFC30, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFC32, 0x0215 ); - rtl8168_mac_ocp_write( tp, 0xFC34, 0x0285 ); -} - -static void -rtl8168_set_mac_mcu_8168gu_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - rtl8168_hw_disable_mac_mcu_bps(dev); - - rtl8168_mac_ocp_write( tp, 0xF800, 0xE008 ); - rtl8168_mac_ocp_write( tp, 0xF802, 0xE00A ); - rtl8168_mac_ocp_write( tp, 0xF804, 0xE00D ); - rtl8168_mac_ocp_write( tp, 0xF806, 0xE02F ); - rtl8168_mac_ocp_write( tp, 0xF808, 0xE031 ); - rtl8168_mac_ocp_write( tp, 0xF80A, 0xE038 ); - rtl8168_mac_ocp_write( tp, 0xF80C, 0xE03A ); - rtl8168_mac_ocp_write( tp, 0xF80E, 0xE051 ); - rtl8168_mac_ocp_write( tp, 0xF810, 0xC202 ); - rtl8168_mac_ocp_write( tp, 0xF812, 0xBA00 ); - rtl8168_mac_ocp_write( tp, 0xF814, 0x0DFC ); - rtl8168_mac_ocp_write( tp, 0xF816, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xF818, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF81A, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF81C, 0x0A30 ); - rtl8168_mac_ocp_write( tp, 0xF81E, 0x49D9 ); - rtl8168_mac_ocp_write( tp, 0xF820, 0xF019 ); - rtl8168_mac_ocp_write( tp, 0xF822, 0xC520 ); - rtl8168_mac_ocp_write( tp, 0xF824, 0x64A5 ); - rtl8168_mac_ocp_write( tp, 0xF826, 0x1400 ); - rtl8168_mac_ocp_write( tp, 0xF828, 0xF007 ); - rtl8168_mac_ocp_write( tp, 0xF82A, 0x0C01 ); - rtl8168_mac_ocp_write( tp, 0xF82C, 0x8CA5 ); - rtl8168_mac_ocp_write( tp, 0xF82E, 0x1C15 ); - rtl8168_mac_ocp_write( tp, 0xF830, 0xC515 ); - rtl8168_mac_ocp_write( tp, 0xF832, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF834, 0xE00F ); - rtl8168_mac_ocp_write( tp, 0xF836, 0xC513 ); - rtl8168_mac_ocp_write( tp, 0xF838, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF83A, 0x48C8 ); - rtl8168_mac_ocp_write( tp, 0xF83C, 0x48CA ); - rtl8168_mac_ocp_write( tp, 0xF83E, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF840, 0xC510 ); - rtl8168_mac_ocp_write( tp, 0xF842, 0x1B00 ); - rtl8168_mac_ocp_write( tp, 0xF844, 0x9BA0 ); - rtl8168_mac_ocp_write( tp, 0xF846, 0x1B1C ); - rtl8168_mac_ocp_write( tp, 0xF848, 0x483F ); - rtl8168_mac_ocp_write( tp, 0xF84A, 0x9BA2 ); - rtl8168_mac_ocp_write( tp, 0xF84C, 0x1B04 ); - rtl8168_mac_ocp_write( tp, 0xF84E, 0xC506 ); - rtl8168_mac_ocp_write( tp, 0xF850, 0x9BA0 ); - rtl8168_mac_ocp_write( tp, 0xF852, 0xC603 ); - rtl8168_mac_ocp_write( tp, 0xF854, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF856, 0x0298 ); - rtl8168_mac_ocp_write( tp, 0xF858, 0x03DE ); - rtl8168_mac_ocp_write( tp, 0xF85A, 0xE434 ); - rtl8168_mac_ocp_write( tp, 0xF85C, 0xE096 ); - rtl8168_mac_ocp_write( tp, 0xF85E, 0xE860 ); - rtl8168_mac_ocp_write( tp, 0xF860, 0xDE20 ); - rtl8168_mac_ocp_write( tp, 0xF862, 0xD3C0 ); - rtl8168_mac_ocp_write( tp, 0xF864, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF866, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF868, 0x0A64 ); - rtl8168_mac_ocp_write( tp, 0xF86A, 0xC707 ); - rtl8168_mac_ocp_write( tp, 0xF86C, 0x1D00 ); - rtl8168_mac_ocp_write( tp, 0xF86E, 0x8DE2 ); - rtl8168_mac_ocp_write( tp, 0xF870, 0x48C1 ); - rtl8168_mac_ocp_write( tp, 0xF872, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF874, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF876, 0x00AA ); - rtl8168_mac_ocp_write( tp, 0xF878, 0xE0C0 ); - rtl8168_mac_ocp_write( tp, 0xF87A, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF87C, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF87E, 0x0132 ); - rtl8168_mac_ocp_write( tp, 0xF880, 0xC50C ); - rtl8168_mac_ocp_write( tp, 0xF882, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xF884, 0x49CE ); - rtl8168_mac_ocp_write( tp, 0xF886, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xF888, 0x1C00 ); - rtl8168_mac_ocp_write( tp, 0xF88A, 0x9EA0 ); - rtl8168_mac_ocp_write( tp, 0xF88C, 0x1C1C ); - rtl8168_mac_ocp_write( tp, 0xF88E, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xF890, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xF892, 0xC402 ); - rtl8168_mac_ocp_write( tp, 0xF894, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF896, 0x0AFA ); - rtl8168_mac_ocp_write( tp, 0xF898, 0xDE20 ); - rtl8168_mac_ocp_write( tp, 0xF89A, 0xE000 ); - rtl8168_mac_ocp_write( tp, 0xF89C, 0xE092 ); - rtl8168_mac_ocp_write( tp, 0xF89E, 0xE430 ); - rtl8168_mac_ocp_write( tp, 0xF8A0, 0xDE20 ); - rtl8168_mac_ocp_write( tp, 0xF8A2, 0xE0C0 ); - rtl8168_mac_ocp_write( tp, 0xF8A4, 0xE860 ); - rtl8168_mac_ocp_write( tp, 0xF8A6, 0xE84C ); - rtl8168_mac_ocp_write( tp, 0xF8A8, 0xB400 ); - rtl8168_mac_ocp_write( tp, 0xF8AA, 0xB430 ); - rtl8168_mac_ocp_write( tp, 0xF8AC, 0xE410 ); - rtl8168_mac_ocp_write( tp, 0xF8AE, 0xC0AE ); - rtl8168_mac_ocp_write( tp, 0xF8B0, 0xB407 ); - rtl8168_mac_ocp_write( tp, 0xF8B2, 0xB406 ); - rtl8168_mac_ocp_write( tp, 0xF8B4, 0xB405 ); - rtl8168_mac_ocp_write( tp, 0xF8B6, 0xB404 ); - rtl8168_mac_ocp_write( tp, 0xF8B8, 0xB403 ); - rtl8168_mac_ocp_write( tp, 0xF8BA, 0xB402 ); - rtl8168_mac_ocp_write( tp, 0xF8BC, 0xB401 ); - rtl8168_mac_ocp_write( tp, 0xF8BE, 0xC7EE ); - rtl8168_mac_ocp_write( tp, 0xF8C0, 0x76F4 ); - rtl8168_mac_ocp_write( tp, 0xF8C2, 0xC2ED ); - rtl8168_mac_ocp_write( tp, 0xF8C4, 0xC3ED ); - rtl8168_mac_ocp_write( tp, 0xF8C6, 0xC1EF ); - rtl8168_mac_ocp_write( tp, 0xF8C8, 0xC5F3 ); - rtl8168_mac_ocp_write( tp, 0xF8CA, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF8CC, 0x49CD ); - rtl8168_mac_ocp_write( tp, 0xF8CE, 0xF001 ); - rtl8168_mac_ocp_write( tp, 0xF8D0, 0xC5EE ); - rtl8168_mac_ocp_write( tp, 0xF8D2, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF8D4, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF8D6, 0xF105 ); - rtl8168_mac_ocp_write( tp, 0xF8D8, 0xC5E4 ); - rtl8168_mac_ocp_write( tp, 0xF8DA, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xF8DC, 0x49CE ); - rtl8168_mac_ocp_write( tp, 0xF8DE, 0xF00B ); - rtl8168_mac_ocp_write( tp, 0xF8E0, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xF8E2, 0x484B ); - rtl8168_mac_ocp_write( tp, 0xF8E4, 0x9C44 ); - rtl8168_mac_ocp_write( tp, 0xF8E6, 0x1C10 ); - rtl8168_mac_ocp_write( tp, 0xF8E8, 0x9C62 ); - rtl8168_mac_ocp_write( tp, 0xF8EA, 0x1C11 ); - rtl8168_mac_ocp_write( tp, 0xF8EC, 0x8C60 ); - rtl8168_mac_ocp_write( tp, 0xF8EE, 0x1C00 ); - rtl8168_mac_ocp_write( tp, 0xF8F0, 0x9CF6 ); - rtl8168_mac_ocp_write( tp, 0xF8F2, 0xE0EC ); - rtl8168_mac_ocp_write( tp, 0xF8F4, 0x49E7 ); - rtl8168_mac_ocp_write( tp, 0xF8F6, 0xF016 ); - rtl8168_mac_ocp_write( tp, 0xF8F8, 0x1D80 ); - rtl8168_mac_ocp_write( tp, 0xF8FA, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xF8FC, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF8FE, 0x4843 ); - rtl8168_mac_ocp_write( tp, 0xF900, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF902, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF904, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF906, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xF908, 0x48C8 ); - rtl8168_mac_ocp_write( tp, 0xF90A, 0x48C9 ); - rtl8168_mac_ocp_write( tp, 0xF90C, 0x48CA ); - rtl8168_mac_ocp_write( tp, 0xF90E, 0x9C44 ); - rtl8168_mac_ocp_write( tp, 0xF910, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF912, 0x4844 ); - rtl8168_mac_ocp_write( tp, 0xF914, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF916, 0x1E01 ); - rtl8168_mac_ocp_write( tp, 0xF918, 0xE8DB ); - rtl8168_mac_ocp_write( tp, 0xF91A, 0x7420 ); - rtl8168_mac_ocp_write( tp, 0xF91C, 0x48C1 ); - rtl8168_mac_ocp_write( tp, 0xF91E, 0x9C20 ); - rtl8168_mac_ocp_write( tp, 0xF920, 0xE0D5 ); - rtl8168_mac_ocp_write( tp, 0xF922, 0x49E6 ); - rtl8168_mac_ocp_write( tp, 0xF924, 0xF02A ); - rtl8168_mac_ocp_write( tp, 0xF926, 0x1D40 ); - rtl8168_mac_ocp_write( tp, 0xF928, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xF92A, 0x74FC ); - rtl8168_mac_ocp_write( tp, 0xF92C, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF92E, 0xF124 ); - rtl8168_mac_ocp_write( tp, 0xF930, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF932, 0xF122 ); - rtl8168_mac_ocp_write( tp, 0xF934, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF936, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF938, 0xF01F ); - rtl8168_mac_ocp_write( tp, 0xF93A, 0xE8D3 ); - rtl8168_mac_ocp_write( tp, 0xF93C, 0x48C4 ); - rtl8168_mac_ocp_write( tp, 0xF93E, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF940, 0x1E00 ); - rtl8168_mac_ocp_write( tp, 0xF942, 0xE8C6 ); - rtl8168_mac_ocp_write( tp, 0xF944, 0xC5B1 ); - rtl8168_mac_ocp_write( tp, 0xF946, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF948, 0x49C3 ); - rtl8168_mac_ocp_write( tp, 0xF94A, 0xF016 ); - rtl8168_mac_ocp_write( tp, 0xF94C, 0xC5AF ); - rtl8168_mac_ocp_write( tp, 0xF94E, 0x74A4 ); - rtl8168_mac_ocp_write( tp, 0xF950, 0x49C2 ); - rtl8168_mac_ocp_write( tp, 0xF952, 0xF005 ); - rtl8168_mac_ocp_write( tp, 0xF954, 0xC5AA ); - rtl8168_mac_ocp_write( tp, 0xF956, 0x74B2 ); - rtl8168_mac_ocp_write( tp, 0xF958, 0x49C9 ); - rtl8168_mac_ocp_write( tp, 0xF95A, 0xF10E ); - rtl8168_mac_ocp_write( tp, 0xF95C, 0xC5A6 ); - rtl8168_mac_ocp_write( tp, 0xF95E, 0x74A8 ); - rtl8168_mac_ocp_write( tp, 0xF960, 0x4845 ); - rtl8168_mac_ocp_write( tp, 0xF962, 0x4846 ); - rtl8168_mac_ocp_write( tp, 0xF964, 0x4847 ); - rtl8168_mac_ocp_write( tp, 0xF966, 0x4848 ); - rtl8168_mac_ocp_write( tp, 0xF968, 0x9CA8 ); - rtl8168_mac_ocp_write( tp, 0xF96A, 0x74B2 ); - rtl8168_mac_ocp_write( tp, 0xF96C, 0x4849 ); - rtl8168_mac_ocp_write( tp, 0xF96E, 0x9CB2 ); - rtl8168_mac_ocp_write( tp, 0xF970, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF972, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xF974, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF976, 0xE0AA ); - rtl8168_mac_ocp_write( tp, 0xF978, 0x49E4 ); - rtl8168_mac_ocp_write( tp, 0xF97A, 0xF018 ); - rtl8168_mac_ocp_write( tp, 0xF97C, 0x1D10 ); - rtl8168_mac_ocp_write( tp, 0xF97E, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xF980, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF982, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF984, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF986, 0x4843 ); - rtl8168_mac_ocp_write( tp, 0xF988, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF98A, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF98C, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF98E, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF990, 0x4844 ); - rtl8168_mac_ocp_write( tp, 0xF992, 0x4842 ); - rtl8168_mac_ocp_write( tp, 0xF994, 0x4841 ); - rtl8168_mac_ocp_write( tp, 0xF996, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF998, 0x1E01 ); - rtl8168_mac_ocp_write( tp, 0xF99A, 0xE89A ); - rtl8168_mac_ocp_write( tp, 0xF99C, 0x7420 ); - rtl8168_mac_ocp_write( tp, 0xF99E, 0x4841 ); - rtl8168_mac_ocp_write( tp, 0xF9A0, 0x9C20 ); - rtl8168_mac_ocp_write( tp, 0xF9A2, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xF9A4, 0x4848 ); - rtl8168_mac_ocp_write( tp, 0xF9A6, 0x9C44 ); - rtl8168_mac_ocp_write( tp, 0xF9A8, 0xE091 ); - rtl8168_mac_ocp_write( tp, 0xF9AA, 0x49E5 ); - rtl8168_mac_ocp_write( tp, 0xF9AC, 0xF03E ); - rtl8168_mac_ocp_write( tp, 0xF9AE, 0x1D20 ); - rtl8168_mac_ocp_write( tp, 0xF9B0, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xF9B2, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF9B4, 0x48C2 ); - rtl8168_mac_ocp_write( tp, 0xF9B6, 0x4841 ); - rtl8168_mac_ocp_write( tp, 0xF9B8, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF9BA, 0x1E01 ); - rtl8168_mac_ocp_write( tp, 0xF9BC, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xF9BE, 0x49CA ); - rtl8168_mac_ocp_write( tp, 0xF9C0, 0xF103 ); - rtl8168_mac_ocp_write( tp, 0xF9C2, 0x49C2 ); - rtl8168_mac_ocp_write( tp, 0xF9C4, 0xF00C ); - rtl8168_mac_ocp_write( tp, 0xF9C6, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF9C8, 0xF004 ); - rtl8168_mac_ocp_write( tp, 0xF9CA, 0x6447 ); - rtl8168_mac_ocp_write( tp, 0xF9CC, 0x2244 ); - rtl8168_mac_ocp_write( tp, 0xF9CE, 0xE002 ); - rtl8168_mac_ocp_write( tp, 0xF9D0, 0x1C01 ); - rtl8168_mac_ocp_write( tp, 0xF9D2, 0x9C62 ); - rtl8168_mac_ocp_write( tp, 0xF9D4, 0x1C11 ); - rtl8168_mac_ocp_write( tp, 0xF9D6, 0x8C60 ); - rtl8168_mac_ocp_write( tp, 0xF9D8, 0x1C00 ); - rtl8168_mac_ocp_write( tp, 0xF9DA, 0x9CF6 ); - rtl8168_mac_ocp_write( tp, 0xF9DC, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xF9DE, 0x49C8 ); - rtl8168_mac_ocp_write( tp, 0xF9E0, 0xF01D ); - rtl8168_mac_ocp_write( tp, 0xF9E2, 0x74FC ); - rtl8168_mac_ocp_write( tp, 0xF9E4, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF9E6, 0xF11A ); - rtl8168_mac_ocp_write( tp, 0xF9E8, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xF9EA, 0xF118 ); - rtl8168_mac_ocp_write( tp, 0xF9EC, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF9EE, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF9F0, 0xF015 ); - rtl8168_mac_ocp_write( tp, 0xF9F2, 0x49C6 ); - rtl8168_mac_ocp_write( tp, 0xF9F4, 0xF113 ); - rtl8168_mac_ocp_write( tp, 0xF9F6, 0xE875 ); - rtl8168_mac_ocp_write( tp, 0xF9F8, 0x48C4 ); - rtl8168_mac_ocp_write( tp, 0xF9FA, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF9FC, 0x7420 ); - rtl8168_mac_ocp_write( tp, 0xF9FE, 0x48C1 ); - rtl8168_mac_ocp_write( tp, 0xFA00, 0x9C20 ); - rtl8168_mac_ocp_write( tp, 0xFA02, 0xC50A ); - rtl8168_mac_ocp_write( tp, 0xFA04, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFA06, 0x8CA5 ); - rtl8168_mac_ocp_write( tp, 0xFA08, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xFA0A, 0xC505 ); - rtl8168_mac_ocp_write( tp, 0xFA0C, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xFA0E, 0x1C11 ); - rtl8168_mac_ocp_write( tp, 0xFA10, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xFA12, 0xE00A ); - rtl8168_mac_ocp_write( tp, 0xFA14, 0xE434 ); - rtl8168_mac_ocp_write( tp, 0xFA16, 0xD3C0 ); - rtl8168_mac_ocp_write( tp, 0xFA18, 0xDC00 ); - rtl8168_mac_ocp_write( tp, 0xFA1A, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xFA1C, 0x49CA ); - rtl8168_mac_ocp_write( tp, 0xFA1E, 0xF004 ); - rtl8168_mac_ocp_write( tp, 0xFA20, 0x48CA ); - rtl8168_mac_ocp_write( tp, 0xFA22, 0x9C44 ); - rtl8168_mac_ocp_write( tp, 0xFA24, 0xE855 ); - rtl8168_mac_ocp_write( tp, 0xFA26, 0xE052 ); - rtl8168_mac_ocp_write( tp, 0xFA28, 0x49E8 ); - rtl8168_mac_ocp_write( tp, 0xFA2A, 0xF024 ); - rtl8168_mac_ocp_write( tp, 0xFA2C, 0x1D01 ); - rtl8168_mac_ocp_write( tp, 0xFA2E, 0x8DF5 ); - rtl8168_mac_ocp_write( tp, 0xFA30, 0x7440 ); - rtl8168_mac_ocp_write( tp, 0xFA32, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xFA34, 0xF11E ); - rtl8168_mac_ocp_write( tp, 0xFA36, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xFA38, 0x49C8 ); - rtl8168_mac_ocp_write( tp, 0xFA3A, 0xF01B ); - rtl8168_mac_ocp_write( tp, 0xFA3C, 0x49CA ); - rtl8168_mac_ocp_write( tp, 0xFA3E, 0xF119 ); - rtl8168_mac_ocp_write( tp, 0xFA40, 0xC5EC ); - rtl8168_mac_ocp_write( tp, 0xFA42, 0x76A4 ); - rtl8168_mac_ocp_write( tp, 0xFA44, 0x49E3 ); - rtl8168_mac_ocp_write( tp, 0xFA46, 0xF015 ); - rtl8168_mac_ocp_write( tp, 0xFA48, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xFA4A, 0xF103 ); - rtl8168_mac_ocp_write( tp, 0xFA4C, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xFA4E, 0xF011 ); - rtl8168_mac_ocp_write( tp, 0xFA50, 0x4849 ); - rtl8168_mac_ocp_write( tp, 0xFA52, 0x9C44 ); - rtl8168_mac_ocp_write( tp, 0xFA54, 0x1C00 ); - rtl8168_mac_ocp_write( tp, 0xFA56, 0x9CF6 ); - rtl8168_mac_ocp_write( tp, 0xFA58, 0x7444 ); - rtl8168_mac_ocp_write( tp, 0xFA5A, 0x49C1 ); - rtl8168_mac_ocp_write( tp, 0xFA5C, 0xF004 ); - rtl8168_mac_ocp_write( tp, 0xFA5E, 0x6446 ); - rtl8168_mac_ocp_write( tp, 0xFA60, 0x1E07 ); - rtl8168_mac_ocp_write( tp, 0xFA62, 0xE003 ); - rtl8168_mac_ocp_write( tp, 0xFA64, 0x1C01 ); - rtl8168_mac_ocp_write( tp, 0xFA66, 0x1E03 ); - rtl8168_mac_ocp_write( tp, 0xFA68, 0x9C62 ); - rtl8168_mac_ocp_write( tp, 0xFA6A, 0x1C11 ); - rtl8168_mac_ocp_write( tp, 0xFA6C, 0x8C60 ); - rtl8168_mac_ocp_write( tp, 0xFA6E, 0xE830 ); - rtl8168_mac_ocp_write( tp, 0xFA70, 0xE02D ); - rtl8168_mac_ocp_write( tp, 0xFA72, 0x49E9 ); - rtl8168_mac_ocp_write( tp, 0xFA74, 0xF004 ); - rtl8168_mac_ocp_write( tp, 0xFA76, 0x1D02 ); - rtl8168_mac_ocp_write( tp, 0xFA78, 0x8DF5 ); - rtl8168_mac_ocp_write( tp, 0xFA7A, 0xE79C ); - rtl8168_mac_ocp_write( tp, 0xFA7C, 0x49E3 ); - rtl8168_mac_ocp_write( tp, 0xFA7E, 0xF006 ); - rtl8168_mac_ocp_write( tp, 0xFA80, 0x1D08 ); - rtl8168_mac_ocp_write( tp, 0xFA82, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xFA84, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xFA86, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xFA88, 0xE73A ); - rtl8168_mac_ocp_write( tp, 0xFA8A, 0x49E1 ); - rtl8168_mac_ocp_write( tp, 0xFA8C, 0xF007 ); - rtl8168_mac_ocp_write( tp, 0xFA8E, 0x1D02 ); - rtl8168_mac_ocp_write( tp, 0xFA90, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xFA92, 0x1E01 ); - rtl8168_mac_ocp_write( tp, 0xFA94, 0xE7A7 ); - rtl8168_mac_ocp_write( tp, 0xFA96, 0xDE20 ); - rtl8168_mac_ocp_write( tp, 0xFA98, 0xE410 ); - rtl8168_mac_ocp_write( tp, 0xFA9A, 0x49E0 ); - rtl8168_mac_ocp_write( tp, 0xFA9C, 0xF017 ); - rtl8168_mac_ocp_write( tp, 0xFA9E, 0x1D01 ); - rtl8168_mac_ocp_write( tp, 0xFAA0, 0x8DF4 ); - rtl8168_mac_ocp_write( tp, 0xFAA2, 0xC5FA ); - rtl8168_mac_ocp_write( tp, 0xFAA4, 0x1C00 ); - rtl8168_mac_ocp_write( tp, 0xFAA6, 0x8CA0 ); - rtl8168_mac_ocp_write( tp, 0xFAA8, 0x1C1B ); - rtl8168_mac_ocp_write( tp, 0xFAAA, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xFAAC, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFAAE, 0x49CF ); - rtl8168_mac_ocp_write( tp, 0xFAB0, 0xF0FE ); - rtl8168_mac_ocp_write( tp, 0xFAB2, 0xC5F3 ); - rtl8168_mac_ocp_write( tp, 0xFAB4, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xFAB6, 0x4849 ); - rtl8168_mac_ocp_write( tp, 0xFAB8, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xFABA, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xFABC, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xFABE, 0xF006 ); - rtl8168_mac_ocp_write( tp, 0xFAC0, 0x48C3 ); - rtl8168_mac_ocp_write( tp, 0xFAC2, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xFAC4, 0xE820 ); - rtl8168_mac_ocp_write( tp, 0xFAC6, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xFAC8, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xFACA, 0xC432 ); - rtl8168_mac_ocp_write( tp, 0xFACC, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xFACE, 0xC5E4 ); - rtl8168_mac_ocp_write( tp, 0xFAD0, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFAD2, 0x49CE ); - rtl8168_mac_ocp_write( tp, 0xFAD4, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xFAD6, 0x9EA0 ); - rtl8168_mac_ocp_write( tp, 0xFAD8, 0x1C1C ); - rtl8168_mac_ocp_write( tp, 0xFADA, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xFADC, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xFADE, 0xFF80 ); - rtl8168_mac_ocp_write( tp, 0xFAE0, 0xB404 ); - rtl8168_mac_ocp_write( tp, 0xFAE2, 0xB405 ); - rtl8168_mac_ocp_write( tp, 0xFAE4, 0xC5D9 ); - rtl8168_mac_ocp_write( tp, 0xFAE6, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFAE8, 0x49CE ); - rtl8168_mac_ocp_write( tp, 0xFAEA, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xFAEC, 0xC41F ); - rtl8168_mac_ocp_write( tp, 0xFAEE, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xFAF0, 0xC41C ); - rtl8168_mac_ocp_write( tp, 0xFAF2, 0x1C13 ); - rtl8168_mac_ocp_write( tp, 0xFAF4, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xFAF6, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xFAF8, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFAFA, 0x49CF ); - rtl8168_mac_ocp_write( tp, 0xFAFC, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xFAFE, 0xB005 ); - rtl8168_mac_ocp_write( tp, 0xFB00, 0xB004 ); - rtl8168_mac_ocp_write( tp, 0xFB02, 0xFF80 ); - rtl8168_mac_ocp_write( tp, 0xFB04, 0xB404 ); - rtl8168_mac_ocp_write( tp, 0xFB06, 0xB405 ); - rtl8168_mac_ocp_write( tp, 0xFB08, 0xC5C7 ); - rtl8168_mac_ocp_write( tp, 0xFB0A, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFB0C, 0x49CE ); - rtl8168_mac_ocp_write( tp, 0xFB0E, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xFB10, 0xC40E ); - rtl8168_mac_ocp_write( tp, 0xFB12, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xFB14, 0xC40A ); - rtl8168_mac_ocp_write( tp, 0xFB16, 0x1C13 ); - rtl8168_mac_ocp_write( tp, 0xFB18, 0x484F ); - rtl8168_mac_ocp_write( tp, 0xFB1A, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xFB1C, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xFB1E, 0x49CF ); - rtl8168_mac_ocp_write( tp, 0xFB20, 0xF1FE ); - rtl8168_mac_ocp_write( tp, 0xFB22, 0xB005 ); - rtl8168_mac_ocp_write( tp, 0xFB24, 0xB004 ); - rtl8168_mac_ocp_write( tp, 0xFB26, 0xFF80 ); - rtl8168_mac_ocp_write( tp, 0xFB28, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFB2A, 0x0481 ); - rtl8168_mac_ocp_write( tp, 0xFB2C, 0x0C81 ); - rtl8168_mac_ocp_write( tp, 0xFB2E, 0x0AE0 ); - - - rtl8168_mac_ocp_write( tp, 0xFC26, 0x8000 ); - - rtl8168_mac_ocp_write( tp, 0xFC28, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFC2A, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFC2C, 0x0297 ); - rtl8168_mac_ocp_write( tp, 0xFC2E, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFC30, 0x00A9 ); - rtl8168_mac_ocp_write( tp, 0xFC32, 0x012D ); - rtl8168_mac_ocp_write( tp, 0xFC34, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xFC36, 0x08DF ); -} - -static void -rtl8168_set_mac_mcu_8411b_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - rtl8168_hw_disable_mac_mcu_bps(dev); - - rtl8168_mac_ocp_write( tp, 0xF800, 0xE008 ); - rtl8168_mac_ocp_write( tp, 0xF802, 0xE00A ); - rtl8168_mac_ocp_write( tp, 0xF804, 0xE00C ); - rtl8168_mac_ocp_write( tp, 0xF806, 0xE00E ); - rtl8168_mac_ocp_write( tp, 0xF808, 0xE027 ); - rtl8168_mac_ocp_write( tp, 0xF80A, 0xE04F ); - rtl8168_mac_ocp_write( tp, 0xF80C, 0xE05E ); - rtl8168_mac_ocp_write( tp, 0xF80E, 0xE065 ); - rtl8168_mac_ocp_write( tp, 0xF810, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF812, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF814, 0x0000 ); - rtl8168_mac_ocp_write( tp, 0xF816, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF818, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF81A, 0x074C ); - rtl8168_mac_ocp_write( tp, 0xF81C, 0xC302 ); - rtl8168_mac_ocp_write( tp, 0xF81E, 0xBB00 ); - rtl8168_mac_ocp_write( tp, 0xF820, 0x080A ); - rtl8168_mac_ocp_write( tp, 0xF822, 0x6420 ); - rtl8168_mac_ocp_write( tp, 0xF824, 0x48C2 ); - rtl8168_mac_ocp_write( tp, 0xF826, 0x8C20 ); - rtl8168_mac_ocp_write( tp, 0xF828, 0xC516 ); - rtl8168_mac_ocp_write( tp, 0xF82A, 0x64A4 ); - rtl8168_mac_ocp_write( tp, 0xF82C, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF82E, 0xF009 ); - rtl8168_mac_ocp_write( tp, 0xF830, 0x74A2 ); - rtl8168_mac_ocp_write( tp, 0xF832, 0x8CA5 ); - rtl8168_mac_ocp_write( tp, 0xF834, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF836, 0xC50E ); - rtl8168_mac_ocp_write( tp, 0xF838, 0x9CA2 ); - rtl8168_mac_ocp_write( tp, 0xF83A, 0x1C11 ); - rtl8168_mac_ocp_write( tp, 0xF83C, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF83E, 0xE006 ); - rtl8168_mac_ocp_write( tp, 0xF840, 0x74F8 ); - rtl8168_mac_ocp_write( tp, 0xF842, 0x48C4 ); - rtl8168_mac_ocp_write( tp, 0xF844, 0x8CF8 ); - rtl8168_mac_ocp_write( tp, 0xF846, 0xC404 ); - rtl8168_mac_ocp_write( tp, 0xF848, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF84A, 0xC403 ); - rtl8168_mac_ocp_write( tp, 0xF84C, 0xBC00 ); - rtl8168_mac_ocp_write( tp, 0xF84E, 0x0BF2 ); - rtl8168_mac_ocp_write( tp, 0xF850, 0x0C0A ); - rtl8168_mac_ocp_write( tp, 0xF852, 0xE434 ); - rtl8168_mac_ocp_write( tp, 0xF854, 0xD3C0 ); - rtl8168_mac_ocp_write( tp, 0xF856, 0x49D9 ); - rtl8168_mac_ocp_write( tp, 0xF858, 0xF01F ); - rtl8168_mac_ocp_write( tp, 0xF85A, 0xC526 ); - rtl8168_mac_ocp_write( tp, 0xF85C, 0x64A5 ); - rtl8168_mac_ocp_write( tp, 0xF85E, 0x1400 ); - rtl8168_mac_ocp_write( tp, 0xF860, 0xF007 ); - rtl8168_mac_ocp_write( tp, 0xF862, 0x0C01 ); - rtl8168_mac_ocp_write( tp, 0xF864, 0x8CA5 ); - rtl8168_mac_ocp_write( tp, 0xF866, 0x1C15 ); - rtl8168_mac_ocp_write( tp, 0xF868, 0xC51B ); - rtl8168_mac_ocp_write( tp, 0xF86A, 0x9CA0 ); - rtl8168_mac_ocp_write( tp, 0xF86C, 0xE013 ); - rtl8168_mac_ocp_write( tp, 0xF86E, 0xC519 ); - rtl8168_mac_ocp_write( tp, 0xF870, 0x74A0 ); - rtl8168_mac_ocp_write( tp, 0xF872, 0x48C4 ); - rtl8168_mac_ocp_write( tp, 0xF874, 0x8CA0 ); - rtl8168_mac_ocp_write( tp, 0xF876, 0xC516 ); - rtl8168_mac_ocp_write( tp, 0xF878, 0x74A4 ); - rtl8168_mac_ocp_write( tp, 0xF87A, 0x48C8 ); - rtl8168_mac_ocp_write( tp, 0xF87C, 0x48CA ); - rtl8168_mac_ocp_write( tp, 0xF87E, 0x9CA4 ); - rtl8168_mac_ocp_write( tp, 0xF880, 0xC512 ); - rtl8168_mac_ocp_write( tp, 0xF882, 0x1B00 ); - rtl8168_mac_ocp_write( tp, 0xF884, 0x9BA0 ); - rtl8168_mac_ocp_write( tp, 0xF886, 0x1B1C ); - rtl8168_mac_ocp_write( tp, 0xF888, 0x483F ); - rtl8168_mac_ocp_write( tp, 0xF88A, 0x9BA2 ); - rtl8168_mac_ocp_write( tp, 0xF88C, 0x1B04 ); - rtl8168_mac_ocp_write( tp, 0xF88E, 0xC508 ); - rtl8168_mac_ocp_write( tp, 0xF890, 0x9BA0 ); - rtl8168_mac_ocp_write( tp, 0xF892, 0xC505 ); - rtl8168_mac_ocp_write( tp, 0xF894, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF896, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF898, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF89A, 0x0300 ); - rtl8168_mac_ocp_write( tp, 0xF89C, 0x051E ); - rtl8168_mac_ocp_write( tp, 0xF89E, 0xE434 ); - rtl8168_mac_ocp_write( tp, 0xF8A0, 0xE018 ); - rtl8168_mac_ocp_write( tp, 0xF8A2, 0xE092 ); - rtl8168_mac_ocp_write( tp, 0xF8A4, 0xDE20 ); - rtl8168_mac_ocp_write( tp, 0xF8A6, 0xD3C0 ); - rtl8168_mac_ocp_write( tp, 0xF8A8, 0xC50F ); - rtl8168_mac_ocp_write( tp, 0xF8AA, 0x76A4 ); - rtl8168_mac_ocp_write( tp, 0xF8AC, 0x49E3 ); - rtl8168_mac_ocp_write( tp, 0xF8AE, 0xF007 ); - rtl8168_mac_ocp_write( tp, 0xF8B0, 0x49C0 ); - rtl8168_mac_ocp_write( tp, 0xF8B2, 0xF103 ); - rtl8168_mac_ocp_write( tp, 0xF8B4, 0xC607 ); - rtl8168_mac_ocp_write( tp, 0xF8B6, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF8B8, 0xC606 ); - rtl8168_mac_ocp_write( tp, 0xF8BA, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF8BC, 0xC602 ); - rtl8168_mac_ocp_write( tp, 0xF8BE, 0xBE00 ); - rtl8168_mac_ocp_write( tp, 0xF8C0, 0x0C4C ); - rtl8168_mac_ocp_write( tp, 0xF8C2, 0x0C28 ); - rtl8168_mac_ocp_write( tp, 0xF8C4, 0x0C2C ); - rtl8168_mac_ocp_write( tp, 0xF8C6, 0xDC00 ); - rtl8168_mac_ocp_write( tp, 0xF8C8, 0xC707 ); - rtl8168_mac_ocp_write( tp, 0xF8CA, 0x1D00 ); - rtl8168_mac_ocp_write( tp, 0xF8CC, 0x8DE2 ); - rtl8168_mac_ocp_write( tp, 0xF8CE, 0x48C1 ); - rtl8168_mac_ocp_write( tp, 0xF8D0, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF8D2, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF8D4, 0x00AA ); - rtl8168_mac_ocp_write( tp, 0xF8D6, 0xE0C0 ); - rtl8168_mac_ocp_write( tp, 0xF8D8, 0xC502 ); - rtl8168_mac_ocp_write( tp, 0xF8DA, 0xBD00 ); - rtl8168_mac_ocp_write( tp, 0xF8DC, 0x0132 ); - - rtl8168_mac_ocp_write( tp, 0xFC26, 0x8000 ); - - rtl8168_mac_ocp_write( tp, 0xFC2A, 0x0743 ); - rtl8168_mac_ocp_write( tp, 0xFC2C, 0x0801 ); - rtl8168_mac_ocp_write( tp, 0xFC2E, 0x0BE9 ); - rtl8168_mac_ocp_write( tp, 0xFC30, 0x02FD ); - rtl8168_mac_ocp_write( tp, 0xFC32, 0x0C25 ); - rtl8168_mac_ocp_write( tp, 0xFC34, 0x00A9 ); - rtl8168_mac_ocp_write( tp, 0xFC36, 0x012D ); -} - -static void -rtl8168_set_mac_mcu_8168ep_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8168ep_1[] = { - 0xE008, 0xE0D3, 0xE0D6, 0xE0D9, 0xE0DB, 0xE0DD, 0xE0DF, 0xE0E1, 0xC251, - 0x7340, 0x49B1, 0xF010, 0x1D02, 0x8D40, 0xC202, 0xBA00, 0x2C3A, 0xC0F0, - 0xE8DE, 0x2000, 0x8000, 0xC0B6, 0x268C, 0x752C, 0x49D4, 0xF112, 0xE025, - 0xC2F6, 0x7146, 0xC2F5, 0x7340, 0x49BE, 0xF103, 0xC7F2, 0xE002, 0xC7F1, - 0x304F, 0x6226, 0x49A1, 0xF1F0, 0x7222, 0x49A0, 0xF1ED, 0x2525, 0x1F28, - 0x3097, 0x3091, 0x9A36, 0x752C, 0x21DC, 0x25BC, 0xC6E2, 0x77C0, 0x1304, - 0xF014, 0x1303, 0xF014, 0x1302, 0xF014, 0x1301, 0xF014, 0x49D4, 0xF103, - 0xC3D7, 0xBB00, 0xC618, 0x67C6, 0x752E, 0x22D7, 0x26DD, 0x1505, 0xF013, - 0xC60A, 0xBE00, 0xC309, 0xBB00, 0xC308, 0xBB00, 0xC307, 0xBB00, 0xC306, - 0xBB00, 0x25C8, 0x25A6, 0x25AC, 0x25B2, 0x25B8, 0xCD08, 0x0000, 0xC0BC, - 0xC2FF, 0x7340, 0x49B0, 0xF04E, 0x1F46, 0x308F, 0xC3F7, 0x1C04, 0xE84D, - 0x1401, 0xF147, 0x7226, 0x49A7, 0xF044, 0x7222, 0x2525, 0x1F30, 0x3097, - 0x3091, 0x7340, 0xC4EA, 0x401C, 0xF006, 0xC6E8, 0x75C0, 0x49D7, 0xF105, - 0xE036, 0x1D08, 0x8DC1, 0x0208, 0x6640, 0x2764, 0x1606, 0xF12F, 0x6346, - 0x133B, 0xF12C, 0x9B34, 0x1B18, 0x3093, 0xC32A, 0x1C10, 0xE82A, 0x1401, - 0xF124, 0x1A36, 0x308A, 0x7322, 0x25B5, 0x0B0E, 0x1C00, 0xE82C, 0xC71F, - 0x4027, 0xF11A, 0xE838, 0x1F42, 0x308F, 0x1B08, 0xE824, 0x7236, 0x7746, - 0x1700, 0xF00D, 0xC313, 0x401F, 0xF103, 0x1F00, 0x9F46, 0x7744, 0x449F, - 0x445F, 0xE817, 0xC70A, 0x4027, 0xF105, 0xC302, 0xBB00, 0x2E08, 0x2DC2, - 0xC7FF, 0xBF00, 0xCDB8, 0xFFFF, 0x0C02, 0xA554, 0xA5DC, 0x402F, 0xF105, - 0x1400, 0xF1FA, 0x1C01, 0xE002, 0x1C00, 0xFF80, 0x49B0, 0xF004, 0x0B01, - 0xA1D3, 0xE003, 0x0B02, 0xA5D3, 0x3127, 0x3720, 0x0B02, 0xA5D3, 0x3127, - 0x3720, 0x1300, 0xF1FB, 0xFF80, 0x7322, 0x25B5, 0x1E28, 0x30DE, 0x30D9, - 0x7264, 0x1E11, 0x2368, 0x3116, 0xFF80, 0x1B7E, 0xC602, 0xBE00, 0x06A6, - 0x1B7E, 0xC602, 0xBE00, 0x0764, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, - 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, - 0x0000 - }; - - rtl8168_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168ep_1); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168ep_1[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x2549); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x06A5); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x0763); -} - -static void -rtl8168_set_mac_mcu_8168ep_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8168ep_2[] = { - 0xE008, 0xE017, 0xE052, 0xE056, 0xE058, 0xE05A, 0xE05C, 0xE05E, 0xC50F, - 0x76A4, 0x49E3, 0xF007, 0x49C0, 0xF103, 0xC607, 0xBE00, 0xC606, 0xBE00, - 0xC602, 0xBE00, 0x0BDA, 0x0BB6, 0x0BBA, 0xDC00, 0xB400, 0xB401, 0xB402, - 0xB403, 0xB404, 0xC02E, 0x7206, 0x49AE, 0xF1FE, 0xC12B, 0x9904, 0xC12A, - 0x9906, 0x7206, 0x49AE, 0xF1FE, 0x7200, 0x49A0, 0xF117, 0xC123, 0xC223, - 0xC323, 0xE808, 0xC322, 0xE806, 0xC321, 0xE804, 0xC320, 0xE802, 0xE00C, - 0x740E, 0x49CE, 0xF1FE, 0x9908, 0x990A, 0x9A0C, 0x9B0E, 0x740E, 0x49CE, - 0xF1FE, 0xFF80, 0xB004, 0xB003, 0xB002, 0xB001, 0xB000, 0xC604, 0xC002, - 0xB800, 0x1FC8, 0xE000, 0xE8E0, 0xF128, 0x0002, 0xFFFF, 0xF000, 0x8001, - 0x8002, 0x8003, 0x8004, 0x48C1, 0x48C2, 0xC502, 0xBD00, 0x0490, 0xC602, - 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, - 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, - }; - - rtl8168_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168ep_2); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168ep_2[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x0BB3); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x1FC7); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x0485); -} - -static void -rtl8168_set_mac_mcu_8168h_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8168h_1[] = { - 0xE008, 0xE00F, 0xE011, 0xE047, 0xE049, 0xE073, 0xE075, 0xE079, 0xC707, - 0x1D00, 0x8DE2, 0x48C1, 0xC502, 0xBD00, 0x00E4, 0xE0C0, 0xC502, 0xBD00, - 0x0216, 0xC634, 0x75C0, 0x49D3, 0xF027, 0xC631, 0x75C0, 0x49D3, 0xF123, - 0xC627, 0x75C0, 0xB405, 0xC525, 0x9DC0, 0xC621, 0x75C8, 0x49D5, 0xF00A, - 0x49D6, 0xF008, 0x49D7, 0xF006, 0x49D8, 0xF004, 0x75D2, 0x49D9, 0xF111, - 0xC517, 0x9DC8, 0xC516, 0x9DD2, 0xC618, 0x75C0, 0x49D4, 0xF003, 0x49D0, - 0xF104, 0xC60A, 0xC50E, 0x9DC0, 0xB005, 0xC607, 0x9DC0, 0xB007, 0xC602, - 0xBE00, 0x1A06, 0xB400, 0xE86C, 0xA000, 0x01E1, 0x0200, 0x9200, 0xE84C, - 0xE004, 0xE908, 0xC502, 0xBD00, 0x0B58, 0xB407, 0xB404, 0x2195, 0x25BD, - 0x9BE0, 0x1C1C, 0x484F, 0x9CE2, 0x72E2, 0x49AE, 0xF1FE, 0x0B00, 0xF116, - 0xC71C, 0xC419, 0x9CE0, 0x1C13, 0x484F, 0x9CE2, 0x74E2, 0x49CE, 0xF1FE, - 0xC412, 0x9CE0, 0x1C13, 0x484F, 0x9CE2, 0x74E2, 0x49CE, 0xF1FE, 0xC70C, - 0x74F8, 0x48C3, 0x8CF8, 0xB004, 0xB007, 0xC502, 0xBD00, 0x0F24, 0x0481, - 0x0C81, 0xDE24, 0xE000, 0xC602, 0xBE00, 0x0CA4, 0x48C1, 0x48C2, 0xC502, - 0xBD00, 0x0578, 0xC602, 0xBE00, 0x0000 - }; - - rtl8168_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168h_1); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168h_1[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x00E2); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x0210); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x1A04); - rtl8168_mac_ocp_write(tp, 0xFC2E, 0x0B26); - rtl8168_mac_ocp_write(tp, 0xFC30, 0x0F02); - rtl8168_mac_ocp_write(tp, 0xFC32, 0x0CA0); - rtl8168_mac_ocp_write(tp, 0xFC34, 0x056C); - - rtl8168_mac_ocp_write(tp, 0xFC38, 0x007F); -} - -static void -rtl8168_set_mac_mcu_8168fp_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 i; - u16 breakPointEnabled = 0; - - rtl8168_hw_disable_mac_mcu_bps(dev); - - if(tp->HwPkgDet == 0x00 || tp->HwPkgDet == 0x0F) { - static const u16 mcu_patch_code_8168fp_1_1[] = { - 0xE00A, 0xE0C1, 0xE104, 0xE108, 0xE10D, 0xE112, 0xE11C, 0xE121, 0xE000, - 0xE0C8, 0xB400, 0xC1FE, 0x49E2, 0xF04C, 0x49EA, 0xF04A, 0x74E6, 0xC246, - 0x7542, 0x73EC, 0x1800, 0x49C0, 0xF10D, 0x49C1, 0xF10B, 0x49C2, 0xF109, - 0x49B0, 0xF107, 0x49B1, 0xF105, 0x7220, 0x49A2, 0xF102, 0xE002, 0x4800, - 0x49D0, 0xF10A, 0x49D1, 0xF108, 0x49D2, 0xF106, 0x49D3, 0xF104, 0x49DF, - 0xF102, 0xE00C, 0x4801, 0x72E4, 0x49AD, 0xF108, 0xC225, 0x6741, 0x48F0, - 0x8F41, 0x4870, 0x8F41, 0xC7CF, 0x49B5, 0xF01F, 0x49B2, 0xF00B, 0x4980, - 0xF003, 0x484E, 0x94E7, 0x4981, 0xF004, 0x485E, 0xC212, 0x9543, 0xE071, - 0x49B6, 0xF003, 0x49B3, 0xF10F, 0x4980, 0xF003, 0x484E, 0x94E7, 0x4981, - 0xF004, 0x485E, 0xC204, 0x9543, 0xE005, 0xE000, 0xE0FC, 0xE0FA, 0xE065, - 0x49B7, 0xF007, 0x4980, 0xF005, 0x1A38, 0x46D4, 0x1200, 0xF109, 0x4981, - 0xF055, 0x49C3, 0xF105, 0x1A30, 0x46D5, 0x1200, 0xF04F, 0x7220, 0x49A2, - 0xF130, 0x49C1, 0xF12E, 0x49B0, 0xF12C, 0xC2E6, 0x7240, 0x49A8, 0xF003, - 0x49D0, 0xF126, 0x49A9, 0xF003, 0x49D1, 0xF122, 0x49AA, 0xF003, 0x49D2, - 0xF11E, 0x49AB, 0xF003, 0x49DF, 0xF11A, 0x49AC, 0xF003, 0x49D3, 0xF116, - 0x4980, 0xF003, 0x49C7, 0xF105, 0x4981, 0xF02C, 0x49D7, 0xF02A, 0x49C0, - 0xF00C, 0xC721, 0x62F4, 0x49A0, 0xF008, 0x49A4, 0xF106, 0x4824, 0x8AF4, - 0xC71A, 0x1A40, 0x9AE0, 0x49B6, 0xF017, 0x200E, 0xC7B8, 0x72E0, 0x4710, - 0x92E1, 0xC70E, 0x77E0, 0x49F0, 0xF112, 0xC70B, 0x77E0, 0x27FE, 0x1AFA, - 0x4317, 0xC705, 0x9AE2, 0x1A11, 0x8AE0, 0xE008, 0xE41C, 0xC0AE, 0xD23A, - 0xC7A2, 0x74E6, 0x484F, 0x94E7, 0xC79E, 0x8CE6, 0x8BEC, 0xC29C, 0x8D42, - 0x7220, 0xB000, 0xC502, 0xBD00, 0x0932, 0xB400, 0xC240, 0xC340, 0x7060, - 0x498F, 0xF014, 0x488F, 0x9061, 0x744C, 0x49C3, 0xF004, 0x7562, 0x485E, - 0x9563, 0x7446, 0x49C3, 0xF106, 0x7562, 0x1C30, 0x46E5, 0x1200, 0xF004, - 0x7446, 0x484F, 0x9447, 0xC32A, 0x7466, 0x49C0, 0xF00F, 0x48C0, 0x9C66, - 0x7446, 0x4840, 0x4841, 0x4842, 0x9C46, 0x744C, 0x4840, 0x9C4C, 0x744A, - 0x484A, 0x9C4A, 0xE013, 0x498E, 0xF011, 0x488E, 0x9061, 0x744C, 0x49C3, - 0xF004, 0x7446, 0x484E, 0x9447, 0x7446, 0x1D38, 0x46EC, 0x1500, 0xF004, - 0x7446, 0x484F, 0x9447, 0xB000, 0xC502, 0xBD00, 0x074C, 0xE000, 0xE0FC, - 0xE0C0, 0x4830, 0x4837, 0xC502, 0xBD00, 0x0978, 0x63E2, 0x4830, 0x4837, - 0xC502, 0xBD00, 0x09FE, 0x73E2, 0x4830, 0x8BE2, 0xC302, 0xBB00, 0x0A12, - 0x73E2, 0x48B0, 0x48B3, 0x48B4, 0x48B5, 0x48B6, 0x48B7, 0x8BE2, 0xC302, - 0xBB00, 0x0A5A, 0x73E2, 0x4830, 0x8BE2, 0xC302, 0xBB00, 0x0A6C, 0x73E2, - 0x4830, 0x4837, 0xC502, 0xBD00, 0x0A86 - }; - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168fp_1_1); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168fp_1_1[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x0890); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x0712); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x0974); - rtl8168_mac_ocp_write(tp, 0xFC2E, 0x09FC); - rtl8168_mac_ocp_write(tp, 0xFC30, 0x0A0E); - rtl8168_mac_ocp_write(tp, 0xFC32, 0x0A56); - rtl8168_mac_ocp_write(tp, 0xFC34, 0x0A68); - rtl8168_mac_ocp_write(tp, 0xFC36, 0x0A84); - - } else if (tp->HwPkgDet == 0x6) { - static const u16 mcu_patch_code_8168fp_1_2[] = { - 0xE008, 0xE00A, 0xE031, 0xE033, 0xE035, 0xE144, 0xE166, 0xE168, 0xC502, - 0xBD00, 0x0000, 0xC725, 0x75E0, 0x48D0, 0x9DE0, 0xC722, 0x75E0, 0x1C78, - 0x416C, 0x1530, 0xF111, 0xC71D, 0x75F6, 0x49D1, 0xF00D, 0x75E0, 0x1C1F, - 0x416C, 0x1502, 0xF108, 0x75FA, 0x49D3, 0xF005, 0x75EC, 0x9DE4, 0x4853, - 0x9DFA, 0xC70B, 0x75E0, 0x4852, 0x4850, 0x9DE0, 0xC602, 0xBE00, 0x04B8, - 0xE420, 0xE000, 0xE0FC, 0xE43C, 0xDC00, 0xEB00, 0xC202, 0xBA00, 0x0000, - 0xC002, 0xB800, 0x0000, 0xB401, 0xB402, 0xB403, 0xB404, 0xB405, 0xB406, - 0xC44D, 0xC54D, 0x1867, 0xE8A2, 0x2318, 0x276E, 0x1601, 0xF106, 0x1A07, - 0xE861, 0xE86B, 0xE873, 0xE037, 0x231E, 0x276E, 0x1602, 0xF10B, 0x1A07, - 0xE858, 0xE862, 0xC247, 0xC344, 0xE8E3, 0xC73B, 0x66E0, 0xE8B5, 0xE029, - 0x231A, 0x276C, 0xC733, 0x9EE0, 0x1866, 0xE885, 0x251C, 0x120F, 0xF011, - 0x1209, 0xF011, 0x2014, 0x240E, 0x1000, 0xF007, 0x120C, 0xF00D, 0x1203, - 0xF00D, 0x1200, 0xF00D, 0x120C, 0xF00D, 0x1203, 0xF00D, 0x1A03, 0xE00C, - 0x1A07, 0xE00A, 0x1A00, 0xE008, 0x1A01, 0xE006, 0x1A02, 0xE004, 0x1A04, - 0xE002, 0x1A05, 0xE829, 0xE833, 0xB006, 0xB005, 0xB004, 0xB003, 0xB002, - 0xB001, 0x60C4, 0xC702, 0xBF00, 0x2786, 0xDD00, 0xD030, 0xE0C4, 0xE0F8, - 0xDC42, 0xD3F0, 0x0000, 0x0004, 0x0007, 0x0014, 0x0090, 0x1000, 0x0F00, - 0x1004, 0x1008, 0x3000, 0x3004, 0x3008, 0x4000, 0x7777, 0x8000, 0x8001, - 0x8008, 0x8003, 0x8004, 0xC000, 0xC004, 0xF004, 0xFFFF, 0xB406, 0xB407, - 0xC6E5, 0x77C0, 0x27F3, 0x23F3, 0x47FA, 0x9FC0, 0xB007, 0xB006, 0xFF80, - 0xB405, 0xB407, 0xC7D8, 0x75E0, 0x48D0, 0x9DE0, 0xB007, 0xB005, 0xFF80, - 0xB401, 0xC0EA, 0xC2DC, 0xC3D8, 0xE865, 0xC0D3, 0xC1E0, 0xC2E3, 0xE861, - 0xE817, 0xC0CD, 0xC2CF, 0xE85D, 0xC0C9, 0xC1D6, 0xC2DB, 0xE859, 0xE80F, - 0xC1C7, 0xC2CE, 0xE855, 0xC0C0, 0xC1D1, 0xC2D3, 0xE851, 0xE807, 0xC0BE, - 0xC2C2, 0xE84D, 0xE803, 0xB001, 0xFF80, 0xB402, 0xC2C6, 0xE859, 0x499F, - 0xF1FE, 0xB002, 0xFF80, 0xB402, 0xB403, 0xB407, 0xE821, 0x8882, 0x1980, - 0x8983, 0xE81D, 0x7180, 0x218B, 0x25BB, 0x1310, 0xF014, 0x1310, 0xFB03, - 0x1F20, 0x38FB, 0x3288, 0x434B, 0x2491, 0x430B, 0x1F0F, 0x38FB, 0x4313, - 0x2121, 0x4353, 0x2521, 0x418A, 0x6282, 0x2527, 0x212F, 0x418A, 0xB007, - 0xB003, 0xB002, 0xFF80, 0x6183, 0x2496, 0x1100, 0xF1FD, 0xFF80, 0x4800, - 0x4801, 0xC213, 0xC313, 0xE815, 0x4860, 0x8EE0, 0xC210, 0xC310, 0xE822, - 0x481E, 0xC20C, 0xC30C, 0xE80C, 0xC206, 0x7358, 0x483A, 0x9B58, 0xFF80, - 0xE8E0, 0xE000, 0x1008, 0x0F00, 0x800C, 0x0F00, 0xB407, 0xB406, 0xB403, - 0xC7F7, 0x98E0, 0x99E2, 0x9AE4, 0x21B2, 0x4831, 0x483F, 0x9BE6, 0x66E7, - 0x49E6, 0xF1FE, 0xB003, 0xB006, 0xB007, 0xFF80, 0xB407, 0xB406, 0xB403, - 0xC7E5, 0x9AE4, 0x21B2, 0x4831, 0x9BE6, 0x66E7, 0x49E6, 0xF1FE, 0x70E0, - 0x71E2, 0xB003, 0xB006, 0xB007, 0xFF80, 0x4882, 0xB406, 0xB405, 0xC71E, - 0x76E0, 0x1D78, 0x4175, 0x1630, 0xF10C, 0xC715, 0x76E0, 0x4861, 0x9EE0, - 0xC713, 0x1EFF, 0x9EE2, 0x75E0, 0x4850, 0x9DE0, 0xE005, 0xC70B, 0x76E0, - 0x4865, 0x9EE0, 0xB005, 0xB006, 0xC708, 0xC102, 0xB900, 0x279E, 0xEB16, - 0xEB00, 0xE43C, 0xDC00, 0xD3EC, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, - 0x0000 - }; - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168fp_1_2); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168fp_1_2[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x04b4); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC2E, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC30, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC32, 0x279C); - rtl8168_mac_ocp_write(tp, 0xFC34, 0x0000); - rtl8168_mac_ocp_write(tp, 0xFC36, 0x0000); - } - - if (tp->HwPkgDet == 0x00) - breakPointEnabled = 0x00FC; - else if (tp->HwPkgDet == 0x0F) - breakPointEnabled = 0x00FF; - else if (tp->HwPkgDet == 0x06) - breakPointEnabled = 0x0022; - - rtl8168_mac_ocp_write(tp, 0xFC38, breakPointEnabled); -} - -static void -rtl8168_set_mac_mcu_8168fp_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8168fp_2[] = { - 0xE008, 0xE00A, 0xE00F, 0xE014, 0xE05F, 0xE063, 0xE065, 0xE067, 0xC602, - 0xBE00, 0x2AB2, 0x1BC0, 0x46EB, 0x1BFE, 0xC102, 0xB900, 0x0B1A, 0x1BC0, - 0x46EB, 0x1B7E, 0xC102, 0xB900, 0x0BEA, 0xB400, 0xB401, 0xB402, 0xB403, - 0xB404, 0xB405, 0xC03A, 0x7206, 0x49AE, 0xF1FE, 0xC137, 0x9904, 0xC136, - 0x9906, 0x7206, 0x49AE, 0xF1FE, 0x7200, 0x49A0, 0xF10B, 0xC52F, 0xC12E, - 0xC232, 0xC332, 0xE812, 0xC331, 0xE810, 0xC330, 0xE80E, 0xE018, 0xC126, - 0xC229, 0xC525, 0xC328, 0xE808, 0xC523, 0xC326, 0xE805, 0xC521, 0xC324, - 0xE802, 0xE00C, 0x740E, 0x49CE, 0xF1FE, 0x9908, 0x9D0A, 0x9A0C, 0x9B0E, - 0x740E, 0x49CE, 0xF1FE, 0xFF80, 0xB005, 0xB004, 0xB003, 0xB002, 0xB001, - 0xB000, 0xC604, 0xC002, 0xB800, 0x2A5E, 0xE000, 0xE8E0, 0xF128, 0x3DC2, - 0xFFFF, 0x10EC, 0x816A, 0x816D, 0x816C, 0xF000, 0x8002, 0x8004, 0x8007, - 0x48C1, 0x48C2, 0xC502, 0xBD00, 0x07BC, 0xC602, 0xBE00, 0x0000, 0xC602, - 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000 - }; - - rtl8168_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168fp_2); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168fp_2[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x2AAC); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x0B14); - rtl8168_mac_ocp_write(tp, 0xFC2C, 0x0BE4); - rtl8168_mac_ocp_write(tp, 0xFC2E, 0x2A5C); - rtl8168_mac_ocp_write(tp, 0xFC30, 0x07B0); - - if (tp->HwSuppSerDesPhyVer == 1) - rtl8168_mac_ocp_write(tp, 0xFC38, 0x001F); - else - rtl8168_mac_ocp_write(tp, 0xFC38, 0x001E); - -} - -static void -rtl8168_set_mac_mcu_8168fp_3(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 i; - static const u16 mcu_patch_code_8168fp_3[] = { - 0xE008, 0xE053, 0xE057, 0xE059, 0xE05B, 0xE05D, 0xE05F, 0xE061, 0xB400, - 0xB401, 0xB402, 0xB403, 0xB404, 0xB405, 0xC03A, 0x7206, 0x49AE, 0xF1FE, - 0xC137, 0x9904, 0xC136, 0x9906, 0x7206, 0x49AE, 0xF1FE, 0x7200, 0x49A0, - 0xF10B, 0xC52F, 0xC12E, 0xC232, 0xC332, 0xE812, 0xC331, 0xE810, 0xC330, - 0xE80E, 0xE018, 0xC126, 0xC229, 0xC525, 0xC328, 0xE808, 0xC523, 0xC326, - 0xE805, 0xC521, 0xC324, 0xE802, 0xE00C, 0x740E, 0x49CE, 0xF1FE, 0x9908, - 0x9D0A, 0x9A0C, 0x9B0E, 0x740E, 0x49CE, 0xF1FE, 0xFF80, 0xB005, 0xB004, - 0xB003, 0xB002, 0xB001, 0xB000, 0xC604, 0xC002, 0xB800, 0x2B16, 0xE000, - 0xE8E0, 0xF128, 0x3DC2, 0xFFFF, 0x10EC, 0x816A, 0x816D, 0x816C, 0xF000, - 0x8002, 0x8004, 0x8007, 0x48C1, 0x48C2, 0xC502, 0xBD00, 0x07BC, 0xC602, - 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, - 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000, 0xC602, 0xBE00, 0x0000 - }; - - rtl8168_hw_disable_mac_mcu_bps(dev); - - for (i = 0; i < ARRAY_SIZE(mcu_patch_code_8168fp_3); i++) { - rtl8168_mac_ocp_write(tp, 0xF800 + i * 2, mcu_patch_code_8168fp_3[i]); - } - - rtl8168_mac_ocp_write(tp, 0xFC26, 0x8000); - - rtl8168_mac_ocp_write(tp, 0xFC28, 0x2B14); - rtl8168_mac_ocp_write(tp, 0xFC2A, 0x07B0); - - rtl8168_mac_ocp_write(tp, 0xFC38, 0x0003); -} - -static void -rtl8168_hw_mac_mcu_config(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (tp->NotWrMcuPatchCode == TRUE) return; - - switch (tp->mcfg) { - case CFG_METHOD_21: - rtl8168_set_mac_mcu_8168g_1(dev); - break; - case CFG_METHOD_24: - rtl8168_set_mac_mcu_8168gu_1(dev); - break; - case CFG_METHOD_25: - rtl8168_set_mac_mcu_8168gu_2(dev); - break; - case CFG_METHOD_26: - rtl8168_set_mac_mcu_8411b_1(dev); - break; - case CFG_METHOD_27: - rtl8168_set_mac_mcu_8168ep_1(dev); - break; - case CFG_METHOD_28: - rtl8168_set_mac_mcu_8168ep_2(dev); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - rtl8168_set_mac_mcu_8168h_1(dev); - break; - case CFG_METHOD_31: - rtl8168_set_mac_mcu_8168fp_1(dev); - break; - case CFG_METHOD_32: - rtl8168_set_mac_mcu_8168fp_2(dev); - break; - case CFG_METHOD_33: - rtl8168_set_mac_mcu_8168fp_3(dev); - break; - } -} -#endif - -#ifdef ENABLE_USE_FIRMWARE_FILE -static void rtl8168_release_firmware(struct rtl8168_private *tp) -{ - if (tp->rtl_fw) { - rtl8168_fw_release_firmware(tp->rtl_fw); - kfree(tp->rtl_fw); - tp->rtl_fw = NULL; - } -} - -void rtl8168_apply_firmware(struct rtl8168_private *tp) -{ - /* TODO: release firmware if rtl_fw_write_firmware signals failure. */ - if (tp->rtl_fw) { - rtl8168_fw_write_firmware(tp, tp->rtl_fw); - /* At least one firmware doesn't reset tp->ocp_base. */ - tp->ocp_base = OCP_STD_PHY_BASE; - - /* PHY soft reset may still be in progress */ - //phy_read_poll_timeout(tp->phydev, MII_BMCR, val, - // !(val & BMCR_RESET), - // 50000, 600000, true); - rtl8168_wait_phy_reset_complete(tp); - - tp->hw_ram_code_ver = rtl8168_get_hw_phy_mcu_code_ver(tp); - tp->sw_ram_code_ver = tp->hw_ram_code_ver; - tp->HwHasWrRamCodeToMicroP = TRUE; - } -} -#endif - -static void -rtl8168_hw_init(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 csi_tmp; - - if (tp->HwSuppAspmClkIntrLock) { - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - rtl8168_enable_cfg9346_write(tp); - rtl8168_hw_aspm_clkreq_enable(tp, false); - rtl8168_disable_cfg9346_write(tp); - } - - //Disable UPS - if (HW_SUPPORT_UPS_MODE(tp)) - rtl8168_mac_ocp_write(tp, 0xD400, rtl8168_mac_ocp_read( tp, 0xD400) & ~(BIT_0)); - - //Disable DMA Aggregation - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mac_ocp_write(tp, 0xE63E, rtl8168_mac_ocp_read( tp, 0xE63E) & ~(BIT_3 | BIT_2 | BIT_1)); - rtl8168_mac_ocp_write(tp, 0xE63E, rtl8168_mac_ocp_read( tp, 0xE63E) | (BIT_0)); - rtl8168_mac_ocp_write(tp, 0xE63E, rtl8168_mac_ocp_read( tp, 0xE63E) & ~(BIT_0)); - rtl8168_mac_ocp_write(tp, 0xC094, 0x0); - rtl8168_mac_ocp_write(tp, 0xC09E, 0x0); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - RTL_W8(tp, DBG_reg, RTL_R8(tp, DBG_reg) | BIT_1 | BIT_7); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - RTL_W8(tp, 0xF2, (RTL_R8(tp, 0xF2) & ~(BIT_2 | BIT_1 | BIT_0))); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - if (aspm) { - RTL_W8(tp, 0x6E, RTL_R8(tp, 0x6E) | BIT_6); - rtl8168_eri_write(tp, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); - } - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_29: - case CFG_METHOD_30: - if (aspm) { - if ((rtl8168_mac_ocp_read(tp, 0xDC00) & BIT_3) || (RTL_R8(tp, Config0) & 0x07)) { - RTL_W8(tp, 0x6E, RTL_R8(tp, 0x6E) | BIT_6); - rtl8168_eri_write(tp, 0x1AE, 2, 0x0403, ERIAR_ExGMAC); - } - } - break; - } - - if (tp->mcfg == CFG_METHOD_10 || tp->mcfg == CFG_METHOD_14 || tp->mcfg == CFG_METHOD_15) - RTL_W8(tp, 0xF3, RTL_R8(tp, 0xF3) | BIT_2); - -#ifndef ENABLE_USE_FIRMWARE_FILE - if (!tp->rtl_fw) - rtl8168_hw_mac_mcu_config(dev); -#endif - - /*disable ocp phy power saving*/ - if (tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) - if (!tp->dash_printer_enabled) - rtl8168_disable_ocp_phy_power_saving(dev); - - //Set PCIE uncorrectable error status mask pcie 0x108 - csi_tmp = rtl8168_csi_read(tp, 0x108); - csi_tmp |= BIT_20; - rtl8168_csi_write(tp, 0x108, csi_tmp); - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - csi_tmp = rtl8168_eri_read(tp, 0x1AB, 1, ERIAR_ExGMAC); - csi_tmp |= ( BIT_2 | BIT_3 | BIT_4 | BIT_5 | BIT_6 | BIT_7 ); - rtl8168_eri_write(tp, 0x1AB, 1, csi_tmp, ERIAR_ExGMAC); - break; - } - - rtl8168_set_pci_pme(tp, 0); - - if (s0_magic_packet == 1) - rtl8168_enable_magic_packet(dev); - -#ifdef ENABLE_USE_FIRMWARE_FILE - if (tp->rtl_fw && - !(HW_DASH_SUPPORT_TYPE_3(tp) && - tp->HwPkgDet == 0x06)) - rtl8168_apply_firmware(tp); -#endif -} - -static void -rtl8168_hw_ephy_config(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 ephy_data; - - switch (tp->mcfg) { - case CFG_METHOD_4: - /*Set EPHY registers begin*/ - /*Set EPHY register offset 0x02 bit 11 to 0 and bit 12 to 1*/ - ephy_data = rtl8168_ephy_read(tp, 0x02); - ephy_data &= ~BIT_11; - ephy_data |= BIT_12; - rtl8168_ephy_write(tp, 0x02, ephy_data); - - /*Set EPHY register offset 0x03 bit 1 to 1*/ - ephy_data = rtl8168_ephy_read(tp, 0x03); - ephy_data |= (1 << 1); - rtl8168_ephy_write(tp, 0x03, ephy_data); - - /*Set EPHY register offset 0x06 bit 7 to 0*/ - ephy_data = rtl8168_ephy_read(tp, 0x06); - ephy_data &= ~(1 << 7); - rtl8168_ephy_write(tp, 0x06, ephy_data); - /*Set EPHY registers end*/ - - break; - case CFG_METHOD_5: - /* set EPHY registers */ - SetPCIePhyBit(tp, 0x01, BIT_0); - - ClearAndSetPCIePhyBit(tp, - 0x03, - BIT_10, - BIT_5 - ); - - break; - case CFG_METHOD_9: - /* set EPHY registers */ - rtl8168_ephy_write(tp, 0x01, 0x7C7F); - rtl8168_ephy_write(tp, 0x02, 0x011F); - if (tp->eeprom_type != EEPROM_TYPE_NONE) { - ClearAndSetPCIePhyBit(tp, - 0x03, - 0xFFB0, - 0x05B0 - ); - } else { - ClearAndSetPCIePhyBit(tp, - 0x03, - 0xFFF0, - 0x05F0 - ); - } - rtl8168_ephy_write(tp, 0x06, 0xB271); - rtl8168_ephy_write(tp, 0x07, 0xCE00); - - break; - case CFG_METHOD_10: - /* set EPHY registers */ - rtl8168_ephy_write(tp, 0x01, 0x6C7F); - rtl8168_ephy_write(tp, 0x02, 0x011F); - ClearAndSetPCIePhyBit(tp, - 0x03, - 0xFFF0, - 0x01B0 - ); - rtl8168_ephy_write(tp, 0x1A, 0x0546); - rtl8168_ephy_write(tp, 0x1C, 0x80C4); - rtl8168_ephy_write(tp, 0x1D, 0x78E5); - rtl8168_ephy_write(tp, 0x0A, 0x8100); - - break; - case CFG_METHOD_12: - case CFG_METHOD_13: - ephy_data = rtl8168_ephy_read(tp, 0x0B); - rtl8168_ephy_write(tp, 0x0B, ephy_data|0x48); - ephy_data = rtl8168_ephy_read(tp, 0x19); - ephy_data &= ~0x20; - rtl8168_ephy_write(tp, 0x19, ephy_data|0x50); - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~0x100; - rtl8168_ephy_write(tp, 0x0C, ephy_data|0x20); - ephy_data = rtl8168_ephy_read(tp, 0x10); - ephy_data &= ~0x04; - rtl8168_ephy_write(tp, 0x10, ephy_data); - - break; - case CFG_METHOD_14: - case CFG_METHOD_15: - /* set EPHY registers */ - ephy_data = rtl8168_ephy_read(tp, 0x00) & ~0x0200; - ephy_data |= 0x0100; - rtl8168_ephy_write(tp, 0x00, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data |= 0x0004; - rtl8168_ephy_write(tp, 0x00, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x06) & ~0x0002; - ephy_data |= 0x0001; - rtl8168_ephy_write(tp, 0x06, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x06); - ephy_data |= 0x0030; - rtl8168_ephy_write(tp, 0x06, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x07); - ephy_data |= 0x2000; - rtl8168_ephy_write(tp, 0x07, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data |= 0x0020; - rtl8168_ephy_write(tp, 0x00, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x03) & ~0x5800; - ephy_data |= 0x2000; - rtl8168_ephy_write(tp, 0x03, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x03); - ephy_data |= 0x0001; - rtl8168_ephy_write(tp, 0x03, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x01) & ~0x0800; - ephy_data |= 0x1000; - rtl8168_ephy_write(tp, 0x01, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x07); - ephy_data |= 0x4000; - rtl8168_ephy_write(tp, 0x07, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x1E); - ephy_data |= 0x2000; - rtl8168_ephy_write(tp, 0x1E, ephy_data); - - rtl8168_ephy_write(tp, 0x19, 0xFE6C); - - ephy_data = rtl8168_ephy_read(tp, 0x0A); - ephy_data |= 0x0040; - rtl8168_ephy_write(tp, 0x0A, ephy_data); - - break; - case CFG_METHOD_16: - case CFG_METHOD_17: - if (tp->mcfg == CFG_METHOD_16) { - rtl8168_ephy_write(tp, 0x06, 0xF020); - rtl8168_ephy_write(tp, 0x07, 0x01FF); - rtl8168_ephy_write(tp, 0x00, 0x5027); - rtl8168_ephy_write(tp, 0x01, 0x0003); - rtl8168_ephy_write(tp, 0x02, 0x2D16); - rtl8168_ephy_write(tp, 0x03, 0x6D49); - rtl8168_ephy_write(tp, 0x08, 0x0006); - rtl8168_ephy_write(tp, 0x0A, 0x00C8); - } - - ephy_data = rtl8168_ephy_read(tp, 0x09); - ephy_data |= BIT_7; - rtl8168_ephy_write(tp, 0x09, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x19); - ephy_data |= (BIT_2 | BIT_5 | BIT_9); - rtl8168_ephy_write(tp, 0x19, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data |= BIT_3; - rtl8168_ephy_write(tp, 0x00, ephy_data); - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~(BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4); - ephy_data |= BIT_9; - rtl8168_ephy_write(tp, 0x0C, ephy_data); - - break; - case CFG_METHOD_18: - case CFG_METHOD_19: - if (tp->mcfg == CFG_METHOD_18) { - ephy_data = rtl8168_ephy_read(tp, 0x06); - ephy_data |= BIT_5; - ephy_data &= ~(BIT_7 | BIT_6); - rtl8168_ephy_write(tp, 0x06, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x08); - ephy_data |= BIT_1; - ephy_data &= ~BIT_0; - rtl8168_ephy_write(tp, 0x08, ephy_data); - } - - ephy_data = rtl8168_ephy_read(tp, 0x09); - ephy_data |= BIT_7; - rtl8168_ephy_write(tp, 0x09, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x19); - ephy_data |= (BIT_2 | BIT_5 | BIT_9); - rtl8168_ephy_write(tp, 0x19, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data |= BIT_3; - rtl8168_ephy_write(tp, 0x00, ephy_data); - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~(BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4); - ephy_data |= BIT_9; - rtl8168_ephy_write(tp, 0x0C, ephy_data); - - break; - case CFG_METHOD_20: - ephy_data = rtl8168_ephy_read(tp, 0x06); - ephy_data |= BIT_5; - ephy_data &= ~(BIT_7 | BIT_6); - rtl8168_ephy_write(tp, 0x06, ephy_data); - - rtl8168_ephy_write(tp, 0x0f, 0x5200); - - ephy_data = rtl8168_ephy_read(tp, 0x19); - ephy_data |= (BIT_2 | BIT_5 | BIT_9); - rtl8168_ephy_write(tp, 0x19, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data |= BIT_3; - rtl8168_ephy_write(tp, 0x00, ephy_data); - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~(BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4); - ephy_data |= BIT_9; - rtl8168_ephy_write(tp, 0x0C, ephy_data); - - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data &= ~(BIT_3); - rtl8168_ephy_write(tp, 0x00, ephy_data); - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~(BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4); - ephy_data |= (BIT_5 | BIT_11); - rtl8168_ephy_write(tp, 0x0C, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x1E); - ephy_data |= (BIT_0); - rtl8168_ephy_write(tp, 0x1E, ephy_data); - - ephy_data = rtl8168_ephy_read(tp, 0x19); - ephy_data &= ~(BIT_15); - rtl8168_ephy_write(tp, 0x19, ephy_data); - - break; - case CFG_METHOD_25: - ephy_data = rtl8168_ephy_read(tp, 0x00); - ephy_data &= ~BIT_3; - rtl8168_ephy_write(tp, 0x00, ephy_data); - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~(BIT_13 | BIT_12 | BIT_11 | BIT_10| BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4); - ephy_data |= (BIT_5 | BIT_11); - rtl8168_ephy_write(tp, 0x0C, ephy_data); - - rtl8168_ephy_write(tp, 0x19, 0x7C00); - rtl8168_ephy_write(tp, 0x1E, 0x20EB); - rtl8168_ephy_write(tp, 0x0D, 0x1666); - rtl8168_ephy_write(tp, 0x00, 0x10A3); - rtl8168_ephy_write(tp, 0x06, 0xF050); - - SetPCIePhyBit(tp, 0x04, BIT_4); - ClearPCIePhyBit(tp, 0x1D, BIT_14); - - break; - case CFG_METHOD_26: - ClearPCIePhyBit(tp, 0x00, BIT_3); - ClearAndSetPCIePhyBit( tp, - 0x0C, - (BIT_13 | BIT_12 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_4), - (BIT_5 | BIT_11) - ); - SetPCIePhyBit(tp, 0x1E, BIT_0); - ClearPCIePhyBit(tp, 0x19, BIT_15); - - ClearPCIePhyBit(tp, 0x19, (BIT_5 | BIT_0)); - - SetPCIePhyBit(tp, 0x1E, BIT_13); - ClearPCIePhyBit(tp, 0x0D, BIT_8); - SetPCIePhyBit(tp, 0x0D, BIT_9); - SetPCIePhyBit(tp, 0x00, BIT_7); - - SetPCIePhyBit(tp, 0x06, BIT_4); - - SetPCIePhyBit(tp, 0x04, BIT_4); - SetPCIePhyBit(tp, 0x1D, BIT_14); - - break; - case CFG_METHOD_23: - rtl8168_ephy_write(tp, 0x00, 0x10AB); - rtl8168_ephy_write(tp, 0x06, 0xf030); - rtl8168_ephy_write(tp, 0x08, 0x2006); - rtl8168_ephy_write(tp, 0x0D, 0x1666); - - ephy_data = rtl8168_ephy_read(tp, 0x0C); - ephy_data &= ~(BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4); - rtl8168_ephy_write(tp, 0x0C, ephy_data); - - break; - case CFG_METHOD_27: - rtl8168_ephy_write(tp, 0x00, 0x10A3); - rtl8168_ephy_write(tp, 0x19, 0xFC00); - rtl8168_ephy_write(tp, 0x1E, 0x20EA); - - break; - case CFG_METHOD_28: - rtl8168_ephy_write(tp, 0x00, 0x10AB); - rtl8168_ephy_write(tp, 0x19, 0xFC00); - rtl8168_ephy_write(tp, 0x1E, 0x20EB); - rtl8168_ephy_write(tp, 0x0D, 0x1666); - ClearPCIePhyBit(tp, 0x0B, BIT_0); - SetPCIePhyBit(tp, 0x1D, BIT_14); - ClearAndSetPCIePhyBit(tp, - 0x0C, - BIT_13 | BIT_12 | BIT_11 | BIT_10 | BIT_8 | BIT_7 | BIT_6 | BIT_5, - BIT_9 | BIT_4 - ); - - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - ClearPCIePhyBit(tp, 0x1E, BIT_11); - - SetPCIePhyBit(tp, 0x1E, BIT_0); - SetPCIePhyBit(tp, 0x1D, BIT_11); - - rtl8168_ephy_write(tp, 0x05, 0x2089); - rtl8168_ephy_write(tp, 0x06, 0x5881); - - rtl8168_ephy_write(tp, 0x04, 0x854A); - rtl8168_ephy_write(tp, 0x01, 0x068B); - - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - ClearAndSetPCIePhyBit(tp, - 0x19, - BIT_6, - (BIT_12| BIT_8) - ); - ClearAndSetPCIePhyBit(tp, - 0x59, - BIT_6, - (BIT_12| BIT_8) - ); - - ClearPCIePhyBit(tp, 0x0C, BIT_4); - ClearPCIePhyBit(tp, 0x4C, BIT_4); - ClearPCIePhyBit(tp, 0x0B, BIT_0); - - break; - } -} - -static int -rtl8168_set_phy_mcu_patch_request(struct rtl8168_private *tp) -{ - u16 PhyRegValue; - u32 WaitCnt; - int retval = TRUE; - - switch (tp->mcfg) { - case CFG_METHOD_21 ... CFG_METHOD_33: - rtl8168_mdio_write(tp,0x1f, 0x0B82); - rtl8168_set_eth_phy_bit(tp, 0x10, BIT_4); - - rtl8168_mdio_write(tp,0x1f, 0x0B80); - WaitCnt = 0; - do { - PhyRegValue = rtl8168_mdio_read(tp, 0x10); - udelay(100); - WaitCnt++; - } while (!(PhyRegValue & BIT_6) && (WaitCnt < 1000)); - - if (!(PhyRegValue & BIT_6) && (WaitCnt == 1000)) retval = FALSE; - - rtl8168_mdio_write(tp,0x1f, 0x0000); - break; - } - - return retval; -} - -static int -rtl8168_clear_phy_mcu_patch_request(struct rtl8168_private *tp) -{ - u16 PhyRegValue; - u32 WaitCnt; - int retval = TRUE; - - switch (tp->mcfg) { - case CFG_METHOD_21 ... CFG_METHOD_33: - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - rtl8168_clear_eth_phy_bit(tp, 0x10, BIT_4); - - rtl8168_mdio_write(tp,0x1f, 0x0B80); - WaitCnt = 0; - do { - PhyRegValue = rtl8168_mdio_read(tp, 0x10); - udelay(100); - WaitCnt++; - } while ((PhyRegValue & BIT_6) && (WaitCnt < 1000)); - - if ((PhyRegValue & BIT_6) && (WaitCnt == 1000)) retval = FALSE; - - rtl8168_mdio_write(tp,0x1f, 0x0000); - break; - } - - return retval; -} - -static u16 -rtl8168_get_hw_phy_mcu_code_ver(struct rtl8168_private *tp) -{ - u16 hw_ram_code_ver = ~0; - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B60); - hw_ram_code_ver = rtl8168_mdio_read(tp, 0x06); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B30); - hw_ram_code_ver = rtl8168_mdio_read(tp, 0x06); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x801E); - hw_ram_code_ver = rtl8168_mdio_read(tp, 0x14); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - break; - default: - tp->hw_ram_code_ver = ~0; - break; - } - - return hw_ram_code_ver; -} - -#ifndef ENABLE_USE_FIRMWARE_FILE -static void -rtl8168_enable_phy_disable_mode(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 1: - rtl8168_mac_ocp_write(tp, 0xDC20, rtl8168_mac_ocp_read(tp, 0xDC20) | BIT_1); - break; - case 2: - case 3: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_5); - break; - } - - dprintk("enable phy disable mode.\n"); -} - -static void -rtl8168_disable_phy_disable_mode(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->HwSuppCheckPhyDisableModeVer) { - case 1: - rtl8168_mac_ocp_write(tp, 0xDC20, rtl8168_mac_ocp_read(tp, 0xDC20) & ~BIT_1); - break; - case 2: - case 3: - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_5); - break; - } - - mdelay(1); - - dprintk("disable phy disable mode.\n"); -} - -static int -rtl8168_check_hw_phy_mcu_code_ver(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int ram_code_ver_match = 0; - - tp->hw_ram_code_ver = rtl8168_get_hw_phy_mcu_code_ver(tp); - - if ( tp->hw_ram_code_ver == tp->sw_ram_code_ver) { - ram_code_ver_match = 1; - tp->HwHasWrRamCodeToMicroP = TRUE; - } - - return ram_code_ver_match; -} - -static void -rtl8168_write_hw_phy_mcu_code_ver(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B60); - rtl8168_mdio_write(tp, 0x06, tp->sw_ram_code_ver); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - tp->hw_ram_code_ver = tp->sw_ram_code_ver; - break; - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B30); - rtl8168_mdio_write(tp, 0x06, tp->sw_ram_code_ver); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - tp->hw_ram_code_ver = tp->sw_ram_code_ver; - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x801E); - rtl8168_mdio_write(tp, 0x14, tp->sw_ram_code_ver); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - tp->hw_ram_code_ver = tp->sw_ram_code_ver; - break; - } -} -static int -rtl8168_phy_ram_code_check(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 PhyRegValue; - int retval = TRUE; - - switch(tp->mcfg) { - case CFG_METHOD_21: - rtl8168_mdio_write(tp, 0x1f, 0x0A40); - PhyRegValue = rtl8168_mdio_read(tp, 0x10); - PhyRegValue &= ~(BIT_11); - rtl8168_mdio_write(tp, 0x10, PhyRegValue); - - - rtl8168_mdio_write(tp, 0x1f, 0x0A00); - PhyRegValue = rtl8168_mdio_read(tp, 0x10); - PhyRegValue &= ~(BIT_12 | BIT_13 | BIT_14 | BIT_15); - rtl8168_mdio_write(tp, 0x10, PhyRegValue); - - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8010); - PhyRegValue = rtl8168_mdio_read(tp, 0x14); - PhyRegValue &= ~(BIT_11); - rtl8168_mdio_write(tp, 0x14, PhyRegValue); - - retval = rtl8168_set_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp, 0x1f, 0x0A40); - rtl8168_mdio_write(tp, 0x10, 0x0140); - - rtl8168_mdio_write(tp, 0x1f, 0x0A4A); - PhyRegValue = rtl8168_mdio_read(tp, 0x13); - PhyRegValue &= ~(BIT_6); - PhyRegValue |= (BIT_7); - rtl8168_mdio_write(tp, 0x13, PhyRegValue); - - rtl8168_mdio_write(tp, 0x1f, 0x0A44); - PhyRegValue = rtl8168_mdio_read(tp, 0x14); - PhyRegValue |= (BIT_2); - rtl8168_mdio_write(tp, 0x14, PhyRegValue); - - rtl8168_mdio_write(tp, 0x1f, 0x0A50); - PhyRegValue = rtl8168_mdio_read(tp, 0x11); - PhyRegValue |= (BIT_11|BIT_12); - rtl8168_mdio_write(tp, 0x11, PhyRegValue); - - retval = rtl8168_clear_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp, 0x1f, 0x0A40); - rtl8168_mdio_write(tp, 0x10, 0x1040); - - rtl8168_mdio_write(tp, 0x1f, 0x0A4A); - PhyRegValue = rtl8168_mdio_read(tp, 0x13); - PhyRegValue &= ~(BIT_6|BIT_7); - rtl8168_mdio_write(tp, 0x13, PhyRegValue); - - rtl8168_mdio_write(tp, 0x1f, 0x0A44); - PhyRegValue = rtl8168_mdio_read(tp, 0x14); - PhyRegValue &= ~(BIT_2); - rtl8168_mdio_write(tp, 0x14, PhyRegValue); - - rtl8168_mdio_write(tp, 0x1f, 0x0A50); - PhyRegValue = rtl8168_mdio_read(tp, 0x11); - PhyRegValue &= ~(BIT_11|BIT_12); - rtl8168_mdio_write(tp, 0x11, PhyRegValue); - - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8010); - PhyRegValue = rtl8168_mdio_read(tp, 0x14); - PhyRegValue |= (BIT_11); - rtl8168_mdio_write(tp, 0x14, PhyRegValue); - - retval = rtl8168_set_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp, 0x1f, 0x0A20); - PhyRegValue = rtl8168_mdio_read(tp, 0x13); - if (PhyRegValue & BIT_11) { - if (PhyRegValue & BIT_10) { - retval = FALSE; - } - } - - retval = rtl8168_clear_phy_mcu_patch_request(tp); - - mdelay(2); - break; - default: - break; - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - return retval; -} - -static void -rtl8168_set_phy_ram_code_check_fail_flag(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u16 TmpUshort; - - switch(tp->mcfg) { - case CFG_METHOD_21: - TmpUshort = rtl8168_mac_ocp_read(tp, 0xD3C0); - TmpUshort |= BIT_0; - rtl8168_mac_ocp_write(tp, 0xD3C0, TmpUshort); - break; - } -} - -static void -rtl8168_set_phy_mcu_8168e_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val,i; - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x1800); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x17, 0x0117); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - rtl8168_mdio_write(tp, 0x1B, 0x5000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x4104); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1E); - gphy_val &= 0x03FF; - if (gphy_val == 0x000C) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x07); - if ((gphy_val & BIT_5) == 0) - break; - } - gphy_val = rtl8168_mdio_read(tp, 0x07); - if (gphy_val & BIT_5) { - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x00a1); - rtl8168_mdio_write(tp, 0x17, 0x1000); - rtl8168_mdio_write(tp, 0x17, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2000); - rtl8168_mdio_write(tp, 0x1e, 0x002f); - rtl8168_mdio_write(tp, 0x18, 0x9bfb); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x07, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x08); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x08, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x000e); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x0010); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x0018); - rtl8168_mdio_write(tp, 0x19, 0x4801); - rtl8168_mdio_write(tp, 0x15, 0x0019); - rtl8168_mdio_write(tp, 0x19, 0x6801); - rtl8168_mdio_write(tp, 0x15, 0x001a); - rtl8168_mdio_write(tp, 0x19, 0x66a1); - rtl8168_mdio_write(tp, 0x15, 0x001f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0020); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0021); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0022); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0023); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0024); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0025); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0026); - rtl8168_mdio_write(tp, 0x19, 0x40ea); - rtl8168_mdio_write(tp, 0x15, 0x0027); - rtl8168_mdio_write(tp, 0x19, 0x4503); - rtl8168_mdio_write(tp, 0x15, 0x0028); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0029); - rtl8168_mdio_write(tp, 0x19, 0xa631); - rtl8168_mdio_write(tp, 0x15, 0x002a); - rtl8168_mdio_write(tp, 0x19, 0x9717); - rtl8168_mdio_write(tp, 0x15, 0x002b); - rtl8168_mdio_write(tp, 0x19, 0x302c); - rtl8168_mdio_write(tp, 0x15, 0x002c); - rtl8168_mdio_write(tp, 0x19, 0x4802); - rtl8168_mdio_write(tp, 0x15, 0x002d); - rtl8168_mdio_write(tp, 0x19, 0x58da); - rtl8168_mdio_write(tp, 0x15, 0x002e); - rtl8168_mdio_write(tp, 0x19, 0x400d); - rtl8168_mdio_write(tp, 0x15, 0x002f); - rtl8168_mdio_write(tp, 0x19, 0x4488); - rtl8168_mdio_write(tp, 0x15, 0x0030); - rtl8168_mdio_write(tp, 0x19, 0x9e00); - rtl8168_mdio_write(tp, 0x15, 0x0031); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0032); - rtl8168_mdio_write(tp, 0x19, 0x6481); - rtl8168_mdio_write(tp, 0x15, 0x0033); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0034); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0035); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0036); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0037); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0038); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0039); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x003a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x003b); - rtl8168_mdio_write(tp, 0x19, 0x63e8); - rtl8168_mdio_write(tp, 0x15, 0x003c); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x003d); - rtl8168_mdio_write(tp, 0x19, 0x59d4); - rtl8168_mdio_write(tp, 0x15, 0x003e); - rtl8168_mdio_write(tp, 0x19, 0x63f8); - rtl8168_mdio_write(tp, 0x15, 0x0040); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0041); - rtl8168_mdio_write(tp, 0x19, 0x30de); - rtl8168_mdio_write(tp, 0x15, 0x0044); - rtl8168_mdio_write(tp, 0x19, 0x480f); - rtl8168_mdio_write(tp, 0x15, 0x0045); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x0046); - rtl8168_mdio_write(tp, 0x19, 0x6680); - rtl8168_mdio_write(tp, 0x15, 0x0047); - rtl8168_mdio_write(tp, 0x19, 0x7c10); - rtl8168_mdio_write(tp, 0x15, 0x0048); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0049); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004f); - rtl8168_mdio_write(tp, 0x19, 0x40ea); - rtl8168_mdio_write(tp, 0x15, 0x0050); - rtl8168_mdio_write(tp, 0x19, 0x4503); - rtl8168_mdio_write(tp, 0x15, 0x0051); - rtl8168_mdio_write(tp, 0x19, 0x58ca); - rtl8168_mdio_write(tp, 0x15, 0x0052); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0053); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x0054); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x0055); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0056); - rtl8168_mdio_write(tp, 0x19, 0x3000); - rtl8168_mdio_write(tp, 0x15, 0x006E); - rtl8168_mdio_write(tp, 0x19, 0x9afa); - rtl8168_mdio_write(tp, 0x15, 0x00a1); - rtl8168_mdio_write(tp, 0x19, 0x3044); - rtl8168_mdio_write(tp, 0x15, 0x00ab); - rtl8168_mdio_write(tp, 0x19, 0x5820); - rtl8168_mdio_write(tp, 0x15, 0x00ac); - rtl8168_mdio_write(tp, 0x19, 0x5e04); - rtl8168_mdio_write(tp, 0x15, 0x00ad); - rtl8168_mdio_write(tp, 0x19, 0xb60c); - rtl8168_mdio_write(tp, 0x15, 0x00af); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x00b2); - rtl8168_mdio_write(tp, 0x19, 0x30b9); - rtl8168_mdio_write(tp, 0x15, 0x00b9); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x00ba); - rtl8168_mdio_write(tp, 0x19, 0x480b); - rtl8168_mdio_write(tp, 0x15, 0x00bb); - rtl8168_mdio_write(tp, 0x19, 0x5e00); - rtl8168_mdio_write(tp, 0x15, 0x00bc); - rtl8168_mdio_write(tp, 0x19, 0x405f); - rtl8168_mdio_write(tp, 0x15, 0x00bd); - rtl8168_mdio_write(tp, 0x19, 0x4448); - rtl8168_mdio_write(tp, 0x15, 0x00be); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x00bf); - rtl8168_mdio_write(tp, 0x19, 0x4468); - rtl8168_mdio_write(tp, 0x15, 0x00c0); - rtl8168_mdio_write(tp, 0x19, 0x9c02); - rtl8168_mdio_write(tp, 0x15, 0x00c1); - rtl8168_mdio_write(tp, 0x19, 0x58a0); - rtl8168_mdio_write(tp, 0x15, 0x00c2); - rtl8168_mdio_write(tp, 0x19, 0xb605); - rtl8168_mdio_write(tp, 0x15, 0x00c3); - rtl8168_mdio_write(tp, 0x19, 0xc0d3); - rtl8168_mdio_write(tp, 0x15, 0x00c4); - rtl8168_mdio_write(tp, 0x19, 0x00e6); - rtl8168_mdio_write(tp, 0x15, 0x00c5); - rtl8168_mdio_write(tp, 0x19, 0xdaec); - rtl8168_mdio_write(tp, 0x15, 0x00c6); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00c7); - rtl8168_mdio_write(tp, 0x19, 0x9df9); - rtl8168_mdio_write(tp, 0x15, 0x00c8); - rtl8168_mdio_write(tp, 0x19, 0x307a); - rtl8168_mdio_write(tp, 0x15, 0x0112); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0113); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0114); - rtl8168_mdio_write(tp, 0x19, 0x63f0); - rtl8168_mdio_write(tp, 0x15, 0x0115); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0116); - rtl8168_mdio_write(tp, 0x19, 0x4418); - rtl8168_mdio_write(tp, 0x15, 0x0117); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x15, 0x0118); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0119); - rtl8168_mdio_write(tp, 0x19, 0x64e1); - rtl8168_mdio_write(tp, 0x15, 0x011a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0150); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0151); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0152); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0153); - rtl8168_mdio_write(tp, 0x19, 0x4540); - rtl8168_mdio_write(tp, 0x15, 0x0154); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0155); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x15, 0x0156); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0157); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0158); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0159); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x015a); - rtl8168_mdio_write(tp, 0x19, 0x30fe); - rtl8168_mdio_write(tp, 0x15, 0x021e); - rtl8168_mdio_write(tp, 0x19, 0x5410); - rtl8168_mdio_write(tp, 0x15, 0x0225); - rtl8168_mdio_write(tp, 0x19, 0x5400); - rtl8168_mdio_write(tp, 0x15, 0x023D); - rtl8168_mdio_write(tp, 0x19, 0x4050); - rtl8168_mdio_write(tp, 0x15, 0x0295); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x02bd); - rtl8168_mdio_write(tp, 0x19, 0xa523); - rtl8168_mdio_write(tp, 0x15, 0x02be); - rtl8168_mdio_write(tp, 0x19, 0x32ca); - rtl8168_mdio_write(tp, 0x15, 0x02ca); - rtl8168_mdio_write(tp, 0x19, 0x48b3); - rtl8168_mdio_write(tp, 0x15, 0x02cb); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x02cc); - rtl8168_mdio_write(tp, 0x19, 0x4823); - rtl8168_mdio_write(tp, 0x15, 0x02cd); - rtl8168_mdio_write(tp, 0x19, 0x4510); - rtl8168_mdio_write(tp, 0x15, 0x02ce); - rtl8168_mdio_write(tp, 0x19, 0xb63a); - rtl8168_mdio_write(tp, 0x15, 0x02cf); - rtl8168_mdio_write(tp, 0x19, 0x7dc8); - rtl8168_mdio_write(tp, 0x15, 0x02d6); - rtl8168_mdio_write(tp, 0x19, 0x9bf8); - rtl8168_mdio_write(tp, 0x15, 0x02d8); - rtl8168_mdio_write(tp, 0x19, 0x85f6); - rtl8168_mdio_write(tp, 0x15, 0x02d9); - rtl8168_mdio_write(tp, 0x19, 0x32e0); - rtl8168_mdio_write(tp, 0x15, 0x02e0); - rtl8168_mdio_write(tp, 0x19, 0x4834); - rtl8168_mdio_write(tp, 0x15, 0x02e1); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x02e2); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x02e3); - rtl8168_mdio_write(tp, 0x19, 0x4824); - rtl8168_mdio_write(tp, 0x15, 0x02e4); - rtl8168_mdio_write(tp, 0x19, 0x4520); - rtl8168_mdio_write(tp, 0x15, 0x02e5); - rtl8168_mdio_write(tp, 0x19, 0x4008); - rtl8168_mdio_write(tp, 0x15, 0x02e6); - rtl8168_mdio_write(tp, 0x19, 0x4560); - rtl8168_mdio_write(tp, 0x15, 0x02e7); - rtl8168_mdio_write(tp, 0x19, 0x9d04); - rtl8168_mdio_write(tp, 0x15, 0x02e8); - rtl8168_mdio_write(tp, 0x19, 0x48c4); - rtl8168_mdio_write(tp, 0x15, 0x02e9); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02ea); - rtl8168_mdio_write(tp, 0x19, 0x4844); - rtl8168_mdio_write(tp, 0x15, 0x02eb); - rtl8168_mdio_write(tp, 0x19, 0x7dc8); - rtl8168_mdio_write(tp, 0x15, 0x02f0); - rtl8168_mdio_write(tp, 0x19, 0x9cf7); - rtl8168_mdio_write(tp, 0x15, 0x02f1); - rtl8168_mdio_write(tp, 0x19, 0xdf94); - rtl8168_mdio_write(tp, 0x15, 0x02f2); - rtl8168_mdio_write(tp, 0x19, 0x0002); - rtl8168_mdio_write(tp, 0x15, 0x02f3); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x02f4); - rtl8168_mdio_write(tp, 0x19, 0xb614); - rtl8168_mdio_write(tp, 0x15, 0x02f5); - rtl8168_mdio_write(tp, 0x19, 0xc42b); - rtl8168_mdio_write(tp, 0x15, 0x02f6); - rtl8168_mdio_write(tp, 0x19, 0x00d4); - rtl8168_mdio_write(tp, 0x15, 0x02f7); - rtl8168_mdio_write(tp, 0x19, 0xc455); - rtl8168_mdio_write(tp, 0x15, 0x02f8); - rtl8168_mdio_write(tp, 0x19, 0x0093); - rtl8168_mdio_write(tp, 0x15, 0x02f9); - rtl8168_mdio_write(tp, 0x19, 0x92ee); - rtl8168_mdio_write(tp, 0x15, 0x02fa); - rtl8168_mdio_write(tp, 0x19, 0xefed); - rtl8168_mdio_write(tp, 0x15, 0x02fb); - rtl8168_mdio_write(tp, 0x19, 0x3312); - rtl8168_mdio_write(tp, 0x15, 0x0312); - rtl8168_mdio_write(tp, 0x19, 0x49b5); - rtl8168_mdio_write(tp, 0x15, 0x0313); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x0314); - rtl8168_mdio_write(tp, 0x19, 0x4d00); - rtl8168_mdio_write(tp, 0x15, 0x0315); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x031e); - rtl8168_mdio_write(tp, 0x19, 0x404f); - rtl8168_mdio_write(tp, 0x15, 0x031f); - rtl8168_mdio_write(tp, 0x19, 0x44c8); - rtl8168_mdio_write(tp, 0x15, 0x0320); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0321); - rtl8168_mdio_write(tp, 0x19, 0x00e7); - rtl8168_mdio_write(tp, 0x15, 0x0322); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0323); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x0324); - rtl8168_mdio_write(tp, 0x19, 0x4d48); - rtl8168_mdio_write(tp, 0x15, 0x0325); - rtl8168_mdio_write(tp, 0x19, 0x3327); - rtl8168_mdio_write(tp, 0x15, 0x0326); - rtl8168_mdio_write(tp, 0x19, 0x4d40); - rtl8168_mdio_write(tp, 0x15, 0x0327); - rtl8168_mdio_write(tp, 0x19, 0xc8d7); - rtl8168_mdio_write(tp, 0x15, 0x0328); - rtl8168_mdio_write(tp, 0x19, 0x0003); - rtl8168_mdio_write(tp, 0x15, 0x0329); - rtl8168_mdio_write(tp, 0x19, 0x7c20); - rtl8168_mdio_write(tp, 0x15, 0x032a); - rtl8168_mdio_write(tp, 0x19, 0x4c20); - rtl8168_mdio_write(tp, 0x15, 0x032b); - rtl8168_mdio_write(tp, 0x19, 0xc8ed); - rtl8168_mdio_write(tp, 0x15, 0x032c); - rtl8168_mdio_write(tp, 0x19, 0x00f4); - rtl8168_mdio_write(tp, 0x15, 0x032d); - rtl8168_mdio_write(tp, 0x19, 0x82b3); - rtl8168_mdio_write(tp, 0x15, 0x032e); - rtl8168_mdio_write(tp, 0x19, 0xd11d); - rtl8168_mdio_write(tp, 0x15, 0x032f); - rtl8168_mdio_write(tp, 0x19, 0x00b1); - rtl8168_mdio_write(tp, 0x15, 0x0330); - rtl8168_mdio_write(tp, 0x19, 0xde18); - rtl8168_mdio_write(tp, 0x15, 0x0331); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x0332); - rtl8168_mdio_write(tp, 0x19, 0x91ee); - rtl8168_mdio_write(tp, 0x15, 0x0333); - rtl8168_mdio_write(tp, 0x19, 0x3339); - rtl8168_mdio_write(tp, 0x15, 0x033a); - rtl8168_mdio_write(tp, 0x19, 0x4064); - rtl8168_mdio_write(tp, 0x15, 0x0340); - rtl8168_mdio_write(tp, 0x19, 0x9e06); - rtl8168_mdio_write(tp, 0x15, 0x0341); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0342); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x0343); - rtl8168_mdio_write(tp, 0x19, 0x4d48); - rtl8168_mdio_write(tp, 0x15, 0x0344); - rtl8168_mdio_write(tp, 0x19, 0x3346); - rtl8168_mdio_write(tp, 0x15, 0x0345); - rtl8168_mdio_write(tp, 0x19, 0x4d40); - rtl8168_mdio_write(tp, 0x15, 0x0346); - rtl8168_mdio_write(tp, 0x19, 0xd11d); - rtl8168_mdio_write(tp, 0x15, 0x0347); - rtl8168_mdio_write(tp, 0x19, 0x0099); - rtl8168_mdio_write(tp, 0x15, 0x0348); - rtl8168_mdio_write(tp, 0x19, 0xbb17); - rtl8168_mdio_write(tp, 0x15, 0x0349); - rtl8168_mdio_write(tp, 0x19, 0x8102); - rtl8168_mdio_write(tp, 0x15, 0x034a); - rtl8168_mdio_write(tp, 0x19, 0x334d); - rtl8168_mdio_write(tp, 0x15, 0x034b); - rtl8168_mdio_write(tp, 0x19, 0xa22c); - rtl8168_mdio_write(tp, 0x15, 0x034c); - rtl8168_mdio_write(tp, 0x19, 0x3397); - rtl8168_mdio_write(tp, 0x15, 0x034d); - rtl8168_mdio_write(tp, 0x19, 0x91f2); - rtl8168_mdio_write(tp, 0x15, 0x034e); - rtl8168_mdio_write(tp, 0x19, 0xc218); - rtl8168_mdio_write(tp, 0x15, 0x034f); - rtl8168_mdio_write(tp, 0x19, 0x00f0); - rtl8168_mdio_write(tp, 0x15, 0x0350); - rtl8168_mdio_write(tp, 0x19, 0x3397); - rtl8168_mdio_write(tp, 0x15, 0x0351); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0364); - rtl8168_mdio_write(tp, 0x19, 0xbc05); - rtl8168_mdio_write(tp, 0x15, 0x0367); - rtl8168_mdio_write(tp, 0x19, 0xa1fc); - rtl8168_mdio_write(tp, 0x15, 0x0368); - rtl8168_mdio_write(tp, 0x19, 0x3377); - rtl8168_mdio_write(tp, 0x15, 0x0369); - rtl8168_mdio_write(tp, 0x19, 0x328b); - rtl8168_mdio_write(tp, 0x15, 0x036a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0377); - rtl8168_mdio_write(tp, 0x19, 0x4b97); - rtl8168_mdio_write(tp, 0x15, 0x0378); - rtl8168_mdio_write(tp, 0x19, 0x6818); - rtl8168_mdio_write(tp, 0x15, 0x0379); - rtl8168_mdio_write(tp, 0x19, 0x4b07); - rtl8168_mdio_write(tp, 0x15, 0x037a); - rtl8168_mdio_write(tp, 0x19, 0x40ac); - rtl8168_mdio_write(tp, 0x15, 0x037b); - rtl8168_mdio_write(tp, 0x19, 0x4445); - rtl8168_mdio_write(tp, 0x15, 0x037c); - rtl8168_mdio_write(tp, 0x19, 0x404e); - rtl8168_mdio_write(tp, 0x15, 0x037d); - rtl8168_mdio_write(tp, 0x19, 0x4461); - rtl8168_mdio_write(tp, 0x15, 0x037e); - rtl8168_mdio_write(tp, 0x19, 0x9c09); - rtl8168_mdio_write(tp, 0x15, 0x037f); - rtl8168_mdio_write(tp, 0x19, 0x63da); - rtl8168_mdio_write(tp, 0x15, 0x0380); - rtl8168_mdio_write(tp, 0x19, 0x5440); - rtl8168_mdio_write(tp, 0x15, 0x0381); - rtl8168_mdio_write(tp, 0x19, 0x4b98); - rtl8168_mdio_write(tp, 0x15, 0x0382); - rtl8168_mdio_write(tp, 0x19, 0x7c60); - rtl8168_mdio_write(tp, 0x15, 0x0383); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x0384); - rtl8168_mdio_write(tp, 0x19, 0x4b08); - rtl8168_mdio_write(tp, 0x15, 0x0385); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x0386); - rtl8168_mdio_write(tp, 0x19, 0x338d); - rtl8168_mdio_write(tp, 0x15, 0x0387); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0388); - rtl8168_mdio_write(tp, 0x19, 0x0080); - rtl8168_mdio_write(tp, 0x15, 0x0389); - rtl8168_mdio_write(tp, 0x19, 0x820c); - rtl8168_mdio_write(tp, 0x15, 0x038a); - rtl8168_mdio_write(tp, 0x19, 0xa10b); - rtl8168_mdio_write(tp, 0x15, 0x038b); - rtl8168_mdio_write(tp, 0x19, 0x9df3); - rtl8168_mdio_write(tp, 0x15, 0x038c); - rtl8168_mdio_write(tp, 0x19, 0x3395); - rtl8168_mdio_write(tp, 0x15, 0x038d); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x038e); - rtl8168_mdio_write(tp, 0x19, 0x00f9); - rtl8168_mdio_write(tp, 0x15, 0x038f); - rtl8168_mdio_write(tp, 0x19, 0xc017); - rtl8168_mdio_write(tp, 0x15, 0x0390); - rtl8168_mdio_write(tp, 0x19, 0x0005); - rtl8168_mdio_write(tp, 0x15, 0x0391); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x0392); - rtl8168_mdio_write(tp, 0x19, 0xa103); - rtl8168_mdio_write(tp, 0x15, 0x0393); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x0394); - rtl8168_mdio_write(tp, 0x19, 0x9df9); - rtl8168_mdio_write(tp, 0x15, 0x0395); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x0396); - rtl8168_mdio_write(tp, 0x19, 0x3397); - rtl8168_mdio_write(tp, 0x15, 0x0399); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x03a4); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x03a5); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x03a6); - rtl8168_mdio_write(tp, 0x19, 0x4d08); - rtl8168_mdio_write(tp, 0x15, 0x03a7); - rtl8168_mdio_write(tp, 0x19, 0x33a9); - rtl8168_mdio_write(tp, 0x15, 0x03a8); - rtl8168_mdio_write(tp, 0x19, 0x4d00); - rtl8168_mdio_write(tp, 0x15, 0x03a9); - rtl8168_mdio_write(tp, 0x19, 0x9bfa); - rtl8168_mdio_write(tp, 0x15, 0x03aa); - rtl8168_mdio_write(tp, 0x19, 0x33b6); - rtl8168_mdio_write(tp, 0x15, 0x03bb); - rtl8168_mdio_write(tp, 0x19, 0x4056); - rtl8168_mdio_write(tp, 0x15, 0x03bc); - rtl8168_mdio_write(tp, 0x19, 0x44e9); - rtl8168_mdio_write(tp, 0x15, 0x03bd); - rtl8168_mdio_write(tp, 0x19, 0x405e); - rtl8168_mdio_write(tp, 0x15, 0x03be); - rtl8168_mdio_write(tp, 0x19, 0x44f8); - rtl8168_mdio_write(tp, 0x15, 0x03bf); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x03c0); - rtl8168_mdio_write(tp, 0x19, 0x0037); - rtl8168_mdio_write(tp, 0x15, 0x03c1); - rtl8168_mdio_write(tp, 0x19, 0xbd37); - rtl8168_mdio_write(tp, 0x15, 0x03c2); - rtl8168_mdio_write(tp, 0x19, 0x9cfd); - rtl8168_mdio_write(tp, 0x15, 0x03c3); - rtl8168_mdio_write(tp, 0x19, 0xc639); - rtl8168_mdio_write(tp, 0x15, 0x03c4); - rtl8168_mdio_write(tp, 0x19, 0x0011); - rtl8168_mdio_write(tp, 0x15, 0x03c5); - rtl8168_mdio_write(tp, 0x19, 0x9b03); - rtl8168_mdio_write(tp, 0x15, 0x03c6); - rtl8168_mdio_write(tp, 0x19, 0x7c01); - rtl8168_mdio_write(tp, 0x15, 0x03c7); - rtl8168_mdio_write(tp, 0x19, 0x4c01); - rtl8168_mdio_write(tp, 0x15, 0x03c8); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x03c9); - rtl8168_mdio_write(tp, 0x19, 0x7c20); - rtl8168_mdio_write(tp, 0x15, 0x03ca); - rtl8168_mdio_write(tp, 0x19, 0x4c20); - rtl8168_mdio_write(tp, 0x15, 0x03cb); - rtl8168_mdio_write(tp, 0x19, 0x9af4); - rtl8168_mdio_write(tp, 0x15, 0x03cc); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03cd); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03ce); - rtl8168_mdio_write(tp, 0x19, 0x4470); - rtl8168_mdio_write(tp, 0x15, 0x03cf); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03d0); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03d1); - rtl8168_mdio_write(tp, 0x19, 0x33bf); - rtl8168_mdio_write(tp, 0x15, 0x03d6); - rtl8168_mdio_write(tp, 0x19, 0x4047); - rtl8168_mdio_write(tp, 0x15, 0x03d7); - rtl8168_mdio_write(tp, 0x19, 0x4469); - rtl8168_mdio_write(tp, 0x15, 0x03d8); - rtl8168_mdio_write(tp, 0x19, 0x492b); - rtl8168_mdio_write(tp, 0x15, 0x03d9); - rtl8168_mdio_write(tp, 0x19, 0x4479); - rtl8168_mdio_write(tp, 0x15, 0x03da); - rtl8168_mdio_write(tp, 0x19, 0x7c09); - rtl8168_mdio_write(tp, 0x15, 0x03db); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x03dc); - rtl8168_mdio_write(tp, 0x19, 0x4d48); - rtl8168_mdio_write(tp, 0x15, 0x03dd); - rtl8168_mdio_write(tp, 0x19, 0x33df); - rtl8168_mdio_write(tp, 0x15, 0x03de); - rtl8168_mdio_write(tp, 0x19, 0x4d40); - rtl8168_mdio_write(tp, 0x15, 0x03df); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x03e0); - rtl8168_mdio_write(tp, 0x19, 0x0017); - rtl8168_mdio_write(tp, 0x15, 0x03e1); - rtl8168_mdio_write(tp, 0x19, 0xbd17); - rtl8168_mdio_write(tp, 0x15, 0x03e2); - rtl8168_mdio_write(tp, 0x19, 0x9b03); - rtl8168_mdio_write(tp, 0x15, 0x03e3); - rtl8168_mdio_write(tp, 0x19, 0x7c20); - rtl8168_mdio_write(tp, 0x15, 0x03e4); - rtl8168_mdio_write(tp, 0x19, 0x4c20); - rtl8168_mdio_write(tp, 0x15, 0x03e5); - rtl8168_mdio_write(tp, 0x19, 0x88f5); - rtl8168_mdio_write(tp, 0x15, 0x03e6); - rtl8168_mdio_write(tp, 0x19, 0xc428); - rtl8168_mdio_write(tp, 0x15, 0x03e7); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x03e8); - rtl8168_mdio_write(tp, 0x19, 0x9af2); - rtl8168_mdio_write(tp, 0x15, 0x03e9); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03ea); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03eb); - rtl8168_mdio_write(tp, 0x19, 0x4470); - rtl8168_mdio_write(tp, 0x15, 0x03ec); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03ed); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03ee); - rtl8168_mdio_write(tp, 0x19, 0x33da); - rtl8168_mdio_write(tp, 0x15, 0x03ef); - rtl8168_mdio_write(tp, 0x19, 0x3312); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2179); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0040); - rtl8168_mdio_write(tp, 0x18, 0x0645); - rtl8168_mdio_write(tp, 0x19, 0xe200); - rtl8168_mdio_write(tp, 0x18, 0x0655); - rtl8168_mdio_write(tp, 0x19, 0x9000); - rtl8168_mdio_write(tp, 0x18, 0x0d05); - rtl8168_mdio_write(tp, 0x19, 0xbe00); - rtl8168_mdio_write(tp, 0x18, 0x0d15); - rtl8168_mdio_write(tp, 0x19, 0xd300); - rtl8168_mdio_write(tp, 0x18, 0x0d25); - rtl8168_mdio_write(tp, 0x19, 0xfe00); - rtl8168_mdio_write(tp, 0x18, 0x0d35); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x0d45); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x0d55); - rtl8168_mdio_write(tp, 0x19, 0x1000); - rtl8168_mdio_write(tp, 0x18, 0x0d65); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x0d75); - rtl8168_mdio_write(tp, 0x19, 0x8200); - rtl8168_mdio_write(tp, 0x18, 0x0d85); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x0d95); - rtl8168_mdio_write(tp, 0x19, 0x7000); - rtl8168_mdio_write(tp, 0x18, 0x0da5); - rtl8168_mdio_write(tp, 0x19, 0x0f00); - rtl8168_mdio_write(tp, 0x18, 0x0db5); - rtl8168_mdio_write(tp, 0x19, 0x0100); - rtl8168_mdio_write(tp, 0x18, 0x0dc5); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x18, 0x0dd5); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x0de5); - rtl8168_mdio_write(tp, 0x19, 0xe000); - rtl8168_mdio_write(tp, 0x18, 0x0df5); - rtl8168_mdio_write(tp, 0x19, 0xef00); - rtl8168_mdio_write(tp, 0x18, 0x16d5); - rtl8168_mdio_write(tp, 0x19, 0xe200); - rtl8168_mdio_write(tp, 0x18, 0x16e5); - rtl8168_mdio_write(tp, 0x19, 0xab00); - rtl8168_mdio_write(tp, 0x18, 0x2904); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x2914); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x2924); - rtl8168_mdio_write(tp, 0x19, 0x0100); - rtl8168_mdio_write(tp, 0x18, 0x2934); - rtl8168_mdio_write(tp, 0x19, 0x2000); - rtl8168_mdio_write(tp, 0x18, 0x2944); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2954); - rtl8168_mdio_write(tp, 0x19, 0x4600); - rtl8168_mdio_write(tp, 0x18, 0x2964); - rtl8168_mdio_write(tp, 0x19, 0xfc00); - rtl8168_mdio_write(tp, 0x18, 0x2974); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2984); - rtl8168_mdio_write(tp, 0x19, 0x5000); - rtl8168_mdio_write(tp, 0x18, 0x2994); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x18, 0x29a4); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x29b4); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x29c4); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x29d4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x29e4); - rtl8168_mdio_write(tp, 0x19, 0x2000); - rtl8168_mdio_write(tp, 0x18, 0x29f4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2a04); - rtl8168_mdio_write(tp, 0x19, 0xe600); - rtl8168_mdio_write(tp, 0x18, 0x2a14); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x2a24); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2a34); - rtl8168_mdio_write(tp, 0x19, 0x5000); - rtl8168_mdio_write(tp, 0x18, 0x2a44); - rtl8168_mdio_write(tp, 0x19, 0x8500); - rtl8168_mdio_write(tp, 0x18, 0x2a54); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x2a64); - rtl8168_mdio_write(tp, 0x19, 0xac00); - rtl8168_mdio_write(tp, 0x18, 0x2a74); - rtl8168_mdio_write(tp, 0x19, 0x0800); - rtl8168_mdio_write(tp, 0x18, 0x2a84); - rtl8168_mdio_write(tp, 0x19, 0xfc00); - rtl8168_mdio_write(tp, 0x18, 0x2a94); - rtl8168_mdio_write(tp, 0x19, 0xe000); - rtl8168_mdio_write(tp, 0x18, 0x2aa4); - rtl8168_mdio_write(tp, 0x19, 0x7400); - rtl8168_mdio_write(tp, 0x18, 0x2ab4); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x2ac4); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x2ad4); - rtl8168_mdio_write(tp, 0x19, 0x0100); - rtl8168_mdio_write(tp, 0x18, 0x2ae4); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x2af4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2b04); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x18, 0x2b14); - rtl8168_mdio_write(tp, 0x19, 0xfc00); - rtl8168_mdio_write(tp, 0x18, 0x2b24); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2b34); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x2b44); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x18, 0x2b54); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x2b64); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x2b74); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x2b84); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2b94); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x2ba4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2bb4); - rtl8168_mdio_write(tp, 0x19, 0xfc00); - rtl8168_mdio_write(tp, 0x18, 0x2bc4); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x2bd4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2be4); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x2bf4); - rtl8168_mdio_write(tp, 0x19, 0x8900); - rtl8168_mdio_write(tp, 0x18, 0x2c04); - rtl8168_mdio_write(tp, 0x19, 0x8300); - rtl8168_mdio_write(tp, 0x18, 0x2c14); - rtl8168_mdio_write(tp, 0x19, 0xe000); - rtl8168_mdio_write(tp, 0x18, 0x2c24); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x18, 0x2c34); - rtl8168_mdio_write(tp, 0x19, 0xac00); - rtl8168_mdio_write(tp, 0x18, 0x2c44); - rtl8168_mdio_write(tp, 0x19, 0x0800); - rtl8168_mdio_write(tp, 0x18, 0x2c54); - rtl8168_mdio_write(tp, 0x19, 0xfa00); - rtl8168_mdio_write(tp, 0x18, 0x2c64); - rtl8168_mdio_write(tp, 0x19, 0xe100); - rtl8168_mdio_write(tp, 0x18, 0x2c74); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x18, 0x0001); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2100); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8b88); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0xd480); - rtl8168_mdio_write(tp, 0x06, 0xc1e4); - rtl8168_mdio_write(tp, 0x06, 0x8b9a); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x9bee); - rtl8168_mdio_write(tp, 0x06, 0x8b83); - rtl8168_mdio_write(tp, 0x06, 0x41bf); - rtl8168_mdio_write(tp, 0x06, 0x8b88); - rtl8168_mdio_write(tp, 0x06, 0xec00); - rtl8168_mdio_write(tp, 0x06, 0x19a9); - rtl8168_mdio_write(tp, 0x06, 0x8b90); - rtl8168_mdio_write(tp, 0x06, 0xf9ee); - rtl8168_mdio_write(tp, 0x06, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x41f7); - rtl8168_mdio_write(tp, 0x06, 0x2ff6); - rtl8168_mdio_write(tp, 0x06, 0x28e4); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xe5e1); - rtl8168_mdio_write(tp, 0x06, 0x41f7); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x020c); - rtl8168_mdio_write(tp, 0x06, 0x0202); - rtl8168_mdio_write(tp, 0x06, 0x1d02); - rtl8168_mdio_write(tp, 0x06, 0x0230); - rtl8168_mdio_write(tp, 0x06, 0x0202); - rtl8168_mdio_write(tp, 0x06, 0x4002); - rtl8168_mdio_write(tp, 0x06, 0x028b); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x6c02); - rtl8168_mdio_write(tp, 0x06, 0x8085); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaec3); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x10ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x1310); - rtl8168_mdio_write(tp, 0x06, 0x021f); - rtl8168_mdio_write(tp, 0x06, 0x9d02); - rtl8168_mdio_write(tp, 0x06, 0x1f0c); - rtl8168_mdio_write(tp, 0x06, 0x0227); - rtl8168_mdio_write(tp, 0x06, 0x49fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x200b); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x830e); - rtl8168_mdio_write(tp, 0x06, 0x021b); - rtl8168_mdio_write(tp, 0x06, 0x67ad); - rtl8168_mdio_write(tp, 0x06, 0x2211); - rtl8168_mdio_write(tp, 0x06, 0xf622); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x2ba5); - rtl8168_mdio_write(tp, 0x06, 0x022a); - rtl8168_mdio_write(tp, 0x06, 0x2402); - rtl8168_mdio_write(tp, 0x06, 0x80c6); - rtl8168_mdio_write(tp, 0x06, 0x022a); - rtl8168_mdio_write(tp, 0x06, 0xf0ad); - rtl8168_mdio_write(tp, 0x06, 0x2511); - rtl8168_mdio_write(tp, 0x06, 0xf625); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x8226); - rtl8168_mdio_write(tp, 0x06, 0x0204); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x19cc); - rtl8168_mdio_write(tp, 0x06, 0x022b); - rtl8168_mdio_write(tp, 0x06, 0x5bfc); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x0105); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b83); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x44e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x23ad); - rtl8168_mdio_write(tp, 0x06, 0x223b); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xbea0); - rtl8168_mdio_write(tp, 0x06, 0x0005); - rtl8168_mdio_write(tp, 0x06, 0x0228); - rtl8168_mdio_write(tp, 0x06, 0xdeae); - rtl8168_mdio_write(tp, 0x06, 0x42a0); - rtl8168_mdio_write(tp, 0x06, 0x0105); - rtl8168_mdio_write(tp, 0x06, 0x0228); - rtl8168_mdio_write(tp, 0x06, 0xf1ae); - rtl8168_mdio_write(tp, 0x06, 0x3aa0); - rtl8168_mdio_write(tp, 0x06, 0x0205); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x25ae); - rtl8168_mdio_write(tp, 0x06, 0x32a0); - rtl8168_mdio_write(tp, 0x06, 0x0305); - rtl8168_mdio_write(tp, 0x06, 0x0229); - rtl8168_mdio_write(tp, 0x06, 0x9aae); - rtl8168_mdio_write(tp, 0x06, 0x2aa0); - rtl8168_mdio_write(tp, 0x06, 0x0405); - rtl8168_mdio_write(tp, 0x06, 0x0229); - rtl8168_mdio_write(tp, 0x06, 0xaeae); - rtl8168_mdio_write(tp, 0x06, 0x22a0); - rtl8168_mdio_write(tp, 0x06, 0x0505); - rtl8168_mdio_write(tp, 0x06, 0x0229); - rtl8168_mdio_write(tp, 0x06, 0xd7ae); - rtl8168_mdio_write(tp, 0x06, 0x1aa0); - rtl8168_mdio_write(tp, 0x06, 0x0605); - rtl8168_mdio_write(tp, 0x06, 0x0229); - rtl8168_mdio_write(tp, 0x06, 0xfeae); - rtl8168_mdio_write(tp, 0x06, 0x12ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac0); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac1); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x00fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0x022a); - rtl8168_mdio_write(tp, 0x06, 0x67e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x230d); - rtl8168_mdio_write(tp, 0x06, 0x0658); - rtl8168_mdio_write(tp, 0x06, 0x03a0); - rtl8168_mdio_write(tp, 0x06, 0x0202); - rtl8168_mdio_write(tp, 0x06, 0xae2d); - rtl8168_mdio_write(tp, 0x06, 0xa001); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x2da0); - rtl8168_mdio_write(tp, 0x06, 0x004d); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe201); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x44e0); - rtl8168_mdio_write(tp, 0x06, 0x8ac2); - rtl8168_mdio_write(tp, 0x06, 0xe48a); - rtl8168_mdio_write(tp, 0x06, 0xc4e0); - rtl8168_mdio_write(tp, 0x06, 0x8ac3); - rtl8168_mdio_write(tp, 0x06, 0xe48a); - rtl8168_mdio_write(tp, 0x06, 0xc5ee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x03e0); - rtl8168_mdio_write(tp, 0x06, 0x8b83); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x3aee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x05ae); - rtl8168_mdio_write(tp, 0x06, 0x34e0); - rtl8168_mdio_write(tp, 0x06, 0x8ace); - rtl8168_mdio_write(tp, 0x06, 0xae03); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xcfe1); - rtl8168_mdio_write(tp, 0x06, 0x8ac2); - rtl8168_mdio_write(tp, 0x06, 0x4905); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xc4e1); - rtl8168_mdio_write(tp, 0x06, 0x8ac3); - rtl8168_mdio_write(tp, 0x06, 0x4905); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xc5ee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x2ab6); - rtl8168_mdio_write(tp, 0x06, 0xac20); - rtl8168_mdio_write(tp, 0x06, 0x1202); - rtl8168_mdio_write(tp, 0x06, 0x819b); - rtl8168_mdio_write(tp, 0x06, 0xac20); - rtl8168_mdio_write(tp, 0x06, 0x0cee); - rtl8168_mdio_write(tp, 0x06, 0x8ac1); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x02fc); - rtl8168_mdio_write(tp, 0x06, 0x04d0); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x590f); - rtl8168_mdio_write(tp, 0x06, 0x3902); - rtl8168_mdio_write(tp, 0x06, 0xaa04); - rtl8168_mdio_write(tp, 0x06, 0xd001); - rtl8168_mdio_write(tp, 0x06, 0xae02); - rtl8168_mdio_write(tp, 0x06, 0xd000); - rtl8168_mdio_write(tp, 0x06, 0x04f9); - rtl8168_mdio_write(tp, 0x06, 0xfae2); - rtl8168_mdio_write(tp, 0x06, 0xe2d2); - rtl8168_mdio_write(tp, 0x06, 0xe3e2); - rtl8168_mdio_write(tp, 0x06, 0xd3f9); - rtl8168_mdio_write(tp, 0x06, 0x5af7); - rtl8168_mdio_write(tp, 0x06, 0xe6e2); - rtl8168_mdio_write(tp, 0x06, 0xd2e7); - rtl8168_mdio_write(tp, 0x06, 0xe2d3); - rtl8168_mdio_write(tp, 0x06, 0xe2e0); - rtl8168_mdio_write(tp, 0x06, 0x2ce3); - rtl8168_mdio_write(tp, 0x06, 0xe02d); - rtl8168_mdio_write(tp, 0x06, 0xf95b); - rtl8168_mdio_write(tp, 0x06, 0xe01e); - rtl8168_mdio_write(tp, 0x06, 0x30e6); - rtl8168_mdio_write(tp, 0x06, 0xe02c); - rtl8168_mdio_write(tp, 0x06, 0xe7e0); - rtl8168_mdio_write(tp, 0x06, 0x2de2); - rtl8168_mdio_write(tp, 0x06, 0xe2cc); - rtl8168_mdio_write(tp, 0x06, 0xe3e2); - rtl8168_mdio_write(tp, 0x06, 0xcdf9); - rtl8168_mdio_write(tp, 0x06, 0x5a0f); - rtl8168_mdio_write(tp, 0x06, 0x6a50); - rtl8168_mdio_write(tp, 0x06, 0xe6e2); - rtl8168_mdio_write(tp, 0x06, 0xcce7); - rtl8168_mdio_write(tp, 0x06, 0xe2cd); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x3ce1); - rtl8168_mdio_write(tp, 0x06, 0xe03d); - rtl8168_mdio_write(tp, 0x06, 0xef64); - rtl8168_mdio_write(tp, 0x06, 0xfde0); - rtl8168_mdio_write(tp, 0x06, 0xe2cc); - rtl8168_mdio_write(tp, 0x06, 0xe1e2); - rtl8168_mdio_write(tp, 0x06, 0xcd58); - rtl8168_mdio_write(tp, 0x06, 0x0f5a); - rtl8168_mdio_write(tp, 0x06, 0xf01e); - rtl8168_mdio_write(tp, 0x06, 0x02e4); - rtl8168_mdio_write(tp, 0x06, 0xe2cc); - rtl8168_mdio_write(tp, 0x06, 0xe5e2); - rtl8168_mdio_write(tp, 0x06, 0xcdfd); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x2ce1); - rtl8168_mdio_write(tp, 0x06, 0xe02d); - rtl8168_mdio_write(tp, 0x06, 0x59e0); - rtl8168_mdio_write(tp, 0x06, 0x5b1f); - rtl8168_mdio_write(tp, 0x06, 0x1e13); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x2ce5); - rtl8168_mdio_write(tp, 0x06, 0xe02d); - rtl8168_mdio_write(tp, 0x06, 0xfde0); - rtl8168_mdio_write(tp, 0x06, 0xe2d2); - rtl8168_mdio_write(tp, 0x06, 0xe1e2); - rtl8168_mdio_write(tp, 0x06, 0xd358); - rtl8168_mdio_write(tp, 0x06, 0xf75a); - rtl8168_mdio_write(tp, 0x06, 0x081e); - rtl8168_mdio_write(tp, 0x06, 0x02e4); - rtl8168_mdio_write(tp, 0x06, 0xe2d2); - rtl8168_mdio_write(tp, 0x06, 0xe5e2); - rtl8168_mdio_write(tp, 0x06, 0xd3ef); - rtl8168_mdio_write(tp, 0x06, 0x46fe); - rtl8168_mdio_write(tp, 0x06, 0xfd04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xc4e1); - rtl8168_mdio_write(tp, 0x06, 0x8b6e); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e58); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x6ead); - rtl8168_mdio_write(tp, 0x06, 0x2222); - rtl8168_mdio_write(tp, 0x06, 0xac27); - rtl8168_mdio_write(tp, 0x06, 0x55ac); - rtl8168_mdio_write(tp, 0x06, 0x2602); - rtl8168_mdio_write(tp, 0x06, 0xae1a); - rtl8168_mdio_write(tp, 0x06, 0xd106); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xba02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd107); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xbd02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd107); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xc002); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xae30); - rtl8168_mdio_write(tp, 0x06, 0xd103); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xc302); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xc602); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xca02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd10f); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xba02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xbd02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xc002); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xc302); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd011); - rtl8168_mdio_write(tp, 0x06, 0x022b); - rtl8168_mdio_write(tp, 0x06, 0xfb59); - rtl8168_mdio_write(tp, 0x06, 0x03ef); - rtl8168_mdio_write(tp, 0x06, 0x01d1); - rtl8168_mdio_write(tp, 0x06, 0x00a0); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0xc602); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xd111); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x020c); - rtl8168_mdio_write(tp, 0x06, 0x11ad); - rtl8168_mdio_write(tp, 0x06, 0x2102); - rtl8168_mdio_write(tp, 0x06, 0x0c12); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xca02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xaec8); - rtl8168_mdio_write(tp, 0x06, 0x70e4); - rtl8168_mdio_write(tp, 0x06, 0x2602); - rtl8168_mdio_write(tp, 0x06, 0x82d1); - rtl8168_mdio_write(tp, 0x06, 0x05f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0xe2fe); - rtl8168_mdio_write(tp, 0x06, 0xe1e2); - rtl8168_mdio_write(tp, 0x06, 0xffad); - rtl8168_mdio_write(tp, 0x06, 0x2d1a); - rtl8168_mdio_write(tp, 0x06, 0xe0e1); - rtl8168_mdio_write(tp, 0x06, 0x4ee1); - rtl8168_mdio_write(tp, 0x06, 0xe14f); - rtl8168_mdio_write(tp, 0x06, 0xac2d); - rtl8168_mdio_write(tp, 0x06, 0x22f6); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x033b); - rtl8168_mdio_write(tp, 0x06, 0xf703); - rtl8168_mdio_write(tp, 0x06, 0xf706); - rtl8168_mdio_write(tp, 0x06, 0xbf84); - rtl8168_mdio_write(tp, 0x06, 0x4402); - rtl8168_mdio_write(tp, 0x06, 0x2d21); - rtl8168_mdio_write(tp, 0x06, 0xae11); - rtl8168_mdio_write(tp, 0x06, 0xe0e1); - rtl8168_mdio_write(tp, 0x06, 0x4ee1); - rtl8168_mdio_write(tp, 0x06, 0xe14f); - rtl8168_mdio_write(tp, 0x06, 0xad2d); - rtl8168_mdio_write(tp, 0x06, 0x08bf); - rtl8168_mdio_write(tp, 0x06, 0x844f); - rtl8168_mdio_write(tp, 0x06, 0x022d); - rtl8168_mdio_write(tp, 0x06, 0x21f6); - rtl8168_mdio_write(tp, 0x06, 0x06ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0x4502); - rtl8168_mdio_write(tp, 0x06, 0x83a2); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe001); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x1fd1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x843b); - rtl8168_mdio_write(tp, 0x06, 0x022d); - rtl8168_mdio_write(tp, 0x06, 0xc1e0); - rtl8168_mdio_write(tp, 0x06, 0xe020); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x21ad); - rtl8168_mdio_write(tp, 0x06, 0x200e); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf84); - rtl8168_mdio_write(tp, 0x06, 0x3b02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xbf3b); - rtl8168_mdio_write(tp, 0x06, 0x9602); - rtl8168_mdio_write(tp, 0x06, 0x2d21); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x204c); - rtl8168_mdio_write(tp, 0x06, 0xd200); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x0058); - rtl8168_mdio_write(tp, 0x06, 0x010c); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0x5810); - rtl8168_mdio_write(tp, 0x06, 0x1e20); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x3658); - rtl8168_mdio_write(tp, 0x06, 0x031e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xe01e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0x8b64); - rtl8168_mdio_write(tp, 0x06, 0x1f02); - rtl8168_mdio_write(tp, 0x06, 0x9e22); - rtl8168_mdio_write(tp, 0x06, 0xe68b); - rtl8168_mdio_write(tp, 0x06, 0x64ad); - rtl8168_mdio_write(tp, 0x06, 0x3214); - rtl8168_mdio_write(tp, 0x06, 0xad34); - rtl8168_mdio_write(tp, 0x06, 0x11ef); - rtl8168_mdio_write(tp, 0x06, 0x0258); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x07ad); - rtl8168_mdio_write(tp, 0x06, 0x3508); - rtl8168_mdio_write(tp, 0x06, 0x5ac0); - rtl8168_mdio_write(tp, 0x06, 0x9f04); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xae02); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf84); - rtl8168_mdio_write(tp, 0x06, 0x3e02); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfbe0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x22e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x23e2); - rtl8168_mdio_write(tp, 0x06, 0xe036); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0x375a); - rtl8168_mdio_write(tp, 0x06, 0xc40d); - rtl8168_mdio_write(tp, 0x06, 0x0158); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x20e3); - rtl8168_mdio_write(tp, 0x06, 0x8ae7); - rtl8168_mdio_write(tp, 0x06, 0xac31); - rtl8168_mdio_write(tp, 0x06, 0x60ac); - rtl8168_mdio_write(tp, 0x06, 0x3a08); - rtl8168_mdio_write(tp, 0x06, 0xac3e); - rtl8168_mdio_write(tp, 0x06, 0x26ae); - rtl8168_mdio_write(tp, 0x06, 0x67af); - rtl8168_mdio_write(tp, 0x06, 0x8437); - rtl8168_mdio_write(tp, 0x06, 0xad37); - rtl8168_mdio_write(tp, 0x06, 0x61e0); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xe91b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x51d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8441); - rtl8168_mdio_write(tp, 0x06, 0x022d); - rtl8168_mdio_write(tp, 0x06, 0xc1ee); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x43ad); - rtl8168_mdio_write(tp, 0x06, 0x3627); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xeee1); - rtl8168_mdio_write(tp, 0x06, 0x8aef); - rtl8168_mdio_write(tp, 0x06, 0xef74); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xeae1); - rtl8168_mdio_write(tp, 0x06, 0x8aeb); - rtl8168_mdio_write(tp, 0x06, 0x1b74); - rtl8168_mdio_write(tp, 0x06, 0x9e2e); - rtl8168_mdio_write(tp, 0x06, 0x14e4); - rtl8168_mdio_write(tp, 0x06, 0x8aea); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xebef); - rtl8168_mdio_write(tp, 0x06, 0x74e0); - rtl8168_mdio_write(tp, 0x06, 0x8aee); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xef1b); - rtl8168_mdio_write(tp, 0x06, 0x479e); - rtl8168_mdio_write(tp, 0x06, 0x0fae); - rtl8168_mdio_write(tp, 0x06, 0x19ee); - rtl8168_mdio_write(tp, 0x06, 0x8aea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8aeb); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x0fac); - rtl8168_mdio_write(tp, 0x06, 0x390c); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf84); - rtl8168_mdio_write(tp, 0x06, 0x4102); - rtl8168_mdio_write(tp, 0x06, 0x2dc1); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe800); - rtl8168_mdio_write(tp, 0x06, 0xe68a); - rtl8168_mdio_write(tp, 0x06, 0xe7ff); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x0400); - rtl8168_mdio_write(tp, 0x06, 0xe234); - rtl8168_mdio_write(tp, 0x06, 0xcce2); - rtl8168_mdio_write(tp, 0x06, 0x0088); - rtl8168_mdio_write(tp, 0x06, 0xe200); - rtl8168_mdio_write(tp, 0x06, 0xa725); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x1de5); - rtl8168_mdio_write(tp, 0x06, 0x0a2c); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x6de5); - rtl8168_mdio_write(tp, 0x06, 0x0a1d); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x1ce5); - rtl8168_mdio_write(tp, 0x06, 0x0a2d); - rtl8168_mdio_write(tp, 0x06, 0xa755); - rtl8168_mdio_write(tp, 0x05, 0x8b64); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8b94); - rtl8168_mdio_write(tp, 0x06, 0x82cd); - rtl8168_mdio_write(tp, 0x05, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0x2000); - rtl8168_mdio_write(tp, 0x05, 0x8aee); - rtl8168_mdio_write(tp, 0x06, 0x03b8); - rtl8168_mdio_write(tp, 0x05, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x01); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x01, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~(BIT_2); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0028); - rtl8168_mdio_write(tp, 0x15, 0x0010); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0041); - rtl8168_mdio_write(tp, 0x15, 0x0802); - rtl8168_mdio_write(tp, 0x16, 0x2185); - rtl8168_mdio_write(tp, 0x1f, 0x0000); -} - -static void -rtl8168_set_phy_mcu_8168e_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val,i; - - if (rtl8168_efuse_read(tp, 0x22) == 0x0c) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x1800); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x17, 0x0117); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - rtl8168_mdio_write(tp, 0x1B, 0x5000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x4104); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1E); - gphy_val &= 0x03FF; - if (gphy_val==0x000C) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x07); - if ((gphy_val & BIT_5) == 0) - break; - } - gphy_val = rtl8168_mdio_read(tp, 0x07); - if (gphy_val & BIT_5) { - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x00a1); - rtl8168_mdio_write(tp, 0x17, 0x1000); - rtl8168_mdio_write(tp, 0x17, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2000); - rtl8168_mdio_write(tp, 0x1e, 0x002f); - rtl8168_mdio_write(tp, 0x18, 0x9bfb); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x07, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x08); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x08, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x000e); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x0010); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x0018); - rtl8168_mdio_write(tp, 0x19, 0x4801); - rtl8168_mdio_write(tp, 0x15, 0x0019); - rtl8168_mdio_write(tp, 0x19, 0x6801); - rtl8168_mdio_write(tp, 0x15, 0x001a); - rtl8168_mdio_write(tp, 0x19, 0x66a1); - rtl8168_mdio_write(tp, 0x15, 0x001f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0020); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0021); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0022); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0023); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0024); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0025); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0026); - rtl8168_mdio_write(tp, 0x19, 0x40ea); - rtl8168_mdio_write(tp, 0x15, 0x0027); - rtl8168_mdio_write(tp, 0x19, 0x4503); - rtl8168_mdio_write(tp, 0x15, 0x0028); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0029); - rtl8168_mdio_write(tp, 0x19, 0xa631); - rtl8168_mdio_write(tp, 0x15, 0x002a); - rtl8168_mdio_write(tp, 0x19, 0x9717); - rtl8168_mdio_write(tp, 0x15, 0x002b); - rtl8168_mdio_write(tp, 0x19, 0x302c); - rtl8168_mdio_write(tp, 0x15, 0x002c); - rtl8168_mdio_write(tp, 0x19, 0x4802); - rtl8168_mdio_write(tp, 0x15, 0x002d); - rtl8168_mdio_write(tp, 0x19, 0x58da); - rtl8168_mdio_write(tp, 0x15, 0x002e); - rtl8168_mdio_write(tp, 0x19, 0x400d); - rtl8168_mdio_write(tp, 0x15, 0x002f); - rtl8168_mdio_write(tp, 0x19, 0x4488); - rtl8168_mdio_write(tp, 0x15, 0x0030); - rtl8168_mdio_write(tp, 0x19, 0x9e00); - rtl8168_mdio_write(tp, 0x15, 0x0031); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0032); - rtl8168_mdio_write(tp, 0x19, 0x6481); - rtl8168_mdio_write(tp, 0x15, 0x0033); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0034); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0035); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0036); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0037); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0038); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0039); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x003a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x003b); - rtl8168_mdio_write(tp, 0x19, 0x63e8); - rtl8168_mdio_write(tp, 0x15, 0x003c); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x003d); - rtl8168_mdio_write(tp, 0x19, 0x59d4); - rtl8168_mdio_write(tp, 0x15, 0x003e); - rtl8168_mdio_write(tp, 0x19, 0x63f8); - rtl8168_mdio_write(tp, 0x15, 0x0040); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0041); - rtl8168_mdio_write(tp, 0x19, 0x30de); - rtl8168_mdio_write(tp, 0x15, 0x0044); - rtl8168_mdio_write(tp, 0x19, 0x480f); - rtl8168_mdio_write(tp, 0x15, 0x0045); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x0046); - rtl8168_mdio_write(tp, 0x19, 0x6680); - rtl8168_mdio_write(tp, 0x15, 0x0047); - rtl8168_mdio_write(tp, 0x19, 0x7c10); - rtl8168_mdio_write(tp, 0x15, 0x0048); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0049); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004f); - rtl8168_mdio_write(tp, 0x19, 0x40ea); - rtl8168_mdio_write(tp, 0x15, 0x0050); - rtl8168_mdio_write(tp, 0x19, 0x4503); - rtl8168_mdio_write(tp, 0x15, 0x0051); - rtl8168_mdio_write(tp, 0x19, 0x58ca); - rtl8168_mdio_write(tp, 0x15, 0x0052); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0053); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x0054); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x0055); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0056); - rtl8168_mdio_write(tp, 0x19, 0x3000); - rtl8168_mdio_write(tp, 0x15, 0x00a1); - rtl8168_mdio_write(tp, 0x19, 0x3044); - rtl8168_mdio_write(tp, 0x15, 0x00ab); - rtl8168_mdio_write(tp, 0x19, 0x5820); - rtl8168_mdio_write(tp, 0x15, 0x00ac); - rtl8168_mdio_write(tp, 0x19, 0x5e04); - rtl8168_mdio_write(tp, 0x15, 0x00ad); - rtl8168_mdio_write(tp, 0x19, 0xb60c); - rtl8168_mdio_write(tp, 0x15, 0x00af); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x00b2); - rtl8168_mdio_write(tp, 0x19, 0x30b9); - rtl8168_mdio_write(tp, 0x15, 0x00b9); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x00ba); - rtl8168_mdio_write(tp, 0x19, 0x480b); - rtl8168_mdio_write(tp, 0x15, 0x00bb); - rtl8168_mdio_write(tp, 0x19, 0x5e00); - rtl8168_mdio_write(tp, 0x15, 0x00bc); - rtl8168_mdio_write(tp, 0x19, 0x405f); - rtl8168_mdio_write(tp, 0x15, 0x00bd); - rtl8168_mdio_write(tp, 0x19, 0x4448); - rtl8168_mdio_write(tp, 0x15, 0x00be); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x00bf); - rtl8168_mdio_write(tp, 0x19, 0x4468); - rtl8168_mdio_write(tp, 0x15, 0x00c0); - rtl8168_mdio_write(tp, 0x19, 0x9c02); - rtl8168_mdio_write(tp, 0x15, 0x00c1); - rtl8168_mdio_write(tp, 0x19, 0x58a0); - rtl8168_mdio_write(tp, 0x15, 0x00c2); - rtl8168_mdio_write(tp, 0x19, 0xb605); - rtl8168_mdio_write(tp, 0x15, 0x00c3); - rtl8168_mdio_write(tp, 0x19, 0xc0d3); - rtl8168_mdio_write(tp, 0x15, 0x00c4); - rtl8168_mdio_write(tp, 0x19, 0x00e6); - rtl8168_mdio_write(tp, 0x15, 0x00c5); - rtl8168_mdio_write(tp, 0x19, 0xdaec); - rtl8168_mdio_write(tp, 0x15, 0x00c6); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00c7); - rtl8168_mdio_write(tp, 0x19, 0x9df9); - rtl8168_mdio_write(tp, 0x15, 0x0112); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0113); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0114); - rtl8168_mdio_write(tp, 0x19, 0x63f0); - rtl8168_mdio_write(tp, 0x15, 0x0115); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0116); - rtl8168_mdio_write(tp, 0x19, 0x4418); - rtl8168_mdio_write(tp, 0x15, 0x0117); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x15, 0x0118); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0119); - rtl8168_mdio_write(tp, 0x19, 0x64e1); - rtl8168_mdio_write(tp, 0x15, 0x011a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0150); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0151); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0152); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0153); - rtl8168_mdio_write(tp, 0x19, 0x4540); - rtl8168_mdio_write(tp, 0x15, 0x0154); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0155); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x15, 0x0156); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0157); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0158); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0159); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x015a); - rtl8168_mdio_write(tp, 0x19, 0x30fe); - rtl8168_mdio_write(tp, 0x15, 0x029c); - rtl8168_mdio_write(tp, 0x19, 0x0070); - rtl8168_mdio_write(tp, 0x15, 0x02b2); - rtl8168_mdio_write(tp, 0x19, 0x005a); - rtl8168_mdio_write(tp, 0x15, 0x02bd); - rtl8168_mdio_write(tp, 0x19, 0xa522); - rtl8168_mdio_write(tp, 0x15, 0x02ce); - rtl8168_mdio_write(tp, 0x19, 0xb63e); - rtl8168_mdio_write(tp, 0x15, 0x02d9); - rtl8168_mdio_write(tp, 0x19, 0x32df); - rtl8168_mdio_write(tp, 0x15, 0x02df); - rtl8168_mdio_write(tp, 0x19, 0x4500); - rtl8168_mdio_write(tp, 0x15, 0x02e7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02f4); - rtl8168_mdio_write(tp, 0x19, 0xb618); - rtl8168_mdio_write(tp, 0x15, 0x02fb); - rtl8168_mdio_write(tp, 0x19, 0xb900); - rtl8168_mdio_write(tp, 0x15, 0x02fc); - rtl8168_mdio_write(tp, 0x19, 0x49b5); - rtl8168_mdio_write(tp, 0x15, 0x02fd); - rtl8168_mdio_write(tp, 0x19, 0x6812); - rtl8168_mdio_write(tp, 0x15, 0x02fe); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x02ff); - rtl8168_mdio_write(tp, 0x19, 0x9900); - rtl8168_mdio_write(tp, 0x15, 0x0300); - rtl8168_mdio_write(tp, 0x19, 0x64a0); - rtl8168_mdio_write(tp, 0x15, 0x0301); - rtl8168_mdio_write(tp, 0x19, 0x3316); - rtl8168_mdio_write(tp, 0x15, 0x0308); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030c); - rtl8168_mdio_write(tp, 0x19, 0x3000); - rtl8168_mdio_write(tp, 0x15, 0x0312); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0313); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0314); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0315); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0316); - rtl8168_mdio_write(tp, 0x19, 0x49b5); - rtl8168_mdio_write(tp, 0x15, 0x0317); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x0318); - rtl8168_mdio_write(tp, 0x19, 0x4d00); - rtl8168_mdio_write(tp, 0x15, 0x0319); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x031a); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x031b); - rtl8168_mdio_write(tp, 0x19, 0x4925); - rtl8168_mdio_write(tp, 0x15, 0x031c); - rtl8168_mdio_write(tp, 0x19, 0x403b); - rtl8168_mdio_write(tp, 0x15, 0x031d); - rtl8168_mdio_write(tp, 0x19, 0xa602); - rtl8168_mdio_write(tp, 0x15, 0x031e); - rtl8168_mdio_write(tp, 0x19, 0x402f); - rtl8168_mdio_write(tp, 0x15, 0x031f); - rtl8168_mdio_write(tp, 0x19, 0x4484); - rtl8168_mdio_write(tp, 0x15, 0x0320); - rtl8168_mdio_write(tp, 0x19, 0x40c8); - rtl8168_mdio_write(tp, 0x15, 0x0321); - rtl8168_mdio_write(tp, 0x19, 0x44c4); - rtl8168_mdio_write(tp, 0x15, 0x0322); - rtl8168_mdio_write(tp, 0x19, 0x404f); - rtl8168_mdio_write(tp, 0x15, 0x0323); - rtl8168_mdio_write(tp, 0x19, 0x44c8); - rtl8168_mdio_write(tp, 0x15, 0x0324); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0325); - rtl8168_mdio_write(tp, 0x19, 0x00e7); - rtl8168_mdio_write(tp, 0x15, 0x0326); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0327); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x0328); - rtl8168_mdio_write(tp, 0x19, 0x4d48); - rtl8168_mdio_write(tp, 0x15, 0x0329); - rtl8168_mdio_write(tp, 0x19, 0x332b); - rtl8168_mdio_write(tp, 0x15, 0x032a); - rtl8168_mdio_write(tp, 0x19, 0x4d40); - rtl8168_mdio_write(tp, 0x15, 0x032c); - rtl8168_mdio_write(tp, 0x19, 0x00f8); - rtl8168_mdio_write(tp, 0x15, 0x032d); - rtl8168_mdio_write(tp, 0x19, 0x82b2); - rtl8168_mdio_write(tp, 0x15, 0x032f); - rtl8168_mdio_write(tp, 0x19, 0x00b0); - rtl8168_mdio_write(tp, 0x15, 0x0332); - rtl8168_mdio_write(tp, 0x19, 0x91f2); - rtl8168_mdio_write(tp, 0x15, 0x033f); - rtl8168_mdio_write(tp, 0x19, 0xb6cd); - rtl8168_mdio_write(tp, 0x15, 0x0340); - rtl8168_mdio_write(tp, 0x19, 0x9e01); - rtl8168_mdio_write(tp, 0x15, 0x0341); - rtl8168_mdio_write(tp, 0x19, 0xd11d); - rtl8168_mdio_write(tp, 0x15, 0x0342); - rtl8168_mdio_write(tp, 0x19, 0x009d); - rtl8168_mdio_write(tp, 0x15, 0x0343); - rtl8168_mdio_write(tp, 0x19, 0xbb1c); - rtl8168_mdio_write(tp, 0x15, 0x0344); - rtl8168_mdio_write(tp, 0x19, 0x8102); - rtl8168_mdio_write(tp, 0x15, 0x0345); - rtl8168_mdio_write(tp, 0x19, 0x3348); - rtl8168_mdio_write(tp, 0x15, 0x0346); - rtl8168_mdio_write(tp, 0x19, 0xa231); - rtl8168_mdio_write(tp, 0x15, 0x0347); - rtl8168_mdio_write(tp, 0x19, 0x335b); - rtl8168_mdio_write(tp, 0x15, 0x0348); - rtl8168_mdio_write(tp, 0x19, 0x91f7); - rtl8168_mdio_write(tp, 0x15, 0x0349); - rtl8168_mdio_write(tp, 0x19, 0xc218); - rtl8168_mdio_write(tp, 0x15, 0x034a); - rtl8168_mdio_write(tp, 0x19, 0x00f5); - rtl8168_mdio_write(tp, 0x15, 0x034b); - rtl8168_mdio_write(tp, 0x19, 0x335b); - rtl8168_mdio_write(tp, 0x15, 0x034c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x034d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x034e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x034f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0350); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x035b); - rtl8168_mdio_write(tp, 0x19, 0xa23c); - rtl8168_mdio_write(tp, 0x15, 0x035c); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x035d); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x035e); - rtl8168_mdio_write(tp, 0x19, 0x3397); - rtl8168_mdio_write(tp, 0x15, 0x0363); - rtl8168_mdio_write(tp, 0x19, 0xb6a9); - rtl8168_mdio_write(tp, 0x15, 0x0366); - rtl8168_mdio_write(tp, 0x19, 0x00f5); - rtl8168_mdio_write(tp, 0x15, 0x0382); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0388); - rtl8168_mdio_write(tp, 0x19, 0x0084); - rtl8168_mdio_write(tp, 0x15, 0x0389); - rtl8168_mdio_write(tp, 0x19, 0xdd17); - rtl8168_mdio_write(tp, 0x15, 0x038a); - rtl8168_mdio_write(tp, 0x19, 0x000b); - rtl8168_mdio_write(tp, 0x15, 0x038b); - rtl8168_mdio_write(tp, 0x19, 0xa10a); - rtl8168_mdio_write(tp, 0x15, 0x038c); - rtl8168_mdio_write(tp, 0x19, 0x337e); - rtl8168_mdio_write(tp, 0x15, 0x038d); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x038e); - rtl8168_mdio_write(tp, 0x19, 0xa107); - rtl8168_mdio_write(tp, 0x15, 0x038f); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x0390); - rtl8168_mdio_write(tp, 0x19, 0xc017); - rtl8168_mdio_write(tp, 0x15, 0x0391); - rtl8168_mdio_write(tp, 0x19, 0x0004); - rtl8168_mdio_write(tp, 0x15, 0x0392); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0393); - rtl8168_mdio_write(tp, 0x19, 0x00f4); - rtl8168_mdio_write(tp, 0x15, 0x0397); - rtl8168_mdio_write(tp, 0x19, 0x4098); - rtl8168_mdio_write(tp, 0x15, 0x0398); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x0399); - rtl8168_mdio_write(tp, 0x19, 0x55bf); - rtl8168_mdio_write(tp, 0x15, 0x039a); - rtl8168_mdio_write(tp, 0x19, 0x4bb9); - rtl8168_mdio_write(tp, 0x15, 0x039b); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x039c); - rtl8168_mdio_write(tp, 0x19, 0x4b29); - rtl8168_mdio_write(tp, 0x15, 0x039d); - rtl8168_mdio_write(tp, 0x19, 0x4041); - rtl8168_mdio_write(tp, 0x15, 0x039e); - rtl8168_mdio_write(tp, 0x19, 0x442a); - rtl8168_mdio_write(tp, 0x15, 0x039f); - rtl8168_mdio_write(tp, 0x19, 0x4029); - rtl8168_mdio_write(tp, 0x15, 0x03aa); - rtl8168_mdio_write(tp, 0x19, 0x33b8); - rtl8168_mdio_write(tp, 0x15, 0x03b6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b8); - rtl8168_mdio_write(tp, 0x19, 0x543f); - rtl8168_mdio_write(tp, 0x15, 0x03b9); - rtl8168_mdio_write(tp, 0x19, 0x499a); - rtl8168_mdio_write(tp, 0x15, 0x03ba); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x03bb); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03bc); - rtl8168_mdio_write(tp, 0x19, 0x490a); - rtl8168_mdio_write(tp, 0x15, 0x03bd); - rtl8168_mdio_write(tp, 0x19, 0x405e); - rtl8168_mdio_write(tp, 0x15, 0x03c2); - rtl8168_mdio_write(tp, 0x19, 0x9a03); - rtl8168_mdio_write(tp, 0x15, 0x03c4); - rtl8168_mdio_write(tp, 0x19, 0x0015); - rtl8168_mdio_write(tp, 0x15, 0x03c5); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x03c8); - rtl8168_mdio_write(tp, 0x19, 0x9cf7); - rtl8168_mdio_write(tp, 0x15, 0x03c9); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03ca); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03cb); - rtl8168_mdio_write(tp, 0x19, 0x4458); - rtl8168_mdio_write(tp, 0x15, 0x03cd); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03ce); - rtl8168_mdio_write(tp, 0x19, 0x33bf); - rtl8168_mdio_write(tp, 0x15, 0x03cf); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d0); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d1); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d9); - rtl8168_mdio_write(tp, 0x19, 0x49bb); - rtl8168_mdio_write(tp, 0x15, 0x03da); - rtl8168_mdio_write(tp, 0x19, 0x4478); - rtl8168_mdio_write(tp, 0x15, 0x03db); - rtl8168_mdio_write(tp, 0x19, 0x492b); - rtl8168_mdio_write(tp, 0x15, 0x03dc); - rtl8168_mdio_write(tp, 0x19, 0x7c01); - rtl8168_mdio_write(tp, 0x15, 0x03dd); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x03de); - rtl8168_mdio_write(tp, 0x19, 0xbd1a); - rtl8168_mdio_write(tp, 0x15, 0x03df); - rtl8168_mdio_write(tp, 0x19, 0xc428); - rtl8168_mdio_write(tp, 0x15, 0x03e0); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x03e1); - rtl8168_mdio_write(tp, 0x19, 0x9cfd); - rtl8168_mdio_write(tp, 0x15, 0x03e2); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03e3); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03e4); - rtl8168_mdio_write(tp, 0x19, 0x4458); - rtl8168_mdio_write(tp, 0x15, 0x03e5); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03e6); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03e7); - rtl8168_mdio_write(tp, 0x19, 0x33de); - rtl8168_mdio_write(tp, 0x15, 0x03e8); - rtl8168_mdio_write(tp, 0x19, 0xc218); - rtl8168_mdio_write(tp, 0x15, 0x03e9); - rtl8168_mdio_write(tp, 0x19, 0x0002); - rtl8168_mdio_write(tp, 0x15, 0x03ea); - rtl8168_mdio_write(tp, 0x19, 0x32df); - rtl8168_mdio_write(tp, 0x15, 0x03eb); - rtl8168_mdio_write(tp, 0x19, 0x3316); - rtl8168_mdio_write(tp, 0x15, 0x03ec); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ed); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ee); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ef); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03f7); - rtl8168_mdio_write(tp, 0x19, 0x330c); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x0200); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x9002); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x0202); - rtl8168_mdio_write(tp, 0x06, 0x3402); - rtl8168_mdio_write(tp, 0x06, 0x027f); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0xa602); - rtl8168_mdio_write(tp, 0x06, 0x80bf); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe600); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xee03); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xefb8); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe902); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8285); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8520); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8701); - rtl8168_mdio_write(tp, 0x06, 0xd481); - rtl8168_mdio_write(tp, 0x06, 0x35e4); - rtl8168_mdio_write(tp, 0x06, 0x8b94); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x95bf); - rtl8168_mdio_write(tp, 0x06, 0x8b88); - rtl8168_mdio_write(tp, 0x06, 0xec00); - rtl8168_mdio_write(tp, 0x06, 0x19a9); - rtl8168_mdio_write(tp, 0x06, 0x8b90); - rtl8168_mdio_write(tp, 0x06, 0xf9ee); - rtl8168_mdio_write(tp, 0x06, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x41f7); - rtl8168_mdio_write(tp, 0x06, 0x2ff6); - rtl8168_mdio_write(tp, 0x06, 0x28e4); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xe5e1); - rtl8168_mdio_write(tp, 0x06, 0x4104); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x0dee); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x82f4); - rtl8168_mdio_write(tp, 0x06, 0x021f); - rtl8168_mdio_write(tp, 0x06, 0x4102); - rtl8168_mdio_write(tp, 0x06, 0x2812); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x10ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x139d); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xd602); - rtl8168_mdio_write(tp, 0x06, 0x1f99); - rtl8168_mdio_write(tp, 0x06, 0x0227); - rtl8168_mdio_write(tp, 0x06, 0xeafc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2014); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x8104); - rtl8168_mdio_write(tp, 0x06, 0x021b); - rtl8168_mdio_write(tp, 0x06, 0xf402); - rtl8168_mdio_write(tp, 0x06, 0x2c9c); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x7902); - rtl8168_mdio_write(tp, 0x06, 0x8443); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x11f6); - rtl8168_mdio_write(tp, 0x06, 0x22e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x022c); - rtl8168_mdio_write(tp, 0x06, 0x4602); - rtl8168_mdio_write(tp, 0x06, 0x2ac5); - rtl8168_mdio_write(tp, 0x06, 0x0229); - rtl8168_mdio_write(tp, 0x06, 0x2002); - rtl8168_mdio_write(tp, 0x06, 0x2b91); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x11f6); - rtl8168_mdio_write(tp, 0x06, 0x25e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0xe202); - rtl8168_mdio_write(tp, 0x06, 0x043a); - rtl8168_mdio_write(tp, 0x06, 0x021a); - rtl8168_mdio_write(tp, 0x06, 0x5902); - rtl8168_mdio_write(tp, 0x06, 0x2bfc); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe001); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x1fd1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8638); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50e0); - rtl8168_mdio_write(tp, 0x06, 0xe020); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x21ad); - rtl8168_mdio_write(tp, 0x06, 0x200e); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xbf3d); - rtl8168_mdio_write(tp, 0x06, 0x3902); - rtl8168_mdio_write(tp, 0x06, 0x2eb0); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x0402); - rtl8168_mdio_write(tp, 0x06, 0x8591); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x3c05); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xfee1); - rtl8168_mdio_write(tp, 0x06, 0xe2ff); - rtl8168_mdio_write(tp, 0x06, 0xad2d); - rtl8168_mdio_write(tp, 0x06, 0x1ae0); - rtl8168_mdio_write(tp, 0x06, 0xe14e); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x4fac); - rtl8168_mdio_write(tp, 0x06, 0x2d22); - rtl8168_mdio_write(tp, 0x06, 0xf603); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x36f7); - rtl8168_mdio_write(tp, 0x06, 0x03f7); - rtl8168_mdio_write(tp, 0x06, 0x06bf); - rtl8168_mdio_write(tp, 0x06, 0x8622); - rtl8168_mdio_write(tp, 0x06, 0x022e); - rtl8168_mdio_write(tp, 0x06, 0xb0ae); - rtl8168_mdio_write(tp, 0x06, 0x11e0); - rtl8168_mdio_write(tp, 0x06, 0xe14e); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x4fad); - rtl8168_mdio_write(tp, 0x06, 0x2d08); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x2d02); - rtl8168_mdio_write(tp, 0x06, 0x2eb0); - rtl8168_mdio_write(tp, 0x06, 0xf606); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x204c); - rtl8168_mdio_write(tp, 0x06, 0xd200); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x0058); - rtl8168_mdio_write(tp, 0x06, 0x010c); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0x5810); - rtl8168_mdio_write(tp, 0x06, 0x1e20); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x3658); - rtl8168_mdio_write(tp, 0x06, 0x031e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xe01e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0x8ae6); - rtl8168_mdio_write(tp, 0x06, 0x1f02); - rtl8168_mdio_write(tp, 0x06, 0x9e22); - rtl8168_mdio_write(tp, 0x06, 0xe68a); - rtl8168_mdio_write(tp, 0x06, 0xe6ad); - rtl8168_mdio_write(tp, 0x06, 0x3214); - rtl8168_mdio_write(tp, 0x06, 0xad34); - rtl8168_mdio_write(tp, 0x06, 0x11ef); - rtl8168_mdio_write(tp, 0x06, 0x0258); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x07ad); - rtl8168_mdio_write(tp, 0x06, 0x3508); - rtl8168_mdio_write(tp, 0x06, 0x5ac0); - rtl8168_mdio_write(tp, 0x06, 0x9f04); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xae02); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x3e02); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfae0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac26); - rtl8168_mdio_write(tp, 0x06, 0x0ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xac24); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x6bee); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xe0eb); - rtl8168_mdio_write(tp, 0x06, 0x00e2); - rtl8168_mdio_write(tp, 0x06, 0xe07c); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0x7da5); - rtl8168_mdio_write(tp, 0x06, 0x1111); - rtl8168_mdio_write(tp, 0x06, 0x15d2); - rtl8168_mdio_write(tp, 0x06, 0x60d6); - rtl8168_mdio_write(tp, 0x06, 0x6666); - rtl8168_mdio_write(tp, 0x06, 0x0207); - rtl8168_mdio_write(tp, 0x06, 0xf9d2); - rtl8168_mdio_write(tp, 0x06, 0xa0d6); - rtl8168_mdio_write(tp, 0x06, 0xaaaa); - rtl8168_mdio_write(tp, 0x06, 0x0207); - rtl8168_mdio_write(tp, 0x06, 0xf902); - rtl8168_mdio_write(tp, 0x06, 0x825c); - rtl8168_mdio_write(tp, 0x06, 0xae44); - rtl8168_mdio_write(tp, 0x06, 0xa566); - rtl8168_mdio_write(tp, 0x06, 0x6602); - rtl8168_mdio_write(tp, 0x06, 0xae38); - rtl8168_mdio_write(tp, 0x06, 0xa5aa); - rtl8168_mdio_write(tp, 0x06, 0xaa02); - rtl8168_mdio_write(tp, 0x06, 0xae32); - rtl8168_mdio_write(tp, 0x06, 0xeee0); - rtl8168_mdio_write(tp, 0x06, 0xea04); - rtl8168_mdio_write(tp, 0x06, 0xeee0); - rtl8168_mdio_write(tp, 0x06, 0xeb06); - rtl8168_mdio_write(tp, 0x06, 0xe2e0); - rtl8168_mdio_write(tp, 0x06, 0x7ce3); - rtl8168_mdio_write(tp, 0x06, 0xe07d); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x38e1); - rtl8168_mdio_write(tp, 0x06, 0xe039); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x21ad); - rtl8168_mdio_write(tp, 0x06, 0x3f13); - rtl8168_mdio_write(tp, 0x06, 0xe0e4); - rtl8168_mdio_write(tp, 0x06, 0x14e1); - rtl8168_mdio_write(tp, 0x06, 0xe415); - rtl8168_mdio_write(tp, 0x06, 0x6880); - rtl8168_mdio_write(tp, 0x06, 0xe4e4); - rtl8168_mdio_write(tp, 0x06, 0x14e5); - rtl8168_mdio_write(tp, 0x06, 0xe415); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x5cae); - rtl8168_mdio_write(tp, 0x06, 0x0bac); - rtl8168_mdio_write(tp, 0x06, 0x3e02); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x8602); - rtl8168_mdio_write(tp, 0x06, 0x82b0); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2605); - rtl8168_mdio_write(tp, 0x06, 0x0221); - rtl8168_mdio_write(tp, 0x06, 0xf3f7); - rtl8168_mdio_write(tp, 0x06, 0x28e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xad21); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x22f8); - rtl8168_mdio_write(tp, 0x06, 0xf729); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2405); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xebf7); - rtl8168_mdio_write(tp, 0x06, 0x2ae5); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x2134); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2109); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x2eac); - rtl8168_mdio_write(tp, 0x06, 0x2003); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0x52e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x09e0); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x8337); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2608); - rtl8168_mdio_write(tp, 0x06, 0xe085); - rtl8168_mdio_write(tp, 0x06, 0xd2ad); - rtl8168_mdio_write(tp, 0x06, 0x2502); - rtl8168_mdio_write(tp, 0x06, 0xf628); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x210a); - rtl8168_mdio_write(tp, 0x06, 0xe086); - rtl8168_mdio_write(tp, 0x06, 0x0af6); - rtl8168_mdio_write(tp, 0x06, 0x27a0); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0xf629); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2408); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xedad); - rtl8168_mdio_write(tp, 0x06, 0x2002); - rtl8168_mdio_write(tp, 0x06, 0xf62a); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x2ea1); - rtl8168_mdio_write(tp, 0x06, 0x0003); - rtl8168_mdio_write(tp, 0x06, 0x0221); - rtl8168_mdio_write(tp, 0x06, 0x11fc); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x8aed); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8aec); - rtl8168_mdio_write(tp, 0x06, 0x0004); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x3ae0); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xeb58); - rtl8168_mdio_write(tp, 0x06, 0xf8d1); - rtl8168_mdio_write(tp, 0x06, 0x01e4); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0xebe0); - rtl8168_mdio_write(tp, 0x06, 0xe07c); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x7d5c); - rtl8168_mdio_write(tp, 0x06, 0x00ff); - rtl8168_mdio_write(tp, 0x06, 0x3c00); - rtl8168_mdio_write(tp, 0x06, 0x1eab); - rtl8168_mdio_write(tp, 0x06, 0x1ce0); - rtl8168_mdio_write(tp, 0x06, 0xe04c); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x4d58); - rtl8168_mdio_write(tp, 0x06, 0xc1e4); - rtl8168_mdio_write(tp, 0x06, 0xe04c); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0x4de0); - rtl8168_mdio_write(tp, 0x06, 0xe0ee); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0x3ce4); - rtl8168_mdio_write(tp, 0x06, 0xe0ee); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0xeffc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2412); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0xeee1); - rtl8168_mdio_write(tp, 0x06, 0xe0ef); - rtl8168_mdio_write(tp, 0x06, 0x59c3); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0xeee5); - rtl8168_mdio_write(tp, 0x06, 0xe0ef); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xed01); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac25); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x8363); - rtl8168_mdio_write(tp, 0x06, 0xae03); - rtl8168_mdio_write(tp, 0x06, 0x0225); - rtl8168_mdio_write(tp, 0x06, 0x16fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfae0); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0xa000); - rtl8168_mdio_write(tp, 0x06, 0x19e0); - rtl8168_mdio_write(tp, 0x06, 0x860b); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x331b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x04aa); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x06ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0xe602); - rtl8168_mdio_write(tp, 0x06, 0x241e); - rtl8168_mdio_write(tp, 0x06, 0xae14); - rtl8168_mdio_write(tp, 0x06, 0xa001); - rtl8168_mdio_write(tp, 0x06, 0x1402); - rtl8168_mdio_write(tp, 0x06, 0x2426); - rtl8168_mdio_write(tp, 0x06, 0xbf26); - rtl8168_mdio_write(tp, 0x06, 0x6d02); - rtl8168_mdio_write(tp, 0x06, 0x2eb0); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0b00); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0a02); - rtl8168_mdio_write(tp, 0x06, 0xaf84); - rtl8168_mdio_write(tp, 0x06, 0x3ca0); - rtl8168_mdio_write(tp, 0x06, 0x0252); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0400); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0500); - rtl8168_mdio_write(tp, 0x06, 0xe086); - rtl8168_mdio_write(tp, 0x06, 0x0be1); - rtl8168_mdio_write(tp, 0x06, 0x8b32); - rtl8168_mdio_write(tp, 0x06, 0x1b10); - rtl8168_mdio_write(tp, 0x06, 0x9e04); - rtl8168_mdio_write(tp, 0x06, 0xaa02); - rtl8168_mdio_write(tp, 0x06, 0xaecb); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0b00); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x3ae2); - rtl8168_mdio_write(tp, 0x06, 0x8604); - rtl8168_mdio_write(tp, 0x06, 0xe386); - rtl8168_mdio_write(tp, 0x06, 0x05ef); - rtl8168_mdio_write(tp, 0x06, 0x65e2); - rtl8168_mdio_write(tp, 0x06, 0x8606); - rtl8168_mdio_write(tp, 0x06, 0xe386); - rtl8168_mdio_write(tp, 0x06, 0x071b); - rtl8168_mdio_write(tp, 0x06, 0x56aa); - rtl8168_mdio_write(tp, 0x06, 0x0eef); - rtl8168_mdio_write(tp, 0x06, 0x56e6); - rtl8168_mdio_write(tp, 0x06, 0x8606); - rtl8168_mdio_write(tp, 0x06, 0xe786); - rtl8168_mdio_write(tp, 0x06, 0x07e2); - rtl8168_mdio_write(tp, 0x06, 0x8609); - rtl8168_mdio_write(tp, 0x06, 0xe686); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8609); - rtl8168_mdio_write(tp, 0x06, 0xa000); - rtl8168_mdio_write(tp, 0x06, 0x07ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x03af); - rtl8168_mdio_write(tp, 0x06, 0x8369); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x2426); - rtl8168_mdio_write(tp, 0x06, 0xae48); - rtl8168_mdio_write(tp, 0x06, 0xa003); - rtl8168_mdio_write(tp, 0x06, 0x21e0); - rtl8168_mdio_write(tp, 0x06, 0x8608); - rtl8168_mdio_write(tp, 0x06, 0xe186); - rtl8168_mdio_write(tp, 0x06, 0x091b); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x0caa); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x249d); - rtl8168_mdio_write(tp, 0x06, 0xaee7); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x8eae); - rtl8168_mdio_write(tp, 0x06, 0xe2ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x860b); - rtl8168_mdio_write(tp, 0x06, 0x00af); - rtl8168_mdio_write(tp, 0x06, 0x8369); - rtl8168_mdio_write(tp, 0x06, 0xa004); - rtl8168_mdio_write(tp, 0x06, 0x15e0); - rtl8168_mdio_write(tp, 0x06, 0x860b); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x341b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x05aa); - rtl8168_mdio_write(tp, 0x06, 0x03af); - rtl8168_mdio_write(tp, 0x06, 0x8383); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0a05); - rtl8168_mdio_write(tp, 0x06, 0xae0c); - rtl8168_mdio_write(tp, 0x06, 0xa005); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x0702); - rtl8168_mdio_write(tp, 0x06, 0x2309); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0a00); - rtl8168_mdio_write(tp, 0x06, 0xfeef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfbe0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x22e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x23e2); - rtl8168_mdio_write(tp, 0x06, 0xe036); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0x375a); - rtl8168_mdio_write(tp, 0x06, 0xc40d); - rtl8168_mdio_write(tp, 0x06, 0x0158); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x20e3); - rtl8168_mdio_write(tp, 0x06, 0x8ae7); - rtl8168_mdio_write(tp, 0x06, 0xac31); - rtl8168_mdio_write(tp, 0x06, 0x60ac); - rtl8168_mdio_write(tp, 0x06, 0x3a08); - rtl8168_mdio_write(tp, 0x06, 0xac3e); - rtl8168_mdio_write(tp, 0x06, 0x26ae); - rtl8168_mdio_write(tp, 0x06, 0x67af); - rtl8168_mdio_write(tp, 0x06, 0x84db); - rtl8168_mdio_write(tp, 0x06, 0xad37); - rtl8168_mdio_write(tp, 0x06, 0x61e0); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xe91b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x51d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x863b); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50ee); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x43ad); - rtl8168_mdio_write(tp, 0x06, 0x3627); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xeee1); - rtl8168_mdio_write(tp, 0x06, 0x8aef); - rtl8168_mdio_write(tp, 0x06, 0xef74); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xeae1); - rtl8168_mdio_write(tp, 0x06, 0x8aeb); - rtl8168_mdio_write(tp, 0x06, 0x1b74); - rtl8168_mdio_write(tp, 0x06, 0x9e2e); - rtl8168_mdio_write(tp, 0x06, 0x14e4); - rtl8168_mdio_write(tp, 0x06, 0x8aea); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xebef); - rtl8168_mdio_write(tp, 0x06, 0x74e0); - rtl8168_mdio_write(tp, 0x06, 0x8aee); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xef1b); - rtl8168_mdio_write(tp, 0x06, 0x479e); - rtl8168_mdio_write(tp, 0x06, 0x0fae); - rtl8168_mdio_write(tp, 0x06, 0x19ee); - rtl8168_mdio_write(tp, 0x06, 0x8aea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8aeb); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x0fac); - rtl8168_mdio_write(tp, 0x06, 0x390c); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x3b02); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe800); - rtl8168_mdio_write(tp, 0x06, 0xe68a); - rtl8168_mdio_write(tp, 0x06, 0xe7ff); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xc4e1); - rtl8168_mdio_write(tp, 0x06, 0x8b6e); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e24); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x6ead); - rtl8168_mdio_write(tp, 0x06, 0x2218); - rtl8168_mdio_write(tp, 0x06, 0xac27); - rtl8168_mdio_write(tp, 0x06, 0x0dac); - rtl8168_mdio_write(tp, 0x06, 0x2605); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x8fae); - rtl8168_mdio_write(tp, 0x06, 0x1302); - rtl8168_mdio_write(tp, 0x06, 0x03c8); - rtl8168_mdio_write(tp, 0x06, 0xae0e); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0xe102); - rtl8168_mdio_write(tp, 0x06, 0x8520); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x8f02); - rtl8168_mdio_write(tp, 0x06, 0x8566); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x82ad); - rtl8168_mdio_write(tp, 0x06, 0x2737); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4402); - rtl8168_mdio_write(tp, 0x06, 0x2f23); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x2ed1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8647); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50bf); - rtl8168_mdio_write(tp, 0x06, 0x8641); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x23e5); - rtl8168_mdio_write(tp, 0x06, 0x8af0); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x22e1); - rtl8168_mdio_write(tp, 0x06, 0xe023); - rtl8168_mdio_write(tp, 0x06, 0xac2e); - rtl8168_mdio_write(tp, 0x06, 0x04d1); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0x02d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8641); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50d1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8644); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4702); - rtl8168_mdio_write(tp, 0x06, 0x2f23); - rtl8168_mdio_write(tp, 0x06, 0xad28); - rtl8168_mdio_write(tp, 0x06, 0x19d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8644); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50e1); - rtl8168_mdio_write(tp, 0x06, 0x8af0); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4102); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4702); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xfee1); - rtl8168_mdio_write(tp, 0x06, 0xe2ff); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x63e0); - rtl8168_mdio_write(tp, 0x06, 0xe038); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x39ad); - rtl8168_mdio_write(tp, 0x06, 0x2f10); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xf726); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xae0e); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e1); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xf728); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e5); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xf72b); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xd07d); - rtl8168_mdio_write(tp, 0x06, 0xb0fe); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xf62b); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xf626); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e1); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xf628); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e5); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xae20); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0xa725); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x1de5); - rtl8168_mdio_write(tp, 0x06, 0x0a2c); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x6de5); - rtl8168_mdio_write(tp, 0x06, 0x0a1d); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x1ce5); - rtl8168_mdio_write(tp, 0x06, 0x0a2d); - rtl8168_mdio_write(tp, 0x06, 0xa755); - rtl8168_mdio_write(tp, 0x06, 0x00e2); - rtl8168_mdio_write(tp, 0x06, 0x3488); - rtl8168_mdio_write(tp, 0x06, 0xe200); - rtl8168_mdio_write(tp, 0x06, 0xcce2); - rtl8168_mdio_write(tp, 0x06, 0x0055); - rtl8168_mdio_write(tp, 0x06, 0xe020); - rtl8168_mdio_write(tp, 0x06, 0x55e2); - rtl8168_mdio_write(tp, 0x06, 0xd600); - rtl8168_mdio_write(tp, 0x06, 0xe24a); - gphy_val = rtl8168_mdio_read(tp, 0x01); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x01, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2179); - rtl8168_mdio_write(tp, 0x1f, 0x0001); - rtl8168_mdio_write(tp, 0x10, 0xf274); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0042); - rtl8168_mdio_write(tp, 0x15, 0x0f00); - rtl8168_mdio_write(tp, 0x15, 0x0f00); - rtl8168_mdio_write(tp, 0x16, 0x7408); - rtl8168_mdio_write(tp, 0x15, 0x0e00); - rtl8168_mdio_write(tp, 0x15, 0x0f00); - rtl8168_mdio_write(tp, 0x15, 0x0f01); - rtl8168_mdio_write(tp, 0x16, 0x4000); - rtl8168_mdio_write(tp, 0x15, 0x0e01); - rtl8168_mdio_write(tp, 0x15, 0x0f01); - rtl8168_mdio_write(tp, 0x15, 0x0f02); - rtl8168_mdio_write(tp, 0x16, 0x9400); - rtl8168_mdio_write(tp, 0x15, 0x0e02); - rtl8168_mdio_write(tp, 0x15, 0x0f02); - rtl8168_mdio_write(tp, 0x15, 0x0f03); - rtl8168_mdio_write(tp, 0x16, 0x7408); - rtl8168_mdio_write(tp, 0x15, 0x0e03); - rtl8168_mdio_write(tp, 0x15, 0x0f03); - rtl8168_mdio_write(tp, 0x15, 0x0f04); - rtl8168_mdio_write(tp, 0x16, 0x4008); - rtl8168_mdio_write(tp, 0x15, 0x0e04); - rtl8168_mdio_write(tp, 0x15, 0x0f04); - rtl8168_mdio_write(tp, 0x15, 0x0f05); - rtl8168_mdio_write(tp, 0x16, 0x9400); - rtl8168_mdio_write(tp, 0x15, 0x0e05); - rtl8168_mdio_write(tp, 0x15, 0x0f05); - rtl8168_mdio_write(tp, 0x15, 0x0f06); - rtl8168_mdio_write(tp, 0x16, 0x0803); - rtl8168_mdio_write(tp, 0x15, 0x0e06); - rtl8168_mdio_write(tp, 0x15, 0x0f06); - rtl8168_mdio_write(tp, 0x15, 0x0d00); - rtl8168_mdio_write(tp, 0x15, 0x0100); - rtl8168_mdio_write(tp, 0x1f, 0x0001); - rtl8168_mdio_write(tp, 0x10, 0xf074); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2149); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~(BIT_2); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val |= BIT_14; - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1e, 0x0020); - gphy_val = rtl8168_mdio_read(tp, 0x1b); - gphy_val |= BIT_7; - rtl8168_mdio_write(tp, 0x1b, gphy_val); - rtl8168_mdio_write(tp, 0x1e, 0x0041); - rtl8168_mdio_write(tp, 0x15, 0x0e02); - rtl8168_mdio_write(tp, 0x1e, 0x0028); - gphy_val = rtl8168_mdio_read(tp, 0x19); - gphy_val |= BIT_15; - rtl8168_mdio_write(tp, 0x19, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } else { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x1800); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x17, 0x0117); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - rtl8168_mdio_write(tp, 0x1B, 0x5000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x4104); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1E); - gphy_val &= 0x03FF; - if (gphy_val==0x000C) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x07); - if ((gphy_val & BIT_5) == 0) - break; - } - gphy_val = rtl8168_mdio_read(tp, 0x07); - if (gphy_val & BIT_5) { - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x00a1); - rtl8168_mdio_write(tp, 0x17, 0x1000); - rtl8168_mdio_write(tp, 0x17, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2000); - rtl8168_mdio_write(tp, 0x1e, 0x002f); - rtl8168_mdio_write(tp, 0x18, 0x9bfb); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x07, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x08); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x08, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x000e); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x0010); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x0018); - rtl8168_mdio_write(tp, 0x19, 0x4801); - rtl8168_mdio_write(tp, 0x15, 0x0019); - rtl8168_mdio_write(tp, 0x19, 0x6801); - rtl8168_mdio_write(tp, 0x15, 0x001a); - rtl8168_mdio_write(tp, 0x19, 0x66a1); - rtl8168_mdio_write(tp, 0x15, 0x001f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0020); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0021); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0022); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0023); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0024); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0025); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0026); - rtl8168_mdio_write(tp, 0x19, 0x40ea); - rtl8168_mdio_write(tp, 0x15, 0x0027); - rtl8168_mdio_write(tp, 0x19, 0x4503); - rtl8168_mdio_write(tp, 0x15, 0x0028); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0029); - rtl8168_mdio_write(tp, 0x19, 0xa631); - rtl8168_mdio_write(tp, 0x15, 0x002a); - rtl8168_mdio_write(tp, 0x19, 0x9717); - rtl8168_mdio_write(tp, 0x15, 0x002b); - rtl8168_mdio_write(tp, 0x19, 0x302c); - rtl8168_mdio_write(tp, 0x15, 0x002c); - rtl8168_mdio_write(tp, 0x19, 0x4802); - rtl8168_mdio_write(tp, 0x15, 0x002d); - rtl8168_mdio_write(tp, 0x19, 0x58da); - rtl8168_mdio_write(tp, 0x15, 0x002e); - rtl8168_mdio_write(tp, 0x19, 0x400d); - rtl8168_mdio_write(tp, 0x15, 0x002f); - rtl8168_mdio_write(tp, 0x19, 0x4488); - rtl8168_mdio_write(tp, 0x15, 0x0030); - rtl8168_mdio_write(tp, 0x19, 0x9e00); - rtl8168_mdio_write(tp, 0x15, 0x0031); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0032); - rtl8168_mdio_write(tp, 0x19, 0x6481); - rtl8168_mdio_write(tp, 0x15, 0x0033); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0034); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0035); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0036); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0037); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0038); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0039); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x003a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x003b); - rtl8168_mdio_write(tp, 0x19, 0x63e8); - rtl8168_mdio_write(tp, 0x15, 0x003c); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x003d); - rtl8168_mdio_write(tp, 0x19, 0x59d4); - rtl8168_mdio_write(tp, 0x15, 0x003e); - rtl8168_mdio_write(tp, 0x19, 0x63f8); - rtl8168_mdio_write(tp, 0x15, 0x0040); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0041); - rtl8168_mdio_write(tp, 0x19, 0x30de); - rtl8168_mdio_write(tp, 0x15, 0x0044); - rtl8168_mdio_write(tp, 0x19, 0x480f); - rtl8168_mdio_write(tp, 0x15, 0x0045); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x0046); - rtl8168_mdio_write(tp, 0x19, 0x6680); - rtl8168_mdio_write(tp, 0x15, 0x0047); - rtl8168_mdio_write(tp, 0x19, 0x7c10); - rtl8168_mdio_write(tp, 0x15, 0x0048); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0049); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004f); - rtl8168_mdio_write(tp, 0x19, 0x40ea); - rtl8168_mdio_write(tp, 0x15, 0x0050); - rtl8168_mdio_write(tp, 0x19, 0x4503); - rtl8168_mdio_write(tp, 0x15, 0x0051); - rtl8168_mdio_write(tp, 0x19, 0x58ca); - rtl8168_mdio_write(tp, 0x15, 0x0052); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x0053); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x0054); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x0055); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0056); - rtl8168_mdio_write(tp, 0x19, 0x3000); - rtl8168_mdio_write(tp, 0x15, 0x00a1); - rtl8168_mdio_write(tp, 0x19, 0x3044); - rtl8168_mdio_write(tp, 0x15, 0x00ab); - rtl8168_mdio_write(tp, 0x19, 0x5820); - rtl8168_mdio_write(tp, 0x15, 0x00ac); - rtl8168_mdio_write(tp, 0x19, 0x5e04); - rtl8168_mdio_write(tp, 0x15, 0x00ad); - rtl8168_mdio_write(tp, 0x19, 0xb60c); - rtl8168_mdio_write(tp, 0x15, 0x00af); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x00b2); - rtl8168_mdio_write(tp, 0x19, 0x30b9); - rtl8168_mdio_write(tp, 0x15, 0x00b9); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x00ba); - rtl8168_mdio_write(tp, 0x19, 0x480b); - rtl8168_mdio_write(tp, 0x15, 0x00bb); - rtl8168_mdio_write(tp, 0x19, 0x5e00); - rtl8168_mdio_write(tp, 0x15, 0x00bc); - rtl8168_mdio_write(tp, 0x19, 0x405f); - rtl8168_mdio_write(tp, 0x15, 0x00bd); - rtl8168_mdio_write(tp, 0x19, 0x4448); - rtl8168_mdio_write(tp, 0x15, 0x00be); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x00bf); - rtl8168_mdio_write(tp, 0x19, 0x4468); - rtl8168_mdio_write(tp, 0x15, 0x00c0); - rtl8168_mdio_write(tp, 0x19, 0x9c02); - rtl8168_mdio_write(tp, 0x15, 0x00c1); - rtl8168_mdio_write(tp, 0x19, 0x58a0); - rtl8168_mdio_write(tp, 0x15, 0x00c2); - rtl8168_mdio_write(tp, 0x19, 0xb605); - rtl8168_mdio_write(tp, 0x15, 0x00c3); - rtl8168_mdio_write(tp, 0x19, 0xc0d3); - rtl8168_mdio_write(tp, 0x15, 0x00c4); - rtl8168_mdio_write(tp, 0x19, 0x00e6); - rtl8168_mdio_write(tp, 0x15, 0x00c5); - rtl8168_mdio_write(tp, 0x19, 0xdaec); - rtl8168_mdio_write(tp, 0x15, 0x00c6); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00c7); - rtl8168_mdio_write(tp, 0x19, 0x9df9); - rtl8168_mdio_write(tp, 0x15, 0x0112); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0113); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0114); - rtl8168_mdio_write(tp, 0x19, 0x63f0); - rtl8168_mdio_write(tp, 0x15, 0x0115); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0116); - rtl8168_mdio_write(tp, 0x19, 0x4418); - rtl8168_mdio_write(tp, 0x15, 0x0117); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x15, 0x0118); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0119); - rtl8168_mdio_write(tp, 0x19, 0x64e1); - rtl8168_mdio_write(tp, 0x15, 0x011a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0150); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0151); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0152); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0153); - rtl8168_mdio_write(tp, 0x19, 0x4540); - rtl8168_mdio_write(tp, 0x15, 0x0154); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0155); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x15, 0x0156); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0157); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0158); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0159); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x015a); - rtl8168_mdio_write(tp, 0x19, 0x30fe); - rtl8168_mdio_write(tp, 0x15, 0x029c); - rtl8168_mdio_write(tp, 0x19, 0x0070); - rtl8168_mdio_write(tp, 0x15, 0x02b2); - rtl8168_mdio_write(tp, 0x19, 0x005a); - rtl8168_mdio_write(tp, 0x15, 0x02bd); - rtl8168_mdio_write(tp, 0x19, 0xa522); - rtl8168_mdio_write(tp, 0x15, 0x02ce); - rtl8168_mdio_write(tp, 0x19, 0xb63e); - rtl8168_mdio_write(tp, 0x15, 0x02d9); - rtl8168_mdio_write(tp, 0x19, 0x32df); - rtl8168_mdio_write(tp, 0x15, 0x02df); - rtl8168_mdio_write(tp, 0x19, 0x4500); - rtl8168_mdio_write(tp, 0x15, 0x02f4); - rtl8168_mdio_write(tp, 0x19, 0xb618); - rtl8168_mdio_write(tp, 0x15, 0x02fb); - rtl8168_mdio_write(tp, 0x19, 0xb900); - rtl8168_mdio_write(tp, 0x15, 0x02fc); - rtl8168_mdio_write(tp, 0x19, 0x49b5); - rtl8168_mdio_write(tp, 0x15, 0x02fd); - rtl8168_mdio_write(tp, 0x19, 0x6812); - rtl8168_mdio_write(tp, 0x15, 0x02fe); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x02ff); - rtl8168_mdio_write(tp, 0x19, 0x9900); - rtl8168_mdio_write(tp, 0x15, 0x0300); - rtl8168_mdio_write(tp, 0x19, 0x64a0); - rtl8168_mdio_write(tp, 0x15, 0x0301); - rtl8168_mdio_write(tp, 0x19, 0x3316); - rtl8168_mdio_write(tp, 0x15, 0x0308); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030c); - rtl8168_mdio_write(tp, 0x19, 0x3000); - rtl8168_mdio_write(tp, 0x15, 0x0312); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0313); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0314); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0315); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0316); - rtl8168_mdio_write(tp, 0x19, 0x49b5); - rtl8168_mdio_write(tp, 0x15, 0x0317); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x0318); - rtl8168_mdio_write(tp, 0x19, 0x4d00); - rtl8168_mdio_write(tp, 0x15, 0x0319); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x031a); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x031b); - rtl8168_mdio_write(tp, 0x19, 0x4925); - rtl8168_mdio_write(tp, 0x15, 0x031c); - rtl8168_mdio_write(tp, 0x19, 0x403b); - rtl8168_mdio_write(tp, 0x15, 0x031d); - rtl8168_mdio_write(tp, 0x19, 0xa602); - rtl8168_mdio_write(tp, 0x15, 0x031e); - rtl8168_mdio_write(tp, 0x19, 0x402f); - rtl8168_mdio_write(tp, 0x15, 0x031f); - rtl8168_mdio_write(tp, 0x19, 0x4484); - rtl8168_mdio_write(tp, 0x15, 0x0320); - rtl8168_mdio_write(tp, 0x19, 0x40c8); - rtl8168_mdio_write(tp, 0x15, 0x0321); - rtl8168_mdio_write(tp, 0x19, 0x44c4); - rtl8168_mdio_write(tp, 0x15, 0x0322); - rtl8168_mdio_write(tp, 0x19, 0x404f); - rtl8168_mdio_write(tp, 0x15, 0x0323); - rtl8168_mdio_write(tp, 0x19, 0x44c8); - rtl8168_mdio_write(tp, 0x15, 0x0324); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0325); - rtl8168_mdio_write(tp, 0x19, 0x00e7); - rtl8168_mdio_write(tp, 0x15, 0x0326); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0327); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x0328); - rtl8168_mdio_write(tp, 0x19, 0x4d48); - rtl8168_mdio_write(tp, 0x15, 0x0329); - rtl8168_mdio_write(tp, 0x19, 0x332b); - rtl8168_mdio_write(tp, 0x15, 0x032a); - rtl8168_mdio_write(tp, 0x19, 0x4d40); - rtl8168_mdio_write(tp, 0x15, 0x032c); - rtl8168_mdio_write(tp, 0x19, 0x00f8); - rtl8168_mdio_write(tp, 0x15, 0x032d); - rtl8168_mdio_write(tp, 0x19, 0x82b2); - rtl8168_mdio_write(tp, 0x15, 0x032f); - rtl8168_mdio_write(tp, 0x19, 0x00b0); - rtl8168_mdio_write(tp, 0x15, 0x0332); - rtl8168_mdio_write(tp, 0x19, 0x91f2); - rtl8168_mdio_write(tp, 0x15, 0x033f); - rtl8168_mdio_write(tp, 0x19, 0xb6cd); - rtl8168_mdio_write(tp, 0x15, 0x0340); - rtl8168_mdio_write(tp, 0x19, 0x9e01); - rtl8168_mdio_write(tp, 0x15, 0x0341); - rtl8168_mdio_write(tp, 0x19, 0xd11d); - rtl8168_mdio_write(tp, 0x15, 0x0342); - rtl8168_mdio_write(tp, 0x19, 0x009d); - rtl8168_mdio_write(tp, 0x15, 0x0343); - rtl8168_mdio_write(tp, 0x19, 0xbb1c); - rtl8168_mdio_write(tp, 0x15, 0x0344); - rtl8168_mdio_write(tp, 0x19, 0x8102); - rtl8168_mdio_write(tp, 0x15, 0x0345); - rtl8168_mdio_write(tp, 0x19, 0x3348); - rtl8168_mdio_write(tp, 0x15, 0x0346); - rtl8168_mdio_write(tp, 0x19, 0xa231); - rtl8168_mdio_write(tp, 0x15, 0x0347); - rtl8168_mdio_write(tp, 0x19, 0x335b); - rtl8168_mdio_write(tp, 0x15, 0x0348); - rtl8168_mdio_write(tp, 0x19, 0x91f7); - rtl8168_mdio_write(tp, 0x15, 0x0349); - rtl8168_mdio_write(tp, 0x19, 0xc218); - rtl8168_mdio_write(tp, 0x15, 0x034a); - rtl8168_mdio_write(tp, 0x19, 0x00f5); - rtl8168_mdio_write(tp, 0x15, 0x034b); - rtl8168_mdio_write(tp, 0x19, 0x335b); - rtl8168_mdio_write(tp, 0x15, 0x034c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x034d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x034e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x034f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0350); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x035b); - rtl8168_mdio_write(tp, 0x19, 0xa23c); - rtl8168_mdio_write(tp, 0x15, 0x035c); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x035d); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x035e); - rtl8168_mdio_write(tp, 0x19, 0x3397); - rtl8168_mdio_write(tp, 0x15, 0x0363); - rtl8168_mdio_write(tp, 0x19, 0xb6a9); - rtl8168_mdio_write(tp, 0x15, 0x0366); - rtl8168_mdio_write(tp, 0x19, 0x00f5); - rtl8168_mdio_write(tp, 0x15, 0x0382); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0388); - rtl8168_mdio_write(tp, 0x19, 0x0084); - rtl8168_mdio_write(tp, 0x15, 0x0389); - rtl8168_mdio_write(tp, 0x19, 0xdd17); - rtl8168_mdio_write(tp, 0x15, 0x038a); - rtl8168_mdio_write(tp, 0x19, 0x000b); - rtl8168_mdio_write(tp, 0x15, 0x038b); - rtl8168_mdio_write(tp, 0x19, 0xa10a); - rtl8168_mdio_write(tp, 0x15, 0x038c); - rtl8168_mdio_write(tp, 0x19, 0x337e); - rtl8168_mdio_write(tp, 0x15, 0x038d); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x038e); - rtl8168_mdio_write(tp, 0x19, 0xa107); - rtl8168_mdio_write(tp, 0x15, 0x038f); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x0390); - rtl8168_mdio_write(tp, 0x19, 0xc017); - rtl8168_mdio_write(tp, 0x15, 0x0391); - rtl8168_mdio_write(tp, 0x19, 0x0004); - rtl8168_mdio_write(tp, 0x15, 0x0392); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0393); - rtl8168_mdio_write(tp, 0x19, 0x00f4); - rtl8168_mdio_write(tp, 0x15, 0x0397); - rtl8168_mdio_write(tp, 0x19, 0x4098); - rtl8168_mdio_write(tp, 0x15, 0x0398); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x0399); - rtl8168_mdio_write(tp, 0x19, 0x55bf); - rtl8168_mdio_write(tp, 0x15, 0x039a); - rtl8168_mdio_write(tp, 0x19, 0x4bb9); - rtl8168_mdio_write(tp, 0x15, 0x039b); - rtl8168_mdio_write(tp, 0x19, 0x6810); - rtl8168_mdio_write(tp, 0x15, 0x039c); - rtl8168_mdio_write(tp, 0x19, 0x4b29); - rtl8168_mdio_write(tp, 0x15, 0x039d); - rtl8168_mdio_write(tp, 0x19, 0x4041); - rtl8168_mdio_write(tp, 0x15, 0x039e); - rtl8168_mdio_write(tp, 0x19, 0x442a); - rtl8168_mdio_write(tp, 0x15, 0x039f); - rtl8168_mdio_write(tp, 0x19, 0x4029); - rtl8168_mdio_write(tp, 0x15, 0x03aa); - rtl8168_mdio_write(tp, 0x19, 0x33b8); - rtl8168_mdio_write(tp, 0x15, 0x03b6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b8); - rtl8168_mdio_write(tp, 0x19, 0x543f); - rtl8168_mdio_write(tp, 0x15, 0x03b9); - rtl8168_mdio_write(tp, 0x19, 0x499a); - rtl8168_mdio_write(tp, 0x15, 0x03ba); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x03bb); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03bc); - rtl8168_mdio_write(tp, 0x19, 0x490a); - rtl8168_mdio_write(tp, 0x15, 0x03bd); - rtl8168_mdio_write(tp, 0x19, 0x405e); - rtl8168_mdio_write(tp, 0x15, 0x03c2); - rtl8168_mdio_write(tp, 0x19, 0x9a03); - rtl8168_mdio_write(tp, 0x15, 0x03c4); - rtl8168_mdio_write(tp, 0x19, 0x0015); - rtl8168_mdio_write(tp, 0x15, 0x03c5); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x03c8); - rtl8168_mdio_write(tp, 0x19, 0x9cf7); - rtl8168_mdio_write(tp, 0x15, 0x03c9); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03ca); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03cb); - rtl8168_mdio_write(tp, 0x19, 0x4458); - rtl8168_mdio_write(tp, 0x15, 0x03cd); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03ce); - rtl8168_mdio_write(tp, 0x19, 0x33bf); - rtl8168_mdio_write(tp, 0x15, 0x03cf); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d0); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d1); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03d9); - rtl8168_mdio_write(tp, 0x19, 0x49bb); - rtl8168_mdio_write(tp, 0x15, 0x03da); - rtl8168_mdio_write(tp, 0x19, 0x4478); - rtl8168_mdio_write(tp, 0x15, 0x03db); - rtl8168_mdio_write(tp, 0x19, 0x492b); - rtl8168_mdio_write(tp, 0x15, 0x03dc); - rtl8168_mdio_write(tp, 0x19, 0x7c01); - rtl8168_mdio_write(tp, 0x15, 0x03dd); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x03de); - rtl8168_mdio_write(tp, 0x19, 0xbd1a); - rtl8168_mdio_write(tp, 0x15, 0x03df); - rtl8168_mdio_write(tp, 0x19, 0xc428); - rtl8168_mdio_write(tp, 0x15, 0x03e0); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x03e1); - rtl8168_mdio_write(tp, 0x19, 0x9cfd); - rtl8168_mdio_write(tp, 0x15, 0x03e2); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03e3); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03e4); - rtl8168_mdio_write(tp, 0x19, 0x4458); - rtl8168_mdio_write(tp, 0x15, 0x03e5); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03e6); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03e7); - rtl8168_mdio_write(tp, 0x19, 0x33de); - rtl8168_mdio_write(tp, 0x15, 0x03e8); - rtl8168_mdio_write(tp, 0x19, 0xc218); - rtl8168_mdio_write(tp, 0x15, 0x03e9); - rtl8168_mdio_write(tp, 0x19, 0x0002); - rtl8168_mdio_write(tp, 0x15, 0x03ea); - rtl8168_mdio_write(tp, 0x19, 0x32df); - rtl8168_mdio_write(tp, 0x15, 0x03eb); - rtl8168_mdio_write(tp, 0x19, 0x3316); - rtl8168_mdio_write(tp, 0x15, 0x03ec); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ed); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ee); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ef); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03f7); - rtl8168_mdio_write(tp, 0x19, 0x330c); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x0200); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x9002); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x0202); - rtl8168_mdio_write(tp, 0x06, 0x3402); - rtl8168_mdio_write(tp, 0x06, 0x027f); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0xa602); - rtl8168_mdio_write(tp, 0x06, 0x80bf); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe600); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xee03); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xefb8); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe902); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8285); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8520); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8701); - rtl8168_mdio_write(tp, 0x06, 0xd481); - rtl8168_mdio_write(tp, 0x06, 0x35e4); - rtl8168_mdio_write(tp, 0x06, 0x8b94); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x95bf); - rtl8168_mdio_write(tp, 0x06, 0x8b88); - rtl8168_mdio_write(tp, 0x06, 0xec00); - rtl8168_mdio_write(tp, 0x06, 0x19a9); - rtl8168_mdio_write(tp, 0x06, 0x8b90); - rtl8168_mdio_write(tp, 0x06, 0xf9ee); - rtl8168_mdio_write(tp, 0x06, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x41f7); - rtl8168_mdio_write(tp, 0x06, 0x2ff6); - rtl8168_mdio_write(tp, 0x06, 0x28e4); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xe5e1); - rtl8168_mdio_write(tp, 0x06, 0x4104); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x0dee); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x82f4); - rtl8168_mdio_write(tp, 0x06, 0x021f); - rtl8168_mdio_write(tp, 0x06, 0x4102); - rtl8168_mdio_write(tp, 0x06, 0x2812); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x10ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x139d); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xd602); - rtl8168_mdio_write(tp, 0x06, 0x1f99); - rtl8168_mdio_write(tp, 0x06, 0x0227); - rtl8168_mdio_write(tp, 0x06, 0xeafc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2014); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x8104); - rtl8168_mdio_write(tp, 0x06, 0x021b); - rtl8168_mdio_write(tp, 0x06, 0xf402); - rtl8168_mdio_write(tp, 0x06, 0x2c9c); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x7902); - rtl8168_mdio_write(tp, 0x06, 0x8443); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x11f6); - rtl8168_mdio_write(tp, 0x06, 0x22e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x022c); - rtl8168_mdio_write(tp, 0x06, 0x4602); - rtl8168_mdio_write(tp, 0x06, 0x2ac5); - rtl8168_mdio_write(tp, 0x06, 0x0229); - rtl8168_mdio_write(tp, 0x06, 0x2002); - rtl8168_mdio_write(tp, 0x06, 0x2b91); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x11f6); - rtl8168_mdio_write(tp, 0x06, 0x25e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0xe202); - rtl8168_mdio_write(tp, 0x06, 0x043a); - rtl8168_mdio_write(tp, 0x06, 0x021a); - rtl8168_mdio_write(tp, 0x06, 0x5902); - rtl8168_mdio_write(tp, 0x06, 0x2bfc); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe001); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x1fd1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8638); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50e0); - rtl8168_mdio_write(tp, 0x06, 0xe020); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x21ad); - rtl8168_mdio_write(tp, 0x06, 0x200e); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xbf3d); - rtl8168_mdio_write(tp, 0x06, 0x3902); - rtl8168_mdio_write(tp, 0x06, 0x2eb0); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x0402); - rtl8168_mdio_write(tp, 0x06, 0x8591); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x3c05); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xfee1); - rtl8168_mdio_write(tp, 0x06, 0xe2ff); - rtl8168_mdio_write(tp, 0x06, 0xad2d); - rtl8168_mdio_write(tp, 0x06, 0x1ae0); - rtl8168_mdio_write(tp, 0x06, 0xe14e); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x4fac); - rtl8168_mdio_write(tp, 0x06, 0x2d22); - rtl8168_mdio_write(tp, 0x06, 0xf603); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x36f7); - rtl8168_mdio_write(tp, 0x06, 0x03f7); - rtl8168_mdio_write(tp, 0x06, 0x06bf); - rtl8168_mdio_write(tp, 0x06, 0x8622); - rtl8168_mdio_write(tp, 0x06, 0x022e); - rtl8168_mdio_write(tp, 0x06, 0xb0ae); - rtl8168_mdio_write(tp, 0x06, 0x11e0); - rtl8168_mdio_write(tp, 0x06, 0xe14e); - rtl8168_mdio_write(tp, 0x06, 0xe1e1); - rtl8168_mdio_write(tp, 0x06, 0x4fad); - rtl8168_mdio_write(tp, 0x06, 0x2d08); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x2d02); - rtl8168_mdio_write(tp, 0x06, 0x2eb0); - rtl8168_mdio_write(tp, 0x06, 0xf606); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x204c); - rtl8168_mdio_write(tp, 0x06, 0xd200); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x0058); - rtl8168_mdio_write(tp, 0x06, 0x010c); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0x5810); - rtl8168_mdio_write(tp, 0x06, 0x1e20); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x3658); - rtl8168_mdio_write(tp, 0x06, 0x031e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xe01e); - rtl8168_mdio_write(tp, 0x06, 0x20e0); - rtl8168_mdio_write(tp, 0x06, 0x8ae6); - rtl8168_mdio_write(tp, 0x06, 0x1f02); - rtl8168_mdio_write(tp, 0x06, 0x9e22); - rtl8168_mdio_write(tp, 0x06, 0xe68a); - rtl8168_mdio_write(tp, 0x06, 0xe6ad); - rtl8168_mdio_write(tp, 0x06, 0x3214); - rtl8168_mdio_write(tp, 0x06, 0xad34); - rtl8168_mdio_write(tp, 0x06, 0x11ef); - rtl8168_mdio_write(tp, 0x06, 0x0258); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x07ad); - rtl8168_mdio_write(tp, 0x06, 0x3508); - rtl8168_mdio_write(tp, 0x06, 0x5ac0); - rtl8168_mdio_write(tp, 0x06, 0x9f04); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xae02); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x3e02); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfae0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac26); - rtl8168_mdio_write(tp, 0x06, 0x0ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xac24); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x6bee); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xe0eb); - rtl8168_mdio_write(tp, 0x06, 0x00e2); - rtl8168_mdio_write(tp, 0x06, 0xe07c); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0x7da5); - rtl8168_mdio_write(tp, 0x06, 0x1111); - rtl8168_mdio_write(tp, 0x06, 0x15d2); - rtl8168_mdio_write(tp, 0x06, 0x60d6); - rtl8168_mdio_write(tp, 0x06, 0x6666); - rtl8168_mdio_write(tp, 0x06, 0x0207); - rtl8168_mdio_write(tp, 0x06, 0xf9d2); - rtl8168_mdio_write(tp, 0x06, 0xa0d6); - rtl8168_mdio_write(tp, 0x06, 0xaaaa); - rtl8168_mdio_write(tp, 0x06, 0x0207); - rtl8168_mdio_write(tp, 0x06, 0xf902); - rtl8168_mdio_write(tp, 0x06, 0x825c); - rtl8168_mdio_write(tp, 0x06, 0xae44); - rtl8168_mdio_write(tp, 0x06, 0xa566); - rtl8168_mdio_write(tp, 0x06, 0x6602); - rtl8168_mdio_write(tp, 0x06, 0xae38); - rtl8168_mdio_write(tp, 0x06, 0xa5aa); - rtl8168_mdio_write(tp, 0x06, 0xaa02); - rtl8168_mdio_write(tp, 0x06, 0xae32); - rtl8168_mdio_write(tp, 0x06, 0xeee0); - rtl8168_mdio_write(tp, 0x06, 0xea04); - rtl8168_mdio_write(tp, 0x06, 0xeee0); - rtl8168_mdio_write(tp, 0x06, 0xeb06); - rtl8168_mdio_write(tp, 0x06, 0xe2e0); - rtl8168_mdio_write(tp, 0x06, 0x7ce3); - rtl8168_mdio_write(tp, 0x06, 0xe07d); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x38e1); - rtl8168_mdio_write(tp, 0x06, 0xe039); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x21ad); - rtl8168_mdio_write(tp, 0x06, 0x3f13); - rtl8168_mdio_write(tp, 0x06, 0xe0e4); - rtl8168_mdio_write(tp, 0x06, 0x14e1); - rtl8168_mdio_write(tp, 0x06, 0xe415); - rtl8168_mdio_write(tp, 0x06, 0x6880); - rtl8168_mdio_write(tp, 0x06, 0xe4e4); - rtl8168_mdio_write(tp, 0x06, 0x14e5); - rtl8168_mdio_write(tp, 0x06, 0xe415); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x5cae); - rtl8168_mdio_write(tp, 0x06, 0x0bac); - rtl8168_mdio_write(tp, 0x06, 0x3e02); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x8602); - rtl8168_mdio_write(tp, 0x06, 0x82b0); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2605); - rtl8168_mdio_write(tp, 0x06, 0x0221); - rtl8168_mdio_write(tp, 0x06, 0xf3f7); - rtl8168_mdio_write(tp, 0x06, 0x28e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xad21); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x22f8); - rtl8168_mdio_write(tp, 0x06, 0xf729); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2405); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xebf7); - rtl8168_mdio_write(tp, 0x06, 0x2ae5); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x2134); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2109); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x2eac); - rtl8168_mdio_write(tp, 0x06, 0x2003); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0x52e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x09e0); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x8337); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8b2e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2608); - rtl8168_mdio_write(tp, 0x06, 0xe085); - rtl8168_mdio_write(tp, 0x06, 0xd2ad); - rtl8168_mdio_write(tp, 0x06, 0x2502); - rtl8168_mdio_write(tp, 0x06, 0xf628); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x210a); - rtl8168_mdio_write(tp, 0x06, 0xe086); - rtl8168_mdio_write(tp, 0x06, 0x0af6); - rtl8168_mdio_write(tp, 0x06, 0x27a0); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0xf629); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2408); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xedad); - rtl8168_mdio_write(tp, 0x06, 0x2002); - rtl8168_mdio_write(tp, 0x06, 0xf62a); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x2ea1); - rtl8168_mdio_write(tp, 0x06, 0x0003); - rtl8168_mdio_write(tp, 0x06, 0x0221); - rtl8168_mdio_write(tp, 0x06, 0x11fc); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x8aed); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8aec); - rtl8168_mdio_write(tp, 0x06, 0x0004); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x3ae0); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xeb58); - rtl8168_mdio_write(tp, 0x06, 0xf8d1); - rtl8168_mdio_write(tp, 0x06, 0x01e4); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0xebe0); - rtl8168_mdio_write(tp, 0x06, 0xe07c); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x7d5c); - rtl8168_mdio_write(tp, 0x06, 0x00ff); - rtl8168_mdio_write(tp, 0x06, 0x3c00); - rtl8168_mdio_write(tp, 0x06, 0x1eab); - rtl8168_mdio_write(tp, 0x06, 0x1ce0); - rtl8168_mdio_write(tp, 0x06, 0xe04c); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x4d58); - rtl8168_mdio_write(tp, 0x06, 0xc1e4); - rtl8168_mdio_write(tp, 0x06, 0xe04c); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0x4de0); - rtl8168_mdio_write(tp, 0x06, 0xe0ee); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0x3ce4); - rtl8168_mdio_write(tp, 0x06, 0xe0ee); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0xeffc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2412); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0xeee1); - rtl8168_mdio_write(tp, 0x06, 0xe0ef); - rtl8168_mdio_write(tp, 0x06, 0x59c3); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0xeee5); - rtl8168_mdio_write(tp, 0x06, 0xe0ef); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xed01); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac25); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x8363); - rtl8168_mdio_write(tp, 0x06, 0xae03); - rtl8168_mdio_write(tp, 0x06, 0x0225); - rtl8168_mdio_write(tp, 0x06, 0x16fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfae0); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0xa000); - rtl8168_mdio_write(tp, 0x06, 0x19e0); - rtl8168_mdio_write(tp, 0x06, 0x860b); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x331b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x04aa); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x06ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0xe602); - rtl8168_mdio_write(tp, 0x06, 0x241e); - rtl8168_mdio_write(tp, 0x06, 0xae14); - rtl8168_mdio_write(tp, 0x06, 0xa001); - rtl8168_mdio_write(tp, 0x06, 0x1402); - rtl8168_mdio_write(tp, 0x06, 0x2426); - rtl8168_mdio_write(tp, 0x06, 0xbf26); - rtl8168_mdio_write(tp, 0x06, 0x6d02); - rtl8168_mdio_write(tp, 0x06, 0x2eb0); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0b00); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0a02); - rtl8168_mdio_write(tp, 0x06, 0xaf84); - rtl8168_mdio_write(tp, 0x06, 0x3ca0); - rtl8168_mdio_write(tp, 0x06, 0x0252); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0400); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0500); - rtl8168_mdio_write(tp, 0x06, 0xe086); - rtl8168_mdio_write(tp, 0x06, 0x0be1); - rtl8168_mdio_write(tp, 0x06, 0x8b32); - rtl8168_mdio_write(tp, 0x06, 0x1b10); - rtl8168_mdio_write(tp, 0x06, 0x9e04); - rtl8168_mdio_write(tp, 0x06, 0xaa02); - rtl8168_mdio_write(tp, 0x06, 0xaecb); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0b00); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x3ae2); - rtl8168_mdio_write(tp, 0x06, 0x8604); - rtl8168_mdio_write(tp, 0x06, 0xe386); - rtl8168_mdio_write(tp, 0x06, 0x05ef); - rtl8168_mdio_write(tp, 0x06, 0x65e2); - rtl8168_mdio_write(tp, 0x06, 0x8606); - rtl8168_mdio_write(tp, 0x06, 0xe386); - rtl8168_mdio_write(tp, 0x06, 0x071b); - rtl8168_mdio_write(tp, 0x06, 0x56aa); - rtl8168_mdio_write(tp, 0x06, 0x0eef); - rtl8168_mdio_write(tp, 0x06, 0x56e6); - rtl8168_mdio_write(tp, 0x06, 0x8606); - rtl8168_mdio_write(tp, 0x06, 0xe786); - rtl8168_mdio_write(tp, 0x06, 0x07e2); - rtl8168_mdio_write(tp, 0x06, 0x8609); - rtl8168_mdio_write(tp, 0x06, 0xe686); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8609); - rtl8168_mdio_write(tp, 0x06, 0xa000); - rtl8168_mdio_write(tp, 0x06, 0x07ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x03af); - rtl8168_mdio_write(tp, 0x06, 0x8369); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x2426); - rtl8168_mdio_write(tp, 0x06, 0xae48); - rtl8168_mdio_write(tp, 0x06, 0xa003); - rtl8168_mdio_write(tp, 0x06, 0x21e0); - rtl8168_mdio_write(tp, 0x06, 0x8608); - rtl8168_mdio_write(tp, 0x06, 0xe186); - rtl8168_mdio_write(tp, 0x06, 0x091b); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x0caa); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x249d); - rtl8168_mdio_write(tp, 0x06, 0xaee7); - rtl8168_mdio_write(tp, 0x06, 0x0224); - rtl8168_mdio_write(tp, 0x06, 0x8eae); - rtl8168_mdio_write(tp, 0x06, 0xe2ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x860b); - rtl8168_mdio_write(tp, 0x06, 0x00af); - rtl8168_mdio_write(tp, 0x06, 0x8369); - rtl8168_mdio_write(tp, 0x06, 0xa004); - rtl8168_mdio_write(tp, 0x06, 0x15e0); - rtl8168_mdio_write(tp, 0x06, 0x860b); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x341b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x05aa); - rtl8168_mdio_write(tp, 0x06, 0x03af); - rtl8168_mdio_write(tp, 0x06, 0x8383); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0a05); - rtl8168_mdio_write(tp, 0x06, 0xae0c); - rtl8168_mdio_write(tp, 0x06, 0xa005); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x0702); - rtl8168_mdio_write(tp, 0x06, 0x2309); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0a00); - rtl8168_mdio_write(tp, 0x06, 0xfeef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfbe0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x22e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x23e2); - rtl8168_mdio_write(tp, 0x06, 0xe036); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0x375a); - rtl8168_mdio_write(tp, 0x06, 0xc40d); - rtl8168_mdio_write(tp, 0x06, 0x0158); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x20e3); - rtl8168_mdio_write(tp, 0x06, 0x8ae7); - rtl8168_mdio_write(tp, 0x06, 0xac31); - rtl8168_mdio_write(tp, 0x06, 0x60ac); - rtl8168_mdio_write(tp, 0x06, 0x3a08); - rtl8168_mdio_write(tp, 0x06, 0xac3e); - rtl8168_mdio_write(tp, 0x06, 0x26ae); - rtl8168_mdio_write(tp, 0x06, 0x67af); - rtl8168_mdio_write(tp, 0x06, 0x84db); - rtl8168_mdio_write(tp, 0x06, 0xad37); - rtl8168_mdio_write(tp, 0x06, 0x61e0); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xe91b); - rtl8168_mdio_write(tp, 0x06, 0x109e); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x51d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x863b); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50ee); - rtl8168_mdio_write(tp, 0x06, 0x8ae8); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x43ad); - rtl8168_mdio_write(tp, 0x06, 0x3627); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xeee1); - rtl8168_mdio_write(tp, 0x06, 0x8aef); - rtl8168_mdio_write(tp, 0x06, 0xef74); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xeae1); - rtl8168_mdio_write(tp, 0x06, 0x8aeb); - rtl8168_mdio_write(tp, 0x06, 0x1b74); - rtl8168_mdio_write(tp, 0x06, 0x9e2e); - rtl8168_mdio_write(tp, 0x06, 0x14e4); - rtl8168_mdio_write(tp, 0x06, 0x8aea); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xebef); - rtl8168_mdio_write(tp, 0x06, 0x74e0); - rtl8168_mdio_write(tp, 0x06, 0x8aee); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xef1b); - rtl8168_mdio_write(tp, 0x06, 0x479e); - rtl8168_mdio_write(tp, 0x06, 0x0fae); - rtl8168_mdio_write(tp, 0x06, 0x19ee); - rtl8168_mdio_write(tp, 0x06, 0x8aea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8aeb); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0x0fac); - rtl8168_mdio_write(tp, 0x06, 0x390c); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x3b02); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xe800); - rtl8168_mdio_write(tp, 0x06, 0xe68a); - rtl8168_mdio_write(tp, 0x06, 0xe7ff); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xc4e1); - rtl8168_mdio_write(tp, 0x06, 0x8b6e); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e24); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x6ead); - rtl8168_mdio_write(tp, 0x06, 0x2218); - rtl8168_mdio_write(tp, 0x06, 0xac27); - rtl8168_mdio_write(tp, 0x06, 0x0dac); - rtl8168_mdio_write(tp, 0x06, 0x2605); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x8fae); - rtl8168_mdio_write(tp, 0x06, 0x1302); - rtl8168_mdio_write(tp, 0x06, 0x03c8); - rtl8168_mdio_write(tp, 0x06, 0xae0e); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0xe102); - rtl8168_mdio_write(tp, 0x06, 0x8520); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x8f02); - rtl8168_mdio_write(tp, 0x06, 0x8566); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x82ad); - rtl8168_mdio_write(tp, 0x06, 0x2737); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4402); - rtl8168_mdio_write(tp, 0x06, 0x2f23); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x2ed1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8647); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50bf); - rtl8168_mdio_write(tp, 0x06, 0x8641); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x23e5); - rtl8168_mdio_write(tp, 0x06, 0x8af0); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x22e1); - rtl8168_mdio_write(tp, 0x06, 0xe023); - rtl8168_mdio_write(tp, 0x06, 0xac2e); - rtl8168_mdio_write(tp, 0x06, 0x04d1); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0x02d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8641); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50d1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8644); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4702); - rtl8168_mdio_write(tp, 0x06, 0x2f23); - rtl8168_mdio_write(tp, 0x06, 0xad28); - rtl8168_mdio_write(tp, 0x06, 0x19d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8644); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x50e1); - rtl8168_mdio_write(tp, 0x06, 0x8af0); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4102); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x4702); - rtl8168_mdio_write(tp, 0x06, 0x2f50); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xfee1); - rtl8168_mdio_write(tp, 0x06, 0xe2ff); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x63e0); - rtl8168_mdio_write(tp, 0x06, 0xe038); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x39ad); - rtl8168_mdio_write(tp, 0x06, 0x2f10); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xf726); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xae0e); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e1); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xf728); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e5); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xf72b); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xd07d); - rtl8168_mdio_write(tp, 0x06, 0xb0fe); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xf62b); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xf626); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe035); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e1); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xf628); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0xd6e5); - rtl8168_mdio_write(tp, 0x06, 0xe2d7); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xae20); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0xa725); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x1de5); - rtl8168_mdio_write(tp, 0x06, 0x0a2c); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x6de5); - rtl8168_mdio_write(tp, 0x06, 0x0a1d); - rtl8168_mdio_write(tp, 0x06, 0xe50a); - rtl8168_mdio_write(tp, 0x06, 0x1ce5); - rtl8168_mdio_write(tp, 0x06, 0x0a2d); - rtl8168_mdio_write(tp, 0x06, 0xa755); - rtl8168_mdio_write(tp, 0x06, 0x00e2); - rtl8168_mdio_write(tp, 0x06, 0x3488); - rtl8168_mdio_write(tp, 0x06, 0xe200); - rtl8168_mdio_write(tp, 0x06, 0xcce2); - rtl8168_mdio_write(tp, 0x06, 0x0055); - rtl8168_mdio_write(tp, 0x06, 0xe020); - rtl8168_mdio_write(tp, 0x06, 0x55e2); - rtl8168_mdio_write(tp, 0x06, 0xd600); - rtl8168_mdio_write(tp, 0x06, 0xe24a); - gphy_val = rtl8168_mdio_read(tp, 0x01); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x01, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~(BIT_2); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } -} - -static void -rtl8168_set_phy_mcu_8168evl_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val,i; - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x1800); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val &= ~(BIT_12); - rtl8168_mdio_write(tp, 0x15, gphy_val); - mdelay(20); - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - if ((gphy_val & BIT_11) == 0x0000) { - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x17, gphy_val); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x17); - if (gphy_val & BIT_11) - break; - } - } - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - rtl8168_mdio_write(tp, 0x1B, 0x5000); - rtl8168_mdio_write(tp, 0x1E, 0x002d); - rtl8168_mdio_write(tp, 0x19, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1E); - if ((gphy_val & 0x03FF) == 0x0014) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x07); - if ((gphy_val & BIT_5) == 0) - break; - } - gphy_val = rtl8168_mdio_read(tp, 0x07); - if (gphy_val & BIT_5) { - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x00a1); - rtl8168_mdio_write(tp, 0x17, 0x1000); - rtl8168_mdio_write(tp, 0x17, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2000); - rtl8168_mdio_write(tp, 0x1e, 0x002f); - rtl8168_mdio_write(tp, 0x18, 0x9bfb); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x07, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - gphy_val = rtl8168_mdio_read(tp, 0x00); - gphy_val &= ~(BIT_7); - rtl8168_mdio_write(tp, 0x00, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x0000); - rtl8168_mdio_write(tp, 0x19, 0x407d); - rtl8168_mdio_write(tp, 0x15, 0x0001); - rtl8168_mdio_write(tp, 0x19, 0x440f); - rtl8168_mdio_write(tp, 0x15, 0x0002); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0003); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x0004); - rtl8168_mdio_write(tp, 0x19, 0xc4d5); - rtl8168_mdio_write(tp, 0x15, 0x0005); - rtl8168_mdio_write(tp, 0x19, 0x00ff); - rtl8168_mdio_write(tp, 0x15, 0x0006); - rtl8168_mdio_write(tp, 0x19, 0x74f0); - rtl8168_mdio_write(tp, 0x15, 0x0007); - rtl8168_mdio_write(tp, 0x19, 0x4880); - rtl8168_mdio_write(tp, 0x15, 0x0008); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x0009); - rtl8168_mdio_write(tp, 0x19, 0x4800); - rtl8168_mdio_write(tp, 0x15, 0x000a); - rtl8168_mdio_write(tp, 0x19, 0x5000); - rtl8168_mdio_write(tp, 0x15, 0x000b); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x000c); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x000d); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x15, 0x000e); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x000f); - rtl8168_mdio_write(tp, 0x19, 0x7010); - rtl8168_mdio_write(tp, 0x15, 0x0010); - rtl8168_mdio_write(tp, 0x19, 0x6804); - rtl8168_mdio_write(tp, 0x15, 0x0011); - rtl8168_mdio_write(tp, 0x19, 0x64a0); - rtl8168_mdio_write(tp, 0x15, 0x0012); - rtl8168_mdio_write(tp, 0x19, 0x63da); - rtl8168_mdio_write(tp, 0x15, 0x0013); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x0014); - rtl8168_mdio_write(tp, 0x19, 0x6f05); - rtl8168_mdio_write(tp, 0x15, 0x0015); - rtl8168_mdio_write(tp, 0x19, 0x5420); - rtl8168_mdio_write(tp, 0x15, 0x0016); - rtl8168_mdio_write(tp, 0x19, 0x58ce); - rtl8168_mdio_write(tp, 0x15, 0x0017); - rtl8168_mdio_write(tp, 0x19, 0x5cf3); - rtl8168_mdio_write(tp, 0x15, 0x0018); - rtl8168_mdio_write(tp, 0x19, 0xb600); - rtl8168_mdio_write(tp, 0x15, 0x0019); - rtl8168_mdio_write(tp, 0x19, 0xc659); - rtl8168_mdio_write(tp, 0x15, 0x001a); - rtl8168_mdio_write(tp, 0x19, 0x0018); - rtl8168_mdio_write(tp, 0x15, 0x001b); - rtl8168_mdio_write(tp, 0x19, 0xc403); - rtl8168_mdio_write(tp, 0x15, 0x001c); - rtl8168_mdio_write(tp, 0x19, 0x0016); - rtl8168_mdio_write(tp, 0x15, 0x001d); - rtl8168_mdio_write(tp, 0x19, 0xaa05); - rtl8168_mdio_write(tp, 0x15, 0x001e); - rtl8168_mdio_write(tp, 0x19, 0xc503); - rtl8168_mdio_write(tp, 0x15, 0x001f); - rtl8168_mdio_write(tp, 0x19, 0x0003); - rtl8168_mdio_write(tp, 0x15, 0x0020); - rtl8168_mdio_write(tp, 0x19, 0x89f8); - rtl8168_mdio_write(tp, 0x15, 0x0021); - rtl8168_mdio_write(tp, 0x19, 0x32ae); - rtl8168_mdio_write(tp, 0x15, 0x0022); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0023); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x0024); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0025); - rtl8168_mdio_write(tp, 0x19, 0x6801); - rtl8168_mdio_write(tp, 0x15, 0x0026); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x0027); - rtl8168_mdio_write(tp, 0x19, 0xa300); - rtl8168_mdio_write(tp, 0x15, 0x0028); - rtl8168_mdio_write(tp, 0x19, 0x64a0); - rtl8168_mdio_write(tp, 0x15, 0x0029); - rtl8168_mdio_write(tp, 0x19, 0x76f0); - rtl8168_mdio_write(tp, 0x15, 0x002a); - rtl8168_mdio_write(tp, 0x19, 0x7670); - rtl8168_mdio_write(tp, 0x15, 0x002b); - rtl8168_mdio_write(tp, 0x19, 0x7630); - rtl8168_mdio_write(tp, 0x15, 0x002c); - rtl8168_mdio_write(tp, 0x19, 0x31a6); - rtl8168_mdio_write(tp, 0x15, 0x002d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x002e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x002f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0030); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0031); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0032); - rtl8168_mdio_write(tp, 0x19, 0x4801); - rtl8168_mdio_write(tp, 0x15, 0x0033); - rtl8168_mdio_write(tp, 0x19, 0x6803); - rtl8168_mdio_write(tp, 0x15, 0x0034); - rtl8168_mdio_write(tp, 0x19, 0x66a1); - rtl8168_mdio_write(tp, 0x15, 0x0035); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0036); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x0037); - rtl8168_mdio_write(tp, 0x19, 0xa300); - rtl8168_mdio_write(tp, 0x15, 0x0038); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0039); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x003a); - rtl8168_mdio_write(tp, 0x19, 0x74f8); - rtl8168_mdio_write(tp, 0x15, 0x003b); - rtl8168_mdio_write(tp, 0x19, 0x63d0); - rtl8168_mdio_write(tp, 0x15, 0x003c); - rtl8168_mdio_write(tp, 0x19, 0x7ff0); - rtl8168_mdio_write(tp, 0x15, 0x003d); - rtl8168_mdio_write(tp, 0x19, 0x77f0); - rtl8168_mdio_write(tp, 0x15, 0x003e); - rtl8168_mdio_write(tp, 0x19, 0x7ff0); - rtl8168_mdio_write(tp, 0x15, 0x003f); - rtl8168_mdio_write(tp, 0x19, 0x7750); - rtl8168_mdio_write(tp, 0x15, 0x0040); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x0041); - rtl8168_mdio_write(tp, 0x19, 0x7cf0); - rtl8168_mdio_write(tp, 0x15, 0x0042); - rtl8168_mdio_write(tp, 0x19, 0x7708); - rtl8168_mdio_write(tp, 0x15, 0x0043); - rtl8168_mdio_write(tp, 0x19, 0xa654); - rtl8168_mdio_write(tp, 0x15, 0x0044); - rtl8168_mdio_write(tp, 0x19, 0x304a); - rtl8168_mdio_write(tp, 0x15, 0x0045); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0046); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0047); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0048); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0049); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x004a); - rtl8168_mdio_write(tp, 0x19, 0x4802); - rtl8168_mdio_write(tp, 0x15, 0x004b); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x004c); - rtl8168_mdio_write(tp, 0x19, 0x4440); - rtl8168_mdio_write(tp, 0x15, 0x004d); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x004e); - rtl8168_mdio_write(tp, 0x19, 0x6481); - rtl8168_mdio_write(tp, 0x15, 0x004f); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x15, 0x0050); - rtl8168_mdio_write(tp, 0x19, 0x63e8); - rtl8168_mdio_write(tp, 0x15, 0x0051); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x0052); - rtl8168_mdio_write(tp, 0x19, 0x5900); - rtl8168_mdio_write(tp, 0x15, 0x0053); - rtl8168_mdio_write(tp, 0x19, 0x63f8); - rtl8168_mdio_write(tp, 0x15, 0x0054); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0055); - rtl8168_mdio_write(tp, 0x19, 0x3116); - rtl8168_mdio_write(tp, 0x15, 0x0056); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0057); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0058); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0059); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x005a); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x005b); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x005c); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x005d); - rtl8168_mdio_write(tp, 0x19, 0x6000); - rtl8168_mdio_write(tp, 0x15, 0x005e); - rtl8168_mdio_write(tp, 0x19, 0x59ce); - rtl8168_mdio_write(tp, 0x15, 0x005f); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x0060); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x0061); - rtl8168_mdio_write(tp, 0x19, 0x72b0); - rtl8168_mdio_write(tp, 0x15, 0x0062); - rtl8168_mdio_write(tp, 0x19, 0x400e); - rtl8168_mdio_write(tp, 0x15, 0x0063); - rtl8168_mdio_write(tp, 0x19, 0x4440); - rtl8168_mdio_write(tp, 0x15, 0x0064); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x15, 0x0065); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x15, 0x0066); - rtl8168_mdio_write(tp, 0x19, 0x70b0); - rtl8168_mdio_write(tp, 0x15, 0x0067); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0068); - rtl8168_mdio_write(tp, 0x19, 0x6008); - rtl8168_mdio_write(tp, 0x15, 0x0069); - rtl8168_mdio_write(tp, 0x19, 0x7cf0); - rtl8168_mdio_write(tp, 0x15, 0x006a); - rtl8168_mdio_write(tp, 0x19, 0x7750); - rtl8168_mdio_write(tp, 0x15, 0x006b); - rtl8168_mdio_write(tp, 0x19, 0x4007); - rtl8168_mdio_write(tp, 0x15, 0x006c); - rtl8168_mdio_write(tp, 0x19, 0x4500); - rtl8168_mdio_write(tp, 0x15, 0x006d); - rtl8168_mdio_write(tp, 0x19, 0x4023); - rtl8168_mdio_write(tp, 0x15, 0x006e); - rtl8168_mdio_write(tp, 0x19, 0x4580); - rtl8168_mdio_write(tp, 0x15, 0x006f); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x0070); - rtl8168_mdio_write(tp, 0x19, 0xcd78); - rtl8168_mdio_write(tp, 0x15, 0x0071); - rtl8168_mdio_write(tp, 0x19, 0x0003); - rtl8168_mdio_write(tp, 0x15, 0x0072); - rtl8168_mdio_write(tp, 0x19, 0xbe02); - rtl8168_mdio_write(tp, 0x15, 0x0073); - rtl8168_mdio_write(tp, 0x19, 0x3070); - rtl8168_mdio_write(tp, 0x15, 0x0074); - rtl8168_mdio_write(tp, 0x19, 0x7cf0); - rtl8168_mdio_write(tp, 0x15, 0x0075); - rtl8168_mdio_write(tp, 0x19, 0x77f0); - rtl8168_mdio_write(tp, 0x15, 0x0076); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x0077); - rtl8168_mdio_write(tp, 0x19, 0x4007); - rtl8168_mdio_write(tp, 0x15, 0x0078); - rtl8168_mdio_write(tp, 0x19, 0x4500); - rtl8168_mdio_write(tp, 0x15, 0x0079); - rtl8168_mdio_write(tp, 0x19, 0x4023); - rtl8168_mdio_write(tp, 0x15, 0x007a); - rtl8168_mdio_write(tp, 0x19, 0x4580); - rtl8168_mdio_write(tp, 0x15, 0x007b); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x007c); - rtl8168_mdio_write(tp, 0x19, 0xce80); - rtl8168_mdio_write(tp, 0x15, 0x007d); - rtl8168_mdio_write(tp, 0x19, 0x0004); - rtl8168_mdio_write(tp, 0x15, 0x007e); - rtl8168_mdio_write(tp, 0x19, 0xce80); - rtl8168_mdio_write(tp, 0x15, 0x007f); - rtl8168_mdio_write(tp, 0x19, 0x0002); - rtl8168_mdio_write(tp, 0x15, 0x0080); - rtl8168_mdio_write(tp, 0x19, 0x307c); - rtl8168_mdio_write(tp, 0x15, 0x0081); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x0082); - rtl8168_mdio_write(tp, 0x19, 0x480f); - rtl8168_mdio_write(tp, 0x15, 0x0083); - rtl8168_mdio_write(tp, 0x19, 0x6802); - rtl8168_mdio_write(tp, 0x15, 0x0084); - rtl8168_mdio_write(tp, 0x19, 0x6680); - rtl8168_mdio_write(tp, 0x15, 0x0085); - rtl8168_mdio_write(tp, 0x19, 0x7c10); - rtl8168_mdio_write(tp, 0x15, 0x0086); - rtl8168_mdio_write(tp, 0x19, 0x6010); - rtl8168_mdio_write(tp, 0x15, 0x0087); - rtl8168_mdio_write(tp, 0x19, 0x400a); - rtl8168_mdio_write(tp, 0x15, 0x0088); - rtl8168_mdio_write(tp, 0x19, 0x4580); - rtl8168_mdio_write(tp, 0x15, 0x0089); - rtl8168_mdio_write(tp, 0x19, 0x9e00); - rtl8168_mdio_write(tp, 0x15, 0x008a); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x008b); - rtl8168_mdio_write(tp, 0x19, 0x5800); - rtl8168_mdio_write(tp, 0x15, 0x008c); - rtl8168_mdio_write(tp, 0x19, 0x63c8); - rtl8168_mdio_write(tp, 0x15, 0x008d); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x008e); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x008f); - rtl8168_mdio_write(tp, 0x19, 0x8300); - rtl8168_mdio_write(tp, 0x15, 0x0090); - rtl8168_mdio_write(tp, 0x19, 0x7ff0); - rtl8168_mdio_write(tp, 0x15, 0x0091); - rtl8168_mdio_write(tp, 0x19, 0x74f0); - rtl8168_mdio_write(tp, 0x15, 0x0092); - rtl8168_mdio_write(tp, 0x19, 0x3006); - rtl8168_mdio_write(tp, 0x15, 0x0093); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0094); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0095); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0096); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0097); - rtl8168_mdio_write(tp, 0x19, 0x4803); - rtl8168_mdio_write(tp, 0x15, 0x0098); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0099); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x009a); - rtl8168_mdio_write(tp, 0x19, 0xa203); - rtl8168_mdio_write(tp, 0x15, 0x009b); - rtl8168_mdio_write(tp, 0x19, 0x64b1); - rtl8168_mdio_write(tp, 0x15, 0x009c); - rtl8168_mdio_write(tp, 0x19, 0x309e); - rtl8168_mdio_write(tp, 0x15, 0x009d); - rtl8168_mdio_write(tp, 0x19, 0x64b3); - rtl8168_mdio_write(tp, 0x15, 0x009e); - rtl8168_mdio_write(tp, 0x19, 0x4030); - rtl8168_mdio_write(tp, 0x15, 0x009f); - rtl8168_mdio_write(tp, 0x19, 0x440e); - rtl8168_mdio_write(tp, 0x15, 0x00a0); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x00a1); - rtl8168_mdio_write(tp, 0x19, 0x4419); - rtl8168_mdio_write(tp, 0x15, 0x00a2); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x00a3); - rtl8168_mdio_write(tp, 0x19, 0xc520); - rtl8168_mdio_write(tp, 0x15, 0x00a4); - rtl8168_mdio_write(tp, 0x19, 0x000b); - rtl8168_mdio_write(tp, 0x15, 0x00a5); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x00a6); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x00a7); - rtl8168_mdio_write(tp, 0x19, 0x58a4); - rtl8168_mdio_write(tp, 0x15, 0x00a8); - rtl8168_mdio_write(tp, 0x19, 0x63da); - rtl8168_mdio_write(tp, 0x15, 0x00a9); - rtl8168_mdio_write(tp, 0x19, 0x5cb0); - rtl8168_mdio_write(tp, 0x15, 0x00aa); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x00ab); - rtl8168_mdio_write(tp, 0x19, 0x72b0); - rtl8168_mdio_write(tp, 0x15, 0x00ac); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x15, 0x00ad); - rtl8168_mdio_write(tp, 0x19, 0x70b0); - rtl8168_mdio_write(tp, 0x15, 0x00ae); - rtl8168_mdio_write(tp, 0x19, 0x30b8); - rtl8168_mdio_write(tp, 0x15, 0x00AF); - rtl8168_mdio_write(tp, 0x19, 0x4060); - rtl8168_mdio_write(tp, 0x15, 0x00B0); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x00B1); - rtl8168_mdio_write(tp, 0x19, 0x7e00); - rtl8168_mdio_write(tp, 0x15, 0x00B2); - rtl8168_mdio_write(tp, 0x19, 0x72B0); - rtl8168_mdio_write(tp, 0x15, 0x00B3); - rtl8168_mdio_write(tp, 0x19, 0x7F00); - rtl8168_mdio_write(tp, 0x15, 0x00B4); - rtl8168_mdio_write(tp, 0x19, 0x73B0); - rtl8168_mdio_write(tp, 0x15, 0x00b5); - rtl8168_mdio_write(tp, 0x19, 0x58a0); - rtl8168_mdio_write(tp, 0x15, 0x00b6); - rtl8168_mdio_write(tp, 0x19, 0x63d2); - rtl8168_mdio_write(tp, 0x15, 0x00b7); - rtl8168_mdio_write(tp, 0x19, 0x5c00); - rtl8168_mdio_write(tp, 0x15, 0x00b8); - rtl8168_mdio_write(tp, 0x19, 0x5780); - rtl8168_mdio_write(tp, 0x15, 0x00b9); - rtl8168_mdio_write(tp, 0x19, 0xb60d); - rtl8168_mdio_write(tp, 0x15, 0x00ba); - rtl8168_mdio_write(tp, 0x19, 0x9bff); - rtl8168_mdio_write(tp, 0x15, 0x00bb); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x00bc); - rtl8168_mdio_write(tp, 0x19, 0x6001); - rtl8168_mdio_write(tp, 0x15, 0x00bd); - rtl8168_mdio_write(tp, 0x19, 0xc020); - rtl8168_mdio_write(tp, 0x15, 0x00be); - rtl8168_mdio_write(tp, 0x19, 0x002b); - rtl8168_mdio_write(tp, 0x15, 0x00bf); - rtl8168_mdio_write(tp, 0x19, 0xc137); - rtl8168_mdio_write(tp, 0x15, 0x00c0); - rtl8168_mdio_write(tp, 0x19, 0x0006); - rtl8168_mdio_write(tp, 0x15, 0x00c1); - rtl8168_mdio_write(tp, 0x19, 0x9af8); - rtl8168_mdio_write(tp, 0x15, 0x00c2); - rtl8168_mdio_write(tp, 0x19, 0x30c6); - rtl8168_mdio_write(tp, 0x15, 0x00c3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00c4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00c5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00c6); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x00c7); - rtl8168_mdio_write(tp, 0x19, 0x70b0); - rtl8168_mdio_write(tp, 0x15, 0x00c8); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x00c9); - rtl8168_mdio_write(tp, 0x19, 0x4804); - rtl8168_mdio_write(tp, 0x15, 0x00ca); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x00cb); - rtl8168_mdio_write(tp, 0x19, 0x5c80); - rtl8168_mdio_write(tp, 0x15, 0x00cc); - rtl8168_mdio_write(tp, 0x19, 0x4010); - rtl8168_mdio_write(tp, 0x15, 0x00cd); - rtl8168_mdio_write(tp, 0x19, 0x4415); - rtl8168_mdio_write(tp, 0x15, 0x00ce); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x15, 0x00cf); - rtl8168_mdio_write(tp, 0x19, 0x7f00); - rtl8168_mdio_write(tp, 0x15, 0x00d0); - rtl8168_mdio_write(tp, 0x19, 0x70b0); - rtl8168_mdio_write(tp, 0x15, 0x00d1); - rtl8168_mdio_write(tp, 0x19, 0x3177); - rtl8168_mdio_write(tp, 0x15, 0x00d2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00d3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00d4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00d5); - rtl8168_mdio_write(tp, 0x19, 0x4808); - rtl8168_mdio_write(tp, 0x15, 0x00d6); - rtl8168_mdio_write(tp, 0x19, 0x4007); - rtl8168_mdio_write(tp, 0x15, 0x00d7); - rtl8168_mdio_write(tp, 0x19, 0x4420); - rtl8168_mdio_write(tp, 0x15, 0x00d8); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x00d9); - rtl8168_mdio_write(tp, 0x19, 0xb608); - rtl8168_mdio_write(tp, 0x15, 0x00da); - rtl8168_mdio_write(tp, 0x19, 0xbcbd); - rtl8168_mdio_write(tp, 0x15, 0x00db); - rtl8168_mdio_write(tp, 0x19, 0xc60b); - rtl8168_mdio_write(tp, 0x15, 0x00dc); - rtl8168_mdio_write(tp, 0x19, 0x00fd); - rtl8168_mdio_write(tp, 0x15, 0x00dd); - rtl8168_mdio_write(tp, 0x19, 0x30e1); - rtl8168_mdio_write(tp, 0x15, 0x00de); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00df); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00e0); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00e1); - rtl8168_mdio_write(tp, 0x19, 0x4809); - rtl8168_mdio_write(tp, 0x15, 0x00e2); - rtl8168_mdio_write(tp, 0x19, 0x7e40); - rtl8168_mdio_write(tp, 0x15, 0x00e3); - rtl8168_mdio_write(tp, 0x19, 0x5a40); - rtl8168_mdio_write(tp, 0x15, 0x00e4); - rtl8168_mdio_write(tp, 0x19, 0x305a); - rtl8168_mdio_write(tp, 0x15, 0x00e5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00e6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00e7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00e8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00e9); - rtl8168_mdio_write(tp, 0x19, 0x480a); - rtl8168_mdio_write(tp, 0x15, 0x00ea); - rtl8168_mdio_write(tp, 0x19, 0x5820); - rtl8168_mdio_write(tp, 0x15, 0x00eb); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x00ec); - rtl8168_mdio_write(tp, 0x19, 0xb60a); - rtl8168_mdio_write(tp, 0x15, 0x00ed); - rtl8168_mdio_write(tp, 0x19, 0xda07); - rtl8168_mdio_write(tp, 0x15, 0x00ee); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x00ef); - rtl8168_mdio_write(tp, 0x19, 0xc60b); - rtl8168_mdio_write(tp, 0x15, 0x00f0); - rtl8168_mdio_write(tp, 0x19, 0x00fc); - rtl8168_mdio_write(tp, 0x15, 0x00f1); - rtl8168_mdio_write(tp, 0x19, 0x30f6); - rtl8168_mdio_write(tp, 0x15, 0x00f2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00f3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00f4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00f5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x00f6); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x00f7); - rtl8168_mdio_write(tp, 0x19, 0x480b); - rtl8168_mdio_write(tp, 0x15, 0x00f8); - rtl8168_mdio_write(tp, 0x19, 0x6f03); - rtl8168_mdio_write(tp, 0x15, 0x00f9); - rtl8168_mdio_write(tp, 0x19, 0x405f); - rtl8168_mdio_write(tp, 0x15, 0x00fa); - rtl8168_mdio_write(tp, 0x19, 0x4448); - rtl8168_mdio_write(tp, 0x15, 0x00fb); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x00fc); - rtl8168_mdio_write(tp, 0x19, 0x4468); - rtl8168_mdio_write(tp, 0x15, 0x00fd); - rtl8168_mdio_write(tp, 0x19, 0x9c03); - rtl8168_mdio_write(tp, 0x15, 0x00fe); - rtl8168_mdio_write(tp, 0x19, 0x6f07); - rtl8168_mdio_write(tp, 0x15, 0x00ff); - rtl8168_mdio_write(tp, 0x19, 0x58a0); - rtl8168_mdio_write(tp, 0x15, 0x0100); - rtl8168_mdio_write(tp, 0x19, 0xd6d1); - rtl8168_mdio_write(tp, 0x15, 0x0101); - rtl8168_mdio_write(tp, 0x19, 0x0004); - rtl8168_mdio_write(tp, 0x15, 0x0102); - rtl8168_mdio_write(tp, 0x19, 0xc137); - rtl8168_mdio_write(tp, 0x15, 0x0103); - rtl8168_mdio_write(tp, 0x19, 0x0002); - rtl8168_mdio_write(tp, 0x15, 0x0104); - rtl8168_mdio_write(tp, 0x19, 0xa0e5); - rtl8168_mdio_write(tp, 0x15, 0x0105); - rtl8168_mdio_write(tp, 0x19, 0x9df8); - rtl8168_mdio_write(tp, 0x15, 0x0106); - rtl8168_mdio_write(tp, 0x19, 0x30c6); - rtl8168_mdio_write(tp, 0x15, 0x0107); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0108); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0109); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x010a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x010b); - rtl8168_mdio_write(tp, 0x19, 0x4808); - rtl8168_mdio_write(tp, 0x15, 0x010c); - rtl8168_mdio_write(tp, 0x19, 0xc32d); - rtl8168_mdio_write(tp, 0x15, 0x010d); - rtl8168_mdio_write(tp, 0x19, 0x0003); - rtl8168_mdio_write(tp, 0x15, 0x010e); - rtl8168_mdio_write(tp, 0x19, 0xc8b3); - rtl8168_mdio_write(tp, 0x15, 0x010f); - rtl8168_mdio_write(tp, 0x19, 0x00fc); - rtl8168_mdio_write(tp, 0x15, 0x0110); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x0111); - rtl8168_mdio_write(tp, 0x19, 0x3116); - rtl8168_mdio_write(tp, 0x15, 0x0112); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0113); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0114); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0115); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0116); - rtl8168_mdio_write(tp, 0x19, 0x4803); - rtl8168_mdio_write(tp, 0x15, 0x0117); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0118); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x0119); - rtl8168_mdio_write(tp, 0x19, 0x7c04); - rtl8168_mdio_write(tp, 0x15, 0x011a); - rtl8168_mdio_write(tp, 0x19, 0x6000); - rtl8168_mdio_write(tp, 0x15, 0x011b); - rtl8168_mdio_write(tp, 0x19, 0x5cf7); - rtl8168_mdio_write(tp, 0x15, 0x011c); - rtl8168_mdio_write(tp, 0x19, 0x7c2a); - rtl8168_mdio_write(tp, 0x15, 0x011d); - rtl8168_mdio_write(tp, 0x19, 0x5800); - rtl8168_mdio_write(tp, 0x15, 0x011e); - rtl8168_mdio_write(tp, 0x19, 0x5400); - rtl8168_mdio_write(tp, 0x15, 0x011f); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0120); - rtl8168_mdio_write(tp, 0x19, 0x74f0); - rtl8168_mdio_write(tp, 0x15, 0x0121); - rtl8168_mdio_write(tp, 0x19, 0x4019); - rtl8168_mdio_write(tp, 0x15, 0x0122); - rtl8168_mdio_write(tp, 0x19, 0x440d); - rtl8168_mdio_write(tp, 0x15, 0x0123); - rtl8168_mdio_write(tp, 0x19, 0xb6c1); - rtl8168_mdio_write(tp, 0x15, 0x0124); - rtl8168_mdio_write(tp, 0x19, 0xc05b); - rtl8168_mdio_write(tp, 0x15, 0x0125); - rtl8168_mdio_write(tp, 0x19, 0x00bf); - rtl8168_mdio_write(tp, 0x15, 0x0126); - rtl8168_mdio_write(tp, 0x19, 0xc025); - rtl8168_mdio_write(tp, 0x15, 0x0127); - rtl8168_mdio_write(tp, 0x19, 0x00bd); - rtl8168_mdio_write(tp, 0x15, 0x0128); - rtl8168_mdio_write(tp, 0x19, 0xc603); - rtl8168_mdio_write(tp, 0x15, 0x0129); - rtl8168_mdio_write(tp, 0x19, 0x00bb); - rtl8168_mdio_write(tp, 0x15, 0x012a); - rtl8168_mdio_write(tp, 0x19, 0x8805); - rtl8168_mdio_write(tp, 0x15, 0x012b); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x012c); - rtl8168_mdio_write(tp, 0x19, 0x4001); - rtl8168_mdio_write(tp, 0x15, 0x012d); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x012e); - rtl8168_mdio_write(tp, 0x19, 0xa3dd); - rtl8168_mdio_write(tp, 0x15, 0x012f); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0130); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x0131); - rtl8168_mdio_write(tp, 0x19, 0x8407); - rtl8168_mdio_write(tp, 0x15, 0x0132); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0133); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x0134); - rtl8168_mdio_write(tp, 0x19, 0xd9b8); - rtl8168_mdio_write(tp, 0x15, 0x0135); - rtl8168_mdio_write(tp, 0x19, 0x0003); - rtl8168_mdio_write(tp, 0x15, 0x0136); - rtl8168_mdio_write(tp, 0x19, 0xc240); - rtl8168_mdio_write(tp, 0x15, 0x0137); - rtl8168_mdio_write(tp, 0x19, 0x0015); - rtl8168_mdio_write(tp, 0x15, 0x0138); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0139); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x013a); - rtl8168_mdio_write(tp, 0x19, 0x9ae9); - rtl8168_mdio_write(tp, 0x15, 0x013b); - rtl8168_mdio_write(tp, 0x19, 0x3140); - rtl8168_mdio_write(tp, 0x15, 0x013c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x013d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x013e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x013f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0140); - rtl8168_mdio_write(tp, 0x19, 0x4807); - rtl8168_mdio_write(tp, 0x15, 0x0141); - rtl8168_mdio_write(tp, 0x19, 0x4004); - rtl8168_mdio_write(tp, 0x15, 0x0142); - rtl8168_mdio_write(tp, 0x19, 0x4410); - rtl8168_mdio_write(tp, 0x15, 0x0143); - rtl8168_mdio_write(tp, 0x19, 0x7c0c); - rtl8168_mdio_write(tp, 0x15, 0x0144); - rtl8168_mdio_write(tp, 0x19, 0x600c); - rtl8168_mdio_write(tp, 0x15, 0x0145); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x15, 0x0146); - rtl8168_mdio_write(tp, 0x19, 0xa68f); - rtl8168_mdio_write(tp, 0x15, 0x0147); - rtl8168_mdio_write(tp, 0x19, 0x3116); - rtl8168_mdio_write(tp, 0x15, 0x0148); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0149); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x014a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x014b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x014c); - rtl8168_mdio_write(tp, 0x19, 0x4804); - rtl8168_mdio_write(tp, 0x15, 0x014d); - rtl8168_mdio_write(tp, 0x19, 0x54c0); - rtl8168_mdio_write(tp, 0x15, 0x014e); - rtl8168_mdio_write(tp, 0x19, 0xb703); - rtl8168_mdio_write(tp, 0x15, 0x014f); - rtl8168_mdio_write(tp, 0x19, 0x5cff); - rtl8168_mdio_write(tp, 0x15, 0x0150); - rtl8168_mdio_write(tp, 0x19, 0x315f); - rtl8168_mdio_write(tp, 0x15, 0x0151); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0152); - rtl8168_mdio_write(tp, 0x19, 0x74f8); - rtl8168_mdio_write(tp, 0x15, 0x0153); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0154); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0155); - rtl8168_mdio_write(tp, 0x19, 0x6000); - rtl8168_mdio_write(tp, 0x15, 0x0156); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x0157); - rtl8168_mdio_write(tp, 0x19, 0x4418); - rtl8168_mdio_write(tp, 0x15, 0x0158); - rtl8168_mdio_write(tp, 0x19, 0x9b00); - rtl8168_mdio_write(tp, 0x15, 0x0159); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x015a); - rtl8168_mdio_write(tp, 0x19, 0x64e1); - rtl8168_mdio_write(tp, 0x15, 0x015b); - rtl8168_mdio_write(tp, 0x19, 0x7c20); - rtl8168_mdio_write(tp, 0x15, 0x015c); - rtl8168_mdio_write(tp, 0x19, 0x5820); - rtl8168_mdio_write(tp, 0x15, 0x015d); - rtl8168_mdio_write(tp, 0x19, 0x5ccf); - rtl8168_mdio_write(tp, 0x15, 0x015e); - rtl8168_mdio_write(tp, 0x19, 0x7050); - rtl8168_mdio_write(tp, 0x15, 0x015f); - rtl8168_mdio_write(tp, 0x19, 0xd9b8); - rtl8168_mdio_write(tp, 0x15, 0x0160); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x0161); - rtl8168_mdio_write(tp, 0x19, 0xdab1); - rtl8168_mdio_write(tp, 0x15, 0x0162); - rtl8168_mdio_write(tp, 0x19, 0x0015); - rtl8168_mdio_write(tp, 0x15, 0x0163); - rtl8168_mdio_write(tp, 0x19, 0xc244); - rtl8168_mdio_write(tp, 0x15, 0x0164); - rtl8168_mdio_write(tp, 0x19, 0x0013); - rtl8168_mdio_write(tp, 0x15, 0x0165); - rtl8168_mdio_write(tp, 0x19, 0xc021); - rtl8168_mdio_write(tp, 0x15, 0x0166); - rtl8168_mdio_write(tp, 0x19, 0x00f9); - rtl8168_mdio_write(tp, 0x15, 0x0167); - rtl8168_mdio_write(tp, 0x19, 0x3177); - rtl8168_mdio_write(tp, 0x15, 0x0168); - rtl8168_mdio_write(tp, 0x19, 0x5cf7); - rtl8168_mdio_write(tp, 0x15, 0x0169); - rtl8168_mdio_write(tp, 0x19, 0x4010); - rtl8168_mdio_write(tp, 0x15, 0x016a); - rtl8168_mdio_write(tp, 0x19, 0x4428); - rtl8168_mdio_write(tp, 0x15, 0x016b); - rtl8168_mdio_write(tp, 0x19, 0x9c00); - rtl8168_mdio_write(tp, 0x15, 0x016c); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x016d); - rtl8168_mdio_write(tp, 0x19, 0x6008); - rtl8168_mdio_write(tp, 0x15, 0x016e); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x016f); - rtl8168_mdio_write(tp, 0x19, 0x74f0); - rtl8168_mdio_write(tp, 0x15, 0x0170); - rtl8168_mdio_write(tp, 0x19, 0x6461); - rtl8168_mdio_write(tp, 0x15, 0x0171); - rtl8168_mdio_write(tp, 0x19, 0x6421); - rtl8168_mdio_write(tp, 0x15, 0x0172); - rtl8168_mdio_write(tp, 0x19, 0x64a1); - rtl8168_mdio_write(tp, 0x15, 0x0173); - rtl8168_mdio_write(tp, 0x19, 0x3116); - rtl8168_mdio_write(tp, 0x15, 0x0174); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0175); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0176); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0177); - rtl8168_mdio_write(tp, 0x19, 0x4805); - rtl8168_mdio_write(tp, 0x15, 0x0178); - rtl8168_mdio_write(tp, 0x19, 0xa103); - rtl8168_mdio_write(tp, 0x15, 0x0179); - rtl8168_mdio_write(tp, 0x19, 0x7c02); - rtl8168_mdio_write(tp, 0x15, 0x017a); - rtl8168_mdio_write(tp, 0x19, 0x6002); - rtl8168_mdio_write(tp, 0x15, 0x017b); - rtl8168_mdio_write(tp, 0x19, 0x7e00); - rtl8168_mdio_write(tp, 0x15, 0x017c); - rtl8168_mdio_write(tp, 0x19, 0x5400); - rtl8168_mdio_write(tp, 0x15, 0x017d); - rtl8168_mdio_write(tp, 0x19, 0x7c6b); - rtl8168_mdio_write(tp, 0x15, 0x017e); - rtl8168_mdio_write(tp, 0x19, 0x5c63); - rtl8168_mdio_write(tp, 0x15, 0x017f); - rtl8168_mdio_write(tp, 0x19, 0x407d); - rtl8168_mdio_write(tp, 0x15, 0x0180); - rtl8168_mdio_write(tp, 0x19, 0xa602); - rtl8168_mdio_write(tp, 0x15, 0x0181); - rtl8168_mdio_write(tp, 0x19, 0x4001); - rtl8168_mdio_write(tp, 0x15, 0x0182); - rtl8168_mdio_write(tp, 0x19, 0x4420); - rtl8168_mdio_write(tp, 0x15, 0x0183); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x0184); - rtl8168_mdio_write(tp, 0x19, 0x44a1); - rtl8168_mdio_write(tp, 0x15, 0x0185); - rtl8168_mdio_write(tp, 0x19, 0xd6e0); - rtl8168_mdio_write(tp, 0x15, 0x0186); - rtl8168_mdio_write(tp, 0x19, 0x0009); - rtl8168_mdio_write(tp, 0x15, 0x0187); - rtl8168_mdio_write(tp, 0x19, 0x9efe); - rtl8168_mdio_write(tp, 0x15, 0x0188); - rtl8168_mdio_write(tp, 0x19, 0x7c02); - rtl8168_mdio_write(tp, 0x15, 0x0189); - rtl8168_mdio_write(tp, 0x19, 0x6000); - rtl8168_mdio_write(tp, 0x15, 0x018a); - rtl8168_mdio_write(tp, 0x19, 0x9c00); - rtl8168_mdio_write(tp, 0x15, 0x018b); - rtl8168_mdio_write(tp, 0x19, 0x318f); - rtl8168_mdio_write(tp, 0x15, 0x018c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x018d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x018e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x018f); - rtl8168_mdio_write(tp, 0x19, 0x4806); - rtl8168_mdio_write(tp, 0x15, 0x0190); - rtl8168_mdio_write(tp, 0x19, 0x7c10); - rtl8168_mdio_write(tp, 0x15, 0x0191); - rtl8168_mdio_write(tp, 0x19, 0x5c10); - rtl8168_mdio_write(tp, 0x15, 0x0192); - rtl8168_mdio_write(tp, 0x19, 0x40fa); - rtl8168_mdio_write(tp, 0x15, 0x0193); - rtl8168_mdio_write(tp, 0x19, 0xa602); - rtl8168_mdio_write(tp, 0x15, 0x0194); - rtl8168_mdio_write(tp, 0x19, 0x4010); - rtl8168_mdio_write(tp, 0x15, 0x0195); - rtl8168_mdio_write(tp, 0x19, 0x4440); - rtl8168_mdio_write(tp, 0x15, 0x0196); - rtl8168_mdio_write(tp, 0x19, 0x9d00); - rtl8168_mdio_write(tp, 0x15, 0x0197); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x0198); - rtl8168_mdio_write(tp, 0x19, 0x6400); - rtl8168_mdio_write(tp, 0x15, 0x0199); - rtl8168_mdio_write(tp, 0x19, 0x4003); - rtl8168_mdio_write(tp, 0x15, 0x019a); - rtl8168_mdio_write(tp, 0x19, 0x4540); - rtl8168_mdio_write(tp, 0x15, 0x019b); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x019c); - rtl8168_mdio_write(tp, 0x19, 0x6008); - rtl8168_mdio_write(tp, 0x15, 0x019d); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x019e); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x019f); - rtl8168_mdio_write(tp, 0x19, 0x6400); - rtl8168_mdio_write(tp, 0x15, 0x01a0); - rtl8168_mdio_write(tp, 0x19, 0x7c80); - rtl8168_mdio_write(tp, 0x15, 0x01a1); - rtl8168_mdio_write(tp, 0x19, 0x6480); - rtl8168_mdio_write(tp, 0x15, 0x01a2); - rtl8168_mdio_write(tp, 0x19, 0x3140); - rtl8168_mdio_write(tp, 0x15, 0x01a3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01a4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01a5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01a6); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x01a7); - rtl8168_mdio_write(tp, 0x19, 0x7c0b); - rtl8168_mdio_write(tp, 0x15, 0x01a8); - rtl8168_mdio_write(tp, 0x19, 0x6c01); - rtl8168_mdio_write(tp, 0x15, 0x01a9); - rtl8168_mdio_write(tp, 0x19, 0x64a8); - rtl8168_mdio_write(tp, 0x15, 0x01aa); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x01ab); - rtl8168_mdio_write(tp, 0x19, 0x5cf0); - rtl8168_mdio_write(tp, 0x15, 0x01ac); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x01ad); - rtl8168_mdio_write(tp, 0x19, 0xb628); - rtl8168_mdio_write(tp, 0x15, 0x01ae); - rtl8168_mdio_write(tp, 0x19, 0xc053); - rtl8168_mdio_write(tp, 0x15, 0x01af); - rtl8168_mdio_write(tp, 0x19, 0x0026); - rtl8168_mdio_write(tp, 0x15, 0x01b0); - rtl8168_mdio_write(tp, 0x19, 0xc02d); - rtl8168_mdio_write(tp, 0x15, 0x01b1); - rtl8168_mdio_write(tp, 0x19, 0x0024); - rtl8168_mdio_write(tp, 0x15, 0x01b2); - rtl8168_mdio_write(tp, 0x19, 0xc603); - rtl8168_mdio_write(tp, 0x15, 0x01b3); - rtl8168_mdio_write(tp, 0x19, 0x0022); - rtl8168_mdio_write(tp, 0x15, 0x01b4); - rtl8168_mdio_write(tp, 0x19, 0x8cf9); - rtl8168_mdio_write(tp, 0x15, 0x01b5); - rtl8168_mdio_write(tp, 0x19, 0x31ba); - rtl8168_mdio_write(tp, 0x15, 0x01b6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01b7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01b8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01b9); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01ba); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x01bb); - rtl8168_mdio_write(tp, 0x19, 0x5420); - rtl8168_mdio_write(tp, 0x15, 0x01bc); - rtl8168_mdio_write(tp, 0x19, 0x4811); - rtl8168_mdio_write(tp, 0x15, 0x01bd); - rtl8168_mdio_write(tp, 0x19, 0x5000); - rtl8168_mdio_write(tp, 0x15, 0x01be); - rtl8168_mdio_write(tp, 0x19, 0x4801); - rtl8168_mdio_write(tp, 0x15, 0x01bf); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x01c0); - rtl8168_mdio_write(tp, 0x19, 0x31f5); - rtl8168_mdio_write(tp, 0x15, 0x01c1); - rtl8168_mdio_write(tp, 0x19, 0xb614); - rtl8168_mdio_write(tp, 0x15, 0x01c2); - rtl8168_mdio_write(tp, 0x19, 0x8ce4); - rtl8168_mdio_write(tp, 0x15, 0x01c3); - rtl8168_mdio_write(tp, 0x19, 0xb30c); - rtl8168_mdio_write(tp, 0x15, 0x01c4); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x01c5); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x01c6); - rtl8168_mdio_write(tp, 0x19, 0x8206); - rtl8168_mdio_write(tp, 0x15, 0x01c7); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x01c8); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x01c9); - rtl8168_mdio_write(tp, 0x19, 0x7c04); - rtl8168_mdio_write(tp, 0x15, 0x01ca); - rtl8168_mdio_write(tp, 0x19, 0x7404); - rtl8168_mdio_write(tp, 0x15, 0x01cb); - rtl8168_mdio_write(tp, 0x19, 0x31c0); - rtl8168_mdio_write(tp, 0x15, 0x01cc); - rtl8168_mdio_write(tp, 0x19, 0x7c04); - rtl8168_mdio_write(tp, 0x15, 0x01cd); - rtl8168_mdio_write(tp, 0x19, 0x7400); - rtl8168_mdio_write(tp, 0x15, 0x01ce); - rtl8168_mdio_write(tp, 0x19, 0x31c0); - rtl8168_mdio_write(tp, 0x15, 0x01cf); - rtl8168_mdio_write(tp, 0x19, 0x8df1); - rtl8168_mdio_write(tp, 0x15, 0x01d0); - rtl8168_mdio_write(tp, 0x19, 0x3248); - rtl8168_mdio_write(tp, 0x15, 0x01d1); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01d2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01d3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01d4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01d5); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x01d6); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x01d7); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x01d8); - rtl8168_mdio_write(tp, 0x19, 0x7670); - rtl8168_mdio_write(tp, 0x15, 0x01d9); - rtl8168_mdio_write(tp, 0x19, 0x4023); - rtl8168_mdio_write(tp, 0x15, 0x01da); - rtl8168_mdio_write(tp, 0x19, 0x4500); - rtl8168_mdio_write(tp, 0x15, 0x01db); - rtl8168_mdio_write(tp, 0x19, 0x4069); - rtl8168_mdio_write(tp, 0x15, 0x01dc); - rtl8168_mdio_write(tp, 0x19, 0x4580); - rtl8168_mdio_write(tp, 0x15, 0x01dd); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x01de); - rtl8168_mdio_write(tp, 0x19, 0xcff5); - rtl8168_mdio_write(tp, 0x15, 0x01df); - rtl8168_mdio_write(tp, 0x19, 0x00ff); - rtl8168_mdio_write(tp, 0x15, 0x01e0); - rtl8168_mdio_write(tp, 0x19, 0x76f0); - rtl8168_mdio_write(tp, 0x15, 0x01e1); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x01e2); - rtl8168_mdio_write(tp, 0x19, 0x4023); - rtl8168_mdio_write(tp, 0x15, 0x01e3); - rtl8168_mdio_write(tp, 0x19, 0x4500); - rtl8168_mdio_write(tp, 0x15, 0x01e4); - rtl8168_mdio_write(tp, 0x19, 0x4069); - rtl8168_mdio_write(tp, 0x15, 0x01e5); - rtl8168_mdio_write(tp, 0x19, 0x4580); - rtl8168_mdio_write(tp, 0x15, 0x01e6); - rtl8168_mdio_write(tp, 0x19, 0x9f00); - rtl8168_mdio_write(tp, 0x15, 0x01e7); - rtl8168_mdio_write(tp, 0x19, 0xd0f5); - rtl8168_mdio_write(tp, 0x15, 0x01e8); - rtl8168_mdio_write(tp, 0x19, 0x00ff); - rtl8168_mdio_write(tp, 0x15, 0x01e9); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x01ea); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x01eb); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x01ec); - rtl8168_mdio_write(tp, 0x19, 0x66a0); - rtl8168_mdio_write(tp, 0x15, 0x01ed); - rtl8168_mdio_write(tp, 0x19, 0x8300); - rtl8168_mdio_write(tp, 0x15, 0x01ee); - rtl8168_mdio_write(tp, 0x19, 0x74f0); - rtl8168_mdio_write(tp, 0x15, 0x01ef); - rtl8168_mdio_write(tp, 0x19, 0x3006); - rtl8168_mdio_write(tp, 0x15, 0x01f0); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01f1); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01f2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01f3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01f4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x01f5); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x01f6); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x01f7); - rtl8168_mdio_write(tp, 0x19, 0x409d); - rtl8168_mdio_write(tp, 0x15, 0x01f8); - rtl8168_mdio_write(tp, 0x19, 0x7c87); - rtl8168_mdio_write(tp, 0x15, 0x01f9); - rtl8168_mdio_write(tp, 0x19, 0xae14); - rtl8168_mdio_write(tp, 0x15, 0x01fa); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x01fb); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x01fc); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x01fd); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x01fe); - rtl8168_mdio_write(tp, 0x19, 0x980e); - rtl8168_mdio_write(tp, 0x15, 0x01ff); - rtl8168_mdio_write(tp, 0x19, 0x930c); - rtl8168_mdio_write(tp, 0x15, 0x0200); - rtl8168_mdio_write(tp, 0x19, 0x9206); - rtl8168_mdio_write(tp, 0x15, 0x0201); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0202); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0203); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0204); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0205); - rtl8168_mdio_write(tp, 0x19, 0x320c); - rtl8168_mdio_write(tp, 0x15, 0x0206); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x15, 0x0207); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0208); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x0209); - rtl8168_mdio_write(tp, 0x19, 0x5500); - rtl8168_mdio_write(tp, 0x15, 0x020a); - rtl8168_mdio_write(tp, 0x19, 0x320c); - rtl8168_mdio_write(tp, 0x15, 0x020b); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x020c); - rtl8168_mdio_write(tp, 0x19, 0x3220); - rtl8168_mdio_write(tp, 0x15, 0x020d); - rtl8168_mdio_write(tp, 0x19, 0x4480); - rtl8168_mdio_write(tp, 0x15, 0x020e); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x020f); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0210); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x0211); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0212); - rtl8168_mdio_write(tp, 0x19, 0x980e); - rtl8168_mdio_write(tp, 0x15, 0x0213); - rtl8168_mdio_write(tp, 0x19, 0x930c); - rtl8168_mdio_write(tp, 0x15, 0x0214); - rtl8168_mdio_write(tp, 0x19, 0x9206); - rtl8168_mdio_write(tp, 0x15, 0x0215); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x15, 0x0216); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0217); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0218); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0219); - rtl8168_mdio_write(tp, 0x19, 0x3220); - rtl8168_mdio_write(tp, 0x15, 0x021a); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x021b); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x021c); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x021d); - rtl8168_mdio_write(tp, 0x19, 0x5540); - rtl8168_mdio_write(tp, 0x15, 0x021e); - rtl8168_mdio_write(tp, 0x19, 0x3220); - rtl8168_mdio_write(tp, 0x15, 0x021f); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x15, 0x0220); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0221); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0222); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0223); - rtl8168_mdio_write(tp, 0x19, 0x3231); - rtl8168_mdio_write(tp, 0x15, 0x0224); - rtl8168_mdio_write(tp, 0x19, 0xab06); - rtl8168_mdio_write(tp, 0x15, 0x0225); - rtl8168_mdio_write(tp, 0x19, 0xbf08); - rtl8168_mdio_write(tp, 0x15, 0x0226); - rtl8168_mdio_write(tp, 0x19, 0x4076); - rtl8168_mdio_write(tp, 0x15, 0x0227); - rtl8168_mdio_write(tp, 0x19, 0x7d07); - rtl8168_mdio_write(tp, 0x15, 0x0228); - rtl8168_mdio_write(tp, 0x19, 0x4502); - rtl8168_mdio_write(tp, 0x15, 0x0229); - rtl8168_mdio_write(tp, 0x19, 0x3231); - rtl8168_mdio_write(tp, 0x15, 0x022a); - rtl8168_mdio_write(tp, 0x19, 0x7d80); - rtl8168_mdio_write(tp, 0x15, 0x022b); - rtl8168_mdio_write(tp, 0x19, 0x5180); - rtl8168_mdio_write(tp, 0x15, 0x022c); - rtl8168_mdio_write(tp, 0x19, 0x322f); - rtl8168_mdio_write(tp, 0x15, 0x022d); - rtl8168_mdio_write(tp, 0x19, 0x7d80); - rtl8168_mdio_write(tp, 0x15, 0x022e); - rtl8168_mdio_write(tp, 0x19, 0x5000); - rtl8168_mdio_write(tp, 0x15, 0x022f); - rtl8168_mdio_write(tp, 0x19, 0x7d07); - rtl8168_mdio_write(tp, 0x15, 0x0230); - rtl8168_mdio_write(tp, 0x19, 0x4402); - rtl8168_mdio_write(tp, 0x15, 0x0231); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0232); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x0233); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0234); - rtl8168_mdio_write(tp, 0x19, 0xb309); - rtl8168_mdio_write(tp, 0x15, 0x0235); - rtl8168_mdio_write(tp, 0x19, 0xb204); - rtl8168_mdio_write(tp, 0x15, 0x0236); - rtl8168_mdio_write(tp, 0x19, 0xb105); - rtl8168_mdio_write(tp, 0x15, 0x0237); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0238); - rtl8168_mdio_write(tp, 0x19, 0x31c1); - rtl8168_mdio_write(tp, 0x15, 0x0239); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x023a); - rtl8168_mdio_write(tp, 0x19, 0x3261); - rtl8168_mdio_write(tp, 0x15, 0x023b); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x023c); - rtl8168_mdio_write(tp, 0x19, 0x3250); - rtl8168_mdio_write(tp, 0x15, 0x023d); - rtl8168_mdio_write(tp, 0x19, 0xb203); - rtl8168_mdio_write(tp, 0x15, 0x023e); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x023f); - rtl8168_mdio_write(tp, 0x19, 0x327a); - rtl8168_mdio_write(tp, 0x15, 0x0240); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0241); - rtl8168_mdio_write(tp, 0x19, 0x3293); - rtl8168_mdio_write(tp, 0x15, 0x0242); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0243); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0244); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0245); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0246); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0247); - rtl8168_mdio_write(tp, 0x19, 0x32a3); - rtl8168_mdio_write(tp, 0x15, 0x0248); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0249); - rtl8168_mdio_write(tp, 0x19, 0x403d); - rtl8168_mdio_write(tp, 0x15, 0x024a); - rtl8168_mdio_write(tp, 0x19, 0x440c); - rtl8168_mdio_write(tp, 0x15, 0x024b); - rtl8168_mdio_write(tp, 0x19, 0x4812); - rtl8168_mdio_write(tp, 0x15, 0x024c); - rtl8168_mdio_write(tp, 0x19, 0x5001); - rtl8168_mdio_write(tp, 0x15, 0x024d); - rtl8168_mdio_write(tp, 0x19, 0x4802); - rtl8168_mdio_write(tp, 0x15, 0x024e); - rtl8168_mdio_write(tp, 0x19, 0x6880); - rtl8168_mdio_write(tp, 0x15, 0x024f); - rtl8168_mdio_write(tp, 0x19, 0x31f5); - rtl8168_mdio_write(tp, 0x15, 0x0250); - rtl8168_mdio_write(tp, 0x19, 0xb685); - rtl8168_mdio_write(tp, 0x15, 0x0251); - rtl8168_mdio_write(tp, 0x19, 0x801c); - rtl8168_mdio_write(tp, 0x15, 0x0252); - rtl8168_mdio_write(tp, 0x19, 0xbaf5); - rtl8168_mdio_write(tp, 0x15, 0x0253); - rtl8168_mdio_write(tp, 0x19, 0xc07c); - rtl8168_mdio_write(tp, 0x15, 0x0254); - rtl8168_mdio_write(tp, 0x19, 0x00fb); - rtl8168_mdio_write(tp, 0x15, 0x0255); - rtl8168_mdio_write(tp, 0x19, 0x325a); - rtl8168_mdio_write(tp, 0x15, 0x0256); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0257); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0258); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0259); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x025a); - rtl8168_mdio_write(tp, 0x19, 0x481a); - rtl8168_mdio_write(tp, 0x15, 0x025b); - rtl8168_mdio_write(tp, 0x19, 0x5001); - rtl8168_mdio_write(tp, 0x15, 0x025c); - rtl8168_mdio_write(tp, 0x19, 0x401b); - rtl8168_mdio_write(tp, 0x15, 0x025d); - rtl8168_mdio_write(tp, 0x19, 0x480a); - rtl8168_mdio_write(tp, 0x15, 0x025e); - rtl8168_mdio_write(tp, 0x19, 0x4418); - rtl8168_mdio_write(tp, 0x15, 0x025f); - rtl8168_mdio_write(tp, 0x19, 0x6900); - rtl8168_mdio_write(tp, 0x15, 0x0260); - rtl8168_mdio_write(tp, 0x19, 0x31f5); - rtl8168_mdio_write(tp, 0x15, 0x0261); - rtl8168_mdio_write(tp, 0x19, 0xb64b); - rtl8168_mdio_write(tp, 0x15, 0x0262); - rtl8168_mdio_write(tp, 0x19, 0xdb00); - rtl8168_mdio_write(tp, 0x15, 0x0263); - rtl8168_mdio_write(tp, 0x19, 0x0048); - rtl8168_mdio_write(tp, 0x15, 0x0264); - rtl8168_mdio_write(tp, 0x19, 0xdb7d); - rtl8168_mdio_write(tp, 0x15, 0x0265); - rtl8168_mdio_write(tp, 0x19, 0x0002); - rtl8168_mdio_write(tp, 0x15, 0x0266); - rtl8168_mdio_write(tp, 0x19, 0xa0fa); - rtl8168_mdio_write(tp, 0x15, 0x0267); - rtl8168_mdio_write(tp, 0x19, 0x4408); - rtl8168_mdio_write(tp, 0x15, 0x0268); - rtl8168_mdio_write(tp, 0x19, 0x3248); - rtl8168_mdio_write(tp, 0x15, 0x0269); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x026a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x026b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x026c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x026d); - rtl8168_mdio_write(tp, 0x19, 0xb806); - rtl8168_mdio_write(tp, 0x15, 0x026e); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x026f); - rtl8168_mdio_write(tp, 0x19, 0x5500); - rtl8168_mdio_write(tp, 0x15, 0x0270); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0271); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0272); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0273); - rtl8168_mdio_write(tp, 0x19, 0x4814); - rtl8168_mdio_write(tp, 0x15, 0x0274); - rtl8168_mdio_write(tp, 0x19, 0x500b); - rtl8168_mdio_write(tp, 0x15, 0x0275); - rtl8168_mdio_write(tp, 0x19, 0x4804); - rtl8168_mdio_write(tp, 0x15, 0x0276); - rtl8168_mdio_write(tp, 0x19, 0x40c4); - rtl8168_mdio_write(tp, 0x15, 0x0277); - rtl8168_mdio_write(tp, 0x19, 0x4425); - rtl8168_mdio_write(tp, 0x15, 0x0278); - rtl8168_mdio_write(tp, 0x19, 0x6a00); - rtl8168_mdio_write(tp, 0x15, 0x0279); - rtl8168_mdio_write(tp, 0x19, 0x31f5); - rtl8168_mdio_write(tp, 0x15, 0x027a); - rtl8168_mdio_write(tp, 0x19, 0xb632); - rtl8168_mdio_write(tp, 0x15, 0x027b); - rtl8168_mdio_write(tp, 0x19, 0xdc03); - rtl8168_mdio_write(tp, 0x15, 0x027c); - rtl8168_mdio_write(tp, 0x19, 0x0027); - rtl8168_mdio_write(tp, 0x15, 0x027d); - rtl8168_mdio_write(tp, 0x19, 0x80fc); - rtl8168_mdio_write(tp, 0x15, 0x027e); - rtl8168_mdio_write(tp, 0x19, 0x3283); - rtl8168_mdio_write(tp, 0x15, 0x027f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0280); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0281); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0282); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0283); - rtl8168_mdio_write(tp, 0x19, 0xb806); - rtl8168_mdio_write(tp, 0x15, 0x0284); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0285); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0286); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0287); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x15, 0x0288); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0289); - rtl8168_mdio_write(tp, 0x19, 0x4818); - rtl8168_mdio_write(tp, 0x15, 0x028a); - rtl8168_mdio_write(tp, 0x19, 0x5051); - rtl8168_mdio_write(tp, 0x15, 0x028b); - rtl8168_mdio_write(tp, 0x19, 0x4808); - rtl8168_mdio_write(tp, 0x15, 0x028c); - rtl8168_mdio_write(tp, 0x19, 0x4050); - rtl8168_mdio_write(tp, 0x15, 0x028d); - rtl8168_mdio_write(tp, 0x19, 0x4462); - rtl8168_mdio_write(tp, 0x15, 0x028e); - rtl8168_mdio_write(tp, 0x19, 0x40c4); - rtl8168_mdio_write(tp, 0x15, 0x028f); - rtl8168_mdio_write(tp, 0x19, 0x4473); - rtl8168_mdio_write(tp, 0x15, 0x0290); - rtl8168_mdio_write(tp, 0x19, 0x5041); - rtl8168_mdio_write(tp, 0x15, 0x0291); - rtl8168_mdio_write(tp, 0x19, 0x6b00); - rtl8168_mdio_write(tp, 0x15, 0x0292); - rtl8168_mdio_write(tp, 0x19, 0x31f5); - rtl8168_mdio_write(tp, 0x15, 0x0293); - rtl8168_mdio_write(tp, 0x19, 0xb619); - rtl8168_mdio_write(tp, 0x15, 0x0294); - rtl8168_mdio_write(tp, 0x19, 0x80d9); - rtl8168_mdio_write(tp, 0x15, 0x0295); - rtl8168_mdio_write(tp, 0x19, 0xbd06); - rtl8168_mdio_write(tp, 0x15, 0x0296); - rtl8168_mdio_write(tp, 0x19, 0xbb0d); - rtl8168_mdio_write(tp, 0x15, 0x0297); - rtl8168_mdio_write(tp, 0x19, 0xaf14); - rtl8168_mdio_write(tp, 0x15, 0x0298); - rtl8168_mdio_write(tp, 0x19, 0x8efa); - rtl8168_mdio_write(tp, 0x15, 0x0299); - rtl8168_mdio_write(tp, 0x19, 0x5049); - rtl8168_mdio_write(tp, 0x15, 0x029a); - rtl8168_mdio_write(tp, 0x19, 0x3248); - rtl8168_mdio_write(tp, 0x15, 0x029b); - rtl8168_mdio_write(tp, 0x19, 0x4c10); - rtl8168_mdio_write(tp, 0x15, 0x029c); - rtl8168_mdio_write(tp, 0x19, 0x44b0); - rtl8168_mdio_write(tp, 0x15, 0x029d); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x029e); - rtl8168_mdio_write(tp, 0x19, 0x3292); - rtl8168_mdio_write(tp, 0x15, 0x029f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02a0); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02a1); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02a2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02a3); - rtl8168_mdio_write(tp, 0x19, 0x481f); - rtl8168_mdio_write(tp, 0x15, 0x02a4); - rtl8168_mdio_write(tp, 0x19, 0x5005); - rtl8168_mdio_write(tp, 0x15, 0x02a5); - rtl8168_mdio_write(tp, 0x19, 0x480f); - rtl8168_mdio_write(tp, 0x15, 0x02a6); - rtl8168_mdio_write(tp, 0x19, 0xac00); - rtl8168_mdio_write(tp, 0x15, 0x02a7); - rtl8168_mdio_write(tp, 0x19, 0x31a6); - rtl8168_mdio_write(tp, 0x15, 0x02a8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02a9); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02aa); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02ab); - rtl8168_mdio_write(tp, 0x19, 0x31ba); - rtl8168_mdio_write(tp, 0x15, 0x02ac); - rtl8168_mdio_write(tp, 0x19, 0x31d5); - rtl8168_mdio_write(tp, 0x15, 0x02ad); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02ae); - rtl8168_mdio_write(tp, 0x19, 0x5cf0); - rtl8168_mdio_write(tp, 0x15, 0x02af); - rtl8168_mdio_write(tp, 0x19, 0x588c); - rtl8168_mdio_write(tp, 0x15, 0x02b0); - rtl8168_mdio_write(tp, 0x19, 0x542f); - rtl8168_mdio_write(tp, 0x15, 0x02b1); - rtl8168_mdio_write(tp, 0x19, 0x7ffb); - rtl8168_mdio_write(tp, 0x15, 0x02b2); - rtl8168_mdio_write(tp, 0x19, 0x6ff8); - rtl8168_mdio_write(tp, 0x15, 0x02b3); - rtl8168_mdio_write(tp, 0x19, 0x64a4); - rtl8168_mdio_write(tp, 0x15, 0x02b4); - rtl8168_mdio_write(tp, 0x19, 0x64a0); - rtl8168_mdio_write(tp, 0x15, 0x02b5); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x02b6); - rtl8168_mdio_write(tp, 0x19, 0x4400); - rtl8168_mdio_write(tp, 0x15, 0x02b7); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x02b8); - rtl8168_mdio_write(tp, 0x19, 0x4480); - rtl8168_mdio_write(tp, 0x15, 0x02b9); - rtl8168_mdio_write(tp, 0x19, 0x9e00); - rtl8168_mdio_write(tp, 0x15, 0x02ba); - rtl8168_mdio_write(tp, 0x19, 0x4891); - rtl8168_mdio_write(tp, 0x15, 0x02bb); - rtl8168_mdio_write(tp, 0x19, 0x4cc0); - rtl8168_mdio_write(tp, 0x15, 0x02bc); - rtl8168_mdio_write(tp, 0x19, 0x4801); - rtl8168_mdio_write(tp, 0x15, 0x02bd); - rtl8168_mdio_write(tp, 0x19, 0xa609); - rtl8168_mdio_write(tp, 0x15, 0x02be); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x02bf); - rtl8168_mdio_write(tp, 0x19, 0x004e); - rtl8168_mdio_write(tp, 0x15, 0x02c0); - rtl8168_mdio_write(tp, 0x19, 0x87fe); - rtl8168_mdio_write(tp, 0x15, 0x02c1); - rtl8168_mdio_write(tp, 0x19, 0x32c6); - rtl8168_mdio_write(tp, 0x15, 0x02c2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02c3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02c4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02c5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02c6); - rtl8168_mdio_write(tp, 0x19, 0x48b2); - rtl8168_mdio_write(tp, 0x15, 0x02c7); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x02c8); - rtl8168_mdio_write(tp, 0x19, 0x4822); - rtl8168_mdio_write(tp, 0x15, 0x02c9); - rtl8168_mdio_write(tp, 0x19, 0x4488); - rtl8168_mdio_write(tp, 0x15, 0x02ca); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x02cb); - rtl8168_mdio_write(tp, 0x19, 0x0042); - rtl8168_mdio_write(tp, 0x15, 0x02cc); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x02cd); - rtl8168_mdio_write(tp, 0x19, 0x4cc8); - rtl8168_mdio_write(tp, 0x15, 0x02ce); - rtl8168_mdio_write(tp, 0x19, 0x32d0); - rtl8168_mdio_write(tp, 0x15, 0x02cf); - rtl8168_mdio_write(tp, 0x19, 0x4cc0); - rtl8168_mdio_write(tp, 0x15, 0x02d0); - rtl8168_mdio_write(tp, 0x19, 0xc4d4); - rtl8168_mdio_write(tp, 0x15, 0x02d1); - rtl8168_mdio_write(tp, 0x19, 0x00f9); - rtl8168_mdio_write(tp, 0x15, 0x02d2); - rtl8168_mdio_write(tp, 0x19, 0xa51a); - rtl8168_mdio_write(tp, 0x15, 0x02d3); - rtl8168_mdio_write(tp, 0x19, 0x32d9); - rtl8168_mdio_write(tp, 0x15, 0x02d4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02d5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02d6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02d7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02d8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02d9); - rtl8168_mdio_write(tp, 0x19, 0x48b3); - rtl8168_mdio_write(tp, 0x15, 0x02da); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x02db); - rtl8168_mdio_write(tp, 0x19, 0x4823); - rtl8168_mdio_write(tp, 0x15, 0x02dc); - rtl8168_mdio_write(tp, 0x19, 0x4410); - rtl8168_mdio_write(tp, 0x15, 0x02dd); - rtl8168_mdio_write(tp, 0x19, 0xb630); - rtl8168_mdio_write(tp, 0x15, 0x02de); - rtl8168_mdio_write(tp, 0x19, 0x7dc8); - rtl8168_mdio_write(tp, 0x15, 0x02df); - rtl8168_mdio_write(tp, 0x19, 0x8203); - rtl8168_mdio_write(tp, 0x15, 0x02e0); - rtl8168_mdio_write(tp, 0x19, 0x4c48); - rtl8168_mdio_write(tp, 0x15, 0x02e1); - rtl8168_mdio_write(tp, 0x19, 0x32e3); - rtl8168_mdio_write(tp, 0x15, 0x02e2); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x02e3); - rtl8168_mdio_write(tp, 0x19, 0x9bfa); - rtl8168_mdio_write(tp, 0x15, 0x02e4); - rtl8168_mdio_write(tp, 0x19, 0x84ca); - rtl8168_mdio_write(tp, 0x15, 0x02e5); - rtl8168_mdio_write(tp, 0x19, 0x85f8); - rtl8168_mdio_write(tp, 0x15, 0x02e6); - rtl8168_mdio_write(tp, 0x19, 0x32ec); - rtl8168_mdio_write(tp, 0x15, 0x02e7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02e8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02e9); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02ea); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02eb); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x02ec); - rtl8168_mdio_write(tp, 0x19, 0x48d4); - rtl8168_mdio_write(tp, 0x15, 0x02ed); - rtl8168_mdio_write(tp, 0x19, 0x4020); - rtl8168_mdio_write(tp, 0x15, 0x02ee); - rtl8168_mdio_write(tp, 0x19, 0x4844); - rtl8168_mdio_write(tp, 0x15, 0x02ef); - rtl8168_mdio_write(tp, 0x19, 0x4420); - rtl8168_mdio_write(tp, 0x15, 0x02f0); - rtl8168_mdio_write(tp, 0x19, 0x6800); - rtl8168_mdio_write(tp, 0x15, 0x02f1); - rtl8168_mdio_write(tp, 0x19, 0x7dc0); - rtl8168_mdio_write(tp, 0x15, 0x02f2); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x02f3); - rtl8168_mdio_write(tp, 0x19, 0x7c0b); - rtl8168_mdio_write(tp, 0x15, 0x02f4); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x02f5); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x02f6); - rtl8168_mdio_write(tp, 0x19, 0x9cfd); - rtl8168_mdio_write(tp, 0x15, 0x02f7); - rtl8168_mdio_write(tp, 0x19, 0xb616); - rtl8168_mdio_write(tp, 0x15, 0x02f8); - rtl8168_mdio_write(tp, 0x19, 0xc42b); - rtl8168_mdio_write(tp, 0x15, 0x02f9); - rtl8168_mdio_write(tp, 0x19, 0x00e0); - rtl8168_mdio_write(tp, 0x15, 0x02fa); - rtl8168_mdio_write(tp, 0x19, 0xc455); - rtl8168_mdio_write(tp, 0x15, 0x02fb); - rtl8168_mdio_write(tp, 0x19, 0x00b3); - rtl8168_mdio_write(tp, 0x15, 0x02fc); - rtl8168_mdio_write(tp, 0x19, 0xb20a); - rtl8168_mdio_write(tp, 0x15, 0x02fd); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x02fe); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x02ff); - rtl8168_mdio_write(tp, 0x19, 0x8204); - rtl8168_mdio_write(tp, 0x15, 0x0300); - rtl8168_mdio_write(tp, 0x19, 0x7c04); - rtl8168_mdio_write(tp, 0x15, 0x0301); - rtl8168_mdio_write(tp, 0x19, 0x7404); - rtl8168_mdio_write(tp, 0x15, 0x0302); - rtl8168_mdio_write(tp, 0x19, 0x32f3); - rtl8168_mdio_write(tp, 0x15, 0x0303); - rtl8168_mdio_write(tp, 0x19, 0x7c04); - rtl8168_mdio_write(tp, 0x15, 0x0304); - rtl8168_mdio_write(tp, 0x19, 0x7400); - rtl8168_mdio_write(tp, 0x15, 0x0305); - rtl8168_mdio_write(tp, 0x19, 0x32f3); - rtl8168_mdio_write(tp, 0x15, 0x0306); - rtl8168_mdio_write(tp, 0x19, 0xefed); - rtl8168_mdio_write(tp, 0x15, 0x0307); - rtl8168_mdio_write(tp, 0x19, 0x3342); - rtl8168_mdio_write(tp, 0x15, 0x0308); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0309); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030d); - rtl8168_mdio_write(tp, 0x19, 0x3006); - rtl8168_mdio_write(tp, 0x15, 0x030e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x030f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0310); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0311); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0312); - rtl8168_mdio_write(tp, 0x19, 0xa207); - rtl8168_mdio_write(tp, 0x15, 0x0313); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x0314); - rtl8168_mdio_write(tp, 0x19, 0x3322); - rtl8168_mdio_write(tp, 0x15, 0x0315); - rtl8168_mdio_write(tp, 0x19, 0x4041); - rtl8168_mdio_write(tp, 0x15, 0x0316); - rtl8168_mdio_write(tp, 0x19, 0x7d07); - rtl8168_mdio_write(tp, 0x15, 0x0317); - rtl8168_mdio_write(tp, 0x19, 0x4502); - rtl8168_mdio_write(tp, 0x15, 0x0318); - rtl8168_mdio_write(tp, 0x19, 0x3322); - rtl8168_mdio_write(tp, 0x15, 0x0319); - rtl8168_mdio_write(tp, 0x19, 0x4c08); - rtl8168_mdio_write(tp, 0x15, 0x031a); - rtl8168_mdio_write(tp, 0x19, 0x3322); - rtl8168_mdio_write(tp, 0x15, 0x031b); - rtl8168_mdio_write(tp, 0x19, 0x7d80); - rtl8168_mdio_write(tp, 0x15, 0x031c); - rtl8168_mdio_write(tp, 0x19, 0x5180); - rtl8168_mdio_write(tp, 0x15, 0x031d); - rtl8168_mdio_write(tp, 0x19, 0x3320); - rtl8168_mdio_write(tp, 0x15, 0x031e); - rtl8168_mdio_write(tp, 0x19, 0x7d80); - rtl8168_mdio_write(tp, 0x15, 0x031f); - rtl8168_mdio_write(tp, 0x19, 0x5000); - rtl8168_mdio_write(tp, 0x15, 0x0320); - rtl8168_mdio_write(tp, 0x19, 0x7d07); - rtl8168_mdio_write(tp, 0x15, 0x0321); - rtl8168_mdio_write(tp, 0x19, 0x4402); - rtl8168_mdio_write(tp, 0x15, 0x0322); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0323); - rtl8168_mdio_write(tp, 0x19, 0x6c02); - rtl8168_mdio_write(tp, 0x15, 0x0324); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x0325); - rtl8168_mdio_write(tp, 0x19, 0xb30c); - rtl8168_mdio_write(tp, 0x15, 0x0326); - rtl8168_mdio_write(tp, 0x19, 0xb206); - rtl8168_mdio_write(tp, 0x15, 0x0327); - rtl8168_mdio_write(tp, 0x19, 0xb103); - rtl8168_mdio_write(tp, 0x15, 0x0328); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0329); - rtl8168_mdio_write(tp, 0x19, 0x32f6); - rtl8168_mdio_write(tp, 0x15, 0x032a); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x032b); - rtl8168_mdio_write(tp, 0x19, 0x3352); - rtl8168_mdio_write(tp, 0x15, 0x032c); - rtl8168_mdio_write(tp, 0x19, 0xb103); - rtl8168_mdio_write(tp, 0x15, 0x032d); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x032e); - rtl8168_mdio_write(tp, 0x19, 0x336a); - rtl8168_mdio_write(tp, 0x15, 0x032f); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0330); - rtl8168_mdio_write(tp, 0x19, 0x3382); - rtl8168_mdio_write(tp, 0x15, 0x0331); - rtl8168_mdio_write(tp, 0x19, 0xb206); - rtl8168_mdio_write(tp, 0x15, 0x0332); - rtl8168_mdio_write(tp, 0x19, 0xb103); - rtl8168_mdio_write(tp, 0x15, 0x0333); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0334); - rtl8168_mdio_write(tp, 0x19, 0x3395); - rtl8168_mdio_write(tp, 0x15, 0x0335); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0336); - rtl8168_mdio_write(tp, 0x19, 0x33c6); - rtl8168_mdio_write(tp, 0x15, 0x0337); - rtl8168_mdio_write(tp, 0x19, 0xb103); - rtl8168_mdio_write(tp, 0x15, 0x0338); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x0339); - rtl8168_mdio_write(tp, 0x19, 0x33d7); - rtl8168_mdio_write(tp, 0x15, 0x033a); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x033b); - rtl8168_mdio_write(tp, 0x19, 0x33f2); - rtl8168_mdio_write(tp, 0x15, 0x033c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x033d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x033e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x033f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0340); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0341); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0342); - rtl8168_mdio_write(tp, 0x19, 0x49b5); - rtl8168_mdio_write(tp, 0x15, 0x0343); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x15, 0x0344); - rtl8168_mdio_write(tp, 0x19, 0x4d00); - rtl8168_mdio_write(tp, 0x15, 0x0345); - rtl8168_mdio_write(tp, 0x19, 0x6880); - rtl8168_mdio_write(tp, 0x15, 0x0346); - rtl8168_mdio_write(tp, 0x19, 0x7c08); - rtl8168_mdio_write(tp, 0x15, 0x0347); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x0348); - rtl8168_mdio_write(tp, 0x19, 0x4925); - rtl8168_mdio_write(tp, 0x15, 0x0349); - rtl8168_mdio_write(tp, 0x19, 0x403b); - rtl8168_mdio_write(tp, 0x15, 0x034a); - rtl8168_mdio_write(tp, 0x19, 0xa602); - rtl8168_mdio_write(tp, 0x15, 0x034b); - rtl8168_mdio_write(tp, 0x19, 0x402f); - rtl8168_mdio_write(tp, 0x15, 0x034c); - rtl8168_mdio_write(tp, 0x19, 0x4484); - rtl8168_mdio_write(tp, 0x15, 0x034d); - rtl8168_mdio_write(tp, 0x19, 0x40c8); - rtl8168_mdio_write(tp, 0x15, 0x034e); - rtl8168_mdio_write(tp, 0x19, 0x44c4); - rtl8168_mdio_write(tp, 0x15, 0x034f); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x0350); - rtl8168_mdio_write(tp, 0x19, 0x00bd); - rtl8168_mdio_write(tp, 0x15, 0x0351); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x0352); - rtl8168_mdio_write(tp, 0x19, 0xc8ed); - rtl8168_mdio_write(tp, 0x15, 0x0353); - rtl8168_mdio_write(tp, 0x19, 0x00fc); - rtl8168_mdio_write(tp, 0x15, 0x0354); - rtl8168_mdio_write(tp, 0x19, 0x8221); - rtl8168_mdio_write(tp, 0x15, 0x0355); - rtl8168_mdio_write(tp, 0x19, 0xd11d); - rtl8168_mdio_write(tp, 0x15, 0x0356); - rtl8168_mdio_write(tp, 0x19, 0x001f); - rtl8168_mdio_write(tp, 0x15, 0x0357); - rtl8168_mdio_write(tp, 0x19, 0xde18); - rtl8168_mdio_write(tp, 0x15, 0x0358); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x0359); - rtl8168_mdio_write(tp, 0x19, 0x91f6); - rtl8168_mdio_write(tp, 0x15, 0x035a); - rtl8168_mdio_write(tp, 0x19, 0x3360); - rtl8168_mdio_write(tp, 0x15, 0x035b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x035c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x035d); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x035e); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x035f); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0360); - rtl8168_mdio_write(tp, 0x19, 0x4bb6); - rtl8168_mdio_write(tp, 0x15, 0x0361); - rtl8168_mdio_write(tp, 0x19, 0x4064); - rtl8168_mdio_write(tp, 0x15, 0x0362); - rtl8168_mdio_write(tp, 0x19, 0x4b26); - rtl8168_mdio_write(tp, 0x15, 0x0363); - rtl8168_mdio_write(tp, 0x19, 0x4410); - rtl8168_mdio_write(tp, 0x15, 0x0364); - rtl8168_mdio_write(tp, 0x19, 0x4006); - rtl8168_mdio_write(tp, 0x15, 0x0365); - rtl8168_mdio_write(tp, 0x19, 0x4490); - rtl8168_mdio_write(tp, 0x15, 0x0366); - rtl8168_mdio_write(tp, 0x19, 0x6900); - rtl8168_mdio_write(tp, 0x15, 0x0367); - rtl8168_mdio_write(tp, 0x19, 0xb6a6); - rtl8168_mdio_write(tp, 0x15, 0x0368); - rtl8168_mdio_write(tp, 0x19, 0x9e02); - rtl8168_mdio_write(tp, 0x15, 0x0369); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x036a); - rtl8168_mdio_write(tp, 0x19, 0xd11d); - rtl8168_mdio_write(tp, 0x15, 0x036b); - rtl8168_mdio_write(tp, 0x19, 0x000a); - rtl8168_mdio_write(tp, 0x15, 0x036c); - rtl8168_mdio_write(tp, 0x19, 0xbb0f); - rtl8168_mdio_write(tp, 0x15, 0x036d); - rtl8168_mdio_write(tp, 0x19, 0x8102); - rtl8168_mdio_write(tp, 0x15, 0x036e); - rtl8168_mdio_write(tp, 0x19, 0x3371); - rtl8168_mdio_write(tp, 0x15, 0x036f); - rtl8168_mdio_write(tp, 0x19, 0xa21e); - rtl8168_mdio_write(tp, 0x15, 0x0370); - rtl8168_mdio_write(tp, 0x19, 0x33b6); - rtl8168_mdio_write(tp, 0x15, 0x0371); - rtl8168_mdio_write(tp, 0x19, 0x91f6); - rtl8168_mdio_write(tp, 0x15, 0x0372); - rtl8168_mdio_write(tp, 0x19, 0xc218); - rtl8168_mdio_write(tp, 0x15, 0x0373); - rtl8168_mdio_write(tp, 0x19, 0x00f4); - rtl8168_mdio_write(tp, 0x15, 0x0374); - rtl8168_mdio_write(tp, 0x19, 0x33b6); - rtl8168_mdio_write(tp, 0x15, 0x0375); - rtl8168_mdio_write(tp, 0x19, 0x32ec); - rtl8168_mdio_write(tp, 0x15, 0x0376); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0377); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0378); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x0379); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x037a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x037b); - rtl8168_mdio_write(tp, 0x19, 0x4b97); - rtl8168_mdio_write(tp, 0x15, 0x037c); - rtl8168_mdio_write(tp, 0x19, 0x402b); - rtl8168_mdio_write(tp, 0x15, 0x037d); - rtl8168_mdio_write(tp, 0x19, 0x4b07); - rtl8168_mdio_write(tp, 0x15, 0x037e); - rtl8168_mdio_write(tp, 0x19, 0x4422); - rtl8168_mdio_write(tp, 0x15, 0x037f); - rtl8168_mdio_write(tp, 0x19, 0x6980); - rtl8168_mdio_write(tp, 0x15, 0x0380); - rtl8168_mdio_write(tp, 0x19, 0xb608); - rtl8168_mdio_write(tp, 0x15, 0x0381); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x0382); - rtl8168_mdio_write(tp, 0x19, 0xbc05); - rtl8168_mdio_write(tp, 0x15, 0x0383); - rtl8168_mdio_write(tp, 0x19, 0xc21c); - rtl8168_mdio_write(tp, 0x15, 0x0384); - rtl8168_mdio_write(tp, 0x19, 0x0032); - rtl8168_mdio_write(tp, 0x15, 0x0385); - rtl8168_mdio_write(tp, 0x19, 0xa1fb); - rtl8168_mdio_write(tp, 0x15, 0x0386); - rtl8168_mdio_write(tp, 0x19, 0x338d); - rtl8168_mdio_write(tp, 0x15, 0x0387); - rtl8168_mdio_write(tp, 0x19, 0x32ae); - rtl8168_mdio_write(tp, 0x15, 0x0388); - rtl8168_mdio_write(tp, 0x19, 0x330d); - rtl8168_mdio_write(tp, 0x15, 0x0389); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x038a); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x038b); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x038c); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x038d); - rtl8168_mdio_write(tp, 0x19, 0x4b97); - rtl8168_mdio_write(tp, 0x15, 0x038e); - rtl8168_mdio_write(tp, 0x19, 0x6a08); - rtl8168_mdio_write(tp, 0x15, 0x038f); - rtl8168_mdio_write(tp, 0x19, 0x4b07); - rtl8168_mdio_write(tp, 0x15, 0x0390); - rtl8168_mdio_write(tp, 0x19, 0x40ac); - rtl8168_mdio_write(tp, 0x15, 0x0391); - rtl8168_mdio_write(tp, 0x19, 0x4445); - rtl8168_mdio_write(tp, 0x15, 0x0392); - rtl8168_mdio_write(tp, 0x19, 0x404e); - rtl8168_mdio_write(tp, 0x15, 0x0393); - rtl8168_mdio_write(tp, 0x19, 0x4461); - rtl8168_mdio_write(tp, 0x15, 0x0394); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x0395); - rtl8168_mdio_write(tp, 0x19, 0x9c0a); - rtl8168_mdio_write(tp, 0x15, 0x0396); - rtl8168_mdio_write(tp, 0x19, 0x63da); - rtl8168_mdio_write(tp, 0x15, 0x0397); - rtl8168_mdio_write(tp, 0x19, 0x6f0c); - rtl8168_mdio_write(tp, 0x15, 0x0398); - rtl8168_mdio_write(tp, 0x19, 0x5440); - rtl8168_mdio_write(tp, 0x15, 0x0399); - rtl8168_mdio_write(tp, 0x19, 0x4b98); - rtl8168_mdio_write(tp, 0x15, 0x039a); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x039b); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x039c); - rtl8168_mdio_write(tp, 0x19, 0x4b08); - rtl8168_mdio_write(tp, 0x15, 0x039d); - rtl8168_mdio_write(tp, 0x19, 0x63d8); - rtl8168_mdio_write(tp, 0x15, 0x039e); - rtl8168_mdio_write(tp, 0x19, 0x33a5); - rtl8168_mdio_write(tp, 0x15, 0x039f); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x03a0); - rtl8168_mdio_write(tp, 0x19, 0x00e8); - rtl8168_mdio_write(tp, 0x15, 0x03a1); - rtl8168_mdio_write(tp, 0x19, 0x820e); - rtl8168_mdio_write(tp, 0x15, 0x03a2); - rtl8168_mdio_write(tp, 0x19, 0xa10d); - rtl8168_mdio_write(tp, 0x15, 0x03a3); - rtl8168_mdio_write(tp, 0x19, 0x9df1); - rtl8168_mdio_write(tp, 0x15, 0x03a4); - rtl8168_mdio_write(tp, 0x19, 0x33af); - rtl8168_mdio_write(tp, 0x15, 0x03a5); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x03a6); - rtl8168_mdio_write(tp, 0x19, 0x00f9); - rtl8168_mdio_write(tp, 0x15, 0x03a7); - rtl8168_mdio_write(tp, 0x19, 0xc017); - rtl8168_mdio_write(tp, 0x15, 0x03a8); - rtl8168_mdio_write(tp, 0x19, 0x0007); - rtl8168_mdio_write(tp, 0x15, 0x03a9); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x03aa); - rtl8168_mdio_write(tp, 0x19, 0x6c03); - rtl8168_mdio_write(tp, 0x15, 0x03ab); - rtl8168_mdio_write(tp, 0x19, 0xa104); - rtl8168_mdio_write(tp, 0x15, 0x03ac); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x03ad); - rtl8168_mdio_write(tp, 0x19, 0x6c00); - rtl8168_mdio_write(tp, 0x15, 0x03ae); - rtl8168_mdio_write(tp, 0x19, 0x9df7); - rtl8168_mdio_write(tp, 0x15, 0x03af); - rtl8168_mdio_write(tp, 0x19, 0x7c03); - rtl8168_mdio_write(tp, 0x15, 0x03b0); - rtl8168_mdio_write(tp, 0x19, 0x6c08); - rtl8168_mdio_write(tp, 0x15, 0x03b1); - rtl8168_mdio_write(tp, 0x19, 0x33b6); - rtl8168_mdio_write(tp, 0x15, 0x03b2); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b3); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b4); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03b6); - rtl8168_mdio_write(tp, 0x19, 0x55af); - rtl8168_mdio_write(tp, 0x15, 0x03b7); - rtl8168_mdio_write(tp, 0x19, 0x7ff0); - rtl8168_mdio_write(tp, 0x15, 0x03b8); - rtl8168_mdio_write(tp, 0x19, 0x6ff0); - rtl8168_mdio_write(tp, 0x15, 0x03b9); - rtl8168_mdio_write(tp, 0x19, 0x4bb9); - rtl8168_mdio_write(tp, 0x15, 0x03ba); - rtl8168_mdio_write(tp, 0x19, 0x6a80); - rtl8168_mdio_write(tp, 0x15, 0x03bb); - rtl8168_mdio_write(tp, 0x19, 0x4b29); - rtl8168_mdio_write(tp, 0x15, 0x03bc); - rtl8168_mdio_write(tp, 0x19, 0x4041); - rtl8168_mdio_write(tp, 0x15, 0x03bd); - rtl8168_mdio_write(tp, 0x19, 0x440a); - rtl8168_mdio_write(tp, 0x15, 0x03be); - rtl8168_mdio_write(tp, 0x19, 0x4029); - rtl8168_mdio_write(tp, 0x15, 0x03bf); - rtl8168_mdio_write(tp, 0x19, 0x4418); - rtl8168_mdio_write(tp, 0x15, 0x03c0); - rtl8168_mdio_write(tp, 0x19, 0x4090); - rtl8168_mdio_write(tp, 0x15, 0x03c1); - rtl8168_mdio_write(tp, 0x19, 0x4438); - rtl8168_mdio_write(tp, 0x15, 0x03c2); - rtl8168_mdio_write(tp, 0x19, 0x40c4); - rtl8168_mdio_write(tp, 0x15, 0x03c3); - rtl8168_mdio_write(tp, 0x19, 0x447b); - rtl8168_mdio_write(tp, 0x15, 0x03c4); - rtl8168_mdio_write(tp, 0x19, 0xb6c4); - rtl8168_mdio_write(tp, 0x15, 0x03c5); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x03c6); - rtl8168_mdio_write(tp, 0x19, 0x9bfe); - rtl8168_mdio_write(tp, 0x15, 0x03c7); - rtl8168_mdio_write(tp, 0x19, 0x33cc); - rtl8168_mdio_write(tp, 0x15, 0x03c8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03c9); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03ca); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03cb); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03cc); - rtl8168_mdio_write(tp, 0x19, 0x542f); - rtl8168_mdio_write(tp, 0x15, 0x03cd); - rtl8168_mdio_write(tp, 0x19, 0x499a); - rtl8168_mdio_write(tp, 0x15, 0x03ce); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x03cf); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03d0); - rtl8168_mdio_write(tp, 0x19, 0x490a); - rtl8168_mdio_write(tp, 0x15, 0x03d1); - rtl8168_mdio_write(tp, 0x19, 0x405e); - rtl8168_mdio_write(tp, 0x15, 0x03d2); - rtl8168_mdio_write(tp, 0x19, 0x44f8); - rtl8168_mdio_write(tp, 0x15, 0x03d3); - rtl8168_mdio_write(tp, 0x19, 0x6b00); - rtl8168_mdio_write(tp, 0x15, 0x03d4); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x03d5); - rtl8168_mdio_write(tp, 0x19, 0x0028); - rtl8168_mdio_write(tp, 0x15, 0x03d6); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x03d7); - rtl8168_mdio_write(tp, 0x19, 0xbd27); - rtl8168_mdio_write(tp, 0x15, 0x03d8); - rtl8168_mdio_write(tp, 0x19, 0x9cfc); - rtl8168_mdio_write(tp, 0x15, 0x03d9); - rtl8168_mdio_write(tp, 0x19, 0xc639); - rtl8168_mdio_write(tp, 0x15, 0x03da); - rtl8168_mdio_write(tp, 0x19, 0x000f); - rtl8168_mdio_write(tp, 0x15, 0x03db); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x03dc); - rtl8168_mdio_write(tp, 0x19, 0x7c01); - rtl8168_mdio_write(tp, 0x15, 0x03dd); - rtl8168_mdio_write(tp, 0x19, 0x4c01); - rtl8168_mdio_write(tp, 0x15, 0x03de); - rtl8168_mdio_write(tp, 0x19, 0x9af6); - rtl8168_mdio_write(tp, 0x15, 0x03df); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03e0); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03e1); - rtl8168_mdio_write(tp, 0x19, 0x4470); - rtl8168_mdio_write(tp, 0x15, 0x03e2); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03e3); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03e4); - rtl8168_mdio_write(tp, 0x19, 0x33d4); - rtl8168_mdio_write(tp, 0x15, 0x03e5); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03e6); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03e7); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03e8); - rtl8168_mdio_write(tp, 0x19, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x03e9); - rtl8168_mdio_write(tp, 0x19, 0x49bb); - rtl8168_mdio_write(tp, 0x15, 0x03ea); - rtl8168_mdio_write(tp, 0x19, 0x4478); - rtl8168_mdio_write(tp, 0x15, 0x03eb); - rtl8168_mdio_write(tp, 0x19, 0x492b); - rtl8168_mdio_write(tp, 0x15, 0x03ec); - rtl8168_mdio_write(tp, 0x19, 0x6b80); - rtl8168_mdio_write(tp, 0x15, 0x03ed); - rtl8168_mdio_write(tp, 0x19, 0x7c01); - rtl8168_mdio_write(tp, 0x15, 0x03ee); - rtl8168_mdio_write(tp, 0x19, 0x4c00); - rtl8168_mdio_write(tp, 0x15, 0x03ef); - rtl8168_mdio_write(tp, 0x19, 0xd64f); - rtl8168_mdio_write(tp, 0x15, 0x03f0); - rtl8168_mdio_write(tp, 0x19, 0x000d); - rtl8168_mdio_write(tp, 0x15, 0x03f1); - rtl8168_mdio_write(tp, 0x19, 0x3311); - rtl8168_mdio_write(tp, 0x15, 0x03f2); - rtl8168_mdio_write(tp, 0x19, 0xbd0c); - rtl8168_mdio_write(tp, 0x15, 0x03f3); - rtl8168_mdio_write(tp, 0x19, 0xc428); - rtl8168_mdio_write(tp, 0x15, 0x03f4); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x15, 0x03f5); - rtl8168_mdio_write(tp, 0x19, 0x9afa); - rtl8168_mdio_write(tp, 0x15, 0x03f6); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03f7); - rtl8168_mdio_write(tp, 0x19, 0x4c52); - rtl8168_mdio_write(tp, 0x15, 0x03f8); - rtl8168_mdio_write(tp, 0x19, 0x4470); - rtl8168_mdio_write(tp, 0x15, 0x03f9); - rtl8168_mdio_write(tp, 0x19, 0x7c12); - rtl8168_mdio_write(tp, 0x15, 0x03fa); - rtl8168_mdio_write(tp, 0x19, 0x4c40); - rtl8168_mdio_write(tp, 0x15, 0x03fb); - rtl8168_mdio_write(tp, 0x19, 0x33ef); - rtl8168_mdio_write(tp, 0x15, 0x03fc); - rtl8168_mdio_write(tp, 0x19, 0x3342); - rtl8168_mdio_write(tp, 0x15, 0x03fd); - rtl8168_mdio_write(tp, 0x19, 0x330d); - rtl8168_mdio_write(tp, 0x15, 0x03fe); - rtl8168_mdio_write(tp, 0x19, 0x32ae); - rtl8168_mdio_write(tp, 0x15, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x0112); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x1f02); - rtl8168_mdio_write(tp, 0x06, 0x012c); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x3c02); - rtl8168_mdio_write(tp, 0x06, 0x0156); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x6d02); - rtl8168_mdio_write(tp, 0x06, 0x809d); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xc702); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd105); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xcd02); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xca02); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd105); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xd002); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd481); - rtl8168_mdio_write(tp, 0x06, 0xc9e4); - rtl8168_mdio_write(tp, 0x06, 0x8b90); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x91d4); - rtl8168_mdio_write(tp, 0x06, 0x81b8); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x92e5); - rtl8168_mdio_write(tp, 0x06, 0x8b93); - rtl8168_mdio_write(tp, 0x06, 0xbf8b); - rtl8168_mdio_write(tp, 0x06, 0x88ec); - rtl8168_mdio_write(tp, 0x06, 0x0019); - rtl8168_mdio_write(tp, 0x06, 0xa98b); - rtl8168_mdio_write(tp, 0x06, 0x90f9); - rtl8168_mdio_write(tp, 0x06, 0xeeff); - rtl8168_mdio_write(tp, 0x06, 0xf600); - rtl8168_mdio_write(tp, 0x06, 0xeeff); - rtl8168_mdio_write(tp, 0x06, 0xf7fc); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xc102); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xc402); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x201a); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x824b); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x1902); - rtl8168_mdio_write(tp, 0x06, 0x2c9d); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x9602); - rtl8168_mdio_write(tp, 0x06, 0x0473); - rtl8168_mdio_write(tp, 0x06, 0x022e); - rtl8168_mdio_write(tp, 0x06, 0x3902); - rtl8168_mdio_write(tp, 0x06, 0x044d); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x210b); - rtl8168_mdio_write(tp, 0x06, 0xf621); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x0416); - rtl8168_mdio_write(tp, 0x06, 0x021b); - rtl8168_mdio_write(tp, 0x06, 0xa4e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x22e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2305); - rtl8168_mdio_write(tp, 0x06, 0xf623); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x24e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2505); - rtl8168_mdio_write(tp, 0x06, 0xf625); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x26e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xdae0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x27e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x5cfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad21); - rtl8168_mdio_write(tp, 0x06, 0x57e0); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x2358); - rtl8168_mdio_write(tp, 0x06, 0xc059); - rtl8168_mdio_write(tp, 0x06, 0x021e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b3c); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e44); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x3cad); - rtl8168_mdio_write(tp, 0x06, 0x211d); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x84f7); - rtl8168_mdio_write(tp, 0x06, 0x29e5); - rtl8168_mdio_write(tp, 0x06, 0x8b84); - rtl8168_mdio_write(tp, 0x06, 0xac27); - rtl8168_mdio_write(tp, 0x06, 0x0dac); - rtl8168_mdio_write(tp, 0x06, 0x2605); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x7fae); - rtl8168_mdio_write(tp, 0x06, 0x2b02); - rtl8168_mdio_write(tp, 0x06, 0x2c23); - rtl8168_mdio_write(tp, 0x06, 0xae26); - rtl8168_mdio_write(tp, 0x06, 0x022c); - rtl8168_mdio_write(tp, 0x06, 0x41ae); - rtl8168_mdio_write(tp, 0x06, 0x21e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x18e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0x58fc); - rtl8168_mdio_write(tp, 0x06, 0xe4ff); - rtl8168_mdio_write(tp, 0x06, 0xf7d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x2eee); - rtl8168_mdio_write(tp, 0x06, 0x0232); - rtl8168_mdio_write(tp, 0x06, 0x0ad1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x82e8); - rtl8168_mdio_write(tp, 0x06, 0x0232); - rtl8168_mdio_write(tp, 0x06, 0x0a02); - rtl8168_mdio_write(tp, 0x06, 0x2bdf); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x04d0); - rtl8168_mdio_write(tp, 0x06, 0x0202); - rtl8168_mdio_write(tp, 0x06, 0x1e97); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2228); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xd302); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd10c); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xd602); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd104); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xd902); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xe802); - rtl8168_mdio_write(tp, 0x06, 0x320a); - rtl8168_mdio_write(tp, 0x06, 0xe0ff); - rtl8168_mdio_write(tp, 0x06, 0xf768); - rtl8168_mdio_write(tp, 0x06, 0x03e4); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xd004); - rtl8168_mdio_write(tp, 0x06, 0x0228); - rtl8168_mdio_write(tp, 0x06, 0x7a04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0xe234); - rtl8168_mdio_write(tp, 0x06, 0xe1e2); - rtl8168_mdio_write(tp, 0x06, 0x35f6); - rtl8168_mdio_write(tp, 0x06, 0x2be4); - rtl8168_mdio_write(tp, 0x06, 0xe234); - rtl8168_mdio_write(tp, 0x06, 0xe5e2); - rtl8168_mdio_write(tp, 0x06, 0x35fc); - rtl8168_mdio_write(tp, 0x06, 0x05f8); - rtl8168_mdio_write(tp, 0x06, 0xe0e2); - rtl8168_mdio_write(tp, 0x06, 0x34e1); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xf72b); - rtl8168_mdio_write(tp, 0x06, 0xe4e2); - rtl8168_mdio_write(tp, 0x06, 0x34e5); - rtl8168_mdio_write(tp, 0x06, 0xe235); - rtl8168_mdio_write(tp, 0x06, 0xfc05); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69ac); - rtl8168_mdio_write(tp, 0x06, 0x1b4c); - rtl8168_mdio_write(tp, 0x06, 0xbf2e); - rtl8168_mdio_write(tp, 0x06, 0x3002); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0xef01); - rtl8168_mdio_write(tp, 0x06, 0xe28a); - rtl8168_mdio_write(tp, 0x06, 0x76e4); - rtl8168_mdio_write(tp, 0x06, 0x8a76); - rtl8168_mdio_write(tp, 0x06, 0x1f12); - rtl8168_mdio_write(tp, 0x06, 0x9e3a); - rtl8168_mdio_write(tp, 0x06, 0xef12); - rtl8168_mdio_write(tp, 0x06, 0x5907); - rtl8168_mdio_write(tp, 0x06, 0x9f12); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf721); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40d0); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x287a); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x34fc); - rtl8168_mdio_write(tp, 0x06, 0xa000); - rtl8168_mdio_write(tp, 0x06, 0x1002); - rtl8168_mdio_write(tp, 0x06, 0x2dc3); - rtl8168_mdio_write(tp, 0x06, 0x022e); - rtl8168_mdio_write(tp, 0x06, 0x21e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf621); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40ae); - rtl8168_mdio_write(tp, 0x06, 0x0fbf); - rtl8168_mdio_write(tp, 0x06, 0x3fa5); - rtl8168_mdio_write(tp, 0x06, 0x0231); - rtl8168_mdio_write(tp, 0x06, 0x6cbf); - rtl8168_mdio_write(tp, 0x06, 0x3fa2); - rtl8168_mdio_write(tp, 0x06, 0x0231); - rtl8168_mdio_write(tp, 0x06, 0x6c02); - rtl8168_mdio_write(tp, 0x06, 0x2dc3); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0xe2f4); - rtl8168_mdio_write(tp, 0x06, 0xe1e2); - rtl8168_mdio_write(tp, 0x06, 0xf5e4); - rtl8168_mdio_write(tp, 0x06, 0x8a78); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0x79ee); - rtl8168_mdio_write(tp, 0x06, 0xe2f4); - rtl8168_mdio_write(tp, 0x06, 0xd8ee); - rtl8168_mdio_write(tp, 0x06, 0xe2f5); - rtl8168_mdio_write(tp, 0x06, 0x20fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2065); - rtl8168_mdio_write(tp, 0x06, 0xd200); - rtl8168_mdio_write(tp, 0x06, 0xbf2e); - rtl8168_mdio_write(tp, 0x06, 0xe802); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0x1e21); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xdf02); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0x0c11); - rtl8168_mdio_write(tp, 0x06, 0x1e21); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xe202); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0x0c12); - rtl8168_mdio_write(tp, 0x06, 0x1e21); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xe502); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0x0c13); - rtl8168_mdio_write(tp, 0x06, 0x1e21); - rtl8168_mdio_write(tp, 0x06, 0xbf1f); - rtl8168_mdio_write(tp, 0x06, 0x5302); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0x0c14); - rtl8168_mdio_write(tp, 0x06, 0x1e21); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0xeb02); - rtl8168_mdio_write(tp, 0x06, 0x31dd); - rtl8168_mdio_write(tp, 0x06, 0x0c16); - rtl8168_mdio_write(tp, 0x06, 0x1e21); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0xe01f); - rtl8168_mdio_write(tp, 0x06, 0x029e); - rtl8168_mdio_write(tp, 0x06, 0x22e6); - rtl8168_mdio_write(tp, 0x06, 0x83e0); - rtl8168_mdio_write(tp, 0x06, 0xad31); - rtl8168_mdio_write(tp, 0x06, 0x14ad); - rtl8168_mdio_write(tp, 0x06, 0x3011); - rtl8168_mdio_write(tp, 0x06, 0xef02); - rtl8168_mdio_write(tp, 0x06, 0x580c); - rtl8168_mdio_write(tp, 0x06, 0x9e07); - rtl8168_mdio_write(tp, 0x06, 0xad36); - rtl8168_mdio_write(tp, 0x06, 0x085a); - rtl8168_mdio_write(tp, 0x06, 0x309f); - rtl8168_mdio_write(tp, 0x06, 0x04d1); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0x02d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x82dc); - rtl8168_mdio_write(tp, 0x06, 0x0232); - rtl8168_mdio_write(tp, 0x06, 0x0aef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x0400); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0x77e1); - rtl8168_mdio_write(tp, 0x06, 0x4010); - rtl8168_mdio_write(tp, 0x06, 0xe150); - rtl8168_mdio_write(tp, 0x06, 0x32e1); - rtl8168_mdio_write(tp, 0x06, 0x5030); - rtl8168_mdio_write(tp, 0x06, 0xe144); - rtl8168_mdio_write(tp, 0x06, 0x74e1); - rtl8168_mdio_write(tp, 0x06, 0x44bb); - rtl8168_mdio_write(tp, 0x06, 0xe2d2); - rtl8168_mdio_write(tp, 0x06, 0x40e0); - rtl8168_mdio_write(tp, 0x06, 0x2cfc); - rtl8168_mdio_write(tp, 0x06, 0xe2cc); - rtl8168_mdio_write(tp, 0x06, 0xcce2); - rtl8168_mdio_write(tp, 0x06, 0x00cc); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0x99e0); - rtl8168_mdio_write(tp, 0x06, 0x3688); - rtl8168_mdio_write(tp, 0x06, 0xe036); - rtl8168_mdio_write(tp, 0x06, 0x99e1); - rtl8168_mdio_write(tp, 0x06, 0x40dd); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x05, 0xe142); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x05, 0xe140); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - gphy_val |= BIT_2; - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); -} - -static void -rtl8168_set_phy_mcu_8168evl_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - unsigned int gphy_val,i; - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x1800); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val &= ~(BIT_12); - rtl8168_mdio_write(tp, 0x15, gphy_val); - rtl8168_mdio_write(tp, 0x00, 0x4800); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x002f); - for (i = 0; i < 1000; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1c); - if ((gphy_val & 0x0080) == 0x0080) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x1800); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x17); - if (!(gphy_val & 0x0001)) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x00AF); - rtl8168_mdio_write(tp, 0x19, 0x4060); - rtl8168_mdio_write(tp, 0x15, 0x00B0); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x00B1); - rtl8168_mdio_write(tp, 0x19, 0x7e00); - rtl8168_mdio_write(tp, 0x15, 0x00B2); - rtl8168_mdio_write(tp, 0x19, 0x72B0); - rtl8168_mdio_write(tp, 0x15, 0x00B3); - rtl8168_mdio_write(tp, 0x19, 0x7F00); - rtl8168_mdio_write(tp, 0x15, 0x00B4); - rtl8168_mdio_write(tp, 0x19, 0x73B0); - rtl8168_mdio_write(tp, 0x15, 0x0101); - rtl8168_mdio_write(tp, 0x19, 0x0005); - rtl8168_mdio_write(tp, 0x15, 0x0103); - rtl8168_mdio_write(tp, 0x19, 0x0003); - rtl8168_mdio_write(tp, 0x15, 0x0105); - rtl8168_mdio_write(tp, 0x19, 0x30FD); - rtl8168_mdio_write(tp, 0x15, 0x0106); - rtl8168_mdio_write(tp, 0x19, 0x9DF7); - rtl8168_mdio_write(tp, 0x15, 0x0107); - rtl8168_mdio_write(tp, 0x19, 0x30C6); - rtl8168_mdio_write(tp, 0x15, 0x0098); - rtl8168_mdio_write(tp, 0x19, 0x7c0b); - rtl8168_mdio_write(tp, 0x15, 0x0099); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00eb); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00f8); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00fe); - rtl8168_mdio_write(tp, 0x19, 0x6f0f); - rtl8168_mdio_write(tp, 0x15, 0x00db); - rtl8168_mdio_write(tp, 0x19, 0x6f09); - rtl8168_mdio_write(tp, 0x15, 0x00dc); - rtl8168_mdio_write(tp, 0x19, 0xaefd); - rtl8168_mdio_write(tp, 0x15, 0x00dd); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00de); - rtl8168_mdio_write(tp, 0x19, 0xc60b); - rtl8168_mdio_write(tp, 0x15, 0x00df); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00e0); - rtl8168_mdio_write(tp, 0x19, 0x30e1); - rtl8168_mdio_write(tp, 0x15, 0x020c); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x020e); - rtl8168_mdio_write(tp, 0x19, 0x9813); - rtl8168_mdio_write(tp, 0x15, 0x020f); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0210); - rtl8168_mdio_write(tp, 0x19, 0x930f); - rtl8168_mdio_write(tp, 0x15, 0x0211); - rtl8168_mdio_write(tp, 0x19, 0x9206); - rtl8168_mdio_write(tp, 0x15, 0x0212); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0213); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0214); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0215); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0216); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0217); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0218); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0219); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x021a); - rtl8168_mdio_write(tp, 0x19, 0x5540); - rtl8168_mdio_write(tp, 0x15, 0x021b); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x021c); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x021d); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x021e); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x021f); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0220); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0221); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x0222); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0223); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x0224); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0225); - rtl8168_mdio_write(tp, 0x19, 0x3231); - rtl8168_mdio_write(tp, 0x15, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2160); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0040); - rtl8168_mdio_write(tp, 0x18, 0x0004); - if (pdev->subsystem_vendor == 0x144d && - pdev->subsystem_device == 0xc0a6) { - rtl8168_mdio_write(tp, 0x18, 0x0724); - rtl8168_mdio_write(tp, 0x19, 0xfe00); - rtl8168_mdio_write(tp, 0x18, 0x0734); - rtl8168_mdio_write(tp, 0x19, 0xfd00); - rtl8168_mdio_write(tp, 0x18, 0x1824); - rtl8168_mdio_write(tp, 0x19, 0xfc00); - rtl8168_mdio_write(tp, 0x18, 0x1834); - rtl8168_mdio_write(tp, 0x19, 0xfd00); - } - rtl8168_mdio_write(tp, 0x18, 0x09d4); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x09e4); - rtl8168_mdio_write(tp, 0x19, 0x0800); - rtl8168_mdio_write(tp, 0x18, 0x09f4); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x0a04); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x0a14); - rtl8168_mdio_write(tp, 0x19, 0x0c00); - rtl8168_mdio_write(tp, 0x18, 0x0a24); - rtl8168_mdio_write(tp, 0x19, 0xff00); - rtl8168_mdio_write(tp, 0x18, 0x0a74); - rtl8168_mdio_write(tp, 0x19, 0xf600); - rtl8168_mdio_write(tp, 0x18, 0x1a24); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x18, 0x1a64); - rtl8168_mdio_write(tp, 0x19, 0x0500); - rtl8168_mdio_write(tp, 0x18, 0x1a74); - rtl8168_mdio_write(tp, 0x19, 0x9500); - rtl8168_mdio_write(tp, 0x18, 0x1a84); - rtl8168_mdio_write(tp, 0x19, 0x8000); - rtl8168_mdio_write(tp, 0x18, 0x1a94); - rtl8168_mdio_write(tp, 0x19, 0x7d00); - rtl8168_mdio_write(tp, 0x18, 0x1aa4); - rtl8168_mdio_write(tp, 0x19, 0x9600); - rtl8168_mdio_write(tp, 0x18, 0x1ac4); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x1ad4); - rtl8168_mdio_write(tp, 0x19, 0x0800); - rtl8168_mdio_write(tp, 0x18, 0x1af4); - rtl8168_mdio_write(tp, 0x19, 0xc400); - rtl8168_mdio_write(tp, 0x18, 0x1b04); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x1b14); - rtl8168_mdio_write(tp, 0x19, 0x0800); - rtl8168_mdio_write(tp, 0x18, 0x1b24); - rtl8168_mdio_write(tp, 0x19, 0xfd00); - rtl8168_mdio_write(tp, 0x18, 0x1b34); - rtl8168_mdio_write(tp, 0x19, 0x4000); - rtl8168_mdio_write(tp, 0x18, 0x1b44); - rtl8168_mdio_write(tp, 0x19, 0x0400); - rtl8168_mdio_write(tp, 0x18, 0x1b94); - rtl8168_mdio_write(tp, 0x19, 0xf100); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x17, 0x2100); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0040); - rtl8168_mdio_write(tp, 0x18, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x0115); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x2202); - rtl8168_mdio_write(tp, 0x06, 0x80a0); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x3f02); - rtl8168_mdio_write(tp, 0x06, 0x0159); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0xbd02); - rtl8168_mdio_write(tp, 0x06, 0x80da); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xd481); - rtl8168_mdio_write(tp, 0x06, 0xd2e4); - rtl8168_mdio_write(tp, 0x06, 0x8b92); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x93d1); - rtl8168_mdio_write(tp, 0x06, 0x03bf); - rtl8168_mdio_write(tp, 0x06, 0x859e); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23d1); - rtl8168_mdio_write(tp, 0x06, 0x02bf); - rtl8168_mdio_write(tp, 0x06, 0x85a1); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23ee); - rtl8168_mdio_write(tp, 0x06, 0x8608); - rtl8168_mdio_write(tp, 0x06, 0x03ee); - rtl8168_mdio_write(tp, 0x06, 0x860a); - rtl8168_mdio_write(tp, 0x06, 0x60ee); - rtl8168_mdio_write(tp, 0x06, 0x8610); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8611); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x07ee); - rtl8168_mdio_write(tp, 0x06, 0x8abf); - rtl8168_mdio_write(tp, 0x06, 0x73ee); - rtl8168_mdio_write(tp, 0x06, 0x8a95); - rtl8168_mdio_write(tp, 0x06, 0x02bf); - rtl8168_mdio_write(tp, 0x06, 0x8b88); - rtl8168_mdio_write(tp, 0x06, 0xec00); - rtl8168_mdio_write(tp, 0x06, 0x19a9); - rtl8168_mdio_write(tp, 0x06, 0x8b90); - rtl8168_mdio_write(tp, 0x06, 0xf9ee); - rtl8168_mdio_write(tp, 0x06, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xfed1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8595); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23d1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x8598); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x2304); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8a); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x14ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8a); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x1f9a); - rtl8168_mdio_write(tp, 0x06, 0xe0e4); - rtl8168_mdio_write(tp, 0x06, 0x26e1); - rtl8168_mdio_write(tp, 0x06, 0xe427); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x2623); - rtl8168_mdio_write(tp, 0x06, 0xe5e4); - rtl8168_mdio_write(tp, 0x06, 0x27fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8dad); - rtl8168_mdio_write(tp, 0x06, 0x2014); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8d00); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0x5a78); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x0902); - rtl8168_mdio_write(tp, 0x06, 0x05db); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x7b02); - rtl8168_mdio_write(tp, 0x06, 0x3231); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x1df6); - rtl8168_mdio_write(tp, 0x06, 0x20e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x5c02); - rtl8168_mdio_write(tp, 0x06, 0x2bcb); - rtl8168_mdio_write(tp, 0x06, 0x022d); - rtl8168_mdio_write(tp, 0x06, 0x2902); - rtl8168_mdio_write(tp, 0x06, 0x03b4); - rtl8168_mdio_write(tp, 0x06, 0x0285); - rtl8168_mdio_write(tp, 0x06, 0x6402); - rtl8168_mdio_write(tp, 0x06, 0x2eca); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0xcd02); - rtl8168_mdio_write(tp, 0x06, 0x046f); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x210b); - rtl8168_mdio_write(tp, 0x06, 0xf621); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x8520); - rtl8168_mdio_write(tp, 0x06, 0x021b); - rtl8168_mdio_write(tp, 0x06, 0xe8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x22e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2308); - rtl8168_mdio_write(tp, 0x06, 0xf623); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x311c); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2405); - rtl8168_mdio_write(tp, 0x06, 0xf624); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x25e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2608); - rtl8168_mdio_write(tp, 0x06, 0xf626); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x2df5); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2705); - rtl8168_mdio_write(tp, 0x06, 0xf627); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x037a); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x65d2); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x2fe9); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf61e); - rtl8168_mdio_write(tp, 0x06, 0x21bf); - rtl8168_mdio_write(tp, 0x06, 0x2ff5); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf60c); - rtl8168_mdio_write(tp, 0x06, 0x111e); - rtl8168_mdio_write(tp, 0x06, 0x21bf); - rtl8168_mdio_write(tp, 0x06, 0x2ff8); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf60c); - rtl8168_mdio_write(tp, 0x06, 0x121e); - rtl8168_mdio_write(tp, 0x06, 0x21bf); - rtl8168_mdio_write(tp, 0x06, 0x2ffb); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf60c); - rtl8168_mdio_write(tp, 0x06, 0x131e); - rtl8168_mdio_write(tp, 0x06, 0x21bf); - rtl8168_mdio_write(tp, 0x06, 0x1f97); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf60c); - rtl8168_mdio_write(tp, 0x06, 0x141e); - rtl8168_mdio_write(tp, 0x06, 0x21bf); - rtl8168_mdio_write(tp, 0x06, 0x859b); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf60c); - rtl8168_mdio_write(tp, 0x06, 0x161e); - rtl8168_mdio_write(tp, 0x06, 0x21e0); - rtl8168_mdio_write(tp, 0x06, 0x8a8c); - rtl8168_mdio_write(tp, 0x06, 0x1f02); - rtl8168_mdio_write(tp, 0x06, 0x9e22); - rtl8168_mdio_write(tp, 0x06, 0xe68a); - rtl8168_mdio_write(tp, 0x06, 0x8cad); - rtl8168_mdio_write(tp, 0x06, 0x3114); - rtl8168_mdio_write(tp, 0x06, 0xad30); - rtl8168_mdio_write(tp, 0x06, 0x11ef); - rtl8168_mdio_write(tp, 0x06, 0x0258); - rtl8168_mdio_write(tp, 0x06, 0x0c9e); - rtl8168_mdio_write(tp, 0x06, 0x07ad); - rtl8168_mdio_write(tp, 0x06, 0x3608); - rtl8168_mdio_write(tp, 0x06, 0x5a30); - rtl8168_mdio_write(tp, 0x06, 0x9f04); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xae02); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf2f); - rtl8168_mdio_write(tp, 0x06, 0xf202); - rtl8168_mdio_write(tp, 0x06, 0x3723); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xface); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69fa); - rtl8168_mdio_write(tp, 0x06, 0xd401); - rtl8168_mdio_write(tp, 0x06, 0x55b4); - rtl8168_mdio_write(tp, 0x06, 0xfebf); - rtl8168_mdio_write(tp, 0x06, 0x85a7); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf6ac); - rtl8168_mdio_write(tp, 0x06, 0x280b); - rtl8168_mdio_write(tp, 0x06, 0xbf85); - rtl8168_mdio_write(tp, 0x06, 0xa402); - rtl8168_mdio_write(tp, 0x06, 0x36f6); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x49ae); - rtl8168_mdio_write(tp, 0x06, 0x64bf); - rtl8168_mdio_write(tp, 0x06, 0x85a4); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf6ac); - rtl8168_mdio_write(tp, 0x06, 0x285b); - rtl8168_mdio_write(tp, 0x06, 0xd000); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x60ac); - rtl8168_mdio_write(tp, 0x06, 0x2105); - rtl8168_mdio_write(tp, 0x06, 0xac22); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x4ebf); - rtl8168_mdio_write(tp, 0x06, 0xe0c4); - rtl8168_mdio_write(tp, 0x06, 0xbe86); - rtl8168_mdio_write(tp, 0x06, 0x14d2); - rtl8168_mdio_write(tp, 0x06, 0x04d8); - rtl8168_mdio_write(tp, 0x06, 0x19d9); - rtl8168_mdio_write(tp, 0x06, 0x1907); - rtl8168_mdio_write(tp, 0x06, 0xdc19); - rtl8168_mdio_write(tp, 0x06, 0xdd19); - rtl8168_mdio_write(tp, 0x06, 0x0789); - rtl8168_mdio_write(tp, 0x06, 0x89ef); - rtl8168_mdio_write(tp, 0x06, 0x645e); - rtl8168_mdio_write(tp, 0x06, 0x07ff); - rtl8168_mdio_write(tp, 0x06, 0x0d65); - rtl8168_mdio_write(tp, 0x06, 0x5cf8); - rtl8168_mdio_write(tp, 0x06, 0x001e); - rtl8168_mdio_write(tp, 0x06, 0x46dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0x19b2); - rtl8168_mdio_write(tp, 0x06, 0xe2d4); - rtl8168_mdio_write(tp, 0x06, 0x0001); - rtl8168_mdio_write(tp, 0x06, 0xbf85); - rtl8168_mdio_write(tp, 0x06, 0xa402); - rtl8168_mdio_write(tp, 0x06, 0x3723); - rtl8168_mdio_write(tp, 0x06, 0xae1d); - rtl8168_mdio_write(tp, 0x06, 0xbee0); - rtl8168_mdio_write(tp, 0x06, 0xc4bf); - rtl8168_mdio_write(tp, 0x06, 0x8614); - rtl8168_mdio_write(tp, 0x06, 0xd204); - rtl8168_mdio_write(tp, 0x06, 0xd819); - rtl8168_mdio_write(tp, 0x06, 0xd919); - rtl8168_mdio_write(tp, 0x06, 0x07dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0x1907); - rtl8168_mdio_write(tp, 0x06, 0xb2f4); - rtl8168_mdio_write(tp, 0x06, 0xd400); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x85a4); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23fe); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfec6); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc05); - rtl8168_mdio_write(tp, 0x06, 0xf9e2); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0xeb5a); - rtl8168_mdio_write(tp, 0x06, 0x070c); - rtl8168_mdio_write(tp, 0x06, 0x031e); - rtl8168_mdio_write(tp, 0x06, 0x20e6); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe7e0); - rtl8168_mdio_write(tp, 0x06, 0xebe0); - rtl8168_mdio_write(tp, 0x06, 0xe0fc); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xfdfd); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac26); - rtl8168_mdio_write(tp, 0x06, 0x1ae0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x14e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xac20); - rtl8168_mdio_write(tp, 0x06, 0x0ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xac23); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xac24); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0x1ab5); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x1c04); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x1d04); - rtl8168_mdio_write(tp, 0x06, 0xe2e0); - rtl8168_mdio_write(tp, 0x06, 0x7ce3); - rtl8168_mdio_write(tp, 0x06, 0xe07d); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x38e1); - rtl8168_mdio_write(tp, 0x06, 0xe039); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x1bad); - rtl8168_mdio_write(tp, 0x06, 0x390d); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf21); - rtl8168_mdio_write(tp, 0x06, 0xd502); - rtl8168_mdio_write(tp, 0x06, 0x3723); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xd8ae); - rtl8168_mdio_write(tp, 0x06, 0x0bac); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0x1802); - rtl8168_mdio_write(tp, 0x06, 0x8360); - rtl8168_mdio_write(tp, 0x06, 0x021a); - rtl8168_mdio_write(tp, 0x06, 0xc6fd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2605); - rtl8168_mdio_write(tp, 0x06, 0x0222); - rtl8168_mdio_write(tp, 0x06, 0xa4f7); - rtl8168_mdio_write(tp, 0x06, 0x28e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xad21); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x23a9); - rtl8168_mdio_write(tp, 0x06, 0xf729); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2005); - rtl8168_mdio_write(tp, 0x06, 0x0214); - rtl8168_mdio_write(tp, 0x06, 0xabf7); - rtl8168_mdio_write(tp, 0x06, 0x2ae0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad23); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x12e7); - rtl8168_mdio_write(tp, 0x06, 0xf72b); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2405); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0xbcf7); - rtl8168_mdio_write(tp, 0x06, 0x2ce5); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x21e5); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2109); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xf4ac); - rtl8168_mdio_write(tp, 0x06, 0x2003); - rtl8168_mdio_write(tp, 0x06, 0x0223); - rtl8168_mdio_write(tp, 0x06, 0x98e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x09e0); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x13fb); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2309); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xf4ac); - rtl8168_mdio_write(tp, 0x06, 0x2203); - rtl8168_mdio_write(tp, 0x06, 0x0212); - rtl8168_mdio_write(tp, 0x06, 0xfae0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x09e0); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xac23); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x83c1); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2608); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0xd2ad); - rtl8168_mdio_write(tp, 0x06, 0x2502); - rtl8168_mdio_write(tp, 0x06, 0xf628); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x210a); - rtl8168_mdio_write(tp, 0x06, 0xe084); - rtl8168_mdio_write(tp, 0x06, 0x0af6); - rtl8168_mdio_write(tp, 0x06, 0x27a0); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0xf629); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2008); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xe8ad); - rtl8168_mdio_write(tp, 0x06, 0x2102); - rtl8168_mdio_write(tp, 0x06, 0xf62a); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2308); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x20a0); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0xf62b); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2408); - rtl8168_mdio_write(tp, 0x06, 0xe086); - rtl8168_mdio_write(tp, 0x06, 0x02a0); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0xf62c); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xf4a1); - rtl8168_mdio_write(tp, 0x06, 0x0008); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf21); - rtl8168_mdio_write(tp, 0x06, 0xd502); - rtl8168_mdio_write(tp, 0x06, 0x3723); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x0200); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x241e); - rtl8168_mdio_write(tp, 0x06, 0xe086); - rtl8168_mdio_write(tp, 0x06, 0x02a0); - rtl8168_mdio_write(tp, 0x06, 0x0005); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0xe8ae); - rtl8168_mdio_write(tp, 0x06, 0xf5a0); - rtl8168_mdio_write(tp, 0x06, 0x0105); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0xf8ae); - rtl8168_mdio_write(tp, 0x06, 0x0ba0); - rtl8168_mdio_write(tp, 0x06, 0x0205); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0x14ae); - rtl8168_mdio_write(tp, 0x06, 0x03a0); - rtl8168_mdio_write(tp, 0x06, 0x0300); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0x2bee); - rtl8168_mdio_write(tp, 0x06, 0x8602); - rtl8168_mdio_write(tp, 0x06, 0x01ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8ee); - rtl8168_mdio_write(tp, 0x06, 0x8609); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x8461); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xae10); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8608); - rtl8168_mdio_write(tp, 0x06, 0xe186); - rtl8168_mdio_write(tp, 0x06, 0x091f); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x0611); - rtl8168_mdio_write(tp, 0x06, 0xe586); - rtl8168_mdio_write(tp, 0x06, 0x09ae); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x8602); - rtl8168_mdio_write(tp, 0x06, 0x01fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfbbf); - rtl8168_mdio_write(tp, 0x06, 0x8604); - rtl8168_mdio_write(tp, 0x06, 0xef79); - rtl8168_mdio_write(tp, 0x06, 0xd200); - rtl8168_mdio_write(tp, 0x06, 0xd400); - rtl8168_mdio_write(tp, 0x06, 0x221e); - rtl8168_mdio_write(tp, 0x06, 0x02bf); - rtl8168_mdio_write(tp, 0x06, 0x2fec); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23bf); - rtl8168_mdio_write(tp, 0x06, 0x13f2); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf60d); - rtl8168_mdio_write(tp, 0x06, 0x4559); - rtl8168_mdio_write(tp, 0x06, 0x1fef); - rtl8168_mdio_write(tp, 0x06, 0x97dd); - rtl8168_mdio_write(tp, 0x06, 0xd308); - rtl8168_mdio_write(tp, 0x06, 0x1a93); - rtl8168_mdio_write(tp, 0x06, 0xdd12); - rtl8168_mdio_write(tp, 0x06, 0x17a2); - rtl8168_mdio_write(tp, 0x06, 0x04de); - rtl8168_mdio_write(tp, 0x06, 0xffef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfbee); - rtl8168_mdio_write(tp, 0x06, 0x8602); - rtl8168_mdio_write(tp, 0x06, 0x03d5); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x06, 0xbf86); - rtl8168_mdio_write(tp, 0x06, 0x04ef); - rtl8168_mdio_write(tp, 0x06, 0x79ef); - rtl8168_mdio_write(tp, 0x06, 0x45bf); - rtl8168_mdio_write(tp, 0x06, 0x2fec); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23bf); - rtl8168_mdio_write(tp, 0x06, 0x13f2); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf6ad); - rtl8168_mdio_write(tp, 0x06, 0x2702); - rtl8168_mdio_write(tp, 0x06, 0x78ff); - rtl8168_mdio_write(tp, 0x06, 0xe186); - rtl8168_mdio_write(tp, 0x06, 0x0a1b); - rtl8168_mdio_write(tp, 0x06, 0x01aa); - rtl8168_mdio_write(tp, 0x06, 0x2eef); - rtl8168_mdio_write(tp, 0x06, 0x97d9); - rtl8168_mdio_write(tp, 0x06, 0x7900); - rtl8168_mdio_write(tp, 0x06, 0x9e2b); - rtl8168_mdio_write(tp, 0x06, 0x81dd); - rtl8168_mdio_write(tp, 0x06, 0xbf85); - rtl8168_mdio_write(tp, 0x06, 0xad02); - rtl8168_mdio_write(tp, 0x06, 0x3723); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xef02); - rtl8168_mdio_write(tp, 0x06, 0x100c); - rtl8168_mdio_write(tp, 0x06, 0x11b0); - rtl8168_mdio_write(tp, 0x06, 0xfc0d); - rtl8168_mdio_write(tp, 0x06, 0x11bf); - rtl8168_mdio_write(tp, 0x06, 0x85aa); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x85aa); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x23ee); - rtl8168_mdio_write(tp, 0x06, 0x8602); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x0413); - rtl8168_mdio_write(tp, 0x06, 0xa38b); - rtl8168_mdio_write(tp, 0x06, 0xb4d3); - rtl8168_mdio_write(tp, 0x06, 0x8012); - rtl8168_mdio_write(tp, 0x06, 0x17a2); - rtl8168_mdio_write(tp, 0x06, 0x04ad); - rtl8168_mdio_write(tp, 0x06, 0xffef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x48e0); - rtl8168_mdio_write(tp, 0x06, 0x8a96); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0x977c); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x9e35); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x9600); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x9700); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xbee1); - rtl8168_mdio_write(tp, 0x06, 0x8abf); - rtl8168_mdio_write(tp, 0x06, 0xe286); - rtl8168_mdio_write(tp, 0x06, 0x10e3); - rtl8168_mdio_write(tp, 0x06, 0x8611); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0x1aad); - rtl8168_mdio_write(tp, 0x06, 0x2012); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x9603); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x97b7); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x1000); - rtl8168_mdio_write(tp, 0x06, 0xee86); - rtl8168_mdio_write(tp, 0x06, 0x1100); - rtl8168_mdio_write(tp, 0x06, 0xae11); - rtl8168_mdio_write(tp, 0x06, 0x15e6); - rtl8168_mdio_write(tp, 0x06, 0x8610); - rtl8168_mdio_write(tp, 0x06, 0xe786); - rtl8168_mdio_write(tp, 0x06, 0x11ae); - rtl8168_mdio_write(tp, 0x06, 0x08ee); - rtl8168_mdio_write(tp, 0x06, 0x8610); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8611); - rtl8168_mdio_write(tp, 0x06, 0x00fd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe001); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x32e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf720); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40bf); - rtl8168_mdio_write(tp, 0x06, 0x31f5); - rtl8168_mdio_write(tp, 0x06, 0x0236); - rtl8168_mdio_write(tp, 0x06, 0xf6ad); - rtl8168_mdio_write(tp, 0x06, 0x2821); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x20e1); - rtl8168_mdio_write(tp, 0x06, 0xe021); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x18e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40ee); - rtl8168_mdio_write(tp, 0x06, 0x8b3b); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0x8a8a); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0x8be4); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0x01ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x80ad); - rtl8168_mdio_write(tp, 0x06, 0x2722); - rtl8168_mdio_write(tp, 0x06, 0xbf44); - rtl8168_mdio_write(tp, 0x06, 0xfc02); - rtl8168_mdio_write(tp, 0x06, 0x36f6); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x441f); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x15e5); - rtl8168_mdio_write(tp, 0x06, 0x8b44); - rtl8168_mdio_write(tp, 0x06, 0xad29); - rtl8168_mdio_write(tp, 0x06, 0x07ac); - rtl8168_mdio_write(tp, 0x06, 0x2804); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xae02); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf85); - rtl8168_mdio_write(tp, 0x06, 0xb002); - rtl8168_mdio_write(tp, 0x06, 0x3723); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x0400); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0x77e1); - rtl8168_mdio_write(tp, 0x06, 0x40dd); - rtl8168_mdio_write(tp, 0x06, 0xe022); - rtl8168_mdio_write(tp, 0x06, 0x32e1); - rtl8168_mdio_write(tp, 0x06, 0x5074); - rtl8168_mdio_write(tp, 0x06, 0xe144); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0xdaff); - rtl8168_mdio_write(tp, 0x06, 0xe0c0); - rtl8168_mdio_write(tp, 0x06, 0x52e0); - rtl8168_mdio_write(tp, 0x06, 0xeed9); - rtl8168_mdio_write(tp, 0x06, 0xe04c); - rtl8168_mdio_write(tp, 0x06, 0xbbe0); - rtl8168_mdio_write(tp, 0x06, 0x2a00); - rtl8168_mdio_write(tp, 0x05, 0xe142); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x05, 0xe140); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0042); - rtl8168_mdio_write(tp, 0x18, 0x2300); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - if (tp->RequiredSecLanDonglePatch) { - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~BIT_2; - rtl8168_mdio_write(tp, 0x17, gphy_val); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); -} - -static void -rtl8168_set_phy_mcu_8168f_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val,i; - - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x1800); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val &= ~(BIT_12); - rtl8168_mdio_write(tp,0x15, gphy_val); - rtl8168_mdio_write(tp,0x00, 0x4800); - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x002f); - for (i = 0; i < 1000; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1c); - if (gphy_val & 0x0080) - break; - } - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x1800); - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x0023); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x18); - if (!(gphy_val & 0x0001)) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x0194); - rtl8168_mdio_write(tp, 0x19, 0x407D); - rtl8168_mdio_write(tp, 0x15, 0x0098); - rtl8168_mdio_write(tp, 0x19, 0x7c0b); - rtl8168_mdio_write(tp, 0x15, 0x0099); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00eb); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00f8); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00fe); - rtl8168_mdio_write(tp, 0x19, 0x6f0f); - rtl8168_mdio_write(tp, 0x15, 0x00db); - rtl8168_mdio_write(tp, 0x19, 0x6f09); - rtl8168_mdio_write(tp, 0x15, 0x00dc); - rtl8168_mdio_write(tp, 0x19, 0xaefd); - rtl8168_mdio_write(tp, 0x15, 0x00dd); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00de); - rtl8168_mdio_write(tp, 0x19, 0xc60b); - rtl8168_mdio_write(tp, 0x15, 0x00df); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00e0); - rtl8168_mdio_write(tp, 0x19, 0x30e1); - rtl8168_mdio_write(tp, 0x15, 0x020c); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x020e); - rtl8168_mdio_write(tp, 0x19, 0x9813); - rtl8168_mdio_write(tp, 0x15, 0x020f); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0210); - rtl8168_mdio_write(tp, 0x19, 0x930f); - rtl8168_mdio_write(tp, 0x15, 0x0211); - rtl8168_mdio_write(tp, 0x19, 0x9206); - rtl8168_mdio_write(tp, 0x15, 0x0212); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0213); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0214); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0215); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0216); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0217); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0218); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0219); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x021a); - rtl8168_mdio_write(tp, 0x19, 0x5540); - rtl8168_mdio_write(tp, 0x15, 0x021b); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x021c); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x021d); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x021e); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x021f); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0220); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0221); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x0222); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0223); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x0224); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0225); - rtl8168_mdio_write(tp, 0x19, 0x3231); - rtl8168_mdio_write(tp, 0x15, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x0118); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x2502); - rtl8168_mdio_write(tp, 0x06, 0x8090); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x4202); - rtl8168_mdio_write(tp, 0x06, 0x015c); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0xad02); - rtl8168_mdio_write(tp, 0x06, 0x80ca); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xd484); - rtl8168_mdio_write(tp, 0x06, 0x3ce4); - rtl8168_mdio_write(tp, 0x06, 0x8b92); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x93ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac8); - rtl8168_mdio_write(tp, 0x06, 0x03ee); - rtl8168_mdio_write(tp, 0x06, 0x8aca); - rtl8168_mdio_write(tp, 0x06, 0x60ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac0); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac1); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8abe); - rtl8168_mdio_write(tp, 0x06, 0x07ee); - rtl8168_mdio_write(tp, 0x06, 0x8abf); - rtl8168_mdio_write(tp, 0x06, 0x73ee); - rtl8168_mdio_write(tp, 0x06, 0x8a95); - rtl8168_mdio_write(tp, 0x06, 0x02bf); - rtl8168_mdio_write(tp, 0x06, 0x8b88); - rtl8168_mdio_write(tp, 0x06, 0xec00); - rtl8168_mdio_write(tp, 0x06, 0x19a9); - rtl8168_mdio_write(tp, 0x06, 0x8b90); - rtl8168_mdio_write(tp, 0x06, 0xf9ee); - rtl8168_mdio_write(tp, 0x06, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xfed1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x85a4); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7dd1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x85a7); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7d04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8a); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x14ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8a); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x204b); - rtl8168_mdio_write(tp, 0x06, 0xe0e4); - rtl8168_mdio_write(tp, 0x06, 0x26e1); - rtl8168_mdio_write(tp, 0x06, 0xe427); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x2623); - rtl8168_mdio_write(tp, 0x06, 0xe5e4); - rtl8168_mdio_write(tp, 0x06, 0x27fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8dad); - rtl8168_mdio_write(tp, 0x06, 0x2014); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8d00); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0x5a78); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x0902); - rtl8168_mdio_write(tp, 0x06, 0x05e8); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x4f02); - rtl8168_mdio_write(tp, 0x06, 0x326c); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x1df6); - rtl8168_mdio_write(tp, 0x06, 0x20e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x0902); - rtl8168_mdio_write(tp, 0x06, 0x2ab0); - rtl8168_mdio_write(tp, 0x06, 0x0285); - rtl8168_mdio_write(tp, 0x06, 0x1602); - rtl8168_mdio_write(tp, 0x06, 0x03ba); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0xe502); - rtl8168_mdio_write(tp, 0x06, 0x2df1); - rtl8168_mdio_write(tp, 0x06, 0x0283); - rtl8168_mdio_write(tp, 0x06, 0x8302); - rtl8168_mdio_write(tp, 0x06, 0x0475); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x210b); - rtl8168_mdio_write(tp, 0x06, 0xf621); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x83f8); - rtl8168_mdio_write(tp, 0x06, 0x021c); - rtl8168_mdio_write(tp, 0x06, 0x99e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x22e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0235); - rtl8168_mdio_write(tp, 0x06, 0x63e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad23); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x23e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0231); - rtl8168_mdio_write(tp, 0x06, 0x57e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x24e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2505); - rtl8168_mdio_write(tp, 0x06, 0xf625); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x26e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x022d); - rtl8168_mdio_write(tp, 0x06, 0x1ce0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x27e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x80fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac26); - rtl8168_mdio_write(tp, 0x06, 0x1ae0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x14e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xac20); - rtl8168_mdio_write(tp, 0x06, 0x0ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xac23); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xac24); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0x1ac2); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x1c04); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x1d04); - rtl8168_mdio_write(tp, 0x06, 0xe2e0); - rtl8168_mdio_write(tp, 0x06, 0x7ce3); - rtl8168_mdio_write(tp, 0x06, 0xe07d); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x38e1); - rtl8168_mdio_write(tp, 0x06, 0xe039); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x1bad); - rtl8168_mdio_write(tp, 0x06, 0x390d); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf22); - rtl8168_mdio_write(tp, 0x06, 0x7a02); - rtl8168_mdio_write(tp, 0x06, 0x387d); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xacae); - rtl8168_mdio_write(tp, 0x06, 0x0bac); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xe902); - rtl8168_mdio_write(tp, 0x06, 0x822e); - rtl8168_mdio_write(tp, 0x06, 0x021a); - rtl8168_mdio_write(tp, 0x06, 0xd3fd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2602); - rtl8168_mdio_write(tp, 0x06, 0xf728); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2105); - rtl8168_mdio_write(tp, 0x06, 0x0222); - rtl8168_mdio_write(tp, 0x06, 0x8ef7); - rtl8168_mdio_write(tp, 0x06, 0x29e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x14b8); - rtl8168_mdio_write(tp, 0x06, 0xf72a); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2305); - rtl8168_mdio_write(tp, 0x06, 0x0212); - rtl8168_mdio_write(tp, 0x06, 0xf4f7); - rtl8168_mdio_write(tp, 0x06, 0x2be0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0x8284); - rtl8168_mdio_write(tp, 0x06, 0xf72c); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xf4fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2600); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2109); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xf4ac); - rtl8168_mdio_write(tp, 0x06, 0x2003); - rtl8168_mdio_write(tp, 0x06, 0x0222); - rtl8168_mdio_write(tp, 0x06, 0x7de0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x09e0); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x1408); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2309); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xf4ac); - rtl8168_mdio_write(tp, 0x06, 0x2203); - rtl8168_mdio_write(tp, 0x06, 0x0213); - rtl8168_mdio_write(tp, 0x06, 0x07e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x09e0); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xac23); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0x8289); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e1); - rtl8168_mdio_write(tp, 0x06, 0x8af4); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x2602); - rtl8168_mdio_write(tp, 0x06, 0xf628); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ad); - rtl8168_mdio_write(tp, 0x06, 0x210a); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0xecf6); - rtl8168_mdio_write(tp, 0x06, 0x27a0); - rtl8168_mdio_write(tp, 0x06, 0x0502); - rtl8168_mdio_write(tp, 0x06, 0xf629); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2008); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xe8ad); - rtl8168_mdio_write(tp, 0x06, 0x2102); - rtl8168_mdio_write(tp, 0x06, 0xf62a); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ad); - rtl8168_mdio_write(tp, 0x06, 0x2308); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x20a0); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0xf62b); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x2408); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xc2a0); - rtl8168_mdio_write(tp, 0x06, 0x0302); - rtl8168_mdio_write(tp, 0x06, 0xf62c); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xf4a1); - rtl8168_mdio_write(tp, 0x06, 0x0008); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf22); - rtl8168_mdio_write(tp, 0x06, 0x7a02); - rtl8168_mdio_write(tp, 0x06, 0x387d); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xc200); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ad); - rtl8168_mdio_write(tp, 0x06, 0x241e); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xc2a0); - rtl8168_mdio_write(tp, 0x06, 0x0005); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xb0ae); - rtl8168_mdio_write(tp, 0x06, 0xf5a0); - rtl8168_mdio_write(tp, 0x06, 0x0105); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xc0ae); - rtl8168_mdio_write(tp, 0x06, 0x0ba0); - rtl8168_mdio_write(tp, 0x06, 0x0205); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xcaae); - rtl8168_mdio_write(tp, 0x06, 0x03a0); - rtl8168_mdio_write(tp, 0x06, 0x0300); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xe1ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac2); - rtl8168_mdio_write(tp, 0x06, 0x01ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac9); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x8317); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8ac8); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xc91f); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x0611); - rtl8168_mdio_write(tp, 0x06, 0xe58a); - rtl8168_mdio_write(tp, 0x06, 0xc9ae); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac2); - rtl8168_mdio_write(tp, 0x06, 0x01fc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfbbf); - rtl8168_mdio_write(tp, 0x06, 0x8ac4); - rtl8168_mdio_write(tp, 0x06, 0xef79); - rtl8168_mdio_write(tp, 0x06, 0xd200); - rtl8168_mdio_write(tp, 0x06, 0xd400); - rtl8168_mdio_write(tp, 0x06, 0x221e); - rtl8168_mdio_write(tp, 0x06, 0x02bf); - rtl8168_mdio_write(tp, 0x06, 0x3024); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7dbf); - rtl8168_mdio_write(tp, 0x06, 0x13ff); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x500d); - rtl8168_mdio_write(tp, 0x06, 0x4559); - rtl8168_mdio_write(tp, 0x06, 0x1fef); - rtl8168_mdio_write(tp, 0x06, 0x97dd); - rtl8168_mdio_write(tp, 0x06, 0xd308); - rtl8168_mdio_write(tp, 0x06, 0x1a93); - rtl8168_mdio_write(tp, 0x06, 0xdd12); - rtl8168_mdio_write(tp, 0x06, 0x17a2); - rtl8168_mdio_write(tp, 0x06, 0x04de); - rtl8168_mdio_write(tp, 0x06, 0xffef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xfbee); - rtl8168_mdio_write(tp, 0x06, 0x8ac2); - rtl8168_mdio_write(tp, 0x06, 0x03d5); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x06, 0xbf8a); - rtl8168_mdio_write(tp, 0x06, 0xc4ef); - rtl8168_mdio_write(tp, 0x06, 0x79ef); - rtl8168_mdio_write(tp, 0x06, 0x45bf); - rtl8168_mdio_write(tp, 0x06, 0x3024); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7dbf); - rtl8168_mdio_write(tp, 0x06, 0x13ff); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x50ad); - rtl8168_mdio_write(tp, 0x06, 0x2702); - rtl8168_mdio_write(tp, 0x06, 0x78ff); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0xca1b); - rtl8168_mdio_write(tp, 0x06, 0x01aa); - rtl8168_mdio_write(tp, 0x06, 0x2eef); - rtl8168_mdio_write(tp, 0x06, 0x97d9); - rtl8168_mdio_write(tp, 0x06, 0x7900); - rtl8168_mdio_write(tp, 0x06, 0x9e2b); - rtl8168_mdio_write(tp, 0x06, 0x81dd); - rtl8168_mdio_write(tp, 0x06, 0xbf85); - rtl8168_mdio_write(tp, 0x06, 0xad02); - rtl8168_mdio_write(tp, 0x06, 0x387d); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xef02); - rtl8168_mdio_write(tp, 0x06, 0x100c); - rtl8168_mdio_write(tp, 0x06, 0x11b0); - rtl8168_mdio_write(tp, 0x06, 0xfc0d); - rtl8168_mdio_write(tp, 0x06, 0x11bf); - rtl8168_mdio_write(tp, 0x06, 0x85aa); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7dd1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x85aa); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7dee); - rtl8168_mdio_write(tp, 0x06, 0x8ac2); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x0413); - rtl8168_mdio_write(tp, 0x06, 0xa38b); - rtl8168_mdio_write(tp, 0x06, 0xb4d3); - rtl8168_mdio_write(tp, 0x06, 0x8012); - rtl8168_mdio_write(tp, 0x06, 0x17a2); - rtl8168_mdio_write(tp, 0x06, 0x04ad); - rtl8168_mdio_write(tp, 0x06, 0xffef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x48e0); - rtl8168_mdio_write(tp, 0x06, 0x8a96); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0x977c); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x9e35); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x9600); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x9700); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0xbee1); - rtl8168_mdio_write(tp, 0x06, 0x8abf); - rtl8168_mdio_write(tp, 0x06, 0xe28a); - rtl8168_mdio_write(tp, 0x06, 0xc0e3); - rtl8168_mdio_write(tp, 0x06, 0x8ac1); - rtl8168_mdio_write(tp, 0x06, 0x0237); - rtl8168_mdio_write(tp, 0x06, 0x74ad); - rtl8168_mdio_write(tp, 0x06, 0x2012); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x9603); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0x97b7); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xc000); - rtl8168_mdio_write(tp, 0x06, 0xee8a); - rtl8168_mdio_write(tp, 0x06, 0xc100); - rtl8168_mdio_write(tp, 0x06, 0xae11); - rtl8168_mdio_write(tp, 0x06, 0x15e6); - rtl8168_mdio_write(tp, 0x06, 0x8ac0); - rtl8168_mdio_write(tp, 0x06, 0xe78a); - rtl8168_mdio_write(tp, 0x06, 0xc1ae); - rtl8168_mdio_write(tp, 0x06, 0x08ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac0); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8ac1); - rtl8168_mdio_write(tp, 0x06, 0x00fd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xae20); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe001); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x32e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf720); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40bf); - rtl8168_mdio_write(tp, 0x06, 0x3230); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x50ad); - rtl8168_mdio_write(tp, 0x06, 0x2821); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x20e1); - rtl8168_mdio_write(tp, 0x06, 0xe021); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x18e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40ee); - rtl8168_mdio_write(tp, 0x06, 0x8b3b); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0x8a8a); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0x8be4); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0x01ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xface); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69fa); - rtl8168_mdio_write(tp, 0x06, 0xd401); - rtl8168_mdio_write(tp, 0x06, 0x55b4); - rtl8168_mdio_write(tp, 0x06, 0xfebf); - rtl8168_mdio_write(tp, 0x06, 0x1c1e); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x50ac); - rtl8168_mdio_write(tp, 0x06, 0x280b); - rtl8168_mdio_write(tp, 0x06, 0xbf1c); - rtl8168_mdio_write(tp, 0x06, 0x1b02); - rtl8168_mdio_write(tp, 0x06, 0x3850); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x49ae); - rtl8168_mdio_write(tp, 0x06, 0x64bf); - rtl8168_mdio_write(tp, 0x06, 0x1c1b); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x50ac); - rtl8168_mdio_write(tp, 0x06, 0x285b); - rtl8168_mdio_write(tp, 0x06, 0xd000); - rtl8168_mdio_write(tp, 0x06, 0x0284); - rtl8168_mdio_write(tp, 0x06, 0xcaac); - rtl8168_mdio_write(tp, 0x06, 0x2105); - rtl8168_mdio_write(tp, 0x06, 0xac22); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x4ebf); - rtl8168_mdio_write(tp, 0x06, 0xe0c4); - rtl8168_mdio_write(tp, 0x06, 0xbe85); - rtl8168_mdio_write(tp, 0x06, 0xf6d2); - rtl8168_mdio_write(tp, 0x06, 0x04d8); - rtl8168_mdio_write(tp, 0x06, 0x19d9); - rtl8168_mdio_write(tp, 0x06, 0x1907); - rtl8168_mdio_write(tp, 0x06, 0xdc19); - rtl8168_mdio_write(tp, 0x06, 0xdd19); - rtl8168_mdio_write(tp, 0x06, 0x0789); - rtl8168_mdio_write(tp, 0x06, 0x89ef); - rtl8168_mdio_write(tp, 0x06, 0x645e); - rtl8168_mdio_write(tp, 0x06, 0x07ff); - rtl8168_mdio_write(tp, 0x06, 0x0d65); - rtl8168_mdio_write(tp, 0x06, 0x5cf8); - rtl8168_mdio_write(tp, 0x06, 0x001e); - rtl8168_mdio_write(tp, 0x06, 0x46dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0x19b2); - rtl8168_mdio_write(tp, 0x06, 0xe2d4); - rtl8168_mdio_write(tp, 0x06, 0x0001); - rtl8168_mdio_write(tp, 0x06, 0xbf1c); - rtl8168_mdio_write(tp, 0x06, 0x1b02); - rtl8168_mdio_write(tp, 0x06, 0x387d); - rtl8168_mdio_write(tp, 0x06, 0xae1d); - rtl8168_mdio_write(tp, 0x06, 0xbee0); - rtl8168_mdio_write(tp, 0x06, 0xc4bf); - rtl8168_mdio_write(tp, 0x06, 0x85f6); - rtl8168_mdio_write(tp, 0x06, 0xd204); - rtl8168_mdio_write(tp, 0x06, 0xd819); - rtl8168_mdio_write(tp, 0x06, 0xd919); - rtl8168_mdio_write(tp, 0x06, 0x07dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0x1907); - rtl8168_mdio_write(tp, 0x06, 0xb2f4); - rtl8168_mdio_write(tp, 0x06, 0xd400); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x1c1b); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7dfe); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfec6); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc05); - rtl8168_mdio_write(tp, 0x06, 0xf9e2); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0xeb5a); - rtl8168_mdio_write(tp, 0x06, 0x070c); - rtl8168_mdio_write(tp, 0x06, 0x031e); - rtl8168_mdio_write(tp, 0x06, 0x20e6); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe7e0); - rtl8168_mdio_write(tp, 0x06, 0xebe0); - rtl8168_mdio_write(tp, 0x06, 0xe0fc); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xfdfd); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0x8b80); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x22bf); - rtl8168_mdio_write(tp, 0x06, 0x4616); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x50e0); - rtl8168_mdio_write(tp, 0x06, 0x8b44); - rtl8168_mdio_write(tp, 0x06, 0x1f01); - rtl8168_mdio_write(tp, 0x06, 0x9e15); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x44ad); - rtl8168_mdio_write(tp, 0x06, 0x2907); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x04d1); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0x02d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x85b0); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7def); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x30e0); - rtl8168_mdio_write(tp, 0x06, 0xe036); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x37e1); - rtl8168_mdio_write(tp, 0x06, 0x8b3f); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e23); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x3fac); - rtl8168_mdio_write(tp, 0x06, 0x200b); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x0dac); - rtl8168_mdio_write(tp, 0x06, 0x250f); - rtl8168_mdio_write(tp, 0x06, 0xac27); - rtl8168_mdio_write(tp, 0x06, 0x11ae); - rtl8168_mdio_write(tp, 0x06, 0x1202); - rtl8168_mdio_write(tp, 0x06, 0x2c47); - rtl8168_mdio_write(tp, 0x06, 0xae0d); - rtl8168_mdio_write(tp, 0x06, 0x0285); - rtl8168_mdio_write(tp, 0x06, 0x4fae); - rtl8168_mdio_write(tp, 0x06, 0x0802); - rtl8168_mdio_write(tp, 0x06, 0x2c69); - rtl8168_mdio_write(tp, 0x06, 0xae03); - rtl8168_mdio_write(tp, 0x06, 0x022c); - rtl8168_mdio_write(tp, 0x06, 0x7cfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x6902); - rtl8168_mdio_write(tp, 0x06, 0x856c); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x14e1); - rtl8168_mdio_write(tp, 0x06, 0xe015); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x08d1); - rtl8168_mdio_write(tp, 0x06, 0x1ebf); - rtl8168_mdio_write(tp, 0x06, 0x2cd9); - rtl8168_mdio_write(tp, 0x06, 0x0238); - rtl8168_mdio_write(tp, 0x06, 0x7def); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x2fd0); - rtl8168_mdio_write(tp, 0x06, 0x0b02); - rtl8168_mdio_write(tp, 0x06, 0x3682); - rtl8168_mdio_write(tp, 0x06, 0x5882); - rtl8168_mdio_write(tp, 0x06, 0x7882); - rtl8168_mdio_write(tp, 0x06, 0x9f24); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x32e1); - rtl8168_mdio_write(tp, 0x06, 0x8b33); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e1a); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x8b32); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x28e1); - rtl8168_mdio_write(tp, 0x06, 0xe029); - rtl8168_mdio_write(tp, 0x06, 0xf72c); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x28e5); - rtl8168_mdio_write(tp, 0x06, 0xe029); - rtl8168_mdio_write(tp, 0x06, 0xf62c); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x28e5); - rtl8168_mdio_write(tp, 0x06, 0xe029); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0x4077); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0x52e0); - rtl8168_mdio_write(tp, 0x06, 0xeed9); - rtl8168_mdio_write(tp, 0x06, 0xe04c); - rtl8168_mdio_write(tp, 0x06, 0xbbe0); - rtl8168_mdio_write(tp, 0x06, 0x2a00); - rtl8168_mdio_write(tp, 0x05, 0xe142); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp,0x06, gphy_val); - rtl8168_mdio_write(tp, 0x05, 0xe140); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp,0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp,0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val |= BIT_1; - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~BIT_2; - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x09, 0xA20F); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0003); - rtl8168_mdio_write(tp, 0x01, 0x328A); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); -} - -static void -rtl8168_set_phy_mcu_8168f_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val,i; - - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x1800); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val &= ~(BIT_12); - rtl8168_mdio_write(tp,0x15, gphy_val); - rtl8168_mdio_write(tp,0x00, 0x4800); - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x002f); - for (i = 0; i < 1000; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1c); - if (gphy_val & 0x0080) - break; - } - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x1800); - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x0023); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x18); - if (!(gphy_val & 0x0001)) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x0098); - rtl8168_mdio_write(tp, 0x19, 0x7c0b); - rtl8168_mdio_write(tp, 0x15, 0x0099); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00eb); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00f8); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00fe); - rtl8168_mdio_write(tp, 0x19, 0x6f0f); - rtl8168_mdio_write(tp, 0x15, 0x00db); - rtl8168_mdio_write(tp, 0x19, 0x6f09); - rtl8168_mdio_write(tp, 0x15, 0x00dc); - rtl8168_mdio_write(tp, 0x19, 0xaefd); - rtl8168_mdio_write(tp, 0x15, 0x00dd); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00de); - rtl8168_mdio_write(tp, 0x19, 0xc60b); - rtl8168_mdio_write(tp, 0x15, 0x00df); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00e0); - rtl8168_mdio_write(tp, 0x19, 0x30e1); - rtl8168_mdio_write(tp, 0x15, 0x020c); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x020e); - rtl8168_mdio_write(tp, 0x19, 0x9813); - rtl8168_mdio_write(tp, 0x15, 0x020f); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0210); - rtl8168_mdio_write(tp, 0x19, 0x930f); - rtl8168_mdio_write(tp, 0x15, 0x0211); - rtl8168_mdio_write(tp, 0x19, 0x9206); - rtl8168_mdio_write(tp, 0x15, 0x0212); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0213); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0214); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0215); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0216); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0217); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0218); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0219); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x021a); - rtl8168_mdio_write(tp, 0x19, 0x5540); - rtl8168_mdio_write(tp, 0x15, 0x021b); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x021c); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x021d); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x021e); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x021f); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0220); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0221); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x0222); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0223); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x0224); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0225); - rtl8168_mdio_write(tp, 0x19, 0x3231); - rtl8168_mdio_write(tp, 0x15, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x011b); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x2802); - rtl8168_mdio_write(tp, 0x06, 0x0135); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x4502); - rtl8168_mdio_write(tp, 0x06, 0x015f); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x6b02); - rtl8168_mdio_write(tp, 0x06, 0x80e5); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xbf8b); - rtl8168_mdio_write(tp, 0x06, 0x88ec); - rtl8168_mdio_write(tp, 0x06, 0x0019); - rtl8168_mdio_write(tp, 0x06, 0xa98b); - rtl8168_mdio_write(tp, 0x06, 0x90f9); - rtl8168_mdio_write(tp, 0x06, 0xeeff); - rtl8168_mdio_write(tp, 0x06, 0xf600); - rtl8168_mdio_write(tp, 0x06, 0xeeff); - rtl8168_mdio_write(tp, 0x06, 0xf7fe); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf81); - rtl8168_mdio_write(tp, 0x06, 0x9802); - rtl8168_mdio_write(tp, 0x06, 0x39f3); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf81); - rtl8168_mdio_write(tp, 0x06, 0x9b02); - rtl8168_mdio_write(tp, 0x06, 0x39f3); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8dad); - rtl8168_mdio_write(tp, 0x06, 0x2014); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8d00); - rtl8168_mdio_write(tp, 0x06, 0xe08a); - rtl8168_mdio_write(tp, 0x06, 0x5a78); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x0902); - rtl8168_mdio_write(tp, 0x06, 0x05fc); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x8802); - rtl8168_mdio_write(tp, 0x06, 0x32dd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ac); - rtl8168_mdio_write(tp, 0x06, 0x261a); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x81ac); - rtl8168_mdio_write(tp, 0x06, 0x2114); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ac); - rtl8168_mdio_write(tp, 0x06, 0x200e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x85ac); - rtl8168_mdio_write(tp, 0x06, 0x2308); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x87ac); - rtl8168_mdio_write(tp, 0x06, 0x2402); - rtl8168_mdio_write(tp, 0x06, 0xae38); - rtl8168_mdio_write(tp, 0x06, 0x021a); - rtl8168_mdio_write(tp, 0x06, 0xd6ee); - rtl8168_mdio_write(tp, 0x06, 0xe41c); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0xe41d); - rtl8168_mdio_write(tp, 0x06, 0x04e2); - rtl8168_mdio_write(tp, 0x06, 0xe07c); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0x7de0); - rtl8168_mdio_write(tp, 0x06, 0xe038); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x39ad); - rtl8168_mdio_write(tp, 0x06, 0x2e1b); - rtl8168_mdio_write(tp, 0x06, 0xad39); - rtl8168_mdio_write(tp, 0x06, 0x0dd1); - rtl8168_mdio_write(tp, 0x06, 0x01bf); - rtl8168_mdio_write(tp, 0x06, 0x22c8); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xf302); - rtl8168_mdio_write(tp, 0x06, 0x21f0); - rtl8168_mdio_write(tp, 0x06, 0xae0b); - rtl8168_mdio_write(tp, 0x06, 0xac38); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x0602); - rtl8168_mdio_write(tp, 0x06, 0x222d); - rtl8168_mdio_write(tp, 0x06, 0x0222); - rtl8168_mdio_write(tp, 0x06, 0x7202); - rtl8168_mdio_write(tp, 0x06, 0x1ae7); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x201a); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x2afe); - rtl8168_mdio_write(tp, 0x06, 0x022c); - rtl8168_mdio_write(tp, 0x06, 0x5c02); - rtl8168_mdio_write(tp, 0x06, 0x03c5); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x6702); - rtl8168_mdio_write(tp, 0x06, 0x2e4f); - rtl8168_mdio_write(tp, 0x06, 0x0204); - rtl8168_mdio_write(tp, 0x06, 0x8902); - rtl8168_mdio_write(tp, 0x06, 0x2f7a); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x210b); - rtl8168_mdio_write(tp, 0x06, 0xf621); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x0445); - rtl8168_mdio_write(tp, 0x06, 0x021c); - rtl8168_mdio_write(tp, 0x06, 0xb8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad22); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x22e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0235); - rtl8168_mdio_write(tp, 0x06, 0xd4e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad23); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x23e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0231); - rtl8168_mdio_write(tp, 0x06, 0xc8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad24); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x24e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2505); - rtl8168_mdio_write(tp, 0x06, 0xf625); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x08f6); - rtl8168_mdio_write(tp, 0x06, 0x26e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x022d); - rtl8168_mdio_write(tp, 0x06, 0x6ae0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x27e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0x8bfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0x8b80); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x22bf); - rtl8168_mdio_write(tp, 0x06, 0x479a); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xc6e0); - rtl8168_mdio_write(tp, 0x06, 0x8b44); - rtl8168_mdio_write(tp, 0x06, 0x1f01); - rtl8168_mdio_write(tp, 0x06, 0x9e15); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x44ad); - rtl8168_mdio_write(tp, 0x06, 0x2907); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x04d1); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0x02d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x819e); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xf3ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0x4077); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xbbe0); - rtl8168_mdio_write(tp, 0x06, 0x2a00); - rtl8168_mdio_write(tp, 0x05, 0xe142); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x05, 0xe140); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp,0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val |= BIT_1; - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~BIT_2; - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); -} - -static void -rtl8168_set_phy_mcu_8411_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val,i; - - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x1800); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val &= ~(BIT_12); - rtl8168_mdio_write(tp,0x15, gphy_val); - rtl8168_mdio_write(tp,0x00, 0x4800); - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x002f); - for (i = 0; i < 1000; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x1c); - if (gphy_val & 0x0080) - break; - } - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x1800); - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x0023); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x18); - if (!(gphy_val & 0x0001)) - break; - } - rtl8168_mdio_write(tp,0x1f, 0x0005); - rtl8168_mdio_write(tp,0x05, 0xfff6); - rtl8168_mdio_write(tp,0x06, 0x0080); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0307); - rtl8168_mdio_write(tp, 0x15, 0x0098); - rtl8168_mdio_write(tp, 0x19, 0x7c0b); - rtl8168_mdio_write(tp, 0x15, 0x0099); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00eb); - rtl8168_mdio_write(tp, 0x19, 0x6c0b); - rtl8168_mdio_write(tp, 0x15, 0x00f8); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00fe); - rtl8168_mdio_write(tp, 0x19, 0x6f0f); - rtl8168_mdio_write(tp, 0x15, 0x00db); - rtl8168_mdio_write(tp, 0x19, 0x6f09); - rtl8168_mdio_write(tp, 0x15, 0x00dc); - rtl8168_mdio_write(tp, 0x19, 0xaefd); - rtl8168_mdio_write(tp, 0x15, 0x00dd); - rtl8168_mdio_write(tp, 0x19, 0x6f0b); - rtl8168_mdio_write(tp, 0x15, 0x00de); - rtl8168_mdio_write(tp, 0x19, 0xc60b); - rtl8168_mdio_write(tp, 0x15, 0x00df); - rtl8168_mdio_write(tp, 0x19, 0x00fa); - rtl8168_mdio_write(tp, 0x15, 0x00e0); - rtl8168_mdio_write(tp, 0x19, 0x30e1); - rtl8168_mdio_write(tp, 0x15, 0x020c); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x020e); - rtl8168_mdio_write(tp, 0x19, 0x9813); - rtl8168_mdio_write(tp, 0x15, 0x020f); - rtl8168_mdio_write(tp, 0x19, 0x7801); - rtl8168_mdio_write(tp, 0x15, 0x0210); - rtl8168_mdio_write(tp, 0x19, 0x930f); - rtl8168_mdio_write(tp, 0x15, 0x0211); - rtl8168_mdio_write(tp, 0x19, 0x9206); - rtl8168_mdio_write(tp, 0x15, 0x0212); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0213); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0214); - rtl8168_mdio_write(tp, 0x19, 0x588f); - rtl8168_mdio_write(tp, 0x15, 0x0215); - rtl8168_mdio_write(tp, 0x19, 0x5520); - rtl8168_mdio_write(tp, 0x15, 0x0216); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0217); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0218); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0219); - rtl8168_mdio_write(tp, 0x19, 0x588d); - rtl8168_mdio_write(tp, 0x15, 0x021a); - rtl8168_mdio_write(tp, 0x19, 0x5540); - rtl8168_mdio_write(tp, 0x15, 0x021b); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x021c); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x021d); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x021e); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x021f); - rtl8168_mdio_write(tp, 0x19, 0x4002); - rtl8168_mdio_write(tp, 0x15, 0x0220); - rtl8168_mdio_write(tp, 0x19, 0x3224); - rtl8168_mdio_write(tp, 0x15, 0x0221); - rtl8168_mdio_write(tp, 0x19, 0x9e03); - rtl8168_mdio_write(tp, 0x15, 0x0222); - rtl8168_mdio_write(tp, 0x19, 0x7c40); - rtl8168_mdio_write(tp, 0x15, 0x0223); - rtl8168_mdio_write(tp, 0x19, 0x6840); - rtl8168_mdio_write(tp, 0x15, 0x0224); - rtl8168_mdio_write(tp, 0x19, 0x7800); - rtl8168_mdio_write(tp, 0x15, 0x0225); - rtl8168_mdio_write(tp, 0x19, 0x3231); - rtl8168_mdio_write(tp, 0x15, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x0306); - rtl8168_mdio_write(tp, 0x16, 0x0300); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x48f7); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xfff7); - rtl8168_mdio_write(tp, 0x06, 0xa080); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0xf602); - rtl8168_mdio_write(tp, 0x06, 0x011e); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x2b02); - rtl8168_mdio_write(tp, 0x06, 0x8077); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x4802); - rtl8168_mdio_write(tp, 0x06, 0x0162); - rtl8168_mdio_write(tp, 0x06, 0x0280); - rtl8168_mdio_write(tp, 0x06, 0x9402); - rtl8168_mdio_write(tp, 0x06, 0x810e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x88e1); - rtl8168_mdio_write(tp, 0x06, 0x8b89); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8a1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8b); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8c1e); - rtl8168_mdio_write(tp, 0x06, 0x01e1); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x1e01); - rtl8168_mdio_write(tp, 0x06, 0xe18b); - rtl8168_mdio_write(tp, 0x06, 0x8e1e); - rtl8168_mdio_write(tp, 0x06, 0x01a0); - rtl8168_mdio_write(tp, 0x06, 0x00c7); - rtl8168_mdio_write(tp, 0x06, 0xaebb); - rtl8168_mdio_write(tp, 0x06, 0xd481); - rtl8168_mdio_write(tp, 0x06, 0xd4e4); - rtl8168_mdio_write(tp, 0x06, 0x8b92); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x9302); - rtl8168_mdio_write(tp, 0x06, 0x2e5a); - rtl8168_mdio_write(tp, 0x06, 0xbf8b); - rtl8168_mdio_write(tp, 0x06, 0x88ec); - rtl8168_mdio_write(tp, 0x06, 0x0019); - rtl8168_mdio_write(tp, 0x06, 0xa98b); - rtl8168_mdio_write(tp, 0x06, 0x90f9); - rtl8168_mdio_write(tp, 0x06, 0xeeff); - rtl8168_mdio_write(tp, 0x06, 0xf600); - rtl8168_mdio_write(tp, 0x06, 0xeeff); - rtl8168_mdio_write(tp, 0x06, 0xf7fc); - rtl8168_mdio_write(tp, 0x06, 0xd100); - rtl8168_mdio_write(tp, 0x06, 0xbf83); - rtl8168_mdio_write(tp, 0x06, 0x3c02); - rtl8168_mdio_write(tp, 0x06, 0x3a21); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf83); - rtl8168_mdio_write(tp, 0x06, 0x3f02); - rtl8168_mdio_write(tp, 0x06, 0x3a21); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8aad); - rtl8168_mdio_write(tp, 0x06, 0x2014); - rtl8168_mdio_write(tp, 0x06, 0xee8b); - rtl8168_mdio_write(tp, 0x06, 0x8a00); - rtl8168_mdio_write(tp, 0x06, 0x0220); - rtl8168_mdio_write(tp, 0x06, 0x8be0); - rtl8168_mdio_write(tp, 0x06, 0xe426); - rtl8168_mdio_write(tp, 0x06, 0xe1e4); - rtl8168_mdio_write(tp, 0x06, 0x27ee); - rtl8168_mdio_write(tp, 0x06, 0xe426); - rtl8168_mdio_write(tp, 0x06, 0x23e5); - rtl8168_mdio_write(tp, 0x06, 0xe427); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x14ee); - rtl8168_mdio_write(tp, 0x06, 0x8b8d); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0x8a5a); - rtl8168_mdio_write(tp, 0x06, 0x7803); - rtl8168_mdio_write(tp, 0x06, 0x9e09); - rtl8168_mdio_write(tp, 0x06, 0x0206); - rtl8168_mdio_write(tp, 0x06, 0x2802); - rtl8168_mdio_write(tp, 0x06, 0x80b1); - rtl8168_mdio_write(tp, 0x06, 0x0232); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xf9e0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac26); - rtl8168_mdio_write(tp, 0x06, 0x1ae0); - rtl8168_mdio_write(tp, 0x06, 0x8b81); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x14e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xac20); - rtl8168_mdio_write(tp, 0x06, 0x0ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xac23); - rtl8168_mdio_write(tp, 0x06, 0x08e0); - rtl8168_mdio_write(tp, 0x06, 0x8b87); - rtl8168_mdio_write(tp, 0x06, 0xac24); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0x1b02); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x1c04); - rtl8168_mdio_write(tp, 0x06, 0xeee4); - rtl8168_mdio_write(tp, 0x06, 0x1d04); - rtl8168_mdio_write(tp, 0x06, 0xe2e0); - rtl8168_mdio_write(tp, 0x06, 0x7ce3); - rtl8168_mdio_write(tp, 0x06, 0xe07d); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x38e1); - rtl8168_mdio_write(tp, 0x06, 0xe039); - rtl8168_mdio_write(tp, 0x06, 0xad2e); - rtl8168_mdio_write(tp, 0x06, 0x1bad); - rtl8168_mdio_write(tp, 0x06, 0x390d); - rtl8168_mdio_write(tp, 0x06, 0xd101); - rtl8168_mdio_write(tp, 0x06, 0xbf22); - rtl8168_mdio_write(tp, 0x06, 0xe802); - rtl8168_mdio_write(tp, 0x06, 0x3a21); - rtl8168_mdio_write(tp, 0x06, 0x0222); - rtl8168_mdio_write(tp, 0x06, 0x10ae); - rtl8168_mdio_write(tp, 0x06, 0x0bac); - rtl8168_mdio_write(tp, 0x06, 0x3802); - rtl8168_mdio_write(tp, 0x06, 0xae06); - rtl8168_mdio_write(tp, 0x06, 0x0222); - rtl8168_mdio_write(tp, 0x06, 0x4d02); - rtl8168_mdio_write(tp, 0x06, 0x2292); - rtl8168_mdio_write(tp, 0x06, 0x021b); - rtl8168_mdio_write(tp, 0x06, 0x13fd); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x1af6); - rtl8168_mdio_write(tp, 0x06, 0x20e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x022b); - rtl8168_mdio_write(tp, 0x06, 0x1e02); - rtl8168_mdio_write(tp, 0x06, 0x82ae); - rtl8168_mdio_write(tp, 0x06, 0x0203); - rtl8168_mdio_write(tp, 0x06, 0xc002); - rtl8168_mdio_write(tp, 0x06, 0x827d); - rtl8168_mdio_write(tp, 0x06, 0x022e); - rtl8168_mdio_write(tp, 0x06, 0x6f02); - rtl8168_mdio_write(tp, 0x06, 0x047b); - rtl8168_mdio_write(tp, 0x06, 0x022f); - rtl8168_mdio_write(tp, 0x06, 0x9ae0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad21); - rtl8168_mdio_write(tp, 0x06, 0x0bf6); - rtl8168_mdio_write(tp, 0x06, 0x21e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0x9002); - rtl8168_mdio_write(tp, 0x06, 0x1cd9); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2208); - rtl8168_mdio_write(tp, 0x06, 0xf622); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x35f4); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2308); - rtl8168_mdio_write(tp, 0x06, 0xf623); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x31e8); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2405); - rtl8168_mdio_write(tp, 0x06, 0xf624); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8ee0); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xad25); - rtl8168_mdio_write(tp, 0x06, 0x05f6); - rtl8168_mdio_write(tp, 0x06, 0x25e4); - rtl8168_mdio_write(tp, 0x06, 0x8b8e); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2608); - rtl8168_mdio_write(tp, 0x06, 0xf626); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x2d8a); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x8ead); - rtl8168_mdio_write(tp, 0x06, 0x2705); - rtl8168_mdio_write(tp, 0x06, 0xf627); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x8e02); - rtl8168_mdio_write(tp, 0x06, 0x0386); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xef69); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0xe001); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x32e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf720); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40bf); - rtl8168_mdio_write(tp, 0x06, 0x32c1); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xf4ad); - rtl8168_mdio_write(tp, 0x06, 0x2821); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x20e1); - rtl8168_mdio_write(tp, 0x06, 0xe021); - rtl8168_mdio_write(tp, 0x06, 0xad20); - rtl8168_mdio_write(tp, 0x06, 0x18e0); - rtl8168_mdio_write(tp, 0x06, 0x8b40); - rtl8168_mdio_write(tp, 0x06, 0xf620); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x40ee); - rtl8168_mdio_write(tp, 0x06, 0x8b3b); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0x8a8a); - rtl8168_mdio_write(tp, 0x06, 0xe18a); - rtl8168_mdio_write(tp, 0x06, 0x8be4); - rtl8168_mdio_write(tp, 0x06, 0xe000); - rtl8168_mdio_write(tp, 0x06, 0xe5e0); - rtl8168_mdio_write(tp, 0x06, 0x01ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xface); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69fa); - rtl8168_mdio_write(tp, 0x06, 0xd401); - rtl8168_mdio_write(tp, 0x06, 0x55b4); - rtl8168_mdio_write(tp, 0x06, 0xfebf); - rtl8168_mdio_write(tp, 0x06, 0x1c5e); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xf4ac); - rtl8168_mdio_write(tp, 0x06, 0x280b); - rtl8168_mdio_write(tp, 0x06, 0xbf1c); - rtl8168_mdio_write(tp, 0x06, 0x5b02); - rtl8168_mdio_write(tp, 0x06, 0x39f4); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x49ae); - rtl8168_mdio_write(tp, 0x06, 0x64bf); - rtl8168_mdio_write(tp, 0x06, 0x1c5b); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xf4ac); - rtl8168_mdio_write(tp, 0x06, 0x285b); - rtl8168_mdio_write(tp, 0x06, 0xd000); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x62ac); - rtl8168_mdio_write(tp, 0x06, 0x2105); - rtl8168_mdio_write(tp, 0x06, 0xac22); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x4ebf); - rtl8168_mdio_write(tp, 0x06, 0xe0c4); - rtl8168_mdio_write(tp, 0x06, 0xbe85); - rtl8168_mdio_write(tp, 0x06, 0xecd2); - rtl8168_mdio_write(tp, 0x06, 0x04d8); - rtl8168_mdio_write(tp, 0x06, 0x19d9); - rtl8168_mdio_write(tp, 0x06, 0x1907); - rtl8168_mdio_write(tp, 0x06, 0xdc19); - rtl8168_mdio_write(tp, 0x06, 0xdd19); - rtl8168_mdio_write(tp, 0x06, 0x0789); - rtl8168_mdio_write(tp, 0x06, 0x89ef); - rtl8168_mdio_write(tp, 0x06, 0x645e); - rtl8168_mdio_write(tp, 0x06, 0x07ff); - rtl8168_mdio_write(tp, 0x06, 0x0d65); - rtl8168_mdio_write(tp, 0x06, 0x5cf8); - rtl8168_mdio_write(tp, 0x06, 0x001e); - rtl8168_mdio_write(tp, 0x06, 0x46dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0x19b2); - rtl8168_mdio_write(tp, 0x06, 0xe2d4); - rtl8168_mdio_write(tp, 0x06, 0x0001); - rtl8168_mdio_write(tp, 0x06, 0xbf1c); - rtl8168_mdio_write(tp, 0x06, 0x5b02); - rtl8168_mdio_write(tp, 0x06, 0x3a21); - rtl8168_mdio_write(tp, 0x06, 0xae1d); - rtl8168_mdio_write(tp, 0x06, 0xbee0); - rtl8168_mdio_write(tp, 0x06, 0xc4bf); - rtl8168_mdio_write(tp, 0x06, 0x85ec); - rtl8168_mdio_write(tp, 0x06, 0xd204); - rtl8168_mdio_write(tp, 0x06, 0xd819); - rtl8168_mdio_write(tp, 0x06, 0xd919); - rtl8168_mdio_write(tp, 0x06, 0x07dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0x1907); - rtl8168_mdio_write(tp, 0x06, 0xb2f4); - rtl8168_mdio_write(tp, 0x06, 0xd400); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x1c5b); - rtl8168_mdio_write(tp, 0x06, 0x023a); - rtl8168_mdio_write(tp, 0x06, 0x21fe); - rtl8168_mdio_write(tp, 0x06, 0xef96); - rtl8168_mdio_write(tp, 0x06, 0xfec6); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc05); - rtl8168_mdio_write(tp, 0x06, 0xf9e2); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe3e0); - rtl8168_mdio_write(tp, 0x06, 0xeb5a); - rtl8168_mdio_write(tp, 0x06, 0x070c); - rtl8168_mdio_write(tp, 0x06, 0x031e); - rtl8168_mdio_write(tp, 0x06, 0x20e6); - rtl8168_mdio_write(tp, 0x06, 0xe0ea); - rtl8168_mdio_write(tp, 0x06, 0xe7e0); - rtl8168_mdio_write(tp, 0x06, 0xebe0); - rtl8168_mdio_write(tp, 0x06, 0xe0fc); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0xfdfd); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x69e0); - rtl8168_mdio_write(tp, 0x06, 0x8b80); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x22bf); - rtl8168_mdio_write(tp, 0x06, 0x47ba); - rtl8168_mdio_write(tp, 0x06, 0x0239); - rtl8168_mdio_write(tp, 0x06, 0xf4e0); - rtl8168_mdio_write(tp, 0x06, 0x8b44); - rtl8168_mdio_write(tp, 0x06, 0x1f01); - rtl8168_mdio_write(tp, 0x06, 0x9e15); - rtl8168_mdio_write(tp, 0x06, 0xe58b); - rtl8168_mdio_write(tp, 0x06, 0x44ad); - rtl8168_mdio_write(tp, 0x06, 0x2907); - rtl8168_mdio_write(tp, 0x06, 0xac28); - rtl8168_mdio_write(tp, 0x06, 0x04d1); - rtl8168_mdio_write(tp, 0x06, 0x01ae); - rtl8168_mdio_write(tp, 0x06, 0x02d1); - rtl8168_mdio_write(tp, 0x06, 0x00bf); - rtl8168_mdio_write(tp, 0x06, 0x8342); - rtl8168_mdio_write(tp, 0x06, 0x023a); - rtl8168_mdio_write(tp, 0x06, 0x21ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x30e0); - rtl8168_mdio_write(tp, 0x06, 0xe036); - rtl8168_mdio_write(tp, 0x06, 0xe1e0); - rtl8168_mdio_write(tp, 0x06, 0x37e1); - rtl8168_mdio_write(tp, 0x06, 0x8b3f); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e23); - rtl8168_mdio_write(tp, 0x06, 0xe48b); - rtl8168_mdio_write(tp, 0x06, 0x3fac); - rtl8168_mdio_write(tp, 0x06, 0x200b); - rtl8168_mdio_write(tp, 0x06, 0xac21); - rtl8168_mdio_write(tp, 0x06, 0x0dac); - rtl8168_mdio_write(tp, 0x06, 0x250f); - rtl8168_mdio_write(tp, 0x06, 0xac27); - rtl8168_mdio_write(tp, 0x06, 0x11ae); - rtl8168_mdio_write(tp, 0x06, 0x1202); - rtl8168_mdio_write(tp, 0x06, 0x2cb5); - rtl8168_mdio_write(tp, 0x06, 0xae0d); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0xe7ae); - rtl8168_mdio_write(tp, 0x06, 0x0802); - rtl8168_mdio_write(tp, 0x06, 0x2cd7); - rtl8168_mdio_write(tp, 0x06, 0xae03); - rtl8168_mdio_write(tp, 0x06, 0x022c); - rtl8168_mdio_write(tp, 0x06, 0xeafc); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x6902); - rtl8168_mdio_write(tp, 0x06, 0x8304); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x14e1); - rtl8168_mdio_write(tp, 0x06, 0xe015); - rtl8168_mdio_write(tp, 0x06, 0xad26); - rtl8168_mdio_write(tp, 0x06, 0x08d1); - rtl8168_mdio_write(tp, 0x06, 0x1ebf); - rtl8168_mdio_write(tp, 0x06, 0x2d47); - rtl8168_mdio_write(tp, 0x06, 0x023a); - rtl8168_mdio_write(tp, 0x06, 0x21ef); - rtl8168_mdio_write(tp, 0x06, 0x96fe); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0x8b85); - rtl8168_mdio_write(tp, 0x06, 0xad27); - rtl8168_mdio_write(tp, 0x06, 0x2fd0); - rtl8168_mdio_write(tp, 0x06, 0x0b02); - rtl8168_mdio_write(tp, 0x06, 0x3826); - rtl8168_mdio_write(tp, 0x06, 0x5882); - rtl8168_mdio_write(tp, 0x06, 0x7882); - rtl8168_mdio_write(tp, 0x06, 0x9f24); - rtl8168_mdio_write(tp, 0x06, 0xe08b); - rtl8168_mdio_write(tp, 0x06, 0x32e1); - rtl8168_mdio_write(tp, 0x06, 0x8b33); - rtl8168_mdio_write(tp, 0x06, 0x1f10); - rtl8168_mdio_write(tp, 0x06, 0x9e1a); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x8b32); - rtl8168_mdio_write(tp, 0x06, 0xe0e0); - rtl8168_mdio_write(tp, 0x06, 0x28e1); - rtl8168_mdio_write(tp, 0x06, 0xe029); - rtl8168_mdio_write(tp, 0x06, 0xf72c); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x28e5); - rtl8168_mdio_write(tp, 0x06, 0xe029); - rtl8168_mdio_write(tp, 0x06, 0xf62c); - rtl8168_mdio_write(tp, 0x06, 0xe4e0); - rtl8168_mdio_write(tp, 0x06, 0x28e5); - rtl8168_mdio_write(tp, 0x06, 0xe029); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0x00e1); - rtl8168_mdio_write(tp, 0x06, 0x4077); - rtl8168_mdio_write(tp, 0x06, 0xe140); - rtl8168_mdio_write(tp, 0x06, 0xbbe0); - rtl8168_mdio_write(tp, 0x06, 0x2a00); - rtl8168_mdio_write(tp, 0x05, 0xe142); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp,0x06, gphy_val); - rtl8168_mdio_write(tp, 0x05, 0xe140); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp,0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp,0x1f, 0x0005); - for (i = 0; i < 200; i++) { - udelay(100); - gphy_val = rtl8168_mdio_read(tp, 0x00); - if (gphy_val & BIT_7) - break; - } - rtl8168_mdio_write(tp,0x1f, 0x0007); - rtl8168_mdio_write(tp,0x1e, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val |= BIT_1; - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~BIT_2; - rtl8168_mdio_write(tp,0x17, gphy_val); - rtl8168_mdio_write(tp,0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x09, 0xA20F); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0003); - rtl8168_mdio_write(tp, 0x01, 0x328A); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp,0x1f, 0x0000); - rtl8168_mdio_write(tp,0x00, 0x9200); -} - -static void -rtl8168_set_phy_mcu_8168g_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val; - - rtl8168_set_phy_mcu_patch_request(tp); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8146); - rtl8168_mdio_write(tp, 0x14, 0x2300); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0210); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0290); - rtl8168_mdio_write(tp, 0x13, 0xA012); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xA014); - rtl8168_mdio_write(tp, 0x14, 0x2c04); - rtl8168_mdio_write(tp, 0x14, 0x2c0c); - rtl8168_mdio_write(tp, 0x14, 0x2c6c); - rtl8168_mdio_write(tp, 0x14, 0x2d0d); - rtl8168_mdio_write(tp, 0x14, 0x31ce); - rtl8168_mdio_write(tp, 0x14, 0x506d); - rtl8168_mdio_write(tp, 0x14, 0xd708); - rtl8168_mdio_write(tp, 0x14, 0x3108); - rtl8168_mdio_write(tp, 0x14, 0x106d); - rtl8168_mdio_write(tp, 0x14, 0x1560); - rtl8168_mdio_write(tp, 0x14, 0x15a9); - rtl8168_mdio_write(tp, 0x14, 0x206e); - rtl8168_mdio_write(tp, 0x14, 0x175b); - rtl8168_mdio_write(tp, 0x14, 0x6062); - rtl8168_mdio_write(tp, 0x14, 0xd700); - rtl8168_mdio_write(tp, 0x14, 0x5fae); - rtl8168_mdio_write(tp, 0x14, 0xd708); - rtl8168_mdio_write(tp, 0x14, 0x3107); - rtl8168_mdio_write(tp, 0x14, 0x4c1e); - rtl8168_mdio_write(tp, 0x14, 0x4169); - rtl8168_mdio_write(tp, 0x14, 0x316a); - rtl8168_mdio_write(tp, 0x14, 0x0c19); - rtl8168_mdio_write(tp, 0x14, 0x31aa); - rtl8168_mdio_write(tp, 0x14, 0x0c19); - rtl8168_mdio_write(tp, 0x14, 0x2c1b); - rtl8168_mdio_write(tp, 0x14, 0x5e62); - rtl8168_mdio_write(tp, 0x14, 0x26b5); - rtl8168_mdio_write(tp, 0x14, 0x31ab); - rtl8168_mdio_write(tp, 0x14, 0x5c1e); - rtl8168_mdio_write(tp, 0x14, 0x2c0c); - rtl8168_mdio_write(tp, 0x14, 0xc040); - rtl8168_mdio_write(tp, 0x14, 0x8808); - rtl8168_mdio_write(tp, 0x14, 0xc520); - rtl8168_mdio_write(tp, 0x14, 0xc421); - rtl8168_mdio_write(tp, 0x14, 0xd05a); - rtl8168_mdio_write(tp, 0x14, 0xd19a); - rtl8168_mdio_write(tp, 0x14, 0xd709); - rtl8168_mdio_write(tp, 0x14, 0x608f); - rtl8168_mdio_write(tp, 0x14, 0xd06b); - rtl8168_mdio_write(tp, 0x14, 0xd18a); - rtl8168_mdio_write(tp, 0x14, 0x2c2c); - rtl8168_mdio_write(tp, 0x14, 0xd0be); - rtl8168_mdio_write(tp, 0x14, 0xd188); - rtl8168_mdio_write(tp, 0x14, 0x2c2c); - rtl8168_mdio_write(tp, 0x14, 0xd708); - rtl8168_mdio_write(tp, 0x14, 0x4072); - rtl8168_mdio_write(tp, 0x14, 0xc104); - rtl8168_mdio_write(tp, 0x14, 0x2c3e); - rtl8168_mdio_write(tp, 0x14, 0x4076); - rtl8168_mdio_write(tp, 0x14, 0xc110); - rtl8168_mdio_write(tp, 0x14, 0x2c3e); - rtl8168_mdio_write(tp, 0x14, 0x4071); - rtl8168_mdio_write(tp, 0x14, 0xc102); - rtl8168_mdio_write(tp, 0x14, 0x2c3e); - rtl8168_mdio_write(tp, 0x14, 0x4070); - rtl8168_mdio_write(tp, 0x14, 0xc101); - rtl8168_mdio_write(tp, 0x14, 0x2c3e); - rtl8168_mdio_write(tp, 0x14, 0x175b); - rtl8168_mdio_write(tp, 0x14, 0xd709); - rtl8168_mdio_write(tp, 0x14, 0x3390); - rtl8168_mdio_write(tp, 0x14, 0x5c39); - rtl8168_mdio_write(tp, 0x14, 0x2c4e); - rtl8168_mdio_write(tp, 0x14, 0x175b); - rtl8168_mdio_write(tp, 0x14, 0xd708); - rtl8168_mdio_write(tp, 0x14, 0x6193); - rtl8168_mdio_write(tp, 0x14, 0xd709); - rtl8168_mdio_write(tp, 0x14, 0x5f9d); - rtl8168_mdio_write(tp, 0x14, 0x408b); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x6042); - rtl8168_mdio_write(tp, 0x14, 0xb401); - rtl8168_mdio_write(tp, 0x14, 0x175b); - rtl8168_mdio_write(tp, 0x14, 0xd708); - rtl8168_mdio_write(tp, 0x14, 0x6073); - rtl8168_mdio_write(tp, 0x14, 0x5fbc); - rtl8168_mdio_write(tp, 0x14, 0x2c4d); - rtl8168_mdio_write(tp, 0x14, 0x26ed); - rtl8168_mdio_write(tp, 0x14, 0xb280); - rtl8168_mdio_write(tp, 0x14, 0xa841); - rtl8168_mdio_write(tp, 0x14, 0x9420); - rtl8168_mdio_write(tp, 0x14, 0x8710); - rtl8168_mdio_write(tp, 0x14, 0xd709); - rtl8168_mdio_write(tp, 0x14, 0x42ec); - rtl8168_mdio_write(tp, 0x14, 0x606d); - rtl8168_mdio_write(tp, 0x14, 0xd207); - rtl8168_mdio_write(tp, 0x14, 0x2c57); - rtl8168_mdio_write(tp, 0x14, 0xd203); - rtl8168_mdio_write(tp, 0x14, 0x33ff); - rtl8168_mdio_write(tp, 0x14, 0x563b); - rtl8168_mdio_write(tp, 0x14, 0x3275); - rtl8168_mdio_write(tp, 0x14, 0x7c5e); - rtl8168_mdio_write(tp, 0x14, 0xb240); - rtl8168_mdio_write(tp, 0x14, 0xb402); - rtl8168_mdio_write(tp, 0x14, 0x263b); - rtl8168_mdio_write(tp, 0x14, 0x6096); - rtl8168_mdio_write(tp, 0x14, 0xb240); - rtl8168_mdio_write(tp, 0x14, 0xb406); - rtl8168_mdio_write(tp, 0x14, 0x263b); - rtl8168_mdio_write(tp, 0x14, 0x31d7); - rtl8168_mdio_write(tp, 0x14, 0x7c67); - rtl8168_mdio_write(tp, 0x14, 0xb240); - rtl8168_mdio_write(tp, 0x14, 0xb40e); - rtl8168_mdio_write(tp, 0x14, 0x263b); - rtl8168_mdio_write(tp, 0x14, 0xb410); - rtl8168_mdio_write(tp, 0x14, 0x8802); - rtl8168_mdio_write(tp, 0x14, 0xb240); - rtl8168_mdio_write(tp, 0x14, 0x940e); - rtl8168_mdio_write(tp, 0x14, 0x263b); - rtl8168_mdio_write(tp, 0x14, 0xba04); - rtl8168_mdio_write(tp, 0x14, 0x1cd6); - rtl8168_mdio_write(tp, 0x14, 0xa902); - rtl8168_mdio_write(tp, 0x14, 0xd711); - rtl8168_mdio_write(tp, 0x14, 0x4045); - rtl8168_mdio_write(tp, 0x14, 0xa980); - rtl8168_mdio_write(tp, 0x14, 0x3003); - rtl8168_mdio_write(tp, 0x14, 0x59b1); - rtl8168_mdio_write(tp, 0x14, 0xa540); - rtl8168_mdio_write(tp, 0x14, 0xa601); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4043); - rtl8168_mdio_write(tp, 0x14, 0xa910); - rtl8168_mdio_write(tp, 0x14, 0xd711); - rtl8168_mdio_write(tp, 0x14, 0x60a0); - rtl8168_mdio_write(tp, 0x14, 0xca33); - rtl8168_mdio_write(tp, 0x14, 0xcb33); - rtl8168_mdio_write(tp, 0x14, 0xa941); - rtl8168_mdio_write(tp, 0x14, 0x2c82); - rtl8168_mdio_write(tp, 0x14, 0xcaff); - rtl8168_mdio_write(tp, 0x14, 0xcbff); - rtl8168_mdio_write(tp, 0x14, 0xa921); - rtl8168_mdio_write(tp, 0x14, 0xce02); - rtl8168_mdio_write(tp, 0x14, 0xe070); - rtl8168_mdio_write(tp, 0x14, 0x0f10); - rtl8168_mdio_write(tp, 0x14, 0xaf01); - rtl8168_mdio_write(tp, 0x14, 0x8f01); - rtl8168_mdio_write(tp, 0x14, 0x1766); - rtl8168_mdio_write(tp, 0x14, 0x8e02); - rtl8168_mdio_write(tp, 0x14, 0x1787); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x609c); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fa4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0x1ce9); - rtl8168_mdio_write(tp, 0x14, 0xce04); - rtl8168_mdio_write(tp, 0x14, 0xe070); - rtl8168_mdio_write(tp, 0x14, 0x0f20); - rtl8168_mdio_write(tp, 0x14, 0xaf01); - rtl8168_mdio_write(tp, 0x14, 0x8f01); - rtl8168_mdio_write(tp, 0x14, 0x1766); - rtl8168_mdio_write(tp, 0x14, 0x8e04); - rtl8168_mdio_write(tp, 0x14, 0x6044); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0xa520); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4043); - rtl8168_mdio_write(tp, 0x14, 0x2cc1); - rtl8168_mdio_write(tp, 0x14, 0xe00f); - rtl8168_mdio_write(tp, 0x14, 0x0501); - rtl8168_mdio_write(tp, 0x14, 0x1cef); - rtl8168_mdio_write(tp, 0x14, 0xb801); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x4060); - rtl8168_mdio_write(tp, 0x14, 0x7fc4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0x1cf5); - rtl8168_mdio_write(tp, 0x14, 0xe00f); - rtl8168_mdio_write(tp, 0x14, 0x0502); - rtl8168_mdio_write(tp, 0x14, 0x1cef); - rtl8168_mdio_write(tp, 0x14, 0xb802); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x4061); - rtl8168_mdio_write(tp, 0x14, 0x7fc4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0x1cf5); - rtl8168_mdio_write(tp, 0x14, 0xe00f); - rtl8168_mdio_write(tp, 0x14, 0x0504); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6099); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fa4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0xc17f); - rtl8168_mdio_write(tp, 0x14, 0xc200); - rtl8168_mdio_write(tp, 0x14, 0xc43f); - rtl8168_mdio_write(tp, 0x14, 0xcc03); - rtl8168_mdio_write(tp, 0x14, 0xa701); - rtl8168_mdio_write(tp, 0x14, 0xa510); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4018); - rtl8168_mdio_write(tp, 0x14, 0x9910); - rtl8168_mdio_write(tp, 0x14, 0x8510); - rtl8168_mdio_write(tp, 0x14, 0x2860); - rtl8168_mdio_write(tp, 0x14, 0xe00f); - rtl8168_mdio_write(tp, 0x14, 0x0504); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6099); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fa4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0xa608); - rtl8168_mdio_write(tp, 0x14, 0xc17d); - rtl8168_mdio_write(tp, 0x14, 0xc200); - rtl8168_mdio_write(tp, 0x14, 0xc43f); - rtl8168_mdio_write(tp, 0x14, 0xcc03); - rtl8168_mdio_write(tp, 0x14, 0xa701); - rtl8168_mdio_write(tp, 0x14, 0xa510); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4018); - rtl8168_mdio_write(tp, 0x14, 0x9910); - rtl8168_mdio_write(tp, 0x14, 0x8510); - rtl8168_mdio_write(tp, 0x14, 0x2926); - rtl8168_mdio_write(tp, 0x14, 0x1792); - rtl8168_mdio_write(tp, 0x14, 0x27db); - rtl8168_mdio_write(tp, 0x14, 0xc000); - rtl8168_mdio_write(tp, 0x14, 0xc100); - rtl8168_mdio_write(tp, 0x14, 0xc200); - rtl8168_mdio_write(tp, 0x14, 0xc300); - rtl8168_mdio_write(tp, 0x14, 0xc400); - rtl8168_mdio_write(tp, 0x14, 0xc500); - rtl8168_mdio_write(tp, 0x14, 0xc600); - rtl8168_mdio_write(tp, 0x14, 0xc7c1); - rtl8168_mdio_write(tp, 0x14, 0xc800); - rtl8168_mdio_write(tp, 0x14, 0xcc00); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xca0f); - rtl8168_mdio_write(tp, 0x14, 0xcbff); - rtl8168_mdio_write(tp, 0x14, 0xa901); - rtl8168_mdio_write(tp, 0x14, 0x8902); - rtl8168_mdio_write(tp, 0x14, 0xc900); - rtl8168_mdio_write(tp, 0x14, 0xca00); - rtl8168_mdio_write(tp, 0x14, 0xcb00); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xb804); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x6044); - rtl8168_mdio_write(tp, 0x14, 0x9804); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6099); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fa4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xa510); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6098); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fa4); - rtl8168_mdio_write(tp, 0x14, 0x2cd4); - rtl8168_mdio_write(tp, 0x14, 0x8510); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xd711); - rtl8168_mdio_write(tp, 0x14, 0x3003); - rtl8168_mdio_write(tp, 0x14, 0x1d01); - rtl8168_mdio_write(tp, 0x14, 0x2d0b); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x60be); - rtl8168_mdio_write(tp, 0x14, 0xe060); - rtl8168_mdio_write(tp, 0x14, 0x0920); - rtl8168_mdio_write(tp, 0x14, 0x1cd6); - rtl8168_mdio_write(tp, 0x14, 0x2c89); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x3063); - rtl8168_mdio_write(tp, 0x14, 0x1948); - rtl8168_mdio_write(tp, 0x14, 0x288a); - rtl8168_mdio_write(tp, 0x14, 0x1cd6); - rtl8168_mdio_write(tp, 0x14, 0x29bd); - rtl8168_mdio_write(tp, 0x14, 0xa802); - rtl8168_mdio_write(tp, 0x14, 0xa303); - rtl8168_mdio_write(tp, 0x14, 0x843f); - rtl8168_mdio_write(tp, 0x14, 0x81ff); - rtl8168_mdio_write(tp, 0x14, 0x8208); - rtl8168_mdio_write(tp, 0x14, 0xa201); - rtl8168_mdio_write(tp, 0x14, 0xc001); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x30a0); - rtl8168_mdio_write(tp, 0x14, 0x0d1c); - rtl8168_mdio_write(tp, 0x14, 0x30a0); - rtl8168_mdio_write(tp, 0x14, 0x3d13); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7f4c); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0xe003); - rtl8168_mdio_write(tp, 0x14, 0x0202); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6090); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fac); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0xa20c); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6091); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fac); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0x820e); - rtl8168_mdio_write(tp, 0x14, 0xa3e0); - rtl8168_mdio_write(tp, 0x14, 0xa520); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x609d); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fac); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0x8520); - rtl8168_mdio_write(tp, 0x14, 0x6703); - rtl8168_mdio_write(tp, 0x14, 0x2d34); - rtl8168_mdio_write(tp, 0x14, 0xa13e); - rtl8168_mdio_write(tp, 0x14, 0xc001); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0x6046); - rtl8168_mdio_write(tp, 0x14, 0x2d0d); - rtl8168_mdio_write(tp, 0x14, 0xa43f); - rtl8168_mdio_write(tp, 0x14, 0xa101); - rtl8168_mdio_write(tp, 0x14, 0xc020); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x3121); - rtl8168_mdio_write(tp, 0x14, 0x0d45); - rtl8168_mdio_write(tp, 0x14, 0x30c0); - rtl8168_mdio_write(tp, 0x14, 0x3d0d); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7f4c); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0xa540); - rtl8168_mdio_write(tp, 0x14, 0xc001); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4001); - rtl8168_mdio_write(tp, 0x14, 0xe00f); - rtl8168_mdio_write(tp, 0x14, 0x0501); - rtl8168_mdio_write(tp, 0x14, 0x1dac); - rtl8168_mdio_write(tp, 0x14, 0xc1c4); - rtl8168_mdio_write(tp, 0x14, 0xa268); - rtl8168_mdio_write(tp, 0x14, 0xa303); - rtl8168_mdio_write(tp, 0x14, 0x8420); - rtl8168_mdio_write(tp, 0x14, 0xe00f); - rtl8168_mdio_write(tp, 0x14, 0x0502); - rtl8168_mdio_write(tp, 0x14, 0x1dac); - rtl8168_mdio_write(tp, 0x14, 0xc002); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0x8208); - rtl8168_mdio_write(tp, 0x14, 0x8410); - rtl8168_mdio_write(tp, 0x14, 0xa121); - rtl8168_mdio_write(tp, 0x14, 0xc002); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0x8120); - rtl8168_mdio_write(tp, 0x14, 0x8180); - rtl8168_mdio_write(tp, 0x14, 0x1d97); - rtl8168_mdio_write(tp, 0x14, 0xa180); - rtl8168_mdio_write(tp, 0x14, 0xa13a); - rtl8168_mdio_write(tp, 0x14, 0x8240); - rtl8168_mdio_write(tp, 0x14, 0xa430); - rtl8168_mdio_write(tp, 0x14, 0xc010); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x30e1); - rtl8168_mdio_write(tp, 0x14, 0x0abc); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7f8c); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0xa480); - rtl8168_mdio_write(tp, 0x14, 0xa230); - rtl8168_mdio_write(tp, 0x14, 0xa303); - rtl8168_mdio_write(tp, 0x14, 0xc001); - rtl8168_mdio_write(tp, 0x14, 0xd70c); - rtl8168_mdio_write(tp, 0x14, 0x4124); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x6120); - rtl8168_mdio_write(tp, 0x14, 0xd711); - rtl8168_mdio_write(tp, 0x14, 0x3128); - rtl8168_mdio_write(tp, 0x14, 0x3d76); - rtl8168_mdio_write(tp, 0x14, 0x2d70); - rtl8168_mdio_write(tp, 0x14, 0xa801); - rtl8168_mdio_write(tp, 0x14, 0x2d6c); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0xe018); - rtl8168_mdio_write(tp, 0x14, 0x0208); - rtl8168_mdio_write(tp, 0x14, 0xa1f8); - rtl8168_mdio_write(tp, 0x14, 0x8480); - rtl8168_mdio_write(tp, 0x14, 0xc004); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0x6046); - rtl8168_mdio_write(tp, 0x14, 0x2d0d); - rtl8168_mdio_write(tp, 0x14, 0xa43f); - rtl8168_mdio_write(tp, 0x14, 0xa105); - rtl8168_mdio_write(tp, 0x14, 0x8228); - rtl8168_mdio_write(tp, 0x14, 0xc004); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0x81bc); - rtl8168_mdio_write(tp, 0x14, 0xa220); - rtl8168_mdio_write(tp, 0x14, 0x1d97); - rtl8168_mdio_write(tp, 0x14, 0x8220); - rtl8168_mdio_write(tp, 0x14, 0xa1bc); - rtl8168_mdio_write(tp, 0x14, 0xc040); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x30e1); - rtl8168_mdio_write(tp, 0x14, 0x0abc); - rtl8168_mdio_write(tp, 0x14, 0x30e1); - rtl8168_mdio_write(tp, 0x14, 0x3d0d); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7f4c); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0xa802); - rtl8168_mdio_write(tp, 0x14, 0xd70c); - rtl8168_mdio_write(tp, 0x14, 0x4244); - rtl8168_mdio_write(tp, 0x14, 0xa301); - rtl8168_mdio_write(tp, 0x14, 0xc004); - rtl8168_mdio_write(tp, 0x14, 0xd711); - rtl8168_mdio_write(tp, 0x14, 0x3128); - rtl8168_mdio_write(tp, 0x14, 0x3da5); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x5f80); - rtl8168_mdio_write(tp, 0x14, 0xd711); - rtl8168_mdio_write(tp, 0x14, 0x3109); - rtl8168_mdio_write(tp, 0x14, 0x3da7); - rtl8168_mdio_write(tp, 0x14, 0x2dab); - rtl8168_mdio_write(tp, 0x14, 0xa801); - rtl8168_mdio_write(tp, 0x14, 0x2d9a); - rtl8168_mdio_write(tp, 0x14, 0xa802); - rtl8168_mdio_write(tp, 0x14, 0xc004); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x4000); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x14, 0xa510); - rtl8168_mdio_write(tp, 0x14, 0xd710); - rtl8168_mdio_write(tp, 0x14, 0x609a); - rtl8168_mdio_write(tp, 0x14, 0xd71e); - rtl8168_mdio_write(tp, 0x14, 0x7fac); - rtl8168_mdio_write(tp, 0x14, 0x2ab6); - rtl8168_mdio_write(tp, 0x14, 0x8510); - rtl8168_mdio_write(tp, 0x14, 0x0800); - rtl8168_mdio_write(tp, 0x13, 0xA01A); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xA006); - rtl8168_mdio_write(tp, 0x14, 0x0ad6); - rtl8168_mdio_write(tp, 0x13, 0xA004); - rtl8168_mdio_write(tp, 0x14, 0x07f5); - rtl8168_mdio_write(tp, 0x13, 0xA002); - rtl8168_mdio_write(tp, 0x14, 0x06a9); - rtl8168_mdio_write(tp, 0x13, 0xA000); - rtl8168_mdio_write(tp, 0x14, 0xf069); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0210); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x83a0); - rtl8168_mdio_write(tp, 0x14, 0xaf83); - rtl8168_mdio_write(tp, 0x14, 0xacaf); - rtl8168_mdio_write(tp, 0x14, 0x83b8); - rtl8168_mdio_write(tp, 0x14, 0xaf83); - rtl8168_mdio_write(tp, 0x14, 0xcdaf); - rtl8168_mdio_write(tp, 0x14, 0x83d3); - rtl8168_mdio_write(tp, 0x14, 0x0204); - rtl8168_mdio_write(tp, 0x14, 0x9a02); - rtl8168_mdio_write(tp, 0x14, 0x09a9); - rtl8168_mdio_write(tp, 0x14, 0x0284); - rtl8168_mdio_write(tp, 0x14, 0x61af); - rtl8168_mdio_write(tp, 0x14, 0x02fc); - rtl8168_mdio_write(tp, 0x14, 0xad20); - rtl8168_mdio_write(tp, 0x14, 0x0302); - rtl8168_mdio_write(tp, 0x14, 0x867c); - rtl8168_mdio_write(tp, 0x14, 0xad21); - rtl8168_mdio_write(tp, 0x14, 0x0302); - rtl8168_mdio_write(tp, 0x14, 0x85c9); - rtl8168_mdio_write(tp, 0x14, 0xad22); - rtl8168_mdio_write(tp, 0x14, 0x0302); - rtl8168_mdio_write(tp, 0x14, 0x1bc0); - rtl8168_mdio_write(tp, 0x14, 0xaf17); - rtl8168_mdio_write(tp, 0x14, 0xe302); - rtl8168_mdio_write(tp, 0x14, 0x8703); - rtl8168_mdio_write(tp, 0x14, 0xaf18); - rtl8168_mdio_write(tp, 0x14, 0x6201); - rtl8168_mdio_write(tp, 0x14, 0x06e0); - rtl8168_mdio_write(tp, 0x14, 0x8148); - rtl8168_mdio_write(tp, 0x14, 0xaf3c); - rtl8168_mdio_write(tp, 0x14, 0x69f8); - rtl8168_mdio_write(tp, 0x14, 0xf9fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0x10f7); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0x131f); - rtl8168_mdio_write(tp, 0x14, 0xd104); - rtl8168_mdio_write(tp, 0x14, 0xbf87); - rtl8168_mdio_write(tp, 0x14, 0xf302); - rtl8168_mdio_write(tp, 0x14, 0x4259); - rtl8168_mdio_write(tp, 0x14, 0x0287); - rtl8168_mdio_write(tp, 0x14, 0x88bf); - rtl8168_mdio_write(tp, 0x14, 0x87cf); - rtl8168_mdio_write(tp, 0x14, 0xd7b8); - rtl8168_mdio_write(tp, 0x14, 0x22d0); - rtl8168_mdio_write(tp, 0x14, 0x0c02); - rtl8168_mdio_write(tp, 0x14, 0x4252); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xcda0); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xce8b); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xd1f5); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xd2a9); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xd30a); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xf010); - rtl8168_mdio_write(tp, 0x14, 0xee80); - rtl8168_mdio_write(tp, 0x14, 0xf38f); - rtl8168_mdio_write(tp, 0x14, 0xee81); - rtl8168_mdio_write(tp, 0x14, 0x011e); - rtl8168_mdio_write(tp, 0x14, 0xee81); - rtl8168_mdio_write(tp, 0x14, 0x0b4a); - rtl8168_mdio_write(tp, 0x14, 0xee81); - rtl8168_mdio_write(tp, 0x14, 0x0c7c); - rtl8168_mdio_write(tp, 0x14, 0xee81); - rtl8168_mdio_write(tp, 0x14, 0x127f); - rtl8168_mdio_write(tp, 0x14, 0xd100); - rtl8168_mdio_write(tp, 0x14, 0x0210); - rtl8168_mdio_write(tp, 0x14, 0xb5ee); - rtl8168_mdio_write(tp, 0x14, 0x8088); - rtl8168_mdio_write(tp, 0x14, 0xa4ee); - rtl8168_mdio_write(tp, 0x14, 0x8089); - rtl8168_mdio_write(tp, 0x14, 0x44ee); - rtl8168_mdio_write(tp, 0x14, 0x809a); - rtl8168_mdio_write(tp, 0x14, 0xa4ee); - rtl8168_mdio_write(tp, 0x14, 0x809b); - rtl8168_mdio_write(tp, 0x14, 0x44ee); - rtl8168_mdio_write(tp, 0x14, 0x809c); - rtl8168_mdio_write(tp, 0x14, 0xa7ee); - rtl8168_mdio_write(tp, 0x14, 0x80a5); - rtl8168_mdio_write(tp, 0x14, 0xa7d2); - rtl8168_mdio_write(tp, 0x14, 0x0002); - rtl8168_mdio_write(tp, 0x14, 0x0e66); - rtl8168_mdio_write(tp, 0x14, 0x0285); - rtl8168_mdio_write(tp, 0x14, 0xc0ee); - rtl8168_mdio_write(tp, 0x14, 0x87fc); - rtl8168_mdio_write(tp, 0x14, 0x00e0); - rtl8168_mdio_write(tp, 0x14, 0x8245); - rtl8168_mdio_write(tp, 0x14, 0xf622); - rtl8168_mdio_write(tp, 0x14, 0xe482); - rtl8168_mdio_write(tp, 0x14, 0x45ef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfdfc); - rtl8168_mdio_write(tp, 0x14, 0x0402); - rtl8168_mdio_write(tp, 0x14, 0x847a); - rtl8168_mdio_write(tp, 0x14, 0x0284); - rtl8168_mdio_write(tp, 0x14, 0xb302); - rtl8168_mdio_write(tp, 0x14, 0x0cab); - rtl8168_mdio_write(tp, 0x14, 0x020c); - rtl8168_mdio_write(tp, 0x14, 0xc402); - rtl8168_mdio_write(tp, 0x14, 0x0cef); - rtl8168_mdio_write(tp, 0x14, 0x020d); - rtl8168_mdio_write(tp, 0x14, 0x0802); - rtl8168_mdio_write(tp, 0x14, 0x0d33); - rtl8168_mdio_write(tp, 0x14, 0x020c); - rtl8168_mdio_write(tp, 0x14, 0x3d04); - rtl8168_mdio_write(tp, 0x14, 0xf8fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xe182); - rtl8168_mdio_write(tp, 0x14, 0x2fac); - rtl8168_mdio_write(tp, 0x14, 0x291a); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x24ac); - rtl8168_mdio_write(tp, 0x14, 0x2102); - rtl8168_mdio_write(tp, 0x14, 0xae22); - rtl8168_mdio_write(tp, 0x14, 0x0210); - rtl8168_mdio_write(tp, 0x14, 0x57f6); - rtl8168_mdio_write(tp, 0x14, 0x21e4); - rtl8168_mdio_write(tp, 0x14, 0x8224); - rtl8168_mdio_write(tp, 0x14, 0xd101); - rtl8168_mdio_write(tp, 0x14, 0xbf44); - rtl8168_mdio_write(tp, 0x14, 0xd202); - rtl8168_mdio_write(tp, 0x14, 0x4259); - rtl8168_mdio_write(tp, 0x14, 0xae10); - rtl8168_mdio_write(tp, 0x14, 0x0212); - rtl8168_mdio_write(tp, 0x14, 0x4cf6); - rtl8168_mdio_write(tp, 0x14, 0x29e5); - rtl8168_mdio_write(tp, 0x14, 0x822f); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x24f6); - rtl8168_mdio_write(tp, 0x14, 0x21e4); - rtl8168_mdio_write(tp, 0x14, 0x8224); - rtl8168_mdio_write(tp, 0x14, 0xef96); - rtl8168_mdio_write(tp, 0x14, 0xfefc); - rtl8168_mdio_write(tp, 0x14, 0x04f8); - rtl8168_mdio_write(tp, 0x14, 0xe182); - rtl8168_mdio_write(tp, 0x14, 0x2fac); - rtl8168_mdio_write(tp, 0x14, 0x2a18); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x24ac); - rtl8168_mdio_write(tp, 0x14, 0x2202); - rtl8168_mdio_write(tp, 0x14, 0xae26); - rtl8168_mdio_write(tp, 0x14, 0x0284); - rtl8168_mdio_write(tp, 0x14, 0xf802); - rtl8168_mdio_write(tp, 0x14, 0x8565); - rtl8168_mdio_write(tp, 0x14, 0xd101); - rtl8168_mdio_write(tp, 0x14, 0xbf44); - rtl8168_mdio_write(tp, 0x14, 0xd502); - rtl8168_mdio_write(tp, 0x14, 0x4259); - rtl8168_mdio_write(tp, 0x14, 0xae0e); - rtl8168_mdio_write(tp, 0x14, 0x0284); - rtl8168_mdio_write(tp, 0x14, 0xea02); - rtl8168_mdio_write(tp, 0x14, 0x85a9); - rtl8168_mdio_write(tp, 0x14, 0xe182); - rtl8168_mdio_write(tp, 0x14, 0x2ff6); - rtl8168_mdio_write(tp, 0x14, 0x2ae5); - rtl8168_mdio_write(tp, 0x14, 0x822f); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x24f6); - rtl8168_mdio_write(tp, 0x14, 0x22e4); - rtl8168_mdio_write(tp, 0x14, 0x8224); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xf9e2); - rtl8168_mdio_write(tp, 0x14, 0x8011); - rtl8168_mdio_write(tp, 0x14, 0xad31); - rtl8168_mdio_write(tp, 0x14, 0x05d2); - rtl8168_mdio_write(tp, 0x14, 0x0002); - rtl8168_mdio_write(tp, 0x14, 0x0e66); - rtl8168_mdio_write(tp, 0x14, 0xfd04); - rtl8168_mdio_write(tp, 0x14, 0xf8f9); - rtl8168_mdio_write(tp, 0x14, 0xfaef); - rtl8168_mdio_write(tp, 0x14, 0x69e0); - rtl8168_mdio_write(tp, 0x14, 0x8011); - rtl8168_mdio_write(tp, 0x14, 0xad21); - rtl8168_mdio_write(tp, 0x14, 0x5cbf); - rtl8168_mdio_write(tp, 0x14, 0x43be); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97ac); - rtl8168_mdio_write(tp, 0x14, 0x281b); - rtl8168_mdio_write(tp, 0x14, 0xbf43); - rtl8168_mdio_write(tp, 0x14, 0xc102); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0xac28); - rtl8168_mdio_write(tp, 0x14, 0x12bf); - rtl8168_mdio_write(tp, 0x14, 0x43c7); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97ac); - rtl8168_mdio_write(tp, 0x14, 0x2804); - rtl8168_mdio_write(tp, 0x14, 0xd300); - rtl8168_mdio_write(tp, 0x14, 0xae07); - rtl8168_mdio_write(tp, 0x14, 0xd306); - rtl8168_mdio_write(tp, 0x14, 0xaf85); - rtl8168_mdio_write(tp, 0x14, 0x56d3); - rtl8168_mdio_write(tp, 0x14, 0x03e0); - rtl8168_mdio_write(tp, 0x14, 0x8011); - rtl8168_mdio_write(tp, 0x14, 0xad26); - rtl8168_mdio_write(tp, 0x14, 0x25bf); - rtl8168_mdio_write(tp, 0x14, 0x4559); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97e2); - rtl8168_mdio_write(tp, 0x14, 0x8073); - rtl8168_mdio_write(tp, 0x14, 0x0d21); - rtl8168_mdio_write(tp, 0x14, 0xf637); - rtl8168_mdio_write(tp, 0x14, 0x0d11); - rtl8168_mdio_write(tp, 0x14, 0xf62f); - rtl8168_mdio_write(tp, 0x14, 0x1b21); - rtl8168_mdio_write(tp, 0x14, 0xaa02); - rtl8168_mdio_write(tp, 0x14, 0xae10); - rtl8168_mdio_write(tp, 0x14, 0xe280); - rtl8168_mdio_write(tp, 0x14, 0x740d); - rtl8168_mdio_write(tp, 0x14, 0x21f6); - rtl8168_mdio_write(tp, 0x14, 0x371b); - rtl8168_mdio_write(tp, 0x14, 0x21aa); - rtl8168_mdio_write(tp, 0x14, 0x0313); - rtl8168_mdio_write(tp, 0x14, 0xae02); - rtl8168_mdio_write(tp, 0x14, 0x2b02); - rtl8168_mdio_write(tp, 0x14, 0x020e); - rtl8168_mdio_write(tp, 0x14, 0x5102); - rtl8168_mdio_write(tp, 0x14, 0x0e66); - rtl8168_mdio_write(tp, 0x14, 0x020f); - rtl8168_mdio_write(tp, 0x14, 0xa3ef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfdfc); - rtl8168_mdio_write(tp, 0x14, 0x04f8); - rtl8168_mdio_write(tp, 0x14, 0xf9fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xe080); - rtl8168_mdio_write(tp, 0x14, 0x12ad); - rtl8168_mdio_write(tp, 0x14, 0x2733); - rtl8168_mdio_write(tp, 0x14, 0xbf43); - rtl8168_mdio_write(tp, 0x14, 0xbe02); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0xac28); - rtl8168_mdio_write(tp, 0x14, 0x09bf); - rtl8168_mdio_write(tp, 0x14, 0x43c1); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97ad); - rtl8168_mdio_write(tp, 0x14, 0x2821); - rtl8168_mdio_write(tp, 0x14, 0xbf45); - rtl8168_mdio_write(tp, 0x14, 0x5902); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0xe387); - rtl8168_mdio_write(tp, 0x14, 0xffd2); - rtl8168_mdio_write(tp, 0x14, 0x001b); - rtl8168_mdio_write(tp, 0x14, 0x45ac); - rtl8168_mdio_write(tp, 0x14, 0x2711); - rtl8168_mdio_write(tp, 0x14, 0xe187); - rtl8168_mdio_write(tp, 0x14, 0xfebf); - rtl8168_mdio_write(tp, 0x14, 0x87e4); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x590d); - rtl8168_mdio_write(tp, 0x14, 0x11bf); - rtl8168_mdio_write(tp, 0x14, 0x87e7); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59ef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfdfc); - rtl8168_mdio_write(tp, 0x14, 0x04f8); - rtl8168_mdio_write(tp, 0x14, 0xfaef); - rtl8168_mdio_write(tp, 0x14, 0x69d1); - rtl8168_mdio_write(tp, 0x14, 0x00bf); - rtl8168_mdio_write(tp, 0x14, 0x87e4); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59bf); - rtl8168_mdio_write(tp, 0x14, 0x87e7); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59ef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xee87); - rtl8168_mdio_write(tp, 0x14, 0xff46); - rtl8168_mdio_write(tp, 0x14, 0xee87); - rtl8168_mdio_write(tp, 0x14, 0xfe01); - rtl8168_mdio_write(tp, 0x14, 0x04f8); - rtl8168_mdio_write(tp, 0x14, 0xfaef); - rtl8168_mdio_write(tp, 0x14, 0x69e0); - rtl8168_mdio_write(tp, 0x14, 0x8241); - rtl8168_mdio_write(tp, 0x14, 0xa000); - rtl8168_mdio_write(tp, 0x14, 0x0502); - rtl8168_mdio_write(tp, 0x14, 0x85eb); - rtl8168_mdio_write(tp, 0x14, 0xae0e); - rtl8168_mdio_write(tp, 0x14, 0xa001); - rtl8168_mdio_write(tp, 0x14, 0x0502); - rtl8168_mdio_write(tp, 0x14, 0x1a5a); - rtl8168_mdio_write(tp, 0x14, 0xae06); - rtl8168_mdio_write(tp, 0x14, 0xa002); - rtl8168_mdio_write(tp, 0x14, 0x0302); - rtl8168_mdio_write(tp, 0x14, 0x1ae6); - rtl8168_mdio_write(tp, 0x14, 0xef96); - rtl8168_mdio_write(tp, 0x14, 0xfefc); - rtl8168_mdio_write(tp, 0x14, 0x04f8); - rtl8168_mdio_write(tp, 0x14, 0xf9fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x29f6); - rtl8168_mdio_write(tp, 0x14, 0x21e4); - rtl8168_mdio_write(tp, 0x14, 0x8229); - rtl8168_mdio_write(tp, 0x14, 0xe080); - rtl8168_mdio_write(tp, 0x14, 0x10ac); - rtl8168_mdio_write(tp, 0x14, 0x2202); - rtl8168_mdio_write(tp, 0x14, 0xae76); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x27f7); - rtl8168_mdio_write(tp, 0x14, 0x21e4); - rtl8168_mdio_write(tp, 0x14, 0x8227); - rtl8168_mdio_write(tp, 0x14, 0xbf43); - rtl8168_mdio_write(tp, 0x14, 0x1302); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0xef21); - rtl8168_mdio_write(tp, 0x14, 0xbf43); - rtl8168_mdio_write(tp, 0x14, 0x1602); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0x0c11); - rtl8168_mdio_write(tp, 0x14, 0x1e21); - rtl8168_mdio_write(tp, 0x14, 0xbf43); - rtl8168_mdio_write(tp, 0x14, 0x1902); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0x0c12); - rtl8168_mdio_write(tp, 0x14, 0x1e21); - rtl8168_mdio_write(tp, 0x14, 0xe682); - rtl8168_mdio_write(tp, 0x14, 0x43a2); - rtl8168_mdio_write(tp, 0x14, 0x000a); - rtl8168_mdio_write(tp, 0x14, 0xe182); - rtl8168_mdio_write(tp, 0x14, 0x27f6); - rtl8168_mdio_write(tp, 0x14, 0x29e5); - rtl8168_mdio_write(tp, 0x14, 0x8227); - rtl8168_mdio_write(tp, 0x14, 0xae42); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x44f7); - rtl8168_mdio_write(tp, 0x14, 0x21e4); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x0246); - rtl8168_mdio_write(tp, 0x14, 0xaebf); - rtl8168_mdio_write(tp, 0x14, 0x4325); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97ef); - rtl8168_mdio_write(tp, 0x14, 0x21bf); - rtl8168_mdio_write(tp, 0x14, 0x431c); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x970c); - rtl8168_mdio_write(tp, 0x14, 0x121e); - rtl8168_mdio_write(tp, 0x14, 0x21bf); - rtl8168_mdio_write(tp, 0x14, 0x431f); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x970c); - rtl8168_mdio_write(tp, 0x14, 0x131e); - rtl8168_mdio_write(tp, 0x14, 0x21bf); - rtl8168_mdio_write(tp, 0x14, 0x4328); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x970c); - rtl8168_mdio_write(tp, 0x14, 0x141e); - rtl8168_mdio_write(tp, 0x14, 0x21bf); - rtl8168_mdio_write(tp, 0x14, 0x44b1); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x970c); - rtl8168_mdio_write(tp, 0x14, 0x161e); - rtl8168_mdio_write(tp, 0x14, 0x21e6); - rtl8168_mdio_write(tp, 0x14, 0x8242); - rtl8168_mdio_write(tp, 0x14, 0xee82); - rtl8168_mdio_write(tp, 0x14, 0x4101); - rtl8168_mdio_write(tp, 0x14, 0xef96); - rtl8168_mdio_write(tp, 0x14, 0xfefd); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xf8fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x46a0); - rtl8168_mdio_write(tp, 0x14, 0x0005); - rtl8168_mdio_write(tp, 0x14, 0x0286); - rtl8168_mdio_write(tp, 0x14, 0x96ae); - rtl8168_mdio_write(tp, 0x14, 0x06a0); - rtl8168_mdio_write(tp, 0x14, 0x0103); - rtl8168_mdio_write(tp, 0x14, 0x0219); - rtl8168_mdio_write(tp, 0x14, 0x19ef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xf8fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x29f6); - rtl8168_mdio_write(tp, 0x14, 0x20e4); - rtl8168_mdio_write(tp, 0x14, 0x8229); - rtl8168_mdio_write(tp, 0x14, 0xe080); - rtl8168_mdio_write(tp, 0x14, 0x10ac); - rtl8168_mdio_write(tp, 0x14, 0x2102); - rtl8168_mdio_write(tp, 0x14, 0xae54); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x27f7); - rtl8168_mdio_write(tp, 0x14, 0x20e4); - rtl8168_mdio_write(tp, 0x14, 0x8227); - rtl8168_mdio_write(tp, 0x14, 0xbf42); - rtl8168_mdio_write(tp, 0x14, 0xe602); - rtl8168_mdio_write(tp, 0x14, 0x4297); - rtl8168_mdio_write(tp, 0x14, 0xac28); - rtl8168_mdio_write(tp, 0x14, 0x22bf); - rtl8168_mdio_write(tp, 0x14, 0x430d); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97e5); - rtl8168_mdio_write(tp, 0x14, 0x8247); - rtl8168_mdio_write(tp, 0x14, 0xac28); - rtl8168_mdio_write(tp, 0x14, 0x20d1); - rtl8168_mdio_write(tp, 0x14, 0x03bf); - rtl8168_mdio_write(tp, 0x14, 0x4307); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59ee); - rtl8168_mdio_write(tp, 0x14, 0x8246); - rtl8168_mdio_write(tp, 0x14, 0x00e1); - rtl8168_mdio_write(tp, 0x14, 0x8227); - rtl8168_mdio_write(tp, 0x14, 0xf628); - rtl8168_mdio_write(tp, 0x14, 0xe582); - rtl8168_mdio_write(tp, 0x14, 0x27ae); - rtl8168_mdio_write(tp, 0x14, 0x21d1); - rtl8168_mdio_write(tp, 0x14, 0x04bf); - rtl8168_mdio_write(tp, 0x14, 0x4307); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59ae); - rtl8168_mdio_write(tp, 0x14, 0x08d1); - rtl8168_mdio_write(tp, 0x14, 0x05bf); - rtl8168_mdio_write(tp, 0x14, 0x4307); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59e0); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0xf720); - rtl8168_mdio_write(tp, 0x14, 0xe482); - rtl8168_mdio_write(tp, 0x14, 0x4402); - rtl8168_mdio_write(tp, 0x14, 0x46ae); - rtl8168_mdio_write(tp, 0x14, 0xee82); - rtl8168_mdio_write(tp, 0x14, 0x4601); - rtl8168_mdio_write(tp, 0x14, 0xef96); - rtl8168_mdio_write(tp, 0x14, 0xfefc); - rtl8168_mdio_write(tp, 0x14, 0x04f8); - rtl8168_mdio_write(tp, 0x14, 0xfaef); - rtl8168_mdio_write(tp, 0x14, 0x69e0); - rtl8168_mdio_write(tp, 0x14, 0x8013); - rtl8168_mdio_write(tp, 0x14, 0xad24); - rtl8168_mdio_write(tp, 0x14, 0x1cbf); - rtl8168_mdio_write(tp, 0x14, 0x87f0); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x97ad); - rtl8168_mdio_write(tp, 0x14, 0x2813); - rtl8168_mdio_write(tp, 0x14, 0xe087); - rtl8168_mdio_write(tp, 0x14, 0xfca0); - rtl8168_mdio_write(tp, 0x14, 0x0005); - rtl8168_mdio_write(tp, 0x14, 0x0287); - rtl8168_mdio_write(tp, 0x14, 0x36ae); - rtl8168_mdio_write(tp, 0x14, 0x10a0); - rtl8168_mdio_write(tp, 0x14, 0x0105); - rtl8168_mdio_write(tp, 0x14, 0x0287); - rtl8168_mdio_write(tp, 0x14, 0x48ae); - rtl8168_mdio_write(tp, 0x14, 0x08e0); - rtl8168_mdio_write(tp, 0x14, 0x8230); - rtl8168_mdio_write(tp, 0x14, 0xf626); - rtl8168_mdio_write(tp, 0x14, 0xe482); - rtl8168_mdio_write(tp, 0x14, 0x30ef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xf8e0); - rtl8168_mdio_write(tp, 0x14, 0x8245); - rtl8168_mdio_write(tp, 0x14, 0xf722); - rtl8168_mdio_write(tp, 0x14, 0xe482); - rtl8168_mdio_write(tp, 0x14, 0x4502); - rtl8168_mdio_write(tp, 0x14, 0x46ae); - rtl8168_mdio_write(tp, 0x14, 0xee87); - rtl8168_mdio_write(tp, 0x14, 0xfc01); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xf8fa); - rtl8168_mdio_write(tp, 0x14, 0xef69); - rtl8168_mdio_write(tp, 0x14, 0xfb02); - rtl8168_mdio_write(tp, 0x14, 0x46d3); - rtl8168_mdio_write(tp, 0x14, 0xad50); - rtl8168_mdio_write(tp, 0x14, 0x2fbf); - rtl8168_mdio_write(tp, 0x14, 0x87ed); - rtl8168_mdio_write(tp, 0x14, 0xd101); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59bf); - rtl8168_mdio_write(tp, 0x14, 0x87ed); - rtl8168_mdio_write(tp, 0x14, 0xd100); - rtl8168_mdio_write(tp, 0x14, 0x0242); - rtl8168_mdio_write(tp, 0x14, 0x59e0); - rtl8168_mdio_write(tp, 0x14, 0x8245); - rtl8168_mdio_write(tp, 0x14, 0xf622); - rtl8168_mdio_write(tp, 0x14, 0xe482); - rtl8168_mdio_write(tp, 0x14, 0x4502); - rtl8168_mdio_write(tp, 0x14, 0x46ae); - rtl8168_mdio_write(tp, 0x14, 0xd100); - rtl8168_mdio_write(tp, 0x14, 0xbf87); - rtl8168_mdio_write(tp, 0x14, 0xf002); - rtl8168_mdio_write(tp, 0x14, 0x4259); - rtl8168_mdio_write(tp, 0x14, 0xee87); - rtl8168_mdio_write(tp, 0x14, 0xfc00); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x30f6); - rtl8168_mdio_write(tp, 0x14, 0x26e4); - rtl8168_mdio_write(tp, 0x14, 0x8230); - rtl8168_mdio_write(tp, 0x14, 0xffef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xfc04); - rtl8168_mdio_write(tp, 0x14, 0xf8f9); - rtl8168_mdio_write(tp, 0x14, 0xface); - rtl8168_mdio_write(tp, 0x14, 0xfaef); - rtl8168_mdio_write(tp, 0x14, 0x69fb); - rtl8168_mdio_write(tp, 0x14, 0xbf87); - rtl8168_mdio_write(tp, 0x14, 0xb3d7); - rtl8168_mdio_write(tp, 0x14, 0x001c); - rtl8168_mdio_write(tp, 0x14, 0xd819); - rtl8168_mdio_write(tp, 0x14, 0xd919); - rtl8168_mdio_write(tp, 0x14, 0xda19); - rtl8168_mdio_write(tp, 0x14, 0xdb19); - rtl8168_mdio_write(tp, 0x14, 0x07ef); - rtl8168_mdio_write(tp, 0x14, 0x9502); - rtl8168_mdio_write(tp, 0x14, 0x4259); - rtl8168_mdio_write(tp, 0x14, 0x073f); - rtl8168_mdio_write(tp, 0x14, 0x0004); - rtl8168_mdio_write(tp, 0x14, 0x9fec); - rtl8168_mdio_write(tp, 0x14, 0xffef); - rtl8168_mdio_write(tp, 0x14, 0x96fe); - rtl8168_mdio_write(tp, 0x14, 0xc6fe); - rtl8168_mdio_write(tp, 0x14, 0xfdfc); - rtl8168_mdio_write(tp, 0x14, 0x0400); - rtl8168_mdio_write(tp, 0x14, 0x0145); - rtl8168_mdio_write(tp, 0x14, 0x7d00); - rtl8168_mdio_write(tp, 0x14, 0x0345); - rtl8168_mdio_write(tp, 0x14, 0x5c00); - rtl8168_mdio_write(tp, 0x14, 0x0143); - rtl8168_mdio_write(tp, 0x14, 0x4f00); - rtl8168_mdio_write(tp, 0x14, 0x0387); - rtl8168_mdio_write(tp, 0x14, 0xdb00); - rtl8168_mdio_write(tp, 0x14, 0x0987); - rtl8168_mdio_write(tp, 0x14, 0xde00); - rtl8168_mdio_write(tp, 0x14, 0x0987); - rtl8168_mdio_write(tp, 0x14, 0xe100); - rtl8168_mdio_write(tp, 0x14, 0x0087); - rtl8168_mdio_write(tp, 0x14, 0xeaa4); - rtl8168_mdio_write(tp, 0x14, 0x00b8); - rtl8168_mdio_write(tp, 0x14, 0x20c4); - rtl8168_mdio_write(tp, 0x14, 0x1600); - rtl8168_mdio_write(tp, 0x14, 0x000f); - rtl8168_mdio_write(tp, 0x14, 0xf800); - rtl8168_mdio_write(tp, 0x14, 0x7098); - rtl8168_mdio_write(tp, 0x14, 0xa58a); - rtl8168_mdio_write(tp, 0x14, 0xb6a8); - rtl8168_mdio_write(tp, 0x14, 0x3e50); - rtl8168_mdio_write(tp, 0x14, 0xa83e); - rtl8168_mdio_write(tp, 0x14, 0x33bc); - rtl8168_mdio_write(tp, 0x14, 0xc622); - rtl8168_mdio_write(tp, 0x14, 0xbcc6); - rtl8168_mdio_write(tp, 0x14, 0xaaa4); - rtl8168_mdio_write(tp, 0x14, 0x42ff); - rtl8168_mdio_write(tp, 0x14, 0xc408); - rtl8168_mdio_write(tp, 0x14, 0x00c4); - rtl8168_mdio_write(tp, 0x14, 0x16a8); - rtl8168_mdio_write(tp, 0x14, 0xbcc0); - rtl8168_mdio_write(tp, 0x13, 0xb818); - rtl8168_mdio_write(tp, 0x14, 0x02f3); - rtl8168_mdio_write(tp, 0x13, 0xb81a); - rtl8168_mdio_write(tp, 0x14, 0x17d1); - rtl8168_mdio_write(tp, 0x13, 0xb81c); - rtl8168_mdio_write(tp, 0x14, 0x185a); - rtl8168_mdio_write(tp, 0x13, 0xb81e); - rtl8168_mdio_write(tp, 0x14, 0x3c66); - rtl8168_mdio_write(tp, 0x13, 0xb820); - rtl8168_mdio_write(tp, 0x14, 0x021f); - rtl8168_mdio_write(tp, 0x13, 0xc416); - rtl8168_mdio_write(tp, 0x14, 0x0500); - rtl8168_mdio_write(tp, 0x13, 0xb82e); - rtl8168_mdio_write(tp, 0x14, 0xfffc); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - gphy_val = rtl8168_mdio_read(tp, 0x10); - gphy_val &= ~(BIT_9); - rtl8168_mdio_write(tp, 0x10, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8146); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8168_set_phy_mcu_8168gu_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val; - - rtl8168_set_phy_mcu_patch_request(tp); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8146); - rtl8168_mdio_write(tp, 0x14, 0x0300); - rtl8168_mdio_write(tp, 0x13, 0xB82E); - rtl8168_mdio_write(tp, 0x14, 0x0001); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0xb820); - rtl8168_mdio_write(tp, 0x14, 0x0290); - rtl8168_mdio_write(tp, 0x13, 0xa012); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xa014); - rtl8168_mdio_write(tp, 0x14, 0x2c04); - rtl8168_mdio_write(tp, 0x14, 0x2c07); - rtl8168_mdio_write(tp, 0x14, 0x2c07); - rtl8168_mdio_write(tp, 0x14, 0x2c07); - rtl8168_mdio_write(tp, 0x14, 0xa304); - rtl8168_mdio_write(tp, 0x14, 0xa301); - rtl8168_mdio_write(tp, 0x14, 0x207e); - rtl8168_mdio_write(tp, 0x13, 0xa01a); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xa006); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xa004); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xa002); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xa000); - rtl8168_mdio_write(tp, 0x14, 0x107c); - rtl8168_mdio_write(tp, 0x13, 0xb820); - rtl8168_mdio_write(tp, 0x14, 0x0210); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8146); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8168_set_phy_mcu_8411b_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val; - - rtl8168_set_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp,0x1f, 0x0A43); - rtl8168_mdio_write(tp,0x13, 0x8146); - rtl8168_mdio_write(tp,0x14, 0x0100); - rtl8168_mdio_write(tp,0x13, 0xB82E); - rtl8168_mdio_write(tp,0x14, 0x0001); - - - rtl8168_mdio_write(tp,0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0xb820); - rtl8168_mdio_write(tp, 0x14, 0x0290); - rtl8168_mdio_write(tp, 0x13, 0xa012); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xa014); - rtl8168_mdio_write(tp, 0x14, 0x2c04); - rtl8168_mdio_write(tp, 0x14, 0x2c07); - rtl8168_mdio_write(tp, 0x14, 0x2c07); - rtl8168_mdio_write(tp, 0x14, 0x2c07); - rtl8168_mdio_write(tp, 0x14, 0xa304); - rtl8168_mdio_write(tp, 0x14, 0xa301); - rtl8168_mdio_write(tp, 0x14, 0x207e); - rtl8168_mdio_write(tp, 0x13, 0xa01a); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xa006); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xa004); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xa002); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xa000); - rtl8168_mdio_write(tp, 0x14, 0x107c); - rtl8168_mdio_write(tp, 0x13, 0xb820); - rtl8168_mdio_write(tp, 0x14, 0x0210); - - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8146); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8168_set_phy_mcu_8168ep_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val; - - rtl8168_set_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp,0x1f, 0x0A43); - rtl8168_mdio_write(tp,0x13, 0x8146); - rtl8168_mdio_write(tp,0x14, 0x8700); - rtl8168_mdio_write(tp,0x13, 0xB82E); - rtl8168_mdio_write(tp,0x14, 0x0001); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - - rtl8168_mdio_write(tp, 0x13, 0x83DD); - rtl8168_mdio_write(tp, 0x14, 0xAF83); - rtl8168_mdio_write(tp, 0x14, 0xE9AF); - rtl8168_mdio_write(tp, 0x14, 0x83EE); - rtl8168_mdio_write(tp, 0x14, 0xAF83); - rtl8168_mdio_write(tp, 0x14, 0xF1A1); - rtl8168_mdio_write(tp, 0x14, 0x83F4); - rtl8168_mdio_write(tp, 0x14, 0xD149); - rtl8168_mdio_write(tp, 0x14, 0xAF06); - rtl8168_mdio_write(tp, 0x14, 0x47AF); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0xAF00); - rtl8168_mdio_write(tp, 0x14, 0x00AF); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_mdio_write(tp, 0x13, 0xB818); - rtl8168_mdio_write(tp, 0x14, 0x0645); - - rtl8168_mdio_write(tp, 0x13, 0xB81A); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_mdio_write(tp, 0x13, 0xB81C); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_mdio_write(tp, 0x13, 0xB81E); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_mdio_write(tp, 0x13, 0xB832); - rtl8168_mdio_write(tp, 0x14, 0x0001); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8146); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8168_set_phy_mcu_8168h_1(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val; - - rtl8168_set_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8028); - rtl8168_mdio_write(tp, 0x14, 0x6200); - rtl8168_mdio_write(tp, 0x13, 0xB82E); - rtl8168_mdio_write(tp, 0x14, 0x0001); - - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0290); - rtl8168_mdio_write(tp, 0x13, 0xA012); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xA014); - rtl8168_mdio_write(tp, 0x14, 0x2c04); - rtl8168_mdio_write(tp, 0x14, 0x2c10); - rtl8168_mdio_write(tp, 0x14, 0x2c10); - rtl8168_mdio_write(tp, 0x14, 0x2c10); - rtl8168_mdio_write(tp, 0x14, 0xa210); - rtl8168_mdio_write(tp, 0x14, 0xa101); - rtl8168_mdio_write(tp, 0x14, 0xce10); - rtl8168_mdio_write(tp, 0x14, 0xe070); - rtl8168_mdio_write(tp, 0x14, 0x0f40); - rtl8168_mdio_write(tp, 0x14, 0xaf01); - rtl8168_mdio_write(tp, 0x14, 0x8f01); - rtl8168_mdio_write(tp, 0x14, 0x183e); - rtl8168_mdio_write(tp, 0x14, 0x8e10); - rtl8168_mdio_write(tp, 0x14, 0x8101); - rtl8168_mdio_write(tp, 0x14, 0x8210); - rtl8168_mdio_write(tp, 0x14, 0x28da); - rtl8168_mdio_write(tp, 0x13, 0xA01A); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xA006); - rtl8168_mdio_write(tp, 0x14, 0x0017); - rtl8168_mdio_write(tp, 0x13, 0xA004); - rtl8168_mdio_write(tp, 0x14, 0x0015); - rtl8168_mdio_write(tp, 0x13, 0xA002); - rtl8168_mdio_write(tp, 0x14, 0x0013); - rtl8168_mdio_write(tp, 0x13, 0xA000); - rtl8168_mdio_write(tp, 0x14, 0x18d1); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0210); - - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8028); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_clear_phy_mcu_patch_request(tp); -} - -static void -rtl8168_set_phy_mcu_8168h_2(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int gphy_val; - - rtl8168_set_phy_mcu_patch_request(tp); - - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8028); - rtl8168_mdio_write(tp, 0x14, 0x6201); - rtl8168_mdio_write(tp, 0x13, 0xB82E); - rtl8168_mdio_write(tp, 0x14, 0x0001); - - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0290); - rtl8168_mdio_write(tp, 0x13, 0xA012); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xA014); - rtl8168_mdio_write(tp, 0x14, 0x2c04); - rtl8168_mdio_write(tp, 0x14, 0x2c09); - rtl8168_mdio_write(tp, 0x14, 0x2c09); - rtl8168_mdio_write(tp, 0x14, 0x2c09); - rtl8168_mdio_write(tp, 0x14, 0xad01); - rtl8168_mdio_write(tp, 0x14, 0xad01); - rtl8168_mdio_write(tp, 0x14, 0xad01); - rtl8168_mdio_write(tp, 0x14, 0xad01); - rtl8168_mdio_write(tp, 0x14, 0x236c); - rtl8168_mdio_write(tp, 0x13, 0xA01A); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x13, 0xA006); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xA004); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xA002); - rtl8168_mdio_write(tp, 0x14, 0x0fff); - rtl8168_mdio_write(tp, 0x13, 0xA000); - rtl8168_mdio_write(tp, 0x14, 0x136b); - rtl8168_mdio_write(tp, 0x13, 0xB820); - rtl8168_mdio_write(tp, 0x14, 0x0210); - - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8323); - rtl8168_mdio_write(tp, 0x14, 0xaf83); - rtl8168_mdio_write(tp, 0x14, 0x2faf); - rtl8168_mdio_write(tp, 0x14, 0x853d); - rtl8168_mdio_write(tp, 0x14, 0xaf85); - rtl8168_mdio_write(tp, 0x14, 0x3daf); - rtl8168_mdio_write(tp, 0x14, 0x853d); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x45ad); - rtl8168_mdio_write(tp, 0x14, 0x2052); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7ae3); - rtl8168_mdio_write(tp, 0x14, 0x85fe); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f6); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7a1b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fa); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7be3); - rtl8168_mdio_write(tp, 0x14, 0x85fe); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f7); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7b1b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fb); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7ce3); - rtl8168_mdio_write(tp, 0x14, 0x85fe); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f8); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7c1b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fc); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7de3); - rtl8168_mdio_write(tp, 0x14, 0x85fe); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f9); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7d1b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fd); - rtl8168_mdio_write(tp, 0x14, 0xae50); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7ee3); - rtl8168_mdio_write(tp, 0x14, 0x85ff); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f6); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7e1b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fa); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7fe3); - rtl8168_mdio_write(tp, 0x14, 0x85ff); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f7); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x7f1b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fb); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x80e3); - rtl8168_mdio_write(tp, 0x14, 0x85ff); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f8); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x801b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fc); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x81e3); - rtl8168_mdio_write(tp, 0x14, 0x85ff); - rtl8168_mdio_write(tp, 0x14, 0x1a03); - rtl8168_mdio_write(tp, 0x14, 0x10e4); - rtl8168_mdio_write(tp, 0x14, 0x85f9); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x811b); - rtl8168_mdio_write(tp, 0x14, 0x03e4); - rtl8168_mdio_write(tp, 0x14, 0x85fd); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf6ad); - rtl8168_mdio_write(tp, 0x14, 0x2404); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xf610); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf7ad); - rtl8168_mdio_write(tp, 0x14, 0x2404); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xf710); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf8ad); - rtl8168_mdio_write(tp, 0x14, 0x2404); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xf810); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf9ad); - rtl8168_mdio_write(tp, 0x14, 0x2404); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xf910); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfaad); - rtl8168_mdio_write(tp, 0x14, 0x2704); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xfa00); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfbad); - rtl8168_mdio_write(tp, 0x14, 0x2704); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xfb00); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfcad); - rtl8168_mdio_write(tp, 0x14, 0x2704); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xfc00); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfdad); - rtl8168_mdio_write(tp, 0x14, 0x2704); - rtl8168_mdio_write(tp, 0x14, 0xee85); - rtl8168_mdio_write(tp, 0x14, 0xfd00); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x44ad); - rtl8168_mdio_write(tp, 0x14, 0x203f); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf6e4); - rtl8168_mdio_write(tp, 0x14, 0x8288); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfae4); - rtl8168_mdio_write(tp, 0x14, 0x8289); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x440d); - rtl8168_mdio_write(tp, 0x14, 0x0458); - rtl8168_mdio_write(tp, 0x14, 0x01bf); - rtl8168_mdio_write(tp, 0x14, 0x8264); - rtl8168_mdio_write(tp, 0x14, 0x0215); - rtl8168_mdio_write(tp, 0x14, 0x38bf); - rtl8168_mdio_write(tp, 0x14, 0x824e); - rtl8168_mdio_write(tp, 0x14, 0x0213); - rtl8168_mdio_write(tp, 0x14, 0x06a0); - rtl8168_mdio_write(tp, 0x14, 0x010f); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x44f6); - rtl8168_mdio_write(tp, 0x14, 0x20e4); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x580f); - rtl8168_mdio_write(tp, 0x14, 0xe582); - rtl8168_mdio_write(tp, 0x14, 0x5aae); - rtl8168_mdio_write(tp, 0x14, 0x0ebf); - rtl8168_mdio_write(tp, 0x14, 0x825e); - rtl8168_mdio_write(tp, 0x14, 0xe382); - rtl8168_mdio_write(tp, 0x14, 0x44f7); - rtl8168_mdio_write(tp, 0x14, 0x3ce7); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x0212); - rtl8168_mdio_write(tp, 0x14, 0xf0ad); - rtl8168_mdio_write(tp, 0x14, 0x213f); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf7e4); - rtl8168_mdio_write(tp, 0x14, 0x8288); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfbe4); - rtl8168_mdio_write(tp, 0x14, 0x8289); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x440d); - rtl8168_mdio_write(tp, 0x14, 0x0558); - rtl8168_mdio_write(tp, 0x14, 0x01bf); - rtl8168_mdio_write(tp, 0x14, 0x826b); - rtl8168_mdio_write(tp, 0x14, 0x0215); - rtl8168_mdio_write(tp, 0x14, 0x38bf); - rtl8168_mdio_write(tp, 0x14, 0x824f); - rtl8168_mdio_write(tp, 0x14, 0x0213); - rtl8168_mdio_write(tp, 0x14, 0x06a0); - rtl8168_mdio_write(tp, 0x14, 0x010f); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x44f6); - rtl8168_mdio_write(tp, 0x14, 0x21e4); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x580f); - rtl8168_mdio_write(tp, 0x14, 0xe582); - rtl8168_mdio_write(tp, 0x14, 0x5bae); - rtl8168_mdio_write(tp, 0x14, 0x0ebf); - rtl8168_mdio_write(tp, 0x14, 0x8265); - rtl8168_mdio_write(tp, 0x14, 0xe382); - rtl8168_mdio_write(tp, 0x14, 0x44f7); - rtl8168_mdio_write(tp, 0x14, 0x3de7); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x0212); - rtl8168_mdio_write(tp, 0x14, 0xf0ad); - rtl8168_mdio_write(tp, 0x14, 0x223f); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf8e4); - rtl8168_mdio_write(tp, 0x14, 0x8288); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfce4); - rtl8168_mdio_write(tp, 0x14, 0x8289); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x440d); - rtl8168_mdio_write(tp, 0x14, 0x0658); - rtl8168_mdio_write(tp, 0x14, 0x01bf); - rtl8168_mdio_write(tp, 0x14, 0x8272); - rtl8168_mdio_write(tp, 0x14, 0x0215); - rtl8168_mdio_write(tp, 0x14, 0x38bf); - rtl8168_mdio_write(tp, 0x14, 0x8250); - rtl8168_mdio_write(tp, 0x14, 0x0213); - rtl8168_mdio_write(tp, 0x14, 0x06a0); - rtl8168_mdio_write(tp, 0x14, 0x010f); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x44f6); - rtl8168_mdio_write(tp, 0x14, 0x22e4); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x580f); - rtl8168_mdio_write(tp, 0x14, 0xe582); - rtl8168_mdio_write(tp, 0x14, 0x5cae); - rtl8168_mdio_write(tp, 0x14, 0x0ebf); - rtl8168_mdio_write(tp, 0x14, 0x826c); - rtl8168_mdio_write(tp, 0x14, 0xe382); - rtl8168_mdio_write(tp, 0x14, 0x44f7); - rtl8168_mdio_write(tp, 0x14, 0x3ee7); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x0212); - rtl8168_mdio_write(tp, 0x14, 0xf0ad); - rtl8168_mdio_write(tp, 0x14, 0x233f); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xf9e4); - rtl8168_mdio_write(tp, 0x14, 0x8288); - rtl8168_mdio_write(tp, 0x14, 0xe085); - rtl8168_mdio_write(tp, 0x14, 0xfde4); - rtl8168_mdio_write(tp, 0x14, 0x8289); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x440d); - rtl8168_mdio_write(tp, 0x14, 0x0758); - rtl8168_mdio_write(tp, 0x14, 0x01bf); - rtl8168_mdio_write(tp, 0x14, 0x8279); - rtl8168_mdio_write(tp, 0x14, 0x0215); - rtl8168_mdio_write(tp, 0x14, 0x38bf); - rtl8168_mdio_write(tp, 0x14, 0x8251); - rtl8168_mdio_write(tp, 0x14, 0x0213); - rtl8168_mdio_write(tp, 0x14, 0x06a0); - rtl8168_mdio_write(tp, 0x14, 0x010f); - rtl8168_mdio_write(tp, 0x14, 0xe082); - rtl8168_mdio_write(tp, 0x14, 0x44f6); - rtl8168_mdio_write(tp, 0x14, 0x23e4); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x580f); - rtl8168_mdio_write(tp, 0x14, 0xe582); - rtl8168_mdio_write(tp, 0x14, 0x5dae); - rtl8168_mdio_write(tp, 0x14, 0x0ebf); - rtl8168_mdio_write(tp, 0x14, 0x8273); - rtl8168_mdio_write(tp, 0x14, 0xe382); - rtl8168_mdio_write(tp, 0x14, 0x44f7); - rtl8168_mdio_write(tp, 0x14, 0x3fe7); - rtl8168_mdio_write(tp, 0x14, 0x8244); - rtl8168_mdio_write(tp, 0x14, 0x0212); - rtl8168_mdio_write(tp, 0x14, 0xf0ee); - rtl8168_mdio_write(tp, 0x14, 0x8288); - rtl8168_mdio_write(tp, 0x14, 0x10ee); - rtl8168_mdio_write(tp, 0x14, 0x8289); - rtl8168_mdio_write(tp, 0x14, 0x00af); - rtl8168_mdio_write(tp, 0x14, 0x14aa); - rtl8168_mdio_write(tp, 0x13, 0xb818); - rtl8168_mdio_write(tp, 0x14, 0x13cf); - rtl8168_mdio_write(tp, 0x13, 0xb81a); - rtl8168_mdio_write(tp, 0x14, 0xfffd); - rtl8168_mdio_write(tp, 0x13, 0xb81c); - rtl8168_mdio_write(tp, 0x14, 0xfffd); - rtl8168_mdio_write(tp, 0x13, 0xb81e); - rtl8168_mdio_write(tp, 0x14, 0xfffd); - rtl8168_mdio_write(tp, 0x13, 0xb832); - rtl8168_mdio_write(tp, 0x14, 0x0001); - - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x0000); - rtl8168_mdio_write(tp, 0x14, 0x0000); - rtl8168_mdio_write(tp, 0x1f, 0x0B82); - gphy_val = rtl8168_mdio_read(tp, 0x17); - gphy_val &= ~(BIT_0); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8028); - rtl8168_mdio_write(tp, 0x14, 0x0000); - - rtl8168_clear_phy_mcu_patch_request(tp); - - if (tp->RequiredSecLanDonglePatch) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - gphy_val = rtl8168_mdio_read(tp, 0x11); - gphy_val &= ~BIT_6; - rtl8168_mdio_write(tp, 0x11, gphy_val); - } -} - -static void -rtl8168_init_hw_phy_mcu(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u8 require_disable_phy_disable_mode = FALSE; - - if (tp->NotWrRamCodeToMicroP == TRUE) return; - if (rtl8168_check_hw_phy_mcu_code_ver(dev)) return; - - if (FALSE == rtl8168_phy_ram_code_check(dev)) { - rtl8168_set_phy_ram_code_check_fail_flag(dev); - return; - } - - if (HW_SUPPORT_CHECK_PHY_DISABLE_MODE(tp) && rtl8168_is_in_phy_disable_mode(dev)) - require_disable_phy_disable_mode = TRUE; - - if (require_disable_phy_disable_mode) - rtl8168_disable_phy_disable_mode(dev); - - switch (tp->mcfg) { - case CFG_METHOD_14: - rtl8168_set_phy_mcu_8168e_1(dev); - break; - case CFG_METHOD_15: - rtl8168_set_phy_mcu_8168e_2(dev); - break; - case CFG_METHOD_16: - rtl8168_set_phy_mcu_8168evl_1(dev); - break; - case CFG_METHOD_17: - rtl8168_set_phy_mcu_8168evl_2(dev); - break; - case CFG_METHOD_18: - rtl8168_set_phy_mcu_8168f_1(dev); - break; - case CFG_METHOD_19: - rtl8168_set_phy_mcu_8168f_2(dev); - break; - case CFG_METHOD_20: - rtl8168_set_phy_mcu_8411_1(dev); - break; - case CFG_METHOD_21: - rtl8168_set_phy_mcu_8168g_1(dev); - break; - case CFG_METHOD_25: - rtl8168_set_phy_mcu_8168gu_2(dev); - break; - case CFG_METHOD_26: - rtl8168_set_phy_mcu_8411b_1(dev); - break; - case CFG_METHOD_28: - rtl8168_set_phy_mcu_8168ep_2(dev); - break; - case CFG_METHOD_29: - rtl8168_set_phy_mcu_8168h_1(dev); - break; - case CFG_METHOD_30: - rtl8168_set_phy_mcu_8168h_2(dev); - break; - } - - if (require_disable_phy_disable_mode) - rtl8168_enable_phy_disable_mode(dev); - - rtl8168_write_hw_phy_mcu_code_ver(dev); - - rtl8168_mdio_write(tp,0x1F, 0x0000); - - tp->HwHasWrRamCodeToMicroP = TRUE; -} -#endif - -static void -rtl8168_hw_phy_config(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - u16 gphy_val; - unsigned int i; - - tp->phy_reset_enable(dev); - - if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x06) return; - -#ifndef ENABLE_USE_FIRMWARE_FILE - if (!tp->rtl_fw) { - rtl8168_init_hw_phy_mcu(dev); - } -#endif - - if (tp->mcfg == CFG_METHOD_1) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0B, 0x94B0); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x12, 0x6096); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x0D, 0xF8A0); - } else if (tp->mcfg == CFG_METHOD_2) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0B, 0x94B0); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x12, 0x6096); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_3) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0B, 0x94B0); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x12, 0x6096); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_4) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x12, 0x2300); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x16, 0x000A); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x12, 0xC096); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x00, 0x88DE); - rtl8168_mdio_write(tp, 0x01, 0x82B1); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x08, 0x9E30); - rtl8168_mdio_write(tp, 0x09, 0x01F0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0A, 0x5500); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x03, 0x7002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0C, 0x00C8); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | (1 << 5)); - rtl8168_mdio_write(tp, 0x0D, rtl8168_mdio_read(tp, 0x0D) & ~(1 << 5)); - } else if (tp->mcfg == CFG_METHOD_5) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x12, 0x2300); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x16, 0x0F0A); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x00, 0x88DE); - rtl8168_mdio_write(tp, 0x01, 0x82B1); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0C, 0x7EB8); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x0761); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x03, 0x802F); - rtl8168_mdio_write(tp, 0x02, 0x4F02); - rtl8168_mdio_write(tp, 0x01, 0x0409); - rtl8168_mdio_write(tp, 0x00, 0xF099); - rtl8168_mdio_write(tp, 0x04, 0x9800); - rtl8168_mdio_write(tp, 0x04, 0x9000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x16, rtl8168_mdio_read(tp, 0x16) | (1 << 0)); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | (1 << 5)); - rtl8168_mdio_write(tp, 0x0D, rtl8168_mdio_read(tp, 0x0D) & ~(1 << 5)); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x1D, 0x3D98); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_6) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x12, 0x2300); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x16, 0x0F0A); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x00, 0x88DE); - rtl8168_mdio_write(tp, 0x01, 0x82B1); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0C, 0x7EB8); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x5461); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x5461); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x16, rtl8168_mdio_read(tp, 0x16) | (1 << 0)); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | (1 << 5)); - rtl8168_mdio_write(tp, 0x0D, rtl8168_mdio_read(tp, 0x0D) & ~(1 << 5)); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x1D, 0x3D98); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_7) { - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | (1 << 5)); - rtl8168_mdio_write(tp, 0x0D, rtl8168_mdio_read(tp, 0x0D) & ~(1 << 5)); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x1D, 0x3D98); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x14, 0xCAA3); - rtl8168_mdio_write(tp, 0x1C, 0x000A); - rtl8168_mdio_write(tp, 0x18, 0x65D0); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x17, 0xB580); - rtl8168_mdio_write(tp, 0x18, 0xFF54); - rtl8168_mdio_write(tp, 0x19, 0x3954); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0D, 0x310C); - rtl8168_mdio_write(tp, 0x0E, 0x310C); - rtl8168_mdio_write(tp, 0x0F, 0x311C); - rtl8168_mdio_write(tp, 0x06, 0x0761); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x18, 0xFF55); - rtl8168_mdio_write(tp, 0x19, 0x3955); - rtl8168_mdio_write(tp, 0x18, 0xFF54); - rtl8168_mdio_write(tp, 0x19, 0x3954); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_8) { - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | (1 << 5)); - rtl8168_mdio_write(tp, 0x0D, rtl8168_mdio_read(tp, 0x0D) & ~(1 << 5)); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x14, 0xCAA3); - rtl8168_mdio_write(tp, 0x1C, 0x000A); - rtl8168_mdio_write(tp, 0x18, 0x65D0); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x17, 0xB580); - rtl8168_mdio_write(tp, 0x18, 0xFF54); - rtl8168_mdio_write(tp, 0x19, 0x3954); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0D, 0x310C); - rtl8168_mdio_write(tp, 0x0E, 0x310C); - rtl8168_mdio_write(tp, 0x0F, 0x311C); - rtl8168_mdio_write(tp, 0x06, 0x0761); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x18, 0xFF55); - rtl8168_mdio_write(tp, 0x19, 0x3955); - rtl8168_mdio_write(tp, 0x18, 0xFF54); - rtl8168_mdio_write(tp, 0x19, 0x3954); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x16, rtl8168_mdio_read(tp, 0x16) | (1 << 0)); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_9) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x06, 0x4064); - rtl8168_mdio_write(tp, 0x07, 0x2863); - rtl8168_mdio_write(tp, 0x08, 0x059C); - rtl8168_mdio_write(tp, 0x09, 0x26B4); - rtl8168_mdio_write(tp, 0x0A, 0x6A19); - rtl8168_mdio_write(tp, 0x0B, 0xDCC8); - rtl8168_mdio_write(tp, 0x10, 0xF06D); - rtl8168_mdio_write(tp, 0x14, 0x7F68); - rtl8168_mdio_write(tp, 0x18, 0x7FD9); - rtl8168_mdio_write(tp, 0x1C, 0xF0FF); - rtl8168_mdio_write(tp, 0x1D, 0x3D9C); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x12, 0xF49F); - rtl8168_mdio_write(tp, 0x13, 0x070B); - rtl8168_mdio_write(tp, 0x1A, 0x05AD); - rtl8168_mdio_write(tp, 0x14, 0x94C0); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0B) & 0xFF00; - gphy_val |= 0x10; - rtl8168_mdio_write(tp, 0x0B, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x0C) & 0x00FF; - gphy_val |= 0xA200; - rtl8168_mdio_write(tp, 0x0C, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x5561); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8332); - rtl8168_mdio_write(tp, 0x06, 0x5561); - - if (rtl8168_efuse_read(tp, 0x01) == 0xb1) { - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x05, 0x669A); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8330); - rtl8168_mdio_write(tp, 0x06, 0x669A); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0D); - if ((gphy_val & 0x00FF) != 0x006C) { - gphy_val &= 0xFF00; - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0065); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0066); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0067); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0068); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0069); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x006A); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x006B); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x006C); - } - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x05, 0x6662); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8330); - rtl8168_mdio_write(tp, 0x06, 0x6662); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0D); - gphy_val |= BIT_9; - gphy_val |= BIT_8; - rtl8168_mdio_write(tp, 0x0D, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x0F); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x0F, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x02); - gphy_val &= ~BIT_10; - gphy_val &= ~BIT_9; - gphy_val |= BIT_8; - rtl8168_mdio_write(tp, 0x02, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x03); - gphy_val &= ~BIT_15; - gphy_val &= ~BIT_14; - gphy_val &= ~BIT_13; - rtl8168_mdio_write(tp, 0x03, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x001B); - if (rtl8168_mdio_read(tp, 0x06) == 0xBF00) { - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaef); - rtl8168_mdio_write(tp, 0x06, 0x59ee); - rtl8168_mdio_write(tp, 0x06, 0xf8ea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xf8eb); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0xf87c); - rtl8168_mdio_write(tp, 0x06, 0xe1f8); - rtl8168_mdio_write(tp, 0x06, 0x7d59); - rtl8168_mdio_write(tp, 0x06, 0x0fef); - rtl8168_mdio_write(tp, 0x06, 0x0139); - rtl8168_mdio_write(tp, 0x06, 0x029e); - rtl8168_mdio_write(tp, 0x06, 0x06ef); - rtl8168_mdio_write(tp, 0x06, 0x1039); - rtl8168_mdio_write(tp, 0x06, 0x089f); - rtl8168_mdio_write(tp, 0x06, 0x2aee); - rtl8168_mdio_write(tp, 0x06, 0xf8ea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xf8eb); - rtl8168_mdio_write(tp, 0x06, 0x01e0); - rtl8168_mdio_write(tp, 0x06, 0xf87c); - rtl8168_mdio_write(tp, 0x06, 0xe1f8); - rtl8168_mdio_write(tp, 0x06, 0x7d58); - rtl8168_mdio_write(tp, 0x06, 0x409e); - rtl8168_mdio_write(tp, 0x06, 0x0f39); - rtl8168_mdio_write(tp, 0x06, 0x46aa); - rtl8168_mdio_write(tp, 0x06, 0x0bbf); - rtl8168_mdio_write(tp, 0x06, 0x8290); - rtl8168_mdio_write(tp, 0x06, 0xd682); - rtl8168_mdio_write(tp, 0x06, 0x9802); - rtl8168_mdio_write(tp, 0x06, 0x014f); - rtl8168_mdio_write(tp, 0x06, 0xae09); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0x98d6); - rtl8168_mdio_write(tp, 0x06, 0x82a0); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x4fef); - rtl8168_mdio_write(tp, 0x06, 0x95fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x05f8); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xeef8); - rtl8168_mdio_write(tp, 0x06, 0xea00); - rtl8168_mdio_write(tp, 0x06, 0xeef8); - rtl8168_mdio_write(tp, 0x06, 0xeb00); - rtl8168_mdio_write(tp, 0x06, 0xe2f8); - rtl8168_mdio_write(tp, 0x06, 0x7ce3); - rtl8168_mdio_write(tp, 0x06, 0xf87d); - rtl8168_mdio_write(tp, 0x06, 0xa511); - rtl8168_mdio_write(tp, 0x06, 0x1112); - rtl8168_mdio_write(tp, 0x06, 0xd240); - rtl8168_mdio_write(tp, 0x06, 0xd644); - rtl8168_mdio_write(tp, 0x06, 0x4402); - rtl8168_mdio_write(tp, 0x06, 0x8217); - rtl8168_mdio_write(tp, 0x06, 0xd2a0); - rtl8168_mdio_write(tp, 0x06, 0xd6aa); - rtl8168_mdio_write(tp, 0x06, 0xaa02); - rtl8168_mdio_write(tp, 0x06, 0x8217); - rtl8168_mdio_write(tp, 0x06, 0xae0f); - rtl8168_mdio_write(tp, 0x06, 0xa544); - rtl8168_mdio_write(tp, 0x06, 0x4402); - rtl8168_mdio_write(tp, 0x06, 0xae4d); - rtl8168_mdio_write(tp, 0x06, 0xa5aa); - rtl8168_mdio_write(tp, 0x06, 0xaa02); - rtl8168_mdio_write(tp, 0x06, 0xae47); - rtl8168_mdio_write(tp, 0x06, 0xaf82); - rtl8168_mdio_write(tp, 0x06, 0x13ee); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0x0fee); - rtl8168_mdio_write(tp, 0x06, 0x834c); - rtl8168_mdio_write(tp, 0x06, 0x0fee); - rtl8168_mdio_write(tp, 0x06, 0x834f); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8351); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x834a); - rtl8168_mdio_write(tp, 0x06, 0xffee); - rtl8168_mdio_write(tp, 0x06, 0x834b); - rtl8168_mdio_write(tp, 0x06, 0xffe0); - rtl8168_mdio_write(tp, 0x06, 0x8330); - rtl8168_mdio_write(tp, 0x06, 0xe183); - rtl8168_mdio_write(tp, 0x06, 0x3158); - rtl8168_mdio_write(tp, 0x06, 0xfee4); - rtl8168_mdio_write(tp, 0x06, 0xf88a); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x8be0); - rtl8168_mdio_write(tp, 0x06, 0x8332); - rtl8168_mdio_write(tp, 0x06, 0xe183); - rtl8168_mdio_write(tp, 0x06, 0x3359); - rtl8168_mdio_write(tp, 0x06, 0x0fe2); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0x0c24); - rtl8168_mdio_write(tp, 0x06, 0x5af0); - rtl8168_mdio_write(tp, 0x06, 0x1e12); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x8ce5); - rtl8168_mdio_write(tp, 0x06, 0xf88d); - rtl8168_mdio_write(tp, 0x06, 0xaf82); - rtl8168_mdio_write(tp, 0x06, 0x13e0); - rtl8168_mdio_write(tp, 0x06, 0x834f); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x834f); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x009f); - rtl8168_mdio_write(tp, 0x06, 0x0ae0); - rtl8168_mdio_write(tp, 0x06, 0x834f); - rtl8168_mdio_write(tp, 0x06, 0xa010); - rtl8168_mdio_write(tp, 0x06, 0xa5ee); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x01e0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7805); - rtl8168_mdio_write(tp, 0x06, 0x9e9a); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x049e); - rtl8168_mdio_write(tp, 0x06, 0x10e0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7803); - rtl8168_mdio_write(tp, 0x06, 0x9e0f); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x05ae); - rtl8168_mdio_write(tp, 0x06, 0x0caf); - rtl8168_mdio_write(tp, 0x06, 0x81f8); - rtl8168_mdio_write(tp, 0x06, 0xaf81); - rtl8168_mdio_write(tp, 0x06, 0xa3af); - rtl8168_mdio_write(tp, 0x06, 0x81dc); - rtl8168_mdio_write(tp, 0x06, 0xaf82); - rtl8168_mdio_write(tp, 0x06, 0x13ee); - rtl8168_mdio_write(tp, 0x06, 0x8348); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0x8349); - rtl8168_mdio_write(tp, 0x06, 0x00e0); - rtl8168_mdio_write(tp, 0x06, 0x8351); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x8351); - rtl8168_mdio_write(tp, 0x06, 0x5801); - rtl8168_mdio_write(tp, 0x06, 0x9fea); - rtl8168_mdio_write(tp, 0x06, 0xd000); - rtl8168_mdio_write(tp, 0x06, 0xd180); - rtl8168_mdio_write(tp, 0x06, 0x1f66); - rtl8168_mdio_write(tp, 0x06, 0xe2f8); - rtl8168_mdio_write(tp, 0x06, 0xeae3); - rtl8168_mdio_write(tp, 0x06, 0xf8eb); - rtl8168_mdio_write(tp, 0x06, 0x5af8); - rtl8168_mdio_write(tp, 0x06, 0x1e20); - rtl8168_mdio_write(tp, 0x06, 0xe6f8); - rtl8168_mdio_write(tp, 0x06, 0xeae5); - rtl8168_mdio_write(tp, 0x06, 0xf8eb); - rtl8168_mdio_write(tp, 0x06, 0xd302); - rtl8168_mdio_write(tp, 0x06, 0xb3fe); - rtl8168_mdio_write(tp, 0x06, 0xe2f8); - rtl8168_mdio_write(tp, 0x06, 0x7cef); - rtl8168_mdio_write(tp, 0x06, 0x325b); - rtl8168_mdio_write(tp, 0x06, 0x80e3); - rtl8168_mdio_write(tp, 0x06, 0xf87d); - rtl8168_mdio_write(tp, 0x06, 0x9e03); - rtl8168_mdio_write(tp, 0x06, 0x7dff); - rtl8168_mdio_write(tp, 0x06, 0xff0d); - rtl8168_mdio_write(tp, 0x06, 0x581c); - rtl8168_mdio_write(tp, 0x06, 0x551a); - rtl8168_mdio_write(tp, 0x06, 0x6511); - rtl8168_mdio_write(tp, 0x06, 0xa190); - rtl8168_mdio_write(tp, 0x06, 0xd3e2); - rtl8168_mdio_write(tp, 0x06, 0x8348); - rtl8168_mdio_write(tp, 0x06, 0xe383); - rtl8168_mdio_write(tp, 0x06, 0x491b); - rtl8168_mdio_write(tp, 0x06, 0x56ab); - rtl8168_mdio_write(tp, 0x06, 0x08ef); - rtl8168_mdio_write(tp, 0x06, 0x56e6); - rtl8168_mdio_write(tp, 0x06, 0x8348); - rtl8168_mdio_write(tp, 0x06, 0xe783); - rtl8168_mdio_write(tp, 0x06, 0x4910); - rtl8168_mdio_write(tp, 0x06, 0xd180); - rtl8168_mdio_write(tp, 0x06, 0x1f66); - rtl8168_mdio_write(tp, 0x06, 0xa004); - rtl8168_mdio_write(tp, 0x06, 0xb9e2); - rtl8168_mdio_write(tp, 0x06, 0x8348); - rtl8168_mdio_write(tp, 0x06, 0xe383); - rtl8168_mdio_write(tp, 0x06, 0x49ef); - rtl8168_mdio_write(tp, 0x06, 0x65e2); - rtl8168_mdio_write(tp, 0x06, 0x834a); - rtl8168_mdio_write(tp, 0x06, 0xe383); - rtl8168_mdio_write(tp, 0x06, 0x4b1b); - rtl8168_mdio_write(tp, 0x06, 0x56aa); - rtl8168_mdio_write(tp, 0x06, 0x0eef); - rtl8168_mdio_write(tp, 0x06, 0x56e6); - rtl8168_mdio_write(tp, 0x06, 0x834a); - rtl8168_mdio_write(tp, 0x06, 0xe783); - rtl8168_mdio_write(tp, 0x06, 0x4be2); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0xe683); - rtl8168_mdio_write(tp, 0x06, 0x4ce0); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0xa000); - rtl8168_mdio_write(tp, 0x06, 0x0caf); - rtl8168_mdio_write(tp, 0x06, 0x81dc); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4d10); - rtl8168_mdio_write(tp, 0x06, 0xe483); - rtl8168_mdio_write(tp, 0x06, 0x4dae); - rtl8168_mdio_write(tp, 0x06, 0x0480); - rtl8168_mdio_write(tp, 0x06, 0xe483); - rtl8168_mdio_write(tp, 0x06, 0x4de0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7803); - rtl8168_mdio_write(tp, 0x06, 0x9e0b); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x049e); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x02e0); - rtl8168_mdio_write(tp, 0x06, 0x8332); - rtl8168_mdio_write(tp, 0x06, 0xe183); - rtl8168_mdio_write(tp, 0x06, 0x3359); - rtl8168_mdio_write(tp, 0x06, 0x0fe2); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0x0c24); - rtl8168_mdio_write(tp, 0x06, 0x5af0); - rtl8168_mdio_write(tp, 0x06, 0x1e12); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x8ce5); - rtl8168_mdio_write(tp, 0x06, 0xf88d); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x30e1); - rtl8168_mdio_write(tp, 0x06, 0x8331); - rtl8168_mdio_write(tp, 0x06, 0x6801); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x8ae5); - rtl8168_mdio_write(tp, 0x06, 0xf88b); - rtl8168_mdio_write(tp, 0x06, 0xae37); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4e03); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4ce1); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0x1b01); - rtl8168_mdio_write(tp, 0x06, 0x9e04); - rtl8168_mdio_write(tp, 0x06, 0xaaa1); - rtl8168_mdio_write(tp, 0x06, 0xaea8); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4e04); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4f00); - rtl8168_mdio_write(tp, 0x06, 0xaeab); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4f78); - rtl8168_mdio_write(tp, 0x06, 0x039f); - rtl8168_mdio_write(tp, 0x06, 0x14ee); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x05d2); - rtl8168_mdio_write(tp, 0x06, 0x40d6); - rtl8168_mdio_write(tp, 0x06, 0x5554); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x17d2); - rtl8168_mdio_write(tp, 0x06, 0xa0d6); - rtl8168_mdio_write(tp, 0x06, 0xba00); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x17fe); - rtl8168_mdio_write(tp, 0x06, 0xfdfc); - rtl8168_mdio_write(tp, 0x06, 0x05f8); - rtl8168_mdio_write(tp, 0x06, 0xe0f8); - rtl8168_mdio_write(tp, 0x06, 0x60e1); - rtl8168_mdio_write(tp, 0x06, 0xf861); - rtl8168_mdio_write(tp, 0x06, 0x6802); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x60e5); - rtl8168_mdio_write(tp, 0x06, 0xf861); - rtl8168_mdio_write(tp, 0x06, 0xe0f8); - rtl8168_mdio_write(tp, 0x06, 0x48e1); - rtl8168_mdio_write(tp, 0x06, 0xf849); - rtl8168_mdio_write(tp, 0x06, 0x580f); - rtl8168_mdio_write(tp, 0x06, 0x1e02); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x48e5); - rtl8168_mdio_write(tp, 0x06, 0xf849); - rtl8168_mdio_write(tp, 0x06, 0xd000); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x5bbf); - rtl8168_mdio_write(tp, 0x06, 0x8350); - rtl8168_mdio_write(tp, 0x06, 0xef46); - rtl8168_mdio_write(tp, 0x06, 0xdc19); - rtl8168_mdio_write(tp, 0x06, 0xddd0); - rtl8168_mdio_write(tp, 0x06, 0x0102); - rtl8168_mdio_write(tp, 0x06, 0x825b); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x77e0); - rtl8168_mdio_write(tp, 0x06, 0xf860); - rtl8168_mdio_write(tp, 0x06, 0xe1f8); - rtl8168_mdio_write(tp, 0x06, 0x6158); - rtl8168_mdio_write(tp, 0x06, 0xfde4); - rtl8168_mdio_write(tp, 0x06, 0xf860); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x61fc); - rtl8168_mdio_write(tp, 0x06, 0x04f9); - rtl8168_mdio_write(tp, 0x06, 0xfafb); - rtl8168_mdio_write(tp, 0x06, 0xc6bf); - rtl8168_mdio_write(tp, 0x06, 0xf840); - rtl8168_mdio_write(tp, 0x06, 0xbe83); - rtl8168_mdio_write(tp, 0x06, 0x50a0); - rtl8168_mdio_write(tp, 0x06, 0x0101); - rtl8168_mdio_write(tp, 0x06, 0x071b); - rtl8168_mdio_write(tp, 0x06, 0x89cf); - rtl8168_mdio_write(tp, 0x06, 0xd208); - rtl8168_mdio_write(tp, 0x06, 0xebdb); - rtl8168_mdio_write(tp, 0x06, 0x19b2); - rtl8168_mdio_write(tp, 0x06, 0xfbff); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0x04f8); - rtl8168_mdio_write(tp, 0x06, 0xe0f8); - rtl8168_mdio_write(tp, 0x06, 0x48e1); - rtl8168_mdio_write(tp, 0x06, 0xf849); - rtl8168_mdio_write(tp, 0x06, 0x6808); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x48e5); - rtl8168_mdio_write(tp, 0x06, 0xf849); - rtl8168_mdio_write(tp, 0x06, 0x58f7); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x48e5); - rtl8168_mdio_write(tp, 0x06, 0xf849); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0x4d20); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x4e22); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x4ddf); - rtl8168_mdio_write(tp, 0x06, 0xff01); - rtl8168_mdio_write(tp, 0x06, 0x4edd); - rtl8168_mdio_write(tp, 0x06, 0xff01); - rtl8168_mdio_write(tp, 0x06, 0xf8fa); - rtl8168_mdio_write(tp, 0x06, 0xfbef); - rtl8168_mdio_write(tp, 0x06, 0x79bf); - rtl8168_mdio_write(tp, 0x06, 0xf822); - rtl8168_mdio_write(tp, 0x06, 0xd819); - rtl8168_mdio_write(tp, 0x06, 0xd958); - rtl8168_mdio_write(tp, 0x06, 0x849f); - rtl8168_mdio_write(tp, 0x06, 0x09bf); - rtl8168_mdio_write(tp, 0x06, 0x82be); - rtl8168_mdio_write(tp, 0x06, 0xd682); - rtl8168_mdio_write(tp, 0x06, 0xc602); - rtl8168_mdio_write(tp, 0x06, 0x014f); - rtl8168_mdio_write(tp, 0x06, 0xef97); - rtl8168_mdio_write(tp, 0x06, 0xfffe); - rtl8168_mdio_write(tp, 0x06, 0xfc05); - rtl8168_mdio_write(tp, 0x06, 0x17ff); - rtl8168_mdio_write(tp, 0x06, 0xfe01); - rtl8168_mdio_write(tp, 0x06, 0x1700); - rtl8168_mdio_write(tp, 0x06, 0x0102); - rtl8168_mdio_write(tp, 0x05, 0x83d8); - rtl8168_mdio_write(tp, 0x06, 0x8051); - rtl8168_mdio_write(tp, 0x05, 0x83d6); - rtl8168_mdio_write(tp, 0x06, 0x82a0); - rtl8168_mdio_write(tp, 0x05, 0x83d4); - rtl8168_mdio_write(tp, 0x06, 0x8000); - rtl8168_mdio_write(tp, 0x02, 0x2010); - rtl8168_mdio_write(tp, 0x03, 0xdc00); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x0b, 0x0600); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00fc); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0xF880); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_10) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x06, 0x4064); - rtl8168_mdio_write(tp, 0x07, 0x2863); - rtl8168_mdio_write(tp, 0x08, 0x059C); - rtl8168_mdio_write(tp, 0x09, 0x26B4); - rtl8168_mdio_write(tp, 0x0A, 0x6A19); - rtl8168_mdio_write(tp, 0x0B, 0xDCC8); - rtl8168_mdio_write(tp, 0x10, 0xF06D); - rtl8168_mdio_write(tp, 0x14, 0x7F68); - rtl8168_mdio_write(tp, 0x18, 0x7FD9); - rtl8168_mdio_write(tp, 0x1C, 0xF0FF); - rtl8168_mdio_write(tp, 0x1D, 0x3D9C); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x12, 0xF49F); - rtl8168_mdio_write(tp, 0x13, 0x070B); - rtl8168_mdio_write(tp, 0x1A, 0x05AD); - rtl8168_mdio_write(tp, 0x14, 0x94C0); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x5561); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8332); - rtl8168_mdio_write(tp, 0x06, 0x5561); - - if (rtl8168_efuse_read(tp, 0x01) == 0xb1) { - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x05, 0x669A); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8330); - rtl8168_mdio_write(tp, 0x06, 0x669A); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0D); - if ((gphy_val & 0x00FF) != 0x006C) { - gphy_val &= 0xFF00; - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0065); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0066); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0067); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0068); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x0069); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x006A); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x006B); - rtl8168_mdio_write(tp, 0x0D, gphy_val | 0x006C); - } - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x05, 0x2642); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8330); - rtl8168_mdio_write(tp, 0x06, 0x2642); - } - - if (rtl8168_efuse_read(tp, 0x30) == 0x98) { - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) & ~BIT_1); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x01, rtl8168_mdio_read(tp, 0x01) | BIT_9); - } else if (rtl8168_efuse_read(tp, 0x30) == 0x90) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x01, rtl8168_mdio_read(tp, 0x01) & ~BIT_9); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x16, 0x5101); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x02); - gphy_val &= ~BIT_10; - gphy_val &= ~BIT_9; - gphy_val |= BIT_8; - rtl8168_mdio_write(tp, 0x02, gphy_val); - gphy_val = rtl8168_mdio_read(tp, 0x03); - gphy_val &= ~BIT_15; - gphy_val &= ~BIT_14; - gphy_val &= ~BIT_13; - rtl8168_mdio_write(tp, 0x03, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0F); - gphy_val |= BIT_4; - gphy_val |= BIT_2; - gphy_val |= BIT_1; - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x0F, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x001B); - if (rtl8168_mdio_read(tp, 0x06) == 0xB300) { - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x0080); - rtl8168_mdio_write(tp, 0x05, 0x8000); - rtl8168_mdio_write(tp, 0x06, 0xf8f9); - rtl8168_mdio_write(tp, 0x06, 0xfaee); - rtl8168_mdio_write(tp, 0x06, 0xf8ea); - rtl8168_mdio_write(tp, 0x06, 0x00ee); - rtl8168_mdio_write(tp, 0x06, 0xf8eb); - rtl8168_mdio_write(tp, 0x06, 0x00e2); - rtl8168_mdio_write(tp, 0x06, 0xf87c); - rtl8168_mdio_write(tp, 0x06, 0xe3f8); - rtl8168_mdio_write(tp, 0x06, 0x7da5); - rtl8168_mdio_write(tp, 0x06, 0x1111); - rtl8168_mdio_write(tp, 0x06, 0x12d2); - rtl8168_mdio_write(tp, 0x06, 0x40d6); - rtl8168_mdio_write(tp, 0x06, 0x4444); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xc6d2); - rtl8168_mdio_write(tp, 0x06, 0xa0d6); - rtl8168_mdio_write(tp, 0x06, 0xaaaa); - rtl8168_mdio_write(tp, 0x06, 0x0281); - rtl8168_mdio_write(tp, 0x06, 0xc6ae); - rtl8168_mdio_write(tp, 0x06, 0x0fa5); - rtl8168_mdio_write(tp, 0x06, 0x4444); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x4da5); - rtl8168_mdio_write(tp, 0x06, 0xaaaa); - rtl8168_mdio_write(tp, 0x06, 0x02ae); - rtl8168_mdio_write(tp, 0x06, 0x47af); - rtl8168_mdio_write(tp, 0x06, 0x81c2); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4e00); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4d0f); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4c0f); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4f00); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x5100); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4aff); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4bff); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x30e1); - rtl8168_mdio_write(tp, 0x06, 0x8331); - rtl8168_mdio_write(tp, 0x06, 0x58fe); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x8ae5); - rtl8168_mdio_write(tp, 0x06, 0xf88b); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x32e1); - rtl8168_mdio_write(tp, 0x06, 0x8333); - rtl8168_mdio_write(tp, 0x06, 0x590f); - rtl8168_mdio_write(tp, 0x06, 0xe283); - rtl8168_mdio_write(tp, 0x06, 0x4d0c); - rtl8168_mdio_write(tp, 0x06, 0x245a); - rtl8168_mdio_write(tp, 0x06, 0xf01e); - rtl8168_mdio_write(tp, 0x06, 0x12e4); - rtl8168_mdio_write(tp, 0x06, 0xf88c); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x8daf); - rtl8168_mdio_write(tp, 0x06, 0x81c2); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4f10); - rtl8168_mdio_write(tp, 0x06, 0xe483); - rtl8168_mdio_write(tp, 0x06, 0x4fe0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7800); - rtl8168_mdio_write(tp, 0x06, 0x9f0a); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4fa0); - rtl8168_mdio_write(tp, 0x06, 0x10a5); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4e01); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x059e); - rtl8168_mdio_write(tp, 0x06, 0x9ae0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7804); - rtl8168_mdio_write(tp, 0x06, 0x9e10); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x0fe0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7801); - rtl8168_mdio_write(tp, 0x06, 0x9e05); - rtl8168_mdio_write(tp, 0x06, 0xae0c); - rtl8168_mdio_write(tp, 0x06, 0xaf81); - rtl8168_mdio_write(tp, 0x06, 0xa7af); - rtl8168_mdio_write(tp, 0x06, 0x8152); - rtl8168_mdio_write(tp, 0x06, 0xaf81); - rtl8168_mdio_write(tp, 0x06, 0x8baf); - rtl8168_mdio_write(tp, 0x06, 0x81c2); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4800); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4900); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x5110); - rtl8168_mdio_write(tp, 0x06, 0xe483); - rtl8168_mdio_write(tp, 0x06, 0x5158); - rtl8168_mdio_write(tp, 0x06, 0x019f); - rtl8168_mdio_write(tp, 0x06, 0xead0); - rtl8168_mdio_write(tp, 0x06, 0x00d1); - rtl8168_mdio_write(tp, 0x06, 0x801f); - rtl8168_mdio_write(tp, 0x06, 0x66e2); - rtl8168_mdio_write(tp, 0x06, 0xf8ea); - rtl8168_mdio_write(tp, 0x06, 0xe3f8); - rtl8168_mdio_write(tp, 0x06, 0xeb5a); - rtl8168_mdio_write(tp, 0x06, 0xf81e); - rtl8168_mdio_write(tp, 0x06, 0x20e6); - rtl8168_mdio_write(tp, 0x06, 0xf8ea); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0xebd3); - rtl8168_mdio_write(tp, 0x06, 0x02b3); - rtl8168_mdio_write(tp, 0x06, 0xfee2); - rtl8168_mdio_write(tp, 0x06, 0xf87c); - rtl8168_mdio_write(tp, 0x06, 0xef32); - rtl8168_mdio_write(tp, 0x06, 0x5b80); - rtl8168_mdio_write(tp, 0x06, 0xe3f8); - rtl8168_mdio_write(tp, 0x06, 0x7d9e); - rtl8168_mdio_write(tp, 0x06, 0x037d); - rtl8168_mdio_write(tp, 0x06, 0xffff); - rtl8168_mdio_write(tp, 0x06, 0x0d58); - rtl8168_mdio_write(tp, 0x06, 0x1c55); - rtl8168_mdio_write(tp, 0x06, 0x1a65); - rtl8168_mdio_write(tp, 0x06, 0x11a1); - rtl8168_mdio_write(tp, 0x06, 0x90d3); - rtl8168_mdio_write(tp, 0x06, 0xe283); - rtl8168_mdio_write(tp, 0x06, 0x48e3); - rtl8168_mdio_write(tp, 0x06, 0x8349); - rtl8168_mdio_write(tp, 0x06, 0x1b56); - rtl8168_mdio_write(tp, 0x06, 0xab08); - rtl8168_mdio_write(tp, 0x06, 0xef56); - rtl8168_mdio_write(tp, 0x06, 0xe683); - rtl8168_mdio_write(tp, 0x06, 0x48e7); - rtl8168_mdio_write(tp, 0x06, 0x8349); - rtl8168_mdio_write(tp, 0x06, 0x10d1); - rtl8168_mdio_write(tp, 0x06, 0x801f); - rtl8168_mdio_write(tp, 0x06, 0x66a0); - rtl8168_mdio_write(tp, 0x06, 0x04b9); - rtl8168_mdio_write(tp, 0x06, 0xe283); - rtl8168_mdio_write(tp, 0x06, 0x48e3); - rtl8168_mdio_write(tp, 0x06, 0x8349); - rtl8168_mdio_write(tp, 0x06, 0xef65); - rtl8168_mdio_write(tp, 0x06, 0xe283); - rtl8168_mdio_write(tp, 0x06, 0x4ae3); - rtl8168_mdio_write(tp, 0x06, 0x834b); - rtl8168_mdio_write(tp, 0x06, 0x1b56); - rtl8168_mdio_write(tp, 0x06, 0xaa0e); - rtl8168_mdio_write(tp, 0x06, 0xef56); - rtl8168_mdio_write(tp, 0x06, 0xe683); - rtl8168_mdio_write(tp, 0x06, 0x4ae7); - rtl8168_mdio_write(tp, 0x06, 0x834b); - rtl8168_mdio_write(tp, 0x06, 0xe283); - rtl8168_mdio_write(tp, 0x06, 0x4de6); - rtl8168_mdio_write(tp, 0x06, 0x834c); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4da0); - rtl8168_mdio_write(tp, 0x06, 0x000c); - rtl8168_mdio_write(tp, 0x06, 0xaf81); - rtl8168_mdio_write(tp, 0x06, 0x8be0); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0x10e4); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0xae04); - rtl8168_mdio_write(tp, 0x06, 0x80e4); - rtl8168_mdio_write(tp, 0x06, 0x834d); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x4e78); - rtl8168_mdio_write(tp, 0x06, 0x039e); - rtl8168_mdio_write(tp, 0x06, 0x0be0); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x7804); - rtl8168_mdio_write(tp, 0x06, 0x9e04); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4e02); - rtl8168_mdio_write(tp, 0x06, 0xe083); - rtl8168_mdio_write(tp, 0x06, 0x32e1); - rtl8168_mdio_write(tp, 0x06, 0x8333); - rtl8168_mdio_write(tp, 0x06, 0x590f); - rtl8168_mdio_write(tp, 0x06, 0xe283); - rtl8168_mdio_write(tp, 0x06, 0x4d0c); - rtl8168_mdio_write(tp, 0x06, 0x245a); - rtl8168_mdio_write(tp, 0x06, 0xf01e); - rtl8168_mdio_write(tp, 0x06, 0x12e4); - rtl8168_mdio_write(tp, 0x06, 0xf88c); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x8de0); - rtl8168_mdio_write(tp, 0x06, 0x8330); - rtl8168_mdio_write(tp, 0x06, 0xe183); - rtl8168_mdio_write(tp, 0x06, 0x3168); - rtl8168_mdio_write(tp, 0x06, 0x01e4); - rtl8168_mdio_write(tp, 0x06, 0xf88a); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x8bae); - rtl8168_mdio_write(tp, 0x06, 0x37ee); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x03e0); - rtl8168_mdio_write(tp, 0x06, 0x834c); - rtl8168_mdio_write(tp, 0x06, 0xe183); - rtl8168_mdio_write(tp, 0x06, 0x4d1b); - rtl8168_mdio_write(tp, 0x06, 0x019e); - rtl8168_mdio_write(tp, 0x06, 0x04aa); - rtl8168_mdio_write(tp, 0x06, 0xa1ae); - rtl8168_mdio_write(tp, 0x06, 0xa8ee); - rtl8168_mdio_write(tp, 0x06, 0x834e); - rtl8168_mdio_write(tp, 0x06, 0x04ee); - rtl8168_mdio_write(tp, 0x06, 0x834f); - rtl8168_mdio_write(tp, 0x06, 0x00ae); - rtl8168_mdio_write(tp, 0x06, 0xabe0); - rtl8168_mdio_write(tp, 0x06, 0x834f); - rtl8168_mdio_write(tp, 0x06, 0x7803); - rtl8168_mdio_write(tp, 0x06, 0x9f14); - rtl8168_mdio_write(tp, 0x06, 0xee83); - rtl8168_mdio_write(tp, 0x06, 0x4e05); - rtl8168_mdio_write(tp, 0x06, 0xd240); - rtl8168_mdio_write(tp, 0x06, 0xd655); - rtl8168_mdio_write(tp, 0x06, 0x5402); - rtl8168_mdio_write(tp, 0x06, 0x81c6); - rtl8168_mdio_write(tp, 0x06, 0xd2a0); - rtl8168_mdio_write(tp, 0x06, 0xd6ba); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x81c6); - rtl8168_mdio_write(tp, 0x06, 0xfefd); - rtl8168_mdio_write(tp, 0x06, 0xfc05); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0xf860); - rtl8168_mdio_write(tp, 0x06, 0xe1f8); - rtl8168_mdio_write(tp, 0x06, 0x6168); - rtl8168_mdio_write(tp, 0x06, 0x02e4); - rtl8168_mdio_write(tp, 0x06, 0xf860); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x61e0); - rtl8168_mdio_write(tp, 0x06, 0xf848); - rtl8168_mdio_write(tp, 0x06, 0xe1f8); - rtl8168_mdio_write(tp, 0x06, 0x4958); - rtl8168_mdio_write(tp, 0x06, 0x0f1e); - rtl8168_mdio_write(tp, 0x06, 0x02e4); - rtl8168_mdio_write(tp, 0x06, 0xf848); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x49d0); - rtl8168_mdio_write(tp, 0x06, 0x0002); - rtl8168_mdio_write(tp, 0x06, 0x820a); - rtl8168_mdio_write(tp, 0x06, 0xbf83); - rtl8168_mdio_write(tp, 0x06, 0x50ef); - rtl8168_mdio_write(tp, 0x06, 0x46dc); - rtl8168_mdio_write(tp, 0x06, 0x19dd); - rtl8168_mdio_write(tp, 0x06, 0xd001); - rtl8168_mdio_write(tp, 0x06, 0x0282); - rtl8168_mdio_write(tp, 0x06, 0x0a02); - rtl8168_mdio_write(tp, 0x06, 0x8226); - rtl8168_mdio_write(tp, 0x06, 0xe0f8); - rtl8168_mdio_write(tp, 0x06, 0x60e1); - rtl8168_mdio_write(tp, 0x06, 0xf861); - rtl8168_mdio_write(tp, 0x06, 0x58fd); - rtl8168_mdio_write(tp, 0x06, 0xe4f8); - rtl8168_mdio_write(tp, 0x06, 0x60e5); - rtl8168_mdio_write(tp, 0x06, 0xf861); - rtl8168_mdio_write(tp, 0x06, 0xfc04); - rtl8168_mdio_write(tp, 0x06, 0xf9fa); - rtl8168_mdio_write(tp, 0x06, 0xfbc6); - rtl8168_mdio_write(tp, 0x06, 0xbff8); - rtl8168_mdio_write(tp, 0x06, 0x40be); - rtl8168_mdio_write(tp, 0x06, 0x8350); - rtl8168_mdio_write(tp, 0x06, 0xa001); - rtl8168_mdio_write(tp, 0x06, 0x0107); - rtl8168_mdio_write(tp, 0x06, 0x1b89); - rtl8168_mdio_write(tp, 0x06, 0xcfd2); - rtl8168_mdio_write(tp, 0x06, 0x08eb); - rtl8168_mdio_write(tp, 0x06, 0xdb19); - rtl8168_mdio_write(tp, 0x06, 0xb2fb); - rtl8168_mdio_write(tp, 0x06, 0xfffe); - rtl8168_mdio_write(tp, 0x06, 0xfd04); - rtl8168_mdio_write(tp, 0x06, 0xf8e0); - rtl8168_mdio_write(tp, 0x06, 0xf848); - rtl8168_mdio_write(tp, 0x06, 0xe1f8); - rtl8168_mdio_write(tp, 0x06, 0x4968); - rtl8168_mdio_write(tp, 0x06, 0x08e4); - rtl8168_mdio_write(tp, 0x06, 0xf848); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x4958); - rtl8168_mdio_write(tp, 0x06, 0xf7e4); - rtl8168_mdio_write(tp, 0x06, 0xf848); - rtl8168_mdio_write(tp, 0x06, 0xe5f8); - rtl8168_mdio_write(tp, 0x06, 0x49fc); - rtl8168_mdio_write(tp, 0x06, 0x044d); - rtl8168_mdio_write(tp, 0x06, 0x2000); - rtl8168_mdio_write(tp, 0x06, 0x024e); - rtl8168_mdio_write(tp, 0x06, 0x2200); - rtl8168_mdio_write(tp, 0x06, 0x024d); - rtl8168_mdio_write(tp, 0x06, 0xdfff); - rtl8168_mdio_write(tp, 0x06, 0x014e); - rtl8168_mdio_write(tp, 0x06, 0xddff); - rtl8168_mdio_write(tp, 0x06, 0x01f8); - rtl8168_mdio_write(tp, 0x06, 0xfafb); - rtl8168_mdio_write(tp, 0x06, 0xef79); - rtl8168_mdio_write(tp, 0x06, 0xbff8); - rtl8168_mdio_write(tp, 0x06, 0x22d8); - rtl8168_mdio_write(tp, 0x06, 0x19d9); - rtl8168_mdio_write(tp, 0x06, 0x5884); - rtl8168_mdio_write(tp, 0x06, 0x9f09); - rtl8168_mdio_write(tp, 0x06, 0xbf82); - rtl8168_mdio_write(tp, 0x06, 0x6dd6); - rtl8168_mdio_write(tp, 0x06, 0x8275); - rtl8168_mdio_write(tp, 0x06, 0x0201); - rtl8168_mdio_write(tp, 0x06, 0x4fef); - rtl8168_mdio_write(tp, 0x06, 0x97ff); - rtl8168_mdio_write(tp, 0x06, 0xfefc); - rtl8168_mdio_write(tp, 0x06, 0x0517); - rtl8168_mdio_write(tp, 0x06, 0xfffe); - rtl8168_mdio_write(tp, 0x06, 0x0117); - rtl8168_mdio_write(tp, 0x06, 0x0001); - rtl8168_mdio_write(tp, 0x06, 0x0200); - rtl8168_mdio_write(tp, 0x05, 0x83d8); - rtl8168_mdio_write(tp, 0x06, 0x8000); - rtl8168_mdio_write(tp, 0x05, 0x83d6); - rtl8168_mdio_write(tp, 0x06, 0x824f); - rtl8168_mdio_write(tp, 0x02, 0x2010); - rtl8168_mdio_write(tp, 0x03, 0xdc00); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x0b, 0x0600); - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0xfff6); - rtl8168_mdio_write(tp, 0x06, 0x00fc); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x0D, 0xF880); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_11) { - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x10, 0x0008); - rtl8168_mdio_write(tp, 0x0D, 0x006C); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0B, 0xA4D8); - rtl8168_mdio_write(tp, 0x09, 0x281C); - rtl8168_mdio_write(tp, 0x07, 0x2883); - rtl8168_mdio_write(tp, 0x0A, 0x6B35); - rtl8168_mdio_write(tp, 0x1D, 0x3DA4); - rtl8168_mdio_write(tp, 0x1C, 0xEFFD); - rtl8168_mdio_write(tp, 0x14, 0x7F52); - rtl8168_mdio_write(tp, 0x18, 0x7FC6); - rtl8168_mdio_write(tp, 0x08, 0x0601); - rtl8168_mdio_write(tp, 0x06, 0x4063); - rtl8168_mdio_write(tp, 0x10, 0xF074); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x13, 0x0789); - rtl8168_mdio_write(tp, 0x12, 0xF4BD); - rtl8168_mdio_write(tp, 0x1A, 0x04FD); - rtl8168_mdio_write(tp, 0x14, 0x84B0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x00, 0x9200); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x01, 0x0340); - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x04, 0x4000); - rtl8168_mdio_write(tp, 0x03, 0x1D21); - rtl8168_mdio_write(tp, 0x02, 0x0C32); - rtl8168_mdio_write(tp, 0x01, 0x0200); - rtl8168_mdio_write(tp, 0x00, 0x5554); - rtl8168_mdio_write(tp, 0x04, 0x4800); - rtl8168_mdio_write(tp, 0x04, 0x4000); - rtl8168_mdio_write(tp, 0x04, 0xF000); - rtl8168_mdio_write(tp, 0x03, 0xDF01); - rtl8168_mdio_write(tp, 0x02, 0xDF20); - rtl8168_mdio_write(tp, 0x01, 0x101A); - rtl8168_mdio_write(tp, 0x00, 0xA0FF); - rtl8168_mdio_write(tp, 0x04, 0xF800); - rtl8168_mdio_write(tp, 0x04, 0xF000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0023); - rtl8168_mdio_write(tp, 0x16, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - gphy_val = rtl8168_mdio_read(tp, 0x0D); - gphy_val |= BIT_5; - rtl8168_mdio_write(tp, 0x0D, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0C); - gphy_val |= BIT_10; - rtl8168_mdio_write(tp, 0x0C, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_12) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x17, 0x0CC0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x0D); - gphy_val |= BIT_5; - rtl8168_mdio_write(tp, 0x0D, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0C); - gphy_val |= BIT_10; - rtl8168_mdio_write(tp, 0x0C, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - rtl8168_mdio_write(tp, 0x15, 0x035D); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x01, 0x0300); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_13) { - rtl8168_mdio_write(tp, 0x1F, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x0D); - gphy_val |= BIT_5; - rtl8168_mdio_write(tp, 0x0D, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x0C); - gphy_val |= BIT_10; - rtl8168_mdio_write(tp, 0x0C, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_14 || tp->mcfg == CFG_METHOD_15) { - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0023); - gphy_val = rtl8168_mdio_read(tp, 0x17) | BIT_1; - if (tp->RequiredSecLanDonglePatch) - gphy_val &= ~(BIT_2); - else - gphy_val |= (BIT_2); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b80); - rtl8168_mdio_write(tp, 0x06, 0xc896); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0B, 0x6C20); - rtl8168_mdio_write(tp, 0x07, 0x2872); - rtl8168_mdio_write(tp, 0x1C, 0xEFFF); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x14, 0x6420); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - gphy_val = rtl8168_mdio_read(tp, 0x08) & 0x00FF; - rtl8168_mdio_write(tp, 0x08, gphy_val | 0x8000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - rtl8168_mdio_write(tp, 0x18, gphy_val | 0x0010); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x14); - rtl8168_mdio_write(tp, 0x14, gphy_val | 0x8000); - - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x00, 0x080B); - rtl8168_mdio_write(tp, 0x0B, 0x09D7); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x1006); - } - } - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x19, 0x7F46); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8AD2); - rtl8168_mdio_write(tp, 0x06, 0x6810); - rtl8168_mdio_write(tp, 0x05, 0x8AD4); - rtl8168_mdio_write(tp, 0x06, 0x8002); - rtl8168_mdio_write(tp, 0x05, 0x8ADE); - rtl8168_mdio_write(tp, 0x06, 0x8025); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002F); - rtl8168_mdio_write(tp, 0x15, 0x1919); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - rtl8168_mdio_write(tp, 0x18, gphy_val | 0x0040); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - rtl8168_mdio_write(tp, 0x06, gphy_val | 0x0001); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x00AC); - rtl8168_mdio_write(tp, 0x18, 0x0006); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_16) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_2 | BIT_1; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x18, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x14); - gphy_val |= BIT_15; - rtl8168_mdio_write(tp, 0x14, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x15, 0x1006); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0B, 0x6C14); - rtl8168_mdio_write(tp, 0x14, 0x7F3D); - rtl8168_mdio_write(tp, 0x1C, 0xFAFE); - rtl8168_mdio_write(tp, 0x08, 0x07C5); - rtl8168_mdio_write(tp, 0x10, 0xF090); - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x14, 0x641A); - rtl8168_mdio_write(tp, 0x1A, 0x0606); - rtl8168_mdio_write(tp, 0x12, 0xF480); - rtl8168_mdio_write(tp, 0x13, 0x0747); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0004); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0078); - rtl8168_mdio_write(tp, 0x15, 0xA408); - rtl8168_mdio_write(tp, 0x17, 0x5100); - rtl8168_mdio_write(tp, 0x19, 0x0008); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x0D, 0x0207); - rtl8168_mdio_write(tp, 0x02, 0x5FD0); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0004); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x00A1); - gphy_val = rtl8168_mdio_read(tp, 0x1A); - gphy_val &= ~BIT_2; - rtl8168_mdio_write(tp, 0x1A, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0004); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x16); - gphy_val |= BIT_5; - rtl8168_mdio_write(tp, 0x16, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0004); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x00AC); - rtl8168_mdio_write(tp, 0x18, 0x0006); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x09, 0xA20F); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B5B); - rtl8168_mdio_write(tp, 0x06, 0x9222); - rtl8168_mdio_write(tp, 0x05, 0x8B6D); - rtl8168_mdio_write(tp, 0x06, 0x8000); - rtl8168_mdio_write(tp, 0x05, 0x8B76); - rtl8168_mdio_write(tp, 0x06, 0x8000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (pdev->subsystem_vendor == 0x1043 && - pdev->subsystem_device == 0x13F7) { - - static const u16 evl_phy_value[] = { - 0x8B56, 0x8B5F, 0x8B68, 0x8B71, - 0x8B7A, 0x8A7B, 0x8A7E, 0x8A81, - 0x8A84, 0x8A87 - }; - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - for (i = 0; i < ARRAY_SIZE(evl_phy_value); i++) { - rtl8168_mdio_write(tp, 0x05, evl_phy_value[i]); - gphy_val = (0xAA << 8) | (rtl8168_mdio_read(tp, 0x06) & 0xFF); - rtl8168_mdio_write(tp, 0x06, gphy_val); - } - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0078); - rtl8168_mdio_write(tp, 0x17, 0x51AA); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B54); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8B5D); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8A7C); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A7F); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A82); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A88); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - gphy_val = rtl8168_mdio_read(tp, 0x06) | BIT_14 | BIT_15; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } else if (tp->mcfg == CFG_METHOD_17) { - if (pdev->subsystem_vendor == 0x144d && - pdev->subsystem_device == 0xc0a6) { - rtl8168_mdio_write(tp, 0x1F, 0x0001); - rtl8168_mdio_write(tp, 0x0e, 0x6b7f); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } else { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_2 | BIT_1; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val &= ~BIT_4; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0004); - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x18, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0002); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x14); - gphy_val |= BIT_15; - rtl8168_mdio_write(tp, 0x14, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0004); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x00AC); - rtl8168_mdio_write(tp, 0x18, 0x0006); - rtl8168_mdio_write(tp, 0x1F, 0x0002); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x09, 0xA20F); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - gphy_val = rtl8168_mdio_read(tp, 0x06) | BIT_14 | BIT_15; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B5B); - rtl8168_mdio_write(tp, 0x06, 0x9222); - rtl8168_mdio_write(tp, 0x05, 0x8B6D); - rtl8168_mdio_write(tp, 0x06, 0x8000); - rtl8168_mdio_write(tp, 0x05, 0x8B76); - rtl8168_mdio_write(tp, 0x06, 0x8000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (pdev->subsystem_vendor == 0x1043 && - pdev->subsystem_device == 0x13F7) { - - static const u16 evl_phy_value[] = { - 0x8B56, 0x8B5F, 0x8B68, 0x8B71, - 0x8B7A, 0x8A7B, 0x8A7E, 0x8A81, - 0x8A84, 0x8A87 - }; - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - for (i = 0; i < ARRAY_SIZE(evl_phy_value); i++) { - rtl8168_mdio_write(tp, 0x05, evl_phy_value[i]); - gphy_val = (0xAA << 8) | (rtl8168_mdio_read(tp, 0x06) & 0xFF); - rtl8168_mdio_write(tp, 0x06, gphy_val); - } - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0078); - rtl8168_mdio_write(tp, 0x17, 0x51AA); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B54); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8B5D); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8A7C); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A7F); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A82); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A88); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val |= BIT_12; - rtl8168_mdio_write(tp, 0x15, gphy_val); - } - } - } else if (tp->mcfg == CFG_METHOD_18) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_2 | BIT_1; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x18, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x14); - gphy_val |= BIT_15; - rtl8168_mdio_write(tp, 0x14, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_14; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x09, 0xA20F); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B55); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8B5E); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8B67); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8B70); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0078); - rtl8168_mdio_write(tp, 0x17, 0x0000); - rtl8168_mdio_write(tp, 0x19, 0x00FB); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B79); - rtl8168_mdio_write(tp, 0x06, 0xAA00); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0003); - rtl8168_mdio_write(tp, 0x01, 0x328A); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B54); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8B5D); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8A7C); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A7F); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A82); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A88); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_15); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val |= BIT_12; - rtl8168_mdio_write(tp, 0x15, gphy_val); - } - } - } else if (tp->mcfg == CFG_METHOD_19) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_2 | BIT_1; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x18, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x14); - gphy_val |= BIT_15; - rtl8168_mdio_write(tp, 0x14, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B54); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8B5D); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8A7C); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A7F); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A82); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A88); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_15); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val |= BIT_12; - rtl8168_mdio_write(tp, 0x15, gphy_val); - } - } - } else if (tp->mcfg == CFG_METHOD_20) { - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_2 | BIT_1; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - rtl8168_mdio_write(tp, 0x1f, 0x0007); - rtl8168_mdio_write(tp, 0x1e, 0x002D); - gphy_val = rtl8168_mdio_read(tp, 0x18); - gphy_val |= BIT_4; - rtl8168_mdio_write(tp, 0x18, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x14); - gphy_val |= BIT_15; - rtl8168_mdio_write(tp, 0x14, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B86); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_0; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B85); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_14; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0003); - rtl8168_mdio_write(tp, 0x09, 0xA20F); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B55); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8B5E); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8B67); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x05, 0x8B70); - rtl8168_mdio_write(tp, 0x06, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x0078); - rtl8168_mdio_write(tp, 0x17, 0x0000); - rtl8168_mdio_write(tp, 0x19, 0x00FB); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B79); - rtl8168_mdio_write(tp, 0x06, 0xAA00); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B54); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8B5D); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_11); - rtl8168_mdio_write(tp, 0x05, 0x8A7C); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A7F); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A82); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x05, 0x8A88); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8b85); - rtl8168_mdio_write(tp, 0x06, rtl8168_mdio_read(tp, 0x06) | BIT_15); - rtl8168_mdio_write(tp, 0x1f, 0x0000); - } - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1f, 0x0000); - gphy_val = rtl8168_mdio_read(tp, 0x15); - gphy_val |= BIT_12; - rtl8168_mdio_write(tp, 0x15, gphy_val); - } - } - } else if (tp->mcfg == CFG_METHOD_21) { - rtl8168_mdio_write(tp, 0x1F, 0x0A46); - gphy_val = rtl8168_mdio_read(tp, 0x10); - rtl8168_mdio_write(tp, 0x1F, 0x0BCC); - if (gphy_val & BIT_8) - rtl8168_clear_eth_phy_bit(tp, 0x12, BIT_15); - else - rtl8168_set_eth_phy_bit(tp, 0x12, BIT_15); - rtl8168_mdio_write(tp, 0x1F, 0x0A46); - gphy_val = rtl8168_mdio_read(tp, 0x13); - rtl8168_mdio_write(tp, 0x1F, 0x0C41); - if (gphy_val & BIT_8) - rtl8168_set_eth_phy_bit(tp, 0x15, BIT_1); - else - rtl8168_clear_eth_phy_bit(tp, 0x15, BIT_1); - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_2 | BIT_3); - - rtl8168_mdio_write(tp, 0x1F, 0x0BCC); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_7); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_6); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8084); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~(BIT_14 | BIT_13)); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_12); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_1); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_0); - - rtl8168_mdio_write(tp, 0x1F, 0x0A4B); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_2); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8012); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | BIT_15); - - rtl8168_mdio_write(tp, 0x1F, 0x0C42); - gphy_val = rtl8168_mdio_read(tp, 0x11); - gphy_val |= BIT_14; - gphy_val &= ~BIT_13; - rtl8168_mdio_write(tp, 0x11, gphy_val); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x809A); - rtl8168_mdio_write(tp, 0x14, 0x8022); - rtl8168_mdio_write(tp, 0x13, 0x80A0); - gphy_val = rtl8168_mdio_read(tp, 0x14) & 0x00FF; - gphy_val |= 0x1000; - rtl8168_mdio_write(tp, 0x14, gphy_val); - rtl8168_mdio_write(tp, 0x13, 0x8088); - rtl8168_mdio_write(tp, 0x14, 0x9222); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_2); - } - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_22) { - //do nothing - } else if (tp->mcfg == CFG_METHOD_23) { - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | (BIT_3 | BIT_2)); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0BCC); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_7); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_6); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8084); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~(BIT_14 | BIT_13)); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_12); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_1); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_0); - - rtl8168_mdio_write(tp, 0x1F, 0x0A4B); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_2); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8012); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | BIT_15); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0C42); - ClearAndSetEthPhyBit(tp, - 0x11, - BIT_13, - BIT_14 - ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_2); - } - } - } else if (tp->mcfg == CFG_METHOD_24) { - rtl8168_mdio_write(tp, 0x1F, 0x0BCC); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_7); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_6); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8084); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~(BIT_14 | BIT_13)); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_12); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_1); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_0); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8012); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | BIT_15); - - rtl8168_mdio_write(tp, 0x1F, 0x0C42); - gphy_val = rtl8168_mdio_read(tp, 0x11); - gphy_val |= BIT_14; - gphy_val &= ~BIT_13; - rtl8168_mdio_write(tp, 0x11, gphy_val); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_2); - } - } - } else if (tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26) { - rtl8168_mdio_write(tp, 0x1F, 0x0BCC); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_7); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_6); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8084); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~(BIT_14 | BIT_13)); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_12); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_1); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_0); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8012); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | BIT_15); - - rtl8168_mdio_write(tp, 0x1F, 0x0BCE); - rtl8168_mdio_write(tp, 0x12, 0x8860); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x80F3); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x8B00); - rtl8168_mdio_write(tp, 0x13, 0x80F0); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x3A00); - rtl8168_mdio_write(tp, 0x13, 0x80EF); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x0500); - rtl8168_mdio_write(tp, 0x13, 0x80F6); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x6E00); - rtl8168_mdio_write(tp, 0x13, 0x80EC); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x6800); - rtl8168_mdio_write(tp, 0x13, 0x80ED); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x7C00); - rtl8168_mdio_write(tp, 0x13, 0x80F2); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xF400); - rtl8168_mdio_write(tp, 0x13, 0x80F4); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x8500); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8110); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xA800); - rtl8168_mdio_write(tp, 0x13, 0x810F); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x1D00); - rtl8168_mdio_write(tp, 0x13, 0x8111); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xF500); - rtl8168_mdio_write(tp, 0x13, 0x8113); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x6100); - rtl8168_mdio_write(tp, 0x13, 0x8115); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x9200); - rtl8168_mdio_write(tp, 0x13, 0x810E); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x0400); - rtl8168_mdio_write(tp, 0x13, 0x810C); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x7C00); - rtl8168_mdio_write(tp, 0x13, 0x810B); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x5A00); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x80D1); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xFF00); - rtl8168_mdio_write(tp, 0x13, 0x80CD); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x9E00); - rtl8168_mdio_write(tp, 0x13, 0x80D3); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x0E00); - rtl8168_mdio_write(tp, 0x13, 0x80D5); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xCA00); - rtl8168_mdio_write(tp, 0x13, 0x80D7); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x8400); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_2); - } - } - } else if (tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28) { - rtl8168_mdio_write(tp, 0x1F, 0x0BCC); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~BIT_8); - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_7); - rtl8168_mdio_write(tp, 0x11, rtl8168_mdio_read(tp, 0x11) | BIT_6); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8084); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) & ~(BIT_14 | BIT_13)); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_12); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_1); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_0); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8012); - rtl8168_mdio_write(tp, 0x14, rtl8168_mdio_read(tp, 0x14) | BIT_15); - - rtl8168_mdio_write(tp, 0x1F, 0x0C42); - rtl8168_mdio_write(tp, 0x11, (rtl8168_mdio_read(tp, 0x11) & ~BIT_13) | BIT_14); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x80F3); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x8B00); - rtl8168_mdio_write(tp, 0x13, 0x80F0); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x3A00); - rtl8168_mdio_write(tp, 0x13, 0x80EF); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x0500); - rtl8168_mdio_write(tp, 0x13, 0x80F6); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x6E00); - rtl8168_mdio_write(tp, 0x13, 0x80EC); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x6800); - rtl8168_mdio_write(tp, 0x13, 0x80ED); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x7C00); - rtl8168_mdio_write(tp, 0x13, 0x80F2); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xF400); - rtl8168_mdio_write(tp, 0x13, 0x80F4); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x8500); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8110); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xA800); - rtl8168_mdio_write(tp, 0x13, 0x810F); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x1D00); - rtl8168_mdio_write(tp, 0x13, 0x8111); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xF500); - rtl8168_mdio_write(tp, 0x13, 0x8113); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x6100); - rtl8168_mdio_write(tp, 0x13, 0x8115); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x9200); - rtl8168_mdio_write(tp, 0x13, 0x810E); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x0400); - rtl8168_mdio_write(tp, 0x13, 0x810C); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x7C00); - rtl8168_mdio_write(tp, 0x13, 0x810B); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x5A00); - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x80D1); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xFF00); - rtl8168_mdio_write(tp, 0x13, 0x80CD); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x9E00); - rtl8168_mdio_write(tp, 0x13, 0x80D3); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x0E00); - rtl8168_mdio_write(tp, 0x13, 0x80D5); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0xCA00); - rtl8168_mdio_write(tp, 0x13, 0x80D7); - rtl8168_mdio_write(tp, 0x14, (rtl8168_mdio_read(tp, 0x14) & ~0xFF00) | 0x8400); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x10, rtl8168_mdio_read(tp, 0x10) | BIT_2); - } - } - } else if (tp->mcfg == CFG_METHOD_29) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x809b); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xF800 , - 0x8000 - ); - rtl8168_mdio_write(tp, 0x13, 0x80A2); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x8000 - ); - rtl8168_mdio_write(tp, 0x13, 0x80A4); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x8500 - ); - rtl8168_mdio_write(tp, 0x13, 0x809C); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0xbd00 - ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x80AD); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xF800 , - 0x7000 - ); - rtl8168_mdio_write(tp, 0x13, 0x80B4); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x5000 - ); - rtl8168_mdio_write(tp, 0x13, 0x80AC); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x4000 - ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x808E); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x1200 - ); - rtl8168_mdio_write(tp, 0x13, 0x8090); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0xE500 - ); - rtl8168_mdio_write(tp, 0x13, 0x8092); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x9F00 - ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - u16 dout_tapbin; - - dout_tapbin = 0x0000; - rtl8168_mdio_write( tp, 0x1F, 0x0A46 ); - gphy_val = rtl8168_mdio_read( tp, 0x13 ); - gphy_val &= (BIT_1|BIT_0); - gphy_val <<= 2; - dout_tapbin |= gphy_val; - - gphy_val = rtl8168_mdio_read( tp, 0x12 ); - gphy_val &= (BIT_15|BIT_14); - gphy_val >>= 14; - dout_tapbin |= gphy_val; - - dout_tapbin = ~( dout_tapbin^BIT_3 ); - dout_tapbin <<= 12; - dout_tapbin &= 0xF000; - - rtl8168_mdio_write( tp, 0x1F, 0x0A43 ); - - rtl8168_mdio_write( tp, 0x13, 0x827A ); - ClearAndSetEthPhyBit( tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_12, - dout_tapbin - ); - - - rtl8168_mdio_write( tp, 0x13, 0x827B ); - ClearAndSetEthPhyBit( tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_12, - dout_tapbin - ); - - - rtl8168_mdio_write( tp, 0x13, 0x827C ); - ClearAndSetEthPhyBit( tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_12, - dout_tapbin - ); - - - rtl8168_mdio_write( tp, 0x13, 0x827D ); - ClearAndSetEthPhyBit( tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_12, - dout_tapbin - ); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_11); - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - rtl8168_set_eth_phy_bit(tp, 0x16, BIT_1); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_set_eth_phy_bit( tp, 0x11, BIT_11 ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - - rtl8168_mdio_write(tp, 0x1F, 0x0BCA); - ClearAndSetEthPhyBit( tp, - 0x17, - (BIT_13 | BIT_12) , - BIT_14 - ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x803F); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x13, 0x8047); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x13, 0x804F); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x13, 0x8057); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x13, 0x805F); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x13, 0x8067 ); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x13, 0x806F ); - rtl8168_clear_eth_phy_bit( tp, 0x14, (BIT_13 | BIT_12)); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_set_eth_phy_bit( tp, 0x10, BIT_2 ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - } - } else if (tp->mcfg == CFG_METHOD_30) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x808A); - ClearAndSetEthPhyBit( tp, - 0x14, - BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0, - 0x0A ); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_11); - rtl8168_mdio_write(tp, 0x1F, 0x0A42); - rtl8168_set_eth_phy_bit(tp, 0x16, BIT_1); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_set_eth_phy_bit( tp, 0x11, BIT_11 ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (tp->RequireAdcBiasPatch) { - rtl8168_mdio_write(tp, 0x1F, 0x0BCF); - rtl8168_mdio_write(tp, 0x16, tp->AdcBiasPatchIoffset); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - { - u16 rlen; - - rtl8168_mdio_write(tp, 0x1F, 0x0BCD); - gphy_val = rtl8168_mdio_read( tp, 0x16 ); - gphy_val &= 0x000F; - - if ( gphy_val > 3 ) { - rlen = gphy_val - 3; - } else { - rlen = 0; - } - - gphy_val = rlen | (rlen<<4) | (rlen<<8) | (rlen<<12); - - rtl8168_mdio_write(tp, 0x1F, 0x0BCD); - rtl8168_mdio_write(tp, 0x17, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x85FE); - ClearAndSetEthPhyBit( - tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_12|BIT_11|BIT_10|BIT_8, - BIT_9); - rtl8168_mdio_write(tp, 0x13, 0x85FF); - ClearAndSetEthPhyBit( - tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_12, - BIT_11|BIT_10|BIT_9|BIT_8); - rtl8168_mdio_write(tp, 0x13, 0x814B); - ClearAndSetEthPhyBit( - tp, - 0x14, - BIT_15|BIT_14|BIT_13|BIT_11|BIT_10|BIT_9|BIT_8, - BIT_12); - } - - if (aspm) { - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_set_eth_phy_bit( tp, 0x10, BIT_2 ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - } - } else if (tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x808E); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x4800 - ); - rtl8168_mdio_write(tp, 0x13, 0x8090); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0xCC00 - ); - rtl8168_mdio_write(tp, 0x13, 0x8092); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0xB000 - ); - rtl8168_mdio_write(tp, 0x13, 0x8088); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x6000 - ); - rtl8168_mdio_write(tp, 0x13, 0x808B); - ClearAndSetEthPhyBit( tp, - 0x14, - 0x3F00 , - 0x0B00 - ); - rtl8168_mdio_write(tp, 0x13, 0x808D); - ClearAndSetEthPhyBit( tp, - 0x14, - 0x1F00 , - 0x0600 - ); - rtl8168_mdio_write(tp, 0x13, 0x808C); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0xB000 - ); - - rtl8168_mdio_write(tp, 0x13, 0x80A0); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x2800 - ); - rtl8168_mdio_write(tp, 0x13, 0x80A2); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x5000 - ); - rtl8168_mdio_write(tp, 0x13, 0x809B); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xF800 , - 0xB000 - ); - rtl8168_mdio_write(tp, 0x13, 0x809A); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x4B00 - ); - rtl8168_mdio_write(tp, 0x13, 0x809D); - ClearAndSetEthPhyBit( tp, - 0x14, - 0x3F00 , - 0x0800 - ); - rtl8168_mdio_write(tp, 0x13, 0x80A1); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x7000 - ); - rtl8168_mdio_write(tp, 0x13, 0x809F); - ClearAndSetEthPhyBit( tp, - 0x14, - 0x1F00 , - 0x0300 - ); - rtl8168_mdio_write(tp, 0x13, 0x809E); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x8800 - ); - - rtl8168_mdio_write(tp, 0x13, 0x80B2); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x2200 - ); - rtl8168_mdio_write(tp, 0x13, 0x80AD); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xF800 , - 0x9800 - ); - rtl8168_mdio_write(tp, 0x13, 0x80AF); - ClearAndSetEthPhyBit( tp, - 0x14, - 0x3F00 , - 0x0800 - ); - rtl8168_mdio_write(tp, 0x13, 0x80B3); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x6F00 - ); - rtl8168_mdio_write(tp, 0x13, 0x80B1); - ClearAndSetEthPhyBit( tp, - 0x14, - 0x1F00 , - 0x0300 - ); - rtl8168_mdio_write(tp, 0x13, 0x80B0); - ClearAndSetEthPhyBit( tp, - 0x14, - 0xFF00 , - 0x9300 - ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8011); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_11); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_set_eth_phy_bit(tp, 0x11, BIT_11); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_mdio_write(tp, 0x13, 0x8016); - rtl8168_set_eth_phy_bit(tp, 0x14, BIT_10); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (aspm) { - if (!HW_SUPP_SERDES_PHY(tp) && - HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - rtl8168_mdio_write(tp, 0x1F, 0x0A43); - rtl8168_set_eth_phy_bit( tp, 0x10, BIT_2 ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - } - } - -#ifdef ENABLE_FIBER_SUPPORT - if (HW_FIBER_MODE_ENABLED(tp)) - rtl8168_hw_fiber_phy_config(dev); -#endif //ENABLE_FIBER_SUPPORT - - //EthPhyPPSW - if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_24 || tp->mcfg == CFG_METHOD_25 || - tp->mcfg == CFG_METHOD_26) { - //disable EthPhyPPSW - rtl8168_mdio_write(tp, 0x1F, 0x0BCD); - rtl8168_mdio_write(tp, 0x14, 0x5065); - rtl8168_mdio_write(tp, 0x14, 0xD065); - rtl8168_mdio_write(tp, 0x1F, 0x0BC8); - rtl8168_mdio_write(tp, 0x11, 0x5655); - rtl8168_mdio_write(tp, 0x1F, 0x0BCD); - rtl8168_mdio_write(tp, 0x14, 0x1065); - rtl8168_mdio_write(tp, 0x14, 0x9065); - rtl8168_mdio_write(tp, 0x14, 0x1065); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } else if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - //enable EthPhyPPSW - rtl8168_mdio_write(tp, 0x1F, 0x0A44); - rtl8168_set_eth_phy_bit( tp, 0x11, BIT_7 ); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - - /*ocp phy power saving*/ - if (tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - if (aspm) - rtl8168_enable_ocp_phy_power_saving(dev); - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if (HW_HAS_WRITE_PHY_MCU_RAM_CODE(tp)) { - if (tp->eee_enabled) - rtl8168_enable_EEE(tp); - else - rtl8168_disable_EEE(tp); - } -} - -static inline void rtl8168_delete_esd_timer(struct net_device *dev, struct timer_list *timer) -{ - del_timer_sync(timer); -} - -static inline void rtl8168_request_esd_timer(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->esd_timer; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - setup_timer(timer, rtl8168_esd_timer, (unsigned long)dev); -#else - timer_setup(timer, rtl8168_esd_timer, 0); -#endif - mod_timer(timer, jiffies + RTL8168_ESD_TIMEOUT); -} - -static inline void rtl8168_delete_link_timer(struct net_device *dev, struct timer_list *timer) -{ - del_timer_sync(timer); -} - -static inline void rtl8168_request_link_timer(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->link_timer; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - setup_timer(timer, rtl8168_link_timer, (unsigned long)dev); -#else - timer_setup(timer, rtl8168_link_timer, 0); -#endif - mod_timer(timer, jiffies + RTL8168_LINK_TIMEOUT); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - * Polling 'interrupt' - used by things like netconsole to send skbs - * without having to re-enable interrupts. It's not called while - * the interrupt routine is executing. - */ -static void -rtl8168_netpoll(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - disable_irq(pdev->irq); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) - rtl8168_interrupt(pdev->irq, dev, NULL); -#else - rtl8168_interrupt(pdev->irq, dev); -#endif - enable_irq(pdev->irq); -} -#endif - -static void -rtl8168_get_bios_setting(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->bios_setting = RTL_R32(tp, 0x8c); - break; - } -} - -static void -rtl8168_set_bios_setting(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W32(tp, 0x8C, tp->bios_setting); - break; - } -} - -static void -rtl8168_init_software_variable(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - rtl8168_get_bios_setting(dev); - - switch (tp->mcfg) { - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - tp->HwSuppDashVer = 1; - break; - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - tp->HwSuppDashVer = 2; - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppDashVer = 3; - break; - default: - tp->HwSuppDashVer = 0; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwPkgDet = rtl8168_mac_ocp_read(tp, 0xDC00); - tp->HwPkgDet = (tp->HwPkgDet >> 3) & 0x0F; - break; - } - - if (HW_SUPP_SERDES_PHY(tp)) - eee_enable = 0; - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppNowIsOobVer = 1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppPhyOcpVer = 1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppUpsVer = 1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwPcieSNOffset = 0x16C; - break; - case CFG_METHOD_DEFAULT: - tp->HwPcieSNOffset = 0; - break; - default: - tp->HwPcieSNOffset = 0x164; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppAspmClkIntrLock = 1; - break; - } - - if (!aspm || !tp->HwSuppAspmClkIntrLock) - dynamic_aspm = 0; - -#ifdef ENABLE_REALWOW_SUPPORT - rtl8168_get_realwow_hw_version(dev); -#endif //ENABLE_REALWOW_SUPPORT - - if (HW_DASH_SUPPORT_DASH(tp) && rtl8168_check_dash(tp)) - tp->DASH = 1; - else - tp->DASH = 0; - - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_3(tp)) { - u64 CmacMemPhysAddress; - void __iomem *cmac_ioaddr = NULL; - struct pci_dev *pdev_cmac; - - pdev_cmac = pci_get_slot(pdev->bus, PCI_DEVFN(PCI_SLOT(pdev->devfn), 0)); - - //map CMAC IO space - CmacMemPhysAddress = pci_resource_start(pdev_cmac, 2); - - /* ioremap MMIO region */ - cmac_ioaddr = ioremap(CmacMemPhysAddress, R8168_REGS_SIZE); - - if (cmac_ioaddr == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap CMAC MMIO, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - tp->DASH = 0; - } else { - tp->mapped_cmac_ioaddr = cmac_ioaddr; - } - } - - eee_enable = 0; - } - -#ifdef ENABLE_DASH_SUPPORT -#ifdef ENABLE_DASH_PRINTER_SUPPORT - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_3(tp) && tp->HwPkgDet == 0x0F) - tp->dash_printer_enabled = 1; - else if (HW_DASH_SUPPORT_TYPE_2(tp)) - tp->dash_printer_enabled = 1; - } -#endif //ENABLE_DASH_PRINTER_SUPPORT -#endif //ENABLE_DASH_SUPPORT - - if (HW_DASH_SUPPORT_TYPE_2(tp)) - tp->cmac_ioaddr = tp->mmio_addr; - else if (HW_DASH_SUPPORT_TYPE_3(tp)) - tp->cmac_ioaddr = tp->mapped_cmac_ioaddr; - - switch (tp->mcfg) { - case CFG_METHOD_1: - tp->intr_mask = RxDescUnavail | RxFIFOOver | TxDescUnavail | TxOK | RxOK | SWInt; - tp->timer_intr_mask = PCSTimeout | RxFIFOOver; - break; - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - tp->intr_mask = RxDescUnavail | TxDescUnavail | TxOK | RxOK | SWInt; - tp->timer_intr_mask = PCSTimeout; - break; - default: - tp->intr_mask = RxDescUnavail | TxOK | RxOK | SWInt; - tp->timer_intr_mask = PCSTimeout; - break; - } - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) { - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - tp->timer_intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); - tp->intr_mask |= ( ISRIMR_DASH_INTR_EN | ISRIMR_DASH_INTR_CMAC_RESET); - } else { - tp->timer_intr_mask |= ( ISRIMR_DP_DASH_OK | ISRIMR_DP_HOST_OK | ISRIMR_DP_REQSYS_OK ); - tp->intr_mask |= ( ISRIMR_DP_DASH_OK | ISRIMR_DP_HOST_OK | ISRIMR_DP_REQSYS_OK ); - } - } -#endif - if (aspm) { - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->org_pci_offset_99 = rtl8168_csi_fun0_read_byte(tp, 0x99); - tp->org_pci_offset_99 &= ~(BIT_5|BIT_6); - break; - } - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - tp->org_pci_offset_180 = rtl8168_csi_fun0_read_byte(tp, 0x180); - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->org_pci_offset_180 = rtl8168_csi_fun0_read_byte(tp, 0x214); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_27: - case CFG_METHOD_28: - if (tp->org_pci_offset_99 & BIT_2) - tp->issue_offset_99_event = TRUE; - break; - } - } - - pci_read_config_byte(pdev, 0x80, &tp->org_pci_offset_80); - pci_read_config_byte(pdev, 0x81, &tp->org_pci_offset_81); - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - if ((tp->features & RTL_FEATURE_MSI) && (tp->org_pci_offset_80 & BIT_1)) - tp->use_timer_interrrupt = FALSE; - else - tp->use_timer_interrrupt = TRUE; - break; - default: - tp->use_timer_interrrupt = TRUE; - break; - } - - if (timer_count == 0 || tp->mcfg == CFG_METHOD_DEFAULT) - tp->use_timer_interrrupt = FALSE; - - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - tp->ShortPacketSwChecksum = TRUE; - break; - case CFG_METHOD_16: - case CFG_METHOD_17: - tp->ShortPacketSwChecksum = TRUE; - tp->UseSwPaddingShortPkt = TRUE; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_30: { - u16 ioffset_p3, ioffset_p2, ioffset_p1, ioffset_p0; - u16 TmpUshort; - - rtl8168_mac_ocp_write( tp, 0xDD02, 0x807D); - TmpUshort = rtl8168_mac_ocp_read( tp, 0xDD02 ); - ioffset_p3 = ( (TmpUshort & BIT_7) >>7 ); - ioffset_p3 <<= 3; - TmpUshort = rtl8168_mac_ocp_read( tp, 0xDD00 ); - - ioffset_p3 |= ((TmpUshort & (BIT_15 | BIT_14 | BIT_13))>>13); - - ioffset_p2 = ((TmpUshort & (BIT_12|BIT_11|BIT_10|BIT_9))>>9); - ioffset_p1 = ((TmpUshort & (BIT_8|BIT_7|BIT_6|BIT_5))>>5); - - ioffset_p0 = ( (TmpUshort & BIT_4) >>4 ); - ioffset_p0 <<= 3; - ioffset_p0 |= (TmpUshort & (BIT_2| BIT_1 | BIT_0)); - - if ((ioffset_p3 == 0x0F) && (ioffset_p2 == 0x0F) && (ioffset_p1 == 0x0F) && (ioffset_p0 == 0x0F)) { - tp->RequireAdcBiasPatch = FALSE; - } else { - tp->RequireAdcBiasPatch = TRUE; - tp->AdcBiasPatchIoffset = (ioffset_p3<<12)|(ioffset_p2<<8)|(ioffset_p1<<4)|(ioffset_p0); - } - } - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: { - u16 rg_saw_cnt; - - rtl8168_mdio_write(tp, 0x1F, 0x0C42); - rg_saw_cnt = rtl8168_mdio_read(tp, 0x13); - rg_saw_cnt &= ~(BIT_15|BIT_14); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - if ( rg_saw_cnt > 0) { - tp->SwrCnt1msIni = 16000000/rg_saw_cnt; - tp->SwrCnt1msIni &= 0x0FFF; - - tp->RequireAdjustUpsTxLinkPulseTiming = TRUE; - } - } - break; - } - -#ifdef ENABLE_FIBER_SUPPORT - rtl8168_check_hw_fiber_mode_support(dev); -#endif //ENABLE_FIBER_SUPPORT - - switch(tp->mcfg) { - case CFG_METHOD_32: - case CFG_METHOD_33: - if (tp->HwPkgDet == 0x06) { - u8 tmpUchar = rtl8168_eri_read(tp, 0xE6, 1, ERIAR_ExGMAC); - if (tmpUchar == 0x02) - tp->HwSuppSerDesPhyVer = 1; - else if (tmpUchar == 0x00) - tp->HwSuppSerDesPhyVer = 2; - } - break; - } - - if (pdev->subsystem_vendor == 0x144d) { - if (pdev->subsystem_device == 0xc098 || - pdev->subsystem_device == 0xc0b1 || - pdev->subsystem_device == 0xc0b8) - hwoptimize |= HW_PATCH_SAMSUNG_LAN_DONGLE; - } - - if (hwoptimize & HW_PATCH_SAMSUNG_LAN_DONGLE) { - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_30: - tp->RequiredSecLanDonglePatch = TRUE; - break; - } - } - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_V2; - break; - case CFG_METHOD_DEFAULT: - tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_NOT_SUPPORT; - break; - default: - tp->HwSuppMagicPktVer = WAKEUP_MAGIC_PACKET_V1; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_29: - case CFG_METHOD_30: - tp->HwSuppEsdVer = 2; - break; - default: - tp->HwSuppEsdVer = 1; - break; - } - - if (tp->HwSuppEsdVer == 2) { - rtl8168_mdio_write(tp, 0x1F, 0x0A46); - tp->BackupPhyFuseDout_15_0 = rtl8168_mdio_read(tp, 0x10); - tp->BackupPhyFuseDout_47_32 = rtl8168_mdio_read(tp, 0x12); - tp->BackupPhyFuseDout_63_48 = rtl8168_mdio_read(tp, 0x13); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - - tp->TestPhyOcpReg = TRUE; - } - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - tp->HwSuppCheckPhyDisableModeVer = 1; - break; - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_29: - case CFG_METHOD_30: - tp->HwSuppCheckPhyDisableModeVer = 2; - break; - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->HwSuppCheckPhyDisableModeVer = 3; - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_14; - break; - case CFG_METHOD_16: - case CFG_METHOD_17: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_16; - break; - case CFG_METHOD_18: - case CFG_METHOD_19: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_18; - break; - case CFG_METHOD_20: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_20; - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_21; - break; - case CFG_METHOD_23: - case CFG_METHOD_27: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_23; - break; - case CFG_METHOD_24: - case CFG_METHOD_25: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_24; - break; - case CFG_METHOD_26: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_26; - break; - case CFG_METHOD_28: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_28; - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_29; - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - tp->sw_ram_code_ver = NIC_RAMCODE_VERSION_CFG_METHOD_31; - break; - } - - if (tp->HwIcVerUnknown) { - tp->NotWrRamCodeToMicroP = TRUE; - tp->NotWrMcuPatchCode = TRUE; - } - - tp->NicCustLedValue = RTL_R16(tp, CustomLED); - - rtl8168_get_hw_wol(dev); - - rtl8168_link_option((u8*)&autoneg_mode, (u32*)&speed_mode, (u8*)&duplex_mode, (u32*)&advertising_mode); - - tp->autoneg = autoneg_mode; - tp->speed = speed_mode; - tp->duplex = duplex_mode; - tp->advertising = advertising_mode; - - tp->max_jumbo_frame_size = rtl_chip_info[tp->chipset].jumbo_frame_sz; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - /* MTU range: 60 - hw-specific max */ - dev->min_mtu = ETH_MIN_MTU; - dev->max_mtu = tp->max_jumbo_frame_size; -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - tp->eee_enabled = eee_enable; - tp->eee_adv_t = MDIO_EEE_1000T | MDIO_EEE_100TX; - -#ifdef ENABLE_FIBER_SUPPORT - if (HW_FIBER_MODE_ENABLED(tp)) - rtl8168_set_fiber_mode_software_variable(dev); -#endif //ENABLE_FIBER_SUPPORT -} - -static void -rtl8168_release_board(struct pci_dev *pdev, - struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - rtl8168_set_bios_setting(dev); - rtl8168_rar_set(tp, tp->org_mac_addr); - tp->wol_enabled = WOL_DISABLED; - - if (!tp->DASH) - rtl8168_phy_power_down(dev); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - FreeAllocatedDashShareMemory(dev); -#endif - - if (tp->mapped_cmac_ioaddr != NULL) - iounmap(tp->mapped_cmac_ioaddr); - - iounmap(ioaddr); - pci_release_regions(pdev); - pci_clear_mwi(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -static int -rtl8168_get_mac_address(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int i; - u8 mac_addr[MAC_ADDR_LEN]; - - for (i = 0; i < MAC_ADDR_LEN; i++) - mac_addr[i] = RTL_R8(tp, MAC0 + i); - - if (tp->mcfg == CFG_METHOD_18 || - tp->mcfg == CFG_METHOD_19 || - tp->mcfg == CFG_METHOD_20 || - tp->mcfg == CFG_METHOD_21 || - tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_23 || - tp->mcfg == CFG_METHOD_24 || - tp->mcfg == CFG_METHOD_25 || - tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || - tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || - tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || - tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - *(u32*)&mac_addr[0] = rtl8168_eri_read(tp, 0xE0, 4, ERIAR_ExGMAC); - *(u16*)&mac_addr[4] = rtl8168_eri_read(tp, 0xE4, 2, ERIAR_ExGMAC); - } else { - if (tp->eeprom_type != EEPROM_TYPE_NONE) { - u16 *pUshort = (u16*)mac_addr; - /* Get MAC address from EEPROM */ - if (tp->mcfg == CFG_METHOD_16 || - tp->mcfg == CFG_METHOD_17 || - tp->mcfg == CFG_METHOD_18 || - tp->mcfg == CFG_METHOD_19 || - tp->mcfg == CFG_METHOD_20 || - tp->mcfg == CFG_METHOD_21 || - tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_23 || - tp->mcfg == CFG_METHOD_24 || - tp->mcfg == CFG_METHOD_25 || - tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || - tp->mcfg == CFG_METHOD_28 || - tp->mcfg == CFG_METHOD_29 || - tp->mcfg == CFG_METHOD_30 || - tp->mcfg == CFG_METHOD_31 || - tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - *pUshort++ = rtl8168_eeprom_read_sc(tp, 1); - *pUshort++ = rtl8168_eeprom_read_sc(tp, 2); - *pUshort = rtl8168_eeprom_read_sc(tp, 3); - } else { - *pUshort++ = rtl8168_eeprom_read_sc(tp, 7); - *pUshort++ = rtl8168_eeprom_read_sc(tp, 8); - *pUshort = rtl8168_eeprom_read_sc(tp, 9); - } - } - } - - if (!is_valid_ether_addr(mac_addr)) { - netif_err(tp, probe, dev, "Invalid ether addr %pM\n", - mac_addr); - eth_hw_addr_random(dev); - ether_addr_copy(mac_addr, dev->dev_addr); - netif_info(tp, probe, dev, "Random ether addr %pM\n", - mac_addr); - tp->random_mac = 1; - } - - rtl8168_rar_set(tp, mac_addr); - - for (i = 0; i < MAC_ADDR_LEN; i++) { - dev->dev_addr[i] = RTL_R8(tp, MAC0 + i); - tp->org_mac_addr[i] = dev->dev_addr[i]; /* keep the original MAC address */ - } -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - memcpy(dev->perm_addr, dev->dev_addr, dev->addr_len); -#endif -// memcpy(dev->dev_addr, dev->dev_addr, dev->addr_len); - - return 0; -} - -/** - * rtl8168_set_mac_address - Change the Ethernet Address of the NIC - * @dev: network interface device structure - * @p: pointer to an address structure - * - * Return 0 on success, negative on failure - **/ -static int -rtl8168_set_mac_address(struct net_device *dev, - void *p) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - unsigned long flags; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - spin_lock_irqsave(&tp->lock, flags); - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl8168_rar_set(tp, dev->dev_addr); - - spin_unlock_irqrestore(&tp->lock, flags); - - return 0; -} - -/****************************************************************************** - * rtl8168_rar_set - Puts an ethernet address into a receive address register. - * - * tp - The private data structure for driver - * addr - Address to put into receive address register - *****************************************************************************/ -void -rtl8168_rar_set(struct rtl8168_private *tp, - uint8_t *addr) -{ - uint32_t rar_low = 0; - uint32_t rar_high = 0; - - rar_low = ((uint32_t) addr[0] | - ((uint32_t) addr[1] << 8) | - ((uint32_t) addr[2] << 16) | - ((uint32_t) addr[3] << 24)); - - rar_high = ((uint32_t) addr[4] | - ((uint32_t) addr[5] << 8)); - - rtl8168_enable_cfg9346_write(tp); - RTL_W32(tp, MAC0, rar_low); - RTL_W32(tp, MAC4, rar_high); - - switch (tp->mcfg) { - case CFG_METHOD_14: - case CFG_METHOD_15: - RTL_W32(tp, SecMAC0, rar_low); - RTL_W16(tp, SecMAC4, (uint16_t)rar_high); - break; - } - - if (tp->mcfg == CFG_METHOD_17) { - rtl8168_eri_write(tp, 0xf0, 4, rar_low << 16, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xf4, 4, rar_low >> 16 | rar_high << 16, ERIAR_ExGMAC); - } - - rtl8168_disable_cfg9346_write(tp); -} - -#ifdef ETHTOOL_OPS_COMPAT -static int ethtool_get_settings(struct net_device *dev, void *useraddr) -{ - struct ethtool_cmd cmd = { ETHTOOL_GSET }; - int err; - - if (!ethtool_ops->get_settings) - return -EOPNOTSUPP; - - err = ethtool_ops->get_settings(dev, &cmd); - if (err < 0) - return err; - - if (copy_to_user(useraddr, &cmd, sizeof(cmd))) - return -EFAULT; - return 0; -} - -static int ethtool_set_settings(struct net_device *dev, void *useraddr) -{ - struct ethtool_cmd cmd; - - if (!ethtool_ops->set_settings) - return -EOPNOTSUPP; - - if (copy_from_user(&cmd, useraddr, sizeof(cmd))) - return -EFAULT; - - return ethtool_ops->set_settings(dev, &cmd); -} - -static int ethtool_get_drvinfo(struct net_device *dev, void *useraddr) -{ - struct ethtool_drvinfo info; - struct ethtool_ops *ops = ethtool_ops; - - if (!ops->get_drvinfo) - return -EOPNOTSUPP; - - memset(&info, 0, sizeof(info)); - info.cmd = ETHTOOL_GDRVINFO; - ops->get_drvinfo(dev, &info); - - if (ops->self_test_count) - info.testinfo_len = ops->self_test_count(dev); - if (ops->get_stats_count) - info.n_stats = ops->get_stats_count(dev); - if (ops->get_regs_len) - info.regdump_len = ops->get_regs_len(dev); - if (ops->get_eeprom_len) - info.eedump_len = ops->get_eeprom_len(dev); - - if (copy_to_user(useraddr, &info, sizeof(info))) - return -EFAULT; - return 0; -} - -static int ethtool_get_regs(struct net_device *dev, char *useraddr) -{ - struct ethtool_regs regs; - struct ethtool_ops *ops = ethtool_ops; - void *regbuf; - int reglen, ret; - - if (!ops->get_regs || !ops->get_regs_len) - return -EOPNOTSUPP; - - if (copy_from_user(®s, useraddr, sizeof(regs))) - return -EFAULT; - - reglen = ops->get_regs_len(dev); - if (regs.len > reglen) - regs.len = reglen; - - regbuf = kmalloc(reglen, GFP_USER); - if (!regbuf) - return -ENOMEM; - - ops->get_regs(dev, ®s, regbuf); - - ret = -EFAULT; - if (copy_to_user(useraddr, ®s, sizeof(regs))) - goto out; - useraddr += offsetof(struct ethtool_regs, data); - if (copy_to_user(useraddr, regbuf, reglen)) - goto out; - ret = 0; - -out: - kfree(regbuf); - return ret; -} - -static int ethtool_get_wol(struct net_device *dev, char *useraddr) -{ - struct ethtool_wolinfo wol = { ETHTOOL_GWOL }; - - if (!ethtool_ops->get_wol) - return -EOPNOTSUPP; - - ethtool_ops->get_wol(dev, &wol); - - if (copy_to_user(useraddr, &wol, sizeof(wol))) - return -EFAULT; - return 0; -} - -static int ethtool_set_wol(struct net_device *dev, char *useraddr) -{ - struct ethtool_wolinfo wol; - - if (!ethtool_ops->set_wol) - return -EOPNOTSUPP; - - if (copy_from_user(&wol, useraddr, sizeof(wol))) - return -EFAULT; - - return ethtool_ops->set_wol(dev, &wol); -} - -static int ethtool_get_msglevel(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GMSGLVL }; - - if (!ethtool_ops->get_msglevel) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_msglevel(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_msglevel(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_msglevel) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - ethtool_ops->set_msglevel(dev, edata.data); - return 0; -} - -static int ethtool_nway_reset(struct net_device *dev) -{ - if (!ethtool_ops->nway_reset) - return -EOPNOTSUPP; - - return ethtool_ops->nway_reset(dev); -} - -static int ethtool_get_link(struct net_device *dev, void *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GLINK }; - - if (!ethtool_ops->get_link) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_link(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_get_eeprom(struct net_device *dev, void *useraddr) -{ - struct ethtool_eeprom eeprom; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->get_eeprom || !ops->get_eeprom_len) - return -EOPNOTSUPP; - - if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; - - /* Check for wrap and zero */ - if (eeprom.offset + eeprom.len <= eeprom.offset) - return -EINVAL; - - /* Check for exceeding total eeprom len */ - if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) - return -EINVAL; - - data = kmalloc(eeprom.len, GFP_USER); - if (!data) - return -ENOMEM; - - ret = -EFAULT; - if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) - goto out; - - ret = ops->get_eeprom(dev, &eeprom, data); - if (ret) - goto out; - - ret = -EFAULT; - if (copy_to_user(useraddr, &eeprom, sizeof(eeprom))) - goto out; - if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_set_eeprom(struct net_device *dev, void *useraddr) -{ - struct ethtool_eeprom eeprom; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->set_eeprom || !ops->get_eeprom_len) - return -EOPNOTSUPP; - - if (copy_from_user(&eeprom, useraddr, sizeof(eeprom))) - return -EFAULT; - - /* Check for wrap and zero */ - if (eeprom.offset + eeprom.len <= eeprom.offset) - return -EINVAL; - - /* Check for exceeding total eeprom len */ - if (eeprom.offset + eeprom.len > ops->get_eeprom_len(dev)) - return -EINVAL; - - data = kmalloc(eeprom.len, GFP_USER); - if (!data) - return -ENOMEM; - - ret = -EFAULT; - if (copy_from_user(data, useraddr + sizeof(eeprom), eeprom.len)) - goto out; - - ret = ops->set_eeprom(dev, &eeprom, data); - if (ret) - goto out; - - if (copy_to_user(useraddr + sizeof(eeprom), data, eeprom.len)) - ret = -EFAULT; - -out: - kfree(data); - return ret; -} - -static int ethtool_get_coalesce(struct net_device *dev, void *useraddr) -{ - struct ethtool_coalesce coalesce = { ETHTOOL_GCOALESCE }; - - if (!ethtool_ops->get_coalesce) - return -EOPNOTSUPP; - - ethtool_ops->get_coalesce(dev, &coalesce); - - if (copy_to_user(useraddr, &coalesce, sizeof(coalesce))) - return -EFAULT; - return 0; -} - -static int ethtool_set_coalesce(struct net_device *dev, void *useraddr) -{ - struct ethtool_coalesce coalesce; - - if (!ethtool_ops->get_coalesce) - return -EOPNOTSUPP; - - if (copy_from_user(&coalesce, useraddr, sizeof(coalesce))) - return -EFAULT; - - return ethtool_ops->set_coalesce(dev, &coalesce); -} - -static int ethtool_get_ringparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_ringparam ringparam = { ETHTOOL_GRINGPARAM }; - - if (!ethtool_ops->get_ringparam) - return -EOPNOTSUPP; - - ethtool_ops->get_ringparam(dev, &ringparam); - - if (copy_to_user(useraddr, &ringparam, sizeof(ringparam))) - return -EFAULT; - return 0; -} - -static int ethtool_set_ringparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_ringparam ringparam; - - if (!ethtool_ops->get_ringparam) - return -EOPNOTSUPP; - - if (copy_from_user(&ringparam, useraddr, sizeof(ringparam))) - return -EFAULT; - - return ethtool_ops->set_ringparam(dev, &ringparam); -} - -static int ethtool_get_pauseparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; - - if (!ethtool_ops->get_pauseparam) - return -EOPNOTSUPP; - - ethtool_ops->get_pauseparam(dev, &pauseparam); - - if (copy_to_user(useraddr, &pauseparam, sizeof(pauseparam))) - return -EFAULT; - return 0; -} - -static int ethtool_set_pauseparam(struct net_device *dev, void *useraddr) -{ - struct ethtool_pauseparam pauseparam; - - if (!ethtool_ops->get_pauseparam) - return -EOPNOTSUPP; - - if (copy_from_user(&pauseparam, useraddr, sizeof(pauseparam))) - return -EFAULT; - - return ethtool_ops->set_pauseparam(dev, &pauseparam); -} - -static int ethtool_get_rx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GRXCSUM }; - - if (!ethtool_ops->get_rx_csum) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_rx_csum(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_rx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_rx_csum) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - ethtool_ops->set_rx_csum(dev, edata.data); - return 0; -} - -static int ethtool_get_tx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GTXCSUM }; - - if (!ethtool_ops->get_tx_csum) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_tx_csum(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_tx_csum(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_tx_csum) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_tx_csum(dev, edata.data); -} - -static int ethtool_get_sg(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GSG }; - - if (!ethtool_ops->get_sg) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_sg(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_sg(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_sg) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_sg(dev, edata.data); -} - -static int ethtool_get_tso(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata = { ETHTOOL_GTSO }; - - if (!ethtool_ops->get_tso) - return -EOPNOTSUPP; - - edata.data = ethtool_ops->get_tso(dev); - - if (copy_to_user(useraddr, &edata, sizeof(edata))) - return -EFAULT; - return 0; -} - -static int ethtool_set_tso(struct net_device *dev, char *useraddr) -{ - struct ethtool_value edata; - - if (!ethtool_ops->set_tso) - return -EOPNOTSUPP; - - if (copy_from_user(&edata, useraddr, sizeof(edata))) - return -EFAULT; - - return ethtool_ops->set_tso(dev, edata.data); -} - -static int ethtool_self_test(struct net_device *dev, char *useraddr) -{ - struct ethtool_test test; - struct ethtool_ops *ops = ethtool_ops; - u64 *data; - int ret; - - if (!ops->self_test || !ops->self_test_count) - return -EOPNOTSUPP; - - if (copy_from_user(&test, useraddr, sizeof(test))) - return -EFAULT; - - test.len = ops->self_test_count(dev); - data = kmalloc(test.len * sizeof(u64), GFP_USER); - if (!data) - return -ENOMEM; - - ops->self_test(dev, &test, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &test, sizeof(test))) - goto out; - useraddr += sizeof(test); - if (copy_to_user(useraddr, data, test.len * sizeof(u64))) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_get_strings(struct net_device *dev, void *useraddr) -{ - struct ethtool_gstrings gstrings; - struct ethtool_ops *ops = ethtool_ops; - u8 *data; - int ret; - - if (!ops->get_strings) - return -EOPNOTSUPP; - - if (copy_from_user(&gstrings, useraddr, sizeof(gstrings))) - return -EFAULT; - - switch (gstrings.string_set) { - case ETH_SS_TEST: - if (!ops->self_test_count) - return -EOPNOTSUPP; - gstrings.len = ops->self_test_count(dev); - break; - case ETH_SS_STATS: - if (!ops->get_stats_count) - return -EOPNOTSUPP; - gstrings.len = ops->get_stats_count(dev); - break; - default: - return -EINVAL; - } - - data = kmalloc(gstrings.len * ETH_GSTRING_LEN, GFP_USER); - if (!data) - return -ENOMEM; - - ops->get_strings(dev, gstrings.string_set, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &gstrings, sizeof(gstrings))) - goto out; - useraddr += sizeof(gstrings); - if (copy_to_user(useraddr, data, gstrings.len * ETH_GSTRING_LEN)) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_phys_id(struct net_device *dev, void *useraddr) -{ - struct ethtool_value id; - - if (!ethtool_ops->phys_id) - return -EOPNOTSUPP; - - if (copy_from_user(&id, useraddr, sizeof(id))) - return -EFAULT; - - return ethtool_ops->phys_id(dev, id.data); -} - -static int ethtool_get_stats(struct net_device *dev, void *useraddr) -{ - struct ethtool_stats stats; - struct ethtool_ops *ops = ethtool_ops; - u64 *data; - int ret; - - if (!ops->get_ethtool_stats || !ops->get_stats_count) - return -EOPNOTSUPP; - - if (copy_from_user(&stats, useraddr, sizeof(stats))) - return -EFAULT; - - stats.n_stats = ops->get_stats_count(dev); - data = kmalloc(stats.n_stats * sizeof(u64), GFP_USER); - if (!data) - return -ENOMEM; - - ops->get_ethtool_stats(dev, &stats, data); - - ret = -EFAULT; - if (copy_to_user(useraddr, &stats, sizeof(stats))) - goto out; - useraddr += sizeof(stats); - if (copy_to_user(useraddr, data, stats.n_stats * sizeof(u64))) - goto out; - ret = 0; - -out: - kfree(data); - return ret; -} - -static int ethtool_ioctl(struct ifreq *ifr) -{ - struct net_device *dev = __dev_get_by_name(ifr->ifr_name); - void *useraddr = (void *) ifr->ifr_data; - u32 ethcmd; - - /* - * XXX: This can be pushed down into the ethtool_* handlers that - * need it. Keep existing behaviour for the moment. - */ - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (!dev || !netif_device_present(dev)) - return -ENODEV; - - if (copy_from_user(ðcmd, useraddr, sizeof (ethcmd))) - return -EFAULT; - - switch (ethcmd) { - case ETHTOOL_GSET: - return ethtool_get_settings(dev, useraddr); - case ETHTOOL_SSET: - return ethtool_set_settings(dev, useraddr); - case ETHTOOL_GDRVINFO: - return ethtool_get_drvinfo(dev, useraddr); - case ETHTOOL_GREGS: - return ethtool_get_regs(dev, useraddr); - case ETHTOOL_GWOL: - return ethtool_get_wol(dev, useraddr); - case ETHTOOL_SWOL: - return ethtool_set_wol(dev, useraddr); - case ETHTOOL_GMSGLVL: - return ethtool_get_msglevel(dev, useraddr); - case ETHTOOL_SMSGLVL: - return ethtool_set_msglevel(dev, useraddr); - case ETHTOOL_NWAY_RST: - return ethtool_nway_reset(dev); - case ETHTOOL_GLINK: - return ethtool_get_link(dev, useraddr); - case ETHTOOL_GEEPROM: - return ethtool_get_eeprom(dev, useraddr); - case ETHTOOL_SEEPROM: - return ethtool_set_eeprom(dev, useraddr); - case ETHTOOL_GCOALESCE: - return ethtool_get_coalesce(dev, useraddr); - case ETHTOOL_SCOALESCE: - return ethtool_set_coalesce(dev, useraddr); - case ETHTOOL_GRINGPARAM: - return ethtool_get_ringparam(dev, useraddr); - case ETHTOOL_SRINGPARAM: - return ethtool_set_ringparam(dev, useraddr); - case ETHTOOL_GPAUSEPARAM: - return ethtool_get_pauseparam(dev, useraddr); - case ETHTOOL_SPAUSEPARAM: - return ethtool_set_pauseparam(dev, useraddr); - case ETHTOOL_GRXCSUM: - return ethtool_get_rx_csum(dev, useraddr); - case ETHTOOL_SRXCSUM: - return ethtool_set_rx_csum(dev, useraddr); - case ETHTOOL_GTXCSUM: - return ethtool_get_tx_csum(dev, useraddr); - case ETHTOOL_STXCSUM: - return ethtool_set_tx_csum(dev, useraddr); - case ETHTOOL_GSG: - return ethtool_get_sg(dev, useraddr); - case ETHTOOL_SSG: - return ethtool_set_sg(dev, useraddr); - case ETHTOOL_GTSO: - return ethtool_get_tso(dev, useraddr); - case ETHTOOL_STSO: - return ethtool_set_tso(dev, useraddr); - case ETHTOOL_TEST: - return ethtool_self_test(dev, useraddr); - case ETHTOOL_GSTRINGS: - return ethtool_get_strings(dev, useraddr); - case ETHTOOL_PHYS_ID: - return ethtool_phys_id(dev, useraddr); - case ETHTOOL_GSTATS: - return ethtool_get_stats(dev, useraddr); - default: - return -EOPNOTSUPP; - } - - return -EOPNOTSUPP; -} -#endif //ETHTOOL_OPS_COMPAT - -static int -rtl8168_do_ioctl(struct net_device *dev, - struct ifreq *ifr, - int cmd) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - int ret; - unsigned long flags; - - ret = 0; - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - break; - - case SIOCGMIIREG: - spin_lock_irqsave(&tp->lock, flags); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - data->val_out = rtl8168_mdio_read(tp, data->reg_num); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case SIOCSMIIREG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - spin_lock_irqsave(&tp->lock, flags); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - rtl8168_mdio_write(tp, data->reg_num, data->val_in); - spin_unlock_irqrestore(&tp->lock, flags); - break; - -#ifdef ETHTOOL_OPS_COMPAT - case SIOCETHTOOL: - ret = ethtool_ioctl(ifr); - break; -#endif - case SIOCDEVPRIVATE_RTLASF: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - - ret = rtl8168_asf_ioctl(dev, ifr); - break; - -#ifdef ENABLE_DASH_SUPPORT - case SIOCDEVPRIVATE_RTLDASH: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - if (!capable(CAP_NET_ADMIN)) { - ret = -EPERM; - break; - } - - ret = rtl8168_dash_ioctl(dev, ifr); - break; -#endif - -#ifdef ENABLE_REALWOW_SUPPORT - case SIOCDEVPRIVATE_RTLREALWOW: - if (!netif_running(dev)) { - ret = -ENODEV; - break; - } - - ret = rtl8168_realwow_ioctl(dev, ifr); - break; -#endif - - case SIOCRTLTOOL: - ret = rtl8168_tool_ioctl(tp, ifr); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} - -static void -rtl8168_phy_power_up(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (rtl8168_is_in_phy_disable_mode(dev)) - return; - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - case CFG_METHOD_8: - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - rtl8168_mdio_write(tp, 0x0E, 0x0000); - break; - } - rtl8168_mdio_write(tp, MII_BMCR, BMCR_ANENABLE); - - //wait mdc/mdio ready - switch (tp->mcfg) { - case CFG_METHOD_23: - case CFG_METHOD_27: - case CFG_METHOD_28: - mdelay(10); - break; - } - - //wait ups resume (phy state 3) - if (HW_SUPPORT_UPS_MODE(tp)) - rtl8168_wait_phy_ups_resume(dev, HW_PHY_STATUS_LAN_ON); -} - -static void -rtl8168_phy_power_down(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 csi_tmp; - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - csi_tmp = rtl8168_eri_read(tp, 0x1AB, 1, ERIAR_ExGMAC); - csi_tmp &= ~( BIT_2 | BIT_3 | BIT_4 | BIT_5 | BIT_6 | BIT_7 ); - rtl8168_eri_write(tp, 0x1AB, 1, csi_tmp, ERIAR_ExGMAC); - break; - } - - rtl8168_mdio_write(tp, 0x1F, 0x0000); - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - case CFG_METHOD_8: - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - rtl8168_mdio_write(tp, 0x0E, 0x0200); - rtl8168_mdio_write(tp, MII_BMCR, BMCR_PDOWN); - break; - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_29: - case CFG_METHOD_30: - rtl8168_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); - break; - case CFG_METHOD_21: - case CFG_METHOD_22: - rtl8168_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); - break; - case CFG_METHOD_23: - case CFG_METHOD_24: - rtl8168_mdio_write(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); - break; - default: - rtl8168_mdio_write(tp, MII_BMCR, BMCR_PDOWN); - break; - } -} - -static int __devinit -rtl8168_init_board(struct pci_dev *pdev, - struct net_device **dev_out, - void __iomem **ioaddr_out) -{ - void __iomem *ioaddr; - struct net_device *dev; - struct rtl8168_private *tp; - int rc = -ENOMEM, i, pm_cap; - - assert(ioaddr_out != NULL); - - /* dev zeroed in alloc_etherdev */ - dev = alloc_etherdev(sizeof (*tp)); - if (dev == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_drv(&debug)) - dev_err(&pdev->dev, "unable to alloc new ethernet\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out; - } - - SET_MODULE_OWNER(dev); - SET_NETDEV_DEV(dev, &pdev->dev); - tp = netdev_priv(dev); - tp->dev = dev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8168_MSG_DEFAULT); - - if (!aspm || tp->mcfg == CFG_METHOD_9) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26) - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | - PCIE_LINK_STATE_CLKPM); -#endif - } - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "enable failure\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_free_dev; - } - - if (pci_set_mwi(pdev) < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_drv(&debug)) - dev_info(&pdev->dev, "Mem-Wr-Inval unavailable.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - } - - /* save power state before pci_enable_device overwrites it */ - pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); - if (pm_cap) { - u16 pwr_command; - - pci_read_config_word(pdev, pm_cap + PCI_PM_CTRL, &pwr_command); - } else { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) { - dev_err(&pdev->dev, "PowerManagement capability not found.\n"); - } -#else - printk("PowerManagement capability not found.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - - } - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, 2) & IORESOURCE_MEM)) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "region #1 not an MMIO resource, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -ENODEV; - goto err_out_mwi; - } - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, 2) < R8168_REGS_SIZE) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "Invalid PCI region size(s), aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -ENODEV; - goto err_out_mwi; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "could not request regions.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_mwi; - } - - if ((sizeof(dma_addr_t) > 4) && - use_dac && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && - !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) { - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "DMA configuration failed.\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - goto err_out_free_res; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, 2), R8168_REGS_SIZE); - if (ioaddr == NULL) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_err(&pdev->dev, "cannot remap MMIO, aborting\n"); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - rc = -EIO; - goto err_out_free_res; - } - - tp->mmio_addr = ioaddr; - - /* Identify chip attached to board */ - rtl8168_get_mac_version(tp); - - rtl8168_print_mac_version(tp); - - for (i = ARRAY_SIZE(rtl_chip_info) - 1; i >= 0; i--) { - if (tp->mcfg == rtl_chip_info[i].mcfg) - break; - } - - if (i < 0) { - /* Unknown chip: assume array element #0, original RTL-8168 */ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (netif_msg_probe(tp)) - dev_printk(KERN_DEBUG, &pdev->dev, "unknown chip version, assuming %s\n", rtl_chip_info[0].name); -#else - printk("Realtek unknown chip version, assuming %s\n", rtl_chip_info[0].name); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0) - i++; - } - - tp->chipset = i; - - *ioaddr_out = ioaddr; - *dev_out = dev; -out: - return rc; - -err_out_free_res: - pci_release_regions(pdev); -err_out_mwi: - pci_clear_mwi(pdev); - pci_disable_device(pdev); -err_out_free_dev: - free_netdev(dev); -err_out: - *ioaddr_out = NULL; - *dev_out = NULL; - goto out; -} - -static void -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -rtl8168_esd_timer(unsigned long __opaque) -#else -rtl8168_esd_timer(struct timer_list *t) -#endif -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8168_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->esd_timer; -#else - struct rtl8168_private *tp = from_timer(tp, t, esd_timer); - struct net_device *dev = tp->dev; - struct timer_list *timer = t; -#endif - struct pci_dev *pdev = tp->pci_dev; - unsigned long timeout = RTL8168_ESD_TIMEOUT; - unsigned long flags; - u8 cmd; - u16 io_base_l; - u16 mem_base_l; - u16 mem_base_h; - u8 ilr; - u16 resv_0x1c_h; - u16 resv_0x1c_l; - u16 resv_0x20_l; - u16 resv_0x20_h; - u16 resv_0x24_l; - u16 resv_0x24_h; - u16 resv_0x2c_h; - u16 resv_0x2c_l; - u32 pci_sn_l; - u32 pci_sn_h; - - spin_lock_irqsave(&tp->lock, flags); - - tp->esd_flag = 0; - - pci_read_config_byte(pdev, PCI_COMMAND, &cmd); - if (cmd != tp->pci_cfg_space.cmd) { - printk(KERN_ERR "%s: cmd = 0x%02x, should be 0x%02x \n.", dev->name, cmd, tp->pci_cfg_space.cmd); - pci_write_config_byte(pdev, PCI_COMMAND, tp->pci_cfg_space.cmd); - tp->esd_flag |= BIT_0; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &io_base_l); - if (io_base_l != tp->pci_cfg_space.io_base_l) { - printk(KERN_ERR "%s: io_base_l = 0x%04x, should be 0x%04x \n.", dev->name, io_base_l, tp->pci_cfg_space.io_base_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_0, tp->pci_cfg_space.io_base_l); - tp->esd_flag |= BIT_1; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &mem_base_l); - if (mem_base_l != tp->pci_cfg_space.mem_base_l) { - printk(KERN_ERR "%s: mem_base_l = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_l, tp->pci_cfg_space.mem_base_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_2, tp->pci_cfg_space.mem_base_l); - tp->esd_flag |= BIT_2; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &mem_base_h); - if (mem_base_h!= tp->pci_cfg_space.mem_base_h) { - printk(KERN_ERR "%s: mem_base_h = 0x%04x, should be 0x%04x \n.", dev->name, mem_base_h, tp->pci_cfg_space.mem_base_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, tp->pci_cfg_space.mem_base_h); - tp->esd_flag |= BIT_3; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &resv_0x1c_l); - if (resv_0x1c_l != tp->pci_cfg_space.resv_0x1c_l) { - printk(KERN_ERR "%s: resv_0x1c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_l, tp->pci_cfg_space.resv_0x1c_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_3, tp->pci_cfg_space.resv_0x1c_l); - tp->esd_flag |= BIT_4; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &resv_0x1c_h); - if (resv_0x1c_h != tp->pci_cfg_space.resv_0x1c_h) { - printk(KERN_ERR "%s: resv_0x1c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x1c_h, tp->pci_cfg_space.resv_0x1c_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, tp->pci_cfg_space.resv_0x1c_h); - tp->esd_flag |= BIT_5; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &resv_0x20_l); - if (resv_0x20_l != tp->pci_cfg_space.resv_0x20_l) { - printk(KERN_ERR "%s: resv_0x20_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_l, tp->pci_cfg_space.resv_0x20_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_4, tp->pci_cfg_space.resv_0x20_l); - tp->esd_flag |= BIT_6; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &resv_0x20_h); - if (resv_0x20_h != tp->pci_cfg_space.resv_0x20_h) { - printk(KERN_ERR "%s: resv_0x20_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x20_h, tp->pci_cfg_space.resv_0x20_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, tp->pci_cfg_space.resv_0x20_h); - tp->esd_flag |= BIT_7; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &resv_0x24_l); - if (resv_0x24_l != tp->pci_cfg_space.resv_0x24_l) { - printk(KERN_ERR "%s: resv_0x24_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_l, tp->pci_cfg_space.resv_0x24_l); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_5, tp->pci_cfg_space.resv_0x24_l); - tp->esd_flag |= BIT_8; - } - - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &resv_0x24_h); - if (resv_0x24_h != tp->pci_cfg_space.resv_0x24_h) { - printk(KERN_ERR "%s: resv_0x24_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x24_h, tp->pci_cfg_space.resv_0x24_h); - pci_write_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, tp->pci_cfg_space.resv_0x24_h); - tp->esd_flag |= BIT_9; - } - - pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &ilr); - if (ilr != tp->pci_cfg_space.ilr) { - printk(KERN_ERR "%s: ilr = 0x%02x, should be 0x%02x \n.", dev->name, ilr, tp->pci_cfg_space.ilr); - pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, tp->pci_cfg_space.ilr); - tp->esd_flag |= BIT_10; - } - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &resv_0x2c_l); - if (resv_0x2c_l != tp->pci_cfg_space.resv_0x2c_l) { - printk(KERN_ERR "%s: resv_0x2c_l = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_l, tp->pci_cfg_space.resv_0x2c_l); - pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, tp->pci_cfg_space.resv_0x2c_l); - tp->esd_flag |= BIT_11; - } - - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &resv_0x2c_h); - if (resv_0x2c_h != tp->pci_cfg_space.resv_0x2c_h) { - printk(KERN_ERR "%s: resv_0x2c_h = 0x%04x, should be 0x%04x \n.", dev->name, resv_0x2c_h, tp->pci_cfg_space.resv_0x2c_h); - pci_write_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, tp->pci_cfg_space.resv_0x2c_h); - tp->esd_flag |= BIT_12; - } - - if (tp->HwPcieSNOffset > 0) { - pci_sn_l = rtl8168_csi_read(tp, tp->HwPcieSNOffset); - if (pci_sn_l != tp->pci_cfg_space.pci_sn_l) { - printk(KERN_ERR "%s: pci_sn_l = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_l, tp->pci_cfg_space.pci_sn_l); - rtl8168_csi_write(tp, tp->HwPcieSNOffset, tp->pci_cfg_space.pci_sn_l); - tp->esd_flag |= BIT_13; - } - - pci_sn_h = rtl8168_csi_read(tp, tp->HwPcieSNOffset + 4); - if (pci_sn_h != tp->pci_cfg_space.pci_sn_h) { - printk(KERN_ERR "%s: pci_sn_h = 0x%08x, should be 0x%08x \n.", dev->name, pci_sn_h, tp->pci_cfg_space.pci_sn_h); - rtl8168_csi_write(tp, tp->HwPcieSNOffset + 4, tp->pci_cfg_space.pci_sn_h); - tp->esd_flag |= BIT_14; - } - } - - if (tp->TestPhyOcpReg && rtl8168_test_phy_ocp(tp)) - tp->esd_flag |= BIT_15; - - if (tp->esd_flag != 0) { - printk(KERN_ERR "%s: esd_flag = 0x%04x\n.\n", dev->name, tp->esd_flag); - netif_stop_queue(dev); - netif_carrier_off(dev); - rtl8168_hw_reset(dev); - rtl8168_tx_clear(tp); - rtl8168_rx_clear(tp); - rtl8168_init_ring(dev); - rtl8168_hw_init(dev); - rtl8168_powerup_pll(dev); - rtl8168_hw_ephy_config(dev); - rtl8168_hw_phy_config(dev); - rtl8168_hw_config(dev); - rtl8168_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - tp->esd_flag = 0; - } - spin_unlock_irqrestore(&tp->lock, flags); - - mod_timer(timer, jiffies + timeout); -} - -static void -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) -rtl8168_link_timer(unsigned long __opaque) -#else -rtl8168_link_timer(struct timer_list *t) -#endif -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,14,0) - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8168_private *tp = netdev_priv(dev); - struct timer_list *timer = &tp->link_timer; -#else - struct rtl8168_private *tp = from_timer(tp, t, link_timer); - struct net_device *dev = tp->dev; - struct timer_list *timer = t; -#endif - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_check_link_status(dev); - spin_unlock_irqrestore(&tp->lock, flags); - - mod_timer(timer, jiffies + RTL8168_LINK_TIMEOUT); -} - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl8168_try_msi(struct pci_dev *pdev, struct rtl8168_private *tp) -{ - unsigned msi = 0; - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - switch (tp->mcfg) { - case CFG_METHOD_1: - case CFG_METHOD_2: - case CFG_METHOD_3: - case CFG_METHOD_4: - case CFG_METHOD_5: - case CFG_METHOD_6: - case CFG_METHOD_7: - case CFG_METHOD_8: - dev_info(&pdev->dev, "Default use INTx.\n"); - break; - default: - if (pci_enable_msi(pdev)) - dev_info(&pdev->dev, "no MSI. Back to INTx.\n"); - else - msi |= RTL_FEATURE_MSI; - break; - } -#endif - - return msi; -} - -static void rtl8168_disable_msi(struct pci_dev *pdev, struct rtl8168_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,13) - pci_disable_msi(pdev); -#endif - tp->features &= ~RTL_FEATURE_MSI; - } -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,29) -static const struct net_device_ops rtl8168_netdev_ops = { - .ndo_open = rtl8168_open, - .ndo_stop = rtl8168_close, - .ndo_get_stats = rtl8168_get_stats, - .ndo_start_xmit = rtl8168_start_xmit, - .ndo_tx_timeout = rtl8168_tx_timeout, - .ndo_change_mtu = rtl8168_change_mtu, - .ndo_set_mac_address = rtl8168_set_mac_address, - .ndo_do_ioctl = rtl8168_do_ioctl, -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,1,0) - .ndo_set_multicast_list = rtl8168_set_rx_mode, -#else - .ndo_set_rx_mode = rtl8168_set_rx_mode, -#endif -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) -#ifdef CONFIG_R8168_VLAN - .ndo_vlan_rx_register = rtl8168_vlan_rx_register, -#endif -#else - .ndo_fix_features = rtl8168_fix_features, - .ndo_set_features = rtl8168_set_features, -#endif -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8168_netpoll, -#endif -}; -#endif - -static int __devinit -rtl8168_init_one(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct net_device *dev = NULL; - struct rtl8168_private *tp; - void __iomem *ioaddr = NULL; - static int board_idx = -1; - - int rc; - - assert(pdev != NULL); - assert(ent != NULL); - - board_idx++; - - if (netif_msg_drv(&debug)) - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8168_VERSION); - - rc = rtl8168_init_board(pdev, &dev, &ioaddr); - if (rc) - goto out; - - tp = netdev_priv(dev); - assert(ioaddr != NULL); - - tp->set_speed = rtl8168_set_speed_xmii; - tp->get_settings = rtl8168_gset_xmii; - tp->phy_reset_enable = rtl8168_xmii_reset_enable; - tp->phy_reset_pending = rtl8168_xmii_reset_pending; - tp->link_ok = rtl8168_xmii_link_ok; - - tp->features |= rtl8168_try_msi(pdev, tp); - - RTL_NET_DEVICE_OPS(rtl8168_netdev_ops); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,4,22) - SET_ETHTOOL_OPS(dev, &rtl8168_ethtool_ops); -#endif - - dev->watchdog_timeo = RTL8168_TX_TIMEOUT; - dev->irq = pdev->irq; - dev->base_addr = (unsigned long) ioaddr; - -#ifdef CONFIG_R8168_NAPI - RTL_NAPI_CONFIG(dev, tp, rtl8168_poll, R8168_NAPI_WEIGHT); -#endif - -#ifdef CONFIG_R8168_VLAN - if (tp->mcfg != CFG_METHOD_DEFAULT) { - dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - dev->vlan_rx_kill_vid = rtl8168_vlan_rx_kill_vid; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - } -#endif - - /* There has been a number of reports that using SG/TSO results in - * tx timeouts. However for a lot of people SG/TSO works fine. - * Therefore disable both features by default, but allow users to - * enable them. Use at own risk! - */ - tp->cp_cmd |= RTL_R16(tp, CPlusCmd); - if (tp->mcfg != CFG_METHOD_DEFAULT) { - dev->features |= NETIF_F_IP_CSUM; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - tp->cp_cmd |= RxChkSum; -#else - dev->features |= NETIF_F_RXCSUM; - dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | - NETIF_F_RXCSUM | NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX; - dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | - NETIF_F_HIGHDMA; - if ((tp->mcfg != CFG_METHOD_16) && (tp->mcfg != CFG_METHOD_17)) { - //dev->features |= NETIF_F_TSO; - dev->hw_features |= NETIF_F_TSO; - dev->vlan_features |= NETIF_F_TSO; - } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) - dev->priv_flags |= IFF_LIVE_ADDR_CHANGE; -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,15,0) - dev->hw_features |= NETIF_F_RXALL; - dev->hw_features |= NETIF_F_RXFCS; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - if ((tp->mcfg == CFG_METHOD_1) || (tp->mcfg == CFG_METHOD_2) || (tp->mcfg == CFG_METHOD_3)) { - dev->hw_features &= ~NETIF_F_IPV6_CSUM; - netif_set_gso_max_size(dev, LSO_32K); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - dev->gso_max_segs = NIC_MAX_PHYS_BUF_COUNT_LSO_64K; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) - dev->gso_min_segs = NIC_MIN_PHYS_BUF_COUNT; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - } else { - dev->hw_features |= NETIF_F_IPV6_CSUM; - dev->features |= NETIF_F_IPV6_CSUM; - if ((tp->mcfg != CFG_METHOD_16) && (tp->mcfg != CFG_METHOD_17)) { - dev->hw_features |= NETIF_F_TSO6; - //dev->features |= NETIF_F_TSO6; - } - netif_set_gso_max_size(dev, LSO_64K); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - dev->gso_max_segs = NIC_MAX_PHYS_BUF_COUNT_LSO2; -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) - dev->gso_min_segs = NIC_MIN_PHYS_BUF_COUNT; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,7,0) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,18,0) - } -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - } - - tp->pci_dev = pdev; - - spin_lock_init(&tp->lock); - - rtl8168_init_software_variable(dev); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH) - AllocateDashShareMemory(dev); -#endif - - rtl8168_exit_oob(dev); - - rtl8168_hw_init(dev); - - rtl8168_hw_reset(dev); - - /* Get production from EEPROM */ - if (((tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_29 || - tp->mcfg == CFG_METHOD_30) && (rtl8168_mac_ocp_read(tp, 0xDC00) & BIT_3)) || - ((tp->mcfg == CFG_METHOD_26) && (rtl8168_mac_ocp_read(tp, 0xDC00) & BIT_4))) - tp->eeprom_type = EEPROM_TYPE_NONE; - else - rtl8168_eeprom_type(tp); - - if (tp->eeprom_type == EEPROM_TYPE_93C46 || tp->eeprom_type == EEPROM_TYPE_93C56) - rtl8168_set_eeprom_sel_low(tp); - - rtl8168_get_mac_address(dev); - - tp->fw_name = rtl_chip_fw_infos[tp->mcfg].fw_name; - -#if defined(ENABLE_DASH_PRINTER_SUPPORT) - init_completion(&tp->fw_host_ok); - init_completion(&tp->fw_ack); - init_completion(&tp->fw_req); -#endif - - tp->tally_vaddr = dma_alloc_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), - &tp->tally_paddr, GFP_KERNEL); - if (!tp->tally_vaddr) { - rc = -ENOMEM; - goto err_out; - } - - rtl8168_tally_counter_clear(tp); - - pci_set_drvdata(pdev, dev); - - rc = register_netdev(dev); - if (rc) - goto err_out; - - printk(KERN_INFO "%s: This product is covered by one or more of the following patents: US6,570,884, US6,115,776, and US6,327,625.\n", MODULENAME); - - rtl8168_disable_rxdvgate(dev); - - device_set_wakeup_enable(&pdev->dev, tp->wol_enabled); - - netif_carrier_off(dev); - - printk("%s", GPL_CLAIM); - -out: - return rc; - -err_out: - if (tp->tally_vaddr != NULL) { - dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, - tp->tally_paddr); - - tp->tally_vaddr = NULL; - } -#ifdef CONFIG_R8168_NAPI - RTL_NAPI_DEL(tp); -#endif - rtl8168_disable_msi(pdev, tp); - rtl8168_release_board(pdev, dev); - - goto out; -} - -static void __devexit -rtl8168_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8168_private *tp = netdev_priv(dev); - - assert(dev != NULL); - assert(tp != NULL); - -#ifdef CONFIG_R8168_NAPI - RTL_NAPI_DEL(tp); -#endif - if (HW_DASH_SUPPORT_DASH(tp)) - rtl8168_driver_stop(tp); - - unregister_netdev(dev); - rtl8168_disable_msi(pdev, tp); -#ifdef ENABLE_R8168_PROCFS - rtl8168_proc_remove(dev); -#endif - if (tp->tally_vaddr != NULL) { - dma_free_coherent(&pdev->dev, sizeof(*tp->tally_vaddr), tp->tally_vaddr, tp->tally_paddr); - tp->tally_vaddr = NULL; - } - - rtl8168_release_board(pdev, dev); - -#ifdef ENABLE_USE_FIRMWARE_FILE - rtl8168_release_firmware(tp); -#endif - - pci_set_drvdata(pdev, NULL); -} - -static void -rtl8168_set_rxbufsize(struct rtl8168_private *tp, - struct net_device *dev) -{ - unsigned int mtu = dev->mtu; - - tp->rx_buf_sz = (mtu > ETH_DATA_LEN) ? mtu + ETH_HLEN + 8 + 1 : RX_BUF_SIZE; -} - -#ifdef ENABLE_USE_FIRMWARE_FILE -static void rtl8168_request_firmware(struct rtl8168_private *tp) -{ - struct rtl8168_fw *rtl_fw; - - /* firmware loaded already or no firmware available */ - if (tp->rtl_fw || !tp->fw_name) - return; - - rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL); - if (!rtl_fw) - return; - - rtl_fw->phy_write = rtl8168_mdio_write; - rtl_fw->phy_read = rtl8168_mdio_read; - rtl_fw->mac_mcu_write = mac_mcu_write; - rtl_fw->mac_mcu_read = mac_mcu_read; - rtl_fw->fw_name = tp->fw_name; - rtl_fw->dev = tp_to_dev(tp); - - if (rtl8168_fw_request_firmware(rtl_fw)) - kfree(rtl_fw); - else - tp->rtl_fw = rtl_fw; -} -#endif - -static int rtl8168_open(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - unsigned long flags; - int retval; - - retval = -ENOMEM; - -#ifdef ENABLE_R8168_PROCFS - rtl8168_proc_init(dev); -#endif - rtl8168_set_rxbufsize(tp, dev); - /* - * Rx and Tx descriptors needs 256 bytes alignment. - * pci_alloc_consistent provides more. - */ - tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8168_TX_RING_BYTES, - &tp->TxPhyAddr, GFP_KERNEL); - if (!tp->TxDescArray) - goto err_free_all_allocated_mem; - - tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8168_RX_RING_BYTES, - &tp->RxPhyAddr, GFP_KERNEL); - if (!tp->RxDescArray) - goto err_free_all_allocated_mem; - - retval = rtl8168_init_ring(dev); - if (retval < 0) - goto err_free_all_allocated_mem; - - retval = request_irq(dev->irq, rtl8168_interrupt, (tp->features & RTL_FEATURE_MSI) ? 0 : SA_SHIRQ, dev->name, dev); - if (retval<0) - goto err_free_all_allocated_mem; - - if (netif_msg_probe(tp)) { - printk(KERN_INFO "%s: 0x%lx, " - "%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x, " - "IRQ %d\n", - dev->name, - dev->base_addr, - dev->dev_addr[0], dev->dev_addr[1], - dev->dev_addr[2], dev->dev_addr[3], - dev->dev_addr[4], dev->dev_addr[5], dev->irq); - } - -#ifdef ENABLE_USE_FIRMWARE_FILE - rtl8168_request_firmware(tp); -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - INIT_WORK(&tp->task, rtl8168_reset_task, dev); -#else - INIT_DELAYED_WORK(&tp->task, rtl8168_reset_task); -#endif - - pci_set_master(pdev); - -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - RTL_NAPI_ENABLE(dev, &tp->napi); -#endif -#endif - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_exit_oob(dev); - - rtl8168_hw_init(dev); - - rtl8168_hw_reset(dev); - - rtl8168_powerup_pll(dev); - - rtl8168_hw_ephy_config(dev); - - rtl8168_hw_phy_config(dev); - - rtl8168_hw_config(dev); - - rtl8168_dsm(dev, DSM_IF_UP); - - rtl8168_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - - spin_unlock_irqrestore(&tp->lock, flags); - - if (tp->esd_flag == 0) - rtl8168_request_esd_timer(dev); - - rtl8168_request_link_timer(dev); - -out: - - return retval; - -err_free_all_allocated_mem: - if (tp->RxDescArray != NULL) { - dma_free_coherent(&pdev->dev, R8168_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - tp->RxDescArray = NULL; - } - - if (tp->TxDescArray != NULL) { - dma_free_coherent(&pdev->dev, R8168_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - } - - goto out; -} - -static void -rtl8168_dsm(struct net_device *dev, int dev_state) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - switch (dev_state) { - case DSM_MAC_INIT: - if ((tp->mcfg == CFG_METHOD_5) || (tp->mcfg == CFG_METHOD_6)) { - if (RTL_R8(tp, MACDBG) & 0x80) - RTL_W8(tp, GPIO, RTL_R8(tp, GPIO) | GPIO_en); - else - RTL_W8(tp, GPIO, RTL_R8(tp, GPIO) & ~GPIO_en); - } - - break; - case DSM_NIC_GOTO_D3: - case DSM_IF_DOWN: - if ((tp->mcfg == CFG_METHOD_5) || (tp->mcfg == CFG_METHOD_6)) { - if (RTL_R8(tp, MACDBG) & 0x80) - RTL_W8(tp, GPIO, RTL_R8(tp, GPIO) & ~GPIO_en); - } - break; - - case DSM_NIC_RESUME_D3: - case DSM_IF_UP: - if ((tp->mcfg == CFG_METHOD_5) || (tp->mcfg == CFG_METHOD_6)) { - if (RTL_R8(tp, MACDBG) & 0x80) - RTL_W8(tp, GPIO, RTL_R8(tp, GPIO) | GPIO_en); - } - - break; - } - -} - -static void -set_offset70F(struct rtl8168_private *tp, u8 setting) -{ - u32 csi_tmp; - u32 temp = (u32)setting; - temp = temp << 24; - /*set PCI configuration space offset 0x70F to setting*/ - /*When the register offset of PCI configuration space larger than 0xff, use CSI to access it.*/ - - csi_tmp = rtl8168_csi_read(tp, 0x70c) & 0x00ffffff; - rtl8168_csi_write(tp, 0x70c, csi_tmp | temp); -} - -static void -set_offset79(struct rtl8168_private *tp, u8 setting) -{ - //Set PCI configuration space offset 0x79 to setting - - struct pci_dev *pdev = tp->pci_dev; - u8 device_control; - - if (hwoptimize & HW_PATCH_SOC_LAN) return; - - pci_read_config_byte(pdev, 0x79, &device_control); - device_control &= ~0x70; - device_control |= setting; - pci_write_config_byte(pdev, 0x79, device_control); -} - -static void -set_offset711(struct rtl8168_private *tp, u8 setting) -{ - u32 csi_tmp; - u32 temp = (u32)setting; - temp &= 0x0f; - temp = temp << 12; - /*set PCI configuration space offset 0x711 to setting*/ - - csi_tmp = rtl8168_csi_read(tp, 0x710) & 0xffff0fff; - rtl8168_csi_write(tp, 0x710, csi_tmp | temp); -} - -static void -rtl8168_hw_set_rx_packet_filter(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - if (netif_msg_link(tp)) - printk(KERN_NOTICE "%s: Promiscuous mode enabled.\n", - dev->name); - - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) - || (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,35) - struct dev_mc_list *mclist; - unsigned int i; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count; - i++, mclist = mclist->next) { - int bit_nr = ether_crc(ETH_ALEN, mclist->dmi_addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } -#else - struct netdev_hw_addr *ha; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } -#endif - } - - if (dev->features & NETIF_F_RXALL) - rx_mode |= (AcceptErr | AcceptRunt); - - tmp = mc_filter[0]; - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(tmp); - - tp->rtl8168_rx_config = rtl_chip_info[tp->chipset].RCR_Cfg; - tmp = tp->rtl8168_rx_config | rx_mode | (RTL_R32(tp, RxConfig) & rtl_chip_info[tp->chipset].RxConfigMask); - - RTL_W32(tp, RxConfig, tmp); - RTL_W32(tp, MAR0 + 0, mc_filter[0]); - RTL_W32(tp, MAR0 + 4, mc_filter[1]); -} - -static void -rtl8168_set_rx_mode(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_hw_set_rx_packet_filter(dev); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -static void -rtl8168_hw_config(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - u8 device_control; - u16 mac_ocp_data; - u32 csi_tmp; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - if (dev->mtu > ETH_DATA_LEN) { - dev->features &= ~(NETIF_F_IP_CSUM); - } else { - dev->features |= NETIF_F_IP_CSUM; - } -#endif - - RTL_W32(tp, RxConfig, (RX_DMA_BURST << RxCfgDMAShift)); - - rtl8168_hw_reset(dev); - - rtl8168_enable_cfg9346_write(tp); - if (tp->HwSuppAspmClkIntrLock) { - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) & ~BIT_7); - rtl8168_hw_aspm_clkreq_enable(tp, false); - } - - //clear io_rdy_l23 - switch (tp->mcfg) { - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~BIT_1); - break; - } - - //keep magic packet only - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - csi_tmp = rtl8168_eri_read(tp, 0xDE, 1, ERIAR_ExGMAC); - csi_tmp &= BIT_0; - rtl8168_eri_write(tp, 0xDE, 1, csi_tmp, ERIAR_ExGMAC); - break; - } - - RTL_W8(tp, MTPS, Reserved1_data); - - tp->cp_cmd |= INTT_1; - if (tp->use_timer_interrrupt) - tp->cp_cmd |= PktCntrDisable; - else - tp->cp_cmd &= ~PktCntrDisable; - - RTL_W16(tp, IntrMitigate, 0x5f51); - - rtl8168_tally_counter_addr_fill(tp); - - rtl8168_desc_addr_fill(tp); - - /* Set DMA burst size and Interframe Gap Time */ - if (tp->mcfg == CFG_METHOD_1) - RTL_W32(tp, TxConfig, (TX_DMA_BURST_512 << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - else - RTL_W32(tp, TxConfig, (TX_DMA_BURST_unlimited << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); - - if (tp->mcfg == CFG_METHOD_4) { - set_offset70F(tp, 0x27); - - RTL_W8(tp, DBG_reg, (0x0E << 4) | Fix_Nak_1 | Fix_Nak_2); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - //disable clock request. - pci_write_config_byte(pdev, 0x81, 0x00); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - set_offset79(tp, 0x50); - } - - //rx checksum offload enable -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - tp->cp_cmd |= RxChkSum; -#else - dev->features |= NETIF_F_RXCSUM; -#endif - - tp->cp_cmd &= ~(EnableBist | Macdbgo_oe | Force_halfdup | - Force_rxflow_en | Force_txflow_en | Cxpl_dbg_sel | - ASF | PktCntrDisable | Macdbgo_sel); - } else if (tp->mcfg == CFG_METHOD_5) { - - set_offset70F(tp, 0x27); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - //disable clock request. - pci_write_config_byte(pdev, 0x81, 0x00); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - set_offset79(tp, 0x50); - } - - //rx checksum offload enable -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - tp->cp_cmd |= RxChkSum; -#else - dev->features |= NETIF_F_RXCSUM; -#endif - } else if (tp->mcfg == CFG_METHOD_6) { - set_offset70F(tp, 0x27); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - //disable clock request. - pci_write_config_byte(pdev, 0x81, 0x00); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - set_offset79(tp, 0x50); - } - - //rx checksum offload enable -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - tp->cp_cmd |= RxChkSum; -#else - dev->features |= NETIF_F_RXCSUM; -#endif - } else if (tp->mcfg == CFG_METHOD_7) { - set_offset70F(tp, 0x27); - - rtl8168_eri_write(tp, 0x1EC, 1, 0x07, ERIAR_ASF); - - //disable clock request. - pci_write_config_byte(pdev, 0x81, 0x00); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - - set_offset79(tp, 0x50); - } - } else if (tp->mcfg == CFG_METHOD_8) { - - set_offset70F(tp, 0x27); - - rtl8168_eri_write(tp, 0x1EC, 1, 0x07, ERIAR_ASF); - - //disable clock request. - pci_write_config_byte(pdev, 0x81, 0x00); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - RTL_W8(tp, 0xD1, 0x20); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - set_offset79(tp, 0x50); - } - } else if (tp->mcfg == CFG_METHOD_9) { - set_offset70F(tp, 0x27); - - /* disable clock request. */ - pci_write_config_byte(pdev, 0x81, 0x00); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~BIT_4); - RTL_W8(tp, DBG_reg, RTL_R8(tp, DBG_reg) | BIT_7 | BIT_1); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - set_offset79(tp, 0x50); - } - - RTL_W8(tp, TDFNR, 0x8); - - } else if (tp->mcfg == CFG_METHOD_10) { - set_offset70F(tp, 0x27); - - RTL_W8(tp, DBG_reg, RTL_R8(tp, DBG_reg) | BIT_7 | BIT_1); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | Jumbo_En1); - - set_offset79(tp, 0x20); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~Jumbo_En1); - - set_offset79(tp, 0x50); - } - - RTL_W8(tp, TDFNR, 0x8); - - RTL_W8(tp, Config1, RTL_R8(tp, Config1) | 0x10); - - /* disable clock request. */ - pci_write_config_byte(pdev, 0x81, 0x00); - } else if (tp->mcfg == CFG_METHOD_11 || tp->mcfg == CFG_METHOD_13) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - else - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - - pci_write_config_byte(pdev, 0x81, 0x00); - - RTL_W8(tp, Config1, RTL_R8(tp, Config1) | 0x10); - - } else if (tp->mcfg == CFG_METHOD_12) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - else - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - - pci_write_config_byte(pdev, 0x81, 0x01); - - RTL_W8(tp, Config1, RTL_R8(tp, Config1) | 0x10); - - } else if (tp->mcfg == CFG_METHOD_14 || tp->mcfg == CFG_METHOD_15) { - - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - if (dev->mtu > ETH_DATA_LEN) { - RTL_W8(tp, MTPS, 0x24); - RTL_W8(tp, Config3, RTL_R8(tp, Config3) | Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | 0x01); - } else { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Jumbo_En0); - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~0x01); - } - - RTL_W8(tp, 0xF3, RTL_R8(tp, 0xF3) | BIT_5); - RTL_W8(tp, 0xF3, RTL_R8(tp, 0xF3) & ~BIT_5); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_7 | BIT_6); - - RTL_W8(tp, 0xD1, RTL_R8(tp, 0xD1) | BIT_2 | BIT_3); - - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_6 | BIT_5 | BIT_4 | BIT_2 | BIT_1); - - RTL_W8(tp, TDFNR, 0x8); - - /* - if (aspm) - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_7); - */ - - RTL_W8(tp, Config5, RTL_R8(tp, Config5) & ~BIT_3); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - RTL_W8(tp, Config1, RTL_R8(tp, Config1) & ~0x10); - } else if (tp->mcfg == CFG_METHOD_16 || tp->mcfg == CFG_METHOD_17) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - rtl8168_eri_write(tp, 0xC0, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xB8, 4, 0x00000000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xC8, 4, 0x00100002, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xE8, 4, 0x00100006, ERIAR_ExGMAC); - csi_tmp = rtl8168_eri_read(tp, 0x1D0, 4, ERIAR_ExGMAC); - csi_tmp |= BIT_1; - rtl8168_eri_write(tp, 0x1D0, 1, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0xDC, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | BIT_7); - RTL_W8(tp, 0xD3, RTL_R8(tp, 0xD3) & ~BIT_7); - RTL_W8(tp, 0x1B, RTL_R8(tp, 0x1B) & ~0x07); - - if (tp->mcfg == CFG_METHOD_16) { - RTL_W32(tp, 0xB0, 0xEE480010); - RTL_W8(tp, 0x1A, RTL_R8(tp, 0x1A) & ~(BIT_2|BIT_3)); - rtl8168_eri_write(tp, 0x1DC, 1, 0x64, ERIAR_ExGMAC); - } else { - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp |= BIT_4; - rtl8168_eri_write(tp, 0x1B0, 1, csi_tmp, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xCC, 4, 0x00000050, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xD0, 4, 0x07ff0060, ERIAR_ExGMAC); - } - - RTL_W8(tp, TDFNR, 0x8); - - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~PMSTS_En); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_6); - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, MTPS, 0x27); - - /* disable clock request. */ - pci_write_config_byte(pdev, 0x81, 0x00); - - } else if (tp->mcfg == CFG_METHOD_18 || tp->mcfg == CFG_METHOD_19) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - rtl8168_eri_write(tp, 0xC8, 4, 0x00100002, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xE8, 4, 0x00100006, ERIAR_ExGMAC); - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | BIT_7); - RTL_W8(tp, 0xD3, RTL_R8(tp, 0xD3) & ~BIT_7); - csi_tmp = rtl8168_eri_read(tp, 0xDC, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - - /* - if (aspm) - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_7); - */ - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, MTPS, 0x27); - - RTL_W8(tp, TDFNR, 0x8); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_6); - - rtl8168_eri_write(tp, 0xC0, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xB8, 4, 0x00000000, ERIAR_ExGMAC); - RTL_W8(tp, 0x1B,RTL_R8(tp, 0x1B) & ~0x07); - - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_4; - rtl8168_eri_write(tp, 0x1B0, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp = rtl8168_eri_read(tp, 0x1d0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_4 | BIT_1; - rtl8168_eri_write(tp, 0x1d0, 1, csi_tmp, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xCC, 4, 0x00000050, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xd0, 4, 0x00000060, ERIAR_ExGMAC); - } else if (tp->mcfg == CFG_METHOD_20) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - rtl8168_eri_write(tp, 0xC8, 4, 0x00100002, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xE8, 4, 0x00100006, ERIAR_ExGMAC); - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | BIT_7); - RTL_W8(tp, 0xD3, RTL_R8(tp, 0xD3) & ~BIT_7); - csi_tmp = rtl8168_eri_read(tp, 0xDC, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - - /* - if (aspm) - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_7); - */ - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, MTPS, 0x27); - - RTL_W8(tp, TDFNR, 0x8); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_6); - rtl8168_eri_write(tp, 0xC0, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xB8, 4, 0x00000000, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_4; - rtl8168_eri_write(tp, 0x1B0, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp = rtl8168_eri_read(tp, 0x1d0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_4 | BIT_1; - rtl8168_eri_write(tp, 0x1d0, 1, csi_tmp, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xCC, 4, 0x00000050, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xd0, 4, 0x00000060, ERIAR_ExGMAC); - } else if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_24 || tp->mcfg == CFG_METHOD_25 || - tp->mcfg == CFG_METHOD_26 || tp->mcfg == CFG_METHOD_29 || - tp->mcfg == CFG_METHOD_30) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22) - set_offset711(tp, 0x04); - - rtl8168_eri_write(tp, 0xC8, 4, 0x00080002, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xCC, 1, 0x38, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xD0, 1, 0x48, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xE8, 4, 0x00100006, ERIAR_ExGMAC); - - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | BIT_7); - - csi_tmp = rtl8168_eri_read(tp, 0xDC, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - - if (tp->mcfg == CFG_METHOD_26) { - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD3C0); - mac_ocp_data &= ~(BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= 0x0FFF; - rtl8168_mac_ocp_write(tp, 0xD3C0, mac_ocp_data); - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD3C2); - mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - rtl8168_mac_ocp_write(tp, 0xD3C2, mac_ocp_data); - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD3C4); - mac_ocp_data |= BIT_0; - rtl8168_mac_ocp_write(tp, 0xD3C4, mac_ocp_data); - } else if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30) { - - if (tp->RequireAdjustUpsTxLinkPulseTiming) { - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD412); - mac_ocp_data &= ~(0x0FFF); - mac_ocp_data |= tp->SwrCnt1msIni; - rtl8168_mac_ocp_write(tp, 0xD412, mac_ocp_data); - } - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xE056); - mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4); - //mac_ocp_data |= (BIT_6 | BIT_5 | BIT_4); - rtl8168_mac_ocp_write(tp, 0xE056, mac_ocp_data); - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xE052); - mac_ocp_data &= ~(BIT_15 | BIT_14 | BIT_13 | BIT_3); - mac_ocp_data |= BIT_15; - //mac_ocp_data |= BIT_3; - rtl8168_mac_ocp_write(tp, 0xE052, mac_ocp_data); - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD420); - mac_ocp_data &= ~(BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= 0x45F; - rtl8168_mac_ocp_write(tp, 0xD420, mac_ocp_data); - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xE0D6); - mac_ocp_data &= ~(BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= 0x17F; - rtl8168_mac_ocp_write(tp, 0xE0D6, mac_ocp_data); - } - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - RTL_W8(tp, 0x1B, RTL_R8(tp, 0x1B) & ~0x07); - - RTL_W8(tp, TDFNR, 0x4); - - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~PMSTS_En); - - /* - if (aspm) - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_7); - */ - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, MTPS, 0x27); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_6); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_7); - - rtl8168_eri_write(tp, 0xC0, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xB8, 4, 0x00000000, ERIAR_ExGMAC); - - if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30) { - rtl8168_mac_ocp_write(tp, 0xE054, 0x0000); - - rtl8168_eri_write(tp, 0x5F0, 2, 0x4000, ERIAR_ExGMAC); - } else { - rtl8168_eri_write(tp, 0x5F0, 2, 0x4F87, ERIAR_ExGMAC); - } - - if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30) { - csi_tmp = rtl8168_eri_read(tp, 0xDC, 4, ERIAR_ExGMAC); - csi_tmp |= (BIT_2 | BIT_3 | BIT_4); - rtl8168_eri_write(tp, 0xDC, 4, csi_tmp, ERIAR_ExGMAC); - } - - if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_24 || tp->mcfg == CFG_METHOD_25) { - rtl8168_mac_ocp_write(tp, 0xC140, 0xFFFF); - } else if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30) { - rtl8168_mac_ocp_write(tp, 0xC140, 0xFFFF); - rtl8168_mac_ocp_write(tp, 0xC142, 0xFFFF); - } - - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp &= ~BIT_12; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - - if (tp->mcfg == CFG_METHOD_29 || tp->mcfg == CFG_METHOD_30) { - csi_tmp = rtl8168_eri_read(tp, 0x2FC, 1, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_2); - rtl8168_eri_write(tp, 0x2FC, 1, csi_tmp, ERIAR_ExGMAC); - } else { - csi_tmp = rtl8168_eri_read(tp, 0x2FC, 1, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_0 | BIT_1 | BIT_2); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0x2FC, 1, csi_tmp, ERIAR_ExGMAC); - } - - csi_tmp = rtl8168_eri_read(tp, 0x1D0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_1; - rtl8168_eri_write(tp, 0x1D0, 1, csi_tmp, ERIAR_ExGMAC); - } else if (tp->mcfg == CFG_METHOD_23 || tp->mcfg == CFG_METHOD_27 || - tp->mcfg == CFG_METHOD_28) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - rtl8168_eri_write(tp, 0xC8, 4, 0x00080002, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xCC, 1, 0x2F, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xD0, 1, 0x5F, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xE8, 4, 0x00100006, ERIAR_ExGMAC); - - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | BIT_7); - - csi_tmp = rtl8168_eri_read(tp, 0xDC, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_6); - - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_7); - - rtl8168_eri_write(tp, 0xC0, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xB8, 4, 0x00000000, ERIAR_ExGMAC); - RTL_W8(tp, 0x1B, RTL_R8(tp, 0x1B) & ~0x07); - - RTL_W8(tp, TDFNR, 0x4); - - /* - if (aspm) - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_7); - */ - - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp &= ~BIT_12; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x2FC, 1, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_0 | BIT_1 | BIT_2); - csi_tmp |= (BIT_0 | BIT_1); - rtl8168_eri_write(tp, 0x2FC, 1, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x1D0, 1, ERIAR_ExGMAC); - csi_tmp |= BIT_1; - rtl8168_eri_write(tp, 0x1D0, 1, csi_tmp, ERIAR_ExGMAC); - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, MTPS, 0x27); - - if (tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28) { - rtl8168_oob_mutex_lock(tp); - rtl8168_eri_write(tp, 0x5F0, 2, 0x4F87, ERIAR_ExGMAC); - rtl8168_oob_mutex_unlock(tp); - } - - rtl8168_mac_ocp_write(tp, 0xC140, 0xFFFF); - rtl8168_mac_ocp_write(tp, 0xC142, 0xFFFF); - - if (tp->mcfg == CFG_METHOD_28) { - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD3E2); - mac_ocp_data &= 0xF000; - mac_ocp_data |= 0xAFD; - rtl8168_mac_ocp_write(tp, 0xD3E2, mac_ocp_data); - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD3E4); - mac_ocp_data &= 0xFF00; - rtl8168_mac_ocp_write(tp, 0xD3E4, mac_ocp_data); - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xE860); - mac_ocp_data |= BIT_7; - rtl8168_mac_ocp_write(tp, 0xE860, mac_ocp_data); - } - } else if (tp->mcfg == CFG_METHOD_31 || tp->mcfg == CFG_METHOD_32 || - tp->mcfg == CFG_METHOD_33) { - set_offset70F(tp, 0x27); - set_offset79(tp, 0x50); - - rtl8168_eri_write(tp, 0xC8, 4, 0x00080002, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xCC, 1, 0x2F, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xD0, 1, 0x5F, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xE8, 4, 0x00100006, ERIAR_ExGMAC); - - RTL_W32(tp, TxConfig, RTL_R32(tp, TxConfig) | BIT_7); - - csi_tmp = rtl8168_eri_read(tp, 0xDC, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0xDC, 1, csi_tmp, ERIAR_ExGMAC); - - if (tp->RequireAdjustUpsTxLinkPulseTiming) { - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD412); - mac_ocp_data &= ~(0x0FFF); - mac_ocp_data |= tp->SwrCnt1msIni; - rtl8168_mac_ocp_write(tp, 0xD412, mac_ocp_data); - } - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xE056); - mac_ocp_data &= ~(BIT_7 | BIT_6 | BIT_5 | BIT_4); - rtl8168_mac_ocp_write(tp, 0xE056, mac_ocp_data); - if (FALSE == HW_SUPP_SERDES_PHY(tp)) - rtl8168_mac_ocp_write(tp, 0xEA80, 0x0003); - else - rtl8168_mac_ocp_write(tp, 0xEA80, 0x0000); - - rtl8168_oob_mutex_lock(tp); - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xE052); - mac_ocp_data &= ~(BIT_3 | BIT_0); - rtl8168_mac_ocp_write(tp, 0xE052, mac_ocp_data); - rtl8168_oob_mutex_unlock(tp); - - mac_ocp_data = rtl8168_mac_ocp_read(tp, 0xD420); - mac_ocp_data &= ~(BIT_11 | BIT_10 | BIT_9 | BIT_8 | BIT_7 | BIT_6 | BIT_5 | BIT_4 | BIT_3 | BIT_2 | BIT_1 | BIT_0); - mac_ocp_data |= 0x45F; - rtl8168_mac_ocp_write(tp, 0xD420, mac_ocp_data); - - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - RTL_W8(tp, 0x1B, RTL_R8(tp, 0x1B) & ~0x07); - - RTL_W8(tp, TDFNR, 0x4); - - RTL_W8(tp, Config2, RTL_R8(tp, Config2) & ~PMSTS_En); - - /* - if (aspm) - RTL_W8(tp, 0xF1, RTL_R8(tp, 0xF1) | BIT_7); - */ - - if (dev->mtu > ETH_DATA_LEN) - RTL_W8(tp, MTPS, 0x27); - - if (FALSE == HW_SUPP_SERDES_PHY(tp)) { - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) | BIT_6); - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) | BIT_7); - } else { - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) & ~BIT_6); - RTL_W8(tp, 0xF2, RTL_R8(tp, 0xF2) & ~BIT_6); - RTL_W8(tp, 0xD0, RTL_R8(tp, 0xD0) & ~BIT_7); - } - - rtl8168_eri_write(tp, 0xC0, 2, 0x0000, ERIAR_ExGMAC); - rtl8168_eri_write(tp, 0xB8, 4, 0x00000000, ERIAR_ExGMAC); - - rtl8168_oob_mutex_lock(tp); - rtl8168_eri_write(tp, 0x5F0, 2, 0x4000, ERIAR_ExGMAC); - rtl8168_oob_mutex_unlock(tp); - - if (tp->mcfg == CFG_METHOD_32 || tp->mcfg == CFG_METHOD_33) { - csi_tmp = rtl8168_eri_read(tp, 0xD4, 4, ERIAR_ExGMAC); - csi_tmp |= BIT_4; - rtl8168_eri_write(tp, 0xD4, 4, csi_tmp, ERIAR_ExGMAC); - } - - rtl8168_mac_ocp_write(tp, 0xC140, 0xFFFF); - rtl8168_mac_ocp_write(tp, 0xC142, 0xFFFF); - - csi_tmp = rtl8168_eri_read(tp, 0x1B0, 4, ERIAR_ExGMAC); - csi_tmp &= ~BIT_12; - rtl8168_eri_write(tp, 0x1B0, 4, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x2FC, 1, ERIAR_ExGMAC); - csi_tmp &= ~(BIT_0 | BIT_1); - csi_tmp |= BIT_0; - rtl8168_eri_write(tp, 0x2FC, 1, csi_tmp, ERIAR_ExGMAC); - - csi_tmp = rtl8168_eri_read(tp, 0x1D0, 1, ERIAR_ExGMAC); - csi_tmp &= ~BIT_1; - rtl8168_eri_write(tp, 0x1D0, 1, csi_tmp, ERIAR_ExGMAC); - } else if (tp->mcfg == CFG_METHOD_1) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - if (dev->mtu > ETH_DATA_LEN) { - pci_read_config_byte(pdev, 0x69, &device_control); - device_control &= ~0x70; - device_control |= 0x28; - pci_write_config_byte(pdev, 0x69, device_control); - } else { - pci_read_config_byte(pdev, 0x69, &device_control); - device_control &= ~0x70; - device_control |= 0x58; - pci_write_config_byte(pdev, 0x69, device_control); - } - } else if (tp->mcfg == CFG_METHOD_2) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - if (dev->mtu > ETH_DATA_LEN) { - pci_read_config_byte(pdev, 0x69, &device_control); - device_control &= ~0x70; - device_control |= 0x28; - pci_write_config_byte(pdev, 0x69, device_control); - - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | (1 << 0)); - } else { - pci_read_config_byte(pdev, 0x69, &device_control); - device_control &= ~0x70; - device_control |= 0x58; - pci_write_config_byte(pdev, 0x69, device_control); - - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~(1 << 0)); - } - } else if (tp->mcfg == CFG_METHOD_3) { - RTL_W8(tp, Config3, RTL_R8(tp, Config3) & ~Beacon_en); - - if (dev->mtu > ETH_DATA_LEN) { - pci_read_config_byte(pdev, 0x69, &device_control); - device_control &= ~0x70; - device_control |= 0x28; - pci_write_config_byte(pdev, 0x69, device_control); - - RTL_W8(tp, Config4, RTL_R8(tp, Config4) | (1 << 0)); - } else { - pci_read_config_byte(pdev, 0x69, &device_control); - device_control &= ~0x70; - device_control |= 0x58; - pci_write_config_byte(pdev, 0x69, device_control); - - RTL_W8(tp, Config4, RTL_R8(tp, Config4) & ~(1 << 0)); - } - } - - if ((tp->mcfg == CFG_METHOD_1) || (tp->mcfg == CFG_METHOD_2) || (tp->mcfg == CFG_METHOD_3)) { - /* csum offload command for RTL8168B/8111B */ - tp->tx_tcp_csum_cmd = TxTCPCS; - tp->tx_udp_csum_cmd = TxUDPCS; - tp->tx_ip_csum_cmd = TxIPCS; - tp->tx_ipv6_csum_cmd = 0; - } else { - /* csum offload command for RTL8168C/8111C and RTL8168CP/8111CP */ - tp->tx_tcp_csum_cmd = TxTCPCS_C; - tp->tx_udp_csum_cmd = TxUDPCS_C; - tp->tx_ip_csum_cmd = TxIPCS_C; - tp->tx_ipv6_csum_cmd = TxIPV6F_C; - } - - - //other hw parameters - if (tp->mcfg == CFG_METHOD_21 || tp->mcfg == CFG_METHOD_22 || - tp->mcfg == CFG_METHOD_23 || tp->mcfg == CFG_METHOD_24 || - tp->mcfg == CFG_METHOD_25 || tp->mcfg == CFG_METHOD_26 || - tp->mcfg == CFG_METHOD_27 || tp->mcfg == CFG_METHOD_28) - rtl8168_eri_write(tp, 0x2F8, 2, 0x1D8F, ERIAR_ExGMAC); - - if (tp->bios_setting & BIT_28) { - if (tp->mcfg == CFG_METHOD_18 || tp->mcfg == CFG_METHOD_19 || - tp->mcfg == CFG_METHOD_20) { - u32 gphy_val; - - rtl8168_mdio_write(tp, 0x1F, 0x0007); - rtl8168_mdio_write(tp, 0x1E, 0x002C); - gphy_val = rtl8168_mdio_read(tp, 0x16); - gphy_val |= BIT_10; - rtl8168_mdio_write(tp, 0x16, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0005); - rtl8168_mdio_write(tp, 0x05, 0x8B80); - gphy_val = rtl8168_mdio_read(tp, 0x06); - gphy_val |= BIT_7; - rtl8168_mdio_write(tp, 0x06, gphy_val); - rtl8168_mdio_write(tp, 0x1F, 0x0000); - } - } - - rtl8168_hw_clear_timer_int(dev); - - rtl8168_enable_exit_l1_mask(tp); - - switch (tp->mcfg) { - case CFG_METHOD_25: - rtl8168_mac_ocp_write(tp, 0xD3C0, 0x0B00); - rtl8168_mac_ocp_write(tp, 0xD3C2, 0x0000); - break; - case CFG_METHOD_29: - case CFG_METHOD_30: - rtl8168_mac_ocp_write(tp, 0xE098, 0x0AA2); - break; - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - rtl8168_mac_ocp_write(tp, 0xE098, 0xC302); - break; - } - - switch (tp->mcfg) { - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - if (aspm) { - rtl8168_init_pci_offset_99(tp); - } - break; - } - switch (tp->mcfg) { - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - if (aspm) { - rtl8168_init_pci_offset_180(tp); - } - break; - } - - tp->cp_cmd &= ~(EnableBist | Macdbgo_oe | Force_halfdup | - Force_rxflow_en | Force_txflow_en | Cxpl_dbg_sel | - ASF | Macdbgo_sel); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,0,0) - RTL_W16(tp, CPlusCmd, tp->cp_cmd); -#else - rtl8168_hw_set_features(dev, dev->features); -#endif - - switch (tp->mcfg) { - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: { - int timeout; - for (timeout = 0; timeout < 10; timeout++) { - if ((rtl8168_eri_read(tp, 0x1AE, 2, ERIAR_ExGMAC) & BIT_13)==0) - break; - mdelay(1); - } - } - break; - } - - RTL_W16(tp, RxMaxSize, tp->rx_buf_sz); - - rtl8168_disable_rxdvgate(dev); - - if (tp->mcfg == CFG_METHOD_11 || tp->mcfg == CFG_METHOD_12) - rtl8168_mac_loopback_test(tp); - - if (!tp->pci_cfg_is_read) { - pci_read_config_byte(pdev, PCI_COMMAND, &tp->pci_cfg_space.cmd); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0, &tp->pci_cfg_space.io_base_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_0 + 2, &tp->pci_cfg_space.io_base_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2, &tp->pci_cfg_space.mem_base_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_2 + 2, &tp->pci_cfg_space.mem_base_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3, &tp->pci_cfg_space.resv_0x1c_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_3 + 2, &tp->pci_cfg_space.resv_0x1c_h); - pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tp->pci_cfg_space.ilr); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4, &tp->pci_cfg_space.resv_0x20_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_4 + 2, &tp->pci_cfg_space.resv_0x20_h); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5, &tp->pci_cfg_space.resv_0x24_l); - pci_read_config_word(pdev, PCI_BASE_ADDRESS_5 + 2, &tp->pci_cfg_space.resv_0x24_h); - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID, &tp->pci_cfg_space.resv_0x2c_l); - pci_read_config_word(pdev, PCI_SUBSYSTEM_VENDOR_ID + 2, &tp->pci_cfg_space.resv_0x2c_h); - if (tp->HwPcieSNOffset > 0) { - tp->pci_cfg_space.pci_sn_l = rtl8168_csi_read(tp, tp->HwPcieSNOffset); - tp->pci_cfg_space.pci_sn_h = rtl8168_csi_read(tp, tp->HwPcieSNOffset + 4); - } - - tp->pci_cfg_is_read = 1; - } - - rtl8168_dsm(dev, DSM_MAC_INIT); - - /* Set Rx packet filter */ - rtl8168_hw_set_rx_packet_filter(dev); - -#ifdef ENABLE_DASH_SUPPORT - if (tp->DASH && !tp->dash_printer_enabled) - NICChkTypeEnableDashInterrupt(tp); -#endif - - if (tp->HwSuppAspmClkIntrLock) - rtl8168_hw_aspm_clkreq_enable(tp, true); - - rtl8168_disable_cfg9346_write(tp); - - udelay(10); -} - -static void -rtl8168_hw_start(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - RTL_W8(tp, ChipCmd, CmdTxEnb | CmdRxEnb); - - rtl8168_enable_hw_interrupt(tp); -} - -static int -rtl8168_change_mtu(struct net_device *dev, - int new_mtu) -{ - struct rtl8168_private *tp = netdev_priv(dev); - int ret = 0; - unsigned long flags; - -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) - if (new_mtu < ETH_MIN_MTU) - return -EINVAL; - else if (new_mtu > tp->max_jumbo_frame_size) - new_mtu = tp->max_jumbo_frame_size; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,10,0) - - spin_lock_irqsave(&tp->lock, flags); - dev->mtu = new_mtu; - spin_unlock_irqrestore(&tp->lock, flags); - - if (!netif_running(dev)) - goto out; - - rtl8168_down(dev); - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_set_rxbufsize(tp, dev); - - ret = rtl8168_init_ring(dev); - - if (ret < 0) { - spin_unlock_irqrestore(&tp->lock, flags); - goto err_out; - } - -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - RTL_NAPI_ENABLE(dev, &tp->napi); -#endif -#endif//CONFIG_R8168_NAPI - - netif_stop_queue(dev); - netif_carrier_off(dev); - rtl8168_hw_config(dev); - spin_unlock_irqrestore(&tp->lock, flags); - - rtl8168_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - - mod_timer(&tp->esd_timer, jiffies + RTL8168_ESD_TIMEOUT); - mod_timer(&tp->link_timer, jiffies + RTL8168_LINK_TIMEOUT); -out: -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,0,0) - netdev_update_features(dev); -#endif - -err_out: - return ret; -} - -static inline void -rtl8168_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = 0x0badbadbadbadbadull; - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void -rtl8168_free_rx_skb(struct rtl8168_private *tp, - struct sk_buff **sk_buff, - struct RxDesc *desc) -{ - struct pci_dev *pdev = tp->pci_dev; - - dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), tp->rx_buf_sz, - DMA_FROM_DEVICE); - dev_kfree_skb(*sk_buff); - *sk_buff = NULL; - rtl8168_make_unusable_by_asic(desc); -} - -static inline void -rtl8168_mark_to_asic(struct RxDesc *desc, - u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void -rtl8168_map_to_asic(struct RxDesc *desc, - dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8168_mark_to_asic(desc, rx_buf_sz); -} - -static int -rtl8168_alloc_rx_skb(struct rtl8168_private *tp, - struct sk_buff **sk_buff, - struct RxDesc *desc, - int rx_buf_sz, - u8 in_intr) -{ - struct sk_buff *skb; - dma_addr_t mapping; - int ret = 0; - - if (in_intr) - skb = RTL_ALLOC_SKB_INTR(tp, rx_buf_sz + RTK_RX_ALIGN); - else - skb = dev_alloc_skb(rx_buf_sz + RTK_RX_ALIGN); - - if (unlikely(!skb)) - goto err_out; - - skb_reserve(skb, RTK_RX_ALIGN); - - mapping = dma_map_single(tp_to_dev(tp), skb->data, rx_buf_sz, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); - goto err_out; - } - - *sk_buff = skb; - rtl8168_map_to_asic(desc, mapping, rx_buf_sz); -out: - return ret; - -err_out: - if (skb) - dev_kfree_skb(skb); - ret = -ENOMEM; - rtl8168_make_unusable_by_asic(desc); - goto out; -} - -static void -rtl8168_rx_clear(struct rtl8168_private *tp) -{ - int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_skbuff[i]) - rtl8168_free_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i); - } -} - -static u32 -rtl8168_rx_fill(struct rtl8168_private *tp, - struct net_device *dev, - u32 start, - u32 end, - u8 in_intr) -{ - u32 cur; - - for (cur = start; end - cur > 0; cur++) { - int ret, i = cur % NUM_RX_DESC; - - if (tp->Rx_skbuff[i]) - continue; - - ret = rtl8168_alloc_rx_skb(tp, tp->Rx_skbuff + i, - tp->RxDescArray + i, - tp->rx_buf_sz, - in_intr); - if (ret < 0) - break; - } - return cur - start; -} - -static inline void -rtl8168_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static void -rtl8168_desc_addr_fill(struct rtl8168_private *tp) -{ - if (!tp->TxPhyAddr || !tp->RxPhyAddr) - return; - - RTL_W32(tp, TxDescStartAddrLow, ((u64) tp->TxPhyAddr & DMA_BIT_MASK(32))); - RTL_W32(tp, TxDescStartAddrHigh, ((u64) tp->TxPhyAddr >> 32)); - RTL_W32(tp, RxDescAddrLow, ((u64) tp->RxPhyAddr & DMA_BIT_MASK(32))); - RTL_W32(tp, RxDescAddrHigh, ((u64) tp->RxPhyAddr >> 32)); -} - -static void -rtl8168_tx_desc_init(struct rtl8168_private *tp) -{ - int i = 0; - - memset(tp->TxDescArray, 0x0, NUM_TX_DESC * sizeof(struct TxDesc)); - - for (i = 0; i < NUM_TX_DESC; i++) { - if (i == (NUM_TX_DESC - 1)) - tp->TxDescArray[i].opts1 = cpu_to_le32(RingEnd); - } -} - -static void -rtl8168_rx_desc_offset0_init(struct rtl8168_private *tp, int own) -{ - int i = 0; - int ownbit = 0; - - if (tp->RxDescArray == NULL) return; - - if (own) - ownbit = DescOwn; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (i == (NUM_RX_DESC - 1)) - tp->RxDescArray[i].opts1 = cpu_to_le32((ownbit | RingEnd) | (unsigned long)tp->rx_buf_sz); - else - tp->RxDescArray[i].opts1 = cpu_to_le32(ownbit | (unsigned long)tp->rx_buf_sz); - } -} - -static void -rtl8168_rx_desc_init(struct rtl8168_private *tp) -{ - memset(tp->RxDescArray, 0x0, NUM_RX_DESC * sizeof(struct RxDesc)); -} - -static int -rtl8168_init_ring(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - rtl8168_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_skbuff, 0x0, NUM_RX_DESC * sizeof(struct sk_buff *)); - - rtl8168_tx_desc_init(tp); - rtl8168_rx_desc_init(tp); - - if (rtl8168_rx_fill(tp, dev, 0, NUM_RX_DESC, 0) != NUM_RX_DESC) - goto err_out; - - rtl8168_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - - return 0; - -err_out: - rtl8168_rx_clear(tp); - return -ENOMEM; -} - -static void -rtl8168_unmap_tx_skb(struct pci_dev *pdev, - struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - dma_unmap_single(&pdev->dev, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE); - - desc->opts1 = cpu_to_le32(RTK_MAGIC_DEBUG_VALUE); - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8168_tx_clear_range(struct rtl8168_private *tp, u32 start, - unsigned int n) -{ - unsigned int i; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22) - struct net_device *dev = tp->dev; -#endif - - for (i = 0; i < n; i++) { - unsigned int entry = (start + i) % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8168_unmap_tx_skb(tp->pci_dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - RTLDEV->stats.tx_dropped++; - dev_kfree_skb_any(skb); - tx_skb->skb = NULL; - } - } - } -} - -static void -rtl8168_tx_clear(struct rtl8168_private *tp) -{ - rtl8168_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC); - tp->cur_tx = tp->dirty_tx = 0; -} - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8168_schedule_work(struct net_device *dev, void (*task)(void *)) -{ -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - struct rtl8168_private *tp = netdev_priv(dev); - - INIT_WORK(&tp->task, task, dev); - schedule_delayed_work(&tp->task, 4); -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) -} - -#define rtl8168_cancel_schedule_work(a) - -#else -static void rtl8168_schedule_work(struct net_device *dev, work_func_t task) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - INIT_DELAYED_WORK(&tp->task, task); - schedule_delayed_work(&tp->task, 4); -} - -static void rtl8168_cancel_schedule_work(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct work_struct *work = &tp->task.work; - - if (!work->func) return; - - cancel_delayed_work_sync(&tp->task); -} -#endif - -static void -rtl8168_wait_for_quiescence(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - synchronize_irq(dev->irq); - - /* Wait for any pending NAPI task to complete */ -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - RTL_NAPI_DISABLE(dev, &tp->napi); -#endif -#endif//CONFIG_R8168_NAPI - - rtl8168_irq_mask_and_ack(tp); - -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - RTL_NAPI_ENABLE(dev, &tp->napi); -#endif -#endif//CONFIG_R8168_NAPI -} - -#if 0 -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8168_reinit_task(void *_data) -#else -static void rtl8168_reinit_task(struct work_struct *work) -#endif -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) - struct net_device *dev = _data; -#else - struct rtl8168_private *tp = - container_of(work, struct rtl8168_private, task.work); - struct net_device *dev = tp->dev; -#endif - int ret; - - if (netif_running(dev)) { - rtl8168_wait_for_quiescence(dev); - rtl8168_close(dev); - } - - ret = rtl8168_open(dev); - if (unlikely(ret < 0)) { - if (unlikely(net_ratelimit())) { - struct rtl8168_private *tp = netdev_priv(dev); - - if (netif_msg_drv(tp)) { - printk(PFX KERN_ERR - "%s: reinit failure (status = %d)." - " Rescheduling.\n", dev->name, ret); - } - } - rtl8168_schedule_work(dev, rtl8168_reinit_task); - } -} -#endif - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20) -static void rtl8168_reset_task(void *_data) -{ - struct net_device *dev = _data; - struct rtl8168_private *tp = netdev_priv(dev); -#else -static void rtl8168_reset_task(struct work_struct *work) -{ - struct rtl8168_private *tp = - container_of(work, struct rtl8168_private, task.work); - struct net_device *dev = tp->dev; -#endif - u32 budget = ~(u32)0; - unsigned long flags; - - if (!netif_running(dev)) - return; - - rtl8168_wait_for_quiescence(dev); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8168_rx_interrupt(dev, tp, &budget); -#else - rtl8168_rx_interrupt(dev, tp, budget); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_tx_clear(tp); - - if (tp->dirty_rx == tp->cur_rx) { - rtl8168_rx_clear(tp); - rtl8168_init_ring(dev); - rtl8168_set_speed(dev, tp->autoneg, tp->speed, tp->duplex, tp->advertising); - spin_unlock_irqrestore(&tp->lock, flags); - } else { - spin_unlock_irqrestore(&tp->lock, flags); - if (unlikely(net_ratelimit())) { - struct rtl8168_private *tp = netdev_priv(dev); - - if (netif_msg_intr(tp)) { - printk(PFX KERN_EMERG - "%s: Rx buffers shortage\n", dev->name); - } - } - rtl8168_schedule_work(dev, rtl8168_reset_task); - } -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,6,0) -static void -rtl8168_tx_timeout(struct net_device *dev, unsigned int txqueue) -#else -static void -rtl8168_tx_timeout(struct net_device *dev) -#endif -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - spin_lock_irqsave(&tp->lock, flags); - netif_stop_queue(dev); - netif_carrier_off(dev); - rtl8168_hw_reset(dev); - spin_unlock_irqrestore(&tp->lock, flags); - - /* Let's wait a bit while any (async) irq lands on */ - rtl8168_schedule_work(dev, rtl8168_reset_task); -} - -static u32 -rtl8168_get_txd_opts1(u32 opts1, u32 len, unsigned int entry) -{ - u32 status = opts1 | len; - - if (entry == NUM_TX_DESC - 1) - status |= RingEnd; - - return status; -} - -static int -rtl8168_xmit_frags(struct rtl8168_private *tp, - struct sk_buff *skb, - const u32 *opts) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc *txd = NULL; - const unsigned char nr_frags = info->nr_frags; - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < nr_frags; cur_frag++) { - skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,2,0) - len = frag->size; - addr = ((void *) page_address(frag->page)) + frag->page_offset; -#else - len = skb_frag_size(frag); - addr = skb_frag_address(frag); -#endif - mapping = dma_map_single(tp_to_dev(tp), addr, len, DMA_TO_DEVICE); - - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, tp->dev, - "Failed to map TX fragments DMA!\n"); - goto err_out; - } - - /* anti gcc 2.95.3 bugware (sic) */ - status = rtl8168_get_txd_opts1(opts[0], len, entry); - if (cur_frag == (nr_frags - 1)) { - tp->tx_skb[entry].skb = skb; - status |= LastFrag; - } - - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - - txd->opts2 = cpu_to_le32(opts[1]); - wmb(); - txd->opts1 = cpu_to_le32(status); - } - - return cur_frag; - -err_out: - rtl8168_tx_clear_range(tp, tp->cur_tx + 1, cur_frag); - return -EIO; -} - -static inline -__be16 get_protocol(struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,37) - return vlan_get_protocol(skb); -#else - __be16 protocol; - - if (skb->protocol == htons(ETH_P_8021Q)) - protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; - else - protocol = skb->protocol; - - return protocol; -#endif -} - -static bool rtl8168_skb_pad(struct sk_buff *skb) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,19,0) - if (skb_padto(skb, ETH_ZLEN)) - return false; - skb_put(skb, ETH_ZLEN - skb->len); - return true; -#else - return !eth_skb_pad(skb); -#endif -} - -static inline bool -rtl8168_tx_csum(struct sk_buff *skb, - struct net_device *dev, - u32 *opts) -{ - struct rtl8168_private *tp = netdev_priv(dev); - u32 csum_cmd = 0; - u8 sw_calc_csum = FALSE; - - if (skb->ip_summed == CHECKSUM_PARTIAL) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - const struct iphdr *ip = skb->nh.iph; - - if (dev->features & NETIF_F_IP_CSUM) { - if (ip->protocol == IPPROTO_TCP) - csum_cmd = tp->tx_ip_csum_cmd | tp->tx_tcp_csum_cmd; - else if (ip->protocol == IPPROTO_UDP) - csum_cmd = tp->tx_ip_csum_cmd | tp->tx_udp_csum_cmd; - else if (ip->protocol == IPPROTO_IP) - csum_cmd = tp->tx_ip_csum_cmd; - } -#else - u8 ip_protocol = IPPROTO_RAW; - - switch (get_protocol(skb)) { - case __constant_htons(ETH_P_IP): - if (dev->features & NETIF_F_IP_CSUM) { - ip_protocol = ip_hdr(skb)->protocol; - csum_cmd = tp->tx_ip_csum_cmd; - } - break; - case __constant_htons(ETH_P_IPV6): - if (dev->features & NETIF_F_IPV6_CSUM) { - u32 transport_offset = (u32)skb_transport_offset(skb); - if (transport_offset > 0 && transport_offset <= TCPHO_MAX) { - ip_protocol = ipv6_hdr(skb)->nexthdr; - csum_cmd = tp->tx_ipv6_csum_cmd; - csum_cmd |= transport_offset << TCPHO_SHIFT; - } - } - break; - default: - if (unlikely(net_ratelimit())) - dprintk("checksum_partial proto=%x!\n", skb->protocol); - break; - } - - if (ip_protocol == IPPROTO_TCP) - csum_cmd |= tp->tx_tcp_csum_cmd; - else if (ip_protocol == IPPROTO_UDP) - csum_cmd |= tp->tx_udp_csum_cmd; -#endif - if (csum_cmd == 0) { - sw_calc_csum = TRUE; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - WARN_ON(1); /* we need a WARN() */ -#endif - } - } - - if (csum_cmd != 0) { - if (tp->ShortPacketSwChecksum && skb->len < ETH_ZLEN) { - sw_calc_csum = TRUE; - if (!rtl8168_skb_pad(skb)) - return false; - } else { - if ((tp->mcfg == CFG_METHOD_1) || (tp->mcfg == CFG_METHOD_2) || (tp->mcfg == CFG_METHOD_3)) - opts[0] |= csum_cmd; - else - opts[1] |= csum_cmd; - } - } - - if (tp->UseSwPaddingShortPkt && skb->len < ETH_ZLEN) - if (!rtl8168_skb_pad(skb)) - return false; - - if (sw_calc_csum) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,7) - skb_checksum_help(&skb, 0); -#elif LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10) - skb_checksum_help(skb, 0); -#else - skb_checksum_help(skb); -#endif - } - - return true; -} - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) -/* r8169_csum_workaround() - * The hw limits the value the transport offset. When the offset is out of the - * range, calculate the checksum by sw. - */ -static void r8168_csum_workaround(struct rtl8168_private *tp, - struct sk_buff *skb) -{ - if (skb_shinfo(skb)->gso_size) { - netdev_features_t features = tp->dev->features; - struct sk_buff *segs, *nskb; - - features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6); - segs = skb_gso_segment(skb, features); - if (IS_ERR(segs) || !segs) - goto drop; - - do { - nskb = segs; - segs = segs->next; - nskb->next = NULL; - rtl8168_start_xmit(nskb, tp->dev); - } while (segs); - - dev_consume_skb_any(skb); - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - if (skb_checksum_help(skb) < 0) - goto drop; - - rtl8168_start_xmit(skb, tp->dev); - } else { - struct net_device_stats *stats; - -drop: - stats = &tp->dev->stats; - stats->tx_dropped++; - dev_kfree_skb_any(skb); - } -} - -/* msdn_giant_send_check() - * According to the document of microsoft, the TCP Pseudo Header excludes the - * packet length for IPv6 TCP large packets. - */ -static int msdn_giant_send_check(struct sk_buff *skb) -{ - const struct ipv6hdr *ipv6h; - struct tcphdr *th; - int ret; - - ret = skb_cow_head(skb, 0); - if (ret) - return ret; - - ipv6h = ipv6_hdr(skb); - th = tcp_hdr(skb); - - th->check = 0; - th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0); - - return ret; -} -#endif - -static bool rtl8168_tx_slots_avail(struct rtl8168_private *tp, - unsigned int nr_frags) -{ - unsigned int slots_avail = tp->dirty_tx + NUM_TX_DESC - tp->cur_tx; - - /* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */ - return slots_avail > nr_frags; -} - -static netdev_tx_t -rtl8168_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned int entry; - struct TxDesc *txd; - dma_addr_t mapping; - u32 len; - u32 opts[2]; - netdev_tx_t ret = NETDEV_TX_OK; - unsigned long flags, large_send; - int frags; - - spin_lock_irqsave(&tp->lock, flags); - - if (unlikely(!rtl8168_tx_slots_avail(tp, skb_shinfo(skb)->nr_frags))) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Ring full when queue awake!\n", - dev->name); - } - goto err_stop; - } - - entry = tp->cur_tx % NUM_TX_DESC; - txd = tp->TxDescArray + entry; - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) { - if (netif_msg_drv(tp)) { - printk(KERN_ERR - "%s: BUG! Tx Desc is own by hardware!\n", - dev->name); - } - goto err_stop; - } - - opts[0] = DescOwn; - opts[1] = rtl8168_tx_vlan_tag(tp, skb); - - large_send = 0; -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - if (dev->features & (NETIF_F_TSO | NETIF_F_TSO6)) { -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) - u32 mss = skb_shinfo(skb)->tso_size; -#else - u32 mss = skb_shinfo(skb)->gso_size; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,18) - - /* TCP Segmentation Offload (or TCP Large Send) */ - if (mss) { - if ((tp->mcfg == CFG_METHOD_1) || - (tp->mcfg == CFG_METHOD_2) || - (tp->mcfg == CFG_METHOD_3)) { - opts[0] |= LargeSend | (min(mss, MSS_MAX) << 16); - large_send = 1; - } else { - u32 transport_offset = (u32)skb_transport_offset(skb); - switch (get_protocol(skb)) { - case __constant_htons(ETH_P_IP): - if (transport_offset <= GTTCPHO_MAX) { - opts[0] |= GiantSendv4; - opts[0] |= transport_offset << GTTCPHO_SHIFT; - opts[1] |= min(mss, MSS_MAX) << 18; - large_send = 1; - } - break; - case __constant_htons(ETH_P_IPV6): -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) - if (msdn_giant_send_check(skb)) { - spin_unlock_irqrestore(&tp->lock, flags); - r8168_csum_workaround(tp, skb); - goto out; - } -#endif - if (transport_offset <= GTTCPHO_MAX) { - opts[0] |= GiantSendv6; - opts[0] |= transport_offset << GTTCPHO_SHIFT; - opts[1] |= min(mss, MSS_MAX) << 18; - large_send = 1; - } - break; - default: - if (unlikely(net_ratelimit())) - dprintk("tso proto=%x!\n", skb->protocol); - break; - } - } - - if (large_send == 0) - goto err_dma_0; - } - } -#endif //LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - - if (large_send == 0) { - if (unlikely(!rtl8168_tx_csum(skb, dev, opts))) - goto err_dma_0; - } - - frags = rtl8168_xmit_frags(tp, skb, opts); - if (unlikely(frags < 0)) - goto err_dma_0; - if (frags) { - len = skb_headlen(skb); - opts[0] |= FirstFrag; - } else { - len = skb->len; - - tp->tx_skb[entry].skb = skb; - - opts[0] |= FirstFrag | LastFrag; - } - - opts[0] = rtl8168_get_txd_opts1(opts[0], len, entry); - mapping = dma_map_single(tp_to_dev(tp), skb->data, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(tp_to_dev(tp), mapping))) { - if (unlikely(net_ratelimit())) - netif_err(tp, drv, dev, "Failed to map TX DMA!\n"); - goto err_dma_1; - } - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - txd->opts2 = cpu_to_le32(opts[1]); - wmb(); - txd->opts1 = cpu_to_le32(opts[0]); - -#if LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) - dev->trans_start = jiffies; -#else - skb_tx_timestamp(skb); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(3,5,0) - - tp->cur_tx += frags + 1; - - wmb(); - - RTL_W8(tp, TxPoll, NPQ); /* set polling bit */ - - if (!rtl8168_tx_slots_avail(tp, MAX_SKB_FRAGS)) { - netif_stop_queue(dev); - smp_rmb(); - if (rtl8168_tx_slots_avail(tp, MAX_SKB_FRAGS)) - netif_wake_queue(dev); - } - - spin_unlock_irqrestore(&tp->lock, flags); -out: - return ret; -err_dma_1: - tp->tx_skb[entry].skb = NULL; - rtl8168_tx_clear_range(tp, tp->cur_tx + 1, frags); -err_dma_0: - RTLDEV->stats.tx_dropped++; - spin_unlock_irqrestore(&tp->lock, flags); - dev_kfree_skb_any(skb); - ret = NETDEV_TX_OK; - goto out; -err_stop: - netif_stop_queue(dev); - ret = NETDEV_TX_BUSY; - RTLDEV->stats.tx_dropped++; - - spin_unlock_irqrestore(&tp->lock, flags); - goto out; -} - -static void -rtl8168_tx_interrupt(struct net_device *dev, - struct rtl8168_private *tp) -{ - unsigned int dirty_tx, tx_left; - - assert(dev != NULL); - assert(tp != NULL); - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - tp->dynamic_aspm_packet_count += tx_left; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 len = tx_skb->len; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - RTLDEV->stats.tx_bytes += len; - RTLDEV->stats.tx_packets++; - - rtl8168_unmap_tx_skb(tp->pci_dev, - tx_skb, - tp->TxDescArray + entry); - - if (tx_skb->skb!=NULL) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,14,0) - dev_consume_skb_any(tx_skb->skb); -#else - dev_kfree_skb_any(tx_skb->skb); -#endif - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - tp->dynamic_aspm_packet_count -= tx_left; - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - smp_wmb(); - if (netif_queue_stopped(dev) && - (rtl8168_tx_slots_avail(tp, MAX_SKB_FRAGS))) { - netif_wake_queue(dev); - } - smp_rmb(); - if (tp->cur_tx != dirty_tx) - RTL_W8(tp, TxPoll, NPQ); - } -} - -static inline int -rtl8168_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void -rtl8168_rx_csum(struct rtl8168_private *tp, - struct sk_buff *skb, - struct RxDesc *desc) -{ - u32 opts1 = le32_to_cpu(desc->opts1); - u32 opts2 = le32_to_cpu(desc->opts2); - - if ((tp->mcfg == CFG_METHOD_1) || - (tp->mcfg == CFG_METHOD_2) || - (tp->mcfg == CFG_METHOD_3)) { - u32 status = opts1 & RxProtoMask; - - /* rx csum offload for RTL8168B/8111B */ - if (((status == RxProtoTCP) && !(opts1 & (RxTCPF | RxIPF))) || - ((status == RxProtoUDP) && !(opts1 & (RxUDPF | RxIPF)))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - } else { - /* rx csum offload for RTL8168C/8111C and RTL8168CP/8111CP */ - if (((opts2 & RxV4F) && !(opts1 & RxIPF)) || (opts2 & RxV6F)) { - if (((opts1 & RxTCPT) && !(opts1 & RxTCPF)) || - ((opts1 & RxUDPT) && !(opts1 & RxUDPF))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb->ip_summed = CHECKSUM_NONE; - } else - skb->ip_summed = CHECKSUM_NONE; - } -} - -static inline int -rtl8168_try_rx_copy(struct rtl8168_private *tp, - struct sk_buff **sk_buff, - int pkt_size, - struct RxDesc *desc, - int rx_buf_sz) -{ - int ret = -1; - - if (pkt_size < rx_copybreak) { - struct sk_buff *skb; - - skb = RTL_ALLOC_SKB_INTR(tp, pkt_size + RTK_RX_ALIGN); - if (skb) { - u8 *data; - - data = sk_buff[0]->data; - skb_reserve(skb, RTK_RX_ALIGN); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) - prefetch(data - RTK_RX_ALIGN); -#endif - eth_copy_and_sum(skb, data, pkt_size, 0); - *sk_buff = skb; - rtl8168_mark_to_asic(desc, rx_buf_sz); - ret = 0; - } - } - return ret; -} - -static inline void -rtl8168_rx_skb(struct rtl8168_private *tp, - struct sk_buff *skb) -{ -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29) - netif_receive_skb(skb); -#else - napi_gro_receive(&tp->napi, skb); -#endif -#else - netif_rx(skb); -#endif -} - -static int -rtl8168_rx_interrupt(struct net_device *dev, - struct rtl8168_private *tp, - napi_budget budget) -{ - unsigned int cur_rx, rx_left; - unsigned int delta, count = 0; - unsigned int entry; - struct RxDesc *desc; - u32 status; - u32 rx_quota; - - assert(dev != NULL); - assert(tp != NULL); - - if (tp->RxDescArray == NULL) - goto rx_out; - - rx_quota = RTL_RX_QUOTA(budget); - cur_rx = tp->cur_rx; - entry = cur_rx % NUM_RX_DESC; - desc = tp->RxDescArray + entry; - rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; - rx_left = rtl8168_rx_quota(rx_left, (u32)rx_quota); - - for (; rx_left > 0; rx_left--) { - rmb(); - status = le32_to_cpu(desc->opts1); - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - if (netif_msg_rx_err(tp)) { - printk(KERN_INFO - "%s: Rx ERROR. status = %08x\n", - dev->name, status); - } - - RTLDEV->stats.rx_errors++; - - if (status & (RxRWT | RxRUNT)) - RTLDEV->stats.rx_length_errors++; - if (status & RxCRC) - RTLDEV->stats.rx_crc_errors++; - if (dev->features & NETIF_F_RXALL) - goto process_pkt; - - rtl8168_mark_to_asic(desc, tp->rx_buf_sz); - } else { - struct sk_buff *skb; - int pkt_size; - -process_pkt: - if (likely(!(dev->features & NETIF_F_RXFCS))) - pkt_size = (status & 0x00003fff) - 4; - else - pkt_size = status & 0x00003fff; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8168_fragmented_frame(status))) { - RTLDEV->stats.rx_dropped++; - RTLDEV->stats.rx_length_errors++; - rtl8168_mark_to_asic(desc, tp->rx_buf_sz); - continue; - } - - skb = tp->Rx_skbuff[entry]; - - dma_sync_single_for_cpu(tp_to_dev(tp), - le64_to_cpu(desc->addr), tp->rx_buf_sz, - DMA_FROM_DEVICE); - - if (rtl8168_try_rx_copy(tp, &skb, pkt_size, - desc, tp->rx_buf_sz)) { - tp->Rx_skbuff[entry] = NULL; - dma_unmap_single(tp_to_dev(tp), le64_to_cpu(desc->addr), - tp->rx_buf_sz, DMA_FROM_DEVICE); - } else { - dma_sync_single_for_device(tp_to_dev(tp), le64_to_cpu(desc->addr), - tp->rx_buf_sz, DMA_FROM_DEVICE); - } - - if (tp->cp_cmd & RxChkSum) - rtl8168_rx_csum(tp, skb, desc); - - skb->dev = dev; - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - if (skb->pkt_type == PACKET_MULTICAST) - RTLDEV->stats.multicast++; - - if (rtl8168_rx_vlan_skb(tp, desc, skb) < 0) - rtl8168_rx_skb(tp, skb); -#if LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) - dev->last_rx = jiffies; -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(4,11,0) - RTLDEV->stats.rx_bytes += pkt_size; - RTLDEV->stats.rx_packets++; - } - - cur_rx++; - entry = cur_rx % NUM_RX_DESC; - desc = tp->RxDescArray + entry; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,37) - prefetch(desc); -#endif - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - delta = rtl8168_rx_fill(tp, dev, tp->dirty_rx, tp->cur_rx, 1); - if (!delta && count && netif_msg_intr(tp)) - printk(KERN_INFO "%s: no Rx buffer allocated\n", dev->name); - tp->dirty_rx += delta; - - tp->dynamic_aspm_packet_count += delta; - - /* - * FIXME: until there is periodic timer to try and refill the ring, - * a temporary shortage may definitely kill the Rx process. - * - disable the asic to try and avoid an overflow and kick it again - * after refill ? - * - how do others driver handle this condition (Uh oh...). - */ - if ((tp->dirty_rx + NUM_RX_DESC == tp->cur_rx) && netif_msg_intr(tp)) - printk(KERN_EMERG "%s: Rx buffers exhausted\n", dev->name); - -rx_out: - return count; -} - -/* - *The interrupt handler does all of the Rx thread work and cleans up after - *the Tx thread. - */ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,19) -static irqreturn_t rtl8168_interrupt(int irq, void *dev_instance, struct pt_regs *regs) -#else -static irqreturn_t rtl8168_interrupt(int irq, void *dev_instance) -#endif -{ - struct net_device *dev = (struct net_device *) dev_instance; - struct rtl8168_private *tp = netdev_priv(dev); - int status; - int handled = 0; - - do { - status = RTL_R16(tp, IntrStatus); - - if (!(tp->features & RTL_FEATURE_MSI)) { - /* hotplug/major error/no more work/shared irq */ - if ((status == 0xFFFF) || !status) - break; - - if (!(status & (tp->intr_mask | tp->timer_intr_mask))) - break; - } - - handled = 1; - - rtl8168_disable_hw_interrupt(tp); - - switch (tp->mcfg) { - case CFG_METHOD_9: - case CFG_METHOD_10: - case CFG_METHOD_11: - case CFG_METHOD_12: - case CFG_METHOD_13: - case CFG_METHOD_14: - case CFG_METHOD_15: - case CFG_METHOD_16: - case CFG_METHOD_17: - case CFG_METHOD_18: - case CFG_METHOD_19: - case CFG_METHOD_20: - case CFG_METHOD_21: - case CFG_METHOD_22: - case CFG_METHOD_23: - case CFG_METHOD_24: - case CFG_METHOD_25: - case CFG_METHOD_26: - case CFG_METHOD_27: - case CFG_METHOD_28: - case CFG_METHOD_29: - case CFG_METHOD_30: - case CFG_METHOD_31: - case CFG_METHOD_32: - case CFG_METHOD_33: - /* RX_OVERFLOW RE-START mechanism now HW handles it automatically*/ - RTL_W16(tp, IntrStatus, status&~RxFIFOOver); - break; - default: - RTL_W16(tp, IntrStatus, status); - break; - } - - //Work around for rx fifo overflow - if (unlikely(status & RxFIFOOver)) { - if (tp->mcfg == CFG_METHOD_1) { - netif_stop_queue(dev); - udelay(300); - rtl8168_hw_reset(dev); - rtl8168_tx_clear(tp); - rtl8168_rx_clear(tp); - rtl8168_init_ring(dev); - rtl8168_hw_config(dev); - rtl8168_hw_start(dev); - netif_wake_queue(dev); - } - } - -#ifdef ENABLE_DASH_SUPPORT - if ( tp->DASH ) { - if (HW_DASH_SUPPORT_TYPE_2(tp) || HW_DASH_SUPPORT_TYPE_3(tp)) { - u8 DashIntType2Status; - - if (status & ISRIMR_DASH_INTR_CMAC_RESET) - tp->CmacResetIntr = TRUE; - - DashIntType2Status = RTL_CMAC_R8(tp, CMAC_IBISR0); - if (DashIntType2Status & ISRIMR_DASH_TYPE2_ROK) { - tp->RcvFwDashOkEvt = TRUE; - } - if (DashIntType2Status & ISRIMR_DASH_TYPE2_TOK) { - tp->SendFwHostOkEvt = TRUE; - } - if (DashIntType2Status & ISRIMR_DASH_TYPE2_RX_DISABLE_IDLE) { - tp->DashFwDisableRx = TRUE; - } - - RTL_CMAC_W8(tp, CMAC_IBISR0, DashIntType2Status); - } else { - if (status & ISRIMR_DP_REQSYS_OK) { - tp->RcvFwReqSysOkEvt = TRUE; - } - if (status & ISRIMR_DP_DASH_OK) { - tp->RcvFwDashOkEvt = TRUE; - } - if (status & ISRIMR_DP_HOST_OK) { - tp->SendFwHostOkEvt = TRUE; - } - } - } -#endif - -#ifdef CONFIG_R8168_NAPI - if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { - if (status & tp->intr_mask) - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - - if (likely(RTL_NETIF_RX_SCHEDULE_PREP(dev, &tp->napi))) - __RTL_NETIF_RX_SCHEDULE(dev, &tp->napi); - else if (netif_msg_intr(tp)) - printk(KERN_INFO "%s: interrupt %04x in poll\n", - dev->name, status); - } else { - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - rtl8168_switch_to_hw_interrupt(tp); - } -#else - if (status & tp->intr_mask || tp->keep_intr_cnt-- > 0) { - u32 budget = ~(u32)0; - - if (status & tp->intr_mask) - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8168_rx_interrupt(dev, tp, &budget); -#else - rtl8168_rx_interrupt(dev, tp, budget); -#endif //LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24) - rtl8168_tx_interrupt(dev, tp); - -#ifdef ENABLE_DASH_SUPPORT - if ( tp->DASH ) { - struct net_device *dev = tp->dev; - - HandleDashInterrupt(dev); - } -#endif - - rtl8168_switch_to_timer_interrupt(tp); - } else { - tp->keep_intr_cnt = RTK_KEEP_INTERRUPT_COUNT; - rtl8168_switch_to_hw_interrupt(tp); - } -#endif - - } while (false); - - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_R8168_NAPI -static int rtl8168_poll(napi_ptr napi, napi_budget budget) -{ - struct rtl8168_private *tp = RTL_GET_PRIV(napi, struct rtl8168_private); - RTL_GET_NETDEV(tp) - unsigned int work_to_do = RTL_NAPI_QUOTA(budget, dev); - unsigned int work_done; - unsigned long flags; - - work_done = rtl8168_rx_interrupt(dev, tp, budget); - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_tx_interrupt(dev, tp); - spin_unlock_irqrestore(&tp->lock, flags); - - RTL_NAPI_QUOTA_UPDATE(dev, work_done, budget); - - if (work_done < work_to_do) { -#ifdef ENABLE_DASH_SUPPORT - if ( tp->DASH ) { - struct net_device *dev = tp->dev; - - spin_lock_irqsave(&tp->lock, flags); - HandleDashInterrupt(dev); - spin_unlock_irqrestore(&tp->lock, flags); - } -#endif - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(4,10,0) - if (RTL_NETIF_RX_COMPLETE(dev, napi, work_done) == FALSE) return RTL_NAPI_RETURN_VALUE; -#else - RTL_NETIF_RX_COMPLETE(dev, napi, work_done); -#endif - /* - * 20040426: the barrier is not strictly required but the - * behavior of the irq handler could be less predictable - * without it. Btw, the lack of flush for the posted pci - * write is safe - FR - */ - smp_wmb(); - - rtl8168_switch_to_timer_interrupt(tp); - } - - return RTL_NAPI_RETURN_VALUE; -} -#endif//CONFIG_R8168_NAPI - -static void rtl8168_sleep_rx_enable(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - - if (tp->wol_enabled != WOL_ENABLED) return; - - if ((tp->mcfg == CFG_METHOD_1) || (tp->mcfg == CFG_METHOD_2)) { - RTL_W8(tp, ChipCmd, CmdReset); - rtl8168_rx_desc_offset0_init(tp, 0); - RTL_W8(tp, ChipCmd, CmdRxEnb); - } else if (tp->mcfg == CFG_METHOD_14 || tp->mcfg == CFG_METHOD_15) { - rtl8168_ephy_write(tp, 0x19, 0xFF64); - RTL_W32(tp, RxConfig, RTL_R32(tp, RxConfig) | AcceptBroadcast | AcceptMulticast | AcceptMyPhys); - } -} - -static void rtl8168_down(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; - - rtl8168_delete_esd_timer(dev, &tp->esd_timer); - - rtl8168_delete_link_timer(dev, &tp->link_timer); - -#ifdef CONFIG_R8168_NAPI -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - RTL_NAPI_DISABLE(dev, &tp->napi); -#endif -#endif//CONFIG_R8168_NAPI - - netif_stop_queue(dev); - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_rcu(); /* FIXME: should this be synchronize_irq()? */ -#endif - - spin_lock_irqsave(&tp->lock, flags); - - netif_carrier_off(dev); - - rtl8168_dsm(dev, DSM_IF_DOWN); - - rtl8168_hw_reset(dev); - - spin_unlock_irqrestore(&tp->lock, flags); - - synchronize_irq(dev->irq); - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_tx_clear(tp); - - rtl8168_rx_clear(tp); - - spin_unlock_irqrestore(&tp->lock, flags); -} - -static int rtl8168_close(struct net_device *dev) -{ - struct rtl8168_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - unsigned long flags; - - if (tp->TxDescArray!=NULL && tp->RxDescArray!=NULL) { - rtl8168_cancel_schedule_work(dev); - - rtl8168_down(dev); - - pci_clear_master(tp->pci_dev); - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_hw_d3_para(dev); - - rtl8168_powerdown_pll(dev); - - rtl8168_sleep_rx_enable(dev); - - spin_unlock_irqrestore(&tp->lock, flags); - - free_irq(dev->irq, dev); - - dma_free_coherent(&pdev->dev, R8168_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - dma_free_coherent(&pdev->dev, R8168_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - } else { - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_hw_d3_para(dev); - - rtl8168_powerdown_pll(dev); - - spin_unlock_irqrestore(&tp->lock, flags); - } - - return 0; -} - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) -static void rtl8168_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8168_private *tp = netdev_priv(dev); - - if (HW_DASH_SUPPORT_DASH(tp)) - rtl8168_driver_stop(tp); - - rtl8168_set_bios_setting(dev); - if (s5_keep_curr_mac == 0 && tp->random_mac == 0) - rtl8168_rar_set(tp, tp->org_mac_addr); - -#ifdef ENABLE_FIBER_SUPPORT - rtl8168_hw_fiber_nic_d3_para(dev); -#endif //ENABLE_FIBER_SUPPORT - - if (s5wol == 0) - tp->wol_enabled = WOL_DISABLED; - - rtl8168_close(dev); - rtl8168_disable_msi(pdev, tp); - - if (system_state == SYSTEM_POWER_OFF) { - pci_clear_master(tp->pci_dev); - rtl8168_sleep_rx_enable(dev); - pci_wake_from_d3(pdev, tp->wol_enabled); - pci_set_power_state(pdev, PCI_D3hot); - } -} -#endif - -/** - * rtl8168_get_stats - Get rtl8168 read/write statistics - * @dev: The Ethernet Device to get statistics for - * - * Get TX/RX statistics for rtl8168 - */ -static struct -net_device_stats *rtl8168_get_stats(struct net_device *dev) -{ -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,22) - struct rtl8168_private *tp = netdev_priv(dev); -#endif - if (netif_running(dev)) { -// spin_lock_irqsave(&tp->lock, flags); -// spin_unlock_irqrestore(&tp->lock, flags); - } - - return &RTLDEV->stats; -} - -#ifdef CONFIG_PM - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,11) -static int -rtl8168_suspend(struct pci_dev *pdev, u32 state) -#else -static int -rtl8168_suspend(struct pci_dev *pdev, pm_message_t state) -#endif -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8168_private *tp = netdev_priv(dev); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - u32 pci_pm_state = pci_choose_state(pdev, state); -#endif - unsigned long flags; - - if (!netif_running(dev)) - goto out; - - rtl8168_cancel_schedule_work(dev); - - rtl8168_delete_esd_timer(dev, &tp->esd_timer); - - rtl8168_delete_link_timer(dev, &tp->link_timer); - - netif_stop_queue(dev); - - netif_carrier_off(dev); - - netif_device_detach(dev); - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_dsm(dev, DSM_NIC_GOTO_D3); - - rtl8168_hw_reset(dev); - - pci_clear_master(pdev); - - rtl8168_hw_d3_para(dev); - -#ifdef ENABLE_FIBER_SUPPORT - rtl8168_hw_fiber_nic_d3_para(dev); -#endif //ENABLE_FIBER_SUPPORT - - rtl8168_powerdown_pll(dev); - - rtl8168_sleep_rx_enable(dev); - - spin_unlock_irqrestore(&tp->lock, flags); - -out: - if (HW_DASH_SUPPORT_DASH(tp)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8168_driver_stop(tp); - spin_unlock_irqrestore(&tp->lock, flags); - } - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - pci_save_state(pdev, &pci_pm_state); -#else - pci_save_state(pdev); -#endif - pci_enable_wake(pdev, pci_choose_state(pdev, state), tp->wol_enabled); -// pci_set_power_state(pdev, pci_choose_state(pdev, state)); - - return 0; -} - -static int -rtl8168_resume(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8168_private *tp = netdev_priv(dev); - unsigned long flags; -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - u32 pci_pm_state = PCI_D0; -#endif - - pci_set_power_state(pdev, PCI_D0); -#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,10) - pci_restore_state(pdev, &pci_pm_state); -#else - pci_restore_state(pdev); -#endif - pci_enable_wake(pdev, PCI_D0, 0); - - spin_lock_irqsave(&tp->lock, flags); - - /* restore last modified mac address */ - rtl8168_rar_set(tp, dev->dev_addr); - - spin_unlock_irqrestore(&tp->lock, flags); - - if (!netif_running(dev)) { - if (HW_DASH_SUPPORT_DASH(tp)) { - spin_lock_irqsave(&tp->lock, flags); - rtl8168_driver_start(tp); - spin_unlock_irqrestore(&tp->lock, flags); - } - goto out; - } - - pci_set_master(pdev); - - spin_lock_irqsave(&tp->lock, flags); - - rtl8168_exit_oob(dev); - - rtl8168_dsm(dev, DSM_NIC_RESUME_D3); - - rtl8168_hw_init(dev); - - rtl8168_powerup_pll(dev); - - rtl8168_hw_ephy_config(dev); - - rtl8168_hw_phy_config(dev); - - rtl8168_hw_config(dev); - - spin_unlock_irqrestore(&tp->lock, flags); - - rtl8168_schedule_work(dev, rtl8168_reset_task); - - netif_device_attach(dev); - - mod_timer(&tp->esd_timer, jiffies + RTL8168_ESD_TIMEOUT); - mod_timer(&tp->link_timer, jiffies + RTL8168_LINK_TIMEOUT); -out: - return 0; -} - -#endif /* CONFIG_PM */ - -static struct pci_driver rtl8168_pci_driver = { - .name = MODULENAME, - .id_table = rtl8168_pci_tbl, - .probe = rtl8168_init_one, - .remove = __devexit_p(rtl8168_remove_one), -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,11) - .shutdown = rtl8168_shutdown, -#endif -#ifdef CONFIG_PM - .suspend = rtl8168_suspend, - .resume = rtl8168_resume, -#endif -}; - -static int __init -rtl8168_init_module(void) -{ -#ifdef ENABLE_R8168_PROCFS - rtl8168_proc_module_init(); -#endif -#if LINUX_VERSION_CODE > KERNEL_VERSION(2,6,0) - return pci_register_driver(&rtl8168_pci_driver); -#else - return pci_module_init(&rtl8168_pci_driver); -#endif -} - -static void __exit -rtl8168_cleanup_module(void) -{ - pci_unregister_driver(&rtl8168_pci_driver); -#ifdef ENABLE_R8168_PROCFS - if (rtl8168_proc) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - remove_proc_subtree(MODULENAME, init_net.proc_net); -#else -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) - remove_proc_entry(MODULENAME, init_net.proc_net); -#else - remove_proc_entry(MODULENAME, proc_net); -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,32) -#endif //LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0) - rtl8168_proc = NULL; - } -#endif -} - -module_init(rtl8168_init_module); -module_exit(rtl8168_cleanup_module); diff --git a/addons/r8168/src/4.4.180/r8168_realwow.h b/addons/r8168/src/4.4.180/r8168_realwow.h deleted file mode 100644 index 28e2579e..00000000 --- a/addons/r8168/src/4.4.180/r8168_realwow.h +++ /dev/null @@ -1,118 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_R8168_REALWOW_H -#define _LINUX_R8168_REALWOW_H - -#define SIOCDEVPRIVATE_RTLREALWOW SIOCDEVPRIVATE+3 - -#define MAX_RealWoW_KCP_SIZE (100) -#define MAX_RealWoW_Payload (64) - -#define KA_TX_PACKET_SIZE (100) -#define KA_WAKEUP_PATTERN_SIZE (120) - -//HwSuppKeepAliveOffloadVer -#define HW_SUPPORT_KCP_OFFLOAD(_M) ((_M)->HwSuppKCPOffloadVer > 0) - -enum rtl_realwow_cmd { - - RTL_REALWOW_SET_KCP_DISABLE=0, - RTL_REALWOW_SET_KCP_INFO, - RTL_REALWOW_SET_KCP_CONTENT, - - RTL_REALWOW_SET_KCP_ACKPKTINFO, - RTL_REALWOW_SET_KCP_WPINFO, - RTL_REALWOW_SET_KCPDHCP_TIMEOUT, - - RTLT_REALWOW_COMMAND_INVALID -}; - -struct rtl_realwow_ioctl_struct { - __u32 cmd; - __u32 offset; - __u32 len; - union { - __u32 data; - void *data_buffer; - }; -}; - -typedef struct _MP_KCPInfo { - u8 DIPv4[4]; - u8 MacID[6]; - u16 UdpPort[2]; - u8 PKTLEN[2]; - - u16 ackLostCnt; - u8 KCP_WakePattern[MAX_RealWoW_Payload]; - u8 KCP_AckPacket[MAX_RealWoW_Payload]; - u32 KCP_interval; - u8 KCP_WakePattern_Len; - u8 KCP_AckPacket_Len; - u8 KCP_TxPacket[2][KA_TX_PACKET_SIZE]; -} MP_KCP_INFO, *PMP_KCP_INFO; - -typedef struct _KCPInfo { - u32 nId; // = id - u8 DIPv4[4]; - u8 MacID[6]; - u16 UdpPort; - u16 PKTLEN; -} KCPInfo, *PKCPInfo; - -typedef struct _KCPContent { - u32 id; // = id - u32 mSec; // = msec - u32 size; // =size - u8 bPacket[MAX_RealWoW_KCP_SIZE]; // put packet here -} KCPContent, *PKCPContent; - -typedef struct _RealWoWAckPktInfo { - u16 ackLostCnt; - u16 patterntSize; - u8 pattern[MAX_RealWoW_Payload]; -} RealWoWAckPktInfo,*PRealWoWAckPktInfo; - -typedef struct _RealWoWWPInfo { - u16 patterntSize; - u8 pattern[MAX_RealWoW_Payload]; -} RealWoWWPInfo,*PRealWoWWPInfo; - -int rtl8168_realwow_ioctl(struct net_device *dev, struct ifreq *ifr); -void rtl8168_realwow_hw_init(struct net_device *dev); -void rtl8168_get_realwow_hw_version(struct net_device *dev); -void rtl8168_set_realwow_d3_para(struct net_device *dev); - -#endif /* _LINUX_R8168_REALWOW_H */ diff --git a/addons/r8168/src/4.4.180/rtl_eeprom.c b/addons/r8168/src/4.4.180/rtl_eeprom.c deleted file mode 100644 index 51bd3a12..00000000 --- a/addons/r8168/src/4.4.180/rtl_eeprom.c +++ /dev/null @@ -1,289 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include - -#include - -#include "r8168.h" -#include "rtl_eeprom.h" - -//------------------------------------------------------------------- -//rtl8168_eeprom_type(): -// tell the eeprom type -//return value: -// 0: the eeprom type is 93C46 -// 1: the eeprom type is 93C56 or 93C66 -//------------------------------------------------------------------- -void rtl8168_eeprom_type(struct rtl8168_private *tp) -{ - u16 magic = 0; - - if (tp->mcfg == CFG_METHOD_DEFAULT) - goto out_no_eeprom; - - if(RTL_R8(tp, 0xD2)&0x04) { - //not support - //tp->eeprom_type = EEPROM_TWSI; - //tp->eeprom_len = 256; - goto out_no_eeprom; - } else if(RTL_R32(tp, RxConfig) & RxCfg_9356SEL) { - tp->eeprom_type = EEPROM_TYPE_93C56; - tp->eeprom_len = 256; - } else { - tp->eeprom_type = EEPROM_TYPE_93C46; - tp->eeprom_len = 128; - } - - magic = rtl8168_eeprom_read_sc(tp, 0); - -out_no_eeprom: - if ((magic != 0x8129) && (magic != 0x8128)) { - tp->eeprom_type = EEPROM_TYPE_NONE; - tp->eeprom_len = 0; - } -} - -void rtl8168_eeprom_cleanup(struct rtl8168_private *tp) -{ - u8 x; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EECS); - - RTL_W8(tp, Cfg9346, x); - - rtl8168_raise_clock(tp, &x); - rtl8168_lower_clock(tp, &x); -} - -int rtl8168_eeprom_cmd_done(struct rtl8168_private *tp) -{ - u8 x; - int i; - - rtl8168_stand_by(tp); - - for (i = 0; i < 50000; i++) { - x = RTL_R8(tp, Cfg9346); - - if (x & Cfg9346_EEDO) { - udelay(RTL_CLOCK_RATE * 2 * 3); - return 0; - } - udelay(1); - } - - return -1; -} - -//------------------------------------------------------------------- -//rtl8168_eeprom_read_sc(): -// read one word from eeprom -//------------------------------------------------------------------- -u16 rtl8168_eeprom_read_sc(struct rtl8168_private *tp, u16 reg) -{ - int addr_sz = 6; - u8 x; - u16 data; - - if(tp->eeprom_type == EEPROM_TYPE_NONE) { - return -1; - } - - if (tp->eeprom_type==EEPROM_TYPE_93C46) - addr_sz = 6; - else if (tp->eeprom_type==EEPROM_TYPE_93C56) - addr_sz = 8; - - x = Cfg9346_EEM1 | Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); - - rtl8168_shift_out_bits(tp, RTL_EEPROM_READ_OPCODE, 3); - rtl8168_shift_out_bits(tp, reg, addr_sz); - - data = rtl8168_shift_in_bits(tp); - - rtl8168_eeprom_cleanup(tp); - - RTL_W8(tp, Cfg9346, 0); - - return data; -} - -//------------------------------------------------------------------- -//rtl8168_eeprom_write_sc(): -// write one word to a specific address in the eeprom -//------------------------------------------------------------------- -void rtl8168_eeprom_write_sc(struct rtl8168_private *tp, u16 reg, u16 data) -{ - u8 x; - int addr_sz = 6; - int w_dummy_addr = 4; - - if(tp->eeprom_type == EEPROM_TYPE_NONE) { - return ; - } - - if (tp->eeprom_type==EEPROM_TYPE_93C46) { - addr_sz = 6; - w_dummy_addr = 4; - } else if (tp->eeprom_type==EEPROM_TYPE_93C56) { - addr_sz = 8; - w_dummy_addr = 6; - } - - x = Cfg9346_EEM1 | Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); - - rtl8168_shift_out_bits(tp, RTL_EEPROM_EWEN_OPCODE, 5); - rtl8168_shift_out_bits(tp, reg, w_dummy_addr); - rtl8168_stand_by(tp); - - rtl8168_shift_out_bits(tp, RTL_EEPROM_ERASE_OPCODE, 3); - rtl8168_shift_out_bits(tp, reg, addr_sz); - if (rtl8168_eeprom_cmd_done(tp) < 0) { - return; - } - rtl8168_stand_by(tp); - - rtl8168_shift_out_bits(tp, RTL_EEPROM_WRITE_OPCODE, 3); - rtl8168_shift_out_bits(tp, reg, addr_sz); - rtl8168_shift_out_bits(tp, data, 16); - if (rtl8168_eeprom_cmd_done(tp) < 0) { - return; - } - rtl8168_stand_by(tp); - - rtl8168_shift_out_bits(tp, RTL_EEPROM_EWDS_OPCODE, 5); - rtl8168_shift_out_bits(tp, reg, w_dummy_addr); - - rtl8168_eeprom_cleanup(tp); - RTL_W8(tp, Cfg9346, 0); -} - -void rtl8168_raise_clock(struct rtl8168_private *tp, u8 *x) -{ - *x = *x | Cfg9346_EESK; - RTL_W8(tp, Cfg9346, *x); - udelay(RTL_CLOCK_RATE); -} - -void rtl8168_lower_clock(struct rtl8168_private *tp, u8 *x) -{ - - *x = *x & ~Cfg9346_EESK; - RTL_W8(tp, Cfg9346, *x); - udelay(RTL_CLOCK_RATE); -} - -void rtl8168_shift_out_bits(struct rtl8168_private *tp, int data, int count) -{ - u8 x; - int mask; - - mask = 0x01 << (count - 1); - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); - - do { - if (data & mask) - x |= Cfg9346_EEDI; - else - x &= ~Cfg9346_EEDI; - - RTL_W8(tp, Cfg9346, x); - udelay(RTL_CLOCK_RATE); - rtl8168_raise_clock(tp, &x); - rtl8168_lower_clock(tp, &x); - mask = mask >> 1; - } while(mask); - - x &= ~Cfg9346_EEDI; - RTL_W8(tp, Cfg9346, x); -} - -u16 rtl8168_shift_in_bits(struct rtl8168_private *tp) -{ - u8 x; - u16 d, i; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EEDI | Cfg9346_EEDO); - - d = 0; - - for (i = 0; i < 16; i++) { - d = d << 1; - rtl8168_raise_clock(tp, &x); - - x = RTL_R8(tp, Cfg9346); - x &= ~Cfg9346_EEDI; - - if (x & Cfg9346_EEDO) - d |= 1; - - rtl8168_lower_clock(tp, &x); - } - - return d; -} - -void rtl8168_stand_by(struct rtl8168_private *tp) -{ - u8 x; - - x = RTL_R8(tp, Cfg9346); - x &= ~(Cfg9346_EECS | Cfg9346_EESK); - RTL_W8(tp, Cfg9346, x); - udelay(RTL_CLOCK_RATE); - - x |= Cfg9346_EECS; - RTL_W8(tp, Cfg9346, x); -} - -void rtl8168_set_eeprom_sel_low(struct rtl8168_private *tp) -{ - RTL_W8(tp, Cfg9346, Cfg9346_EEM1); - RTL_W8(tp, Cfg9346, Cfg9346_EEM1 | Cfg9346_EESK); - - udelay(20); - - RTL_W8(tp, Cfg9346, Cfg9346_EEM1); -} diff --git a/addons/r8168/src/4.4.180/rtl_eeprom.h b/addons/r8168/src/4.4.180/rtl_eeprom.h deleted file mode 100644 index 861defd0..00000000 --- a/addons/r8168/src/4.4.180/rtl_eeprom.h +++ /dev/null @@ -1,56 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -//EEPROM opcodes -#define RTL_EEPROM_READ_OPCODE 06 -#define RTL_EEPROM_WRITE_OPCODE 05 -#define RTL_EEPROM_ERASE_OPCODE 07 -#define RTL_EEPROM_EWEN_OPCODE 19 -#define RTL_EEPROM_EWDS_OPCODE 16 - -#define RTL_CLOCK_RATE 3 - -void rtl8168_eeprom_type(struct rtl8168_private *tp); -void rtl8168_eeprom_cleanup(struct rtl8168_private *tp); -u16 rtl8168_eeprom_read_sc(struct rtl8168_private *tp, u16 reg); -void rtl8168_eeprom_write_sc(struct rtl8168_private *tp, u16 reg, u16 data); -void rtl8168_shift_out_bits(struct rtl8168_private *tp, int data, int count); -u16 rtl8168_shift_in_bits(struct rtl8168_private *tp); -void rtl8168_raise_clock(struct rtl8168_private *tp, u8 *x); -void rtl8168_lower_clock(struct rtl8168_private *tp, u8 *x); -void rtl8168_stand_by(struct rtl8168_private *tp); -void rtl8168_set_eeprom_sel_low(struct rtl8168_private *tp); - - - diff --git a/addons/r8168/src/4.4.180/rtltool.c b/addons/r8168/src/4.4.180/rtltool.c deleted file mode 100644 index 2a1be083..00000000 --- a/addons/r8168/src/4.4.180/rtltool.c +++ /dev/null @@ -1,359 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include "r8168.h" -#include "rtl_eeprom.h" -#include "rtltool.h" - -int rtl8168_tool_ioctl(struct rtl8168_private *tp, struct ifreq *ifr) -{ - struct rtltool_cmd my_cmd; - unsigned long flags; - int ret; - - if (copy_from_user(&my_cmd, ifr->ifr_data, sizeof(my_cmd))) - return -EFAULT; - - ret = 0; - switch (my_cmd.cmd) { - case RTLTOOL_READ_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1) - my_cmd.data = readb(tp->mmio_addr+my_cmd.offset); - else if (my_cmd.len==2) - my_cmd.data = readw(tp->mmio_addr+(my_cmd.offset&~1)); - else if (my_cmd.len==4) - my_cmd.data = readl(tp->mmio_addr+(my_cmd.offset&~3)); - else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTLTOOL_WRITE_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1) - writeb(my_cmd.data, tp->mmio_addr+my_cmd.offset); - else if (my_cmd.len==2) - writew(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~1)); - else if (my_cmd.len==4) - writel(my_cmd.data, tp->mmio_addr+(my_cmd.offset&~3)); - else { - ret = -EOPNOTSUPP; - break; - } - - break; - - case RTLTOOL_READ_PHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8168_mdio_prot_read(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_PHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_mdio_prot_write(tp, my_cmd.offset, my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTLTOOL_READ_EPHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8168_ephy_read(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_EPHY: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_ephy_write(tp, my_cmd.offset, my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTLTOOL_READ_ERI: - my_cmd.data = 0; - if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8168_eri_read(tp, my_cmd.offset, my_cmd.len, ERIAR_ExGMAC); - spin_unlock_irqrestore(&tp->lock, flags); - } else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_ERI: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1 || my_cmd.len==2 || my_cmd.len==4) { - spin_lock_irqsave(&tp->lock, flags); - rtl8168_eri_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data, ERIAR_ExGMAC); - spin_unlock_irqrestore(&tp->lock, flags); - } else { - ret = -EOPNOTSUPP; - break; - } - break; - - case RTLTOOL_READ_PCI: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - my_cmd.data = 0; - if (my_cmd.len==1) - pci_read_config_byte(tp->pci_dev, my_cmd.offset, - (u8 *)&my_cmd.data); - else if (my_cmd.len==2) - pci_read_config_word(tp->pci_dev, my_cmd.offset, - (u16 *)&my_cmd.data); - else if (my_cmd.len==4) - pci_read_config_dword(tp->pci_dev, my_cmd.offset, - &my_cmd.data); - else { - ret = -EOPNOTSUPP; - break; - } - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTLTOOL_WRITE_PCI: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len==1) - pci_write_config_byte(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else if (my_cmd.len==2) - pci_write_config_word(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else if (my_cmd.len==4) - pci_write_config_dword(tp->pci_dev, my_cmd.offset, - my_cmd.data); - else { - ret = -EOPNOTSUPP; - break; - } - - break; - - case RTLTOOL_READ_EEPROM: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8168_eeprom_read_sc(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTLTOOL_WRITE_EEPROM: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_eeprom_write_sc(tp, my_cmd.offset, my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTL_READ_OOB_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_oob_mutex_lock(tp); - my_cmd.data = rtl8168_ocp_read(tp, my_cmd.offset, 4); - rtl8168_oob_mutex_unlock(tp); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTL_WRITE_OOB_MAC: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.len == 0 || my_cmd.len > 4) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_oob_mutex_lock(tp); - rtl8168_ocp_write(tp, my_cmd.offset, my_cmd.len, my_cmd.data); - rtl8168_oob_mutex_unlock(tp); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTL_ENABLE_PCI_DIAG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - tp->rtk_enable_diag = 1; - spin_unlock_irqrestore(&tp->lock, flags); - - dprintk("enable rtk diag\n"); - break; - - case RTL_DISABLE_PCI_DIAG: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - tp->rtk_enable_diag = 0; - spin_unlock_irqrestore(&tp->lock, flags); - - dprintk("disable rtk diag\n"); - break; - - case RTL_READ_MAC_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if (my_cmd.offset % 2) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8168_mac_ocp_read(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - break; - - case RTL_WRITE_MAC_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - if ((my_cmd.offset % 2) || (my_cmd.len != 2)) - return -EOPNOTSUPP; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_mac_ocp_write(tp, my_cmd.offset, (u16)my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - case RTL_DIRECT_READ_PHY_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - my_cmd.data = rtl8168_mdio_prot_direct_read_phy_ocp(tp, my_cmd.offset); - spin_unlock_irqrestore(&tp->lock, flags); - - if (copy_to_user(ifr->ifr_data, &my_cmd, sizeof(my_cmd))) { - ret = -EFAULT; - break; - } - - break; - - case RTL_DIRECT_WRITE_PHY_OCP: - if (!capable(CAP_NET_ADMIN)) - return -EPERM; - - spin_lock_irqsave(&tp->lock, flags); - rtl8168_mdio_prot_direct_write_phy_ocp(tp, my_cmd.offset, my_cmd.data); - spin_unlock_irqrestore(&tp->lock, flags); - break; - - default: - ret = -EOPNOTSUPP; - break; - } - - return ret; -} diff --git a/addons/r8168/src/4.4.180/rtltool.h b/addons/r8168/src/4.4.180/rtltool.h deleted file mode 100644 index d8731dff..00000000 --- a/addons/r8168/src/4.4.180/rtltool.h +++ /dev/null @@ -1,86 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* -################################################################################ -# -# r8168 is the Linux device driver released for Realtek Gigabit Ethernet -# controllers with PCI-Express interface. -# -# Copyright(c) 2021 Realtek Semiconductor Corp. All rights reserved. -# -# This program is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License as published by the Free -# Software Foundation; either version 2 of the License, or (at your option) -# any later version. -# -# This program is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for -# more details. -# -# You should have received a copy of the GNU General Public License along with -# this program; if not, see . -# -# Author: -# Realtek NIC software team -# No. 2, Innovation Road II, Hsinchu Science Park, Hsinchu 300, Taiwan -# -################################################################################ -*/ - -/************************************************************************************ - * This product is covered by one or more of the following patents: - * US6,570,884, US6,115,776, and US6,327,625. - ***********************************************************************************/ - -#ifndef _LINUX_RTLTOOL_H -#define _LINUX_RTLTOOL_H - -#define SIOCRTLTOOL SIOCDEVPRIVATE+1 - -enum rtl_cmd { - RTLTOOL_READ_MAC=0, - RTLTOOL_WRITE_MAC, - RTLTOOL_READ_PHY, - RTLTOOL_WRITE_PHY, - RTLTOOL_READ_EPHY, - RTLTOOL_WRITE_EPHY, - RTLTOOL_READ_ERI, - RTLTOOL_WRITE_ERI, - RTLTOOL_READ_PCI, - RTLTOOL_WRITE_PCI, - RTLTOOL_READ_EEPROM, - RTLTOOL_WRITE_EEPROM, - - RTL_READ_OOB_MAC, - RTL_WRITE_OOB_MAC, - - RTL_ENABLE_PCI_DIAG, - RTL_DISABLE_PCI_DIAG, - - RTL_READ_MAC_OCP, - RTL_WRITE_MAC_OCP, - - RTL_DIRECT_READ_PHY_OCP, - RTL_DIRECT_WRITE_PHY_OCP, - - RTLTOOL_INVALID -}; - -struct rtltool_cmd { - __u32 cmd; - __u32 offset; - __u32 len; - __u32 data; -}; - -enum mode_access { - MODE_NONE=0, - MODE_READ, - MODE_WRITE -}; - -#ifdef __KERNEL__ -int rtl8168_tool_ioctl(struct rtl8168_private *tp, struct ifreq *ifr); -#endif - -#endif /* _LINUX_RTLTOOL_H */ diff --git a/addons/r8169/install.sh b/addons/r8169/install.sh deleted file mode 100644 index d1e3f082..00000000 --- a/addons/r8169/install.sh +++ /dev/null @@ -1,5 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Installing module for Realtek R8169 Ethernet adapter" - ${INSMOD} "/modules/mii.ko" - ${INSMOD} "/modules/r8169.ko" ${PARAMS} -fi diff --git a/addons/r8169/manifest.yml b/addons/r8169/manifest.yml deleted file mode 100644 index d09dc879..00000000 --- a/addons/r8169/manifest.yml +++ /dev/null @@ -1,30 +0,0 @@ -version: 1 -name: r8169 -description: "Driver for Realtek R8169 Ethernet adapters" -conflits: - - r8168 -available-for: - bromolow-3.10.108: - install-script: &script "install.sh" - modules: true - apollolake-4.4.180: - install-script: *script - modules: true - broadwell-4.4.180: - install-script: *script - modules: true - broadwellnk-4.4.180: - install-script: *script - modules: true - denverton-4.4.180: - install-script: *script - modules: true - geminilake-4.4.180: - install-script: *script - modules: true - v1000-4.4.180: - install-script: *script - modules: true - purley-4.4.180: - install-script: *script - modules: true diff --git a/addons/r8169/src/3.10.108/Makefile b/addons/r8169/src/3.10.108/Makefile deleted file mode 100644 index 340f8cbe..00000000 --- a/addons/r8169/src/3.10.108/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-m += r8169.o -obj-m += mii.o diff --git a/addons/r8169/src/3.10.108/mii.c b/addons/r8169/src/3.10.108/mii.c deleted file mode 100644 index 4a99c391..00000000 --- a/addons/r8169/src/3.10.108/mii.c +++ /dev/null @@ -1,472 +0,0 @@ -/* - - mii.c: MII interface library - - Maintained by Jeff Garzik - Copyright 2001,2002 Jeff Garzik - - Various code came from myson803.c and other files by - Donald Becker. Copyright: - - Written 1998-2002 by Donald Becker. - - This software may be used and distributed according - to the terms of the GNU General Public License (GPL), - incorporated herein by reference. Drivers based on - or derived from this code fall under the GPL and must - retain the authorship, copyright and license notice. - This file is not a complete program and may only be - used when the entire operating system is licensed - under the GPL. - - The author may be reached as becker@scyld.com, or C/O - Scyld Computing Corporation - 410 Severn Ave., Suite 210 - Annapolis MD 21403 - - - */ - -#include -#include -#include -#include -#include - -static u32 mii_get_an(struct mii_if_info *mii, u16 addr) -{ - int advert; - - advert = mii->mdio_read(mii->dev, mii->phy_id, addr); - - return mii_lpa_to_ethtool_lpa_t(advert); -} - -/** - * mii_ethtool_gset - get settings that are specified in @ecmd - * @mii: MII interface - * @ecmd: requested ethtool_cmd - * - * The @ecmd parameter is expected to have been cleared before calling - * mii_ethtool_gset(). - * - * Returns 0 for success, negative on error. - */ -int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) -{ - struct net_device *dev = mii->dev; - u16 bmcr, bmsr, ctrl1000 = 0, stat1000 = 0; - u32 nego; - - ecmd->supported = - (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); - if (mii->supports_gmii) - ecmd->supported |= SUPPORTED_1000baseT_Half | - SUPPORTED_1000baseT_Full; - - /* only supports twisted-pair */ - ecmd->port = PORT_MII; - - /* only supports internal transceiver */ - ecmd->transceiver = XCVR_INTERNAL; - - /* this isn't fully supported at higher layers */ - ecmd->phy_address = mii->phy_id; - ecmd->mdio_support = ETH_MDIO_SUPPORTS_C22; - - ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII; - - bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); - bmsr = mii->mdio_read(dev, mii->phy_id, MII_BMSR); - if (mii->supports_gmii) { - ctrl1000 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); - stat1000 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000); - } - if (bmcr & BMCR_ANENABLE) { - ecmd->advertising |= ADVERTISED_Autoneg; - ecmd->autoneg = AUTONEG_ENABLE; - - ecmd->advertising |= mii_get_an(mii, MII_ADVERTISE); - if (mii->supports_gmii) - ecmd->advertising |= - mii_ctrl1000_to_ethtool_adv_t(ctrl1000); - - if (bmsr & BMSR_ANEGCOMPLETE) { - ecmd->lp_advertising = mii_get_an(mii, MII_LPA); - ecmd->lp_advertising |= - mii_stat1000_to_ethtool_lpa_t(stat1000); - } else { - ecmd->lp_advertising = 0; - } - - nego = ecmd->advertising & ecmd->lp_advertising; - - if (nego & (ADVERTISED_1000baseT_Full | - ADVERTISED_1000baseT_Half)) { - ethtool_cmd_speed_set(ecmd, SPEED_1000); - ecmd->duplex = !!(nego & ADVERTISED_1000baseT_Full); - } else if (nego & (ADVERTISED_100baseT_Full | - ADVERTISED_100baseT_Half)) { - ethtool_cmd_speed_set(ecmd, SPEED_100); - ecmd->duplex = !!(nego & ADVERTISED_100baseT_Full); - } else { - ethtool_cmd_speed_set(ecmd, SPEED_10); - ecmd->duplex = !!(nego & ADVERTISED_10baseT_Full); - } - } else { - ecmd->autoneg = AUTONEG_DISABLE; - - ethtool_cmd_speed_set(ecmd, - ((bmcr & BMCR_SPEED1000 && - (bmcr & BMCR_SPEED100) == 0) ? - SPEED_1000 : - ((bmcr & BMCR_SPEED100) ? - SPEED_100 : SPEED_10))); - ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; - } - - mii->full_duplex = ecmd->duplex; - - /* ignore maxtxpkt, maxrxpkt for now */ - - return 0; -} - -/** - * mii_ethtool_sset - set settings that are specified in @ecmd - * @mii: MII interface - * @ecmd: requested ethtool_cmd - * - * Returns 0 for success, negative on error. - */ -int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) -{ - struct net_device *dev = mii->dev; - u32 speed = ethtool_cmd_speed(ecmd); - - if (speed != SPEED_10 && - speed != SPEED_100 && - speed != SPEED_1000) - return -EINVAL; - if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) - return -EINVAL; - if (ecmd->port != PORT_MII) - return -EINVAL; - if (ecmd->transceiver != XCVR_INTERNAL) - return -EINVAL; - if (ecmd->phy_address != mii->phy_id) - return -EINVAL; - if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) - return -EINVAL; - if ((speed == SPEED_1000) && (!mii->supports_gmii)) - return -EINVAL; - - /* ignore supported, maxtxpkt, maxrxpkt */ - - if (ecmd->autoneg == AUTONEG_ENABLE) { - u32 bmcr, advert, tmp; - u32 advert2 = 0, tmp2 = 0; - - if ((ecmd->advertising & (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full)) == 0) - return -EINVAL; - - /* advertise only what has been requested */ - advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); - tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4); - if (mii->supports_gmii) { - advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); - tmp2 = advert2 & ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - } - tmp |= ethtool_adv_to_mii_adv_t(ecmd->advertising); - - if (mii->supports_gmii) - tmp2 |= - ethtool_adv_to_mii_ctrl1000_t(ecmd->advertising); - if (advert != tmp) { - mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp); - mii->advertising = tmp; - } - if ((mii->supports_gmii) && (advert2 != tmp2)) - mii->mdio_write(dev, mii->phy_id, MII_CTRL1000, tmp2); - - /* turn on autonegotiation, and force a renegotiate */ - bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); - bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); - mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr); - - mii->force_media = 0; - } else { - u32 bmcr, tmp; - - /* turn off auto negotiation, set speed and duplexity */ - bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); - tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | - BMCR_SPEED1000 | BMCR_FULLDPLX); - if (speed == SPEED_1000) - tmp |= BMCR_SPEED1000; - else if (speed == SPEED_100) - tmp |= BMCR_SPEED100; - if (ecmd->duplex == DUPLEX_FULL) { - tmp |= BMCR_FULLDPLX; - mii->full_duplex = 1; - } else - mii->full_duplex = 0; - if (bmcr != tmp) - mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp); - - mii->force_media = 1; - } - return 0; -} - -/** - * mii_check_gmii_support - check if the MII supports Gb interfaces - * @mii: the MII interface - */ -int mii_check_gmii_support(struct mii_if_info *mii) -{ - int reg; - - reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); - if (reg & BMSR_ESTATEN) { - reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS); - if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF)) - return 1; - } - - return 0; -} - -/** - * mii_link_ok - is link status up/ok - * @mii: the MII interface - * - * Returns 1 if the MII reports link status up/ok, 0 otherwise. - */ -int mii_link_ok (struct mii_if_info *mii) -{ - /* first, a dummy read, needed to latch some MII phys */ - mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); - if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS) - return 1; - return 0; -} - -/** - * mii_nway_restart - restart NWay (autonegotiation) for this interface - * @mii: the MII interface - * - * Returns 0 on success, negative on error. - */ -int mii_nway_restart (struct mii_if_info *mii) -{ - int bmcr; - int r = -EINVAL; - - /* if autoneg is off, it's an error */ - bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR); - - if (bmcr & BMCR_ANENABLE) { - bmcr |= BMCR_ANRESTART; - mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr); - r = 0; - } - - return r; -} - -/** - * mii_check_link - check MII link status - * @mii: MII interface - * - * If the link status changed (previous != current), call - * netif_carrier_on() if current link status is Up or call - * netif_carrier_off() if current link status is Down. - */ -void mii_check_link (struct mii_if_info *mii) -{ - int cur_link = mii_link_ok(mii); - int prev_link = netif_carrier_ok(mii->dev); - - if (cur_link && !prev_link) - netif_carrier_on(mii->dev); - else if (prev_link && !cur_link) - netif_carrier_off(mii->dev); -} - -/** - * mii_check_media - check the MII interface for a duplex change - * @mii: the MII interface - * @ok_to_print: OK to print link up/down messages - * @init_media: OK to save duplex mode in @mii - * - * Returns 1 if the duplex mode changed, 0 if not. - * If the media type is forced, always returns 0. - */ -unsigned int mii_check_media (struct mii_if_info *mii, - unsigned int ok_to_print, - unsigned int init_media) -{ - unsigned int old_carrier, new_carrier; - int advertise, lpa, media, duplex; - int lpa2 = 0; - - /* if forced media, go no further */ - if (mii->force_media) - return 0; /* duplex did not change */ - - /* check current and old link status */ - old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0; - new_carrier = (unsigned int) mii_link_ok(mii); - - /* if carrier state did not change, this is a "bounce", - * just exit as everything is already set correctly - */ - if ((!init_media) && (old_carrier == new_carrier)) - return 0; /* duplex did not change */ - - /* no carrier, nothing much to do */ - if (!new_carrier) { - netif_carrier_off(mii->dev); - if (ok_to_print) - netdev_info(mii->dev, "link down\n"); - return 0; /* duplex did not change */ - } - - /* - * we have carrier, see who's on the other end - */ - netif_carrier_on(mii->dev); - - /* get MII advertise and LPA values */ - if ((!init_media) && (mii->advertising)) - advertise = mii->advertising; - else { - advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE); - mii->advertising = advertise; - } - lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA); - if (mii->supports_gmii) - lpa2 = mii->mdio_read(mii->dev, mii->phy_id, MII_STAT1000); - - /* figure out media and duplex from advertise and LPA values */ - media = mii_nway_result(lpa & advertise); - duplex = (media & ADVERTISE_FULL) ? 1 : 0; - if (lpa2 & LPA_1000FULL) - duplex = 1; - - if (ok_to_print) - netdev_info(mii->dev, "link up, %uMbps, %s-duplex, lpa 0x%04X\n", - lpa2 & (LPA_1000FULL | LPA_1000HALF) ? 1000 : - media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? - 100 : 10, - duplex ? "full" : "half", - lpa); - - if ((init_media) || (mii->full_duplex != duplex)) { - mii->full_duplex = duplex; - return 1; /* duplex changed */ - } - - return 0; /* duplex did not change */ -} - -/** - * generic_mii_ioctl - main MII ioctl interface - * @mii_if: the MII interface - * @mii_data: MII ioctl data structure - * @cmd: MII ioctl command - * @duplex_chg_out: pointer to @duplex_changed status if there was no - * ioctl error - * - * Returns 0 on success, negative on error. - */ -int generic_mii_ioctl(struct mii_if_info *mii_if, - struct mii_ioctl_data *mii_data, int cmd, - unsigned int *duplex_chg_out) -{ - int rc = 0; - unsigned int duplex_changed = 0; - - if (duplex_chg_out) - *duplex_chg_out = 0; - - mii_data->phy_id &= mii_if->phy_id_mask; - mii_data->reg_num &= mii_if->reg_num_mask; - - switch(cmd) { - case SIOCGMIIPHY: - mii_data->phy_id = mii_if->phy_id; - /* fall through */ - - case SIOCGMIIREG: - mii_data->val_out = - mii_if->mdio_read(mii_if->dev, mii_data->phy_id, - mii_data->reg_num); - break; - - case SIOCSMIIREG: { - u16 val = mii_data->val_in; - - if (mii_data->phy_id == mii_if->phy_id) { - switch(mii_data->reg_num) { - case MII_BMCR: { - unsigned int new_duplex = 0; - if (val & (BMCR_RESET|BMCR_ANENABLE)) - mii_if->force_media = 0; - else - mii_if->force_media = 1; - if (mii_if->force_media && - (val & BMCR_FULLDPLX)) - new_duplex = 1; - if (mii_if->full_duplex != new_duplex) { - duplex_changed = 1; - mii_if->full_duplex = new_duplex; - } - break; - } - case MII_ADVERTISE: - mii_if->advertising = val; - break; - default: - /* do nothing */ - break; - } - } - - mii_if->mdio_write(mii_if->dev, mii_data->phy_id, - mii_data->reg_num, val); - break; - } - - default: - rc = -EOPNOTSUPP; - break; - } - - if ((rc == 0) && (duplex_chg_out) && (duplex_changed)) - *duplex_chg_out = 1; - - return rc; -} - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("MII hardware support library"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(mii_link_ok); -EXPORT_SYMBOL(mii_nway_restart); -EXPORT_SYMBOL(mii_ethtool_gset); -EXPORT_SYMBOL(mii_ethtool_sset); -EXPORT_SYMBOL(mii_check_link); -EXPORT_SYMBOL(mii_check_media); -EXPORT_SYMBOL(mii_check_gmii_support); -EXPORT_SYMBOL(generic_mii_ioctl); - diff --git a/addons/r8169/src/3.10.108/r8169.c b/addons/r8169/src/3.10.108/r8169.c deleted file mode 100644 index 2183c618..00000000 --- a/addons/r8169/src/3.10.108/r8169.c +++ /dev/null @@ -1,7150 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "r8169" -#define PFX MODULENAME ": " - -#define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw" -#define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw" -#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw" -#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw" -#define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw" -#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw" -#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw" -#define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw" -#define FIRMWARE_8402_1 "rtl_nic/rtl8402-1.fw" -#define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw" -#define FIRMWARE_8106E_1 "rtl_nic/rtl8106e-1.fw" -#define FIRMWARE_8106E_2 "rtl_nic/rtl8106e-2.fw" -#define FIRMWARE_8168G_2 "rtl_nic/rtl8168g-2.fw" -#define FIRMWARE_8168G_3 "rtl_nic/rtl8168g-3.fw" - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_SLOTS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx) - -/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */ -#define TX_FRAGS_READY_FOR(tp,nr_frags) \ - (TX_SLOTS_AVAIL(tp) >= (nr_frags + 1)) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -#define MAX_READ_REQUEST_SHIFT 12 -#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256U /* Number of Rx descriptor registers */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) readl (ioaddr + (reg)) - -enum mac_version { - RTL_GIGA_MAC_VER_01 = 0, - RTL_GIGA_MAC_VER_02, - RTL_GIGA_MAC_VER_03, - RTL_GIGA_MAC_VER_04, - RTL_GIGA_MAC_VER_05, - RTL_GIGA_MAC_VER_06, - RTL_GIGA_MAC_VER_07, - RTL_GIGA_MAC_VER_08, - RTL_GIGA_MAC_VER_09, - RTL_GIGA_MAC_VER_10, - RTL_GIGA_MAC_VER_11, - RTL_GIGA_MAC_VER_12, - RTL_GIGA_MAC_VER_13, - RTL_GIGA_MAC_VER_14, - RTL_GIGA_MAC_VER_15, - RTL_GIGA_MAC_VER_16, - RTL_GIGA_MAC_VER_17, - RTL_GIGA_MAC_VER_18, - RTL_GIGA_MAC_VER_19, - RTL_GIGA_MAC_VER_20, - RTL_GIGA_MAC_VER_21, - RTL_GIGA_MAC_VER_22, - RTL_GIGA_MAC_VER_23, - RTL_GIGA_MAC_VER_24, - RTL_GIGA_MAC_VER_25, - RTL_GIGA_MAC_VER_26, - RTL_GIGA_MAC_VER_27, - RTL_GIGA_MAC_VER_28, - RTL_GIGA_MAC_VER_29, - RTL_GIGA_MAC_VER_30, - RTL_GIGA_MAC_VER_31, - RTL_GIGA_MAC_VER_32, - RTL_GIGA_MAC_VER_33, - RTL_GIGA_MAC_VER_34, - RTL_GIGA_MAC_VER_35, - RTL_GIGA_MAC_VER_36, - RTL_GIGA_MAC_VER_37, - RTL_GIGA_MAC_VER_38, - RTL_GIGA_MAC_VER_39, - RTL_GIGA_MAC_VER_40, - RTL_GIGA_MAC_VER_41, - RTL_GIGA_MAC_VER_42, - RTL_GIGA_MAC_VER_43, - RTL_GIGA_MAC_NONE = 0xff, -}; - -enum rtl_tx_desc_version { - RTL_TD_0 = 0, - RTL_TD_1 = 1, -}; - -#define JUMBO_1K ETH_DATA_LEN -#define JUMBO_4K (4*1024 - ETH_HLEN - 2) -#define JUMBO_6K (6*1024 - ETH_HLEN - 2) -#define JUMBO_7K (7*1024 - ETH_HLEN - 2) -#define JUMBO_9K (9*1024 - ETH_HLEN - 2) - -#define _R(NAME,TD,FW,SZ,B) { \ - .name = NAME, \ - .txd_version = TD, \ - .fw_name = FW, \ - .jumbo_max = SZ, \ - .jumbo_tx_csum = B \ -} - -static const struct { - const char *name; - enum rtl_tx_desc_version txd_version; - const char *fw_name; - u16 jumbo_max; - bool jumbo_tx_csum; -} rtl_chip_infos[] = { - /* PCI devices. */ - [RTL_GIGA_MAC_VER_01] = - _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true), - [RTL_GIGA_MAC_VER_02] = - _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true), - [RTL_GIGA_MAC_VER_03] = - _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true), - [RTL_GIGA_MAC_VER_04] = - _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true), - [RTL_GIGA_MAC_VER_05] = - _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true), - [RTL_GIGA_MAC_VER_06] = - _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true), - /* PCI-E devices. */ - [RTL_GIGA_MAC_VER_07] = - _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_08] = - _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_09] = - _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_10] = - _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_11] = - _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), - [RTL_GIGA_MAC_VER_12] = - _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), - [RTL_GIGA_MAC_VER_13] = - _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_14] = - _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_15] = - _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_16] = - _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_17] = - _R("RTL8168b/8111b", RTL_TD_1, NULL, JUMBO_4K, false), - [RTL_GIGA_MAC_VER_18] = - _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_19] = - _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_20] = - _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_21] = - _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_22] = - _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_23] = - _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_24] = - _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_25] = - _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_26] = - _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_27] = - _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), - [RTL_GIGA_MAC_VER_28] = - _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), - [RTL_GIGA_MAC_VER_29] = - _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1, - JUMBO_1K, true), - [RTL_GIGA_MAC_VER_30] = - _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1, - JUMBO_1K, true), - [RTL_GIGA_MAC_VER_31] = - _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), - [RTL_GIGA_MAC_VER_32] = - _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_33] = - _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_34] = - _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_35] = - _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_1, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_36] = - _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_37] = - _R("RTL8402", RTL_TD_1, FIRMWARE_8402_1, - JUMBO_1K, true), - [RTL_GIGA_MAC_VER_38] = - _R("RTL8411", RTL_TD_1, FIRMWARE_8411_1, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_39] = - _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_1, - JUMBO_1K, true), - [RTL_GIGA_MAC_VER_40] = - _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_2, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_41] = - _R("RTL8168g/8111g", RTL_TD_1, NULL, JUMBO_9K, false), - [RTL_GIGA_MAC_VER_42] = - _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_3, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_43] = - _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_2, - JUMBO_1K, true), -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static DEFINE_PCI_DEVICE_TABLE(rtl8169_pci_tbl) = { - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_DLINK, 0x4300, - PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_buf_sz = 16383; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - - TxConfig = 0x40, -#define TXCFG_AUTO_FIFO (1 << 7) /* 8111e-vl */ -#define TXCFG_EMPTY (1 << 11) /* 8111e-vl */ - - RxConfig = 0x44, -#define RX128_INT_EN (1 << 15) /* 8111c and later */ -#define RX_MULTI_EN (1 << 14) /* 8111c only */ -#define RXCFG_FIFO_SHIFT 13 - /* No threshold before first PCI xfer */ -#define RX_FIFO_THRESH (7 << RXCFG_FIFO_SHIFT) -#define RX_EARLY_OFF (1 << 11) -#define RXCFG_DMA_SHIFT 8 - /* Unlimited maximum PCI burst. */ -#define RX_DMA_BURST (7 << RXCFG_DMA_SHIFT) - - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, -#define PME_SIGNAL (1 << 5) /* 8168c and later */ - - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, /* 8169. Unit of 32 bytes. */ - -#define NoEarlyTx 0x3f /* Max value : no early transmit. */ - - MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */ - -#define TxPacketMax (8064 >> 7) -#define EarlySize 0x27 - - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff -#define CSIAR_FUNC_CARD 0x00000000 -#define CSIAR_FUNC_SDIO 0x00010000 -#define CSIAR_FUNC_NIC 0x00020000 - PMCH = 0x6f, - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DLLPR = 0xd0, -#define PFM_EN (1 << 6) - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) - TWSI = 0xd2, - MCU = 0xd3, -#define NOW_IS_OOB (1 << 7) -#define TX_EMPTY (1 << 5) -#define RX_EMPTY (1 << 4) -#define RXTX_EMPTY (TX_EMPTY | RX_EMPTY) -#define EN_NDP (1 << 3) -#define EN_OOB_RESET (1 << 2) -#define LINK_LIST_RDY (1 << 1) - EFUSEAR = 0xdc, -#define EFUSEAR_FLAG 0x80000000 -#define EFUSEAR_WRITE_CMD 0x80000000 -#define EFUSEAR_READ_CMD 0x00000000 -#define EFUSEAR_REG_MASK 0x03ff -#define EFUSEAR_REG_SHIFT 8 -#define EFUSEAR_DATA_MASK 0xff -}; - -enum rtl8168_registers { - LED_FREQ = 0x1a, - EEE_LED = 0x1b, - ERIDR = 0x70, - ERIAR = 0x74, -#define ERIAR_FLAG 0x80000000 -#define ERIAR_WRITE_CMD 0x80000000 -#define ERIAR_READ_CMD 0x00000000 -#define ERIAR_ADDR_BYTE_ALIGN 4 -#define ERIAR_TYPE_SHIFT 16 -#define ERIAR_EXGMAC (0x00 << ERIAR_TYPE_SHIFT) -#define ERIAR_MSIX (0x01 << ERIAR_TYPE_SHIFT) -#define ERIAR_ASF (0x02 << ERIAR_TYPE_SHIFT) -#define ERIAR_MASK_SHIFT 12 -#define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT) -#define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT) -#define ERIAR_MASK_0101 (0x5 << ERIAR_MASK_SHIFT) -#define ERIAR_MASK_1111 (0xf << ERIAR_MASK_SHIFT) - EPHY_RXER_NUM = 0x7c, - OCPDR = 0xb0, /* OCP GPHY access */ -#define OCPDR_WRITE_CMD 0x80000000 -#define OCPDR_READ_CMD 0x00000000 -#define OCPDR_REG_MASK 0x7f -#define OCPDR_GPHY_REG_SHIFT 16 -#define OCPDR_DATA_MASK 0xffff - OCPAR = 0xb4, -#define OCPAR_FLAG 0x80000000 -#define OCPAR_GPHY_WRITE_CMD 0x8000f060 -#define OCPAR_GPHY_READ_CMD 0x0000f060 - GPHY_OCP = 0xb8, - RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */ - MISC = 0xf0, /* 8168e only. */ -#define TXPLA_RST (1 << 29) -#define DISABLE_LAN_EN (1 << 23) /* Enable GPIO pin */ -#define PWM_EN (1 << 22) -#define RXDV_GATED_EN (1 << 19) -#define EARLY_TALLY_EN (1 << 16) -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxBOVF = (1 << 24), - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - StopReq = 0x80, - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -#define RX_CONFIG_ACCEPT_MASK 0x3f - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - ClkReqEn = (1 << 7), /* Clock Request Enable */ - MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config4 register */ - Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - Spi_en = (1 << 3), - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - ASPM_en = (1 << 0), /* ASPM enable */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* DumpCounterCommand */ - CounterDump = 0x8, -}; - -enum rtl_desc_bit { - /* First doubleword. */ - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ -}; - -/* Generic case. */ -enum rtl_tx_desc_bit { - /* First doubleword. */ - TD_LSO = (1 << 27), /* Large Send Offload */ -#define TD_MSS_MAX 0x07ffu /* MSS value */ - - /* Second doubleword. */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ -}; - -/* 8169, 8168b and 810x except 8102e. */ -enum rtl_tx_desc_bit_0 { - /* First doubleword. */ -#define TD0_MSS_SHIFT 16 /* MSS position (11 bits) */ - TD0_TCP_CS = (1 << 16), /* Calculate TCP/IP checksum */ - TD0_UDP_CS = (1 << 17), /* Calculate UDP/IP checksum */ - TD0_IP_CS = (1 << 18), /* Calculate IP checksum */ -}; - -/* 8102e, 8168c and beyond. */ -enum rtl_tx_desc_bit_1 { - /* Second doubleword. */ -#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */ - TD1_IP_CS = (1 << 29), /* Calculate IP checksum */ - TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */ - TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */ -}; - -static const struct rtl_tx_desc_info { - struct { - u32 udp; - u32 tcp; - } checksum; - u16 mss_shift; - u16 opts_offset; -} tx_desc_info [] = { - [RTL_TD_0] = { - .checksum = { - .udp = TD0_IP_CS | TD0_UDP_CS, - .tcp = TD0_IP_CS | TD0_TCP_CS - }, - .mss_shift = TD0_MSS_SHIFT, - .opts_offset = 0 - }, - [RTL_TD_1] = { - .checksum = { - .udp = TD1_IP_CS | TD1_UDP_CS, - .tcp = TD1_IP_CS | TD1_TCP_CS - }, - .mss_shift = TD1_MSS_SHIFT, - .opts_offset = 1 - } -}; - -enum rtl_rx_desc_bit { - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -enum rtl_flag { - RTL_FLAG_TASK_ENABLED, - RTL_FLAG_TASK_SLOW_PENDING, - RTL_FLAG_TASK_RESET_PENDING, - RTL_FLAG_TASK_PHY_PENDING, - RTL_FLAG_MAX -}; - -struct rtl8169_stats { - u64 packets; - u64 bytes; - struct u64_stats_sync syncp; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; - struct net_device *dev; - struct napi_struct napi; - u32 msg_enable; - u16 txd_version; - u16 mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_tx; - struct rtl8169_stats rx_stats; - struct rtl8169_stats tx_stats; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - struct timer_list timer; - u16 cp_cmd; - - u16 event_slow; - - struct mdio_ops { - void (*write)(struct rtl8169_private *, int, int); - int (*read)(struct rtl8169_private *, int); - } mdio_ops; - - struct pll_power_ops { - void (*down)(struct rtl8169_private *); - void (*up)(struct rtl8169_private *); - } pll_power_ops; - - struct jumbo_ops { - void (*enable)(struct rtl8169_private *); - void (*disable)(struct rtl8169_private *); - } jumbo_ops; - - struct csi_ops { - void (*write)(struct rtl8169_private *, int, int); - u32 (*read)(struct rtl8169_private *, int); - } csi_ops; - - int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(struct rtl8169_private *tp); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(struct rtl8169_private *tp); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - - struct { - DECLARE_BITMAP(flags, RTL_FLAG_MAX); - struct mutex mutex; - struct work_struct work; - } wk; - - unsigned features; - - struct mii_if_info mii; - struct rtl8169_counters counters; - u32 saved_wolopts; - u32 opts1_mask; - - struct rtl_fw { - const struct firmware *fw; - -#define RTL_VER_SIZE 32 - - char version[RTL_VER_SIZE]; - - struct rtl_fw_phy_action { - __le32 *code; - size_t size; - } phy_action; - } *rtl_fw; -#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN) - - u32 ocp_base; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(RTL8169_VERSION); -MODULE_FIRMWARE(FIRMWARE_8168D_1); -MODULE_FIRMWARE(FIRMWARE_8168D_2); -MODULE_FIRMWARE(FIRMWARE_8168E_1); -MODULE_FIRMWARE(FIRMWARE_8168E_2); -MODULE_FIRMWARE(FIRMWARE_8168E_3); -MODULE_FIRMWARE(FIRMWARE_8105E_1); -MODULE_FIRMWARE(FIRMWARE_8168F_1); -MODULE_FIRMWARE(FIRMWARE_8168F_2); -MODULE_FIRMWARE(FIRMWARE_8402_1); -MODULE_FIRMWARE(FIRMWARE_8411_1); -MODULE_FIRMWARE(FIRMWARE_8106E_1); -MODULE_FIRMWARE(FIRMWARE_8106E_2); -MODULE_FIRMWARE(FIRMWARE_8168G_2); -MODULE_FIRMWARE(FIRMWARE_8168G_3); - -static void rtl_lock_work(struct rtl8169_private *tp) -{ - mutex_lock(&tp->wk.mutex); -} - -static void rtl_unlock_work(struct rtl8169_private *tp) -{ - mutex_unlock(&tp->wk.mutex); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_READRQ, force); -} - -struct rtl_cond { - bool (*check)(struct rtl8169_private *); - const char *msg; -}; - -static void rtl_udelay(unsigned int d) -{ - udelay(d); -} - -static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c, - void (*delay)(unsigned int), unsigned int d, int n, - bool high) -{ - int i; - - for (i = 0; i < n; i++) { - delay(d); - if (c->check(tp) == high) - return true; - } - netif_err(tp, drv, tp->dev, "%s == %d (loop: %d, delay: %d).\n", - c->msg, !high, n, d); - return false; -} - -static bool rtl_udelay_loop_wait_high(struct rtl8169_private *tp, - const struct rtl_cond *c, - unsigned int d, int n) -{ - return rtl_loop_wait(tp, c, rtl_udelay, d, n, true); -} - -static bool rtl_udelay_loop_wait_low(struct rtl8169_private *tp, - const struct rtl_cond *c, - unsigned int d, int n) -{ - return rtl_loop_wait(tp, c, rtl_udelay, d, n, false); -} - -static bool rtl_msleep_loop_wait_high(struct rtl8169_private *tp, - const struct rtl_cond *c, - unsigned int d, int n) -{ - return rtl_loop_wait(tp, c, msleep, d, n, true); -} - -static bool rtl_msleep_loop_wait_low(struct rtl8169_private *tp, - const struct rtl_cond *c, - unsigned int d, int n) -{ - return rtl_loop_wait(tp, c, msleep, d, n, false); -} - -#define DECLARE_RTL_COND(name) \ -static bool name ## _check(struct rtl8169_private *); \ - \ -static const struct rtl_cond name = { \ - .check = name ## _check, \ - .msg = #name \ -}; \ - \ -static bool name ## _check(struct rtl8169_private *tp) - -DECLARE_RTL_COND(rtl_ocpar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(OCPAR) & OCPAR_FLAG; -} - -static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff)); - - return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ? - RTL_R32(OCPDR) : ~0; -} - -static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(OCPDR, data); - RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff)); - - rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20); -} - -DECLARE_RTL_COND(rtl_eriar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(ERIAR) & ERIAR_FLAG; -} - -static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(ERIDR, cmd); - RTL_W32(ERIAR, 0x800010e8); - msleep(2); - - if (!rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 5)) - return; - - ocp_write(tp, 0x1, 0x30, 0x00000001); -} - -#define OOB_CMD_RESET 0x00 -#define OOB_CMD_DRIVER_START 0x05 -#define OOB_CMD_DRIVER_STOP 0x06 - -static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp) -{ - return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10; -} - -DECLARE_RTL_COND(rtl_ocp_read_cond) -{ - u16 reg; - - reg = rtl8168_get_ocp_reg(tp); - - return ocp_read(tp, 0x0f, reg) & 0x00000800; -} - -static void rtl8168_driver_start(struct rtl8169_private *tp) -{ - rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START); - - rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10); -} - -static void rtl8168_driver_stop(struct rtl8169_private *tp) -{ - rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP); - - rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10); -} - -static int r8168dp_check_dash(struct rtl8169_private *tp) -{ - u16 reg = rtl8168_get_ocp_reg(tp); - - return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0; -} - -static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg) -{ - if (reg & 0xffff0001) { - netif_err(tp, drv, tp->dev, "Invalid ocp reg %x!\n", reg); - return true; - } - return false; -} - -DECLARE_RTL_COND(rtl_ocp_gphy_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(GPHY_OCP) & OCPAR_FLAG; -} - -static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_ocp_reg_failure(tp, reg)) - return; - - RTL_W32(GPHY_OCP, OCPAR_FLAG | (reg << 15) | data); - - rtl_udelay_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10); -} - -static u16 r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_ocp_reg_failure(tp, reg)) - return 0; - - RTL_W32(GPHY_OCP, reg << 15); - - return rtl_udelay_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ? - (RTL_R32(GPHY_OCP) & 0xffff) : ~0; -} - -static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_ocp_reg_failure(tp, reg)) - return; - - RTL_W32(OCPDR, OCPAR_FLAG | (reg << 15) | data); -} - -static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_ocp_reg_failure(tp, reg)) - return 0; - - RTL_W32(OCPDR, reg << 15); - - return RTL_R32(OCPDR); -} - -#define OCP_STD_PHY_BASE 0xa400 - -static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value) -{ - if (reg == 0x1f) { - tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE; - return; - } - - if (tp->ocp_base != OCP_STD_PHY_BASE) - reg -= 0x10; - - r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value); -} - -static int r8168g_mdio_read(struct rtl8169_private *tp, int reg) -{ - if (tp->ocp_base != OCP_STD_PHY_BASE) - reg -= 0x10; - - return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2); -} - -static void mac_mcu_write(struct rtl8169_private *tp, int reg, int value) -{ - if (reg == 0x1f) { - tp->ocp_base = value << 4; - return; - } - - r8168_mac_ocp_write(tp, tp->ocp_base + reg, value); -} - -static int mac_mcu_read(struct rtl8169_private *tp, int reg) -{ - return r8168_mac_ocp_read(tp, tp->ocp_base + reg); -} - -DECLARE_RTL_COND(rtl_phyar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(PHYAR) & 0x80000000; -} - -static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff)); - - rtl_udelay_loop_wait_low(tp, &rtl_phyar_cond, 25, 20); - /* - * According to hardware specs a 20us delay is required after write - * complete indication, but before sending next command. - */ - udelay(20); -} - -static int r8169_mdio_read(struct rtl8169_private *tp, int reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - int value; - - RTL_W32(PHYAR, 0x0 | (reg & 0x1f) << 16); - - value = rtl_udelay_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ? - RTL_R32(PHYAR) & 0xffff : ~0; - - /* - * According to hardware specs a 20us delay is required after read - * complete indication, but before sending next command. - */ - udelay(20); - - return value; -} - -static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT)); - RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD); - RTL_W32(EPHY_RXER_NUM, 0); - - rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100); -} - -static void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value) -{ - r8168dp_1_mdio_access(tp, reg, - OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK)); -} - -static int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - - r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD); - - mdelay(1); - RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD); - RTL_W32(EPHY_RXER_NUM, 0); - - return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ? - RTL_R32(OCPDR) & OCPDR_DATA_MASK : ~0; -} - -#define R8168DP_1_MDIO_ACCESS_BIT 0x00020000 - -static void r8168dp_2_mdio_start(void __iomem *ioaddr) -{ - RTL_W32(0xd0, RTL_R32(0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT); -} - -static void r8168dp_2_mdio_stop(void __iomem *ioaddr) -{ - RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT); -} - -static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value) -{ - void __iomem *ioaddr = tp->mmio_addr; - - r8168dp_2_mdio_start(ioaddr); - - r8169_mdio_write(tp, reg, value); - - r8168dp_2_mdio_stop(ioaddr); -} - -static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - int value; - - r8168dp_2_mdio_start(ioaddr); - - value = r8169_mdio_read(tp, reg); - - r8168dp_2_mdio_stop(ioaddr); - - return value; -} - -static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val) -{ - tp->mdio_ops.write(tp, location, val); -} - -static int rtl_readphy(struct rtl8169_private *tp, int location) -{ - return tp->mdio_ops.read(tp, location); -} - -static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value) -{ - rtl_writephy(tp, reg_addr, rtl_readphy(tp, reg_addr) | value); -} - -static void rtl_w1w0_phy(struct rtl8169_private *tp, int reg_addr, int p, int m) -{ - int val; - - val = rtl_readphy(tp, reg_addr); - rtl_writephy(tp, reg_addr, (val | p) & ~m); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl_writephy(tp, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return rtl_readphy(tp, location); -} - -DECLARE_RTL_COND(rtl_ephyar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(EPHYAR) & EPHYAR_FLAG; -} - -static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - rtl_udelay_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100); - - udelay(10); -} - -static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - return rtl_udelay_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ? - RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0; -} - -static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask, - u32 val, int type) -{ - void __iomem *ioaddr = tp->mmio_addr; - - BUG_ON((addr & 3) || (mask == 0)); - RTL_W32(ERIDR, val); - RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr); - - rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100); -} - -static u32 rtl_eri_read(struct rtl8169_private *tp, int addr, int type) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr); - - return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ? - RTL_R32(ERIDR) : ~0; -} - -static void rtl_w1w0_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p, - u32 m, int type) -{ - u32 val; - - val = rtl_eri_read(tp, addr, type); - rtl_eri_write(tp, addr, mask, (val & ~m) | p, type); -} - -struct exgmac_reg { - u16 addr; - u16 mask; - u32 val; -}; - -static void rtl_write_exgmac_batch(struct rtl8169_private *tp, - const struct exgmac_reg *r, int len) -{ - while (len-- > 0) { - rtl_eri_write(tp, r->addr, r->mask, r->val, ERIAR_EXGMAC); - r++; - } -} - -DECLARE_RTL_COND(rtl_efusear_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(EFUSEAR) & EFUSEAR_FLAG; -} - -static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); - - return rtl_udelay_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ? - RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK : ~0; -} - -static u16 rtl_get_events(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R16(IntrStatus); -} - -static void rtl_ack_events(struct rtl8169_private *tp, u16 bits) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W16(IntrStatus, bits); - mmiowb(); -} - -static void rtl_irq_disable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W16(IntrMask, 0); - mmiowb(); -} - -static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W16(IntrMask, bits); -} - -#define RTL_EVENT_NAPI_RX (RxOK | RxErr) -#define RTL_EVENT_NAPI_TX (TxOK | TxErr) -#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX) - -static void rtl_irq_enable_all(struct rtl8169_private *tp) -{ - rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow); -} - -static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_irq_disable(tp); - rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow); - RTL_R8(ChipCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(struct rtl8169_private *tp) -{ - return rtl_readphy(tp, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp) -{ - unsigned int val; - - val = rtl_readphy(tp, MII_BMCR) | BMCR_RESET; - rtl_writephy(tp, MII_BMCR, val & 0xffff); -} - -static void rtl_link_chg_patch(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct net_device *dev = tp->dev; - - if (!netif_running(dev)) - return; - - if (tp->mac_version == RTL_GIGA_MAC_VER_34 || - tp->mac_version == RTL_GIGA_MAC_VER_38) { - if (RTL_R8(PHYstatus) & _1000bpsF) { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005, - ERIAR_EXGMAC); - } else if (RTL_R8(PHYstatus) & _100bps) { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005, - ERIAR_EXGMAC); - } else { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f, - ERIAR_EXGMAC); - } - /* Reset packet filter */ - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, - ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, - ERIAR_EXGMAC); - } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 || - tp->mac_version == RTL_GIGA_MAC_VER_36) { - if (RTL_R8(PHYstatus) & _1000bpsF) { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005, - ERIAR_EXGMAC); - } else { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f, - ERIAR_EXGMAC); - } - } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) { - if (RTL_R8(PHYstatus) & _10bps) { - rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060, - ERIAR_EXGMAC); - } else { - rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, - ERIAR_EXGMAC); - } - } -} - -static void __rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, bool pm) -{ - if (tp->link_ok(ioaddr)) { - rtl_link_chg_patch(tp); - /* This is to cancel a scheduled suspend if there's one. */ - if (pm) - pm_request_resume(&tp->pci_dev->dev); - netif_carrier_on(dev); - if (net_ratelimit()) - netif_info(tp, ifup, dev, "link up\n"); - } else { - netif_carrier_off(dev); - netif_info(tp, ifdown, dev, "link down\n"); - if (pm) - pm_schedule_suspend(&tp->pci_dev->dev, 5000); - } -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - __rtl8169_check_link_status(dev, tp, ioaddr, false); -} - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - -static u32 __rtl8169_get_wol(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - u32 wolopts = 0; - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - return 0; - - options = RTL_R8(Config3); - if (options & LinkUp) - wolopts |= WAKE_PHY; - if (options & MagicPacket) - wolopts |= WAKE_MAGIC; - - options = RTL_R8(Config5); - if (options & UWF) - wolopts |= WAKE_UCAST; - if (options & BWF) - wolopts |= WAKE_BCAST; - if (options & MWF) - wolopts |= WAKE_MCAST; - - return wolopts; -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl_lock_work(tp); - - wol->supported = WAKE_ANY; - wol->wolopts = __rtl8169_get_wol(tp); - - rtl_unlock_work(tp); -} - -static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i; - static const struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_PHY, Config3, LinkUp }, - { WAKE_MAGIC, Config3, MagicPacket }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake } - }; - u8 options; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - for (i = 0; i < ARRAY_SIZE(cfg); i++) { - options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17: - options = RTL_R8(Config1) & ~PMEnable; - if (wolopts) - options |= PMEnable; - RTL_W8(Config1, options); - break; - default: - options = RTL_R8(Config2) & ~PME_SIGNAL; - if (wolopts) - options |= PME_SIGNAL; - RTL_W8(Config2, options); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl_lock_work(tp); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - __rtl8169_set_wol(tp, wol->wolopts); - - rtl_unlock_work(tp); - - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - return 0; -} - -static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp) -{ - return rtl_chip_infos[tp->mac_version].fw_name; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct rtl_fw *rtl_fw = tp->rtl_fw; - - strlcpy(info->driver, MODULENAME, sizeof(info->driver)); - strlcpy(info->version, RTL8169_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info)); - BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version)); - if (!IS_ERR_OR_NULL(rtl_fw)) - strlcpy(info->fw_version, rtl_fw->version, - sizeof(info->fw_version)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex, u32 ignored) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - netif_warn(tp, link, dev, - "incorrect speed setting refused in TBI mode\n"); - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex, u32 adv) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int giga_ctrl, bmcr; - int rc = -EINVAL; - - rtl_writephy(tp, 0x1f, 0x0000); - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = rtl_readphy(tp, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - - if (adv & ADVERTISED_10baseT_Half) - auto_nego |= ADVERTISE_10HALF; - if (adv & ADVERTISED_10baseT_Full) - auto_nego |= ADVERTISE_10FULL; - if (adv & ADVERTISED_100baseT_Half) - auto_nego |= ADVERTISE_100HALF; - if (adv & ADVERTISED_100baseT_Full) - auto_nego |= ADVERTISE_100FULL; - - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = rtl_readphy(tp, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if (tp->mii.supports_gmii) { - if (adv & ADVERTISED_1000baseT_Half) - giga_ctrl |= ADVERTISE_1000HALF; - if (adv & ADVERTISED_1000baseT_Full) - giga_ctrl |= ADVERTISE_1000FULL; - } else if (adv & (ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full)) { - netif_info(tp, link, dev, - "PHY does not support 1000Mbps\n"); - goto out; - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - rtl_writephy(tp, MII_ADVERTISE, auto_nego); - rtl_writephy(tp, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - goto out; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - } - - rtl_writephy(tp, MII_BMCR, bmcr); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02 || - tp->mac_version == RTL_GIGA_MAC_VER_03) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - rtl_writephy(tp, 0x17, 0x2138); - rtl_writephy(tp, 0x0e, 0x0260); - } else { - rtl_writephy(tp, 0x17, 0x2108); - rtl_writephy(tp, 0x0e, 0x0000); - } - } - - rc = 0; -out: - return rc; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex, u32 advertising) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex, advertising); - if (ret < 0) - goto out; - - if (netif_running(dev) && (autoneg == AUTONEG_ENABLE) && - (advertising & ADVERTISED_1000baseT_Full)) { - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - } -out: - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - del_timer_sync(&tp->timer); - - rtl_lock_work(tp); - ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd), - cmd->duplex, cmd->advertising); - rtl_unlock_work(tp); - - return ret; -} - -static netdev_features_t rtl8169_fix_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (dev->mtu > TD_MSS_MAX) - features &= ~NETIF_F_ALL_TSO; - - if (dev->mtu > JUMBO_1K && - !rtl_chip_infos[tp->mac_version].jumbo_tx_csum) - features &= ~NETIF_F_IP_CSUM; - - return features; -} - -static void __rtl8169_set_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8169_private *tp = netdev_priv(dev); - netdev_features_t changed = features ^ dev->features; - void __iomem *ioaddr = tp->mmio_addr; - - if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM | - NETIF_F_HW_VLAN_CTAG_RX))) - return; - - if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX)) { - if (features & NETIF_F_RXCSUM) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - if (dev->features & NETIF_F_HW_VLAN_CTAG_RX) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - } - if (changed & NETIF_F_RXALL) { - int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt)); - if (features & NETIF_F_RXALL) - tmp |= (AcceptErr | AcceptRunt); - RTL_W32(RxConfig, tmp); - } -} - -static int rtl8169_set_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl_lock_work(tp); - __rtl8169_set_features(dev, features); - rtl_unlock_work(tp); - - return 0; -} - - -static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb) -{ - return (vlan_tx_tag_present(skb)) ? - TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00; -} - -static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - - if (opts2 & RxVlanTag) - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff)); -} - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - ethtool_cmd_speed_set(cmd, SPEED_1000); - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int rc; - - rtl_lock_work(tp); - rc = tp->get_settings(dev, cmd); - rtl_unlock_work(tp); - - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (regs->len > R8169_REGS_SIZE) - regs->len = R8169_REGS_SIZE; - - rtl_lock_work(tp); - memcpy_fromio(p, tp->mmio_addr, regs->len); - rtl_unlock_work(tp); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -DECLARE_RTL_COND(rtl_counters_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(CounterAddrLow) & CounterDump; -} - -static void rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct device *d = &tp->pci_dev->dev; - struct rtl8169_counters *counters; - dma_addr_t paddr; - u32 cmd; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return; - - counters = dma_alloc_coherent(d, sizeof(*counters), &paddr, GFP_KERNEL); - if (!counters) - return; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | CounterDump); - - if (rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000)) - memcpy(&tp->counters, counters, sizeof(*counters)); - - RTL_W32(CounterAddrLow, 0); - RTL_W32(CounterAddrHigh, 0); - - dma_free_coherent(d, sizeof(*counters), counters, paddr); -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(tp->counters.tx_packets); - data[1] = le64_to_cpu(tp->counters.rx_packets); - data[2] = le64_to_cpu(tp->counters.tx_errors); - data[3] = le32_to_cpu(tp->counters.rx_errors); - data[4] = le16_to_cpu(tp->counters.rx_missed); - data[5] = le16_to_cpu(tp->counters.align_errors); - data[6] = le32_to_cpu(tp->counters.tx_one_collision); - data[7] = le32_to_cpu(tp->counters.tx_multi_collision); - data[8] = le64_to_cpu(tp->counters.rx_unicast); - data[9] = le64_to_cpu(tp->counters.rx_broadcast); - data[10] = le32_to_cpu(tp->counters.rx_multicast); - data[11] = le16_to_cpu(tp->counters.tx_aborted); - data[12] = le16_to_cpu(tp->counters.tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, - .get_ts_info = ethtool_op_get_ts_info, -}; - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - struct net_device *dev, u8 default_version) -{ - void __iomem *ioaddr = tp->mmio_addr; - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - static const struct rtl_mac_info { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168G family. */ - { 0x7cf00000, 0x50900000, RTL_GIGA_MAC_VER_42 }, - { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 }, - { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 }, - - /* 8168F family. */ - { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 }, - { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 }, - { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 }, - - /* 8168E family. */ - { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 }, - { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 }, - { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 }, - { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 }, - - /* 8168D family. */ - { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, - { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 }, - - /* 8168DP family. */ - { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 }, - { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 }, - { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 }, - { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 }, - { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 }, - { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 }, - { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 }, - { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 }, - { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 }, - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }; - const struct rtl_mac_info *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; - - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - netif_notice(tp, probe, dev, - "unknown MAC, using family default\n"); - tp->mac_version = default_version; - } else if (tp->mac_version == RTL_GIGA_MAC_VER_42) { - tp->mac_version = tp->mii.supports_gmii ? - RTL_GIGA_MAC_VER_42 : - RTL_GIGA_MAC_VER_43; - } -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_writephy_batch(struct rtl8169_private *tp, - const struct phy_reg *regs, int len) -{ - while (len-- > 0) { - rtl_writephy(tp, regs->reg, regs->val); - regs++; - } -} - -#define PHY_READ 0x00000000 -#define PHY_DATA_OR 0x10000000 -#define PHY_DATA_AND 0x20000000 -#define PHY_BJMPN 0x30000000 -#define PHY_MDIO_CHG 0x40000000 -#define PHY_CLEAR_READCOUNT 0x70000000 -#define PHY_WRITE 0x80000000 -#define PHY_READCOUNT_EQ_SKIP 0x90000000 -#define PHY_COMP_EQ_SKIPN 0xa0000000 -#define PHY_COMP_NEQ_SKIPN 0xb0000000 -#define PHY_WRITE_PREVIOUS 0xc0000000 -#define PHY_SKIPN 0xd0000000 -#define PHY_DELAY_MS 0xe0000000 - -struct fw_info { - u32 magic; - char version[RTL_VER_SIZE]; - __le32 fw_start; - __le32 fw_len; - u8 chksum; -} __packed; - -#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code)) - -static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) -{ - const struct firmware *fw = rtl_fw->fw; - struct fw_info *fw_info = (struct fw_info *)fw->data; - struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; - char *version = rtl_fw->version; - bool rc = false; - - if (fw->size < FW_OPCODE_SIZE) - goto out; - - if (!fw_info->magic) { - size_t i, size, start; - u8 checksum = 0; - - if (fw->size < sizeof(*fw_info)) - goto out; - - for (i = 0; i < fw->size; i++) - checksum += fw->data[i]; - if (checksum != 0) - goto out; - - start = le32_to_cpu(fw_info->fw_start); - if (start > fw->size) - goto out; - - size = le32_to_cpu(fw_info->fw_len); - if (size > (fw->size - start) / FW_OPCODE_SIZE) - goto out; - - memcpy(version, fw_info->version, RTL_VER_SIZE); - - pa->code = (__le32 *)(fw->data + start); - pa->size = size; - } else { - if (fw->size % FW_OPCODE_SIZE) - goto out; - - strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE); - - pa->code = (__le32 *)fw->data; - pa->size = fw->size / FW_OPCODE_SIZE; - } - version[RTL_VER_SIZE - 1] = 0; - - rc = true; -out: - return rc; -} - -static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev, - struct rtl_fw_phy_action *pa) -{ - bool rc = false; - size_t index; - - for (index = 0; index < pa->size; index++) { - u32 action = le32_to_cpu(pa->code[index]); - u32 regno = (action & 0x0fff0000) >> 16; - - switch(action & 0xf0000000) { - case PHY_READ: - case PHY_DATA_OR: - case PHY_DATA_AND: - case PHY_MDIO_CHG: - case PHY_CLEAR_READCOUNT: - case PHY_WRITE: - case PHY_WRITE_PREVIOUS: - case PHY_DELAY_MS: - break; - - case PHY_BJMPN: - if (regno > index) { - netif_err(tp, ifup, tp->dev, - "Out of range of firmware\n"); - goto out; - } - break; - case PHY_READCOUNT_EQ_SKIP: - if (index + 2 >= pa->size) { - netif_err(tp, ifup, tp->dev, - "Out of range of firmware\n"); - goto out; - } - break; - case PHY_COMP_EQ_SKIPN: - case PHY_COMP_NEQ_SKIPN: - case PHY_SKIPN: - if (index + 1 + regno >= pa->size) { - netif_err(tp, ifup, tp->dev, - "Out of range of firmware\n"); - goto out; - } - break; - - default: - netif_err(tp, ifup, tp->dev, - "Invalid action 0x%08x\n", action); - goto out; - } - } - rc = true; -out: - return rc; -} - -static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) -{ - struct net_device *dev = tp->dev; - int rc = -EINVAL; - - if (!rtl_fw_format_ok(tp, rtl_fw)) { - netif_err(tp, ifup, dev, "invalid firwmare\n"); - goto out; - } - - if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action)) - rc = 0; -out: - return rc; -} - -static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) -{ - struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; - struct mdio_ops org, *ops = &tp->mdio_ops; - u32 predata, count; - size_t index; - - predata = count = 0; - org.write = ops->write; - org.read = ops->read; - - for (index = 0; index < pa->size; ) { - u32 action = le32_to_cpu(pa->code[index]); - u32 data = action & 0x0000ffff; - u32 regno = (action & 0x0fff0000) >> 16; - - if (!action) - break; - - switch(action & 0xf0000000) { - case PHY_READ: - predata = rtl_readphy(tp, regno); - count++; - index++; - break; - case PHY_DATA_OR: - predata |= data; - index++; - break; - case PHY_DATA_AND: - predata &= data; - index++; - break; - case PHY_BJMPN: - index -= regno; - break; - case PHY_MDIO_CHG: - if (data == 0) { - ops->write = org.write; - ops->read = org.read; - } else if (data == 1) { - ops->write = mac_mcu_write; - ops->read = mac_mcu_read; - } - - index++; - break; - case PHY_CLEAR_READCOUNT: - count = 0; - index++; - break; - case PHY_WRITE: - rtl_writephy(tp, regno, data); - index++; - break; - case PHY_READCOUNT_EQ_SKIP: - index += (count == data) ? 2 : 1; - break; - case PHY_COMP_EQ_SKIPN: - if (predata == data) - index += regno; - index++; - break; - case PHY_COMP_NEQ_SKIPN: - if (predata != data) - index += regno; - index++; - break; - case PHY_WRITE_PREVIOUS: - rtl_writephy(tp, regno, predata); - index++; - break; - case PHY_SKIPN: - index += regno + 1; - break; - case PHY_DELAY_MS: - mdelay(data); - index++; - break; - - default: - BUG(); - } - } - - ops->write = org.write; - ops->read = org.read; -} - -static void rtl_release_firmware(struct rtl8169_private *tp) -{ - if (!IS_ERR_OR_NULL(tp->rtl_fw)) { - release_firmware(tp->rtl_fw->fw); - kfree(tp->rtl_fw); - } - tp->rtl_fw = RTL_FIRMWARE_UNKNOWN; -} - -static void rtl_apply_firmware(struct rtl8169_private *tp) -{ - struct rtl_fw *rtl_fw = tp->rtl_fw; - - /* TODO: release firmware once rtl_phy_write_fw signals failures. */ - if (!IS_ERR_OR_NULL(rtl_fw)) - rtl_phy_write_fw(tp, rtl_fw); -} - -static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val) -{ - if (rtl_readphy(tp, reg) != val) - netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n"); - else - rtl_apply_firmware(tp); -} - -static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x006e }, - { 0x08, 0x0708 }, - { 0x15, 0x4000 }, - { 0x18, 0x65c7 }, - - { 0x1f, 0x0001 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x0000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf60 }, - { 0x01, 0x0140 }, - { 0x00, 0x0077 }, - { 0x04, 0x7800 }, - { 0x04, 0x7000 }, - - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf0f9 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xa000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf20 }, - { 0x01, 0x0140 }, - { 0x00, 0x00bb }, - { 0x04, 0xb800 }, - { 0x04, 0xb000 }, - - { 0x03, 0xdf41 }, - { 0x02, 0xdc60 }, - { 0x01, 0x6340 }, - { 0x00, 0x007d }, - { 0x04, 0xd800 }, - { 0x04, 0xd000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x100a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - - { 0x1f, 0x0000 }, - { 0x0b, 0x0000 }, - { 0x00, 0x9200 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp) -{ - struct pci_dev *pdev = tp->pci_dev; - - if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) || - (pdev->subsystem_device != 0xe000)) - return; - - rtl_writephy(tp, 0x1f, 0x0001); - rtl_writephy(tp, 0x10, 0xf01b); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x14, 0xfb54 }, - { 0x18, 0xf5c7 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8169scd_hw_phy_config_quirk(tp); -} - -static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0x8480 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x18, 0x67c7 }, - { 0x04, 0x2000 }, - { 0x03, 0x002f }, - { 0x02, 0x4360 }, - { 0x01, 0x0109 }, - { 0x00, 0x3022 }, - { 0x04, 0x2800 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_writephy(tp, 0x1f, 0x0001); - rtl_patchphy(tp, 0x16, 1 << 0); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy(tp, 0x1f, 0x0000); - rtl_patchphy(tp, 0x14, 1 << 5); - rtl_patchphy(tp, 0x0d, 1 << 5); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl_patchphy(tp, 0x14, 1 << 5); - rtl_patchphy(tp, 0x0d, 1 << 5); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl_patchphy(tp, 0x16, 1 << 0); - rtl_patchphy(tp, 0x14, 1 << 5); - rtl_patchphy(tp, 0x0d, 1 << 5); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl_patchphy(tp, 0x16, 1 << 0); - rtl_patchphy(tp, 0x14, 1 << 5); - rtl_patchphy(tp, 0x0d, 1 << 5); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(struct rtl8169_private *tp) -{ - rtl8168c_3_hw_phy_config(tp); -} - -static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init_0[] = { - /* Channel Estimation */ - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - /* - * Tx Error Issue - * Enhance line driver power - */ - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 }, - - /* - * Can not link to 1Gbps with bad cable - * Decrease SNR threshold form 21.07dB to 19.04dB - */ - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 } - }; - - rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - /* - * Rx Error Issue - * Fine Tune Switching regulator parameter - */ - rtl_writephy(tp, 0x1f, 0x0002); - rtl_w1w0_phy(tp, 0x0b, 0x0010, 0x00ef); - rtl_w1w0_phy(tp, 0x0c, 0xa200, 0x5d00); - - if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - { 0x1f, 0x0002 } - }; - int val; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = rtl_readphy(tp, 0x0d); - - if ((val & 0x00ff) != 0x006c) { - static const u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - rtl_writephy(tp, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - rtl_writephy(tp, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x6662 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - /* RSET couple improve */ - rtl_writephy(tp, 0x1f, 0x0002); - rtl_patchphy(tp, 0x0d, 0x0300); - rtl_patchphy(tp, 0x0f, 0x0010); - - /* Fine tune PLL performance */ - rtl_writephy(tp, 0x1f, 0x0002); - rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600); - rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000); - - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x001b); - - rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00); - - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init_0[] = { - /* Channel Estimation */ - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - /* - * Tx Error Issue - * Enhance line driver power - */ - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 }, - - /* - * Can not link to 1Gbps with bad cable - * Decrease SNR threshold form 21.07dB to 19.04dB - */ - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 } - }; - - rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - - { 0x1f, 0x0002 } - }; - int val; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = rtl_readphy(tp, 0x0d); - if ((val & 0x00ff) != 0x006c) { - static const u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - rtl_writephy(tp, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - rtl_writephy(tp, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x2642 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x2642 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - /* Fine tune PLL performance */ - rtl_writephy(tp, 0x1f, 0x0002); - rtl_w1w0_phy(tp, 0x02, 0x0100, 0x0600); - rtl_w1w0_phy(tp, 0x03, 0x0000, 0xe000); - - /* Switching regulator Slew rate */ - rtl_writephy(tp, 0x1f, 0x0002); - rtl_patchphy(tp, 0x0f, 0x0017); - - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x001b); - - rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300); - - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168d_3_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x10, 0x0008 }, - { 0x0d, 0x006c }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0xa4d8 }, - { 0x09, 0x281c }, - { 0x07, 0x2883 }, - { 0x0a, 0x6b35 }, - { 0x1d, 0x3da4 }, - { 0x1c, 0xeffd }, - { 0x14, 0x7f52 }, - { 0x18, 0x7fc6 }, - { 0x08, 0x0601 }, - { 0x06, 0x4063 }, - { 0x10, 0xf074 }, - { 0x1f, 0x0003 }, - { 0x13, 0x0789 }, - { 0x12, 0xf4bd }, - { 0x1a, 0x04fd }, - { 0x14, 0x84b0 }, - { 0x1f, 0x0000 }, - { 0x00, 0x9200 }, - - { 0x1f, 0x0005 }, - { 0x01, 0x0340 }, - { 0x1f, 0x0001 }, - { 0x04, 0x4000 }, - { 0x03, 0x1d21 }, - { 0x02, 0x0c32 }, - { 0x01, 0x0200 }, - { 0x00, 0x5554 }, - { 0x04, 0x4800 }, - { 0x04, 0x4000 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x0023 }, - { 0x16, 0x0000 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x002d }, - { 0x18, 0x0040 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - rtl_patchphy(tp, 0x0d, 1 << 5); -} - -static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - /* Enable Delay cap */ - { 0x1f, 0x0005 }, - { 0x05, 0x8b80 }, - { 0x06, 0xc896 }, - { 0x1f, 0x0000 }, - - /* Channel estimation fine tune */ - { 0x1f, 0x0001 }, - { 0x0b, 0x6c20 }, - { 0x07, 0x2872 }, - { 0x1c, 0xefff }, - { 0x1f, 0x0003 }, - { 0x14, 0x6420 }, - { 0x1f, 0x0000 }, - - /* Update PFM & 10M TX idle timer */ - { 0x1f, 0x0007 }, - { 0x1e, 0x002f }, - { 0x15, 0x1919 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x00ac }, - { 0x18, 0x0006 }, - { 0x1f, 0x0000 } - }; - - rtl_apply_firmware(tp); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - /* DCO enable for 10M IDLE Power */ - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x0023); - rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* For impedance matching */ - rtl_writephy(tp, 0x1f, 0x0002); - rtl_w1w0_phy(tp, 0x08, 0x8000, 0x7f00); - rtl_writephy(tp, 0x1f, 0x0000); - - /* PHY auto speed down */ - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x002d); - rtl_w1w0_phy(tp, 0x18, 0x0050, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000); - - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b86); - rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000); - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x0020); - rtl_w1w0_phy(tp, 0x15, 0x0000, 0x1100); - rtl_writephy(tp, 0x1f, 0x0006); - rtl_writephy(tp, 0x00, 0x5a00); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x0d, 0x0007); - rtl_writephy(tp, 0x0e, 0x003c); - rtl_writephy(tp, 0x0d, 0x4007); - rtl_writephy(tp, 0x0e, 0x0000); - rtl_writephy(tp, 0x0d, 0x0000); -} - -static void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr) -{ - const u16 w[] = { - addr[0] | (addr[1] << 8), - addr[2] | (addr[3] << 8), - addr[4] | (addr[5] << 8) - }; - const struct exgmac_reg e[] = { - { .addr = 0xe0, ERIAR_MASK_1111, .val = w[0] | (w[1] << 16) }, - { .addr = 0xe4, ERIAR_MASK_1111, .val = w[2] }, - { .addr = 0xf0, ERIAR_MASK_1111, .val = w[0] << 16 }, - { .addr = 0xf4, ERIAR_MASK_1111, .val = w[1] | (w[2] << 16) } - }; - - rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e)); -} - -static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - /* Enable Delay cap */ - { 0x1f, 0x0004 }, - { 0x1f, 0x0007 }, - { 0x1e, 0x00ac }, - { 0x18, 0x0006 }, - { 0x1f, 0x0002 }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - - /* Channel estimation fine tune */ - { 0x1f, 0x0003 }, - { 0x09, 0xa20f }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - - /* Green Setting */ - { 0x1f, 0x0005 }, - { 0x05, 0x8b5b }, - { 0x06, 0x9222 }, - { 0x05, 0x8b6d }, - { 0x06, 0x8000 }, - { 0x05, 0x8b76 }, - { 0x06, 0x8000 }, - { 0x1f, 0x0000 } - }; - - rtl_apply_firmware(tp); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - /* For 4-corner performance improve */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b80); - rtl_w1w0_phy(tp, 0x17, 0x0006, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* PHY auto speed down */ - rtl_writephy(tp, 0x1f, 0x0004); - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x002d); - rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000); - rtl_writephy(tp, 0x1f, 0x0002); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000); - - /* improve 10M EEE waveform */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b86); - rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* Improve 2-pair detection performance */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* EEE setting */ - rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, ERIAR_EXGMAC); - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000); - rtl_writephy(tp, 0x1f, 0x0004); - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x0020); - rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100); - rtl_writephy(tp, 0x1f, 0x0002); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x0d, 0x0007); - rtl_writephy(tp, 0x0e, 0x003c); - rtl_writephy(tp, 0x0d, 0x4007); - rtl_writephy(tp, 0x0e, 0x0000); - rtl_writephy(tp, 0x0d, 0x0000); - - /* Green feature */ - rtl_writephy(tp, 0x1f, 0x0003); - rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001); - rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400); - rtl_writephy(tp, 0x1f, 0x0000); - - /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */ - rtl_rar_exgmac_set(tp, tp->dev->dev_addr); -} - -static void rtl8168f_hw_phy_config(struct rtl8169_private *tp) -{ - /* For 4-corner performance improve */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b80); - rtl_w1w0_phy(tp, 0x06, 0x0006, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* PHY auto speed down */ - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x002d); - rtl_w1w0_phy(tp, 0x18, 0x0010, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000); - - /* Improve 10M EEE waveform */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b86); - rtl_w1w0_phy(tp, 0x06, 0x0001, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - /* Channel estimation fine tune */ - { 0x1f, 0x0003 }, - { 0x09, 0xa20f }, - { 0x1f, 0x0000 }, - - /* Modify green table for giga & fnet */ - { 0x1f, 0x0005 }, - { 0x05, 0x8b55 }, - { 0x06, 0x0000 }, - { 0x05, 0x8b5e }, - { 0x06, 0x0000 }, - { 0x05, 0x8b67 }, - { 0x06, 0x0000 }, - { 0x05, 0x8b70 }, - { 0x06, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0007 }, - { 0x1e, 0x0078 }, - { 0x17, 0x0000 }, - { 0x19, 0x00fb }, - { 0x1f, 0x0000 }, - - /* Modify green table for 10M */ - { 0x1f, 0x0005 }, - { 0x05, 0x8b79 }, - { 0x06, 0xaa00 }, - { 0x1f, 0x0000 }, - - /* Disable hiimpedance detection (RTCT) */ - { 0x1f, 0x0003 }, - { 0x01, 0x328a }, - { 0x1f, 0x0000 } - }; - - rtl_apply_firmware(tp); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8168f_hw_phy_config(tp); - - /* Improve 2-pair detection performance */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp) -{ - rtl_apply_firmware(tp); - - rtl8168f_hw_phy_config(tp); -} - -static void rtl8411_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - /* Channel estimation fine tune */ - { 0x1f, 0x0003 }, - { 0x09, 0xa20f }, - { 0x1f, 0x0000 }, - - /* Modify green table for giga & fnet */ - { 0x1f, 0x0005 }, - { 0x05, 0x8b55 }, - { 0x06, 0x0000 }, - { 0x05, 0x8b5e }, - { 0x06, 0x0000 }, - { 0x05, 0x8b67 }, - { 0x06, 0x0000 }, - { 0x05, 0x8b70 }, - { 0x06, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0007 }, - { 0x1e, 0x0078 }, - { 0x17, 0x0000 }, - { 0x19, 0x00aa }, - { 0x1f, 0x0000 }, - - /* Modify green table for 10M */ - { 0x1f, 0x0005 }, - { 0x05, 0x8b79 }, - { 0x06, 0xaa00 }, - { 0x1f, 0x0000 }, - - /* Disable hiimpedance detection (RTCT) */ - { 0x1f, 0x0003 }, - { 0x01, 0x328a }, - { 0x1f, 0x0000 } - }; - - - rtl_apply_firmware(tp); - - rtl8168f_hw_phy_config(tp); - - /* Improve 2-pair detection performance */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - /* Modify green table for giga */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b54); - rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800); - rtl_writephy(tp, 0x05, 0x8b5d); - rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0800); - rtl_writephy(tp, 0x05, 0x8a7c); - rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100); - rtl_writephy(tp, 0x05, 0x8a7f); - rtl_w1w0_phy(tp, 0x06, 0x0100, 0x0000); - rtl_writephy(tp, 0x05, 0x8a82); - rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100); - rtl_writephy(tp, 0x05, 0x8a85); - rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100); - rtl_writephy(tp, 0x05, 0x8a88); - rtl_w1w0_phy(tp, 0x06, 0x0000, 0x0100); - rtl_writephy(tp, 0x1f, 0x0000); - - /* uc same-seed solution */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w1w0_phy(tp, 0x06, 0x8000, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* eee setting */ - rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC); - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w1w0_phy(tp, 0x06, 0x0000, 0x2000); - rtl_writephy(tp, 0x1f, 0x0004); - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x0020); - rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0100); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x0d, 0x0007); - rtl_writephy(tp, 0x0e, 0x003c); - rtl_writephy(tp, 0x0d, 0x4007); - rtl_writephy(tp, 0x0e, 0x0000); - rtl_writephy(tp, 0x0d, 0x0000); - - /* Green feature */ - rtl_writephy(tp, 0x1f, 0x0003); - rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001); - rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) -{ - rtl_apply_firmware(tp); - - rtl_writephy(tp, 0x1f, 0x0a46); - if (rtl_readphy(tp, 0x10) & 0x0100) { - rtl_writephy(tp, 0x1f, 0x0bcc); - rtl_w1w0_phy(tp, 0x12, 0x0000, 0x8000); - } else { - rtl_writephy(tp, 0x1f, 0x0bcc); - rtl_w1w0_phy(tp, 0x12, 0x8000, 0x0000); - } - - rtl_writephy(tp, 0x1f, 0x0a46); - if (rtl_readphy(tp, 0x13) & 0x0100) { - rtl_writephy(tp, 0x1f, 0x0c41); - rtl_w1w0_phy(tp, 0x15, 0x0002, 0x0000); - } else { - rtl_writephy(tp, 0x1f, 0x0c41); - rtl_w1w0_phy(tp, 0x15, 0x0000, 0x0002); - } - - /* Enable PHY auto speed down */ - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w1w0_phy(tp, 0x11, 0x000c, 0x0000); - - rtl_writephy(tp, 0x1f, 0x0bcc); - rtl_w1w0_phy(tp, 0x14, 0x0100, 0x0000); - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w1w0_phy(tp, 0x11, 0x00c0, 0x0000); - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x8084); - rtl_w1w0_phy(tp, 0x14, 0x0000, 0x6000); - rtl_w1w0_phy(tp, 0x10, 0x1003, 0x0000); - - /* EEE auto-fallback function */ - rtl_writephy(tp, 0x1f, 0x0a4b); - rtl_w1w0_phy(tp, 0x11, 0x0004, 0x0000); - - /* Enable UC LPF tune function */ - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x8012); - rtl_w1w0_phy(tp, 0x14, 0x8000, 0x0000); - - rtl_writephy(tp, 0x1f, 0x0c42); - rtl_w1w0_phy(tp, 0x11, 0x4000, 0x2000); - - /* Improve SWR Efficiency */ - rtl_writephy(tp, 0x1f, 0x0bcd); - rtl_writephy(tp, 0x14, 0x5065); - rtl_writephy(tp, 0x14, 0xd065); - rtl_writephy(tp, 0x1f, 0x0bc8); - rtl_writephy(tp, 0x11, 0x5655); - rtl_writephy(tp, 0x1f, 0x0bcd); - rtl_writephy(tp, 0x14, 0x1065); - rtl_writephy(tp, 0x14, 0x9065); - rtl_writephy(tp, 0x14, 0x1065); - - /* Check ALDPS bit, disable it if enabled */ - rtl_writephy(tp, 0x1f, 0x0a43); - if (rtl_readphy(tp, 0x10) & 0x0004) - rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0004); - - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp) -{ - rtl_apply_firmware(tp); -} - -static void rtl8102e_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy(tp, 0x1f, 0x0000); - rtl_patchphy(tp, 0x11, 1 << 12); - rtl_patchphy(tp, 0x19, 1 << 13); - rtl_patchphy(tp, 0x10, 1 << 15); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8105e_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0005 }, - { 0x1a, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0004 }, - { 0x1c, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x15, 0x7701 }, - { 0x1f, 0x0000 } - }; - - /* Disable ALDPS before ram code */ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x18, 0x0310); - msleep(100); - - rtl_apply_firmware(tp); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8402_hw_phy_config(struct rtl8169_private *tp) -{ - /* Disable ALDPS before setting firmware */ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x18, 0x0310); - msleep(20); - - rtl_apply_firmware(tp); - - /* EEE setting */ - rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_writephy(tp, 0x1f, 0x0004); - rtl_writephy(tp, 0x10, 0x401f); - rtl_writephy(tp, 0x19, 0x7030); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8106e_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0004 }, - { 0x10, 0xc07f }, - { 0x19, 0x7030 }, - { 0x1f, 0x0000 } - }; - - /* Disable ALDPS before ram code */ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x18, 0x0310); - msleep(100); - - rtl_apply_firmware(tp); - - rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_05: - rtl8169scd_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_06: - rtl8169sce_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_26: - rtl8168d_2_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_27: - rtl8168d_3_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_28: - rtl8168d_4_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_29: - case RTL_GIGA_MAC_VER_30: - rtl8105e_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_31: - /* None. */ - break; - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - rtl8168e_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_34: - rtl8168e_2_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_35: - rtl8168f_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_36: - rtl8168f_2_hw_phy_config(tp); - break; - - case RTL_GIGA_MAC_VER_37: - rtl8402_hw_phy_config(tp); - break; - - case RTL_GIGA_MAC_VER_38: - rtl8411_hw_phy_config(tp); - break; - - case RTL_GIGA_MAC_VER_39: - rtl8106e_hw_phy_config(tp); - break; - - case RTL_GIGA_MAC_VER_40: - rtl8168g_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - rtl8168g_2_hw_phy_config(tp); - break; - - case RTL_GIGA_MAC_VER_41: - default: - break; - } -} - -static void rtl_phy_work(struct rtl8169_private *tp) -{ - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (tp->phy_reset_pending(tp)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - return; - - netif_warn(tp, link, tp->dev, "PHY reset until link up\n"); - - tp->phy_reset_enable(tp); - -out_mod_timer: - mod_timer(timer, jiffies + timeout); -} - -static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag) -{ - if (!test_and_set_bit(flag, tp->wk.flags)) - schedule_work(&tp->wk.work); -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - - rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING); -} - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_clear_mwi(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -DECLARE_RTL_COND(rtl_phy_reset_cond) -{ - return tp->phy_reset_pending(tp); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - tp->phy_reset_enable(tp); - rtl_msleep_loop_wait_low(tp, &rtl_phy_reset_cond, 1, 100); -} - -static bool rtl_tbi_enabled(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return (tp->mac_version == RTL_GIGA_MAC_VER_01) && - (RTL_R8(PHYstatus) & TBI_Enable); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL, - ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | - (tp->mii.supports_gmii ? - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full : 0)); - - if (rtl_tbi_enabled(tp)) - netif_info(tp, link, dev, "TBI auto-negotiating\n"); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_lock_work(tp); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W32(MAC4, addr[4] | addr[5] << 8); - RTL_R32(MAC4); - - RTL_W32(MAC0, addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24); - RTL_R32(MAC0); - - if (tp->mac_version == RTL_GIGA_MAC_VER_34) - rtl_rar_exgmac_set(tp, addr); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - rtl_unlock_work(tp); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, - struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = rtl_readphy(tp, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - rtl_writephy(tp, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static void rtl_init_mdio_ops(struct rtl8169_private *tp) -{ - struct mdio_ops *ops = &tp->mdio_ops; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_27: - ops->write = r8168dp_1_mdio_write; - ops->read = r8168dp_1_mdio_read; - break; - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - ops->write = r8168dp_2_mdio_write; - ops->read = r8168dp_2_mdio_read; - break; - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - ops->write = r8168g_mdio_write; - ops->read = r8168g_mdio_read; - break; - default: - ops->write = r8169_mdio_write; - ops->read = r8169_mdio_read; - break; - } -} - -static void rtl_speed_down(struct rtl8169_private *tp) -{ - u32 adv; - int lpa; - - rtl_writephy(tp, 0x1f, 0x0000); - lpa = rtl_readphy(tp, MII_LPA); - - if (lpa & (LPA_10HALF | LPA_10FULL)) - adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full; - else if (lpa & (LPA_100HALF | LPA_100FULL)) - adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full; - else - adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | - (tp->mii.supports_gmii ? - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full : 0); - - rtl8169_set_speed(tp->dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL, - adv); -} - -static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_29: - case RTL_GIGA_MAC_VER_30: - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_37: - case RTL_GIGA_MAC_VER_38: - case RTL_GIGA_MAC_VER_39: - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - RTL_W32(RxConfig, RTL_R32(RxConfig) | - AcceptBroadcast | AcceptMulticast | AcceptMyPhys); - break; - default: - break; - } -} - -static bool rtl_wol_pll_power_down(struct rtl8169_private *tp) -{ - if (!(__rtl8169_get_wol(tp) & WAKE_ANY)) - return false; - - rtl_speed_down(tp); - rtl_wol_suspend_quirk(tp); - - return true; -} - -static void r810x_phy_power_down(struct rtl8169_private *tp) -{ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, MII_BMCR, BMCR_PDOWN); -} - -static void r810x_phy_power_up(struct rtl8169_private *tp) -{ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE); -} - -static void r810x_pll_power_down(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_wol_pll_power_down(tp)) - return; - - r810x_phy_power_down(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - case RTL_GIGA_MAC_VER_10: - case RTL_GIGA_MAC_VER_13: - case RTL_GIGA_MAC_VER_16: - break; - default: - RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80); - break; - } -} - -static void r810x_pll_power_up(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - r810x_phy_power_up(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - case RTL_GIGA_MAC_VER_10: - case RTL_GIGA_MAC_VER_13: - case RTL_GIGA_MAC_VER_16: - break; - default: - RTL_W8(PMCH, RTL_R8(PMCH) | 0x80); - break; - } -} - -static void r8168_phy_power_up(struct rtl8169_private *tp) -{ - rtl_writephy(tp, 0x1f, 0x0000); - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - case RTL_GIGA_MAC_VER_18: - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - rtl_writephy(tp, 0x0e, 0x0000); - break; - default: - break; - } - rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE); -} - -static void r8168_phy_power_down(struct rtl8169_private *tp) -{ - rtl_writephy(tp, 0x1f, 0x0000); - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); - break; - - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - case RTL_GIGA_MAC_VER_18: - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - rtl_writephy(tp, 0x0e, 0x0200); - default: - rtl_writephy(tp, MII_BMCR, BMCR_PDOWN); - break; - } -} - -static void r8168_pll_power_down(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_27 || - tp->mac_version == RTL_GIGA_MAC_VER_28 || - tp->mac_version == RTL_GIGA_MAC_VER_31) && - r8168dp_check_dash(tp)) { - return; - } - - if ((tp->mac_version == RTL_GIGA_MAC_VER_23 || - tp->mac_version == RTL_GIGA_MAC_VER_24) && - (RTL_R16(CPlusCmd) & ASF)) { - return; - } - - if (tp->mac_version == RTL_GIGA_MAC_VER_32 || - tp->mac_version == RTL_GIGA_MAC_VER_33) - rtl_ephy_write(tp, 0x19, 0xff64); - - if (rtl_wol_pll_power_down(tp)) - return; - - r8168_phy_power_down(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80); - break; - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - rtl_w1w0_eri(tp, 0x1a8, ERIAR_MASK_1111, 0x00000000, - 0xfc000000, ERIAR_EXGMAC); - break; - } -} - -static void r8168_pll_power_up(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - RTL_W8(PMCH, RTL_R8(PMCH) | 0x80); - break; - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - rtl_w1w0_eri(tp, 0x1a8, ERIAR_MASK_1111, 0xfc000000, - 0x00000000, ERIAR_EXGMAC); - break; - } - - r8168_phy_power_up(tp); -} - -static void rtl_generic_op(struct rtl8169_private *tp, - void (*op)(struct rtl8169_private *)) -{ - if (op) - op(tp); -} - -static void rtl_pll_power_down(struct rtl8169_private *tp) -{ - rtl_generic_op(tp, tp->pll_power_ops.down); -} - -static void rtl_pll_power_up(struct rtl8169_private *tp) -{ - rtl_generic_op(tp, tp->pll_power_ops.up); -} - -static void rtl_init_pll_power_ops(struct rtl8169_private *tp) -{ - struct pll_power_ops *ops = &tp->pll_power_ops; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - case RTL_GIGA_MAC_VER_10: - case RTL_GIGA_MAC_VER_16: - case RTL_GIGA_MAC_VER_29: - case RTL_GIGA_MAC_VER_30: - case RTL_GIGA_MAC_VER_37: - case RTL_GIGA_MAC_VER_39: - case RTL_GIGA_MAC_VER_43: - ops->down = r810x_pll_power_down; - ops->up = r810x_pll_power_up; - break; - - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - case RTL_GIGA_MAC_VER_18: - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_35: - case RTL_GIGA_MAC_VER_36: - case RTL_GIGA_MAC_VER_38: - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - ops->down = r8168_pll_power_down; - ops->up = r8168_pll_power_up; - break; - - default: - ops->down = NULL; - ops->up = NULL; - break; - } -} - -static void rtl_init_rxcfg(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - case RTL_GIGA_MAC_VER_04: - case RTL_GIGA_MAC_VER_05: - case RTL_GIGA_MAC_VER_06: - case RTL_GIGA_MAC_VER_10: - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_13: - case RTL_GIGA_MAC_VER_14: - case RTL_GIGA_MAC_VER_15: - case RTL_GIGA_MAC_VER_16: - case RTL_GIGA_MAC_VER_17: - RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST); - break; - case RTL_GIGA_MAC_VER_18: - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_35: - RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST); - break; - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST | RX_EARLY_OFF); - break; - default: - RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST); - break; - } -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->cur_tx = tp->cur_rx = 0; -} - -static void rtl_hw_jumbo_enable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - rtl_generic_op(tp, tp->jumbo_ops.enable); - RTL_W8(Cfg9346, Cfg9346_Lock); -} - -static void rtl_hw_jumbo_disable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - rtl_generic_op(tp, tp->jumbo_ops.disable); - RTL_W8(Cfg9346, Cfg9346_Lock); -} - -static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); - RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1); - rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT); -} - -static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); - RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1); - rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); -} - -static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); -} - -static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); -} - -static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(MaxTxPacketSize, 0x3f); - RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); - RTL_W8(Config4, RTL_R8(Config4) | 0x01); - rtl_tx_performance_tweak(tp->pci_dev, 0x2 << MAX_READ_REQUEST_SHIFT); -} - -static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(MaxTxPacketSize, 0x0c); - RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); - RTL_W8(Config4, RTL_R8(Config4) & ~0x01); - rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); -} - -static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp) -{ - rtl_tx_performance_tweak(tp->pci_dev, - (0x2 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp) -{ - rtl_tx_performance_tweak(tp->pci_dev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - r8168b_0_hw_jumbo_enable(tp); - - RTL_W8(Config4, RTL_R8(Config4) | (1 << 0)); -} - -static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - r8168b_0_hw_jumbo_disable(tp); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void rtl_init_jumbo_ops(struct rtl8169_private *tp) -{ - struct jumbo_ops *ops = &tp->jumbo_ops; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - ops->disable = r8168b_0_hw_jumbo_disable; - ops->enable = r8168b_0_hw_jumbo_enable; - break; - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - ops->disable = r8168b_1_hw_jumbo_disable; - ops->enable = r8168b_1_hw_jumbo_enable; - break; - case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */ - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */ - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - ops->disable = r8168c_hw_jumbo_disable; - ops->enable = r8168c_hw_jumbo_enable; - break; - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - ops->disable = r8168dp_hw_jumbo_disable; - ops->enable = r8168dp_hw_jumbo_enable; - break; - case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */ - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - case RTL_GIGA_MAC_VER_34: - ops->disable = r8168e_hw_jumbo_disable; - ops->enable = r8168e_hw_jumbo_enable; - break; - - /* - * No action needed for jumbo frames with 8169. - * No jumbo for 810x at all. - */ - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - default: - ops->disable = NULL; - ops->enable = NULL; - break; - } -} - -DECLARE_RTL_COND(rtl_chipcmd_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R8(ChipCmd) & CmdReset; -} - -static void rtl_hw_reset(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(ChipCmd, CmdReset); - - rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100); -} - -static void rtl_request_uncached_firmware(struct rtl8169_private *tp) -{ - struct rtl_fw *rtl_fw; - const char *name; - int rc = -ENOMEM; - - name = rtl_lookup_firmware_name(tp); - if (!name) - goto out_no_firmware; - - rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL); - if (!rtl_fw) - goto err_warn; - - rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev); - if (rc < 0) - goto err_free; - - rc = rtl_check_firmware(tp, rtl_fw); - if (rc < 0) - goto err_release_firmware; - - tp->rtl_fw = rtl_fw; -out: - return; - -err_release_firmware: - release_firmware(rtl_fw->fw); -err_free: - kfree(rtl_fw); -err_warn: - netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n", - name, rc); -out_no_firmware: - tp->rtl_fw = NULL; - goto out; -} - -static void rtl_request_firmware(struct rtl8169_private *tp) -{ - if (IS_ERR(tp->rtl_fw)) - rtl_request_uncached_firmware(tp); -} - -static void rtl_rx_close(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK); -} - -DECLARE_RTL_COND(rtl_npq_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R8(TxPoll) & NPQ; -} - -DECLARE_RTL_COND(rtl_txcfg_empty_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(TxConfig) & TXCFG_EMPTY; -} - -static void rtl8169_hw_reset(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(tp); - - rtl_rx_close(tp); - - if (tp->mac_version == RTL_GIGA_MAC_VER_27 || - tp->mac_version == RTL_GIGA_MAC_VER_28 || - tp->mac_version == RTL_GIGA_MAC_VER_31) { - rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42); - } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 || - tp->mac_version == RTL_GIGA_MAC_VER_35 || - tp->mac_version == RTL_GIGA_MAC_VER_36 || - tp->mac_version == RTL_GIGA_MAC_VER_37 || - tp->mac_version == RTL_GIGA_MAC_VER_40 || - tp->mac_version == RTL_GIGA_MAC_VER_41 || - tp->mac_version == RTL_GIGA_MAC_VER_42 || - tp->mac_version == RTL_GIGA_MAC_VER_43 || - tp->mac_version == RTL_GIGA_MAC_VER_38) { - RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq); - rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666); - } else { - RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq); - udelay(100); - } - - rtl_hw_reset(tp); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->hw_start(dev); - - rtl_irq_enable_all(tp); -} - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz + 1); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - static const struct rtl_cfg2_info { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }; - const struct rtl_cfg2_info *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - netif_notice(tp, link, dev, "Promiscuous mode enabled\n"); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - if (dev->features & NETIF_F_RXALL) - rx_mode |= (AcceptErr | AcceptRunt); - - tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode; - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - if (tp->mac_version == RTL_GIGA_MAC_VER_35) - mc_filter[1] = mc_filter[0] = 0xffffffff; - - RTL_W32(MAR0 + 4, mc_filter[1]); - RTL_W32(MAR0 + 0, mc_filter[0]); - - RTL_W32(RxConfig, tmp); -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if (tp->mac_version == RTL_GIGA_MAC_VER_01 || - tp->mac_version == RTL_GIGA_MAC_VER_02 || - tp->mac_version == RTL_GIGA_MAC_VER_03 || - tp->mac_version == RTL_GIGA_MAC_VER_04) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - rtl_init_rxcfg(tp); - - RTL_W8(EarlyTxThres, NoEarlyTx); - - rtl_set_rx_max_size(ioaddr, rx_buf_sz); - - if (tp->mac_version == RTL_GIGA_MAC_VER_01 || - tp->mac_version == RTL_GIGA_MAC_VER_02 || - tp->mac_version == RTL_GIGA_MAC_VER_03 || - tp->mac_version == RTL_GIGA_MAC_VER_04) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if (tp->mac_version == RTL_GIGA_MAC_VER_02 || - tp->mac_version == RTL_GIGA_MAC_VER_03) { - dprintk("Set MAC Reg C+CR Offset 0xE0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if (tp->mac_version != RTL_GIGA_MAC_VER_01 && - tp->mac_version != RTL_GIGA_MAC_VER_02 && - tp->mac_version != RTL_GIGA_MAC_VER_03 && - tp->mac_version != RTL_GIGA_MAC_VER_04) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); -} - -static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value) -{ - if (tp->csi_ops.write) - tp->csi_ops.write(tp, addr, value); -} - -static u32 rtl_csi_read(struct rtl8169_private *tp, int addr) -{ - return tp->csi_ops.read ? tp->csi_ops.read(tp, addr) : ~0; -} - -static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits) -{ - u32 csi; - - csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff; - rtl_csi_write(tp, 0x070c, csi | bits); -} - -static void rtl_csi_access_enable_1(struct rtl8169_private *tp) -{ - rtl_csi_access_enable(tp, 0x17000000); -} - -static void rtl_csi_access_enable_2(struct rtl8169_private *tp) -{ - rtl_csi_access_enable(tp, 0x27000000); -} - -DECLARE_RTL_COND(rtl_csiar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(CSIAR) & CSIAR_FLAG; -} - -static void r8169_csi_write(struct rtl8169_private *tp, int addr, int value) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100); -} - -static u32 r8169_csi_read(struct rtl8169_private *tp, int addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ? - RTL_R32(CSIDR) : ~0; -} - -static void r8402_csi_write(struct rtl8169_private *tp, int addr, int value) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT | - CSIAR_FUNC_NIC); - - rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100); -} - -static u32 r8402_csi_read(struct rtl8169_private *tp, int addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ? - RTL_R32(CSIDR) : ~0; -} - -static void rtl_init_csi_ops(struct rtl8169_private *tp) -{ - struct csi_ops *ops = &tp->csi_ops; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - case RTL_GIGA_MAC_VER_04: - case RTL_GIGA_MAC_VER_05: - case RTL_GIGA_MAC_VER_06: - case RTL_GIGA_MAC_VER_10: - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_13: - case RTL_GIGA_MAC_VER_14: - case RTL_GIGA_MAC_VER_15: - case RTL_GIGA_MAC_VER_16: - case RTL_GIGA_MAC_VER_17: - ops->write = NULL; - ops->read = NULL; - break; - - case RTL_GIGA_MAC_VER_37: - case RTL_GIGA_MAC_VER_38: - ops->write = r8402_csi_write; - ops->read = r8402_csi_read; - break; - - default: - ops->write = r8169_csi_write; - ops->read = r8169_csi_read; - break; - } -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e, - int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(tp, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_CLKREQ_EN); -} - -static void rtl_enable_clock_request(struct pci_dev *pdev) -{ - pcie_capability_set_word(pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_CLKREQ_EN); -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - if (tp->dev->mtu <= ETH_DATA_LEN) { - rtl_tx_performance_tweak(pdev, (0x5 << MAX_READ_REQUEST_SHIFT) | - PCI_EXP_DEVCTL_NOSNOOP_EN); - } -} - -static void rtl_hw_start_8168bef(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_start_8168bb(tp); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp) -{ - static const struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable_2(tp); - - rtl_ephy_init(tp, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(tp); -} - -static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl_csi_access_enable_2(tp); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl_csi_access_enable_2(tp); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable_2(tp); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(tp, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(tp); -} - -static void rtl_hw_start_8168c_2(struct rtl8169_private *tp) -{ - static const struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable_2(tp); - - rtl_ephy_init(tp, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(tp); -} - -static void rtl_hw_start_8168c_3(struct rtl8169_private *tp) -{ - rtl_hw_start_8168c_2(tp); -} - -static void rtl_hw_start_8168c_4(struct rtl8169_private *tp) -{ - rtl_csi_access_enable_2(tp); - - __rtl_hw_start_8168cp(tp); -} - -static void rtl_hw_start_8168d(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl_csi_access_enable_2(tp); - - rtl_disable_clock_request(pdev); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168dp(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl_csi_access_enable_1(tp); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - rtl_disable_clock_request(pdev); -} - -static void rtl_hw_start_8168d_4(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - static const struct ephy_info e_info_8168d_4[] = { - { 0x0b, ~0, 0x48 }, - { 0x19, 0x20, 0x50 }, - { 0x0c, ~0, 0x20 } - }; - int i; - - rtl_csi_access_enable_1(tp); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - for (i = 0; i < ARRAY_SIZE(e_info_8168d_4); i++) { - const struct ephy_info *e = e_info_8168d_4 + i; - u16 w; - - w = rtl_ephy_read(tp, e->offset); - rtl_ephy_write(tp, 0x03, (w & e->mask) | e->bits); - } - - rtl_enable_clock_request(pdev); -} - -static void rtl_hw_start_8168e_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - static const struct ephy_info e_info_8168e_1[] = { - { 0x00, 0x0200, 0x0100 }, - { 0x00, 0x0000, 0x0004 }, - { 0x06, 0x0002, 0x0001 }, - { 0x06, 0x0000, 0x0030 }, - { 0x07, 0x0000, 0x2000 }, - { 0x00, 0x0000, 0x0020 }, - { 0x03, 0x5800, 0x2000 }, - { 0x03, 0x0000, 0x0001 }, - { 0x01, 0x0800, 0x1000 }, - { 0x07, 0x0000, 0x4000 }, - { 0x1e, 0x0000, 0x2000 }, - { 0x19, 0xffff, 0xfe6c }, - { 0x0a, 0x0000, 0x0040 } - }; - - rtl_csi_access_enable_2(tp); - - rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1)); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - rtl_disable_clock_request(pdev); - - /* Reset tx FIFO pointer */ - RTL_W32(MISC, RTL_R32(MISC) | TXPLA_RST); - RTL_W32(MISC, RTL_R32(MISC) & ~TXPLA_RST); - - RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); -} - -static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - static const struct ephy_info e_info_8168e_2[] = { - { 0x09, 0x0000, 0x0080 }, - { 0x19, 0x0000, 0x0224 } - }; - - rtl_csi_access_enable_1(tp); - - rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2)); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC); - - RTL_W8(MaxTxPacketSize, EarlySize); - - rtl_disable_clock_request(pdev); - - RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); - RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); - - /* Adjust EEE LED frequency */ - RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); - - RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); - RTL_W32(MISC, RTL_R32(MISC) | PWM_EN); - RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); -} - -static void rtl_hw_start_8168f(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl_csi_access_enable_2(tp); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC); - - RTL_W8(MaxTxPacketSize, EarlySize); - - rtl_disable_clock_request(pdev); - - RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); - RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); - RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); - RTL_W32(MISC, RTL_R32(MISC) | PWM_EN); - RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); -} - -static void rtl_hw_start_8168f_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8168f_1[] = { - { 0x06, 0x00c0, 0x0020 }, - { 0x08, 0x0001, 0x0002 }, - { 0x09, 0x0000, 0x0080 }, - { 0x19, 0x0000, 0x0224 } - }; - - rtl_hw_start_8168f(tp); - - rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1)); - - rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC); - - /* Adjust EEE LED frequency */ - RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); -} - -static void rtl_hw_start_8411(struct rtl8169_private *tp) -{ - static const struct ephy_info e_info_8168f_1[] = { - { 0x06, 0x00c0, 0x0020 }, - { 0x0f, 0xffff, 0x5200 }, - { 0x1e, 0x0000, 0x4000 }, - { 0x19, 0x0000, 0x0224 } - }; - - rtl_hw_start_8168f(tp); - - rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1)); - - rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, ERIAR_EXGMAC); -} - -static void rtl_hw_start_8168g_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); - - rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x080002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); - - rtl_csi_access_enable_1(tp); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); - rtl_eri_write(tp, 0x2f8, ERIAR_MASK_0011, 0x1d8f, ERIAR_EXGMAC); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN); - RTL_W8(MaxTxPacketSize, EarlySize); - - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - - /* Adjust EEE LED frequency */ - RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); - - rtl_w1w0_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x06, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC); -} - -static void rtl_hw_start_8168g_2(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8168g_2[] = { - { 0x00, 0x0000, 0x0008 }, - { 0x0c, 0x3df0, 0x0200 }, - { 0x19, 0xffff, 0xfc00 }, - { 0x1e, 0xffff, 0x20eb } - }; - - rtl_hw_start_8168g_1(tp); - - /* disable aspm and clock request before access ephy */ - RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn); - RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en); - rtl_ephy_init(tp, e_info_8168g_2, ARRAY_SIZE(e_info_8168g_2)); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - rtl_set_rx_max_size(ioaddr, rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->event_slow |= RxFIFOOver | PCSTimeout; - tp->event_slow &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_tx_config_registers(tp); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(tp); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(tp); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(tp); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(tp); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(tp); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(tp); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(tp); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(tp); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(tp); - break; - - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - rtl_hw_start_8168d(tp); - break; - - case RTL_GIGA_MAC_VER_28: - rtl_hw_start_8168d_4(tp); - break; - - case RTL_GIGA_MAC_VER_31: - rtl_hw_start_8168dp(tp); - break; - - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - rtl_hw_start_8168e_1(tp); - break; - case RTL_GIGA_MAC_VER_34: - rtl_hw_start_8168e_2(tp); - break; - - case RTL_GIGA_MAC_VER_35: - case RTL_GIGA_MAC_VER_36: - rtl_hw_start_8168f_1(tp); - break; - - case RTL_GIGA_MAC_VER_38: - rtl_hw_start_8411(tp); - break; - - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - rtl_hw_start_8168g_1(tp); - break; - case RTL_GIGA_MAC_VER_42: - rtl_hw_start_8168g_2(tp); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - rtl_set_rx_mode(dev); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xF000); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8102e_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - static const struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable_2(tp); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - rtl_ephy_init(tp, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl_csi_access_enable_2(tp); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); -} - -static void rtl_hw_start_8102e_3(struct rtl8169_private *tp) -{ - rtl_hw_start_8102e_2(tp); - - rtl_ephy_write(tp, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8105e_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8105e_1[] = { - { 0x07, 0, 0x4000 }, - { 0x19, 0, 0x0200 }, - { 0x19, 0, 0x0020 }, - { 0x1e, 0, 0x2000 }, - { 0x03, 0, 0x0001 }, - { 0x19, 0, 0x0100 }, - { 0x19, 0, 0x0004 }, - { 0x0a, 0, 0x0020 } - }; - - /* Force LAN exit from ASPM if Rx/Tx are not idle */ - RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); - - /* Disable Early Tally Counter */ - RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000); - - RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); - RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); - - rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1)); -} - -static void rtl_hw_start_8105e_2(struct rtl8169_private *tp) -{ - rtl_hw_start_8105e_1(tp); - rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000); -} - -static void rtl_hw_start_8402(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8402[] = { - { 0x19, 0xffff, 0xff64 }, - { 0x1e, 0, 0x4000 } - }; - - rtl_csi_access_enable_2(tp); - - /* Force LAN exit from ASPM if Rx/Tx are not idle */ - RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); - - RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); - RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); - - rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402)); - - rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_w1w0_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC); -} - -static void rtl_hw_start_8106(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - /* Force LAN exit from ASPM if Rx/Tx are not idle */ - RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); - - RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN); - RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); - RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version >= RTL_GIGA_MAC_VER_30) - tp->event_slow &= ~RxFIFOOver; - - if (tp->mac_version == RTL_GIGA_MAC_VER_13 || - tp->mac_version == RTL_GIGA_MAC_VER_16) - pcie_capability_set_word(pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - rtl_set_rx_max_size(ioaddr, rx_buf_sz); - - tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK; - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_tx_config_registers(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(tp); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(tp); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(tp); - break; - - case RTL_GIGA_MAC_VER_29: - rtl_hw_start_8105e_1(tp); - break; - case RTL_GIGA_MAC_VER_30: - rtl_hw_start_8105e_2(tp); - break; - - case RTL_GIGA_MAC_VER_37: - rtl_hw_start_8402(tp); - break; - - case RTL_GIGA_MAC_VER_39: - rtl_hw_start_8106(tp); - break; - case RTL_GIGA_MAC_VER_43: - rtl_hw_start_8168g_2(tp); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(IntrMitigate, 0x0000); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - rtl_set_rx_mode(dev); - - RTL_R8(IntrMask); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (new_mtu < ETH_ZLEN || - new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max) - return -EINVAL; - - if (new_mtu > ETH_DATA_LEN) - rtl_hw_jumbo_enable(tp); - else - rtl_hw_jumbo_disable(tp); - - dev->mtu = new_mtu; - netdev_update_features(dev); - - return 0; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_databuff(struct rtl8169_private *tp, - void **data_buff, struct RxDesc *desc) -{ - dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz, - DMA_FROM_DEVICE); - - kfree(*data_buff); - *data_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static inline void *rtl8169_align(void *data) -{ - return (void *)ALIGN((long)data, 16); -} - -static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp, - struct RxDesc *desc) -{ - void *data; - dma_addr_t mapping; - struct device *d = &tp->pci_dev->dev; - struct net_device *dev = tp->dev; - int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1; - - data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node); - if (!data) - return NULL; - - if (rtl8169_align(data) != data) { - kfree(data); - data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node); - if (!data) - return NULL; - } - - mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(d, mapping))) { - if (net_ratelimit()) - netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); - goto err_out; - } - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); - return data; - -err_out: - kfree(data); - return NULL; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_databuff[i]) { - rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i, - tp->RxDescArray + i); - } - } -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static int rtl8169_rx_fill(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - void *data; - - if (tp->Rx_databuff[i]) - continue; - - data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i); - if (!data) { - rtl8169_make_unusable_by_asic(tp->RxDescArray + i); - goto err_out; - } - tp->Rx_databuff[i] = data; - } - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *)); - - return rtl8169_rx_fill(tp); -} - -static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE); - - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start, - unsigned int n) -{ - unsigned int i; - - for (i = 0; i < n; i++) { - unsigned int entry = (start + i) % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - tp->dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - tx_skb->skb = NULL; - } - } - } -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC); - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl_reset_work(struct rtl8169_private *tp) -{ - struct net_device *dev = tp->dev; - int i; - - napi_disable(&tp->napi); - netif_stop_queue(dev); - synchronize_sched(); - - rtl8169_hw_reset(tp); - - for (i = 0; i < NUM_RX_DESC; i++) - rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz); - - rtl8169_tx_clear(tp); - rtl8169_init_ring_indexes(tp); - - napi_enable(&tp->napi); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 *opts) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc * uninitialized_var(txd); - struct device *d = &tp->pci_dev->dev; - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - const skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = skb_frag_size(frag); - addr = skb_frag_address(frag); - mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(d, mapping))) { - if (net_ratelimit()) - netif_err(tp, drv, tp->dev, - "Failed to map TX fragments DMA!\n"); - goto err_out; - } - - /* Anti gcc 2.95.3 bugware (sic) */ - status = opts[0] | len | - (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->opts2 = cpu_to_le32(opts[1]); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; - -err_out: - rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag); - return -EIO; -} - -static bool rtl_skb_pad(struct sk_buff *skb) -{ - if (skb_padto(skb, ETH_ZLEN)) - return false; - skb_put(skb, ETH_ZLEN - skb->len); - return true; -} - -static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp, struct sk_buff *skb) -{ - return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34; -} - -static inline bool rtl8169_tso_csum(struct rtl8169_private *tp, - struct sk_buff *skb, u32 *opts) -{ - const struct rtl_tx_desc_info *info = tx_desc_info + tp->txd_version; - u32 mss = skb_shinfo(skb)->gso_size; - int offset = info->opts_offset; - - if (mss) { - opts[0] |= TD_LSO; - opts[offset] |= min(mss, TD_MSS_MAX) << info->mss_shift; - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (unlikely(rtl_test_hw_pad_bug(tp, skb))) - return skb_checksum_help(skb) == 0 && rtl_skb_pad(skb); - - if (ip->protocol == IPPROTO_TCP) - opts[offset] |= info->checksum.tcp; - else if (ip->protocol == IPPROTO_UDP) - opts[offset] |= info->checksum.udp; - else - WARN_ON_ONCE(1); - } else { - if (unlikely(rtl_test_hw_pad_bug(tp, skb))) - return rtl_skb_pad(skb); - } - return true; -} - -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - struct device *d = &tp->pci_dev->dev; - dma_addr_t mapping; - u32 status, len; - u32 opts[2]; - int frags; - - if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) { - netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n"); - goto err_stop_0; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop_0; - - opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb)); - opts[0] = DescOwn; - - if (!rtl8169_tso_csum(tp, skb, opts)) - goto err_update_stats; - - len = skb_headlen(skb); - mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(d, mapping))) { - if (net_ratelimit()) - netif_err(tp, drv, dev, "Failed to map TX DMA!\n"); - goto err_dma_0; - } - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - - frags = rtl8169_xmit_frags(tp, skb, opts); - if (frags < 0) - goto err_dma_1; - else if (frags) - opts[0] |= FirstFrag; - else { - opts[0] |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - txd->opts2 = cpu_to_le32(opts[1]); - - skb_tx_timestamp(skb); - - wmb(); - - /* Anti gcc 2.95.3 bugware (sic) */ - status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - tp->cur_tx += frags + 1; - - wmb(); - - RTL_W8(TxPoll, NPQ); - - mmiowb(); - - if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) { - /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must - * not miss a ring update when it notices a stopped queue. - */ - smp_wmb(); - netif_stop_queue(dev); - /* Sync with rtl_tx: - * - publish queue status and cur_tx ring index (write barrier) - * - refresh dirty_tx ring index (read barrier). - * May the current thread have a pessimistic view of the ring - * status and forget to wake up queue, a racing rtl_tx thread - * can't. - */ - smp_mb(); - if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) - netif_wake_queue(dev); - } - - return NETDEV_TX_OK; - -err_dma_1: - rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd); -err_dma_0: - dev_kfree_skb_any(skb); -err_update_stats: - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - -err_stop_0: - netif_stop_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n", - pci_cmd, pci_status); - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->cur_rx) { - void __iomem *ioaddr = tp->mmio_addr; - - netif_info(tp, intr, dev, "disabling PCI DAC\n"); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(tp); - - rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); -} - -static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 status; - - rmb(); - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, - tp->TxDescArray + entry); - if (status & LastFrag) { - u64_stats_update_begin(&tp->tx_stats.syncp); - tp->tx_stats.packets++; - tp->tx_stats.bytes += tx_skb->skb->len; - u64_stats_update_end(&tp->tx_stats.syncp); - dev_kfree_skb_any(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - /* Sync with rtl8169_start_xmit: - * - publish dirty_tx ring index (write barrier) - * - refresh cur_tx ring index and queue status (read barrier) - * May the current thread miss the stopped queue condition, - * a racing xmit thread can only have a right view of the - * ring status. - */ - smp_mb(); - if (netif_queue_stopped(dev) && - TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - if (tp->cur_tx != dirty_tx) { - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(TxPoll, NPQ); - } - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1) -{ - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb_checksum_none_assert(skb); -} - -static struct sk_buff *rtl8169_try_rx_copy(void *data, - struct rtl8169_private *tp, - int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - struct device *d = &tp->pci_dev->dev; - - data = rtl8169_align(data); - dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE); - prefetch(data); - skb = netdev_alloc_skb_ip_align(tp->dev, pkt_size); - if (skb) - memcpy(skb->data, data, pkt_size); - dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE); - - return skb; -} - -static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int count; - - cur_rx = tp->cur_rx; - - for (rx_left = min(budget, NUM_RX_DESC); rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - rmb(); - status = le32_to_cpu(desc->opts1) & tp->opts1_mask; - - if (status & DescOwn) - break; - if (unlikely(status & RxRES)) { - netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n", - status); - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); - dev->stats.rx_fifo_errors++; - } - if ((status & (RxRUNT | RxCRC)) && - !(status & (RxRWT | RxFOVF)) && - (dev->features & NETIF_F_RXALL)) - goto process_pkt; - } else { - struct sk_buff *skb; - dma_addr_t addr; - int pkt_size; - -process_pkt: - addr = le64_to_cpu(desc->addr); - if (likely(!(dev->features & NETIF_F_RXFCS))) - pkt_size = (status & 0x00003fff) - 4; - else - pkt_size = status & 0x00003fff; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - goto release_descriptor; - } - - skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], - tp, pkt_size, addr); - if (!skb) { - dev->stats.rx_dropped++; - goto release_descriptor; - } - - rtl8169_rx_csum(skb, status); - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - rtl8169_rx_vlan_tag(desc, skb); - - napi_gro_receive(&tp->napi, skb); - - u64_stats_update_begin(&tp->rx_stats.syncp); - tp->rx_stats.packets++; - tp->rx_stats.bytes += pkt_size; - u64_stats_update_end(&tp->rx_stats.syncp); - } -release_descriptor: - desc->opts2 = 0; - wmb(); - rtl8169_mark_to_asic(desc, rx_buf_sz); - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - int handled = 0; - u16 status; - - status = rtl_get_events(tp); - if (status && status != 0xffff) { - status &= RTL_EVENT_NAPI | tp->event_slow; - if (status) { - handled = 1; - - rtl_irq_disable(tp); - napi_schedule(&tp->napi); - } - } - return IRQ_RETVAL(handled); -} - -/* - * Workqueue context. - */ -static void rtl_slow_event_work(struct rtl8169_private *tp) -{ - struct net_device *dev = tp->dev; - u16 status; - - status = rtl_get_events(tp) & tp->event_slow; - rtl_ack_events(tp, status); - - if (unlikely(status & RxFIFOOver)) { - switch (tp->mac_version) { - /* Work around for rx fifo overflow */ - case RTL_GIGA_MAC_VER_11: - netif_stop_queue(dev); - /* XXX - Hack alert. See rtl_task(). */ - set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags); - default: - break; - } - } - - if (unlikely(status & SYSErr)) - rtl8169_pcierr_interrupt(dev); - - if (status & LinkChg) - __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true); - - rtl_irq_enable_all(tp); -} - -static void rtl_task(struct work_struct *work) -{ - static const struct { - int bitnr; - void (*action)(struct rtl8169_private *); - } rtl_work[] = { - /* XXX - keep rtl_slow_event_work() as first element. */ - { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work }, - { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work }, - { RTL_FLAG_TASK_PHY_PENDING, rtl_phy_work } - }; - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, wk.work); - struct net_device *dev = tp->dev; - int i; - - rtl_lock_work(tp); - - if (!netif_running(dev) || - !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags)) - goto out_unlock; - - for (i = 0; i < ARRAY_SIZE(rtl_work); i++) { - bool pending; - - pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags); - if (pending) - rtl_work[i].action(tp); - } - -out_unlock: - rtl_unlock_work(tp); -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow; - int work_done= 0; - u16 status; - - status = rtl_get_events(tp); - rtl_ack_events(tp, status & ~tp->event_slow); - - if (status & RTL_EVENT_NAPI_RX) - work_done = rtl_rx(dev, tp, (u32) budget); - - if (status & RTL_EVENT_NAPI_TX) - rtl_tx(dev, tp); - - if (status & tp->event_slow) { - enable_mask &= ~tp->event_slow; - - rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING); - } - - if (work_done < budget) { - napi_complete(napi); - - rtl_irq_enable(tp, enable_mask); - mmiowb(); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - del_timer_sync(&tp->timer); - - napi_disable(&tp->napi); - netif_stop_queue(dev); - - rtl8169_hw_reset(tp); - /* - * At this point device interrupts can not be enabled in any function, - * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task) - * and napi is disabled (rtl8169_poll). - */ - rtl8169_rx_missed(dev, ioaddr); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); - - rtl_pll_power_down(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - pm_runtime_get_sync(&pdev->dev); - - /* Update counters before going down */ - rtl8169_update_counters(dev); - - rtl_lock_work(tp); - clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); - - rtl8169_down(dev); - rtl_unlock_work(tp); - - free_irq(pdev->irq, dev); - - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - pm_runtime_put_sync(&pdev->dev); - - return 0; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_interrupt(tp->pci_dev->irq, dev); -} -#endif - -static int rtl_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - pm_runtime_get_sync(&pdev->dev); - - /* - * Rx and Tx descriptors needs 256 bytes alignment. - * dma_alloc_coherent provides more. - */ - tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr, GFP_KERNEL); - if (!tp->TxDescArray) - goto err_pm_runtime_put; - - tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr, GFP_KERNEL); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_WORK(&tp->wk.work, rtl_task); - - smp_mb(); - - rtl_request_firmware(tp); - - retval = request_irq(pdev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_fw_2; - - rtl_lock_work(tp); - - set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); - - napi_enable(&tp->napi); - - rtl8169_init_phy(dev, tp); - - __rtl8169_set_features(dev, dev->features); - - rtl_pll_power_up(tp); - - rtl_hw_start(dev); - - netif_start_queue(dev); - - rtl_unlock_work(tp); - - tp->saved_wolopts = 0; - pm_runtime_put_noidle(&pdev->dev); - - rtl8169_check_link_status(dev, tp, ioaddr); -out: - return retval; - -err_release_fw_2: - rtl_release_firmware(tp); - rtl8169_rx_clear(tp); -err_free_rx_1: - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - tp->RxDescArray = NULL; -err_free_tx_0: - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; -err_pm_runtime_put: - pm_runtime_put_noidle(&pdev->dev); - goto out; -} - -static struct rtnl_link_stats64 * -rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - unsigned int start; - - if (netif_running(dev)) - rtl8169_rx_missed(dev, ioaddr); - - do { - start = u64_stats_fetch_begin_bh(&tp->rx_stats.syncp); - stats->rx_packets = tp->rx_stats.packets; - stats->rx_bytes = tp->rx_stats.bytes; - } while (u64_stats_fetch_retry_bh(&tp->rx_stats.syncp, start)); - - - do { - start = u64_stats_fetch_begin_bh(&tp->tx_stats.syncp); - stats->tx_packets = tp->tx_stats.packets; - stats->tx_bytes = tp->tx_stats.bytes; - } while (u64_stats_fetch_retry_bh(&tp->tx_stats.syncp, start)); - - stats->rx_dropped = dev->stats.rx_dropped; - stats->tx_dropped = dev->stats.tx_dropped; - stats->rx_length_errors = dev->stats.rx_length_errors; - stats->rx_errors = dev->stats.rx_errors; - stats->rx_crc_errors = dev->stats.rx_crc_errors; - stats->rx_fifo_errors = dev->stats.rx_fifo_errors; - stats->rx_missed_errors = dev->stats.rx_missed_errors; - - return stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); - - rtl_lock_work(tp); - napi_disable(&tp->napi); - clear_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); - rtl_unlock_work(tp); - - rtl_pll_power_down(tp); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - - rtl8169_net_suspend(dev); - - return 0; -} - -static void __rtl8169_resume(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - netif_device_attach(dev); - - rtl_pll_power_up(tp); - - rtl_lock_work(tp); - napi_enable(&tp->napi); - set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); - rtl_unlock_work(tp); - - rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_phy(dev, tp); - - if (netif_running(dev)) - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - rtl_lock_work(tp); - tp->saved_wolopts = __rtl8169_get_wol(tp); - __rtl8169_set_wol(tp, WAKE_ANY); - rtl_unlock_work(tp); - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_runtime_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - rtl_lock_work(tp); - __rtl8169_set_wol(tp, tp->saved_wolopts); - tp->saved_wolopts = 0; - rtl_unlock_work(tp); - - rtl8169_init_phy(dev, tp); - - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_idle(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->TxDescArray ? -EBUSY : 0; -} - -static const struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, - .runtime_suspend = rtl8169_runtime_suspend, - .runtime_resume = rtl8169_runtime_resume, - .runtime_idle = rtl8169_runtime_idle, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_wol_shutdown_quirk(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - /* WoL fails with 8168b when the receiver is disabled. */ - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - pci_clear_master(tp->pci_dev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - break; - default: - break; - } -} - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - struct device *d = &pdev->dev; - - pm_runtime_get_sync(d); - - rtl8169_net_suspend(dev); - - /* Restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl8169_hw_reset(tp); - - if (system_state == SYSTEM_POWER_OFF) { - if (__rtl8169_get_wol(tp) & WAKE_ANY) { - rtl_wol_suspend_quirk(tp); - rtl_wol_shutdown_quirk(tp); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } - - pm_runtime_put_noidle(d); -} - -static void rtl_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version == RTL_GIGA_MAC_VER_27 || - tp->mac_version == RTL_GIGA_MAC_VER_28 || - tp->mac_version == RTL_GIGA_MAC_VER_31) { - rtl8168_driver_stop(tp); - } - - cancel_work_sync(&tp->wk.work); - - netif_napi_del(&tp->napi); - - unregister_netdev(dev); - - rtl_release_firmware(tp); - - if (pci_dev_run_wake(pdev)) - pm_runtime_get_noresume(&pdev->dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); - pci_set_drvdata(pdev, NULL); -} - -static const struct net_device_ops rtl_netdev_ops = { - .ndo_open = rtl_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats64 = rtl8169_get_stats64, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_fix_features = rtl8169_fix_features, - .ndo_set_features = rtl8169_set_features, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_rx_mode = rtl_set_rx_mode, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 event_slow; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .event_slow = SYSErr | LinkChg | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver | - PCSTimeout, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct rtl8169_private *tp, - const struct rtl_cfg_info *cfg) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(tp->pci_dev)) { - netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - RTL_W8(Config2, cfg2); - return msi; -} - -DECLARE_RTL_COND(rtl_link_list_ready_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R8(MCU) & LINK_LIST_RDY; -} - -DECLARE_RTL_COND(rtl_rxtx_empty_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY; -} - -static void rtl_hw_init_8168g(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 data; - - tp->ocp_base = OCP_STD_PHY_BASE; - - RTL_W32(MISC, RTL_R32(MISC) | RXDV_GATED_EN); - - if (!rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42)) - return; - - if (!rtl_udelay_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42)) - return; - - RTL_W8(ChipCmd, RTL_R8(ChipCmd) & ~(CmdTxEnb | CmdRxEnb)); - msleep(1); - RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); - - data = r8168_mac_ocp_read(tp, 0xe8de); - data &= ~(1 << 14); - r8168_mac_ocp_write(tp, 0xe8de, data); - - if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42)) - return; - - data = r8168_mac_ocp_read(tp, 0xe8de); - data |= (1 << 15); - r8168_mac_ocp_write(tp, 0xe8de, data); - - if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42)) - return; -} - -static void rtl_hw_initialize(struct rtl8169_private *tp) -{ - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - rtl_hw_init_8168g(tp); - break; - - default: - break; - } -} - -static int -rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - int chipset, i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* disable ASPM completely as that cause random device stop working - * problems as well as full system hangs for some PCIe devices users */ - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | - PCIE_LINK_STATE_CLKPM); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - netif_err(tp, probe, dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - if (pci_set_mwi(pdev) < 0) - netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n"); - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - netif_err(tp, probe, dev, - "region #%d not an MMIO resource, aborting\n", - region); - rc = -ENODEV; - goto err_out_mwi_2; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - netif_err(tp, probe, dev, - "Invalid PCI region size(s), aborting\n"); - rc = -ENODEV; - goto err_out_mwi_2; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - netif_err(tp, probe, dev, "could not request regions\n"); - goto err_out_mwi_2; - } - - tp->cp_cmd = RxChkSum; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - netif_err(tp, probe, dev, "DMA configuration failed\n"); - goto err_out_free_res_3; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_3; - } - tp->mmio_addr = ioaddr; - - if (!pci_is_pcie(pdev)) - netif_info(tp, probe, dev, "not PCI Express\n"); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, dev, cfg->default_ver); - - rtl_init_rxcfg(tp); - - rtl_irq_disable(tp); - - rtl_hw_initialize(tp); - - rtl_hw_reset(tp); - - rtl_ack_events(tp, 0xffff); - - pci_set_master(pdev); - - /* - * Pretend we are using VLANs; This bypasses a nasty bug where - * Interrupts stop flowing on high load on 8110SCd controllers. - */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - tp->cp_cmd |= RxVlan; - - rtl_init_mdio_ops(tp); - rtl_init_pll_power_ops(tp); - rtl_init_jumbo_ops(tp); - rtl_init_csi_ops(tp); - - rtl8169_print_mac_version(tp); - - chipset = tp->mac_version; - tp->txd_version = rtl_chip_infos[chipset].txd_version; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & PMEStatus); - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(tp, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (rtl_tbi_enabled(tp)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - mutex_init(&tp->wk.mutex); - - /* Get MAC address */ - for (i = 0; i < ETH_ALEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - - SET_ETHTOOL_OPS(dev, &rtl8169_ethtool_ops); - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - - /* don't enable SG, IP_CSUM and TSO by default - it might not work - * properly for all devices */ - dev->features |= NETIF_F_RXCSUM | - NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; - - dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | - NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_RX; - dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | - NETIF_F_HIGHDMA; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - /* 8110SCd requires hardware Rx VLAN - disallow toggling */ - dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX; - - dev->hw_features |= NETIF_F_RXALL; - dev->hw_features |= NETIF_F_RXFCS; - - tp->hw_start = cfg->hw_start; - tp->event_slow = cfg->event_slow; - - tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ? - ~(RxBOVF | RxFOVF) : ~0; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - tp->rtl_fw = RTL_FIRMWARE_UNKNOWN; - - rc = register_netdev(dev); - if (rc < 0) - goto err_out_msi_4; - - pci_set_drvdata(pdev, dev); - - netif_info(tp, probe, dev, "%s at 0x%p, %pM, XID %08x IRQ %d\n", - rtl_chip_infos[chipset].name, ioaddr, dev->dev_addr, - (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), pdev->irq); - if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) { - netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, " - "tx checksumming: %s]\n", - rtl_chip_infos[chipset].jumbo_max, - rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko"); - } - - if (tp->mac_version == RTL_GIGA_MAC_VER_27 || - tp->mac_version == RTL_GIGA_MAC_VER_28 || - tp->mac_version == RTL_GIGA_MAC_VER_31) { - rtl8168_driver_start(tp); - } - - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - - if (pci_dev_run_wake(pdev)) - pm_runtime_put_noidle(&pdev->dev); - - netif_carrier_off(dev); - -out: - return rc; - -err_out_msi_4: - netif_napi_del(&tp->napi); - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_3: - pci_release_regions(pdev); -err_out_mwi_2: - pci_clear_mwi(pdev); - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl_init_one, - .remove = rtl_remove_one, - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -module_pci_driver(rtl8169_pci_driver); diff --git a/addons/r8169/src/4.4.180/Makefile b/addons/r8169/src/4.4.180/Makefile deleted file mode 100644 index 340f8cbe..00000000 --- a/addons/r8169/src/4.4.180/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -obj-m += r8169.o -obj-m += mii.o diff --git a/addons/r8169/src/4.4.180/mii.c b/addons/r8169/src/4.4.180/mii.c deleted file mode 100644 index 993570b1..00000000 --- a/addons/r8169/src/4.4.180/mii.c +++ /dev/null @@ -1,474 +0,0 @@ -/* - - mii.c: MII interface library - - Maintained by Jeff Garzik - Copyright 2001,2002 Jeff Garzik - - Various code came from myson803.c and other files by - Donald Becker. Copyright: - - Written 1998-2002 by Donald Becker. - - This software may be used and distributed according - to the terms of the GNU General Public License (GPL), - incorporated herein by reference. Drivers based on - or derived from this code fall under the GPL and must - retain the authorship, copyright and license notice. - This file is not a complete program and may only be - used when the entire operating system is licensed - under the GPL. - - The author may be reached as becker@scyld.com, or C/O - Scyld Computing Corporation - 410 Severn Ave., Suite 210 - Annapolis MD 21403 - - - */ - -#include -#include -#include -#include -#include - -static u32 mii_get_an(struct mii_if_info *mii, u16 addr) -{ - int advert; - - advert = mii->mdio_read(mii->dev, mii->phy_id, addr); - - return mii_lpa_to_ethtool_lpa_t(advert); -} - -/** - * mii_ethtool_gset - get settings that are specified in @ecmd - * @mii: MII interface - * @ecmd: requested ethtool_cmd - * - * The @ecmd parameter is expected to have been cleared before calling - * mii_ethtool_gset(). - * - * Returns 0 for success, negative on error. - */ -int mii_ethtool_gset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) -{ - struct net_device *dev = mii->dev; - u16 bmcr, bmsr, ctrl1000 = 0, stat1000 = 0; - u32 nego; - - ecmd->supported = - (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | - SUPPORTED_Autoneg | SUPPORTED_TP | SUPPORTED_MII); - if (mii->supports_gmii) - ecmd->supported |= SUPPORTED_1000baseT_Half | - SUPPORTED_1000baseT_Full; - - /* only supports twisted-pair */ - ecmd->port = PORT_MII; - - /* only supports internal transceiver */ - ecmd->transceiver = XCVR_INTERNAL; - - /* this isn't fully supported at higher layers */ - ecmd->phy_address = mii->phy_id; - ecmd->mdio_support = ETH_MDIO_SUPPORTS_C22; - - ecmd->advertising = ADVERTISED_TP | ADVERTISED_MII; - - bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); - bmsr = mii->mdio_read(dev, mii->phy_id, MII_BMSR); - if (mii->supports_gmii) { - ctrl1000 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); - stat1000 = mii->mdio_read(dev, mii->phy_id, MII_STAT1000); - } - if (bmcr & BMCR_ANENABLE) { - ecmd->advertising |= ADVERTISED_Autoneg; - ecmd->autoneg = AUTONEG_ENABLE; - - ecmd->advertising |= mii_get_an(mii, MII_ADVERTISE); - if (mii->supports_gmii) - ecmd->advertising |= - mii_ctrl1000_to_ethtool_adv_t(ctrl1000); - - if (bmsr & BMSR_ANEGCOMPLETE) { - ecmd->lp_advertising = mii_get_an(mii, MII_LPA); - ecmd->lp_advertising |= - mii_stat1000_to_ethtool_lpa_t(stat1000); - } else { - ecmd->lp_advertising = 0; - } - - nego = ecmd->advertising & ecmd->lp_advertising; - - if (nego & (ADVERTISED_1000baseT_Full | - ADVERTISED_1000baseT_Half)) { - ethtool_cmd_speed_set(ecmd, SPEED_1000); - ecmd->duplex = !!(nego & ADVERTISED_1000baseT_Full); - } else if (nego & (ADVERTISED_100baseT_Full | - ADVERTISED_100baseT_Half)) { - ethtool_cmd_speed_set(ecmd, SPEED_100); - ecmd->duplex = !!(nego & ADVERTISED_100baseT_Full); - } else { - ethtool_cmd_speed_set(ecmd, SPEED_10); - ecmd->duplex = !!(nego & ADVERTISED_10baseT_Full); - } - } else { - ecmd->autoneg = AUTONEG_DISABLE; - - ethtool_cmd_speed_set(ecmd, - ((bmcr & BMCR_SPEED1000 && - (bmcr & BMCR_SPEED100) == 0) ? - SPEED_1000 : - ((bmcr & BMCR_SPEED100) ? - SPEED_100 : SPEED_10))); - ecmd->duplex = (bmcr & BMCR_FULLDPLX) ? DUPLEX_FULL : DUPLEX_HALF; - } - - mii->full_duplex = ecmd->duplex; - - /* ignore maxtxpkt, maxrxpkt for now */ - - return 0; -} - -/** - * mii_ethtool_sset - set settings that are specified in @ecmd - * @mii: MII interface - * @ecmd: requested ethtool_cmd - * - * Returns 0 for success, negative on error. - */ -int mii_ethtool_sset(struct mii_if_info *mii, struct ethtool_cmd *ecmd) -{ - struct net_device *dev = mii->dev; - u32 speed = ethtool_cmd_speed(ecmd); - - if (speed != SPEED_10 && - speed != SPEED_100 && - speed != SPEED_1000) - return -EINVAL; - if (ecmd->duplex != DUPLEX_HALF && ecmd->duplex != DUPLEX_FULL) - return -EINVAL; - if (ecmd->port != PORT_MII) - return -EINVAL; - if (ecmd->transceiver != XCVR_INTERNAL) - return -EINVAL; - if (ecmd->phy_address != mii->phy_id) - return -EINVAL; - if (ecmd->autoneg != AUTONEG_DISABLE && ecmd->autoneg != AUTONEG_ENABLE) - return -EINVAL; - if ((speed == SPEED_1000) && (!mii->supports_gmii)) - return -EINVAL; - - /* ignore supported, maxtxpkt, maxrxpkt */ - - if (ecmd->autoneg == AUTONEG_ENABLE) { - u32 bmcr, advert, tmp; - u32 advert2 = 0, tmp2 = 0; - - if ((ecmd->advertising & (ADVERTISED_10baseT_Half | - ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | - ADVERTISED_100baseT_Full | - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full)) == 0) - return -EINVAL; - - /* advertise only what has been requested */ - advert = mii->mdio_read(dev, mii->phy_id, MII_ADVERTISE); - tmp = advert & ~(ADVERTISE_ALL | ADVERTISE_100BASE4); - if (mii->supports_gmii) { - advert2 = mii->mdio_read(dev, mii->phy_id, MII_CTRL1000); - tmp2 = advert2 & ~(ADVERTISE_1000HALF | ADVERTISE_1000FULL); - } - tmp |= ethtool_adv_to_mii_adv_t(ecmd->advertising); - - if (mii->supports_gmii) - tmp2 |= - ethtool_adv_to_mii_ctrl1000_t(ecmd->advertising); - if (advert != tmp) { - mii->mdio_write(dev, mii->phy_id, MII_ADVERTISE, tmp); - mii->advertising = tmp; - } - if ((mii->supports_gmii) && (advert2 != tmp2)) - mii->mdio_write(dev, mii->phy_id, MII_CTRL1000, tmp2); - - /* turn on autonegotiation, and force a renegotiate */ - bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); - bmcr |= (BMCR_ANENABLE | BMCR_ANRESTART); - mii->mdio_write(dev, mii->phy_id, MII_BMCR, bmcr); - - mii->force_media = 0; - } else { - u32 bmcr, tmp; - - /* turn off auto negotiation, set speed and duplexity */ - bmcr = mii->mdio_read(dev, mii->phy_id, MII_BMCR); - tmp = bmcr & ~(BMCR_ANENABLE | BMCR_SPEED100 | - BMCR_SPEED1000 | BMCR_FULLDPLX); - if (speed == SPEED_1000) - tmp |= BMCR_SPEED1000; - else if (speed == SPEED_100) - tmp |= BMCR_SPEED100; - if (ecmd->duplex == DUPLEX_FULL) { - tmp |= BMCR_FULLDPLX; - mii->full_duplex = 1; - } else - mii->full_duplex = 0; - if (bmcr != tmp) - mii->mdio_write(dev, mii->phy_id, MII_BMCR, tmp); - - mii->force_media = 1; - } - return 0; -} - -/** - * mii_check_gmii_support - check if the MII supports Gb interfaces - * @mii: the MII interface - */ -int mii_check_gmii_support(struct mii_if_info *mii) -{ - int reg; - - reg = mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); - if (reg & BMSR_ESTATEN) { - reg = mii->mdio_read(mii->dev, mii->phy_id, MII_ESTATUS); - if (reg & (ESTATUS_1000_TFULL | ESTATUS_1000_THALF)) - return 1; - } - - return 0; -} - -/** - * mii_link_ok - is link status up/ok - * @mii: the MII interface - * - * Returns 1 if the MII reports link status up/ok, 0 otherwise. - */ -int mii_link_ok (struct mii_if_info *mii) -{ - /* first, a dummy read, needed to latch some MII phys */ - mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR); - if (mii->mdio_read(mii->dev, mii->phy_id, MII_BMSR) & BMSR_LSTATUS) - return 1; - return 0; -} - -/** - * mii_nway_restart - restart NWay (autonegotiation) for this interface - * @mii: the MII interface - * - * Returns 0 on success, negative on error. - */ -int mii_nway_restart (struct mii_if_info *mii) -{ - int bmcr; - int r = -EINVAL; - - /* if autoneg is off, it's an error */ - bmcr = mii->mdio_read(mii->dev, mii->phy_id, MII_BMCR); - - if (bmcr & BMCR_ANENABLE) { - bmcr |= BMCR_ANRESTART; - mii->mdio_write(mii->dev, mii->phy_id, MII_BMCR, bmcr); - r = 0; - } - - return r; -} - -/** - * mii_check_link - check MII link status - * @mii: MII interface - * - * If the link status changed (previous != current), call - * netif_carrier_on() if current link status is Up or call - * netif_carrier_off() if current link status is Down. - */ -void mii_check_link (struct mii_if_info *mii) -{ - int cur_link = mii_link_ok(mii); - int prev_link = netif_carrier_ok(mii->dev); - - if (cur_link && !prev_link) - netif_carrier_on(mii->dev); - else if (prev_link && !cur_link) - netif_carrier_off(mii->dev); -} - -/** - * mii_check_media - check the MII interface for a carrier/speed/duplex change - * @mii: the MII interface - * @ok_to_print: OK to print link up/down messages - * @init_media: OK to save duplex mode in @mii - * - * Returns 1 if the duplex mode changed, 0 if not. - * If the media type is forced, always returns 0. - */ -unsigned int mii_check_media (struct mii_if_info *mii, - unsigned int ok_to_print, - unsigned int init_media) -{ - unsigned int old_carrier, new_carrier; - int advertise, lpa, media, duplex; - int lpa2 = 0; - - /* check current and old link status */ - old_carrier = netif_carrier_ok(mii->dev) ? 1 : 0; - new_carrier = (unsigned int) mii_link_ok(mii); - - /* if carrier state did not change, this is a "bounce", - * just exit as everything is already set correctly - */ - if ((!init_media) && (old_carrier == new_carrier)) - return 0; /* duplex did not change */ - - /* no carrier, nothing much to do */ - if (!new_carrier) { - netif_carrier_off(mii->dev); - if (ok_to_print) - netdev_info(mii->dev, "link down\n"); - return 0; /* duplex did not change */ - } - - /* - * we have carrier, see who's on the other end - */ - netif_carrier_on(mii->dev); - - if (mii->force_media) { - if (ok_to_print) - netdev_info(mii->dev, "link up\n"); - return 0; /* duplex did not change */ - } - - /* get MII advertise and LPA values */ - if ((!init_media) && (mii->advertising)) - advertise = mii->advertising; - else { - advertise = mii->mdio_read(mii->dev, mii->phy_id, MII_ADVERTISE); - mii->advertising = advertise; - } - lpa = mii->mdio_read(mii->dev, mii->phy_id, MII_LPA); - if (mii->supports_gmii) - lpa2 = mii->mdio_read(mii->dev, mii->phy_id, MII_STAT1000); - - /* figure out media and duplex from advertise and LPA values */ - media = mii_nway_result(lpa & advertise); - duplex = (media & ADVERTISE_FULL) ? 1 : 0; - if (lpa2 & LPA_1000FULL) - duplex = 1; - - if (ok_to_print) - netdev_info(mii->dev, "link up, %uMbps, %s-duplex, lpa 0x%04X\n", - lpa2 & (LPA_1000FULL | LPA_1000HALF) ? 1000 : - media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? - 100 : 10, - duplex ? "full" : "half", - lpa); - - if ((init_media) || (mii->full_duplex != duplex)) { - mii->full_duplex = duplex; - return 1; /* duplex changed */ - } - - return 0; /* duplex did not change */ -} - -/** - * generic_mii_ioctl - main MII ioctl interface - * @mii_if: the MII interface - * @mii_data: MII ioctl data structure - * @cmd: MII ioctl command - * @duplex_chg_out: pointer to @duplex_changed status if there was no - * ioctl error - * - * Returns 0 on success, negative on error. - */ -int generic_mii_ioctl(struct mii_if_info *mii_if, - struct mii_ioctl_data *mii_data, int cmd, - unsigned int *duplex_chg_out) -{ - int rc = 0; - unsigned int duplex_changed = 0; - - if (duplex_chg_out) - *duplex_chg_out = 0; - - mii_data->phy_id &= mii_if->phy_id_mask; - mii_data->reg_num &= mii_if->reg_num_mask; - - switch(cmd) { - case SIOCGMIIPHY: - mii_data->phy_id = mii_if->phy_id; - /* fall through */ - - case SIOCGMIIREG: - mii_data->val_out = - mii_if->mdio_read(mii_if->dev, mii_data->phy_id, - mii_data->reg_num); - break; - - case SIOCSMIIREG: { - u16 val = mii_data->val_in; - - if (mii_data->phy_id == mii_if->phy_id) { - switch(mii_data->reg_num) { - case MII_BMCR: { - unsigned int new_duplex = 0; - if (val & (BMCR_RESET|BMCR_ANENABLE)) - mii_if->force_media = 0; - else - mii_if->force_media = 1; - if (mii_if->force_media && - (val & BMCR_FULLDPLX)) - new_duplex = 1; - if (mii_if->full_duplex != new_duplex) { - duplex_changed = 1; - mii_if->full_duplex = new_duplex; - } - break; - } - case MII_ADVERTISE: - mii_if->advertising = val; - break; - default: - /* do nothing */ - break; - } - } - - mii_if->mdio_write(mii_if->dev, mii_data->phy_id, - mii_data->reg_num, val); - break; - } - - default: - rc = -EOPNOTSUPP; - break; - } - - if ((rc == 0) && (duplex_chg_out) && (duplex_changed)) - *duplex_chg_out = 1; - - return rc; -} - -MODULE_AUTHOR ("Jeff Garzik "); -MODULE_DESCRIPTION ("MII hardware support library"); -MODULE_LICENSE("GPL"); - -EXPORT_SYMBOL(mii_link_ok); -EXPORT_SYMBOL(mii_nway_restart); -EXPORT_SYMBOL(mii_ethtool_gset); -EXPORT_SYMBOL(mii_ethtool_sset); -EXPORT_SYMBOL(mii_check_link); -EXPORT_SYMBOL(mii_check_media); -EXPORT_SYMBOL(mii_check_gmii_support); -EXPORT_SYMBOL(generic_mii_ioctl); - diff --git a/addons/r8169/src/4.4.180/r8169.c b/addons/r8169/src/4.4.180/r8169.c deleted file mode 100644 index 8f40e121..00000000 --- a/addons/r8169/src/4.4.180/r8169.c +++ /dev/null @@ -1,8482 +0,0 @@ -/* - * r8169.c: RealTek 8169/8168/8101 ethernet driver. - * - * Copyright (c) 2002 ShuChen - * Copyright (c) 2003 - 2007 Francois Romieu - * Copyright (c) a lot of people too. Please respect their work. - * - * See MAINTAINERS file for support contact information. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#define RTL8169_VERSION "2.3LK-NAPI" -#define MODULENAME "r8169" -#define PFX MODULENAME ": " - -#define FIRMWARE_8168D_1 "rtl_nic/rtl8168d-1.fw" -#define FIRMWARE_8168D_2 "rtl_nic/rtl8168d-2.fw" -#define FIRMWARE_8168E_1 "rtl_nic/rtl8168e-1.fw" -#define FIRMWARE_8168E_2 "rtl_nic/rtl8168e-2.fw" -#define FIRMWARE_8168E_3 "rtl_nic/rtl8168e-3.fw" -#define FIRMWARE_8168F_1 "rtl_nic/rtl8168f-1.fw" -#define FIRMWARE_8168F_2 "rtl_nic/rtl8168f-2.fw" -#define FIRMWARE_8105E_1 "rtl_nic/rtl8105e-1.fw" -#define FIRMWARE_8402_1 "rtl_nic/rtl8402-1.fw" -#define FIRMWARE_8411_1 "rtl_nic/rtl8411-1.fw" -#define FIRMWARE_8411_2 "rtl_nic/rtl8411-2.fw" -#define FIRMWARE_8106E_1 "rtl_nic/rtl8106e-1.fw" -#define FIRMWARE_8106E_2 "rtl_nic/rtl8106e-2.fw" -#define FIRMWARE_8168G_2 "rtl_nic/rtl8168g-2.fw" -#define FIRMWARE_8168G_3 "rtl_nic/rtl8168g-3.fw" -#define FIRMWARE_8168H_1 "rtl_nic/rtl8168h-1.fw" -#define FIRMWARE_8168H_2 "rtl_nic/rtl8168h-2.fw" -#define FIRMWARE_8107E_1 "rtl_nic/rtl8107e-1.fw" -#define FIRMWARE_8107E_2 "rtl_nic/rtl8107e-2.fw" - -#ifdef RTL8169_DEBUG -#define assert(expr) \ - if (!(expr)) { \ - printk( "Assertion failed! %s,%s,%s,line=%d\n", \ - #expr,__FILE__,__func__,__LINE__); \ - } -#define dprintk(fmt, args...) \ - do { printk(KERN_DEBUG PFX fmt, ## args); } while (0) -#else -#define assert(expr) do {} while (0) -#define dprintk(fmt, args...) do {} while (0) -#endif /* RTL8169_DEBUG */ - -#define R8169_MSG_DEFAULT \ - (NETIF_MSG_DRV | NETIF_MSG_PROBE | NETIF_MSG_IFUP | NETIF_MSG_IFDOWN) - -#define TX_SLOTS_AVAIL(tp) \ - (tp->dirty_tx + NUM_TX_DESC - tp->cur_tx) - -/* A skbuff with nr_frags needs nr_frags+1 entries in the tx queue */ -#define TX_FRAGS_READY_FOR(tp,nr_frags) \ - (TX_SLOTS_AVAIL(tp) >= (nr_frags + 1)) - -/* Maximum number of multicast addresses to filter (vs. Rx-all-multicast). - The RTL chips use a 64 element hash table based on the Ethernet CRC. */ -static const int multicast_filter_limit = 32; - -#define MAX_READ_REQUEST_SHIFT 12 -#define TX_DMA_BURST 7 /* Maximum PCI burst, '7' is unlimited */ -#define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ - -#define R8169_REGS_SIZE 256 -#define R8169_NAPI_WEIGHT 64 -#define NUM_TX_DESC 64 /* Number of Tx descriptor registers */ -#define NUM_RX_DESC 256U /* Number of Rx descriptor registers */ -#define R8169_TX_RING_BYTES (NUM_TX_DESC * sizeof(struct TxDesc)) -#define R8169_RX_RING_BYTES (NUM_RX_DESC * sizeof(struct RxDesc)) - -#define RTL8169_TX_TIMEOUT (6*HZ) -#define RTL8169_PHY_TIMEOUT (10*HZ) - -/* write/read MMIO register */ -#define RTL_W8(reg, val8) writeb ((val8), ioaddr + (reg)) -#define RTL_W16(reg, val16) writew ((val16), ioaddr + (reg)) -#define RTL_W32(reg, val32) writel ((val32), ioaddr + (reg)) -#define RTL_R8(reg) readb (ioaddr + (reg)) -#define RTL_R16(reg) readw (ioaddr + (reg)) -#define RTL_R32(reg) readl (ioaddr + (reg)) - -enum mac_version { - RTL_GIGA_MAC_VER_01 = 0, - RTL_GIGA_MAC_VER_02, - RTL_GIGA_MAC_VER_03, - RTL_GIGA_MAC_VER_04, - RTL_GIGA_MAC_VER_05, - RTL_GIGA_MAC_VER_06, - RTL_GIGA_MAC_VER_07, - RTL_GIGA_MAC_VER_08, - RTL_GIGA_MAC_VER_09, - RTL_GIGA_MAC_VER_10, - RTL_GIGA_MAC_VER_11, - RTL_GIGA_MAC_VER_12, - RTL_GIGA_MAC_VER_13, - RTL_GIGA_MAC_VER_14, - RTL_GIGA_MAC_VER_15, - RTL_GIGA_MAC_VER_16, - RTL_GIGA_MAC_VER_17, - RTL_GIGA_MAC_VER_18, - RTL_GIGA_MAC_VER_19, - RTL_GIGA_MAC_VER_20, - RTL_GIGA_MAC_VER_21, - RTL_GIGA_MAC_VER_22, - RTL_GIGA_MAC_VER_23, - RTL_GIGA_MAC_VER_24, - RTL_GIGA_MAC_VER_25, - RTL_GIGA_MAC_VER_26, - RTL_GIGA_MAC_VER_27, - RTL_GIGA_MAC_VER_28, - RTL_GIGA_MAC_VER_29, - RTL_GIGA_MAC_VER_30, - RTL_GIGA_MAC_VER_31, - RTL_GIGA_MAC_VER_32, - RTL_GIGA_MAC_VER_33, - RTL_GIGA_MAC_VER_34, - RTL_GIGA_MAC_VER_35, - RTL_GIGA_MAC_VER_36, - RTL_GIGA_MAC_VER_37, - RTL_GIGA_MAC_VER_38, - RTL_GIGA_MAC_VER_39, - RTL_GIGA_MAC_VER_40, - RTL_GIGA_MAC_VER_41, - RTL_GIGA_MAC_VER_42, - RTL_GIGA_MAC_VER_43, - RTL_GIGA_MAC_VER_44, - RTL_GIGA_MAC_VER_45, - RTL_GIGA_MAC_VER_46, - RTL_GIGA_MAC_VER_47, - RTL_GIGA_MAC_VER_48, - RTL_GIGA_MAC_VER_49, - RTL_GIGA_MAC_VER_50, - RTL_GIGA_MAC_VER_51, - RTL_GIGA_MAC_NONE = 0xff, -}; - -enum rtl_tx_desc_version { - RTL_TD_0 = 0, - RTL_TD_1 = 1, -}; - -#define JUMBO_1K ETH_DATA_LEN -#define JUMBO_4K (4*1024 - ETH_HLEN - 2) -#define JUMBO_6K (6*1024 - ETH_HLEN - 2) -#define JUMBO_7K (7*1024 - ETH_HLEN - 2) -#define JUMBO_9K (9*1024 - ETH_HLEN - 2) - -#define _R(NAME,TD,FW,SZ,B) { \ - .name = NAME, \ - .txd_version = TD, \ - .fw_name = FW, \ - .jumbo_max = SZ, \ - .jumbo_tx_csum = B \ -} - -static const struct { - const char *name; - enum rtl_tx_desc_version txd_version; - const char *fw_name; - u16 jumbo_max; - bool jumbo_tx_csum; -} rtl_chip_infos[] = { - /* PCI devices. */ - [RTL_GIGA_MAC_VER_01] = - _R("RTL8169", RTL_TD_0, NULL, JUMBO_7K, true), - [RTL_GIGA_MAC_VER_02] = - _R("RTL8169s", RTL_TD_0, NULL, JUMBO_7K, true), - [RTL_GIGA_MAC_VER_03] = - _R("RTL8110s", RTL_TD_0, NULL, JUMBO_7K, true), - [RTL_GIGA_MAC_VER_04] = - _R("RTL8169sb/8110sb", RTL_TD_0, NULL, JUMBO_7K, true), - [RTL_GIGA_MAC_VER_05] = - _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true), - [RTL_GIGA_MAC_VER_06] = - _R("RTL8169sc/8110sc", RTL_TD_0, NULL, JUMBO_7K, true), - /* PCI-E devices. */ - [RTL_GIGA_MAC_VER_07] = - _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_08] = - _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_09] = - _R("RTL8102e", RTL_TD_1, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_10] = - _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_11] = - _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), - [RTL_GIGA_MAC_VER_12] = - _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), - [RTL_GIGA_MAC_VER_13] = - _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_14] = - _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_15] = - _R("RTL8100e", RTL_TD_0, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_16] = - _R("RTL8101e", RTL_TD_0, NULL, JUMBO_1K, true), - [RTL_GIGA_MAC_VER_17] = - _R("RTL8168b/8111b", RTL_TD_0, NULL, JUMBO_4K, false), - [RTL_GIGA_MAC_VER_18] = - _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_19] = - _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_20] = - _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_21] = - _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_22] = - _R("RTL8168c/8111c", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_23] = - _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_24] = - _R("RTL8168cp/8111cp", RTL_TD_1, NULL, JUMBO_6K, false), - [RTL_GIGA_MAC_VER_25] = - _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_1, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_26] = - _R("RTL8168d/8111d", RTL_TD_1, FIRMWARE_8168D_2, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_27] = - _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), - [RTL_GIGA_MAC_VER_28] = - _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), - [RTL_GIGA_MAC_VER_29] = - _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1, - JUMBO_1K, true), - [RTL_GIGA_MAC_VER_30] = - _R("RTL8105e", RTL_TD_1, FIRMWARE_8105E_1, - JUMBO_1K, true), - [RTL_GIGA_MAC_VER_31] = - _R("RTL8168dp/8111dp", RTL_TD_1, NULL, JUMBO_9K, false), - [RTL_GIGA_MAC_VER_32] = - _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_1, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_33] = - _R("RTL8168e/8111e", RTL_TD_1, FIRMWARE_8168E_2, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_34] = - _R("RTL8168evl/8111evl",RTL_TD_1, FIRMWARE_8168E_3, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_35] = - _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_1, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_36] = - _R("RTL8168f/8111f", RTL_TD_1, FIRMWARE_8168F_2, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_37] = - _R("RTL8402", RTL_TD_1, FIRMWARE_8402_1, - JUMBO_1K, true), - [RTL_GIGA_MAC_VER_38] = - _R("RTL8411", RTL_TD_1, FIRMWARE_8411_1, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_39] = - _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_1, - JUMBO_1K, true), - [RTL_GIGA_MAC_VER_40] = - _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_2, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_41] = - _R("RTL8168g/8111g", RTL_TD_1, NULL, JUMBO_9K, false), - [RTL_GIGA_MAC_VER_42] = - _R("RTL8168g/8111g", RTL_TD_1, FIRMWARE_8168G_3, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_43] = - _R("RTL8106e", RTL_TD_1, FIRMWARE_8106E_2, - JUMBO_1K, true), - [RTL_GIGA_MAC_VER_44] = - _R("RTL8411", RTL_TD_1, FIRMWARE_8411_2, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_45] = - _R("RTL8168h/8111h", RTL_TD_1, FIRMWARE_8168H_1, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_46] = - _R("RTL8168h/8111h", RTL_TD_1, FIRMWARE_8168H_2, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_47] = - _R("RTL8107e", RTL_TD_1, FIRMWARE_8107E_1, - JUMBO_1K, false), - [RTL_GIGA_MAC_VER_48] = - _R("RTL8107e", RTL_TD_1, FIRMWARE_8107E_2, - JUMBO_1K, false), - [RTL_GIGA_MAC_VER_49] = - _R("RTL8168ep/8111ep", RTL_TD_1, NULL, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_50] = - _R("RTL8168ep/8111ep", RTL_TD_1, NULL, - JUMBO_9K, false), - [RTL_GIGA_MAC_VER_51] = - _R("RTL8168ep/8111ep", RTL_TD_1, NULL, - JUMBO_9K, false), -}; -#undef _R - -enum cfg_version { - RTL_CFG_0 = 0x00, - RTL_CFG_1, - RTL_CFG_2 -}; - -static const struct pci_device_id rtl8169_pci_tbl[] = { - { PCI_VDEVICE(REALTEK, 0x2502), RTL_CFG_1 }, - { PCI_VDEVICE(REALTEK, 0x2600), RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8129), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8136), 0, 0, RTL_CFG_2 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8161), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8167), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8168), 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x8169), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_DLINK, 0x4300, - PCI_VENDOR_ID_DLINK, 0x4b10, 0, 0, RTL_CFG_1 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4300), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(PCI_VENDOR_ID_AT, 0xc107), 0, 0, RTL_CFG_0 }, - { PCI_DEVICE(0x16ec, 0x0116), 0, 0, RTL_CFG_0 }, - { PCI_VENDOR_ID_LINKSYS, 0x1032, - PCI_ANY_ID, 0x0024, 0, 0, RTL_CFG_0 }, - { 0x0001, 0x8168, - PCI_ANY_ID, 0x2410, 0, 0, RTL_CFG_2 }, - {0,}, -}; - -MODULE_DEVICE_TABLE(pci, rtl8169_pci_tbl); - -static int rx_buf_sz = 16383; -static int use_dac; -static struct { - u32 msg_enable; -} debug = { -1 }; - -enum rtl_registers { - MAC0 = 0, /* Ethernet hardware address. */ - MAC4 = 4, - MAR0 = 8, /* Multicast filter. */ - CounterAddrLow = 0x10, - CounterAddrHigh = 0x14, - TxDescStartAddrLow = 0x20, - TxDescStartAddrHigh = 0x24, - TxHDescStartAddrLow = 0x28, - TxHDescStartAddrHigh = 0x2c, - FLASH = 0x30, - ERSR = 0x36, - ChipCmd = 0x37, - TxPoll = 0x38, - IntrMask = 0x3c, - IntrStatus = 0x3e, - - TxConfig = 0x40, -#define TXCFG_AUTO_FIFO (1 << 7) /* 8111e-vl */ -#define TXCFG_EMPTY (1 << 11) /* 8111e-vl */ - - RxConfig = 0x44, -#define RX128_INT_EN (1 << 15) /* 8111c and later */ -#define RX_MULTI_EN (1 << 14) /* 8111c only */ -#define RXCFG_FIFO_SHIFT 13 - /* No threshold before first PCI xfer */ -#define RX_FIFO_THRESH (7 << RXCFG_FIFO_SHIFT) -#define RX_EARLY_OFF (1 << 11) -#define RXCFG_DMA_SHIFT 8 - /* Unlimited maximum PCI burst. */ -#define RX_DMA_BURST (7 << RXCFG_DMA_SHIFT) - - RxMissed = 0x4c, - Cfg9346 = 0x50, - Config0 = 0x51, - Config1 = 0x52, - Config2 = 0x53, -#define PME_SIGNAL (1 << 5) /* 8168c and later */ - - Config3 = 0x54, - Config4 = 0x55, - Config5 = 0x56, - MultiIntr = 0x5c, - PHYAR = 0x60, - PHYstatus = 0x6c, - RxMaxSize = 0xda, - CPlusCmd = 0xe0, - IntrMitigate = 0xe2, - RxDescAddrLow = 0xe4, - RxDescAddrHigh = 0xe8, - EarlyTxThres = 0xec, /* 8169. Unit of 32 bytes. */ - -#define NoEarlyTx 0x3f /* Max value : no early transmit. */ - - MaxTxPacketSize = 0xec, /* 8101/8168. Unit of 128 bytes. */ - -#define TxPacketMax (8064 >> 7) -#define EarlySize 0x27 - - FuncEvent = 0xf0, - FuncEventMask = 0xf4, - FuncPresetState = 0xf8, - IBCR0 = 0xf8, - IBCR2 = 0xf9, - IBIMR0 = 0xfa, - IBISR0 = 0xfb, - FuncForceEvent = 0xfc, -}; - -enum rtl8110_registers { - TBICSR = 0x64, - TBI_ANAR = 0x68, - TBI_LPAR = 0x6a, -}; - -enum rtl8168_8101_registers { - CSIDR = 0x64, - CSIAR = 0x68, -#define CSIAR_FLAG 0x80000000 -#define CSIAR_WRITE_CMD 0x80000000 -#define CSIAR_BYTE_ENABLE 0x0f -#define CSIAR_BYTE_ENABLE_SHIFT 12 -#define CSIAR_ADDR_MASK 0x0fff -#define CSIAR_FUNC_CARD 0x00000000 -#define CSIAR_FUNC_SDIO 0x00010000 -#define CSIAR_FUNC_NIC 0x00020000 -#define CSIAR_FUNC_NIC2 0x00010000 - PMCH = 0x6f, - EPHYAR = 0x80, -#define EPHYAR_FLAG 0x80000000 -#define EPHYAR_WRITE_CMD 0x80000000 -#define EPHYAR_REG_MASK 0x1f -#define EPHYAR_REG_SHIFT 16 -#define EPHYAR_DATA_MASK 0xffff - DLLPR = 0xd0, -#define PFM_EN (1 << 6) -#define TX_10M_PS_EN (1 << 7) - DBG_REG = 0xd1, -#define FIX_NAK_1 (1 << 4) -#define FIX_NAK_2 (1 << 3) - TWSI = 0xd2, - MCU = 0xd3, -#define NOW_IS_OOB (1 << 7) -#define TX_EMPTY (1 << 5) -#define RX_EMPTY (1 << 4) -#define RXTX_EMPTY (TX_EMPTY | RX_EMPTY) -#define EN_NDP (1 << 3) -#define EN_OOB_RESET (1 << 2) -#define LINK_LIST_RDY (1 << 1) - EFUSEAR = 0xdc, -#define EFUSEAR_FLAG 0x80000000 -#define EFUSEAR_WRITE_CMD 0x80000000 -#define EFUSEAR_READ_CMD 0x00000000 -#define EFUSEAR_REG_MASK 0x03ff -#define EFUSEAR_REG_SHIFT 8 -#define EFUSEAR_DATA_MASK 0xff - MISC_1 = 0xf2, -#define PFM_D3COLD_EN (1 << 6) -}; - -enum rtl8168_registers { - LED_FREQ = 0x1a, - EEE_LED = 0x1b, - ERIDR = 0x70, - ERIAR = 0x74, -#define ERIAR_FLAG 0x80000000 -#define ERIAR_WRITE_CMD 0x80000000 -#define ERIAR_READ_CMD 0x00000000 -#define ERIAR_ADDR_BYTE_ALIGN 4 -#define ERIAR_TYPE_SHIFT 16 -#define ERIAR_EXGMAC (0x00 << ERIAR_TYPE_SHIFT) -#define ERIAR_MSIX (0x01 << ERIAR_TYPE_SHIFT) -#define ERIAR_ASF (0x02 << ERIAR_TYPE_SHIFT) -#define ERIAR_OOB (0x02 << ERIAR_TYPE_SHIFT) -#define ERIAR_MASK_SHIFT 12 -#define ERIAR_MASK_0001 (0x1 << ERIAR_MASK_SHIFT) -#define ERIAR_MASK_0011 (0x3 << ERIAR_MASK_SHIFT) -#define ERIAR_MASK_0100 (0x4 << ERIAR_MASK_SHIFT) -#define ERIAR_MASK_0101 (0x5 << ERIAR_MASK_SHIFT) -#define ERIAR_MASK_1111 (0xf << ERIAR_MASK_SHIFT) - EPHY_RXER_NUM = 0x7c, - OCPDR = 0xb0, /* OCP GPHY access */ -#define OCPDR_WRITE_CMD 0x80000000 -#define OCPDR_READ_CMD 0x00000000 -#define OCPDR_REG_MASK 0x7f -#define OCPDR_GPHY_REG_SHIFT 16 -#define OCPDR_DATA_MASK 0xffff - OCPAR = 0xb4, -#define OCPAR_FLAG 0x80000000 -#define OCPAR_GPHY_WRITE_CMD 0x8000f060 -#define OCPAR_GPHY_READ_CMD 0x0000f060 - GPHY_OCP = 0xb8, - RDSAR1 = 0xd0, /* 8168c only. Undocumented on 8168dp */ - MISC = 0xf0, /* 8168e only. */ -#define TXPLA_RST (1 << 29) -#define DISABLE_LAN_EN (1 << 23) /* Enable GPIO pin */ -#define PWM_EN (1 << 22) -#define RXDV_GATED_EN (1 << 19) -#define EARLY_TALLY_EN (1 << 16) -}; - -enum rtl_register_content { - /* InterruptStatusBits */ - SYSErr = 0x8000, - PCSTimeout = 0x4000, - SWInt = 0x0100, - TxDescUnavail = 0x0080, - RxFIFOOver = 0x0040, - LinkChg = 0x0020, - RxOverflow = 0x0010, - TxErr = 0x0008, - TxOK = 0x0004, - RxErr = 0x0002, - RxOK = 0x0001, - - /* RxStatusDesc */ - RxBOVF = (1 << 24), - RxFOVF = (1 << 23), - RxRWT = (1 << 22), - RxRES = (1 << 21), - RxRUNT = (1 << 20), - RxCRC = (1 << 19), - - /* ChipCmdBits */ - StopReq = 0x80, - CmdReset = 0x10, - CmdRxEnb = 0x08, - CmdTxEnb = 0x04, - RxBufEmpty = 0x01, - - /* TXPoll register p.5 */ - HPQ = 0x80, /* Poll cmd on the high prio queue */ - NPQ = 0x40, /* Poll cmd on the low prio queue */ - FSWInt = 0x01, /* Forced software interrupt */ - - /* Cfg9346Bits */ - Cfg9346_Lock = 0x00, - Cfg9346_Unlock = 0xc0, - - /* rx_mode_bits */ - AcceptErr = 0x20, - AcceptRunt = 0x10, - AcceptBroadcast = 0x08, - AcceptMulticast = 0x04, - AcceptMyPhys = 0x02, - AcceptAllPhys = 0x01, -#define RX_CONFIG_ACCEPT_MASK 0x3f - - /* TxConfigBits */ - TxInterFrameGapShift = 24, - TxDMAShift = 8, /* DMA burst value (0-7) is shift this many bits */ - - /* Config1 register p.24 */ - LEDS1 = (1 << 7), - LEDS0 = (1 << 6), - Speed_down = (1 << 4), - MEMMAP = (1 << 3), - IOMAP = (1 << 2), - VPD = (1 << 1), - PMEnable = (1 << 0), /* Power Management Enable */ - - /* Config2 register p. 25 */ - ClkReqEn = (1 << 7), /* Clock Request Enable */ - MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */ - PCI_Clock_66MHz = 0x01, - PCI_Clock_33MHz = 0x00, - - /* Config3 register p.25 */ - MagicPacket = (1 << 5), /* Wake up when receives a Magic Packet */ - LinkUp = (1 << 4), /* Wake up when the cable connection is re-established */ - Jumbo_En0 = (1 << 2), /* 8168 only. Reserved in the 8168b */ - Rdy_to_L23 = (1 << 1), /* L23 Enable */ - Beacon_en = (1 << 0), /* 8168 only. Reserved in the 8168b */ - - /* Config4 register */ - Jumbo_En1 = (1 << 1), /* 8168 only. Reserved in the 8168b */ - - /* Config5 register p.27 */ - BWF = (1 << 6), /* Accept Broadcast wakeup frame */ - MWF = (1 << 5), /* Accept Multicast wakeup frame */ - UWF = (1 << 4), /* Accept Unicast wakeup frame */ - Spi_en = (1 << 3), - LanWake = (1 << 1), /* LanWake enable/disable */ - PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ - ASPM_en = (1 << 0), /* ASPM enable */ - - /* TBICSR p.28 */ - TBIReset = 0x80000000, - TBILoopback = 0x40000000, - TBINwEnable = 0x20000000, - TBINwRestart = 0x10000000, - TBILinkOk = 0x02000000, - TBINwComplete = 0x01000000, - - /* CPlusCmd p.31 */ - EnableBist = (1 << 15), // 8168 8101 - Mac_dbgo_oe = (1 << 14), // 8168 8101 - Normal_mode = (1 << 13), // unused - Force_half_dup = (1 << 12), // 8168 8101 - Force_rxflow_en = (1 << 11), // 8168 8101 - Force_txflow_en = (1 << 10), // 8168 8101 - Cxpl_dbg_sel = (1 << 9), // 8168 8101 - ASF = (1 << 8), // 8168 8101 - PktCntrDisable = (1 << 7), // 8168 8101 - Mac_dbgo_sel = 0x001c, // 8168 - RxVlan = (1 << 6), - RxChkSum = (1 << 5), - PCIDAC = (1 << 4), - PCIMulRW = (1 << 3), - INTT_0 = 0x0000, // 8168 - INTT_1 = 0x0001, // 8168 - INTT_2 = 0x0002, // 8168 - INTT_3 = 0x0003, // 8168 - - /* rtl8169_PHYstatus */ - TBI_Enable = 0x80, - TxFlowCtrl = 0x40, - RxFlowCtrl = 0x20, - _1000bpsF = 0x10, - _100bps = 0x08, - _10bps = 0x04, - LinkStatus = 0x02, - FullDup = 0x01, - - /* _TBICSRBit */ - TBILinkOK = 0x02000000, - - /* ResetCounterCommand */ - CounterReset = 0x1, - - /* DumpCounterCommand */ - CounterDump = 0x8, - - /* magic enable v2 */ - MagicPacket_v2 = (1 << 16), /* Wake up when receives a Magic Packet */ -}; - -enum rtl_desc_bit { - /* First doubleword. */ - DescOwn = (1 << 31), /* Descriptor is owned by NIC */ - RingEnd = (1 << 30), /* End of descriptor ring */ - FirstFrag = (1 << 29), /* First segment of a packet */ - LastFrag = (1 << 28), /* Final segment of a packet */ -}; - -/* Generic case. */ -enum rtl_tx_desc_bit { - /* First doubleword. */ - TD_LSO = (1 << 27), /* Large Send Offload */ -#define TD_MSS_MAX 0x07ffu /* MSS value */ - - /* Second doubleword. */ - TxVlanTag = (1 << 17), /* Add VLAN tag */ -}; - -/* 8169, 8168b and 810x except 8102e. */ -enum rtl_tx_desc_bit_0 { - /* First doubleword. */ -#define TD0_MSS_SHIFT 16 /* MSS position (11 bits) */ - TD0_TCP_CS = (1 << 16), /* Calculate TCP/IP checksum */ - TD0_UDP_CS = (1 << 17), /* Calculate UDP/IP checksum */ - TD0_IP_CS = (1 << 18), /* Calculate IP checksum */ -}; - -/* 8102e, 8168c and beyond. */ -enum rtl_tx_desc_bit_1 { - /* First doubleword. */ - TD1_GTSENV4 = (1 << 26), /* Giant Send for IPv4 */ - TD1_GTSENV6 = (1 << 25), /* Giant Send for IPv6 */ -#define GTTCPHO_SHIFT 18 -#define GTTCPHO_MAX 0x7fU - - /* Second doubleword. */ -#define TCPHO_SHIFT 18 -#define TCPHO_MAX 0x3ffU -#define TD1_MSS_SHIFT 18 /* MSS position (11 bits) */ - TD1_IPv6_CS = (1 << 28), /* Calculate IPv6 checksum */ - TD1_IPv4_CS = (1 << 29), /* Calculate IPv4 checksum */ - TD1_TCP_CS = (1 << 30), /* Calculate TCP/IP checksum */ - TD1_UDP_CS = (1 << 31), /* Calculate UDP/IP checksum */ -}; - -enum rtl_rx_desc_bit { - /* Rx private */ - PID1 = (1 << 18), /* Protocol ID bit 1/2 */ - PID0 = (1 << 17), /* Protocol ID bit 2/2 */ - -#define RxProtoUDP (PID1) -#define RxProtoTCP (PID0) -#define RxProtoIP (PID1 | PID0) -#define RxProtoMask RxProtoIP - - IPFail = (1 << 16), /* IP checksum failed */ - UDPFail = (1 << 15), /* UDP/IP checksum failed */ - TCPFail = (1 << 14), /* TCP/IP checksum failed */ - RxVlanTag = (1 << 16), /* VLAN tag available */ -}; - -#define RsvdMask 0x3fffc000 - -struct TxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct RxDesc { - __le32 opts1; - __le32 opts2; - __le64 addr; -}; - -struct ring_info { - struct sk_buff *skb; - u32 len; - u8 __pad[sizeof(void *) - sizeof(u32)]; -}; - -enum features { - RTL_FEATURE_WOL = (1 << 0), - RTL_FEATURE_MSI = (1 << 1), - RTL_FEATURE_GMII = (1 << 2), -}; - -struct rtl8169_counters { - __le64 tx_packets; - __le64 rx_packets; - __le64 tx_errors; - __le32 rx_errors; - __le16 rx_missed; - __le16 align_errors; - __le32 tx_one_collision; - __le32 tx_multi_collision; - __le64 rx_unicast; - __le64 rx_broadcast; - __le32 rx_multicast; - __le16 tx_aborted; - __le16 tx_underun; -}; - -struct rtl8169_tc_offsets { - bool inited; - __le64 tx_errors; - __le32 tx_multi_collision; - __le16 tx_aborted; -}; - -enum rtl_flag { - RTL_FLAG_TASK_ENABLED = 0, - RTL_FLAG_TASK_SLOW_PENDING, - RTL_FLAG_TASK_RESET_PENDING, - RTL_FLAG_TASK_PHY_PENDING, - RTL_FLAG_MAX -}; - -struct rtl8169_stats { - u64 packets; - u64 bytes; - struct u64_stats_sync syncp; -}; - -struct rtl8169_private { - void __iomem *mmio_addr; /* memory map physical address */ - struct pci_dev *pci_dev; - struct net_device *dev; - struct napi_struct napi; - u32 msg_enable; - u16 txd_version; - u16 mac_version; - u32 cur_rx; /* Index into the Rx descriptor buffer of next Rx pkt. */ - u32 cur_tx; /* Index into the Tx descriptor buffer of next Rx pkt. */ - u32 dirty_tx; - struct rtl8169_stats rx_stats; - struct rtl8169_stats tx_stats; - struct TxDesc *TxDescArray; /* 256-aligned Tx descriptor ring */ - struct RxDesc *RxDescArray; /* 256-aligned Rx descriptor ring */ - dma_addr_t TxPhyAddr; - dma_addr_t RxPhyAddr; - void *Rx_databuff[NUM_RX_DESC]; /* Rx data buffers */ - struct ring_info tx_skb[NUM_TX_DESC]; /* Tx data buffers */ - struct timer_list timer; - u16 cp_cmd; - - u16 event_slow; - - struct mdio_ops { - void (*write)(struct rtl8169_private *, int, int); - int (*read)(struct rtl8169_private *, int); - } mdio_ops; - - struct pll_power_ops { - void (*down)(struct rtl8169_private *); - void (*up)(struct rtl8169_private *); - } pll_power_ops; - - struct jumbo_ops { - void (*enable)(struct rtl8169_private *); - void (*disable)(struct rtl8169_private *); - } jumbo_ops; - - struct csi_ops { - void (*write)(struct rtl8169_private *, int, int); - u32 (*read)(struct rtl8169_private *, int); - } csi_ops; - - int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv); - int (*get_settings)(struct net_device *, struct ethtool_cmd *); - void (*phy_reset_enable)(struct rtl8169_private *tp); - void (*hw_start)(struct net_device *); - unsigned int (*phy_reset_pending)(struct rtl8169_private *tp); - unsigned int (*link_ok)(void __iomem *); - int (*do_ioctl)(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd); - bool (*tso_csum)(struct rtl8169_private *, struct sk_buff *, u32 *); - - struct { - DECLARE_BITMAP(flags, RTL_FLAG_MAX); - struct mutex mutex; - struct work_struct work; - } wk; - - unsigned features; - - struct mii_if_info mii; - dma_addr_t counters_phys_addr; - struct rtl8169_counters *counters; - struct rtl8169_tc_offsets tc_offset; - u32 saved_wolopts; - u32 opts1_mask; - - struct rtl_fw { - const struct firmware *fw; - -#define RTL_VER_SIZE 32 - - char version[RTL_VER_SIZE]; - - struct rtl_fw_phy_action { - __le32 *code; - size_t size; - } phy_action; - } *rtl_fw; -#define RTL_FIRMWARE_UNKNOWN ERR_PTR(-EAGAIN) - - u32 ocp_base; -}; - -MODULE_AUTHOR("Realtek and the Linux r8169 crew "); -MODULE_DESCRIPTION("RealTek RTL-8169 Gigabit Ethernet driver"); -module_param(use_dac, int, 0); -MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot."); -module_param_named(debug, debug.msg_enable, int, 0); -MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(RTL8169_VERSION); -MODULE_FIRMWARE(FIRMWARE_8168D_1); -MODULE_FIRMWARE(FIRMWARE_8168D_2); -MODULE_FIRMWARE(FIRMWARE_8168E_1); -MODULE_FIRMWARE(FIRMWARE_8168E_2); -MODULE_FIRMWARE(FIRMWARE_8168E_3); -MODULE_FIRMWARE(FIRMWARE_8105E_1); -MODULE_FIRMWARE(FIRMWARE_8168F_1); -MODULE_FIRMWARE(FIRMWARE_8168F_2); -MODULE_FIRMWARE(FIRMWARE_8402_1); -MODULE_FIRMWARE(FIRMWARE_8411_1); -MODULE_FIRMWARE(FIRMWARE_8411_2); -MODULE_FIRMWARE(FIRMWARE_8106E_1); -MODULE_FIRMWARE(FIRMWARE_8106E_2); -MODULE_FIRMWARE(FIRMWARE_8168G_2); -MODULE_FIRMWARE(FIRMWARE_8168G_3); -MODULE_FIRMWARE(FIRMWARE_8168H_1); -MODULE_FIRMWARE(FIRMWARE_8168H_2); -MODULE_FIRMWARE(FIRMWARE_8107E_1); -MODULE_FIRMWARE(FIRMWARE_8107E_2); - -static void rtl_lock_work(struct rtl8169_private *tp) -{ - mutex_lock(&tp->wk.mutex); -} - -static void rtl_unlock_work(struct rtl8169_private *tp) -{ - mutex_unlock(&tp->wk.mutex); -} - -static void rtl_tx_performance_tweak(struct pci_dev *pdev, u16 force) -{ - pcie_capability_clear_and_set_word(pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_READRQ, force); -} - -struct rtl_cond { - bool (*check)(struct rtl8169_private *); - const char *msg; -}; - -static void rtl_udelay(unsigned int d) -{ - udelay(d); -} - -static bool rtl_loop_wait(struct rtl8169_private *tp, const struct rtl_cond *c, - void (*delay)(unsigned int), unsigned int d, int n, - bool high) -{ - int i; - - for (i = 0; i < n; i++) { - delay(d); - if (c->check(tp) == high) - return true; - } - netif_err(tp, drv, tp->dev, "%s == %d (loop: %d, delay: %d).\n", - c->msg, !high, n, d); - return false; -} - -static bool rtl_udelay_loop_wait_high(struct rtl8169_private *tp, - const struct rtl_cond *c, - unsigned int d, int n) -{ - return rtl_loop_wait(tp, c, rtl_udelay, d, n, true); -} - -static bool rtl_udelay_loop_wait_low(struct rtl8169_private *tp, - const struct rtl_cond *c, - unsigned int d, int n) -{ - return rtl_loop_wait(tp, c, rtl_udelay, d, n, false); -} - -static bool rtl_msleep_loop_wait_high(struct rtl8169_private *tp, - const struct rtl_cond *c, - unsigned int d, int n) -{ - return rtl_loop_wait(tp, c, msleep, d, n, true); -} - -static bool rtl_msleep_loop_wait_low(struct rtl8169_private *tp, - const struct rtl_cond *c, - unsigned int d, int n) -{ - return rtl_loop_wait(tp, c, msleep, d, n, false); -} - -#define DECLARE_RTL_COND(name) \ -static bool name ## _check(struct rtl8169_private *); \ - \ -static const struct rtl_cond name = { \ - .check = name ## _check, \ - .msg = #name \ -}; \ - \ -static bool name ## _check(struct rtl8169_private *tp) - -static bool rtl_ocp_reg_failure(struct rtl8169_private *tp, u32 reg) -{ - if (reg & 0xffff0001) { - netif_err(tp, drv, tp->dev, "Invalid ocp reg %x!\n", reg); - return true; - } - return false; -} - -DECLARE_RTL_COND(rtl_ocp_gphy_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(GPHY_OCP) & OCPAR_FLAG; -} - -static void r8168_phy_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_ocp_reg_failure(tp, reg)) - return; - - RTL_W32(GPHY_OCP, OCPAR_FLAG | (reg << 15) | data); - - rtl_udelay_loop_wait_low(tp, &rtl_ocp_gphy_cond, 25, 10); -} - -static u16 r8168_phy_ocp_read(struct rtl8169_private *tp, u32 reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_ocp_reg_failure(tp, reg)) - return 0; - - RTL_W32(GPHY_OCP, reg << 15); - - return rtl_udelay_loop_wait_high(tp, &rtl_ocp_gphy_cond, 25, 10) ? - (RTL_R32(GPHY_OCP) & 0xffff) : ~0; -} - -static void r8168_mac_ocp_write(struct rtl8169_private *tp, u32 reg, u32 data) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_ocp_reg_failure(tp, reg)) - return; - - RTL_W32(OCPDR, OCPAR_FLAG | (reg << 15) | data); -} - -static u16 r8168_mac_ocp_read(struct rtl8169_private *tp, u32 reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_ocp_reg_failure(tp, reg)) - return 0; - - RTL_W32(OCPDR, reg << 15); - - return RTL_R32(OCPDR); -} - -#define OCP_STD_PHY_BASE 0xa400 - -static void r8168g_mdio_write(struct rtl8169_private *tp, int reg, int value) -{ - if (reg == 0x1f) { - tp->ocp_base = value ? value << 4 : OCP_STD_PHY_BASE; - return; - } - - if (tp->ocp_base != OCP_STD_PHY_BASE) - reg -= 0x10; - - r8168_phy_ocp_write(tp, tp->ocp_base + reg * 2, value); -} - -static int r8168g_mdio_read(struct rtl8169_private *tp, int reg) -{ - if (tp->ocp_base != OCP_STD_PHY_BASE) - reg -= 0x10; - - return r8168_phy_ocp_read(tp, tp->ocp_base + reg * 2); -} - -static void mac_mcu_write(struct rtl8169_private *tp, int reg, int value) -{ - if (reg == 0x1f) { - tp->ocp_base = value << 4; - return; - } - - r8168_mac_ocp_write(tp, tp->ocp_base + reg, value); -} - -static int mac_mcu_read(struct rtl8169_private *tp, int reg) -{ - return r8168_mac_ocp_read(tp, tp->ocp_base + reg); -} - -DECLARE_RTL_COND(rtl_phyar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(PHYAR) & 0x80000000; -} - -static void r8169_mdio_write(struct rtl8169_private *tp, int reg, int value) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(PHYAR, 0x80000000 | (reg & 0x1f) << 16 | (value & 0xffff)); - - rtl_udelay_loop_wait_low(tp, &rtl_phyar_cond, 25, 20); - /* - * According to hardware specs a 20us delay is required after write - * complete indication, but before sending next command. - */ - udelay(20); -} - -static int r8169_mdio_read(struct rtl8169_private *tp, int reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - int value; - - RTL_W32(PHYAR, 0x0 | (reg & 0x1f) << 16); - - value = rtl_udelay_loop_wait_high(tp, &rtl_phyar_cond, 25, 20) ? - RTL_R32(PHYAR) & 0xffff : ~0; - - /* - * According to hardware specs a 20us delay is required after read - * complete indication, but before sending next command. - */ - udelay(20); - - return value; -} - -DECLARE_RTL_COND(rtl_ocpar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(OCPAR) & OCPAR_FLAG; -} - -static void r8168dp_1_mdio_access(struct rtl8169_private *tp, int reg, u32 data) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(OCPDR, data | ((reg & OCPDR_REG_MASK) << OCPDR_GPHY_REG_SHIFT)); - RTL_W32(OCPAR, OCPAR_GPHY_WRITE_CMD); - RTL_W32(EPHY_RXER_NUM, 0); - - rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 1000, 100); -} - -static void r8168dp_1_mdio_write(struct rtl8169_private *tp, int reg, int value) -{ - r8168dp_1_mdio_access(tp, reg, - OCPDR_WRITE_CMD | (value & OCPDR_DATA_MASK)); -} - -static int r8168dp_1_mdio_read(struct rtl8169_private *tp, int reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - - r8168dp_1_mdio_access(tp, reg, OCPDR_READ_CMD); - - mdelay(1); - RTL_W32(OCPAR, OCPAR_GPHY_READ_CMD); - RTL_W32(EPHY_RXER_NUM, 0); - - return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 1000, 100) ? - RTL_R32(OCPDR) & OCPDR_DATA_MASK : ~0; -} - -#define R8168DP_1_MDIO_ACCESS_BIT 0x00020000 - -static void r8168dp_2_mdio_start(void __iomem *ioaddr) -{ - RTL_W32(0xd0, RTL_R32(0xd0) & ~R8168DP_1_MDIO_ACCESS_BIT); -} - -static void r8168dp_2_mdio_stop(void __iomem *ioaddr) -{ - RTL_W32(0xd0, RTL_R32(0xd0) | R8168DP_1_MDIO_ACCESS_BIT); -} - -static void r8168dp_2_mdio_write(struct rtl8169_private *tp, int reg, int value) -{ - void __iomem *ioaddr = tp->mmio_addr; - - r8168dp_2_mdio_start(ioaddr); - - r8169_mdio_write(tp, reg, value); - - r8168dp_2_mdio_stop(ioaddr); -} - -static int r8168dp_2_mdio_read(struct rtl8169_private *tp, int reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - int value; - - r8168dp_2_mdio_start(ioaddr); - - value = r8169_mdio_read(tp, reg); - - r8168dp_2_mdio_stop(ioaddr); - - return value; -} - -static void rtl_writephy(struct rtl8169_private *tp, int location, u32 val) -{ - tp->mdio_ops.write(tp, location, val); -} - -static int rtl_readphy(struct rtl8169_private *tp, int location) -{ - return tp->mdio_ops.read(tp, location); -} - -static void rtl_patchphy(struct rtl8169_private *tp, int reg_addr, int value) -{ - rtl_writephy(tp, reg_addr, rtl_readphy(tp, reg_addr) | value); -} - -static void rtl_w0w1_phy(struct rtl8169_private *tp, int reg_addr, int p, int m) -{ - int val; - - val = rtl_readphy(tp, reg_addr); - rtl_writephy(tp, reg_addr, (val & ~m) | p); -} - -static void rtl_mdio_write(struct net_device *dev, int phy_id, int location, - int val) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl_writephy(tp, location, val); -} - -static int rtl_mdio_read(struct net_device *dev, int phy_id, int location) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return rtl_readphy(tp, location); -} - -DECLARE_RTL_COND(rtl_ephyar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(EPHYAR) & EPHYAR_FLAG; -} - -static void rtl_ephy_write(struct rtl8169_private *tp, int reg_addr, int value) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(EPHYAR, EPHYAR_WRITE_CMD | (value & EPHYAR_DATA_MASK) | - (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - rtl_udelay_loop_wait_low(tp, &rtl_ephyar_cond, 10, 100); - - udelay(10); -} - -static u16 rtl_ephy_read(struct rtl8169_private *tp, int reg_addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(EPHYAR, (reg_addr & EPHYAR_REG_MASK) << EPHYAR_REG_SHIFT); - - return rtl_udelay_loop_wait_high(tp, &rtl_ephyar_cond, 10, 100) ? - RTL_R32(EPHYAR) & EPHYAR_DATA_MASK : ~0; -} - -DECLARE_RTL_COND(rtl_eriar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(ERIAR) & ERIAR_FLAG; -} - -static void rtl_eri_write(struct rtl8169_private *tp, int addr, u32 mask, - u32 val, int type) -{ - void __iomem *ioaddr = tp->mmio_addr; - - BUG_ON((addr & 3) || (mask == 0)); - RTL_W32(ERIDR, val); - RTL_W32(ERIAR, ERIAR_WRITE_CMD | type | mask | addr); - - rtl_udelay_loop_wait_low(tp, &rtl_eriar_cond, 100, 100); -} - -static u32 rtl_eri_read(struct rtl8169_private *tp, int addr, int type) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(ERIAR, ERIAR_READ_CMD | type | ERIAR_MASK_1111 | addr); - - return rtl_udelay_loop_wait_high(tp, &rtl_eriar_cond, 100, 100) ? - RTL_R32(ERIDR) : ~0; -} - -static void rtl_w0w1_eri(struct rtl8169_private *tp, int addr, u32 mask, u32 p, - u32 m, int type) -{ - u32 val; - - val = rtl_eri_read(tp, addr, type); - rtl_eri_write(tp, addr, mask, (val & ~m) | p, type); -} - -static u32 r8168dp_ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(OCPAR, ((u32)mask & 0x0f) << 12 | (reg & 0x0fff)); - return rtl_udelay_loop_wait_high(tp, &rtl_ocpar_cond, 100, 20) ? - RTL_R32(OCPDR) : ~0; -} - -static u32 r8168ep_ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg) -{ - return rtl_eri_read(tp, reg, ERIAR_OOB); -} - -static u32 ocp_read(struct rtl8169_private *tp, u8 mask, u16 reg) -{ - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - return r8168dp_ocp_read(tp, mask, reg); - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - return r8168ep_ocp_read(tp, mask, reg); - default: - BUG(); - return ~0; - } -} - -static void r8168dp_ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, - u32 data) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(OCPDR, data); - RTL_W32(OCPAR, OCPAR_FLAG | ((u32)mask & 0x0f) << 12 | (reg & 0x0fff)); - rtl_udelay_loop_wait_low(tp, &rtl_ocpar_cond, 100, 20); -} - -static void r8168ep_ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, - u32 data) -{ - rtl_eri_write(tp, reg, ((u32)mask & 0x0f) << ERIAR_MASK_SHIFT, - data, ERIAR_OOB); -} - -static void ocp_write(struct rtl8169_private *tp, u8 mask, u16 reg, u32 data) -{ - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - r8168dp_ocp_write(tp, mask, reg, data); - break; - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - r8168ep_ocp_write(tp, mask, reg, data); - break; - default: - BUG(); - break; - } -} - -static void rtl8168_oob_notify(struct rtl8169_private *tp, u8 cmd) -{ - rtl_eri_write(tp, 0xe8, ERIAR_MASK_0001, cmd, ERIAR_EXGMAC); - - ocp_write(tp, 0x1, 0x30, 0x00000001); -} - -#define OOB_CMD_RESET 0x00 -#define OOB_CMD_DRIVER_START 0x05 -#define OOB_CMD_DRIVER_STOP 0x06 - -static u16 rtl8168_get_ocp_reg(struct rtl8169_private *tp) -{ - return (tp->mac_version == RTL_GIGA_MAC_VER_31) ? 0xb8 : 0x10; -} - -DECLARE_RTL_COND(rtl_ocp_read_cond) -{ - u16 reg; - - reg = rtl8168_get_ocp_reg(tp); - - return ocp_read(tp, 0x0f, reg) & 0x00000800; -} - -DECLARE_RTL_COND(rtl_ep_ocp_read_cond) -{ - return ocp_read(tp, 0x0f, 0x124) & 0x00000001; -} - -DECLARE_RTL_COND(rtl_ocp_tx_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R8(IBISR0) & 0x20; -} - -static void rtl8168ep_stop_cmac(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(IBCR2, RTL_R8(IBCR2) & ~0x01); - rtl_msleep_loop_wait_high(tp, &rtl_ocp_tx_cond, 50, 2000); - RTL_W8(IBISR0, RTL_R8(IBISR0) | 0x20); - RTL_W8(IBCR0, RTL_R8(IBCR0) & ~0x01); -} - -static void rtl8168dp_driver_start(struct rtl8169_private *tp) -{ - rtl8168_oob_notify(tp, OOB_CMD_DRIVER_START); - rtl_msleep_loop_wait_high(tp, &rtl_ocp_read_cond, 10, 10); -} - -static void rtl8168ep_driver_start(struct rtl8169_private *tp) -{ - ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_START); - ocp_write(tp, 0x01, 0x30, ocp_read(tp, 0x01, 0x30) | 0x01); - rtl_msleep_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10, 10); -} - -static void rtl8168_driver_start(struct rtl8169_private *tp) -{ - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - rtl8168dp_driver_start(tp); - break; - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - rtl8168ep_driver_start(tp); - break; - default: - BUG(); - break; - } -} - -static void rtl8168dp_driver_stop(struct rtl8169_private *tp) -{ - rtl8168_oob_notify(tp, OOB_CMD_DRIVER_STOP); - rtl_msleep_loop_wait_low(tp, &rtl_ocp_read_cond, 10, 10); -} - -static void rtl8168ep_driver_stop(struct rtl8169_private *tp) -{ - rtl8168ep_stop_cmac(tp); - ocp_write(tp, 0x01, 0x180, OOB_CMD_DRIVER_STOP); - ocp_write(tp, 0x01, 0x30, ocp_read(tp, 0x01, 0x30) | 0x01); - rtl_msleep_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10, 10); -} - -static void rtl8168_driver_stop(struct rtl8169_private *tp) -{ - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - rtl8168dp_driver_stop(tp); - break; - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - rtl8168ep_driver_stop(tp); - break; - default: - BUG(); - break; - } -} - -static int r8168dp_check_dash(struct rtl8169_private *tp) -{ - u16 reg = rtl8168_get_ocp_reg(tp); - - return (ocp_read(tp, 0x0f, reg) & 0x00008000) ? 1 : 0; -} - -static int r8168ep_check_dash(struct rtl8169_private *tp) -{ - return (ocp_read(tp, 0x0f, 0x128) & 0x00000001) ? 1 : 0; -} - -static int r8168_check_dash(struct rtl8169_private *tp) -{ - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - return r8168dp_check_dash(tp); - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - return r8168ep_check_dash(tp); - default: - return 0; - } -} - -struct exgmac_reg { - u16 addr; - u16 mask; - u32 val; -}; - -static void rtl_write_exgmac_batch(struct rtl8169_private *tp, - const struct exgmac_reg *r, int len) -{ - while (len-- > 0) { - rtl_eri_write(tp, r->addr, r->mask, r->val, ERIAR_EXGMAC); - r++; - } -} - -DECLARE_RTL_COND(rtl_efusear_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(EFUSEAR) & EFUSEAR_FLAG; -} - -static u8 rtl8168d_efuse_read(struct rtl8169_private *tp, int reg_addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(EFUSEAR, (reg_addr & EFUSEAR_REG_MASK) << EFUSEAR_REG_SHIFT); - - return rtl_udelay_loop_wait_high(tp, &rtl_efusear_cond, 100, 300) ? - RTL_R32(EFUSEAR) & EFUSEAR_DATA_MASK : ~0; -} - -static u16 rtl_get_events(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R16(IntrStatus); -} - -static void rtl_ack_events(struct rtl8169_private *tp, u16 bits) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W16(IntrStatus, bits); - mmiowb(); -} - -static void rtl_irq_disable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W16(IntrMask, 0); - mmiowb(); -} - -static void rtl_irq_enable(struct rtl8169_private *tp, u16 bits) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W16(IntrMask, bits); -} - -#define RTL_EVENT_NAPI_RX (RxOK | RxErr) -#define RTL_EVENT_NAPI_TX (TxOK | TxErr) -#define RTL_EVENT_NAPI (RTL_EVENT_NAPI_RX | RTL_EVENT_NAPI_TX) - -static void rtl_irq_enable_all(struct rtl8169_private *tp) -{ - rtl_irq_enable(tp, RTL_EVENT_NAPI | tp->event_slow); -} - -static void rtl8169_irq_mask_and_ack(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_irq_disable(tp); - rtl_ack_events(tp, RTL_EVENT_NAPI | tp->event_slow); - RTL_R8(ChipCmd); -} - -static unsigned int rtl8169_tbi_reset_pending(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(TBICSR) & TBIReset; -} - -static unsigned int rtl8169_xmii_reset_pending(struct rtl8169_private *tp) -{ - return rtl_readphy(tp, MII_BMCR) & BMCR_RESET; -} - -static unsigned int rtl8169_tbi_link_ok(void __iomem *ioaddr) -{ - return RTL_R32(TBICSR) & TBILinkOk; -} - -static unsigned int rtl8169_xmii_link_ok(void __iomem *ioaddr) -{ - return RTL_R8(PHYstatus) & LinkStatus; -} - -static void rtl8169_tbi_reset_enable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(TBICSR, RTL_R32(TBICSR) | TBIReset); -} - -static void rtl8169_xmii_reset_enable(struct rtl8169_private *tp) -{ - unsigned int val; - - val = rtl_readphy(tp, MII_BMCR) | BMCR_RESET; - rtl_writephy(tp, MII_BMCR, val & 0xffff); -} - -static void rtl_link_chg_patch(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct net_device *dev = tp->dev; - - if (!netif_running(dev)) - return; - - if (tp->mac_version == RTL_GIGA_MAC_VER_34 || - tp->mac_version == RTL_GIGA_MAC_VER_38) { - if (RTL_R8(PHYstatus) & _1000bpsF) { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005, - ERIAR_EXGMAC); - } else if (RTL_R8(PHYstatus) & _100bps) { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005, - ERIAR_EXGMAC); - } else { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f, - ERIAR_EXGMAC); - } - /* Reset packet filter */ - rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, - ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, - ERIAR_EXGMAC); - } else if (tp->mac_version == RTL_GIGA_MAC_VER_35 || - tp->mac_version == RTL_GIGA_MAC_VER_36) { - if (RTL_R8(PHYstatus) & _1000bpsF) { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x00000011, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x00000005, - ERIAR_EXGMAC); - } else { - rtl_eri_write(tp, 0x1bc, ERIAR_MASK_1111, 0x0000001f, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_1111, 0x0000003f, - ERIAR_EXGMAC); - } - } else if (tp->mac_version == RTL_GIGA_MAC_VER_37) { - if (RTL_R8(PHYstatus) & _10bps) { - rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x4d02, - ERIAR_EXGMAC); - rtl_eri_write(tp, 0x1dc, ERIAR_MASK_0011, 0x0060, - ERIAR_EXGMAC); - } else { - rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, - ERIAR_EXGMAC); - } - } -} - -static void __rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr, bool pm) -{ - if (tp->link_ok(ioaddr)) { - rtl_link_chg_patch(tp); - /* This is to cancel a scheduled suspend if there's one. */ - if (pm) - pm_request_resume(&tp->pci_dev->dev); - netif_carrier_on(dev); - if (net_ratelimit()) - netif_info(tp, ifup, dev, "link up\n"); - } else { - netif_carrier_off(dev); - netif_info(tp, ifdown, dev, "link down\n"); - if (pm) - pm_schedule_suspend(&tp->pci_dev->dev, 5000); - } -} - -static void rtl8169_check_link_status(struct net_device *dev, - struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - __rtl8169_check_link_status(dev, tp, ioaddr, false); -} - -#define WAKE_ANY (WAKE_PHY | WAKE_MAGIC | WAKE_UCAST | WAKE_BCAST | WAKE_MCAST) - -static u32 __rtl8169_get_wol(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u8 options; - u32 wolopts = 0; - - options = RTL_R8(Config1); - if (!(options & PMEnable)) - return 0; - - options = RTL_R8(Config3); - if (options & LinkUp) - wolopts |= WAKE_PHY; - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_35: - case RTL_GIGA_MAC_VER_36: - case RTL_GIGA_MAC_VER_37: - case RTL_GIGA_MAC_VER_38: - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - case RTL_GIGA_MAC_VER_44: - case RTL_GIGA_MAC_VER_45: - case RTL_GIGA_MAC_VER_46: - case RTL_GIGA_MAC_VER_47: - case RTL_GIGA_MAC_VER_48: - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - if (rtl_eri_read(tp, 0xdc, ERIAR_EXGMAC) & MagicPacket_v2) - wolopts |= WAKE_MAGIC; - break; - default: - if (options & MagicPacket) - wolopts |= WAKE_MAGIC; - break; - } - - options = RTL_R8(Config5); - if (options & UWF) - wolopts |= WAKE_UCAST; - if (options & BWF) - wolopts |= WAKE_BCAST; - if (options & MWF) - wolopts |= WAKE_MCAST; - - return wolopts; -} - -static void rtl8169_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl_lock_work(tp); - - wol->supported = WAKE_ANY; - wol->wolopts = __rtl8169_get_wol(tp); - - rtl_unlock_work(tp); -} - -static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned int i, tmp; - static const struct { - u32 opt; - u16 reg; - u8 mask; - } cfg[] = { - { WAKE_PHY, Config3, LinkUp }, - { WAKE_UCAST, Config5, UWF }, - { WAKE_BCAST, Config5, BWF }, - { WAKE_MCAST, Config5, MWF }, - { WAKE_ANY, Config5, LanWake }, - { WAKE_MAGIC, Config3, MagicPacket } - }; - u8 options; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_35: - case RTL_GIGA_MAC_VER_36: - case RTL_GIGA_MAC_VER_37: - case RTL_GIGA_MAC_VER_38: - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - case RTL_GIGA_MAC_VER_44: - case RTL_GIGA_MAC_VER_45: - case RTL_GIGA_MAC_VER_46: - case RTL_GIGA_MAC_VER_47: - case RTL_GIGA_MAC_VER_48: - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - tmp = ARRAY_SIZE(cfg) - 1; - if (wolopts & WAKE_MAGIC) - rtl_w0w1_eri(tp, - 0x0dc, - ERIAR_MASK_0100, - MagicPacket_v2, - 0x0000, - ERIAR_EXGMAC); - else - rtl_w0w1_eri(tp, - 0x0dc, - ERIAR_MASK_0100, - 0x0000, - MagicPacket_v2, - ERIAR_EXGMAC); - break; - default: - tmp = ARRAY_SIZE(cfg); - break; - } - - for (i = 0; i < tmp; i++) { - options = RTL_R8(cfg[i].reg) & ~cfg[i].mask; - if (wolopts & cfg[i].opt) - options |= cfg[i].mask; - RTL_W8(cfg[i].reg, options); - } - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01 ... RTL_GIGA_MAC_VER_17: - options = RTL_R8(Config1) & ~PMEnable; - if (wolopts) - options |= PMEnable; - RTL_W8(Config1, options); - break; - default: - options = RTL_R8(Config2) & ~PME_SIGNAL; - if (wolopts) - options |= PME_SIGNAL; - RTL_W8(Config2, options); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Lock); -} - -static int rtl8169_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl_lock_work(tp); - - if (wol->wolopts) - tp->features |= RTL_FEATURE_WOL; - else - tp->features &= ~RTL_FEATURE_WOL; - __rtl8169_set_wol(tp, wol->wolopts); - - rtl_unlock_work(tp); - - device_set_wakeup_enable(&tp->pci_dev->dev, wol->wolopts); - - return 0; -} - -static const char *rtl_lookup_firmware_name(struct rtl8169_private *tp) -{ - return rtl_chip_infos[tp->mac_version].fw_name; -} - -static void rtl8169_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct rtl_fw *rtl_fw = tp->rtl_fw; - - strlcpy(info->driver, MODULENAME, sizeof(info->driver)); - strlcpy(info->version, RTL8169_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, pci_name(tp->pci_dev), sizeof(info->bus_info)); - BUILD_BUG_ON(sizeof(info->fw_version) < sizeof(rtl_fw->version)); - if (!IS_ERR_OR_NULL(rtl_fw)) - strlcpy(info->fw_version, rtl_fw->version, - sizeof(info->fw_version)); -} - -static int rtl8169_get_regs_len(struct net_device *dev) -{ - return R8169_REGS_SIZE; -} - -static int rtl8169_set_speed_tbi(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex, u32 ignored) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - int ret = 0; - u32 reg; - - reg = RTL_R32(TBICSR); - if ((autoneg == AUTONEG_DISABLE) && (speed == SPEED_1000) && - (duplex == DUPLEX_FULL)) { - RTL_W32(TBICSR, reg & ~(TBINwEnable | TBINwRestart)); - } else if (autoneg == AUTONEG_ENABLE) - RTL_W32(TBICSR, reg | TBINwEnable | TBINwRestart); - else { - netif_warn(tp, link, dev, - "incorrect speed setting refused in TBI mode\n"); - ret = -EOPNOTSUPP; - } - - return ret; -} - -static int rtl8169_set_speed_xmii(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex, u32 adv) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int giga_ctrl, bmcr; - int rc = -EINVAL; - - rtl_writephy(tp, 0x1f, 0x0000); - - if (autoneg == AUTONEG_ENABLE) { - int auto_nego; - - auto_nego = rtl_readphy(tp, MII_ADVERTISE); - auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL | - ADVERTISE_100HALF | ADVERTISE_100FULL); - - if (adv & ADVERTISED_10baseT_Half) - auto_nego |= ADVERTISE_10HALF; - if (adv & ADVERTISED_10baseT_Full) - auto_nego |= ADVERTISE_10FULL; - if (adv & ADVERTISED_100baseT_Half) - auto_nego |= ADVERTISE_100HALF; - if (adv & ADVERTISED_100baseT_Full) - auto_nego |= ADVERTISE_100FULL; - - auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM; - - giga_ctrl = rtl_readphy(tp, MII_CTRL1000); - giga_ctrl &= ~(ADVERTISE_1000FULL | ADVERTISE_1000HALF); - - /* The 8100e/8101e/8102e do Fast Ethernet only. */ - if (tp->mii.supports_gmii) { - if (adv & ADVERTISED_1000baseT_Half) - giga_ctrl |= ADVERTISE_1000HALF; - if (adv & ADVERTISED_1000baseT_Full) - giga_ctrl |= ADVERTISE_1000FULL; - } else if (adv & (ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full)) { - netif_info(tp, link, dev, - "PHY does not support 1000Mbps\n"); - goto out; - } - - bmcr = BMCR_ANENABLE | BMCR_ANRESTART; - - rtl_writephy(tp, MII_ADVERTISE, auto_nego); - rtl_writephy(tp, MII_CTRL1000, giga_ctrl); - } else { - giga_ctrl = 0; - - if (speed == SPEED_10) - bmcr = 0; - else if (speed == SPEED_100) - bmcr = BMCR_SPEED100; - else - goto out; - - if (duplex == DUPLEX_FULL) - bmcr |= BMCR_FULLDPLX; - } - - rtl_writephy(tp, MII_BMCR, bmcr); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02 || - tp->mac_version == RTL_GIGA_MAC_VER_03) { - if ((speed == SPEED_100) && (autoneg != AUTONEG_ENABLE)) { - rtl_writephy(tp, 0x17, 0x2138); - rtl_writephy(tp, 0x0e, 0x0260); - } else { - rtl_writephy(tp, 0x17, 0x2108); - rtl_writephy(tp, 0x0e, 0x0000); - } - } - - rc = 0; -out: - return rc; -} - -static int rtl8169_set_speed(struct net_device *dev, - u8 autoneg, u16 speed, u8 duplex, u32 advertising) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - ret = tp->set_speed(dev, autoneg, speed, duplex, advertising); - if (ret < 0) - goto out; - - if (netif_running(dev) && (autoneg == AUTONEG_ENABLE) && - (advertising & ADVERTISED_1000baseT_Full)) { - mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT); - } -out: - return ret; -} - -static int rtl8169_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int ret; - - del_timer_sync(&tp->timer); - - rtl_lock_work(tp); - ret = rtl8169_set_speed(dev, cmd->autoneg, ethtool_cmd_speed(cmd), - cmd->duplex, cmd->advertising); - rtl_unlock_work(tp); - - return ret; -} - -static netdev_features_t rtl8169_fix_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (dev->mtu > TD_MSS_MAX) - features &= ~NETIF_F_ALL_TSO; - - if (dev->mtu > JUMBO_1K && - !rtl_chip_infos[tp->mac_version].jumbo_tx_csum) - features &= ~NETIF_F_IP_CSUM; - - return features; -} - -static void __rtl8169_set_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 rx_config; - - rx_config = RTL_R32(RxConfig); - if (features & NETIF_F_RXALL) - rx_config |= (AcceptErr | AcceptRunt); - else - rx_config &= ~(AcceptErr | AcceptRunt); - - RTL_W32(RxConfig, rx_config); - - if (features & NETIF_F_RXCSUM) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; - - if (features & NETIF_F_HW_VLAN_CTAG_RX) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; - - tp->cp_cmd |= RTL_R16(CPlusCmd) & ~(RxVlan | RxChkSum); - - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); -} - -static int rtl8169_set_features(struct net_device *dev, - netdev_features_t features) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - features &= NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX; - - rtl_lock_work(tp); - if (features ^ dev->features) - __rtl8169_set_features(dev, features); - rtl_unlock_work(tp); - - return 0; -} - - -static inline u32 rtl8169_tx_vlan_tag(struct sk_buff *skb) -{ - return (skb_vlan_tag_present(skb)) ? - TxVlanTag | swab16(skb_vlan_tag_get(skb)) : 0x00; -} - -static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb) -{ - u32 opts2 = le32_to_cpu(desc->opts2); - - if (opts2 & RxVlanTag) - __vlan_hwaccel_put_tag(skb, htons(ETH_P_8021Q), swab16(opts2 & 0xffff)); -} - -static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 status; - - cmd->supported = - SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg | SUPPORTED_FIBRE; - cmd->port = PORT_FIBRE; - cmd->transceiver = XCVR_INTERNAL; - - status = RTL_R32(TBICSR); - cmd->advertising = (status & TBINwEnable) ? ADVERTISED_Autoneg : 0; - cmd->autoneg = !!(status & TBINwEnable); - - ethtool_cmd_speed_set(cmd, SPEED_1000); - cmd->duplex = DUPLEX_FULL; /* Always set */ - - return 0; -} - -static int rtl8169_gset_xmii(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return mii_ethtool_gset(&tp->mii, cmd); -} - -static int rtl8169_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - int rc; - - rtl_lock_work(tp); - rc = tp->get_settings(dev, cmd); - rtl_unlock_work(tp); - - return rc; -} - -static void rtl8169_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - u32 __iomem *data = tp->mmio_addr; - u32 *dw = p; - int i; - - rtl_lock_work(tp); - for (i = 0; i < R8169_REGS_SIZE; i += 4) - memcpy_fromio(dw++, data++, 4); - rtl_unlock_work(tp); -} - -static u32 rtl8169_get_msglevel(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->msg_enable; -} - -static void rtl8169_set_msglevel(struct net_device *dev, u32 value) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->msg_enable = value; -} - -static const char rtl8169_gstrings[][ETH_GSTRING_LEN] = { - "tx_packets", - "rx_packets", - "tx_errors", - "rx_errors", - "rx_missed", - "align_errors", - "tx_single_collisions", - "tx_multi_collisions", - "unicast", - "broadcast", - "multicast", - "tx_aborted", - "tx_underrun", -}; - -static int rtl8169_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(rtl8169_gstrings); - default: - return -EOPNOTSUPP; - } -} - -DECLARE_RTL_COND(rtl_counters_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(CounterAddrLow) & (CounterReset | CounterDump); -} - -static bool rtl8169_do_counters(struct net_device *dev, u32 counter_cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - dma_addr_t paddr = tp->counters_phys_addr; - u32 cmd; - - RTL_W32(CounterAddrHigh, (u64)paddr >> 32); - RTL_R32(CounterAddrHigh); - cmd = (u64)paddr & DMA_BIT_MASK(32); - RTL_W32(CounterAddrLow, cmd); - RTL_W32(CounterAddrLow, cmd | counter_cmd); - - return rtl_udelay_loop_wait_low(tp, &rtl_counters_cond, 10, 1000); -} - -static bool rtl8169_reset_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - /* - * Versions prior to RTL_GIGA_MAC_VER_19 don't support resetting the - * tally counters. - */ - if (tp->mac_version < RTL_GIGA_MAC_VER_19) - return true; - - return rtl8169_do_counters(dev, CounterReset); -} - -static bool rtl8169_update_counters(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - /* - * Some chips are unable to dump tally counters when the receiver - * is disabled. - */ - if ((RTL_R8(ChipCmd) & CmdRxEnb) == 0) - return true; - - return rtl8169_do_counters(dev, CounterDump); -} - -static bool rtl8169_init_counter_offsets(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct rtl8169_counters *counters = tp->counters; - bool ret = false; - - /* - * rtl8169_init_counter_offsets is called from rtl_open. On chip - * versions prior to RTL_GIGA_MAC_VER_19 the tally counters are only - * reset by a power cycle, while the counter values collected by the - * driver are reset at every driver unload/load cycle. - * - * To make sure the HW values returned by @get_stats64 match the SW - * values, we collect the initial values at first open(*) and use them - * as offsets to normalize the values returned by @get_stats64. - * - * (*) We can't call rtl8169_init_counter_offsets from rtl_init_one - * for the reason stated in rtl8169_update_counters; CmdRxEnb is only - * set at open time by rtl_hw_start. - */ - - if (tp->tc_offset.inited) - return true; - - /* If both, reset and update fail, propagate to caller. */ - if (rtl8169_reset_counters(dev)) - ret = true; - - if (rtl8169_update_counters(dev)) - ret = true; - - tp->tc_offset.tx_errors = counters->tx_errors; - tp->tc_offset.tx_multi_collision = counters->tx_multi_collision; - tp->tc_offset.tx_aborted = counters->tx_aborted; - tp->tc_offset.inited = true; - - return ret; -} - -static void rtl8169_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct rtl8169_counters *counters = tp->counters; - - ASSERT_RTNL(); - - rtl8169_update_counters(dev); - - data[0] = le64_to_cpu(counters->tx_packets); - data[1] = le64_to_cpu(counters->rx_packets); - data[2] = le64_to_cpu(counters->tx_errors); - data[3] = le32_to_cpu(counters->rx_errors); - data[4] = le16_to_cpu(counters->rx_missed); - data[5] = le16_to_cpu(counters->align_errors); - data[6] = le32_to_cpu(counters->tx_one_collision); - data[7] = le32_to_cpu(counters->tx_multi_collision); - data[8] = le64_to_cpu(counters->rx_unicast); - data[9] = le64_to_cpu(counters->rx_broadcast); - data[10] = le32_to_cpu(counters->rx_multicast); - data[11] = le16_to_cpu(counters->tx_aborted); - data[12] = le16_to_cpu(counters->tx_underun); -} - -static void rtl8169_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - switch(stringset) { - case ETH_SS_STATS: - memcpy(data, *rtl8169_gstrings, sizeof(rtl8169_gstrings)); - break; - } -} - -static const struct ethtool_ops rtl8169_ethtool_ops = { - .get_drvinfo = rtl8169_get_drvinfo, - .get_regs_len = rtl8169_get_regs_len, - .get_link = ethtool_op_get_link, - .get_settings = rtl8169_get_settings, - .set_settings = rtl8169_set_settings, - .get_msglevel = rtl8169_get_msglevel, - .set_msglevel = rtl8169_set_msglevel, - .get_regs = rtl8169_get_regs, - .get_wol = rtl8169_get_wol, - .set_wol = rtl8169_set_wol, - .get_strings = rtl8169_get_strings, - .get_sset_count = rtl8169_get_sset_count, - .get_ethtool_stats = rtl8169_get_ethtool_stats, - .get_ts_info = ethtool_op_get_ts_info, -}; - -static void rtl8169_get_mac_version(struct rtl8169_private *tp, - struct net_device *dev, u8 default_version) -{ - void __iomem *ioaddr = tp->mmio_addr; - /* - * The driver currently handles the 8168Bf and the 8168Be identically - * but they can be identified more specifically through the test below - * if needed: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x500000 ? 8168Bf : 8168Be - * - * Same thing for the 8101Eb and the 8101Ec: - * - * (RTL_R32(TxConfig) & 0x700000) == 0x200000 ? 8101Eb : 8101Ec - */ - static const struct rtl_mac_info { - u32 mask; - u32 val; - int mac_version; - } mac_info[] = { - /* 8168EP family. */ - { 0x7cf00000, 0x50200000, RTL_GIGA_MAC_VER_51 }, - { 0x7cf00000, 0x50100000, RTL_GIGA_MAC_VER_50 }, - { 0x7cf00000, 0x50000000, RTL_GIGA_MAC_VER_49 }, - - /* 8168H family. */ - { 0x7cf00000, 0x54100000, RTL_GIGA_MAC_VER_46 }, - { 0x7cf00000, 0x54000000, RTL_GIGA_MAC_VER_45 }, - - /* 8168G family. */ - { 0x7cf00000, 0x5c800000, RTL_GIGA_MAC_VER_44 }, - { 0x7cf00000, 0x50900000, RTL_GIGA_MAC_VER_42 }, - { 0x7cf00000, 0x4c100000, RTL_GIGA_MAC_VER_41 }, - { 0x7cf00000, 0x4c000000, RTL_GIGA_MAC_VER_40 }, - - /* 8168F family. */ - { 0x7c800000, 0x48800000, RTL_GIGA_MAC_VER_38 }, - { 0x7cf00000, 0x48100000, RTL_GIGA_MAC_VER_36 }, - { 0x7cf00000, 0x48000000, RTL_GIGA_MAC_VER_35 }, - - /* 8168E family. */ - { 0x7c800000, 0x2c800000, RTL_GIGA_MAC_VER_34 }, - { 0x7cf00000, 0x2c200000, RTL_GIGA_MAC_VER_33 }, - { 0x7cf00000, 0x2c100000, RTL_GIGA_MAC_VER_32 }, - { 0x7c800000, 0x2c000000, RTL_GIGA_MAC_VER_33 }, - - /* 8168D family. */ - { 0x7cf00000, 0x28300000, RTL_GIGA_MAC_VER_26 }, - { 0x7cf00000, 0x28100000, RTL_GIGA_MAC_VER_25 }, - { 0x7c800000, 0x28000000, RTL_GIGA_MAC_VER_26 }, - - /* 8168DP family. */ - { 0x7cf00000, 0x28800000, RTL_GIGA_MAC_VER_27 }, - { 0x7cf00000, 0x28a00000, RTL_GIGA_MAC_VER_28 }, - { 0x7cf00000, 0x28b00000, RTL_GIGA_MAC_VER_31 }, - - /* 8168C family. */ - { 0x7cf00000, 0x3cb00000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c900000, RTL_GIGA_MAC_VER_23 }, - { 0x7cf00000, 0x3c800000, RTL_GIGA_MAC_VER_18 }, - { 0x7c800000, 0x3c800000, RTL_GIGA_MAC_VER_24 }, - { 0x7cf00000, 0x3c000000, RTL_GIGA_MAC_VER_19 }, - { 0x7cf00000, 0x3c200000, RTL_GIGA_MAC_VER_20 }, - { 0x7cf00000, 0x3c300000, RTL_GIGA_MAC_VER_21 }, - { 0x7cf00000, 0x3c400000, RTL_GIGA_MAC_VER_22 }, - { 0x7c800000, 0x3c000000, RTL_GIGA_MAC_VER_22 }, - - /* 8168B family. */ - { 0x7cf00000, 0x38000000, RTL_GIGA_MAC_VER_12 }, - { 0x7cf00000, 0x38500000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x38000000, RTL_GIGA_MAC_VER_17 }, - { 0x7c800000, 0x30000000, RTL_GIGA_MAC_VER_11 }, - - /* 8101 family. */ - { 0x7cf00000, 0x44900000, RTL_GIGA_MAC_VER_39 }, - { 0x7c800000, 0x44800000, RTL_GIGA_MAC_VER_39 }, - { 0x7c800000, 0x44000000, RTL_GIGA_MAC_VER_37 }, - { 0x7cf00000, 0x40b00000, RTL_GIGA_MAC_VER_30 }, - { 0x7cf00000, 0x40a00000, RTL_GIGA_MAC_VER_30 }, - { 0x7cf00000, 0x40900000, RTL_GIGA_MAC_VER_29 }, - { 0x7c800000, 0x40800000, RTL_GIGA_MAC_VER_30 }, - { 0x7cf00000, 0x34a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x24a00000, RTL_GIGA_MAC_VER_09 }, - { 0x7cf00000, 0x34900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x24900000, RTL_GIGA_MAC_VER_08 }, - { 0x7cf00000, 0x34800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x24800000, RTL_GIGA_MAC_VER_07 }, - { 0x7cf00000, 0x34000000, RTL_GIGA_MAC_VER_13 }, - { 0x7cf00000, 0x34300000, RTL_GIGA_MAC_VER_10 }, - { 0x7cf00000, 0x34200000, RTL_GIGA_MAC_VER_16 }, - { 0x7c800000, 0x34800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x24800000, RTL_GIGA_MAC_VER_09 }, - { 0x7c800000, 0x34000000, RTL_GIGA_MAC_VER_16 }, - /* FIXME: where did these entries come from ? -- FR */ - { 0xfc800000, 0x38800000, RTL_GIGA_MAC_VER_15 }, - { 0xfc800000, 0x30800000, RTL_GIGA_MAC_VER_14 }, - - /* 8110 family. */ - { 0xfc800000, 0x98000000, RTL_GIGA_MAC_VER_06 }, - { 0xfc800000, 0x18000000, RTL_GIGA_MAC_VER_05 }, - { 0xfc800000, 0x10000000, RTL_GIGA_MAC_VER_04 }, - { 0xfc800000, 0x04000000, RTL_GIGA_MAC_VER_03 }, - { 0xfc800000, 0x00800000, RTL_GIGA_MAC_VER_02 }, - { 0xfc800000, 0x00000000, RTL_GIGA_MAC_VER_01 }, - - /* Catch-all */ - { 0x00000000, 0x00000000, RTL_GIGA_MAC_NONE } - }; - const struct rtl_mac_info *p = mac_info; - u32 reg; - - reg = RTL_R32(TxConfig); - while ((reg & p->mask) != p->val) - p++; - tp->mac_version = p->mac_version; - - if (tp->mac_version == RTL_GIGA_MAC_NONE) { - netif_notice(tp, probe, dev, - "unknown MAC, using family default\n"); - tp->mac_version = default_version; - } else if (tp->mac_version == RTL_GIGA_MAC_VER_42) { - tp->mac_version = tp->mii.supports_gmii ? - RTL_GIGA_MAC_VER_42 : - RTL_GIGA_MAC_VER_43; - } else if (tp->mac_version == RTL_GIGA_MAC_VER_45) { - tp->mac_version = tp->mii.supports_gmii ? - RTL_GIGA_MAC_VER_45 : - RTL_GIGA_MAC_VER_47; - } else if (tp->mac_version == RTL_GIGA_MAC_VER_46) { - tp->mac_version = tp->mii.supports_gmii ? - RTL_GIGA_MAC_VER_46 : - RTL_GIGA_MAC_VER_48; - } -} - -static void rtl8169_print_mac_version(struct rtl8169_private *tp) -{ - dprintk("mac_version = 0x%02x\n", tp->mac_version); -} - -struct phy_reg { - u16 reg; - u16 val; -}; - -static void rtl_writephy_batch(struct rtl8169_private *tp, - const struct phy_reg *regs, int len) -{ - while (len-- > 0) { - rtl_writephy(tp, regs->reg, regs->val); - regs++; - } -} - -#define PHY_READ 0x00000000 -#define PHY_DATA_OR 0x10000000 -#define PHY_DATA_AND 0x20000000 -#define PHY_BJMPN 0x30000000 -#define PHY_MDIO_CHG 0x40000000 -#define PHY_CLEAR_READCOUNT 0x70000000 -#define PHY_WRITE 0x80000000 -#define PHY_READCOUNT_EQ_SKIP 0x90000000 -#define PHY_COMP_EQ_SKIPN 0xa0000000 -#define PHY_COMP_NEQ_SKIPN 0xb0000000 -#define PHY_WRITE_PREVIOUS 0xc0000000 -#define PHY_SKIPN 0xd0000000 -#define PHY_DELAY_MS 0xe0000000 - -struct fw_info { - u32 magic; - char version[RTL_VER_SIZE]; - __le32 fw_start; - __le32 fw_len; - u8 chksum; -} __packed; - -#define FW_OPCODE_SIZE sizeof(typeof(*((struct rtl_fw_phy_action *)0)->code)) - -static bool rtl_fw_format_ok(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) -{ - const struct firmware *fw = rtl_fw->fw; - struct fw_info *fw_info = (struct fw_info *)fw->data; - struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; - char *version = rtl_fw->version; - bool rc = false; - - if (fw->size < FW_OPCODE_SIZE) - goto out; - - if (!fw_info->magic) { - size_t i, size, start; - u8 checksum = 0; - - if (fw->size < sizeof(*fw_info)) - goto out; - - for (i = 0; i < fw->size; i++) - checksum += fw->data[i]; - if (checksum != 0) - goto out; - - start = le32_to_cpu(fw_info->fw_start); - if (start > fw->size) - goto out; - - size = le32_to_cpu(fw_info->fw_len); - if (size > (fw->size - start) / FW_OPCODE_SIZE) - goto out; - - memcpy(version, fw_info->version, RTL_VER_SIZE); - - pa->code = (__le32 *)(fw->data + start); - pa->size = size; - } else { - if (fw->size % FW_OPCODE_SIZE) - goto out; - - strlcpy(version, rtl_lookup_firmware_name(tp), RTL_VER_SIZE); - - pa->code = (__le32 *)fw->data; - pa->size = fw->size / FW_OPCODE_SIZE; - } - version[RTL_VER_SIZE - 1] = 0; - - rc = true; -out: - return rc; -} - -static bool rtl_fw_data_ok(struct rtl8169_private *tp, struct net_device *dev, - struct rtl_fw_phy_action *pa) -{ - bool rc = false; - size_t index; - - for (index = 0; index < pa->size; index++) { - u32 action = le32_to_cpu(pa->code[index]); - u32 regno = (action & 0x0fff0000) >> 16; - - switch(action & 0xf0000000) { - case PHY_READ: - case PHY_DATA_OR: - case PHY_DATA_AND: - case PHY_MDIO_CHG: - case PHY_CLEAR_READCOUNT: - case PHY_WRITE: - case PHY_WRITE_PREVIOUS: - case PHY_DELAY_MS: - break; - - case PHY_BJMPN: - if (regno > index) { - netif_err(tp, ifup, tp->dev, - "Out of range of firmware\n"); - goto out; - } - break; - case PHY_READCOUNT_EQ_SKIP: - if (index + 2 >= pa->size) { - netif_err(tp, ifup, tp->dev, - "Out of range of firmware\n"); - goto out; - } - break; - case PHY_COMP_EQ_SKIPN: - case PHY_COMP_NEQ_SKIPN: - case PHY_SKIPN: - if (index + 1 + regno >= pa->size) { - netif_err(tp, ifup, tp->dev, - "Out of range of firmware\n"); - goto out; - } - break; - - default: - netif_err(tp, ifup, tp->dev, - "Invalid action 0x%08x\n", action); - goto out; - } - } - rc = true; -out: - return rc; -} - -static int rtl_check_firmware(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) -{ - struct net_device *dev = tp->dev; - int rc = -EINVAL; - - if (!rtl_fw_format_ok(tp, rtl_fw)) { - netif_err(tp, ifup, dev, "invalid firmware\n"); - goto out; - } - - if (rtl_fw_data_ok(tp, dev, &rtl_fw->phy_action)) - rc = 0; -out: - return rc; -} - -static void rtl_phy_write_fw(struct rtl8169_private *tp, struct rtl_fw *rtl_fw) -{ - struct rtl_fw_phy_action *pa = &rtl_fw->phy_action; - struct mdio_ops org, *ops = &tp->mdio_ops; - u32 predata, count; - size_t index; - - predata = count = 0; - org.write = ops->write; - org.read = ops->read; - - for (index = 0; index < pa->size; ) { - u32 action = le32_to_cpu(pa->code[index]); - u32 data = action & 0x0000ffff; - u32 regno = (action & 0x0fff0000) >> 16; - - if (!action) - break; - - switch(action & 0xf0000000) { - case PHY_READ: - predata = rtl_readphy(tp, regno); - count++; - index++; - break; - case PHY_DATA_OR: - predata |= data; - index++; - break; - case PHY_DATA_AND: - predata &= data; - index++; - break; - case PHY_BJMPN: - index -= regno; - break; - case PHY_MDIO_CHG: - if (data == 0) { - ops->write = org.write; - ops->read = org.read; - } else if (data == 1) { - ops->write = mac_mcu_write; - ops->read = mac_mcu_read; - } - - index++; - break; - case PHY_CLEAR_READCOUNT: - count = 0; - index++; - break; - case PHY_WRITE: - rtl_writephy(tp, regno, data); - index++; - break; - case PHY_READCOUNT_EQ_SKIP: - index += (count == data) ? 2 : 1; - break; - case PHY_COMP_EQ_SKIPN: - if (predata == data) - index += regno; - index++; - break; - case PHY_COMP_NEQ_SKIPN: - if (predata != data) - index += regno; - index++; - break; - case PHY_WRITE_PREVIOUS: - rtl_writephy(tp, regno, predata); - index++; - break; - case PHY_SKIPN: - index += regno + 1; - break; - case PHY_DELAY_MS: - mdelay(data); - index++; - break; - - default: - BUG(); - } - } - - ops->write = org.write; - ops->read = org.read; -} - -static void rtl_release_firmware(struct rtl8169_private *tp) -{ - if (!IS_ERR_OR_NULL(tp->rtl_fw)) { - release_firmware(tp->rtl_fw->fw); - kfree(tp->rtl_fw); - } - tp->rtl_fw = RTL_FIRMWARE_UNKNOWN; -} - -static void rtl_apply_firmware(struct rtl8169_private *tp) -{ - struct rtl_fw *rtl_fw = tp->rtl_fw; - - /* TODO: release firmware once rtl_phy_write_fw signals failures. */ - if (!IS_ERR_OR_NULL(rtl_fw)) - rtl_phy_write_fw(tp, rtl_fw); -} - -static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val) -{ - if (rtl_readphy(tp, reg) != val) - netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n"); - else - rtl_apply_firmware(tp); -} - -static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x06, 0x006e }, - { 0x08, 0x0708 }, - { 0x15, 0x4000 }, - { 0x18, 0x65c7 }, - - { 0x1f, 0x0001 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x0000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf60 }, - { 0x01, 0x0140 }, - { 0x00, 0x0077 }, - { 0x04, 0x7800 }, - { 0x04, 0x7000 }, - - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf0f9 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xa000 }, - - { 0x03, 0xff41 }, - { 0x02, 0xdf20 }, - { 0x01, 0x0140 }, - { 0x00, 0x00bb }, - { 0x04, 0xb800 }, - { 0x04, 0xb000 }, - - { 0x03, 0xdf41 }, - { 0x02, 0xdc60 }, - { 0x01, 0x6340 }, - { 0x00, 0x007d }, - { 0x04, 0xd800 }, - { 0x04, 0xd000 }, - - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x100a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - - { 0x1f, 0x0000 }, - { 0x0b, 0x0000 }, - { 0x00, 0x9200 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169sb_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x01, 0x90d0 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8169scd_hw_phy_config_quirk(struct rtl8169_private *tp) -{ - struct pci_dev *pdev = tp->pci_dev; - - if ((pdev->subsystem_vendor != PCI_VENDOR_ID_GIGABYTE) || - (pdev->subsystem_device != 0xe000)) - return; - - rtl_writephy(tp, 0x1f, 0x0001); - rtl_writephy(tp, 0x10, 0xf01b); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8169scd_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x14, 0xfb54 }, - { 0x18, 0xf5c7 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8169scd_hw_phy_config_quirk(tp); -} - -static void rtl8169sce_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x04, 0x0000 }, - { 0x03, 0x00a1 }, - { 0x02, 0x0008 }, - { 0x01, 0x0120 }, - { 0x00, 0x1000 }, - { 0x04, 0x0800 }, - { 0x04, 0x9000 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0xa000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0xff95 }, - { 0x00, 0xba00 }, - { 0x04, 0xa800 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0x8480 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x18, 0x67c7 }, - { 0x04, 0x2000 }, - { 0x03, 0x002f }, - { 0x02, 0x4360 }, - { 0x01, 0x0109 }, - { 0x00, 0x3022 }, - { 0x04, 0x2800 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bb_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_writephy(tp, 0x1f, 0x0001); - rtl_patchphy(tp, 0x16, 1 << 0); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168bef_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x10, 0xf41b }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_1_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0000 }, - { 0x1d, 0x0f00 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x1ec8 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168cp_2_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy(tp, 0x1f, 0x0000); - rtl_patchphy(tp, 0x14, 1 << 5); - rtl_patchphy(tp, 0x0d, 1 << 5); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168c_1_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1f, 0x0002 }, - { 0x00, 0x88d4 }, - { 0x01, 0x82b1 }, - { 0x03, 0x7002 }, - { 0x08, 0x9e30 }, - { 0x09, 0x01f0 }, - { 0x0a, 0x5500 }, - { 0x0c, 0x00c8 }, - { 0x1f, 0x0003 }, - { 0x12, 0xc096 }, - { 0x16, 0x000a }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x09, 0x2000 }, - { 0x09, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl_patchphy(tp, 0x14, 1 << 5); - rtl_patchphy(tp, 0x0d, 1 << 5); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168c_2_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x03, 0x802f }, - { 0x02, 0x4f02 }, - { 0x01, 0x0409 }, - { 0x00, 0xf099 }, - { 0x04, 0x9800 }, - { 0x04, 0x9000 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x0761 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl_patchphy(tp, 0x16, 1 << 0); - rtl_patchphy(tp, 0x14, 1 << 5); - rtl_patchphy(tp, 0x0d, 1 << 5); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168c_3_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x12, 0x2300 }, - { 0x1d, 0x3d98 }, - { 0x1f, 0x0002 }, - { 0x0c, 0x7eb8 }, - { 0x06, 0x5461 }, - { 0x1f, 0x0003 }, - { 0x16, 0x0f0a }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl_patchphy(tp, 0x16, 1 << 0); - rtl_patchphy(tp, 0x14, 1 << 5); - rtl_patchphy(tp, 0x0d, 1 << 5); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168c_4_hw_phy_config(struct rtl8169_private *tp) -{ - rtl8168c_3_hw_phy_config(tp); -} - -static void rtl8168d_1_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init_0[] = { - /* Channel Estimation */ - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - /* - * Tx Error Issue - * Enhance line driver power - */ - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 }, - - /* - * Can not link to 1Gbps with bad cable - * Decrease SNR threshold form 21.07dB to 19.04dB - */ - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 } - }; - - rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - /* - * Rx Error Issue - * Fine Tune Switching regulator parameter - */ - rtl_writephy(tp, 0x1f, 0x0002); - rtl_w0w1_phy(tp, 0x0b, 0x0010, 0x00ef); - rtl_w0w1_phy(tp, 0x0c, 0xa200, 0x5d00); - - if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - { 0x1f, 0x0002 } - }; - int val; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = rtl_readphy(tp, 0x0d); - - if ((val & 0x00ff) != 0x006c) { - static const u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - rtl_writephy(tp, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - rtl_writephy(tp, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x6662 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x6662 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - /* RSET couple improve */ - rtl_writephy(tp, 0x1f, 0x0002); - rtl_patchphy(tp, 0x0d, 0x0300); - rtl_patchphy(tp, 0x0f, 0x0010); - - /* Fine tune PLL performance */ - rtl_writephy(tp, 0x1f, 0x0002); - rtl_w0w1_phy(tp, 0x02, 0x0100, 0x0600); - rtl_w0w1_phy(tp, 0x03, 0x0000, 0xe000); - - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x001b); - - rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00); - - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168d_2_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init_0[] = { - /* Channel Estimation */ - { 0x1f, 0x0001 }, - { 0x06, 0x4064 }, - { 0x07, 0x2863 }, - { 0x08, 0x059c }, - { 0x09, 0x26b4 }, - { 0x0a, 0x6a19 }, - { 0x0b, 0xdcc8 }, - { 0x10, 0xf06d }, - { 0x14, 0x7f68 }, - { 0x18, 0x7fd9 }, - { 0x1c, 0xf0ff }, - { 0x1d, 0x3d9c }, - { 0x1f, 0x0003 }, - { 0x12, 0xf49f }, - { 0x13, 0x070b }, - { 0x1a, 0x05ad }, - { 0x14, 0x94c0 }, - - /* - * Tx Error Issue - * Enhance line driver power - */ - { 0x1f, 0x0002 }, - { 0x06, 0x5561 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8332 }, - { 0x06, 0x5561 }, - - /* - * Can not link to 1Gbps with bad cable - * Decrease SNR threshold form 21.07dB to 19.04dB - */ - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 } - }; - - rtl_writephy_batch(tp, phy_reg_init_0, ARRAY_SIZE(phy_reg_init_0)); - - if (rtl8168d_efuse_read(tp, 0x01) == 0xb1) { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x669a }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x669a }, - - { 0x1f, 0x0002 } - }; - int val; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - val = rtl_readphy(tp, 0x0d); - if ((val & 0x00ff) != 0x006c) { - static const u32 set[] = { - 0x0065, 0x0066, 0x0067, 0x0068, - 0x0069, 0x006a, 0x006b, 0x006c - }; - int i; - - rtl_writephy(tp, 0x1f, 0x0002); - - val &= 0xff00; - for (i = 0; i < ARRAY_SIZE(set); i++) - rtl_writephy(tp, 0x0d, val | set[i]); - } - } else { - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x05, 0x2642 }, - { 0x1f, 0x0005 }, - { 0x05, 0x8330 }, - { 0x06, 0x2642 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - } - - /* Fine tune PLL performance */ - rtl_writephy(tp, 0x1f, 0x0002); - rtl_w0w1_phy(tp, 0x02, 0x0100, 0x0600); - rtl_w0w1_phy(tp, 0x03, 0x0000, 0xe000); - - /* Switching regulator Slew rate */ - rtl_writephy(tp, 0x1f, 0x0002); - rtl_patchphy(tp, 0x0f, 0x0017); - - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x001b); - - rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300); - - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168d_3_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0002 }, - { 0x10, 0x0008 }, - { 0x0d, 0x006c }, - - { 0x1f, 0x0000 }, - { 0x0d, 0xf880 }, - - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0001 }, - { 0x0b, 0xa4d8 }, - { 0x09, 0x281c }, - { 0x07, 0x2883 }, - { 0x0a, 0x6b35 }, - { 0x1d, 0x3da4 }, - { 0x1c, 0xeffd }, - { 0x14, 0x7f52 }, - { 0x18, 0x7fc6 }, - { 0x08, 0x0601 }, - { 0x06, 0x4063 }, - { 0x10, 0xf074 }, - { 0x1f, 0x0003 }, - { 0x13, 0x0789 }, - { 0x12, 0xf4bd }, - { 0x1a, 0x04fd }, - { 0x14, 0x84b0 }, - { 0x1f, 0x0000 }, - { 0x00, 0x9200 }, - - { 0x1f, 0x0005 }, - { 0x01, 0x0340 }, - { 0x1f, 0x0001 }, - { 0x04, 0x4000 }, - { 0x03, 0x1d21 }, - { 0x02, 0x0c32 }, - { 0x01, 0x0200 }, - { 0x00, 0x5554 }, - { 0x04, 0x4800 }, - { 0x04, 0x4000 }, - { 0x04, 0xf000 }, - { 0x03, 0xdf01 }, - { 0x02, 0xdf20 }, - { 0x01, 0x101a }, - { 0x00, 0xa0ff }, - { 0x04, 0xf800 }, - { 0x04, 0xf000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x0023 }, - { 0x16, 0x0000 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8168d_4_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0001 }, - { 0x17, 0x0cc0 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x002d }, - { 0x18, 0x0040 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - rtl_patchphy(tp, 0x0d, 1 << 5); -} - -static void rtl8168e_1_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - /* Enable Delay cap */ - { 0x1f, 0x0005 }, - { 0x05, 0x8b80 }, - { 0x06, 0xc896 }, - { 0x1f, 0x0000 }, - - /* Channel estimation fine tune */ - { 0x1f, 0x0001 }, - { 0x0b, 0x6c20 }, - { 0x07, 0x2872 }, - { 0x1c, 0xefff }, - { 0x1f, 0x0003 }, - { 0x14, 0x6420 }, - { 0x1f, 0x0000 }, - - /* Update PFM & 10M TX idle timer */ - { 0x1f, 0x0007 }, - { 0x1e, 0x002f }, - { 0x15, 0x1919 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0007 }, - { 0x1e, 0x00ac }, - { 0x18, 0x0006 }, - { 0x1f, 0x0000 } - }; - - rtl_apply_firmware(tp); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - /* DCO enable for 10M IDLE Power */ - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x0023); - rtl_w0w1_phy(tp, 0x17, 0x0006, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* For impedance matching */ - rtl_writephy(tp, 0x1f, 0x0002); - rtl_w0w1_phy(tp, 0x08, 0x8000, 0x7f00); - rtl_writephy(tp, 0x1f, 0x0000); - - /* PHY auto speed down */ - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x002d); - rtl_w0w1_phy(tp, 0x18, 0x0050, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_w0w1_phy(tp, 0x14, 0x8000, 0x0000); - - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b86); - rtl_w0w1_phy(tp, 0x06, 0x0001, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w0w1_phy(tp, 0x06, 0x0000, 0x2000); - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x0020); - rtl_w0w1_phy(tp, 0x15, 0x0000, 0x1100); - rtl_writephy(tp, 0x1f, 0x0006); - rtl_writephy(tp, 0x00, 0x5a00); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x0d, 0x0007); - rtl_writephy(tp, 0x0e, 0x003c); - rtl_writephy(tp, 0x0d, 0x4007); - rtl_writephy(tp, 0x0e, 0x0000); - rtl_writephy(tp, 0x0d, 0x0000); -} - -static void rtl_rar_exgmac_set(struct rtl8169_private *tp, u8 *addr) -{ - const u16 w[] = { - addr[0] | (addr[1] << 8), - addr[2] | (addr[3] << 8), - addr[4] | (addr[5] << 8) - }; - const struct exgmac_reg e[] = { - { .addr = 0xe0, ERIAR_MASK_1111, .val = w[0] | (w[1] << 16) }, - { .addr = 0xe4, ERIAR_MASK_1111, .val = w[2] }, - { .addr = 0xf0, ERIAR_MASK_1111, .val = w[0] << 16 }, - { .addr = 0xf4, ERIAR_MASK_1111, .val = w[1] | (w[2] << 16) } - }; - - rtl_write_exgmac_batch(tp, e, ARRAY_SIZE(e)); -} - -static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - /* Enable Delay cap */ - { 0x1f, 0x0004 }, - { 0x1f, 0x0007 }, - { 0x1e, 0x00ac }, - { 0x18, 0x0006 }, - { 0x1f, 0x0002 }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - - /* Channel estimation fine tune */ - { 0x1f, 0x0003 }, - { 0x09, 0xa20f }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0000 }, - - /* Green Setting */ - { 0x1f, 0x0005 }, - { 0x05, 0x8b5b }, - { 0x06, 0x9222 }, - { 0x05, 0x8b6d }, - { 0x06, 0x8000 }, - { 0x05, 0x8b76 }, - { 0x06, 0x8000 }, - { 0x1f, 0x0000 } - }; - - rtl_apply_firmware(tp); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - /* For 4-corner performance improve */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b80); - rtl_w0w1_phy(tp, 0x17, 0x0006, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* PHY auto speed down */ - rtl_writephy(tp, 0x1f, 0x0004); - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x002d); - rtl_w0w1_phy(tp, 0x18, 0x0010, 0x0000); - rtl_writephy(tp, 0x1f, 0x0002); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_w0w1_phy(tp, 0x14, 0x8000, 0x0000); - - /* improve 10M EEE waveform */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b86); - rtl_w0w1_phy(tp, 0x06, 0x0001, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* Improve 2-pair detection performance */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w0w1_phy(tp, 0x06, 0x4000, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* EEE setting */ - rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_1111, 0x0000, 0x0003, ERIAR_EXGMAC); - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w0w1_phy(tp, 0x06, 0x0000, 0x2000); - rtl_writephy(tp, 0x1f, 0x0004); - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x0020); - rtl_w0w1_phy(tp, 0x15, 0x0000, 0x0100); - rtl_writephy(tp, 0x1f, 0x0002); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x0d, 0x0007); - rtl_writephy(tp, 0x0e, 0x003c); - rtl_writephy(tp, 0x0d, 0x4007); - rtl_writephy(tp, 0x0e, 0x0000); - rtl_writephy(tp, 0x0d, 0x0000); - - /* Green feature */ - rtl_writephy(tp, 0x1f, 0x0003); - rtl_w0w1_phy(tp, 0x19, 0x0000, 0x0001); - rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0400); - rtl_writephy(tp, 0x1f, 0x0000); - - /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */ - rtl_rar_exgmac_set(tp, tp->dev->dev_addr); -} - -static void rtl8168f_hw_phy_config(struct rtl8169_private *tp) -{ - /* For 4-corner performance improve */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b80); - rtl_w0w1_phy(tp, 0x06, 0x0006, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* PHY auto speed down */ - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x002d); - rtl_w0w1_phy(tp, 0x18, 0x0010, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_w0w1_phy(tp, 0x14, 0x8000, 0x0000); - - /* Improve 10M EEE waveform */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b86); - rtl_w0w1_phy(tp, 0x06, 0x0001, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - /* Channel estimation fine tune */ - { 0x1f, 0x0003 }, - { 0x09, 0xa20f }, - { 0x1f, 0x0000 }, - - /* Modify green table for giga & fnet */ - { 0x1f, 0x0005 }, - { 0x05, 0x8b55 }, - { 0x06, 0x0000 }, - { 0x05, 0x8b5e }, - { 0x06, 0x0000 }, - { 0x05, 0x8b67 }, - { 0x06, 0x0000 }, - { 0x05, 0x8b70 }, - { 0x06, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0007 }, - { 0x1e, 0x0078 }, - { 0x17, 0x0000 }, - { 0x19, 0x00fb }, - { 0x1f, 0x0000 }, - - /* Modify green table for 10M */ - { 0x1f, 0x0005 }, - { 0x05, 0x8b79 }, - { 0x06, 0xaa00 }, - { 0x1f, 0x0000 }, - - /* Disable hiimpedance detection (RTCT) */ - { 0x1f, 0x0003 }, - { 0x01, 0x328a }, - { 0x1f, 0x0000 } - }; - - rtl_apply_firmware(tp); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl8168f_hw_phy_config(tp); - - /* Improve 2-pair detection performance */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w0w1_phy(tp, 0x06, 0x4000, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp) -{ - rtl_apply_firmware(tp); - - rtl8168f_hw_phy_config(tp); -} - -static void rtl8411_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - /* Channel estimation fine tune */ - { 0x1f, 0x0003 }, - { 0x09, 0xa20f }, - { 0x1f, 0x0000 }, - - /* Modify green table for giga & fnet */ - { 0x1f, 0x0005 }, - { 0x05, 0x8b55 }, - { 0x06, 0x0000 }, - { 0x05, 0x8b5e }, - { 0x06, 0x0000 }, - { 0x05, 0x8b67 }, - { 0x06, 0x0000 }, - { 0x05, 0x8b70 }, - { 0x06, 0x0000 }, - { 0x1f, 0x0000 }, - { 0x1f, 0x0007 }, - { 0x1e, 0x0078 }, - { 0x17, 0x0000 }, - { 0x19, 0x00aa }, - { 0x1f, 0x0000 }, - - /* Modify green table for 10M */ - { 0x1f, 0x0005 }, - { 0x05, 0x8b79 }, - { 0x06, 0xaa00 }, - { 0x1f, 0x0000 }, - - /* Disable hiimpedance detection (RTCT) */ - { 0x1f, 0x0003 }, - { 0x01, 0x328a }, - { 0x1f, 0x0000 } - }; - - - rtl_apply_firmware(tp); - - rtl8168f_hw_phy_config(tp); - - /* Improve 2-pair detection performance */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w0w1_phy(tp, 0x06, 0x4000, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - /* Modify green table for giga */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b54); - rtl_w0w1_phy(tp, 0x06, 0x0000, 0x0800); - rtl_writephy(tp, 0x05, 0x8b5d); - rtl_w0w1_phy(tp, 0x06, 0x0000, 0x0800); - rtl_writephy(tp, 0x05, 0x8a7c); - rtl_w0w1_phy(tp, 0x06, 0x0000, 0x0100); - rtl_writephy(tp, 0x05, 0x8a7f); - rtl_w0w1_phy(tp, 0x06, 0x0100, 0x0000); - rtl_writephy(tp, 0x05, 0x8a82); - rtl_w0w1_phy(tp, 0x06, 0x0000, 0x0100); - rtl_writephy(tp, 0x05, 0x8a85); - rtl_w0w1_phy(tp, 0x06, 0x0000, 0x0100); - rtl_writephy(tp, 0x05, 0x8a88); - rtl_w0w1_phy(tp, 0x06, 0x0000, 0x0100); - rtl_writephy(tp, 0x1f, 0x0000); - - /* uc same-seed solution */ - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w0w1_phy(tp, 0x06, 0x8000, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* eee setting */ - rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x00, 0x03, ERIAR_EXGMAC); - rtl_writephy(tp, 0x1f, 0x0005); - rtl_writephy(tp, 0x05, 0x8b85); - rtl_w0w1_phy(tp, 0x06, 0x0000, 0x2000); - rtl_writephy(tp, 0x1f, 0x0004); - rtl_writephy(tp, 0x1f, 0x0007); - rtl_writephy(tp, 0x1e, 0x0020); - rtl_w0w1_phy(tp, 0x15, 0x0000, 0x0100); - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x0d, 0x0007); - rtl_writephy(tp, 0x0e, 0x003c); - rtl_writephy(tp, 0x0d, 0x4007); - rtl_writephy(tp, 0x0e, 0x0000); - rtl_writephy(tp, 0x0d, 0x0000); - - /* Green feature */ - rtl_writephy(tp, 0x1f, 0x0003); - rtl_w0w1_phy(tp, 0x19, 0x0000, 0x0001); - rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0400); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) -{ - rtl_apply_firmware(tp); - - rtl_writephy(tp, 0x1f, 0x0a46); - if (rtl_readphy(tp, 0x10) & 0x0100) { - rtl_writephy(tp, 0x1f, 0x0bcc); - rtl_w0w1_phy(tp, 0x12, 0x0000, 0x8000); - } else { - rtl_writephy(tp, 0x1f, 0x0bcc); - rtl_w0w1_phy(tp, 0x12, 0x8000, 0x0000); - } - - rtl_writephy(tp, 0x1f, 0x0a46); - if (rtl_readphy(tp, 0x13) & 0x0100) { - rtl_writephy(tp, 0x1f, 0x0c41); - rtl_w0w1_phy(tp, 0x15, 0x0002, 0x0000); - } else { - rtl_writephy(tp, 0x1f, 0x0c41); - rtl_w0w1_phy(tp, 0x15, 0x0000, 0x0002); - } - - /* Enable PHY auto speed down */ - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w0w1_phy(tp, 0x11, 0x000c, 0x0000); - - rtl_writephy(tp, 0x1f, 0x0bcc); - rtl_w0w1_phy(tp, 0x14, 0x0100, 0x0000); - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w0w1_phy(tp, 0x11, 0x00c0, 0x0000); - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x8084); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x6000); - rtl_w0w1_phy(tp, 0x10, 0x1003, 0x0000); - - /* EEE auto-fallback function */ - rtl_writephy(tp, 0x1f, 0x0a4b); - rtl_w0w1_phy(tp, 0x11, 0x0004, 0x0000); - - /* Enable UC LPF tune function */ - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x8012); - rtl_w0w1_phy(tp, 0x14, 0x8000, 0x0000); - - rtl_writephy(tp, 0x1f, 0x0c42); - rtl_w0w1_phy(tp, 0x11, 0x4000, 0x2000); - - /* Improve SWR Efficiency */ - rtl_writephy(tp, 0x1f, 0x0bcd); - rtl_writephy(tp, 0x14, 0x5065); - rtl_writephy(tp, 0x14, 0xd065); - rtl_writephy(tp, 0x1f, 0x0bc8); - rtl_writephy(tp, 0x11, 0x5655); - rtl_writephy(tp, 0x1f, 0x0bcd); - rtl_writephy(tp, 0x14, 0x1065); - rtl_writephy(tp, 0x14, 0x9065); - rtl_writephy(tp, 0x14, 0x1065); - - /* Check ALDPS bit, disable it if enabled */ - rtl_writephy(tp, 0x1f, 0x0a43); - if (rtl_readphy(tp, 0x10) & 0x0004) - rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004); - - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168g_2_hw_phy_config(struct rtl8169_private *tp) -{ - rtl_apply_firmware(tp); -} - -static void rtl8168h_1_hw_phy_config(struct rtl8169_private *tp) -{ - u16 dout_tapbin; - u32 data; - - rtl_apply_firmware(tp); - - /* CHN EST parameters adjust - giga master */ - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x809b); - rtl_w0w1_phy(tp, 0x14, 0x8000, 0xf800); - rtl_writephy(tp, 0x13, 0x80a2); - rtl_w0w1_phy(tp, 0x14, 0x8000, 0xff00); - rtl_writephy(tp, 0x13, 0x80a4); - rtl_w0w1_phy(tp, 0x14, 0x8500, 0xff00); - rtl_writephy(tp, 0x13, 0x809c); - rtl_w0w1_phy(tp, 0x14, 0xbd00, 0xff00); - rtl_writephy(tp, 0x1f, 0x0000); - - /* CHN EST parameters adjust - giga slave */ - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x80ad); - rtl_w0w1_phy(tp, 0x14, 0x7000, 0xf800); - rtl_writephy(tp, 0x13, 0x80b4); - rtl_w0w1_phy(tp, 0x14, 0x5000, 0xff00); - rtl_writephy(tp, 0x13, 0x80ac); - rtl_w0w1_phy(tp, 0x14, 0x4000, 0xff00); - rtl_writephy(tp, 0x1f, 0x0000); - - /* CHN EST parameters adjust - fnet */ - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x808e); - rtl_w0w1_phy(tp, 0x14, 0x1200, 0xff00); - rtl_writephy(tp, 0x13, 0x8090); - rtl_w0w1_phy(tp, 0x14, 0xe500, 0xff00); - rtl_writephy(tp, 0x13, 0x8092); - rtl_w0w1_phy(tp, 0x14, 0x9f00, 0xff00); - rtl_writephy(tp, 0x1f, 0x0000); - - /* enable R-tune & PGA-retune function */ - dout_tapbin = 0; - rtl_writephy(tp, 0x1f, 0x0a46); - data = rtl_readphy(tp, 0x13); - data &= 3; - data <<= 2; - dout_tapbin |= data; - data = rtl_readphy(tp, 0x12); - data &= 0xc000; - data >>= 14; - dout_tapbin |= data; - dout_tapbin = ~(dout_tapbin^0x08); - dout_tapbin <<= 12; - dout_tapbin &= 0xf000; - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x827a); - rtl_w0w1_phy(tp, 0x14, dout_tapbin, 0xf000); - rtl_writephy(tp, 0x13, 0x827b); - rtl_w0w1_phy(tp, 0x14, dout_tapbin, 0xf000); - rtl_writephy(tp, 0x13, 0x827c); - rtl_w0w1_phy(tp, 0x14, dout_tapbin, 0xf000); - rtl_writephy(tp, 0x13, 0x827d); - rtl_w0w1_phy(tp, 0x14, dout_tapbin, 0xf000); - - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x0811); - rtl_w0w1_phy(tp, 0x14, 0x0800, 0x0000); - rtl_writephy(tp, 0x1f, 0x0a42); - rtl_w0w1_phy(tp, 0x16, 0x0002, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* enable GPHY 10M */ - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w0w1_phy(tp, 0x11, 0x0800, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* SAR ADC performance */ - rtl_writephy(tp, 0x1f, 0x0bca); - rtl_w0w1_phy(tp, 0x17, 0x4000, 0x3000); - rtl_writephy(tp, 0x1f, 0x0000); - - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x803f); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000); - rtl_writephy(tp, 0x13, 0x8047); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000); - rtl_writephy(tp, 0x13, 0x804f); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000); - rtl_writephy(tp, 0x13, 0x8057); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000); - rtl_writephy(tp, 0x13, 0x805f); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000); - rtl_writephy(tp, 0x13, 0x8067); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000); - rtl_writephy(tp, 0x13, 0x806f); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x3000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* disable phy pfm mode */ - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x0080); - rtl_writephy(tp, 0x1f, 0x0000); - - /* Check ALDPS bit, disable it if enabled */ - rtl_writephy(tp, 0x1f, 0x0a43); - if (rtl_readphy(tp, 0x10) & 0x0004) - rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004); - - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168h_2_hw_phy_config(struct rtl8169_private *tp) -{ - u16 ioffset_p3, ioffset_p2, ioffset_p1, ioffset_p0; - u16 rlen; - u32 data; - - rtl_apply_firmware(tp); - - /* CHIN EST parameter update */ - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x808a); - rtl_w0w1_phy(tp, 0x14, 0x000a, 0x003f); - rtl_writephy(tp, 0x1f, 0x0000); - - /* enable R-tune & PGA-retune function */ - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x0811); - rtl_w0w1_phy(tp, 0x14, 0x0800, 0x0000); - rtl_writephy(tp, 0x1f, 0x0a42); - rtl_w0w1_phy(tp, 0x16, 0x0002, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* enable GPHY 10M */ - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w0w1_phy(tp, 0x11, 0x0800, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - r8168_mac_ocp_write(tp, 0xdd02, 0x807d); - data = r8168_mac_ocp_read(tp, 0xdd02); - ioffset_p3 = ((data & 0x80)>>7); - ioffset_p3 <<= 3; - - data = r8168_mac_ocp_read(tp, 0xdd00); - ioffset_p3 |= ((data & (0xe000))>>13); - ioffset_p2 = ((data & (0x1e00))>>9); - ioffset_p1 = ((data & (0x01e0))>>5); - ioffset_p0 = ((data & 0x0010)>>4); - ioffset_p0 <<= 3; - ioffset_p0 |= (data & (0x07)); - data = (ioffset_p3<<12)|(ioffset_p2<<8)|(ioffset_p1<<4)|(ioffset_p0); - - if ((ioffset_p3 != 0x0f) || (ioffset_p2 != 0x0f) || - (ioffset_p1 != 0x0f) || (ioffset_p0 == 0x0f)) { - rtl_writephy(tp, 0x1f, 0x0bcf); - rtl_writephy(tp, 0x16, data); - rtl_writephy(tp, 0x1f, 0x0000); - } - - /* Modify rlen (TX LPF corner frequency) level */ - rtl_writephy(tp, 0x1f, 0x0bcd); - data = rtl_readphy(tp, 0x16); - data &= 0x000f; - rlen = 0; - if (data > 3) - rlen = data - 3; - data = rlen | (rlen<<4) | (rlen<<8) | (rlen<<12); - rtl_writephy(tp, 0x17, data); - rtl_writephy(tp, 0x1f, 0x0bcd); - rtl_writephy(tp, 0x1f, 0x0000); - - /* disable phy pfm mode */ - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x0080); - rtl_writephy(tp, 0x1f, 0x0000); - - /* Check ALDPS bit, disable it if enabled */ - rtl_writephy(tp, 0x1f, 0x0a43); - if (rtl_readphy(tp, 0x10) & 0x0004) - rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004); - - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168ep_1_hw_phy_config(struct rtl8169_private *tp) -{ - /* Enable PHY auto speed down */ - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w0w1_phy(tp, 0x11, 0x000c, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* patch 10M & ALDPS */ - rtl_writephy(tp, 0x1f, 0x0bcc); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x0100); - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w0w1_phy(tp, 0x11, 0x00c0, 0x0000); - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x8084); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x6000); - rtl_w0w1_phy(tp, 0x10, 0x1003, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* Enable EEE auto-fallback function */ - rtl_writephy(tp, 0x1f, 0x0a4b); - rtl_w0w1_phy(tp, 0x11, 0x0004, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* Enable UC LPF tune function */ - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x8012); - rtl_w0w1_phy(tp, 0x14, 0x8000, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* set rg_sel_sdm_rate */ - rtl_writephy(tp, 0x1f, 0x0c42); - rtl_w0w1_phy(tp, 0x11, 0x4000, 0x2000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* Check ALDPS bit, disable it if enabled */ - rtl_writephy(tp, 0x1f, 0x0a43); - if (rtl_readphy(tp, 0x10) & 0x0004) - rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004); - - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8168ep_2_hw_phy_config(struct rtl8169_private *tp) -{ - /* patch 10M & ALDPS */ - rtl_writephy(tp, 0x1f, 0x0bcc); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x0100); - rtl_writephy(tp, 0x1f, 0x0a44); - rtl_w0w1_phy(tp, 0x11, 0x00c0, 0x0000); - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x8084); - rtl_w0w1_phy(tp, 0x14, 0x0000, 0x6000); - rtl_w0w1_phy(tp, 0x10, 0x1003, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* Enable UC LPF tune function */ - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x8012); - rtl_w0w1_phy(tp, 0x14, 0x8000, 0x0000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* Set rg_sel_sdm_rate */ - rtl_writephy(tp, 0x1f, 0x0c42); - rtl_w0w1_phy(tp, 0x11, 0x4000, 0x2000); - rtl_writephy(tp, 0x1f, 0x0000); - - /* Channel estimation parameters */ - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x80f3); - rtl_w0w1_phy(tp, 0x14, 0x8b00, ~0x8bff); - rtl_writephy(tp, 0x13, 0x80f0); - rtl_w0w1_phy(tp, 0x14, 0x3a00, ~0x3aff); - rtl_writephy(tp, 0x13, 0x80ef); - rtl_w0w1_phy(tp, 0x14, 0x0500, ~0x05ff); - rtl_writephy(tp, 0x13, 0x80f6); - rtl_w0w1_phy(tp, 0x14, 0x6e00, ~0x6eff); - rtl_writephy(tp, 0x13, 0x80ec); - rtl_w0w1_phy(tp, 0x14, 0x6800, ~0x68ff); - rtl_writephy(tp, 0x13, 0x80ed); - rtl_w0w1_phy(tp, 0x14, 0x7c00, ~0x7cff); - rtl_writephy(tp, 0x13, 0x80f2); - rtl_w0w1_phy(tp, 0x14, 0xf400, ~0xf4ff); - rtl_writephy(tp, 0x13, 0x80f4); - rtl_w0w1_phy(tp, 0x14, 0x8500, ~0x85ff); - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x8110); - rtl_w0w1_phy(tp, 0x14, 0xa800, ~0xa8ff); - rtl_writephy(tp, 0x13, 0x810f); - rtl_w0w1_phy(tp, 0x14, 0x1d00, ~0x1dff); - rtl_writephy(tp, 0x13, 0x8111); - rtl_w0w1_phy(tp, 0x14, 0xf500, ~0xf5ff); - rtl_writephy(tp, 0x13, 0x8113); - rtl_w0w1_phy(tp, 0x14, 0x6100, ~0x61ff); - rtl_writephy(tp, 0x13, 0x8115); - rtl_w0w1_phy(tp, 0x14, 0x9200, ~0x92ff); - rtl_writephy(tp, 0x13, 0x810e); - rtl_w0w1_phy(tp, 0x14, 0x0400, ~0x04ff); - rtl_writephy(tp, 0x13, 0x810c); - rtl_w0w1_phy(tp, 0x14, 0x7c00, ~0x7cff); - rtl_writephy(tp, 0x13, 0x810b); - rtl_w0w1_phy(tp, 0x14, 0x5a00, ~0x5aff); - rtl_writephy(tp, 0x1f, 0x0a43); - rtl_writephy(tp, 0x13, 0x80d1); - rtl_w0w1_phy(tp, 0x14, 0xff00, ~0xffff); - rtl_writephy(tp, 0x13, 0x80cd); - rtl_w0w1_phy(tp, 0x14, 0x9e00, ~0x9eff); - rtl_writephy(tp, 0x13, 0x80d3); - rtl_w0w1_phy(tp, 0x14, 0x0e00, ~0x0eff); - rtl_writephy(tp, 0x13, 0x80d5); - rtl_w0w1_phy(tp, 0x14, 0xca00, ~0xcaff); - rtl_writephy(tp, 0x13, 0x80d7); - rtl_w0w1_phy(tp, 0x14, 0x8400, ~0x84ff); - - /* Force PWM-mode */ - rtl_writephy(tp, 0x1f, 0x0bcd); - rtl_writephy(tp, 0x14, 0x5065); - rtl_writephy(tp, 0x14, 0xd065); - rtl_writephy(tp, 0x1f, 0x0bc8); - rtl_writephy(tp, 0x12, 0x00ed); - rtl_writephy(tp, 0x1f, 0x0bcd); - rtl_writephy(tp, 0x14, 0x1065); - rtl_writephy(tp, 0x14, 0x9065); - rtl_writephy(tp, 0x14, 0x1065); - rtl_writephy(tp, 0x1f, 0x0000); - - /* Check ALDPS bit, disable it if enabled */ - rtl_writephy(tp, 0x1f, 0x0a43); - if (rtl_readphy(tp, 0x10) & 0x0004) - rtl_w0w1_phy(tp, 0x10, 0x0000, 0x0004); - - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8102e_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0003 }, - { 0x08, 0x441d }, - { 0x01, 0x9100 }, - { 0x1f, 0x0000 } - }; - - rtl_writephy(tp, 0x1f, 0x0000); - rtl_patchphy(tp, 0x11, 1 << 12); - rtl_patchphy(tp, 0x19, 1 << 13); - rtl_patchphy(tp, 0x10, 1 << 15); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8105e_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0005 }, - { 0x1a, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0004 }, - { 0x1c, 0x0000 }, - { 0x1f, 0x0000 }, - - { 0x1f, 0x0001 }, - { 0x15, 0x7701 }, - { 0x1f, 0x0000 } - }; - - /* Disable ALDPS before ram code */ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x18, 0x0310); - msleep(100); - - rtl_apply_firmware(tp); - - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); -} - -static void rtl8402_hw_phy_config(struct rtl8169_private *tp) -{ - /* Disable ALDPS before setting firmware */ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x18, 0x0310); - msleep(20); - - rtl_apply_firmware(tp); - - /* EEE setting */ - rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_writephy(tp, 0x1f, 0x0004); - rtl_writephy(tp, 0x10, 0x401f); - rtl_writephy(tp, 0x19, 0x7030); - rtl_writephy(tp, 0x1f, 0x0000); -} - -static void rtl8106e_hw_phy_config(struct rtl8169_private *tp) -{ - static const struct phy_reg phy_reg_init[] = { - { 0x1f, 0x0004 }, - { 0x10, 0xc07f }, - { 0x19, 0x7030 }, - { 0x1f, 0x0000 } - }; - - /* Disable ALDPS before ram code */ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, 0x18, 0x0310); - msleep(100); - - rtl_apply_firmware(tp); - - rtl_eri_write(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); - - rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); -} - -static void rtl_hw_phy_config(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_print_mac_version(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - break; - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - rtl8169s_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_04: - rtl8169sb_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_05: - rtl8169scd_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_06: - rtl8169sce_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - rtl8102e_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_11: - rtl8168bb_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_12: - rtl8168bef_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_17: - rtl8168bef_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_18: - rtl8168cp_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_19: - rtl8168c_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_20: - rtl8168c_2_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_21: - rtl8168c_3_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_22: - rtl8168c_4_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - rtl8168cp_2_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_25: - rtl8168d_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_26: - rtl8168d_2_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_27: - rtl8168d_3_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_28: - rtl8168d_4_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_29: - case RTL_GIGA_MAC_VER_30: - rtl8105e_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_31: - /* None. */ - break; - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - rtl8168e_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_34: - rtl8168e_2_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_35: - rtl8168f_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_36: - rtl8168f_2_hw_phy_config(tp); - break; - - case RTL_GIGA_MAC_VER_37: - rtl8402_hw_phy_config(tp); - break; - - case RTL_GIGA_MAC_VER_38: - rtl8411_hw_phy_config(tp); - break; - - case RTL_GIGA_MAC_VER_39: - rtl8106e_hw_phy_config(tp); - break; - - case RTL_GIGA_MAC_VER_40: - rtl8168g_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - case RTL_GIGA_MAC_VER_44: - rtl8168g_2_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_45: - case RTL_GIGA_MAC_VER_47: - rtl8168h_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_46: - case RTL_GIGA_MAC_VER_48: - rtl8168h_2_hw_phy_config(tp); - break; - - case RTL_GIGA_MAC_VER_49: - rtl8168ep_1_hw_phy_config(tp); - break; - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - rtl8168ep_2_hw_phy_config(tp); - break; - - case RTL_GIGA_MAC_VER_41: - default: - break; - } -} - -static void rtl_phy_work(struct rtl8169_private *tp) -{ - struct timer_list *timer = &tp->timer; - void __iomem *ioaddr = tp->mmio_addr; - unsigned long timeout = RTL8169_PHY_TIMEOUT; - - assert(tp->mac_version > RTL_GIGA_MAC_VER_01); - - if (tp->phy_reset_pending(tp)) { - /* - * A busy loop could burn quite a few cycles on nowadays CPU. - * Let's delay the execution of the timer for a few ticks. - */ - timeout = HZ/10; - goto out_mod_timer; - } - - if (tp->link_ok(ioaddr)) - return; - - netif_dbg(tp, link, tp->dev, "PHY reset until link up\n"); - - tp->phy_reset_enable(tp); - -out_mod_timer: - mod_timer(timer, jiffies + timeout); -} - -static void rtl_schedule_task(struct rtl8169_private *tp, enum rtl_flag flag) -{ - if (!test_and_set_bit(flag, tp->wk.flags)) - schedule_work(&tp->wk.work); -} - -static void rtl8169_phy_timer(unsigned long __opaque) -{ - struct net_device *dev = (struct net_device *)__opaque; - struct rtl8169_private *tp = netdev_priv(dev); - - rtl_schedule_task(tp, RTL_FLAG_TASK_PHY_PENDING); -} - -static void rtl8169_release_board(struct pci_dev *pdev, struct net_device *dev, - void __iomem *ioaddr) -{ - iounmap(ioaddr); - pci_release_regions(pdev); - pci_clear_mwi(pdev); - pci_disable_device(pdev); - free_netdev(dev); -} - -DECLARE_RTL_COND(rtl_phy_reset_cond) -{ - return tp->phy_reset_pending(tp); -} - -static void rtl8169_phy_reset(struct net_device *dev, - struct rtl8169_private *tp) -{ - tp->phy_reset_enable(tp); - rtl_msleep_loop_wait_low(tp, &rtl_phy_reset_cond, 1, 100); -} - -static bool rtl_tbi_enabled(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return (tp->mac_version == RTL_GIGA_MAC_VER_01) && - (RTL_R8(PHYstatus) & TBI_Enable); -} - -static void rtl8169_init_phy(struct net_device *dev, struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_phy_config(dev); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - } - - pci_write_config_byte(tp->pci_dev, PCI_LATENCY_TIMER, 0x40); - - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - pci_write_config_byte(tp->pci_dev, PCI_CACHE_LINE_SIZE, 0x08); - - if (tp->mac_version == RTL_GIGA_MAC_VER_02) { - dprintk("Set MAC Reg C+CR Offset 0x82h = 0x01h\n"); - RTL_W8(0x82, 0x01); - dprintk("Set PHY Reg 0x0bh = 0x00h\n"); - rtl_writephy(tp, 0x0b, 0x0000); //w 0x0b 15 0 0 - } - - rtl8169_phy_reset(dev, tp); - - rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL, - ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | - (tp->mii.supports_gmii ? - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full : 0)); - - if (rtl_tbi_enabled(tp)) - netif_info(tp, link, dev, "TBI auto-negotiating\n"); -} - -static void rtl_rar_set(struct rtl8169_private *tp, u8 *addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_lock_work(tp); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W32(MAC4, addr[4] | addr[5] << 8); - RTL_R32(MAC4); - - RTL_W32(MAC0, addr[0] | addr[1] << 8 | addr[2] << 16 | addr[3] << 24); - RTL_R32(MAC0); - - if (tp->mac_version == RTL_GIGA_MAC_VER_34) - rtl_rar_exgmac_set(tp, addr); - - RTL_W8(Cfg9346, Cfg9346_Lock); - - rtl_unlock_work(tp); -} - -static int rtl_set_mac_address(struct net_device *dev, void *p) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct sockaddr *addr = p; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, dev->addr_len); - - rtl_rar_set(tp, dev->dev_addr); - - return 0; -} - -static int rtl8169_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct mii_ioctl_data *data = if_mii(ifr); - - return netif_running(dev) ? tp->do_ioctl(tp, data, cmd) : -ENODEV; -} - -static int rtl_xmii_ioctl(struct rtl8169_private *tp, - struct mii_ioctl_data *data, int cmd) -{ - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = 32; /* Internal PHY */ - return 0; - - case SIOCGMIIREG: - data->val_out = rtl_readphy(tp, data->reg_num & 0x1f); - return 0; - - case SIOCSMIIREG: - rtl_writephy(tp, data->reg_num & 0x1f, data->val_in); - return 0; - } - return -EOPNOTSUPP; -} - -static int rtl_tbi_ioctl(struct rtl8169_private *tp, struct mii_ioctl_data *data, int cmd) -{ - return -EOPNOTSUPP; -} - -static void rtl_disable_msi(struct pci_dev *pdev, struct rtl8169_private *tp) -{ - if (tp->features & RTL_FEATURE_MSI) { - pci_disable_msi(pdev); - tp->features &= ~RTL_FEATURE_MSI; - } -} - -static void rtl_init_mdio_ops(struct rtl8169_private *tp) -{ - struct mdio_ops *ops = &tp->mdio_ops; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_27: - ops->write = r8168dp_1_mdio_write; - ops->read = r8168dp_1_mdio_read; - break; - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - ops->write = r8168dp_2_mdio_write; - ops->read = r8168dp_2_mdio_read; - break; - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - case RTL_GIGA_MAC_VER_44: - case RTL_GIGA_MAC_VER_45: - case RTL_GIGA_MAC_VER_46: - case RTL_GIGA_MAC_VER_47: - case RTL_GIGA_MAC_VER_48: - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - ops->write = r8168g_mdio_write; - ops->read = r8168g_mdio_read; - break; - default: - ops->write = r8169_mdio_write; - ops->read = r8169_mdio_read; - break; - } -} - -static void rtl_speed_down(struct rtl8169_private *tp) -{ - u32 adv; - int lpa; - - rtl_writephy(tp, 0x1f, 0x0000); - lpa = rtl_readphy(tp, MII_LPA); - - if (lpa & (LPA_10HALF | LPA_10FULL)) - adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full; - else if (lpa & (LPA_100HALF | LPA_100FULL)) - adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full; - else - adv = ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full | - ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full | - (tp->mii.supports_gmii ? - ADVERTISED_1000baseT_Half | - ADVERTISED_1000baseT_Full : 0); - - rtl8169_set_speed(tp->dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL, - adv); -} - -static void rtl_wol_suspend_quirk(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_29: - case RTL_GIGA_MAC_VER_30: - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_37: - case RTL_GIGA_MAC_VER_38: - case RTL_GIGA_MAC_VER_39: - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - case RTL_GIGA_MAC_VER_44: - case RTL_GIGA_MAC_VER_45: - case RTL_GIGA_MAC_VER_46: - case RTL_GIGA_MAC_VER_47: - case RTL_GIGA_MAC_VER_48: - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - RTL_W32(RxConfig, RTL_R32(RxConfig) | - AcceptBroadcast | AcceptMulticast | AcceptMyPhys); - break; - default: - break; - } -} - -static bool rtl_wol_pll_power_down(struct rtl8169_private *tp) -{ - if (!(__rtl8169_get_wol(tp) & WAKE_ANY)) - return false; - - rtl_speed_down(tp); - rtl_wol_suspend_quirk(tp); - - return true; -} - -static void r810x_phy_power_down(struct rtl8169_private *tp) -{ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, MII_BMCR, BMCR_PDOWN); -} - -static void r810x_phy_power_up(struct rtl8169_private *tp) -{ - rtl_writephy(tp, 0x1f, 0x0000); - rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE); -} - -static void r810x_pll_power_down(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if (rtl_wol_pll_power_down(tp)) - return; - - r810x_phy_power_down(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - case RTL_GIGA_MAC_VER_10: - case RTL_GIGA_MAC_VER_13: - case RTL_GIGA_MAC_VER_16: - break; - default: - RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80); - break; - } -} - -static void r810x_pll_power_up(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - r810x_phy_power_up(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - case RTL_GIGA_MAC_VER_10: - case RTL_GIGA_MAC_VER_13: - case RTL_GIGA_MAC_VER_16: - break; - case RTL_GIGA_MAC_VER_47: - case RTL_GIGA_MAC_VER_48: - RTL_W8(PMCH, RTL_R8(PMCH) | 0xc0); - break; - default: - RTL_W8(PMCH, RTL_R8(PMCH) | 0x80); - break; - } -} - -static void r8168_phy_power_up(struct rtl8169_private *tp) -{ - rtl_writephy(tp, 0x1f, 0x0000); - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - case RTL_GIGA_MAC_VER_18: - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - rtl_writephy(tp, 0x0e, 0x0000); - break; - default: - break; - } - rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE); -} - -static void r8168_phy_power_down(struct rtl8169_private *tp) -{ - rtl_writephy(tp, 0x1f, 0x0000); - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - rtl_writephy(tp, MII_BMCR, BMCR_ANENABLE | BMCR_PDOWN); - break; - - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - case RTL_GIGA_MAC_VER_18: - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - rtl_writephy(tp, 0x0e, 0x0200); - default: - rtl_writephy(tp, MII_BMCR, BMCR_PDOWN); - break; - } -} - -static void r8168_pll_power_down(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - if ((tp->mac_version == RTL_GIGA_MAC_VER_27 || - tp->mac_version == RTL_GIGA_MAC_VER_28 || - tp->mac_version == RTL_GIGA_MAC_VER_31 || - tp->mac_version == RTL_GIGA_MAC_VER_49 || - tp->mac_version == RTL_GIGA_MAC_VER_50 || - tp->mac_version == RTL_GIGA_MAC_VER_51) && - r8168_check_dash(tp)) { - return; - } - - if ((tp->mac_version == RTL_GIGA_MAC_VER_23 || - tp->mac_version == RTL_GIGA_MAC_VER_24) && - (RTL_R16(CPlusCmd) & ASF)) { - return; - } - - if (tp->mac_version == RTL_GIGA_MAC_VER_32 || - tp->mac_version == RTL_GIGA_MAC_VER_33) - rtl_ephy_write(tp, 0x19, 0xff64); - - if (rtl_wol_pll_power_down(tp)) - return; - - r8168_phy_power_down(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - case RTL_GIGA_MAC_VER_44: - case RTL_GIGA_MAC_VER_45: - case RTL_GIGA_MAC_VER_46: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80); - break; - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_49: - rtl_w0w1_eri(tp, 0x1a8, ERIAR_MASK_1111, 0x00000000, - 0xfc000000, ERIAR_EXGMAC); - RTL_W8(PMCH, RTL_R8(PMCH) & ~0x80); - break; - } -} - -static void r8168_pll_power_up(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - RTL_W8(PMCH, RTL_R8(PMCH) | 0x80); - break; - case RTL_GIGA_MAC_VER_44: - case RTL_GIGA_MAC_VER_45: - case RTL_GIGA_MAC_VER_46: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - RTL_W8(PMCH, RTL_R8(PMCH) | 0xc0); - break; - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_49: - RTL_W8(PMCH, RTL_R8(PMCH) | 0xc0); - rtl_w0w1_eri(tp, 0x1a8, ERIAR_MASK_1111, 0xfc000000, - 0x00000000, ERIAR_EXGMAC); - break; - } - - r8168_phy_power_up(tp); -} - -static void rtl_generic_op(struct rtl8169_private *tp, - void (*op)(struct rtl8169_private *)) -{ - if (op) - op(tp); -} - -static void rtl_pll_power_down(struct rtl8169_private *tp) -{ - rtl_generic_op(tp, tp->pll_power_ops.down); -} - -static void rtl_pll_power_up(struct rtl8169_private *tp) -{ - rtl_generic_op(tp, tp->pll_power_ops.up); - - /* give MAC/PHY some time to resume */ - msleep(20); -} - -static void rtl_init_pll_power_ops(struct rtl8169_private *tp) -{ - struct pll_power_ops *ops = &tp->pll_power_ops; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - case RTL_GIGA_MAC_VER_08: - case RTL_GIGA_MAC_VER_09: - case RTL_GIGA_MAC_VER_10: - case RTL_GIGA_MAC_VER_16: - case RTL_GIGA_MAC_VER_29: - case RTL_GIGA_MAC_VER_30: - case RTL_GIGA_MAC_VER_37: - case RTL_GIGA_MAC_VER_39: - case RTL_GIGA_MAC_VER_43: - case RTL_GIGA_MAC_VER_47: - case RTL_GIGA_MAC_VER_48: - ops->down = r810x_pll_power_down; - ops->up = r810x_pll_power_up; - break; - - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - case RTL_GIGA_MAC_VER_18: - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - case RTL_GIGA_MAC_VER_31: - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_35: - case RTL_GIGA_MAC_VER_36: - case RTL_GIGA_MAC_VER_38: - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_44: - case RTL_GIGA_MAC_VER_45: - case RTL_GIGA_MAC_VER_46: - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - ops->down = r8168_pll_power_down; - ops->up = r8168_pll_power_up; - break; - - default: - ops->down = NULL; - ops->up = NULL; - break; - } -} - -static void rtl_init_rxcfg(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - case RTL_GIGA_MAC_VER_04: - case RTL_GIGA_MAC_VER_05: - case RTL_GIGA_MAC_VER_06: - case RTL_GIGA_MAC_VER_10: - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_13: - case RTL_GIGA_MAC_VER_14: - case RTL_GIGA_MAC_VER_15: - case RTL_GIGA_MAC_VER_16: - case RTL_GIGA_MAC_VER_17: - RTL_W32(RxConfig, RX_FIFO_THRESH | RX_DMA_BURST); - break; - case RTL_GIGA_MAC_VER_18: - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_35: - RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST); - break; - case RTL_GIGA_MAC_VER_40: - RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF); - break; - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - case RTL_GIGA_MAC_VER_44: - case RTL_GIGA_MAC_VER_45: - case RTL_GIGA_MAC_VER_46: - case RTL_GIGA_MAC_VER_47: - case RTL_GIGA_MAC_VER_48: - RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST | RX_EARLY_OFF); - break; - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - RTL_W32(RxConfig, RX128_INT_EN | RX_MULTI_EN | RX_DMA_BURST | RX_EARLY_OFF); - break; - default: - RTL_W32(RxConfig, RX128_INT_EN | RX_DMA_BURST); - break; - } -} - -static void rtl8169_init_ring_indexes(struct rtl8169_private *tp) -{ - tp->dirty_tx = tp->cur_tx = tp->cur_rx = 0; -} - -static void rtl_hw_jumbo_enable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - rtl_generic_op(tp, tp->jumbo_ops.enable); - RTL_W8(Cfg9346, Cfg9346_Lock); -} - -static void rtl_hw_jumbo_disable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - rtl_generic_op(tp, tp->jumbo_ops.disable); - RTL_W8(Cfg9346, Cfg9346_Lock); -} - -static void r8168c_hw_jumbo_enable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); - RTL_W8(Config4, RTL_R8(Config4) | Jumbo_En1); - rtl_tx_performance_tweak(tp->pci_dev, PCI_EXP_DEVCTL_READRQ_512B); -} - -static void r8168c_hw_jumbo_disable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); - RTL_W8(Config4, RTL_R8(Config4) & ~Jumbo_En1); - rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); -} - -static void r8168dp_hw_jumbo_enable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); -} - -static void r8168dp_hw_jumbo_disable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); -} - -static void r8168e_hw_jumbo_enable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(MaxTxPacketSize, 0x3f); - RTL_W8(Config3, RTL_R8(Config3) | Jumbo_En0); - RTL_W8(Config4, RTL_R8(Config4) | 0x01); - rtl_tx_performance_tweak(tp->pci_dev, PCI_EXP_DEVCTL_READRQ_512B); -} - -static void r8168e_hw_jumbo_disable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(MaxTxPacketSize, 0x0c); - RTL_W8(Config3, RTL_R8(Config3) & ~Jumbo_En0); - RTL_W8(Config4, RTL_R8(Config4) & ~0x01); - rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); -} - -static void r8168b_0_hw_jumbo_enable(struct rtl8169_private *tp) -{ - rtl_tx_performance_tweak(tp->pci_dev, - PCI_EXP_DEVCTL_READRQ_512B | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void r8168b_0_hw_jumbo_disable(struct rtl8169_private *tp) -{ - rtl_tx_performance_tweak(tp->pci_dev, - (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); -} - -static void r8168b_1_hw_jumbo_enable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - r8168b_0_hw_jumbo_enable(tp); - - RTL_W8(Config4, RTL_R8(Config4) | (1 << 0)); -} - -static void r8168b_1_hw_jumbo_disable(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - r8168b_0_hw_jumbo_disable(tp); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void rtl_init_jumbo_ops(struct rtl8169_private *tp) -{ - struct jumbo_ops *ops = &tp->jumbo_ops; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - ops->disable = r8168b_0_hw_jumbo_disable; - ops->enable = r8168b_0_hw_jumbo_enable; - break; - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - ops->disable = r8168b_1_hw_jumbo_disable; - ops->enable = r8168b_1_hw_jumbo_enable; - break; - case RTL_GIGA_MAC_VER_18: /* Wild guess. Needs info from Realtek. */ - case RTL_GIGA_MAC_VER_19: - case RTL_GIGA_MAC_VER_20: - case RTL_GIGA_MAC_VER_21: /* Wild guess. Needs info from Realtek. */ - case RTL_GIGA_MAC_VER_22: - case RTL_GIGA_MAC_VER_23: - case RTL_GIGA_MAC_VER_24: - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - ops->disable = r8168c_hw_jumbo_disable; - ops->enable = r8168c_hw_jumbo_enable; - break; - case RTL_GIGA_MAC_VER_27: - case RTL_GIGA_MAC_VER_28: - ops->disable = r8168dp_hw_jumbo_disable; - ops->enable = r8168dp_hw_jumbo_enable; - break; - case RTL_GIGA_MAC_VER_31: /* Wild guess. Needs info from Realtek. */ - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - case RTL_GIGA_MAC_VER_34: - ops->disable = r8168e_hw_jumbo_disable; - ops->enable = r8168e_hw_jumbo_enable; - break; - - /* - * No action needed for jumbo frames with 8169. - * No jumbo for 810x at all. - */ - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - case RTL_GIGA_MAC_VER_44: - case RTL_GIGA_MAC_VER_45: - case RTL_GIGA_MAC_VER_46: - case RTL_GIGA_MAC_VER_47: - case RTL_GIGA_MAC_VER_48: - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - default: - ops->disable = NULL; - ops->enable = NULL; - break; - } -} - -DECLARE_RTL_COND(rtl_chipcmd_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R8(ChipCmd) & CmdReset; -} - -static void rtl_hw_reset(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(ChipCmd, CmdReset); - - rtl_udelay_loop_wait_low(tp, &rtl_chipcmd_cond, 100, 100); -} - -static void rtl_request_uncached_firmware(struct rtl8169_private *tp) -{ - struct rtl_fw *rtl_fw; - const char *name; - int rc = -ENOMEM; - - name = rtl_lookup_firmware_name(tp); - if (!name) - goto out_no_firmware; - - rtl_fw = kzalloc(sizeof(*rtl_fw), GFP_KERNEL); - if (!rtl_fw) - goto err_warn; - - rc = request_firmware(&rtl_fw->fw, name, &tp->pci_dev->dev); - if (rc < 0) - goto err_free; - - rc = rtl_check_firmware(tp, rtl_fw); - if (rc < 0) - goto err_release_firmware; - - tp->rtl_fw = rtl_fw; -out: - return; - -err_release_firmware: - release_firmware(rtl_fw->fw); -err_free: - kfree(rtl_fw); -err_warn: - netif_warn(tp, ifup, tp->dev, "unable to load firmware patch %s (%d)\n", - name, rc); -out_no_firmware: - tp->rtl_fw = NULL; - goto out; -} - -static void rtl_request_firmware(struct rtl8169_private *tp) -{ - if (IS_ERR(tp->rtl_fw)) - rtl_request_uncached_firmware(tp); -} - -static void rtl_rx_close(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(RxConfig, RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK); -} - -DECLARE_RTL_COND(rtl_npq_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R8(TxPoll) & NPQ; -} - -DECLARE_RTL_COND(rtl_txcfg_empty_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(TxConfig) & TXCFG_EMPTY; -} - -static void rtl8169_hw_reset(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - /* Disable interrupts */ - rtl8169_irq_mask_and_ack(tp); - - rtl_rx_close(tp); - - if (tp->mac_version == RTL_GIGA_MAC_VER_27 || - tp->mac_version == RTL_GIGA_MAC_VER_28 || - tp->mac_version == RTL_GIGA_MAC_VER_31) { - rtl_udelay_loop_wait_low(tp, &rtl_npq_cond, 20, 42*42); - } else if (tp->mac_version == RTL_GIGA_MAC_VER_34 || - tp->mac_version == RTL_GIGA_MAC_VER_35 || - tp->mac_version == RTL_GIGA_MAC_VER_36 || - tp->mac_version == RTL_GIGA_MAC_VER_37 || - tp->mac_version == RTL_GIGA_MAC_VER_38 || - tp->mac_version == RTL_GIGA_MAC_VER_40 || - tp->mac_version == RTL_GIGA_MAC_VER_41 || - tp->mac_version == RTL_GIGA_MAC_VER_42 || - tp->mac_version == RTL_GIGA_MAC_VER_43 || - tp->mac_version == RTL_GIGA_MAC_VER_44 || - tp->mac_version == RTL_GIGA_MAC_VER_45 || - tp->mac_version == RTL_GIGA_MAC_VER_46 || - tp->mac_version == RTL_GIGA_MAC_VER_47 || - tp->mac_version == RTL_GIGA_MAC_VER_48 || - tp->mac_version == RTL_GIGA_MAC_VER_49 || - tp->mac_version == RTL_GIGA_MAC_VER_50 || - tp->mac_version == RTL_GIGA_MAC_VER_51) { - RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq); - rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666); - } else { - RTL_W8(ChipCmd, RTL_R8(ChipCmd) | StopReq); - udelay(100); - } - - rtl_hw_reset(tp); -} - -static void rtl_set_rx_tx_config_registers(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - /* Set DMA burst size and Interframe Gap Time */ - RTL_W32(TxConfig, (TX_DMA_BURST << TxDMAShift) | - (InterFrameGap << TxInterFrameGapShift)); -} - -static void rtl_hw_start(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - tp->hw_start(dev); - - rtl_irq_enable_all(tp); -} - -static void rtl_set_rx_tx_desc_registers(struct rtl8169_private *tp, - void __iomem *ioaddr) -{ - /* - * Magic spell: some iop3xx ARM board needs the TxDescAddrHigh - * register to be written before TxDescAddrLow to work. - * Switching from MMIO to I/O access fixes the issue as well. - */ - RTL_W32(TxDescStartAddrHigh, ((u64) tp->TxPhyAddr) >> 32); - RTL_W32(TxDescStartAddrLow, ((u64) tp->TxPhyAddr) & DMA_BIT_MASK(32)); - RTL_W32(RxDescAddrHigh, ((u64) tp->RxPhyAddr) >> 32); - RTL_W32(RxDescAddrLow, ((u64) tp->RxPhyAddr) & DMA_BIT_MASK(32)); -} - -static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) -{ - u16 cmd; - - cmd = RTL_R16(CPlusCmd); - RTL_W16(CPlusCmd, cmd); - return cmd; -} - -static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) -{ - /* Low hurts. Let's disable the filtering. */ - RTL_W16(RxMaxSize, rx_buf_sz + 1); -} - -static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) -{ - static const struct rtl_cfg2_info { - u32 mac_version; - u32 clk; - u32 val; - } cfg2_info [] = { - { RTL_GIGA_MAC_VER_05, PCI_Clock_33MHz, 0x000fff00 }, // 8110SCd - { RTL_GIGA_MAC_VER_05, PCI_Clock_66MHz, 0x000fffff }, - { RTL_GIGA_MAC_VER_06, PCI_Clock_33MHz, 0x00ffff00 }, // 8110SCe - { RTL_GIGA_MAC_VER_06, PCI_Clock_66MHz, 0x00ffffff } - }; - const struct rtl_cfg2_info *p = cfg2_info; - unsigned int i; - u32 clk; - - clk = RTL_R8(Config2) & PCI_Clock_66MHz; - for (i = 0; i < ARRAY_SIZE(cfg2_info); i++, p++) { - if ((p->mac_version == mac_version) && (p->clk == clk)) { - RTL_W32(0x7c, p->val); - break; - } - } -} - -static void rtl_set_rx_mode(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - u32 mc_filter[2]; /* Multicast hash filter */ - int rx_mode; - u32 tmp = 0; - - if (dev->flags & IFF_PROMISC) { - /* Unconditionally log net taps. */ - netif_notice(tp, link, dev, "Promiscuous mode enabled\n"); - rx_mode = - AcceptBroadcast | AcceptMulticast | AcceptMyPhys | - AcceptAllPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else if ((netdev_mc_count(dev) > multicast_filter_limit) || - (dev->flags & IFF_ALLMULTI)) { - /* Too many to filter perfectly -- accept all multicasts. */ - rx_mode = AcceptBroadcast | AcceptMulticast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0xffffffff; - } else { - struct netdev_hw_addr *ha; - - rx_mode = AcceptBroadcast | AcceptMyPhys; - mc_filter[1] = mc_filter[0] = 0; - netdev_for_each_mc_addr(ha, dev) { - int bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26; - mc_filter[bit_nr >> 5] |= 1 << (bit_nr & 31); - rx_mode |= AcceptMulticast; - } - } - - if (dev->features & NETIF_F_RXALL) - rx_mode |= (AcceptErr | AcceptRunt); - - tmp = (RTL_R32(RxConfig) & ~RX_CONFIG_ACCEPT_MASK) | rx_mode; - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) { - u32 data = mc_filter[0]; - - mc_filter[0] = swab32(mc_filter[1]); - mc_filter[1] = swab32(data); - } - - if (tp->mac_version == RTL_GIGA_MAC_VER_35) - mc_filter[1] = mc_filter[0] = 0xffffffff; - - RTL_W32(MAR0 + 4, mc_filter[1]); - RTL_W32(MAR0 + 0, mc_filter[0]); - - RTL_W32(RxConfig, tmp); -} - -static void rtl_hw_start_8169(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version == RTL_GIGA_MAC_VER_05) { - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | PCIMulRW); - pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, 0x08); - } - - RTL_W8(Cfg9346, Cfg9346_Unlock); - if (tp->mac_version == RTL_GIGA_MAC_VER_01 || - tp->mac_version == RTL_GIGA_MAC_VER_02 || - tp->mac_version == RTL_GIGA_MAC_VER_03 || - tp->mac_version == RTL_GIGA_MAC_VER_04) - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - rtl_init_rxcfg(tp); - - RTL_W8(EarlyTxThres, NoEarlyTx); - - rtl_set_rx_max_size(ioaddr, rx_buf_sz); - - if (tp->mac_version == RTL_GIGA_MAC_VER_01 || - tp->mac_version == RTL_GIGA_MAC_VER_02 || - tp->mac_version == RTL_GIGA_MAC_VER_03 || - tp->mac_version == RTL_GIGA_MAC_VER_04) - rtl_set_rx_tx_config_registers(tp); - - tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; - - if (tp->mac_version == RTL_GIGA_MAC_VER_02 || - tp->mac_version == RTL_GIGA_MAC_VER_03) { - dprintk("Set MAC Reg C+CR Offset 0xe0. " - "Bit-3 and bit-14 MUST be 1\n"); - tp->cp_cmd |= (1 << 14); - } - - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl8169_set_magic_reg(ioaddr, tp->mac_version); - - /* - * Undocumented corner. Supposedly: - * (TxTimer << 12) | (TxPackets << 8) | (RxTimer << 4) | RxPackets - */ - RTL_W16(IntrMitigate, 0x0000); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - if (tp->mac_version != RTL_GIGA_MAC_VER_01 && - tp->mac_version != RTL_GIGA_MAC_VER_02 && - tp->mac_version != RTL_GIGA_MAC_VER_03 && - tp->mac_version != RTL_GIGA_MAC_VER_04) { - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - rtl_set_rx_tx_config_registers(tp); - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - /* Initially a 10 us delay. Turned it into a PCI commit. - FR */ - RTL_R8(IntrMask); - - RTL_W32(RxMissed, 0); - - rtl_set_rx_mode(dev); - - /* no early-rx interrupts */ - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); -} - -static void rtl_csi_write(struct rtl8169_private *tp, int addr, int value) -{ - if (tp->csi_ops.write) - tp->csi_ops.write(tp, addr, value); -} - -static u32 rtl_csi_read(struct rtl8169_private *tp, int addr) -{ - return tp->csi_ops.read ? tp->csi_ops.read(tp, addr) : ~0; -} - -static void rtl_csi_access_enable(struct rtl8169_private *tp, u32 bits) -{ - u32 csi; - - csi = rtl_csi_read(tp, 0x070c) & 0x00ffffff; - rtl_csi_write(tp, 0x070c, csi | bits); -} - -static void rtl_csi_access_enable_1(struct rtl8169_private *tp) -{ - rtl_csi_access_enable(tp, 0x17000000); -} - -static void rtl_csi_access_enable_2(struct rtl8169_private *tp) -{ - rtl_csi_access_enable(tp, 0x27000000); -} - -DECLARE_RTL_COND(rtl_csiar_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R32(CSIAR) & CSIAR_FLAG; -} - -static void r8169_csi_write(struct rtl8169_private *tp, int addr, int value) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100); -} - -static u32 r8169_csi_read(struct rtl8169_private *tp, int addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ? - RTL_R32(CSIDR) : ~0; -} - -static void r8402_csi_write(struct rtl8169_private *tp, int addr, int value) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT | - CSIAR_FUNC_NIC); - - rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100); -} - -static u32 r8402_csi_read(struct rtl8169_private *tp, int addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ? - RTL_R32(CSIDR) : ~0; -} - -static void r8411_csi_write(struct rtl8169_private *tp, int addr, int value) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(CSIDR, value); - RTL_W32(CSIAR, CSIAR_WRITE_CMD | (addr & CSIAR_ADDR_MASK) | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT | - CSIAR_FUNC_NIC2); - - rtl_udelay_loop_wait_low(tp, &rtl_csiar_cond, 10, 100); -} - -static u32 r8411_csi_read(struct rtl8169_private *tp, int addr) -{ - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W32(CSIAR, (addr & CSIAR_ADDR_MASK) | CSIAR_FUNC_NIC2 | - CSIAR_BYTE_ENABLE << CSIAR_BYTE_ENABLE_SHIFT); - - return rtl_udelay_loop_wait_high(tp, &rtl_csiar_cond, 10, 100) ? - RTL_R32(CSIDR) : ~0; -} - -static void rtl_init_csi_ops(struct rtl8169_private *tp) -{ - struct csi_ops *ops = &tp->csi_ops; - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_01: - case RTL_GIGA_MAC_VER_02: - case RTL_GIGA_MAC_VER_03: - case RTL_GIGA_MAC_VER_04: - case RTL_GIGA_MAC_VER_05: - case RTL_GIGA_MAC_VER_06: - case RTL_GIGA_MAC_VER_10: - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_13: - case RTL_GIGA_MAC_VER_14: - case RTL_GIGA_MAC_VER_15: - case RTL_GIGA_MAC_VER_16: - case RTL_GIGA_MAC_VER_17: - ops->write = NULL; - ops->read = NULL; - break; - - case RTL_GIGA_MAC_VER_37: - case RTL_GIGA_MAC_VER_38: - ops->write = r8402_csi_write; - ops->read = r8402_csi_read; - break; - - case RTL_GIGA_MAC_VER_44: - ops->write = r8411_csi_write; - ops->read = r8411_csi_read; - break; - - default: - ops->write = r8169_csi_write; - ops->read = r8169_csi_read; - break; - } -} - -struct ephy_info { - unsigned int offset; - u16 mask; - u16 bits; -}; - -static void rtl_ephy_init(struct rtl8169_private *tp, const struct ephy_info *e, - int len) -{ - u16 w; - - while (len-- > 0) { - w = (rtl_ephy_read(tp, e->offset) & ~e->mask) | e->bits; - rtl_ephy_write(tp, e->offset, w); - e++; - } -} - -static void rtl_disable_clock_request(struct pci_dev *pdev) -{ - pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_CLKREQ_EN); -} - -static void rtl_enable_clock_request(struct pci_dev *pdev) -{ - pcie_capability_set_word(pdev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_CLKREQ_EN); -} - -static void rtl_pcie_state_l2l3_enable(struct rtl8169_private *tp, bool enable) -{ - void __iomem *ioaddr = tp->mmio_addr; - u8 data; - - data = RTL_R8(Config3); - - if (enable) - data |= Rdy_to_L23; - else - data &= ~Rdy_to_L23; - - RTL_W8(Config3, data); -} - -#define R8168_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8168bb(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); - - if (tp->dev->mtu <= ETH_DATA_LEN) { - rtl_tx_performance_tweak(pdev, (0x5 << MAX_READ_REQUEST_SHIFT) | - PCI_EXP_DEVCTL_NOSNOOP_EN); - } -} - -static void rtl_hw_start_8168bef(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - rtl_hw_start_8168bb(tp); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - RTL_W8(Config4, RTL_R8(Config4) & ~(1 << 0)); -} - -static void __rtl_hw_start_8168cp(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W8(Config1, RTL_R8(Config1) | Speed_down); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_disable_clock_request(pdev); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_1(struct rtl8169_private *tp) -{ - static const struct ephy_info e_info_8168cp[] = { - { 0x01, 0, 0x0001 }, - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0042 }, - { 0x06, 0x0080, 0x0000 }, - { 0x07, 0, 0x2000 } - }; - - rtl_csi_access_enable_2(tp); - - rtl_ephy_init(tp, e_info_8168cp, ARRAY_SIZE(e_info_8168cp)); - - __rtl_hw_start_8168cp(tp); -} - -static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl_csi_access_enable_2(tp); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl_csi_access_enable_2(tp); - - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - /* Magic. */ - RTL_W8(DBG_REG, 0x20); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168c_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8168c_1[] = { - { 0x02, 0x0800, 0x1000 }, - { 0x03, 0, 0x0002 }, - { 0x06, 0x0080, 0x0000 } - }; - - rtl_csi_access_enable_2(tp); - - RTL_W8(DBG_REG, 0x06 | FIX_NAK_1 | FIX_NAK_2); - - rtl_ephy_init(tp, e_info_8168c_1, ARRAY_SIZE(e_info_8168c_1)); - - __rtl_hw_start_8168cp(tp); -} - -static void rtl_hw_start_8168c_2(struct rtl8169_private *tp) -{ - static const struct ephy_info e_info_8168c_2[] = { - { 0x01, 0, 0x0001 }, - { 0x03, 0x0400, 0x0220 } - }; - - rtl_csi_access_enable_2(tp); - - rtl_ephy_init(tp, e_info_8168c_2, ARRAY_SIZE(e_info_8168c_2)); - - __rtl_hw_start_8168cp(tp); -} - -static void rtl_hw_start_8168c_3(struct rtl8169_private *tp) -{ - rtl_hw_start_8168c_2(tp); -} - -static void rtl_hw_start_8168c_4(struct rtl8169_private *tp) -{ - rtl_csi_access_enable_2(tp); - - __rtl_hw_start_8168cp(tp); -} - -static void rtl_hw_start_8168d(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl_csi_access_enable_2(tp); - - rtl_disable_clock_request(pdev); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); -} - -static void rtl_hw_start_8168dp(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl_csi_access_enable_1(tp); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - rtl_disable_clock_request(pdev); -} - -static void rtl_hw_start_8168d_4(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - static const struct ephy_info e_info_8168d_4[] = { - { 0x0b, ~0, 0x48 }, - { 0x19, 0x20, 0x50 }, - { 0x0c, ~0, 0x20 } - }; - int i; - - rtl_csi_access_enable_1(tp); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - for (i = 0; i < ARRAY_SIZE(e_info_8168d_4); i++) { - const struct ephy_info *e = e_info_8168d_4 + i; - u16 w; - - w = rtl_ephy_read(tp, e->offset); - rtl_ephy_write(tp, 0x03, (w & e->mask) | e->bits); - } - - rtl_enable_clock_request(pdev); -} - -static void rtl_hw_start_8168e_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - static const struct ephy_info e_info_8168e_1[] = { - { 0x00, 0x0200, 0x0100 }, - { 0x00, 0x0000, 0x0004 }, - { 0x06, 0x0002, 0x0001 }, - { 0x06, 0x0000, 0x0030 }, - { 0x07, 0x0000, 0x2000 }, - { 0x00, 0x0000, 0x0020 }, - { 0x03, 0x5800, 0x2000 }, - { 0x03, 0x0000, 0x0001 }, - { 0x01, 0x0800, 0x1000 }, - { 0x07, 0x0000, 0x4000 }, - { 0x1e, 0x0000, 0x2000 }, - { 0x19, 0xffff, 0xfe6c }, - { 0x0a, 0x0000, 0x0040 } - }; - - rtl_csi_access_enable_2(tp); - - rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1)); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - rtl_disable_clock_request(pdev); - - /* Reset tx FIFO pointer */ - RTL_W32(MISC, RTL_R32(MISC) | TXPLA_RST); - RTL_W32(MISC, RTL_R32(MISC) & ~TXPLA_RST); - - RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); -} - -static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - static const struct ephy_info e_info_8168e_2[] = { - { 0x09, 0x0000, 0x0080 }, - { 0x19, 0x0000, 0x0224 } - }; - - rtl_csi_access_enable_1(tp); - - rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2)); - - if (tp->dev->mtu <= ETH_DATA_LEN) - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x07ff0060, ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC); - - RTL_W8(MaxTxPacketSize, EarlySize); - - rtl_disable_clock_request(pdev); - - RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); - RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); - - /* Adjust EEE LED frequency */ - RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); - - RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); - RTL_W32(MISC, RTL_R32(MISC) | PWM_EN); - RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); -} - -static void rtl_hw_start_8168f(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl_csi_access_enable_2(tp); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00100002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0x1d0, ERIAR_MASK_0001, 0x10, 0x00, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xcc, ERIAR_MASK_1111, 0x00000050, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xd0, ERIAR_MASK_1111, 0x00000060, ERIAR_EXGMAC); - - RTL_W8(MaxTxPacketSize, EarlySize); - - rtl_disable_clock_request(pdev); - - RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); - RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); - RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); - RTL_W32(MISC, RTL_R32(MISC) | PWM_EN); - RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); -} - -static void rtl_hw_start_8168f_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8168f_1[] = { - { 0x06, 0x00c0, 0x0020 }, - { 0x08, 0x0001, 0x0002 }, - { 0x09, 0x0000, 0x0080 }, - { 0x19, 0x0000, 0x0224 } - }; - - rtl_hw_start_8168f(tp); - - rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1)); - - rtl_w0w1_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0xff00, ERIAR_EXGMAC); - - /* Adjust EEE LED frequency */ - RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); -} - -static void rtl_hw_start_8411(struct rtl8169_private *tp) -{ - static const struct ephy_info e_info_8168f_1[] = { - { 0x06, 0x00c0, 0x0020 }, - { 0x0f, 0xffff, 0x5200 }, - { 0x1e, 0x0000, 0x4000 }, - { 0x19, 0x0000, 0x0224 } - }; - - rtl_hw_start_8168f(tp); - rtl_pcie_state_l2l3_enable(tp, false); - - rtl_ephy_init(tp, e_info_8168f_1, ARRAY_SIZE(e_info_8168f_1)); - - rtl_w0w1_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0c00, 0x0000, ERIAR_EXGMAC); -} - -static void rtl_hw_start_8168g(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); - - rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x080002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); - - rtl_csi_access_enable_1(tp); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); - rtl_eri_write(tp, 0x2f8, ERIAR_MASK_0011, 0x1d8f, ERIAR_EXGMAC); - - RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN); - RTL_W8(MaxTxPacketSize, EarlySize); - - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - - /* Adjust EEE LED frequency */ - RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); - - rtl_w0w1_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x06, ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC); - - rtl_pcie_state_l2l3_enable(tp, false); -} - -static void rtl_hw_start_8168g_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8168g_1[] = { - { 0x00, 0x0000, 0x0008 }, - { 0x0c, 0x37d0, 0x0820 }, - { 0x1e, 0x0000, 0x0001 }, - { 0x19, 0x8000, 0x0000 } - }; - - rtl_hw_start_8168g(tp); - - /* disable aspm and clock request before access ephy */ - RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn); - RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en); - rtl_ephy_init(tp, e_info_8168g_1, ARRAY_SIZE(e_info_8168g_1)); -} - -static void rtl_hw_start_8168g_2(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8168g_2[] = { - { 0x00, 0x0000, 0x0008 }, - { 0x0c, 0x3df0, 0x0200 }, - { 0x19, 0xffff, 0xfc00 }, - { 0x1e, 0xffff, 0x20eb } - }; - - rtl_hw_start_8168g(tp); - - /* disable aspm and clock request before access ephy */ - RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn); - RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en); - rtl_ephy_init(tp, e_info_8168g_2, ARRAY_SIZE(e_info_8168g_2)); -} - -static void rtl_hw_start_8411_2(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8411_2[] = { - { 0x00, 0x0000, 0x0008 }, - { 0x0c, 0x3df0, 0x0200 }, - { 0x0f, 0xffff, 0x5200 }, - { 0x19, 0x0020, 0x0000 }, - { 0x1e, 0x0000, 0x2000 } - }; - - rtl_hw_start_8168g(tp); - - /* disable aspm and clock request before access ephy */ - RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn); - RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en); - rtl_ephy_init(tp, e_info_8411_2, ARRAY_SIZE(e_info_8411_2)); -} - -static void rtl_hw_start_8168h_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - int rg_saw_cnt; - u32 data; - static const struct ephy_info e_info_8168h_1[] = { - { 0x1e, 0x0800, 0x0001 }, - { 0x1d, 0x0000, 0x0800 }, - { 0x05, 0xffff, 0x2089 }, - { 0x06, 0xffff, 0x5881 }, - { 0x04, 0xffff, 0x154a }, - { 0x01, 0xffff, 0x068b } - }; - - /* disable aspm and clock request before access ephy */ - RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn); - RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en); - rtl_ephy_init(tp, e_info_8168h_1, ARRAY_SIZE(e_info_8168h_1)); - - RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); - - rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x00080002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x38, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x48, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); - - rtl_csi_access_enable_1(tp); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); - - rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_1111, 0x0010, 0x00, ERIAR_EXGMAC); - - rtl_w0w1_eri(tp, 0xd4, ERIAR_MASK_1111, 0x1f00, 0x00, ERIAR_EXGMAC); - - rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87, ERIAR_EXGMAC); - - RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN); - RTL_W8(MaxTxPacketSize, EarlySize); - - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - - /* Adjust EEE LED frequency */ - RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); - - RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN); - RTL_W8(DLLPR, RTL_R8(MISC_1) & ~PFM_D3COLD_EN); - - RTL_W8(DLLPR, RTL_R8(DLLPR) & ~TX_10M_PS_EN); - - rtl_w0w1_eri(tp, 0x1b0, ERIAR_MASK_0011, 0x0000, 0x1000, ERIAR_EXGMAC); - - rtl_pcie_state_l2l3_enable(tp, false); - - rtl_writephy(tp, 0x1f, 0x0c42); - rg_saw_cnt = rtl_readphy(tp, 0x13); - rtl_writephy(tp, 0x1f, 0x0000); - if (rg_saw_cnt > 0) { - u16 sw_cnt_1ms_ini; - - sw_cnt_1ms_ini = 16000000/rg_saw_cnt; - sw_cnt_1ms_ini &= 0x0fff; - data = r8168_mac_ocp_read(tp, 0xd412); - data &= 0x0fff; - data |= sw_cnt_1ms_ini; - r8168_mac_ocp_write(tp, 0xd412, data); - } - - data = r8168_mac_ocp_read(tp, 0xe056); - data &= 0xf0; - data |= 0x07; - r8168_mac_ocp_write(tp, 0xe056, data); - - data = r8168_mac_ocp_read(tp, 0xe052); - data &= 0x8008; - data |= 0x6000; - r8168_mac_ocp_write(tp, 0xe052, data); - - data = r8168_mac_ocp_read(tp, 0xe0d6); - data &= 0x01ff; - data |= 0x017f; - r8168_mac_ocp_write(tp, 0xe0d6, data); - - data = r8168_mac_ocp_read(tp, 0xd420); - data &= 0x0fff; - data |= 0x047f; - r8168_mac_ocp_write(tp, 0xd420, data); - - r8168_mac_ocp_write(tp, 0xe63e, 0x0001); - r8168_mac_ocp_write(tp, 0xe63e, 0x0000); - r8168_mac_ocp_write(tp, 0xc094, 0x0000); - r8168_mac_ocp_write(tp, 0xc09e, 0x0000); -} - -static void rtl_hw_start_8168ep(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl8168ep_stop_cmac(tp); - - RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); - - rtl_eri_write(tp, 0xc8, ERIAR_MASK_0101, 0x00080002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xcc, ERIAR_MASK_0001, 0x2f, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xd0, ERIAR_MASK_0001, 0x5f, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00100006, ERIAR_EXGMAC); - - rtl_csi_access_enable_1(tp); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); - - rtl_w0w1_eri(tp, 0xd4, ERIAR_MASK_1111, 0x1f80, 0x00, ERIAR_EXGMAC); - - rtl_eri_write(tp, 0x5f0, ERIAR_MASK_0011, 0x4f87, ERIAR_EXGMAC); - - RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN); - RTL_W8(MaxTxPacketSize, EarlySize); - - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - - /* Adjust EEE LED frequency */ - RTL_W8(EEE_LED, RTL_R8(EEE_LED) & ~0x07); - - rtl_w0w1_eri(tp, 0x2fc, ERIAR_MASK_0001, 0x01, 0x06, ERIAR_EXGMAC); - - RTL_W8(DLLPR, RTL_R8(DLLPR) & ~TX_10M_PS_EN); - - rtl_pcie_state_l2l3_enable(tp, false); -} - -static void rtl_hw_start_8168ep_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8168ep_1[] = { - { 0x00, 0xffff, 0x10ab }, - { 0x06, 0xffff, 0xf030 }, - { 0x08, 0xffff, 0x2006 }, - { 0x0d, 0xffff, 0x1666 }, - { 0x0c, 0x3ff0, 0x0000 } - }; - - /* disable aspm and clock request before access ephy */ - RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn); - RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en); - rtl_ephy_init(tp, e_info_8168ep_1, ARRAY_SIZE(e_info_8168ep_1)); - - rtl_hw_start_8168ep(tp); -} - -static void rtl_hw_start_8168ep_2(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8168ep_2[] = { - { 0x00, 0xffff, 0x10a3 }, - { 0x19, 0xffff, 0xfc00 }, - { 0x1e, 0xffff, 0x20ea } - }; - - /* disable aspm and clock request before access ephy */ - RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn); - RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en); - rtl_ephy_init(tp, e_info_8168ep_2, ARRAY_SIZE(e_info_8168ep_2)); - - rtl_hw_start_8168ep(tp); - - RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN); - RTL_W8(DLLPR, RTL_R8(MISC_1) & ~PFM_D3COLD_EN); -} - -static void rtl_hw_start_8168ep_3(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 data; - static const struct ephy_info e_info_8168ep_3[] = { - { 0x00, 0xffff, 0x10a3 }, - { 0x19, 0xffff, 0x7c00 }, - { 0x1e, 0xffff, 0x20eb }, - { 0x0d, 0xffff, 0x1666 } - }; - - /* disable aspm and clock request before access ephy */ - RTL_W8(Config2, RTL_R8(Config2) & ~ClkReqEn); - RTL_W8(Config5, RTL_R8(Config5) & ~ASPM_en); - rtl_ephy_init(tp, e_info_8168ep_3, ARRAY_SIZE(e_info_8168ep_3)); - - rtl_hw_start_8168ep(tp); - - RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN); - RTL_W8(DLLPR, RTL_R8(MISC_1) & ~PFM_D3COLD_EN); - - data = r8168_mac_ocp_read(tp, 0xd3e2); - data &= 0xf000; - data |= 0x0271; - r8168_mac_ocp_write(tp, 0xd3e2, data); - - data = r8168_mac_ocp_read(tp, 0xd3e4); - data &= 0xff00; - r8168_mac_ocp_write(tp, 0xd3e4, data); - - data = r8168_mac_ocp_read(tp, 0xe860); - data |= 0x0080; - r8168_mac_ocp_write(tp, 0xe860, data); -} - -static void rtl_hw_start_8168(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - rtl_set_rx_max_size(ioaddr, rx_buf_sz); - - tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; - - RTL_W16(CPlusCmd, tp->cp_cmd); - - RTL_W16(IntrMitigate, 0x5151); - - /* Work around for RxFIFO overflow. */ - if (tp->mac_version == RTL_GIGA_MAC_VER_11) { - tp->event_slow |= RxFIFOOver | PCSTimeout; - tp->event_slow &= ~RxOverflow; - } - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_tx_config_registers(tp); - - RTL_R8(IntrMask); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - rtl_hw_start_8168bb(tp); - break; - - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - rtl_hw_start_8168bef(tp); - break; - - case RTL_GIGA_MAC_VER_18: - rtl_hw_start_8168cp_1(tp); - break; - - case RTL_GIGA_MAC_VER_19: - rtl_hw_start_8168c_1(tp); - break; - - case RTL_GIGA_MAC_VER_20: - rtl_hw_start_8168c_2(tp); - break; - - case RTL_GIGA_MAC_VER_21: - rtl_hw_start_8168c_3(tp); - break; - - case RTL_GIGA_MAC_VER_22: - rtl_hw_start_8168c_4(tp); - break; - - case RTL_GIGA_MAC_VER_23: - rtl_hw_start_8168cp_2(tp); - break; - - case RTL_GIGA_MAC_VER_24: - rtl_hw_start_8168cp_3(tp); - break; - - case RTL_GIGA_MAC_VER_25: - case RTL_GIGA_MAC_VER_26: - case RTL_GIGA_MAC_VER_27: - rtl_hw_start_8168d(tp); - break; - - case RTL_GIGA_MAC_VER_28: - rtl_hw_start_8168d_4(tp); - break; - - case RTL_GIGA_MAC_VER_31: - rtl_hw_start_8168dp(tp); - break; - - case RTL_GIGA_MAC_VER_32: - case RTL_GIGA_MAC_VER_33: - rtl_hw_start_8168e_1(tp); - break; - case RTL_GIGA_MAC_VER_34: - rtl_hw_start_8168e_2(tp); - break; - - case RTL_GIGA_MAC_VER_35: - case RTL_GIGA_MAC_VER_36: - rtl_hw_start_8168f_1(tp); - break; - - case RTL_GIGA_MAC_VER_38: - rtl_hw_start_8411(tp); - break; - - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - rtl_hw_start_8168g_1(tp); - break; - case RTL_GIGA_MAC_VER_42: - rtl_hw_start_8168g_2(tp); - break; - - case RTL_GIGA_MAC_VER_44: - rtl_hw_start_8411_2(tp); - break; - - case RTL_GIGA_MAC_VER_45: - case RTL_GIGA_MAC_VER_46: - rtl_hw_start_8168h_1(tp); - break; - - case RTL_GIGA_MAC_VER_49: - rtl_hw_start_8168ep_1(tp); - break; - - case RTL_GIGA_MAC_VER_50: - rtl_hw_start_8168ep_2(tp); - break; - - case RTL_GIGA_MAC_VER_51: - rtl_hw_start_8168ep_3(tp); - break; - - default: - printk(KERN_ERR PFX "%s: unknown chipset (mac_version = %d).\n", - dev->name, tp->mac_version); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - rtl_set_rx_mode(dev); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); -} - -#define R810X_CPCMD_QUIRK_MASK (\ - EnableBist | \ - Mac_dbgo_oe | \ - Force_half_dup | \ - Force_rxflow_en | \ - Force_txflow_en | \ - Cxpl_dbg_sel | \ - ASF | \ - PktCntrDisable | \ - Mac_dbgo_sel) - -static void rtl_hw_start_8102e_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - static const struct ephy_info e_info_8102e_1[] = { - { 0x01, 0, 0x6e65 }, - { 0x02, 0, 0x091f }, - { 0x03, 0, 0xc2f9 }, - { 0x06, 0, 0xafb5 }, - { 0x07, 0, 0x0e00 }, - { 0x19, 0, 0xec80 }, - { 0x01, 0, 0x2e65 }, - { 0x01, 0, 0x6e65 } - }; - u8 cfg1; - - rtl_csi_access_enable_2(tp); - - RTL_W8(DBG_REG, FIX_NAK_1); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, - LEDS1 | LEDS0 | Speed_down | MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); - - cfg1 = RTL_R8(Config1); - if ((cfg1 & LEDS0) && (cfg1 & LEDS1)) - RTL_W8(Config1, cfg1 & ~LEDS0); - - rtl_ephy_init(tp, e_info_8102e_1, ARRAY_SIZE(e_info_8102e_1)); -} - -static void rtl_hw_start_8102e_2(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - rtl_csi_access_enable_2(tp); - - rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); - - RTL_W8(Config1, MEMMAP | IOMAP | VPD | PMEnable); - RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); -} - -static void rtl_hw_start_8102e_3(struct rtl8169_private *tp) -{ - rtl_hw_start_8102e_2(tp); - - rtl_ephy_write(tp, 0x03, 0xc2f9); -} - -static void rtl_hw_start_8105e_1(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8105e_1[] = { - { 0x07, 0, 0x4000 }, - { 0x19, 0, 0x0200 }, - { 0x19, 0, 0x0020 }, - { 0x1e, 0, 0x2000 }, - { 0x03, 0, 0x0001 }, - { 0x19, 0, 0x0100 }, - { 0x19, 0, 0x0004 }, - { 0x0a, 0, 0x0020 } - }; - - /* Force LAN exit from ASPM if Rx/Tx are not idle */ - RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); - - /* Disable Early Tally Counter */ - RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000); - - RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); - RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); - - rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1)); - - rtl_pcie_state_l2l3_enable(tp, false); -} - -static void rtl_hw_start_8105e_2(struct rtl8169_private *tp) -{ - rtl_hw_start_8105e_1(tp); - rtl_ephy_write(tp, 0x1e, rtl_ephy_read(tp, 0x1e) | 0x8000); -} - -static void rtl_hw_start_8402(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - static const struct ephy_info e_info_8402[] = { - { 0x19, 0xffff, 0xff64 }, - { 0x1e, 0, 0x4000 } - }; - - rtl_csi_access_enable_2(tp); - - /* Force LAN exit from ASPM if Rx/Tx are not idle */ - RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); - - RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); - RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); - - rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402)); - - rtl_tx_performance_tweak(tp->pci_dev, 0x5 << MAX_READ_REQUEST_SHIFT); - - rtl_eri_write(tp, 0xc8, ERIAR_MASK_1111, 0x00000002, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xe8, ERIAR_MASK_1111, 0x00000006, ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x00, 0x01, ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); - rtl_w0w1_eri(tp, 0x0d4, ERIAR_MASK_0011, 0x0e00, 0xff00, ERIAR_EXGMAC); - - rtl_pcie_state_l2l3_enable(tp, false); -} - -static void rtl_hw_start_8106(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - /* Force LAN exit from ASPM if Rx/Tx are not idle */ - RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); - - RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN); - RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); - RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN); - - rtl_pcie_state_l2l3_enable(tp, false); -} - -static void rtl_hw_start_8101(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - - if (tp->mac_version >= RTL_GIGA_MAC_VER_30) - tp->event_slow &= ~RxFIFOOver; - - if (tp->mac_version == RTL_GIGA_MAC_VER_13 || - tp->mac_version == RTL_GIGA_MAC_VER_16) - pcie_capability_set_word(pdev, PCI_EXP_DEVCTL, - PCI_EXP_DEVCTL_NOSNOOP_EN); - - RTL_W8(Cfg9346, Cfg9346_Unlock); - - RTL_W8(MaxTxPacketSize, TxPacketMax); - - rtl_set_rx_max_size(ioaddr, rx_buf_sz); - - tp->cp_cmd &= ~R810X_CPCMD_QUIRK_MASK; - RTL_W16(CPlusCmd, tp->cp_cmd); - - rtl_set_rx_tx_desc_registers(tp, ioaddr); - - rtl_set_rx_tx_config_registers(tp); - - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_07: - rtl_hw_start_8102e_1(tp); - break; - - case RTL_GIGA_MAC_VER_08: - rtl_hw_start_8102e_3(tp); - break; - - case RTL_GIGA_MAC_VER_09: - rtl_hw_start_8102e_2(tp); - break; - - case RTL_GIGA_MAC_VER_29: - rtl_hw_start_8105e_1(tp); - break; - case RTL_GIGA_MAC_VER_30: - rtl_hw_start_8105e_2(tp); - break; - - case RTL_GIGA_MAC_VER_37: - rtl_hw_start_8402(tp); - break; - - case RTL_GIGA_MAC_VER_39: - rtl_hw_start_8106(tp); - break; - case RTL_GIGA_MAC_VER_43: - rtl_hw_start_8168g_2(tp); - break; - case RTL_GIGA_MAC_VER_47: - case RTL_GIGA_MAC_VER_48: - rtl_hw_start_8168h_1(tp); - break; - } - - RTL_W8(Cfg9346, Cfg9346_Lock); - - RTL_W16(IntrMitigate, 0x0000); - - RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); - - rtl_set_rx_mode(dev); - - RTL_R8(IntrMask); - - RTL_W16(MultiIntr, RTL_R16(MultiIntr) & 0xf000); -} - -static int rtl8169_change_mtu(struct net_device *dev, int new_mtu) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (new_mtu < ETH_ZLEN || - new_mtu > rtl_chip_infos[tp->mac_version].jumbo_max) - return -EINVAL; - - if (new_mtu > ETH_DATA_LEN) - rtl_hw_jumbo_enable(tp); - else - rtl_hw_jumbo_disable(tp); - - dev->mtu = new_mtu; - netdev_update_features(dev); - - return 0; -} - -static inline void rtl8169_make_unusable_by_asic(struct RxDesc *desc) -{ - desc->addr = cpu_to_le64(0x0badbadbadbadbadull); - desc->opts1 &= ~cpu_to_le32(DescOwn | RsvdMask); -} - -static void rtl8169_free_rx_databuff(struct rtl8169_private *tp, - void **data_buff, struct RxDesc *desc) -{ - dma_unmap_single(&tp->pci_dev->dev, le64_to_cpu(desc->addr), rx_buf_sz, - DMA_FROM_DEVICE); - - kfree(*data_buff); - *data_buff = NULL; - rtl8169_make_unusable_by_asic(desc); -} - -static inline void rtl8169_mark_to_asic(struct RxDesc *desc, u32 rx_buf_sz) -{ - u32 eor = le32_to_cpu(desc->opts1) & RingEnd; - - /* Force memory writes to complete before releasing descriptor */ - dma_wmb(); - - desc->opts1 = cpu_to_le32(DescOwn | eor | rx_buf_sz); -} - -static inline void rtl8169_map_to_asic(struct RxDesc *desc, dma_addr_t mapping, - u32 rx_buf_sz) -{ - desc->addr = cpu_to_le64(mapping); - rtl8169_mark_to_asic(desc, rx_buf_sz); -} - -static inline void *rtl8169_align(void *data) -{ - return (void *)ALIGN((long)data, 16); -} - -static struct sk_buff *rtl8169_alloc_rx_data(struct rtl8169_private *tp, - struct RxDesc *desc) -{ - void *data; - dma_addr_t mapping; - struct device *d = &tp->pci_dev->dev; - struct net_device *dev = tp->dev; - int node = dev->dev.parent ? dev_to_node(dev->dev.parent) : -1; - - data = kmalloc_node(rx_buf_sz, GFP_KERNEL, node); - if (!data) - return NULL; - - if (rtl8169_align(data) != data) { - kfree(data); - data = kmalloc_node(rx_buf_sz + 15, GFP_KERNEL, node); - if (!data) - return NULL; - } - - mapping = dma_map_single(d, rtl8169_align(data), rx_buf_sz, - DMA_FROM_DEVICE); - if (unlikely(dma_mapping_error(d, mapping))) { - if (net_ratelimit()) - netif_err(tp, drv, tp->dev, "Failed to map RX DMA!\n"); - goto err_out; - } - - rtl8169_map_to_asic(desc, mapping, rx_buf_sz); - return data; - -err_out: - kfree(data); - return NULL; -} - -static void rtl8169_rx_clear(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - if (tp->Rx_databuff[i]) { - rtl8169_free_rx_databuff(tp, tp->Rx_databuff + i, - tp->RxDescArray + i); - } - } -} - -static inline void rtl8169_mark_as_last_descriptor(struct RxDesc *desc) -{ - desc->opts1 |= cpu_to_le32(RingEnd); -} - -static int rtl8169_rx_fill(struct rtl8169_private *tp) -{ - unsigned int i; - - for (i = 0; i < NUM_RX_DESC; i++) { - void *data; - - if (tp->Rx_databuff[i]) - continue; - - data = rtl8169_alloc_rx_data(tp, tp->RxDescArray + i); - if (!data) { - rtl8169_make_unusable_by_asic(tp->RxDescArray + i); - goto err_out; - } - tp->Rx_databuff[i] = data; - } - - rtl8169_mark_as_last_descriptor(tp->RxDescArray + NUM_RX_DESC - 1); - return 0; - -err_out: - rtl8169_rx_clear(tp); - return -ENOMEM; -} - -static int rtl8169_init_ring(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_ring_indexes(tp); - - memset(tp->tx_skb, 0x0, NUM_TX_DESC * sizeof(struct ring_info)); - memset(tp->Rx_databuff, 0x0, NUM_RX_DESC * sizeof(void *)); - - return rtl8169_rx_fill(tp); -} - -static void rtl8169_unmap_tx_skb(struct device *d, struct ring_info *tx_skb, - struct TxDesc *desc) -{ - unsigned int len = tx_skb->len; - - dma_unmap_single(d, le64_to_cpu(desc->addr), len, DMA_TO_DEVICE); - - desc->opts1 = 0x00; - desc->opts2 = 0x00; - desc->addr = 0x00; - tx_skb->len = 0; -} - -static void rtl8169_tx_clear_range(struct rtl8169_private *tp, u32 start, - unsigned int n) -{ - unsigned int i; - - for (i = 0; i < n; i++) { - unsigned int entry = (start + i) % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - unsigned int len = tx_skb->len; - - if (len) { - struct sk_buff *skb = tx_skb->skb; - - rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, - tp->TxDescArray + entry); - if (skb) { - tp->dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - tx_skb->skb = NULL; - } - } - } -} - -static void rtl8169_tx_clear(struct rtl8169_private *tp) -{ - rtl8169_tx_clear_range(tp, tp->dirty_tx, NUM_TX_DESC); - tp->cur_tx = tp->dirty_tx = 0; -} - -static void rtl_reset_work(struct rtl8169_private *tp) -{ - struct net_device *dev = tp->dev; - int i; - - napi_disable(&tp->napi); - netif_stop_queue(dev); - synchronize_sched(); - - rtl8169_hw_reset(tp); - - for (i = 0; i < NUM_RX_DESC; i++) - rtl8169_mark_to_asic(tp->RxDescArray + i, rx_buf_sz); - - rtl8169_tx_clear(tp); - rtl8169_init_ring_indexes(tp); - - napi_enable(&tp->napi); - rtl_hw_start(dev); - netif_wake_queue(dev); - rtl8169_check_link_status(dev, tp, tp->mmio_addr); -} - -static void rtl8169_tx_timeout(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); -} - -static int rtl8169_xmit_frags(struct rtl8169_private *tp, struct sk_buff *skb, - u32 *opts) -{ - struct skb_shared_info *info = skb_shinfo(skb); - unsigned int cur_frag, entry; - struct TxDesc *uninitialized_var(txd); - struct device *d = &tp->pci_dev->dev; - - entry = tp->cur_tx; - for (cur_frag = 0; cur_frag < info->nr_frags; cur_frag++) { - const skb_frag_t *frag = info->frags + cur_frag; - dma_addr_t mapping; - u32 status, len; - void *addr; - - entry = (entry + 1) % NUM_TX_DESC; - - txd = tp->TxDescArray + entry; - len = skb_frag_size(frag); - addr = skb_frag_address(frag); - mapping = dma_map_single(d, addr, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(d, mapping))) { - if (net_ratelimit()) - netif_err(tp, drv, tp->dev, - "Failed to map TX fragments DMA!\n"); - goto err_out; - } - - /* Anti gcc 2.95.3 bugware (sic) */ - status = opts[0] | len | - (RingEnd * !((entry + 1) % NUM_TX_DESC)); - - txd->opts1 = cpu_to_le32(status); - txd->opts2 = cpu_to_le32(opts[1]); - txd->addr = cpu_to_le64(mapping); - - tp->tx_skb[entry].len = len; - } - - if (cur_frag) { - tp->tx_skb[entry].skb = skb; - txd->opts1 |= cpu_to_le32(LastFrag); - } - - return cur_frag; - -err_out: - rtl8169_tx_clear_range(tp, tp->cur_tx + 1, cur_frag); - return -EIO; -} - -static bool rtl_test_hw_pad_bug(struct rtl8169_private *tp, struct sk_buff *skb) -{ - return skb->len < ETH_ZLEN && tp->mac_version == RTL_GIGA_MAC_VER_34; -} - -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev); -/* r8169_csum_workaround() - * The hw limites the value the transport offset. When the offset is out of the - * range, calculate the checksum by sw. - */ -static void r8169_csum_workaround(struct rtl8169_private *tp, - struct sk_buff *skb) -{ - if (skb_shinfo(skb)->gso_size) { - netdev_features_t features = tp->dev->features; - struct sk_buff *segs, *nskb; - - features &= ~(NETIF_F_SG | NETIF_F_IPV6_CSUM | NETIF_F_TSO6); - segs = skb_gso_segment(skb, features); - if (IS_ERR(segs) || !segs) - goto drop; - - do { - nskb = segs; - segs = segs->next; - nskb->next = NULL; - rtl8169_start_xmit(nskb, tp->dev); - } while (segs); - - dev_consume_skb_any(skb); - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - if (skb_checksum_help(skb) < 0) - goto drop; - - rtl8169_start_xmit(skb, tp->dev); - } else { - struct net_device_stats *stats; - -drop: - stats = &tp->dev->stats; - stats->tx_dropped++; - dev_kfree_skb_any(skb); - } -} - -/* msdn_giant_send_check() - * According to the document of microsoft, the TCP Pseudo Header excludes the - * packet length for IPv6 TCP large packets. - */ -static int msdn_giant_send_check(struct sk_buff *skb) -{ - const struct ipv6hdr *ipv6h; - struct tcphdr *th; - int ret; - - ret = skb_cow_head(skb, 0); - if (ret) - return ret; - - ipv6h = ipv6_hdr(skb); - th = tcp_hdr(skb); - - th->check = 0; - th->check = ~tcp_v6_check(0, &ipv6h->saddr, &ipv6h->daddr, 0); - - return ret; -} - -static inline __be16 get_protocol(struct sk_buff *skb) -{ - __be16 protocol; - - if (skb->protocol == htons(ETH_P_8021Q)) - protocol = vlan_eth_hdr(skb)->h_vlan_encapsulated_proto; - else - protocol = skb->protocol; - - return protocol; -} - -static bool rtl8169_tso_csum_v1(struct rtl8169_private *tp, - struct sk_buff *skb, u32 *opts) -{ - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) { - opts[0] |= TD_LSO; - opts[0] |= min(mss, TD_MSS_MAX) << TD0_MSS_SHIFT; - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - const struct iphdr *ip = ip_hdr(skb); - - if (ip->protocol == IPPROTO_TCP) - opts[0] |= TD0_IP_CS | TD0_TCP_CS; - else if (ip->protocol == IPPROTO_UDP) - opts[0] |= TD0_IP_CS | TD0_UDP_CS; - else - WARN_ON_ONCE(1); - } - - return true; -} - -static bool rtl8169_tso_csum_v2(struct rtl8169_private *tp, - struct sk_buff *skb, u32 *opts) -{ - u32 transport_offset = (u32)skb_transport_offset(skb); - u32 mss = skb_shinfo(skb)->gso_size; - - if (mss) { - if (transport_offset > GTTCPHO_MAX) { - netif_warn(tp, tx_err, tp->dev, - "Invalid transport offset 0x%x for TSO\n", - transport_offset); - return false; - } - - switch (get_protocol(skb)) { - case htons(ETH_P_IP): - opts[0] |= TD1_GTSENV4; - break; - - case htons(ETH_P_IPV6): - if (msdn_giant_send_check(skb)) - return false; - - opts[0] |= TD1_GTSENV6; - break; - - default: - WARN_ON_ONCE(1); - break; - } - - opts[0] |= transport_offset << GTTCPHO_SHIFT; - opts[1] |= min(mss, TD_MSS_MAX) << TD1_MSS_SHIFT; - } else if (skb->ip_summed == CHECKSUM_PARTIAL) { - u8 ip_protocol; - - if (unlikely(rtl_test_hw_pad_bug(tp, skb))) - return !(skb_checksum_help(skb) || eth_skb_pad(skb)); - - if (transport_offset > TCPHO_MAX) { - netif_warn(tp, tx_err, tp->dev, - "Invalid transport offset 0x%x\n", - transport_offset); - return false; - } - - switch (get_protocol(skb)) { - case htons(ETH_P_IP): - opts[1] |= TD1_IPv4_CS; - ip_protocol = ip_hdr(skb)->protocol; - break; - - case htons(ETH_P_IPV6): - opts[1] |= TD1_IPv6_CS; - ip_protocol = ipv6_hdr(skb)->nexthdr; - break; - - default: - ip_protocol = IPPROTO_RAW; - break; - } - - if (ip_protocol == IPPROTO_TCP) - opts[1] |= TD1_TCP_CS; - else if (ip_protocol == IPPROTO_UDP) - opts[1] |= TD1_UDP_CS; - else - WARN_ON_ONCE(1); - - opts[1] |= transport_offset << TCPHO_SHIFT; - } else { - if (unlikely(rtl_test_hw_pad_bug(tp, skb))) - return !eth_skb_pad(skb); - } - - return true; -} - -static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb, - struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - unsigned int entry = tp->cur_tx % NUM_TX_DESC; - struct TxDesc *txd = tp->TxDescArray + entry; - void __iomem *ioaddr = tp->mmio_addr; - struct device *d = &tp->pci_dev->dev; - dma_addr_t mapping; - u32 status, len; - u32 opts[2]; - int frags; - - if (unlikely(!TX_FRAGS_READY_FOR(tp, skb_shinfo(skb)->nr_frags))) { - netif_err(tp, drv, dev, "BUG! Tx Ring full when queue awake!\n"); - goto err_stop_0; - } - - if (unlikely(le32_to_cpu(txd->opts1) & DescOwn)) - goto err_stop_0; - - opts[1] = cpu_to_le32(rtl8169_tx_vlan_tag(skb)); - opts[0] = DescOwn; - - if (!tp->tso_csum(tp, skb, opts)) { - r8169_csum_workaround(tp, skb); - return NETDEV_TX_OK; - } - - len = skb_headlen(skb); - mapping = dma_map_single(d, skb->data, len, DMA_TO_DEVICE); - if (unlikely(dma_mapping_error(d, mapping))) { - if (net_ratelimit()) - netif_err(tp, drv, dev, "Failed to map TX DMA!\n"); - goto err_dma_0; - } - - tp->tx_skb[entry].len = len; - txd->addr = cpu_to_le64(mapping); - - frags = rtl8169_xmit_frags(tp, skb, opts); - if (frags < 0) - goto err_dma_1; - else if (frags) - opts[0] |= FirstFrag; - else { - opts[0] |= FirstFrag | LastFrag; - tp->tx_skb[entry].skb = skb; - } - - txd->opts2 = cpu_to_le32(opts[1]); - - skb_tx_timestamp(skb); - - /* Force memory writes to complete before releasing descriptor */ - dma_wmb(); - - /* Anti gcc 2.95.3 bugware (sic) */ - status = opts[0] | len | (RingEnd * !((entry + 1) % NUM_TX_DESC)); - txd->opts1 = cpu_to_le32(status); - - /* Force all memory writes to complete before notifying device */ - wmb(); - - tp->cur_tx += frags + 1; - - RTL_W8(TxPoll, NPQ); - - mmiowb(); - - if (!TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) { - /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must - * not miss a ring update when it notices a stopped queue. - */ - smp_wmb(); - netif_stop_queue(dev); - /* Sync with rtl_tx: - * - publish queue status and cur_tx ring index (write barrier) - * - refresh dirty_tx ring index (read barrier). - * May the current thread have a pessimistic view of the ring - * status and forget to wake up queue, a racing rtl_tx thread - * can't. - */ - smp_mb(); - if (TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) - netif_wake_queue(dev); - } - - return NETDEV_TX_OK; - -err_dma_1: - rtl8169_unmap_tx_skb(d, tp->tx_skb + entry, txd); -err_dma_0: - dev_kfree_skb_any(skb); - dev->stats.tx_dropped++; - return NETDEV_TX_OK; - -err_stop_0: - netif_stop_queue(dev); - dev->stats.tx_dropped++; - return NETDEV_TX_BUSY; -} - -static void rtl8169_pcierr_interrupt(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - netif_err(tp, intr, dev, "PCI error (cmd = 0x%04x, status = 0x%04x)\n", - pci_cmd, pci_status); - - /* - * The recovery sequence below admits a very elaborated explanation: - * - it seems to work; - * - I did not see what else could be done; - * - it makes iop3xx happy. - * - * Feel free to adjust to your needs. - */ - if (pdev->broken_parity_status) - pci_cmd &= ~PCI_COMMAND_PARITY; - else - pci_cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY; - - pci_write_config_word(pdev, PCI_COMMAND, pci_cmd); - - pci_write_config_word(pdev, PCI_STATUS, - pci_status & (PCI_STATUS_DETECTED_PARITY | - PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_REC_MASTER_ABORT | - PCI_STATUS_REC_TARGET_ABORT | PCI_STATUS_SIG_TARGET_ABORT)); - - /* The infamous DAC f*ckup only happens at boot time */ - if ((tp->cp_cmd & PCIDAC) && !tp->cur_rx) { - void __iomem *ioaddr = tp->mmio_addr; - - netif_info(tp, intr, dev, "disabling PCI DAC\n"); - tp->cp_cmd &= ~PCIDAC; - RTL_W16(CPlusCmd, tp->cp_cmd); - dev->features &= ~NETIF_F_HIGHDMA; - } - - rtl8169_hw_reset(tp); - - rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); -} - -static void rtl_tx(struct net_device *dev, struct rtl8169_private *tp) -{ - unsigned int dirty_tx, tx_left; - - dirty_tx = tp->dirty_tx; - smp_rmb(); - tx_left = tp->cur_tx - dirty_tx; - - while (tx_left > 0) { - unsigned int entry = dirty_tx % NUM_TX_DESC; - struct ring_info *tx_skb = tp->tx_skb + entry; - u32 status; - - status = le32_to_cpu(tp->TxDescArray[entry].opts1); - if (status & DescOwn) - break; - - /* This barrier is needed to keep us from reading - * any other fields out of the Tx descriptor until - * we know the status of DescOwn - */ - dma_rmb(); - - rtl8169_unmap_tx_skb(&tp->pci_dev->dev, tx_skb, - tp->TxDescArray + entry); - if (status & LastFrag) { - u64_stats_update_begin(&tp->tx_stats.syncp); - tp->tx_stats.packets++; - tp->tx_stats.bytes += tx_skb->skb->len; - u64_stats_update_end(&tp->tx_stats.syncp); - dev_kfree_skb_any(tx_skb->skb); - tx_skb->skb = NULL; - } - dirty_tx++; - tx_left--; - } - - if (tp->dirty_tx != dirty_tx) { - tp->dirty_tx = dirty_tx; - /* Sync with rtl8169_start_xmit: - * - publish dirty_tx ring index (write barrier) - * - refresh cur_tx ring index and queue status (read barrier) - * May the current thread miss the stopped queue condition, - * a racing xmit thread can only have a right view of the - * ring status. - */ - smp_mb(); - if (netif_queue_stopped(dev) && - TX_FRAGS_READY_FOR(tp, MAX_SKB_FRAGS)) { - netif_wake_queue(dev); - } - /* - * 8168 hack: TxPoll requests are lost when the Tx packets are - * too close. Let's kick an extra TxPoll request when a burst - * of start_xmit activity is detected (if it is not detected, - * it is slow enough). -- FR - */ - if (tp->cur_tx != dirty_tx) { - void __iomem *ioaddr = tp->mmio_addr; - - RTL_W8(TxPoll, NPQ); - } - } -} - -static inline int rtl8169_fragmented_frame(u32 status) -{ - return (status & (FirstFrag | LastFrag)) != (FirstFrag | LastFrag); -} - -static inline void rtl8169_rx_csum(struct sk_buff *skb, u32 opts1) -{ - u32 status = opts1 & RxProtoMask; - - if (((status == RxProtoTCP) && !(opts1 & TCPFail)) || - ((status == RxProtoUDP) && !(opts1 & UDPFail))) - skb->ip_summed = CHECKSUM_UNNECESSARY; - else - skb_checksum_none_assert(skb); -} - -static struct sk_buff *rtl8169_try_rx_copy(void *data, - struct rtl8169_private *tp, - int pkt_size, - dma_addr_t addr) -{ - struct sk_buff *skb; - struct device *d = &tp->pci_dev->dev; - - data = rtl8169_align(data); - dma_sync_single_for_cpu(d, addr, pkt_size, DMA_FROM_DEVICE); - prefetch(data); - skb = napi_alloc_skb(&tp->napi, pkt_size); - if (skb) - memcpy(skb->data, data, pkt_size); - dma_sync_single_for_device(d, addr, pkt_size, DMA_FROM_DEVICE); - - return skb; -} - -static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget) -{ - unsigned int cur_rx, rx_left; - unsigned int count; - - cur_rx = tp->cur_rx; - - for (rx_left = min(budget, NUM_RX_DESC); rx_left > 0; rx_left--, cur_rx++) { - unsigned int entry = cur_rx % NUM_RX_DESC; - struct RxDesc *desc = tp->RxDescArray + entry; - u32 status; - - status = le32_to_cpu(desc->opts1) & tp->opts1_mask; - if (status & DescOwn) - break; - - /* This barrier is needed to keep us from reading - * any other fields out of the Rx descriptor until - * we know the status of DescOwn - */ - dma_rmb(); - - if (unlikely(status & RxRES)) { - netif_info(tp, rx_err, dev, "Rx ERROR. status = %08x\n", - status); - dev->stats.rx_errors++; - if (status & (RxRWT | RxRUNT)) - dev->stats.rx_length_errors++; - if (status & RxCRC) - dev->stats.rx_crc_errors++; - if (status & RxFOVF) { - rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); - dev->stats.rx_fifo_errors++; - } - if ((status & (RxRUNT | RxCRC)) && - !(status & (RxRWT | RxFOVF)) && - (dev->features & NETIF_F_RXALL)) - goto process_pkt; - } else { - struct sk_buff *skb; - dma_addr_t addr; - int pkt_size; - -process_pkt: - addr = le64_to_cpu(desc->addr); - if (likely(!(dev->features & NETIF_F_RXFCS))) - pkt_size = (status & 0x00003fff) - 4; - else - pkt_size = status & 0x00003fff; - - /* - * The driver does not support incoming fragmented - * frames. They are seen as a symptom of over-mtu - * sized frames. - */ - if (unlikely(rtl8169_fragmented_frame(status))) { - dev->stats.rx_dropped++; - dev->stats.rx_length_errors++; - goto release_descriptor; - } - - skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], - tp, pkt_size, addr); - if (!skb) { - dev->stats.rx_dropped++; - goto release_descriptor; - } - - rtl8169_rx_csum(skb, status); - skb_put(skb, pkt_size); - skb->protocol = eth_type_trans(skb, dev); - - rtl8169_rx_vlan_tag(desc, skb); - - if (skb->pkt_type == PACKET_MULTICAST) - dev->stats.multicast++; - - napi_gro_receive(&tp->napi, skb); - - u64_stats_update_begin(&tp->rx_stats.syncp); - tp->rx_stats.packets++; - tp->rx_stats.bytes += pkt_size; - u64_stats_update_end(&tp->rx_stats.syncp); - } -release_descriptor: - desc->opts2 = 0; - rtl8169_mark_to_asic(desc, rx_buf_sz); - } - - count = cur_rx - tp->cur_rx; - tp->cur_rx = cur_rx; - - return count; -} - -static irqreturn_t rtl8169_interrupt(int irq, void *dev_instance) -{ - struct net_device *dev = dev_instance; - struct rtl8169_private *tp = netdev_priv(dev); - int handled = 0; - u16 status; - - status = rtl_get_events(tp); - if (status && status != 0xffff) { - status &= RTL_EVENT_NAPI | tp->event_slow; - if (status) { - handled = 1; - - rtl_irq_disable(tp); - napi_schedule(&tp->napi); - } - } - return IRQ_RETVAL(handled); -} - -/* - * Workqueue context. - */ -static void rtl_slow_event_work(struct rtl8169_private *tp) -{ - struct net_device *dev = tp->dev; - u16 status; - - status = rtl_get_events(tp) & tp->event_slow; - rtl_ack_events(tp, status); - - if (unlikely(status & RxFIFOOver)) { - switch (tp->mac_version) { - /* Work around for rx fifo overflow */ - case RTL_GIGA_MAC_VER_11: - netif_stop_queue(dev); - /* XXX - Hack alert. See rtl_task(). */ - set_bit(RTL_FLAG_TASK_RESET_PENDING, tp->wk.flags); - default: - break; - } - } - - if (unlikely(status & SYSErr)) - rtl8169_pcierr_interrupt(dev); - - if (status & LinkChg) - __rtl8169_check_link_status(dev, tp, tp->mmio_addr, true); - - rtl_irq_enable_all(tp); -} - -static void rtl_task(struct work_struct *work) -{ - static const struct { - int bitnr; - void (*action)(struct rtl8169_private *); - } rtl_work[] = { - /* XXX - keep rtl_slow_event_work() as first element. */ - { RTL_FLAG_TASK_SLOW_PENDING, rtl_slow_event_work }, - { RTL_FLAG_TASK_RESET_PENDING, rtl_reset_work }, - { RTL_FLAG_TASK_PHY_PENDING, rtl_phy_work } - }; - struct rtl8169_private *tp = - container_of(work, struct rtl8169_private, wk.work); - struct net_device *dev = tp->dev; - int i; - - rtl_lock_work(tp); - - if (!netif_running(dev) || - !test_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags)) - goto out_unlock; - - for (i = 0; i < ARRAY_SIZE(rtl_work); i++) { - bool pending; - - pending = test_and_clear_bit(rtl_work[i].bitnr, tp->wk.flags); - if (pending) - rtl_work[i].action(tp); - } - -out_unlock: - rtl_unlock_work(tp); -} - -static int rtl8169_poll(struct napi_struct *napi, int budget) -{ - struct rtl8169_private *tp = container_of(napi, struct rtl8169_private, napi); - struct net_device *dev = tp->dev; - u16 enable_mask = RTL_EVENT_NAPI | tp->event_slow; - int work_done; - u16 status; - - status = rtl_get_events(tp); - rtl_ack_events(tp, status & ~tp->event_slow); - - work_done = rtl_rx(dev, tp, (u32) budget); - - rtl_tx(dev, tp); - - if (status & tp->event_slow) { - enable_mask &= ~tp->event_slow; - - rtl_schedule_task(tp, RTL_FLAG_TASK_SLOW_PENDING); - } - - if (work_done < budget) { - napi_complete(napi); - - rtl_irq_enable(tp, enable_mask); - mmiowb(); - } - - return work_done; -} - -static void rtl8169_rx_missed(struct net_device *dev, void __iomem *ioaddr) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (tp->mac_version > RTL_GIGA_MAC_VER_06) - return; - - dev->stats.rx_missed_errors += (RTL_R32(RxMissed) & 0xffffff); - RTL_W32(RxMissed, 0); -} - -static void rtl8169_down(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - - del_timer_sync(&tp->timer); - - napi_disable(&tp->napi); - netif_stop_queue(dev); - - rtl8169_hw_reset(tp); - /* - * At this point device interrupts can not be enabled in any function, - * as netif_running is not true (rtl8169_interrupt, rtl8169_reset_task) - * and napi is disabled (rtl8169_poll). - */ - rtl8169_rx_missed(dev, ioaddr); - - /* Give a racing hard_start_xmit a few cycles to complete. */ - synchronize_sched(); - - rtl8169_tx_clear(tp); - - rtl8169_rx_clear(tp); - - rtl_pll_power_down(tp); -} - -static int rtl8169_close(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - struct pci_dev *pdev = tp->pci_dev; - - pm_runtime_get_sync(&pdev->dev); - - /* Update counters before going down */ - rtl8169_update_counters(dev); - - rtl_lock_work(tp); - /* Clear all task flags */ - bitmap_zero(tp->wk.flags, RTL_FLAG_MAX); - - rtl8169_down(dev); - rtl_unlock_work(tp); - - cancel_work_sync(&tp->wk.work); - - free_irq(pdev->irq, dev); - - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; - tp->RxDescArray = NULL; - - pm_runtime_put_sync(&pdev->dev); - - return 0; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void rtl8169_netpoll(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_interrupt(tp->pci_dev->irq, dev); -} -#endif - -static int rtl_open(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct pci_dev *pdev = tp->pci_dev; - int retval = -ENOMEM; - - pm_runtime_get_sync(&pdev->dev); - - /* - * Rx and Tx descriptors needs 256 bytes alignment. - * dma_alloc_coherent provides more. - */ - tp->TxDescArray = dma_alloc_coherent(&pdev->dev, R8169_TX_RING_BYTES, - &tp->TxPhyAddr, GFP_KERNEL); - if (!tp->TxDescArray) - goto err_pm_runtime_put; - - tp->RxDescArray = dma_alloc_coherent(&pdev->dev, R8169_RX_RING_BYTES, - &tp->RxPhyAddr, GFP_KERNEL); - if (!tp->RxDescArray) - goto err_free_tx_0; - - retval = rtl8169_init_ring(dev); - if (retval < 0) - goto err_free_rx_1; - - INIT_WORK(&tp->wk.work, rtl_task); - - smp_mb(); - - rtl_request_firmware(tp); - - retval = request_irq(pdev->irq, rtl8169_interrupt, - (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED, - dev->name, dev); - if (retval < 0) - goto err_release_fw_2; - - rtl_lock_work(tp); - - set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); - - napi_enable(&tp->napi); - - rtl8169_init_phy(dev, tp); - - __rtl8169_set_features(dev, dev->features); - - rtl_pll_power_up(tp); - - rtl_hw_start(dev); - - if (!rtl8169_init_counter_offsets(dev)) - netif_warn(tp, hw, dev, "counter reset/update failed\n"); - - netif_start_queue(dev); - - rtl_unlock_work(tp); - - tp->saved_wolopts = 0; - pm_runtime_put_noidle(&pdev->dev); - - rtl8169_check_link_status(dev, tp, ioaddr); -out: - return retval; - -err_release_fw_2: - rtl_release_firmware(tp); - rtl8169_rx_clear(tp); -err_free_rx_1: - dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray, - tp->RxPhyAddr); - tp->RxDescArray = NULL; -err_free_tx_0: - dma_free_coherent(&pdev->dev, R8169_TX_RING_BYTES, tp->TxDescArray, - tp->TxPhyAddr); - tp->TxDescArray = NULL; -err_pm_runtime_put: - pm_runtime_put_noidle(&pdev->dev); - goto out; -} - -static struct rtnl_link_stats64 * -rtl8169_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) -{ - struct rtl8169_private *tp = netdev_priv(dev); - void __iomem *ioaddr = tp->mmio_addr; - struct rtl8169_counters *counters = tp->counters; - unsigned int start; - - if (netif_running(dev)) - rtl8169_rx_missed(dev, ioaddr); - - do { - start = u64_stats_fetch_begin_irq(&tp->rx_stats.syncp); - stats->rx_packets = tp->rx_stats.packets; - stats->rx_bytes = tp->rx_stats.bytes; - } while (u64_stats_fetch_retry_irq(&tp->rx_stats.syncp, start)); - - do { - start = u64_stats_fetch_begin_irq(&tp->tx_stats.syncp); - stats->tx_packets = tp->tx_stats.packets; - stats->tx_bytes = tp->tx_stats.bytes; - } while (u64_stats_fetch_retry_irq(&tp->tx_stats.syncp, start)); - - stats->rx_dropped = dev->stats.rx_dropped; - stats->tx_dropped = dev->stats.tx_dropped; - stats->rx_length_errors = dev->stats.rx_length_errors; - stats->rx_errors = dev->stats.rx_errors; - stats->rx_crc_errors = dev->stats.rx_crc_errors; - stats->rx_fifo_errors = dev->stats.rx_fifo_errors; - stats->rx_missed_errors = dev->stats.rx_missed_errors; - stats->multicast = dev->stats.multicast; - - /* - * Fetch additonal counter values missing in stats collected by driver - * from tally counters. - */ - rtl8169_update_counters(dev); - - /* - * Subtract values fetched during initalization. - * See rtl8169_init_counter_offsets for a description why we do that. - */ - stats->tx_errors = le64_to_cpu(counters->tx_errors) - - le64_to_cpu(tp->tc_offset.tx_errors); - stats->collisions = le32_to_cpu(counters->tx_multi_collision) - - le32_to_cpu(tp->tc_offset.tx_multi_collision); - stats->tx_aborted_errors = le16_to_cpu(counters->tx_aborted) - - le16_to_cpu(tp->tc_offset.tx_aborted); - - return stats; -} - -static void rtl8169_net_suspend(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - if (!netif_running(dev)) - return; - - netif_device_detach(dev); - netif_stop_queue(dev); - - rtl_lock_work(tp); - napi_disable(&tp->napi); - /* Clear all task flags */ - bitmap_zero(tp->wk.flags, RTL_FLAG_MAX); - - rtl_unlock_work(tp); - - rtl_pll_power_down(tp); -} - -#ifdef CONFIG_PM - -static int rtl8169_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - - rtl8169_net_suspend(dev); - - return 0; -} - -static void __rtl8169_resume(struct net_device *dev) -{ - struct rtl8169_private *tp = netdev_priv(dev); - - netif_device_attach(dev); - - rtl_pll_power_up(tp); - - rtl_lock_work(tp); - napi_enable(&tp->napi); - set_bit(RTL_FLAG_TASK_ENABLED, tp->wk.flags); - rtl_unlock_work(tp); - - rtl_schedule_task(tp, RTL_FLAG_TASK_RESET_PENDING); -} - -static int rtl8169_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - rtl8169_init_phy(dev, tp); - - if (netif_running(dev)) - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_suspend(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - rtl_lock_work(tp); - tp->saved_wolopts = __rtl8169_get_wol(tp); - __rtl8169_set_wol(tp, WAKE_ANY); - rtl_unlock_work(tp); - - rtl8169_net_suspend(dev); - - return 0; -} - -static int rtl8169_runtime_resume(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if (!tp->TxDescArray) - return 0; - - rtl_lock_work(tp); - __rtl8169_set_wol(tp, tp->saved_wolopts); - tp->saved_wolopts = 0; - rtl_unlock_work(tp); - - rtl8169_init_phy(dev, tp); - - __rtl8169_resume(dev); - - return 0; -} - -static int rtl8169_runtime_idle(struct device *device) -{ - struct pci_dev *pdev = to_pci_dev(device); - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - return tp->TxDescArray ? -EBUSY : 0; -} - -static const struct dev_pm_ops rtl8169_pm_ops = { - .suspend = rtl8169_suspend, - .resume = rtl8169_resume, - .freeze = rtl8169_suspend, - .thaw = rtl8169_resume, - .poweroff = rtl8169_suspend, - .restore = rtl8169_resume, - .runtime_suspend = rtl8169_runtime_suspend, - .runtime_resume = rtl8169_runtime_resume, - .runtime_idle = rtl8169_runtime_idle, -}; - -#define RTL8169_PM_OPS (&rtl8169_pm_ops) - -#else /* !CONFIG_PM */ - -#define RTL8169_PM_OPS NULL - -#endif /* !CONFIG_PM */ - -static void rtl_wol_shutdown_quirk(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - - /* WoL fails with 8168b when the receiver is disabled. */ - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_11: - case RTL_GIGA_MAC_VER_12: - case RTL_GIGA_MAC_VER_17: - pci_clear_master(tp->pci_dev); - - RTL_W8(ChipCmd, CmdRxEnb); - /* PCI commit */ - RTL_R8(ChipCmd); - break; - default: - break; - } -} - -static void rtl_shutdown(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - struct device *d = &pdev->dev; - - pm_runtime_get_sync(d); - - rtl8169_net_suspend(dev); - - /* Restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl8169_hw_reset(tp); - - if (system_state == SYSTEM_POWER_OFF) { - if (__rtl8169_get_wol(tp) & WAKE_ANY) { - rtl_wol_suspend_quirk(tp); - rtl_wol_shutdown_quirk(tp); - } - - pci_wake_from_d3(pdev, true); - pci_set_power_state(pdev, PCI_D3hot); - } - - pm_runtime_put_noidle(d); -} - -static void rtl_remove_one(struct pci_dev *pdev) -{ - struct net_device *dev = pci_get_drvdata(pdev); - struct rtl8169_private *tp = netdev_priv(dev); - - if ((tp->mac_version == RTL_GIGA_MAC_VER_27 || - tp->mac_version == RTL_GIGA_MAC_VER_28 || - tp->mac_version == RTL_GIGA_MAC_VER_31 || - tp->mac_version == RTL_GIGA_MAC_VER_49 || - tp->mac_version == RTL_GIGA_MAC_VER_50 || - tp->mac_version == RTL_GIGA_MAC_VER_51) && - r8168_check_dash(tp)) { - rtl8168_driver_stop(tp); - } - - netif_napi_del(&tp->napi); - - unregister_netdev(dev); - - dma_free_coherent(&tp->pci_dev->dev, sizeof(*tp->counters), - tp->counters, tp->counters_phys_addr); - - rtl_release_firmware(tp); - - if (pci_dev_run_wake(pdev)) - pm_runtime_get_noresume(&pdev->dev); - - /* restore original MAC address */ - rtl_rar_set(tp, dev->perm_addr); - - rtl_disable_msi(pdev, tp); - rtl8169_release_board(pdev, dev, tp->mmio_addr); -} - -static const struct net_device_ops rtl_netdev_ops = { - .ndo_open = rtl_open, - .ndo_stop = rtl8169_close, - .ndo_get_stats64 = rtl8169_get_stats64, - .ndo_start_xmit = rtl8169_start_xmit, - .ndo_tx_timeout = rtl8169_tx_timeout, - .ndo_validate_addr = eth_validate_addr, - .ndo_change_mtu = rtl8169_change_mtu, - .ndo_fix_features = rtl8169_fix_features, - .ndo_set_features = rtl8169_set_features, - .ndo_set_mac_address = rtl_set_mac_address, - .ndo_do_ioctl = rtl8169_ioctl, - .ndo_set_rx_mode = rtl_set_rx_mode, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = rtl8169_netpoll, -#endif - -}; - -static const struct rtl_cfg_info { - void (*hw_start)(struct net_device *); - unsigned int region; - unsigned int align; - u16 event_slow; - unsigned features; - u8 default_ver; -} rtl_cfg_infos [] = { - [RTL_CFG_0] = { - .hw_start = rtl_hw_start_8169, - .region = 1, - .align = 0, - .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver, - .features = RTL_FEATURE_GMII, - .default_ver = RTL_GIGA_MAC_VER_01, - }, - [RTL_CFG_1] = { - .hw_start = rtl_hw_start_8168, - .region = 2, - .align = 8, - .event_slow = SYSErr | LinkChg | RxOverflow, - .features = RTL_FEATURE_GMII | RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_11, - }, - [RTL_CFG_2] = { - .hw_start = rtl_hw_start_8101, - .region = 2, - .align = 8, - .event_slow = SYSErr | LinkChg | RxOverflow | RxFIFOOver | - PCSTimeout, - .features = RTL_FEATURE_MSI, - .default_ver = RTL_GIGA_MAC_VER_13, - } -}; - -/* Cfg9346_Unlock assumed. */ -static unsigned rtl_try_msi(struct rtl8169_private *tp, - const struct rtl_cfg_info *cfg) -{ - void __iomem *ioaddr = tp->mmio_addr; - unsigned msi = 0; - u8 cfg2; - - cfg2 = RTL_R8(Config2) & ~MSIEnable; - if (cfg->features & RTL_FEATURE_MSI) { - if (pci_enable_msi(tp->pci_dev)) { - netif_info(tp, hw, tp->dev, "no MSI. Back to INTx.\n"); - } else { - cfg2 |= MSIEnable; - msi = RTL_FEATURE_MSI; - } - } - if (tp->mac_version <= RTL_GIGA_MAC_VER_06) - RTL_W8(Config2, cfg2); - return msi; -} - -DECLARE_RTL_COND(rtl_link_list_ready_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return RTL_R8(MCU) & LINK_LIST_RDY; -} - -DECLARE_RTL_COND(rtl_rxtx_empty_cond) -{ - void __iomem *ioaddr = tp->mmio_addr; - - return (RTL_R8(MCU) & RXTX_EMPTY) == RXTX_EMPTY; -} - -static void rtl_hw_init_8168g(struct rtl8169_private *tp) -{ - void __iomem *ioaddr = tp->mmio_addr; - u32 data; - - tp->ocp_base = OCP_STD_PHY_BASE; - - RTL_W32(MISC, RTL_R32(MISC) | RXDV_GATED_EN); - - if (!rtl_udelay_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 42)) - return; - - if (!rtl_udelay_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42)) - return; - - RTL_W8(ChipCmd, RTL_R8(ChipCmd) & ~(CmdTxEnb | CmdRxEnb)); - msleep(1); - RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); - - data = r8168_mac_ocp_read(tp, 0xe8de); - data &= ~(1 << 14); - r8168_mac_ocp_write(tp, 0xe8de, data); - - if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42)) - return; - - data = r8168_mac_ocp_read(tp, 0xe8de); - data |= (1 << 15); - r8168_mac_ocp_write(tp, 0xe8de, data); - - if (!rtl_udelay_loop_wait_high(tp, &rtl_link_list_ready_cond, 100, 42)) - return; -} - -static void rtl_hw_init_8168ep(struct rtl8169_private *tp) -{ - rtl8168ep_stop_cmac(tp); - rtl_hw_init_8168g(tp); -} - -static void rtl_hw_initialize(struct rtl8169_private *tp) -{ - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - case RTL_GIGA_MAC_VER_44: - case RTL_GIGA_MAC_VER_45: - case RTL_GIGA_MAC_VER_46: - case RTL_GIGA_MAC_VER_47: - case RTL_GIGA_MAC_VER_48: - rtl_hw_init_8168g(tp); - break; - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - rtl_hw_init_8168ep(tp); - break; - default: - break; - } -} - -static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; - const unsigned int region = cfg->region; - struct rtl8169_private *tp; - struct mii_if_info *mii; - struct net_device *dev; - void __iomem *ioaddr; - int chipset, i; - int rc; - - if (netif_msg_drv(&debug)) { - printk(KERN_INFO "%s Gigabit Ethernet driver %s loaded\n", - MODULENAME, RTL8169_VERSION); - } - - dev = alloc_etherdev(sizeof (*tp)); - if (!dev) { - rc = -ENOMEM; - goto out; - } - - SET_NETDEV_DEV(dev, &pdev->dev); - dev->netdev_ops = &rtl_netdev_ops; - tp = netdev_priv(dev); - tp->dev = dev; - tp->pci_dev = pdev; - tp->msg_enable = netif_msg_init(debug.msg_enable, R8169_MSG_DEFAULT); - - mii = &tp->mii; - mii->dev = dev; - mii->mdio_read = rtl_mdio_read; - mii->mdio_write = rtl_mdio_write; - mii->phy_id_mask = 0x1f; - mii->reg_num_mask = 0x1f; - mii->supports_gmii = !!(cfg->features & RTL_FEATURE_GMII); - - /* disable ASPM completely as that cause random device stop working - * problems as well as full system hangs for some PCIe devices users */ - pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 | - PCIE_LINK_STATE_CLKPM); - - /* enable device (incl. PCI PM wakeup and hotplug setup) */ - rc = pci_enable_device(pdev); - if (rc < 0) { - netif_err(tp, probe, dev, "enable failure\n"); - goto err_out_free_dev_1; - } - - if (pci_set_mwi(pdev) < 0) - netif_info(tp, probe, dev, "Mem-Wr-Inval unavailable\n"); - - /* make sure PCI base addr 1 is MMIO */ - if (!(pci_resource_flags(pdev, region) & IORESOURCE_MEM)) { - netif_err(tp, probe, dev, - "region #%d not an MMIO resource, aborting\n", - region); - rc = -ENODEV; - goto err_out_mwi_2; - } - - /* check for weird/broken PCI region reporting */ - if (pci_resource_len(pdev, region) < R8169_REGS_SIZE) { - netif_err(tp, probe, dev, - "Invalid PCI region size(s), aborting\n"); - rc = -ENODEV; - goto err_out_mwi_2; - } - - rc = pci_request_regions(pdev, MODULENAME); - if (rc < 0) { - netif_err(tp, probe, dev, "could not request regions\n"); - goto err_out_mwi_2; - } - - tp->cp_cmd = 0; - - if ((sizeof(dma_addr_t) > 4) && - !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { - tp->cp_cmd |= PCIDAC; - dev->features |= NETIF_F_HIGHDMA; - } else { - rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (rc < 0) { - netif_err(tp, probe, dev, "DMA configuration failed\n"); - goto err_out_free_res_3; - } - } - - /* ioremap MMIO region */ - ioaddr = ioremap(pci_resource_start(pdev, region), R8169_REGS_SIZE); - if (!ioaddr) { - netif_err(tp, probe, dev, "cannot remap MMIO, aborting\n"); - rc = -EIO; - goto err_out_free_res_3; - } - tp->mmio_addr = ioaddr; - - if (!pci_is_pcie(pdev)) - netif_info(tp, probe, dev, "not PCI Express\n"); - - /* Identify chip attached to board */ - rtl8169_get_mac_version(tp, dev, cfg->default_ver); - - rtl_init_rxcfg(tp); - - rtl_irq_disable(tp); - - rtl_hw_initialize(tp); - - rtl_hw_reset(tp); - - rtl_ack_events(tp, 0xffff); - - pci_set_master(pdev); - - rtl_init_mdio_ops(tp); - rtl_init_pll_power_ops(tp); - rtl_init_jumbo_ops(tp); - rtl_init_csi_ops(tp); - - rtl8169_print_mac_version(tp); - - chipset = tp->mac_version; - tp->txd_version = rtl_chip_infos[chipset].txd_version; - - RTL_W8(Cfg9346, Cfg9346_Unlock); - RTL_W8(Config1, RTL_R8(Config1) | PMEnable); - RTL_W8(Config5, RTL_R8(Config5) & (BWF | MWF | UWF | LanWake | PMEStatus)); - switch (tp->mac_version) { - case RTL_GIGA_MAC_VER_34: - case RTL_GIGA_MAC_VER_35: - case RTL_GIGA_MAC_VER_36: - case RTL_GIGA_MAC_VER_37: - case RTL_GIGA_MAC_VER_38: - case RTL_GIGA_MAC_VER_40: - case RTL_GIGA_MAC_VER_41: - case RTL_GIGA_MAC_VER_42: - case RTL_GIGA_MAC_VER_43: - case RTL_GIGA_MAC_VER_44: - case RTL_GIGA_MAC_VER_45: - case RTL_GIGA_MAC_VER_46: - case RTL_GIGA_MAC_VER_47: - case RTL_GIGA_MAC_VER_48: - case RTL_GIGA_MAC_VER_49: - case RTL_GIGA_MAC_VER_50: - case RTL_GIGA_MAC_VER_51: - if (rtl_eri_read(tp, 0xdc, ERIAR_EXGMAC) & MagicPacket_v2) - tp->features |= RTL_FEATURE_WOL; - if ((RTL_R8(Config3) & LinkUp) != 0) - tp->features |= RTL_FEATURE_WOL; - break; - default: - if ((RTL_R8(Config3) & (LinkUp | MagicPacket)) != 0) - tp->features |= RTL_FEATURE_WOL; - break; - } - if ((RTL_R8(Config5) & (UWF | BWF | MWF)) != 0) - tp->features |= RTL_FEATURE_WOL; - tp->features |= rtl_try_msi(tp, cfg); - RTL_W8(Cfg9346, Cfg9346_Lock); - - if (rtl_tbi_enabled(tp)) { - tp->set_speed = rtl8169_set_speed_tbi; - tp->get_settings = rtl8169_gset_tbi; - tp->phy_reset_enable = rtl8169_tbi_reset_enable; - tp->phy_reset_pending = rtl8169_tbi_reset_pending; - tp->link_ok = rtl8169_tbi_link_ok; - tp->do_ioctl = rtl_tbi_ioctl; - } else { - tp->set_speed = rtl8169_set_speed_xmii; - tp->get_settings = rtl8169_gset_xmii; - tp->phy_reset_enable = rtl8169_xmii_reset_enable; - tp->phy_reset_pending = rtl8169_xmii_reset_pending; - tp->link_ok = rtl8169_xmii_link_ok; - tp->do_ioctl = rtl_xmii_ioctl; - } - - mutex_init(&tp->wk.mutex); - u64_stats_init(&tp->rx_stats.syncp); - u64_stats_init(&tp->tx_stats.syncp); - - /* Get MAC address */ - if (tp->mac_version == RTL_GIGA_MAC_VER_35 || - tp->mac_version == RTL_GIGA_MAC_VER_36 || - tp->mac_version == RTL_GIGA_MAC_VER_37 || - tp->mac_version == RTL_GIGA_MAC_VER_38 || - tp->mac_version == RTL_GIGA_MAC_VER_40 || - tp->mac_version == RTL_GIGA_MAC_VER_41 || - tp->mac_version == RTL_GIGA_MAC_VER_42 || - tp->mac_version == RTL_GIGA_MAC_VER_43 || - tp->mac_version == RTL_GIGA_MAC_VER_44 || - tp->mac_version == RTL_GIGA_MAC_VER_45 || - tp->mac_version == RTL_GIGA_MAC_VER_46 || - tp->mac_version == RTL_GIGA_MAC_VER_47 || - tp->mac_version == RTL_GIGA_MAC_VER_48 || - tp->mac_version == RTL_GIGA_MAC_VER_49 || - tp->mac_version == RTL_GIGA_MAC_VER_50 || - tp->mac_version == RTL_GIGA_MAC_VER_51) { - u16 mac_addr[3]; - - *(u32 *)&mac_addr[0] = rtl_eri_read(tp, 0xe0, ERIAR_EXGMAC); - *(u16 *)&mac_addr[2] = rtl_eri_read(tp, 0xe4, ERIAR_EXGMAC); - - if (is_valid_ether_addr((u8 *)mac_addr)) - rtl_rar_set(tp, (u8 *)mac_addr); - } - for (i = 0; i < ETH_ALEN; i++) - dev->dev_addr[i] = RTL_R8(MAC0 + i); - - dev->ethtool_ops = &rtl8169_ethtool_ops; - dev->watchdog_timeo = RTL8169_TX_TIMEOUT; - - netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT); - - /* don't enable SG, IP_CSUM and TSO by default - it might not work - * properly for all devices */ - dev->features |= NETIF_F_RXCSUM | - NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX; - - dev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | - NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX | - NETIF_F_HW_VLAN_CTAG_RX; - dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | - NETIF_F_HIGHDMA; - - tp->cp_cmd |= RxChkSum | RxVlan; - - /* - * Pretend we are using VLANs; This bypasses a nasty bug where - * Interrupts stop flowing on high load on 8110SCd controllers. - */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - /* Disallow toggling */ - dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX; - - if (tp->txd_version == RTL_TD_0) - tp->tso_csum = rtl8169_tso_csum_v1; - else if (tp->txd_version == RTL_TD_1) { - tp->tso_csum = rtl8169_tso_csum_v2; - dev->hw_features |= NETIF_F_IPV6_CSUM | NETIF_F_TSO6; - } else - WARN_ON_ONCE(1); - - dev->hw_features |= NETIF_F_RXALL; - dev->hw_features |= NETIF_F_RXFCS; - - tp->hw_start = cfg->hw_start; - tp->event_slow = cfg->event_slow; - - tp->opts1_mask = (tp->mac_version != RTL_GIGA_MAC_VER_01) ? - ~(RxBOVF | RxFOVF) : ~0; - - init_timer(&tp->timer); - tp->timer.data = (unsigned long) dev; - tp->timer.function = rtl8169_phy_timer; - - tp->rtl_fw = RTL_FIRMWARE_UNKNOWN; - - tp->counters = dma_alloc_coherent (&pdev->dev, sizeof(*tp->counters), - &tp->counters_phys_addr, GFP_KERNEL); - if (!tp->counters) { - rc = -ENOMEM; - goto err_out_msi_4; - } - - pci_set_drvdata(pdev, dev); - - rc = register_netdev(dev); - if (rc < 0) - goto err_out_cnt_5; - - netif_info(tp, probe, dev, "%s at 0x%p, %pM, XID %08x IRQ %d\n", - rtl_chip_infos[chipset].name, ioaddr, dev->dev_addr, - (u32)(RTL_R32(TxConfig) & 0x9cf0f8ff), pdev->irq); - if (rtl_chip_infos[chipset].jumbo_max != JUMBO_1K) { - netif_info(tp, probe, dev, "jumbo features [frames: %d bytes, " - "tx checksumming: %s]\n", - rtl_chip_infos[chipset].jumbo_max, - rtl_chip_infos[chipset].jumbo_tx_csum ? "ok" : "ko"); - } - - if ((tp->mac_version == RTL_GIGA_MAC_VER_27 || - tp->mac_version == RTL_GIGA_MAC_VER_28 || - tp->mac_version == RTL_GIGA_MAC_VER_31 || - tp->mac_version == RTL_GIGA_MAC_VER_49 || - tp->mac_version == RTL_GIGA_MAC_VER_50 || - tp->mac_version == RTL_GIGA_MAC_VER_51) && - r8168_check_dash(tp)) { - rtl8168_driver_start(tp); - } - - device_set_wakeup_enable(&pdev->dev, tp->features & RTL_FEATURE_WOL); - - if (pci_dev_run_wake(pdev)) - pm_runtime_put_noidle(&pdev->dev); - - netif_carrier_off(dev); - -out: - return rc; - -err_out_cnt_5: - dma_free_coherent(&pdev->dev, sizeof(*tp->counters), tp->counters, - tp->counters_phys_addr); -err_out_msi_4: - netif_napi_del(&tp->napi); - rtl_disable_msi(pdev, tp); - iounmap(ioaddr); -err_out_free_res_3: - pci_release_regions(pdev); -err_out_mwi_2: - pci_clear_mwi(pdev); - pci_disable_device(pdev); -err_out_free_dev_1: - free_netdev(dev); - goto out; -} - -static struct pci_driver rtl8169_pci_driver = { - .name = MODULENAME, - .id_table = rtl8169_pci_tbl, - .probe = rtl_init_one, - .remove = rtl_remove_one, - .shutdown = rtl_shutdown, - .driver.pm = RTL8169_PM_OPS, -}; - -module_pci_driver(rtl8169_pci_driver); diff --git a/addons/skge/install.sh b/addons/skge/install.sh deleted file mode 100644 index 9a5111b6..00000000 --- a/addons/skge/install.sh +++ /dev/null @@ -1,4 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Installing module for Marvell Yukon Gigabit Ethernet adapter" - ${INSMOD} "/modules/skge.ko" ${PARAMS} -fi diff --git a/addons/skge/manifest.yml b/addons/skge/manifest.yml deleted file mode 100644 index 1f11e717..00000000 --- a/addons/skge/manifest.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: 1 -name: skge -description: "Driver for Marvell Yukon Gigabit Ethernet adapters" -available-for: - bromolow-3.10.108: - install-script: &script "install.sh" - modules: true - apollolake-4.4.180: - install-script: *script - modules: true - broadwell-4.4.180: - install-script: *script - modules: true - broadwellnk-4.4.180: - install-script: *script - modules: true - denverton-4.4.180: - install-script: *script - modules: true - geminilake-4.4.180: - install-script: *script - modules: true - v1000-4.4.180: - install-script: *script - modules: true - purley-4.4.180: - install-script: *script - modules: true diff --git a/addons/skge/src/3.10.108/Makefile b/addons/skge/src/3.10.108/Makefile deleted file mode 100644 index f0ca3939..00000000 --- a/addons/skge/src/3.10.108/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-m += skge.o diff --git a/addons/skge/src/3.10.108/skge.c b/addons/skge/src/3.10.108/skge.c deleted file mode 100644 index 171f4b3d..00000000 --- a/addons/skge/src/3.10.108/skge.c +++ /dev/null @@ -1,4180 +0,0 @@ -/* - * New driver for Marvell Yukon chipset and SysKonnect Gigabit - * Ethernet adapters. Based on earlier sk98lin, e100 and - * FreeBSD if_sk drivers. - * - * This driver intentionally does not support all the features - * of the original driver such as link fail-over and link management because - * those should be done at higher levels. - * - * Copyright (C) 2004, 2005 Stephen Hemminger - * - * 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. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "skge.h" - -#define DRV_NAME "skge" -#define DRV_VERSION "1.14" - -#define DEFAULT_TX_RING_SIZE 128 -#define DEFAULT_RX_RING_SIZE 512 -#define MAX_TX_RING_SIZE 1024 -#define TX_LOW_WATER (MAX_SKB_FRAGS + 1) -#define MAX_RX_RING_SIZE 4096 -#define RX_COPY_THRESHOLD 128 -#define RX_BUF_SIZE 1536 -#define PHY_RETRIES 1000 -#define ETH_JUMBO_MTU 9000 -#define TX_WATCHDOG (5 * HZ) -#define NAPI_WEIGHT 64 -#define BLINK_MS 250 -#define LINK_HZ HZ - -#define SKGE_EEPROM_MAGIC 0x9933aabb - - -MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); -MODULE_AUTHOR("Stephen Hemminger "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -static const u32 default_msg = (NETIF_MSG_DRV | NETIF_MSG_PROBE | - NETIF_MSG_LINK | NETIF_MSG_IFUP | - NETIF_MSG_IFDOWN); - -static int debug = -1; /* defaults above */ -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); - -static DEFINE_PCI_DEVICE_TABLE(skge_id_table) = { - { PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x1700) }, /* 3Com 3C940 */ - { PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x80EB) }, /* 3Com 3C940B */ -#ifdef CONFIG_SKGE_GENESIS - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4300) }, /* SK-9xx */ -#endif - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4320) }, /* SK-98xx V2.0 */ - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, /* D-Link DGE-530T (rev.B) */ - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4c00) }, /* D-Link DGE-530T */ - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302) }, /* D-Link DGE-530T Rev C1 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, /* Marvell Yukon 88E8001/8003/8010 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ - { PCI_DEVICE(PCI_VENDOR_ID_CNET, 0x434E) }, /* CNet PowerG-2000 */ - { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, 0x1064) }, /* Linksys EG1064 v2 */ - { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015 }, /* Linksys EG1032 v2 */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, skge_id_table); - -static int skge_up(struct net_device *dev); -static int skge_down(struct net_device *dev); -static void skge_phy_reset(struct skge_port *skge); -static void skge_tx_clean(struct net_device *dev); -static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); -static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); -static void genesis_get_stats(struct skge_port *skge, u64 *data); -static void yukon_get_stats(struct skge_port *skge, u64 *data); -static void yukon_init(struct skge_hw *hw, int port); -static void genesis_mac_init(struct skge_hw *hw, int port); -static void genesis_link_up(struct skge_port *skge); -static void skge_set_multicast(struct net_device *dev); -static irqreturn_t skge_intr(int irq, void *dev_id); - -/* Avoid conditionals by using array */ -static const int txqaddr[] = { Q_XA1, Q_XA2 }; -static const int rxqaddr[] = { Q_R1, Q_R2 }; -static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F }; -static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F }; -static const u32 napimask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F }; -static const u32 portmask[] = { IS_PORT_1, IS_PORT_2 }; - -static inline bool is_genesis(const struct skge_hw *hw) -{ -#ifdef CONFIG_SKGE_GENESIS - return hw->chip_id == CHIP_ID_GENESIS; -#else - return false; -#endif -} - -static int skge_get_regs_len(struct net_device *dev) -{ - return 0x4000; -} - -/* - * Returns copy of whole control register region - * Note: skip RAM address register because accessing it will - * cause bus hangs! - */ -static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - const struct skge_port *skge = netdev_priv(dev); - const void __iomem *io = skge->hw->regs; - - regs->version = 1; - memset(p, 0, regs->len); - memcpy_fromio(p, io, B3_RAM_ADDR); - - memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, - regs->len - B3_RI_WTO_R1); -} - -/* Wake on Lan only supported on Yukon chips with rev 1 or above */ -static u32 wol_supported(const struct skge_hw *hw) -{ - if (is_genesis(hw)) - return 0; - - if (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0) - return 0; - - return WAKE_MAGIC | WAKE_PHY; -} - -static void skge_wol_init(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 ctrl; - - skge_write16(hw, B0_CTST, CS_RST_CLR); - skge_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR); - - /* Turn on Vaux */ - skge_write8(hw, B0_POWER_CTRL, - PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF); - - /* WA code for COMA mode -- clear PHY reset */ - if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev >= CHIP_REV_YU_LITE_A3) { - u32 reg = skge_read32(hw, B2_GP_IO); - reg |= GP_DIR_9; - reg &= ~GP_IO_9; - skge_write32(hw, B2_GP_IO, reg); - } - - skge_write32(hw, SK_REG(port, GPHY_CTRL), - GPC_DIS_SLEEP | - GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 | - GPC_ANEG_1 | GPC_RST_SET); - - skge_write32(hw, SK_REG(port, GPHY_CTRL), - GPC_DIS_SLEEP | - GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 | - GPC_ANEG_1 | GPC_RST_CLR); - - skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); - - /* Force to 10/100 skge_reset will re-enable on resume */ - gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, - (PHY_AN_100FULL | PHY_AN_100HALF | - PHY_AN_10FULL | PHY_AN_10HALF | PHY_AN_CSMA)); - /* no 1000 HD/FD */ - gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_CTRL, - PHY_CT_RESET | PHY_CT_SPS_LSB | PHY_CT_ANE | - PHY_CT_RE_CFG | PHY_CT_DUP_MD); - - - /* Set GMAC to no flow control and auto update for speed/duplex */ - gma_write16(hw, port, GM_GP_CTRL, - GM_GPCR_FC_TX_DIS|GM_GPCR_TX_ENA|GM_GPCR_RX_ENA| - GM_GPCR_DUP_FULL|GM_GPCR_FC_RX_DIS|GM_GPCR_AU_FCT_DIS); - - /* Set WOL address */ - memcpy_toio(hw->regs + WOL_REGS(port, WOL_MAC_ADDR), - skge->netdev->dev_addr, ETH_ALEN); - - /* Turn on appropriate WOL control bits */ - skge_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), WOL_CTL_CLEAR_RESULT); - ctrl = 0; - if (skge->wol & WAKE_PHY) - ctrl |= WOL_CTL_ENA_PME_ON_LINK_CHG|WOL_CTL_ENA_LINK_CHG_UNIT; - else - ctrl |= WOL_CTL_DIS_PME_ON_LINK_CHG|WOL_CTL_DIS_LINK_CHG_UNIT; - - if (skge->wol & WAKE_MAGIC) - ctrl |= WOL_CTL_ENA_PME_ON_MAGIC_PKT|WOL_CTL_ENA_MAGIC_PKT_UNIT; - else - ctrl |= WOL_CTL_DIS_PME_ON_MAGIC_PKT|WOL_CTL_DIS_MAGIC_PKT_UNIT; - - ctrl |= WOL_CTL_DIS_PME_ON_PATTERN|WOL_CTL_DIS_PATTERN_UNIT; - skge_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl); - - /* block receiver */ - skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); -} - -static void skge_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct skge_port *skge = netdev_priv(dev); - - wol->supported = wol_supported(skge->hw); - wol->wolopts = skge->wol; -} - -static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - - if ((wol->wolopts & ~wol_supported(hw)) || - !device_can_wakeup(&hw->pdev->dev)) - return -EOPNOTSUPP; - - skge->wol = wol->wolopts; - - device_set_wakeup_enable(&hw->pdev->dev, skge->wol); - - return 0; -} - -/* Determine supported/advertised modes based on hardware. - * Note: ethtool ADVERTISED_xxx == SUPPORTED_xxx - */ -static u32 skge_supported_modes(const struct skge_hw *hw) -{ - u32 supported; - - if (hw->copper) { - supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Half | - SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP); - - if (is_genesis(hw)) - supported &= ~(SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full); - - else if (hw->chip_id == CHIP_ID_YUKON) - supported &= ~SUPPORTED_1000baseT_Half; - } else - supported = (SUPPORTED_1000baseT_Full | - SUPPORTED_1000baseT_Half | - SUPPORTED_FIBRE | - SUPPORTED_Autoneg); - - return supported; -} - -static int skge_get_settings(struct net_device *dev, - struct ethtool_cmd *ecmd) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - - ecmd->transceiver = XCVR_INTERNAL; - ecmd->supported = skge_supported_modes(hw); - - if (hw->copper) { - ecmd->port = PORT_TP; - ecmd->phy_address = hw->phy_addr; - } else - ecmd->port = PORT_FIBRE; - - ecmd->advertising = skge->advertising; - ecmd->autoneg = skge->autoneg; - ethtool_cmd_speed_set(ecmd, skge->speed); - ecmd->duplex = skge->duplex; - return 0; -} - -static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) -{ - struct skge_port *skge = netdev_priv(dev); - const struct skge_hw *hw = skge->hw; - u32 supported = skge_supported_modes(hw); - int err = 0; - - if (ecmd->autoneg == AUTONEG_ENABLE) { - ecmd->advertising = supported; - skge->duplex = -1; - skge->speed = -1; - } else { - u32 setting; - u32 speed = ethtool_cmd_speed(ecmd); - - switch (speed) { - case SPEED_1000: - if (ecmd->duplex == DUPLEX_FULL) - setting = SUPPORTED_1000baseT_Full; - else if (ecmd->duplex == DUPLEX_HALF) - setting = SUPPORTED_1000baseT_Half; - else - return -EINVAL; - break; - case SPEED_100: - if (ecmd->duplex == DUPLEX_FULL) - setting = SUPPORTED_100baseT_Full; - else if (ecmd->duplex == DUPLEX_HALF) - setting = SUPPORTED_100baseT_Half; - else - return -EINVAL; - break; - - case SPEED_10: - if (ecmd->duplex == DUPLEX_FULL) - setting = SUPPORTED_10baseT_Full; - else if (ecmd->duplex == DUPLEX_HALF) - setting = SUPPORTED_10baseT_Half; - else - return -EINVAL; - break; - default: - return -EINVAL; - } - - if ((setting & supported) == 0) - return -EINVAL; - - skge->speed = speed; - skge->duplex = ecmd->duplex; - } - - skge->autoneg = ecmd->autoneg; - skge->advertising = ecmd->advertising; - - if (netif_running(dev)) { - skge_down(dev); - err = skge_up(dev); - if (err) { - dev_close(dev); - return err; - } - } - - return 0; -} - -static void skge_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct skge_port *skge = netdev_priv(dev); - - strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); - strlcpy(info->version, DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, pci_name(skge->hw->pdev), - sizeof(info->bus_info)); -} - -static const struct skge_stat { - char name[ETH_GSTRING_LEN]; - u16 xmac_offset; - u16 gma_offset; -} skge_stats[] = { - { "tx_bytes", XM_TXO_OK_HI, GM_TXO_OK_HI }, - { "rx_bytes", XM_RXO_OK_HI, GM_RXO_OK_HI }, - - { "tx_broadcast", XM_TXF_BC_OK, GM_TXF_BC_OK }, - { "rx_broadcast", XM_RXF_BC_OK, GM_RXF_BC_OK }, - { "tx_multicast", XM_TXF_MC_OK, GM_TXF_MC_OK }, - { "rx_multicast", XM_RXF_MC_OK, GM_RXF_MC_OK }, - { "tx_unicast", XM_TXF_UC_OK, GM_TXF_UC_OK }, - { "rx_unicast", XM_RXF_UC_OK, GM_RXF_UC_OK }, - { "tx_mac_pause", XM_TXF_MPAUSE, GM_TXF_MPAUSE }, - { "rx_mac_pause", XM_RXF_MPAUSE, GM_RXF_MPAUSE }, - - { "collisions", XM_TXF_SNG_COL, GM_TXF_SNG_COL }, - { "multi_collisions", XM_TXF_MUL_COL, GM_TXF_MUL_COL }, - { "aborted", XM_TXF_ABO_COL, GM_TXF_ABO_COL }, - { "late_collision", XM_TXF_LAT_COL, GM_TXF_LAT_COL }, - { "fifo_underrun", XM_TXE_FIFO_UR, GM_TXE_FIFO_UR }, - { "fifo_overflow", XM_RXE_FIFO_OV, GM_RXE_FIFO_OV }, - - { "rx_toolong", XM_RXF_LNG_ERR, GM_RXF_LNG_ERR }, - { "rx_jabber", XM_RXF_JAB_PKT, GM_RXF_JAB_PKT }, - { "rx_runt", XM_RXE_RUNT, GM_RXE_FRAG }, - { "rx_too_long", XM_RXF_LNG_ERR, GM_RXF_LNG_ERR }, - { "rx_fcs_error", XM_RXF_FCS_ERR, GM_RXF_FCS_ERR }, -}; - -static int skge_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(skge_stats); - default: - return -EOPNOTSUPP; - } -} - -static void skge_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct skge_port *skge = netdev_priv(dev); - - if (is_genesis(skge->hw)) - genesis_get_stats(skge, data); - else - yukon_get_stats(skge, data); -} - -/* Use hardware MIB variables for critical path statistics and - * transmit feedback not reported at interrupt. - * Other errors are accounted for in interrupt handler. - */ -static struct net_device_stats *skge_get_stats(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - u64 data[ARRAY_SIZE(skge_stats)]; - - if (is_genesis(skge->hw)) - genesis_get_stats(skge, data); - else - yukon_get_stats(skge, data); - - dev->stats.tx_bytes = data[0]; - dev->stats.rx_bytes = data[1]; - dev->stats.tx_packets = data[2] + data[4] + data[6]; - dev->stats.rx_packets = data[3] + data[5] + data[7]; - dev->stats.multicast = data[3] + data[5]; - dev->stats.collisions = data[10]; - dev->stats.tx_aborted_errors = data[12]; - - return &dev->stats; -} - -static void skge_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - int i; - - switch (stringset) { - case ETH_SS_STATS: - for (i = 0; i < ARRAY_SIZE(skge_stats); i++) - memcpy(data + i * ETH_GSTRING_LEN, - skge_stats[i].name, ETH_GSTRING_LEN); - break; - } -} - -static void skge_get_ring_param(struct net_device *dev, - struct ethtool_ringparam *p) -{ - struct skge_port *skge = netdev_priv(dev); - - p->rx_max_pending = MAX_RX_RING_SIZE; - p->tx_max_pending = MAX_TX_RING_SIZE; - - p->rx_pending = skge->rx_ring.count; - p->tx_pending = skge->tx_ring.count; -} - -static int skge_set_ring_param(struct net_device *dev, - struct ethtool_ringparam *p) -{ - struct skge_port *skge = netdev_priv(dev); - int err = 0; - - if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE || - p->tx_pending < TX_LOW_WATER || p->tx_pending > MAX_TX_RING_SIZE) - return -EINVAL; - - skge->rx_ring.count = p->rx_pending; - skge->tx_ring.count = p->tx_pending; - - if (netif_running(dev)) { - skge_down(dev); - err = skge_up(dev); - if (err) - dev_close(dev); - } - - return err; -} - -static u32 skge_get_msglevel(struct net_device *netdev) -{ - struct skge_port *skge = netdev_priv(netdev); - return skge->msg_enable; -} - -static void skge_set_msglevel(struct net_device *netdev, u32 value) -{ - struct skge_port *skge = netdev_priv(netdev); - skge->msg_enable = value; -} - -static int skge_nway_reset(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - - if (skge->autoneg != AUTONEG_ENABLE || !netif_running(dev)) - return -EINVAL; - - skge_phy_reset(skge); - return 0; -} - -static void skge_get_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *ecmd) -{ - struct skge_port *skge = netdev_priv(dev); - - ecmd->rx_pause = ((skge->flow_control == FLOW_MODE_SYMMETRIC) || - (skge->flow_control == FLOW_MODE_SYM_OR_REM)); - ecmd->tx_pause = (ecmd->rx_pause || - (skge->flow_control == FLOW_MODE_LOC_SEND)); - - ecmd->autoneg = ecmd->rx_pause || ecmd->tx_pause; -} - -static int skge_set_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *ecmd) -{ - struct skge_port *skge = netdev_priv(dev); - struct ethtool_pauseparam old; - int err = 0; - - skge_get_pauseparam(dev, &old); - - if (ecmd->autoneg != old.autoneg) - skge->flow_control = ecmd->autoneg ? FLOW_MODE_NONE : FLOW_MODE_SYMMETRIC; - else { - if (ecmd->rx_pause && ecmd->tx_pause) - skge->flow_control = FLOW_MODE_SYMMETRIC; - else if (ecmd->rx_pause && !ecmd->tx_pause) - skge->flow_control = FLOW_MODE_SYM_OR_REM; - else if (!ecmd->rx_pause && ecmd->tx_pause) - skge->flow_control = FLOW_MODE_LOC_SEND; - else - skge->flow_control = FLOW_MODE_NONE; - } - - if (netif_running(dev)) { - skge_down(dev); - err = skge_up(dev); - if (err) { - dev_close(dev); - return err; - } - } - - return 0; -} - -/* Chip internal frequency for clock calculations */ -static inline u32 hwkhz(const struct skge_hw *hw) -{ - return is_genesis(hw) ? 53125 : 78125; -} - -/* Chip HZ to microseconds */ -static inline u32 skge_clk2usec(const struct skge_hw *hw, u32 ticks) -{ - return (ticks * 1000) / hwkhz(hw); -} - -/* Microseconds to chip HZ */ -static inline u32 skge_usecs2clk(const struct skge_hw *hw, u32 usec) -{ - return hwkhz(hw) * usec / 1000; -} - -static int skge_get_coalesce(struct net_device *dev, - struct ethtool_coalesce *ecmd) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - - ecmd->rx_coalesce_usecs = 0; - ecmd->tx_coalesce_usecs = 0; - - if (skge_read32(hw, B2_IRQM_CTRL) & TIM_START) { - u32 delay = skge_clk2usec(hw, skge_read32(hw, B2_IRQM_INI)); - u32 msk = skge_read32(hw, B2_IRQM_MSK); - - if (msk & rxirqmask[port]) - ecmd->rx_coalesce_usecs = delay; - if (msk & txirqmask[port]) - ecmd->tx_coalesce_usecs = delay; - } - - return 0; -} - -/* Note: interrupt timer is per board, but can turn on/off per port */ -static int skge_set_coalesce(struct net_device *dev, - struct ethtool_coalesce *ecmd) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - u32 msk = skge_read32(hw, B2_IRQM_MSK); - u32 delay = 25; - - if (ecmd->rx_coalesce_usecs == 0) - msk &= ~rxirqmask[port]; - else if (ecmd->rx_coalesce_usecs < 25 || - ecmd->rx_coalesce_usecs > 33333) - return -EINVAL; - else { - msk |= rxirqmask[port]; - delay = ecmd->rx_coalesce_usecs; - } - - if (ecmd->tx_coalesce_usecs == 0) - msk &= ~txirqmask[port]; - else if (ecmd->tx_coalesce_usecs < 25 || - ecmd->tx_coalesce_usecs > 33333) - return -EINVAL; - else { - msk |= txirqmask[port]; - delay = min(delay, ecmd->rx_coalesce_usecs); - } - - skge_write32(hw, B2_IRQM_MSK, msk); - if (msk == 0) - skge_write32(hw, B2_IRQM_CTRL, TIM_STOP); - else { - skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, delay)); - skge_write32(hw, B2_IRQM_CTRL, TIM_START); - } - return 0; -} - -enum led_mode { LED_MODE_OFF, LED_MODE_ON, LED_MODE_TST }; -static void skge_led(struct skge_port *skge, enum led_mode mode) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - - spin_lock_bh(&hw->phy_lock); - if (is_genesis(hw)) { - switch (mode) { - case LED_MODE_OFF: - if (hw->phy_type == SK_PHY_BCOM) - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); - else { - skge_write32(hw, SK_REG(port, TX_LED_VAL), 0); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_T_OFF); - } - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); - skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); - break; - - case LED_MODE_ON: - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON); - - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); - - break; - - case LED_MODE_TST: - skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON); - skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); - - if (hw->phy_type == SK_PHY_BCOM) - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); - else { - skge_write8(hw, SK_REG(port, TX_LED_TST), LED_T_ON); - skge_write32(hw, SK_REG(port, TX_LED_VAL), 100); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); - } - - } - } else { - switch (mode) { - case LED_MODE_OFF: - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_DUP(MO_LED_OFF) | - PHY_M_LED_MO_10(MO_LED_OFF) | - PHY_M_LED_MO_100(MO_LED_OFF) | - PHY_M_LED_MO_1000(MO_LED_OFF) | - PHY_M_LED_MO_RX(MO_LED_OFF)); - break; - case LED_MODE_ON: - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, - PHY_M_LED_PULS_DUR(PULS_170MS) | - PHY_M_LED_BLINK_RT(BLINK_84MS) | - PHY_M_LEDC_TX_CTRL | - PHY_M_LEDC_DP_CTRL); - - gm_phy_write(hw, port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_RX(MO_LED_OFF) | - (skge->speed == SPEED_100 ? - PHY_M_LED_MO_100(MO_LED_ON) : 0)); - break; - case LED_MODE_TST: - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_DUP(MO_LED_ON) | - PHY_M_LED_MO_10(MO_LED_ON) | - PHY_M_LED_MO_100(MO_LED_ON) | - PHY_M_LED_MO_1000(MO_LED_ON) | - PHY_M_LED_MO_RX(MO_LED_ON)); - } - } - spin_unlock_bh(&hw->phy_lock); -} - -/* blink LED's for finding board */ -static int skge_set_phys_id(struct net_device *dev, - enum ethtool_phys_id_state state) -{ - struct skge_port *skge = netdev_priv(dev); - - switch (state) { - case ETHTOOL_ID_ACTIVE: - return 2; /* cycle on/off twice per second */ - - case ETHTOOL_ID_ON: - skge_led(skge, LED_MODE_TST); - break; - - case ETHTOOL_ID_OFF: - skge_led(skge, LED_MODE_OFF); - break; - - case ETHTOOL_ID_INACTIVE: - /* back to regular LED state */ - skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF); - } - - return 0; -} - -static int skge_get_eeprom_len(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - u32 reg2; - - pci_read_config_dword(skge->hw->pdev, PCI_DEV_REG2, ®2); - return 1 << (((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); -} - -static u32 skge_vpd_read(struct pci_dev *pdev, int cap, u16 offset) -{ - u32 val; - - pci_write_config_word(pdev, cap + PCI_VPD_ADDR, offset); - - do { - pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset); - } while (!(offset & PCI_VPD_ADDR_F)); - - pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &val); - return val; -} - -static void skge_vpd_write(struct pci_dev *pdev, int cap, u16 offset, u32 val) -{ - pci_write_config_dword(pdev, cap + PCI_VPD_DATA, val); - pci_write_config_word(pdev, cap + PCI_VPD_ADDR, - offset | PCI_VPD_ADDR_F); - - do { - pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset); - } while (offset & PCI_VPD_ADDR_F); -} - -static int skge_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, - u8 *data) -{ - struct skge_port *skge = netdev_priv(dev); - struct pci_dev *pdev = skge->hw->pdev; - int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD); - int length = eeprom->len; - u16 offset = eeprom->offset; - - if (!cap) - return -EINVAL; - - eeprom->magic = SKGE_EEPROM_MAGIC; - - while (length > 0) { - u32 val = skge_vpd_read(pdev, cap, offset); - int n = min_t(int, length, sizeof(val)); - - memcpy(data, &val, n); - length -= n; - data += n; - offset += n; - } - return 0; -} - -static int skge_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, - u8 *data) -{ - struct skge_port *skge = netdev_priv(dev); - struct pci_dev *pdev = skge->hw->pdev; - int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD); - int length = eeprom->len; - u16 offset = eeprom->offset; - - if (!cap) - return -EINVAL; - - if (eeprom->magic != SKGE_EEPROM_MAGIC) - return -EINVAL; - - while (length > 0) { - u32 val; - int n = min_t(int, length, sizeof(val)); - - if (n < sizeof(val)) - val = skge_vpd_read(pdev, cap, offset); - memcpy(&val, data, n); - - skge_vpd_write(pdev, cap, offset, val); - - length -= n; - data += n; - offset += n; - } - return 0; -} - -static const struct ethtool_ops skge_ethtool_ops = { - .get_settings = skge_get_settings, - .set_settings = skge_set_settings, - .get_drvinfo = skge_get_drvinfo, - .get_regs_len = skge_get_regs_len, - .get_regs = skge_get_regs, - .get_wol = skge_get_wol, - .set_wol = skge_set_wol, - .get_msglevel = skge_get_msglevel, - .set_msglevel = skge_set_msglevel, - .nway_reset = skge_nway_reset, - .get_link = ethtool_op_get_link, - .get_eeprom_len = skge_get_eeprom_len, - .get_eeprom = skge_get_eeprom, - .set_eeprom = skge_set_eeprom, - .get_ringparam = skge_get_ring_param, - .set_ringparam = skge_set_ring_param, - .get_pauseparam = skge_get_pauseparam, - .set_pauseparam = skge_set_pauseparam, - .get_coalesce = skge_get_coalesce, - .set_coalesce = skge_set_coalesce, - .get_strings = skge_get_strings, - .set_phys_id = skge_set_phys_id, - .get_sset_count = skge_get_sset_count, - .get_ethtool_stats = skge_get_ethtool_stats, -}; - -/* - * Allocate ring elements and chain them together - * One-to-one association of board descriptors with ring elements - */ -static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base) -{ - struct skge_tx_desc *d; - struct skge_element *e; - int i; - - ring->start = kcalloc(ring->count, sizeof(*e), GFP_KERNEL); - if (!ring->start) - return -ENOMEM; - - for (i = 0, e = ring->start, d = vaddr; i < ring->count; i++, e++, d++) { - e->desc = d; - if (i == ring->count - 1) { - e->next = ring->start; - d->next_offset = base; - } else { - e->next = e + 1; - d->next_offset = base + (i+1) * sizeof(*d); - } - } - ring->to_use = ring->to_clean = ring->start; - - return 0; -} - -/* Allocate and setup a new buffer for receiving */ -static void skge_rx_setup(struct skge_port *skge, struct skge_element *e, - struct sk_buff *skb, unsigned int bufsize) -{ - struct skge_rx_desc *rd = e->desc; - u64 map; - - map = pci_map_single(skge->hw->pdev, skb->data, bufsize, - PCI_DMA_FROMDEVICE); - - rd->dma_lo = map; - rd->dma_hi = map >> 32; - e->skb = skb; - rd->csum1_start = ETH_HLEN; - rd->csum2_start = ETH_HLEN; - rd->csum1 = 0; - rd->csum2 = 0; - - wmb(); - - rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize; - dma_unmap_addr_set(e, mapaddr, map); - dma_unmap_len_set(e, maplen, bufsize); -} - -/* Resume receiving using existing skb, - * Note: DMA address is not changed by chip. - * MTU not changed while receiver active. - */ -static inline void skge_rx_reuse(struct skge_element *e, unsigned int size) -{ - struct skge_rx_desc *rd = e->desc; - - rd->csum2 = 0; - rd->csum2_start = ETH_HLEN; - - wmb(); - - rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | size; -} - - -/* Free all buffers in receive ring, assumes receiver stopped */ -static void skge_rx_clean(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - struct skge_ring *ring = &skge->rx_ring; - struct skge_element *e; - - e = ring->start; - do { - struct skge_rx_desc *rd = e->desc; - rd->control = 0; - if (e->skb) { - pci_unmap_single(hw->pdev, - dma_unmap_addr(e, mapaddr), - dma_unmap_len(e, maplen), - PCI_DMA_FROMDEVICE); - dev_kfree_skb(e->skb); - e->skb = NULL; - } - } while ((e = e->next) != ring->start); -} - - -/* Allocate buffers for receive ring - * For receive: to_clean is next received frame. - */ -static int skge_rx_fill(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_ring *ring = &skge->rx_ring; - struct skge_element *e; - - e = ring->start; - do { - struct sk_buff *skb; - - skb = __netdev_alloc_skb(dev, skge->rx_buf_size + NET_IP_ALIGN, - GFP_KERNEL); - if (!skb) - return -ENOMEM; - - skb_reserve(skb, NET_IP_ALIGN); - skge_rx_setup(skge, e, skb, skge->rx_buf_size); - } while ((e = e->next) != ring->start); - - ring->to_clean = ring->start; - return 0; -} - -static const char *skge_pause(enum pause_status status) -{ - switch (status) { - case FLOW_STAT_NONE: - return "none"; - case FLOW_STAT_REM_SEND: - return "rx only"; - case FLOW_STAT_LOC_SEND: - return "tx_only"; - case FLOW_STAT_SYMMETRIC: /* Both station may send PAUSE */ - return "both"; - default: - return "indeterminated"; - } -} - - -static void skge_link_up(struct skge_port *skge) -{ - skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), - LED_BLK_OFF|LED_SYNC_OFF|LED_ON); - - netif_carrier_on(skge->netdev); - netif_wake_queue(skge->netdev); - - netif_info(skge, link, skge->netdev, - "Link is up at %d Mbps, %s duplex, flow control %s\n", - skge->speed, - skge->duplex == DUPLEX_FULL ? "full" : "half", - skge_pause(skge->flow_status)); -} - -static void skge_link_down(struct skge_port *skge) -{ - skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); - netif_carrier_off(skge->netdev); - netif_stop_queue(skge->netdev); - - netif_info(skge, link, skge->netdev, "Link is down\n"); -} - -static void xm_link_down(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); - - xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE); - - if (netif_carrier_ok(dev)) - skge_link_down(skge); -} - -static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val) -{ - int i; - - xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); - *val = xm_read16(hw, port, XM_PHY_DATA); - - if (hw->phy_type == SK_PHY_XMAC) - goto ready; - - for (i = 0; i < PHY_RETRIES; i++) { - if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY) - goto ready; - udelay(1); - } - - return -ETIMEDOUT; - ready: - *val = xm_read16(hw, port, XM_PHY_DATA); - - return 0; -} - -static u16 xm_phy_read(struct skge_hw *hw, int port, u16 reg) -{ - u16 v = 0; - if (__xm_phy_read(hw, port, reg, &v)) - pr_warning("%s: phy read timed out\n", hw->dev[port]->name); - return v; -} - -static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) -{ - int i; - - xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); - for (i = 0; i < PHY_RETRIES; i++) { - if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY)) - goto ready; - udelay(1); - } - return -EIO; - - ready: - xm_write16(hw, port, XM_PHY_DATA, val); - for (i = 0; i < PHY_RETRIES; i++) { - if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY)) - return 0; - udelay(1); - } - return -ETIMEDOUT; -} - -static void genesis_init(struct skge_hw *hw) -{ - /* set blink source counter */ - skge_write32(hw, B2_BSC_INI, (SK_BLK_DUR * SK_FACT_53) / 100); - skge_write8(hw, B2_BSC_CTRL, BSC_START); - - /* configure mac arbiter */ - skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR); - - /* configure mac arbiter timeout values */ - skge_write8(hw, B3_MA_TOINI_RX1, SK_MAC_TO_53); - skge_write8(hw, B3_MA_TOINI_RX2, SK_MAC_TO_53); - skge_write8(hw, B3_MA_TOINI_TX1, SK_MAC_TO_53); - skge_write8(hw, B3_MA_TOINI_TX2, SK_MAC_TO_53); - - skge_write8(hw, B3_MA_RCINI_RX1, 0); - skge_write8(hw, B3_MA_RCINI_RX2, 0); - skge_write8(hw, B3_MA_RCINI_TX1, 0); - skge_write8(hw, B3_MA_RCINI_TX2, 0); - - /* configure packet arbiter timeout */ - skge_write16(hw, B3_PA_CTRL, PA_RST_CLR); - skge_write16(hw, B3_PA_TOINI_RX1, SK_PKT_TO_MAX); - skge_write16(hw, B3_PA_TOINI_TX1, SK_PKT_TO_MAX); - skge_write16(hw, B3_PA_TOINI_RX2, SK_PKT_TO_MAX); - skge_write16(hw, B3_PA_TOINI_TX2, SK_PKT_TO_MAX); -} - -static void genesis_reset(struct skge_hw *hw, int port) -{ - static const u8 zero[8] = { 0 }; - u32 reg; - - skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); - - /* reset the statistics module */ - xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT); - xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE); - xm_write32(hw, port, XM_MODE, 0); /* clear Mode Reg */ - xm_write16(hw, port, XM_TX_CMD, 0); /* reset TX CMD Reg */ - xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */ - - /* disable Broadcom PHY IRQ */ - if (hw->phy_type == SK_PHY_BCOM) - xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff); - - xm_outhash(hw, port, XM_HSM, zero); - - /* Flush TX and RX fifo */ - reg = xm_read32(hw, port, XM_MODE); - xm_write32(hw, port, XM_MODE, reg | XM_MD_FTF); - xm_write32(hw, port, XM_MODE, reg | XM_MD_FRF); -} - -/* Convert mode to MII values */ -static const u16 phy_pause_map[] = { - [FLOW_MODE_NONE] = 0, - [FLOW_MODE_LOC_SEND] = PHY_AN_PAUSE_ASYM, - [FLOW_MODE_SYMMETRIC] = PHY_AN_PAUSE_CAP, - [FLOW_MODE_SYM_OR_REM] = PHY_AN_PAUSE_CAP | PHY_AN_PAUSE_ASYM, -}; - -/* special defines for FIBER (88E1011S only) */ -static const u16 fiber_pause_map[] = { - [FLOW_MODE_NONE] = PHY_X_P_NO_PAUSE, - [FLOW_MODE_LOC_SEND] = PHY_X_P_ASYM_MD, - [FLOW_MODE_SYMMETRIC] = PHY_X_P_SYM_MD, - [FLOW_MODE_SYM_OR_REM] = PHY_X_P_BOTH_MD, -}; - - -/* Check status of Broadcom phy link */ -static void bcom_check_link(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); - u16 status; - - /* read twice because of latch */ - xm_phy_read(hw, port, PHY_BCOM_STAT); - status = xm_phy_read(hw, port, PHY_BCOM_STAT); - - if ((status & PHY_ST_LSYNC) == 0) { - xm_link_down(hw, port); - return; - } - - if (skge->autoneg == AUTONEG_ENABLE) { - u16 lpa, aux; - - if (!(status & PHY_ST_AN_OVER)) - return; - - lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP); - if (lpa & PHY_B_AN_RF) { - netdev_notice(dev, "remote fault\n"); - return; - } - - aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT); - - /* Check Duplex mismatch */ - switch (aux & PHY_B_AS_AN_RES_MSK) { - case PHY_B_RES_1000FD: - skge->duplex = DUPLEX_FULL; - break; - case PHY_B_RES_1000HD: - skge->duplex = DUPLEX_HALF; - break; - default: - netdev_notice(dev, "duplex mismatch\n"); - return; - } - - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - switch (aux & PHY_B_AS_PAUSE_MSK) { - case PHY_B_AS_PAUSE_MSK: - skge->flow_status = FLOW_STAT_SYMMETRIC; - break; - case PHY_B_AS_PRR: - skge->flow_status = FLOW_STAT_REM_SEND; - break; - case PHY_B_AS_PRT: - skge->flow_status = FLOW_STAT_LOC_SEND; - break; - default: - skge->flow_status = FLOW_STAT_NONE; - } - skge->speed = SPEED_1000; - } - - if (!netif_carrier_ok(dev)) - genesis_link_up(skge); -} - -/* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional - * Phy on for 100 or 10Mbit operation - */ -static void bcom_phy_init(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - int i; - u16 id1, r, ext, ctl; - - /* magic workaround patterns for Broadcom */ - static const struct { - u16 reg; - u16 val; - } A1hack[] = { - { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, - { 0x17, 0x0013 }, { 0x15, 0x0404 }, { 0x17, 0x8006 }, - { 0x15, 0x0132 }, { 0x17, 0x8006 }, { 0x15, 0x0232 }, - { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 }, - }, C0hack[] = { - { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, - { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 }, - }; - - /* read Id from external PHY (all have the same address) */ - id1 = xm_phy_read(hw, port, PHY_XMAC_ID1); - - /* Optimize MDIO transfer by suppressing preamble. */ - r = xm_read16(hw, port, XM_MMU_CMD); - r |= XM_MMU_NO_PRE; - xm_write16(hw, port, XM_MMU_CMD, r); - - switch (id1) { - case PHY_BCOM_ID1_C0: - /* - * Workaround BCOM Errata for the C0 type. - * Write magic patterns to reserved registers. - */ - for (i = 0; i < ARRAY_SIZE(C0hack); i++) - xm_phy_write(hw, port, - C0hack[i].reg, C0hack[i].val); - - break; - case PHY_BCOM_ID1_A1: - /* - * Workaround BCOM Errata for the A1 type. - * Write magic patterns to reserved registers. - */ - for (i = 0; i < ARRAY_SIZE(A1hack); i++) - xm_phy_write(hw, port, - A1hack[i].reg, A1hack[i].val); - break; - } - - /* - * Workaround BCOM Errata (#10523) for all BCom PHYs. - * Disable Power Management after reset. - */ - r = xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL); - r |= PHY_B_AC_DIS_PM; - xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, r); - - /* Dummy read */ - xm_read16(hw, port, XM_ISRC); - - ext = PHY_B_PEC_EN_LTR; /* enable tx led */ - ctl = PHY_CT_SP1000; /* always 1000mbit */ - - if (skge->autoneg == AUTONEG_ENABLE) { - /* - * Workaround BCOM Errata #1 for the C5 type. - * 1000Base-T Link Acquisition Failure in Slave Mode - * Set Repeater/DTE bit 10 of the 1000Base-T Control Register - */ - u16 adv = PHY_B_1000C_RD; - if (skge->advertising & ADVERTISED_1000baseT_Half) - adv |= PHY_B_1000C_AHD; - if (skge->advertising & ADVERTISED_1000baseT_Full) - adv |= PHY_B_1000C_AFD; - xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, adv); - - ctl |= PHY_CT_ANE | PHY_CT_RE_CFG; - } else { - if (skge->duplex == DUPLEX_FULL) - ctl |= PHY_CT_DUP_MD; - /* Force to slave */ - xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, PHY_B_1000C_MSE); - } - - /* Set autonegotiation pause parameters */ - xm_phy_write(hw, port, PHY_BCOM_AUNE_ADV, - phy_pause_map[skge->flow_control] | PHY_AN_CSMA); - - /* Handle Jumbo frames */ - if (hw->dev[port]->mtu > ETH_DATA_LEN) { - xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, - PHY_B_AC_TX_TST | PHY_B_AC_LONG_PACK); - - ext |= PHY_B_PEC_HIGH_LA; - - } - - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ext); - xm_phy_write(hw, port, PHY_BCOM_CTRL, ctl); - - /* Use link status change interrupt */ - xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); -} - -static void xm_phy_init(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 ctrl = 0; - - if (skge->autoneg == AUTONEG_ENABLE) { - if (skge->advertising & ADVERTISED_1000baseT_Half) - ctrl |= PHY_X_AN_HD; - if (skge->advertising & ADVERTISED_1000baseT_Full) - ctrl |= PHY_X_AN_FD; - - ctrl |= fiber_pause_map[skge->flow_control]; - - xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl); - - /* Restart Auto-negotiation */ - ctrl = PHY_CT_ANE | PHY_CT_RE_CFG; - } else { - /* Set DuplexMode in Config register */ - if (skge->duplex == DUPLEX_FULL) - ctrl |= PHY_CT_DUP_MD; - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLEs are transmitted - */ - } - - xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl); - - /* Poll PHY for status changes */ - mod_timer(&skge->link_timer, jiffies + LINK_HZ); -} - -static int xm_check_link(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 status; - - /* read twice because of latch */ - xm_phy_read(hw, port, PHY_XMAC_STAT); - status = xm_phy_read(hw, port, PHY_XMAC_STAT); - - if ((status & PHY_ST_LSYNC) == 0) { - xm_link_down(hw, port); - return 0; - } - - if (skge->autoneg == AUTONEG_ENABLE) { - u16 lpa, res; - - if (!(status & PHY_ST_AN_OVER)) - return 0; - - lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP); - if (lpa & PHY_B_AN_RF) { - netdev_notice(dev, "remote fault\n"); - return 0; - } - - res = xm_phy_read(hw, port, PHY_XMAC_RES_ABI); - - /* Check Duplex mismatch */ - switch (res & (PHY_X_RS_HD | PHY_X_RS_FD)) { - case PHY_X_RS_FD: - skge->duplex = DUPLEX_FULL; - break; - case PHY_X_RS_HD: - skge->duplex = DUPLEX_HALF; - break; - default: - netdev_notice(dev, "duplex mismatch\n"); - return 0; - } - - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - if ((skge->flow_control == FLOW_MODE_SYMMETRIC || - skge->flow_control == FLOW_MODE_SYM_OR_REM) && - (lpa & PHY_X_P_SYM_MD)) - skge->flow_status = FLOW_STAT_SYMMETRIC; - else if (skge->flow_control == FLOW_MODE_SYM_OR_REM && - (lpa & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) - /* Enable PAUSE receive, disable PAUSE transmit */ - skge->flow_status = FLOW_STAT_REM_SEND; - else if (skge->flow_control == FLOW_MODE_LOC_SEND && - (lpa & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) - /* Disable PAUSE receive, enable PAUSE transmit */ - skge->flow_status = FLOW_STAT_LOC_SEND; - else - skge->flow_status = FLOW_STAT_NONE; - - skge->speed = SPEED_1000; - } - - if (!netif_carrier_ok(dev)) - genesis_link_up(skge); - return 1; -} - -/* Poll to check for link coming up. - * - * Since internal PHY is wired to a level triggered pin, can't - * get an interrupt when carrier is detected, need to poll for - * link coming up. - */ -static void xm_link_timer(unsigned long arg) -{ - struct skge_port *skge = (struct skge_port *) arg; - struct net_device *dev = skge->netdev; - struct skge_hw *hw = skge->hw; - int port = skge->port; - int i; - unsigned long flags; - - if (!netif_running(dev)) - return; - - spin_lock_irqsave(&hw->phy_lock, flags); - - /* - * Verify that the link by checking GPIO register three times. - * This pin has the signal from the link_sync pin connected to it. - */ - for (i = 0; i < 3; i++) { - if (xm_read16(hw, port, XM_GP_PORT) & XM_GP_INP_ASS) - goto link_down; - } - - /* Re-enable interrupt to detect link down */ - if (xm_check_link(dev)) { - u16 msk = xm_read16(hw, port, XM_IMSK); - msk &= ~XM_IS_INP_ASS; - xm_write16(hw, port, XM_IMSK, msk); - xm_read16(hw, port, XM_ISRC); - } else { -link_down: - mod_timer(&skge->link_timer, - round_jiffies(jiffies + LINK_HZ)); - } - spin_unlock_irqrestore(&hw->phy_lock, flags); -} - -static void genesis_mac_init(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); - int jumbo = hw->dev[port]->mtu > ETH_DATA_LEN; - int i; - u32 r; - static const u8 zero[6] = { 0 }; - - for (i = 0; i < 10; i++) { - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), - MFF_SET_MAC_RST); - if (skge_read16(hw, SK_REG(port, TX_MFF_CTRL1)) & MFF_SET_MAC_RST) - goto reset_ok; - udelay(1); - } - - netdev_warn(dev, "genesis reset failed\n"); - - reset_ok: - /* Unreset the XMAC. */ - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); - - /* - * Perform additional initialization for external PHYs, - * namely for the 1000baseTX cards that use the XMAC's - * GMII mode. - */ - if (hw->phy_type != SK_PHY_XMAC) { - /* Take external Phy out of reset */ - r = skge_read32(hw, B2_GP_IO); - if (port == 0) - r |= GP_DIR_0|GP_IO_0; - else - r |= GP_DIR_2|GP_IO_2; - - skge_write32(hw, B2_GP_IO, r); - - /* Enable GMII interface */ - xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); - } - - - switch (hw->phy_type) { - case SK_PHY_XMAC: - xm_phy_init(skge); - break; - case SK_PHY_BCOM: - bcom_phy_init(skge); - bcom_check_link(hw, port); - } - - /* Set Station Address */ - xm_outaddr(hw, port, XM_SA, dev->dev_addr); - - /* We don't use match addresses so clear */ - for (i = 1; i < 16; i++) - xm_outaddr(hw, port, XM_EXM(i), zero); - - /* Clear MIB counters */ - xm_write16(hw, port, XM_STAT_CMD, - XM_SC_CLR_RXC | XM_SC_CLR_TXC); - /* Clear two times according to Errata #3 */ - xm_write16(hw, port, XM_STAT_CMD, - XM_SC_CLR_RXC | XM_SC_CLR_TXC); - - /* configure Rx High Water Mark (XM_RX_HI_WM) */ - xm_write16(hw, port, XM_RX_HI_WM, 1450); - - /* We don't need the FCS appended to the packet. */ - r = XM_RX_LENERR_OK | XM_RX_STRIP_FCS; - if (jumbo) - r |= XM_RX_BIG_PK_OK; - - if (skge->duplex == DUPLEX_HALF) { - /* - * If in manual half duplex mode the other side might be in - * full duplex mode, so ignore if a carrier extension is not seen - * on frames received - */ - r |= XM_RX_DIS_CEXT; - } - xm_write16(hw, port, XM_RX_CMD, r); - - /* We want short frames padded to 60 bytes. */ - xm_write16(hw, port, XM_TX_CMD, XM_TX_AUTO_PAD); - - /* Increase threshold for jumbo frames on dual port */ - if (hw->ports > 1 && jumbo) - xm_write16(hw, port, XM_TX_THR, 1020); - else - xm_write16(hw, port, XM_TX_THR, 512); - - /* - * Enable the reception of all error frames. This is is - * a necessary evil due to the design of the XMAC. The - * XMAC's receive FIFO is only 8K in size, however jumbo - * frames can be up to 9000 bytes in length. When bad - * frame filtering is enabled, the XMAC's RX FIFO operates - * in 'store and forward' mode. For this to work, the - * entire frame has to fit into the FIFO, but that means - * that jumbo frames larger than 8192 bytes will be - * truncated. Disabling all bad frame filtering causes - * the RX FIFO to operate in streaming mode, in which - * case the XMAC will start transferring frames out of the - * RX FIFO as soon as the FIFO threshold is reached. - */ - xm_write32(hw, port, XM_MODE, XM_DEF_MODE); - - - /* - * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK) - * - Enable all bits excepting 'Octets Rx OK Low CntOv' - * and 'Octets Rx OK Hi Cnt Ov'. - */ - xm_write32(hw, port, XM_RX_EV_MSK, XMR_DEF_MSK); - - /* - * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK) - * - Enable all bits excepting 'Octets Tx OK Low CntOv' - * and 'Octets Tx OK Hi Cnt Ov'. - */ - xm_write32(hw, port, XM_TX_EV_MSK, XMT_DEF_MSK); - - /* Configure MAC arbiter */ - skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR); - - /* configure timeout values */ - skge_write8(hw, B3_MA_TOINI_RX1, 72); - skge_write8(hw, B3_MA_TOINI_RX2, 72); - skge_write8(hw, B3_MA_TOINI_TX1, 72); - skge_write8(hw, B3_MA_TOINI_TX2, 72); - - skge_write8(hw, B3_MA_RCINI_RX1, 0); - skge_write8(hw, B3_MA_RCINI_RX2, 0); - skge_write8(hw, B3_MA_RCINI_TX1, 0); - skge_write8(hw, B3_MA_RCINI_TX2, 0); - - /* Configure Rx MAC FIFO */ - skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_CLR); - skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_TIM_PAT); - skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_ENA_OP_MD); - - /* Configure Tx MAC FIFO */ - skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_CLR); - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF); - skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_ENA_OP_MD); - - if (jumbo) { - /* Enable frame flushing if jumbo frames used */ - skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_FLUSH); - } else { - /* enable timeout timers if normal frames */ - skge_write16(hw, B3_PA_CTRL, - (port == 0) ? PA_ENA_TO_TX1 : PA_ENA_TO_TX2); - } -} - -static void genesis_stop(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - unsigned retries = 1000; - u16 cmd; - - /* Disable Tx and Rx */ - cmd = xm_read16(hw, port, XM_MMU_CMD); - cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); - xm_write16(hw, port, XM_MMU_CMD, cmd); - - genesis_reset(hw, port); - - /* Clear Tx packet arbiter timeout IRQ */ - skge_write16(hw, B3_PA_CTRL, - port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2); - - /* Reset the MAC */ - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); - do { - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST); - if (!(skge_read16(hw, SK_REG(port, TX_MFF_CTRL1)) & MFF_SET_MAC_RST)) - break; - } while (--retries > 0); - - /* For external PHYs there must be special handling */ - if (hw->phy_type != SK_PHY_XMAC) { - u32 reg = skge_read32(hw, B2_GP_IO); - if (port == 0) { - reg |= GP_DIR_0; - reg &= ~GP_IO_0; - } else { - reg |= GP_DIR_2; - reg &= ~GP_IO_2; - } - skge_write32(hw, B2_GP_IO, reg); - skge_read32(hw, B2_GP_IO); - } - - xm_write16(hw, port, XM_MMU_CMD, - xm_read16(hw, port, XM_MMU_CMD) - & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX)); - - xm_read16(hw, port, XM_MMU_CMD); -} - - -static void genesis_get_stats(struct skge_port *skge, u64 *data) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - int i; - unsigned long timeout = jiffies + HZ; - - xm_write16(hw, port, - XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC); - - /* wait for update to complete */ - while (xm_read16(hw, port, XM_STAT_CMD) - & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) { - if (time_after(jiffies, timeout)) - break; - udelay(10); - } - - /* special case for 64 bit octet counter */ - data[0] = (u64) xm_read32(hw, port, XM_TXO_OK_HI) << 32 - | xm_read32(hw, port, XM_TXO_OK_LO); - data[1] = (u64) xm_read32(hw, port, XM_RXO_OK_HI) << 32 - | xm_read32(hw, port, XM_RXO_OK_LO); - - for (i = 2; i < ARRAY_SIZE(skge_stats); i++) - data[i] = xm_read32(hw, port, skge_stats[i].xmac_offset); -} - -static void genesis_mac_intr(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); - u16 status = xm_read16(hw, port, XM_ISRC); - - netif_printk(skge, intr, KERN_DEBUG, skge->netdev, - "mac interrupt status 0x%x\n", status); - - if (hw->phy_type == SK_PHY_XMAC && (status & XM_IS_INP_ASS)) { - xm_link_down(hw, port); - mod_timer(&skge->link_timer, jiffies + 1); - } - - if (status & XM_IS_TXF_UR) { - xm_write32(hw, port, XM_MODE, XM_MD_FTF); - ++dev->stats.tx_fifo_errors; - } -} - -static void genesis_link_up(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 cmd, msk; - u32 mode; - - cmd = xm_read16(hw, port, XM_MMU_CMD); - - /* - * enabling pause frame reception is required for 1000BT - * because the XMAC is not reset if the link is going down - */ - if (skge->flow_status == FLOW_STAT_NONE || - skge->flow_status == FLOW_STAT_LOC_SEND) - /* Disable Pause Frame Reception */ - cmd |= XM_MMU_IGN_PF; - else - /* Enable Pause Frame Reception */ - cmd &= ~XM_MMU_IGN_PF; - - xm_write16(hw, port, XM_MMU_CMD, cmd); - - mode = xm_read32(hw, port, XM_MODE); - if (skge->flow_status == FLOW_STAT_SYMMETRIC || - skge->flow_status == FLOW_STAT_LOC_SEND) { - /* - * Configure Pause Frame Generation - * Use internal and external Pause Frame Generation. - * Sending pause frames is edge triggered. - * Send a Pause frame with the maximum pause time if - * internal oder external FIFO full condition occurs. - * Send a zero pause time frame to re-start transmission. - */ - /* XM_PAUSE_DA = '010000C28001' (default) */ - /* XM_MAC_PTIME = 0xffff (maximum) */ - /* remember this value is defined in big endian (!) */ - xm_write16(hw, port, XM_MAC_PTIME, 0xffff); - - mode |= XM_PAUSE_MODE; - skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_PAUSE); - } else { - /* - * disable pause frame generation is required for 1000BT - * because the XMAC is not reset if the link is going down - */ - /* Disable Pause Mode in Mode Register */ - mode &= ~XM_PAUSE_MODE; - - skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_DIS_PAUSE); - } - - xm_write32(hw, port, XM_MODE, mode); - - /* Turn on detection of Tx underrun */ - msk = xm_read16(hw, port, XM_IMSK); - msk &= ~XM_IS_TXF_UR; - xm_write16(hw, port, XM_IMSK, msk); - - xm_read16(hw, port, XM_ISRC); - - /* get MMU Command Reg. */ - cmd = xm_read16(hw, port, XM_MMU_CMD); - if (hw->phy_type != SK_PHY_XMAC && skge->duplex == DUPLEX_FULL) - cmd |= XM_MMU_GMII_FD; - - /* - * Workaround BCOM Errata (#10523) for all BCom Phys - * Enable Power Management after link up - */ - if (hw->phy_type == SK_PHY_BCOM) { - xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, - xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL) - & ~PHY_B_AC_DIS_PM); - xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); - } - - /* enable Rx/Tx */ - xm_write16(hw, port, XM_MMU_CMD, - cmd | XM_MMU_ENA_RX | XM_MMU_ENA_TX); - skge_link_up(skge); -} - - -static inline void bcom_phy_intr(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 isrc; - - isrc = xm_phy_read(hw, port, PHY_BCOM_INT_STAT); - netif_printk(skge, intr, KERN_DEBUG, skge->netdev, - "phy interrupt status 0x%x\n", isrc); - - if (isrc & PHY_B_IS_PSE) - pr_err("%s: uncorrectable pair swap error\n", - hw->dev[port]->name); - - /* Workaround BCom Errata: - * enable and disable loopback mode if "NO HCD" occurs. - */ - if (isrc & PHY_B_IS_NO_HDCL) { - u16 ctrl = xm_phy_read(hw, port, PHY_BCOM_CTRL); - xm_phy_write(hw, port, PHY_BCOM_CTRL, - ctrl | PHY_CT_LOOP); - xm_phy_write(hw, port, PHY_BCOM_CTRL, - ctrl & ~PHY_CT_LOOP); - } - - if (isrc & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) - bcom_check_link(hw, port); - -} - -static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) -{ - int i; - - gma_write16(hw, port, GM_SMI_DATA, val); - gma_write16(hw, port, GM_SMI_CTRL, - GM_SMI_CT_PHY_AD(hw->phy_addr) | GM_SMI_CT_REG_AD(reg)); - for (i = 0; i < PHY_RETRIES; i++) { - udelay(1); - - if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY)) - return 0; - } - - pr_warning("%s: phy write timeout\n", hw->dev[port]->name); - return -EIO; -} - -static int __gm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val) -{ - int i; - - gma_write16(hw, port, GM_SMI_CTRL, - GM_SMI_CT_PHY_AD(hw->phy_addr) - | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); - - for (i = 0; i < PHY_RETRIES; i++) { - udelay(1); - if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) - goto ready; - } - - return -ETIMEDOUT; - ready: - *val = gma_read16(hw, port, GM_SMI_DATA); - return 0; -} - -static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg) -{ - u16 v = 0; - if (__gm_phy_read(hw, port, reg, &v)) - pr_warning("%s: phy read timeout\n", hw->dev[port]->name); - return v; -} - -/* Marvell Phy Initialization */ -static void yukon_init(struct skge_hw *hw, int port) -{ - struct skge_port *skge = netdev_priv(hw->dev[port]); - u16 ctrl, ct1000, adv; - - if (skge->autoneg == AUTONEG_ENABLE) { - u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); - - ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | - PHY_M_EC_MAC_S_MSK); - ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ); - - ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1); - - gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl); - } - - ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); - if (skge->autoneg == AUTONEG_DISABLE) - ctrl &= ~PHY_CT_ANE; - - ctrl |= PHY_CT_RESET; - gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); - - ctrl = 0; - ct1000 = 0; - adv = PHY_AN_CSMA; - - if (skge->autoneg == AUTONEG_ENABLE) { - if (hw->copper) { - if (skge->advertising & ADVERTISED_1000baseT_Full) - ct1000 |= PHY_M_1000C_AFD; - if (skge->advertising & ADVERTISED_1000baseT_Half) - ct1000 |= PHY_M_1000C_AHD; - if (skge->advertising & ADVERTISED_100baseT_Full) - adv |= PHY_M_AN_100_FD; - if (skge->advertising & ADVERTISED_100baseT_Half) - adv |= PHY_M_AN_100_HD; - if (skge->advertising & ADVERTISED_10baseT_Full) - adv |= PHY_M_AN_10_FD; - if (skge->advertising & ADVERTISED_10baseT_Half) - adv |= PHY_M_AN_10_HD; - - /* Set Flow-control capabilities */ - adv |= phy_pause_map[skge->flow_control]; - } else { - if (skge->advertising & ADVERTISED_1000baseT_Full) - adv |= PHY_M_AN_1000X_AFD; - if (skge->advertising & ADVERTISED_1000baseT_Half) - adv |= PHY_M_AN_1000X_AHD; - - adv |= fiber_pause_map[skge->flow_control]; - } - - /* Restart Auto-negotiation */ - ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG; - } else { - /* forced speed/duplex settings */ - ct1000 = PHY_M_1000C_MSE; - - if (skge->duplex == DUPLEX_FULL) - ctrl |= PHY_CT_DUP_MD; - - switch (skge->speed) { - case SPEED_1000: - ctrl |= PHY_CT_SP1000; - break; - case SPEED_100: - ctrl |= PHY_CT_SP100; - break; - } - - ctrl |= PHY_CT_RESET; - } - - gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); - - gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); - gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); - - /* Enable phy interrupt on autonegotiation complete (or link up) */ - if (skge->autoneg == AUTONEG_ENABLE) - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_MSK); - else - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); -} - -static void yukon_reset(struct skge_hw *hw, int port) -{ - gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);/* disable PHY IRQs */ - gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */ - gma_write16(hw, port, GM_MC_ADDR_H2, 0); - gma_write16(hw, port, GM_MC_ADDR_H3, 0); - gma_write16(hw, port, GM_MC_ADDR_H4, 0); - - gma_write16(hw, port, GM_RX_CTRL, - gma_read16(hw, port, GM_RX_CTRL) - | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); -} - -/* Apparently, early versions of Yukon-Lite had wrong chip_id? */ -static int is_yukon_lite_a0(struct skge_hw *hw) -{ - u32 reg; - int ret; - - if (hw->chip_id != CHIP_ID_YUKON) - return 0; - - reg = skge_read32(hw, B2_FAR); - skge_write8(hw, B2_FAR + 3, 0xff); - ret = (skge_read8(hw, B2_FAR + 3) != 0); - skge_write32(hw, B2_FAR, reg); - return ret; -} - -static void yukon_mac_init(struct skge_hw *hw, int port) -{ - struct skge_port *skge = netdev_priv(hw->dev[port]); - int i; - u32 reg; - const u8 *addr = hw->dev[port]->dev_addr; - - /* WA code for COMA mode -- set PHY reset */ - if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev >= CHIP_REV_YU_LITE_A3) { - reg = skge_read32(hw, B2_GP_IO); - reg |= GP_DIR_9 | GP_IO_9; - skge_write32(hw, B2_GP_IO, reg); - } - - /* hard reset */ - skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); - skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); - - /* WA code for COMA mode -- clear PHY reset */ - if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev >= CHIP_REV_YU_LITE_A3) { - reg = skge_read32(hw, B2_GP_IO); - reg |= GP_DIR_9; - reg &= ~GP_IO_9; - skge_write32(hw, B2_GP_IO, reg); - } - - /* Set hardware config mode */ - reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | - GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE; - reg |= hw->copper ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB; - - /* Clear GMC reset */ - skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET); - skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_CLR); - skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); - - if (skge->autoneg == AUTONEG_DISABLE) { - reg = GM_GPCR_AU_ALL_DIS; - gma_write16(hw, port, GM_GP_CTRL, - gma_read16(hw, port, GM_GP_CTRL) | reg); - - switch (skge->speed) { - case SPEED_1000: - reg &= ~GM_GPCR_SPEED_100; - reg |= GM_GPCR_SPEED_1000; - break; - case SPEED_100: - reg &= ~GM_GPCR_SPEED_1000; - reg |= GM_GPCR_SPEED_100; - break; - case SPEED_10: - reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100); - break; - } - - if (skge->duplex == DUPLEX_FULL) - reg |= GM_GPCR_DUP_FULL; - } else - reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL; - - switch (skge->flow_control) { - case FLOW_MODE_NONE: - skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); - reg |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; - break; - case FLOW_MODE_LOC_SEND: - /* disable Rx flow-control */ - reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; - break; - case FLOW_MODE_SYMMETRIC: - case FLOW_MODE_SYM_OR_REM: - /* enable Tx & Rx flow-control */ - break; - } - - gma_write16(hw, port, GM_GP_CTRL, reg); - skge_read16(hw, SK_REG(port, GMAC_IRQ_SRC)); - - yukon_init(hw, port); - - /* MIB clear */ - reg = gma_read16(hw, port, GM_PHY_ADDR); - gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR); - - for (i = 0; i < GM_MIB_CNT_SIZE; i++) - gma_read16(hw, port, GM_MIB_CNT_BASE + 8*i); - gma_write16(hw, port, GM_PHY_ADDR, reg); - - /* transmit control */ - gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF)); - - /* receive control reg: unicast + multicast + no FCS */ - gma_write16(hw, port, GM_RX_CTRL, - GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA); - - /* transmit flow control */ - gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff); - - /* transmit parameter */ - gma_write16(hw, port, GM_TX_PARAM, - TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) | - TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) | - TX_IPG_JAM_DATA(TX_IPG_JAM_DEF)); - - /* configure the Serial Mode Register */ - reg = DATA_BLIND_VAL(DATA_BLIND_DEF) - | GM_SMOD_VLAN_ENA - | IPG_DATA_VAL(IPG_DATA_DEF); - - if (hw->dev[port]->mtu > ETH_DATA_LEN) - reg |= GM_SMOD_JUMBO_ENA; - - gma_write16(hw, port, GM_SERIAL_MODE, reg); - - /* physical address: used for pause frames */ - gma_set_addr(hw, port, GM_SRC_ADDR_1L, addr); - /* virtual address for data */ - gma_set_addr(hw, port, GM_SRC_ADDR_2L, addr); - - /* enable interrupt mask for counter overflows */ - gma_write16(hw, port, GM_TX_IRQ_MSK, 0); - gma_write16(hw, port, GM_RX_IRQ_MSK, 0); - gma_write16(hw, port, GM_TR_IRQ_MSK, 0); - - /* Initialize Mac Fifo */ - - /* Configure Rx MAC FIFO */ - skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK); - reg = GMF_OPER_ON | GMF_RX_F_FL_ON; - - /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */ - if (is_yukon_lite_a0(hw)) - reg &= ~GMF_RX_F_FL_ON; - - skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); - skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg); - /* - * because Pause Packet Truncation in GMAC is not working - * we have to increase the Flush Threshold to 64 bytes - * in order to flush pause packets in Rx FIFO on Yukon-1 - */ - skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1); - - /* Configure Tx MAC FIFO */ - skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); - skge_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); -} - -/* Go into power down mode */ -static void yukon_suspend(struct skge_hw *hw, int port) -{ - u16 ctrl; - - ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); - ctrl |= PHY_M_PC_POL_R_DIS; - gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); - - ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); - ctrl |= PHY_CT_RESET; - gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); - - /* switch IEEE compatible power down mode on */ - ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); - ctrl |= PHY_CT_PDOWN; - gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); -} - -static void yukon_stop(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - - skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); - yukon_reset(hw, port); - - gma_write16(hw, port, GM_GP_CTRL, - gma_read16(hw, port, GM_GP_CTRL) - & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA)); - gma_read16(hw, port, GM_GP_CTRL); - - yukon_suspend(hw, port); - - /* set GPHY Control reset */ - skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); - skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); -} - -static void yukon_get_stats(struct skge_port *skge, u64 *data) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - int i; - - data[0] = (u64) gma_read32(hw, port, GM_TXO_OK_HI) << 32 - | gma_read32(hw, port, GM_TXO_OK_LO); - data[1] = (u64) gma_read32(hw, port, GM_RXO_OK_HI) << 32 - | gma_read32(hw, port, GM_RXO_OK_LO); - - for (i = 2; i < ARRAY_SIZE(skge_stats); i++) - data[i] = gma_read32(hw, port, - skge_stats[i].gma_offset); -} - -static void yukon_mac_intr(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); - u8 status = skge_read8(hw, SK_REG(port, GMAC_IRQ_SRC)); - - netif_printk(skge, intr, KERN_DEBUG, skge->netdev, - "mac interrupt status 0x%x\n", status); - - if (status & GM_IS_RX_FF_OR) { - ++dev->stats.rx_fifo_errors; - skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); - } - - if (status & GM_IS_TX_FF_UR) { - ++dev->stats.tx_fifo_errors; - skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU); - } - -} - -static u16 yukon_speed(const struct skge_hw *hw, u16 aux) -{ - switch (aux & PHY_M_PS_SPEED_MSK) { - case PHY_M_PS_SPEED_1000: - return SPEED_1000; - case PHY_M_PS_SPEED_100: - return SPEED_100; - default: - return SPEED_10; - } -} - -static void yukon_link_up(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 reg; - - /* Enable Transmit FIFO Underrun */ - skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK); - - reg = gma_read16(hw, port, GM_GP_CTRL); - if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE) - reg |= GM_GPCR_DUP_FULL; - - /* enable Rx/Tx */ - reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; - gma_write16(hw, port, GM_GP_CTRL, reg); - - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); - skge_link_up(skge); -} - -static void yukon_link_down(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 ctrl; - - ctrl = gma_read16(hw, port, GM_GP_CTRL); - ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); - gma_write16(hw, port, GM_GP_CTRL, ctrl); - - if (skge->flow_status == FLOW_STAT_REM_SEND) { - ctrl = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV); - ctrl |= PHY_M_AN_ASP; - /* restore Asymmetric Pause bit */ - gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, ctrl); - } - - skge_link_down(skge); - - yukon_init(hw, port); -} - -static void yukon_phy_intr(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - const char *reason = NULL; - u16 istatus, phystat; - - istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT); - phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT); - - netif_printk(skge, intr, KERN_DEBUG, skge->netdev, - "phy interrupt status 0x%x 0x%x\n", istatus, phystat); - - if (istatus & PHY_M_IS_AN_COMPL) { - if (gm_phy_read(hw, port, PHY_MARV_AUNE_LP) - & PHY_M_AN_RF) { - reason = "remote fault"; - goto failed; - } - - if (gm_phy_read(hw, port, PHY_MARV_1000T_STAT) & PHY_B_1000S_MSF) { - reason = "master/slave fault"; - goto failed; - } - - if (!(phystat & PHY_M_PS_SPDUP_RES)) { - reason = "speed/duplex"; - goto failed; - } - - skge->duplex = (phystat & PHY_M_PS_FULL_DUP) - ? DUPLEX_FULL : DUPLEX_HALF; - skge->speed = yukon_speed(hw, phystat); - - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - switch (phystat & PHY_M_PS_PAUSE_MSK) { - case PHY_M_PS_PAUSE_MSK: - skge->flow_status = FLOW_STAT_SYMMETRIC; - break; - case PHY_M_PS_RX_P_EN: - skge->flow_status = FLOW_STAT_REM_SEND; - break; - case PHY_M_PS_TX_P_EN: - skge->flow_status = FLOW_STAT_LOC_SEND; - break; - default: - skge->flow_status = FLOW_STAT_NONE; - } - - if (skge->flow_status == FLOW_STAT_NONE || - (skge->speed < SPEED_1000 && skge->duplex == DUPLEX_HALF)) - skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); - else - skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); - yukon_link_up(skge); - return; - } - - if (istatus & PHY_M_IS_LSP_CHANGE) - skge->speed = yukon_speed(hw, phystat); - - if (istatus & PHY_M_IS_DUP_CHANGE) - skge->duplex = (phystat & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF; - if (istatus & PHY_M_IS_LST_CHANGE) { - if (phystat & PHY_M_PS_LINK_UP) - yukon_link_up(skge); - else - yukon_link_down(skge); - } - return; - failed: - pr_err("%s: autonegotiation failed (%s)\n", skge->netdev->name, reason); - - /* XXX restart autonegotiation? */ -} - -static void skge_phy_reset(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - struct net_device *dev = hw->dev[port]; - - netif_stop_queue(skge->netdev); - netif_carrier_off(skge->netdev); - - spin_lock_bh(&hw->phy_lock); - if (is_genesis(hw)) { - genesis_reset(hw, port); - genesis_mac_init(hw, port); - } else { - yukon_reset(hw, port); - yukon_init(hw, port); - } - spin_unlock_bh(&hw->phy_lock); - - skge_set_multicast(dev); -} - -/* Basic MII support */ -static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct mii_ioctl_data *data = if_mii(ifr); - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int err = -EOPNOTSUPP; - - if (!netif_running(dev)) - return -ENODEV; /* Phy still in reset */ - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = hw->phy_addr; - - /* fallthru */ - case SIOCGMIIREG: { - u16 val = 0; - spin_lock_bh(&hw->phy_lock); - - if (is_genesis(hw)) - err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); - else - err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); - spin_unlock_bh(&hw->phy_lock); - data->val_out = val; - break; - } - - case SIOCSMIIREG: - spin_lock_bh(&hw->phy_lock); - if (is_genesis(hw)) - err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f, - data->val_in); - else - err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f, - data->val_in); - spin_unlock_bh(&hw->phy_lock); - break; - } - return err; -} - -static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len) -{ - u32 end; - - start /= 8; - len /= 8; - end = start + len - 1; - - skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); - skge_write32(hw, RB_ADDR(q, RB_START), start); - skge_write32(hw, RB_ADDR(q, RB_WP), start); - skge_write32(hw, RB_ADDR(q, RB_RP), start); - skge_write32(hw, RB_ADDR(q, RB_END), end); - - if (q == Q_R1 || q == Q_R2) { - /* Set thresholds on receive queue's */ - skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), - start + (2*len)/3); - skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), - start + (len/3)); - } else { - /* Enable store & forward on Tx queue's because - * Tx FIFO is only 4K on Genesis and 1K on Yukon - */ - skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD); - } - - skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD); -} - -/* Setup Bus Memory Interface */ -static void skge_qset(struct skge_port *skge, u16 q, - const struct skge_element *e) -{ - struct skge_hw *hw = skge->hw; - u32 watermark = 0x600; - u64 base = skge->dma + (e->desc - skge->mem); - - /* optimization to reduce window on 32bit/33mhz */ - if ((skge_read16(hw, B0_CTST) & (CS_BUS_CLOCK | CS_BUS_SLOT_SZ)) == 0) - watermark /= 2; - - skge_write32(hw, Q_ADDR(q, Q_CSR), CSR_CLR_RESET); - skge_write32(hw, Q_ADDR(q, Q_F), watermark); - skge_write32(hw, Q_ADDR(q, Q_DA_H), (u32)(base >> 32)); - skge_write32(hw, Q_ADDR(q, Q_DA_L), (u32)base); -} - -static int skge_up(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - u32 chunk, ram_addr; - size_t rx_size, tx_size; - int err; - - if (!is_valid_ether_addr(dev->dev_addr)) - return -EINVAL; - - netif_info(skge, ifup, skge->netdev, "enabling interface\n"); - - if (dev->mtu > RX_BUF_SIZE) - skge->rx_buf_size = dev->mtu + ETH_HLEN; - else - skge->rx_buf_size = RX_BUF_SIZE; - - - rx_size = skge->rx_ring.count * sizeof(struct skge_rx_desc); - tx_size = skge->tx_ring.count * sizeof(struct skge_tx_desc); - skge->mem_size = tx_size + rx_size; - skge->mem = pci_alloc_consistent(hw->pdev, skge->mem_size, &skge->dma); - if (!skge->mem) - return -ENOMEM; - - BUG_ON(skge->dma & 7); - - if ((u64)skge->dma >> 32 != ((u64) skge->dma + skge->mem_size) >> 32) { - dev_err(&hw->pdev->dev, "pci_alloc_consistent region crosses 4G boundary\n"); - err = -EINVAL; - goto free_pci_mem; - } - - memset(skge->mem, 0, skge->mem_size); - - err = skge_ring_alloc(&skge->rx_ring, skge->mem, skge->dma); - if (err) - goto free_pci_mem; - - err = skge_rx_fill(dev); - if (err) - goto free_rx_ring; - - err = skge_ring_alloc(&skge->tx_ring, skge->mem + rx_size, - skge->dma + rx_size); - if (err) - goto free_rx_ring; - - if (hw->ports == 1) { - err = request_irq(hw->pdev->irq, skge_intr, IRQF_SHARED, - dev->name, hw); - if (err) { - netdev_err(dev, "Unable to allocate interrupt %d error: %d\n", - hw->pdev->irq, err); - goto free_tx_ring; - } - } - - /* Initialize MAC */ - netif_carrier_off(dev); - spin_lock_bh(&hw->phy_lock); - if (is_genesis(hw)) - genesis_mac_init(hw, port); - else - yukon_mac_init(hw, port); - spin_unlock_bh(&hw->phy_lock); - - /* Configure RAMbuffers - equally between ports and tx/rx */ - chunk = (hw->ram_size - hw->ram_offset) / (hw->ports * 2); - ram_addr = hw->ram_offset + 2 * chunk * port; - - skge_ramset(hw, rxqaddr[port], ram_addr, chunk); - skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean); - - BUG_ON(skge->tx_ring.to_use != skge->tx_ring.to_clean); - skge_ramset(hw, txqaddr[port], ram_addr+chunk, chunk); - skge_qset(skge, txqaddr[port], skge->tx_ring.to_use); - - /* Start receiver BMU */ - wmb(); - skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); - skge_led(skge, LED_MODE_ON); - - spin_lock_irq(&hw->hw_lock); - hw->intr_mask |= portmask[port]; - skge_write32(hw, B0_IMSK, hw->intr_mask); - skge_read32(hw, B0_IMSK); - spin_unlock_irq(&hw->hw_lock); - - napi_enable(&skge->napi); - - skge_set_multicast(dev); - - return 0; - - free_tx_ring: - kfree(skge->tx_ring.start); - free_rx_ring: - skge_rx_clean(skge); - kfree(skge->rx_ring.start); - free_pci_mem: - pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma); - skge->mem = NULL; - - return err; -} - -/* stop receiver */ -static void skge_rx_stop(struct skge_hw *hw, int port) -{ - skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_STOP); - skge_write32(hw, RB_ADDR(port ? Q_R2 : Q_R1, RB_CTRL), - RB_RST_SET|RB_DIS_OP_MD); - skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET); -} - -static int skge_down(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - - if (skge->mem == NULL) - return 0; - - netif_info(skge, ifdown, skge->netdev, "disabling interface\n"); - - netif_tx_disable(dev); - - if (is_genesis(hw) && hw->phy_type == SK_PHY_XMAC) - del_timer_sync(&skge->link_timer); - - napi_disable(&skge->napi); - netif_carrier_off(dev); - - spin_lock_irq(&hw->hw_lock); - hw->intr_mask &= ~portmask[port]; - skge_write32(hw, B0_IMSK, (hw->ports == 1) ? 0 : hw->intr_mask); - skge_read32(hw, B0_IMSK); - spin_unlock_irq(&hw->hw_lock); - - if (hw->ports == 1) - free_irq(hw->pdev->irq, hw); - - skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); - if (is_genesis(hw)) - genesis_stop(skge); - else - yukon_stop(skge); - - /* Stop transmitter */ - skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); - skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), - RB_RST_SET|RB_DIS_OP_MD); - - - /* Disable Force Sync bit and Enable Alloc bit */ - skge_write8(hw, SK_REG(port, TXA_CTRL), - TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); - - /* Stop Interval Timer and Limit Counter of Tx Arbiter */ - skge_write32(hw, SK_REG(port, TXA_ITI_INI), 0L); - skge_write32(hw, SK_REG(port, TXA_LIM_INI), 0L); - - /* Reset PCI FIFO */ - skge_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_SET_RESET); - skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET); - - /* Reset the RAM Buffer async Tx queue */ - skge_write8(hw, RB_ADDR(port == 0 ? Q_XA1 : Q_XA2, RB_CTRL), RB_RST_SET); - - skge_rx_stop(hw, port); - - if (is_genesis(hw)) { - skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET); - skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET); - } else { - skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); - skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); - } - - skge_led(skge, LED_MODE_OFF); - - netif_tx_lock_bh(dev); - skge_tx_clean(dev); - netif_tx_unlock_bh(dev); - - skge_rx_clean(skge); - - kfree(skge->rx_ring.start); - kfree(skge->tx_ring.start); - pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma); - skge->mem = NULL; - return 0; -} - -static inline int skge_avail(const struct skge_ring *ring) -{ - smp_mb(); - return ((ring->to_clean > ring->to_use) ? 0 : ring->count) - + (ring->to_clean - ring->to_use) - 1; -} - -static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, - struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - struct skge_element *e; - struct skge_tx_desc *td; - int i; - u32 control, len; - u64 map; - - if (skb_padto(skb, ETH_ZLEN)) - return NETDEV_TX_OK; - - if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1)) - return NETDEV_TX_BUSY; - - e = skge->tx_ring.to_use; - td = e->desc; - BUG_ON(td->control & BMU_OWN); - e->skb = skb; - len = skb_headlen(skb); - map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); - dma_unmap_addr_set(e, mapaddr, map); - dma_unmap_len_set(e, maplen, len); - - td->dma_lo = map; - td->dma_hi = map >> 32; - - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const int offset = skb_checksum_start_offset(skb); - - /* This seems backwards, but it is what the sk98lin - * does. Looks like hardware is wrong? - */ - if (ipip_hdr(skb)->protocol == IPPROTO_UDP && - hw->chip_rev == 0 && hw->chip_id == CHIP_ID_YUKON) - control = BMU_TCP_CHECK; - else - control = BMU_UDP_CHECK; - - td->csum_offs = 0; - td->csum_start = offset; - td->csum_write = offset + skb->csum_offset; - } else - control = BMU_CHECK; - - if (!skb_shinfo(skb)->nr_frags) /* single buffer i.e. no fragments */ - control |= BMU_EOF | BMU_IRQ_EOF; - else { - struct skge_tx_desc *tf = td; - - control |= BMU_STFWD; - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - map = skb_frag_dma_map(&hw->pdev->dev, frag, 0, - skb_frag_size(frag), DMA_TO_DEVICE); - - e = e->next; - e->skb = skb; - tf = e->desc; - BUG_ON(tf->control & BMU_OWN); - - tf->dma_lo = map; - tf->dma_hi = (u64) map >> 32; - dma_unmap_addr_set(e, mapaddr, map); - dma_unmap_len_set(e, maplen, skb_frag_size(frag)); - - tf->control = BMU_OWN | BMU_SW | control | skb_frag_size(frag); - } - tf->control |= BMU_EOF | BMU_IRQ_EOF; - } - /* Make sure all the descriptors written */ - wmb(); - td->control = BMU_OWN | BMU_SW | BMU_STF | control | len; - wmb(); - - netdev_sent_queue(dev, skb->len); - - skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START); - - netif_printk(skge, tx_queued, KERN_DEBUG, skge->netdev, - "tx queued, slot %td, len %d\n", - e - skge->tx_ring.start, skb->len); - - skge->tx_ring.to_use = e->next; - smp_wmb(); - - if (skge_avail(&skge->tx_ring) <= TX_LOW_WATER) { - netdev_dbg(dev, "transmit queue full\n"); - netif_stop_queue(dev); - } - - return NETDEV_TX_OK; -} - - -/* Free resources associated with this reing element */ -static inline void skge_tx_unmap(struct pci_dev *pdev, struct skge_element *e, - u32 control) -{ - /* skb header vs. fragment */ - if (control & BMU_STF) - pci_unmap_single(pdev, dma_unmap_addr(e, mapaddr), - dma_unmap_len(e, maplen), - PCI_DMA_TODEVICE); - else - pci_unmap_page(pdev, dma_unmap_addr(e, mapaddr), - dma_unmap_len(e, maplen), - PCI_DMA_TODEVICE); -} - -/* Free all buffers in transmit ring */ -static void skge_tx_clean(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_element *e; - - for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { - struct skge_tx_desc *td = e->desc; - - skge_tx_unmap(skge->hw->pdev, e, td->control); - - if (td->control & BMU_EOF) - dev_kfree_skb(e->skb); - td->control = 0; - } - - netdev_reset_queue(dev); - skge->tx_ring.to_clean = e; -} - -static void skge_tx_timeout(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - - netif_printk(skge, timer, KERN_DEBUG, skge->netdev, "tx timeout\n"); - - skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_STOP); - skge_tx_clean(dev); - netif_wake_queue(dev); -} - -static int skge_change_mtu(struct net_device *dev, int new_mtu) -{ - int err; - - if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) - return -EINVAL; - - if (!netif_running(dev)) { - dev->mtu = new_mtu; - return 0; - } - - skge_down(dev); - - dev->mtu = new_mtu; - - err = skge_up(dev); - if (err) - dev_close(dev); - - return err; -} - -static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 }; - -static void genesis_add_filter(u8 filter[8], const u8 *addr) -{ - u32 crc, bit; - - crc = ether_crc_le(ETH_ALEN, addr); - bit = ~crc & 0x3f; - filter[bit/8] |= 1 << (bit%8); -} - -static void genesis_set_multicast(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - struct netdev_hw_addr *ha; - u32 mode; - u8 filter[8]; - - mode = xm_read32(hw, port, XM_MODE); - mode |= XM_MD_ENA_HASH; - if (dev->flags & IFF_PROMISC) - mode |= XM_MD_ENA_PROM; - else - mode &= ~XM_MD_ENA_PROM; - - if (dev->flags & IFF_ALLMULTI) - memset(filter, 0xff, sizeof(filter)); - else { - memset(filter, 0, sizeof(filter)); - - if (skge->flow_status == FLOW_STAT_REM_SEND || - skge->flow_status == FLOW_STAT_SYMMETRIC) - genesis_add_filter(filter, pause_mc_addr); - - netdev_for_each_mc_addr(ha, dev) - genesis_add_filter(filter, ha->addr); - } - - xm_write32(hw, port, XM_MODE, mode); - xm_outhash(hw, port, XM_HSM, filter); -} - -static void yukon_add_filter(u8 filter[8], const u8 *addr) -{ - u32 bit = ether_crc(ETH_ALEN, addr) & 0x3f; - filter[bit/8] |= 1 << (bit%8); -} - -static void yukon_set_multicast(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - struct netdev_hw_addr *ha; - int rx_pause = (skge->flow_status == FLOW_STAT_REM_SEND || - skge->flow_status == FLOW_STAT_SYMMETRIC); - u16 reg; - u8 filter[8]; - - memset(filter, 0, sizeof(filter)); - - reg = gma_read16(hw, port, GM_RX_CTRL); - reg |= GM_RXCR_UCF_ENA; - - if (dev->flags & IFF_PROMISC) /* promiscuous */ - reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); - else if (dev->flags & IFF_ALLMULTI) /* all multicast */ - memset(filter, 0xff, sizeof(filter)); - else if (netdev_mc_empty(dev) && !rx_pause)/* no multicast */ - reg &= ~GM_RXCR_MCF_ENA; - else { - reg |= GM_RXCR_MCF_ENA; - - if (rx_pause) - yukon_add_filter(filter, pause_mc_addr); - - netdev_for_each_mc_addr(ha, dev) - yukon_add_filter(filter, ha->addr); - } - - - gma_write16(hw, port, GM_MC_ADDR_H1, - (u16)filter[0] | ((u16)filter[1] << 8)); - gma_write16(hw, port, GM_MC_ADDR_H2, - (u16)filter[2] | ((u16)filter[3] << 8)); - gma_write16(hw, port, GM_MC_ADDR_H3, - (u16)filter[4] | ((u16)filter[5] << 8)); - gma_write16(hw, port, GM_MC_ADDR_H4, - (u16)filter[6] | ((u16)filter[7] << 8)); - - gma_write16(hw, port, GM_RX_CTRL, reg); -} - -static inline u16 phy_length(const struct skge_hw *hw, u32 status) -{ - if (is_genesis(hw)) - return status >> XMR_FS_LEN_SHIFT; - else - return status >> GMR_FS_LEN_SHIFT; -} - -static inline int bad_phy_status(const struct skge_hw *hw, u32 status) -{ - if (is_genesis(hw)) - return (status & (XMR_FS_ERR | XMR_FS_2L_VLAN)) != 0; - else - return (status & GMR_FS_ANY_ERR) || - (status & GMR_FS_RX_OK) == 0; -} - -static void skge_set_multicast(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - - if (is_genesis(skge->hw)) - genesis_set_multicast(dev); - else - yukon_set_multicast(dev); - -} - - -/* Get receive buffer from descriptor. - * Handles copy of small buffers and reallocation failures - */ -static struct sk_buff *skge_rx_get(struct net_device *dev, - struct skge_element *e, - u32 control, u32 status, u16 csum) -{ - struct skge_port *skge = netdev_priv(dev); - struct sk_buff *skb; - u16 len = control & BMU_BBC; - - netif_printk(skge, rx_status, KERN_DEBUG, skge->netdev, - "rx slot %td status 0x%x len %d\n", - e - skge->rx_ring.start, status, len); - - if (len > skge->rx_buf_size) - goto error; - - if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)) - goto error; - - if (bad_phy_status(skge->hw, status)) - goto error; - - if (phy_length(skge->hw, status) != len) - goto error; - - if (len < RX_COPY_THRESHOLD) { - skb = netdev_alloc_skb_ip_align(dev, len); - if (!skb) - goto resubmit; - - pci_dma_sync_single_for_cpu(skge->hw->pdev, - dma_unmap_addr(e, mapaddr), - len, PCI_DMA_FROMDEVICE); - skb_copy_from_linear_data(e->skb, skb->data, len); - pci_dma_sync_single_for_device(skge->hw->pdev, - dma_unmap_addr(e, mapaddr), - len, PCI_DMA_FROMDEVICE); - skge_rx_reuse(e, skge->rx_buf_size); - } else { - struct sk_buff *nskb; - - nskb = netdev_alloc_skb_ip_align(dev, skge->rx_buf_size); - if (!nskb) - goto resubmit; - - pci_unmap_single(skge->hw->pdev, - dma_unmap_addr(e, mapaddr), - dma_unmap_len(e, maplen), - PCI_DMA_FROMDEVICE); - skb = e->skb; - prefetch(skb->data); - skge_rx_setup(skge, e, nskb, skge->rx_buf_size); - } - - skb_put(skb, len); - - if (dev->features & NETIF_F_RXCSUM) { - skb->csum = csum; - skb->ip_summed = CHECKSUM_COMPLETE; - } - - skb->protocol = eth_type_trans(skb, dev); - - return skb; -error: - - netif_printk(skge, rx_err, KERN_DEBUG, skge->netdev, - "rx err, slot %td control 0x%x status 0x%x\n", - e - skge->rx_ring.start, control, status); - - if (is_genesis(skge->hw)) { - if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR)) - dev->stats.rx_length_errors++; - if (status & XMR_FS_FRA_ERR) - dev->stats.rx_frame_errors++; - if (status & XMR_FS_FCS_ERR) - dev->stats.rx_crc_errors++; - } else { - if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE)) - dev->stats.rx_length_errors++; - if (status & GMR_FS_FRAGMENT) - dev->stats.rx_frame_errors++; - if (status & GMR_FS_CRC_ERR) - dev->stats.rx_crc_errors++; - } - -resubmit: - skge_rx_reuse(e, skge->rx_buf_size); - return NULL; -} - -/* Free all buffers in Tx ring which are no longer owned by device */ -static void skge_tx_done(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_ring *ring = &skge->tx_ring; - struct skge_element *e; - unsigned int bytes_compl = 0, pkts_compl = 0; - - skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); - - for (e = ring->to_clean; e != ring->to_use; e = e->next) { - u32 control = ((const struct skge_tx_desc *) e->desc)->control; - - if (control & BMU_OWN) - break; - - skge_tx_unmap(skge->hw->pdev, e, control); - - if (control & BMU_EOF) { - netif_printk(skge, tx_done, KERN_DEBUG, skge->netdev, - "tx done slot %td\n", - e - skge->tx_ring.start); - - pkts_compl++; - bytes_compl += e->skb->len; - - dev_kfree_skb(e->skb); - } - } - netdev_completed_queue(dev, pkts_compl, bytes_compl); - skge->tx_ring.to_clean = e; - - /* Can run lockless until we need to synchronize to restart queue. */ - smp_mb(); - - if (unlikely(netif_queue_stopped(dev) && - skge_avail(&skge->tx_ring) > TX_LOW_WATER)) { - netif_tx_lock(dev); - if (unlikely(netif_queue_stopped(dev) && - skge_avail(&skge->tx_ring) > TX_LOW_WATER)) { - netif_wake_queue(dev); - - } - netif_tx_unlock(dev); - } -} - -static int skge_poll(struct napi_struct *napi, int to_do) -{ - struct skge_port *skge = container_of(napi, struct skge_port, napi); - struct net_device *dev = skge->netdev; - struct skge_hw *hw = skge->hw; - struct skge_ring *ring = &skge->rx_ring; - struct skge_element *e; - int work_done = 0; - - skge_tx_done(dev); - - skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); - - for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) { - struct skge_rx_desc *rd = e->desc; - struct sk_buff *skb; - u32 control; - - rmb(); - control = rd->control; - if (control & BMU_OWN) - break; - - skb = skge_rx_get(dev, e, control, rd->status, rd->csum2); - if (likely(skb)) { - napi_gro_receive(napi, skb); - ++work_done; - } - } - ring->to_clean = e; - - /* restart receiver */ - wmb(); - skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_START); - - if (work_done < to_do) { - unsigned long flags; - - napi_gro_flush(napi, false); - spin_lock_irqsave(&hw->hw_lock, flags); - __napi_complete(napi); - hw->intr_mask |= napimask[skge->port]; - skge_write32(hw, B0_IMSK, hw->intr_mask); - skge_read32(hw, B0_IMSK); - spin_unlock_irqrestore(&hw->hw_lock, flags); - } - - return work_done; -} - -/* Parity errors seem to happen when Genesis is connected to a switch - * with no other ports present. Heartbeat error?? - */ -static void skge_mac_parity(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - - ++dev->stats.tx_heartbeat_errors; - - if (is_genesis(hw)) - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), - MFF_CLR_PERR); - else - /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */ - skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), - (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0) - ? GMF_CLI_TX_FC : GMF_CLI_TX_PE); -} - -static void skge_mac_intr(struct skge_hw *hw, int port) -{ - if (is_genesis(hw)) - genesis_mac_intr(hw, port); - else - yukon_mac_intr(hw, port); -} - -/* Handle device specific framing and timeout interrupts */ -static void skge_error_irq(struct skge_hw *hw) -{ - struct pci_dev *pdev = hw->pdev; - u32 hwstatus = skge_read32(hw, B0_HWE_ISRC); - - if (is_genesis(hw)) { - /* clear xmac errors */ - if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1)) - skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT); - if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2)) - skge_write16(hw, RX_MFF_CTRL2, MFF_CLR_INSTAT); - } else { - /* Timestamp (unused) overflow */ - if (hwstatus & IS_IRQ_TIST_OV) - skge_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ); - } - - if (hwstatus & IS_RAM_RD_PAR) { - dev_err(&pdev->dev, "Ram read data parity error\n"); - skge_write16(hw, B3_RI_CTRL, RI_CLR_RD_PERR); - } - - if (hwstatus & IS_RAM_WR_PAR) { - dev_err(&pdev->dev, "Ram write data parity error\n"); - skge_write16(hw, B3_RI_CTRL, RI_CLR_WR_PERR); - } - - if (hwstatus & IS_M1_PAR_ERR) - skge_mac_parity(hw, 0); - - if (hwstatus & IS_M2_PAR_ERR) - skge_mac_parity(hw, 1); - - if (hwstatus & IS_R1_PAR_ERR) { - dev_err(&pdev->dev, "%s: receive queue parity error\n", - hw->dev[0]->name); - skge_write32(hw, B0_R1_CSR, CSR_IRQ_CL_P); - } - - if (hwstatus & IS_R2_PAR_ERR) { - dev_err(&pdev->dev, "%s: receive queue parity error\n", - hw->dev[1]->name); - skge_write32(hw, B0_R2_CSR, CSR_IRQ_CL_P); - } - - if (hwstatus & (IS_IRQ_MST_ERR|IS_IRQ_STAT)) { - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - dev_err(&pdev->dev, "PCI error cmd=%#x status=%#x\n", - pci_cmd, pci_status); - - /* Write the error bits back to clear them. */ - pci_status &= PCI_STATUS_ERROR_BITS; - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); - pci_write_config_word(pdev, PCI_COMMAND, - pci_cmd | PCI_COMMAND_SERR | PCI_COMMAND_PARITY); - pci_write_config_word(pdev, PCI_STATUS, pci_status); - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - /* if error still set then just ignore it */ - hwstatus = skge_read32(hw, B0_HWE_ISRC); - if (hwstatus & IS_IRQ_STAT) { - dev_warn(&hw->pdev->dev, "unable to clear error (so ignoring them)\n"); - hw->intr_mask &= ~IS_HW_ERR; - } - } -} - -/* - * Interrupt from PHY are handled in tasklet (softirq) - * because accessing phy registers requires spin wait which might - * cause excess interrupt latency. - */ -static void skge_extirq(unsigned long arg) -{ - struct skge_hw *hw = (struct skge_hw *) arg; - int port; - - for (port = 0; port < hw->ports; port++) { - struct net_device *dev = hw->dev[port]; - - if (netif_running(dev)) { - struct skge_port *skge = netdev_priv(dev); - - spin_lock(&hw->phy_lock); - if (!is_genesis(hw)) - yukon_phy_intr(skge); - else if (hw->phy_type == SK_PHY_BCOM) - bcom_phy_intr(skge); - spin_unlock(&hw->phy_lock); - } - } - - spin_lock_irq(&hw->hw_lock); - hw->intr_mask |= IS_EXT_REG; - skge_write32(hw, B0_IMSK, hw->intr_mask); - skge_read32(hw, B0_IMSK); - spin_unlock_irq(&hw->hw_lock); -} - -static irqreturn_t skge_intr(int irq, void *dev_id) -{ - struct skge_hw *hw = dev_id; - u32 status; - int handled = 0; - - spin_lock(&hw->hw_lock); - /* Reading this register masks IRQ */ - status = skge_read32(hw, B0_SP_ISRC); - if (status == 0 || status == ~0) - goto out; - - handled = 1; - status &= hw->intr_mask; - if (status & IS_EXT_REG) { - hw->intr_mask &= ~IS_EXT_REG; - tasklet_schedule(&hw->phy_task); - } - - if (status & (IS_XA1_F|IS_R1_F)) { - struct skge_port *skge = netdev_priv(hw->dev[0]); - hw->intr_mask &= ~(IS_XA1_F|IS_R1_F); - napi_schedule(&skge->napi); - } - - if (status & IS_PA_TO_TX1) - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1); - - if (status & IS_PA_TO_RX1) { - ++hw->dev[0]->stats.rx_over_errors; - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1); - } - - - if (status & IS_MAC1) - skge_mac_intr(hw, 0); - - if (hw->dev[1]) { - struct skge_port *skge = netdev_priv(hw->dev[1]); - - if (status & (IS_XA2_F|IS_R2_F)) { - hw->intr_mask &= ~(IS_XA2_F|IS_R2_F); - napi_schedule(&skge->napi); - } - - if (status & IS_PA_TO_RX2) { - ++hw->dev[1]->stats.rx_over_errors; - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2); - } - - if (status & IS_PA_TO_TX2) - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2); - - if (status & IS_MAC2) - skge_mac_intr(hw, 1); - } - - if (status & IS_HW_ERR) - skge_error_irq(hw); - - skge_write32(hw, B0_IMSK, hw->intr_mask); - skge_read32(hw, B0_IMSK); -out: - spin_unlock(&hw->hw_lock); - - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void skge_netpoll(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - - disable_irq(dev->irq); - skge_intr(dev->irq, skge->hw); - enable_irq(dev->irq); -} -#endif - -static int skge_set_mac_address(struct net_device *dev, void *p) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - unsigned port = skge->port; - const struct sockaddr *addr = p; - u16 ctrl; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - - if (!netif_running(dev)) { - memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN); - memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN); - } else { - /* disable Rx */ - spin_lock_bh(&hw->phy_lock); - ctrl = gma_read16(hw, port, GM_GP_CTRL); - gma_write16(hw, port, GM_GP_CTRL, ctrl & ~GM_GPCR_RX_ENA); - - memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN); - memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN); - - if (is_genesis(hw)) - xm_outaddr(hw, port, XM_SA, dev->dev_addr); - else { - gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); - gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); - } - - gma_write16(hw, port, GM_GP_CTRL, ctrl); - spin_unlock_bh(&hw->phy_lock); - } - - return 0; -} - -static const struct { - u8 id; - const char *name; -} skge_chips[] = { - { CHIP_ID_GENESIS, "Genesis" }, - { CHIP_ID_YUKON, "Yukon" }, - { CHIP_ID_YUKON_LITE, "Yukon-Lite"}, - { CHIP_ID_YUKON_LP, "Yukon-LP"}, -}; - -static const char *skge_board_name(const struct skge_hw *hw) -{ - int i; - static char buf[16]; - - for (i = 0; i < ARRAY_SIZE(skge_chips); i++) - if (skge_chips[i].id == hw->chip_id) - return skge_chips[i].name; - - snprintf(buf, sizeof buf, "chipid 0x%x", hw->chip_id); - return buf; -} - - -/* - * Setup the board data structure, but don't bring up - * the port(s) - */ -static int skge_reset(struct skge_hw *hw) -{ - u32 reg; - u16 ctst, pci_status; - u8 t8, mac_cfg, pmd_type; - int i; - - ctst = skge_read16(hw, B0_CTST); - - /* do a SW reset */ - skge_write8(hw, B0_CTST, CS_RST_SET); - skge_write8(hw, B0_CTST, CS_RST_CLR); - - /* clear PCI errors, if any */ - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); - skge_write8(hw, B2_TST_CTRL2, 0); - - pci_read_config_word(hw->pdev, PCI_STATUS, &pci_status); - pci_write_config_word(hw->pdev, PCI_STATUS, - pci_status | PCI_STATUS_ERROR_BITS); - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - skge_write8(hw, B0_CTST, CS_MRST_CLR); - - /* restore CLK_RUN bits (for Yukon-Lite) */ - skge_write16(hw, B0_CTST, - ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA)); - - hw->chip_id = skge_read8(hw, B2_CHIP_ID); - hw->phy_type = skge_read8(hw, B2_E_1) & 0xf; - pmd_type = skge_read8(hw, B2_PMD_TYP); - hw->copper = (pmd_type == 'T' || pmd_type == '1'); - - switch (hw->chip_id) { - case CHIP_ID_GENESIS: -#ifdef CONFIG_SKGE_GENESIS - switch (hw->phy_type) { - case SK_PHY_XMAC: - hw->phy_addr = PHY_ADDR_XMAC; - break; - case SK_PHY_BCOM: - hw->phy_addr = PHY_ADDR_BCOM; - break; - default: - dev_err(&hw->pdev->dev, "unsupported phy type 0x%x\n", - hw->phy_type); - return -EOPNOTSUPP; - } - break; -#else - dev_err(&hw->pdev->dev, "Genesis chip detected but not configured\n"); - return -EOPNOTSUPP; -#endif - - case CHIP_ID_YUKON: - case CHIP_ID_YUKON_LITE: - case CHIP_ID_YUKON_LP: - if (hw->phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S') - hw->copper = 1; - - hw->phy_addr = PHY_ADDR_MARV; - break; - - default: - dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", - hw->chip_id); - return -EOPNOTSUPP; - } - - mac_cfg = skge_read8(hw, B2_MAC_CFG); - hw->ports = (mac_cfg & CFG_SNG_MAC) ? 1 : 2; - hw->chip_rev = (mac_cfg & CFG_CHIP_R_MSK) >> 4; - - /* read the adapters RAM size */ - t8 = skge_read8(hw, B2_E_0); - if (is_genesis(hw)) { - if (t8 == 3) { - /* special case: 4 x 64k x 36, offset = 0x80000 */ - hw->ram_size = 0x100000; - hw->ram_offset = 0x80000; - } else - hw->ram_size = t8 * 512; - } else if (t8 == 0) - hw->ram_size = 0x20000; - else - hw->ram_size = t8 * 4096; - - hw->intr_mask = IS_HW_ERR; - - /* Use PHY IRQ for all but fiber based Genesis board */ - if (!(is_genesis(hw) && hw->phy_type == SK_PHY_XMAC)) - hw->intr_mask |= IS_EXT_REG; - - if (is_genesis(hw)) - genesis_init(hw); - else { - /* switch power to VCC (WA for VAUX problem) */ - skge_write8(hw, B0_POWER_CTRL, - PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); - - /* avoid boards with stuck Hardware error bits */ - if ((skge_read32(hw, B0_ISRC) & IS_HW_ERR) && - (skge_read32(hw, B0_HWE_ISRC) & IS_IRQ_SENSOR)) { - dev_warn(&hw->pdev->dev, "stuck hardware sensor bit\n"); - hw->intr_mask &= ~IS_HW_ERR; - } - - /* Clear PHY COMA */ - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); - pci_read_config_dword(hw->pdev, PCI_DEV_REG1, ®); - reg &= ~PCI_PHY_COMA; - pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg); - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - - for (i = 0; i < hw->ports; i++) { - skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); - skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR); - } - } - - /* turn off hardware timer (unused) */ - skge_write8(hw, B2_TI_CTRL, TIM_STOP); - skge_write8(hw, B2_TI_CTRL, TIM_CLR_IRQ); - skge_write8(hw, B0_LED, LED_STAT_ON); - - /* enable the Tx Arbiters */ - for (i = 0; i < hw->ports; i++) - skge_write8(hw, SK_REG(i, TXA_CTRL), TXA_ENA_ARB); - - /* Initialize ram interface */ - skge_write16(hw, B3_RI_CTRL, RI_RST_CLR); - - skge_write8(hw, B3_RI_WTO_R1, SK_RI_TO_53); - skge_write8(hw, B3_RI_WTO_XA1, SK_RI_TO_53); - skge_write8(hw, B3_RI_WTO_XS1, SK_RI_TO_53); - skge_write8(hw, B3_RI_RTO_R1, SK_RI_TO_53); - skge_write8(hw, B3_RI_RTO_XA1, SK_RI_TO_53); - skge_write8(hw, B3_RI_RTO_XS1, SK_RI_TO_53); - skge_write8(hw, B3_RI_WTO_R2, SK_RI_TO_53); - skge_write8(hw, B3_RI_WTO_XA2, SK_RI_TO_53); - skge_write8(hw, B3_RI_WTO_XS2, SK_RI_TO_53); - skge_write8(hw, B3_RI_RTO_R2, SK_RI_TO_53); - skge_write8(hw, B3_RI_RTO_XA2, SK_RI_TO_53); - skge_write8(hw, B3_RI_RTO_XS2, SK_RI_TO_53); - - skge_write32(hw, B0_HWE_IMSK, IS_ERR_MSK); - - /* Set interrupt moderation for Transmit only - * Receive interrupts avoided by NAPI - */ - skge_write32(hw, B2_IRQM_MSK, IS_XA1_F|IS_XA2_F); - skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100)); - skge_write32(hw, B2_IRQM_CTRL, TIM_START); - - /* Leave irq disabled until first port is brought up. */ - skge_write32(hw, B0_IMSK, 0); - - for (i = 0; i < hw->ports; i++) { - if (is_genesis(hw)) - genesis_reset(hw, i); - else - yukon_reset(hw, i); - } - - return 0; -} - - -#ifdef CONFIG_SKGE_DEBUG - -static struct dentry *skge_debug; - -static int skge_debug_show(struct seq_file *seq, void *v) -{ - struct net_device *dev = seq->private; - const struct skge_port *skge = netdev_priv(dev); - const struct skge_hw *hw = skge->hw; - const struct skge_element *e; - - if (!netif_running(dev)) - return -ENETDOWN; - - seq_printf(seq, "IRQ src=%x mask=%x\n", skge_read32(hw, B0_ISRC), - skge_read32(hw, B0_IMSK)); - - seq_printf(seq, "Tx Ring: (%d)\n", skge_avail(&skge->tx_ring)); - for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { - const struct skge_tx_desc *t = e->desc; - seq_printf(seq, "%#x dma=%#x%08x %#x csum=%#x/%x/%x\n", - t->control, t->dma_hi, t->dma_lo, t->status, - t->csum_offs, t->csum_write, t->csum_start); - } - - seq_printf(seq, "\nRx Ring:\n"); - for (e = skge->rx_ring.to_clean; ; e = e->next) { - const struct skge_rx_desc *r = e->desc; - - if (r->control & BMU_OWN) - break; - - seq_printf(seq, "%#x dma=%#x%08x %#x %#x csum=%#x/%x\n", - r->control, r->dma_hi, r->dma_lo, r->status, - r->timestamp, r->csum1, r->csum1_start); - } - - return 0; -} - -static int skge_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, skge_debug_show, inode->i_private); -} - -static const struct file_operations skge_debug_fops = { - .owner = THIS_MODULE, - .open = skge_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* - * Use network device events to create/remove/rename - * debugfs file entries - */ -static int skge_device_event(struct notifier_block *unused, - unsigned long event, void *ptr) -{ - struct net_device *dev = ptr; - struct skge_port *skge; - struct dentry *d; - - if (dev->netdev_ops->ndo_open != &skge_up || !skge_debug) - goto done; - - skge = netdev_priv(dev); - switch (event) { - case NETDEV_CHANGENAME: - if (skge->debugfs) { - d = debugfs_rename(skge_debug, skge->debugfs, - skge_debug, dev->name); - if (d) - skge->debugfs = d; - else { - netdev_info(dev, "rename failed\n"); - debugfs_remove(skge->debugfs); - } - } - break; - - case NETDEV_GOING_DOWN: - if (skge->debugfs) { - debugfs_remove(skge->debugfs); - skge->debugfs = NULL; - } - break; - - case NETDEV_UP: - d = debugfs_create_file(dev->name, S_IRUGO, - skge_debug, dev, - &skge_debug_fops); - if (!d || IS_ERR(d)) - netdev_info(dev, "debugfs create failed\n"); - else - skge->debugfs = d; - break; - } - -done: - return NOTIFY_DONE; -} - -static struct notifier_block skge_notifier = { - .notifier_call = skge_device_event, -}; - - -static __init void skge_debug_init(void) -{ - struct dentry *ent; - - ent = debugfs_create_dir("skge", NULL); - if (!ent || IS_ERR(ent)) { - pr_info("debugfs create directory failed\n"); - return; - } - - skge_debug = ent; - register_netdevice_notifier(&skge_notifier); -} - -static __exit void skge_debug_cleanup(void) -{ - if (skge_debug) { - unregister_netdevice_notifier(&skge_notifier); - debugfs_remove(skge_debug); - skge_debug = NULL; - } -} - -#else -#define skge_debug_init() -#define skge_debug_cleanup() -#endif - -static const struct net_device_ops skge_netdev_ops = { - .ndo_open = skge_up, - .ndo_stop = skge_down, - .ndo_start_xmit = skge_xmit_frame, - .ndo_do_ioctl = skge_ioctl, - .ndo_get_stats = skge_get_stats, - .ndo_tx_timeout = skge_tx_timeout, - .ndo_change_mtu = skge_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_rx_mode = skge_set_multicast, - .ndo_set_mac_address = skge_set_mac_address, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = skge_netpoll, -#endif -}; - - -/* Initialize network device */ -static struct net_device *skge_devinit(struct skge_hw *hw, int port, - int highmem) -{ - struct skge_port *skge; - struct net_device *dev = alloc_etherdev(sizeof(*skge)); - - if (!dev) - return NULL; - - SET_NETDEV_DEV(dev, &hw->pdev->dev); - dev->netdev_ops = &skge_netdev_ops; - dev->ethtool_ops = &skge_ethtool_ops; - dev->watchdog_timeo = TX_WATCHDOG; - dev->irq = hw->pdev->irq; - - if (highmem) - dev->features |= NETIF_F_HIGHDMA; - - skge = netdev_priv(dev); - netif_napi_add(dev, &skge->napi, skge_poll, NAPI_WEIGHT); - skge->netdev = dev; - skge->hw = hw; - skge->msg_enable = netif_msg_init(debug, default_msg); - - skge->tx_ring.count = DEFAULT_TX_RING_SIZE; - skge->rx_ring.count = DEFAULT_RX_RING_SIZE; - - /* Auto speed and flow control */ - skge->autoneg = AUTONEG_ENABLE; - skge->flow_control = FLOW_MODE_SYM_OR_REM; - skge->duplex = -1; - skge->speed = -1; - skge->advertising = skge_supported_modes(hw); - - if (device_can_wakeup(&hw->pdev->dev)) { - skge->wol = wol_supported(hw) & WAKE_MAGIC; - device_set_wakeup_enable(&hw->pdev->dev, skge->wol); - } - - hw->dev[port] = dev; - - skge->port = port; - - /* Only used for Genesis XMAC */ - if (is_genesis(hw)) - setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge); - else { - dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | - NETIF_F_RXCSUM; - dev->features |= dev->hw_features; - } - - /* read the mac address */ - memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN); - - return dev; -} - -static void skge_show_addr(struct net_device *dev) -{ - const struct skge_port *skge = netdev_priv(dev); - - netif_info(skge, probe, skge->netdev, "addr %pM\n", dev->dev_addr); -} - -static int only_32bit_dma; - -static int skge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct net_device *dev, *dev1; - struct skge_hw *hw; - int err, using_dac = 0; - - err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "cannot enable PCI device\n"); - goto err_out; - } - - err = pci_request_regions(pdev, DRV_NAME); - if (err) { - dev_err(&pdev->dev, "cannot obtain PCI resources\n"); - goto err_out_disable_pdev; - } - - pci_set_master(pdev); - - if (!only_32bit_dma && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { - using_dac = 1; - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); - } else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { - using_dac = 0; - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - } - - if (err) { - dev_err(&pdev->dev, "no usable DMA configuration\n"); - goto err_out_free_regions; - } - -#ifdef __BIG_ENDIAN - /* byte swap descriptors in hardware */ - { - u32 reg; - - pci_read_config_dword(pdev, PCI_DEV_REG2, ®); - reg |= PCI_REV_DESC; - pci_write_config_dword(pdev, PCI_DEV_REG2, reg); - } -#endif - - err = -ENOMEM; - /* space for skge@pci:0000:04:00.0 */ - hw = kzalloc(sizeof(*hw) + strlen(DRV_NAME "@pci:") - + strlen(pci_name(pdev)) + 1, GFP_KERNEL); - if (!hw) - goto err_out_free_regions; - - sprintf(hw->irq_name, DRV_NAME "@pci:%s", pci_name(pdev)); - - hw->pdev = pdev; - spin_lock_init(&hw->hw_lock); - spin_lock_init(&hw->phy_lock); - tasklet_init(&hw->phy_task, skge_extirq, (unsigned long) hw); - - hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); - if (!hw->regs) { - dev_err(&pdev->dev, "cannot map device registers\n"); - goto err_out_free_hw; - } - - err = skge_reset(hw); - if (err) - goto err_out_iounmap; - - pr_info("%s addr 0x%llx irq %d chip %s rev %d\n", - DRV_VERSION, - (unsigned long long)pci_resource_start(pdev, 0), pdev->irq, - skge_board_name(hw), hw->chip_rev); - - dev = skge_devinit(hw, 0, using_dac); - if (!dev) { - err = -ENOMEM; - goto err_out_led_off; - } - - /* Some motherboards are broken and has zero in ROM. */ - if (!is_valid_ether_addr(dev->dev_addr)) - dev_warn(&pdev->dev, "bad (zero?) ethernet address in rom\n"); - - err = register_netdev(dev); - if (err) { - dev_err(&pdev->dev, "cannot register net device\n"); - goto err_out_free_netdev; - } - - skge_show_addr(dev); - - if (hw->ports > 1) { - dev1 = skge_devinit(hw, 1, using_dac); - if (!dev1) { - err = -ENOMEM; - goto err_out_unregister; - } - - err = register_netdev(dev1); - if (err) { - dev_err(&pdev->dev, "cannot register second net device\n"); - goto err_out_free_dev1; - } - - err = request_irq(pdev->irq, skge_intr, IRQF_SHARED, - hw->irq_name, hw); - if (err) { - dev_err(&pdev->dev, "cannot assign irq %d\n", - pdev->irq); - goto err_out_unregister_dev1; - } - - skge_show_addr(dev1); - } - pci_set_drvdata(pdev, hw); - - return 0; - -err_out_unregister_dev1: - unregister_netdev(dev1); -err_out_free_dev1: - free_netdev(dev1); -err_out_unregister: - unregister_netdev(dev); -err_out_free_netdev: - free_netdev(dev); -err_out_led_off: - skge_write16(hw, B0_LED, LED_STAT_OFF); -err_out_iounmap: - iounmap(hw->regs); -err_out_free_hw: - kfree(hw); -err_out_free_regions: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); - pci_set_drvdata(pdev, NULL); -err_out: - return err; -} - -static void skge_remove(struct pci_dev *pdev) -{ - struct skge_hw *hw = pci_get_drvdata(pdev); - struct net_device *dev0, *dev1; - - if (!hw) - return; - - dev1 = hw->dev[1]; - if (dev1) - unregister_netdev(dev1); - dev0 = hw->dev[0]; - unregister_netdev(dev0); - - tasklet_kill(&hw->phy_task); - - spin_lock_irq(&hw->hw_lock); - hw->intr_mask = 0; - - if (hw->ports > 1) { - skge_write32(hw, B0_IMSK, 0); - skge_read32(hw, B0_IMSK); - free_irq(pdev->irq, hw); - } - spin_unlock_irq(&hw->hw_lock); - - skge_write16(hw, B0_LED, LED_STAT_OFF); - skge_write8(hw, B0_CTST, CS_RST_SET); - - if (hw->ports > 1) - free_irq(pdev->irq, hw); - pci_release_regions(pdev); - pci_disable_device(pdev); - if (dev1) - free_netdev(dev1); - free_netdev(dev0); - - iounmap(hw->regs); - kfree(hw); - pci_set_drvdata(pdev, NULL); -} - -#ifdef CONFIG_PM_SLEEP -static int skge_suspend(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct skge_hw *hw = pci_get_drvdata(pdev); - int i; - - if (!hw) - return 0; - - for (i = 0; i < hw->ports; i++) { - struct net_device *dev = hw->dev[i]; - struct skge_port *skge = netdev_priv(dev); - - if (netif_running(dev)) - skge_down(dev); - - if (skge->wol) - skge_wol_init(skge); - } - - skge_write32(hw, B0_IMSK, 0); - - return 0; -} - -static int skge_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct skge_hw *hw = pci_get_drvdata(pdev); - int i, err; - - if (!hw) - return 0; - - err = skge_reset(hw); - if (err) - goto out; - - for (i = 0; i < hw->ports; i++) { - struct net_device *dev = hw->dev[i]; - - if (netif_running(dev)) { - err = skge_up(dev); - - if (err) { - netdev_err(dev, "could not up: %d\n", err); - dev_close(dev); - goto out; - } - } - } -out: - return err; -} - -static SIMPLE_DEV_PM_OPS(skge_pm_ops, skge_suspend, skge_resume); -#define SKGE_PM_OPS (&skge_pm_ops) - -#else - -#define SKGE_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ - -static void skge_shutdown(struct pci_dev *pdev) -{ - struct skge_hw *hw = pci_get_drvdata(pdev); - int i; - - if (!hw) - return; - - for (i = 0; i < hw->ports; i++) { - struct net_device *dev = hw->dev[i]; - struct skge_port *skge = netdev_priv(dev); - - if (skge->wol) - skge_wol_init(skge); - } - - pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev)); - pci_set_power_state(pdev, PCI_D3hot); -} - -static struct pci_driver skge_driver = { - .name = DRV_NAME, - .id_table = skge_id_table, - .probe = skge_probe, - .remove = skge_remove, - .shutdown = skge_shutdown, - .driver.pm = SKGE_PM_OPS, -}; - -static struct dmi_system_id skge_32bit_dma_boards[] = { - { - .ident = "Gigabyte nForce boards", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co"), - DMI_MATCH(DMI_BOARD_NAME, "nForce"), - }, - }, - { - .ident = "ASUS P5NSLI", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), - DMI_MATCH(DMI_BOARD_NAME, "P5NSLI") - }, - }, - {} -}; - -static int __init skge_init_module(void) -{ - if (dmi_check_system(skge_32bit_dma_boards)) - only_32bit_dma = 1; - skge_debug_init(); - return pci_register_driver(&skge_driver); -} - -static void __exit skge_cleanup_module(void) -{ - pci_unregister_driver(&skge_driver); - skge_debug_cleanup(); -} - -module_init(skge_init_module); -module_exit(skge_cleanup_module); diff --git a/addons/skge/src/3.10.108/skge.h b/addons/skge/src/3.10.108/skge.h deleted file mode 100644 index a2eb3411..00000000 --- a/addons/skge/src/3.10.108/skge.h +++ /dev/null @@ -1,2584 +0,0 @@ -/* - * Definitions for the new Marvell Yukon / SysKonnect driver. - */ -#ifndef _SKGE_H -#define _SKGE_H -#include - -/* PCI config registers */ -#define PCI_DEV_REG1 0x40 -#define PCI_PHY_COMA 0x8000000 -#define PCI_VIO 0x2000000 - -#define PCI_DEV_REG2 0x44 -#define PCI_VPD_ROM_SZ 7L<<14 /* VPD ROM size 0=256, 1=512, ... */ -#define PCI_REV_DESC 1<<2 /* Reverse Descriptor bytes */ - -#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \ - PCI_STATUS_SIG_SYSTEM_ERROR | \ - PCI_STATUS_REC_MASTER_ABORT | \ - PCI_STATUS_REC_TARGET_ABORT | \ - PCI_STATUS_PARITY) - -enum csr_regs { - B0_RAP = 0x0000, - B0_CTST = 0x0004, - B0_LED = 0x0006, - B0_POWER_CTRL = 0x0007, - B0_ISRC = 0x0008, - B0_IMSK = 0x000c, - B0_HWE_ISRC = 0x0010, - B0_HWE_IMSK = 0x0014, - B0_SP_ISRC = 0x0018, - B0_XM1_IMSK = 0x0020, - B0_XM1_ISRC = 0x0028, - B0_XM1_PHY_ADDR = 0x0030, - B0_XM1_PHY_DATA = 0x0034, - B0_XM2_IMSK = 0x0040, - B0_XM2_ISRC = 0x0048, - B0_XM2_PHY_ADDR = 0x0050, - B0_XM2_PHY_DATA = 0x0054, - B0_R1_CSR = 0x0060, - B0_R2_CSR = 0x0064, - B0_XS1_CSR = 0x0068, - B0_XA1_CSR = 0x006c, - B0_XS2_CSR = 0x0070, - B0_XA2_CSR = 0x0074, - - B2_MAC_1 = 0x0100, - B2_MAC_2 = 0x0108, - B2_MAC_3 = 0x0110, - B2_CONN_TYP = 0x0118, - B2_PMD_TYP = 0x0119, - B2_MAC_CFG = 0x011a, - B2_CHIP_ID = 0x011b, - B2_E_0 = 0x011c, - B2_E_1 = 0x011d, - B2_E_2 = 0x011e, - B2_E_3 = 0x011f, - B2_FAR = 0x0120, - B2_FDP = 0x0124, - B2_LD_CTRL = 0x0128, - B2_LD_TEST = 0x0129, - B2_TI_INI = 0x0130, - B2_TI_VAL = 0x0134, - B2_TI_CTRL = 0x0138, - B2_TI_TEST = 0x0139, - B2_IRQM_INI = 0x0140, - B2_IRQM_VAL = 0x0144, - B2_IRQM_CTRL = 0x0148, - B2_IRQM_TEST = 0x0149, - B2_IRQM_MSK = 0x014c, - B2_IRQM_HWE_MSK = 0x0150, - B2_TST_CTRL1 = 0x0158, - B2_TST_CTRL2 = 0x0159, - B2_GP_IO = 0x015c, - B2_I2C_CTRL = 0x0160, - B2_I2C_DATA = 0x0164, - B2_I2C_IRQ = 0x0168, - B2_I2C_SW = 0x016c, - B2_BSC_INI = 0x0170, - B2_BSC_VAL = 0x0174, - B2_BSC_CTRL = 0x0178, - B2_BSC_STAT = 0x0179, - B2_BSC_TST = 0x017a, - - B3_RAM_ADDR = 0x0180, - B3_RAM_DATA_LO = 0x0184, - B3_RAM_DATA_HI = 0x0188, - B3_RI_WTO_R1 = 0x0190, - B3_RI_WTO_XA1 = 0x0191, - B3_RI_WTO_XS1 = 0x0192, - B3_RI_RTO_R1 = 0x0193, - B3_RI_RTO_XA1 = 0x0194, - B3_RI_RTO_XS1 = 0x0195, - B3_RI_WTO_R2 = 0x0196, - B3_RI_WTO_XA2 = 0x0197, - B3_RI_WTO_XS2 = 0x0198, - B3_RI_RTO_R2 = 0x0199, - B3_RI_RTO_XA2 = 0x019a, - B3_RI_RTO_XS2 = 0x019b, - B3_RI_TO_VAL = 0x019c, - B3_RI_CTRL = 0x01a0, - B3_RI_TEST = 0x01a2, - B3_MA_TOINI_RX1 = 0x01b0, - B3_MA_TOINI_RX2 = 0x01b1, - B3_MA_TOINI_TX1 = 0x01b2, - B3_MA_TOINI_TX2 = 0x01b3, - B3_MA_TOVAL_RX1 = 0x01b4, - B3_MA_TOVAL_RX2 = 0x01b5, - B3_MA_TOVAL_TX1 = 0x01b6, - B3_MA_TOVAL_TX2 = 0x01b7, - B3_MA_TO_CTRL = 0x01b8, - B3_MA_TO_TEST = 0x01ba, - B3_MA_RCINI_RX1 = 0x01c0, - B3_MA_RCINI_RX2 = 0x01c1, - B3_MA_RCINI_TX1 = 0x01c2, - B3_MA_RCINI_TX2 = 0x01c3, - B3_MA_RCVAL_RX1 = 0x01c4, - B3_MA_RCVAL_RX2 = 0x01c5, - B3_MA_RCVAL_TX1 = 0x01c6, - B3_MA_RCVAL_TX2 = 0x01c7, - B3_MA_RC_CTRL = 0x01c8, - B3_MA_RC_TEST = 0x01ca, - B3_PA_TOINI_RX1 = 0x01d0, - B3_PA_TOINI_RX2 = 0x01d4, - B3_PA_TOINI_TX1 = 0x01d8, - B3_PA_TOINI_TX2 = 0x01dc, - B3_PA_TOVAL_RX1 = 0x01e0, - B3_PA_TOVAL_RX2 = 0x01e4, - B3_PA_TOVAL_TX1 = 0x01e8, - B3_PA_TOVAL_TX2 = 0x01ec, - B3_PA_CTRL = 0x01f0, - B3_PA_TEST = 0x01f2, -}; - -/* B0_CTST 16 bit Control/Status register */ -enum { - CS_CLK_RUN_HOT = 1<<13,/* CLK_RUN hot m. (YUKON-Lite only) */ - CS_CLK_RUN_RST = 1<<12,/* CLK_RUN reset (YUKON-Lite only) */ - CS_CLK_RUN_ENA = 1<<11,/* CLK_RUN enable (YUKON-Lite only) */ - CS_VAUX_AVAIL = 1<<10,/* VAUX available (YUKON only) */ - CS_BUS_CLOCK = 1<<9, /* Bus Clock 0/1 = 33/66 MHz */ - CS_BUS_SLOT_SZ = 1<<8, /* Slot Size 0/1 = 32/64 bit slot */ - CS_ST_SW_IRQ = 1<<7, /* Set IRQ SW Request */ - CS_CL_SW_IRQ = 1<<6, /* Clear IRQ SW Request */ - CS_STOP_DONE = 1<<5, /* Stop Master is finished */ - CS_STOP_MAST = 1<<4, /* Command Bit to stop the master */ - CS_MRST_CLR = 1<<3, /* Clear Master reset */ - CS_MRST_SET = 1<<2, /* Set Master reset */ - CS_RST_CLR = 1<<1, /* Clear Software reset */ - CS_RST_SET = 1, /* Set Software reset */ - -/* B0_LED 8 Bit LED register */ -/* Bit 7.. 2: reserved */ - LED_STAT_ON = 1<<1, /* Status LED on */ - LED_STAT_OFF = 1, /* Status LED off */ - -/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */ - PC_VAUX_ENA = 1<<7, /* Switch VAUX Enable */ - PC_VAUX_DIS = 1<<6, /* Switch VAUX Disable */ - PC_VCC_ENA = 1<<5, /* Switch VCC Enable */ - PC_VCC_DIS = 1<<4, /* Switch VCC Disable */ - PC_VAUX_ON = 1<<3, /* Switch VAUX On */ - PC_VAUX_OFF = 1<<2, /* Switch VAUX Off */ - PC_VCC_ON = 1<<1, /* Switch VCC On */ - PC_VCC_OFF = 1<<0, /* Switch VCC Off */ -}; - -/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */ -enum { - IS_ALL_MSK = 0xbffffffful, /* All Interrupt bits */ - IS_HW_ERR = 1<<31, /* Interrupt HW Error */ - /* Bit 30: reserved */ - IS_PA_TO_RX1 = 1<<29, /* Packet Arb Timeout Rx1 */ - IS_PA_TO_RX2 = 1<<28, /* Packet Arb Timeout Rx2 */ - IS_PA_TO_TX1 = 1<<27, /* Packet Arb Timeout Tx1 */ - IS_PA_TO_TX2 = 1<<26, /* Packet Arb Timeout Tx2 */ - IS_I2C_READY = 1<<25, /* IRQ on end of I2C Tx */ - IS_IRQ_SW = 1<<24, /* SW forced IRQ */ - IS_EXT_REG = 1<<23, /* IRQ from LM80 or PHY (GENESIS only) */ - /* IRQ from PHY (YUKON only) */ - IS_TIMINT = 1<<22, /* IRQ from Timer */ - IS_MAC1 = 1<<21, /* IRQ from MAC 1 */ - IS_LNK_SYNC_M1 = 1<<20, /* Link Sync Cnt wrap MAC 1 */ - IS_MAC2 = 1<<19, /* IRQ from MAC 2 */ - IS_LNK_SYNC_M2 = 1<<18, /* Link Sync Cnt wrap MAC 2 */ -/* Receive Queue 1 */ - IS_R1_B = 1<<17, /* Q_R1 End of Buffer */ - IS_R1_F = 1<<16, /* Q_R1 End of Frame */ - IS_R1_C = 1<<15, /* Q_R1 Encoding Error */ -/* Receive Queue 2 */ - IS_R2_B = 1<<14, /* Q_R2 End of Buffer */ - IS_R2_F = 1<<13, /* Q_R2 End of Frame */ - IS_R2_C = 1<<12, /* Q_R2 Encoding Error */ -/* Synchronous Transmit Queue 1 */ - IS_XS1_B = 1<<11, /* Q_XS1 End of Buffer */ - IS_XS1_F = 1<<10, /* Q_XS1 End of Frame */ - IS_XS1_C = 1<<9, /* Q_XS1 Encoding Error */ -/* Asynchronous Transmit Queue 1 */ - IS_XA1_B = 1<<8, /* Q_XA1 End of Buffer */ - IS_XA1_F = 1<<7, /* Q_XA1 End of Frame */ - IS_XA1_C = 1<<6, /* Q_XA1 Encoding Error */ -/* Synchronous Transmit Queue 2 */ - IS_XS2_B = 1<<5, /* Q_XS2 End of Buffer */ - IS_XS2_F = 1<<4, /* Q_XS2 End of Frame */ - IS_XS2_C = 1<<3, /* Q_XS2 Encoding Error */ -/* Asynchronous Transmit Queue 2 */ - IS_XA2_B = 1<<2, /* Q_XA2 End of Buffer */ - IS_XA2_F = 1<<1, /* Q_XA2 End of Frame */ - IS_XA2_C = 1<<0, /* Q_XA2 Encoding Error */ - - IS_TO_PORT1 = IS_PA_TO_RX1 | IS_PA_TO_TX1, - IS_TO_PORT2 = IS_PA_TO_RX2 | IS_PA_TO_TX2, - - IS_PORT_1 = IS_XA1_F| IS_R1_F | IS_TO_PORT1 | IS_MAC1, - IS_PORT_2 = IS_XA2_F| IS_R2_F | IS_TO_PORT2 | IS_MAC2, -}; - - -/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ -enum { - IS_IRQ_TIST_OV = 1<<13, /* Time Stamp Timer Overflow (YUKON only) */ - IS_IRQ_SENSOR = 1<<12, /* IRQ from Sensor (YUKON only) */ - IS_IRQ_MST_ERR = 1<<11, /* IRQ master error detected */ - IS_IRQ_STAT = 1<<10, /* IRQ status exception */ - IS_NO_STAT_M1 = 1<<9, /* No Rx Status from MAC 1 */ - IS_NO_STAT_M2 = 1<<8, /* No Rx Status from MAC 2 */ - IS_NO_TIST_M1 = 1<<7, /* No Time Stamp from MAC 1 */ - IS_NO_TIST_M2 = 1<<6, /* No Time Stamp from MAC 2 */ - IS_RAM_RD_PAR = 1<<5, /* RAM Read Parity Error */ - IS_RAM_WR_PAR = 1<<4, /* RAM Write Parity Error */ - IS_M1_PAR_ERR = 1<<3, /* MAC 1 Parity Error */ - IS_M2_PAR_ERR = 1<<2, /* MAC 2 Parity Error */ - IS_R1_PAR_ERR = 1<<1, /* Queue R1 Parity Error */ - IS_R2_PAR_ERR = 1<<0, /* Queue R2 Parity Error */ - - IS_ERR_MSK = IS_IRQ_MST_ERR | IS_IRQ_STAT - | IS_RAM_RD_PAR | IS_RAM_WR_PAR - | IS_M1_PAR_ERR | IS_M2_PAR_ERR - | IS_R1_PAR_ERR | IS_R2_PAR_ERR, -}; - -/* B2_TST_CTRL1 8 bit Test Control Register 1 */ -enum { - TST_FRC_DPERR_MR = 1<<7, /* force DATAPERR on MST RD */ - TST_FRC_DPERR_MW = 1<<6, /* force DATAPERR on MST WR */ - TST_FRC_DPERR_TR = 1<<5, /* force DATAPERR on TRG RD */ - TST_FRC_DPERR_TW = 1<<4, /* force DATAPERR on TRG WR */ - TST_FRC_APERR_M = 1<<3, /* force ADDRPERR on MST */ - TST_FRC_APERR_T = 1<<2, /* force ADDRPERR on TRG */ - TST_CFG_WRITE_ON = 1<<1, /* Enable Config Reg WR */ - TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */ -}; - -/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ -enum { - CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */ - /* Bit 3.. 2: reserved */ - CFG_DIS_M2_CLK = 1<<1, /* Disable Clock for 2nd MAC */ - CFG_SNG_MAC = 1<<0, /* MAC Config: 0=2 MACs / 1=1 MAC*/ -}; - -/* B2_CHIP_ID 8 bit Chip Identification Number */ -enum { - CHIP_ID_GENESIS = 0x0a, /* Chip ID for GENESIS */ - CHIP_ID_YUKON = 0xb0, /* Chip ID for YUKON */ - CHIP_ID_YUKON_LITE = 0xb1, /* Chip ID for YUKON-Lite (Rev. A1-A3) */ - CHIP_ID_YUKON_LP = 0xb2, /* Chip ID for YUKON-LP */ - CHIP_ID_YUKON_XL = 0xb3, /* Chip ID for YUKON-2 XL */ - CHIP_ID_YUKON_EC = 0xb6, /* Chip ID for YUKON-2 EC */ - CHIP_ID_YUKON_FE = 0xb7, /* Chip ID for YUKON-2 FE */ - - CHIP_REV_YU_LITE_A1 = 3, /* Chip Rev. for YUKON-Lite A1,A2 */ - CHIP_REV_YU_LITE_A3 = 7, /* Chip Rev. for YUKON-Lite A3 */ -}; - -/* B2_TI_CTRL 8 bit Timer control */ -/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */ -enum { - TIM_START = 1<<2, /* Start Timer */ - TIM_STOP = 1<<1, /* Stop Timer */ - TIM_CLR_IRQ = 1<<0, /* Clear Timer IRQ (!IRQM) */ -}; - -/* B2_TI_TEST 8 Bit Timer Test */ -/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */ -/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */ -enum { - TIM_T_ON = 1<<2, /* Test mode on */ - TIM_T_OFF = 1<<1, /* Test mode off */ - TIM_T_STEP = 1<<0, /* Test step */ -}; - -/* B2_GP_IO 32 bit General Purpose I/O Register */ -enum { - GP_DIR_9 = 1<<25, /* IO_9 direct, 0=In/1=Out */ - GP_DIR_8 = 1<<24, /* IO_8 direct, 0=In/1=Out */ - GP_DIR_7 = 1<<23, /* IO_7 direct, 0=In/1=Out */ - GP_DIR_6 = 1<<22, /* IO_6 direct, 0=In/1=Out */ - GP_DIR_5 = 1<<21, /* IO_5 direct, 0=In/1=Out */ - GP_DIR_4 = 1<<20, /* IO_4 direct, 0=In/1=Out */ - GP_DIR_3 = 1<<19, /* IO_3 direct, 0=In/1=Out */ - GP_DIR_2 = 1<<18, /* IO_2 direct, 0=In/1=Out */ - GP_DIR_1 = 1<<17, /* IO_1 direct, 0=In/1=Out */ - GP_DIR_0 = 1<<16, /* IO_0 direct, 0=In/1=Out */ - - GP_IO_9 = 1<<9, /* IO_9 pin */ - GP_IO_8 = 1<<8, /* IO_8 pin */ - GP_IO_7 = 1<<7, /* IO_7 pin */ - GP_IO_6 = 1<<6, /* IO_6 pin */ - GP_IO_5 = 1<<5, /* IO_5 pin */ - GP_IO_4 = 1<<4, /* IO_4 pin */ - GP_IO_3 = 1<<3, /* IO_3 pin */ - GP_IO_2 = 1<<2, /* IO_2 pin */ - GP_IO_1 = 1<<1, /* IO_1 pin */ - GP_IO_0 = 1<<0, /* IO_0 pin */ -}; - -/* Descriptor Bit Definition */ -/* TxCtrl Transmit Buffer Control Field */ -/* RxCtrl Receive Buffer Control Field */ -enum { - BMU_OWN = 1<<31, /* OWN bit: 0=host/1=BMU */ - BMU_STF = 1<<30, /* Start of Frame */ - BMU_EOF = 1<<29, /* End of Frame */ - BMU_IRQ_EOB = 1<<28, /* Req "End of Buffer" IRQ */ - BMU_IRQ_EOF = 1<<27, /* Req "End of Frame" IRQ */ - /* TxCtrl specific bits */ - BMU_STFWD = 1<<26, /* (Tx) Store & Forward Frame */ - BMU_NO_FCS = 1<<25, /* (Tx) Disable MAC FCS (CRC) generation */ - BMU_SW = 1<<24, /* (Tx) 1 bit res. for SW use */ - /* RxCtrl specific bits */ - BMU_DEV_0 = 1<<26, /* (Rx) Transfer data to Dev0 */ - BMU_STAT_VAL = 1<<25, /* (Rx) Rx Status Valid */ - BMU_TIST_VAL = 1<<24, /* (Rx) Rx TimeStamp Valid */ - /* Bit 23..16: BMU Check Opcodes */ - BMU_CHECK = 0x55<<16, /* Default BMU check */ - BMU_TCP_CHECK = 0x56<<16, /* Descr with TCP ext */ - BMU_UDP_CHECK = 0x57<<16, /* Descr with UDP ext (YUKON only) */ - BMU_BBC = 0xffffL, /* Bit 15.. 0: Buffer Byte Counter */ -}; - -/* B2_BSC_CTRL 8 bit Blink Source Counter Control */ -enum { - BSC_START = 1<<1, /* Start Blink Source Counter */ - BSC_STOP = 1<<0, /* Stop Blink Source Counter */ -}; - -/* B2_BSC_STAT 8 bit Blink Source Counter Status */ -enum { - BSC_SRC = 1<<0, /* Blink Source, 0=Off / 1=On */ -}; - -/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */ -enum { - BSC_T_ON = 1<<2, /* Test mode on */ - BSC_T_OFF = 1<<1, /* Test mode off */ - BSC_T_STEP = 1<<0, /* Test step */ -}; - -/* B3_RAM_ADDR 32 bit RAM Address, to read or write */ - /* Bit 31..19: reserved */ -#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */ -/* RAM Interface Registers */ - -/* B3_RI_CTRL 16 bit RAM Iface Control Register */ -enum { - RI_CLR_RD_PERR = 1<<9, /* Clear IRQ RAM Read Parity Err */ - RI_CLR_WR_PERR = 1<<8, /* Clear IRQ RAM Write Parity Err*/ - - RI_RST_CLR = 1<<1, /* Clear RAM Interface Reset */ - RI_RST_SET = 1<<0, /* Set RAM Interface Reset */ -}; - -/* MAC Arbiter Registers */ -/* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */ -enum { - MA_FOE_ON = 1<<3, /* XMAC Fast Output Enable ON */ - MA_FOE_OFF = 1<<2, /* XMAC Fast Output Enable OFF */ - MA_RST_CLR = 1<<1, /* Clear MAC Arbiter Reset */ - MA_RST_SET = 1<<0, /* Set MAC Arbiter Reset */ - -}; - -/* Timeout values */ -#define SK_MAC_TO_53 72 /* MAC arbiter timeout */ -#define SK_PKT_TO_53 0x2000 /* Packet arbiter timeout */ -#define SK_PKT_TO_MAX 0xffff /* Maximum value */ -#define SK_RI_TO_53 36 /* RAM interface timeout */ - -/* Packet Arbiter Registers */ -/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */ -enum { - PA_CLR_TO_TX2 = 1<<13,/* Clear IRQ Packet Timeout TX2 */ - PA_CLR_TO_TX1 = 1<<12,/* Clear IRQ Packet Timeout TX1 */ - PA_CLR_TO_RX2 = 1<<11,/* Clear IRQ Packet Timeout RX2 */ - PA_CLR_TO_RX1 = 1<<10,/* Clear IRQ Packet Timeout RX1 */ - PA_ENA_TO_TX2 = 1<<9, /* Enable Timeout Timer TX2 */ - PA_DIS_TO_TX2 = 1<<8, /* Disable Timeout Timer TX2 */ - PA_ENA_TO_TX1 = 1<<7, /* Enable Timeout Timer TX1 */ - PA_DIS_TO_TX1 = 1<<6, /* Disable Timeout Timer TX1 */ - PA_ENA_TO_RX2 = 1<<5, /* Enable Timeout Timer RX2 */ - PA_DIS_TO_RX2 = 1<<4, /* Disable Timeout Timer RX2 */ - PA_ENA_TO_RX1 = 1<<3, /* Enable Timeout Timer RX1 */ - PA_DIS_TO_RX1 = 1<<2, /* Disable Timeout Timer RX1 */ - PA_RST_CLR = 1<<1, /* Clear MAC Arbiter Reset */ - PA_RST_SET = 1<<0, /* Set MAC Arbiter Reset */ -}; - -#define PA_ENA_TO_ALL (PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\ - PA_ENA_TO_TX1 | PA_ENA_TO_TX2) - - -/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */ -/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */ -/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */ -/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */ -/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */ - -#define TXA_MAX_VAL 0x00ffffffUL /* Bit 23.. 0: Max TXA Timer/Cnt Val */ - -/* TXA_CTRL 8 bit Tx Arbiter Control Register */ -enum { - TXA_ENA_FSYNC = 1<<7, /* Enable force of sync Tx queue */ - TXA_DIS_FSYNC = 1<<6, /* Disable force of sync Tx queue */ - TXA_ENA_ALLOC = 1<<5, /* Enable alloc of free bandwidth */ - TXA_DIS_ALLOC = 1<<4, /* Disable alloc of free bandwidth */ - TXA_START_RC = 1<<3, /* Start sync Rate Control */ - TXA_STOP_RC = 1<<2, /* Stop sync Rate Control */ - TXA_ENA_ARB = 1<<1, /* Enable Tx Arbiter */ - TXA_DIS_ARB = 1<<0, /* Disable Tx Arbiter */ -}; - -/* - * Bank 4 - 5 - */ -/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */ -enum { - TXA_ITI_INI = 0x0200,/* 32 bit Tx Arb Interval Timer Init Val*/ - TXA_ITI_VAL = 0x0204,/* 32 bit Tx Arb Interval Timer Value */ - TXA_LIM_INI = 0x0208,/* 32 bit Tx Arb Limit Counter Init Val */ - TXA_LIM_VAL = 0x020c,/* 32 bit Tx Arb Limit Counter Value */ - TXA_CTRL = 0x0210,/* 8 bit Tx Arbiter Control Register */ - TXA_TEST = 0x0211,/* 8 bit Tx Arbiter Test Register */ - TXA_STAT = 0x0212,/* 8 bit Tx Arbiter Status Register */ -}; - - -enum { - B6_EXT_REG = 0x0300,/* External registers (GENESIS only) */ - B7_CFG_SPC = 0x0380,/* copy of the Configuration register */ - B8_RQ1_REGS = 0x0400,/* Receive Queue 1 */ - B8_RQ2_REGS = 0x0480,/* Receive Queue 2 */ - B8_TS1_REGS = 0x0600,/* Transmit sync queue 1 */ - B8_TA1_REGS = 0x0680,/* Transmit async queue 1 */ - B8_TS2_REGS = 0x0700,/* Transmit sync queue 2 */ - B8_TA2_REGS = 0x0780,/* Transmit sync queue 2 */ - B16_RAM_REGS = 0x0800,/* RAM Buffer Registers */ -}; - -/* Queue Register Offsets, use Q_ADDR() to access */ -enum { - B8_Q_REGS = 0x0400, /* base of Queue registers */ - Q_D = 0x00, /* 8*32 bit Current Descriptor */ - Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */ - Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */ - Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */ - Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */ - Q_BC = 0x30, /* 32 bit Current Byte Counter */ - Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */ - Q_F = 0x38, /* 32 bit Flag Register */ - Q_T1 = 0x3c, /* 32 bit Test Register 1 */ - Q_T1_TR = 0x3c, /* 8 bit Test Register 1 Transfer SM */ - Q_T1_WR = 0x3d, /* 8 bit Test Register 1 Write Descriptor SM */ - Q_T1_RD = 0x3e, /* 8 bit Test Register 1 Read Descriptor SM */ - Q_T1_SV = 0x3f, /* 8 bit Test Register 1 Supervisor SM */ - Q_T2 = 0x40, /* 32 bit Test Register 2 */ - Q_T3 = 0x44, /* 32 bit Test Register 3 */ - -}; -#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs)) - -/* RAM Buffer Register Offsets */ -enum { - - RB_START= 0x00,/* 32 bit RAM Buffer Start Address */ - RB_END = 0x04,/* 32 bit RAM Buffer End Address */ - RB_WP = 0x08,/* 32 bit RAM Buffer Write Pointer */ - RB_RP = 0x0c,/* 32 bit RAM Buffer Read Pointer */ - RB_RX_UTPP= 0x10,/* 32 bit Rx Upper Threshold, Pause Packet */ - RB_RX_LTPP= 0x14,/* 32 bit Rx Lower Threshold, Pause Packet */ - RB_RX_UTHP= 0x18,/* 32 bit Rx Upper Threshold, High Prio */ - RB_RX_LTHP= 0x1c,/* 32 bit Rx Lower Threshold, High Prio */ - /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */ - RB_PC = 0x20,/* 32 bit RAM Buffer Packet Counter */ - RB_LEV = 0x24,/* 32 bit RAM Buffer Level Register */ - RB_CTRL = 0x28,/* 32 bit RAM Buffer Control Register */ - RB_TST1 = 0x29,/* 8 bit RAM Buffer Test Register 1 */ - RB_TST2 = 0x2a,/* 8 bit RAM Buffer Test Register 2 */ -}; - -/* Receive and Transmit Queues */ -enum { - Q_R1 = 0x0000, /* Receive Queue 1 */ - Q_R2 = 0x0080, /* Receive Queue 2 */ - Q_XS1 = 0x0200, /* Synchronous Transmit Queue 1 */ - Q_XA1 = 0x0280, /* Asynchronous Transmit Queue 1 */ - Q_XS2 = 0x0300, /* Synchronous Transmit Queue 2 */ - Q_XA2 = 0x0380, /* Asynchronous Transmit Queue 2 */ -}; - -/* Different MAC Types */ -enum { - SK_MAC_XMAC = 0, /* Xaqti XMAC II */ - SK_MAC_GMAC = 1, /* Marvell GMAC */ -}; - -/* Different PHY Types */ -enum { - SK_PHY_XMAC = 0,/* integrated in XMAC II */ - SK_PHY_BCOM = 1,/* Broadcom BCM5400 */ - SK_PHY_LONE = 2,/* Level One LXT1000 [not supported]*/ - SK_PHY_NAT = 3,/* National DP83891 [not supported] */ - SK_PHY_MARV_COPPER= 4,/* Marvell 88E1011S */ - SK_PHY_MARV_FIBER = 5,/* Marvell 88E1011S working on fiber */ -}; - -/* PHY addresses (bits 12..8 of PHY address reg) */ -enum { - PHY_ADDR_XMAC = 0<<8, - PHY_ADDR_BCOM = 1<<8, - -/* GPHY address (bits 15..11 of SMI control reg) */ - PHY_ADDR_MARV = 0, -}; - -#define RB_ADDR(offs, queue) ((u16)B16_RAM_REGS + (u16)(queue) + (offs)) - -/* Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only) */ -enum { - RX_MFF_EA = 0x0c00,/* 32 bit Receive MAC FIFO End Address */ - RX_MFF_WP = 0x0c04,/* 32 bit Receive MAC FIFO Write Pointer */ - - RX_MFF_RP = 0x0c0c,/* 32 bit Receive MAC FIFO Read Pointer */ - RX_MFF_PC = 0x0c10,/* 32 bit Receive MAC FIFO Packet Cnt */ - RX_MFF_LEV = 0x0c14,/* 32 bit Receive MAC FIFO Level */ - RX_MFF_CTRL1 = 0x0c18,/* 16 bit Receive MAC FIFO Control Reg 1*/ - RX_MFF_STAT_TO = 0x0c1a,/* 8 bit Receive MAC Status Timeout */ - RX_MFF_TIST_TO = 0x0c1b,/* 8 bit Receive MAC Time Stamp Timeout */ - RX_MFF_CTRL2 = 0x0c1c,/* 8 bit Receive MAC FIFO Control Reg 2*/ - RX_MFF_TST1 = 0x0c1d,/* 8 bit Receive MAC FIFO Test Reg 1 */ - RX_MFF_TST2 = 0x0c1e,/* 8 bit Receive MAC FIFO Test Reg 2 */ - - RX_LED_INI = 0x0c20,/* 32 bit Receive LED Cnt Init Value */ - RX_LED_VAL = 0x0c24,/* 32 bit Receive LED Cnt Current Value */ - RX_LED_CTRL = 0x0c28,/* 8 bit Receive LED Cnt Control Reg */ - RX_LED_TST = 0x0c29,/* 8 bit Receive LED Cnt Test Register */ - - LNK_SYNC_INI = 0x0c30,/* 32 bit Link Sync Cnt Init Value */ - LNK_SYNC_VAL = 0x0c34,/* 32 bit Link Sync Cnt Current Value */ - LNK_SYNC_CTRL = 0x0c38,/* 8 bit Link Sync Cnt Control Register */ - LNK_SYNC_TST = 0x0c39,/* 8 bit Link Sync Cnt Test Register */ - LNK_LED_REG = 0x0c3c,/* 8 bit Link LED Register */ -}; - -/* Receive and Transmit MAC FIFO Registers (GENESIS only) */ -/* RX_MFF_CTRL1 16 bit Receive MAC FIFO Control Reg 1 */ -enum { - MFF_ENA_RDY_PAT = 1<<13, /* Enable Ready Patch */ - MFF_DIS_RDY_PAT = 1<<12, /* Disable Ready Patch */ - MFF_ENA_TIM_PAT = 1<<11, /* Enable Timing Patch */ - MFF_DIS_TIM_PAT = 1<<10, /* Disable Timing Patch */ - MFF_ENA_ALM_FUL = 1<<9, /* Enable AlmostFull Sign */ - MFF_DIS_ALM_FUL = 1<<8, /* Disable AlmostFull Sign */ - MFF_ENA_PAUSE = 1<<7, /* Enable Pause Signaling */ - MFF_DIS_PAUSE = 1<<6, /* Disable Pause Signaling */ - MFF_ENA_FLUSH = 1<<5, /* Enable Frame Flushing */ - MFF_DIS_FLUSH = 1<<4, /* Disable Frame Flushing */ - MFF_ENA_TIST = 1<<3, /* Enable Time Stamp Gener */ - MFF_DIS_TIST = 1<<2, /* Disable Time Stamp Gener */ - MFF_CLR_INTIST = 1<<1, /* Clear IRQ No Time Stamp */ - MFF_CLR_INSTAT = 1<<0, /* Clear IRQ No Status */ - MFF_RX_CTRL_DEF = MFF_ENA_TIM_PAT, -}; - -/* TX_MFF_CTRL1 16 bit Transmit MAC FIFO Control Reg 1 */ -enum { - MFF_CLR_PERR = 1<<15, /* Clear Parity Error IRQ */ - - MFF_ENA_PKT_REC = 1<<13, /* Enable Packet Recovery */ - MFF_DIS_PKT_REC = 1<<12, /* Disable Packet Recovery */ - - MFF_ENA_W4E = 1<<7, /* Enable Wait for Empty */ - MFF_DIS_W4E = 1<<6, /* Disable Wait for Empty */ - - MFF_ENA_LOOPB = 1<<3, /* Enable Loopback */ - MFF_DIS_LOOPB = 1<<2, /* Disable Loopback */ - MFF_CLR_MAC_RST = 1<<1, /* Clear XMAC Reset */ - MFF_SET_MAC_RST = 1<<0, /* Set XMAC Reset */ - - MFF_TX_CTRL_DEF = MFF_ENA_PKT_REC | (u16) MFF_ENA_TIM_PAT | MFF_ENA_FLUSH, -}; - - -/* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */ -/* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */ -enum { - MFF_WSP_T_ON = 1<<6, /* Tx: Write Shadow Ptr TestOn */ - MFF_WSP_T_OFF = 1<<5, /* Tx: Write Shadow Ptr TstOff */ - MFF_WSP_INC = 1<<4, /* Tx: Write Shadow Ptr Increment */ - MFF_PC_DEC = 1<<3, /* Packet Counter Decrement */ - MFF_PC_T_ON = 1<<2, /* Packet Counter Test On */ - MFF_PC_T_OFF = 1<<1, /* Packet Counter Test Off */ - MFF_PC_INC = 1<<0, /* Packet Counter Increment */ -}; - -/* RX_MFF_TST1 8 bit Receive MAC FIFO Test Register 1 */ -/* TX_MFF_TST1 8 bit Transmit MAC FIFO Test Register 1 */ -enum { - MFF_WP_T_ON = 1<<6, /* Write Pointer Test On */ - MFF_WP_T_OFF = 1<<5, /* Write Pointer Test Off */ - MFF_WP_INC = 1<<4, /* Write Pointer Increm */ - - MFF_RP_T_ON = 1<<2, /* Read Pointer Test On */ - MFF_RP_T_OFF = 1<<1, /* Read Pointer Test Off */ - MFF_RP_DEC = 1<<0, /* Read Pointer Decrement */ -}; - -/* RX_MFF_CTRL2 8 bit Receive MAC FIFO Control Reg 2 */ -/* TX_MFF_CTRL2 8 bit Transmit MAC FIFO Control Reg 2 */ -enum { - MFF_ENA_OP_MD = 1<<3, /* Enable Operation Mode */ - MFF_DIS_OP_MD = 1<<2, /* Disable Operation Mode */ - MFF_RST_CLR = 1<<1, /* Clear MAC FIFO Reset */ - MFF_RST_SET = 1<<0, /* Set MAC FIFO Reset */ -}; - - -/* Link LED Counter Registers (GENESIS only) */ - -/* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */ -/* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */ -/* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */ -enum { - LED_START = 1<<2, /* Start Timer */ - LED_STOP = 1<<1, /* Stop Timer */ - LED_STATE = 1<<0, /* Rx/Tx: LED State, 1=LED on */ -}; - -/* RX_LED_TST 8 bit Receive LED Cnt Test Register */ -/* TX_LED_TST 8 bit Transmit LED Cnt Test Register */ -/* LNK_SYNC_TST 8 bit Link Sync Cnt Test Register */ -enum { - LED_T_ON = 1<<2, /* LED Counter Test mode On */ - LED_T_OFF = 1<<1, /* LED Counter Test mode Off */ - LED_T_STEP = 1<<0, /* LED Counter Step */ -}; - -/* LNK_LED_REG 8 bit Link LED Register */ -enum { - LED_BLK_ON = 1<<5, /* Link LED Blinking On */ - LED_BLK_OFF = 1<<4, /* Link LED Blinking Off */ - LED_SYNC_ON = 1<<3, /* Use Sync Wire to switch LED */ - LED_SYNC_OFF = 1<<2, /* Disable Sync Wire Input */ - LED_ON = 1<<1, /* switch LED on */ - LED_OFF = 1<<0, /* switch LED off */ -}; - -/* Receive GMAC FIFO (YUKON) */ -enum { - RX_GMF_EA = 0x0c40,/* 32 bit Rx GMAC FIFO End Address */ - RX_GMF_AF_THR = 0x0c44,/* 32 bit Rx GMAC FIFO Almost Full Thresh. */ - RX_GMF_CTRL_T = 0x0c48,/* 32 bit Rx GMAC FIFO Control/Test */ - RX_GMF_FL_MSK = 0x0c4c,/* 32 bit Rx GMAC FIFO Flush Mask */ - RX_GMF_FL_THR = 0x0c50,/* 32 bit Rx GMAC FIFO Flush Threshold */ - RX_GMF_WP = 0x0c60,/* 32 bit Rx GMAC FIFO Write Pointer */ - RX_GMF_WLEV = 0x0c68,/* 32 bit Rx GMAC FIFO Write Level */ - RX_GMF_RP = 0x0c70,/* 32 bit Rx GMAC FIFO Read Pointer */ - RX_GMF_RLEV = 0x0c78,/* 32 bit Rx GMAC FIFO Read Level */ -}; - - -/* TXA_TEST 8 bit Tx Arbiter Test Register */ -enum { - TXA_INT_T_ON = 1<<5, /* Tx Arb Interval Timer Test On */ - TXA_INT_T_OFF = 1<<4, /* Tx Arb Interval Timer Test Off */ - TXA_INT_T_STEP = 1<<3, /* Tx Arb Interval Timer Step */ - TXA_LIM_T_ON = 1<<2, /* Tx Arb Limit Timer Test On */ - TXA_LIM_T_OFF = 1<<1, /* Tx Arb Limit Timer Test Off */ - TXA_LIM_T_STEP = 1<<0, /* Tx Arb Limit Timer Step */ -}; - -/* TXA_STAT 8 bit Tx Arbiter Status Register */ -enum { - TXA_PRIO_XS = 1<<0, /* sync queue has prio to send */ -}; - - -/* Q_BC 32 bit Current Byte Counter */ - -/* BMU Control Status Registers */ -/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */ -/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */ -/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ -/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */ -/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ -/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */ -/* Q_CSR 32 bit BMU Control/Status Register */ - -enum { - CSR_SV_IDLE = 1<<24, /* BMU SM Idle */ - - CSR_DESC_CLR = 1<<21, /* Clear Reset for Descr */ - CSR_DESC_SET = 1<<20, /* Set Reset for Descr */ - CSR_FIFO_CLR = 1<<19, /* Clear Reset for FIFO */ - CSR_FIFO_SET = 1<<18, /* Set Reset for FIFO */ - CSR_HPI_RUN = 1<<17, /* Release HPI SM */ - CSR_HPI_RST = 1<<16, /* Reset HPI SM to Idle */ - CSR_SV_RUN = 1<<15, /* Release Supervisor SM */ - CSR_SV_RST = 1<<14, /* Reset Supervisor SM */ - CSR_DREAD_RUN = 1<<13, /* Release Descr Read SM */ - CSR_DREAD_RST = 1<<12, /* Reset Descr Read SM */ - CSR_DWRITE_RUN = 1<<11, /* Release Descr Write SM */ - CSR_DWRITE_RST = 1<<10, /* Reset Descr Write SM */ - CSR_TRANS_RUN = 1<<9, /* Release Transfer SM */ - CSR_TRANS_RST = 1<<8, /* Reset Transfer SM */ - CSR_ENA_POL = 1<<7, /* Enable Descr Polling */ - CSR_DIS_POL = 1<<6, /* Disable Descr Polling */ - CSR_STOP = 1<<5, /* Stop Rx/Tx Queue */ - CSR_START = 1<<4, /* Start Rx/Tx Queue */ - CSR_IRQ_CL_P = 1<<3, /* (Rx) Clear Parity IRQ */ - CSR_IRQ_CL_B = 1<<2, /* Clear EOB IRQ */ - CSR_IRQ_CL_F = 1<<1, /* Clear EOF IRQ */ - CSR_IRQ_CL_C = 1<<0, /* Clear ERR IRQ */ -}; - -#define CSR_SET_RESET (CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\ - CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\ - CSR_TRANS_RST) -#define CSR_CLR_RESET (CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\ - CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\ - CSR_TRANS_RUN) - -/* Q_F 32 bit Flag Register */ -enum { - F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */ - F_EMPTY = 1<<27, /* Tx FIFO: empty flag */ - F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */ - F_WM_REACHED = 1<<25, /* Watermark reached */ - - F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */ - F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */ -}; - -/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */ -/* RB_START 32 bit RAM Buffer Start Address */ -/* RB_END 32 bit RAM Buffer End Address */ -/* RB_WP 32 bit RAM Buffer Write Pointer */ -/* RB_RP 32 bit RAM Buffer Read Pointer */ -/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */ -/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */ -/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */ -/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */ -/* RB_PC 32 bit RAM Buffer Packet Counter */ -/* RB_LEV 32 bit RAM Buffer Level Register */ - -#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */ -/* RB_TST2 8 bit RAM Buffer Test Register 2 */ -/* RB_TST1 8 bit RAM Buffer Test Register 1 */ - -/* RB_CTRL 8 bit RAM Buffer Control Register */ -enum { - RB_ENA_STFWD = 1<<5, /* Enable Store & Forward */ - RB_DIS_STFWD = 1<<4, /* Disable Store & Forward */ - RB_ENA_OP_MD = 1<<3, /* Enable Operation Mode */ - RB_DIS_OP_MD = 1<<2, /* Disable Operation Mode */ - RB_RST_CLR = 1<<1, /* Clear RAM Buf STM Reset */ - RB_RST_SET = 1<<0, /* Set RAM Buf STM Reset */ -}; - -/* Transmit MAC FIFO and Transmit LED Registers (GENESIS only), */ -enum { - TX_MFF_EA = 0x0d00,/* 32 bit Transmit MAC FIFO End Address */ - TX_MFF_WP = 0x0d04,/* 32 bit Transmit MAC FIFO WR Pointer */ - TX_MFF_WSP = 0x0d08,/* 32 bit Transmit MAC FIFO WR Shadow Ptr */ - TX_MFF_RP = 0x0d0c,/* 32 bit Transmit MAC FIFO RD Pointer */ - TX_MFF_PC = 0x0d10,/* 32 bit Transmit MAC FIFO Packet Cnt */ - TX_MFF_LEV = 0x0d14,/* 32 bit Transmit MAC FIFO Level */ - TX_MFF_CTRL1 = 0x0d18,/* 16 bit Transmit MAC FIFO Ctrl Reg 1 */ - TX_MFF_WAF = 0x0d1a,/* 8 bit Transmit MAC Wait after flush */ - - TX_MFF_CTRL2 = 0x0d1c,/* 8 bit Transmit MAC FIFO Ctrl Reg 2 */ - TX_MFF_TST1 = 0x0d1d,/* 8 bit Transmit MAC FIFO Test Reg 1 */ - TX_MFF_TST2 = 0x0d1e,/* 8 bit Transmit MAC FIFO Test Reg 2 */ - - TX_LED_INI = 0x0d20,/* 32 bit Transmit LED Cnt Init Value */ - TX_LED_VAL = 0x0d24,/* 32 bit Transmit LED Cnt Current Val */ - TX_LED_CTRL = 0x0d28,/* 8 bit Transmit LED Cnt Control Reg */ - TX_LED_TST = 0x0d29,/* 8 bit Transmit LED Cnt Test Reg */ -}; - -/* Counter and Timer constants, for a host clock of 62.5 MHz */ -#define SK_XMIT_DUR 0x002faf08UL /* 50 ms */ -#define SK_BLK_DUR 0x01dcd650UL /* 500 ms */ - -#define SK_DPOLL_DEF 0x00ee6b28UL /* 250 ms at 62.5 MHz */ - -#define SK_DPOLL_MAX 0x00ffffffUL /* 268 ms at 62.5 MHz */ - /* 215 ms at 78.12 MHz */ - -#define SK_FACT_62 100 /* is given in percent */ -#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */ -#define SK_FACT_78 125 /* on YUKON: 78.12 MHz */ - - -/* Transmit GMAC FIFO (YUKON only) */ -enum { - TX_GMF_EA = 0x0d40,/* 32 bit Tx GMAC FIFO End Address */ - TX_GMF_AE_THR = 0x0d44,/* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ - TX_GMF_CTRL_T = 0x0d48,/* 32 bit Tx GMAC FIFO Control/Test */ - - TX_GMF_WP = 0x0d60,/* 32 bit Tx GMAC FIFO Write Pointer */ - TX_GMF_WSP = 0x0d64,/* 32 bit Tx GMAC FIFO Write Shadow Ptr. */ - TX_GMF_WLEV = 0x0d68,/* 32 bit Tx GMAC FIFO Write Level */ - - TX_GMF_RP = 0x0d70,/* 32 bit Tx GMAC FIFO Read Pointer */ - TX_GMF_RSTP = 0x0d74,/* 32 bit Tx GMAC FIFO Restart Pointer */ - TX_GMF_RLEV = 0x0d78,/* 32 bit Tx GMAC FIFO Read Level */ - - /* Descriptor Poll Timer Registers */ - B28_DPT_INI = 0x0e00,/* 24 bit Descriptor Poll Timer Init Val */ - B28_DPT_VAL = 0x0e04,/* 24 bit Descriptor Poll Timer Curr Val */ - B28_DPT_CTRL = 0x0e08,/* 8 bit Descriptor Poll Timer Ctrl Reg */ - - B28_DPT_TST = 0x0e0a,/* 8 bit Descriptor Poll Timer Test Reg */ - - /* Time Stamp Timer Registers (YUKON only) */ - GMAC_TI_ST_VAL = 0x0e14,/* 32 bit Time Stamp Timer Curr Val */ - GMAC_TI_ST_CTRL = 0x0e18,/* 8 bit Time Stamp Timer Ctrl Reg */ - GMAC_TI_ST_TST = 0x0e1a,/* 8 bit Time Stamp Timer Test Reg */ -}; - - -enum { - LINKLED_OFF = 0x01, - LINKLED_ON = 0x02, - LINKLED_LINKSYNC_OFF = 0x04, - LINKLED_LINKSYNC_ON = 0x08, - LINKLED_BLINK_OFF = 0x10, - LINKLED_BLINK_ON = 0x20, -}; - -/* GMAC and GPHY Control Registers (YUKON only) */ -enum { - GMAC_CTRL = 0x0f00,/* 32 bit GMAC Control Reg */ - GPHY_CTRL = 0x0f04,/* 32 bit GPHY Control Reg */ - GMAC_IRQ_SRC = 0x0f08,/* 8 bit GMAC Interrupt Source Reg */ - GMAC_IRQ_MSK = 0x0f0c,/* 8 bit GMAC Interrupt Mask Reg */ - GMAC_LINK_CTRL = 0x0f10,/* 16 bit Link Control Reg */ - -/* Wake-up Frame Pattern Match Control Registers (YUKON only) */ - - WOL_REG_OFFS = 0x20,/* HW-Bug: Address is + 0x20 against spec. */ - - WOL_CTRL_STAT = 0x0f20,/* 16 bit WOL Control/Status Reg */ - WOL_MATCH_CTL = 0x0f22,/* 8 bit WOL Match Control Reg */ - WOL_MATCH_RES = 0x0f23,/* 8 bit WOL Match Result Reg */ - WOL_MAC_ADDR = 0x0f24,/* 32 bit WOL MAC Address */ - WOL_PATT_RPTR = 0x0f2c,/* 8 bit WOL Pattern Read Pointer */ - -/* WOL Pattern Length Registers (YUKON only) */ - - WOL_PATT_LEN_LO = 0x0f30,/* 32 bit WOL Pattern Length 3..0 */ - WOL_PATT_LEN_HI = 0x0f34,/* 24 bit WOL Pattern Length 6..4 */ - -/* WOL Pattern Counter Registers (YUKON only) */ - - WOL_PATT_CNT_0 = 0x0f38,/* 32 bit WOL Pattern Counter 3..0 */ - WOL_PATT_CNT_4 = 0x0f3c,/* 24 bit WOL Pattern Counter 6..4 */ -}; -#define WOL_REGS(port, x) (x + (port)*0x80) - -enum { - WOL_PATT_RAM_1 = 0x1000,/* WOL Pattern RAM Link 1 */ - WOL_PATT_RAM_2 = 0x1400,/* WOL Pattern RAM Link 2 */ -}; -#define WOL_PATT_RAM_BASE(port) (WOL_PATT_RAM_1 + (port)*0x400) - -enum { - BASE_XMAC_1 = 0x2000,/* XMAC 1 registers */ - BASE_GMAC_1 = 0x2800,/* GMAC 1 registers */ - BASE_XMAC_2 = 0x3000,/* XMAC 2 registers */ - BASE_GMAC_2 = 0x3800,/* GMAC 2 registers */ -}; - -/* - * Receive Frame Status Encoding - */ -enum { - XMR_FS_LEN = 0x3fff<<18, /* Bit 31..18: Rx Frame Length */ - XMR_FS_LEN_SHIFT = 18, - XMR_FS_2L_VLAN = 1<<17, /* Bit 17: tagged wh 2Lev VLAN ID*/ - XMR_FS_1_VLAN = 1<<16, /* Bit 16: tagged wh 1ev VLAN ID*/ - XMR_FS_BC = 1<<15, /* Bit 15: Broadcast Frame */ - XMR_FS_MC = 1<<14, /* Bit 14: Multicast Frame */ - XMR_FS_UC = 1<<13, /* Bit 13: Unicast Frame */ - - XMR_FS_BURST = 1<<11, /* Bit 11: Burst Mode */ - XMR_FS_CEX_ERR = 1<<10, /* Bit 10: Carrier Ext. Error */ - XMR_FS_802_3 = 1<<9, /* Bit 9: 802.3 Frame */ - XMR_FS_COL_ERR = 1<<8, /* Bit 8: Collision Error */ - XMR_FS_CAR_ERR = 1<<7, /* Bit 7: Carrier Event Error */ - XMR_FS_LEN_ERR = 1<<6, /* Bit 6: In-Range Length Error */ - XMR_FS_FRA_ERR = 1<<5, /* Bit 5: Framing Error */ - XMR_FS_RUNT = 1<<4, /* Bit 4: Runt Frame */ - XMR_FS_LNG_ERR = 1<<3, /* Bit 3: Giant (Jumbo) Frame */ - XMR_FS_FCS_ERR = 1<<2, /* Bit 2: Frame Check Sequ Err */ - XMR_FS_ERR = 1<<1, /* Bit 1: Frame Error */ - XMR_FS_MCTRL = 1<<0, /* Bit 0: MAC Control Packet */ - -/* - * XMR_FS_ERR will be set if - * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT, - * XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR - * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue - * XMR_FS_ERR unless the corresponding bit in the Receive Command - * Register is set. - */ -}; - -/* -,* XMAC-PHY Registers, indirect addressed over the XMAC - */ -enum { - PHY_XMAC_CTRL = 0x00,/* 16 bit r/w PHY Control Register */ - PHY_XMAC_STAT = 0x01,/* 16 bit r/w PHY Status Register */ - PHY_XMAC_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */ - PHY_XMAC_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */ - PHY_XMAC_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */ - PHY_XMAC_AUNE_LP = 0x05,/* 16 bit r/o Link Partner Abi Reg */ - PHY_XMAC_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */ - PHY_XMAC_NEPG = 0x07,/* 16 bit r/w Next Page Register */ - PHY_XMAC_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */ - - PHY_XMAC_EXT_STAT = 0x0f,/* 16 bit r/o Ext Status Register */ - PHY_XMAC_RES_ABI = 0x10,/* 16 bit r/o PHY Resolved Ability */ -}; -/* - * Broadcom-PHY Registers, indirect addressed over XMAC - */ -enum { - PHY_BCOM_CTRL = 0x00,/* 16 bit r/w PHY Control Register */ - PHY_BCOM_STAT = 0x01,/* 16 bit r/o PHY Status Register */ - PHY_BCOM_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */ - PHY_BCOM_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */ - PHY_BCOM_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */ - PHY_BCOM_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */ - PHY_BCOM_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */ - PHY_BCOM_NEPG = 0x07,/* 16 bit r/w Next Page Register */ - PHY_BCOM_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */ - /* Broadcom-specific registers */ - PHY_BCOM_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */ - PHY_BCOM_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */ - PHY_BCOM_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */ - PHY_BCOM_P_EXT_CTRL = 0x10,/* 16 bit r/w PHY Extended Ctrl Reg */ - PHY_BCOM_P_EXT_STAT = 0x11,/* 16 bit r/o PHY Extended Stat Reg */ - PHY_BCOM_RE_CTR = 0x12,/* 16 bit r/w Receive Error Counter */ - PHY_BCOM_FC_CTR = 0x13,/* 16 bit r/w False Carrier Sense Cnt */ - PHY_BCOM_RNO_CTR = 0x14,/* 16 bit r/w Receiver NOT_OK Cnt */ - - PHY_BCOM_AUX_CTRL = 0x18,/* 16 bit r/w Auxiliary Control Reg */ - PHY_BCOM_AUX_STAT = 0x19,/* 16 bit r/o Auxiliary Stat Summary */ - PHY_BCOM_INT_STAT = 0x1a,/* 16 bit r/o Interrupt Status Reg */ - PHY_BCOM_INT_MASK = 0x1b,/* 16 bit r/w Interrupt Mask Reg */ -}; - -/* - * Marvel-PHY Registers, indirect addressed over GMAC - */ -enum { - PHY_MARV_CTRL = 0x00,/* 16 bit r/w PHY Control Register */ - PHY_MARV_STAT = 0x01,/* 16 bit r/o PHY Status Register */ - PHY_MARV_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */ - PHY_MARV_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */ - PHY_MARV_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */ - PHY_MARV_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */ - PHY_MARV_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */ - PHY_MARV_NEPG = 0x07,/* 16 bit r/w Next Page Register */ - PHY_MARV_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */ - /* Marvel-specific registers */ - PHY_MARV_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */ - PHY_MARV_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */ - PHY_MARV_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */ - PHY_MARV_PHY_CTRL = 0x10,/* 16 bit r/w PHY Specific Ctrl Reg */ - PHY_MARV_PHY_STAT = 0x11,/* 16 bit r/o PHY Specific Stat Reg */ - PHY_MARV_INT_MASK = 0x12,/* 16 bit r/w Interrupt Mask Reg */ - PHY_MARV_INT_STAT = 0x13,/* 16 bit r/o Interrupt Status Reg */ - PHY_MARV_EXT_CTRL = 0x14,/* 16 bit r/w Ext. PHY Specific Ctrl */ - PHY_MARV_RXE_CNT = 0x15,/* 16 bit r/w Receive Error Counter */ - PHY_MARV_EXT_ADR = 0x16,/* 16 bit r/w Ext. Ad. for Cable Diag. */ - PHY_MARV_PORT_IRQ = 0x17,/* 16 bit r/o Port 0 IRQ (88E1111 only) */ - PHY_MARV_LED_CTRL = 0x18,/* 16 bit r/w LED Control Reg */ - PHY_MARV_LED_OVER = 0x19,/* 16 bit r/w Manual LED Override Reg */ - PHY_MARV_EXT_CTRL_2 = 0x1a,/* 16 bit r/w Ext. PHY Specific Ctrl 2 */ - PHY_MARV_EXT_P_STAT = 0x1b,/* 16 bit r/w Ext. PHY Spec. Stat Reg */ - PHY_MARV_CABLE_DIAG = 0x1c,/* 16 bit r/o Cable Diagnostic Reg */ - PHY_MARV_PAGE_ADDR = 0x1d,/* 16 bit r/w Extended Page Address Reg */ - PHY_MARV_PAGE_DATA = 0x1e,/* 16 bit r/w Extended Page Data Reg */ - -/* for 10/100 Fast Ethernet PHY (88E3082 only) */ - PHY_MARV_FE_LED_PAR = 0x16,/* 16 bit r/w LED Parallel Select Reg. */ - PHY_MARV_FE_LED_SER = 0x17,/* 16 bit r/w LED Stream Select S. LED */ - PHY_MARV_FE_VCT_TX = 0x1a,/* 16 bit r/w VCT Reg. for TXP/N Pins */ - PHY_MARV_FE_VCT_RX = 0x1b,/* 16 bit r/o VCT Reg. for RXP/N Pins */ - PHY_MARV_FE_SPEC_2 = 0x1c,/* 16 bit r/w Specific Control Reg. 2 */ -}; - -enum { - PHY_CT_RESET = 1<<15, /* Bit 15: (sc) clear all PHY related regs */ - PHY_CT_LOOP = 1<<14, /* Bit 14: enable Loopback over PHY */ - PHY_CT_SPS_LSB = 1<<13, /* Bit 13: Speed select, lower bit */ - PHY_CT_ANE = 1<<12, /* Bit 12: Auto-Negotiation Enabled */ - PHY_CT_PDOWN = 1<<11, /* Bit 11: Power Down Mode */ - PHY_CT_ISOL = 1<<10, /* Bit 10: Isolate Mode */ - PHY_CT_RE_CFG = 1<<9, /* Bit 9: (sc) Restart Auto-Negotiation */ - PHY_CT_DUP_MD = 1<<8, /* Bit 8: Duplex Mode */ - PHY_CT_COL_TST = 1<<7, /* Bit 7: Collision Test enabled */ - PHY_CT_SPS_MSB = 1<<6, /* Bit 6: Speed select, upper bit */ -}; - -enum { - PHY_CT_SP1000 = PHY_CT_SPS_MSB, /* enable speed of 1000 Mbps */ - PHY_CT_SP100 = PHY_CT_SPS_LSB, /* enable speed of 100 Mbps */ - PHY_CT_SP10 = 0, /* enable speed of 10 Mbps */ -}; - -enum { - PHY_ST_EXT_ST = 1<<8, /* Bit 8: Extended Status Present */ - - PHY_ST_PRE_SUP = 1<<6, /* Bit 6: Preamble Suppression */ - PHY_ST_AN_OVER = 1<<5, /* Bit 5: Auto-Negotiation Over */ - PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occurred */ - PHY_ST_AN_CAP = 1<<3, /* Bit 3: Auto-Negotiation Capability */ - PHY_ST_LSYNC = 1<<2, /* Bit 2: Link Synchronized */ - PHY_ST_JAB_DET = 1<<1, /* Bit 1: Jabber Detected */ - PHY_ST_EXT_REG = 1<<0, /* Bit 0: Extended Register available */ -}; - -enum { - PHY_I1_OUI_MSK = 0x3f<<10, /* Bit 15..10: Organization Unique ID */ - PHY_I1_MOD_NUM = 0x3f<<4, /* Bit 9.. 4: Model Number */ - PHY_I1_REV_MSK = 0xf, /* Bit 3.. 0: Revision Number */ -}; - -/* different Broadcom PHY Ids */ -enum { - PHY_BCOM_ID1_A1 = 0x6041, - PHY_BCOM_ID1_B2 = 0x6043, - PHY_BCOM_ID1_C0 = 0x6044, - PHY_BCOM_ID1_C5 = 0x6047, -}; - -/* different Marvell PHY Ids */ -enum { - PHY_MARV_ID0_VAL= 0x0141, /* Marvell Unique Identifier */ - PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */ - PHY_MARV_ID1_B2 = 0x0C25, /* Yukon-Plus (PHY 88E1011) */ - PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */ - PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */ -}; - -/* Advertisement register bits */ -enum { - PHY_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */ - PHY_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */ - PHY_AN_RF = 1<<13, /* Bit 13: Remote Fault Bits */ - - PHY_AN_PAUSE_ASYM = 1<<11,/* Bit 11: Try for asymmetric */ - PHY_AN_PAUSE_CAP = 1<<10, /* Bit 10: Try for pause */ - PHY_AN_100BASE4 = 1<<9, /* Bit 9: Try for 100mbps 4k packets */ - PHY_AN_100FULL = 1<<8, /* Bit 8: Try for 100mbps full-duplex */ - PHY_AN_100HALF = 1<<7, /* Bit 7: Try for 100mbps half-duplex */ - PHY_AN_10FULL = 1<<6, /* Bit 6: Try for 10mbps full-duplex */ - PHY_AN_10HALF = 1<<5, /* Bit 5: Try for 10mbps half-duplex */ - PHY_AN_CSMA = 1<<0, /* Bit 0: Only selector supported */ - PHY_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/ - PHY_AN_FULL = PHY_AN_100FULL | PHY_AN_10FULL | PHY_AN_CSMA, - PHY_AN_ALL = PHY_AN_10HALF | PHY_AN_10FULL | - PHY_AN_100HALF | PHY_AN_100FULL, -}; - -/* Xmac Specific */ -enum { - PHY_X_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */ - PHY_X_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */ - PHY_X_AN_RFB = 3<<12,/* Bit 13..12: Remote Fault Bits */ - - PHY_X_AN_PAUSE = 3<<7,/* Bit 8.. 7: Pause Bits */ - PHY_X_AN_HD = 1<<6, /* Bit 6: Half Duplex */ - PHY_X_AN_FD = 1<<5, /* Bit 5: Full Duplex */ -}; - -/* Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding */ -enum { - PHY_X_P_NO_PAUSE= 0<<7,/* Bit 8..7: no Pause Mode */ - PHY_X_P_SYM_MD = 1<<7, /* Bit 8..7: symmetric Pause Mode */ - PHY_X_P_ASYM_MD = 2<<7,/* Bit 8..7: asymmetric Pause Mode */ - PHY_X_P_BOTH_MD = 3<<7,/* Bit 8..7: both Pause Mode */ -}; - - -/***** PHY_XMAC_EXT_STAT 16 bit r/w Extended Status Register *****/ -enum { - PHY_X_EX_FD = 1<<15, /* Bit 15: Device Supports Full Duplex */ - PHY_X_EX_HD = 1<<14, /* Bit 14: Device Supports Half Duplex */ -}; - -/***** PHY_XMAC_RES_ABI 16 bit r/o PHY Resolved Ability *****/ -enum { - PHY_X_RS_PAUSE = 3<<7, /* Bit 8..7: selected Pause Mode */ - PHY_X_RS_HD = 1<<6, /* Bit 6: Half Duplex Mode selected */ - PHY_X_RS_FD = 1<<5, /* Bit 5: Full Duplex Mode selected */ - PHY_X_RS_ABLMIS = 1<<4, /* Bit 4: duplex or pause cap mismatch */ - PHY_X_RS_PAUMIS = 1<<3, /* Bit 3: pause capability mismatch */ -}; - -/* Remote Fault Bits (PHY_X_AN_RFB) encoding */ -enum { - X_RFB_OK = 0<<12,/* Bit 13..12 No errors, Link OK */ - X_RFB_LF = 1<<12,/* Bit 13..12 Link Failure */ - X_RFB_OFF = 2<<12,/* Bit 13..12 Offline */ - X_RFB_AN_ERR = 3<<12,/* Bit 13..12 Auto-Negotiation Error */ -}; - -/* Broadcom-Specific */ -/***** PHY_BCOM_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -enum { - PHY_B_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */ - PHY_B_1000C_MSE = 1<<12, /* Bit 12: Master/Slave Enable */ - PHY_B_1000C_MSC = 1<<11, /* Bit 11: M/S Configuration */ - PHY_B_1000C_RD = 1<<10, /* Bit 10: Repeater/DTE */ - PHY_B_1000C_AFD = 1<<9, /* Bit 9: Advertise Full Duplex */ - PHY_B_1000C_AHD = 1<<8, /* Bit 8: Advertise Half Duplex */ -}; - -/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -enum { - PHY_B_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */ - PHY_B_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */ - PHY_B_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */ - PHY_B_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status */ - PHY_B_1000S_LP_FD = 1<<11, /* Bit 11: Link Partner can FD */ - PHY_B_1000S_LP_HD = 1<<10, /* Bit 10: Link Partner can HD */ - /* Bit 9..8: reserved */ - PHY_B_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */ -}; - -/***** PHY_BCOM_EXT_STAT 16 bit r/o Extended Status Register *****/ -enum { - PHY_B_ES_X_FD_CAP = 1<<15, /* Bit 15: 1000Base-X FD capable */ - PHY_B_ES_X_HD_CAP = 1<<14, /* Bit 14: 1000Base-X HD capable */ - PHY_B_ES_T_FD_CAP = 1<<13, /* Bit 13: 1000Base-T FD capable */ - PHY_B_ES_T_HD_CAP = 1<<12, /* Bit 12: 1000Base-T HD capable */ -}; - -/***** PHY_BCOM_P_EXT_CTRL 16 bit r/w PHY Extended Control Reg *****/ -enum { - PHY_B_PEC_MAC_PHY = 1<<15, /* Bit 15: 10BIT/GMI-Interface */ - PHY_B_PEC_DIS_CROSS = 1<<14, /* Bit 14: Disable MDI Crossover */ - PHY_B_PEC_TX_DIS = 1<<13, /* Bit 13: Tx output Disabled */ - PHY_B_PEC_INT_DIS = 1<<12, /* Bit 12: Interrupts Disabled */ - PHY_B_PEC_F_INT = 1<<11, /* Bit 11: Force Interrupt */ - PHY_B_PEC_BY_45 = 1<<10, /* Bit 10: Bypass 4B5B-Decoder */ - PHY_B_PEC_BY_SCR = 1<<9, /* Bit 9: Bypass Scrambler */ - PHY_B_PEC_BY_MLT3 = 1<<8, /* Bit 8: Bypass MLT3 Encoder */ - PHY_B_PEC_BY_RXA = 1<<7, /* Bit 7: Bypass Rx Alignm. */ - PHY_B_PEC_RES_SCR = 1<<6, /* Bit 6: Reset Scrambler */ - PHY_B_PEC_EN_LTR = 1<<5, /* Bit 5: Ena LED Traffic Mode */ - PHY_B_PEC_LED_ON = 1<<4, /* Bit 4: Force LED's on */ - PHY_B_PEC_LED_OFF = 1<<3, /* Bit 3: Force LED's off */ - PHY_B_PEC_EX_IPG = 1<<2, /* Bit 2: Extend Tx IPG Mode */ - PHY_B_PEC_3_LED = 1<<1, /* Bit 1: Three Link LED mode */ - PHY_B_PEC_HIGH_LA = 1<<0, /* Bit 0: GMII FIFO Elasticy */ -}; - -/***** PHY_BCOM_P_EXT_STAT 16 bit r/o PHY Extended Status Reg *****/ -enum { - PHY_B_PES_CROSS_STAT = 1<<13, /* Bit 13: MDI Crossover Status */ - PHY_B_PES_INT_STAT = 1<<12, /* Bit 12: Interrupt Status */ - PHY_B_PES_RRS = 1<<11, /* Bit 11: Remote Receiver Stat. */ - PHY_B_PES_LRS = 1<<10, /* Bit 10: Local Receiver Stat. */ - PHY_B_PES_LOCKED = 1<<9, /* Bit 9: Locked */ - PHY_B_PES_LS = 1<<8, /* Bit 8: Link Status */ - PHY_B_PES_RF = 1<<7, /* Bit 7: Remote Fault */ - PHY_B_PES_CE_ER = 1<<6, /* Bit 6: Carrier Ext Error */ - PHY_B_PES_BAD_SSD = 1<<5, /* Bit 5: Bad SSD */ - PHY_B_PES_BAD_ESD = 1<<4, /* Bit 4: Bad ESD */ - PHY_B_PES_RX_ER = 1<<3, /* Bit 3: Receive Error */ - PHY_B_PES_TX_ER = 1<<2, /* Bit 2: Transmit Error */ - PHY_B_PES_LOCK_ER = 1<<1, /* Bit 1: Lock Error */ - PHY_B_PES_MLT3_ER = 1<<0, /* Bit 0: MLT3 code Error */ -}; - -/* PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/* PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -enum { - PHY_B_AN_RF = 1<<13, /* Bit 13: Remote Fault */ - - PHY_B_AN_ASP = 1<<11, /* Bit 11: Asymmetric Pause */ - PHY_B_AN_PC = 1<<10, /* Bit 10: Pause Capable */ -}; - - -/***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/ -enum { - PHY_B_FC_CTR = 0xff, /* Bit 7..0: False Carrier Counter */ - -/***** PHY_BCOM_RNO_CTR 16 bit r/w Receive NOT_OK Counter *****/ - PHY_B_RC_LOC_MSK = 0xff00, /* Bit 15..8: Local Rx NOT_OK cnt */ - PHY_B_RC_REM_MSK = 0x00ff, /* Bit 7..0: Remote Rx NOT_OK cnt */ - -/***** PHY_BCOM_AUX_CTRL 16 bit r/w Auxiliary Control Reg *****/ - PHY_B_AC_L_SQE = 1<<15, /* Bit 15: Low Squelch */ - PHY_B_AC_LONG_PACK = 1<<14, /* Bit 14: Rx Long Packets */ - PHY_B_AC_ER_CTRL = 3<<12,/* Bit 13..12: Edgerate Control */ - /* Bit 11: reserved */ - PHY_B_AC_TX_TST = 1<<10, /* Bit 10: Tx test bit, always 1 */ - /* Bit 9.. 8: reserved */ - PHY_B_AC_DIS_PRF = 1<<7, /* Bit 7: dis part resp filter */ - /* Bit 6: reserved */ - PHY_B_AC_DIS_PM = 1<<5, /* Bit 5: dis power management */ - /* Bit 4: reserved */ - PHY_B_AC_DIAG = 1<<3, /* Bit 3: Diagnostic Mode */ -}; - -/***** PHY_BCOM_AUX_STAT 16 bit r/o Auxiliary Status Reg *****/ -enum { - PHY_B_AS_AN_C = 1<<15, /* Bit 15: AutoNeg complete */ - PHY_B_AS_AN_CA = 1<<14, /* Bit 14: AN Complete Ack */ - PHY_B_AS_ANACK_D = 1<<13, /* Bit 13: AN Ack Detect */ - PHY_B_AS_ANAB_D = 1<<12, /* Bit 12: AN Ability Detect */ - PHY_B_AS_NPW = 1<<11, /* Bit 11: AN Next Page Wait */ - PHY_B_AS_AN_RES_MSK = 7<<8,/* Bit 10..8: AN HDC */ - PHY_B_AS_PDF = 1<<7, /* Bit 7: Parallel Detect. Fault */ - PHY_B_AS_RF = 1<<6, /* Bit 6: Remote Fault */ - PHY_B_AS_ANP_R = 1<<5, /* Bit 5: AN Page Received */ - PHY_B_AS_LP_ANAB = 1<<4, /* Bit 4: LP AN Ability */ - PHY_B_AS_LP_NPAB = 1<<3, /* Bit 3: LP Next Page Ability */ - PHY_B_AS_LS = 1<<2, /* Bit 2: Link Status */ - PHY_B_AS_PRR = 1<<1, /* Bit 1: Pause Resolution-Rx */ - PHY_B_AS_PRT = 1<<0, /* Bit 0: Pause Resolution-Tx */ -}; -#define PHY_B_AS_PAUSE_MSK (PHY_B_AS_PRR | PHY_B_AS_PRT) - -/***** PHY_BCOM_INT_STAT 16 bit r/o Interrupt Status Reg *****/ -/***** PHY_BCOM_INT_MASK 16 bit r/w Interrupt Mask Reg *****/ -enum { - PHY_B_IS_PSE = 1<<14, /* Bit 14: Pair Swap Error */ - PHY_B_IS_MDXI_SC = 1<<13, /* Bit 13: MDIX Status Change */ - PHY_B_IS_HCT = 1<<12, /* Bit 12: counter above 32k */ - PHY_B_IS_LCT = 1<<11, /* Bit 11: counter above 128 */ - PHY_B_IS_AN_PR = 1<<10, /* Bit 10: Page Received */ - PHY_B_IS_NO_HDCL = 1<<9, /* Bit 9: No HCD Link */ - PHY_B_IS_NO_HDC = 1<<8, /* Bit 8: No HCD */ - PHY_B_IS_NEG_USHDC = 1<<7, /* Bit 7: Negotiated Unsup. HCD */ - PHY_B_IS_SCR_S_ER = 1<<6, /* Bit 6: Scrambler Sync Error */ - PHY_B_IS_RRS_CHANGE = 1<<5, /* Bit 5: Remote Rx Stat Change */ - PHY_B_IS_LRS_CHANGE = 1<<4, /* Bit 4: Local Rx Stat Change */ - PHY_B_IS_DUP_CHANGE = 1<<3, /* Bit 3: Duplex Mode Change */ - PHY_B_IS_LSP_CHANGE = 1<<2, /* Bit 2: Link Speed Change */ - PHY_B_IS_LST_CHANGE = 1<<1, /* Bit 1: Link Status Changed */ - PHY_B_IS_CRC_ER = 1<<0, /* Bit 0: CRC Error */ -}; -#define PHY_B_DEF_MSK \ - (~(PHY_B_IS_PSE | PHY_B_IS_AN_PR | PHY_B_IS_DUP_CHANGE | \ - PHY_B_IS_LSP_CHANGE | PHY_B_IS_LST_CHANGE)) - -/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */ -enum { - PHY_B_P_NO_PAUSE = 0<<10,/* Bit 11..10: no Pause Mode */ - PHY_B_P_SYM_MD = 1<<10, /* Bit 11..10: symmetric Pause Mode */ - PHY_B_P_ASYM_MD = 2<<10,/* Bit 11..10: asymmetric Pause Mode */ - PHY_B_P_BOTH_MD = 3<<10,/* Bit 11..10: both Pause Mode */ -}; -/* - * Resolved Duplex mode and Capabilities (Aux Status Summary Reg) - */ -enum { - PHY_B_RES_1000FD = 7<<8,/* Bit 10..8: 1000Base-T Full Dup. */ - PHY_B_RES_1000HD = 6<<8,/* Bit 10..8: 1000Base-T Half Dup. */ -}; - -/** Marvell-Specific */ -enum { - PHY_M_AN_NXT_PG = 1<<15, /* Request Next Page */ - PHY_M_AN_ACK = 1<<14, /* (ro) Acknowledge Received */ - PHY_M_AN_RF = 1<<13, /* Remote Fault */ - - PHY_M_AN_ASP = 1<<11, /* Asymmetric Pause */ - PHY_M_AN_PC = 1<<10, /* MAC Pause implemented */ - PHY_M_AN_100_T4 = 1<<9, /* Not cap. 100Base-T4 (always 0) */ - PHY_M_AN_100_FD = 1<<8, /* Advertise 100Base-TX Full Duplex */ - PHY_M_AN_100_HD = 1<<7, /* Advertise 100Base-TX Half Duplex */ - PHY_M_AN_10_FD = 1<<6, /* Advertise 10Base-TX Full Duplex */ - PHY_M_AN_10_HD = 1<<5, /* Advertise 10Base-TX Half Duplex */ - PHY_M_AN_SEL_MSK =0x1f<<4, /* Bit 4.. 0: Selector Field Mask */ -}; - -/* special defines for FIBER (88E1011S only) */ -enum { - PHY_M_AN_ASP_X = 1<<8, /* Asymmetric Pause */ - PHY_M_AN_PC_X = 1<<7, /* MAC Pause implemented */ - PHY_M_AN_1000X_AHD = 1<<6, /* Advertise 10000Base-X Half Duplex */ - PHY_M_AN_1000X_AFD = 1<<5, /* Advertise 10000Base-X Full Duplex */ -}; - -/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */ -enum { - PHY_M_P_NO_PAUSE_X = 0<<7,/* Bit 8.. 7: no Pause Mode */ - PHY_M_P_SYM_MD_X = 1<<7, /* Bit 8.. 7: symmetric Pause Mode */ - PHY_M_P_ASYM_MD_X = 2<<7,/* Bit 8.. 7: asymmetric Pause Mode */ - PHY_M_P_BOTH_MD_X = 3<<7,/* Bit 8.. 7: both Pause Mode */ -}; - -/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -enum { - PHY_M_1000C_TEST= 7<<13,/* Bit 15..13: Test Modes */ - PHY_M_1000C_MSE = 1<<12, /* Manual Master/Slave Enable */ - PHY_M_1000C_MSC = 1<<11, /* M/S Configuration (1=Master) */ - PHY_M_1000C_MPD = 1<<10, /* Multi-Port Device */ - PHY_M_1000C_AFD = 1<<9, /* Advertise Full Duplex */ - PHY_M_1000C_AHD = 1<<8, /* Advertise Half Duplex */ -}; - -/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/ -enum { - PHY_M_PC_TX_FFD_MSK = 3<<14,/* Bit 15..14: Tx FIFO Depth Mask */ - PHY_M_PC_RX_FFD_MSK = 3<<12,/* Bit 13..12: Rx FIFO Depth Mask */ - PHY_M_PC_ASS_CRS_TX = 1<<11, /* Assert CRS on Transmit */ - PHY_M_PC_FL_GOOD = 1<<10, /* Force Link Good */ - PHY_M_PC_EN_DET_MSK = 3<<8,/* Bit 9.. 8: Energy Detect Mask */ - PHY_M_PC_ENA_EXT_D = 1<<7, /* Enable Ext. Distance (10BT) */ - PHY_M_PC_MDIX_MSK = 3<<5,/* Bit 6.. 5: MDI/MDIX Config. Mask */ - PHY_M_PC_DIS_125CLK = 1<<4, /* Disable 125 CLK */ - PHY_M_PC_MAC_POW_UP = 1<<3, /* MAC Power up */ - PHY_M_PC_SQE_T_ENA = 1<<2, /* SQE Test Enabled */ - PHY_M_PC_POL_R_DIS = 1<<1, /* Polarity Reversal Disabled */ - PHY_M_PC_DIS_JABBER = 1<<0, /* Disable Jabber */ -}; - -enum { - PHY_M_PC_EN_DET = 2<<8, /* Energy Detect (Mode 1) */ - PHY_M_PC_EN_DET_PLUS = 3<<8, /* Energy Detect Plus (Mode 2) */ -}; - -enum { - PHY_M_PC_MAN_MDI = 0, /* 00 = Manual MDI configuration */ - PHY_M_PC_MAN_MDIX = 1, /* 01 = Manual MDIX configuration */ - PHY_M_PC_ENA_AUTO = 3, /* 11 = Enable Automatic Crossover */ -}; - -/* for 10/100 Fast Ethernet PHY (88E3082 only) */ -enum { - PHY_M_PC_ENA_DTE_DT = 1<<15, /* Enable Data Terminal Equ. (DTE) Detect */ - PHY_M_PC_ENA_ENE_DT = 1<<14, /* Enable Energy Detect (sense & pulse) */ - PHY_M_PC_DIS_NLP_CK = 1<<13, /* Disable Normal Link Puls (NLP) Check */ - PHY_M_PC_ENA_LIP_NP = 1<<12, /* Enable Link Partner Next Page Reg. */ - PHY_M_PC_DIS_NLP_GN = 1<<11, /* Disable Normal Link Puls Generation */ - - PHY_M_PC_DIS_SCRAMB = 1<<9, /* Disable Scrambler */ - PHY_M_PC_DIS_FEFI = 1<<8, /* Disable Far End Fault Indic. (FEFI) */ - - PHY_M_PC_SH_TP_SEL = 1<<6, /* Shielded Twisted Pair Select */ - PHY_M_PC_RX_FD_MSK = 3<<2,/* Bit 3.. 2: Rx FIFO Depth Mask */ -}; - -/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/ -enum { - PHY_M_PS_SPEED_MSK = 3<<14, /* Bit 15..14: Speed Mask */ - PHY_M_PS_SPEED_1000 = 1<<15, /* 10 = 1000 Mbps */ - PHY_M_PS_SPEED_100 = 1<<14, /* 01 = 100 Mbps */ - PHY_M_PS_SPEED_10 = 0, /* 00 = 10 Mbps */ - PHY_M_PS_FULL_DUP = 1<<13, /* Full Duplex */ - PHY_M_PS_PAGE_REC = 1<<12, /* Page Received */ - PHY_M_PS_SPDUP_RES = 1<<11, /* Speed & Duplex Resolved */ - PHY_M_PS_LINK_UP = 1<<10, /* Link Up */ - PHY_M_PS_CABLE_MSK = 7<<7, /* Bit 9.. 7: Cable Length Mask */ - PHY_M_PS_MDI_X_STAT = 1<<6, /* MDI Crossover Stat (1=MDIX) */ - PHY_M_PS_DOWNS_STAT = 1<<5, /* Downshift Status (1=downsh.) */ - PHY_M_PS_ENDET_STAT = 1<<4, /* Energy Detect Status (1=act) */ - PHY_M_PS_TX_P_EN = 1<<3, /* Tx Pause Enabled */ - PHY_M_PS_RX_P_EN = 1<<2, /* Rx Pause Enabled */ - PHY_M_PS_POL_REV = 1<<1, /* Polarity Reversed */ - PHY_M_PS_JABBER = 1<<0, /* Jabber */ -}; - -#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN) - -/* for 10/100 Fast Ethernet PHY (88E3082 only) */ -enum { - PHY_M_PS_DTE_DETECT = 1<<15, /* Data Terminal Equipment (DTE) Detected */ - PHY_M_PS_RES_SPEED = 1<<14, /* Resolved Speed (1=100 Mbps, 0=10 Mbps */ -}; - -enum { - PHY_M_IS_AN_ERROR = 1<<15, /* Auto-Negotiation Error */ - PHY_M_IS_LSP_CHANGE = 1<<14, /* Link Speed Changed */ - PHY_M_IS_DUP_CHANGE = 1<<13, /* Duplex Mode Changed */ - PHY_M_IS_AN_PR = 1<<12, /* Page Received */ - PHY_M_IS_AN_COMPL = 1<<11, /* Auto-Negotiation Completed */ - PHY_M_IS_LST_CHANGE = 1<<10, /* Link Status Changed */ - PHY_M_IS_SYMB_ERROR = 1<<9, /* Symbol Error */ - PHY_M_IS_FALSE_CARR = 1<<8, /* False Carrier */ - PHY_M_IS_FIFO_ERROR = 1<<7, /* FIFO Overflow/Underrun Error */ - PHY_M_IS_MDI_CHANGE = 1<<6, /* MDI Crossover Changed */ - PHY_M_IS_DOWNSH_DET = 1<<5, /* Downshift Detected */ - PHY_M_IS_END_CHANGE = 1<<4, /* Energy Detect Changed */ - - PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */ - PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */ - PHY_M_IS_JABBER = 1<<0, /* Jabber */ - - PHY_M_IS_DEF_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | - PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR, - - PHY_M_IS_AN_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL, -}; - -/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ -enum { - PHY_M_EC_ENA_BC_EXT = 1<<15, /* Enable Block Carr. Ext. (88E1111 only) */ - PHY_M_EC_ENA_LIN_LB = 1<<14, /* Enable Line Loopback (88E1111 only) */ - - PHY_M_EC_DIS_LINK_P = 1<<12, /* Disable Link Pulses (88E1111 only) */ - PHY_M_EC_M_DSC_MSK = 3<<10, /* Bit 11..10: Master Downshift Counter */ - /* (88E1011 only) */ - PHY_M_EC_S_DSC_MSK = 3<<8, /* Bit 9.. 8: Slave Downshift Counter */ - /* (88E1011 only) */ - PHY_M_EC_M_DSC_MSK2 = 7<<9, /* Bit 11.. 9: Master Downshift Counter */ - /* (88E1111 only) */ - PHY_M_EC_DOWN_S_ENA = 1<<8, /* Downshift Enable (88E1111 only) */ - /* !!! Errata in spec. (1 = disable) */ - PHY_M_EC_RX_TIM_CT = 1<<7, /* RGMII Rx Timing Control*/ - PHY_M_EC_MAC_S_MSK = 7<<4, /* Bit 6.. 4: Def. MAC interface speed */ - PHY_M_EC_FIB_AN_ENA = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */ - PHY_M_EC_DTE_D_ENA = 1<<2, /* DTE Detect Enable (88E1111 only) */ - PHY_M_EC_TX_TIM_CT = 1<<1, /* RGMII Tx Timing Control */ - PHY_M_EC_TRANS_DIS = 1<<0, /* Transmitter Disable (88E1111 only) */}; - -#define PHY_M_EC_M_DSC(x) ((u16)(x)<<10) /* 00=1x; 01=2x; 10=3x; 11=4x */ -#define PHY_M_EC_S_DSC(x) ((u16)(x)<<8) /* 00=dis; 01=1x; 10=2x; 11=3x */ -#define PHY_M_EC_MAC_S(x) ((u16)(x)<<4) /* 01X=0; 110=2.5; 111=25 (MHz) */ - -#define PHY_M_EC_M_DSC_2(x) ((u16)(x)<<9) /* 000=1x; 001=2x; 010=3x; 011=4x */ - /* 100=5x; 101=6x; 110=7x; 111=8x */ -enum { - MAC_TX_CLK_0_MHZ = 2, - MAC_TX_CLK_2_5_MHZ = 6, - MAC_TX_CLK_25_MHZ = 7, -}; - -/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/ -enum { - PHY_M_LEDC_DIS_LED = 1<<15, /* Disable LED */ - PHY_M_LEDC_PULS_MSK = 7<<12,/* Bit 14..12: Pulse Stretch Mask */ - PHY_M_LEDC_F_INT = 1<<11, /* Force Interrupt */ - PHY_M_LEDC_BL_R_MSK = 7<<8,/* Bit 10.. 8: Blink Rate Mask */ - PHY_M_LEDC_DP_C_LSB = 1<<7, /* Duplex Control (LSB, 88E1111 only) */ - PHY_M_LEDC_TX_C_LSB = 1<<6, /* Tx Control (LSB, 88E1111 only) */ - PHY_M_LEDC_LK_C_MSK = 7<<3,/* Bit 5.. 3: Link Control Mask */ - /* (88E1111 only) */ -}; -#define PHY_M_LED_PULS_DUR(x) (((u16)(x)<<12) & PHY_M_LEDC_PULS_MSK) -#define PHY_M_LED_BLINK_RT(x) (((u16)(x)<<8) & PHY_M_LEDC_BL_R_MSK) - -enum { - PHY_M_LEDC_LINK_MSK = 3<<3, /* Bit 4.. 3: Link Control Mask */ - /* (88E1011 only) */ - PHY_M_LEDC_DP_CTRL = 1<<2, /* Duplex Control */ - PHY_M_LEDC_DP_C_MSB = 1<<2, /* Duplex Control (MSB, 88E1111 only) */ - PHY_M_LEDC_RX_CTRL = 1<<1, /* Rx Activity / Link */ - PHY_M_LEDC_TX_CTRL = 1<<0, /* Tx Activity / Link */ - PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */ -}; - -enum { - PULS_NO_STR = 0, /* no pulse stretching */ - PULS_21MS = 1, /* 21 ms to 42 ms */ - PULS_42MS = 2, /* 42 ms to 84 ms */ - PULS_84MS = 3, /* 84 ms to 170 ms */ - PULS_170MS = 4, /* 170 ms to 340 ms */ - PULS_340MS = 5, /* 340 ms to 670 ms */ - PULS_670MS = 6, /* 670 ms to 1.3 s */ - PULS_1300MS = 7, /* 1.3 s to 2.7 s */ -}; - - -enum { - BLINK_42MS = 0, /* 42 ms */ - BLINK_84MS = 1, /* 84 ms */ - BLINK_170MS = 2, /* 170 ms */ - BLINK_340MS = 3, /* 340 ms */ - BLINK_670MS = 4, /* 670 ms */ -}; - -/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/ -#define PHY_M_LED_MO_SGMII(x) ((x)<<14) /* Bit 15..14: SGMII AN Timer */ - /* Bit 13..12: reserved */ -#define PHY_M_LED_MO_DUP(x) ((x)<<10) /* Bit 11..10: Duplex */ -#define PHY_M_LED_MO_10(x) ((x)<<8) /* Bit 9.. 8: Link 10 */ -#define PHY_M_LED_MO_100(x) ((x)<<6) /* Bit 7.. 6: Link 100 */ -#define PHY_M_LED_MO_1000(x) ((x)<<4) /* Bit 5.. 4: Link 1000 */ -#define PHY_M_LED_MO_RX(x) ((x)<<2) /* Bit 3.. 2: Rx */ -#define PHY_M_LED_MO_TX(x) ((x)<<0) /* Bit 1.. 0: Tx */ - -enum { - MO_LED_NORM = 0, - MO_LED_BLINK = 1, - MO_LED_OFF = 2, - MO_LED_ON = 3, -}; - -/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/ -enum { - PHY_M_EC2_FI_IMPED = 1<<6, /* Fiber Input Impedance */ - PHY_M_EC2_FO_IMPED = 1<<5, /* Fiber Output Impedance */ - PHY_M_EC2_FO_M_CLK = 1<<4, /* Fiber Mode Clock Enable */ - PHY_M_EC2_FO_BOOST = 1<<3, /* Fiber Output Boost */ - PHY_M_EC2_FO_AM_MSK = 7, /* Bit 2.. 0: Fiber Output Amplitude */ -}; - -/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/ -enum { - PHY_M_FC_AUTO_SEL = 1<<15, /* Fiber/Copper Auto Sel. Dis. */ - PHY_M_FC_AN_REG_ACC = 1<<14, /* Fiber/Copper AN Reg. Access */ - PHY_M_FC_RESOLUTION = 1<<13, /* Fiber/Copper Resolution */ - PHY_M_SER_IF_AN_BP = 1<<12, /* Ser. IF AN Bypass Enable */ - PHY_M_SER_IF_BP_ST = 1<<11, /* Ser. IF AN Bypass Status */ - PHY_M_IRQ_POLARITY = 1<<10, /* IRQ polarity */ - PHY_M_DIS_AUT_MED = 1<<9, /* Disable Aut. Medium Reg. Selection */ - /* (88E1111 only) */ - /* Bit 9.. 4: reserved (88E1011 only) */ - PHY_M_UNDOC1 = 1<<7, /* undocumented bit !! */ - PHY_M_DTE_POW_STAT = 1<<4, /* DTE Power Status (88E1111 only) */ - PHY_M_MODE_MASK = 0xf, /* Bit 3.. 0: copy of HWCFG MODE[3:0] */ -}; - -/***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/ -enum { - PHY_M_CABD_ENA_TEST = 1<<15, /* Enable Test (Page 0) */ - PHY_M_CABD_DIS_WAIT = 1<<15, /* Disable Waiting Period (Page 1) */ - /* (88E1111 only) */ - PHY_M_CABD_STAT_MSK = 3<<13, /* Bit 14..13: Status Mask */ - PHY_M_CABD_AMPL_MSK = 0x1f<<8, /* Bit 12.. 8: Amplitude Mask */ - /* (88E1111 only) */ - PHY_M_CABD_DIST_MSK = 0xff, /* Bit 7.. 0: Distance Mask */ -}; - -/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */ -enum { - CABD_STAT_NORMAL= 0, - CABD_STAT_SHORT = 1, - CABD_STAT_OPEN = 2, - CABD_STAT_FAIL = 3, -}; - -/* for 10/100 Fast Ethernet PHY (88E3082 only) */ -/***** PHY_MARV_FE_LED_PAR 16 bit r/w LED Parallel Select Reg. *****/ - /* Bit 15..12: reserved (used internally) */ -enum { - PHY_M_FELP_LED2_MSK = 0xf<<8, /* Bit 11.. 8: LED2 Mask (LINK) */ - PHY_M_FELP_LED1_MSK = 0xf<<4, /* Bit 7.. 4: LED1 Mask (ACT) */ - PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */ -}; - -#define PHY_M_FELP_LED2_CTRL(x) (((x)<<8) & PHY_M_FELP_LED2_MSK) -#define PHY_M_FELP_LED1_CTRL(x) (((x)<<4) & PHY_M_FELP_LED1_MSK) -#define PHY_M_FELP_LED0_CTRL(x) (((x)<<0) & PHY_M_FELP_LED0_MSK) - -enum { - LED_PAR_CTRL_COLX = 0x00, - LED_PAR_CTRL_ERROR = 0x01, - LED_PAR_CTRL_DUPLEX = 0x02, - LED_PAR_CTRL_DP_COL = 0x03, - LED_PAR_CTRL_SPEED = 0x04, - LED_PAR_CTRL_LINK = 0x05, - LED_PAR_CTRL_TX = 0x06, - LED_PAR_CTRL_RX = 0x07, - LED_PAR_CTRL_ACT = 0x08, - LED_PAR_CTRL_LNK_RX = 0x09, - LED_PAR_CTRL_LNK_AC = 0x0a, - LED_PAR_CTRL_ACT_BL = 0x0b, - LED_PAR_CTRL_TX_BL = 0x0c, - LED_PAR_CTRL_RX_BL = 0x0d, - LED_PAR_CTRL_COL_BL = 0x0e, - LED_PAR_CTRL_INACT = 0x0f -}; - -/*****,PHY_MARV_FE_SPEC_2 16 bit r/w Specific Control Reg. 2 *****/ -enum { - PHY_M_FESC_DIS_WAIT = 1<<2, /* Disable TDR Waiting Period */ - PHY_M_FESC_ENA_MCLK = 1<<1, /* Enable MAC Rx Clock in sleep mode */ - PHY_M_FESC_SEL_CL_A = 1<<0, /* Select Class A driver (100B-TX) */ -}; - - -/***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/ -enum { - PHY_M_LEDC_LOS_MSK = 0xf<<12, /* Bit 15..12: LOS LED Ctrl. Mask */ - PHY_M_LEDC_INIT_MSK = 0xf<<8, /* Bit 11.. 8: INIT LED Ctrl. Mask */ - PHY_M_LEDC_STA1_MSK = 0xf<<4, /* Bit 7.. 4: STAT1 LED Ctrl. Mask */ - PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */ -}; - -#define PHY_M_LEDC_LOS_CTRL(x) (((x)<<12) & PHY_M_LEDC_LOS_MSK) -#define PHY_M_LEDC_INIT_CTRL(x) (((x)<<8) & PHY_M_LEDC_INIT_MSK) -#define PHY_M_LEDC_STA1_CTRL(x) (((x)<<4) & PHY_M_LEDC_STA1_MSK) -#define PHY_M_LEDC_STA0_CTRL(x) (((x)<<0) & PHY_M_LEDC_STA0_MSK) - -/* GMAC registers */ -/* Port Registers */ -enum { - GM_GP_STAT = 0x0000, /* 16 bit r/o General Purpose Status */ - GM_GP_CTRL = 0x0004, /* 16 bit r/w General Purpose Control */ - GM_TX_CTRL = 0x0008, /* 16 bit r/w Transmit Control Reg. */ - GM_RX_CTRL = 0x000c, /* 16 bit r/w Receive Control Reg. */ - GM_TX_FLOW_CTRL = 0x0010, /* 16 bit r/w Transmit Flow-Control */ - GM_TX_PARAM = 0x0014, /* 16 bit r/w Transmit Parameter Reg. */ - GM_SERIAL_MODE = 0x0018, /* 16 bit r/w Serial Mode Register */ -/* Source Address Registers */ - GM_SRC_ADDR_1L = 0x001c, /* 16 bit r/w Source Address 1 (low) */ - GM_SRC_ADDR_1M = 0x0020, /* 16 bit r/w Source Address 1 (middle) */ - GM_SRC_ADDR_1H = 0x0024, /* 16 bit r/w Source Address 1 (high) */ - GM_SRC_ADDR_2L = 0x0028, /* 16 bit r/w Source Address 2 (low) */ - GM_SRC_ADDR_2M = 0x002c, /* 16 bit r/w Source Address 2 (middle) */ - GM_SRC_ADDR_2H = 0x0030, /* 16 bit r/w Source Address 2 (high) */ - -/* Multicast Address Hash Registers */ - GM_MC_ADDR_H1 = 0x0034, /* 16 bit r/w Multicast Address Hash 1 */ - GM_MC_ADDR_H2 = 0x0038, /* 16 bit r/w Multicast Address Hash 2 */ - GM_MC_ADDR_H3 = 0x003c, /* 16 bit r/w Multicast Address Hash 3 */ - GM_MC_ADDR_H4 = 0x0040, /* 16 bit r/w Multicast Address Hash 4 */ - -/* Interrupt Source Registers */ - GM_TX_IRQ_SRC = 0x0044, /* 16 bit r/o Tx Overflow IRQ Source */ - GM_RX_IRQ_SRC = 0x0048, /* 16 bit r/o Rx Overflow IRQ Source */ - GM_TR_IRQ_SRC = 0x004c, /* 16 bit r/o Tx/Rx Over. IRQ Source */ - -/* Interrupt Mask Registers */ - GM_TX_IRQ_MSK = 0x0050, /* 16 bit r/w Tx Overflow IRQ Mask */ - GM_RX_IRQ_MSK = 0x0054, /* 16 bit r/w Rx Overflow IRQ Mask */ - GM_TR_IRQ_MSK = 0x0058, /* 16 bit r/w Tx/Rx Over. IRQ Mask */ - -/* Serial Management Interface (SMI) Registers */ - GM_SMI_CTRL = 0x0080, /* 16 bit r/w SMI Control Register */ - GM_SMI_DATA = 0x0084, /* 16 bit r/w SMI Data Register */ - GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */ -}; - -/* MIB Counters */ -#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */ -#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */ - -/* - * MIB Counters base address definitions (low word) - - * use offset 4 for access to high word (32 bit r/o) - */ -enum { - GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */ - GM_RXF_BC_OK = GM_MIB_CNT_BASE + 8, /* Broadcast Frames Received OK */ - GM_RXF_MPAUSE = GM_MIB_CNT_BASE + 16, /* Pause MAC Ctrl Frames Received */ - GM_RXF_MC_OK = GM_MIB_CNT_BASE + 24, /* Multicast Frames Received OK */ - GM_RXF_FCS_ERR = GM_MIB_CNT_BASE + 32, /* Rx Frame Check Seq. Error */ - /* GM_MIB_CNT_BASE + 40: reserved */ - GM_RXO_OK_LO = GM_MIB_CNT_BASE + 48, /* Octets Received OK Low */ - GM_RXO_OK_HI = GM_MIB_CNT_BASE + 56, /* Octets Received OK High */ - GM_RXO_ERR_LO = GM_MIB_CNT_BASE + 64, /* Octets Received Invalid Low */ - GM_RXO_ERR_HI = GM_MIB_CNT_BASE + 72, /* Octets Received Invalid High */ - GM_RXF_SHT = GM_MIB_CNT_BASE + 80, /* Frames <64 Byte Received OK */ - GM_RXE_FRAG = GM_MIB_CNT_BASE + 88, /* Frames <64 Byte Received with FCS Err */ - GM_RXF_64B = GM_MIB_CNT_BASE + 96, /* 64 Byte Rx Frame */ - GM_RXF_127B = GM_MIB_CNT_BASE + 104, /* 65-127 Byte Rx Frame */ - GM_RXF_255B = GM_MIB_CNT_BASE + 112, /* 128-255 Byte Rx Frame */ - GM_RXF_511B = GM_MIB_CNT_BASE + 120, /* 256-511 Byte Rx Frame */ - GM_RXF_1023B = GM_MIB_CNT_BASE + 128, /* 512-1023 Byte Rx Frame */ - GM_RXF_1518B = GM_MIB_CNT_BASE + 136, /* 1024-1518 Byte Rx Frame */ - GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144, /* 1519-MaxSize Byte Rx Frame */ - GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152, /* Rx Frame too Long Error */ - GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160, /* Rx Jabber Packet Frame */ - /* GM_MIB_CNT_BASE + 168: reserved */ - GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176, /* Rx FIFO overflow Event */ - /* GM_MIB_CNT_BASE + 184: reserved */ - GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192, /* Unicast Frames Xmitted OK */ - GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200, /* Broadcast Frames Xmitted OK */ - GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208, /* Pause MAC Ctrl Frames Xmitted */ - GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216, /* Multicast Frames Xmitted OK */ - GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224, /* Octets Transmitted OK Low */ - GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232, /* Octets Transmitted OK High */ - GM_TXF_64B = GM_MIB_CNT_BASE + 240, /* 64 Byte Tx Frame */ - GM_TXF_127B = GM_MIB_CNT_BASE + 248, /* 65-127 Byte Tx Frame */ - GM_TXF_255B = GM_MIB_CNT_BASE + 256, /* 128-255 Byte Tx Frame */ - GM_TXF_511B = GM_MIB_CNT_BASE + 264, /* 256-511 Byte Tx Frame */ - GM_TXF_1023B = GM_MIB_CNT_BASE + 272, /* 512-1023 Byte Tx Frame */ - GM_TXF_1518B = GM_MIB_CNT_BASE + 280, /* 1024-1518 Byte Tx Frame */ - GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288, /* 1519-MaxSize Byte Tx Frame */ - - GM_TXF_COL = GM_MIB_CNT_BASE + 304, /* Tx Collision */ - GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312, /* Tx Late Collision */ - GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320, /* Tx aborted due to Exces. Col. */ - GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328, /* Tx Multiple Collision */ - GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336, /* Tx Single Collision */ - GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344, /* Tx FIFO Underrun Event */ -}; - -/* GMAC Bit Definitions */ -/* GM_GP_STAT 16 bit r/o General Purpose Status Register */ -enum { - GM_GPSR_SPEED = 1<<15, /* Bit 15: Port Speed (1 = 100 Mbps) */ - GM_GPSR_DUPLEX = 1<<14, /* Bit 14: Duplex Mode (1 = Full) */ - GM_GPSR_FC_TX_DIS = 1<<13, /* Bit 13: Tx Flow-Control Mode Disabled */ - GM_GPSR_LINK_UP = 1<<12, /* Bit 12: Link Up Status */ - GM_GPSR_PAUSE = 1<<11, /* Bit 11: Pause State */ - GM_GPSR_TX_ACTIVE = 1<<10, /* Bit 10: Tx in Progress */ - GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occurred */ - GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occurred */ - - GM_GPSR_PHY_ST_CH = 1<<5, /* Bit 5: PHY Status Change */ - GM_GPSR_GIG_SPEED = 1<<4, /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */ - GM_GPSR_PART_MODE = 1<<3, /* Bit 3: Partition mode */ - GM_GPSR_FC_RX_DIS = 1<<2, /* Bit 2: Rx Flow-Control Mode Disabled */ - GM_GPSR_PROM_EN = 1<<1, /* Bit 1: Promiscuous Mode Enabled */ -}; - -/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */ -enum { - GM_GPCR_PROM_ENA = 1<<14, /* Bit 14: Enable Promiscuous Mode */ - GM_GPCR_FC_TX_DIS = 1<<13, /* Bit 13: Disable Tx Flow-Control Mode */ - GM_GPCR_TX_ENA = 1<<12, /* Bit 12: Enable Transmit */ - GM_GPCR_RX_ENA = 1<<11, /* Bit 11: Enable Receive */ - GM_GPCR_BURST_ENA = 1<<10, /* Bit 10: Enable Burst Mode */ - GM_GPCR_LOOP_ENA = 1<<9, /* Bit 9: Enable MAC Loopback Mode */ - GM_GPCR_PART_ENA = 1<<8, /* Bit 8: Enable Partition Mode */ - GM_GPCR_GIGS_ENA = 1<<7, /* Bit 7: Gigabit Speed (1000 Mbps) */ - GM_GPCR_FL_PASS = 1<<6, /* Bit 6: Force Link Pass */ - GM_GPCR_DUP_FULL = 1<<5, /* Bit 5: Full Duplex Mode */ - GM_GPCR_FC_RX_DIS = 1<<4, /* Bit 4: Disable Rx Flow-Control Mode */ - GM_GPCR_SPEED_100 = 1<<3, /* Bit 3: Port Speed 100 Mbps */ - GM_GPCR_AU_DUP_DIS = 1<<2, /* Bit 2: Disable Auto-Update Duplex */ - GM_GPCR_AU_FCT_DIS = 1<<1, /* Bit 1: Disable Auto-Update Flow-C. */ - GM_GPCR_AU_SPD_DIS = 1<<0, /* Bit 0: Disable Auto-Update Speed */ -}; - -#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100) -#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS|GM_GPCR_AU_SPD_DIS) - -/* GM_TX_CTRL 16 bit r/w Transmit Control Register */ -enum { - GM_TXCR_FORCE_JAM = 1<<15, /* Bit 15: Force Jam / Flow-Control */ - GM_TXCR_CRC_DIS = 1<<14, /* Bit 14: Disable insertion of CRC */ - GM_TXCR_PAD_DIS = 1<<13, /* Bit 13: Disable padding of packets */ - GM_TXCR_COL_THR_MSK = 7<<10, /* Bit 12..10: Collision Threshold */ -}; - -#define TX_COL_THR(x) (((x)<<10) & GM_TXCR_COL_THR_MSK) -#define TX_COL_DEF 0x04 /* late collision after 64 byte */ - -/* GM_RX_CTRL 16 bit r/w Receive Control Register */ -enum { - GM_RXCR_UCF_ENA = 1<<15, /* Bit 15: Enable Unicast filtering */ - GM_RXCR_MCF_ENA = 1<<14, /* Bit 14: Enable Multicast filtering */ - GM_RXCR_CRC_DIS = 1<<13, /* Bit 13: Remove 4-byte CRC */ - GM_RXCR_PASS_FC = 1<<12, /* Bit 12: Pass FC packets to FIFO */ -}; - -/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */ -enum { - GM_TXPA_JAMLEN_MSK = 0x03<<14, /* Bit 15..14: Jam Length */ - GM_TXPA_JAMIPG_MSK = 0x1f<<9, /* Bit 13..9: Jam IPG */ - GM_TXPA_JAMDAT_MSK = 0x1f<<4, /* Bit 8..4: IPG Jam to Data */ - - TX_JAM_LEN_DEF = 0x03, - TX_JAM_IPG_DEF = 0x0b, - TX_IPG_JAM_DEF = 0x1c, -}; - -#define TX_JAM_LEN_VAL(x) (((x)<<14) & GM_TXPA_JAMLEN_MSK) -#define TX_JAM_IPG_VAL(x) (((x)<<9) & GM_TXPA_JAMIPG_MSK) -#define TX_IPG_JAM_DATA(x) (((x)<<4) & GM_TXPA_JAMDAT_MSK) - - -/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */ -enum { - GM_SMOD_DATABL_MSK = 0x1f<<11, /* Bit 15..11: Data Blinder (r/o) */ - GM_SMOD_LIMIT_4 = 1<<10, /* Bit 10: 4 consecutive Tx trials */ - GM_SMOD_VLAN_ENA = 1<<9, /* Bit 9: Enable VLAN (Max. Frame Len) */ - GM_SMOD_JUMBO_ENA = 1<<8, /* Bit 8: Enable Jumbo (Max. Frame Len) */ - GM_SMOD_IPG_MSK = 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */ -}; - -#define DATA_BLIND_VAL(x) (((x)<<11) & GM_SMOD_DATABL_MSK) -#define DATA_BLIND_DEF 0x04 - -#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK) -#define IPG_DATA_DEF 0x1e - -/* GM_SMI_CTRL 16 bit r/w SMI Control Register */ -enum { - GM_SMI_CT_PHY_A_MSK = 0x1f<<11, /* Bit 15..11: PHY Device Address */ - GM_SMI_CT_REG_A_MSK = 0x1f<<6, /* Bit 10.. 6: PHY Register Address */ - GM_SMI_CT_OP_RD = 1<<5, /* Bit 5: OpCode Read (0=Write)*/ - GM_SMI_CT_RD_VAL = 1<<4, /* Bit 4: Read Valid (Read completed) */ - GM_SMI_CT_BUSY = 1<<3, /* Bit 3: Busy (Operation in progress) */ -}; - -#define GM_SMI_CT_PHY_AD(x) (((x)<<11) & GM_SMI_CT_PHY_A_MSK) -#define GM_SMI_CT_REG_AD(x) (((x)<<6) & GM_SMI_CT_REG_A_MSK) - -/* GM_PHY_ADDR 16 bit r/w GPHY Address Register */ -enum { - GM_PAR_MIB_CLR = 1<<5, /* Bit 5: Set MIB Clear Counter Mode */ - GM_PAR_MIB_TST = 1<<4, /* Bit 4: MIB Load Counter (Test Mode) */ -}; - -/* Receive Frame Status Encoding */ -enum { - GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */ - GMR_FS_LEN_SHIFT = 16, - GMR_FS_VLAN = 1<<13, /* Bit 13: VLAN Packet */ - GMR_FS_JABBER = 1<<12, /* Bit 12: Jabber Packet */ - GMR_FS_UN_SIZE = 1<<11, /* Bit 11: Undersize Packet */ - GMR_FS_MC = 1<<10, /* Bit 10: Multicast Packet */ - GMR_FS_BC = 1<<9, /* Bit 9: Broadcast Packet */ - GMR_FS_RX_OK = 1<<8, /* Bit 8: Receive OK (Good Packet) */ - GMR_FS_GOOD_FC = 1<<7, /* Bit 7: Good Flow-Control Packet */ - GMR_FS_BAD_FC = 1<<6, /* Bit 6: Bad Flow-Control Packet */ - GMR_FS_MII_ERR = 1<<5, /* Bit 5: MII Error */ - GMR_FS_LONG_ERR = 1<<4, /* Bit 4: Too Long Packet */ - GMR_FS_FRAGMENT = 1<<3, /* Bit 3: Fragment */ - - GMR_FS_CRC_ERR = 1<<1, /* Bit 1: CRC Error */ - GMR_FS_RX_FF_OV = 1<<0, /* Bit 0: Rx FIFO Overflow */ - -/* - * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR) - */ - GMR_FS_ANY_ERR = GMR_FS_CRC_ERR | GMR_FS_LONG_ERR | - GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC | - GMR_FS_JABBER, -/* Rx GMAC FIFO Flush Mask (default) */ - RX_FF_FL_DEF_MSK = GMR_FS_CRC_ERR | GMR_FS_RX_FF_OV |GMR_FS_MII_ERR | - GMR_FS_BAD_FC | GMR_FS_UN_SIZE | GMR_FS_JABBER, -}; - -/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */ -enum { - GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */ - GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */ - GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */ - - GMF_RP_TST_ON = 1<<10, /* Read Pointer Test On */ - GMF_RP_TST_OFF = 1<<9, /* Read Pointer Test Off */ - GMF_RP_STEP = 1<<8, /* Read Pointer Step/Increment */ - GMF_RX_F_FL_ON = 1<<7, /* Rx FIFO Flush Mode On */ - GMF_RX_F_FL_OFF = 1<<6, /* Rx FIFO Flush Mode Off */ - GMF_CLI_RX_FO = 1<<5, /* Clear IRQ Rx FIFO Overrun */ - GMF_CLI_RX_FC = 1<<4, /* Clear IRQ Rx Frame Complete */ - GMF_OPER_ON = 1<<3, /* Operational Mode On */ - GMF_OPER_OFF = 1<<2, /* Operational Mode Off */ - GMF_RST_CLR = 1<<1, /* Clear GMAC FIFO Reset */ - GMF_RST_SET = 1<<0, /* Set GMAC FIFO Reset */ - - RX_GMF_FL_THR_DEF = 0xa, /* flush threshold (default) */ -}; - - -/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ -enum { - GMF_WSP_TST_ON = 1<<18, /* Write Shadow Pointer Test On */ - GMF_WSP_TST_OFF = 1<<17, /* Write Shadow Pointer Test Off */ - GMF_WSP_STEP = 1<<16, /* Write Shadow Pointer Step/Increment */ - - GMF_CLI_TX_FU = 1<<6, /* Clear IRQ Tx FIFO Underrun */ - GMF_CLI_TX_FC = 1<<5, /* Clear IRQ Tx Frame Complete */ - GMF_CLI_TX_PE = 1<<4, /* Clear IRQ Tx Parity Error */ -}; - -/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */ -enum { - GMT_ST_START = 1<<2, /* Start Time Stamp Timer */ - GMT_ST_STOP = 1<<1, /* Stop Time Stamp Timer */ - GMT_ST_CLR_IRQ = 1<<0, /* Clear Time Stamp Timer IRQ */ -}; - -/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */ -enum { - GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */ - GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */ - GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */ - GMC_F_LOOPB_OFF = 1<<4, /* FIFO Loopback Off */ - GMC_PAUSE_ON = 1<<3, /* Pause On */ - GMC_PAUSE_OFF = 1<<2, /* Pause Off */ - GMC_RST_CLR = 1<<1, /* Clear GMAC Reset */ - GMC_RST_SET = 1<<0, /* Set GMAC Reset */ -}; - -/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */ -enum { - GPC_SEL_BDT = 1<<28, /* Select Bi-Dir. Transfer for MDC/MDIO */ - GPC_INT_POL_HI = 1<<27, /* IRQ Polarity is Active HIGH */ - GPC_75_OHM = 1<<26, /* Use 75 Ohm Termination instead of 50 */ - GPC_DIS_FC = 1<<25, /* Disable Automatic Fiber/Copper Detection */ - GPC_DIS_SLEEP = 1<<24, /* Disable Energy Detect */ - GPC_HWCFG_M_3 = 1<<23, /* HWCFG_MODE[3] */ - GPC_HWCFG_M_2 = 1<<22, /* HWCFG_MODE[2] */ - GPC_HWCFG_M_1 = 1<<21, /* HWCFG_MODE[1] */ - GPC_HWCFG_M_0 = 1<<20, /* HWCFG_MODE[0] */ - GPC_ANEG_0 = 1<<19, /* ANEG[0] */ - GPC_ENA_XC = 1<<18, /* Enable MDI crossover */ - GPC_DIS_125 = 1<<17, /* Disable 125 MHz clock */ - GPC_ANEG_3 = 1<<16, /* ANEG[3] */ - GPC_ANEG_2 = 1<<15, /* ANEG[2] */ - GPC_ANEG_1 = 1<<14, /* ANEG[1] */ - GPC_ENA_PAUSE = 1<<13, /* Enable Pause (SYM_OR_REM) */ - GPC_PHYADDR_4 = 1<<12, /* Bit 4 of Phy Addr */ - GPC_PHYADDR_3 = 1<<11, /* Bit 3 of Phy Addr */ - GPC_PHYADDR_2 = 1<<10, /* Bit 2 of Phy Addr */ - GPC_PHYADDR_1 = 1<<9, /* Bit 1 of Phy Addr */ - GPC_PHYADDR_0 = 1<<8, /* Bit 0 of Phy Addr */ - /* Bits 7..2: reserved */ - GPC_RST_CLR = 1<<1, /* Clear GPHY Reset */ - GPC_RST_SET = 1<<0, /* Set GPHY Reset */ -}; - -#define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3|GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0) -#define GPC_HWCFG_GMII_FIB (GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0) -#define GPC_ANEG_ADV_ALL_M (GPC_ANEG_3 | GPC_ANEG_2 | GPC_ANEG_1 | GPC_ANEG_0) - -/* forced speed and duplex mode (don't mix with other ANEG bits) */ -#define GPC_FRC10MBIT_HALF 0 -#define GPC_FRC10MBIT_FULL GPC_ANEG_0 -#define GPC_FRC100MBIT_HALF GPC_ANEG_1 -#define GPC_FRC100MBIT_FULL (GPC_ANEG_0 | GPC_ANEG_1) - -/* auto-negotiation with limited advertised speeds */ -/* mix only with master/slave settings (for copper) */ -#define GPC_ADV_1000_HALF GPC_ANEG_2 -#define GPC_ADV_1000_FULL GPC_ANEG_3 -#define GPC_ADV_ALL (GPC_ANEG_2 | GPC_ANEG_3) - -/* master/slave settings */ -/* only for copper with 1000 Mbps */ -#define GPC_FORCE_MASTER 0 -#define GPC_FORCE_SLAVE GPC_ANEG_0 -#define GPC_PREF_MASTER GPC_ANEG_1 -#define GPC_PREF_SLAVE (GPC_ANEG_1 | GPC_ANEG_0) - -/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */ -/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */ -enum { - GM_IS_TX_CO_OV = 1<<5, /* Transmit Counter Overflow IRQ */ - GM_IS_RX_CO_OV = 1<<4, /* Receive Counter Overflow IRQ */ - GM_IS_TX_FF_UR = 1<<3, /* Transmit FIFO Underrun */ - GM_IS_TX_COMPL = 1<<2, /* Frame Transmission Complete */ - GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */ - GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */ - -#define GMAC_DEF_MSK (GM_IS_RX_FF_OR | GM_IS_TX_FF_UR) - -/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ - /* Bits 15.. 2: reserved */ - GMLC_RST_CLR = 1<<1, /* Clear GMAC Link Reset */ - GMLC_RST_SET = 1<<0, /* Set GMAC Link Reset */ - - -/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */ - WOL_CTL_LINK_CHG_OCC = 1<<15, - WOL_CTL_MAGIC_PKT_OCC = 1<<14, - WOL_CTL_PATTERN_OCC = 1<<13, - WOL_CTL_CLEAR_RESULT = 1<<12, - WOL_CTL_ENA_PME_ON_LINK_CHG = 1<<11, - WOL_CTL_DIS_PME_ON_LINK_CHG = 1<<10, - WOL_CTL_ENA_PME_ON_MAGIC_PKT = 1<<9, - WOL_CTL_DIS_PME_ON_MAGIC_PKT = 1<<8, - WOL_CTL_ENA_PME_ON_PATTERN = 1<<7, - WOL_CTL_DIS_PME_ON_PATTERN = 1<<6, - WOL_CTL_ENA_LINK_CHG_UNIT = 1<<5, - WOL_CTL_DIS_LINK_CHG_UNIT = 1<<4, - WOL_CTL_ENA_MAGIC_PKT_UNIT = 1<<3, - WOL_CTL_DIS_MAGIC_PKT_UNIT = 1<<2, - WOL_CTL_ENA_PATTERN_UNIT = 1<<1, - WOL_CTL_DIS_PATTERN_UNIT = 1<<0, -}; - -#define WOL_CTL_DEFAULT \ - (WOL_CTL_DIS_PME_ON_LINK_CHG | \ - WOL_CTL_DIS_PME_ON_PATTERN | \ - WOL_CTL_DIS_PME_ON_MAGIC_PKT | \ - WOL_CTL_DIS_LINK_CHG_UNIT | \ - WOL_CTL_DIS_PATTERN_UNIT | \ - WOL_CTL_DIS_MAGIC_PKT_UNIT) - -/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */ -#define WOL_CTL_PATT_ENA(x) (1 << (x)) - - -/* XMAC II registers */ -enum { - XM_MMU_CMD = 0x0000, /* 16 bit r/w MMU Command Register */ - XM_POFF = 0x0008, /* 32 bit r/w Packet Offset Register */ - XM_BURST = 0x000c, /* 32 bit r/w Burst Register for half duplex*/ - XM_1L_VLAN_TAG = 0x0010, /* 16 bit r/w One Level VLAN Tag ID */ - XM_2L_VLAN_TAG = 0x0014, /* 16 bit r/w Two Level VLAN Tag ID */ - XM_TX_CMD = 0x0020, /* 16 bit r/w Transmit Command Register */ - XM_TX_RT_LIM = 0x0024, /* 16 bit r/w Transmit Retry Limit Register */ - XM_TX_STIME = 0x0028, /* 16 bit r/w Transmit Slottime Register */ - XM_TX_IPG = 0x002c, /* 16 bit r/w Transmit Inter Packet Gap */ - XM_RX_CMD = 0x0030, /* 16 bit r/w Receive Command Register */ - XM_PHY_ADDR = 0x0034, /* 16 bit r/w PHY Address Register */ - XM_PHY_DATA = 0x0038, /* 16 bit r/w PHY Data Register */ - XM_GP_PORT = 0x0040, /* 32 bit r/w General Purpose Port Register */ - XM_IMSK = 0x0044, /* 16 bit r/w Interrupt Mask Register */ - XM_ISRC = 0x0048, /* 16 bit r/o Interrupt Status Register */ - XM_HW_CFG = 0x004c, /* 16 bit r/w Hardware Config Register */ - XM_TX_LO_WM = 0x0060, /* 16 bit r/w Tx FIFO Low Water Mark */ - XM_TX_HI_WM = 0x0062, /* 16 bit r/w Tx FIFO High Water Mark */ - XM_TX_THR = 0x0064, /* 16 bit r/w Tx Request Threshold */ - XM_HT_THR = 0x0066, /* 16 bit r/w Host Request Threshold */ - XM_PAUSE_DA = 0x0068, /* NA reg r/w Pause Destination Address */ - XM_CTL_PARA = 0x0070, /* 32 bit r/w Control Parameter Register */ - XM_MAC_OPCODE = 0x0074, /* 16 bit r/w Opcode for MAC control frames */ - XM_MAC_PTIME = 0x0076, /* 16 bit r/w Pause time for MAC ctrl frames*/ - XM_TX_STAT = 0x0078, /* 32 bit r/o Tx Status LIFO Register */ - - XM_EXM_START = 0x0080, /* r/w Start Address of the EXM Regs */ -#define XM_EXM(reg) (XM_EXM_START + ((reg) << 3)) -}; - -enum { - XM_SRC_CHK = 0x0100, /* NA reg r/w Source Check Address Register */ - XM_SA = 0x0108, /* NA reg r/w Station Address Register */ - XM_HSM = 0x0110, /* 64 bit r/w Hash Match Address Registers */ - XM_RX_LO_WM = 0x0118, /* 16 bit r/w Receive Low Water Mark */ - XM_RX_HI_WM = 0x011a, /* 16 bit r/w Receive High Water Mark */ - XM_RX_THR = 0x011c, /* 32 bit r/w Receive Request Threshold */ - XM_DEV_ID = 0x0120, /* 32 bit r/o Device ID Register */ - XM_MODE = 0x0124, /* 32 bit r/w Mode Register */ - XM_LSA = 0x0128, /* NA reg r/o Last Source Register */ - XM_TS_READ = 0x0130, /* 32 bit r/o Time Stamp Read Register */ - XM_TS_LOAD = 0x0134, /* 32 bit r/o Time Stamp Load Value */ - XM_STAT_CMD = 0x0200, /* 16 bit r/w Statistics Command Register */ - XM_RX_CNT_EV = 0x0204, /* 32 bit r/o Rx Counter Event Register */ - XM_TX_CNT_EV = 0x0208, /* 32 bit r/o Tx Counter Event Register */ - XM_RX_EV_MSK = 0x020c, /* 32 bit r/w Rx Counter Event Mask */ - XM_TX_EV_MSK = 0x0210, /* 32 bit r/w Tx Counter Event Mask */ - XM_TXF_OK = 0x0280, /* 32 bit r/o Frames Transmitted OK Conuter */ - XM_TXO_OK_HI = 0x0284, /* 32 bit r/o Octets Transmitted OK High Cnt*/ - XM_TXO_OK_LO = 0x0288, /* 32 bit r/o Octets Transmitted OK Low Cnt */ - XM_TXF_BC_OK = 0x028c, /* 32 bit r/o Broadcast Frames Xmitted OK */ - XM_TXF_MC_OK = 0x0290, /* 32 bit r/o Multicast Frames Xmitted OK */ - XM_TXF_UC_OK = 0x0294, /* 32 bit r/o Unicast Frames Xmitted OK */ - XM_TXF_LONG = 0x0298, /* 32 bit r/o Tx Long Frame Counter */ - XM_TXE_BURST = 0x029c, /* 32 bit r/o Tx Burst Event Counter */ - XM_TXF_MPAUSE = 0x02a0, /* 32 bit r/o Tx Pause MAC Ctrl Frame Cnt */ - XM_TXF_MCTRL = 0x02a4, /* 32 bit r/o Tx MAC Ctrl Frame Counter */ - XM_TXF_SNG_COL = 0x02a8, /* 32 bit r/o Tx Single Collision Counter */ - XM_TXF_MUL_COL = 0x02ac, /* 32 bit r/o Tx Multiple Collision Counter */ - XM_TXF_ABO_COL = 0x02b0, /* 32 bit r/o Tx aborted due to Exces. Col. */ - XM_TXF_LAT_COL = 0x02b4, /* 32 bit r/o Tx Late Collision Counter */ - XM_TXF_DEF = 0x02b8, /* 32 bit r/o Tx Deferred Frame Counter */ - XM_TXF_EX_DEF = 0x02bc, /* 32 bit r/o Tx Excessive Deferall Counter */ - XM_TXE_FIFO_UR = 0x02c0, /* 32 bit r/o Tx FIFO Underrun Event Cnt */ - XM_TXE_CS_ERR = 0x02c4, /* 32 bit r/o Tx Carrier Sense Error Cnt */ - XM_TXP_UTIL = 0x02c8, /* 32 bit r/o Tx Utilization in % */ - XM_TXF_64B = 0x02d0, /* 32 bit r/o 64 Byte Tx Frame Counter */ - XM_TXF_127B = 0x02d4, /* 32 bit r/o 65-127 Byte Tx Frame Counter */ - XM_TXF_255B = 0x02d8, /* 32 bit r/o 128-255 Byte Tx Frame Counter */ - XM_TXF_511B = 0x02dc, /* 32 bit r/o 256-511 Byte Tx Frame Counter */ - XM_TXF_1023B = 0x02e0, /* 32 bit r/o 512-1023 Byte Tx Frame Counter*/ - XM_TXF_MAX_SZ = 0x02e4, /* 32 bit r/o 1024-MaxSize Byte Tx Frame Cnt*/ - XM_RXF_OK = 0x0300, /* 32 bit r/o Frames Received OK */ - XM_RXO_OK_HI = 0x0304, /* 32 bit r/o Octets Received OK High Cnt */ - XM_RXO_OK_LO = 0x0308, /* 32 bit r/o Octets Received OK Low Counter*/ - XM_RXF_BC_OK = 0x030c, /* 32 bit r/o Broadcast Frames Received OK */ - XM_RXF_MC_OK = 0x0310, /* 32 bit r/o Multicast Frames Received OK */ - XM_RXF_UC_OK = 0x0314, /* 32 bit r/o Unicast Frames Received OK */ - XM_RXF_MPAUSE = 0x0318, /* 32 bit r/o Rx Pause MAC Ctrl Frame Cnt */ - XM_RXF_MCTRL = 0x031c, /* 32 bit r/o Rx MAC Ctrl Frame Counter */ - XM_RXF_INV_MP = 0x0320, /* 32 bit r/o Rx invalid Pause Frame Cnt */ - XM_RXF_INV_MOC = 0x0324, /* 32 bit r/o Rx Frames with inv. MAC Opcode*/ - XM_RXE_BURST = 0x0328, /* 32 bit r/o Rx Burst Event Counter */ - XM_RXE_FMISS = 0x032c, /* 32 bit r/o Rx Missed Frames Event Cnt */ - XM_RXF_FRA_ERR = 0x0330, /* 32 bit r/o Rx Framing Error Counter */ - XM_RXE_FIFO_OV = 0x0334, /* 32 bit r/o Rx FIFO overflow Event Cnt */ - XM_RXF_JAB_PKT = 0x0338, /* 32 bit r/o Rx Jabber Packet Frame Cnt */ - XM_RXE_CAR_ERR = 0x033c, /* 32 bit r/o Rx Carrier Event Error Cnt */ - XM_RXF_LEN_ERR = 0x0340, /* 32 bit r/o Rx in Range Length Error */ - XM_RXE_SYM_ERR = 0x0344, /* 32 bit r/o Rx Symbol Error Counter */ - XM_RXE_SHT_ERR = 0x0348, /* 32 bit r/o Rx Short Event Error Cnt */ - XM_RXE_RUNT = 0x034c, /* 32 bit r/o Rx Runt Event Counter */ - XM_RXF_LNG_ERR = 0x0350, /* 32 bit r/o Rx Frame too Long Error Cnt */ - XM_RXF_FCS_ERR = 0x0354, /* 32 bit r/o Rx Frame Check Seq. Error Cnt */ - XM_RXF_CEX_ERR = 0x035c, /* 32 bit r/o Rx Carrier Ext Error Frame Cnt*/ - XM_RXP_UTIL = 0x0360, /* 32 bit r/o Rx Utilization in % */ - XM_RXF_64B = 0x0368, /* 32 bit r/o 64 Byte Rx Frame Counter */ - XM_RXF_127B = 0x036c, /* 32 bit r/o 65-127 Byte Rx Frame Counter */ - XM_RXF_255B = 0x0370, /* 32 bit r/o 128-255 Byte Rx Frame Counter */ - XM_RXF_511B = 0x0374, /* 32 bit r/o 256-511 Byte Rx Frame Counter */ - XM_RXF_1023B = 0x0378, /* 32 bit r/o 512-1023 Byte Rx Frame Counter*/ - XM_RXF_MAX_SZ = 0x037c, /* 32 bit r/o 1024-MaxSize Byte Rx Frame Cnt*/ -}; - -/* XM_MMU_CMD 16 bit r/w MMU Command Register */ -enum { - XM_MMU_PHY_RDY = 1<<12, /* Bit 12: PHY Read Ready */ - XM_MMU_PHY_BUSY = 1<<11, /* Bit 11: PHY Busy */ - XM_MMU_IGN_PF = 1<<10, /* Bit 10: Ignore Pause Frame */ - XM_MMU_MAC_LB = 1<<9, /* Bit 9: Enable MAC Loopback */ - XM_MMU_FRC_COL = 1<<7, /* Bit 7: Force Collision */ - XM_MMU_SIM_COL = 1<<6, /* Bit 6: Simulate Collision */ - XM_MMU_NO_PRE = 1<<5, /* Bit 5: No MDIO Preamble */ - XM_MMU_GMII_FD = 1<<4, /* Bit 4: GMII uses Full Duplex */ - XM_MMU_RAT_CTRL = 1<<3, /* Bit 3: Enable Rate Control */ - XM_MMU_GMII_LOOP= 1<<2, /* Bit 2: PHY is in Loopback Mode */ - XM_MMU_ENA_RX = 1<<1, /* Bit 1: Enable Receiver */ - XM_MMU_ENA_TX = 1<<0, /* Bit 0: Enable Transmitter */ -}; - - -/* XM_TX_CMD 16 bit r/w Transmit Command Register */ -enum { - XM_TX_BK2BK = 1<<6, /* Bit 6: Ignor Carrier Sense (Tx Bk2Bk)*/ - XM_TX_ENC_BYP = 1<<5, /* Bit 5: Set Encoder in Bypass Mode */ - XM_TX_SAM_LINE = 1<<4, /* Bit 4: (sc) Start utilization calculation */ - XM_TX_NO_GIG_MD = 1<<3, /* Bit 3: Disable Carrier Extension */ - XM_TX_NO_PRE = 1<<2, /* Bit 2: Disable Preamble Generation */ - XM_TX_NO_CRC = 1<<1, /* Bit 1: Disable CRC Generation */ - XM_TX_AUTO_PAD = 1<<0, /* Bit 0: Enable Automatic Padding */ -}; - -/* XM_TX_RT_LIM 16 bit r/w Transmit Retry Limit Register */ -#define XM_RT_LIM_MSK 0x1f /* Bit 4..0: Tx Retry Limit */ - - -/* XM_TX_STIME 16 bit r/w Transmit Slottime Register */ -#define XM_STIME_MSK 0x7f /* Bit 6..0: Tx Slottime bits */ - - -/* XM_TX_IPG 16 bit r/w Transmit Inter Packet Gap */ -#define XM_IPG_MSK 0xff /* Bit 7..0: IPG value bits */ - - -/* XM_RX_CMD 16 bit r/w Receive Command Register */ -enum { - XM_RX_LENERR_OK = 1<<8, /* Bit 8 don't set Rx Err bit for */ - /* inrange error packets */ - XM_RX_BIG_PK_OK = 1<<7, /* Bit 7 don't set Rx Err bit for */ - /* jumbo packets */ - XM_RX_IPG_CAP = 1<<6, /* Bit 6 repl. type field with IPG */ - XM_RX_TP_MD = 1<<5, /* Bit 5: Enable transparent Mode */ - XM_RX_STRIP_FCS = 1<<4, /* Bit 4: Enable FCS Stripping */ - XM_RX_SELF_RX = 1<<3, /* Bit 3: Enable Rx of own packets */ - XM_RX_SAM_LINE = 1<<2, /* Bit 2: (sc) Start utilization calculation */ - XM_RX_STRIP_PAD = 1<<1, /* Bit 1: Strip pad bytes of Rx frames */ - XM_RX_DIS_CEXT = 1<<0, /* Bit 0: Disable carrier ext. check */ -}; - - -/* XM_GP_PORT 32 bit r/w General Purpose Port Register */ -enum { - XM_GP_ANIP = 1<<6, /* Bit 6: (ro) Auto-Neg. in progress */ - XM_GP_FRC_INT = 1<<5, /* Bit 5: (sc) Force Interrupt */ - XM_GP_RES_MAC = 1<<3, /* Bit 3: (sc) Reset MAC and FIFOs */ - XM_GP_RES_STAT = 1<<2, /* Bit 2: (sc) Reset the statistics module */ - XM_GP_INP_ASS = 1<<0, /* Bit 0: (ro) GP Input Pin asserted */ -}; - - -/* XM_IMSK 16 bit r/w Interrupt Mask Register */ -/* XM_ISRC 16 bit r/o Interrupt Status Register */ -enum { - XM_IS_LNK_AE = 1<<14, /* Bit 14: Link Asynchronous Event */ - XM_IS_TX_ABORT = 1<<13, /* Bit 13: Transmit Abort, late Col. etc */ - XM_IS_FRC_INT = 1<<12, /* Bit 12: Force INT bit set in GP */ - XM_IS_INP_ASS = 1<<11, /* Bit 11: Input Asserted, GP bit 0 set */ - XM_IS_LIPA_RC = 1<<10, /* Bit 10: Link Partner requests config */ - XM_IS_RX_PAGE = 1<<9, /* Bit 9: Page Received */ - XM_IS_TX_PAGE = 1<<8, /* Bit 8: Next Page Loaded for Transmit */ - XM_IS_AND = 1<<7, /* Bit 7: Auto-Negotiation Done */ - XM_IS_TSC_OV = 1<<6, /* Bit 6: Time Stamp Counter Overflow */ - XM_IS_RXC_OV = 1<<5, /* Bit 5: Rx Counter Event Overflow */ - XM_IS_TXC_OV = 1<<4, /* Bit 4: Tx Counter Event Overflow */ - XM_IS_RXF_OV = 1<<3, /* Bit 3: Receive FIFO Overflow */ - XM_IS_TXF_UR = 1<<2, /* Bit 2: Transmit FIFO Underrun */ - XM_IS_TX_COMP = 1<<1, /* Bit 1: Frame Tx Complete */ - XM_IS_RX_COMP = 1<<0, /* Bit 0: Frame Rx Complete */ - - XM_IMSK_DISABLE = 0xffff, -}; - -/* XM_HW_CFG 16 bit r/w Hardware Config Register */ -enum { - XM_HW_GEN_EOP = 1<<3, /* Bit 3: generate End of Packet pulse */ - XM_HW_COM4SIG = 1<<2, /* Bit 2: use Comma Detect for Sig. Det.*/ - XM_HW_GMII_MD = 1<<0, /* Bit 0: GMII Interface selected */ -}; - - -/* XM_TX_LO_WM 16 bit r/w Tx FIFO Low Water Mark */ -/* XM_TX_HI_WM 16 bit r/w Tx FIFO High Water Mark */ -#define XM_TX_WM_MSK 0x01ff /* Bit 9.. 0 Tx FIFO Watermark bits */ - -/* XM_TX_THR 16 bit r/w Tx Request Threshold */ -/* XM_HT_THR 16 bit r/w Host Request Threshold */ -/* XM_RX_THR 16 bit r/w Rx Request Threshold */ -#define XM_THR_MSK 0x03ff /* Bit 10.. 0 Rx/Tx Request Threshold bits */ - - -/* XM_TX_STAT 32 bit r/o Tx Status LIFO Register */ -enum { - XM_ST_VALID = (1UL<<31), /* Bit 31: Status Valid */ - XM_ST_BYTE_CNT = (0x3fffL<<17), /* Bit 30..17: Tx frame Length */ - XM_ST_RETRY_CNT = (0x1fL<<12), /* Bit 16..12: Retry Count */ - XM_ST_EX_COL = 1<<11, /* Bit 11: Excessive Collisions */ - XM_ST_EX_DEF = 1<<10, /* Bit 10: Excessive Deferral */ - XM_ST_BURST = 1<<9, /* Bit 9: p. xmitted in burst md*/ - XM_ST_DEFER = 1<<8, /* Bit 8: packet was defered */ - XM_ST_BC = 1<<7, /* Bit 7: Broadcast packet */ - XM_ST_MC = 1<<6, /* Bit 6: Multicast packet */ - XM_ST_UC = 1<<5, /* Bit 5: Unicast packet */ - XM_ST_TX_UR = 1<<4, /* Bit 4: FIFO Underrun occurred */ - XM_ST_CS_ERR = 1<<3, /* Bit 3: Carrier Sense Error */ - XM_ST_LAT_COL = 1<<2, /* Bit 2: Late Collision Error */ - XM_ST_MUL_COL = 1<<1, /* Bit 1: Multiple Collisions */ - XM_ST_SGN_COL = 1<<0, /* Bit 0: Single Collision */ -}; - -/* XM_RX_LO_WM 16 bit r/w Receive Low Water Mark */ -/* XM_RX_HI_WM 16 bit r/w Receive High Water Mark */ -#define XM_RX_WM_MSK 0x03ff /* Bit 11.. 0: Rx FIFO Watermark bits */ - - -/* XM_DEV_ID 32 bit r/o Device ID Register */ -#define XM_DEV_OUI (0x00ffffffUL<<8) /* Bit 31..8: Device OUI */ -#define XM_DEV_REV (0x07L << 5) /* Bit 7..5: Chip Rev Num */ - - -/* XM_MODE 32 bit r/w Mode Register */ -enum { - XM_MD_ENA_REJ = 1<<26, /* Bit 26: Enable Frame Reject */ - XM_MD_SPOE_E = 1<<25, /* Bit 25: Send Pause on Edge */ - /* extern generated */ - XM_MD_TX_REP = 1<<24, /* Bit 24: Transmit Repeater Mode */ - XM_MD_SPOFF_I = 1<<23, /* Bit 23: Send Pause on FIFO full */ - /* intern generated */ - XM_MD_LE_STW = 1<<22, /* Bit 22: Rx Stat Word in Little Endian */ - XM_MD_TX_CONT = 1<<21, /* Bit 21: Send Continuous */ - XM_MD_TX_PAUSE = 1<<20, /* Bit 20: (sc) Send Pause Frame */ - XM_MD_ATS = 1<<19, /* Bit 19: Append Time Stamp */ - XM_MD_SPOL_I = 1<<18, /* Bit 18: Send Pause on Low */ - /* intern generated */ - XM_MD_SPOH_I = 1<<17, /* Bit 17: Send Pause on High */ - /* intern generated */ - XM_MD_CAP = 1<<16, /* Bit 16: Check Address Pair */ - XM_MD_ENA_HASH = 1<<15, /* Bit 15: Enable Hashing */ - XM_MD_CSA = 1<<14, /* Bit 14: Check Station Address */ - XM_MD_CAA = 1<<13, /* Bit 13: Check Address Array */ - XM_MD_RX_MCTRL = 1<<12, /* Bit 12: Rx MAC Control Frame */ - XM_MD_RX_RUNT = 1<<11, /* Bit 11: Rx Runt Frames */ - XM_MD_RX_IRLE = 1<<10, /* Bit 10: Rx in Range Len Err Frame */ - XM_MD_RX_LONG = 1<<9, /* Bit 9: Rx Long Frame */ - XM_MD_RX_CRCE = 1<<8, /* Bit 8: Rx CRC Error Frame */ - XM_MD_RX_ERR = 1<<7, /* Bit 7: Rx Error Frame */ - XM_MD_DIS_UC = 1<<6, /* Bit 6: Disable Rx Unicast */ - XM_MD_DIS_MC = 1<<5, /* Bit 5: Disable Rx Multicast */ - XM_MD_DIS_BC = 1<<4, /* Bit 4: Disable Rx Broadcast */ - XM_MD_ENA_PROM = 1<<3, /* Bit 3: Enable Promiscuous */ - XM_MD_ENA_BE = 1<<2, /* Bit 2: Enable Big Endian */ - XM_MD_FTF = 1<<1, /* Bit 1: (sc) Flush Tx FIFO */ - XM_MD_FRF = 1<<0, /* Bit 0: (sc) Flush Rx FIFO */ -}; - -#define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I) -#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\ - XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA) - -/* XM_STAT_CMD 16 bit r/w Statistics Command Register */ -enum { - XM_SC_SNP_RXC = 1<<5, /* Bit 5: (sc) Snap Rx Counters */ - XM_SC_SNP_TXC = 1<<4, /* Bit 4: (sc) Snap Tx Counters */ - XM_SC_CP_RXC = 1<<3, /* Bit 3: Copy Rx Counters Continuously */ - XM_SC_CP_TXC = 1<<2, /* Bit 2: Copy Tx Counters Continuously */ - XM_SC_CLR_RXC = 1<<1, /* Bit 1: (sc) Clear Rx Counters */ - XM_SC_CLR_TXC = 1<<0, /* Bit 0: (sc) Clear Tx Counters */ -}; - - -/* XM_RX_CNT_EV 32 bit r/o Rx Counter Event Register */ -/* XM_RX_EV_MSK 32 bit r/w Rx Counter Event Mask */ -enum { - XMR_MAX_SZ_OV = 1<<31, /* Bit 31: 1024-MaxSize Rx Cnt Ov*/ - XMR_1023B_OV = 1<<30, /* Bit 30: 512-1023Byte Rx Cnt Ov*/ - XMR_511B_OV = 1<<29, /* Bit 29: 256-511 Byte Rx Cnt Ov*/ - XMR_255B_OV = 1<<28, /* Bit 28: 128-255 Byte Rx Cnt Ov*/ - XMR_127B_OV = 1<<27, /* Bit 27: 65-127 Byte Rx Cnt Ov */ - XMR_64B_OV = 1<<26, /* Bit 26: 64 Byte Rx Cnt Ov */ - XMR_UTIL_OV = 1<<25, /* Bit 25: Rx Util Cnt Overflow */ - XMR_UTIL_UR = 1<<24, /* Bit 24: Rx Util Cnt Underrun */ - XMR_CEX_ERR_OV = 1<<23, /* Bit 23: CEXT Err Cnt Ov */ - XMR_FCS_ERR_OV = 1<<21, /* Bit 21: Rx FCS Error Cnt Ov */ - XMR_LNG_ERR_OV = 1<<20, /* Bit 20: Rx too Long Err Cnt Ov*/ - XMR_RUNT_OV = 1<<19, /* Bit 19: Runt Event Cnt Ov */ - XMR_SHT_ERR_OV = 1<<18, /* Bit 18: Rx Short Ev Err Cnt Ov*/ - XMR_SYM_ERR_OV = 1<<17, /* Bit 17: Rx Sym Err Cnt Ov */ - XMR_CAR_ERR_OV = 1<<15, /* Bit 15: Rx Carr Ev Err Cnt Ov */ - XMR_JAB_PKT_OV = 1<<14, /* Bit 14: Rx Jabb Packet Cnt Ov */ - XMR_FIFO_OV = 1<<13, /* Bit 13: Rx FIFO Ov Ev Cnt Ov */ - XMR_FRA_ERR_OV = 1<<12, /* Bit 12: Rx Framing Err Cnt Ov */ - XMR_FMISS_OV = 1<<11, /* Bit 11: Rx Missed Ev Cnt Ov */ - XMR_BURST = 1<<10, /* Bit 10: Rx Burst Event Cnt Ov */ - XMR_INV_MOC = 1<<9, /* Bit 9: Rx with inv. MAC OC Ov*/ - XMR_INV_MP = 1<<8, /* Bit 8: Rx inv Pause Frame Ov */ - XMR_MCTRL_OV = 1<<7, /* Bit 7: Rx MAC Ctrl-F Cnt Ov */ - XMR_MPAUSE_OV = 1<<6, /* Bit 6: Rx Pause MAC Ctrl-F Ov*/ - XMR_UC_OK_OV = 1<<5, /* Bit 5: Rx Unicast Frame CntOv*/ - XMR_MC_OK_OV = 1<<4, /* Bit 4: Rx Multicast Cnt Ov */ - XMR_BC_OK_OV = 1<<3, /* Bit 3: Rx Broadcast Cnt Ov */ - XMR_OK_LO_OV = 1<<2, /* Bit 2: Octets Rx OK Low CntOv*/ - XMR_OK_HI_OV = 1<<1, /* Bit 1: Octets Rx OK Hi Cnt Ov*/ - XMR_OK_OV = 1<<0, /* Bit 0: Frames Received Ok Ov */ -}; - -#define XMR_DEF_MSK (XMR_OK_LO_OV | XMR_OK_HI_OV) - -/* XM_TX_CNT_EV 32 bit r/o Tx Counter Event Register */ -/* XM_TX_EV_MSK 32 bit r/w Tx Counter Event Mask */ -enum { - XMT_MAX_SZ_OV = 1<<25, /* Bit 25: 1024-MaxSize Tx Cnt Ov*/ - XMT_1023B_OV = 1<<24, /* Bit 24: 512-1023Byte Tx Cnt Ov*/ - XMT_511B_OV = 1<<23, /* Bit 23: 256-511 Byte Tx Cnt Ov*/ - XMT_255B_OV = 1<<22, /* Bit 22: 128-255 Byte Tx Cnt Ov*/ - XMT_127B_OV = 1<<21, /* Bit 21: 65-127 Byte Tx Cnt Ov */ - XMT_64B_OV = 1<<20, /* Bit 20: 64 Byte Tx Cnt Ov */ - XMT_UTIL_OV = 1<<19, /* Bit 19: Tx Util Cnt Overflow */ - XMT_UTIL_UR = 1<<18, /* Bit 18: Tx Util Cnt Underrun */ - XMT_CS_ERR_OV = 1<<17, /* Bit 17: Tx Carr Sen Err Cnt Ov*/ - XMT_FIFO_UR_OV = 1<<16, /* Bit 16: Tx FIFO Ur Ev Cnt Ov */ - XMT_EX_DEF_OV = 1<<15, /* Bit 15: Tx Ex Deferall Cnt Ov */ - XMT_DEF = 1<<14, /* Bit 14: Tx Deferred Cnt Ov */ - XMT_LAT_COL_OV = 1<<13, /* Bit 13: Tx Late Col Cnt Ov */ - XMT_ABO_COL_OV = 1<<12, /* Bit 12: Tx abo dueto Ex Col Ov*/ - XMT_MUL_COL_OV = 1<<11, /* Bit 11: Tx Mult Col Cnt Ov */ - XMT_SNG_COL = 1<<10, /* Bit 10: Tx Single Col Cnt Ov */ - XMT_MCTRL_OV = 1<<9, /* Bit 9: Tx MAC Ctrl Counter Ov*/ - XMT_MPAUSE = 1<<8, /* Bit 8: Tx Pause MAC Ctrl-F Ov*/ - XMT_BURST = 1<<7, /* Bit 7: Tx Burst Event Cnt Ov */ - XMT_LONG = 1<<6, /* Bit 6: Tx Long Frame Cnt Ov */ - XMT_UC_OK_OV = 1<<5, /* Bit 5: Tx Unicast Cnt Ov */ - XMT_MC_OK_OV = 1<<4, /* Bit 4: Tx Multicast Cnt Ov */ - XMT_BC_OK_OV = 1<<3, /* Bit 3: Tx Broadcast Cnt Ov */ - XMT_OK_LO_OV = 1<<2, /* Bit 2: Octets Tx OK Low CntOv*/ - XMT_OK_HI_OV = 1<<1, /* Bit 1: Octets Tx OK Hi Cnt Ov*/ - XMT_OK_OV = 1<<0, /* Bit 0: Frames Tx Ok Ov */ -}; - -#define XMT_DEF_MSK (XMT_OK_LO_OV | XMT_OK_HI_OV) - -struct skge_rx_desc { - u32 control; - u32 next_offset; - u32 dma_lo; - u32 dma_hi; - u32 status; - u32 timestamp; - u16 csum2; - u16 csum1; - u16 csum2_start; - u16 csum1_start; -}; - -struct skge_tx_desc { - u32 control; - u32 next_offset; - u32 dma_lo; - u32 dma_hi; - u32 status; - u32 csum_offs; - u16 csum_write; - u16 csum_start; - u32 rsvd; -}; - -struct skge_element { - struct skge_element *next; - void *desc; - struct sk_buff *skb; - DEFINE_DMA_UNMAP_ADDR(mapaddr); - DEFINE_DMA_UNMAP_LEN(maplen); -}; - -struct skge_ring { - struct skge_element *to_clean; - struct skge_element *to_use; - struct skge_element *start; - unsigned long count; -}; - - -struct skge_hw { - void __iomem *regs; - struct pci_dev *pdev; - spinlock_t hw_lock; - u32 intr_mask; - struct net_device *dev[2]; - - u8 chip_id; - u8 chip_rev; - u8 copper; - u8 ports; - u8 phy_type; - - u32 ram_size; - u32 ram_offset; - u16 phy_addr; - spinlock_t phy_lock; - struct tasklet_struct phy_task; - - char irq_name[0]; /* skge@pci:000:04:00.0 */ -}; - -enum pause_control { - FLOW_MODE_NONE = 1, /* No Flow-Control */ - FLOW_MODE_LOC_SEND = 2, /* Local station sends PAUSE */ - FLOW_MODE_SYMMETRIC = 3, /* Both stations may send PAUSE */ - FLOW_MODE_SYM_OR_REM = 4, /* Both stations may send PAUSE or - * just the remote station may send PAUSE - */ -}; - -enum pause_status { - FLOW_STAT_INDETERMINATED=0, /* indeterminated */ - FLOW_STAT_NONE, /* No Flow Control */ - FLOW_STAT_REM_SEND, /* Remote Station sends PAUSE */ - FLOW_STAT_LOC_SEND, /* Local station sends PAUSE */ - FLOW_STAT_SYMMETRIC, /* Both station may send PAUSE */ -}; - - -struct skge_port { - struct skge_hw *hw; - struct net_device *netdev; - struct napi_struct napi; - int port; - u32 msg_enable; - - struct skge_ring tx_ring; - - struct skge_ring rx_ring ____cacheline_aligned_in_smp; - unsigned int rx_buf_size; - - struct timer_list link_timer; - enum pause_control flow_control; - enum pause_status flow_status; - u8 blink_on; - u8 wol; - u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */ - u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */ - u16 speed; /* SPEED_1000, SPEED_100, ... */ - u32 advertising; - - void *mem; /* PCI memory for rings */ - dma_addr_t dma; - unsigned long mem_size; -#ifdef CONFIG_SKGE_DEBUG - struct dentry *debugfs; -#endif -}; - - -/* Register accessor for memory mapped device */ -static inline u32 skge_read32(const struct skge_hw *hw, int reg) -{ - return readl(hw->regs + reg); -} - -static inline u16 skge_read16(const struct skge_hw *hw, int reg) -{ - return readw(hw->regs + reg); -} - -static inline u8 skge_read8(const struct skge_hw *hw, int reg) -{ - return readb(hw->regs + reg); -} - -static inline void skge_write32(const struct skge_hw *hw, int reg, u32 val) -{ - writel(val, hw->regs + reg); -} - -static inline void skge_write16(const struct skge_hw *hw, int reg, u16 val) -{ - writew(val, hw->regs + reg); -} - -static inline void skge_write8(const struct skge_hw *hw, int reg, u8 val) -{ - writeb(val, hw->regs + reg); -} - -/* MAC Related Registers inside the device. */ -#define SK_REG(port,reg) (((port)<<7)+(u16)(reg)) -#define SK_XMAC_REG(port, reg) \ - ((BASE_XMAC_1 + (port) * (BASE_XMAC_2 - BASE_XMAC_1)) | (reg) << 1) - -static inline u32 xm_read32(const struct skge_hw *hw, int port, int reg) -{ - u32 v; - v = skge_read16(hw, SK_XMAC_REG(port, reg)); - v |= (u32)skge_read16(hw, SK_XMAC_REG(port, reg+2)) << 16; - return v; -} - -static inline u16 xm_read16(const struct skge_hw *hw, int port, int reg) -{ - return skge_read16(hw, SK_XMAC_REG(port,reg)); -} - -static inline void xm_write32(const struct skge_hw *hw, int port, int r, u32 v) -{ - skge_write16(hw, SK_XMAC_REG(port,r), v & 0xffff); - skge_write16(hw, SK_XMAC_REG(port,r+2), v >> 16); -} - -static inline void xm_write16(const struct skge_hw *hw, int port, int r, u16 v) -{ - skge_write16(hw, SK_XMAC_REG(port,r), v); -} - -static inline void xm_outhash(const struct skge_hw *hw, int port, int reg, - const u8 *hash) -{ - xm_write16(hw, port, reg, (u16)hash[0] | ((u16)hash[1] << 8)); - xm_write16(hw, port, reg+2, (u16)hash[2] | ((u16)hash[3] << 8)); - xm_write16(hw, port, reg+4, (u16)hash[4] | ((u16)hash[5] << 8)); - xm_write16(hw, port, reg+6, (u16)hash[6] | ((u16)hash[7] << 8)); -} - -static inline void xm_outaddr(const struct skge_hw *hw, int port, int reg, - const u8 *addr) -{ - xm_write16(hw, port, reg, (u16)addr[0] | ((u16)addr[1] << 8)); - xm_write16(hw, port, reg+2, (u16)addr[2] | ((u16)addr[3] << 8)); - xm_write16(hw, port, reg+4, (u16)addr[4] | ((u16)addr[5] << 8)); -} - -#define SK_GMAC_REG(port,reg) \ - (BASE_GMAC_1 + (port) * (BASE_GMAC_2-BASE_GMAC_1) + (reg)) - -static inline u16 gma_read16(const struct skge_hw *hw, int port, int reg) -{ - return skge_read16(hw, SK_GMAC_REG(port,reg)); -} - -static inline u32 gma_read32(const struct skge_hw *hw, int port, int reg) -{ - return (u32) skge_read16(hw, SK_GMAC_REG(port,reg)) - | ((u32)skge_read16(hw, SK_GMAC_REG(port,reg+4)) << 16); -} - -static inline void gma_write16(const struct skge_hw *hw, int port, int r, u16 v) -{ - skge_write16(hw, SK_GMAC_REG(port,r), v); -} - -static inline void gma_set_addr(struct skge_hw *hw, int port, int reg, - const u8 *addr) -{ - gma_write16(hw, port, reg, (u16) addr[0] | ((u16) addr[1] << 8)); - gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8)); - gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8)); -} - -#endif diff --git a/addons/skge/src/4.4.180/Makefile b/addons/skge/src/4.4.180/Makefile deleted file mode 100644 index f0ca3939..00000000 --- a/addons/skge/src/4.4.180/Makefile +++ /dev/null @@ -1 +0,0 @@ -obj-m += skge.o diff --git a/addons/skge/src/4.4.180/skge.c b/addons/skge/src/4.4.180/skge.c deleted file mode 100644 index c9f4b541..00000000 --- a/addons/skge/src/4.4.180/skge.c +++ /dev/null @@ -1,4228 +0,0 @@ -/* - * New driver for Marvell Yukon chipset and SysKonnect Gigabit - * Ethernet adapters. Based on earlier sk98lin, e100 and - * FreeBSD if_sk drivers. - * - * This driver intentionally does not support all the features - * of the original driver such as link fail-over and link management because - * those should be done at higher levels. - * - * Copyright (C) 2004, 2005 Stephen Hemminger - * - * 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. - * - * 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., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "skge.h" - -#define DRV_NAME "skge" -#define DRV_VERSION "1.14" - -#define DEFAULT_TX_RING_SIZE 128 -#define DEFAULT_RX_RING_SIZE 512 -#define MAX_TX_RING_SIZE 1024 -#define TX_LOW_WATER (MAX_SKB_FRAGS + 1) -#define MAX_RX_RING_SIZE 4096 -#define RX_COPY_THRESHOLD 128 -#define RX_BUF_SIZE 1536 -#define PHY_RETRIES 1000 -#define ETH_JUMBO_MTU 9000 -#define TX_WATCHDOG (5 * HZ) -#define NAPI_WEIGHT 64 -#define BLINK_MS 250 -#define LINK_HZ HZ - -#define SKGE_EEPROM_MAGIC 0x9933aabb - - -MODULE_DESCRIPTION("SysKonnect Gigabit Ethernet driver"); -MODULE_AUTHOR("Stephen Hemminger "); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -static const u32 default_msg = (NETIF_MSG_DRV | NETIF_MSG_PROBE | - NETIF_MSG_LINK | NETIF_MSG_IFUP | - NETIF_MSG_IFDOWN); - -static int debug = -1; /* defaults above */ -module_param(debug, int, 0); -MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all)"); - -static const struct pci_device_id skge_id_table[] = { - { PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x1700) }, /* 3Com 3C940 */ - { PCI_DEVICE(PCI_VENDOR_ID_3COM, 0x80EB) }, /* 3Com 3C940B */ -#ifdef CONFIG_SKGE_GENESIS - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4300) }, /* SK-9xx */ -#endif - { PCI_DEVICE(PCI_VENDOR_ID_SYSKONNECT, 0x4320) }, /* SK-98xx V2.0 */ - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4b01) }, /* D-Link DGE-530T (rev.B) */ - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4c00) }, /* D-Link DGE-530T */ - { PCI_DEVICE(PCI_VENDOR_ID_DLINK, 0x4302) }, /* D-Link DGE-530T Rev C1 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4320) }, /* Marvell Yukon 88E8001/8003/8010 */ - { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x5005) }, /* Belkin */ - { PCI_DEVICE(PCI_VENDOR_ID_CNET, 0x434E) }, /* CNet PowerG-2000 */ - { PCI_DEVICE(PCI_VENDOR_ID_LINKSYS, 0x1064) }, /* Linksys EG1064 v2 */ - { PCI_VENDOR_ID_LINKSYS, 0x1032, PCI_ANY_ID, 0x0015 }, /* Linksys EG1032 v2 */ - { 0 } -}; -MODULE_DEVICE_TABLE(pci, skge_id_table); - -static int skge_up(struct net_device *dev); -static int skge_down(struct net_device *dev); -static void skge_phy_reset(struct skge_port *skge); -static void skge_tx_clean(struct net_device *dev); -static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); -static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val); -static void genesis_get_stats(struct skge_port *skge, u64 *data); -static void yukon_get_stats(struct skge_port *skge, u64 *data); -static void yukon_init(struct skge_hw *hw, int port); -static void genesis_mac_init(struct skge_hw *hw, int port); -static void genesis_link_up(struct skge_port *skge); -static void skge_set_multicast(struct net_device *dev); -static irqreturn_t skge_intr(int irq, void *dev_id); - -/* Avoid conditionals by using array */ -static const int txqaddr[] = { Q_XA1, Q_XA2 }; -static const int rxqaddr[] = { Q_R1, Q_R2 }; -static const u32 rxirqmask[] = { IS_R1_F, IS_R2_F }; -static const u32 txirqmask[] = { IS_XA1_F, IS_XA2_F }; -static const u32 napimask[] = { IS_R1_F|IS_XA1_F, IS_R2_F|IS_XA2_F }; -static const u32 portmask[] = { IS_PORT_1, IS_PORT_2 }; - -static inline bool is_genesis(const struct skge_hw *hw) -{ -#ifdef CONFIG_SKGE_GENESIS - return hw->chip_id == CHIP_ID_GENESIS; -#else - return false; -#endif -} - -static int skge_get_regs_len(struct net_device *dev) -{ - return 0x4000; -} - -/* - * Returns copy of whole control register region - * Note: skip RAM address register because accessing it will - * cause bus hangs! - */ -static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs, - void *p) -{ - const struct skge_port *skge = netdev_priv(dev); - const void __iomem *io = skge->hw->regs; - - regs->version = 1; - memset(p, 0, regs->len); - memcpy_fromio(p, io, B3_RAM_ADDR); - - if (regs->len > B3_RI_WTO_R1) { - memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1, - regs->len - B3_RI_WTO_R1); - } -} - -/* Wake on Lan only supported on Yukon chips with rev 1 or above */ -static u32 wol_supported(const struct skge_hw *hw) -{ - if (is_genesis(hw)) - return 0; - - if (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0) - return 0; - - return WAKE_MAGIC | WAKE_PHY; -} - -static void skge_wol_init(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 ctrl; - - skge_write16(hw, B0_CTST, CS_RST_CLR); - skge_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR); - - /* Turn on Vaux */ - skge_write8(hw, B0_POWER_CTRL, - PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF); - - /* WA code for COMA mode -- clear PHY reset */ - if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev >= CHIP_REV_YU_LITE_A3) { - u32 reg = skge_read32(hw, B2_GP_IO); - reg |= GP_DIR_9; - reg &= ~GP_IO_9; - skge_write32(hw, B2_GP_IO, reg); - } - - skge_write32(hw, SK_REG(port, GPHY_CTRL), - GPC_DIS_SLEEP | - GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 | - GPC_ANEG_1 | GPC_RST_SET); - - skge_write32(hw, SK_REG(port, GPHY_CTRL), - GPC_DIS_SLEEP | - GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 | - GPC_ANEG_1 | GPC_RST_CLR); - - skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); - - /* Force to 10/100 skge_reset will re-enable on resume */ - gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, - (PHY_AN_100FULL | PHY_AN_100HALF | - PHY_AN_10FULL | PHY_AN_10HALF | PHY_AN_CSMA)); - /* no 1000 HD/FD */ - gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_CTRL, - PHY_CT_RESET | PHY_CT_SPS_LSB | PHY_CT_ANE | - PHY_CT_RE_CFG | PHY_CT_DUP_MD); - - - /* Set GMAC to no flow control and auto update for speed/duplex */ - gma_write16(hw, port, GM_GP_CTRL, - GM_GPCR_FC_TX_DIS|GM_GPCR_TX_ENA|GM_GPCR_RX_ENA| - GM_GPCR_DUP_FULL|GM_GPCR_FC_RX_DIS|GM_GPCR_AU_FCT_DIS); - - /* Set WOL address */ - memcpy_toio(hw->regs + WOL_REGS(port, WOL_MAC_ADDR), - skge->netdev->dev_addr, ETH_ALEN); - - /* Turn on appropriate WOL control bits */ - skge_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), WOL_CTL_CLEAR_RESULT); - ctrl = 0; - if (skge->wol & WAKE_PHY) - ctrl |= WOL_CTL_ENA_PME_ON_LINK_CHG|WOL_CTL_ENA_LINK_CHG_UNIT; - else - ctrl |= WOL_CTL_DIS_PME_ON_LINK_CHG|WOL_CTL_DIS_LINK_CHG_UNIT; - - if (skge->wol & WAKE_MAGIC) - ctrl |= WOL_CTL_ENA_PME_ON_MAGIC_PKT|WOL_CTL_ENA_MAGIC_PKT_UNIT; - else - ctrl |= WOL_CTL_DIS_PME_ON_MAGIC_PKT|WOL_CTL_DIS_MAGIC_PKT_UNIT; - - ctrl |= WOL_CTL_DIS_PME_ON_PATTERN|WOL_CTL_DIS_PATTERN_UNIT; - skge_write16(hw, WOL_REGS(port, WOL_CTRL_STAT), ctrl); - - /* block receiver */ - skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); -} - -static void skge_get_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct skge_port *skge = netdev_priv(dev); - - wol->supported = wol_supported(skge->hw); - wol->wolopts = skge->wol; -} - -static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - - if ((wol->wolopts & ~wol_supported(hw)) || - !device_can_wakeup(&hw->pdev->dev)) - return -EOPNOTSUPP; - - skge->wol = wol->wolopts; - - device_set_wakeup_enable(&hw->pdev->dev, skge->wol); - - return 0; -} - -/* Determine supported/advertised modes based on hardware. - * Note: ethtool ADVERTISED_xxx == SUPPORTED_xxx - */ -static u32 skge_supported_modes(const struct skge_hw *hw) -{ - u32 supported; - - if (hw->copper) { - supported = (SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full | - SUPPORTED_1000baseT_Half | - SUPPORTED_1000baseT_Full | - SUPPORTED_Autoneg | - SUPPORTED_TP); - - if (is_genesis(hw)) - supported &= ~(SUPPORTED_10baseT_Half | - SUPPORTED_10baseT_Full | - SUPPORTED_100baseT_Half | - SUPPORTED_100baseT_Full); - - else if (hw->chip_id == CHIP_ID_YUKON) - supported &= ~SUPPORTED_1000baseT_Half; - } else - supported = (SUPPORTED_1000baseT_Full | - SUPPORTED_1000baseT_Half | - SUPPORTED_FIBRE | - SUPPORTED_Autoneg); - - return supported; -} - -static int skge_get_settings(struct net_device *dev, - struct ethtool_cmd *ecmd) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - - ecmd->transceiver = XCVR_INTERNAL; - ecmd->supported = skge_supported_modes(hw); - - if (hw->copper) { - ecmd->port = PORT_TP; - ecmd->phy_address = hw->phy_addr; - } else - ecmd->port = PORT_FIBRE; - - ecmd->advertising = skge->advertising; - ecmd->autoneg = skge->autoneg; - ethtool_cmd_speed_set(ecmd, skge->speed); - ecmd->duplex = skge->duplex; - return 0; -} - -static int skge_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd) -{ - struct skge_port *skge = netdev_priv(dev); - const struct skge_hw *hw = skge->hw; - u32 supported = skge_supported_modes(hw); - int err = 0; - - if (ecmd->autoneg == AUTONEG_ENABLE) { - ecmd->advertising = supported; - skge->duplex = -1; - skge->speed = -1; - } else { - u32 setting; - u32 speed = ethtool_cmd_speed(ecmd); - - switch (speed) { - case SPEED_1000: - if (ecmd->duplex == DUPLEX_FULL) - setting = SUPPORTED_1000baseT_Full; - else if (ecmd->duplex == DUPLEX_HALF) - setting = SUPPORTED_1000baseT_Half; - else - return -EINVAL; - break; - case SPEED_100: - if (ecmd->duplex == DUPLEX_FULL) - setting = SUPPORTED_100baseT_Full; - else if (ecmd->duplex == DUPLEX_HALF) - setting = SUPPORTED_100baseT_Half; - else - return -EINVAL; - break; - - case SPEED_10: - if (ecmd->duplex == DUPLEX_FULL) - setting = SUPPORTED_10baseT_Full; - else if (ecmd->duplex == DUPLEX_HALF) - setting = SUPPORTED_10baseT_Half; - else - return -EINVAL; - break; - default: - return -EINVAL; - } - - if ((setting & supported) == 0) - return -EINVAL; - - skge->speed = speed; - skge->duplex = ecmd->duplex; - } - - skge->autoneg = ecmd->autoneg; - skge->advertising = ecmd->advertising; - - if (netif_running(dev)) { - skge_down(dev); - err = skge_up(dev); - if (err) { - dev_close(dev); - return err; - } - } - - return 0; -} - -static void skge_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct skge_port *skge = netdev_priv(dev); - - strlcpy(info->driver, DRV_NAME, sizeof(info->driver)); - strlcpy(info->version, DRV_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, pci_name(skge->hw->pdev), - sizeof(info->bus_info)); -} - -static const struct skge_stat { - char name[ETH_GSTRING_LEN]; - u16 xmac_offset; - u16 gma_offset; -} skge_stats[] = { - { "tx_bytes", XM_TXO_OK_HI, GM_TXO_OK_HI }, - { "rx_bytes", XM_RXO_OK_HI, GM_RXO_OK_HI }, - - { "tx_broadcast", XM_TXF_BC_OK, GM_TXF_BC_OK }, - { "rx_broadcast", XM_RXF_BC_OK, GM_RXF_BC_OK }, - { "tx_multicast", XM_TXF_MC_OK, GM_TXF_MC_OK }, - { "rx_multicast", XM_RXF_MC_OK, GM_RXF_MC_OK }, - { "tx_unicast", XM_TXF_UC_OK, GM_TXF_UC_OK }, - { "rx_unicast", XM_RXF_UC_OK, GM_RXF_UC_OK }, - { "tx_mac_pause", XM_TXF_MPAUSE, GM_TXF_MPAUSE }, - { "rx_mac_pause", XM_RXF_MPAUSE, GM_RXF_MPAUSE }, - - { "collisions", XM_TXF_SNG_COL, GM_TXF_SNG_COL }, - { "multi_collisions", XM_TXF_MUL_COL, GM_TXF_MUL_COL }, - { "aborted", XM_TXF_ABO_COL, GM_TXF_ABO_COL }, - { "late_collision", XM_TXF_LAT_COL, GM_TXF_LAT_COL }, - { "fifo_underrun", XM_TXE_FIFO_UR, GM_TXE_FIFO_UR }, - { "fifo_overflow", XM_RXE_FIFO_OV, GM_RXE_FIFO_OV }, - - { "rx_toolong", XM_RXF_LNG_ERR, GM_RXF_LNG_ERR }, - { "rx_jabber", XM_RXF_JAB_PKT, GM_RXF_JAB_PKT }, - { "rx_runt", XM_RXE_RUNT, GM_RXE_FRAG }, - { "rx_too_long", XM_RXF_LNG_ERR, GM_RXF_LNG_ERR }, - { "rx_fcs_error", XM_RXF_FCS_ERR, GM_RXF_FCS_ERR }, -}; - -static int skge_get_sset_count(struct net_device *dev, int sset) -{ - switch (sset) { - case ETH_SS_STATS: - return ARRAY_SIZE(skge_stats); - default: - return -EOPNOTSUPP; - } -} - -static void skge_get_ethtool_stats(struct net_device *dev, - struct ethtool_stats *stats, u64 *data) -{ - struct skge_port *skge = netdev_priv(dev); - - if (is_genesis(skge->hw)) - genesis_get_stats(skge, data); - else - yukon_get_stats(skge, data); -} - -/* Use hardware MIB variables for critical path statistics and - * transmit feedback not reported at interrupt. - * Other errors are accounted for in interrupt handler. - */ -static struct net_device_stats *skge_get_stats(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - u64 data[ARRAY_SIZE(skge_stats)]; - - if (is_genesis(skge->hw)) - genesis_get_stats(skge, data); - else - yukon_get_stats(skge, data); - - dev->stats.tx_bytes = data[0]; - dev->stats.rx_bytes = data[1]; - dev->stats.tx_packets = data[2] + data[4] + data[6]; - dev->stats.rx_packets = data[3] + data[5] + data[7]; - dev->stats.multicast = data[3] + data[5]; - dev->stats.collisions = data[10]; - dev->stats.tx_aborted_errors = data[12]; - - return &dev->stats; -} - -static void skge_get_strings(struct net_device *dev, u32 stringset, u8 *data) -{ - int i; - - switch (stringset) { - case ETH_SS_STATS: - for (i = 0; i < ARRAY_SIZE(skge_stats); i++) - memcpy(data + i * ETH_GSTRING_LEN, - skge_stats[i].name, ETH_GSTRING_LEN); - break; - } -} - -static void skge_get_ring_param(struct net_device *dev, - struct ethtool_ringparam *p) -{ - struct skge_port *skge = netdev_priv(dev); - - p->rx_max_pending = MAX_RX_RING_SIZE; - p->tx_max_pending = MAX_TX_RING_SIZE; - - p->rx_pending = skge->rx_ring.count; - p->tx_pending = skge->tx_ring.count; -} - -static int skge_set_ring_param(struct net_device *dev, - struct ethtool_ringparam *p) -{ - struct skge_port *skge = netdev_priv(dev); - int err = 0; - - if (p->rx_pending == 0 || p->rx_pending > MAX_RX_RING_SIZE || - p->tx_pending < TX_LOW_WATER || p->tx_pending > MAX_TX_RING_SIZE) - return -EINVAL; - - skge->rx_ring.count = p->rx_pending; - skge->tx_ring.count = p->tx_pending; - - if (netif_running(dev)) { - skge_down(dev); - err = skge_up(dev); - if (err) - dev_close(dev); - } - - return err; -} - -static u32 skge_get_msglevel(struct net_device *netdev) -{ - struct skge_port *skge = netdev_priv(netdev); - return skge->msg_enable; -} - -static void skge_set_msglevel(struct net_device *netdev, u32 value) -{ - struct skge_port *skge = netdev_priv(netdev); - skge->msg_enable = value; -} - -static int skge_nway_reset(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - - if (skge->autoneg != AUTONEG_ENABLE || !netif_running(dev)) - return -EINVAL; - - skge_phy_reset(skge); - return 0; -} - -static void skge_get_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *ecmd) -{ - struct skge_port *skge = netdev_priv(dev); - - ecmd->rx_pause = ((skge->flow_control == FLOW_MODE_SYMMETRIC) || - (skge->flow_control == FLOW_MODE_SYM_OR_REM)); - ecmd->tx_pause = (ecmd->rx_pause || - (skge->flow_control == FLOW_MODE_LOC_SEND)); - - ecmd->autoneg = ecmd->rx_pause || ecmd->tx_pause; -} - -static int skge_set_pauseparam(struct net_device *dev, - struct ethtool_pauseparam *ecmd) -{ - struct skge_port *skge = netdev_priv(dev); - struct ethtool_pauseparam old; - int err = 0; - - skge_get_pauseparam(dev, &old); - - if (ecmd->autoneg != old.autoneg) - skge->flow_control = ecmd->autoneg ? FLOW_MODE_NONE : FLOW_MODE_SYMMETRIC; - else { - if (ecmd->rx_pause && ecmd->tx_pause) - skge->flow_control = FLOW_MODE_SYMMETRIC; - else if (ecmd->rx_pause && !ecmd->tx_pause) - skge->flow_control = FLOW_MODE_SYM_OR_REM; - else if (!ecmd->rx_pause && ecmd->tx_pause) - skge->flow_control = FLOW_MODE_LOC_SEND; - else - skge->flow_control = FLOW_MODE_NONE; - } - - if (netif_running(dev)) { - skge_down(dev); - err = skge_up(dev); - if (err) { - dev_close(dev); - return err; - } - } - - return 0; -} - -/* Chip internal frequency for clock calculations */ -static inline u32 hwkhz(const struct skge_hw *hw) -{ - return is_genesis(hw) ? 53125 : 78125; -} - -/* Chip HZ to microseconds */ -static inline u32 skge_clk2usec(const struct skge_hw *hw, u32 ticks) -{ - return (ticks * 1000) / hwkhz(hw); -} - -/* Microseconds to chip HZ */ -static inline u32 skge_usecs2clk(const struct skge_hw *hw, u32 usec) -{ - return hwkhz(hw) * usec / 1000; -} - -static int skge_get_coalesce(struct net_device *dev, - struct ethtool_coalesce *ecmd) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - - ecmd->rx_coalesce_usecs = 0; - ecmd->tx_coalesce_usecs = 0; - - if (skge_read32(hw, B2_IRQM_CTRL) & TIM_START) { - u32 delay = skge_clk2usec(hw, skge_read32(hw, B2_IRQM_INI)); - u32 msk = skge_read32(hw, B2_IRQM_MSK); - - if (msk & rxirqmask[port]) - ecmd->rx_coalesce_usecs = delay; - if (msk & txirqmask[port]) - ecmd->tx_coalesce_usecs = delay; - } - - return 0; -} - -/* Note: interrupt timer is per board, but can turn on/off per port */ -static int skge_set_coalesce(struct net_device *dev, - struct ethtool_coalesce *ecmd) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - u32 msk = skge_read32(hw, B2_IRQM_MSK); - u32 delay = 25; - - if (ecmd->rx_coalesce_usecs == 0) - msk &= ~rxirqmask[port]; - else if (ecmd->rx_coalesce_usecs < 25 || - ecmd->rx_coalesce_usecs > 33333) - return -EINVAL; - else { - msk |= rxirqmask[port]; - delay = ecmd->rx_coalesce_usecs; - } - - if (ecmd->tx_coalesce_usecs == 0) - msk &= ~txirqmask[port]; - else if (ecmd->tx_coalesce_usecs < 25 || - ecmd->tx_coalesce_usecs > 33333) - return -EINVAL; - else { - msk |= txirqmask[port]; - delay = min(delay, ecmd->rx_coalesce_usecs); - } - - skge_write32(hw, B2_IRQM_MSK, msk); - if (msk == 0) - skge_write32(hw, B2_IRQM_CTRL, TIM_STOP); - else { - skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, delay)); - skge_write32(hw, B2_IRQM_CTRL, TIM_START); - } - return 0; -} - -enum led_mode { LED_MODE_OFF, LED_MODE_ON, LED_MODE_TST }; -static void skge_led(struct skge_port *skge, enum led_mode mode) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - - spin_lock_bh(&hw->phy_lock); - if (is_genesis(hw)) { - switch (mode) { - case LED_MODE_OFF: - if (hw->phy_type == SK_PHY_BCOM) - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_OFF); - else { - skge_write32(hw, SK_REG(port, TX_LED_VAL), 0); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_T_OFF); - } - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_OFF); - skge_write32(hw, SK_REG(port, RX_LED_VAL), 0); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_T_OFF); - break; - - case LED_MODE_ON: - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_ON); - skge_write8(hw, SK_REG(port, LNK_LED_REG), LINKLED_LINKSYNC_ON); - - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); - - break; - - case LED_MODE_TST: - skge_write8(hw, SK_REG(port, RX_LED_TST), LED_T_ON); - skge_write32(hw, SK_REG(port, RX_LED_VAL), 100); - skge_write8(hw, SK_REG(port, RX_LED_CTRL), LED_START); - - if (hw->phy_type == SK_PHY_BCOM) - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, PHY_B_PEC_LED_ON); - else { - skge_write8(hw, SK_REG(port, TX_LED_TST), LED_T_ON); - skge_write32(hw, SK_REG(port, TX_LED_VAL), 100); - skge_write8(hw, SK_REG(port, TX_LED_CTRL), LED_START); - } - - } - } else { - switch (mode) { - case LED_MODE_OFF: - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_DUP(MO_LED_OFF) | - PHY_M_LED_MO_10(MO_LED_OFF) | - PHY_M_LED_MO_100(MO_LED_OFF) | - PHY_M_LED_MO_1000(MO_LED_OFF) | - PHY_M_LED_MO_RX(MO_LED_OFF)); - break; - case LED_MODE_ON: - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, - PHY_M_LED_PULS_DUR(PULS_170MS) | - PHY_M_LED_BLINK_RT(BLINK_84MS) | - PHY_M_LEDC_TX_CTRL | - PHY_M_LEDC_DP_CTRL); - - gm_phy_write(hw, port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_RX(MO_LED_OFF) | - (skge->speed == SPEED_100 ? - PHY_M_LED_MO_100(MO_LED_ON) : 0)); - break; - case LED_MODE_TST: - gm_phy_write(hw, port, PHY_MARV_LED_CTRL, 0); - gm_phy_write(hw, port, PHY_MARV_LED_OVER, - PHY_M_LED_MO_DUP(MO_LED_ON) | - PHY_M_LED_MO_10(MO_LED_ON) | - PHY_M_LED_MO_100(MO_LED_ON) | - PHY_M_LED_MO_1000(MO_LED_ON) | - PHY_M_LED_MO_RX(MO_LED_ON)); - } - } - spin_unlock_bh(&hw->phy_lock); -} - -/* blink LED's for finding board */ -static int skge_set_phys_id(struct net_device *dev, - enum ethtool_phys_id_state state) -{ - struct skge_port *skge = netdev_priv(dev); - - switch (state) { - case ETHTOOL_ID_ACTIVE: - return 2; /* cycle on/off twice per second */ - - case ETHTOOL_ID_ON: - skge_led(skge, LED_MODE_TST); - break; - - case ETHTOOL_ID_OFF: - skge_led(skge, LED_MODE_OFF); - break; - - case ETHTOOL_ID_INACTIVE: - /* back to regular LED state */ - skge_led(skge, netif_running(dev) ? LED_MODE_ON : LED_MODE_OFF); - } - - return 0; -} - -static int skge_get_eeprom_len(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - u32 reg2; - - pci_read_config_dword(skge->hw->pdev, PCI_DEV_REG2, ®2); - return 1 << (((reg2 & PCI_VPD_ROM_SZ) >> 14) + 8); -} - -static u32 skge_vpd_read(struct pci_dev *pdev, int cap, u16 offset) -{ - u32 val; - - pci_write_config_word(pdev, cap + PCI_VPD_ADDR, offset); - - do { - pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset); - } while (!(offset & PCI_VPD_ADDR_F)); - - pci_read_config_dword(pdev, cap + PCI_VPD_DATA, &val); - return val; -} - -static void skge_vpd_write(struct pci_dev *pdev, int cap, u16 offset, u32 val) -{ - pci_write_config_dword(pdev, cap + PCI_VPD_DATA, val); - pci_write_config_word(pdev, cap + PCI_VPD_ADDR, - offset | PCI_VPD_ADDR_F); - - do { - pci_read_config_word(pdev, cap + PCI_VPD_ADDR, &offset); - } while (offset & PCI_VPD_ADDR_F); -} - -static int skge_get_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, - u8 *data) -{ - struct skge_port *skge = netdev_priv(dev); - struct pci_dev *pdev = skge->hw->pdev; - int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD); - int length = eeprom->len; - u16 offset = eeprom->offset; - - if (!cap) - return -EINVAL; - - eeprom->magic = SKGE_EEPROM_MAGIC; - - while (length > 0) { - u32 val = skge_vpd_read(pdev, cap, offset); - int n = min_t(int, length, sizeof(val)); - - memcpy(data, &val, n); - length -= n; - data += n; - offset += n; - } - return 0; -} - -static int skge_set_eeprom(struct net_device *dev, struct ethtool_eeprom *eeprom, - u8 *data) -{ - struct skge_port *skge = netdev_priv(dev); - struct pci_dev *pdev = skge->hw->pdev; - int cap = pci_find_capability(pdev, PCI_CAP_ID_VPD); - int length = eeprom->len; - u16 offset = eeprom->offset; - - if (!cap) - return -EINVAL; - - if (eeprom->magic != SKGE_EEPROM_MAGIC) - return -EINVAL; - - while (length > 0) { - u32 val; - int n = min_t(int, length, sizeof(val)); - - if (n < sizeof(val)) - val = skge_vpd_read(pdev, cap, offset); - memcpy(&val, data, n); - - skge_vpd_write(pdev, cap, offset, val); - - length -= n; - data += n; - offset += n; - } - return 0; -} - -static const struct ethtool_ops skge_ethtool_ops = { - .get_settings = skge_get_settings, - .set_settings = skge_set_settings, - .get_drvinfo = skge_get_drvinfo, - .get_regs_len = skge_get_regs_len, - .get_regs = skge_get_regs, - .get_wol = skge_get_wol, - .set_wol = skge_set_wol, - .get_msglevel = skge_get_msglevel, - .set_msglevel = skge_set_msglevel, - .nway_reset = skge_nway_reset, - .get_link = ethtool_op_get_link, - .get_eeprom_len = skge_get_eeprom_len, - .get_eeprom = skge_get_eeprom, - .set_eeprom = skge_set_eeprom, - .get_ringparam = skge_get_ring_param, - .set_ringparam = skge_set_ring_param, - .get_pauseparam = skge_get_pauseparam, - .set_pauseparam = skge_set_pauseparam, - .get_coalesce = skge_get_coalesce, - .set_coalesce = skge_set_coalesce, - .get_strings = skge_get_strings, - .set_phys_id = skge_set_phys_id, - .get_sset_count = skge_get_sset_count, - .get_ethtool_stats = skge_get_ethtool_stats, -}; - -/* - * Allocate ring elements and chain them together - * One-to-one association of board descriptors with ring elements - */ -static int skge_ring_alloc(struct skge_ring *ring, void *vaddr, u32 base) -{ - struct skge_tx_desc *d; - struct skge_element *e; - int i; - - ring->start = kcalloc(ring->count, sizeof(*e), GFP_KERNEL); - if (!ring->start) - return -ENOMEM; - - for (i = 0, e = ring->start, d = vaddr; i < ring->count; i++, e++, d++) { - e->desc = d; - if (i == ring->count - 1) { - e->next = ring->start; - d->next_offset = base; - } else { - e->next = e + 1; - d->next_offset = base + (i+1) * sizeof(*d); - } - } - ring->to_use = ring->to_clean = ring->start; - - return 0; -} - -/* Allocate and setup a new buffer for receiving */ -static int skge_rx_setup(struct skge_port *skge, struct skge_element *e, - struct sk_buff *skb, unsigned int bufsize) -{ - struct skge_rx_desc *rd = e->desc; - dma_addr_t map; - - map = pci_map_single(skge->hw->pdev, skb->data, bufsize, - PCI_DMA_FROMDEVICE); - - if (pci_dma_mapping_error(skge->hw->pdev, map)) - return -1; - - rd->dma_lo = lower_32_bits(map); - rd->dma_hi = upper_32_bits(map); - e->skb = skb; - rd->csum1_start = ETH_HLEN; - rd->csum2_start = ETH_HLEN; - rd->csum1 = 0; - rd->csum2 = 0; - - wmb(); - - rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | bufsize; - dma_unmap_addr_set(e, mapaddr, map); - dma_unmap_len_set(e, maplen, bufsize); - return 0; -} - -/* Resume receiving using existing skb, - * Note: DMA address is not changed by chip. - * MTU not changed while receiver active. - */ -static inline void skge_rx_reuse(struct skge_element *e, unsigned int size) -{ - struct skge_rx_desc *rd = e->desc; - - rd->csum2 = 0; - rd->csum2_start = ETH_HLEN; - - wmb(); - - rd->control = BMU_OWN | BMU_STF | BMU_IRQ_EOF | BMU_TCP_CHECK | size; -} - - -/* Free all buffers in receive ring, assumes receiver stopped */ -static void skge_rx_clean(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - struct skge_ring *ring = &skge->rx_ring; - struct skge_element *e; - - e = ring->start; - do { - struct skge_rx_desc *rd = e->desc; - rd->control = 0; - if (e->skb) { - pci_unmap_single(hw->pdev, - dma_unmap_addr(e, mapaddr), - dma_unmap_len(e, maplen), - PCI_DMA_FROMDEVICE); - dev_kfree_skb(e->skb); - e->skb = NULL; - } - } while ((e = e->next) != ring->start); -} - - -/* Allocate buffers for receive ring - * For receive: to_clean is next received frame. - */ -static int skge_rx_fill(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_ring *ring = &skge->rx_ring; - struct skge_element *e; - - e = ring->start; - do { - struct sk_buff *skb; - - skb = __netdev_alloc_skb(dev, skge->rx_buf_size + NET_IP_ALIGN, - GFP_KERNEL); - if (!skb) - return -ENOMEM; - - skb_reserve(skb, NET_IP_ALIGN); - if (skge_rx_setup(skge, e, skb, skge->rx_buf_size) < 0) { - dev_kfree_skb(skb); - return -EIO; - } - } while ((e = e->next) != ring->start); - - ring->to_clean = ring->start; - return 0; -} - -static const char *skge_pause(enum pause_status status) -{ - switch (status) { - case FLOW_STAT_NONE: - return "none"; - case FLOW_STAT_REM_SEND: - return "rx only"; - case FLOW_STAT_LOC_SEND: - return "tx_only"; - case FLOW_STAT_SYMMETRIC: /* Both station may send PAUSE */ - return "both"; - default: - return "indeterminated"; - } -} - - -static void skge_link_up(struct skge_port *skge) -{ - skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), - LED_BLK_OFF|LED_SYNC_OFF|LED_ON); - - netif_carrier_on(skge->netdev); - netif_wake_queue(skge->netdev); - - netif_info(skge, link, skge->netdev, - "Link is up at %d Mbps, %s duplex, flow control %s\n", - skge->speed, - skge->duplex == DUPLEX_FULL ? "full" : "half", - skge_pause(skge->flow_status)); -} - -static void skge_link_down(struct skge_port *skge) -{ - skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); - netif_carrier_off(skge->netdev); - netif_stop_queue(skge->netdev); - - netif_info(skge, link, skge->netdev, "Link is down\n"); -} - -static void xm_link_down(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); - - xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE); - - if (netif_carrier_ok(dev)) - skge_link_down(skge); -} - -static int __xm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val) -{ - int i; - - xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); - *val = xm_read16(hw, port, XM_PHY_DATA); - - if (hw->phy_type == SK_PHY_XMAC) - goto ready; - - for (i = 0; i < PHY_RETRIES; i++) { - if (xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_RDY) - goto ready; - udelay(1); - } - - return -ETIMEDOUT; - ready: - *val = xm_read16(hw, port, XM_PHY_DATA); - - return 0; -} - -static u16 xm_phy_read(struct skge_hw *hw, int port, u16 reg) -{ - u16 v = 0; - if (__xm_phy_read(hw, port, reg, &v)) - pr_warn("%s: phy read timed out\n", hw->dev[port]->name); - return v; -} - -static int xm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) -{ - int i; - - xm_write16(hw, port, XM_PHY_ADDR, reg | hw->phy_addr); - for (i = 0; i < PHY_RETRIES; i++) { - if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY)) - goto ready; - udelay(1); - } - return -EIO; - - ready: - xm_write16(hw, port, XM_PHY_DATA, val); - for (i = 0; i < PHY_RETRIES; i++) { - if (!(xm_read16(hw, port, XM_MMU_CMD) & XM_MMU_PHY_BUSY)) - return 0; - udelay(1); - } - return -ETIMEDOUT; -} - -static void genesis_init(struct skge_hw *hw) -{ - /* set blink source counter */ - skge_write32(hw, B2_BSC_INI, (SK_BLK_DUR * SK_FACT_53) / 100); - skge_write8(hw, B2_BSC_CTRL, BSC_START); - - /* configure mac arbiter */ - skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR); - - /* configure mac arbiter timeout values */ - skge_write8(hw, B3_MA_TOINI_RX1, SK_MAC_TO_53); - skge_write8(hw, B3_MA_TOINI_RX2, SK_MAC_TO_53); - skge_write8(hw, B3_MA_TOINI_TX1, SK_MAC_TO_53); - skge_write8(hw, B3_MA_TOINI_TX2, SK_MAC_TO_53); - - skge_write8(hw, B3_MA_RCINI_RX1, 0); - skge_write8(hw, B3_MA_RCINI_RX2, 0); - skge_write8(hw, B3_MA_RCINI_TX1, 0); - skge_write8(hw, B3_MA_RCINI_TX2, 0); - - /* configure packet arbiter timeout */ - skge_write16(hw, B3_PA_CTRL, PA_RST_CLR); - skge_write16(hw, B3_PA_TOINI_RX1, SK_PKT_TO_MAX); - skge_write16(hw, B3_PA_TOINI_TX1, SK_PKT_TO_MAX); - skge_write16(hw, B3_PA_TOINI_RX2, SK_PKT_TO_MAX); - skge_write16(hw, B3_PA_TOINI_TX2, SK_PKT_TO_MAX); -} - -static void genesis_reset(struct skge_hw *hw, int port) -{ - static const u8 zero[8] = { 0 }; - u32 reg; - - skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); - - /* reset the statistics module */ - xm_write32(hw, port, XM_GP_PORT, XM_GP_RES_STAT); - xm_write16(hw, port, XM_IMSK, XM_IMSK_DISABLE); - xm_write32(hw, port, XM_MODE, 0); /* clear Mode Reg */ - xm_write16(hw, port, XM_TX_CMD, 0); /* reset TX CMD Reg */ - xm_write16(hw, port, XM_RX_CMD, 0); /* reset RX CMD Reg */ - - /* disable Broadcom PHY IRQ */ - if (hw->phy_type == SK_PHY_BCOM) - xm_write16(hw, port, PHY_BCOM_INT_MASK, 0xffff); - - xm_outhash(hw, port, XM_HSM, zero); - - /* Flush TX and RX fifo */ - reg = xm_read32(hw, port, XM_MODE); - xm_write32(hw, port, XM_MODE, reg | XM_MD_FTF); - xm_write32(hw, port, XM_MODE, reg | XM_MD_FRF); -} - -/* Convert mode to MII values */ -static const u16 phy_pause_map[] = { - [FLOW_MODE_NONE] = 0, - [FLOW_MODE_LOC_SEND] = PHY_AN_PAUSE_ASYM, - [FLOW_MODE_SYMMETRIC] = PHY_AN_PAUSE_CAP, - [FLOW_MODE_SYM_OR_REM] = PHY_AN_PAUSE_CAP | PHY_AN_PAUSE_ASYM, -}; - -/* special defines for FIBER (88E1011S only) */ -static const u16 fiber_pause_map[] = { - [FLOW_MODE_NONE] = PHY_X_P_NO_PAUSE, - [FLOW_MODE_LOC_SEND] = PHY_X_P_ASYM_MD, - [FLOW_MODE_SYMMETRIC] = PHY_X_P_SYM_MD, - [FLOW_MODE_SYM_OR_REM] = PHY_X_P_BOTH_MD, -}; - - -/* Check status of Broadcom phy link */ -static void bcom_check_link(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); - u16 status; - - /* read twice because of latch */ - xm_phy_read(hw, port, PHY_BCOM_STAT); - status = xm_phy_read(hw, port, PHY_BCOM_STAT); - - if ((status & PHY_ST_LSYNC) == 0) { - xm_link_down(hw, port); - return; - } - - if (skge->autoneg == AUTONEG_ENABLE) { - u16 lpa, aux; - - if (!(status & PHY_ST_AN_OVER)) - return; - - lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP); - if (lpa & PHY_B_AN_RF) { - netdev_notice(dev, "remote fault\n"); - return; - } - - aux = xm_phy_read(hw, port, PHY_BCOM_AUX_STAT); - - /* Check Duplex mismatch */ - switch (aux & PHY_B_AS_AN_RES_MSK) { - case PHY_B_RES_1000FD: - skge->duplex = DUPLEX_FULL; - break; - case PHY_B_RES_1000HD: - skge->duplex = DUPLEX_HALF; - break; - default: - netdev_notice(dev, "duplex mismatch\n"); - return; - } - - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - switch (aux & PHY_B_AS_PAUSE_MSK) { - case PHY_B_AS_PAUSE_MSK: - skge->flow_status = FLOW_STAT_SYMMETRIC; - break; - case PHY_B_AS_PRR: - skge->flow_status = FLOW_STAT_REM_SEND; - break; - case PHY_B_AS_PRT: - skge->flow_status = FLOW_STAT_LOC_SEND; - break; - default: - skge->flow_status = FLOW_STAT_NONE; - } - skge->speed = SPEED_1000; - } - - if (!netif_carrier_ok(dev)) - genesis_link_up(skge); -} - -/* Broadcom 5400 only supports giagabit! SysKonnect did not put an additional - * Phy on for 100 or 10Mbit operation - */ -static void bcom_phy_init(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - int i; - u16 id1, r, ext, ctl; - - /* magic workaround patterns for Broadcom */ - static const struct { - u16 reg; - u16 val; - } A1hack[] = { - { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1104 }, - { 0x17, 0x0013 }, { 0x15, 0x0404 }, { 0x17, 0x8006 }, - { 0x15, 0x0132 }, { 0x17, 0x8006 }, { 0x15, 0x0232 }, - { 0x17, 0x800D }, { 0x15, 0x000F }, { 0x18, 0x0420 }, - }, C0hack[] = { - { 0x18, 0x0c20 }, { 0x17, 0x0012 }, { 0x15, 0x1204 }, - { 0x17, 0x0013 }, { 0x15, 0x0A04 }, { 0x18, 0x0420 }, - }; - - /* read Id from external PHY (all have the same address) */ - id1 = xm_phy_read(hw, port, PHY_XMAC_ID1); - - /* Optimize MDIO transfer by suppressing preamble. */ - r = xm_read16(hw, port, XM_MMU_CMD); - r |= XM_MMU_NO_PRE; - xm_write16(hw, port, XM_MMU_CMD, r); - - switch (id1) { - case PHY_BCOM_ID1_C0: - /* - * Workaround BCOM Errata for the C0 type. - * Write magic patterns to reserved registers. - */ - for (i = 0; i < ARRAY_SIZE(C0hack); i++) - xm_phy_write(hw, port, - C0hack[i].reg, C0hack[i].val); - - break; - case PHY_BCOM_ID1_A1: - /* - * Workaround BCOM Errata for the A1 type. - * Write magic patterns to reserved registers. - */ - for (i = 0; i < ARRAY_SIZE(A1hack); i++) - xm_phy_write(hw, port, - A1hack[i].reg, A1hack[i].val); - break; - } - - /* - * Workaround BCOM Errata (#10523) for all BCom PHYs. - * Disable Power Management after reset. - */ - r = xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL); - r |= PHY_B_AC_DIS_PM; - xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, r); - - /* Dummy read */ - xm_read16(hw, port, XM_ISRC); - - ext = PHY_B_PEC_EN_LTR; /* enable tx led */ - ctl = PHY_CT_SP1000; /* always 1000mbit */ - - if (skge->autoneg == AUTONEG_ENABLE) { - /* - * Workaround BCOM Errata #1 for the C5 type. - * 1000Base-T Link Acquisition Failure in Slave Mode - * Set Repeater/DTE bit 10 of the 1000Base-T Control Register - */ - u16 adv = PHY_B_1000C_RD; - if (skge->advertising & ADVERTISED_1000baseT_Half) - adv |= PHY_B_1000C_AHD; - if (skge->advertising & ADVERTISED_1000baseT_Full) - adv |= PHY_B_1000C_AFD; - xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, adv); - - ctl |= PHY_CT_ANE | PHY_CT_RE_CFG; - } else { - if (skge->duplex == DUPLEX_FULL) - ctl |= PHY_CT_DUP_MD; - /* Force to slave */ - xm_phy_write(hw, port, PHY_BCOM_1000T_CTRL, PHY_B_1000C_MSE); - } - - /* Set autonegotiation pause parameters */ - xm_phy_write(hw, port, PHY_BCOM_AUNE_ADV, - phy_pause_map[skge->flow_control] | PHY_AN_CSMA); - - /* Handle Jumbo frames */ - if (hw->dev[port]->mtu > ETH_DATA_LEN) { - xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, - PHY_B_AC_TX_TST | PHY_B_AC_LONG_PACK); - - ext |= PHY_B_PEC_HIGH_LA; - - } - - xm_phy_write(hw, port, PHY_BCOM_P_EXT_CTRL, ext); - xm_phy_write(hw, port, PHY_BCOM_CTRL, ctl); - - /* Use link status change interrupt */ - xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); -} - -static void xm_phy_init(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 ctrl = 0; - - if (skge->autoneg == AUTONEG_ENABLE) { - if (skge->advertising & ADVERTISED_1000baseT_Half) - ctrl |= PHY_X_AN_HD; - if (skge->advertising & ADVERTISED_1000baseT_Full) - ctrl |= PHY_X_AN_FD; - - ctrl |= fiber_pause_map[skge->flow_control]; - - xm_phy_write(hw, port, PHY_XMAC_AUNE_ADV, ctrl); - - /* Restart Auto-negotiation */ - ctrl = PHY_CT_ANE | PHY_CT_RE_CFG; - } else { - /* Set DuplexMode in Config register */ - if (skge->duplex == DUPLEX_FULL) - ctrl |= PHY_CT_DUP_MD; - /* - * Do NOT enable Auto-negotiation here. This would hold - * the link down because no IDLEs are transmitted - */ - } - - xm_phy_write(hw, port, PHY_XMAC_CTRL, ctrl); - - /* Poll PHY for status changes */ - mod_timer(&skge->link_timer, jiffies + LINK_HZ); -} - -static int xm_check_link(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 status; - - /* read twice because of latch */ - xm_phy_read(hw, port, PHY_XMAC_STAT); - status = xm_phy_read(hw, port, PHY_XMAC_STAT); - - if ((status & PHY_ST_LSYNC) == 0) { - xm_link_down(hw, port); - return 0; - } - - if (skge->autoneg == AUTONEG_ENABLE) { - u16 lpa, res; - - if (!(status & PHY_ST_AN_OVER)) - return 0; - - lpa = xm_phy_read(hw, port, PHY_XMAC_AUNE_LP); - if (lpa & PHY_B_AN_RF) { - netdev_notice(dev, "remote fault\n"); - return 0; - } - - res = xm_phy_read(hw, port, PHY_XMAC_RES_ABI); - - /* Check Duplex mismatch */ - switch (res & (PHY_X_RS_HD | PHY_X_RS_FD)) { - case PHY_X_RS_FD: - skge->duplex = DUPLEX_FULL; - break; - case PHY_X_RS_HD: - skge->duplex = DUPLEX_HALF; - break; - default: - netdev_notice(dev, "duplex mismatch\n"); - return 0; - } - - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - if ((skge->flow_control == FLOW_MODE_SYMMETRIC || - skge->flow_control == FLOW_MODE_SYM_OR_REM) && - (lpa & PHY_X_P_SYM_MD)) - skge->flow_status = FLOW_STAT_SYMMETRIC; - else if (skge->flow_control == FLOW_MODE_SYM_OR_REM && - (lpa & PHY_X_RS_PAUSE) == PHY_X_P_ASYM_MD) - /* Enable PAUSE receive, disable PAUSE transmit */ - skge->flow_status = FLOW_STAT_REM_SEND; - else if (skge->flow_control == FLOW_MODE_LOC_SEND && - (lpa & PHY_X_RS_PAUSE) == PHY_X_P_BOTH_MD) - /* Disable PAUSE receive, enable PAUSE transmit */ - skge->flow_status = FLOW_STAT_LOC_SEND; - else - skge->flow_status = FLOW_STAT_NONE; - - skge->speed = SPEED_1000; - } - - if (!netif_carrier_ok(dev)) - genesis_link_up(skge); - return 1; -} - -/* Poll to check for link coming up. - * - * Since internal PHY is wired to a level triggered pin, can't - * get an interrupt when carrier is detected, need to poll for - * link coming up. - */ -static void xm_link_timer(unsigned long arg) -{ - struct skge_port *skge = (struct skge_port *) arg; - struct net_device *dev = skge->netdev; - struct skge_hw *hw = skge->hw; - int port = skge->port; - int i; - unsigned long flags; - - if (!netif_running(dev)) - return; - - spin_lock_irqsave(&hw->phy_lock, flags); - - /* - * Verify that the link by checking GPIO register three times. - * This pin has the signal from the link_sync pin connected to it. - */ - for (i = 0; i < 3; i++) { - if (xm_read16(hw, port, XM_GP_PORT) & XM_GP_INP_ASS) - goto link_down; - } - - /* Re-enable interrupt to detect link down */ - if (xm_check_link(dev)) { - u16 msk = xm_read16(hw, port, XM_IMSK); - msk &= ~XM_IS_INP_ASS; - xm_write16(hw, port, XM_IMSK, msk); - xm_read16(hw, port, XM_ISRC); - } else { -link_down: - mod_timer(&skge->link_timer, - round_jiffies(jiffies + LINK_HZ)); - } - spin_unlock_irqrestore(&hw->phy_lock, flags); -} - -static void genesis_mac_init(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); - int jumbo = hw->dev[port]->mtu > ETH_DATA_LEN; - int i; - u32 r; - static const u8 zero[6] = { 0 }; - - for (i = 0; i < 10; i++) { - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), - MFF_SET_MAC_RST); - if (skge_read16(hw, SK_REG(port, TX_MFF_CTRL1)) & MFF_SET_MAC_RST) - goto reset_ok; - udelay(1); - } - - netdev_warn(dev, "genesis reset failed\n"); - - reset_ok: - /* Unreset the XMAC. */ - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); - - /* - * Perform additional initialization for external PHYs, - * namely for the 1000baseTX cards that use the XMAC's - * GMII mode. - */ - if (hw->phy_type != SK_PHY_XMAC) { - /* Take external Phy out of reset */ - r = skge_read32(hw, B2_GP_IO); - if (port == 0) - r |= GP_DIR_0|GP_IO_0; - else - r |= GP_DIR_2|GP_IO_2; - - skge_write32(hw, B2_GP_IO, r); - - /* Enable GMII interface */ - xm_write16(hw, port, XM_HW_CFG, XM_HW_GMII_MD); - } - - - switch (hw->phy_type) { - case SK_PHY_XMAC: - xm_phy_init(skge); - break; - case SK_PHY_BCOM: - bcom_phy_init(skge); - bcom_check_link(hw, port); - } - - /* Set Station Address */ - xm_outaddr(hw, port, XM_SA, dev->dev_addr); - - /* We don't use match addresses so clear */ - for (i = 1; i < 16; i++) - xm_outaddr(hw, port, XM_EXM(i), zero); - - /* Clear MIB counters */ - xm_write16(hw, port, XM_STAT_CMD, - XM_SC_CLR_RXC | XM_SC_CLR_TXC); - /* Clear two times according to Errata #3 */ - xm_write16(hw, port, XM_STAT_CMD, - XM_SC_CLR_RXC | XM_SC_CLR_TXC); - - /* configure Rx High Water Mark (XM_RX_HI_WM) */ - xm_write16(hw, port, XM_RX_HI_WM, 1450); - - /* We don't need the FCS appended to the packet. */ - r = XM_RX_LENERR_OK | XM_RX_STRIP_FCS; - if (jumbo) - r |= XM_RX_BIG_PK_OK; - - if (skge->duplex == DUPLEX_HALF) { - /* - * If in manual half duplex mode the other side might be in - * full duplex mode, so ignore if a carrier extension is not seen - * on frames received - */ - r |= XM_RX_DIS_CEXT; - } - xm_write16(hw, port, XM_RX_CMD, r); - - /* We want short frames padded to 60 bytes. */ - xm_write16(hw, port, XM_TX_CMD, XM_TX_AUTO_PAD); - - /* Increase threshold for jumbo frames on dual port */ - if (hw->ports > 1 && jumbo) - xm_write16(hw, port, XM_TX_THR, 1020); - else - xm_write16(hw, port, XM_TX_THR, 512); - - /* - * Enable the reception of all error frames. This is is - * a necessary evil due to the design of the XMAC. The - * XMAC's receive FIFO is only 8K in size, however jumbo - * frames can be up to 9000 bytes in length. When bad - * frame filtering is enabled, the XMAC's RX FIFO operates - * in 'store and forward' mode. For this to work, the - * entire frame has to fit into the FIFO, but that means - * that jumbo frames larger than 8192 bytes will be - * truncated. Disabling all bad frame filtering causes - * the RX FIFO to operate in streaming mode, in which - * case the XMAC will start transferring frames out of the - * RX FIFO as soon as the FIFO threshold is reached. - */ - xm_write32(hw, port, XM_MODE, XM_DEF_MODE); - - - /* - * Initialize the Receive Counter Event Mask (XM_RX_EV_MSK) - * - Enable all bits excepting 'Octets Rx OK Low CntOv' - * and 'Octets Rx OK Hi Cnt Ov'. - */ - xm_write32(hw, port, XM_RX_EV_MSK, XMR_DEF_MSK); - - /* - * Initialize the Transmit Counter Event Mask (XM_TX_EV_MSK) - * - Enable all bits excepting 'Octets Tx OK Low CntOv' - * and 'Octets Tx OK Hi Cnt Ov'. - */ - xm_write32(hw, port, XM_TX_EV_MSK, XMT_DEF_MSK); - - /* Configure MAC arbiter */ - skge_write16(hw, B3_MA_TO_CTRL, MA_RST_CLR); - - /* configure timeout values */ - skge_write8(hw, B3_MA_TOINI_RX1, 72); - skge_write8(hw, B3_MA_TOINI_RX2, 72); - skge_write8(hw, B3_MA_TOINI_TX1, 72); - skge_write8(hw, B3_MA_TOINI_TX2, 72); - - skge_write8(hw, B3_MA_RCINI_RX1, 0); - skge_write8(hw, B3_MA_RCINI_RX2, 0); - skge_write8(hw, B3_MA_RCINI_TX1, 0); - skge_write8(hw, B3_MA_RCINI_TX2, 0); - - /* Configure Rx MAC FIFO */ - skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_CLR); - skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_TIM_PAT); - skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_ENA_OP_MD); - - /* Configure Tx MAC FIFO */ - skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_CLR); - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_TX_CTRL_DEF); - skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_ENA_OP_MD); - - if (jumbo) { - /* Enable frame flushing if jumbo frames used */ - skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_FLUSH); - } else { - /* enable timeout timers if normal frames */ - skge_write16(hw, B3_PA_CTRL, - (port == 0) ? PA_ENA_TO_TX1 : PA_ENA_TO_TX2); - } -} - -static void genesis_stop(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - unsigned retries = 1000; - u16 cmd; - - /* Disable Tx and Rx */ - cmd = xm_read16(hw, port, XM_MMU_CMD); - cmd &= ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX); - xm_write16(hw, port, XM_MMU_CMD, cmd); - - genesis_reset(hw, port); - - /* Clear Tx packet arbiter timeout IRQ */ - skge_write16(hw, B3_PA_CTRL, - port == 0 ? PA_CLR_TO_TX1 : PA_CLR_TO_TX2); - - /* Reset the MAC */ - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_CLR_MAC_RST); - do { - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), MFF_SET_MAC_RST); - if (!(skge_read16(hw, SK_REG(port, TX_MFF_CTRL1)) & MFF_SET_MAC_RST)) - break; - } while (--retries > 0); - - /* For external PHYs there must be special handling */ - if (hw->phy_type != SK_PHY_XMAC) { - u32 reg = skge_read32(hw, B2_GP_IO); - if (port == 0) { - reg |= GP_DIR_0; - reg &= ~GP_IO_0; - } else { - reg |= GP_DIR_2; - reg &= ~GP_IO_2; - } - skge_write32(hw, B2_GP_IO, reg); - skge_read32(hw, B2_GP_IO); - } - - xm_write16(hw, port, XM_MMU_CMD, - xm_read16(hw, port, XM_MMU_CMD) - & ~(XM_MMU_ENA_RX | XM_MMU_ENA_TX)); - - xm_read16(hw, port, XM_MMU_CMD); -} - - -static void genesis_get_stats(struct skge_port *skge, u64 *data) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - int i; - unsigned long timeout = jiffies + HZ; - - xm_write16(hw, port, - XM_STAT_CMD, XM_SC_SNP_TXC | XM_SC_SNP_RXC); - - /* wait for update to complete */ - while (xm_read16(hw, port, XM_STAT_CMD) - & (XM_SC_SNP_TXC | XM_SC_SNP_RXC)) { - if (time_after(jiffies, timeout)) - break; - udelay(10); - } - - /* special case for 64 bit octet counter */ - data[0] = (u64) xm_read32(hw, port, XM_TXO_OK_HI) << 32 - | xm_read32(hw, port, XM_TXO_OK_LO); - data[1] = (u64) xm_read32(hw, port, XM_RXO_OK_HI) << 32 - | xm_read32(hw, port, XM_RXO_OK_LO); - - for (i = 2; i < ARRAY_SIZE(skge_stats); i++) - data[i] = xm_read32(hw, port, skge_stats[i].xmac_offset); -} - -static void genesis_mac_intr(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); - u16 status = xm_read16(hw, port, XM_ISRC); - - netif_printk(skge, intr, KERN_DEBUG, skge->netdev, - "mac interrupt status 0x%x\n", status); - - if (hw->phy_type == SK_PHY_XMAC && (status & XM_IS_INP_ASS)) { - xm_link_down(hw, port); - mod_timer(&skge->link_timer, jiffies + 1); - } - - if (status & XM_IS_TXF_UR) { - xm_write32(hw, port, XM_MODE, XM_MD_FTF); - ++dev->stats.tx_fifo_errors; - } -} - -static void genesis_link_up(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 cmd, msk; - u32 mode; - - cmd = xm_read16(hw, port, XM_MMU_CMD); - - /* - * enabling pause frame reception is required for 1000BT - * because the XMAC is not reset if the link is going down - */ - if (skge->flow_status == FLOW_STAT_NONE || - skge->flow_status == FLOW_STAT_LOC_SEND) - /* Disable Pause Frame Reception */ - cmd |= XM_MMU_IGN_PF; - else - /* Enable Pause Frame Reception */ - cmd &= ~XM_MMU_IGN_PF; - - xm_write16(hw, port, XM_MMU_CMD, cmd); - - mode = xm_read32(hw, port, XM_MODE); - if (skge->flow_status == FLOW_STAT_SYMMETRIC || - skge->flow_status == FLOW_STAT_LOC_SEND) { - /* - * Configure Pause Frame Generation - * Use internal and external Pause Frame Generation. - * Sending pause frames is edge triggered. - * Send a Pause frame with the maximum pause time if - * internal oder external FIFO full condition occurs. - * Send a zero pause time frame to re-start transmission. - */ - /* XM_PAUSE_DA = '010000C28001' (default) */ - /* XM_MAC_PTIME = 0xffff (maximum) */ - /* remember this value is defined in big endian (!) */ - xm_write16(hw, port, XM_MAC_PTIME, 0xffff); - - mode |= XM_PAUSE_MODE; - skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_ENA_PAUSE); - } else { - /* - * disable pause frame generation is required for 1000BT - * because the XMAC is not reset if the link is going down - */ - /* Disable Pause Mode in Mode Register */ - mode &= ~XM_PAUSE_MODE; - - skge_write16(hw, SK_REG(port, RX_MFF_CTRL1), MFF_DIS_PAUSE); - } - - xm_write32(hw, port, XM_MODE, mode); - - /* Turn on detection of Tx underrun */ - msk = xm_read16(hw, port, XM_IMSK); - msk &= ~XM_IS_TXF_UR; - xm_write16(hw, port, XM_IMSK, msk); - - xm_read16(hw, port, XM_ISRC); - - /* get MMU Command Reg. */ - cmd = xm_read16(hw, port, XM_MMU_CMD); - if (hw->phy_type != SK_PHY_XMAC && skge->duplex == DUPLEX_FULL) - cmd |= XM_MMU_GMII_FD; - - /* - * Workaround BCOM Errata (#10523) for all BCom Phys - * Enable Power Management after link up - */ - if (hw->phy_type == SK_PHY_BCOM) { - xm_phy_write(hw, port, PHY_BCOM_AUX_CTRL, - xm_phy_read(hw, port, PHY_BCOM_AUX_CTRL) - & ~PHY_B_AC_DIS_PM); - xm_phy_write(hw, port, PHY_BCOM_INT_MASK, PHY_B_DEF_MSK); - } - - /* enable Rx/Tx */ - xm_write16(hw, port, XM_MMU_CMD, - cmd | XM_MMU_ENA_RX | XM_MMU_ENA_TX); - skge_link_up(skge); -} - - -static inline void bcom_phy_intr(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 isrc; - - isrc = xm_phy_read(hw, port, PHY_BCOM_INT_STAT); - netif_printk(skge, intr, KERN_DEBUG, skge->netdev, - "phy interrupt status 0x%x\n", isrc); - - if (isrc & PHY_B_IS_PSE) - pr_err("%s: uncorrectable pair swap error\n", - hw->dev[port]->name); - - /* Workaround BCom Errata: - * enable and disable loopback mode if "NO HCD" occurs. - */ - if (isrc & PHY_B_IS_NO_HDCL) { - u16 ctrl = xm_phy_read(hw, port, PHY_BCOM_CTRL); - xm_phy_write(hw, port, PHY_BCOM_CTRL, - ctrl | PHY_CT_LOOP); - xm_phy_write(hw, port, PHY_BCOM_CTRL, - ctrl & ~PHY_CT_LOOP); - } - - if (isrc & (PHY_B_IS_AN_PR | PHY_B_IS_LST_CHANGE)) - bcom_check_link(hw, port); - -} - -static int gm_phy_write(struct skge_hw *hw, int port, u16 reg, u16 val) -{ - int i; - - gma_write16(hw, port, GM_SMI_DATA, val); - gma_write16(hw, port, GM_SMI_CTRL, - GM_SMI_CT_PHY_AD(hw->phy_addr) | GM_SMI_CT_REG_AD(reg)); - for (i = 0; i < PHY_RETRIES; i++) { - udelay(1); - - if (!(gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_BUSY)) - return 0; - } - - pr_warn("%s: phy write timeout\n", hw->dev[port]->name); - return -EIO; -} - -static int __gm_phy_read(struct skge_hw *hw, int port, u16 reg, u16 *val) -{ - int i; - - gma_write16(hw, port, GM_SMI_CTRL, - GM_SMI_CT_PHY_AD(hw->phy_addr) - | GM_SMI_CT_REG_AD(reg) | GM_SMI_CT_OP_RD); - - for (i = 0; i < PHY_RETRIES; i++) { - udelay(1); - if (gma_read16(hw, port, GM_SMI_CTRL) & GM_SMI_CT_RD_VAL) - goto ready; - } - - return -ETIMEDOUT; - ready: - *val = gma_read16(hw, port, GM_SMI_DATA); - return 0; -} - -static u16 gm_phy_read(struct skge_hw *hw, int port, u16 reg) -{ - u16 v = 0; - if (__gm_phy_read(hw, port, reg, &v)) - pr_warn("%s: phy read timeout\n", hw->dev[port]->name); - return v; -} - -/* Marvell Phy Initialization */ -static void yukon_init(struct skge_hw *hw, int port) -{ - struct skge_port *skge = netdev_priv(hw->dev[port]); - u16 ctrl, ct1000, adv; - - if (skge->autoneg == AUTONEG_ENABLE) { - u16 ectrl = gm_phy_read(hw, port, PHY_MARV_EXT_CTRL); - - ectrl &= ~(PHY_M_EC_M_DSC_MSK | PHY_M_EC_S_DSC_MSK | - PHY_M_EC_MAC_S_MSK); - ectrl |= PHY_M_EC_MAC_S(MAC_TX_CLK_25_MHZ); - - ectrl |= PHY_M_EC_M_DSC(0) | PHY_M_EC_S_DSC(1); - - gm_phy_write(hw, port, PHY_MARV_EXT_CTRL, ectrl); - } - - ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); - if (skge->autoneg == AUTONEG_DISABLE) - ctrl &= ~PHY_CT_ANE; - - ctrl |= PHY_CT_RESET; - gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); - - ctrl = 0; - ct1000 = 0; - adv = PHY_AN_CSMA; - - if (skge->autoneg == AUTONEG_ENABLE) { - if (hw->copper) { - if (skge->advertising & ADVERTISED_1000baseT_Full) - ct1000 |= PHY_M_1000C_AFD; - if (skge->advertising & ADVERTISED_1000baseT_Half) - ct1000 |= PHY_M_1000C_AHD; - if (skge->advertising & ADVERTISED_100baseT_Full) - adv |= PHY_M_AN_100_FD; - if (skge->advertising & ADVERTISED_100baseT_Half) - adv |= PHY_M_AN_100_HD; - if (skge->advertising & ADVERTISED_10baseT_Full) - adv |= PHY_M_AN_10_FD; - if (skge->advertising & ADVERTISED_10baseT_Half) - adv |= PHY_M_AN_10_HD; - - /* Set Flow-control capabilities */ - adv |= phy_pause_map[skge->flow_control]; - } else { - if (skge->advertising & ADVERTISED_1000baseT_Full) - adv |= PHY_M_AN_1000X_AFD; - if (skge->advertising & ADVERTISED_1000baseT_Half) - adv |= PHY_M_AN_1000X_AHD; - - adv |= fiber_pause_map[skge->flow_control]; - } - - /* Restart Auto-negotiation */ - ctrl |= PHY_CT_ANE | PHY_CT_RE_CFG; - } else { - /* forced speed/duplex settings */ - ct1000 = PHY_M_1000C_MSE; - - if (skge->duplex == DUPLEX_FULL) - ctrl |= PHY_CT_DUP_MD; - - switch (skge->speed) { - case SPEED_1000: - ctrl |= PHY_CT_SP1000; - break; - case SPEED_100: - ctrl |= PHY_CT_SP100; - break; - } - - ctrl |= PHY_CT_RESET; - } - - gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); - - gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); - gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); - - /* Enable phy interrupt on autonegotiation complete (or link up) */ - if (skge->autoneg == AUTONEG_ENABLE) - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_MSK); - else - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); -} - -static void yukon_reset(struct skge_hw *hw, int port) -{ - gm_phy_write(hw, port, PHY_MARV_INT_MASK, 0);/* disable PHY IRQs */ - gma_write16(hw, port, GM_MC_ADDR_H1, 0); /* clear MC hash */ - gma_write16(hw, port, GM_MC_ADDR_H2, 0); - gma_write16(hw, port, GM_MC_ADDR_H3, 0); - gma_write16(hw, port, GM_MC_ADDR_H4, 0); - - gma_write16(hw, port, GM_RX_CTRL, - gma_read16(hw, port, GM_RX_CTRL) - | GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); -} - -/* Apparently, early versions of Yukon-Lite had wrong chip_id? */ -static int is_yukon_lite_a0(struct skge_hw *hw) -{ - u32 reg; - int ret; - - if (hw->chip_id != CHIP_ID_YUKON) - return 0; - - reg = skge_read32(hw, B2_FAR); - skge_write8(hw, B2_FAR + 3, 0xff); - ret = (skge_read8(hw, B2_FAR + 3) != 0); - skge_write32(hw, B2_FAR, reg); - return ret; -} - -static void yukon_mac_init(struct skge_hw *hw, int port) -{ - struct skge_port *skge = netdev_priv(hw->dev[port]); - int i; - u32 reg; - const u8 *addr = hw->dev[port]->dev_addr; - - /* WA code for COMA mode -- set PHY reset */ - if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev >= CHIP_REV_YU_LITE_A3) { - reg = skge_read32(hw, B2_GP_IO); - reg |= GP_DIR_9 | GP_IO_9; - skge_write32(hw, B2_GP_IO, reg); - } - - /* hard reset */ - skge_write32(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); - skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); - - /* WA code for COMA mode -- clear PHY reset */ - if (hw->chip_id == CHIP_ID_YUKON_LITE && - hw->chip_rev >= CHIP_REV_YU_LITE_A3) { - reg = skge_read32(hw, B2_GP_IO); - reg |= GP_DIR_9; - reg &= ~GP_IO_9; - skge_write32(hw, B2_GP_IO, reg); - } - - /* Set hardware config mode */ - reg = GPC_INT_POL_HI | GPC_DIS_FC | GPC_DIS_SLEEP | - GPC_ENA_XC | GPC_ANEG_ADV_ALL_M | GPC_ENA_PAUSE; - reg |= hw->copper ? GPC_HWCFG_GMII_COP : GPC_HWCFG_GMII_FIB; - - /* Clear GMC reset */ - skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_SET); - skge_write32(hw, SK_REG(port, GPHY_CTRL), reg | GPC_RST_CLR); - skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON | GMC_RST_CLR); - - if (skge->autoneg == AUTONEG_DISABLE) { - reg = GM_GPCR_AU_ALL_DIS; - gma_write16(hw, port, GM_GP_CTRL, - gma_read16(hw, port, GM_GP_CTRL) | reg); - - switch (skge->speed) { - case SPEED_1000: - reg &= ~GM_GPCR_SPEED_100; - reg |= GM_GPCR_SPEED_1000; - break; - case SPEED_100: - reg &= ~GM_GPCR_SPEED_1000; - reg |= GM_GPCR_SPEED_100; - break; - case SPEED_10: - reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100); - break; - } - - if (skge->duplex == DUPLEX_FULL) - reg |= GM_GPCR_DUP_FULL; - } else - reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL; - - switch (skge->flow_control) { - case FLOW_MODE_NONE: - skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); - reg |= GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; - break; - case FLOW_MODE_LOC_SEND: - /* disable Rx flow-control */ - reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; - break; - case FLOW_MODE_SYMMETRIC: - case FLOW_MODE_SYM_OR_REM: - /* enable Tx & Rx flow-control */ - break; - } - - gma_write16(hw, port, GM_GP_CTRL, reg); - skge_read16(hw, SK_REG(port, GMAC_IRQ_SRC)); - - yukon_init(hw, port); - - /* MIB clear */ - reg = gma_read16(hw, port, GM_PHY_ADDR); - gma_write16(hw, port, GM_PHY_ADDR, reg | GM_PAR_MIB_CLR); - - for (i = 0; i < GM_MIB_CNT_SIZE; i++) - gma_read16(hw, port, GM_MIB_CNT_BASE + 8*i); - gma_write16(hw, port, GM_PHY_ADDR, reg); - - /* transmit control */ - gma_write16(hw, port, GM_TX_CTRL, TX_COL_THR(TX_COL_DEF)); - - /* receive control reg: unicast + multicast + no FCS */ - gma_write16(hw, port, GM_RX_CTRL, - GM_RXCR_UCF_ENA | GM_RXCR_CRC_DIS | GM_RXCR_MCF_ENA); - - /* transmit flow control */ - gma_write16(hw, port, GM_TX_FLOW_CTRL, 0xffff); - - /* transmit parameter */ - gma_write16(hw, port, GM_TX_PARAM, - TX_JAM_LEN_VAL(TX_JAM_LEN_DEF) | - TX_JAM_IPG_VAL(TX_JAM_IPG_DEF) | - TX_IPG_JAM_DATA(TX_IPG_JAM_DEF)); - - /* configure the Serial Mode Register */ - reg = DATA_BLIND_VAL(DATA_BLIND_DEF) - | GM_SMOD_VLAN_ENA - | IPG_DATA_VAL(IPG_DATA_DEF); - - if (hw->dev[port]->mtu > ETH_DATA_LEN) - reg |= GM_SMOD_JUMBO_ENA; - - gma_write16(hw, port, GM_SERIAL_MODE, reg); - - /* physical address: used for pause frames */ - gma_set_addr(hw, port, GM_SRC_ADDR_1L, addr); - /* virtual address for data */ - gma_set_addr(hw, port, GM_SRC_ADDR_2L, addr); - - /* enable interrupt mask for counter overflows */ - gma_write16(hw, port, GM_TX_IRQ_MSK, 0); - gma_write16(hw, port, GM_RX_IRQ_MSK, 0); - gma_write16(hw, port, GM_TR_IRQ_MSK, 0); - - /* Initialize Mac Fifo */ - - /* Configure Rx MAC FIFO */ - skge_write16(hw, SK_REG(port, RX_GMF_FL_MSK), RX_FF_FL_DEF_MSK); - reg = GMF_OPER_ON | GMF_RX_F_FL_ON; - - /* disable Rx GMAC FIFO Flush for YUKON-Lite Rev. A0 only */ - if (is_yukon_lite_a0(hw)) - reg &= ~GMF_RX_F_FL_ON; - - skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); - skge_write16(hw, SK_REG(port, RX_GMF_CTRL_T), reg); - /* - * because Pause Packet Truncation in GMAC is not working - * we have to increase the Flush Threshold to 64 bytes - * in order to flush pause packets in Rx FIFO on Yukon-1 - */ - skge_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1); - - /* Configure Tx MAC FIFO */ - skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); - skge_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON); -} - -/* Go into power down mode */ -static void yukon_suspend(struct skge_hw *hw, int port) -{ - u16 ctrl; - - ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); - ctrl |= PHY_M_PC_POL_R_DIS; - gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); - - ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); - ctrl |= PHY_CT_RESET; - gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); - - /* switch IEEE compatible power down mode on */ - ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); - ctrl |= PHY_CT_PDOWN; - gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); -} - -static void yukon_stop(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - - skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), 0); - yukon_reset(hw, port); - - gma_write16(hw, port, GM_GP_CTRL, - gma_read16(hw, port, GM_GP_CTRL) - & ~(GM_GPCR_TX_ENA|GM_GPCR_RX_ENA)); - gma_read16(hw, port, GM_GP_CTRL); - - yukon_suspend(hw, port); - - /* set GPHY Control reset */ - skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_SET); - skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_SET); -} - -static void yukon_get_stats(struct skge_port *skge, u64 *data) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - int i; - - data[0] = (u64) gma_read32(hw, port, GM_TXO_OK_HI) << 32 - | gma_read32(hw, port, GM_TXO_OK_LO); - data[1] = (u64) gma_read32(hw, port, GM_RXO_OK_HI) << 32 - | gma_read32(hw, port, GM_RXO_OK_LO); - - for (i = 2; i < ARRAY_SIZE(skge_stats); i++) - data[i] = gma_read32(hw, port, - skge_stats[i].gma_offset); -} - -static void yukon_mac_intr(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - struct skge_port *skge = netdev_priv(dev); - u8 status = skge_read8(hw, SK_REG(port, GMAC_IRQ_SRC)); - - netif_printk(skge, intr, KERN_DEBUG, skge->netdev, - "mac interrupt status 0x%x\n", status); - - if (status & GM_IS_RX_FF_OR) { - ++dev->stats.rx_fifo_errors; - skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_CLI_RX_FO); - } - - if (status & GM_IS_TX_FF_UR) { - ++dev->stats.tx_fifo_errors; - skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_CLI_TX_FU); - } - -} - -static u16 yukon_speed(const struct skge_hw *hw, u16 aux) -{ - switch (aux & PHY_M_PS_SPEED_MSK) { - case PHY_M_PS_SPEED_1000: - return SPEED_1000; - case PHY_M_PS_SPEED_100: - return SPEED_100; - default: - return SPEED_10; - } -} - -static void yukon_link_up(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 reg; - - /* Enable Transmit FIFO Underrun */ - skge_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK); - - reg = gma_read16(hw, port, GM_GP_CTRL); - if (skge->duplex == DUPLEX_FULL || skge->autoneg == AUTONEG_ENABLE) - reg |= GM_GPCR_DUP_FULL; - - /* enable Rx/Tx */ - reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; - gma_write16(hw, port, GM_GP_CTRL, reg); - - gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_DEF_MSK); - skge_link_up(skge); -} - -static void yukon_link_down(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - u16 ctrl; - - ctrl = gma_read16(hw, port, GM_GP_CTRL); - ctrl &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); - gma_write16(hw, port, GM_GP_CTRL, ctrl); - - if (skge->flow_status == FLOW_STAT_REM_SEND) { - ctrl = gm_phy_read(hw, port, PHY_MARV_AUNE_ADV); - ctrl |= PHY_M_AN_ASP; - /* restore Asymmetric Pause bit */ - gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, ctrl); - } - - skge_link_down(skge); - - yukon_init(hw, port); -} - -static void yukon_phy_intr(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - const char *reason = NULL; - u16 istatus, phystat; - - istatus = gm_phy_read(hw, port, PHY_MARV_INT_STAT); - phystat = gm_phy_read(hw, port, PHY_MARV_PHY_STAT); - - netif_printk(skge, intr, KERN_DEBUG, skge->netdev, - "phy interrupt status 0x%x 0x%x\n", istatus, phystat); - - if (istatus & PHY_M_IS_AN_COMPL) { - if (gm_phy_read(hw, port, PHY_MARV_AUNE_LP) - & PHY_M_AN_RF) { - reason = "remote fault"; - goto failed; - } - - if (gm_phy_read(hw, port, PHY_MARV_1000T_STAT) & PHY_B_1000S_MSF) { - reason = "master/slave fault"; - goto failed; - } - - if (!(phystat & PHY_M_PS_SPDUP_RES)) { - reason = "speed/duplex"; - goto failed; - } - - skge->duplex = (phystat & PHY_M_PS_FULL_DUP) - ? DUPLEX_FULL : DUPLEX_HALF; - skge->speed = yukon_speed(hw, phystat); - - /* We are using IEEE 802.3z/D5.0 Table 37-4 */ - switch (phystat & PHY_M_PS_PAUSE_MSK) { - case PHY_M_PS_PAUSE_MSK: - skge->flow_status = FLOW_STAT_SYMMETRIC; - break; - case PHY_M_PS_RX_P_EN: - skge->flow_status = FLOW_STAT_REM_SEND; - break; - case PHY_M_PS_TX_P_EN: - skge->flow_status = FLOW_STAT_LOC_SEND; - break; - default: - skge->flow_status = FLOW_STAT_NONE; - } - - if (skge->flow_status == FLOW_STAT_NONE || - (skge->speed < SPEED_1000 && skge->duplex == DUPLEX_HALF)) - skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); - else - skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); - yukon_link_up(skge); - return; - } - - if (istatus & PHY_M_IS_LSP_CHANGE) - skge->speed = yukon_speed(hw, phystat); - - if (istatus & PHY_M_IS_DUP_CHANGE) - skge->duplex = (phystat & PHY_M_PS_FULL_DUP) ? DUPLEX_FULL : DUPLEX_HALF; - if (istatus & PHY_M_IS_LST_CHANGE) { - if (phystat & PHY_M_PS_LINK_UP) - yukon_link_up(skge); - else - yukon_link_down(skge); - } - return; - failed: - pr_err("%s: autonegotiation failed (%s)\n", skge->netdev->name, reason); - - /* XXX restart autonegotiation? */ -} - -static void skge_phy_reset(struct skge_port *skge) -{ - struct skge_hw *hw = skge->hw; - int port = skge->port; - struct net_device *dev = hw->dev[port]; - - netif_stop_queue(skge->netdev); - netif_carrier_off(skge->netdev); - - spin_lock_bh(&hw->phy_lock); - if (is_genesis(hw)) { - genesis_reset(hw, port); - genesis_mac_init(hw, port); - } else { - yukon_reset(hw, port); - yukon_init(hw, port); - } - spin_unlock_bh(&hw->phy_lock); - - skge_set_multicast(dev); -} - -/* Basic MII support */ -static int skge_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) -{ - struct mii_ioctl_data *data = if_mii(ifr); - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int err = -EOPNOTSUPP; - - if (!netif_running(dev)) - return -ENODEV; /* Phy still in reset */ - - switch (cmd) { - case SIOCGMIIPHY: - data->phy_id = hw->phy_addr; - - /* fallthru */ - case SIOCGMIIREG: { - u16 val = 0; - spin_lock_bh(&hw->phy_lock); - - if (is_genesis(hw)) - err = __xm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); - else - err = __gm_phy_read(hw, skge->port, data->reg_num & 0x1f, &val); - spin_unlock_bh(&hw->phy_lock); - data->val_out = val; - break; - } - - case SIOCSMIIREG: - spin_lock_bh(&hw->phy_lock); - if (is_genesis(hw)) - err = xm_phy_write(hw, skge->port, data->reg_num & 0x1f, - data->val_in); - else - err = gm_phy_write(hw, skge->port, data->reg_num & 0x1f, - data->val_in); - spin_unlock_bh(&hw->phy_lock); - break; - } - return err; -} - -static void skge_ramset(struct skge_hw *hw, u16 q, u32 start, size_t len) -{ - u32 end; - - start /= 8; - len /= 8; - end = start + len - 1; - - skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_RST_CLR); - skge_write32(hw, RB_ADDR(q, RB_START), start); - skge_write32(hw, RB_ADDR(q, RB_WP), start); - skge_write32(hw, RB_ADDR(q, RB_RP), start); - skge_write32(hw, RB_ADDR(q, RB_END), end); - - if (q == Q_R1 || q == Q_R2) { - /* Set thresholds on receive queue's */ - skge_write32(hw, RB_ADDR(q, RB_RX_UTPP), - start + (2*len)/3); - skge_write32(hw, RB_ADDR(q, RB_RX_LTPP), - start + (len/3)); - } else { - /* Enable store & forward on Tx queue's because - * Tx FIFO is only 4K on Genesis and 1K on Yukon - */ - skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_STFWD); - } - - skge_write8(hw, RB_ADDR(q, RB_CTRL), RB_ENA_OP_MD); -} - -/* Setup Bus Memory Interface */ -static void skge_qset(struct skge_port *skge, u16 q, - const struct skge_element *e) -{ - struct skge_hw *hw = skge->hw; - u32 watermark = 0x600; - u64 base = skge->dma + (e->desc - skge->mem); - - /* optimization to reduce window on 32bit/33mhz */ - if ((skge_read16(hw, B0_CTST) & (CS_BUS_CLOCK | CS_BUS_SLOT_SZ)) == 0) - watermark /= 2; - - skge_write32(hw, Q_ADDR(q, Q_CSR), CSR_CLR_RESET); - skge_write32(hw, Q_ADDR(q, Q_F), watermark); - skge_write32(hw, Q_ADDR(q, Q_DA_H), (u32)(base >> 32)); - skge_write32(hw, Q_ADDR(q, Q_DA_L), (u32)base); -} - -static int skge_up(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - u32 chunk, ram_addr; - size_t rx_size, tx_size; - int err; - - if (!is_valid_ether_addr(dev->dev_addr)) - return -EINVAL; - - netif_info(skge, ifup, skge->netdev, "enabling interface\n"); - - if (dev->mtu > RX_BUF_SIZE) - skge->rx_buf_size = dev->mtu + ETH_HLEN; - else - skge->rx_buf_size = RX_BUF_SIZE; - - - rx_size = skge->rx_ring.count * sizeof(struct skge_rx_desc); - tx_size = skge->tx_ring.count * sizeof(struct skge_tx_desc); - skge->mem_size = tx_size + rx_size; - skge->mem = pci_alloc_consistent(hw->pdev, skge->mem_size, &skge->dma); - if (!skge->mem) - return -ENOMEM; - - BUG_ON(skge->dma & 7); - - if (upper_32_bits(skge->dma) != upper_32_bits(skge->dma + skge->mem_size)) { - dev_err(&hw->pdev->dev, "pci_alloc_consistent region crosses 4G boundary\n"); - err = -EINVAL; - goto free_pci_mem; - } - - memset(skge->mem, 0, skge->mem_size); - - err = skge_ring_alloc(&skge->rx_ring, skge->mem, skge->dma); - if (err) - goto free_pci_mem; - - err = skge_rx_fill(dev); - if (err) - goto free_rx_ring; - - err = skge_ring_alloc(&skge->tx_ring, skge->mem + rx_size, - skge->dma + rx_size); - if (err) - goto free_rx_ring; - - if (hw->ports == 1) { - err = request_irq(hw->pdev->irq, skge_intr, IRQF_SHARED, - dev->name, hw); - if (err) { - netdev_err(dev, "Unable to allocate interrupt %d error: %d\n", - hw->pdev->irq, err); - goto free_tx_ring; - } - } - - /* Initialize MAC */ - netif_carrier_off(dev); - spin_lock_bh(&hw->phy_lock); - if (is_genesis(hw)) - genesis_mac_init(hw, port); - else - yukon_mac_init(hw, port); - spin_unlock_bh(&hw->phy_lock); - - /* Configure RAMbuffers - equally between ports and tx/rx */ - chunk = (hw->ram_size - hw->ram_offset) / (hw->ports * 2); - ram_addr = hw->ram_offset + 2 * chunk * port; - - skge_ramset(hw, rxqaddr[port], ram_addr, chunk); - skge_qset(skge, rxqaddr[port], skge->rx_ring.to_clean); - - BUG_ON(skge->tx_ring.to_use != skge->tx_ring.to_clean); - skge_ramset(hw, txqaddr[port], ram_addr+chunk, chunk); - skge_qset(skge, txqaddr[port], skge->tx_ring.to_use); - - /* Start receiver BMU */ - wmb(); - skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_START | CSR_IRQ_CL_F); - skge_led(skge, LED_MODE_ON); - - spin_lock_irq(&hw->hw_lock); - hw->intr_mask |= portmask[port]; - skge_write32(hw, B0_IMSK, hw->intr_mask); - skge_read32(hw, B0_IMSK); - spin_unlock_irq(&hw->hw_lock); - - napi_enable(&skge->napi); - - skge_set_multicast(dev); - - return 0; - - free_tx_ring: - kfree(skge->tx_ring.start); - free_rx_ring: - skge_rx_clean(skge); - kfree(skge->rx_ring.start); - free_pci_mem: - pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma); - skge->mem = NULL; - - return err; -} - -/* stop receiver */ -static void skge_rx_stop(struct skge_hw *hw, int port) -{ - skge_write8(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_STOP); - skge_write32(hw, RB_ADDR(port ? Q_R2 : Q_R1, RB_CTRL), - RB_RST_SET|RB_DIS_OP_MD); - skge_write32(hw, Q_ADDR(rxqaddr[port], Q_CSR), CSR_SET_RESET); -} - -static int skge_down(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - - if (skge->mem == NULL) - return 0; - - netif_info(skge, ifdown, skge->netdev, "disabling interface\n"); - - netif_tx_disable(dev); - - if (is_genesis(hw) && hw->phy_type == SK_PHY_XMAC) - del_timer_sync(&skge->link_timer); - - napi_disable(&skge->napi); - netif_carrier_off(dev); - - spin_lock_irq(&hw->hw_lock); - hw->intr_mask &= ~portmask[port]; - skge_write32(hw, B0_IMSK, (hw->ports == 1) ? 0 : hw->intr_mask); - skge_read32(hw, B0_IMSK); - spin_unlock_irq(&hw->hw_lock); - - if (hw->ports == 1) - free_irq(hw->pdev->irq, hw); - - skge_write8(skge->hw, SK_REG(skge->port, LNK_LED_REG), LED_OFF); - if (is_genesis(hw)) - genesis_stop(skge); - else - yukon_stop(skge); - - /* Stop transmitter */ - skge_write8(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_STOP); - skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), - RB_RST_SET|RB_DIS_OP_MD); - - - /* Disable Force Sync bit and Enable Alloc bit */ - skge_write8(hw, SK_REG(port, TXA_CTRL), - TXA_DIS_FSYNC | TXA_DIS_ALLOC | TXA_STOP_RC); - - /* Stop Interval Timer and Limit Counter of Tx Arbiter */ - skge_write32(hw, SK_REG(port, TXA_ITI_INI), 0L); - skge_write32(hw, SK_REG(port, TXA_LIM_INI), 0L); - - /* Reset PCI FIFO */ - skge_write32(hw, Q_ADDR(txqaddr[port], Q_CSR), CSR_SET_RESET); - skge_write32(hw, RB_ADDR(txqaddr[port], RB_CTRL), RB_RST_SET); - - /* Reset the RAM Buffer async Tx queue */ - skge_write8(hw, RB_ADDR(port == 0 ? Q_XA1 : Q_XA2, RB_CTRL), RB_RST_SET); - - skge_rx_stop(hw, port); - - if (is_genesis(hw)) { - skge_write8(hw, SK_REG(port, TX_MFF_CTRL2), MFF_RST_SET); - skge_write8(hw, SK_REG(port, RX_MFF_CTRL2), MFF_RST_SET); - } else { - skge_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); - skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); - } - - skge_led(skge, LED_MODE_OFF); - - netif_tx_lock_bh(dev); - skge_tx_clean(dev); - netif_tx_unlock_bh(dev); - - skge_rx_clean(skge); - - kfree(skge->rx_ring.start); - kfree(skge->tx_ring.start); - pci_free_consistent(hw->pdev, skge->mem_size, skge->mem, skge->dma); - skge->mem = NULL; - return 0; -} - -static inline int skge_avail(const struct skge_ring *ring) -{ - smp_mb(); - return ((ring->to_clean > ring->to_use) ? 0 : ring->count) - + (ring->to_clean - ring->to_use) - 1; -} - -static netdev_tx_t skge_xmit_frame(struct sk_buff *skb, - struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - struct skge_element *e; - struct skge_tx_desc *td; - int i; - u32 control, len; - dma_addr_t map; - - if (skb_padto(skb, ETH_ZLEN)) - return NETDEV_TX_OK; - - if (unlikely(skge_avail(&skge->tx_ring) < skb_shinfo(skb)->nr_frags + 1)) - return NETDEV_TX_BUSY; - - e = skge->tx_ring.to_use; - td = e->desc; - BUG_ON(td->control & BMU_OWN); - e->skb = skb; - len = skb_headlen(skb); - map = pci_map_single(hw->pdev, skb->data, len, PCI_DMA_TODEVICE); - if (pci_dma_mapping_error(hw->pdev, map)) - goto mapping_error; - - dma_unmap_addr_set(e, mapaddr, map); - dma_unmap_len_set(e, maplen, len); - - td->dma_lo = lower_32_bits(map); - td->dma_hi = upper_32_bits(map); - - if (skb->ip_summed == CHECKSUM_PARTIAL) { - const int offset = skb_checksum_start_offset(skb); - - /* This seems backwards, but it is what the sk98lin - * does. Looks like hardware is wrong? - */ - if (ipip_hdr(skb)->protocol == IPPROTO_UDP && - hw->chip_rev == 0 && hw->chip_id == CHIP_ID_YUKON) - control = BMU_TCP_CHECK; - else - control = BMU_UDP_CHECK; - - td->csum_offs = 0; - td->csum_start = offset; - td->csum_write = offset + skb->csum_offset; - } else - control = BMU_CHECK; - - if (!skb_shinfo(skb)->nr_frags) /* single buffer i.e. no fragments */ - control |= BMU_EOF | BMU_IRQ_EOF; - else { - struct skge_tx_desc *tf = td; - - control |= BMU_STFWD; - for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { - const skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; - - map = skb_frag_dma_map(&hw->pdev->dev, frag, 0, - skb_frag_size(frag), DMA_TO_DEVICE); - if (dma_mapping_error(&hw->pdev->dev, map)) - goto mapping_unwind; - - e = e->next; - e->skb = skb; - tf = e->desc; - BUG_ON(tf->control & BMU_OWN); - - tf->dma_lo = lower_32_bits(map); - tf->dma_hi = upper_32_bits(map); - dma_unmap_addr_set(e, mapaddr, map); - dma_unmap_len_set(e, maplen, skb_frag_size(frag)); - - tf->control = BMU_OWN | BMU_SW | control | skb_frag_size(frag); - } - tf->control |= BMU_EOF | BMU_IRQ_EOF; - } - /* Make sure all the descriptors written */ - wmb(); - td->control = BMU_OWN | BMU_SW | BMU_STF | control | len; - wmb(); - - netdev_sent_queue(dev, skb->len); - - skge_write8(hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_START); - - netif_printk(skge, tx_queued, KERN_DEBUG, skge->netdev, - "tx queued, slot %td, len %d\n", - e - skge->tx_ring.start, skb->len); - - skge->tx_ring.to_use = e->next; - smp_wmb(); - - if (skge_avail(&skge->tx_ring) <= TX_LOW_WATER) { - netdev_dbg(dev, "transmit queue full\n"); - netif_stop_queue(dev); - } - - return NETDEV_TX_OK; - -mapping_unwind: - e = skge->tx_ring.to_use; - pci_unmap_single(hw->pdev, - dma_unmap_addr(e, mapaddr), - dma_unmap_len(e, maplen), - PCI_DMA_TODEVICE); - while (i-- > 0) { - e = e->next; - pci_unmap_page(hw->pdev, - dma_unmap_addr(e, mapaddr), - dma_unmap_len(e, maplen), - PCI_DMA_TODEVICE); - } - -mapping_error: - if (net_ratelimit()) - dev_warn(&hw->pdev->dev, "%s: tx mapping error\n", dev->name); - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; -} - - -/* Free resources associated with this reing element */ -static inline void skge_tx_unmap(struct pci_dev *pdev, struct skge_element *e, - u32 control) -{ - /* skb header vs. fragment */ - if (control & BMU_STF) - pci_unmap_single(pdev, dma_unmap_addr(e, mapaddr), - dma_unmap_len(e, maplen), - PCI_DMA_TODEVICE); - else - pci_unmap_page(pdev, dma_unmap_addr(e, mapaddr), - dma_unmap_len(e, maplen), - PCI_DMA_TODEVICE); -} - -/* Free all buffers in transmit ring */ -static void skge_tx_clean(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_element *e; - - for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { - struct skge_tx_desc *td = e->desc; - - skge_tx_unmap(skge->hw->pdev, e, td->control); - - if (td->control & BMU_EOF) - dev_kfree_skb(e->skb); - td->control = 0; - } - - netdev_reset_queue(dev); - skge->tx_ring.to_clean = e; -} - -static void skge_tx_timeout(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - - netif_printk(skge, timer, KERN_DEBUG, skge->netdev, "tx timeout\n"); - - skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_STOP); - skge_tx_clean(dev); - netif_wake_queue(dev); -} - -static int skge_change_mtu(struct net_device *dev, int new_mtu) -{ - int err; - - if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) - return -EINVAL; - - if (!netif_running(dev)) { - dev->mtu = new_mtu; - return 0; - } - - skge_down(dev); - - dev->mtu = new_mtu; - - err = skge_up(dev); - if (err) - dev_close(dev); - - return err; -} - -static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 }; - -static void genesis_add_filter(u8 filter[8], const u8 *addr) -{ - u32 crc, bit; - - crc = ether_crc_le(ETH_ALEN, addr); - bit = ~crc & 0x3f; - filter[bit/8] |= 1 << (bit%8); -} - -static void genesis_set_multicast(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - struct netdev_hw_addr *ha; - u32 mode; - u8 filter[8]; - - mode = xm_read32(hw, port, XM_MODE); - mode |= XM_MD_ENA_HASH; - if (dev->flags & IFF_PROMISC) - mode |= XM_MD_ENA_PROM; - else - mode &= ~XM_MD_ENA_PROM; - - if (dev->flags & IFF_ALLMULTI) - memset(filter, 0xff, sizeof(filter)); - else { - memset(filter, 0, sizeof(filter)); - - if (skge->flow_status == FLOW_STAT_REM_SEND || - skge->flow_status == FLOW_STAT_SYMMETRIC) - genesis_add_filter(filter, pause_mc_addr); - - netdev_for_each_mc_addr(ha, dev) - genesis_add_filter(filter, ha->addr); - } - - xm_write32(hw, port, XM_MODE, mode); - xm_outhash(hw, port, XM_HSM, filter); -} - -static void yukon_add_filter(u8 filter[8], const u8 *addr) -{ - u32 bit = ether_crc(ETH_ALEN, addr) & 0x3f; - filter[bit/8] |= 1 << (bit%8); -} - -static void yukon_set_multicast(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - int port = skge->port; - struct netdev_hw_addr *ha; - int rx_pause = (skge->flow_status == FLOW_STAT_REM_SEND || - skge->flow_status == FLOW_STAT_SYMMETRIC); - u16 reg; - u8 filter[8]; - - memset(filter, 0, sizeof(filter)); - - reg = gma_read16(hw, port, GM_RX_CTRL); - reg |= GM_RXCR_UCF_ENA; - - if (dev->flags & IFF_PROMISC) /* promiscuous */ - reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); - else if (dev->flags & IFF_ALLMULTI) /* all multicast */ - memset(filter, 0xff, sizeof(filter)); - else if (netdev_mc_empty(dev) && !rx_pause)/* no multicast */ - reg &= ~GM_RXCR_MCF_ENA; - else { - reg |= GM_RXCR_MCF_ENA; - - if (rx_pause) - yukon_add_filter(filter, pause_mc_addr); - - netdev_for_each_mc_addr(ha, dev) - yukon_add_filter(filter, ha->addr); - } - - - gma_write16(hw, port, GM_MC_ADDR_H1, - (u16)filter[0] | ((u16)filter[1] << 8)); - gma_write16(hw, port, GM_MC_ADDR_H2, - (u16)filter[2] | ((u16)filter[3] << 8)); - gma_write16(hw, port, GM_MC_ADDR_H3, - (u16)filter[4] | ((u16)filter[5] << 8)); - gma_write16(hw, port, GM_MC_ADDR_H4, - (u16)filter[6] | ((u16)filter[7] << 8)); - - gma_write16(hw, port, GM_RX_CTRL, reg); -} - -static inline u16 phy_length(const struct skge_hw *hw, u32 status) -{ - if (is_genesis(hw)) - return status >> XMR_FS_LEN_SHIFT; - else - return status >> GMR_FS_LEN_SHIFT; -} - -static inline int bad_phy_status(const struct skge_hw *hw, u32 status) -{ - if (is_genesis(hw)) - return (status & (XMR_FS_ERR | XMR_FS_2L_VLAN)) != 0; - else - return (status & GMR_FS_ANY_ERR) || - (status & GMR_FS_RX_OK) == 0; -} - -static void skge_set_multicast(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - - if (is_genesis(skge->hw)) - genesis_set_multicast(dev); - else - yukon_set_multicast(dev); - -} - - -/* Get receive buffer from descriptor. - * Handles copy of small buffers and reallocation failures - */ -static struct sk_buff *skge_rx_get(struct net_device *dev, - struct skge_element *e, - u32 control, u32 status, u16 csum) -{ - struct skge_port *skge = netdev_priv(dev); - struct sk_buff *skb; - u16 len = control & BMU_BBC; - - netif_printk(skge, rx_status, KERN_DEBUG, skge->netdev, - "rx slot %td status 0x%x len %d\n", - e - skge->rx_ring.start, status, len); - - if (len > skge->rx_buf_size) - goto error; - - if ((control & (BMU_EOF|BMU_STF)) != (BMU_STF|BMU_EOF)) - goto error; - - if (bad_phy_status(skge->hw, status)) - goto error; - - if (phy_length(skge->hw, status) != len) - goto error; - - if (len < RX_COPY_THRESHOLD) { - skb = netdev_alloc_skb_ip_align(dev, len); - if (!skb) - goto resubmit; - - pci_dma_sync_single_for_cpu(skge->hw->pdev, - dma_unmap_addr(e, mapaddr), - dma_unmap_len(e, maplen), - PCI_DMA_FROMDEVICE); - skb_copy_from_linear_data(e->skb, skb->data, len); - pci_dma_sync_single_for_device(skge->hw->pdev, - dma_unmap_addr(e, mapaddr), - dma_unmap_len(e, maplen), - PCI_DMA_FROMDEVICE); - skge_rx_reuse(e, skge->rx_buf_size); - } else { - struct skge_element ee; - struct sk_buff *nskb; - - nskb = netdev_alloc_skb_ip_align(dev, skge->rx_buf_size); - if (!nskb) - goto resubmit; - - ee = *e; - - skb = ee.skb; - prefetch(skb->data); - - if (skge_rx_setup(skge, e, nskb, skge->rx_buf_size) < 0) { - dev_kfree_skb(nskb); - goto resubmit; - } - - pci_unmap_single(skge->hw->pdev, - dma_unmap_addr(&ee, mapaddr), - dma_unmap_len(&ee, maplen), - PCI_DMA_FROMDEVICE); - } - - skb_put(skb, len); - - if (dev->features & NETIF_F_RXCSUM) { - skb->csum = csum; - skb->ip_summed = CHECKSUM_COMPLETE; - } - - skb->protocol = eth_type_trans(skb, dev); - - return skb; -error: - - netif_printk(skge, rx_err, KERN_DEBUG, skge->netdev, - "rx err, slot %td control 0x%x status 0x%x\n", - e - skge->rx_ring.start, control, status); - - if (is_genesis(skge->hw)) { - if (status & (XMR_FS_RUNT|XMR_FS_LNG_ERR)) - dev->stats.rx_length_errors++; - if (status & XMR_FS_FRA_ERR) - dev->stats.rx_frame_errors++; - if (status & XMR_FS_FCS_ERR) - dev->stats.rx_crc_errors++; - } else { - if (status & (GMR_FS_LONG_ERR|GMR_FS_UN_SIZE)) - dev->stats.rx_length_errors++; - if (status & GMR_FS_FRAGMENT) - dev->stats.rx_frame_errors++; - if (status & GMR_FS_CRC_ERR) - dev->stats.rx_crc_errors++; - } - -resubmit: - skge_rx_reuse(e, skge->rx_buf_size); - return NULL; -} - -/* Free all buffers in Tx ring which are no longer owned by device */ -static void skge_tx_done(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_ring *ring = &skge->tx_ring; - struct skge_element *e; - unsigned int bytes_compl = 0, pkts_compl = 0; - - skge_write8(skge->hw, Q_ADDR(txqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); - - for (e = ring->to_clean; e != ring->to_use; e = e->next) { - u32 control = ((const struct skge_tx_desc *) e->desc)->control; - - if (control & BMU_OWN) - break; - - skge_tx_unmap(skge->hw->pdev, e, control); - - if (control & BMU_EOF) { - netif_printk(skge, tx_done, KERN_DEBUG, skge->netdev, - "tx done slot %td\n", - e - skge->tx_ring.start); - - pkts_compl++; - bytes_compl += e->skb->len; - - dev_consume_skb_any(e->skb); - } - } - netdev_completed_queue(dev, pkts_compl, bytes_compl); - skge->tx_ring.to_clean = e; - - /* Can run lockless until we need to synchronize to restart queue. */ - smp_mb(); - - if (unlikely(netif_queue_stopped(dev) && - skge_avail(&skge->tx_ring) > TX_LOW_WATER)) { - netif_tx_lock(dev); - if (unlikely(netif_queue_stopped(dev) && - skge_avail(&skge->tx_ring) > TX_LOW_WATER)) { - netif_wake_queue(dev); - - } - netif_tx_unlock(dev); - } -} - -static int skge_poll(struct napi_struct *napi, int to_do) -{ - struct skge_port *skge = container_of(napi, struct skge_port, napi); - struct net_device *dev = skge->netdev; - struct skge_hw *hw = skge->hw; - struct skge_ring *ring = &skge->rx_ring; - struct skge_element *e; - int work_done = 0; - - skge_tx_done(dev); - - skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_IRQ_CL_F); - - for (e = ring->to_clean; prefetch(e->next), work_done < to_do; e = e->next) { - struct skge_rx_desc *rd = e->desc; - struct sk_buff *skb; - u32 control; - - rmb(); - control = rd->control; - if (control & BMU_OWN) - break; - - skb = skge_rx_get(dev, e, control, rd->status, rd->csum2); - if (likely(skb)) { - napi_gro_receive(napi, skb); - ++work_done; - } - } - ring->to_clean = e; - - /* restart receiver */ - wmb(); - skge_write8(hw, Q_ADDR(rxqaddr[skge->port], Q_CSR), CSR_START); - - if (work_done < to_do) { - unsigned long flags; - - napi_gro_flush(napi, false); - spin_lock_irqsave(&hw->hw_lock, flags); - __napi_complete(napi); - hw->intr_mask |= napimask[skge->port]; - skge_write32(hw, B0_IMSK, hw->intr_mask); - skge_read32(hw, B0_IMSK); - spin_unlock_irqrestore(&hw->hw_lock, flags); - } - - return work_done; -} - -/* Parity errors seem to happen when Genesis is connected to a switch - * with no other ports present. Heartbeat error?? - */ -static void skge_mac_parity(struct skge_hw *hw, int port) -{ - struct net_device *dev = hw->dev[port]; - - ++dev->stats.tx_heartbeat_errors; - - if (is_genesis(hw)) - skge_write16(hw, SK_REG(port, TX_MFF_CTRL1), - MFF_CLR_PERR); - else - /* HW-Bug #8: cleared by GMF_CLI_TX_FC instead of GMF_CLI_TX_PE */ - skge_write8(hw, SK_REG(port, TX_GMF_CTRL_T), - (hw->chip_id == CHIP_ID_YUKON && hw->chip_rev == 0) - ? GMF_CLI_TX_FC : GMF_CLI_TX_PE); -} - -static void skge_mac_intr(struct skge_hw *hw, int port) -{ - if (is_genesis(hw)) - genesis_mac_intr(hw, port); - else - yukon_mac_intr(hw, port); -} - -/* Handle device specific framing and timeout interrupts */ -static void skge_error_irq(struct skge_hw *hw) -{ - struct pci_dev *pdev = hw->pdev; - u32 hwstatus = skge_read32(hw, B0_HWE_ISRC); - - if (is_genesis(hw)) { - /* clear xmac errors */ - if (hwstatus & (IS_NO_STAT_M1|IS_NO_TIST_M1)) - skge_write16(hw, RX_MFF_CTRL1, MFF_CLR_INSTAT); - if (hwstatus & (IS_NO_STAT_M2|IS_NO_TIST_M2)) - skge_write16(hw, RX_MFF_CTRL2, MFF_CLR_INSTAT); - } else { - /* Timestamp (unused) overflow */ - if (hwstatus & IS_IRQ_TIST_OV) - skge_write8(hw, GMAC_TI_ST_CTRL, GMT_ST_CLR_IRQ); - } - - if (hwstatus & IS_RAM_RD_PAR) { - dev_err(&pdev->dev, "Ram read data parity error\n"); - skge_write16(hw, B3_RI_CTRL, RI_CLR_RD_PERR); - } - - if (hwstatus & IS_RAM_WR_PAR) { - dev_err(&pdev->dev, "Ram write data parity error\n"); - skge_write16(hw, B3_RI_CTRL, RI_CLR_WR_PERR); - } - - if (hwstatus & IS_M1_PAR_ERR) - skge_mac_parity(hw, 0); - - if (hwstatus & IS_M2_PAR_ERR) - skge_mac_parity(hw, 1); - - if (hwstatus & IS_R1_PAR_ERR) { - dev_err(&pdev->dev, "%s: receive queue parity error\n", - hw->dev[0]->name); - skge_write32(hw, B0_R1_CSR, CSR_IRQ_CL_P); - } - - if (hwstatus & IS_R2_PAR_ERR) { - dev_err(&pdev->dev, "%s: receive queue parity error\n", - hw->dev[1]->name); - skge_write32(hw, B0_R2_CSR, CSR_IRQ_CL_P); - } - - if (hwstatus & (IS_IRQ_MST_ERR|IS_IRQ_STAT)) { - u16 pci_status, pci_cmd; - - pci_read_config_word(pdev, PCI_COMMAND, &pci_cmd); - pci_read_config_word(pdev, PCI_STATUS, &pci_status); - - dev_err(&pdev->dev, "PCI error cmd=%#x status=%#x\n", - pci_cmd, pci_status); - - /* Write the error bits back to clear them. */ - pci_status &= PCI_STATUS_ERROR_BITS; - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); - pci_write_config_word(pdev, PCI_COMMAND, - pci_cmd | PCI_COMMAND_SERR | PCI_COMMAND_PARITY); - pci_write_config_word(pdev, PCI_STATUS, pci_status); - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - /* if error still set then just ignore it */ - hwstatus = skge_read32(hw, B0_HWE_ISRC); - if (hwstatus & IS_IRQ_STAT) { - dev_warn(&hw->pdev->dev, "unable to clear error (so ignoring them)\n"); - hw->intr_mask &= ~IS_HW_ERR; - } - } -} - -/* - * Interrupt from PHY are handled in tasklet (softirq) - * because accessing phy registers requires spin wait which might - * cause excess interrupt latency. - */ -static void skge_extirq(unsigned long arg) -{ - struct skge_hw *hw = (struct skge_hw *) arg; - int port; - - for (port = 0; port < hw->ports; port++) { - struct net_device *dev = hw->dev[port]; - - if (netif_running(dev)) { - struct skge_port *skge = netdev_priv(dev); - - spin_lock(&hw->phy_lock); - if (!is_genesis(hw)) - yukon_phy_intr(skge); - else if (hw->phy_type == SK_PHY_BCOM) - bcom_phy_intr(skge); - spin_unlock(&hw->phy_lock); - } - } - - spin_lock_irq(&hw->hw_lock); - hw->intr_mask |= IS_EXT_REG; - skge_write32(hw, B0_IMSK, hw->intr_mask); - skge_read32(hw, B0_IMSK); - spin_unlock_irq(&hw->hw_lock); -} - -static irqreturn_t skge_intr(int irq, void *dev_id) -{ - struct skge_hw *hw = dev_id; - u32 status; - int handled = 0; - - spin_lock(&hw->hw_lock); - /* Reading this register masks IRQ */ - status = skge_read32(hw, B0_SP_ISRC); - if (status == 0 || status == ~0) - goto out; - - handled = 1; - status &= hw->intr_mask; - if (status & IS_EXT_REG) { - hw->intr_mask &= ~IS_EXT_REG; - tasklet_schedule(&hw->phy_task); - } - - if (status & (IS_XA1_F|IS_R1_F)) { - struct skge_port *skge = netdev_priv(hw->dev[0]); - hw->intr_mask &= ~(IS_XA1_F|IS_R1_F); - napi_schedule(&skge->napi); - } - - if (status & IS_PA_TO_TX1) - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX1); - - if (status & IS_PA_TO_RX1) { - ++hw->dev[0]->stats.rx_over_errors; - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX1); - } - - - if (status & IS_MAC1) - skge_mac_intr(hw, 0); - - if (hw->dev[1]) { - struct skge_port *skge = netdev_priv(hw->dev[1]); - - if (status & (IS_XA2_F|IS_R2_F)) { - hw->intr_mask &= ~(IS_XA2_F|IS_R2_F); - napi_schedule(&skge->napi); - } - - if (status & IS_PA_TO_RX2) { - ++hw->dev[1]->stats.rx_over_errors; - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_RX2); - } - - if (status & IS_PA_TO_TX2) - skge_write16(hw, B3_PA_CTRL, PA_CLR_TO_TX2); - - if (status & IS_MAC2) - skge_mac_intr(hw, 1); - } - - if (status & IS_HW_ERR) - skge_error_irq(hw); -out: - skge_write32(hw, B0_IMSK, hw->intr_mask); - skge_read32(hw, B0_IMSK); - spin_unlock(&hw->hw_lock); - - return IRQ_RETVAL(handled); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void skge_netpoll(struct net_device *dev) -{ - struct skge_port *skge = netdev_priv(dev); - - disable_irq(dev->irq); - skge_intr(dev->irq, skge->hw); - enable_irq(dev->irq); -} -#endif - -static int skge_set_mac_address(struct net_device *dev, void *p) -{ - struct skge_port *skge = netdev_priv(dev); - struct skge_hw *hw = skge->hw; - unsigned port = skge->port; - const struct sockaddr *addr = p; - u16 ctrl; - - if (!is_valid_ether_addr(addr->sa_data)) - return -EADDRNOTAVAIL; - - memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); - - if (!netif_running(dev)) { - memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN); - memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN); - } else { - /* disable Rx */ - spin_lock_bh(&hw->phy_lock); - ctrl = gma_read16(hw, port, GM_GP_CTRL); - gma_write16(hw, port, GM_GP_CTRL, ctrl & ~GM_GPCR_RX_ENA); - - memcpy_toio(hw->regs + B2_MAC_1 + port*8, dev->dev_addr, ETH_ALEN); - memcpy_toio(hw->regs + B2_MAC_2 + port*8, dev->dev_addr, ETH_ALEN); - - if (is_genesis(hw)) - xm_outaddr(hw, port, XM_SA, dev->dev_addr); - else { - gma_set_addr(hw, port, GM_SRC_ADDR_1L, dev->dev_addr); - gma_set_addr(hw, port, GM_SRC_ADDR_2L, dev->dev_addr); - } - - gma_write16(hw, port, GM_GP_CTRL, ctrl); - spin_unlock_bh(&hw->phy_lock); - } - - return 0; -} - -static const struct { - u8 id; - const char *name; -} skge_chips[] = { - { CHIP_ID_GENESIS, "Genesis" }, - { CHIP_ID_YUKON, "Yukon" }, - { CHIP_ID_YUKON_LITE, "Yukon-Lite"}, - { CHIP_ID_YUKON_LP, "Yukon-LP"}, -}; - -static const char *skge_board_name(const struct skge_hw *hw) -{ - int i; - static char buf[16]; - - for (i = 0; i < ARRAY_SIZE(skge_chips); i++) - if (skge_chips[i].id == hw->chip_id) - return skge_chips[i].name; - - snprintf(buf, sizeof buf, "chipid 0x%x", hw->chip_id); - return buf; -} - - -/* - * Setup the board data structure, but don't bring up - * the port(s) - */ -static int skge_reset(struct skge_hw *hw) -{ - u32 reg; - u16 ctst, pci_status; - u8 t8, mac_cfg, pmd_type; - int i; - - ctst = skge_read16(hw, B0_CTST); - - /* do a SW reset */ - skge_write8(hw, B0_CTST, CS_RST_SET); - skge_write8(hw, B0_CTST, CS_RST_CLR); - - /* clear PCI errors, if any */ - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); - skge_write8(hw, B2_TST_CTRL2, 0); - - pci_read_config_word(hw->pdev, PCI_STATUS, &pci_status); - pci_write_config_word(hw->pdev, PCI_STATUS, - pci_status | PCI_STATUS_ERROR_BITS); - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - skge_write8(hw, B0_CTST, CS_MRST_CLR); - - /* restore CLK_RUN bits (for Yukon-Lite) */ - skge_write16(hw, B0_CTST, - ctst & (CS_CLK_RUN_HOT|CS_CLK_RUN_RST|CS_CLK_RUN_ENA)); - - hw->chip_id = skge_read8(hw, B2_CHIP_ID); - hw->phy_type = skge_read8(hw, B2_E_1) & 0xf; - pmd_type = skge_read8(hw, B2_PMD_TYP); - hw->copper = (pmd_type == 'T' || pmd_type == '1'); - - switch (hw->chip_id) { - case CHIP_ID_GENESIS: -#ifdef CONFIG_SKGE_GENESIS - switch (hw->phy_type) { - case SK_PHY_XMAC: - hw->phy_addr = PHY_ADDR_XMAC; - break; - case SK_PHY_BCOM: - hw->phy_addr = PHY_ADDR_BCOM; - break; - default: - dev_err(&hw->pdev->dev, "unsupported phy type 0x%x\n", - hw->phy_type); - return -EOPNOTSUPP; - } - break; -#else - dev_err(&hw->pdev->dev, "Genesis chip detected but not configured\n"); - return -EOPNOTSUPP; -#endif - - case CHIP_ID_YUKON: - case CHIP_ID_YUKON_LITE: - case CHIP_ID_YUKON_LP: - if (hw->phy_type < SK_PHY_MARV_COPPER && pmd_type != 'S') - hw->copper = 1; - - hw->phy_addr = PHY_ADDR_MARV; - break; - - default: - dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", - hw->chip_id); - return -EOPNOTSUPP; - } - - mac_cfg = skge_read8(hw, B2_MAC_CFG); - hw->ports = (mac_cfg & CFG_SNG_MAC) ? 1 : 2; - hw->chip_rev = (mac_cfg & CFG_CHIP_R_MSK) >> 4; - - /* read the adapters RAM size */ - t8 = skge_read8(hw, B2_E_0); - if (is_genesis(hw)) { - if (t8 == 3) { - /* special case: 4 x 64k x 36, offset = 0x80000 */ - hw->ram_size = 0x100000; - hw->ram_offset = 0x80000; - } else - hw->ram_size = t8 * 512; - } else if (t8 == 0) - hw->ram_size = 0x20000; - else - hw->ram_size = t8 * 4096; - - hw->intr_mask = IS_HW_ERR; - - /* Use PHY IRQ for all but fiber based Genesis board */ - if (!(is_genesis(hw) && hw->phy_type == SK_PHY_XMAC)) - hw->intr_mask |= IS_EXT_REG; - - if (is_genesis(hw)) - genesis_init(hw); - else { - /* switch power to VCC (WA for VAUX problem) */ - skge_write8(hw, B0_POWER_CTRL, - PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_OFF | PC_VCC_ON); - - /* avoid boards with stuck Hardware error bits */ - if ((skge_read32(hw, B0_ISRC) & IS_HW_ERR) && - (skge_read32(hw, B0_HWE_ISRC) & IS_IRQ_SENSOR)) { - dev_warn(&hw->pdev->dev, "stuck hardware sensor bit\n"); - hw->intr_mask &= ~IS_HW_ERR; - } - - /* Clear PHY COMA */ - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); - pci_read_config_dword(hw->pdev, PCI_DEV_REG1, ®); - reg &= ~PCI_PHY_COMA; - pci_write_config_dword(hw->pdev, PCI_DEV_REG1, reg); - skge_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); - - - for (i = 0; i < hw->ports; i++) { - skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_SET); - skge_write16(hw, SK_REG(i, GMAC_LINK_CTRL), GMLC_RST_CLR); - } - } - - /* turn off hardware timer (unused) */ - skge_write8(hw, B2_TI_CTRL, TIM_STOP); - skge_write8(hw, B2_TI_CTRL, TIM_CLR_IRQ); - skge_write8(hw, B0_LED, LED_STAT_ON); - - /* enable the Tx Arbiters */ - for (i = 0; i < hw->ports; i++) - skge_write8(hw, SK_REG(i, TXA_CTRL), TXA_ENA_ARB); - - /* Initialize ram interface */ - skge_write16(hw, B3_RI_CTRL, RI_RST_CLR); - - skge_write8(hw, B3_RI_WTO_R1, SK_RI_TO_53); - skge_write8(hw, B3_RI_WTO_XA1, SK_RI_TO_53); - skge_write8(hw, B3_RI_WTO_XS1, SK_RI_TO_53); - skge_write8(hw, B3_RI_RTO_R1, SK_RI_TO_53); - skge_write8(hw, B3_RI_RTO_XA1, SK_RI_TO_53); - skge_write8(hw, B3_RI_RTO_XS1, SK_RI_TO_53); - skge_write8(hw, B3_RI_WTO_R2, SK_RI_TO_53); - skge_write8(hw, B3_RI_WTO_XA2, SK_RI_TO_53); - skge_write8(hw, B3_RI_WTO_XS2, SK_RI_TO_53); - skge_write8(hw, B3_RI_RTO_R2, SK_RI_TO_53); - skge_write8(hw, B3_RI_RTO_XA2, SK_RI_TO_53); - skge_write8(hw, B3_RI_RTO_XS2, SK_RI_TO_53); - - skge_write32(hw, B0_HWE_IMSK, IS_ERR_MSK); - - /* Set interrupt moderation for Transmit only - * Receive interrupts avoided by NAPI - */ - skge_write32(hw, B2_IRQM_MSK, IS_XA1_F|IS_XA2_F); - skge_write32(hw, B2_IRQM_INI, skge_usecs2clk(hw, 100)); - skge_write32(hw, B2_IRQM_CTRL, TIM_START); - - /* Leave irq disabled until first port is brought up. */ - skge_write32(hw, B0_IMSK, 0); - - for (i = 0; i < hw->ports; i++) { - if (is_genesis(hw)) - genesis_reset(hw, i); - else - yukon_reset(hw, i); - } - - return 0; -} - - -#ifdef CONFIG_SKGE_DEBUG - -static struct dentry *skge_debug; - -static int skge_debug_show(struct seq_file *seq, void *v) -{ - struct net_device *dev = seq->private; - const struct skge_port *skge = netdev_priv(dev); - const struct skge_hw *hw = skge->hw; - const struct skge_element *e; - - if (!netif_running(dev)) - return -ENETDOWN; - - seq_printf(seq, "IRQ src=%x mask=%x\n", skge_read32(hw, B0_ISRC), - skge_read32(hw, B0_IMSK)); - - seq_printf(seq, "Tx Ring: (%d)\n", skge_avail(&skge->tx_ring)); - for (e = skge->tx_ring.to_clean; e != skge->tx_ring.to_use; e = e->next) { - const struct skge_tx_desc *t = e->desc; - seq_printf(seq, "%#x dma=%#x%08x %#x csum=%#x/%x/%x\n", - t->control, t->dma_hi, t->dma_lo, t->status, - t->csum_offs, t->csum_write, t->csum_start); - } - - seq_printf(seq, "\nRx Ring:\n"); - for (e = skge->rx_ring.to_clean; ; e = e->next) { - const struct skge_rx_desc *r = e->desc; - - if (r->control & BMU_OWN) - break; - - seq_printf(seq, "%#x dma=%#x%08x %#x %#x csum=%#x/%x\n", - r->control, r->dma_hi, r->dma_lo, r->status, - r->timestamp, r->csum1, r->csum1_start); - } - - return 0; -} - -static int skge_debug_open(struct inode *inode, struct file *file) -{ - return single_open(file, skge_debug_show, inode->i_private); -} - -static const struct file_operations skge_debug_fops = { - .owner = THIS_MODULE, - .open = skge_debug_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* - * Use network device events to create/remove/rename - * debugfs file entries - */ -static int skge_device_event(struct notifier_block *unused, - unsigned long event, void *ptr) -{ - struct net_device *dev = netdev_notifier_info_to_dev(ptr); - struct skge_port *skge; - struct dentry *d; - - if (dev->netdev_ops->ndo_open != &skge_up || !skge_debug) - goto done; - - skge = netdev_priv(dev); - switch (event) { - case NETDEV_CHANGENAME: - if (skge->debugfs) { - d = debugfs_rename(skge_debug, skge->debugfs, - skge_debug, dev->name); - if (d) - skge->debugfs = d; - else { - netdev_info(dev, "rename failed\n"); - debugfs_remove(skge->debugfs); - } - } - break; - - case NETDEV_GOING_DOWN: - if (skge->debugfs) { - debugfs_remove(skge->debugfs); - skge->debugfs = NULL; - } - break; - - case NETDEV_UP: - d = debugfs_create_file(dev->name, S_IRUGO, - skge_debug, dev, - &skge_debug_fops); - if (!d || IS_ERR(d)) - netdev_info(dev, "debugfs create failed\n"); - else - skge->debugfs = d; - break; - } - -done: - return NOTIFY_DONE; -} - -static struct notifier_block skge_notifier = { - .notifier_call = skge_device_event, -}; - - -static __init void skge_debug_init(void) -{ - struct dentry *ent; - - ent = debugfs_create_dir("skge", NULL); - if (!ent || IS_ERR(ent)) { - pr_info("debugfs create directory failed\n"); - return; - } - - skge_debug = ent; - register_netdevice_notifier(&skge_notifier); -} - -static __exit void skge_debug_cleanup(void) -{ - if (skge_debug) { - unregister_netdevice_notifier(&skge_notifier); - debugfs_remove(skge_debug); - skge_debug = NULL; - } -} - -#else -#define skge_debug_init() -#define skge_debug_cleanup() -#endif - -static const struct net_device_ops skge_netdev_ops = { - .ndo_open = skge_up, - .ndo_stop = skge_down, - .ndo_start_xmit = skge_xmit_frame, - .ndo_do_ioctl = skge_ioctl, - .ndo_get_stats = skge_get_stats, - .ndo_tx_timeout = skge_tx_timeout, - .ndo_change_mtu = skge_change_mtu, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_rx_mode = skge_set_multicast, - .ndo_set_mac_address = skge_set_mac_address, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = skge_netpoll, -#endif -}; - - -/* Initialize network device */ -static struct net_device *skge_devinit(struct skge_hw *hw, int port, - int highmem) -{ - struct skge_port *skge; - struct net_device *dev = alloc_etherdev(sizeof(*skge)); - - if (!dev) - return NULL; - - SET_NETDEV_DEV(dev, &hw->pdev->dev); - dev->netdev_ops = &skge_netdev_ops; - dev->ethtool_ops = &skge_ethtool_ops; - dev->watchdog_timeo = TX_WATCHDOG; - dev->irq = hw->pdev->irq; - - if (highmem) - dev->features |= NETIF_F_HIGHDMA; - - skge = netdev_priv(dev); - netif_napi_add(dev, &skge->napi, skge_poll, NAPI_WEIGHT); - skge->netdev = dev; - skge->hw = hw; - skge->msg_enable = netif_msg_init(debug, default_msg); - - skge->tx_ring.count = DEFAULT_TX_RING_SIZE; - skge->rx_ring.count = DEFAULT_RX_RING_SIZE; - - /* Auto speed and flow control */ - skge->autoneg = AUTONEG_ENABLE; - skge->flow_control = FLOW_MODE_SYM_OR_REM; - skge->duplex = -1; - skge->speed = -1; - skge->advertising = skge_supported_modes(hw); - - if (device_can_wakeup(&hw->pdev->dev)) { - skge->wol = wol_supported(hw) & WAKE_MAGIC; - device_set_wakeup_enable(&hw->pdev->dev, skge->wol); - } - - hw->dev[port] = dev; - - skge->port = port; - - /* Only used for Genesis XMAC */ - if (is_genesis(hw)) - setup_timer(&skge->link_timer, xm_link_timer, (unsigned long) skge); - else { - dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_SG | - NETIF_F_RXCSUM; - dev->features |= dev->hw_features; - } - - /* read the mac address */ - memcpy_fromio(dev->dev_addr, hw->regs + B2_MAC_1 + port*8, ETH_ALEN); - - return dev; -} - -static void skge_show_addr(struct net_device *dev) -{ - const struct skge_port *skge = netdev_priv(dev); - - netif_info(skge, probe, skge->netdev, "addr %pM\n", dev->dev_addr); -} - -static int only_32bit_dma; - -static int skge_probe(struct pci_dev *pdev, const struct pci_device_id *ent) -{ - struct net_device *dev, *dev1; - struct skge_hw *hw; - int err, using_dac = 0; - - err = pci_enable_device(pdev); - if (err) { - dev_err(&pdev->dev, "cannot enable PCI device\n"); - goto err_out; - } - - err = pci_request_regions(pdev, DRV_NAME); - if (err) { - dev_err(&pdev->dev, "cannot obtain PCI resources\n"); - goto err_out_disable_pdev; - } - - pci_set_master(pdev); - - if (!only_32bit_dma && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { - using_dac = 1; - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); - } else if (!(err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)))) { - using_dac = 0; - err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - } - - if (err) { - dev_err(&pdev->dev, "no usable DMA configuration\n"); - goto err_out_free_regions; - } - -#ifdef __BIG_ENDIAN - /* byte swap descriptors in hardware */ - { - u32 reg; - - pci_read_config_dword(pdev, PCI_DEV_REG2, ®); - reg |= PCI_REV_DESC; - pci_write_config_dword(pdev, PCI_DEV_REG2, reg); - } -#endif - - err = -ENOMEM; - /* space for skge@pci:0000:04:00.0 */ - hw = kzalloc(sizeof(*hw) + strlen(DRV_NAME "@pci:") - + strlen(pci_name(pdev)) + 1, GFP_KERNEL); - if (!hw) - goto err_out_free_regions; - - sprintf(hw->irq_name, DRV_NAME "@pci:%s", pci_name(pdev)); - - hw->pdev = pdev; - spin_lock_init(&hw->hw_lock); - spin_lock_init(&hw->phy_lock); - tasklet_init(&hw->phy_task, skge_extirq, (unsigned long) hw); - - hw->regs = ioremap_nocache(pci_resource_start(pdev, 0), 0x4000); - if (!hw->regs) { - dev_err(&pdev->dev, "cannot map device registers\n"); - goto err_out_free_hw; - } - - err = skge_reset(hw); - if (err) - goto err_out_iounmap; - - pr_info("%s addr 0x%llx irq %d chip %s rev %d\n", - DRV_VERSION, - (unsigned long long)pci_resource_start(pdev, 0), pdev->irq, - skge_board_name(hw), hw->chip_rev); - - dev = skge_devinit(hw, 0, using_dac); - if (!dev) { - err = -ENOMEM; - goto err_out_led_off; - } - - /* Some motherboards are broken and has zero in ROM. */ - if (!is_valid_ether_addr(dev->dev_addr)) - dev_warn(&pdev->dev, "bad (zero?) ethernet address in rom\n"); - - err = register_netdev(dev); - if (err) { - dev_err(&pdev->dev, "cannot register net device\n"); - goto err_out_free_netdev; - } - - skge_show_addr(dev); - - if (hw->ports > 1) { - dev1 = skge_devinit(hw, 1, using_dac); - if (!dev1) { - err = -ENOMEM; - goto err_out_unregister; - } - - err = register_netdev(dev1); - if (err) { - dev_err(&pdev->dev, "cannot register second net device\n"); - goto err_out_free_dev1; - } - - err = request_irq(pdev->irq, skge_intr, IRQF_SHARED, - hw->irq_name, hw); - if (err) { - dev_err(&pdev->dev, "cannot assign irq %d\n", - pdev->irq); - goto err_out_unregister_dev1; - } - - skge_show_addr(dev1); - } - pci_set_drvdata(pdev, hw); - - return 0; - -err_out_unregister_dev1: - unregister_netdev(dev1); -err_out_free_dev1: - free_netdev(dev1); -err_out_unregister: - unregister_netdev(dev); -err_out_free_netdev: - free_netdev(dev); -err_out_led_off: - skge_write16(hw, B0_LED, LED_STAT_OFF); -err_out_iounmap: - iounmap(hw->regs); -err_out_free_hw: - kfree(hw); -err_out_free_regions: - pci_release_regions(pdev); -err_out_disable_pdev: - pci_disable_device(pdev); -err_out: - return err; -} - -static void skge_remove(struct pci_dev *pdev) -{ - struct skge_hw *hw = pci_get_drvdata(pdev); - struct net_device *dev0, *dev1; - - if (!hw) - return; - - dev1 = hw->dev[1]; - if (dev1) - unregister_netdev(dev1); - dev0 = hw->dev[0]; - unregister_netdev(dev0); - - tasklet_kill(&hw->phy_task); - - spin_lock_irq(&hw->hw_lock); - hw->intr_mask = 0; - - if (hw->ports > 1) { - skge_write32(hw, B0_IMSK, 0); - skge_read32(hw, B0_IMSK); - free_irq(pdev->irq, hw); - } - spin_unlock_irq(&hw->hw_lock); - - skge_write16(hw, B0_LED, LED_STAT_OFF); - skge_write8(hw, B0_CTST, CS_RST_SET); - - if (hw->ports > 1) - free_irq(pdev->irq, hw); - pci_release_regions(pdev); - pci_disable_device(pdev); - if (dev1) - free_netdev(dev1); - free_netdev(dev0); - - iounmap(hw->regs); - kfree(hw); -} - -#ifdef CONFIG_PM_SLEEP -static int skge_suspend(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct skge_hw *hw = pci_get_drvdata(pdev); - int i; - - if (!hw) - return 0; - - for (i = 0; i < hw->ports; i++) { - struct net_device *dev = hw->dev[i]; - struct skge_port *skge = netdev_priv(dev); - - if (netif_running(dev)) - skge_down(dev); - - if (skge->wol) - skge_wol_init(skge); - } - - skge_write32(hw, B0_IMSK, 0); - - return 0; -} - -static int skge_resume(struct device *dev) -{ - struct pci_dev *pdev = to_pci_dev(dev); - struct skge_hw *hw = pci_get_drvdata(pdev); - int i, err; - - if (!hw) - return 0; - - err = skge_reset(hw); - if (err) - goto out; - - for (i = 0; i < hw->ports; i++) { - struct net_device *dev = hw->dev[i]; - - if (netif_running(dev)) { - err = skge_up(dev); - - if (err) { - netdev_err(dev, "could not up: %d\n", err); - dev_close(dev); - goto out; - } - } - } -out: - return err; -} - -static SIMPLE_DEV_PM_OPS(skge_pm_ops, skge_suspend, skge_resume); -#define SKGE_PM_OPS (&skge_pm_ops) - -#else - -#define SKGE_PM_OPS NULL -#endif /* CONFIG_PM_SLEEP */ - -static void skge_shutdown(struct pci_dev *pdev) -{ - struct skge_hw *hw = pci_get_drvdata(pdev); - int i; - - if (!hw) - return; - - for (i = 0; i < hw->ports; i++) { - struct net_device *dev = hw->dev[i]; - struct skge_port *skge = netdev_priv(dev); - - if (skge->wol) - skge_wol_init(skge); - } - - pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev)); - pci_set_power_state(pdev, PCI_D3hot); -} - -static struct pci_driver skge_driver = { - .name = DRV_NAME, - .id_table = skge_id_table, - .probe = skge_probe, - .remove = skge_remove, - .shutdown = skge_shutdown, - .driver.pm = SKGE_PM_OPS, -}; - -static struct dmi_system_id skge_32bit_dma_boards[] = { - { - .ident = "Gigabyte nForce boards", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co"), - DMI_MATCH(DMI_BOARD_NAME, "nForce"), - }, - }, - { - .ident = "ASUS P5NSLI", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK Computer INC."), - DMI_MATCH(DMI_BOARD_NAME, "P5NSLI") - }, - }, - { - .ident = "FUJITSU SIEMENS A8NE-FM", - .matches = { - DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek Computer INC."), - DMI_MATCH(DMI_BOARD_NAME, "A8NE-FM") - }, - }, - {} -}; - -static int __init skge_init_module(void) -{ - if (dmi_check_system(skge_32bit_dma_boards)) - only_32bit_dma = 1; - skge_debug_init(); - return pci_register_driver(&skge_driver); -} - -static void __exit skge_cleanup_module(void) -{ - pci_unregister_driver(&skge_driver); - skge_debug_cleanup(); -} - -module_init(skge_init_module); -module_exit(skge_cleanup_module); diff --git a/addons/skge/src/4.4.180/skge.h b/addons/skge/src/4.4.180/skge.h deleted file mode 100644 index a2eb3411..00000000 --- a/addons/skge/src/4.4.180/skge.h +++ /dev/null @@ -1,2584 +0,0 @@ -/* - * Definitions for the new Marvell Yukon / SysKonnect driver. - */ -#ifndef _SKGE_H -#define _SKGE_H -#include - -/* PCI config registers */ -#define PCI_DEV_REG1 0x40 -#define PCI_PHY_COMA 0x8000000 -#define PCI_VIO 0x2000000 - -#define PCI_DEV_REG2 0x44 -#define PCI_VPD_ROM_SZ 7L<<14 /* VPD ROM size 0=256, 1=512, ... */ -#define PCI_REV_DESC 1<<2 /* Reverse Descriptor bytes */ - -#define PCI_STATUS_ERROR_BITS (PCI_STATUS_DETECTED_PARITY | \ - PCI_STATUS_SIG_SYSTEM_ERROR | \ - PCI_STATUS_REC_MASTER_ABORT | \ - PCI_STATUS_REC_TARGET_ABORT | \ - PCI_STATUS_PARITY) - -enum csr_regs { - B0_RAP = 0x0000, - B0_CTST = 0x0004, - B0_LED = 0x0006, - B0_POWER_CTRL = 0x0007, - B0_ISRC = 0x0008, - B0_IMSK = 0x000c, - B0_HWE_ISRC = 0x0010, - B0_HWE_IMSK = 0x0014, - B0_SP_ISRC = 0x0018, - B0_XM1_IMSK = 0x0020, - B0_XM1_ISRC = 0x0028, - B0_XM1_PHY_ADDR = 0x0030, - B0_XM1_PHY_DATA = 0x0034, - B0_XM2_IMSK = 0x0040, - B0_XM2_ISRC = 0x0048, - B0_XM2_PHY_ADDR = 0x0050, - B0_XM2_PHY_DATA = 0x0054, - B0_R1_CSR = 0x0060, - B0_R2_CSR = 0x0064, - B0_XS1_CSR = 0x0068, - B0_XA1_CSR = 0x006c, - B0_XS2_CSR = 0x0070, - B0_XA2_CSR = 0x0074, - - B2_MAC_1 = 0x0100, - B2_MAC_2 = 0x0108, - B2_MAC_3 = 0x0110, - B2_CONN_TYP = 0x0118, - B2_PMD_TYP = 0x0119, - B2_MAC_CFG = 0x011a, - B2_CHIP_ID = 0x011b, - B2_E_0 = 0x011c, - B2_E_1 = 0x011d, - B2_E_2 = 0x011e, - B2_E_3 = 0x011f, - B2_FAR = 0x0120, - B2_FDP = 0x0124, - B2_LD_CTRL = 0x0128, - B2_LD_TEST = 0x0129, - B2_TI_INI = 0x0130, - B2_TI_VAL = 0x0134, - B2_TI_CTRL = 0x0138, - B2_TI_TEST = 0x0139, - B2_IRQM_INI = 0x0140, - B2_IRQM_VAL = 0x0144, - B2_IRQM_CTRL = 0x0148, - B2_IRQM_TEST = 0x0149, - B2_IRQM_MSK = 0x014c, - B2_IRQM_HWE_MSK = 0x0150, - B2_TST_CTRL1 = 0x0158, - B2_TST_CTRL2 = 0x0159, - B2_GP_IO = 0x015c, - B2_I2C_CTRL = 0x0160, - B2_I2C_DATA = 0x0164, - B2_I2C_IRQ = 0x0168, - B2_I2C_SW = 0x016c, - B2_BSC_INI = 0x0170, - B2_BSC_VAL = 0x0174, - B2_BSC_CTRL = 0x0178, - B2_BSC_STAT = 0x0179, - B2_BSC_TST = 0x017a, - - B3_RAM_ADDR = 0x0180, - B3_RAM_DATA_LO = 0x0184, - B3_RAM_DATA_HI = 0x0188, - B3_RI_WTO_R1 = 0x0190, - B3_RI_WTO_XA1 = 0x0191, - B3_RI_WTO_XS1 = 0x0192, - B3_RI_RTO_R1 = 0x0193, - B3_RI_RTO_XA1 = 0x0194, - B3_RI_RTO_XS1 = 0x0195, - B3_RI_WTO_R2 = 0x0196, - B3_RI_WTO_XA2 = 0x0197, - B3_RI_WTO_XS2 = 0x0198, - B3_RI_RTO_R2 = 0x0199, - B3_RI_RTO_XA2 = 0x019a, - B3_RI_RTO_XS2 = 0x019b, - B3_RI_TO_VAL = 0x019c, - B3_RI_CTRL = 0x01a0, - B3_RI_TEST = 0x01a2, - B3_MA_TOINI_RX1 = 0x01b0, - B3_MA_TOINI_RX2 = 0x01b1, - B3_MA_TOINI_TX1 = 0x01b2, - B3_MA_TOINI_TX2 = 0x01b3, - B3_MA_TOVAL_RX1 = 0x01b4, - B3_MA_TOVAL_RX2 = 0x01b5, - B3_MA_TOVAL_TX1 = 0x01b6, - B3_MA_TOVAL_TX2 = 0x01b7, - B3_MA_TO_CTRL = 0x01b8, - B3_MA_TO_TEST = 0x01ba, - B3_MA_RCINI_RX1 = 0x01c0, - B3_MA_RCINI_RX2 = 0x01c1, - B3_MA_RCINI_TX1 = 0x01c2, - B3_MA_RCINI_TX2 = 0x01c3, - B3_MA_RCVAL_RX1 = 0x01c4, - B3_MA_RCVAL_RX2 = 0x01c5, - B3_MA_RCVAL_TX1 = 0x01c6, - B3_MA_RCVAL_TX2 = 0x01c7, - B3_MA_RC_CTRL = 0x01c8, - B3_MA_RC_TEST = 0x01ca, - B3_PA_TOINI_RX1 = 0x01d0, - B3_PA_TOINI_RX2 = 0x01d4, - B3_PA_TOINI_TX1 = 0x01d8, - B3_PA_TOINI_TX2 = 0x01dc, - B3_PA_TOVAL_RX1 = 0x01e0, - B3_PA_TOVAL_RX2 = 0x01e4, - B3_PA_TOVAL_TX1 = 0x01e8, - B3_PA_TOVAL_TX2 = 0x01ec, - B3_PA_CTRL = 0x01f0, - B3_PA_TEST = 0x01f2, -}; - -/* B0_CTST 16 bit Control/Status register */ -enum { - CS_CLK_RUN_HOT = 1<<13,/* CLK_RUN hot m. (YUKON-Lite only) */ - CS_CLK_RUN_RST = 1<<12,/* CLK_RUN reset (YUKON-Lite only) */ - CS_CLK_RUN_ENA = 1<<11,/* CLK_RUN enable (YUKON-Lite only) */ - CS_VAUX_AVAIL = 1<<10,/* VAUX available (YUKON only) */ - CS_BUS_CLOCK = 1<<9, /* Bus Clock 0/1 = 33/66 MHz */ - CS_BUS_SLOT_SZ = 1<<8, /* Slot Size 0/1 = 32/64 bit slot */ - CS_ST_SW_IRQ = 1<<7, /* Set IRQ SW Request */ - CS_CL_SW_IRQ = 1<<6, /* Clear IRQ SW Request */ - CS_STOP_DONE = 1<<5, /* Stop Master is finished */ - CS_STOP_MAST = 1<<4, /* Command Bit to stop the master */ - CS_MRST_CLR = 1<<3, /* Clear Master reset */ - CS_MRST_SET = 1<<2, /* Set Master reset */ - CS_RST_CLR = 1<<1, /* Clear Software reset */ - CS_RST_SET = 1, /* Set Software reset */ - -/* B0_LED 8 Bit LED register */ -/* Bit 7.. 2: reserved */ - LED_STAT_ON = 1<<1, /* Status LED on */ - LED_STAT_OFF = 1, /* Status LED off */ - -/* B0_POWER_CTRL 8 Bit Power Control reg (YUKON only) */ - PC_VAUX_ENA = 1<<7, /* Switch VAUX Enable */ - PC_VAUX_DIS = 1<<6, /* Switch VAUX Disable */ - PC_VCC_ENA = 1<<5, /* Switch VCC Enable */ - PC_VCC_DIS = 1<<4, /* Switch VCC Disable */ - PC_VAUX_ON = 1<<3, /* Switch VAUX On */ - PC_VAUX_OFF = 1<<2, /* Switch VAUX Off */ - PC_VCC_ON = 1<<1, /* Switch VCC On */ - PC_VCC_OFF = 1<<0, /* Switch VCC Off */ -}; - -/* B2_IRQM_MSK 32 bit IRQ Moderation Mask */ -enum { - IS_ALL_MSK = 0xbffffffful, /* All Interrupt bits */ - IS_HW_ERR = 1<<31, /* Interrupt HW Error */ - /* Bit 30: reserved */ - IS_PA_TO_RX1 = 1<<29, /* Packet Arb Timeout Rx1 */ - IS_PA_TO_RX2 = 1<<28, /* Packet Arb Timeout Rx2 */ - IS_PA_TO_TX1 = 1<<27, /* Packet Arb Timeout Tx1 */ - IS_PA_TO_TX2 = 1<<26, /* Packet Arb Timeout Tx2 */ - IS_I2C_READY = 1<<25, /* IRQ on end of I2C Tx */ - IS_IRQ_SW = 1<<24, /* SW forced IRQ */ - IS_EXT_REG = 1<<23, /* IRQ from LM80 or PHY (GENESIS only) */ - /* IRQ from PHY (YUKON only) */ - IS_TIMINT = 1<<22, /* IRQ from Timer */ - IS_MAC1 = 1<<21, /* IRQ from MAC 1 */ - IS_LNK_SYNC_M1 = 1<<20, /* Link Sync Cnt wrap MAC 1 */ - IS_MAC2 = 1<<19, /* IRQ from MAC 2 */ - IS_LNK_SYNC_M2 = 1<<18, /* Link Sync Cnt wrap MAC 2 */ -/* Receive Queue 1 */ - IS_R1_B = 1<<17, /* Q_R1 End of Buffer */ - IS_R1_F = 1<<16, /* Q_R1 End of Frame */ - IS_R1_C = 1<<15, /* Q_R1 Encoding Error */ -/* Receive Queue 2 */ - IS_R2_B = 1<<14, /* Q_R2 End of Buffer */ - IS_R2_F = 1<<13, /* Q_R2 End of Frame */ - IS_R2_C = 1<<12, /* Q_R2 Encoding Error */ -/* Synchronous Transmit Queue 1 */ - IS_XS1_B = 1<<11, /* Q_XS1 End of Buffer */ - IS_XS1_F = 1<<10, /* Q_XS1 End of Frame */ - IS_XS1_C = 1<<9, /* Q_XS1 Encoding Error */ -/* Asynchronous Transmit Queue 1 */ - IS_XA1_B = 1<<8, /* Q_XA1 End of Buffer */ - IS_XA1_F = 1<<7, /* Q_XA1 End of Frame */ - IS_XA1_C = 1<<6, /* Q_XA1 Encoding Error */ -/* Synchronous Transmit Queue 2 */ - IS_XS2_B = 1<<5, /* Q_XS2 End of Buffer */ - IS_XS2_F = 1<<4, /* Q_XS2 End of Frame */ - IS_XS2_C = 1<<3, /* Q_XS2 Encoding Error */ -/* Asynchronous Transmit Queue 2 */ - IS_XA2_B = 1<<2, /* Q_XA2 End of Buffer */ - IS_XA2_F = 1<<1, /* Q_XA2 End of Frame */ - IS_XA2_C = 1<<0, /* Q_XA2 Encoding Error */ - - IS_TO_PORT1 = IS_PA_TO_RX1 | IS_PA_TO_TX1, - IS_TO_PORT2 = IS_PA_TO_RX2 | IS_PA_TO_TX2, - - IS_PORT_1 = IS_XA1_F| IS_R1_F | IS_TO_PORT1 | IS_MAC1, - IS_PORT_2 = IS_XA2_F| IS_R2_F | IS_TO_PORT2 | IS_MAC2, -}; - - -/* B2_IRQM_HWE_MSK 32 bit IRQ Moderation HW Error Mask */ -enum { - IS_IRQ_TIST_OV = 1<<13, /* Time Stamp Timer Overflow (YUKON only) */ - IS_IRQ_SENSOR = 1<<12, /* IRQ from Sensor (YUKON only) */ - IS_IRQ_MST_ERR = 1<<11, /* IRQ master error detected */ - IS_IRQ_STAT = 1<<10, /* IRQ status exception */ - IS_NO_STAT_M1 = 1<<9, /* No Rx Status from MAC 1 */ - IS_NO_STAT_M2 = 1<<8, /* No Rx Status from MAC 2 */ - IS_NO_TIST_M1 = 1<<7, /* No Time Stamp from MAC 1 */ - IS_NO_TIST_M2 = 1<<6, /* No Time Stamp from MAC 2 */ - IS_RAM_RD_PAR = 1<<5, /* RAM Read Parity Error */ - IS_RAM_WR_PAR = 1<<4, /* RAM Write Parity Error */ - IS_M1_PAR_ERR = 1<<3, /* MAC 1 Parity Error */ - IS_M2_PAR_ERR = 1<<2, /* MAC 2 Parity Error */ - IS_R1_PAR_ERR = 1<<1, /* Queue R1 Parity Error */ - IS_R2_PAR_ERR = 1<<0, /* Queue R2 Parity Error */ - - IS_ERR_MSK = IS_IRQ_MST_ERR | IS_IRQ_STAT - | IS_RAM_RD_PAR | IS_RAM_WR_PAR - | IS_M1_PAR_ERR | IS_M2_PAR_ERR - | IS_R1_PAR_ERR | IS_R2_PAR_ERR, -}; - -/* B2_TST_CTRL1 8 bit Test Control Register 1 */ -enum { - TST_FRC_DPERR_MR = 1<<7, /* force DATAPERR on MST RD */ - TST_FRC_DPERR_MW = 1<<6, /* force DATAPERR on MST WR */ - TST_FRC_DPERR_TR = 1<<5, /* force DATAPERR on TRG RD */ - TST_FRC_DPERR_TW = 1<<4, /* force DATAPERR on TRG WR */ - TST_FRC_APERR_M = 1<<3, /* force ADDRPERR on MST */ - TST_FRC_APERR_T = 1<<2, /* force ADDRPERR on TRG */ - TST_CFG_WRITE_ON = 1<<1, /* Enable Config Reg WR */ - TST_CFG_WRITE_OFF= 1<<0, /* Disable Config Reg WR */ -}; - -/* B2_MAC_CFG 8 bit MAC Configuration / Chip Revision */ -enum { - CFG_CHIP_R_MSK = 0xf<<4, /* Bit 7.. 4: Chip Revision */ - /* Bit 3.. 2: reserved */ - CFG_DIS_M2_CLK = 1<<1, /* Disable Clock for 2nd MAC */ - CFG_SNG_MAC = 1<<0, /* MAC Config: 0=2 MACs / 1=1 MAC*/ -}; - -/* B2_CHIP_ID 8 bit Chip Identification Number */ -enum { - CHIP_ID_GENESIS = 0x0a, /* Chip ID for GENESIS */ - CHIP_ID_YUKON = 0xb0, /* Chip ID for YUKON */ - CHIP_ID_YUKON_LITE = 0xb1, /* Chip ID for YUKON-Lite (Rev. A1-A3) */ - CHIP_ID_YUKON_LP = 0xb2, /* Chip ID for YUKON-LP */ - CHIP_ID_YUKON_XL = 0xb3, /* Chip ID for YUKON-2 XL */ - CHIP_ID_YUKON_EC = 0xb6, /* Chip ID for YUKON-2 EC */ - CHIP_ID_YUKON_FE = 0xb7, /* Chip ID for YUKON-2 FE */ - - CHIP_REV_YU_LITE_A1 = 3, /* Chip Rev. for YUKON-Lite A1,A2 */ - CHIP_REV_YU_LITE_A3 = 7, /* Chip Rev. for YUKON-Lite A3 */ -}; - -/* B2_TI_CTRL 8 bit Timer control */ -/* B2_IRQM_CTRL 8 bit IRQ Moderation Timer Control */ -enum { - TIM_START = 1<<2, /* Start Timer */ - TIM_STOP = 1<<1, /* Stop Timer */ - TIM_CLR_IRQ = 1<<0, /* Clear Timer IRQ (!IRQM) */ -}; - -/* B2_TI_TEST 8 Bit Timer Test */ -/* B2_IRQM_TEST 8 bit IRQ Moderation Timer Test */ -/* B28_DPT_TST 8 bit Descriptor Poll Timer Test Reg */ -enum { - TIM_T_ON = 1<<2, /* Test mode on */ - TIM_T_OFF = 1<<1, /* Test mode off */ - TIM_T_STEP = 1<<0, /* Test step */ -}; - -/* B2_GP_IO 32 bit General Purpose I/O Register */ -enum { - GP_DIR_9 = 1<<25, /* IO_9 direct, 0=In/1=Out */ - GP_DIR_8 = 1<<24, /* IO_8 direct, 0=In/1=Out */ - GP_DIR_7 = 1<<23, /* IO_7 direct, 0=In/1=Out */ - GP_DIR_6 = 1<<22, /* IO_6 direct, 0=In/1=Out */ - GP_DIR_5 = 1<<21, /* IO_5 direct, 0=In/1=Out */ - GP_DIR_4 = 1<<20, /* IO_4 direct, 0=In/1=Out */ - GP_DIR_3 = 1<<19, /* IO_3 direct, 0=In/1=Out */ - GP_DIR_2 = 1<<18, /* IO_2 direct, 0=In/1=Out */ - GP_DIR_1 = 1<<17, /* IO_1 direct, 0=In/1=Out */ - GP_DIR_0 = 1<<16, /* IO_0 direct, 0=In/1=Out */ - - GP_IO_9 = 1<<9, /* IO_9 pin */ - GP_IO_8 = 1<<8, /* IO_8 pin */ - GP_IO_7 = 1<<7, /* IO_7 pin */ - GP_IO_6 = 1<<6, /* IO_6 pin */ - GP_IO_5 = 1<<5, /* IO_5 pin */ - GP_IO_4 = 1<<4, /* IO_4 pin */ - GP_IO_3 = 1<<3, /* IO_3 pin */ - GP_IO_2 = 1<<2, /* IO_2 pin */ - GP_IO_1 = 1<<1, /* IO_1 pin */ - GP_IO_0 = 1<<0, /* IO_0 pin */ -}; - -/* Descriptor Bit Definition */ -/* TxCtrl Transmit Buffer Control Field */ -/* RxCtrl Receive Buffer Control Field */ -enum { - BMU_OWN = 1<<31, /* OWN bit: 0=host/1=BMU */ - BMU_STF = 1<<30, /* Start of Frame */ - BMU_EOF = 1<<29, /* End of Frame */ - BMU_IRQ_EOB = 1<<28, /* Req "End of Buffer" IRQ */ - BMU_IRQ_EOF = 1<<27, /* Req "End of Frame" IRQ */ - /* TxCtrl specific bits */ - BMU_STFWD = 1<<26, /* (Tx) Store & Forward Frame */ - BMU_NO_FCS = 1<<25, /* (Tx) Disable MAC FCS (CRC) generation */ - BMU_SW = 1<<24, /* (Tx) 1 bit res. for SW use */ - /* RxCtrl specific bits */ - BMU_DEV_0 = 1<<26, /* (Rx) Transfer data to Dev0 */ - BMU_STAT_VAL = 1<<25, /* (Rx) Rx Status Valid */ - BMU_TIST_VAL = 1<<24, /* (Rx) Rx TimeStamp Valid */ - /* Bit 23..16: BMU Check Opcodes */ - BMU_CHECK = 0x55<<16, /* Default BMU check */ - BMU_TCP_CHECK = 0x56<<16, /* Descr with TCP ext */ - BMU_UDP_CHECK = 0x57<<16, /* Descr with UDP ext (YUKON only) */ - BMU_BBC = 0xffffL, /* Bit 15.. 0: Buffer Byte Counter */ -}; - -/* B2_BSC_CTRL 8 bit Blink Source Counter Control */ -enum { - BSC_START = 1<<1, /* Start Blink Source Counter */ - BSC_STOP = 1<<0, /* Stop Blink Source Counter */ -}; - -/* B2_BSC_STAT 8 bit Blink Source Counter Status */ -enum { - BSC_SRC = 1<<0, /* Blink Source, 0=Off / 1=On */ -}; - -/* B2_BSC_TST 16 bit Blink Source Counter Test Reg */ -enum { - BSC_T_ON = 1<<2, /* Test mode on */ - BSC_T_OFF = 1<<1, /* Test mode off */ - BSC_T_STEP = 1<<0, /* Test step */ -}; - -/* B3_RAM_ADDR 32 bit RAM Address, to read or write */ - /* Bit 31..19: reserved */ -#define RAM_ADR_RAN 0x0007ffffL /* Bit 18.. 0: RAM Address Range */ -/* RAM Interface Registers */ - -/* B3_RI_CTRL 16 bit RAM Iface Control Register */ -enum { - RI_CLR_RD_PERR = 1<<9, /* Clear IRQ RAM Read Parity Err */ - RI_CLR_WR_PERR = 1<<8, /* Clear IRQ RAM Write Parity Err*/ - - RI_RST_CLR = 1<<1, /* Clear RAM Interface Reset */ - RI_RST_SET = 1<<0, /* Set RAM Interface Reset */ -}; - -/* MAC Arbiter Registers */ -/* B3_MA_TO_CTRL 16 bit MAC Arbiter Timeout Ctrl Reg */ -enum { - MA_FOE_ON = 1<<3, /* XMAC Fast Output Enable ON */ - MA_FOE_OFF = 1<<2, /* XMAC Fast Output Enable OFF */ - MA_RST_CLR = 1<<1, /* Clear MAC Arbiter Reset */ - MA_RST_SET = 1<<0, /* Set MAC Arbiter Reset */ - -}; - -/* Timeout values */ -#define SK_MAC_TO_53 72 /* MAC arbiter timeout */ -#define SK_PKT_TO_53 0x2000 /* Packet arbiter timeout */ -#define SK_PKT_TO_MAX 0xffff /* Maximum value */ -#define SK_RI_TO_53 36 /* RAM interface timeout */ - -/* Packet Arbiter Registers */ -/* B3_PA_CTRL 16 bit Packet Arbiter Ctrl Register */ -enum { - PA_CLR_TO_TX2 = 1<<13,/* Clear IRQ Packet Timeout TX2 */ - PA_CLR_TO_TX1 = 1<<12,/* Clear IRQ Packet Timeout TX1 */ - PA_CLR_TO_RX2 = 1<<11,/* Clear IRQ Packet Timeout RX2 */ - PA_CLR_TO_RX1 = 1<<10,/* Clear IRQ Packet Timeout RX1 */ - PA_ENA_TO_TX2 = 1<<9, /* Enable Timeout Timer TX2 */ - PA_DIS_TO_TX2 = 1<<8, /* Disable Timeout Timer TX2 */ - PA_ENA_TO_TX1 = 1<<7, /* Enable Timeout Timer TX1 */ - PA_DIS_TO_TX1 = 1<<6, /* Disable Timeout Timer TX1 */ - PA_ENA_TO_RX2 = 1<<5, /* Enable Timeout Timer RX2 */ - PA_DIS_TO_RX2 = 1<<4, /* Disable Timeout Timer RX2 */ - PA_ENA_TO_RX1 = 1<<3, /* Enable Timeout Timer RX1 */ - PA_DIS_TO_RX1 = 1<<2, /* Disable Timeout Timer RX1 */ - PA_RST_CLR = 1<<1, /* Clear MAC Arbiter Reset */ - PA_RST_SET = 1<<0, /* Set MAC Arbiter Reset */ -}; - -#define PA_ENA_TO_ALL (PA_ENA_TO_RX1 | PA_ENA_TO_RX2 |\ - PA_ENA_TO_TX1 | PA_ENA_TO_TX2) - - -/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */ -/* TXA_ITI_INI 32 bit Tx Arb Interval Timer Init Val */ -/* TXA_ITI_VAL 32 bit Tx Arb Interval Timer Value */ -/* TXA_LIM_INI 32 bit Tx Arb Limit Counter Init Val */ -/* TXA_LIM_VAL 32 bit Tx Arb Limit Counter Value */ - -#define TXA_MAX_VAL 0x00ffffffUL /* Bit 23.. 0: Max TXA Timer/Cnt Val */ - -/* TXA_CTRL 8 bit Tx Arbiter Control Register */ -enum { - TXA_ENA_FSYNC = 1<<7, /* Enable force of sync Tx queue */ - TXA_DIS_FSYNC = 1<<6, /* Disable force of sync Tx queue */ - TXA_ENA_ALLOC = 1<<5, /* Enable alloc of free bandwidth */ - TXA_DIS_ALLOC = 1<<4, /* Disable alloc of free bandwidth */ - TXA_START_RC = 1<<3, /* Start sync Rate Control */ - TXA_STOP_RC = 1<<2, /* Stop sync Rate Control */ - TXA_ENA_ARB = 1<<1, /* Enable Tx Arbiter */ - TXA_DIS_ARB = 1<<0, /* Disable Tx Arbiter */ -}; - -/* - * Bank 4 - 5 - */ -/* Transmit Arbiter Registers MAC 1 and 2, use SK_REG() to access */ -enum { - TXA_ITI_INI = 0x0200,/* 32 bit Tx Arb Interval Timer Init Val*/ - TXA_ITI_VAL = 0x0204,/* 32 bit Tx Arb Interval Timer Value */ - TXA_LIM_INI = 0x0208,/* 32 bit Tx Arb Limit Counter Init Val */ - TXA_LIM_VAL = 0x020c,/* 32 bit Tx Arb Limit Counter Value */ - TXA_CTRL = 0x0210,/* 8 bit Tx Arbiter Control Register */ - TXA_TEST = 0x0211,/* 8 bit Tx Arbiter Test Register */ - TXA_STAT = 0x0212,/* 8 bit Tx Arbiter Status Register */ -}; - - -enum { - B6_EXT_REG = 0x0300,/* External registers (GENESIS only) */ - B7_CFG_SPC = 0x0380,/* copy of the Configuration register */ - B8_RQ1_REGS = 0x0400,/* Receive Queue 1 */ - B8_RQ2_REGS = 0x0480,/* Receive Queue 2 */ - B8_TS1_REGS = 0x0600,/* Transmit sync queue 1 */ - B8_TA1_REGS = 0x0680,/* Transmit async queue 1 */ - B8_TS2_REGS = 0x0700,/* Transmit sync queue 2 */ - B8_TA2_REGS = 0x0780,/* Transmit sync queue 2 */ - B16_RAM_REGS = 0x0800,/* RAM Buffer Registers */ -}; - -/* Queue Register Offsets, use Q_ADDR() to access */ -enum { - B8_Q_REGS = 0x0400, /* base of Queue registers */ - Q_D = 0x00, /* 8*32 bit Current Descriptor */ - Q_DA_L = 0x20, /* 32 bit Current Descriptor Address Low dWord */ - Q_DA_H = 0x24, /* 32 bit Current Descriptor Address High dWord */ - Q_AC_L = 0x28, /* 32 bit Current Address Counter Low dWord */ - Q_AC_H = 0x2c, /* 32 bit Current Address Counter High dWord */ - Q_BC = 0x30, /* 32 bit Current Byte Counter */ - Q_CSR = 0x34, /* 32 bit BMU Control/Status Register */ - Q_F = 0x38, /* 32 bit Flag Register */ - Q_T1 = 0x3c, /* 32 bit Test Register 1 */ - Q_T1_TR = 0x3c, /* 8 bit Test Register 1 Transfer SM */ - Q_T1_WR = 0x3d, /* 8 bit Test Register 1 Write Descriptor SM */ - Q_T1_RD = 0x3e, /* 8 bit Test Register 1 Read Descriptor SM */ - Q_T1_SV = 0x3f, /* 8 bit Test Register 1 Supervisor SM */ - Q_T2 = 0x40, /* 32 bit Test Register 2 */ - Q_T3 = 0x44, /* 32 bit Test Register 3 */ - -}; -#define Q_ADDR(reg, offs) (B8_Q_REGS + (reg) + (offs)) - -/* RAM Buffer Register Offsets */ -enum { - - RB_START= 0x00,/* 32 bit RAM Buffer Start Address */ - RB_END = 0x04,/* 32 bit RAM Buffer End Address */ - RB_WP = 0x08,/* 32 bit RAM Buffer Write Pointer */ - RB_RP = 0x0c,/* 32 bit RAM Buffer Read Pointer */ - RB_RX_UTPP= 0x10,/* 32 bit Rx Upper Threshold, Pause Packet */ - RB_RX_LTPP= 0x14,/* 32 bit Rx Lower Threshold, Pause Packet */ - RB_RX_UTHP= 0x18,/* 32 bit Rx Upper Threshold, High Prio */ - RB_RX_LTHP= 0x1c,/* 32 bit Rx Lower Threshold, High Prio */ - /* 0x10 - 0x1f: reserved at Tx RAM Buffer Registers */ - RB_PC = 0x20,/* 32 bit RAM Buffer Packet Counter */ - RB_LEV = 0x24,/* 32 bit RAM Buffer Level Register */ - RB_CTRL = 0x28,/* 32 bit RAM Buffer Control Register */ - RB_TST1 = 0x29,/* 8 bit RAM Buffer Test Register 1 */ - RB_TST2 = 0x2a,/* 8 bit RAM Buffer Test Register 2 */ -}; - -/* Receive and Transmit Queues */ -enum { - Q_R1 = 0x0000, /* Receive Queue 1 */ - Q_R2 = 0x0080, /* Receive Queue 2 */ - Q_XS1 = 0x0200, /* Synchronous Transmit Queue 1 */ - Q_XA1 = 0x0280, /* Asynchronous Transmit Queue 1 */ - Q_XS2 = 0x0300, /* Synchronous Transmit Queue 2 */ - Q_XA2 = 0x0380, /* Asynchronous Transmit Queue 2 */ -}; - -/* Different MAC Types */ -enum { - SK_MAC_XMAC = 0, /* Xaqti XMAC II */ - SK_MAC_GMAC = 1, /* Marvell GMAC */ -}; - -/* Different PHY Types */ -enum { - SK_PHY_XMAC = 0,/* integrated in XMAC II */ - SK_PHY_BCOM = 1,/* Broadcom BCM5400 */ - SK_PHY_LONE = 2,/* Level One LXT1000 [not supported]*/ - SK_PHY_NAT = 3,/* National DP83891 [not supported] */ - SK_PHY_MARV_COPPER= 4,/* Marvell 88E1011S */ - SK_PHY_MARV_FIBER = 5,/* Marvell 88E1011S working on fiber */ -}; - -/* PHY addresses (bits 12..8 of PHY address reg) */ -enum { - PHY_ADDR_XMAC = 0<<8, - PHY_ADDR_BCOM = 1<<8, - -/* GPHY address (bits 15..11 of SMI control reg) */ - PHY_ADDR_MARV = 0, -}; - -#define RB_ADDR(offs, queue) ((u16)B16_RAM_REGS + (u16)(queue) + (offs)) - -/* Receive MAC FIFO, Receive LED, and Link_Sync regs (GENESIS only) */ -enum { - RX_MFF_EA = 0x0c00,/* 32 bit Receive MAC FIFO End Address */ - RX_MFF_WP = 0x0c04,/* 32 bit Receive MAC FIFO Write Pointer */ - - RX_MFF_RP = 0x0c0c,/* 32 bit Receive MAC FIFO Read Pointer */ - RX_MFF_PC = 0x0c10,/* 32 bit Receive MAC FIFO Packet Cnt */ - RX_MFF_LEV = 0x0c14,/* 32 bit Receive MAC FIFO Level */ - RX_MFF_CTRL1 = 0x0c18,/* 16 bit Receive MAC FIFO Control Reg 1*/ - RX_MFF_STAT_TO = 0x0c1a,/* 8 bit Receive MAC Status Timeout */ - RX_MFF_TIST_TO = 0x0c1b,/* 8 bit Receive MAC Time Stamp Timeout */ - RX_MFF_CTRL2 = 0x0c1c,/* 8 bit Receive MAC FIFO Control Reg 2*/ - RX_MFF_TST1 = 0x0c1d,/* 8 bit Receive MAC FIFO Test Reg 1 */ - RX_MFF_TST2 = 0x0c1e,/* 8 bit Receive MAC FIFO Test Reg 2 */ - - RX_LED_INI = 0x0c20,/* 32 bit Receive LED Cnt Init Value */ - RX_LED_VAL = 0x0c24,/* 32 bit Receive LED Cnt Current Value */ - RX_LED_CTRL = 0x0c28,/* 8 bit Receive LED Cnt Control Reg */ - RX_LED_TST = 0x0c29,/* 8 bit Receive LED Cnt Test Register */ - - LNK_SYNC_INI = 0x0c30,/* 32 bit Link Sync Cnt Init Value */ - LNK_SYNC_VAL = 0x0c34,/* 32 bit Link Sync Cnt Current Value */ - LNK_SYNC_CTRL = 0x0c38,/* 8 bit Link Sync Cnt Control Register */ - LNK_SYNC_TST = 0x0c39,/* 8 bit Link Sync Cnt Test Register */ - LNK_LED_REG = 0x0c3c,/* 8 bit Link LED Register */ -}; - -/* Receive and Transmit MAC FIFO Registers (GENESIS only) */ -/* RX_MFF_CTRL1 16 bit Receive MAC FIFO Control Reg 1 */ -enum { - MFF_ENA_RDY_PAT = 1<<13, /* Enable Ready Patch */ - MFF_DIS_RDY_PAT = 1<<12, /* Disable Ready Patch */ - MFF_ENA_TIM_PAT = 1<<11, /* Enable Timing Patch */ - MFF_DIS_TIM_PAT = 1<<10, /* Disable Timing Patch */ - MFF_ENA_ALM_FUL = 1<<9, /* Enable AlmostFull Sign */ - MFF_DIS_ALM_FUL = 1<<8, /* Disable AlmostFull Sign */ - MFF_ENA_PAUSE = 1<<7, /* Enable Pause Signaling */ - MFF_DIS_PAUSE = 1<<6, /* Disable Pause Signaling */ - MFF_ENA_FLUSH = 1<<5, /* Enable Frame Flushing */ - MFF_DIS_FLUSH = 1<<4, /* Disable Frame Flushing */ - MFF_ENA_TIST = 1<<3, /* Enable Time Stamp Gener */ - MFF_DIS_TIST = 1<<2, /* Disable Time Stamp Gener */ - MFF_CLR_INTIST = 1<<1, /* Clear IRQ No Time Stamp */ - MFF_CLR_INSTAT = 1<<0, /* Clear IRQ No Status */ - MFF_RX_CTRL_DEF = MFF_ENA_TIM_PAT, -}; - -/* TX_MFF_CTRL1 16 bit Transmit MAC FIFO Control Reg 1 */ -enum { - MFF_CLR_PERR = 1<<15, /* Clear Parity Error IRQ */ - - MFF_ENA_PKT_REC = 1<<13, /* Enable Packet Recovery */ - MFF_DIS_PKT_REC = 1<<12, /* Disable Packet Recovery */ - - MFF_ENA_W4E = 1<<7, /* Enable Wait for Empty */ - MFF_DIS_W4E = 1<<6, /* Disable Wait for Empty */ - - MFF_ENA_LOOPB = 1<<3, /* Enable Loopback */ - MFF_DIS_LOOPB = 1<<2, /* Disable Loopback */ - MFF_CLR_MAC_RST = 1<<1, /* Clear XMAC Reset */ - MFF_SET_MAC_RST = 1<<0, /* Set XMAC Reset */ - - MFF_TX_CTRL_DEF = MFF_ENA_PKT_REC | (u16) MFF_ENA_TIM_PAT | MFF_ENA_FLUSH, -}; - - -/* RX_MFF_TST2 8 bit Receive MAC FIFO Test Register 2 */ -/* TX_MFF_TST2 8 bit Transmit MAC FIFO Test Register 2 */ -enum { - MFF_WSP_T_ON = 1<<6, /* Tx: Write Shadow Ptr TestOn */ - MFF_WSP_T_OFF = 1<<5, /* Tx: Write Shadow Ptr TstOff */ - MFF_WSP_INC = 1<<4, /* Tx: Write Shadow Ptr Increment */ - MFF_PC_DEC = 1<<3, /* Packet Counter Decrement */ - MFF_PC_T_ON = 1<<2, /* Packet Counter Test On */ - MFF_PC_T_OFF = 1<<1, /* Packet Counter Test Off */ - MFF_PC_INC = 1<<0, /* Packet Counter Increment */ -}; - -/* RX_MFF_TST1 8 bit Receive MAC FIFO Test Register 1 */ -/* TX_MFF_TST1 8 bit Transmit MAC FIFO Test Register 1 */ -enum { - MFF_WP_T_ON = 1<<6, /* Write Pointer Test On */ - MFF_WP_T_OFF = 1<<5, /* Write Pointer Test Off */ - MFF_WP_INC = 1<<4, /* Write Pointer Increm */ - - MFF_RP_T_ON = 1<<2, /* Read Pointer Test On */ - MFF_RP_T_OFF = 1<<1, /* Read Pointer Test Off */ - MFF_RP_DEC = 1<<0, /* Read Pointer Decrement */ -}; - -/* RX_MFF_CTRL2 8 bit Receive MAC FIFO Control Reg 2 */ -/* TX_MFF_CTRL2 8 bit Transmit MAC FIFO Control Reg 2 */ -enum { - MFF_ENA_OP_MD = 1<<3, /* Enable Operation Mode */ - MFF_DIS_OP_MD = 1<<2, /* Disable Operation Mode */ - MFF_RST_CLR = 1<<1, /* Clear MAC FIFO Reset */ - MFF_RST_SET = 1<<0, /* Set MAC FIFO Reset */ -}; - - -/* Link LED Counter Registers (GENESIS only) */ - -/* RX_LED_CTRL 8 bit Receive LED Cnt Control Reg */ -/* TX_LED_CTRL 8 bit Transmit LED Cnt Control Reg */ -/* LNK_SYNC_CTRL 8 bit Link Sync Cnt Control Register */ -enum { - LED_START = 1<<2, /* Start Timer */ - LED_STOP = 1<<1, /* Stop Timer */ - LED_STATE = 1<<0, /* Rx/Tx: LED State, 1=LED on */ -}; - -/* RX_LED_TST 8 bit Receive LED Cnt Test Register */ -/* TX_LED_TST 8 bit Transmit LED Cnt Test Register */ -/* LNK_SYNC_TST 8 bit Link Sync Cnt Test Register */ -enum { - LED_T_ON = 1<<2, /* LED Counter Test mode On */ - LED_T_OFF = 1<<1, /* LED Counter Test mode Off */ - LED_T_STEP = 1<<0, /* LED Counter Step */ -}; - -/* LNK_LED_REG 8 bit Link LED Register */ -enum { - LED_BLK_ON = 1<<5, /* Link LED Blinking On */ - LED_BLK_OFF = 1<<4, /* Link LED Blinking Off */ - LED_SYNC_ON = 1<<3, /* Use Sync Wire to switch LED */ - LED_SYNC_OFF = 1<<2, /* Disable Sync Wire Input */ - LED_ON = 1<<1, /* switch LED on */ - LED_OFF = 1<<0, /* switch LED off */ -}; - -/* Receive GMAC FIFO (YUKON) */ -enum { - RX_GMF_EA = 0x0c40,/* 32 bit Rx GMAC FIFO End Address */ - RX_GMF_AF_THR = 0x0c44,/* 32 bit Rx GMAC FIFO Almost Full Thresh. */ - RX_GMF_CTRL_T = 0x0c48,/* 32 bit Rx GMAC FIFO Control/Test */ - RX_GMF_FL_MSK = 0x0c4c,/* 32 bit Rx GMAC FIFO Flush Mask */ - RX_GMF_FL_THR = 0x0c50,/* 32 bit Rx GMAC FIFO Flush Threshold */ - RX_GMF_WP = 0x0c60,/* 32 bit Rx GMAC FIFO Write Pointer */ - RX_GMF_WLEV = 0x0c68,/* 32 bit Rx GMAC FIFO Write Level */ - RX_GMF_RP = 0x0c70,/* 32 bit Rx GMAC FIFO Read Pointer */ - RX_GMF_RLEV = 0x0c78,/* 32 bit Rx GMAC FIFO Read Level */ -}; - - -/* TXA_TEST 8 bit Tx Arbiter Test Register */ -enum { - TXA_INT_T_ON = 1<<5, /* Tx Arb Interval Timer Test On */ - TXA_INT_T_OFF = 1<<4, /* Tx Arb Interval Timer Test Off */ - TXA_INT_T_STEP = 1<<3, /* Tx Arb Interval Timer Step */ - TXA_LIM_T_ON = 1<<2, /* Tx Arb Limit Timer Test On */ - TXA_LIM_T_OFF = 1<<1, /* Tx Arb Limit Timer Test Off */ - TXA_LIM_T_STEP = 1<<0, /* Tx Arb Limit Timer Step */ -}; - -/* TXA_STAT 8 bit Tx Arbiter Status Register */ -enum { - TXA_PRIO_XS = 1<<0, /* sync queue has prio to send */ -}; - - -/* Q_BC 32 bit Current Byte Counter */ - -/* BMU Control Status Registers */ -/* B0_R1_CSR 32 bit BMU Ctrl/Stat Rx Queue 1 */ -/* B0_R2_CSR 32 bit BMU Ctrl/Stat Rx Queue 2 */ -/* B0_XA1_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 1 */ -/* B0_XS1_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 1 */ -/* B0_XA2_CSR 32 bit BMU Ctrl/Stat Sync Tx Queue 2 */ -/* B0_XS2_CSR 32 bit BMU Ctrl/Stat Async Tx Queue 2 */ -/* Q_CSR 32 bit BMU Control/Status Register */ - -enum { - CSR_SV_IDLE = 1<<24, /* BMU SM Idle */ - - CSR_DESC_CLR = 1<<21, /* Clear Reset for Descr */ - CSR_DESC_SET = 1<<20, /* Set Reset for Descr */ - CSR_FIFO_CLR = 1<<19, /* Clear Reset for FIFO */ - CSR_FIFO_SET = 1<<18, /* Set Reset for FIFO */ - CSR_HPI_RUN = 1<<17, /* Release HPI SM */ - CSR_HPI_RST = 1<<16, /* Reset HPI SM to Idle */ - CSR_SV_RUN = 1<<15, /* Release Supervisor SM */ - CSR_SV_RST = 1<<14, /* Reset Supervisor SM */ - CSR_DREAD_RUN = 1<<13, /* Release Descr Read SM */ - CSR_DREAD_RST = 1<<12, /* Reset Descr Read SM */ - CSR_DWRITE_RUN = 1<<11, /* Release Descr Write SM */ - CSR_DWRITE_RST = 1<<10, /* Reset Descr Write SM */ - CSR_TRANS_RUN = 1<<9, /* Release Transfer SM */ - CSR_TRANS_RST = 1<<8, /* Reset Transfer SM */ - CSR_ENA_POL = 1<<7, /* Enable Descr Polling */ - CSR_DIS_POL = 1<<6, /* Disable Descr Polling */ - CSR_STOP = 1<<5, /* Stop Rx/Tx Queue */ - CSR_START = 1<<4, /* Start Rx/Tx Queue */ - CSR_IRQ_CL_P = 1<<3, /* (Rx) Clear Parity IRQ */ - CSR_IRQ_CL_B = 1<<2, /* Clear EOB IRQ */ - CSR_IRQ_CL_F = 1<<1, /* Clear EOF IRQ */ - CSR_IRQ_CL_C = 1<<0, /* Clear ERR IRQ */ -}; - -#define CSR_SET_RESET (CSR_DESC_SET | CSR_FIFO_SET | CSR_HPI_RST |\ - CSR_SV_RST | CSR_DREAD_RST | CSR_DWRITE_RST |\ - CSR_TRANS_RST) -#define CSR_CLR_RESET (CSR_DESC_CLR | CSR_FIFO_CLR | CSR_HPI_RUN |\ - CSR_SV_RUN | CSR_DREAD_RUN | CSR_DWRITE_RUN |\ - CSR_TRANS_RUN) - -/* Q_F 32 bit Flag Register */ -enum { - F_ALM_FULL = 1<<27, /* Rx FIFO: almost full */ - F_EMPTY = 1<<27, /* Tx FIFO: empty flag */ - F_FIFO_EOF = 1<<26, /* Tag (EOF Flag) bit in FIFO */ - F_WM_REACHED = 1<<25, /* Watermark reached */ - - F_FIFO_LEVEL = 0x1fL<<16, /* Bit 23..16: # of Qwords in FIFO */ - F_WATER_MARK = 0x0007ffL, /* Bit 10.. 0: Watermark */ -}; - -/* RAM Buffer Register Offsets, use RB_ADDR(Queue, Offs) to access */ -/* RB_START 32 bit RAM Buffer Start Address */ -/* RB_END 32 bit RAM Buffer End Address */ -/* RB_WP 32 bit RAM Buffer Write Pointer */ -/* RB_RP 32 bit RAM Buffer Read Pointer */ -/* RB_RX_UTPP 32 bit Rx Upper Threshold, Pause Pack */ -/* RB_RX_LTPP 32 bit Rx Lower Threshold, Pause Pack */ -/* RB_RX_UTHP 32 bit Rx Upper Threshold, High Prio */ -/* RB_RX_LTHP 32 bit Rx Lower Threshold, High Prio */ -/* RB_PC 32 bit RAM Buffer Packet Counter */ -/* RB_LEV 32 bit RAM Buffer Level Register */ - -#define RB_MSK 0x0007ffff /* Bit 18.. 0: RAM Buffer Pointer Bits */ -/* RB_TST2 8 bit RAM Buffer Test Register 2 */ -/* RB_TST1 8 bit RAM Buffer Test Register 1 */ - -/* RB_CTRL 8 bit RAM Buffer Control Register */ -enum { - RB_ENA_STFWD = 1<<5, /* Enable Store & Forward */ - RB_DIS_STFWD = 1<<4, /* Disable Store & Forward */ - RB_ENA_OP_MD = 1<<3, /* Enable Operation Mode */ - RB_DIS_OP_MD = 1<<2, /* Disable Operation Mode */ - RB_RST_CLR = 1<<1, /* Clear RAM Buf STM Reset */ - RB_RST_SET = 1<<0, /* Set RAM Buf STM Reset */ -}; - -/* Transmit MAC FIFO and Transmit LED Registers (GENESIS only), */ -enum { - TX_MFF_EA = 0x0d00,/* 32 bit Transmit MAC FIFO End Address */ - TX_MFF_WP = 0x0d04,/* 32 bit Transmit MAC FIFO WR Pointer */ - TX_MFF_WSP = 0x0d08,/* 32 bit Transmit MAC FIFO WR Shadow Ptr */ - TX_MFF_RP = 0x0d0c,/* 32 bit Transmit MAC FIFO RD Pointer */ - TX_MFF_PC = 0x0d10,/* 32 bit Transmit MAC FIFO Packet Cnt */ - TX_MFF_LEV = 0x0d14,/* 32 bit Transmit MAC FIFO Level */ - TX_MFF_CTRL1 = 0x0d18,/* 16 bit Transmit MAC FIFO Ctrl Reg 1 */ - TX_MFF_WAF = 0x0d1a,/* 8 bit Transmit MAC Wait after flush */ - - TX_MFF_CTRL2 = 0x0d1c,/* 8 bit Transmit MAC FIFO Ctrl Reg 2 */ - TX_MFF_TST1 = 0x0d1d,/* 8 bit Transmit MAC FIFO Test Reg 1 */ - TX_MFF_TST2 = 0x0d1e,/* 8 bit Transmit MAC FIFO Test Reg 2 */ - - TX_LED_INI = 0x0d20,/* 32 bit Transmit LED Cnt Init Value */ - TX_LED_VAL = 0x0d24,/* 32 bit Transmit LED Cnt Current Val */ - TX_LED_CTRL = 0x0d28,/* 8 bit Transmit LED Cnt Control Reg */ - TX_LED_TST = 0x0d29,/* 8 bit Transmit LED Cnt Test Reg */ -}; - -/* Counter and Timer constants, for a host clock of 62.5 MHz */ -#define SK_XMIT_DUR 0x002faf08UL /* 50 ms */ -#define SK_BLK_DUR 0x01dcd650UL /* 500 ms */ - -#define SK_DPOLL_DEF 0x00ee6b28UL /* 250 ms at 62.5 MHz */ - -#define SK_DPOLL_MAX 0x00ffffffUL /* 268 ms at 62.5 MHz */ - /* 215 ms at 78.12 MHz */ - -#define SK_FACT_62 100 /* is given in percent */ -#define SK_FACT_53 85 /* on GENESIS: 53.12 MHz */ -#define SK_FACT_78 125 /* on YUKON: 78.12 MHz */ - - -/* Transmit GMAC FIFO (YUKON only) */ -enum { - TX_GMF_EA = 0x0d40,/* 32 bit Tx GMAC FIFO End Address */ - TX_GMF_AE_THR = 0x0d44,/* 32 bit Tx GMAC FIFO Almost Empty Thresh.*/ - TX_GMF_CTRL_T = 0x0d48,/* 32 bit Tx GMAC FIFO Control/Test */ - - TX_GMF_WP = 0x0d60,/* 32 bit Tx GMAC FIFO Write Pointer */ - TX_GMF_WSP = 0x0d64,/* 32 bit Tx GMAC FIFO Write Shadow Ptr. */ - TX_GMF_WLEV = 0x0d68,/* 32 bit Tx GMAC FIFO Write Level */ - - TX_GMF_RP = 0x0d70,/* 32 bit Tx GMAC FIFO Read Pointer */ - TX_GMF_RSTP = 0x0d74,/* 32 bit Tx GMAC FIFO Restart Pointer */ - TX_GMF_RLEV = 0x0d78,/* 32 bit Tx GMAC FIFO Read Level */ - - /* Descriptor Poll Timer Registers */ - B28_DPT_INI = 0x0e00,/* 24 bit Descriptor Poll Timer Init Val */ - B28_DPT_VAL = 0x0e04,/* 24 bit Descriptor Poll Timer Curr Val */ - B28_DPT_CTRL = 0x0e08,/* 8 bit Descriptor Poll Timer Ctrl Reg */ - - B28_DPT_TST = 0x0e0a,/* 8 bit Descriptor Poll Timer Test Reg */ - - /* Time Stamp Timer Registers (YUKON only) */ - GMAC_TI_ST_VAL = 0x0e14,/* 32 bit Time Stamp Timer Curr Val */ - GMAC_TI_ST_CTRL = 0x0e18,/* 8 bit Time Stamp Timer Ctrl Reg */ - GMAC_TI_ST_TST = 0x0e1a,/* 8 bit Time Stamp Timer Test Reg */ -}; - - -enum { - LINKLED_OFF = 0x01, - LINKLED_ON = 0x02, - LINKLED_LINKSYNC_OFF = 0x04, - LINKLED_LINKSYNC_ON = 0x08, - LINKLED_BLINK_OFF = 0x10, - LINKLED_BLINK_ON = 0x20, -}; - -/* GMAC and GPHY Control Registers (YUKON only) */ -enum { - GMAC_CTRL = 0x0f00,/* 32 bit GMAC Control Reg */ - GPHY_CTRL = 0x0f04,/* 32 bit GPHY Control Reg */ - GMAC_IRQ_SRC = 0x0f08,/* 8 bit GMAC Interrupt Source Reg */ - GMAC_IRQ_MSK = 0x0f0c,/* 8 bit GMAC Interrupt Mask Reg */ - GMAC_LINK_CTRL = 0x0f10,/* 16 bit Link Control Reg */ - -/* Wake-up Frame Pattern Match Control Registers (YUKON only) */ - - WOL_REG_OFFS = 0x20,/* HW-Bug: Address is + 0x20 against spec. */ - - WOL_CTRL_STAT = 0x0f20,/* 16 bit WOL Control/Status Reg */ - WOL_MATCH_CTL = 0x0f22,/* 8 bit WOL Match Control Reg */ - WOL_MATCH_RES = 0x0f23,/* 8 bit WOL Match Result Reg */ - WOL_MAC_ADDR = 0x0f24,/* 32 bit WOL MAC Address */ - WOL_PATT_RPTR = 0x0f2c,/* 8 bit WOL Pattern Read Pointer */ - -/* WOL Pattern Length Registers (YUKON only) */ - - WOL_PATT_LEN_LO = 0x0f30,/* 32 bit WOL Pattern Length 3..0 */ - WOL_PATT_LEN_HI = 0x0f34,/* 24 bit WOL Pattern Length 6..4 */ - -/* WOL Pattern Counter Registers (YUKON only) */ - - WOL_PATT_CNT_0 = 0x0f38,/* 32 bit WOL Pattern Counter 3..0 */ - WOL_PATT_CNT_4 = 0x0f3c,/* 24 bit WOL Pattern Counter 6..4 */ -}; -#define WOL_REGS(port, x) (x + (port)*0x80) - -enum { - WOL_PATT_RAM_1 = 0x1000,/* WOL Pattern RAM Link 1 */ - WOL_PATT_RAM_2 = 0x1400,/* WOL Pattern RAM Link 2 */ -}; -#define WOL_PATT_RAM_BASE(port) (WOL_PATT_RAM_1 + (port)*0x400) - -enum { - BASE_XMAC_1 = 0x2000,/* XMAC 1 registers */ - BASE_GMAC_1 = 0x2800,/* GMAC 1 registers */ - BASE_XMAC_2 = 0x3000,/* XMAC 2 registers */ - BASE_GMAC_2 = 0x3800,/* GMAC 2 registers */ -}; - -/* - * Receive Frame Status Encoding - */ -enum { - XMR_FS_LEN = 0x3fff<<18, /* Bit 31..18: Rx Frame Length */ - XMR_FS_LEN_SHIFT = 18, - XMR_FS_2L_VLAN = 1<<17, /* Bit 17: tagged wh 2Lev VLAN ID*/ - XMR_FS_1_VLAN = 1<<16, /* Bit 16: tagged wh 1ev VLAN ID*/ - XMR_FS_BC = 1<<15, /* Bit 15: Broadcast Frame */ - XMR_FS_MC = 1<<14, /* Bit 14: Multicast Frame */ - XMR_FS_UC = 1<<13, /* Bit 13: Unicast Frame */ - - XMR_FS_BURST = 1<<11, /* Bit 11: Burst Mode */ - XMR_FS_CEX_ERR = 1<<10, /* Bit 10: Carrier Ext. Error */ - XMR_FS_802_3 = 1<<9, /* Bit 9: 802.3 Frame */ - XMR_FS_COL_ERR = 1<<8, /* Bit 8: Collision Error */ - XMR_FS_CAR_ERR = 1<<7, /* Bit 7: Carrier Event Error */ - XMR_FS_LEN_ERR = 1<<6, /* Bit 6: In-Range Length Error */ - XMR_FS_FRA_ERR = 1<<5, /* Bit 5: Framing Error */ - XMR_FS_RUNT = 1<<4, /* Bit 4: Runt Frame */ - XMR_FS_LNG_ERR = 1<<3, /* Bit 3: Giant (Jumbo) Frame */ - XMR_FS_FCS_ERR = 1<<2, /* Bit 2: Frame Check Sequ Err */ - XMR_FS_ERR = 1<<1, /* Bit 1: Frame Error */ - XMR_FS_MCTRL = 1<<0, /* Bit 0: MAC Control Packet */ - -/* - * XMR_FS_ERR will be set if - * XMR_FS_FCS_ERR, XMR_FS_LNG_ERR, XMR_FS_RUNT, - * XMR_FS_FRA_ERR, XMR_FS_LEN_ERR, or XMR_FS_CEX_ERR - * is set. XMR_FS_LNG_ERR and XMR_FS_LEN_ERR will issue - * XMR_FS_ERR unless the corresponding bit in the Receive Command - * Register is set. - */ -}; - -/* -,* XMAC-PHY Registers, indirect addressed over the XMAC - */ -enum { - PHY_XMAC_CTRL = 0x00,/* 16 bit r/w PHY Control Register */ - PHY_XMAC_STAT = 0x01,/* 16 bit r/w PHY Status Register */ - PHY_XMAC_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */ - PHY_XMAC_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */ - PHY_XMAC_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */ - PHY_XMAC_AUNE_LP = 0x05,/* 16 bit r/o Link Partner Abi Reg */ - PHY_XMAC_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */ - PHY_XMAC_NEPG = 0x07,/* 16 bit r/w Next Page Register */ - PHY_XMAC_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */ - - PHY_XMAC_EXT_STAT = 0x0f,/* 16 bit r/o Ext Status Register */ - PHY_XMAC_RES_ABI = 0x10,/* 16 bit r/o PHY Resolved Ability */ -}; -/* - * Broadcom-PHY Registers, indirect addressed over XMAC - */ -enum { - PHY_BCOM_CTRL = 0x00,/* 16 bit r/w PHY Control Register */ - PHY_BCOM_STAT = 0x01,/* 16 bit r/o PHY Status Register */ - PHY_BCOM_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */ - PHY_BCOM_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */ - PHY_BCOM_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */ - PHY_BCOM_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */ - PHY_BCOM_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */ - PHY_BCOM_NEPG = 0x07,/* 16 bit r/w Next Page Register */ - PHY_BCOM_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */ - /* Broadcom-specific registers */ - PHY_BCOM_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */ - PHY_BCOM_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */ - PHY_BCOM_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */ - PHY_BCOM_P_EXT_CTRL = 0x10,/* 16 bit r/w PHY Extended Ctrl Reg */ - PHY_BCOM_P_EXT_STAT = 0x11,/* 16 bit r/o PHY Extended Stat Reg */ - PHY_BCOM_RE_CTR = 0x12,/* 16 bit r/w Receive Error Counter */ - PHY_BCOM_FC_CTR = 0x13,/* 16 bit r/w False Carrier Sense Cnt */ - PHY_BCOM_RNO_CTR = 0x14,/* 16 bit r/w Receiver NOT_OK Cnt */ - - PHY_BCOM_AUX_CTRL = 0x18,/* 16 bit r/w Auxiliary Control Reg */ - PHY_BCOM_AUX_STAT = 0x19,/* 16 bit r/o Auxiliary Stat Summary */ - PHY_BCOM_INT_STAT = 0x1a,/* 16 bit r/o Interrupt Status Reg */ - PHY_BCOM_INT_MASK = 0x1b,/* 16 bit r/w Interrupt Mask Reg */ -}; - -/* - * Marvel-PHY Registers, indirect addressed over GMAC - */ -enum { - PHY_MARV_CTRL = 0x00,/* 16 bit r/w PHY Control Register */ - PHY_MARV_STAT = 0x01,/* 16 bit r/o PHY Status Register */ - PHY_MARV_ID0 = 0x02,/* 16 bit r/o PHY ID0 Register */ - PHY_MARV_ID1 = 0x03,/* 16 bit r/o PHY ID1 Register */ - PHY_MARV_AUNE_ADV = 0x04,/* 16 bit r/w Auto-Neg. Advertisement */ - PHY_MARV_AUNE_LP = 0x05,/* 16 bit r/o Link Part Ability Reg */ - PHY_MARV_AUNE_EXP = 0x06,/* 16 bit r/o Auto-Neg. Expansion Reg */ - PHY_MARV_NEPG = 0x07,/* 16 bit r/w Next Page Register */ - PHY_MARV_NEPG_LP = 0x08,/* 16 bit r/o Next Page Link Partner */ - /* Marvel-specific registers */ - PHY_MARV_1000T_CTRL = 0x09,/* 16 bit r/w 1000Base-T Control Reg */ - PHY_MARV_1000T_STAT = 0x0a,/* 16 bit r/o 1000Base-T Status Reg */ - PHY_MARV_EXT_STAT = 0x0f,/* 16 bit r/o Extended Status Reg */ - PHY_MARV_PHY_CTRL = 0x10,/* 16 bit r/w PHY Specific Ctrl Reg */ - PHY_MARV_PHY_STAT = 0x11,/* 16 bit r/o PHY Specific Stat Reg */ - PHY_MARV_INT_MASK = 0x12,/* 16 bit r/w Interrupt Mask Reg */ - PHY_MARV_INT_STAT = 0x13,/* 16 bit r/o Interrupt Status Reg */ - PHY_MARV_EXT_CTRL = 0x14,/* 16 bit r/w Ext. PHY Specific Ctrl */ - PHY_MARV_RXE_CNT = 0x15,/* 16 bit r/w Receive Error Counter */ - PHY_MARV_EXT_ADR = 0x16,/* 16 bit r/w Ext. Ad. for Cable Diag. */ - PHY_MARV_PORT_IRQ = 0x17,/* 16 bit r/o Port 0 IRQ (88E1111 only) */ - PHY_MARV_LED_CTRL = 0x18,/* 16 bit r/w LED Control Reg */ - PHY_MARV_LED_OVER = 0x19,/* 16 bit r/w Manual LED Override Reg */ - PHY_MARV_EXT_CTRL_2 = 0x1a,/* 16 bit r/w Ext. PHY Specific Ctrl 2 */ - PHY_MARV_EXT_P_STAT = 0x1b,/* 16 bit r/w Ext. PHY Spec. Stat Reg */ - PHY_MARV_CABLE_DIAG = 0x1c,/* 16 bit r/o Cable Diagnostic Reg */ - PHY_MARV_PAGE_ADDR = 0x1d,/* 16 bit r/w Extended Page Address Reg */ - PHY_MARV_PAGE_DATA = 0x1e,/* 16 bit r/w Extended Page Data Reg */ - -/* for 10/100 Fast Ethernet PHY (88E3082 only) */ - PHY_MARV_FE_LED_PAR = 0x16,/* 16 bit r/w LED Parallel Select Reg. */ - PHY_MARV_FE_LED_SER = 0x17,/* 16 bit r/w LED Stream Select S. LED */ - PHY_MARV_FE_VCT_TX = 0x1a,/* 16 bit r/w VCT Reg. for TXP/N Pins */ - PHY_MARV_FE_VCT_RX = 0x1b,/* 16 bit r/o VCT Reg. for RXP/N Pins */ - PHY_MARV_FE_SPEC_2 = 0x1c,/* 16 bit r/w Specific Control Reg. 2 */ -}; - -enum { - PHY_CT_RESET = 1<<15, /* Bit 15: (sc) clear all PHY related regs */ - PHY_CT_LOOP = 1<<14, /* Bit 14: enable Loopback over PHY */ - PHY_CT_SPS_LSB = 1<<13, /* Bit 13: Speed select, lower bit */ - PHY_CT_ANE = 1<<12, /* Bit 12: Auto-Negotiation Enabled */ - PHY_CT_PDOWN = 1<<11, /* Bit 11: Power Down Mode */ - PHY_CT_ISOL = 1<<10, /* Bit 10: Isolate Mode */ - PHY_CT_RE_CFG = 1<<9, /* Bit 9: (sc) Restart Auto-Negotiation */ - PHY_CT_DUP_MD = 1<<8, /* Bit 8: Duplex Mode */ - PHY_CT_COL_TST = 1<<7, /* Bit 7: Collision Test enabled */ - PHY_CT_SPS_MSB = 1<<6, /* Bit 6: Speed select, upper bit */ -}; - -enum { - PHY_CT_SP1000 = PHY_CT_SPS_MSB, /* enable speed of 1000 Mbps */ - PHY_CT_SP100 = PHY_CT_SPS_LSB, /* enable speed of 100 Mbps */ - PHY_CT_SP10 = 0, /* enable speed of 10 Mbps */ -}; - -enum { - PHY_ST_EXT_ST = 1<<8, /* Bit 8: Extended Status Present */ - - PHY_ST_PRE_SUP = 1<<6, /* Bit 6: Preamble Suppression */ - PHY_ST_AN_OVER = 1<<5, /* Bit 5: Auto-Negotiation Over */ - PHY_ST_REM_FLT = 1<<4, /* Bit 4: Remote Fault Condition Occurred */ - PHY_ST_AN_CAP = 1<<3, /* Bit 3: Auto-Negotiation Capability */ - PHY_ST_LSYNC = 1<<2, /* Bit 2: Link Synchronized */ - PHY_ST_JAB_DET = 1<<1, /* Bit 1: Jabber Detected */ - PHY_ST_EXT_REG = 1<<0, /* Bit 0: Extended Register available */ -}; - -enum { - PHY_I1_OUI_MSK = 0x3f<<10, /* Bit 15..10: Organization Unique ID */ - PHY_I1_MOD_NUM = 0x3f<<4, /* Bit 9.. 4: Model Number */ - PHY_I1_REV_MSK = 0xf, /* Bit 3.. 0: Revision Number */ -}; - -/* different Broadcom PHY Ids */ -enum { - PHY_BCOM_ID1_A1 = 0x6041, - PHY_BCOM_ID1_B2 = 0x6043, - PHY_BCOM_ID1_C0 = 0x6044, - PHY_BCOM_ID1_C5 = 0x6047, -}; - -/* different Marvell PHY Ids */ -enum { - PHY_MARV_ID0_VAL= 0x0141, /* Marvell Unique Identifier */ - PHY_MARV_ID1_B0 = 0x0C23, /* Yukon (PHY 88E1011) */ - PHY_MARV_ID1_B2 = 0x0C25, /* Yukon-Plus (PHY 88E1011) */ - PHY_MARV_ID1_C2 = 0x0CC2, /* Yukon-EC (PHY 88E1111) */ - PHY_MARV_ID1_Y2 = 0x0C91, /* Yukon-2 (PHY 88E1112) */ -}; - -/* Advertisement register bits */ -enum { - PHY_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */ - PHY_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */ - PHY_AN_RF = 1<<13, /* Bit 13: Remote Fault Bits */ - - PHY_AN_PAUSE_ASYM = 1<<11,/* Bit 11: Try for asymmetric */ - PHY_AN_PAUSE_CAP = 1<<10, /* Bit 10: Try for pause */ - PHY_AN_100BASE4 = 1<<9, /* Bit 9: Try for 100mbps 4k packets */ - PHY_AN_100FULL = 1<<8, /* Bit 8: Try for 100mbps full-duplex */ - PHY_AN_100HALF = 1<<7, /* Bit 7: Try for 100mbps half-duplex */ - PHY_AN_10FULL = 1<<6, /* Bit 6: Try for 10mbps full-duplex */ - PHY_AN_10HALF = 1<<5, /* Bit 5: Try for 10mbps half-duplex */ - PHY_AN_CSMA = 1<<0, /* Bit 0: Only selector supported */ - PHY_AN_SEL = 0x1f, /* Bit 4..0: Selector Field, 00001=Ethernet*/ - PHY_AN_FULL = PHY_AN_100FULL | PHY_AN_10FULL | PHY_AN_CSMA, - PHY_AN_ALL = PHY_AN_10HALF | PHY_AN_10FULL | - PHY_AN_100HALF | PHY_AN_100FULL, -}; - -/* Xmac Specific */ -enum { - PHY_X_AN_NXT_PG = 1<<15, /* Bit 15: Request Next Page */ - PHY_X_AN_ACK = 1<<14, /* Bit 14: (ro) Acknowledge Received */ - PHY_X_AN_RFB = 3<<12,/* Bit 13..12: Remote Fault Bits */ - - PHY_X_AN_PAUSE = 3<<7,/* Bit 8.. 7: Pause Bits */ - PHY_X_AN_HD = 1<<6, /* Bit 6: Half Duplex */ - PHY_X_AN_FD = 1<<5, /* Bit 5: Full Duplex */ -}; - -/* Pause Bits (PHY_X_AN_PAUSE and PHY_X_RS_PAUSE) encoding */ -enum { - PHY_X_P_NO_PAUSE= 0<<7,/* Bit 8..7: no Pause Mode */ - PHY_X_P_SYM_MD = 1<<7, /* Bit 8..7: symmetric Pause Mode */ - PHY_X_P_ASYM_MD = 2<<7,/* Bit 8..7: asymmetric Pause Mode */ - PHY_X_P_BOTH_MD = 3<<7,/* Bit 8..7: both Pause Mode */ -}; - - -/***** PHY_XMAC_EXT_STAT 16 bit r/w Extended Status Register *****/ -enum { - PHY_X_EX_FD = 1<<15, /* Bit 15: Device Supports Full Duplex */ - PHY_X_EX_HD = 1<<14, /* Bit 14: Device Supports Half Duplex */ -}; - -/***** PHY_XMAC_RES_ABI 16 bit r/o PHY Resolved Ability *****/ -enum { - PHY_X_RS_PAUSE = 3<<7, /* Bit 8..7: selected Pause Mode */ - PHY_X_RS_HD = 1<<6, /* Bit 6: Half Duplex Mode selected */ - PHY_X_RS_FD = 1<<5, /* Bit 5: Full Duplex Mode selected */ - PHY_X_RS_ABLMIS = 1<<4, /* Bit 4: duplex or pause cap mismatch */ - PHY_X_RS_PAUMIS = 1<<3, /* Bit 3: pause capability mismatch */ -}; - -/* Remote Fault Bits (PHY_X_AN_RFB) encoding */ -enum { - X_RFB_OK = 0<<12,/* Bit 13..12 No errors, Link OK */ - X_RFB_LF = 1<<12,/* Bit 13..12 Link Failure */ - X_RFB_OFF = 2<<12,/* Bit 13..12 Offline */ - X_RFB_AN_ERR = 3<<12,/* Bit 13..12 Auto-Negotiation Error */ -}; - -/* Broadcom-Specific */ -/***** PHY_BCOM_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -enum { - PHY_B_1000C_TEST = 7<<13,/* Bit 15..13: Test Modes */ - PHY_B_1000C_MSE = 1<<12, /* Bit 12: Master/Slave Enable */ - PHY_B_1000C_MSC = 1<<11, /* Bit 11: M/S Configuration */ - PHY_B_1000C_RD = 1<<10, /* Bit 10: Repeater/DTE */ - PHY_B_1000C_AFD = 1<<9, /* Bit 9: Advertise Full Duplex */ - PHY_B_1000C_AHD = 1<<8, /* Bit 8: Advertise Half Duplex */ -}; - -/***** PHY_BCOM_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -/***** PHY_MARV_1000T_STAT 16 bit r/o 1000Base-T Status Reg *****/ -enum { - PHY_B_1000S_MSF = 1<<15, /* Bit 15: Master/Slave Fault */ - PHY_B_1000S_MSR = 1<<14, /* Bit 14: Master/Slave Result */ - PHY_B_1000S_LRS = 1<<13, /* Bit 13: Local Receiver Status */ - PHY_B_1000S_RRS = 1<<12, /* Bit 12: Remote Receiver Status */ - PHY_B_1000S_LP_FD = 1<<11, /* Bit 11: Link Partner can FD */ - PHY_B_1000S_LP_HD = 1<<10, /* Bit 10: Link Partner can HD */ - /* Bit 9..8: reserved */ - PHY_B_1000S_IEC = 0xff, /* Bit 7..0: Idle Error Count */ -}; - -/***** PHY_BCOM_EXT_STAT 16 bit r/o Extended Status Register *****/ -enum { - PHY_B_ES_X_FD_CAP = 1<<15, /* Bit 15: 1000Base-X FD capable */ - PHY_B_ES_X_HD_CAP = 1<<14, /* Bit 14: 1000Base-X HD capable */ - PHY_B_ES_T_FD_CAP = 1<<13, /* Bit 13: 1000Base-T FD capable */ - PHY_B_ES_T_HD_CAP = 1<<12, /* Bit 12: 1000Base-T HD capable */ -}; - -/***** PHY_BCOM_P_EXT_CTRL 16 bit r/w PHY Extended Control Reg *****/ -enum { - PHY_B_PEC_MAC_PHY = 1<<15, /* Bit 15: 10BIT/GMI-Interface */ - PHY_B_PEC_DIS_CROSS = 1<<14, /* Bit 14: Disable MDI Crossover */ - PHY_B_PEC_TX_DIS = 1<<13, /* Bit 13: Tx output Disabled */ - PHY_B_PEC_INT_DIS = 1<<12, /* Bit 12: Interrupts Disabled */ - PHY_B_PEC_F_INT = 1<<11, /* Bit 11: Force Interrupt */ - PHY_B_PEC_BY_45 = 1<<10, /* Bit 10: Bypass 4B5B-Decoder */ - PHY_B_PEC_BY_SCR = 1<<9, /* Bit 9: Bypass Scrambler */ - PHY_B_PEC_BY_MLT3 = 1<<8, /* Bit 8: Bypass MLT3 Encoder */ - PHY_B_PEC_BY_RXA = 1<<7, /* Bit 7: Bypass Rx Alignm. */ - PHY_B_PEC_RES_SCR = 1<<6, /* Bit 6: Reset Scrambler */ - PHY_B_PEC_EN_LTR = 1<<5, /* Bit 5: Ena LED Traffic Mode */ - PHY_B_PEC_LED_ON = 1<<4, /* Bit 4: Force LED's on */ - PHY_B_PEC_LED_OFF = 1<<3, /* Bit 3: Force LED's off */ - PHY_B_PEC_EX_IPG = 1<<2, /* Bit 2: Extend Tx IPG Mode */ - PHY_B_PEC_3_LED = 1<<1, /* Bit 1: Three Link LED mode */ - PHY_B_PEC_HIGH_LA = 1<<0, /* Bit 0: GMII FIFO Elasticy */ -}; - -/***** PHY_BCOM_P_EXT_STAT 16 bit r/o PHY Extended Status Reg *****/ -enum { - PHY_B_PES_CROSS_STAT = 1<<13, /* Bit 13: MDI Crossover Status */ - PHY_B_PES_INT_STAT = 1<<12, /* Bit 12: Interrupt Status */ - PHY_B_PES_RRS = 1<<11, /* Bit 11: Remote Receiver Stat. */ - PHY_B_PES_LRS = 1<<10, /* Bit 10: Local Receiver Stat. */ - PHY_B_PES_LOCKED = 1<<9, /* Bit 9: Locked */ - PHY_B_PES_LS = 1<<8, /* Bit 8: Link Status */ - PHY_B_PES_RF = 1<<7, /* Bit 7: Remote Fault */ - PHY_B_PES_CE_ER = 1<<6, /* Bit 6: Carrier Ext Error */ - PHY_B_PES_BAD_SSD = 1<<5, /* Bit 5: Bad SSD */ - PHY_B_PES_BAD_ESD = 1<<4, /* Bit 4: Bad ESD */ - PHY_B_PES_RX_ER = 1<<3, /* Bit 3: Receive Error */ - PHY_B_PES_TX_ER = 1<<2, /* Bit 2: Transmit Error */ - PHY_B_PES_LOCK_ER = 1<<1, /* Bit 1: Lock Error */ - PHY_B_PES_MLT3_ER = 1<<0, /* Bit 0: MLT3 code Error */ -}; - -/* PHY_BCOM_AUNE_ADV 16 bit r/w Auto-Negotiation Advertisement *****/ -/* PHY_BCOM_AUNE_LP 16 bit r/o Link Partner Ability Reg *****/ -enum { - PHY_B_AN_RF = 1<<13, /* Bit 13: Remote Fault */ - - PHY_B_AN_ASP = 1<<11, /* Bit 11: Asymmetric Pause */ - PHY_B_AN_PC = 1<<10, /* Bit 10: Pause Capable */ -}; - - -/***** PHY_BCOM_FC_CTR 16 bit r/w False Carrier Counter *****/ -enum { - PHY_B_FC_CTR = 0xff, /* Bit 7..0: False Carrier Counter */ - -/***** PHY_BCOM_RNO_CTR 16 bit r/w Receive NOT_OK Counter *****/ - PHY_B_RC_LOC_MSK = 0xff00, /* Bit 15..8: Local Rx NOT_OK cnt */ - PHY_B_RC_REM_MSK = 0x00ff, /* Bit 7..0: Remote Rx NOT_OK cnt */ - -/***** PHY_BCOM_AUX_CTRL 16 bit r/w Auxiliary Control Reg *****/ - PHY_B_AC_L_SQE = 1<<15, /* Bit 15: Low Squelch */ - PHY_B_AC_LONG_PACK = 1<<14, /* Bit 14: Rx Long Packets */ - PHY_B_AC_ER_CTRL = 3<<12,/* Bit 13..12: Edgerate Control */ - /* Bit 11: reserved */ - PHY_B_AC_TX_TST = 1<<10, /* Bit 10: Tx test bit, always 1 */ - /* Bit 9.. 8: reserved */ - PHY_B_AC_DIS_PRF = 1<<7, /* Bit 7: dis part resp filter */ - /* Bit 6: reserved */ - PHY_B_AC_DIS_PM = 1<<5, /* Bit 5: dis power management */ - /* Bit 4: reserved */ - PHY_B_AC_DIAG = 1<<3, /* Bit 3: Diagnostic Mode */ -}; - -/***** PHY_BCOM_AUX_STAT 16 bit r/o Auxiliary Status Reg *****/ -enum { - PHY_B_AS_AN_C = 1<<15, /* Bit 15: AutoNeg complete */ - PHY_B_AS_AN_CA = 1<<14, /* Bit 14: AN Complete Ack */ - PHY_B_AS_ANACK_D = 1<<13, /* Bit 13: AN Ack Detect */ - PHY_B_AS_ANAB_D = 1<<12, /* Bit 12: AN Ability Detect */ - PHY_B_AS_NPW = 1<<11, /* Bit 11: AN Next Page Wait */ - PHY_B_AS_AN_RES_MSK = 7<<8,/* Bit 10..8: AN HDC */ - PHY_B_AS_PDF = 1<<7, /* Bit 7: Parallel Detect. Fault */ - PHY_B_AS_RF = 1<<6, /* Bit 6: Remote Fault */ - PHY_B_AS_ANP_R = 1<<5, /* Bit 5: AN Page Received */ - PHY_B_AS_LP_ANAB = 1<<4, /* Bit 4: LP AN Ability */ - PHY_B_AS_LP_NPAB = 1<<3, /* Bit 3: LP Next Page Ability */ - PHY_B_AS_LS = 1<<2, /* Bit 2: Link Status */ - PHY_B_AS_PRR = 1<<1, /* Bit 1: Pause Resolution-Rx */ - PHY_B_AS_PRT = 1<<0, /* Bit 0: Pause Resolution-Tx */ -}; -#define PHY_B_AS_PAUSE_MSK (PHY_B_AS_PRR | PHY_B_AS_PRT) - -/***** PHY_BCOM_INT_STAT 16 bit r/o Interrupt Status Reg *****/ -/***** PHY_BCOM_INT_MASK 16 bit r/w Interrupt Mask Reg *****/ -enum { - PHY_B_IS_PSE = 1<<14, /* Bit 14: Pair Swap Error */ - PHY_B_IS_MDXI_SC = 1<<13, /* Bit 13: MDIX Status Change */ - PHY_B_IS_HCT = 1<<12, /* Bit 12: counter above 32k */ - PHY_B_IS_LCT = 1<<11, /* Bit 11: counter above 128 */ - PHY_B_IS_AN_PR = 1<<10, /* Bit 10: Page Received */ - PHY_B_IS_NO_HDCL = 1<<9, /* Bit 9: No HCD Link */ - PHY_B_IS_NO_HDC = 1<<8, /* Bit 8: No HCD */ - PHY_B_IS_NEG_USHDC = 1<<7, /* Bit 7: Negotiated Unsup. HCD */ - PHY_B_IS_SCR_S_ER = 1<<6, /* Bit 6: Scrambler Sync Error */ - PHY_B_IS_RRS_CHANGE = 1<<5, /* Bit 5: Remote Rx Stat Change */ - PHY_B_IS_LRS_CHANGE = 1<<4, /* Bit 4: Local Rx Stat Change */ - PHY_B_IS_DUP_CHANGE = 1<<3, /* Bit 3: Duplex Mode Change */ - PHY_B_IS_LSP_CHANGE = 1<<2, /* Bit 2: Link Speed Change */ - PHY_B_IS_LST_CHANGE = 1<<1, /* Bit 1: Link Status Changed */ - PHY_B_IS_CRC_ER = 1<<0, /* Bit 0: CRC Error */ -}; -#define PHY_B_DEF_MSK \ - (~(PHY_B_IS_PSE | PHY_B_IS_AN_PR | PHY_B_IS_DUP_CHANGE | \ - PHY_B_IS_LSP_CHANGE | PHY_B_IS_LST_CHANGE)) - -/* Pause Bits (PHY_B_AN_ASP and PHY_B_AN_PC) encoding */ -enum { - PHY_B_P_NO_PAUSE = 0<<10,/* Bit 11..10: no Pause Mode */ - PHY_B_P_SYM_MD = 1<<10, /* Bit 11..10: symmetric Pause Mode */ - PHY_B_P_ASYM_MD = 2<<10,/* Bit 11..10: asymmetric Pause Mode */ - PHY_B_P_BOTH_MD = 3<<10,/* Bit 11..10: both Pause Mode */ -}; -/* - * Resolved Duplex mode and Capabilities (Aux Status Summary Reg) - */ -enum { - PHY_B_RES_1000FD = 7<<8,/* Bit 10..8: 1000Base-T Full Dup. */ - PHY_B_RES_1000HD = 6<<8,/* Bit 10..8: 1000Base-T Half Dup. */ -}; - -/** Marvell-Specific */ -enum { - PHY_M_AN_NXT_PG = 1<<15, /* Request Next Page */ - PHY_M_AN_ACK = 1<<14, /* (ro) Acknowledge Received */ - PHY_M_AN_RF = 1<<13, /* Remote Fault */ - - PHY_M_AN_ASP = 1<<11, /* Asymmetric Pause */ - PHY_M_AN_PC = 1<<10, /* MAC Pause implemented */ - PHY_M_AN_100_T4 = 1<<9, /* Not cap. 100Base-T4 (always 0) */ - PHY_M_AN_100_FD = 1<<8, /* Advertise 100Base-TX Full Duplex */ - PHY_M_AN_100_HD = 1<<7, /* Advertise 100Base-TX Half Duplex */ - PHY_M_AN_10_FD = 1<<6, /* Advertise 10Base-TX Full Duplex */ - PHY_M_AN_10_HD = 1<<5, /* Advertise 10Base-TX Half Duplex */ - PHY_M_AN_SEL_MSK =0x1f<<4, /* Bit 4.. 0: Selector Field Mask */ -}; - -/* special defines for FIBER (88E1011S only) */ -enum { - PHY_M_AN_ASP_X = 1<<8, /* Asymmetric Pause */ - PHY_M_AN_PC_X = 1<<7, /* MAC Pause implemented */ - PHY_M_AN_1000X_AHD = 1<<6, /* Advertise 10000Base-X Half Duplex */ - PHY_M_AN_1000X_AFD = 1<<5, /* Advertise 10000Base-X Full Duplex */ -}; - -/* Pause Bits (PHY_M_AN_ASP_X and PHY_M_AN_PC_X) encoding */ -enum { - PHY_M_P_NO_PAUSE_X = 0<<7,/* Bit 8.. 7: no Pause Mode */ - PHY_M_P_SYM_MD_X = 1<<7, /* Bit 8.. 7: symmetric Pause Mode */ - PHY_M_P_ASYM_MD_X = 2<<7,/* Bit 8.. 7: asymmetric Pause Mode */ - PHY_M_P_BOTH_MD_X = 3<<7,/* Bit 8.. 7: both Pause Mode */ -}; - -/***** PHY_MARV_1000T_CTRL 16 bit r/w 1000Base-T Control Reg *****/ -enum { - PHY_M_1000C_TEST= 7<<13,/* Bit 15..13: Test Modes */ - PHY_M_1000C_MSE = 1<<12, /* Manual Master/Slave Enable */ - PHY_M_1000C_MSC = 1<<11, /* M/S Configuration (1=Master) */ - PHY_M_1000C_MPD = 1<<10, /* Multi-Port Device */ - PHY_M_1000C_AFD = 1<<9, /* Advertise Full Duplex */ - PHY_M_1000C_AHD = 1<<8, /* Advertise Half Duplex */ -}; - -/***** PHY_MARV_PHY_CTRL 16 bit r/w PHY Specific Ctrl Reg *****/ -enum { - PHY_M_PC_TX_FFD_MSK = 3<<14,/* Bit 15..14: Tx FIFO Depth Mask */ - PHY_M_PC_RX_FFD_MSK = 3<<12,/* Bit 13..12: Rx FIFO Depth Mask */ - PHY_M_PC_ASS_CRS_TX = 1<<11, /* Assert CRS on Transmit */ - PHY_M_PC_FL_GOOD = 1<<10, /* Force Link Good */ - PHY_M_PC_EN_DET_MSK = 3<<8,/* Bit 9.. 8: Energy Detect Mask */ - PHY_M_PC_ENA_EXT_D = 1<<7, /* Enable Ext. Distance (10BT) */ - PHY_M_PC_MDIX_MSK = 3<<5,/* Bit 6.. 5: MDI/MDIX Config. Mask */ - PHY_M_PC_DIS_125CLK = 1<<4, /* Disable 125 CLK */ - PHY_M_PC_MAC_POW_UP = 1<<3, /* MAC Power up */ - PHY_M_PC_SQE_T_ENA = 1<<2, /* SQE Test Enabled */ - PHY_M_PC_POL_R_DIS = 1<<1, /* Polarity Reversal Disabled */ - PHY_M_PC_DIS_JABBER = 1<<0, /* Disable Jabber */ -}; - -enum { - PHY_M_PC_EN_DET = 2<<8, /* Energy Detect (Mode 1) */ - PHY_M_PC_EN_DET_PLUS = 3<<8, /* Energy Detect Plus (Mode 2) */ -}; - -enum { - PHY_M_PC_MAN_MDI = 0, /* 00 = Manual MDI configuration */ - PHY_M_PC_MAN_MDIX = 1, /* 01 = Manual MDIX configuration */ - PHY_M_PC_ENA_AUTO = 3, /* 11 = Enable Automatic Crossover */ -}; - -/* for 10/100 Fast Ethernet PHY (88E3082 only) */ -enum { - PHY_M_PC_ENA_DTE_DT = 1<<15, /* Enable Data Terminal Equ. (DTE) Detect */ - PHY_M_PC_ENA_ENE_DT = 1<<14, /* Enable Energy Detect (sense & pulse) */ - PHY_M_PC_DIS_NLP_CK = 1<<13, /* Disable Normal Link Puls (NLP) Check */ - PHY_M_PC_ENA_LIP_NP = 1<<12, /* Enable Link Partner Next Page Reg. */ - PHY_M_PC_DIS_NLP_GN = 1<<11, /* Disable Normal Link Puls Generation */ - - PHY_M_PC_DIS_SCRAMB = 1<<9, /* Disable Scrambler */ - PHY_M_PC_DIS_FEFI = 1<<8, /* Disable Far End Fault Indic. (FEFI) */ - - PHY_M_PC_SH_TP_SEL = 1<<6, /* Shielded Twisted Pair Select */ - PHY_M_PC_RX_FD_MSK = 3<<2,/* Bit 3.. 2: Rx FIFO Depth Mask */ -}; - -/***** PHY_MARV_PHY_STAT 16 bit r/o PHY Specific Status Reg *****/ -enum { - PHY_M_PS_SPEED_MSK = 3<<14, /* Bit 15..14: Speed Mask */ - PHY_M_PS_SPEED_1000 = 1<<15, /* 10 = 1000 Mbps */ - PHY_M_PS_SPEED_100 = 1<<14, /* 01 = 100 Mbps */ - PHY_M_PS_SPEED_10 = 0, /* 00 = 10 Mbps */ - PHY_M_PS_FULL_DUP = 1<<13, /* Full Duplex */ - PHY_M_PS_PAGE_REC = 1<<12, /* Page Received */ - PHY_M_PS_SPDUP_RES = 1<<11, /* Speed & Duplex Resolved */ - PHY_M_PS_LINK_UP = 1<<10, /* Link Up */ - PHY_M_PS_CABLE_MSK = 7<<7, /* Bit 9.. 7: Cable Length Mask */ - PHY_M_PS_MDI_X_STAT = 1<<6, /* MDI Crossover Stat (1=MDIX) */ - PHY_M_PS_DOWNS_STAT = 1<<5, /* Downshift Status (1=downsh.) */ - PHY_M_PS_ENDET_STAT = 1<<4, /* Energy Detect Status (1=act) */ - PHY_M_PS_TX_P_EN = 1<<3, /* Tx Pause Enabled */ - PHY_M_PS_RX_P_EN = 1<<2, /* Rx Pause Enabled */ - PHY_M_PS_POL_REV = 1<<1, /* Polarity Reversed */ - PHY_M_PS_JABBER = 1<<0, /* Jabber */ -}; - -#define PHY_M_PS_PAUSE_MSK (PHY_M_PS_TX_P_EN | PHY_M_PS_RX_P_EN) - -/* for 10/100 Fast Ethernet PHY (88E3082 only) */ -enum { - PHY_M_PS_DTE_DETECT = 1<<15, /* Data Terminal Equipment (DTE) Detected */ - PHY_M_PS_RES_SPEED = 1<<14, /* Resolved Speed (1=100 Mbps, 0=10 Mbps */ -}; - -enum { - PHY_M_IS_AN_ERROR = 1<<15, /* Auto-Negotiation Error */ - PHY_M_IS_LSP_CHANGE = 1<<14, /* Link Speed Changed */ - PHY_M_IS_DUP_CHANGE = 1<<13, /* Duplex Mode Changed */ - PHY_M_IS_AN_PR = 1<<12, /* Page Received */ - PHY_M_IS_AN_COMPL = 1<<11, /* Auto-Negotiation Completed */ - PHY_M_IS_LST_CHANGE = 1<<10, /* Link Status Changed */ - PHY_M_IS_SYMB_ERROR = 1<<9, /* Symbol Error */ - PHY_M_IS_FALSE_CARR = 1<<8, /* False Carrier */ - PHY_M_IS_FIFO_ERROR = 1<<7, /* FIFO Overflow/Underrun Error */ - PHY_M_IS_MDI_CHANGE = 1<<6, /* MDI Crossover Changed */ - PHY_M_IS_DOWNSH_DET = 1<<5, /* Downshift Detected */ - PHY_M_IS_END_CHANGE = 1<<4, /* Energy Detect Changed */ - - PHY_M_IS_DTE_CHANGE = 1<<2, /* DTE Power Det. Status Changed */ - PHY_M_IS_POL_CHANGE = 1<<1, /* Polarity Changed */ - PHY_M_IS_JABBER = 1<<0, /* Jabber */ - - PHY_M_IS_DEF_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_LSP_CHANGE | - PHY_M_IS_LST_CHANGE | PHY_M_IS_FIFO_ERROR, - - PHY_M_IS_AN_MSK = PHY_M_IS_AN_ERROR | PHY_M_IS_AN_COMPL, -}; - -/***** PHY_MARV_EXT_CTRL 16 bit r/w Ext. PHY Specific Ctrl *****/ -enum { - PHY_M_EC_ENA_BC_EXT = 1<<15, /* Enable Block Carr. Ext. (88E1111 only) */ - PHY_M_EC_ENA_LIN_LB = 1<<14, /* Enable Line Loopback (88E1111 only) */ - - PHY_M_EC_DIS_LINK_P = 1<<12, /* Disable Link Pulses (88E1111 only) */ - PHY_M_EC_M_DSC_MSK = 3<<10, /* Bit 11..10: Master Downshift Counter */ - /* (88E1011 only) */ - PHY_M_EC_S_DSC_MSK = 3<<8, /* Bit 9.. 8: Slave Downshift Counter */ - /* (88E1011 only) */ - PHY_M_EC_M_DSC_MSK2 = 7<<9, /* Bit 11.. 9: Master Downshift Counter */ - /* (88E1111 only) */ - PHY_M_EC_DOWN_S_ENA = 1<<8, /* Downshift Enable (88E1111 only) */ - /* !!! Errata in spec. (1 = disable) */ - PHY_M_EC_RX_TIM_CT = 1<<7, /* RGMII Rx Timing Control*/ - PHY_M_EC_MAC_S_MSK = 7<<4, /* Bit 6.. 4: Def. MAC interface speed */ - PHY_M_EC_FIB_AN_ENA = 1<<3, /* Fiber Auto-Neg. Enable (88E1011S only) */ - PHY_M_EC_DTE_D_ENA = 1<<2, /* DTE Detect Enable (88E1111 only) */ - PHY_M_EC_TX_TIM_CT = 1<<1, /* RGMII Tx Timing Control */ - PHY_M_EC_TRANS_DIS = 1<<0, /* Transmitter Disable (88E1111 only) */}; - -#define PHY_M_EC_M_DSC(x) ((u16)(x)<<10) /* 00=1x; 01=2x; 10=3x; 11=4x */ -#define PHY_M_EC_S_DSC(x) ((u16)(x)<<8) /* 00=dis; 01=1x; 10=2x; 11=3x */ -#define PHY_M_EC_MAC_S(x) ((u16)(x)<<4) /* 01X=0; 110=2.5; 111=25 (MHz) */ - -#define PHY_M_EC_M_DSC_2(x) ((u16)(x)<<9) /* 000=1x; 001=2x; 010=3x; 011=4x */ - /* 100=5x; 101=6x; 110=7x; 111=8x */ -enum { - MAC_TX_CLK_0_MHZ = 2, - MAC_TX_CLK_2_5_MHZ = 6, - MAC_TX_CLK_25_MHZ = 7, -}; - -/***** PHY_MARV_LED_CTRL 16 bit r/w LED Control Reg *****/ -enum { - PHY_M_LEDC_DIS_LED = 1<<15, /* Disable LED */ - PHY_M_LEDC_PULS_MSK = 7<<12,/* Bit 14..12: Pulse Stretch Mask */ - PHY_M_LEDC_F_INT = 1<<11, /* Force Interrupt */ - PHY_M_LEDC_BL_R_MSK = 7<<8,/* Bit 10.. 8: Blink Rate Mask */ - PHY_M_LEDC_DP_C_LSB = 1<<7, /* Duplex Control (LSB, 88E1111 only) */ - PHY_M_LEDC_TX_C_LSB = 1<<6, /* Tx Control (LSB, 88E1111 only) */ - PHY_M_LEDC_LK_C_MSK = 7<<3,/* Bit 5.. 3: Link Control Mask */ - /* (88E1111 only) */ -}; -#define PHY_M_LED_PULS_DUR(x) (((u16)(x)<<12) & PHY_M_LEDC_PULS_MSK) -#define PHY_M_LED_BLINK_RT(x) (((u16)(x)<<8) & PHY_M_LEDC_BL_R_MSK) - -enum { - PHY_M_LEDC_LINK_MSK = 3<<3, /* Bit 4.. 3: Link Control Mask */ - /* (88E1011 only) */ - PHY_M_LEDC_DP_CTRL = 1<<2, /* Duplex Control */ - PHY_M_LEDC_DP_C_MSB = 1<<2, /* Duplex Control (MSB, 88E1111 only) */ - PHY_M_LEDC_RX_CTRL = 1<<1, /* Rx Activity / Link */ - PHY_M_LEDC_TX_CTRL = 1<<0, /* Tx Activity / Link */ - PHY_M_LEDC_TX_C_MSB = 1<<0, /* Tx Control (MSB, 88E1111 only) */ -}; - -enum { - PULS_NO_STR = 0, /* no pulse stretching */ - PULS_21MS = 1, /* 21 ms to 42 ms */ - PULS_42MS = 2, /* 42 ms to 84 ms */ - PULS_84MS = 3, /* 84 ms to 170 ms */ - PULS_170MS = 4, /* 170 ms to 340 ms */ - PULS_340MS = 5, /* 340 ms to 670 ms */ - PULS_670MS = 6, /* 670 ms to 1.3 s */ - PULS_1300MS = 7, /* 1.3 s to 2.7 s */ -}; - - -enum { - BLINK_42MS = 0, /* 42 ms */ - BLINK_84MS = 1, /* 84 ms */ - BLINK_170MS = 2, /* 170 ms */ - BLINK_340MS = 3, /* 340 ms */ - BLINK_670MS = 4, /* 670 ms */ -}; - -/***** PHY_MARV_LED_OVER 16 bit r/w Manual LED Override Reg *****/ -#define PHY_M_LED_MO_SGMII(x) ((x)<<14) /* Bit 15..14: SGMII AN Timer */ - /* Bit 13..12: reserved */ -#define PHY_M_LED_MO_DUP(x) ((x)<<10) /* Bit 11..10: Duplex */ -#define PHY_M_LED_MO_10(x) ((x)<<8) /* Bit 9.. 8: Link 10 */ -#define PHY_M_LED_MO_100(x) ((x)<<6) /* Bit 7.. 6: Link 100 */ -#define PHY_M_LED_MO_1000(x) ((x)<<4) /* Bit 5.. 4: Link 1000 */ -#define PHY_M_LED_MO_RX(x) ((x)<<2) /* Bit 3.. 2: Rx */ -#define PHY_M_LED_MO_TX(x) ((x)<<0) /* Bit 1.. 0: Tx */ - -enum { - MO_LED_NORM = 0, - MO_LED_BLINK = 1, - MO_LED_OFF = 2, - MO_LED_ON = 3, -}; - -/***** PHY_MARV_EXT_CTRL_2 16 bit r/w Ext. PHY Specific Ctrl 2 *****/ -enum { - PHY_M_EC2_FI_IMPED = 1<<6, /* Fiber Input Impedance */ - PHY_M_EC2_FO_IMPED = 1<<5, /* Fiber Output Impedance */ - PHY_M_EC2_FO_M_CLK = 1<<4, /* Fiber Mode Clock Enable */ - PHY_M_EC2_FO_BOOST = 1<<3, /* Fiber Output Boost */ - PHY_M_EC2_FO_AM_MSK = 7, /* Bit 2.. 0: Fiber Output Amplitude */ -}; - -/***** PHY_MARV_EXT_P_STAT 16 bit r/w Ext. PHY Specific Status *****/ -enum { - PHY_M_FC_AUTO_SEL = 1<<15, /* Fiber/Copper Auto Sel. Dis. */ - PHY_M_FC_AN_REG_ACC = 1<<14, /* Fiber/Copper AN Reg. Access */ - PHY_M_FC_RESOLUTION = 1<<13, /* Fiber/Copper Resolution */ - PHY_M_SER_IF_AN_BP = 1<<12, /* Ser. IF AN Bypass Enable */ - PHY_M_SER_IF_BP_ST = 1<<11, /* Ser. IF AN Bypass Status */ - PHY_M_IRQ_POLARITY = 1<<10, /* IRQ polarity */ - PHY_M_DIS_AUT_MED = 1<<9, /* Disable Aut. Medium Reg. Selection */ - /* (88E1111 only) */ - /* Bit 9.. 4: reserved (88E1011 only) */ - PHY_M_UNDOC1 = 1<<7, /* undocumented bit !! */ - PHY_M_DTE_POW_STAT = 1<<4, /* DTE Power Status (88E1111 only) */ - PHY_M_MODE_MASK = 0xf, /* Bit 3.. 0: copy of HWCFG MODE[3:0] */ -}; - -/***** PHY_MARV_CABLE_DIAG 16 bit r/o Cable Diagnostic Reg *****/ -enum { - PHY_M_CABD_ENA_TEST = 1<<15, /* Enable Test (Page 0) */ - PHY_M_CABD_DIS_WAIT = 1<<15, /* Disable Waiting Period (Page 1) */ - /* (88E1111 only) */ - PHY_M_CABD_STAT_MSK = 3<<13, /* Bit 14..13: Status Mask */ - PHY_M_CABD_AMPL_MSK = 0x1f<<8, /* Bit 12.. 8: Amplitude Mask */ - /* (88E1111 only) */ - PHY_M_CABD_DIST_MSK = 0xff, /* Bit 7.. 0: Distance Mask */ -}; - -/* values for Cable Diagnostic Status (11=fail; 00=OK; 10=open; 01=short) */ -enum { - CABD_STAT_NORMAL= 0, - CABD_STAT_SHORT = 1, - CABD_STAT_OPEN = 2, - CABD_STAT_FAIL = 3, -}; - -/* for 10/100 Fast Ethernet PHY (88E3082 only) */ -/***** PHY_MARV_FE_LED_PAR 16 bit r/w LED Parallel Select Reg. *****/ - /* Bit 15..12: reserved (used internally) */ -enum { - PHY_M_FELP_LED2_MSK = 0xf<<8, /* Bit 11.. 8: LED2 Mask (LINK) */ - PHY_M_FELP_LED1_MSK = 0xf<<4, /* Bit 7.. 4: LED1 Mask (ACT) */ - PHY_M_FELP_LED0_MSK = 0xf, /* Bit 3.. 0: LED0 Mask (SPEED) */ -}; - -#define PHY_M_FELP_LED2_CTRL(x) (((x)<<8) & PHY_M_FELP_LED2_MSK) -#define PHY_M_FELP_LED1_CTRL(x) (((x)<<4) & PHY_M_FELP_LED1_MSK) -#define PHY_M_FELP_LED0_CTRL(x) (((x)<<0) & PHY_M_FELP_LED0_MSK) - -enum { - LED_PAR_CTRL_COLX = 0x00, - LED_PAR_CTRL_ERROR = 0x01, - LED_PAR_CTRL_DUPLEX = 0x02, - LED_PAR_CTRL_DP_COL = 0x03, - LED_PAR_CTRL_SPEED = 0x04, - LED_PAR_CTRL_LINK = 0x05, - LED_PAR_CTRL_TX = 0x06, - LED_PAR_CTRL_RX = 0x07, - LED_PAR_CTRL_ACT = 0x08, - LED_PAR_CTRL_LNK_RX = 0x09, - LED_PAR_CTRL_LNK_AC = 0x0a, - LED_PAR_CTRL_ACT_BL = 0x0b, - LED_PAR_CTRL_TX_BL = 0x0c, - LED_PAR_CTRL_RX_BL = 0x0d, - LED_PAR_CTRL_COL_BL = 0x0e, - LED_PAR_CTRL_INACT = 0x0f -}; - -/*****,PHY_MARV_FE_SPEC_2 16 bit r/w Specific Control Reg. 2 *****/ -enum { - PHY_M_FESC_DIS_WAIT = 1<<2, /* Disable TDR Waiting Period */ - PHY_M_FESC_ENA_MCLK = 1<<1, /* Enable MAC Rx Clock in sleep mode */ - PHY_M_FESC_SEL_CL_A = 1<<0, /* Select Class A driver (100B-TX) */ -}; - - -/***** PHY_MARV_PHY_CTRL (page 3) 16 bit r/w LED Control Reg. *****/ -enum { - PHY_M_LEDC_LOS_MSK = 0xf<<12, /* Bit 15..12: LOS LED Ctrl. Mask */ - PHY_M_LEDC_INIT_MSK = 0xf<<8, /* Bit 11.. 8: INIT LED Ctrl. Mask */ - PHY_M_LEDC_STA1_MSK = 0xf<<4, /* Bit 7.. 4: STAT1 LED Ctrl. Mask */ - PHY_M_LEDC_STA0_MSK = 0xf, /* Bit 3.. 0: STAT0 LED Ctrl. Mask */ -}; - -#define PHY_M_LEDC_LOS_CTRL(x) (((x)<<12) & PHY_M_LEDC_LOS_MSK) -#define PHY_M_LEDC_INIT_CTRL(x) (((x)<<8) & PHY_M_LEDC_INIT_MSK) -#define PHY_M_LEDC_STA1_CTRL(x) (((x)<<4) & PHY_M_LEDC_STA1_MSK) -#define PHY_M_LEDC_STA0_CTRL(x) (((x)<<0) & PHY_M_LEDC_STA0_MSK) - -/* GMAC registers */ -/* Port Registers */ -enum { - GM_GP_STAT = 0x0000, /* 16 bit r/o General Purpose Status */ - GM_GP_CTRL = 0x0004, /* 16 bit r/w General Purpose Control */ - GM_TX_CTRL = 0x0008, /* 16 bit r/w Transmit Control Reg. */ - GM_RX_CTRL = 0x000c, /* 16 bit r/w Receive Control Reg. */ - GM_TX_FLOW_CTRL = 0x0010, /* 16 bit r/w Transmit Flow-Control */ - GM_TX_PARAM = 0x0014, /* 16 bit r/w Transmit Parameter Reg. */ - GM_SERIAL_MODE = 0x0018, /* 16 bit r/w Serial Mode Register */ -/* Source Address Registers */ - GM_SRC_ADDR_1L = 0x001c, /* 16 bit r/w Source Address 1 (low) */ - GM_SRC_ADDR_1M = 0x0020, /* 16 bit r/w Source Address 1 (middle) */ - GM_SRC_ADDR_1H = 0x0024, /* 16 bit r/w Source Address 1 (high) */ - GM_SRC_ADDR_2L = 0x0028, /* 16 bit r/w Source Address 2 (low) */ - GM_SRC_ADDR_2M = 0x002c, /* 16 bit r/w Source Address 2 (middle) */ - GM_SRC_ADDR_2H = 0x0030, /* 16 bit r/w Source Address 2 (high) */ - -/* Multicast Address Hash Registers */ - GM_MC_ADDR_H1 = 0x0034, /* 16 bit r/w Multicast Address Hash 1 */ - GM_MC_ADDR_H2 = 0x0038, /* 16 bit r/w Multicast Address Hash 2 */ - GM_MC_ADDR_H3 = 0x003c, /* 16 bit r/w Multicast Address Hash 3 */ - GM_MC_ADDR_H4 = 0x0040, /* 16 bit r/w Multicast Address Hash 4 */ - -/* Interrupt Source Registers */ - GM_TX_IRQ_SRC = 0x0044, /* 16 bit r/o Tx Overflow IRQ Source */ - GM_RX_IRQ_SRC = 0x0048, /* 16 bit r/o Rx Overflow IRQ Source */ - GM_TR_IRQ_SRC = 0x004c, /* 16 bit r/o Tx/Rx Over. IRQ Source */ - -/* Interrupt Mask Registers */ - GM_TX_IRQ_MSK = 0x0050, /* 16 bit r/w Tx Overflow IRQ Mask */ - GM_RX_IRQ_MSK = 0x0054, /* 16 bit r/w Rx Overflow IRQ Mask */ - GM_TR_IRQ_MSK = 0x0058, /* 16 bit r/w Tx/Rx Over. IRQ Mask */ - -/* Serial Management Interface (SMI) Registers */ - GM_SMI_CTRL = 0x0080, /* 16 bit r/w SMI Control Register */ - GM_SMI_DATA = 0x0084, /* 16 bit r/w SMI Data Register */ - GM_PHY_ADDR = 0x0088, /* 16 bit r/w GPHY Address Register */ -}; - -/* MIB Counters */ -#define GM_MIB_CNT_BASE 0x0100 /* Base Address of MIB Counters */ -#define GM_MIB_CNT_SIZE 44 /* Number of MIB Counters */ - -/* - * MIB Counters base address definitions (low word) - - * use offset 4 for access to high word (32 bit r/o) - */ -enum { - GM_RXF_UC_OK = GM_MIB_CNT_BASE + 0, /* Unicast Frames Received OK */ - GM_RXF_BC_OK = GM_MIB_CNT_BASE + 8, /* Broadcast Frames Received OK */ - GM_RXF_MPAUSE = GM_MIB_CNT_BASE + 16, /* Pause MAC Ctrl Frames Received */ - GM_RXF_MC_OK = GM_MIB_CNT_BASE + 24, /* Multicast Frames Received OK */ - GM_RXF_FCS_ERR = GM_MIB_CNT_BASE + 32, /* Rx Frame Check Seq. Error */ - /* GM_MIB_CNT_BASE + 40: reserved */ - GM_RXO_OK_LO = GM_MIB_CNT_BASE + 48, /* Octets Received OK Low */ - GM_RXO_OK_HI = GM_MIB_CNT_BASE + 56, /* Octets Received OK High */ - GM_RXO_ERR_LO = GM_MIB_CNT_BASE + 64, /* Octets Received Invalid Low */ - GM_RXO_ERR_HI = GM_MIB_CNT_BASE + 72, /* Octets Received Invalid High */ - GM_RXF_SHT = GM_MIB_CNT_BASE + 80, /* Frames <64 Byte Received OK */ - GM_RXE_FRAG = GM_MIB_CNT_BASE + 88, /* Frames <64 Byte Received with FCS Err */ - GM_RXF_64B = GM_MIB_CNT_BASE + 96, /* 64 Byte Rx Frame */ - GM_RXF_127B = GM_MIB_CNT_BASE + 104, /* 65-127 Byte Rx Frame */ - GM_RXF_255B = GM_MIB_CNT_BASE + 112, /* 128-255 Byte Rx Frame */ - GM_RXF_511B = GM_MIB_CNT_BASE + 120, /* 256-511 Byte Rx Frame */ - GM_RXF_1023B = GM_MIB_CNT_BASE + 128, /* 512-1023 Byte Rx Frame */ - GM_RXF_1518B = GM_MIB_CNT_BASE + 136, /* 1024-1518 Byte Rx Frame */ - GM_RXF_MAX_SZ = GM_MIB_CNT_BASE + 144, /* 1519-MaxSize Byte Rx Frame */ - GM_RXF_LNG_ERR = GM_MIB_CNT_BASE + 152, /* Rx Frame too Long Error */ - GM_RXF_JAB_PKT = GM_MIB_CNT_BASE + 160, /* Rx Jabber Packet Frame */ - /* GM_MIB_CNT_BASE + 168: reserved */ - GM_RXE_FIFO_OV = GM_MIB_CNT_BASE + 176, /* Rx FIFO overflow Event */ - /* GM_MIB_CNT_BASE + 184: reserved */ - GM_TXF_UC_OK = GM_MIB_CNT_BASE + 192, /* Unicast Frames Xmitted OK */ - GM_TXF_BC_OK = GM_MIB_CNT_BASE + 200, /* Broadcast Frames Xmitted OK */ - GM_TXF_MPAUSE = GM_MIB_CNT_BASE + 208, /* Pause MAC Ctrl Frames Xmitted */ - GM_TXF_MC_OK = GM_MIB_CNT_BASE + 216, /* Multicast Frames Xmitted OK */ - GM_TXO_OK_LO = GM_MIB_CNT_BASE + 224, /* Octets Transmitted OK Low */ - GM_TXO_OK_HI = GM_MIB_CNT_BASE + 232, /* Octets Transmitted OK High */ - GM_TXF_64B = GM_MIB_CNT_BASE + 240, /* 64 Byte Tx Frame */ - GM_TXF_127B = GM_MIB_CNT_BASE + 248, /* 65-127 Byte Tx Frame */ - GM_TXF_255B = GM_MIB_CNT_BASE + 256, /* 128-255 Byte Tx Frame */ - GM_TXF_511B = GM_MIB_CNT_BASE + 264, /* 256-511 Byte Tx Frame */ - GM_TXF_1023B = GM_MIB_CNT_BASE + 272, /* 512-1023 Byte Tx Frame */ - GM_TXF_1518B = GM_MIB_CNT_BASE + 280, /* 1024-1518 Byte Tx Frame */ - GM_TXF_MAX_SZ = GM_MIB_CNT_BASE + 288, /* 1519-MaxSize Byte Tx Frame */ - - GM_TXF_COL = GM_MIB_CNT_BASE + 304, /* Tx Collision */ - GM_TXF_LAT_COL = GM_MIB_CNT_BASE + 312, /* Tx Late Collision */ - GM_TXF_ABO_COL = GM_MIB_CNT_BASE + 320, /* Tx aborted due to Exces. Col. */ - GM_TXF_MUL_COL = GM_MIB_CNT_BASE + 328, /* Tx Multiple Collision */ - GM_TXF_SNG_COL = GM_MIB_CNT_BASE + 336, /* Tx Single Collision */ - GM_TXE_FIFO_UR = GM_MIB_CNT_BASE + 344, /* Tx FIFO Underrun Event */ -}; - -/* GMAC Bit Definitions */ -/* GM_GP_STAT 16 bit r/o General Purpose Status Register */ -enum { - GM_GPSR_SPEED = 1<<15, /* Bit 15: Port Speed (1 = 100 Mbps) */ - GM_GPSR_DUPLEX = 1<<14, /* Bit 14: Duplex Mode (1 = Full) */ - GM_GPSR_FC_TX_DIS = 1<<13, /* Bit 13: Tx Flow-Control Mode Disabled */ - GM_GPSR_LINK_UP = 1<<12, /* Bit 12: Link Up Status */ - GM_GPSR_PAUSE = 1<<11, /* Bit 11: Pause State */ - GM_GPSR_TX_ACTIVE = 1<<10, /* Bit 10: Tx in Progress */ - GM_GPSR_EXC_COL = 1<<9, /* Bit 9: Excessive Collisions Occurred */ - GM_GPSR_LAT_COL = 1<<8, /* Bit 8: Late Collisions Occurred */ - - GM_GPSR_PHY_ST_CH = 1<<5, /* Bit 5: PHY Status Change */ - GM_GPSR_GIG_SPEED = 1<<4, /* Bit 4: Gigabit Speed (1 = 1000 Mbps) */ - GM_GPSR_PART_MODE = 1<<3, /* Bit 3: Partition mode */ - GM_GPSR_FC_RX_DIS = 1<<2, /* Bit 2: Rx Flow-Control Mode Disabled */ - GM_GPSR_PROM_EN = 1<<1, /* Bit 1: Promiscuous Mode Enabled */ -}; - -/* GM_GP_CTRL 16 bit r/w General Purpose Control Register */ -enum { - GM_GPCR_PROM_ENA = 1<<14, /* Bit 14: Enable Promiscuous Mode */ - GM_GPCR_FC_TX_DIS = 1<<13, /* Bit 13: Disable Tx Flow-Control Mode */ - GM_GPCR_TX_ENA = 1<<12, /* Bit 12: Enable Transmit */ - GM_GPCR_RX_ENA = 1<<11, /* Bit 11: Enable Receive */ - GM_GPCR_BURST_ENA = 1<<10, /* Bit 10: Enable Burst Mode */ - GM_GPCR_LOOP_ENA = 1<<9, /* Bit 9: Enable MAC Loopback Mode */ - GM_GPCR_PART_ENA = 1<<8, /* Bit 8: Enable Partition Mode */ - GM_GPCR_GIGS_ENA = 1<<7, /* Bit 7: Gigabit Speed (1000 Mbps) */ - GM_GPCR_FL_PASS = 1<<6, /* Bit 6: Force Link Pass */ - GM_GPCR_DUP_FULL = 1<<5, /* Bit 5: Full Duplex Mode */ - GM_GPCR_FC_RX_DIS = 1<<4, /* Bit 4: Disable Rx Flow-Control Mode */ - GM_GPCR_SPEED_100 = 1<<3, /* Bit 3: Port Speed 100 Mbps */ - GM_GPCR_AU_DUP_DIS = 1<<2, /* Bit 2: Disable Auto-Update Duplex */ - GM_GPCR_AU_FCT_DIS = 1<<1, /* Bit 1: Disable Auto-Update Flow-C. */ - GM_GPCR_AU_SPD_DIS = 1<<0, /* Bit 0: Disable Auto-Update Speed */ -}; - -#define GM_GPCR_SPEED_1000 (GM_GPCR_GIGS_ENA | GM_GPCR_SPEED_100) -#define GM_GPCR_AU_ALL_DIS (GM_GPCR_AU_DUP_DIS | GM_GPCR_AU_FCT_DIS|GM_GPCR_AU_SPD_DIS) - -/* GM_TX_CTRL 16 bit r/w Transmit Control Register */ -enum { - GM_TXCR_FORCE_JAM = 1<<15, /* Bit 15: Force Jam / Flow-Control */ - GM_TXCR_CRC_DIS = 1<<14, /* Bit 14: Disable insertion of CRC */ - GM_TXCR_PAD_DIS = 1<<13, /* Bit 13: Disable padding of packets */ - GM_TXCR_COL_THR_MSK = 7<<10, /* Bit 12..10: Collision Threshold */ -}; - -#define TX_COL_THR(x) (((x)<<10) & GM_TXCR_COL_THR_MSK) -#define TX_COL_DEF 0x04 /* late collision after 64 byte */ - -/* GM_RX_CTRL 16 bit r/w Receive Control Register */ -enum { - GM_RXCR_UCF_ENA = 1<<15, /* Bit 15: Enable Unicast filtering */ - GM_RXCR_MCF_ENA = 1<<14, /* Bit 14: Enable Multicast filtering */ - GM_RXCR_CRC_DIS = 1<<13, /* Bit 13: Remove 4-byte CRC */ - GM_RXCR_PASS_FC = 1<<12, /* Bit 12: Pass FC packets to FIFO */ -}; - -/* GM_TX_PARAM 16 bit r/w Transmit Parameter Register */ -enum { - GM_TXPA_JAMLEN_MSK = 0x03<<14, /* Bit 15..14: Jam Length */ - GM_TXPA_JAMIPG_MSK = 0x1f<<9, /* Bit 13..9: Jam IPG */ - GM_TXPA_JAMDAT_MSK = 0x1f<<4, /* Bit 8..4: IPG Jam to Data */ - - TX_JAM_LEN_DEF = 0x03, - TX_JAM_IPG_DEF = 0x0b, - TX_IPG_JAM_DEF = 0x1c, -}; - -#define TX_JAM_LEN_VAL(x) (((x)<<14) & GM_TXPA_JAMLEN_MSK) -#define TX_JAM_IPG_VAL(x) (((x)<<9) & GM_TXPA_JAMIPG_MSK) -#define TX_IPG_JAM_DATA(x) (((x)<<4) & GM_TXPA_JAMDAT_MSK) - - -/* GM_SERIAL_MODE 16 bit r/w Serial Mode Register */ -enum { - GM_SMOD_DATABL_MSK = 0x1f<<11, /* Bit 15..11: Data Blinder (r/o) */ - GM_SMOD_LIMIT_4 = 1<<10, /* Bit 10: 4 consecutive Tx trials */ - GM_SMOD_VLAN_ENA = 1<<9, /* Bit 9: Enable VLAN (Max. Frame Len) */ - GM_SMOD_JUMBO_ENA = 1<<8, /* Bit 8: Enable Jumbo (Max. Frame Len) */ - GM_SMOD_IPG_MSK = 0x1f /* Bit 4..0: Inter-Packet Gap (IPG) */ -}; - -#define DATA_BLIND_VAL(x) (((x)<<11) & GM_SMOD_DATABL_MSK) -#define DATA_BLIND_DEF 0x04 - -#define IPG_DATA_VAL(x) (x & GM_SMOD_IPG_MSK) -#define IPG_DATA_DEF 0x1e - -/* GM_SMI_CTRL 16 bit r/w SMI Control Register */ -enum { - GM_SMI_CT_PHY_A_MSK = 0x1f<<11, /* Bit 15..11: PHY Device Address */ - GM_SMI_CT_REG_A_MSK = 0x1f<<6, /* Bit 10.. 6: PHY Register Address */ - GM_SMI_CT_OP_RD = 1<<5, /* Bit 5: OpCode Read (0=Write)*/ - GM_SMI_CT_RD_VAL = 1<<4, /* Bit 4: Read Valid (Read completed) */ - GM_SMI_CT_BUSY = 1<<3, /* Bit 3: Busy (Operation in progress) */ -}; - -#define GM_SMI_CT_PHY_AD(x) (((x)<<11) & GM_SMI_CT_PHY_A_MSK) -#define GM_SMI_CT_REG_AD(x) (((x)<<6) & GM_SMI_CT_REG_A_MSK) - -/* GM_PHY_ADDR 16 bit r/w GPHY Address Register */ -enum { - GM_PAR_MIB_CLR = 1<<5, /* Bit 5: Set MIB Clear Counter Mode */ - GM_PAR_MIB_TST = 1<<4, /* Bit 4: MIB Load Counter (Test Mode) */ -}; - -/* Receive Frame Status Encoding */ -enum { - GMR_FS_LEN = 0xffff<<16, /* Bit 31..16: Rx Frame Length */ - GMR_FS_LEN_SHIFT = 16, - GMR_FS_VLAN = 1<<13, /* Bit 13: VLAN Packet */ - GMR_FS_JABBER = 1<<12, /* Bit 12: Jabber Packet */ - GMR_FS_UN_SIZE = 1<<11, /* Bit 11: Undersize Packet */ - GMR_FS_MC = 1<<10, /* Bit 10: Multicast Packet */ - GMR_FS_BC = 1<<9, /* Bit 9: Broadcast Packet */ - GMR_FS_RX_OK = 1<<8, /* Bit 8: Receive OK (Good Packet) */ - GMR_FS_GOOD_FC = 1<<7, /* Bit 7: Good Flow-Control Packet */ - GMR_FS_BAD_FC = 1<<6, /* Bit 6: Bad Flow-Control Packet */ - GMR_FS_MII_ERR = 1<<5, /* Bit 5: MII Error */ - GMR_FS_LONG_ERR = 1<<4, /* Bit 4: Too Long Packet */ - GMR_FS_FRAGMENT = 1<<3, /* Bit 3: Fragment */ - - GMR_FS_CRC_ERR = 1<<1, /* Bit 1: CRC Error */ - GMR_FS_RX_FF_OV = 1<<0, /* Bit 0: Rx FIFO Overflow */ - -/* - * GMR_FS_ANY_ERR (analogous to XMR_FS_ANY_ERR) - */ - GMR_FS_ANY_ERR = GMR_FS_CRC_ERR | GMR_FS_LONG_ERR | - GMR_FS_MII_ERR | GMR_FS_BAD_FC | GMR_FS_GOOD_FC | - GMR_FS_JABBER, -/* Rx GMAC FIFO Flush Mask (default) */ - RX_FF_FL_DEF_MSK = GMR_FS_CRC_ERR | GMR_FS_RX_FF_OV |GMR_FS_MII_ERR | - GMR_FS_BAD_FC | GMR_FS_UN_SIZE | GMR_FS_JABBER, -}; - -/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */ -enum { - GMF_WP_TST_ON = 1<<14, /* Write Pointer Test On */ - GMF_WP_TST_OFF = 1<<13, /* Write Pointer Test Off */ - GMF_WP_STEP = 1<<12, /* Write Pointer Step/Increment */ - - GMF_RP_TST_ON = 1<<10, /* Read Pointer Test On */ - GMF_RP_TST_OFF = 1<<9, /* Read Pointer Test Off */ - GMF_RP_STEP = 1<<8, /* Read Pointer Step/Increment */ - GMF_RX_F_FL_ON = 1<<7, /* Rx FIFO Flush Mode On */ - GMF_RX_F_FL_OFF = 1<<6, /* Rx FIFO Flush Mode Off */ - GMF_CLI_RX_FO = 1<<5, /* Clear IRQ Rx FIFO Overrun */ - GMF_CLI_RX_FC = 1<<4, /* Clear IRQ Rx Frame Complete */ - GMF_OPER_ON = 1<<3, /* Operational Mode On */ - GMF_OPER_OFF = 1<<2, /* Operational Mode Off */ - GMF_RST_CLR = 1<<1, /* Clear GMAC FIFO Reset */ - GMF_RST_SET = 1<<0, /* Set GMAC FIFO Reset */ - - RX_GMF_FL_THR_DEF = 0xa, /* flush threshold (default) */ -}; - - -/* TX_GMF_CTRL_T 32 bit Tx GMAC FIFO Control/Test */ -enum { - GMF_WSP_TST_ON = 1<<18, /* Write Shadow Pointer Test On */ - GMF_WSP_TST_OFF = 1<<17, /* Write Shadow Pointer Test Off */ - GMF_WSP_STEP = 1<<16, /* Write Shadow Pointer Step/Increment */ - - GMF_CLI_TX_FU = 1<<6, /* Clear IRQ Tx FIFO Underrun */ - GMF_CLI_TX_FC = 1<<5, /* Clear IRQ Tx Frame Complete */ - GMF_CLI_TX_PE = 1<<4, /* Clear IRQ Tx Parity Error */ -}; - -/* GMAC_TI_ST_CTRL 8 bit Time Stamp Timer Ctrl Reg (YUKON only) */ -enum { - GMT_ST_START = 1<<2, /* Start Time Stamp Timer */ - GMT_ST_STOP = 1<<1, /* Stop Time Stamp Timer */ - GMT_ST_CLR_IRQ = 1<<0, /* Clear Time Stamp Timer IRQ */ -}; - -/* GMAC_CTRL 32 bit GMAC Control Reg (YUKON only) */ -enum { - GMC_H_BURST_ON = 1<<7, /* Half Duplex Burst Mode On */ - GMC_H_BURST_OFF = 1<<6, /* Half Duplex Burst Mode Off */ - GMC_F_LOOPB_ON = 1<<5, /* FIFO Loopback On */ - GMC_F_LOOPB_OFF = 1<<4, /* FIFO Loopback Off */ - GMC_PAUSE_ON = 1<<3, /* Pause On */ - GMC_PAUSE_OFF = 1<<2, /* Pause Off */ - GMC_RST_CLR = 1<<1, /* Clear GMAC Reset */ - GMC_RST_SET = 1<<0, /* Set GMAC Reset */ -}; - -/* GPHY_CTRL 32 bit GPHY Control Reg (YUKON only) */ -enum { - GPC_SEL_BDT = 1<<28, /* Select Bi-Dir. Transfer for MDC/MDIO */ - GPC_INT_POL_HI = 1<<27, /* IRQ Polarity is Active HIGH */ - GPC_75_OHM = 1<<26, /* Use 75 Ohm Termination instead of 50 */ - GPC_DIS_FC = 1<<25, /* Disable Automatic Fiber/Copper Detection */ - GPC_DIS_SLEEP = 1<<24, /* Disable Energy Detect */ - GPC_HWCFG_M_3 = 1<<23, /* HWCFG_MODE[3] */ - GPC_HWCFG_M_2 = 1<<22, /* HWCFG_MODE[2] */ - GPC_HWCFG_M_1 = 1<<21, /* HWCFG_MODE[1] */ - GPC_HWCFG_M_0 = 1<<20, /* HWCFG_MODE[0] */ - GPC_ANEG_0 = 1<<19, /* ANEG[0] */ - GPC_ENA_XC = 1<<18, /* Enable MDI crossover */ - GPC_DIS_125 = 1<<17, /* Disable 125 MHz clock */ - GPC_ANEG_3 = 1<<16, /* ANEG[3] */ - GPC_ANEG_2 = 1<<15, /* ANEG[2] */ - GPC_ANEG_1 = 1<<14, /* ANEG[1] */ - GPC_ENA_PAUSE = 1<<13, /* Enable Pause (SYM_OR_REM) */ - GPC_PHYADDR_4 = 1<<12, /* Bit 4 of Phy Addr */ - GPC_PHYADDR_3 = 1<<11, /* Bit 3 of Phy Addr */ - GPC_PHYADDR_2 = 1<<10, /* Bit 2 of Phy Addr */ - GPC_PHYADDR_1 = 1<<9, /* Bit 1 of Phy Addr */ - GPC_PHYADDR_0 = 1<<8, /* Bit 0 of Phy Addr */ - /* Bits 7..2: reserved */ - GPC_RST_CLR = 1<<1, /* Clear GPHY Reset */ - GPC_RST_SET = 1<<0, /* Set GPHY Reset */ -}; - -#define GPC_HWCFG_GMII_COP (GPC_HWCFG_M_3|GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0) -#define GPC_HWCFG_GMII_FIB (GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0) -#define GPC_ANEG_ADV_ALL_M (GPC_ANEG_3 | GPC_ANEG_2 | GPC_ANEG_1 | GPC_ANEG_0) - -/* forced speed and duplex mode (don't mix with other ANEG bits) */ -#define GPC_FRC10MBIT_HALF 0 -#define GPC_FRC10MBIT_FULL GPC_ANEG_0 -#define GPC_FRC100MBIT_HALF GPC_ANEG_1 -#define GPC_FRC100MBIT_FULL (GPC_ANEG_0 | GPC_ANEG_1) - -/* auto-negotiation with limited advertised speeds */ -/* mix only with master/slave settings (for copper) */ -#define GPC_ADV_1000_HALF GPC_ANEG_2 -#define GPC_ADV_1000_FULL GPC_ANEG_3 -#define GPC_ADV_ALL (GPC_ANEG_2 | GPC_ANEG_3) - -/* master/slave settings */ -/* only for copper with 1000 Mbps */ -#define GPC_FORCE_MASTER 0 -#define GPC_FORCE_SLAVE GPC_ANEG_0 -#define GPC_PREF_MASTER GPC_ANEG_1 -#define GPC_PREF_SLAVE (GPC_ANEG_1 | GPC_ANEG_0) - -/* GMAC_IRQ_SRC 8 bit GMAC Interrupt Source Reg (YUKON only) */ -/* GMAC_IRQ_MSK 8 bit GMAC Interrupt Mask Reg (YUKON only) */ -enum { - GM_IS_TX_CO_OV = 1<<5, /* Transmit Counter Overflow IRQ */ - GM_IS_RX_CO_OV = 1<<4, /* Receive Counter Overflow IRQ */ - GM_IS_TX_FF_UR = 1<<3, /* Transmit FIFO Underrun */ - GM_IS_TX_COMPL = 1<<2, /* Frame Transmission Complete */ - GM_IS_RX_FF_OR = 1<<1, /* Receive FIFO Overrun */ - GM_IS_RX_COMPL = 1<<0, /* Frame Reception Complete */ - -#define GMAC_DEF_MSK (GM_IS_RX_FF_OR | GM_IS_TX_FF_UR) - -/* GMAC_LINK_CTRL 16 bit GMAC Link Control Reg (YUKON only) */ - /* Bits 15.. 2: reserved */ - GMLC_RST_CLR = 1<<1, /* Clear GMAC Link Reset */ - GMLC_RST_SET = 1<<0, /* Set GMAC Link Reset */ - - -/* WOL_CTRL_STAT 16 bit WOL Control/Status Reg */ - WOL_CTL_LINK_CHG_OCC = 1<<15, - WOL_CTL_MAGIC_PKT_OCC = 1<<14, - WOL_CTL_PATTERN_OCC = 1<<13, - WOL_CTL_CLEAR_RESULT = 1<<12, - WOL_CTL_ENA_PME_ON_LINK_CHG = 1<<11, - WOL_CTL_DIS_PME_ON_LINK_CHG = 1<<10, - WOL_CTL_ENA_PME_ON_MAGIC_PKT = 1<<9, - WOL_CTL_DIS_PME_ON_MAGIC_PKT = 1<<8, - WOL_CTL_ENA_PME_ON_PATTERN = 1<<7, - WOL_CTL_DIS_PME_ON_PATTERN = 1<<6, - WOL_CTL_ENA_LINK_CHG_UNIT = 1<<5, - WOL_CTL_DIS_LINK_CHG_UNIT = 1<<4, - WOL_CTL_ENA_MAGIC_PKT_UNIT = 1<<3, - WOL_CTL_DIS_MAGIC_PKT_UNIT = 1<<2, - WOL_CTL_ENA_PATTERN_UNIT = 1<<1, - WOL_CTL_DIS_PATTERN_UNIT = 1<<0, -}; - -#define WOL_CTL_DEFAULT \ - (WOL_CTL_DIS_PME_ON_LINK_CHG | \ - WOL_CTL_DIS_PME_ON_PATTERN | \ - WOL_CTL_DIS_PME_ON_MAGIC_PKT | \ - WOL_CTL_DIS_LINK_CHG_UNIT | \ - WOL_CTL_DIS_PATTERN_UNIT | \ - WOL_CTL_DIS_MAGIC_PKT_UNIT) - -/* WOL_MATCH_CTL 8 bit WOL Match Control Reg */ -#define WOL_CTL_PATT_ENA(x) (1 << (x)) - - -/* XMAC II registers */ -enum { - XM_MMU_CMD = 0x0000, /* 16 bit r/w MMU Command Register */ - XM_POFF = 0x0008, /* 32 bit r/w Packet Offset Register */ - XM_BURST = 0x000c, /* 32 bit r/w Burst Register for half duplex*/ - XM_1L_VLAN_TAG = 0x0010, /* 16 bit r/w One Level VLAN Tag ID */ - XM_2L_VLAN_TAG = 0x0014, /* 16 bit r/w Two Level VLAN Tag ID */ - XM_TX_CMD = 0x0020, /* 16 bit r/w Transmit Command Register */ - XM_TX_RT_LIM = 0x0024, /* 16 bit r/w Transmit Retry Limit Register */ - XM_TX_STIME = 0x0028, /* 16 bit r/w Transmit Slottime Register */ - XM_TX_IPG = 0x002c, /* 16 bit r/w Transmit Inter Packet Gap */ - XM_RX_CMD = 0x0030, /* 16 bit r/w Receive Command Register */ - XM_PHY_ADDR = 0x0034, /* 16 bit r/w PHY Address Register */ - XM_PHY_DATA = 0x0038, /* 16 bit r/w PHY Data Register */ - XM_GP_PORT = 0x0040, /* 32 bit r/w General Purpose Port Register */ - XM_IMSK = 0x0044, /* 16 bit r/w Interrupt Mask Register */ - XM_ISRC = 0x0048, /* 16 bit r/o Interrupt Status Register */ - XM_HW_CFG = 0x004c, /* 16 bit r/w Hardware Config Register */ - XM_TX_LO_WM = 0x0060, /* 16 bit r/w Tx FIFO Low Water Mark */ - XM_TX_HI_WM = 0x0062, /* 16 bit r/w Tx FIFO High Water Mark */ - XM_TX_THR = 0x0064, /* 16 bit r/w Tx Request Threshold */ - XM_HT_THR = 0x0066, /* 16 bit r/w Host Request Threshold */ - XM_PAUSE_DA = 0x0068, /* NA reg r/w Pause Destination Address */ - XM_CTL_PARA = 0x0070, /* 32 bit r/w Control Parameter Register */ - XM_MAC_OPCODE = 0x0074, /* 16 bit r/w Opcode for MAC control frames */ - XM_MAC_PTIME = 0x0076, /* 16 bit r/w Pause time for MAC ctrl frames*/ - XM_TX_STAT = 0x0078, /* 32 bit r/o Tx Status LIFO Register */ - - XM_EXM_START = 0x0080, /* r/w Start Address of the EXM Regs */ -#define XM_EXM(reg) (XM_EXM_START + ((reg) << 3)) -}; - -enum { - XM_SRC_CHK = 0x0100, /* NA reg r/w Source Check Address Register */ - XM_SA = 0x0108, /* NA reg r/w Station Address Register */ - XM_HSM = 0x0110, /* 64 bit r/w Hash Match Address Registers */ - XM_RX_LO_WM = 0x0118, /* 16 bit r/w Receive Low Water Mark */ - XM_RX_HI_WM = 0x011a, /* 16 bit r/w Receive High Water Mark */ - XM_RX_THR = 0x011c, /* 32 bit r/w Receive Request Threshold */ - XM_DEV_ID = 0x0120, /* 32 bit r/o Device ID Register */ - XM_MODE = 0x0124, /* 32 bit r/w Mode Register */ - XM_LSA = 0x0128, /* NA reg r/o Last Source Register */ - XM_TS_READ = 0x0130, /* 32 bit r/o Time Stamp Read Register */ - XM_TS_LOAD = 0x0134, /* 32 bit r/o Time Stamp Load Value */ - XM_STAT_CMD = 0x0200, /* 16 bit r/w Statistics Command Register */ - XM_RX_CNT_EV = 0x0204, /* 32 bit r/o Rx Counter Event Register */ - XM_TX_CNT_EV = 0x0208, /* 32 bit r/o Tx Counter Event Register */ - XM_RX_EV_MSK = 0x020c, /* 32 bit r/w Rx Counter Event Mask */ - XM_TX_EV_MSK = 0x0210, /* 32 bit r/w Tx Counter Event Mask */ - XM_TXF_OK = 0x0280, /* 32 bit r/o Frames Transmitted OK Conuter */ - XM_TXO_OK_HI = 0x0284, /* 32 bit r/o Octets Transmitted OK High Cnt*/ - XM_TXO_OK_LO = 0x0288, /* 32 bit r/o Octets Transmitted OK Low Cnt */ - XM_TXF_BC_OK = 0x028c, /* 32 bit r/o Broadcast Frames Xmitted OK */ - XM_TXF_MC_OK = 0x0290, /* 32 bit r/o Multicast Frames Xmitted OK */ - XM_TXF_UC_OK = 0x0294, /* 32 bit r/o Unicast Frames Xmitted OK */ - XM_TXF_LONG = 0x0298, /* 32 bit r/o Tx Long Frame Counter */ - XM_TXE_BURST = 0x029c, /* 32 bit r/o Tx Burst Event Counter */ - XM_TXF_MPAUSE = 0x02a0, /* 32 bit r/o Tx Pause MAC Ctrl Frame Cnt */ - XM_TXF_MCTRL = 0x02a4, /* 32 bit r/o Tx MAC Ctrl Frame Counter */ - XM_TXF_SNG_COL = 0x02a8, /* 32 bit r/o Tx Single Collision Counter */ - XM_TXF_MUL_COL = 0x02ac, /* 32 bit r/o Tx Multiple Collision Counter */ - XM_TXF_ABO_COL = 0x02b0, /* 32 bit r/o Tx aborted due to Exces. Col. */ - XM_TXF_LAT_COL = 0x02b4, /* 32 bit r/o Tx Late Collision Counter */ - XM_TXF_DEF = 0x02b8, /* 32 bit r/o Tx Deferred Frame Counter */ - XM_TXF_EX_DEF = 0x02bc, /* 32 bit r/o Tx Excessive Deferall Counter */ - XM_TXE_FIFO_UR = 0x02c0, /* 32 bit r/o Tx FIFO Underrun Event Cnt */ - XM_TXE_CS_ERR = 0x02c4, /* 32 bit r/o Tx Carrier Sense Error Cnt */ - XM_TXP_UTIL = 0x02c8, /* 32 bit r/o Tx Utilization in % */ - XM_TXF_64B = 0x02d0, /* 32 bit r/o 64 Byte Tx Frame Counter */ - XM_TXF_127B = 0x02d4, /* 32 bit r/o 65-127 Byte Tx Frame Counter */ - XM_TXF_255B = 0x02d8, /* 32 bit r/o 128-255 Byte Tx Frame Counter */ - XM_TXF_511B = 0x02dc, /* 32 bit r/o 256-511 Byte Tx Frame Counter */ - XM_TXF_1023B = 0x02e0, /* 32 bit r/o 512-1023 Byte Tx Frame Counter*/ - XM_TXF_MAX_SZ = 0x02e4, /* 32 bit r/o 1024-MaxSize Byte Tx Frame Cnt*/ - XM_RXF_OK = 0x0300, /* 32 bit r/o Frames Received OK */ - XM_RXO_OK_HI = 0x0304, /* 32 bit r/o Octets Received OK High Cnt */ - XM_RXO_OK_LO = 0x0308, /* 32 bit r/o Octets Received OK Low Counter*/ - XM_RXF_BC_OK = 0x030c, /* 32 bit r/o Broadcast Frames Received OK */ - XM_RXF_MC_OK = 0x0310, /* 32 bit r/o Multicast Frames Received OK */ - XM_RXF_UC_OK = 0x0314, /* 32 bit r/o Unicast Frames Received OK */ - XM_RXF_MPAUSE = 0x0318, /* 32 bit r/o Rx Pause MAC Ctrl Frame Cnt */ - XM_RXF_MCTRL = 0x031c, /* 32 bit r/o Rx MAC Ctrl Frame Counter */ - XM_RXF_INV_MP = 0x0320, /* 32 bit r/o Rx invalid Pause Frame Cnt */ - XM_RXF_INV_MOC = 0x0324, /* 32 bit r/o Rx Frames with inv. MAC Opcode*/ - XM_RXE_BURST = 0x0328, /* 32 bit r/o Rx Burst Event Counter */ - XM_RXE_FMISS = 0x032c, /* 32 bit r/o Rx Missed Frames Event Cnt */ - XM_RXF_FRA_ERR = 0x0330, /* 32 bit r/o Rx Framing Error Counter */ - XM_RXE_FIFO_OV = 0x0334, /* 32 bit r/o Rx FIFO overflow Event Cnt */ - XM_RXF_JAB_PKT = 0x0338, /* 32 bit r/o Rx Jabber Packet Frame Cnt */ - XM_RXE_CAR_ERR = 0x033c, /* 32 bit r/o Rx Carrier Event Error Cnt */ - XM_RXF_LEN_ERR = 0x0340, /* 32 bit r/o Rx in Range Length Error */ - XM_RXE_SYM_ERR = 0x0344, /* 32 bit r/o Rx Symbol Error Counter */ - XM_RXE_SHT_ERR = 0x0348, /* 32 bit r/o Rx Short Event Error Cnt */ - XM_RXE_RUNT = 0x034c, /* 32 bit r/o Rx Runt Event Counter */ - XM_RXF_LNG_ERR = 0x0350, /* 32 bit r/o Rx Frame too Long Error Cnt */ - XM_RXF_FCS_ERR = 0x0354, /* 32 bit r/o Rx Frame Check Seq. Error Cnt */ - XM_RXF_CEX_ERR = 0x035c, /* 32 bit r/o Rx Carrier Ext Error Frame Cnt*/ - XM_RXP_UTIL = 0x0360, /* 32 bit r/o Rx Utilization in % */ - XM_RXF_64B = 0x0368, /* 32 bit r/o 64 Byte Rx Frame Counter */ - XM_RXF_127B = 0x036c, /* 32 bit r/o 65-127 Byte Rx Frame Counter */ - XM_RXF_255B = 0x0370, /* 32 bit r/o 128-255 Byte Rx Frame Counter */ - XM_RXF_511B = 0x0374, /* 32 bit r/o 256-511 Byte Rx Frame Counter */ - XM_RXF_1023B = 0x0378, /* 32 bit r/o 512-1023 Byte Rx Frame Counter*/ - XM_RXF_MAX_SZ = 0x037c, /* 32 bit r/o 1024-MaxSize Byte Rx Frame Cnt*/ -}; - -/* XM_MMU_CMD 16 bit r/w MMU Command Register */ -enum { - XM_MMU_PHY_RDY = 1<<12, /* Bit 12: PHY Read Ready */ - XM_MMU_PHY_BUSY = 1<<11, /* Bit 11: PHY Busy */ - XM_MMU_IGN_PF = 1<<10, /* Bit 10: Ignore Pause Frame */ - XM_MMU_MAC_LB = 1<<9, /* Bit 9: Enable MAC Loopback */ - XM_MMU_FRC_COL = 1<<7, /* Bit 7: Force Collision */ - XM_MMU_SIM_COL = 1<<6, /* Bit 6: Simulate Collision */ - XM_MMU_NO_PRE = 1<<5, /* Bit 5: No MDIO Preamble */ - XM_MMU_GMII_FD = 1<<4, /* Bit 4: GMII uses Full Duplex */ - XM_MMU_RAT_CTRL = 1<<3, /* Bit 3: Enable Rate Control */ - XM_MMU_GMII_LOOP= 1<<2, /* Bit 2: PHY is in Loopback Mode */ - XM_MMU_ENA_RX = 1<<1, /* Bit 1: Enable Receiver */ - XM_MMU_ENA_TX = 1<<0, /* Bit 0: Enable Transmitter */ -}; - - -/* XM_TX_CMD 16 bit r/w Transmit Command Register */ -enum { - XM_TX_BK2BK = 1<<6, /* Bit 6: Ignor Carrier Sense (Tx Bk2Bk)*/ - XM_TX_ENC_BYP = 1<<5, /* Bit 5: Set Encoder in Bypass Mode */ - XM_TX_SAM_LINE = 1<<4, /* Bit 4: (sc) Start utilization calculation */ - XM_TX_NO_GIG_MD = 1<<3, /* Bit 3: Disable Carrier Extension */ - XM_TX_NO_PRE = 1<<2, /* Bit 2: Disable Preamble Generation */ - XM_TX_NO_CRC = 1<<1, /* Bit 1: Disable CRC Generation */ - XM_TX_AUTO_PAD = 1<<0, /* Bit 0: Enable Automatic Padding */ -}; - -/* XM_TX_RT_LIM 16 bit r/w Transmit Retry Limit Register */ -#define XM_RT_LIM_MSK 0x1f /* Bit 4..0: Tx Retry Limit */ - - -/* XM_TX_STIME 16 bit r/w Transmit Slottime Register */ -#define XM_STIME_MSK 0x7f /* Bit 6..0: Tx Slottime bits */ - - -/* XM_TX_IPG 16 bit r/w Transmit Inter Packet Gap */ -#define XM_IPG_MSK 0xff /* Bit 7..0: IPG value bits */ - - -/* XM_RX_CMD 16 bit r/w Receive Command Register */ -enum { - XM_RX_LENERR_OK = 1<<8, /* Bit 8 don't set Rx Err bit for */ - /* inrange error packets */ - XM_RX_BIG_PK_OK = 1<<7, /* Bit 7 don't set Rx Err bit for */ - /* jumbo packets */ - XM_RX_IPG_CAP = 1<<6, /* Bit 6 repl. type field with IPG */ - XM_RX_TP_MD = 1<<5, /* Bit 5: Enable transparent Mode */ - XM_RX_STRIP_FCS = 1<<4, /* Bit 4: Enable FCS Stripping */ - XM_RX_SELF_RX = 1<<3, /* Bit 3: Enable Rx of own packets */ - XM_RX_SAM_LINE = 1<<2, /* Bit 2: (sc) Start utilization calculation */ - XM_RX_STRIP_PAD = 1<<1, /* Bit 1: Strip pad bytes of Rx frames */ - XM_RX_DIS_CEXT = 1<<0, /* Bit 0: Disable carrier ext. check */ -}; - - -/* XM_GP_PORT 32 bit r/w General Purpose Port Register */ -enum { - XM_GP_ANIP = 1<<6, /* Bit 6: (ro) Auto-Neg. in progress */ - XM_GP_FRC_INT = 1<<5, /* Bit 5: (sc) Force Interrupt */ - XM_GP_RES_MAC = 1<<3, /* Bit 3: (sc) Reset MAC and FIFOs */ - XM_GP_RES_STAT = 1<<2, /* Bit 2: (sc) Reset the statistics module */ - XM_GP_INP_ASS = 1<<0, /* Bit 0: (ro) GP Input Pin asserted */ -}; - - -/* XM_IMSK 16 bit r/w Interrupt Mask Register */ -/* XM_ISRC 16 bit r/o Interrupt Status Register */ -enum { - XM_IS_LNK_AE = 1<<14, /* Bit 14: Link Asynchronous Event */ - XM_IS_TX_ABORT = 1<<13, /* Bit 13: Transmit Abort, late Col. etc */ - XM_IS_FRC_INT = 1<<12, /* Bit 12: Force INT bit set in GP */ - XM_IS_INP_ASS = 1<<11, /* Bit 11: Input Asserted, GP bit 0 set */ - XM_IS_LIPA_RC = 1<<10, /* Bit 10: Link Partner requests config */ - XM_IS_RX_PAGE = 1<<9, /* Bit 9: Page Received */ - XM_IS_TX_PAGE = 1<<8, /* Bit 8: Next Page Loaded for Transmit */ - XM_IS_AND = 1<<7, /* Bit 7: Auto-Negotiation Done */ - XM_IS_TSC_OV = 1<<6, /* Bit 6: Time Stamp Counter Overflow */ - XM_IS_RXC_OV = 1<<5, /* Bit 5: Rx Counter Event Overflow */ - XM_IS_TXC_OV = 1<<4, /* Bit 4: Tx Counter Event Overflow */ - XM_IS_RXF_OV = 1<<3, /* Bit 3: Receive FIFO Overflow */ - XM_IS_TXF_UR = 1<<2, /* Bit 2: Transmit FIFO Underrun */ - XM_IS_TX_COMP = 1<<1, /* Bit 1: Frame Tx Complete */ - XM_IS_RX_COMP = 1<<0, /* Bit 0: Frame Rx Complete */ - - XM_IMSK_DISABLE = 0xffff, -}; - -/* XM_HW_CFG 16 bit r/w Hardware Config Register */ -enum { - XM_HW_GEN_EOP = 1<<3, /* Bit 3: generate End of Packet pulse */ - XM_HW_COM4SIG = 1<<2, /* Bit 2: use Comma Detect for Sig. Det.*/ - XM_HW_GMII_MD = 1<<0, /* Bit 0: GMII Interface selected */ -}; - - -/* XM_TX_LO_WM 16 bit r/w Tx FIFO Low Water Mark */ -/* XM_TX_HI_WM 16 bit r/w Tx FIFO High Water Mark */ -#define XM_TX_WM_MSK 0x01ff /* Bit 9.. 0 Tx FIFO Watermark bits */ - -/* XM_TX_THR 16 bit r/w Tx Request Threshold */ -/* XM_HT_THR 16 bit r/w Host Request Threshold */ -/* XM_RX_THR 16 bit r/w Rx Request Threshold */ -#define XM_THR_MSK 0x03ff /* Bit 10.. 0 Rx/Tx Request Threshold bits */ - - -/* XM_TX_STAT 32 bit r/o Tx Status LIFO Register */ -enum { - XM_ST_VALID = (1UL<<31), /* Bit 31: Status Valid */ - XM_ST_BYTE_CNT = (0x3fffL<<17), /* Bit 30..17: Tx frame Length */ - XM_ST_RETRY_CNT = (0x1fL<<12), /* Bit 16..12: Retry Count */ - XM_ST_EX_COL = 1<<11, /* Bit 11: Excessive Collisions */ - XM_ST_EX_DEF = 1<<10, /* Bit 10: Excessive Deferral */ - XM_ST_BURST = 1<<9, /* Bit 9: p. xmitted in burst md*/ - XM_ST_DEFER = 1<<8, /* Bit 8: packet was defered */ - XM_ST_BC = 1<<7, /* Bit 7: Broadcast packet */ - XM_ST_MC = 1<<6, /* Bit 6: Multicast packet */ - XM_ST_UC = 1<<5, /* Bit 5: Unicast packet */ - XM_ST_TX_UR = 1<<4, /* Bit 4: FIFO Underrun occurred */ - XM_ST_CS_ERR = 1<<3, /* Bit 3: Carrier Sense Error */ - XM_ST_LAT_COL = 1<<2, /* Bit 2: Late Collision Error */ - XM_ST_MUL_COL = 1<<1, /* Bit 1: Multiple Collisions */ - XM_ST_SGN_COL = 1<<0, /* Bit 0: Single Collision */ -}; - -/* XM_RX_LO_WM 16 bit r/w Receive Low Water Mark */ -/* XM_RX_HI_WM 16 bit r/w Receive High Water Mark */ -#define XM_RX_WM_MSK 0x03ff /* Bit 11.. 0: Rx FIFO Watermark bits */ - - -/* XM_DEV_ID 32 bit r/o Device ID Register */ -#define XM_DEV_OUI (0x00ffffffUL<<8) /* Bit 31..8: Device OUI */ -#define XM_DEV_REV (0x07L << 5) /* Bit 7..5: Chip Rev Num */ - - -/* XM_MODE 32 bit r/w Mode Register */ -enum { - XM_MD_ENA_REJ = 1<<26, /* Bit 26: Enable Frame Reject */ - XM_MD_SPOE_E = 1<<25, /* Bit 25: Send Pause on Edge */ - /* extern generated */ - XM_MD_TX_REP = 1<<24, /* Bit 24: Transmit Repeater Mode */ - XM_MD_SPOFF_I = 1<<23, /* Bit 23: Send Pause on FIFO full */ - /* intern generated */ - XM_MD_LE_STW = 1<<22, /* Bit 22: Rx Stat Word in Little Endian */ - XM_MD_TX_CONT = 1<<21, /* Bit 21: Send Continuous */ - XM_MD_TX_PAUSE = 1<<20, /* Bit 20: (sc) Send Pause Frame */ - XM_MD_ATS = 1<<19, /* Bit 19: Append Time Stamp */ - XM_MD_SPOL_I = 1<<18, /* Bit 18: Send Pause on Low */ - /* intern generated */ - XM_MD_SPOH_I = 1<<17, /* Bit 17: Send Pause on High */ - /* intern generated */ - XM_MD_CAP = 1<<16, /* Bit 16: Check Address Pair */ - XM_MD_ENA_HASH = 1<<15, /* Bit 15: Enable Hashing */ - XM_MD_CSA = 1<<14, /* Bit 14: Check Station Address */ - XM_MD_CAA = 1<<13, /* Bit 13: Check Address Array */ - XM_MD_RX_MCTRL = 1<<12, /* Bit 12: Rx MAC Control Frame */ - XM_MD_RX_RUNT = 1<<11, /* Bit 11: Rx Runt Frames */ - XM_MD_RX_IRLE = 1<<10, /* Bit 10: Rx in Range Len Err Frame */ - XM_MD_RX_LONG = 1<<9, /* Bit 9: Rx Long Frame */ - XM_MD_RX_CRCE = 1<<8, /* Bit 8: Rx CRC Error Frame */ - XM_MD_RX_ERR = 1<<7, /* Bit 7: Rx Error Frame */ - XM_MD_DIS_UC = 1<<6, /* Bit 6: Disable Rx Unicast */ - XM_MD_DIS_MC = 1<<5, /* Bit 5: Disable Rx Multicast */ - XM_MD_DIS_BC = 1<<4, /* Bit 4: Disable Rx Broadcast */ - XM_MD_ENA_PROM = 1<<3, /* Bit 3: Enable Promiscuous */ - XM_MD_ENA_BE = 1<<2, /* Bit 2: Enable Big Endian */ - XM_MD_FTF = 1<<1, /* Bit 1: (sc) Flush Tx FIFO */ - XM_MD_FRF = 1<<0, /* Bit 0: (sc) Flush Rx FIFO */ -}; - -#define XM_PAUSE_MODE (XM_MD_SPOE_E | XM_MD_SPOL_I | XM_MD_SPOH_I) -#define XM_DEF_MODE (XM_MD_RX_RUNT | XM_MD_RX_IRLE | XM_MD_RX_LONG |\ - XM_MD_RX_CRCE | XM_MD_RX_ERR | XM_MD_CSA) - -/* XM_STAT_CMD 16 bit r/w Statistics Command Register */ -enum { - XM_SC_SNP_RXC = 1<<5, /* Bit 5: (sc) Snap Rx Counters */ - XM_SC_SNP_TXC = 1<<4, /* Bit 4: (sc) Snap Tx Counters */ - XM_SC_CP_RXC = 1<<3, /* Bit 3: Copy Rx Counters Continuously */ - XM_SC_CP_TXC = 1<<2, /* Bit 2: Copy Tx Counters Continuously */ - XM_SC_CLR_RXC = 1<<1, /* Bit 1: (sc) Clear Rx Counters */ - XM_SC_CLR_TXC = 1<<0, /* Bit 0: (sc) Clear Tx Counters */ -}; - - -/* XM_RX_CNT_EV 32 bit r/o Rx Counter Event Register */ -/* XM_RX_EV_MSK 32 bit r/w Rx Counter Event Mask */ -enum { - XMR_MAX_SZ_OV = 1<<31, /* Bit 31: 1024-MaxSize Rx Cnt Ov*/ - XMR_1023B_OV = 1<<30, /* Bit 30: 512-1023Byte Rx Cnt Ov*/ - XMR_511B_OV = 1<<29, /* Bit 29: 256-511 Byte Rx Cnt Ov*/ - XMR_255B_OV = 1<<28, /* Bit 28: 128-255 Byte Rx Cnt Ov*/ - XMR_127B_OV = 1<<27, /* Bit 27: 65-127 Byte Rx Cnt Ov */ - XMR_64B_OV = 1<<26, /* Bit 26: 64 Byte Rx Cnt Ov */ - XMR_UTIL_OV = 1<<25, /* Bit 25: Rx Util Cnt Overflow */ - XMR_UTIL_UR = 1<<24, /* Bit 24: Rx Util Cnt Underrun */ - XMR_CEX_ERR_OV = 1<<23, /* Bit 23: CEXT Err Cnt Ov */ - XMR_FCS_ERR_OV = 1<<21, /* Bit 21: Rx FCS Error Cnt Ov */ - XMR_LNG_ERR_OV = 1<<20, /* Bit 20: Rx too Long Err Cnt Ov*/ - XMR_RUNT_OV = 1<<19, /* Bit 19: Runt Event Cnt Ov */ - XMR_SHT_ERR_OV = 1<<18, /* Bit 18: Rx Short Ev Err Cnt Ov*/ - XMR_SYM_ERR_OV = 1<<17, /* Bit 17: Rx Sym Err Cnt Ov */ - XMR_CAR_ERR_OV = 1<<15, /* Bit 15: Rx Carr Ev Err Cnt Ov */ - XMR_JAB_PKT_OV = 1<<14, /* Bit 14: Rx Jabb Packet Cnt Ov */ - XMR_FIFO_OV = 1<<13, /* Bit 13: Rx FIFO Ov Ev Cnt Ov */ - XMR_FRA_ERR_OV = 1<<12, /* Bit 12: Rx Framing Err Cnt Ov */ - XMR_FMISS_OV = 1<<11, /* Bit 11: Rx Missed Ev Cnt Ov */ - XMR_BURST = 1<<10, /* Bit 10: Rx Burst Event Cnt Ov */ - XMR_INV_MOC = 1<<9, /* Bit 9: Rx with inv. MAC OC Ov*/ - XMR_INV_MP = 1<<8, /* Bit 8: Rx inv Pause Frame Ov */ - XMR_MCTRL_OV = 1<<7, /* Bit 7: Rx MAC Ctrl-F Cnt Ov */ - XMR_MPAUSE_OV = 1<<6, /* Bit 6: Rx Pause MAC Ctrl-F Ov*/ - XMR_UC_OK_OV = 1<<5, /* Bit 5: Rx Unicast Frame CntOv*/ - XMR_MC_OK_OV = 1<<4, /* Bit 4: Rx Multicast Cnt Ov */ - XMR_BC_OK_OV = 1<<3, /* Bit 3: Rx Broadcast Cnt Ov */ - XMR_OK_LO_OV = 1<<2, /* Bit 2: Octets Rx OK Low CntOv*/ - XMR_OK_HI_OV = 1<<1, /* Bit 1: Octets Rx OK Hi Cnt Ov*/ - XMR_OK_OV = 1<<0, /* Bit 0: Frames Received Ok Ov */ -}; - -#define XMR_DEF_MSK (XMR_OK_LO_OV | XMR_OK_HI_OV) - -/* XM_TX_CNT_EV 32 bit r/o Tx Counter Event Register */ -/* XM_TX_EV_MSK 32 bit r/w Tx Counter Event Mask */ -enum { - XMT_MAX_SZ_OV = 1<<25, /* Bit 25: 1024-MaxSize Tx Cnt Ov*/ - XMT_1023B_OV = 1<<24, /* Bit 24: 512-1023Byte Tx Cnt Ov*/ - XMT_511B_OV = 1<<23, /* Bit 23: 256-511 Byte Tx Cnt Ov*/ - XMT_255B_OV = 1<<22, /* Bit 22: 128-255 Byte Tx Cnt Ov*/ - XMT_127B_OV = 1<<21, /* Bit 21: 65-127 Byte Tx Cnt Ov */ - XMT_64B_OV = 1<<20, /* Bit 20: 64 Byte Tx Cnt Ov */ - XMT_UTIL_OV = 1<<19, /* Bit 19: Tx Util Cnt Overflow */ - XMT_UTIL_UR = 1<<18, /* Bit 18: Tx Util Cnt Underrun */ - XMT_CS_ERR_OV = 1<<17, /* Bit 17: Tx Carr Sen Err Cnt Ov*/ - XMT_FIFO_UR_OV = 1<<16, /* Bit 16: Tx FIFO Ur Ev Cnt Ov */ - XMT_EX_DEF_OV = 1<<15, /* Bit 15: Tx Ex Deferall Cnt Ov */ - XMT_DEF = 1<<14, /* Bit 14: Tx Deferred Cnt Ov */ - XMT_LAT_COL_OV = 1<<13, /* Bit 13: Tx Late Col Cnt Ov */ - XMT_ABO_COL_OV = 1<<12, /* Bit 12: Tx abo dueto Ex Col Ov*/ - XMT_MUL_COL_OV = 1<<11, /* Bit 11: Tx Mult Col Cnt Ov */ - XMT_SNG_COL = 1<<10, /* Bit 10: Tx Single Col Cnt Ov */ - XMT_MCTRL_OV = 1<<9, /* Bit 9: Tx MAC Ctrl Counter Ov*/ - XMT_MPAUSE = 1<<8, /* Bit 8: Tx Pause MAC Ctrl-F Ov*/ - XMT_BURST = 1<<7, /* Bit 7: Tx Burst Event Cnt Ov */ - XMT_LONG = 1<<6, /* Bit 6: Tx Long Frame Cnt Ov */ - XMT_UC_OK_OV = 1<<5, /* Bit 5: Tx Unicast Cnt Ov */ - XMT_MC_OK_OV = 1<<4, /* Bit 4: Tx Multicast Cnt Ov */ - XMT_BC_OK_OV = 1<<3, /* Bit 3: Tx Broadcast Cnt Ov */ - XMT_OK_LO_OV = 1<<2, /* Bit 2: Octets Tx OK Low CntOv*/ - XMT_OK_HI_OV = 1<<1, /* Bit 1: Octets Tx OK Hi Cnt Ov*/ - XMT_OK_OV = 1<<0, /* Bit 0: Frames Tx Ok Ov */ -}; - -#define XMT_DEF_MSK (XMT_OK_LO_OV | XMT_OK_HI_OV) - -struct skge_rx_desc { - u32 control; - u32 next_offset; - u32 dma_lo; - u32 dma_hi; - u32 status; - u32 timestamp; - u16 csum2; - u16 csum1; - u16 csum2_start; - u16 csum1_start; -}; - -struct skge_tx_desc { - u32 control; - u32 next_offset; - u32 dma_lo; - u32 dma_hi; - u32 status; - u32 csum_offs; - u16 csum_write; - u16 csum_start; - u32 rsvd; -}; - -struct skge_element { - struct skge_element *next; - void *desc; - struct sk_buff *skb; - DEFINE_DMA_UNMAP_ADDR(mapaddr); - DEFINE_DMA_UNMAP_LEN(maplen); -}; - -struct skge_ring { - struct skge_element *to_clean; - struct skge_element *to_use; - struct skge_element *start; - unsigned long count; -}; - - -struct skge_hw { - void __iomem *regs; - struct pci_dev *pdev; - spinlock_t hw_lock; - u32 intr_mask; - struct net_device *dev[2]; - - u8 chip_id; - u8 chip_rev; - u8 copper; - u8 ports; - u8 phy_type; - - u32 ram_size; - u32 ram_offset; - u16 phy_addr; - spinlock_t phy_lock; - struct tasklet_struct phy_task; - - char irq_name[0]; /* skge@pci:000:04:00.0 */ -}; - -enum pause_control { - FLOW_MODE_NONE = 1, /* No Flow-Control */ - FLOW_MODE_LOC_SEND = 2, /* Local station sends PAUSE */ - FLOW_MODE_SYMMETRIC = 3, /* Both stations may send PAUSE */ - FLOW_MODE_SYM_OR_REM = 4, /* Both stations may send PAUSE or - * just the remote station may send PAUSE - */ -}; - -enum pause_status { - FLOW_STAT_INDETERMINATED=0, /* indeterminated */ - FLOW_STAT_NONE, /* No Flow Control */ - FLOW_STAT_REM_SEND, /* Remote Station sends PAUSE */ - FLOW_STAT_LOC_SEND, /* Local station sends PAUSE */ - FLOW_STAT_SYMMETRIC, /* Both station may send PAUSE */ -}; - - -struct skge_port { - struct skge_hw *hw; - struct net_device *netdev; - struct napi_struct napi; - int port; - u32 msg_enable; - - struct skge_ring tx_ring; - - struct skge_ring rx_ring ____cacheline_aligned_in_smp; - unsigned int rx_buf_size; - - struct timer_list link_timer; - enum pause_control flow_control; - enum pause_status flow_status; - u8 blink_on; - u8 wol; - u8 autoneg; /* AUTONEG_ENABLE, AUTONEG_DISABLE */ - u8 duplex; /* DUPLEX_HALF, DUPLEX_FULL */ - u16 speed; /* SPEED_1000, SPEED_100, ... */ - u32 advertising; - - void *mem; /* PCI memory for rings */ - dma_addr_t dma; - unsigned long mem_size; -#ifdef CONFIG_SKGE_DEBUG - struct dentry *debugfs; -#endif -}; - - -/* Register accessor for memory mapped device */ -static inline u32 skge_read32(const struct skge_hw *hw, int reg) -{ - return readl(hw->regs + reg); -} - -static inline u16 skge_read16(const struct skge_hw *hw, int reg) -{ - return readw(hw->regs + reg); -} - -static inline u8 skge_read8(const struct skge_hw *hw, int reg) -{ - return readb(hw->regs + reg); -} - -static inline void skge_write32(const struct skge_hw *hw, int reg, u32 val) -{ - writel(val, hw->regs + reg); -} - -static inline void skge_write16(const struct skge_hw *hw, int reg, u16 val) -{ - writew(val, hw->regs + reg); -} - -static inline void skge_write8(const struct skge_hw *hw, int reg, u8 val) -{ - writeb(val, hw->regs + reg); -} - -/* MAC Related Registers inside the device. */ -#define SK_REG(port,reg) (((port)<<7)+(u16)(reg)) -#define SK_XMAC_REG(port, reg) \ - ((BASE_XMAC_1 + (port) * (BASE_XMAC_2 - BASE_XMAC_1)) | (reg) << 1) - -static inline u32 xm_read32(const struct skge_hw *hw, int port, int reg) -{ - u32 v; - v = skge_read16(hw, SK_XMAC_REG(port, reg)); - v |= (u32)skge_read16(hw, SK_XMAC_REG(port, reg+2)) << 16; - return v; -} - -static inline u16 xm_read16(const struct skge_hw *hw, int port, int reg) -{ - return skge_read16(hw, SK_XMAC_REG(port,reg)); -} - -static inline void xm_write32(const struct skge_hw *hw, int port, int r, u32 v) -{ - skge_write16(hw, SK_XMAC_REG(port,r), v & 0xffff); - skge_write16(hw, SK_XMAC_REG(port,r+2), v >> 16); -} - -static inline void xm_write16(const struct skge_hw *hw, int port, int r, u16 v) -{ - skge_write16(hw, SK_XMAC_REG(port,r), v); -} - -static inline void xm_outhash(const struct skge_hw *hw, int port, int reg, - const u8 *hash) -{ - xm_write16(hw, port, reg, (u16)hash[0] | ((u16)hash[1] << 8)); - xm_write16(hw, port, reg+2, (u16)hash[2] | ((u16)hash[3] << 8)); - xm_write16(hw, port, reg+4, (u16)hash[4] | ((u16)hash[5] << 8)); - xm_write16(hw, port, reg+6, (u16)hash[6] | ((u16)hash[7] << 8)); -} - -static inline void xm_outaddr(const struct skge_hw *hw, int port, int reg, - const u8 *addr) -{ - xm_write16(hw, port, reg, (u16)addr[0] | ((u16)addr[1] << 8)); - xm_write16(hw, port, reg+2, (u16)addr[2] | ((u16)addr[3] << 8)); - xm_write16(hw, port, reg+4, (u16)addr[4] | ((u16)addr[5] << 8)); -} - -#define SK_GMAC_REG(port,reg) \ - (BASE_GMAC_1 + (port) * (BASE_GMAC_2-BASE_GMAC_1) + (reg)) - -static inline u16 gma_read16(const struct skge_hw *hw, int port, int reg) -{ - return skge_read16(hw, SK_GMAC_REG(port,reg)); -} - -static inline u32 gma_read32(const struct skge_hw *hw, int port, int reg) -{ - return (u32) skge_read16(hw, SK_GMAC_REG(port,reg)) - | ((u32)skge_read16(hw, SK_GMAC_REG(port,reg+4)) << 16); -} - -static inline void gma_write16(const struct skge_hw *hw, int port, int r, u16 v) -{ - skge_write16(hw, SK_GMAC_REG(port,r), v); -} - -static inline void gma_set_addr(struct skge_hw *hw, int port, int reg, - const u8 *addr) -{ - gma_write16(hw, port, reg, (u16) addr[0] | ((u16) addr[1] << 8)); - gma_write16(hw, port, reg+4,(u16) addr[2] | ((u16) addr[3] << 8)); - gma_write16(hw, port, reg+8,(u16) addr[4] | ((u16) addr[5] << 8)); -} - -#endif diff --git a/addons/virtio/install.sh b/addons/virtio/install.sh deleted file mode 100644 index ffe448be..00000000 --- a/addons/virtio/install.sh +++ /dev/null @@ -1,14 +0,0 @@ -if [ "${1}" = "rd" ]; then - echo "Checking for VirtIO..." - if (grep -r -q -E "(QEMU|VirtualBox)" /sys/devices/virtual/dmi/id/); then - echo "VirtIO hypervisor detected!" - ${INSMOD} "/modules/virtio.ko" ${PARAMS} - ${INSMOD} "/modules/virtio_ring.ko" ${PARAMS} - ${INSMOD} "/modules/virtio_mmio.ko" ${PARAMS} - ${INSMOD} "/modules/virtio_pci.ko" ${PARAMS} - ${INSMOD} "/modules/virtio_net.ko" ${PARAMS} - ${INSMOD} "/modules/virtio_scsi.ko" ${PARAMS} - else - echo "No VirtIO hypervisor detected!" - fi -fi diff --git a/addons/virtio/manifest.yml b/addons/virtio/manifest.yml deleted file mode 100644 index f67a8123..00000000 --- a/addons/virtio/manifest.yml +++ /dev/null @@ -1,28 +0,0 @@ -version: 1 -name: virtio -description: "Drivers for QEMU/Virtualbox hypervisor" -available-for: - bromolow-3.10.108: - install-script: &script "install.sh" - modules: true - apollolake-4.4.180: - install-script: *script - modules: true - broadwell-4.4.180: - install-script: *script - modules: true - broadwellnk-4.4.180: - install-script: *script - modules: true - denverton-4.4.180: - install-script: *script - modules: true - geminilake-4.4.180: - install-script: *script - modules: true - v1000-4.4.180: - install-script: *script - modules: true - purley-4.4.180: - install-script: *script - modules: true diff --git a/addons/virtio/src/3.10.108/Makefile b/addons/virtio/src/3.10.108/Makefile deleted file mode 100644 index bde7770d..00000000 --- a/addons/virtio/src/3.10.108/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -obj-m += virtio.o virtio_ring.o -obj-m += virtio_mmio.o -obj-m += virtio_pci.o -obj-m += virtio_net.o -obj-m += virtio_scsi.o diff --git a/addons/virtio/src/3.10.108/config.c b/addons/virtio/src/3.10.108/config.c deleted file mode 100644 index f70bcd2f..00000000 --- a/addons/virtio/src/3.10.108/config.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Configuration space parsing helpers for virtio. - * - * The configuration is [type][len][... len bytes ...] fields. - * - * Copyright 2007 Rusty Russell, IBM Corporation. - * GPL v2 or later. - */ -#include -#include -#include -#include - diff --git a/addons/virtio/src/3.10.108/virtio.c b/addons/virtio/src/3.10.108/virtio.c deleted file mode 100644 index beaa7cc4..00000000 --- a/addons/virtio/src/3.10.108/virtio.c +++ /dev/null @@ -1,246 +0,0 @@ -#include -#include -#include -#include -#include - -/* Unique numbering for virtio devices. */ -static DEFINE_IDA(virtio_index_ida); - -static ssize_t device_show(struct device *_d, - struct device_attribute *attr, char *buf) -{ - struct virtio_device *dev = dev_to_virtio(_d); - return sprintf(buf, "0x%04x\n", dev->id.device); -} -static ssize_t vendor_show(struct device *_d, - struct device_attribute *attr, char *buf) -{ - struct virtio_device *dev = dev_to_virtio(_d); - return sprintf(buf, "0x%04x\n", dev->id.vendor); -} -static ssize_t status_show(struct device *_d, - struct device_attribute *attr, char *buf) -{ - struct virtio_device *dev = dev_to_virtio(_d); - return sprintf(buf, "0x%08x\n", dev->config->get_status(dev)); -} -static ssize_t modalias_show(struct device *_d, - struct device_attribute *attr, char *buf) -{ - struct virtio_device *dev = dev_to_virtio(_d); - return sprintf(buf, "virtio:d%08Xv%08X\n", - dev->id.device, dev->id.vendor); -} -static ssize_t features_show(struct device *_d, - struct device_attribute *attr, char *buf) -{ - struct virtio_device *dev = dev_to_virtio(_d); - unsigned int i; - ssize_t len = 0; - - /* We actually represent this as a bitstring, as it could be - * arbitrary length in future. */ - for (i = 0; i < ARRAY_SIZE(dev->features)*BITS_PER_LONG; i++) - len += sprintf(buf+len, "%c", - test_bit(i, dev->features) ? '1' : '0'); - len += sprintf(buf+len, "\n"); - return len; -} -static struct device_attribute virtio_dev_attrs[] = { - __ATTR_RO(device), - __ATTR_RO(vendor), - __ATTR_RO(status), - __ATTR_RO(modalias), - __ATTR_RO(features), - __ATTR_NULL -}; - -static inline int virtio_id_match(const struct virtio_device *dev, - const struct virtio_device_id *id) -{ - if (id->device != dev->id.device && id->device != VIRTIO_DEV_ANY_ID) - return 0; - - return id->vendor == VIRTIO_DEV_ANY_ID || id->vendor == dev->id.vendor; -} - -/* This looks through all the IDs a driver claims to support. If any of them - * match, we return 1 and the kernel will call virtio_dev_probe(). */ -static int virtio_dev_match(struct device *_dv, struct device_driver *_dr) -{ - unsigned int i; - struct virtio_device *dev = dev_to_virtio(_dv); - const struct virtio_device_id *ids; - - ids = drv_to_virtio(_dr)->id_table; - for (i = 0; ids[i].device; i++) - if (virtio_id_match(dev, &ids[i])) - return 1; - return 0; -} - -static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env) -{ - struct virtio_device *dev = dev_to_virtio(_dv); - - return add_uevent_var(env, "MODALIAS=virtio:d%08Xv%08X", - dev->id.device, dev->id.vendor); -} - -static void add_status(struct virtio_device *dev, unsigned status) -{ - dev->config->set_status(dev, dev->config->get_status(dev) | status); -} - -void virtio_check_driver_offered_feature(const struct virtio_device *vdev, - unsigned int fbit) -{ - unsigned int i; - struct virtio_driver *drv = drv_to_virtio(vdev->dev.driver); - - for (i = 0; i < drv->feature_table_size; i++) - if (drv->feature_table[i] == fbit) - return; - BUG(); -} -EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature); - -static int virtio_dev_probe(struct device *_d) -{ - int err, i; - struct virtio_device *dev = dev_to_virtio(_d); - struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); - u32 device_features; - - /* We have a driver! */ - add_status(dev, VIRTIO_CONFIG_S_DRIVER); - - /* Figure out what features the device supports. */ - device_features = dev->config->get_features(dev); - - /* Features supported by both device and driver into dev->features. */ - memset(dev->features, 0, sizeof(dev->features)); - for (i = 0; i < drv->feature_table_size; i++) { - unsigned int f = drv->feature_table[i]; - BUG_ON(f >= 32); - if (device_features & (1 << f)) - set_bit(f, dev->features); - } - - /* Transport features always preserved to pass to finalize_features. */ - for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) - if (device_features & (1 << i)) - set_bit(i, dev->features); - - dev->config->finalize_features(dev); - - err = drv->probe(dev); - if (err) - add_status(dev, VIRTIO_CONFIG_S_FAILED); - else { - add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); - if (drv->scan) - drv->scan(dev); - } - - return err; -} - -static int virtio_dev_remove(struct device *_d) -{ - struct virtio_device *dev = dev_to_virtio(_d); - struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); - - drv->remove(dev); - - /* Driver should have reset device. */ - WARN_ON_ONCE(dev->config->get_status(dev)); - - /* Acknowledge the device's existence again. */ - add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); - return 0; -} - -static struct bus_type virtio_bus = { - .name = "virtio", - .match = virtio_dev_match, - .dev_attrs = virtio_dev_attrs, - .uevent = virtio_uevent, - .probe = virtio_dev_probe, - .remove = virtio_dev_remove, -}; - -int register_virtio_driver(struct virtio_driver *driver) -{ - /* Catch this early. */ - BUG_ON(driver->feature_table_size && !driver->feature_table); - driver->driver.bus = &virtio_bus; - return driver_register(&driver->driver); -} -EXPORT_SYMBOL_GPL(register_virtio_driver); - -void unregister_virtio_driver(struct virtio_driver *driver) -{ - driver_unregister(&driver->driver); -} -EXPORT_SYMBOL_GPL(unregister_virtio_driver); - -int register_virtio_device(struct virtio_device *dev) -{ - int err; - - dev->dev.bus = &virtio_bus; - - /* Assign a unique device index and hence name. */ - err = ida_simple_get(&virtio_index_ida, 0, 0, GFP_KERNEL); - if (err < 0) - goto out; - - dev->index = err; - dev_set_name(&dev->dev, "virtio%u", dev->index); - - /* We always start by resetting the device, in case a previous - * driver messed it up. This also tests that code path a little. */ - dev->config->reset(dev); - - /* Acknowledge that we've seen the device. */ - add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); - - INIT_LIST_HEAD(&dev->vqs); - - /* device_register() causes the bus infrastructure to look for a - * matching driver. */ - err = device_register(&dev->dev); -out: - if (err) - add_status(dev, VIRTIO_CONFIG_S_FAILED); - return err; -} -EXPORT_SYMBOL_GPL(register_virtio_device); - -void unregister_virtio_device(struct virtio_device *dev) -{ - int index = dev->index; /* save for after device release */ - - device_unregister(&dev->dev); - ida_simple_remove(&virtio_index_ida, index); -} -EXPORT_SYMBOL_GPL(unregister_virtio_device); - -static int virtio_init(void) -{ - if (bus_register(&virtio_bus) != 0) - panic("virtio bus registration failed"); - return 0; -} - -static void __exit virtio_exit(void) -{ - bus_unregister(&virtio_bus); - ida_destroy(&virtio_index_ida); -} -core_initcall(virtio_init); -module_exit(virtio_exit); - -MODULE_LICENSE("GPL"); diff --git a/addons/virtio/src/3.10.108/virtio_mmio.c b/addons/virtio/src/3.10.108/virtio_mmio.c deleted file mode 100644 index 1ba0d683..00000000 --- a/addons/virtio/src/3.10.108/virtio_mmio.c +++ /dev/null @@ -1,665 +0,0 @@ -/* - * Virtio memory mapped device driver - * - * Copyright 2011, ARM Ltd. - * - * This module allows virtio devices to be used over a virtual, memory mapped - * platform device. - * - * The guest device(s) may be instantiated in one of three equivalent ways: - * - * 1. Static platform device in board's code, eg.: - * - * static struct platform_device v2m_virtio_device = { - * .name = "virtio-mmio", - * .id = -1, - * .num_resources = 2, - * .resource = (struct resource []) { - * { - * .start = 0x1001e000, - * .end = 0x1001e0ff, - * .flags = IORESOURCE_MEM, - * }, { - * .start = 42 + 32, - * .end = 42 + 32, - * .flags = IORESOURCE_IRQ, - * }, - * } - * }; - * - * 2. Device Tree node, eg.: - * - * virtio_block@1e000 { - * compatible = "virtio,mmio"; - * reg = <0x1e000 0x100>; - * interrupts = <42>; - * } - * - * 3. Kernel module (or command line) parameter. Can be used more than once - - * one device will be created for each one. Syntax: - * - * [virtio_mmio.]device=@:[:] - * where: - * := size (can use standard suffixes like K, M or G) - * := physical base address - * := interrupt number (as passed to request_irq()) - * := (optional) platform device id - * eg.: - * virtio_mmio.device=0x100@0x100b0000:48 \ - * virtio_mmio.device=1K@0x1001e000:74 - * - * - * - * Registers layout (all 32-bit wide): - * - * offset d. name description - * ------ -- ---------------- ----------------- - * - * 0x000 R MagicValue Magic value "virt" - * 0x004 R Version Device version (current max. 1) - * 0x008 R DeviceID Virtio device ID - * 0x00c R VendorID Virtio vendor ID - * - * 0x010 R HostFeatures Features supported by the host - * 0x014 W HostFeaturesSel Set of host features to access via HostFeatures - * - * 0x020 W GuestFeatures Features activated by the guest - * 0x024 W GuestFeaturesSel Set of activated features to set via GuestFeatures - * 0x028 W GuestPageSize Size of guest's memory page in bytes - * - * 0x030 W QueueSel Queue selector - * 0x034 R QueueNumMax Maximum size of the currently selected queue - * 0x038 W QueueNum Queue size for the currently selected queue - * 0x03c W QueueAlign Used Ring alignment for the current queue - * 0x040 RW QueuePFN PFN for the currently selected queue - * - * 0x050 W QueueNotify Queue notifier - * 0x060 R InterruptStatus Interrupt status register - * 0x064 W InterruptACK Interrupt acknowledge register - * 0x070 RW Status Device status register - * - * 0x100+ RW Device-specific configuration space - * - * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007 - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#define pr_fmt(fmt) "virtio-mmio: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - -/* The alignment to use between consumer and producer parts of vring. - * Currently hardcoded to the page size. */ -#define VIRTIO_MMIO_VRING_ALIGN PAGE_SIZE - - - -#define to_virtio_mmio_device(_plat_dev) \ - container_of(_plat_dev, struct virtio_mmio_device, vdev) - -struct virtio_mmio_device { - struct virtio_device vdev; - struct platform_device *pdev; - - void __iomem *base; - unsigned long version; - - /* a list of queues so we can dispatch IRQs */ - spinlock_t lock; - struct list_head virtqueues; -}; - -struct virtio_mmio_vq_info { - /* the actual virtqueue */ - struct virtqueue *vq; - - /* the number of entries in the queue */ - unsigned int num; - - /* the virtual address of the ring queue */ - void *queue; - - /* the list node for the virtqueues list */ - struct list_head node; -}; - - - -/* Configuration interface */ - -static u32 vm_get_features(struct virtio_device *vdev) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - - /* TODO: Features > 32 bits */ - writel(0, vm_dev->base + VIRTIO_MMIO_HOST_FEATURES_SEL); - - return readl(vm_dev->base + VIRTIO_MMIO_HOST_FEATURES); -} - -static void vm_finalize_features(struct virtio_device *vdev) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - int i; - - /* Give virtio_ring a chance to accept features. */ - vring_transport_features(vdev); - - for (i = 0; i < ARRAY_SIZE(vdev->features); i++) { - writel(i, vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES_SEL); - writel(vdev->features[i], - vm_dev->base + VIRTIO_MMIO_GUEST_FEATURES); - } -} - -static void vm_get(struct virtio_device *vdev, unsigned offset, - void *buf, unsigned len) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - u8 *ptr = buf; - int i; - - for (i = 0; i < len; i++) - ptr[i] = readb(vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i); -} - -static void vm_set(struct virtio_device *vdev, unsigned offset, - const void *buf, unsigned len) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - const u8 *ptr = buf; - int i; - - for (i = 0; i < len; i++) - writeb(ptr[i], vm_dev->base + VIRTIO_MMIO_CONFIG + offset + i); -} - -static u8 vm_get_status(struct virtio_device *vdev) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - - return readl(vm_dev->base + VIRTIO_MMIO_STATUS) & 0xff; -} - -static void vm_set_status(struct virtio_device *vdev, u8 status) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - - /* We should never be setting status to 0. */ - BUG_ON(status == 0); - - writel(status, vm_dev->base + VIRTIO_MMIO_STATUS); -} - -static void vm_reset(struct virtio_device *vdev) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - - /* 0 status means a reset. */ - writel(0, vm_dev->base + VIRTIO_MMIO_STATUS); -} - - - -/* Transport interface */ - -/* the notify function used when creating a virt queue */ -static void vm_notify(struct virtqueue *vq) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev); - - /* We write the queue's selector into the notification register to - * signal the other end */ - writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY); -} - -/* Notify all virtqueues on an interrupt. */ -static irqreturn_t vm_interrupt(int irq, void *opaque) -{ - struct virtio_mmio_device *vm_dev = opaque; - struct virtio_mmio_vq_info *info; - struct virtio_driver *vdrv = container_of(vm_dev->vdev.dev.driver, - struct virtio_driver, driver); - unsigned long status; - unsigned long flags; - irqreturn_t ret = IRQ_NONE; - - /* Read and acknowledge interrupts */ - status = readl(vm_dev->base + VIRTIO_MMIO_INTERRUPT_STATUS); - writel(status, vm_dev->base + VIRTIO_MMIO_INTERRUPT_ACK); - - if (unlikely(status & VIRTIO_MMIO_INT_CONFIG) - && vdrv && vdrv->config_changed) { - vdrv->config_changed(&vm_dev->vdev); - ret = IRQ_HANDLED; - } - - if (likely(status & VIRTIO_MMIO_INT_VRING)) { - spin_lock_irqsave(&vm_dev->lock, flags); - list_for_each_entry(info, &vm_dev->virtqueues, node) - ret |= vring_interrupt(irq, info->vq); - spin_unlock_irqrestore(&vm_dev->lock, flags); - } - - return ret; -} - - - -static void vm_del_vq(struct virtqueue *vq) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev); - struct virtio_mmio_vq_info *info = vq->priv; - unsigned long flags, size; - unsigned int index = vq->index; - - spin_lock_irqsave(&vm_dev->lock, flags); - list_del(&info->node); - spin_unlock_irqrestore(&vm_dev->lock, flags); - - vring_del_virtqueue(vq); - - /* Select and deactivate the queue */ - writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); - writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); - - size = PAGE_ALIGN(vring_size(info->num, VIRTIO_MMIO_VRING_ALIGN)); - free_pages_exact(info->queue, size); - kfree(info); -} - -static void vm_del_vqs(struct virtio_device *vdev) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - struct virtqueue *vq, *n; - - list_for_each_entry_safe(vq, n, &vdev->vqs, list) - vm_del_vq(vq); - - free_irq(platform_get_irq(vm_dev->pdev, 0), vm_dev); -} - - - -static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index, - void (*callback)(struct virtqueue *vq), - const char *name) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - struct virtio_mmio_vq_info *info; - struct virtqueue *vq; - unsigned long flags, size; - int err; - - if (!name) - return NULL; - - /* Select the queue we're interested in */ - writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); - - /* Queue shouldn't already be set up. */ - if (readl(vm_dev->base + VIRTIO_MMIO_QUEUE_PFN)) { - err = -ENOENT; - goto error_available; - } - - /* Allocate and fill out our active queue description */ - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) { - err = -ENOMEM; - goto error_kmalloc; - } - - /* Allocate pages for the queue - start with a queue as big as - * possible (limited by maximum size allowed by device), drop down - * to a minimal size, just big enough to fit descriptor table - * and two rings (which makes it "alignment_size * 2") - */ - info->num = readl(vm_dev->base + VIRTIO_MMIO_QUEUE_NUM_MAX); - - /* If the device reports a 0 entry queue, we won't be able to - * use it to perform I/O, and vring_new_virtqueue() can't create - * empty queues anyway, so don't bother to set up the device. - */ - if (info->num == 0) { - err = -ENOENT; - goto error_alloc_pages; - } - - while (1) { - size = PAGE_ALIGN(vring_size(info->num, - VIRTIO_MMIO_VRING_ALIGN)); - /* Did the last iter shrink the queue below minimum size? */ - if (size < VIRTIO_MMIO_VRING_ALIGN * 2) { - err = -ENOMEM; - goto error_alloc_pages; - } - - info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO); - if (info->queue) - break; - - info->num /= 2; - } - - /* Activate the queue */ - writel(info->num, vm_dev->base + VIRTIO_MMIO_QUEUE_NUM); - writel(VIRTIO_MMIO_VRING_ALIGN, - vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN); - writel(virt_to_phys(info->queue) >> PAGE_SHIFT, - vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); - - /* Create the vring */ - vq = vring_new_virtqueue(index, info->num, VIRTIO_MMIO_VRING_ALIGN, vdev, - true, info->queue, vm_notify, callback, name); - if (!vq) { - err = -ENOMEM; - goto error_new_virtqueue; - } - - vq->priv = info; - info->vq = vq; - - spin_lock_irqsave(&vm_dev->lock, flags); - list_add(&info->node, &vm_dev->virtqueues); - spin_unlock_irqrestore(&vm_dev->lock, flags); - - return vq; - -error_new_virtqueue: - writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); - free_pages_exact(info->queue, size); -error_alloc_pages: - kfree(info); -error_kmalloc: -error_available: - return ERR_PTR(err); -} - -static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], - const char *names[]) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - unsigned int irq = platform_get_irq(vm_dev->pdev, 0); - int i, err; - - err = request_irq(irq, vm_interrupt, IRQF_SHARED, - dev_name(&vdev->dev), vm_dev); - if (err) - return err; - - for (i = 0; i < nvqs; ++i) { - vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i]); - if (IS_ERR(vqs[i])) { - vm_del_vqs(vdev); - return PTR_ERR(vqs[i]); - } - } - - return 0; -} - -static const char *vm_bus_name(struct virtio_device *vdev) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - - return vm_dev->pdev->name; -} - -static const struct virtio_config_ops virtio_mmio_config_ops = { - .get = vm_get, - .set = vm_set, - .get_status = vm_get_status, - .set_status = vm_set_status, - .reset = vm_reset, - .find_vqs = vm_find_vqs, - .del_vqs = vm_del_vqs, - .get_features = vm_get_features, - .finalize_features = vm_finalize_features, - .bus_name = vm_bus_name, -}; - - - -/* Platform device */ - -static int virtio_mmio_probe(struct platform_device *pdev) -{ - struct virtio_mmio_device *vm_dev; - struct resource *mem; - unsigned long magic; - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) - return -EINVAL; - - if (!devm_request_mem_region(&pdev->dev, mem->start, - resource_size(mem), pdev->name)) - return -EBUSY; - - vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL); - if (!vm_dev) - return -ENOMEM; - - vm_dev->vdev.dev.parent = &pdev->dev; - vm_dev->vdev.config = &virtio_mmio_config_ops; - vm_dev->pdev = pdev; - INIT_LIST_HEAD(&vm_dev->virtqueues); - spin_lock_init(&vm_dev->lock); - - vm_dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); - if (vm_dev->base == NULL) - return -EFAULT; - - /* Check magic value */ - magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE); - if (memcmp(&magic, "virt", 4) != 0) { - dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic); - return -ENODEV; - } - - /* Check device version */ - vm_dev->version = readl(vm_dev->base + VIRTIO_MMIO_VERSION); - if (vm_dev->version != 1) { - dev_err(&pdev->dev, "Version %ld not supported!\n", - vm_dev->version); - return -ENXIO; - } - - vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID); - vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID); - - writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE); - - platform_set_drvdata(pdev, vm_dev); - - return register_virtio_device(&vm_dev->vdev); -} - -static int virtio_mmio_remove(struct platform_device *pdev) -{ - struct virtio_mmio_device *vm_dev = platform_get_drvdata(pdev); - - unregister_virtio_device(&vm_dev->vdev); - - return 0; -} - - - -/* Devices list parameter */ - -#if defined(CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES) - -static struct device vm_cmdline_parent = { - .init_name = "virtio-mmio-cmdline", -}; - -static int vm_cmdline_parent_registered; -static int vm_cmdline_id; - -static int vm_cmdline_set(const char *device, - const struct kernel_param *kp) -{ - int err; - struct resource resources[2] = {}; - char *str; - long long int base, size; - unsigned int irq; - int processed, consumed = 0; - struct platform_device *pdev; - - /* Consume "size" part of the command line parameter */ - size = memparse(device, &str); - - /* Get "@:[:]" chunks */ - processed = sscanf(str, "@%lli:%u%n:%d%n", - &base, &irq, &consumed, - &vm_cmdline_id, &consumed); - - /* - * sscanf() must processes at least 2 chunks; also there - * must be no extra characters after the last chunk, so - * str[consumed] must be '\0' - */ - if (processed < 2 || str[consumed]) - return -EINVAL; - - resources[0].flags = IORESOURCE_MEM; - resources[0].start = base; - resources[0].end = base + size - 1; - - resources[1].flags = IORESOURCE_IRQ; - resources[1].start = resources[1].end = irq; - - if (!vm_cmdline_parent_registered) { - err = device_register(&vm_cmdline_parent); - if (err) { - pr_err("Failed to register parent device!\n"); - return err; - } - vm_cmdline_parent_registered = 1; - } - - pr_info("Registering device virtio-mmio.%d at 0x%llx-0x%llx, IRQ %d.\n", - vm_cmdline_id, - (unsigned long long)resources[0].start, - (unsigned long long)resources[0].end, - (int)resources[1].start); - - pdev = platform_device_register_resndata(&vm_cmdline_parent, - "virtio-mmio", vm_cmdline_id++, - resources, ARRAY_SIZE(resources), NULL, 0); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); - - return 0; -} - -static int vm_cmdline_get_device(struct device *dev, void *data) -{ - char *buffer = data; - unsigned int len = strlen(buffer); - struct platform_device *pdev = to_platform_device(dev); - - snprintf(buffer + len, PAGE_SIZE - len, "0x%llx@0x%llx:%llu:%d\n", - pdev->resource[0].end - pdev->resource[0].start + 1ULL, - (unsigned long long)pdev->resource[0].start, - (unsigned long long)pdev->resource[1].start, - pdev->id); - return 0; -} - -static int vm_cmdline_get(char *buffer, const struct kernel_param *kp) -{ - buffer[0] = '\0'; - device_for_each_child(&vm_cmdline_parent, buffer, - vm_cmdline_get_device); - return strlen(buffer) + 1; -} - -static struct kernel_param_ops vm_cmdline_param_ops = { - .set = vm_cmdline_set, - .get = vm_cmdline_get, -}; - -device_param_cb(device, &vm_cmdline_param_ops, NULL, S_IRUSR); - -static int vm_unregister_cmdline_device(struct device *dev, - void *data) -{ - platform_device_unregister(to_platform_device(dev)); - - return 0; -} - -static void vm_unregister_cmdline_devices(void) -{ - if (vm_cmdline_parent_registered) { - device_for_each_child(&vm_cmdline_parent, NULL, - vm_unregister_cmdline_device); - device_unregister(&vm_cmdline_parent); - vm_cmdline_parent_registered = 0; - } -} - -#else - -static void vm_unregister_cmdline_devices(void) -{ -} - -#endif - -/* Platform driver */ - -static struct of_device_id virtio_mmio_match[] = { - { .compatible = "virtio,mmio", }, - {}, -}; -MODULE_DEVICE_TABLE(of, virtio_mmio_match); - -static struct platform_driver virtio_mmio_driver = { - .probe = virtio_mmio_probe, - .remove = virtio_mmio_remove, - .driver = { - .name = "virtio-mmio", - .owner = THIS_MODULE, - .of_match_table = virtio_mmio_match, - }, -}; - -static int __init virtio_mmio_init(void) -{ - return platform_driver_register(&virtio_mmio_driver); -} - -static void __exit virtio_mmio_exit(void) -{ - platform_driver_unregister(&virtio_mmio_driver); - vm_unregister_cmdline_devices(); -} - -module_init(virtio_mmio_init); -module_exit(virtio_mmio_exit); - -MODULE_AUTHOR("Pawel Moll "); -MODULE_DESCRIPTION("Platform bus driver for memory mapped virtio devices"); -MODULE_LICENSE("GPL"); diff --git a/addons/virtio/src/3.10.108/virtio_net.c b/addons/virtio/src/3.10.108/virtio_net.c deleted file mode 100644 index b5d11529..00000000 --- a/addons/virtio/src/3.10.108/virtio_net.c +++ /dev/null @@ -1,1812 +0,0 @@ -/* A network driver using virtio. - * - * Copyright 2007 Rusty Russell IBM Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -//#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int napi_weight = NAPI_POLL_WEIGHT; -module_param(napi_weight, int, 0444); - -static bool csum = true, gso = true; -module_param(csum, bool, 0444); -module_param(gso, bool, 0444); - -/* FIXME: MTU in config. */ -#define MAX_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) -#define GOOD_COPY_LEN 128 - -#define VIRTNET_DRIVER_VERSION "1.0.0" - -struct virtnet_stats { - struct u64_stats_sync tx_syncp; - struct u64_stats_sync rx_syncp; - u64 tx_bytes; - u64 tx_packets; - - u64 rx_bytes; - u64 rx_packets; -}; - -/* Internal representation of a send virtqueue */ -struct send_queue { - /* Virtqueue associated with this send _queue */ - struct virtqueue *vq; - - /* TX: fragments + linear part + virtio header */ - struct scatterlist sg[MAX_SKB_FRAGS + 2]; - - /* Name of the send queue: output.$index */ - char name[40]; -}; - -/* Internal representation of a receive virtqueue */ -struct receive_queue { - /* Virtqueue associated with this receive_queue */ - struct virtqueue *vq; - - struct napi_struct napi; - - /* Number of input buffers, and max we've ever had. */ - unsigned int num, max; - - /* Chain pages by the private ptr. */ - struct page *pages; - - /* RX: fragments + linear part + virtio header */ - struct scatterlist sg[MAX_SKB_FRAGS + 2]; - - /* Name of this receive queue: input.$index */ - char name[40]; -}; - -struct virtnet_info { - struct virtio_device *vdev; - struct virtqueue *cvq; - struct net_device *dev; - struct send_queue *sq; - struct receive_queue *rq; - unsigned int status; - - /* Max # of queue pairs supported by the device */ - u16 max_queue_pairs; - - /* # of queue pairs currently used by the driver */ - u16 curr_queue_pairs; - - /* I like... big packets and I cannot lie! */ - bool big_packets; - - /* Host will merge rx buffers for big packets (shake it! shake it!) */ - bool mergeable_rx_bufs; - - /* Has control virtqueue */ - bool has_cvq; - - /* enable config space updates */ - bool config_enable; - - /* Active statistics */ - struct virtnet_stats __percpu *stats; - - /* Work struct for refilling if we run low on memory. */ - struct delayed_work refill; - - /* Work struct for config space updates */ - struct work_struct config_work; - - /* Lock for config space updates */ - struct mutex config_lock; - - /* Does the affinity hint is set for virtqueues? */ - bool affinity_hint_set; - - /* Per-cpu variable to show the mapping from CPU to virtqueue */ - int __percpu *vq_index; - - /* CPU hot plug notifier */ - struct notifier_block nb; -}; - -struct skb_vnet_hdr { - union { - struct virtio_net_hdr hdr; - struct virtio_net_hdr_mrg_rxbuf mhdr; - }; -}; - -struct padded_vnet_hdr { - struct virtio_net_hdr hdr; - /* - * virtio_net_hdr should be in a separated sg buffer because of a - * QEMU bug, and data sg buffer shares same page with this header sg. - * This padding makes next sg 16 byte aligned after virtio_net_hdr. - */ - char padding[6]; -}; - -/* Converting between virtqueue no. and kernel tx/rx queue no. - * 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq - */ -static int vq2txq(struct virtqueue *vq) -{ - return (vq->index - 1) / 2; -} - -static int txq2vq(int txq) -{ - return txq * 2 + 1; -} - -static int vq2rxq(struct virtqueue *vq) -{ - return vq->index / 2; -} - -static int rxq2vq(int rxq) -{ - return rxq * 2; -} - -static inline struct skb_vnet_hdr *skb_vnet_hdr(struct sk_buff *skb) -{ - return (struct skb_vnet_hdr *)skb->cb; -} - -/* - * private is used to chain pages for big packets, put the whole - * most recent used list in the beginning for reuse - */ -static void give_pages(struct receive_queue *rq, struct page *page) -{ - struct page *end; - - /* Find end of list, sew whole thing into vi->rq.pages. */ - for (end = page; end->private; end = (struct page *)end->private); - end->private = (unsigned long)rq->pages; - rq->pages = page; -} - -static struct page *get_a_page(struct receive_queue *rq, gfp_t gfp_mask) -{ - struct page *p = rq->pages; - - if (p) { - rq->pages = (struct page *)p->private; - /* clear private here, it is used to chain pages */ - p->private = 0; - } else - p = alloc_page(gfp_mask); - return p; -} - -static void skb_xmit_done(struct virtqueue *vq) -{ - struct virtnet_info *vi = vq->vdev->priv; - - /* Suppress further interrupts. */ - virtqueue_disable_cb(vq); - - /* We were probably waiting for more output buffers. */ - netif_wake_subqueue(vi->dev, vq2txq(vq)); -} - -static void set_skb_frag(struct sk_buff *skb, struct page *page, - unsigned int offset, unsigned int *len) -{ - int size = min((unsigned)PAGE_SIZE - offset, *len); - int i = skb_shinfo(skb)->nr_frags; - - __skb_fill_page_desc(skb, i, page, offset, size); - - skb->data_len += size; - skb->len += size; - skb->truesize += PAGE_SIZE; - skb_shinfo(skb)->nr_frags++; - skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG; - *len -= size; -} - -/* Called from bottom half context */ -static struct sk_buff *page_to_skb(struct receive_queue *rq, - struct page *page, unsigned int len) -{ - struct virtnet_info *vi = rq->vq->vdev->priv; - struct sk_buff *skb; - struct skb_vnet_hdr *hdr; - unsigned int copy, hdr_len, offset; - char *p; - - p = page_address(page); - - /* copy small packet so we can reuse these pages for small data */ - skb = netdev_alloc_skb_ip_align(vi->dev, GOOD_COPY_LEN); - if (unlikely(!skb)) - return NULL; - - hdr = skb_vnet_hdr(skb); - - if (vi->mergeable_rx_bufs) { - hdr_len = sizeof hdr->mhdr; - offset = hdr_len; - } else { - hdr_len = sizeof hdr->hdr; - offset = sizeof(struct padded_vnet_hdr); - } - - memcpy(hdr, p, hdr_len); - - len -= hdr_len; - p += offset; - - copy = len; - if (copy > skb_tailroom(skb)) - copy = skb_tailroom(skb); - memcpy(skb_put(skb, copy), p, copy); - - len -= copy; - offset += copy; - - /* - * Verify that we can indeed put this data into a skb. - * This is here to handle cases when the device erroneously - * tries to receive more than is possible. This is usually - * the case of a broken device. - */ - if (unlikely(len > MAX_SKB_FRAGS * PAGE_SIZE)) { - net_dbg_ratelimited("%s: too much data\n", skb->dev->name); - dev_kfree_skb(skb); - return NULL; - } - - while (len) { - set_skb_frag(skb, page, offset, &len); - page = (struct page *)page->private; - offset = 0; - } - - if (page) - give_pages(rq, page); - - return skb; -} - -static struct sk_buff *receive_small(void *buf, unsigned int len) -{ - struct sk_buff * skb = buf; - - len -= sizeof(struct virtio_net_hdr); - skb_trim(skb, len); - - return skb; -} - -static struct sk_buff *receive_big(struct net_device *dev, - struct receive_queue *rq, - void *buf) -{ - struct page *page = buf; - struct sk_buff *skb = page_to_skb(rq, page, 0); - - if (unlikely(!skb)) - goto err; - - return skb; - -err: - dev->stats.rx_dropped++; - give_pages(rq, page); - return NULL; -} - -static struct sk_buff *receive_mergeable(struct net_device *dev, - struct receive_queue *rq, - void *buf, - unsigned int len) -{ - struct skb_vnet_hdr *hdr = page_address(buf); - int num_buf = hdr->mhdr.num_buffers; - struct page *page = buf; - struct sk_buff *skb = page_to_skb(rq, page, len); - int i; - - if (unlikely(!skb)) - goto err_skb; - - while (--num_buf) { - i = skb_shinfo(skb)->nr_frags; - if (i >= MAX_SKB_FRAGS) { - pr_debug("%s: packet too long\n", skb->dev->name); - skb->dev->stats.rx_length_errors++; - goto err_frags; - } - page = virtqueue_get_buf(rq->vq, &len); - if (!page) { - pr_debug("%s: rx error: %d buffers %d missing\n", - dev->name, hdr->mhdr.num_buffers, num_buf); - dev->stats.rx_length_errors++; - goto err_buf; - } - - if (len > PAGE_SIZE) - len = PAGE_SIZE; - - set_skb_frag(skb, page, 0, &len); - - --rq->num; - } - return skb; -err_skb: - give_pages(rq, page); - while (--num_buf) { -err_frags: - buf = virtqueue_get_buf(rq->vq, &len); - if (unlikely(!buf)) { - pr_debug("%s: rx error: %d buffers missing\n", - dev->name, num_buf); - dev->stats.rx_length_errors++; - break; - } - page = buf; - give_pages(rq, page); - --rq->num; - } -err_buf: - dev->stats.rx_dropped++; - dev_kfree_skb(skb); - return NULL; -} - -static void receive_buf(struct receive_queue *rq, void *buf, unsigned int len) -{ - struct virtnet_info *vi = rq->vq->vdev->priv; - struct net_device *dev = vi->dev; - struct virtnet_stats *stats = this_cpu_ptr(vi->stats); - struct sk_buff *skb; - struct skb_vnet_hdr *hdr; - - if (unlikely(len < sizeof(struct virtio_net_hdr) + ETH_HLEN)) { - pr_debug("%s: short packet %i\n", dev->name, len); - dev->stats.rx_length_errors++; - if (vi->mergeable_rx_bufs || vi->big_packets) - give_pages(rq, buf); - else - dev_kfree_skb(buf); - return; - } - if (vi->mergeable_rx_bufs) - skb = receive_mergeable(dev, rq, buf, len); - else if (vi->big_packets) - skb = receive_big(dev, rq, buf); - else - skb = receive_small(buf, len); - - if (unlikely(!skb)) - return; - - hdr = skb_vnet_hdr(skb); - - u64_stats_update_begin(&stats->rx_syncp); - stats->rx_bytes += skb->len; - stats->rx_packets++; - u64_stats_update_end(&stats->rx_syncp); - - if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { - pr_debug("Needs csum!\n"); - if (!skb_partial_csum_set(skb, - hdr->hdr.csum_start, - hdr->hdr.csum_offset)) - goto frame_err; - } else if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - } - - skb->protocol = eth_type_trans(skb, dev); - pr_debug("Receiving skb proto 0x%04x len %i type %i\n", - ntohs(skb->protocol), skb->len, skb->pkt_type); - - if (hdr->hdr.gso_type != VIRTIO_NET_HDR_GSO_NONE) { - pr_debug("GSO!\n"); - switch (hdr->hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { - case VIRTIO_NET_HDR_GSO_TCPV4: - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; - break; - case VIRTIO_NET_HDR_GSO_UDP: - skb_shinfo(skb)->gso_type = SKB_GSO_UDP; - break; - case VIRTIO_NET_HDR_GSO_TCPV6: - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; - break; - default: - net_warn_ratelimited("%s: bad gso type %u.\n", - dev->name, hdr->hdr.gso_type); - goto frame_err; - } - - if (hdr->hdr.gso_type & VIRTIO_NET_HDR_GSO_ECN) - skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; - - skb_shinfo(skb)->gso_size = hdr->hdr.gso_size; - if (skb_shinfo(skb)->gso_size == 0) { - net_warn_ratelimited("%s: zero gso size.\n", dev->name); - goto frame_err; - } - - /* Header must be checked, and gso_segs computed. */ - skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; - skb_shinfo(skb)->gso_segs = 0; - } - - netif_receive_skb(skb); - return; - -frame_err: - dev->stats.rx_frame_errors++; - dev_kfree_skb(skb); -} - -static int add_recvbuf_small(struct receive_queue *rq, gfp_t gfp) -{ - struct virtnet_info *vi = rq->vq->vdev->priv; - struct sk_buff *skb; - struct skb_vnet_hdr *hdr; - int err; - - skb = __netdev_alloc_skb_ip_align(vi->dev, MAX_PACKET_LEN, gfp); - if (unlikely(!skb)) - return -ENOMEM; - - skb_put(skb, MAX_PACKET_LEN); - - hdr = skb_vnet_hdr(skb); - sg_set_buf(rq->sg, &hdr->hdr, sizeof hdr->hdr); - - skb_to_sgvec(skb, rq->sg + 1, 0, skb->len); - - err = virtqueue_add_inbuf(rq->vq, rq->sg, 2, skb, gfp); - if (err < 0) - dev_kfree_skb(skb); - - return err; -} - -static int add_recvbuf_big(struct receive_queue *rq, gfp_t gfp) -{ - struct page *first, *list = NULL; - char *p; - int i, err, offset; - - /* page in rq->sg[MAX_SKB_FRAGS + 1] is list tail */ - for (i = MAX_SKB_FRAGS + 1; i > 1; --i) { - first = get_a_page(rq, gfp); - if (!first) { - if (list) - give_pages(rq, list); - return -ENOMEM; - } - sg_set_buf(&rq->sg[i], page_address(first), PAGE_SIZE); - - /* chain new page in list head to match sg */ - first->private = (unsigned long)list; - list = first; - } - - first = get_a_page(rq, gfp); - if (!first) { - give_pages(rq, list); - return -ENOMEM; - } - p = page_address(first); - - /* rq->sg[0], rq->sg[1] share the same page */ - /* a separated rq->sg[0] for virtio_net_hdr only due to QEMU bug */ - sg_set_buf(&rq->sg[0], p, sizeof(struct virtio_net_hdr)); - - /* rq->sg[1] for data packet, from offset */ - offset = sizeof(struct padded_vnet_hdr); - sg_set_buf(&rq->sg[1], p + offset, PAGE_SIZE - offset); - - /* chain first in list head */ - first->private = (unsigned long)list; - err = virtqueue_add_inbuf(rq->vq, rq->sg, MAX_SKB_FRAGS + 2, - first, gfp); - if (err < 0) - give_pages(rq, first); - - return err; -} - -static int add_recvbuf_mergeable(struct receive_queue *rq, gfp_t gfp) -{ - struct page *page; - int err; - - page = get_a_page(rq, gfp); - if (!page) - return -ENOMEM; - - sg_init_one(rq->sg, page_address(page), PAGE_SIZE); - - err = virtqueue_add_inbuf(rq->vq, rq->sg, 1, page, gfp); - if (err < 0) - give_pages(rq, page); - - return err; -} - -/* - * Returns false if we couldn't fill entirely (OOM). - * - * Normally run in the receive path, but can also be run from ndo_open - * before we're receiving packets, or from refill_work which is - * careful to disable receiving (using napi_disable). - */ -static bool try_fill_recv(struct receive_queue *rq, gfp_t gfp) -{ - struct virtnet_info *vi = rq->vq->vdev->priv; - int err; - bool oom; - - do { - if (vi->mergeable_rx_bufs) - err = add_recvbuf_mergeable(rq, gfp); - else if (vi->big_packets) - err = add_recvbuf_big(rq, gfp); - else - err = add_recvbuf_small(rq, gfp); - - oom = err == -ENOMEM; - if (err) - break; - ++rq->num; - } while (rq->vq->num_free); - if (unlikely(rq->num > rq->max)) - rq->max = rq->num; - virtqueue_kick(rq->vq); - return !oom; -} - -static void skb_recv_done(struct virtqueue *rvq) -{ - struct virtnet_info *vi = rvq->vdev->priv; - struct receive_queue *rq = &vi->rq[vq2rxq(rvq)]; - - /* Schedule NAPI, Suppress further interrupts if successful. */ - if (napi_schedule_prep(&rq->napi)) { - virtqueue_disable_cb(rvq); - __napi_schedule(&rq->napi); - } -} - -static void virtnet_napi_enable(struct receive_queue *rq) -{ - napi_enable(&rq->napi); - - /* If all buffers were filled by other side before we napi_enabled, we - * won't get another interrupt, so process any outstanding packets - * now. virtnet_poll wants re-enable the queue, so we disable here. - * We synchronize against interrupts via NAPI_STATE_SCHED */ - if (napi_schedule_prep(&rq->napi)) { - virtqueue_disable_cb(rq->vq); - local_bh_disable(); - __napi_schedule(&rq->napi); - local_bh_enable(); - } -} - -static void refill_work(struct work_struct *work) -{ - struct virtnet_info *vi = - container_of(work, struct virtnet_info, refill.work); - bool still_empty; - int i; - - for (i = 0; i < vi->curr_queue_pairs; i++) { - struct receive_queue *rq = &vi->rq[i]; - - napi_disable(&rq->napi); - still_empty = !try_fill_recv(rq, GFP_KERNEL); - virtnet_napi_enable(rq); - - /* In theory, this can happen: if we don't get any buffers in - * we will *never* try to fill again. - */ - if (still_empty) - schedule_delayed_work(&vi->refill, HZ/2); - } -} - -static int virtnet_poll(struct napi_struct *napi, int budget) -{ - struct receive_queue *rq = - container_of(napi, struct receive_queue, napi); - struct virtnet_info *vi = rq->vq->vdev->priv; - void *buf; - unsigned int r, len, received = 0; - -again: - while (received < budget && - (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) { - receive_buf(rq, buf, len); - --rq->num; - received++; - } - - if (rq->num < rq->max / 2) { - if (!try_fill_recv(rq, GFP_ATOMIC)) - schedule_delayed_work(&vi->refill, 0); - } - - /* Out of packets? */ - if (received < budget) { - r = virtqueue_enable_cb_prepare(rq->vq); - napi_complete(napi); - if (unlikely(virtqueue_poll(rq->vq, r)) && - napi_schedule_prep(napi)) { - virtqueue_disable_cb(rq->vq); - __napi_schedule(napi); - goto again; - } - } - - return received; -} - -static int virtnet_open(struct net_device *dev) -{ - struct virtnet_info *vi = netdev_priv(dev); - int i; - - for (i = 0; i < vi->max_queue_pairs; i++) { - if (i < vi->curr_queue_pairs) - /* Make sure we have some buffers: if oom use wq. */ - if (!try_fill_recv(&vi->rq[i], GFP_KERNEL)) - schedule_delayed_work(&vi->refill, 0); - virtnet_napi_enable(&vi->rq[i]); - } - - return 0; -} - -static void free_old_xmit_skbs(struct send_queue *sq) -{ - struct sk_buff *skb; - unsigned int len; - struct virtnet_info *vi = sq->vq->vdev->priv; - struct virtnet_stats *stats = this_cpu_ptr(vi->stats); - - while ((skb = virtqueue_get_buf(sq->vq, &len)) != NULL) { - pr_debug("Sent skb %p\n", skb); - - u64_stats_update_begin(&stats->tx_syncp); - stats->tx_bytes += skb->len; - stats->tx_packets++; - u64_stats_update_end(&stats->tx_syncp); - - dev_kfree_skb_any(skb); - } -} - -static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) -{ - struct skb_vnet_hdr *hdr = skb_vnet_hdr(skb); - const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; - struct virtnet_info *vi = sq->vq->vdev->priv; - unsigned num_sg; - - pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); - - if (skb->ip_summed == CHECKSUM_PARTIAL) { - hdr->hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; - hdr->hdr.csum_start = skb_checksum_start_offset(skb); - hdr->hdr.csum_offset = skb->csum_offset; - } else { - hdr->hdr.flags = 0; - hdr->hdr.csum_offset = hdr->hdr.csum_start = 0; - } - - if (skb_is_gso(skb)) { - hdr->hdr.hdr_len = skb_headlen(skb); - hdr->hdr.gso_size = skb_shinfo(skb)->gso_size; - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) - hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; - else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; - else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) - hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP; - else - BUG(); - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN) - hdr->hdr.gso_type |= VIRTIO_NET_HDR_GSO_ECN; - } else { - hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE; - hdr->hdr.gso_size = hdr->hdr.hdr_len = 0; - } - - hdr->mhdr.num_buffers = 0; - - /* Encode metadata header at front. */ - if (vi->mergeable_rx_bufs) - sg_set_buf(sq->sg, &hdr->mhdr, sizeof hdr->mhdr); - else - sg_set_buf(sq->sg, &hdr->hdr, sizeof hdr->hdr); - - num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len) + 1; - return virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, skb, GFP_ATOMIC); -} - -static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct virtnet_info *vi = netdev_priv(dev); - int qnum = skb_get_queue_mapping(skb); - struct send_queue *sq = &vi->sq[qnum]; - int err; - - /* Free up any pending old buffers before queueing new ones. */ - free_old_xmit_skbs(sq); - - /* Try to transmit */ - err = xmit_skb(sq, skb); - - /* This should not happen! */ - if (unlikely(err)) { - dev->stats.tx_fifo_errors++; - if (net_ratelimit()) - dev_warn(&dev->dev, - "Unexpected TXQ (%d) queue failure: %d\n", qnum, err); - dev->stats.tx_dropped++; - kfree_skb(skb); - return NETDEV_TX_OK; - } - virtqueue_kick(sq->vq); - - /* Don't wait up for transmitted skbs to be freed. */ - skb_orphan(skb); - nf_reset(skb); - - /* Apparently nice girls don't return TX_BUSY; stop the queue - * before it gets out of hand. Naturally, this wastes entries. */ - if (sq->vq->num_free < 2+MAX_SKB_FRAGS) { - netif_stop_subqueue(dev, qnum); - if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { - /* More just got used, free them then recheck. */ - free_old_xmit_skbs(sq); - if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) { - netif_start_subqueue(dev, qnum); - virtqueue_disable_cb(sq->vq); - } - } - } - - return NETDEV_TX_OK; -} - -/* - * Send command via the control virtqueue and check status. Commands - * supported by the hypervisor, as indicated by feature bits, should - * never fail unless improperly formated. - */ -static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, - struct scatterlist *out, - struct scatterlist *in) -{ - struct scatterlist *sgs[4], hdr, stat; - struct virtio_net_ctrl_hdr ctrl; - virtio_net_ctrl_ack status = ~0; - unsigned out_num = 0, in_num = 0, tmp; - - /* Caller should know better */ - BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)); - - ctrl.class = class; - ctrl.cmd = cmd; - /* Add header */ - sg_init_one(&hdr, &ctrl, sizeof(ctrl)); - sgs[out_num++] = &hdr; - - if (out) - sgs[out_num++] = out; - if (in) - sgs[out_num + in_num++] = in; - - /* Add return status. */ - sg_init_one(&stat, &status, sizeof(status)); - sgs[out_num + in_num++] = &stat; - - BUG_ON(out_num + in_num > ARRAY_SIZE(sgs)); - BUG_ON(virtqueue_add_sgs(vi->cvq, sgs, out_num, in_num, vi, GFP_ATOMIC) - < 0); - - virtqueue_kick(vi->cvq); - - /* Spin for a response, the kick causes an ioport write, trapping - * into the hypervisor, so the request should be handled immediately. - */ - while (!virtqueue_get_buf(vi->cvq, &tmp)) - cpu_relax(); - - return status == VIRTIO_NET_OK; -} - -static int virtnet_set_mac_address(struct net_device *dev, void *p) -{ - struct virtnet_info *vi = netdev_priv(dev); - struct virtio_device *vdev = vi->vdev; - int ret; - struct sockaddr *addr = p; - struct scatterlist sg; - - ret = eth_prepare_mac_addr_change(dev, p); - if (ret) - return ret; - - if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR)) { - sg_init_one(&sg, addr->sa_data, dev->addr_len); - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC, - VIRTIO_NET_CTRL_MAC_ADDR_SET, - &sg, NULL)) { - dev_warn(&vdev->dev, - "Failed to set mac address by vq command.\n"); - return -EINVAL; - } - } else if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) { - vdev->config->set(vdev, offsetof(struct virtio_net_config, mac), - addr->sa_data, dev->addr_len); - } - - eth_commit_mac_addr_change(dev, p); - - return 0; -} - -static struct rtnl_link_stats64 *virtnet_stats(struct net_device *dev, - struct rtnl_link_stats64 *tot) -{ - struct virtnet_info *vi = netdev_priv(dev); - int cpu; - unsigned int start; - - for_each_possible_cpu(cpu) { - struct virtnet_stats *stats = per_cpu_ptr(vi->stats, cpu); - u64 tpackets, tbytes, rpackets, rbytes; - - do { - start = u64_stats_fetch_begin_bh(&stats->tx_syncp); - tpackets = stats->tx_packets; - tbytes = stats->tx_bytes; - } while (u64_stats_fetch_retry_bh(&stats->tx_syncp, start)); - - do { - start = u64_stats_fetch_begin_bh(&stats->rx_syncp); - rpackets = stats->rx_packets; - rbytes = stats->rx_bytes; - } while (u64_stats_fetch_retry_bh(&stats->rx_syncp, start)); - - tot->rx_packets += rpackets; - tot->tx_packets += tpackets; - tot->rx_bytes += rbytes; - tot->tx_bytes += tbytes; - } - - tot->tx_dropped = dev->stats.tx_dropped; - tot->tx_fifo_errors = dev->stats.tx_fifo_errors; - tot->rx_dropped = dev->stats.rx_dropped; - tot->rx_length_errors = dev->stats.rx_length_errors; - tot->rx_frame_errors = dev->stats.rx_frame_errors; - - return tot; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void virtnet_netpoll(struct net_device *dev) -{ - struct virtnet_info *vi = netdev_priv(dev); - int i; - - for (i = 0; i < vi->curr_queue_pairs; i++) - napi_schedule(&vi->rq[i].napi); -} -#endif - -static void virtnet_ack_link_announce(struct virtnet_info *vi) -{ - rtnl_lock(); - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_ANNOUNCE, - VIRTIO_NET_CTRL_ANNOUNCE_ACK, NULL, NULL)) - dev_warn(&vi->dev->dev, "Failed to ack link announce.\n"); - rtnl_unlock(); -} - -static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs) -{ - struct scatterlist sg; - struct virtio_net_ctrl_mq s; - struct net_device *dev = vi->dev; - - if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ)) - return 0; - - s.virtqueue_pairs = queue_pairs; - sg_init_one(&sg, &s, sizeof(s)); - - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ, - VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, &sg, NULL)) { - dev_warn(&dev->dev, "Fail to set num of queue pairs to %d\n", - queue_pairs); - return -EINVAL; - } else { - vi->curr_queue_pairs = queue_pairs; - /* virtnet_open() will refill when device is going to up. */ - if (dev->flags & IFF_UP) - schedule_delayed_work(&vi->refill, 0); - } - - return 0; -} - -static int virtnet_close(struct net_device *dev) -{ - struct virtnet_info *vi = netdev_priv(dev); - int i; - - /* Make sure refill_work doesn't re-enable napi! */ - cancel_delayed_work_sync(&vi->refill); - - for (i = 0; i < vi->max_queue_pairs; i++) - napi_disable(&vi->rq[i].napi); - - return 0; -} - -static void virtnet_set_rx_mode(struct net_device *dev) -{ - struct virtnet_info *vi = netdev_priv(dev); - struct scatterlist sg[2]; - u8 promisc, allmulti; - struct virtio_net_ctrl_mac *mac_data; - struct netdev_hw_addr *ha; - int uc_count; - int mc_count; - void *buf; - int i; - - /* We can't dynamicaly set ndo_set_rx_mode, so return gracefully */ - if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) - return; - - promisc = ((dev->flags & IFF_PROMISC) != 0); - allmulti = ((dev->flags & IFF_ALLMULTI) != 0); - - sg_init_one(sg, &promisc, sizeof(promisc)); - - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, - VIRTIO_NET_CTRL_RX_PROMISC, - sg, NULL)) - dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", - promisc ? "en" : "dis"); - - sg_init_one(sg, &allmulti, sizeof(allmulti)); - - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, - VIRTIO_NET_CTRL_RX_ALLMULTI, - sg, NULL)) - dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", - allmulti ? "en" : "dis"); - - uc_count = netdev_uc_count(dev); - mc_count = netdev_mc_count(dev); - /* MAC filter - use one buffer for both lists */ - buf = kzalloc(((uc_count + mc_count) * ETH_ALEN) + - (2 * sizeof(mac_data->entries)), GFP_ATOMIC); - mac_data = buf; - if (!buf) - return; - - sg_init_table(sg, 2); - - /* Store the unicast list and count in the front of the buffer */ - mac_data->entries = uc_count; - i = 0; - netdev_for_each_uc_addr(ha, dev) - memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); - - sg_set_buf(&sg[0], mac_data, - sizeof(mac_data->entries) + (uc_count * ETH_ALEN)); - - /* multicast list and count fill the end */ - mac_data = (void *)&mac_data->macs[uc_count][0]; - - mac_data->entries = mc_count; - i = 0; - netdev_for_each_mc_addr(ha, dev) - memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); - - sg_set_buf(&sg[1], mac_data, - sizeof(mac_data->entries) + (mc_count * ETH_ALEN)); - - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC, - VIRTIO_NET_CTRL_MAC_TABLE_SET, - sg, NULL)) - dev_warn(&dev->dev, "Failed to set MAC fitler table.\n"); - - kfree(buf); -} - -static int virtnet_vlan_rx_add_vid(struct net_device *dev, - __be16 proto, u16 vid) -{ - struct virtnet_info *vi = netdev_priv(dev); - struct scatterlist sg; - - sg_init_one(&sg, &vid, sizeof(vid)); - - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, - VIRTIO_NET_CTRL_VLAN_ADD, &sg, NULL)) - dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid); - return 0; -} - -static int virtnet_vlan_rx_kill_vid(struct net_device *dev, - __be16 proto, u16 vid) -{ - struct virtnet_info *vi = netdev_priv(dev); - struct scatterlist sg; - - sg_init_one(&sg, &vid, sizeof(vid)); - - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, - VIRTIO_NET_CTRL_VLAN_DEL, &sg, NULL)) - dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid); - return 0; -} - -static void virtnet_clean_affinity(struct virtnet_info *vi, long hcpu) -{ - int i; - int cpu; - - if (vi->affinity_hint_set) { - for (i = 0; i < vi->max_queue_pairs; i++) { - virtqueue_set_affinity(vi->rq[i].vq, -1); - virtqueue_set_affinity(vi->sq[i].vq, -1); - } - - vi->affinity_hint_set = false; - } - - i = 0; - for_each_online_cpu(cpu) { - if (cpu == hcpu) { - *per_cpu_ptr(vi->vq_index, cpu) = -1; - } else { - *per_cpu_ptr(vi->vq_index, cpu) = - ++i % vi->curr_queue_pairs; - } - } -} - -static void virtnet_set_affinity(struct virtnet_info *vi) -{ - int i; - int cpu; - - /* In multiqueue mode, when the number of cpu is equal to the number of - * queue pairs, we let the queue pairs to be private to one cpu by - * setting the affinity hint to eliminate the contention. - */ - if (vi->curr_queue_pairs == 1 || - vi->max_queue_pairs != num_online_cpus()) { - virtnet_clean_affinity(vi, -1); - return; - } - - i = 0; - for_each_online_cpu(cpu) { - virtqueue_set_affinity(vi->rq[i].vq, cpu); - virtqueue_set_affinity(vi->sq[i].vq, cpu); - *per_cpu_ptr(vi->vq_index, cpu) = i; - i++; - } - - vi->affinity_hint_set = true; -} - -static int virtnet_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb); - - switch(action & ~CPU_TASKS_FROZEN) { - case CPU_ONLINE: - case CPU_DOWN_FAILED: - case CPU_DEAD: - virtnet_set_affinity(vi); - break; - case CPU_DOWN_PREPARE: - virtnet_clean_affinity(vi, (long)hcpu); - break; - default: - break; - } - - return NOTIFY_OK; -} - -static void virtnet_get_ringparam(struct net_device *dev, - struct ethtool_ringparam *ring) -{ - struct virtnet_info *vi = netdev_priv(dev); - - ring->rx_max_pending = virtqueue_get_vring_size(vi->rq[0].vq); - ring->tx_max_pending = virtqueue_get_vring_size(vi->sq[0].vq); - ring->rx_pending = ring->rx_max_pending; - ring->tx_pending = ring->tx_max_pending; -} - - -static void virtnet_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct virtnet_info *vi = netdev_priv(dev); - struct virtio_device *vdev = vi->vdev; - - strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); - strlcpy(info->version, VIRTNET_DRIVER_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, virtio_bus_name(vdev), sizeof(info->bus_info)); - -} - -/* TODO: Eliminate OOO packets during switching */ -static int virtnet_set_channels(struct net_device *dev, - struct ethtool_channels *channels) -{ - struct virtnet_info *vi = netdev_priv(dev); - u16 queue_pairs = channels->combined_count; - int err; - - /* We don't support separate rx/tx channels. - * We don't allow setting 'other' channels. - */ - if (channels->rx_count || channels->tx_count || channels->other_count) - return -EINVAL; - - if (queue_pairs > vi->max_queue_pairs) - return -EINVAL; - - get_online_cpus(); - err = virtnet_set_queues(vi, queue_pairs); - if (!err) { - netif_set_real_num_tx_queues(dev, queue_pairs); - netif_set_real_num_rx_queues(dev, queue_pairs); - - virtnet_set_affinity(vi); - } - put_online_cpus(); - - return err; -} - -static void virtnet_get_channels(struct net_device *dev, - struct ethtool_channels *channels) -{ - struct virtnet_info *vi = netdev_priv(dev); - - channels->combined_count = vi->curr_queue_pairs; - channels->max_combined = vi->max_queue_pairs; - channels->max_other = 0; - channels->rx_count = 0; - channels->tx_count = 0; - channels->other_count = 0; -} - -static const struct ethtool_ops virtnet_ethtool_ops = { - .get_drvinfo = virtnet_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_ringparam = virtnet_get_ringparam, - .set_channels = virtnet_set_channels, - .get_channels = virtnet_get_channels, -}; - -#define MIN_MTU 68 -#define MAX_MTU 65535 - -static int virtnet_change_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu < MIN_MTU || new_mtu > MAX_MTU) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - -/* To avoid contending a lock hold by a vcpu who would exit to host, select the - * txq based on the processor id. - */ -static u16 virtnet_select_queue(struct net_device *dev, struct sk_buff *skb) -{ - int txq; - struct virtnet_info *vi = netdev_priv(dev); - - if (skb_rx_queue_recorded(skb)) { - txq = skb_get_rx_queue(skb); - } else { - txq = *__this_cpu_ptr(vi->vq_index); - if (txq == -1) - txq = 0; - } - - while (unlikely(txq >= dev->real_num_tx_queues)) - txq -= dev->real_num_tx_queues; - - return txq; -} - -static const struct net_device_ops virtnet_netdev = { - .ndo_open = virtnet_open, - .ndo_stop = virtnet_close, - .ndo_start_xmit = start_xmit, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = virtnet_set_mac_address, - .ndo_set_rx_mode = virtnet_set_rx_mode, - .ndo_change_mtu = virtnet_change_mtu, - .ndo_get_stats64 = virtnet_stats, - .ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid, - .ndo_select_queue = virtnet_select_queue, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = virtnet_netpoll, -#endif -}; - -static void virtnet_config_changed_work(struct work_struct *work) -{ - struct virtnet_info *vi = - container_of(work, struct virtnet_info, config_work); - u16 v; - - mutex_lock(&vi->config_lock); - if (!vi->config_enable) - goto done; - - if (virtio_config_val(vi->vdev, VIRTIO_NET_F_STATUS, - offsetof(struct virtio_net_config, status), - &v) < 0) - goto done; - - if (v & VIRTIO_NET_S_ANNOUNCE) { - netdev_notify_peers(vi->dev); - virtnet_ack_link_announce(vi); - } - - /* Ignore unknown (future) status bits */ - v &= VIRTIO_NET_S_LINK_UP; - - if (vi->status == v) - goto done; - - vi->status = v; - - if (vi->status & VIRTIO_NET_S_LINK_UP) { - netif_carrier_on(vi->dev); - netif_tx_wake_all_queues(vi->dev); - } else { - netif_carrier_off(vi->dev); - netif_tx_stop_all_queues(vi->dev); - } -done: - mutex_unlock(&vi->config_lock); -} - -static void virtnet_config_changed(struct virtio_device *vdev) -{ - struct virtnet_info *vi = vdev->priv; - - schedule_work(&vi->config_work); -} - -static void virtnet_free_queues(struct virtnet_info *vi) -{ - int i; - - for (i = 0; i < vi->max_queue_pairs; i++) - netif_napi_del(&vi->rq[i].napi); - - kfree(vi->rq); - kfree(vi->sq); -} - -static void free_receive_bufs(struct virtnet_info *vi) -{ - int i; - - for (i = 0; i < vi->max_queue_pairs; i++) { - while (vi->rq[i].pages) - __free_pages(get_a_page(&vi->rq[i], GFP_KERNEL), 0); - } -} - -static void free_unused_bufs(struct virtnet_info *vi) -{ - void *buf; - int i; - - for (i = 0; i < vi->max_queue_pairs; i++) { - struct virtqueue *vq = vi->sq[i].vq; - while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) - dev_kfree_skb(buf); - } - - for (i = 0; i < vi->max_queue_pairs; i++) { - struct virtqueue *vq = vi->rq[i].vq; - - while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) { - if (vi->mergeable_rx_bufs || vi->big_packets) - give_pages(&vi->rq[i], buf); - else - dev_kfree_skb(buf); - --vi->rq[i].num; - } - BUG_ON(vi->rq[i].num != 0); - } -} - -static void virtnet_del_vqs(struct virtnet_info *vi) -{ - struct virtio_device *vdev = vi->vdev; - - virtnet_clean_affinity(vi, -1); - - vdev->config->del_vqs(vdev); - - virtnet_free_queues(vi); -} - -static int virtnet_find_vqs(struct virtnet_info *vi) -{ - vq_callback_t **callbacks; - struct virtqueue **vqs; - int ret = -ENOMEM; - int i, total_vqs; - const char **names; - - /* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by - * possible N-1 RX/TX queue pairs used in multiqueue mode, followed by - * possible control vq. - */ - total_vqs = vi->max_queue_pairs * 2 + - virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ); - - /* Allocate space for find_vqs parameters */ - vqs = kzalloc(total_vqs * sizeof(*vqs), GFP_KERNEL); - if (!vqs) - goto err_vq; - callbacks = kmalloc(total_vqs * sizeof(*callbacks), GFP_KERNEL); - if (!callbacks) - goto err_callback; - names = kmalloc(total_vqs * sizeof(*names), GFP_KERNEL); - if (!names) - goto err_names; - - /* Parameters for control virtqueue, if any */ - if (vi->has_cvq) { - callbacks[total_vqs - 1] = NULL; - names[total_vqs - 1] = "control"; - } - - /* Allocate/initialize parameters for send/receive virtqueues */ - for (i = 0; i < vi->max_queue_pairs; i++) { - callbacks[rxq2vq(i)] = skb_recv_done; - callbacks[txq2vq(i)] = skb_xmit_done; - sprintf(vi->rq[i].name, "input.%d", i); - sprintf(vi->sq[i].name, "output.%d", i); - names[rxq2vq(i)] = vi->rq[i].name; - names[txq2vq(i)] = vi->sq[i].name; - } - - ret = vi->vdev->config->find_vqs(vi->vdev, total_vqs, vqs, callbacks, - names); - if (ret) - goto err_find; - - if (vi->has_cvq) { - vi->cvq = vqs[total_vqs - 1]; - if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN)) - vi->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; - } - - for (i = 0; i < vi->max_queue_pairs; i++) { - vi->rq[i].vq = vqs[rxq2vq(i)]; - vi->sq[i].vq = vqs[txq2vq(i)]; - } - - kfree(names); - kfree(callbacks); - kfree(vqs); - - return 0; - -err_find: - kfree(names); -err_names: - kfree(callbacks); -err_callback: - kfree(vqs); -err_vq: - return ret; -} - -static int virtnet_alloc_queues(struct virtnet_info *vi) -{ - int i; - - vi->sq = kzalloc(sizeof(*vi->sq) * vi->max_queue_pairs, GFP_KERNEL); - if (!vi->sq) - goto err_sq; - vi->rq = kzalloc(sizeof(*vi->rq) * vi->max_queue_pairs, GFP_KERNEL); - if (!vi->rq) - goto err_rq; - - INIT_DELAYED_WORK(&vi->refill, refill_work); - for (i = 0; i < vi->max_queue_pairs; i++) { - vi->rq[i].pages = NULL; - netif_napi_add(vi->dev, &vi->rq[i].napi, virtnet_poll, - napi_weight); - - sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg)); - sg_init_table(vi->sq[i].sg, ARRAY_SIZE(vi->sq[i].sg)); - } - - return 0; - -err_rq: - kfree(vi->sq); -err_sq: - return -ENOMEM; -} - -static int init_vqs(struct virtnet_info *vi) -{ - int ret; - - /* Allocate send & receive queues */ - ret = virtnet_alloc_queues(vi); - if (ret) - goto err; - - ret = virtnet_find_vqs(vi); - if (ret) - goto err_free; - - get_online_cpus(); - virtnet_set_affinity(vi); - put_online_cpus(); - - return 0; - -err_free: - virtnet_free_queues(vi); -err: - return ret; -} - -static int virtnet_probe(struct virtio_device *vdev) -{ - int i, err; - struct net_device *dev; - struct virtnet_info *vi; - u16 max_queue_pairs; - - /* Find if host supports multiqueue virtio_net device */ - err = virtio_config_val(vdev, VIRTIO_NET_F_MQ, - offsetof(struct virtio_net_config, - max_virtqueue_pairs), &max_queue_pairs); - - /* We need at least 2 queue's */ - if (err || max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN || - max_queue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX || - !virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) - max_queue_pairs = 1; - - /* Allocate ourselves a network device with room for our info */ - dev = alloc_etherdev_mq(sizeof(struct virtnet_info), max_queue_pairs); - if (!dev) - return -ENOMEM; - - /* Set up network device as normal. */ - dev->priv_flags |= IFF_UNICAST_FLT | IFF_LIVE_ADDR_CHANGE; - dev->netdev_ops = &virtnet_netdev; - dev->features = NETIF_F_HIGHDMA; - - SET_ETHTOOL_OPS(dev, &virtnet_ethtool_ops); - SET_NETDEV_DEV(dev, &vdev->dev); - - /* Do we support "hardware" checksums? */ - if (virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) { - /* This opens up the world of extra features. */ - dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_SG; - if (csum) - dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; - - if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { - dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO - | NETIF_F_TSO_ECN | NETIF_F_TSO6; - } - /* Individual feature bits: what can host handle? */ - if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO4)) - dev->hw_features |= NETIF_F_TSO; - if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO6)) - dev->hw_features |= NETIF_F_TSO6; - if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN)) - dev->hw_features |= NETIF_F_TSO_ECN; - if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO)) - dev->hw_features |= NETIF_F_UFO; - - if (gso) - dev->features |= dev->hw_features & (NETIF_F_ALL_TSO|NETIF_F_UFO); - /* (!csum && gso) case will be fixed by register_netdev() */ - } - - dev->vlan_features = dev->features; - - /* Configuration may specify what MAC to use. Otherwise random. */ - if (virtio_config_val_len(vdev, VIRTIO_NET_F_MAC, - offsetof(struct virtio_net_config, mac), - dev->dev_addr, dev->addr_len) < 0) - eth_hw_addr_random(dev); - - /* Set up our device-specific information */ - vi = netdev_priv(dev); - vi->dev = dev; - vi->vdev = vdev; - vdev->priv = vi; - vi->stats = alloc_percpu(struct virtnet_stats); - err = -ENOMEM; - if (vi->stats == NULL) - goto free; - - vi->vq_index = alloc_percpu(int); - if (vi->vq_index == NULL) - goto free_stats; - - mutex_init(&vi->config_lock); - vi->config_enable = true; - INIT_WORK(&vi->config_work, virtnet_config_changed_work); - - /* If we can receive ANY GSO packets, we must allocate large ones. */ - if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || - virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) || - virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) || - virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO)) - vi->big_packets = true; - - if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) - vi->mergeable_rx_bufs = true; - - if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) - vi->has_cvq = true; - - /* Use single tx/rx queue pair as default */ - vi->curr_queue_pairs = 1; - vi->max_queue_pairs = max_queue_pairs; - - /* Allocate/initialize the rx/tx queues, and invoke find_vqs */ - err = init_vqs(vi); - if (err) - goto free_index; - - netif_set_real_num_tx_queues(dev, 1); - netif_set_real_num_rx_queues(dev, 1); - - err = register_netdev(dev); - if (err) { - pr_debug("virtio_net: registering device failed\n"); - goto free_vqs; - } - - /* Last of all, set up some receive buffers. */ - for (i = 0; i < vi->curr_queue_pairs; i++) { - try_fill_recv(&vi->rq[i], GFP_KERNEL); - - /* If we didn't even get one input buffer, we're useless. */ - if (vi->rq[i].num == 0) { - free_unused_bufs(vi); - err = -ENOMEM; - goto free_recv_bufs; - } - } - - vi->nb.notifier_call = &virtnet_cpu_callback; - err = register_hotcpu_notifier(&vi->nb); - if (err) { - pr_debug("virtio_net: registering cpu notifier failed\n"); - goto free_recv_bufs; - } - - /* Assume link up if device can't report link status, - otherwise get link status from config. */ - if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) { - netif_carrier_off(dev); - schedule_work(&vi->config_work); - } else { - vi->status = VIRTIO_NET_S_LINK_UP; - netif_carrier_on(dev); - } - - pr_debug("virtnet: registered device %s with %d RX and TX vq's\n", - dev->name, max_queue_pairs); - - return 0; - -free_recv_bufs: - free_receive_bufs(vi); - unregister_netdev(dev); -free_vqs: - cancel_delayed_work_sync(&vi->refill); - virtnet_del_vqs(vi); -free_index: - free_percpu(vi->vq_index); -free_stats: - free_percpu(vi->stats); -free: - free_netdev(dev); - return err; -} - -static void remove_vq_common(struct virtnet_info *vi) -{ - vi->vdev->config->reset(vi->vdev); - - /* Free unused buffers in both send and recv, if any. */ - free_unused_bufs(vi); - - free_receive_bufs(vi); - - virtnet_del_vqs(vi); -} - -static void virtnet_remove(struct virtio_device *vdev) -{ - struct virtnet_info *vi = vdev->priv; - - unregister_hotcpu_notifier(&vi->nb); - - /* Prevent config work handler from accessing the device. */ - mutex_lock(&vi->config_lock); - vi->config_enable = false; - mutex_unlock(&vi->config_lock); - - unregister_netdev(vi->dev); - - remove_vq_common(vi); - - flush_work(&vi->config_work); - - free_percpu(vi->vq_index); - free_percpu(vi->stats); - free_netdev(vi->dev); -} - -#ifdef CONFIG_PM -static int virtnet_freeze(struct virtio_device *vdev) -{ - struct virtnet_info *vi = vdev->priv; - int i; - - unregister_hotcpu_notifier(&vi->nb); - - /* Prevent config work handler from accessing the device */ - mutex_lock(&vi->config_lock); - vi->config_enable = false; - mutex_unlock(&vi->config_lock); - - netif_device_detach(vi->dev); - cancel_delayed_work_sync(&vi->refill); - - if (netif_running(vi->dev)) - for (i = 0; i < vi->max_queue_pairs; i++) { - napi_disable(&vi->rq[i].napi); - netif_napi_del(&vi->rq[i].napi); - } - - remove_vq_common(vi); - - flush_work(&vi->config_work); - - return 0; -} - -static int virtnet_restore(struct virtio_device *vdev) -{ - struct virtnet_info *vi = vdev->priv; - int err, i; - - err = init_vqs(vi); - if (err) - return err; - - if (netif_running(vi->dev)) { - for (i = 0; i < vi->curr_queue_pairs; i++) - if (!try_fill_recv(&vi->rq[i], GFP_KERNEL)) - schedule_delayed_work(&vi->refill, 0); - - for (i = 0; i < vi->max_queue_pairs; i++) - virtnet_napi_enable(&vi->rq[i]); - } - - netif_device_attach(vi->dev); - - mutex_lock(&vi->config_lock); - vi->config_enable = true; - mutex_unlock(&vi->config_lock); - - rtnl_lock(); - virtnet_set_queues(vi, vi->curr_queue_pairs); - rtnl_unlock(); - - err = register_hotcpu_notifier(&vi->nb); - if (err) - return err; - - return 0; -} -#endif - -static struct virtio_device_id id_table[] = { - { VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID }, - { 0 }, -}; - -static unsigned int features[] = { - VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, - VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, - VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, - VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, - VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO, - VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, - VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, - VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, - VIRTIO_NET_F_CTRL_MAC_ADDR, -}; - -static struct virtio_driver virtio_net_driver = { - .feature_table = features, - .feature_table_size = ARRAY_SIZE(features), - .driver.name = KBUILD_MODNAME, - .driver.owner = THIS_MODULE, - .id_table = id_table, - .probe = virtnet_probe, - .remove = virtnet_remove, - .config_changed = virtnet_config_changed, -#ifdef CONFIG_PM - .freeze = virtnet_freeze, - .restore = virtnet_restore, -#endif -}; - -module_virtio_driver(virtio_net_driver); - -MODULE_DEVICE_TABLE(virtio, id_table); -MODULE_DESCRIPTION("Virtio network driver"); -MODULE_LICENSE("GPL"); diff --git a/addons/virtio/src/3.10.108/virtio_pci.c b/addons/virtio/src/3.10.108/virtio_pci.c deleted file mode 100644 index 933241a6..00000000 --- a/addons/virtio/src/3.10.108/virtio_pci.c +++ /dev/null @@ -1,858 +0,0 @@ -/* - * Virtio PCI driver - * - * This module allows virtio devices to be used over a virtual PCI device. - * This can be used with QEMU based VMMs like KVM or Xen. - * - * Copyright IBM Corp. 2007 - * - * Authors: - * Anthony Liguori - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -MODULE_AUTHOR("Anthony Liguori "); -MODULE_DESCRIPTION("virtio-pci"); -MODULE_LICENSE("GPL"); -MODULE_VERSION("1"); - -/* Our device structure */ -struct virtio_pci_device -{ - struct virtio_device vdev; - struct pci_dev *pci_dev; - - /* the IO mapping for the PCI config space */ - void __iomem *ioaddr; - - /* a list of queues so we can dispatch IRQs */ - spinlock_t lock; - struct list_head virtqueues; - - /* MSI-X support */ - int msix_enabled; - int intx_enabled; - struct msix_entry *msix_entries; - cpumask_var_t *msix_affinity_masks; - /* Name strings for interrupts. This size should be enough, - * and I'm too lazy to allocate each name separately. */ - char (*msix_names)[256]; - /* Number of available vectors */ - unsigned msix_vectors; - /* Vectors allocated, excluding per-vq vectors if any */ - unsigned msix_used_vectors; - - /* Status saved during hibernate/restore */ - u8 saved_status; - - /* Whether we have vector per vq */ - bool per_vq_vectors; -}; - -/* Constants for MSI-X */ -/* Use first vector for configuration changes, second and the rest for - * virtqueues Thus, we need at least 2 vectors for MSI. */ -enum { - VP_MSIX_CONFIG_VECTOR = 0, - VP_MSIX_VQ_VECTOR = 1, -}; - -struct virtio_pci_vq_info -{ - /* the actual virtqueue */ - struct virtqueue *vq; - - /* the number of entries in the queue */ - int num; - - /* the virtual address of the ring queue */ - void *queue; - - /* the list node for the virtqueues list */ - struct list_head node; - - /* MSI-X vector (or none) */ - unsigned msix_vector; -}; - -/* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */ -static DEFINE_PCI_DEVICE_TABLE(virtio_pci_id_table) = { - { PCI_DEVICE(0x1af4, PCI_ANY_ID) }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, virtio_pci_id_table); - -/* Convert a generic virtio device to our structure */ -static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev) -{ - return container_of(vdev, struct virtio_pci_device, vdev); -} - -/* virtio config->get_features() implementation */ -static u32 vp_get_features(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - - /* When someone needs more than 32 feature bits, we'll need to - * steal a bit to indicate that the rest are somewhere else. */ - return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES); -} - -/* virtio config->finalize_features() implementation */ -static void vp_finalize_features(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - - /* Give virtio_ring a chance to accept features. */ - vring_transport_features(vdev); - - /* We only support 32 feature bits. */ - BUILD_BUG_ON(ARRAY_SIZE(vdev->features) != 1); - iowrite32(vdev->features[0], vp_dev->ioaddr+VIRTIO_PCI_GUEST_FEATURES); -} - -/* virtio config->get() implementation */ -static void vp_get(struct virtio_device *vdev, unsigned offset, - void *buf, unsigned len) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - void __iomem *ioaddr = vp_dev->ioaddr + - VIRTIO_PCI_CONFIG(vp_dev) + offset; - u8 *ptr = buf; - int i; - - for (i = 0; i < len; i++) - ptr[i] = ioread8(ioaddr + i); -} - -/* the config->set() implementation. it's symmetric to the config->get() - * implementation */ -static void vp_set(struct virtio_device *vdev, unsigned offset, - const void *buf, unsigned len) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - void __iomem *ioaddr = vp_dev->ioaddr + - VIRTIO_PCI_CONFIG(vp_dev) + offset; - const u8 *ptr = buf; - int i; - - for (i = 0; i < len; i++) - iowrite8(ptr[i], ioaddr + i); -} - -/* config->{get,set}_status() implementations */ -static u8 vp_get_status(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - return ioread8(vp_dev->ioaddr + VIRTIO_PCI_STATUS); -} - -static void vp_set_status(struct virtio_device *vdev, u8 status) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - /* We should never be setting status to 0. */ - BUG_ON(status == 0); - iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS); -} - -/* wait for pending irq handlers */ -static void vp_synchronize_vectors(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - int i; - - if (vp_dev->intx_enabled) - synchronize_irq(vp_dev->pci_dev->irq); - - for (i = 0; i < vp_dev->msix_vectors; ++i) - synchronize_irq(vp_dev->msix_entries[i].vector); -} - -static void vp_reset(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - /* 0 status means a reset. */ - iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS); - /* Flush out the status write, and flush in device writes, - * including MSi-X interrupts, if any. */ - ioread8(vp_dev->ioaddr + VIRTIO_PCI_STATUS); - /* Flush pending VQ/configuration callbacks. */ - vp_synchronize_vectors(vdev); -} - -/* the notify function used when creating a virt queue */ -static void vp_notify(struct virtqueue *vq) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); - - /* we write the queue's selector into the notification register to - * signal the other end */ - iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY); -} - -/* Handle a configuration change: Tell driver if it wants to know. */ -static irqreturn_t vp_config_changed(int irq, void *opaque) -{ - struct virtio_pci_device *vp_dev = opaque; - struct virtio_driver *drv; - drv = container_of(vp_dev->vdev.dev.driver, - struct virtio_driver, driver); - - if (drv && drv->config_changed) - drv->config_changed(&vp_dev->vdev); - return IRQ_HANDLED; -} - -/* Notify all virtqueues on an interrupt. */ -static irqreturn_t vp_vring_interrupt(int irq, void *opaque) -{ - struct virtio_pci_device *vp_dev = opaque; - struct virtio_pci_vq_info *info; - irqreturn_t ret = IRQ_NONE; - unsigned long flags; - - spin_lock_irqsave(&vp_dev->lock, flags); - list_for_each_entry(info, &vp_dev->virtqueues, node) { - if (vring_interrupt(irq, info->vq) == IRQ_HANDLED) - ret = IRQ_HANDLED; - } - spin_unlock_irqrestore(&vp_dev->lock, flags); - - return ret; -} - -/* A small wrapper to also acknowledge the interrupt when it's handled. - * I really need an EIO hook for the vring so I can ack the interrupt once we - * know that we'll be handling the IRQ but before we invoke the callback since - * the callback may notify the host which results in the host attempting to - * raise an interrupt that we would then mask once we acknowledged the - * interrupt. */ -static irqreturn_t vp_interrupt(int irq, void *opaque) -{ - struct virtio_pci_device *vp_dev = opaque; - u8 isr; - - /* reading the ISR has the effect of also clearing it so it's very - * important to save off the value. */ - isr = ioread8(vp_dev->ioaddr + VIRTIO_PCI_ISR); - - /* It's definitely not us if the ISR was not high */ - if (!isr) - return IRQ_NONE; - - /* Configuration change? Tell driver if it wants to know. */ - if (isr & VIRTIO_PCI_ISR_CONFIG) - vp_config_changed(irq, opaque); - - return vp_vring_interrupt(irq, opaque); -} - -static void vp_free_vectors(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - int i; - - if (vp_dev->intx_enabled) { - free_irq(vp_dev->pci_dev->irq, vp_dev); - vp_dev->intx_enabled = 0; - } - - for (i = 0; i < vp_dev->msix_used_vectors; ++i) - free_irq(vp_dev->msix_entries[i].vector, vp_dev); - - for (i = 0; i < vp_dev->msix_vectors; i++) - if (vp_dev->msix_affinity_masks[i]) - free_cpumask_var(vp_dev->msix_affinity_masks[i]); - - if (vp_dev->msix_enabled) { - /* Disable the vector used for configuration */ - iowrite16(VIRTIO_MSI_NO_VECTOR, - vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); - /* Flush the write out to device */ - ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); - - pci_disable_msix(vp_dev->pci_dev); - vp_dev->msix_enabled = 0; - vp_dev->msix_vectors = 0; - } - - vp_dev->msix_used_vectors = 0; - kfree(vp_dev->msix_names); - vp_dev->msix_names = NULL; - kfree(vp_dev->msix_entries); - vp_dev->msix_entries = NULL; - kfree(vp_dev->msix_affinity_masks); - vp_dev->msix_affinity_masks = NULL; -} - -static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, - bool per_vq_vectors) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - const char *name = dev_name(&vp_dev->vdev.dev); - unsigned i, v; - int err = -ENOMEM; - - vp_dev->msix_entries = kmalloc(nvectors * sizeof *vp_dev->msix_entries, - GFP_KERNEL); - if (!vp_dev->msix_entries) - goto error; - vp_dev->msix_names = kmalloc(nvectors * sizeof *vp_dev->msix_names, - GFP_KERNEL); - if (!vp_dev->msix_names) - goto error; - vp_dev->msix_affinity_masks - = kzalloc(nvectors * sizeof *vp_dev->msix_affinity_masks, - GFP_KERNEL); - if (!vp_dev->msix_affinity_masks) - goto error; - for (i = 0; i < nvectors; ++i) - if (!alloc_cpumask_var(&vp_dev->msix_affinity_masks[i], - GFP_KERNEL)) - goto error; - - for (i = 0; i < nvectors; ++i) - vp_dev->msix_entries[i].entry = i; - - /* pci_enable_msix returns positive if we can't get this many. */ - err = pci_enable_msix(vp_dev->pci_dev, vp_dev->msix_entries, nvectors); - if (err > 0) - err = -ENOSPC; - if (err) - goto error; - vp_dev->msix_vectors = nvectors; - vp_dev->msix_enabled = 1; - - /* Set the vector used for configuration */ - v = vp_dev->msix_used_vectors; - snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names, - "%s-config", name); - err = request_irq(vp_dev->msix_entries[v].vector, - vp_config_changed, 0, vp_dev->msix_names[v], - vp_dev); - if (err) - goto error; - ++vp_dev->msix_used_vectors; - - iowrite16(v, vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); - /* Verify we had enough resources to assign the vector */ - v = ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); - if (v == VIRTIO_MSI_NO_VECTOR) { - err = -EBUSY; - goto error; - } - - if (!per_vq_vectors) { - /* Shared vector for all VQs */ - v = vp_dev->msix_used_vectors; - snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names, - "%s-virtqueues", name); - err = request_irq(vp_dev->msix_entries[v].vector, - vp_vring_interrupt, 0, vp_dev->msix_names[v], - vp_dev); - if (err) - goto error; - ++vp_dev->msix_used_vectors; - } - return 0; -error: - vp_free_vectors(vdev); - return err; -} - -static int vp_request_intx(struct virtio_device *vdev) -{ - int err; - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - - err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, - IRQF_SHARED, dev_name(&vdev->dev), vp_dev); - if (!err) - vp_dev->intx_enabled = 1; - return err; -} - -static struct virtqueue *setup_vq(struct virtio_device *vdev, unsigned index, - void (*callback)(struct virtqueue *vq), - const char *name, - u16 msix_vec) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - struct virtio_pci_vq_info *info; - struct virtqueue *vq; - unsigned long flags, size; - u16 num; - int err; - - /* Select the queue we're interested in */ - iowrite16(index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); - - /* Check if queue is either not available or already active. */ - num = ioread16(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NUM); - if (!num || ioread32(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN)) - return ERR_PTR(-ENOENT); - - /* allocate and fill out our structure the represents an active - * queue */ - info = kmalloc(sizeof(struct virtio_pci_vq_info), GFP_KERNEL); - if (!info) - return ERR_PTR(-ENOMEM); - - info->num = num; - info->msix_vector = msix_vec; - - size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); - info->queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); - if (info->queue == NULL) { - err = -ENOMEM; - goto out_info; - } - - /* activate the queue */ - iowrite32(virt_to_phys(info->queue) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT, - vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); - - /* create the vring */ - vq = vring_new_virtqueue(index, info->num, VIRTIO_PCI_VRING_ALIGN, vdev, - true, info->queue, vp_notify, callback, name); - if (!vq) { - err = -ENOMEM; - goto out_activate_queue; - } - - vq->priv = info; - info->vq = vq; - - if (msix_vec != VIRTIO_MSI_NO_VECTOR) { - iowrite16(msix_vec, vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - msix_vec = ioread16(vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - if (msix_vec == VIRTIO_MSI_NO_VECTOR) { - err = -EBUSY; - goto out_assign; - } - } - - if (callback) { - spin_lock_irqsave(&vp_dev->lock, flags); - list_add(&info->node, &vp_dev->virtqueues); - spin_unlock_irqrestore(&vp_dev->lock, flags); - } else { - INIT_LIST_HEAD(&info->node); - } - - return vq; - -out_assign: - vring_del_virtqueue(vq); -out_activate_queue: - iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); - free_pages_exact(info->queue, size); -out_info: - kfree(info); - return ERR_PTR(err); -} - -static void vp_del_vq(struct virtqueue *vq) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); - struct virtio_pci_vq_info *info = vq->priv; - unsigned long flags, size; - - spin_lock_irqsave(&vp_dev->lock, flags); - list_del(&info->node); - spin_unlock_irqrestore(&vp_dev->lock, flags); - - iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); - - if (vp_dev->msix_enabled) { - iowrite16(VIRTIO_MSI_NO_VECTOR, - vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - /* Flush the write out to device */ - ioread8(vp_dev->ioaddr + VIRTIO_PCI_ISR); - } - - vring_del_virtqueue(vq); - - /* Select and deactivate the queue */ - iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); - - size = PAGE_ALIGN(vring_size(info->num, VIRTIO_PCI_VRING_ALIGN)); - free_pages_exact(info->queue, size); - kfree(info); -} - -/* the config->del_vqs() implementation */ -static void vp_del_vqs(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - struct virtqueue *vq, *n; - struct virtio_pci_vq_info *info; - - list_for_each_entry_safe(vq, n, &vdev->vqs, list) { - info = vq->priv; - if (vp_dev->per_vq_vectors && - info->msix_vector != VIRTIO_MSI_NO_VECTOR) - free_irq(vp_dev->msix_entries[info->msix_vector].vector, - vq); - vp_del_vq(vq); - } - vp_dev->per_vq_vectors = false; - - vp_free_vectors(vdev); -} - -static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], - const char *names[], - bool use_msix, - bool per_vq_vectors) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - u16 msix_vec; - int i, err, nvectors, allocated_vectors; - - if (!use_msix) { - /* Old style: one normal interrupt for change and all vqs. */ - err = vp_request_intx(vdev); - if (err) - goto error_request; - } else { - if (per_vq_vectors) { - /* Best option: one for change interrupt, one per vq. */ - nvectors = 1; - for (i = 0; i < nvqs; ++i) - if (callbacks[i]) - ++nvectors; - } else { - /* Second best: one for change, shared for all vqs. */ - nvectors = 2; - } - - err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors); - if (err) - goto error_request; - } - - vp_dev->per_vq_vectors = per_vq_vectors; - allocated_vectors = vp_dev->msix_used_vectors; - for (i = 0; i < nvqs; ++i) { - if (!names[i]) { - vqs[i] = NULL; - continue; - } else if (!callbacks[i] || !vp_dev->msix_enabled) - msix_vec = VIRTIO_MSI_NO_VECTOR; - else if (vp_dev->per_vq_vectors) - msix_vec = allocated_vectors++; - else - msix_vec = VP_MSIX_VQ_VECTOR; - vqs[i] = setup_vq(vdev, i, callbacks[i], names[i], msix_vec); - if (IS_ERR(vqs[i])) { - err = PTR_ERR(vqs[i]); - goto error_find; - } - - if (!vp_dev->per_vq_vectors || msix_vec == VIRTIO_MSI_NO_VECTOR) - continue; - - /* allocate per-vq irq if available and necessary */ - snprintf(vp_dev->msix_names[msix_vec], - sizeof *vp_dev->msix_names, - "%s-%s", - dev_name(&vp_dev->vdev.dev), names[i]); - err = request_irq(vp_dev->msix_entries[msix_vec].vector, - vring_interrupt, 0, - vp_dev->msix_names[msix_vec], - vqs[i]); - if (err) { - vp_del_vq(vqs[i]); - goto error_find; - } - } - return 0; - -error_find: - vp_del_vqs(vdev); - -error_request: - return err; -} - -/* the config->find_vqs() implementation */ -static int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], - const char *names[]) -{ - int err; - - /* Try MSI-X with one vector per queue. */ - err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, true, true); - if (!err) - return 0; - /* Fallback: MSI-X with one vector for config, one shared for queues. */ - err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, - true, false); - if (!err) - return 0; - /* Finally fall back to regular interrupts. */ - return vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, - false, false); -} - -static const char *vp_bus_name(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - - return pci_name(vp_dev->pci_dev); -} - -/* Setup the affinity for a virtqueue: - * - force the affinity for per vq vector - * - OR over all affinities for shared MSI - * - ignore the affinity request if we're using INTX - */ -static int vp_set_vq_affinity(struct virtqueue *vq, int cpu) -{ - struct virtio_device *vdev = vq->vdev; - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - struct virtio_pci_vq_info *info = vq->priv; - struct cpumask *mask; - unsigned int irq; - - if (!vq->callback) - return -EINVAL; - - if (vp_dev->msix_enabled) { - mask = vp_dev->msix_affinity_masks[info->msix_vector]; - irq = vp_dev->msix_entries[info->msix_vector].vector; - if (cpu == -1) - irq_set_affinity_hint(irq, NULL); - else { - cpumask_set_cpu(cpu, mask); - irq_set_affinity_hint(irq, mask); - } - } - return 0; -} - -static const struct virtio_config_ops virtio_pci_config_ops = { - .get = vp_get, - .set = vp_set, - .get_status = vp_get_status, - .set_status = vp_set_status, - .reset = vp_reset, - .find_vqs = vp_find_vqs, - .del_vqs = vp_del_vqs, - .get_features = vp_get_features, - .finalize_features = vp_finalize_features, - .bus_name = vp_bus_name, - .set_vq_affinity = vp_set_vq_affinity, -}; - -static void virtio_pci_release_dev(struct device *_d) -{ - /* - * No need for a release method as we allocate/free - * all devices together with the pci devices. - * Provide an empty one to avoid getting a warning from core. - */ -} - -/* the PCI probing function */ -static int virtio_pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *id) -{ - struct virtio_pci_device *vp_dev; - int err; - - /* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */ - if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f) - return -ENODEV; - - if (pci_dev->revision != VIRTIO_PCI_ABI_VERSION) { - printk(KERN_ERR "virtio_pci: expected ABI version %d, got %d\n", - VIRTIO_PCI_ABI_VERSION, pci_dev->revision); - return -ENODEV; - } - - /* allocate our structure and fill it out */ - vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL); - if (vp_dev == NULL) - return -ENOMEM; - - vp_dev->vdev.dev.parent = &pci_dev->dev; - vp_dev->vdev.dev.release = virtio_pci_release_dev; - vp_dev->vdev.config = &virtio_pci_config_ops; - vp_dev->pci_dev = pci_dev; - INIT_LIST_HEAD(&vp_dev->virtqueues); - spin_lock_init(&vp_dev->lock); - - /* Disable MSI/MSIX to bring device to a known good state. */ - pci_msi_off(pci_dev); - - /* enable the device */ - err = pci_enable_device(pci_dev); - if (err) - goto out; - - err = pci_request_regions(pci_dev, "virtio-pci"); - if (err) - goto out_enable_device; - - vp_dev->ioaddr = pci_iomap(pci_dev, 0, 0); - if (vp_dev->ioaddr == NULL) { - err = -ENOMEM; - goto out_req_regions; - } - - pci_set_drvdata(pci_dev, vp_dev); - pci_set_master(pci_dev); - - /* we use the subsystem vendor/device id as the virtio vendor/device - * id. this allows us to use the same PCI vendor/device id for all - * virtio devices and to identify the particular virtio driver by - * the subsystem ids */ - vp_dev->vdev.id.vendor = pci_dev->subsystem_vendor; - vp_dev->vdev.id.device = pci_dev->subsystem_device; - - /* finally register the virtio device */ - err = register_virtio_device(&vp_dev->vdev); - if (err) - goto out_set_drvdata; - - return 0; - -out_set_drvdata: - pci_set_drvdata(pci_dev, NULL); - pci_iounmap(pci_dev, vp_dev->ioaddr); -out_req_regions: - pci_release_regions(pci_dev); -out_enable_device: - pci_disable_device(pci_dev); -out: - kfree(vp_dev); - return err; -} - -static void virtio_pci_remove(struct pci_dev *pci_dev) -{ - struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); - - unregister_virtio_device(&vp_dev->vdev); - - vp_del_vqs(&vp_dev->vdev); - pci_set_drvdata(pci_dev, NULL); - pci_iounmap(pci_dev, vp_dev->ioaddr); - pci_release_regions(pci_dev); - pci_disable_device(pci_dev); - kfree(vp_dev); -} - -#ifdef CONFIG_PM -static int virtio_pci_freeze(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); - struct virtio_driver *drv; - int ret; - - drv = container_of(vp_dev->vdev.dev.driver, - struct virtio_driver, driver); - - ret = 0; - vp_dev->saved_status = vp_get_status(&vp_dev->vdev); - if (drv && drv->freeze) - ret = drv->freeze(&vp_dev->vdev); - - if (!ret) - pci_disable_device(pci_dev); - return ret; -} - -static int virtio_pci_restore(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); - struct virtio_driver *drv; - unsigned status = 0; - int ret; - - drv = container_of(vp_dev->vdev.dev.driver, - struct virtio_driver, driver); - - ret = pci_enable_device(pci_dev); - if (ret) - return ret; - - pci_set_master(pci_dev); - /* We always start by resetting the device, in case a previous - * driver messed it up. */ - vp_reset(&vp_dev->vdev); - - /* Acknowledge that we've seen the device. */ - status |= VIRTIO_CONFIG_S_ACKNOWLEDGE; - vp_set_status(&vp_dev->vdev, status); - - /* Maybe driver failed before freeze. - * Restore the failed status, for debugging. */ - status |= vp_dev->saved_status & VIRTIO_CONFIG_S_FAILED; - vp_set_status(&vp_dev->vdev, status); - - if (!drv) - return 0; - - /* We have a driver! */ - status |= VIRTIO_CONFIG_S_DRIVER; - vp_set_status(&vp_dev->vdev, status); - - vp_finalize_features(&vp_dev->vdev); - - if (drv->restore) { - ret = drv->restore(&vp_dev->vdev); - if (ret) { - status |= VIRTIO_CONFIG_S_FAILED; - vp_set_status(&vp_dev->vdev, status); - return ret; - } - } - - /* Finally, tell the device we're all set */ - status |= VIRTIO_CONFIG_S_DRIVER_OK; - vp_set_status(&vp_dev->vdev, status); - - return ret; -} - -static const struct dev_pm_ops virtio_pci_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(virtio_pci_freeze, virtio_pci_restore) -}; -#endif - -static struct pci_driver virtio_pci_driver = { - .name = "virtio-pci", - .id_table = virtio_pci_id_table, - .probe = virtio_pci_probe, - .remove = virtio_pci_remove, -#ifdef CONFIG_PM - .driver.pm = &virtio_pci_pm_ops, -#endif -}; - -module_pci_driver(virtio_pci_driver); diff --git a/addons/virtio/src/3.10.108/virtio_ring.c b/addons/virtio/src/3.10.108/virtio_ring.c deleted file mode 100644 index 37d58f84..00000000 --- a/addons/virtio/src/3.10.108/virtio_ring.c +++ /dev/null @@ -1,871 +0,0 @@ -/* Virtio ring implementation. - * - * Copyright 2007 Rusty Russell IBM Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include -#include -#include -#include -#include -#include -#include - -#ifdef DEBUG -/* For development, we want to crash whenever the ring is screwed. */ -#define BAD_RING(_vq, fmt, args...) \ - do { \ - dev_err(&(_vq)->vq.vdev->dev, \ - "%s:"fmt, (_vq)->vq.name, ##args); \ - BUG(); \ - } while (0) -/* Caller is supposed to guarantee no reentry. */ -#define START_USE(_vq) \ - do { \ - if ((_vq)->in_use) \ - panic("%s:in_use = %i\n", \ - (_vq)->vq.name, (_vq)->in_use); \ - (_vq)->in_use = __LINE__; \ - } while (0) -#define END_USE(_vq) \ - do { BUG_ON(!(_vq)->in_use); (_vq)->in_use = 0; } while(0) -#else -#define BAD_RING(_vq, fmt, args...) \ - do { \ - dev_err(&_vq->vq.vdev->dev, \ - "%s:"fmt, (_vq)->vq.name, ##args); \ - (_vq)->broken = true; \ - } while (0) -#define START_USE(vq) -#define END_USE(vq) -#endif - -struct vring_virtqueue -{ - struct virtqueue vq; - - /* Actual memory layout for this queue */ - struct vring vring; - - /* Can we use weak barriers? */ - bool weak_barriers; - - /* Other side has made a mess, don't try any more. */ - bool broken; - - /* Host supports indirect buffers */ - bool indirect; - - /* Host publishes avail event idx */ - bool event; - - /* Head of free buffer list. */ - unsigned int free_head; - /* Number we've added since last sync. */ - unsigned int num_added; - - /* Last used index we've seen. */ - u16 last_used_idx; - - /* How to notify other side. FIXME: commonalize hcalls! */ - void (*notify)(struct virtqueue *vq); - -#ifdef DEBUG - /* They're supposed to lock for us. */ - unsigned int in_use; - - /* Figure out if their kicks are too delayed. */ - bool last_add_time_valid; - ktime_t last_add_time; -#endif - - /* Tokens for callbacks. */ - void *data[]; -}; - -#define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq) - -static inline struct scatterlist *sg_next_chained(struct scatterlist *sg, - unsigned int *count) -{ - return sg_next(sg); -} - -static inline struct scatterlist *sg_next_arr(struct scatterlist *sg, - unsigned int *count) -{ - if (--(*count) == 0) - return NULL; - return sg + 1; -} - -/* Set up an indirect table of descriptors and add it to the queue. */ -static inline int vring_add_indirect(struct vring_virtqueue *vq, - struct scatterlist *sgs[], - struct scatterlist *(*next) - (struct scatterlist *, unsigned int *), - unsigned int total_sg, - unsigned int total_out, - unsigned int total_in, - unsigned int out_sgs, - unsigned int in_sgs, - gfp_t gfp) -{ - struct vring_desc *desc; - unsigned head; - struct scatterlist *sg; - int i, n; - - /* - * We require lowmem mappings for the descriptors because - * otherwise virt_to_phys will give us bogus addresses in the - * virtqueue. - */ - gfp &= ~(__GFP_HIGHMEM | __GFP_HIGH); - - desc = kmalloc(total_sg * sizeof(struct vring_desc), gfp); - if (!desc) - return -ENOMEM; - - /* Transfer entries from the sg lists into the indirect page */ - i = 0; - for (n = 0; n < out_sgs; n++) { - for (sg = sgs[n]; sg; sg = next(sg, &total_out)) { - desc[i].flags = VRING_DESC_F_NEXT; - desc[i].addr = sg_phys(sg); - desc[i].len = sg->length; - desc[i].next = i+1; - i++; - } - } - for (; n < (out_sgs + in_sgs); n++) { - for (sg = sgs[n]; sg; sg = next(sg, &total_in)) { - desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE; - desc[i].addr = sg_phys(sg); - desc[i].len = sg->length; - desc[i].next = i+1; - i++; - } - } - BUG_ON(i != total_sg); - - /* Last one doesn't continue. */ - desc[i-1].flags &= ~VRING_DESC_F_NEXT; - desc[i-1].next = 0; - - /* We're about to use a buffer */ - vq->vq.num_free--; - - /* Use a single buffer which doesn't continue */ - head = vq->free_head; - vq->vring.desc[head].flags = VRING_DESC_F_INDIRECT; - vq->vring.desc[head].addr = virt_to_phys(desc); - vq->vring.desc[head].len = i * sizeof(struct vring_desc); - - /* Update free pointer */ - vq->free_head = vq->vring.desc[head].next; - - return head; -} - -static inline int virtqueue_add(struct virtqueue *_vq, - struct scatterlist *sgs[], - struct scatterlist *(*next) - (struct scatterlist *, unsigned int *), - unsigned int total_out, - unsigned int total_in, - unsigned int out_sgs, - unsigned int in_sgs, - void *data, - gfp_t gfp) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - struct scatterlist *sg; - unsigned int i, n, avail, uninitialized_var(prev), total_sg; - int head; - - START_USE(vq); - - BUG_ON(data == NULL); - -#ifdef DEBUG - { - ktime_t now = ktime_get(); - - /* No kick or get, with .1 second between? Warn. */ - if (vq->last_add_time_valid) - WARN_ON(ktime_to_ms(ktime_sub(now, vq->last_add_time)) - > 100); - vq->last_add_time = now; - vq->last_add_time_valid = true; - } -#endif - - total_sg = total_in + total_out; - - /* If the host supports indirect descriptor tables, and we have multiple - * buffers, then go indirect. FIXME: tune this threshold */ - if (vq->indirect && total_sg > 1 && vq->vq.num_free) { - head = vring_add_indirect(vq, sgs, next, total_sg, total_out, - total_in, - out_sgs, in_sgs, gfp); - if (likely(head >= 0)) - goto add_head; - } - - BUG_ON(total_sg > vq->vring.num); - BUG_ON(total_sg == 0); - - if (vq->vq.num_free < total_sg) { - pr_debug("Can't add buf len %i - avail = %i\n", - total_sg, vq->vq.num_free); - /* FIXME: for historical reasons, we force a notify here if - * there are outgoing parts to the buffer. Presumably the - * host should service the ring ASAP. */ - if (out_sgs) - vq->notify(&vq->vq); - END_USE(vq); - return -ENOSPC; - } - - /* We're about to use some buffers from the free list. */ - vq->vq.num_free -= total_sg; - - head = i = vq->free_head; - for (n = 0; n < out_sgs; n++) { - for (sg = sgs[n]; sg; sg = next(sg, &total_out)) { - vq->vring.desc[i].flags = VRING_DESC_F_NEXT; - vq->vring.desc[i].addr = sg_phys(sg); - vq->vring.desc[i].len = sg->length; - prev = i; - i = vq->vring.desc[i].next; - } - } - for (; n < (out_sgs + in_sgs); n++) { - for (sg = sgs[n]; sg; sg = next(sg, &total_in)) { - vq->vring.desc[i].flags = VRING_DESC_F_NEXT|VRING_DESC_F_WRITE; - vq->vring.desc[i].addr = sg_phys(sg); - vq->vring.desc[i].len = sg->length; - prev = i; - i = vq->vring.desc[i].next; - } - } - /* Last one doesn't continue. */ - vq->vring.desc[prev].flags &= ~VRING_DESC_F_NEXT; - - /* Update free pointer */ - vq->free_head = i; - -add_head: - /* Set token. */ - vq->data[head] = data; - - /* Put entry in available array (but don't update avail->idx until they - * do sync). */ - avail = (vq->vring.avail->idx & (vq->vring.num-1)); - vq->vring.avail->ring[avail] = head; - - /* Descriptors and available array need to be set before we expose the - * new available array entries. */ - virtio_wmb(vq->weak_barriers); - vq->vring.avail->idx++; - vq->num_added++; - - /* This is very unlikely, but theoretically possible. Kick - * just in case. */ - if (unlikely(vq->num_added == (1 << 16) - 1)) - virtqueue_kick(_vq); - - pr_debug("Added buffer head %i to %p\n", head, vq); - END_USE(vq); - - return 0; -} - -/** - * virtqueue_add_buf - expose buffer to other end - * @vq: the struct virtqueue we're talking about. - * @sg: the description of the buffer(s). - * @out_num: the number of sg readable by other side - * @in_num: the number of sg which are writable (after readable ones) - * @data: the token identifying the buffer. - * @gfp: how to do memory allocations (if necessary). - * - * Caller must ensure we don't call this with other virtqueue operations - * at the same time (except where noted). - * - * Returns zero or a negative error (ie. ENOSPC, ENOMEM). - */ -int virtqueue_add_buf(struct virtqueue *_vq, - struct scatterlist sg[], - unsigned int out, - unsigned int in, - void *data, - gfp_t gfp) -{ - struct scatterlist *sgs[2]; - - sgs[0] = sg; - sgs[1] = sg + out; - - return virtqueue_add(_vq, sgs, sg_next_arr, - out, in, out ? 1 : 0, in ? 1 : 0, data, gfp); -} -EXPORT_SYMBOL_GPL(virtqueue_add_buf); - -/** - * virtqueue_add_sgs - expose buffers to other end - * @vq: the struct virtqueue we're talking about. - * @sgs: array of terminated scatterlists. - * @out_num: the number of scatterlists readable by other side - * @in_num: the number of scatterlists which are writable (after readable ones) - * @data: the token identifying the buffer. - * @gfp: how to do memory allocations (if necessary). - * - * Caller must ensure we don't call this with other virtqueue operations - * at the same time (except where noted). - * - * Returns zero or a negative error (ie. ENOSPC, ENOMEM). - */ -int virtqueue_add_sgs(struct virtqueue *_vq, - struct scatterlist *sgs[], - unsigned int out_sgs, - unsigned int in_sgs, - void *data, - gfp_t gfp) -{ - unsigned int i, total_out, total_in; - - /* Count them first. */ - for (i = total_out = total_in = 0; i < out_sgs; i++) { - struct scatterlist *sg; - for (sg = sgs[i]; sg; sg = sg_next(sg)) - total_out++; - } - for (; i < out_sgs + in_sgs; i++) { - struct scatterlist *sg; - for (sg = sgs[i]; sg; sg = sg_next(sg)) - total_in++; - } - return virtqueue_add(_vq, sgs, sg_next_chained, - total_out, total_in, out_sgs, in_sgs, data, gfp); -} -EXPORT_SYMBOL_GPL(virtqueue_add_sgs); - -/** - * virtqueue_add_outbuf - expose output buffers to other end - * @vq: the struct virtqueue we're talking about. - * @sgs: array of scatterlists (need not be terminated!) - * @num: the number of scatterlists readable by other side - * @data: the token identifying the buffer. - * @gfp: how to do memory allocations (if necessary). - * - * Caller must ensure we don't call this with other virtqueue operations - * at the same time (except where noted). - * - * Returns zero or a negative error (ie. ENOSPC, ENOMEM). - */ -int virtqueue_add_outbuf(struct virtqueue *vq, - struct scatterlist sg[], unsigned int num, - void *data, - gfp_t gfp) -{ - return virtqueue_add(vq, &sg, sg_next_arr, num, 0, 1, 0, data, gfp); -} -EXPORT_SYMBOL_GPL(virtqueue_add_outbuf); - -/** - * virtqueue_add_inbuf - expose input buffers to other end - * @vq: the struct virtqueue we're talking about. - * @sgs: array of scatterlists (need not be terminated!) - * @num: the number of scatterlists writable by other side - * @data: the token identifying the buffer. - * @gfp: how to do memory allocations (if necessary). - * - * Caller must ensure we don't call this with other virtqueue operations - * at the same time (except where noted). - * - * Returns zero or a negative error (ie. ENOSPC, ENOMEM). - */ -int virtqueue_add_inbuf(struct virtqueue *vq, - struct scatterlist sg[], unsigned int num, - void *data, - gfp_t gfp) -{ - return virtqueue_add(vq, &sg, sg_next_arr, 0, num, 0, 1, data, gfp); -} -EXPORT_SYMBOL_GPL(virtqueue_add_inbuf); - -/** - * virtqueue_kick_prepare - first half of split virtqueue_kick call. - * @vq: the struct virtqueue - * - * Instead of virtqueue_kick(), you can do: - * if (virtqueue_kick_prepare(vq)) - * virtqueue_notify(vq); - * - * This is sometimes useful because the virtqueue_kick_prepare() needs - * to be serialized, but the actual virtqueue_notify() call does not. - */ -bool virtqueue_kick_prepare(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - u16 new, old; - bool needs_kick; - - START_USE(vq); - /* We need to expose available array entries before checking avail - * event. */ - virtio_mb(vq->weak_barriers); - - old = vq->vring.avail->idx - vq->num_added; - new = vq->vring.avail->idx; - vq->num_added = 0; - -#ifdef DEBUG - if (vq->last_add_time_valid) { - WARN_ON(ktime_to_ms(ktime_sub(ktime_get(), - vq->last_add_time)) > 100); - } - vq->last_add_time_valid = false; -#endif - - if (vq->event) { - needs_kick = vring_need_event(vring_avail_event(&vq->vring), - new, old); - } else { - needs_kick = !(vq->vring.used->flags & VRING_USED_F_NO_NOTIFY); - } - END_USE(vq); - return needs_kick; -} -EXPORT_SYMBOL_GPL(virtqueue_kick_prepare); - -/** - * virtqueue_notify - second half of split virtqueue_kick call. - * @vq: the struct virtqueue - * - * This does not need to be serialized. - */ -void virtqueue_notify(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - - /* Prod other side to tell it about changes. */ - vq->notify(_vq); -} -EXPORT_SYMBOL_GPL(virtqueue_notify); - -/** - * virtqueue_kick - update after add_buf - * @vq: the struct virtqueue - * - * After one or more virtqueue_add_buf calls, invoke this to kick - * the other side. - * - * Caller must ensure we don't call this with other virtqueue - * operations at the same time (except where noted). - */ -void virtqueue_kick(struct virtqueue *vq) -{ - if (virtqueue_kick_prepare(vq)) - virtqueue_notify(vq); -} -EXPORT_SYMBOL_GPL(virtqueue_kick); - -static void detach_buf(struct vring_virtqueue *vq, unsigned int head) -{ - unsigned int i; - - /* Clear data ptr. */ - vq->data[head] = NULL; - - /* Put back on free list: find end */ - i = head; - - /* Free the indirect table */ - if (vq->vring.desc[i].flags & VRING_DESC_F_INDIRECT) - kfree(phys_to_virt(vq->vring.desc[i].addr)); - - while (vq->vring.desc[i].flags & VRING_DESC_F_NEXT) { - i = vq->vring.desc[i].next; - vq->vq.num_free++; - } - - vq->vring.desc[i].next = vq->free_head; - vq->free_head = head; - /* Plus final descriptor */ - vq->vq.num_free++; -} - -static inline bool more_used(const struct vring_virtqueue *vq) -{ - return vq->last_used_idx != vq->vring.used->idx; -} - -/** - * virtqueue_get_buf - get the next used buffer - * @vq: the struct virtqueue we're talking about. - * @len: the length written into the buffer - * - * If the driver wrote data into the buffer, @len will be set to the - * amount written. This means you don't need to clear the buffer - * beforehand to ensure there's no data leakage in the case of short - * writes. - * - * Caller must ensure we don't call this with other virtqueue - * operations at the same time (except where noted). - * - * Returns NULL if there are no used buffers, or the "data" token - * handed to virtqueue_add_buf(). - */ -void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - void *ret; - unsigned int i; - u16 last_used; - - START_USE(vq); - - if (unlikely(vq->broken)) { - END_USE(vq); - return NULL; - } - - if (!more_used(vq)) { - pr_debug("No more buffers in queue\n"); - END_USE(vq); - return NULL; - } - - /* Only get used array entries after they have been exposed by host. */ - virtio_rmb(vq->weak_barriers); - - last_used = (vq->last_used_idx & (vq->vring.num - 1)); - i = vq->vring.used->ring[last_used].id; - *len = vq->vring.used->ring[last_used].len; - - if (unlikely(i >= vq->vring.num)) { - BAD_RING(vq, "id %u out of range\n", i); - return NULL; - } - if (unlikely(!vq->data[i])) { - BAD_RING(vq, "id %u is not a head!\n", i); - return NULL; - } - - /* detach_buf clears data, so grab it now. */ - ret = vq->data[i]; - detach_buf(vq, i); - vq->last_used_idx++; - /* If we expect an interrupt for the next entry, tell host - * by writing event index and flush out the write before - * the read in the next get_buf call. */ - if (!(vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT)) { - vring_used_event(&vq->vring) = vq->last_used_idx; - virtio_mb(vq->weak_barriers); - } - -#ifdef DEBUG - vq->last_add_time_valid = false; -#endif - - END_USE(vq); - return ret; -} -EXPORT_SYMBOL_GPL(virtqueue_get_buf); - -/** - * virtqueue_disable_cb - disable callbacks - * @vq: the struct virtqueue we're talking about. - * - * Note that this is not necessarily synchronous, hence unreliable and only - * useful as an optimization. - * - * Unlike other operations, this need not be serialized. - */ -void virtqueue_disable_cb(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - - vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; -} -EXPORT_SYMBOL_GPL(virtqueue_disable_cb); - -/** - * virtqueue_enable_cb_prepare - restart callbacks after disable_cb - * @vq: the struct virtqueue we're talking about. - * - * This re-enables callbacks; it returns current queue state - * in an opaque unsigned value. This value should be later tested by - * virtqueue_poll, to detect a possible race between the driver checking for - * more work, and enabling callbacks. - * - * Caller must ensure we don't call this with other virtqueue - * operations at the same time (except where noted). - */ -unsigned virtqueue_enable_cb_prepare(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - u16 last_used_idx; - - START_USE(vq); - - /* We optimistically turn back on interrupts, then check if there was - * more to do. */ - /* Depending on the VIRTIO_RING_F_EVENT_IDX feature, we need to - * either clear the flags bit or point the event index at the next - * entry. Always do both to keep code simple. */ - vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; - vring_used_event(&vq->vring) = last_used_idx = vq->last_used_idx; - END_USE(vq); - return last_used_idx; -} -EXPORT_SYMBOL_GPL(virtqueue_enable_cb_prepare); - -/** - * virtqueue_poll - query pending used buffers - * @vq: the struct virtqueue we're talking about. - * @last_used_idx: virtqueue state (from call to virtqueue_enable_cb_prepare). - * - * Returns "true" if there are pending used buffers in the queue. - * - * This does not need to be serialized. - */ -bool virtqueue_poll(struct virtqueue *_vq, unsigned last_used_idx) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - - virtio_mb(vq->weak_barriers); - return (u16)last_used_idx != vq->vring.used->idx; -} -EXPORT_SYMBOL_GPL(virtqueue_poll); - -/** - * virtqueue_enable_cb - restart callbacks after disable_cb. - * @vq: the struct virtqueue we're talking about. - * - * This re-enables callbacks; it returns "false" if there are pending - * buffers in the queue, to detect a possible race between the driver - * checking for more work, and enabling callbacks. - * - * Caller must ensure we don't call this with other virtqueue - * operations at the same time (except where noted). - */ -bool virtqueue_enable_cb(struct virtqueue *_vq) -{ - unsigned last_used_idx = virtqueue_enable_cb_prepare(_vq); - return !virtqueue_poll(_vq, last_used_idx); -} -EXPORT_SYMBOL_GPL(virtqueue_enable_cb); - -/** - * virtqueue_enable_cb_delayed - restart callbacks after disable_cb. - * @vq: the struct virtqueue we're talking about. - * - * This re-enables callbacks but hints to the other side to delay - * interrupts until most of the available buffers have been processed; - * it returns "false" if there are many pending buffers in the queue, - * to detect a possible race between the driver checking for more work, - * and enabling callbacks. - * - * Caller must ensure we don't call this with other virtqueue - * operations at the same time (except where noted). - */ -bool virtqueue_enable_cb_delayed(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - u16 bufs; - - START_USE(vq); - - /* We optimistically turn back on interrupts, then check if there was - * more to do. */ - /* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to - * either clear the flags bit or point the event index at the next - * entry. Always do both to keep code simple. */ - vq->vring.avail->flags &= ~VRING_AVAIL_F_NO_INTERRUPT; - /* TODO: tune this threshold */ - bufs = (u16)(vq->vring.avail->idx - vq->last_used_idx) * 3 / 4; - vring_used_event(&vq->vring) = vq->last_used_idx + bufs; - virtio_mb(vq->weak_barriers); - if (unlikely((u16)(vq->vring.used->idx - vq->last_used_idx) > bufs)) { - END_USE(vq); - return false; - } - - END_USE(vq); - return true; -} -EXPORT_SYMBOL_GPL(virtqueue_enable_cb_delayed); - -/** - * virtqueue_detach_unused_buf - detach first unused buffer - * @vq: the struct virtqueue we're talking about. - * - * Returns NULL or the "data" token handed to virtqueue_add_buf(). - * This is not valid on an active queue; it is useful only for device - * shutdown. - */ -void *virtqueue_detach_unused_buf(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - unsigned int i; - void *buf; - - START_USE(vq); - - for (i = 0; i < vq->vring.num; i++) { - if (!vq->data[i]) - continue; - /* detach_buf clears data, so grab it now. */ - buf = vq->data[i]; - detach_buf(vq, i); - vq->vring.avail->idx--; - END_USE(vq); - return buf; - } - /* That should have freed everything. */ - BUG_ON(vq->vq.num_free != vq->vring.num); - - END_USE(vq); - return NULL; -} -EXPORT_SYMBOL_GPL(virtqueue_detach_unused_buf); - -irqreturn_t vring_interrupt(int irq, void *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - - if (!more_used(vq)) { - pr_debug("virtqueue interrupt with no work for %p\n", vq); - return IRQ_NONE; - } - - if (unlikely(vq->broken)) - return IRQ_HANDLED; - - pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback); - if (vq->vq.callback) - vq->vq.callback(&vq->vq); - - return IRQ_HANDLED; -} -EXPORT_SYMBOL_GPL(vring_interrupt); - -struct virtqueue *vring_new_virtqueue(unsigned int index, - unsigned int num, - unsigned int vring_align, - struct virtio_device *vdev, - bool weak_barriers, - void *pages, - void (*notify)(struct virtqueue *), - void (*callback)(struct virtqueue *), - const char *name) -{ - struct vring_virtqueue *vq; - unsigned int i; - - /* We assume num is a power of 2. */ - if (num & (num - 1)) { - dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num); - return NULL; - } - - vq = kmalloc(sizeof(*vq) + sizeof(void *)*num, GFP_KERNEL); - if (!vq) - return NULL; - - vring_init(&vq->vring, num, pages, vring_align); - vq->vq.callback = callback; - vq->vq.vdev = vdev; - vq->vq.name = name; - vq->vq.num_free = num; - vq->vq.index = index; - vq->notify = notify; - vq->weak_barriers = weak_barriers; - vq->broken = false; - vq->last_used_idx = 0; - vq->num_added = 0; - list_add_tail(&vq->vq.list, &vdev->vqs); -#ifdef DEBUG - vq->in_use = false; - vq->last_add_time_valid = false; -#endif - - vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC); - vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX); - - /* No callback? Tell other side not to bother us. */ - if (!callback) - vq->vring.avail->flags |= VRING_AVAIL_F_NO_INTERRUPT; - - /* Put everything in free lists. */ - vq->free_head = 0; - for (i = 0; i < num-1; i++) { - vq->vring.desc[i].next = i+1; - vq->data[i] = NULL; - } - vq->data[i] = NULL; - - return &vq->vq; -} -EXPORT_SYMBOL_GPL(vring_new_virtqueue); - -void vring_del_virtqueue(struct virtqueue *vq) -{ - list_del(&vq->list); - kfree(to_vvq(vq)); -} -EXPORT_SYMBOL_GPL(vring_del_virtqueue); - -/* Manipulates transport-specific feature bits. */ -void vring_transport_features(struct virtio_device *vdev) -{ - unsigned int i; - - for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) { - switch (i) { - case VIRTIO_RING_F_INDIRECT_DESC: - break; - case VIRTIO_RING_F_EVENT_IDX: - break; - default: - /* We don't understand this bit. */ - clear_bit(i, vdev->features); - } - } -} -EXPORT_SYMBOL_GPL(vring_transport_features); - -/** - * virtqueue_get_vring_size - return the size of the virtqueue's vring - * @vq: the struct virtqueue containing the vring of interest. - * - * Returns the size of the vring. This is mainly used for boasting to - * userspace. Unlike other operations, this need not be serialized. - */ -unsigned int virtqueue_get_vring_size(struct virtqueue *_vq) -{ - - struct vring_virtqueue *vq = to_vvq(_vq); - - return vq->vring.num; -} -EXPORT_SYMBOL_GPL(virtqueue_get_vring_size); - -MODULE_LICENSE("GPL"); diff --git a/addons/virtio/src/3.10.108/virtio_scsi.c b/addons/virtio/src/3.10.108/virtio_scsi.c deleted file mode 100644 index 11f5326f..00000000 --- a/addons/virtio/src/3.10.108/virtio_scsi.c +++ /dev/null @@ -1,1086 +0,0 @@ -/* - * Virtio SCSI HBA driver - * - * Copyright IBM Corp. 2010 - * Copyright Red Hat, Inc. 2011 - * - * Authors: - * Stefan Hajnoczi - * Paolo Bonzini - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define VIRTIO_SCSI_MEMPOOL_SZ 64 -#define VIRTIO_SCSI_EVENT_LEN 8 -#define VIRTIO_SCSI_VQ_BASE 2 - -/* Command queue element */ -struct virtio_scsi_cmd { - struct scsi_cmnd *sc; - struct completion *comp; - union { - struct virtio_scsi_cmd_req cmd; - struct virtio_scsi_ctrl_tmf_req tmf; - struct virtio_scsi_ctrl_an_req an; - } req; - union { - struct virtio_scsi_cmd_resp cmd; - struct virtio_scsi_ctrl_tmf_resp tmf; - struct virtio_scsi_ctrl_an_resp an; - struct virtio_scsi_event evt; - } resp; -} ____cacheline_aligned_in_smp; - -struct virtio_scsi_event_node { - struct virtio_scsi *vscsi; - struct virtio_scsi_event event; - struct work_struct work; -}; - -struct virtio_scsi_vq { - /* Protects vq */ - spinlock_t vq_lock; - - struct virtqueue *vq; -}; - -/* - * Per-target queue state. - * - * This struct holds the data needed by the queue steering policy. When a - * target is sent multiple requests, we need to drive them to the same queue so - * that FIFO processing order is kept. However, if a target was idle, we can - * choose a queue arbitrarily. In this case the queue is chosen according to - * the current VCPU, so the driver expects the number of request queues to be - * equal to the number of VCPUs. This makes it easy and fast to select the - * queue, and also lets the driver optimize the IRQ affinity for the virtqueues - * (each virtqueue's affinity is set to the CPU that "owns" the queue). - * - * An interesting effect of this policy is that only writes to req_vq need to - * take the tgt_lock. Read can be done outside the lock because: - * - * - writes of req_vq only occur when atomic_inc_return(&tgt->reqs) returns 1. - * In that case, no other CPU is reading req_vq: even if they were in - * virtscsi_queuecommand_multi, they would be spinning on tgt_lock. - * - * - reads of req_vq only occur when the target is not idle (reqs != 0). - * A CPU that enters virtscsi_queuecommand_multi will not modify req_vq. - * - * Similarly, decrements of reqs are never concurrent with writes of req_vq. - * Thus they can happen outside the tgt_lock, provided of course we make reqs - * an atomic_t. - */ -struct virtio_scsi_target_state { - /* This spinlock never held at the same time as vq_lock. */ - spinlock_t tgt_lock; - - /* Count of outstanding requests. */ - atomic_t reqs; - - /* Currently active virtqueue for requests sent to this target. */ - struct virtio_scsi_vq *req_vq; -}; - -/* Driver instance state */ -struct virtio_scsi { - struct virtio_device *vdev; - - /* Get some buffers ready for event vq */ - struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN]; - - u32 num_queues; - - /* If the affinity hint is set for virtqueues */ - bool affinity_hint_set; - - /* CPU hotplug notifier */ - struct notifier_block nb; - - struct virtio_scsi_vq ctrl_vq; - struct virtio_scsi_vq event_vq; - struct virtio_scsi_vq req_vqs[]; -}; - -static struct kmem_cache *virtscsi_cmd_cache; -static mempool_t *virtscsi_cmd_pool; - -static inline struct Scsi_Host *virtio_scsi_host(struct virtio_device *vdev) -{ - return vdev->priv; -} - -static void virtscsi_compute_resid(struct scsi_cmnd *sc, u32 resid) -{ - if (!resid) - return; - - if (!scsi_bidi_cmnd(sc)) { - scsi_set_resid(sc, resid); - return; - } - - scsi_in(sc)->resid = min(resid, scsi_in(sc)->length); - scsi_out(sc)->resid = resid - scsi_in(sc)->resid; -} - -/** - * virtscsi_complete_cmd - finish a scsi_cmd and invoke scsi_done - * - * Called with vq_lock held. - */ -static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf) -{ - struct virtio_scsi_cmd *cmd = buf; - struct scsi_cmnd *sc = cmd->sc; - struct virtio_scsi_cmd_resp *resp = &cmd->resp.cmd; - struct virtio_scsi_target_state *tgt = - scsi_target(sc->device)->hostdata; - - dev_dbg(&sc->device->sdev_gendev, - "cmd %p response %u status %#02x sense_len %u\n", - sc, resp->response, resp->status, resp->sense_len); - - sc->result = resp->status; - virtscsi_compute_resid(sc, resp->resid); - switch (resp->response) { - case VIRTIO_SCSI_S_OK: - set_host_byte(sc, DID_OK); - break; - case VIRTIO_SCSI_S_OVERRUN: - set_host_byte(sc, DID_ERROR); - break; - case VIRTIO_SCSI_S_ABORTED: - set_host_byte(sc, DID_ABORT); - break; - case VIRTIO_SCSI_S_BAD_TARGET: - set_host_byte(sc, DID_BAD_TARGET); - break; - case VIRTIO_SCSI_S_RESET: - set_host_byte(sc, DID_RESET); - break; - case VIRTIO_SCSI_S_BUSY: - set_host_byte(sc, DID_BUS_BUSY); - break; - case VIRTIO_SCSI_S_TRANSPORT_FAILURE: - set_host_byte(sc, DID_TRANSPORT_DISRUPTED); - break; - case VIRTIO_SCSI_S_TARGET_FAILURE: - set_host_byte(sc, DID_TARGET_FAILURE); - break; - case VIRTIO_SCSI_S_NEXUS_FAILURE: - set_host_byte(sc, DID_NEXUS_FAILURE); - break; - default: - scmd_printk(KERN_WARNING, sc, "Unknown response %d", - resp->response); - /* fall through */ - case VIRTIO_SCSI_S_FAILURE: - set_host_byte(sc, DID_ERROR); - break; - } - - WARN_ON(resp->sense_len > VIRTIO_SCSI_SENSE_SIZE); - if (sc->sense_buffer) { - memcpy(sc->sense_buffer, resp->sense, - min_t(u32, resp->sense_len, VIRTIO_SCSI_SENSE_SIZE)); - if (resp->sense_len) - set_driver_byte(sc, DRIVER_SENSE); - } - - mempool_free(cmd, virtscsi_cmd_pool); - sc->scsi_done(sc); - - atomic_dec(&tgt->reqs); -} - -static void virtscsi_vq_done(struct virtio_scsi *vscsi, - struct virtio_scsi_vq *virtscsi_vq, - void (*fn)(struct virtio_scsi *vscsi, void *buf)) -{ - void *buf; - unsigned int len; - unsigned long flags; - struct virtqueue *vq = virtscsi_vq->vq; - - spin_lock_irqsave(&virtscsi_vq->vq_lock, flags); - do { - virtqueue_disable_cb(vq); - while ((buf = virtqueue_get_buf(vq, &len)) != NULL) - fn(vscsi, buf); - } while (!virtqueue_enable_cb(vq)); - spin_unlock_irqrestore(&virtscsi_vq->vq_lock, flags); -} - -static void virtscsi_req_done(struct virtqueue *vq) -{ - struct Scsi_Host *sh = virtio_scsi_host(vq->vdev); - struct virtio_scsi *vscsi = shost_priv(sh); - int index = vq->index - VIRTIO_SCSI_VQ_BASE; - struct virtio_scsi_vq *req_vq = &vscsi->req_vqs[index]; - - /* - * Read req_vq before decrementing the reqs field in - * virtscsi_complete_cmd. - * - * With barriers: - * - * CPU #0 virtscsi_queuecommand_multi (CPU #1) - * ------------------------------------------------------------ - * lock vq_lock - * read req_vq - * read reqs (reqs = 1) - * write reqs (reqs = 0) - * increment reqs (reqs = 1) - * write req_vq - * - * Possible reordering without barriers: - * - * CPU #0 virtscsi_queuecommand_multi (CPU #1) - * ------------------------------------------------------------ - * lock vq_lock - * read reqs (reqs = 1) - * write reqs (reqs = 0) - * increment reqs (reqs = 1) - * write req_vq - * read (wrong) req_vq - * - * We do not need a full smp_rmb, because req_vq is required to get - * to tgt->reqs: tgt is &vscsi->tgt[sc->device->id], where sc is stored - * in the virtqueue as the user token. - */ - smp_read_barrier_depends(); - - virtscsi_vq_done(vscsi, req_vq, virtscsi_complete_cmd); -}; - -static void virtscsi_poll_requests(struct virtio_scsi *vscsi) -{ - int i, num_vqs; - - num_vqs = vscsi->num_queues; - for (i = 0; i < num_vqs; i++) - virtscsi_vq_done(vscsi, &vscsi->req_vqs[i], - virtscsi_complete_cmd); -} - -static void virtscsi_complete_free(struct virtio_scsi *vscsi, void *buf) -{ - struct virtio_scsi_cmd *cmd = buf; - - if (cmd->comp) - complete_all(cmd->comp); - else - mempool_free(cmd, virtscsi_cmd_pool); -} - -static void virtscsi_ctrl_done(struct virtqueue *vq) -{ - struct Scsi_Host *sh = virtio_scsi_host(vq->vdev); - struct virtio_scsi *vscsi = shost_priv(sh); - - virtscsi_vq_done(vscsi, &vscsi->ctrl_vq, virtscsi_complete_free); -}; - -static void virtscsi_handle_event(struct work_struct *work); - -static int virtscsi_kick_event(struct virtio_scsi *vscsi, - struct virtio_scsi_event_node *event_node) -{ - int err; - struct scatterlist sg; - unsigned long flags; - - INIT_WORK(&event_node->work, virtscsi_handle_event); - sg_init_one(&sg, &event_node->event, sizeof(struct virtio_scsi_event)); - - spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags); - - err = virtqueue_add_inbuf(vscsi->event_vq.vq, &sg, 1, event_node, - GFP_ATOMIC); - if (!err) - virtqueue_kick(vscsi->event_vq.vq); - - spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags); - - return err; -} - -static int virtscsi_kick_event_all(struct virtio_scsi *vscsi) -{ - int i; - - for (i = 0; i < VIRTIO_SCSI_EVENT_LEN; i++) { - vscsi->event_list[i].vscsi = vscsi; - virtscsi_kick_event(vscsi, &vscsi->event_list[i]); - } - - return 0; -} - -static void virtscsi_cancel_event_work(struct virtio_scsi *vscsi) -{ - int i; - - for (i = 0; i < VIRTIO_SCSI_EVENT_LEN; i++) - cancel_work_sync(&vscsi->event_list[i].work); -} - -static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi, - struct virtio_scsi_event *event) -{ - struct scsi_device *sdev; - struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); - unsigned int target = event->lun[1]; - unsigned int lun = (event->lun[2] << 8) | event->lun[3]; - - switch (event->reason) { - case VIRTIO_SCSI_EVT_RESET_RESCAN: - scsi_add_device(shost, 0, target, lun); - break; - case VIRTIO_SCSI_EVT_RESET_REMOVED: - sdev = scsi_device_lookup(shost, 0, target, lun); - if (sdev) { - scsi_remove_device(sdev); - scsi_device_put(sdev); - } else { - pr_err("SCSI device %d 0 %d %d not found\n", - shost->host_no, target, lun); - } - break; - default: - pr_info("Unsupport virtio scsi event reason %x\n", event->reason); - } -} - -static void virtscsi_handle_param_change(struct virtio_scsi *vscsi, - struct virtio_scsi_event *event) -{ - struct scsi_device *sdev; - struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); - unsigned int target = event->lun[1]; - unsigned int lun = (event->lun[2] << 8) | event->lun[3]; - u8 asc = event->reason & 255; - u8 ascq = event->reason >> 8; - - sdev = scsi_device_lookup(shost, 0, target, lun); - if (!sdev) { - pr_err("SCSI device %d 0 %d %d not found\n", - shost->host_no, target, lun); - return; - } - - /* Handle "Parameters changed", "Mode parameters changed", and - "Capacity data has changed". */ - if (asc == 0x2a && (ascq == 0x00 || ascq == 0x01 || ascq == 0x09)) - scsi_rescan_device(&sdev->sdev_gendev); - - scsi_device_put(sdev); -} - -static void virtscsi_handle_event(struct work_struct *work) -{ - struct virtio_scsi_event_node *event_node = - container_of(work, struct virtio_scsi_event_node, work); - struct virtio_scsi *vscsi = event_node->vscsi; - struct virtio_scsi_event *event = &event_node->event; - - if (event->event & VIRTIO_SCSI_T_EVENTS_MISSED) { - event->event &= ~VIRTIO_SCSI_T_EVENTS_MISSED; - scsi_scan_host(virtio_scsi_host(vscsi->vdev)); - } - - switch (event->event) { - case VIRTIO_SCSI_T_NO_EVENT: - break; - case VIRTIO_SCSI_T_TRANSPORT_RESET: - virtscsi_handle_transport_reset(vscsi, event); - break; - case VIRTIO_SCSI_T_PARAM_CHANGE: - virtscsi_handle_param_change(vscsi, event); - break; - default: - pr_err("Unsupport virtio scsi event %x\n", event->event); - } - virtscsi_kick_event(vscsi, event_node); -} - -static void virtscsi_complete_event(struct virtio_scsi *vscsi, void *buf) -{ - struct virtio_scsi_event_node *event_node = buf; - - schedule_work(&event_node->work); -} - -static void virtscsi_event_done(struct virtqueue *vq) -{ - struct Scsi_Host *sh = virtio_scsi_host(vq->vdev); - struct virtio_scsi *vscsi = shost_priv(sh); - - virtscsi_vq_done(vscsi, &vscsi->event_vq, virtscsi_complete_event); -}; - -/** - * virtscsi_add_cmd - add a virtio_scsi_cmd to a virtqueue - * @vq : the struct virtqueue we're talking about - * @cmd : command structure - * @req_size : size of the request buffer - * @resp_size : size of the response buffer - * @gfp : flags to use for memory allocations - */ -static int virtscsi_add_cmd(struct virtqueue *vq, - struct virtio_scsi_cmd *cmd, - size_t req_size, size_t resp_size, gfp_t gfp) -{ - struct scsi_cmnd *sc = cmd->sc; - struct scatterlist *sgs[4], req, resp; - struct sg_table *out, *in; - unsigned out_num = 0, in_num = 0; - - out = in = NULL; - - if (sc && sc->sc_data_direction != DMA_NONE) { - if (sc->sc_data_direction != DMA_FROM_DEVICE) - out = &scsi_out(sc)->table; - if (sc->sc_data_direction != DMA_TO_DEVICE) - in = &scsi_in(sc)->table; - } - - /* Request header. */ - sg_init_one(&req, &cmd->req, req_size); - sgs[out_num++] = &req; - - /* Data-out buffer. */ - if (out) - sgs[out_num++] = out->sgl; - - /* Response header. */ - sg_init_one(&resp, &cmd->resp, resp_size); - sgs[out_num + in_num++] = &resp; - - /* Data-in buffer */ - if (in) - sgs[out_num + in_num++] = in->sgl; - - return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, gfp); -} - -static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq, - struct virtio_scsi_cmd *cmd, - size_t req_size, size_t resp_size, gfp_t gfp) -{ - unsigned long flags; - int err; - bool needs_kick = false; - - spin_lock_irqsave(&vq->vq_lock, flags); - err = virtscsi_add_cmd(vq->vq, cmd, req_size, resp_size, gfp); - if (!err) - needs_kick = virtqueue_kick_prepare(vq->vq); - - spin_unlock_irqrestore(&vq->vq_lock, flags); - - if (needs_kick) - virtqueue_notify(vq->vq); - return err; -} - -static int virtscsi_queuecommand(struct virtio_scsi *vscsi, - struct virtio_scsi_vq *req_vq, - struct scsi_cmnd *sc) -{ - struct virtio_scsi_cmd *cmd; - int ret; - - struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); - BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize); - - /* TODO: check feature bit and fail if unsupported? */ - BUG_ON(sc->sc_data_direction == DMA_BIDIRECTIONAL); - - dev_dbg(&sc->device->sdev_gendev, - "cmd %p CDB: %#02x\n", sc, sc->cmnd[0]); - - ret = SCSI_MLQUEUE_HOST_BUSY; - cmd = mempool_alloc(virtscsi_cmd_pool, GFP_ATOMIC); - if (!cmd) - goto out; - - memset(cmd, 0, sizeof(*cmd)); - cmd->sc = sc; - cmd->req.cmd = (struct virtio_scsi_cmd_req){ - .lun[0] = 1, - .lun[1] = sc->device->id, - .lun[2] = (sc->device->lun >> 8) | 0x40, - .lun[3] = sc->device->lun & 0xff, - .tag = (unsigned long)sc, - .task_attr = VIRTIO_SCSI_S_SIMPLE, - .prio = 0, - .crn = 0, - }; - - BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE); - memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len); - - if (virtscsi_kick_cmd(req_vq, cmd, - sizeof cmd->req.cmd, sizeof cmd->resp.cmd, - GFP_ATOMIC) == 0) - ret = 0; - else - mempool_free(cmd, virtscsi_cmd_pool); - -out: - return ret; -} - -static int virtscsi_queuecommand_single(struct Scsi_Host *sh, - struct scsi_cmnd *sc) -{ - struct virtio_scsi *vscsi = shost_priv(sh); - struct virtio_scsi_target_state *tgt = - scsi_target(sc->device)->hostdata; - - atomic_inc(&tgt->reqs); - return virtscsi_queuecommand(vscsi, &vscsi->req_vqs[0], sc); -} - -static struct virtio_scsi_vq *virtscsi_pick_vq(struct virtio_scsi *vscsi, - struct virtio_scsi_target_state *tgt) -{ - struct virtio_scsi_vq *vq; - unsigned long flags; - u32 queue_num; - - spin_lock_irqsave(&tgt->tgt_lock, flags); - - /* - * The memory barrier after atomic_inc_return matches - * the smp_read_barrier_depends() in virtscsi_req_done. - */ - if (atomic_inc_return(&tgt->reqs) > 1) - vq = ACCESS_ONCE(tgt->req_vq); - else { - queue_num = smp_processor_id(); - while (unlikely(queue_num >= vscsi->num_queues)) - queue_num -= vscsi->num_queues; - - tgt->req_vq = vq = &vscsi->req_vqs[queue_num]; - } - - spin_unlock_irqrestore(&tgt->tgt_lock, flags); - return vq; -} - -static int virtscsi_queuecommand_multi(struct Scsi_Host *sh, - struct scsi_cmnd *sc) -{ - struct virtio_scsi *vscsi = shost_priv(sh); - struct virtio_scsi_target_state *tgt = - scsi_target(sc->device)->hostdata; - struct virtio_scsi_vq *req_vq = virtscsi_pick_vq(vscsi, tgt); - - return virtscsi_queuecommand(vscsi, req_vq, sc); -} - -static int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd) -{ - DECLARE_COMPLETION_ONSTACK(comp); - int ret = FAILED; - - cmd->comp = ∁ - if (virtscsi_kick_cmd(&vscsi->ctrl_vq, cmd, - sizeof cmd->req.tmf, sizeof cmd->resp.tmf, - GFP_NOIO) < 0) - goto out; - - wait_for_completion(&comp); - if (cmd->resp.tmf.response == VIRTIO_SCSI_S_OK || - cmd->resp.tmf.response == VIRTIO_SCSI_S_FUNCTION_SUCCEEDED) - ret = SUCCESS; - - /* - * The spec guarantees that all requests related to the TMF have - * been completed, but the callback might not have run yet if - * we're using independent interrupts (e.g. MSI). Poll the - * virtqueues once. - * - * In the abort case, sc->scsi_done will do nothing, because - * the block layer must have detected a timeout and as a result - * REQ_ATOM_COMPLETE has been set. - */ - virtscsi_poll_requests(vscsi); - -out: - mempool_free(cmd, virtscsi_cmd_pool); - return ret; -} - -static int virtscsi_device_reset(struct scsi_cmnd *sc) -{ - struct virtio_scsi *vscsi = shost_priv(sc->device->host); - struct virtio_scsi_cmd *cmd; - - sdev_printk(KERN_INFO, sc->device, "device reset\n"); - cmd = mempool_alloc(virtscsi_cmd_pool, GFP_NOIO); - if (!cmd) - return FAILED; - - memset(cmd, 0, sizeof(*cmd)); - cmd->sc = sc; - cmd->req.tmf = (struct virtio_scsi_ctrl_tmf_req){ - .type = VIRTIO_SCSI_T_TMF, - .subtype = VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET, - .lun[0] = 1, - .lun[1] = sc->device->id, - .lun[2] = (sc->device->lun >> 8) | 0x40, - .lun[3] = sc->device->lun & 0xff, - }; - return virtscsi_tmf(vscsi, cmd); -} - -static int virtscsi_abort(struct scsi_cmnd *sc) -{ - struct virtio_scsi *vscsi = shost_priv(sc->device->host); - struct virtio_scsi_cmd *cmd; - - scmd_printk(KERN_INFO, sc, "abort\n"); - cmd = mempool_alloc(virtscsi_cmd_pool, GFP_NOIO); - if (!cmd) - return FAILED; - - memset(cmd, 0, sizeof(*cmd)); - cmd->sc = sc; - cmd->req.tmf = (struct virtio_scsi_ctrl_tmf_req){ - .type = VIRTIO_SCSI_T_TMF, - .subtype = VIRTIO_SCSI_T_TMF_ABORT_TASK, - .lun[0] = 1, - .lun[1] = sc->device->id, - .lun[2] = (sc->device->lun >> 8) | 0x40, - .lun[3] = sc->device->lun & 0xff, - .tag = (unsigned long)sc, - }; - return virtscsi_tmf(vscsi, cmd); -} - -static int virtscsi_target_alloc(struct scsi_target *starget) -{ - struct virtio_scsi_target_state *tgt = - kmalloc(sizeof(*tgt), GFP_KERNEL); - if (!tgt) - return -ENOMEM; - - spin_lock_init(&tgt->tgt_lock); - atomic_set(&tgt->reqs, 0); - tgt->req_vq = NULL; - - starget->hostdata = tgt; - return 0; -} - -static void virtscsi_target_destroy(struct scsi_target *starget) -{ - struct virtio_scsi_target_state *tgt = starget->hostdata; - kfree(tgt); -} - -static struct scsi_host_template virtscsi_host_template_single = { - .module = THIS_MODULE, - .name = "Virtio SCSI HBA", - .proc_name = "virtio_scsi", - .this_id = -1, - .queuecommand = virtscsi_queuecommand_single, - .eh_abort_handler = virtscsi_abort, - .eh_device_reset_handler = virtscsi_device_reset, - - .can_queue = 1024, - .dma_boundary = UINT_MAX, - .use_clustering = ENABLE_CLUSTERING, - .target_alloc = virtscsi_target_alloc, - .target_destroy = virtscsi_target_destroy, -}; - -static struct scsi_host_template virtscsi_host_template_multi = { - .module = THIS_MODULE, - .name = "Virtio SCSI HBA", - .proc_name = "virtio_scsi", - .this_id = -1, - .queuecommand = virtscsi_queuecommand_multi, - .eh_abort_handler = virtscsi_abort, - .eh_device_reset_handler = virtscsi_device_reset, - - .can_queue = 1024, - .dma_boundary = UINT_MAX, - .use_clustering = ENABLE_CLUSTERING, - .target_alloc = virtscsi_target_alloc, - .target_destroy = virtscsi_target_destroy, -}; - -#define virtscsi_config_get(vdev, fld) \ - ({ \ - typeof(((struct virtio_scsi_config *)0)->fld) __val; \ - vdev->config->get(vdev, \ - offsetof(struct virtio_scsi_config, fld), \ - &__val, sizeof(__val)); \ - __val; \ - }) - -#define virtscsi_config_set(vdev, fld, val) \ - (void)({ \ - typeof(((struct virtio_scsi_config *)0)->fld) __val = (val); \ - vdev->config->set(vdev, \ - offsetof(struct virtio_scsi_config, fld), \ - &__val, sizeof(__val)); \ - }) - -static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) -{ - int i; - int cpu; - - /* In multiqueue mode, when the number of cpu is equal - * to the number of request queues, we let the qeueues - * to be private to one cpu by setting the affinity hint - * to eliminate the contention. - */ - if ((vscsi->num_queues == 1 || - vscsi->num_queues != num_online_cpus()) && affinity) { - if (vscsi->affinity_hint_set) - affinity = false; - else - return; - } - - if (affinity) { - i = 0; - for_each_online_cpu(cpu) { - virtqueue_set_affinity(vscsi->req_vqs[i].vq, cpu); - i++; - } - - vscsi->affinity_hint_set = true; - } else { - for (i = 0; i < vscsi->num_queues; i++) { - if (!vscsi->req_vqs[i].vq) - continue; - - virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1); - } - - vscsi->affinity_hint_set = false; - } -} - -static void virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) -{ - get_online_cpus(); - __virtscsi_set_affinity(vscsi, affinity); - put_online_cpus(); -} - -static int virtscsi_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - struct virtio_scsi *vscsi = container_of(nfb, struct virtio_scsi, nb); - switch(action) { - case CPU_ONLINE: - case CPU_ONLINE_FROZEN: - case CPU_DEAD: - case CPU_DEAD_FROZEN: - __virtscsi_set_affinity(vscsi, true); - break; - default: - break; - } - return NOTIFY_OK; -} - -static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq, - struct virtqueue *vq) -{ - spin_lock_init(&virtscsi_vq->vq_lock); - virtscsi_vq->vq = vq; -} - -static void virtscsi_scan(struct virtio_device *vdev) -{ - struct Scsi_Host *shost = (struct Scsi_Host *)vdev->priv; - - scsi_scan_host(shost); -} - -static void virtscsi_remove_vqs(struct virtio_device *vdev) -{ - struct Scsi_Host *sh = virtio_scsi_host(vdev); - struct virtio_scsi *vscsi = shost_priv(sh); - - virtscsi_set_affinity(vscsi, false); - - /* Stop all the virtqueues. */ - vdev->config->reset(vdev); - - vdev->config->del_vqs(vdev); -} - -static int virtscsi_init(struct virtio_device *vdev, - struct virtio_scsi *vscsi) -{ - int err; - u32 i; - u32 num_vqs; - vq_callback_t **callbacks; - const char **names; - struct virtqueue **vqs; - - num_vqs = vscsi->num_queues + VIRTIO_SCSI_VQ_BASE; - vqs = kmalloc(num_vqs * sizeof(struct virtqueue *), GFP_KERNEL); - callbacks = kmalloc(num_vqs * sizeof(vq_callback_t *), GFP_KERNEL); - names = kmalloc(num_vqs * sizeof(char *), GFP_KERNEL); - - if (!callbacks || !vqs || !names) { - err = -ENOMEM; - goto out; - } - - callbacks[0] = virtscsi_ctrl_done; - callbacks[1] = virtscsi_event_done; - names[0] = "control"; - names[1] = "event"; - for (i = VIRTIO_SCSI_VQ_BASE; i < num_vqs; i++) { - callbacks[i] = virtscsi_req_done; - names[i] = "request"; - } - - /* Discover virtqueues and write information to configuration. */ - err = vdev->config->find_vqs(vdev, num_vqs, vqs, callbacks, names); - if (err) - goto out; - - virtscsi_init_vq(&vscsi->ctrl_vq, vqs[0]); - virtscsi_init_vq(&vscsi->event_vq, vqs[1]); - for (i = VIRTIO_SCSI_VQ_BASE; i < num_vqs; i++) - virtscsi_init_vq(&vscsi->req_vqs[i - VIRTIO_SCSI_VQ_BASE], - vqs[i]); - - virtscsi_set_affinity(vscsi, true); - - virtscsi_config_set(vdev, cdb_size, VIRTIO_SCSI_CDB_SIZE); - virtscsi_config_set(vdev, sense_size, VIRTIO_SCSI_SENSE_SIZE); - - if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) - virtscsi_kick_event_all(vscsi); - - err = 0; - -out: - kfree(names); - kfree(callbacks); - kfree(vqs); - if (err) - virtscsi_remove_vqs(vdev); - return err; -} - -static int virtscsi_probe(struct virtio_device *vdev) -{ - struct Scsi_Host *shost; - struct virtio_scsi *vscsi; - int err; - u32 sg_elems, num_targets; - u32 cmd_per_lun; - u32 num_queues; - struct scsi_host_template *hostt; - - /* We need to know how many queues before we allocate. */ - num_queues = virtscsi_config_get(vdev, num_queues) ? : 1; - - num_targets = virtscsi_config_get(vdev, max_target) + 1; - - if (num_queues == 1) - hostt = &virtscsi_host_template_single; - else - hostt = &virtscsi_host_template_multi; - - shost = scsi_host_alloc(hostt, - sizeof(*vscsi) + sizeof(vscsi->req_vqs[0]) * num_queues); - if (!shost) - return -ENOMEM; - - sg_elems = virtscsi_config_get(vdev, seg_max) ?: 1; - shost->sg_tablesize = sg_elems; - vscsi = shost_priv(shost); - vscsi->vdev = vdev; - vscsi->num_queues = num_queues; - vdev->priv = shost; - - err = virtscsi_init(vdev, vscsi); - if (err) - goto virtscsi_init_failed; - - vscsi->nb.notifier_call = &virtscsi_cpu_callback; - err = register_hotcpu_notifier(&vscsi->nb); - if (err) { - pr_err("registering cpu notifier failed\n"); - goto scsi_add_host_failed; - } - - cmd_per_lun = virtscsi_config_get(vdev, cmd_per_lun) ?: 1; - shost->cmd_per_lun = min_t(u32, cmd_per_lun, shost->can_queue); - shost->max_sectors = virtscsi_config_get(vdev, max_sectors) ?: 0xFFFF; - - /* LUNs > 256 are reported with format 1, so they go in the range - * 16640-32767. - */ - shost->max_lun = virtscsi_config_get(vdev, max_lun) + 1 + 0x4000; - shost->max_id = num_targets; - shost->max_channel = 0; - shost->max_cmd_len = VIRTIO_SCSI_CDB_SIZE; - err = scsi_add_host(shost, &vdev->dev); - if (err) - goto scsi_add_host_failed; - /* - * scsi_scan_host() happens in virtscsi_scan() via virtio_driver->scan() - * after VIRTIO_CONFIG_S_DRIVER_OK has been set.. - */ - return 0; - -scsi_add_host_failed: - vdev->config->del_vqs(vdev); -virtscsi_init_failed: - scsi_host_put(shost); - return err; -} - -static void virtscsi_remove(struct virtio_device *vdev) -{ - struct Scsi_Host *shost = virtio_scsi_host(vdev); - struct virtio_scsi *vscsi = shost_priv(shost); - - if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) - virtscsi_cancel_event_work(vscsi); - - scsi_remove_host(shost); - - unregister_hotcpu_notifier(&vscsi->nb); - - virtscsi_remove_vqs(vdev); - scsi_host_put(shost); -} - -#ifdef CONFIG_PM -static int virtscsi_freeze(struct virtio_device *vdev) -{ - struct Scsi_Host *sh = virtio_scsi_host(vdev); - struct virtio_scsi *vscsi = shost_priv(sh); - - unregister_hotcpu_notifier(&vscsi->nb); - virtscsi_remove_vqs(vdev); - return 0; -} - -static int virtscsi_restore(struct virtio_device *vdev) -{ - struct Scsi_Host *sh = virtio_scsi_host(vdev); - struct virtio_scsi *vscsi = shost_priv(sh); - int err; - - err = virtscsi_init(vdev, vscsi); - if (err) - return err; - - err = register_hotcpu_notifier(&vscsi->nb); - if (err) - vdev->config->del_vqs(vdev); - - return err; -} -#endif - -static struct virtio_device_id id_table[] = { - { VIRTIO_ID_SCSI, VIRTIO_DEV_ANY_ID }, - { 0 }, -}; - -static unsigned int features[] = { - VIRTIO_SCSI_F_HOTPLUG, - VIRTIO_SCSI_F_CHANGE, -}; - -static struct virtio_driver virtio_scsi_driver = { - .feature_table = features, - .feature_table_size = ARRAY_SIZE(features), - .driver.name = KBUILD_MODNAME, - .driver.owner = THIS_MODULE, - .id_table = id_table, - .probe = virtscsi_probe, - .scan = virtscsi_scan, -#ifdef CONFIG_PM - .freeze = virtscsi_freeze, - .restore = virtscsi_restore, -#endif - .remove = virtscsi_remove, -}; - -static int __init init(void) -{ - int ret = -ENOMEM; - - virtscsi_cmd_cache = KMEM_CACHE(virtio_scsi_cmd, 0); - if (!virtscsi_cmd_cache) { - pr_err("kmem_cache_create() for virtscsi_cmd_cache failed\n"); - goto error; - } - - - virtscsi_cmd_pool = - mempool_create_slab_pool(VIRTIO_SCSI_MEMPOOL_SZ, - virtscsi_cmd_cache); - if (!virtscsi_cmd_pool) { - pr_err("mempool_create() for virtscsi_cmd_pool failed\n"); - goto error; - } - ret = register_virtio_driver(&virtio_scsi_driver); - if (ret < 0) - goto error; - - return 0; - -error: - if (virtscsi_cmd_pool) { - mempool_destroy(virtscsi_cmd_pool); - virtscsi_cmd_pool = NULL; - } - if (virtscsi_cmd_cache) { - kmem_cache_destroy(virtscsi_cmd_cache); - virtscsi_cmd_cache = NULL; - } - return ret; -} - -static void __exit fini(void) -{ - unregister_virtio_driver(&virtio_scsi_driver); - mempool_destroy(virtscsi_cmd_pool); - kmem_cache_destroy(virtscsi_cmd_cache); -} -module_init(init); -module_exit(fini); - -MODULE_DEVICE_TABLE(virtio, id_table); -MODULE_DESCRIPTION("Virtio SCSI HBA driver"); -MODULE_LICENSE("GPL"); diff --git a/addons/virtio/src/4.4.180/Makefile b/addons/virtio/src/4.4.180/Makefile deleted file mode 100644 index c07407df..00000000 --- a/addons/virtio/src/4.4.180/Makefile +++ /dev/null @@ -1,7 +0,0 @@ -obj-m += virtio.o virtio_ring.o -obj-m += virtio_mmio.o -obj-m += virtio_pci.o -virtio_pci-y := virtio_pci_modern.o virtio_pci_common.o -virtio_pci-m += virtio_pci_legacy.o -obj-m += virtio_net.o -obj-m += virtio_scsi.o diff --git a/addons/virtio/src/4.4.180/config.c b/addons/virtio/src/4.4.180/config.c deleted file mode 100644 index f70bcd2f..00000000 --- a/addons/virtio/src/4.4.180/config.c +++ /dev/null @@ -1,12 +0,0 @@ -/* Configuration space parsing helpers for virtio. - * - * The configuration is [type][len][... len bytes ...] fields. - * - * Copyright 2007 Rusty Russell, IBM Corporation. - * GPL v2 or later. - */ -#include -#include -#include -#include - diff --git a/addons/virtio/src/4.4.180/virtio.c b/addons/virtio/src/4.4.180/virtio.c deleted file mode 100644 index 462e1836..00000000 --- a/addons/virtio/src/4.4.180/virtio.c +++ /dev/null @@ -1,422 +0,0 @@ -#include -#include -#include -#include -#include -#include - -/* Unique numbering for virtio devices. */ -static DEFINE_IDA(virtio_index_ida); - -static ssize_t device_show(struct device *_d, - struct device_attribute *attr, char *buf) -{ - struct virtio_device *dev = dev_to_virtio(_d); - return sprintf(buf, "0x%04x\n", dev->id.device); -} -static DEVICE_ATTR_RO(device); - -static ssize_t vendor_show(struct device *_d, - struct device_attribute *attr, char *buf) -{ - struct virtio_device *dev = dev_to_virtio(_d); - return sprintf(buf, "0x%04x\n", dev->id.vendor); -} -static DEVICE_ATTR_RO(vendor); - -static ssize_t status_show(struct device *_d, - struct device_attribute *attr, char *buf) -{ - struct virtio_device *dev = dev_to_virtio(_d); - return sprintf(buf, "0x%08x\n", dev->config->get_status(dev)); -} -static DEVICE_ATTR_RO(status); - -static ssize_t modalias_show(struct device *_d, - struct device_attribute *attr, char *buf) -{ - struct virtio_device *dev = dev_to_virtio(_d); - return sprintf(buf, "virtio:d%08Xv%08X\n", - dev->id.device, dev->id.vendor); -} -static DEVICE_ATTR_RO(modalias); - -static ssize_t features_show(struct device *_d, - struct device_attribute *attr, char *buf) -{ - struct virtio_device *dev = dev_to_virtio(_d); - unsigned int i; - ssize_t len = 0; - - /* We actually represent this as a bitstring, as it could be - * arbitrary length in future. */ - for (i = 0; i < sizeof(dev->features)*8; i++) - len += sprintf(buf+len, "%c", - __virtio_test_bit(dev, i) ? '1' : '0'); - len += sprintf(buf+len, "\n"); - return len; -} -static DEVICE_ATTR_RO(features); - -static struct attribute *virtio_dev_attrs[] = { - &dev_attr_device.attr, - &dev_attr_vendor.attr, - &dev_attr_status.attr, - &dev_attr_modalias.attr, - &dev_attr_features.attr, - NULL, -}; -ATTRIBUTE_GROUPS(virtio_dev); - -static inline int virtio_id_match(const struct virtio_device *dev, - const struct virtio_device_id *id) -{ - if (id->device != dev->id.device && id->device != VIRTIO_DEV_ANY_ID) - return 0; - - return id->vendor == VIRTIO_DEV_ANY_ID || id->vendor == dev->id.vendor; -} - -/* This looks through all the IDs a driver claims to support. If any of them - * match, we return 1 and the kernel will call virtio_dev_probe(). */ -static int virtio_dev_match(struct device *_dv, struct device_driver *_dr) -{ - unsigned int i; - struct virtio_device *dev = dev_to_virtio(_dv); - const struct virtio_device_id *ids; - - ids = drv_to_virtio(_dr)->id_table; - for (i = 0; ids[i].device; i++) - if (virtio_id_match(dev, &ids[i])) - return 1; - return 0; -} - -static int virtio_uevent(struct device *_dv, struct kobj_uevent_env *env) -{ - struct virtio_device *dev = dev_to_virtio(_dv); - - return add_uevent_var(env, "MODALIAS=virtio:d%08Xv%08X", - dev->id.device, dev->id.vendor); -} - -static void add_status(struct virtio_device *dev, unsigned status) -{ - dev->config->set_status(dev, dev->config->get_status(dev) | status); -} - -void virtio_check_driver_offered_feature(const struct virtio_device *vdev, - unsigned int fbit) -{ - unsigned int i; - struct virtio_driver *drv = drv_to_virtio(vdev->dev.driver); - - for (i = 0; i < drv->feature_table_size; i++) - if (drv->feature_table[i] == fbit) - return; - - if (drv->feature_table_legacy) { - for (i = 0; i < drv->feature_table_size_legacy; i++) - if (drv->feature_table_legacy[i] == fbit) - return; - } - - BUG(); -} -EXPORT_SYMBOL_GPL(virtio_check_driver_offered_feature); - -static void __virtio_config_changed(struct virtio_device *dev) -{ - struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); - - if (!dev->config_enabled) - dev->config_change_pending = true; - else if (drv && drv->config_changed) - drv->config_changed(dev); -} - -void virtio_config_changed(struct virtio_device *dev) -{ - unsigned long flags; - - spin_lock_irqsave(&dev->config_lock, flags); - __virtio_config_changed(dev); - spin_unlock_irqrestore(&dev->config_lock, flags); -} -EXPORT_SYMBOL_GPL(virtio_config_changed); - -static void virtio_config_disable(struct virtio_device *dev) -{ - spin_lock_irq(&dev->config_lock); - dev->config_enabled = false; - spin_unlock_irq(&dev->config_lock); -} - -static void virtio_config_enable(struct virtio_device *dev) -{ - spin_lock_irq(&dev->config_lock); - dev->config_enabled = true; - if (dev->config_change_pending) - __virtio_config_changed(dev); - dev->config_change_pending = false; - spin_unlock_irq(&dev->config_lock); -} - -static int virtio_finalize_features(struct virtio_device *dev) -{ - int ret = dev->config->finalize_features(dev); - unsigned status; - - if (ret) - return ret; - - if (!virtio_has_feature(dev, VIRTIO_F_VERSION_1)) - return 0; - - add_status(dev, VIRTIO_CONFIG_S_FEATURES_OK); - status = dev->config->get_status(dev); - if (!(status & VIRTIO_CONFIG_S_FEATURES_OK)) { - dev_err(&dev->dev, "virtio: device refuses features: %x\n", - status); - return -ENODEV; - } - return 0; -} - -static int virtio_dev_probe(struct device *_d) -{ - int err, i; - struct virtio_device *dev = dev_to_virtio(_d); - struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); - u64 device_features; - u64 driver_features; - u64 driver_features_legacy; - - /* We have a driver! */ - add_status(dev, VIRTIO_CONFIG_S_DRIVER); - - /* Figure out what features the device supports. */ - device_features = dev->config->get_features(dev); - - /* Figure out what features the driver supports. */ - driver_features = 0; - for (i = 0; i < drv->feature_table_size; i++) { - unsigned int f = drv->feature_table[i]; - BUG_ON(f >= 64); - driver_features |= (1ULL << f); - } - - /* Some drivers have a separate feature table for virtio v1.0 */ - if (drv->feature_table_legacy) { - driver_features_legacy = 0; - for (i = 0; i < drv->feature_table_size_legacy; i++) { - unsigned int f = drv->feature_table_legacy[i]; - BUG_ON(f >= 64); - driver_features_legacy |= (1ULL << f); - } - } else { - driver_features_legacy = driver_features; - } - - if (device_features & (1ULL << VIRTIO_F_VERSION_1)) - dev->features = driver_features & device_features; - else - dev->features = driver_features_legacy & device_features; - - /* Transport features always preserved to pass to finalize_features. */ - for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) - if (device_features & (1ULL << i)) - __virtio_set_bit(dev, i); - - err = virtio_finalize_features(dev); - if (err) - goto err; - - err = drv->probe(dev); - if (err) - goto err; - - /* If probe didn't do it, mark device DRIVER_OK ourselves. */ - if (!(dev->config->get_status(dev) & VIRTIO_CONFIG_S_DRIVER_OK)) - virtio_device_ready(dev); - - if (drv->scan) - drv->scan(dev); - - virtio_config_enable(dev); - - return 0; -err: - add_status(dev, VIRTIO_CONFIG_S_FAILED); - return err; - -} - -static int virtio_dev_remove(struct device *_d) -{ - struct virtio_device *dev = dev_to_virtio(_d); - struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); - - virtio_config_disable(dev); - - drv->remove(dev); - - /* Driver should have reset device. */ - WARN_ON_ONCE(dev->config->get_status(dev)); - - /* Acknowledge the device's existence again. */ - add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); - return 0; -} - -static struct bus_type virtio_bus = { - .name = "virtio", - .match = virtio_dev_match, - .dev_groups = virtio_dev_groups, - .uevent = virtio_uevent, - .probe = virtio_dev_probe, - .remove = virtio_dev_remove, -}; - -int register_virtio_driver(struct virtio_driver *driver) -{ - /* Catch this early. */ - BUG_ON(driver->feature_table_size && !driver->feature_table); - driver->driver.bus = &virtio_bus; - return driver_register(&driver->driver); -} -EXPORT_SYMBOL_GPL(register_virtio_driver); - -void unregister_virtio_driver(struct virtio_driver *driver) -{ - driver_unregister(&driver->driver); -} -EXPORT_SYMBOL_GPL(unregister_virtio_driver); - -int register_virtio_device(struct virtio_device *dev) -{ - int err; - - dev->dev.bus = &virtio_bus; - - /* Assign a unique device index and hence name. */ - err = ida_simple_get(&virtio_index_ida, 0, 0, GFP_KERNEL); - if (err < 0) - goto out; - - dev->index = err; - dev_set_name(&dev->dev, "virtio%u", dev->index); - - spin_lock_init(&dev->config_lock); - dev->config_enabled = false; - dev->config_change_pending = false; - - /* We always start by resetting the device, in case a previous - * driver messed it up. This also tests that code path a little. */ - dev->config->reset(dev); - - /* Acknowledge that we've seen the device. */ - add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); - - INIT_LIST_HEAD(&dev->vqs); - - /* device_register() causes the bus infrastructure to look for a - * matching driver. */ - err = device_register(&dev->dev); - if (err) - ida_simple_remove(&virtio_index_ida, dev->index); -out: - if (err) - add_status(dev, VIRTIO_CONFIG_S_FAILED); - return err; -} -EXPORT_SYMBOL_GPL(register_virtio_device); - -void unregister_virtio_device(struct virtio_device *dev) -{ - int index = dev->index; /* save for after device release */ - - device_unregister(&dev->dev); - ida_simple_remove(&virtio_index_ida, index); -} -EXPORT_SYMBOL_GPL(unregister_virtio_device); - -#ifdef CONFIG_PM_SLEEP -int virtio_device_freeze(struct virtio_device *dev) -{ - struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); - - virtio_config_disable(dev); - - dev->failed = dev->config->get_status(dev) & VIRTIO_CONFIG_S_FAILED; - - if (drv && drv->freeze) - return drv->freeze(dev); - - return 0; -} -EXPORT_SYMBOL_GPL(virtio_device_freeze); - -int virtio_device_restore(struct virtio_device *dev) -{ - struct virtio_driver *drv = drv_to_virtio(dev->dev.driver); - int ret; - - /* We always start by resetting the device, in case a previous - * driver messed it up. */ - dev->config->reset(dev); - - /* Acknowledge that we've seen the device. */ - add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE); - - /* Maybe driver failed before freeze. - * Restore the failed status, for debugging. */ - if (dev->failed) - add_status(dev, VIRTIO_CONFIG_S_FAILED); - - if (!drv) - return 0; - - /* We have a driver! */ - add_status(dev, VIRTIO_CONFIG_S_DRIVER); - - ret = virtio_finalize_features(dev); - if (ret) - goto err; - - if (drv->restore) { - ret = drv->restore(dev); - if (ret) - goto err; - } - - /* Finally, tell the device we're all set */ - add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK); - - virtio_config_enable(dev); - - return 0; - -err: - add_status(dev, VIRTIO_CONFIG_S_FAILED); - return ret; -} -EXPORT_SYMBOL_GPL(virtio_device_restore); -#endif - -static int virtio_init(void) -{ - if (bus_register(&virtio_bus) != 0) - panic("virtio bus registration failed"); - return 0; -} - -static void __exit virtio_exit(void) -{ - bus_unregister(&virtio_bus); - ida_destroy(&virtio_index_ida); -} -core_initcall(virtio_init); -module_exit(virtio_exit); - -MODULE_LICENSE("GPL"); diff --git a/addons/virtio/src/4.4.180/virtio_mmio.c b/addons/virtio/src/4.4.180/virtio_mmio.c deleted file mode 100644 index f499d9da..00000000 --- a/addons/virtio/src/4.4.180/virtio_mmio.c +++ /dev/null @@ -1,770 +0,0 @@ -/* - * Virtio memory mapped device driver - * - * Copyright 2011-2014, ARM Ltd. - * - * This module allows virtio devices to be used over a virtual, memory mapped - * platform device. - * - * The guest device(s) may be instantiated in one of three equivalent ways: - * - * 1. Static platform device in board's code, eg.: - * - * static struct platform_device v2m_virtio_device = { - * .name = "virtio-mmio", - * .id = -1, - * .num_resources = 2, - * .resource = (struct resource []) { - * { - * .start = 0x1001e000, - * .end = 0x1001e0ff, - * .flags = IORESOURCE_MEM, - * }, { - * .start = 42 + 32, - * .end = 42 + 32, - * .flags = IORESOURCE_IRQ, - * }, - * } - * }; - * - * 2. Device Tree node, eg.: - * - * virtio_block@1e000 { - * compatible = "virtio,mmio"; - * reg = <0x1e000 0x100>; - * interrupts = <42>; - * } - * - * 3. Kernel module (or command line) parameter. Can be used more than once - - * one device will be created for each one. Syntax: - * - * [virtio_mmio.]device=@:[:] - * where: - * := size (can use standard suffixes like K, M or G) - * := physical base address - * := interrupt number (as passed to request_irq()) - * := (optional) platform device id - * eg.: - * virtio_mmio.device=0x100@0x100b0000:48 \ - * virtio_mmio.device=1K@0x1001e000:74 - * - * - * - * Based on Virtio PCI driver by Anthony Liguori, copyright IBM Corp. 2007 - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - */ - -#define pr_fmt(fmt) "virtio-mmio: " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - - -/* The alignment to use between consumer and producer parts of vring. - * Currently hardcoded to the page size. */ -#define VIRTIO_MMIO_VRING_ALIGN PAGE_SIZE - - - -#define to_virtio_mmio_device(_plat_dev) \ - container_of(_plat_dev, struct virtio_mmio_device, vdev) - -struct virtio_mmio_device { - struct virtio_device vdev; - struct platform_device *pdev; - - void __iomem *base; - unsigned long version; - - /* a list of queues so we can dispatch IRQs */ - spinlock_t lock; - struct list_head virtqueues; -}; - -struct virtio_mmio_vq_info { - /* the actual virtqueue */ - struct virtqueue *vq; - - /* the number of entries in the queue */ - unsigned int num; - - /* the virtual address of the ring queue */ - void *queue; - - /* the list node for the virtqueues list */ - struct list_head node; -}; - - - -/* Configuration interface */ - -static u64 vm_get_features(struct virtio_device *vdev) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - u64 features; - - writel(1, vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL); - features = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES); - features <<= 32; - - writel(0, vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES_SEL); - features |= readl(vm_dev->base + VIRTIO_MMIO_DEVICE_FEATURES); - - return features; -} - -static int vm_finalize_features(struct virtio_device *vdev) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - - /* Give virtio_ring a chance to accept features. */ - vring_transport_features(vdev); - - /* Make sure there is are no mixed devices */ - if (vm_dev->version == 2 && - !__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) { - dev_err(&vdev->dev, "New virtio-mmio devices (version 2) must provide VIRTIO_F_VERSION_1 feature!\n"); - return -EINVAL; - } - - writel(1, vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL); - writel((u32)(vdev->features >> 32), - vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES); - - writel(0, vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES_SEL); - writel((u32)vdev->features, - vm_dev->base + VIRTIO_MMIO_DRIVER_FEATURES); - - return 0; -} - -static void vm_get(struct virtio_device *vdev, unsigned offset, - void *buf, unsigned len) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - void __iomem *base = vm_dev->base + VIRTIO_MMIO_CONFIG; - u8 b; - __le16 w; - __le32 l; - - if (vm_dev->version == 1) { - u8 *ptr = buf; - int i; - - for (i = 0; i < len; i++) - ptr[i] = readb(base + offset + i); - return; - } - - switch (len) { - case 1: - b = readb(base + offset); - memcpy(buf, &b, sizeof b); - break; - case 2: - w = cpu_to_le16(readw(base + offset)); - memcpy(buf, &w, sizeof w); - break; - case 4: - l = cpu_to_le32(readl(base + offset)); - memcpy(buf, &l, sizeof l); - break; - case 8: - l = cpu_to_le32(readl(base + offset)); - memcpy(buf, &l, sizeof l); - l = cpu_to_le32(ioread32(base + offset + sizeof l)); - memcpy(buf + sizeof l, &l, sizeof l); - break; - default: - BUG(); - } -} - -static void vm_set(struct virtio_device *vdev, unsigned offset, - const void *buf, unsigned len) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - void __iomem *base = vm_dev->base + VIRTIO_MMIO_CONFIG; - u8 b; - __le16 w; - __le32 l; - - if (vm_dev->version == 1) { - const u8 *ptr = buf; - int i; - - for (i = 0; i < len; i++) - writeb(ptr[i], base + offset + i); - - return; - } - - switch (len) { - case 1: - memcpy(&b, buf, sizeof b); - writeb(b, base + offset); - break; - case 2: - memcpy(&w, buf, sizeof w); - writew(le16_to_cpu(w), base + offset); - break; - case 4: - memcpy(&l, buf, sizeof l); - writel(le32_to_cpu(l), base + offset); - break; - case 8: - memcpy(&l, buf, sizeof l); - writel(le32_to_cpu(l), base + offset); - memcpy(&l, buf + sizeof l, sizeof l); - writel(le32_to_cpu(l), base + offset + sizeof l); - break; - default: - BUG(); - } -} - -static u32 vm_generation(struct virtio_device *vdev) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - - if (vm_dev->version == 1) - return 0; - else - return readl(vm_dev->base + VIRTIO_MMIO_CONFIG_GENERATION); -} - -static u8 vm_get_status(struct virtio_device *vdev) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - - return readl(vm_dev->base + VIRTIO_MMIO_STATUS) & 0xff; -} - -static void vm_set_status(struct virtio_device *vdev, u8 status) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - - /* We should never be setting status to 0. */ - BUG_ON(status == 0); - - writel(status, vm_dev->base + VIRTIO_MMIO_STATUS); -} - -static void vm_reset(struct virtio_device *vdev) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - - /* 0 status means a reset. */ - writel(0, vm_dev->base + VIRTIO_MMIO_STATUS); -} - - - -/* Transport interface */ - -/* the notify function used when creating a virt queue */ -static bool vm_notify(struct virtqueue *vq) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev); - - /* We write the queue's selector into the notification register to - * signal the other end */ - writel(vq->index, vm_dev->base + VIRTIO_MMIO_QUEUE_NOTIFY); - return true; -} - -/* Notify all virtqueues on an interrupt. */ -static irqreturn_t vm_interrupt(int irq, void *opaque) -{ - struct virtio_mmio_device *vm_dev = opaque; - struct virtio_mmio_vq_info *info; - unsigned long status; - unsigned long flags; - irqreturn_t ret = IRQ_NONE; - - /* Read and acknowledge interrupts */ - status = readl(vm_dev->base + VIRTIO_MMIO_INTERRUPT_STATUS); - writel(status, vm_dev->base + VIRTIO_MMIO_INTERRUPT_ACK); - - if (unlikely(status & VIRTIO_MMIO_INT_CONFIG)) { - virtio_config_changed(&vm_dev->vdev); - ret = IRQ_HANDLED; - } - - if (likely(status & VIRTIO_MMIO_INT_VRING)) { - spin_lock_irqsave(&vm_dev->lock, flags); - list_for_each_entry(info, &vm_dev->virtqueues, node) - ret |= vring_interrupt(irq, info->vq); - spin_unlock_irqrestore(&vm_dev->lock, flags); - } - - return ret; -} - - - -static void vm_del_vq(struct virtqueue *vq) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vq->vdev); - struct virtio_mmio_vq_info *info = vq->priv; - unsigned long flags, size; - unsigned int index = vq->index; - - spin_lock_irqsave(&vm_dev->lock, flags); - list_del(&info->node); - spin_unlock_irqrestore(&vm_dev->lock, flags); - - vring_del_virtqueue(vq); - - /* Select and deactivate the queue */ - writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); - if (vm_dev->version == 1) { - writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); - } else { - writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); - WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY)); - } - - size = PAGE_ALIGN(vring_size(info->num, VIRTIO_MMIO_VRING_ALIGN)); - free_pages_exact(info->queue, size); - kfree(info); -} - -static void vm_del_vqs(struct virtio_device *vdev) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - struct virtqueue *vq, *n; - - list_for_each_entry_safe(vq, n, &vdev->vqs, list) - vm_del_vq(vq); - - free_irq(platform_get_irq(vm_dev->pdev, 0), vm_dev); -} - - - -static struct virtqueue *vm_setup_vq(struct virtio_device *vdev, unsigned index, - void (*callback)(struct virtqueue *vq), - const char *name) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - struct virtio_mmio_vq_info *info; - struct virtqueue *vq; - unsigned long flags, size; - int err; - - if (!name) - return NULL; - - /* Select the queue we're interested in */ - writel(index, vm_dev->base + VIRTIO_MMIO_QUEUE_SEL); - - /* Queue shouldn't already be set up. */ - if (readl(vm_dev->base + (vm_dev->version == 1 ? - VIRTIO_MMIO_QUEUE_PFN : VIRTIO_MMIO_QUEUE_READY))) { - err = -ENOENT; - goto error_available; - } - - /* Allocate and fill out our active queue description */ - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) { - err = -ENOMEM; - goto error_kmalloc; - } - - /* Allocate pages for the queue - start with a queue as big as - * possible (limited by maximum size allowed by device), drop down - * to a minimal size, just big enough to fit descriptor table - * and two rings (which makes it "alignment_size * 2") - */ - info->num = readl(vm_dev->base + VIRTIO_MMIO_QUEUE_NUM_MAX); - - /* If the device reports a 0 entry queue, we won't be able to - * use it to perform I/O, and vring_new_virtqueue() can't create - * empty queues anyway, so don't bother to set up the device. - */ - if (info->num == 0) { - err = -ENOENT; - goto error_alloc_pages; - } - - while (1) { - size = PAGE_ALIGN(vring_size(info->num, - VIRTIO_MMIO_VRING_ALIGN)); - /* Did the last iter shrink the queue below minimum size? */ - if (size < VIRTIO_MMIO_VRING_ALIGN * 2) { - err = -ENOMEM; - goto error_alloc_pages; - } - - info->queue = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO); - if (info->queue) - break; - - info->num /= 2; - } - - /* Create the vring */ - vq = vring_new_virtqueue(index, info->num, VIRTIO_MMIO_VRING_ALIGN, vdev, - true, info->queue, vm_notify, callback, name); - if (!vq) { - err = -ENOMEM; - goto error_new_virtqueue; - } - - /* Activate the queue */ - writel(info->num, vm_dev->base + VIRTIO_MMIO_QUEUE_NUM); - if (vm_dev->version == 1) { - writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_QUEUE_ALIGN); - writel(virt_to_phys(info->queue) >> PAGE_SHIFT, - vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); - } else { - u64 addr; - - addr = virt_to_phys(info->queue); - writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_LOW); - writel((u32)(addr >> 32), - vm_dev->base + VIRTIO_MMIO_QUEUE_DESC_HIGH); - - addr = virt_to_phys(virtqueue_get_avail(vq)); - writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_LOW); - writel((u32)(addr >> 32), - vm_dev->base + VIRTIO_MMIO_QUEUE_AVAIL_HIGH); - - addr = virt_to_phys(virtqueue_get_used(vq)); - writel((u32)addr, vm_dev->base + VIRTIO_MMIO_QUEUE_USED_LOW); - writel((u32)(addr >> 32), - vm_dev->base + VIRTIO_MMIO_QUEUE_USED_HIGH); - - writel(1, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); - } - - vq->priv = info; - info->vq = vq; - - spin_lock_irqsave(&vm_dev->lock, flags); - list_add(&info->node, &vm_dev->virtqueues); - spin_unlock_irqrestore(&vm_dev->lock, flags); - - return vq; - -error_new_virtqueue: - if (vm_dev->version == 1) { - writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_PFN); - } else { - writel(0, vm_dev->base + VIRTIO_MMIO_QUEUE_READY); - WARN_ON(readl(vm_dev->base + VIRTIO_MMIO_QUEUE_READY)); - } - free_pages_exact(info->queue, size); -error_alloc_pages: - kfree(info); -error_kmalloc: -error_available: - return ERR_PTR(err); -} - -static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], - const char *names[]) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - unsigned int irq = platform_get_irq(vm_dev->pdev, 0); - int i, err; - - err = request_irq(irq, vm_interrupt, IRQF_SHARED, - dev_name(&vdev->dev), vm_dev); - if (err) - return err; - - for (i = 0; i < nvqs; ++i) { - vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i]); - if (IS_ERR(vqs[i])) { - vm_del_vqs(vdev); - return PTR_ERR(vqs[i]); - } - } - - return 0; -} - -static const char *vm_bus_name(struct virtio_device *vdev) -{ - struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev); - - return vm_dev->pdev->name; -} - -static const struct virtio_config_ops virtio_mmio_config_ops = { - .get = vm_get, - .set = vm_set, - .generation = vm_generation, - .get_status = vm_get_status, - .set_status = vm_set_status, - .reset = vm_reset, - .find_vqs = vm_find_vqs, - .del_vqs = vm_del_vqs, - .get_features = vm_get_features, - .finalize_features = vm_finalize_features, - .bus_name = vm_bus_name, -}; - - - -/* Platform device */ - -static int virtio_mmio_probe(struct platform_device *pdev) -{ - struct virtio_mmio_device *vm_dev; - struct resource *mem; - unsigned long magic; - - mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!mem) - return -EINVAL; - - if (!devm_request_mem_region(&pdev->dev, mem->start, - resource_size(mem), pdev->name)) - return -EBUSY; - - vm_dev = devm_kzalloc(&pdev->dev, sizeof(*vm_dev), GFP_KERNEL); - if (!vm_dev) - return -ENOMEM; - - vm_dev->vdev.dev.parent = &pdev->dev; - vm_dev->vdev.config = &virtio_mmio_config_ops; - vm_dev->pdev = pdev; - INIT_LIST_HEAD(&vm_dev->virtqueues); - spin_lock_init(&vm_dev->lock); - - vm_dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); - if (vm_dev->base == NULL) - return -EFAULT; - - /* Check magic value */ - magic = readl(vm_dev->base + VIRTIO_MMIO_MAGIC_VALUE); - if (magic != ('v' | 'i' << 8 | 'r' << 16 | 't' << 24)) { - dev_warn(&pdev->dev, "Wrong magic value 0x%08lx!\n", magic); - return -ENODEV; - } - - /* Check device version */ - vm_dev->version = readl(vm_dev->base + VIRTIO_MMIO_VERSION); - if (vm_dev->version < 1 || vm_dev->version > 2) { - dev_err(&pdev->dev, "Version %ld not supported!\n", - vm_dev->version); - return -ENXIO; - } - - vm_dev->vdev.id.device = readl(vm_dev->base + VIRTIO_MMIO_DEVICE_ID); - if (vm_dev->vdev.id.device == 0) { - /* - * virtio-mmio device with an ID 0 is a (dummy) placeholder - * with no function. End probing now with no error reported. - */ - return -ENODEV; - } - vm_dev->vdev.id.vendor = readl(vm_dev->base + VIRTIO_MMIO_VENDOR_ID); - - if (vm_dev->version == 1) - writel(PAGE_SIZE, vm_dev->base + VIRTIO_MMIO_GUEST_PAGE_SIZE); - - platform_set_drvdata(pdev, vm_dev); - - return register_virtio_device(&vm_dev->vdev); -} - -static int virtio_mmio_remove(struct platform_device *pdev) -{ - struct virtio_mmio_device *vm_dev = platform_get_drvdata(pdev); - - unregister_virtio_device(&vm_dev->vdev); - - return 0; -} - - - -/* Devices list parameter */ - -#if defined(CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES) - -static struct device vm_cmdline_parent = { - .init_name = "virtio-mmio-cmdline", -}; - -static int vm_cmdline_parent_registered; -static int vm_cmdline_id; - -static int vm_cmdline_set(const char *device, - const struct kernel_param *kp) -{ - int err; - struct resource resources[2] = {}; - char *str; - long long int base, size; - unsigned int irq; - int processed, consumed = 0; - struct platform_device *pdev; - - /* Consume "size" part of the command line parameter */ - size = memparse(device, &str); - - /* Get "@:[:]" chunks */ - processed = sscanf(str, "@%lli:%u%n:%d%n", - &base, &irq, &consumed, - &vm_cmdline_id, &consumed); - - /* - * sscanf() must processes at least 2 chunks; also there - * must be no extra characters after the last chunk, so - * str[consumed] must be '\0' - */ - if (processed < 2 || str[consumed]) - return -EINVAL; - - resources[0].flags = IORESOURCE_MEM; - resources[0].start = base; - resources[0].end = base + size - 1; - - resources[1].flags = IORESOURCE_IRQ; - resources[1].start = resources[1].end = irq; - - if (!vm_cmdline_parent_registered) { - err = device_register(&vm_cmdline_parent); - if (err) { - pr_err("Failed to register parent device!\n"); - return err; - } - vm_cmdline_parent_registered = 1; - } - - pr_info("Registering device virtio-mmio.%d at 0x%llx-0x%llx, IRQ %d.\n", - vm_cmdline_id, - (unsigned long long)resources[0].start, - (unsigned long long)resources[0].end, - (int)resources[1].start); - - pdev = platform_device_register_resndata(&vm_cmdline_parent, - "virtio-mmio", vm_cmdline_id++, - resources, ARRAY_SIZE(resources), NULL, 0); - if (IS_ERR(pdev)) - return PTR_ERR(pdev); - - return 0; -} - -static int vm_cmdline_get_device(struct device *dev, void *data) -{ - char *buffer = data; - unsigned int len = strlen(buffer); - struct platform_device *pdev = to_platform_device(dev); - - snprintf(buffer + len, PAGE_SIZE - len, "0x%llx@0x%llx:%llu:%d\n", - pdev->resource[0].end - pdev->resource[0].start + 1ULL, - (unsigned long long)pdev->resource[0].start, - (unsigned long long)pdev->resource[1].start, - pdev->id); - return 0; -} - -static int vm_cmdline_get(char *buffer, const struct kernel_param *kp) -{ - buffer[0] = '\0'; - device_for_each_child(&vm_cmdline_parent, buffer, - vm_cmdline_get_device); - return strlen(buffer) + 1; -} - -static const struct kernel_param_ops vm_cmdline_param_ops = { - .set = vm_cmdline_set, - .get = vm_cmdline_get, -}; - -device_param_cb(device, &vm_cmdline_param_ops, NULL, S_IRUSR); - -static int vm_unregister_cmdline_device(struct device *dev, - void *data) -{ - platform_device_unregister(to_platform_device(dev)); - - return 0; -} - -static void vm_unregister_cmdline_devices(void) -{ - if (vm_cmdline_parent_registered) { - device_for_each_child(&vm_cmdline_parent, NULL, - vm_unregister_cmdline_device); - device_unregister(&vm_cmdline_parent); - vm_cmdline_parent_registered = 0; - } -} - -#else - -static void vm_unregister_cmdline_devices(void) -{ -} - -#endif - -/* Platform driver */ - -static struct of_device_id virtio_mmio_match[] = { - { .compatible = "virtio,mmio", }, - {}, -}; -MODULE_DEVICE_TABLE(of, virtio_mmio_match); - -#ifdef CONFIG_ACPI -static const struct acpi_device_id virtio_mmio_acpi_match[] = { - { "LNRO0005", }, - { } -}; -MODULE_DEVICE_TABLE(acpi, virtio_mmio_acpi_match); -#endif - -static struct platform_driver virtio_mmio_driver = { - .probe = virtio_mmio_probe, - .remove = virtio_mmio_remove, - .driver = { - .name = "virtio-mmio", - .of_match_table = virtio_mmio_match, - .acpi_match_table = ACPI_PTR(virtio_mmio_acpi_match), - }, -}; - -static int __init virtio_mmio_init(void) -{ - return platform_driver_register(&virtio_mmio_driver); -} - -static void __exit virtio_mmio_exit(void) -{ - platform_driver_unregister(&virtio_mmio_driver); - vm_unregister_cmdline_devices(); -} - -module_init(virtio_mmio_init); -module_exit(virtio_mmio_exit); - -MODULE_AUTHOR("Pawel Moll "); -MODULE_DESCRIPTION("Platform bus driver for memory mapped virtio devices"); -MODULE_LICENSE("GPL"); diff --git a/addons/virtio/src/4.4.180/virtio_net.c b/addons/virtio/src/4.4.180/virtio_net.c deleted file mode 100644 index 2759d386..00000000 --- a/addons/virtio/src/4.4.180/virtio_net.c +++ /dev/null @@ -1,2070 +0,0 @@ -/* A network driver using virtio. - * - * Copyright 2007 Rusty Russell IBM Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, see . - */ -//#define DEBUG -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -static int napi_weight = NAPI_POLL_WEIGHT; -module_param(napi_weight, int, 0444); - -static bool csum = true, gso = true; -module_param(csum, bool, 0444); -module_param(gso, bool, 0444); - -/* FIXME: MTU in config. */ -#define GOOD_PACKET_LEN (ETH_HLEN + VLAN_HLEN + ETH_DATA_LEN) -#define GOOD_COPY_LEN 128 - -/* RX packet size EWMA. The average packet size is used to determine the packet - * buffer size when refilling RX rings. As the entire RX ring may be refilled - * at once, the weight is chosen so that the EWMA will be insensitive to short- - * term, transient changes in packet size. - */ -DECLARE_EWMA(pkt_len, 1, 64) - -/* With mergeable buffers we align buffer address and use the low bits to - * encode its true size. Buffer size is up to 1 page so we need to align to - * square root of page size to ensure we reserve enough bits to encode the true - * size. - */ -#define MERGEABLE_BUFFER_MIN_ALIGN_SHIFT ((PAGE_SHIFT + 1) / 2) - -/* Minimum alignment for mergeable packet buffers. */ -#define MERGEABLE_BUFFER_ALIGN max(L1_CACHE_BYTES, \ - 1 << MERGEABLE_BUFFER_MIN_ALIGN_SHIFT) - -#define VIRTNET_DRIVER_VERSION "1.0.0" - -struct virtnet_stats { - struct u64_stats_sync tx_syncp; - struct u64_stats_sync rx_syncp; - u64 tx_bytes; - u64 tx_packets; - - u64 rx_bytes; - u64 rx_packets; -}; - -/* Internal representation of a send virtqueue */ -struct send_queue { - /* Virtqueue associated with this send _queue */ - struct virtqueue *vq; - - /* TX: fragments + linear part + virtio header */ - struct scatterlist sg[MAX_SKB_FRAGS + 2]; - - /* Name of the send queue: output.$index */ - char name[40]; -}; - -/* Internal representation of a receive virtqueue */ -struct receive_queue { - /* Virtqueue associated with this receive_queue */ - struct virtqueue *vq; - - struct napi_struct napi; - - /* Chain pages by the private ptr. */ - struct page *pages; - - /* Average packet length for mergeable receive buffers. */ - struct ewma_pkt_len mrg_avg_pkt_len; - - /* Page frag for packet buffer allocation. */ - struct page_frag alloc_frag; - - /* RX: fragments + linear part + virtio header */ - struct scatterlist sg[MAX_SKB_FRAGS + 2]; - - /* Name of this receive queue: input.$index */ - char name[40]; -}; - -struct virtnet_info { - struct virtio_device *vdev; - struct virtqueue *cvq; - struct net_device *dev; - struct send_queue *sq; - struct receive_queue *rq; - unsigned int status; - - /* Max # of queue pairs supported by the device */ - u16 max_queue_pairs; - - /* # of queue pairs currently used by the driver */ - u16 curr_queue_pairs; - - /* I like... big packets and I cannot lie! */ - bool big_packets; - - /* Host will merge rx buffers for big packets (shake it! shake it!) */ - bool mergeable_rx_bufs; - - /* Has control virtqueue */ - bool has_cvq; - - /* Host can handle any s/g split between our header and packet data */ - bool any_header_sg; - - /* Packet virtio header size */ - u8 hdr_len; - - /* Active statistics */ - struct virtnet_stats __percpu *stats; - - /* Work struct for refilling if we run low on memory. */ - struct delayed_work refill; - - /* Work struct for config space updates */ - struct work_struct config_work; - - /* Does the affinity hint is set for virtqueues? */ - bool affinity_hint_set; - - /* CPU hot plug notifier */ - struct notifier_block nb; - - /* Control VQ buffers: protected by the rtnl lock */ - struct virtio_net_ctrl_hdr ctrl_hdr; - virtio_net_ctrl_ack ctrl_status; - u8 ctrl_promisc; - u8 ctrl_allmulti; -}; - -struct padded_vnet_hdr { - struct virtio_net_hdr_mrg_rxbuf hdr; - /* - * hdr is in a separate sg buffer, and data sg buffer shares same page - * with this header sg. This padding makes next sg 16 byte aligned - * after the header. - */ - char padding[4]; -}; - -/* Converting between virtqueue no. and kernel tx/rx queue no. - * 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq - */ -static int vq2txq(struct virtqueue *vq) -{ - return (vq->index - 1) / 2; -} - -static int txq2vq(int txq) -{ - return txq * 2 + 1; -} - -static int vq2rxq(struct virtqueue *vq) -{ - return vq->index / 2; -} - -static int rxq2vq(int rxq) -{ - return rxq * 2; -} - -static inline struct virtio_net_hdr_mrg_rxbuf *skb_vnet_hdr(struct sk_buff *skb) -{ - return (struct virtio_net_hdr_mrg_rxbuf *)skb->cb; -} - -/* - * private is used to chain pages for big packets, put the whole - * most recent used list in the beginning for reuse - */ -static void give_pages(struct receive_queue *rq, struct page *page) -{ - struct page *end; - - /* Find end of list, sew whole thing into vi->rq.pages. */ - for (end = page; end->private; end = (struct page *)end->private); - end->private = (unsigned long)rq->pages; - rq->pages = page; -} - -static struct page *get_a_page(struct receive_queue *rq, gfp_t gfp_mask) -{ - struct page *p = rq->pages; - - if (p) { - rq->pages = (struct page *)p->private; - /* clear private here, it is used to chain pages */ - p->private = 0; - } else - p = alloc_page(gfp_mask); - return p; -} - -static void skb_xmit_done(struct virtqueue *vq) -{ - struct virtnet_info *vi = vq->vdev->priv; - - /* Suppress further interrupts. */ - virtqueue_disable_cb(vq); - - /* We were probably waiting for more output buffers. */ - netif_wake_subqueue(vi->dev, vq2txq(vq)); -} - -static unsigned int mergeable_ctx_to_buf_truesize(unsigned long mrg_ctx) -{ - unsigned int truesize = mrg_ctx & (MERGEABLE_BUFFER_ALIGN - 1); - return (truesize + 1) * MERGEABLE_BUFFER_ALIGN; -} - -static void *mergeable_ctx_to_buf_address(unsigned long mrg_ctx) -{ - return (void *)(mrg_ctx & -MERGEABLE_BUFFER_ALIGN); - -} - -static unsigned long mergeable_buf_to_ctx(void *buf, unsigned int truesize) -{ - unsigned int size = truesize / MERGEABLE_BUFFER_ALIGN; - return (unsigned long)buf | (size - 1); -} - -/* Called from bottom half context */ -static struct sk_buff *page_to_skb(struct virtnet_info *vi, - struct receive_queue *rq, - struct page *page, unsigned int offset, - unsigned int len, unsigned int truesize) -{ - struct sk_buff *skb; - struct virtio_net_hdr_mrg_rxbuf *hdr; - unsigned int copy, hdr_len, hdr_padded_len; - char *p; - - p = page_address(page) + offset; - - /* copy small packet so we can reuse these pages for small data */ - skb = netdev_alloc_skb_ip_align(vi->dev, GOOD_COPY_LEN); - if (unlikely(!skb)) - return NULL; - - hdr = skb_vnet_hdr(skb); - - hdr_len = vi->hdr_len; - if (vi->mergeable_rx_bufs) - hdr_padded_len = sizeof *hdr; - else - hdr_padded_len = sizeof(struct padded_vnet_hdr); - - memcpy(hdr, p, hdr_len); - - len -= hdr_len; - offset += hdr_padded_len; - p += hdr_padded_len; - - copy = len; - if (copy > skb_tailroom(skb)) - copy = skb_tailroom(skb); - memcpy(skb_put(skb, copy), p, copy); - - len -= copy; - offset += copy; - - if (vi->mergeable_rx_bufs) { - if (len) - skb_add_rx_frag(skb, 0, page, offset, len, truesize); - else - put_page(page); - return skb; - } - - /* - * Verify that we can indeed put this data into a skb. - * This is here to handle cases when the device erroneously - * tries to receive more than is possible. This is usually - * the case of a broken device. - */ - if (unlikely(len > MAX_SKB_FRAGS * PAGE_SIZE)) { - net_dbg_ratelimited("%s: too much data\n", skb->dev->name); - dev_kfree_skb(skb); - return NULL; - } - BUG_ON(offset >= PAGE_SIZE); - while (len) { - unsigned int frag_size = min((unsigned)PAGE_SIZE - offset, len); - skb_add_rx_frag(skb, skb_shinfo(skb)->nr_frags, page, offset, - frag_size, truesize); - len -= frag_size; - page = (struct page *)page->private; - offset = 0; - } - - if (page) - give_pages(rq, page); - - return skb; -} - -static struct sk_buff *receive_small(struct virtnet_info *vi, void *buf, unsigned int len) -{ - struct sk_buff * skb = buf; - - len -= vi->hdr_len; - skb_trim(skb, len); - - return skb; -} - -static struct sk_buff *receive_big(struct net_device *dev, - struct virtnet_info *vi, - struct receive_queue *rq, - void *buf, - unsigned int len) -{ - struct page *page = buf; - struct sk_buff *skb = page_to_skb(vi, rq, page, 0, len, PAGE_SIZE); - - if (unlikely(!skb)) - goto err; - - return skb; - -err: - dev->stats.rx_dropped++; - give_pages(rq, page); - return NULL; -} - -static struct sk_buff *receive_mergeable(struct net_device *dev, - struct virtnet_info *vi, - struct receive_queue *rq, - unsigned long ctx, - unsigned int len) -{ - void *buf = mergeable_ctx_to_buf_address(ctx); - struct virtio_net_hdr_mrg_rxbuf *hdr = buf; - u16 num_buf = virtio16_to_cpu(vi->vdev, hdr->num_buffers); - struct page *page = virt_to_head_page(buf); - int offset = buf - page_address(page); - unsigned int truesize = max(len, mergeable_ctx_to_buf_truesize(ctx)); - - struct sk_buff *head_skb = page_to_skb(vi, rq, page, offset, len, - truesize); - struct sk_buff *curr_skb = head_skb; - - if (unlikely(!curr_skb)) - goto err_skb; - while (--num_buf) { - int num_skb_frags; - - ctx = (unsigned long)virtqueue_get_buf(rq->vq, &len); - if (unlikely(!ctx)) { - pr_debug("%s: rx error: %d buffers out of %d missing\n", - dev->name, num_buf, - virtio16_to_cpu(vi->vdev, - hdr->num_buffers)); - dev->stats.rx_length_errors++; - goto err_buf; - } - - buf = mergeable_ctx_to_buf_address(ctx); - page = virt_to_head_page(buf); - - num_skb_frags = skb_shinfo(curr_skb)->nr_frags; - if (unlikely(num_skb_frags == MAX_SKB_FRAGS)) { - struct sk_buff *nskb = alloc_skb(0, GFP_ATOMIC); - - if (unlikely(!nskb)) - goto err_skb; - if (curr_skb == head_skb) - skb_shinfo(curr_skb)->frag_list = nskb; - else - curr_skb->next = nskb; - curr_skb = nskb; - head_skb->truesize += nskb->truesize; - num_skb_frags = 0; - } - truesize = max(len, mergeable_ctx_to_buf_truesize(ctx)); - if (curr_skb != head_skb) { - head_skb->data_len += len; - head_skb->len += len; - head_skb->truesize += truesize; - } - offset = buf - page_address(page); - if (skb_can_coalesce(curr_skb, num_skb_frags, page, offset)) { - put_page(page); - skb_coalesce_rx_frag(curr_skb, num_skb_frags - 1, - len, truesize); - } else { - skb_add_rx_frag(curr_skb, num_skb_frags, page, - offset, len, truesize); - } - } - - ewma_pkt_len_add(&rq->mrg_avg_pkt_len, head_skb->len); - return head_skb; - -err_skb: - put_page(page); - while (--num_buf) { - ctx = (unsigned long)virtqueue_get_buf(rq->vq, &len); - if (unlikely(!ctx)) { - pr_debug("%s: rx error: %d buffers missing\n", - dev->name, num_buf); - dev->stats.rx_length_errors++; - break; - } - page = virt_to_head_page(mergeable_ctx_to_buf_address(ctx)); - put_page(page); - } -err_buf: - dev->stats.rx_dropped++; - dev_kfree_skb(head_skb); - return NULL; -} - -static void receive_buf(struct virtnet_info *vi, struct receive_queue *rq, - void *buf, unsigned int len) -{ - struct net_device *dev = vi->dev; - struct virtnet_stats *stats = this_cpu_ptr(vi->stats); - struct sk_buff *skb; - struct virtio_net_hdr_mrg_rxbuf *hdr; - - if (unlikely(len < vi->hdr_len + ETH_HLEN)) { - pr_debug("%s: short packet %i\n", dev->name, len); - dev->stats.rx_length_errors++; - if (vi->mergeable_rx_bufs) { - unsigned long ctx = (unsigned long)buf; - void *base = mergeable_ctx_to_buf_address(ctx); - put_page(virt_to_head_page(base)); - } else if (vi->big_packets) { - give_pages(rq, buf); - } else { - dev_kfree_skb(buf); - } - return; - } - - if (vi->mergeable_rx_bufs) - skb = receive_mergeable(dev, vi, rq, (unsigned long)buf, len); - else if (vi->big_packets) - skb = receive_big(dev, vi, rq, buf, len); - else - skb = receive_small(vi, buf, len); - - if (unlikely(!skb)) - return; - - hdr = skb_vnet_hdr(skb); - - u64_stats_update_begin(&stats->rx_syncp); - stats->rx_bytes += skb->len; - stats->rx_packets++; - u64_stats_update_end(&stats->rx_syncp); - - if (hdr->hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { - pr_debug("Needs csum!\n"); - if (!skb_partial_csum_set(skb, - virtio16_to_cpu(vi->vdev, hdr->hdr.csum_start), - virtio16_to_cpu(vi->vdev, hdr->hdr.csum_offset))) - goto frame_err; - } else if (hdr->hdr.flags & VIRTIO_NET_HDR_F_DATA_VALID) { - skb->ip_summed = CHECKSUM_UNNECESSARY; - } - - skb->protocol = eth_type_trans(skb, dev); - pr_debug("Receiving skb proto 0x%04x len %i type %i\n", - ntohs(skb->protocol), skb->len, skb->pkt_type); - - if (hdr->hdr.gso_type != VIRTIO_NET_HDR_GSO_NONE) { - pr_debug("GSO!\n"); - switch (hdr->hdr.gso_type & ~VIRTIO_NET_HDR_GSO_ECN) { - case VIRTIO_NET_HDR_GSO_TCPV4: - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; - break; - case VIRTIO_NET_HDR_GSO_UDP: - skb_shinfo(skb)->gso_type = SKB_GSO_UDP; - break; - case VIRTIO_NET_HDR_GSO_TCPV6: - skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; - break; - default: - net_warn_ratelimited("%s: bad gso type %u.\n", - dev->name, hdr->hdr.gso_type); - goto frame_err; - } - - if (hdr->hdr.gso_type & VIRTIO_NET_HDR_GSO_ECN) - skb_shinfo(skb)->gso_type |= SKB_GSO_TCP_ECN; - - skb_shinfo(skb)->gso_size = virtio16_to_cpu(vi->vdev, - hdr->hdr.gso_size); - if (skb_shinfo(skb)->gso_size == 0) { - net_warn_ratelimited("%s: zero gso size.\n", dev->name); - goto frame_err; - } - - /* Header must be checked, and gso_segs computed. */ - skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY; - skb_shinfo(skb)->gso_segs = 0; - } - - skb_mark_napi_id(skb, &rq->napi); - - napi_gro_receive(&rq->napi, skb); - return; - -frame_err: - dev->stats.rx_frame_errors++; - dev_kfree_skb(skb); -} - -static int add_recvbuf_small(struct virtnet_info *vi, struct receive_queue *rq, - gfp_t gfp) -{ - struct sk_buff *skb; - struct virtio_net_hdr_mrg_rxbuf *hdr; - int err; - - skb = __netdev_alloc_skb_ip_align(vi->dev, GOOD_PACKET_LEN, gfp); - if (unlikely(!skb)) - return -ENOMEM; - - skb_put(skb, GOOD_PACKET_LEN); - - hdr = skb_vnet_hdr(skb); - sg_init_table(rq->sg, 2); - sg_set_buf(rq->sg, hdr, vi->hdr_len); - - err = skb_to_sgvec(skb, rq->sg + 1, 0, skb->len); - if (unlikely(err < 0)) { - dev_kfree_skb(skb); - return err; - } - - err = virtqueue_add_inbuf(rq->vq, rq->sg, 2, skb, gfp); - if (err < 0) - dev_kfree_skb(skb); - - return err; -} - -static int add_recvbuf_big(struct virtnet_info *vi, struct receive_queue *rq, - gfp_t gfp) -{ - struct page *first, *list = NULL; - char *p; - int i, err, offset; - - sg_init_table(rq->sg, MAX_SKB_FRAGS + 2); - - /* page in rq->sg[MAX_SKB_FRAGS + 1] is list tail */ - for (i = MAX_SKB_FRAGS + 1; i > 1; --i) { - first = get_a_page(rq, gfp); - if (!first) { - if (list) - give_pages(rq, list); - return -ENOMEM; - } - sg_set_buf(&rq->sg[i], page_address(first), PAGE_SIZE); - - /* chain new page in list head to match sg */ - first->private = (unsigned long)list; - list = first; - } - - first = get_a_page(rq, gfp); - if (!first) { - give_pages(rq, list); - return -ENOMEM; - } - p = page_address(first); - - /* rq->sg[0], rq->sg[1] share the same page */ - /* a separated rq->sg[0] for header - required in case !any_header_sg */ - sg_set_buf(&rq->sg[0], p, vi->hdr_len); - - /* rq->sg[1] for data packet, from offset */ - offset = sizeof(struct padded_vnet_hdr); - sg_set_buf(&rq->sg[1], p + offset, PAGE_SIZE - offset); - - /* chain first in list head */ - first->private = (unsigned long)list; - err = virtqueue_add_inbuf(rq->vq, rq->sg, MAX_SKB_FRAGS + 2, - first, gfp); - if (err < 0) - give_pages(rq, first); - - return err; -} - -static unsigned int get_mergeable_buf_len(struct ewma_pkt_len *avg_pkt_len) -{ - const size_t hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); - unsigned int len; - - len = hdr_len + clamp_t(unsigned int, ewma_pkt_len_read(avg_pkt_len), - GOOD_PACKET_LEN, PAGE_SIZE - hdr_len); - return ALIGN(len, MERGEABLE_BUFFER_ALIGN); -} - -static int add_recvbuf_mergeable(struct receive_queue *rq, gfp_t gfp) -{ - struct page_frag *alloc_frag = &rq->alloc_frag; - char *buf; - unsigned long ctx; - int err; - unsigned int len, hole; - - len = get_mergeable_buf_len(&rq->mrg_avg_pkt_len); - if (unlikely(!skb_page_frag_refill(len, alloc_frag, gfp))) - return -ENOMEM; - - buf = (char *)page_address(alloc_frag->page) + alloc_frag->offset; - ctx = mergeable_buf_to_ctx(buf, len); - get_page(alloc_frag->page); - alloc_frag->offset += len; - hole = alloc_frag->size - alloc_frag->offset; - if (hole < len) { - /* To avoid internal fragmentation, if there is very likely not - * enough space for another buffer, add the remaining space to - * the current buffer. This extra space is not included in - * the truesize stored in ctx. - */ - len += hole; - alloc_frag->offset += hole; - } - - sg_init_one(rq->sg, buf, len); - err = virtqueue_add_inbuf(rq->vq, rq->sg, 1, (void *)ctx, gfp); - if (err < 0) - put_page(virt_to_head_page(buf)); - - return err; -} - -/* - * Returns false if we couldn't fill entirely (OOM). - * - * Normally run in the receive path, but can also be run from ndo_open - * before we're receiving packets, or from refill_work which is - * careful to disable receiving (using napi_disable). - */ -static bool try_fill_recv(struct virtnet_info *vi, struct receive_queue *rq, - gfp_t gfp) -{ - int err; - bool oom; - - gfp |= __GFP_COLD; - do { - if (vi->mergeable_rx_bufs) - err = add_recvbuf_mergeable(rq, gfp); - else if (vi->big_packets) - err = add_recvbuf_big(vi, rq, gfp); - else - err = add_recvbuf_small(vi, rq, gfp); - - oom = err == -ENOMEM; - if (err) - break; - } while (rq->vq->num_free); - virtqueue_kick(rq->vq); - return !oom; -} - -static void skb_recv_done(struct virtqueue *rvq) -{ - struct virtnet_info *vi = rvq->vdev->priv; - struct receive_queue *rq = &vi->rq[vq2rxq(rvq)]; - - /* Schedule NAPI, Suppress further interrupts if successful. */ - if (napi_schedule_prep(&rq->napi)) { - virtqueue_disable_cb(rvq); - __napi_schedule(&rq->napi); - } -} - -static void virtnet_napi_enable(struct receive_queue *rq) -{ - napi_enable(&rq->napi); - - /* If all buffers were filled by other side before we napi_enabled, we - * won't get another interrupt, so process any outstanding packets - * now. virtnet_poll wants re-enable the queue, so we disable here. - * We synchronize against interrupts via NAPI_STATE_SCHED */ - if (napi_schedule_prep(&rq->napi)) { - virtqueue_disable_cb(rq->vq); - local_bh_disable(); - __napi_schedule(&rq->napi); - local_bh_enable(); - } -} - -static void refill_work(struct work_struct *work) -{ - struct virtnet_info *vi = - container_of(work, struct virtnet_info, refill.work); - bool still_empty; - int i; - - for (i = 0; i < vi->curr_queue_pairs; i++) { - struct receive_queue *rq = &vi->rq[i]; - - napi_disable(&rq->napi); - still_empty = !try_fill_recv(vi, rq, GFP_KERNEL); - virtnet_napi_enable(rq); - - /* In theory, this can happen: if we don't get any buffers in - * we will *never* try to fill again. - */ - if (still_empty) - schedule_delayed_work(&vi->refill, HZ/2); - } -} - -static int virtnet_receive(struct receive_queue *rq, int budget) -{ - struct virtnet_info *vi = rq->vq->vdev->priv; - unsigned int len, received = 0; - void *buf; - - while (received < budget && - (buf = virtqueue_get_buf(rq->vq, &len)) != NULL) { - receive_buf(vi, rq, buf, len); - received++; - } - - if (rq->vq->num_free > virtqueue_get_vring_size(rq->vq) / 2) { - if (!try_fill_recv(vi, rq, GFP_ATOMIC)) - schedule_delayed_work(&vi->refill, 0); - } - - return received; -} - -static int virtnet_poll(struct napi_struct *napi, int budget) -{ - struct receive_queue *rq = - container_of(napi, struct receive_queue, napi); - unsigned int r, received; - - received = virtnet_receive(rq, budget); - - /* Out of packets? */ - if (received < budget) { - r = virtqueue_enable_cb_prepare(rq->vq); - napi_complete_done(napi, received); - if (unlikely(virtqueue_poll(rq->vq, r)) && - napi_schedule_prep(napi)) { - virtqueue_disable_cb(rq->vq); - __napi_schedule(napi); - } - } - - return received; -} - -#ifdef CONFIG_NET_RX_BUSY_POLL -/* must be called with local_bh_disable()d */ -static int virtnet_busy_poll(struct napi_struct *napi) -{ - struct receive_queue *rq = - container_of(napi, struct receive_queue, napi); - struct virtnet_info *vi = rq->vq->vdev->priv; - int r, received = 0, budget = 4; - - if (!(vi->status & VIRTIO_NET_S_LINK_UP)) - return LL_FLUSH_FAILED; - - if (!napi_schedule_prep(napi)) - return LL_FLUSH_BUSY; - - virtqueue_disable_cb(rq->vq); - -again: - received += virtnet_receive(rq, budget); - - r = virtqueue_enable_cb_prepare(rq->vq); - clear_bit(NAPI_STATE_SCHED, &napi->state); - if (unlikely(virtqueue_poll(rq->vq, r)) && - napi_schedule_prep(napi)) { - virtqueue_disable_cb(rq->vq); - if (received < budget) { - budget -= received; - goto again; - } else { - __napi_schedule(napi); - } - } - - return received; -} -#endif /* CONFIG_NET_RX_BUSY_POLL */ - -static int virtnet_open(struct net_device *dev) -{ - struct virtnet_info *vi = netdev_priv(dev); - int i; - - for (i = 0; i < vi->max_queue_pairs; i++) { - if (i < vi->curr_queue_pairs) - /* Make sure we have some buffers: if oom use wq. */ - if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL)) - schedule_delayed_work(&vi->refill, 0); - virtnet_napi_enable(&vi->rq[i]); - } - - return 0; -} - -static void free_old_xmit_skbs(struct send_queue *sq) -{ - struct sk_buff *skb; - unsigned int len; - struct virtnet_info *vi = sq->vq->vdev->priv; - struct virtnet_stats *stats = this_cpu_ptr(vi->stats); - - while ((skb = virtqueue_get_buf(sq->vq, &len)) != NULL) { - pr_debug("Sent skb %p\n", skb); - - u64_stats_update_begin(&stats->tx_syncp); - stats->tx_bytes += skb->len; - stats->tx_packets++; - u64_stats_update_end(&stats->tx_syncp); - - dev_kfree_skb_any(skb); - } -} - -static int xmit_skb(struct send_queue *sq, struct sk_buff *skb) -{ - struct virtio_net_hdr_mrg_rxbuf *hdr; - const unsigned char *dest = ((struct ethhdr *)skb->data)->h_dest; - struct virtnet_info *vi = sq->vq->vdev->priv; - int num_sg; - unsigned hdr_len = vi->hdr_len; - bool can_push; - - pr_debug("%s: xmit %p %pM\n", vi->dev->name, skb, dest); - - can_push = vi->any_header_sg && - !((unsigned long)skb->data & (__alignof__(*hdr) - 1)) && - !skb_header_cloned(skb) && skb_headroom(skb) >= hdr_len; - /* Even if we can, don't push here yet as this would skew - * csum_start offset below. */ - if (can_push) - hdr = (struct virtio_net_hdr_mrg_rxbuf *)(skb->data - hdr_len); - else - hdr = skb_vnet_hdr(skb); - - if (skb->ip_summed == CHECKSUM_PARTIAL) { - hdr->hdr.flags = VIRTIO_NET_HDR_F_NEEDS_CSUM; - hdr->hdr.csum_start = cpu_to_virtio16(vi->vdev, - skb_checksum_start_offset(skb)); - hdr->hdr.csum_offset = cpu_to_virtio16(vi->vdev, - skb->csum_offset); - } else { - hdr->hdr.flags = 0; - hdr->hdr.csum_offset = hdr->hdr.csum_start = 0; - } - - if (skb_is_gso(skb)) { - hdr->hdr.hdr_len = cpu_to_virtio16(vi->vdev, skb_headlen(skb)); - hdr->hdr.gso_size = cpu_to_virtio16(vi->vdev, - skb_shinfo(skb)->gso_size); - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV4) - hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV4; - else if (skb_shinfo(skb)->gso_type & SKB_GSO_TCPV6) - hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_TCPV6; - else if (skb_shinfo(skb)->gso_type & SKB_GSO_UDP) - hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_UDP; - else - BUG(); - if (skb_shinfo(skb)->gso_type & SKB_GSO_TCP_ECN) - hdr->hdr.gso_type |= VIRTIO_NET_HDR_GSO_ECN; - } else { - hdr->hdr.gso_type = VIRTIO_NET_HDR_GSO_NONE; - hdr->hdr.gso_size = hdr->hdr.hdr_len = 0; - } - - if (vi->mergeable_rx_bufs) - hdr->num_buffers = 0; - - sg_init_table(sq->sg, skb_shinfo(skb)->nr_frags + (can_push ? 1 : 2)); - if (can_push) { - __skb_push(skb, hdr_len); - num_sg = skb_to_sgvec(skb, sq->sg, 0, skb->len); - if (unlikely(num_sg < 0)) - return num_sg; - /* Pull header back to avoid skew in tx bytes calculations. */ - __skb_pull(skb, hdr_len); - } else { - sg_set_buf(sq->sg, hdr, hdr_len); - num_sg = skb_to_sgvec(skb, sq->sg + 1, 0, skb->len); - if (unlikely(num_sg < 0)) - return num_sg; - num_sg++; - } - return virtqueue_add_outbuf(sq->vq, sq->sg, num_sg, skb, GFP_ATOMIC); -} - -static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct virtnet_info *vi = netdev_priv(dev); - int qnum = skb_get_queue_mapping(skb); - struct send_queue *sq = &vi->sq[qnum]; - int err; - struct netdev_queue *txq = netdev_get_tx_queue(dev, qnum); - bool kick = !skb->xmit_more; - - /* Free up any pending old buffers before queueing new ones. */ - free_old_xmit_skbs(sq); - - /* timestamp packet in software */ - skb_tx_timestamp(skb); - - /* Try to transmit */ - err = xmit_skb(sq, skb); - - /* This should not happen! */ - if (unlikely(err)) { - dev->stats.tx_fifo_errors++; - if (net_ratelimit()) - dev_warn(&dev->dev, - "Unexpected TXQ (%d) queue failure: %d\n", qnum, err); - dev->stats.tx_dropped++; - dev_kfree_skb_any(skb); - return NETDEV_TX_OK; - } - - /* Don't wait up for transmitted skbs to be freed. */ - skb_orphan(skb); - nf_reset(skb); - - /* If running out of space, stop queue to avoid getting packets that we - * are then unable to transmit. - * An alternative would be to force queuing layer to requeue the skb by - * returning NETDEV_TX_BUSY. However, NETDEV_TX_BUSY should not be - * returned in a normal path of operation: it means that driver is not - * maintaining the TX queue stop/start state properly, and causes - * the stack to do a non-trivial amount of useless work. - * Since most packets only take 1 or 2 ring slots, stopping the queue - * early means 16 slots are typically wasted. - */ - if (sq->vq->num_free < 2+MAX_SKB_FRAGS) { - netif_stop_subqueue(dev, qnum); - if (unlikely(!virtqueue_enable_cb_delayed(sq->vq))) { - /* More just got used, free them then recheck. */ - free_old_xmit_skbs(sq); - if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) { - netif_start_subqueue(dev, qnum); - virtqueue_disable_cb(sq->vq); - } - } - } - - if (kick || netif_xmit_stopped(txq)) - virtqueue_kick(sq->vq); - - return NETDEV_TX_OK; -} - -/* - * Send command via the control virtqueue and check status. Commands - * supported by the hypervisor, as indicated by feature bits, should - * never fail unless improperly formatted. - */ -static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, - struct scatterlist *out) -{ - struct scatterlist *sgs[4], hdr, stat; - unsigned out_num = 0, tmp; - - /* Caller should know better */ - BUG_ON(!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ)); - - vi->ctrl_status = ~0; - vi->ctrl_hdr.class = class; - vi->ctrl_hdr.cmd = cmd; - /* Add header */ - sg_init_one(&hdr, &vi->ctrl_hdr, sizeof(vi->ctrl_hdr)); - sgs[out_num++] = &hdr; - - if (out) - sgs[out_num++] = out; - - /* Add return status. */ - sg_init_one(&stat, &vi->ctrl_status, sizeof(vi->ctrl_status)); - sgs[out_num] = &stat; - - BUG_ON(out_num + 1 > ARRAY_SIZE(sgs)); - virtqueue_add_sgs(vi->cvq, sgs, out_num, 1, vi, GFP_ATOMIC); - - if (unlikely(!virtqueue_kick(vi->cvq))) - return vi->ctrl_status == VIRTIO_NET_OK; - - /* Spin for a response, the kick causes an ioport write, trapping - * into the hypervisor, so the request should be handled immediately. - */ - while (!virtqueue_get_buf(vi->cvq, &tmp) && - !virtqueue_is_broken(vi->cvq)) - cpu_relax(); - - return vi->ctrl_status == VIRTIO_NET_OK; -} - -static int virtnet_set_mac_address(struct net_device *dev, void *p) -{ - struct virtnet_info *vi = netdev_priv(dev); - struct virtio_device *vdev = vi->vdev; - int ret; - struct sockaddr *addr = p; - struct scatterlist sg; - - ret = eth_prepare_mac_addr_change(dev, p); - if (ret) - return ret; - - if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR)) { - sg_init_one(&sg, addr->sa_data, dev->addr_len); - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC, - VIRTIO_NET_CTRL_MAC_ADDR_SET, &sg)) { - dev_warn(&vdev->dev, - "Failed to set mac address by vq command.\n"); - return -EINVAL; - } - } else if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC) && - !virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) { - unsigned int i; - - /* Naturally, this has an atomicity problem. */ - for (i = 0; i < dev->addr_len; i++) - virtio_cwrite8(vdev, - offsetof(struct virtio_net_config, mac) + - i, addr->sa_data[i]); - } - - eth_commit_mac_addr_change(dev, p); - - return 0; -} - -static struct rtnl_link_stats64 *virtnet_stats(struct net_device *dev, - struct rtnl_link_stats64 *tot) -{ - struct virtnet_info *vi = netdev_priv(dev); - int cpu; - unsigned int start; - - for_each_possible_cpu(cpu) { - struct virtnet_stats *stats = per_cpu_ptr(vi->stats, cpu); - u64 tpackets, tbytes, rpackets, rbytes; - - do { - start = u64_stats_fetch_begin_irq(&stats->tx_syncp); - tpackets = stats->tx_packets; - tbytes = stats->tx_bytes; - } while (u64_stats_fetch_retry_irq(&stats->tx_syncp, start)); - - do { - start = u64_stats_fetch_begin_irq(&stats->rx_syncp); - rpackets = stats->rx_packets; - rbytes = stats->rx_bytes; - } while (u64_stats_fetch_retry_irq(&stats->rx_syncp, start)); - - tot->rx_packets += rpackets; - tot->tx_packets += tpackets; - tot->rx_bytes += rbytes; - tot->tx_bytes += tbytes; - } - - tot->tx_dropped = dev->stats.tx_dropped; - tot->tx_fifo_errors = dev->stats.tx_fifo_errors; - tot->rx_dropped = dev->stats.rx_dropped; - tot->rx_length_errors = dev->stats.rx_length_errors; - tot->rx_frame_errors = dev->stats.rx_frame_errors; - - return tot; -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -static void virtnet_netpoll(struct net_device *dev) -{ - struct virtnet_info *vi = netdev_priv(dev); - int i; - - for (i = 0; i < vi->curr_queue_pairs; i++) - napi_schedule(&vi->rq[i].napi); -} -#endif - -static void virtnet_ack_link_announce(struct virtnet_info *vi) -{ - rtnl_lock(); - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_ANNOUNCE, - VIRTIO_NET_CTRL_ANNOUNCE_ACK, NULL)) - dev_warn(&vi->dev->dev, "Failed to ack link announce.\n"); - rtnl_unlock(); -} - -static int virtnet_set_queues(struct virtnet_info *vi, u16 queue_pairs) -{ - struct scatterlist sg; - struct virtio_net_ctrl_mq s; - struct net_device *dev = vi->dev; - - if (!vi->has_cvq || !virtio_has_feature(vi->vdev, VIRTIO_NET_F_MQ)) - return 0; - - s.virtqueue_pairs = cpu_to_virtio16(vi->vdev, queue_pairs); - sg_init_one(&sg, &s, sizeof(s)); - - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MQ, - VIRTIO_NET_CTRL_MQ_VQ_PAIRS_SET, &sg)) { - dev_warn(&dev->dev, "Fail to set num of queue pairs to %d\n", - queue_pairs); - return -EINVAL; - } else { - vi->curr_queue_pairs = queue_pairs; - /* virtnet_open() will refill when device is going to up. */ - if (dev->flags & IFF_UP) - schedule_delayed_work(&vi->refill, 0); - } - - return 0; -} - -static int virtnet_close(struct net_device *dev) -{ - struct virtnet_info *vi = netdev_priv(dev); - int i; - - /* Make sure refill_work doesn't re-enable napi! */ - cancel_delayed_work_sync(&vi->refill); - - for (i = 0; i < vi->max_queue_pairs; i++) - napi_disable(&vi->rq[i].napi); - - return 0; -} - -static void virtnet_set_rx_mode(struct net_device *dev) -{ - struct virtnet_info *vi = netdev_priv(dev); - struct scatterlist sg[2]; - struct virtio_net_ctrl_mac *mac_data; - struct netdev_hw_addr *ha; - int uc_count; - int mc_count; - void *buf; - int i; - - /* We can't dynamically set ndo_set_rx_mode, so return gracefully */ - if (!virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_RX)) - return; - - vi->ctrl_promisc = ((dev->flags & IFF_PROMISC) != 0); - vi->ctrl_allmulti = ((dev->flags & IFF_ALLMULTI) != 0); - - sg_init_one(sg, &vi->ctrl_promisc, sizeof(vi->ctrl_promisc)); - - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, - VIRTIO_NET_CTRL_RX_PROMISC, sg)) - dev_warn(&dev->dev, "Failed to %sable promisc mode.\n", - vi->ctrl_promisc ? "en" : "dis"); - - sg_init_one(sg, &vi->ctrl_allmulti, sizeof(vi->ctrl_allmulti)); - - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_RX, - VIRTIO_NET_CTRL_RX_ALLMULTI, sg)) - dev_warn(&dev->dev, "Failed to %sable allmulti mode.\n", - vi->ctrl_allmulti ? "en" : "dis"); - - uc_count = netdev_uc_count(dev); - mc_count = netdev_mc_count(dev); - /* MAC filter - use one buffer for both lists */ - buf = kzalloc(((uc_count + mc_count) * ETH_ALEN) + - (2 * sizeof(mac_data->entries)), GFP_ATOMIC); - mac_data = buf; - if (!buf) - return; - - sg_init_table(sg, 2); - - /* Store the unicast list and count in the front of the buffer */ - mac_data->entries = cpu_to_virtio32(vi->vdev, uc_count); - i = 0; - netdev_for_each_uc_addr(ha, dev) - memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); - - sg_set_buf(&sg[0], mac_data, - sizeof(mac_data->entries) + (uc_count * ETH_ALEN)); - - /* multicast list and count fill the end */ - mac_data = (void *)&mac_data->macs[uc_count][0]; - - mac_data->entries = cpu_to_virtio32(vi->vdev, mc_count); - i = 0; - netdev_for_each_mc_addr(ha, dev) - memcpy(&mac_data->macs[i++][0], ha->addr, ETH_ALEN); - - sg_set_buf(&sg[1], mac_data, - sizeof(mac_data->entries) + (mc_count * ETH_ALEN)); - - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_MAC, - VIRTIO_NET_CTRL_MAC_TABLE_SET, sg)) - dev_warn(&dev->dev, "Failed to set MAC filter table.\n"); - - kfree(buf); -} - -static int virtnet_vlan_rx_add_vid(struct net_device *dev, - __be16 proto, u16 vid) -{ - struct virtnet_info *vi = netdev_priv(dev); - struct scatterlist sg; - - sg_init_one(&sg, &vid, sizeof(vid)); - - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, - VIRTIO_NET_CTRL_VLAN_ADD, &sg)) - dev_warn(&dev->dev, "Failed to add VLAN ID %d.\n", vid); - return 0; -} - -static int virtnet_vlan_rx_kill_vid(struct net_device *dev, - __be16 proto, u16 vid) -{ - struct virtnet_info *vi = netdev_priv(dev); - struct scatterlist sg; - - sg_init_one(&sg, &vid, sizeof(vid)); - - if (!virtnet_send_command(vi, VIRTIO_NET_CTRL_VLAN, - VIRTIO_NET_CTRL_VLAN_DEL, &sg)) - dev_warn(&dev->dev, "Failed to kill VLAN ID %d.\n", vid); - return 0; -} - -static void virtnet_clean_affinity(struct virtnet_info *vi, long hcpu) -{ - int i; - - if (vi->affinity_hint_set) { - for (i = 0; i < vi->max_queue_pairs; i++) { - virtqueue_set_affinity(vi->rq[i].vq, -1); - virtqueue_set_affinity(vi->sq[i].vq, -1); - } - - vi->affinity_hint_set = false; - } -} - -static void virtnet_set_affinity(struct virtnet_info *vi) -{ - int i; - int cpu; - - /* In multiqueue mode, when the number of cpu is equal to the number of - * queue pairs, we let the queue pairs to be private to one cpu by - * setting the affinity hint to eliminate the contention. - */ - if (vi->curr_queue_pairs == 1 || - vi->max_queue_pairs != num_online_cpus()) { - virtnet_clean_affinity(vi, -1); - return; - } - - i = 0; - for_each_online_cpu(cpu) { - virtqueue_set_affinity(vi->rq[i].vq, cpu); - virtqueue_set_affinity(vi->sq[i].vq, cpu); - netif_set_xps_queue(vi->dev, cpumask_of(cpu), i); - i++; - } - - vi->affinity_hint_set = true; -} - -static int virtnet_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb); - - switch(action & ~CPU_TASKS_FROZEN) { - case CPU_ONLINE: - case CPU_DOWN_FAILED: - case CPU_DEAD: - virtnet_set_affinity(vi); - break; - case CPU_DOWN_PREPARE: - virtnet_clean_affinity(vi, (long)hcpu); - break; - default: - break; - } - - return NOTIFY_OK; -} - -static void virtnet_get_ringparam(struct net_device *dev, - struct ethtool_ringparam *ring) -{ - struct virtnet_info *vi = netdev_priv(dev); - - ring->rx_max_pending = virtqueue_get_vring_size(vi->rq[0].vq); - ring->tx_max_pending = virtqueue_get_vring_size(vi->sq[0].vq); - ring->rx_pending = ring->rx_max_pending; - ring->tx_pending = ring->tx_max_pending; -} - - -static void virtnet_get_drvinfo(struct net_device *dev, - struct ethtool_drvinfo *info) -{ - struct virtnet_info *vi = netdev_priv(dev); - struct virtio_device *vdev = vi->vdev; - - strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver)); - strlcpy(info->version, VIRTNET_DRIVER_VERSION, sizeof(info->version)); - strlcpy(info->bus_info, virtio_bus_name(vdev), sizeof(info->bus_info)); - -} - -/* TODO: Eliminate OOO packets during switching */ -static int virtnet_set_channels(struct net_device *dev, - struct ethtool_channels *channels) -{ - struct virtnet_info *vi = netdev_priv(dev); - u16 queue_pairs = channels->combined_count; - int err; - - /* We don't support separate rx/tx channels. - * We don't allow setting 'other' channels. - */ - if (channels->rx_count || channels->tx_count || channels->other_count) - return -EINVAL; - - if (queue_pairs > vi->max_queue_pairs || queue_pairs == 0) - return -EINVAL; - - get_online_cpus(); - err = virtnet_set_queues(vi, queue_pairs); - if (!err) { - netif_set_real_num_tx_queues(dev, queue_pairs); - netif_set_real_num_rx_queues(dev, queue_pairs); - - virtnet_set_affinity(vi); - } - put_online_cpus(); - - return err; -} - -static void virtnet_get_channels(struct net_device *dev, - struct ethtool_channels *channels) -{ - struct virtnet_info *vi = netdev_priv(dev); - - channels->combined_count = vi->curr_queue_pairs; - channels->max_combined = vi->max_queue_pairs; - channels->max_other = 0; - channels->rx_count = 0; - channels->tx_count = 0; - channels->other_count = 0; -} - -static const struct ethtool_ops virtnet_ethtool_ops = { - .get_drvinfo = virtnet_get_drvinfo, - .get_link = ethtool_op_get_link, - .get_ringparam = virtnet_get_ringparam, - .set_channels = virtnet_set_channels, - .get_channels = virtnet_get_channels, - .get_ts_info = ethtool_op_get_ts_info, -}; - -#define MIN_MTU 68 -#define MAX_MTU 65535 - -static int virtnet_change_mtu(struct net_device *dev, int new_mtu) -{ - if (new_mtu < MIN_MTU || new_mtu > MAX_MTU) - return -EINVAL; - dev->mtu = new_mtu; - return 0; -} - -static const struct net_device_ops virtnet_netdev = { - .ndo_open = virtnet_open, - .ndo_stop = virtnet_close, - .ndo_start_xmit = start_xmit, - .ndo_validate_addr = eth_validate_addr, - .ndo_set_mac_address = virtnet_set_mac_address, - .ndo_set_rx_mode = virtnet_set_rx_mode, - .ndo_change_mtu = virtnet_change_mtu, - .ndo_get_stats64 = virtnet_stats, - .ndo_vlan_rx_add_vid = virtnet_vlan_rx_add_vid, - .ndo_vlan_rx_kill_vid = virtnet_vlan_rx_kill_vid, -#ifdef CONFIG_NET_POLL_CONTROLLER - .ndo_poll_controller = virtnet_netpoll, -#endif -#ifdef CONFIG_NET_RX_BUSY_POLL - .ndo_busy_poll = virtnet_busy_poll, -#endif - .ndo_features_check = passthru_features_check, -}; - -static void virtnet_config_changed_work(struct work_struct *work) -{ - struct virtnet_info *vi = - container_of(work, struct virtnet_info, config_work); - u16 v; - - if (virtio_cread_feature(vi->vdev, VIRTIO_NET_F_STATUS, - struct virtio_net_config, status, &v) < 0) - return; - - if (v & VIRTIO_NET_S_ANNOUNCE) { - netdev_notify_peers(vi->dev); - virtnet_ack_link_announce(vi); - } - - /* Ignore unknown (future) status bits */ - v &= VIRTIO_NET_S_LINK_UP; - - if (vi->status == v) - return; - - vi->status = v; - - if (vi->status & VIRTIO_NET_S_LINK_UP) { - netif_carrier_on(vi->dev); - netif_tx_wake_all_queues(vi->dev); - } else { - netif_carrier_off(vi->dev); - netif_tx_stop_all_queues(vi->dev); - } -} - -static void virtnet_config_changed(struct virtio_device *vdev) -{ - struct virtnet_info *vi = vdev->priv; - - schedule_work(&vi->config_work); -} - -static void virtnet_free_queues(struct virtnet_info *vi) -{ - int i; - - for (i = 0; i < vi->max_queue_pairs; i++) { - napi_hash_del(&vi->rq[i].napi); - netif_napi_del(&vi->rq[i].napi); - } - - /* We called napi_hash_del() before netif_napi_del(), - * we need to respect an RCU grace period before freeing vi->rq - */ - synchronize_net(); - - kfree(vi->rq); - kfree(vi->sq); -} - -static void free_receive_bufs(struct virtnet_info *vi) -{ - int i; - - for (i = 0; i < vi->max_queue_pairs; i++) { - while (vi->rq[i].pages) - __free_pages(get_a_page(&vi->rq[i], GFP_KERNEL), 0); - } -} - -static void free_receive_page_frags(struct virtnet_info *vi) -{ - int i; - for (i = 0; i < vi->max_queue_pairs; i++) - if (vi->rq[i].alloc_frag.page) - put_page(vi->rq[i].alloc_frag.page); -} - -static void free_unused_bufs(struct virtnet_info *vi) -{ - void *buf; - int i; - - for (i = 0; i < vi->max_queue_pairs; i++) { - struct virtqueue *vq = vi->sq[i].vq; - while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) - dev_kfree_skb(buf); - } - - for (i = 0; i < vi->max_queue_pairs; i++) { - struct virtqueue *vq = vi->rq[i].vq; - - while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) { - if (vi->mergeable_rx_bufs) { - unsigned long ctx = (unsigned long)buf; - void *base = mergeable_ctx_to_buf_address(ctx); - put_page(virt_to_head_page(base)); - } else if (vi->big_packets) { - give_pages(&vi->rq[i], buf); - } else { - dev_kfree_skb(buf); - } - } - } -} - -static void virtnet_del_vqs(struct virtnet_info *vi) -{ - struct virtio_device *vdev = vi->vdev; - - virtnet_clean_affinity(vi, -1); - - vdev->config->del_vqs(vdev); - - virtnet_free_queues(vi); -} - -static int virtnet_find_vqs(struct virtnet_info *vi) -{ - vq_callback_t **callbacks; - struct virtqueue **vqs; - int ret = -ENOMEM; - int i, total_vqs; - const char **names; - - /* We expect 1 RX virtqueue followed by 1 TX virtqueue, followed by - * possible N-1 RX/TX queue pairs used in multiqueue mode, followed by - * possible control vq. - */ - total_vqs = vi->max_queue_pairs * 2 + - virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VQ); - - /* Allocate space for find_vqs parameters */ - vqs = kzalloc(total_vqs * sizeof(*vqs), GFP_KERNEL); - if (!vqs) - goto err_vq; - callbacks = kmalloc(total_vqs * sizeof(*callbacks), GFP_KERNEL); - if (!callbacks) - goto err_callback; - names = kmalloc(total_vqs * sizeof(*names), GFP_KERNEL); - if (!names) - goto err_names; - - /* Parameters for control virtqueue, if any */ - if (vi->has_cvq) { - callbacks[total_vqs - 1] = NULL; - names[total_vqs - 1] = "control"; - } - - /* Allocate/initialize parameters for send/receive virtqueues */ - for (i = 0; i < vi->max_queue_pairs; i++) { - callbacks[rxq2vq(i)] = skb_recv_done; - callbacks[txq2vq(i)] = skb_xmit_done; - sprintf(vi->rq[i].name, "input.%d", i); - sprintf(vi->sq[i].name, "output.%d", i); - names[rxq2vq(i)] = vi->rq[i].name; - names[txq2vq(i)] = vi->sq[i].name; - } - - ret = vi->vdev->config->find_vqs(vi->vdev, total_vqs, vqs, callbacks, - names); - if (ret) - goto err_find; - - if (vi->has_cvq) { - vi->cvq = vqs[total_vqs - 1]; - if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_CTRL_VLAN)) - vi->dev->features |= NETIF_F_HW_VLAN_CTAG_FILTER; - } - - for (i = 0; i < vi->max_queue_pairs; i++) { - vi->rq[i].vq = vqs[rxq2vq(i)]; - vi->sq[i].vq = vqs[txq2vq(i)]; - } - - kfree(names); - kfree(callbacks); - kfree(vqs); - - return 0; - -err_find: - kfree(names); -err_names: - kfree(callbacks); -err_callback: - kfree(vqs); -err_vq: - return ret; -} - -static int virtnet_alloc_queues(struct virtnet_info *vi) -{ - int i; - - vi->sq = kzalloc(sizeof(*vi->sq) * vi->max_queue_pairs, GFP_KERNEL); - if (!vi->sq) - goto err_sq; - vi->rq = kzalloc(sizeof(*vi->rq) * vi->max_queue_pairs, GFP_KERNEL); - if (!vi->rq) - goto err_rq; - - INIT_DELAYED_WORK(&vi->refill, refill_work); - for (i = 0; i < vi->max_queue_pairs; i++) { - vi->rq[i].pages = NULL; - netif_napi_add(vi->dev, &vi->rq[i].napi, virtnet_poll, - napi_weight); - napi_hash_add(&vi->rq[i].napi); - - sg_init_table(vi->rq[i].sg, ARRAY_SIZE(vi->rq[i].sg)); - ewma_pkt_len_init(&vi->rq[i].mrg_avg_pkt_len); - sg_init_table(vi->sq[i].sg, ARRAY_SIZE(vi->sq[i].sg)); - } - - return 0; - -err_rq: - kfree(vi->sq); -err_sq: - return -ENOMEM; -} - -static int init_vqs(struct virtnet_info *vi) -{ - int ret; - - /* Allocate send & receive queues */ - ret = virtnet_alloc_queues(vi); - if (ret) - goto err; - - ret = virtnet_find_vqs(vi); - if (ret) - goto err_free; - - get_online_cpus(); - virtnet_set_affinity(vi); - put_online_cpus(); - - return 0; - -err_free: - virtnet_free_queues(vi); -err: - return ret; -} - -#ifdef CONFIG_SYSFS -static ssize_t mergeable_rx_buffer_size_show(struct netdev_rx_queue *queue, - struct rx_queue_attribute *attribute, char *buf) -{ - struct virtnet_info *vi = netdev_priv(queue->dev); - unsigned int queue_index = get_netdev_rx_queue_index(queue); - struct ewma_pkt_len *avg; - - BUG_ON(queue_index >= vi->max_queue_pairs); - avg = &vi->rq[queue_index].mrg_avg_pkt_len; - return sprintf(buf, "%u\n", get_mergeable_buf_len(avg)); -} - -static struct rx_queue_attribute mergeable_rx_buffer_size_attribute = - __ATTR_RO(mergeable_rx_buffer_size); - -static struct attribute *virtio_net_mrg_rx_attrs[] = { - &mergeable_rx_buffer_size_attribute.attr, - NULL -}; - -static const struct attribute_group virtio_net_mrg_rx_group = { - .name = "virtio_net", - .attrs = virtio_net_mrg_rx_attrs -}; -#endif - -static bool virtnet_fail_on_feature(struct virtio_device *vdev, - unsigned int fbit, - const char *fname, const char *dname) -{ - if (!virtio_has_feature(vdev, fbit)) - return false; - - dev_err(&vdev->dev, "device advertises feature %s but not %s", - fname, dname); - - return true; -} - -#define VIRTNET_FAIL_ON(vdev, fbit, dbit) \ - virtnet_fail_on_feature(vdev, fbit, #fbit, dbit) - -static bool virtnet_validate_features(struct virtio_device *vdev) -{ - if (!virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ) && - (VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_RX, - "VIRTIO_NET_F_CTRL_VQ") || - VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_VLAN, - "VIRTIO_NET_F_CTRL_VQ") || - VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_GUEST_ANNOUNCE, - "VIRTIO_NET_F_CTRL_VQ") || - VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_MQ, "VIRTIO_NET_F_CTRL_VQ") || - VIRTNET_FAIL_ON(vdev, VIRTIO_NET_F_CTRL_MAC_ADDR, - "VIRTIO_NET_F_CTRL_VQ"))) { - return false; - } - - return true; -} - -static int virtnet_probe(struct virtio_device *vdev) -{ - int i, err; - struct net_device *dev; - struct virtnet_info *vi; - u16 max_queue_pairs; - - if (!vdev->config->get) { - dev_err(&vdev->dev, "%s failure: config access disabled\n", - __func__); - return -EINVAL; - } - - if (!virtnet_validate_features(vdev)) - return -EINVAL; - - /* Find if host supports multiqueue virtio_net device */ - err = virtio_cread_feature(vdev, VIRTIO_NET_F_MQ, - struct virtio_net_config, - max_virtqueue_pairs, &max_queue_pairs); - - /* We need at least 2 queue's */ - if (err || max_queue_pairs < VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN || - max_queue_pairs > VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX || - !virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) - max_queue_pairs = 1; - - /* Allocate ourselves a network device with room for our info */ - dev = alloc_etherdev_mq(sizeof(struct virtnet_info), max_queue_pairs); - if (!dev) - return -ENOMEM; - - /* Set up network device as normal. */ - dev->priv_flags |= IFF_UNICAST_FLT | IFF_LIVE_ADDR_CHANGE; - dev->netdev_ops = &virtnet_netdev; - dev->features = NETIF_F_HIGHDMA; - - dev->ethtool_ops = &virtnet_ethtool_ops; - SET_NETDEV_DEV(dev, &vdev->dev); - - /* Do we support "hardware" checksums? */ - if (virtio_has_feature(vdev, VIRTIO_NET_F_CSUM)) { - /* This opens up the world of extra features. */ - dev->hw_features |= NETIF_F_HW_CSUM | NETIF_F_SG; - if (csum) - dev->features |= NETIF_F_HW_CSUM | NETIF_F_SG; - - if (virtio_has_feature(vdev, VIRTIO_NET_F_GSO)) { - dev->hw_features |= NETIF_F_TSO | NETIF_F_UFO - | NETIF_F_TSO_ECN | NETIF_F_TSO6; - } - /* Individual feature bits: what can host handle? */ - if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO4)) - dev->hw_features |= NETIF_F_TSO; - if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_TSO6)) - dev->hw_features |= NETIF_F_TSO6; - if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_ECN)) - dev->hw_features |= NETIF_F_TSO_ECN; - if (virtio_has_feature(vdev, VIRTIO_NET_F_HOST_UFO)) - dev->hw_features |= NETIF_F_UFO; - - dev->features |= NETIF_F_GSO_ROBUST; - - if (gso) - dev->features |= dev->hw_features & (NETIF_F_ALL_TSO|NETIF_F_UFO); - /* (!csum && gso) case will be fixed by register_netdev() */ - } - if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_CSUM)) - dev->features |= NETIF_F_RXCSUM; - - dev->vlan_features = dev->features; - - /* Configuration may specify what MAC to use. Otherwise random. */ - if (virtio_has_feature(vdev, VIRTIO_NET_F_MAC)) - virtio_cread_bytes(vdev, - offsetof(struct virtio_net_config, mac), - dev->dev_addr, dev->addr_len); - else - eth_hw_addr_random(dev); - - /* Set up our device-specific information */ - vi = netdev_priv(dev); - vi->dev = dev; - vi->vdev = vdev; - vdev->priv = vi; - vi->stats = alloc_percpu(struct virtnet_stats); - err = -ENOMEM; - if (vi->stats == NULL) - goto free; - - for_each_possible_cpu(i) { - struct virtnet_stats *virtnet_stats; - virtnet_stats = per_cpu_ptr(vi->stats, i); - u64_stats_init(&virtnet_stats->tx_syncp); - u64_stats_init(&virtnet_stats->rx_syncp); - } - - INIT_WORK(&vi->config_work, virtnet_config_changed_work); - - /* If we can receive ANY GSO packets, we must allocate large ones. */ - if (virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO4) || - virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_TSO6) || - virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_ECN) || - virtio_has_feature(vdev, VIRTIO_NET_F_GUEST_UFO)) - vi->big_packets = true; - - if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF)) - vi->mergeable_rx_bufs = true; - - if (virtio_has_feature(vdev, VIRTIO_NET_F_MRG_RXBUF) || - virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) - vi->hdr_len = sizeof(struct virtio_net_hdr_mrg_rxbuf); - else - vi->hdr_len = sizeof(struct virtio_net_hdr); - - if (virtio_has_feature(vdev, VIRTIO_F_ANY_LAYOUT) || - virtio_has_feature(vdev, VIRTIO_F_VERSION_1)) - vi->any_header_sg = true; - - if (virtio_has_feature(vdev, VIRTIO_NET_F_CTRL_VQ)) - vi->has_cvq = true; - - if (vi->any_header_sg) - dev->needed_headroom = vi->hdr_len; - - /* Use single tx/rx queue pair as default */ - vi->curr_queue_pairs = 1; - vi->max_queue_pairs = max_queue_pairs; - - /* Allocate/initialize the rx/tx queues, and invoke find_vqs */ - err = init_vqs(vi); - if (err) - goto free_stats; - -#ifdef CONFIG_SYSFS - if (vi->mergeable_rx_bufs) - dev->sysfs_rx_queue_group = &virtio_net_mrg_rx_group; -#endif - netif_set_real_num_tx_queues(dev, vi->curr_queue_pairs); - netif_set_real_num_rx_queues(dev, vi->curr_queue_pairs); - - err = register_netdev(dev); - if (err) { - pr_debug("virtio_net: registering device failed\n"); - goto free_vqs; - } - - virtio_device_ready(vdev); - - /* Last of all, set up some receive buffers. */ - for (i = 0; i < vi->curr_queue_pairs; i++) { - try_fill_recv(vi, &vi->rq[i], GFP_KERNEL); - - /* If we didn't even get one input buffer, we're useless. */ - if (vi->rq[i].vq->num_free == - virtqueue_get_vring_size(vi->rq[i].vq)) { - free_unused_bufs(vi); - err = -ENOMEM; - goto free_recv_bufs; - } - } - - vi->nb.notifier_call = &virtnet_cpu_callback; - err = register_hotcpu_notifier(&vi->nb); - if (err) { - pr_debug("virtio_net: registering cpu notifier failed\n"); - goto free_recv_bufs; - } - - /* Assume link up if device can't report link status, - otherwise get link status from config. */ - netif_carrier_off(dev); - if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) { - schedule_work(&vi->config_work); - } else { - vi->status = VIRTIO_NET_S_LINK_UP; - netif_carrier_on(dev); - } - - pr_debug("virtnet: registered device %s with %d RX and TX vq's\n", - dev->name, max_queue_pairs); - - return 0; - -free_recv_bufs: - vi->vdev->config->reset(vdev); - - free_receive_bufs(vi); - unregister_netdev(dev); -free_vqs: - cancel_delayed_work_sync(&vi->refill); - free_receive_page_frags(vi); - virtnet_del_vqs(vi); -free_stats: - free_percpu(vi->stats); -free: - free_netdev(dev); - return err; -} - -static void remove_vq_common(struct virtnet_info *vi) -{ - vi->vdev->config->reset(vi->vdev); - - /* Free unused buffers in both send and recv, if any. */ - free_unused_bufs(vi); - - free_receive_bufs(vi); - - free_receive_page_frags(vi); - - virtnet_del_vqs(vi); -} - -static void virtnet_remove(struct virtio_device *vdev) -{ - struct virtnet_info *vi = vdev->priv; - - unregister_hotcpu_notifier(&vi->nb); - - /* Make sure no work handler is accessing the device. */ - flush_work(&vi->config_work); - - unregister_netdev(vi->dev); - - remove_vq_common(vi); - - free_percpu(vi->stats); - free_netdev(vi->dev); -} - -#ifdef CONFIG_PM_SLEEP -static int virtnet_freeze(struct virtio_device *vdev) -{ - struct virtnet_info *vi = vdev->priv; - int i; - - unregister_hotcpu_notifier(&vi->nb); - - /* Make sure no work handler is accessing the device */ - flush_work(&vi->config_work); - - netif_device_detach(vi->dev); - cancel_delayed_work_sync(&vi->refill); - - if (netif_running(vi->dev)) { - for (i = 0; i < vi->max_queue_pairs; i++) - napi_disable(&vi->rq[i].napi); - } - - remove_vq_common(vi); - - return 0; -} - -static int virtnet_restore(struct virtio_device *vdev) -{ - struct virtnet_info *vi = vdev->priv; - int err, i; - - err = init_vqs(vi); - if (err) - return err; - - virtio_device_ready(vdev); - - if (netif_running(vi->dev)) { - for (i = 0; i < vi->curr_queue_pairs; i++) - if (!try_fill_recv(vi, &vi->rq[i], GFP_KERNEL)) - schedule_delayed_work(&vi->refill, 0); - - for (i = 0; i < vi->max_queue_pairs; i++) - virtnet_napi_enable(&vi->rq[i]); - } - - netif_device_attach(vi->dev); - - rtnl_lock(); - virtnet_set_queues(vi, vi->curr_queue_pairs); - rtnl_unlock(); - - err = register_hotcpu_notifier(&vi->nb); - if (err) - return err; - - return 0; -} -#endif - -static struct virtio_device_id id_table[] = { - { VIRTIO_ID_NET, VIRTIO_DEV_ANY_ID }, - { 0 }, -}; - -static unsigned int features[] = { - VIRTIO_NET_F_CSUM, VIRTIO_NET_F_GUEST_CSUM, - VIRTIO_NET_F_GSO, VIRTIO_NET_F_MAC, - VIRTIO_NET_F_HOST_TSO4, VIRTIO_NET_F_HOST_UFO, VIRTIO_NET_F_HOST_TSO6, - VIRTIO_NET_F_HOST_ECN, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, - VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_UFO, - VIRTIO_NET_F_MRG_RXBUF, VIRTIO_NET_F_STATUS, VIRTIO_NET_F_CTRL_VQ, - VIRTIO_NET_F_CTRL_RX, VIRTIO_NET_F_CTRL_VLAN, - VIRTIO_NET_F_GUEST_ANNOUNCE, VIRTIO_NET_F_MQ, - VIRTIO_NET_F_CTRL_MAC_ADDR, - VIRTIO_F_ANY_LAYOUT, -}; - -static struct virtio_driver virtio_net_driver = { - .feature_table = features, - .feature_table_size = ARRAY_SIZE(features), - .driver.name = KBUILD_MODNAME, - .driver.owner = THIS_MODULE, - .id_table = id_table, - .probe = virtnet_probe, - .remove = virtnet_remove, - .config_changed = virtnet_config_changed, -#ifdef CONFIG_PM_SLEEP - .freeze = virtnet_freeze, - .restore = virtnet_restore, -#endif -}; - -module_virtio_driver(virtio_net_driver); - -MODULE_DEVICE_TABLE(virtio, id_table); -MODULE_DESCRIPTION("Virtio network driver"); -MODULE_LICENSE("GPL"); diff --git a/addons/virtio/src/4.4.180/virtio_pci_common.c b/addons/virtio/src/4.4.180/virtio_pci_common.c deleted file mode 100644 index 2046a68a..00000000 --- a/addons/virtio/src/4.4.180/virtio_pci_common.c +++ /dev/null @@ -1,576 +0,0 @@ -/* - * Virtio PCI driver - common functionality for all device versions - * - * This module allows virtio devices to be used over a virtual PCI device. - * This can be used with QEMU based VMMs like KVM or Xen. - * - * Copyright IBM Corp. 2007 - * Copyright Red Hat, Inc. 2014 - * - * Authors: - * Anthony Liguori - * Rusty Russell - * Michael S. Tsirkin - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#include "virtio_pci_common.h" - -static bool force_legacy = false; - -#if IS_ENABLED(CONFIG_VIRTIO_PCI_LEGACY) -module_param(force_legacy, bool, 0444); -MODULE_PARM_DESC(force_legacy, - "Force legacy mode for transitional virtio 1 devices"); -#endif - -/* wait for pending irq handlers */ -void vp_synchronize_vectors(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - int i; - - if (vp_dev->intx_enabled) - synchronize_irq(vp_dev->pci_dev->irq); - - for (i = 0; i < vp_dev->msix_vectors; ++i) - synchronize_irq(vp_dev->msix_entries[i].vector); -} - -/* the notify function used when creating a virt queue */ -bool vp_notify(struct virtqueue *vq) -{ - /* we write the queue's selector into the notification register to - * signal the other end */ - iowrite16(vq->index, (void __iomem *)vq->priv); - return true; -} - -/* Handle a configuration change: Tell driver if it wants to know. */ -static irqreturn_t vp_config_changed(int irq, void *opaque) -{ - struct virtio_pci_device *vp_dev = opaque; - - virtio_config_changed(&vp_dev->vdev); - return IRQ_HANDLED; -} - -/* Notify all virtqueues on an interrupt. */ -static irqreturn_t vp_vring_interrupt(int irq, void *opaque) -{ - struct virtio_pci_device *vp_dev = opaque; - struct virtio_pci_vq_info *info; - irqreturn_t ret = IRQ_NONE; - unsigned long flags; - - spin_lock_irqsave(&vp_dev->lock, flags); - list_for_each_entry(info, &vp_dev->virtqueues, node) { - if (vring_interrupt(irq, info->vq) == IRQ_HANDLED) - ret = IRQ_HANDLED; - } - spin_unlock_irqrestore(&vp_dev->lock, flags); - - return ret; -} - -/* A small wrapper to also acknowledge the interrupt when it's handled. - * I really need an EIO hook for the vring so I can ack the interrupt once we - * know that we'll be handling the IRQ but before we invoke the callback since - * the callback may notify the host which results in the host attempting to - * raise an interrupt that we would then mask once we acknowledged the - * interrupt. */ -static irqreturn_t vp_interrupt(int irq, void *opaque) -{ - struct virtio_pci_device *vp_dev = opaque; - u8 isr; - - /* reading the ISR has the effect of also clearing it so it's very - * important to save off the value. */ - isr = ioread8(vp_dev->isr); - - /* It's definitely not us if the ISR was not high */ - if (!isr) - return IRQ_NONE; - - /* Configuration change? Tell driver if it wants to know. */ - if (isr & VIRTIO_PCI_ISR_CONFIG) - vp_config_changed(irq, opaque); - - return vp_vring_interrupt(irq, opaque); -} - -static void vp_free_vectors(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - int i; - - if (vp_dev->intx_enabled) { - free_irq(vp_dev->pci_dev->irq, vp_dev); - vp_dev->intx_enabled = 0; - } - - for (i = 0; i < vp_dev->msix_used_vectors; ++i) - free_irq(vp_dev->msix_entries[i].vector, vp_dev); - - for (i = 0; i < vp_dev->msix_vectors; i++) - if (vp_dev->msix_affinity_masks[i]) - free_cpumask_var(vp_dev->msix_affinity_masks[i]); - - if (vp_dev->msix_enabled) { - /* Disable the vector used for configuration */ - vp_dev->config_vector(vp_dev, VIRTIO_MSI_NO_VECTOR); - - pci_disable_msix(vp_dev->pci_dev); - vp_dev->msix_enabled = 0; - } - - vp_dev->msix_vectors = 0; - vp_dev->msix_used_vectors = 0; - kfree(vp_dev->msix_names); - vp_dev->msix_names = NULL; - kfree(vp_dev->msix_entries); - vp_dev->msix_entries = NULL; - kfree(vp_dev->msix_affinity_masks); - vp_dev->msix_affinity_masks = NULL; -} - -static int vp_request_msix_vectors(struct virtio_device *vdev, int nvectors, - bool per_vq_vectors) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - const char *name = dev_name(&vp_dev->vdev.dev); - unsigned i, v; - int err = -ENOMEM; - - vp_dev->msix_vectors = nvectors; - - vp_dev->msix_entries = kmalloc(nvectors * sizeof *vp_dev->msix_entries, - GFP_KERNEL); - if (!vp_dev->msix_entries) - goto error; - vp_dev->msix_names = kmalloc(nvectors * sizeof *vp_dev->msix_names, - GFP_KERNEL); - if (!vp_dev->msix_names) - goto error; - vp_dev->msix_affinity_masks - = kzalloc(nvectors * sizeof *vp_dev->msix_affinity_masks, - GFP_KERNEL); - if (!vp_dev->msix_affinity_masks) - goto error; - for (i = 0; i < nvectors; ++i) - if (!alloc_cpumask_var(&vp_dev->msix_affinity_masks[i], - GFP_KERNEL)) - goto error; - - for (i = 0; i < nvectors; ++i) - vp_dev->msix_entries[i].entry = i; - - err = pci_enable_msix_exact(vp_dev->pci_dev, - vp_dev->msix_entries, nvectors); - if (err) - goto error; - vp_dev->msix_enabled = 1; - - /* Set the vector used for configuration */ - v = vp_dev->msix_used_vectors; - snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names, - "%s-config", name); - err = request_irq(vp_dev->msix_entries[v].vector, - vp_config_changed, 0, vp_dev->msix_names[v], - vp_dev); - if (err) - goto error; - ++vp_dev->msix_used_vectors; - - v = vp_dev->config_vector(vp_dev, v); - /* Verify we had enough resources to assign the vector */ - if (v == VIRTIO_MSI_NO_VECTOR) { - err = -EBUSY; - goto error; - } - - if (!per_vq_vectors) { - /* Shared vector for all VQs */ - v = vp_dev->msix_used_vectors; - snprintf(vp_dev->msix_names[v], sizeof *vp_dev->msix_names, - "%s-virtqueues", name); - err = request_irq(vp_dev->msix_entries[v].vector, - vp_vring_interrupt, 0, vp_dev->msix_names[v], - vp_dev); - if (err) - goto error; - ++vp_dev->msix_used_vectors; - } - return 0; -error: - vp_free_vectors(vdev); - return err; -} - -static int vp_request_intx(struct virtio_device *vdev) -{ - int err; - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - - err = request_irq(vp_dev->pci_dev->irq, vp_interrupt, - IRQF_SHARED, dev_name(&vdev->dev), vp_dev); - if (!err) - vp_dev->intx_enabled = 1; - return err; -} - -static struct virtqueue *vp_setup_vq(struct virtio_device *vdev, unsigned index, - void (*callback)(struct virtqueue *vq), - const char *name, - u16 msix_vec) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - struct virtio_pci_vq_info *info = kmalloc(sizeof *info, GFP_KERNEL); - struct virtqueue *vq; - unsigned long flags; - - /* fill out our structure that represents an active queue */ - if (!info) - return ERR_PTR(-ENOMEM); - - vq = vp_dev->setup_vq(vp_dev, info, index, callback, name, msix_vec); - if (IS_ERR(vq)) - goto out_info; - - info->vq = vq; - if (callback) { - spin_lock_irqsave(&vp_dev->lock, flags); - list_add(&info->node, &vp_dev->virtqueues); - spin_unlock_irqrestore(&vp_dev->lock, flags); - } else { - INIT_LIST_HEAD(&info->node); - } - - vp_dev->vqs[index] = info; - return vq; - -out_info: - kfree(info); - return vq; -} - -static void vp_del_vq(struct virtqueue *vq) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); - struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index]; - unsigned long flags; - - spin_lock_irqsave(&vp_dev->lock, flags); - list_del(&info->node); - spin_unlock_irqrestore(&vp_dev->lock, flags); - - vp_dev->del_vq(info); - kfree(info); -} - -/* the config->del_vqs() implementation */ -void vp_del_vqs(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - struct virtqueue *vq, *n; - struct virtio_pci_vq_info *info; - - list_for_each_entry_safe(vq, n, &vdev->vqs, list) { - info = vp_dev->vqs[vq->index]; - if (vp_dev->per_vq_vectors && - info->msix_vector != VIRTIO_MSI_NO_VECTOR) - free_irq(vp_dev->msix_entries[info->msix_vector].vector, - vq); - vp_del_vq(vq); - } - vp_dev->per_vq_vectors = false; - - vp_free_vectors(vdev); - kfree(vp_dev->vqs); - vp_dev->vqs = NULL; -} - -static int vp_try_to_find_vqs(struct virtio_device *vdev, unsigned nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], - const char *names[], - bool use_msix, - bool per_vq_vectors) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - u16 msix_vec; - int i, err, nvectors, allocated_vectors; - - vp_dev->vqs = kmalloc(nvqs * sizeof *vp_dev->vqs, GFP_KERNEL); - if (!vp_dev->vqs) - return -ENOMEM; - - if (!use_msix) { - /* Old style: one normal interrupt for change and all vqs. */ - err = vp_request_intx(vdev); - if (err) - goto error_find; - } else { - if (per_vq_vectors) { - /* Best option: one for change interrupt, one per vq. */ - nvectors = 1; - for (i = 0; i < nvqs; ++i) - if (callbacks[i]) - ++nvectors; - } else { - /* Second best: one for change, shared for all vqs. */ - nvectors = 2; - } - - err = vp_request_msix_vectors(vdev, nvectors, per_vq_vectors); - if (err) - goto error_find; - } - - vp_dev->per_vq_vectors = per_vq_vectors; - allocated_vectors = vp_dev->msix_used_vectors; - for (i = 0; i < nvqs; ++i) { - if (!names[i]) { - vqs[i] = NULL; - continue; - } else if (!callbacks[i] || !vp_dev->msix_enabled) - msix_vec = VIRTIO_MSI_NO_VECTOR; - else if (vp_dev->per_vq_vectors) - msix_vec = allocated_vectors++; - else - msix_vec = VP_MSIX_VQ_VECTOR; - vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i], msix_vec); - if (IS_ERR(vqs[i])) { - err = PTR_ERR(vqs[i]); - goto error_find; - } - - if (!vp_dev->per_vq_vectors || msix_vec == VIRTIO_MSI_NO_VECTOR) - continue; - - /* allocate per-vq irq if available and necessary */ - snprintf(vp_dev->msix_names[msix_vec], - sizeof *vp_dev->msix_names, - "%s-%s", - dev_name(&vp_dev->vdev.dev), names[i]); - err = request_irq(vp_dev->msix_entries[msix_vec].vector, - vring_interrupt, 0, - vp_dev->msix_names[msix_vec], - vqs[i]); - if (err) { - vp_del_vq(vqs[i]); - goto error_find; - } - } - return 0; - -error_find: - vp_del_vqs(vdev); - return err; -} - -/* the config->find_vqs() implementation */ -int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], - const char *names[]) -{ - int err; - - /* Try MSI-X with one vector per queue. */ - err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, true, true); - if (!err) - return 0; - /* Fallback: MSI-X with one vector for config, one shared for queues. */ - err = vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, - true, false); - if (!err) - return 0; - /* Finally fall back to regular interrupts. */ - return vp_try_to_find_vqs(vdev, nvqs, vqs, callbacks, names, - false, false); -} - -const char *vp_bus_name(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - - return pci_name(vp_dev->pci_dev); -} - -/* Setup the affinity for a virtqueue: - * - force the affinity for per vq vector - * - OR over all affinities for shared MSI - * - ignore the affinity request if we're using INTX - */ -int vp_set_vq_affinity(struct virtqueue *vq, int cpu) -{ - struct virtio_device *vdev = vq->vdev; - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - struct virtio_pci_vq_info *info = vp_dev->vqs[vq->index]; - struct cpumask *mask; - unsigned int irq; - - if (!vq->callback) - return -EINVAL; - - if (vp_dev->msix_enabled) { - mask = vp_dev->msix_affinity_masks[info->msix_vector]; - irq = vp_dev->msix_entries[info->msix_vector].vector; - if (cpu == -1) - irq_set_affinity_hint(irq, NULL); - else { - cpumask_clear(mask); - cpumask_set_cpu(cpu, mask); - irq_set_affinity_hint(irq, mask); - } - } - return 0; -} - -#ifdef CONFIG_PM_SLEEP -static int virtio_pci_freeze(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); - int ret; - - ret = virtio_device_freeze(&vp_dev->vdev); - - if (!ret) - pci_disable_device(pci_dev); - return ret; -} - -static int virtio_pci_restore(struct device *dev) -{ - struct pci_dev *pci_dev = to_pci_dev(dev); - struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); - int ret; - - ret = pci_enable_device(pci_dev); - if (ret) - return ret; - - pci_set_master(pci_dev); - return virtio_device_restore(&vp_dev->vdev); -} - -static const struct dev_pm_ops virtio_pci_pm_ops = { - SET_SYSTEM_SLEEP_PM_OPS(virtio_pci_freeze, virtio_pci_restore) -}; -#endif - - -/* Qumranet donated their vendor ID for devices 0x1000 thru 0x10FF. */ -static const struct pci_device_id virtio_pci_id_table[] = { - { PCI_DEVICE(0x1af4, PCI_ANY_ID) }, - { 0 } -}; - -MODULE_DEVICE_TABLE(pci, virtio_pci_id_table); - -static void virtio_pci_release_dev(struct device *_d) -{ - struct virtio_device *vdev = dev_to_virtio(_d); - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - - /* As struct device is a kobject, it's not safe to - * free the memory (including the reference counter itself) - * until it's release callback. */ - kfree(vp_dev); -} - -static int virtio_pci_probe(struct pci_dev *pci_dev, - const struct pci_device_id *id) -{ - struct virtio_pci_device *vp_dev; - int rc; - - /* allocate our structure and fill it out */ - vp_dev = kzalloc(sizeof(struct virtio_pci_device), GFP_KERNEL); - if (!vp_dev) - return -ENOMEM; - - pci_set_drvdata(pci_dev, vp_dev); - vp_dev->vdev.dev.parent = &pci_dev->dev; - vp_dev->vdev.dev.release = virtio_pci_release_dev; - vp_dev->pci_dev = pci_dev; - INIT_LIST_HEAD(&vp_dev->virtqueues); - spin_lock_init(&vp_dev->lock); - - /* enable the device */ - rc = pci_enable_device(pci_dev); - if (rc) - goto err_enable_device; - - if (force_legacy) { - rc = virtio_pci_legacy_probe(vp_dev); - /* Also try modern mode if we can't map BAR0 (no IO space). */ - if (rc == -ENODEV || rc == -ENOMEM) - rc = virtio_pci_modern_probe(vp_dev); - if (rc) - goto err_probe; - } else { - rc = virtio_pci_modern_probe(vp_dev); - if (rc == -ENODEV) - rc = virtio_pci_legacy_probe(vp_dev); - if (rc) - goto err_probe; - } - - pci_set_master(pci_dev); - - rc = register_virtio_device(&vp_dev->vdev); - if (rc) - goto err_register; - - return 0; - -err_register: - if (vp_dev->ioaddr) - virtio_pci_legacy_remove(vp_dev); - else - virtio_pci_modern_remove(vp_dev); -err_probe: - pci_disable_device(pci_dev); -err_enable_device: - kfree(vp_dev); - return rc; -} - -static void virtio_pci_remove(struct pci_dev *pci_dev) -{ - struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev); - struct device *dev = get_device(&vp_dev->vdev.dev); - - unregister_virtio_device(&vp_dev->vdev); - - if (vp_dev->ioaddr) - virtio_pci_legacy_remove(vp_dev); - else - virtio_pci_modern_remove(vp_dev); - - pci_disable_device(pci_dev); - put_device(dev); -} - -static struct pci_driver virtio_pci_driver = { - .name = "virtio-pci", - .id_table = virtio_pci_id_table, - .probe = virtio_pci_probe, - .remove = virtio_pci_remove, -#ifdef CONFIG_PM_SLEEP - .driver.pm = &virtio_pci_pm_ops, -#endif -}; - -module_pci_driver(virtio_pci_driver); - -MODULE_AUTHOR("Anthony Liguori "); -MODULE_DESCRIPTION("virtio-pci"); -MODULE_LICENSE("GPL"); -MODULE_VERSION("1"); diff --git a/addons/virtio/src/4.4.180/virtio_pci_common.h b/addons/virtio/src/4.4.180/virtio_pci_common.h deleted file mode 100644 index b976d968..00000000 --- a/addons/virtio/src/4.4.180/virtio_pci_common.h +++ /dev/null @@ -1,167 +0,0 @@ -#ifndef _DRIVERS_VIRTIO_VIRTIO_PCI_COMMON_H -#define _DRIVERS_VIRTIO_VIRTIO_PCI_COMMON_H -/* - * Virtio PCI driver - APIs for common functionality for all device versions - * - * This module allows virtio devices to be used over a virtual PCI device. - * This can be used with QEMU based VMMs like KVM or Xen. - * - * Copyright IBM Corp. 2007 - * Copyright Red Hat, Inc. 2014 - * - * Authors: - * Anthony Liguori - * Rusty Russell - * Michael S. Tsirkin - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct virtio_pci_vq_info { - /* the actual virtqueue */ - struct virtqueue *vq; - - /* the number of entries in the queue */ - int num; - - /* the virtual address of the ring queue */ - void *queue; - - /* the list node for the virtqueues list */ - struct list_head node; - - /* MSI-X vector (or none) */ - unsigned msix_vector; -}; - -/* Our device structure */ -struct virtio_pci_device { - struct virtio_device vdev; - struct pci_dev *pci_dev; - - /* In legacy mode, these two point to within ->legacy. */ - /* Where to read and clear interrupt */ - u8 __iomem *isr; - - /* Modern only fields */ - /* The IO mapping for the PCI config space (non-legacy mode) */ - struct virtio_pci_common_cfg __iomem *common; - /* Device-specific data (non-legacy mode) */ - void __iomem *device; - /* Base of vq notifications (non-legacy mode). */ - void __iomem *notify_base; - - /* So we can sanity-check accesses. */ - size_t notify_len; - size_t device_len; - - /* Capability for when we need to map notifications per-vq. */ - int notify_map_cap; - - /* Multiply queue_notify_off by this value. (non-legacy mode). */ - u32 notify_offset_multiplier; - - int modern_bars; - - /* Legacy only field */ - /* the IO mapping for the PCI config space */ - void __iomem *ioaddr; - - /* a list of queues so we can dispatch IRQs */ - spinlock_t lock; - struct list_head virtqueues; - - /* array of all queues for house-keeping */ - struct virtio_pci_vq_info **vqs; - - /* MSI-X support */ - int msix_enabled; - int intx_enabled; - struct msix_entry *msix_entries; - cpumask_var_t *msix_affinity_masks; - /* Name strings for interrupts. This size should be enough, - * and I'm too lazy to allocate each name separately. */ - char (*msix_names)[256]; - /* Number of available vectors */ - unsigned msix_vectors; - /* Vectors allocated, excluding per-vq vectors if any */ - unsigned msix_used_vectors; - - /* Whether we have vector per vq */ - bool per_vq_vectors; - - struct virtqueue *(*setup_vq)(struct virtio_pci_device *vp_dev, - struct virtio_pci_vq_info *info, - unsigned idx, - void (*callback)(struct virtqueue *vq), - const char *name, - u16 msix_vec); - void (*del_vq)(struct virtio_pci_vq_info *info); - - u16 (*config_vector)(struct virtio_pci_device *vp_dev, u16 vector); -}; - -/* Constants for MSI-X */ -/* Use first vector for configuration changes, second and the rest for - * virtqueues Thus, we need at least 2 vectors for MSI. */ -enum { - VP_MSIX_CONFIG_VECTOR = 0, - VP_MSIX_VQ_VECTOR = 1, -}; - -/* Convert a generic virtio device to our structure */ -static struct virtio_pci_device *to_vp_device(struct virtio_device *vdev) -{ - return container_of(vdev, struct virtio_pci_device, vdev); -} - -/* wait for pending irq handlers */ -void vp_synchronize_vectors(struct virtio_device *vdev); -/* the notify function used when creating a virt queue */ -bool vp_notify(struct virtqueue *vq); -/* the config->del_vqs() implementation */ -void vp_del_vqs(struct virtio_device *vdev); -/* the config->find_vqs() implementation */ -int vp_find_vqs(struct virtio_device *vdev, unsigned nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], - const char *names[]); -const char *vp_bus_name(struct virtio_device *vdev); - -/* Setup the affinity for a virtqueue: - * - force the affinity for per vq vector - * - OR over all affinities for shared MSI - * - ignore the affinity request if we're using INTX - */ -int vp_set_vq_affinity(struct virtqueue *vq, int cpu); - -#if IS_ENABLED(CONFIG_VIRTIO_PCI_LEGACY) -int virtio_pci_legacy_probe(struct virtio_pci_device *); -void virtio_pci_legacy_remove(struct virtio_pci_device *); -#else -static inline int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev) -{ - return -ENODEV; -} -static inline void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev) -{ -} -#endif -int virtio_pci_modern_probe(struct virtio_pci_device *); -void virtio_pci_modern_remove(struct virtio_pci_device *); - -#endif diff --git a/addons/virtio/src/4.4.180/virtio_pci_legacy.c b/addons/virtio/src/4.4.180/virtio_pci_legacy.c deleted file mode 100644 index 48bc9797..00000000 --- a/addons/virtio/src/4.4.180/virtio_pci_legacy.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Virtio PCI driver - legacy device support - * - * This module allows virtio devices to be used over a virtual PCI device. - * This can be used with QEMU based VMMs like KVM or Xen. - * - * Copyright IBM Corp. 2007 - * Copyright Red Hat, Inc. 2014 - * - * Authors: - * Anthony Liguori - * Rusty Russell - * Michael S. Tsirkin - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#include "virtio_pci_common.h" - -/* virtio config->get_features() implementation */ -static u64 vp_get_features(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - - /* When someone needs more than 32 feature bits, we'll need to - * steal a bit to indicate that the rest are somewhere else. */ - return ioread32(vp_dev->ioaddr + VIRTIO_PCI_HOST_FEATURES); -} - -/* virtio config->finalize_features() implementation */ -static int vp_finalize_features(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - - /* Give virtio_ring a chance to accept features. */ - vring_transport_features(vdev); - - /* Make sure we don't have any features > 32 bits! */ - BUG_ON((u32)vdev->features != vdev->features); - - /* We only support 32 feature bits. */ - iowrite32(vdev->features, vp_dev->ioaddr + VIRTIO_PCI_GUEST_FEATURES); - - return 0; -} - -/* virtio config->get() implementation */ -static void vp_get(struct virtio_device *vdev, unsigned offset, - void *buf, unsigned len) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - void __iomem *ioaddr = vp_dev->ioaddr + - VIRTIO_PCI_CONFIG(vp_dev) + offset; - u8 *ptr = buf; - int i; - - for (i = 0; i < len; i++) - ptr[i] = ioread8(ioaddr + i); -} - -/* the config->set() implementation. it's symmetric to the config->get() - * implementation */ -static void vp_set(struct virtio_device *vdev, unsigned offset, - const void *buf, unsigned len) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - void __iomem *ioaddr = vp_dev->ioaddr + - VIRTIO_PCI_CONFIG(vp_dev) + offset; - const u8 *ptr = buf; - int i; - - for (i = 0; i < len; i++) - iowrite8(ptr[i], ioaddr + i); -} - -/* config->{get,set}_status() implementations */ -static u8 vp_get_status(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - return ioread8(vp_dev->ioaddr + VIRTIO_PCI_STATUS); -} - -static void vp_set_status(struct virtio_device *vdev, u8 status) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - /* We should never be setting status to 0. */ - BUG_ON(status == 0); - iowrite8(status, vp_dev->ioaddr + VIRTIO_PCI_STATUS); -} - -static void vp_reset(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - /* 0 status means a reset. */ - iowrite8(0, vp_dev->ioaddr + VIRTIO_PCI_STATUS); - /* Flush out the status write, and flush in device writes, - * including MSi-X interrupts, if any. */ - ioread8(vp_dev->ioaddr + VIRTIO_PCI_STATUS); - /* Flush pending VQ/configuration callbacks. */ - vp_synchronize_vectors(vdev); -} - -static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector) -{ - /* Setup the vector used for configuration events */ - iowrite16(vector, vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); - /* Verify we had enough resources to assign the vector */ - /* Will also flush the write out to device */ - return ioread16(vp_dev->ioaddr + VIRTIO_MSI_CONFIG_VECTOR); -} - -static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, - struct virtio_pci_vq_info *info, - unsigned index, - void (*callback)(struct virtqueue *vq), - const char *name, - u16 msix_vec) -{ - struct virtqueue *vq; - unsigned long size; - u16 num; - int err; - - /* Select the queue we're interested in */ - iowrite16(index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); - - /* Check if queue is either not available or already active. */ - num = ioread16(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NUM); - if (!num || ioread32(vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN)) - return ERR_PTR(-ENOENT); - - info->num = num; - info->msix_vector = msix_vec; - - size = PAGE_ALIGN(vring_size(num, VIRTIO_PCI_VRING_ALIGN)); - info->queue = alloc_pages_exact(size, GFP_KERNEL|__GFP_ZERO); - if (info->queue == NULL) - return ERR_PTR(-ENOMEM); - - /* activate the queue */ - iowrite32(virt_to_phys(info->queue) >> VIRTIO_PCI_QUEUE_ADDR_SHIFT, - vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); - - /* create the vring */ - vq = vring_new_virtqueue(index, info->num, - VIRTIO_PCI_VRING_ALIGN, &vp_dev->vdev, - true, info->queue, vp_notify, callback, name); - if (!vq) { - err = -ENOMEM; - goto out_activate_queue; - } - - vq->priv = (void __force *)vp_dev->ioaddr + VIRTIO_PCI_QUEUE_NOTIFY; - - if (msix_vec != VIRTIO_MSI_NO_VECTOR) { - iowrite16(msix_vec, vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - msix_vec = ioread16(vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - if (msix_vec == VIRTIO_MSI_NO_VECTOR) { - err = -EBUSY; - goto out_assign; - } - } - - return vq; - -out_assign: - vring_del_virtqueue(vq); -out_activate_queue: - iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); - free_pages_exact(info->queue, size); - return ERR_PTR(err); -} - -static void del_vq(struct virtio_pci_vq_info *info) -{ - struct virtqueue *vq = info->vq; - struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); - unsigned long size; - - iowrite16(vq->index, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_SEL); - - if (vp_dev->msix_enabled) { - iowrite16(VIRTIO_MSI_NO_VECTOR, - vp_dev->ioaddr + VIRTIO_MSI_QUEUE_VECTOR); - /* Flush the write out to device */ - ioread8(vp_dev->ioaddr + VIRTIO_PCI_ISR); - } - - vring_del_virtqueue(vq); - - /* Select and deactivate the queue */ - iowrite32(0, vp_dev->ioaddr + VIRTIO_PCI_QUEUE_PFN); - - size = PAGE_ALIGN(vring_size(info->num, VIRTIO_PCI_VRING_ALIGN)); - free_pages_exact(info->queue, size); -} - -static const struct virtio_config_ops virtio_pci_config_ops = { - .get = vp_get, - .set = vp_set, - .get_status = vp_get_status, - .set_status = vp_set_status, - .reset = vp_reset, - .find_vqs = vp_find_vqs, - .del_vqs = vp_del_vqs, - .get_features = vp_get_features, - .finalize_features = vp_finalize_features, - .bus_name = vp_bus_name, - .set_vq_affinity = vp_set_vq_affinity, -}; - -/* the PCI probing function */ -int virtio_pci_legacy_probe(struct virtio_pci_device *vp_dev) -{ - struct pci_dev *pci_dev = vp_dev->pci_dev; - int rc; - - /* We only own devices >= 0x1000 and <= 0x103f: leave the rest. */ - if (pci_dev->device < 0x1000 || pci_dev->device > 0x103f) - return -ENODEV; - - if (pci_dev->revision != VIRTIO_PCI_ABI_VERSION) { - printk(KERN_ERR "virtio_pci: expected ABI version %d, got %d\n", - VIRTIO_PCI_ABI_VERSION, pci_dev->revision); - return -ENODEV; - } - - rc = pci_request_region(pci_dev, 0, "virtio-pci-legacy"); - if (rc) - return rc; - - rc = -ENOMEM; - vp_dev->ioaddr = pci_iomap(pci_dev, 0, 0); - if (!vp_dev->ioaddr) - goto err_iomap; - - vp_dev->isr = vp_dev->ioaddr + VIRTIO_PCI_ISR; - - /* we use the subsystem vendor/device id as the virtio vendor/device - * id. this allows us to use the same PCI vendor/device id for all - * virtio devices and to identify the particular virtio driver by - * the subsystem ids */ - vp_dev->vdev.id.vendor = pci_dev->subsystem_vendor; - vp_dev->vdev.id.device = pci_dev->subsystem_device; - - vp_dev->vdev.config = &virtio_pci_config_ops; - - vp_dev->config_vector = vp_config_vector; - vp_dev->setup_vq = setup_vq; - vp_dev->del_vq = del_vq; - - return 0; - -err_iomap: - pci_release_region(pci_dev, 0); - return rc; -} - -void virtio_pci_legacy_remove(struct virtio_pci_device *vp_dev) -{ - struct pci_dev *pci_dev = vp_dev->pci_dev; - - pci_iounmap(pci_dev, vp_dev->ioaddr); - pci_release_region(pci_dev, 0); -} diff --git a/addons/virtio/src/4.4.180/virtio_pci_modern.c b/addons/virtio/src/4.4.180/virtio_pci_modern.c deleted file mode 100644 index 4469202e..00000000 --- a/addons/virtio/src/4.4.180/virtio_pci_modern.c +++ /dev/null @@ -1,747 +0,0 @@ -/* - * Virtio PCI driver - modern (virtio 1.0) device support - * - * This module allows virtio devices to be used over a virtual PCI device. - * This can be used with QEMU based VMMs like KVM or Xen. - * - * Copyright IBM Corp. 2007 - * Copyright Red Hat, Inc. 2014 - * - * Authors: - * Anthony Liguori - * Rusty Russell - * Michael S. Tsirkin - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#include -#define VIRTIO_PCI_NO_LEGACY -#include "virtio_pci_common.h" - -/* - * Type-safe wrappers for io accesses. - * Use these to enforce at compile time the following spec requirement: - * - * The driver MUST access each field using the “natural” access - * method, i.e. 32-bit accesses for 32-bit fields, 16-bit accesses - * for 16-bit fields and 8-bit accesses for 8-bit fields. - */ -static inline u8 vp_ioread8(u8 __iomem *addr) -{ - return ioread8(addr); -} -static inline u16 vp_ioread16 (u16 __iomem *addr) -{ - return ioread16(addr); -} - -static inline u32 vp_ioread32(u32 __iomem *addr) -{ - return ioread32(addr); -} - -static inline void vp_iowrite8(u8 value, u8 __iomem *addr) -{ - iowrite8(value, addr); -} - -static inline void vp_iowrite16(u16 value, u16 __iomem *addr) -{ - iowrite16(value, addr); -} - -static inline void vp_iowrite32(u32 value, u32 __iomem *addr) -{ - iowrite32(value, addr); -} - -static void vp_iowrite64_twopart(u64 val, - __le32 __iomem *lo, __le32 __iomem *hi) -{ - vp_iowrite32((u32)val, lo); - vp_iowrite32(val >> 32, hi); -} - -static void __iomem *map_capability(struct pci_dev *dev, int off, - size_t minlen, - u32 align, - u32 start, u32 size, - size_t *len) -{ - u8 bar; - u32 offset, length; - void __iomem *p; - - pci_read_config_byte(dev, off + offsetof(struct virtio_pci_cap, - bar), - &bar); - pci_read_config_dword(dev, off + offsetof(struct virtio_pci_cap, offset), - &offset); - pci_read_config_dword(dev, off + offsetof(struct virtio_pci_cap, length), - &length); - - if (length <= start) { - dev_err(&dev->dev, - "virtio_pci: bad capability len %u (>%u expected)\n", - length, start); - return NULL; - } - - if (length - start < minlen) { - dev_err(&dev->dev, - "virtio_pci: bad capability len %u (>=%zu expected)\n", - length, minlen); - return NULL; - } - - length -= start; - - if (start + offset < offset) { - dev_err(&dev->dev, - "virtio_pci: map wrap-around %u+%u\n", - start, offset); - return NULL; - } - - offset += start; - - if (offset & (align - 1)) { - dev_err(&dev->dev, - "virtio_pci: offset %u not aligned to %u\n", - offset, align); - return NULL; - } - - if (length > size) - length = size; - - if (len) - *len = length; - - if (minlen + offset < minlen || - minlen + offset > pci_resource_len(dev, bar)) { - dev_err(&dev->dev, - "virtio_pci: map virtio %zu@%u " - "out of range on bar %i length %lu\n", - minlen, offset, - bar, (unsigned long)pci_resource_len(dev, bar)); - return NULL; - } - - p = pci_iomap_range(dev, bar, offset, length); - if (!p) - dev_err(&dev->dev, - "virtio_pci: unable to map virtio %u@%u on bar %i\n", - length, offset, bar); - return p; -} - -/* virtio config->get_features() implementation */ -static u64 vp_get_features(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - u64 features; - - vp_iowrite32(0, &vp_dev->common->device_feature_select); - features = vp_ioread32(&vp_dev->common->device_feature); - vp_iowrite32(1, &vp_dev->common->device_feature_select); - features |= ((u64)vp_ioread32(&vp_dev->common->device_feature) << 32); - - return features; -} - -/* virtio config->finalize_features() implementation */ -static int vp_finalize_features(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - - /* Give virtio_ring a chance to accept features. */ - vring_transport_features(vdev); - - if (!__virtio_test_bit(vdev, VIRTIO_F_VERSION_1)) { - dev_err(&vdev->dev, "virtio: device uses modern interface " - "but does not have VIRTIO_F_VERSION_1\n"); - return -EINVAL; - } - - vp_iowrite32(0, &vp_dev->common->guest_feature_select); - vp_iowrite32((u32)vdev->features, &vp_dev->common->guest_feature); - vp_iowrite32(1, &vp_dev->common->guest_feature_select); - vp_iowrite32(vdev->features >> 32, &vp_dev->common->guest_feature); - - return 0; -} - -/* virtio config->get() implementation */ -static void vp_get(struct virtio_device *vdev, unsigned offset, - void *buf, unsigned len) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - u8 b; - __le16 w; - __le32 l; - - BUG_ON(offset + len > vp_dev->device_len); - - switch (len) { - case 1: - b = ioread8(vp_dev->device + offset); - memcpy(buf, &b, sizeof b); - break; - case 2: - w = cpu_to_le16(ioread16(vp_dev->device + offset)); - memcpy(buf, &w, sizeof w); - break; - case 4: - l = cpu_to_le32(ioread32(vp_dev->device + offset)); - memcpy(buf, &l, sizeof l); - break; - case 8: - l = cpu_to_le32(ioread32(vp_dev->device + offset)); - memcpy(buf, &l, sizeof l); - l = cpu_to_le32(ioread32(vp_dev->device + offset + sizeof l)); - memcpy(buf + sizeof l, &l, sizeof l); - break; - default: - BUG(); - } -} - -/* the config->set() implementation. it's symmetric to the config->get() - * implementation */ -static void vp_set(struct virtio_device *vdev, unsigned offset, - const void *buf, unsigned len) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - u8 b; - __le16 w; - __le32 l; - - BUG_ON(offset + len > vp_dev->device_len); - - switch (len) { - case 1: - memcpy(&b, buf, sizeof b); - iowrite8(b, vp_dev->device + offset); - break; - case 2: - memcpy(&w, buf, sizeof w); - iowrite16(le16_to_cpu(w), vp_dev->device + offset); - break; - case 4: - memcpy(&l, buf, sizeof l); - iowrite32(le32_to_cpu(l), vp_dev->device + offset); - break; - case 8: - memcpy(&l, buf, sizeof l); - iowrite32(le32_to_cpu(l), vp_dev->device + offset); - memcpy(&l, buf + sizeof l, sizeof l); - iowrite32(le32_to_cpu(l), vp_dev->device + offset + sizeof l); - break; - default: - BUG(); - } -} - -static u32 vp_generation(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - return vp_ioread8(&vp_dev->common->config_generation); -} - -/* config->{get,set}_status() implementations */ -static u8 vp_get_status(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - return vp_ioread8(&vp_dev->common->device_status); -} - -static void vp_set_status(struct virtio_device *vdev, u8 status) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - /* We should never be setting status to 0. */ - BUG_ON(status == 0); - vp_iowrite8(status, &vp_dev->common->device_status); -} - -static void vp_reset(struct virtio_device *vdev) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - /* 0 status means a reset. */ - vp_iowrite8(0, &vp_dev->common->device_status); - /* After writing 0 to device_status, the driver MUST wait for a read of - * device_status to return 0 before reinitializing the device. - * This will flush out the status write, and flush in device writes, - * including MSI-X interrupts, if any. - */ - while (vp_ioread8(&vp_dev->common->device_status)) - msleep(1); - /* Flush pending VQ/configuration callbacks. */ - vp_synchronize_vectors(vdev); -} - -static u16 vp_config_vector(struct virtio_pci_device *vp_dev, u16 vector) -{ - /* Setup the vector used for configuration events */ - vp_iowrite16(vector, &vp_dev->common->msix_config); - /* Verify we had enough resources to assign the vector */ - /* Will also flush the write out to device */ - return vp_ioread16(&vp_dev->common->msix_config); -} - -static size_t vring_pci_size(u16 num) -{ - /* We only need a cacheline separation. */ - return PAGE_ALIGN(vring_size(num, SMP_CACHE_BYTES)); -} - -static void *alloc_virtqueue_pages(int *num) -{ - void *pages; - - /* TODO: allocate each queue chunk individually */ - for (; *num && vring_pci_size(*num) > PAGE_SIZE; *num /= 2) { - pages = alloc_pages_exact(vring_pci_size(*num), - GFP_KERNEL|__GFP_ZERO|__GFP_NOWARN); - if (pages) - return pages; - } - - if (!*num) - return NULL; - - /* Try to get a single page. You are my only hope! */ - return alloc_pages_exact(vring_pci_size(*num), GFP_KERNEL|__GFP_ZERO); -} - -static struct virtqueue *setup_vq(struct virtio_pci_device *vp_dev, - struct virtio_pci_vq_info *info, - unsigned index, - void (*callback)(struct virtqueue *vq), - const char *name, - u16 msix_vec) -{ - struct virtio_pci_common_cfg __iomem *cfg = vp_dev->common; - struct virtqueue *vq; - u16 num, off; - int err; - - if (index >= vp_ioread16(&cfg->num_queues)) - return ERR_PTR(-ENOENT); - - /* Select the queue we're interested in */ - vp_iowrite16(index, &cfg->queue_select); - - /* Check if queue is either not available or already active. */ - num = vp_ioread16(&cfg->queue_size); - if (!num || vp_ioread16(&cfg->queue_enable)) - return ERR_PTR(-ENOENT); - - if (num & (num - 1)) { - dev_warn(&vp_dev->pci_dev->dev, "bad queue size %u", num); - return ERR_PTR(-EINVAL); - } - - /* get offset of notification word for this vq */ - off = vp_ioread16(&cfg->queue_notify_off); - - info->num = num; - info->msix_vector = msix_vec; - - info->queue = alloc_virtqueue_pages(&info->num); - if (info->queue == NULL) - return ERR_PTR(-ENOMEM); - - /* create the vring */ - vq = vring_new_virtqueue(index, info->num, - SMP_CACHE_BYTES, &vp_dev->vdev, - true, info->queue, vp_notify, callback, name); - if (!vq) { - err = -ENOMEM; - goto err_new_queue; - } - - /* activate the queue */ - vp_iowrite16(num, &cfg->queue_size); - vp_iowrite64_twopart(virt_to_phys(info->queue), - &cfg->queue_desc_lo, &cfg->queue_desc_hi); - vp_iowrite64_twopart(virt_to_phys(virtqueue_get_avail(vq)), - &cfg->queue_avail_lo, &cfg->queue_avail_hi); - vp_iowrite64_twopart(virt_to_phys(virtqueue_get_used(vq)), - &cfg->queue_used_lo, &cfg->queue_used_hi); - - if (vp_dev->notify_base) { - /* offset should not wrap */ - if ((u64)off * vp_dev->notify_offset_multiplier + 2 - > vp_dev->notify_len) { - dev_warn(&vp_dev->pci_dev->dev, - "bad notification offset %u (x %u) " - "for queue %u > %zd", - off, vp_dev->notify_offset_multiplier, - index, vp_dev->notify_len); - err = -EINVAL; - goto err_map_notify; - } - vq->priv = (void __force *)vp_dev->notify_base + - off * vp_dev->notify_offset_multiplier; - } else { - vq->priv = (void __force *)map_capability(vp_dev->pci_dev, - vp_dev->notify_map_cap, 2, 2, - off * vp_dev->notify_offset_multiplier, 2, - NULL); - } - - if (!vq->priv) { - err = -ENOMEM; - goto err_map_notify; - } - - if (msix_vec != VIRTIO_MSI_NO_VECTOR) { - vp_iowrite16(msix_vec, &cfg->queue_msix_vector); - msix_vec = vp_ioread16(&cfg->queue_msix_vector); - if (msix_vec == VIRTIO_MSI_NO_VECTOR) { - err = -EBUSY; - goto err_assign_vector; - } - } - - return vq; - -err_assign_vector: - if (!vp_dev->notify_base) - pci_iounmap(vp_dev->pci_dev, (void __iomem __force *)vq->priv); -err_map_notify: - vring_del_virtqueue(vq); -err_new_queue: - free_pages_exact(info->queue, vring_pci_size(info->num)); - return ERR_PTR(err); -} - -static int vp_modern_find_vqs(struct virtio_device *vdev, unsigned nvqs, - struct virtqueue *vqs[], - vq_callback_t *callbacks[], - const char *names[]) -{ - struct virtio_pci_device *vp_dev = to_vp_device(vdev); - struct virtqueue *vq; - int rc = vp_find_vqs(vdev, nvqs, vqs, callbacks, names); - - if (rc) - return rc; - - /* Select and activate all queues. Has to be done last: once we do - * this, there's no way to go back except reset. - */ - list_for_each_entry(vq, &vdev->vqs, list) { - vp_iowrite16(vq->index, &vp_dev->common->queue_select); - vp_iowrite16(1, &vp_dev->common->queue_enable); - } - - return 0; -} - -static void del_vq(struct virtio_pci_vq_info *info) -{ - struct virtqueue *vq = info->vq; - struct virtio_pci_device *vp_dev = to_vp_device(vq->vdev); - - vp_iowrite16(vq->index, &vp_dev->common->queue_select); - - if (vp_dev->msix_enabled) { - vp_iowrite16(VIRTIO_MSI_NO_VECTOR, - &vp_dev->common->queue_msix_vector); - /* Flush the write out to device */ - vp_ioread16(&vp_dev->common->queue_msix_vector); - } - - if (!vp_dev->notify_base) - pci_iounmap(vp_dev->pci_dev, (void __force __iomem *)vq->priv); - - vring_del_virtqueue(vq); - - free_pages_exact(info->queue, vring_pci_size(info->num)); -} - -static const struct virtio_config_ops virtio_pci_config_nodev_ops = { - .get = NULL, - .set = NULL, - .generation = vp_generation, - .get_status = vp_get_status, - .set_status = vp_set_status, - .reset = vp_reset, - .find_vqs = vp_modern_find_vqs, - .del_vqs = vp_del_vqs, - .get_features = vp_get_features, - .finalize_features = vp_finalize_features, - .bus_name = vp_bus_name, - .set_vq_affinity = vp_set_vq_affinity, -}; - -static const struct virtio_config_ops virtio_pci_config_ops = { - .get = vp_get, - .set = vp_set, - .generation = vp_generation, - .get_status = vp_get_status, - .set_status = vp_set_status, - .reset = vp_reset, - .find_vqs = vp_modern_find_vqs, - .del_vqs = vp_del_vqs, - .get_features = vp_get_features, - .finalize_features = vp_finalize_features, - .bus_name = vp_bus_name, - .set_vq_affinity = vp_set_vq_affinity, -}; - -/** - * virtio_pci_find_capability - walk capabilities to find device info. - * @dev: the pci device - * @cfg_type: the VIRTIO_PCI_CAP_* value we seek - * @ioresource_types: IORESOURCE_MEM and/or IORESOURCE_IO. - * - * Returns offset of the capability, or 0. - */ -static inline int virtio_pci_find_capability(struct pci_dev *dev, u8 cfg_type, - u32 ioresource_types, int *bars) -{ - int pos; - - for (pos = pci_find_capability(dev, PCI_CAP_ID_VNDR); - pos > 0; - pos = pci_find_next_capability(dev, pos, PCI_CAP_ID_VNDR)) { - u8 type, bar; - pci_read_config_byte(dev, pos + offsetof(struct virtio_pci_cap, - cfg_type), - &type); - pci_read_config_byte(dev, pos + offsetof(struct virtio_pci_cap, - bar), - &bar); - - /* Ignore structures with reserved BAR values */ - if (bar > 0x5) - continue; - - if (type == cfg_type) { - if (pci_resource_len(dev, bar) && - pci_resource_flags(dev, bar) & ioresource_types) { - *bars |= (1 << bar); - return pos; - } - } - } - return 0; -} - -/* This is part of the ABI. Don't screw with it. */ -static inline void check_offsets(void) -{ - /* Note: disk space was harmed in compilation of this function. */ - BUILD_BUG_ON(VIRTIO_PCI_CAP_VNDR != - offsetof(struct virtio_pci_cap, cap_vndr)); - BUILD_BUG_ON(VIRTIO_PCI_CAP_NEXT != - offsetof(struct virtio_pci_cap, cap_next)); - BUILD_BUG_ON(VIRTIO_PCI_CAP_LEN != - offsetof(struct virtio_pci_cap, cap_len)); - BUILD_BUG_ON(VIRTIO_PCI_CAP_CFG_TYPE != - offsetof(struct virtio_pci_cap, cfg_type)); - BUILD_BUG_ON(VIRTIO_PCI_CAP_BAR != - offsetof(struct virtio_pci_cap, bar)); - BUILD_BUG_ON(VIRTIO_PCI_CAP_OFFSET != - offsetof(struct virtio_pci_cap, offset)); - BUILD_BUG_ON(VIRTIO_PCI_CAP_LENGTH != - offsetof(struct virtio_pci_cap, length)); - BUILD_BUG_ON(VIRTIO_PCI_NOTIFY_CAP_MULT != - offsetof(struct virtio_pci_notify_cap, - notify_off_multiplier)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_DFSELECT != - offsetof(struct virtio_pci_common_cfg, - device_feature_select)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_DF != - offsetof(struct virtio_pci_common_cfg, device_feature)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_GFSELECT != - offsetof(struct virtio_pci_common_cfg, - guest_feature_select)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_GF != - offsetof(struct virtio_pci_common_cfg, guest_feature)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_MSIX != - offsetof(struct virtio_pci_common_cfg, msix_config)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_NUMQ != - offsetof(struct virtio_pci_common_cfg, num_queues)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_STATUS != - offsetof(struct virtio_pci_common_cfg, device_status)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_CFGGENERATION != - offsetof(struct virtio_pci_common_cfg, config_generation)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_SELECT != - offsetof(struct virtio_pci_common_cfg, queue_select)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_SIZE != - offsetof(struct virtio_pci_common_cfg, queue_size)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_MSIX != - offsetof(struct virtio_pci_common_cfg, queue_msix_vector)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_ENABLE != - offsetof(struct virtio_pci_common_cfg, queue_enable)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_NOFF != - offsetof(struct virtio_pci_common_cfg, queue_notify_off)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_DESCLO != - offsetof(struct virtio_pci_common_cfg, queue_desc_lo)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_DESCHI != - offsetof(struct virtio_pci_common_cfg, queue_desc_hi)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_AVAILLO != - offsetof(struct virtio_pci_common_cfg, queue_avail_lo)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_AVAILHI != - offsetof(struct virtio_pci_common_cfg, queue_avail_hi)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_USEDLO != - offsetof(struct virtio_pci_common_cfg, queue_used_lo)); - BUILD_BUG_ON(VIRTIO_PCI_COMMON_Q_USEDHI != - offsetof(struct virtio_pci_common_cfg, queue_used_hi)); -} - -/* the PCI probing function */ -int virtio_pci_modern_probe(struct virtio_pci_device *vp_dev) -{ - struct pci_dev *pci_dev = vp_dev->pci_dev; - int err, common, isr, notify, device; - u32 notify_length; - u32 notify_offset; - - check_offsets(); - - /* We only own devices >= 0x1000 and <= 0x107f: leave the rest. */ - if (pci_dev->device < 0x1000 || pci_dev->device > 0x107f) - return -ENODEV; - - if (pci_dev->device < 0x1040) { - /* Transitional devices: use the PCI subsystem device id as - * virtio device id, same as legacy driver always did. - */ - vp_dev->vdev.id.device = pci_dev->subsystem_device; - } else { - /* Modern devices: simply use PCI device id, but start from 0x1040. */ - vp_dev->vdev.id.device = pci_dev->device - 0x1040; - } - vp_dev->vdev.id.vendor = pci_dev->subsystem_vendor; - - /* check for a common config: if not, use legacy mode (bar 0). */ - common = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_COMMON_CFG, - IORESOURCE_IO | IORESOURCE_MEM, - &vp_dev->modern_bars); - if (!common) { - dev_info(&pci_dev->dev, - "virtio_pci: leaving for legacy driver\n"); - return -ENODEV; - } - - /* If common is there, these should be too... */ - isr = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_ISR_CFG, - IORESOURCE_IO | IORESOURCE_MEM, - &vp_dev->modern_bars); - notify = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_NOTIFY_CFG, - IORESOURCE_IO | IORESOURCE_MEM, - &vp_dev->modern_bars); - if (!isr || !notify) { - dev_err(&pci_dev->dev, - "virtio_pci: missing capabilities %i/%i/%i\n", - common, isr, notify); - return -EINVAL; - } - - /* Device capability is only mandatory for devices that have - * device-specific configuration. - */ - device = virtio_pci_find_capability(pci_dev, VIRTIO_PCI_CAP_DEVICE_CFG, - IORESOURCE_IO | IORESOURCE_MEM, - &vp_dev->modern_bars); - - err = pci_request_selected_regions(pci_dev, vp_dev->modern_bars, - "virtio-pci-modern"); - if (err) - return err; - - err = -EINVAL; - vp_dev->common = map_capability(pci_dev, common, - sizeof(struct virtio_pci_common_cfg), 4, - 0, sizeof(struct virtio_pci_common_cfg), - NULL); - if (!vp_dev->common) - goto err_map_common; - vp_dev->isr = map_capability(pci_dev, isr, sizeof(u8), 1, - 0, 1, - NULL); - if (!vp_dev->isr) - goto err_map_isr; - - /* Read notify_off_multiplier from config space. */ - pci_read_config_dword(pci_dev, - notify + offsetof(struct virtio_pci_notify_cap, - notify_off_multiplier), - &vp_dev->notify_offset_multiplier); - /* Read notify length and offset from config space. */ - pci_read_config_dword(pci_dev, - notify + offsetof(struct virtio_pci_notify_cap, - cap.length), - ¬ify_length); - - pci_read_config_dword(pci_dev, - notify + offsetof(struct virtio_pci_notify_cap, - cap.length), - ¬ify_offset); - - /* We don't know how many VQs we'll map, ahead of the time. - * If notify length is small, map it all now. - * Otherwise, map each VQ individually later. - */ - if ((u64)notify_length + (notify_offset % PAGE_SIZE) <= PAGE_SIZE) { - vp_dev->notify_base = map_capability(pci_dev, notify, 2, 2, - 0, notify_length, - &vp_dev->notify_len); - if (!vp_dev->notify_base) - goto err_map_notify; - } else { - vp_dev->notify_map_cap = notify; - } - - /* Again, we don't know how much we should map, but PAGE_SIZE - * is more than enough for all existing devices. - */ - if (device) { - vp_dev->device = map_capability(pci_dev, device, 0, 4, - 0, PAGE_SIZE, - &vp_dev->device_len); - if (!vp_dev->device) - goto err_map_device; - - vp_dev->vdev.config = &virtio_pci_config_ops; - } else { - vp_dev->vdev.config = &virtio_pci_config_nodev_ops; - } - - vp_dev->config_vector = vp_config_vector; - vp_dev->setup_vq = setup_vq; - vp_dev->del_vq = del_vq; - - return 0; - -err_map_device: - if (vp_dev->notify_base) - pci_iounmap(pci_dev, vp_dev->notify_base); -err_map_notify: - pci_iounmap(pci_dev, vp_dev->isr); -err_map_isr: - pci_iounmap(pci_dev, vp_dev->common); -err_map_common: - return err; -} - -void virtio_pci_modern_remove(struct virtio_pci_device *vp_dev) -{ - struct pci_dev *pci_dev = vp_dev->pci_dev; - - if (vp_dev->device) - pci_iounmap(pci_dev, vp_dev->device); - if (vp_dev->notify_base) - pci_iounmap(pci_dev, vp_dev->notify_base); - pci_iounmap(pci_dev, vp_dev->isr); - pci_iounmap(pci_dev, vp_dev->common); - pci_release_selected_regions(pci_dev, vp_dev->modern_bars); -} diff --git a/addons/virtio/src/4.4.180/virtio_ring.c b/addons/virtio/src/4.4.180/virtio_ring.c deleted file mode 100644 index a01a41a4..00000000 --- a/addons/virtio/src/4.4.180/virtio_ring.c +++ /dev/null @@ -1,875 +0,0 @@ -/* Virtio ring implementation. - * - * Copyright 2007 Rusty Russell IBM Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - */ -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef DEBUG -/* For development, we want to crash whenever the ring is screwed. */ -#define BAD_RING(_vq, fmt, args...) \ - do { \ - dev_err(&(_vq)->vq.vdev->dev, \ - "%s:"fmt, (_vq)->vq.name, ##args); \ - BUG(); \ - } while (0) -/* Caller is supposed to guarantee no reentry. */ -#define START_USE(_vq) \ - do { \ - if ((_vq)->in_use) \ - panic("%s:in_use = %i\n", \ - (_vq)->vq.name, (_vq)->in_use); \ - (_vq)->in_use = __LINE__; \ - } while (0) -#define END_USE(_vq) \ - do { BUG_ON(!(_vq)->in_use); (_vq)->in_use = 0; } while(0) -#else -#define BAD_RING(_vq, fmt, args...) \ - do { \ - dev_err(&_vq->vq.vdev->dev, \ - "%s:"fmt, (_vq)->vq.name, ##args); \ - (_vq)->broken = true; \ - } while (0) -#define START_USE(vq) -#define END_USE(vq) -#endif - -struct vring_virtqueue { - struct virtqueue vq; - - /* Actual memory layout for this queue */ - struct vring vring; - - /* Can we use weak barriers? */ - bool weak_barriers; - - /* Other side has made a mess, don't try any more. */ - bool broken; - - /* Host supports indirect buffers */ - bool indirect; - - /* Host publishes avail event idx */ - bool event; - - /* Head of free buffer list. */ - unsigned int free_head; - /* Number we've added since last sync. */ - unsigned int num_added; - - /* Last used index we've seen. */ - u16 last_used_idx; - - /* Last written value to avail->flags */ - u16 avail_flags_shadow; - - /* Last written value to avail->idx in guest byte order */ - u16 avail_idx_shadow; - - /* How to notify other side. FIXME: commonalize hcalls! */ - bool (*notify)(struct virtqueue *vq); - -#ifdef DEBUG - /* They're supposed to lock for us. */ - unsigned int in_use; - - /* Figure out if their kicks are too delayed. */ - bool last_add_time_valid; - ktime_t last_add_time; -#endif - - /* Tokens for callbacks. */ - void *data[]; -}; - -#define to_vvq(_vq) container_of(_vq, struct vring_virtqueue, vq) - -static struct vring_desc *alloc_indirect(struct virtqueue *_vq, - unsigned int total_sg, gfp_t gfp) -{ - struct vring_desc *desc; - unsigned int i; - - /* - * We require lowmem mappings for the descriptors because - * otherwise virt_to_phys will give us bogus addresses in the - * virtqueue. - */ - gfp &= ~__GFP_HIGHMEM; - - desc = kmalloc(total_sg * sizeof(struct vring_desc), gfp); - if (!desc) - return NULL; - - for (i = 0; i < total_sg; i++) - desc[i].next = cpu_to_virtio16(_vq->vdev, i + 1); - return desc; -} - -static inline int virtqueue_add(struct virtqueue *_vq, - struct scatterlist *sgs[], - unsigned int total_sg, - unsigned int out_sgs, - unsigned int in_sgs, - void *data, - gfp_t gfp) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - struct scatterlist *sg; - struct vring_desc *desc; - unsigned int i, n, avail, descs_used, uninitialized_var(prev); - int head; - bool indirect; - - START_USE(vq); - - BUG_ON(data == NULL); - - if (unlikely(vq->broken)) { - END_USE(vq); - return -EIO; - } - -#ifdef DEBUG - { - ktime_t now = ktime_get(); - - /* No kick or get, with .1 second between? Warn. */ - if (vq->last_add_time_valid) - WARN_ON(ktime_to_ms(ktime_sub(now, vq->last_add_time)) - > 100); - vq->last_add_time = now; - vq->last_add_time_valid = true; - } -#endif - - BUG_ON(total_sg > vq->vring.num); - BUG_ON(total_sg == 0); - - head = vq->free_head; - - /* If the host supports indirect descriptor tables, and we have multiple - * buffers, then go indirect. FIXME: tune this threshold */ - if (vq->indirect && total_sg > 1 && vq->vq.num_free) - desc = alloc_indirect(_vq, total_sg, gfp); - else - desc = NULL; - - if (desc) { - /* Use a single buffer which doesn't continue */ - vq->vring.desc[head].flags = cpu_to_virtio16(_vq->vdev, VRING_DESC_F_INDIRECT); - vq->vring.desc[head].addr = cpu_to_virtio64(_vq->vdev, virt_to_phys(desc)); - /* avoid kmemleak false positive (hidden by virt_to_phys) */ - kmemleak_ignore(desc); - vq->vring.desc[head].len = cpu_to_virtio32(_vq->vdev, total_sg * sizeof(struct vring_desc)); - - /* Set up rest to use this indirect table. */ - i = 0; - descs_used = 1; - indirect = true; - } else { - desc = vq->vring.desc; - i = head; - descs_used = total_sg; - indirect = false; - } - - if (vq->vq.num_free < descs_used) { - pr_debug("Can't add buf len %i - avail = %i\n", - descs_used, vq->vq.num_free); - /* FIXME: for historical reasons, we force a notify here if - * there are outgoing parts to the buffer. Presumably the - * host should service the ring ASAP. */ - if (out_sgs) - vq->notify(&vq->vq); - if (indirect) - kfree(desc); - END_USE(vq); - return -ENOSPC; - } - - /* We're about to use some buffers from the free list. */ - vq->vq.num_free -= descs_used; - - for (n = 0; n < out_sgs; n++) { - for (sg = sgs[n]; sg; sg = sg_next(sg)) { - desc[i].flags = cpu_to_virtio16(_vq->vdev, VRING_DESC_F_NEXT); - desc[i].addr = cpu_to_virtio64(_vq->vdev, sg_phys(sg)); - desc[i].len = cpu_to_virtio32(_vq->vdev, sg->length); - prev = i; - i = virtio16_to_cpu(_vq->vdev, desc[i].next); - } - } - for (; n < (out_sgs + in_sgs); n++) { - for (sg = sgs[n]; sg; sg = sg_next(sg)) { - desc[i].flags = cpu_to_virtio16(_vq->vdev, VRING_DESC_F_NEXT | VRING_DESC_F_WRITE); - desc[i].addr = cpu_to_virtio64(_vq->vdev, sg_phys(sg)); - desc[i].len = cpu_to_virtio32(_vq->vdev, sg->length); - prev = i; - i = virtio16_to_cpu(_vq->vdev, desc[i].next); - } - } - /* Last one doesn't continue. */ - desc[prev].flags &= cpu_to_virtio16(_vq->vdev, ~VRING_DESC_F_NEXT); - - /* Update free pointer */ - if (indirect) - vq->free_head = virtio16_to_cpu(_vq->vdev, vq->vring.desc[head].next); - else - vq->free_head = i; - - /* Set token. */ - vq->data[head] = data; - - /* Put entry in available array (but don't update avail->idx until they - * do sync). */ - avail = vq->avail_idx_shadow & (vq->vring.num - 1); - vq->vring.avail->ring[avail] = cpu_to_virtio16(_vq->vdev, head); - - /* Descriptors and available array need to be set before we expose the - * new available array entries. */ - virtio_wmb(vq->weak_barriers); - vq->avail_idx_shadow++; - vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, vq->avail_idx_shadow); - vq->num_added++; - - pr_debug("Added buffer head %i to %p\n", head, vq); - END_USE(vq); - - /* This is very unlikely, but theoretically possible. Kick - * just in case. */ - if (unlikely(vq->num_added == (1 << 16) - 1)) - virtqueue_kick(_vq); - - return 0; -} - -/** - * virtqueue_add_sgs - expose buffers to other end - * @vq: the struct virtqueue we're talking about. - * @sgs: array of terminated scatterlists. - * @out_num: the number of scatterlists readable by other side - * @in_num: the number of scatterlists which are writable (after readable ones) - * @data: the token identifying the buffer. - * @gfp: how to do memory allocations (if necessary). - * - * Caller must ensure we don't call this with other virtqueue operations - * at the same time (except where noted). - * - * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO). - */ -int virtqueue_add_sgs(struct virtqueue *_vq, - struct scatterlist *sgs[], - unsigned int out_sgs, - unsigned int in_sgs, - void *data, - gfp_t gfp) -{ - unsigned int i, total_sg = 0; - - /* Count them first. */ - for (i = 0; i < out_sgs + in_sgs; i++) { - struct scatterlist *sg; - for (sg = sgs[i]; sg; sg = sg_next(sg)) - total_sg++; - } - return virtqueue_add(_vq, sgs, total_sg, out_sgs, in_sgs, data, gfp); -} -EXPORT_SYMBOL_GPL(virtqueue_add_sgs); - -/** - * virtqueue_add_outbuf - expose output buffers to other end - * @vq: the struct virtqueue we're talking about. - * @sg: scatterlist (must be well-formed and terminated!) - * @num: the number of entries in @sg readable by other side - * @data: the token identifying the buffer. - * @gfp: how to do memory allocations (if necessary). - * - * Caller must ensure we don't call this with other virtqueue operations - * at the same time (except where noted). - * - * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO). - */ -int virtqueue_add_outbuf(struct virtqueue *vq, - struct scatterlist *sg, unsigned int num, - void *data, - gfp_t gfp) -{ - return virtqueue_add(vq, &sg, num, 1, 0, data, gfp); -} -EXPORT_SYMBOL_GPL(virtqueue_add_outbuf); - -/** - * virtqueue_add_inbuf - expose input buffers to other end - * @vq: the struct virtqueue we're talking about. - * @sg: scatterlist (must be well-formed and terminated!) - * @num: the number of entries in @sg writable by other side - * @data: the token identifying the buffer. - * @gfp: how to do memory allocations (if necessary). - * - * Caller must ensure we don't call this with other virtqueue operations - * at the same time (except where noted). - * - * Returns zero or a negative error (ie. ENOSPC, ENOMEM, EIO). - */ -int virtqueue_add_inbuf(struct virtqueue *vq, - struct scatterlist *sg, unsigned int num, - void *data, - gfp_t gfp) -{ - return virtqueue_add(vq, &sg, num, 0, 1, data, gfp); -} -EXPORT_SYMBOL_GPL(virtqueue_add_inbuf); - -/** - * virtqueue_kick_prepare - first half of split virtqueue_kick call. - * @vq: the struct virtqueue - * - * Instead of virtqueue_kick(), you can do: - * if (virtqueue_kick_prepare(vq)) - * virtqueue_notify(vq); - * - * This is sometimes useful because the virtqueue_kick_prepare() needs - * to be serialized, but the actual virtqueue_notify() call does not. - */ -bool virtqueue_kick_prepare(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - u16 new, old; - bool needs_kick; - - START_USE(vq); - /* We need to expose available array entries before checking avail - * event. */ - virtio_mb(vq->weak_barriers); - - old = vq->avail_idx_shadow - vq->num_added; - new = vq->avail_idx_shadow; - vq->num_added = 0; - -#ifdef DEBUG - if (vq->last_add_time_valid) { - WARN_ON(ktime_to_ms(ktime_sub(ktime_get(), - vq->last_add_time)) > 100); - } - vq->last_add_time_valid = false; -#endif - - if (vq->event) { - needs_kick = vring_need_event(virtio16_to_cpu(_vq->vdev, vring_avail_event(&vq->vring)), - new, old); - } else { - needs_kick = !(vq->vring.used->flags & cpu_to_virtio16(_vq->vdev, VRING_USED_F_NO_NOTIFY)); - } - END_USE(vq); - return needs_kick; -} -EXPORT_SYMBOL_GPL(virtqueue_kick_prepare); - -/** - * virtqueue_notify - second half of split virtqueue_kick call. - * @vq: the struct virtqueue - * - * This does not need to be serialized. - * - * Returns false if host notify failed or queue is broken, otherwise true. - */ -bool virtqueue_notify(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - - if (unlikely(vq->broken)) - return false; - - /* Prod other side to tell it about changes. */ - if (!vq->notify(_vq)) { - vq->broken = true; - return false; - } - return true; -} -EXPORT_SYMBOL_GPL(virtqueue_notify); - -/** - * virtqueue_kick - update after add_buf - * @vq: the struct virtqueue - * - * After one or more virtqueue_add_* calls, invoke this to kick - * the other side. - * - * Caller must ensure we don't call this with other virtqueue - * operations at the same time (except where noted). - * - * Returns false if kick failed, otherwise true. - */ -bool virtqueue_kick(struct virtqueue *vq) -{ - if (virtqueue_kick_prepare(vq)) - return virtqueue_notify(vq); - return true; -} -EXPORT_SYMBOL_GPL(virtqueue_kick); - -static void detach_buf(struct vring_virtqueue *vq, unsigned int head) -{ - unsigned int i; - - /* Clear data ptr. */ - vq->data[head] = NULL; - - /* Put back on free list: find end */ - i = head; - - /* Free the indirect table */ - if (vq->vring.desc[i].flags & cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_INDIRECT)) - kfree(phys_to_virt(virtio64_to_cpu(vq->vq.vdev, vq->vring.desc[i].addr))); - - while (vq->vring.desc[i].flags & cpu_to_virtio16(vq->vq.vdev, VRING_DESC_F_NEXT)) { - i = virtio16_to_cpu(vq->vq.vdev, vq->vring.desc[i].next); - vq->vq.num_free++; - } - - vq->vring.desc[i].next = cpu_to_virtio16(vq->vq.vdev, vq->free_head); - vq->free_head = head; - /* Plus final descriptor */ - vq->vq.num_free++; -} - -static inline bool more_used(const struct vring_virtqueue *vq) -{ - return vq->last_used_idx != virtio16_to_cpu(vq->vq.vdev, vq->vring.used->idx); -} - -/** - * virtqueue_get_buf - get the next used buffer - * @vq: the struct virtqueue we're talking about. - * @len: the length written into the buffer - * - * If the driver wrote data into the buffer, @len will be set to the - * amount written. This means you don't need to clear the buffer - * beforehand to ensure there's no data leakage in the case of short - * writes. - * - * Caller must ensure we don't call this with other virtqueue - * operations at the same time (except where noted). - * - * Returns NULL if there are no used buffers, or the "data" token - * handed to virtqueue_add_*(). - */ -void *virtqueue_get_buf(struct virtqueue *_vq, unsigned int *len) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - void *ret; - unsigned int i; - u16 last_used; - - START_USE(vq); - - if (unlikely(vq->broken)) { - END_USE(vq); - return NULL; - } - - if (!more_used(vq)) { - pr_debug("No more buffers in queue\n"); - END_USE(vq); - return NULL; - } - - /* Only get used array entries after they have been exposed by host. */ - virtio_rmb(vq->weak_barriers); - - last_used = (vq->last_used_idx & (vq->vring.num - 1)); - i = virtio32_to_cpu(_vq->vdev, vq->vring.used->ring[last_used].id); - *len = virtio32_to_cpu(_vq->vdev, vq->vring.used->ring[last_used].len); - - if (unlikely(i >= vq->vring.num)) { - BAD_RING(vq, "id %u out of range\n", i); - return NULL; - } - if (unlikely(!vq->data[i])) { - BAD_RING(vq, "id %u is not a head!\n", i); - return NULL; - } - - /* detach_buf clears data, so grab it now. */ - ret = vq->data[i]; - detach_buf(vq, i); - vq->last_used_idx++; - /* If we expect an interrupt for the next entry, tell host - * by writing event index and flush out the write before - * the read in the next get_buf call. */ - if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) { - vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, vq->last_used_idx); - virtio_mb(vq->weak_barriers); - } - -#ifdef DEBUG - vq->last_add_time_valid = false; -#endif - - END_USE(vq); - return ret; -} -EXPORT_SYMBOL_GPL(virtqueue_get_buf); - -/** - * virtqueue_disable_cb - disable callbacks - * @vq: the struct virtqueue we're talking about. - * - * Note that this is not necessarily synchronous, hence unreliable and only - * useful as an optimization. - * - * Unlike other operations, this need not be serialized. - */ -void virtqueue_disable_cb(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - - if (!(vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT)) { - vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; - if (!vq->event) - vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); - } - -} -EXPORT_SYMBOL_GPL(virtqueue_disable_cb); - -/** - * virtqueue_enable_cb_prepare - restart callbacks after disable_cb - * @vq: the struct virtqueue we're talking about. - * - * This re-enables callbacks; it returns current queue state - * in an opaque unsigned value. This value should be later tested by - * virtqueue_poll, to detect a possible race between the driver checking for - * more work, and enabling callbacks. - * - * Caller must ensure we don't call this with other virtqueue - * operations at the same time (except where noted). - */ -unsigned virtqueue_enable_cb_prepare(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - u16 last_used_idx; - - START_USE(vq); - - /* We optimistically turn back on interrupts, then check if there was - * more to do. */ - /* Depending on the VIRTIO_RING_F_EVENT_IDX feature, we need to - * either clear the flags bit or point the event index at the next - * entry. Always do both to keep code simple. */ - if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) { - vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; - if (!vq->event) - vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); - } - vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, last_used_idx = vq->last_used_idx); - END_USE(vq); - return last_used_idx; -} -EXPORT_SYMBOL_GPL(virtqueue_enable_cb_prepare); - -/** - * virtqueue_poll - query pending used buffers - * @vq: the struct virtqueue we're talking about. - * @last_used_idx: virtqueue state (from call to virtqueue_enable_cb_prepare). - * - * Returns "true" if there are pending used buffers in the queue. - * - * This does not need to be serialized. - */ -bool virtqueue_poll(struct virtqueue *_vq, unsigned last_used_idx) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - - virtio_mb(vq->weak_barriers); - return (u16)last_used_idx != virtio16_to_cpu(_vq->vdev, vq->vring.used->idx); -} -EXPORT_SYMBOL_GPL(virtqueue_poll); - -/** - * virtqueue_enable_cb - restart callbacks after disable_cb. - * @vq: the struct virtqueue we're talking about. - * - * This re-enables callbacks; it returns "false" if there are pending - * buffers in the queue, to detect a possible race between the driver - * checking for more work, and enabling callbacks. - * - * Caller must ensure we don't call this with other virtqueue - * operations at the same time (except where noted). - */ -bool virtqueue_enable_cb(struct virtqueue *_vq) -{ - unsigned last_used_idx = virtqueue_enable_cb_prepare(_vq); - return !virtqueue_poll(_vq, last_used_idx); -} -EXPORT_SYMBOL_GPL(virtqueue_enable_cb); - -/** - * virtqueue_enable_cb_delayed - restart callbacks after disable_cb. - * @vq: the struct virtqueue we're talking about. - * - * This re-enables callbacks but hints to the other side to delay - * interrupts until most of the available buffers have been processed; - * it returns "false" if there are many pending buffers in the queue, - * to detect a possible race between the driver checking for more work, - * and enabling callbacks. - * - * Caller must ensure we don't call this with other virtqueue - * operations at the same time (except where noted). - */ -bool virtqueue_enable_cb_delayed(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - u16 bufs; - - START_USE(vq); - - /* We optimistically turn back on interrupts, then check if there was - * more to do. */ - /* Depending on the VIRTIO_RING_F_USED_EVENT_IDX feature, we need to - * either clear the flags bit or point the event index at the next - * entry. Always update the event index to keep code simple. */ - if (vq->avail_flags_shadow & VRING_AVAIL_F_NO_INTERRUPT) { - vq->avail_flags_shadow &= ~VRING_AVAIL_F_NO_INTERRUPT; - if (!vq->event) - vq->vring.avail->flags = cpu_to_virtio16(_vq->vdev, vq->avail_flags_shadow); - } - /* TODO: tune this threshold */ - bufs = (u16)(vq->avail_idx_shadow - vq->last_used_idx) * 3 / 4; - vring_used_event(&vq->vring) = cpu_to_virtio16(_vq->vdev, vq->last_used_idx + bufs); - virtio_mb(vq->weak_barriers); - if (unlikely((u16)(virtio16_to_cpu(_vq->vdev, vq->vring.used->idx) - vq->last_used_idx) > bufs)) { - END_USE(vq); - return false; - } - - END_USE(vq); - return true; -} -EXPORT_SYMBOL_GPL(virtqueue_enable_cb_delayed); - -/** - * virtqueue_detach_unused_buf - detach first unused buffer - * @vq: the struct virtqueue we're talking about. - * - * Returns NULL or the "data" token handed to virtqueue_add_*(). - * This is not valid on an active queue; it is useful only for device - * shutdown. - */ -void *virtqueue_detach_unused_buf(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - unsigned int i; - void *buf; - - START_USE(vq); - - for (i = 0; i < vq->vring.num; i++) { - if (!vq->data[i]) - continue; - /* detach_buf clears data, so grab it now. */ - buf = vq->data[i]; - detach_buf(vq, i); - vq->avail_idx_shadow--; - vq->vring.avail->idx = cpu_to_virtio16(_vq->vdev, vq->avail_idx_shadow); - END_USE(vq); - return buf; - } - /* That should have freed everything. */ - BUG_ON(vq->vq.num_free != vq->vring.num); - - END_USE(vq); - return NULL; -} -EXPORT_SYMBOL_GPL(virtqueue_detach_unused_buf); - -irqreturn_t vring_interrupt(int irq, void *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - - if (!more_used(vq)) { - pr_debug("virtqueue interrupt with no work for %p\n", vq); - return IRQ_NONE; - } - - if (unlikely(vq->broken)) - return IRQ_HANDLED; - - pr_debug("virtqueue callback for %p (%p)\n", vq, vq->vq.callback); - if (vq->vq.callback) - vq->vq.callback(&vq->vq); - - return IRQ_HANDLED; -} -EXPORT_SYMBOL_GPL(vring_interrupt); - -struct virtqueue *vring_new_virtqueue(unsigned int index, - unsigned int num, - unsigned int vring_align, - struct virtio_device *vdev, - bool weak_barriers, - void *pages, - bool (*notify)(struct virtqueue *), - void (*callback)(struct virtqueue *), - const char *name) -{ - struct vring_virtqueue *vq; - unsigned int i; - - /* We assume num is a power of 2. */ - if (num & (num - 1)) { - dev_warn(&vdev->dev, "Bad virtqueue length %u\n", num); - return NULL; - } - - vq = kmalloc(sizeof(*vq) + sizeof(void *)*num, GFP_KERNEL); - if (!vq) - return NULL; - - vring_init(&vq->vring, num, pages, vring_align); - vq->vq.callback = callback; - vq->vq.vdev = vdev; - vq->vq.name = name; - vq->vq.num_free = num; - vq->vq.index = index; - vq->notify = notify; - vq->weak_barriers = weak_barriers; - vq->broken = false; - vq->last_used_idx = 0; - vq->avail_flags_shadow = 0; - vq->avail_idx_shadow = 0; - vq->num_added = 0; - list_add_tail(&vq->vq.list, &vdev->vqs); -#ifdef DEBUG - vq->in_use = false; - vq->last_add_time_valid = false; -#endif - - vq->indirect = virtio_has_feature(vdev, VIRTIO_RING_F_INDIRECT_DESC); - vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX); - - /* No callback? Tell other side not to bother us. */ - if (!callback) { - vq->avail_flags_shadow |= VRING_AVAIL_F_NO_INTERRUPT; - if (!vq->event) - vq->vring.avail->flags = cpu_to_virtio16(vdev, vq->avail_flags_shadow); - } - - /* Put everything in free lists. */ - vq->free_head = 0; - for (i = 0; i < num-1; i++) { - vq->vring.desc[i].next = cpu_to_virtio16(vdev, i + 1); - vq->data[i] = NULL; - } - vq->data[i] = NULL; - - return &vq->vq; -} -EXPORT_SYMBOL_GPL(vring_new_virtqueue); - -void vring_del_virtqueue(struct virtqueue *vq) -{ - list_del(&vq->list); - kfree(to_vvq(vq)); -} -EXPORT_SYMBOL_GPL(vring_del_virtqueue); - -/* Manipulates transport-specific feature bits. */ -void vring_transport_features(struct virtio_device *vdev) -{ - unsigned int i; - - for (i = VIRTIO_TRANSPORT_F_START; i < VIRTIO_TRANSPORT_F_END; i++) { - switch (i) { - case VIRTIO_RING_F_INDIRECT_DESC: - break; - case VIRTIO_RING_F_EVENT_IDX: - break; - case VIRTIO_F_VERSION_1: - break; - default: - /* We don't understand this bit. */ - __virtio_clear_bit(vdev, i); - } - } -} -EXPORT_SYMBOL_GPL(vring_transport_features); - -/** - * virtqueue_get_vring_size - return the size of the virtqueue's vring - * @vq: the struct virtqueue containing the vring of interest. - * - * Returns the size of the vring. This is mainly used for boasting to - * userspace. Unlike other operations, this need not be serialized. - */ -unsigned int virtqueue_get_vring_size(struct virtqueue *_vq) -{ - - struct vring_virtqueue *vq = to_vvq(_vq); - - return vq->vring.num; -} -EXPORT_SYMBOL_GPL(virtqueue_get_vring_size); - -bool virtqueue_is_broken(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - - return vq->broken; -} -EXPORT_SYMBOL_GPL(virtqueue_is_broken); - -/* - * This should prevent the device from being used, allowing drivers to - * recover. You may need to grab appropriate locks to flush. - */ -void virtio_break_device(struct virtio_device *dev) -{ - struct virtqueue *_vq; - - list_for_each_entry(_vq, &dev->vqs, list) { - struct vring_virtqueue *vq = to_vvq(_vq); - vq->broken = true; - } -} -EXPORT_SYMBOL_GPL(virtio_break_device); - -void *virtqueue_get_avail(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - - return vq->vring.avail; -} -EXPORT_SYMBOL_GPL(virtqueue_get_avail); - -void *virtqueue_get_used(struct virtqueue *_vq) -{ - struct vring_virtqueue *vq = to_vvq(_vq); - - return vq->vring.used; -} -EXPORT_SYMBOL_GPL(virtqueue_get_used); - -MODULE_LICENSE("GPL"); diff --git a/addons/virtio/src/4.4.180/virtio_scsi.c b/addons/virtio/src/4.4.180/virtio_scsi.c deleted file mode 100644 index 92374277..00000000 --- a/addons/virtio/src/4.4.180/virtio_scsi.c +++ /dev/null @@ -1,1200 +0,0 @@ -/* - * Virtio SCSI HBA driver - * - * Copyright IBM Corp. 2010 - * Copyright Red Hat, Inc. 2011 - * - * Authors: - * Stefan Hajnoczi - * Paolo Bonzini - * - * This work is licensed under the terms of the GNU GPL, version 2 or later. - * See the COPYING file in the top-level directory. - * - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define VIRTIO_SCSI_MEMPOOL_SZ 64 -#define VIRTIO_SCSI_EVENT_LEN 8 -#define VIRTIO_SCSI_VQ_BASE 2 - -/* Command queue element */ -struct virtio_scsi_cmd { - struct scsi_cmnd *sc; - struct completion *comp; - union { - struct virtio_scsi_cmd_req cmd; - struct virtio_scsi_cmd_req_pi cmd_pi; - struct virtio_scsi_ctrl_tmf_req tmf; - struct virtio_scsi_ctrl_an_req an; - } req; - union { - struct virtio_scsi_cmd_resp cmd; - struct virtio_scsi_ctrl_tmf_resp tmf; - struct virtio_scsi_ctrl_an_resp an; - struct virtio_scsi_event evt; - } resp; -} ____cacheline_aligned_in_smp; - -struct virtio_scsi_event_node { - struct virtio_scsi *vscsi; - struct virtio_scsi_event event; - struct work_struct work; -}; - -struct virtio_scsi_vq { - /* Protects vq */ - spinlock_t vq_lock; - - struct virtqueue *vq; -}; - -/* - * Per-target queue state. - * - * This struct holds the data needed by the queue steering policy. When a - * target is sent multiple requests, we need to drive them to the same queue so - * that FIFO processing order is kept. However, if a target was idle, we can - * choose a queue arbitrarily. In this case the queue is chosen according to - * the current VCPU, so the driver expects the number of request queues to be - * equal to the number of VCPUs. This makes it easy and fast to select the - * queue, and also lets the driver optimize the IRQ affinity for the virtqueues - * (each virtqueue's affinity is set to the CPU that "owns" the queue). - * - * tgt_seq is held to serialize reading and writing req_vq. - * - * Decrements of reqs are never concurrent with writes of req_vq: before the - * decrement reqs will be != 0; after the decrement the virtqueue completion - * routine will not use the req_vq so it can be changed by a new request. - * Thus they can happen outside the tgt_seq, provided of course we make reqs - * an atomic_t. - */ -struct virtio_scsi_target_state { - seqcount_t tgt_seq; - - /* Count of outstanding requests. */ - atomic_t reqs; - - /* Currently active virtqueue for requests sent to this target. */ - struct virtio_scsi_vq *req_vq; -}; - -/* Driver instance state */ -struct virtio_scsi { - struct virtio_device *vdev; - - /* Get some buffers ready for event vq */ - struct virtio_scsi_event_node event_list[VIRTIO_SCSI_EVENT_LEN]; - - u32 num_queues; - - /* If the affinity hint is set for virtqueues */ - bool affinity_hint_set; - - /* CPU hotplug notifier */ - struct notifier_block nb; - - /* Protected by event_vq lock */ - bool stop_events; - - struct virtio_scsi_vq ctrl_vq; - struct virtio_scsi_vq event_vq; - struct virtio_scsi_vq req_vqs[]; -}; - -static struct kmem_cache *virtscsi_cmd_cache; -static mempool_t *virtscsi_cmd_pool; - -static inline struct Scsi_Host *virtio_scsi_host(struct virtio_device *vdev) -{ - return vdev->priv; -} - -static void virtscsi_compute_resid(struct scsi_cmnd *sc, u32 resid) -{ - if (!resid) - return; - - if (!scsi_bidi_cmnd(sc)) { - scsi_set_resid(sc, resid); - return; - } - - scsi_in(sc)->resid = min(resid, scsi_in(sc)->length); - scsi_out(sc)->resid = resid - scsi_in(sc)->resid; -} - -/** - * virtscsi_complete_cmd - finish a scsi_cmd and invoke scsi_done - * - * Called with vq_lock held. - */ -static void virtscsi_complete_cmd(struct virtio_scsi *vscsi, void *buf) -{ - struct virtio_scsi_cmd *cmd = buf; - struct scsi_cmnd *sc = cmd->sc; - struct virtio_scsi_cmd_resp *resp = &cmd->resp.cmd; - struct virtio_scsi_target_state *tgt = - scsi_target(sc->device)->hostdata; - - dev_dbg(&sc->device->sdev_gendev, - "cmd %p response %u status %#02x sense_len %u\n", - sc, resp->response, resp->status, resp->sense_len); - - sc->result = resp->status; - virtscsi_compute_resid(sc, virtio32_to_cpu(vscsi->vdev, resp->resid)); - switch (resp->response) { - case VIRTIO_SCSI_S_OK: - set_host_byte(sc, DID_OK); - break; - case VIRTIO_SCSI_S_OVERRUN: - set_host_byte(sc, DID_ERROR); - break; - case VIRTIO_SCSI_S_ABORTED: - set_host_byte(sc, DID_ABORT); - break; - case VIRTIO_SCSI_S_BAD_TARGET: - set_host_byte(sc, DID_BAD_TARGET); - break; - case VIRTIO_SCSI_S_RESET: - set_host_byte(sc, DID_RESET); - break; - case VIRTIO_SCSI_S_BUSY: - set_host_byte(sc, DID_BUS_BUSY); - break; - case VIRTIO_SCSI_S_TRANSPORT_FAILURE: - set_host_byte(sc, DID_TRANSPORT_DISRUPTED); - break; - case VIRTIO_SCSI_S_TARGET_FAILURE: - set_host_byte(sc, DID_TARGET_FAILURE); - break; - case VIRTIO_SCSI_S_NEXUS_FAILURE: - set_host_byte(sc, DID_NEXUS_FAILURE); - break; - default: - scmd_printk(KERN_WARNING, sc, "Unknown response %d", - resp->response); - /* fall through */ - case VIRTIO_SCSI_S_FAILURE: - set_host_byte(sc, DID_ERROR); - break; - } - - WARN_ON(virtio32_to_cpu(vscsi->vdev, resp->sense_len) > - VIRTIO_SCSI_SENSE_SIZE); - if (sc->sense_buffer) { - memcpy(sc->sense_buffer, resp->sense, - min_t(u32, - virtio32_to_cpu(vscsi->vdev, resp->sense_len), - VIRTIO_SCSI_SENSE_SIZE)); - if (resp->sense_len) - set_driver_byte(sc, DRIVER_SENSE); - } - - sc->scsi_done(sc); - - atomic_dec(&tgt->reqs); -} - -static void virtscsi_vq_done(struct virtio_scsi *vscsi, - struct virtio_scsi_vq *virtscsi_vq, - void (*fn)(struct virtio_scsi *vscsi, void *buf)) -{ - void *buf; - unsigned int len; - unsigned long flags; - struct virtqueue *vq = virtscsi_vq->vq; - - spin_lock_irqsave(&virtscsi_vq->vq_lock, flags); - do { - virtqueue_disable_cb(vq); - while ((buf = virtqueue_get_buf(vq, &len)) != NULL) - fn(vscsi, buf); - - if (unlikely(virtqueue_is_broken(vq))) - break; - } while (!virtqueue_enable_cb(vq)); - spin_unlock_irqrestore(&virtscsi_vq->vq_lock, flags); -} - -static void virtscsi_req_done(struct virtqueue *vq) -{ - struct Scsi_Host *sh = virtio_scsi_host(vq->vdev); - struct virtio_scsi *vscsi = shost_priv(sh); - int index = vq->index - VIRTIO_SCSI_VQ_BASE; - struct virtio_scsi_vq *req_vq = &vscsi->req_vqs[index]; - - virtscsi_vq_done(vscsi, req_vq, virtscsi_complete_cmd); -}; - -static void virtscsi_poll_requests(struct virtio_scsi *vscsi) -{ - int i, num_vqs; - - num_vqs = vscsi->num_queues; - for (i = 0; i < num_vqs; i++) - virtscsi_vq_done(vscsi, &vscsi->req_vqs[i], - virtscsi_complete_cmd); -} - -static void virtscsi_complete_free(struct virtio_scsi *vscsi, void *buf) -{ - struct virtio_scsi_cmd *cmd = buf; - - if (cmd->comp) - complete_all(cmd->comp); -} - -static void virtscsi_ctrl_done(struct virtqueue *vq) -{ - struct Scsi_Host *sh = virtio_scsi_host(vq->vdev); - struct virtio_scsi *vscsi = shost_priv(sh); - - virtscsi_vq_done(vscsi, &vscsi->ctrl_vq, virtscsi_complete_free); -}; - -static void virtscsi_handle_event(struct work_struct *work); - -static int virtscsi_kick_event(struct virtio_scsi *vscsi, - struct virtio_scsi_event_node *event_node) -{ - int err; - struct scatterlist sg; - unsigned long flags; - - INIT_WORK(&event_node->work, virtscsi_handle_event); - sg_init_one(&sg, &event_node->event, sizeof(struct virtio_scsi_event)); - - spin_lock_irqsave(&vscsi->event_vq.vq_lock, flags); - - err = virtqueue_add_inbuf(vscsi->event_vq.vq, &sg, 1, event_node, - GFP_ATOMIC); - if (!err) - virtqueue_kick(vscsi->event_vq.vq); - - spin_unlock_irqrestore(&vscsi->event_vq.vq_lock, flags); - - return err; -} - -static int virtscsi_kick_event_all(struct virtio_scsi *vscsi) -{ - int i; - - for (i = 0; i < VIRTIO_SCSI_EVENT_LEN; i++) { - vscsi->event_list[i].vscsi = vscsi; - virtscsi_kick_event(vscsi, &vscsi->event_list[i]); - } - - return 0; -} - -static void virtscsi_cancel_event_work(struct virtio_scsi *vscsi) -{ - int i; - - /* Stop scheduling work before calling cancel_work_sync. */ - spin_lock_irq(&vscsi->event_vq.vq_lock); - vscsi->stop_events = true; - spin_unlock_irq(&vscsi->event_vq.vq_lock); - - for (i = 0; i < VIRTIO_SCSI_EVENT_LEN; i++) - cancel_work_sync(&vscsi->event_list[i].work); -} - -static void virtscsi_handle_transport_reset(struct virtio_scsi *vscsi, - struct virtio_scsi_event *event) -{ - struct scsi_device *sdev; - struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); - unsigned int target = event->lun[1]; - unsigned int lun = (event->lun[2] << 8) | event->lun[3]; - - switch (virtio32_to_cpu(vscsi->vdev, event->reason)) { - case VIRTIO_SCSI_EVT_RESET_RESCAN: - scsi_add_device(shost, 0, target, lun); - break; - case VIRTIO_SCSI_EVT_RESET_REMOVED: - sdev = scsi_device_lookup(shost, 0, target, lun); - if (sdev) { - scsi_remove_device(sdev); - scsi_device_put(sdev); - } else { - pr_err("SCSI device %d 0 %d %d not found\n", - shost->host_no, target, lun); - } - break; - default: - pr_info("Unsupport virtio scsi event reason %x\n", event->reason); - } -} - -static void virtscsi_handle_param_change(struct virtio_scsi *vscsi, - struct virtio_scsi_event *event) -{ - struct scsi_device *sdev; - struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); - unsigned int target = event->lun[1]; - unsigned int lun = (event->lun[2] << 8) | event->lun[3]; - u8 asc = virtio32_to_cpu(vscsi->vdev, event->reason) & 255; - u8 ascq = virtio32_to_cpu(vscsi->vdev, event->reason) >> 8; - - sdev = scsi_device_lookup(shost, 0, target, lun); - if (!sdev) { - pr_err("SCSI device %d 0 %d %d not found\n", - shost->host_no, target, lun); - return; - } - - /* Handle "Parameters changed", "Mode parameters changed", and - "Capacity data has changed". */ - if (asc == 0x2a && (ascq == 0x00 || ascq == 0x01 || ascq == 0x09)) - scsi_rescan_device(&sdev->sdev_gendev); - - scsi_device_put(sdev); -} - -static void virtscsi_handle_event(struct work_struct *work) -{ - struct virtio_scsi_event_node *event_node = - container_of(work, struct virtio_scsi_event_node, work); - struct virtio_scsi *vscsi = event_node->vscsi; - struct virtio_scsi_event *event = &event_node->event; - - if (event->event & - cpu_to_virtio32(vscsi->vdev, VIRTIO_SCSI_T_EVENTS_MISSED)) { - event->event &= ~cpu_to_virtio32(vscsi->vdev, - VIRTIO_SCSI_T_EVENTS_MISSED); - scsi_scan_host(virtio_scsi_host(vscsi->vdev)); - } - - switch (virtio32_to_cpu(vscsi->vdev, event->event)) { - case VIRTIO_SCSI_T_NO_EVENT: - break; - case VIRTIO_SCSI_T_TRANSPORT_RESET: - virtscsi_handle_transport_reset(vscsi, event); - break; - case VIRTIO_SCSI_T_PARAM_CHANGE: - virtscsi_handle_param_change(vscsi, event); - break; - default: - pr_err("Unsupport virtio scsi event %x\n", event->event); - } - virtscsi_kick_event(vscsi, event_node); -} - -static void virtscsi_complete_event(struct virtio_scsi *vscsi, void *buf) -{ - struct virtio_scsi_event_node *event_node = buf; - - if (!vscsi->stop_events) - queue_work(system_freezable_wq, &event_node->work); -} - -static void virtscsi_event_done(struct virtqueue *vq) -{ - struct Scsi_Host *sh = virtio_scsi_host(vq->vdev); - struct virtio_scsi *vscsi = shost_priv(sh); - - virtscsi_vq_done(vscsi, &vscsi->event_vq, virtscsi_complete_event); -}; - -/** - * virtscsi_add_cmd - add a virtio_scsi_cmd to a virtqueue - * @vq : the struct virtqueue we're talking about - * @cmd : command structure - * @req_size : size of the request buffer - * @resp_size : size of the response buffer - */ -static int virtscsi_add_cmd(struct virtqueue *vq, - struct virtio_scsi_cmd *cmd, - size_t req_size, size_t resp_size) -{ - struct scsi_cmnd *sc = cmd->sc; - struct scatterlist *sgs[6], req, resp; - struct sg_table *out, *in; - unsigned out_num = 0, in_num = 0; - - out = in = NULL; - - if (sc && sc->sc_data_direction != DMA_NONE) { - if (sc->sc_data_direction != DMA_FROM_DEVICE) - out = &scsi_out(sc)->table; - if (sc->sc_data_direction != DMA_TO_DEVICE) - in = &scsi_in(sc)->table; - } - - /* Request header. */ - sg_init_one(&req, &cmd->req, req_size); - sgs[out_num++] = &req; - - /* Data-out buffer. */ - if (out) { - /* Place WRITE protection SGLs before Data OUT payload */ - if (scsi_prot_sg_count(sc)) - sgs[out_num++] = scsi_prot_sglist(sc); - sgs[out_num++] = out->sgl; - } - - /* Response header. */ - sg_init_one(&resp, &cmd->resp, resp_size); - sgs[out_num + in_num++] = &resp; - - /* Data-in buffer */ - if (in) { - /* Place READ protection SGLs before Data IN payload */ - if (scsi_prot_sg_count(sc)) - sgs[out_num + in_num++] = scsi_prot_sglist(sc); - sgs[out_num + in_num++] = in->sgl; - } - - return virtqueue_add_sgs(vq, sgs, out_num, in_num, cmd, GFP_ATOMIC); -} - -static int virtscsi_kick_cmd(struct virtio_scsi_vq *vq, - struct virtio_scsi_cmd *cmd, - size_t req_size, size_t resp_size) -{ - unsigned long flags; - int err; - bool needs_kick = false; - - spin_lock_irqsave(&vq->vq_lock, flags); - err = virtscsi_add_cmd(vq->vq, cmd, req_size, resp_size); - if (!err) - needs_kick = virtqueue_kick_prepare(vq->vq); - - spin_unlock_irqrestore(&vq->vq_lock, flags); - - if (needs_kick) - virtqueue_notify(vq->vq); - return err; -} - -static void virtio_scsi_init_hdr(struct virtio_device *vdev, - struct virtio_scsi_cmd_req *cmd, - struct scsi_cmnd *sc) -{ - cmd->lun[0] = 1; - cmd->lun[1] = sc->device->id; - cmd->lun[2] = (sc->device->lun >> 8) | 0x40; - cmd->lun[3] = sc->device->lun & 0xff; - cmd->tag = cpu_to_virtio64(vdev, (unsigned long)sc); - cmd->task_attr = VIRTIO_SCSI_S_SIMPLE; - cmd->prio = 0; - cmd->crn = 0; -} - -#ifdef CONFIG_BLK_DEV_INTEGRITY -static void virtio_scsi_init_hdr_pi(struct virtio_device *vdev, - struct virtio_scsi_cmd_req_pi *cmd_pi, - struct scsi_cmnd *sc) -{ - struct request *rq = sc->request; - struct blk_integrity *bi; - - virtio_scsi_init_hdr(vdev, (struct virtio_scsi_cmd_req *)cmd_pi, sc); - - if (!rq || !scsi_prot_sg_count(sc)) - return; - - bi = blk_get_integrity(rq->rq_disk); - - if (sc->sc_data_direction == DMA_TO_DEVICE) - cmd_pi->pi_bytesout = cpu_to_virtio32(vdev, - blk_rq_sectors(rq) * - bi->tuple_size); - else if (sc->sc_data_direction == DMA_FROM_DEVICE) - cmd_pi->pi_bytesin = cpu_to_virtio32(vdev, - blk_rq_sectors(rq) * - bi->tuple_size); -} -#endif - -static int virtscsi_queuecommand(struct virtio_scsi *vscsi, - struct virtio_scsi_vq *req_vq, - struct scsi_cmnd *sc) -{ - struct Scsi_Host *shost = virtio_scsi_host(vscsi->vdev); - struct virtio_scsi_cmd *cmd = scsi_cmd_priv(sc); - unsigned long flags; - int req_size; - int ret; - - BUG_ON(scsi_sg_count(sc) > shost->sg_tablesize); - - /* TODO: check feature bit and fail if unsupported? */ - BUG_ON(sc->sc_data_direction == DMA_BIDIRECTIONAL); - - dev_dbg(&sc->device->sdev_gendev, - "cmd %p CDB: %#02x\n", sc, sc->cmnd[0]); - - memset(cmd, 0, sizeof(*cmd)); - cmd->sc = sc; - - BUG_ON(sc->cmd_len > VIRTIO_SCSI_CDB_SIZE); - -#ifdef CONFIG_BLK_DEV_INTEGRITY - if (virtio_has_feature(vscsi->vdev, VIRTIO_SCSI_F_T10_PI)) { - virtio_scsi_init_hdr_pi(vscsi->vdev, &cmd->req.cmd_pi, sc); - memcpy(cmd->req.cmd_pi.cdb, sc->cmnd, sc->cmd_len); - req_size = sizeof(cmd->req.cmd_pi); - } else -#endif - { - virtio_scsi_init_hdr(vscsi->vdev, &cmd->req.cmd, sc); - memcpy(cmd->req.cmd.cdb, sc->cmnd, sc->cmd_len); - req_size = sizeof(cmd->req.cmd); - } - - ret = virtscsi_kick_cmd(req_vq, cmd, req_size, sizeof(cmd->resp.cmd)); - if (ret == -EIO) { - cmd->resp.cmd.response = VIRTIO_SCSI_S_BAD_TARGET; - spin_lock_irqsave(&req_vq->vq_lock, flags); - virtscsi_complete_cmd(vscsi, cmd); - spin_unlock_irqrestore(&req_vq->vq_lock, flags); - } else if (ret != 0) { - return SCSI_MLQUEUE_HOST_BUSY; - } - return 0; -} - -static int virtscsi_queuecommand_single(struct Scsi_Host *sh, - struct scsi_cmnd *sc) -{ - struct virtio_scsi *vscsi = shost_priv(sh); - struct virtio_scsi_target_state *tgt = - scsi_target(sc->device)->hostdata; - - atomic_inc(&tgt->reqs); - return virtscsi_queuecommand(vscsi, &vscsi->req_vqs[0], sc); -} - -static struct virtio_scsi_vq *virtscsi_pick_vq_mq(struct virtio_scsi *vscsi, - struct scsi_cmnd *sc) -{ - u32 tag = blk_mq_unique_tag(sc->request); - u16 hwq = blk_mq_unique_tag_to_hwq(tag); - - return &vscsi->req_vqs[hwq]; -} - -static struct virtio_scsi_vq *virtscsi_pick_vq(struct virtio_scsi *vscsi, - struct virtio_scsi_target_state *tgt) -{ - struct virtio_scsi_vq *vq; - unsigned long flags; - u32 queue_num; - - local_irq_save(flags); - if (atomic_inc_return(&tgt->reqs) > 1) { - unsigned long seq; - - do { - seq = read_seqcount_begin(&tgt->tgt_seq); - vq = tgt->req_vq; - } while (read_seqcount_retry(&tgt->tgt_seq, seq)); - } else { - /* no writes can be concurrent because of atomic_t */ - write_seqcount_begin(&tgt->tgt_seq); - - /* keep previous req_vq if a reader just arrived */ - if (unlikely(atomic_read(&tgt->reqs) > 1)) { - vq = tgt->req_vq; - goto unlock; - } - - queue_num = smp_processor_id(); - while (unlikely(queue_num >= vscsi->num_queues)) - queue_num -= vscsi->num_queues; - tgt->req_vq = vq = &vscsi->req_vqs[queue_num]; - unlock: - write_seqcount_end(&tgt->tgt_seq); - } - local_irq_restore(flags); - - return vq; -} - -static int virtscsi_queuecommand_multi(struct Scsi_Host *sh, - struct scsi_cmnd *sc) -{ - struct virtio_scsi *vscsi = shost_priv(sh); - struct virtio_scsi_target_state *tgt = - scsi_target(sc->device)->hostdata; - struct virtio_scsi_vq *req_vq; - - if (shost_use_blk_mq(sh)) - req_vq = virtscsi_pick_vq_mq(vscsi, sc); - else - req_vq = virtscsi_pick_vq(vscsi, tgt); - - return virtscsi_queuecommand(vscsi, req_vq, sc); -} - -static int virtscsi_tmf(struct virtio_scsi *vscsi, struct virtio_scsi_cmd *cmd) -{ - DECLARE_COMPLETION_ONSTACK(comp); - int ret = FAILED; - - cmd->comp = ∁ - if (virtscsi_kick_cmd(&vscsi->ctrl_vq, cmd, - sizeof cmd->req.tmf, sizeof cmd->resp.tmf) < 0) - goto out; - - wait_for_completion(&comp); - if (cmd->resp.tmf.response == VIRTIO_SCSI_S_OK || - cmd->resp.tmf.response == VIRTIO_SCSI_S_FUNCTION_SUCCEEDED) - ret = SUCCESS; - - /* - * The spec guarantees that all requests related to the TMF have - * been completed, but the callback might not have run yet if - * we're using independent interrupts (e.g. MSI). Poll the - * virtqueues once. - * - * In the abort case, sc->scsi_done will do nothing, because - * the block layer must have detected a timeout and as a result - * REQ_ATOM_COMPLETE has been set. - */ - virtscsi_poll_requests(vscsi); - -out: - mempool_free(cmd, virtscsi_cmd_pool); - return ret; -} - -static int virtscsi_device_reset(struct scsi_cmnd *sc) -{ - struct virtio_scsi *vscsi = shost_priv(sc->device->host); - struct virtio_scsi_cmd *cmd; - - sdev_printk(KERN_INFO, sc->device, "device reset\n"); - cmd = mempool_alloc(virtscsi_cmd_pool, GFP_NOIO); - if (!cmd) - return FAILED; - - memset(cmd, 0, sizeof(*cmd)); - cmd->req.tmf = (struct virtio_scsi_ctrl_tmf_req){ - .type = VIRTIO_SCSI_T_TMF, - .subtype = cpu_to_virtio32(vscsi->vdev, - VIRTIO_SCSI_T_TMF_LOGICAL_UNIT_RESET), - .lun[0] = 1, - .lun[1] = sc->device->id, - .lun[2] = (sc->device->lun >> 8) | 0x40, - .lun[3] = sc->device->lun & 0xff, - }; - return virtscsi_tmf(vscsi, cmd); -} - -static int virtscsi_device_alloc(struct scsi_device *sdevice) -{ - /* - * Passed through SCSI targets (e.g. with qemu's 'scsi-block') - * may have transfer limits which come from the host SCSI - * controller or something on the host side other than the - * target itself. - * - * To make this work properly, the hypervisor can adjust the - * target's VPD information to advertise these limits. But - * for that to work, the guest has to look at the VPD pages, - * which we won't do by default if it is an SPC-2 device, even - * if it does actually support it. - * - * So, set the blist to always try to read the VPD pages. - */ - sdevice->sdev_bflags = BLIST_TRY_VPD_PAGES; - - return 0; -} - - -/** - * virtscsi_change_queue_depth() - Change a virtscsi target's queue depth - * @sdev: Virtscsi target whose queue depth to change - * @qdepth: New queue depth - */ -static int virtscsi_change_queue_depth(struct scsi_device *sdev, int qdepth) -{ - struct Scsi_Host *shost = sdev->host; - int max_depth = shost->cmd_per_lun; - - return scsi_change_queue_depth(sdev, min(max_depth, qdepth)); -} - -static int virtscsi_abort(struct scsi_cmnd *sc) -{ - struct virtio_scsi *vscsi = shost_priv(sc->device->host); - struct virtio_scsi_cmd *cmd; - - scmd_printk(KERN_INFO, sc, "abort\n"); - cmd = mempool_alloc(virtscsi_cmd_pool, GFP_NOIO); - if (!cmd) - return FAILED; - - memset(cmd, 0, sizeof(*cmd)); - cmd->req.tmf = (struct virtio_scsi_ctrl_tmf_req){ - .type = VIRTIO_SCSI_T_TMF, - .subtype = VIRTIO_SCSI_T_TMF_ABORT_TASK, - .lun[0] = 1, - .lun[1] = sc->device->id, - .lun[2] = (sc->device->lun >> 8) | 0x40, - .lun[3] = sc->device->lun & 0xff, - .tag = cpu_to_virtio64(vscsi->vdev, (unsigned long)sc), - }; - return virtscsi_tmf(vscsi, cmd); -} - -static int virtscsi_target_alloc(struct scsi_target *starget) -{ - struct Scsi_Host *sh = dev_to_shost(starget->dev.parent); - struct virtio_scsi *vscsi = shost_priv(sh); - - struct virtio_scsi_target_state *tgt = - kmalloc(sizeof(*tgt), GFP_KERNEL); - if (!tgt) - return -ENOMEM; - - seqcount_init(&tgt->tgt_seq); - atomic_set(&tgt->reqs, 0); - tgt->req_vq = &vscsi->req_vqs[0]; - - starget->hostdata = tgt; - return 0; -} - -static void virtscsi_target_destroy(struct scsi_target *starget) -{ - struct virtio_scsi_target_state *tgt = starget->hostdata; - kfree(tgt); -} - -static struct scsi_host_template virtscsi_host_template_single = { - .module = THIS_MODULE, - .name = "Virtio SCSI HBA", - .proc_name = "virtio_scsi", - .this_id = -1, - .cmd_size = sizeof(struct virtio_scsi_cmd), - .queuecommand = virtscsi_queuecommand_single, - .change_queue_depth = virtscsi_change_queue_depth, - .eh_abort_handler = virtscsi_abort, - .eh_device_reset_handler = virtscsi_device_reset, - .slave_alloc = virtscsi_device_alloc, - - .can_queue = 1024, - .dma_boundary = UINT_MAX, - .use_clustering = ENABLE_CLUSTERING, - .target_alloc = virtscsi_target_alloc, - .target_destroy = virtscsi_target_destroy, - .track_queue_depth = 1, -}; - -static struct scsi_host_template virtscsi_host_template_multi = { - .module = THIS_MODULE, - .name = "Virtio SCSI HBA", - .proc_name = "virtio_scsi", - .this_id = -1, - .cmd_size = sizeof(struct virtio_scsi_cmd), - .queuecommand = virtscsi_queuecommand_multi, - .change_queue_depth = virtscsi_change_queue_depth, - .eh_abort_handler = virtscsi_abort, - .eh_device_reset_handler = virtscsi_device_reset, - - .slave_alloc = virtscsi_device_alloc, - .can_queue = 1024, - .dma_boundary = UINT_MAX, - .use_clustering = ENABLE_CLUSTERING, - .target_alloc = virtscsi_target_alloc, - .target_destroy = virtscsi_target_destroy, - .track_queue_depth = 1, -}; - -#define virtscsi_config_get(vdev, fld) \ - ({ \ - typeof(((struct virtio_scsi_config *)0)->fld) __val; \ - virtio_cread(vdev, struct virtio_scsi_config, fld, &__val); \ - __val; \ - }) - -#define virtscsi_config_set(vdev, fld, val) \ - do { \ - typeof(((struct virtio_scsi_config *)0)->fld) __val = (val); \ - virtio_cwrite(vdev, struct virtio_scsi_config, fld, &__val); \ - } while(0) - -static void __virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) -{ - int i; - int cpu; - - /* In multiqueue mode, when the number of cpu is equal - * to the number of request queues, we let the qeueues - * to be private to one cpu by setting the affinity hint - * to eliminate the contention. - */ - if ((vscsi->num_queues == 1 || - vscsi->num_queues != num_online_cpus()) && affinity) { - if (vscsi->affinity_hint_set) - affinity = false; - else - return; - } - - if (affinity) { - i = 0; - for_each_online_cpu(cpu) { - virtqueue_set_affinity(vscsi->req_vqs[i].vq, cpu); - i++; - } - - vscsi->affinity_hint_set = true; - } else { - for (i = 0; i < vscsi->num_queues; i++) { - if (!vscsi->req_vqs[i].vq) - continue; - - virtqueue_set_affinity(vscsi->req_vqs[i].vq, -1); - } - - vscsi->affinity_hint_set = false; - } -} - -static void virtscsi_set_affinity(struct virtio_scsi *vscsi, bool affinity) -{ - get_online_cpus(); - __virtscsi_set_affinity(vscsi, affinity); - put_online_cpus(); -} - -static int virtscsi_cpu_callback(struct notifier_block *nfb, - unsigned long action, void *hcpu) -{ - struct virtio_scsi *vscsi = container_of(nfb, struct virtio_scsi, nb); - switch(action) { - case CPU_ONLINE: - case CPU_ONLINE_FROZEN: - case CPU_DEAD: - case CPU_DEAD_FROZEN: - __virtscsi_set_affinity(vscsi, true); - break; - default: - break; - } - return NOTIFY_OK; -} - -static void virtscsi_init_vq(struct virtio_scsi_vq *virtscsi_vq, - struct virtqueue *vq) -{ - spin_lock_init(&virtscsi_vq->vq_lock); - virtscsi_vq->vq = vq; -} - -static void virtscsi_remove_vqs(struct virtio_device *vdev) -{ - struct Scsi_Host *sh = virtio_scsi_host(vdev); - struct virtio_scsi *vscsi = shost_priv(sh); - - virtscsi_set_affinity(vscsi, false); - - /* Stop all the virtqueues. */ - vdev->config->reset(vdev); - - vdev->config->del_vqs(vdev); -} - -static int virtscsi_init(struct virtio_device *vdev, - struct virtio_scsi *vscsi) -{ - int err; - u32 i; - u32 num_vqs; - vq_callback_t **callbacks; - const char **names; - struct virtqueue **vqs; - - num_vqs = vscsi->num_queues + VIRTIO_SCSI_VQ_BASE; - vqs = kmalloc(num_vqs * sizeof(struct virtqueue *), GFP_KERNEL); - callbacks = kmalloc(num_vqs * sizeof(vq_callback_t *), GFP_KERNEL); - names = kmalloc(num_vqs * sizeof(char *), GFP_KERNEL); - - if (!callbacks || !vqs || !names) { - err = -ENOMEM; - goto out; - } - - callbacks[0] = virtscsi_ctrl_done; - callbacks[1] = virtscsi_event_done; - names[0] = "control"; - names[1] = "event"; - for (i = VIRTIO_SCSI_VQ_BASE; i < num_vqs; i++) { - callbacks[i] = virtscsi_req_done; - names[i] = "request"; - } - - /* Discover virtqueues and write information to configuration. */ - err = vdev->config->find_vqs(vdev, num_vqs, vqs, callbacks, names); - if (err) - goto out; - - virtscsi_init_vq(&vscsi->ctrl_vq, vqs[0]); - virtscsi_init_vq(&vscsi->event_vq, vqs[1]); - for (i = VIRTIO_SCSI_VQ_BASE; i < num_vqs; i++) - virtscsi_init_vq(&vscsi->req_vqs[i - VIRTIO_SCSI_VQ_BASE], - vqs[i]); - - virtscsi_set_affinity(vscsi, true); - - virtscsi_config_set(vdev, cdb_size, VIRTIO_SCSI_CDB_SIZE); - virtscsi_config_set(vdev, sense_size, VIRTIO_SCSI_SENSE_SIZE); - - err = 0; - -out: - kfree(names); - kfree(callbacks); - kfree(vqs); - if (err) - virtscsi_remove_vqs(vdev); - return err; -} - -static int virtscsi_probe(struct virtio_device *vdev) -{ - struct Scsi_Host *shost; - struct virtio_scsi *vscsi; - int err; - u32 sg_elems, num_targets; - u32 cmd_per_lun; - u32 num_queues; - struct scsi_host_template *hostt; - - if (!vdev->config->get) { - dev_err(&vdev->dev, "%s failure: config access disabled\n", - __func__); - return -EINVAL; - } - - /* We need to know how many queues before we allocate. */ - num_queues = virtscsi_config_get(vdev, num_queues) ? : 1; - - num_targets = virtscsi_config_get(vdev, max_target) + 1; - - if (num_queues == 1) - hostt = &virtscsi_host_template_single; - else - hostt = &virtscsi_host_template_multi; - - shost = scsi_host_alloc(hostt, - sizeof(*vscsi) + sizeof(vscsi->req_vqs[0]) * num_queues); - if (!shost) - return -ENOMEM; - - sg_elems = virtscsi_config_get(vdev, seg_max) ?: 1; - shost->sg_tablesize = sg_elems; - vscsi = shost_priv(shost); - vscsi->vdev = vdev; - vscsi->num_queues = num_queues; - vdev->priv = shost; - - err = virtscsi_init(vdev, vscsi); - if (err) - goto virtscsi_init_failed; - - vscsi->nb.notifier_call = &virtscsi_cpu_callback; - err = register_hotcpu_notifier(&vscsi->nb); - if (err) { - pr_err("registering cpu notifier failed\n"); - goto scsi_add_host_failed; - } - - cmd_per_lun = virtscsi_config_get(vdev, cmd_per_lun) ?: 1; - shost->cmd_per_lun = min_t(u32, cmd_per_lun, shost->can_queue); - shost->max_sectors = virtscsi_config_get(vdev, max_sectors) ?: 0xFFFF; - - /* LUNs > 256 are reported with format 1, so they go in the range - * 16640-32767. - */ - shost->max_lun = virtscsi_config_get(vdev, max_lun) + 1 + 0x4000; - shost->max_id = num_targets; - shost->max_channel = 0; - shost->max_cmd_len = VIRTIO_SCSI_CDB_SIZE; - shost->nr_hw_queues = num_queues; - -#ifdef CONFIG_BLK_DEV_INTEGRITY - if (virtio_has_feature(vdev, VIRTIO_SCSI_F_T10_PI)) { - int host_prot; - - host_prot = SHOST_DIF_TYPE1_PROTECTION | SHOST_DIF_TYPE2_PROTECTION | - SHOST_DIF_TYPE3_PROTECTION | SHOST_DIX_TYPE1_PROTECTION | - SHOST_DIX_TYPE2_PROTECTION | SHOST_DIX_TYPE3_PROTECTION; - - scsi_host_set_prot(shost, host_prot); - scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC); - } -#endif - - err = scsi_add_host(shost, &vdev->dev); - if (err) - goto scsi_add_host_failed; - - virtio_device_ready(vdev); - - if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) - virtscsi_kick_event_all(vscsi); - - scsi_scan_host(shost); - return 0; - -scsi_add_host_failed: - vdev->config->del_vqs(vdev); -virtscsi_init_failed: - scsi_host_put(shost); - return err; -} - -static void virtscsi_remove(struct virtio_device *vdev) -{ - struct Scsi_Host *shost = virtio_scsi_host(vdev); - struct virtio_scsi *vscsi = shost_priv(shost); - - if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) - virtscsi_cancel_event_work(vscsi); - - scsi_remove_host(shost); - - unregister_hotcpu_notifier(&vscsi->nb); - - virtscsi_remove_vqs(vdev); - scsi_host_put(shost); -} - -#ifdef CONFIG_PM_SLEEP -static int virtscsi_freeze(struct virtio_device *vdev) -{ - struct Scsi_Host *sh = virtio_scsi_host(vdev); - struct virtio_scsi *vscsi = shost_priv(sh); - - unregister_hotcpu_notifier(&vscsi->nb); - virtscsi_remove_vqs(vdev); - return 0; -} - -static int virtscsi_restore(struct virtio_device *vdev) -{ - struct Scsi_Host *sh = virtio_scsi_host(vdev); - struct virtio_scsi *vscsi = shost_priv(sh); - int err; - - err = virtscsi_init(vdev, vscsi); - if (err) - return err; - - err = register_hotcpu_notifier(&vscsi->nb); - if (err) { - vdev->config->del_vqs(vdev); - return err; - } - - virtio_device_ready(vdev); - - if (virtio_has_feature(vdev, VIRTIO_SCSI_F_HOTPLUG)) - virtscsi_kick_event_all(vscsi); - - return err; -} -#endif - -static struct virtio_device_id id_table[] = { - { VIRTIO_ID_SCSI, VIRTIO_DEV_ANY_ID }, - { 0 }, -}; - -static unsigned int features[] = { - VIRTIO_SCSI_F_HOTPLUG, - VIRTIO_SCSI_F_CHANGE, -#ifdef CONFIG_BLK_DEV_INTEGRITY - VIRTIO_SCSI_F_T10_PI, -#endif -}; - -static struct virtio_driver virtio_scsi_driver = { - .feature_table = features, - .feature_table_size = ARRAY_SIZE(features), - .driver.name = KBUILD_MODNAME, - .driver.owner = THIS_MODULE, - .id_table = id_table, - .probe = virtscsi_probe, -#ifdef CONFIG_PM_SLEEP - .freeze = virtscsi_freeze, - .restore = virtscsi_restore, -#endif - .remove = virtscsi_remove, -}; - -static int __init init(void) -{ - int ret = -ENOMEM; - - virtscsi_cmd_cache = KMEM_CACHE(virtio_scsi_cmd, 0); - if (!virtscsi_cmd_cache) { - pr_err("kmem_cache_create() for virtscsi_cmd_cache failed\n"); - goto error; - } - - - virtscsi_cmd_pool = - mempool_create_slab_pool(VIRTIO_SCSI_MEMPOOL_SZ, - virtscsi_cmd_cache); - if (!virtscsi_cmd_pool) { - pr_err("mempool_create() for virtscsi_cmd_pool failed\n"); - goto error; - } - ret = register_virtio_driver(&virtio_scsi_driver); - if (ret < 0) - goto error; - - return 0; - -error: - if (virtscsi_cmd_pool) { - mempool_destroy(virtscsi_cmd_pool); - virtscsi_cmd_pool = NULL; - } - if (virtscsi_cmd_cache) { - kmem_cache_destroy(virtscsi_cmd_cache); - virtscsi_cmd_cache = NULL; - } - return ret; -} - -static void __exit fini(void) -{ - unregister_virtio_driver(&virtio_scsi_driver); - mempool_destroy(virtscsi_cmd_pool); - kmem_cache_destroy(virtscsi_cmd_cache); -} -module_init(init); -module_exit(fini); - -MODULE_DEVICE_TABLE(virtio, id_table); -MODULE_DESCRIPTION("Virtio SCSI HBA driver"); -MODULE_LICENSE("GPL"); diff --git a/files/board/arpl/p3/addons/9p/apollolake-4.4.180.tgz b/files/board/arpl/p3/addons/9p/apollolake-4.4.180.tgz index 300c00e4f7594a8b22e8b896e300753c1eafcf81..745ef0af0bf09075fcc66f8f4474f896ed339769 100644 GIT binary patch delta 34317 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

CDamF&YwXmfvwTgaRk8C!Bt;woRh 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 delta 35306 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

42?Q6AfJb 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 PuRi`C&QnZx0Pp|+&;o7S diff --git a/files/board/arpl/p3/addons/atl1c/broadwell-4.4.180.tgz b/files/board/arpl/p3/addons/atl1c/broadwell-4.4.180.tgz index 98271a24a3878442ad18f34099fe575b168e1e1e..7a360d9ad7a166c4da10be92368830c55a91e222 100644 GIT binary patch delta 20219 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 ZmYNETa~dPCm{pYk`t#p9lo@1Z_J4m6U{nAA diff --git a/files/board/arpl/p3/addons/atl1c/broadwellnk-4.4.180.tgz b/files/board/arpl/p3/addons/atl1c/broadwellnk-4.4.180.tgz index 808c065d9231160f25ede3bb2f00b811f7471615..0649b1daec4170816217eabbd97f2f0a004b3a4c 100644 GIT binary patch literal 21459 zcmV(-K-|9{iwFP!000001ME2sa1&R0yOID|IJXYL9LbTOb4`b&ci<)FuN*-eBv^H1 zZ~}(3sV`0d1*U1BuqL#DLuRGeFB=sTLe2D&fo6_|>7_k-Tq0otmTbp19HEB%lq1aH z_#9%zTyTIB#u%&L_wBAE18I9RC2i+!2lU?i-uJ%uz3=}$Pnyi#_OA%O=~Jg-D^8zU zl--&iCl*hcI(^!7amth_T#;BL7Ek4zQ*S?O99Owcd2+4O$@!mrYSrrh1n<9^|9|>T zn!M^+kiav~Oj@_{cI|-*o>pA^mHM9|7T=(MfE07iqT9t#_V+uk|5bkHn1;`JR>ff^cSlO zV763xR4Q4t$>Cq+_}`Yr@8UOU^4is_mD`&He!KWT4g6meA1wZT{Qo*WL;t2{-j+Rn zd;L$DR`h%Qe=Xk)`Zpu<|L7jK$p55s`W2^&)2C$XAM8XdE_!g<|FQg!V){Dx`I^7Y z9^X6*&!@*c_YlY50p3r(yqpMIXwDNZ#cJIh&Y_p?VF{#o-!NrJmkZQ=dyna3-S`Puw2CPSfc46sWl)s` zRh?HZ^fu(Q14c@SEG-4>xN@h&Vp3Hbm&du1jR8sU#B_iigd8}>haVY4nA&e$KgJV0 zqRgHU`M2Iw?!KOT-7FUG$m{thq^8^hn=APf7N$~9+~L~Y%gNd|*%suzylKM13kI+! z0sY=o;Fz=LtQNpoIIDid#Mo3SRV#<9C!$iq5ql2D)pOtExE`l$-C7IGXgTbN%)hjR zJDEz!YNJiA>aT!#8bT8&O!@3_Oii#{o*2Pusc|Ct3AlJT|*F@Py;iamLb$PZ!DB zuAPLowU*H8YIL-fI+_bNwbseluw6T8F0z-Jt!>!wM`a$YylxGxJ_)#`NRB@Zy;|xu z`ogwv`1qs1Pz92KDOM-*L>J{=!ngUX)f*hdM3l%>m+DNQc3=*L`FJ^ii(uT8Yt`5Yp;~l- zKmc4^tFwb!CR=#LA2=3ZaRY_b;G`G>!O(C^?P!vcK6r%&yVh8c@*C95{FQQ_9A1~_ zV;6`EXju#OWbIopTiN-z^ygA}c@v9QeUjRox*j-ZQC<#oZN39gEG*vhg3gbzzdlHO zABwDUI_VsoigF=E%QNYC1KejYcKX$=vZo>ecj*ewF#l$0L4&D2(@9D>$Cg9FZTgY z>;4euE*f($&>8A$=?otcU*%%#Qq!d-uLeZJ^&FbL`dOdMUc}Wb?$wl>J}*-oeLi-= z$BxVQUzP7a&d1{k>m_+l&riMD8jH+C*5cJRim(iS!hdZ?Oe8Y|+u)z{BMEQImc5o5 z+C~UI4ImbW^Sg5f{StFK1`~^QtTlk;su7h&2!ldI;RpQ;eoRt#;kpekWl5q`bxmf-LaXwpRoA@GRSLwI_%VoQ9yrXPX?*Myu_S$8dZPSN6Ub=&sDl?_ z%PTD%DJW?^1jv%n-taqxX%h{_l){780Hr5N=-%*>F(!g~ZoGk0c}D!Wr|u^ISn6dd zX$kNMl4BoAi=}t)uD+<}UTtUIXynHI?QUgq17=$yB&p|lA(v#G4#1~ zKGFz#2%!)o^P)T`4wOl1|1jl#wcnzQ6k~=!A@`?JS5tI~LW~gw^I7c-Tq&kYE9GErsQJf)$!D>?BH3H{)UL;SC?&$x$k4ZQ)Fb zMPVY9m;^uIV(#pC4UVh5fx0s7`&&{nSojN&wNpBTWohLjkGom7?z$jw>CiBfD2&7- z;>p9-8v!;GkoKL8*HbB=VnhH45jV4#na221)qimq1?eBm2tQn?Hr^}9?P_PA5NY(Y zF=}k{gjkB_{WXp_)Rp=h}1VmQN zWeap&BikOq9=4@rXU500>`Xw~NF5gPPxN|E7Z4C*;GZx$%x7Vv7nJdacN})yiq7AY zPYytt8tA%!M(gQfTWDxvyo4CFXs}Q#YSzG~7g!CBw7Gd|A1}Nh@^}+)3c(u6l@=jb zhn;Q<7WFP9BZR7W!zQsFMxVg|m=Z zOS)(_@oaXGdsz>1u%FsyqrI_@d;BYT_`oPba@a{cMldsqkWvzUg6%fF-Y|(oH~1Hr z7e*GBE%A3SN-H4UN&FS9)n#tgJBc6Yd*qps3Ob1jj4ZB|2ym@TTqF#eiGiI&3}9cG zU)1w?R5@!~V^*qRqtLjuH`;InMjFH=K5cK5s@Z)Q2}(l0RupiZS076@Ta*o6&0_~l zX89T#3D>;>T%B+v!yuE>~?cim+tkDab9IoqwVZ&I{K+BuH zD*s}HFkDt*%|hrS43+Gc-l`T9h7jzbEmaf{3G8DUyVjsg{`fG4J5wY8SY!lI0Ew|7 zbu&0n+DY)dvU)H8Bst~18)>`)yWx}`N}2t}`By1_7#jh3nW;6FbjpA;D2s36B2kG; zZWZZ~Dc~)`mo|*coKOhegSl!UaiSlj9>W~Px`qmyNhB155>p5^*l^Q*vJDw)1;*&6 z+8XFJo?lu6KLWd`xeJT`J+TqSYJEpF9eXFHp*s019ViGkpLcSjg`89lo%@7s3!SOcCh;Ow6)dMcF z%SK&f7huc14&rB@@#h=pMvX4)xf8nM_3o=i*T}DjBO>^xC@2Iygrj}t$c3Y~&C$a+`WcSW;Z#?N=akeE!rL=1)r6vUv>HS`sV^jQ z{@LsDgy2YEQF!4Wk;mB;kcxQB-Ls#9-e&|;^D0NeVRyp1BLO zd&ocYMCBK71KWYem{FRn`~(Q>KoR(7miAS?kE5UIqyEZwldb_?X)q}AJ#YD|uHs?- zMBg555l#~W^l?{s+kw(1P*zLGhPy-C4Db<$@#fmlZN=P;uYMr6x6atf+F}kG9y)C& zGMAz0f)6a`B^}ah*KGoj!oRdryQ2k<>e6kd3*XP~uoCq@+ZbRsaCvg1E zWsG=pG9ebCsD4PD$i1obB9vm{feaCpb>g1P7@aubxSkOn2GpMqW{(v#-g)>o3>F&3 zE5A3q1F!mEZ1^&wUbPEq1W=Q4n-J>9HAj@ufcq9ACF2%XO_2@!HP7b{W%sZ>ky{AnS3@HU@(%RGn!E zHzxBGhaHUGLtY*A=Uh!ij7qR@>d-3f}LY^~Mw%Ub#HSglaM};8fa2HWKI$V}i9BIhc)ZAu$38FMNQTw^qk=w*ZbX8O(FY+Wu4ICikfw z18SQEPKU2m4w&4EP7Z?wb|ILr=LD(@wN33*9rE;|eNn1MJMofPrJjQmcjCT2{v)68 zuvuR@J>n4`-{RHJ^*NsFi(EN=Za4rXBx)9Do7#b7TnNs}+7I_SO^4l30o6<~-SS)& zGI$v)i6T3O7el2S6+(qPDRqfMh7JX0Y-7Bg9n57Qkf4CBQa_auRF#W zH|6ow@yZNVv(WR7Kmn?U%!V7z z>}6zeLU0(R60$`-ZIP3Rsf6Wvn%%@b#HL5=N~|3~C>Yw%-QLsrhC5P}071}s8R&cx z5J?Qu>csnl^w?y?Lohu0lM1`$R}bQ23kYQn7(HIvK&KkMwzR6<#uZMv505XNL;*DN zC<73I5Yceq%oCft;ZkUlX;t%V`XV5s=HfL#+dtN3&?p#6qrjwbbYnMa4khMi+ou7# zcoHb08A41_izzf|i>cYa1gTAumo)+%2t_Ukh-jD4Z4)ArsU;=>hbmH-*|_m!_vfFY z?6cLP>(PPsCA+r5G9%1$|X_&VCj1@ud{4@ws!6||ThQKhX zvTYmlv&nT5UNAq4+;<4gHDu{Tf|ZifY@cFFPw8QaZL1hUlp~_chft7-!b+XOqc>C7 zfUnU9I{;!4Le*S)zJ9j_rwcR0{Pi5qwtXib{}RjXvZUqY%qQ%I41_~S%+g>@Lnac$ zdNuYqXBCg$hN#fn;U)YMKvKnHxS-C^npDxodAZSU;+BO)Cg_*IIj@i>z4wQC9yn*Ov-jG2uf5jVYp=cbZclc!$287# zj|sj;h=fYl@)i4lHcSDl7r-OhYZ-GONli0K!NFWkzSxVPQTTxG#3k?_uNCdD#zvFk zy4$=*&^!_yR4-Y==Ot1uG!iiGjNkqZnQR&RGt6EAs{&1yc}}%tK=B_&n*kKK(-}o4 zCusPwBx*kbi*hfjo>1JWZ0N)(P<-GM_~Z~<9xcX|eze!*&U$nnygJnDavh-Wl`e`2 z_|-Pj%P*0=0$O23Gt|*ksth^uKlLgby4}hfE~VX}USx}YVzJ4`L|Dmu0~NnYJJ>_{ z-TjlqmIx{%pr|WrBUa(H6&zk$*my@Sns+dHY{VwW5u98%UPs>*0{LHra-jAix^nRC z0sOWuVpCV<4(<~K3rve4sLk8>LE>6oJNjR2YId}50#puDbfHV#h(cZ(&g*ij4%`pB zDbMVJb&!QjgLF&Gax-I9wL3<&ZpG5cEHKTq4}Ujq+vo%6n+?Ih^ulx=Q%d@PVEv~igM843Q!jtfa&7W4WN#CtzP+rVaiK# z)YxS5o0`nh<$zFZSq7Et5Y9B8e0g=--vy&$@_t=dc+6av;*HltmIPn;0lD}0i&av%nlI91xzp>na`dN+{B(c(BRN{ zZjnv+SOTAsXLJ~P&S2px`(R~;8Y^rH;8IF#c|M!=wnAX&_>YLe0n$BhJHslH+NHcN zwyZd^i*SdZ$|nE1=y(+d7Bm`YwKC968(Q7UXW?Zaj@{1i?Mt(q(GRlR%2)2JOY)$P zWjXOS1Dk+ds-K2ovGS^X6o%nzHVpALlYf-lYnB$cLr9e}KHP3~6Ca6AH;%+Ef;nfn zLocO`giGBZ=!b$Tb#*vsEZ|8T#>3NW3Vf2=C%X#X6GOM47hCnWy42B5mFCKUz|+|6 zQ_e>6+wp;hMPW&#NpkWvm2Bbt{ks ziOl^GK+eqHJ{z;0$(`LdpDzI3f%#~;F8(2XfA%7nYBpf@ z(Ei|a=&6OKqD#WAKHHPSTQtC1grEC1yg>^xC$x(4HyNZ!&{uRaf=;-?8Qx7h0gvdG zUyjhHQj(DNRM3iUM}N;R$0WChm;&69?(bQ~x6*NoC%l&&?3a;>4(4Gykq6!nMGD1V zwrk`~?VXduWtj12@l-bDE0^+()>fN*DoeT;JJ@9KPtaOQn_{UQcIx5tU>xIAZeOrulwt?VE5V zWx$N%-eo}{DTke5e>XHO zy)lYoKQp-<`$G}`PO-(`Ew(totSV?hX7`^1Z<~Pze_b6>M(S9GJ6N=L zf*NPri+rANIGapja6Y-a`Hn#Pm_n6PvT(s1{E(InSQ|HKI4)-JbimhfpF?+Jxydja zPAeX2^LjFLM}rg1W1CKEVLlq12p&V9(@6WlBnPP-j6H~J+%99psUfuq zTB`mawKpqn?iIACRD*NMON~bZhz9hzTRG}hdSIo>dZ^RuY|HktxICF?5!xjT7uSkS zvBxoPN4HfAFe`}6K;TK7c?P-HEBF#lI)O^-Y5ecxKtjdoNBSPvT5Q(cj-)-k98je; zeQ6#_cSp0eDf+UL?r1hY_5X=C)_)Zvhp-d78Jmy_cv9NZtyA71Uif+G=%$L zn8dMLlKN4LW@XA&vS^C+Y6?5^kJH7duGklsDQ-&oQrln6u$SLT>386_l!o6fB%Sdr zu7}TWrQv6>GSqjEy`8=vHtWq)IvHZi+Gs{z!p)22`4O)3w{S(@WE4Z|j5xhU0)@sj zA3a4SSU~1*Zx@!ZxYY~O8SX=Pl}+cuS|n^*;#D3!0Pyg_!stg?Dfgn>jAepTj9BtH zEa?tEPXs6p?+!q+!*LKRELHqn&T#GmJiTCe#TlLtrs{KVQhi^-A|Fv3zI0Z0lLI(x z>H^F|^i`$}XG7Eti|w%FG}*(KV9YMe)6Z_EsxhkDtv;29_M{t@P{C_yrR_iH40E@1 z5Dd(Pq$f>zWcSa-gd`KCz z&+Jf6Tp!Lg;--M|@D^;MqHd!Gt4M_CQIl6ux5HcG(E*ru!V?O_mfhGDDy1A@1zTCc z2rGCXS+G-AF#r1Sd?SYMQ;8lNg9)cNF8~eu#*$4nfF*i|poHOo%g_axfpj=@rHX9M z#abQ~;1TTs^s)us`lORg)x7BU0Y|2SW0*lZ9cw^xhW?Yp0!+{Kd}|LBP&#uv)!ofw zlluqzEv@L{)H})({U13zb#DswE8*GjrlCHY8$JVxq9HPSw}Akpo4pLe&0b8Xq+bA+PBo(JTssKp z6E_S=7xh1rlDW_OR{a;7SFSyglD*hHv@|B<>AH++kUNvjNLH#dcy;T8?z9zM99MKs zr@9g452R-liMeCDGrX~n3^qqIyt4RuM-#kaPzk(lu?6*i=WC>7^{#ACRx3O0!7EEGj zCZfjV5J-u1jxD|s)gP#sf5!ri$4rEOA>@+R9AxvC7+MZQYGtO!16W~xH*;(Q&p7oH zb*djo0-O3s)7WGgT;M8QVkn5A4tDjK_(Xgbd@KfQ$id`}>|)x%)9Fw?!FXcj6( zVs5u1PQ~BqK;K*0w*K*6N5O}%3U4BbKPJ!u^L5ZuOMxcM6zMYcfaVRbXYIv#LTp*a zmc5FQ@;=-$!m{^Tw!&OyCcX1pQYqvYD^*vt(#rQCQeR78<=ZWdFU2+a$Zm*bXSgBw z!K`ID=-=`>uKqnLAMAq|`aVz_9aP==K8B{!7ScvkXO2+9u6jD1>NcFHr7LlMBhvB1 z9={(@AKp*1GJ*@*){7u;&mkoZ;(gDs0YW@{eeF~q-9}9Uo1mL4tU@%&LhYxtScVr) zQQbY+Y&Lodk^?qz*Y6P^i1%%!P4|rv3P&K0oQ}e1Q#R^1sW)t4$h^#mYt~$dO|)D% zPtbxk+DTf3*wj<0g&uEk?0OPh5Gfwj7H-vlHW%$}vGJ$K`9{Wp7P3)@61lEPmUxV3mPD8?WECz7EUuZM}qT6>cBipdL&1*PqEIP>!Zs@|t<1oN@k&!XQBB>wOZS zQwjJU2S!g|y>dpt#Pam>Lh1gpZ@}F78z|T-QNf~FWEMjg;{xbGiUCktXpw68LfkRl zE8k@l?BSmpq{Uzx?Lppdg9*P~+)z@+z|F;}*9m7>{)E(dM{*GiM&-lmhjuweJC# z?On=?=m+T}3EZ03MS{g@gHrN(BXn}bDAZd!f_eXpbneMom?efDA49rqE18qFELPGs zYb%kRRPZ&pIr^&2xHa!zXe9imu9&zZ3X521Vb{lF2E-lR(cW`mnW{KUgbKF<;_Vh# z^=il?)U4<8*ua13;`rqg=Sbtn;a(D!)iT)B``KVaKPb*)*8Mc-@%R<*)w%Fo`c(D@~jYhXdN2%gzw#lCx9AZnt7A`Tsgbl_{Yzu2U_AafR_PpU5 z`k*nrp}#gJ8@kzeWoVqeqLu+EL^~ zZU*6KRhvnJC{YZM%4(#8aFv5jxjhRgYXZFihDW6D7k@!{Xm_a&+SGC>qcP$g@s>g{ z#uw`1+%uRW51FDg&&*i?m_of75(`kySbt%Gnqr2~kyHpu>;S#%#XC(uZ$C*J7Qwtd z0%KLKVk&tg2tbebbPVPmP%$6E4c&O~Z2SA1HeJ%bm!g zc4fs=jB7yyJNIZ@>lCk}*~hMwHKmO{t|WJ6@-P5Pm9H}y*shi}+0_+K>G{JkDxE*> z8kOXaYeq5tz!qV(8lPxrki^rC>5T0tcumLLjwEwCgmnu*`eT#HVwuPkDzF|@8N$O+ zNQSKupl@t#Do1P?yn_bmE>%uLVIbd0nqym`Mcbi8&=G%A-@KQRn>vu2pjF#Tl?~0% z!l!_MY%`8)8>vyL8ln}iAjeYLv$%3%=BNmmyVADhuF2Sy z1GeXVEi0c@b zIuo%YMAJb|R$JqbaBm~vR(^=nF>#$r#z*4`!~t3c%^z{oPIM}6!2vUDLEcd})3S!% z3tkmBKW0e!;J8)gRqp$8V#@AGnmYb?B9Wies}3%b+CC&asdIh5>OirK>V$(aYyL}K zrPOG0XabYV9ZVTCMBEnK|Ab)aQ78Fs1kIPUVjMb`V`p+Vg-`H&!mm<}q2#b;=){;2YTZ&6ElS1m*|^c5O09 zZky&51`1{xM?9b*3?$;x8i@3BQ?Q$g=f?rG2b0o#)1v{?=jczwuwB zZZVHX$1K3DWU~0rW#@yl{Zm;yTC{H()?psckWv2rSG2&jZ1&RsSKayL9mPhZQM6~W z(gumFXpdz~m$>8RQS`ql+G`%uMOW8gbHyE_0ceQ!Xh3W%E|8P>@*{=uc35p46Vlhp z%XmY@P>(=9kAZVRu9V|2YZ}EMDsGqZI&SQ$lkiOPe)!sWJVB12?C5ce(i{QEZuB|y zi)sK9p~(76o9%v|2zqUiI->h|3VF5g)pZp zQKbth&?(~N%p4N^Fp!Q=+z+PMB)jq(Y`Ffm2Rt09igKq>X~a)-21E@Eu&aD{M`P!b zqbxh4SxQ@MJ>}l7LGdLf(b-VWzk4a_0hP0MyG4H7rbPBmBVsFG*p;@|K32Y-`GwqT zklPKf^^WP1Ph0)R@$|bLsu(B(o{09~9*uJp-36nxIkP6&Rip9+c~YHO+0obqul3r; zv?-Pq!`{b2o{s#t`=_aa2@_C=gn(JPd~f^Hpj!5^Ksfp2dTF*Ta8I6%Hb$h^Syp`4 z74pBloJfiSOq)u>)Q1cJl`8jPDZ-t0{#8Dn&Gen}H`+~`6#Zbb@+K^;j|#dXjV}vA zxdm%iwjpru(m{hhJR&90^1Vxh^#*q8GFE-8RFN#NZo^AHnBrOgW}}Y8!mrCV!Y+7>r9Exp$h_62B+qq+&OXNe+rfO zACr$x1FN?2B|s~TIn@8}UyKDsr+aZFcCalfOK^(g*heJk;s`yI8cNA(}0 z$Us&jI|YuKMJ9(||37&%;#ty3^Sr>0*E5=|9*!o*Y=ehw@-d>xjl+YrcdC7}^%Q5*-r-T0BPwM35Gr^gW2%ERIi- z2<(cZM{yrh%KC7^xe>3TP#rz0`K)_<>+h-U_^8Y_hguFudq^%Nu%0bi7IHGX13xp$G+2`7gvTuoBz1 zbByk5em59YzibeeHW(%s6Q?RO!rr?i0-x>ojkxtz}1!?r;VsH<=3TjiY*5U z#T}YQS$AcRoyxaC`6y;kq8VB6J`ecVzVjah76kPnUD`V~N&}D|yj3kE8 zPO+=aI2+g%|3NLz7uQCgqDE9p*u5Bb0|nB<8ikU-PDAoF1=pZ;6*y>i;RKBDyQ^@P zn!rB9_nW1Bm>0z$ZV#lcx=GHBZ?b$e-S7hbLpJ$d3)J=vWORVU`OxE^3Pxr@jgSJy z^eSaX#Fp;lz5qb?T&-1t88v|1JE+gQ_x>Mo4ctGL*QOG?_0q*oiN4>&k!%uZE}MEw zjZL{_H3fp>df}Gpj2-1Yqjj7Li=C1hx#u)Y!M4pMHB10^#~lZaV(5<;>F+*h#NN6O zDw_xRL@VenM*_-IPz{h=bsPk$f>KiM!1)RdU70Nm!UgMqn0hTX99~( z2Ftq_R=ZxsaU`{sa<#x>#G*};Q)o&I< zcsK~`kX$_FQ*@(A3_Wb1UDY2yaVlYJJSa>h1#VX;2fH8%XLg%>kl#Fz@v&#ke17)< zyCEg`fdP-apQa=4y9=P-?-AZzyEh90-Cv_gAD=9SjO%VrUV(BO$wDE!kclpS!FOEAE<_yYAV}Y{ zYMtU1gq>Ldes@&bM-ud1pKAv{Fj0I7b@KI|259U}+?$Lw zploCH*(im9vannTXhIl!?(_)vI%Tv)BWxCXiTw&214Bx;0nsI0y{Vcw3>x&lkmL-` z5Su1NJNm#UTBP<-i6iyNcUWOAOv0<#6 z&1E1q_>KNNVQIMJVwxI_ge5JQuGZ{UJ=z5;V(2iEI$Xp&oLRb7;Kvqf&9duYA~uPe z8cA+UuM^Q3_X*pz`!!OG9f5*}%% zNJl6ry*xs2*mF?u*YJEOnVD{3kscc%zkCLq6<{2L7u5j5hu{_W$I5n&=XAPhS!vku znM(m<={3|l$(uu94xJ&kxIc@(XqGNe4j=Lg@m01f(Lo+Tv1n6AU|?02&?V zFi`dL^Sq5m1?FJvmfMV8<-BB`T{$ezguMQ@=#C0_UzpebO6GcnqT}T_#nnwLkjvZZiB_JI#fw?TdyHs5VZ;r!E?BFx;0y}D?#S(X!{BvoQ zL+y3s)BZP)(|v^Ebg@HrWk?qx6?SwJrcpXfz}ww)lsev4=${sEvo;(2ljCiHW|MzB z5|zxzDG|BnYdM131GnedZSD3v2@%jPlO5`|{kcjLabP#`mmTm0GY-B_M{T4V$avU$ zt76miK)=C1Fl^68?(TUu`BQ`cPtf4QIGxcRJp~bj{fBkEVIMzBk6(qQzeP{;WxGK) z3UpDZ`XjTqaVHN|w(rA<4c4w`2i1}>#V+X6{0cL1KG+t}gXYr|fkNN-!8?gVpjtmn ze4a>*c};msJ^(znlR||>`&-jbyniYYic1^D;WfuVw!(P35kp(gYkV0-zy$V+(bkg7 z4wlQu4KC$0yT}u0a%3lli6CLLSX!4ln%^D>Z^||n@;jQ(q4d^D_ih0jBo75ps8Zu! zQ1g!q+>Xj)l3n=^=C+xn{7Znp+?UHQcb&xIJKIYnp??SPxQS0T*bbX~XdV;Z6%@6T z2;4g(Y7@71l!WiOH#fFWci&$&dm+;9Lz)E-p4O>M_7dBpyFV*5RIBqG^uLCsu zIBAQ3X+_#QYu$x(C-V34CT3{KetBq=w8jxUCXEiB z;7`^mT~ds@J|4xv$vJuVkM!k|h*4R==bfVi`uSfo!9LqFkxxa_6ChVZH=>uxMvKjOnP3jpmhdXYxzYu&hEEbuFI2V^jgET59 zF-TM?>vZA6uiXwI2LDR4EZeM7SDN=kghG(ocWhZJbH$eHt`S?7F0@5IF@j2i1%9;O zIHn5>Go{32pZSs8VQ^L^oY9YxmmAO}VCeL=6}+=yiCyUd!5Qo_>~qTd4EYyxyp>BCVj=0M z1YUE7mzqn%PZI~AO7FOCh{@?+aqGN;j(xG-(?!LNQRGg#srXsoOmYCQ*hZsSLP|Qp~9gd6^jSiY7gV z{7ejV!KDtvHJKPp8Ev>B6N5Pe!>ySZax*Y^GBCJS>xWhCl{}Co?ewGcYt~V%VI4;m?^E?$5w*AQQuu3=D5%V%VC2;aDaHJYA#5@I@vD zJeH%!a5@vi<7sW+d=FlU3QJ@Bvq?fQ zPPbR_k0=Fa6N_Msa&MuJ4^1|nT}FcM=y6Xqo?T#qhxE9~f;fxx1l#nuO_}Y^5T)Rs z^tjELxHIG`*rdmun~6I^$bygQa4%gwqPPYBS&!9{i8Vv^f6L*GK z2WRSWZ_UJ=A>+ZRdfaql_E`izDC%+3UD{`n{-9Bh`|-?nGgS~9IH}#Tn?%g?KH2g%{zPTUss;Rf)le$p*me z=NQ;AQg4BbcCGY1ehkN}P+BwALiY(6Jj^!xxuLUSpU%UIJE06;D|SNq1CLg~U}9Mx zZI~8cuVExhss9;WlftGD-Q-t=n=*y?hLHgp(vGts?SDo`uZ~SanvsH5b6I-GdGeB9 zZ4Fd*21NMo_ucQi-?#hSVT}q?EKBj`cm95dHT5pwjf+BsHImH3-Ycxy`>hkSJW*Yq zs4h=5EstlSaYpLhK<^C}#Cc<5>b=3Dy=!IVjCU8k5@ATg{ zMGz`2f{@_9;l5Y=o$q&8|4#Y8^S$Bk;Fr(x{kz|Hzu|svTamRvDwjOgHRYA7eKj6y zWqHj-lC{EP^;K1StPQ@JN{_Y5*HB(j?Wv-_Xq!K8O@p<;Q(0S6l_M0D*VNQX)_Tuu zPYq_VE-7+Zt2}FcP^#Q3dFtU)gGWmK&00WL?XU98EpJ#edzGigQ}3&sTeYTq_L}m# zI$zDI*_E|x*3{O_S*_(?Tx<1H-B!EXW`#PvzE%GEa>-X)b4htcZM_7A5c#_L+L~3? zy7J09J<|8B_4N(bb+z?Xmsx!c*6H~7!KOD{Wu4w&UF<5dmilV$M0i=xQLMWv#!u%8Er+c_ix^&zjo$yNLQoh6=ye>#3)_^oJ;|tIO-F)|JH4Tu3dL#j=J)@s%y)uthHV*G{f4kI$3{t zjn%W(QzKbx{A((BtzZVOpWSe0g|(`_wysVB#;EcW5nw1;8*(znyV_UdUq83%uA1^S zzRHz9^LzZBmDRpAKB<9?HId4y@sRU2D-^i1XmxqbDv#Br5j023x6C8qz$5W&eyMi$ zV$Z5t$wyqlEA~jMrP|tRYeSvKQ#H5BUsvr}4@}F7dCPsk%&EVlJYJ{$6T0_rbb@mI z|DAmOcm66F51k=sIog-n3aQ*zLtlWKYW?+OHG`4M0=)sJ&WiJQDw^ zQ73=SygB)E@@Fr$EpZ9JI1NBukdz#OINe&mp7UX{05DixrEeuvv=Y?Ds%j0D;PzKb zK5M;~F;s)Ut_}p(dKXA)jxbkRQ#aRFQ|Fi1A613ozM46eLb1QP+G?k96P)GMUhSR4 z1eH~?+H@96_5=887@@bA;=TMZ|y481CUG^N|7Sc^_PnECSD&1A*A%&1XZ{9pN z2rl#tn#J+uXmnnbM*M2%PECVnQOS~0p~}-xS?{YuR$p|Zzq}e1X7Z1W1Jbz+aq>@$ zFZM{F3GcMp>wSP*DECXNYwOP}>8h!mbBT3fjjwVxkk3FoS@v#LB5SNboV$pHV~GtFtZYmHQ1 z0Z*x(Jy&aQU?_Oztg7+Psqp)%t7iMEggNz|>hd{~XT2oQ|8qcJ`tI~p-^IW9YJ3v^ zOli;h^mKhKPTm54VwL%Gu4LaF(bgo zjsUle06%vG`1xnR&^k8i+H)CyPT=rDp1z4c^EiAvPbYNc2+qyz9sF6u;dk&GQ0Mae zOF4WChiiXky+X^+|3<*~IlNxW&*4=Zey`U4Q7pZI*ZUBM2S&5>LZ1Ig4v%p7Bo2R` z!+SVU( z$?+`V1G1El+n+T&+6}in|30n1m$LK+9R50oZ|8)6o5MfU+CQ14r*Zg@mY>73d4tX| z@_tQa>8%`op$5-m=_R~hmvXp9m?t^BSj&GAOY?`YoWpxK;7bnoYVa8>-NfM%hi{q5 z(j^=&Yxz0+#~l6`hZkO)4u6`%w{!UUoUVI0JTjZ5pWyB9$kaJI_BRi{~$3=?8P!^8yZ!IC%ScJ7*D`H%`FN zL-t#Qw_xh@)ewJPPx-Txa4pB}S)AYac=vGlPdPlo)4UtPJz9SLYvoUc;Nz3I_^5;Pgzk{c*;Ljcof0U;+P5oaqo@0eNA^mqEi{+Y>>9{tr{C8wb z8KX^{{+!V?2itTG-@^SHnj{x-cr%9=b9e=Z-{EHImpFVahc8*q((5=};qWdF*XZ*& zhxcT_|G?n`9Ink|Z5%G#&eAJ5yi02jhjZ~3KIHHKhhNU=6zA{=N1*AA>`}Zu9A3fU z6FGdzPgr_3XR$mE4|rI570a z^N6!tPnL=+%5AyLt&o+Y9ONixTF%Pcdx2Jt9QdfIJvp#UZ7EM?=~D_6D%sG?%*p{y zoB;~*6&XMO@BT0E?sNCK&+WSxHzFnjCyc!Wk~9iY)j|UK!sxs}Wp0`(^0ZjCQ6ctA zZdww6HKRZi0SB20P0it1Y*LQ}dfv$l@RSiaA7y=#GyUh{tvaXNa%G`Ld$8SJoLlb& zeK`nY49@;0K_7}DAdLecKUM>b!Q9^mDBWlfK1>9d)*wI+3-P~8(A6{uj7Jmy=^7c< z3{&a&`1Dz6{q~i%W(|sxsu0p+n@*Pm!Ght2*|<8BQ+!bkLc_1;4U-wW*d_X+#sXGZ z2p1{R^O+&5AGzYF%3qe)!8CEBhC}esqXJ0{f-E1iJ#6n$JokIP>eHtPcix-U5gox4yc-7fx#kkRK4m z^@i|79~o5&3J=DGF&zuA5rDZAzIxUc!nfM_NjT6S%OGRHX zua3W;$9SU}`z1$V zR&*=b3N8bWJsH^_AAjY?Zen6THDo%Ww25^}jYoIQlgSGQ1UAj&GnqNWb}XsejH4!n zDwxHZaE}n-p}>bx2G^xvMA@C^y5-8A*XvhXO?$JERugT%Xu{*26%WJr)6K)9;M4!E z(x4V*oInUthe#B6iVbX?jB(9y`0wuKKCMnYBU;Vx%H;Jn@WfV$wapF1!o;!sn(k^Z zJxlL5knh$z_v+C}LvHU3TI^!l?|ziG@z&jz>!@|Bk&qv=kL|G)lTNNS&4cNAyNLL6 z(rRn>O(nuUgkSpaQ=7$nZSQYR!MRI54vTIRBMLYFz9rf6=SN~4#=m_e1mrGVJQOfn z4n5?WAG$HcDOw3tuX>N5hPo}tD0O${a7$^@QqvKx@jF9>&dehz)c%v#k7rnWw@h`;FWu~n zE&rWH`PgQ5K#u1Jdp>Gk_o2t(S;xt)QF-lwBkiTk`qgU_F);Re#Fwa^D5Jz{$KOv$ zJaRvnr2bbb;=40U!qVz9`bvt&#@yK2I9ca&6>0<%xUZr%`QW0LUbXD^AStRt!=Hbf z&iib64Z0@B$BZ5qeZ{Iq40y6gNtasW65skp_-O+rUr|K+YRSB zWxKWW^R{ff9%d1zgV3MBrV^&+Z}wrAUqyEQ)1>p6(lPZ(7cRHv0n^iV1<4Jxn3%{q z3bd%Yf89?Za#Zon;|3QKqkeCVb*wm=ml9d0AN~8ZYC7l`^?b2`VpU^&Tcv!2jH3U0 z`E5sI`h%z*BI1u-qGU!}{lxBPUH@hs>wpj8qL+ftK3eI#2MNwPckk|uk4Kp%+SvHp zMtJnwssl=Js=Qitq@&M}q|$}ou{HaJU2Odaq=u{>B+Nd+igiG4bhb@DEWLRCfi{u|w1TI^IHzX|Ww7)id6S_0Vw8*64A@~-zi_h|ekbV=fY!OrXGPRHwGx9(p+ zB48DU@|$zVT+7T4)Snb__K@|BfyG~Vc!88xJ7kl2QvBLAlWL!+{KHROimwvRx2{k$ z&)uG#x@{AoQ|M8o z+j=JX!uNZio{WDubyaa# zr-BH!{v6?3d|W!wGpOZB_S3|BZeUa2!SY+bQs$(r5N93S`w`ZC%6jz_v%;mmgUrp)U>kUH^X05w}^@_ zHS{9yK=1g5XJFr`SKM-7x^(E)s8od9ici>In_;9^Q2kNo%A~EAy*%;3(FB%eWVUUD ze?=|tP`G~zi&o=E?>(HLtAhRZ{6_E9DvQ=wpYQFZy@-mye-5foUHA7KwQ!f&ubxn7 zua=tEBd;5AJ1YORMeCNr&yT&z(O2m4FPbj+n3FBP_*VSIP|O+oeXwZpyt}b|%etEu zNvl2c(u=fsQFtlt#%cBGKMUOF%h1^@XAf4G7Vg;kEI*>J;IZ8TyJ)mJ>1}_6n6)7l z>1VUD3)x|7$f~Fi}dV?b4#| zEiobqeZo#QTY;`hN92Z0bwDBjcLEK>KTV;bEx4JK=0ONQj!-Uy69W|U_727=ZYN?h z1uo*tG;y9bB@Rpzoss66P=x3XVe^ybkvG0$f;Xc~mtR2Jz@(i?k!&^k3F6xa!I#?f zeRKJVUqi$*|2f7?!t8w+f?Zxo$tW77iJ^HcXNpw_Osr7|mQ(-4*FLeCR)#nn#hi3N zDbwHWX@iuc>kx1!+S!c0>j{0d&D;SNawu=UjFej` zB2zVP3?2c<6R1K08IG{(#JfqD{Dxv5B1v``D#CO4>I#=!pxP>goaUbXH%aB^XkZMp zhX+@qBAhptd4q<_CNd~6(vlwMX2CV2q!g;~F$6qVb!$>u3KM^O){4BA2bbX}-nPwjo={^VZt_17Mxo@VX&U2im6^4<{BsmGNZ?jB z`!*NRcpdmeNXxN+4bwn)2;fY>3M0Q!rBEQ?BE=GfvHH^G+ghpfxX-(FpgT=FzBCZL z{-MYIOe${hr~jAb36o6rG5{>(36udD3LeDwr7R2HtrXxv+*>P*?Yc+^U!9ItVz7eY z8n_vDE*zZAbt7WLks@^8ylybbE?zOdx5JhVA>t*owdj3>$y@;hXd#{1O)z53M>LVv zUO49}=E8-!$0$%!B)TEOD%d$94=$cP_BHjiZb8}G1z%*o7QY_&{CCfKS?cWbs&X) zm9m>_WNjFLoq@lSW8Q;qgGuQ!PtCK<==0HKIoARNGlV-$0@<(KpuMzvG~c`tqX{p! znORQg3%1C$NlxGk)Jytt6-?iGc#3e^PmtZ(-MRdPT#meq=9f? ztEG+YOri-i*b^F4JA>fId<}aWD~4uQe@T)eW#1DhBQW`^BKMv!P`z4JB7Pa`}S%^t;qNxRE0 zq#1mKD4IWEmaP@v zCC*o%YbZi+2Y@XC6g-psaQ5Cv-@)b$uekFHEuhRB6Uu|b7YGSbsfeiy#Qsg0eErhQ? z3>-F2sN&7I@n(<(qhW`4Yg&vd`N~dsX&{rbXeMnWEExXBbJw?$M{7`u6X;RW)%b7% zN;G@Z-*cCf$uf&lvJb|>euV>vDR8Sv`kv!$bb`r}TuTCqNZ*_1ZSfGSfHjxSpOGVC zMPZDobmXykXu4!`$jCA+l!-9orj<4vpbo6HnPf}T1!8>dcvT(mT4kIx0H%b9BW0Qq zCLD15Iw=H%5(P+mwPD1dg!*OA`ug#EkE5JW8qIiVD-P=W4x=}3wr(V9-HdBM`H2@c zDx%IC6?L1H&2B+v`spXUY4!w@#&YA-ZDS7Hl!GW*ONr5FkG@r-Vjo;s-(@$$-}yAZ zQLDsLa1wYs3GA9NKWO8G z2rQBrW>~sP)8yTioM%ymNU432s=PSBs~5SC7|Rveci?O265_BK>0HGE*D#z0@y=3lG`_C`qvJYRd#djigy-@#4&29|zAMCZ#)pJg4zRLpuS0ll zP9daa6-W-Iy^Yq)_7B2Sm-aeBmNS!`eSeKz;?~)Nls#9rM-)}o?;xvuznY-7u1z5) zy7^yUVeKLV_K+c7T|G$ra6ri#BdIwC0}e_nTGXi)D_LWcms2imP3n=={sofy$uH9H z1G@_NnjUo3lE9;PbdJM=x+_f3hGfN*Ny94KezSBEe0KA$^Vmyaqb>q?YjK< zojIqnhg0lS0uXB6v0Y3~j%HtKmalb1q6A~{gol_=hy+Q)fajQr1Hq-4Rr)z6$pQ}{ z^mdy+2R_D@G|R*MIm7O0LgthTDrpaS3a1VDJOrtGZTal@MrF2&y`b?jqdyoeN=!_OswVjy*ROs-n_*{wp zp9687fELq!H?)MNj{82B!{o6NOQMDt@(LJta#cqs@OI&H$pFcV?-tOD#<9-^W~(ut z4~UPkVUBfUEQiYsJ4Wo=zW#)UjTEu|YB9wR7JgZ@x))IIW$& zce11Q<9P2O@{3am zn^g(zDxZ(v^rS+k<0S8K;$E$eN93mTE`-#FY#9yLZkY_Dc$Oe2k?{w(ui1m2bdHMT~clAl@ncv)abx-)XyjK1d6ISgLe&!lC zhk5f2$`8G=m7*~)*weE-2*p_@9A;>HVG z$-f~kW5Oy&KM~02z>sTC_~bz8!2Pak~Iw z0dMcY+6gp>Ws}MEtFVfQ9W4`Mr{mqbzj5*EzpMH}j zuXq+D@XRxl)-1nOd!T|JC@uX;{ZA1~uhTz3rgF}bTg6cB_dBlt6@KUA&Z6Sy#SKNy zna-lsON*S9Gn~ruWzRaC&SguMuXGl9bpu)P?9BQBZr7b}Zk zwp@BtDqFC@;a}nS-Xj>%Tbl%ayZHYA_`fLLKlS(V|Lgb+{hOY7OZNEf z^*`l-lHcq9Yx%CzzZseTNB6i%{wJN&uQ*kFa7wQJ!A``|lKUV0KbHSdOkW2-U-P%o z_A2nhBmmAJJGdVv)d&HP}#UcsYV~8>*Yl14 z>AHNruQ9I!Fw#O~aXDbemD?p2lWN+z0?w6e3P^${rUUFCVS3a7*Fu9 zGIK)Y-}=(|dwcJ8vsk>dp!c7UnsOIxt`ts~pH4q7eCu`qin~?X)<_Yu98^GQK z^!w6*qt4zlS^#I^tojiXW7Fw$ogA*6h)M}Z?0Fp5z_2O*Xk^pbF-dKL|7)x07yRoxr`Id4A zHj&4m@oDuXdD!fnMosN5L}B&Q@HARI2PhRjZOa~ z7q)%F#~%TPs*ns!v3i*&x+wQDzTIc7UFRSsqC}>)TxSBc19K?M$14F`0^{Z!|IiOG z*DkZGvUa}~b%SU2kYyhjhfb>G$=dUFf;?W?T!;8lg|u*iA$MQ+Cn#oFtHnkL)u9Un z0^s6Wy&c>#*~%;az|jDU8z^iuPKq%Q3=KEcjV3ASgI8#f&4#@hhJ!s5Lz==>P_>x0Di z!FYx7F0Mj|T##$p=nN24)N^(@T#+L3Ld26gOwq(YR9C}$*#fd0mL$3pABivrN%*W_w%woZLKBx8nEjESyn$M2@!dC-j~WMS(`7*Y#`bP zQ|c$Y5b^;#6~fz_=7QA9!m>ryUhKEfvDAM1n!nj&6GFcMilLYgYR53wZ}){??gyUM z{2|U=Fy>yMGc?rE89pMuD#h5v=8Mf<4Ty#tI5d0pvwoSqh^txLt0{T?UZyzueeAf8 z9h2|9BHw$AkH-_%i}LQ?pL(@b7MY2x)vK)+VHy5}|Jsh2NM;DO!9VFo65f_Adn}u2 z8zJ~KfLI*P@6Jp4CFXXd5({;#Reir~C|lOj38?x)>8BP2mS&V$hrz zNWp42lX(tFbLR~r;ladJn7Y_3jL+yBtZ^c^!vb)VjMl;jI!HtB8p`~_oH6uB_QgIj z%u9$I2U@y3oBgJK!!Pb%n@&gn0hM^g^4wFX)xDpCK9$9^^AsJz$=GFm(8zy;Xy za%*QAN}3M=vS_q7{7!MkL_;y9_`p>_>5US)H@s+!iJ+bxZ{Sp)7C-K-zrjBids$jq z1U!P|*oV?W=^ebQFX+8n+fgtYxp9BHN15D+*_H@N>N#GyPYOK5d9@MBDJ_6l(9J=w zKAt^6bMA4PZ{nYebPr`$F*{>$^J%N>khp}*e-(V%1IE%jhStrG>3CHo6rw~oKq)( zlGSC5wE}e#f15&BU7>-8ox~3b7BJURSZ*L#u?fRYqAYzQ9@ZY-@SzP zAe5zV4Saf@ZN`x{yFl&dg%?B~ZvsvsxS4XLMF`eo zr^kXty$i_*p&H(>Nvwy_=L*O_`g8YDh?CK`lV7TxDYgmwZXvRy9IWV2I*kU=>7TF> zlGg0p>3oQ`>E{H}-Lle?`w& zdai&fXKhQ&N;Pa08n^aFJC49egSf<}?TJz~yB8xtS?Je_0-;jpv$0J#{L=cyzI4hXv)~`9d;~A zLSv!Qk=jBhLCLdpGn2`_)p9cIboB@^i5eOq-wTEODn83*hzi}{cpGNKw>p68eizwg zlP_f?~71PE+L5%{N<_gBAqm z-yUrdP7?$4ahG}9{_` zm!Ro}4=m>;9nxplZ32+OzqC`ky%mq@(ru<2-_LHd68r-@?RgF*3+=C=wFAnJ>>Ryd zLibI({)nmb(NmfPW?>JElR83A)~e4L-99N0Zil`dJXF75f7bKkBnF`Dd%%o~ROSaK z02%2Wyn%VOgE=n;=Z8eT#FYU^P?8$%LUT$yh&S56K~zRu2<@T!t!aDv#{r)Wfs8Zc z=J?YM!5iV(1vSe~r-4>>p3n(ND?6<-G6OT^%%=*JS^k+z3WU(gYb20ehR_pF;P{s6S8TjukZCIrugV78=GY zzc;)culitY_%fniu?uPhP?K?+5E{TWhn3NQ`xYW4;}+NE5*-dSW#cVGj&@>d)FW5H z$V?FHFe45NVRrO}L)=Kx7XYvajeTTpCaGR4B`L;Ql(9yDydkxy6uo&dmKb*>b8+Ha+{PkCnwQ%DWS#LnLqJuOFgRbz1B& zE726kAXDsviQ)Kga#)Bc4t!9trxL$0s-f%ap@m*{3DbRFx)vQE=W)+A27@eAof!x> zCi@hJ9gN;XULE!4TunucYQKKpV@-kX#=tR`bh!l$1OEb`ZPV%DbYEJ-eU)L5X)(*v z6lU^`=6(dx)L4coV*`z&CFb=~&At%!YIJ{;S)Y7=EoRJQ3tw#&W6gNto?$>-jG6DD zi?bEsM7VI3Vy4zs+TGzQ-tV6A#uOV~xje^&V4amBY>OPWx!}rW1*uHK7#}G+mULSj zyd2K=`og70gdpZ}upy&n^fD+B;8N=8h?1QMo@Vg`4EOq3#ZgI%93^+GbpoxL6xF!Q z6BBAXDX{Luz%7S97J@An^xwvIGGkI7N+LYkYK%66b;JjT%ki#!nQxN$e>XF`%$kJY zKCCy?z)1kP)IbY166gebKnIiBl_d^vu0H~=LiY8Gf4I)G$c2+qja5BEAnhh0|%)l4bf@?2Fi zco{2;B0Gi`L!}%QLd85Ob&*4ec)$-Up$?i?pmsH@M~dMviySh`Z!$>Gwqa0y%nMsd4?2ZQ)hnF|pkF)D@E9pj7} z_9o6_fEOYWl$%$Z)!^jpmaNK}h0u$LkgOdG^DZGY4qYd*;V6_FaAg=T{7XM_?A7Y= z8539~!)2Q~3lXgiir0xb&umb5#S#lJerU6udw3!ADJHb^>~V>rT&_S&7>GMk=pSvmwW8+?Rv-z+0unZarXdfs6uK=qK>c-@)3 zj4VzF4x>~;wy38qauP9}uw2Wqo4AYE^oZSw)q@BHLmRr=dph56M~V_42s*C-olgQH zi4?6)yq}`SCLreE2{wYds zhO9*}O7`?#(KY?60jy&hFyRZqs}_vxxAS^rM{^TG^Q`7OXrOzatZ4{szyh6Z#jphN zO^30qc=u1L--gvrA=FI~!I&96HZu?++wS2JW*?J*Y1>X)5#%n+fFKo|Bv@bw43jF` zy1p=%To>U53vAQmB1%Vp*pc3E(`I7`gm!0~MBcM9<@vD{8eMo!K`!fwn$IE2J3jn)igB0;QY zvXHTbL)5UNFh}xlW(Ra>Wm`*i{+%#NHUXpgsEv5wJ(t?W!y)PXo_Kyhf9TfKVhXDS z#}{J=JS{{)9iE*~V`JE+R{=d5ux5a4(<`*O@mEQ0+d24+_uHp;2y>g%ex9l4C;^em z)J`r-t;eGFTkecafbfzU_96atkY4wNx7F|BYhUNAc;{#+HI4+5DjvfHb%rkYVT!<- z)FalUiZ;&c^@q+2K5uKZqq$4xi2q>kYr~tWvV~95Ktm~>pdjFIC3B~YAo5W~vJx008D0B5*nbAAe>pU~PqeBZgkQ8hyGEys| z<7cUejrF5C*R+C=cdfPeNlrq`_`J`3-+O$JfgjpF$a>=G@}$8%;n^Zy$BkG5BN@80{`(^(f(>|G%2pT z&3gpRBhf+ik|lgzBIQCO0prg2?cb2ema#v>>=m#o&}5nCR7(aF|6#NlK!H1*QFL;G zh966!_9L(;_oC_v#huEAPMiY82R?yM4zcCYVqED*drj`FN9Vz-L%lB70s3C)qL_eR zZ6m$>64@)D6;?Du9ZjXmkR$(7ud<=rt-Rq<+8ydew&*7on|w@!mCQF#@vF3hJ(SQI2j3pR zZ|fp9b!G10K0&a+v>1Zgyp10uuI06(|HYak#2h$ip`8CgNI$a4FEXzT zm=xUxd%>E+;sZ7V4cQ~9A$tVrVpHpLVH`qnadQJsWb%e?!L1BR6I|hY2m1cut3(2e z-#e;*HVj&Ryj0Pafn*ee@qp7UxtPI#AkPxBujT#ow2cmCK-l6N&CCu#PV_oL$HdSi zv`+?0a&aIe7m^10cNnQ+e+MlWULtrEPUh+@xkTUe8G2emZxc1eHl9uugnsz*sYhaH zc7pXpeDDffgWgWX&cNmw7TmuZ`W~B^NRdYjeh;y{sV#^`kgwAyUuLhom*!hs6NtfA z1ifW%+l!@2MaK|Y_h5;*D))1qV^iZsT1l}{L^yd+1B zO(wso$t+zC2*s9VP{|JAO!N6SLW(EHiY+fWG%qSl-e3=AbH^H1=jT7Ot`nR%WQN!lnQ&rNox!vuSTD1cr|Ph!`9o-Sf6HtRksh%KKu= ziX*!SclfDn@~?}IS7Bg5qk&c{1KqTt)vbIMUIyaW?F`?(G|L(NAj_?M<<7b!5BgY^ z6K^xH3D~9jX&4qOugXVZ7`|r15N|X2N6EcrX@NV0R4L=b?N&GOk?3^eNbDk*bA~(g zQrbwk)D41uD5z3bhl9ofp2T51Jk6%SC%JvHtKdB`bPIa1Re!5X9qm+Ut{ezFjom)w zY$U%OA81$w$`Vt?N}yD?0$GsA z+#dnt%>3=MG25Bk*?sf*0^l8(kCyA=AJX?{FM_FNv(^?TSiIa!9tfx?(B@R=#of%8 zI*^d(WigKfpO1AO2M%E#05&PYOOd%W{3In(UI%R1mv4cB5L=$b8JM=^pfb>4Y-f(_ zfj;p~+MJ^-*pvs~Pb5-N477Eyi)}2t4@L55r}g0||2_xy59a(jp=z#ZxSo@IP19k+PGd&$9m8L8-C9<~#C;QdgfQ2b@P zM&8ukIXPU08GjZ}WmCR#Dc@*qwaKTlq>HhGO$Pr2t);XnmfB&b9zGAoQU80(Tgf}i z=$zXBN9>zADgN$cY4~X@0MwZUTt(hkz=1BiqziU6_bOVB;rfo+yGPEXNSh8n*H2oE z5PECEPmpmhe=?cvj?X0*qN9_uZ`lzN3+Sgy3ue>7cuV41hvSYTCjV`k@7LD830G1E z%sB2{78Ekh$e9*_t6xtfk_oO%`zpV|P9^%5e}Ms%`zPxK8Vm-8Q_z}n*ctYBL(|e5 zqd4|6liRUB6!GsATm0Q(iv!H6f)-?U|2gos3He}-L()HcADOJ15yYyr6nH?UjLfY)*)KT()Z z^Y-CBO-V)T9I`f|b`C%utXW_&aB|Q4;|>YJe4F|xRyRGd?@&VS&5HI;7}I4FcRXsM zzyLAYn=_`1`%aWy*a|K2$L+cV`6szg!z2|ayNh!H-%LJ7tFyAY1x3aag&DQVg^qKd>!{WbT^ip471_1 z;-NOLCqs8MIMF<|>9iK+qrr*bG4wf&v>!}zklMjG^ciw5`oixiRU6FhGDe&lQk$Tq z>JL(Tv*PAnL5oT?IH$bScr<`$K%cvnqi&@KR;sLrI=#-eY%hz;lZh6gUBYm2t=JTM z9OHI$TeSeQg2)U6p2V4FkbAv?FX5yUsI;EO|4t4hRGfaK?}4qwX5H;b+SAJcRch0h z=Am?VG+UdZFFWauX7f}3pLk>aS21!3JF%Ow38{c5r7hh$m{nZS6`K^?G2YyRw`0YZ{8PDQ+ z`21EHeikc3efQYg>HA@`-b|&FA-1fIX5=N@yjY$e;W~c{SM*IrF|^Kz(`zJ9XiW3b zQ&fTlWDfUsVF`;{y)d2OK7?1yKKCZo_a!Xy5w+nW!i8yMBT914ogmxJ$wnq?7}?#>}IMOqq^PdQ+a4lx?u?wyp~ql{)5gicS{Gs zz+6ar(v(Mb|6E-7cFMN7!J4$U62__heKDY$mU$E z}Vci+&$)WGXm@8MM=}1|(iW5+=$NpDd|Es1fA1l_Fq7j z${#Q_AnscCrcl2Uo(*pr>a)4wGmt16BC~fJ2tc~o%OKqB#e_=w1#sz9Bg)RTgMdD9 z!;o}Q|1&9>`@C<}f3bPx+7l_+i`_#@V?v&;%cusqGuez}r8`O_sq0uF@rjf*9&xSD%Sb#Am_BVz7oBOzy}orX4(;4&@V!Cstl@vfwJ_ zc01x!{H+f3y_Ie2AMbS(djO^-T-^nUYsYymSt?& zs|YFY!!08$d#`0H%w=ZMJHI8BLVmGQbww+!d>WMb#Yvu@lq@b&v8U0K ztSa$|N$!mKpsc*%;3#5q(cTste~O%MWE_a0Hv|fKc|adL=n6lQ9y~~8V;^BSgS@dB z*EL|h^ic%GzhNbA^|#myxBC0e?9}??NYb&O0n*k^8a-&?G{dFZ^I&lN(==TMO~k+p zlmBK~v!jO!1HiPl8qeO=OW0Q7_Tdfcv1EV!nQQ{(Xu2h@nMcYQ=dUOX0(8FKCjmN@ zfbVf&^aR!`X9P?vPd_h|?l1cW%$>i1g1r(IESg1TF?2C5fF7h60JVh{sfI7a9pk<7 zT}Htk{;5G)47Sl8>HVp(xYvVn?Ja0qch6v#H%mtOH*|qU>}&92WG9*6n@MP$DwtsC zP=3LpjZOd4aT&)wAWelyoQONz5Nahg6O=g1kY@o~(sgV(9TPq|3IFIcdvcC2g~| z64^-wUxS;YuiA`T^ZtcK!f)z|i94dOh=mq*eLQAB+|eEFJr|a#io-;xa62I0Zh=*= zhCD*edOnX0{Fg3{Up{e;G=3cJC1F`DgH64k4L0S-~=A_Qjc3E&Hxf+)ZN*gk200Ta>D3JD4V2BnEa@JUoq!Mu{#TKw; zn9RMw8A1%s!|K(CSiRk1a51LkpJQOiO!~C+4kvfvpd;qAi3p7$4H3EXd2=%MLy(a z5RO*0nKXzJ#Q>?SMmh*rIp~zzvw*TD&>LWQMEZX57nFx~m+GKREtfJHBi<2jDHLOT zp)SrngDLWmDN6IqoE3m6)SDr(0OgGJ7Z#`~W(XZgg`mU^(7Rr|)AaN9leA$G%-bU{ zR^>VlOi}kN#)C|!Il>b*mMVR`l`u3XhT~m_alqPM@?i7aYY zRy@VH7BsMPkH)o5@j9A)>`GZv+UVm-a%UzF1F%&2I+KCzYFU$AUGbEjKOCdd`Qxrp zN&dKI6ypzU5mu}5iG~JAJl&Yi*p7nNbjp_(vJRF5& z*ct))#@42C#FoK3Xprtw6K*<6+kOd3~%&S@s;udG?&#i2^7N zxl2%@-uy`PsKwAZ5&gZCAL|0w5906vVcY~7^f$u;rg0SHn9i3P9)sQ@lw^(jNx6yWVTa$ z7n|Nq(nLJ1qMvfv^g8QVlrC5FlnG=p68nHr`9<0S1z~5B=8Aq~D$Uxxg$o^La^gnZ z82u+|+*(?iEK{QTr3v2{T?FjsKn4YsOShf5jX8br{WeIFvAw)9d$D;Yv{e; zRdMrUhNKUUTUB1=zAq=H?4G2lXIn8e6FE-T%9B;KLHWS7FrFyj!=p8uzdEj8c8*MWqFXPUt zF?J}e@4d8G13v$4{7kLZenPL+x=x&##b?vfx*^K-qhy z*EaUkuaen-W@7NiBjzmpD&-hT4r_)^j2WTUEoI^2^SO(e9S3VX{mv*{fZ(Z#U(8k? z#fWzKV}pFcxNaIV&rP-$K1PlXp>do#LbYO_+*i0LGD#5Dy;1Om7<^1%j$mNdCWG`w zY52)bTEmIEF3B^B_tDuq=E+1O9Ty+r-FOm2`BHg~j*ckLwUdjby>H!q)}7j;sns*4 zuli-@#qPK@NX4moLF2qS#?Ctqd$k>VOPGR$I30$LHN8_KbZr+S>W!C_ivi*zH!2J_g zu#gCXX;iK^=10_=c+}t@Beq;;8q+EMGJ=utn<<7YTVGh(#|qPVZhYx)9p?TU|3&H+ z^LTX30^CX_i~n49J~-PymBph)`=((X=J5;}rl#Kz(RIf*YnQW$TC)z&c~eXYEV zH&hJu2;}n^I2YtfIS#X?Q4FHub}6sp#;!UE&m`}MuZ_nO z1~3tdtiMF=H%JwGUkH!pZW^ovuQ+&@Wx*>Bc;34X(?|c$lQ5Wgd3OIV)BsipbGi~$ zx{v~$B2LcCA<+*5=?KOBV2Vw$E5E^p>u-C&!;z{ecN&#O{6uF!)W86{%7=F}b}l)} zvNM{cw8hp_?)@4RUt$uS4dwj1m!cj}Icv9DT2*-zk5i-Ly&34<;*b!qWPvpexe&vLKXO zuy$n|0{1Q*H0Z-4QW7oSyF^%TV5d&*1yX1D)05x9=)^4duq61T6G#51P>KIB z`RFvTY8zhyw8EG}{r?Vzz*m4(aUAQTTO%CDbj1|+J4#uP;y>2662H0MQOkN%|1pXT zWHqu=;HX(-a`^TClQ$!tC7m?S3+#A3qsi*wXmZRpc-ST%BbwYe98I9fo!Eg$;h00i zP)1s(QD83b3hVzd?EfF2|6n#nluo?nONfA>ZLurSF;Sq!b96uiY4J(lgSgG&_#}zI zt~h!W_c5ic4=0=(@hS?{(WAPLsbzgQ^~^}Hy_*CcZc6LF*ivH0yJgzIeC{=1T%lu1 z#3uLjcx{alYpxxmp9`CecG1yhrwHjLllK0Kp~;NzUioO@uAXtURE{7Z|Lu6mQiF66 zhALVpRPpV>*Sw7%2nOY?z$?ZkYbyrBi;lOvp_fF*o3t*|UkVY5P%xGMLi_?Nv3)zo z=)UH6gF*Gnw!ycSD_z)kaaw@-<5IwMe+7%^Zrjnx1AGKrZTWH9h&oe#T}r3ea-dM$ zp?Q>bSN7Pcd>fRHVg@Cekp=JbfRF7v|3P3uP#@BjJ%_QXlbX|Wf?Mg?c_HM74z7i(xlVAU&*6DEaF&Bwtf-4O&-$gJu^_!1%tq3TLSa z>_dFNS;~ibQ4HetKJ$1!#py2CVT*;0EZu;^s4 zynA7_>s1^_Qd=ok3oK?#%clY4PP0C5ie#~`Q4^()8^N}mc^?FhGe$y#_2E|iW-)|^ zgTM~S#Zx{-H=4xI!v@+_{qYm061K*J!cx-9d)Cb7cOS4D zQi2~C@W}gVI`Tf=$Z9DKd)^a63yGOcduEatzmKOwx*K~VZzmFsZSO9idtatRywf9Z zdq=&y0Q&tN;oY@+vmns@HJbGC$zsU3?&jnbD7TR;6tWAM=;9ZA$Cd0t#DNZi^gXNA zDQ-d7nHAu7N2PrvLErVccJKoe#g{-H{S`&KOr-!hR}cB!QGhJaAgve^!Ig%M5<4+> zvR|QyvQNsf#X}T1=3j@)ndDVlEB4`#Jj{j!uSQu-!Dqd=5jRsOU+-yv#@@ue$yfu* zHdddFQWz);%Y}d@gt6yNk8rP3Mq4z(X0eypudp#Nq;wk)UDDN?s)@s(LGKGm&fpBO z>GM;(r7 zgo4t`BLs&%2L*o(&xewk=@u60u@UmiXTVtj#xZzN4Iq37UU7e{Z0C4Rr<<0Qh8>@| z6fl-vL%ox{IRxg=8Dfk3v-pc<=>p{dGGN5pctR+YF2F}XD#EKRE@d~tu)_(U(Qys~ zRX;z^+jvx94#sY|&FEFmOXk^?!}3hX>wk;xsDSr{dHt_su2(2JUXD{--2~S5bi(6l zF)cscR+1m5*6ifwMk?Ug(S=t6(jgO=%ksNR)phXZILyQjJ`*pnqefaRahJ(ImsUB{ zUPnIdfAcuqM<`AgJ7iaebP-ZvM>k;_rNacg-AzZS<86ihY4J8|v%x<(-WF&!`Ntzs z$&8#5k$b+DBe*?qd!F6aZqJht0qru`p>Erst27Y@b`yWu0belV;QMscM!JEFhrPEd zHcb!o8~g*q_H5+to@bLkHTeGo4L*$18ST+i5JA{~Sl1i&@w4>!Rap94^fX_#8+4;U z7lo=nGJ6|$@=#^_KAhNK?TU6#Eg4hnf)KK1~rQ^o<|9lQ;yb^~1#H ziNu)Kl(*yqz+*cpR9LjXHT}f@Ci7O+9`PymH0HU0%P z|G2>Is5~awmH%LFn@P&Q1o+E+x%_h1Ni4pzy+jiFcL0x@_+*3au*rw!G2vZ7Q9Fsi zy)&XVacf6O_?~-nV+(cn{bjQkBJDn;S@7U#oyue{u|2x`!?HQuV=|88mNNZ1K(mjN zwg{M3q`kA&T}XE#e;;pRhL-G?hek9{lXw3}UoMFll@)y6IXa-9|1}frvpo~}R5U#Say4`#+9{R*+9{Sl zq89)lV5nFE-q{0gPynAX`d*dhYsB?MN3rP;ip3_nFb1h1WdrPUfOQm`16124y#1!V zScHET_%~k24d7z5*o>D6=1^@3uTq>VT>xuXrFg1W-i!Ap8CSFypKB1e7N3(J*@y7W z_=Yh3c@K5dn-mE0p>{uNOM1GMu9Id-J2uMnebzRbGdJP!5^QyoNg4-0V-nb8mU869 zW)n|YC}rj;Bc-f7WsppeGH`xKUjEC*5s%ZteCcT8?MYL&Etr)qep8EcacMM2qjD01 zM3u5m7e4&j?GR${uQbcD%_?=Jc~3+r1gU+;mbEfhY`N|lv1RE(Tl5nns5DsMNBfOq zy1+0~N=){dAITjCXJx_}{U~|40bK%yPH$VmI~$hRl^zhB!7jr-r@YV5KgIJM7|=#ts%N!~KMKe@eXA{1gApWgVNe8@tqE zGkVwXc%yVK0~;BbWM&fBiNTc7h8r?5m@_cknu#Gd1A`|6gKM?Ecx`5JOGfc~G8-@J}e@J1$vtr-}OWn#e7HF^wRWMaT$ zIeHAIGci1#)&|a}umI0WUb<=ovj|TFCWCNcQeqIAj`%r9?UTYTanPo)G{!%hBn0Dh zdlmnPQgAl02*xP)7W(+mWaHUoB>0XV_f+HA1txe%kDDxrvq(>{O^@4@+3pNc3jRrt z+nk9zL#~2Ndfd60xHE(-_?Qm&($yo1TkxOtSS^`YGh{Cq)VFv-W{WcfF}O~TJ1-M= zhExWBs>dD3#GN6c!4-Pk!A#s4@)}&C$GtfdcZTo=i}bkf&%~V}$-xDB+*>knXNYxh zrXKg!OxzhV9-OMjO*dwrMc{*?9yi^keHQ5t8uhpz&ulkS1+jsX+AX_D#7qyw{&o^K z`C$EN75I9Z!imGbFkwis-ZK-vJCCO+F9BT`Gepty6ta$yIp;yfs#FesRaLK7<`y)0L*@l zfgL0D7RYGVO5fwhaJ&koHDfJwpMb%`Y_p#mIxF_+Jgm4A%J8*fC!{~{Xax)=mi5tw zY4PJ?*iVqC{$P@$vo`6!m7RBIzh`5)#Zum z@*`mEyObD#i-aQkuW*GiX|9w*g zq0%A<3H}@Id&S@Reuwq%l>a;58~zS{`7GbR`+fHt?&r1@SsSEs$zxqpUb)&=56=BA2zwv(^Wt%Ds}O9zHdAq~zbM1$5Q^D$m^VhBdQSd1^fMzRI~(YszP@DX**Z z)vTIbS-WOUZOxq3TK>hgRzKBkwYzOrsMG6P<*zT7e6=-~lvmW&OHc@rudA=ES!Jy& zue{SEecxJN-(X!=TVHjV)z@I1j(;C)dc#%L=?&J!t|DuxujWpKm(?wtUS)Mx)IpYp zYj_LGSTCenYk75bZ6y-Mz076x)j(J3{dJPnQD0wM54fswM#?{IUQVZqdi?XioIVxM zTC2ZqSUOeK`m3v~SY(w)vaa#0sja_@sE=f*@O!cyuNB(dA-N#!5XbI za76tL)!+`ui5YLYb?(wzt+i`C_1@~*b!X-9o2tPQJ^^_SOJ zJ!?HRlC{Rarh?ZBX5jkS4R=;ptLkg(>Lg%{DnAhchLW`*Cu6*;eKr2|bF1#EDPQBO zT=_G<$M0EL?OWrM8rWD9sjM0gId8Kdhw5*u7+y~5@`a81G=-1atF^`>@vjU(1b{aRqSzhhc-bqYQ zStYAYXR%~IfUkxTdVB3UU=eA(6}oUImUb<UQ3@A zjPS`J8o&2xj` zLeHRC9AAz`=S6A6uZHf_G|HSxW zj|7_VPOH7%2e^fDzqGox{>+lDn#wtsSQpm#DrW=vJk^Ci<2mNQf7fWmuJ?JYw}DIw z4fT~;OYOx)S1!2BwjlqCORuySTzS}>KJ&SI`0bWzS%2&B){+#)9@~@mX%eu_H1pi?CN`DP$;QwhY^S|qtCI?Kw{#$?l z4^V#h`|kI@?^jY(bd`06-BaNMgKqwuf;pGY&Yw4{%2RQr|I(QZ@c%v2oQAvBNaYpq zlu#)|;cwtUO1E9gV6s&08vy#PSv%v(fyz|=(T^8*G4+kGJ0(|TU zaLWkrb4P%me+CS#W23G;m+|KW4lm^CoA@)2!?*KvLRXI9+}z&5pG6#g2fqPzF3-P| z!?$p__Gi{BwEX;U1bm;v>$UtGUd7?}YV9Az(i?ca4{>;4G)ph!`Jd$Q2!~JN@aH+a zhr{=Cc!a~7vs3NB-+LU6*DByIhm-I#4lm@Zk$>g+jRuaN!#_# z4*wg+e~Sh`howK^`G3aY0g>Kcr%9|<^6a7Z>T|jq_e+bJtyoUq6MAmYFPF z!r`)(pTmF5;g4~6;l=6jr#XB(ho8^sx|hQvvswBH-u_Mw@8W_xn#;j!9DWBExLY{> z4>UX+Uc=!796oOzOE+_VJE^t*N|v_s{A03s{sNYMFqb_q;P8lpx1YCj7QuPr1Pnc7 zzeRWprcPfC@#poFKRXH6a@?N9`Hhcv4~PGh!y`P+yCK}8<>$Xv{!|D)J_(=5pZ~_; zTAFuDc#gw0eRM5<9^~*lc=`(d?BVc7d0Nxd|3%|DR;Uxwe8oW@8WQcK96&F zPX_!C96rF|+Dz8Q;lk}Ky@JELwDxc~7jNN14i9kn<(y7&4v%mIn%>AB#oNQ-6&ya1 z!FJO|}`iEH(@?yL|or`~7kLcwZjpJkR62&iUg!-tXq4&1L@~dZ`ux z_?<}hPq|o&WPzn9Uo#mvAMR>D2jE*K2h+fz=Ffo(OvGV#oPlQ6gEP$!#MqUJlpk97 z|I_)t=($o%X)U~7h7cMi@kg@c<=uZV;#zpDx-gtB#k6urB-@B^sfrZ03?Z_K2*53_ zAZ=sLZy9z#Ae*c_iy!|0x3m-~{7;dx7@(kl6Qag90hRBu(dG68r@m*kzG zz9CkEh`6DGey2mN?S$;srxIQatl#IH666rUR>`JZ6(rg;pY!tfua8}zJFJUHtd^Dc z{TU5Am|6+hj??;>K>HT;t2T|T(2wdw$EDV8t}u-u$)mBwB>lzP4z_+`X0s}g;0sG` z@`jU^H1yEYh+e{Lu5Eg(S_#M$rcS^HvJK_P{mkCJ5rt-1;y?EiX*-<7ghM)NWn`g(AcMQ z#tP-;&xRqocU145 zOv-U*!PbBX)-N(Q0EP}ghQV`8!ee%}0=a+&!Sy0SBT_?R0YN8>pqT8s$$*EQ0 zUhevqhgz>+J7MtZv$0BlezNh+rGa3{flgRrP3HK55ae({@!6lv{T}}~iB$!Z6+eSU zXcss|HE(=;p|-Z8>1*^*Yqu!ik2GSSB|BmmaQFpK_j|X!r$Xu4e#d!;4k)NP+dF#3 z=gRcz)x85gyHUFK#lXSjGp#{NsuuUBj=VbC`n6Q0^zG}yYc{K`-xl+~wC_gk)N~t# zTzs#b)bPMBRP5_o3a3w!Dv|t`NzHK8?Z{gloIUpL219&PUvuM4Xt9re*+$ZbG^%yw zg!<9LsSkYzVp9%a4CBg*8ap?tz}5U%qoE)Z%Yln`o0YCzYW~qBnY~G>j~tZHO+NXi z+P(T$O#R!??8;Ax&pe!ls`7QDKdy0%uoe2!7c%;8QH*b{cqj~}&upL@A6(z6`~e+5 zxO%8%&(H462WSQg>#$ipHuF$h(t*7+T&50CbiHTR3y7DiPEdbB-9GuF&g1X$vYCsW z*Z$t7PL~>o`#L&Bg*E35zP@=*!mixGf_kK5+U2Yg>xJsf+j!LlN55bFdffri=Zc%n zb$@?c!p-}L+t-KQK+|FxTDzUrT;kzB&vaBGBbwo_4tqYS%X3};IMpurjVrBr)D;g= zPdGP!?Ua&$u;gOc{RNJpnvCqtIJBxxFiYD}Hn*l|@N|m#?W0PBU^nTk@w|bm*IkMd z4y^@`LSjr$&=%W^OU7$n=|9yhaUy+lzbo`W@6&rtRXuYf>#ZsLk>{@44c^&fGETYq zTDJ;MZiCh9_U`yr`#6}qDX2!KMNVau8mr@(|JA7+#QdDs(W*S=Vkb{BxO~;w|D$t* z$7?71ehjOTKzyUUBAk7a^bxqb);b# za_Cbf*y87GyU+BTcg~;a`CQCEsN#8FA!I18P-D+|aQ6%}UMa`6GWT%Bu{RtLI-h zWzyt35C0Hp9vR?S#d1~IytLT&`ZP$sEwxbP&~9C`0rR=L=dfz^3BWhsia+zC(u&>L zuP_hu3l4jHC`HIJU`MAQDXy0=%eUyK2><0i#E&*`OG>i*WZ+>nvFoUOL{byqv` z#_{BqKTZ*4c1Ee6%-_0QKalnJx!(iq2;+*&`FYog<;4ZX*uEDU*nsmRYx#P4bnOe{ zQD)u4yO>+1^T!pg*?|oL?lVPDo`De=^OCWrjyIici{v9oc^|zA7k}!+M~1WgqP4pX z*0t7C4H(zGv?GmQY4jiIj?~%+K4^5AYRb^*{_MW1{V3kCy21}^u8k?|N)M|rIK5Ga zerE6q!~az$RY=r2aF2HV!`lqyknx_$jMUb*uXj#Go_=iq!rSn){?GD$J3H;Q&lLot zgH0l3>CBqZ>7J-rd+%H?e?vJ9qoWO})xY=3cl8gQ;1`G8iWjK`R7;mvWEWJ;H_kq2s$SWMxrR0bJ&Av0w;Ppg7!VD3<5@kn(A^h&ao;O^mfLg*#4Li0?-7OOkxrO zY*08-%5&Igv67d+j#9nLQb>Y}Gf(s=u}knxA_8G1Nrhj!;HI^^DMuTbeZ3w%dxzb8 z6}gx+B2g&Hmkv)SEtJUP6xpkIgcSFe2@)y^W8EMK zgd(yW*Ok(NZ%eY3u@-{F`oP+HP-&bAXTFQD%{I-P0!HK|VkHX$V=X2>(X$sKN1+m& zU^~#Ym+-aC+dU(Dh8;!%m9tj&+1 zuVxP&xNOepwX=`g6ogcCsJK2tP6SR06)N$+=oiG1l%gesUr^WF+Ajw2@W{YIg}+)xU-$^>S?JT)PQ zkY=xq^z`nkQ2%=R|eYCdvL` zqKZ|p3NOxqp>YI=wq`;_$Ab^9$zSL+|q$~24f z!7AV6L~w4qrStVEO~N=*U6!uZj!85`2t`aL(B<}#*YUNp8F;dguT?LTl!O&SJ#Fil z4IfI*Av%)EcCrv^tnZk-L|VeVO&@{@@OPp=6k zl92Eus)aC6l1swd$^tfrL@1d;wn290g_0)=KiOq&o|FgdEqLMAA)F(WSfC9?b5`&G zKPHGnf+SI!t!iM-rYmJ>WE*)Oz&UwfCsCt!N~?(R#O0|-^N{o7zG02e&v#cDc(Mq* z%bs8%j5xr4j?cSn4A^Xmv2VD&B0o@k_*~}dt-PX5j5suJ324PAMvCh5WLNBpezM_^CJjk+11_aoGm#VirS{aKS3b-#SSj( zhSrhus>mcai?|_wavkg9IP}|6lPFoJ9fqXdqmcj7dMJ>o6Lgr(t=dWhumpi58=L6% zm)S!o6bt|DQqoJG()%DsmgPzYslq|b?x0?Je3C$d9j3xR>mNi^rfuPT4~>w$AF}tK z*8-&xH{mtWu)8cZ6<$F){}fVysx{k~iRDEhvEqC(o-Br<1^hH6G>Jl`xODtTAnTL^ zR0zdm%Thq10u?Z4w`F0yeg7I}iSLW@>r&VqR+EUMAk!LDXkiQ+e43ts#EAp;Vn%n@ zVPALGqsz@;5JH|xVc<%K8n|ckZqKl2ARW4l>@+B#3*waZTLIh;kM>T9w8(EP^+tD2C z1Yi-u;KrRHtO|-8vnqt51?dsc0qjA!7|-s#mhkKC5NVn)R-yireDBtRFjAp)lxdL& zlHhCiD1m2Vpdv6WW=8sc*&t37!uW)wJ+3`dNR36u8WO@v$zDwiT4O~z-?2!bvDB2r z?@fmT3Em{R-iS^`FeY=SF*k03`^$B6C#a~G-fy?+0NU(_59rZIw5|GcAlnHX7K>i> zEUcF^?&Va#7n2N>5@}&r`eOh1w$2sC9S2((R-PReVR280H^xxTeH6i)MICdnO&cSc za3mbaLGIG3DaamxoMDCwW$B&ZA;V94m&@#(CBqa?^eTSNC&yj|)(%H~pIGaT4&>Fox~ z>fYM3Zxj+#`47my^TlPB5|W1)&t|v%0*e`H9OlMXFR)^cqIeJQv zA>>8p&Z(dI7zL5E#grJ*st$_&2OaA6ZZ%%|?N;>6Wd_ z7AY*Mfe!7TB-?M%xjJ;e3S8Nb?8uvLDP&gRT(*ebi;N28 zNgg561&yUKU3&xx4RX!3K1#EUm5eE@=CN^~;Q>0)>c z+avr*#?9>2oX7u#3PQ{IkOZZmggeAd@HGUe~m6Z~lcqJg(lm@a~9mFJ9%}nYG|O)FSX}I?x(3pkCZCipQmG*AF~#Sc`9@S>#tC rzE3k3Gi$s$y1#tEv2yt1P>wTV8N@65|AzRWt?-4f4OAhfkkJ1CGXBe9 diff --git a/files/board/arpl/p3/addons/atl1c/bromolow-3.10.108.tgz b/files/board/arpl/p3/addons/atl1c/bromolow-3.10.108.tgz index be850fae6feb3d0897181bb562adec77ceeb814e..6855934a6f90f3d7e40f0c2d8e7bb1a01cfc66d6 100644 GIT binary patch delta 21629 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 Dy{_hd delta 5157 zcmV+=6x!>tsR6R70gxR!#-XJi3mHrhM9DnJ$eVTo5eWV@Yb-E^))f}spu0#j;msIc zU%x}B+HiLDz`A;*J#J;!%ETaK@?()#Fn^rIUGrZd{O&9+#;@zn;==TA^2fP~W)}lZ zaZ%wMuFzHJDxS?bim$zD92eLqKf1x;;QWt%XYIN_LigXz|3CfBoVE4|u)yPw&)isj ztz@8s=M)wFLI2No6^-%#Y*(?1a}-`Hh0=e2=Kf#ncRcJUaBg;ODRA85DA=&Nz<*IW z-yv78c_Q24ShK2nouk032guqd9&`N7y48Wl*Esy^HaJ9}*|2V-!{=J$SiJTzu#W8T zAnu7Zvg6U!kFJ;3Y$yO8&duH>%gdIQZgCXM(wA?X^{D)~Yt_u}tt)`pa&ehhwtP#r ze{J^vwk`e~e=}!oShr5Twuiurx|G$)<;s0c2UK1IAy8ma-Dg2B7 zzm(q?|0gT+|EP?sod4u=`WHIAIkVIK?*ji972Z+wf9(86GkqEQe96BWkMCX!&zobO zTfp&Gp{qZdg5AcyQ@I;C8$fyRzZL#pyrhC#UOBJoeg0cBFG?exul?is-+xqom+MI9 zBe5wG8y7qrbk0E9t$t_{{JS()?Na)!O3xR8 z8~w`2YB|SWJJN4$M2iJx!N_f%emvNK~eBTb%Y&E9sGo6_l+P{#DuY*HeTNVA8;>SplxiP*C^u8F&W;|3g(b$dOirDdsyB>smhx#Nk1 z#Fp8l+Dlb1FW(w$K7VG%wdyhXmnN;mvQ2oP0~mH?U4@tXn8~Ys6fc(j2YFRUT7w&y z`Lyj1WTV*AlG-pAv=(uO%f^|ya++yy<7Tvmd>|KBz_=R5UY3O%kdAMWtPK*acy%t& zEca;*yR&e~u0s6qhke?vJz2zRJ+e}N>t%UP$r>p~q_v?Q^?y(s9>6*N*WY4!*Gv3) zNsCkgPp^93r@g)tDXa}ok+?HH{ur>5cwF`RPWrt16fxeljXvAU3AwADMv+DuZQnzm zx-R%UEPfm0+DZI&w5eDL9B1f@3wiW>dVGU*mP>4!q%F2f+8tV>4>GqOXM+2uViL<> zi_LbzJY3mUkAL)Hg^#_C#uisBPr5^^Lxd219#bS3gc6`N*dcA>9lZR#;E|x(VvwlY zaMBe83)66GeI9v0A3R5cUF%_`kG)EtdB2lyC9`hfB&8#lG+~7}Bv8`+3P=JU!M4T9 z$~I=N{WwvR_#*g;MP|Xinh8K+QCkLTb)^g?^g--Fihu3V^+brAmsm3rN$hr~#8x|p zB=wA>oUxENA>tW1)Hd3FVuiTE$G)~46vrs@svk+}DR1pN$VAtXy)j}(2c4r~@+)ck zO%gA=+c_GL*nHjU`o@H5K^$pIEIu|d-oiJ&2+9lLcS)yBe6Ar*qD2G;Kv4o8h+d2 zgqQuT6_@U~%2H+Q(wGe5!A0)T@xZ2eYujg7(c}N2d!EgZ*#2(LaJoF{`~Ssfe2^KUjO&3!q%!7d!9Gg$Vf2%kDH2i&;q}@vp^4D%(Veu}S;S zgVYNhJqhTNeg&A7d0zIm(+uHoRCeya41Xj8jYRHcE2k)*OdCTJIO+Oupus;XfA06O z5<~A&cAL0Dd>iln%Li`OcIHB!swYan(l5_y=96|4m9xBjn;2Zcd9_UW11*SD0H%=# zj-_coYAa*%9p$e?k0q-h9{4_OJygR?A^aGR#bWnlj++h}tC6(p)vY)RZpN;_Du09@ zB7%BADLtoX8sVlKa`q|_lGw|Noc)twwYlalK3Rd3o?%*paFdm?zsQM+e|jX1{wUQ{ zY^y}|9iSJL_uNXCsBYz`qFFVrIXh{ZCLxW>F5nW53gHYo0mR4!%6Uw>CFS>*Aqs9{rRBoc{>3EBse8faIvvJH5S&TAm#+~=w`;ogMgSeg1Gw01|0&iorDV}*HRI0B%CveLm*a`xRNd(aIUDA9o&g! zvXi<{GFc-`Bw{nMT23?b7o!2sd_EQ2Q^k15`5UmbLp*?`EwCJS#5^44Eq_#e@jwP= z7X10HL$2cotz!{3&aC%FR&4$vkx1vm_M?7qKBj4yHeXSD>3jzDG~b`g7CM#In+2&` z=^YXxt$uZi60MmYP4JwQQ38s;g&UKE16>Ln7nnSi()&GXW}Clr-1&^g8fZxeP70B_ zKG0HaRa*H9|NMqt82Hr&#D9T|K$gFg=3&&*W0S0P-8j*yw}PE+yHTC4JP#?G=w3JqC#2>2vBf9Diwxa+M)oc&3QQ zyM#jsK^f(gA&U?~=PCUbycf8UjSvp;MigQ@jaimU88MVD=Sk8e?>fpvrDsIliZGm; ztI8pAO4Xi&2`IY$=`|yMby0c$W1m6aQmU>hZ%&K2)lR!{h5$?DkRwe~ix94+0yG1x z;!iI{MI_jkOPUFKu7BdlB*4<4xvO)6IJK}E*u`!J2BoYzN7Q8JT(9=DGgo3|eIl#S zHPHaZnc9!fok}EV9_Q4uKAMhwH@&p|NH1+5QR%Xgbc9jL&nT^jCmF^=AXY)RWa%Kk z#8we*cQVzDxQP7@(h8ys%Zb|-+YTes2PP1Eg4XJ0x9UJ_vwtolH(8zlh*e=ZaaSY4 zT^$=F3R{u_f!M(jtRAIf&Xd*7LF%i+(Cu!ITB*-%giopVY8QNj&@*^UXnUg6OYOzj zDGUEz-UPYx!UOSki~N1B=E3E%AVNv^VEI~*Y#j$F6O~5FP5{FRS#OR3IhaIh`=ev$ zqMR`Y>gAd>+<)VW`?POxx&}h{@39(=KR5|vx0BLcQY*S8wd{l;9tK+3iP*P|4tiAn z4+gh)L&ouvR;&wZ7=mGQZZcLY$M(-FM^y|Xe@mG|2%o^jh33Du1C1ku&XaHj4F+Zr zLcKJ0uSXl*eGuzi(n5f!Fls2ET+vZIwa9GFRL0=`C4XiAHekxh?~dit1oCi7ucoSf z?EF8_`C*8XRHfdMl0&Yc^~&_ewV8JQoz4OHK_A8qYeN!IvRgwp|aNXRkyvjn%qD zZ)bQ2K7U#KbqEdur~)Xe;e2Rt%G7^Baj>?w44tJ^!xXtlNO}%QEdfrf$4ej)1H*kE*O@?XJO}7Q*?a3yc_8Na00F@WZYYT-{9vemgIzV@F-hnJh}vs6Ms6JKOO6)e=;t^x z>#FVv&k3<3jJIrF+!k)s$%%>oo{hOE_c$HHLTC!uPI%@83(i!*p>%K}v35 zJb#ey26FVSS0kH4NlQVZM$^c(2fi;^p)ojPQ!c?-x1Xm|HS`8gOLyvuFjSmypbxNfvx2a* zXiND19=>*%c-hX;6DWYM+4WaYU3mYZI9yOc2o^@2pg$G5XAN*r46-hO?U0K4&3_nr zmY>A2-lRVdEdGr8`p{SLP3vvEa(T4_X-^4T%%)SXHW`;OXcg9rK@=;2vq}seKqs^a z;k`IABkrxKpleew8S|r#_>)bcEAgoXwQEi$fY+FLEqz&R5fDH`=E^1hdsgKN;lKNW zjI!IXd~7X_-~JrSTS=;@CX21U)qmL3gt-VU87oRLL3_uXsWDdcSl$Lsc&_xkizJx;LcPwC-e0V_|N*?nIa*Pz~G1o7WIHPy&yLajLQwIe*`%k5`;9 z3e|7k6^-RxG|ge7U>Hs$=pm(o9#ZDhL&~iz+jvNsI?C?J^Xdg`r$#+`EE^tpckI*1 zvXOy*1sjs_%x9E0@i~Uwml&uw-$z#X*jMqmA57F?KBPSc+NQvL3`||j#`~j!6al|}*;8ACeSgitqi*p+JH`n9ML~O3=ZDjS2@U1S8F0el=}J?0jMpUP z5eE7UQz=7$#?g}G-BL+CCJt!S|4D3|bVnVYl<{^xV0A^?aL4@_z#N~q>XVN&W`}qJ zZeT?=yxO<>v~_k-Y3Kc_=cvDQ{;RXGo`-&Hr9#^-F`FAMVOAkhc7GJCGndZu9B;hT zlFj>A(P1I=m`h5jq0u9Kfe`g!*08 z6BX)CQ+?fq^;-&mD1;7MFrAybD1s?M(HiV}iElN=+aO?CE{&5~dUFuT|9kRKmsqY4 z+K1hS62wN%tpwZgBY%PyF`cb-sKY&&6QW8e;h7UCzOyc>Cj$t&3HE+(wxqp*9F(46 zuX>BpWr1x%5x+MZCbwhO!(fSB2<01x1GZq=mTqbhZS?1gDPj{wOKmSo^YOp-X%i^K zDcBNEg5iXPEzn>&e0+yj-`5%3*QYri*CDCplW~9-8!gF7CVwegx`8W*ygN-Kiu;iE z`&1Qpu9$9q?kb77NE@}R(MV$Gog0Plbe`Um!JCy)d``>us!MW}-Ztg16ZW$*TT*k{ zL{{qL{o?#OJs9?)ks{srS1qu&)vImCIPfc;BT&2|pTnha%~6RJZHkv(M^W*g@?r?A z*n|zJ-9*l6^$*!vZ5_=?BRv*X*}r?i>AhINmmQ( zgvI$6Blt`sg%1hOMaiBcsWz8F!P_~G(?bEDEwM~@@qc1Mjijc>)fanwIMw}wmy^?V?C9^ z$fOFmK&qfp~{S8{0jfFNYDMkKII$u64+DH(vt_h$KhaH!ELyq@zCv_Aq#Mm TI&8Bq6na1i|BA=y0Pp|+1-%&x diff --git a/files/board/arpl/p3/addons/atl1c/geminilake-4.4.180.tgz b/files/board/arpl/p3/addons/atl1c/geminilake-4.4.180.tgz index 3011f37fd69f4705c4b90e9ebda2b731fc4ca454..9381ccfe28c181ec5cca8841965efe0fa06c85f4 100644 GIT binary patch literal 21459 zcmV)2K+L}%iwFP!000001ME2qbQIThGrJ3{7C9qhgt3FoMinhi6VPDsE5Ym-EzI_; zKsE^6x{753YdCccff1oKgcY-E@jTuljHx(@eV{&}<}_|YgYA_igLWlZ5)@M*e@ZYX z$cl_L7BLDqix5KFd+*Hbt^l{qImK;HG6(j(ci(;Y-FN@*Y06aYmVX8C&73|RTXE*} zg3Q+XII(cr^qDheiqr0&#ubPKV&M$VJ^j|R#&H!Jl*iY*-CW@DC)TX}Pw@V$`TwWi zl&Nc;1_?a%)RYaYZ`B^C;2DL5U#kCUV&QfA2gr2JU2v-y%KU!E^}i0JfC48Yo316{a0&ORy?)J9ay{GEdkE@wHw@i zalU)unkPXzirb5@r&lTN$5%eSPFb}+4`}2+<6E?(cyZAdcivQE`G%>FD^H0lru^mF zJeVz!9+rxiY;gtFxc;|g@w@mU5Gy9l3VE{YS*B8 zj1RDfT!A?Y$4Ej^quRm;ie{gvI38dN$CWi@(hqKxxKddg1se$A(*V$_`^UiV;+%+d zP3^o^aaTYcTB&3QDu;UPwJ5KOKZeG^_2zrUn0mz~3A^}`^ItJ&{1XX zr0Bo(C9@Cq-c!V4@y?vye?)4^-LScmJ85w;`PglqeSMs)-O08g?`2Js7GE%dy*l*! zlELHd-m_W|XW^{I5%uxOWU^Y0R82;uM54|tj;rJD~)8nf*)UUOBQM$ImVh z7tpd6>dD&IVYZ^{QRy$Fva%)?ulzWL|%w`hmKM-2@IDPogcVFQ}MAuf8-~|^0Nk4kwZgH zV$)*RWVRl$OxUNxT5G9!kj(vjtWVo$t9=>R^?)oZzAp(;d1ThFm36YVSeDs9Z68dj zAM--k5A2i*Z*E%%QY((gHd%YF-$ut$`<)y9=72*8V`vS>gm4>%xqhcV@^WS`;yz8u>i03l)$eB~{p^H% z-xc}36MQ_b+b_xcdw=HB*4bnxvKF7VS%hWy6ZvZ=Vj`Jg*e3s^A4zyqwjHo-r)`AL zlK^6IIDb*rP(Wfut|5J?fwc~>JljR35yGGlRrsL*gCC339k?#WL`hTlL6{h{CI*IJ zHJr&hholu{4I<$|{VGgdY7!=<^bOWH8QftBxJgQDk@|Mh&^x9wKeuK~J(7K~4^8tD zq9=itA|k@jlBmZ z{~XO&ld&{gupnD`NhX8}0OkY#-A6tN_IS9+}MQWMB%Bk)LV0de=PU0q_hlp z1j(@vq@~i^cvoN2dylp!XDo74^o<^6Y6E6lA|$EjdF7i@@Bz-JjZ#i)LBxV?271NG z^a+|WkJEG$|6FExD7%W;8H1Z&TjzwtC4^V<7ya@-_1+g4e-gKfi6@EJt33*qI2 zPz@lp^DIqc-yc~a)nyx=>SyPA#=+v$l3BbJRn*QwT7vyLJK4lJ^zBcFGSJ_p2#H0I z#NGjPwM~-LcRg$yM?uQ2aSbj@Fm*zj$SXhu{c{9m6?+jofD2M&Pp1Me(8SQ^G5AO! z>?eeLjLb`Npg2&br~@OE`_uuOGFpt80)^b4OkPRSDe@^!rzU{rNbY76#$k|i>gXt0 zL&jJuP)GmUA%s=unt0gJe?+jLwU)wi9l`P~7Y-H_LC?I=(KFlA4XjQk}5JRMd z56r3QvLkK{0xPn_4znxAI~}sUsvWznM&aG+ahkE}=J^lm1<00Z4=Xo3>@kR}n#U3B zzDl+|iaqE^$X4`0JVLXo*)o8F#D{A)OCl}au9BK1&)P7!gR^;&};1)vLDOcKrPz`o^ zY*^HLkc<$n{-)qCs>9CT)eJ zHNT|iwM$^RMQlY$L)!Y(W~XIOnq58W&S2Cggx63knhY{|GBYYoqkSDY#F$_>E{;+N zc0};3&JN<#gR6m@elHLximc9tOqo9ml68KL94YQDVxJKoT5&f`z?kMLKfZ7lGHY=+ z&FW8Q2DulEAP4)YZ4TNS`?$xykcSVBF(ro`{Sks$QG}GD2MD&$@_N%G^d9gpFfWWO z9*6#SFiI&P)zQC4YYmy(jgI~UV~-pwQb9*A$H?MYjR4PT{UTvFEDY@EF@Sw(eo@co zQ01)ch}o%zt%asYd$kQmV5A{j;@1wusG2>9k)SyID@6g;iWCVFPAWOZT&vn=0k!(r^>Z=KoKu@~QW4rKCj8pBIb;8dpfLK# z7_{8hRwI^`w#%&el({nuwBl3x6IOi;=j{vbXa_IjWsP3g%!5ftEFWS^mWc zVY;lunuYL(7%JH>e3dOI3?bA@TdF7^64*yH_N+sh{K*jvca}&1u*3|a01{)v>Sl1D zl#}3jWwm}gkmQtiucz@g?1ocDC}qy;=U<}yVQvKEWu{i!QYiz@pe((C3%vrD+$_=~ zQ@~rAFKq;uKA{l48*|lS;>0*e9fmoIbq(bXi%2*IC8iK+aNwo~Wd}0W3XIWBwKdph zKEJdEe++i9{SGYt_s2$=tBoCft>J!XviRGv+Xr0+-D37ni05N3w?R|P_V00GQ4$^x zm5$UJJ_SmiXP8+D*|+)#8FsQ_l$bybjgs$!LVg{eW;0BMZfK$dGvXWVK=myT*=3_4 zvJ0@~0T=Oe(ERfabZgBn?70WJ6OHamX4lNGhvm^m;t-9>7ua15kYa5=GA|~8PWk8* zolc87CE-YvjSvo7U(-9KDXCR5&$M;yop`gz@&wOWVV>PP7_C?JyP+xxm~F zIYMYOuqZtH56I)(a!5ry=I*&qK<`t6sW}y+;jsH)0jk-jk^CW+rF)V_(^Bm#b~;(O z6GoAeL3IFfToX^pG*r*i;ynff5oDmQ+>NoT+zG6X$|4<7Xz9I8R%6*hwB!qXOnV?O z`((xEa0A_!m;W|#C=yoaOLjnP2GI|Qo>$=YHr8Xi9FBr;z> z(+wY3&hrMO&uQ2MAVq%Rq;_`;9@S&mOgFxt-DW5F`%c>PJW3YYUqR~xlpi}edclP5 zYfj@4)8M10FagZM9vCMLgr2ljpEtXGQZUj6eJ6ORalihw=O+maKgrpUpF&LSHnR4zEIm*1i+!Z-Oc?NIl(l|$dW=r2yRM~$hXM6phcd?s8t(#p8wLxF;FaGO z*^O6yFgAP{QLi`!H43PSxI+jJ;F_b#SipS)krHv6XM2GG2b!|^79!VnVrn!ZSI+2E z5No$04hv&;^hLtlXwnw|um_EEbY>>0*eE3^#@dweW`MjQwWt)mc`>F>xRN?K8lavt zh=xIo%B+B$khRUz@M)z0BJw6DFl#)mz`qv0E#6~i@k{c4y>OW1t^D;Pl&V3C9c2ZY z;u>U%b5I|N4<|>3sN%v073Yxt8?zd^z8+fYV_#sp?@Lyp17tkzImTg-g{m_J;l`z( z;;@6!d)TX^@tmuvh*1$R?t82;*xe93;gK#kqha7*0JL2OJ)G`KYPhd50x~UTS(?I3 zzSY`~AW&$em@+reI9g&|FV*x5VXsE_N164>_g7)YOf>Tqb}`n3C+-;m#KoBP9=beT z5l)5+S0QF*z&1FZD8q(zUDJ65@YR^<@YxXc?9 zsyZpK?!~|@hd&ZR%{KJkhBh)|QXfhpGS+U6wu5!V2S&>Au56ial=*+RGP}$gh0r0a zH`L%M0D074Gd2?F4`YJ83OSgIZXq!O3D3Tdo3~cQ47UJ|Fc~ax$=ab)YznAYFCqbEFTWD%q6qzCMi;s&j+MARcH%B z=%*;5XgmJ#350F;X*u4o)wwyREv>R9A^aR7B&x>4yhjL6K-YtQIIL{h8A|4WYlcD255)IJ4_mR!)fGMG>&cVLCvAW0&Ld|Ko>iJ zBAOw@B(;!2leUzaL(7ob6nRA>(1B3ofq;m13Eeg!Dp^`$5^$&@h1rdpJ9<9*1SK~| z)}k0CdwQ=Jn*QYg)-iRM@P*J-8%Flqc_Xr;xe4J#cIzE9*nLRWG=$b+fzEbfSc3Rw zz}QZ_`zO?Iz-qS;?xu)f&Ws(O8VJ!{_wopHj!VI`U1#hFD#}fPAQhY4g-!Sx zUEc{1n-H$zQuB5DY&e~tCKjmUc((Ifx%ih@Zm%sRCwDGkH>4pPLSnWCdkQj{AojCq z$oSl0YS@#TA^F$R1G==borMPfZWtvRfzfQ#Mm+egNA2R_kaT`;JUeJSbZcrpg;j#% zi!lVAW}={uOi!q>actX5fL2G3mesbo~h?40g=ko zPA*NY$ENn%?ut!<@G>;w1N`eCz3vNds^7-fzRr2^&aqHx91A8?JcbAA3`6cC6oECW z$Lt9eZJami4}%wc-qvVGYnRSZ@&91&Yr~tWvV~95Ktm~>fFR&-CG$=hLFA)~Xce@P zq)oJ85Ud}A4E7^|j-~CiCxD|2sV4!>Jx008D0B5*nbAAe>pU~PqeBZgkQ8hyGEys| z<7cUejrF5CV_HGTyVlzKBqyO^eBS52?|Xlk=YezfI(x6Z_u6Z%z4qE`@AjC+nC>;f z*D#S#=~}*GKhTCLVD&#+~syz9Ew>ZGVQ@D_~Wi$uife77r-CBWN>#0(Uwi=;Q!$1JyFwt}i%<^KURYNSzCD27 z)`e~A%G|;If?$DZF$lGJ8$XC&$7@Ibi%rdr^o@tgVTvwvshd#9OG0^FPSt_?VK?WQ zU9b+akg4zs;#WU6RhkL*Q)V+vM>okBP~y9iCWpGA)2-&^?PebBGkrgP7c^wc-(ZO$ ze`exYd|_=B15FO(y?_%~toS^G^aH58*u1-uec6`RgfEe>*?-7FIscQ8eq@thWL_CC zDY^~zf;C6P2W$o!vPY6b_6X9&rq<`eI0R$jmIj>2Y_UydW``grdL6;zVsIkb zCxgYgI1rKxNdx^mf>g1;gO&>~5x5#BbM@9-qHpR9JvFYkiJGFD&Lj&$KYaPrBQZED z&Uzv~cqOhu@1SC5VekP`5*(>j(`4-m%V&D}) zZ`s@SVW|?)F@)AVSR$^91DxmB)H|h1Y+00p2A7|@*Z@oylWqic)NA$1Ck>Ndk|V|@ zlh4#-maYJVV#_k9WT$Yp`TQFp$&;hSmX{ow7ZoONum`ibV-2fwb}X{crw+1Hw26Na zTIrjxFE;rAuvL%vpqqB!TZolh>Rw!da6Djibd%Wu0y&=v<|Fgi^MRY$b0-=cI?pY# z2_H+~GxCfML(l0fTxCD3%ur*6OnzKSi7n4()81AP3?1K5F)%>7=WS<5MN+$z_r;bK zM|TtM&{NsuUl$#(!oY$?1FcpHx@kkJTlp-s48*b98MmNW7}mRtGCopos*^szK2 z)@EQ6uuJvPFf3MHm5;$Ne9eX-)@JgJkbBM2e0LD3Qp$(ht#0Nc(dovK*iA6!ba(Kj zl#y_$8wCAOP^GR82aN?hiNkn!noWUEa{DA#!FyuxR`g=4zE+ny(y7v1IpBX9yM5Z( zNPas$(6A_MDLo3tb7%?>t=EJdbg3^~)RmR+vj#5e$-+5{Z~u9fC8o5MK#6VzGC!Wa zKLW^^`P*k>wllf2`{wZlz&kJ>E!V|Ar0&mN3{%Y(tu0Qlc)6K8;8#(g&B@S&`!W3y5*N6 z_^Fg2q&*q5qTA8m`^!;@?IETBcc%J#mhr80+~NuCBM1BCq@n|P*iPhu_k-a=@t5ry zd6RqRDeP5H{De51A1CZEodF2N2q8GPflmeQtJa)+II_&gX#{qHSrCGRYw zb8`P5v2X6A_`6djp{KC`P-iA^6?tO;2fFMMF4)!Ft7tin>pN=iUOAm2Z94p1KWQ;S z=&cDoLB_rO$t1QrK8IY0j!w?LrAJ9Dpr0-+m`w-cEs1FzjyaB+e79@9Ut9ZTTuB)) zx74KXA1qM(an4}kIFc=t4L2JqpXUNwLO-pTz z;yA!eZpVRO*tbh;@pX$W4lt_`E+z-~nYUdxgAL}5P7 zJBIr-IT@{U*xHEN*$;WJW`V`P$vy9nIV=eCZ0e&}-L&}r!*RJcE7CiDRF_TM`KXBk z1H?#g&ZsW#J5hFHE40KPcjyx2pX5FblT?)GF3tsfO9hOw&DdX8M}(0&n&u7`?VX^; z+4drzCmhZulNgvs?ry##kUFMN<>V|}Fb6)QWdqj6O&X4i89W{EbZ916zyDx;v1xXO;u1vD#2=i})G!z<3vJTO(Cdz0$>5*GQ0+VG{bqMIDRAyXG% z9-^-@Z8#euZdh!GB&W$9x|EJXfYGsqs>Y~pxB65b+LLZrLItj)mA3DYGsNA}0WdHZ zke)QF+)qSW$Ia#87mT+LRF0CiL=x;AkW$Xit355lO>av~ki6LdsKBGf9 zc|$1Ih?@e+!&|Y5in^T|tRfL2$4p*D-2rcn#|B{D35_ohTlQdAsFZS)6>Mb%!>r)J zM8Qs7!TcLS^Nbk2PbGSA491`4yZ|)p8%;LV0G8+-f)a*yu6~Rr8{+3OF(u9K#ISX;=f2Gx%R57GQd==UaQAfKr*;sqSeWo!CD( zU};4cr`}N>@Be^;vTLjwuX|IdUkT5KHx2dK-0&HQFB&4VcRL6`s@cmR-0a1KO8NzG=~N@i&UJ%;K7Qkn zbaDSPNtye+Z`I$~ymH;ir0hlSrKK?;Pt|2qgWQ>DMxs)k!K+&zbf>K7Vz{DnI@L`m ze;_?0NX#8OoS{v9WUx7!;g!YLJDT7XgG%6atIfZcb_!vk%uXH@Q}EReY?R{%zr~$C z@qv}N-!^yvcf`ct3r30*a;cAC0Swpkvp!%BL4+J`BTImS^sTZhy^Xy>kzf*oGY~Z< zhd@fC^K7wAsQy63{0A0jJZ>WV3m})g<`A2|#NcuuQY$k(9>5CoyP0Dfc*d!psFVFb z64=y7nnowe-~w0a5`zH@b+D_?#3tag;A1gRLk=c)csJ7yo=%7I3C0sEuQ*w76?3~C zbt=AA2m0PhxA%|rIto67Rd^Fg{BeO6n6HDLS_(92rbw452Q_biJ!>D%6JpCUw(M1e zr1#<049ni@*a~x*ne@(YNu`iqtVCVWN-N)oNPR7Vm2bB+wglJYncWb}&T>QWgIUXR z(7)w%T=RQWKG+8__aEu>AT&K$wGUG;Q2)$KS@OIP9iMx^71J$^r+ zK74>?Wds+rtrtPyo&!6pla~ISqx;rfkx0Qg7JGka?LA*Q~h^n`pUkzMutd zw3D<5(J7~s3q9W8=nW*eAW}T4E!3(rC8G;*vBP~X>Wb~rpRhQ|3lfsWWh(kKdXiNo zHX*^C(JCk_Z#Xo9*j%)?MaP~d=NlOZV(<-tLS7!w2M@YJkE8|KslCb$!q43a@P4P3WEThulGrSP9@-b z92hx?^~z}h6U$T23#IzYz5#RRZ=hhWLIsOvky#90f(xJrDF#4op+&0U3vuUIuY9*r zu!nwXkQRe&v=@214JQ0{ac5DkQyFy4d?63_?QQDwd8ij`GoR1H8pC}iac4MW+AOw& z3kJj%+eo{3{l{{T#VZdPV72pZ{P71JT_>F(`4dv-9f?IS7?m^PzOH{`wxq@Of|b;! zjkyG`N*d#+C1HAhYBcWkpj>+k+Sc7W*yYWVQT`2Gpb`5Td_Wpzf^Q+Ab*f;3p+orv zi#9g>Psd~&cfT|RCUGL}a6_n-)J#y~EJr>MbH9KU?>JZbD0+)Ki;S_YeXKO1c52gP~Jyq^X=cEDm&UKV%eUf@;SVKMkS zilW2_6B}9aYnt84=XA&x^iH#Lri><|UHPkh#;eZAkO}?UFj~!IYtHMUh!0oR^VATS z5H!ZefYJf5c+Cl&rR}odOmYn_877pQ!a+yO850p2LmI+z=LHnf;8Ke$E~S`4 z9n1j97F!%)FLvVMk?7XwC{aAkHu-adLu`rLLd6D{u))}gZe?x9-leqDo;O@WA2g;m z^w-8jL$?^uZs=kY4^xH7w8KEHz0iKmh9*2&mzRSo6WUDS8TLGE^hhyKJA!=3%^)1D zYBOmNC4vD`S&eiMu42$Bw`T!mO`tcx@Cf();x8x%}Q>eEn|)&lgto2nhZgS9;A1@c&F&+9j9o+B9OONV64h@ z9GIf+nT!XSPIH9DZz@sxcq?IOP7cSr4&@fDl_)h>oY?b#X;`lP14VCtxeHm;uB>>9 zaV=s`e{>RAEEAYQ1=fQqgLpU!$*?U9 z^o_1f=7=tXchDf+CCV8n4CFgSb8IWLXa}?iI^t{UoBJ|yQwMSrv}#9*vY{DT_!Mwf zlS|2FoKM7m=?mGhUI;7^F)vf_xW74e0_$x0p{d@3mfQ zgSxhhEp;Ppv34->{wz@c16+e@vmsNEkQH(ooim2Kk#@7#5;L?HydvIr2a~bqiPxNl zqbMsghJcBY;eg9<+T0l~=oAA#G3l^lsE%aJ$;ZR2_w)K#ld|kNmhXV*cIuszznHCep{p4gyFO{`2xOwl@leZry0Y$ipXrI_%1fR zo1_VNT17wQvgvi^vnXAz$Y~SEVmSH%qwB+V81$W)TGXDb&v&g8_6xH0jFYd@*iYF#JK&hhr3KF8~WNxgSZGI#X1gXntV_Nx&Wq-i5pbO!y= zKlk5H}HFZUHL3{MnFYkC z4FJS@3WG#z;|bFuanLJe<)CXU=Es8$v_Gu)K4BYYzE7e*j;HUBAZa{|)1DDPull}+ zjp*%RjoE!7u?uku7JGZY6w-DgyOY?wTm9E+*U|Xqsav*ST-miirflCr)qnqZ7Az!! zU>cPhjQL?TCl)dIMu{!gn?`ktzYJp}{1%EK%hnf`_Orrto*Q5KTZg&-#&@y0)jSp* zvjDe}$>JNw&If1vrm%RlNZ(Yf!#tKDqx}7^Xn||l?4|#&y7S9Bi;PI4NY5mt4H8+A z9?PgMapx@~=zmkB*F36=uCBr6iaSRF&=Bd-fY?}EASdwUhYMrvu-ZBZ1ETr|*i}BfqtS8XD9cW3 zmeLkoPq`0hP<)9>bT*Xp?>>rpK;^96Zjm3eDdBxniP*{)cBSpLkCm@yd?EK5XU6b|iY?YrXbSZHi^Z zu=lZ$rz8LE{;8^e{CE^1!EctX*w_9vsFwXK5Kca|UYcd|-nf`|25`sY;A%zXw`AEwLAaJ136(PoWauWAd@7 zVAVFh1Zag(hx`8n41uoztKvA`N4G{ej_Zmk?st^Z9>sUOZzXxvP3M-v>&6f}cL)&6kBBLTei|6Qo2-4z{z6Wue#qmi3fn9O* zDDLA*X&+8FH{n$js-s7BA6HBJaO#;JXL~nsJlvGhf3c<5j(5wnf%)8Pz_>!kG9ec!`56oMn4xe8SSE@%}x>0O(yOA6+@F5-@Wp&!reV%XsH}VK>pjY;-v=ZVhmNZ zP^jYDgRglTKM)McTmDy!P1aTnh8G=gd4n&BjyGvtroR*-7^Yw<-$nQZR$}{ijnaM1 z?*@bFmu-V@Emyj*@8VQH^~a@v>HZ29(cQMAlLz<+xZ3h#v=Mc-{JNA*vE^W)xKr~e z>#ppvQ~5S1AHfVtBrOZx=K&wvcm0#Vf}lR6D|?P$Ri`wk=Xkf$v+E-20mVrrrJl~) zpH<$LR(=A|_dq5Dx;d>RRBOYSq*XN-kc9ibz~CiHZ{J_R&IHj6UT#RvNMaD}6ua7t zvw>al9n#`_ac%S|YDBe|-HTy2P#`_5Q7HNA6eM3$a1B~l{zGOLPQduSrxItW@$5tF zfLY3ic~K1D_CWHgo5bAsCd)_D4KLt3Y?C)yptf%yqXQ(a3O)YGU}P552q|DpuTpwc zZ0Szy3jlQQHCiQ@Q3J@mgZjMt?*9?j!2P3nZ7Q)_FJ0^u@B2**$tHp3vZ=S$*pypW zQy@657jCUi+fm*-Qpc&V*eR}&d(OZVY}-;?!vt_o%yGyl2LFhW{_aCY?5+EdvSolz zw1Vz(B%nM6)d0y=$0499C?(}S%$dv-J#j{x)m=ENC&n>)Il99%YT1%|Ca~yau)K}1 z+Vv`qqsgt5YXlZErsdNBa;I6JH%YSS*Qkk7$BkfH&%O@=#~CA`!TNBkKC>9a!$Dw& zpt1g48{$*2!)` z*p=nycSogsBthT(xpwda6GfLo9{m+XyG)!grr@()+=!c@ldtzQKx1!wV2&k5l91ywmjcGp zYp8b;H;2F+I$dmWe-?YuEM2G^LFX7Wj+bK;S2v!uJ(ciyT1?AN zx0U3_s5QH|xsePwc68yDfONR4N$Z)&W~+HCMminaNhO}?>6R5Bwc zhvlBHvLuwcGO~L_oVtcBtF-=Soe)f!)MkcEA_RIQTvtwUKTl<6+-zicQl4 z{RZE_uszG%-Schorv~4jputCQI-@;$3L*&kj_7*BK7N)OzY0r#i=O7o_JD2_=%P^d zM`my1E*`3E-;Wa;tX5O{1Cg$j%Ix2BzZ|8zVUlQxXOYmR|zg|T)chPIyH_%e)u3G5Z4ttFQoESFCh zT*?`CktfjP=q?NsLBeRUv@UfdzdaD%l8+LS-2yg9915UNrN+OY<{#s~ z1C_@_yYipRZ8K5%S3iHbFPC5LI+4Y9wiio6|4!g>6Q69b9X9#!Tqe9LC~7C}-#9&D z6Ss8~hwj~&8(pBg?=PFZ5NY=#%>swc=u{?qiSE_iAC}GO9+hz%x0dSH0h)cButmVM zBJG{E?jpJq`TKYiGqmJ@JTyXD;|Ls=M*8nrC-|;N$T%jYFK}*67y-;C_!uMbC+U@xsI1`gu91HI{I8i{pY5H%r=n?bkgK7a&`z=V(N3}a5xoEa z0Yk;&_s$w{g97-B(f8^UUn8zBI*Lq(Q7ksog)vACDH~v)1FWOS?5El`-k& zUHI^6w?l}5ztSwrHmlT?=DlH|5Ty1UTh_{4vE}+}#g?TDY>`ilpweK0AL%!a>H@<| zDK^<>d?a@moE33rC6mW;Xqb#i=@I^GB^St4ng_6ImsO&$#WDIA35% z(FPRz`f+OPE5*Y0Kc$=RoN6(i-C-A}G<`%_{?=AZa(Dec&--PolTnbEt3 z#~Y<_3~Xdznh9a>M#%>a%A-AWmG?e&`B$(T&l>4n@raym)lENdItEi(8*WU;U{1quTRMi^Gz^|J46fDs;e;Xv<4{Y81m9EJd%#V zpN8SdbPRzs49)2nwxnVBb2^6m(=Z%N$FMaG!yD-swxwY>o{j-e*XS{Pk&Xe6<>)b- zNyqSbN*g$z!U8-iap|fN%pyDymB zG`R{i>2c?#<4zN@z+*bxOIK$Ux4^&Xv0BoxrpaC)pl|W`^cJTHVql#fcV0T~G^q^y zRFB)Ajyp|611t2n1L?TaIEYjn?KOJ|PBnRf}ac@n>ohH_S8G78? z(s8HBcwmYiH{F@W93lye#nO#VO>3&81!8g}COHmditxV&Gx20WkY{26l|p zTOgxdD}9e2!|^JV){M2_eF6p#v(0{P=&abU^RVJhD8tu^osj;(qZKfiSk^}yro`84 z7|BxVe@54&kSRzv`BmbkOd-BuWPpaW<6KDlpV85)WAl(^q@dMYni_JRxa3z`1C^cy z5x)C<_xtYm?S6M!Bf@0MQoQ+{zu#$1z6*HcqEK!PC-SiOa;x@!+juQcM3*O`%M(e- zmUCYnjWsCM+KHk4pd-qJpnr`?9{jZuV2o)AV zi1XiY-^>5O_dBisp!`4h-tZ6b%jfw1-S4~Ka6h+gk+nf8lRVZnWfiNdYCP78vYLw} zYq`f-Raxz^HdNJAc&wFG4Q1uko=WnoG;dYwIN_gvi&`*Ve4E)|FM< z<&nN`t*>veuB)xDyxdyVV4a44A8cB~)z)bZ*2S(x){?54yAWPlw_sYO)m>f(SsJe8 zEi7fdkZP@E)z!5XNEr7rm$j+}x>E0}ldO*V`r3NHRhg41|FC&EoyzO+&jWM%ltXK+ zzPe%QR8i}zuC!v2RUXN@#*})l%5`P+9;*jyv`)tn z^)*-*TIa5xwtfa?y!o~{OK-E*uJzP=t83StoujVo?&{jIN^7mx3(c@LtWMNlR%7+7 z_0&k#8sD07UMrY^>t{9GRc@`UudS<-fH5k4L>Q!1T9DVQd=&SRn^cJ;HFw%eTAnX@ew3UW4wCLs;UN{DSXsktu-Erf7Pgy zKYQ-%{Mq@l7TcD%1Yn#7pe{&CjzFAltzXaiFi`*)tgfPJB~-K$)W)i64VB>bRZCUY zdM{(B247tr2(I;RkklMuj_}UJJ$_@ z3q6BoaeO%%ofoDMzZ$wz)8JWHyre{^^fXk|SJfe_FTBZDR*ecX@kho1=^TbQ@h8R? zdnC|=cUkTARe)P4^GT~~>(4Ifs;QWLsdYh3RmChIpQpO;XFSJj`0rY+*bP-4>+K+u zLPLFp)>3=XqO0a#ZkwNfXLJ0z4F^;y=?CM%f5Zqx!<}0-x@1qO>b+Zr_NJT*{~3J zR;sH7_Vg^g9S3+#*{Z6Fh4W_5o1K5v+?m#8?j`sK<5&7>NCW@>)-wOIekpRm1nj@{ z_kRK9cfap`|MPyuixypNoo@G(SAjt{Z+5}#%Vy=zomuHAzsh&n3 za(GJh?73Qd14F?xdsU5ZcDb*rx^h-kr7*kRQ(ZP&@~oEx`hPa)%c{FP)pzqRRW(%- z|4eDm`qXrNEl%D7e`1ySv#(;`R<11fty(FeS;aFqtf^ax7D7X6{(NCJXzHpOZ!OQq zQQ|8$7LC?gSTN0&R#!EwWPdDPm|flgXmBnCE1LJLcyZ}0Fu^PC`ZhzCMLWU6!AE6) zkIn$MWPp#$0KecY7+S|hU3)I)&+!~y$kR9TXC8;|;OV%o9KpG{y^}u|armA52Glt` z|56U$%Hi6dSufY}^S=@BeGaeJ@^g44hi}x{KZ2z<@OmHOaQ{e_UcmD|$>CuRpUC0Q zb9fJjAK>sXhc{;@+kwCLI2^B4z+Vn0;b$CP$X6r(#`7Bu96yIIoN}42=gR|7isw~W@-KqmUDOy2YkulUJX8-rJFch;_$6A zSh|?QWi3C4|Cqxc1f35tf5PWO`K7l{~ zox`;>@0Rc!him%iI{rMw;dk=%mHgSm;g9mPrm6o<<2hQW6H5gj?%YSFu zlrhr8>CYKWbFfY0@U7gxp-J*04sYi0A`UO-@H^cs{St?-!`uudIX0FySDOs8^Y7*V)$@6t=kq+z_w#+87tiy|BlVFE$-*2$sAKZZ6f^}f zL*#{#D!kM3u+F(>4>}>dNcoBGuz_<@uKVy5)nnBXb&lNnKEU|FA-KMD!3xW9s(e(7tQ1sy1GWU z)dWiNhSm!V$B7p$eT6`&{>$9h?uBQ{E2>%g)GX zEbjChkECj9A9=}sn0rQivV|0HzV^YcxrQ_T4l%L1-V5W>#%bcGF^mRynbpC#K8?7V39_Ox-#NA6X3UehB5=GafpLpXAo#`AHk>Z^V;RcH zQpXxit$$2tVO+zCFI#F{ge?gFsRYoFsURZLCCvplf`yi{Q?fdGm>Yfpy4h2e>7fBE z=y^o6cMLYA9vY=6JTyt#a)E=Ryj3;2X+|pW2#*CUk#3)Lqg#~_kiCol_C?C|0GD2zBIO19m0D)(M zfwKclmiBefB6{xBylVQyo}ZU^2j&xWzfn^@8Ib#bVzOBMCEuvWRJ6Dm6PGo{wlo<= zQGy{Rsgk-qPI|#_{|%dY0^P_GIHp>Ftxs>>rg!ve3L@=rDJ)K^2O^i@$J&7oARv6% zhf*;EOef#@Z6`p5O)978PtjkZOFDF%5i!N68%Oo|a<~QZ-RO+D<({GC2to}G^Rtg0 z>ccJrD1d;icb|qd>n}(yIQMBi?s<*HdIUR+eyEV~95(zzfA6K%cTws3tm}oUX~)Hz zmubI!?^z8U1xq$R{`aZLS;vj;_~NHSi?@mU;VX_?EpvZ?rXyGTBsi}e5AE?=Bzt)u zL-ubUEQnk%sQ8tI_!qpasuSrXSqS!mdF(nRZ}7OyqyH}Y);n9w9#b>zW4BXa=*xQh zA2zKoX}-?PaFl_Sr5Wcz{igdiB{@gvQOS-5SGAWpT^aA%{O2?=&6ina58N(rLOfoS z!hZ~f7K1UiQ8_LH&)8|I+0*!SXnMr0v%&?L^I47GiNUnwz-HCI@o$P{qK{U+)O_J# zcJ$l*U9!n}1F^dbQtGi$&sX}TdpO!&@|4r0Oqwp} zLdzT)G{5lDJYV5LcR91V)IpgxaPlPE=f0Po-^Pihp^T()*MIk3Uug9w4odpZXf!eK zh46sGM>rqiuT{pG=Y=J^dL;!`>N-9=d0lzY^7~l*RQ%sb-DktdVek1-*9WnC&XpYd zV|Q?+{7r8B?hs_LB4MfYS5@^yEskdR2xD04_FrC6gyMqp@j``hPXO&?+28liFJD=A z?skYk-X-ZuHfvmlpKS?~0s=jUnNgCh zCEX7;#iH3+j;*6lpWIX8UOGCN=27qs zAFFmb6%mX*pb?~I)h~h1z+h703po~bZihTt~MKb0`i;L4<3iHGF z?;33LNys6SmJaB)f>*bLCRi_3y5~5DoUeWF4KXMT*Y0|fc^=;4()-XPEmLn!hI<&u z9sy6!X+>+areIx$mJ@D0t|Jww>H9U_H)uFA8sY8;Xs|izcp+4$+HS8s5V#oC*fi6d zo>j5_Fz3R@!!^HCvUKiRIHZWaDyzGh>Q_3_!W?%KcLSJDj)gec>1zAm%L$Bq`I8#a z^EWy6?LFnLb5S)a27Om8^1nrh5TyHWo@fa!D9U;sY$R!R=Og5-es+oh$+<~$BFw?N zXjusyyP&6Oh$@+#Z8mSf1jIH zTpcX!HRJ07NKU05Q&p7KB|0#f&`_Eq2IB44`)u(8+Nb9FE0 zrvu~G@407&dNoev1+?jWISYst1?Jm4JU*m*bTs&@LimG`C-GBelZTrYPY&wfv?|UO z$;5^gR&_tyb?M-J&FZvTb5M&8sfLR0_fxldp8V-k@r9a?rxdOpIcs`Ddn^LEx2kg* zmB$V0BlYCDSB+Zu3}}{V+Sg-ES9DM}&;9P7Z^SEHaJLM2^AKqoSJqf?TIt^d8-V5T}q&vb2I8pCq+E zjk;ZhQmxwcqgQONS~?yReX2_(el4{M3vu--c^LJu?kCLq&CFkBhdht~ja{XzSSw4tTl{o!trEgm`Bs4WdPARBprT6Px=49T!kDa-l zx{X*jue_eG2T@1d_Vs7?G@NXKr1WEp_7N^D6ue(me_Q@=Zsbu5YA?8>tg)`AA1%{Z z*T#wNKOEzo3wfOF7UXK~{pq}_i-pdTtKDpM&%1&D_JlOmy$LKiCM}uQLMWI2a$;KM zvB|fOr#w{0Vl(gfduKNp#k5=-(W!aHDEU)+E}fm(5w!YW=e;+_ip!m&UguNuUEAw_ zLR;>G>=2(1<%LAwL%XtaneCd@oDX{u`!|uoM(@*CH2%eP()(Jy=1r2-io#)fWvqlO z9%}RU{4kLfcd8@_Ar(JxgD@dh0l-RNW!dmVvNTqjO~50>1rR1foGi^##Ums-l-N5$ z484nOKv9*?+@hr(N=3-=E>VWXa3J>Z2!?`_ME@R%;a1CKH!A|No5MAcSwdAjSwuj3 zA7fjvsoG2XYifGMGUNdX2H+IpGl6hQt|(cGCyfscV7oklW&a-jm<8k7bx*|>%u(%> z%cX5qW8~S@c;gVaEOXv5O0=h_+#peC32n6rvbHn&*Ju`5If9t5~#SUWv1| zlF_ov=EN;AhLixv6k$`s)>c)Z21{_mZLlQkXYN=cm3LRHLp0{u+|1>MdY31s{hZd}Xk{4aJ*&;SlfETJ6mT?=rG^zE!y*;Nv*WcIt)#7Pty~LE*>jj2d-o0+ zoFrTE2IAQdF5A1QWi~o?WFCe4{rtafLHiBNUS>ez#KrVqB(8DE39=|BAc>0ovcwFG zw{tRqnv&=hBK)57sZ`EA2-4FqM5HMx>bRta9^;SUR5FaZ`~`iK~u2jXRF)_{hc{#TF{WQ z9#9#@Li;MQfN3yMoGRPmH4v@DY|{h?qbUf{ob6SqRJir%PSFiKNE)qBi8&CX#U#A8 zqmDR)0nNVC8zlHwM*4*_E}`zvL^)a~h5i(JZs_+fPnW!8ISwZ#t{kN=0q$i*u$5h6kmg)V%doQf0S5tP?9OKzzM4l{F}u5Eb3z#X$& zNiebaZ+e6ZY4j1MTT-(a(Hg0Q#MVQ%t`Tsu@n%duekxH2WLFXGxM8pjs{eE1@(24w zr9_xGPlp0BM(32=g?QWhC&8rS`&VLM&B+@4X=ybEVpc3?OB3VEPQ;j~F`~P7`tJqc zMN-aE=)((m%zr$U*RyUwZiBi~_Aqo`h43>wtrI3PyIlP5IPxi6elG}veXBI_)i)6& z(y_u0Y)1*lgGYSPKNZxdmMuS+@9^+9W}8(({5Wx~`vUR_vKY^VQUFi?+?>a==15c$ zH&7p{K-J`pPI`kB8p@2*g9bH*!+dF{DKQBU><|*0qoSa;JR`xoNNEZO;KbQFl;Y;8 zWjSJe%-MubUMSdh^U2)RHf6}HoB6Pr+PaTC|?jeR<2o}Tk{l0mD&eUej4I-2q86y5xMj*xitY? zJV!7Aj+aE1PR!s*6`^AGm?+aT)Dioz79|#>UPCgW!MCpf@9+KWbkyd3^?^`~xWJrQ zc|f^CnZ1q&iOoj5oGTt~SFBuh4!wM!N(6Oh!m4}dDn88GqWlhI*6@=kF*d=1>5-JX zeG`lBQlf4UD{ew^2;D9(*I;S$xP7cVwz$18pj?FkS3t6=6(F4TV}uzyLbE6)BUvT>xgd3wV0)YvkLDF_{ zItHzS1jWc!l6&Zkn=Ck(7oAm>N9$Uy2FI&2g%W}TNHwjoC#oId?86jCND>Ia%OrC)3o0VS_g=&ozqLH0HoeIPi?+$h+Wox0BseY`oJ-Kbg!5wsoniMaq10 zJE4o6(7Li>_6}rdxeE|oaxrcppkZwNe#nR~5Az>N8N`oU7*5onuG`Y97H2+n#DAj` zy@B7!=Q(ecx|fH=b5>D1ogp)a*Es$FT+$pyBxktD{+)>$jXH33E$Y&(7#Ro})X3{! z<0vKh#tm~G&ao3FE>R%pC}ZC7RNOaYKqR&z)0MbfV5Gt17=7tRdLlIZ*v~To7)AD8 z3f#v!iJGugg|`qTchV6e0w`s@BN$?<K!2NR5E_=)B$o6O7e2KCF+x1og_$ z8?1!SqF&=c^7yPKDbd%v&d$4lD?%LCU^pRTQ{o7A?o z=YuX{yXSA;A`*QP?nbH|Az$J_GRbGKL-Ww|;g9TuPE|eIM;!sM$$8Cmi|g?+Yex@k zrCYf3_HxP--ga&6Mue={as;TVu8+UjI+?>S80ROh@oetB@0zD-V~**2+mpGk^gEJb ze$1by$5p%>T;v>lA5$LFJmWpzGPG&+nqpP!Y$C@~q5R85=RRv6TG|@bZ?=3_qW^?% zYc+d&!oh!ko#uqd!~`^04=Ti*y+nNRM4{1iba?SV^Ln@Ezo7K4NZeph?mcdF*zMk1 zm0es^ufi{4n8fy*_1wSBXC3*?*Eg0-@K)ZN3PTOs(zO08wL|CRSV&^d*tU=gN>$o~Ll7O*S; literal 21460 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%0AryN>q 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 diff --git a/files/board/arpl/p3/addons/atl1c/purley-4.4.180.tgz b/files/board/arpl/p3/addons/atl1c/purley-4.4.180.tgz index b11af2c37862792efb1ed4e72a426ed3b5d7ee76..bad87b44e04416f47f0af6376eabb7f1d8ecdbf0 100644 GIT binary patch literal 21429 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 DAA+%0 literal 21427 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�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 LFpd{viHZFm*LKo@ diff --git a/files/board/arpl/p3/addons/atl1c/v1000-4.4.180.tgz b/files/board/arpl/p3/addons/atl1c/v1000-4.4.180.tgz index 4afd7857f35f2e6455e4e3d6fa0262d22216fa1c..c8d1a1dc2f39f32bb066653f701e19640845a35a 100644 GIT binary patch delta 20177 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 E11q>amjD0& delta 20178 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 L@jnB(fx-U)W2)v> diff --git a/files/board/arpl/p3/addons/e1000/apollolake-4.4.180.tgz b/files/board/arpl/p3/addons/e1000/apollolake-4.4.180.tgz index 39f360eacff8e69467d46fd42c69e19c966b5eef..a13c44d0e006796af821cabd5420e597d04fd088 100644 GIT binary patch delta 20930 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 delta 20927 zcmZsAcQjmI*!3@Jl&I076D2_;5z$RV528fxBBDj_^(xVWB#3T^7G0v(Q3eswdmn_+ zXD}FJ%IE#wf8Vw4x%ZrP&N_FWwVt#0UeEKrff(FC{J8)i%UW!JOSe6B%x3HvSd=P| zOrdh8sb0CCm1axes*ZfmxB& zR)mk}e?Y8JuV0laAy((RW0>uE`_w={l3xVv26N)MkjI&OSjQms|<`a|vidxx!x-W3xdr5(8{>-^KOqr|HkI9edMC1CBs%ElKO z?UZ4If|2Xu`0-nW0ND`{JSzc`kXj4$3whj52G(r|5+ZrP3_shuO}?zqE0 zJboAp62Z=jqP#jD>CjTz%}+O!*qC_$$cl`ByW(ft;H|V-o0jIe%iC#uzK>j6{wx8) zHoKm`e;!$ie;Q_GohrP=9AXO7y}y9_}>c_->L+pW|RKnEi9L)Z05^6SNJom zRm5L}N?ZIehq%<0LX0dZKlvB<(vbCQ^1#b8xrlse`?NGMw|1x<`s})O z?5prTOc3ZNWRIJZ)Rx{Kt}$N{f98IH-6!7WM`XaPNtYX*X-nMa*xa9pe_3AlQL*u3 zJD=0KZF)QO#fo3q^K@lq$-#7dQ=%3C@|4W=`||B+mfUqIR5L^<0IhCh{fkrg^Vl6t z7j)Ri>yE1aqX8jTvC?*v2zAeHCx})<>&FyYI{{DHt>wAL19g_$#A#AB5guCg(xF9R z0z(RC>E4r*32TQ8E^i)58m$*6&!eFOnp16O8&s+Rw|+yfLV6;bb<)$%>pf)z+H|gT} zuT}qEV}T&S;gh=~kdbDeC7AZd+2@&UN_bW3yQ7}LpRy3t#mGSjOyytMDs!F_9iAfY z`Ha-3$E4iY-)x8?{ui!ljcYqEcu7kATNBwAGMeD_^@;jKp3X5d4shQ@U{B7pakz!s zks!yLLTUK=Vl%PvF3A&$50?T}Y+|mnBzq|HbNlaJnSx}4@6uU+tTQx<2UG}^s-N(Y z)0v7)>3R=7KznO8$avah875yWHJx)HDNv0mMf$>DYyG$WVYs-R&HTQ&M?cpb8q`|+ zQ22V!CEDXQC*u#BB=sN5<3MRRXB6jKDIV`-)u3fd2foKff;z4+%u#bhX}9CMs~3jP z$Fu(g-TGcw5~}hL zRTp(NKjTsh@7CHCQz*^0*$}@;r{zz>rE4?x{Sf<Pm)^%j=S7Dfb=efwZe$ur}f zYrMyw%|X3A^KU!})G>FvOmtG*Vkau*?8;!YMQY#hM;N~W*T{&)uJz3EY4x4Svn@_P z!^ZI;k9%a~1yLfuo@?3s6EAMeaP9d<3rhVU4h{7eHvKXZa{1Xx-In!;_VtDHY$oe~ zQOX$|5l%B8cI)0?bMs~*kRM!EKnGRtiM!&-I!|iknG9ufRGX_5HY)0m+nR{;cO0z4 zJbkGSvO;X$d2r{rySt#5U%6a2>wBM!1IUJJzK@$85bAvX@QL2{atX8C9VawZ5&xU~ zy(Uu5qqm-k-fGm?iuyWd@;JYK2Z4d1T~lN8=R}mWEXL+@_4MbCKr;E%S6%b{+2ikT z?=f6-#j9rCKlJfh{C(0Rc1E(%#d0T4#3-myZLF$2wW6uKVnyS~nKo#iKJKZe z!lAyuoI%8I5%3w8z$Oq#VH^obb--`7-TyC6e&6TrjMmB!(bl-%mboW&R2iKigY3R& z_+APhx~kzSBgu^SlxPr2Jwz_Nz(r|%PE39(q!J$Swp~w5#kw@w?d3aKYMz*)F@Exe ztRXLPb_*};6Hb6a{mGJBx=sx>Vvy+EOXIAB)L}!umU`g@E+RB!#jVY=rc{&ta|eaI_A+Xj z+;f@sgWe)mwR4#k$qvEAs8zLgwqwXt|J2h)R+mRZ)Tu!A#}7j@$NHcQqkvbhv46_u zx&TjB_LvC z*(07d>i<{Coo8qyA?-g{?3+I;Mpa4Carr~5W7A}>ki@2<6e}Ak1^!i4TKC;5h_zp+ z)ZnIr>S+REhL--m(tOvQZeEYdYW&_kRJOqYmF~3QliJppzIi?RP)+b4t{-$r0OBZ1_pSb;{w6#n}I{w=|#f$;H5t|In zCShU!oI)zSYU^&3~8JkF=3oph*UKSIUKC?ib_Q2tsiOX3*HwN?b zYqJPTL=TGwjE_#bpZA`5bhz$j%5+C?1ixejl|_8BK0rok+Se{^*~nEbue>N0f9Iup z@GaYEP$a-GBe^8pD3gsy%UAw{aJJo)>E`~YWA&O{DO13=rv0v9_a8ylr#S2+jUc#x=E$2Jt+laOHy_-y=8+`4&$887{N z&YkQ5g?~K8F3`(wW|eo|xCXOlOn@KrM(y|B|DIW=r~2YH%f-O-Hx3mHOFch*z>_5z z@Nryc2N@V|jJC(J%1s1KBysupnd_P;8%?;J5KA5B6S zxruju=*CC^+elqwclFl}n;sbOb*ZV*ApO%U5iAhDjbYK05a2)lS zc%TTlBg5=gQAZq{VY;codQ`h|J4B%wrSSutS8(=tp!AHgDLe~ z14dl>R0|>lCX(D5e^jKl&1e-sJwCvu#b+x`y5<~J>Y858UHsCfJ4~M)oN>uc*LAoT z6vAJ|C-%G7oY$&q_Wke5<_zQfZUs%LjE*)S*SAIDTDSdrf#O~_L+4W1UUnhH=&Q3B zO!tsE|C~AE^mCyV!z)ToR{M!ArT}hQuJz$B#`i4vGX5fL{#;&H1cieX#}RVbrfKf` zG;EjpNfx`NWCMD<_ij}@C|zLxVA@mmLxiNL522zK6UJCytC>fXBpMsvQXzWPW0~R( zgo=u+8n1X&XbIi@^DbMs3X;y-_Mkj4kR6dTAAUBA4)d8oIA3XA9#S$30-DWWR^!GwEr(pKb9&|xGs{ZB|7)o# zuj!=sLYwM>exR_%+i660fODhw#bIQEUW_O!TsL;oy+03dF}}_D;IwLEK3k{hNv4z} z>d@Y>Hu-@DIhPwvdyZ;==IX!cGd*BwIlEDe^@H#k8v8|)73{cg{ZFe~=o2!uu06B) z``pyWHx=q>OU9KI=9@c~8PCK5XLq;i`JO32_mi?p6g-0)10}9h)AB2GLpJw=<7j!&`gd2uQ!o` z_@Mkac>#-ZTh!fK8%4iLRB)rEiqCWf0Sd(nUQE_0o9v>H-Wz5I;*5SGK)0?YURV8* zL&KAF;f3g&cbO^KWr=;S?Q2TaV|t@ylWP73ex8)C`XYJ#xT@D6_oJ|;h~(Qkb2lhy zrn%I(@_xj)qUbS?Mlfl>O7VvQTO>1IEL)x2C))|v24owZ%&-3Pp|?6`Db6{z!d$Lm zbZ1S&2~@@ZppG$p-HNF>Q^2THEa{G^oeffW;kZXP?$@FQN9_c29vMsW9_Ybs{bPpi z6DRESbTfU-l&OmvZqC=I~@wp?f*CdBGp18vP*D`bLpwR`pLI&TIaG^vOOrxyxy*4=O9z- z>lN55qJM8`uM`U=j{fcf>V26;>(=`bP?_=+rm%C821Y2x3gmN!;1R1g(cTN z`(ofbGor<{Vd5c8k3?5W93Huqg?nXAc)b#5I1gua<)iunHt5A?2LE{^xuu&YrZ@J% zUh=z9ca04Vc=O_2L(Y*~dsZ$aDpxf;3)@)}9@hmY*xLa3pIHZ@& z>(==CCh3!IaVl{OkLXLMdcorA20NSJFQ5t@o~*i#)0Rj%+*fY__AHVfkW}PQ|Dg>{ ztcH=y@nqqwhoWr}Gk&=g(I@xscBzj{Gv+gRtyt0w3)QG4Nl@idU zonLqEd*FiAZZP7yKe^YbYoAj`jr_Ld9~wFLdgVLel6s`Nz(WS?LxpIUzt!+M3GHXh zcU8(9%z2&o9}n8JiO_gt^~l!w^Ni~qkMDU60P`H|ZBNQ1@t@4M9{UvQlRZ$Re#wTt z?!3I6evM&52@UJjip0=T&!z46?=ZM(1U30nGxWAOi_X?LKT>)u>TRN+FRHRu*vV#9 z!StOZK`;Jr5J(a>LYhh|G1ZgsIRl=c8;r0m%3KaAC*i-rD2?E&s@6S@ygqD%NPGgOVS`2()Tx!X7O# zg!DNj*qQw{e=Et<81U{6eCe%fQ0d1rI_Sv#=jLsXssY^JyEW##`Fnes<2uoxnP`Qs zLWwHS^2S%pxv6s0nx4n2bceGX24S!n>i5H9LRx!S()Ty7GT-~uB?Et59YR0la~Tx3 zJnas{Asl2vyyPU>ha14;o&O|r5@*u9BPYx6Qzi2L(dNJw$aDWBPNG&^F(*dUt{AK! zTT51tc>#T_&O$u{8M}Pc9h%=iUpDe*KI}Mc_y@CQECG?9ZrSmS2mcOHR%=DwFIL8g zkM+n0v3f5(rw1phF%^|J#PQ~?dI&b;Bw(aQoC{CA9U(*aBz;VEVr1-=aRn?)Yaii9KmV>}hT0J(jC>@ENw_Bk4Z_hip(d*&S7spoF4FM&C z`Pz?WQ4`$eA>Zqbeps(p5nq%x;GFkVMoatG;pN^xHVWynlW>tJ-^}9D-v&Cjd z*wM9Iws3X!0`o!9I)9bYd*<@}dNt}^yoskiPM-Wtc-U!9RL;XXt5Y?NHEEbr!|5JS zWeB7(t<3pppRW!L9#krrMZ$wxADnk&e!b_x@ww@mYq)yit-&A2o}cYfN@A|mck!)l z!Rqg2zH+tdJP*0{O1~utROI}L#f*uVVeFY*pYs=At|4u8WQq!E9Fnz-=gTj21zzFQ zi}N$vI~U3r{HQvA2lwv!)qQ@HQC(RBs8FRJIE;l~tr0Gas{|@ur1+~ibhtwd`_hH9 zI+@8``yT{|e8l1gY@U%84szd{4^a@D>oF`+y46VSKWtsD+8*{ZF)p?99SgI&npDk5 z`=eM7Dyib-59n!pF_L(D#}5KsuPwI_3Y*6wN>=jR%`^S15*^D)4x^4U(aR5jTOGB8 z7`*PmcLGGT3vg~H!1oARXB(i=RKhcx=O#V;%TprUSVS*se}cCc#1EQ)n2Dc&V*ssn z+&6sJ7i*CIvV8CzuUQg;&enZ26WRNuFL#gah(@h<8(=6%8^9&qN=my}V9pUA+py>oxv2&3tWvDXXHMWIT$> zzGLJ3iicT;|osnj3P_t&_sL`bU%1dZOGS3w*6pgrBVMk!LSC(-Qc6Cl1I0N9pCqqA=8w7>eUB2ItSYhvqm!WFDGK{v zL+{kjd@hD%F-X3qT}Ia*#`a0ozadw?N9D^cz6bldoh`e~yY05ypalur5h3&k|F6|H z!^|KM!3KE+h7ur09heU%1jzN`CIPr?7$6Xi0mmc)VRf9DK97uEl|{<))tj1Z9c>rGPS{+7VnIz|@P z(ub{TFH`)YP}k1eQNn9x)@<`j^s80ok57*CLiY~#z>9ZgGlt(VWF+;>j60a6IZ*>P z^RquL$N14zeaY|Dy~K@-*sH1^C>IPXK1luC23^2(b`$scsD3<}uy?@XxpDHzye{w`jZ z?r)W*xcSM3wNrIG_hkv+TkV>zy%W0(bhxp)BP#9Cbdd-i&&%hLtNhAxPi9p=sGdB% zjz1(Sh;%(06>i-lF6dp?9HhbI(La`9?+mjD!||*s{vfMcRkcBo;bLH73v}#^iLr!h?rHr*{KW20&!uWFTtGY$T3^J0KKL-MlTP7MZ<8? zr&YwAtn8~wo(7$4iJyaNPK{kBi|zxiV&;BSMgDE zx4Rhw$*0cb78b{mKIeY4(1ZVweP`$AddNKmLrks#V|vS0&*-@=HXm`;>)hoG9^Wk* z8K#7;r=zv(;5?SO%y47mV(W7SR58qpksBMviG6FSei8r>_eqkLGXVtBHA+C6uvk^z zd`426gbXl2Mrznh7qg&dP9#sB0kj7dM*%(EY(eR0dhP{h^_9c|*>5doo%b-`Yx+C6 zFh1416PpFXgk4j25(tO<7GGF?WZ=rJg7ce5WkA)yIALX+)>Pd@6gXF;Zm-Xy$@#Lb zrC@e6V1HuOliTY-K29wDVQ&7mqPKJ)dus)Y!}9J$Z=$To&@JkW=b{i^M~cy;X^D?{LPtrml{NKpr^Qv=MlI7!zn!UU$vAu7;Z0;*;QN z=kPC6w)sT;w;z`l;tb@7f!IU#d>@}fOZrKH!Lb8O@Kf|1m`Km) zwtjho$+tWk?oQht+D8OQqdkHTLbDU_d(z0NLXT)XEv$uI&SU?;UZ*{>C3>73SO=g1 z`P~I6)Cd3BoHTcLk4UeOV**gyhAOreNG8O->ooq|%}N9%7inr|d7Um9nA)1E;3Lld zQ@%fx5hIJ-xuoYp=?sF;F~O3k%t)!Q!n)Bw4>Rsh1pNu~9`5J(&>wYRa)7H7$sZPW zXMeI|a9kI4u7!kCZH=pib%_J$xv(OFq0M?Crin4|Z2jC1@YN{pu?Th|hWCt-AoJXw zvC_(^U#NCO#sUverQri?tj-P3L$z}}ubnnFCcuu^!>V5M^da`^eM~_rA{P@*-scvz z9s^5N0u4@qXv26>W!#~R7!EB$J@5_IGsbXXNniM7sd2v&Ybf99AO zrS4B1*THci9ubx{HXZ@88@N>dxNH}5&3Wi}#F|nk8!|L*BeHTx?M5KJ*>>VJIbvRc zWBnI3r~CUB&sHisNZ^oXs5qI&uRbfX>+4>;G*Z21q~~WIebAi^X7i2OxUhz`x8b5F z$-pXr$-U042`6E_a7_jo@h zbO7vqXMlL0TXSC+<;AG%SGM);Th>l7*AEUIzjI26kb)vp$)xr=aXg&IuS8Z9$an#} z^%5V&z%-`gqUgpj33278s;`N3qjK>@w}6dii;aRi*JAY^I|C*WE#@0*WY_S%ZcTXk zjTA_o?}mL`9;rmE_k_zG<_0$&+5SUJc(z_s&t0rXg*7Nj-08GQ^=wV(m0jTwSsADY zOFrW`W`e~Sw_c*PC~$m3rf2Kd^zJl$k_X?#qq*<6W0Ed=bz9K$FrYpVar6uTRyXCM z2_H^`(LW086q!Ps2jEdsW}TE+nj|m-+JpFo zZh;+$t^x5ot2O7t8?Z%YZYst3P4Z~4{Rv|);wL&3*&-VLC@^)+E}ZE`9T7yJwN2e9 zu;WP+3}{5FAzQ@o{OIRlKws$ck>q$2`ZkhLOpzuuVSx4)WPDR73gUWVj$8}t$9_OQ zVJ0X9{@n!rgZ#H5nki2d&epo8ZhZ@KEAO%x!Q}-Jp1koA*RjhTN9^v19FM@*9&(D% z`ksKh=*N+Wm4vX((*EX@b4^KvZ&0=X5*MK7dc7u(G6=)n{ptyPEd&|D9Efx&LVxy* zKf&8>;vb_8kW7KF$3)?^bcgc1$QDw3P0#ha_N&K{slR8!=iVx&4Doy+QUWQ%d`PYN zkptNeMIV~5O6801)_nxWyg5Iw*!A#WM$z8JvPIU#;C?fNx$Q`@lj1-{Hj^cFqw;$p zO6!j5Qrx1RlE=U$t~bguEt`cBlQ02?wT+V?i+e5HC+8LP5D!V@Ak65t?)IBf9RynWC=ap`9Hp)#Bwq69h?09zfh(Yk5R<92!u80Uk;cq^_ z>)J48$-m1&fn|tX=Rsx=0nGTj#qwYpylmh% zKB}BO)?r2o-R{(e&DO66XLmn$tjT+@3kV@CNb!X|U?#K(5y2G3No1nT!Gh>&Nbz9Y z1YGAXFK#>x)zdQYDC41aTsJ8#AJSC8TQpFP>vz`4;BZvF1WEYMo=i%te`MX$la~We z;fyuJ;^F2txr`Rw^oLmLu*o}^CHXq;`XmcTQqSee&Cj~CPM@nyuux*@BF7_f<};b) zJ-UmksU9F@7Uu%m=M?_65&1h+sB;SdCPIQ!o?z)JtFs{k^d}$>km98HuAXbe{!V{@ z>Q$(b%{sLrO(z}In&3Ju(;)|G82R9MS)LFHZf`V&w{e0Y!`SwNuO_*D5_uzr}mn71#q#gtV zy0{)3b1AD0!jlD(VOY+rSIBx(%^dNV*{i>*EN~$k%&qD^4pMJ)0zF+b=*vBd}tGwAIH4w0$J*iZ= zSU8!SEcR+BYS!i~%&o4YViT)N8Yk8;E=N=x?J`ybd*8CDt1gI%GdS`nvNM=k{~}iA|L#q1X};FnQ03yl)D@+Di@qA-Mc~_2jd`zdv0UhYhXdL$p)8e%-G~`Rn#WG^s*j%O$z4 zo8@Hxskpgh)86Mw7v}qXdtz{HN+Xj2*D$vrD?a*Z$Ll%Z*-VC@uc`ge$ET*NChTs` zWv{=yInMuzV(?J<^~o#f*RM6L&p9rBk3LAtRaU~U?v1?atp4<=gz9cgdG?#T0ZuE57MZ^KkY}cmS)Wd>~vqn%M`llYxe1abSdUcx3|k6QbEEY=XJWDPw~eT zYnKbI;=>1D&wz*f%J;T{irx73G6w(TV6q^SoewPiBn1-UAp&pp(0>@H-byxAXgGJ) ziZY4RIsbSx!j%hp?&AFyBw1el-n#w2zzbh`u!-3lhPqFq9`Tt2Gi#$iTL}X{BgyeW ztUsUTy-I%#&PhL+(yAm)c>SRErJj1ke7XSNPgYY^XOnpj96x>?dZ(A>6zPW$*7+ThuP%ZG9fO9um?{-enWn0E)C6{x5Mj8 z^f7-%;Lj+!W4o3IV|kjZIP6J3ueEsl?#8YaKb?OEI8Rj_l$D;G3hoTFR8NVhVDo)v zQ`&zfYP?`6&#=hMJM_pDQGCDgK2w?u7P z(wfz&-r2jRWY@IY5@q4h?{hqv7|*F%^eBu-H957JfJRiMiHK1?@oVu^C_Dr60OoO+ zsqlQf>S5XLXw@Cf6XLedxYMaDU`0h6H#O=iHNCxZK;HS#g6+~ETLERkXZ6h&K`*KB zgFa;JhxeXQNYkiR=W9upjmIMfO&mXJ-_Wa0pF9@O6JiudN(^`F9Z=aCxfDPa zMNIl00|pPpBhp{pc`5jb&amcToE{?JviEimx5bagsFR&^Ny(E}b+rQ0|AjT$JBdEk zm0EewlQkb(xkcP{$gbedq1vl;YWVk{(y;G`>nwl?+G6DRwh^Kp^l?&|Iz(q~Qf&2k zh=8dDWpak$Qr559)0k?qJ(U*;+Co1ccMH#?{6vtZJta|ArdA>PEIfMzI__s`tMDC zakh85&>KO+mVL>9J>D$HK^~E_>JA_shQ=z)tGTl)iRzUwr-E|KGCG6$zFJNS{eRcWoDS`hxu@N83&zzzmy$Oqts#1|* zSWpi35{b=^Q_evNLN}zdaq&K=7Tk8KsguC{GFrd{`q!+ELTH9w-$kd|CH&!c-v>=E zx4Gw8tZyY&EODN|@3@q*mSMAXu<0twZra>UbQLM{g7#*CHwmwRFFHCXY(;c;1&dOiR7UO- zzX`y!`a>gaW532-zi&a+&5@3Z@-_Ma2e`EM*}nIpJ3|KLg#lF!ZKg)wAAYByb=4CJ z4M{ZpB(*xJ&Rr!CW2)mPt2y(jp=gPtC4S)5eW&kS6!)fmT9(kAB;vawv@@?hSXH~& z8EmJ3D0J(1)c>Tp{FL33oN_rA+#HyZqMvjG)?=Tp*f@R~@Qv!roY=3j(Kf6=zT6zP z3`({pIY}#Seytxb+Vf{pCa??%8N`N!_Sp#XdCUh8G)JU$ghF<0!ewB13Ww6 zvgBWHY*;Q6tuw$cTvXL`NoF=ex*t5G{{3Iz-X34)r{i+{?>~)eq74I$L^^A&kLtRr z1SIMxhp=aoogdx)j-N%%z~h5s8j3LKrhwJV-?4+v^fv>OVo6f_1{GtJs4@@hqRUEG zCjlR&pfF2#q7B9`=#u@vI^!JgRG0MADdnNQByUaSS5h>l)@O|lU&!)b_~EB=Xv+8s zHYM2`+4r3d;X-#ath1~=1??+cv7*Q*+K2U-wZq^?lCNHSXy8#DYO+zepsNZ_Dfz#piY7ff4N& zCpUR;ht?}YBa47r`;j45hv^^9W%T${f+eOBuXOa==`Sef_;`I@vA6xC`U)f}^yfSc zr3js1Gu`)F)NJ~EFv}Xiy2Z~+Xqw-i4YoBn8XdrSQ6$qSCoQxKUF6)P_kL6UTB=K4 zxx2R((H{3MIVHv>{x2gbHTI>$n!9XZpgnWN5!cX3^-5~Quofh1aHOw0$mn*MOjquP zRPv5rf-N#vJ5#vv-o8=9QXufKG{@xZaE`j_A&!*9gy!F}>e@!@so6GU{r9eyCUpN+ zwB66TYW1YMN%;n)Auq7A#QEt7W#WBKK1K6Pyo`nrxPyQ@X<9qb>$_dw8TaS z!-Wc-x;Hid6)(35W~kfSyYQj+x;PtjBf_h1rn+x6H^icgpyVh@bSd;Ko{)x4fNCW` z)H?Igj!+XuLe9U>h6dCcY+{q zJ@Sy4aC6M*0a6(PDOb`(&O#8=n&aF1Z#NI&l#v9@+bvcw&~1ORcOP-0QD8GRcaTVe zPrH~9p6?`%1mD=R&WEQw$#WwPmp%#IG+_Y0?EDz`rH2ukD%AY~24?_kgg!X2XzgYM za?xE;;Wc#by@foG5^b8$gEd1v-}ex-u_oE>xNtc#tgSn_6L5Ey z$$=lI%a3a+vC++&J|o{0XXO5sCI<;u$BIJ<8rbknT}tdt!pR1DM0--4fROk*3Rzhk z1%!?^n?d0w0kVb+@C#tIR!P>T=#R{)v%((uA6|GQ-#y#x*fW3$Ma~Ew*t(?zF@;Rz^9-4?bDnii*zaw~u6k3Gj(H)t-u z-*jwN_+eG?fNI`ymwpJ@&08YgM=q4g%RLSv$h9wiK`GtR&jxKi9fIre0sy68AM+8ORz^$+iASq3kY;;ybqu*RG02_Pi^`#EeCpVw;B z!yc5U9V&2AeHd}pS!@dgv|dK#o;qI)glD1T6)lx5agJ#Ack1WS@42@EGyw9&s|m{a zL&o#$Lc*UZ7Przm2oq{~=OgaPwS(hM>v_LV--U%8psNI$pE9vsPkgIH_*{CE0oPQ5 z%uRVjbz4oqRr@htvH%tqwN;FqMqNq6XT?kNmA@>Q?bsv7J}_^a`}MSUzyIHGT%5(q zVOmHjr zu}fIb&U!1~e}mW;eZ&zc@#|Wc5DlQ` z)-AY~$LKBh>uhqe&XnadisL{rfw4UTo}>j=mk>7yj|y*zUXeeqiqPd>3wYZTgmb*@ zWv%`&i}m&R(3b*6&GDl%?ajOba&1bq{fdpQf4K$X!7W_|u#~_dZL?2Go*E{o#6~r5 z+Glqr;w%`LaoX(UI+r+MK1P(0Vr4dk=z*+2NiXa55inQE{FmKSngXufwiS0C#cXsc zl$%%4Q>~|N!(SOz9M7$W_1u(*=a%3{+BAiTOyI#9!S0s@eBtybnWWcLJ9cKb{guH%UH3Q7N)8dED+9kq5~aW3)^oXY}_Kq?ZE-6 zPT%)Epq&dax?zQz9)A88L4C z2>47`-^tx>ZV>XyQ0xJX3*gE2#u?Dl(6(?~wDkP+T0?)h`wJldiQEL>)5WeFEMOIZ z$`;;DO7Q6x7aBY22PgPke+$s=Y3qiBX)ka~0ECaI!*SgblatXGVS8TH77#hFi-wQV z<%GSVSX>YrK2LmskS;x+3FQcA9f5zujmHsazbHQI{)HNtfbi_jn`7SZ&QoEMZ+4J` z@A}@xc!=T@CJ6U;fw<8-2RaI?tDE9|W05|@au5NzG)+WZ6_0h?=YoEPsj17C*YfHU zL!x2ysO_lkKU3l{-PRN0&8UMykk$m)V{deDe>4jJO3UUp?mQ|yyVQmVmmh^!)LJLQ z@kik`wZM@VK23!-_Io;AfyxtgH^^A$HYPxsF1`?m-zjengn0~gw%Rc_I99aVQ4|(Wyocc;kPQZdZupGqObMtcTMdg*k&NUTl*1*&3EKGilD8&k&Qeg0su_n|U_6=KhJca8;mp3?7vaCRKb!@A(LxN)He0%JYOH*h}Ep zqk7a%XNiZ#I6go;;95onR!pK;x^e`!oN54s%6%1h>N{NO;aaV%-tC#;ksndh=q@kQAiw^=Y(D<|Ks!Rqrwp|M*ejDqviM520 zZ<5n<8zP$1ED+5S$`hFYCFafk>c%7b!xg@TEBi2M$X}l$7R~Xi(|cZAnfNqm_y{fZ zhW_SZbBHO}obLVbC-4yE1%eCO=5?_9I6`m?afLFaL*9Y52r0&)MK?RGy%fB{Y26n3 zBE(@AO0aT9AmYH!z9$HOnyY%l?f7D7n*tCk4T4DT+z>F(S(qSw$s&+MJcfJe;w5dP zEw`?LnP^Qye@F#ryJOM!ryx3=QA4!lZRa82ojGn5tn{WNREAre9xVZ#_r8)>fMt5g zfcRmSYmfNH&JWBtb)X2Iv9oR?=sG{1;Y2Ed)`?R3a$b%Oj_*Qb--2I;zJ;c4UL>Mp zpyToqfUpq0lNfO+&a2P@8cFa`TvHDvJt@BlDj-Q3gt)!|iZ}=}?zxiL(~CqX=S>Ga z^BSvT^?D7yw~4(e;%w%Pjf_#2J3g5@dp+e7oFXeXQ577_y}yTdBoB56(Kevwm4T8% z$XC=VUoV_&%BKUxyNC1BKoi9F770plpmo~rzL&MhumD$Ztqzv$HE?49U-GUb#dy{! z2<5q#DRh28t#Ea}+gmOKl2LhMfIv9+3ICYiP|H8d7JTs;(G4vQevLQ_X^??(3t6jR zJ)ky4xK1N{tqQ(dDL7?b3r?Olbaaq#7PzCnDen&2BWlSfg$8x{PLjII(E@aE-;l4; zw`yR3gT2ankbZfL69oU=62^MpA=vXbAb4rv5tKHvyT8XWC@L6WqWo|pNUP0Oc-W~N z{K#a;W}~@54`xDzWr_p<0VEz0aK;zuaewUG>o~*Ry8f94`MG>B#ZE>;X8SqZ;)Xg+ z%vP$Y{BG>94bxn1rZmR#XioPonlci?^FKw3T-O!sjY29u&P88A(}=*{HOt`{Jr*Q* zxNEd8Rfffs&lMsh-vaDqRS5SEf97=zjKnv9sN#JXVDt2F6k>UEM~fu!|JXLxR0%j1bHD!S;C|zNxqYhSR=Qi-u2z;;{H^bgZM!UZ zw}jJsov%j+QXB^<5sKcyX^(wdjbX$d0RViS3o6syK!OV*f`FwVESP&<7X)soGGdqt zpBEmtJa$gx!GiuRx7ukAJ0e;?c_hUh>r?wTus;v1uz&nw91&vq%5v`{SnFRw2oauW zZ@%`nbloz`>cLp%NJ0bnk`Dg=y0+4&rmn6nlT6AW5K1v3BH{oZLoOhKG}Y*$f|i6}fl^C>2to)$5+IcJjU*^lhJ+*pB_M$$CL|%_cm4OR zZ{1(#+;#WeYoEQJefHVUkt2MT;M?SLYuPKxK2{rHmn3auk)8A=tp$)?1}8 zN6}Z-T0byi>dN#4V`^G6n>l`9PK~8S0!VJmj5LX)|6cIy*4`z!om>MK__uPO)_d6-K@z6`*1&$gRwIahPURQpgeJCc=uNDs+U`F$h+X|AZ|2X=_#G;xl6)fq&E3P?dj;Lt(bLbu-%t`;9gY**ATD#X83Qk|DF_~`p` z#y147C834(lcGe{Hgq>mNCMoao>zr#h&h zW%y`Qw8SeNo(j)m8`@}M9sQt)C5v1AIive(FV>w#Nn4xFPsSqi`;Qp0W8bNa^Nx7$FSyc~o|rLQM*^=%0ZH1vu~ zbjZt&*%%|C4&Sc%ZyVTm4@W~KT{D1SAo`+fR=cws3d$Ti3aAdNTAG9?ZH4M>NV+y= znpyaB<*MOBPjxs>7j&L4`zN%PeWFQttLXj*R;xr9H>B^NZtYcz?X>mslcgjpEy0*z zD5jCM14nU;Xp);Ta|6AEH4=Wxeuquh$&B4p=V(+(AiBq8=5fB05=#%7Tk~SBU)w6> zNqdz@fP}X+CU{EBrRSeRJJ9ht*&pFM!3v;-Uf}kJXe}LmNNQeyo0)^IQR2ZodbaCc zWqqE5P%4~>@7EPz0&7XL_291N?_Gir8}g12T~VeyJfON>)A;!C-13G^78)xJ7bHZ5 z&hFtSz;eYO7Vi|9<9Hdo%0Q|Yyf%;u@Djtou^}fTPpu`Bf)DeSSEDLVxsmXt#T@7W2KzDv$M*qiISOY+rF^j-7wMFsI`z6KAcI$>r=lD%p!w+jl2i)s-XT zV<^Lbek~J50_z-@gS@p05w7*`Z0z}KFWtI~ZDWxwLoWtm0_KfquZ-4i2VN}+hVD1- zot*D8I)8}2{a(L0(7Ui+-^?>Du554%J@_YVm~2fpnNx>F@Jw}&$|&fDU_6W{`m-G0 zT!wG)E_M~H|I)xa7y8~p+-xZSblzFmwyU_OYt~5Rf32U0_apjW z?+1v`?Rj=juPh^v0A-`&=ySpgxtZGV_oo?d*%ZcBHhH1@uTGPK_r;7T*YvcPqNYnN zEW1|f^l90!dwOtXY>2gR&np*!ufch%rRIA5IYiKI5$mEvxETY#qFC+}JyEMFM#p;v zCYU-YO?Vy^2`H=iirlG{jVCYE;Eo}$rhhqEp9q@KqpZbR;+qR-`rOE|KZj|bvXu6=kB!j3*=R+YpYgF}USHHu~&@TsSN5}3UV?lQ0q+oKW z%RAHo)ijFT%zB~PEJu=*p8|gO{HPH>y1HT+=<13FE9k7#3X4pE!77dn%_7I zz>G3FK`Lj2H+pM+*JwPg_5#W!A2TZ6gh-ddfBE!Hf-VN5`}SSjz!zI@^pDnsudGBu zSi=Tn6h!zGDbaAfC@NzH3Zym+UG9XMFNsG;|PE9eiXP&DD&%J5$ElxoXSx zkH0Cc+0jQN#f2E_4q-@x?Hz2N#Gh;~-+}saZC8l-GL5>hdNhVc0bBxqW4PzTFr3!KI;ywsC2FRwJHyF9x$}n}3p80z|F8|H<7*$%7AtBt00Vns)45W36QE zxY^h&#^&7dtO*6&)XfmsX3*H4`~yB3k0hYG8DaTZ=Q|n1{Ei_|%~h}bj#VExXbRL>i>L{Kf&LEvH-BkqnOO9Czo*n{-N&nq~v6-6E$FVAQml?}zPmrW?l zC^yO0Ty;rC=cLiVluc6ln}A8dC}`MpKoE4N_p~9laF8*6z?5>FA7MsG;2$uf%!2Ph z-`j+`Gg>zk5T~_~BtA__f2X@@C(PmR61bi1_p1!-i1vLUdXlqzb%^;LrUe@YeL(J`r2XWYo$uoW{9^*h6zPSe4 zh3=p2Oj#7(EW_u3qjq*`3lZ8y!5)&M3BG#x*GOU)voqzdvB8Rp)hEJq7y7Z~W4Nh*kg>T|&tTg`uRg1pBb%{Ot{o@O z&I%&VmKMcnQL+$VSb%ibyFd_@@SZN!S2zRyy7WWrwCh#rXdv}JU|1g%yCzA$lstkM ze*YFBPL;AVx!_6?Ox#kWHm|Usd?-`T)aoM`URn0Al@EF|^Zt`$X|NxxE=l@)TD*P` zBjz-9V7zyjfwWa)Ne~2P4j&S<(l9>U&52i~IefqgVvwIHzIa_){Q`TrZIm=N(9IQi z^6x_sThPCZPF>P+E=vcc6nzi`a9sH42@zK*sjyDf>4E5(G%3uF)yEM~|I*|}_)zS% z7cc=yl!;_1MuKMhK;VDae!ZFQMk6mK@S=ZB?N1D7NWNlG*stgQq#j-mI9b?V?|TQR zU%BqLysFN3WU~3{zxC7WYv~|UaPT7ae8Wz+Jxi;F|Jn*2UfIh>YxEU+ipSSIqYC>I zMOEtW4lJ#Hf`9R$hGAH5A~7~v^Ld3;4J1bPSswF4+}y#!eomB_N9J^*$;~`7R-M>U zzS#KvjceV*KTY0~$)ITTkS+xx1?n%?63*?NgkCLiB)1bRJ$LC&1Y8e)+^1I7)Cx`Ug7*VDRBUdrVQkav7WTA+eUbYQBuqrpta1wPu zL>*nCuZE)f@p`_isRjzFw`0BqE|PcV_q)V6AT>|vGx}4XB}le|5`@+YYctJ>8hqIF zyy89p1dOlNiEY1>CksAOFMNe_f{2eCOH9qi1rX_iapcF9s~FM|Uh+oD;<7d*J+#*R zN3kUiYZ$?v{?A)@+7)S-7MhgR@3tMf%&B~i{idZfxB@>;ygfsVyC!`FUlw=AEU#Rg zZ(K%>_lkGAYyIukKJ7?K_nOOh*GBGrxCoG^+9zh_-8{>wQ|*VEc(EKCL#Dg-SCiYc z$hk5}(V=0O{V>&a-gfqk%FAk=1pR#^VBx_<`yMD7nl}5P#cAHzc58MpZoj+sZ`0WA zj^(^Dd;N0@c)&LOWoW|)Fm?J#`a2%R%%D3Kwri+&7$y1yP~IEtXMc5}?lWkD0WI~k z1PB@iax@2pS-+_{o+{vDLR&9SkgJC|YsG=5Jza<r$h9nGo9T2DECyy6Hd~WA;{^tkAqaLwVCw=Ffu<`o&sx1CS$33-lm6eM~}MJSkKl=pL+sLV#Tb1`}W$D@k9{=JT6KIl98A zE1cu*+A}gEu1YJ6G-Yw+q(tE67M;*Z*p-b%}MN?Z@`I ziPqWHiR+h7wARkD`c|!fSTovcUGc!GwbqF)ZXm1Ith7F~cDet-6;|)s^;Xv!---uI z7Tj#DSulU99kghzTD=lvfd;OXfKI^jO%hvf;te*%c*?#Prx3GG?qs}^UDnI1m zsVfj`%HOS>2)i}%0=ar&-DvOX(f`{L`P2GLnYw=MTHlpT0)JG0{J(7)_`ltL+iic2 z|KG+()4%SMSA@nNum5S&OaH9@Z{>5D{`HvrKT2bm{LggG{+5-`D4&+Ae>>>^w({xa z|Htw_is{?n=Ue`4cDm>0iJ~zVg})ZWVc;xxriFf123r8gbZ7s-w6pF&%tIYvHaMQ-^08iT0E~|R{ zBid2`jLX5+V)*(nA3*1}lX&psOy**S91I>5guJ}qCBZ6x2)^&~xrlSPqVKv%05lkU z8!m@S7Ql7HNxPg5e1+HdT|<%p@oEOh27sQ%C}~12Ydh4Q3xPv{)I*s}#_P@ASK;iT z7_vMeDh%nmBB|jGz>c3ZD~ZPKn#5taQy+2~G=elpmqNGURP7lg^|+$8#b9cp+a5)U zjf*LhdXHv*GD^O+1g0j=o`p6dkb2g<;U*2AHU@B~esT$p%YarmCWYsrur*i{Lgr~_ zT7HXX7T}q5L4kg5sYYBOM-VE0%Bn+}bEq3o*@J{!=Ca%NZXKX_cmRFdGTb(2cU;U1 zKwbdxk~w9=?-k?TbiS9jVX`jafKY=*6gV*$cqcD^&=x}b2CLL02I8(Uw4uJ8MA6MoJ*OEgEp4J+}_ggy0Ex z%OvTLTHb*b-z}VP^M;9D^^)kDuzm@A=lP3*=bD!Z!ec*F&)Ztjn;lYhmxFZGc95>0 z$^&PAgXb(a!S?vsyTN%jkC)Z6qaM2s{@Pjv4Y=>U*~yUrQYpWIH^{-AU3mlG^a8Yb z^RD1I0k$;~^Sk<<4W3&&)>xR=)%Q5Sx(WfI4qOoEKgM-jktW!+g$fHZHz1X|o2r%30Wa1*9$cq+&q3$#pp-~|hXsZJT z)g;c23CCn|z&9$bMnL6x{sIT-St8$q7um-{sdkt>#=!M$Ej|ZNM+#6`E&U_lE11xt zH3O~f@X*HP=iwT(W!(k%BAd?xeb0PN5L9U{AJ$=Mbv z;=V}=tzQM#Z#Mh#kk#Sj15wyGXOiHC1M-W@hNYtITFQnH@jnZaW0Ocp8S{5G30PrL z5tqV0LIvp%mUFqT{xh3;i!>Jf&2G;(%^ zELqtS2WQM^6EL+z{UQKiCR@K;8!2=@Mtx0AUc-LW#+hLFq7vP!m&QTLml=E~;IBVuXzqwQ(I_ zh~PPD<0?Ml{tPAzF~b8vq1?}Qlgo+6$fNC0@iMV?~7 zzA*#sIQNf2=q`korIwmJuY98g{?(Yh>iLWmdIn(Rv>^Hz*lq?k>nAp3P6|;J(YZ<~ z^p9+?Sqfn)fy{*(5AEe+5yx-wu?fdXHvSTh;q*@aTygJmt=gLT{`FJ=}3=21fL zE!KT}3(w@vE*JTKP>KJ}teEb#hPz4iYf|WOw7LB4@YhAYc9BZ}l_Xs<`9M*7L0rz( zzA+B+J4AAsYOS(*TJ+f!b(Y|JK%oy~LXy=3q7v_cZ6}Z@bC*Aixbt@6F{eYG8KGSKTA011a< zF48WAF5ruSHlRyIYtE`*<_#vSuFsBelMkfO0P~-^B)~j@HyXq6am&H z3t7>2em|O}LMyGo;~9*n;w4Envs|2y=HV7Ql{V(cpJg&`;=#hX&}n~L#&ZNEesTn0 zD6}rgLn2atRmcwt+|&ak#vm`+vS2AU;6Qz3DR4D{Z7*2LjwPMODTs^({)Fr` zowR}J4rHz07^_jZu@u^eDC93v8!ut_b+)?2q}!fU;=LAj&qwi;bOV+Sl~Q=Ih`<9# zvUft7iInrYLquXvGnw9TRy_w4evcH+1BDZe!UtfJ_6Z_?ty2AS0GoOqi*7)UI;Le5 zd%wZ+tzgYrp67@fNhx&8Fp3<@)+$S2;u{AS>vGy-tSHVEXczF$c~6-5*AEKtTUHx3 zVRTI`9Yo%%Ta{>0fnsl0;-6WVzRc*^Bmw6dXC?Ks4CEUJF&^y4VvKrTb3*{s3o<5X zU8$*hCZNB6 z%SA&Oseip>@TZV3961G}!5`>ew=l*kMMm~B%io0B_r$>J(bf%b&|TnE;pJ|C2cQ?E zGMvHGnu{2n0@-?kT<8yMX#(|{m1tYnNaI1V4@*^leOywItuzo8o&bfg+&nU;vS?!Q zZn2RM>5iFb;nA03Bk}81tmQG(he3^0Jv@p(omqy}iUkZVoX9?5v_Wv+Dt)Z(3&0tp zd=KH`Rat;_So?%CzI>h-U%f}dvp!`re5l}C!L)u{mJHw0!W!gtZNpeVHlK$mm%5)7 zZ2LBU>BRcNm(^o>e1}ktA%2sCJ_awD9ZbDE)RXF63aNui!LwT-wULCAAv?$gSNv16 zLgLlrlH2r{)oq%tL|@s?q~Y9|a5f{<3WXL<;yxV3cc7c36yk5KCWH1^!kN@S${2`? zysMDcHvyEf1amC=Q@3IV6Vh5nj0iiu#xZa@Mnd zsPLvP#zg>+Q{!T!(1Ij^6Q(AI*c9MjDEVNZ2Nx{>S(lXL&bftxwB>m;RQgbiy)LWC zNjW{YP?SO*rp3D5bnGn8E-5+}Yvgv3jD`AcZlT%%1<`#)5$9nkyaPPc9l(sD;a<8f4PKWimp6$N&mc#D0Y+ zrHM*SChdwEGvNlvWCX}W2AQnOG^0q~QPdxyNY0>08o5ZeFp;#2ppEWGk?5lHOHjqG zL{$m18AC){xrnx+h?M-@pw?he7Ze!Ac7+@S{x@7L?QtFkk$^c@H^omDkLv7y{pYV( zv~Ggc2o2&f(RCL^e{;GKTYpx+xuSpLTGbg6!8!_jH$ZhU_nN&y*z%ICXyo2W87Xkc z;w8bKaa-EXecjN`6ZbQr)^)LPe+k_xPjg4j2U3+N>MdN1xE!7`PI}3fg-#Vi@EwL7LNT9IXdU!UaL@$ zmu_H}b4ZRP%F{uPIEbf-3l35gN{pY1Wzt&?>S=OQepblJj4F(dss?Hbumon!9^pES z{BI&-TCk5mrVwK;)0;^aFuGmwvm=mlGvPubbvb&*6K zVjt0~Y(tH1@)=5%Yq94`l(D}{rqKWkk*CG#X3*8VYfyCx-GdR$3rg1=y}&DzFgBEY z6QEvfl3STdog|#AQvlJG>L#ankspQx1OZGYwc}-44gczj?dghh8_hEH7r~q5=JVp0 zl7?0bI&Y@cA@Ru)xP(Z5Co?_NMilW$%q`>~3|PlcJ+LXKNaZT=99E*OyLD4xny4y~ zLPyZyBHZCT;BXNpT?)|T&eDWDlSk(}Z&&CY;9Eb;s2`(q9f3m8lJU(P5^Flm7BRK; zLM9VIr*J}Hb4sC+o!kca^B3ftD$5vwps!8iZFpOObTGtL(8y?ifKfCt19p>2Jr+1f z&FwB)13b>bnCO_#HOXUfcc(c|9Nyitj-I*>3zau?Yjl~a;R61{ z(w-!9`BvR3f&cAF{M-m7{&Ar@Y8D;jz24LPnM^1K+;8_!hC4>I&c77C_5v0>EZS)a zT8}=dN6tf3gr{16>J$tDg!}ItmU5k4U?XaP)lV!cr+x(`*#2wrQi%k=zlR$mN-TB# zAhRkCx^oa~9KF6dqtFcnN;vJCtkL5mT zPxmhS9Ll7c%YJ|I?C04}S0Y^0OfJID)&Y%Boi zVFMI@mDC~nc3f89WBU$t#p-rYON>jN8&;&B&sZx@AnlWY%{KgLPpAxhBC=m`o@9oQ zR~brwYjD1m{O3i5Qal7u1~Q}_k<3CmI0_@Ris!9e5n7cROxX27PQZFC^2K4aYaiTd^$$j}PD9 zx}*DYEG3gwV(ov+98bUBGs-Z=mzXgQu{RcfK#<-&AdtSNzUe(Nun_KmO~q{2h`%G8 zNq4lFw}*0CNB;5@*4jhbKO+@lan4#|%Q zaLU+`vor)}*JYg!jZ*67O!l>~JEz-!@ct$2HdL{0!*?=6-s`%3IPGb8WDkOwpm)3J zi)bINXvn6$Ad`@9AfSxzdqiRXr@%Kq+m+}PofR94HY|0~@OD-kp3&`s!}j5&R z6yB3fd~LZoukRHD9=F&JhLbr0B)UgdMSRX{Km+-I|G6N@?D21R@r4o~ja0L>RGXWpS zf5bCGay(9;t-a5gGn0g1 z@BMy$|L^DX#Wu6g-fQo@_G|66)?Rz<7qc+e^1XDN=rxxI#G#cPRl+pj?7~{p$q+xI zN3Cp&kVuscg1fEZ&(j4qP{2?~>jc@3e~B<_I4ax3=MJkp5i7N0?~Zh_0Uly5sds6r|xiFNiW%{s~Rf*6`Fg~F2BMIT&s9m1lYqSxiZAyCG22hZGkp{HvK;1e5Yxg zn>{Fl0w$v{mr;Rdy{l;j0buV%Uq|xBHRUdLwi2pXj;ANek+2k68m?)Io4N3ow-Ps@ zpk^mmQE>j|O3LdvJE=nq1$u>D47@EVFURd_hSnk4AW#7V)L3KIj{DgN{mI+<93>H%%`4w#tG*K6BNOE4Nixpjl* z9|h2Ow|Wpj)F##QV*BcYC|k2LSzIVC<(R-1O7v|I+1=uXvh_GD+T0d(&S>Z&EqAnb zM`rfEoR%fSByH|me{EKV(k_f^5gO&oppir*pmwt^jcby$xdCli7^ZBU@B*q^ga%Z- z01XhHn!wb^!c$!3Qo*cSOj?&ZraZ`{;s`$}*dhkAyA#Ks#{CV`p-2_=E7N3QTXY6# zY;WJ5#RB-uqH>mX8}?C1s?0~OpqRSNG?K(szmVKfXdz-&g0pEJY3ido;4sl`iC~En?tR8y*ARnc)fU z6a&9Q^N}GPR4Nh?izmAm4|bb9q%X<-(51c|MS>#M-+h%EWD)3IVfGex%9Bn>yA=3G zx4LY-oT_c|e*=uLtN~RmF69jYPxvMthxUVV$ zyV?n2`=x+yqw0AX`KkPrOFO3`zO8ae&flvZfZV`iKwV*%dO(}|GBi>O-STWcv^zg? z*jAYGU02S3yF$}Jvbp6eF>qHe)43uh?XP}eLc=p@e{lx4PII@rlx8UNXzVXAC?55g zTU)dR+m45Kn&$Kz^22{Qq;7jmu?YQP;w-BX~_9AKwi;-5S4{1WE;daVxEfwl^v za`rA2JH$=vk(LSKQ=h?<3w|gDPtmenw${J=phcdfd0uXse$bLnM*}uLY(goLR%FHF zLis95e;YxAJZ_h`;jZ_j1v}f3KnlCWx*Lc%z;Y?vB86s?K3k}hsl|maxP=B<9>PW> zI|afY#tS&w-VC?qTL&ZsHlbxOk8;~V*kjZ)=M%TuAu2yW#p2xkIdj*k?}5R}CEPk~&Sr`d!-d45MYM z+HZarN#wZ{m)hiYsnhF#^wWXGvbC6unVtslCn(oSB47gKP#Y2WX|F5i9haE*ju(%r z1BcNn$C!mF+t(K)*|9?suBbW2cRV1;MDC4Hhvcaji<%)#8eGk(ScbdV#CY z(45$Urb=R9(>b<{!PI1UioxHX!{asme^i~eI8Ru~eL;wZ2>5xzccxuAVG2;ylg&*DGgEYRlRnUX4J+1+YJmSK$vPc%+#&JH7(gG+~Nvarvit9tmtV0$xd&fMTK@hdyb zzl~At^uG@!z<9fb3k3!qVgj3fVPwsKUx1yxFswb2f#R>#YAVOI#WIiQFHjc&lldGW z0m73T9Uy;(=7}wf7^+uDY4Jo>2A*pECr!6~`6c_%#vOJn3C+EQCQnXLRwh? zThFATtkDvwv<*o}bT`9<&d)5+rU7P;I>h=PT~VN2?p6!e7ijqqHL?Jy4U|)J1dlF= zsdysGAt^nAT9gH|@BXaJ%RAlbK3<~IRI1vtuvvez*XySS>k)UC(kKxA$IqdTsVFN$ zR1QNhn%m31`#~*=r!%2B0&0jpk1p>*%CTrYh-BF7>fiHA_S128=oW{hwn`~^PIpd8 zCf7g7m%1mFjOHIwbA*?l@3b4TU`AGfW`{YcT?#{iIz2uuQ*Z_jg+ekaf6fMC zee{2EK-jx#HV{PMf85%%%ATUy2piuNOm}9ZzWm()}w8O#4a-E6bUFL zWbQv_LkF}rXV;SLMxM2przbnC)Y{X?9Map5y&LJB=Rp<=)0ZQ`(VnOCW!2Xz*4NkJ zl2+evje8qJt?s&YV&IV!61%!r9{sIJ(Ig=h*p;95<@ zSAYT~YjCGpxCVFxv}4<_npu`KZA7j`Ih5i*1AFkMREvd(WV7ctsP@ec2YY?PUH;|Q zfmE84$`mfzBNcdE}Vh;}%P#&7rhdRnIDy zHa(N~h3cu}eIwxAhxt~oC-}J-Ts?mjJ4N{!P5rrbYD77h;y(>tavN|-Kugs#$}YRt zrE~+GcnQZ$^t`LStL$eW|Xd>DO6Y$`>~OvKL@1gG2OgWCInr zeF&-NF%INue*=yyzzrcdl0v*5)t3qK+GtC@>TwXcPia6A)4!|%AlIi@`q;a@NFsN? zhKs94^l!L`rdyFO(p_|35VwEUVnhjRg39e;u!@r20FWh+xoXRA^SeivpDn*<*9q$eb2+0^E7@49k&s#{z+O=4{*4SRpNb6k(X2_jaH z!tBsAKigGXfliv1bnW%PcDS}qrp0=|HEs`NH<}~aaaw6?z3-rDv{MY;F&xjXJKVyn zSY&puN=eb9Xuw~%#EtvQVgUEQ;hZlz7zBi6sVl}OU-U#f+_k%V{L zXwBmax7%Rj3U06w(SSmkvI!Le>^%8Byrs~S;tqMc#oD1z`qpD{?g5&^%+9ER(c1ym zrG5yTZ`chh-GkHQ4{S2FXsg-8)!0$~vIdWOfRpqgB7Yr-LxGh<%9n)!31+3UY<a$t_ORE+rh%~pZ?YvWLAQDc zS0TuiUw`t2_yX>YLZhTC3u9K0!o~xO(RV!tt)>H&&Tn7=I}7Gubar=Ni_jOllTLPi z)olzfE70m|$ zyFiT}#rqfv-PxV5?uovM;hG-Y z2*nkDID^JVg==YHz6c*1G2XQm|3+8Bwh=C}|ZMj21j+=)IQ!Q+PVaX0d8DZ?K&A5&|xS+D{)T48n9&9FgW{z!muxa;POP?y>z zgc_2))2m8D^{MYtXIufiXug{3a80_0saTkKS*uIECzJ65HhBncbb?a2%Eotdm-<$8 zGP0oK_Dl`kvI3|XFvh@Ww~N7BX$084iP(~!pX z+T3cBIPH{~dIuI5JeOPhBleB6-U4|?p$;a45SjadX*=wh;p>P6U5s{^oO0s z3gjoLj36bRq%xYs*V~h4%@){CoQl!UtY+4OD|5+$XPZ?6X(_+X*2NW z6b8iLPtT%%Ro@9<3eNU74a?7xXbiG&)PuR${7O;C5VIZz4=Ls2cpbXF5lFH|yAG~B z^~>+m)+D|XajWmcCLgk?`PyAhQbVbu(c04KRf~kHa80VR)rk?fHc`e8*&@MCm=|+^ zoK6CwqOI2V$C@*E7AZcf}D=C+~KU*gQg@9V-l%twhebBJDPp(k6(WE|(G&P~3y|sld$&1)Kvv(PF zLMI)$vLjzxfnC+<$GtN}z7%O9o(*4%sB!}h6-3(TIU-hNbf;_Xg?>F7`B@~5Y@(=Ulg6EBgphB+t>BwQ&?p!U$Hv5-q> z&54M$SukSbT5!RuHQ1!+8_-K2I)sT!@&Nf48neS*^)V~VyQyg@QymviO~1qfEFH{$ zb+yrp!X~jMkwXrl^%A`MDAun=x_YWL((X9b>Q&vN9Gui5eX{CQ*dV+4>Mo?G`QyIw zgerTZxI5?wbZ#6*zhR-7WPjHNICkyGZIvE25J+pnU%$n#-;Zr&04{W`i6 z)~lQzA=X|caQQ@ftL+b0r{h8EvlxZ0U}`qwl}W(~&{CI}7g5fP5Cfl(Hd?p;0Fo2R z2&<8;Z|>f`J904X`x<6xQjn7uB8Son)X&t`Q%5xA7Kn%(O;Hs*KY10(Ck|${a(FwpTFDNxe)s}6?-c?G2d3u7ZDSnB z)F7l95$nT|s3WxI*2}2bY0zK=_4Mky@;EjJz%uO8hsbl{8wQfytAe@HY-nXTdQW}86Jup8m6xH z!^b8xxf<69Bdo4}4#0Obdd_S=NxD0Bbt_-()|7doafb_Sr}TCFK!^V&+}=*3@hj16)&4S3HQ#{c#QwX_dh1NmIA-Hv z?+md%?>4XM+u>E0HF>98RhPs7Y-_ihFE%ubfi1YYL$s~1 zgU@`mRw8YGhG%_#s1^rMIem43x*3PIP~AqHh3aX@SAT_as93Au5$jGljcCeSZ6S%S zuzJ*2a0+C1y400Ob3N+s?7OGh_+>A>t#)^TAAxPy{VrD3H5};N`H1O56 zB=1XIlIDdu&Dkf~Q(F|P5Pc*dJIqX)V=0^uZ zuI5@>IA~{62}luuXjn!gF}qeEMy! zZ5hs}hf7y@2i~Gf)63RdbPbGRXhWZ+@7xN1JfOIFEAw?>=q7Q&{3vl%^WMXLi*85q zrffz61tsrbYOVEDh|&LlrdS1GHd5)TJsC(&XFfJmrOrw$BJ^Q?b8Uyfn!&5BM}IZY zy59i8bs$n~!~y54T<>&XD%)vBcZz{GkZg*kM8Z^wKUvBR0)hA?g?MK|*4)$(`%fAw%ZTfWSN)-d$bWPtX*1kwrG*@=flzkoz zS(L63@@44BN^Qv%pKp>zU`x>cU-YzpxR}=vwZp$V7h080#IsdGpAUF0X^~P}q}08h zU?(8hK~#uJ7K2w%HMMpmQzKHLK;V_P(ZY2AsGYn;jDbBJB+nVxVN{K27DHwGQ%$S! zNx{4tbB5~6P|pI(FY#V5L>RYP?;d!09z;4RS%&!w>o>BDPA5KAFxwH$w>2gyjlq> z^8R#maA3!Ih_kCzRD>biOVxK7>yaUDxOAPhZj>0T9L6Rr8q$sGY!rNUvEF4%ZS|Ro zpN9^X8ro2kLQ8(zI^4u|LR-*96pXy0n#L|JdFpMi0s{CiEjxp>9I1SQhv}>=j8WTg(Y;VwX z!#@q^TFD#q?2zp)W#t@y8X4rxraa~l1DB#FnH573V#?F-ok^j;Ie^u*>J%1N-CN9L z7D(D0jxMP&#{xj}5DWi@`dc6nyHjcTAh&=c$r)-h#;J(0Zz}8zv5_vN=V~#~L`p$a zv(IkwsP!EHL`Ew;VAB&HTfCr~0GFVjz#=iGz@ui7-d=&h#aoj5ae8`lr)G zf#-8y+qz-2-YfDY{q~4KUvLF0z&Jo&{PCKUIo6r&F-N+&PebD zfltw{D8Be{rAJ3~<375r6j>j&1BQpnrz!2ew2K0)e|YC)hfhd@+53IxPnV9LLZxE0blzpjB{fX(hKJNvX{`Eh=z?_(PWE&2c3FYNFFE+=Bg zNAK&VxrR({bUKV|;{DR@Sq0iQes?H-MJ(BWO>S8Y+hd`V%G}!Z7z7CbIYt=gV5fYC zTkViSqjROmC&ThnenlK*h)z(s==w+0)pYnZIumJD@C)f~6KQ4HWyDETUgh7ICdOog ziI$=qH9ECAhmPL3{?2Af&b4nt@|^u4=S6$@YTA-zxPL$;)DwS3p7pbKTRnMeL3I^> z?9_oQl>8yEChH30_K@~W);zqVzw^nlQptAxe%>v)XvT;a^Kub#bQo64q!$VDiTAMN zD_V>j+o;J&)>kFz*Iek{ty>rE(ZE}FNm`z?PVjv{?zSjH*Pk^YSHiVq_t6InOY9mm zQ=B#5M;j$e>977o`#kg}nPQj&1Ihk>>6JJMN<3Q%v{%UwYA8K7KXTAkkfP-hm*>hT zRNo9u_D4QTkxF{wn}f$G1`1LT!jn-L`W+5;VQ87X*%QXiq(CieiL}{6TX=W@<^y({YMrE6Ng~@tLVj2)4C9@DCC#@U zO{U^FH3C|&>%5Hoq{4i+&2@yNE+AIQX`y-=^HL|@hH8Qjn9|y_1vpI)-7|$>x_PR3 zw&W<-OXA8;NK3Ip$_|@G`HqnLie9suH&p#I2eJNq&0|Ny95J|EpgVui5v|Rh9oQ#g z;4>ky-S3hL&$k2G-C6)lA`qQ_wWjtL5Sw^wQXhQRN=tt&^}`P82h9DkX=p4grw#jI zHS33E4(3{}x=1-QRK5!^69fNB%)$nCxv^6W+za1y!BGr2XoRNG9mh-XBvC7Tp+JQd z)T7T%?Am;7nI(#Lz_*8rCiKQ#x5;av{Cus@E(S7^h8l5t@h7L6EOgO-+(~V@*IpR> zko?E3$EwsuQ#IHUC=44Q20ltccy}D(bTh(kwa1JzD~Y@CW$w_q``$#hAXcrL1EFcc z!>A@7&H)S5y@u&efo@Vvc+GVnisoSsUT$(Vhb7^6?6m@RAdH9ye~xEh!*%y8(2dRn z6vqb&@2dyh;@5iZ|$@NU!fBoTUvXdlSf!UOw+X`O$da z$%}ZuePuEFO$=1weXRcaj{I4fudW(>fQ^stW9kLwgKtZcPU03iMm5?_Uj1S<=KeW` z+D*J_XYQgbbW-?UPhz!r$rY-GMN+s9Nr}$Ut^zdH0?zAD?;8DouXE=^_MP*lcJwf} zdG9CfpKAXbq9~VSYcb#Pp`4jn5^p7#mNvgRbZZ|`%Y*BQtn4@dI1Tw;A73%we_3eOi`g77eWwgVPy zD)&8vey%=$BY#otx4ee(50@miZWxj%bVdKw>`w{zIZfG3V%;{947&vR2bGsAT~>Jr z6v7Ye#SO~eY~%usnQ^4bWBr?7LrKKGK9h8pBYWGGHUXlW6oeD>V(>%h5MsYg z@F$BlHC|;~CV4H;y_}HC3prJ3z*{kbJi_Dw23i{jdSx`7O`SE95jhq|4l%{n>9JvR z>@!9Q=Gdir>^gJo6MF1=bL`7{Y?nFqem%Cr96L{sU22Xk)nonU*!g;FojG=)9=pmM zTcO9kV2-uxvG19aZaE!)@p`P&96Lde9dC}!)njwbv63DunPUs|*cs;78G7s-b8L|w zJI@?DM~|Ivj`i!Y4d&QYdTgsXc8$@$=Ge7*Y@0duH+pQlId+{f7UtOXM*j{q#fJ6R zvF6wvMo*e!TlClo=Gfgv|C(c4js7*qzGw8LIrbx?C(W^KMo*f5V-FiEz#Q9dtN?TD zF=GXoV>^r$V2(X$tN?TDevDO$Z2GJ)r;Vkw8G2gg5Z$WHDy|5ah?(DJ46}I=q#FZj zj=jYg4)f4WHagxM+hr_IGg{pSnPRa>Rr1w9)_msDDU*LzFmpeuJY{tY`)OrAG?`LX zcd?%dlw(bn#0p@4iHt0%3fc!_aZ6bumV=*l?6Z}Bu411Z{Bte)w6KyKtfY3HI3u2j zpX=DCgMYTL&$0Y-J$(8%Z^x}fzQ(I;Mjf5icUgWjOQJocnV|8Xwwhiq+2@nIHJfp_ zXiq5!y@cJycvCif_9f#qWk(7bvRy5OW`Df(5{ua|(U&HF)_Xn{lnhkiY~De2Pc^!K zi$R&pgYud|#mun{dTb_HD|Q-BUChAqDy%szp=L37Z!h_Pf!ZCz$b$6a=yckUa})G; z1)<+h=<4mo?YS_th18(T5!@@SXOYXRUwVcqI~o5mTM{>f=``KWk7i_Ryk4{cVD?68 z7_5ScZpUBY!zl)SjFbO7AAg~VqclT|qO8Y$!%@Y@ z3fRpHHa+^A5$+G@vN&bnXB_ zyB1RYhmY%tVm%&-y~8vo)Dl6@g5==GyezV0Gh*}b5eF!cV*R@>G8Yp4?m*S+5&qo{ zbB1`q@^IGG(J){3^sUwR$v`#6cE+b}cG%mj%%GVDfteIY5L)=03|dH#r-6_{tHb(o zH9gq&@wt=DJv19n!18nWW^gZxz9A$&7HBW6V@Ag9V?#)tm9>)`J{^B~o!+9@e;WQk znOW~vrys9Ln$Grm(DxOdp>LxjHRV`l{J|J>p@vuXuO+Pxy%6Zu)?$me_qEO)up&{n z*iRbZEL__(sm(YeD)o^suy=MX>JJH&kcqR(8nIPH*2**YJxjTC=M&*dn)?Vjw< z^(s_Wg|Zc`a0D@M8>)XD1D}h5e~{wo&vQ^~68atfxae`P!kkaVz+Wj(Gpt{qgM9wo z)5}ln7cqc$37}W>y$@wn5Zzu;L4ECM&ChwmHzxWHZZweHjb7~zctQ^eMhOLz7PWfR z&*WRFgb#QnluRh75w-EH&mu>MsOa>mMLD!Q)%Lue(YFh8$&Y_!@8pe2nW~#>zQFth z=f2GS1Q(&xQtAfP&iezVjX9g`n`CPi2;Vxo{Ty14hMWz{Ek@_2gffDJM#(bY6@YA557w$bedws?S?d9>f}PGvQ4wq!bbK)o)Xsd>0^M-1+wv|3$z zvz~~6{?3lclkw9GjyhDr2f2WBCuaN0bH{d zW5z>FeO8~OJ)@VGwjQ`RN!vBiY;cr`4oDbMuFR;M>9_ZU}7cm2AbbhlXFw&Z5MZvxS0O2n1_ zi5>xpvIHF-$W20)>NhowZe_tVew5Bxlw3NKqMb~eks-n2h#a!?VdMf#-Q-`vD^#>I%#9~Ue$CL4?Wb+%U1Lk-1m#nSECg5|(&fQ)B@v2kD_MeuC zY1cB%six8EnmD_yp&#|q1+Z}H2#a%`ML8pEO0%!Um$r?oX%3rlc}`nB1G_Aam9sBa zw(5&{R!u2F+v%sSn_x(wxU=gQ@>pR&xy6p&-e#r1N|Pji#Z|Mr3*CHTIJi$1jT8l= z6n4mkz5;7kz&GA3a;OBNSD{iBbc5<}`%;Cu`pgX=-(E^G_LFzymz?BGPyeSZAphx( z{8E@7KRT4zAsAecJLe_R$N!CHIAUQ}&e#|tV(<}^1U8=}%}lVA%!^i8^_LqFonLD} z9v(Z_cRibb_4y!EA1|U|HgjW;qw0$(L0;31?l-^L0*J$81B&nXUWH6 zzV;juFY>Vn;CxTVj45%)U1T9-fTH|7J{-NFm(@Lg?3d6}c)U+;zi2BEhkFyw1KMAr zE5R?}OAbITVy|v`%{AL4Sav!FX9$zv_wD>1ZKA9iB|jnDrEU zLare661$p+x9rh$N=`TFaV|5x?8Zjw1+}*~_I9G-Tpn-jhtAJR5}n{Hjk1>7ul zi)9o3X&`S=cQ(5GTe6nWWjIt#rlM{qq-3GLleV+IbXPNr{AvjEPMH}uU1{fS|5I=b9$Qq!sMJT7^X{L5IRu3mmoYF zYm6Hl_NA}+>Pfo3PG_aWg5UgmyvO8!I<*7&L*Fd+w3HjWD!2omE6kLT9C>K;xnOM%A;Y3dao{!q+eu2IxK1#p=@9VqMdSHWf+k2w;a+Vqv>t$(yF}8gyi>s#;1=Z{}1u^ zHDJ#F@1?7)>Q|6{Tz_vPx3fvWHP}@9JRPN{i5nW#?aC)T^2MEWL6p|TjYVct zkZ%>5l%7)gUzbc)deY>DO3!fL-lp1L;30b~pGyLL$mrbdH9hFxL2mS)5q!UnZB}~9 z@)}l*-rrH;5dRA7tH5Ow5OY9H}q{QA&=)cfY8>`uZ&|hiV z1_DPfp6)y8Dk@$b(^jG^SP-gbYvuR2R#1k(d0BHtQjszH8kU6^XrP#U6=&@)X$4KY z$hGY&DDe+%z`*$)gNO_%wDKbo?*AdFg{>~N*{gc^#U`=dcM<%5c^Bpvs>JvvTiA-1 zwwm!VM93rtZGy4aBVxgQzGe7A_C;Q$%OM8-Zb7wgSB4ls9ljS&6xf^bJDhH{%d|Ub zwRp44lill8r#WH=q?+vvtpjmf@w{;#QiUO6(5%DRPc2$Z2d7dDOVVgs++d#tkT)2k}K)bRe4Ba3hYXa!)#q zsWK6MW3L+QtJ)k4H=HGZ{GKi{Fkb`;|k2t{Ne?@=$j4BUoFjW`}M!s3WO;@YybZeAcMj^%g9WVOnMlc5e#s zQu4# zbJHE_92;GHiw!~JBgtH-JIkTv+JfPwpT_>U2^TS4mXCaLQTuXq(F5K4)C`z=UsGD@ z$2k06)UQ2`W^N5VI9h~9LpKilL%n_U?VMAl7v_e4X}Jz%d8SQmte&8>08e_EI@Q6V z*ZI{(-*-0SbYWONmfUm#kq@Ije1>w`Dm!4?IW5RzIk|_fICO>ve1=2WW#u7b$A_K3 zb4)qZov)>5sXuby5Nk8-+nV(&u$t#syr8yim=3rRD;@h~fBKSPZf%}Jn?3{WoZM*h z#5DPTZnX`Xg_PaaHNiJnKd%-NWvLAalqb;mZLg#1mQfa>+n_4;$Qe8Ze;eqb^H-Xu0x97lV5p&rdWwg}{bb6X9;tx4NYD z#NgX{E)?EGFN$WlxYp{d>#Za4`KR48LpfuWeQHG6X~!22+>wG%$-S_6z5tHh6Z}F> zQCe)kPC&o*?QbbG`y+Pz(taa5{L?@2ZAjPNFM$8>)k8s;+w&0?VCF`Ywo|d64fLLW zU-zsymVi!=(ssfV>{UJc<@*alOYX%N?>@&9MY0n3O!$!AOXO<<&2}+XIdoQ?y}4 zabo?fySEPE@c~qv+WE)#pd)|>e}l|_3h^Qmxi>%?$yH)~?Gav$cSCqVNhR5#%nS+%4rXoZonnJfJB2I`F^G;^#0|Ayz|Ul>7{GTDC#U$HfC^B5)0G_t z(o@eRH^05p|An`#khba_7I3c%pM7@i~O2Tchqu@C7YYvAWd zv~ToIaX|QK28I6bVq3gZe&LYwXm7<*d=B3UNE^x1G8{`%;S=4i#Qp>U9D`V$cgo|A zYLUDOH9=%Lt$hff083OkI}Bfcs8wjH{g#ejx})+J5Njj6qnSv%r(Egq1tAUxGm0}D z!U9Y0;@qxjy}>qzV+os@JVmU3{s1C=Frvr+Kr%2Tq`>5d@jTAkJ#jQC#_%_+auA0xF3wqq@MEHPzO%~5pwc#jJ1HUzj z#SueAXN3Rg;mBU>R=;gd+=A9S`dwjQl|4cyBy+Bfk>xmBhTj166+RcBHUsth19E}D zntnwHeTv+iTfNp)KI?h^F~Rqe8&7Y~Q?gqfYl=18fN7o< z=Ae;c;6pUnpVZTr-_ot2wR&_Bz8vMb9+ zr}!3T>(14EZvq=BWTKDP&jjBn7_2Ap{THYKxJ!su9?wjFfo?nB!n;^scqydNrH(YK zV789ZXP$1@7O&FzzfdKJ9Y;Xy2m_J#%P_x=`u7MB&UK6KqtS(|I<$YF=Q@x-A^(i= z7Zg7S*7Y6OnAsz$4jAogz3Ncyp3$hx-9}^)$%dHpn5@*i9ow|gPZRiavHoT>l|dy% z;cmTiccZO;j5pFgEHtCntDIRT){a4yb>VK8@P;=hB2I6Sl9R~lul+ZLk zG)zW731e^*lLX%xgG%>E*D!P-QmavMl9ur{f|28YmW_*%C_H0f@5-nm{QuVI*QlhN zf$N}Qv7YinuSXpk{SYVeMm#2WZJNQ7JdnwwUK$P4LH~zzh7J)|L!PUme?)(USo$X1 zKXv?J6M7aCXlDq@of0Yasw0&)f!r#h2WlkW zFwq5n`CHpJBAde=??tD#BVl;0nB@D^zYU+uw#Xlu6qNgMrR1w$Zyic&k>1SK2lJv% z&k=#&V*o_)85z@Zb5TW5`p9S{;~9?_oD(l#FRb#}_~2HlJQDt<`NB|QuKed%11>)K zcd_*e=PUH+^Ykp3I>^ATc#{v_aU?n0j?*lE2sB!VTm2%z8!$rsy}tyt5ibGZaYU!* z3#S+vaAz!u3wo-i(RKZk0Nq#pX@Y&UaI9~!OsZ)X4b;sRm9fNq=rp>j3phGwq3q| z4gRLfV@@epKkm#ja+xz6J&J)`f<=qUfWz-}hq4CXDd{sJGZp`IWO`zWPS>FqiTq zESYTO6MT(+KR!G8al3e&G&OO{K7FG$Q9`l)E!w;A^yt7BZ0~B88)CZ>&kMJq*Ainv zK`Tyfz3;|&E6~liB_W0~Fx_+KCY)PF!Vo!6Y%`uisA!fWe z2J7CMZH^g@FgKZFsQqiqF+aqZpX)K3kX_&EaK`bDUJm2D=@%GXb+swl$_P;B*1aa+ zPR}Vc=+l#0O-ZmEI?>2YIauL;tvTcuy~^p_B~s|G7QC7VVbT2##bf#yOGoNnv}pMV z3P^2X2B3_aAQviIKQ<%yGScs;LuvG*Y9NV!L3W!oxE~Y0dNDuJL?_sIFY;pD!1Cht zcJqEuPCl9x(Kx|kY^iofX2|um(soV^pi5*WYEw?zmwd}`jr=@HnL(6)I@d|eqDp77 zEjG96q?sg$PoXn;+z(gaaSC^+xhy_+2+UTUiKzIUbAS{dK0v5q7!x5!+d1DDEzgOB z^b|u+^IJwDXa{kiDVAZ-o{`CICb%%0j)HuNabYh$+haAI3cgtCkPjuD@B&l_s=|A^aHv#`tZ{1eNZ_N1WpMK z<%fJWloN3MFn4F<`~fi(&=9ZNcp*2lhu$aadwCV!u;w^rB@_ZR?|B6+S^wx>Ns4BEMMIRIe4w*Ta7_5j#dWSx(#hE>aa zKrh>uEv_g+#{!|Uck-Lb!5%P(J|Mg}AIvW%z1G7xJU1O0c*peq&}^xV5XfWYD{oly zYsgsDx1m{~E=Ht(Wp4LPEi-b=LkH~r^sX43)?@CIK0Pc3$B_TZ9US57vZ%p`@fQY& zm0`Re;yA|M5f(qgdcOhn5qi#4c3ANZLd5zn{frPw>Vu5XbLY_Xi8>eCi>~CbPsxg( zCifu&^k2y*FBa#)#}ht}UEv9SPLBTY)eyA8^?GtniApYi);dRZ>2@NA^ummioa|ZW zcYybIDd&b%*TWpa>NhRuZ~A?OODEQi=Ob}_G}j!Gl0&i^%whFtn8vC8&FNU2ZyCM< z1^XC#mYJzm{C<=>re~od_^x1Bev27dF4<2aH4~UYeAiTjQw~|#DKao1@Xq6k9YN_(rD=@T2lekfrx&!)=&GUZK?xb_1qc$<{2dpV?bdy4* zAwdqHRWY6!{ZilrHU*R`m#0xP!7?(Z zqY4p!HMDtUj~HB!H$|Qyr;VJCHBaN)*|Pp3(mn(Pv^oVvF8@pTSBTy~-OKs>DfICr z&MI*Qs#RQDkgt#4bdGH$Lyzmj61W?Wrmo;M0^K~8G@W|8iM$?bPm%BSZx)$U;NqRk zFL9hT_zTWSM4dgn2^S|dq4peW0*K}!Yd}*n^6H-vD5jD zzR?@cBl8WP2J|d5cH`D^7c*0n=;i17=woMdag7@x&pv4qQVsiK;_*@wTH-sbJU%)F zc|ES;t}i?(*00`YLC&Nbxj2wGuI}k<6ufHTNqLyE(}{u3Myou;s}!Eh?QFEkL%lVB zg(v-%&PF>6S_I{gQy%8uZN&n#yj-L(>6PVp*mN(fJl`G2ZTt76d)3)c+rB=cW&zr4 zB3^;1B$y?k9lfp>?@4t>kw%aXmhNLwp-0a8_t>%A*zef)3Hta&f9JKtZKg1tSoK0+ z7ugY>!2u1^8Oyjj(8>9tf7_oL=lvLedw0daJYBpHej@4C=An}JIMfDp`gaS&lNt2^ zhvg8=)z0G_TWp2tyvEEY`7-qZwIe44j8iTbkJ-y2dg@W*X%R2*W`6VIBB+{*pNhsB zv{_D&U^fD&>N(ba$5&`!b1e1;CciZgMKjpuX*Tv_XFuue$H9Iw*iR<=8I3=Gu-oAH z-XNGP+-Dz_)Dw(QLu2yQZhhLOa>kF^aF`%W_M3+~J%?d)coQ!XXhm70=?U`>af3K& z#qF=rC2k00;mV{P#=&x{dFgrqzlK?V6e$HpH|}kZ936)0qC8ALC3A1GZjp8Sqi=~|5Ef6rK|vzt@+LDX=) zrBMMw%_;o+=_GPyDQx*fKckNn_VEFIFg;%MO?s?^t?%qGSBK#=^Et!~@Z^hvwz0G<1uTQ06Z+a<5^ z_#FGz;k3oo&~`EFZmRH@a95}_%UUR$Y=6W+M!p_vMoi|KFd>Y)A;KF8+X!fkKFlxezf|87S^GKUuVr{J-q_V`N_km`vFV84XHv%bdijQ!NZ-xU zBrwLgQ;-CSfm1Nsv{{)%FiHe=fnmiw3Z$r{JQM?I^f2eFEFio1JaN#Aj2@jrh%1)a zki>sRyLYZ?b+gx9@s-QKZ8okA7$yd;CcDZsG4LGU4p54UMrqEl13hvLFZlnQeyHRvE;%4bpDOwEtEj^i;4p`Hf zV!>XAPbH0qptr#So6dC&g1?bCi>YJbFO>X&1ua_9KSXC9I@Rj1^1~N)KgQmMS54+! z1I4AJs1BZgB8}-ffbsM7c-%-6tsl;*dAa`0mymLODB5-8W*7eXk9>u`Yxgl9I1Ed5OPfSdGm2mOF6GE6w|WylS;Urqsl;k?8j%IXoUn6VdkpZ)7I#j& z7-+LIK7J9kH7|=^0S=KpqwiyVjTER~>4K^ehi`DJvp?3iYv`5eD~#X$XzP`hKJwED zl+2Ni^q1Iij=Pw+s&CqU#@ZTb{=+>?;{MnS^=E*h2Xp!>{%7YY-j`hbZhJq)-$hXU zx9sMBb0o_}FQr|o@METs9oiQ#jTQ2-7hezhwsJ_^dIbYA_ale>xSJLFJL2Lmrg>UK z>%E@dyoOm$$}E4sYXE@WVL*MBLR{+ROCh1mq|##R3qp%N+G^Ej!BKtZ4g3R7tkfOR zTLI4zxtUBHuqG|@M?lJrW^{8=cZlcm&t0c~-geb|ijyz;54!tb_+H$Heq4iMCw=dG z-Z7T(Fac8N+=lPB`_8aze-$W?nN9yK&xW!kZlsYm8}PBw9e4!-wzH{7--0XoGV{0L zsz5U_SV3(T)7dajYCA_1)s~Q&IG{P$zK%1-i3}-u$HGkeApUk92OW796)UU1q($U^ z`9R&PHYo?sd25dJ9`~OH+JYkQ)Jj0iSzS7%%)z6Zc%%DC%6&PZa4V-&xQc0Nr6X)Um zo4;ba1|AP*@5HI)+Jagu5aB+8$<^n7fbiex<(9tj3R|-ut+V-@+e-DBL-t_4df2>h zg5s;F2*YZK**Lr_4&PtN;|8d4)H!Z%2IW_cM#qIe#}{T^M}{0_Jximn<`hVotcv7r~L8hY>$V|5?sCYed~|=)}uH(wmox~0BgsglHYUQRbLTjWA2ikvuu{AjY^xSlDBj~yXH^_ za5cl}h2W5MPB}eXrLb80U9=(B(#gdvo!on;Se#SbHYkc2xg%Wy z2EVL1Gai};A_O|6s-2O7cNhpR@HB;;l=>`%u_Q5gJJIUVIFNyzuu#9&jU-x6V|A2a zO++tu4!~8vTyrK&Uzk^aTrrtSBNPG?DC|#J#~DAytS5DD;Q0NSAQ2d%{_e^7-3sKuda}oV3 zT5tj4(20R-ZEO`?)ORACILS6hQrn2Z(^fW(nC>6{H7O((`Vaqq1E&zqsD4WM)5*A^ zGI0M%T>SF|xAyQnF))R0Y4gLWYi#7H30ZSkeK&BlQu`K&Wgs4OoPyUdhJ$#0C?j&_ zYNgQ%BA8X3RVoHtL)dcwV!%$J&jsHw|L#nNC~#c;6r2JDM>m~dtYV*y^3xNH60!GY zb?-eNnL!#)U{h&-FQLv2K0+$ebW+&PKZ6ck`_>vd!8bLY2EEzOruGnn`XGA4X*|t( zi6oflZ6|OU!T3g>If;id`nf_<71y576KN8C>jYlC+=hEODwKCSahHtd0i~q_)#$&T zz$uG!U!GYlu{keGd=dv<@5Tj7S}NBTT0(!vmwiX%+SSH?=(Tw0J;I5>tIrY~t!cFz zOT?M)+W~Qeg%9F3p@f{ox{ARmoyanS*qp=`i^1=7#&?Flon^EC+V_}7{snx($cm)u zwd-U5(sw6=5&W9AF{c=uk7sU)`?DCB)zjYwDE}?`r>_}%%qe^P>`QI+A7)(A-Pn;p z>4Pq#M?a>211SIDFM-QKOaSkftbl$thC9AYWQ+Qj6vlkX zS2G;})xLkqbbhe=RQ&v)cH5~wWF^`Gef#@Utbn$2WHs_2oom?ye$w=3fk}ix+&%gt z3Nx55+pOhCC>(vZ9x>>_^;ZGe{kt91f&YbW&ssTud5PlDlgPwt!44wknbALjlHa7l z6!{N-pVG&o`HZe|{Ex4a?4yiJ88aN(^vsZiPirr^*RUPwAomh$h*(b+gQ$R5C(0AI z<{|}QZ?Mp__O4C188%Nx4;#P`Eh+N4)#-P`pS$M3pL_1*7K0!eE}tRzzNF{fK;Y`! z#2BdQMVx}3)fLyRVm(i-IcOP;+T=9lwBS{L-tSc+L*F{&Rc95&UM2*{?$Uq6YE%yO zs(0Nh|DXZq8kXH)XYq4LhqjSU@>wREk?AhTwB%mj-w89yG*r)oS8zLpa@HG~#uod;d?s08m{ob5LaV5Gx z^P;LSlY4#J*TUonJE^pQi<8J44Vd_50d0c2UY4;#NX4dPs}ITRx|S7I~}E z4pIP&ZCJp^uT8g=TwCxkwY_yGvxDJHpBlPlJT_?~MCU;}eU?o+`S{&VR&q}>^vkHY z^**}^btkd1j&*kVQ>NAy+TR9$z`~p!pGw#}bnFjv?C;*$7yGFY7d?zt(p!j2!Pny$ zzw$vmaud`%$GmRFX({JD-U5;nhH;5ai4G}loZJQfuv!}L>!6#R?<2T074Ii~e+J=f7 z_US2jWyq9ji?rD&)f|};X&Yk7LjHWk4R;EVjJF^o2kntIM`}deFckkx1Mo}=*yyC% zrG~Mb&@E)64@kLF!+5S;czHO#rVTv?=7(Mzj~)Z1lz&l2N}8yD<=YV;l<_tlyptn9 z=2>vfCD#|#Wz_xPZ_#oIEZ7}VRh;R_|6Vzcg9jE!Eig6 z=yULHtmLt9LCCu-wD8E;qyKtEn4gBz%s z=DL+G(YH=N7P@qQ2rj9?@SiyV{{GD;s88}TB|#nZl)}@O)Evp($Kp3d^SOQd9T|Q`m2R3fGy!&zQoiOyM=A@LE&& zH>U79Q}|_5c)ckcHidVX!Y!uoZd16`6y9$Nzh?@6WD2*L!iP=ac2oG6DcoTSqi=hd zR95(|uA~^7DK*^`zQq)tYzlXo!ri%iib82w6!V%XwZRnL!op(xYP#TAa|W-?{#u~m zFC1!%7+52J===XqxJ4ovK*J`Z*5WC;TKgLPMQ0vN8E3P^Pc78V!&Z4C{2f~TBlw%Txk>EBd6Z^&Z~%lJGE1#KuGHGDyN4nxu`&YZ3Piv-Lt-l>+;1Qo!>VK${CyQ z-=arBpfDHpasNfdUNwNiZgmf2f2$3^TE9cC^-?>?gB=FNAaYUB)n}Ng+N!Y==**!v z+ykF@BqazcMMn3WHPsA-etf<{zd+IHHWYqFslC11Mycdb{#bO2Zg+?mm#r3VE{-?H zTlg@4T|7Rl8{v~Fl)(XTJ9OV1pqbIFXX4T}o;(wOVa{e)mPao$flfgOTjEcTqf!Zj zhRN4|n}A~f!5E}48GQJO*6R0>ZO9v>6llXtw7MpOTTRIJH$o-9D34` z=Y-P#)=k!^H3*xph6_@Lc{DrUNFztAu$N+gVYHXt&Gu3#;xe?6h4S&-V0orh5~oF^ zlwoewu9ps&Y()5&zmI$|OS>l%HdNSfDm{2l$X0!&a&$N^&!eT^R>NXB7?#mP zH7q709(tqZ(1Bh9z;{5Km4&yBVCMx^d@mV@(gOM!F01<(7eq@;Rd9J_ji)V1WUAAD z>~QQqO#IJ1nYxJ?;+MtnyMg0(iCEtUKOf!irGoVW?=$-wW%sS|ZmQaXMP7?{Q>WsZ zagITM!8JS4%NI<#T;KD z-&I)O1gtNEvS20hca!V*j#0;JraBUT3g4}^usY5DTK(HD75K2qcl)B55?1Bhx+vwKo;iW3P0t>71FuG>6_%O*@k<>m5%1= z1398m;O*ZaRF`Z*;2DC6mEy7=NK|rEw^f6nl-=)jS=2%fXL? zKj@jjjarb{8nSMPJxv#wVhThf#fm=0?h9+v7h-#0Szb;X7vA)tiY*sm#qd|Q;j~iP zNG-VrSoE;j{{Y&jb*J(X6rT&L(`;Jpy5Z~%E%M4T5`8OJ0iS7fEYUoTtly3AWPOE3 zJ`q|KryKXp+AYIb?Q@0j_EpTQ9J*9^9^ZtPw3Ya(J)|zVvU!>f z$u_Bs)M*aQl`&VHmZ43}P^US!W1@q*M2sCw@UK8#!*LCgIdkfY_eOH|o#ew{X9JVU zKb1!)J;Ek*_O<>7(bLHAW%vw1{HnjLtvm@`r5K#HRXZATr;7NV#Fu~rbTEil>YcW^ z+Z&VbZ6ZFi>~e_))ZdmRDci3@J35d??ffpb{3GoSXK<%{3pyX#?I-8X7T-G_wOwk) zJGYjtx1bNh1SgqH%OS+pvy)G58Ug*2YHl5W=wA58?QTmxkkt32lv?Je*WuReu4{IA za`yTpj~a1b6LHlX{4M;0tqhaYU632U5#qa^?42y$6Wr;$#I0H&m>qWI>;yO;yTIzn z-pBmV3Hj(W{w&_Vv|HuPPkIy)?Uashs)Q!c%~WmO5CtOX1j5uHfVzl7 z>DUhlm|*};I6q*f0XTU;Ky*HOyg83{Yz~}j1|F4M>T7X8$qblb25iooLG)-}bKV@I zWa`-h4Td4_ekOwWd*b%xv!#=L-jGZFTWW*ud;1Y zk8G;N=QAyve~+xF7{A1buJZPn%O^1T1$HZ7ej zP}4}5u0`@9)~}qAj&vCWE?+D9DnbI&f-K53`&N8w*AptW^s14)QPB{ zYE@g3pC}o(Tde;Qil$czB=jg0%Z))lR3poO8T)+$`c94Qq$ho2jll0oYS(Njw2hn; zYcnKdWe?et?{OJPsj)||noTESai@HtCvB2?!t8ie3O%01zX_J@mHY)*Nux(|rC_Ig zF#wjvA^7di^(X_x4k!A1psKWO&k$dB0xc5pbO~6vhdl!QL0q-M3POuqbcty3vF|A(z!E; zKv;A)*5zHzFH!;W^K67X{xnS!Q*;!Eh_!PGgHg=YKgREXCB$Thy1c7mzr%Oj-b=-a zwkGQX`rSfJVSg(McUw%&?)0ivqrI>nda(=yw2Eu;M$$EIs5qO{udbfzo${DNzP9??LW&C&|lj{4qrk1 zQK@w{-vQ>C&gPKcuKq51yp!MbP7xh)vl&YMK&yR$Jb&QJuf+CvueUhR3+s}PV!tMD zZ~J4vK;L%0-Lan`f6}GTZ+>#qInDkfG57{e(-Tst+Lo{GXuqXbcS9BYHOg%b3<3?_=*lK$2_~*s2sA&8G5XZ#ge!MIFD3z0lT?|k|27W z9b+8k7=NccT-jySW3oGg`*OwSnqZZ^U@QW++RjdO03O(U=zwFc*HK1@r*!7otzw`U zXGUir3xy>?{t(-P9&?i(DA(m9l1Ic9c>7hm)25t;dC*vM8sEtgpAXv`#UOh23%Smc zuL!*112T&|T{)dneZ3*LsI?s^%(Qi@wI`W}{x69jbnyp&=q)^$)dYi&@MzO)3@-Lg zGyP&Ov1IDEl^Dw2N3ZHh8qsxnTu)uGgOinXBR-SV+uI~f`Urm8;rB57cEIm3`0bK% zzVhuyQZs~6tH1c&gd;~&)V(L9llF8Ve@t`E_YyI#4&ZZ(qZayoq5jBkf88+K$H#5sw$^gkQoCHwvo+YG>VJth`0 z$ySLuPfFL7xXJjR@t?uRu6CqVIObs}dkq#lB*mEo$P?+g{$` zj33+Y`id!FAN-2l4U9iOgf-BYe^0Ktc!XZl2ijY+>HfU4s&vZ{fxi#iSMtg7r z>ers7U;a-a{%M7y`kvnvS?zi;9 zmLT-H_I@sv^zMztS->64)2mCHZpXKC_R{*fCtYY=hdkdKbQMy;NcDq4waqi`s4H~4 z5Zo#L^bifP5(ZYUBWKSOo#=DDKy6kFTRB(P%2Qi&c0JMQe;yapeESR3gP~ahag6%i z9(B8KBuua$F1N>@Owk|dNn#42e!zk_PqF?4paMAxR8Kg+q|vR;Zp{y+yZQRRC%r)P zgx%Wg)@WfbnPR-LiQP^^$_hKO=q-i8 z&&B!~f0;ne1>~8Y$--`vu!;i$B9uS25XS4*uxD&!^XNG5rw%EF%8dmjW%CSV4aLBf z?0u~Y9p^o0u)4YwafTN8Er~df2AmO7DiF{`xT>G<{Dmc_09Bg_)xC&nU^bz-hNB6k zx(UtO3C%wvnmE|>7)~OtSZFK+G}1}f?UU~>f5frZ#ty^lw6BiGE@FI|7ze3ojZUn`y(OX0hGe>NVnPvRT_^iH!D~;Bjl@R@OtJJsz;!nIaJRd=TSXP ztR5@X^BZ2zVKIRAz`UL-1?CA~ujmV^=#*a345OmWx%#tC5T>qgrh&2O6BE8Gbm%0X zf1uh3ny;78$?7E(UXNjA82L6*$YK@%u;&wEY zlzkZ<^G?D2LmPuNV+REBrnNY{K)asBd@crq5EDCQlpTB#%R=ucTQ3p}mA0f7wgA0v z<=p@uNC98JAgCMrv*)}gUwzkgw-kEbe^Al0m0BUGz89d3bp_f(Qip#f5+Ff&(k96B zJ8SbrazAu}E@&-VmmgZqxRk@N8T( z1Xc^|B0j)Jm4~QIy^AC@h%SHf)u!0R#ErRA%35K=%oPLo3?*BPR@&NNY3S<$Z38iT zawU4(=qav!8|kQ@A(pQKFYH+le`(0G7pf7>k7sQ9@W8I_S*u%h1YaCN>}{t)Jui>u zXDj_SHSyWA_e_1u9jWN8j*Y|@16@jY8lwm7fdIF9(Dl|4PvCRk^kxN*r%a>cR@c9m z@YT|{bVgHyuVPj)SUv)G!oJ0{exqUn*9>8g9|!RnDc7lY`V{G^If5>Ke=it8Z8H`C zl0%@2Jg!Z547rf5;~nfX*ddJBU7-2a^?iqqh8RYBt)`qD$*lBM+-)E3 z8oM>@&$a5Tp`{egu z7)cetbn>h%2(5d8(Xaw_e^HAVh@{{?wbmf@f1#5dUsww9w~7OR&&1*EVG-Irucw!H z!dfBF{jadO@n?+*$u=64KZtmvi!@)&N;e;mW~Iv*nbnAR-zP?CAv<_ZZS}E4AX~pc zCmB%WkS*!a(*(GL_evf810+3X%90z-bfoB`&+f8n+DYp5^|SM4JlpH&=qq}F zh{RWTz~L`Y=dQx*&JZK?NEFq(1U|&6Q&=zLIz8DtT}+ha5Ejc(Kq2x)I=$*C^ceht zHg^>aTfUlyWDcjo?V3EnE(XfUM98yN()^752s2heQkKqxktn6)+^| zDO7uiHA;CEXF!5LGastk%HB0?*2xgoeMiW)tspe{4YnY%8aYaMfP-ihs%O1Z)uIWR z1u6fI@z8n~u!5MBuf3LqOHj^8YI%@7W=)!usE@+i`jWxue~GTRaa8n|rw0O?bsBkV zY&a6I5i;|@jC zn?2nm28z&li_!7u&1djtH(tPy$L51f1U34;gZl|t{{QiGBCGPlZe&$ZcEWk^9NvYi zJI$yViu%zXf8cF7Mz~bmPnWH85lJJv8@C!MP1BGS@2-DfBnn>mgVrNge(?I5?U+^9`m+0 z^DKY4pe%Uk+rEZpdD5Jv3$t`3WI-nxHI3*bqrI4Cx#Lv4>vs7jxmfo5}NDrYyp%-Dm+CTf4f$!}+e=lM#=ta!(8qe|{ zoeWttf85*IyUD`w{{1BO3hjQHk|i>t_A9(+ zPhX650^^#@&WtB^W+T0<{Zbaa8U1P|y#TzZwb`>nXK8@!Gd{*CGCoEOtV&^9o|$ub ze}Zu?JAiX(H8>aKqzujlA&7I?5$9Z5P53wnpQr4I_;sSrvWyiIm`P?3!r1}z(nKb@ zIt!t##s-)SJ8=5+n>9ax%%w?lZ_^GF)kd%A7YP+c*e`Pbr zxGx9twrT(0iQ#7AiK%P0kS7k5{hm42+gqqUl&K2`V!h|5n806;6gPN6b;^%f=$Sft zS<<(igy0$QzOyiSmGlR$mkk;^q6ClMjOOelP(Xwt#r>oQt z_V(p%o;UM0&zjm+PPgsI#`D@Fe|?FJZkMZ1F}8zB?)r*4!XfG%K@LT}BKBz6D%Tcz zoa__+sjD9}1$C_4JM*HGQq%%#+qIuB_%PI7u-T_t=!Z2YZr&X-Ie?!1?yP+ZX zMS|+7D+txUKn%~a^&qO}s|T7rtBAaK*0M#=U7()uWOv3Uq23pDYa=$A-4CFq!87R< zES$aWEV|qCm8P-zH9cs3DhBMNm#bxBLB@DVV-jj;G<|n8T;CV3648wiEhLEOEeWEV zh#(@OcV>u|qDz!uZuFKQdhbDysL>fUqRlAZ=!_CZpJ9~2n0bEht@p=S`<}J#T4&$2 z&%OKHy+3<@zT3V%@#{_$@VO^f&-;<9S=>ZhBEW}pEu%Z9;Q)>Y7k|304A{2)sISR4 ze&)mvcEAPPqu+&nmW*iHK z)XRUNh*h@MzhKFGY{iK>Ecn!mjH z`R=`Msv22Ou|=`$cc=vO|4l;JJ5?Po9?9Xq21)k)o%6N~IVoP~Syl^Rn7$#;QJ!bY z{RMqp;V$3vs#j-wjPFwq#@iteqW_%BFU5CAUgs?UHSEGP84&km;)MWyWuDxZy4g1? zYh7lu>LM=r^pCw_;PETpcmI*7wtc4_{iIAwDK>jE z;Zvo5@P?(o-fWC+`lVPEzzW>jf8?3aN={+PFZ(gh_x-~(Mg^_akO(5D`ie!4ef|5K zs2eJW>}wHL4uhWy`bTKo*X)4k+-e(E0laYR@u1gF~Scem_= zxhp|!CefZT+zXcGluzOZMYCs$-c%WHlyINx|6|+ii&Mq^DH}KlXO&ylTvhN6Q9amm zTXb7q*ej*1;jLlS1{B}P@~1QPQz&U#3J7TPeAiQ=yn%o4X-lrwJ?4(w(t>}=iGkAF zzP%1|w=#cLQJ#(lWWcT2gnK*{wUZ8bKovm)iay|)%Pl_Wmd$7`L^+H;rjycFa{AJA zZD6fcqVUiM_WVy<{HZn8$ah4u>Bb|3GbwV}I;J^t%RRJA6A&}Z$q+2ltWpipRghIo zpW*#?ZB;2-zOQRO!>Ue^zL5L>ccgW$J#iK{bpME@sAF_G8;~1N+!EUGziIKds_F5i z!0LbZ^G<5lxz_$h>yEUEQ?dueesqbn2xK)e^|_TU_(RX@TuSia3&k0#7%~ixewNpt zhl{kY_1^*ZF;c(oQ~En*E$G991EC`u6Lc~qNm}0w$#%WJJ} zS)B|g?4hpMY^C0?!Cf-NGqoNRmWq{k8&3Kh7_3Y#2v&yo)y~ z?BB)BMia&NMDo~&`nAY@NSod&eCosU3ElCus~Ry4@Ruu`{7YApUwmtR6g;zCFu*h8 z5DyC+=??s?V9?vQ0zcr2cN2~&&9V}PmuU3C?A--cBP0_&W0}S%8lO5;_c@8$-mVg0 z$VMs@FU@2}2D|yVr9ak71Kr@E-g!-w($*5RQ4#_79!ntCVNp^B29K7H4tjBzUZDMm0b;tnudJm351g)dRg zO(i|rLR1MN8R-ziyzMi7pZpzxawZw4Kg2OG(0vzv2T9#hU|5>gH}!G!au7l9vp9$O zn(C{6H}9&`qEJi8?BpwZ_z#J5)ssnQhgw%3phBnX&vf)M#Ex8)mP+L@m23uGc~(^b zgfdjY1}8g4OS3jPxcf<7;y=6Xxa;2QRbmO`&b13A+oI#)yMhNzP z>i?zdB!%g4KmyN{TP=y!^>Nektt^j@D# zLC7GJXv0TI@aVYf2)D*-%dqV?uc2|Pvw*RGV}t?nG~%P)ar+dJ^GUF7)OJ~wBqb;i zZ2R+LV*^l~%`@m4Qv?t4R};$PQ~8$@{H@Z&&j%`W9r)m$2sG~P zR=b&1R~XKpFs5}h!FN9qoQFC;Chnqj=d+glh!xdFwaFyv{?^T3wQ4(|jO)USq_EJz zV)Oh^OYqfcynEcQP$#EIkey%5@5$1C9k1->?3_MtIb(K&F4po53=ZigT+_Yx-+HZ= zX(W=gdM&Kg%UxB^^u)&?ny24ufG}vMw6cxQpF_bx4yKYi#}hU)?YBO<3K=E++&Zf+vwO1Hpm?m7;0;7`rBGZF4FqY7_4I-UqMMq z>d7l*cx0(p@+ouVsEJQbOv}_g1YY~u`TSd}=$&dFn?L`tSHJtpT1R;US9wiQ*%dE{l96LWXhPecYin6W3OuRN=rK*8Mlnm)E65o2 zS)fb#=VR5PiRcD!Bt$_6RWM8JJCEp<4&*9Sk#0hT#fPX$_aaVseo36W{g<7o3%mQ> zk>Kw4YS1G`m!hBR&GmlFNwt1~p2x$@&-V-n?x=`@s5Vyh^bXfh%FjSx=zX&{ZWRqu zTTe+r0e8Ap>Y+^gVPMwrUOfb@K zeB=13(%Sq>lr%Sr2{?y%1i4I{zB@SIYU79S275ek)+^nn9iaF7JFO>e|t9BH2mq1-x^1QZ~OgmD7K`6{uY? z8xnG{;hx{I<*mD*P374Lj#b`b3!|rMrI}Cg_?Jl$>k*tIx+ebL?g7I`FQaGA??^Hv zCO(n(Q-KmzBuq9g_8Wa|V;>cBP;2wr*2axMdIJ3}p46tf$!|T#Ryyy!WojbCsSD*q zu^t?$b>;_yj(|6H)plJQ=XDoxJd0arJ&~{v=gV+G-y;Z%tV`g3(K}hWm*)z#ZE{h< zZF0)Hbd7&d@&UpvIf24n(E91(#tb>^X0~HT*YlTiwD0AmpS90l=sx@GD*LULOM8lH z`y}g5$@*baSgxA(tEHJgeICah7c`9S&PexU^xe1LYpZ`iYaNI^Iq_O zd|MohNw5RHEv~Q<=)-5{->$@?XCF8Cw$edKuztQRbEYKNU%oBW?R%GjVI>K-?=8wd z`*_T^1?XPafhs*aFAggKKYDh)b|oG>JD&_IA-zgGf-@#{;v+*QsV~y0kE*=8HE>So znItd7Zca|lj>j!9(aeSTs>QWXrn`W$)Ho}%a*F=zDfgWfgSW55>nh{Wr0It zV#6E<|G_4_a?Q=o#T>6s2zL~;x36}uCPh(;!R@+VsWP%~pfYmQX5d5LKqik504Hx# z(w0a}krA-RocLFYnf-RolNOK~oj;>VH50e@hSp)U_8CRlO&(V~Rrt=5x%J zG^VCV+cX!@on)*3R!IKR-&5BQQXj-oKemqgRRa^Lma0_opu909&Fre2Qw3srqTlRO=LjO8QWfS+2{A-doYPE#v!SB#tZsVcJ{E4@K`v&HlH4a==ej!ak zV`>`1{-1K8W;UW=3o{8&O2`y^|=jB7LR#K`ndHvYER!Bj>ZOt^F|h> zBErf)qqUls*R6lq9ca*7W(IeEn31v$>R=>$+cjs|au}-Vw64|yzu{c-nmdHafUJ>4 zMEGcqG66pnp z|E-&ruJWnvMq)Cobtc0_)b*$I$1(X$;)bJxmwFA;r*-bGPh1REs_zRXI6t4|%WWwO zZq271sovXCZmF=>L7kLf{wu*WlwekLP+K}Efuv4tq2M?j6ru$4E~yiqdvuvwf~hLO zJkUX*^ni0BWa4zD1mmc+H&=4SPZA7GKMD?>IAzp9$y;^K!n-$m?MO)j(wX}W!usVN z7J&DOV@TlCT|TtTPu|cniG&o))1J50ofx&2uTnNjVj#A^hB>uJNK0hXUM$Q1 z0sDO4=@t{|vu&)wj{`--OkHI18O0&TC1?kbKIfeRQ`2mZC{mVz(tum8bOEmV__D*c zAn&tWC(3s@)Wet)Qwa&>gbXzcq9vOX+F@MUjNg0_$ySldtRvygtDvpo$#CgEe6Zy?O}?o4PS`D_?==g3fR9=drrahbk)EGXRg4 zdJ)X;Su6)B-$kt9bv*01j~Ruyf?CVJhRjlvybOzO3Jm36`Zx{^s+a>)(ArOiagd4u z`3kjIP?!8rjkfZvRnCI1Rj>p!?#tq0gY}iI1sNy*I-0ANKFxv5CW(S=41$3A?m6$iT`4?7K4W-CN zkbDlAg|_+;65>*SE0IteMz$2A#h(*K%Ta|XwK9i?115Sr##SP#*MVxl69`d3D3%u8 zAN4M7FJJvl6(=5a_{C(LGA@=wqO-7%LN{n5hdXY=VqXGkbN%+~%%CnjEd(4K~+Yj!W&>y+oA2sUqC-Wq8xNsAV zSp1z51=@YzvY_Zp4m+0lV#mfVP4SPjrKI}dy+?dpsRBtsC!7DZm)H4w{Vk%Zn|!el zWcpNisJ)+0LTR`IkqrYp#XtM$%!Y2)UF%ZmJn_2ZEB06kxUbAN$gOUjV2ldLsG;`N=%xn?t#X6Z89gH zu-D^;@}yg339(D5H8($H4bqn*b`RvA?}r$bGNyRvy+99ZzM;(pc(kSX%`mNP?9xH9 z5BfP%I(04?izW*?+^2-mv!_JT9?JDCD4tIzuPglb^u6Ns$42%)x_#02B0`gW6*^rW zXCZZz%v@?2QdCBbTFddF%kSr`ZGLT@M-8#3n@Wka+&F}QvK^=x{v8Xh$FZlbF^!N~ z>}S)+zJFks{D6oA_UO-fUWc)Qfp8`EvNP1b2lT;B_C?m-Cs${P5u-FSS-ZK_x^IV+ z-e;7Z6?Np3&)L)1q+dQ;qwAuI>sUV(d^{TATCVbu?Dbqx>{AuiAsZu!^b!3E43xva zgT4Tj#62Uw#%R#KTltFX7#3ImRPZ#F;zyS58D>~KY%tp#NQD|2rJ1X}`-$u9sSta! zGGZAJ_Zw+p(a3rCj*aJ~n?lAe%0_rQr{GBdt=zZgkL0eY+rvr(r_A5}tj?$d|`M$DE!n)9*Nf5XF+c9c(DY7i9{;Bui zc2_Qe9~R$}^Qjeu^&f~(^K#_g7!`+nRol>oR&`>L;LE4k`~B_%eNRiutYP8PGX2RM+pF-y^K# z735)=mBs*Vujz{#I+*DD24)UY+wm_`;cZ^>&Sy|b^cf^PEawxl_E%f&ib%gabkv;EP>Uvl%Qcja)KrR__ zetwkwvW1;Z`lQ<=_@?J4E-S5Gns>4F)l&vPj zXfG&PB$I)mpkhdSN6?F}a+p0m`Ee%OgUq!YgTG%aif}I@g&yj~k+X6ph7;TB7q$eX zzBoF*{^8fHF|D}uIl6?5s1LES3Q$ju%)Ad|Qm)7)2B~mAVoLPkttt;q*~xKk^nC@t zFxNR)#S9{-Gxx*4TGt6+O*01FRiG>#`?^&fuLlg)!?s!!boh-zhf_*EF!$2Bz7W+3 zB$E%UR)(;~lht&+sy~0j(4&M)M>Y!y1Y{|90qJHTrWuvX#cO^DCo;VD!yo zxh!VDs@uZwWHiglP(ovkqyB}~4UVkrov@DnG2Um( zc)oE+1G9@Q8xsdh9`~@}j&^Zm302&~jY>7Z{XS!bA$3H{b9ORehQ<5N-3ktGx1ZRl zv~VJ^pMr*Qvwe@P`Zun-at_jwIpiTGzCOGk8p@Hb&LLq}S^2_Ty#^3kO#bd(#dZQQ zdk}&Us{Jq3#Nxq_^Z~_?`p7@3>?3QEP0I$wi*@G&m$;l?^&W!~+H+m&+f>+xWd~kS zzWGw3W7AwhK*hV`A%Hm%kuint=xpeE?i`3-Y}lzu3#>e|u+2?cJxs;UQh_ zcH7|b*aQ)KpWMl@kgmSG^3B=Td)Oy#rb&aQI{nfLHv+CbeSbJP^JF=qx z*v|CqN&bR)azAlvC`-NTg|7#}j`3?(y&QUmDsH`kyK?CH=Ie&)3VJJRQ!`7(FA;Au zmc+?_zU?lGjmV)`ycXtjc?~ba^h?mx%k!nS=M2|nPyB(DKeGtaG^6>kegqy5TLV6y zUlS3YvWUE$ywl}5fu+qbS*A*z*4FX6J-vDWP*(1;kW+_b`*wSBSO5=~`8>m>z zU?xR{1^MpNo{JwKLc|J++WUU<8x96P^}XH65Dv0aJ?!3P!d1(%g+_7{CTW7_ya+!@Nfk#X>mN@z@EC z^&-*t5pG4?BqfeC(=bm}UqVWM7l(~sFQdFodhpK88M}cSBG2#h@HFz$gCFH3z5nXK z|IEDRn_i|`aaWOUJk6t;*ZV)iJE|ursxXAZA<^KUu{P+O7jHYbA2WOhhWZ^sBjm|I zUfdcegMWGw5|CEAub}W&s)W=+v&cc=X2ro~LGopa2`+N_x@OmydhfmFB67e_FG+LC zpiQONdJNRBg+6;VUW9xy{GR-53e9KnuJ)&;^enBVL$V4EsE4HHyhp`{(Gs516^HA z{D;s5?Y1AmS01B_Zm%Hr^xR%uE04Pogz`TQ?gGcv*_(xRBaT5p^S9i3` zqb6KT>ik*X(51&cv#Y6J5c=DilJw|KyKEC~BIl*9PpKbd?kp*F^8b!Vkusd1`2QPR z*^_4yf4*88q}@mIPh9lBW&QB|7EWspHjqW`YkJV`xCL9QA8oF{}K zP`BUgmbHM_`~Ati?6waltQaZV^q;I|M9>t&rc%!uYUv(zwPWP~l0+X*(jky0JF|<2 zNu=HJbrNv0c}M~WzCR=7tF{tI$U7wDg*5p567EUJwuerSe;|;&MlzH>JfE5gV-Xx& z-L5*AO|HkC42{kfOBg0Wf&3-DF(lcC2nY{KKzq6x~Jjc2?`tllJZN-K29z zr&-8gorSMkQJq4Y)VP5*Y2;`1&ld>&E9i_&{&1bpIJ0W?j|Z6C0qk^mc6M&uyR8b7 z_PWydFr|-*;AWnL^#71?(`RwCj^=+;GCiVp*+}a=7PPw;VB{kYz^uRW?Zk)QU|w23 zy=$X!X>xzR#kk@ko6Dps<@r-eROLsw3u3mFN`8M<)ZR<|DK7OvqH=O&v#@GzOyg{# zO*_hzTOz&E%|gojZ%q()gh!d@>BA7!R|3lSCpF)f`OkjP`u)jeb%FShW8s8ce+?5d z#dMyNYkw$$-S`oTdj}kxsLSC?$GguwH>GPm=P_wo3VOY*Z|E+GHWlUR*G1(%nnfU9Nx^!1bK($RBq;}2sdKgEyhxJciGAMN( zRi`vw2s>|wR=_%!q}zhNP0W$=f?&7&h1f%DF(EduFUg^F04$7=W8vpO-F1~pj}(9g zLIb^4NzD#oA6qpu`Ts#%YJ^M_ay+aWH@o`n6kROLRmRtQNNP zM)%ppvbmLVaVSo|+q#R}u#1-hU{|4D_hG|lFK1eIp9%b_)?41G!F~y@FZBSG2(x$9 zuGt`6P{HRLW+&Fl8)@V+< zZz3kJg=`~ z^T1>H{>*X^xj&;nD|>bA`u0uiO?K**+XNP@M9@7|mc3EEWvaMPT$n+^e$&Z8Bt~{7 zfUcc!L5iw=X--{z=GF;{Tv|y^0d;%pBvUVcG7JapMI=lCSo^WlJu2W<7)}X$WBJE3 zWVM}(^e{3MHHM)S>~z=hRO39z9Um@%OUl^?T*x)6^2WmHgVY*qJ?7DqfmG`yRLM5Q zLf6HKF#09BedQ}?Om=P?fj%ioc=yeeneT1@k;rJ7dsY zyd$iYZ!hr@>e8oza=Av%D53KdMxPInMb1pp31f>c_hK{f3`+K_hM2~Vc>O#x&?J&-4`8)hNy76+5!s9yX zjtWOR+rm%IM}Ox4)-8$)?XV_-qyqfTxfQktXtLuy*V;kOM{^vdhj27dp*NjhH68Wh zd8vMI5%@Q!)k!>fpGOc(7t{8*^%THxpEm*w4fW{h@)gGBT^hpF=n&G{=LuvUm-iHS z8{M#ee%MDTIrVlfV64e08ADWV?|Jd!<6bz=xeODHV3jk)Xq|IUA% zh=_#AG~1F*9!f5M2`*|s{lsUp)5PeFsYegX_o`()ZEApsSbW!UfdYNNE`_+ zTZT@DB(M-9u=b%)^3Gq&rwor_v_AF zaHOvx>O|+el)JZwvzMusEtkRFM5CE}vd-RuPvGnB!{b%z>dn3c=iXd-K%@qG?c(*L zSLhJ=SWojF;y{hZ&brTX@gAOxAP_z;(Q`?Al5LOrN#C|;m*R87eSf)&NWNI?>l`NB zy{F)|w9IESA8&m*ScAHL(WuyVP34iwt$n%~Fz<<*5}1(~9*w!6@k^#T4V*#Vy7Q%a zHgEt5z2WZbY)4X^Y1$bB5M;b#0=H0gBYZZ2fK#vSwF}MO;)4#FcEj*M`dtjwMRFJK zb!p0h_gcG7;nsXT!5sfn2PSdE=wC@A?@-xAuIkl_X&yY;)J*(hQ)O6`C}mA^Y?meDK9K*Jb-~FfLxk+1x9hvI~G5i z87jHF*5#(;p?r_V?-$J}hejg2#$!^E_kZeO6T3P)q%|J)zr3a&I!`RTv(gyji447T zo@qMmH~-WW>**18>0^f~#ofZ1E;ruk2=kPA8cY)2ZR+m)p>55mNsRv-*)}lNMdYsW zK)aNNfi~FyM)?P_H1gWvfpohrUp_|$Qu&9_oZbP%>>uyG_96v>dq%HJ1v#R^3Us*v z2Tb@kp#UYUZ8^A!2`?U+aGhj{wZSe1YM;qsi?4y%+YPZ|*woN`aw11}H5q0~c*uhq zWsDu@O1KfEiq8xM$YANqs1Oh4pyfy882$}mz>f^c9z=n!4MkFbt+A|Km>WUlc<#`A z%B3sc1f|Loz}qel&=T+AS-PQAq>g3YFt{jQe>wPE^UQ4ix{5wFw_Be%hy`!d?GlC( z#?vl)(B@HK=D|Zq3SMdaLu~VMQ&>L8y-fGcbvVPqiNH>GH8uKpGq7(#`uWjj4Y1w0 z?)@uxc)j8*%|$FIx+h93sJTa5H0V9`$=7ryYsC#=YIhEwkD1@F9ZfPm7fY7{8v}Vy zS?-i?g3SCgdnW0?nkz27`OYed4LF(MZkY!wO_T&z!(Ej^tUMbrx95V<2WLo!3b0sq zVcj1%;Jo)pa~x@cucfOt#EbU604z*?-gj5hABWO{_b7j#ZF+bZ9f3p$ZzAAtCs%To z7nY`jsy5+u=aZp6f%!*aMHu;o(I~Nn&lg`VpQzYb+F|I~F3HEx%PmOQvi7F|cLqdT z;gYF{?@Lp>VrOnVa$3s#NM4Kpi2xU3U4D=!cm!m`>6<06&`LfBiHaElcVal*%lYBRhHw(Le5f8kkl2L&XW)?Zor z*bmFz{@M=xw@KuL8u;RkyFrJ%!!`pIp6mD?OZ1OO7j3_FLN7&&i0eWc9Hom9%p$6d z@G^AJYAlGYQ)k6FdTljWySU>?&>mq)x+@!NH*`|Z%BCz+mCM%M5)5DE#8Rku)?>cp zl*}mFu5gG3we(;N@D5nvcTS$}r^0h&o!{jYq^U?{uh1^Q=Cmzqj)(figV&#}!CEVA zpF_aX*U`Qn`3JF`k5}rinsJ}(h26fmGe>yPjXyDd|Mld|uJ{$2?j1GKbRI>2WvnNt zIw=KhAND}VIJ^{F%|;CCp?1e?D7%74D+zAq!XYlJ!3=HYi0;_j-a_do$|P=VcoCTK z{CDXxPc;zJCuMvjUf{v9zVbkmBpgA~TgewESVx==8BHkCA5+mf=R+~2oAfu;v{wei zRAM~iuy_B=mixJcmgO-bs-I{tmCRUP4<^sMm_ONO(j*o1Op6lSB7j2dzH;-~pW6lr zPl0qw$k9DQ?`6M9KjJH$v^o9_9o%L`z9;`l15o)cQTo)HWcZlr%HQ-Ou1CP>l`Z|K z(8>1;NVkGmCk7BCKh(IJOZIJhYR1Cb$bTVC3^Y8v5ndPXv8Dc=?r3SLrS)%4 z|D6_+crLuXZG12{(fXXM?fToEixy31{RF&@v%H9djAa`ii^WC6YrF1ho^z(5fEcBE z<7c_5)p{c`y1xe6;RoBR6;DsX2U&fDfYn#Q6(g<%*;SQaI3=qk^QaT6+~Lk?#rh>X zf2as5rnNJurh5?coV*0xvjEoL`mysJp{h}Y4#b>v6!+?!=Ua}x+S^>ue!;^d^>hHu z#%9Z}qt~YQZR(^TrZ%=J(uOukRWGI_5s$dboD#TE`*mEx9|v(2cWL7S|fTAkSOR-5@EYgWp1n zcHgRKUpSf;N^tbR9@82vK~=jiZU^oO2Do`cG;N%B*;?>Yjiw(dZn~T~R5lt<)F{`I*+3eU)%gf&G_b8FgDu zQf;T8Ilnbo>2AHnd>^Np1sz~;k(rL%yGP)fa?fTCvH0oTPE!!PIOO$}zWY{cz@rP@ zWQc9k73N;vOS;o36~e!YYB1lkk$-e!@Qt6UD~-ZK{!ul@ifM#DDPI9WB0a^C77haT zW-}zJR$eMvKkX^o>p1)RVn#w50h5S-BsQMJUl z8ENS+7xQ|3qv`IDwpj?G1J+epm)Z{ztB-=|-c0#caQf%=6*&jhD)pBXncIfR*Kjy(_#Las|9*RkSYS3YP z^5`>-><_Uh19Y-~4Ik_E&w*~`vugJPd-@2piZ`jG2Pcy&Yi^P2CjYJxVD&8|-4^=B z$zI(gH=~>KRO5|PM>3&?3((0NHKWnarZ?xuDf>*uYhAzQG`JeTW7p~+I~jlII2^uZ z*0J$3m}W!zfk&j29L)O5(-@N>qx$bblGnB@J_MVp%%o1DKz+lh?{h`9)`aotH4j`Y zE9wd_lgxWY1lugjW0 zzOzI7!$-v89{i@i%X>}A~MKnxDc z6pa)mAxiyWMQUuIMyqI3j%2aKW@?PnggPU`YPfq zjq|U_!vx_Qf7|@P`E5U9%|2-69pqC`t2!3ita6Re-(i7GCI{`;^f$RdBQIRt+TR*Z{EG(w)+Mzt9&!Dw z!R?aiXW6sa863u_rxG(4kCIl1Dh?`l?ui7&jC7v&_odKD-|Ng2ucj4JC;WT%H;Wq) zo{7;h|0rKl>-Yuy?hXze*YQHjD1&06lM7PSA&zzL4tvF_fA$8NT@@Sf#wyEd;f^qA z>S2a=hR4LcNS^!sGFd!Afau5(w#dZGRdmlfh2flT0v|ghMR$8reeDX;u5Zm=31TUq%D18q{Vwtnm%}*6h?A{Y zV~u?-{X$wH`@vs17(3wK9mO`IJMGx=qs=KsNuQbhB(k8v{BK%{7_HG1v$cPnhotl8 zzBd(rP+k9dY!B)7{vLOKdy}@Q83B?P2`;6&0ye*Ef7_9?;`B~q0azXQRo&d!aM%5< z0W&M|Q`zbC1Dr!D#Kv}e(Zozx-`%6(Y=tbTxuLY~;hXEG&Og5Z=qxdIF61ks&?GLD zeE{n7Vx()l%Q3%ghr#@+Ewh_px!b5wD+XOoKGVYeOEsEGx(=m}n z`@SvYOLMr6!3AD=qQ?FdVCR7|R5xvTW0 zlZthkSX}nj_t#X+eFcBx%4XAB9zu-l1+rflCNDO+0>097!@;$K4V+4mCLN?}N|s#W z$8~eM$OzUo;(d{+B{#gBKO~S*P1F*S_gU@l?wI>bX?Mz5!?ayW0AtiueeW&!hvD2! zosM`3Q%vfMdbh7$zw3=tV_z0tY(?~J`nkU8Tu$wZP;dHsK%0m%V@sd?6kDmwnmWEQ zX|h*958MYWyj#PuI&XA+R@mNsCcZDPx%Z{UyoOyo(|E4yi*1IrfAGiDLn&sZKmV0dI(x=ua zM?GeGIPwfGaE3>bf-{1UGW#wQb)`*5R-#(i3IVMcXmuQeJ< z?+#o|*ifk%!hqTgzLbpDedSoP~>-^*U132EWWw-cvD)5&>! z!LdjA%%pI9bzs}&3l(Y zMG22qcVd8-1cOx+Gd#(^>Bkeulc0hgzk4vA11~!8Cp>vy!abPG!CDMl2WWpj4y_8G zcX^fp^&5BTZW9jzN1){TauYxxM#c1GOe53T%~gj+uX!Do1Xk#a1zFp@J?;Z8o9ZUU zfEx$BF}zQMxDJ%A7R*N;zi&%KuAHRd^J9RDO(+-pq2pk$ z7@v<24Fc6Fh#5_&+lc@;iAqhCeHiq61AoMyL}?+lT>Onbb1@aUxlvy3y+(k<>8BL* zEN7n7+X$MRg$6R8c`ck25_Kl>pX5yLCG9P)T>a+0i{{k{DlQ^L^|&}k5OK|wFFlnz z-wx63c`5_EUMDV+2gz5gB00EA?TG39<(K*F5#Z-JYZsq;=mB4b0Imb7KGM@5wga@k zO+)c~{)%!-@1jrH{aiipYxrc|i;q9c=>5E-F7Pk+J)!13moI2fl?4|F&~Uawc5+8>!jX^t1vJoIxW>yhOAKnh+8pl+SqqgvHj4KOYyx_$yv8EagsOysNQOyU?< zRd|otyz&x0;tLYx>u;|jSy1j)e|T5%Ea24ep2FbUp~KDgaY!ai(=03;DalT>rGZh`xJT2SQA2T{M%D&(N@j--jPC^OhMpld)e}^d23_fXZ*g3l)a4_fy z(0c8sdk7*f$65P4_+bC76y}%O%zo&K=U9kG>r#=fpU?GbTx9a6<&yGtroC5fs;&RT$4qM-VL)QO zYIhN5kRZoDEx`)u3QZoo%;b3-gtR@gWhH|*D)PzbNHResx6IFI?p7_Fs*Dd=h*$!GEw5Mi;$S&M*+s(_%Cs3M8 zfmqm=G3h8GC>EAG=JAOrr%6g1n~(SlHaNJNsAfQcS0ZnPeA`4oR_^H{Uf zgabdu<}Z1)#m{pimZsuVZ(iP8UFgi!C2YCd2Y%o>C~HRXLv(^<&el#b3Z$5$rexSc zEkF8{=Y$_|Is9T3!wP+tb1|SFov+tUs@6c9Y6r4{v+$#RNWmpcb0YMGO1?sqgIwQP zi#~kq%ANu3^N2kKh#WiY4CEydq3U$0=&^qYuxxS96G`H_+a&_qFo~s(yE6ln4Qz1SI+>!hiMs z0P5~#F@5=i`c;A^*y^h!!F%EtL4NhGTpYj8BOrA7nmNN~1AU4RRC+6}Njp;+&`#Gp z_Jx<^>L7_|W*0EX1pj~z%GdMj%0Cm@^~Re-&RuR^=F0`&{a5Ct#EL!v9tZrv#dzqo zr{YCcd0DH)K$o&>@@?-hZzQ(_wjL8K?r?|_=p%Slr2i3?>{`YC1;Nj5dBO6rKAPYk zO8?4O^_itNPLlB*eWyQY6_H3JKLUqC-++hVF>i~u+Lb5H$h-ZhfajiV2_v{reKG)w z4Z`YEHC>@WH5TANLo(!hazVE+*V{$k!>i#ec5b8zhELtzH|j@>#^$EYB`Xbt%)A@)Kc&^t5G-5XR)Xo=+m*rO3>Mp)d8{g z5IkiLoc_xG(jVfUAl3+MeJ!dU{0O8p-K{6ddOao-+%d_;J*p3Hc<{qiy`<1r-X9&j z6NAHb`o-XUCaT$%ipO&imoYvty}O7lnJ@(~NRJu)-u?CGWR~6#h7F%52+U|B3y|Z_ zot)px2ISpEtYy+i?I)0K4&|k5>sdoNE9&EePBzpA$C#kRe zg@3@s#w~2s(CrLmA9}cl?7lS9w`JLG35o}rO?1$@i@r?!s_B*Jo65Xm?Wa!90}TAX z_FM(O4I_Ac0{*n9sa0Ytt7#^?RT3bv7eg1-o;xUxbD_;B$vAIiY1zQcc?3ma(-nu2 z*Eegp)=HqHA8v~-zZzT5Mx^n|h}G`=7qe+9|0*6 zTKqij%JmQgR~JZ~Wq2H;*SgPGQou?6~qL~1LmE!6vKN>)X3C_(12_tZnfh_2gJ-hywsXf(q ziRSzIY($2GC#!8Xn3qk#F@VqcNaxZXvNpC;Yen~Fr%f%;Rs`f-z3RQ$lv49J)$GNC z+{xWWsKl;BRIXM(;%{uOa*R*=9m6A}I1&CWd>(hbDR+^-HJTGwa{Rj{p>eN>r zY`lUL4Vt*^4k^YSrjj?UF}49GtEq)~sMFU1?nnL|f{ka0L{i9+GU~Q>UK9M}j$dcH zcFyI(6O{?32B7(P&3fVdi6-1&99oJEys2C*b`BR0`ad;YX;f238?Le^>;#b_Ac!o2 z&=w_VFsUFSE(B0S6pcuQT7d{Ci&-uP0ut2Vp-L%B6tvWe0$K@_B_@Eer6eFCQ36>M z0|F)(mXPJlH`;E5xr5pU=ydt=g9k zBf$86UL%c6k6Xjk)sk?Vd;WO@g*srSD`r@}eCGrX3q|5TMn5kS8NrndIfC>#ECX1# z>%(&Dqk54fi3wI(buMkDf&0VtztrpNf-wL~X~P5)AQ7*fGuAD<)MU}f9UNESwe#m$ z8kic+;wQVw7M@qpJLZMjU&eV%8u`Qf3|$|0LjB%ecMgVo49yk<_JoNS+GCO8@$I|9|E22&P z+1JmPR?C8|>PhWYa~|G86hecsVU;d+vw&i#ze-yS;rV4 zVne>G%O4%&dWS?vysTweukK9q4=*Bp)zznf>{;9qmDnQVR2w^;6*a6sI*fZb9q*$~ zwbzZ)zyskJ@g*kt^=yXDFdTDec+6XkDpdwc{$mE2=k-1k%~&wOuccZt&r>Rly0Lox zW&Wmn|MVy0wP{H60Fb04s42IHxNy#gLhGxJ9Vv0C87%lygY zzHv91{LB7H%iblH=6g-K$1bK7_fP8O417Que5qJ(?7Vs_RAfpn8^T+l9^?u^zsuZt zzQ4SX&>?YG$(dLPh%{;b;lGM~8prb={G4*it7OQF~0qg7?D?Ycr|hiK$aK%-kTgouJ=@gGxTG|MkiI{Bfy zn8|kN?D2#>H3RcgG%yD?c5%}n#7zmfSvU4AShJY2L9_EkE5;Pul()hULutE}E`1#} zkb8u~L`!gFKwO?hCKhy{;8#p+p>ODWpH?%-c~zkwV~3R^0Nr?nzynn zg5ykw5WP{GZw7Wf60p8hmsjgkq=Z)y2(XxALY)05(*=G=B=>COO{JCNr(hh3UXKCd7Ls$x!8LqDza<$Z95V{t$8&diF zy+MB37#fH{ZEtzX6fcQK)O$vr+RWy<`pzXM3>>4jWc$zELud{Z>DCHZ#|7N1rq&3} z9%ZZjs*30eRT4Zn-7kNumSS1v6048ll_`6A2e~Bm6Z715B%EZkxUxl!yowuGdW`>( z>vuh-z`-!rM%cs1zbd|-_m#DLHmW3_G%<4l_z4I3s)_h}2FrxJKbujfaQ~rZAa?Ps zu3jBF*U*B;Fv)F0$WToDFyjrsmRAW!Jxr28fzXvY`MG4_uX_0y<_`v3*8*nf{O&^8 z`ucE&wc38D(Vp~l2zi${`DohJUOhU5X`W`;sjm;MIEvrk12_J`FVdrY)V%-|4PTAB zH|<-RO=v$T_`86C^vyYA(2&!Tb}sGZ^B;E|FTT7jRB=mOX^J`)6qHjj#0+J{wvL>S zhTcA5(k+}2qpY>0+hW%O`KCF6?q~{JXEo%C_Wm^^yOqArD3hfRCy=kSFpM-zQ;p;L zv5CzpOL4O)s^PQ@F2Qcn0;@*_j#j7!lZg4#orQvX?3ixnR512J=j4$@0XxXGwZE_d zY%0K{n&)uOQ(GXNU2l16=}_m8^QuMZlgVODyC|9tGHXv7@i{$acHd1*vAhF6HIkxg zdDqn04%!{zitS>iDXI-U>D%rcAL7>TY^8Mz{2Dhd>UNWk(ty15BhqKeqxG16(qe!S z-aIO~(QFc?n~$ZdztF@+`$}BzJ2wHh0{5s4PWiR#ZoG%Fo#u0?Vf8cRr9>cq-!GOW zF*|>-yi{2+U%Xej08{D9?tWgZX%Ot#uNV~HqM^5PPEs!LqdDD)f&?0o6*G+4xJVts z+@GE;=f80U2;1J}vyUxm2FoJlbjDqr|D0f1X57zXltxTKr{8>->qy{-n=AY5$sUmWstXS3aQ=cyiVkBKGmlDFc=5GL9rqRdIW{+L` zK*19a24T68Mee+EKJ03>NSfnWJYTT$XGU$L99S7>rwhUaZ`b5}L7*xkG1Xc>>zpT< z>BWn#vK;-IWc_-VF&h~v?xUIJeG=>VLblC}ZXwWCwJn@K!zWvABw5f6GB5T5K+$_g z3Z_(kJkTC}P?A6aEHueROvy*@5S+w_f-yuN9(LHG-YfOA5WUDtejt_?BF#V_6_CY7 zUO~dattuFsWrDXM!c{-933o_o_8|tuN8-ZgV`e?uRmSXy0;U<-nAjjjQSi3Jc*P(k zb!FrC#0`1H;);2+GsU66%8qE9cUzqOoC_ltku2R+i3%dS>^a;pz=YugaX9aa&nY@6 z0mcEg+KUPpn{SLYBfI1Qh2l0G9-)OP?o;%ZU6G0u#S}%fcG6F^Utv$tPu|8#KeF7L z2v2q^JevyNc;>;s1|iu=6O3ak-uV8VaL2xZ2e_9A^`&DbZU+>F2E_)vqYO)7V2Lcp3+cNA5yfFr6zcDw{t2TiRS3p;@aN~$$SHimzeU(8dxZ_zxAk(Zv51M_p z`v?QK=NV<{dt8u)7NHnxrSSnO+EqP80UWM0TN8a$KP3TvbIt!bD!esB>}(J_3Xr)^ z7wtllPe{C=rKpC~Iti=83RM_;kdIIg4)N_n;C4iN3f~YKv4;3SJSZM8!kP4hD%QU` z`%JtlK7UqSfG?jh=!yBwN|jP&DRvwW?>Hn%qBvZk+Y4W0duCREnZP}LA~oKd_<&RC zOQdq*eW6VkE_O1+nfAm$G~+=^vmt-|x~ZH=yk};eiN6Q9=9yD=sZ#qPHi^qSfb_|^ z4M*j4Jv%CBU3oZ*KsgmTqv*eW8}bvEH=b&nit4?p)P6dc$H(Vxw&1JljrhYvmO`CSc(~hF?(u_ShmC_ z@xvB|w2s2Zd=t#K(GnF46kM66fyl=7q0==mG~BKPGHtrf%hFaGA*>ukgqX~BySV4M z9<*KuL)&Wiv2%?XzIkpcXdL{MM;<({O8k)RYX}&x&~H(&J2wSm0W;7)uU1TWPj1_- zs1mbmh~G?(;SnKb^a#f686LR2%}BH1-?+u_P}b`h94#_nHXQ%D^5=@bMuOIq zRV<8b0}l7;R)nV;cPrc#d;8HC`Du+du@?a0s6h&{P?>Gf#^-MrkRP^;z)+AC8pvc0 zX$%Igg+z{mPFP+vR~z!z%4CQ%%$vb<1|vc>V}xgStTr2BnD{Hsl zTv2UM6)1MH*Hj}k+7J#F5d3Z3HF)D;=~G=&-&^oll2>tN-VKOOyGqlo?I+)bZUdl% zJqx)b!k$&|&h7yB3~+!`xB_FJ7%Fcx#P^a74j5tYiqdSm%+x6odN+WT$ui;XA<;y- zjHq>W@qBwwKXg*DRy&b!;jPt;vP*Nl|0a#hV8a@CDX^14Y3odTBvsd;XRZkPW)8;$ThVfqJEiLZo(3Nf8YWS>=)Y>}i!nXk>5 zTURU^w;`9>lC$Ej}x2FB`W#p=&Z13I<^Tz#VEPKhg z=`RY+4i3gqBI~b@7%$qWW$xizv;zWSwfG5Sbdz=BZM|}vKGkU5ylPN|8ItJZXnK2% zk%aYU`p?SXkqx;%Aa=)h(ZYcCfA#h>{nirWbz?EB{EL7}Uv3LJnCkxqWBhx8s8tf& z*fhJJYJT@b0|a0!>pSA7_0c8z=Dy#tcN*?&Gi5a@aK*}cTk@OX-Ks~e-)Pe}NLY7^ zfavWUhr~MIv6k#f4jAd|%}1`tofZiBcfX$|U+Z`;%DKp0?lqtKK^u_+KUSg`UUl|p zzXq%e)$(nGAn3+Es}nss!QJ*P_rvjAFW(1MH-7F>%Do`a^d;;zDSO*##giaZFrQ{5 w|NQsj?8745g=B@sH&;C-$*q`w<4~b{V`3BW-!&Wj4iKJ;>8$^%VC`4`13Rvm&j0`b delta 53659 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 EKbdos&j0`b diff --git a/files/board/arpl/p3/addons/e1000/broadwellnk-4.4.180.tgz b/files/board/arpl/p3/addons/e1000/broadwellnk-4.4.180.tgz index 0c229c3b9727ae860c45764a867febfb9ea99f40..2a7cae92c99a6bbd13161479b098282e11f6a76b 100644 GIT binary patch delta 54681 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 delta 54633 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�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 OR?)Gn!Z}yw&iOxx;h+ux diff --git a/files/board/arpl/p3/addons/e1000/bromolow-3.10.108.tgz b/files/board/arpl/p3/addons/e1000/bromolow-3.10.108.tgz index c52cc4b97e722ee1c925ee62e452d29eb0fd50f9..eeeb714988b2bdf905bdb9c9f7d57f75f10f8f8a 100644 GIT binary patch delta 68746 zcmV(%K;plsp#-a;1dyW+&Ym^fRqS$cMXn-O@l27hI)AHp1}7F>FNHEcf8_pO?H8-X zd})j8>3ng%n7{t5X%MfOKd*qIUX2z13#nI62tX0(<`> z8-GX_b&y!_qh#_*k{k&h;W&#WIKqh>r{2Myd3=WBsW(psqT%3SI2cYjV6QtyI^;xP z2MDvM6UcF(*pmdY0gz{CNt#j1PGM3hr=7YSI2wpQkxV8>pO>ka)(IwBKudjHuF%j9 zbFs5lrMvM(3o{oCcbP-O5=|(B^eFmHe1FtV4U=s+qqVPu$1Htk9{ea1qsrvI_mfE_ zTP%RbET*1AZ$u(($hz@PW53=g;>xxu1voASS>dP7yvO-gHq^b}Q^5tpf4dfC-$5;(6-U@kkZwanC=81(~@A4vRUL4WbJ z*POUEi>+BUPD#gFIR;VS%y8hCCD1NmY(rEU76Wsar@WyZwvZ;n=>hc8SGq4gZv;Z2 z*{wGg!Hlc7jXUypbA9@D;^nZQsuYp>-B(-5SyM?kIzc9%SBho|Tll1&R9vli@ zblk~t&*abF4VknxU)F|lp2>r6sf{ys^&eyV<{!TS2>(LfhsR+|=y@5R`K6O!|7qB1 z-TG4SA_qi<+y{F4pGA4Wi?x52n!LX!t|sw}r5tRr2;2Se6ug*(RYNdPEPuh&X;$ZGagLeT^`-D#^3-Ve_$_6mhu5W?+r?RnhL2D_7F+xv7zqby2oFpA~? zxux!AC9;1v3;-#y(fHliHO|jeo+s2GpRdp>iC+Q41XKJ8%#s@f80rV z8I&5^Tv19-2{Q2v#SH|u7r}ljh{azpuU(0>D>oSWfvIaU#&c}xF@FYCbsQf|esU$8 z0H6nsM<>yF=Dc4RDbB^~PB;9`^v{-2a-YlZxK+T1K3szE#`W#|rgpJG0l^TCd6XYn;f z8>^1uQIhK#Kr(%3E`KPdkwzZ^B0Q9I2;s*u222X9x#YN_>-dQHAH*3$gs$%fYg|(e zV*3gjM<$KISJ#k+1erRcro^;{geqfdR%+|kehefm^4~E=UOgmXdjP4n`$e3X*cwn9J>Y#mQ1E}(oN@>i- z@rriPRtZf1XzisdSc93P z`+p=%;iTA*D2##|rUAkYO+%J(l-%DeFO@5Okv9=YmR88* zUCfyYES@88a(|dTRw48nLmLB%@_ru_xyf07?0mL%cB{63B}`>StZz|GC-y4A)7);v zj*x|Wkb0QzaWD`jANk1VCr){U)-!|0Z|k5Z9&ihLUPUDiV8>%7n16m!*f7ieorA1kQ{5Cr! zh2UG~NoaN}qL7ao(@!*{^}9CkT=K#whSgo2X3-*iQo@lg%{kZjkJ5ixQx+^(3l#`>si0! zbtAGcN7LtL@%S2xNAg~x(GGRT0!C4D z{3ScN96XIL@_H&Ld>KKp=}~h2zZHBW?jxU^IDaLyp35-;Pk5b*NQIW))b9Xq_^$%2 z)4#oWRDK7}e3)v=@VV1})%sEK>UBKtQiTjxK!tkI%yeI57fM%1r!UfidV+d=`4

*Cc0;2bVg%MBTn*~@cPit} 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 H09XP5FP&g~ diff --git a/files/board/arpl/p3/addons/9p/broadwell-4.4.180.tgz b/files/board/arpl/p3/addons/9p/broadwell-4.4.180.tgz index e4bb3f8497d522a11b6f4a6b15e6b58b4155c054..9f52292c3be3a74f9a44f8154609ee5d6b37dd13 100644 GIT binary patch delta 17523 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 Orau8G`7zG`FaiJ|XIVr5 delta 17496 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 diff --git a/files/board/arpl/p3/addons/9p/broadwellnk-4.4.180.tgz b/files/board/arpl/p3/addons/9p/broadwellnk-4.4.180.tgz index 3b77588308dd8485a3e04e5de355ef8f9fe6d86c..94e985297bfea4f3035801b07b27b3dac9253261 100644 GIT binary patch literal 37735 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 literal 37737 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 diff --git a/files/board/arpl/p3/addons/9p/bromolow-3.10.108.tgz b/files/board/arpl/p3/addons/9p/bromolow-3.10.108.tgz index 24d94b1252b0da465beebbcc6b7f84d7ce4b230e..cbd09208cc7e1aa4e4eca2a9c83cdac581f95af4 100644 GIT binary patch delta 29102 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 delta 29137 zcmV)BK*PU`lmd^G0)HQi2mk;800003>{<_S6xVs*lMZQvne5fb_BkfujMufW3EY7I zDaf&wJBfG0%Dz}A(8`K&h0Y?#ph|n7M*NX-cSUd3XKN;I?WUfoTf4QVbseWoB}56F z5Ym}RNWg7vCd5Xzv3=(=AZ&~&|J3h$Z})Cbf3PzX+-90%bbq_I@4fGR-|zeXmiY^W zYyNS=XX)a_c=aq@?6zLbkKid;xOnLj&*DXHkKp#WJtZE&wfNezCJ3Q6?V(neO9(#n zC+jy|W!`6v|Bim z*9Tp7t~qjtXMfuq*WIo;t?TBv>X*5+rpAraU9QH4rcJIner_P^H$LooWYfA(bE7M` zsnr!|erThs%yoZb+on)!L!+yv>7iDfQWI)v+0?4Jipv5ELAP_~03Er*e{W6oeZFn3 zISV+6wgqJ^8ymIx8#Y~a{K3uZTebC@t~w0|VJM*7uYXk6Y?~fjKmC6j)8D1f`~|I> zHfh&33H)a9ALe;Ho<;88$Nw+lW9Z*>r)#puZ?6A^OWeQL{}=KZr++gl|5o>yB>yv= z8_9p+k|pEyU*cZs`9GHb5vDJKpD*~cqf)KPv)MAgZNfJN+a&Ycf1Q0=VSL{y+#%TE zt_c3};eT(%y|u!ZesKR^tyA;E&o}6gDR11dy644`?^@~95PFd$5_p@$FQQLl7y4Cp zN#yfiUXf5|CmXWW4F-errP+}w*3Tq5&R!0G4nl7sv`)+}?5TwXmva~Jow_dKB{VaA zw=~;_k8d#^Y4eEQ0hCU$>Ct%T1pIcfACb8Bx_?2N(4%$rK;LsLeKMHC-_(0a>E<5m zKDu{SG_IYrk{=<_W7DHv`F==m4Sn2i_99 z-hUngyO=vb!uzMwSLO~&edkEb{t07s;JpGecbL#ol5c5#X!&ik z{#I5i-&SgsRiMZ4hYq5za1;GO#|xr%BMBdH)YU5wDD}#Blm|`ve)_3G|C1hi`f*2dGb;VHM+9s~BL*`&HT^`nua4KDxFDB%)2utSD0SPl0P)m1m$xAb$#5 z#N}B%L7r8$guceSQ2$Z4%P@4n;~uFudX*`X@C!z0em+9luqkdpNLq!lOx<2f* zA-TV?Y%N6t5SOH0?;@YnTelFtYJWWNwbBiL3#8t*ufv18;6dA+@a4S&z8Y?auMIMd z$TNVNk3KDLwJ{2}A%$WeeL`+$1CPoYUV*?|r1*zYZ^t}%*uo!n%%?w*9dHlxooxP3 zuo3Tz@s146&kF7GZo1 zj0gC50LE9baas1!RdO*56Bu5@hbwebqYua~7%Bx<^u%GnJ((ktt^??5IWbT`NA$#N zYy9+5{|zi2enRMffmb4MB=&#|f$R9kmimvq+Up9OA*mqp{{6|1y=~8 zEg@Q^#-_OZy34iUSOi}=mfgx~VJJHJ_ z;{SK|auD7N!Y>Emy&$}s&{hz>1?IJa@GT&GD+piVROx$AYt739#&1J{Kq4#&exTAT zJa60skB$0dyXZN%8-du1wH+@*a`R&)O&|n*4Euh179zi&9zr9Hx~0T(sk6x>zLjYBCfrFts{*4xq7Dbhp{*%phG^pyeyw zORA$MwP`_xRtwe96PjHCHB~~jR7e_561qX09RFI(5&GSDTeCZWQXS5i6CEUp_*n!5 zin#9)eVg0hrTx#apiOukeA;Qa#o9wicxS-uv5X#x-ha6U3TnM#7NK{+q+)zXy|R(v zs!K_%1~fB_BouipyJ5cLbh4ZG2mkyg=@;^hJBn*^=yn<@GdY^(2ZU~&2f z%;xF)Y=4PAQ+fDxaNz1#vs~&g8zQ=s#F`FE(MB7ew%_Po&86%;z)W5O$|@?O|MAfqUsO z+=?+&={afE#mCHgz7mTzr)Xfwe>rk~IZ1fXz`E-q@*g?~#wIA?AsYz~iJuD=rEF-c zUZ*7ZEc}doO>+0$=^*zxS(bI;RU_XNKz)!DaLSk`6=aqGsjVK0K z$SDwke6mZ5pzVPT5t0~0mosQ9^nlcj_pvp$AWWPt^`(95Ph!`i44k}4DSHXURrD%* zb;C)lnx)6?#NwrIaAj=Xscd_*f8cF#?tgxIc z`Zly-De|~kn7|V!yTQ0K-LF?Vf|L{}iAv@)B)>j@-P-8b*p@13Z!?tU&}u5uzO(cL zZYEOiW|6g@P>#C@1TAMqup#YsK-}SvZ6{E>`y1X!_5kJ(rHYx$X95+`+Z-zWlz-Pr z)A(xbXk#YC+`!m-Ht*&*JddmT*YP*T!a2Y$3LyH!Ly-L6!f<}hkg5`sNa*c!4^X}@ zR?fQ}W!X#I#O(6c2E&f`y5O=8jWU~hRs^KTY>?mcYTEACR|FDv2dBCs04dYKqhfe} zDe1bvtofLt|2Yz#2G%2#B^AnkZGV4`=q0i#S;`N>@51N_J_P@cF>Nb*(Be`zATT^g z@5Vs87Xx*cpGr}RoM-l&Fw=&mJOSj3Ao$E+i^>M1ssXj(yg#S`KEP_k69?x5C#<1|%o+@O>d&shlEPJM zu+7;LY?ehI+Hx$xj2^pMe+aq$~enwfPd}lDXz5sbx))}jvRH91AZBq+1dUc_; zWQCHgLRDFW^3fJ&wf^|k1%H!2k6_^5!EyPU(09!mlEf+!yZ1Lr(Fjzw_Uq6eBKtC1*UfqE1IqYoaE6u zlau zDyS^qgoW_5)EdKYg7B{AhtJ!k#|IHNlSreg&*RiU0@2@f^5{M6q0AlzdkDC$h`_qJ zV0Acuip%kfyM^I!+(RWz->VPP)N}gHiiF*!u zc&r8KdDK?*4NfFEkcUf7NYP)iF54&1EC)irf*<7@q{yo_Gs;&=eUB8tf=B?O#N^># ziXf~ikBrq&-`wff3(fjv2gLn^qmqvJXo{T!nX$hRL;rDPA%F4-gekL5$)qAMk$%j; zw)4<}#3J&T1jHLo+>KYiRP}2X+_L%JilCmKdKb72FDullz-fXEn(Dmqec&}b^VSW(9M?(GiGIiy!$fU14j z?EeNCKY!9b7&G^37I>4i;{uCuW=VI*Y@C#Exop?uPN@3OkV$MC8gg>vEUVW)xPO;OJ2&RDddc*SZv34Ho4o^+kHcQk zmhjpIpe99@*^I{6v{HTq0s6M{SnLGD;Bh3j74nCr{32);r!cyf3ffy39$m(;xjp11 zDI(`#BXtfv^gQ@UZ64m_hh9c{E|U-*azwh3b6)X47u%2L2Os}~6j=l-`oAPt$MA9a zq<@d2PXZBz*_g5?Pso;hzV0?LRciJhY)h{rROL?`c$S@jV7wz{H*7fN2#GaX(w$~ZFKKrSe#j)RM7}*k%dfULR z+MO7WT<9y#%qlKf!w8EZ|HfDVz4eP$9A85mG5>+3T()Ug357SANs zLGX>r%V$_rf}%r;yuwQQ8b=EE16(m`#aSb&VQ@5+9*ws@0OZ0c`exF^RR{C{*< zir}$u<|K?OOo}{-an@`tnk@MWm=#j1*@I4|AI~|AX_qb==UX6js?;)HVKtnx2ftIV z!9W({)RQ0sSjGqJ$ZWYgb2OuOn1Q*&cm}{>7f(dHqF(uPr33_g71ApA`d{7OY1o~j(Rl+tlU#h;CyZ$-tYks}JuWyHd zJq)&a!F;s@Pg%fb3Qm26OOJ8LH1^b+hJ1NrY-}esIUill%uDUXaeB^R-oVaqBd)CU zzp|q#R`eN-k#!nwEtNud3~|Bg?k2Mn4M>tSNOXwqks5la!VyT2lim-9CmaLG1obGn*J8prrk$FGiasD zYU#tLkj#knm7wwd)!ckWX7lNM^VD{HHP>V6ECf2!UYw%Ke}eEXpFo#?C!Qi@`v(H; zB7uHir5~AUBSyD>BK1ec+kd}t{o$neMZ-8s4*_yM8fV2h9mO)`5FY2yBR)D$Hih}J z5o7N87)3eY=k>!D9|sW<0xx;+C0;IubSN|*-Mf-*oT1Pv7bZ>v#P^b2C&$L1LCe7~ zgO4U7K);*CTDvRE&72`W;d<%75_q1>m7lQ2r5s zgWD;+?1}qmNd}EpX3p;?Js;&%6GXuSY&;EeW-37EM57uC%|k>CqvCb*R+-fsEgv%D z#3P~%B4%&VhHxC20*?OAWiN<%j=iM2I39j_1kk9a2Wn7eLrT_9n5NS4@0WI!v zd^?o<#+hupI0W)+aerqL4Sj1ed1YdF4*nmFN7KBf0y#4>;yI!zC-aM6Od)5ls^8Al zenPv=uiNEd51Jn+{6Mb4?J^4ZPCD9C1I&YbXytlU*2ni&87AF4YD%-^dZGsmK8KSh zz(%0%8^rYxSzvv3?LuR%dy2I$7;8~3zW*qTPe-yORD;CH(|?nbXf#OlVA;64N#FC#Wk&u7@x5X>%ubHEDZ$e+vs%ZkDLZ2Zd3Ukmf=04&SAo+)s8%7W7! zs-7Rr>ECnlg5hdR^QpCnSLXDdKx3ln3!t@fLw0Nw*<3;S- zKJx@KR=_5K|Ka3WpqnhSOq$RJsQi;N6(<3hlUo%&e=piO1?PED%#-~i(AnFV3abl1 zLw=Wf{&d`4CJx_{WBCtX`mla}HUFx38OZ5$n}hSl3XH?u=|D2M=9o?<8<8pgf*-0` zRY)%3#2ok!nlsx&jy#ISr~yz?&S#aAl?9D5Y`{`xxw!O6%yOc`Uf9W;qh2fI=n9gf z)raX=lNA;iE2RMKLi}~AfN^OyKa69a3;qhoX}jGdYXZvc0Mk-c-eT$+>QNm>^N(~3 zlUNoZOacqn$8^Dfux*w~rl(?xhI1uQs$>CN!4lA>_qMlPB%n}yl%%E170_kh=Mr;8 zeu=rU=~|=2{NbTIy5{v}{0h0*RRF!O8`Pz1LzBf8ISX7J)u5);mJwy%VUr0LC4YXV z?!IiCK1loCUSQwrza74_PxAeXW$_HV)11_C|2G)+?xek+5L+e|6$bVWH2-(Fql=H2 zEQK&KHsplDTA1SmcIXi7&_T>jWrqe<$2yzJOq}k{17I=qnofe5zZF!Fzn;BtJU=`{ zeC1SKGcC-@_ zdj@jo1T9(BW6WRIX#00OxRFgI%;(z~j=-O)Ar- zWj@tFKqb?e$3%$uO-j?lTnT!Nl%V;aqLOwf;y{yY^kWirWueARCN3{qL>FY$=`Y}>J&%4#|O>q@C zD4zu5hnfy>KUVfRJqvm5D}U&N6b@NaC_2sC+5avWpA5mO{cHeuAreQt8_0hVi?}CY zl#W8xk%w^Qzu&9ld$ZJXzZDZUg6<%2!l2Z;McwEx_(uJ#*6k+> zt3DIC09{lLbQnqd0QZfDGJimfaCoAkA+`2kU|)x!Hgs3|dEG59OCeT>ep`!MZ#xybX-0{()sj803>&h4FJMvNr}gu>&YvS+;5i?5nCVk36joj$WH^{l43-492`H7 z3K}2VuhID5nrXagAE)sv_HY{S%%$(o)L0Eqmow!Hgm^x9h@Ign;lQO~vZ7uSFZ+`P zqf9;rkzSo{e_Scn*0|rmwWJobn03F#$$U(!(!{hD8JX6f_kW_L$D?}lfm!Js$JpzM zy=33*&*euS0zSjlpW_@I$ok&Jp=_|7>|YAle^Tu6Z^NfT*23ko0$ws^1T3Yv^0PX>D}?Xc z$0r7u;;??!8(=44XP2vPKM{`o1Wde}jru|ZcR-?B`^4_Cu|yQ}0OZDfln)@M+A&u^ zmS*>c*k6GQHKX%J=R#{e?_p%iDK~b@i5U(x+!(`j3EchLr-+sK%sY&*j9dI39US55 zcsxNMj(?GM0({fOv>(56uYKhRf3_4O?ZlqPq}an8Eh5{X=@QdMz6%@4%z>fSzD=)Q zH7>$$&H~t6APb=1lm#$$jw1aLw*x4>NQ(7Rx=AhQMAJMSD~E>wUeYrdN(HhD*=k+U zOiA@NGWb_qiDv!rpf+dDrg6A-H1;mMQ918kyxTB1x$SF@K z$~>O~M?DtCZu(%RYY|xtBO=N>rF0Qly+bg;V;$kjS4wQ#G9BbcqPiG+UmlFd!5sfU;CRcfFYgBXybCqSFf=1~D@)lV^%;jvM5KU`jQae38GAqXG3k$zkTtf*26+M{U~ zM*TO!MAe;A%R4w>z+DOL*}X8P-C}uMl7BHZG1@F!r1&cq(uw?FN{Pjm6Y@`h(L(u5 z>8JJ>O))SwmfdZz#E7eh-IaL+oD|=HgGXTU)6$a_Y9`cE7EP<+R@qxSVCS$z;10fV zeqGj?`N0@%p7R^Z24+B~L2tJ*8`j;6lufA(m|ce}PTAd);ltYvI8t|mdc3zi=zkqc z&mW@gWWLAa^{|jiJWy3yG{LrDO?_Qm!UibZhvr6nFj*1oryF%4r#j^#ctbDiwIHz?YX?$(_;e! z+pN#9K9EW}5ad>g&$R)1Z8)@`Ys zyjX_L`&ESFfHJ!b@EnY{2NH6c=QszeyQG#A7D_k;gl`3eclcKhBEqGo$sWf9rRbw@ z_G4R#xg83SOBqoPjKC-T3n)`Z!Q}1_Nx_dal!M*o5C;oR9;#Yx5jtdqH#}HH{YEzi zOE3GO=Eyh?m)P920*i1itAE3E!~YcP769;%P?e85n zzdd@qRE{P~J-cm>eCcOf{mFK_wIkq7`Pran(7GGG7Y6_^tliUL9fWU=fVTtsd3IYn z;G5Ifv+Dv=PdoICj+QR_H(9BqvTt6=vF@SC$-^$|DQHYe9(Gb=V)C$q8vJhwcIbmf zF?PVl1nhtfJN>m`hkpTR6k!K!Sg`{%CVD%pTUaugoZ@+pZS(FkWT#l)()sw@HrHVTQIG+8=q&Z@vOWBh^B^z@y(lZC9~!Vf zXOk=;Mt^yVr%%VeEGi*Db>zs$EU=&@VyD8$g!qwtkAFrtmBG`rtlZm&kd8k$DvUw8 z|3Rw-MC-LsE#QT~=Ms-O7BQQ6sNd^A;pD`x9IB2zpBK!T>+R3Y-Jn;ns2P=s6%LS$ z++N(S#bU8M^91YU=}`(_sUZ3-jEHI0=8FdBki|d?v_2m!I|^EUx8;h z0)Hjs49K2NZ4jzw*ek0$Wa*G~0dx`r>GBswNjyI07xlOwilPf?T@hREZjOPdkARF_ z8%@ugQ6;rpJb{Bov2W6k3B{d)V6s+7(PyCp>yT{?PB`g6j7rgZyjq3vl5aWj27RIo z97dB5Rf+$yBL~roGxEm&)$t!F9ydN(A%Ba+1ld2R{!r21J-$EE{A%7k^E0)+7j%^9 z5cK~D)}Qb@P++p2=->_TNNpOLVud_@gJRcO+(q+&{-#pDFrdhG6n_|CnEQsMR(TNA@r6qLUGQ;_QeO`r^|De=jyD+^ zK5T#zSzm<>uo~(suu%bxa%_}CqYN8mNWcZ zPg3j==s71*dUNimNt+7d?U}z?bI#+MqI~ex{3l1Gb&jwiI|7Q&4#IpX43%9%ekt*O zW#0G6sZn1M5O1o`B`}w%V0J;nMP5ukVt z;)xMVH^>|vQSA^F{&*=y-hcD???qn;{@)d8;Qv4R^%NXSeDL5fXGQTBVHF5?pCt;+ z&nmSvYxV!y+G6)%5frh*RVRnl^+}T#nc$9!nGtSb<;FU6bR94xXupL;p7IaquTk`Ow8ZFEmaw=e2K&9vMZc&W#hH-e{{uJ7 z&LozOfx5unaIdjwd{O8Hua*?j3;0NIQl*x)CHzeAOJtB{`F}&y3a~5{&IrJh^aV{T zi(}QK!pm0utk`hBfyOHy86#eSMz%p;FwDEy@wMhHGR)g_r_{A_cXf&2apJZe;&XidF!4I8 zL*sR8#LrdX@qhddo3NE-K&!X$0`KGzo4T?PE0JPQI-s!(NxDEy8m6=#fF$GZalOPG)SU<(ET=+J%1TJ;tjt?-8F1#;E4w zq)dg)0rx`aw?G%A_|rY`(>+v`3ypfJ(S-)p>H45S2e}FwRoJM2Mg_$|ph1a_Wze8R zM;A0Mr+-5Z4W99+rT<8=F)Ak+Fv3U$&hO8OxRQaM_G7V{ASR$I*26U5$v{ssoM?Pk zYU!LXj;<<@(D7*waS0%*G`1qFyhGiH&O*|LnLulHoz{w_m~R5n+Dwb|G{!Z6LuRir z${W4`e>7#4Hdy@CDJkJPi)2?EYTTkvEhi7y5r5X!qy~>jXGpotOfSVokgPhJLoct} z3h)DEl1Vr6wuciTM>yf<8_B$6HR!Jf_*U4?b6!#R{*iq=T*GWA|9O?-J4Y~{XLtLr z1GM|AOZ-x8iJz5_kwDd^eXTAkw6BZk9E3@ZZIe@U-Hn`j@^=>gFPymD z6@O+aaST=_@g;r|LMHt|=F}z%^w;FxFh2FHcU2 z?E-suE28ZyjbG0M)CA=Ed-xIiX_k6+o<8oL_@sgt_E*AWdUK@F4&kZY27kd;SrQ& zjoY;=Jh;6!E;-YQiB=*Z(@>WL%#&a$2?33hYAQDgy{tTdtm3gtwUeqUC^KgVo2Mrr zwRL#A)m`)hpE`J&_<(w!pv=xFSArJKsYL6D&eA>UR_M#_1wDC_y8I?-ev<_&COs(g zT=DHqzocNU@?aT83x9&we96k}a=c;YUh>$)w@2?j9=~a^=gv?EG$+o2=qBiDf&N>eC11;RKO)d;#w=YY9JV7xRxfpcP!0eNDZ;!cUQ3Ctae)+@Mw8hkopX z!WUYHfqp4oPdPj*fI0j#u!FiXyoW6@uaku=D1ZOY-qQxhbzOC3DT#1CD+?Bsn;iKN2aDoTqp#tE+XI)R^UI_wDLMyYH>vhd!K-I;=d-&W?y@G7y-78HP{@ zWCk+z&^R$9O5LE+foT)?;R&J5Feyki5Yse?i({K}&VBd2`|jEy36z$Z-LbXz+|P5* zJ%9JybI!Z(Yz-I;@4D@P|1&VsT|oJVU~#_yi#!b9--ixC;+zhiNx{OyV4Xwtt$TXD zJ~TISTA!Ob?GF#t+s|AD=U?q&{ZKf}kxP6Oy?&^ZciVxZr10*4t&c`Yk%AwM0zK+; zGpB=Rb&R|wT=e*Ow7ymEfsrbwQ**`B{(q2OXX2c`8~Vl*XPL}{yNCzjyHk%MXdyqL zuDA{#qV&9)n)}t$!Munv9mnC81{P)Ven!Xd4;j5y$#-qXELINVTXYqF~(61=bYc@PeG=~vbp6|4*Bd8@nsfIb14cnzYpHT6y02CHTJ0r7u=?G$ zGp`knA^*gaj{QIJD94hc4ALFjh`uM#(Y$aqTG$J_+VHDTqxa^J5AlvNIe)m|5X8$O za-5jnSj&E?WA@98+aK)|8C{9T;@^d_SiZ}TW;GT|YweW(4UEFkMoNV^Q=X}wZ}HRB z^UH#b81tYH`ffY(`-NlTeN}uSYVw<(2jrOa_=FXm$JnTVt=g9?`MwwLtZmH_`iDrV zJM)#q^YiMVd4^B)=DxfFkAKk)$T-KIrPJ!Fw@w`cC1I|O9#w-ye6_y*MSX7ehQr}J zzoWN&L$A5VK#l~*}o z_xJ#9s`E!)>6pbZ&}R?lK66pe9q+~YJvKl$>7O_YHP?S%Z#}Nl+keAvbj)J+eboon ztXkGF`;Ux=2-3(W_Dx2YN_hmiRQ-?fVlrrPQI@{&Fx^!qE}e$8+{+)PLWPx7f!}@y zBkE7E9_#}iw(Qa0q&PZn`!_|`G>^P9ZTVxZgzNU>h-;0~9kVy`nP_j;tC$UY=6b#Q zQm5YY6cJp5E#qnJe1D&P8tZmEH=*(UGy6P~VjmOzood;Zc&+ECzGsusRju1co5mIvf%X;hM_i%pn4{%=e_X$4q zcjIZB14Vv{vws(Hl@Ch87yAfZJYgb6qG-j7gYVMn_FmvKdn>vxK+5i!SEKz+9lSs? z+9&r=JT-< z5FRj*bciCfpaj{5(4H&+p4wTrVU{fKOfpW97+~Abf?Lt_`CeJ2$8=9F5RAifCO!+u$f- zy>$IW?%&)V67H8dYu^)3a-gmaY%jLC%SrWL8o&n6RIZYa3D`h5MgQA%R$XkZo@<%< zdkSO?W#{`=>tLrdJnu zz$T2P8m(S04io&gL}hN#|L%n(|0m*e>lB9UaD0-{wVbd1fUtO(sMAWnH8a->R`B>) zP_@qTrKBGrp$hl{eSi3deRZqIUZ|dBqQ;vToPUb~r=55md#21PvY9?t#T&>_8&#Z3 zp$wwUSH)i|NHoxRgLS+({OY94eo)}(|McQ(|ADLTw}aL~_RN!Qz&8Z;wa`z-d~1Kg zzKnm^0^RjsG2ltP_*d`p_@Z)dl~HX z#i0vv0Gz=UQ+x33bP>_{)CYO3qRx^MhgF`8FQBSdJCEDl(yJr|^B= zleDX5Vttj{oBX~Qy|{&!y`vdd&rNh3#b1ojtMe_-@pz~0g<59Ka?}>D>!{+ZM}K&# zAy2_lb##2?+9#Jil7gZm_}-Ho`hMgpyg%GWy4q0fb^e#v_HWAPlmLyB&VdaoAOn|=^OC?ic)@i^JjNjvUZ)K^!M@4g23)Lzu<{U3~mrYwhK?^e@q6Ui2$pTYsC!>h)CXd$rWE_m;Nt{MvlSGpW{#1<1R&^b41y z7gPAc;g8YaI~A8%KAcLpn_geaG&a3byA!YBQhoL^4K7z3JAe0LWBdgks0H83BLT4v zsd?Svm)_z^#6J;z!}nZ&4u5xH4G;e(%mCQ`UkyjVNViA+B5nZY^ut?GRDX9o`iI0T z^KE+1w}LY#mI=P(oP?3PIUC~Jdia9q%7_Ulb{*#gx~}%(d^=XZQRN$nMQW#l2SV;x z5pu^Wg*$4erq}ZL+W)e6{yYz&9{&CiCMlj5!3`_1^!_VYJALN(2U!fLR~PZ!B)j+u z>8^R{_Z&Vzec71QbMJtKbAKznd-vj-*Xb`VUbp_7Y;V2u&@I(}Z$Tw-!`tn&Fz5A_ z3)20M?UJ!yJ=L!FoC&^1RzBg65gqDV@MitXVaRGw+}dib7>h+lCi#;1snPrJwSkZ} zeJ60>Fmhq|IO=@Z*RKR=s`~5-s@Njc5iBTv@#Eg$ru#%8wCFp54u8pKS2kAt!v1jl z%M2`Pit)3-gGp2o145?Z7e^vgS5n2c4~^=o|9ezFP8FAZ7*w?@Q#HBP#DC3C^V9tN z=suO6Y_4RPwhv!{J@KL2U#-B`C~&(1|C9n>r@+@M@C^#wp};E?_+twEaRvTq1zxGZ zKcm1utH7U7;8hCzNq+^tQGq|Dz@Jv&pI2Z_fj^_b>lAps0(UF$W(B@Qfz{tk-lD*_ zD)24^zEgp91s+o1yA*i00;d#sj{@fv*i_(x0v8o{T!AeGzE6SG9a2)@vI5%*to}rB zMS%}0u&cnH0;|6%94PRl0#7OMv;xm4@F4}hUx6P`;0G1>A%6w_q5@wEKkOrZn(`<4 zY097ErzwAupQijtewy+p`Dx0Zjkn=^HfY&w z#kIgF_GZdsPJhYDt)nu3rebc;?$<_ovYFIiI=wf&L0cUItF;Hi(zINfR!cLZnZC@f z(XcHCq_%QtS}o0__Kpk=i(xS>j~bVym9k8#KRwu&85Au!B)65z(+%aB(R=r#hK6?w zq&XyGEtjVo$}@X*5APiaTT@zUE0v{{vP^n#xNna@n|}jROSv?ymO}Nu0SRdVCfdt2 z(v3ATcMie|WW+*;kkmt>Jl#;98BMewZD^k;PdAij?m_tTeJL@C2$uR#>ZC7Ihqp`c zfRv;5mEeWT)+1sL45cN~0;EtjDo;0*15@8S+#j~4wA5BAODko-^ZmOc_V3@F;C@k( zPL|-RNq@~kD7l7GyKIy zAh(lB(`so(7RRbImW8n@i+82=jfx>DE%RYqmVZ{tGSZe*cB8Zrl|3klZbfoSf?JW> zi7nf(TN4}gvU^n8pvvx)wx&F<^iVV$rRAB$Woe}>)1TTGZ4ye$SjJ^(r3?_;v-j>; zz9W#pGcHZ5rF3*kr>JsBGiQ#b!|yxCDH0i;?W>dv%s+d<+F)0OF!$;CT4hE*@ zOX^2c?-*(79ZkKXsdqH>j;7wx)H|Ab$CdPskLdmQ$^TS(vYngXA=LX1En9jjwtwkw z(}rx%H%cYTE^0j^-JPACnio_mj_WT^*4t;793y|FYV3W@vE@qnmE6Tt@BjO?3WaXF zoWRa&1uKu!v>jig_YKT^NVk^FVZDAQDCO;&e68p@Q$!cTb&Z+j>UvQ<>Zo8r$AZ|t zYuFyH2TaIYo>;dD+nKVpitG4J&VMOslcwugj?JsFmRrJluo&xr)Z4U-JA4 zz;QWZY14B8H)m?TS%zAMYn5i8o-t`yC1b1!LCZU3 z!-}q9WgJH<8}^J=GAGTFhZTe)Km+EV5cjJ_X%A|!2VKKQGQmIFu{ZL)3FDdml;cil zdDp2_0QH<>+h$JG1lBhFu%CiIWw@r6GXgJJ&lrPQM|g>K(@Z;GaV)^!@-(9a8$UlI zTABGP)FXb1>foo}urbqvT7Q~R@PW#HV@q#5@bf@$s6Pd}ANnwm^PneK7GE2KIhv*o z>s>Md7w9Q(xiEy|TBe{AmT9n9qGTq**_^gKKf11l$QWALERO*yKy+Zkih~3JHV-O{ zIX0{-paP|Ugq9mO?4rpFHOtlrJ?zJv25$7MNmB!I5@ykWBrjdZp?_7U5^u%>wm|~r z9M=shf;jMr@dZ|azabGp0y;TEsz-Q*A`VCx*g4J)uq_Umt^;gj7yWU@f}Vn>x#JE@ z*$DjcZP1&B3FzGlo8T6OQF+%?A1eS;ng4BVY2SdH4hjV;M`F~eU|mluzzWdD-dPB@ zrnJw({ak<@1N8Qh|9>mmmFpS#Jg_f_WY{U_JL7_+u^x;E`>(9g*@TjUZw*zRHP#Pz zK-7ZEg0&o>577>%f~djPHQ^Z9dFM!qArT#SXBr5&$FglJH?Hk)%RJRvGVIc(qBD7$ zs5S@^L%SQ;O@|JEF^jFj`tQpYLqtRoN`n*#u_CX0oUl^J10{%Nq;zZl$=5X znL@=+L0xEu0`(*rVX{VUT*?>&rm(Yl%L})VRCM`FP=6#`XQlxS%%~WyXJ*HNIHpYV z+!z9&tpNKt69K8QmX{@&gxCjaMybIv<*?&sE!!e&EI6f{QWo}HZbE`9fm{lUD?t+G zqP4&r1%AA&xcG^5!8ODA&ES^I7Wo`(7jlXwF`R3bOams*GxB3oq@=P*2Xwk$WcUDq zWwXInhJWq^NNnzA_!t9HU0WE61QytyRkTqF7&qMgo4XHyxH!1+wyA^6yFJhHY>M?% zP^AvPHU%P)VjCFOwjr7KL^=o)EDx>6*yrG{m(LgR@7V2tq30FZ=b#Xi(EBLMA7p(j zkBK43K1d&Ggf)07Y!83NpaK+(L5e5nuZR74w|@ulm0@Xi5cz`$bPDvO<{OnAzoE@VJB z|EWMq3#UFGQ_7Fr@Kln3WaoQaD$OHQks~C+GT#bx5B62-7H2N@t>ZNpumT zM1QHs=PXf%1Cb}0N@PGdh^atIlkb-@MI!X;^1LXSiP<6M26DObxr$UKB4gY{H`d=RiVgY5)g+z^XK%bSy+YT!6ityQwn_6#*fc88JYsDV7rxmE@65eA7+u+bDid`EDS9vPx})3#u4*jV&`2Y)If zV%$h09*FR8g>^UPYf9naes_CUvNay9^>VGQh6i&j+m9h+Q2q#C3C6NmHGzp!GfykK!Un4RQUPGmlSp;*|GtCLGf{pw} zGDRf2MzUqeaJ|EICScHt1qV@V4u1oQK%o@Iu#09@Y*gn_D?}0-c!~jO2{}}`;>8@s z@7x5CC9=79ff*FBsa39kdJd#5U3olIUED9SW+{@alVmAnDugVP3dvTfRF6h*W)ZtJYPW#*Uu4m?c4|3a?q`NBBslHV&0JWdvGH3O3E4%hwt!zju&Y?=3b&ju*$&_17~$l z>Xn4qYT1AFs2<*nZ7z#&8Ytb5etxSjVx&kb*DMtfQIOw}rDL*Ke)XZD?5fu<9dpf9 zE0U9#L$^*b?1HzquHyZ#HK~D1etN~xDYOUik|&k@Qj;Z?-Hb%ON;fK9aG2cbbzG)( zNcETE36pU1KaN}Gk3{Tdo#{(Ng~{JMBq{c#<@DK;&AxlshgaR6tf^+IpLh{I>!4G7 z_1yfPZx+Cf^NsuG@;mMJcPjQjhhN%uMF!yGep)DV^#5%HT@?%|`=rP^d-E?>h{Lrg ze#tM@Bpcq^R3z>TGVSw=INGGsnpCzDyzBKH?ZcNRl~)e`>p$;CnQBt=NCSJi^e(e?Y2xIazMN zC{){s>Tz6__U-q(jmim7!L{tSMgM=JE}0KZ0~NOFaqrANbMw@sK^=r=v#B#y@40WvZ*^LCr0y zmBy67vjNpUxL;DM%J!_x0(fJbmA`8B52ZE0E}`URdw#==*K?gmLAxS<5I=mVL0nmd zfxUOEosT8NJ#Mb>8}U`Si&Fx z{q^ptG^*ZhGeg?Wr$xo?XF`%>dgt1-!z~VUF>{U7;ormf&t!UC`@{I}p%az|!!4}3 zm`2CcF?kf!kuK&VnO=W?GiyD_j+{(Li6O+<3@Mr12Q)bvspAfHF?Ce3;ZXDcWO|Jf zV4JUGdb?DziGGm67Dyr6E+kx2y~S5`>jBy~sBUTx)iqjtU&Oc#G-^YJW=|c-qA=S(2zOf=;l}rUgmLOM8U+e}(hK=Kx^?Ly z_t-QE9Ay}NK~`;qR&n}&0ag6GH-Zi13dt`B^nZi{e{aArJ}Us%oCwBq0C{;-(o5~h zrz>DpziR3xVx=1@0{pweVsj%=+q}2F&QCw$-_Nej9`Mi0FTSAcab?Wh_aE8phfWvn z-MSon?A>?1bJRF4i|_6cckIg4;Mldc+Qv7p{?t~TsA$$6Q#jz#^XZ?ob?}x6|GoLx zyGPltwf?z3{xc^sW}}PZC)eMo7V@xZP(@>9Y|@2$*(Gmxfy$RUU?tM|?)pkv+@qMv zH+5Q+%lZH0oe7>&g%^_(|Iv6F@SWSdcW1Vqg+iKgOV6S8cLQl*!>R{w6loXycpJO) zKFq28r&9yrZS1o$-;1x$UP`(7bMoce+1oyD`|fz3uYQL+bTjDXO5GUG!=i_VZ06LS zIi}FxykMVQ66Dfqkg0B;I|JXcJsGpr&VpWXSBw!xF# z4V#Z&=+P1k&W2b<$XMHQomh*iFFvQ|rB~$VzNw!XJS2 zJV!za}5>nc@ zQWGE1qAS?yumQbW&5O zp7l}{3Aq!L16D}3I4BFDU~bNyHon1Iykb>=+R5C~eq^a^sieS%r2KAw^8;4a2>fp1?mwxcoyw(WI-bS30SnYhT+)U)1}I?(P64KiIA9OL@0tJKeFei3N^NgFsB-i>UO(E*zm+5MmTBIFUIS@l%Qag)*v)U_RJBYkJ zn{EdDm=YFd$hsFq4-+K?<60lBbIb|?zMQ@z5HH8>OE|f(bQY$}4H+)*i=on5E9uHy zfaid)XOvXZm6&VRi^~6$t`VM>f9&uWH}`p6hkId0EX%7T9bh5%2@ZC)LdrO%4j6?E z;2gLA6t0A&mJtyvc*?RVN1Wldp5f;ZUhyt;6W)7zfDaoYv=&Vz6SNnB!z|M$9j*(w z(_BE2$a5TK|95}CK=UbVMkk@E0l-*%9|H_osa^Vr?Fl-IYp-w2@oKVJX$+b{B|>L% z32btJLcxB5elbYD!TXG9I*UkW6?;oK!0GJV^hvI5B`x-Vaq%B`dFb8*i^Y~U?!m?2 zRH4f-R?DiF=2IyzEvTskKQch=;n1%ezwNUc))Bkg0=DI0J`15OkU%2KQ`GAm*ZO94 z7Rz-f?VdhTC&6=pzE_a>8MHr(G+<$$2oINo_}M>hzTWA6-Dg`hChd7k3+&3LKT5SE zFt0Yg);|4M;(60wYl5=+XvMfeGym@Qh`8t9r0!6gy{ubpl4U|bpVkJ-%H9c@oyL<+iRLlCJWbAiKs9KQDA zwcgEN5yO3`q9gx}x$fdFRxC$deWpWAu7!$@Y`m|5gPFU>8+G4>BK|49dOf%a5*y&QLp)WNOpKH28G`2*QJH3Nz>ugn%@tZ_1e zueyp}1kh*VHJBycn+e>y&1aYc$a^3)JKlmM{yIrzuP|b^v!b2&A#Yg%+rY-zZg}sX zaTUEGz7w=!LhAQ*THQiFPXq9R%HD z)k%j^4ouyey{C#l_JU*HZF;^tM-SZ@Fi8MH|G`XYHW#yszI7^}B{^}uha-fzv=uk| z1=V5pla3-*F&GMSUY9f3)1txhnYHPp`v~^Hfm_BOM$U93+!b+Um6fyH~Y3S5#)XMuEq_31Ay8A2*XMqW1b@g)B?x|Yet-T9~j%rh1 z3wH0G#+MOxbU5j+m}&r-jc!1Uo(j^q=Y#T2mKw$KC@J}-@@jmo)g#1Y6rNR zd3-kE2jv$pL6({Di)J$%YB>OYLZ9UB{bB@E)BUo9TV(;KF5nd<)UEl$kIvXUKKMX@ zxkD$Eh5MdO!j&8q+l83joXJoX7|SBhL?yFso;jYXrZWJ0%t&}PINp-Y`oK!Ut928D zS)?IG+&345Rp_QDv#xv7oN;Ov9Ytwm*WuZmW5X11FF1bOy;RLvgNHP?jyZOtY0xsXL>-bDjO3rJz+qSk zKa8anfEOs)=^V>!zRpKiHLM5!V^2qHH?`M3yLvT$RjnyKhqyra!DvxMXQZW@#G7v_ z?pWtJs|xBWN%nAji{~fD3IKS{vN)j8;=fvJ2ku@Be*IbH6k3pndUBsX6W7iBB_G+@ zTzx654JXK`q*ug7X_!b6h8O&UI6Ak}mGJ{FQ2~Ps7AE`?vf!t*(8{p2MRR#}D^NK! zIl`J)+q~8&PVRVd;*{))RBxZGNu|9Ytt%5=`w7LI3cKw4-0ws&@H=T^`GH&f)i?46 zN##~Au1VzKRSWN%B{h&s$_9H+ecE!Uvfo!N-Jz5dNxxNeghBK>Vqu>r+ePh6jOQaFt5sDqz+N7eRhvX>d2n8@HBV zJA6@Gt#F{~1&MvhY#wtg-C-B~TB+0nE4^154%-6@0sX!RM)5!B zuk700f@{B@R0&=M=U=N)9BbmLOY@F92%h&!h9S21B^)|Lyc%{rVdFs1EvuT6UnBoo zJU-H%in^*~vFC2a{&*1uiIH2ng0JBOf2rT6#c<6oJqH{F*{@1gGHzRr#+?La!lz^U zvU<+Gyx^QYt(pO}t_%;q8L4tHQkT9qVpR80&%a8eGXnMdZj5-iDUbSVYGw+a^EKkf zwi&elk%Cy0FHM-zmLI&`x2=1J>%Ua*Rcw4nj6AW{Z2=JD9#f2|0S@6~t%^@8emYuR z4}Q67TxXkELmRiM=6(umYk!rhEdS`etxwzOrS7Y4B}M<_0Z-@mfOio&WR2jc%QF|Y zs~CSU8F$sc^euQy+q-orf8)&ei137>n*|Fi%-f%338j`_ zx_SXq=5fku?m}baPwUhr?WilvU3(7-%*=B&YQ_FB-mn{A5hnYh+}`Zzl5*6}lkfQG8eLthH$&hgc~Kkwun@WV`=u()HJNVu*YKaH9F32D3BZR_&fWcKwRxYMHTo2H5=2zTPpt=J`Hi?X;*T0A9SiVs;=WWK z8*zJ-AJ$xRCoLv#W7}K5)fZN}BX#%;6rE)+@l~YUdjP~mBQ zRq!!*<*c=o8#_s$KirY=ebw74$y7nA@kLFOM_0ey`^K(+dvc$iF}i)>VEuQQyWA&t z*i-Mqy;KagUOL1ay$VEQ4;m~V+bhU;L+g1ZGA!-d-!=Vq_DJT~xQ1~4s=Y^TYEF#m zzAIXRGxb+?s(d`RZ7HP5vDFT1auqB7>Egc|4cab^#*f!tyIn>`F3z2a&1W3{c)4?8 z?9G_0TdrmejZ-W=rV*^9`c&@zGa{wa)_dyqheuW;d1nrlcGN%N0+xl;@$9gr6d&fv z?g3vU|a*vM^82%R25p5VCTt6W8q$mv-Zi z?LR9E>9o#wmwn#wPV5f3yy;~eysrex?F{RW!a4Ux{b}6u40Kd?m7ihZzC2P;YBYF# z)7hM8m@V+B`0n;!^LF6kHIu+8m(!#7gFf^f;eM!5SQpwl6EwVArUHFlo8#)(TcYBA zsFYXPWy_@#QI-Rj+vWQEk3A;HO-x?>m1aR-M#<7*OzijkY4!e~l;WKlm$*!ju;RMO z#;z(*y8(oUsr-}P^3f7JS18Mu>?nTU{Tlja2D zN#Z~ijguZ{n+-Jg3}>7mS`RQq{basZRS;ow{R26 zFo3vvSG(l$>oQI&*S4%TtROQihQB23+{_O6EV$j!?ETIt?jg{Oky}seqpr)#uFFSz z)%USQL82#d04WP?H{j}??afSYiT$p}yjicg=3pB3UC$!X$2vyQY(Cc@t(7ucJTpY8 zM{i+GCYk!T%xxIp(`}mLl5#|?LmsFBe|9y`sAzi%b_^oL;tw+Rhl!%#3~Ey7@Hp7s zBb-#_QSCp)?`NDM`->vC#49kSp~%Raa7S`h+0{;6@Il52SsYv6)a%mEv5P1JkzRg-sM&mz6(s0gNDu#>ei%QR&}%g8xm}&!TC_I3q#Dvp`Zg`@IZcnq0AS0- z@=+f}>=Ds{9A&%KjmzrT3NtI;_cgtIH)(Zj(?uUzrm96|q7S;`T-TBb-_E(&H1M;= z(Vn@hLd?;g4=Hn?4p7#+ibMMN4_*Z<{2#A3tw}As^|Yb{xaVxHO;rfiBa(a)-e0P4 z-GUVpI!i_yf5avN;>1=_PCDMztYq^O-9CK~*=p^MF% z#vip#hb_^8-&a8nf9S0+>SKx~b<13tvcenjnp?6Li@eA`J6Tq{Iq_#njY&SA4jp9l zbbYDJN!FxNT*%Kuc@H!+?LqN{x45Wvvx1sc42>2lkv#|Mk`<45lCQ!6$#_FXGSeFo z!`G?4Rz|16{j!$zaEI38ltS4L21(~WsX-J&&v`6?rN+?8b<)0xN zB>KcA$a1zyvL#e`7$*jI&39Fgz6}652OyWi_l4aFB@8XVEjrcyT$gUT5Vk?Po+aen zfGw2(TdndD^2wTg7}^63LqOb^d1QIJka=xG%+zykJAiSMioMfxDR|jaXPK2-;+Iuo zm{r2-%zk7lG>pQMO%*}O8BwTZk36SOAG9bA%+r zBCg(-lz$53I3;RQBR(|Hr*iPhw?NhAM-pgx=Dx7U>GGYh$adU*fkQQFQ#9VIn$rty z{@EiBjRDIk>5ZeB9ip+1(_0@T&^orvY~k8ee*)AeCwl`p2UM-Sy0Dg`Y6w1hHcnNr zb_&#Av@e~XE0)LZYRf?p0)+)u3=y(4m4t$MnQKFjrXd6P?N#no|wUzH_c#XH#ymh`?H9XJE}nNT3DO4Y(~(_nj`Y2Qf-f#e7k90W2<`=xQi2 zFF8QhKJCBBBW+a|0JyCX*8xallaz&vg|rzL2zpB-;GPPPb((|7Ys+*%5$Y?ih7=(n z8Os6|ZUdmJX!hKAUT!-&oR5%E$0)CCDW%?`#*qJGPu+Y>FehwNk`LPA z=A%AR%96ATvq!X=8Vi{R>ask6tm5Bu{0@M137Sqs!X6XWpe3p)Il+}D!PkwWAu%GjM=ssi z680Um-1^TUiPirE)RhpRoW`4jC+F-JCiS>-JnT5}yR7cz}D z)Ug`bm~Z%_UVa$rPxqVRZ%Y3au^MxOCu(91!s-jw`1>-&XdGm0z3vQjsaqN>Ki1;W zMcD5p@Y&T?NBZXeS1-b~e-$_LmKI}9OHW?oW0x$+&w)Qk1c4+hfv#xOc1{eLW)BTE z%9e$rns&u>n7j`DDCTx2Do_0o$*x(wFH6Fny9NvDao>eElTfEKTcIWC;)+2jZ7IL3 zFE99gu%+_-m0c+%qBdBKQj&S==eaS|!T-RngPs=8L056BGz-V@b16H*Ou93OIW3aQ z9#lY}KXrn9H3TOY^(@1173jJH078c@`WVAhYZ{&s#_NQ&!M$Isgs;bEd@}0sfcjGb zeyG0r`cmqq8QJJ0Vms%+xTbjaI$a6xDl#LfzBGXiUXGXNpq6{L!ZKHGl1rnox>Gmv zgxsU5=(aTFAe2Vf9R%O0t1+-_JIw$n#e|Go7I+Xu7t!8kgbyhzuQg7AUc;Cpq&~Wy z@Dn*&0b%tkwAzDlxEr&B&+9h$w~engi`ZF=H9#fBd7(&N_mXgk;2JNh>_$}_UJc{1 z(DT}h{5wZXU??l^xj+bQ9VB63Nt#O~>4{WSrIvEcO4z5z?O#a)V)&ytz$A$CRTZ1y zLK;v7c&1ws(#!FOmKp2w-pir1OJr1gAAI8{h2MC^$6q_Ft)3)hQB2whTE65pI~sxZ zxSxR&=BIiKf-6DcDL~+Vioi6w{}dz9Shn4^$2$Fqdj2P+V!BDh_g!>S!BX7g*kiNID4)`XwfaAc);6$vld*ejSvU#ePmcpG#9oLB+pDuZ0eZ9NqIO@ycvPjK)D>x}; zSe6|iJm#J=H+~$N1uZHJ5z4@1d!#Vxk3=>*bnkp9h)i_fLfWp*)2<$ERiD(8#a{+; ziKo4!)OkhGqj6LWF(c+;n78}9`5Qg7dy1*2u!F2c-t(ssk4RhM)}>)47Q)*|)xoH< zU2q~pGVD8MCF{@nzb6321o@95EY1`)1X>M25q0WKWkx5;%Q*yS=2*rb4~s;sezLfX z&%?BSCA`oD5CvP1$t(LH*=f~Mk!)s6V;TaoD#sqV0<_P$x5j=*YsmG+znxw!?Qyx% zXgY%ulzWm7&g2i;--+oLGOuh=r`}Z(#mBu9PTLxI@@(g$=&^dI+PnG7@d0 zqbg7@r)`8uvhI$1k8*I5tiA^H4-T?s$TWZtTmwd|izQcNU0Z9$=B|zZN#<%yI_ew+ zW?nMaY{;-AAsbH;8Mx-aM2JL>4H-{azxug)GG~((Kpw?!@67%$x$PEFrn7{-e4|>X zPoKPVO8kP+=Ufyfrv3!ihjT1$(Z z3r?hq3lt#1Inyn;9sCJ>)^fBuYU@JlgHodWvc!zMP)5=UYd{Ka=F67>q}!!)J;mVUv0(jqH= z{1HRp_IN{NxUC%XGLk+d8xLcs4$^nTdb@Wh^JS9JxeN?3k1lR8@!b2fHP!$r%6A%s z?}SdzB!-c~=751_nX$D`s|omO>bf+YM-aoqMo3}h30PA?zMYBNOb z;Fvif%W1Lg+c^6Vxk7;yliz|#Tr_~raa_oa4Q)!X-n2Lv1D=e=4X&La3Gg{0g2cb2 zc6`@WZz(G*c1kvWU%vY(!jeI#xaJnY?sD3CUW^;iCdqndNr{YoYiUk7GAGsK&gi(Z zGVHThtdop6+jb$$FrsxEO^83y8Pn02mF%ua+HXck`Dhy!68vXJTNcN#vjuZxFULKD zu3S86brr6UwpdY?6uQ1g?l&W{eUlOAcv_v9IgT>lHyh||K@RC~;?%)p;6EnZtN>ZG z4M5~`c6Yk!besnv<>@8kdqViS!c0ASLWNRgDGu%8sthNV4IBi#)NYs{#Hni+kg}*k`ZkN8S{{8 zA6Acyk{Vd=OC)>ZmX(W_3Z^=}2i6^vpz1CNcLWNd(t~X@u5SiZFqVd(0;o`{2#IDT zM+n|IKnx!xAqF|f-U%HuB3$$@jD+Cubd)&}E|wf&?hOSS?hD}x3Q#*8s4%P#Azn}v zJ6s^i;}CD3?q7m^5Nz>R-Cr#-k^^q*edx}X(yto7=OBw9JGu zL5Fi2f@H*#Ed&KSy>lr+s(-7wB|*xfk6GclTEQy0gF)J&bNcYyoxv~w@s+8~IsY3Y zBU$Pik0VnbuCcSPu|gxC%-S=|yG4@;`@Q$04loruGanX6p%s{AkVyJAf}S_jYSwWZ zVV}1F2hBBndx6p3O-%+1Q3Yfo;Ul|M47<0(g>h_FZ5zfZzJgq>Kv%Ln8J|n;-AOvc z(Vz9$26Jk2Wt;|-HiUAW2;B}h25tvQhXc!?E4E=e3MSzr1s$120}NV=YAKc?mfU+_ zD$x#ENzqaDuARD9B<*8FsQc!KeagtIdpae2E>-h9NSmX2SJ$jt?1LFx{@H zC)nL-Iuc!!kjx%p=UZ$;+LJQ>{8)$%MB&Kd6DorX>_84$)^uR?|GiSx1O^%VWZ^@M zW3uu=sI!cIRzheNx!o9lJA*vU^15F~Hep#sRp?GNr$Ho5Y1k2ltZK)Ft~itU+_ca! z#$nZ&YKnz%d^MT3&^qX)nt&tQR>J;IPnL#e^YeVr#1h%H-Pp2>Vyo)?lH#kX3Hd|L z>JB#M>Lk<4fYrJy6`{L|sYdlf(NZ&xTn+qX++x6Q`xS+F5$4uTSFHh$;~H_9;+66W z@m6(ePYpQj#^lIKGBx0aR|mO35pkVir~2A^FX!B>;P@;vrGe`XuS7 zp#py|Qzu!znyz2J%km6qeN-B)!aUJQn%{ct{ek0%zUkh37S*DEf40)HRw696t*sEC zFXp*cdk!xQxqA8^aqmjOkK$x+zrMoQ!VKx;p{A6>G^yC*<{{NjmdR$to($1m(!mj% z7l6NX?_qgS#II&$G`!>VIBjX-z{*Ihmf4?>J>bpC9JNCGjeF{64LK=Py*xpO;$q?+ zdHj-?__k0j&1Y0aGp}u+y^C@uU1!F?4C_9wXNJSkmE-084>3E?N7@l`lGaJ69nIX_ zUdpI+g4ANG7{;~Doza)UmeSOofpb0p{G$(0q=fA}I7faQ=!8`Yu6J%G#5a-o)*bGQ zrU~G04M*;k(*n~`n~U#ZJKBmjQj*u=*w;H_a8MGg8JBkF#e4`B{!zTbI-@KaJTfVVfu-{w%Y8$q8KcKmTe{9xfv*S6c zj%=zx-_4Kfj+^6oLgLjA+1m$*J`dR$agZ7E5ZfA$e!Y{hcShFpi(Zc2(%-BLx*|Wb zn>QDCxxTiW*L)e8Fi58?^*LUUe!^e<=h~E;KN)JW$Mnn!`UIZ`toaQJoFktG@RC>! zG*WRF5O2hUJQkdVl9P^2(3RRAqcCLT{u#I#E}EA1Fc$-<4&AT0i!TQy@sM1hw4D`* z8rujhYM+JMtsf&A6zRb(do_2&AB3hR6X?#!W9>nNz<_mgm@VCr43U}cpet{*Xqwo? ztdsmeF;EH$b;959C_>I&1|UZff7!kYMcwPyIH!b9p0ArfBZ$O!3r>W9l7b7BSS9}L z+394$z8M3~mu}uRc}2Q%TdJ99a|!S1Way^1AQDP@LaRZv1jty-El`ZcUPwq@<8}x> z6H3&HF11RB&^QxPdsu6-w@oD4k9+udK z%Z7SPcLUb^jzG0(6{9grEK)Vl;Iw=^mJ%WgUD#&p25hMrSB()tvIM7#{nopqaNee7 zYdv4ZM)*U-9#DOy!98znXvQ1SfsQ(+e>Fo7L$#+85*r$mtf!`{nf|yQ7^VO!FYOW% zJM4Jxy5Zp3^oS$_hV$qD(3=96qbyV5A)>wXQ=M~b^>5OO{F<5U5A=_*F&%?Sx&38i zLGQRS4kNcq<&Szo5S3T!sVL05n?}#q*-*Z11}5A~wnS7i0YF*y>Kr}r8JLp5$DLCY ziaf%18Gi}Ypnd70)PfAo1Ua+Qs z+NlWJGytd;v|hd~Q=9W+gP;n!k9@ZD5G&ZEY4&ffp@Tr-XBzL?ROu1E08~3{eC^PT znr{Y)6!aM$J1$hhZXNy)Qvy9WW7mH;O{R}u=GVkI^ne&+N+@c)hI-h2nH~I@fGj|R z8dOCg+L=>yfZtf@^%grn&b9!fRY70w8z7XLK*vNbvR#vMz|>tGUv<-%4+U=8KLd{y zXS`rEo#%MPgm9<{pE0#kIKOK5-XbU5hzX_Oj*}}+%9=tLdO&ifq@Q`v7d9~RfMiRN z&;rq&dVEJ?3LAF=3{kM$yP>==3vRHMTEHTS@3( zO+gm;HooVxJ$U|6X&mHfVS(fTO*v!Dck_d_fuQu=K-`3c>f-fLO{X=D0nj^bBc0Ta zh5qOT$`IC@zy+zen7~>e<8HoSIKF-wLtuLUiLL_(b*OOrxVZ4};5aXT$3sV3EN6B* zrnwtO?l1b8Su_b+-+cC5ck*%I$dAy)i4n)zgop~#8>3wYCC7ca6GrE%T@M$AJbUJX XIZnOP7>uly~NB3u3kt9fzY diff --git a/files/board/arpl/p3/addons/9p/denverton-4.4.180.tgz b/files/board/arpl/p3/addons/9p/denverton-4.4.180.tgz index a7f168c856ce3212d65d355c19698b0851c618f6..cb8ef7a433aabdceffb3dee0fedbbb7d61b5d029 100644 GIT binary patch delta 38223 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 F{15PxtULe! delta 38165 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 z%0D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 C8^E6c diff --git a/files/board/arpl/p3/addons/9p/v1000-4.4.180.tgz b/files/board/arpl/p3/addons/9p/v1000-4.4.180.tgz index 06a6566c4c7ab064736ee98f042136d195565fd6..a8a24f4b79e1304ddc6dcc7d0cf4f540cfa09a4d 100644 GIT binary patch delta 35307 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